create-agent-rig 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/CHANGELOG.md +170 -0
  2. package/README.md +66 -10
  3. package/package.json +9 -2
  4. package/packages/cli/dist/commands/init.js +73 -18
  5. package/packages/cli/dist/index.js +11 -1
  6. package/packages/cli/dist/lib/init-settings.js +52 -0
  7. package/packages/cli/dist/lib/summary.js +19 -5
  8. package/packages/cli/dist/templates.js +8 -0
  9. package/templates/agent-os/init/CLAUDE.md +133 -0
  10. package/templates/agent-os/stack/aws-cdk/.claude/rules/aws-cdk.md +46 -0
  11. package/templates/agent-os/stack/aws-cdk/.claude/skills/ro-debug/SKILL.md +117 -0
  12. package/templates/agent-os/universal/.claude/agents/code-reviewer.md +1 -1
  13. package/templates/agent-os/universal/.claude/hooks/block-no-verify.mjs +12 -2
  14. package/templates/agent-os/universal/.claude/hooks/guard-bash.mjs +808 -0
  15. package/templates/agent-os/universal/.claude/queue.json +3 -0
  16. package/templates/agent-os/universal/.claude/rules/autonomy.md +43 -0
  17. package/templates/agent-os/universal/.claude/rules/invariants.md +170 -0
  18. package/templates/agent-os/universal/.claude/scripts/detect-missed-gate.mjs +489 -0
  19. package/templates/agent-os/universal/.claude/scripts/preflight.mjs +161 -0
  20. package/templates/agent-os/universal/.claude/scripts/queue/core.mjs +305 -0
  21. package/templates/agent-os/universal/.claude/scripts/queue/github-issues.mjs +231 -0
  22. package/templates/agent-os/universal/.claude/scripts/queue/index.mjs +175 -0
  23. package/templates/agent-os/universal/.claude/scripts/queue/jira.mjs +345 -0
  24. package/templates/agent-os/universal/.claude/scripts/queue/plan-md.mjs +239 -0
  25. package/templates/agent-os/universal/.claude/scripts/reconcile-external-prs.mjs +280 -0
  26. package/templates/agent-os/universal/.claude/scripts/stop-flag.mjs +62 -0
  27. package/templates/agent-os/universal/.claude/settings.json +4 -0
  28. package/templates/agent-os/universal/.claude/skills/loop/SKILL.md +297 -40
  29. package/templates/agent-os/universal/.claude/skills/new-invariant/SKILL.md +102 -0
  30. package/templates/agent-os/universal/.claude/skills/new-invariant/guard-invariant.example.mjs +78 -0
  31. package/templates/agent-os/universal/.claude/skills/new-invariant/guard-invariant.example.test.mjs +89 -0
  32. package/templates/agent-os/universal/.claude/skills/worktree-task/SKILL.md +73 -0
  33. package/templates/agent-os/universal/CLAUDE.md +57 -7
  34. package/templates/agent-os/universal/PLAN.md +28 -2
  35. package/templates/agent-os/universal/layers.json +20 -1
  36. package/templates/skeleton/aws-serverless/.github/workflows/ci.yml +6 -1
  37. package/templates/skeleton/aws-serverless/gitignore +8 -0
  38. package/templates/skeleton/node-service/.github/workflows/ci.yml +6 -1
  39. package/templates/skeleton/node-service/gitignore +8 -0
@@ -0,0 +1,73 @@
1
+ ---
2
+ name: worktree-task
3
+ description: Start and finish a task in its own git worktree — creation off the remote default branch, and the full cleanup after the merge. Use at the start of every implementation task and after every merge, and whenever two sessions might touch this repo at once.
4
+ allowed-tools: Bash, Read
5
+ ---
6
+
7
+ # Worktree task lifecycle
8
+
9
+ `.claude/rules/workflow.md` says **one task, one branch**. A worktree is how
10
+ that rule survives a second session: two branches checked out at once, in two
11
+ directories, with one `.git`. Without it, an unattended run and a hand-driven
12
+ session share a working tree and overwrite each other's edits.
13
+
14
+ **Use one when** anything else may touch this repo while you work — an
15
+ unattended `loop` run, a colleague, a second Claude session. A single attended
16
+ session on a quiet repo can just use a branch; the discipline that is never
17
+ optional is the branch, not the worktree.
18
+
19
+ ## Start
20
+
21
+ ```bash
22
+ cd "$(git rev-parse --show-toplevel)" # ALWAYS anchor cwd first — see gotcha 1
23
+ git fetch origin
24
+ git worktree add -b <type>/<slug> .claude/worktrees/<slug> origin/HEAD
25
+ git worktree list # verify the path is DIRECTLY under .claude/worktrees/
26
+ ```
27
+
28
+ - **Branch off the remote default branch**, never a local copy — a stale local
29
+ default is how a task gets built on code that was replaced last week
30
+ (`.claude/rules/autonomy.md`, "Session staleness"). If `origin/HEAD` is not
31
+ set locally, name the branch explicitly: `origin/<default-branch>`.
32
+ - **Branch name: `<type>/<slug>`**, type one of `feat|fix|docs|chore|refactor`.
33
+ If the project's queue gives work an id, the branch carries it —
34
+ `feat/<id>-<slug>` — because the branch name is often the only thread between
35
+ a queue item and its code. Work with no queue item keeps the plain form: **do
36
+ not invent an id.**
37
+ - If tests will run there, install inside the worktree first. A worktree gets a
38
+ fresh, empty `node_modules`; a missing install fails as a confusing
39
+ module-resolution error rather than as "you forgot to install".
40
+
41
+ ## Finish (after the PR is merged)
42
+
43
+ ```bash
44
+ cd "$(git -C <repo root> rev-parse --show-toplevel)" # cd OUT of the worktree first — gotcha 2
45
+ git worktree remove .claude/worktrees/<slug> --force
46
+ git worktree prune
47
+ git branch -D <type>/<slug>
48
+ git push origin --delete <type>/<slug> # if the merge did not already delete it
49
+ rm -rf .claude/worktrees/<slug> # only if `remove` left the directory behind
50
+ ```
51
+
52
+ Add `.claude/worktrees/` to `.gitignore` once, so a live worktree never shows
53
+ up as untracked noise in every `git status`.
54
+
55
+ ## Gotchas
56
+
57
+ 1. **A stale cwd creates worktrees inside dead paths.** If your shell sits in a
58
+ directory that has been removed (typically the *previous* task's worktree), a
59
+ relative `git worktree add .claude/worktrees/x` recreates the dead path and
60
+ nests the new worktree inside it. Always `cd` to the repo root by an
61
+ **absolute** path first, and verify with `git worktree list` afterwards.
62
+ 2. **`git worktree remove` fails while your shell is inside it** — or while a
63
+ watcher or install still holds a handle on `node_modules`. `cd` out first. If
64
+ the directory survives `remove --force`, run `git worktree prune` (the
65
+ metadata is then clean) and delete the leftover directory; retry later if it
66
+ is still busy.
67
+ 3. **Never touch a worktree you did not create.** Concurrent sessions make
68
+ worktrees appear and vanish mid-task. Removing another session's worktree
69
+ destroys unmerged work — and it is indistinguishable, afterwards, from that
70
+ session never having done the work.
71
+ 4. **One worktree per task.** Do not reuse a finished task's worktree: its
72
+ branch state and its install are both stale, and the reuse is invisible in
73
+ the diff.
@@ -46,18 +46,68 @@ them all; they are one rulebook.
46
46
  short-lived branch; the default branch is never committed to directly. Once
47
47
  the project has a remote and CI, changes reach it through the PR flow (local
48
48
  checks → reviewer fan-out → merge on an explicit criterion). See
49
- `.claude/rules/workflow.md` ("Branches and commits", "PR flow").
49
+ `.claude/rules/workflow.md` ("Branches and commits", "PR flow"). When another
50
+ session may touch this repo at the same time, the branch lives in its own
51
+ worktree — the `worktree-task` skill has the lifecycle and the cleanup.
50
52
  - **Gates.** `code-reviewer` runs before every PR; `security-scanner` runs when
51
53
  a change touches auth, secrets, parsing, or outbound calls. Blocking findings
52
54
  are resolved, not argued with. The `pr-ship` skill drives the gate.
53
55
  - **Enforcement is mechanical.** `guard-core-purity` catches an impure edit to
54
56
  the core the moment it lands; `guard-web-boundary` keeps the frontend off the
55
- backend; `block-no-verify` refuses pre-commit bypasses; `gate-stop-dod`
56
- refuses to end the session while a Definition-of-Done check fails. If a hook
57
- blocks you, fix the cause; never route around a hook.
58
- - **Work comes from the queue.** The Agent queue in `PLAN.md` is where
59
- autonomous work is picked up (the `loop` skill drives it); an empty queue
60
- ends the session it is never a cue to invent work.
57
+ backend; `block-no-verify` refuses pre-commit bypasses; `guard-bash` refuses
58
+ the "Never" tier force-pushing a shared branch, a production deploy, a
59
+ filesystem wipe and carries the kill switch; `gate-stop-dod` refuses to end
60
+ the session while a Definition-of-Done check fails. If a hook blocks you, fix
61
+ the cause; never route around a hook.
62
+ - **Enforcement is a pattern you can apply again.** Each of those hooks is one
63
+ stated invariant + one mechanical check + one test — the pattern is written down
64
+ in `.claude/rules/invariants.md`, and the `new-invariant` skill walks you
65
+ through adding one. The hooks that ship here are **examples, not laws**: if the
66
+ invariant they guard is not load-bearing in this project, delete it and spend
67
+ the slot on one that is.
68
+ - **There is a brake, and it is a real file.** `touch
69
+ ~/.claude/__PROJECT_NAME__-loop-STOP` and `guard-bash` denies every merge
70
+ until it is removed. Everything short of the merge stays allowed on purpose:
71
+ finish the task, push the branch, open the PR, write the journal, stop.
72
+ Stopping cleanly never means losing the work.
73
+ - **Work comes from the queue, through an adapter.** The `loop` skill selects via
74
+ `.claude/scripts/queue/index.mjs`, which reads whichever queue
75
+ `.claude/queue.json` names — the Agent queue in `PLAN.md` by default, issues in
76
+ this repository once it has a remote. An empty queue **ends the session**; it is
77
+ never a cue to invent work, and the agent never files its own work items.
78
+
79
+ ## The elevated paths of this project
80
+
81
+ Tier 2 in `.claude/rules/autonomy.md` names *kinds* of change. This block names
82
+ the **paths** in this repository where those kinds live, and
83
+ `.claude/scripts/detect-missed-gate.mjs` reads it — so a path that is not declared
84
+ is a path the gate sweep cannot see.
85
+
86
+ ```elevated-paths
87
+ packages/db/src/
88
+ .claude/
89
+ .github/workflows/
90
+ ```
91
+
92
+ `.claude/` and `.github/workflows/` are there because they are what *disarms* the
93
+ rest: a merge that rewrites the Never tier, unwires a hook or edits what CI runs
94
+ should never pass unreviewed. `packages/db/src/` is the one the generated shape
95
+ has.
96
+
97
+ **They are a seed, not a law — the list is yours to extend.** It is what every
98
+ generated shape has; a real project accumulates more (auth handlers, billing, a
99
+ credentials module, a migration directory). Add a path the same day you add the
100
+ code, because the gap between the two is exactly the window in which a change
101
+ slips through unreviewed.
102
+
103
+ The declaration is **composed, not centralised**: the sweep unions this block with
104
+ every `elevated-paths` block in `.claude/rules/`, so a stack layer declares the
105
+ paths that only exist in its shape. A gate declared over a directory this project
106
+ does not have would report "clean" while looking nowhere.
107
+
108
+ Nothing about this list is retroactive. Installing the sweep into a repo with
109
+ history means passing `--epoch <the day you installed it>` once, or the first run
110
+ reports every merge that predates the gate.
61
111
 
62
112
  ## Foot-guns
63
113
 
@@ -23,5 +23,31 @@ journal records history; the queues state only what is next.
23
23
 
24
24
  ## Journal
25
25
 
26
- <!-- One line per session, newest first: date-free, what moved, what blocked.
27
- Prune freely this is an operational log, not an archive. -->
26
+ Newest first, date-free order carries the sequence. Prune freely: this is
27
+ operational memory, not an archive. An unattended run writes an entry at every
28
+ stop **and** at checkpoints along the way, because a run that dies unexpectedly
29
+ must not take its history with it.
30
+
31
+ The fields exist so an entry can be visibly **incomplete**. A journal with no
32
+ stated shape decays into a diary that reads fine and proves nothing.
33
+
34
+ <!-- Template — copy the block, drop the fields that do not apply:
35
+
36
+ ### <one-line summary of the session>
37
+
38
+ - **done** — what landed, one line each, with the PR reference
39
+ - **escalated** — what stopped, and the diagnosis: what failed, what was tried,
40
+ the current hypothesis, and the one question whose answer unblocks it
41
+ - **reviewed** — changes that went through a reviewer gate, and what it returned
42
+ - **stopped at** — which stop condition ended the session (or "checkpoint,
43
+ still running")
44
+ - **queue hygiene** — queue items fixed in passing: stale state, a dependency
45
+ that was already satisfied, an item that describes work already done
46
+ - **cost** — the counts the session actually observed: reviewer subagents run,
47
+ CI runs consumed (re-runs included — the cheapest signal that a task fought
48
+ its tests), deploys triggered
49
+
50
+ A field the session cannot observe stays **visibly empty — never estimated**.
51
+ A plausible number will be believed, by the next reader and by the next run
52
+ reasoning about its own budget. Leave the gap; it is information.
53
+ -->
@@ -2,14 +2,30 @@
2
2
  "process": [
3
3
  ".claude/rules/workflow.md",
4
4
  ".claude/rules/autonomy.md",
5
+ ".claude/rules/invariants.md",
6
+ ".claude/skills/new-invariant/SKILL.md",
7
+ ".claude/skills/new-invariant/guard-invariant.example.mjs",
8
+ ".claude/skills/new-invariant/guard-invariant.example.test.mjs",
5
9
  ".claude/agents/test-writer.md",
6
10
  ".claude/agents/code-reviewer.md",
7
11
  ".claude/agents/security-scanner.md",
8
12
  ".claude/hooks/block-no-verify.mjs",
13
+ ".claude/hooks/guard-bash.mjs",
9
14
  ".claude/hooks/gate-stop-dod.mjs",
10
15
  ".claude/hooks/inject-rules.mjs",
11
16
  ".claude/skills/pr-ship/SKILL.md",
12
17
  ".claude/skills/loop/SKILL.md",
18
+ ".claude/skills/worktree-task/SKILL.md",
19
+ ".claude/scripts/detect-missed-gate.mjs",
20
+ ".claude/scripts/reconcile-external-prs.mjs",
21
+ ".claude/scripts/stop-flag.mjs",
22
+ ".claude/scripts/preflight.mjs",
23
+ ".claude/scripts/queue/core.mjs",
24
+ ".claude/scripts/queue/plan-md.mjs",
25
+ ".claude/scripts/queue/github-issues.mjs",
26
+ ".claude/scripts/queue/jira.mjs",
27
+ ".claude/scripts/queue/index.mjs",
28
+ ".claude/queue.json",
13
29
  "PLAN.md"
14
30
  ],
15
31
  "architecture": [
@@ -17,5 +33,8 @@
17
33
  ".claude/hooks/guard-core-purity.mjs",
18
34
  ".claude/hooks/guard-web-boundary.mjs"
19
35
  ],
20
- "meta": [".claude/settings.json", "CLAUDE.md"]
36
+ "meta": [
37
+ ".claude/settings.json",
38
+ "CLAUDE.md"
39
+ ]
21
40
  }
@@ -1,5 +1,10 @@
1
1
  name: CI
2
2
 
3
+ # The default token is read-only for this job: CI needs nothing else, and a
4
+ # workflow that can write is a workflow a compromised dependency can write with.
5
+ permissions:
6
+ contents: read
7
+
3
8
  on:
4
9
  push:
5
10
  pull_request:
@@ -16,7 +21,7 @@ jobs:
16
21
  with:
17
22
  node-version: 22
18
23
  cache: pnpm
19
- - run: pnpm install --no-frozen-lockfile
24
+ - run: pnpm install --frozen-lockfile
20
25
  - run: pnpm lint
21
26
  - run: pnpm typecheck
22
27
  - run: pnpm test
@@ -7,3 +7,11 @@ cdk.out/
7
7
  .next/
8
8
  out/
9
9
  next-env.d.ts
10
+ .claude/worktrees/
11
+
12
+ # secrets — never commit these
13
+ .env
14
+ .env.*
15
+ !.env.example
16
+ *.pem
17
+ *.key
@@ -1,5 +1,10 @@
1
1
  name: CI
2
2
 
3
+ # The default token is read-only for this job: CI needs nothing else, and a
4
+ # workflow that can write is a workflow a compromised dependency can write with.
5
+ permissions:
6
+ contents: read
7
+
3
8
  on:
4
9
  push:
5
10
  pull_request:
@@ -16,7 +21,7 @@ jobs:
16
21
  with:
17
22
  node-version: 22
18
23
  cache: pnpm
19
- - run: pnpm install --no-frozen-lockfile
24
+ - run: pnpm install --frozen-lockfile
20
25
  - run: pnpm lint
21
26
  - run: pnpm typecheck
22
27
  - run: pnpm test
@@ -8,3 +8,11 @@ var/
8
8
  out/
9
9
  next-env.d.ts
10
10
  dist/
11
+ .claude/worktrees/
12
+
13
+ # secrets — never commit these
14
+ .env
15
+ .env.*
16
+ !.env.example
17
+ *.pem
18
+ *.key