aboutsummaryrefslogtreecommitdiffziptar.gz
path: root/CHANGES.md
blob: f6d9cc06c6570f741a563511c29ff02d6af45839 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
# Changes (newest first)
- 2026-10-07 Lane cloud: one stuck task no longer stops it: `wf orch post <id> cloud` with awaiting / handback / lost parks only that task (awaiting: park as local lanes; handback / lost: `Cloud: no` + status cleared + note, local lanes may retry with pull's Recovery note), prints `alert: …; lane cloud keeps picking`, then the next cloud pick (never the same id). Projects: nothing.
- 2026-10-07 Owner-absent default: workers never wait; owner-only step → `wf add -s human` + `wf set <id> --after <h-id>` + status clear, result `needs-owner <h-id>`. `wf orch post` parks it (After: the h-task, claim cleared, alert), lane keeps picking; owner's `wf done <h-id>` makes it pickable again. Worker def, shared CLAUDE.md, wf-orchestrate, wf-pilot, batch prompt, docs. Projects: nothing.
- 2026-10-07 One stuck task no longer freezes its lane: `wf orch post` with awaiting / handback / post-check-red (local lanes; lane cloud unchanged: pull re-queues) parks only that task (blocked on the a-id named in the result, else `Sessions: owner` + an `orch …` note; handback also clears its claim), commits, prints `alert: <id> <outcome> → tell the owner (…); lane <lane> keeps picking`, then the lane's next pick. `stop lane` only for none / stop file / push-failed / wip / no report. Batch prompt, wf-orchestrate, wf-pilot, docs: keep picking, never wait on the owner while tasks are pickable. Projects: nothing.
- 2026-10-07 `wf orch post` done: leftover TASKS/archive changes in the main tree are committed (`<id> done (code <sha>)` in a split project, else `<id> done (orchestrator)`); split: a `--commit` sha not in the code repo (stale private HEAD) is replaced by the code repo's master sha (noted). wf-worker: the report's commit = first sha of `report: commit …`, never a looked-up HEAD. Projects: nothing.
- 2026-10-07 wf start refuses an existing worktree of another repo; .wf-home ignored by finish/merge stray checks. Projects: nothing.
- 2026-10-07 split projects 6/6: `wf check` split rules (cloud error; warns: no push, `.wf-home` not git-ignored, merged code worktrees); docs. Projects: split projects: push key, .wf-home in the code repo's .gitignore (migration task in the workflow project).
- 2026-10-07 split projects 5/6: `wf orch pick/post` use the code repo (worktrees, branch/merge checks, commit sha); `.wf/push-failed` after a done worker stops the lane (`push-failed`). Projects: nothing.
- 2026-10-07 split projects 4/6: workflow.toml `push` (cwd root, env WF_MAIN), `wf push`, `.wf/push-failed` marker (`wf next` shows it); finish report gains ` push-failed <rc>`. Projects: split projects set push (follow-up migration task).
- 2026-10-07 split projects 3/6: `wf finish` / `wf merge` / `wf wip` across code + private repo: paths under the private root are committed there (with TASKS/archive, message `<msg> (code <sha>)`), code paths on the branch; no code paths → no code commit; report `commit <code|-> books <private>`; `wf done` merge advice names the private books. Projects: nothing.
- 2026-10-07 split projects 2/6: `wf start` makes code worktrees (branch in the code repo, `.wf-home` pointing at the private project); `wf next` multi-session advice names `wf start` in the code repo. Projects: nothing.
- 2026-10-07 split projects 1/6: Config.split, push key, .wf-home discovery. Projects: nothing.
- 2026-10-07 Shared push rule: in a split project the public `code_root` repo is pushed only via the project's publish command, never `git push home --all` (that pushes local review branches unscanned). Projects: split projects name their publish command in their CLAUDE.md.
- 2026-10-07 Denylist guard at commit time: `.githooks/pre-commit` (staged lines + paths) and `.githooks/commit-msg` run `scripts/denylist_check.py` against the git-ignored `publish-denylist.local` (worktree top + main tree, plus `git config denylist.file` lists; `word` / `!token` exemption / `#`, case-insensitive; output `word #<line>` only; no list → warning). Enable per clone: `git config core.hooksPath .githooks`; audit: `denylist_check.py tree`. `scripts/publish_snapshot.py` removed (history is public now). Projects: nothing.
- 2026-10-07 Tests use generic fixtures (/h/u, 10.0.0.x) instead of real home-dir and LAN paths (publish-scan clean). Projects: nothing.

- 2026-10-06 Tool path is now `/projects/public/workflow` (was `/projects/workflow`): docs, shared CLAUDE.md, skills, wf-worker agent, messages. `wf projects` / `wf usage --report` scan the grandparent when the parent holds no project. Projects: point `~/.claude` symlinks/settings, `wf-res.service` and any script calling `wf.py` at the new path.
- 2026-10-06 New `scripts/publish_snapshot.py [DEST]`: scrubbed fresh-history snapshot of the master tree into a separate local repo (default ~/src/wf-public; drops inbox.md, .worktrees/, __pycache__/, out/); refuses on any word of the git-ignored `publish-denylist.local` in a path or file; one commit per run (new CHANGES lines as message); never pushes or adds a remote (docs/manual.md). Projects: nothing.
- 2026-10-06 docs/manual.md: owner-facing manual (setup, daily use per session type, writing good tasks, best practices, troubleshooting); linked from the README top (replaces 'no installation guide'). Projects: nothing.
- 2026-10-06 `wf orch post`: `--duration 0` (orchestrator lacked duration_ms) falls back to the time since the pick like an omitted one (was logged `0m00s`, starving the task p90 of `wf batch --left/--time-left`); a post-check-red post keeps the orch record, so the re-post after the fix logs the real duration. Projects: nothing.
- 2026-10-06 `wf res` entry project = main tree name (git common dir's parent), not the lane worktree dir (was 'slow'/'fast-2': history kinds split per worktree); `wf res hist`, history hints, `wf batch --status` use it too. Older history records keep their worktree name. Projects: nothing.
- 2026-10-06 `wf batch K --left DURATION`: K' = min(K, floor(left / task p90)) (p90 of done/handback durations in `out/wf-orch.log`, local lanes, > 0; < 3 runs → 30 min), prints `fit: K' of K tasks (…)`, K' = 0 → nothing started (rc 0); `--for` defaults to left. New `wf batch --time-left DEADLINE` → `time left X, task p90 Y (n runs): spawn|stop`; batch prompt runs it before each round (deadline = start + ceiling) and stops with 'stopped: deadline (…)'. wf-pilot launches with `--left <time left>` (was `--for <time left, ≥ 1h>`: a pilot of a few hours closed ~1h early). Projects: nothing.
- 2026-10-06 `wf res` reservations from history: finished runs (rc=0, peak) go to `~/.local/state/wf/resources-history.jsonl` when pruned from the ledger; new `wf res hist [--project P]` = per project and title kind (title minus trailing sha/hex words and `(…)`) n, request, peak p50/p95, estimate, duration p50/p90, suggestion (≥ 3 runs: p95 peak ×1.15 ≥ 0.2 GB, p90 duration ×1.5 ≥ 5 min); `run`/`note` asking > 2× it print one `hint: history says ~X GB / Y min (n runs)` line on stderr (no auto-resize); `wf batch` default `--mem`/`--for` = the project's `wf-batch` suggestion when it exists (ceiling stays 6h; not `--prep`). Projects: nothing.
- 2026-10-06 `wf batch` cloud tail: when the orchestrator exits with `.wf/cloud` records left, the batch sidecar keeps pulling every 10 min (`wf orch post … --no-pick`, no picks/sends) until none remain, `out/wf-batch.stop` or 24 h (`batch-sidecar --cap`); the job's ledger entry shrinks to 0.2 GB / 1 cpu (via `WF_RES_ID`; unit MemoryMax unchanged); summary line `cloud tail ended: <why>; <n> pulls; left: …`. Cause: tasks sent at batch end stayed unpulled. Projects: nothing.
- 2026-10-06 `wf batch` on a `cloud = true` project pulls cloud tasks itself: the job runs `wf_res.py batch-sidecar` around `claude -p`, every 10 min while it lives (until the stop file) `wf cloud pull --all` → per ended task `wf orch post <id> cloud --result <state> [--commit <sha>] --no-pick` + a `(sidecar pull)` summary line; batch prompt: the orchestrator only picks cloud, never pulls (pulls starved while it blocked on foreground workers). `wf cloud pull`: flock on the task record, a second concurrent pull of one id prints `<id>: pulled by another wf cloud pull, skipped` (rc 0) instead of `branch … exists (local WIP?)`. Projects: nothing.
- 2026-10-06 Cloud routing per task: `wf add --cloud yes|no` (like `wf set --cloud`); `Cloud: yes` still needs Model opus (sonnet/haiku never fit, was: yes overrode Model) and skips only the regex list; `wf orch pick cloud` order = `Cloud: yes` first, then prio, then larger effort (was: opus first). shared/CLAUDE.md "Lanes and models": Cloud bullet (classify at add); wf-worker follow-ups get `--cloud` in cloud projects. Projects: with `cloud = true`, mark runner-ready opus tasks `Cloud: yes|no`.
- 2026-10-06 `wf finish` no longer half-finishes: a PATH outside the repo (e.g. a tool/other-project file), missing, unchanged (lane worktree) or the worktree's own TASKS/archive copy is refused before done; an id already archived resumes (commit + merge) instead of `unknown id`; a git add/commit failure after done says rerun resumes. `wf done`/`wf finish` in the main tree refuse a task `in progress: <branch>` checked out in a linked worktree (run it there, or `wf status <id> clear` first). wf-worker.md: paths = worktree files only, never hand-edit/commit the books. Cause: workers passed other-repo paths → done ran, commit failed, retry `unknown id` → books hand-edited on the branch / left uncommitted in the main tree. Projects: nothing.
- 2026-10-06 `wf res run --lock KEY`: one queued/running job per KEY and main tree (lane worktrees share it); titles starting with `gate` lock `gate` unasked, so overlapping gates in one shared gate checkout are refused (exit 3 `busy: lock 'gate' held by r-N …`, also with --force) or wait with --queue (queued lock-blocked entries are skipped by the FIFO, not blocking others). Ledger field `lock`. The 'ambiguous argument %s' in a-game-project-builder gate logs r-671/r-672 = nested `\"%h %s\"` quoting in a hand-written bash -c copy of gate-bg.sh (no wf/systemd expansion; test pins verbatim argv). Projects: nothing (gate scripts titled `gate …` get the lock).
- 2026-10-06 `wf cloud pull` archives each session it ends (done/awaiting/handback/lost) in the claude.ai app via the CLI's internal `POST /v1/code/sessions/<sid>/archive` (login token read in-process, never printed); failure → one `archive <sid> failed: …; archive by hand (wf cloud archive --ended)` line, pull's exit code unchanged. New `wf cloud archive <sid>|--ended`. Ledger rows get `archived: true`. Projects: nothing.
- 2026-10-06 `wf cloud pull`: no `● WF-RESULT` but the last assistant message ends in a bare `WF-PATCH-END` (session dropped the key words) → handback `bad result: no WF-RESULT key` (usage charged, patch kept when a `sha256=… bytes=…` header decodes) instead of running until 24h lost. Projects: nothing.
- 2026-10-06 Cloud prompt: final-message lines written literally (`WF-RESULT <…>`, …; the `[WF-RESULT R]` form made a live session drop every key word → pull saw no result), the usage script prints the `WF-USAGE` line and the patch command prints the `WF-PATCH-BEGIN sha256=… bytes=…` / base64 / `WF-PATCH-END` block to copy; commit only needed paths (no __pycache__/bin/obj). `wf cloud send --dry-run` snapshots into `out/cloud/<id>.dry-run`: it no longer deletes the live snapshot of a sent task. Projects: nothing.
- 2026-10-06 `wf orch pick cloud [--id ID]`: virtual lane cloud = stop file, ledger check (`stop lane cloud: ledger|max parallel (…)`), first task across all lanes that is runner-ready, not in progress and fits the cloud rules (opus first; none → `stop lane cloud: none fit (…)`) → `wf cloud send`, orch record lane cloud (task_lane, branch); `wf orch post <id> cloud --result <state>` after `wf cloud pull --all` (branch check uses the recorded `<task lane>/<id>`). Local lanes already skip `in progress: cloud:*`. docs/orchestrator.md "Cloud lane", wf-orchestrate skill. Projects: opt in with `cloud = true`.
- 2026-10-06 `wf cloud pull <id> | --all [--export FILE] [--no-push]`: teleport + /export, parse the final `● WF-RESULT` message (wrapped header/base64 rejoined, sha256 + bytes checked, gunzip); done → patch paths checked (outside the project / TASKS / archive / .wf / .worktrees / out / cloud_include refused), `git am --3way` on `<lane>/<id>` from the recorded master in a free lane worktree, worktree_setup, quick_gate, wf done -m "<WF-REPORT> (cloud <sid>)" + wf merge, `report: commit <sha>`; awaiting → wf add -s awaiting + blocked; handback / red gate / bad patch → note `Recovery: cloud attempt <sid> — <why>`, status clear, patch kept in out/cloud/<id>.patch; no result → running (exit 4), > 24h → lost. Every end charges the ledger and deletes snapshot + record; branch exists / worktree setup failed → exit 1, session kept. `wf.lane_worktree` shared with orch pick. Projects: nothing.
- 2026-10-06 `wf cloud send <id> [--dry-run] [--project DIR]`: snapshot of the project's master (git archive minus TASKS/archive/.wf/.worktrees/out, plus `cloud_include`) in `out/cloud/<id>` as a one-commit repo, 90 MB packed cap, prompt `templates/cloud-prompt.md` (task + area notes + `cloud_note`, WF-RESULT/REPORT/USAGE/PATCH final-message rules, usage script), ledger reserve (refused: exit 3), `claude --cloud`, claim `in progress: cloud:<sid>`, record `.wf/cloud/<id>.json`. `cloud.final_message(export)` = the marker parser (only an assistant `● WF-RESULT` message). New workflow.toml keys `cloud`, `cloud_include`, `cloud_note`. Projects: nothing (opt in with `cloud = true`).
- 2026-10-06 Cloud pty driver (library, no command yet): `wf_cloud.send(folder, prompt) -> sid` runs `claude --cloud` on a pty (pre-accepts the trust dialog in ~/.claude.json, Down+Enter fallback), `wf_cloud.export(folder, sid, out) -> path` = `--teleport` → `/export` (Enter retries) → `/exit`, teleport retried once; `cloud.strip_ansi/parse_sid/trust` pure. Env `WF_CLAUDE`, `WF_CLAUDE_JSON`. Projects: nothing.
- 2026-10-05 `wf wip <id> -m NOTE [--commit MSG] [PATHS]` (lane worktree): wrap-up in one call = commit paths, note, status clear; wf-worker prompt uses it. Projects: nothing.
- 2026-10-05 Lane worktree config: wf run inside a linked worktree whose copy of the project has a workflow.toml reads `worktree_setup`, `quick_gate`, `areas`, `area_stale_commits`, `area_ignore` from that copy, and the areas file (default CLAUDE.md) resolves there: a branch can test its setup/gate/area edits before merge; `wf areas --mark` writes the worktree copy (commit it on the branch). Tasks/archive/ledgers/other keys stay the main tree's. New `config.load_at` / `find_local`. Projects: nothing.
- 2026-10-05 `wf orch pick <lane> [--id ID] [--recovery WHY]` (stop file, runner pick skipping in-progress, claim, free worktree `.worktrees/<lane>`/-2… (no live session cwd, no other picked worker, clean detached or own branch), prints the wf-worker prompt; record `.wf/orch/<id>.json`) and `wf orch post <id> <lane> --result LINE [--commit] [--agent] [--duration] [--no-pick]` (post-check: archive line, branch gone, worktree clean + in master else wf merge, wf check; leftover commit otherwise; out/wf-orch.log + wf-cost.log lines; model-raised detection; next pick or `stop lane`). wf-orchestrate 'One worker', docs/orchestrator.md, batch prompt use them. Projects: nothing.
- 2026-10-05 `wf res` ledger fix: entries vanished (ledger moved to .bad, restarted empty at r-1) when a process running older code (a `wf res wait` started before the `by`-field release) read entries with a key it did not know. Unknown entry keys are now ignored; a corrupt ledger restarts with its salvaged id counter; starting a job removes stale logs/<id>.rc/.peak. Projects: nothing.
- 2026-10-05 wf finish prints `report: commit <sha> [tool <sha>]` (+ --tool-commit); wf-worker.md Report says copy it. Projects: nothing.
- 2026-10-05 `wf ctx <id>` ends with the notes (code map, test recipe…) of every area the task names (area name, code-map anchor or Paths entry, whole word). workflow.toml `code_root`: areas' anchors / Paths / Checked refer to another repo (wf areas, --mark, check, stale t-map tasks; no uncovered nudge). Projects: nothing.
- 2026-10-05 /wf-orchestrate-loop retired (duplicate of /wf-pilot): the skill only points to /wf-pilot for one release, then is removed; docs/orchestrator.md section dropped. `.gitattributes`: CHANGES.md merge=union (parallel releases no longer conflict on the top line). Projects: nothing.
- 2026-10-05 `wf start <id> --worktree PATH --branch B [--recovery]` (main tree): worker setup in one call = worktree add/switch (dirty refused; --recovery keeps a dirty WIP on B and prints it with master..HEAD), worktree_setup, status progress B, wf ctx, a ready `cd wt && (verify) && wf finish …` line. wf-worker.md Start section → that one call. Projects: nothing.
- 2026-10-05 shared/CLAUDE.md trimmed 7.1 → 4.9 KB (same rules, less wording; TASKS item format left to wf check; new line: batch independent tool calls). Projects: nothing.
- 2026-10-05 `wf res` entries name their owner: ledger field `by` (name: `--by` on run/note, else WF_SESSION_NAME, else `<lane> session` from .wf/sessions by CLAUDE_PID; task: WF_TASK, else `<lane>/<id>` branch; batch: WF_RES_ID, now set in every job unit; address: uds:<messaging socket>). `wf res status` lines end `[by … , message uds:…]`, throttle warning ends `; started by …`. Projects: nothing.
- 2026-10-05 `wf res run/note --force`: fit against MemAvailable − user reserve − headroom only (ledger claims + queue ignored; entry still recorded); busy line ends with '; X GB really free beyond the reserve: --force starts it past the ledger (…)' when --force would fit; refused → 'busy even with --force: …' exit 3. `wf batch --prep` / `wf prep` default --mem 1G (was 4-8G). Projects: nothing.
- 2026-10-05 Batch stop at once: batch prompt, wf-orchestrate-loop, wf-orchestrate 'One worker' check `out/wf-batch.stop` before EVERY spawn (not per round; running workers finish, latency ≤ the running tasks); batch prompt gets the absolute stop path; `wf lanes --wait` exits 2 ('stop requested') as soon as the stop file exists; pilot/loop treat exit 2 as stop. Projects: nothing.
- 2026-10-05 Uncovered-area nudge: when a project's areas use `- Paths:`, `wf done` adds `t-map-<folder>` (≤3, once per id, also not when archived) for folders (≤2 levels) the task's diff (branch since merge-base with master/main + uncommitted + untracked; bookkeeping files skipped) touches outside every area's Paths (an area without Paths: folders of files holding its Code map anchors); `wf areas` prints `uncovered: <folder> (n files)` lines. New workflow.toml `area_ignore` (default tests/test/docs/doc; dot folders and root files always skipped). Projects: nothing (optional area_ignore).
- 2026-10-05 `wf finish <id> -m ENTRY [--commit MSG PATH…]` = quick_gate → done → commit explicit paths → wf merge in one call (main tree: TASKS/archive join the commit); refuses before done on gate red / stray uncommitted files. `wf ctx <id>` prints a `Verify (run before wf finish):` line. wf-worker.md Done uses finish. `wf usage --explore`: `git worktree list` / `git branch --list` no longer count as bookkeeping. Projects: nothing.
- 2026-10-05 Prep batch: `wf batch K --prep [--lanes …]` = headless run (templates/prep-prompt.md) where sonnet subagents write Done (+Model) for up to K pending tasks without Done (not owner-bound, no status/open slices; pickable first); unclear → awaiting + blocked; summary lines `id → Done: …` | `id → awaiting a-…`; none → 'nothing started'. New `wf set <id> --done TEXT` ("" removes). wf-pilot / wf-orchestrate-loop run a prep batch when idle with not-runner-ready tasks (once per idle spell). Projects: nothing.
- 2026-10-05 wf-pilot / wf-orchestrate-loop: every PushNotification also logged as 'ALERT ...' line in out/wf-orch.log + summary; docs/orchestrator.md names the push setting (agentPushNotifEnabled). Projects: nothing.
- 2026-10-05 `wf batch` writes the `out/wf-batch-*.md` "# wf-batch <project> <time> (N, lanes)" header itself before launch (also --dry-run); prompt only appends. Projects: nothing.
- 2026-10-05 `wf merge` on a detached-HEAD lane worktree with commits not in master now rebases + ff-merges them (message 'bookkeeping', output 'merged detached HEAD'), never only the bookkeeping; dirty worktree refused in both modes; `wf done` there warns 'detached HEAD has N commits not in master'. Orchestrator post-check (wf-orchestrate, docs/orchestrator.md): worktree HEAD ancestor of master. Projects: nothing. (`wf check` unaffected.)
- 2026-10-05 `wf usage --log ... --duration <s>` writes `dur=` (agent wall time); `wf usage --report` adds med_dur column; wf-orchestrate / loop pass duration_ms/1000. Projects: nothing.
- 2026-10-05 Stopped lane (handback/awaiting) resumes only after the task/fix that stopped it is done, or the owner says so: wf-orchestrate-loop, wf-pilot, batch prompt text. Projects: nothing.
- 2026-10-05 `wf add --done "<text>"` writes the Done line (follow-ups born runner-ready); `wf add -p 0` without Done warns on stderr naming --done; wf-worker adds follow-ups / gate-fix tasks with --done. Projects: nothing.
- 2026-10-05 `wf merge` run again in the (detached) worktree after a merge commits TASKS.md/archive changes made since (late notes, follow-ups; message 'bookkeeping'); nothing dirty → still 'nothing to merge'. Workers: run `wf merge` once more after post-merge `wf add`/`note`. Projects: nothing.
- 2026-10-05 Gate-red outcome: new optional workflow.toml `quick_gate = [...]` + `wf gate` (runs it in the current tree, red = exit 1); wf-worker runs `wf gate` before `wf done`. Async slow gate red not caused by the worker's diff → worker adds a runner-ready P0 fix task and reports `done+gate-red <culprit> <fix-id>`; orchestrate / loop / batch prompt treat it as done and pick the fix next (lane not stopped); `wf usage --report` counts it as done. Projects: optional — set `quick_gate` to a fast regression check (e.g. contract tests).
- 2026-10-05 `wf lanes` / `lanes --wait` count runner-pickable (= `list --runner --lane`: needs a usable Done); not-ready ones shown as "· N not runner-ready (no Done)". `wf next` lanes block unchanged. Projects: nothing.
- 2026-10-05 New skill `/wf-pilot [--batch 4] [--lanes a,b] [--for 8h]`: nested overnight pilot running `wf batch K` in a loop (wait via `wf res wait`, idle-poll `wf lanes --wait`, stop via `wf batch --stop`, PushNotification on stop/awaiting/end); docs/orchestrator.md 'Pilot (nested)'. Install: `ln -s /projects/workflow/shared/skills/wf-pilot ~/.claude/skills/`. Projects: nothing.
- 2026-10-05 `wf batch --stop`: creates out/wf-batch.stop; batch checks it before each round, stops ("stopped: stop file"), removes it; `--status` shows it. Projects: nothing. (`wf check` unaffected: no change to check code.)
- 2026-10-05 New skill `/wf-orchestrate-loop [N] [--lanes a,b] [--for 10h]` (replaces the `loop N` argument of wf-orchestrate, same release day): piloted loop, typed into any idle project session (e.g. phone Remote Control); docs/orchestrator.md 'Piloted loop session'. Install: `ln -s /projects/workflow/shared/skills/wf-orchestrate-loop ~/.claude/skills/`. Projects: nothing.
- 2026-10-05 `/wf-orchestrate loop N [--lanes a,b] [--for 10h]`: piloted overnight loop mode (background workers, never asks, idle-poll via `wf lanes --wait`, summary in out/wf-batch-*.md); docs/orchestrator.md 'Piloted batch session'. Projects: nothing (skill symlink picks it up at next session start).
- 2026-10-05 `wf lanes --wait SECS`: block until any lane has a pickable task (exit 0) or timeout (exit 1); prints the lanes line either way. Projects: nothing.
- 2026-10-05 `wf body -h` names stdin, kept lines (Model/Sessions/After/Ref), heredoc example; `wf body ID text` errors with stdin hint. Projects: nothing.
- 2026-10-05 `wf list --runner` no longer lists sliced-out parents (effort > slice_above, slices all archived); row set
  matches `wf lanes` pickable. Projects: nothing.
- 2026-10-05 Model-lane leftovers removed: `wf batch --lanes <model>` warning (a model name is now just an
  unknown lane), old `{haiku,sonnet,opus}.json` registry cleanup. docs/model-lanes.md folded into docs/lanes.md
  (now a current reference: Model line §0, registry/claims §4). Projects: nothing.
- 2026-10-05 Speed lanes: lanes by size instead of model (`[lanes.*]` in workflow.toml; default fast = <1h
  unblock-first + slice jobs, slow = 1h priority-first, falls back to fast), `slice_above` (default 1h: bigger =
  slice job, split never implement), sessions take Model ≤ their own (`wf next --as M [--lane L]`), `wf lanes`,
  orchestrator/worker/batch by lane, `wf areas` (code-map anchors, staleness, `--mark`) + `wf done` auto-adds
  `t-map-<area>` refresh tasks. Old: `--lanes <model>` warns; old model registry files dropped. Spec: docs/lanes.md.
  Projects: rollout — area sections get `Paths:` + first `wf areas --mark`, remove merged model worktrees.
- 2026-10-05 `wf setup` (in a lane worktree) runs new workflow.toml key `worktree_setup = [cmds]` (cwd = worktree,
  env `WF_MAIN` = main tree; first non-zero exit stops, exit 1). wf-worker runs it after worktree create/reuse;
  `wf next` Multi-session hint appends `&& wf setup` when set. Projects: optional — list commands that provide
  git-ignored inputs (e.g. link `out/…` from `$WF_MAIN`); must be idempotent.
- 2026-10-05 `wf init` also seeds CLAUDE.md (templates/CLAUDE.md: Layout · Loop additions · Gotchas · Areas with code map / test recipe / tools / worktree setup); kept if it exists. Projects: nothing.
- 2026-10-05 `wf usage --explore`: per subagent of a session, % billed input exploring / before the first edit, median calls before it, result tokens per tool (grep/Read/sed-cat/…), files read by >= 2 agents. Projects: nothing (replaces per-project session-cost scripts).
- 2026-10-05 re-learning rules: shared CLAUDE.md grep discipline + code-map/test-recipe notes, worker/design/orchestrate lines; `wf done` always prints a checklist line "re-learned anything…". Projects: keep a code map + test recipe per area in their notes.
- 2026-10-05 `wf usage --effort` accepts only task estimates (<1h|1h|5h|10h|100h), not reasoning effort.
  Projects: nothing; fix old cost-log lines with effort=medium by hand.
- 2026-10-05 `wf usage`: subagent output tokens were undercounted (transcripts keep only the stream-start
  placeholder); now estimated from content (fit ±5% per session), shown `~`, cost-log lines get `est=N`.
  Projects: nothing; older `out/wf-cost.log` lines undercount out/usd.
- 2026-10-05 `wf check` warns about tool worktrees (wf repo `.worktrees/*`) whose branch is merged into master (leftover after release; `WF_TOOL_ROOT` overrides the repo). Projects: nothing.
- 2026-10-05 `wf lanes --unregister` drops this session's lane record (orchestrator holds none); wf-orchestrate cold start runs it. Projects: nothing.
- 2026-10-05 `wf list --runner [--model M]` = ready + Done line, no Sessions: owner, Done not about owner/report to/confirm,
  no open slices. `wf add` of a task without Done prints a stderr hint. Projects: nothing. Orchestrator uses --runner.
- 2026-10-05 `wf list --stale` lists in-progress tasks with no live claim (dead holder or none); `wf status --clear-stale`
  clears them. Projects: nothing. Orchestrator cold start may use it.
- 2026-10-05 `wf next` / `wf done`: last line `context ~Nk tokens (> 100k): ask the owner to /clear, then continue`
  when this session's last prompt is over `ctx_hint` (workflow.toml, tokens, default 100000, 0 = off).
  Projects: nothing (optional key).
- 2026-10-05 `wf batch N [--lanes …] [--model] [--for] [--mem] [--dry-run]` starts the unattended batch
  orchestrator (claude -p under `wf res run`, bg-wait ceiling = --for, prompt in templates/batch-prompt.md);
  `wf batch --status`. Owner: allow rule `Bash(python3 /projects/workflow/wf.py batch:*)` once. Projects: nothing.
- 2026-10-05 docs: `/clear` safe only with no background worker (it SIGKILLs the worker's running Bash;
  notice still arrives). orchestrator.md Context + wf-orchestrate skill. Projects: nothing.
- 2026-10-05 `wf usage`: tokens + API-price $ per agent of a session (`--session`, `--agent`, `--since`),
  deduped per request (transcripts repeat usage per content block: earlier 153 turns / 8.9M cr = 86 / 5.0M);
  `--log TASK OUTCOME --effort E` appends to `out/wf-cost.log`; `--report` = lane/effort table over all
  projects. Orchestrator skill step 6 logs the cost line. Projects: nothing to do.

- 2026-10-04 shared CLAUDE.md compacted (orchestrator → `/wf-orchestrate`, reflowed); no rule changes.

- 2026-10-04 `wf add --parent` no longer chains After to a deferred slice; rules: never delete what you did
  not create, owner-done parts / approved "(brainstorm)" titles updated same turn, post-merge gates run from
  the main tree, batch orchestrator wf-adds follow-ups instead of asking.

- 2026-10-04 Pilot 4 fixes: wf-worker 4-line report with `followups` (loose ends → `wf add`), background
  gates run after `wf merge` on the merged sha, `Recovery:` prompt mode, wf spelled out; spawn prompt ends
  with "Final message: the 4 report lines only."; status-note parentheses error has a hint.

- 2026-10-04 Skills `/wf-orchestrate [go | batch N]` and `/wf-design [topic | id]` (`shared/skills/`, symlink
  into `~/.claude/skills/`): cold start of an orchestrator or design/rulings session after /clear.

- 2026-10-04 Orchestrator + workers (docs/orchestrator.md): project lock `.wf/lock` around every wf write
  (parallel sessions/workers safe); `wf merge` in a lane worktree = rebase, ff-merge, TASKS/archive commit,
  detach, push home, under the lock (`wf done` there now points to it); `wf-worker` subagent definition
  `shared/agents/wf-worker.md` (install: symlink into `~/.claude/agents/`). Shared rule: an orchestrator session
  holds no lane and spawns workers. Projects: `out/` git-ignored for the orchestrator log.

- 2026-10-04 Sessions field: task line `Sessions: parallel|solo|owner [— why]` (none = parallel; `- Sessions:`
  note form works too; `wf add/set --sessions`, `wf list` mark `[solo]`/`[owner]`, `wf check` validates).
  `wf next` skips solo while another session is live; a solo task in progress → other sessions pick nothing;
  its `wf done` notifies them. Owner tasks only with `wf next --owner`. Header flag `, interactive` = owner
  (`wf check` warns: `wf set <id> --sessions owner`); `--interactive` = old spelling, one more release.
  Projects: nothing required; replace `interactive` flags when `wf check` warns.

- 2026-10-04 Multi-session (docs/multi-session.md): `wf status … progress` claims the task for the session
  (`.wf/claims/`); `wf next` skips tasks held by another live session and warns when another live session holds
  your lane. More than one live session → `wf next` prints a `Multi-session` block: work in `.worktrees/<lane>`
  on a branch `<lane>/<task>`. `wf` run in a linked git worktree uses the main tree's project (TASKS.md, archive,
  docs, `.wf`). `wf done` there prints the merge-back steps; ff-merging one's own task branch is allowed.
  Shared rule: commit explicit paths, never `git add -A` / `commit -a`. Projects: `.worktrees/` git-ignored.
- 2026-10-04 Model lanes (docs/model-lanes.md): task line `Model: haiku|sonnet|opus` (none = opus;
  `wf add/set --model`, `wf list` column + `--model`, `wf check` validates). `wf next --as <model>` picks only
  that lane (no `--as` = haiku, with a hint), registers the session in `.wf/sessions/` (self-ignored) and shows
  other lanes' sessions and what waits on them; new `wf lanes`; `wf done` names the lanes to notify. Pick order
  for everyone: inherited priority (a task counts at the best P of all that wait on it), then work other lanes
  wait on, then more waiting. Shared rule: cold start `wf next --as <your model>`, own lane only. `wf res run`
  keeps the caller's environment (variables the user manager lacks; secret-named ones are not stored).
  Projects: flag tasks with `wf set <id> --model …` (plain `- Model: sonnet ok` notes → check warning).
- 2026-10-03 shared rule: agents may push to remote `home` (the owner's private server) after a Done commit or
  a group of commits; every other remote still only when asked. Projects: nothing (repos without `home` unchanged).
- 2026-10-02 `wf res`: each Claude session in agents.slice is capped at `session_mem_gb` (default 6 GB,
  MemoryHigh: throttled, not killed) by the timer tick; `status` warns when a session sits at its cap. A runaway
  foreground test can no longer take all RAM. Projects: big work via `wf res run` (as before).
- 2026-10-02 `wf res` automatic clean also sweeps `/tmp` and `/var/tmp` litter: own empty dirs idle 2 h, .NET debug
  pipes of dead processes (thousands accumulated). Files with content are untouched. Projects: tests should
  still delete their temp dirs.
- 2026-10-02 `wf res run --queue` says how to cancel (`cancel: wf res release r-N`); `release -h` too. Projects: nothing to do.
- 2026-10-02 `wf res` clean: never deletes the scratch dir of a running Claude session, however idle (was: after
  2 h, taking its scratchpad and background-task output). Projects: nothing to do.
- 2026-10-01 Shared rule: `/tmp` is RAM; temp dirs made by code/tests must be deleted after use. Machine tip:
  `TMPDIR=/var/tmp` (disk) in the Claude Code settings `env` moves agents' temp files off RAM. Projects: nothing to do.
- 2026-10-01 `wf res hook`: Claude Code PreToolUse hook; while game mode is on, agent Bash commands run without
  a display (no windows over the game). Shared rule line added. Machine: add the hook to
  `~/.claude/settings.json` (docs/resource-ledger.md §4.6). Projects: nothing to do.
- 2026-10-01 tests: the `wf res` lock race test fails instead of hanging when a child crashes. Projects: nothing to do.
- 2026-10-01 `wf res status`: `unreserved agent memory` says how much of it is reclaimable file cache.
  Projects: nothing to do.
- 2026-10-01 `wf res status` warns about jobs started with bare `systemd-run` (transient services outside
  agents.slice); shared rule: also not from project scripts. Projects: a script that calls `systemd-run`
  itself → start it through `wf res run`.
- 2026-10-01 `wf res`: `run`, `note`, `status` and `-h` say what `--for` means: a job is never killed when it
  runs over (`ETA overdue (still running, not killed)`); a note is freed. Projects: nothing to do.
- 2026-10-01 `wf res status`/`wait`: warn when a running job is stuck at its own memory limit (≥ 85 % of
  `--mem` and ≥ 20 % memory stall) — `r-N throttled at its memory limit …: likely too small`. Projects: nothing to do.
- 2026-10-01 `wf res`: a job killed with its wrapper (OOM, signal, timeout) now says why in `status`/`wait`,
  e.g. `done rc=? peak 3.9 GB … (killed: oom-kill by systemd-oomd, limit 4.0 GB; raise --mem)`, read from
  the journal; was `rc=? peak ?`. Projects: nothing to do.
- 2026-10-01 `wf projects` skips a wf checkout (its `templates/workflow.toml` is no project). Projects: nothing to do.
- 2026-10-01 Repo split: the tool repo holds only the tool (fresh history); the workflow's own tasks
  and history moved to a separate private wf project. Reference docs: `docs/design.md`,
  `docs/resource-ledger.md`. `wf report` / inbox unchanged. Projects: nothing to do.
- 2026-10-01 `wf res`: background Claude sessions (process named by version, e.g. `2.1.283`) are now
  recognised: `adopt`/timer move them into agents.slice, and their `note`s are owned by the session, not
  its shell. Projects: nothing to do.
- 2026-10-01 `wf res`: shared memory/CPU ledger for agent jobs — `run` (exit 3 = busy, with ETA; `--queue`),
  `status`, `wait`, `release`, `note`, `game on|off` (gaming reserve, auto-off 4h), `clean` (stale
  /tmp/claude-* scratch auto-deleted after 2h), `adopt` (running Claude sessions → agents.slice, no restart),
  `timer on|off`, `shell-init`. Rule in shared CLAUDE.md: big/long jobs go through `wf res run`.
  Projects: nothing to change; move ad-hoc systemd-run jobs to `wf res run`.
- 2026-10-01 `wf check` errors on bare ids in `After:` / `Slices:` (were silently ignored, so
  `next` could pick a task before its dependency). Project: write them as `[[id]]`.
- 2026-09-30 Inbox fixes: `wf rename OLD NEW` (id + all links); `add` takes a leading `<id>: `
  as the id; `--parent --id` slices chain `After:` via `Slices:` and count for `done`/`next`;
  `next` skips parents with open slices; `set --title "Title. Goal."` / question replaces the text.
  Projects: nothing to do.
- 2026-09-29 First release: `wf` (next list show ctx search log projects check add done prio
  move status set note body tick report init migrate), shared CLAUDE.md, TASKS format 1.
  Projects: `wf init` or `wf migrate --write`, pointer line in CLAUDE.md.