Skip to content

Add Resync as the Third Entry Point - #651

Merged
ptr727 merged 9 commits into
developfrom
add-resync-entrypoint
Aug 10, 2026
Merged

Add Resync as the Third Entry Point#651
ptr727 merged 9 commits into
developfrom
add-resync-entrypoint

Conversation

@ptr727

Copy link
Copy Markdown
Owner

Merge after #650. Section 4 documents the hub-only: finding that PR lands. Merged first, this file describes a detector that does not exist yet.

Problem

"Sync this repository with the hub" had no procedure to resolve to. STANDUP.md takes a repository from nothing to operational, AUDIT.md measures one and deliberately changes nothing, so an already-stood-up repository that has fallen behind routed to the audit and got a findings list. A findings list states no order, and three things were undocumented rather than merely unwritten:

  1. The order. The rules govern every file judged against them, so a verbatim rule section lands before those files, the same closing-window shape as STANDUP.md section 1A. And a deletion lands before the re-vendors, or you refresh a file that is about to go.
  2. Deletion. The one remedy that removes content, so a wrong finding loses work instead of adding noise.
  3. What the measurement cannot see. A carried file at intent fidelity is presence-checked only, so a clean run does not mean a current file.

Change

RESYNC.md, hub-only like STANDUP.md for the same reason (a repository needing it cannot be relied on to hold a current copy), wired into every surface that already advertises the other two:

SurfaceWhat it gains
AGENTS.md "Fleet Bootstrap"The third route points here instead of at AUDIT.md
host-setup/agent-safety/claude-md-fleet.mdThe same routing, kept in sync deliberately
README.mdA Getting Started row, a doc bullet, a "Resync a repository" vocabulary entry, and the carry-the-rules paragraph
AUDIT.mdStates that it measures and does not sequence
GOVERNANCE.md "Repository Onboarding and Conformance"Names the third procedure
spec/section-model.mdLists it as hub machinery, not fleet law

The vocabulary entry is the point of the whole PR: per that section of the README, a request using one of those terms is "a complete instruction rather than a starting point for interpretation." Saying "resync with the hub" in a downstream repo now resolves to an ordered procedure.

Host verification joins a procedure for the first time

scripts/host_gate.py and spec/host-tools.json both existed and neitherSTANDUP.md nor AUDIT.md ever invoked them. STANDUP.md section 0 checks identity and signing only.

The documented invocation passes --repo, and that is not incidental:

python3 scripts/host_gate.py --repo <path-to-target-checkout>

A repository may declare a root host-tools.json layering over the hub's (tighten-only). The gate reads that file relative to --repo, which defaults to the working directory, so a bare run from a hub checkout layers the hub's own declaration and silently passes on the floors the target adds. Verified both ways: the bare run emits no layering note, and a target carrying no local file is silent by design, so a missing note is not evidence the flag was unnecessary. My first draft of that line said to run it bare, which would have shipped a command that skips what it claims to check.

Blast radius of the byte-locked edit

The AGENTS.md "Fleet Bootstrap" section is verbatim fleet-wide, so editing it makes downstream copies stale. Measured before writing it: two repositories carry the section (Blog, HomeAutomation-Config) and both are already on the re-vendor list, so this adds no repository to it. The other 18 do not carry it at all, which is a standup gap rather than drift.

claude-md-fleet.md is the source of the installed ~/.claude/CLAUDE.md fleet block, so each machine picks the new routing up when host-setup/agent-safety/install.py is next run. I have not run the installer, since the source is unmerged and installing from a branch would put unreleased content on the host.

Verification

Every command in the file was run as written, not transcribed: host_gate.py (passes, confirming the Python 3.13 floor), audit.py, fidelity_honesty.py --report, and configure.sh's signature checked against its own usage.

Gates: prose_lint.py --diff HEAD clean, repo_gate.py --check eol clean, markdownlint-cli2 0 issues over all 7 files, cspell 0 issues on RESYNC.md, CRLF confirmed byte-wise on every file (the new file was written LF and converted).

Deliberately not in this PR

Declaring host-tools.json in the spec/files.json baseline. That makes every repository owe a file it does not have, which is a fleet-wide new finding and a spec decision rather than a doc fix.

🤖 Generated with Claude Code

A request to sync a repository with the hub had no procedure to resolve to.
STANDUP.md takes a repository from nothing to operational and AUDIT.md measures
one, so a repository that is stood up already and has fallen behind routed to
the audit, which reports findings and deliberately states no order for applying
them. Three things were therefore undocumented rather than merely unwritten.
The order matters and was nowhere. The rules govern every file authored against
them, so a verbatim rule section lands before the files it judges, the same
closing-window shape as STANDUP.md section 1A. A deletion lands before the
re-vendors, since doing it after means refreshing a copy that is about to go.
Deletion had no entry in any procedure. It is the one remedy that removes
content, so acting on a wrong finding loses work rather than adding noise, and
the detector matches on path alone. RESYNC.md section 4 says only a retire
disposition authorizes it and an untriaged hit is read first, naming the two
path collisions the first fleet run produced.
What a resync cannot see is now stated rather than implied. A carried file at
intent fidelity is checked for presence alone, so a hub revision inside
CODESTYLE.md, WORKFLOW.md, .editorconfig, cspell.json or version.json raises no
finding anywhere, and a clean run does not mean a current file.
Host verification joins the procedure, which no procedure invoked before.
scripts/host_gate.py and spec/host-tools.json existed and neither STANDUP.md nor
AUDIT.md ran them. The documented invocation passes --repo, because the flag is
what makes the target's own floors count: a bare run layers the hub's own
declaration and prints the same healthy digest either way.
The byte-locked AGENTS.md Fleet Bootstrap section changes, so downstream copies
go stale. Two repositories carry it, Blog and HomeAutomation-Config, and both
are already on the re-vendor list, so the edit adds no repository to it.
host-setup/agent-safety/claude-md-fleet.md carries the same routing and changes
with it, which reaches each machine when the installer is next run.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
CopilotAI lite review requested due to automatic review settings August 10, 2026 16:21

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds RESYNC.md as the third hub entry point alongside STANDUP.md and AUDIT.md, documenting an ordered procedure for bringing already-stood-up repositories back into conformance and wiring that procedure into the hub's main routing surfaces.

Changes:

  • Add new hub-only RESYNC.md procedure covering routing, host verification, ordered remedies (including deletions), and blind spots.
  • Update entry-point routing references across AGENTS.md, README.md, AUDIT.md, and GOVERNANCE.md to point "already stood up and stale" cases at RESYNC.md.
  • Update supporting docs to classify the new procedure as hub machinery (not fleet law) and keep the host-installed fleet block in sync.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

Show a summary per file
FileDescription
spec/section-model.mdTreat RESYNC.md as hub-only machinery alongside other hub procedures.
RESYNC.mdNew ordered resync procedure: routing, host gate invocation, remedy sequencing, and audit blind spots.
README.mdAdd "Resync" to Getting Started and vocabulary, and link to RESYNC.md.
host-setup/agent-safety/claude-md-fleet.mdUpdate host-installed fleet routing to send "stale instruction set" to RESYNC.md.
GOVERNANCE.mdMention RESYNC.md as the procedure for resyncing already-stood-up repos.
AUDIT.mdClarify audit is measurement only and point sequencing to RESYNC.md; add reference link.
AGENTS.mdRoute "instruction set present" cases to RESYNC.md instead of audit-only.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment threadRESYNC.md Outdated
Comment threadRESYNC.md Outdated
Two review findings on RESYNC.md. The hub-checkout rule dropped the "that" the
canonical wording in AGENTS.md carries, leaving "in one another task is using".
And section 2 called the mechanized subset one command directly above a block
holding three, so name what each of the three does instead: the first measures,
the second renders that run, and the third is a different tool over the fleet.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
CopilotAI review requested due to automatic review settings August 10, 2026 16:25

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated no new comments.

CI's cspell step gates README.md and HISTORY.md, and the README gained
"resynced". The local check ran against RESYNC.md, which that step does not
read, so the one file under the gate was the one not checked.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
CopilotAI review requested due to automatic review settings August 10, 2026 16:30

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.

Suppressed comments (1)

RESYNC.md:35

  • python3 spec/audit.py --issue <Repo> still runs a live audit (audit_repo(...)) and is not just a different rendering of the previous run. The current wording implies it avoids re-measuring, which is inaccurate and could mislead readers about the cost/behavior of running both commands.
Run [`AUDIT.md`][audit] end to end. Three commands cover the mechanized part, and they are not interchangeable: the first produces the findings, the second renders that same run as a filable issue rather than measuring again, and the third refreshes the fleet-wide ledger, which is a different tool over a different question. The rest of that file is the half no tool evaluates.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.

The wording had --issue rendering the previous run "rather than measuring
again". It calls audit_repo itself, so it is a second live measurement and the
two can disagree if the repository moves between them. Say that, since the
inaccuracy understated both the cost and the freshness question.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
CopilotAI review requested due to automatic review settings August 10, 2026 16:47

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.

Suppressed comments (1)

RESYNC.md:39

  • In section 2's command block, the --issue invocation is documented as producing "the same findings". spec/audit.py --issue re-runs audit_repo(...) (it does not reuse the previous spec/audit.py <Repo> run), so the comment should reflect that it re-measures and that results can differ if the repo changes between runs.
python3 spec/audit.py <Repo> # the deterministic findings, read at the registry groundTruthBranch
python3 spec/audit.py --issue <Repo> # the same findings as a ready-to-file convergence issue
python3 spec/fidelity_honesty.py --report # regenerate reports/divergences.md before using it as a work list

ptr727and others added 2 commits August 10, 2026 09:59
The prose in section 2 was fixed and the inline comment on the command itself
still read "the same findings", which is the same false claim one line lower.
Swept the term tree-wide rather than the instance: no other file claims the
renderer reuses a previous run.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
CopilotAI review requested due to automatic review settings August 10, 2026 16:59

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.

Suppressed comments (1)

RESYNC.md:30

  • The --repo explanation implies that running scripts/host_gate.py with/without --repo produces “the same healthy digest either way”, but scripts/host_gate.py changes both the declared-tool count and emits a note: when it successfully layers a repo’s host-tools.json (and those differences are exactly how you can tell the target’s floors were applied). Reword to avoid claiming the output is identical and instead state that omitting --repo skips reading the target’s host-tools.json entirely.
**Pass `--repo`, because the flag is what makes the target's own floors count.** A repository may declare a root `host-tools.json` layering over the hub's, tighten-only, per [`scripts/README.md`][scripts], and the gate reads that file relative to `--repo`, which defaults to the working directory. So a bare run from a hub checkout layers the hub's own declaration, silently passes on the floors the target adds, and prints the same healthy digest either way. A target carrying no local file is the common case and is silent by design, so the absence of a layering note is not evidence the flag was unnecessary.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.

The paragraph claimed a bare run prints the same healthy digest either way. It
does not: a successful layering changes the declared-tool count and emits a note,
and those differences are how a reader can tell the target's floors were applied
at all.
The accurate statement is also the one that matters. Omitting --repo does not read
the target's declaration, so every floor that repository adds goes unapplied, and
the run reports nothing about the omission because it cannot know a target was
intended. A healthy digest from a bare run is a statement about the fleet floors
alone.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
CopilotAI review requested due to automatic review settings August 10, 2026 17:26
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Addressed the suppressed finding on head in 12664a5. It was a real overclaim.

A successful layering does change the output: the declared-tool count moves and a note: line appears, and those differences are exactly how a reader can tell the target's floors were applied. My sentence was only ever true for a target carrying no local file, and #652 makes host-tools.json a carried baseline file, so from that point every conformant repo has one to layer and the claim would have been false in the ordinary case rather than the rare one.

Reworded to state what is skipped rather than what looks identical:

So a bare run from a hub checkout reads the hub's declaration and does not read the target's at all, which means every floor that repository adds goes unapplied. The run reports nothing about the omission either, since it has no way to know a target was intended, so a healthy digest from a bare run is a statement about the fleet floors alone.

The same wording appeared in AUDIT.md and STANDUP.md on #652 and is corrected there in the same pass, since this was one claim in three places rather than one line. STANDUP.md needed more than a reword: its host-gate step runs before the git init in section 0B, so there is no target checkout to point --repo at, and that step now runs bare deliberately and says why, with a second run after section 2 once the file exists.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.

Suppressed comments (2)

RESYNC.md:39

  • Spelling: prefer "fileable" over "filable" in this inline comment for consistency/readability.
python3 spec/audit.py --issue <Repo> # audits again and renders that run as a filable issue, so it can differ from the line above

RESYNC.md:35

  • Spelling: "filable" is uncommon in US English and may read like a typo; "fileable" is the standard form for an issue that can be filed.

This issue also appears on line 39 of the same file.

Run [`AUDIT.md`][audit] end to end. Three commands cover the mechanized part, and they are not interchangeable. The first reports the findings. The second **runs its own audit** and renders those findings as a filable issue, so it is a second measurement rather than a view over the first, and the two can disagree if the repository moves between them. The third is a different tool answering a fleet-wide question. The rest of that file is the half no tool evaluates.

Both "filable" and "fileable" are defensible, neither is settled US usage, and
the file's own gates cannot arbitrate: cspell reads README and HISTORY only, so
this file is outside it, and the prose spelling rule covers British against US
pairs rather than a coinage. An issue ready to file needs no adjective at all.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
CopilotAI review requested due to automatic review settings August 10, 2026 17:45
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Spelling finding answered in 31cc663, by removing the word rather than choosing between the two spellings.

Both filable and fileable are defensible and neither is settled US usage, so picking one would have been my preference standing in for a rule. The file's own gates cannot arbitrate either: cspell reads README.md and HISTORY.md only, so RESYNC.md is outside its scope, and prose_lint.py's spelling rule covers British-against-US pairs rather than a coinage. An issue ready to file needs no adjective, so both instances now read that way and there is nothing left to disagree about.

Both lines were changed together, since the finding named line 39 and noted it also appears on line 35.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.

Suppressed comments (1)

RESYNC.md:38

  • In the audit command list, the comment says spec/audit.py <Repo> reads from the registry groundTruthBranch. However, AUDIT.md section 1 states ground truth is main and that a registry groundTruthBranch of develop contradicts the procedure. To avoid mixed guidance, clarify that groundTruthBranch is expected to be main (and that --branch is the supported override when you intentionally want to audit in-flight work).
python3 spec/audit.py <Repo> # the deterministic findings, read at the registry groundTruthBranch

The command comment cited the registry groundTruthBranch as though the value were
open, where AUDIT.md section 1 says main is ground truth for both workflow models
and a field naming develop contradicts the procedure rather than configuring it.
Read together the two files gave mixed guidance. The line now says main, and the
paragraph beside it states that the field is not a choice a resync makes. Measured
rather than asserted: 18 cataloged repositories declare main and the other 4 omit
the field and take it as the default, so none names anything else.
--branch was missing from this file entirely, and a resync is where it earns its
place. Convergence lands on a feature branch and reaches main only after the
maintainer merges, so auditing ground truth mid-resync measures the state being
replaced rather than the work replacing it.
The invocation is verified as written rather than transcribed from the help text,
including the claim about its stamp: the run prints "branch override develop"
beside the hub sha and reads the repository at develop.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
CopilotAI review requested due to automatic review settings August 10, 2026 17:51
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Addressed in 287ffec, and it was two problems rather than one.

The mixed guidance was real. My comment cited the registry groundTruthBranch as though the value were open, where AUDIT.md section 1 says main is ground truth for both workflow models and that a field naming developcontradicts the procedure rather than configuring it. Read together, the two files disagreed about whether that field is a knob.

Measured before rewording rather than asserting it: 18 cataloged repositories declare main and the other 4 omit the field and take it as the default, so none names anything else. The line now reads main, and the paragraph beside it states that the field is not a choice a resync makes.

The --branch half was a genuine gap, not just a clarification. This file did not mention it at all, and a resync is exactly where it earns its place: convergence lands on a feature branch and reaches main only after the maintainer merges, so auditing ground truth mid-resync measures the state you are part-way through replacing rather than the work replacing it. It is now a fourth line in the block with that rationale.

Verified as written rather than transcribed from the help text, including the claim about the stamp:

audit run 2026-08-10T17:50:14Z | hub 31cc663 | branch override develop
== Blog (hugo, source-only; release) @ develop@53df4a9 ==

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.

@ptr727
ptr727 merged commit 68aef25 into developAug 10, 2026
7 checks passed
@ptr727
ptr727 deleted the add-resync-entrypoint branch August 10, 2026 18:05
ptr727 added a commit that referenced this pull request Aug 10, 2026
Your call, per the decision to accept the fleet-wide finding. Floor set
to **1.7** per your follow-up.
## The jq gap
`jq` is used by the ruleset normalizer in `repo-config/configure.sh`,
the ruleset diff in `AUDIT.md` section 6, and payload regeneration in
`docs/repo-config-carry.md`. It was declared in **neither** the contract
table nor `spec/host-tools.json`. A host without it cannot apply, check,
or audit a repo's branch configuration, and nothing said so.
## The floor is 1.7, and it is a target
I did not pick a number and justify it after. Measuring first said **no
floor was warranted at all**: nothing in the tree uses a post-1.5 jq
feature (checked `walk`, `@base64d`, `--args`, `$__loc__`, `pick`,
`toarray`, `abs`, `getpath`, `ltrimstr`, `splits`, `limit`, `$ENV` — the
only hits were shell variables and Actions expressions, not jq filters).
So the floor is a **target**, the same kind as `python3`, and the entry
says so rather than implying a defect nobody found.
1.7 is anchored to what the platform provides: **current Debian stable
packages 1.7.1**, so a distribution install satisfies the floor and no
host needs a manual build to meet it, while an older release sits below
and is the case the floor exists for. That anchor is what makes it
actionable. Two rejected alternatives, for the record:
- **1.8** (the newest, installed here) would fail a current apt host
that runs every documented filter correctly. A floor set to whatever
happens to be installed is a host failure nobody can act on, which is
the hazard this file's own note names.
- **1.6** would encode the `walk/1` boundary, which is a fact about the
filters rather than something a host operator can act on.
Facts kept in the entry because a reader needs them: on jq 1.5 `walk/1`
does not degrade, it **fails to compile**, so a diff built on it reports
drift on every ruleset it never compared. And the claim that
`keys_unsorted` also needs 1.6 stays **disproved** per the
`.github/copilot-instructions.md` record, measured on
`jq-1.5-1-a5b5cbe`.
## Consequences swept, not left
The floor now sits **above** 1.6, so `walk/1` is available — which made
false the comments in `AUDIT.md` and `repo-config/configure.sh` that
justified hand-defining a recursion by walk's absence. Both now give the
reason that survives: the recursion costs nothing and compiles below the
floor as well. This is the same class of defect as #649 (a rule changed,
its prose left asserting the old one), so it was swept by term rather
than by instance.
## host-tools.json becomes a carried file
A repo now states the tools its **own** procedures need beyond the fleet
declaration, so the tighten-only layering lives somewhere a reader finds
rather than has to know to look for. A repo with nothing to add carries
the stub with an empty `tools` list — the footing `OPERATIONS.md`
already set — and this repo's new root file is that worked example, with
a `note` distinguishing it from `spec/host-tools.json`.
**Measured before landing: none of the 22 cataloged repos carries one**,
so this adds exactly one `LETTER` per repo. This PR satisfies the hub's
own.
## The gate joins the procedures it was written for
`scripts/host_gate.py` existed and **no procedure ran it**. `STANDUP.md`
section 0 and `AUDIT.md` now do, alongside `RESYNC.md` in #651. Each
passes `--repo`, because the gate reads the target's declaration
relative to that flag and a bare run layers the hub's instead while
printing the same healthy digest either way.
## Verification
`scripts/test_host_gate.py` **failed first**, which is the tests
working: `test_the_declared_floors_are_the_ones_with_a_stated_reason`
asserts the floor set exactly, so a new floor cannot land unnoticed. I
updated it and generalized
`test_a_target_floor_says_so_rather_than_implying_a_defect` from the
single `python3` entry to the **set** of target floors, so a third one
added without the two-kinds wording fails rather than reading as
measured.
The boundary is checked through the gate's own `compare`/`parse_version`
rather than a reimplementation of them:
```
jq 1.5 -> FAILS jq 1.7 -> meets
jq 1.6 -> FAILS jq 1.7.1 -> meets
jq 1.6.1 -> FAILS jq 1.8.2 -> meets
```
- 552 script tests OK, `--selftest` PASS, `validate.py` OK
- `host_gate.py`: 7 tools, `jq 1.8.2 meets the 1.7 floor`, and it reads
the hub's own stub (`host-tools.json layered 0 local entry(s)`)
- `prose_lint`, `repo_gate --check eol`, `markdownlint-cli2`, `cspell`
on the gated files: all clean
- **`editorconfig-checker` caught a real defect every other gate
passed**: a `sed -i` I used wrote one bare LF into `AUDIT.md`. Fixed and
re-verified byte-wise; the diff stayed at 9 lines rather than a
whole-file rewrite.
## One bookkeeping item left for you
The `keys_unsorted` entry in `.github/copilot-instructions.md` carries
**Delete when** - "nothing this check runs on carries a jq older than
1.6", and an enforced 1.7 floor arguably satisfies that. I left it in
place rather than deleting it unilaterally, because it exists to answer
a repeat reviewer finding and its measured proof is cited from the new
`jq` entry. Your call whether it retires.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
ptr727 added a commit that referenced this pull request Aug 10, 2026
## Problem
#650 introduced the `hub-only:` finding, whose remedy removes a file
rather than updating one. #651 and #652 stated that remedy in `AUDIT.md`
section 10 and `RESYNC.md` section 4 as: delete the copy, reach the
hub's, and *"where a carried doc named the local path, point it at the
hub's."*
That covers one of three shapes and assumes a hub equivalent exists. The
two it missed are the ones that cost something.
**A runnable command citing the deleted path.** This is the expensive
shape, because a documented command *fails* where a dead link merely
disappoints. Measured rather than argued:
```
NxWitness repo-config/README.md
13: - [`configure.sh`](./configure.sh) - idempotent `gh api` script with two modes:
14: - `./repo-config/configure.sh check` - validate only, no writes...
17: - `./repo-config/configure.sh apply` - create-or-update the rulesets...
61: REPO=ptr727/NxWitness ./repo-config/configure.sh apply
62: REPO=ptr727/NxWitness ./repo-config/configure.sh check
```
Retiring that one file makes **five lines of a carried document wrong,
two of them commands a reader would run**. `configure.sh` is carried by
**15 repositories**, so this is queued work rather than a hypothetical.
**A mention with no hub equivalent.** It is removed rather than
re-pointed, and removing a reference-style link removes its definition
with it, per `GOVERNANCE.md` "Documentation Style Conventions", *because
an orphaned definition fails the no-unused-defs rule.* So the old remedy
could leave a **gate failure** behind while reading as complete.
## Provenance
Raised by the **ESPHome-Config agent** over peer messaging, from a case
of its own: deleting a nested `easystart/AGENTS.md` at Pieter's
instruction, it found three inbound references across two files, one of
them a reference definition that would have been left orphaned. It put
the scope question to Pieter rather than deciding it, and that is what
surfaced the generalization.
I measured the fleet-wide shape rather than adopting the specific case:
checked five repositories' `repo-config/README.md` for links (not merely
mentions) to `configure.sh`, which is how the NxWitness figures above
were obtained. Four mention it without linking; one links it and
documents four invocations.
## Change
Both statements of the remedy now name the sweep as part of the
deletion, with the three shapes and their different fixes. `RESYNC.md`
additionally carries the measured evidence, since it is the procedure an
agent follows step by step.
## Verification
`prose_lint --diff HEAD`, `repo_gate --check eol`, `markdownlint-cli2`
on both files, `editorconfig-checker`: all clean. Both files gained a
`governance-documentation-style` reference definition, and both
reference blocks re-verified as sorted by reference name.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
ptr727 added a commit that referenced this pull request Aug 10, 2026
Promotion of six squashes. **Merge with a merge commit, never a squash,
and never with `--delete-branch`** — this PR's head *is* `develop`.
| PR | What it fixed |
|---|---|
| [#649](#649) |
`AUDIT.md` section 6's ruleset diff projected `bypass_actors`, which no
payload declares, so jq exited 5 and **every ruleset on every repo
reported DRIFT**. Two further surfaces carried the same dead policy. |
| [#650](#650) | The
deletion detector: hub git-tracked paths minus the `spec/files.json`
baseline, so a retired file is derived rather than remembered. Corrected
`configure.sh` from 6 carriers to **15**. |
| [#651](#651) |
`RESYNC.md`, the third entry point, routed from the byte-locked
`AGENTS.md` "Fleet Bootstrap". |
| [#652](#652) | A `jq`
1.7 target floor, `host-tools.json` as a carried baseline file, and
`scripts/host_gate.py` wired into all three procedures for the first
time. |
| [#653](#653) | Two
`spec/` enumerations that went stale when the host contract landed
there. |
| [#654](#654) | The
inbound-reference sweep counts as part of a deletion, including the
runnable-command and orphaned-definition shapes. |
## Why this promotion matters more than most
Downstream repos read hub `main` as ground truth. While `main` sits at
[`0a86bca`](0a86bca):
- Every repo that runs the `AUDIT.md` section 6 snippet gets **false
ruleset drift on both branches**. The ESPHome-Config agent reproduced
this live and is holding its own fix stashed rather than diverging from
the hub.
- A repo resyncing now re-vendors to `main`'s revision and then again
after promotion. Verified against Blog, whose carried `AGENTS.md` "Fleet
Bootstrap" differs from both refs, so it is two re-vendors instead of
one.
- `RESYNC.md` does not exist on `main`, so a downstream agent asking
"how do I sync" still routes to `AUDIT.md`, which measures and
deliberately states no order.
## Fleet cost this carries, measured and accepted
`host-tools.json` becomes a carried baseline file, so it is one `LETTER`
on **22 of 22** cataloged repos, the hub included. That was measured
before landing and accepted by the maintainer. `RESYNC.md` section 0 was
amended so a letter wave of this shape reads as a file to carry inside a
resync rather than as evidence a repo was never stood up.
## Verification on the merged head
`spec/validate.py` OK, `spec/audit.py --selftest` PASS, 557 script tests
OK, `scripts/host_gate.py` clean over 7 declared tools, `repo_gate.py
--check eol` clean, `editorconfig-checker` clean, working tree clean.
Post-merge fleet audit: 22 repos, **zero errors**.
Two hub-side artifacts clear on this merge, both promotion-pending
rather than defects: the hub's own `AGENTS.md` "Fleet Bootstrap" reads
as stale against its `develop` canonical, and the hub reports its own
`host-tools.json` absent because the file exists on `develop` only.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@ptr727