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.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/README.md +50 -84
- package/agents/ai-reviewer.md.tmpl +1 -1
- package/ai/using-riskrails.md +0 -3
- package/bin/menu.js +116 -0
- package/bin/riskrails.js +132 -79
- package/hooks/ai-path-guard-defaults.json +1 -1
- package/hooks/context-guard.py +2 -4
- package/hooks/guard/dialog.py +14 -2
- package/hooks/guard/paths.py +3 -6
- package/hooks/guard/scope.py +1 -3
- package/hooks/runtime-gate.py +18 -58
- package/instructions/routing.md +2 -2
- package/package.json +1 -1
- package/scripts/ai-path +1 -1
- package/scripts/resolve-profile.py +0 -3
- package/skills/ai-audit/templates/ai-sdlc-adoption-plan.md +1 -1
- package/skills/ai-audit/templates/play-scoring-rubric.md +1 -1
- package/skills/ai-init/scaffold-ai.sh +2 -1
- package/skills/ai-init/templates/.ai/AGENTS.md +6 -6
- package/skills/ai-init/templates/.ai/VERSION +1 -1
- package/skills/ai-init/templates/.ai/policies/safety.md +4 -3
- package/skills/ai-init/templates/.ai/policies/security.md +1 -2
- package/skills/ai-init/templates/.ai/policies/testing.md +5 -12
- package/skills/ai-init/templates/.ai/policies/verification.md +18 -0
- package/skills/ai-init/templates/.ai/policies/weight.json +0 -1
- package/skills/ai-init/templates/.ai/policies/weight.md +1 -2
- package/skills/ai-init/templates/.ai/policies/weight.project.json +4 -0
- package/skills/ai-init/templates/.ai/project/architecture.md +1 -1
- package/skills/ai-init/templates/.ai/project/initial-assessment.md +2 -2
- package/skills/ai-init/templates/.ai/project/overview.md +1 -1
- package/skills/ai-init/templates/.ai/rules/README.md +2 -2
- package/skills/ai-init/templates/.ai/state/README.md +1 -1
- package/skills/ai-task/memory_store.py +8 -9
- package/skills/ai-task/rr_state/cli.py +2 -2
- package/skills/ai-task/rr_state/dialog.py +2 -4
- package/skills/ai-task/rr_state/dialog_cmd.py +183 -6
- package/skills/ai-task/rr_state/fs.py +5 -13
- package/skills/ai-task/rr_state/labels.py +14 -2
- package/skills/ai-task/rr_state/memory_cmd.py +7 -4
- package/skills/ai-task/rr_state/profile.py +2 -4
- package/skills/ai-task/rr_state/questions_cmd.py +1 -1
- package/skills/ai-task/rr_state/report.py +3 -4
- package/skills/ai-task/rr_state/runtime.py +1 -1
- package/skills/ai-task/rr_state/start.py +7 -7
- package/skills/ai-task/sensors.py +10 -11
- package/skills/ai-task/state.py +4 -24
- package/skills/ai-task/weight.py +17 -17
- package/skills/ai-task/weight_overlay.py +38 -0
- package/skills/project-init/templates/constitution.md +2 -2
- package/skills/project-update/history/blobs/00f5e27ce2d66e3a1d8b222b013ae8fa1fed32612d91a551e0c661cee3ef9c2d +34 -0
- package/skills/project-update/history/blobs/0a6b1b6dd06a35582b2e9989a1f41c40abc29254b8e482714fcc6f0a7b16c406 +32 -0
- package/skills/project-update/history/blobs/0aeb04b04262683cac6513545683486a73dc473b447bba43b5aaab18403957a6 +34 -0
- package/skills/project-update/history/blobs/0ce913a28996f546f72d570b0e5a376362e993ce4d805bc4aae57d38caa44212 +41 -0
- package/skills/project-update/history/blobs/0ea9e36446b624b73b2a821231b2ee66a357b43d584a5b23da48b3c800855e65 +41 -0
- package/skills/project-update/history/blobs/0fb1d68678a1349195b2e79433bb20174d25874e3bfd0b70410bb4e428b4e4b8 +35 -0
- package/skills/project-update/history/blobs/119b2b9d0f9c647a243540724edac6b29afa020c69aa205797bcfa9eb06bc021 +35 -0
- package/skills/project-update/history/blobs/1d0fe3ee5fb8260ba610942d4bbdfff7410fbe80ed826ac07f32985031dc2b3f +34 -0
- package/skills/project-update/history/blobs/1de9a37ed6402893dcab6e61ddbf15ffd35f15a6d84b18e675a0c5bf4e981f85 +42 -0
- package/skills/project-update/history/blobs/1f44e1a236233dcbab58064f39b69f798b35d1d9a29f8c615b5b12854ce633cb +15 -0
- package/skills/project-update/history/blobs/1f824645299579cbdd8141642ddbb4bca9fd5fe9d3112f036d8221f0811e0abf +40 -0
- package/skills/project-update/history/blobs/235fb88393cfe20dd58b35fe9785cc45baf5ffe21a13d926652d76ec68cea8b7 +35 -0
- package/skills/project-update/history/blobs/3918b4ee011d9477b9d2779e2893ab599749c406d4b09439a9748b64fbff58f3 +18 -0
- package/skills/project-update/history/blobs/449273200dfec2a56885c881ff34d40e8ecc00da53c24c2d09b7fbeb1004d255 +40 -0
- package/skills/project-update/history/blobs/4c45aee9b9fc5f6b4e1d9739e434c4094975a5a8dec6b9703fb25f3080680c77 +124 -0
- package/skills/project-update/history/blobs/4dd3fa12bc45acc8c836ab65d790248ca7504a021bca6677499d17bb3d798ed9 +64 -0
- package/skills/project-update/history/blobs/51e3f15095d7123ea8566b512479ee10a6cb2f336b7352a259a083a887bd7116 +33 -0
- package/skills/project-update/history/blobs/5497a204967bea7dab29079a6e1dfa3d8713b2d2cb294c2779378039f03a55fc +36 -0
- package/skills/project-update/history/blobs/60c4d7e7fde7049d92d84295fc13ca9a91eb2de423be08f093b3ee5d5e817ff8 +64 -0
- package/skills/project-update/history/blobs/6221b7c14cc04634e485e562d464c6860d45666a7f63e293c06bb2944ff556cc +27 -0
- package/skills/project-update/history/blobs/637971cfb844ef4285e2886a4b1c834fb2ed5c46e773adb88c2c147fea626ad3 +33 -0
- package/skills/project-update/history/blobs/65af2282eea2a51fcc27a4acf2c26c727b0961c30e1be13176369200c460c219 +34 -0
- package/skills/project-update/history/blobs/66ecd73e303e7bbc1aa8ee72435d0d10812ff7b2eff0adac59bbf0a303e2cc01 +41 -0
- package/skills/project-update/history/blobs/6a43bf32461b22b87fafe2865529dc04fa66cd00182a2a7598aa071667ca255a +35 -0
- package/skills/project-update/history/blobs/6d6dee8634abf9ac057bb206828b83a893a2afcf4f86bbe69e839a3b47d0adde +48 -0
- package/skills/project-update/history/blobs/7224ede803ea81e65a456e21b6028a0e848e8a880456c6503eebe7534ca4f6aa +74 -0
- package/skills/project-update/history/blobs/765a39a202617096c232017822ae738d37e4405430c71700dc7bc14bf1ba794e +33 -0
- package/skills/project-update/history/blobs/77577440a933d1cabd8c6f4a6401cf361a784aa09a25500a6f7b44ead8ab5e55 +41 -0
- package/skills/project-update/history/blobs/7bae90789625d6fb9071ecb412d14a8d1eb0bc5659d8d284c4eaf213e1b5de56 +67 -0
- package/skills/project-update/history/blobs/7bcdf9a0e6b85277b9b60669150224b9414d2e32821ff06f4d148eb1d18785bb +42 -0
- package/skills/project-update/history/blobs/7f834103e9d97aea44e76717bcdcbbe349c560e5b81a42ce85a1cec341041281 +4 -0
- package/skills/project-update/history/blobs/7fb3acb0211818efebc2234863db0b8c846022a7280a6d2d69f267dbf63db48c +34 -0
- package/skills/project-update/history/blobs/87f0855859ff68cc6c988cc0b631ee7f56af7fbba062172bf80e01f4982cc054 +35 -0
- package/skills/project-update/history/blobs/8abab74759766d02b5cb7b0c3e59a3d440b25a454216cd8fea325c23fd822d36 +33 -0
- package/skills/project-update/history/blobs/8ec171f0fbdf38cc6996d496f01491fd1f21f04a435a118ad979b127a8be06f1 +85 -0
- package/skills/project-update/history/blobs/a1fb50e6c86fae1679ef3351296fd6713411a08cf8dd1790a4fd05fae8688164 +1 -0
- package/skills/project-update/history/blobs/a3df7268feb0780be0d2cf9acced6ed81780a7790f36fe024b6ea0b1bd6eb7a6 +35 -0
- package/skills/project-update/history/blobs/b28721136482dafb9fd2801af340364cb97e9f6eaa987908606c786045b8d334 +28 -0
- package/skills/project-update/history/blobs/b3726422d767f9219fea633bea77f0c99ad9af843c591e6e928e1ccd2a47f374 +27 -0
- package/skills/project-update/history/blobs/b3839425f9d0ab2efa42a6f5e9488ec2d26ca5fb8dcd694b8ab098e10743ca46 +32 -0
- package/skills/project-update/history/blobs/ba14a457e83f9dde65e4190fdfab83b912f7398c1442a2a1cb3d89bfac741cf3 +8 -0
- package/skills/project-update/history/blobs/bceb7189444bb6291b262ca08e34db01010dda2f6e64d696231ec3c343c95c66 +34 -0
- package/skills/project-update/history/blobs/bf82a2bb4fce1bd349ff66118930a01d61a7af8e2bd8d200c721d43afc58c713 +34 -0
- package/skills/project-update/history/blobs/c4dbeb180292a6199ad73a3be861ece07c1f8bf6bf0cc7ca204412bc8e1bb1d8 +31 -0
- package/skills/project-update/history/blobs/c644838866df2001a42501a988dd7b77aacf862bf09d22b465f3cd8a22c6b6eb +33 -0
- package/skills/project-update/history/blobs/c980d74f76a4bdfb38c94b573ac10a54eb50b850b052e15fa6f2442889b36ccb +32 -0
- package/skills/project-update/history/blobs/ceed2f3bd937f862d0e6ca59ce1b1e3603e19a0d7f85d90d6dfeb7bf690153be +29 -0
- package/skills/project-update/history/blobs/d51ea2e893482a20c5882056cf8043327ca1dc1c957927f6746929a47ee8368e +45 -0
- package/skills/project-update/history/blobs/d78f5e0bb1380259fce2cce009785a9a11f6de8b87a160080b9872c059f95060 +34 -0
- package/skills/project-update/history/blobs/d97f46a2cca020406252b1f7baa4184617fa71faca3885e2379c44ae4e1d9327 +67 -0
- package/skills/project-update/history/blobs/da3ecd4c4c414c93d04488685931df39a56bf959bfeb9c45cb1aea2c13bd991b +38 -0
- package/skills/project-update/history/blobs/e129bf71a5a922e24b2c1bc8daa8a5d2b5589b0069770e17ce17e7db5ed4e7a4 +27 -0
- package/skills/project-update/history/blobs/e504529519a371892838725f8b89b5d32e3300e345bcbf2643a3a1a48434b3dd +24 -0
- package/skills/project-update/history/blobs/e9e62d03ca70b3dffccef8dceeb214173352cfef005145e519f0e037993f1c03 +36 -0
- package/skills/project-update/history/blobs/effefbaaf4beb8f1ba55081d6b7e74bf25ebb91045dd10613418f17b95fa7182 +33 -0
- package/skills/project-update/history/blobs/f6af4581bafbf62b257d57e06c3ae2c5998aeca608ee7df037fcc3c3e4b563a9 +34 -0
- package/skills/project-update/history/blobs/fc35045777d29630303430752a651b3e553580a581036a02cc103eb96a46f4b0 +34 -0
- package/skills/project-update/history/blobs/fdc21345c77f92a42d244aa104f393f439a0ff9981a9fd462bd837e8a47931bb +48 -0
- package/skills/project-update/history/index.json +34 -14
- package/skills/project-update/render_instructions.py +12 -45
- package/skills/project-update/update.py +757 -1172
- package/skills/rr-setup/SKILL.md +114 -97
- package/skills/rr-setup/scaffold_ai.py +15 -9
- package/skills/rr-setup/setup.py +462 -164
- package/skills/rr-status/status.py +7 -10
- package/skills/usage-report/usage-report.py +4 -5
- package/skills/ai-audit/SKILL.md +0 -9
- package/skills/ai-init/SKILL.md +0 -9
- package/skills/ai-status/SKILL.md +0 -9
- package/skills/ai-task/SKILL.md +0 -9
- package/skills/project-init/SKILL.md +0 -9
- package/skills/project-update/SKILL.md +0 -9
- package/skills/project-update/adopt-map.json +0 -91
- package/skills/project-update/adopt.py +0 -2225
- package/skills/project-update/migrations/0001_schema_version.py +0 -13
- package/skills/project-update/migrations/0002_task_journal.py +0 -123
- package/skills/project-update/migrations/0003_context_diet.py +0 -65
- package/skills/project-update/migrations/0004_deterministic_gates.py +0 -57
- package/skills/project-update/migrations/0005_runtimes_and_plans.py +0 -35
- package/skills/project-update/migrations/0006_shared_files.py +0 -154
- package/skills/project-update/migrations/0007_weight_model.py +0 -295
- package/skills/project-update/migrations/0008_renames.py +0 -43
- package/skills/project-update/migrations/0009_state_file.py +0 -25
- package/skills/project-update/migrations/0010_dialog_switch.py +0 -30
- package/skills/project-update/migrations/0011_retire_risk_tiers.py +0 -37
- package/skills/project-update/migrations/README.md +0 -76
- package/skills/project-update/migrations/__init__.py +0 -186
- package/skills/sdlc-intent/SKILL.md +0 -9
- package/skills/sdlc-plan/SKILL.md +0 -9
- package/skills/sdlc-spec/SKILL.md +0 -9
- package/skills/usage-report/SKILL.md +0 -10
- /package/{ai/workflows/refactoring.md → skills/project-update/history/blobs/36cb593293496fbcf38df828a9b9b2bc0d5a53333f584a5319ebc3d799016e24} +0 -0
- /package/{ai/workflows/feature.md → skills/project-update/history/blobs/56e16072c2f3edc6c8897c690d09a11d12fc414c3e3f361f359f7dc609a21282} +0 -0
- /package/{ai/workflows/hotfix.md → skills/project-update/history/blobs/8cbefbf1aa412bae3e5019acd40b8fe0598fceba6c781906b3bc6dbd014f6b23} +0 -0
- /package/{ai/workflows/bugfix.md → skills/project-update/history/blobs/af56dc16e44ae1d8c3dac4c3ca82e2163b719553c02ea455e77430bab9a14089} +0 -0
- /package/{ai/workflows/investigation.md → skills/project-update/history/blobs/b9e09cb24958cd6831589997558974bd6356305306e8f9685e226bcdc30d60ac} +0 -0
- /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": "
|
|
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": "
|
|
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
|
+
"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
|
+
"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
|
-
[](https://github.com/vanssata/claude-agentic-sdlc-module/releases/tag/v4.1.0)
|
|
4
4
|
[](docs/routing.md)
|
|
5
5
|
[](docs/known-risks.md)
|
|
6
6
|
[](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@
|
|
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
|
|
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
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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@
|
|
124
|
-
npx riskrails@
|
|
125
|
-
npx riskrails@
|
|
126
|
-
npx riskrails@
|
|
127
|
-
npx riskrails@
|
|
128
|
-
npx riskrails@
|
|
129
|
-
npx riskrails@
|
|
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
|
|
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
|
-
|
|
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;
|
|
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
|
|
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`
|
|
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.
|
package/ai/using-riskrails.md
CHANGED
|
@@ -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();
|