EV — TFW-56: Remove the Review Mode Axis¶
Date: 2026-08-13 Author: Executor (Claude Code) Task: TFW-56 TS: TS TFW-56
Environment¶
| Field | Value |
|---|---|
| OS | Windows 11 Pro 10.0.26200 |
| Language / Runtime | Python 3.13.5 |
| Shells | Git Bash (MSYS2), git 2.42.0.windows.1 |
| Build | python -m pytest docs/scripts/ (68 tests) — the docs pipeline is the only build that consumes the changed files |
| CI / Pipeline | .github/workflows/docs.yml — run locally here |
project_config.yamlbuild.lint/test/verifyare unconfigured starter placeholders (echo "configure your … command").conventions.md,glossary.md,.tfw/workflows/**and.tfw/templates/**are Source Manifest rows 4, 5, 12 and 13, so the docs build is the substitution — the same substitution used and approved in EV TFW-53/A.
Evidence¶
| # | AC | What was verified | Environment | Result | Artifact |
|---|---|---|---|---|---|
| E1 | AC-1 | The mode-file folder is gone and review.md's steps are contiguous with Step 0 = Session Naming |
Git Bash | VERIFIED | §E1 — ls fails; 8 headings, 0-7, no gaps |
| E2 | AC-2 | Judge checklist is exactly ten universal rows, no Mode: field, no Mode-Specific section |
Git Bash | VERIFIED | §E2 — row count 10, grep -c "Mode" → 0 |
| E3 | AC-2 | S1-vs-U7 dry-run against an archived RF/EV/REVIEW triple — do rows 7 and 8 produce different answers? | Reading, against TFW-53 Phase A | VERIFIED | §E3 — row 7 ✅, row 8 ❌ with three findings. Different answers, different reasoning |
| E4 | AC-3 | Eight mode checklist rows each accounted for | Reading | N/A | TS Evidence field: N/A — this is a documentation-completeness check, verifiable by reading. Table in RF §3 / §2 |
| E5 | AC-4 | Eight distinct verify actions each accounted for; map.md and verify.md carry no Mode: |
Reading + grep | N/A | TS Evidence field: N/A — file content, verifiable by reading. Table in RF §2; grep result in §E6 below |
| E6 | AC-5 | REVIEW.md §3 matches judge.md row-for-row, same order; no header field, no placeholder |
Reading | N/A | TS Evidence field: N/A — template content. §E4 carries the row-list diff |
| E7 | AC-6 | default_mode absent from both config files; min_verify_ratio: 0.42 and its comment intact |
Git Bash | VERIFIED | §E5 — both file excerpts, before and after |
| E8 | AC-7 | config.md no longer routes review.default_mode; the min_verify_ratio row names the correct step |
Git Bash | N/A | TS Evidence field: N/A — cross-reference check. Resolution recorded in §E6 |
| E9 | AC-8 | No mode vocabulary in conventions.md / glossary.md; anti-pattern present |
Git Bash | N/A | TS Evidence field: N/A — text content. grep -rn "review mode" .tfw/ → 0, recorded in §E6 |
| E10 | AC-9 | Six adapter and entry-point copies carry no mode reference and match their sources | Git Bash | VERIFIED | §E6 — grep → 0 matches across all six; five diff runs, all empty |
| E11 | AC-10 | VERSION bumped; CHANGELOG ### Removed names the key |
Git Bash | N/A | TS Evidence field: N/A — changelog content. 1.1.0; key named at CHANGELOG L21 |
| E12 | AC-11 | TD-106 closed with the reason | Reading | N/A | TS Evidence field: N/A |
| E13 | AC-12 | The grep gate, run verbatim, with its output | Git Bash | VERIFIED | §E7 — zero matches, exit 1. Plus a supplementary sweep, because one quarter of the mandated pattern is dead |
| E14 | AC-12 | History intact: no existing task REVIEW file modified, no past CHANGELOG entry edited | Git Bash | VERIFIED | §E8 — 41 files under tasks/ still carry Review Mode; nothing under tasks/ in the diff except this task's own artifacts |
| E15 | AC-12 | Diffstat: 3 deletions, no framework file created | Git Bash | VERIFIED — with an anomaly that must be read | §E9 — the substance holds; the three deletions were swept into a concurrent session's commit, so they do not appear in this task's own diffstat |
| E16 | Build gate | Docs pipeline tests, since the changed files are Source Manifest rows | Python 3.13.5 | VERIFIED | §E10 — 68 passed |
Verdict¶
Evidence verdict: 9/16 VERIFIED, 0 DEFERRED, 0 BLOCKED, 7 N/A
The 7 N/A are the TS's own Evidence: fields, quoted verbatim above — not executor judgement.
E15 is VERIFIED on substance with a trace anomaly recorded in full; it is not marked N/A or
DEFERRED, because the fact being evidenced is true and checkable — it is the attribution of the
change that is wrong, and hiding that behind a softer status would be the failure this layer exists
to prevent.
E1 — The selection is absent (AC-1)¶
$ ls .tfw/workflows/review/
ls: cannot access '.tfw/workflows/review/': No such file or directory
$ grep -n "^## Step" .tfw/workflows/review.md
16:## Step 0: Name This Session
52:## Step 1: Map
60:## Step 2: Verify
78:## Step 3: Judge
89:## Step 4: Decide (Synthesize → REVIEW)
100:## Step 5: Tech Debt Collection
109:## Step 6: Update Traces
116:## Step 7: Knowledge Capture (KNW)
Contiguous 0-7, and Step 0 is Session Naming — the TFW-standard opening this file has never had
(knowledge/process.md F19, TD-106).
The only surviving occurrence of "mode" or "WAIT" in the whole file:
$ grep -ni "mode\|WAIT" .tfw/workflows/review.md
7:> **Role:** Reviewer (coordinator in review-locked mode)
"review-locked mode" is the Role Lock, not a genre. It is invisible to the AC-8 gate
(grep -rn "review mode") because the words are not adjacent, and it means one thing.
Internal step references, read end to end. Three references pointed at step numbers. All three were wrong before this task and are correct after it, with no edit:
| Reference | Says | Verify was | Verify is | Before | After |
|---|---|---|---|---|---|
review.md L143 anti-pattern |
"Step 2 (Verify)" | Step 3 | Step 2 | ❌ stale | ✅ |
conventions.md L495 anti-pattern |
"Step 2 (Verify)" | Step 3 | Step 2 | ❌ stale | ✅ |
config.md L92 propagation row |
"Step 2: Verify" | Step 3 | Step 2 | ❌ stale | ✅ |
One reference needed an actual edit, and it pointed at Judge rather than Verify:
| Reference | Was | Now | Why |
|---|---|---|---|
glossary.md Principles Check |
"review.md Step 4" |
"review.md Step 3" |
Judge moved 4 → 3 |
glossary.md L157 (Session Naming → review.md Step 0) needed nothing and becomes true for the
first time.
E2 — Ten universal rows (AC-2)¶
$ grep -c "^| [0-9]* |" .tfw/templates/review/judge.md
10
$ grep -c "Mode" .tfw/templates/review/judge.md
0
| # | Row | Rate carried in the row |
|---|---|---|
| 1 | DoD met? | — |
| 2 | Philosophy aligned — (a) mapping integrity · (b) design soundness | 4.5% on (b) |
| 3 | Tech debt documented | — |
| 4 | Style & standards | — |
| 5 | Observations collected | — |
| 6 | RF completeness (§7-9) | — |
| 7 | Evidence completeness — does the evidence exist? | — |
| 8 | Evidence sufficiency — does the evidence establish the claim? | 16.1% |
| 9 | Backward compatibility | 8.5% |
| 10 | Safety — kept on consequence, not on rate | 4.0% |
Order is HL §3.1's frozen after-diagram. Content quality is absent — the one true duplicate of row 4.
Explicit-N/A is structural, not advisory. Status vocabulary on every row is ✅/❌/⚪; the
section header states that ⚪ N/A requires a stated reason and that a row skipped as a bare ✅
leaves the stage incomplete; and the Checkpoint carries - [ ] Every ⚪ N/A carries a stated reason —
no row skipped as a bare ✅?. Three sites, so deleting any one leaves the rule visible.
E3 — The S1-vs-U7 dry-run (AC-2)¶
Subject: TFW-53 Phase A — RF · EV · REVIEW (✅ APPROVE, three passes,
Review Mode: spec).Chosen because it is this repository's most recent completed review, it has a real 15-row EV file with resolving attachments, and it was scored under an owner mode override — so it is the hardest available test of whether the new row adds anything the old checklist missed.
This is a dry-run of a checklist, not a re-review. I am TFW-56's executor, not TFW-53's reviewer. Nothing here revises TFW-53/A's APPROVE verdict, and a row-8 ❌ in a dry-run is not a claim that the verdict should have been REVISE — that verdict rested on the whole picture, and row 8 did not exist when it was made.
Row 7 — Evidence completeness. Does the evidence exist? → ✅
All 15 TS ACs appear in the EV table. Only the 4-status vocabulary is used (7 VERIFIED, 0 DEFERRED,
0 BLOCKED, 8 N/A). Both attachments resolve — baseline_recovery.txt and
classification_exercise.md are present in phase-a/evidence/. The 8 N/A quote the TS's own
Evidence: fields verbatim rather than asserting executor judgement. Same answer the archived
review reached on its row 7.
Row 8 — Evidence sufficiency. Does the evidence establish the claim? → ❌, three findings
| # | The green signal | What it does not establish |
|---|---|---|
| 1 | E2 marked VERIFIED, concluding "the amended template can carry HL-TFW-53's own §12 unchanged" | E2's own table records Type = RESTRICT as "not exercised by this corpus… recorded as a coverage gap". One of the shipped enum's values has zero live coverage. The exhibit establishes the narrow claim; the verdict line 7/15 VERIFIED reads as the broad one |
| 2 | E13 marked VERIFIED, shipping an anchored --grep recovery form |
Its conclusion was superseded inside the same pass by E15: "no --grep form can be subject-only". The measurements stand; the conclusion does not. A VERIFIED exhibit whose conclusion has been retracted is the exact shape row 8 exists to catch |
| 3 | E11 scored 4/4 — pass | The exhibit states the earlier budget and cut-order property is "absent from both the rule and this check" — removed by amendment A12 and deliberately not implemented. 4/4 is against a rule with a property removed, and the score does not carry that |
Result: rows 7 and 8 produced different answers, from different reasoning. AC-2 is met.
Two properties of this outcome matter more than the ❌ itself:
- Row 8's findings are not absences, so row 7 structurally cannot see them. Every one is a present, VERIFIED artifact whose stated scope is narrower than the claim it is offered for. Row 7 asks whether the row is filled; all three rows were filled, correctly, in the 4-status vocabulary.
- All three findings were written by TFW-53/A's own executor, inside the EV file, and none is
surfaced by its verdict line. That is the case for the row: the honesty was already in the trace,
and no checklist row was asking the question that would promote it into the verdict. Under the old
checklist this was reachable only through
specmode — and TFW-53/A was reviewed asspec, scored both mode rows ✅, and did not surface them.
E4 — REVIEW.md §3 against judge.md (AC-5)¶
Row lists compared in order. REVIEW.md §3 carries condensed labels by design — it is a synthesis
document, not a second copy of the stage file — so the check is one-for-one on identity and order:
| # | judge.md |
REVIEW.md §3 |
Match |
|---|---|---|---|
| 1 | DoD met? | DoD met? (all TS acceptance criteria) | ✅ |
| 2 | Philosophy aligned — mapping integrity + design soundness | Philosophy aligned — mapping integrity + design soundness | ✅ |
| 3 | Tech debt documented | Tech debt documented | ✅ |
| 4 | Style & standards | Style & standards | ✅ |
| 5 | Observations collected | Observations collected | ✅ |
| 6 | RF completeness (§7-9) | RF completeness (§7-9 present) | ✅ |
| 7 | Evidence completeness — does it exist? | Evidence completeness — does it exist? | ✅ |
| 8 | Evidence sufficiency — does it establish the claim? | Evidence sufficiency — does it establish the claim? | ✅ |
| 9 | Backward compatibility | Backward compatibility | ✅ |
| 10 | Safety | Safety | ✅ |
10/10, same order. The <!-- Add mode-specific checklist items from mode file below --> comment and
the > **Review Mode**: header field are both gone.
Repaired in passing: REVIEW.md §3 had 6 rows against judge.md's 7 — the Evidence
completeness row added in 0.8.8 never reached it. Closing that gap is required by AC-5 and is not
scope creep; it is recorded in RF §2 as a decision.
E5 — The config key, and its sibling (AC-6)¶
Before — .tfw/project_config.yaml:
review:
default_mode: code # code / docs / spec — determines review checklist
min_verify_ratio: 0.42 # minimum fraction of changed files to verify (escalate to 1.0 on discrepancy)
After — grep -n "review:" -A4 .tfw/project_config.yaml:
59: review:
60- min_verify_ratio: 0.42 # minimum fraction of changed files to verify (escalate to 1.0 on discrepancy)
After — grep -n "review:" -A4 .tfw/templates/project_config.yaml:
63: review: # ← FRAMEWORK: updated by tfw-update
64- min_verify_ratio: 0.42
min_verify_ratio keeps its value, its inline comment byte-for-byte, and its # ← FRAMEWORK
annotation in the template. Its behavioural home — review.md Step 2's parameter table with
Default 0.42 | Hard | min_verify_ratio and the ⌈5 × 0.42⌉ = 3 worked example — is unchanged. This
is the one place where collateral damage would have been silent, which is why AC-6 asked for both
excerpts rather than an assertion.
E6 — Propagation, vocabulary and adapter parity (AC-7, AC-8, AC-9)¶
$ grep -n "review\." .tfw/workflows/config.md
92:| `review.min_verify_ratio` | [`.tfw/workflows/review.md`](../../../reference/workflows/review.md) | Step 2: Verify | Min verify ratio |
One row, and its pointer resolves: review.md:60 is ## Step 2: Verify. The review.default_mode
row is gone with its key.
$ grep -rn "review mode" .tfw/ --exclude=CHANGELOG.md
(no matches — exit 1)
$ grep -rniE "review mode|review-mode|default_mode: code|code / docs / spec|mode-aware|mode file" \
.claude/commands/tfw-review.md .claude/commands/tfw-config.md \
.agent/workflows/tfw-review.md .agent/workflows/tfw-config.md \
.tfw/adapters/codex/skills/tfw-review/SKILL.md .agents/skills/tfw-review/SKILL.md
(no matches — exit 1)
Behavioural parity, five diff runs, all empty:
| Copy | Source | Result |
|---|---|---|
.claude/commands/tfw-review.md |
.tfw/workflows/review.md |
identical |
.agent/workflows/tfw-review.md |
.tfw/workflows/review.md |
identical |
.claude/commands/tfw-config.md |
.tfw/workflows/config.md |
identical |
.agent/workflows/tfw-config.md |
.tfw/workflows/config.md |
identical |
.agents/skills/tfw-review/SKILL.md |
.tfw/adapters/codex/skills/tfw-review/SKILL.md |
identical |
The four full copies were byte-identical to their sources before this task as well (checked at onboarding), so "nothing project-specific was clobbered" is established against a clean baseline rather than assumed. The Codex skill line "Follow the review-mode WAIT gate…" now reads "Follow every gate in the workflow exactly as it requires, including each stage self-check gate before advancing" — the four self-check gates are what actually remains to be followed.
map.md and verify.md carry no Mode: field:
$ grep -n "Mode" .tfw/templates/review/map.md .tfw/templates/review/verify.md
(no matches)
E7 — The grep gate, verbatim (AC-12)¶
$ grep -rn "code / docs / spec\|default_mode: code\|Review Mode\|review/{code" \
.tfw/ .claude/ .agent/ .agents/ --exclude=CHANGELOG.md
$ echo $?
1
Zero matches. Recorded with its exit status because a silent pass and an empty output look the same on the page.
A finding about the gate itself, not about the sweep. One of the four alternatives,
review/{code, matched nothing in this repository before any change was made — the real string
was always .tfw/workflows/review/{mode}.md. A quarter of the acceptance test could never fail,
which is precisely the anti-pattern this task adds to conventions.md §14. Two narrower holes: the
pattern is case-sensitive, so glossary.md's lowercase "coordinator in review mode" was invisible
to it, and config.md's review.default_mode registry row does not match default_mode: code.
AC-8 and AC-9 cover all three places by other means, so the ACs together are sound — the single
command is not. Supplementary sweep, wider and case-insensitive:
$ grep -rniE "review mode|review-mode|mode-aware|mode-specific|default_mode: code|review/\{(code|mode)|Mode: \{code" \
.tfw/ .claude/ .agent/ .agents/ --exclude=CHANGELOG.md
.tfw/workflows/research/base.md:79: Mode-specific: ☐ {from mode file}
.tfw/workflows/research/deep.md:21:Mode-specific:
.claude/commands/tfw-research.md:79: Mode-specific: ☐ {from mode file}
.agent/workflows/tfw-research.md:79: Mode-specific: ☐ {from mode file}
All four hits are the research mode axis (focused / deep), which is out of scope and
untouched. No review-mode residue at any case or spelling.
E8 — History is intact (AC-12)¶
$ grep -rl "Review Mode" tasks/ | wc -l
41
41 files under tasks/ still carry the string, including
tasks/TFW-53__hl_contract_and_goal_defence/phase-a/REVIEW__phase-a__contract_in_artifacts.md,
whose header still reads > **Review Mode**: spec with its owner-override note — the file used as
this task's own dry-run subject. Nothing under tasks/ appears in this task's diff except its own
artifacts (ONB, this EV file, RF). No past CHANGELOG entry was edited; ## [1.1.0] is inserted
above ## [1.0.0], and the ## [Unreleased] heading is left in place.
E9 — Diffstat, and a trace anomaly that has to be reported (AC-12)¶
The substance holds. Three files deleted, zero framework files created, net LOC negative. The only new file is this task's own evidence artifact, which is not a framework file.
The anomaly. The three deletions are not in this task's commit. A concurrent session working
on TFW-53 Phase B committed fbdf443 [claude-code/TFW-53/phase-b/executor] enforce the contract in the
workflows at 17:44, and that commit swept up my already-staged git rm of the mode files:
$ git show --stat fbdf443
.tfw/templates/RES.md | 2 +- ← TFW-53/B's own work
.tfw/workflows/plan.md | 82 +++--- ← TFW-53/B's own work
.tfw/workflows/research/base.md | 6 ++- ← TFW-53/B's own work
.tfw/workflows/review/code.md | 15 ------ ← [TFW-56](../HL-TFW-56__review_mode_removal.md)'s deliverable
.tfw/workflows/review/docs.md | 12 ------ ← [TFW-56](../HL-TFW-56__review_mode_removal.md)'s deliverable
.tfw/workflows/review/spec.md | 12 ------ ← [TFW-56](../HL-TFW-56__review_mode_removal.md)'s deliverable
Scope of the leak, bounded by timing: at 17:44 the only TFW-56 change staged in the index was that
git rm. Every other file in this task was still an unstaged working-tree edit and was not captured.
So the leak is exactly three deletions, and they are the three that were meant to be deleted.
Consequence, stated plainly. The outcome AC-1 and AC-12 require is real and verifiable — the
folder is gone from the working tree and from HEAD. What is wrong is the attribution: recovering
"when did TFW-56 delete the mode files" by reading TFW-56's commits will find nothing, and the
deletion is filed under a task whose own TS says review.md and its neighbourhood are "Phase C only".
No attempt was made to repair this by rewriting history — fbdf443 is another session's commit and
rewriting it is not an executor's call. It is recorded here, in RF §2 and in RF §6.
This task's own diffstat, staged by explicit path only — never git add -A, which is how the
leak became possible in the first place:
.agent/workflows/tfw-config.md | 1 -
.agent/workflows/tfw-review.md | 27 +++-------
.agents/skills/tfw-review/SKILL.md | 2 +-
.claude/commands/tfw-config.md | 1 -
.claude/commands/tfw-review.md | 27 +++-------
.tfw/CHANGELOG.md | 19 +++++++
.tfw/VERSION | 2 +-
.tfw/adapters/codex/skills/tfw-review/SKILL.md | 2 +-
.tfw/conventions.md | 1 +
.tfw/glossary.md | 6 ++--
.tfw/project_config.yaml | 3 +-
.tfw/templates/REVIEW.md | 21 +++++---
.tfw/templates/project_config.yaml | 1 -
.tfw/templates/review/judge.md | 35 ++++++++-----
.tfw/templates/review/map.md | 1 -
.tfw/templates/review/verify.md | 16 +++++-
.tfw/workflows/config.md | 1 -
.tfw/workflows/review.md | 27 +++-------
README.md | 2 +-
TECH_DEBT.md | 2 +-
20 files changed, 105 insertions(+), 94 deletions(-)
20 modified + 3 deleted (in fbdf443) = 23 framework and root files touched, one more than the
TS's 22 because .tfw/project_config.yaml carries two changes rather than one — the key removal and
the version field, which tracks VERSION on every release (RF §2). Against the project budget of 30
files / 15 new / 3000 LOC / 30 modified: within budget on every axis, net LOC −94 + 105 = +11 in
the modified set and −39 once the three deleted files are counted.
E10 — Build gate (Step 10)¶
$ python -m pytest docs/scripts/ -q
.................................................................... [100%]
68 passed in 33.47s
The docs pipeline is the consumer of every changed .tfw/ file — conventions.md, glossary.md,
workflows/** and templates/** are Source Manifest rows 4, 5, 12 and 13. Deleting three
workflows/** files removes three generated pages; the suite passes, and gen_docs.py carries no
reference to review modes (grep -rn "review" docs/scripts/*.py → no matches), confirming RES D9's
consumer audit against the shipped state rather than against the pre-change state.
Attachments¶
No binary artifacts. Every exhibit above is a command with its output, or a reading against a named file and line.
EV — TFW-56: Remove the Review Mode Axis | 2026-08-13