Repository navigation
Follow up items from maintainer for #1483 - afx send/afx inbox #1680
Description
#1483 sub-issues — maintainer (waleedkadous) optional / future-change comments
Collected: 2026-09-12T17:04:20Z
Repo HEAD at collection: bcc46f11e (2026-09-12T16:48:19+10:00 / 2026-09-12T06:48:19Z)
Scope: the 13 sub-issues of #1483 —
1361, 1365, 1450, 1471, 1472, 1473, 1474, 1475, 1476, 1477, 1478, 1481, 1482
(sub-issue set confirmed via the GraphQL subIssues connection, 2026-09-12T17:04:20Z).
Where the comments actually live
Only one maintainer comment sits on a sub-issue itself (#1481). Every other
maintainer note about optional/future work arrived as a PR review on the PR that
closed a sub-issue. Both sources are collected below, each labelled with its sub-issue,
its surface, and its UTC timestamp.
| Sub-issue | Closing PR | PR merged (UTC) | Maintainer comment surface(s) |
|---|---|---|---|
| #1361 | — (closed as stale; fixed by #1354 / PR #1402) | — | none |
| #1365 | #1492 | 2026-09-01T11:19:24Z | review APPROVED 2026-09-01T11:19:20Z |
| #1450 | #1510 | 2026-09-03T12:23:07Z | review APPROVED 2026-09-03T05:38:15Z |
| #1471 | #1487 | 2026-09-03T12:22:57Z | review APPROVED 2026-09-03T05:36:15Z |
| #1472 | #1484 | 2026-09-03T12:22:27Z | review APPROVED 2026-09-03T05:36:14Z |
| #1473 | #1634 | (no maintainer comment on PR) | none |
| #1474 | #1491 | 2026-09-04T15:22:13Z | review CHANGES_REQUESTED 2026-09-03T19:45:15Z; DISMISSED 2026-09-04T15:16:58Z |
| #1475 | #1511 | 2026-09-03T16:58:58Z | review APPROVED 2026-09-03T15:35:37Z |
| #1476 | #1485 | 2026-09-03T12:22:29Z | review APPROVED 2026-09-03T05:36:16Z |
| #1477 | #1625 | 2026-09-08T11:12:56Z | issue-comment 2026-09-08T11:12:52Z (no optional items) |
| #1478 | #1486 | 2026-09-04T15:22:36Z | review CHANGES_REQUESTED 2026-09-03T19:44:48Z; DISMISSED 2026-09-04T15:17:01Z |
| #1481 | #1640 (OPEN, CONFLICTING) | — | issue comment 2026-09-01T11:37:50Z |
| #1482 | #1604 | 2026-09-04T15:16:56Z | review CHANGES_REQUESTED 2026-09-03T19:45:28Z; APPROVED 2026-09-04T15:16:52Z |
#1481 — issue comment, 2026-09-01T11:37:50Z
Known corner to fold into this work (documented in the PR #1492 review, deliberately NOT
built standalone — owner call 2026-09-01):boundedinsubmitToSessionis computed once at
enqueue (contended && ceiling && !behindOperator), so with a long delivery in flight and one
operator queued (ceiling armed), a second operator arriving meanwhile gets an unbounded wait —
it sits through the delivery's entire paced write plus the first operator, where pre-#1365 its
interrupt landed immediately. Needs a >2s delivery plus two operator gestures inside its
window, so it is rare, and the write-edge size cap (new issue, refs #1564/#1521) shrinks
worst-case delivery duration to a couple of seconds, which mostly evaporates the window.
If/when --interrupt-after is built: re-evaluate the bound when the operator ahead drains (or
race against all non-operator predecessors) rather than deciding once at enqueue.
Optional/future item
- O1 — re-evaluate
boundedwhen the operator ahead drains, instead of deciding once at enqueue.
#1365 — PR #1492 review APPROVED, 2026-09-01T11:19:20Z
One design corner to carry forward — non-blocking, I'll file it as a follow-up issue:
boundedinsubmitToSessionis computed once at enqueue (contended && ceiling && !behindOperator). With a long delivery in flight and one operator queued (ceiling armed), a
second operator arriving meanwhile getsbounded=falseand can wait out the delivery's
entire paced write — unbounded, where the pre-convergence behavior was immediate. It needs a2s delivery plus two operator actions inside its window, so it's rare; re-arming the bound
when the operator ahead drains looks like the right shape, and it belongs with the
--interrupt-afterwork that's already sequenced after this PR.Two accepted tradeoffs I'm explicitly endorsing rather than flagging:
preempted→ possible
duplicate delivery (the right direction of error vs silent loss), and the bypass counter's
benign scheduling-time false-positive window.
Optional/future item
- O1 (duplicate of the afx send: add --interrupt-after <seconds> (hold, then force-deliver after a bounded wait) #1481 comment) — same
bounded-recompute corner. Tracked once below.
#1472 — PR #1484 review APPROVED, 2026-09-03T05:36:14Z
Two small things you might consider, neither blocking:
- The identical add-only
seenset lives inbuilder-spawn-handler.ts:11(keyed on
terminalId, no eviction) — the very module this PR's comment cites as its model. Worth a
follow-up issue under Tracking: mailbox-first send follow-ups — gate correctness, interrupt semantics, attribution, visibility (post-1313) #1483 rather than widening this PR.- A half-sentence noting why this module deliberately does not persist its seen-set to
workspaceStatethe waygate-toast.tsdoes (no replay → nothing to re-toast) would save a
future reader the question.
Optional/future items
- O2 — bound the identical add-only
seenset inbuilder-spawn-handler.ts:11; file as a follow-up issue under Tracking: mailbox-first send follow-ups — gate correctness, interrupt semantics, attribution, visibility (post-1313) #1483. - O3 — add a half-sentence on why the escalation-toast seen-set is deliberately not persisted to
workspaceState(contrast withgate-toast.ts).
#1476 — PR #1485 review APPROVED, 2026-09-03T05:36:16Z
I'll take the arch.md follow-up myself (add
db/migrations.tsto Core Components and the repo
tree, and name that test as the enforcing guard) — that's architect territory, as you correctly
left it.One optional tidy-up for a follow-up: the literal
GLOBAL_CURRENT_VERSION = 17source guard in
send-architect-identity.test.ts:239is now behaviorally covered and just adds a per-migration
edit tax.
Optional/future items
- O4 — arch.md: add
db/migrations.tsto Core Components and the repo tree, and name the v1→v17 convergence test as the enforcing guard. (maintainer took this one themselves) - O5 — drop the literal
GLOBAL_CURRENT_VERSIONsource guard insend-architect-identity.test.ts(per-migration edit tax, now behaviorally covered).
#1478 — PR #1486 review CHANGES_REQUESTED, 2026-09-03T19:44:48Z
#1486 (review)
(The three blocking items were fixed and verified in the DISMISSED review of 2026-09-04T15:17:01Z; only the non-blocking tail is reproduced here.)
Worth a follow-up rather than this PR: give the VS Code extension's send an architect
from
(it renders? → buildertoday), and threadsenderHeaderLabelthrough the any→builder path
so builder→builder frames stop claimingARCHITECT(overlaps #1576). Also noting
message-format.tsnow depends on the built sdk — a new build-order edge on a file the Tower
server loads; fine, just worth knowing.
Optional/future items
- O6 — give the VS Code extension's send an architect
from(renders? → buildertoday). - O7 — thread
senderHeaderLabelthrough the any→builder path so builder→builder frames stop claimingARCHITECT(overlaps tower: builder→builder sends carry a reply hint pointing at the architect, not the sender #1576). - (informational, no action asked)
message-format.tsnow depends on the built sdk — a new build-order edge on a file the Tower server loads.
#1471 — PR #1487 review APPROVED, 2026-09-03T05:36:15Z
One small loose end you could fold in before merge, or I'll pick it up: issue #1471 names
codev/reviews/1313-afx-send-mailbox-first-delivery.md, whose lines ~341 and ~348 still
describe the CI-aware wall-clock bound as live and the op-count check as pending. That file's
own convention (line 347) is a strike-through + DONE pointer — two lines pointing at this PR.Worth knowing rather than changing: the branch is well behind main, but the intervening
render-gate work doesn't alterclassifyBuffer's measured behavior, and the facade's coupling
to xterm's descriptor shape fails loudly rather than silently on an upgrade. Claude's lane also
suggested the same technique could retire several sibling wall-clock assertions (tunnel-e2e,
shellper-client, session-manager, spec-1365) — a good follow-up issue if you're inclined.
Optional/future items
- O8 — strike-through + DONE pointer on the two stale lines in
codev/reviews/1313-afx-send-mailbox-first-delivery.md(wall-clock bound described as live; op-count check as pending). - O9 — apply the counting-facade technique to retire sibling wall-clock assertions (tunnel-e2e, shellper-client, session-manager, spec-1365); file as a follow-up issue.
#1474 — PR #1491 review CHANGES_REQUESTED, 2026-09-03T19:45:15Z
#1491 (review)
(The blocking sanitize.py item was fixed and verified in the DISMISSED review of 2026-09-04T15:16:58Z; only the non-blocking tail is reproduced here.)
Two small things you might consider alongside, neither blocking:
buf.cursorYis baseY-relative in xterm's public contract; the code relies on
viewportY === baseY.buf.baseY + buf.cursorY - buf.viewportYremoves that assumption for
free, and it's now load-bearing for delivery.- Idle-session drift is silent —
onLivenessgates on recent output, so a re-themed agy
sitting idle holds forever with no alarm, the same shape as the bare->bug this fixes. A
follow-up on profile-drift observability (classifier-stuck escalation for idle sessions, or
anafx doctorcheck that classifies each live mirror once) would close that.Also noting
markerFgPalettewill want to accept multiple colors before agy ships a truecolor
theme — follow-up territory.
Optional/future items
- O10 — compute the cursor row as
buf.baseY + buf.cursorY - buf.viewportY, removing theviewportY === baseYassumption. - O11 — profile-drift observability for idle sessions: classifier-stuck escalation for idle sessions, or an
afx doctorcheck that classifies each live mirror once. - O12 — let
markerFgPaletteaccept multiple colors (ahead of an agy truecolor theme).
#1450 — PR #1510 review APPROVED, 2026-09-03T05:38:15Z
A few things you might consider, none blocking — happy for them to be a follow-up:
tower-routes.ts~2170: the comment saysconst projected: HeldMessage[]prevents an extra
bodyfrom compiling. The two lanes disagreed on whether contextual typing through.map()
actually gives you excess-property checking there — cheapest resolution is
satisfies HeldMessageon each projected object, which makes the guarantee real regardless.- Three of the post-consult fixes have no test pinning them (keep-rows-during-refetch,
aria-live/aria-busy, and the ref-latched loader — thedoes not refetch on an unrelated rerendertest reuses the same function reference, so it would pass against the old code
too). A future refactor can undo all three silently.handleInboxListis now exported purely as a test seam for a branch that's unreachable
throughhandleRequest; the other route tests all go through the front door, and dropping
the seam costs nothing.- Docs: the popover refreshes only on
heldCountchanges (matches the plan — just avoid
implying every mailbox movement refreshes it), and the new arch.md table line ~672
generalizes "omitted workspace = first known" while/api/inboxintentionally lists all —
worth qualifying as handler-dependent.- The evidence script sits outside
tsconfiginclude and vitest collection, and it's the third
hand-rolled isolated-Tower fixture — extracting that fixture into a shared helper would be a
nice small follow-up.Also noted for the follow-up list: VS Code's
mailbox-indicators.tsshows the sameN held
with no path to the list, and mobile renders no badge at all — the route you added is what both
would need.
Optional/future items
- O13 —
satisfies HeldMessageon each projected object intower-routes.ts(make the excess-property guarantee real). - O14 — tests pinning three post-consult fixes: keep-rows-during-refetch,
aria-live/aria-busy, and the ref-latched loader (the existing "does not refetch on an unrelated rerender" test reuses the same function reference). - O15 — drop the
handleInboxListtest-seam export. - O16 — docs: don't imply every mailbox movement refreshes the popover; qualify arch.md's "omitted workspace = first known" as handler-dependent.
- O17 — extract the hand-rolled isolated-Tower evidence fixture into a shared helper; bring the evidence script under
tsconfig/vitest. - O18 — VS Code
mailbox-indicators.tsshowsN heldwith no path to the list; mobile renders no badge at all — both need the new route.
#1475 — PR #1511 review APPROVED, 2026-09-03T15:35:37Z
Non-blocking things you might consider, from the reviews:
- The empty-command rejection in
setIdentityis only safe becauserestartOnExitis gated on
hasRestartinsession-manager.ts:572— a non-local invariant. A one-line comment at
setIdentity(or a test pinning "a session with no restartOptions never spawns") would
protect it from a futurereconnectSessionrefactor.console.warninShellperClientcan surface inside a user's attached terminal
(clientType: 'terminal'), not just Tower's log — an emitted event or injected logger would
be safer.identitySource: 'welcome'is reported for a Tower-issued SPAWN the shellper hasn't
confirmed yet; a distinct label (e.g.spawn) would let an operator debugging a
no-profilehold tell confirmed from optimistic.- Crash-loop relaunch end-to-end coverage is structurally identical to the clean-exit lane you
covered — cheap to add as a follow-up.- The
codev/evidence/+scripts/*-evidence.mtsconvention now has three instances on main;
worth documenting as a PIR convention and bringing those scripts under a typecheck so the
lessons-learned citations don't rot. Happy to take that one as an architect follow-up if
you'd rather.
Optional/future items
- O19 — comment or test at
setIdentitypinning the non-localrestartOnExit/hasRestartinvariant. - O20 — replace
console.warninShellperClientwith an emitted event or injected logger (it can surface in a user's attached terminal). - O21 — distinct
identitySourcelabel (e.g.spawn) for a Tower-issued SPAWN the shellper hasn't confirmed. - O22 — crash-loop relaunch end-to-end coverage.
- O23 — document
codev/evidence/+scripts/*-evidence.mtsas a PIR convention and bring those scripts under a typecheck.
#1482 — PR #1604 review CHANGES_REQUESTED, 2026-09-03T19:45:28Z
#1604 (review)
(The three blocking items were fixed and verified in the APPROVED review of 2026-09-04T15:16:52Z; only the non-blocking tail is reproduced here.)
Smaller, non-blocking:
isClassifierStuckandisUnverifiableVerdictare now duplicate
predicates that must be kept in sync — one should call the other;HeldMessage.detailis
required whileMailboxEscalationPayload.detailis optional for the same concept; and the 409
RESIZE_DROPPEDbehavior is in arch.md invariant #10 but not the endpoint table at ~778.
Merge-order note: this adds migration v18 — re-checkGLOBAL_CURRENT_VERSIONand the pinned
assertion insend-architect-identity.test.tsif another schema PR lands first.
Also from the same review (item 3, a deferral the maintainer explicitly permitted):
(Fine to land the move here and the three renderers as one AIR follow-up, as long as the toast
fix in item 2 isn't left dead.)
Optional/future items
- O24 — have
isClassifierStuckcallisUnverifiableVerdictrather than restating the rule. - O25 — make
HeldMessage.detailandMailboxEscalationPayload.detailagree on optionality. - O26 — add the 409
RESIZE_DROPPEDbehavior to the arch.md endpoint table (it is in invariant Directory Structure - Separate Framework from Project Files #10 only). - O27 — the "three renderers speak one vocabulary" AIR follow-up permitted after the
hold-verdictmove topackages/sdk.
#1477 — PR #1625 issue comment, 2026-09-08T11:12:52Z
Thank you, this is exactly the missing third leg the issue asked for, and the mutation table
makes it easy to trust. Our three-way review approved with no blocking findings, and two
reviewers independently confirmed the ordering divergence you pinned, so #1633 is the right
home for it. Merging now.
Optional/future items: none (the spun-out divergence is tracked as #1633).
Sub-issues with no maintainer comment
- Render gate: adopt/reconnect mirror seed capped at 1 MiB → idle adopted alt-screen agent can hold mail until next repaint #1361 — closed as stale 2026-08-18 (already fixed by O(screen) replay: headless terminal-state emulation so reconnect renders correctly without the resize nudge #1354 / PR O(screen) reconnect replay via the session screen mirror (PIR #1354) #1402); no maintainer comment on the issue.
- Render gate: fuller close of the gate→write input race (R7 staleness) and input-echo-lag residual #1473 — no maintainer comment on the issue or on PR Render gate: close the gate→write input race and the input-echo-lag residual #1634.
- Render gate: tighten the loose agy prompt marker (AGY_MARKER = /^> /) #1474 / Tower: extract runGlobalMigrations(db) so migration tests drive the real production runner #1476 / Test coverage: mailbox owner-resolution wiring (escalateHeldToOwner) and cleanupBuilder() held-row dismissal #1477 / afx send: carry architect:<name> through to inbox and composer attribution; stop truncating names in afx inbox #1478 — no comment on the issue; maintainer notes live on their PRs (above).
Activity
mohidmakhdoomi commentedon Sep 12, 2026
#1483 maintainer optional/future items — triage: addressed vs pending
Revised: 2026-09-12 — synthesis of two reviews of the original triage.
Original verification: 2026-09-12T17:04:20Z; review B rechecked the evidence at 2026-09-12T17:32:12Z.
Baseline commit:
bcc46f11ecfea63ef1cea1f94f5318ffefd93ac9— committed2026-09-12T16:48:19+10:00 (2026-09-12T06:48:19Z), branch
main.Source of items: maintainer comments collection
(#1680 issue body, collected 2026-09-12T17:04:20Z), with collection clarifications recorded below.
Method: retain O1–O27, reconcile both reviews, and recheck disputed code/history claims against
the baseline. Code references describe that commit; GitHub issue/PR states and search results retain
the reviews' September 12 snapshot. Commit timestamps below are author dates in UTC; PR merge
timestamps are labelled separately. Partial work has its own category and still needs follow-up.
Scoreboard
mainmainmain27 items total: 4 complete on
main, 22 with follow-up work remaining, and 1 awaiting integration.The four completed items were folded into fix rounds following CHANGES_REQUESTED reviews on
PR #1491 (2026-09-03T19:45:15Z) and PR #1604 (2026-09-03T19:45:28Z), before those PRs merged.
That is an observed pattern, not a sufficient explanation: O27 from #1604 is only partial, and
O6/O7 remain pending despite #1486 also receiving CHANGES_REQUESTED. O3, from an APPROVED review,
has relevant rationale already present but still lacks the requested persistence explanation.
The approvals for #1484, #1485, #1487 and #1510 were at 2026-09-03T05:36–05:38Z; #1511 was
approved at 2026-09-03T15:35:37Z. Related issues #1576 and #1594 both pre-date the comments that
mention or overlap them. They provide existing tracking context, not evidence that follow-up issues
were filed in response to these reviews. The searches found no follow-up issue for O2 or O9.
Addressed on
mainO10 — cursor row through
baseY(from #1474, PR #1491 review 2026-09-03T19:45:15Z)DONE in
8d9d666c8— 2026-09-03T23:36:35Z (author date 19:36:35-04:00),3h 51m 20s after the review that asked for it; folded into the same fix round.
render-gate.ts:371now readsconst cursorRow = buf.baseY + buf.cursorY - top;with a comment(
:366-368) naming the retiredviewportY === baseYassumption.O24 —
isClassifierStuckdelegates toisUnverifiableVerdict(from #1482, PR #1604 review 2026-09-03T19:45:28Z)DONE in
dca5699ef— 2026-09-03T23:32:40Z (author date 19:32:40-04:00).mailbox-delivery.ts:517-522is now a thin wrapper returningisUnverifiableVerdict(reason, detail),with a doc comment citing the maintainer review and explaining why the wrapper is kept (the two
callers want different types: DB/gate unions vs plain strings).
O25 —
detailoptionality reconciled (from #1482, same review)DONE in
dca5699ef— 2026-09-03T23:32:40Z.packages/types/src/sse.ts:61-67documentsMailboxEscalationPayload.detailas REQUIRED,matching
HeldMessage.detailand the payload's ownreason. The field at:68is the non-optionaldetail: string | null.O26 — 409
RESIZE_DROPPEDin the arch.md endpoint table (from #1482, same review)DONE in
dca5699ef— 2026-09-03T23:32:40Z.codev/resources/arch.md:782now carries the row: "200 with the APPLIED dims; 409RESIZE_DROPPEDwhen the session exists but the resize never reached its process (dimsunchanged); 404 only for an unknown id (#1482)". Also at
:424in the route summary and:112in invariant 10.Partially addressed on
mainO3 — rationale for not persisting the escalation-toast seen-set
(from #1472, PR #1484 review 2026-09-03T05:36:14Z)
PARTIAL.
apps/vscode/src/notifications/mailbox-escalation-toast.ts:46says "no SSE replay, soan evicted id has no second event to be deduped against", explaining eviction safety. That text
dates to
744995fa5(2026-08-17T23:14:47Z), before the review; it does not establish that arequested follow-up landed. The explicit explanation of why this module does not persist to
workspaceStatethe waygate-toast.tsdoes remains absent.Remaining: add the requested persistence explanation beside the existing rationale.
O27 — the three renderers speak one vocabulary
(from #1482, PR #1604 review 2026-09-03T19:45:28Z, item 3's permitted deferral)
PARTIAL in
dca5699ef— 2026-09-03T23:32:40Z, within PR #1604 itself.The original review
names
HeldCountBadge,escalationToastText, andapprove.ts; the collection's excerpt omitsthat naming sentence. The first two use the shared formatter in
packages/sdk/src/hold-verdict.ts(
apps/web/src/components/HeldCountBadge.tsx:40,apps/vscode/src/mailbox-indicators.ts:16).apps/vscode/src/commands/approve.ts:119still interpolates onlyresult.reason, and its localSendResulttype at:90has nodetail, although the SDK response carries it(
packages/sdk/src/tower-client.ts:824-831).Remaining: carry the detail through the approval relay result and format it with the same
shared vocabulary.
5e3deef4e(2026-09-09T17:20:48Z) later extended the formatter withcomposer-redraw; it did not complete this renderer conversion.Implemented but not yet on
mainO1 — re-evaluate
boundedwhen the operator ahead drains(from PR #1492's approval 2026-09-01T11:19:20Z, carried into the #1481 issue comment
2026-09-01T11:37:50Z)
Implemented in PR #1640 — OPEN and
CONFLICTING in the reviews' September 12 snapshot. The diff removes the enqueue-time
!behindOperatordisarm (const bounded = contended && ceilingMs !== undefined && ceilingMs >= 0;)and splits the wait into two concurrently-evaluated conditions — preceding operators finished
(unbounded, by design) AND predecessors finished or the ceiling expired — which is exactly the
shape the maintainer prescribed ("re-evaluate the bound when the operator ahead drains… rather than
deciding once at enqueue"). On
main,session-submit.ts:374still computesbounded = contended && … && !behindOperator, so the corner remains at the baseline.Action: resolve #1640's conflicts, validate the resulting PR, and merge through the normal
approval process. The implementation is already in that PR; no separate implementation is needed.
Pending
From #1472 — PR #1484 review, 2026-09-03T05:36:14Z (merged 2026-09-03T12:22:27Z)
O2 — bound the
builder-spawn-handler.tsseen set.apps/vscode/src/builder-spawn-handler.ts:11is still
private seen = new Set<string>();— add-only, keyed on terminalId, no eviction. Themaintainer asked for a follow-up issue under #1483; none was found in the collection's
2026-09-12T17:04:20Z search or the reviews' verification. Pending implementation and tracking.
From #1476 — PR #1485 review, 2026-09-03T05:36:16Z (merged 2026-09-03T12:22:29Z)
O4 — arch.md:
db/migrations.ts+ name the convergence test.db/migrations.tsappearsnowhere in
codev/resources/arch.md; the repo tree at:1388-1391enumeratesindex.ts,schema.tsandmigrate.tsunderdb/, but omitsmigrations.ts. The reference at:1836to"the convergence test" is generic: the migration convergence test is not named as the enforcing
guard. Add the module to both Core Components and the tree, and name the guard. The maintainer
offered to take this documentation follow-up themselves; it remains pending.
Related staleness found while checking:
arch.md:463still cites "GLOBAL_SCHEMA, migrationv14" while the schema is at v18 — worth fixing in the same edit.
O5 — drop the
GLOBAL_CURRENT_VERSIONsource guard. Still present, and the predicted edit taxhas already been paid once:
send-architect-identity.test.ts:253now assertsGLOBAL_CURRENT_VERSION = 18, bumped from 17 by3ef84a726(2026-09-03T18:20:48Z, author date14:20:48-04:00, PIR #1482's v18 migration) — 12h 44m 32s after the review, approximately
12h 45m. PR #1640 touches the same test again for v19, so a second bump is queued. These bumps
preserve the guard; O5 asks to remove it.
From #1478 — PR #1486 review, 2026-09-03T19:44:48Z (merged 2026-09-04T15:22:36Z)
O6 — VS Code send carries no architect
from. Both call sites pass options withoutfrom:apps/vscode/src/commands/send.ts:37({ workspace: workspacePath }) andapps/vscode/src/extension.ts:1036-1040. The SDK supports it (tower-client.ts:778—from?: string),so this is a caller-side gap;
afx inboxstill renders? → builderfor a VS Code send.O7 — any→builder still claims
ARCHITECTfor a builder sender.tower-routes.ts:1589routes any→builder toformatArchitectToBuilderMessage, which(
message-format.ts:239→formatArchitectMessage:215) interpolatesarchitectHeaderLabel(sender)— notsenderHeaderLabel(sender).senderHeaderLabel(
:99) exists and does the right shape-based dispatch, but only the builder→architect path uses it.Overlapping issue #1576 is OPEN
("builder→builder sends carry a reply hint pointing at the architect, not the sender"). It was
created by
waleedkadousat 2026-09-01T12:08:57Z, before the September 3 review. It is anexisting related issue whose scope should include the header correction when O7 is picked up.
From #1471 — PR #1487 review, 2026-09-03T05:36:15Z (merged 2026-09-03T12:22:57Z)
O8 — stale lines in the 1313 review doc.
codev/reviews/1313-afx-send-mailbox-first-delivery.mdstill carries both stale claims verbatim, with no strike-through and no DONE pointer: the Flaky
Tests entry describes the CI-aware wall-clock bound (
process.env.CI ? 800 : 250) as the livemitigation and calls the op-count check "the intended replacement (Follow-up)", and the Follow-up
Items list still reads "Replace the render-gate perf wall-clock assertion with a deterministic
op-count check" — nine days after PR #1487 did exactly that.
O9 — retire sibling wall-clock assertions. Pending; no follow-up issue was found in the reviews'
search. All four files named by the maintainer still have wall-clock assertions:
packages/codev/src/agent-farm/__tests__/tunnel-e2e.test.ts:863— p95 below 50ms; anotherelapsed-time measurement uses
performance.now()at:900.packages/codev/src/terminal/__tests__/shellper-client.test.ts:676-679— elapsed-time bounds.packages/codev/src/terminal/__tests__/session-manager.test.ts:2248— two measured start timesmust differ by less than 1000ms.
packages/codev/src/agent-farm/__tests__/spec-1365-serializer-convergence.test.ts:279— wait below100ms (also timing bounds at
:312and:339).From #1474 — PR #1491 review, 2026-09-03T19:45:15Z (merged 2026-09-04T15:22:13Z)
O11 — idle profile-drift observability. The remaining gap is idle-session classifier liveness:
the
onLivenesspath still requires recent output (mailbox-wiring.ts:572), and there is noafx doctorcheck that classifies each live mirror once. Existing alerts provide some coverage:packages/codev/src/agent-farm/servers/mailbox-delivery.ts:1726(noticeOverdue()) enqueues ownernotices for overdue builder mail without requiring recent output, normally after 180 seconds,
provided an owner can be resolved. That path skips architect recipients and does not supply the
general idle-session classifier check requested here. An idle hold can already generate an owner
notice; the targeted liveness/doctor follow-up remains pending.
O12 —
markerFgPalettesingle color. StillmarkerFgPalette?: number(render-gate.ts:132),compared with
!==at:259, and set to the single value12ingate-profiles.ts:145. An agytruecolor theme would need this widened.
From #1450 — PR #1510 review, 2026-09-03T05:38:15Z (merged 2026-09-03T12:23:07Z)
O13 —
satisfies HeldMessage.tower-routes.ts:2403is stillconst projected: HeldMessage[] = rows.map((r) => ({…}))— the annotation form whoseexcess-property behavior the two review lanes disagreed about. No
satisfiesanywhere in theprojection.
O14 — the three unpinned post-consult fixes. All three remain unpinned in
apps/web/__tests__/HeldCountBadge.test.tsx: there is no assertion onaria-live/aria-busy(both live in the component at
HeldCountBadge.tsx:208-209, untested); no test asserts rows stayvisible across a refetch; and
does not refetch on an unrelated rerender(:321) still reuses oneloadMessagesreference across both renders, so it would pass against the pre-fix code — the exactvacuity the maintainer called out. A refactor can still undo all three silently.
O15 —
handleInboxListtest seam. Still exported (tower-routes.ts:2388) and still imported byinbox-routes.test.ts:16, used directly at:421. Both production callers (tower-routes.ts:214and
:2980) are internal to the same module, so they do not need the export. The direct testpasses an empty-string
workspaceOverride, a branchhandleRequestcannot produce. Remove thetest-only export and reconsider that unreachable-branch test while retaining route-level coverage
through
handleRequestand the internal handler used by production.O16 — doc qualifications.
arch.md:676still readsfrom ?workspace=, else "first known"with no handler-dependent qualifier, and nothing notes that
/api/inboxintentionally lists allworkspaces. The popover-refresh wording was not revisited either.
O17 — shared isolated-Tower fixture + typecheck. There are seven hand-rolled harness/evidence
scripts in
packages/codev/scripts/(bugfix-1567-head-loss-harness.mts,bugfix-1664-streaming-delivery-harness.mts,issue-1450-dashboard-evidence.mts,pir-1473-dev-approval-evidence.mts,pir-1473-human-harness.mts,pir-1475-dev-approval-evidence.mts,spec-1365-e2e-evidence.mts), up from the three the maintainer counted. A shared helper doesexist:
startTowerinpackages/codev/src/agent-farm/__tests__/helpers/tower-test-utils.ts:200provides isolated sockets, database/state directory, startup and cleanup, and multiple integration
tests use it. These seven scripts do not reuse that fixture and still duplicate setup.
packages/codev/tsconfig.jsonincludes onlysrc/**/*, leaving the scripts outside the package'snormal typecheck. The follow-up is to reuse or adapt the existing fixture for evidence scripts and
give those scripts maintained typecheck/validation coverage.
O18 — VS Code / mobile held-mail surfaces.
apps/vscode/src/mailbox-indicators.ts:7-8describesthe indicators as count-only/read-only and says dismissal stays CLI-only (
afx inbox).Separately,
heldStatusSegment(:25-30) rendersN heldwith no drill-in, andapps/web/src/components/MobileLayout.tsxcontains no held-mail rendering.Existing related tracking: #1594 is OPEN
("vscode: held-mail drill-in — clickable held indicator with inspect + dismiss"). It was created
by
amrmelsayedat 2026-09-03T03:43:31Z, before the 05:38:15Z review, and covers the VS Codehalf. The reviews identified no issue tracking the mobile badge.
From #1475 — PR #1511 review, 2026-09-03T15:35:37Z (merged 2026-09-03T16:58:58Z)
O19 — explicit
restartOnExit/hasRestartinvariant still missing.setIdentity(
packages/codev/src/terminal/shellper-client.ts:263) has a substantial doc comment, but it explainstrust and coherence rather than the
hasRestartdependency.session-manager.ts:570computesconst hasRestart = !!restartOptions;, and:583assignsrestartOnExit: hasRestart.There is already related coverage:
packages/codev/src/terminal/__tests__/session-manager.test.ts:1101reconnects without
restartOptionsand checks that exit removes the session. It does not explicitlyassert that no SPAWN is sent. The remaining ask is the linking comment at
setIdentityor anexplicit no-SPAWN assertion; existing teardown coverage should be retained.
O20 —
console.warninShellperClient. Still atshellper-client.ts:275, inside the rejectpath, so a discarded WELCOME identity can still print into a user's attached terminal. No emitted
event, no injected logger.
O21 — no distinct
identitySourcelabel for an unconfirmed SPAWN. The union is still'welcome' | 'config'in both places (pty-session.ts:971,tower-utils.ts:723). An operatordebugging a
no-profilehold still cannot tell a confirmed WELCOME identity from an optimisticTower-issued one.
O22 — crash-loop relaunch e2e coverage. Not added. The only match for
restartOptionsinpackages/codev/src/terminal/__tests__/is a signature comment(
tower-shellper-integration.test.ts:603); the clean-exit lane remains the only one covered.O23 — evidence convention undocumented and untypechecked. No mention of
codev/evidence/orscripts/*-evidence.mtsas a convention incodev/protocols/orcodev-skeleton/protocols/.codev/evidence/holds six artifacts (1567-head-loss/,1664-streaming-delivery/,1365-dev-approval-transcript.txt,1473-dev-approval-transcript.txt,1473-human-runbook.md,1475-dev-approval-transcript.txt), andlessons-learned.md:303citespackages/codev/scripts/pir-1475-dev-approval-evidence.mtsby path. Keeping those scripts outsidethe typecheck leaves cited evidence vulnerable to unchecked drift (the typecheck gap also appears
in O17).
Source collection clarifications
Both reviews support keeping the 27-item inventory. Review A found all relevant optional asks;
review B's broader surface inventory found three omitted rebase comments, which contain no optional
items. These findings are compatible: the item harvest is complete, while the comment-surface
table needs the following qualifications.
approve.ts. The full PR Stop suggesting 'afx interrupt' against a human who is just typing (render gate dims + held-verdict detail) #1604 review names it alongsideHeldCountBadgeandescalationToastText. The abbreviated excerpt in the collection is not thecomplete statement of the three-renderer follow-up; O27 above uses the full scope.
at 2026-09-03T05:31:41Z; PR #1491 comment
at 2026-09-03T05:31:42Z; PR #1511 comment
at 2026-09-03T05:31:43Z. All request a rebase and add no O-item.
merged at 2026-09-08T21:39:05Z. The absence of a maintainer comment belongs in the surface
column; it does not replace the merge timestamp.
integration guidance, recorded here as context for O5. It adds no separate optional item.
Updating the pinned version is the maintenance tax O5 asks to remove, so a bump does not close O5.
itself. The other twelve lack maintainer issue comments, including those with architect comments.
The collection's closing list should distinguish this from having zero comments of any kind.
The Tower: extract runGlobalMigrations(db) so migration tests drive the real production runner #1476/PR [Air #1476] Extract runGlobalMigrations(db) so migration tests drive the real production runner #1485 excerpt begins mid-paragraph and omits the preceding convergence-test sentence;
O4 retains the request to name that test. The collection uses excerpts, not full review bodies.
Suggested grouping if these get picked up
arch.md:463v14→v18[-]Follow up items from maintainer for #1483[/-][+]Follow up items from maintainer for #1483 - afx send/afx inbox[/+]