santos/dev: crew family, Pareto crewing and the Model Pool, custom connections - #1108
Conversation
… custom connections (#1194) Lands the integration branch santos/dev (#1108, head 6db5125, 152 commits over dev) on dev as one squash, plus two fixes that kept its touched-packages job red: the pool start-up test empties the CI word it is not about (649bb4b), and a zombie leader no longer keeps a job's process group alive on Linux, which had delayed every finished background job by the two-second termination grace since #1155 (053e6a9). #1108 carries the full account; the 94 change entries under docs/changes/unreleased/ are the per-change record. The commits folded in, oldest first: 5c413ef Keep archived evidence readable while tasks finish 3705a0c Document recovery evidence retrieval change 7834cc7 tui3, manual: a question's own answer box answers to the whole caret vocabulary 99d66e9 task: Add open/all source toggle to crew config c1e4cb5 docs: the change entry for the crew model family toggle e63b439 crew: round-1 review fixes 304a5a2 crew: round-2 review fix 65477c0 task: Add open/all selector to /crew TUI picker 9189ef7 Merge branch 'task/add-open-all-selector-to-crew-tu-9e8cc0' into feat/crew-open-all-toggle ba9c12d crew: reconcile the picker onto config's source helpers ea05bc0 crew: a chosen family counts as an answered crew e1a037e Merge remote-tracking branch 'origin/dev' into feat/crew-open-all-toggle f6c2924 crew: the open table takes the picks we landed on eff44b5 docs: the change entry carries the open-table move and the family gate 71ce9be crew: the family reaches the fallback, the settings skin, and the row's line b8ca5f5 crew: round-1 review fixes on the new table 8db5708 crew: round-2 review fixes ce9759e crew: round-3 review fixes 956e1f5 crew: round-4 review fixes 37ad27f crew: fixes from the first Opus round 6ffb958 crew: the fixes from the Opus confirmation round 72b0274 crew: the comments the atomic write left behind 70d0e20 crew: round-four fixes from the Opus review 234300e Merge branch 'dev' into feat/crew-open-all-toggle 894292f crew: round-five fixes from the Opus review fba77f9 An answered landing carries its answer's fate when it is raised again, and an in-flight settle holds the question down (#1077) e694450 Changelog entry for the landing-answer fate (#1086) 64ab7ea crew: round-six fixes from the Opus review 0700164 crew: round-seven fixes from the Opus review af09aa8 The review round's four findings: claim ownership, decider changes, recordable answers, plain words c24af02 crew: round-eight fixes from the Opus review 289d372 The tests the landing's answer carries: fate, hold-down, redraw, claim doors 7e38346 The take-down comes before every mint, and the tui3 walk reads the newest card dbe1be0 The review rounds' last word: the release owns its claim, and the docs say what the code does 4cc4945 The Opus review: a release owns its generation, and every failed round still says its word a5cce0d The done card says who is deciding, so the clause is a duplication, not the fact 6bd276e Merge fix/1077-landing-reraise into santos/dev 2710169 Merge feat/crew-open-all-toggle into santos/dev b459399 Merge fix/question-answer-box-caret-keys into santos/dev a384920 Merge codex/recovery-evidence into santos/dev dc22e64 cmd/codeaf: the role-door tests read the shipped mastermind instead of a copy of it 39f528f release: the pin-example check reads the guide the examples moved to 6439d3c session, tui3: gofmt the three files santos/dev merged unformatted 8540379 tui3: a question's answer box kills to the end of the line on ctrl+k d93ec61 session: the late-attach proposal test holds the work until the replay is read a81ead4 session: the landing-fate tests read today's clock instead of a fixed date 8fe4fff provider: the retry-avoid list rides the call's context into the knobs a266da3 provider: the retry-avoid veto narrows the wire through one field law 197d893 exec: a node retry asks the router to avoid the lanes that failed it 2d02cc0 provider: the set-servable law's doc comment keeps its paragraph break e1d0e75 exec: the retry test names its helper and spells its wall in time units e7d65a5 docs: the change note for the retry that avoids the failed upstream 11decbd Merge fix/provider-failover into santos/dev c099a51 Merge dev into santos/dev e47d92b provider, exec: the lane a failure names is a wire fact provider reads (#1105) 396be97 Merge dev into santos/dev 3b97f50 Merge dev into santos/dev ea3b5c9 telemetry: the send path drops events that cannot name their version 573b288 cmd/codeaf: keep smoke runs from sending usage counts e8d627c docs: the change note for the usage-count audit fixes 11bec8d chat: a hosted session's usage counts are read off the events it receives b9d75b3 chat: the hosted-count tee is tested against the tally it must produce 39fa08d telemetry: stamp a version in the lifecycle tests 681e2ad chat: count the hosted boot agent once, and conversations opened beside 825ef2c connect, settings: named, multiple, switchable custom connections (#1092) f4d3f9a Merge branch 'dev' into fix/telemetry-audit 76fec37 ci: the Model Pool mirror workflow and the signature check it runs 2fb296b crew: Pareto crewing, the learned picker and the Model Pool (#1093) a065ebb Merge remote-tracking branch 'origin/dev' into santos/dev 80ac250 Merge remote-tracking branch 'origin/feat/pool-mirror-workflow' into santos/dev 6092393 Merge remote-tracking branch 'origin/fix/telemetry-audit' into santos/dev ef808dd session: a decision card under --yolo takes its default (#1117) 70a9e1f session: a task's thread stops its parts before it closes, and a machinery cut says so (#1118) c4df8f3 crew: an auto seat's rung names the pick that ran, once, for both doors (#1119) a9fcf9b crew: a bare auto row under picked from = catalog reads the catalog's figures alone (#1120) 13be0dc relay: accept the exec and run doors, not only task and do (#1121) 90f29ae changes: name the #1120 note by its PR and stamp the pr field 0b77926 do: seat from the settings the run will use (#1122) 32148d8 changes: stamp pr: 1120 on the #1120 note 113ed62 pool: a launch's start-up errands stop when the process closes (#1124) 6c98ddc verify, codeaf: a launch compiles fewer patterns and a surface holds fewer Ps (#1125) 50fe6a3 pool: the min_installs floor counts installs on the client (#1127) 076cde8 relay: fold a resubmitted row once by its nonce (#1128) 8339ae7 relay: carry the acceptable metric beside role_quality (#1129) 0367c44 outbox: a refused row leaves the outbox and the rest of its batch is sent (#1130) 09aecd2 relay: the index holds only the cells that meet the min_installs floor (#1131) ae7c05d outbox: a Send compacts the file to the rows it still holds (#1133) 9e24f72 pool: the errand tracker's critical sections unlock from a defer (#1134) 358a569 relay: fold a submit batch with one read and one write per distinct cell and day (#1136) a1d2eb1 pool: judge landed-but-unjudged runs on the next chat start (#1132) 3c67228 verify: take the finished-tree check at a project cloned into a subdirectory (#1135) 263625b exec: a headless run leaves a pending judge record at its tail (#1137) 8be373d run: the headless task door leaves a pending judge record (#1138) a336b24 do: leave a pending landing for the Model Pool's judge (#1139) 8820a56 cmd/codeaf: one readPendingRows test helper, not two (#1140) 49760fb pool: show and verify print both metrics the index carries (#1141) 6eaeb25 pool: status shows the pending judge records and the last sweep (#1142) 7c00b5f codeaf: a test's crash fixture stays in a profile the test owns (#1145) fc2eb35 manual: the status row's ledger is the tree's, not the conversation's (#1143) a06b53a test: pin the delivery gate over a grown job root (#1147) 7231347 resident: the wall refuses a first replan round it cannot hold (#1144) 5e25755 cmd/codeaf: the package's test floor clears a profile the environment named 4dd1c56 Revert "cmd/codeaf: the package's test floor clears a profile the environment named" 9075f86 pool: the seed index is regenerated from the relay by seedgen (#1148) a5c44f3 pool: show --cells lists the held index's cells with installs and dims (#1149) 8259967 cmd/codeaf: the package test floor clears a profile the environment named (#1150) 81568aa session: report gitignored build products a run leaves, without gating on them (#1152) da49105 internal/tui3: the opening hint test owns its profile and pins both doors 72de3bc docs/changes: #1151 — the opening hint test owns its profile 499083d Revert "docs/changes: #1151 — the opening hint test owns its profile" beb31ec Revert "internal/tui3: the opening hint test owns its profile and pins both doors" 25b8b7d version: an unstamped binary names the condition, not a Makefile target (#1151) c833b42 pool: a dropped row keeps the relay's reason and status shows it (#1154) cbb7d6d processgroup: verify a job group's identity before signalling it (#1155) efe498e internal/tui3: the opening hint test owns its profile and pins both doors (#1153) 17b3b0e do: a continuation continues the plan it has instead of re-planning (#1156) 22cf3ce changes: correct the #1155 and #1156 notes' pr fields (#1157) 8e85b0f cmd/codeaf: a surface runs under a soft memory limit drawn from the machine (#1158) ef1e927 task: status row accounting (#1159) 44f572e pool: status's index line says what this run's fetch did to the cache (#1161) 3600fc9 pool: the pool's copy of a seat's id is the bare vendor/id (#1163) a2ebd13 cmd/codeaf: no test can push pool rows to the default relay (#1164) 4fb7f05 docs: the road a chat door bash push took under --yolo (#1160) 69219a1 cmd/codeaf: the soft memory limit is the smallest real bound, not the host s memory (#1162) 2b155b4 relay: bound judge severity, clamp adjusted scores, publish mean and sd on one scale (#1165) 2fb5532 relay: purge fixture vendors and refuse them at the door (#1167) 5750418 exec: a job's shell cannot reach the tmux server hosting codeaf (#1166) eb7b465 internal/session: an unattended run may not move a branch it did not create (#1168) 80f7706 pool: status says the identity, the judged total and that nothing has landed (#1169) 1cb7333 exec: an exec run's worker spend reaches the usage ledger (#1170) 96bb940 changes: the #1169 note's title parses and reads as one line (#1172) 627236d config: the task door honors a stored crew word, and a pin survives the learned pick (#1171) 593092b internal/tui3: a test may not read a profile it did not create (#1173) ad8be1e session: a landing card under --yolo takes its default instead of parking the run (#1174) 03d49a6 gitignore: the .furrow ids the engine writes into a workspace (#1175) 46edbdd internal/tui3: gofmt the profile-law helpers from #1173 (#1176) 3179e36 relay: ALLOWED_VENDORS names the catalog's vendors and codeaf (#1177) 397a145 docs: why a settled /task leaves commits on task/<slug>, not the worktree branch (#1178) 915ff3a pool: regenerate the seed index from the relay's first clean publish (#1180) d9b4243 cmd/codeaf: the model warm stops when the process closes (#1179) bd2dcf3 session: the auditor's calls say they are the auditor's and which node they check (#1181) c6ed47c task: json unverified branch (#1182) 360352a session: a settle turn runs under the checker's own bound, not the run's wall (#1183) 814e1af session: the tasks text and record line name a failed/unverified node's kept branch and verdict (#1184) 7c25a26 internal/session: the identical-effects test stops riding the turn guard (#1185) 6e7d0ed cmd/codeaf: exec and run envelopes name a non-verified node's kept branch and verdict (#1186) f4079d7 session: bound a worker's park on a promoted command (#1187) 994689f docs: the model pool runbook names the Workers Paid plan and what it costs (#1188) c315be1 docs: the runbook's plan line says metered, not capped, and nothing more (#1189) 2e80c60 internal/tui3: the status word says working while a task subtree turns (#1191) 99363ca session: bound a job subtree's CPU and process count (#1190) 6db5125 docs: what the audit check seat can execute, and where that boundary is set (#1192) 649bb4b cmd/codeaf: the pool start-up test empties the CI word it is not about 053e6a9 processgroup: a zombie leader does not keep a job's group alive b4e66f5 docs/changes: the entry for #1194 Co-Authored-By: Santosh kumar <29346072+santoshkumarradha@users.noreply.github.com> Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Merged into
Nothing on One observation from the smoke, not a blocker: |
The spine draws its samples in concurrent goroutines by design, and two tests counted the fake client's calls with a plain int. Under load an increment could be lost, so no sample saw the third call and the draw read 3,3,3. The counter is now atomic.Int64 in levels_test.go and named_test.go; every assertion is unchanged. Test-only. Evidence (Spark): -race on the unfixed tree reports the race at levels_test.go:87 from spineWithProgress goroutines, product clean; after the fix go test ./internal/plan -race -count=200 ok; build, changes check, guard and namelaw green on 65249bf, tree aa25dee before and after.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…nd (#1290) A firing copied the conversation's approval policy, which on a fresh install prompts a person, while also being told it was inside a task where no person exists. Every decision came back a refusal. What survived was the read-only lift, so a watch could not run one shell command, not even one the person had explicitly allowed. A real watch fired thirty-nine times over four days, spent real money and did nothing. A firing now carries the policy a task node carries: allow everything except approval's critical floor. The floor still turns an allow into a prompt for the shapes that destroy a disk or drop the machine, and a prompt with nobody to ask is a refusal the firing can read and report. The calls that act in the person's name outside this machine stay refused, and a bash call whose arguments cannot be read stays refused. The owner decided this on 2026-09-20, after being shown the shape and what it widens. The probe road is deliberately untouched: it is a different function with a different risk, and a watch's probe command never meets this gate at all.
A conversation whose sub-harness had stopped on a question reported that it was working. The question was registered and open, but the reading that decides whether a person is needed never looked at that lane, so no row appeared on home, no mark was drawn, and nothing moved until somebody happened to open the conversation. Work stopped in silence. Two halves, and either alone is worse than neither. The reading now counts that lane beside the others. And the lane banks its question at the desk the sentence is read from, rather than only raising it, so the row carries what is being asked instead of an attention mark with nothing under it. Three sibling lanes share the shape and are deliberately left: sign-in, the sub-harness offer and the harness design card all raise without banking, so each draws a mark with no sentence today. They belong to a change about that desk, and a fix that quietly repaired four lanes while claiming one would be a fix nobody could review. The reading also split along the seam its own comments had drawn. One part reads every lane under the lock and hands back what the answer is made of; the other decides which answer a person should read first. The lock discipline is unchanged and no lane's behaviour moved.
) A row that was live when the process went away came back stamped failed and stopped, and the run's row said it had ended when codeaf closed. Two untrue things in one line: that the work went wrong, and that somebody ended it. It now reads interrupted, which means nothing is driving it and everything it did is kept. The word lives on the reading rather than in the surfaces, so one rung on the state ladder and one on the presence ladder give the tier, the mark, the two answers and the sentence, and no surface grows a table of its own. Continuing sits in the person's tier and is never the model's answer, because continuing spends money. The ask and its two answers are carried here rather than in the cell that draws them, because a your-call row is required by its own type to carry an ask, and splitting it would ship a card with no answers for one gate cycle. The old sentence is deleted rather than left unused, and the manual page that quoted it is corrected in the same change. A known window while the piece that continues work is still to come: a conversation that genuinely ends cuts its run, and a reopen still stamps that run failed. That is named rather than left to be discovered. The const block is reformatted here because the new sentences widened it. It reached a gate unformatted because the check that should have caught it read an exit code from a tool that reports by printing.
…in (#1298) A run's stored row carried its number, title, state, cost and timings, and nothing about where its work is. No folder, no branch, no ground. After a reopen the product knew a run had existed and had no idea where to look for what it did. The row now carries the copy, and the road that makes a copy is never asked twice. That road mints a new branch name with a random suffix on every call and clears the directory it is handed, which is safe only because the sole thing that can be sitting there is that run's own wreckage. Called a second time for a run being resumed it would delete the work and hand back an empty branch that looks correct. A run with no copy recorded is refused, in words naming what is missing, and nothing on that road may carve a directory, cut a branch or derive a path. Every row on disk today predates this field, so that refusal is the answer those runs get forever rather than a stopgap. A copy gone from disk is refused too, naming the branch, because the branch is the one thing a person can still act on. The directory is derived from the run's number. The branch is not: it is random and nothing else writes it down. That asymmetry is the whole reason this record exists, and a reader who believes both are reconstructible will delete this change. Every publish replaces the row and only the first knows where the work is, so the carry-forward lives inside the one function every publisher goes through rather than in its callers. A notice naming a copy of its own still wins, as the more recent reading.
…give (#1304) The page said an interrupted row offers two answers, continue it or leave it. Nothing draws them. There are three readers of a task's two answers in the tree and a run's row reaches none of them: it never enters the index the needs panel reads, it never holds the state the landing question requires, and it never matches the question the record card looks for. What is true stays. The row does wear the asking mark and does wait for a person, through the surface's own node rather than through the record, so that clause is kept rather than softened away with the rest. In place of the promise the page states the limit: nothing picks an interrupted run up yet, no key, command or background pass does, and nothing ever will without being asked. That is the sentence a person came to the page for.
* task: benchmark methodology Co-Authored-By: codeaf <agentfield-bot@users.noreply.github.com> * readme: the one-binary claim is measured, not asserted Startup, on-disk footprint and idle memory against six other agent CLIs, placed next to the sentence they substantiate. Memory is PSS because the two-process design shares one binary's text; the metric the fastest competitor wins is in the table rather than only in the linked write-up. Co-Authored-By: codeaf <agentfield-bot@users.noreply.github.com> * readme: cut an opening sentence the window section already makes, and a badge The second sentence of the opening paragraph restated the one-window-and-tasks framing that "One window for every project" and "What a factory is" carry in full. The model-pool badge repeated a link the section's own prose and the design document already give. Kept as its own commit so the cuts can be dropped without losing the measurements above. Co-Authored-By: codeaf <agentfield-bot@users.noreply.github.com> * docs, readme: the footprint method, the full named table, and a five-row summary The cell wrote measure-cli.sh but no methodology, and a three-row table that omitted the two strongest honest rows while keeping two we lose. This adds docs/benchmarks/README.md (method, the four rules the numbers depend on, and the known limits including the wakeup figure being unusable), docs/benchmarks/results-2026-09-17.md (the full table with every CLI named, including the three rows where another binary beats this one and the row where it could not be measured at all), and replaces the README summary with five rows. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * changes: note the footprint table entry for #1126 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * readme: restore the hero block the footprint section displaced My own edit script matched from the new heading to the next ## and so removed everything between, which is the hero: the early-preview notice with its Discord and issue links, the overview screenshot and its alt text, the demo video and its caption. They are restored untouched and the footprint section now sits between them and Install, which is where it belongs anyway. The em dash in the closing sentence is gone, and the table ranges read x to y rather than using a dash. The two listed README cuts are unchanged and remain in their own commit (cbc1d0d). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * readme: leave the top-level README as it was; the footprint table stays under docs/benchmarks Santosh reviewed the README hunk and asked for it to go. The method, the script and the full named table remain in docs/benchmarks/ and the change note now says so. * docs/benchmarks: the results file, not the README, is the script's output * changes: name the #1126 note for what it notes * docs/benchmarks: record the machine's load average around every timed phase load1/5/15 land in phase=meta, and again immediately before and after the startup and idle windows, read from /proc/loadavg with a builtin read. Telemetry only: no default changes, no new dependency. Co-Authored-By: codeaf <agentfield-bot@users.noreply.github.com> * docs/benchmarks: the README now says what the script does and how to invoke it The example invocation was flags the script does not have (--name/--home parse as NAME and HOME), cold start was documented as best-of-N with no word of the discarded warm-ups or the warm cache behind it, and the README claimed every table in the results file was this script's output when the on-disk and one-turn tables are not. Load recording documented. Co-Authored-By: codeaf <agentfield-bot@users.noreply.github.com> * docs/benchmarks: the method review — per-column verdicts against the competitor test Three columns fail the read (version rows contradicted by the box, on-disk rule stated nowhere and unreproducible, one-turn sampler uncommitted); the startup, frame, idle and strace columns hold with caveats. Facts 3 and 4 caveated, not invalidating. Evidence named for everything still open. Co-Authored-By: codeaf <agentfield-bot@users.noreply.github.com> * docs/benchmarks: the rerun that tests the review, and what it settles The method review above was taken by reading. This adds the measuring: all seven CLIs again in one session on a quiet box, at ONE build for every column (4f002ca2), with the one-minute load recorded beside every figure and sampled six times across a full minute before the run began. Startup and first frame stand and are published with the load beside them. Several figures move a long way from 2026-09-17 — claude's first frame 572 to 429 ms, cursor-agent's 1,298 to 592, pi's startup 330-360 to 146, omp's first frame 400 to 1,254 the other way — which is the load finding demonstrated rather than argued. The idle memory column's verdict MOVES, from "fair with caveat" to "cannot decide, and not reproducible as it stands". Every one of the seven measured procs=1, where the table has CodeAF at 2 and cursor-agent at 5. It cuts both ways and is nobody's win: CodeAF's PSS came out 38.7 MB against 66.4, and cursor-agent's 194.4 against 412.7. Three explanations were tested and killed — not the sweep or the choice of HOME (sweep_home is teardown only, and a controlled pair under a dedicated home and under the operator's own both gave procs=1), not a product change (cursor-agent is the same version string), and not a different script (the script was committed before the results). What is left is the invocations, which were never recorded. Also records what each CLI actually resolves to. opencode is not on a login PATH at all and exists as two different products; pi is a JavaScript bundle; codex and cursor-agent resolve to different binaries depending on how the measuring shell started. The header's own two-build split needs no caveat: the package-init changes have landed, so measuring at one build removes it. The run's log and the rig it was taken with are committed beside the note, so the next person to ask this question starts from a recorded rig rather than from a reconstruction. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * benchmarks: make CLI teardown workspace-specific * docs: correct defective memory measurement * benchmarks: split teardown survivor accounting * docs: repair benchmark method review prose * docs: record c245 teardown accounting checks * benchmarks: retain launched process ancestry * benchmarks: state which processes the idle figure sums The script sums the processes of the launched tree that are alive at the last sample of the idle window, and the README did not say so. A reader comparing two CLIs could not tell whether a helper that exited during the window was charged or not. The rule is stated with its reason: a steady-state figure must not depend on how long the window was, which is what summing every process ever seen would produce. The transient cost is reported in peak RSS instead, and procs_seen is named beside procs so a CLI that churns helpers is visible rather than hidden behind a single count. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * docs: the 2026-09-20 footprint tables, their drivers, and the hero figure Co-Authored-By: codeaf <agentfield-bot@users.noreply.github.com> * docs: classify benchmarks under docs/benchmarks/performance Co-Authored-By: codeaf <agentfield-bot@users.noreply.github.com> * docs: sharper performance benchmark gist Co-Authored-By: codeaf <agentfield-bot@users.noreply.github.com> * docs: neutral review voice, explicit multiples in the gist Co-Authored-By: codeaf <agentfield-bot@users.noreply.github.com> * docs: gist as bullets Co-Authored-By: codeaf <agentfield-bot@users.noreply.github.com> --------- Co-authored-by: codeaf <agentfield-bot@users.noreply.github.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
* docs: resume cost joins the footprint benchmark Co-Authored-By: codeaf <agentfield-bot@users.noreply.github.com> * docs: change note for the resume table Co-Authored-By: codeaf <agentfield-bot@users.noreply.github.com> * docs: the quick table joins the gist Co-Authored-By: codeaf <agentfield-bot@users.noreply.github.com> * docs: table outside the list, blank lines around it Co-Authored-By: codeaf <agentfield-bot@users.noreply.github.com> --------- Co-authored-by: codeaf <agentfield-bot@users.noreply.github.com>
…y its work is already in An interrupted run's store holds every step it took and, since the copy record landed, its row knows where that work is. This is the one door that starts work on it again: it adopts the recorded working copy and the store already on disk, hands both to the same engine under the same seats, and lets the supervisor's ordinary next pass release the claims whose owner is gone. No resume machinery, no second scheduler. IT HAS NO CALLER, ON PURPOSE. Continuing seats workers and spends money, and a door that spends money reachable before anything means to reach it is not a smaller version of the feature but a worse thing than no door. The card that offers the choice is the next change; until it lands a person cannot reach this from any surface. The refusals name what is in the way: a run that never stopped, a number with no run behind it, a run that already said its last word, and a copy that was never written down or is gone. The refusal for a run with no copy is the SAME sentence the row shows where the offer would otherwise be, taken from one constant, so the reading and the answer cannot drift into two spellings of one fact. The reading gains that sentence as a sentence rather than as a flag, and the run spec is now built in one place so the start road and this door cannot diverge the day a cap moves. Every refusal is proved twice: that it said no in the person's words, and that nothing started. The test that matters puts a worker's file in a run's copy, carries the run on, and reads the file back: the road this door could have taken instead clears that directory (#1298 shows it doing so). Fourth cell of the settled close-window design (#1224). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ne tested form Three shapes of proof step were each written more than once and each was incapable of reporting the failure it was checking for. gofmt -l prints the files it would reformat and exits 0 whether it printed any or none, so a step reading its exit code reports green on every tree that has ever existed. A pipeline ending in a reader hands back the reader's status, so `cmd 2>&1 | tail -25; echo "exit=$?"` printed exit=0 underneath a screen of FAIL, which does not merely hide a red but manufactures a green directly below the evidence. And a -run pattern is a second copy of the list of tests in a file: when the two drift, go test answers a filter matching nothing with ok, because from its side nothing failed, so a named test that never ran reads exactly like one that passed. scripts/proof.sh is the one written form of all three. THE ACCEPTANCE IS THE FAILING ARM: internal/ci/prooflib_test.go runs each function twice, once where the thing it checks is sound and once where it is broken, and each broken arm also pins what the plain command says about the same situation, because in all three cases the obvious command reports success. A guard against invisible failure that has only ever been seen passing is the thing it was written to prevent, wearing its own name. No caller is converted here, on purpose. If the library is right the conversions are mechanical; if it is wrong, that is better learned on one caller than on all of them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…e caret parks where you type (#1321) * task: Implement fzf v2 fuzzy matcher universally Co-Authored-By: codeaf <agentfield-bot@users.noreply.github.com> * fuzzy: land the remaining surface cutover (autonomy, connections, memory, folder search, rewind, registry) and manual pages Co-Authored-By: codeaf <agentfield-bot@users.noreply.github.com> * fuzzy: state the gap price the code and tests charge fzf's own algo.go charges scoreGapStart (3) for the first skipped byte and scoreGapExtension (1) for each byte after it in the same gap; the const-block comment claimed the first byte paid extension too, which the alignment, the gap-price test, and fzf's source all contradict. Co-Authored-By: codeaf <agentfield-bot@users.noreply.github.com> * task: Fuzzy match highlighting across the search surfaces Co-Authored-By: codeaf <agentfield-bot@users.noreply.github.com> * task: Fix the terminal cursor park for the settings search box Co-Authored-By: codeaf <agentfield-bot@users.noreply.github.com> * changelog: the 1321 change entries, renumbered from the task placeholders, with the caret entry Co-Authored-By: codeaf <agentfield-bot@users.noreply.github.com> --------- Co-authored-by: codeaf <agentfield-bot@users.noreply.github.com>
…es the model (#1325) * exec, session: the commit co-author links to the CodeAF account, and assisted-by names the model The co-author address gains the account's numeric id, 267109073+, the form GitHub renders as a link with the account's avatar, and a new Assisted-by line above it names the model that wrote the commit, so git interpret-trailers can answer who typed it beyond the account. The Assisted-by line is filled at the belt render, the one surface that knows the session's configured model; the leaf loop's standing contract carries the co-author alone, as before, because exec is handed facts about the model and never its name. The manual pages show both lines, and the fixed arm's prefix waiver rises by the 162 bytes the wider belt fact costs. Assisted-by: CodeAF (z-ai/glm-5.3) Co-Authored-By: CodeAF <267109073+agentfield-bot@users.noreply.github.com> * changelog: the co-author links to the CodeAF account, and assisted-by names the model --------- Co-authored-by: CodeAF <267109073+agentfield-bot@users.noreply.github.com>
|
@AbirAbbas heads up, not a review request yet: this branch is now a closed slice at Evidence on that exact head, fresh clone, on Spark:
Landed since the last pass, newest first:
The PR stays in draft on purpose. Work from here goes on the next shared branch so this slice stops growing while it is being read. Say if you would rather have it split before you start. |
…1329) agentfield.ai/github redirects to Agent-Field/agentfield, so every pull request, issue and comment codeaf drafted pointed a reader at the wrong repository. agentfield.ai/github/codeaf redirects to Agent-Field/CodeAF and is already serving, so the three attribution constants, their fixtures and the two manual pages take the longer path. The utm parameters and the rest of each line are unchanged.
The squash of #1329 carried the code and left its entry behind.
) A landing question is raised for unverified and retired for every other state, so a failed node has no question object and never had one. The reading was inventing one out of the ending's shape alone, and a row nobody was waiting on stood in the needs-you group for the rest of the session. Attention goes; the tier, the word, the reason and the take-it-anyway answers stay.
…id for The refactor that made GenerateImage one road for the belt's tool and the command line's image door (the slice landing as #1108) dropped the guard the belt-only tool had carried since it was written: an empty or blank prompt was answered "Invalid arguments: prompt is required" and cost nothing. Without it the request went to the provider, which billed the call and answered with an image that could not be read, and the tool reported that as the provider's fault ("returned an unreadable image"). The guard is back, on the shared road so both doors refuse the same call the same way, beside the model and reference checks that already refuse before the request is sent. The video and music doors never lost theirs. TestGenerateImageRefusesAnEmptyPromptAndCostsNothing pins it: a missing prompt and a prompt of spaces are both tool errors naming the prompt, and the fake painter sees no generation. It fails on the slice's head without the guard. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
AbirAbbas
left a comment
There was a problem hiding this comment.
Reviewed and verified 2026-09-21: gates green locally and in CI, the default road checked live on both roads against a dev baseline, the one regression the slice introduced fixed on the branch with a contract test. Evidence and the full write-up are in the review ledger.
Integration branch
santos/devintodev. Draft: it is the running index of what the branch carries, and it stays a draft until the worker harness is complete, the independent end-to-end pass on Spark is green, and Santosh has tested it himself.State
dev. Everything through docs: what the audit check seat can execute, and where that boundary is set #1192 already reacheddevas santos/dev lands on dev: crew family, Pareto crewing, the Model Pool, custom connections (#1108) #1194 on 2026-09-18, anddevhas been merged back each time it moved (ci: Model Pool mirror workflow (signed index onto the model-pool branch) #1116 mirror workflow, chat: the unconnected custom row on /connect keeps its vendored name #1195 /connect custom row, docs/changes: v0.3.0 rolled up into CHANGELOG.md #1196 v0.3.0 changelog).make checkon Spark, fresh clone, on the exact commit. The check has cross-compiled every release target since build: cross-compile the shipped platforms in make check #1254.CODEAF_TASK_BELT=bashis set, so the default road does not move.The worker harness
One loop under
/taskandcodeaf do, with a plan store per run, a plan seat, a work seat, a check seat, and a review round after each piece of work (#1109)./task,codeaf do, and a task the chat starts by itself all take the same road; a landing wakes no model turn, and a reply comes only when an answer is owed (The chat's role: a landing speaks only when an answer is owed #1205).--check-model,CODEAF_CHECK_MODEL, a pinned seat, then the profile (a belt check runs on the crew checking seat, not the thinking seat #1207). A declared check is read the way a shell reads its quotes (session: a check is one command as the shell reads its quotes, its refusal says what passes, and side-by-side calls are one attempt #1215).codeaf dorun whose root finished itself still gets its review (fix(run): a self-finished codeaf do run seats its review before it ends #1233, run: regression test for seating the check after a self-finished worker returns #1243); a parked task is finished only by a worker woken for it (A parked task is finished only by a worker woken for it #1271).Stopping and limits
A person's stop reaches a run. The stop ends the run's task and everything open under it in one write, cuts the run's context, keeps the work on the run's own branch, puts nothing into the person's folder, and buys no model turn; ctrl+c is read above a page that is loading or open (fix: a person's stop reaches a run #1250). A stopped task reads stopped wherever its state word is drawn (fix: a task you stopped reads stopped wherever its state word is drawn #1258).
A time limit ends a run. A run is handed what is left of the conversation's time; work in flight is ended and its endings are absorbed (run: a time limit a person sets ends a run by the same road as the cost limit #1262).
A dollar limit holds while a worker is still working. A worker tells its run what it has banked as each call is paid for, without ever waiting on the run; a dollar is counted once, and what a run counts as spent never goes down (A run's dollar limit holds while a worker is still working #1268).
A run's dollars reach the conversation's total. The run hands its owner its running total whenever it rises, with or without a dollar limit, and the conversation closes on the run's final figure before any ending splits off, so every ending counts once (session, run: a run's dollars reach the conversation's own total #1280).
An ending a person caused is not a fault. A run ended by a limit says which one,
a time limit you set stopped itora dollar limit you set stopped it, with no fault colouring; the first limit reached names the ending, the tasks that ending cut read the same way, and a task that failed by itself keeps its own reason (run, session: an ending a person caused is not a fault, and it names the limit that caused it #1279).A run is handed what is left. A run's dollar ceiling is the smaller of the conversation's dollar limits, including one typed on the command line, less what the conversation has already spent, so a second run gets the remainder after the first (session: a run is handed what is left of every dollar limit #1281).
A cancelled command is ended by the call that ran it. A cancel that arrived as a command started could leave it running under no parent; the cancel arm now sends the kill itself unless the call was adopted or already reaped (exec/bare: the arm that ends a cancelled call's wait ends its command #1282).
A worker that has stopped making progress is told once, then ended. The same command coming back with the same answer, with nothing moving under the worker's own task, brings one note from the belt saying what the worker can do; three more identical steps end the task with a reason a person can read. A task blocked on another task is parked, not ended (run: a worker that has stopped making progress ends, by an observable property #1266).
The task page and the rail
The engine host and sign-in
The profile
config.jsonthat nothing reads are said once, in the conversation, and never for a key the product itself writes or retired (config: report unread profile config keys once at load #1223, chat: name unread config.json keys once before defaults apply #1239, config: unread notice skips keys the product itself retired #1245).Nothing keeps writing after the process closes
Tests and tooling
scripts/(scripts: a repeatable hosted drive of a run on the real binary #1241).Also on the branch
Landings
santos/devinternal/lanecleared by mechanism, not by rerunStill to come before this leaves draft
Already on
devthrough #1194, kept for the recordWhat follows reached
devon 2026-09-18 as #1194 and is unchanged since.What a person gets
models.crew.source = open|all(defaultall), or the open/all switch in/crew.santos/dev(#1073)auto./crew catalog, ormodels.crew.pick = catalog.santos/dev(#1093, squash 2fb296b)table,catalog,learn/crew table|catalog|learn,models.crew.pick.santos/dev(#1093, squash 2fb296b)/taskrun an independent judge scores every seat (billed to ajudgeseat). Scores go to your own sheet and feed the picker next time, blended with the pool by observation count, so your own runs improve your own picks first. Starts from a seed built from 145 real runs, so learning works on day one. A seat you type by hand is judged too.pick = learn.codeaf pool showlists what the picker knows.santos/dev(#1093, squash 2fb296b)model_pool on|read|off(defaulton, notice shown once).codeaf pool show|status|verify [--json].santos/dev(#1093, squash 2fb296b)relay/with a runbook; it is live athttps://codeaf.agentfield.ai/pool. The signed index is mirrored to themodel-poolbranch of this repo so anyone can watch it update. A team can run its own private relay with its own key (CODEAF_MODEL_POOL_RELAY_URL,_MIRROR_URL,_PUBLIC_KEY).santos/dev(#1093, squash 2fb296b)docs/design/model-pool/pareto-crewing.pdf("Pareto Crewing"): the objective, estimator and picker, with figures from real runs.santos/dev(#1093, squash 2fb296b)/modelgroups models under each connection's name. Switching onto a keyless default service is refused with a reason./connect→ Custom OpenAI-compatible API;/settings→ Providers → add / edit / active connection.santos/dev(#1092, squash 825ef2c; Santosh e2e-tested locally against a local OpenAI-compatible proxy)/taskanddo/taskdoor andcodeaf do.Bug fixes on the branch (question answer-box keys, landing answer fate, retry avoiding the failed upstream, recovery evidence, taxonomy lane read, and, with #1092, mid-session
/connectnow reaching the live conversation on the engine road, a pre-existing hole) are not listed above; each has its own change note underdocs/changes/unreleased/.Known limits, stated on purpose
/taskdoor only;codeaf do,askand remote sessions do not feed the pool yet.codeaf pool verifypulls a fresh copy, read at the next start.Relay status
Live at
https://codeaf.agentfield.ai/pool(healthz 200, index signed,codeaf pool verifygood). Themodel-poolbranch exists and carries the current signed index (refreshed hourly by a stand-in job until #1116 puts the workflow ondev). The pool is primed with the same measured runs the embedded seed encodes, so the published index carries real cells from day one.End-to-end pass on Spark (independent session, done)
All 12 steps pass on #1093's head (cf4ea35; final fd29d79 differs by a runbook sentence). Report:
spark:~/src/e2e-learn-2026-09-17.mdwithKNOWN-LIMITS.mdandevidence/INDEX.mdbeside it; 18 capped runs, about $26.learn, judged tasks, own sheet + outbox flushedreadandoffsend nothing/modeloverride underlearnis still judgedauto/catalog/learn seats resolve on headless doors/crewchooser and/settingspool row with noticecodeaf models,--refresh, daily cachedo/exec under a learn crewFollow-ups from the e2e, now on
santos/dev: a task's thread stops its parts before closing and a machinery cut records its reason (#1118); a decision card under--yolotakes its default (#1117); the auto crew row shows the rung it actually resolved to (#1119); a bareautorow underpicked from = catalogreads the catalog's figures alone (#1120).codeaf doseats from the settings the run will use, so a fresh profile with the key in the environment reads the catalog, not the table (#1122); the relay accepts the exec and run doors (#1121); a launch's pool errands stop when the process closes instead of writing into a closed profile (#1124); a launch compilesinternal/verify's patterns on first use and the engine host runs on a capped scheduler (#1125); the client'smin_installsfloor counts installs, as the relay's does (#1127); the relay folds a retried batch once by its nonce (#1128), carries anacceptablemetric beside the judge score (#1129), publishes only cells that meet the floor (#1131) and writes once per cell per batch (#1136); a refused row leaves the outbox and the file is compacted (#1130, #1133); the pool errand tracker's critical sections unlock from a defer (#1134); a run a process death left unjudged, and any headless door's landing, is judged on the next chat start (#1132). the finished-tree check reads a project cloned into a subdirectory (#1135); the exec, run and do doors leave a pending record for the sweep (#1137, #1138, #1139); the wall admits a first round it cannot cost and refuses an overrun it cannot hold, so a longcodeaf dolands instead of re-planning to the wall (#1144), with the delivery gate over a grown job root pinned by a test (#1147);pool show,pool verifyandpool statusprint both metrics, the pending judge records and the last sweep (#1141, #1142); a test's crash fixture stays in a profile the test owns, and the package's test floor clears any profile the environment named, and the opening-hint test reads a profile it made and pins the greeting contract both ways (#1145, #1150, #1153), and tui3's package law makes every surface-building helper name a profile of its own (#1173); the manual's status row says whose ledger it is (#1143); the seed index is regenerated from the live relay by one in-repo command, so a fresh install's fallback is a verified copy of the pool (#1148);pool show --cellslists the held index's cells with their installs and dims (#1149); a landing that leaves gitignored build products behind stays complete and the reconciled row names them (#1152);codeaf versionon an unstamped binary names the condition, no.gitdirectory for the toolchain to read, instead of blaming a Makefile target (#1151).pool statussays when the relay dropped a row and why, instead of the row vanishing silently (#1154); a job teardown records the group leader's identity at launch and never signals a process group the kernel has since handed to someone else (#1155); acodeaf docontinuation after an overrun continues the plan it has from the recorded turns instead of re-planning from scratch (#1156); the process sets a soft memory limit of half the machine's memory, nothing below a 512 MiB floor, an explicitGOMEMLIMITuntouched, carried intoengine --daemon(#1158), and the bound is the smallest finite one of physical memory and the cgroup v2/v1 limits walked from the process's own level to the root (#1162);pool statussays when this run cached the index, so the seed-to-cache flip is visible in the run that caused it (#1161). The pool's copy of a seat's id is the bare vendor/id, so a fresh install on the default model (whose seat carries codeaf's alias marker) no longer has its first rows refused by the relay, and the judge picker's same-vendor exclusion works on it (#1163); no cmd/codeaf test can push rows to the default relay, the package floor pins a dead address (#1164); the relay bounds each judge's fitted severity to ±10, clamps every adjusted score to the rubric, publishes mean and sd on one scale and falls back to the median when spread is zero, which is what had published a cell at 103.5 (#1165); the relay can purge stored rows from a fixture vendor and refuse vendors not inALLOWED_VENDORS(#1167), withALLOWED_VENDORSset to the catalog's vendors plus codeaf (#1177, Worker version 47102a26; 624 fixture keys purged from the live store); the built-in seed is regenerated from the relay's first clean publish after the purge, 18 cells, no fixture rows (#1180); a job's shell no longer inherits the host's TMUX handle and gets a profile-owned TMUX_TMPDIR, so a command the model runs cannot kill the terminal hosting codeaf (#1166); an unattended run (--yolo, nobody to answer) is refused agit push,mergeorrebasethat would move a branch it did not create, including the branch the checkout began on, while its own task branch stays pushable and attended sessions are untouched (#1168, the road it took is in #1160's note);pool statussays the install's identity, the judged total across all doors, and "none yet" when no landing has been judged (#1169); an exec run's worker spend is minted into the usage ledger at the door, one row per run, so the status row, the cap and the pool row count it (#1170); the task door honours a storedmodels.crewword (every arm had resolved to balanced) and a pinned tier row survivespick=learninstead of being recomputed (#1171); a landing card raised on the check road under--yolotakes its default and records that the dial answered and that the check ran out of time, instead of parking a headless run forever, while conflict, shift and ground landings still park and now say so in the record (#1174); the model catalog warm is seated on the profile's start-up errand tracker so a process close joins it, instead of a warm outliving the process and writing its cache into whatever state root was current (#1179); the auditor's calls tag themselvesauditorwith the node they check, and its usage rows carry the auditor role and the task, so a ledger tells an audit call from a session turn (#1181); a headlessdo --jsonwhose node ends failed or unverified names the kept branch and the verdict in its envelope, so nobody digs through tasks.json for kept work (#1182); the settle turn a landing note wakes undertask.settle autoruns under the checker's own bound, a call ceiling and a share of the run's cap, one call for a clean tree with no declared check, and records "not settled within its bound" instead of running to the wall, which had been a one-to-two-dollar tax on most headless runs (#1183); the chat-sidetaskstext and a resumed session's record line name a failed or unverified node's kepttask/<slug>branch and its verdict word, the same two words the headless envelope carries (#1184); the identical-effects test is deterministic, its forty saves carrying distinct call signatures so the turn's repetition guard cannot end the turn and the leash is the only thing the assertion is about, which closes a margin-of-one race that had read as a load flake since #284 (#1185); a non-verifiedcodeaf execorcodeaf runnames its kept branch and verdict in its envelope through the one result-envelope seam the three headless doors share, so do, exec and run answer alike (#1186); a task worker parked on a command it started (a bash call the 30-second background clock promoted to a job) waited the node's whole allowance when the job never ended, which is what held a DOE run silent for 53 minutes under a live cap; the park now has a bound of its own, a third of the allowance, posts "the park was not settled within its bound" and hands the turn back while the command keeps running, with the diagnosis at docs/notes/yolo-task-worker-parked-on-promoted-bash.md (#1187); the model pool runbook's plan line says metered, not capped (#1188, #1189, docs only); the status row saysworkingwhile the door's task subtree turns, read from the same signal the tab strip draws from so the two cannot disagree, with the manual's screen and task-page sections moved to match (#1191); a job subtree is cut when it passes a CPU or process bound, 60% of the machine sustained for 30 s or 128 processes when nothing else bounds it, the process backstop alone under a cgroup or affinity quota, and the run learns it as "the job subtree was not settled within its bound", which is what a model that spawns infinite loops under a dollar cap had escaped (#1190); a note records what a task's audit step can execute and where that boundary is set, the declared checks plus read-only git and coreutils, which is why a brief that declares no check leaves a cautious auditor nothing it may run (#1192, docs only); the prose lexer registry loads a curated set of forty languages on first use instead of parsing all 279 of chroma's lexers at init, plain text for the rest, which takes about 3 ms off cold start and 2 MB off the binary, with chroma's files and licence carried beside the copies (#1193). Still open, PRs in progress: the footprint benchmark method and table under docs/benchmarks (#1126); Pareto crewing v2 with a model-free grader (#1123, Santosh reviews). The "task-branch merge fails 1 in 3" observation was the test driver killing runs mid-check, not a product defect.Related, not on this branch
devdirectly (must ride staging and the next main release; the website relay fix is already live). Also merged intosantos/devso the e2e covers it.devdirectly (workflow file + verifier only), so themodel-poolbranch is refreshed by Actions; until then a stand-in job on Spark refreshes it hourly. Also onsantos/dev.Before this leaves draft
santos/dev;dev, telemetry: audit fixes — hosted chat counters, no unversioned sends, silent smoke tests #1111's and ci: Model Pool mirror workflow (signed index onto the model-pool branch) #1116's branches merged on top (6092393).santos/dev.make checkon the finalsantos/devhead, on Spark — done atd39a4e308: EXIT 0, 116 packages ok, 0 failures, 0 cached, fresh clone. Pre-checks on the same head: package laws rc 0, 80 change entries all well formed,gofmt -llists nothing,go build ./...andGOOS=windows go build ./...both rc 0.Slice line
This branch is held at
d39a4e308as a reviewable slice. Two landings since the slice was first cut: the drafted-with footer links to the CodeAF repository rather than to agentfield (#1329), and a held landing offers its answer and stops demanding one (#1331).santos/dev2carries the same head and is where work goes once Abir picks this up. Work that lands after this goes on the next shared branch so the slice stops growing under review.