Skip to content

first run: a worker's codeaf is the running one, the usage notice is read on screen, no raw log lines, the receipt names devaf - #1519

Merged
AbirAbbas merged 9 commits into
devfrom
fix/first-run-names
Sep 25, 2026
Merged

AbirAbbas merged 9 commits into
devfrom
fix/first-run-names

Conversation

@AbirAbbas

Copy link
Copy Markdown
Collaborator

Four first-run defects found by a fresh-install check of the published dev build, installed as devaf through the real installer.

1. A worker's codeaf reached the wrong binary. The worker is taught to edit with codeaf patch, but only a plandb shim was on its PATH. On any install not named codeaf, the call was command not found, or it reached an older codeaf (there is no \codeaf patch`). Now armShimalso writesbin/codeaf, which execs the binary the codeaf command registered at start (session.SetRunningCLI). A process that registered nothing gets a one-line refusal with exit 127, and never another codeaf. The landing reads bin/codeafas the harness's own file. Found during the hand check: the plan CLI's plandb statusprobe hitdatabase is lockedbeside the live store, which failed a whole task withno plandb CLI found. The registered codeaf is now the worker's plandb` without a probe.

2. The telemetry notice was hidden under the full-screen UI. It was printed on the normal screen and marked seen at once, so it was read only after quitting, and that exit had already sent the counts. This is a design choice (option b of three): a chat now owes the notice to the surface. The first conversation's screen draws all six lines, dim, under the starting points. It is marked seen from the update loop only after a frame drew it. A frame too short for the whole notice, or the setup in front, leaves it owed, and nothing is flushed before the mark. Task commands and chat --once still print it to stderr.

3. Raw log lines appeared on a first launch. A keyless first launch logged media: no generation endpoint … provider API key is required onto the terminal. Keyless media is now an absent capability, with no line. The Model Pool judge kept the boot's keyless settings, so every landing in the first session failed with no API key and was marked judged for good. The judge now reads the process's live account when it asks. A judge with no key at all stops without a reason line or a judged marker, which leaves the landing for the next start.

4. The installer receipt named the wrong command. A devaf install said installed codeaf dev-…. It now says installed devaf · codeaf dev-… built …, and a default install is unchanged. The manual and GUIDE no longer say the installer prints the telemetry notice.

Validation contract

  • Whatever the running binary is named, and with a codeaf that prints WRONG first on PATH, a worker's codeaf … and plandb … reach the running binary: first word, after cd, and command -v. With no running codeaf registered, codeaf refuses with exit 127 and never prints WRONG. (internal/session/codeaf_shim_test.go)
  • A chat on a terminal marks the notice seen only after a surface frame drew it, and hands the surface the exact notice. A task still prints and marks it. A short frame, or setup in front, draws none of it and marks nothing. (cmd/codeaf/telemetry_notice_surface_test.go, internal/tui3/telemetrynotice_test.go)
  • A keyless first launch writes nothing to the standard logger, while a media fault that has a key still logs. The judge asks with the key pasted after boot. A keyless judge leaves no judged marker. (cmd/codeaf/firstrun_quiet_test.go)
  • A --name devaf install, from the flag or the environment, prints installed devaf · codeaf <tag> …, and no line starts installed codeaf. (internal/release/install_test.go)

Each test was shown failing on the pre-fix behaviour before the fix.

By hand

make build gave bin/codeaf, which was installed as ~/.codeaf/bin/devaf on a throwaway HOME. A stale codeaf script printing WRONG was first on PATH, and every seat was pinned to deepseek/deepseek-v4-flash.

  • The normal screen under the alt screen held nothing after launch or after the task (no notice, no media: line). chat.log was empty.
  • The first conversation drew the six notice lines, and telemetry/notice_seen appeared only after that.
  • A /task worker ran codeaf patch calc.py --old 'a - b' --new 'a + b', which answered patched calc.py. The run's bin/codeaf was exec …/devaf "$@".
  • The judge half could not be driven by hand: the chat's default /task road (the run engine) does not reach the pool judge, and quick_task was not on the belt. The unit tests prove it.

Follows #1429 / #1485 / #1494 / #1436 review

🤖 Generated with Claude Code

AbirAbbas and others added 9 commits September 25, 2026 15:59
…e key pasted into setup

A first launch builds its conversation before setup has a key, so the
media door logged `media: no generation endpoint on this install:
provider API key is required` onto the person's terminal just before the
surface covered it. A keyless install now leaves media absent and says
nothing; a media failure with a key in hand still logs.

The Model Pool judge was built from the same keyless boot copy of the
settings and never learned the key pasted into setup, so every task that
landed in an install's first session failed with `no API key` and was
marked judged for good. The judge now reads the process's live account
when it asks, and a judge with no key at all stops without a reason line
or a judged marker, leaving the landing for the next start's sweep.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
An install under another file name (`/get/devaf`, `/get/stageaf`,
`--name WORD`) printed `installed codeaf dev-… built …`, sending the
person to a command this install never wrote, or to an older codeaf
that happened to be on PATH. Such an install now reads
`installed devaf · codeaf dev-… built …`; a default install's receipt is
unchanged.

The manual and GUIDE also said the installer prints the telemetry
notice, which has been false since the installer stopped printing it;
both now say it prints two things.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… as seen only once drawn

A chat printed the anonymous usage counts' notice to stderr and marked it
seen in the same breath, then handed the terminal to the full-screen
surface, which covered it. A new person read it only after quitting, and
the exit that uncovered it had already sent the first counts.

A chat on a terminal now owes the notice to the surface: runSurface hands
the exact text to tui3, the first conversation's greeting draws all six
lines dim under the starting points, and the door marks it seen from the
update loop after a frame has drawn it. A frame too short for the whole
notice, or the setup standing in front, draws none of it and leaves it
owed; nothing is flushed until the mark. Task commands and `chat --once`
still print it to stderr before they start.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…its file is called

The bash worker is taught to edit with `codeaf patch`, but the harness
put only a `plandb` shim on the worker's PATH, so `codeaf` resolved on
the machine's own PATH. On a devaf, stageaf or `--name` install that was
`command not found`, and on the fresh-install check it reached an older
codeaf that answered `there is no \`codeaf patch\`` three times.

armShim now writes `bin/codeaf` beside `bin/plandb`, on the same PATH
entry every worker command already carries. It execs the binary the
codeaf command registered at start (SetRunningCLI), so it is the running
one under any name, ahead of any other codeaf on PATH. A process that
registered nothing (a bench driver, a test binary) gets a shim that
refuses in one line with exit 127 instead of reaching another codeaf.
It is registered rather than probed because there is no harmless probe
for every verb, and a driver handed `patch` would start its own grid.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A run whose store sits inside the working copy writes its shims into
that copy's bin/, and harnessWrote already reads bin/plandb as the
harness's own. bin/codeaf now reads the same way, so a landing never
counts the shim as a change the run made or keeps a branch for it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The plan CLI's resolver probed `<self> plandb status` beside the run's
store while the run was writing it. On the hand check that probe met
`database is locked (SQLITE_BUSY)`, so the resolver fell through to the
codeaf on the machine's PATH: an older version answering this run's plan
on the fresh-install machine, and on a clean devaf install nothing,
which failed the task with `no plandb CLI found`. The codeaf command now
registers itself at start, so the resolver takes it unprobed, right
after the explicit override; unregistered processes (a bench driver)
still probe.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
# Conflicts:
#	internal/manual/chat/worker-harness.md
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@AbirAbbas
AbirAbbas merged commit 3e0bb5b into dev Sep 25, 2026
5 of 7 checks passed
@AbirAbbas
AbirAbbas deleted the fix/first-run-names branch September 25, 2026 23:01
AbirAbbas added a commit that referenced this pull request Sep 25, 2026
…he task room

Brings in #1516, #1517, #1518 and #1519. The two conflicts were dev editing the
inline run-road code that this branch had moved into helpers: the --one-model
seat (#1517) now rides the precomputed crew factory in enginewire, and the
hand-off's named model reaches the crew router as a worker pin (#1518) through
the crew wish set before commitProposalToRun. That wish is read only by the
ordinary task's crew routing, so a senior-dev run keeps the models it names.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant