diff options
Diffstat (limited to 'templates')
| -rw-r--r-- | templates/CLAUDE.md | 21 | ||||
| -rw-r--r-- | templates/TASKS.md | 12 | ||||
| -rw-r--r-- | templates/archive.md | 1 | ||||
| -rw-r--r-- | templates/batch-prompt.md | 1 | ||||
| -rw-r--r-- | templates/cloud-prompt.md | 38 | ||||
| -rw-r--r-- | templates/prep-prompt.md | 1 | ||||
| -rw-r--r-- | templates/workflow.toml | 36 |
7 files changed, 110 insertions, 0 deletions
diff --git a/templates/CLAUDE.md b/templates/CLAUDE.md new file mode 100644 index 0000000..88f70b4 --- /dev/null +++ b/templates/CLAUDE.md @@ -0,0 +1,21 @@ +# CLAUDE.md — {name} + +Project rules; win over the shared /projects/CLAUDE.md on conflict. Terse. Update when you re-learn something. + +## Layout +- <dirs / entry points, one line each> + +## Loop additions +- Verify: <command> + +## Gotchas +- <env / layout / tool surprise, found at cost> + +## Areas +### <area> +- Code map: <grep anchors: function / class / string names, no line numbers> +- Test recipe: <command for this area, fixture / data notes> +- Tools: <scripts / CLIs, one line each: what, how to run> +- Worktree setup: <steps a fresh worktree needs: venv, submodules, data links> +- Paths: <globs the area's code lives in; none = whole repo> +- Checked: <short sha: wf areas --mark <area> after a refresh> diff --git a/templates/TASKS.md b/templates/TASKS.md new file mode 100644 index 0000000..2148242 --- /dev/null +++ b/templates/TASKS.md @@ -0,0 +1,12 @@ +# Tasks — {name} + +Format and rules: /projects/CLAUDE.md. Done history: [`tasks/archive.md`](tasks/archive.md). +Look and change with `wf` (`wf -h`), not by hand. + +## Awaiting your decision + +## Pending + +## Needs human + +## Deferred diff --git a/templates/archive.md b/templates/archive.md new file mode 100644 index 0000000..14e4146 --- /dev/null +++ b/templates/archive.md @@ -0,0 +1 @@ +# Task archive (newest first) diff --git a/templates/batch-prompt.md b/templates/batch-prompt.md new file mode 100644 index 0000000..1a0f338 --- /dev/null +++ b/templates/batch-prompt.md @@ -0,0 +1 @@ +You are a batch orchestrator. Follow {here}/docs/orchestrator.md 'One worker' for up to {n} tasks (lanes: {lanes}), never implement. Before EVERY spawn (each round, a lane's P0 fix, a recovery worker) run `test -e {stop}`: it exists → spawn nothing, let running workers finish (never kill one), post-check them, append 'stopped: stop file' to {out}, delete the stop file, exit. Else, before each round run `wf batch --time-left {deadline}`: its line ends in ': stop' (less time left than a task takes, p90) → spawn nothing new, let running workers finish, post-check them, append 'stopped: deadline (<that line>)' to {out}, exit. Else each round: `wf orch pick <lane>` per lane, spawn one wf-worker per picked lane in ONE message (model and prompt: as printed), foreground (not background), wait for all, post-check each with `wf orch post <id> <lane> --result "<result line>" --commit <sha> --agent <agent id> --duration <s> --no-pick`, append one line per task to {out} (it exists with its '# wf-batch' header: only append, never rewrite) (time, lane, id, outcome, commit), repeat. If the project has `cloud = true`, the virtual lane cloud also runs each round (nothing to spawn): `wf orch pick cloud` until a `stop lane cloud` / `none fit` / `max parallel` line; never run `wf cloud pull` or `wf orch post <id> cloud` yourself: the batch job's sidecar pulls every 10 min (`wf cloud pull --all` → `wf orch post <id> cloud … --no-pick`, a 'cloud <id> <state> … (sidecar pull)' line in {out}), also while you wait on workers; a cloud stop never stops the local lanes. Stop a lane on its first stop outcome, and keep it stopped (never resume because some other task is pickable) until the task/fix that stopped it is done or the owner says so; done+gate-red <culprit> <fix-id> is not one (post-check as done, the lane picks the P0 fix next). Never ask the owner: follow-ups → wf add -p 2 --model <model>, decisions → wf add -s awaiting. At batch start note `git branch --list 'fast/*' 'slow/*'` (and worktrees): a branch already there is pre-existing; report it ONCE in {out} as 'pre-existing branch <name>' (+ the awaiting id when a task/awaiting names it), never per round or per task. End with the ids added in that file, then exit. diff --git a/templates/cloud-prompt.md b/templates/cloud-prompt.md new file mode 100644 index 0000000..6020e90 --- /dev/null +++ b/templates/cloud-prompt.md @@ -0,0 +1,38 @@ +You are a remote worker for one task in a snapshot repo (branch main, base commit {{base}}). +Rules (they override CLAUDE.md where they differ): +- The task tool `wf` is absent: ignore wf / TASKS / lane / worktree / gate rules in CLAUDE.md; never create or edit TASKS.md or the archive. +- Never ask questions. Blocked on a decision you cannot make: end with result awaiting and the one-line question as the report. +- Work: test red -> implement -> green (test recipe below); commit on main, one-line messages; never rewrite {{base}}. +- A needed network source is blocked: say so in the report, continue with what the repo has. +- When done, measure your usage with the usage script at the end of this prompt (it sums your own transcript). +- Commit only what the task needs: `git add <paths>`, never -A or `.`; no build output (__pycache__, bin, obj). +- Then build the patch block: git format-patch --binary {{base}}..HEAD --stdout | gzip -9 > /tmp/wf.patch.gz; echo "WF-PATCH-BEGIN sha256=$(sha256sum < /tmp/wf.patch.gz | cut -c1-64) bytes=$(wc -c < /tmp/wf.patch.gz)"; base64 -w 76 /tmp/wf.patch.gz; echo WF-PATCH-END +- Your final message is plain text (not a tool call, no code fences, no other text), first line = the result line. + Every line keeps its key word (WF-RESULT, WF-REPORT, WF-USAGE, then the patch block) literally; replace only <...>: + WF-RESULT <done, awaiting or handback> + WF-REPORT <one or two lines: what changed, tests run + result, open questions> + <the WF-USAGE line the usage script printed> + <the patch block: its WF-PATCH-BEGIN line, the base64 lines, WF-PATCH-END> + No commits (awaiting / handback without work): still write the patch block, for the empty patch. + +Task {{id}}: +{{task}} + +Test recipe (area notes): +{{recipe}} +{{note}} +Usage script (run as is): +python3 - <<'PY' +import json, glob, os +f = max(glob.glob(os.path.expanduser("~/.claude/projects/*/*.jsonl")), key=os.path.getmtime) +m = {} +for line in open(f): + try: + j = json.loads(line); x = j.get("message") or {} + if x.get("usage"): m[x.get("id") or j.get("uuid")] = x + except Exception: pass +t = [sum(x["usage"].get(k) or 0 for x in m.values()) for k in + ("input_tokens", "cache_creation_input_tokens", "cache_read_input_tokens", "output_tokens")] +model = next((x["model"] for x in m.values() if x.get("model")), "?") +print("WF-USAGE in=%d cw=%d cr=%d out=%d model=%s" % (*t, model)) +PY diff --git a/templates/prep-prompt.md b/templates/prep-prompt.md new file mode 100644 index 0000000..a503e7a --- /dev/null +++ b/templates/prep-prompt.md @@ -0,0 +1 @@ +You are a prep batch orchestrator: make not-runner-ready tasks runner-ready; never implement, never edit files yourself. wf = python3 {here}/wf.py, project {root}. Tasks: {ids}. First, if out/wf-batch.stop exists → append 'stopped: stop file' to {out}, delete the stop file, exit. Else spawn sonnet workers (Agent tool, general-purpose, model sonnet, foreground, not background), up to 3 tasks each, all in ONE message, and wait for all. Worker prompt (fill in its ids): "Prep wf tasks <ids> in project {root} (cd there; wf = python3 {here}/wf.py). Read only task text: wf show <id> (wf ctx <id> for its refs, ~40-line reads). Never implement, never edit files, never commit. Per task: goal clear → wf set <id> --done "<one checkable line: command or observable result that proves it>". Done = observable check of the task text; never invert recorded original behaviour unless the task is a bug fix. Done names concrete files/runs, not 'each listed X'. Effort > slice_above (default 1h) → no Done on it: wf add --parent <id> slices (each with Done + Model), parent Done = all slices done. Also --model haiku|sonnet|opus if it has no Model line (haiku = mechanical, exact steps; sonnet = exact Done + existing pattern to copy; opus = design forks, debugging, anything unclear; any model above sonnet must be justified in the reply). Unclear (real fork, info only the owner has) → wf add -s awaiting "<id>: <question>", then wf status <id> blocked <a-id>. Reply one line per task: <id> → Done: <text> [Model: <m>] (model above sonnet: [opus: <why>]) | <id> → awaiting <a-id>." Then check each task with wf show <id> and append one line per task to {out} (it exists with its '# wf-batch' header: only append, never rewrite): <id> → Done: <text> | <id> → awaiting <a-id> | <id> → unchanged <why>. Finally commit only the task file: git -C {root} commit -m "prep batch: <ids changed>" -- {tasks}. Never ask the owner: questions → wf add -s awaiting. Then exit. diff --git a/templates/workflow.toml b/templates/workflow.toml new file mode 100644 index 0000000..b8b05cd --- /dev/null +++ b/templates/workflow.toml @@ -0,0 +1,36 @@ +# wf project config. Design: docs/design.md. Unknown keys are errors. +format = 1 +tasks = "TASKS.md" +archive = "tasks/archive.md" +docs = [] # files/folders whose [[id]] links `wf check` validates, e.g. ["DESIGN.md", "docs/"] +verify = [] # commands `wf done` reminds of (never runs), e.g. ["make test"] +done = [] # extra checklist lines `wf done` prints +# ledgers = ".superpowers/sdd" # in-flight plan ledgers shown by `wf next` +# ctx_hint = 100000 # tokens: `wf next`/`done` suggest /clear above it (0 = off) +# worktree_setup = ["mkdir -p out && ln -sfn \"$WF_MAIN/out/data\" out/data"] +# # `wf setup` in a lane worktree: cwd = worktree, env WF_MAIN = main tree; +# # git-ignored inputs; idempotent (workers run it every start) +# quick_gate = ["make quick-test"] # `wf gate`: fast regression check workers run before `wf done` +# # (cwd = this tree's project folder, env WF_MAIN; red = exit 1) + +# [anchors] # optional: every task Ref anchor into `index` must be a heading there +# index = "DESIGN.md" +# index_section = "Subsystems" +# specs = "docs/superpowers/specs" + +# slice_above = "1h" # effort above this → slice job on the slices lane (never implemented whole) +# [lanes.fast] # default lanes = fast + slow below; defining any [lanes.*] replaces both +# efforts = ["<1h"] # efforts this lane implements (disjoint, cover every effort ≤ slice_above) +# order = "unblock" # unblock = tasks others wait on first · priority = inherited priority first +# slices = true # takes slice jobs (one lane; default: the lane with "<1h") +# [lanes.slow] +# efforts = ["1h"] +# order = "priority" +# fallback = "fast" # nothing pickable here → pick from that lane +# areas = "CLAUDE.md" # area notes (## Areas / ### <area>): wf areas checks their code maps +# code_root = "../tool" # repo the areas' anchors / Paths / Checked refer to (default: this project); no uncovered nudge then +# area_stale_commits = 20 # commits touching an area's Paths since Checked → stale +# area_ignore = ["tests", "test", "docs", "doc"] # folders never nudged as uncovered (default shown) +# cloud = true # cloud lane opt-in (wf cloud send) +# cloud_include = ["out/pack"] # git-ignored inputs force-added to the cloud snapshot +# cloud_note = "Game data: out/pack" # appended to the cloud prompt |
