Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
177 commits
Select commit Hold shift + click to select a range
70696bd
chore(porch): 250 init spir
pseudoseed Aug 30, 2026
4783b99
chore(porch): 250 skip pre-approved plan
pseudoseed Aug 30, 2026
2882b2e
[Spec 250] Initial implementation plan
pseudoseed Aug 30, 2026
2ab7c89
chore(porch): 250 plan build-complete
pseudoseed Aug 30, 2026
da20333
[Spec 250] thread: plan-phase verification notes
pseudoseed Aug 30, 2026
985736c
[Spec 250] thread: opencode lane permission fix
pseudoseed Aug 30, 2026
6c1d5d8
[Spec 250] Plan with multi-agent review
pseudoseed Aug 30, 2026
8d25ac8
[Spec 250] Plan: ground the schema guard in upstream's own idiom
pseudoseed Aug 30, 2026
245296d
[Spec 250] Plan with codex review and architect ruling
pseudoseed Aug 30, 2026
abf5f3d
[Spec 250] Plan: move the browser harness out of the fork
pseudoseed Aug 30, 2026
987c5a4
[Spec 250] Plan: record the porch-level opencode lane case
pseudoseed Aug 30, 2026
841f26b
[Spec 250] Plan: correct the sidebar grouping relationship and pre-ch…
pseudoseed Aug 30, 2026
f5073c8
[Spec 250] thread: correct the opencode lane diagnosis
pseudoseed Aug 30, 2026
4ebfd09
[Spec 250] Plan: drop the stale connect-src claim from phase 10's obj…
pseudoseed Aug 30, 2026
46285ad
[Spec 250] Plan with opencode review
pseudoseed Aug 30, 2026
002023b
[Spec 250] Plan review round 1 rebuttals
pseudoseed Aug 30, 2026
5caca05
chore(porch): 250 plan-approval gate-requested
pseudoseed Aug 30, 2026
0851c4f
chore(porch): 250 plan-approval gate-request-updated
pseudoseed Aug 30, 2026
209562a
[Spec 250] thread: plan-approval gate reached
pseudoseed Aug 30, 2026
080f791
[Spec 250] Plan: private repo, never a GitHub fork
pseudoseed Aug 30, 2026
743fc7e
chore(porch): 250 plan-approval gate-approved
pseudoseed Aug 30, 2026
28dd339
chore(porch): 250 implement phase-transition
pseudoseed Aug 30, 2026
0cd37c4
[Spec 250] thread: record the per-phase visibility rule before contex…
pseudoseed Aug 30, 2026
c08e5d3
chore(porch): 250 acknowledge context refresh
pseudoseed Aug 30, 2026
82af955
[Spec 250][Phase: phase_1] feat: two-identity vendoring harness
pseudoseed Aug 30, 2026
49b0fb6
chore(porch): 250 implement build-complete
pseudoseed Aug 30, 2026
ea82d21
[Spec 250][Phase: phase_1] docs: name the one deliberate identity exc…
pseudoseed Aug 30, 2026
f055369
[Spec 250][Phase: phase_1] fix: per-identity verify verbs, and a swal…
pseudoseed Aug 30, 2026
beb7fb4
chore(porch): 250 implement re-iter (iter 2)
pseudoseed Aug 30, 2026
417721d
chore(porch): 250 implement build-complete
pseudoseed Aug 30, 2026
f2aebb6
[Spec 250][Phase: phase_1] fix: guard the ref --since actually names
pseudoseed Aug 30, 2026
9ef53fb
chore(porch): 250 advance plan phase → phase_2
pseudoseed Aug 30, 2026
7bae1cc
[Spec 250][Phase: phase_1] feat: ahead of the contract is not the wro…
pseudoseed Aug 30, 2026
b8f8c1a
chore(porch): 250 acknowledge context refresh
pseudoseed Aug 30, 2026
19341a6
[Spec 250][Phase: phase_2] feat: fork hierarchy commit, and two bugs …
pseudoseed Aug 30, 2026
0349e28
chore(porch): 250 implement build-complete
pseudoseed Aug 30, 2026
6005a9c
[Spec 250][Phase: phase_2] docs: review, lesson, and phase 5's named …
pseudoseed Aug 30, 2026
505f657
[Spec 250][Phase: phase_2] test: exercise criterion 8b instead of arg…
pseudoseed Aug 30, 2026
543352e
[Spec 250][Phase: phase_2] docs: rebuttals, and why start --keep-data…
pseudoseed Aug 30, 2026
22cd0fd
chore(porch): 250 implement re-iter (iter 2)
pseudoseed Aug 30, 2026
6ed7752
chore(porch): 250 implement build-complete
pseudoseed Aug 30, 2026
fb897de
[Spec 250][Phase: phase_2] test: name the fork commit the 8b evidence…
pseudoseed Aug 30, 2026
57a05a1
chore(porch): 250 advance plan phase → phase_3
pseudoseed Aug 30, 2026
d063aae
chore(porch): 250 acknowledge context refresh
pseudoseed Aug 30, 2026
ffdf47d
[Spec 250][Phase: phase_3] fix: a crashed 8b run must not destroy pas…
pseudoseed Aug 30, 2026
f6f6581
chore(porch): 250 implement build-complete
pseudoseed Aug 30, 2026
be41c10
[Spec 250][Phase: phase_3] docs: rebuttals and the engine-collapse fi…
pseudoseed Aug 30, 2026
33bb421
[Spec 250][Phase: phase_3] chore: log the engine-fix commit, refresh …
pseudoseed Aug 30, 2026
2dad99c
[Spec 250] docs: promote "a test that cannot fail is not a test" to t…
pseudoseed Aug 30, 2026
5be4a5e
chore(porch): 250 implement re-iter (iter 2)
pseudoseed Aug 30, 2026
837bfe6
chore(porch): 250 implement build-complete
pseudoseed Aug 30, 2026
cfad6da
[Spec 250] docs: keep the stuck-trigger always-on, folded into slot 1
pseudoseed Aug 30, 2026
71e5a7d
[Spec 250][Phase: phase_3] docs: make the ws/RPC hop a phase 6 accept…
pseudoseed Aug 30, 2026
22c5260
chore(porch): 250 advance plan phase → phase_4
pseudoseed Aug 30, 2026
1b1ff58
chore(porch): 250 acknowledge context refresh
pseudoseed Aug 30, 2026
6a88f87
[Spec 250][Phase: phase_4] fix: derive the 8b column set instead of h…
pseudoseed Aug 31, 2026
d91f445
chore(porch): 250 implement build-complete
pseudoseed Aug 31, 2026
56c95e8
[Spec 250][Phase: phase_4] docs: rebuttals, and the third occurrence …
pseudoseed Aug 31, 2026
e226d4b
[Spec 250][Phase: phase_4] docs: correct a workaround I got wrong
pseudoseed Aug 31, 2026
3b566c9
[Spec 250][Phase: phase_4] docs: the four costumes, as one list for p…
pseudoseed Aug 31, 2026
85fa148
[Spec 250][Phase: phase_4] chore: refresh 8b evidence for the exhaust…
pseudoseed Aug 31, 2026
c825852
chore(porch): 250 implement re-iter (iter 2)
pseudoseed Aug 31, 2026
3cc8b78
chore(porch): 250 implement build-complete
pseudoseed Aug 31, 2026
6b8b301
[Spec 250][Phase: phase_4] docs: widen slot 8 to the rule the four co…
pseudoseed Aug 31, 2026
cc35433
[Spec 250][Phase: phase_4] docs: costume five, one commit after the t…
pseudoseed Aug 31, 2026
23542cf
[Spec 250][Phase: phase_4] chore: refresh 8b evidence for the provisi…
pseudoseed Aug 31, 2026
5b35d3d
[Spec 250][Phase: phase_4] docs: promote the antidote above the five …
pseudoseed Aug 31, 2026
049638a
chore(porch): 250 implement re-iter (iter 3)
pseudoseed Aug 31, 2026
b7a334e
[Spec 250][Phase: phase_4] docs: amend the plan so it agrees with the…
pseudoseed Aug 31, 2026
1dbbf0d
chore(porch): 250 implement build-complete
pseudoseed Aug 31, 2026
9f866df
chore(porch): 250 advance plan phase → phase_5
pseudoseed Aug 31, 2026
3e0ee68
[Spec 250][Phase: phase_4] docs: iteration 3 reviews, both lanes APPROVE
pseudoseed Aug 31, 2026
80a87dc
[Spec 250][Phase: phase_4] docs: thread log for iteration 3
pseudoseed Aug 31, 2026
4b4008e
chore(porch): 250 acknowledge context refresh
pseudoseed Aug 31, 2026
9ce83d4
[Spec 250][Phase: phase_5] feat: regenerate the vendored contract fro…
pseudoseed Aug 31, 2026
f7c1515
[Spec 250][Phase: phase_5] fix: shapeCheck threw on the payload it wa…
pseudoseed Aug 31, 2026
76ff7b5
[Spec 250][Phase: phase_5] fix: the evidence collectors recorded a fo…
pseudoseed Aug 31, 2026
4146e4d
[Spec 250][Phase: phase_5] test: the decided union verdict, the flip,…
pseudoseed Aug 31, 2026
8394d97
[Spec 250][Phase: phase_5] docs: phase 5 review, plan amendment, thre…
pseudoseed Aug 31, 2026
6b5a606
chore(porch): 250 implement build-complete
pseudoseed Aug 31, 2026
44989ad
[Spec 250][Phase: phase_5] fix: the shipped module attributed a fork …
pseudoseed Aug 31, 2026
d53ca56
[Spec 250][Phase: phase_5] docs: iteration 1 rebuttals and review
pseudoseed Aug 31, 2026
ff18fd8
chore(porch): 250 implement re-iter (iter 2)
pseudoseed Aug 31, 2026
8d1289a
chore(porch): 250 implement build-complete
pseudoseed Aug 31, 2026
1a69f7b
[Spec 250][Phase: phase_5] test: drop the extension filter, both lane…
pseudoseed Aug 31, 2026
3e4d2c6
chore(porch): 250 advance plan phase → phase_6
pseudoseed Aug 31, 2026
eba5f59
chore(porch): 250 acknowledge context refresh
pseudoseed Aug 31, 2026
9ff5c9b
[Spec 250][Phase: phase_6] feat: porch-driver names the role and the …
pseudoseed Aug 31, 2026
f1fd980
[Spec 250][Phase: phase_6] feat: resolve the spawning architect as th…
pseudoseed Aug 31, 2026
f80da1b
[Spec 250][Phase: phase_6] feat: publish porch gate state onto the th…
pseudoseed Aug 31, 2026
abbedee
[Spec 250][Phase: phase_6] test: the refusal discriminant, over a rea…
pseudoseed Aug 31, 2026
aa2d82a
[Spec 250][Phase: phase_6] chore: regenerate the contract from the fo…
pseudoseed Aug 31, 2026
7ef165e
[Spec 250][Phase: phase_6] docs: phase 6 review and thread log
pseudoseed Aug 31, 2026
53279e8
chore(porch): 250 implement build-complete
pseudoseed Aug 31, 2026
25f46ef
[Spec 250][Phase: phase_6] fix: a reconnect leaked the gate watch it …
pseudoseed Aug 31, 2026
18d48eb
chore(porch): 250 implement re-iter (iter 2)
pseudoseed Aug 31, 2026
9e94e7b
[Spec 250][Phase: phase_6] test: hash the wire evidence's sources ins…
pseudoseed Aug 31, 2026
7f61768
chore(porch): 250 implement build-complete
pseudoseed Aug 31, 2026
350bd61
chore(porch): 250 advance plan phase → phase_7
pseudoseed Aug 31, 2026
86561e6
chore(porch): 250 acknowledge context refresh
pseudoseed Aug 31, 2026
28140ca
[Spec 250][Phase: phase_7] test: drive the fork's real sidebar in a b…
pseudoseed Aug 31, 2026
531181b
chore(porch): 250 implement build-complete
pseudoseed Aug 31, 2026
8de01c4
[Spec 250][Phase: phase_7] fix: act on the 3-way review — both lanes …
pseudoseed Aug 31, 2026
e787d6b
chore(porch): 250 advance plan phase → phase_8
pseudoseed Aug 31, 2026
924efa7
[Spec 250][Phase: phase_7] docs: record the appearance approval and t…
pseudoseed Aug 31, 2026
0475e81
chore(porch): 250 acknowledge context refresh
pseudoseed Aug 31, 2026
0b5031a
[Spec 250][Phase: phase_8] test: drive the gate through the credentia…
pseudoseed Aug 31, 2026
5483c4b
chore(porch): 250 implement build-complete
pseudoseed Aug 31, 2026
b77fa03
[Spec 250][Phase: phase_8] chore: stop exporting screenshots as base6…
pseudoseed Aug 31, 2026
692f3f5
chore(porch): 250 advance plan phase → phase_9
pseudoseed Aug 31, 2026
0333ad0
chore(porch): 250 acknowledge context refresh
pseudoseed Aug 31, 2026
4be6072
[Spec 250][Phase: phase_9] test: measure the tiling in a browser, and…
pseudoseed Aug 31, 2026
c0b3659
chore(porch): 250 implement build-complete
pseudoseed Aug 31, 2026
3302bc2
[Spec 250][Phase: phase_9] test: reach the grid the way a user reache…
pseudoseed Aug 31, 2026
aece38c
chore(porch): 250 advance plan phase → phase_10
pseudoseed Aug 31, 2026
e945483
chore(porch): 250 acknowledge context refresh
pseudoseed Aug 31, 2026
012b871
[Spec 250][Phase: phase_10] test: drive the real proxy, and watch wha…
Aug 31, 2026
dcce077
chore(porch): 250 implement build-complete
pseudoseed Aug 31, 2026
7b9acc9
[Spec 250][Phase: phase_10] docs: the phase 10 review, and the rebase…
Aug 31, 2026
4b1ed3f
[Spec 250][Phase: phase_10] test: the proxy's body bound, asserted at…
Aug 31, 2026
d3f031a
[Spec 250][Phase: phase_10] fix: act on the 3-way review — a test tha…
Aug 31, 2026
cd00d5b
chore(porch): 250 implement re-iter (iter 2)
pseudoseed Aug 31, 2026
a3c6ac5
[Spec 250][Phase: phase_10] docs: the review outcome in the builder t…
Aug 31, 2026
6b685e9
[Spec 250][Phase: phase_10] docs: the phase 11 rulings, and the iPad …
Aug 31, 2026
059ca41
chore(porch): 250 implement build-complete
pseudoseed Aug 31, 2026
1fc70a4
[Spec 250][Phase: phase_10] fix: the runbook named two variables that…
Aug 31, 2026
8d26d21
[Spec 250][Phase: phase_10] docs: the runbook's tokens expire in 10 m…
Aug 31, 2026
7a44d26
[Spec 250][Phase: phase_10] fix: the runbook sent the human to the te…
Aug 31, 2026
e6e50a6
[Spec 250][Phase: phase_10] docs: every deliverable mapped to the tes…
Aug 31, 2026
4407754
[Spec 250][Phase: phase_10] docs: the runbook made the human transcri…
Aug 31, 2026
ecf5d39
[Spec 250][Phase: phase_10] docs: the runbook's step numbers pointed …
Aug 31, 2026
9764e17
[Spec 250][Phase: phase_10] fix: the same-origin assertion was a pref…
Aug 31, 2026
78123af
chore(porch): 250 advance plan phase → phase_11
pseudoseed Aug 31, 2026
01a9054
[Spec 250][Phase: phase_10] docs: phase 10 closed, and the two review…
Aug 31, 2026
becc626
chore(porch): 250 acknowledge context refresh
pseudoseed Aug 31, 2026
04e5074
[Spec 250][Phase: phase_11] feat: the rebase drill, as a procedure th…
Aug 31, 2026
8a67894
[Spec 250][Phase: phase_11] fix: the frozen fallback's suite went red…
Aug 31, 2026
bb9bedf
[Spec 250][Phase: phase_11] fix: a timeout that was a wrong budget, n…
Aug 31, 2026
c22fdc2
[Spec 250][Phase: phase_11] docs: the regression numbers, with the re…
Aug 31, 2026
6380dd4
[Spec 250][Phase: phase_11] feat: the acceptance evidence's numbers c…
Aug 31, 2026
d7c3e4d
[Spec 250][Phase: phase_11] docs: phase 11 in the builder thread
Aug 31, 2026
e851894
[Spec 250][Phase: phase_11] docs: phase 11 adds no fork commit, and t…
Aug 31, 2026
36e1624
chore(porch): 250 implement build-complete
pseudoseed Aug 31, 2026
1e5b8bb
[Spec 250][Phase: phase_11] fix: the zero-movement path dropped the w…
Aug 31, 2026
ebc3d57
[Spec 250][Phase: phase_11] docs: the phase 10 iteration 2 consult co…
pseudoseed Aug 31, 2026
e50b8fe
chore(porch): 250 implement re-iter (iter 2)
pseudoseed Aug 31, 2026
00524fa
[Spec 250][Phase: phase_11] fix: the drill's `ok` claimed a shape-che…
pseudoseed Aug 31, 2026
059753f
[Spec 250][Phase: phase_11] docs: the shape-check row described the p…
pseudoseed Aug 31, 2026
3edd244
[Spec 250][Phase: phase_11] docs: iteration 1 rebuttals, and the e2e …
pseudoseed Aug 31, 2026
049e497
[Spec 250][Phase: phase_11] fix: a merge that never ran walks into th…
pseudoseed Aug 31, 2026
8a27ffa
[Spec 250][Phase: phase_11] docs: what iteration 2 taught, in the review
pseudoseed Aug 31, 2026
cc223f1
[Spec 250][Phase: phase_11] docs: criterion 9's status now says which…
pseudoseed Aug 31, 2026
4b0c6d8
chore(porch): 250 implement build-complete
pseudoseed Aug 31, 2026
fbcb235
[Spec 250][Phase: phase_11] docs: iteration 2 consult context
pseudoseed Aug 31, 2026
e4286d1
[Spec 250][Phase: phase_11] test: the guard nothing could reach now l…
pseudoseed Aug 31, 2026
28e18b2
[Spec 250][Phase: phase_11] docs: the context now describes the extra…
pseudoseed Aug 31, 2026
2892576
[Spec 250][Phase: phase_11] fix: my own tests would have failed a cor…
pseudoseed Aug 31, 2026
c643627
[Spec 250][Phase: phase_11] docs: iteration 2 rebuttals
pseudoseed Aug 31, 2026
32ca31c
[Spec 250][Phase: phase_11] docs: iteration 2 in the builder thread
pseudoseed Aug 31, 2026
67888a9
chore(porch): 250 all plan phases complete → review
pseudoseed Aug 31, 2026
4178aa4
[Spec 250][Phase: phase_11] feat: the contract is regenerated after t…
pseudoseed Aug 31, 2026
9fbf7a1
[Spec 250][Phase: phase_11] docs: the regeneration proof, in the revi…
pseudoseed Aug 31, 2026
d56affe
[Spec 250][Phase: phase_11] docs: the regression row carries the run …
pseudoseed Aug 31, 2026
d2bff28
chore(porch): 250 record PR #266
pseudoseed Aug 31, 2026
564c185
chore(porch): 250 acknowledge context refresh
pseudoseed Aug 31, 2026
5df1487
[Spec 250][Phase: review] docs: the retrospective the incremental log…
pseudoseed Aug 31, 2026
5491afb
chore(porch): 250 review build-complete
pseudoseed Aug 31, 2026
173bc23
[Spec 250][Phase: review] docs: three counts corrected, and where the…
pseudoseed Aug 31, 2026
99c4690
[Spec 250][Phase: review] fix: the collector test stops writing to th…
pseudoseed Aug 31, 2026
6e0a494
[Spec 250][Phase: review] docs: which repository each cited path is i…
pseudoseed Aug 31, 2026
d8f25e4
[Spec 250][Phase: review] docs: stop stating a branch count that ever…
pseudoseed Aug 31, 2026
8be5ea2
[Spec 250][Phase: review] docs: the one red test was my own concurren…
pseudoseed Aug 31, 2026
bb0ed66
chore(porch): 250 pr gate-requested
pseudoseed Aug 31, 2026
da2e89e
chore(porch): 250 pr gate-request-updated
pseudoseed Aug 31, 2026
f442cc0
[Spec 250][Phase: review] fix: the approval path answers a dead netwo…
pseudoseed Aug 31, 2026
8892aa2
[Spec 250][Phase: review] docs: the e2e re-run at the pin it now desc…
pseudoseed Aug 31, 2026
c224c6e
chore(porch): 250 pr gate-approved
pseudoseed Aug 31, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion apps/client/__tests__/derive.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,27 @@ describe('deriveRowStatus', () => {
),
) as { $defs: Record<string, { properties?: { status?: { enum?: string[] } } }> };

const session = schema.$defs.subscribeThreadOutput__Objects_6;
/*
* `_7`, not `_6`, and the number is generated rather than chosen.
*
* Spec 250 phase 5 regenerated the vendored contract FROM THE FORK, and the
* fork's `codevGate` object lands ahead of the session object in the
* generator's numbering — so the enum this test reads moved one along. The
* mapping below is unaffected; only the path was stale.
*
* The assertion message under this is what made that diagnosable, and it is
* why the message says what it says: "this test needing a new path, not a
* mapping change" is the difference between a one-character fix and an hour
* spent looking at `deriveRowStatus`.
*
* A positional key like this WILL move again whenever the contract is
* regenerated after a change ahead of it. That is the cost of reading a
* generated artifact positionally, and it is accepted here rather than
* hidden: the alternative — searching every `$def` for one carrying a status
* enum — would silently find a DIFFERENT object if the session one ever lost
* its enum, which is the failure this test exists to catch.
*/
const session = schema.$defs.subscribeThreadOutput__Objects_7;
const declared = session?.properties?.status?.enum;
expect(
declared,
Expand Down
2 changes: 2 additions & 0 deletions codev-skeleton/resources/lessons-critical.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ STARTER: a few universal lessons are seeded; add your project's as you learn the
- Check for existing work (PRs, git history) before building from scratch.
- "It compiled" / "tests pass" is not "it works" — verify the real user path before calling it done.
- When stuck (2 failed hypotheses or ~30 min), get an outside perspective instead of guessing.
- A test that cannot fail is not a test — revert the fix and confirm the test fails before trusting it.
- A test that supplies the boundary itself cannot tell you the boundary exists — test the seam, not the two ends.
- <Add your project's hard-won, cross-cutting lessons; keep <=10, one line each.>

## Map of lessons-learned.md (consult when…)
Expand Down
1,409 changes: 1,409 additions & 0 deletions codev/plans/250-t3code-front-end-customization.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# Spec 250, phase_1, iteration 1 — review responses

Two lanes: **claude** (APPROVE) and **opencode / grok-4.6** (REQUEST_CHANGES).

The opencode lane timed out at 360s on its first attempt and produced no verdict. `consult` has
no timeout flag — `OPENCODE_TIMEOUT_MS` is a hard-coded 6 minutes in
`packages/codev/src/commands/consult/index.ts:1561` — so the run was retried and completed. The
first failure was loud and exited 1, which is the lane behaving correctly; it is recorded here
rather than left as an unexplained gap.

---

## opencode #1 — `ready()` still runs full `verify()` — ACCEPTED

> `start()` only calls `verifyUpstream()` so a spec 146 run does not need the fork. `ready()`
> then calls `verify('CHECKOUT_MOVED_DURING_RUN')`, which requires fork HEAD == `pin.commit`.

Correct, and it made `start()`'s upstream-only exemption buy nothing: `smoke.mjs` calls
`acquire`, `verify`, `start`, `ready` in sequence, so the fork requirement came back one call
later. `packages/t3-client/live/integration.mjs:202` had the same shape.

The consequence is not hypothetical. Phases 2 through 4 commit to the fork while `pin.commit`
stays at `upstreamBase` until phase 5. On the first fork commit, a correct upstream server would
have failed `ready` with `CHECKOUT_MOVED_DURING_RUN` — a signal about the checkout the *server*
runs from, reported for a checkout the server never touches.

**Fixed.** `ready()` now calls `verifyUpstream('CHECKOUT_MOVED_DURING_RUN')`. Two new subcommands,
`verify-upstream` and `verify-fork`, assert one identity each; `smoke.mjs` and
`live/integration.mjs` use `verify-upstream`. Bare `verify` still asserts both, which is what the
phase's acceptance criterion requires.

Four tests: `verify-upstream` passes with no fork checkout at all, `verify-fork` passes with no
upstream root, bare `verify` still stops at `3` on a missing fork, and the three callers are
asserted to use the upstream-only verb.

The cold-start evidence was re-collected after the `smoke.mjs` change.

## opencode #2 — `verifyCheckout` treats a failed `git status` as clean — ACCEPTED

> The catch comment says undetermined; the code returns success. Same "could not tell" as pass.

Correct. The catch fell through to `dirty = ''`, and an empty string is how "clean" is spelled.
The comment claiming otherwise was inherited from the spec 146 version, which had the same bug —
the reviewer found it in the new file, and it was there before.

**Fixed.** The catch now `die(UNDETERMINED, 'NO_<IDENTITY>_STATUS: could not check: ...')`.

The test triggers it for real rather than asserting on source: `chmod 000` on `.git/index` leaves
`rev-parse HEAD` working (it reads only the ref) and makes `git status` exit 128, which lands the
failure exactly between the two checks. The test refuses to pass vacuously — if the platform
ignores the mode, it fails with a message saying so rather than skipping quietly.

## claude #1 — `FORK.md` overstates "nothing re-derives it" — ACCEPTED

`packages/t3-client/live/integration.mjs` deliberately reads `process.env.T3CODE_ROOT` directly
and keeps it **required** (#214). The sentence was stronger than the code.

**Fixed.** `FORK.md` names the exception and why it is one.

## claude #2 — test heading says "the seventh readers" over six — ACCEPTED

**Fixed.** Renamed to "the root readers".

## claude — items it could not verify from its session

The lane had no shell. All three are now checked:

| Claim | Result |
|---|---|
| `pnpm -w test` | 7263 passed, 54 skipped, 0 failed, with both live suites executing |
| `gh repo view pseudoseed/t3code` | `visibility: PRIVATE`, `isFork: false`, default branch `codev` |
| MIT `LICENSE` unmodified in the fork | `diff` against the upstream clone reports identical |

## Not changed

**When `pin.commit` moves to the fork head.** Both lanes brushed against it; neither asked for a
change. The plan puts it at phase 5, so phases 2 through 4 will run with a fork checkout ahead of
`pin.commit` and bare `verify` will report `FORK_CHECKOUT_MISMATCH` in that window. That is the
plan's sequencing, not a phase 1 defect, and the per-identity verbs above mean it no longer blocks
an upstream server. Flagged to the architect rather than resolved here.

---

# Iteration 2 review responses

Both lanes APPROVE. claude raised two non-blocking notes; opencode raised none.

## claude — `--since` bypassed the ref-resolution guard — ACCEPTED

The guard ran over `range.from` before `--since` replaced it, so an unresolvable `--since` ref
slipped past and surfaced as a raw git error: exit 1 doing exit 3's job.

**Fixed.** The guard now runs after `from` is computed, over the refs actually used. Tested with a
throwaway checkout and a `--since` naming a sha that does not exist.

## claude — no direct test for the `NO_UPSTREAM_MOVEMENT` named zero — ACCEPTED

Its `NO_FORK_DRIFT` twin was tested; the upstream one was not, because upstream has genuinely
moved on this machine (3 closure commits between `upstreamBase` and `origin/main`), so the real
pair cannot produce the zero.

**Fixed.** The test builds a throwaway checkout whose `refs/remotes/origin/main` sits exactly where
the range starts. A real empty range, not a mocked one.

## claude — items it could not verify without a shell

`gh repo view pseudoseed/t3code --json visibility,isFork,nameWithOwner,defaultBranchRef` returns
`{"defaultBranchRef":{"name":"codev"},"isFork":false,"nameWithOwner":"pseudoseed/t3code","visibility":"PRIVATE"}`.
`pnpm -w test`: 7263 passed, 54 skipped, 0 failed, plus 180 in the v2 suite. Both re-run after
these two fixes.
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
### Iteration 1 Reviews
- claude: APPROVE — Phase 1 two-identity harness is complete and correct; the destructive acquire path, merge-base check, and three-code exit semantics are all implemented and tested.
- opencode: REQUEST_CHANGES — ready/smoke/integration still run both-identity verify, so an upstream server start dies once the fork HEAD leaves pin.commit.

### Builder Response to Iteration 1
# Spec 250, phase_1, iteration 1 — review responses

Two lanes: **claude** (APPROVE) and **opencode / grok-4.6** (REQUEST_CHANGES).

The opencode lane timed out at 360s on its first attempt and produced no verdict. `consult` has
no timeout flag — `OPENCODE_TIMEOUT_MS` is a hard-coded 6 minutes in
`packages/codev/src/commands/consult/index.ts:1561` — so the run was retried and completed. The
first failure was loud and exited 1, which is the lane behaving correctly; it is recorded here
rather than left as an unexplained gap.

---

## opencode #1 — `ready()` still runs full `verify()` — ACCEPTED

> `start()` only calls `verifyUpstream()` so a spec 146 run does not need the fork. `ready()`
> then calls `verify('CHECKOUT_MOVED_DURING_RUN')`, which requires fork HEAD == `pin.commit`.

Correct, and it made `start()`'s upstream-only exemption buy nothing: `smoke.mjs` calls
`acquire`, `verify`, `start`, `ready` in sequence, so the fork requirement came back one call
later. `packages/t3-client/live/integration.mjs:202` had the same shape.

The consequence is not hypothetical. Phases 2 through 4 commit to the fork while `pin.commit`
stays at `upstreamBase` until phase 5. On the first fork commit, a correct upstream server would
have failed `ready` with `CHECKOUT_MOVED_DURING_RUN` — a signal about the checkout the *server*
runs from, reported for a checkout the server never touches.

**Fixed.** `ready()` now calls `verifyUpstream('CHECKOUT_MOVED_DURING_RUN')`. Two new subcommands,
`verify-upstream` and `verify-fork`, assert one identity each; `smoke.mjs` and
`live/integration.mjs` use `verify-upstream`. Bare `verify` still asserts both, which is what the
phase's acceptance criterion requires.

Four tests: `verify-upstream` passes with no fork checkout at all, `verify-fork` passes with no
upstream root, bare `verify` still stops at `3` on a missing fork, and the three callers are
asserted to use the upstream-only verb.

The cold-start evidence was re-collected after the `smoke.mjs` change.

## opencode #2 — `verifyCheckout` treats a failed `git status` as clean — ACCEPTED

> The catch comment says undetermined; the code returns success. Same "could not tell" as pass.

Correct. The catch fell through to `dirty = ''`, and an empty string is how "clean" is spelled.
The comment claiming otherwise was inherited from the spec 146 version, which had the same bug —
the reviewer found it in the new file, and it was there before.

**Fixed.** The catch now `die(UNDETERMINED, 'NO_<IDENTITY>_STATUS: could not check: ...')`.

The test triggers it for real rather than asserting on source: `chmod 000` on `.git/index` leaves
`rev-parse HEAD` working (it reads only the ref) and makes `git status` exit 128, which lands the
failure exactly between the two checks. The test refuses to pass vacuously — if the platform
ignores the mode, it fails with a message saying so rather than skipping quietly.

## claude #1 — `FORK.md` overstates "nothing re-derives it" — ACCEPTED

`packages/t3-client/live/integration.mjs` deliberately reads `process.env.T3CODE_ROOT` directly
and keeps it **required** (#214). The sentence was stronger than the code.

**Fixed.** `FORK.md` names the exception and why it is one.

## claude #2 — test heading says "the seventh readers" over six — ACCEPTED

**Fixed.** Renamed to "the root readers".

## claude — items it could not verify from its session

The lane had no shell. All three are now checked:

| Claim | Result |
|---|---|
| `pnpm -w test` | 7263 passed, 54 skipped, 0 failed, with both live suites executing |
| `gh repo view pseudoseed/t3code` | `visibility: PRIVATE`, `isFork: false`, default branch `codev` |
| MIT `LICENSE` unmodified in the fork | `diff` against the upstream clone reports identical |

## Not changed

**When `pin.commit` moves to the fork head.** Both lanes brushed against it; neither asked for a
change. The plan puts it at phase 5, so phases 2 through 4 will run with a fork checkout ahead of
`pin.commit` and bare `verify` will report `FORK_CHECKOUT_MISMATCH` in that window. That is the
plan's sequencing, not a phase 1 defect, and the per-identity verbs above mean it no longer blocks
an upstream server. Flagged to the architect rather than resolved here.


### IMPORTANT: Stateful Review Context
This is NOT the first review iteration. Previous reviewers raised concerns and the builder has responded.
Before re-raising a previous concern:
1. Check if the builder has already addressed it in code
2. If the builder disputes a concern with evidence, verify the claim against actual project files before insisting
3. Do not re-raise concerns that have been explained as false positives with valid justification
4. Check package.json and config files for version numbers before flagging missing configuration
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# Phase 10 — 3-way review, iteration 1

Two lanes. **Claude APPROVE / HIGH** (after a second pass that closed its own stated
coverage gap). **opencode REQUEST_CHANGES / HIGH.** The stricter lane is binding, and it
found the one defect that mattered.

Every finding was accepted. Nothing is in a disagree column.

---

## 1. The vitest e2e reported a PASS on a run that never happened — opencode, blocking

> `spec-250-t3code-approval.e2e.test.ts` returns from `it()` when the fork is unavailable, so
> criterion 4 / SSRF at the wired handler go green without running. The file's own header says
> "skips, never passes".

**Accepted, and it is the worst defect in the phase.** The guard was:

```ts
function skipIfUnavailable(): boolean {
if (unavailable === null) return false;
console.warn(`SKIP spec-250 t3code approval: ${unavailable}`);
return true; // <- vitest records this as a PASS
}
```

So a run where the fork server never started reported **8 passed** with not one assertion
executed — on the phase's own acceptance criterion. That is this project's recurring defect
inverted: not "I could not tell" spelled as "no", but spelled as **"yes"**, which is strictly
worse. The file's header had the rule written in it and the code broke it; a header is not a
mechanism.

Worse, it was invisible in every run I did, because the fork was always up. It would have
surfaced the first time someone ran the suite without `T3_NODE` — and it would have surfaced
as a green tick.

**Fixed** with `ctx.skip(...)`, which marks the test skipped and does not return, so the body
is unreachable rather than merely unexecuted. The Playwright spec beside it already did this
with `test.skip`; the two now agree.

**Demonstrated, not asserted.** Same file, same command, `T3_NODE` unset:

```
before: Tests 8 passed (8)
after: Tests 8 skipped (8)
```

and with the fork available, `Tests 8 passed (8)`.

## 2. `UPSTREAM_TIMEOUT_MS` claimed more than the mechanism gives — Claude, non-blocking

> applied via `upstream.setTimeout`, a Node idle-socket timeout, while the comment describes it
> as bounding "the whole exchange".

**Accepted.** `ClientRequest.setTimeout` restarts its clock on socket activity, so it bounds
SILENCE, not elapsed time. The comment said otherwise, and overstating a bound is the same class
of error as the `connect-src 'self'` claim this phase existed to correct — it reads as protection
that is not there.

The comment now says what the mechanism gives and states the residual explicitly: a trickling
upstream is not bounded by it. That upstream is one the operator named in
`T3CODE_CODEV_AGENT_ORIGINS`, so it is not a stranger, and a total-duration bound would have to
be large enough for the slowest legitimate answer — a worse trade for a threat the allowlist
already narrows to the operator's own hosts. Recorded rather than quietly accepted.

## 3. `data-codev-approval-state` was coarser than its own words — both lanes

> a session-ended outcome tags as `refused` in the machine-readable attribute while the visible
> text and testid distinguish it correctly.

**Accepted**, and both lanes finding it independently is the signal. The attribute computed three
values over four outcomes. Nothing asserts on it today, which is exactly why it was worth fixing
now rather than later: **the first test written against it would have inherited the conflation
the file's own header exists to prevent** — "the session idled out" spelled the same as "your
approval was refused", one layer below where a human reads it.

Four outcomes, four words, in an exported pure function (`approvalStateAttribute`) so the
attribute and the rendering cannot drift. Three tests, including one that pins the precedence
when an outcome carries both flags. Removing the `session-ended` branch fails two of them.

## 4. Claude's own coverage gap, stated and then closed

Claude's first pass said plainly which files it had not read — `agentState.ts`,
`useCodevAgent.ts`, `GateApproval.tsx`, `PairingPanel.tsx`, patches 0029-0031, the harness — and
rested its verdict on what it had read in full. Its second pass read them and raised confidence
from MEDIUM to HIGH.

Worth recording because the honest declaration is what made the second pass targeted. A lane that
had said nothing would have produced the same verdict with no way to tell what it covered.

## 5. A finding of my own, confirmed by the review

Between the two lanes I found that the proxy buffered request bodies with **no bound** —
Effect's `MaxBodySize` defaults to unbounded, and this route reads the whole body before
forwarding. One authenticated caller could pin arbitrary memory on the route whose whole purpose
is to be reachable from a phone.

Capped at 64 KiB; a declared oversize `content-length` is refused **before** the read, because
refusing after reading would already have done the thing the cap exists to prevent; a chunked
body declares no length, so the cap on the read catches that one. Too-large and could-not-read
get separate signals.

Claude's second pass called it "a real availability fix". Verified by running the same test
against the fork commit before it (`e0476d49aec1`): it fails there and passes at `24aeeebb3ded`,
with no fork history touched.

## What both lanes verified as holding

Server-held origin allowlist with selection by id; `CODEV_AGENT_PATH_ABSOLUTE` for a URL in the
path; redirects refused rather than followed; unreachable and silent as distinct signals;
`Connection`'s own tokens subtracted from the header allowlist; `authorization` and `cookie`
never forwarded; the machine credential and the `client-session` token both required and refused
differently; four approval outcomes with the record server-sourced and an empty 200 rendering as
`unconfirmed` rather than a manufactured yes; pane content from one workspace-state poll rather
than six transcripts; and the Playwright spec recording every request and asserting same-origin,
with a positive assertion that the proxy was reached at all so the negative cannot pass vacuously.
Loading
Loading