Skip to content

chore(console): reconcile the June work that now has docs - #71

Merged
ProtocolWarden merged 1 commit into
mainfrom
claude/reconcile-june-2026-08-03
Aug 3, 2026
Merged

chore(console): reconcile the June work that now has docs#71
ProtocolWarden merged 1 commit into
mainfrom
claude/reconcile-june-2026-08-03

Conversation

@ProtocolWarden

Copy link
Copy Markdown
Owner

The first cl reconcile prune --apply this repo has ever had. The workflow was unrunnable here until ContextLifecycle #52 gave the lock an msvcrt backend — reconcile_lock raised on any non-POSIX host, which is why this log kept being hand-trimmed instead of reconciled.

Pairs with PrivateManifest#1, which carries the archived sections. Merge that one too, or the pointer in this log leads nowhere.

What moved

Six sections → PrivateManifest/archive/console/Custodian/log-2026-08-03.md:

  • feat: INJ1 prompt-injection signature detector
  • feat(DC10): claims-integrated-while-deferring detector (opt-in)
  • fix(doctor): register d12_baseline as a known audit key
  • feat(D12): baseline ratchet (audit.d12_baseline)
  • D12 ships OPT-IN (default-off) — was red-walling consumers
  • D12 precision: skip pytest_* plugin hooks (FP class)

Exactly the work #68 documented. The DOC GAP gate holds the rest back, correctly — pattern-collision masking, the orphan-scaffold cleanup and the --only gate still have no durable doc, so they stay partial and stay in the log.

The --recent flag matters more than it looks

Ran with --recent 20, not the default 10. At 10, prune archives claimed sections plus every unclaimed section past the tenth, purely by age — so the recency rule silently outranks the DOC GAP gate and would have archived exactly the undocumented work the gate had just declined to release.

Worth knowing before anyone runs this with defaults.

Verification

  • No content lost — diffed every non-blank line of the pre-prune log; all present in either the trimmed log or the archive
  • Idempotent — re-running prune reports nothing to archive; post-prune check is GREEN
  • .console/log.md 399 → 346, then 371 with this entry — RC1 clear
  • Audit 0 findings

One wart

CHANGELOG lines are generated from worksheet titles, and those titles are built from tokens unique to each log heading rather than written as prose. Hence ships default red walling consumers was. Legible, not elegant — flagging it since those lines are durable.

🤖 Generated with Claude Code

@ProtocolWarden
ProtocolWarden force-pushed the claude/reconcile-june-2026-08-03 branch from 96bfb2f to c10548f Compare August 3, 2026 20:04
@ProtocolWarden

Copy link
Copy Markdown
Owner Author

Review finding, fixed in-place before merge.

cl reconcile prune writes the archive's absolute local path into the pointer section (prune.py:329_pointer_section interpolates the full archive_file). On this machine that produced:

_Archived completed history → `C:\Users\<name>\Documents\GitHub\PrivateManifest\...`_

— a home directory and a real name, about to land in a public repo, and meaningless on any other host. Verified origin/main has no absolute paths today, so this commit would have been the first.

Replaced with the spec's own <private-manifest>/... form, which is what boundary rule I2 requires anyway (the private repo is resolved at runtime, never hardcoded).

Safe to hand-edit: _ensure_pointer is idempotent on the heading plus the _Archived completed history → prefix, not on the path — confirmed by re-running prune, which still reports nothing to archive.

The generator bug is ContextLifecycle's and is not fixed here — it will reproduce on the next prune in any repo.

First `cl reconcile prune --apply` this repo has had. It was unrunnable here
until ContextLifecycle #52 gave the lock an msvcrt backend (`reconcile_lock`
raised on any non-POSIX host) -- the mechanical reason this log has been
hand-trimmed for months rather than reconciled.

Six sections went to the private archive: INJ1, DC10 and the four D12 entries,
exactly the work #68 documented. The DOC GAP gate held the rest back, correctly
-- pattern-collision masking, the orphan-scaffold cleanup and the `--only` gate
have no durable doc, so they stay `partial`.

What this actually rescues: by the time it landed, #66/#67/#69 had each
hand-pruned to fit under RC1 and all six sections were ALREADY DELETED from
main. ADR 0001 named that pattern in the abstract ("D12's 'ships OPT-IN -- was
red-walling consumers' shaped C16's default in #69, and entries from that era
are now gone"); this is the concrete instance. The archive is therefore not a
tidier copy of what main holds, it is the only copy outside git history.

Ran with `--recent 20`, not the default 10. At 10 the prune also sweeps
unclaimed sections past the tenth purely by age, so the recency rule silently
outranks the DOC GAP gate and would have archived the undocumented work the gate
had just declined to release.

The pointer is hand-corrected. `cl reconcile prune` writes the archive's
ABSOLUTE local path (`prune.py` `_pointer_section`), which on this machine put a
home directory and a real name into this public repo, and is meaningless on any
other host. Replaced with the spec's `<private-manifest>/...` form, which is what
boundary rule I2 requires anyway. Safe to edit: `_ensure_pointer` is idempotent
on the heading plus pointer prefix rather than the path, verified by re-running
prune. The generator bug is ContextLifecycle's and is not fixed here.

No narrative log entry, deliberately. main sits at 389/400 and a full entry runs
~36 lines, so adding one would have meant pruning history to land a commit about
not pruning history. ADR 0001 argues rationale belongs in commit messages rather
than duplicated into the log; this follows that. The pointer is the log's record.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@ProtocolWarden
ProtocolWarden force-pushed the claude/reconcile-june-2026-08-03 branch from c10548f to b42f4f1 Compare August 3, 2026 20:09
@ProtocolWarden
ProtocolWarden merged commit 7a780b7 into main Aug 3, 2026
7 checks passed
@ProtocolWarden
ProtocolWarden deleted the claude/reconcile-june-2026-08-03 branch August 3, 2026 20:13
ProtocolWarden added a commit that referenced this pull request Aug 3, 2026
The 2026-08-03 reconciliation (#71) landed log.md at 395 lines against a 400-line
r1_line_budget, leaving no room for the next entry to be written at all — the
find_tool entry took it to 437 and red-failed our own audit on RC1.

Second pass, same convention as the first: prune the two oldest surviving entries
(2026-06-20 INJ1 detector, 2026-07-10 C32 punctuation-only values) into the
reconciled note, and condense the find_tool entry to a summary. Full rationale
lives in the commit message and PR #72; full history in git as always.

396 lines. Custodian's own audit is back to baseline — the single remaining
finding (W2, core.hooksPath unset) is environmental in this clone and does not
occur in CI, which sets it as the audit job's first step.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ProtocolWarden added a commit that referenced this pull request Aug 3, 2026
…todian's (#72)

* fix(adapters): find_tool must prefer the AUDITED repo's venv, not Custodian's

A globally-installed `custodian-multi` audited OperationsCenter — which pins
`ruff==0.15.13` — using a system-wide ruff 0.16.1, and reported 1222 findings
against a tree OC's own `ruff check` calls clean (BLE001 x316, UP045 x290,
UP037 x118, ...). Same repo, same config, ruff 0.15.13: 0 findings. Vulture
skewed the same way (621 findings). All of them phantom.

Root cause: `find_tool()` resolved `Path(sys.executable).parent / name` — the
venv Custodian ITSELF is installed in — then fell back to PATH. For a
multi-repo auditor that is backwards. Each repo pins the toolchain its config
was written against, so an audit is only meaningful when it runs those
versions; the venv Custodian happens to live in has no authority over the repo
in front of it. The old order was right by accident in the single-repo case
(Custodian installed into the audited repo's venv) and silently wrong
everywhere else — and "silently" is the problem, since the output is a
plausible-looking wall of real rule codes.

A second bug hid in the same three lines: `Path(sys.executable).parent / name`
can never match on Windows, where console scripts are `ruff.exe` and live in
`Scripts/` rather than `bin/`. The venv branch was dead code on that platform.

Resolution order is now:
  1. the audited repo's own venv (`.venv` then `venv`, `bin/` or `Scripts/`)
  2. Custodian's own venv (unchanged fallback, still needed when the venv is
     not fully activated and `shutil.which` alone would miss it)
  3. PATH

`_executable()` tries `.exe`/`.bat`/`.cmd` on Windows, and both script-dir
spellings are accepted on either host — a venv built under WSL but audited
from Windows over /mnt/c carries the other platform's layout.

The audited repo is scoped with a ContextVar and an `audited_repo()` context
manager rather than a new parameter: `is_available()` takes no arguments, and
it and `run()` must agree on which binary they are talking about.
`cli/runner._run_adapters` wraps its adapter loop in it.

Verified: 1238 passed, 5 skipped. Six new tests cover repo-venv preference, the
no-venv fallback, both script-dir spellings, and that the ContextVar does not
leak past the loop — a leak would make later repos in a `--repos a b c` run
inherit the first repo's toolchain. Custodian's own audit is unchanged from
baseline; the one remaining finding (W2, core.hooksPath unset) is
environmental. Live proof: under `audited_repo(~/GitHub/OperationsCenter)`,
`find_tool('ruff')` returns OC's pinned `.venv/bin/ruff` rather than
Custodian's own.

Noted, not fixed (pre-existing, reproduces at origin/main): tests/test_reconcile.py
does not isolate $REPOGRAPH_BOUNDARY_ARTIFACT_FILE, so two tests fail whenever
that variable is set in the caller's environment.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* chore(console): reconcile log.md so the new entry fits the RC1 budget

The 2026-08-03 reconciliation (#71) landed log.md at 395 lines against a 400-line
r1_line_budget, leaving no room for the next entry to be written at all — the
find_tool entry took it to 437 and red-failed our own audit on RC1.

Second pass, same convention as the first: prune the two oldest surviving entries
(2026-06-20 INJ1 detector, 2026-07-10 C32 punctuation-only values) into the
reconciled note, and condense the find_tool entry to a summary. Full rationale
lives in the commit message and PR #72; full history in git as always.

396 lines. Custodian's own audit is back to baseline — the single remaining
finding (W2, core.hooksPath unset) is environmental in this clone and does not
occur in CI, which sets it as the audit job's first step.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
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