Skip to content

backlog: file #1024 -- the writer-side glob that manufactured the wiring its reader validated against - #201

Merged
wshallwshall merged 1 commit into
mainfrom
claude/ledger-file-1024
Aug 5, 2026
Merged

backlog: file #1024 -- the writer-side glob that manufactured the wiring its reader validated against#201
wshallwshall merged 1 commit into
mainfrom
claude/ledger-file-1024

Conversation

@wshallwshall

Copy link
Copy Markdown
Collaborator

Files the writer half of the defect #199 fixed the reader half of. Handed over by the gate-parity session; every claim re-verified against the box and the code at a26db133 before filing.

The fact the whole finding rests on

~/.claude-account-2.lock is a directory (drwxr-xr-x, created 2026-07-29 13:32), not a file.

That is load-bearing: install-gate.ps1:91 filters with -Directory -Filter ".claude-account-*", so a file would have been excluded and there would be no finding at all. It is a directory, the unanchored filter matches it, and its settings.json carries worktree_gate.ps1 wiring that nothing else writes.

Why it is not a duplicate of the reader fix

The Python reader used the same unanchored glob, so it validated wiring against a file its own subject had manufactured. The two agreed not because the wiring was correct but because both globs were wrong identically — a validator satisfied by construction, ADR 0158's exact class.

#199 anchored the reader (\A\.claude-account-\d+\Z) and deliberately left the writer. So the circular evidence is broken — the reader no longer confirms the installer's own output — while the installer keeps re-creating the discrepancy the reader now correctly rejects.

⛔ The fix must anchor the writer, not widen the reader. Widening the reader restores the circularity.

Scoring

Value 4 — developer tooling, no product surface, no deployment effect, and extra wiring in a stale directory is fail-safe rather than fail-open. The real cost was the circular evidence, already broken by #199.

Difficulty 3, not lower — a session must not execute this installer to verify a change, because it writes user-scope wiring into every Claude config dir on the box. Verification is by inspection plus a test exercising the discovery predicate directly. The session that fixed the reader stated it could not verify a writer change for exactly that reason, which is why this half was handed over rather than attempted.

Recorded as explicitly NOT this item

~/.claude-account-4 is a live launcher with no settings.json at all, so no PreToolUse wiring and no gate — confirmed independently here (.claude-account-1/2/3 and .claude-account-2.lock all carry one; -4 does not). That is an owner decision about whether every launcher profile should be wired, not a glob defect, and the scanning tests report it rather than asserting it.

Ledger verification

  • census re-derived from the final table, never delta-adjusted: 106 open, 106 rows, ranks 1-106 contiguous, no duplicates
  • bijection empty both directions
  • all four census lines sum to 106
  • backlog_status_check.py: OK, 300 items across both files (106 + 194), each declaring exactly one status
  • the frozen 2026-07-10 snapshot below the live table asserted byte-identical

…ing its reader validated against

Handed over by the gate-parity session while it anchored the reader in PR #199.
Every claim re-verified against the box and the code at a26db13 before filing,
including the one the whole finding rests on.

THE FACT IT RESTS ON: ~/.claude-account-2.lock is a DIRECTORY (drwxr-xr-x,
created 2026-07-29 13:32), not a file. That matters because
install-gate.ps1:91 filters with `-Directory -Filter ".claude-account-*"`, so a
file would have been excluded and there would be no finding. It is a directory,
the unanchored filter matches it, and its settings.json carries worktree_gate.ps1
wiring that nothing else writes.

WHY IT IS NOT A DUPLICATE OF THE READER FIX. The Python reader used the SAME
unanchored glob, so it validated wiring against a file its own subject had
manufactured. The two agreed not because the wiring was right but because both
globs were wrong identically -- a validator satisfied by construction, ADR 0158's
class. #199 anchored the reader and deliberately left the writer, so the circular
evidence is broken while the discrepancy is still re-created on every run.

Value 4: developer tooling, no product surface, and extra wiring in a stale
directory is fail-SAFE rather than fail-open. The cost was the circular evidence,
already broken. Difficulty 3 rather than lower because a session must NOT execute
this installer to verify a change -- it writes user-scope wiring into every Claude
config dir on the box -- so verification is by inspection plus a test exercising
the predicate. The session that fixed the reader said it could not verify a
writer change for that reason, which is why this half was handed over.

The body also records, as explicitly NOT this item, that ~/.claude-account-4 is a
live launcher with no settings.json at all and therefore no gate -- confirmed
independently here. That is an owner decision about whether every profile should
be wired, and the scanning tests report it rather than asserting it.

Census re-derived FROM the final table: 106 open, 106 rows, ranks 1-106
contiguous, bijection empty both directions, all four lines summing to 106, 300
items across both files each declaring exactly one status. The frozen 2026-07-10
snapshot is asserted byte-identical.
@wshallwshall
wshallwshall enabled auto-merge (squash) August 5, 2026 04:53
@wshallwshall
wshallwshall merged commit 94b4716 into main Aug 5, 2026
31 checks passed
@wshallwshall
wshallwshall deleted the claude/ledger-file-1024 branch August 5, 2026 04:54
wshallwshall added a commit that referenced this pull request Aug 5, 2026
…floor that had 23 items of slack (#202)

TEN doc-drift modules exist to police documents and every one is reachable ONLY
through pytest, which is gated on `code == 'true'`. So on a docs-only PR -- the
exact shape they exist to check -- none of them runs. That is the same defect the
"Backlog status invariant" step above was added to fix, at ten times the surface,
and this change extends that step's own argument rather than inventing a design:
"gating it would skip it on exactly the pull requests it exists to police".

NOT HYPOTHETICAL. On 2026-08-04 four docs-only PRs merged (#197, #198, #200,
#201) and the doc guards ran on none of them. Two carried citation errors found
only by reading: an ADR named ONE inbound citation of docs/releases/ where there
are 23, and a docs/SECURITY.md route-table row asserted a refusal DELETE /me/mfa
does not make. Neither of those two would have been caught by these particular
modules -- but they are the evidence that docs-only PRs land unchecked against
the guards built to check them.

NO NEW REQUIRED CONTEXT, and that is deliberate. The steps ride the existing
required `test (ubuntu-latest, py3.14)` job, which already RUNS on every PR --
only its steps are gated. So this needs no branch-protection change and no owner
action, unlike a new job. .github/required-contexts.txt is explicit that it is
"not the enforcement -- the server is", and adding a required context is
all-or-nothing against a 422.

`[dev]` rather than a bare `pip install pytest`, and this one would have bitten:
pyproject sets asyncio_mode = "auto" (needs pytest-asyncio) and addopts
"--timeout=60 --timeout-method=thread" (needs pytest-timeout), so a bare pytest
ERRORS on an unknown option before collecting anything -- a step that could never
pass, reding every docs-only PR. Still far lighter than the gated install, which
adds console + fhir + dicom + x12 + xml that no doc scan touches.

THE FLOOR HAD 23 ITEMS OF SLACK. `--min-items 277` against a corpus that has
reached 300, in a guard whose entire purpose is to notice the corpus shrinking.
Raised to 300 in BOTH places -- and the second place is the finding: the floor
also lives as `_MIN_TOTAL_ITEMS` in tests/test_backlog_status_check.py and
NOTHING compares them, so the lower copy silently becomes the only floor that
binds. That is BACKLOG #1018's duplicated-constant shape. Both sites now name the
other; it is not mechanised here because a test parsing workflow YAML to compare
an integer is a new coupling, and the honest fix belongs with #1018's helper.

89 of the 241 tests SKIP and that is structural, recorded in the step: they
assert against docs/security/THREAT-MODEL.md, which is vault-only and absent
here. ADR 0156 records the class and ASVS 15.1.3 is open on it. The step prints
the module list BEFORE running and uses -rs so no skip reads as a pass.

⚠️ THIS PR CANNOT EXERCISE ITS OWN NEW STEPS. It changes ci.yml and a test, so
`code == 'true'` here and the new steps skip. Evidence is a local run of the
exact command (152 passed, 89 skipped, 5.12s) plus confirming [dev] supplies both
plugins, that "Set up Python" is ungated, and that constraints.lock is tracked.
The first docs-only PR is the real test, and it fails CLOSED -- a broken step reds
that PR rather than passing silently.

Verified: 57 workflow-structure tests pass (incl. test_workflow_shell_syntax and
test_ci_venv_pinning), 27 backlog/lint-scope tests pass, ruff check and format
clean, and the YAML parses with both floors reading 300.
Sign up for free to 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.

1 participant