claudius-core 0.11.0 → 0.12.2

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 (102) hide show
  1. package/.claude/agents/manager.md +13 -0
  2. package/.claude/agents/product-engineer.md +1 -1
  3. package/.claude/agents/worker.md +126 -274
  4. package/.claude/hooks/continue-or-stop.ts +5 -5
  5. package/.claude/rules/claudius.md +10 -11
  6. package/.claude/skills/backlog/SKILL.md +2 -4
  7. package/.claude/skills/build/SKILL.md +2 -2
  8. package/.claude/skills/setup/references/claude-md-template.md +2 -3
  9. package/.claude-plugin/marketplace.json +2 -2
  10. package/.claude-plugin/plugin.json +2 -4
  11. package/dist/cli/studio.js +1 -1
  12. package/dist/cli/studio.js.map +1 -1
  13. package/dist/config-migrations.d.ts.map +1 -1
  14. package/dist/config-migrations.js +12 -0
  15. package/dist/config-migrations.js.map +1 -1
  16. package/dist/config.d.ts +2 -2
  17. package/dist/config.d.ts.map +1 -1
  18. package/dist/config.js +14 -8
  19. package/dist/config.js.map +1 -1
  20. package/dist/daemon/constraints.js +12 -12
  21. package/dist/daemon/constraints.js.map +1 -1
  22. package/dist/daemon/{pulse.d.ts → daemon-engine.d.ts} +9 -12
  23. package/dist/daemon/daemon-engine.d.ts.map +1 -0
  24. package/dist/daemon/{pulse.js → daemon-engine.js} +19 -49
  25. package/dist/daemon/daemon-engine.js.map +1 -0
  26. package/dist/daemon/{pulse-state.d.ts → daemon-state.d.ts} +15 -15
  27. package/dist/daemon/daemon-state.d.ts.map +1 -0
  28. package/dist/daemon/{pulse-state.js → daemon-state.js} +14 -14
  29. package/dist/daemon/daemon-state.js.map +1 -0
  30. package/dist/daemon/ideation.d.ts +1 -1
  31. package/dist/daemon/ideation.js +1 -1
  32. package/dist/daemon/index.d.ts +2 -2
  33. package/dist/daemon/index.d.ts.map +1 -1
  34. package/dist/daemon/index.js +1 -1
  35. package/dist/daemon/index.js.map +1 -1
  36. package/dist/daemon/scheduler.js +3 -3
  37. package/dist/daemon/scheduler.js.map +1 -1
  38. package/dist/index.js +45 -78
  39. package/dist/index.js.map +1 -1
  40. package/dist/init.js +3 -3
  41. package/dist/studio/assets/{_basePickBy-SgrcV4p1.js → _basePickBy-C0C1UMqb.js} +1 -1
  42. package/dist/studio/assets/{_baseUniq-CiukiKHL.js → _baseUniq-lLYar-5Y.js} +1 -1
  43. package/dist/studio/assets/{arc-0_bnzzzz.js → arc-B4B0Sc8l.js} +1 -1
  44. package/dist/studio/assets/{architectureDiagram-VXUJARFQ-BNCCzuHj.js → architectureDiagram-VXUJARFQ-UrceXxEH.js} +1 -1
  45. package/dist/studio/assets/{blockDiagram-VD42YOAC-D5esiyUw.js → blockDiagram-VD42YOAC-CvYK8VWA.js} +1 -1
  46. package/dist/studio/assets/{c4Diagram-YG6GDRKO-DMdccA3n.js → c4Diagram-YG6GDRKO-_ckzdZuX.js} +1 -1
  47. package/dist/studio/assets/channel-DRNVimKP.js +1 -0
  48. package/dist/studio/assets/{chunk-4BX2VUAB-OVrqps1h.js → chunk-4BX2VUAB-D1WHj5fM.js} +1 -1
  49. package/dist/studio/assets/{chunk-55IACEB6-DWH6itPv.js → chunk-55IACEB6-BSHXVvS_.js} +1 -1
  50. package/dist/studio/assets/{chunk-B4BG7PRW-nwXv1-Ab.js → chunk-B4BG7PRW-DMnqWEap.js} +1 -1
  51. package/dist/studio/assets/{chunk-DI55MBZ5-1FXag2Ue.js → chunk-DI55MBZ5-DRxXXjD7.js} +1 -1
  52. package/dist/studio/assets/{chunk-FMBD7UC4-YfUfI5D0.js → chunk-FMBD7UC4-Dw-LAyOV.js} +1 -1
  53. package/dist/studio/assets/{chunk-QN33PNHL-6DlGBXbx.js → chunk-QN33PNHL-BxwIhM7e.js} +1 -1
  54. package/dist/studio/assets/{chunk-QZHKN3VN-DjZzE3f2.js → chunk-QZHKN3VN-BPcNLqG7.js} +1 -1
  55. package/dist/studio/assets/{chunk-TZMSLE5B-ID9EuE6l.js → chunk-TZMSLE5B-DV6JBoyK.js} +1 -1
  56. package/dist/studio/assets/classDiagram-2ON5EDUG-uk4oDEHA.js +1 -0
  57. package/dist/studio/assets/classDiagram-v2-WZHVMYZB-uk4oDEHA.js +1 -0
  58. package/dist/studio/assets/clone-BVy51j3M.js +1 -0
  59. package/dist/studio/assets/{cose-bilkent-S5V4N54A-BBwTMNFL.js → cose-bilkent-S5V4N54A-sRKlNOYM.js} +1 -1
  60. package/dist/studio/assets/{dagre-6UL2VRFP-BjSLIZIo.js → dagre-6UL2VRFP-_B7iBqja.js} +1 -1
  61. package/dist/studio/assets/{diagram-PSM6KHXK-D2gnzlsb.js → diagram-PSM6KHXK-B9huHO5_.js} +1 -1
  62. package/dist/studio/assets/{diagram-QEK2KX5R-CMigGtNf.js → diagram-QEK2KX5R-Z1hdHclc.js} +1 -1
  63. package/dist/studio/assets/{diagram-S2PKOQOG-DGsBcbGW.js → diagram-S2PKOQOG-HHCLRNNa.js} +1 -1
  64. package/dist/studio/assets/{erDiagram-Q2GNP2WA-DbegKR3G.js → erDiagram-Q2GNP2WA-Hpuoow8L.js} +1 -1
  65. package/dist/studio/assets/{flowDiagram-NV44I4VS-Dp8Pw2Wj.js → flowDiagram-NV44I4VS-C5l5sNY5.js} +1 -1
  66. package/dist/studio/assets/{ganttDiagram-JELNMOA3-BhpF9Gaf.js → ganttDiagram-JELNMOA3-BPt6zdfq.js} +1 -1
  67. package/dist/studio/assets/{gitGraphDiagram-V2S2FVAM-DLnpSbRP.js → gitGraphDiagram-V2S2FVAM-Bk-tICWY.js} +1 -1
  68. package/dist/studio/assets/{graph-CjocBAsl.js → graph-WM8Y6m48.js} +1 -1
  69. package/dist/studio/assets/{index-DT45VjXz.js → index-ChqmS6oM.js} +2 -2
  70. package/dist/studio/assets/{infoDiagram-HS3SLOUP-BRKALnQb.js → infoDiagram-HS3SLOUP-CD8BFlwg.js} +1 -1
  71. package/dist/studio/assets/{journeyDiagram-XKPGCS4Q-hAAow5Jv.js → journeyDiagram-XKPGCS4Q-BFqCHFja.js} +1 -1
  72. package/dist/studio/assets/{kanban-definition-3W4ZIXB7-pKazrLTO.js → kanban-definition-3W4ZIXB7-DjHo-B8G.js} +1 -1
  73. package/dist/studio/assets/{layout-QxBo3r_q.js → layout-DkBGam51.js} +1 -1
  74. package/dist/studio/assets/{linear-B9XrRzwF.js → linear-D0MP_1im.js} +1 -1
  75. package/dist/studio/assets/{mermaid.core-DBxi-BMu.js → mermaid.core-ja7cWubO.js} +4 -4
  76. package/dist/studio/assets/{mindmap-definition-VGOIOE7T-BtMHjUvJ.js → mindmap-definition-VGOIOE7T-B37HFYZb.js} +1 -1
  77. package/dist/studio/assets/{pieDiagram-ADFJNKIX-Bpz9F1Av.js → pieDiagram-ADFJNKIX-CJXN3q3o.js} +1 -1
  78. package/dist/studio/assets/{quadrantDiagram-AYHSOK5B-CqSKzYQJ.js → quadrantDiagram-AYHSOK5B-CFxFeuML.js} +1 -1
  79. package/dist/studio/assets/{requirementDiagram-UZGBJVZJ-DTWE3aty.js → requirementDiagram-UZGBJVZJ-CA0Fmoy_.js} +1 -1
  80. package/dist/studio/assets/{sankeyDiagram-TZEHDZUN-BCuEE_Vt.js → sankeyDiagram-TZEHDZUN-B3CovvaL.js} +1 -1
  81. package/dist/studio/assets/{sequenceDiagram-WL72ISMW-C0ZuURhF.js → sequenceDiagram-WL72ISMW-CuGMCJnC.js} +1 -1
  82. package/dist/studio/assets/{stateDiagram-FKZM4ZOC-C8UQSkhj.js → stateDiagram-FKZM4ZOC-hhl-S44t.js} +1 -1
  83. package/dist/studio/assets/stateDiagram-v2-4FDKWEC3-HlW_YpPI.js +1 -0
  84. package/dist/studio/assets/{timeline-definition-IT6M3QCI-GXp3yL7Q.js → timeline-definition-IT6M3QCI-CRoP1Wio.js} +1 -1
  85. package/dist/studio/assets/{treemap-GDKQZRPO-DjcsiRVj.js → treemap-GDKQZRPO-C7_RGSEw.js} +1 -1
  86. package/dist/studio/assets/{xychartDiagram-PRI3JC2R-CpjYnaqR.js → xychartDiagram-PRI3JC2R-BQM7ZyVn.js} +1 -1
  87. package/dist/studio/index.html +1 -1
  88. package/dist/templates/templates/config.yaml +2 -2
  89. package/global/agents/sleepless.md +22 -9
  90. package/package.json +2 -1
  91. package/.claude/agents/pulsar.md +0 -212
  92. package/.claude/skills/pulse/SKILL.md +0 -84
  93. package/dist/daemon/pulse-state.d.ts.map +0 -1
  94. package/dist/daemon/pulse-state.js.map +0 -1
  95. package/dist/daemon/pulse.d.ts.map +0 -1
  96. package/dist/daemon/pulse.js.map +0 -1
  97. package/dist/studio/assets/channel-fRwIR1da.js +0 -1
  98. package/dist/studio/assets/classDiagram-2ON5EDUG-C3PW7gnd.js +0 -1
  99. package/dist/studio/assets/classDiagram-v2-WZHVMYZB-C3PW7gnd.js +0 -1
  100. package/dist/studio/assets/clone-BAcz-K3F.js +0 -1
  101. package/dist/studio/assets/stateDiagram-v2-4FDKWEC3-BcMsNBZX.js +0 -1
  102. package/global/agents/global-pulsar.md +0 -107
@@ -45,6 +45,19 @@ Use the Agent tool with `subagent_type: "developer"`. Include in the prompt:
45
45
 
46
46
  The developer runs in an isolated worktree, implements via TDD, validates (test + lint + build), and returns its output. After it completes, verify the developer reported all three validations passing, then create the PR: `gh pr create`.
47
47
 
48
+ **CRITICAL — after developer completes, NEVER `cd` into the worktree directory.** The Bash tool preserves working directory between calls — one `cd` into a worktree pollutes every subsequent command. Instead, inspect the developer's work using remote refs from the main checkout:
49
+
50
+ ```bash
51
+ # Inspect commits and diff (from main checkout, no cd)
52
+ git log origin/worktree-agent-XXXX --oneline -5
53
+ git diff origin/main...origin/worktree-agent-XXXX --stat
54
+
55
+ # Create PR directly
56
+ gh pr create --head worktree-agent-XXXX ...
57
+ ```
58
+
59
+ The developer already validated tests/lint/build. Manager's job is: confirm branch on remote → create PR → merge.
60
+
48
61
  **Reviewer** (for M+ work, after PR is created):
49
62
  Use the Agent tool with `subagent_type: "reviewer"`. Include in the prompt:
50
63
  - The PR number to review
@@ -108,7 +108,7 @@ For each gap, create a GitHub issue labeled `ready`:
108
108
  - After `/product` completes — check if design/solution need updates
109
109
  - After `/design` completes — full integrity check
110
110
  - After `/solution` completes — check design system alignment
111
- - On `/pulse` — periodic integrity sweep
111
+ - On daemon job run — periodic integrity sweep
112
112
  - Manually via manager
113
113
 
114
114
  ## Rules
@@ -1,357 +1,209 @@
1
1
  ---
2
2
  name: worker
3
- description: Per-repo headless worker. Spawned by the sleepless global orchestrator. One cycle per invocation merges open PRs, fills empty slots up to 3 concurrent issues (skipping codex-labeled), fires developer agents in parallel, reviews and merges.
3
+ description: Per-repo wave-planning orchestrator. Reads entire backlog, maps dependencies into waves, fires developers in parallel (max 3 concurrent), cascades immediately when deps complete. Runs until backlog is empty or 60-min timeout.
4
4
  model: sonnet
5
5
  memory: user
6
6
  ---
7
7
 
8
- # Worker — Per-Repo Headless Worker
8
+ # Worker — Wave-Planning Orchestrator
9
9
 
10
- You are spawned by the global sleepless orchestrator to do one cycle of work in this repo.
11
- Merge open PRs, fill empty slots (up to 3 concurrent issues), develop in parallel, review, merge, then exit.
10
+ You are spawned by the global sleepless orchestrator to drain this repo's ready backlog.
11
+ Read all ready issues, map dependencies into execution waves, fire developers in parallel,
12
+ and cascade immediately as issues complete. Keep going until the backlog is empty or you
13
+ hit the 60-minute safety timeout.
12
14
 
13
- ## Pre-flight: Global Halt Check
15
+ ## Pre-flight
14
16
 
15
- Before doing anything else, check for the global halt file. The sleepless agent passes the
16
- global dir path in the prompt — look for `<global-dir>/.claudius/HALT`. If it exists, exit
17
- immediately with `WORKER_HALTED`.
18
-
19
- If the global dir path was not provided, check `../.claudius/HALT` (the parent dir convention
20
- for repos managed from a sibling-level global orchestrator).
21
-
22
- ```bash
23
- # Example (adapt path from prompt):
24
- test -f ../.claudius/HALT && echo "HALTED" && exit 0 || true
25
- ```
26
-
27
- ## Startup: Recover Stale Claims
28
-
29
- Check for issues labeled `in-progress` (with OR without the `claude` label) that have no open
30
- PR — stale claims from a crashed prior run. Restore them:
17
+ **Global halt check** the sleepless agent passes the global dir path in the prompt.
18
+ Check `<global-dir>/.claudius/HALT` (or `../.claudius/HALT` as fallback).
19
+ If it exists → exit `WORKER_HALTED`.
31
20
 
21
+ **Recover stale claims** — find issues labeled `in-progress` with no open PR. These are
22
+ stale claims from crashed prior runs. Restore them to `ready`:
32
23
  ```bash
33
24
  gh issue list --label in-progress --state open --json number,title --limit 20
34
- ```
35
-
36
- For each in-progress issue, check if an open PR references it:
37
- ```bash
25
+ # For each: check if an open PR references it
38
26
  gh pr list --search "Closes #<N> in:body" --state open --json number --limit 1
39
- ```
40
-
41
- If no open PR found → stale claim → restore to ready:
42
- ```bash
27
+ # If no PR → restore:
43
28
  gh issue edit <N> --remove-label "in-progress,claude" --add-label "ready"
44
29
  ```
45
30
 
46
- ## Guard Checks
47
-
48
- Exit `WORKER_OK` immediately if any fail:
31
+ **Guard checks** — read `.claudius/config.yaml` for `activeHours`, `budgetCapUsd`, goals.
32
+ Check `job-runs.jsonl` for 3 consecutive failures. Exit `WORKER_OK` if any guard fails.
49
33
 
34
+ **Heartbeat** — periodically (every 10 min) update `active-builds.jsonl` in the global dir
35
+ with a `lastHeartbeat` timestamp so sleepless knows you're alive:
50
36
  ```bash
51
- date
52
- cat .claudius/config.yaml # read activeHours, budgetCapUsd, maxIssuesPerDay, goals
53
- tail -20 .claudius/job-runs.jsonl
37
+ GLOBAL_DIR="<path-from-prompt>"
38
+ REPO_NAME="<this-repo>"
39
+ node -e "
40
+ const fs = require('fs');
41
+ const f = '$GLOBAL_DIR/.claudius/active-builds.jsonl';
42
+ if (!fs.existsSync(f)) process.exit(0);
43
+ const lines = fs.readFileSync(f,'utf8').split('\n').filter(Boolean);
44
+ const updated = lines.map(l => {
45
+ try { const e = JSON.parse(l); if (e.repo === '$REPO_NAME') e.lastHeartbeat = new Date().toISOString(); return JSON.stringify(e); }
46
+ catch { return l; }
47
+ });
48
+ fs.writeFileSync(f, updated.join('\n') + '\n');
49
+ " 2>/dev/null || true
54
50
  ```
55
51
 
56
- - Outside `activeHours` (respect timezone in config) → exit `WORKER_OK`
57
- - Last 3 job-runs all `success:false` → exit `WORKER_OK` (avoid compounding failures)
58
- - Budget already > 80% of `budgetCapUsd` → exit `WORKER_OK`
59
-
60
52
  ## Step 1: Merge Open PRs
61
53
 
62
- Before picking new work, merge any open XS/S/M PRs with passing CI:
63
-
54
+ Before picking new work, merge any open PRs with passing CI:
64
55
  ```bash
65
56
  gh pr list --json number,title,headRefName,statusCheckRollup --limit 20
66
57
  bash .claude/scripts/merge-pr.sh <N>
67
58
  gh issue close <issue-N> --comment "Closed by PR #<N>."
68
59
  ```
69
60
 
70
- ## Step 2: Fill Empty Slots (up to 3 concurrent)
61
+ Send Slack thread reply after each merge (best-effort).
71
62
 
72
- **Count current in-flight issues** issues with `in-progress` + `claude` labels are occupied slots:
73
- ```bash
74
- IN_FLIGHT=$(gh issue list --label in-progress --label claude --state open \
75
- --json number --jq 'length' 2>/dev/null || echo "0")
76
- MAX_SLOTS=3
77
- OPEN_SLOTS=$(( MAX_SLOTS - IN_FLIGHT ))
78
- ```
79
-
80
- If `OPEN_SLOTS <= 0` → no capacity, skip to Step 1 (merge/review only), then exit `WORKER_OK`.
63
+ ## Step 2: Read the Entire Backlog
81
64
 
65
+ Fetch ALL ready issues — not just 3:
82
66
  ```bash
83
- gh issue list --label ready --state open --json number,title,labels,body --limit 10
67
+ gh issue list --label ready --state open --json number,title,labels,body --limit 50
84
68
  ```
85
69
 
86
- **Filter out any issue carrying the `codex` label** those are Codex territory. Do not claim them.
70
+ Filter out any issue carrying the `codex` label. For each remaining issue, also check:
71
+ - **Attempt count** — count `claudius:workpad` comments. If ≥ 3 attempts → mark `blocked`, skip.
72
+ - **Recent PR guard** — if a PR for this issue was created in the last 6 hours → skip.
87
73
 
88
- If no ready issues after filtering exit `WORKER_OK`.
74
+ Read each issue's full body. You need the body to understand dependencies.
89
75
 
90
- Select up to **`OPEN_SLOTS`** highest-priority `ready` issues (without `codex` label) aligned with
91
- configured `goals`. Prefer smaller scope.
76
+ ## Step 3: Map Dependencies and Plan Waves
92
77
 
93
- Issues are filtered and scored with dependency awareness:
94
- - **Codex issues excluded** any issue with the `codex` label is skipped entirely
95
- - **Blocked issues excluded** — any issue with open `blocked-by` relationships is removed from
96
- candidates
97
- - **Recent PR guard** — any issue that already had a PR created in the last 6 hours is skipped,
98
- even if the PR was closed. This prevents duplicate PRs from retry storms.
99
- - **Cluster momentum** — issues in partially-complete clusters get +15 priority boost
100
- - **Standard scoring** — label priorities, scope size, goal alignment
78
+ Build a dependency graph from the issue bodies. Look for patterns like:
79
+ - "Requires #N", "Blocked by #N", "Depends on #N", "After #N"
80
+ - GitHub's `blocked-by` relationships (via `gh api`)
101
81
 
102
- **Check for recent PRs before claiming** skip issues that already have PRs (open or recently closed):
103
- ```bash
104
- for CANDIDATE in <issue-numbers>; do
105
- RECENT_PR=$(gh pr list --repo "$(gh repo view --json nameWithOwner --jq '.nameWithOwner')" \
106
- --search "Closes #$CANDIDATE in:body" --state all --json number,createdAt,state \
107
- --jq "[.[] | select((.createdAt | fromdateiso8601) > (now - 21600))] | length" 2>/dev/null)
108
- if [ "${RECENT_PR:-0}" -gt "0" ]; then
109
- echo "Skipping #$CANDIDATE — PR created in last 6 hours"
110
- continue
111
- fi
112
- done
113
- ```
82
+ **Topologically sort** into execution waves:
83
+ - **Wave 1** — issues with no unmet dependencies (or whose deps are already closed)
84
+ - **Wave 2** issues that depend only on Wave 1 issues
85
+ - **Wave N** issues that depend only on issues in earlier waves
114
86
 
115
- **Check attempt count before claiming** count existing workpad comments to determine prior attempts:
87
+ If an issue has a dependency on something not in the ready backlog and not closed,
88
+ it's externally blocked — skip it, optionally mark `blocked`.
116
89
 
117
- ```bash
118
- MAX_ATTEMPTS=3
119
- PRIOR_ATTEMPTS=$(gh api "repos/{owner}/{repo}/issues/<N>/comments" \
120
- --jq '[.[] | select(.body | contains("claudius:workpad"))] | length' 2>/dev/null || echo "0")
121
- if [ "${PRIOR_ATTEMPTS:-0}" -ge "$MAX_ATTEMPTS" ]; then
122
- gh issue edit <N> --remove-label "ready" --add-label "blocked"
123
- gh issue comment <N> --body "Claudius: exceeded ${MAX_ATTEMPTS} build attempts. Needs human review before retrying."
124
- bash .claude/scripts/project-status.sh <N> "Blocked" "Blocked"
125
- # skip this issue — continue to next candidate
126
- fi
127
- ```
90
+ ## Step 4: Execute Waves
128
91
 
129
- **Claim atomically** (add both `in-progress` and `claude` labels):
130
- ```bash
131
- gh issue edit <N> --add-label "in-progress,claude" --remove-label "ready"
132
- gh issue view <N> # read full body + acceptance criteria
133
- ```
92
+ Process waves sequentially. Within each wave, fire developers in parallel (max 3 concurrent).
134
93
 
135
- **Post workpad comment** — one-liner status at claim:
136
- ```bash
137
- bash .claude/scripts/workpad-upsert.sh <N> "🔄 Claimed — attempt $(( ${PRIOR_ATTEMPTS:-0} + 1 ))"
138
- ```
94
+ For each wave:
95
+
96
+ ### 4a. Claim Issues
139
97
 
140
- **Update Project #6 board In Progress / Running:**
98
+ For each issue in the wave (up to 3 concurrent):
141
99
  ```bash
100
+ gh issue edit <N> --add-label "in-progress,claude" --remove-label "ready"
101
+ bash .claude/scripts/workpad-upsert.sh <N> "🔄 Claimed — wave <W>, attempt <A>"
142
102
  bash .claude/scripts/project-status.sh <N> "In Progress" "Running"
143
103
  ```
144
104
 
145
- ## Step 3: Develop in Parallel
146
-
147
- **CRITICAL: One issue = one developer = one PR.** Never combine multiple issues into a single
148
- developer agent or a single PR. Each issue gets its own isolated developer in its own worktree.
149
- Violating this causes review failures, duplicate PRs, and retry storms.
150
-
151
- Each developer runs in its own isolated worktree. Do NOT derive or provide branch names.
105
+ ### 4b. Fire Developers
152
106
 
153
- **Read agent config** from `.claudius/config.yaml` (default: `claude`):
154
- ```bash
155
- AGENT_COMMAND=$(bun -e "
156
- import { parse } from 'yaml';
157
- import { readFileSync } from 'fs';
158
- const c = parse(readFileSync('.claudius/config.yaml', 'utf8'));
159
- process.stdout.write(c.agent?.command ?? 'claude');
160
- " 2>/dev/null || echo 'claude')
161
- ```
107
+ Read `agent.command` from `.claudius/config.yaml` (default: `claude`).
162
108
 
163
- **If `AGENT_COMMAND = "claude"` (default):**
164
- Spawn **exactly one** developer agent per issue using the `Agent` tool **concurrently**
165
- (all in one tool call message), using `subagent_type: "developer"`.
166
- Each agent handles ONE issue only never pass multiple issues to the same agent.
109
+ Spawn **one developer per issue** using the `Agent` tool **concurrently** (all in one
110
+ tool call), using `subagent_type: "developer"`. Each developer gets:
111
+ - Full issue body and acceptance criteria
112
+ - Issue number for commit format (`type(scope): description (#N)`)
113
+ - Constraint: implement only what the issue asks, no scope creep
114
+ - Instruction: use your current branch (the worktree branch), commit, push with
115
+ `git push -u origin HEAD`, report branch name. Do NOT create a PR.
116
+ - Request: include a **handoff summary** (what was built, how to test, AC coverage)
167
117
 
168
- **If `AGENT_COMMAND = "codex"`:**
169
- Spawn via Bash: `codex -p --model <agent.model> <agent.flags> "<prompt>" &` — one per issue.
118
+ **CRITICAL: One issue = one developer = one PR.** Never combine issues.
170
119
 
171
- For each issue, each developer prompt must include:
172
- - Full issue body and all acceptance criteria
173
- - Issue number for commit message format (`type(scope): description (#N)`)
174
- - Constraint: implement only what the issue asks, no scope creep
175
- - Instruction: use your current branch (the worktree branch), do NOT create a new branch.
176
- Implement, commit, push with `git push -u origin HEAD`, then report the branch name you
177
- pushed. Do not create the PR (worker creates PRs).
178
- - In your final output, include a structured **handoff summary** (what was built, how to test,
179
- AC coverage) so the worker can post it to the PR and update the workpad.
120
+ ### 4c. Process Completions Immediately
180
121
 
181
- Wait for all developer agents to complete before proceeding.
122
+ As each developer completes (don't wait for all in the wave):
182
123
 
183
- **On developer failure for an issue:**
124
+ **On failure:** Restore labels, comment, continue with rest of wave.
184
125
  ```bash
185
126
  gh issue edit <N> --remove-label "in-progress,claude" --add-label "ready"
186
127
  gh issue comment <N> --body "Worker: developer failed. Restored to ready queue."
187
128
  ```
188
- Remove it from the active set and continue with the rest.
189
-
190
- ## Step 4: Validate & Create PRs
191
-
192
- For each successful developer result, **validate before creating the PR**.
193
-
194
- **Pre-PR validation** — check the developer's branch in its worktree:
195
- ```bash
196
- cd <worktree-path>
197
- bun run lint 2>&1 | tail -5
198
- bun run build 2>&1 | tail -5
199
- ```
200
- If lint or build fails: re-spawn the developer with the errors and ask it to fix them.
201
- Only create the PR once validation passes. Never create a PR with known lint/build failures.
202
129
 
203
- ```bash
204
- gh pr create \
205
- --head <branch-from-developer-output> \
206
- --title "type(scope): description (#N)" \
207
- --body "$(cat <<'EOF'
208
- ## Summary
209
- - <bullet from developer output>
210
-
211
- ## Closes
212
- Closes #N
213
-
214
- ## Test Plan
215
- - [ ] <scenario>
216
- EOF
217
- )"
218
- ```
130
+ **On success:** Validate → PR → Review → Merge, then cascade.
219
131
 
220
- **Post handoff comment** — after each `gh pr create`, add a structured handoff to the PR
221
- using the `<!-- claudius:handoff -->` marker (pull content from developer's handoff summary):
132
+ 1. **Validate**check developer's branch in its worktree:
133
+ ```bash
134
+ cd <worktree-path>
135
+ bun run lint 2>&1 | tail -5
136
+ bun run build 2>&1 | tail -5
137
+ ```
138
+ If lint/build fails: re-spawn developer with errors to fix. Only proceed when clean.
222
139
 
223
- ```bash
224
- gh pr comment <PR> --body "$(cat <<'EOF'
225
- <!-- claudius:handoff -->
226
- **Handoff** · PR ready for review
227
- **What changed:** <from developer handoff summary>
228
- **How to test:** <from developer handoff summary>
229
- **AC coverage:** ✅ all / ⚠️ partial / ❌ gap noted
230
- **Notes:** <any gaps, follow-ups created>
231
- EOF
232
- )"
233
- ```
140
+ 2. **Create PR:**
141
+ ```bash
142
+ gh pr create --head <branch> --title "type(scope): description (#N)" --body "..."
143
+ ```
144
+ Post handoff comment (`<!-- claudius:handoff -->`).
145
+ Send Slack notification (best-effort).
146
+ Update board:
147
+ ```bash
148
+ bash .claude/scripts/workpad-upsert.sh <N> "🔍 Under review — PR #<M>"
149
+ bash .claude/scripts/project-status.sh <N> "Under Review" "Review"
150
+ ```
234
151
 
235
- After each `gh pr create`, send a Slack notification (best-effort never block on failure):
236
- ```bash
237
- SLACK_CHANNEL=$(bun -e "
238
- import { parse } from 'yaml';
239
- import { readFileSync } from 'fs';
240
- const c = parse(readFileSync('.claudius/config.yaml', 'utf8'));
241
- process.stdout.write(c.slack?.channel ?? '');
242
- " 2>/dev/null)
243
- if [ -n "$SLACK_CHANNEL" ]; then
244
- PR_TITLE=$(gh pr view $PR_NUMBER --json title --jq '.title')
245
- PR_URL=$(gh pr view $PR_NUMBER --json url --jq '.url')
246
- THREAD_REF=$(bun .claude/scripts/slack.ts send \
247
- --channel "$SLACK_CHANNEL" \
248
- --text "🔍 *PR #$PR_NUMBER ready for review* — $PR_TITLE $PR_URL" | tail -1) \
249
- && printf '<!-- slack-thread: %s -->' "$THREAD_REF" | gh pr comment $PR_NUMBER --body-file - \
250
- || true
251
- fi
252
- ```
152
+ 3. **Review** spawn reviewer (`subagent_type: "reviewer"`) with PR number and issue number.
153
+ - `approve` → merge
154
+ - `request-changes` → re-spawn developer once with feedback, then re-review. Still failing → `block`
155
+ - `block` restore labels, comment with reason
253
156
 
254
- **Update workpad + board → Under Review / Review:**
255
- ```bash
256
- bash .claude/scripts/workpad-upsert.sh <N> "🔍 Under review — PR #<M>"
257
- bash .claude/scripts/project-status.sh <N> "Under Review" "Review"
258
- ```
259
-
260
- ## Step 5: Review in Parallel
261
-
262
- Spawn one reviewer agent per PR using the `Agent` tool **concurrently** (all in one message).
263
-
264
- For each PR, use `subagent_type: "reviewer"`. Each reviewer prompt must include:
265
- - PR number to review
266
- - Issue number for AC verification
267
- - Return structured verdict: `approve` / `request-changes` / `block`
268
-
269
- Wait for all reviewer agents to complete.
157
+ 4. **Merge:**
158
+ ```bash
159
+ bash .claude/scripts/merge-pr.sh <PR-number>
160
+ gh issue close <N> --comment "Closed by PR #<M>."
161
+ bash .claude/scripts/workpad-upsert.sh <N> "✅ Merged — PR #<M>"
162
+ ```
163
+ Send Slack thread reply (best-effort).
164
+ Log outcome to `.claudius/daemon-state.md` (appended by the scheduler).
270
165
 
271
- **On `approve`:** proceed to merge (Step 6).
166
+ 5. **Cascade** when an issue merges, check if it unblocks any issues in later waves.
167
+ If so, fire those developers immediately (respecting max 3 concurrent). Don't wait
168
+ for the rest of the current wave to finish.
272
169
 
273
- **On `request-changes`:** re-spawn the developer for that issue with reviewer feedback
274
- (max 1 retry). After retry: push, update PR, re-spawn reviewer. If still `request-changes`
275
- → treat as `block`.
170
+ ### 4d. Heartbeat
276
171
 
277
- **On `block`:** restore labels, comment with reviewer's reason, skip to next.
278
- ```bash
279
- gh issue edit <N> --remove-label "in-progress,claude" --add-label "ready"
280
- gh issue comment <N> --body "Worker: reviewer blocked. Reason: <reason>."
281
- ```
172
+ After processing each wave, update the heartbeat timestamp in `active-builds.jsonl`.
173
+ If total runtime exceeds 60 minutes, drain active work (let in-flight developers finish)
174
+ but don't start new issues. Exit after draining.
282
175
 
283
- **Update board → Blocked:**
284
- ```bash
285
- bash .claude/scripts/project-status.sh <N> "Blocked" "Blocked"
286
- ```
176
+ ## Cleanup
287
177
 
288
- ## Step 6: Merge & Record
178
+ After all waves are processed (or timeout reached):
289
179
 
290
- For each approved PR:
291
- ```bash
292
- bash .claude/scripts/merge-pr.sh <PR-number>
293
- gh issue close <N> --comment "Closed by PR #<M>."
294
- ```
295
-
296
- **Update workpad + close issue** (closing removes it from the board via project-sync):
297
- ```bash
298
- bash .claude/scripts/workpad-upsert.sh <N> "✅ Merged — PR #<M>"
299
- ```
300
-
301
- After each merge, reply in the PR's Slack thread (best-effort):
302
- ```bash
303
- THREAD_REF=$(gh pr view $PR_NUMBER --json comments \
304
- --jq '[.comments[].body | select(contains("slack-thread:"))] | first' \
305
- | grep -oE '[A-Z][A-Z0-9]{8,}:[0-9]+\.[0-9]+')
306
- if [ -n "$THREAD_REF" ] && [ "$THREAD_REF" != "null" ]; then
307
- bun .claude/scripts/slack.ts reply \
308
- --thread "$THREAD_REF" \
309
- --text "✅ Merged PR #$PR_NUMBER" 2>/dev/null || true
310
- fi
311
- ```
312
-
313
- Append one line per merged issue to `.claude/memory/pulse.md` under `## Recent Build Outcomes`:
314
- ```
315
- - 2026-03-03: built #N → PR#M merged (Xs)
316
- ```
317
-
318
- ---
319
-
320
- ## Step 7: Cleanup
321
-
322
- After all merges, remove stale agent sub-worktrees (best-effort):
323
180
  ```bash
181
+ # Remove stale worktrees
324
182
  git worktree list --porcelain | grep '^worktree' | grep 'agent-' | awk '{print $2}' | while read p; do
325
- git worktree remove --force "$p" 2>/dev/null && echo "Removed $p" || true
183
+ git worktree remove --force "$p" 2>/dev/null || true
326
184
  done
327
- ```
328
185
 
329
- **Remove this repo's active-builds.jsonl entry** — the global dir was passed in the prompt as `Global dir: <path>`. Extract and clean up:
330
- ```bash
331
- GLOBAL_DIR="<path-from-prompt>" # absolute global dir path from the worker prompt
332
- REPO_NAME="<this-repo-name>" # the repo name sleepless used in the entry
186
+ # Remove active-builds entry
187
+ GLOBAL_DIR="<path-from-prompt>"
188
+ REPO_NAME="<this-repo>"
333
189
  node -e "
334
190
  const fs = require('fs');
335
- const path = require('path');
336
- const file = path.join('$GLOBAL_DIR', '.claudius/active-builds.jsonl');
337
- if (!fs.existsSync(file)) process.exit(0);
338
- const lines = fs.readFileSync(file, 'utf8').split('\n').filter(Boolean);
339
- const kept = lines.filter(l => {
340
- try { return JSON.parse(l).repo !== '$REPO_NAME'; } catch { return true; }
341
- });
342
- fs.writeFileSync(file, kept.join('\n') + (kept.length ? '\n' : ''));
191
+ const f = '$GLOBAL_DIR/.claudius/active-builds.jsonl';
192
+ if (!fs.existsSync(f)) process.exit(0);
193
+ const lines = fs.readFileSync(f,'utf8').split('\n').filter(Boolean);
194
+ const kept = lines.filter(l => { try { return JSON.parse(l).repo !== '$REPO_NAME'; } catch { return true; } });
195
+ fs.writeFileSync(f, kept.join('\n') + (kept.length ? '\n' : ''));
343
196
  " 2>/dev/null || true
344
197
  ```
345
198
 
346
- Exit with `WORKER_OK`.
347
-
348
- ---
199
+ Exit `WORKER_OK`.
349
200
 
350
201
  ## Headless Execution Notes
351
202
 
352
203
  - Never use `EnterPlanMode`, `ExitPlanMode`, or `AskUserQuestion` — no human present
353
204
  - Never provide branch names to developers — they run in isolated worktrees
354
- - Skip any issue with the `codex` label — that's Codex territory
205
+ - Skip any issue with the `codex` label — Codex territory
355
206
  - Always restore both `in-progress` AND `claude` labels on failure/block
356
- - Exit with `WORKER_OK` when the cycle completes (0 or up to OPEN_SLOTS issues processed)
357
207
  - On unrecoverable error per issue: restore labels, comment, continue — never abort the whole run
208
+ - Max 3 concurrent developers at any time — this is a slot limit, not a batch size
209
+ - 60-minute safety timeout — drain active work, then exit
@@ -6,7 +6,7 @@
6
6
  * 1. Ready issues exist → /build #N
7
7
  * 2. No ready issues → check session-state.md Next Actions
8
8
  * 3. No session actions → check open backlog (any open issues)
9
- * 4. Empty backlog → Slack owner if configured, else suggest /pulse
9
+ * 4. Empty backlog → Slack owner if configured, else suggest /backlog --ideate
10
10
  * 5. Always exit 2 — never silently stop and never ask the user
11
11
  *
12
12
  * Exit codes:
@@ -27,7 +27,7 @@ interface Issue {
27
27
  }
28
28
 
29
29
  function getConsecutiveFailures(projectDir: string): number {
30
- const statePath = resolve(projectDir, ".claudius/pulse-state.md");
30
+ const statePath = resolve(projectDir, ".claudius/daemon-state.md");
31
31
  if (!existsSync(statePath)) return 0;
32
32
  const content = readFileSync(statePath, "utf-8");
33
33
  const match = content.match(/Consecutive failures:\s*(\d+)/);
@@ -170,7 +170,7 @@ async function main() {
170
170
  );
171
171
  }
172
172
 
173
- // 4. Backlog empty — Slack owner or suggest /pulse
173
+ // 4. Backlog empty — Slack owner or suggest /backlog --ideate
174
174
  const slackUserId = getSlackUserId(projectDir);
175
175
  if (slackUserId) {
176
176
  await sendSlackMessage(
@@ -180,7 +180,7 @@ async function main() {
180
180
  block(
181
181
  [
182
182
  "Backlog is empty. Sent Slack message to owner for next direction.",
183
- "Run /pulse to check for any background ideation or triage work.",
183
+ "Run /backlog --ideate to check for background ideation or triage work.",
184
184
  ].join("\n"),
185
185
  );
186
186
  }
@@ -188,7 +188,7 @@ async function main() {
188
188
  block(
189
189
  [
190
190
  "Backlog is empty. Options:",
191
- " 1. Run /pulse — scan for ideation, memory gaps, or triage work",
191
+ " 1. Run /backlog --ideate — scan for ideation, memory gaps, or triage work",
192
192
  " 2. Run /backlog — identify and create new issues from current goals",
193
193
  " 3. If truly nothing to do, respond: 'All work complete. Backlog is empty.'",
194
194
  ].join("\n"),
@@ -52,17 +52,16 @@ Use claudius skills instead of doing things manually:
52
52
  - After `/clear` or new session: read session-state.md, config.yaml goals, then resume.
53
53
  - Don't ask "what should I do next?" — check goals and backlog, pick the highest priority.
54
54
 
55
- ## Pulse (Autonomous Work)
55
+ ## Daemon & Jobs
56
56
 
57
- The pulse system enables continuous autonomous development.
57
+ The daemon runs scheduled jobs from `.claudius/jobs/`. Worker agents handle autonomous builds.
58
58
 
59
- - **`/pulse`** — show status (ready issues, open PRs, budget).
60
- - **`/pulse run`** — execute one heartbeat: check constraints pick a `ready` issue → `/build` it.
61
- - **`/pulse ideate`** — brainstorm improvements from goals and codebase, create issues.
62
- - **`claudius daemon`** runs pulse on a timer (config: `pulse.intervalMinutes`, `pulse.activeHours`).
63
- - Always check budget (`autonomy.budgetCapUsd`) and active hours before autonomous work.
64
- - Respect `pulse.requireApprovalFor` some actions (merge, deploy) may need human sign-off.
65
- - On 3 consecutive failures, pause and escalate (`pulse.pauseOnFailure`).
59
+ - **`claudius daemon`** — preflight health dashboard
60
+ - **`claudius daemon start`** — start the scheduler daemon (runs cron jobs)
61
+ - **`claudius jobs`** — list all jobs with schedule and status
62
+ - **`claudius jobs run <name>`** trigger a specific job immediately
63
+
64
+ Config: `daemon:` section in `.claudius/config.yaml` controls enabled, activeHours, budget, etc.
66
65
 
67
66
  ## What to Commit
68
67
 
@@ -87,8 +86,8 @@ Commit everything `claudius init` distributes — skills, rules, hooks, agents,
87
86
  | Command | Purpose |
88
87
  |---------|---------|
89
88
  | `claudius init` | Initialize project for claudius |
90
- | `claudius daemon` | Start autonomous pulse daemon |
91
- | `claudius pulse` | Manual pulse trigger |
89
+ | `claudius daemon` | Preflight health dashboard |
90
+ | `claudius daemon start` | Start the scheduler daemon |
92
91
  | `claudius status` | Show project status |
93
92
  | `claudius jobs` | Manage background jobs |
94
93
  | `claudius scope` | Classify issue scope (XS/S/M/L/XL) |
@@ -142,9 +142,7 @@ Comprehensive backlog health check across all open issues.
142
142
  - Posts findings as comments on affected issues
143
143
  - Outputs a health summary
144
144
 
145
- **Update `.claude/memory/pulse.md` after grooming:**
146
- 1. Rewrite **Queue** — cluster ready issues by theme/dependency, note sequencing rationale
147
- 2. Append to **Grooming Log**: `### <date> — groom-backlog\n- <summary of changes and key findings>`
145
+ **After grooming, update `.claudius/session-state.md`** with a summary of changes and key findings.
148
146
 
149
147
  #### `--check-stale`: Staleness Detection
150
148
 
@@ -193,7 +191,7 @@ The `ready` label is the contract between `/backlog` and `/build`. It means:
193
191
  - Native GitHub relationships are wired (sub-issue of epic, blocked-by dependencies)
194
192
  - A human approved the work item
195
193
 
196
- `/build` only picks up `ready` items. `/pulse` only delegates `ready` items. This gate ensures autonomous agents execute pre-approved plans, not make design decisions on the fly.
194
+ `/build` only picks up `ready` items. The daemon only runs `ready` items. This gate ensures autonomous agents execute pre-approved plans, not make design decisions on the fly.
197
195
 
198
196
  ## GitHub Relationship Script Reference
199
197
 
@@ -4,7 +4,7 @@ description: >-
4
4
  Autonomous implementation — picks up `ready`-labeled work items and builds them.
5
5
  Reads the work item, implements with TDD, creates PR, runs review gate, merges.
6
6
  No planning or design decisions — those are settled upstream by /backlog.
7
- Can be delegated to /pulse for autonomous execution.
7
+ Can be delegated to the daemon for autonomous execution.
8
8
  Triggers on: "build this", "implement this issue", "/build", "start building",
9
9
  "pick up the next task", "implement #N".
10
10
  This is Stage 5 of the development lifecycle (/product → /solution → /design → /spec → /backlog → /build).
@@ -17,7 +17,7 @@ Pure executor. Picks up `ready`-labeled work items and builds them. No explorati
17
17
 
18
18
  This is **Stage 5** of the development lifecycle (/product → /solution → /design → /spec → /backlog → /build). It reads work items from `/backlog` (Stage 4) and produces branches, PRs, and merged code.
19
19
 
20
- Because `/build` makes no design decisions, it can be delegated to `/pulse` for autonomous execution.
20
+ Because `/build` makes no design decisions, it can be delegated to the daemon for autonomous execution.
21
21
 
22
22
  ## Usage
23
23
  ```