riskrails 3.0.0 → 3.0.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 (81) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.codex-plugin/plugin.json +2 -2
  4. package/README.md +246 -812
  5. package/agents/ai-reviewer.md.tmpl +6 -4
  6. package/ai/policies/review-economy.md +7 -2
  7. package/ai/using-riskrails.md +15 -0
  8. package/bin/claude-1m +15 -14
  9. package/bin/riskrails.js +108 -32
  10. package/codex/hooks.json +25 -2
  11. package/hooks/AGENTS.md +2 -2
  12. package/hooks/CLAUDE.md +2 -2
  13. package/hooks/ai-guard.py +29 -8
  14. package/hooks/ai-path-guard-defaults.json +3 -1
  15. package/hooks/codex-hooks.json +25 -2
  16. package/hooks/context-guard.py +251 -35
  17. package/hooks/dialog-gate.py +105 -0
  18. package/hooks/guard/common.py +5 -0
  19. package/hooks/guard/decision.py +123 -0
  20. package/hooks/guard/dialog.py +598 -0
  21. package/hooks/guard/git.py +49 -3
  22. package/hooks/guard/paths.py +62 -3
  23. package/hooks/hooks.json +37 -2
  24. package/hooks/memory-pre-push.py +28 -0
  25. package/hooks/runtime-gate.py +59 -12
  26. package/hooks/update_notice.py +135 -0
  27. package/instructions/routing.md +4 -4
  28. package/instructions/stub.md +2 -2
  29. package/package.json +1 -1
  30. package/profiles/max.json +3 -1
  31. package/profiles/pro.json +3 -1
  32. package/scripts/merge-codex-config.py +134 -0
  33. package/scripts/resolve-profile.py +15 -3
  34. package/settings.common.json +39 -2
  35. package/skills/AGENTS.md +2 -2
  36. package/skills/CLAUDE.md +2 -2
  37. package/skills/ai-init/templates/.ai/AGENTS.md +2 -2
  38. package/skills/ai-init/templates/.ai/VERSION +1 -1
  39. package/skills/ai-init/templates/.ai/policies/dialog.json +1 -0
  40. package/skills/ai-init/templates/.ai/policies/safety.md +22 -2
  41. package/skills/ai-init/templates/.ai/policies/weight.json +1 -0
  42. package/skills/ai-init/templates/.ai/policies/weight.md +2 -2
  43. package/skills/ai-init/templates/.ai/state/README.md +9 -6
  44. package/skills/ai-init/templates/AGENTS.block.md +1 -1
  45. package/skills/ai-init/templates/CLAUDE.block.md +1 -1
  46. package/skills/ai-init/templates/GEMINI.block.md +1 -1
  47. package/skills/ai-init/templates/junie-guidelines.block.md +1 -1
  48. package/skills/ai-task/memory_compact.py +968 -0
  49. package/skills/ai-task/memory_format.py +775 -0
  50. package/skills/ai-task/memory_store.py +528 -0
  51. package/skills/ai-task/memory_sync.py +1571 -0
  52. package/skills/ai-task/sensors.py +2 -2
  53. package/skills/ai-task/state.py +967 -70
  54. package/skills/ai-task/weight.py +3 -3
  55. package/skills/project-init/templates/constitution.md +1 -1
  56. package/skills/project-update/history/blobs/164cd34c182de88c33de7df35beb29200d792419e1c13a5f0b2104f944e57be7 +1 -0
  57. package/skills/project-update/history/blobs/1d1d907449ec74594d0ee923ac142ae746b9aedf0a1eda9469f075a44d23e3d7 +13 -0
  58. package/skills/project-update/history/blobs/23a42febbacaa7b52a802d428033a99c0694391c81d51fe3b6e1dff608a641d5 +67 -0
  59. package/skills/project-update/history/blobs/5353ca529c46f2443e12947ec205a6887fb594a4de1f87f0eb1c0e6c0f826133 +49 -0
  60. package/skills/project-update/history/blobs/5f65bc7ab3fc3c4e75ae05d49eaf4331fafc398c661abe33c69f7380a720344c +32 -0
  61. package/skills/project-update/history/blobs/7be527cd648b27cca6e267de30f8e33a2ce17d5631a82694f23ae5c0623efe1f +15 -0
  62. package/skills/project-update/history/blobs/7ee99edafe7cec45ff577376c0d0178fdb2690134d4656488f46e129aba3cc5a +67 -0
  63. package/skills/project-update/history/blobs/8b3ef9586491a426767c01da5d01bdd6b0655c576c68c4cc6dfb093367817dc0 +67 -0
  64. package/skills/project-update/history/blobs/917df3320d778ddbaa5c5c7742bc4046bf803c36ed2b050f30844ed206783469 +1 -0
  65. package/skills/project-update/history/blobs/935af1019931058ec3a0b834fe230e127ec914f75edcc4a6c589cfe733b0b979 +13 -0
  66. package/skills/project-update/history/blobs/ae5ce131d6bae401199ff32d8c3dc4d8aec188010a9111624ac64506e2116ff4 +84 -0
  67. package/skills/project-update/history/blobs/ca4499d829268c8766fb3b825a515e88dc55c237e9d202816b50959b4dac031f +13 -0
  68. package/skills/project-update/history/blobs/e9adb7a9905eb719ac78ab96671f055da53e5001810f5ad6d6c94306b0323fe7 +74 -0
  69. package/skills/project-update/history/blobs/fae3064e648cdc55be4aeb1177525b302a5e34ebd752e4a904f47dc0f4557b96 +71 -0
  70. package/skills/project-update/history/index.json +32 -13
  71. package/skills/project-update/migrations/0009_state_file.py +25 -0
  72. package/skills/project-update/migrations/0010_dialog_switch.py +30 -0
  73. package/skills/project-update/migrations/README.md +2 -1
  74. package/skills/project-update/update.py +12 -3
  75. package/skills/rr-build/SKILL.md +14 -5
  76. package/skills/rr-build-all/SKILL.md +190 -0
  77. package/skills/rr-plan/SKILL.md +13 -3
  78. package/skills/rr-review/SKILL.md +18 -8
  79. package/skills/rr-ship/SKILL.md +16 -8
  80. package/skills/rr-status/SKILL.md +2 -2
  81. package/skills/usage-report/usage-report.py +41 -8
@@ -9,7 +9,8 @@
9
9
  "31bb922076c8dadb4a84bb6a03d331dafc7157893aaf2f92b13792270fbece9b",
10
10
  "a13cb0db5372c3ce3e71470165c17a2db76e7a2415717ba27fccd1b0593c61c4",
11
11
  "54eefe3d8cd6cd1ed56764e7bd412a4c919a28fc64b56b69dcafeecd7a921678",
12
- "fe513647c66e8883b326ea884a7e9cb045ce54c49b03d2e75a0b73c4756c423e"
12
+ "fe513647c66e8883b326ea884a7e9cb045ce54c49b03d2e75a0b73c4756c423e",
13
+ "8b3ef9586491a426767c01da5d01bdd6b0655c576c68c4cc6dfb093367817dc0"
13
14
  ],
14
15
  "ai-init/.ai/VERSION": [
15
16
  "4355a46b19d348dc2f57c046f8ef63d4538ebb936000f3c9ee954a27460dd865",
@@ -19,7 +20,8 @@
19
20
  "f0b5c2c2211c8d67ed15e75e656c7862d086e9245420892a7de62cd9ec582a06",
20
21
  "06e9d52c1720fca412803e3b07c4b228ff113e303f4c7ab94665319d832bbfb7",
21
22
  "10159baf262b43a92d95db59dae1f72c645127301661e0a3ce4e38b295a97c58",
22
- "aa67a169b0bba217aa0aa88a65346920c84c42447c36ba5f7ea65f422c1fe5d8"
23
+ "aa67a169b0bba217aa0aa88a65346920c84c42447c36ba5f7ea65f422c1fe5d8",
24
+ "917df3320d778ddbaa5c5c7742bc4046bf803c36ed2b050f30844ed206783469"
23
25
  ],
24
26
  "ai-init/.ai/agents/context.md": [
25
27
  "a213099429aff491b00e885c8d556465be2405072efbb9a3a297890a15a5b4ca",
@@ -87,6 +89,9 @@
87
89
  "ai-init/.ai/policies/database.md": [
88
90
  "894a37936b769203bbb880ff842cc0a04e62d53e01deb07af83179f6b1359cf4"
89
91
  ],
92
+ "ai-init/.ai/policies/dialog.json": [
93
+ "164cd34c182de88c33de7df35beb29200d792419e1c13a5f0b2104f944e57be7"
94
+ ],
90
95
  "ai-init/.ai/policies/git.md": [
91
96
  "6bbcb8ea55726cdd49e0544725d224ac6d728cd1db757a269399342da92677ca"
92
97
  ],
@@ -119,7 +124,8 @@
119
124
  "9984ac1e1b1edb7217df58e256002ae09913fdc598da6f7773f1c01e5a3e55e2",
120
125
  "c392fd585241389355958099a95bd85358a80d9a10310301a430219f83c8962e",
121
126
  "edecd502e22395300781a3c653b56c3587b1b894ce4b96f60e19c601a5cdae46",
122
- "91e924527f51c8c36fa1156a8f30af4c07adab2d324b8c5a879145a1641c413a"
127
+ "91e924527f51c8c36fa1156a8f30af4c07adab2d324b8c5a879145a1641c413a",
128
+ "6a3f34706c31fc91fdace8ea8729bd7a74065f983032204f5aad3ec80cf13ce0"
123
129
  ],
124
130
  "ai-init/.ai/policies/risk-tiers.json": [
125
131
  "01c32f8ff038787e49070b8b0eb160eb4b4704a020b050678292051fc73a4fc6",
@@ -154,7 +160,10 @@
154
160
  ],
155
161
  "ai-init/.ai/policies/safety.md": [
156
162
  "0f00cbb216a20c7f67749ffb88835bcaaa29cc1a4c15d468edb3c6039bd291d3",
157
- "ae9a22907ba9acbb7e80fac1ba4e3d1ff09e5f1df5c4456afb9099d7090fcaa6"
163
+ "ae9a22907ba9acbb7e80fac1ba4e3d1ff09e5f1df5c4456afb9099d7090fcaa6",
164
+ "fae3064e648cdc55be4aeb1177525b302a5e34ebd752e4a904f47dc0f4557b96",
165
+ "e9adb7a9905eb719ac78ab96671f055da53e5001810f5ad6d6c94306b0323fe7",
166
+ "ae5ce131d6bae401199ff32d8c3dc4d8aec188010a9111624ac64506e2116ff4"
158
167
  ],
159
168
  "ai-init/.ai/policies/security.md": [
160
169
  "cc808d5b940109f1703abfb3ca0334a3fcfd34267feefb2323627d0decc8b89a",
@@ -175,10 +184,12 @@
175
184
  "2c6afb3518714d35eaf0119bf2ae2154782bbece632dfdbd68988351abde61f5"
176
185
  ],
177
186
  "ai-init/.ai/policies/weight.json": [
178
- "7f3859c34035fe32abf937eebdd7240ac72ab32d254286cff7d939cf0cf6eaef"
187
+ "7f3859c34035fe32abf937eebdd7240ac72ab32d254286cff7d939cf0cf6eaef",
188
+ "5353ca529c46f2443e12947ec205a6887fb594a4de1f87f0eb1c0e6c0f826133"
179
189
  ],
180
190
  "ai-init/.ai/policies/weight.md": [
181
- "e639e99d3f59015dc21472de081ca7766231135399ac3a6f439e841e458251f4"
191
+ "e639e99d3f59015dc21472de081ca7766231135399ac3a6f439e841e458251f4",
192
+ "5f65bc7ab3fc3c4e75ae05d49eaf4331fafc398c661abe33c69f7380a720344c"
182
193
  ],
183
194
  "ai-init/.ai/project/architecture.md": [
184
195
  "5cbaaabe2c8d0e24582877aab05eeaaf4d53cb5e9515e81cd18368d13d2fe79e"
@@ -222,7 +233,9 @@
222
233
  "962fd396da83337c3fadcc642d45e98429b18e79bb81f58915baaf2b9bffd3c5",
223
234
  "d7b96902bf9d2078df1e09901327b02f565b174777af34a2b24be660cad81d01",
224
235
  "ad4c4f81855725f7fe6e0e3d8f557df0de5fc063465d428546f69c54020c69d9",
225
- "19b1a6390e96136619d23bc2ef9afed8f15e62107de7c1052bc5ea23e5bb5692"
236
+ "19b1a6390e96136619d23bc2ef9afed8f15e62107de7c1052bc5ea23e5bb5692",
237
+ "23a42febbacaa7b52a802d428033a99c0694391c81d51fe3b6e1dff608a641d5",
238
+ "7ee99edafe7cec45ff577376c0d0178fdb2690134d4656488f46e129aba3cc5a"
226
239
  ],
227
240
  "ai-init/.ai/templates/architecture-decision.md": [
228
241
  "78619b522826ba8f5f0422e9deb7359c8002553d1aeb29a3719da5ab11ff13a1"
@@ -246,7 +259,8 @@
246
259
  "515df0eab178b5f53b50f95bec2671e861efef35b487a6e65d80e80de42c4d0d"
247
260
  ],
248
261
  "ai-init/.ai/using-riskrails.md": [
249
- "03282999978b2bfb5f65135e1884f9447f8a71021a88895d5436d377797b9acb"
262
+ "03282999978b2bfb5f65135e1884f9447f8a71021a88895d5436d377797b9acb",
263
+ "25d08ff01a4ab2069b0dd4e5ec52e888d33e00091dc467dd10d63f10223b6f80"
250
264
  ],
251
265
  "ai-init/.ai/workflows.md": [
252
266
  "500d93714106b1c4e21b13f248f7175c86073a9bcb6e0a849845f61f49b5a66d"
@@ -310,7 +324,8 @@
310
324
  "815d78ce95d18454cf0842335f81755bf3aceb87ee9d2197e121d3ff734cd2b5",
311
325
  "de0685f9bc2ac22c1b0178d6a1fc8d07fa23451f29d0c36571cbf85c69716fc2",
312
326
  "c735911eb1a744f78213a9f7577b425c1605843f6d05fed798d7f41b47fa1e0c",
313
- "7eee4ea9f6e778ff691c263621e717c021505b86386034cc64f8ebbfc9d8fe65"
327
+ "7eee4ea9f6e778ff691c263621e717c021505b86386034cc64f8ebbfc9d8fe65",
328
+ "ca4499d829268c8766fb3b825a515e88dc55c237e9d202816b50959b4dac031f"
314
329
  ],
315
330
  "ai-init/AGENTS.minimal.md": [
316
331
  "b7b697fc987617449ba10634f12f70326281cc182f8b7f20f9e047a75f3f182b",
@@ -324,7 +339,8 @@
324
339
  "3775eed295a794dda73b14f88af70bc2c99b5590f81da53f165423e4337dceed",
325
340
  "ee7c8321fff228d967c5d200c316967195d93a26196383f57f474e837b1b3d33",
326
341
  "da848b831443484c831fa630666c004e07c1c9669dd247e8e4066979c8599080",
327
- "c076d603cffc731823d2acf096bcc17cca1d99eee24b0aa313776d7d01571b4f"
342
+ "c076d603cffc731823d2acf096bcc17cca1d99eee24b0aa313776d7d01571b4f",
343
+ "1d1d907449ec74594d0ee923ac142ae746b9aedf0a1eda9469f075a44d23e3d7"
328
344
  ],
329
345
  "ai-init/CLAUDE.minimal.md": [
330
346
  "7578025c0ce0a64dd37fe4c999541db5681199763df8b373ed0bfba11e2f581e",
@@ -335,7 +351,8 @@
335
351
  "e8df28f07cb784d768bcafbced70fd15771afa61dbec7dc4c1c3f858f9002fec",
336
352
  "c9ddacab2a6943af94c927799ba314877c1f19d40949e927c2d3825689005288",
337
353
  "4d1f9073276936834747199393159f1badc0277b5bb394f78f408d52c36c4e35",
338
- "65acd4be95c695d0cc20cb5f4faffe0f44e0873b385c124140b223c41328cb56"
354
+ "65acd4be95c695d0cc20cb5f4faffe0f44e0873b385c124140b223c41328cb56",
355
+ "935af1019931058ec3a0b834fe230e127ec914f75edcc4a6c589cfe733b0b979"
339
356
  ],
340
357
  "ai-init/GEMINI.minimal.md": [
341
358
  "933629cd5c872a11837046b13051a9b02bbc1033e3ba74f41966af2ed4edee5d"
@@ -348,7 +365,8 @@
348
365
  "e8df28f07cb784d768bcafbced70fd15771afa61dbec7dc4c1c3f858f9002fec",
349
366
  "c9ddacab2a6943af94c927799ba314877c1f19d40949e927c2d3825689005288",
350
367
  "4d1f9073276936834747199393159f1badc0277b5bb394f78f408d52c36c4e35",
351
- "65acd4be95c695d0cc20cb5f4faffe0f44e0873b385c124140b223c41328cb56"
368
+ "65acd4be95c695d0cc20cb5f4faffe0f44e0873b385c124140b223c41328cb56",
369
+ "935af1019931058ec3a0b834fe230e127ec914f75edcc4a6c589cfe733b0b979"
352
370
  ],
353
371
  "ai-init/junie-guidelines.minimal.md": [
354
372
  "5551499579a0bceb74a79731d30213b1ddf9168b92f6d3dd0aecad91d8aff464"
@@ -371,7 +389,8 @@
371
389
  "a349aaad234825ea429df33cafb7928579c0cb5b1801f0a237e103aa8d159642"
372
390
  ],
373
391
  "project-init/constitution.md": [
374
- "5e38d93c4f82300cc5d331f4ce3022d2872db15d108ae23bf33e2169a19b42f2"
392
+ "5e38d93c4f82300cc5d331f4ce3022d2872db15d108ae23bf33e2169a19b42f2",
393
+ "7be527cd648b27cca6e267de30f8e33a2ce17d5631a82694f23ae5c0623efe1f"
375
394
  ],
376
395
  "project-init/gitignore.snippet": [
377
396
  "965a03be82000866cb5275acda18ebb2172c9a50f0011df2fa475f74a1124c35",
@@ -0,0 +1,25 @@
1
+ """0009: the task's state file is `.ai/state/state.json`.
2
+
3
+ R34's contract half. 0008 shipped the expand half: the guards and state.py of
4
+ 3.4b read `.ai/state/state.json` first and `current.json` otherwise, and write
5
+ the file where it is. This migration, run once such a version is installed,
6
+ moves a task in flight from `current.json` to `state.json`, and `state.py start`
7
+ opens every new task in `state.json`.
8
+
9
+ * The move goes through MOVES like any other: no task in flight means no
10
+ file, and nothing happens; a project that already holds `state.json` keeps
11
+ it (a `current.json` beside it is a conflict for a human, not overwritten).
12
+ * The file's bytes are not touched: every field of the task survives.
13
+ * Reverting to 3.4b after the move still guards the task, because that
14
+ version reads `state.json`.
15
+ """
16
+
17
+ VERSION = 9
18
+ TITLE = "the task's state file is state.json"
19
+ STATE_LEGACY = ".ai/state/current.json"
20
+ STATE_NEW = ".ai/state/state.json"
21
+ MOVES = [(STATE_LEGACY, STATE_NEW)]
22
+
23
+
24
+ def plan(ctx):
25
+ ctx.move(STATE_LEGACY, STATE_NEW)
@@ -0,0 +1,30 @@
1
+ """0010: the command-choice dialog is on (R36.1).
2
+
3
+ `.ai/policies/dialog.json` is the project's switch for the dialog: the human
4
+ picks a commit, push or approval command in the runtime's dialog and the agent
5
+ runs that command, verbatim and once. This migration writes the switch, on, as
6
+ the scaffold does for a new project.
7
+
8
+ * A project that already has the file keeps it, whatever it says: `create`
9
+ does not overwrite, and a human's `"enabled": false` stays off.
10
+ * A second run finds the file and does nothing, and prints nothing.
11
+ * The task's state is not touched: a task in flight survives.
12
+ """
13
+
14
+ VERSION = 10
15
+ TITLE = "the command-choice dialog switch"
16
+ SWITCH = ".ai/policies/dialog.json"
17
+ MOVES = []
18
+
19
+
20
+ def plan(ctx):
21
+ if ctx.exists(SWITCH):
22
+ return
23
+ ctx.create(SWITCH, ctx.template(SWITCH))
24
+ ctx.hint("%s is new and the command-choice dialog is on; set \"enabled\": false in it to turn the dialog off"
25
+ % SWITCH)
26
+ ctx.hint("docs/sdlc/constitution.md C5 still says no agent commits, merges or deploys: if you keep the dialog "
27
+ "on, amend C5 to the new sentence (skills/project-init/templates/constitution.md, C5)")
28
+ if ctx.state is not None:
29
+ ctx.hint("a task is in flight: the dialog switch takes effect for it too; set \"enabled\": false in %s "
30
+ "to turn it off" % SWITCH)
@@ -16,7 +16,8 @@ this directory, named `NNNN_slug.py`, numbered contiguously from `0001`, with
16
16
  - A migration that deletes must retire the template in the same release,
17
17
  otherwise the next run re-creates the file.
18
18
  - `ctx.patch_state` is the only way to change a task in flight, and the only
19
- writer of `.ai/state/current.json` other than `state.py`. A migration that
19
+ writer of the task's state file (`.ai/state/state.json`, `current.json` in a
20
+ project not yet at schema 9) other than `state.py`. A migration that
20
21
  moves a path a task's step may touch must patch it, or the scope guard will
21
22
  stop that task on a file that no longer exists.
22
23
  - Operations are planned, never written: the dry run must list everything.
@@ -81,12 +81,18 @@ ROUTER_FILE = ".ai/AGENTS.md"
81
81
  SHARED_SECTION_RE = re.compile(rb"(?m)^## Shared files[ \t]*\r?$")
82
82
  SHARED_SCHEMA = 6 # the schema from which shared copies are overrides (0006)
83
83
  STATE_FILE = ".ai/state/state.json"
84
- LEGACY_STATE_FILE = ".ai/state/current.json" # R34: the name until migration 0008 moves it
84
+ LEGACY_STATE_FILE = ".ai/state/current.json" # R34: the name until migration 0009 moves it
85
+
86
+
87
+ # Templates a migration creates exactly once, on the step to the given schema.
88
+ # From that schema on, a missing file is the human's choice (dialog.json missing
89
+ # means the dialog is off), so the template walk must not re-create it.
90
+ CREATE_ONCE = {".ai/policies/dialog.json": 10}
85
91
 
86
92
 
87
93
  def state_file(plan):
88
94
  """The task state's path as this run leaves the project: state.json once it
89
- exists there (migration 0008 moved it, or the task started under it), else
95
+ exists there (migration 0009 moved it, or the task started under it), else
90
96
  the legacy current.json."""
91
97
  if not plan.exists(STATE_FILE) and plan.exists(LEGACY_STATE_FILE):
92
98
  return LEGACY_STATE_FILE
@@ -1263,6 +1269,8 @@ def build_plan(root, confirm_delete=None, confirm_via=None):
1263
1269
  continue
1264
1270
  if rel in plan.removed: # a migration moved it away in this run
1265
1271
  continue
1272
+ if rel in CREATE_ONCE and version >= CREATE_ONCE[rel] and not plan.exists(rel):
1273
+ continue # past the step that created it: its absence is the human's choice
1266
1274
  content = read(os.path.join(tpl, rel))
1267
1275
  if rel.startswith(".ai/project/") or rel.startswith(".ai/reports/"):
1268
1276
  if not plan.exists(rel):
@@ -1433,7 +1441,8 @@ def apply_item(plan, item, written, recorded):
1433
1441
  if action == "move":
1434
1442
  check(plan, item, target, item["expect"], written)
1435
1443
  mode = os.stat(os.path.join(plan.root, source)).st_mode & 0o7777
1436
- keep_original(plan, source)
1444
+ if not source.startswith(".ai/state/"): # git-ignored task state: a move is byte-identical
1445
+ keep_original(plan, source)
1437
1446
  recorded.append(target)
1438
1447
  # Recorded before the file is gone: an abort later must not lose the note
1439
1448
  # of what was taken away, or of who approved a deletion.
@@ -38,6 +38,8 @@ $STATE handoff --print
38
38
  Trust it over a compaction summary; it is rendered from the state. If
39
39
  `$ARGUMENTS` asks for something else, say what is in flight and ask whether to
40
40
  finish it, or drop it with `$STATE close --abandon`. Never discard it silently.
41
+ A handoff line `Batch: on` means the task runs the loop of `/rr-build-all` —
42
+ parallel implementers and fixers, its own budgets — continue there.
41
43
  - **`Handed to <the other runtime>`:** every state change exits 7 until that
42
44
  runtime resumes it. Say where to resume; take it back with
43
45
  `$STATE handoff --to <this runtime>` only when asked. `Handed to <this
@@ -47,6 +49,11 @@ $STATE handoff --print
47
49
 
48
50
  ## 2. Edit, inside the task
49
51
 
52
+ Before the first edit, recall what the record already holds about the task's
53
+ files — open risks, residual findings, decisions and why, within a token budget,
54
+ read-only: `$STATE recall --files "<the task's files>"` (`memory show <id>` for
55
+ one task in full).
56
+
50
57
  Implement it yourself. The scope guard refuses an edit to a file the task does
51
58
  not name. That refusal is the plan being enforced, not an obstacle:
52
59
 
@@ -56,8 +63,9 @@ $STATE start --amend --files "+<path>" --why "<why the task needs it>"
56
63
  ```
57
64
 
58
65
  The amendment is journaled; the task is not re-planned. A file that belongs to
59
- a different change is not amended in — it is written into
60
- `.ai/project/known-risks.md` and left for its own task.
66
+ a different change is not amended in — it is recorded with `$STATE memory risk
67
+ add --title … --where "file:line" --label RISK --what …` (in files mode that
68
+ writes `.ai/project/known-risks.md`) and left for its own task.
61
69
 
62
70
  Production behaviour is the source of truth: code that looks wrong may be
63
71
  load-bearing. Change only what the task asked for; a refactoring never rides
@@ -94,7 +102,7 @@ at `close` is finished by `close`.
94
102
 
95
103
  ## 4. Verify once, to the end
96
104
 
97
- After the last edit:
105
+ After the last edit (after the last step: `$STATE step-done <id> && $STATE verify --scope all`):
98
106
 
99
107
  ```bash
100
108
  $STATE verify --scope all
@@ -118,10 +126,11 @@ fixed:
118
126
  $STATE verify --scope all --after-fix "<n> regressions: <one line each>"
119
127
  ```
120
128
 
121
- - An existing failure is recorded in `.ai/project/known-risks.md`, not fixed.
129
+ - An existing failure is recorded with `$STATE memory risk add`, not fixed.
122
130
  - An environment failure gets one more run, not a code change.
123
131
  - Never edit a test to make it pass.
124
- - Two whole-suite runs are the budget (`tests.max_suite_runs`). The third
132
+ - Two whole-suite runs are the budget (`tests.max_suite_runs`; in a batch task
133
+ `batch.max_suite_runs`). The third
125
134
  exits 6 `SUITE_BUDGET`: running it again is the human's decision, from their
126
135
  own terminal, with the command it prints — or the pick: with the dialog on it
127
136
  also prints `DIALOG_PENDING`, and you run the command the human picks,
@@ -0,0 +1,190 @@
1
+ ---
2
+ name: rr-build-all
3
+ description: Run a whole programme plan as one task in a repository that has .ai/ — every row of docs/sdlc/plans/<slug>.md becomes a step with its files, tests and dependencies; the ready steps go to parallel implementer subagents on the BALANCED tier, serialized where one depends on another; after the last step the suite runs once to the end, every failure is recorded and fixed by parallel fixers as one batch, then one review at the mode's tier, its findings fixed by parallel fixers as one batch, then tests and the review again until it passes; the pass past the batch budget (three failed reviews) is the human's. Use on "/rr-build-all", "run the whole plan", "all points in one task", "sdlc-lite", "batch build".
4
+ argument-hint: [<path to docs/sdlc/plans/<slug>.md>] | --resume
5
+ ---
6
+
7
+ # /rr-build-all $ARGUMENTS
8
+
9
+ One task for the whole plan — the loop a developer otherwise runs by hand: implement every
10
+ row, test once, fix everything, review, fix everything, again, until the review passes. The
11
+ mode (light, guarded, full) is still the weight's; batch only changes who implements, how
12
+ failures are fixed, and how many rounds run before the human. Resolve the install root once:
13
+
14
+ ```bash
15
+ for AI_HOME in "${CLAUDE_CONFIG_DIR:-$HOME/.claude}" "${CODEX_HOME:-$HOME/.codex}"; do
16
+ [ -d "$AI_HOME/skills/rr-build-all" ] && break
17
+ done
18
+ STATE="python3 $AI_HOME/skills/ai-task/state.py"
19
+ ```
20
+
21
+ Shared files resolve through `"$AI_HOME/riskrails/ai-path" <path>`. Read `policies/safety.md`
22
+ and `using-riskrails.md` once per session. Every rule of `/rr-build` holds here: nothing outside
23
+ the task's files, no commit, a refusal names the way out and is never reworded around.
24
+
25
+ ## 1. Resume or start
26
+
27
+ ```bash
28
+ $STATE handoff --print
29
+ ```
30
+
31
+ - **A task in flight whose handoff says `Batch: on`:** continue at its stage — §3 while
32
+ `steps --ready` prints a step, §4 after the last `step-done`, §5 after a green verify.
33
+ - **A task in flight without that line:** it runs the standard way — say so and hand over to
34
+ `/rr-build`. Only the human turns the loop on mid-task (`batch on`, §Switching).
35
+ - **No task in flight:** §2.
36
+
37
+ ## 2. The plan → one task
38
+
39
+ `$ARGUMENTS` is a programme plan (default: the newest `docs/sdlc/plans/*.md`). Its spec's
40
+ **Flagged concerns** are resolved or accepted, as `/rr-plan` demands; a plan with an open
41
+ blocking question is not started.
42
+
43
+ 1. **Rows → steps.** Every row of **Order of work** that an agent does becomes one step
44
+ `{"id", "files", "tests", "after"}`: the row's files, the tests it names, and in `after` the
45
+ rows it depends on — its *Consumes* line, a stated dependency, or an earlier row it builds
46
+ on. A refactoring row stays its own task (C3): leave it out and say so. A human row (G1, …)
47
+ is not a step: every row after it names in `after` every step before it, so nothing past
48
+ the human row is ready until the rows before it are done — and its question (3.) answered.
49
+ 2. **Weigh and start** — `/rr-plan`'s "A task" section, on the union of the steps' files, then:
50
+
51
+ ```bash
52
+ $STATE start --goal "<the plan's title>" --workflow feature --files "<every file of every step>" \
53
+ --tests "<every test>" [--declare …] --plan-file /path/steps.json \
54
+ --batch --by "<the human's name>" --why "/rr-build-all docs/sdlc/plans/<slug>.md" \
55
+ [--mode <higher> --by "<name>"]
56
+ ```
57
+
58
+ An `after` id must exist and form no cycle; two steps that name one file are ordered by
59
+ `start` itself (`ordered: s4 after s1 (shares …)`), so two implementers never hold one file.
60
+ In full mode the written plan is the programme plan the human already accepted. With
61
+ `batch.default` true in `.ai/policies/weight.json` the flag is implied; `--no-batch` opts out.
62
+ 3. **A human row** becomes a question the moment every step before it is done — asked
63
+ **before** the next wave is dispatched:
64
+ `$STATE ask "G1 is yours: <what>" --option "A: done" --option "B: not yet" --recommend A`,
65
+ then **stop**. Never dispatch while a question is pending (`step-done` and `close` exit 4;
66
+ `steps --ready` still answers); `/rr-build-all --resume` goes on once the human answered.
67
+
68
+ ## 3. Implement, by waves
69
+
70
+ ```bash
71
+ $STATE steps --ready # the next wave: the steps whose dependencies are done, one id per line
72
+ $STATE steps --json # batch_policy.tier and .parallel: the implementers' tier, how many at once
73
+ $STATE profile --tier <that tier> # the tier's model in this runtime (BALANCED as shipped)
74
+ ```
75
+
76
+ **Resuming mid-wave** (after a compaction or a stop): before dispatching, compare
77
+ `git status --short` with each ready step's files. A ready step whose files already changed
78
+ was dispatched before and never recorded — do not send it again blind: brief its implementer
79
+ with that partial diff to finish, or `step-done` it if its tests pass.
80
+
81
+ Dispatch one subagent per ready step, at most `batch.parallel` (shipped 3) at once — under
82
+ Claude Code a `general-purpose` agent with `model:` set to that tier's model; under Codex a
83
+ spawn with no agent named, on that model. Its brief is the implementer contract,
84
+ `agents/implementer.md` in the shared tree, filled in:
85
+
86
+ - **Goal** — the row's text from the plan. **Allowed files** — the step's files, nothing else.
87
+ **Forbidden files** — every other step's files, "another implementer holds them".
88
+ **Required behaviour / behaviour that must not change** — from the row and the spec.
89
+ **Required tests** — the step's tests.
90
+ - Its own tests, run directly: `step_test_command` from `.ai/policies/testing.md` with the
91
+ step's tests in place of `{files}`. **A subagent never calls `state.py`** — one state file,
92
+ one writer, this session.
93
+ - It returns `## RESULT`, or `## SCOPE_CHANGE_REQUIRED`, or `## QUESTIONS_NEEDED`.
94
+
95
+ After the wave, in this session:
96
+
97
+ - `RESULT` → `$STATE step-done <id>` for each step. Exit 6 names a file outside the task:
98
+ `$STATE start --amend --files "+<path>" --why "…"`, then `step-done` again.
99
+ - `SCOPE_CHANGE_REQUIRED` → amend as above and send the same step again. A file that belongs
100
+ to another change goes into `.ai/project/known-risks.md`, not into the task.
101
+ - `QUESTIONS_NEEDED` → `$STATE ask --batch /path/questions.json`, show the questions, **stop**;
102
+ the human answers, and `/rr-build-all --resume` goes on from the handoff.
103
+
104
+ Then `steps --ready` again. Nothing ready and nothing pending: §4. Keep this session small:
105
+ read `## RESULT` blocks, never a subagent's diff; `git status --short` is the only view of the
106
+ tree you need between waves.
107
+
108
+ ## 4. Tests once, failures fixed as one parallel batch
109
+
110
+ After the last wave, `$STATE step-done <id> && $STATE verify --scope all`:
111
+
112
+ ```bash
113
+ $STATE verify --scope all
114
+ $STATE verify --scope all --e2e not-applicable "<why the change reaches no e2e flow>"
115
+ ```
116
+
117
+ Green: §5. **Red:** a FAST `log-reader` reads the log by path and returns every failure
118
+ classified — new regression, existing failure, environment, unknown (`testing.md`, "Reading a
119
+ failure") — each with `file:line`. Then:
120
+
121
+ - an existing failure → one entry in `.ai/project/known-risks.md`; an environment failure →
122
+ one more run, no code change;
123
+ - the new regressions, grouped by the file they point at → one fixer subagent per group, in
124
+ parallel, at most `batch.parallel`, on the batch tier, briefed with the failures' excerpts
125
+ and the files it may touch (that group's files, inside the task's). Fix the code, never the
126
+ test; report `files_changed` and what stayed unfixed;
127
+ - one run: `$STATE verify --scope all --after-fix "<n> regressions: <one line each>"`.
128
+
129
+ Red again → the same once more. Exit 6 `SUITE_BUDGET` — past `batch.max_suite_runs`
130
+ (shipped 8) — is the human's run: the pick in the dialog, or the command it prints, in their
131
+ own terminal. **Stop.**
132
+
133
+ ## 5. Review, findings fixed as one parallel batch, again until it passes
134
+
135
+ One `ai-reviewer` at the mode's tier, briefed as `/rr-review` §2 says: the whole diff since the
136
+ task's base, the task's files, the tests, the last verify log; unbounded "look for" in full
137
+ mode, the security focus when the domain axis is 2. Record it verbatim:
138
+
139
+ ```bash
140
+ $STATE review --verdict <pass|pass_with_findings|blockers_open> --tier <BALANCED|STRONG> \
141
+ [--focus security] --report - <<'EOF'
142
+ <the reviewer's FINDINGS and VERDICT, unchanged>
143
+ EOF
144
+ ```
145
+
146
+ - **pass** → §6.
147
+ - **pass_with_findings** → the in-scope HIGHs, grouped by file, one fixer per group in
148
+ parallel; `$STATE verify --scope all --after-fix "H1,H2: …"`; `$STATE review --closes "H1,H2"`
149
+ → §6. Each MEDIUM and LOW is one `$STATE memory risk add`, not a fix; only a BLOCKER, a HIGH
150
+ or a regression buys an `--after-fix` run.
151
+ - **blockers_open** → every in-scope BLOCKER and HIGH, grouped by file, one fixer per group in
152
+ parallel; `$STATE verify --scope all --after-fix "B1,H1: …"` (red: §4's batch); then
153
+ **§5 again, a full pass** — a fix batch across many files is a new change, not a scoped one.
154
+
155
+ Exit 6 `REVIEW_BUDGET` after `batch.review_rounds_max` passes (shipped 3 — three failed
156
+ reviews) — the next verdict is the human's: the pick in the dialog, or the command it prints,
157
+ in their own terminal. Show the open findings and **stop**. A `verify` past its budget inside
158
+ this loop is `SUITE_BUDGET`, handled the same way.
159
+
160
+ ## 6. Ship
161
+
162
+ `/rr-ship` — `close` measures the two facts and, in full mode, asks the human to approve,
163
+ exactly as for any task; for a documents-only change since the green suite it is
164
+ `$STATE verify --scope step --files "<doc_tests>" && $STATE verify --scope e2e && $STATE close`. Suggest `/clear` after it.
165
+
166
+ ## Switching
167
+
168
+ - **To the standard loop ("full" from here):** `$STATE batch off --by "<name>" --why "<why>"`.
169
+ The standard budgets apply from now, counting what was spent — with two passes behind you,
170
+ the next verdict is already the human's. The session implements the remaining steps itself;
171
+ continue with `/rr-build`, `/rr-review`, `/rr-ship`. Anyone may do this: it raises the rigor.
172
+ - **To batch, mid-task:** lowers the rigor — the human's, in their own terminal:
173
+ `python3 <AI_HOME>/skills/ai-task/state.py --root <project> batch on --by "<name>"`. Never
174
+ from a tool call; the refusal (`APPROVAL_REFUSED`) prints that command.
175
+ - **The project's default:** `batch.default` in `.ai/policies/weight.json`, beside
176
+ `batch.review_rounds_max`, `batch.max_suite_runs`, `batch.parallel` and `batch.tier`
177
+ (`/rr-setup --update` adds the section). A policy is the human's and is frozen during a task.
178
+
179
+ ## Rules
180
+
181
+ - The mode is the weight's and only rises; the scope guard, the two facts, the gate and the
182
+ three nevers are untouched by batch.
183
+ - Three or more parallel agents run at BALANCED, never above — `start` refuses `batch.tier`
184
+ above it when `batch.parallel` is three or more; one reviewer per pass, at the mode's tier;
185
+ the session writes every conclusion (`model-routing.md`).
186
+ - One writer of the state: a subagent never calls `state.py`; this session records every step,
187
+ run and verdict.
188
+ - Failures and findings are fixed as batches, never one at a time; a test is never edited to
189
+ make it pass; what is outside the task is written down, not fixed.
190
+ - No commit, push, merge or deploy. The task ends at `/rr-ship`; approval is the human's.
@@ -38,7 +38,11 @@ When `$ARGUMENTS` is a spec (default: the newest `docs/sdlc/specs/*.md`):
38
38
  4. Copy the template to `docs/sdlc/plans/<slug>.md`, fill **Files that change /
39
39
  Order of work / Risks / Proof / Rollback**; Proof maps every requirement R<n>
40
40
  to a test or command. One round of corrections; suggest the commit
41
- `plan: <title>`. Each row of the plan is later one task, planned below.
41
+ `plan: <title>`. Each row of the plan is later one task, planned below —
42
+ unless the whole plan runs as one task through `/rr-build-all` (the project's
43
+ `batch.default` in `weight.json`, or the developer's call): then every row
44
+ becomes one step of that task, so give each row its files and its *Consumes*
45
+ line (the rows it depends on) — that is what `/rr-build-all` reads.
42
46
 
43
47
  ## A task → weight, mode, plan, start
44
48
 
@@ -48,7 +52,10 @@ investigation — say which and why. `using-riskrails.md` in the shared tree
48
52
  `workflows.md#<kind>` say what each kind requires. A refactoring and a feature
49
53
  are never one task.
50
54
 
51
- **2. Name the files** from the request, confirmed with `grep -n`. Then weigh:
55
+ **2. Name the files** from the request, confirmed with `grep -n`. Recall what
56
+ the record holds about them — `$STATE recall --files "<a>,<b>"`: open risks,
57
+ residual findings and earlier decisions are evidence for the weight and the
58
+ plan. Then weigh:
52
59
 
53
60
  ```bash
54
61
  $STATE weight --files "<a>,<b>" --goal "<one sentence>" \
@@ -64,7 +71,7 @@ The table is `.ai/policies/weight.json` (`weight.md` mirrors it).
64
71
 
65
72
  **3. The mode is the weight's**, not yours: raising it is free
66
73
  (`--mode <m> --by "<name>"` on `start`); lowering it is the human's, from their
67
- own terminal. Shape the plan by it:
74
+ own terminal, or the command they picked in the dialog. Shape the plan by it:
68
75
 
69
76
  | Mode | Plan | Who sees it before the first edit |
70
77
  |---|---|---|
@@ -92,6 +99,9 @@ $STATE start --goal "<one sentence>" --workflow <kind> --files "<a>,<b>" \
92
99
 
93
100
  `--plan-file` is a JSON list `[{"id": "s1", "files": [...], "tests": [...]}]`
94
101
  for a guarded or full plan with steps; a light task is one scope and needs none.
102
+ A step may add `"after": ["s0"]`, the steps it waits for — `/rr-build-all` runs
103
+ the rest in parallel — and `--batch --by "<name>"` (or `--no-batch`) sets that
104
+ loop for the task; the default is `batch.default` in `weight.json`.
95
105
  `--files` lists every file of every step — the guard refuses an edit outside
96
106
  them. `--tests` names the task's own tests; a bugfix names its failing test. At
97
107
  guarded and full, run `start` only after the human accepted the plan.
@@ -30,7 +30,10 @@ STATE="python3 $AI_HOME/skills/ai-task/state.py"
30
30
  (`review_rounds_max`): one full review and one scoped re-review. The pass past
31
31
  it exits 6 `REVIEW_BUDGET` — the next verdict is the human's, from their own
32
32
  terminal, with the command it prints, or the pick in the dialog (`DIALOG_PENDING`,
33
- then the picked command verbatim, once). Never a third pass.
33
+ then the picked command verbatim, once). Never a third pass. A batch task
34
+ (`/rr-build-all`) has its own budget, `batch.review_rounds_max` full passes
35
+ (shipped three): after a `blockers_open` fix batch the next pass is a full one,
36
+ and the pass past the budget is the human's the same way.
34
37
 
35
38
  ## 2. Brief one `ai-reviewer`
36
39
 
@@ -49,10 +52,11 @@ the tier, so name the tier in the brief. Give it paths, not pasted text:
49
52
  **Bounded inputs in light and guarded:** the goal, the diff, the named tests,
50
53
  and the project's own threat model (`.ai/policies/safety.md`, the guards'
51
54
  defaults, the test fixtures). A finding that needs anything outside them comes
52
- back `[INFO]` with `in_scope: no`; write it into `.ai/project/known-risks.md`
55
+ back `[INFO]` with `in_scope: no`; record it with `$STATE memory risk add`
53
56
  as one entry — it never opens a fix. You may move a finding to
54
57
  `in_scope: yes`, never the other way. **In full mode** the reviewer's own "look
55
- for" list applies unbounded.
58
+ for" list applies unbounded. Tell it the cap: about 40 tool calls in light and
59
+ guarded, about 80 in full, then FINDINGS and VERDICT.
56
60
 
57
61
  Before you delegate, probe the change yourself for a minute: the few inputs its
58
62
  own threat model makes interesting, through the real code, and hand the
@@ -77,12 +81,16 @@ task's record (`task.md`), so there is no separate report to write.
77
81
 
78
82
  ## 4. After the verdict
79
83
 
80
- - **pass:** `/rr-ship`.
81
- - **pass_with_findings:** fix every in-scope HIGH (and the MEDIUMs worth it) in
82
- one batch, then
84
+ - **pass:** `/rr-ship`; the record and the close are one call,
85
+ `$STATE review --verdict pass … <<'EOF' && $STATE close`. `review` exits 0 for every
86
+ verdict, so the chain is for `pass` only.
87
+ - **pass_with_findings:** fix every in-scope HIGH in one batch, then
83
88
  `$STATE verify --scope all --after-fix "H1,H2: <one line>"` and
84
89
  `$STATE review --closes "H1,H2"`. The findings close on that green run, on a
85
- tree the fix changed — no second review.
90
+ tree the fix changed — no second review. Each MEDIUM and LOW is one
91
+ `$STATE memory risk add` (`.ai/project/known-risks.md` amended into the task
92
+ if missing), not a fix; only a BLOCKER, a HIGH or a regression buys an
93
+ `--after-fix` run.
86
94
  - **blockers_open:** fix every BLOCKER and HIGH together, `verify --scope all
87
95
  --after-fix "…"`, then **one scoped re-review** (`/rr-review B1,H1`): brief a fresh `ai-reviewer`
88
96
  with the named findings and the fix's diff only — do they close, and what did
@@ -94,6 +102,8 @@ The `verify` after a fix is often the task's third whole-suite run: past
94
102
  from their own terminal, with the command it prints, or the pick in the dialog.
95
103
 
96
104
  A finding whose cause is the plan goes back to `/rr-plan` for that part only. A
97
- real problem outside the task goes into `.ai/project/known-risks.md`. A mistake
105
+ real problem outside the task is recorded with `$STATE memory risk add`; a
106
+ fix in this task closes its risk with `$STATE memory risk close <rkey> --status
107
+ fixed --why "…"`. A mistake
98
108
  this repository has seen before — the second time a review flags it — gets one
99
109
  line in the project instruction file, in this task.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: rr-ship
3
- description: Close the task — state.py close measures the two facts (a green whole-suite verify on the tree as it is now; every changed file inside the task's files), applies the mode table and either archives the task or, in full mode, requests the human's approval and prints the exact approve command for their own terminal. Writes the commit message body and suggests the commit; never commits, pushes or approves. Use on "/rr-ship", "close the task", "ship it", "ready for approval", after /rr-build or /rr-review.
3
+ description: Close the task — state.py close measures the two facts (a green whole-suite verify on the tree as it is now; every changed file inside the task's files), applies the mode table and either archives the task or, in full mode, requests the human's approval and prints the exact approve command for their own terminal. Writes the commit message body and suggests the commit; never merges or deploys, and commits, pushes or approves only as the command the human picked in the dialog, verbatim, once. Use on "/rr-ship", "close the task", "ship it", "ready for approval", after /rr-build or /rr-review.
4
4
  argument-hint: [--abandon]
5
5
  ---
6
6
 
@@ -33,7 +33,8 @@ Then the mode table decides:
33
33
  |---|---|---|
34
34
  | 0, `closed` | archived: `task.md` holds the changes and the verdict | §3 |
35
35
  | 0, `ready for approval` | full mode: the gate is requested | §2 |
36
- | 2 `review required` | light with a red fact, or guarded/full without its review | `/rr-review` |
36
+ | 2 `review required` whose text holds `only documents changed since run …` (read this row first) | a green suite, then documents only | `$STATE verify --scope step --files "<doc_tests>" && $STATE verify --scope e2e && $STATE close` — `close` prints the files comma-joined; use its text |
37
+ | 2 `review required`, any other reason | light with a red fact, or guarded/full without its review | `/rr-review` |
37
38
  | 2 `verify required` | e2e owed, or not on this tree | `$STATE verify --scope all` (or `--scope e2e`, or `--e2e not-applicable "<why>"`) |
38
39
  | 4 | a question is pending | show it; §4 |
39
40
  | 5 `APPROVAL_REFUSED` | rejected, and nothing changed since | address the rejection, `verify --scope all`, close again |
@@ -54,9 +55,13 @@ Show the human the summary (§3), the open findings, the rollback, and that
54
55
  command **verbatim** — paths absolute and quoted, because they paste it into
55
56
  their own shell, where `$AI_HOME` is not set. Then **stop**.
56
57
 
57
- - **You cannot approve.** `approve` refuses without a terminal on stdin or
58
- `AI_UNATTENDED` in its own environment — neither of which a tool call from this
59
- session has — and the path guard denies it. Never try another route.
58
+ - **You approve only through the dialog.** With `.ai/policies/dialog.json`
59
+ `enabled: true`, `close` offers the `approve` command in the runtime's dialog;
60
+ once the human picks it, run exactly that command, verbatim and once. With the
61
+ switch off, or no pick, you cannot approve: `approve` refuses without a terminal
62
+ on stdin or `AI_UNATTENDED` in its own environment — neither of which a tool
63
+ call from this session has — and the path guard denies it. Never try another
64
+ route.
60
65
  - **full_irreversible:** the command carries
61
66
  `--confirm "<what it does, naming DROP …>"`; the human names every operation
62
67
  the re-score found, in their own words.
@@ -91,11 +96,14 @@ Write the body from `.ai/reports/<task-id>/task.md` — no new opinion:
91
96
  - the verification command and its result (suite and e2e);
92
97
  - the review verdict, with any finding left open and why;
93
98
  - the rollback: `git revert <commit>`, plus anything a revert does not undo;
94
- - open risks, pointing at `.ai/project/known-risks.md`.
99
+ - open risks: the ones this task recorded or closed with `state.py memory risk
100
+ add|close`, by rkey (`state.py memory risks` lists them).
95
101
 
96
102
  Suggest the commit command — `git add` of the task's files and its
97
- `.ai/reports/<task-id>/`, then `git commit` with that body — for the human to
98
- run. You never commit, push, merge or deploy.
103
+ `.ai/reports/<task-id>/` (in packages mode also `.ai/memory/`, which holds the
104
+ task's record — the pre-push check refuses a closed task without it), then
105
+ `git commit` with that body — for the human to run. You never merge or deploy; you commit, push or
106
+ approve only as the command the human picked in the dialog (§2), verbatim, once.
99
107
 
100
108
  ## 4. Pending questions
101
109