riskrails 3.2.2 → 4.1.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 (149) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.codex-plugin/plugin.json +1 -1
  4. package/README.md +50 -84
  5. package/agents/ai-reviewer.md.tmpl +1 -1
  6. package/ai/using-riskrails.md +0 -3
  7. package/bin/menu.js +116 -0
  8. package/bin/riskrails.js +132 -79
  9. package/hooks/ai-path-guard-defaults.json +1 -1
  10. package/hooks/context-guard.py +2 -4
  11. package/hooks/guard/dialog.py +14 -2
  12. package/hooks/guard/paths.py +3 -6
  13. package/hooks/guard/scope.py +1 -3
  14. package/hooks/runtime-gate.py +18 -58
  15. package/instructions/routing.md +2 -2
  16. package/package.json +1 -1
  17. package/scripts/ai-path +1 -1
  18. package/scripts/resolve-profile.py +0 -3
  19. package/skills/ai-audit/templates/ai-sdlc-adoption-plan.md +1 -1
  20. package/skills/ai-audit/templates/play-scoring-rubric.md +1 -1
  21. package/skills/ai-init/scaffold-ai.sh +2 -1
  22. package/skills/ai-init/templates/.ai/AGENTS.md +6 -6
  23. package/skills/ai-init/templates/.ai/VERSION +1 -1
  24. package/skills/ai-init/templates/.ai/policies/safety.md +4 -3
  25. package/skills/ai-init/templates/.ai/policies/security.md +1 -2
  26. package/skills/ai-init/templates/.ai/policies/testing.md +5 -12
  27. package/skills/ai-init/templates/.ai/policies/verification.md +18 -0
  28. package/skills/ai-init/templates/.ai/policies/weight.json +0 -1
  29. package/skills/ai-init/templates/.ai/policies/weight.md +1 -2
  30. package/skills/ai-init/templates/.ai/policies/weight.project.json +4 -0
  31. package/skills/ai-init/templates/.ai/project/architecture.md +1 -1
  32. package/skills/ai-init/templates/.ai/project/initial-assessment.md +2 -2
  33. package/skills/ai-init/templates/.ai/project/overview.md +1 -1
  34. package/skills/ai-init/templates/.ai/rules/README.md +2 -2
  35. package/skills/ai-init/templates/.ai/state/README.md +1 -1
  36. package/skills/ai-task/memory_store.py +8 -9
  37. package/skills/ai-task/rr_state/cli.py +2 -2
  38. package/skills/ai-task/rr_state/dialog.py +2 -4
  39. package/skills/ai-task/rr_state/dialog_cmd.py +183 -6
  40. package/skills/ai-task/rr_state/fs.py +5 -13
  41. package/skills/ai-task/rr_state/labels.py +14 -2
  42. package/skills/ai-task/rr_state/memory_cmd.py +7 -4
  43. package/skills/ai-task/rr_state/profile.py +2 -4
  44. package/skills/ai-task/rr_state/questions_cmd.py +1 -1
  45. package/skills/ai-task/rr_state/report.py +3 -4
  46. package/skills/ai-task/rr_state/runtime.py +1 -1
  47. package/skills/ai-task/rr_state/start.py +7 -7
  48. package/skills/ai-task/sensors.py +10 -11
  49. package/skills/ai-task/state.py +4 -24
  50. package/skills/ai-task/weight.py +17 -17
  51. package/skills/ai-task/weight_overlay.py +38 -0
  52. package/skills/project-init/templates/constitution.md +2 -2
  53. package/skills/project-update/history/blobs/00f5e27ce2d66e3a1d8b222b013ae8fa1fed32612d91a551e0c661cee3ef9c2d +34 -0
  54. package/skills/project-update/history/blobs/0a6b1b6dd06a35582b2e9989a1f41c40abc29254b8e482714fcc6f0a7b16c406 +32 -0
  55. package/skills/project-update/history/blobs/0aeb04b04262683cac6513545683486a73dc473b447bba43b5aaab18403957a6 +34 -0
  56. package/skills/project-update/history/blobs/0ce913a28996f546f72d570b0e5a376362e993ce4d805bc4aae57d38caa44212 +41 -0
  57. package/skills/project-update/history/blobs/0ea9e36446b624b73b2a821231b2ee66a357b43d584a5b23da48b3c800855e65 +41 -0
  58. package/skills/project-update/history/blobs/0fb1d68678a1349195b2e79433bb20174d25874e3bfd0b70410bb4e428b4e4b8 +35 -0
  59. package/skills/project-update/history/blobs/119b2b9d0f9c647a243540724edac6b29afa020c69aa205797bcfa9eb06bc021 +35 -0
  60. package/skills/project-update/history/blobs/1d0fe3ee5fb8260ba610942d4bbdfff7410fbe80ed826ac07f32985031dc2b3f +34 -0
  61. package/skills/project-update/history/blobs/1de9a37ed6402893dcab6e61ddbf15ffd35f15a6d84b18e675a0c5bf4e981f85 +42 -0
  62. package/skills/project-update/history/blobs/1f44e1a236233dcbab58064f39b69f798b35d1d9a29f8c615b5b12854ce633cb +15 -0
  63. package/skills/project-update/history/blobs/1f824645299579cbdd8141642ddbb4bca9fd5fe9d3112f036d8221f0811e0abf +40 -0
  64. package/skills/project-update/history/blobs/235fb88393cfe20dd58b35fe9785cc45baf5ffe21a13d926652d76ec68cea8b7 +35 -0
  65. package/skills/project-update/history/blobs/3918b4ee011d9477b9d2779e2893ab599749c406d4b09439a9748b64fbff58f3 +18 -0
  66. package/skills/project-update/history/blobs/449273200dfec2a56885c881ff34d40e8ecc00da53c24c2d09b7fbeb1004d255 +40 -0
  67. package/skills/project-update/history/blobs/4c45aee9b9fc5f6b4e1d9739e434c4094975a5a8dec6b9703fb25f3080680c77 +124 -0
  68. package/skills/project-update/history/blobs/4dd3fa12bc45acc8c836ab65d790248ca7504a021bca6677499d17bb3d798ed9 +64 -0
  69. package/skills/project-update/history/blobs/51e3f15095d7123ea8566b512479ee10a6cb2f336b7352a259a083a887bd7116 +33 -0
  70. package/skills/project-update/history/blobs/5497a204967bea7dab29079a6e1dfa3d8713b2d2cb294c2779378039f03a55fc +36 -0
  71. package/skills/project-update/history/blobs/60c4d7e7fde7049d92d84295fc13ca9a91eb2de423be08f093b3ee5d5e817ff8 +64 -0
  72. package/skills/project-update/history/blobs/6221b7c14cc04634e485e562d464c6860d45666a7f63e293c06bb2944ff556cc +27 -0
  73. package/skills/project-update/history/blobs/637971cfb844ef4285e2886a4b1c834fb2ed5c46e773adb88c2c147fea626ad3 +33 -0
  74. package/skills/project-update/history/blobs/65af2282eea2a51fcc27a4acf2c26c727b0961c30e1be13176369200c460c219 +34 -0
  75. package/skills/project-update/history/blobs/66ecd73e303e7bbc1aa8ee72435d0d10812ff7b2eff0adac59bbf0a303e2cc01 +41 -0
  76. package/skills/project-update/history/blobs/6a43bf32461b22b87fafe2865529dc04fa66cd00182a2a7598aa071667ca255a +35 -0
  77. package/skills/project-update/history/blobs/6d6dee8634abf9ac057bb206828b83a893a2afcf4f86bbe69e839a3b47d0adde +48 -0
  78. package/skills/project-update/history/blobs/7224ede803ea81e65a456e21b6028a0e848e8a880456c6503eebe7534ca4f6aa +74 -0
  79. package/skills/project-update/history/blobs/765a39a202617096c232017822ae738d37e4405430c71700dc7bc14bf1ba794e +33 -0
  80. package/skills/project-update/history/blobs/77577440a933d1cabd8c6f4a6401cf361a784aa09a25500a6f7b44ead8ab5e55 +41 -0
  81. package/skills/project-update/history/blobs/7bae90789625d6fb9071ecb412d14a8d1eb0bc5659d8d284c4eaf213e1b5de56 +67 -0
  82. package/skills/project-update/history/blobs/7bcdf9a0e6b85277b9b60669150224b9414d2e32821ff06f4d148eb1d18785bb +42 -0
  83. package/skills/project-update/history/blobs/7f834103e9d97aea44e76717bcdcbbe349c560e5b81a42ce85a1cec341041281 +4 -0
  84. package/skills/project-update/history/blobs/7fb3acb0211818efebc2234863db0b8c846022a7280a6d2d69f267dbf63db48c +34 -0
  85. package/skills/project-update/history/blobs/87f0855859ff68cc6c988cc0b631ee7f56af7fbba062172bf80e01f4982cc054 +35 -0
  86. package/skills/project-update/history/blobs/8abab74759766d02b5cb7b0c3e59a3d440b25a454216cd8fea325c23fd822d36 +33 -0
  87. package/skills/project-update/history/blobs/8ec171f0fbdf38cc6996d496f01491fd1f21f04a435a118ad979b127a8be06f1 +85 -0
  88. package/skills/project-update/history/blobs/a1fb50e6c86fae1679ef3351296fd6713411a08cf8dd1790a4fd05fae8688164 +1 -0
  89. package/skills/project-update/history/blobs/a3df7268feb0780be0d2cf9acced6ed81780a7790f36fe024b6ea0b1bd6eb7a6 +35 -0
  90. package/skills/project-update/history/blobs/b28721136482dafb9fd2801af340364cb97e9f6eaa987908606c786045b8d334 +28 -0
  91. package/skills/project-update/history/blobs/b3726422d767f9219fea633bea77f0c99ad9af843c591e6e928e1ccd2a47f374 +27 -0
  92. package/skills/project-update/history/blobs/b3839425f9d0ab2efa42a6f5e9488ec2d26ca5fb8dcd694b8ab098e10743ca46 +32 -0
  93. package/skills/project-update/history/blobs/ba14a457e83f9dde65e4190fdfab83b912f7398c1442a2a1cb3d89bfac741cf3 +8 -0
  94. package/skills/project-update/history/blobs/bceb7189444bb6291b262ca08e34db01010dda2f6e64d696231ec3c343c95c66 +34 -0
  95. package/skills/project-update/history/blobs/bf82a2bb4fce1bd349ff66118930a01d61a7af8e2bd8d200c721d43afc58c713 +34 -0
  96. package/skills/project-update/history/blobs/c4dbeb180292a6199ad73a3be861ece07c1f8bf6bf0cc7ca204412bc8e1bb1d8 +31 -0
  97. package/skills/project-update/history/blobs/c644838866df2001a42501a988dd7b77aacf862bf09d22b465f3cd8a22c6b6eb +33 -0
  98. package/skills/project-update/history/blobs/c980d74f76a4bdfb38c94b573ac10a54eb50b850b052e15fa6f2442889b36ccb +32 -0
  99. package/skills/project-update/history/blobs/ceed2f3bd937f862d0e6ca59ce1b1e3603e19a0d7f85d90d6dfeb7bf690153be +29 -0
  100. package/skills/project-update/history/blobs/d51ea2e893482a20c5882056cf8043327ca1dc1c957927f6746929a47ee8368e +45 -0
  101. package/skills/project-update/history/blobs/d78f5e0bb1380259fce2cce009785a9a11f6de8b87a160080b9872c059f95060 +34 -0
  102. package/skills/project-update/history/blobs/d97f46a2cca020406252b1f7baa4184617fa71faca3885e2379c44ae4e1d9327 +67 -0
  103. package/skills/project-update/history/blobs/da3ecd4c4c414c93d04488685931df39a56bf959bfeb9c45cb1aea2c13bd991b +38 -0
  104. package/skills/project-update/history/blobs/e129bf71a5a922e24b2c1bc8daa8a5d2b5589b0069770e17ce17e7db5ed4e7a4 +27 -0
  105. package/skills/project-update/history/blobs/e504529519a371892838725f8b89b5d32e3300e345bcbf2643a3a1a48434b3dd +24 -0
  106. package/skills/project-update/history/blobs/e9e62d03ca70b3dffccef8dceeb214173352cfef005145e519f0e037993f1c03 +36 -0
  107. package/skills/project-update/history/blobs/effefbaaf4beb8f1ba55081d6b7e74bf25ebb91045dd10613418f17b95fa7182 +33 -0
  108. package/skills/project-update/history/blobs/f6af4581bafbf62b257d57e06c3ae2c5998aeca608ee7df037fcc3c3e4b563a9 +34 -0
  109. package/skills/project-update/history/blobs/fc35045777d29630303430752a651b3e553580a581036a02cc103eb96a46f4b0 +34 -0
  110. package/skills/project-update/history/blobs/fdc21345c77f92a42d244aa104f393f439a0ff9981a9fd462bd837e8a47931bb +48 -0
  111. package/skills/project-update/history/index.json +34 -14
  112. package/skills/project-update/render_instructions.py +12 -45
  113. package/skills/project-update/update.py +757 -1172
  114. package/skills/rr-setup/SKILL.md +114 -97
  115. package/skills/rr-setup/scaffold_ai.py +15 -9
  116. package/skills/rr-setup/setup.py +462 -164
  117. package/skills/rr-status/status.py +7 -10
  118. package/skills/usage-report/usage-report.py +4 -5
  119. package/skills/ai-audit/SKILL.md +0 -9
  120. package/skills/ai-init/SKILL.md +0 -9
  121. package/skills/ai-status/SKILL.md +0 -9
  122. package/skills/ai-task/SKILL.md +0 -9
  123. package/skills/project-init/SKILL.md +0 -9
  124. package/skills/project-update/SKILL.md +0 -9
  125. package/skills/project-update/adopt-map.json +0 -91
  126. package/skills/project-update/adopt.py +0 -2225
  127. package/skills/project-update/migrations/0001_schema_version.py +0 -13
  128. package/skills/project-update/migrations/0002_task_journal.py +0 -123
  129. package/skills/project-update/migrations/0003_context_diet.py +0 -65
  130. package/skills/project-update/migrations/0004_deterministic_gates.py +0 -57
  131. package/skills/project-update/migrations/0005_runtimes_and_plans.py +0 -35
  132. package/skills/project-update/migrations/0006_shared_files.py +0 -154
  133. package/skills/project-update/migrations/0007_weight_model.py +0 -295
  134. package/skills/project-update/migrations/0008_renames.py +0 -43
  135. package/skills/project-update/migrations/0009_state_file.py +0 -25
  136. package/skills/project-update/migrations/0010_dialog_switch.py +0 -30
  137. package/skills/project-update/migrations/0011_retire_risk_tiers.py +0 -37
  138. package/skills/project-update/migrations/README.md +0 -76
  139. package/skills/project-update/migrations/__init__.py +0 -186
  140. package/skills/sdlc-intent/SKILL.md +0 -9
  141. package/skills/sdlc-plan/SKILL.md +0 -9
  142. package/skills/sdlc-spec/SKILL.md +0 -9
  143. package/skills/usage-report/SKILL.md +0 -10
  144. /package/{ai/workflows/refactoring.md → skills/project-update/history/blobs/36cb593293496fbcf38df828a9b9b2bc0d5a53333f584a5319ebc3d799016e24} +0 -0
  145. /package/{ai/workflows/feature.md → skills/project-update/history/blobs/56e16072c2f3edc6c8897c690d09a11d12fc414c3e3f361f359f7dc609a21282} +0 -0
  146. /package/{ai/workflows/hotfix.md → skills/project-update/history/blobs/8cbefbf1aa412bae3e5019acd40b8fe0598fceba6c781906b3bc6dbd014f6b23} +0 -0
  147. /package/{ai/workflows/bugfix.md → skills/project-update/history/blobs/af56dc16e44ae1d8c3dac4c3ca82e2163b719553c02ea455e77430bab9a14089} +0 -0
  148. /package/{ai/workflows/investigation.md → skills/project-update/history/blobs/b9e09cb24958cd6831589997558974bd6356305306e8f9685e226bcdc30d60ac} +0 -0
  149. /package/{ai/agents/manager.md → skills/project-update/history/blobs/d0cf6388f35a92a0cf607d33909278382f6d7b6a4c32e281b9f9e0ea652c7b91} +0 -0
@@ -0,0 +1,34 @@
1
+ # Workflow: investigation
2
+
3
+ A question, not a change. "Why does this happen?", "where is this handled?",
4
+ "can we do X?". The deliverable is an answer with evidence.
5
+
6
+ > Who runs a stage is set by `pipeline_profile` in `policies/risk-tiers.json`.
7
+ > The table names the agent for when a stage is delegated. In the default `solo`
8
+ > profile T0–T3 run in direct mode — the session does every stage itself, in a
9
+ > few lines, with cheap readers and one review (BALANCED at T2; STRONG at T3,
10
+ > whose plan the human approves in plan mode) — and T4+ run the full pipeline
11
+ > with the delegations below.
12
+
13
+ | Stage | Who | Notes |
14
+ |---|---|---|
15
+ | DISCOVERY | `ai-indexer`, then `ai-discovery` in parallel per area | read-only |
16
+ | CONTEXT | `ai-context` | the structured summary is often the deliverable itself |
17
+ | IMPACT ANALYSIS | `ai-discovery` | only if the question is "what would it take to…" |
18
+ | RISK CLASSIFICATION | `ai-risk` | so the answer carries the tier a change would have |
19
+ | REPORT | the session | written by the main session, not delegated |
20
+
21
+ There is no implementation stage. If the investigation concludes that something
22
+ should change, that is a **new task** with its own intent, plan and approval.
23
+
24
+ ## Rules
25
+
26
+ - Nothing is edited. Not a comment, not a formatting fix.
27
+ - Every claim in the answer is labelled and cited: KNOWN FACT with `file:line`,
28
+ INFERENCE with what it rests on, UNKNOWN with what would settle it.
29
+ - Contradictions between documentation and code are reported as both, not
30
+ resolved by preference.
31
+ - Findings worth acting on go into `project/known-risks.md` so the next task can
32
+ see them.
33
+ - Say what you could not determine. An investigation that hides its gaps is worse
34
+ than one that admits them.
@@ -0,0 +1,67 @@
1
+ # Task state
2
+
3
+ `state.json` is the machine-readable record of the task in flight. It is
4
+ written by `skills/ai-task/state.py` (atomically), read by `/rr-status`, and
5
+ enforced by `ai-scope-guard`, which derives the files the current step may touch
6
+ from it.
7
+
8
+ Two other writers exist, and only these two. A schema migration in
9
+ `/rr-setup --update` may change the state through `ctx.patch_state()`, with the
10
+ same atomic write and a `schema_migrated` history entry — that is how a task in
11
+ flight survives a change to the shape of this file. And `hooks/context-guard.py`
12
+ writes `session.json`, the sidecar beside this file, and nothing else: it never
13
+ touches `state.json`. Nothing else writes any of it — an agent never edits
14
+ them by hand, and the path guard refuses when one tries.
15
+
16
+ It is **not committed**: it describes a session, not the repository. The
17
+ `.gitignore` entry added by `/rr-setup` keeps it out of git.
18
+
19
+ When a task closes, `state.py close` writes the final state to
20
+ `.ai/state/logs/<task-id>/state.json`, beside the task's verify logs — local,
21
+ **not** committed. What is committed is `.ai/reports/<task-id>/events.jsonl`
22
+ and `task.md`, and in packages mode the task's compact record under
23
+ `.ai/memory/` — that is the audit trail: which stages ran, in what order, who
24
+ approved what, and when (the plugin's `docs/local-memory.md`).
25
+
26
+ It holds facts, never transcripts:
27
+
28
+ ```
29
+ task_id, goal, workflow, risk_tier, current_stage, affected_modules,
30
+ context_summary_ref, approved_plan { ref, current_step_id, steps[] },
31
+ completed_steps, test_status, e2e_status, review_status, security_status, open_risks,
32
+ next_action, owner_runtime, resume_point { stage, step_id, next_action, at, runtime },
33
+ questions { file, pending[] }, handoff { file, written_at, reason },
34
+ human_approval { required, granted, granted_by, granted_at,
35
+ requested_at, gate_id, requested_session, rejected_at, via, unattended },
36
+ created_at, updated_at, history[]
37
+ ```
38
+
39
+ `state.py` applies the schema-2 keys in memory as it loads, so a project that has
40
+ not run `/rr-setup --update` yet still answers every command; `save()` then writes
41
+ them. A reader that opens this file directly sees what is on disk, not those
42
+ defaults.
43
+
44
+ ## The other files beside it
45
+
46
+ | File | Written by | Committed |
47
+ |---|---|---|
48
+ | `state.json` | `state.py` | no |
49
+ | `session.json` | `context-guard.py`, on SessionStart and each prompt | no |
50
+ | `handoff.md` | `state.py handoff` — never a model | no |
51
+ | `../reports/<task-id>/task.md` §Questions | `state.py ask/answer/questions` | yes |
52
+ | `../reports/<task-id>/events.jsonl` | `state.py` (`emit`), append-only | yes |
53
+
54
+ `handoff.md` is the ≤ 30-line frame a session that lost its context reads first:
55
+ the goal, the next action and its resume point, the pending questions, the latest
56
+ decisions, rejected options and failed attempts, and the user's last instruction
57
+ verbatim. It is rendered from the four sources above, so deleting it loses
58
+ nothing — the next stage-moving command writes it again.
59
+
60
+ `events.jsonl` is the journal: one line per state change, `history[]`'s facts
61
+ with types beside them. It is best effort by contract — a line that cannot be
62
+ written never fails the command that emitted it — so nothing depends on it being
63
+ complete, and readers skip a line they cannot parse.
64
+
65
+ If this file is corrupt, `state.py` refuses to read it rather than replacing it.
66
+ Inspect it by hand: the scope guard's boundaries come from here, and a silently
67
+ regenerated state file means an unbounded implementer.
@@ -0,0 +1,38 @@
1
+ # Manager
2
+
3
+ The manager is the main session, not a subagent. It orchestrates; it does not
4
+ collect facts itself, and it keeps its own context small so it can stay in the
5
+ task until the end.
6
+
7
+ ## Responsibilities
8
+
9
+ - Understand the request and restate it in one sentence the human can correct.
10
+ - Classify the task: which workflow, which risk tier.
11
+ - Establish scope, and defend it.
12
+ - Choose the stages the tier requires, and the agent for each.
13
+ - Do inline what the pipeline profile leaves inline — in a few lines, recorded
14
+ in the state file — and delegate the rest. In the `solo` profile the
15
+ developer's request and `grep -n` are the context for anything up to T2; a
16
+ subagent is spawned only for what the tier makes mandatory, or on a trigger
17
+ from `policies/risk-tiers.json`. Never read logs, test output or large files
18
+ into its own context.
19
+ - Split the work into steps small enough that each one names the files it touches.
20
+ - Track state through `state.py` after every stage. The state file, not the
21
+ conversation, is what survives.
22
+ - Decide when to escalate a model tier, one task at a time, against the triggers
23
+ in `policies/risk-tiers.json`.
24
+ - Write the final summary the human reads.
25
+
26
+ ## What the manager must not do
27
+
28
+ - Skip a stage because the task looks easy. Make it lightweight instead, and
29
+ record that it happened.
30
+ - Expand scope. A discovered problem goes into `project/known-risks.md`.
31
+ - Delegate the conclusion. The synthesis a human reads is written by the session.
32
+ - Commit, push, merge or deploy. The pipeline ends at human approval.
33
+
34
+ ## Implementation
35
+
36
+ The manager implements approved steps itself, under this policy and under
37
+ `ai-scope-guard`. `ai-implementer` exists for mechanical, pattern-copying steps
38
+ and for when the human asks for it — not as the default.
@@ -0,0 +1,27 @@
1
+ # Workflow: feature
2
+
3
+ New behaviour that someone asked for. The default workflow.
4
+
5
+ | Stage | Who | Notes |
6
+ |---|---|---|
7
+ | DISCOVERY | `ai-indexer` then `ai-discovery` | where the feature lands, what it will touch |
8
+ | CONTEXT | `ai-context` | the structured summary everything downstream reads |
9
+ | IMPACT ANALYSIS | `ai-discovery` (second pass) | callers, data, contracts, other environments |
10
+ | RISK CLASSIFICATION | `ai-risk` | one tier, from `policies/risk-tiers.json` |
11
+ | PLAN | `ai-planner` | steps with `allowed_files`; STRONG for T3/T4, `ai-expert` for T5 |
12
+ | PLAN REVIEW | `ai-reviewer` | T3 and above |
13
+ | IMPLEMENTATION | the session, one step at a time | scope-guarded |
14
+ | TEST | `ai-tester` | after every step, not only at the end |
15
+ | ADVERSARIAL REVIEW | `ai-reviewer` | T2 and above |
16
+ | SECURITY REVIEW | `ai-security` | T4, T5, and anything touching auth or personal data |
17
+ | RELEASE REPORT | `ai-release` | full report from T2 up |
18
+ | HUMAN APPROVAL | the human | the pipeline stops here |
19
+
20
+ ## Specific to this workflow
21
+
22
+ - The plan states what stays the same, not only what changes. A feature that
23
+ quietly alters an existing behaviour is the most common source of regressions.
24
+ - New code paths need their negative cases tested: not authorized, not found,
25
+ invalid input, external system down.
26
+ - If the feature needs a new dependency, that is a decision worth its own line in
27
+ the plan.
@@ -0,0 +1,24 @@
1
+ # Directory rules
2
+
3
+ One file per slug, `<slug>.md`, holding the rules that apply to a part of this
4
+ repository and nowhere else. `/rr-setup --update` renders each of them into a
5
+ managed block in the instruction file of every directory it names, so an agent
6
+ working there reads them without anything being loaded for a task that never
7
+ goes near that code.
8
+
9
+ ```markdown
10
+ ---
11
+ dirs: [src/Payment, tests/Payment] # required: where the rules apply
12
+ paths: ["src/Payment/**"] # optional: also a path-scoped rules file
13
+ ---
14
+ # Payment rules
15
+ - Amounts are integer minor units; never a float.
16
+ - A refund never writes to the order; it emits an event.
17
+ ```
18
+
19
+ - `dirs:` is the list of directories whose `CLAUDE.md` / `AGENTS.md` receive the
20
+ block `<!-- riskrails:rule:<slug>:start -->` … `:end`, created if absent.
21
+ Text outside the markers is yours and is never touched.
22
+ - The body is what an agent reads: rules, not rationale. Keep it under a screen.
23
+ - This file is the format, not a rule: no rule ships with the plugin. Delete a
24
+ `<slug>.md` and the next `/rr-setup --update` offers to remove what it rendered.
@@ -0,0 +1,36 @@
1
+ # Workflow: bugfix
2
+
3
+ Something behaves wrongly. The goal is the smallest change that fixes it without
4
+ changing anything else.
5
+
6
+ > Who runs a stage is set by `pipeline_profile` in `policies/risk-tiers.json`.
7
+ > The table names the agent for when a stage is delegated. In the default `solo`
8
+ > profile T0–T3 run in direct mode — the session does every stage itself, in a
9
+ > few lines, with cheap readers and one review (BALANCED at T2; STRONG at T3,
10
+ > whose plan the human approves in plan mode) — and T4+ run the full pipeline
11
+ > with the delegations below.
12
+
13
+ | Stage | Who | Notes |
14
+ |---|---|---|
15
+ | DISCOVERY | `ai-discovery` | reproduce first: find the exact path that produces the symptom |
16
+ | CONTEXT | `ai-context` | include the *correct* behaviour and where it is defined |
17
+ | IMPACT ANALYSIS | `ai-discovery` | who else depends on the current, wrong behaviour |
18
+ | RISK CLASSIFICATION | `ai-risk` | a bug in a payment path is still T4 |
19
+ | PLAN | `ai-planner` | failing test first, then the fix |
20
+ | IMPLEMENTATION | the session | the failing test is its own step |
21
+ | TEST | the session (`ai-tester` in `team`) | the new test is shown failing before the fix; each step runs only its own scoped tests; the full verification command runs once after the last step, to the end, then the e2e suite once; every failure fixed as one batch |
22
+ | ADVERSARIAL REVIEW | `ai-reviewer` | T2 and above |
23
+ | SECURITY REVIEW | `ai-security` | if the bug was a security bug, always |
24
+ | RELEASE REPORT | `ai-release` | |
25
+ | HUMAN APPROVAL | the human | |
26
+
27
+ ## Specific to this workflow
28
+
29
+ - **Write the failing test first.** A bugfix without a test that failed before it
30
+ is a bugfix nobody can prove.
31
+ - Find out *why* the bug exists before fixing it. A bug that is deliberate
32
+ behaviour somebody depends on is not a bug; it is a requirements conflict, and
33
+ it goes back to the human.
34
+ - Resist the urge to fix the surrounding code. Note it, fix the bug.
35
+ - If the same bug exists in three places, fix the one that was reported and list
36
+ the other two in `project/known-risks.md`.
@@ -0,0 +1,33 @@
1
+ # Workflow: investigation
2
+
3
+ A question, not a change. "Why does this happen?", "where is this handled?",
4
+ "can we do X?". The deliverable is an answer with evidence.
5
+
6
+ > Who runs a stage is set by `pipeline_profile` in `policies/risk-tiers.json`.
7
+ > The table names the agent for when a stage is delegated. In the default `solo`
8
+ > profile T0–T2 run in direct mode — the session does every stage itself, in a
9
+ > few lines, with cheap readers and one `sonnet` review at T2 — and T3+ run the
10
+ > full pipeline with the delegations below.
11
+
12
+ | Stage | Who | Notes |
13
+ |---|---|---|
14
+ | DISCOVERY | `ai-indexer`, then `ai-discovery` in parallel per area | read-only |
15
+ | CONTEXT | `ai-context` | the structured summary is often the deliverable itself |
16
+ | IMPACT ANALYSIS | `ai-discovery` | only if the question is "what would it take to…" |
17
+ | RISK CLASSIFICATION | `ai-risk` | so the answer carries the tier a change would have |
18
+ | REPORT | the session | written by the main session, not delegated |
19
+
20
+ There is no implementation stage. If the investigation concludes that something
21
+ should change, that is a **new task** with its own intent, plan and approval.
22
+
23
+ ## Rules
24
+
25
+ - Nothing is edited. Not a comment, not a formatting fix.
26
+ - Every claim in the answer is labelled and cited: KNOWN FACT with `file:line`,
27
+ INFERENCE with what it rests on, UNKNOWN with what would settle it.
28
+ - Contradictions between documentation and code are reported as both, not
29
+ resolved by preference.
30
+ - Findings worth acting on go into `project/known-risks.md` so the next task can
31
+ see them.
32
+ - Say what you could not determine. An investigation that hides its gaps is worse
33
+ than one that admits them.
@@ -0,0 +1,34 @@
1
+ # Workflow: bugfix
2
+
3
+ Something behaves wrongly. The goal is the smallest change that fixes it without
4
+ changing anything else.
5
+
6
+ > Who runs a stage is set by `pipeline_profile` in `policies/risk-tiers.json`.
7
+ > The table names the agent for when a stage is delegated; in the default `solo`
8
+ > profile the session does the stage inline up to the tier where the profile
9
+ > delegates it.
10
+
11
+ | Stage | Who | Notes |
12
+ |---|---|---|
13
+ | DISCOVERY | `ai-discovery` | reproduce first: find the exact path that produces the symptom |
14
+ | CONTEXT | `ai-context` | include the *correct* behaviour and where it is defined |
15
+ | IMPACT ANALYSIS | `ai-discovery` | who else depends on the current, wrong behaviour |
16
+ | RISK CLASSIFICATION | `ai-risk` | a bug in a payment path is still T4 |
17
+ | PLAN | `ai-planner` | failing test first, then the fix |
18
+ | IMPLEMENTATION | the session | the failing test is its own step |
19
+ | TEST | the session (`ai-tester` in `team`) | the new test is shown failing before the fix; the full verification command runs once at the end |
20
+ | ADVERSARIAL REVIEW | `ai-reviewer` | T2 and above |
21
+ | SECURITY REVIEW | `ai-security` | if the bug was a security bug, always |
22
+ | RELEASE REPORT | `ai-release` | |
23
+ | HUMAN APPROVAL | the human | |
24
+
25
+ ## Specific to this workflow
26
+
27
+ - **Write the failing test first.** A bugfix without a test that failed before it
28
+ is a bugfix nobody can prove.
29
+ - Find out *why* the bug exists before fixing it. A bug that is deliberate
30
+ behaviour somebody depends on is not a bug; it is a requirements conflict, and
31
+ it goes back to the human.
32
+ - Resist the urge to fix the surrounding code. Note it, fix the bug.
33
+ - If the same bug exists in three places, fix the one that was reported and list
34
+ the other two in `project/known-risks.md`.
@@ -0,0 +1,34 @@
1
+ # Workflow: feature
2
+
3
+ New behaviour that someone asked for. The default workflow.
4
+
5
+ > Who runs a stage is set by `pipeline_profile` in `policies/risk-tiers.json`.
6
+ > The table names the agent for when a stage is delegated. In the default `solo`
7
+ > profile T0–T3 run in direct mode — the session does every stage itself, in a
8
+ > few lines, with cheap readers and one review (BALANCED at T2; STRONG at T3,
9
+ > whose plan the human approves in plan mode) — and T4+ run the full pipeline
10
+ > with the delegations below.
11
+
12
+ | Stage | Who | Notes |
13
+ |---|---|---|
14
+ | DISCOVERY | `ai-indexer` then `ai-discovery` | where the feature lands, what it will touch |
15
+ | CONTEXT | `ai-context` | the structured summary everything downstream reads |
16
+ | IMPACT ANALYSIS | `ai-discovery` (second pass) | callers, data, contracts, other environments |
17
+ | RISK CLASSIFICATION | `ai-risk` | one tier, from `policies/risk-tiers.json` |
18
+ | PLAN | none at T0/T1; the session at T2, in plan mode at T3; `ai-planner` from T4 | steps with `allowed_files`; STRONG for T4, `ai-expert` for T5 |
19
+ | PLAN REVIEW | the human at T3 (plan mode); `ai-reviewer` from T4 | |
20
+ | IMPLEMENTATION | the session, one step at a time | scope-guarded |
21
+ | TEST | the session (`ai-tester` in `team`) | per step, only that step's tests; the full suite once after the last step, to the end, then the e2e suite once at the end of the task; every failure fixed as one batch, then one more run |
22
+ | ADVERSARIAL REVIEW | `ai-reviewer` | T2 and above |
23
+ | SECURITY REVIEW | `ai-security` | T4, T5, and anything touching auth or personal data |
24
+ | RELEASE REPORT | `ai-release` | full report from T2 up |
25
+ | HUMAN APPROVAL | the human | the pipeline stops here |
26
+
27
+ ## Specific to this workflow
28
+
29
+ - The plan states what stays the same, not only what changes. A feature that
30
+ quietly alters an existing behaviour is the most common source of regressions.
31
+ - New code paths need their negative cases tested: not authorized, not found,
32
+ invalid input, external system down.
33
+ - If the feature needs a new dependency, that is a decision worth its own line in
34
+ the plan.
@@ -0,0 +1,48 @@
1
+ # Manager
2
+
3
+ The manager is the main session, not a subagent. It orchestrates; it does not
4
+ collect facts itself, and it keeps its own context small so it can stay in the
5
+ task until the end.
6
+
7
+ The role is the same whichever runtime the session is: Claude Code or Codex. The
8
+ agents it delegates to carry the same names in both, and the tier each runs at is
9
+ the same; only the model behind that tier differs.
10
+
11
+ ## Responsibilities
12
+
13
+ - Understand the request and restate it in one sentence the human can correct.
14
+ - Classify the task: which workflow, which risk tier.
15
+ - Establish scope, and defend it.
16
+ - Choose the stages the tier requires, and the agent for each.
17
+ - Do inline what the pipeline profile leaves inline — in a few lines — and
18
+ delegate the rest. In the `solo` profile T0–T2 are direct mode: the
19
+ developer's request and `grep -n` are the context, the plan is a few lines in
20
+ the conversation, and a subagent is spawned only as a cheap reader, for the
21
+ one `sonnet` review at T2, or on a trigger from `policies/risk-tiers.json`.
22
+ From T3 the full pipeline runs, stage by stage. Never read logs, test output
23
+ or large files into its own context.
24
+ - Run the tests once, to the end, and fix every failure as one batch in a
25
+ `state.py remediate` step. One failure never restarts the task.
26
+ - Split the work into steps small enough that each one names the files it touches.
27
+ - Track state through `state.py` after every stage. The state file, not the
28
+ conversation, is what survives.
29
+ - Decide when to escalate a model tier, one task at a time, against the triggers
30
+ in `policies/risk-tiers.json`, and name the trigger when it does.
31
+ - Record, in every artifact, the tier **and the model that actually ran** — see
32
+ `policies/model-routing.md`. A gate may have moved an agent down a tier, and a
33
+ Codex agent file may override the model asked for at spawn time.
34
+ - Write the final summary the human reads.
35
+
36
+ ## What the manager must not do
37
+
38
+ - Skip a stage because the task looks easy. Make it lightweight instead, and
39
+ record that it happened.
40
+ - Expand scope. A discovered problem goes into `project/known-risks.md`.
41
+ - Delegate the conclusion. The synthesis a human reads is written by the session.
42
+ - Commit, push, merge or deploy. The pipeline ends at human approval.
43
+
44
+ ## Implementation
45
+
46
+ The manager implements approved steps itself, under this policy and under
47
+ `ai-scope-guard`. `ai-implementer` exists for mechanical, pattern-copying steps
48
+ and for when the human asks for it — not as the default.
@@ -11,7 +11,8 @@
11
11
  "54eefe3d8cd6cd1ed56764e7bd412a4c919a28fc64b56b69dcafeecd7a921678",
12
12
  "fe513647c66e8883b326ea884a7e9cb045ce54c49b03d2e75a0b73c4756c423e",
13
13
  "8b3ef9586491a426767c01da5d01bdd6b0655c576c68c4cc6dfb093367817dc0",
14
- "774b1e3a04ef0d49d33c44a2cfecd92eb6f6b738a12b6a681103ba7fc13e7b86"
14
+ "774b1e3a04ef0d49d33c44a2cfecd92eb6f6b738a12b6a681103ba7fc13e7b86",
15
+ "7bae90789625d6fb9071ecb412d14a8d1eb0bc5659d8d284c4eaf213e1b5de56"
15
16
  ],
16
17
  "ai-init/.ai/VERSION": [
17
18
  "4355a46b19d348dc2f57c046f8ef63d4538ebb936000f3c9ee954a27460dd865",
@@ -23,7 +24,8 @@
23
24
  "10159baf262b43a92d95db59dae1f72c645127301661e0a3ce4e38b295a97c58",
24
25
  "aa67a169b0bba217aa0aa88a65346920c84c42447c36ba5f7ea65f422c1fe5d8",
25
26
  "917df3320d778ddbaa5c5c7742bc4046bf803c36ed2b050f30844ed206783469",
26
- "25d4f2a86deb5e2574bb3210b67bb24fcc4afb19f93a7b65a057daa874a9d18e"
27
+ "25d4f2a86deb5e2574bb3210b67bb24fcc4afb19f93a7b65a057daa874a9d18e",
28
+ "a1fb50e6c86fae1679ef3351296fd6713411a08cf8dd1790a4fd05fae8688164"
27
29
  ],
28
30
  "ai-init/.ai/agents/context.md": [
29
31
  "a213099429aff491b00e885c8d556465be2405072efbb9a3a297890a15a5b4ca",
@@ -169,7 +171,8 @@
169
171
  "ae9a22907ba9acbb7e80fac1ba4e3d1ff09e5f1df5c4456afb9099d7090fcaa6",
170
172
  "fae3064e648cdc55be4aeb1177525b302a5e34ebd752e4a904f47dc0f4557b96",
171
173
  "e9adb7a9905eb719ac78ab96671f055da53e5001810f5ad6d6c94306b0323fe7",
172
- "ae5ce131d6bae401199ff32d8c3dc4d8aec188010a9111624ac64506e2116ff4"
174
+ "ae5ce131d6bae401199ff32d8c3dc4d8aec188010a9111624ac64506e2116ff4",
175
+ "8ec171f0fbdf38cc6996d496f01491fd1f21f04a435a118ad979b127a8be06f1"
173
176
  ],
174
177
  "ai-init/.ai/policies/security.md": [
175
178
  "cc808d5b940109f1703abfb3ca0334a3fcfd34267feefb2323627d0decc8b89a",
@@ -177,7 +180,8 @@
177
180
  "4e67b352e2d7a29a83c4fa9f80a0d3ed9272da0f976a084c344b55e349f741b2",
178
181
  "1fdc406be22d9ea39f41e738c6bbd36a31ef4adc84ece06cfceebddaa86c9798",
179
182
  "1a8995e5f7e51b5be74fca82551e5d9e4d970c546d9fd6eecb6809a7f6af8821",
180
- "6a3be0e624e5ad91e44d08857b7183ee53b7903e1e8d56ff196dbc9dde271e4a"
183
+ "6a3be0e624e5ad91e44d08857b7183ee53b7903e1e8d56ff196dbc9dde271e4a",
184
+ "7224ede803ea81e65a456e21b6028a0e848e8a880456c6503eebe7534ca4f6aa"
181
185
  ],
182
186
  "ai-init/.ai/policies/testing.md": [
183
187
  "930ccfac4ba1306341e32279278410b451246a52223c42e0597b5ee83706ff00",
@@ -187,21 +191,31 @@
187
191
  "3a492555cac3198136e239539466fb768cf672d5a972f5afd7d57c038d3cfed6",
188
192
  "8ad13d2ca4504cfd8e4ab7fe3a49129b228d9979461f0f758a71daeec78b6ae1",
189
193
  "0ef4a360c76da290173dea0f8073949cb0f8113710a38df95acae5d96bdd1286",
190
- "00289f98434fed230eebe768dfb3425f83d737866a3aebc97aa95167c4fa0c6e"
194
+ "00289f98434fed230eebe768dfb3425f83d737866a3aebc97aa95167c4fa0c6e",
195
+ "4c45aee9b9fc5f6b4e1d9739e434c4094975a5a8dec6b9703fb25f3080680c77"
191
196
  ],
192
197
  "ai-init/.ai/policies/tooling.md": [
193
198
  "2c6afb3518714d35eaf0119bf2ae2154782bbece632dfdbd68988351abde61f5"
194
199
  ],
200
+ "ai-init/.ai/policies/verification.md": [
201
+ "3918b4ee011d9477b9d2779e2893ab599749c406d4b09439a9748b64fbff58f3"
202
+ ],
195
203
  "ai-init/.ai/policies/weight.json": [
196
204
  "7f3859c34035fe32abf937eebdd7240ac72ab32d254286cff7d939cf0cf6eaef",
197
- "5353ca529c46f2443e12947ec205a6887fb594a4de1f87f0eb1c0e6c0f826133"
205
+ "5353ca529c46f2443e12947ec205a6887fb594a4de1f87f0eb1c0e6c0f826133",
206
+ "6d6dee8634abf9ac057bb206828b83a893a2afcf4f86bbe69e839a3b47d0adde"
198
207
  ],
199
208
  "ai-init/.ai/policies/weight.md": [
200
209
  "e639e99d3f59015dc21472de081ca7766231135399ac3a6f439e841e458251f4",
201
- "5f65bc7ab3fc3c4e75ae05d49eaf4331fafc398c661abe33c69f7380a720344c"
210
+ "5f65bc7ab3fc3c4e75ae05d49eaf4331fafc398c661abe33c69f7380a720344c",
211
+ "c4dbeb180292a6199ad73a3be861ece07c1f8bf6bf0cc7ca204412bc8e1bb1d8"
212
+ ],
213
+ "ai-init/.ai/policies/weight.project.json": [
214
+ "7f834103e9d97aea44e76717bcdcbbe349c560e5b81a42ce85a1cec341041281"
202
215
  ],
203
216
  "ai-init/.ai/project/architecture.md": [
204
- "5cbaaabe2c8d0e24582877aab05eeaaf4d53cb5e9515e81cd18368d13d2fe79e"
217
+ "5cbaaabe2c8d0e24582877aab05eeaaf4d53cb5e9515e81cd18368d13d2fe79e",
218
+ "449273200dfec2a56885c881ff34d40e8ecc00da53c24c2d09b7fbeb1004d255"
205
219
  ],
206
220
  "ai-init/.ai/project/business-rules.md": [
207
221
  "ab13c708e91c1de2adbc9ccdb1caec5c320197708bcaaa6d5cfd30c18a7dac34"
@@ -213,7 +227,8 @@
213
227
  "d9abea96dbe584fd77c27d5ed0523eb20d048f2d146e4909d16b2a7948db38c5"
214
228
  ],
215
229
  "ai-init/.ai/project/initial-assessment.md": [
216
- "6af1b12f814384e517e8f09131b0524930ac1c849350db765d8a77c7a59905b9"
230
+ "6af1b12f814384e517e8f09131b0524930ac1c849350db765d8a77c7a59905b9",
231
+ "ba14a457e83f9dde65e4190fdfab83b912f7398c1442a2a1cb3d89bfac741cf3"
217
232
  ],
218
233
  "ai-init/.ai/project/integrations.md": [
219
234
  "1c2c3e5bbb132a152163ebeb678d57f0f7162a56ea92b84acc43cd2dedd4a935"
@@ -228,14 +243,16 @@
228
243
  "ab0ce5062b41aaff12b0525d56b42de6b9dee9ce9e1de2938f72675435013c6a"
229
244
  ],
230
245
  "ai-init/.ai/project/overview.md": [
231
- "53376d1fca268d8fdb59a5a0d0e0a4fe2d3bc2a7689a79c00a227f41bd5a2165"
246
+ "53376d1fca268d8fdb59a5a0d0e0a4fe2d3bc2a7689a79c00a227f41bd5a2165",
247
+ "6221b7c14cc04634e485e562d464c6860d45666a7f63e293c06bb2944ff556cc"
232
248
  ],
233
249
  "ai-init/.ai/reports/.gitkeep": [
234
250
  "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
235
251
  ],
236
252
  "ai-init/.ai/rules/README.md": [
237
253
  "a1ed0b4f3b73b1a29adfdf0d4d495553ba48707aa5a676496ebc28f993a57dcb",
238
- "ae49c96abe45e56e88ae5e28e046212f7114d6413785cbe998f692d2914792be"
254
+ "ae49c96abe45e56e88ae5e28e046212f7114d6413785cbe998f692d2914792be",
255
+ "e504529519a371892838725f8b89b5d32e3300e345bcbf2643a3a1a48434b3dd"
239
256
  ],
240
257
  "ai-init/.ai/state/README.md": [
241
258
  "30b6dcbdcfbb8e9223af11edacc387b1102868261bbe7051c2d85ad1a18384e5",
@@ -245,7 +262,8 @@
245
262
  "19b1a6390e96136619d23bc2ef9afed8f15e62107de7c1052bc5ea23e5bb5692",
246
263
  "23a42febbacaa7b52a802d428033a99c0694391c81d51fe3b6e1dff608a641d5",
247
264
  "7ee99edafe7cec45ff577376c0d0178fdb2690134d4656488f46e129aba3cc5a",
248
- "a51517e13e57420d2d88a6bcfb4055d762d4a0d10a8f88450929c5c4572213a9"
265
+ "a51517e13e57420d2d88a6bcfb4055d762d4a0d10a8f88450929c5c4572213a9",
266
+ "d97f46a2cca020406252b1f7baa4184617fa71faca3885e2379c44ae4e1d9327"
249
267
  ],
250
268
  "ai-init/.ai/templates/architecture-decision.md": [
251
269
  "78619b522826ba8f5f0422e9deb7359c8002553d1aeb29a3719da5ab11ff13a1"
@@ -270,7 +288,8 @@
270
288
  ],
271
289
  "ai-init/.ai/using-riskrails.md": [
272
290
  "03282999978b2bfb5f65135e1884f9447f8a71021a88895d5436d377797b9acb",
273
- "25d08ff01a4ab2069b0dd4e5ec52e888d33e00091dc467dd10d63f10223b6f80"
291
+ "25d08ff01a4ab2069b0dd4e5ec52e888d33e00091dc467dd10d63f10223b6f80",
292
+ "5c0fac98aeef1bf9882f827f1a5ea72d602712d6ad5c5e628131bb9c164e276b"
274
293
  ],
275
294
  "ai-init/.ai/workflows.md": [
276
295
  "500d93714106b1c4e21b13f248f7175c86073a9bcb6e0a849845f61f49b5a66d"
@@ -410,7 +429,8 @@
410
429
  "project-init/constitution.md": [
411
430
  "5e38d93c4f82300cc5d331f4ce3022d2872db15d108ae23bf33e2169a19b42f2",
412
431
  "7be527cd648b27cca6e267de30f8e33a2ce17d5631a82694f23ae5c0623efe1f",
413
- "18c7a2753ce9cb6f6d3d1e9d5d1125d75950b879d56b7325225b200869631b29"
432
+ "18c7a2753ce9cb6f6d3d1e9d5d1125d75950b879d56b7325225b200869631b29",
433
+ "1f44e1a236233dcbab58064f39b69f798b35d1d9a29f8c615b5b12854ce633cb"
414
434
  ],
415
435
  "project-init/gitignore.snippet": [
416
436
  "965a03be82000866cb5275acda18ebb2172c9a50f0011df2fa475f74a1124c35",
@@ -47,14 +47,10 @@ PLACEHOLDER_RE = re.compile(r"\{\{([A-Z_]+)\}\}")
47
47
  # share a file and the text around them stays the project's.
48
48
  RULE_START = "<!-- riskrails:rule:%s:start -->"
49
49
  RULE_END = "<!-- riskrails:rule:%s:end -->"
50
- # R35: the spelling before 3.4b, read for one version and rewritten on the next
51
- # splice or strip, so a project never carries both for one slug.
52
- LEGACY_RULE_START = "<!-- claude-agentic:rule:%s:start -->"
53
- LEGACY_RULE_END = "<!-- claude-agentic:rule:%s:end -->"
54
50
  RULE_MARKER_RE = re.compile(
55
- r"<!--\s*(?:riskrails|claude-agentic):rule:(?P<slug>[a-z0-9][a-z0-9-]*):start\s*-->"
51
+ r"<!--\s*riskrails:rule:(?P<slug>[a-z0-9][a-z0-9-]*):start\s*-->"
56
52
  )
57
- RULE_GENERATED = ("<!-- generated from .ai/rules/%s.md by /project-update"
53
+ RULE_GENERATED = ("<!-- generated from .ai/rules/%s.md by /rr-setup --update"
58
54
  " \u2014 edit that file -->")
59
55
  SLUG_RE = re.compile(r"^[a-z0-9][a-z0-9-]*$")
60
56
  FRONTMATTER_RE = re.compile(r"\A---[ \t]*\n(?P<body>.*?)\n---[ \t]*(\n|\Z)", re.S)
@@ -417,18 +413,16 @@ def rule_targets(rules, runtimes):
417
413
 
418
414
 
419
415
  def _rule_span(text, slug):
420
- """(start, end) of the rule block of this slug — end past its end marker —
421
- under the current markers, else under the legacy ones, else None."""
422
- for start_marker, end_marker in ((RULE_START, RULE_END), (LEGACY_RULE_START, LEGACY_RULE_END)):
423
- start, end = text.find(start_marker % slug), text.find(end_marker % slug)
424
- if start >= 0 and end >= 0:
425
- return start, end + len(end_marker % slug)
416
+ """(start, end) of the rule block of this slug — end past its end marker — or None."""
417
+ start, end = text.find(RULE_START % slug), text.find(RULE_END % slug)
418
+ if start >= 0 and end >= 0:
419
+ return start, end + len(RULE_END % slug)
426
420
  return None
427
421
 
428
422
 
429
423
  def splice_rule(text, slug, block):
430
424
  """Put one rule block into a file, replacing the block of that slug if it is
431
- already there (a legacy-marked one included). Everything outside the
425
+ already there. Everything outside the
432
426
  markers is the project's and is returned untouched."""
433
427
  span = _rule_span(text, slug)
434
428
  if span is None:
@@ -454,50 +448,23 @@ def rule_slugs_in(text):
454
448
  return [m.group("slug") for m in RULE_MARKER_RE.finditer(text)]
455
449
 
456
450
 
457
- # A marker pair an older or hand-written instruction file may carry instead of
458
- # BLOCK_START/BLOCK_END. Every lookup goes through find_block, so a legacy pair
459
- # is read as the managed block everywhere — measured, merged, renamed — and
460
- # never has a second block appended beside it.
461
- LEGACY_MARKER_RE = re.compile(r"<!-- (?P<name>claude-agentic|[Cc]odex-agentic):start -->")
462
- _LEGACY_MARKER_RE_B = re.compile(LEGACY_MARKER_RE.pattern.encode())
463
-
464
-
465
451
  def find_block(text):
466
452
  """(start, end, start_marker, end_marker) of the managed block in text —
467
- end is past the end marker — or None. The current pair wins; a legacy
468
- pair counts only when both of its markers are there, in order. Works on
453
+ end is past the end marker — or None. Half a pair is none. Works on
469
454
  str and on bytes alike, offsets in the caller's own units."""
470
455
  if isinstance(text, bytes):
471
- start, end, legacy, colon = BLOCK_START.encode(), BLOCK_END.encode(), _LEGACY_MARKER_RE_B, b":"
456
+ start, end = BLOCK_START.encode(), BLOCK_END.encode()
472
457
  else:
473
- start, end, legacy, colon = BLOCK_START, BLOCK_END, LEGACY_MARKER_RE, ":"
458
+ start, end = BLOCK_START, BLOCK_END
474
459
  s, e = text.find(start), text.find(end)
475
460
  if s >= 0 and e >= 0:
476
461
  return s, e + len(end), start, end
477
- if s >= 0 or e >= 0:
478
- return None # half a current pair: a broken file, not a legacy one
479
- m = legacy.search(text)
480
- if m is None:
481
- return None
482
- end_marker = m.group(0).replace(colon + start[start.rfind(colon) + 1:], colon + end[end.rfind(colon) + 1:])
483
- e = text.find(end_marker, m.end())
484
- if e < 0:
485
- return None
486
- return m.start(), e + len(end_marker), m.group(0), end_marker
487
-
488
-
489
- def current_markers(block, start_marker, end_marker):
490
- """The block with its markers renamed to the current pair; a no-op for a
491
- block that already carries them."""
492
- if isinstance(block, bytes):
493
- return block.replace(start_marker, BLOCK_START.encode()).replace(end_marker, BLOCK_END.encode())
494
- return block.replace(start_marker, BLOCK_START).replace(end_marker, BLOCK_END)
462
+ return None
495
463
 
496
464
 
497
465
  def block_of(text):
498
466
  """The managed block of an instruction file, markers included, or None —
499
- the verbatim slice, so a caller can `replace` it; a legacy pair keeps its
500
- own markers here (see current_markers)."""
467
+ the verbatim slice, so a caller can `replace` it."""
501
468
  found = find_block(text)
502
469
  if found is None:
503
470
  return None