Skip to content

feat(docs): doc-truth-up kit — parallel runner + FF-merge helper#26

Merged
saagpatel merged 10 commits into
mainfrom
feat/doc-truth-up-command
May 31, 2026
Merged

feat(docs): doc-truth-up kit — parallel runner + FF-merge helper#26
saagpatel merged 10 commits into
mainfrom
feat/doc-truth-up-command

Conversation

@saagpatel
Copy link
Copy Markdown
Owner

Summary

The /doc-truth-up documentation-reconciliation kit: makes each repo's docs reflect its actual code (docs-only edits, code read-only, runs unattended, commits to a docs/truth-up-<date> branch, never pushes).

This branch adds the parallel runner + FF-merge helper on top of the original kit (triage, guard hook, review doc):

  • doc_truth_up_batch.py--concurrency N (default 8) ThreadPoolExecutor over independent per-repo claude -p sessions. ~5-7x wall-clock vs sequential. Drift-priority ordering + --timeout 1200s. Every per-repo safety invariant (guard hook, doc-only backstop, clean-tree precondition, ff-restore, self-exclude, resume-skip) intact.
  • doc_truth_up_merge.py — FF-merge each reconciliation branch into the branch it was cut from + safe-delete. plan_merge() refuses anything that isn't base + exactly one doc-only commit; ancestor check makes the fast-forward provably clean. Never pushes.

Tier-2 results (2026-05-30)

49 tier-2 repos reconciled at concurrency 8 (0 violations, 0 errors, 0 stranded); 48 FF-merged into origin branches, MCPAudit deferred (base diverged).

Tests

2122 passed, 2 skipped; ruff clean. New: parallel-orchestration + failure isolation (batch), FF safety-gate against a real temp git repo (merge).

saagpatel added 10 commits May 30, 2026 03:20
…de state

Canonical, single-source instruction set for the doc-reconciliation pass:
docs are the only write target, code is read-only ground truth, no execution,
runs unattended (records uncertainty instead of asking), commits doc-only diffs
on a branch for batch review. CC-command format — installable to
~/.claude/commands/ or runnable headless via 'claude -p'.
…time stamp

Adds an explanatory preamble (purpose/origin of the file) and a full date+time
footer (via 'date'), plus HEAD sha and branch, so the record is self-describing
and timestamped for batch review.
…cope guard

Step 1 (triage): doc_truth_up_triage.py joins the presence-claims audit pre-step
(abs_path + git drift) with the audit cells (doc-quality disagreements) to rank
repos into Tier 1 (drifted OR audit-flagged → 39 repos) vs Tier 2 (clean+quiet → 80),
writing output/doc-truth-up-targets.json.

Step 4 (runner + guard):
- doc_truth_up_guard.py: PreToolUse hook (loaded via claude --settings) that hard-blocks
  any non-doc Edit/Write and any Bash outside a git/date allowlist. 10/10 behavior tests pass.
- doc_truth_up_batch.py: headless 'claude -p' runner. Defaults to DRY-RUN (needs --execute);
  skips dirty repos; runs the /doc-truth-up prompt with the guard wired in; verifies the
  committed branch diff is doc-only and DISCARDS the branch otherwise; returns each repo to
  its original branch; never pushes. Writes output/doc-truth-up-run-<date>.json for review.
…ore branch before parsing

claude --output-format json returns a JSON array (final item carries 'result');
_extract_summary now handles list/dict/garbage without raising. Also restore the
repo to its original branch BEFORE summary extraction so a parse error can never
strand a repo on the reconciliation branch. Verified on two live pilots
(DNSWatcher content catch; OrbitMechanic clean end-to-end).
…p-narrow scope)

Per operator decision to keep the edit set narrow (README/CLAUDE/AGENTS + docs/**),
the command now reliably records real drift found in non-editable docs
(IMPLEMENTATION-ROADMAP.md, HANDOFF.md, STATUS.md, etc.) under a 'Contradictions for
manual review' section in DOC-RECONCILIATION.md instead of silently skipping it.
…me-skip

Root-caused a batch failure where ~25 repos returned no_change: the guard hook was
referenced at its in-repo path, and when the auditor repo's HEAD switched to a branch
lacking the script, the missing-file hook exited non-zero → Claude Code blocked every
edit/git call → sessions became silent no-ops. Three fixes:
- copy the guard to a stable temp path so the hook is branch-independent;
- exclude the auditor repo itself from any batch (never manipulate the HEAD a live
  session depends on);
- skip repos that already carry today's docs/truth-up branch, so a re-run resumes
  instead of re-processing completed work.
Verified: Afterimage now reconciles cleanly (48 turns, rate_limit 'allowed').
…conciliations

Collects every docs/truth-up-<date> branch (and husky-blocked staged repos) into
output/doc-truth-up-review-<date>.md: per repo, the DOC-RECONCILIATION.md sign-off +
the doc diff, in collapsible sections. Diffs the reconciliation commit itself
(branch~1..branch) so a branch cut from a non-main base shows only its doc changes;
requires a DOC-RECONCILIATION.md marker (excludes coincidental pre-existing branches);
skips the auditor repo. Prints a compact index to stdout.
…ault 8)

Tier 2 is wall-clock-bound, not token-bound. run_one is fully self-contained
per repo (own .git index, own branch), so the sequential for-loop is the only
bottleneck. Swap it for a bounded ThreadPoolExecutor:

- run_batch(): fan run_one across max_workers=concurrency, gather via
  as_completed, serialize output through a lock, isolate a crashing repo into
  an error result so one failure can't sink an unattended batch.
- --concurrency N (default 8); 1 = sequential. --timeout default 900->1200s so
  BattleGrid-class slow repos finish (a slow repo now holds one slot, not the
  whole batch).
- select_targets() sorts drift-priority (drifted, then disagreement_count),
  stable — a no-op for clean-audit tiers, real ordering for --tier all.

Every per-repo safety invariant (guard hook, doc-only backstop, clean-tree
precondition, ff-restore-to-origin, self-exclude, resume-skip) lives inside
run_one and is untouched. Tests cover the sort + parallel orchestration with
failure isolation.
Completes the kit: FF-merge each reconciliation branch into the branch it was
cut from, then safe-delete it. plan_merge() is pure inspection and refuses
anything that isn't 'base + exactly one doc-only commit':

- branch must exist and the current branch must be its ANCESTOR (merge-base ==
  cur) — a diverged base means ff-only is unsafe, so SKIP (e.g. MCPAudit).
- exactly 1 commit ahead of the base branch, else SKIP.
- that commit re-verified doc-only here (defense in depth over the runner).
- coincidental same-named branches with 0 commits ahead SKIP (e.g. SignalDecay).

merge_one() then does git merge --ff-only (never a merge commit, never loses
history, fails closed) + git branch -d (safe delete). Never pushes.
Tests exercise the gate against a real temp git repo: happy ff, non-doc commit,
diverged base, multi-commit, missing branch, plus end-to-end merge+delete.
Force-added past the output/ gitignore (output/ is ephemeral by repo
convention) to preserve the audit trail of the parallel tier-2 sweep:
- review doc (49 reconciliations), run JSON, smoke + full run logs.

Outcome: 49 tier-2 repos reconciled at concurrency 8; 48 FF-merged into their
origin branches, MCPAudit deferred (base diverged, ff-only unsafe).
@saagpatel saagpatel merged commit d67acc1 into main May 31, 2026
2 checks passed
@saagpatel saagpatel deleted the feat/doc-truth-up-command branch May 31, 2026 07:14
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