Repository navigation
remote: twenty-three surface doors do not cross the wire, and eight of them say something untrue instead #901
Description
remote: twenty-three surface doors do not cross the wire, and eight of them say something untrue instead
Parent issue. The children are the doors, grouped below. Found while landing
MethodTyping in PR #872 — the typing pre-warm was one of these, and it was not special.
A law now walks the tree and refuses a twenty-fourth
(internal/remote/surfacedoors_law_test.go, TestEverySurfaceDoorTheEngineHasCrossesTheWire),
so this list can only shrink. It is the shrinking that is owed.
What this is
internal/tui3 reaches for optional capabilities the way this repo says to — a type
assertion on the agent it holds:
door, ok := a.agent.(memoryAgent)
if !ok { /* the capability is absent */ }A *session.Agent satisfies these. A *remote.Agent — the handle the surface holds when
it is talking to a detached engine over the JSON-lines wire — satisfies twenty-three of
them not at all, because the method was never given a Method* on the wire.
And the default launch is the wire. cmd/aforge/chatv3_local.go's v3TakeHostRoad is
true for every launch except --no-host, --debug, first-run setup and a hostless
--once. A bare aforge holds a *remote.Agent. So this is not the --host <dest>
road's problem — it is what almost every person is running.
Nothing on the list was decided to be local-only. Each is a door somebody wired to
*session.Agent and nobody carried across.
The split, and why it decides the order
A capability that cannot work is ABSENT, NOT BROKEN (CLAUDE.md). Fifteen of these obey
it: the page, the section or the count is simply not drawn and a person meets nothing.
Eight do the inverse, and those are the ones to land first. The surface's guard for
"am I on the far road" is a.hosted(), which is a.host != "" (internal/tui3/host.go:259)
— set only by --host <dest>. On a bare aforge it is false, every hosted() guard is
skipped, the local branch runs, and the person is told a reason that is not the reason.
| door | what a person is told | what is true |
|---|---|---|
memoryAgent |
memory is off for this session · turn it on under /settings |
memory is on; the door did not cross. /settings will not help. |
folderLander |
nothing is waiting · what this conversation writes in the folder it is standing in is already there |
there may be plenty waiting; /land cannot ask |
autonomyAgent |
this conversation has no project to keep question rules in |
there may well be one; only the READ half is missing (SetAutonomy crosses, so the sheet can be changed and not shown) |
subharnessAgent |
no subharnesses here yet — a subharness is a saved program for work that comes round again. |
there may be several |
orchAgent |
adaptive runs unavailable — this session has no orchestrator |
it has one |
harnessRunner |
harnesses are unavailable here |
they are available |
standingHereAgent |
this window cannot change it |
the window could, if the door crossed |
taskRoomAgent |
this session has no task rooms (+ · say it to main) |
it has them |
Three of those send a person to a settings page that cannot fix what they came for. That
is worse than the silence, and it is the half the first version of this ledger left out.
The other fifteen, silently absent: abandonAgent, elsewhereAgent, leavableRunner,
leavableWaker, promoteAgent, runAgent, spellOutAgent, standingCountAgent,
taskMentionAgent, taskWeightDoor, turnResumer, wakeAgent, workingNowAgent,
interface{ LandingFor(…) }, interface{ PendingConsent() []uint64 }. Each one's exact
cost is written beside it in the ledger.
Replication a stranger can run
make build
go test ./internal/remote/ -run TestEverySurfaceDoorTheEngineHasCrossesTheWire -vGreen today — the twenty-three are on the ledger. To see the list and what each costs, read
doorsThatHaveNotCrossed in internal/remote/surfacedoors_law_test.go; every entry carries
what is lost, and the eight above carry the sentence verbatim (the law checks the quote is
still one internal/tui3 spells, so it cannot drift into fiction).
To meet one as a person, with no second machine:
make build
bin/aforge # the DEFAULT launch — this is the far road
/remember something worth keepingand read memory is off for this session · turn it on under /settings. Then
bin/aforge --no-host and type the same thing; it works. The difference is the wire.
The design question this asks first — and it is a ruling, not a task
A ledger in a _test.go is not where this belongs. It is a private list, invisible to
anyone who has not opened that file, and it is a list of names where what a person needs
is a capability that answers. The peer session working the task surface put it plainly:
task journal / watch / index is the family they would build rather than a ledger — that
is, the missing doors around tasks (taskRoomAgent, taskMentionAgent, taskWeightDoor,
wakeAgent, leavableWaker, workingNowAgent) are not six independent wire methods to
add one at a time; they are one family — a journal you can read, a watch you can hold, an
index you can complete from — and building the family lands all six and is less code than
six methods.
So the first decision is family-by-family, not door-by-door, and the candidate families
are:
- tasks — journal, watch, index, weight, wakes, what is working now:
taskRoomAgent,taskMentionAgent,taskWeightDoor,wakeAgent,leavableWaker,
workingNowAgent(6) - standing and autonomy —
standingHereAgent,standingCountAgent,autonomyAgent
(3 doors, 6 person-facing verbs) - the project's shelves —
memoryAgent,folderLander,interface{ LandingFor(…) }(3) - orchestration —
runAgent,orchAgent,leavableRunner,harnessRunner,
subharnessAgent(5) - the turn's own edges —
abandonAgent,turnResumer,spellOutAgent,
promoteAgent,elsewhereAgent,interface{ PendingConsent() []uint64 }(6)
Six plus three plus three plus five plus six is the twenty-three.
Acceptance, end-to-end first
- For each family landed: a tmux drive of the real binary on the DEFAULT road (
bin/aforge,
no flags —docs/remote-access-testing.md§3.0 has the recipe) asserting the exact string a
person now meets, not a unit test over*remote.Agent's method set. The unit-green /
e2e-broken failure (e2e: the tmux TUI suite still expects the pre-redesign home — 7 of 9 subtests fail on a clean dev #184) is exactly this shape. doorsThatHaveNotCrossedloses the entry andsurfaceDoorLedgercomes down in the same
commit — the ratchet fails in both directions.- The false sentences are the acceptance's first line. A door that lands and leaves its
old local-branch wording reachable has not landed; grep the string out ofinternal/tui3
in the same change. - While a family is still unlanded, the
hosted()guard question stands on its own: a
sentence that is false on the default road should at minimum stop naming a cause it
cannot know. That may be worth doing before any door crosses.
Adjacent, deliberately not folded in
a.hosted()isa.host != ""and is therefore "am I on--host", not "am I talking to
a far engine". Everyhosted()guard in the surface is mis-asking on the default road.
Renaming it, or splitting it intoonADistantMachine()andthroughTheWire(), is a
separate and probably small change that would make the eight false sentences visible to
whoever reads that code next. Worth its own issue if this one is broken up.- PR A warm wire, and the socket never waits: the reader reads, typing crosses, and the handshake is on the row #872 landed
MethodTypingand the law. It did not land any of the twenty-three.
🤖 Generated with Claude Code
Drafted with CodeAF · reviewed and owned by the author
Activity
Review: the ratchet turns both ways, a keystroke never waits, and the…
A warm wire, and the socket never waits: the reader reads, typing cro…