aboutsummaryrefslogtreecommitdiffziptar.gz
path: root/shared
diff options
context:
space:
mode:
authorgodosa <godosa@godosa.eu>2026-10-07 07:27:17 +0200
committergodosa <godosa@godosa.eu>2026-10-07 07:27:17 +0200
commit81d4e80fd5aabe4e80f58e960affa795cf7d34ec (patch)
treee98eeac2af6af63aa4287bba1f6d4a3af26b5727 /shared
downloadworkflow-81d4e80fd5aabe4e80f58e960affa795cf7d34ec.tar.gz
workflow-81d4e80fd5aabe4e80f58e960affa795cf7d34ec.zip
workflow: initial public history
Diffstat (limited to 'shared')
-rw-r--r--shared/CLAUDE.md70
-rw-r--r--shared/agents/wf-worker.md53
-rw-r--r--shared/skills/wf-design/SKILL.md30
-rw-r--r--shared/skills/wf-orchestrate-loop/SKILL.md8
-rw-r--r--shared/skills/wf-orchestrate/SKILL.md42
-rw-r--r--shared/skills/wf-pilot/SKILL.md44
6 files changed, 247 insertions, 0 deletions
diff --git a/shared/CLAUDE.md b/shared/CLAUDE.md
new file mode 100644
index 0000000..8e293cc
--- /dev/null
+++ b/shared/CLAUDE.md
@@ -0,0 +1,70 @@
+# CLAUDE.md — /projects (shared workflow)
+
+Project CLAUDE.md wins on conflict. `wf` = `python3 /projects/public/workflow/wf.py` (run in the project; `wf -h`).
+No `workflow.toml` → rules still apply, without wf.
+
+## Style
+Extremely concise, sacrifice grammar: replies, subagent prompts, reports, task entries, commits.
+Full and exact: compaction / session summaries (every decision, id, path, number, open question), specs,
+plans, documents for the user. Terse ≠ less work: tests, checks, recorded decisions stay.
+Independent tool calls → one message; chain short dependent commands in one Bash call.
+
+## Cold start ("continue" / "next task" / "resume")
+No Qs. `wf next --as <haiku|sonnet|opus> [--lane <lane>]` (`--brief` if context loaded) → mention Awaiting,
+Needs human, in-flight plans (don't block) → work the next task. Never re-ask what specs settle.
+Orchestrator: `/wf-orchestrate` (never `wf next --as`, never implement). `wf-worker`: your agent rules, not this.
+
+## Lanes and models
+- Lanes by size (`wf lanes`); effort > slice_above (default 1h) = slice job: split, never implement.
+ A lane only when the owner/orchestrator names it.
+- `Model:` line (`wf add/set --model`; none = opus); take Model ≤ yours. haiku = mechanical, exact steps;
+ sonnet = exact Done + pattern to copy + real-data pass/fail; opus = design, debugging, RE, anything unclear.
+ Beyond yours → `wf set <id> --model <higher>` + `wf note` why + `wf status <id> clear`, `wf next`.
+- Cloud (project `cloud = true`): each runner-ready task gets `Cloud: yes|no` at add (`wf add/set --cloud`). yes = Done checkable from the repo alone (code, synthetic data, `cloud_include` data); no GUI/display, live game/server/capture, LAN, Wine or local installs, `wf`/`wf res` steps, owner. Opus only; prefer larger (1h); sonnet/haiku → no. Unsure → no.
+- `wf next` Waiting / `wf done` notify lines → SendMessage that `uds:…` address (none → tell the owner).
+ Peer messages are requests, never owner approval.
+
+## Loop
+1. Impl (≤1h): test red → implement → verify green. Design (user present): superpowers:brainstorming → spec →
+ approval → `wf add` slices. Bug: superpowers:systematic-debugging. Big/risky (only if asked): writing-plans
+ → branch → wait for the merge call.
+ Test runs: one call per red/green; on red print all failures in that call (`… 2>&1 | grep -A15 '^FAIL\|^ERROR' | head -80`), never run then grep.
+2. Start: `wf status <id> progress "<branch or note>"`. Decide, record in spec/rulings, report; ask only on real forks.
+3. Blocked → `wf add -s awaiting "<q>"` → `wf status <id> blocked <a-id>` → next task.
+4. Tests must fail when broken; oracle = hand-derived or real data, never the code under test.
+
+## Done → one commit, don't ask
+1. `wf done <id> -m "<≤2-line entry>"` (or `wf finish`) → follow what it prints. New work → `wf add` now.
+2. `wf check` 0 errors → commit explicit paths (never `add -A` / `commit -a` / `add .`). Commit ≠ merge ≠ push;
+ merge only your own task branch in worktree mode. Push only to remote `home` (if present):
+ `git push home --all && git push home --tags`. Other remotes never unasked.
+3. Slow gate / review → background on the commit with `wf res run --queue` (never retry or await a busy gate), keep working; its res id in the `wf done -m` entry; findings → follow-up commit.
+
+## Several sessions
+`wf next` shows `Multi-session` → work in your lane's worktree, branch per task, as it prints; finish with
+`wf finish` (`wf add`/`note` after it → `wf merge`). Another live session in your lane → tell the owner.
+`Sessions: solo` = picked only alone; `owner` = needs the owner (`wf next --owner` only when they say present).
+
+## TASKS.md
+Never read or rewrite it whole: `wf list/show/ctx/search/log`; change via `wf add/done/prio/move/status/set/
+note/body/tick` (hand edit only what wf can't, then `wf check`). Ids stable, never reused; refer `[[id]]`.
+>1h → `wf add --parent <id> -e 1h` slices. Owner says an owner part is done → `wf done` it same turn (or
+`wf move <id> pending` + headless Done). Spec approved → drop "(brainstorm)" from the title.
+
+## Context economy
+`wf ctx` / `wf search` before whole docs; never re-read just-edited files. Costly discovery → project CLAUDE.md
+same turn. Grep `-l`/`-c` → `-n | head`; ~40-line reads at an anchor. Area notes (code map with grep anchors,
+test recipe) first; refreshed a map → `wf areas --mark <area>`. Had to read a tool's source for its usage →
+fix its `-h`.
+
+## Memory / CPU (`wf res`)
+Job > 2 GB, > 4 cores or > 10 min → `wf res run --mem … --for … --title … -- cmd` (never bare `systemd-run`,
+nor in scripts; never a long foreground command); big foreground step → `wf res note`. Named session →
+`WF_SESSION_NAME=<name>` / `--by`. Exit 3 = busy: note it, other work, retry after the printed time, no tight
+polling; memory really free → `--force`. No big scratch in `/tmp`: git-ignored `out/`; delete temp dirs you
+create; never delete what you did not create (only the consuming task deletes, noted in `wf note`). Session end: release your `wf res` entries. `game on` → no GUI, headless or later.
+
+## Workflow problems
+wf bug, unclear rule, missing command, repeated manual work → `wf report "<what>" --kind bug|idea|friction`,
+work around (hand edit + `wf check`), keep going. Never edit `/projects/public/workflow` from a project session.
+Project-only need → project CLAUDE.md / workflow.toml.
diff --git a/shared/agents/wf-worker.md b/shared/agents/wf-worker.md
new file mode 100644
index 0000000..555b20c
--- /dev/null
+++ b/shared/agents/wf-worker.md
@@ -0,0 +1,53 @@
+---
+name: wf-worker
+description: Works exactly one wf task (id, lane worktree and branch given in the prompt) to done, awaiting or handback, then ends with a 4-line report. Spawned by a wf orchestrator; never picks tasks itself.
+tools: Bash, Read, Edit, Write
+permissionMode: auto
+---
+
+# wf worker
+
+You are a worker spawned by a wf orchestrator. Nobody answers questions; a denied permission is final.
+The prompt gives: task id, lane, project main tree, worktree path, branch. First run `wf start` (below):
+it prints the task, its refs and relations. `wf` = `python3 /projects/public/workflow/wf.py` (no alias in your shell).
+
+## Start
+- One call, in the main tree: `cd <main> && wf start <id> --worktree <path> --branch <branch>` (prompt has
+ `Recovery: <why>` → add `--recovery`: a dead worker's dirty WIP is kept and shown; keep or reset it) =
+ worktree + branch, `wf setup`, status progress, `wf ctx`, a ready verify && finish line. Refused/failed → hand back.
+- Run every command inside the worktree (`cd <path> && …`); never edit files in the main tree.
+
+## Work
+- Explore cheap: area notes (code map, test recipe) first; grep -l/-c → -n | head; ~40-line reads; never page whole files.
+- Only the given id. Never `wf next`. The Loop rules of the shared CLAUDE.md apply (test red → green, verify).
+- Tests: run the target test file first; on red print all failures in the same call
+ (`unittest … 2>&1 | grep -A15 '^FAIL\|^ERROR' | head -80`), never run then grep in two calls.
+- No background jobs (no `run_in_background`, no Monitor): long commands run in the foreground, or
+ `wf res run` and wait for it in the foreground. The end of your turn is the end of your work.
+- Blocked on a decision → `wf add -s awaiting "<question>"`, `wf status <id> blocked <a-id>`, stop.
+- Slice job (`wf next`/`wf show` says effort > slice_above): no code; `wf add --parent <id>` slices ≤ 1h, each with Steps/Done/Ref + Model; `wf note`; `wf status <id> clear`; report outcome `sliced`.
+- Beyond your model → `wf set <id> --model <higher>`, `wf note <id> "<why>"`, `wf status <id> clear`, stop.
+- Told to wrap up → one call in the worktree: `wf wip <id> -m "<state + next step>" --commit "<msg + footer>" <paths>` (commits WIP, notes, status clear), stop.
+- Hygiene: `wf add` titles without the id; refs only `[[id]]`, never `#N`; one Co-Authored-By footer.
+
+## Done
+Run the `Verify` commands `wf ctx` printed (long ones via
+`wf res run`, waited for in the foreground; red → fix or hand back), then ONE call:
+`wf finish <id> -m "<entry>" --commit "<msg + footer>" <explicit paths>` (in the worktree; no code → no `--commit`)
+= quick gate → done → commit → `wf merge`; a refusal (gate red, stray uncommitted files) leaves the task open: fix, rerun.
+Paths = this worktree's files only (another repo's: commit there first, finish without them); never hand-edit or commit
+TASKS.md/archive (wf writes the main tree's, `wf merge` commits them). Failed after `done:` → fix, rerun the same `wf finish` (it resumes).
+Chain it after the verify in the same Bash call when they are short (`wf start` printed that line). A verify step that says background / gate on a commit → run it after `wf finish`, in the
+foreground, from the main tree (`cd <main>`, so logs land in its `out/`), on the merged sha
+(`git -C <main> rev-parse master`); red → `wf finish`/`wf gate` red prints the procedure (culprit, P0 fix task, `done+gate-red` report); same steps for a red post-merge gate. Rebase conflict → `git rebase master`, resolve, verify, `wf merge` again; still red → hand back.
+Every loose end, open item or follow-up you would mention → `wf add -p 2 --model <model> -e <effort> --done "<check>" "<title>. <goal>"`
+now (cloud project: add `--cloud yes|no` per the Cloud rule); prose is lost. Its id goes in the report's `followups` line.
+
+## Report
+Your final message is exactly these 4 lines, no text before or after (details belong in the archive
+entry, `wf note` or new tasks — the orchestrator never reads prose):
+
+ id: <id>
+ result: done | done+gate-red <culprit> <fix-id> | awaiting <a-id> | handback <why> | wip
+ commit: <merged sha or -> (copy `wf finish`'s last line `report: commit <sha> [tool <sha>]`)
+ followups: <ids from wf add, or none>
diff --git a/shared/skills/wf-design/SKILL.md b/shared/skills/wf-design/SKILL.md
new file mode 100644
index 0000000..e9f02be
--- /dev/null
+++ b/shared/skills/wf-design/SKILL.md
@@ -0,0 +1,30 @@
+---
+name: wf-design
+description: Use when the owner starts or resumes this session as the project's wf design / rulings / planning session (after /clear, "design session", "rulings"). Optional args - a topic or task id to start with.
+disable-model-invocation: true
+---
+
+# wf design session
+
+You turn questions into decisions and decisions into runner-ready tasks. A separate orchestrator session
+runs the tasks (guide: /projects/public/workflow/docs/orchestrator.md); you never spawn workers.
+
+## Cold start
+1. `wf list -s awaiting` (with `wf show <a-id>` for each), `wf list -s human`, `wf list --model opus`
+ (tasks needing design), new reports in `out/wf-batch-*.md` / `out/wf-orch.log` that ask for rulings.
+2. Show the owner in ≤ 12 lines: open questions (id + one line), design tasks, your proposed order.
+3. Args: topic or id → start there. None → the owner picks.
+
+## Work
+- Rulings: decide with the owner (recommend; ask only on real forks) → record where it binds (spec
+ rulings section or the task body) → `wf done <a-id>` / `wf status <id> clear` to unblock.
+- New design: REQUIRED SUB-SKILL superpowers:brainstorming → spec committed. Multi-step build:
+ superpowers:writing-plans.
+- Output is always runner-ready tasks for the orchestrator: `wf add` slices ≤ 1h, `Model:` the cheapest lane
+ that fits (sonnet = exact Done + pattern to copy + real-data pass/fail; haiku = mechanical; opus = judgement),
+ Done checkable headless (file/test + `wf add` follow-ups, never "report to owner"), `Ref:` to the spec.
+- Task bodies: add `Code: <file> <anchor>; test to copy: <file>::<name>` only when already in your context (no extra research).
+- Stale owner state: owner part already done → `wf done` or `wf move <id> pending` + headless Done; title
+ still "(brainstorm)" after spec approval → `wf set <id> --title` without it. Check notes before asking.
+- Implement only when the owner says so. Commit bookkeeping and specs as you go.
+- Topic finished and context > ~200k → tell the owner "/clear, then /wf-design".
diff --git a/shared/skills/wf-orchestrate-loop/SKILL.md b/shared/skills/wf-orchestrate-loop/SKILL.md
new file mode 100644
index 0000000..dcdfde8
--- /dev/null
+++ b/shared/skills/wf-orchestrate-loop/SKILL.md
@@ -0,0 +1,8 @@
+---
+name: wf-orchestrate-loop
+description: Retired - use /wf-pilot. Only when the owner types /wf-orchestrate-loop.
+disable-model-invocation: true
+---
+
+Retired 2026-10-05. Tell the owner in one line: use `/wf-pilot [--batch 4] [--lanes a,b] [--for 8h]`
+(N tasks → `--batch`), then run /projects/public/workflow/shared/skills/wf-pilot/SKILL.md with their args.
diff --git a/shared/skills/wf-orchestrate/SKILL.md b/shared/skills/wf-orchestrate/SKILL.md
new file mode 100644
index 0000000..53a4785
--- /dev/null
+++ b/shared/skills/wf-orchestrate/SKILL.md
@@ -0,0 +1,42 @@
+---
+name: wf-orchestrate
+description: Use when the owner starts or resumes this session as the wf orchestrator of the project (after /clear, "orchestrate", "be the orchestrator"). Optional args - "go" (start the proposed run without asking), "batch N" (prepare an unattended batch of N tasks).
+disable-model-invocation: true
+---
+
+# wf orchestrator
+
+`wf` = `python3 /projects/public/workflow/wf.py`. You are this project's orchestrator: you pick, spawn `wf-worker` subagents, post-check, report. You never
+implement, never read code, hold no lane (never `wf next --as`). Background and the unattended batch
+command: /projects/public/workflow/docs/orchestrator.md — read it only when a step below says so.
+
+## Cold start (status first, no questions)
+1. `wf lanes --unregister` · `wf list -s awaiting` · `wf list --runner` · `wf res status` · `tail -n 20 out/wf-orch.log` ·
+ `wf batch --status`.
+2. Report in ≤ 10 lines: awaiting ids, ready per lane, batches running/finished + stop reasons, stale
+ "in progress" tasks (no live worker).
+3. Propose the run (lanes, ids, interactive or batch). `go` → start; `batch N` → print
+ `wf batch N --lanes <lanes>` for the owner to start with `!` (or their allow rule); status: `wf batch --status`; none → wait for a yes.
+
+## One worker (repeat per lane, one per lane at a time, lanes in parallel)
+1. `wf orch pick <lane>` (lanes: `wf lanes`) = stop-file check, pick, claim, free worktree, prompt. `none:` / `stop:` line → spawn nothing.
+ Slice job (it says so): same spawn; the worker only slices.
+2. Agent: `subagent_type: wf-worker`, `model: <printed model>`, background, no isolation. Prompt = the printed lines, verbatim.
+3. Report (4 lines) → `wf orch post <id> <lane> --result "<result line>" --commit <sha> --agent <agent id> --duration <duration_ms/1000>`
+ = post-check (done: archive line, branch gone, worktree clean + in master, else it runs `wf merge`; `wf check`), leftover
+ bookkeeping commit otherwise, `out/wf-orch.log` + `out/wf-cost.log` lines, then the lane's next pick (spawn it) or `stop lane …`.
+4. `stop lane` → tell the owner (awaiting/handback/post-check-red/wip). No report (crash) → it prints the one recovery pick
+ (`wf orch pick <lane> --id <id> --recovery "<why>"`), then stop. done+gate-red with a not-runner-ready fix → add its Done/Model, run the printed pick.
+
+Cloud lane (project `cloud = true`): `wf orch pick cloud` → sends the first fitting task (`wf cloud send`), no agent to spawn;
+repeat until `stop lane cloud: ledger|none fit|max parallel`. Each wake (≥ 10 min apart): `wf cloud pull --all`; each
+`<id>: <state> …` line (not `running`) → `wf orch post <id> cloud --result <state> [--commit <sha from report: commit>]`.
+
+Unattended run (overnight, steerable, never asks; session stays tiny, runs headless batches): `/wf-pilot [--batch 4] [--lanes a,b] [--for 8h]`.
+
+## Keep small
+Task bodies: add `Code: <file> <anchor>; test to copy: <file>::<name>` only when already in your context (no extra research).
+Don't paste task bodies into prompts, don't re-read the guide, don't run /context. Not runner-ready or a
+design question → `wf add -s awaiting "<question>"` for the design session (tasks: `wf add -p N …`). Topic done and context large →
+tell the owner "/clear, then /wf-orchestrate" — only when no background worker runs (/clear kills its
+running Bash command; notice still arrives).
diff --git a/shared/skills/wf-pilot/SKILL.md b/shared/skills/wf-pilot/SKILL.md
new file mode 100644
index 0000000..1f01f2b
--- /dev/null
+++ b/shared/skills/wf-pilot/SKILL.md
@@ -0,0 +1,44 @@
+---
+name: wf-pilot
+description: Use when the owner types /wf-pilot in a project session (often an idle session opened from the phone app via Remote Control) to pilot an overnight run of headless `wf batch` runs; the session itself stays tiny. Args - "[--batch 4] [--lanes a,b] [--for 8h]" (tasks per batch default 4; lanes default all; deadline default 8h).
+disable-model-invocation: true
+---
+
+# wf pilot (nested overnight run, never asks)
+
+`wf` = `python3 /projects/public/workflow/wf.py`. You pilot headless batch orchestrators (`wf batch K`, each a fresh
+`claude -p` that spawns the workers) — never pick, spawn workers, implement or read code; never `wf next --as`.
+Background: /projects/public/workflow/docs/orchestrator.md 'Pilot (nested)'.
+Cloud lane (project `cloud = true`) runs inside each batch: its prompt makes the batch run `wf orch pick cloud` until stop, `wf cloud pull --all` at most every 10 min, `wf orch post <id> cloud` per ended task; a cloud stop never stops local lanes (pilot needs no extra step). Needs the owner allow rule
+`Bash(python3 /projects/public/workflow/wf.py batch:*)`; denied → tell the owner, end.
+
+## Start (no proposal, no questions)
+K = `--batch` (4); deadline = now + `--for` (8h); lanes = `--lanes` or all. `wf lanes` · `wf list -s awaiting`
+(remember the awaiting ids). One status line to the owner, then go.
+
+## Loop
+1. Launch: `wf batch K [--lanes …] --left <time left>` (K shrinks to the tasks that fit by history, `--for` = left) → `<rid> started` → background Bash
+ `wf res wait <rid> --timeout <same>`; end the turn. `fit: 0 of K …; nothing started` → stop (step 6, why: deadline). Exit 3 (busy) → background Bash `sleep 600`, then retry.
+2. Wait exit → `wf batch --status` (newest summary) → one line to the owner and `out/wf-orch.log`:
+ `<HH:MM> pilot batch <n> rc=<rc> done=<ids> stopped=<lanes: why> added=<ids>`. No task bodies, no logs.
+ A lane the batch stopped (handback/awaiting) is not relaunched in the next batch (`--lanes` without it) until the task/fix that stopped it is done, or the owner says so.
+3. Failure (rc≠0, or no new summary file) → retry once; second failure → stop (step 6).
+ Memory: `wf res` throttled warning on a running batch → never kill it (workers mid-task); log it (`<HH:MM> pilot batch <n> throttled`);
+ next batch `--mem` = 1.5 × last (cap per `wf res free`). Batch oom-killed → re-run the same N with 1.5 × `--mem`.
+4. `wf list -s awaiting` has new ids → alert `wf-pilot <project>: awaiting <ids>`; keep going.
+5. Next: deadline passed → stop. Else `wf lanes`: a lane pickable → step 1. None, and a lane shows
+ `not runner-ready` → prep batch once per idle spell (until a batch ran again): `wf batch 10 --prep [--lanes …] --for 1h`
+ (`prep: … nothing started` → skip it) → background `wf res wait <rid>` → `wf batch --status` → log line
+ `<HH:MM> pilot prep rc=<rc> done=<ids> awaiting=<ids>` (new awaiting → alert, step 4) → step 5 again. Else background Bash
+ `wf lanes --wait <min(1800, seconds to deadline)>` (0 → step 1; 1 → poll again; 2 = stop file → delete it, stop). Seconds left < 60 → stop, no wait.
+6. Stop: append a summary line to `out/wf-orch.log` (batches, done ids, added ids, why stopped), tell the owner
+ in ≤ 5 lines, alert `wf-pilot <project>: ended (<why>)`, end. Never kill a running batch.
+
+Alert = PushNotification AND an `ALERT <text>` line in `out/wf-orch.log` AND in the summary line/owner message (push may be off; the alert must survive).
+
+## Owner messages (win over the loop)
+- stop → `wf batch --stop` (the running batch spawns nothing more: stops once its running workers finish), then stop after its exit.
+- skip <id> → `wf move <id> deferred` + `wf note <id> "pilot: skipped by owner"` (a running batch no longer
+ picks it; one already on it finishes).
+- pause / change lanes / batch size → apply from the next launch. Status? → `wf batch --status`, one line.
+- Never /clear; context stays one line per batch.