Skip to content

chore(archive): preserve the external Codex review log + file backlog #166-#170 - #401

Merged
KbWen merged 5 commits into
mainfrom
chore/archive-codex-review-log
Aug 12, 2026
Merged

chore(archive): preserve the external Codex review log + file backlog #166-#170#401
KbWen merged 5 commits into
mainfrom
chore/archive-codex-review-log

Conversation

@KbWen

@KbWen KbWen commented Aug 12, 2026

Copy link
Copy Markdown
Owner

Housekeeping, records-only. Clears the oldest open item on the backlog's > 2026-08-09 (wave close + pick order) note — an external reviewer's Codex Work Log left active in work/ — and files five verified defects found while clearing it and the adjacent dependabot backlog. No engine, workflow, validator, or governance-rule change.

Two independent reviews ran before merge and both are adopted; details at the bottom.

1. Archive the external Codex review log

chore-govern-audit-20260808.md.agentcortex/context/archive/chore-govern-audit-20260808-20260812.md, moved verbatim, with a hash-chained INDEX.jsonl entry.

Archive, not resume. Its terminal state is review | NOT READY → routed back to the PR owner, the correct final state for a read-only reviewer with no local implementation authority. All four of its findings were real and remediated before merge — each fix commit resolved against git before being written into the chain: bec66d4 (look-timing recursion), 691ea68 (fence-blind parser and the PASS-labeled-advisory labels; counted-WARN promotion routed to backlog #103(d)), c1f724b (byte-level LF coverage).

The premise this PR started from was wrong, and the pre-change baseline caught it. The orphan log was not producing a FAIL: the completeness audit is guarded by validate.sh:1548 if has_ship_receipt or 'ship' in gate_set:, so a log without a ship receipt skips it. Baseline pass=118 warn=3 fail=0 skip=2, log not named anywhere in the 165-line run.

The reason that survives is preservation of the first-party artifact. current_state.md:128 already narrates this review in tracked SSoT, so the record was never at risk — the reviewer's own words were, living only in gitignored work/*.md on one machine. Moved verbatim because the log belongs to another owner (codex-root); the closure narrative lives in the INDEX.jsonl decisions field, per the PR #371 precedent.

The archival entry carries no shipped field, because nothing shipped from that log. Verified behaviour-neutral before removing it: log_date = index_dates.get(name) or _filename_date(name) (:291), and an entry only enters index_dates when shipped is a non-empty string (:141-143), so the -20260812 filename suffix supplies the same date. The sibling entry for this PR's own log keeps shipped, because that log did ship.

This PR also archives its own Work Log, per the same #397/#400 precedent it cites.

2. Five backlog rows, each reproduced before being filed

Row Defect Priority
#166 TruffleHog AC-5 SHA pin binds the wrapper action, not the scanner binary — and AC-3's "full-history scan" claim is false P1
#167 validate.sh:2294 destroys the filename inside its own broken-link diagnostic P3
#168 append_chain_entry.py writes CRLF on Windows into the hash-chained audit log P3
#169 check_decision_disposition.py is fail-open against off-spec Decisions syntax P2
#170 Five legacy archived logs publish a personal email — owner decision, not an AI call P3

#166 is the substantive one. security.yml:101 pins the wrapper action and tests/ci/test_security_workflow.py:211 machine-enforces that pin, but the step passes only extra_args while the wrapper's action.yml declares version: default: "latest" (:21-23), threaded into the docker run image reference (:39, :97). Evidenced by a pre-bump main run31288803917 at 44b2e33 (2026-08-09) loads the old action 00155c9d…, then logs version: latestDigest: sha256:aa821cf4…"trufflehog_version": "3.96.0". So main, pinned to the v3.95.8 action, was executing a 3.96.0 scanner from a mutable tag. P1 because AC-5's declared object is the scanner version — the bounded blast radius (--since-commit scanning, non-required job) limits the consequence, not the control failure.

All five are filed, not fixed — each fix touches tool, workflow, or .gitattributes code a records-only PR should not carry.

Reviews

Review 1 (different vendor) returned NOT READY with eight inline findings; seven adopted, one partially overruled, each verified against the tree first. It caught three defects in records that become immutable at merge: the shipped overload, a personal email in the Owner field, and — most usefully — that #166's original evidence was invalid, since PR #386's CI runs on the bumped head and therefore shows the new wrapper pulling latest. That claim was re-evidenced from a pre-bump main run rather than withdrawn. It also caught that the Decisions section, written as - **D-N** bullets, was invisible to check_decision_disposition.py (D_ENTRY_RE = ^### D-) — ten decisions carried no disposition marker while the check printed OK. Converted to canonical entries; the checker now reports 12 logs checked where it reported 11. That fail-open became #169. Adjudications are posted per-thread on this PR.

Review 2 (second model tier, prompt stripped of the first review's framing) independently reproduced all four then-existing rows from source — re-fetching the #166 job log and re-implementing the chain hash to recompute all 151 entries — and agreed with every severity. Its three actionable findings are adopted: the stale pick-order note (marked DONE, with the recurrence recorded), the untracked legacy-email disposition (now #170), and this PR's own title and body having gone stale against head — which mattered because the repo squash-merges with them, so merging would have written a false description of these records into main's permanent history. Both earlier passes reviewed the diff; neither reviewed the artifact the merge would produce.

Partially overruled: splitting #166 into its own PR. The line-count argument is weak for a records-only PR whose bulk is one archived log; the independent-origin point is correct and recorded in D-4; the rollback-coupling point was strong because #166 was the shakiest content, and repairing its evidence removed that force. Disagreement recorded rather than resolved silently.

Evidence

  • validate.sh and validate.ps1 both pass=118 warn=4 fail=0 skip=2 — exact parity, fail=0. Independently corroborated by review 2 at the same head.
  • Isolation by result LINES (repo-gotchas [Feature] Work Log auto-compaction mechanism #14) against the pre-change baseline: three differing lines, of which two are this PR'sINDEX.jsonl referenced logs 147 → 149 and archive size 2110 → 2146KB. The third is a stale-lock WARN from the reviewer's own gitignored artifacts, external to this diff. Not cherry-picked: an intermediate run read pass=100 warn=3 skip=3 while work/ was genuinely empty, and that state no longer holds.
  • Chain intact at every rewrite (check_audit_chain.py); the pre-merge tail rewrites correctly recomputed successor prev_sha values, independently confirmed by review 2 recomputing all 151 entries.
  • check_decision_disposition.py → OK with 12 logs checked; 11 canonical ### D-N: entries, 11 dispositions.
  • test_backlog_validation.py 3 passed at 105 rows; every row at exactly 11 pipes.
  • Honest ceilings, stated rather than glossed: the verbatim-move sha256 equality and the 12,276-byte pre-compaction state are both self-attestation no reviewer can falsify — the pre-images were gitignored and are gone. The committed log is 17,110 bytes because it legitimately regrew after archival, where the active-log cap no longer applies. What is checkable, and was: the archived bytes are LF-clean, and the log's Diff Base SHA: 7da1859 resolves to a real 2026-08-08 commit whose current_state.md reads Update Sequence: 143, matching the log's own header.

Rollback: revert this PR. The two archived logs return to untracked state and the chain tail drops two entries.

🤖 Generated with Claude Code

KbWen and others added 2 commits August 12, 2026 10:02
…166

Clears the oldest item on the backlog 2026-08-09 pick-order note and files
one real defect found while clearing the adjacent dependabot backlog.

1. Archive chore-govern-audit-20260808.md verbatim into the tracked, hash-
   chained archive. Archive, not resume: its terminal state is review
   NOT READY routed back to the PR owner, the correct final state for a
   read-only reviewer with no local implementation authority, and all four
   of its findings were remediated before merge (bec66d4, 691ea68 x2,
   c1f724b -- each SHA resolved against git before being written into the
   chain, which corrected the record: 691ea68 carries both the fenced-decoy
   parser fix and the advisory labeling, not just the former).

   The premise this task started from was wrong and the baseline caught it.
   The orphan log was NOT producing a FAIL: the completeness audit is guarded
   by validate.sh:1548 `if has_ship_receipt or 'ship' in gate_set:`, so a log
   with no ship receipt skips it entirely. The reason that survives is
   preservation -- .gitignore:4 ignores work/*.md while archive/ is tracked,
   so this repo's only different-vendor external review record was living on
   a single machine, outside version control. That review is also the evidence
   backing the [audit-method][HIGH] lesson's external-signal requirement.

   Moved verbatim (sha256 identical, source deleted -- a MOVE per ship.md:198)
   because the log belongs to another owner (codex-root); the closure narrative
   goes in the INDEX.jsonl decisions field, per the PR #371 precedent.

2. Backlog #166 -- the TruffleHog AC-5 SHA pin does not bind the scanner.
   security.yml:101 pins the wrapper action and test_security_workflow.py:211
   machine-enforces that pin, but the step passes only extra_args and the
   wrapper's action.yml at that exact pinned SHA declares version: "latest"
   (:21-23) threaded into docker run "${IMAGE}:${VERSION}" (:39, :96). The
   enforced control does not bind the artifact it was written to protect --
   PR #386's job log shows a 3.96.0 scanner running since 2026-08-03 while
   main still pinned the v3.95.8 action SHA. Verified at source, not taken
   from the review agent. P2 because the blast radius is bounded: the wrapper
   scans --since-commit BASE --branch HEAD so detector changes cannot
   retro-fire on history, and the job is not branch-protection-required.
   Filed, not fixed.

No engine, workflow, validator, or governance-rule change. SSoT untouched and
no Ship History entry (no feature shipped, per the 2026-07-09 reconcile-note
precedent reaffirmed by PR #397).

Evidence: baseline and post-change validate.sh both pass=118 warn=3 fail=0
skip=2, validate.ps1 identical. Isolation proven by result LINES not totals
(repo-gotchas #14): exactly two lines moved, both expected consequences of the
archival -- INDEX referenced logs 147->148 and archive size 2110->2118KB. No
WARN moved. Chain intact (prev_sha 13c57849). Backlog 100->101 rows, diff
--stat exactly 1 insertion, rows #165/#166 distinct, backlog validation
3 passed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… + #168

A tenth-man refute-only pass ran on this PR after CI went green but before
merge. Ten findings: three MAJOR and two MINOR stood, one stood weaker, four
were refuted. All five actionable ones are adopted here, and working through
them surfaced three further defects in this PR's own output.

Adopted from the refute pass:

* shipped field realigned to the archival date (2026-08-12) and the archive
  filename with it. The draft wrote the review date for a log that shipped
  nothing, and that field is machine-read -- check_decision_disposition.py
  uses it as the lifecycle-close date for cutoff grandfathering. A structured
  field asserting a ship that never happened, corrected only in adjacent
  prose, is backwards for this repo, and it is immutable after merge. The
  INDEX decisions array now states in capitals that nothing shipped.
* "only different-vendor review RECORD" was an overclaim, corrected to "only
  first-party ARTIFACT". current_state.md:128 already narrates this review in
  tracked SSoT. The wrong wording had reached the chain entry, the commit
  message and the PR body; all three are fixed.
* This PR now archives its own Work Log. As drafted it left that log
  untracked and gitignored on one machine -- reproducing the orphan condition
  it exists to clear -- while citing PR #397, which did archive its own.
* Row #166: dropped a variable name that does not exist at the SHA the row
  cites, corrected an off-by-one line reference, and folded in the AC-3
  defect the refute pass surfaced (the spec claims a full-history scan the
  wrapper never performs; the test certifies only fetch-depth).
* Corrected a false evidence line that claimed "exactly 1 insertion" -- read
  before the frontmatter edit and already false when written.

Found while adopting them, each reproduced before being written down:

* Backlog #167 -- validate.sh:2294 prints the broken-link diagnostic with
  printf '%b', which expands backslash escapes in the data, so a Windows
  absolute path emits "missing unicode digit for \U" and a mangled filename.
  The diagnostic fails exactly when it is needed. Scope-checked: 10 of the 11
  '%b' sites dump repo-relative paths and are not reachable, so the row says
  one confirmed site and warns against fixing the rest without a repro.
* Backlog #168 -- append_chain_entry.py writes CRLF on Windows into the
  hash-chained INDEX.jsonl, an un-swept sibling of the #160 LF-stable-writers
  fix. The code looks binary-safe (os.write of encoded bytes); the trap is
  that os.open omits O_BINARY and defaults to text mode on Windows.
  Reproduced from clean inputs. Chain integrity is unaffected; the harm is a
  mixed-EOL tracked file and the manual normalise this session had to perform,
  which is exactly what #160 recorded. Filed P3, not fixed here.
* Self-inflicted, caught by the validator and not by the backlog test: row
  #168's first draft spelled out an os.open flag expression containing literal
  pipes, escaped as \| , which markdown field splitting does not honour. The
  row carried 13 pipes against every other row's 11 and its Labels column
  became garbage, tripping a label-vocabulary WARN. test_backlog_validation.py
  reported 3 passed on the corrupted table. Fixed, then re-checked across all
  103 rows.

Also of record: the log tripped the 12KB active-log compaction cap at 15KB.
It was compacted to 12276 bytes -- genuinely under the 12288 cap, not relying
on the integer-KB truncation that would have let 12.9KB pass -- rather than
letting archival remove the file from the scanned set. Gate progression was
verified while the log was still active, the only window in which that check
can see it: the NOT READY -> implement -> review PASS trace is legal.

Evidence: validate.sh and validate.ps1 both pass=100 warn=3 fail=0 skip=3,
exact parity, fail=0, warn back to the pre-existing 3. Isolation by result
LINES against the pre-change baseline gives exactly three differences and the
arithmetic closes: INDEX referenced logs 147->149, archive size 2110->2142KB,
and 18 active-work-log PASS lines collapsing into the single backlog-#149
family SKIP now that work/ holds no *.md (118-18=100 pass, 2+1=3 skip).
Chain intact. test_backlog_validation.py 3 passed at 103 rows, all rows at 11
pipes. INDEX.jsonl restored to w/lf after the CRLF appends.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@KbWen KbWen changed the title chore(archive): preserve the external Codex review log + file backlog #166 chore(archive): preserve the external Codex review log + file backlog #166, #167, #168 Aug 12, 2026

@KbWen KbWen left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Independent review at exact head 308627ca4ac98f7a0c8fce5181e17f4dd907aabd: NOT READY.

Own account: this is a records-only change that appends two hash-chain entries, commits two archived Work Logs, and adds three backlog rows. The chain and file references are intact, the focused suite passes (43 tests), and #167/#168 are reproducible. It is not correct or safe to merge as written because the records contain a decision-disposition bypass, a machine-field semantic misrepresentation, an invalid #166 evidence claim, an incomplete #168 remediation, and public PII.

Independent backlog severity: #166 mutable scanner HIGH/P1; #166 full-history claim MEDIUM/P2; #167 LOW/P3; #168 LOW/P3. I disagree with the row only on #166's mutable-image half. Note: the initial PR diff fetch exposed the row priorities before I could preserve the requested blind ordering; these ratings were then derived independently from source and reproduction, not adopted from the rows.

Could not verify: actual main branch-protection required contexts (GitHub API 403); the deleted gitignored pre-image for the verbatim-move hash; the intermediate 12,276-byte active-log state. I verified what remains falsifiable and called out those limits inline.

GitHub does not allow the PR author account to submit REQUEST_CHANGES on its own PR, so this review is posted as COMMENT; the substantive verdict remains NOT READY.

Comment thread .agentcortex/context/archive/chore-archive-codex-review-log-20260812.md Outdated
Comment thread .agentcortex/context/archive/INDEX.jsonl Outdated
Comment thread docs/specs/_product-backlog.md Outdated
Comment thread docs/specs/_product-backlog.md Outdated
Comment thread .agentcortex/context/archive/chore-archive-codex-review-log-20260812.md Outdated
Comment thread .agentcortex/context/archive/chore-archive-codex-review-log-20260812.md Outdated
Comment thread .agentcortex/context/archive/chore-archive-codex-review-log-20260812.md Outdated
An independent different-vendor review returned NOT READY with eight inline
findings at head 308627c. Seven adopted, one partially overruled. Each was
verified against the tree before acting.

Adopted:

* Decisions were written as `- **D-N**` bullets, which check_decision_
  disposition.py cannot see (D_ENTRY_RE = ^### D-, caller skips on zero
  entries). Ten decisions carried no disposition marker and the check still
  printed OK. Converted to canonical `### D-N:` entries with `-> local`
  markers; the checker now reports 12 logs checked where it reported 11, so
  the log went from invisible to actually verified. The fail-open itself is
  filed as backlog #169.
* The archival INDEX entry no longer carries a `shipped` field at all. The
  reviewer was right that an archival date overloads a documented ship-date
  field. Verified behaviour-neutral before removing: log_date =
  index_dates.get(name) or _filename_date(name), and an entry only enters
  index_dates when `shipped` is a non-empty string, so the -20260812 filename
  suffix supplies the same date with no false claim. The sibling entry for
  this PR's own log keeps `shipped`, because that log did ship -- the finding
  was blanket where the situation is not.
* #166's evidence was invalid: PR #386's CI runs on the bumped head, so its
  log shows the NEW wrapper pulling `latest`. Re-evidenced rather than
  withdrawn -- main-branch run 31288803917 at 44b2e33 (pre-bump) loads the
  OLD action 00155c9d, then logs `version: latest`, `Digest: sha256:aa821cf4`,
  `"trufflehog_version": "3.96.0"`.
* #166 severity P2 -> P1: AC-5's declared object is the scanner version, so
  the blast-radius argument bounds the consequence, not the control failure.
* #168 now requires an LF checkout contract as well as O_BINARY: .gitattributes
  covers *.json but not *.jsonl, so `* text=auto` plus core.autocrlf=true
  materialises CRLF and an O_BINARY writer would append a lone LF. The earlier
  `w/lf` reading was a one-working-copy artifact, not a repo invariant.
* Owner field no longer publishes a personal email (template asks for a
  session id or username). Five older archived logs carry the same address;
  surfaced to the maintainer rather than rewritten unilaterally.
* The 12,276-byte compaction claim is now carried as an explicit ceiling --
  the committed artifact is 17,110 bytes because it legitimately regrew after
  archival, and the pre-archive state was gitignored and is gone.
* Checkpoint SHA 160acc4 -> 33fb21a.

Partially overruled: splitting #166 into its own PR. The line-count argument
is weak for a records-only PR whose bulk is one archived log; the independent-
origin point is correct and recorded in D-4; the rollback-coupling point was
strong because #166 was the shakiest content, and repairing its evidence
removed that force. Disagreement recorded rather than resolved silently.

Also of record: mid-session the reviewer's own Codex agent created an active
log and lock in work/ -- the same pattern this unit exists to clean up,
recurring during the cleanup, and using the same worklog-key derived from the
shared branch. Both files are gitignored and absent from this diff. No row
filed: AGENTS.md already prescribes <owner>-<worklog-key>.md for this, so it
is an adherence gap, not a missing mechanism.

Evidence: validate.sh and validate.ps1 both pass=118 warn=4 fail=0 skip=2,
exact parity. Result-line isolation against the pre-change baseline gives
three differing lines, only two of them this PR's (INDEX referenced logs
147->149, archive size 2110->2146KB); the third is the reviewer's stale-lock
WARN. Chain intact. Disposition check 12 logs OK. test_backlog_validation.py
3 passed at 104 rows, all rows at 11 pipes. INDEX.jsonl at w/lf.

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

KbWen commented Aug 12, 2026

Copy link
Copy Markdown
Owner Author

Adjudication — 8 findings, 7 adopted, 1 partially overruled

Each finding was verified against the tree before acting, not accepted on read. Thank you for the NOT READY; three of these were real defects in records that become immutable at merge.

Adopted in full

[P1] Bullet-form decisions evade the disposition check — confirmed exactly as described. D_ENTRY_RE = re.compile(r"^### D-") (check_decision_disposition.py:80) and the caller's if not entries: continue (:285-288) mean the log was skipped entirely, not passed. Converted all ten to canonical ### D-N: entries with → local dispositions; the checker now reports 12 logs checked where it previously reported 11 — the log went from invisible to actually verified. The fail-open itself is now backlog #169, framed as the #138 Signal-A tripwire failing in the direction it exists to prevent: a green check is worse than no check because it reads as compliance. Preferred fix recorded as (a) WARN when a non-empty, non-none Decisions section yields zero canonical entries, rather than (b) blessing a second dialect.

[P1] shipped overloading — confirmed, and I went further than the suggested remedy. Rather than invent a field no consumer understands, I verified the fallback path first: log_date = index_dates.get(name) or _filename_date(name) (:290), and an entry only enters index_dates when shipped is a non-empty string (:141-143). So omitting the field entirely is behaviour-identical — the -20260812 filename suffix supplies the same date — while making no false claim. Done.

One correction to the finding as filed: it is blanket where the situation is not. The sibling entry for this PR's own Work Log keeps shipped: 2026-08-12, because that log genuinely did ship. Only the retroactive-archival entry drops it.

[P1] The #386 job-log claim is invalid — you are right, and this was the most useful finding. #386's CI runs on the bumped head, so its log shows the new wrapper pulling latest. The claim was re-evidenced rather than withdrawn: main-branch run 31288803917 at 44b2e33 (2026-08-09, pre-bump) loads the old action trufflesecurity/trufflehog@00155c9d…, then logs version: latestlatest: Pulling from trufflesecurity/trufflehogDigest: sha256:aa821cf4…"trufflehog_version": "3.96.0". So main was executing a 3.96.0 scanner while pinned to the v3.95.8 action. Row updated with that run and an explicit note about the rejected evidence.

[P1] #166 severity — adopted, P2 → P1. Your reasoning is better than mine: AC-5's declared object is the scanner version, so the blast-radius argument bounds the consequence, not the control failure.

[P2] O_BINARY alone is insufficient — confirmed. .gitattributes carries *.json (:16) but no *.jsonl, so the file falls under * text=auto (:2) and a normal Windows checkout materialises CRLF. My w/lf reading was a post-normalise artifact of one working copy, exactly as you say — not a repository invariant. #168 now requires both halves: the O_BINARY flag and an LF checkout contract (*.jsonl text eol=lf). Your independent reproduction of the migrate() path is cited too; that half was previously flagged as unverified.

[P2] Personal email as Owner — confirmed against the template (<session-id or username>), changed to KbWen. Note for the maintainer rather than this PR: the same address already appears in five older archived logs, which I am surfacing rather than rewriting unilaterally.

[P2] The compaction claim is not established by the committed artifact — confirmed. The file is 17,110 bytes because it legitimately regrew after archival, where the active-log cap no longer applies. The 12,276-byte pre-archive state was gitignored and is gone, so that number is not falsifiable by any reviewer. Stated as an explicit ceiling alongside the sha256 one, rather than left as a bare claim.

[P3] Stale Checkpoint SHA — confirmed, 160acc433fb21a.

Partially overruled

[P2] Split #166 into its own PR. Three sub-arguments, adjudicated separately.

Kept together, with the disagreement recorded in D-4 rather than resolved silently. If the maintainer prefers the split it is a one-command change and I will do it.

On your stated limits

Branch protection, which you could not read (403): required contexts are Framework Validation, ShellCheck, Check Markdown Links, with strict: true. That confirms the #166 row's claim that Secret Detection (TruffleHog) cannot block a merge. The two deleted gitignored pre-images — the verbatim-move hash and the 12,276-byte state — are both now carried as explicit honest ceilings; you are right that neither is reproducible.

Noting the ordering leak you flagged: the row priorities were visible in the diff before you could rate blind. Your independent ratings still moved the outcome (P2 → P1 adopted), so I do not think the leak neutralised the exercise, but it is worth designing around next time.

…order note

A second independent review at a different model tier, prompted without any
reference to the first review's findings or severities, reproduced all four
existing backlog rows from source -- re-fetching the #166 job log and
re-implementing the chain hash to recompute all 151 entries -- and agreed with
every severity. Corroboration rather than duplication. Three actionable
findings, all adopted.

* PR title and body had gone stale against head, and this repo squash-merges
  with them -- so merging would have written a false description of these
  records into main's permanent history: three rows instead of four, #166 as
  P2, the #386 evidence the head row itself declares invalid, and a shipped-
  field design the head had already reversed. Rewritten. Neither earlier pass
  caught this: both reviewed the diff, not the artifact the merge produces.

* The governed pick-order note at _product-backlog.md:170 still read "archive
  or resume at next convenience" -- the very instruction this unit exists to
  discharge. Marked DONE, with the recurrence recorded: the review session for
  this PR left its own log and lock in work/ under codex-root-pr401, deriving
  the same worklog-key from the shared branch. Deliberately no row for that --
  AGENTS.md already prescribes <owner>-<worklog-key>.md, so it is an adherence
  gap in the reviewer's setup, not a missing mechanism.

* The legacy-email finding had no tracked disposition -- it lived only in a
  commit message and a PR thread, neither a pickup surface, which the
  no-deferred-disposition rule does not allow. Now backlog #170, framed as an
  owner decision with both options stated (accept-and-close, since the address
  is already public in commit metadata; or a history rewrite that breaks the
  append-only witness) rather than an AI call.

Lower-severity adoptions: #166 now names the dependabot drift trap (a
`with: version:` pin sits outside the action-SHA bump surface, so wrapper SHA
and image version silently diverge on the next bump); this unit's own INDEX
entry had frozen a superseded D-6 narration that contradicted the final design
and the adjacent entry, rewritten before the chain closes over it; and a
:290 -> :291 off-by-one, the same citation-drift class D-9 already fixed.

New D-11 records the second review. Decisions now 11 canonical entries with 11
dispositions.

Evidence: validate.sh and validate.ps1 both pass=118 warn=4 fail=0 skip=2,
exact parity, fail=0 -- independently corroborated by the reviewer running
validate.sh to completion at the same head, and its CI-side 4th WARN
(append-only witness, no merge-base) traced to PR-context shallow checkouts by
observing it identically on PRs #395 and #399. Chain intact after the tail
rewrite. Disposition check 12 logs OK. test_backlog_validation.py 3 passed at
105 rows, all rows at 11 pipes. INDEX.jsonl at w/lf.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@KbWen KbWen changed the title chore(archive): preserve the external Codex review log + file backlog #166, #167, #168 chore(archive): preserve the external Codex review log + file backlog #166-#170 Aug 12, 2026
@KbWen
KbWen merged commit 6f9205d into main Aug 12, 2026
19 checks passed
@KbWen
KbWen deleted the chore/archive-codex-review-log branch August 12, 2026 08:51
KbWen added a commit that referenced this pull request Aug 12, 2026
)

Records-only. Adds the SSoT Ship History entry that PR #402 should have
carried, ahead of the v1.8.20 release cut.

## Why this is not optional

`Update Sequence` stood at **147** with the newest Ship History entry
covering #399/#400. Neither #401 nor #402 was recorded, and `grep -c
'#402' current_state.md` returned **0** — so a **P1 security fix**, an
amendment to a shipped spec's acceptance criteria, and a newly created
L2 domain log were all absent from the record.

That propagates: **the release cut's CHANGELOG derives from Ship
History**, so v1.8.20 would have shipped release notes missing the most
significant item in the version.

**#401 legitimately skipped SSoT** — records-only, no feature shipped,
per the 2026-07-09 reconcile-note precedent reaffirmed by PR #397, and
that call survived independent review. **#402 does not qualify for the
same exemption.**

## What changed

- Ship History entry for
`Ship-fix-166-trufflehog-scanner-pin-2026-08-12`, covering the digest
pin, the AC-3/AC-5 corrections, the reclassification to `hotfix`, and
the Lob false-positive incident that became #171.
- `Update Sequence` 147 → 148, `Last Updated` refreshed.
- **Cap rotation**: Ship History was at 10/10, so the oldest entry
(`Ship-docs-repo-gotchas-14-worklog-archival-2026-07-27`) moved verbatim
into `archive/ship-history-2026.md` rather than being dropped.

Written with `guard_context_write.py --mode replace` under optimistic
locking (`--expected-sha`, receipt committed). Not `--mode append` —
that path lands at file end, and the entry belongs at the top of the
section.

## Process note

Classification was **measured before being assigned**: 21 changed lines
across 2 substantive modules, against `state_machine.md:51`'s 200-line /
2-module hard block. The immediately preceding unit classified first and
violated that block, which the independent review on #402 caught;
reversing the order is the fix, and it is recorded in the Work Log as
the reason the order matters.

## Evidence

- `check_ssot_caps.py` → `ssot caps OK — ship history 10/10, spec index
26/30` (10 entries before and after).
- `check_audit_chain.py` → `audit chain intact`.
- `validate.sh` **`pass=118 warn=4 fail=0 skip=2`**. Self-archival
verified by delta, not asserted: before it `warn=5` including `shipped
work logs still in active work/ directory: 1`; after, that line is gone.
The 4th WARN is an external reviewer's stale lock from PR #401 —
gitignored, outside this diff. Totals are machine-local; CI is the
replayable evidence.
- **Backlog #168 fired a third time during this ship**: after the branch
switch git re-materialised `INDEX.jsonl` fully CRLF and the pre-commit
normalise reported **153 → 0**. Third independent confirmation that
#168's fix needs the `*.jsonl text eol=lf` half, not just `O_BINARY`.

Rollback: revert this PR. The sequence returns to 147 and the rotated
entry returns to `current_state.md`.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
KbWen added a commit that referenced this pull request Aug 12, 2026
…404)

Release cut for **v1.8.20**. Docs-only: version banners, CHANGELOG, and
the release's own Ship History entry. **No engine, test, or logic change
rides this PR** — everything substantive was already merged and
individually CI-green.

## What it packages

Ten commits sat unreleased on `main` while the banner still read 1.8.19.

| | |
|---|---|
| **PR #402** | backlog **#166 (P1)** — the TruffleHog pin bound the
*wrapper*, not the scanner. Now pinned by image digest; AC-3's false
"full-history scan" claim and the Domain Decision that generated it
corrected; new `docs/architecture/ci-security.log.md` |
| **PR #395** | backlog #163+#164 — audit-wave leftovers |
| **PRs #386/#377/#378** | three dependabot bumps, open 8–15 days |
| **PRs #397/#399/#400/#401/#403** | records wave, including the
archival of this repo's only different-vendor review artifact |

## What it changes here

Banners 1.8.19 → 1.8.20 across the canonical 7 (`deploy.sh`
`ACX_VERSION`, `CITATION.cff` version + `date-released`, Model Guide
EN/zh-TW, Testing Protocol EN/zh-TW, `antigravity-v5-runtime.md`),
CHANGELOG `[1.8.20]`, SSoT sequence 148 → 149 with the cap-10 rotation.

## Shipping a known state, not a quiet one

The CHANGELOG names **five defects filed and deliberately unfixed**
(#167#171) rather than omitting them — including **the scanner
false-positive class that blocked this release's own security PR**. Each
fix touches tool, workflow, or `.gitattributes` code a docs-only cut
must not carry, and #171's detector exclusion is a security-coverage
decision that deserves its own review.

It also records a governance failure rather than burying it: **PR #402
was classified `quick-win` at 276 lines across four modules**, against a
hard block at 200 lines / 2 modules — which is what let its review gate
be skipped. Independent review caught it; it was reclassified to
`hotfix` through the documented rollback mechanism, with the retroactive
sequencing stated plainly. The durable fix is procedural — *measure the
diff, then classify* — and the two units after it did so.

## Evidence

- **Banner sweep verified both directions**: each of the 7 replacements
asserted to match exactly once before writing, then `grep -rn
"1\.8\.19"` across the same 7 files → **no matches**.
- **Guarded SSoT write** under optimistic locking → `{"status": "ok"}`;
10 Ship History entries before and after; `check_ssot_caps.py` → `ship
history 10/10, spec index 26/30`.
- `check_audit_chain.py` → `audit chain intact`.
- `validate.sh` **`pass=118 warn=4 fail=0 skip=2`** — machine-local
totals (a clean checkout runs 18 fewer active-work-log checks); CI is
the replayable evidence.
- **A wrong fact caught before it landed**: the Ship History entry first
named the wrong rotated entry. Corrected in the staged content, so it
never reached `current_state.md`.

## Not done at merge

Per `repo-gotchas` #12 — and forgotten twice before — the release is
**not complete when this merges**. The lightweight `v1.8.20` tag and `gh
release create --latest` are separate manual steps, tracked to
completion in this session.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

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