gitoriaLog in with ident

antcolony

All repositories: gitoria

ReadmeCodePull requestsReleasesTicketsSettings
Commita6af7883a6af7883tracker: worker box sees calendar.worldapi.org (login to copy)mrea6af7883/STATUS.md

53.0 KB

  1. # STATUS
  2. ## 2026-09-26 — a ticket waiting for a creator question is not restarted (antcolony#30) — awaiting the architect's check; LIVE CONTAINER UNCHANGED
  3. Cause: a half-done ticket goes back to `open`; its creator question is a child, and children that are questions never blocked. Fix: `lib/relations.hl` `blockReason` —
  4. a question child that is neither confirmed nor rejected → "waiting for the creator's answer on X (state)" (`next`, `run`, `work` refuse it); a rejection newer than the last session still outranks a pending question.
  5. Safety net (`lib/next.hl`): a ticket with `COLONY_MAX_STARTS_PER_HOUR` (default 4, 0 = off) session starts in the last hour is not eligible ("restart limit").
  6. Tested: `COLONY_E2E_PORT_BASE=8730 node tests/e2e.mjs` → 351 passed, 0 failed (new checks: half done + open question waits and `work` refuses; confirmed question → continues; edited the m023 check). The restart limit itself has no own e2e check.
  7. ## 2026-09-26 — sealed workers get the sibling projects their gates start (antcolony#33) — awaiting the architect's check; LIVE CONTAINER UNCHANGED
  8. Cause: the box already binds every `dependsOn` project's dev folder read-only (`lib/sandbox.hl`), but the registry listed only `hybriel` for tickets and gitoria,
  9. so ident (started by their browser gates from `../ident.worldapi.org`) was not in the box. Fix: `projects/tickets.worldapi.org.json` → dependsOn hybriel + ident;
  10. `projects/gitoria.worldapi.org.json` → hybriel + ident + tickets. Read-only, `.env` masked, no code change. Checked: `./colony box tickets.worldapi.org` now binds ident ro.
  11. Now run: inside `./colony box tickets.worldapi.org --folder <copy>` (bwrap), `node tests/browser.mjs` → 233 passed, 0 failed (ports 8712/8713); the box showed ident read-only (touch fails).
  12. Not run: gitoria's box (its folder is not on this machine).
  13. ## 2026-09-26 — a worker killed for parking is parked, not failed (antcolony#28) — awaiting the architect's check; LIVE CONTAINER UNCHANGED
  14. Cause: `running` entries are copies (a Hybriel push copies), so the park reason set at the second SIGTERM never reached the hook the end handler reads;
  15. the killed worker (exit 143) was recorded as WORK FAILED. Fix: process, phase and park reason live in `live[session]` — `lib/daemon.hl` (taken over from
  16. session s-20260926T1538-a97668) and the same fix in `lib/agent.hl`. e2e: `tests/e2e.mjs` has the antcolony#28 park/resume checks (from the earlier session).
  17. Not run: the e2e suites (they break on tickets' new projects, antcolony#31); `lib/agent.hl` only load-checked (`./colony agent` reaches its argument check).
  18. ## 2026-09-26 — only real questions reach the creator (antcolony#24) — awaiting the architect's check; LIVE CONTAINER UNCHANGED
  19. Done (README "Only real questions reach the creator"): no question limit; the controller's verdict rules on every question
  20. (ask / decided / trivial / internal / packed); dropped ones become a "Decided" line with the answer, packed ones fail the check.
  21. Files: `lib/controller.hl`, `lib/report.hl`, `templates/controller.md`, `verdict.schema.json`, `report.md`, `tests/fake-claude.mjs`, `tests/e2e.mjs`.
  22. Tested: `bin/hybriel tests/questions-test.hl` (validate / decide / filter); `COLONY_E2E_PORT_BASE=8710 node tests/e2e.mjs` → 351 passed, 0 failed (2026-09-26).
  23. Not run: a real Claude controller (only the fake one rules in tests).
  24. ## 2026-09-26 — short titles for question tickets (antcolony#23) — awaiting the architect's check; LIVE CONTAINER UNCHANGED
  25. Done: a report's `questions` entry is now `{ title, text }` — the worker writes the short title (one line, ≤ 80 characters) and it becomes the
  26. subject `Question (<ticket>): <title>`; `text` keeps the old limits (≤ 3 lines, ≤ 300 characters). An old plain string is still accepted (first line = title).
  27. Files: `lib/report.hl` (validate, `questionSubject`, `questionText`), `templates/report.schema.json`, `templates/report.md`, README, `tests/e2e.mjs`.
  28. Tested: `tests/e2e.mjs` on the stable copies (ports 8704/8705): report refusals for a title over 80 characters / a missing title, `report --post` files
  29. "Question (alpha#3): Is it small enough?" — ok. The run stopped later at m026 (EADDRINUSE: other workers' servers on 8706–8712), unrelated to this change;
  30. those and the later suites were not re-run.
  31. ## 2026-09-26 — answers of questions in the brief (antcolony#22) — awaiting the architect's check; LIVE CONTAINER UNCHANGED
  32. Done: in "Tickets of <project>" every answered / confirmed creator question is followed by the creator's own comments on it
  33. (quoted, last 3, 600 characters each) — `lib/brief.hl` (`answerLines`). Checked read only: `./colony brief antcolony 22` shows
  34. "Answer of the creator: …" under #5, #10, #11, #12 …. Not run: the big e2e suites; no new test (needs a tickets copy with an answered question).
  35. The creator setting a question to confirmed is the creator's own step (or `/confirm`).
  36. ## 2026-09-26 — small local models for routine decisions (antcolony#20) — awaiting the architect's check; LIVE CONTAINER UNCHANGED
  37. Done (README "Small local models"): librarian model `local` / `local:<alias>` → OpenAI-compatible llama-server (`COLONY_LOCAL_URL`), schema enforced by
  38. the server, same `checkAnswer`; unreachable / cut off / refused → Claude fallback (`COLONY_LIBRARIAN_FALLBACK`, default sonnet). Default model unchanged (sonnet).
  39. Files: `lib/librarian.hl` (`localAnswer`, `classify`), `local-test.hl`, `.env.example`, `docker-compose.yml`. Tested: canned text through `classify` with a real
  40. llama-server (granite-4.0-h-micro Q8) → answered; dead port + fallback off → "did not answer"; dead port + fallback → goes to Claude.
  41. Measured (CPU only, no GPU visible in the box; ~55 s per call): granite micro agreed with Claude on only 4 of 8 real prompts (run cut short by the usage limit). Gemma E4B thinks too long (~95 s/call).
  42. Second run (antcolony#20, session s-20260926T1451): Qwen3.5-9B Q4_K_M on CPU (16 threads, thinking off): ~55 tok/s prompt, 3–4 tok/s output; a call ran to the 700-token cap and took 210–270 s — unusable for the librarian on this box; no accuracy number came out. Only a GPU (not visible to the worker box) or a smaller model can work.
  43. Not done / open: no model proven good enough; a bigger model and the GPU were not tested; keep `sonnet` until a measured run (`.scratch/loc/eval.py URL N`) agrees well; the
  44. controller stays on Claude; the e2e suites were not re-run.
  45. ## 2026-09-26 — status and daily summary from tickets (antcolony#19) — awaiting the architect's check; LIVE CONTAINER UNCHANGED
  46. Done (README "Status and daily summary"): `lib/status.hl` — `./colony status [--write]` (per-project state table → `status/STATUS.md`),
  47. `./colony digest [--post]` (what waits for the creator, filed once a day as one inbox ticket, source `colony:digest:<day>`);
  48. `run` files it once a day after `COLONY_DIGEST_HOUR` (UTC, default 7, `off` = never). Tested: `node tests/e2e-status.mjs` 12/12;
  49. `tests/e2e-keywords.mjs` 15/15; a dry run against the live tickets (read only) lists 138 waiting.
  50. Not done / open: no mail/push delivery (ident#7 on hold) — the inbox ticket is the delivery; the live container runs the old code until restarted.
  51. ## 2026-09-26 — each worker in its own sealed box (antcolony#18) — awaiting the architect's check; LIVE CONTAINER UNCHANGED
  52. Done (README "Sandbox"): every Claude session (worker, finalize, resume, controller) runs in a bubblewrap box built from an
  53. allowlist — system read-only, empty home with only the claude login + toolchain, the project's own folder rw (`.env` masked),
  54. its dependencies' folders + docs read-only, nothing else of the disk; no tokens in the environment; own process namespace.
  55. Deploy rights (live folder rw + `~/.ssh` ro) only for a ticket with the line `colony-deploy: yes` (opening text or creator
  56. comment). Files: `lib/sandbox.hl`, `claude.hl` (`sandbox` option), `work.hl` (`boxOf`, `runBox`, refusal before the lease),
  57. `controller.hl`, `brief.hl` (+ events), `docker-compose.yml` (`COLONY_SANDBOX`, `COLONY_SANDBOX_RO`), `colony box`.
  58. Tested: `node tests/e2e-sandbox.mjs` 19/19; `tests/e2e.mjs` 345/345 (incl. a `work` with the box ON, fake claude), `tests/e2e-agent.mjs` 46/46; a REAL `claude -p` inside the box answers (Chrome headless, node, git too);
  59. bwrap works as uid 1000 inside the live container (`docker exec --user 1000`). The other suites run with `COLONY_SANDBOX=off`.
  60. Not done / open: the network is not restricted (Claude API, tickets, dev servers need it); the Claude login folder is
  61. writable inside (it holds the account's history of ALL colony sessions); nothing marks a ticket for deploy yet (the architect
  62. writes `colony-deploy: yes`); the box takes effect when the architect restarts the container.
  63. ## 2026-09-26 — the end-to-end suites run on tickets' projects and roles (antcolony#31)
  64. Done: `tests/e2e.mjs` (348/348) and `tests/e2e-agent.mjs` (46/46) run against the current tickets + ident folders. The creator logs in
  65. first (admin) and opens each test project right before its first ticket (`openProject`), with Colony as member `edit`; `antcolony`
  66. is opened up front (the scheduler files questions there). Reads are translated back to the scheduler's own state names
  67. (progress / review / pending / done / reopened → in progress / awaiting creator / on hold / confirmed / rejected; a pending
  68. "Question…" = awaiting creator) and the server's extra `assign` events are left out. The librarian is off in the suite unless its own
  69. section turns it on (the creator is a project admin now, so its comments would start a real librarian call). The old "Colony may not
  70. reject" check is now "Colony (edit) may not change members (403)".
  71. Not done: none. The tickets copy must be in a starting state (another worker's half-written edit once stopped it at boot).
  72. ## 2026-09-26 — new ticket states and roles (antcolony#27) — awaiting the architect's check; LIVE CONTAINER UNCHANGED
  73. Done (README "New ticket states and roles"): `lib/tickets.hl` reads the new states (review / pending / done / reopened / progress)
  74. as the old names the logic knows and writes the names the server speaks (asks `GET /api/projects` once); a built ticket → `review`,
  75. a creator question → `pending`, `/hold` → `pending`, `/confirm` → `done`, `/reject` → `reopened`, the lease → `progress`; a reopened
  76. ticket is picked up like a rejected one. The creator = the project's admin (members API), used by librarian + keywords instead of a
  77. name list (the names list stays as the fallback for the old tickets). New `tests/e2e-states.mjs` (own tickets#20 copy): 14/14.
  78. Old suites on the old tickets copy unchanged (see the run files in `.scratch/`).
  79. Not done / open:
  80. - The tickets API never shows the ident short id, and events carry only the author's display name: the admin is matched by name
  81. (by user id as soon as tickets adds `userId` to an event — the code already takes it). Filed as a tickets issue.
  82. - tools/t.py and tools/watch.py on Byrodin are the architect's (read-only for workers).
  83. - The scheduler's and the architect's tokens must be members with role `edit` of every project (admin adds them) — day-of-switch step.
  84. - The big e2e suites still run on the OLD tickets copy (`.scratch/stable`); only `e2e-states.mjs` uses the #20 copy.
  85. ## 2026-09-26 — keywords in comments (antcolony#17)
  86. Done: `lib/keywords.hl` — `/hold`, `/prio`, `/confirm`, `/reject <why>` from the creator's comments (README "Keywords"); `run`
  87. handles them every iteration, `./colony keywords [--post]` by hand; `next` / `run` order eligible tickets by `/prio` then age.
  88. Tested: `tests/e2e-keywords.mjs` 15/15 against own tickets + ident.
  89. Next: tickets' new state `answered` is counted with `awaiting creator` (creator's inbox) in next/run.
  90. Not done / open:
  91. - `/confirm` / `/reject` need the creator's token (`COLONY_CREATOR_TOKEN_FILE`) — tickets lets only the creator do them; until the
  92. creator provides one the scheduler answers "use the button". A tickets feature "act on behalf of the creator" would be cleaner.
  93. - Tickets' new `answered` state (creator's comment on an `awaiting creator` ticket) is not known to `next` / `relations` yet.
  94. - The live container runs the old code until restarted.
  95. ## 2026-09-26 — Claude quota per account, shared across computers (antcolony#16) — awaiting the architect's check; LIVE CONTAINER UNCHANGED
  96. Done (README "Claude quota per account"): `agent --account NAME` (`COLONY_CLAUDE_ACCOUNT`, default host name) → sync carries account +
  97. last reading + limit pause; the scheduler (`run --serve`) pools per account: freshest reading, a limit on any host holds all, one
  98. start per account until a newer reading (`--account-settle`, 60 s). Files: `lib/agent.hl`, `lib/daemon.hl` (accountBlock), `scheduler.hl`
  99. usage, `tests/e2e-agent.mjs` §5b. Open: the single-host `run` is unchanged (one host = one account); no account auto-detection.
  100. ## 2026-09-26 — agents announce capabilities (antcolony#15) — awaiting the architect's check; LIVE CONTAINER UNCHANGED
  101. Done (README "Capabilities"): `agent --capabilities LIST` (`COLONY_CAPABILITIES`) → sent in every sync; registry `"needs": [..]` per
  102. project; `daemon.hl` starts a new ticket only where the host offers all needs, else `P#n waits — H does not offer: x`. Helpers in
  103. `util.hl`, `needs` parsed in `registry.hl`. Test: `tests/e2e-agent.mjs` extended (+1 check). No project file has `needs` yet
  104. (nothing changes until the architect adds one).
  105. ## 2026-09-26 — scheduler on its own host + an agent per host (mission 035, antcolony#14) — awaiting the architect's check; LIVE CONTAINER UNCHANGED
  106. Done (README "Scheduler + agents per host"): `./colony run --serve PORT` = the scheduler (starts no worker, state in tickets only),
  107. `./colony agent --scheduler URL` = the agent of a host (runs `work` for the commands it gets, owns quota + ports, buffers events while
  108. disconnected). Transport: HTTPS request/answer (`POST /agent/sync`, shared agent token) — Hybriel has no WebSocket client
  109. (hybriel#109, already filed), so the concept's "one WebSocket" is replaced, not faked; same effects. New files: `lib/agent.hl`,
  110. `lib/AgentServer.hl` (hl:http1 server, `plugins/http1` copied from hybriel master), `tests/e2e-agent.mjs`; changed: `daemon.hl`
  111. (serve mode), `work.hl` (`--brief-file`), `brief.hl` (port marker), `tickets.hl` (agent token), `scheduler.hl`, `colony`.
  112. Tested (fake claude only, own tickets+ident, ports 8710-8719): `COLONY_E2E_PORT_BASE=8710 node tests/e2e-agent.mjs` — see the run
  113. 39/39 (`.scratch/t/run3.txt`); the old suite `tests/e2e.mjs`: 343/343 unchanged (`.scratch/t/full1.txt`). Note: the e2e needs a tickets/ident copy that logs in today — the current
  114. ident (ident#23 in progress) breaks the login step of BOTH suites; the runs used yesterday's copies (`COLONY_E2E_TICKETS_DIR` /
  115. `COLONY_E2E_IDENT_DIR`, `.scratch/stable/`).
  116. Not done / open: the Byrodin container files + deploy (architect); the librarian still needs Claude on the scheduler host; the live
  117. Loreana container keeps running the all-in-one `run` (unchanged behaviour, the new code only adds `--serve` / `agent`).
  118. ## 2026-09-26 — antcolony#13 (react to tickets events instead of polling) — BLOCKED on a Hybriel gap, nothing built
  119. Finding: tickets pushes its events only over the hl:web page socket (`/__hl/socket`, frames `ticketCreated` / `ticketEvent`,
  120. sent only to a tab that has said `hello` and mounted a component listening for them). The scheduler would have to be a
  121. WebSocket CLIENT. Hybriel has none: `hl:http1`'s `ws_client.hl` is the SERVER-side peer (natives `http1.ws_send/ws_close/...`
  122. only), `hl:fetch` cannot upgrade (only `stream = true` for chunked/NDJSON bodies), `hl:proc` has no stdin (hybriel#91), and
  123. tickets has no SSE / streaming endpoint to feed `fetch` stream mode. A JS/other-language bridge is forbidden. No code changed.
  124. Filed as a Hybriel gap (report `issues`). Alternative if the architect prefers: tickets gets a streaming endpoint (SSE/NDJSON)
  125. and the scheduler consumes it with `fetch(stream = true)`.
  126. Plan once a source exists: `daemon.hl` — an event (new ticket / comment / state change) triggers `tick()` at once (debounced,
  127. never overlapping the `busy` guard); the `every(interval)` loop stays only as a slow safety net (lease expiry, quota reset,
  128. reconnect gap), default raised from 60 s.
  129. ## 2026-09-25 — the librarian respects the Claude usage limit (mission 034, antcolony#25) — awaiting the architect's check; LIVE CONTAINER NEEDS A RESTART
  130. Why: live 19:58 the 5 h limit was reached, yet every iteration called the librarian's model (answer: subtype `success`,
  131. is_error, 429, empty) → text unfiled → no start, every minute until the reset. Live answer kept: `.scratch/m034/livecheck/`.
  132. Done (README "Usage limit" under `run`, + notes in "Librarian → ORDER", run steps 3/4, "Quota + parking"):
  133. - `daemon.hl`: with the librarian on, `claude -p /usage` FIRST in every iteration; at/above the start threshold (reserve /
  134. week limit; 100 % = reached, also with the checks off) → no librarian call, no start, ITER line `librarian not run: …`.
  135. Reading reused for the start check (re-read if the pass made model calls).
  136. - `claude.hl` rateLimitOf: also the synthetic `error: "rate_limit"` message, 429 without is_error, "session/weekly limit".
  137. Checked on the LIVE result file: limited=true, reset 18:50:00Z.
  138. - `librarian.hl`: a limited call → `→ USAGE LIMIT …`, pass stops, no try counted; summary `limited`, `resetMs`.
  139. - `work.hl` parkRun(…, resetKnown, done) → `limited`/`resetMs` in the result; `run` pauses: `LIMIT: usage limit reached —
  140. librarian and starts paused until <ISO> · <who>` (one line), silent iterations (no librarian / probe / start), `LIMIT:
  141. resumed …` (one line); unknown reset → 15 min. The pause is in-process only (a restart re-probes).
  142. Tested (fake claude only, own tickets+ident 8751/8752, pools 8770-8799): `COLONY_E2E_PORT_BASE=8750 node tests/e2e.mjs`
  143. - dev copy WITHOUT `.env` (`.scratch/m034/dev/`): 343/343 → `.scratch/m034/e2e-new-noenv-2.txt` (baseline pre-034: 330/330 `e2e-baseline-noenv.txt`)
  144. - THIS folder with the LIVE `.env` present (not read, not changed; mtime still 14:03:28), container running (not touched):
  145. 343/343 → `.scratch/m034/e2e-live-env.txt`; `claude-guard.log` absent = no real claude call
  146. - pre-034 code + new tests (`.scratch/m034/origtest/`): 13 FAILED → `.scratch/m034/e2e-origcode-newtests.txt`
  147. - 3 old checks changed on purpose (README "Tests of mission 034"). Pre-034 code: `.scratch/m034/orig/`.
  148. Not done / open:
  149. - Live container still runs the pre-034 code until `docker compose up -d` (architect). After the restart, check
  150. `logs/colony.log` for `librarian not run: …` / `LIMIT:` lines while the limit is reached.
  151. - Every iteration now spawns the `/usage` probe (1–4 s, $0) also when nothing is to start (needed to guard the librarian).
  152. - The 15-min fallback and the reset times are not verified against a REAL limit hit after the change (fake only).
  153. ## 2026-09-24 — lease expiry must never touch finished tickets (mission 031, antcolony#1) — awaiting the architect's check; LIVE CONTAINER NEEDS A RESTART
  154. Why: ITER 45 (21:05Z) expired ident#19 1.9 s after `./colony deployed` had moved it to awaiting creator (stale survey +
  155. the `colony-deployed:` marker voided "ready" so `leaseOf` fell back to the old dead lease) → 2nd worker ran on it.
  156. Done (README "Mission 031" under Leases; code `lib/lease.hl` endOf / stillLeased / expireLease, `lib/daemon.hl`):
  157. - A lease ENDS (kind `ended`, never expired) on any state change after it, a `colony-deployed:` line, or the session's own
  158. report (not "ready to deploy") / verdict / run / lease-expired marker. `run` + `leases` list it with the reason.
  159. - `run` expiry, `leases --expire` and `run`'s resume of a parked session RE-READ the ticket right before writing; not STILL
  160. `in progress` with the same lease → nothing written, `NOT expired|NOT resumed <ref> …: re-read right before — <why>`.
  161. - Test hook `COLONY_TEST_HOOK_URL` (tests only) → e2e reproduces the race deterministically.
  162. Tested (fake claude only, own tickets+ident 8751/8752, hook server 8758, pools 8770-8799): `COLONY_E2E_PORT_BASE=8750 node tests/e2e.mjs`
  163. - dev copy WITHOUT `.env` (`.scratch/m031/dev/`): 330/330 → `.scratch/m031/e2e-new-noenv-2.txt` (run 1 had 4 test bugs, fixed)
  164. - THIS folder with the LIVE `.env` present (not read, not changed; mtime still 21:58:49), container running: 330/330 →
  165. `.scratch/m031/e2e-live-env.txt`; `claude-guard.log` absent = no real claude call
  166. - pre-031 code + only the hook (`.scratch/m031/orighook/`): 322/8 FAILED → `.scratch/m031/e2e-orighook.txt` — the new
  167. checks catch the bug (B: `expired lr#2 … → open` after the move to awaiting creator; A: expired + a 2nd worker started)
  168. - live, GET only: `./colony leases` from the dev copy → `.scratch/m031/live-leases-get-only.txt`
  169. Pre-031 code: `.scratch/m031/orig/`.
  170. Not done / open:
  171. - Live container still runs the pre-031 code until `docker compose up -d` (architect).
  172. - Remaining gap: re-read → write are two requests (ms apart); closing it needs a conditional state change in tickets
  173. (e.g. `expect: "in progress"` on POST …/state) — not built (other project).
  174. - The heartbeat of a RUNNING session still renews a lease on a ticket someone moved away (not in scope; the renewal is a
  175. comment only, and `leaseOf` now ignores it because the state change ended the lease).
  176. ## 2026-09-24 — scheduler fixes after the librarian (mission 030, antcolony#1) — awaiting the architect's check; container NOT started
  177. Done (README "Relations, questions, rejections" last bullet, "Librarian → Where the files go", "Test → Test isolation"):
  178. - **A question ticket is never work, in no state**: `next`/`cycle`/`run` list it "a question for the creator — the
  179. librarian takes its answer (<state>) — never work" (checked before the rework-on-rejection logic); `brief`/`work`/`salvage`
  180. refuse it; `run` never resumes a session parked on one. Code: `lib/relations.hl` `questionWhy`, `next.hl` survey,
  181. `brief.hl` buildBrief, `work.hl` salvage, `daemon.hl` resume.
  182. - **Test isolation**: Hybriel loads the `.env` beside `scheduler.hl` (proved: `.scratch/m030/envprobe/`), so the e2e now
  183. runs the scheduler from a copy WITHOUT `.env` (`.scratch/e2e/app/`), drops inherited COLONY_*/FAKE_*, and puts a
  184. refusing `claude` guard on PATH (fake only).
  185. - **DECISIONS never into a `"workers": false` project**: `librarian.hl` projectFile → `librarian/projects/<p>/`. Hybriel's
  186. file re-rendered to `librarian/projects/hybriel/DECISIONS.md` (`./colony librarian --render`), the untracked
  187. `/media/STORAGE/projects/hybriel/DECISIONS.md` deleted (nothing else touched there).
  188. - What the wrongly started sessions changed: `.scratch/m030/wrong-sessions.txt` (run folders + transcripts),
  189. `.scratch/m030/wrong-sessions-tickets.txt` (live ticket events, GET only). Nothing there was changed.
  190. Tested (fake claude only, own tickets+ident 8751/8752, pools 8770-8799): `COLONY_E2E_PORT_BASE=8750 node tests/e2e.mjs`
  191. - dev copy WITHOUT `.env`: 320/320 → `.scratch/m030/e2e-new-noenv-1.txt` (baseline pre-030 code: 310/310 `e2e-baseline-noenv.txt`)
  192. - a synthetic hostile `.env` (`.scratch/m030/synthetic.env`: max turns 120, week limit 100, bogus token + CLAUDE_CONFIG_DIR, …):
  193. OLD code 294 passed / 16 failed (`e2e-orig-synthetic-env.txt` — the problem reproduced), NEW code 320/320 (`e2e-new-synthetic-env.txt`)
  194. - THIS folder with the LIVE `.env` present (not read, not changed; mtime still 21:58:49): 320/320 → `.scratch/m030/e2e-live-env.txt`
  195. ("this folder HAS a .env … — ignored"; `claude-guard.log` absent = no real claude call)
  196. Pre-030 code: `.scratch/m030/orig/`, dev copy `.scratch/m030/dev/`.
  197. Not done / open:
  198. - Live container not started (architect). No real Claude run in this mission.
  199. - Hybriel note: the interpreter reads `.env` beside the entry script only (not the cwd) and an empty shell variable beats it;
  200. SPEC only documents `--native` ("beside the binary, then in the cwd") — not filed.
  201. - `ready` / `deployed` do not check for questions: ident#17 (a question) is still "in progress · ready to deploy" from the
  202. pre-030 session s-20260924T1857-dc5328 → `./colony ready` lists it; do NOT run `deployed ident.worldapi.org 17`.
  203. - gitoria#3 / #4 are `awaiting creator` with "Ready for you to test" comments of the wrong sessions; gitoria's
  204. `docs/differ-from-custom-ide.md` + `STATUS.md` were edited by them (list in `.scratch/m030/wrong-sessions.txt`) — the
  205. architect decides; nothing reverted.
  206. - The antcolony-docs README still says the librarian writes DECISIONS.md "per project (dev folder)" — Byrodin file, not edited.
  207. ## 2026-09-24 — the librarian (mission 029, antcolony#21) — awaiting the architect's check; LIVE CONTAINER NEEDS A RESTART
  208. Done (README "Librarian"): `./colony librarian` reads the CREATOR's texts in tickets (comments, state texts incl. answers on
  209. question tickets, tickets he opened, edits; READ only) + once the architect's chat seed; one model step per new text
  210. (sonnet, `--tools ""`, schema `templates/librarian.schema.json`); the code keeps the creator's exact words (a model excerpt
  211. only if verbatim), marks the reading as the librarian's (seed: the architect's), assigns project / `all` + topic; writes
  212. `DECISIONS.md` per project (dev folder, else code folder, else `librarian/projects/<p>/`) and `templates/decisions-global.md`
  213. — current only, by topic, contents on top; corrections → `*-archive.md`. Store `librarian/decisions.json`, state
  214. `librarian/state.json`, calls `librarian/calls/`. Every brief: section "Decisions of the creator — a decision here overrides
  215. anything else; ask only if it is not decided here" (paths + whole file ≤ 150 lines, else the matching topics) after the
  216. conventions; UI projects (registry `"ui": true`: tickets, ident, gitoria) name `antcolony-docs/docs/layouts-conventions.md`.
  217. ORDER: `run` awaits a librarian pass at the start of every iteration and starts nothing while a creator text is unfiled;
  218. `brief`/`work`/`cycle` by hand await a pass first. Chat transcripts as a source were built and then DROPPED (creator: "the
  219. librarian should be enough. i have to adopt to the workflow"): code removed, the 16 chat entries removed from the live store
  220. (backup `.scratch/m029/librarian-before-drop-chat/`).
  221. Installed in this folder (pre-029 code `.scratch/m029/orig/`, dev copy `.scratch/m029/dev/`). **The running container still
  222. runs the old code** (Hybriel loads it at start): `docker compose up -d` (or `docker restart antcolony-scheduler`) is needed for
  223. `run` to call the librarian; the new compose env lines (COLONY_LIBRARIAN*, COLONY_CREATOR_NAMES) need `up -d`.
  224. Tested: `COLONY_E2E_PORT_BASE=8750 node tests/e2e.mjs` 310/310 (266 old — one check changed: the Hybriel block path the
  225. architect changed after 027; baseline was 265/266 — + 44 librarian, fake model) → `.scratch/m029/e2e-fake-final.txt`; m012
  226. tickets → `.scratch/m029/e2e-fake-m012.txt`. Live brief (GETs only, `--librarian off`): `.scratch/m029/briefs/live-tickets-12.md`.
  227. FIRST LIVE PASS (real sonnet, colony subscription `CLAUDE_CONFIG_DIR=/home/mre/.claude-colony`, READ only on tickets):
  228. seed 19 entries (`.scratch/m029/live-seed.txt`); pass `--since 2026-09-23` (`live-pass-probe.txt` 1 call $0.0289,
  229. `live-pass.txt` 155 calls $4.627 — 130 of them chat messages, dropped afterwards); `--redo` of 4 wrongly read answers + 3 new
  230. creator texts (`live-redo.txt`, 7 calls $0.2211). **Total $4.88** (ticket texts alone ≈ $1). Result: global 19 (seed),
  231. antcolony 8, tickets 7, ident 4, gitoria 3, hybriel 1 current entries, nothing superseded.
  232. ```bash
  233. cd /media/STORAGE/projects/antcolony-scheduler
  234. ./colony librarian # what is new (no model call)
  235. CLAUDE_CONFIG_DIR=/home/mre/.claude-colony ./colony librarian --post-files # by hand until the container is restarted
  236. cat templates/decisions-global.md DECISIONS.md ../tickets.worldapi.org/DECISIONS.md ../ident.worldapi.org/DECISIONS.md
  237. ```
  238. Not done / open:
  239. - The tickets API shows DISPLAY NAMES only (no user id, no "is creator" flag): the creator is recognised by name
  240. (`COLONY_CREATOR_NAMES=Caramboleyo,creator`); a user who picks the name "Caramboleyo" would count. Proper: tickets marks
  241. events by the configured creator (e.g. `byCreator: true`, computed from TICKETS_CREATOR_IDENTITY) — needs a tickets change
  242. + deploy (not done here).
  243. - Readings can be wrong (the quote is always there): the first pass read "yes" on ident#13 as the summary's suggestion
  244. (fixed by a prompt rule + `--redo`); antcolony#6's reading says "workers run in bypass" (they run `auto`) — left as is.
  245. - Cost per call ~$0.03 (the input with every current entry is re-written to the cache each call); fine for a few texts per
  246. iteration, costly for a big backlog.
  247. - `librarian/lock` of a pass killed mid-way blocks `run` starts for up to 15 min (stale time).
  248. - A text written while a pass runs reaches the next iteration's briefs (seconds).
  249. - `templates/conventions.md` (hand copy of the antcolony README conventions) overlaps `decisions-global.md` (seed): both are
  250. in every brief; which stays is the architect's call.
  251. - `projects/-media-STORAGE-projects-antcolony-scheduler/` (a Claude Code project folder with a session .jsonl, created 20:32,
  252. not by this mission) sits in the registry folder; the registry ignores it (no .json).
  253. ## 2026-09-24 — permanent operation as the Docker container `antcolony-scheduler` (mission 028, antcolony#1) — awaiting the architect's check
  254. Done (README "Operations"): `docker-compose.yml` (busybox, `restart: unless-stopped`, host network + PID namespace, cap
  255. SYS_ADMIN + seccomp unconfined, `stop_grace_period: 75s`, json-file 3×10 MB), `docker/pivot.sh` (root: private mounts,
  256. `pivot_root` into the host's `/`, drop to uid 1000 with mre's groups), `docker/entrypoint.sh` (uid 1000: mre's env,
  257. `./colony run [--live]`, docker's one SIGTERM → finish, park after `COLONY_STOP_FINISH_SECONDS`=20, `logs/colony.log`
  258. rotating), `.env.example` (reserve 100 / week limit 100 = the creator's setting; everything else commented defaults).
  259. Default `COLONY_LIVE=1`. **Container NOT created** (removed after a `up --no-start` check): start = `cp .env.example .env`
  260. (check it) → `docker compose up -d`.
  261. Tested (own tickets 8752 + ident 8751, fake claude, pool 8770-8779, test container `antcolony-scheduler-m028` via
  262. `.scratch/m028/dc.sh`; outputs `.scratch/m028/test-*.txt`): run picks/works/posts tiny#1..6 (ITER lines in `docker logs`);
  263. docker stop during a session → finish → park after 20 s (stop took 21 s, no process left) → docker start → resumed →
  264. posted; stop during a short session → finished + posted (9 s); idle stop 1 s; docker kill → no process left; kill -9 of the
  265. scheduler → docker restarted the container; docker exec as uid 1000: REAL `claude --version` 2.1.280 + `claude -p /usage`
  266. (cost 0, 0 turns, session 28 %, week 44 %), headless Chrome WITH sandbox ok, `./colony leases`. Processes: uid 1000, CapEff 0.
  267. Not done / open:
  268. - No reboot tested (not allowed on a shared host): restart after boot + park at shutdown rely on docker's
  269. `unless-stopped` + stop timeout (75 s < systemd's 90 s for docker.service) — check at the first reboot.
  270. - `/media/STORAGE` is a separate fstab mount: if docker ever starts before it, the entrypoint is missing → the container
  271. exits and restarts until it is there (not observed).
  272. - The pool 8700-8799 overlaps ports used on Loreana (8765, 8766, 8787, 8795).
  273. - Workers keep mre's docker group + sudo (wheel) as on the host — no isolation beyond the host's.
  274. ## 2026-09-24 — after the first live batch: readable test steps, deploy gate, fewer questions (mission 027, antcolony#1) — awaiting the architect's check
  275. Done (README "Mission 027"): `result` ≤ 120, `test` 2–4 steps ≤ 90 (numbered Markdown list in every comment), no `.scratch`
  276. step, no local address on a project with `live`; ≤ 3 questions of ≤ 3 lines / 300 chars; new report key `decided` (optional
  277. in the validation, required in the schema) → one "Decided: …" bullet. **Deploy gate**: complete + passed report on a project
  278. with `live` → "Built — goes live with the next deploy." (`· ready to deploy` marker), ticket stays `in progress`, never expires,
  279. not in `next`; `./colony ready` lists them, `./colony deployed <project> <n>` posts "Now live on <site> — <result>" + numbered
  280. steps + details and sets `awaiting creator` (needs `runs/<S>/report.json` on this host). Projects without `live` → awaiting
  281. creator as before. Brief: "Conventions for all apps" as text (`templates/conventions.md`, a copy), the project's own tickets
  282. (newest first, ≤ 40), where the creator tests (live URL). A refused report gets ONE fix step (same session resumed, like
  283. finalize). Controller told that live-site steps are checked against the code.
  284. Tested (fake claude only, own tickets+ident 8751/8752, work ports 8753-8759, run 8780-8799):
  285. `COLONY_E2E_PORT_BASE=8750 node tests/e2e.mjs` 266/266 (234 − 3 moved + 35 new) → `.scratch/m027/e2e-fake-3.txt`; m012 tickets 254/254 → `e2e-fake-m012.txt`; baseline
  286. before the change 234/234 (`e2e-baseline.txt`). Live brief (GET only) `.scratch/m027/briefs/live-tickets-12.md`.
  287. Not done / open:
  288. - No real Claude run: whether Sonnet keeps 120/90 is untested; a miss now costs one cheap fix step instead of the session.
  289. `maxLength`/`maxItems` still not in the schema (unknown whether `claude --json-schema` accepts them).
  290. - The deploy itself stays manual: the architect runs `./colony ready` → deploys → `./colony deployed <p> <n>` (on Loreana,
  291. where the run folders are). No `--live` guard on `deployed` (it posts to COLONY_TICKETS_URL like `report --post`).
  292. - `templates/conventions.md` and `templates/hybriel-block.md` are hand copies of Byrodin files. The Hybriel block still tells
  293. workers to read `/CONTAINERS/projects/antcolony/docs/hybriel-for-app-workers.md` — that path does not exist on Loreana.
  294. - The ≤ 5 line limit is counted without the numbered step lines (creator/architect to confirm).
  295. - A 2nd session's report on a live ticket that is already `awaiting creator` posts the "Built — goes live…" line, state left.
  296. ## 2026-09-24 — continue unfinished work, clean up after sessions, cheaper finalize, salvage lease (mission 026, antcolony#1) — awaiting the architect's check
  297. Done (README "Mission 026"): report key `complete` (bool, validated; controller checks it); a passed `complete: false`
  298. report → ONE comment "Half done: <result>; the next worker continues." + still open, ticket `in progress → open` (never
  299. awaiting creator; a half-done report does not answer a rejection). Brief section "Previous attempt" (`lib/previous.hl`:
  300. last colony session, how it ended, result, open, work copy from `.scratch/…` paths, report path). After every worker /
  301. finalize / controller part: `lib/cleanup.sh` stops processes listening on the session's ports that started during that
  302. part (never others: before the part, other user, the scheduler, another `COLONY_SESSION`), logged + `session.json.cleanup`.
  303. Finalize resume without `--disallowedTools`. `salvage` leases the ticket (token always, ticket must be `open`).
  304. Tested: `COLONY_E2E_PORT_BASE=8750 node tests/e2e.mjs` 234/234 (215 old — 3 m025 checks changed on purpose: finalize argv,
  305. salvage lease — + 19 new, fake claude), m012 tickets 222/222 — `.scratch/m026/e2e-fake-5.txt`, `e2e-fake-m012.txt`.
  306. ONE real tiny run (`.scratch/m026/real.sh`, own tickets 8753/8754, stopped): Sonnet worker --max-turns 2 → out of steps
  307. $0.1866 → finalize resume **$0.0301, cache read 83 909 / write 1 259** (m025's with the flag: $1.0528, cache read 0), no
  308. file changed; FAKE controller (its fail verdict is meaningless: it only understands `cat X`). The real salvaged report of
  309. ident.worldapi.org#2 (a COPY + `"complete": false`) posted to own tickets as half done: `.scratch/m026/halfdone-real.txt`.
  310. Pre-026 code: `.scratch/m026/orig/`.
  311. Not done / open:
  312. - Live post of ident.worldapi.org#2 = architect: add `"complete": false` to its `runs/…/report.json`, then `./colony check
  313. runs/s-20260924T1527-525807 --post` (README "Mission 026", last bullet).
  314. - No limit on half-done rounds (a ticket could go half done → open forever); not counted as controller fails.
  315. - Cleanup stops only LISTENING processes of the range: non-listening leftovers (a `--watch` parent, a headless Chrome
  316. without a port in the range) survive; a worker that ignores its range is not covered.
  317. - A half-done comment can still show "Still running: …" from the report although the cleanup stopped it.
  318. - "Previous attempt" reads the run folder only on the host that ran it; old sessions without `complete` show no "(not complete)".
  319. - The real controller never saw a `complete` field yet (the real run used the fake controller).
  320. ## 2026-09-24 — finalize step, budget in the brief, `salvage` (mission 025, antcolony#1) — awaiting the architect's check
  321. Done (README "Finalize step + salvage"): a worker ending with `error_max_turns` or killed by `--timeout` gets its SAME Claude
  322. session resumed once (`claude -p --resume`, same schema/model/permission mode, `--max-turns 8`, Edit/Write/NotebookEdit off,
  323. `runs/<S>/finalize.md` "STOP WORKING — write your report now") → valid report → controller → post as usual; none → back to
  324. open once (unchanged texts). Brief section `## Budget` (steps, "report before step N−min(10,N/3)", time). `./colony salvage
  325. <runs/S> [--post]` = the same for a finished run (no lease; controller told to re-run nothing that writes). Resumed sessions:
  326. Claude reports CUMULATIVE cost → the scheduler now counts `total − claudeCostSeen` per part (also fixes mission 020's
  327. parked-resume double count). Controller transcript keeps start + end of long sessions. `run` passes `--finalize-*`.
  328. Tested: `COLONY_E2E_PORT_BASE=8750 node tests/e2e.mjs` 215/215 (187 old unchanged + 28 new, fake claude only), m012
  329. tickets 203/203 — `.scratch/m025/e2e-fake-4.txt`, `e2e-fake-m012.txt`. Pre-025 code: `.scratch/m025/orig/`.
  330. **Real salvage of the first live run** (the only real Claude run; Sonnet): `runs/s-20260924T1527-525807` (original copy
  331. `.scratch/m025/run-orig/`) against OWN tickets+ident (`.scratch/m025/own-tickets.mjs`, 8753/8754, stopped afterwards):
  332. `COLONY_TICKETS_URL=http://127.0.0.1:8754 COLONY_TOKEN_FILE=.scratch/m025/own/colony-token ./colony salvage
  333. runs/s-20260924T1527-525807 --post --ports 8770-8779` → output `.scratch/m025/salvage-real.txt`: finalize 4 turns, 113 s,
  334. one read-only Bash call, REPORT OK (8 done, 5 verified, 6 open, 3 questions) → controller PASS (15 findings ok, 7 turns) →
  335. posted on the own copy of ident.worldapi.org#2 (3 question tickets, → awaiting creator). Cost: finalize **$1.0528** (Claude
  336. printed $5.7198 = the whole session — session.json corrected by `.scratch/m025/costfix.py`, backup
  337. `session.before-costfix.json`), controller $0.5453 → whole session $6.2651. The ident folder was unchanged (find
  338. size+mtime of 14 064 entries before/after identical: `.scratch/m025/ident-{before,after}.txt`).
  339. **Live post = architect's decision**: `COLONY_TOKEN_FILE=… ./colony check runs/s-20260924T1527-525807 --post` (reuses
  340. verdict.json, no new Claude session; session.json `outcome: posted` refers to the OWN instance).
  341. Not done / open:
  342. - The finalize resume missed the prompt cache: its first call wrote the whole 207 k context anew (cache read 0) although the
  343. worker's 1 h cache was 18 min old — probably because `--disallowedTools` changes the tool list (= the cached prefix). A
  344. finalize WITHOUT that flag might cost ~$0.1 instead of ~$1 — unproven (would need another real run).
  345. - A salvaged report of unfinished work still sets `awaiting creator` ("Ready for you to test") although its result says
  346. "not copied in, not testable" — question for the creator/architect.
  347. - Leftover ident dev servers of the live worker still run (pids 1396754/1396755, ports 8700/8701, from
  348. ident `.scratch/dev-m022`) — not ours, not killed.
  349. - A `run` could pick the (open) ticket while a salvage of it runs (salvage takes no lease).
  350. - A park (2nd SIGTERM) during the finalize step resumes with the normal resume prompt, not the finalize one.
  351. ## 2026-09-24 — readable ticket texts, weekly limit, hand-filed questions (mission 023, antcolony#1) — awaiting the architect's check
  352. Done (README "Ticket texts", "report", "run", "Leases", "Relations"): every text the scheduler writes into tickets follows
  353. antcolony README "Ticket texts are written for the creator" — ≤ 5 short plain lines + ONE short machine line last (lease,
  354. heartbeat, park, resume, give-back, lease expiry, report comment + state, controller fail comment + state, all creator
  355. questions, issue tickets). Report schema + `result` (one sentence) + `test` (1–4 steps), validated (one line, ≤ 200
  356. characters); the comment = result · **Test:** · ≤ 3 detail bullets · `colony-report: S · sha256 <12 hex>[ · controller
  357. pass]` — the full report + verdict stay in `runs/<S>/`. Markers shortened (no ISO times, no Claude id; old markers still
  358. parse). Heartbeats: lease ttl 7200 s, heartbeat ttl/2 (a session < 1 h writes none). `run --week-limit P` /
  359. `COLONY_WEEK_LIMIT` (default 84): no start while the weekly usage is above it or unknown; `--reserve 100` / `--week-limit
  360. 100` switch the checks off (architect update: first live runs up to 100 %). Haiku allowed (never refused; default stays
  361. Sonnet + auto). Hand-filed children whose subject starts with the word `Question` are creator questions, not work.
  362. Tested (own tickets + ident on 8751/8752, `run` workers 8780-8799, fake claude only):
  363. `COLONY_E2E_PORT_BASE=8750 node tests/e2e.mjs` 187/187 (169 old, old-text checks rewritten to the new texts, + 18 new);
  364. with the m012 tickets 175/175. Logs `.scratch/m023/e2e-fake-2.txt`, `e2e-fake-m012.txt`; every scheduler text of the run
  365. `.scratch/m023/texts-2.md`; run outputs `.scratch/m023/run-logs-2/`. Pre-023 code: `.scratch/m023/orig/`.
  366. Not done / open:
  367. - No real Claude run: whether Sonnet keeps `result`/`test` within the limits is untested (the schema only says it in the
  368. descriptions — `maxLength`/`pattern`/`maxItems` were left out because it is unknown whether `claude --json-schema`
  369. accepts them; `report.hl` refuses a too-long result → the ticket goes back to open, which costs a whole session).
  370. - Worker free text quoted in tickets (questions, issue repro/observed/expected) is only clipped where it becomes a single
  371. line (subjects, bullets); a long question or repro stays long.
  372. - Haiku + the default mode `auto` still falls back to `default` (Haiku has no auto mode) → with prompts off it can
  373. edit nothing; `bypassPermissions` stays refused (question for the creator).
  374. - Old tickets keep their old long texts (nothing rewritten).
  375. ## 2026-09-24 — blocked-by, questions as tickets, rejections as work (mission 022, antcolony#1) — awaiting the architect's check
  376. Done (README "Relations, questions, rejections", `lib/relations.hl`): `next`/`cycle`/`run`/`work` treat a ticket with
  377. a blocker that is not `confirmed` ("blocked by X#n (state)") or with children ("a parent …") as not eligible — the
  378. scheduler's own creator-question children don't count; a `rejected` ticket whose last rejection is newer than the last
  379. colony session start is eligible again (`work` leases it `rejected → in progress`), its brief STARTS with `REJECTED by
  380. the creator: <text>` + the creator's comments since the last session + the "build what was described" rule (kept until
  381. a colony report answers it); `report --post` files every `questions` entry as its own ticket in the ticket's project
  382. (`awaiting creator`, parent = the ticket, source `colony-report:<S>:questions:<i>`, idempotent), links it in the comment,
  383. and turns `issues[].blocks = true` into a `blocked-by` link; unknown-project and Nth-fail creator questions get the
  384. ticket as parent. Every brief has a "Relations" section. `templates/report.md`: one self-contained question per entry,
  385. `[]` when none. Fake claude: `questions` default `[]` (was `['fake worker: none']`), `FAKE_QUESTIONS`.
  386. Tested (own tickets + ident on 8751/8752, fake claude only, tickets now started WITH a creator identity):
  387. `COLONY_E2E_PORT_BASE=8750 node tests/e2e.mjs` 169/169 (144 old — 4 report checks adapted to the new link event /
  388. question ticket — + 25 new); with the m012 tickets (no relations, no read view) 159/159. Logs `.scratch/m022/e2e-fake-1.txt`,
  389. `e2e-fake-m012.txt`, briefs + the `run` output `.scratch/m022/briefs/`. Pre-022 code: `.scratch/m022/orig/`.
  390. Not done / open:
  391. - `next --post`'s project-level questions stay in `antcolony` without parent; `cycle` / `run` still never file them.
  392. - A rejected ticket "not newer than the last session" can hardly happen (every rejection is a new event after the lease);
  393. that branch (`work: REFUSED — … no rejection is newer`) is not exercised by the e2e.
  394. - Question children of a ticket are never checked by the scheduler (an unanswered question does not hold the ticket).
  395. - Rejected tickets are ordered like open ones (oldest first), not first.
  396. - No real Claude run in this mission.
  397. ## 2026-09-24 — `run` daemon: loop, expiring leases, quota reserve, parking + resume, ports per session (mission 020, antcolony#1/#2 build order 4 part 2) — awaiting the architect's check
  398. Done (README "run", "Leases", "Quota + parking"): `./colony run [--once] [--interval S] [--parallel K] [--reserve P]
  399. [--port-pool A-B] [--ports-per-session N] [--lease-ttl S] [--heartbeat S] [--live]` (`lib/daemon.hl`): per iteration
  400. expire dead leases → resume due parked sessions → start eligible tickets of this host (one per dev folder) while slots
  401. are free and the `/usage` quota is below the reserve; one `ITER` line per iteration, `SESSION END` per session.
  402. Leases carry an expiry marker + heartbeat comments (`lib/lease.hl`, also for `work`/`cycle`); a restarted run skips
  403. live leases. Usage-limit evictions and the 2nd SIGTERM park the session (`colony-parked` marker, ticket stays leased),
  404. resumed with `claude -p --resume` (worker) or a new controller. Port range per session → brief + env `COLONY_PORTS*`.
  405. Wrapper `colony`: setsid + SIGTERM/SIGINT → stop file (1st finish, 2nd park). Refuses live tickets without `--live`.
  406. `./colony leases [--expire]`. `on Error` in scheduler.hl: a fetch failure no longer aborts (status 0).
  407. Quota reading (proved, $0): `claude -p /usage … --verbose` is a local command (0 turns, cost 0, ~1–4 s);
  408. `usage_report.rate_limits.limits[kind=session].percent` + `resets_at` (`.scratch/m020/usage-probe/`: the first probe
  409. by hand and one through `lib/quota.hl` → `{"percent":5,"resetsMs":1790274000279,"weekly":41,"cost":0}`).
  410. Tested (own tickets + ident on 8761/8762, workers 8780-8799): `COLONY_E2E_PORT_BASE=8760 node tests/e2e.mjs` 144/144
  411. twice (119 old + 25 `run`, fake claude only), with the m012 tickets 143/143. Logs `.scratch/m020/e2e-fake-{1,2}.txt`,
  412. `e2e-fake-m012.txt`, run outputs `.scratch/m020/run-logs-2/`. Pre-020 code: `.scratch/m020/orig/`. No real worker run.
  413. Not done / open:
  414. - Real Claude never hit the limit here: the rate-limit detection (rejected `rate_limit_event`, 429, "hit your limit")
  415. is from the verbose output format seen in normal runs + guesses at the error result; verify on the first real eviction.
  416. - No tickets live events (polling only; `--interval`); no WebSocket / agent split; quota per host = per logged-in account.
  417. - Heartbeat = a comment every ttl/3 (tickets has no editable lease field) → noise in the history; expiry puts the
  418. ticket back to `open` (concept says "host offline, never failed").
  419. - A crashed / SIGKILLed run kills its Claude sessions (hl:proc PDEATHSIG) — work is lost, the lease expires, a new
  420. session starts from the history (no `--resume` after a crash).
  421. - Parked sessions resume only on the host that parked them; if it never comes back the lease expires (resume + ttl).
  422. - "no verdict" (controller crashed) still leaves the ticket leased → with leases it goes back to `open` after the ttl.
  423. - `run` is not a container / service yet; weekly limit only printed, not enforced.
  424. ## 2026-09-24 — controller step + `cycle` built (mission 019, ticket antcolony#1 build order 4 part 1) — awaiting the architect's check
  425. Done (README "The controller", "check", "cycle"): after a schema-valid report `work` starts a second
  426. one-shot Claude session (same safety settings, Edit/Write/NotebookEdit disallowed, same dev folder;
  427. input = templates/controller.md + report + compact transcript of the worker's session + brief) →
  428. `verdict.json` `{verdict pass|fail, findings[], summary}` (`--json-schema templates/verdict.schema.json`;
  429. code validates, a pass with a `false`/`no evidence` finding becomes a fail). `--post` follows the verdict:
  430. pass → report comment + controller section + `awaiting creator`; fail → findings comment → `open`; Nth
  431. fail (`--max-fails`, default 2) → creator question + `on hold`. `./colony check <run dir> [--post]` (reuses
  432. verdict.json), `./colony cycle [--post] [--dry-run]` (next on THIS host → work → controller → post, summed
  433. cost), `work --dry-run`. Refactor: `lib/claude.hl` (session runner shared by worker + controller).
  434. Tested (own tickets + ident on 8761/8762): `COLONY_E2E_PORT_BASE=8760 node tests/e2e.mjs` 119/119 (fake
  435. worker + fake controller), with the m012 tickets 118/118; `COLONY_E2E_REAL=1 …` 124/124 with REAL Sonnet:
  436. cycle → worker made hello.txt ($0.087, 4 turns), controller re-ran the cat → PASS ($0.175, 3 turns),
  437. posted; fake worker claiming `missing.txt` + REAL controller → FAIL, both findings `false` ($0.104, 4
  438. turns), back to open. No permission denials. Logs: `.scratch/m019/e2e-fake-2.txt`, `e2e-fake-m012.txt`,
  439. `e2e-real.txt`; real run folders `.scratch/m019/real-runs/`. Pre-019 code: `.scratch/m019/orig/`.
  440. Not done / open:
  441. - Controller runs with host access like the worker (auto-mode classifier + instructions + no Edit/Write);
  442. a malicious report could name a harmful command to "re-run" — only the classifier and the prompt stop it.
  443. - No verdict → the ticket stays `in progress` (no lease expiry yet); retry by hand with `check`.
  444. - A failed report's `issues` are not filed (listed in the fail comment); the fail count lives only in the
  445. ticket's comments (markers).
  446. - `cycle` does one ticket per call, no loop / daemon; picks only tickets whose dev folder is on this host.
  447. - Everything from mission 016 below still open (daemon, quota, ports per session, isolation).
  448. ## 2026-09-24 — agent v0 `work` built (mission 016, ticket antcolony#2)
  449. Done: `./colony work <project> <n> [--post] …` (README "work"): brief → lease (`in progress`, "session
  450. <id> started on <host>") → `claude -p` headless in the dev folder (`--json-schema`
  451. templates/report.schema.json, `--permission-mode auto`, `--permission-prompts none`,
  452. `--strict-mcp-config`, model/max turns/timeout/budget configurable) → `runs/<session>/` (brief, raw
  453. result, stderr, report, session.json with cost/usage) → `report` validation → `--post`; no valid report
  454. → back to `open` with the reason. Scheduler fixes: `"workers": false` → never eligible ("takes no
  455. workers", no creator question), `work` refuses it; registry `projects/` here is the single source
  456. (`COLONY_PROJECTS_DIR`, default `./projects` beside scheduler.hl). `brief.hl`/`report.hl` refactored
  457. into `buildBrief` / `reportFile` (same output).
  458. Tested (own tickets + ident on 8751/8752): `COLONY_E2E_PORT_BASE=8750 node tests/e2e.mjs` 101/101 (fake
  459. claude), with the m012 tickets 100/100; `COLONY_E2E_REAL=1 …` 106/106 with the REAL claude: Sonnet
  460. created `hello.txt`, report posted, `awaiting creator` ($0.18, 4 turns); Haiku `--max-turns 1` →
  461. `error_max_turns` → back to `open` ($0.06). Logs: `.scratch/m016/e2e-real.txt`, `e2e-fake.txt`,
  462. `e2e-fake-m012.txt`. Claude flag probes: `.scratch/m016/probe/`.
  463. Not done / open:
  464. - No daemon / WebSocket / heartbeat / lease expiry, no quota reserve or parking (`--resume` with the
  465. recorded Claude session id is possible later), no port-range assignment per session (briefs keep
  466. `--ports` / `COLONY_PORTS`), no controller step, no isolation (worker = host user `mre`).
  467. - Auto mode is unavailable for Haiku (falls back to `default` → with prompts off nothing can be
  468. edited); `work` only WARNS after the fact. Could refuse up front or use `stream-json` and kill early.
  469. - Lease + give-back are one state event with text each (not a separate comment).
  470. - Never run against live tickets (rule); first live `work` = architect with the Colony token.
  471. - Exit status always 0 (Hybriel) — read the last line (`WORK DONE/OK/FAILED`).
  472. Hybriel findings (not yet filed): (020) inside an object literal a field defined EARLIER shadows an outer
  473. variable of the same name (`let ref = {project='p'}; { ref = 'x#1' project = ref.project }` → unlocated
  474. `error.NotAnInstance`); no signal handlers (the wrapper does SIGTERM); hl:proc children get PDEATHSIG=SIGTERM
  475. (undocumented in server.hl); options after the script need `--`; no process exit status; hl:proc
  476. `spawn`/`spawnArgs` have no cwd/env options (work uses `sh -c`); hl:proc/hl:fs offer no call for the script's own
  477. absolute directory (the `colony` wrapper exports `COLONY_HOME`); (019) no `Math` (`round4` uses `%`); an
  478. object stored in another object's field is a COPY — later changes to the original are not seen
  479. (`meta.controller = cm` must be re-assigned before each write).
  480. ## 2026-09-26 (3rd session) — antcolony#20 local models: CPU still too slow
  481. Tried the already-running Nemotron-3.5-Lightning-30B-A3B (MoE, CPU, container on :8821) with `.scratch/loc/eval.py`: 4 librarian prompts (~3k tokens each) did not finish in 900 s (killed). Same wall as Qwen3.5-9B: prompt processing on CPU is the bottleneck. Still needed: GPU visible to the worker box (Vulkan lists no device; /dev/dri exists) or a much shorter librarian prompt. Local option stays opt-in; default stays `sonnet`.

Branches

Latest commits

  • a6af7883tracker: worker box sees calendar.worldapi.org (login to copy)mre
  • c613d26btemplates: bridges to external components (login.js for ident's selector) are allowed (creator 2026-09-27)mre
  • 9062978ctracker: worker box sees /media/STORAGE/projects/old-tracker read-only (tracker#2 source data)mre
  • 7f9660eeState of 2026-09-27, before the move to gitoriamre