claude-dev-env 2.4.0 → 2.5.0

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 (195) hide show
  1. package/CLAUDE.md +53 -49
  2. package/_shared/pr-loop/scripts/_claude_permissions_common.py +84 -0
  3. package/_shared/pr-loop/scripts/code_rules_gate.py +4 -2
  4. package/_shared/pr-loop/scripts/grant_project_claude_permissions.py +306 -306
  5. package/_shared/pr-loop/scripts/pr_loop_shared_constants/claude_permissions_constants.py +44 -0
  6. package/_shared/pr-loop/scripts/pr_loop_shared_constants/copilot_quota_constants.py +24 -24
  7. package/_shared/pr-loop/scripts/pr_loop_shared_constants/stale_worktree_rule_sweep_constants.py +107 -107
  8. package/_shared/pr-loop/scripts/revoke_project_claude_permissions.py +290 -48
  9. package/_shared/pr-loop/scripts/tests/test_claude_permissions_common.py +42 -2
  10. package/_shared/pr-loop/scripts/tests/test_claude_permissions_constants.py +36 -0
  11. package/_shared/pr-loop/scripts/tests/test_code_rules_gate.py +100 -1
  12. package/_shared/pr-loop/scripts/tests/test_fix_hookspath.py +497 -497
  13. package/_shared/pr-loop/scripts/tests/test_revoke_project_claude_permissions.py +311 -2
  14. package/_shared/pr-loop/scripts/tests/test_stale_worktree_rule_sweep.py +301 -301
  15. package/_shared/pr-loop/scripts/tests/test_stale_worktree_rule_sweep_constants.py +85 -85
  16. package/_shared/pr-loop/worker-spawn.md +1 -1
  17. package/agents/CLAUDE.md +2 -1
  18. package/agents/caveman.md +0 -1
  19. package/agents/clasp-deployment-orchestrator.md +0 -1
  20. package/agents/clean-coder.md +0 -1
  21. package/agents/code-advisor.md +0 -1
  22. package/agents/code-quality-agent.md +1 -2
  23. package/agents/code-verifier.md +0 -1
  24. package/agents/deep-research.md +0 -1
  25. package/agents/docs-agent.md +0 -1
  26. package/agents/git-commit-crafter.md +0 -1
  27. package/agents/issue-tracker.md +42 -0
  28. package/agents/plan-packet-validator.md +0 -1
  29. package/agents/pr-description-writer.md +0 -1
  30. package/agents/test_agent_frontmatter.py +67 -18
  31. package/audit-rubrics/category_rubrics/category-o-docstring-vs-impl-drift.md +143 -141
  32. package/bin/CLAUDE.md +68 -5
  33. package/bin/ever-shipped-skills.mjs +1 -0
  34. package/bin/install-constants.mjs +88 -0
  35. package/bin/install.mjs +1138 -114
  36. package/bin/install.prune.test.mjs +869 -19
  37. package/bin/install.test.mjs +906 -2
  38. package/commands/implement.md +1 -1
  39. package/commands/right-size.md +1 -1
  40. package/docs/CLAUDE.md +1 -0
  41. package/docs/host-pool-health-monitor.md +102 -0
  42. package/docs/references/CLAUDE.md +4 -2
  43. package/docs/references/advisor-tool.md +13 -0
  44. package/docs/references/code-review-enforcement.md +10 -0
  45. package/docs/references/team-advisor-skill.md +14 -0
  46. package/hooks/blocking/CLAUDE.md +1 -0
  47. package/hooks/blocking/code_review_pr_create_gate.py +7 -3
  48. package/hooks/blocking/code_review_push_gate.py +9 -4
  49. package/hooks/blocking/code_review_stamp_directory_write_blocker.py +8 -0
  50. package/hooks/blocking/config/__init__.py +5 -5
  51. package/hooks/blocking/config/code_review_enforcement_constants.py +4 -1
  52. package/hooks/blocking/config/test_code_review_enforcement_constants.py +5 -0
  53. package/hooks/blocking/config/verified_commit_constants.py +160 -159
  54. package/hooks/blocking/orchestrator_refresh_reschedule_gate.py +256 -0
  55. package/hooks/blocking/pre_tool_use_dispatcher.py +24 -24
  56. package/hooks/blocking/test_code_review_pr_create_gate.py +14 -0
  57. package/hooks/blocking/test_code_review_push_gate.py +16 -0
  58. package/hooks/blocking/test_code_review_stamp_directory_write_blocker.py +19 -0
  59. package/hooks/blocking/test_orchestrator_refresh_reschedule_gate.py +231 -0
  60. package/hooks/blocking/test_pre_tool_use_dispatcher.py +10 -1
  61. package/hooks/blocking/test_verdict_directory_write_blocker.py +808 -808
  62. package/hooks/blocking/test_verification_verdict_store.py +54 -0
  63. package/hooks/blocking/test_verified_commit_gate.py +581 -581
  64. package/hooks/blocking/test_verified_commit_message_accuracy_blocker.py +131 -131
  65. package/hooks/blocking/verdict_directory_write_blocker.py +687 -687
  66. package/hooks/blocking/verification_verdict_store.py +1039 -1036
  67. package/hooks/blocking/verified_commit_message_accuracy_blocker.py +167 -167
  68. package/hooks/blocking/verifier_verdict_minter.py +280 -280
  69. package/hooks/git-hooks/test_pre_push.py +25 -0
  70. package/hooks/hooks.json +10 -0
  71. package/hooks/hooks_constants/CLAUDE.md +2 -1
  72. package/hooks/hooks_constants/enter_worktree_prefetch_constants.py +18 -18
  73. package/hooks/hooks_constants/orchestrator_refresh_reschedule_gate_constants.py +48 -0
  74. package/hooks/hooks_constants/ruff_integration_constants.py +16 -0
  75. package/hooks/lifecycle/enter_worktree_origin_prefetch.py +163 -146
  76. package/hooks/lifecycle/test_enter_worktree_origin_prefetch.py +185 -178
  77. package/hooks/pyproject.toml +1 -0
  78. package/hooks/validators/CLAUDE.md +1 -0
  79. package/hooks/validators/config/__init__.py +0 -0
  80. package/hooks/validators/config/directory_exemption_constants.py +183 -0
  81. package/hooks/validators/config/test_directory_exemption_constants.py +21 -0
  82. package/hooks/validators/conftest.py +4 -0
  83. package/hooks/validators/ruff_integration.py +49 -5
  84. package/hooks/validators/run_all_validators.py +206 -9
  85. package/hooks/validators/test_directory_exemption_constants.py +185 -0
  86. package/hooks/validators/test_python_antipattern_checks.py +110 -5
  87. package/hooks/validators/test_ruff_integration.py +92 -1
  88. package/hooks/validators/test_run_all_validators.py +115 -68
  89. package/hooks/validators/test_run_all_validators_pretooluse.py +159 -1
  90. package/package.json +10 -2
  91. package/rules/CLAUDE.md +1 -0
  92. package/rules/docstring-prose-matches-implementation.md +45 -44
  93. package/rules/state-what-is.md +25 -0
  94. package/rules/verified-commit-gate-skip.md +1 -1
  95. package/scripts/CLAUDE.md +1 -0
  96. package/scripts/Capture-PoolHealth.ps1 +410 -0
  97. package/scripts/_code_review_test_support.py +404 -0
  98. package/scripts/claude_chain_runner.py +141 -1
  99. package/scripts/conftest.py +16 -1
  100. package/scripts/dev_env_scripts_constants/CLAUDE.md +1 -1
  101. package/scripts/dev_env_scripts_constants/claude_chain_constants.py +9 -0
  102. package/scripts/resolve_worker_spawn.py +626 -626
  103. package/scripts/spawn_grok_batch.py +672 -672
  104. package/scripts/test_claude_chain_runner.py +131 -0
  105. package/scripts/test_invoke_code_review_chain.py +70 -0
  106. package/scripts/test_invoke_code_review_cli.py +192 -0
  107. package/scripts/test_invoke_code_review_contract.py +256 -0
  108. package/scripts/test_invoke_code_review_git.py +123 -0
  109. package/scripts/test_invoke_code_review_mode.py +99 -0
  110. package/scripts/test_resolve_worker_spawn.py +1014 -1014
  111. package/skills/CLAUDE.md +2 -0
  112. package/skills/auditing-claude-config/SKILL.md +114 -114
  113. package/skills/autoconverge/SKILL.md +427 -427
  114. package/skills/autoconverge/reference/convergence.md +24 -3
  115. package/skills/autoconverge/workflow/CLAUDE.md +1 -0
  116. package/skills/autoconverge/workflow/converge.clean-audit.test.mjs +3 -3
  117. package/skills/autoconverge/workflow/converge.contract.test.mjs +1263 -1263
  118. package/skills/autoconverge/workflow/converge.mjs +167 -0
  119. package/skills/autoconverge/workflow/converge.p2-advance.test.mjs +202 -0
  120. package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a11d903476b803493.jsonl +2 -2
  121. package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a26213978adeef6fb.jsonl +2 -2
  122. package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a3def0d15ed9d9110.jsonl +2 -2
  123. package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a41f41b1b708ee3b7.jsonl +2 -2
  124. package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a758b880abecc3ff7.jsonl +2 -2
  125. package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a8897b89656b1bd16.jsonl +2 -2
  126. package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-abd463d744a1437bc.jsonl +2 -2
  127. package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-ad19d027ae8ee1816.jsonl +2 -2
  128. package/skills/autoconverge/workflow/fixtures/wf_run/workflows/wf_881252e6-700.json +265 -265
  129. package/skills/closeout/SKILL.md +33 -50
  130. package/skills/codex-review/scripts/codex_review_scripts_constants/run_constants.py +8 -0
  131. package/skills/codex-review/scripts/run_codex_review.py +233 -1
  132. package/skills/codex-review/scripts/test_run_codex_review.py +189 -0
  133. package/skills/condensing-instructions/SKILL.md +81 -0
  134. package/skills/copilot-review/SKILL.md +119 -119
  135. package/skills/e-code-review/SKILL.md +52 -0
  136. package/skills/e-code-review/reference/fix.md +54 -0
  137. package/skills/e-code-review/reference/loop.md +43 -0
  138. package/skills/e-code-review/reference/low.md +57 -0
  139. package/skills/e-code-review/reference/medium.md +153 -0
  140. package/skills/e-code-review/reference/xhigh.md +182 -0
  141. package/skills/e-simplify/SKILL.md +97 -0
  142. package/skills/issue-tracker/SKILL.md +92 -0
  143. package/skills/issue-tracker/reference/epic-and-sub-issue-model.md +55 -0
  144. package/skills/issue-tracker/reference/handoff-schema.md +64 -0
  145. package/skills/issue-tracker/reference/operation-matrix.md +41 -0
  146. package/skills/orchestrator/SKILL.md +162 -21
  147. package/skills/orchestrator/scripts/status_gate.py +625 -0
  148. package/skills/orchestrator/scripts/status_gate_constants/__init__.py +1 -0
  149. package/skills/orchestrator/scripts/status_gate_constants/config/__init__.py +1 -0
  150. package/skills/orchestrator/scripts/status_gate_constants/config/constants.py +47 -0
  151. package/skills/orchestrator/scripts/test_status_gate.py +439 -0
  152. package/skills/orchestrator-refresh/SKILL.md +110 -35
  153. package/skills/plan-to-pr/SKILL.md +155 -0
  154. package/skills/plan-to-pr/reference/final-validation-tasks.md +15 -0
  155. package/skills/plan-to-pr/reference/model-routing.md +36 -0
  156. package/skills/plan-to-pr/reference/packet-contract.md +43 -0
  157. package/skills/plan-to-pr/reference/packet-schema.json +57 -0
  158. package/skills/plan-to-pr/reference/process-inventory.md +22 -0
  159. package/skills/plan-to-pr/reference/review-loop.md +33 -0
  160. package/skills/plan-to-pr/reference/run-record.schema.json +27 -0
  161. package/skills/plan-to-pr/reference/self-audit-tasks.md +15 -0
  162. package/skills/plan-to-pr/reference/task-seeds.md +14 -0
  163. package/skills/plan-to-pr/reference/task-ticket.md +38 -0
  164. package/skills/plan-to-pr/scripts/config/__init__.py +1 -0
  165. package/skills/plan-to-pr/scripts/config/constants.py +193 -0
  166. package/skills/plan-to-pr/scripts/create_packet.py +173 -0
  167. package/skills/plan-to-pr/scripts/test_create_packet.py +102 -0
  168. package/skills/plan-to-pr/scripts/test_validate_packet.py +256 -0
  169. package/skills/plan-to-pr/scripts/test_validate_protocol.py +135 -0
  170. package/skills/plan-to-pr/scripts/test_validate_run.py +158 -0
  171. package/skills/plan-to-pr/scripts/validate_packet.py +655 -0
  172. package/skills/plan-to-pr/scripts/validate_protocol.py +622 -0
  173. package/skills/plan-to-pr/scripts/validate_run.py +173 -0
  174. package/skills/plan-to-pr/test_skill_contract.py +207 -0
  175. package/skills/plan-to-pr/test_task_ticket_contract.py +151 -0
  176. package/skills/pr-converge/SKILL.md +472 -469
  177. package/skills/pr-converge/reference/examples.md +3 -3
  178. package/skills/pr-converge/reference/fix-protocol.md +1 -1
  179. package/skills/pr-converge/reference/ground-rules.md +7 -4
  180. package/skills/pr-converge/reference/multi-pr-orchestration.md +4 -1
  181. package/skills/pr-converge/reference/per-tick.md +5 -5
  182. package/skills/pr-converge/reference/progress-checklist.md +1 -1
  183. package/skills/pr-converge/scripts/check_convergence_gates.py +279 -279
  184. package/skills/pr-converge/scripts/test_check_convergence_codex.py +507 -507
  185. package/skills/pr-converge/scripts/test_check_convergence_gates.py +84 -84
  186. package/skills/pr-converge/test_step5_host_branch.py +1 -1
  187. package/skills/pr-fix-protocol/SKILL.md +1 -1
  188. package/skills/privacy-hygiene/SKILL.md +68 -68
  189. package/skills/prototype/workflows/promotion.md +1 -1
  190. package/skills/release-notes-html/SKILL.md +164 -0
  191. package/skills/task-build/CLAUDE.md +8 -7
  192. package/skills/task-build/SKILL.md +16 -8
  193. package/skills/task-build/reference/tool-routing.md +19 -0
  194. package/scripts/test_invoke_code_review.py +0 -966
  195. package/skills/closeout/reference/issue-body-templates.md +0 -108
@@ -0,0 +1,41 @@
1
+ # Operation matrix
2
+
3
+ Each issue op maps to a GitHub MCP tool and a `gh` fallback that reaches the same REST endpoint. Prefer the MCP tool; fall back to `gh` when the MCP server is unreachable. The REST endpoint column names the authoritative contract both surfaces call, so a session with neither surface can still drive the raw API.
4
+
5
+ The MCP tool names below match the connected GitHub MCP server's issue toolset. When a server exposes a tool under a different name, pick the tool by what the row describes, and the REST endpoint tells you what it must call.
6
+
7
+ | Operation | GitHub MCP tool | REST endpoint | `gh` fallback |
8
+ |-----------|-----------------|---------------|---------------|
9
+ | Search open + closed | `mcp__github__search_issues` | `GET /search/issues?q=<terms>+repo:{owner}/{repo}` | `gh issue list --search "<terms>" --state all` |
10
+ | Create epic / sub-issue | `mcp__github__issue_write` (create) | `POST /repos/{owner}/{repo}/issues` | `gh issue create --title "<t>" --body-file <path> --label <label>` |
11
+ | Read issue body | `mcp__github__issue_read` | `GET /repos/{owner}/{repo}/issues/{number}` | `gh issue view <number> --json body` |
12
+ | Update body / labels | `mcp__github__issue_write` (update) | `PATCH /repos/{owner}/{repo}/issues/{number}` | `gh issue edit <number> --body-file <path> --add-label <label>` |
13
+ | Attach native sub-issue | `mcp__github__sub_issue_write` | `POST /repos/{owner}/{repo}/issues/{number}/sub_issues` | `gh api repos/{owner}/{repo}/issues/{number}/sub_issues -F sub_issue_id=<int>` |
14
+ | Add cross-reference comment | `mcp__github__add_issue_comment` | `POST /repos/{owner}/{repo}/issues/{number}/comments` | `gh issue comment <number> --body-file <path>` |
15
+ | Create label | `mcp__github__` label-create tool | `POST /repos/{owner}/{repo}/labels` | `gh label create <name> --color <hex> --description "<text>"` |
16
+
17
+ ## The sub-issue `.id` rule (read this before every attach)
18
+
19
+ The sub-issues endpoint identifies the child by its REST **database `.id`** — a large integer such as `2138472019` — not by its display number (`#42`). The two are different values. Passing the display number attaches nothing.
20
+
21
+ Read the child's `.id` from the create op's response, or fetch it:
22
+
23
+ ```
24
+ gh api repos/{owner}/{repo}/issues/{number} --jq .id
25
+ ```
26
+
27
+ `gh issue view <number> --json id` returns the GraphQL node id, a base64 string — the wrong value for this endpoint. Use `gh api ... --jq .id` for the REST database id.
28
+
29
+ The gh attach uses `-F` (typed field), which sends the id as a JSON integer. `-f` sends a string, and the endpoint rejects a string sub-issue id.
30
+
31
+ ```
32
+ gh api repos/{owner}/{repo}/issues/{parent}/sub_issues -F sub_issue_id=2138472019
33
+ ```
34
+
35
+ ## Body content through `--body-file`
36
+
37
+ Every `gh issue create`, `gh issue edit`, and `gh issue comment` passes body content with `--body-file <path>`, never `--body "<text>"`. A `--body` string mangles backticks on GitHub — they land as literal `\``. Write the body to a temp file and point `--body-file` at it.
38
+
39
+ ## Paginated reads
40
+
41
+ `gh issue list` needs no pagination flags. For a `gh api` read of a paginated list endpoint (an issue's comments, a repository's issues), pass `--paginate --slurp` and pipe to external `jq` — `gh`'s built-in `--jq` runs per page and gives wrong cross-page results.
@@ -30,15 +30,87 @@ The moment it edits a file or runs a test itself, the pairing breaks —
30
30
  its own tool use stays orchestration, run-artifact writes, and light
31
31
  verification reads.
32
32
 
33
+ ## status_gate (deterministic — not optional)
34
+
35
+ **Prose does not keep the loop alive.** Re-arm and terminate are gated by
36
+ `scripts/status_gate.py` (and, on Claude, the PreToolUse hook
37
+ `orchestrator_refresh_reschedule_gate`). The gate is host-agnostic: a
38
+ single pending re-arm latch in the status file, not host product names.
39
+
40
+ ```
41
+ python scripts/status_gate.py set --status active|done [--run-slug SLUG] [--status-file PATH]
42
+ python scripts/status_gate.py begin-firing [--run-slug SLUG] [--status-file PATH]
43
+ python scripts/status_gate.py should-reschedule [--run-slug SLUG] [--status-file PATH]
44
+ python scripts/status_gate.py claim-rearm [--run-slug SLUG] [--status-file PATH]
45
+ python scripts/status_gate.py release-rearm [--run-slug SLUG] [--status-file PATH]
46
+ ```
47
+
48
+ | Exit / output | Meaning |
49
+ |---|---|
50
+ | `set` → 0 | Status written (`active`/`done`); `done` clears latch; re-asserting `active` preserves it |
51
+ | `begin-firing` → 0 | Active; clears `rearm_pending` (start of a refresh firing) |
52
+ | `begin-firing` → 1 | Stop — missing/invalid/done (fail closed) |
53
+ | `should-reschedule` → 0 | Active and `rearm_pending` is false (read-only) |
54
+ | `should-reschedule` → 1 | Stop — inactive, missing, invalid, or slot already pending |
55
+ | `claim-rearm` → 0 | Slot latched (`rearm_pending` true) after a successful create |
56
+ | `claim-rearm` → 1 | Slot already pending or inactive — cancel any just-created schedule |
57
+ | `release-rearm` → 0 | Cleared pending (recovery if a latch stuck after create) |
58
+ | `release-rearm` → 1 | Stop — missing/invalid/done; nothing to release |
59
+
60
+ Default status path: `.orchestrator-run-status.json` under the repo plans
61
+ directory, or `$ORCHESTRATOR_RUN_STATUS_FILE`. With `--run-slug SLUG`,
62
+ under the slug plans subdirectory. When using a slug, every refresh
63
+ schedule prompt must carry it: `/orchestrator-refresh --run-slug SLUG`.
64
+
65
+ ### Single-pending re-arm protocol (all hosts)
66
+
67
+ Exactly one delayed refresh may be outstanding. **Create then claim**
68
+ (order matters on Claude: PreToolUse denies `ScheduleWakeup` when the
69
+ slot is already pending).
70
+
71
+ 1. **Cancel matching schedules** only when the host can list and cancel
72
+ schedules by prompt. Drop every schedule whose prompt targets
73
+ `/orchestrator-refresh` (and the same `--run-slug` when used).
74
+ Replace, never stack. On Claude, there is no selective cancel for a
75
+ sibling `ScheduleWakeup` — the status-file latch
76
+ (`should-reschedule` / `claim-rearm`) is the sole stacking
77
+ enforcement there.
78
+ 2. **`should-reschedule`** (same path args as activate). Exit 1 → stop;
79
+ do not create. Exit 0 → continue.
80
+ 3. **Create exactly one non-recurring delayed wake** (~1200–2700s) with
81
+ prompt `/orchestrator-refresh` (plus `--run-slug` when used). Use the
82
+ host's one-shot delayed schedule tool (on Claude: `ScheduleWakeup`).
83
+ Never recurring, never cadence, never a second create in the same
84
+ firing.
85
+ 4. **`claim-rearm`** immediately after a successful create. Exit 0 →
86
+ done. Exit 1 → cancel the schedule just created and stop (race /
87
+ already latched).
88
+ 5. **On create failure:** do not claim; stop or retry once from step 1.
89
+
90
+ On Claude, the PreToolUse hook also denies when inactive, already
91
+ pending, or when the tool is `CronCreate`.
92
+
93
+ **Rules:**
94
+
95
+ - **Activate only with open work.** After the first ledger task exists,
96
+ `set --status active` (same `--run-slug` for the whole run if used).
97
+ - **Done is a script.** When every ledger task is completed/cancelled and
98
+ no executor is running: `set --status done`, cancel matching host
99
+ schedules, stop. Do not re-arm.
100
+ - **Invocation guard.** If `should-reschedule` is already exit 1 for
101
+ `rearm_already_pending`, a refresh is already queued — do not arm again.
102
+
33
103
  ## Process
34
104
 
35
- 1. **Invocation guard.** One `/orchestrator` per session. When the
36
- refresh loop is already running, do not schedule a second one; reuse
37
- the live advisor bind and go to step 4.
38
- 2. **Register the discipline reminder.** Schedule it with
39
- `ScheduleWakeup` at `delaySeconds: 2700`, prompt
40
- `/orchestrator-refresh`, where each refresh re-schedules the next one.
41
- 3. **Bind the shared advisor before any executor.** Follow
105
+ 1. **Invocation guard.** One `/orchestrator` per session. When a refresh
106
+ one-shot is already queued (`should-reschedule` exits 1 with
107
+ `rearm_already_pending`), do not stack a second: reuse the live
108
+ advisor bind and go to step 6 (Orchestrate). Skip steps 4–5 — status
109
+ is already active and a re-arm is already latched; re-registering
110
+ would attempt a redundant host schedule. (Re-asserting
111
+ `set --status active` preserves `rearm_pending` when already active,
112
+ but still do not run step 5.)
113
+ 2. **Bind the shared advisor before any executor.** Follow
42
114
  [`_shared/advisor/advisor-protocol.md`](../../_shared/advisor/advisor-protocol.md)
43
115
  end to end: detect the host profile, compute the floor from the
44
116
  orchestrator consumer set — this session plus every tier in the
@@ -48,16 +120,25 @@ verification reads.
48
120
  message the warm agent or report here, and an executor that finds the
49
121
  advisor unreachable reports that upward — it never spawns a
50
122
  replacement itself.
51
- 4. **Write the run artifacts** (next section) before the first spawn.
52
- 5. **Orchestrate.** Hold the plan and the user conversation. Spawn each
123
+ 3. **Write the run artifacts** (next section) before the first spawn.
124
+ 4. **Activate status_gate** when the first open ledger task exists:
125
+ `python scripts/status_gate.py set --status active`.
126
+ 5. **Register the discipline reminder** via the single-pending re-arm
127
+ protocol (cancel matching → `should-reschedule` → one non-recurring
128
+ delayed wake → `claim-rearm`; default delay about 2700s).
129
+ 6. **Orchestrate.** Hold the plan and the user conversation. Spawn each
53
130
  task with a ticket (Spawn ticket section), keep driving while
54
131
  executors work, and keep the ledger reconciled (Task ledger
55
132
  discipline).
56
- 6. **Consult the advisor at hard decisions.** The trigger list, consult
133
+ 7. **Consult the advisor at hard decisions.** The trigger list, consult
57
134
  format, and reply handling live in the protocol's "Consulting the
58
135
  warm agent" section; both this session and every executor are
59
136
  consumers. Replies open with one of ENDORSE, CORRECTION, PLAN, or
60
137
  STOP — `agents/session-advisor.md` defines each signal.
138
+ 8. **Terminate when done.** When every ledger task is completed or
139
+ cancelled and no executor is running: run
140
+ `set --status done`, cancel matching host schedules, report
141
+ completion, and stop. Do not re-arm.
61
142
 
62
143
  ## Run state lives in artifacts
63
144
 
@@ -76,6 +157,9 @@ in the repo the run works on (working files, not committed):
76
157
  may write — and its reply is thin: status, artifact paths, blockers.
77
158
  The orchestrating session records each result into the run's result
78
159
  files as it reconciles the ledger.
160
+ - **Run status file** — written only by `status_gate.py`
161
+ (`active` / `done`, plus `rearm_pending`). Source of truth for
162
+ reschedule and the single-pending latch.
79
163
 
80
164
  Correctness never rides on any agent's private context: when an executor
81
165
  dies or hangs, point a fresh spawn at the same assignment file plus its
@@ -101,6 +185,18 @@ Return: status, artifact paths, blockers — nothing else.
101
185
  fit gets split in the plan — never padded into a longer prompt.
102
186
  Explore fan-outs run tiny; a `clean-coder` assignment can carry a
103
187
  whole scoped feature.
188
+ - **Focused tickets are the house convention.** One mechanical done-check
189
+ per ticket; thick context lives in the assignment file, not the ticket
190
+ prose. The orchestrator owns splitting a big task into tickets and
191
+ synthesizing the results — an executor never does either. Two
192
+ anti-patterns to avoid: an epic ticket that bundles several
193
+ deliverables behind one done-check, and micro-thrash — a run of tickets
194
+ so thin each spawn pays more in setup than the work itself takes. See
195
+ Anthropic's coordinator-pattern cookbook:
196
+ https://github.com/anthropics/claude-cookbooks/blob/main/managed_agents/CMA_plan_big_execute_small.ipynb.
197
+ - **Resume with a thin next-slice ticket.** A warm agent already holds
198
+ the assignment's thick context, so its next ticket names only the next
199
+ slice of work and the done-check — it does not restate the assignment.
104
200
  - **Do not restate what the agent definition carries.** The routing
105
201
  table picks the definition, and `clean-coder` already holds the code
106
202
  discipline. The ticket adds the task, the pointers, and the Advisor
@@ -117,19 +213,38 @@ workflow resume is available.
117
213
 
118
214
  | Work | Agent type | Model |
119
215
  |---|---|---|
120
- | Feature, bug, and refactor coding | `clean-coder` | `opus` |
121
- | Verification passes | `code-verifier` | `sonnet` |
122
- | Script runs, GitHub posting, and backfill driving | `general-purpose` runner | `sonnet` |
216
+ | Feature, bug, and refactor coding | `clean-coder` | `sonnet` on a Claude host; the sonnet-equivalent id the worker-model resolver prints on a third-party host |
217
+ | Verification passes | `code-verifier` | `sonnet` on a Claude host; the sonnet-equivalent id the worker-model resolver prints on a third-party host |
218
+ | Script runs, GitHub posting, and backfill driving | `general-purpose` runner | `sonnet` on a Claude host; the sonnet-equivalent id the worker-model resolver prints on a third-party host |
123
219
  | PR descriptions | `pr-description-writer` | `haiku`, with file-list grounding check |
124
220
  | Fan-out searches and checklist verification reads | `Explore` | `haiku`; use `sonnet` when judgment-heavy |
125
221
 
222
+ Every row that edits code, runs a build, or runs a test is a coding row.
223
+ The per-spawn Agent call's `model:` field carries the routing.
224
+ `CLAUDE_CODE_SUBAGENT_MODEL` and other environment variables do not set
225
+ the worker model; the per-spawn `model:` field does.
226
+
126
227
  Routing rules:
127
228
 
128
229
  - Each row spawns workflow-backed with a ticket; the routing row and the
129
230
  ticket together carry the agent type, model, task, and return
130
- contract. A task category that maps to `clean-coder` on `opus` is not
131
- served by a `general-purpose` Sonnet spawn — the table is the
132
- contract, not a cost suggestion.
231
+ contract. A coding task category is never served by a different tier
232
+ as a cost call — the table is the contract.
233
+ - **Fail closed on a Claude host.** When `sonnet` cannot be spawned, use
234
+ the Claude chain failover for `sonnet` when the session has one
235
+ configured; otherwise stop the coding spawn and report the failure —
236
+ never fall back in silence to `opus` or the session's own model.
237
+ - **Fail closed on a third-party host.** Before each coding spawn, the
238
+ orchestrator runs a deterministic worker-model resolver that prints
239
+ the sonnet-equivalent model id for that host. A non-zero exit stops
240
+ the coding spawn; the orchestrator reports the failure rather than
241
+ picking a model itself. This section states the resolver's contract
242
+ only; a host where no resolver is available fails closed the same
243
+ way — the coding spawn stops and the orchestrator reports it.
244
+ - Host detection follows
245
+ [`_shared/advisor/advisor-protocol.md`](../../_shared/advisor/advisor-protocol.md)
246
+ (Host profiles section, `detect_host_profile`) — the sole detection
247
+ system, with no second one.
133
248
  - Resume a warm workflow agent before creating a new workflow run when
134
249
  the warm agent holds the relevant context.
135
250
  - `clean-coder` owns code edits. `code-verifier` owns verification. The
@@ -175,12 +290,16 @@ the live agents at any moment. Four invariants hold at all times:
175
290
  `blockedBy` links, updated the moment the plan changes.
176
291
 
177
292
  Reconcile on every state change (spawn, completion notification, plan
178
- change) and on every `/orchestrator-refresh` firing.
293
+ change) and on every `/orchestrator-refresh` firing. After reconcile, if
294
+ no open work remains, run `set --status done` before any re-arm attempt.
179
295
 
180
296
  ## Constraints
181
297
 
182
298
  - One `/orchestrator` per session; the invocation guard blocks a second
183
- reminder loop.
299
+ stacked one-shot while one is already queued.
300
+ - Reschedule is mechanical: status file + `claim-rearm` /
301
+ `should-reschedule` exit codes; never a recurring host schedule; at
302
+ most one pending re-arm latch.
184
303
  - The orchestrating session never edits code or runs a build or test
185
304
  itself — executors do that. Its own tool use stays orchestration,
186
305
  run-artifact writes, and light verification reads.
@@ -189,14 +308,36 @@ change) and on every `/orchestrator-refresh` firing.
189
308
  - One shared advisor per orchestrated session, owned by this session per
190
309
  the protocol; executors never spawn, respawn, or shut it down.
191
310
 
311
+ ## Gotchas
312
+
313
+ - **Stacking re-arms.** Creating a second delayed wake while one is
314
+ already queued (or using a recurring host schedule) multiplies loops
315
+ on each refresh. Always cancel matching → `should-reschedule` → one
316
+ create → `claim-rearm`. A second create while pending is denied on
317
+ Claude by PreToolUse; elsewhere `should-reschedule` / `claim-rearm`
318
+ exit 1 is a hard stop.
319
+ - **Claim before create on Claude.** If you `claim-rearm` first, the
320
+ PreToolUse hook sees `rearm_pending` and denies `ScheduleWakeup`.
321
+ Create first, then claim.
322
+ - **Forgetting `begin-firing` on refresh.** The latch stays pending;
323
+ later re-arms are denied forever until a firing clears it. Refresh
324
+ must run `begin-firing` first.
325
+ - **Create without claim.** If create succeeds and you skip
326
+ `claim-rearm`, a second create can stack. Always claim immediately
327
+ after a successful create.
328
+
192
329
  ## File Index
193
330
 
194
331
  | File | Purpose |
195
332
  |---|---|
196
- | `SKILL.md` | Orchestrator strategy: design rule, process, run artifacts, spawn ticket, routing table, reuse rules, ledger invariants, constraints. |
333
+ | `SKILL.md` | Orchestrator strategy; pointers to run-control scripts. |
334
+ | `scripts/status_gate.py` | Status file, latch, and re-arm gate (exit codes). |
335
+ | `scripts/status_gate_constants/config/constants.py` | Named constants for status_gate. |
336
+ | `scripts/test_status_gate.py` | Gate tests. |
197
337
 
198
338
  ## Folder Map
199
339
 
200
- - `SKILL.md` — complete orchestrator workflow instructions. Advisor
201
- policy lives in
340
+ - `SKILL.md` — orchestration process and routing.
341
+ - `scripts/` — deterministic status_gate.
342
+ - Advisor policy:
202
343
  [`_shared/advisor/advisor-protocol.md`](../../_shared/advisor/advisor-protocol.md).