Conversation
The backlog described the VPS as untouched and the deploy as proven on local mirrors alone, which stopped being true once the pipeline deployed staging end to end. The remaining work is narrower than the old list implied, and the part that matters is unproven rather than undone: a pipeline deploy that fails part way has never been shown to leave the site serving. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Bumps the actions-deps group with 1 update: [DavidAnson/markdownlint-cli2-action](https://github.com/davidanson/markdownlint-cli2-action). Updates `DavidAnson/markdownlint-cli2-action` from 24.1.0 to 24.2.0 - [Release notes](https://github.com/davidanson/markdownlint-cli2-action/releases) - [Commits](DavidAnson/markdownlint-cli2-action@6bf21b0...21c1be1) --- updated-dependencies: - dependency-name: DavidAnson/markdownlint-cli2-action dependency-version: 24.2.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions-deps ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…#30) * Declare the generator pin once and record what the theme is a copy of Three conformance gaps against the fleet hugo type (ptr727/ProjectTemplate#560), plus two smaller items found alongside them. Closes#28. Closes#29. The Hugo version and checksum were declared in both validate-task.yml and deploy-site-task.yml, each with an instruction to update both and nothing enforcing it. A one-sided bump was silent and produced the failure the pin exists to prevent: validation building the site with one generator while the deploy shipped a tree built by another, each verifying its own checksum against its own version and both passing. No Dependabot ecosystem tracks Hugo, so there was no bot to catch the skew either. Both installs now call a composite action that owns the pin, so the two cannot diverge, and it asserts the extended build from the binary rather than inferring it from the file name. The vendored theme recorded no upstream ref, so nothing could be diffed, updated, or audited against it. themes/README.md now records the commit, recovered by matching all 125 tracked blobs against upstream history rather than guessed: 154d006e0182dfc7da38008323976b02e6bfab4a, describing as v8.0-138-g154d006. Every file matches it exactly except two, both additions in extension points the theme documents for the purpose, and both are listed with the note that Hugo would resolve them from the project root instead, which would make the next update a clean directory replace. The record sits outside PaperMod/ so replacing that directory does not take it with it. That exposed a scoping bug: the markdown glob excluded all of themes/, so a file we author about a vendored tree would not have been linted. It now excludes themes/*/** instead, reaching inside a theme rather than over the directory that holds them. Also: assert-ref and assert-environment ran without a permissions block, so two jobs that only echo and case-match inherited the repository default, and both are now permissions: {}. And deploy-site-task.yml exposed no outputs, so no caller could record what shipped; it now returns release-id and site-url, and the live check already proves that id is the one answering, which makes it the value a rollback names. Verified: actionlint clean, markdownlint 0 issues across 16 files with the provenance file now in scope and the vendored tree still out, editorconfig-checker clean on everything tracked, and the site builds under --panicOnWarning. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Hardcode the Hugo pin so a caller cannot override it Copilot's point, and it is right: exposing version and sha256 as inputs with defaults left the divergence this action exists to remove, one level up. Two callers could pass different values and reintroduce the silent skew, and the only thing preventing it was that neither caller passes the arguments today. That is correctness by convention, which is what the original two-file pin also was. The pin is now hardcoded in the action, so callers cannot override it and every caller moves together or none does. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Gate production on the full ref, and pin the transport's SSH options Two review findings from the hub's copy of this pipeline (ptr727/ProjectTemplate#560), both of which apply here identically. The production gate compared github.ref_name against "main". Tags and branches are separate namespaces that share a short name, so a tag named main would satisfy that comparison while pointing at an arbitrary commit, bypassing the one gate protecting production. It now compares github.ref against refs/heads/main, which is unambiguous. The rsync transport left host key checking and the known-hosts location to the runner's OpenSSH defaults. StrictHostKeyChecking defaults to ask, which a non-interactive runner resolves ambiguously, and the known-hosts path was the default rather than the file the deploy key step writes. Both are now pinned, along with BatchMode=yes so a credential problem fails the step instead of hanging the job to its timeout. The option string is declared once at workflow level, so the upload and the pointer flip cannot drift apart, which is the same single-declaration reasoning as the generator pin. Verified: actionlint clean at exit 0. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Re-vendors repo-config/configure.sh to the hub canonical, the jq 1.5 portability fix this repo reported as ProjectTemplate#549, and mirrors the README intro into HISTORY.md. Both were findings of a hub audit run, and the branch reports none after them. Replaces the self-audit with a 2026-08-05 run. It adds a hand evaluation of the nine hugo checks the hub authored from this repo's deploy shape, since nothing mechanizes them, and records the one that does not pass: the retention count at the VPS destination is undeclared, because the count recorded beside the ownership line describes the local mirrors. TODO.md drops the spec debt owed to the hub, now authored there, and points the two follow-on items at ProjectTemplate#563.
#35) * Record the host channel, its retention, and what the ref gate holds up The two sides of the deploy are maintained separately and exchange rounds through two files on the VPS. The mechanics lived only in those files and in session directories, so nothing outside the conversation described how the channel works or what protects it. Record the paths, the transfer commands, the four rules, and the ownership convention that is the only thing keeping either side from overwriting the other's file. Name the host's prune unit rather than its count. A second daily retention runs on the same host and keeps a different number, so "ten, daily" identifies neither once it is read on its own. State what a single deploy key confined to the parent of both roots costs. The environments hold separate credentials and that separation stops at the runner, so the workflow's ref gate is what decides which tree a run writes into. It reads like housekeeping and is the boundary the credentials do not draw. Record that a rebuild regenerates the host keys. The transport pins them and fails closed, so a rebuilt host blocks the deploy and the rollback together until the pinned value is replaced on both environments. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Split a semicolon into two sentences in the channel section * Anchor the comms ignore so it cannot swallow a content directory --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Promotes develop to main, carrying forward previously-reviewed operational documentation and CI/CD workflow improvements for this Hugo-based blog repository (no new feature work introduced in this PR beyond the branch convergence).
Changes:
- Updates CI/deploy workflows to single-source the Hugo pin via a composite action and to harden deploy SSH transport options (strict host key checking, explicit known_hosts file, batch mode).
- Refreshes operational and governance-adjacent documentation (retention ownership, agent comms channel rules, updated audit report, and current repo state in TODO/HISTORY).
- Improves ruleset comparison portability by replacing jq
walk/1usage with an inlined recursive equivalent for jq 1.5 compatibility.
Reviewed changes
Copilot reviewed 10 out of 11 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| TODO.md | Updates current repo state, next steps, and hub-conformance notes post-staging deploy and re-audit. |
| themes/README.md | Records vendored theme provenance (upstream commit) and documents local theme edits. |
| reports/Blog/audit.md | Replaces the prior audit run with an updated run including hub comparisons and current deploy status. |
| repo-config/configure.sh | Makes jq normalization portable by defining a walk-like function for jq 1.5 while comparing parameterized rules. |
| OPERATIONS.md | Expands retention semantics (local vs VPS), documents the cross-agent comms channel, and clarifies deploy controls. |
| HISTORY.md | Adds the live blog link and associated reference. |
| .gitignore | Ignores /comms/ working copies for the VPS communication channel. |
| .github/workflows/validate-task.yml | Switches Hugo installation to the composite action and updates markdownlint action pin + globs. |
| .github/workflows/deploy-site.yml | Tightens production ref gating to compare against the full ref and reduces token permissions. |
| .github/workflows/deploy-site-task.yml | Adds reusable-workflow outputs and pins SSH transport options used by rsync/ssh during deploy. |
| .github/actions/install-hugo/action.yml | Introduces composite action to install the pinned Hugo extended build with checksum verification. |
Uh oh!
There was an error while loading. Please reload this page.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Promotes
developtomain. Five commits, no new work.What this carries
939071d(#35)9eee617(#34)hugochecks49dfbbc(#30)8314fa6(#31)e78c795(#26)What the promotion resolves that a feature branch cannot
validate-task.ymldiverges between the branches, and nothing merging intodevelopcan close it because both sides of the divergence are what the two branches hold. The promotion is the mechanism, which is why it is recorded here rather than filed as drift.What this does not close
#33 stays open, deliberately. Its first three checks passed against the real VPS on 2026-08-05 and the evidence is on the issue: staging deployed end to end through the pinned transport, the stored
DEPLOY_SSH_KNOWN_HOSTSverified against the live host key on both environments,BatchMode=yesproven not to fight therrsync -woforced command, and the production ref gate confirmed to refuse a dispatch from a non-default branch. The host side answered the rest: one key installed and neither per-environment key present, the runner reaching sshd directly, and an auth log matching both connections.Its fourth item is a production deploy, and production has never been deployed. That is a cutover decision rather than a transport test, so the issue stays open rather than being closed on three quarters of its own plan.
Verification
prose_lint.py(--diff origin/develop) all clean on the head of each contributing branch.🤖 Generated with Claude Code