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
@@ -5,7 +5,7 @@
5
5
  },
6
6
  "metadata": {
7
7
  "description": "A weight-based engineering pipeline for Claude Code and Codex: each change is weighed on six axes, runs light, guarded or full, edits only the files its plan names, and ends at human approval — enforced by hooks, reviewed adversarially, routed to the cheap model tier by default.",
8
- "version": "3.2.2"
8
+ "version": "4.1.0"
9
9
  },
10
10
  "plugins": [
11
11
  {
@@ -14,7 +14,7 @@
14
14
  "source": "url",
15
15
  "url": "https://github.com/vanssata/claude-agentic-sdlc-module.git"
16
16
  },
17
- "version": "3.2.2",
17
+ "version": "4.1.0",
18
18
  "strict": true
19
19
  }
20
20
  ]
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "riskrails",
3
- "version": "3.2.2",
3
+ "version": "4.1.0",
4
4
  "description": "A weight-based engineering pipeline for Claude Code and Codex: each change is weighed on six axes, runs light, guarded or full, edits only the files its plan names, and ends at human approval — enforced by hooks, reviewed adversarially, routed to the cheap model tier by default.",
5
5
  "author": {
6
6
  "name": "Ivan Kakurov"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "riskrails",
3
- "version": "3.2.2",
3
+ "version": "4.1.0",
4
4
  "description": "A weight-based engineering pipeline for Claude Code and Codex: each change is weighed on six axes, runs light, guarded or full, edits only the files its plan names, and ends at human approval — enforced by hooks, reviewed adversarially, routed to the cheap model tier by default.",
5
5
  "author": {
6
6
  "name": "Ivan Kakurov"
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # RiskRails
2
2
 
3
- [![Version](https://img.shields.io/badge/version-3.2.2-d2f878?labelColor=101210)](https://github.com/vanssata/claude-agentic-sdlc-module/releases/tag/v3.2.2)
3
+ [![Version](https://img.shields.io/badge/version-4.1.0-d2f878?labelColor=101210)](https://github.com/vanssata/claude-agentic-sdlc-module/releases/tag/v4.1.0)
4
4
  [![Runtimes](https://img.shields.io/badge/runtimes-Claude%20Code%20%7C%20Codex-d2f878?labelColor=101210)](docs/routing.md)
5
5
  [![Known risks](https://img.shields.io/badge/known%20risks-documented-d2f878?labelColor=101210)](docs/known-risks.md)
6
6
  [![License: MIT](https://img.shields.io/badge/license-MIT-d2f878?labelColor=101210)](LICENSE)
@@ -18,7 +18,7 @@ approval. Risky actions are stopped by a hook, not by a polite request in a
18
18
  prompt.
19
19
 
20
20
  ```bash
21
- npx riskrails@3.2.2 # detects Claude Code, Codex or both (Node 18+, Python 3.11+)
21
+ npx riskrails@4.1.0 # detects Claude Code, Codex or both (Node 18+, Python 3.11+)
22
22
  ```
23
23
 
24
24
  Then, in any project: `/rr-setup` once, and `/rr-build <what you want>` for
@@ -50,86 +50,58 @@ Tuned for **one developer who knows the codebase**, on a Claude Pro, Max or
50
50
  Team plan, or a ChatGPT Plus or Pro plan, following the
51
51
  [AI-native SDLC playbook](https://claude.com/blog/the-ai-native-sdlc-playbook).
52
52
 
53
- **Version 3.2.2.** The guards have limits: read [Known risks](docs/known-risks.md)
53
+ **Version 4.1.0.** The guards have limits: read [Known risks](docs/known-risks.md)
54
54
  before relying on them. What is decided but not built is in [ROADMAP.md](ROADMAP.md).
55
55
 
56
- ## Upgrade to 3.1
57
-
58
- From 3.0.x: update the home (`npx riskrails@3.2.2`, restart the runtime), then
59
- in each project `/rr-setup --update` (dry run first, then `--apply`). Schema 10
60
- becomes **11**: migration `0011` proposes deleting `.ai/policies/risk-tiers.json`
61
- and `risk-tiers.md`, which `weight.json` and `weight.md` replaced; confirm with
62
- `--apply --confirm-delete <name>` in a terminal of your own. The update now
63
- renders `weight.md` from `weight.json` instead of merging it, reads the
64
- `docs/sdlc/*/TEMPLATE.md` files from the plugin (an unedited project copy is
65
- offered for deletion), and proposes cleanup of old run logs and stale tasks.
66
- See [CHANGELOG.md](CHANGELOG.md).
67
-
68
- ## Upgrade to 3.0
69
-
70
- 3.0 renames the plugin from `claude-agentic` to `riskrails`, replaces the risk
71
- tiers with the weight and the three modes, replaces the `/ai-*` and `/sdlc-*`
72
- commands with `/rr-*`, ports the guards to one Python process, and moves the
73
- task state to `.ai/state/state.json`. The old names stay as aliases for this
74
- version. Step by step, in this order:
75
-
76
- 1. **Commit every project's `.ai/`** before anything else; the update tells you
77
- when the tree is dirty, and `git restore` is the rollback.
78
- 2. **Close or abandon tasks in flight.** A task started by 2.x is refused by
79
- the new commands as `old surface`; finish it with the version that started
80
- it, or drop it with `python3 ~/.claude/skills/ai-task/state.py close
81
- --abandon`. Check with `/rr-status`.
82
- 3. **Update the home** on every machine, for every runtime:
83
-
84
- ```bash
85
- npx riskrails@3.2.2 # or: npx -y riskrails@latest --yes
86
- ```
87
-
88
- It moves `<home>/claude-agentic/` to `<home>/riskrails/` and leaves a
89
- symlink at the old path for one version, replaces the old hook entries with
90
- `ai-guard.py` and `runtime-gate.py`, retires the old agents and shim files
91
- to `backups/<date>/`, and rewrites the managed block. Restart the runtime.
92
- In Codex, open `/hooks` and **trust the changed entries** — until you do,
93
- nothing is enforced. `--dry-run` shows all of it first.
94
- 4. **Update each project:**
95
-
96
- ```
97
- /rr-setup --update # dry run first; read it; then --apply
98
- ```
99
-
100
- Migrations `0007` to `0010` (and `0011`, see Upgrade to 3.1) run inside the dry run, in order, before the merge:
101
- `0007` creates `.ai/policies/weight.json`, carrying over the project's
102
- edits to its risk-tier table; `0008` renames the managed-block markers and
103
- the router's routes; `0009` moves `current.json` to `state.json`; `0010`
104
- creates `.ai/policies/dialog.json` with the dialog on. Edited markdown is
105
- three-way merged, JSON policies key by key with a confirmation per key;
106
- `delete?` proposals are left for you to confirm. The schema becomes 10 with a 3.0 plugin, 11 with 3.1.
107
- 5. **Decide two things the migrations cannot.** Keep the dialog (then amend
108
- constitution C5 as `0010` hints) or set `"enabled": false`; and tune the
109
- weight table — `domain.modules`, `customer_visible`, `hot_paths`,
110
- `needs_step`, `irreversible` — then `state.py weight --mirror`.
111
- 6. **Verify**: `/rr-status` shows schema 11 and no task in flight; a
112
- `/rr-build` on a small change runs light and closes on the two facts.
113
- Commit `.ai/`.
114
-
115
- Every machine of a team upgrades the plugin before a project at schema 11 is
116
- committed; an older plugin refuses such a project. Rollback and the full
117
- migration table are in [docs/project-update.md](docs/project-update.md); the
118
- home-side details in [docs/installation.md](docs/installation.md).
56
+ ## Upgrade to 4.0
57
+
58
+ 4.0 converts nothing any more: the one-version fallbacks, the migrations and
59
+ the adopt command are gone, and `/rr-setup --update` regenerates a project's files from
60
+ the plugin. Step by step, in this order:
61
+
62
+ 1. **Come from 3.1.0 or later.** 4.0 refuses a tree that still holds an old
63
+ shape it detects, naming the file, and regenerates any other older tree
64
+ without the conversions it missed. So a project last updated by an older
65
+ riskrails goes through the version that still converts it: install it
66
+ (`npx riskrails@3.1.0`), run `/rr-setup --update` with it, then install 4.0.
67
+ 2. **Commit every project's `.ai/`** first; `git restore` is the rollback.
68
+ 3. **Update the home** on every machine, for every runtime: `npx riskrails@4.1.0`
69
+ (the plugin route and the npm route are separate installs: reinstall both
70
+ if you use both). Restart the runtime. In Codex, open `/hooks` and trust the
71
+ changed entries.
72
+ 4. **Run `/rr-setup --update` in each project right away.** Until you do, the
73
+ project's old shapes are not read: the weight lacks its `domain.modules`, no
74
+ `verify_command` is found, and a task in the old state file is not scope-guarded.
75
+ Dry run first, then `--apply`; a `regenerate?` or `delete?` row is confirmed
76
+ by you in a terminal of your own.
77
+ 5. **Check**: `/rr-status` shows schema 12 and no task in flight.
78
+
79
+ The alias commands (the `/ai-*`, `/sdlc-*`, `/project-*` and usage-report names)
80
+ are removed; use the `/rr-*` commands. Details are in
81
+ [docs/project-update.md](docs/project-update.md), the home-side ones in
82
+ [docs/installation.md](docs/installation.md).
119
83
 
120
84
  ## Install
121
85
 
122
86
  ```bash
123
- npx riskrails@3.2.2 # detects Claude Code, Codex, or both; proposes the detected plan
124
- npx riskrails@3.2.2 --target codex # auto | claude | codex | both
125
- npx riskrails@3.2.2 --plan max --fable no # pro | team-pro | team-max | max | max20 | balanced-max
126
- npx riskrails@3.2.2 --codex-plan plus # plus | pro | balanced-max
127
- npx riskrails@3.2.2 --context economy # the plan's compaction window; the context guard also blocks
128
- npx riskrails@3.2.2 --statusline own # keep your own statusline command (from 3.2.1; default: the plugin's two-line statusline)
129
- npx riskrails@3.2.2 --dry-run # print what would be written, write nothing
87
+ npx riskrails@4.1.0 # detects Claude Code, Codex, or both; proposes the detected plan
88
+ npx riskrails@4.1.0 --target codex # auto | claude | codex | both
89
+ npx riskrails@4.1.0 --plan max --fable no # pro | team-pro | team-max | max | max20 | balanced-max
90
+ npx riskrails@4.1.0 --codex-plan plus # plus | pro | balanced-max
91
+ npx riskrails@4.1.0 --context economy # the plan's compaction window; the context guard also blocks
92
+ npx riskrails@4.1.0 --statusline own # keep your own statusline command (from 3.2.1; default: the plugin's two-line statusline)
93
+ npx riskrails@4.1.0 --dry-run # print what would be written, write nothing
130
94
  npx -y riskrails@latest --yes # update in place, keeping the recorded plan
131
95
  ```
132
96
 
97
+ On a terminal each question is a menu — runtime, plan, Fable, context,
98
+ statusline, Codex plan — with the proposal highlighted (the detected or
99
+ recorded runtime, plan, statusline and Codex plan; Fable `yes`, context `default`):
100
+ ↑/↓ (or k/j), Home/End or 1–9 to move, Enter to confirm, Esc, q or Ctrl-C to
101
+ stop with nothing written. Enter through every menu installs what detection
102
+ proposes. A flag skips its menu; `--yes` or no terminal asks nothing, and
103
+ `RISKRAILS_MENU=off` (or `TERM=dumb`) brings back the typed plan question.
104
+
133
105
  Pin the version: the hooks it installs see every command an agent runs. It
134
106
  installs the managed block, the plan's settings and limits, the five agents
135
107
  with their tiers baked in, the hooks, the skills, the shared tree at
@@ -145,7 +117,6 @@ The same commands in both runtimes:
145
117
  | You want to | Run |
146
118
  |---|---|
147
119
  | set up `.ai/` in a project, or bring it up to the installed plugin | `/rr-setup`, `/rr-setup --update` |
148
- | move another AI tool's files, or the project's own toolbox, into this layout | `/rr-setup --adopt` |
149
120
  | score the repository against the twelve plays | `/rr-setup --audit` |
150
121
  | turn an idea into intent, requirements and design | `/rr-spec <idea>` |
151
122
  | plan a spec into tasks, or one task into a mode and a start | `/rr-plan <spec or task>` |
@@ -155,10 +126,6 @@ The same commands in both runtimes:
155
126
  | close the task, get the human's approval | `/rr-ship` |
156
127
  | see where the task stands, or what it cost | `/rr-status`, `/rr-status --cost` |
157
128
 
158
- The old names — `/ai-init`, `/ai-task`, `/ai-status`, `/ai-audit`,
159
- `/project-init`, `/project-update`, `/sdlc-intent`, `/sdlc-spec`,
160
- `/sdlc-plan`, `/usage-report` — are aliases for one version.
161
-
162
129
  ### Three modes
163
130
 
164
131
  `state.py weight` scores six axes 0–2 — scope, behaviour, reversibility,
@@ -206,7 +173,8 @@ until it passes. After three failed review passes the next verdict is yours.
206
173
  ### The record
207
174
 
208
175
  A closed task's who, what, how and why travel as a compact record: `state.py
209
- memory enable` (yours, in a terminal) switches a project to packages mode, in
176
+ memory enable` (yours, in a terminal, or as your pick in the `/rr-setup`
177
+ dialog) switches a project to packages mode, in
210
178
  which `close` appends the task's entries to a per-developer batch under
211
179
  `.ai/memory/` and a pre-push hook validates them; `state.py recall --files …`
212
180
  gives an agent what the record holds about the files it is about to touch,
@@ -265,7 +233,6 @@ to do: [docs/known-risks.md](docs/known-risks.md).
265
233
  | Codex facts are observed, not guaranteed | grep the journals for `missed_reroute` after a Codex upgrade |
266
234
  | The dialog switch is read in two places | when the dialog and the terminal disagree, use the terminal |
267
235
  | Budgets and quota are advice, not limits | read the quota with its `stale` field |
268
- | `--adopt` edge cases fail safe, not smoothly | adopt on a committed tree, keep `original/` |
269
236
  | The usage report's parse cache trusts mtime and size | `--no-cache` when a number surprises you |
270
237
 
271
238
  ## Tests
@@ -276,15 +243,14 @@ python3 -I -m unittest discover -s tests -p 'test_*.py' # CI's serial oracl
276
243
  AI_E2E=1 python3 -I -m unittest discover -s tests -p test_end_to_end.py
277
244
  ```
278
245
 
279
- Fifty-nine suites, 1045 tests, about 75 seconds in parallel. The guards against JSON fixtures for both runtimes and a
246
+ Sixty suites, 1217 tests, about 75 seconds in parallel. The guards against JSON fixtures for both runtimes and a
280
247
  golden of 1 341 recorded decisions, byte for byte, with timed cases that hold
281
248
  the hot path under its budget; the state machine, the weight, the batch loop,
282
249
  the dialog contract and the documents rule; the compact record and its
283
250
  pre-push validator; the installer for every plan and `--target`, the Codex
284
251
  agent renderer and the `config.toml` merge against a fixture full of
285
252
  third-party settings; `/rr-setup --update` against projects scaffolded from
286
- the oldest shipped templates and edited by hand; `--adopt` against Spec Kit,
287
- Kiro and Cursor fixtures; and an end-to-end run that installs both runtimes
253
+ the oldest shipped templates and edited by hand; and an end-to-end run that installs both runtimes
288
254
  into scratch directories, drives one task through the guards from Claude and
289
255
  then from Codex, and proves both see the same state. No suite reads or writes
290
256
  the developer's real `~/.claude` or `~/.codex`.
@@ -295,7 +261,7 @@ the developer's real `~/.claude` or `~/.codex`.
295
261
  |---|---|
296
262
  | [docs/getting-started.md](docs/getting-started.md) | the first hour: install, `/rr-setup`, a light and a full task, a batch build, the update, the bill |
297
263
  | [docs/installation.md](docs/installation.md) | every installer option, what it installs per runtime, what loads on every turn, the limits it sets, the 2.x home-side upgrade |
298
- | [docs/project-update.md](docs/project-update.md) | shared versus project-owned files, how a file is updated, the migrations and their rollback, `--adopt` |
264
+ | [docs/project-update.md](docs/project-update.md) | shared versus project-owned files, how a file is regenerated, what is kept, the rollback |
299
265
  | [docs/architecture.md](docs/architecture.md) | how the pieces fit: the installed home, `.ai/`, the pipeline, the state, the hooks, the two adapters |
300
266
  | [docs/weight.md](docs/weight.md) | the six axes, the three modes, what is measured and what is declared, tuning the table |
301
267
  | [docs/workflows.md](docs/workflows.md) | feature, bugfix, refactoring, hotfix, investigation |
@@ -54,7 +54,7 @@ in light and guarded, about 80 in full, then FINDINGS and VERDICT, with
54
54
 
55
55
  ## Boundary
56
56
 
57
- The brief names the task's mode; `.ai/state/state.json` (or the legacy `current.json`) has it otherwise. In
57
+ The brief names the task's mode; `.ai/state/state.json` has it otherwise. In
58
58
  light and guarded mode your inputs are the task goal, the diff, the tests the
59
59
  step names, and the project's own fixture corpus and threat model:
60
60
  `.ai/policies/safety.md`, the guards' `*-defaults.json`, the test fixtures.
@@ -8,7 +8,6 @@ the steps; `policies/` holds the rules; this says which to open.
8
8
  | You want to | Run |
9
9
  |---|---|
10
10
  | set up `.ai/` in a project, or bring it up to the installed plugin | `/rr-setup`, `/rr-setup --update` |
11
- | move another AI tool's files into this layout | `/rr-setup --adopt` |
12
11
  | score the repository against the twelve plays | `/rr-setup --audit` |
13
12
  | turn an idea into intent, requirements and design | `/rr-spec <idea>` |
14
13
  | plan a spec into tasks, or one task into a mode and a start | `/rr-plan <spec or task>` |
@@ -18,8 +17,6 @@ the steps; `policies/` holds the rules; this says which to open.
18
17
  | close the task, get the human's approval | `/rr-ship` |
19
18
  | see where the task stands, or what it cost | `/rr-status`, `/rr-status --cost` |
20
19
 
21
- The old names (`/ai-task`, `/ai-init`, `/sdlc-spec` …) stay one version as aliases.
22
-
23
20
  ## Three modes
24
21
 
25
22
  `state.py weight` scores six axes 0–2 — scope, behaviour, reversibility, domain,
package/bin/menu.js ADDED
@@ -0,0 +1,116 @@
1
+ #!/usr/bin/env node
2
+ // The installer's arrow-key menu (spec interactive-setup-options R2, R7). Node 18+, stdlib only.
3
+ //
4
+ // bin/riskrails.js runs this file as a child, `spawnSync(process.execPath, [menu.js])` with
5
+ // stdio ['inherit', 'pipe', 'inherit'], and passes the menu in RISKRAILS_MENU_SPEC:
6
+ // {"title": "plan", "why": "detected from …", "initial": 0,
7
+ // "items": [{"value": "pro", "label": "pro", "note": "…"}, …]}
8
+ // The child owns the terminal while it runs: raw mode on stdin, the menu drawn on stderr.
9
+ // Enter erases the menu, prints `<title>: <value>` (and ` (<why>)` when the value is the
10
+ // initial one) on stderr, writes the value to stdout, exit 0
11
+ // Ctrl-C/Esc/q erases the menu, exit 130
12
+ // no terminal exit 3, nothing drawn: the parent falls back to its typed prompt
13
+ // Keys: ↑/k ↓/j (stop at the ends), Home/End, 1–9 jump to that row, Enter picks.
14
+ 'use strict';
15
+
16
+ // The key, as readline's keypress event gives it, as one of the reducer's tokens (or null).
17
+ function token(key) {
18
+ if (!key) return null;
19
+ if (key.ctrl && key.name === 'c') return 'abort';
20
+ if (key.ctrl || key.meta) return null;
21
+ const name = key.name || key.sequence;
22
+ if (name === 'up' || name === 'k') return 'up';
23
+ if (name === 'down' || name === 'j') return 'down';
24
+ if (name === 'home' || name === 'end') return name;
25
+ if (name === 'return' || name === 'enter') return 'enter';
26
+ if (name === 'escape' || name === 'q') return 'abort';
27
+ if (/^[1-9]$/.test(String(name))) return String(name);
28
+ return null;
29
+ }
30
+
31
+ // The pure step: {index, count, done} and a token → the next state. done is null, 'pick' or 'abort'.
32
+ function reduce(state, tok) {
33
+ const last = state.count - 1;
34
+ switch (tok) {
35
+ case 'up': return { ...state, index: Math.max(0, state.index - 1) };
36
+ case 'down': return { ...state, index: Math.min(last, state.index + 1) };
37
+ case 'home': return { ...state, index: 0 };
38
+ case 'end': return { ...state, index: last };
39
+ case 'enter': return { ...state, done: 'pick' };
40
+ case 'abort': return { ...state, done: 'abort' };
41
+ default: {
42
+ const n = /^[1-9]$/.test(String(tok)) ? Number(tok) : 0;
43
+ return n >= 1 && n <= state.count ? { ...state, index: n - 1 } : state;
44
+ }
45
+ }
46
+ }
47
+
48
+ // The menu's lines, each cut to the terminal's width: a wrapped line would break the redraw's count.
49
+ function lines(spec, index, columns) {
50
+ const fit = (t) => (columns > 1 && [...t].length > columns - 1 ? [...t].slice(0, columns - 2).join('') + '…' : t);
51
+ const head = `${spec.title}${spec.why ? ` (${spec.why})` : ''} — ↑/↓ to move, Enter to confirm, Esc to abort`;
52
+ const width = Math.max(...spec.items.map((it) => String(it.label).length));
53
+ return [fit(head), ...spec.items.map((it, i) => {
54
+ const mark = i === index ? '❯' : ' ';
55
+ const row = fit(`${mark} ${i + 1}. ${String(it.label).padEnd(width)}${it.note ? ` ${it.note}` : ''}`);
56
+ return i === index ? `\x1b[7m${row}\x1b[0m` : row;
57
+ })];
58
+ }
59
+
60
+ function main() {
61
+ let spec;
62
+ try { spec = JSON.parse(process.env.RISKRAILS_MENU_SPEC || ''); } catch (e) { process.exit(3); }
63
+ if (!spec || !Array.isArray(spec.items) || spec.items.length === 0) process.exit(3);
64
+ const stdin = process.stdin;
65
+ if (!stdin.isTTY || !process.stderr.isTTY) process.exit(3);
66
+ try { stdin.setRawMode(true); } catch (e) { process.exit(3); }
67
+
68
+ const write = (s) => process.stderr.write(s);
69
+ let drawn = 0;
70
+ const erase = () => { if (drawn) write(`\x1b[${drawn}A\r\x1b[J`); drawn = 0; };
71
+ const draw = (index) => {
72
+ erase();
73
+ const shown = lines(spec, index, process.stderr.columns || 0);
74
+ write(shown.join('\n') + '\n');
75
+ drawn = shown.length;
76
+ };
77
+ const restore = () => {
78
+ try { stdin.setRawMode(false); } catch (e) { /* already gone */ }
79
+ stdin.pause();
80
+ write('\x1b[?25h');
81
+ };
82
+ const finish = (code, value) => {
83
+ erase();
84
+ restore();
85
+ if (code === 0) {
86
+ const why = state.index === initial && spec.why ? ` (${spec.why})` : '';
87
+ write(`${spec.title}: ${value}${why}\n`);
88
+ process.stdout.write(value, () => process.exit(0));
89
+ } else {
90
+ process.exit(code);
91
+ }
92
+ };
93
+ for (const sig of ['SIGTERM', 'SIGHUP', 'SIGINT']) process.on(sig, () => finish(130));
94
+
95
+ const initial = Number.isInteger(spec.initial) && spec.initial >= 0 && spec.initial < spec.items.length
96
+ ? spec.initial : 0;
97
+ let state = { index: initial, count: spec.items.length, done: null };
98
+ // A lone Esc: emitKeypressEvents without a readline interface has no escape timeout and would
99
+ // wait for the rest of a sequence. An arrow key arrives as one chunk (ESC [ B), never as ESC alone.
100
+ stdin.on('data', (chunk) => { if (chunk.length === 1 && chunk[0] === 0x1b) finish(130); });
101
+ require('readline').emitKeypressEvents(stdin);
102
+ write('\x1b[?25l');
103
+ draw(state.index);
104
+ stdin.on('keypress', (_str, key) => {
105
+ const tok = token(key);
106
+ if (tok === null) return;
107
+ const next = reduce(state, tok);
108
+ if (next.done === 'pick') { state = next; finish(0, String(spec.items[state.index].value)); return; }
109
+ if (next.done === 'abort') { finish(130); return; }
110
+ if (next.index !== state.index) { state = next; draw(state.index); }
111
+ });
112
+ stdin.resume();
113
+ }
114
+
115
+ module.exports = { reduce, token, lines };
116
+ if (require.main === module) main();