riskrails 3.0.1 → 3.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 +28 -15
- package/ai/policies/model-routing.md +7 -7
- package/ai/policies/production.md +3 -3
- package/ai/policies/release.md +2 -2
- package/ai/policies/review-economy.md +27 -30
- package/bin/riskrails.js +5 -5
- package/hooks/context-guard.py +1 -1
- package/hooks/guard/common.py +2 -0
- package/hooks/guard/paths.py +41 -30
- package/hooks/project-scaffold.py +1 -5
- package/hooks/runtime-gate.py +6 -6
- package/hooks/update_notice.py +20 -14
- package/instructions/routing.md +1 -1
- package/instructions/stub.md +3 -3
- package/package.json +1 -1
- package/skills/AGENTS.md +1 -1
- package/skills/CLAUDE.md +1 -1
- package/skills/ai-init/templates/.ai/AGENTS.md +1 -1
- package/skills/ai-init/templates/.ai/VERSION +1 -1
- package/skills/ai-init/templates/.ai/policies/security.md +7 -1
- package/skills/ai-init/templates/.ai/policies/testing.md +19 -6
- package/skills/ai-init/templates/AGENTS.block.md +2 -2
- package/skills/ai-init/templates/CLAUDE.block.md +2 -2
- package/skills/ai-init/templates/GEMINI.block.md +2 -2
- package/skills/ai-init/templates/gitignore.snippet +1 -0
- package/skills/ai-init/templates/junie-guidelines.block.md +2 -2
- package/skills/ai-task/sensors.py +24 -4
- package/skills/ai-task/state.py +37 -14
- package/skills/project-init/templates/constitution.md +1 -1
- package/skills/project-init/templates/sdlc-README.md +20 -14
- package/skills/project-update/history/blobs/00289f98434fed230eebe768dfb3425f83d737866a3aebc97aa95167c4fa0c6e +131 -0
- package/skills/project-update/history/blobs/079a91f976ad69b5cf49ccb9a28849576e4735ddd9485fc26599e528a69fd2f4 +30 -0
- package/skills/project-update/history/blobs/07ff7fa6f93d471ff533f553b4e523e4105ccde1f3dab70132c5237728f68422 +13 -0
- package/skills/project-update/history/blobs/0ef4a360c76da290173dea0f8073949cb0f8113710a38df95acae5d96bdd1286 +123 -0
- package/skills/project-update/history/blobs/18c7a2753ce9cb6f6d3d1e9d5d1125d75950b879d56b7325225b200869631b29 +15 -0
- package/skills/project-update/history/blobs/25d4f2a86deb5e2574bb3210b67bb24fcc4afb19f93a7b65a057daa874a9d18e +1 -0
- package/skills/project-update/history/blobs/48d9950f16e31d55475f566a80dc95f64b35f1c804d2f51729e313a4f29bac8d +13 -0
- package/skills/project-update/history/blobs/5a93f78b4ed4d416c171139b2ce610a117f9c1dd46fbb56ca86729cb4c53d10c +6 -0
- package/skills/project-update/history/blobs/6a3be0e624e5ad91e44d08857b7183ee53b7903e1e8d56ff196dbc9dde271e4a +75 -0
- package/skills/project-update/history/blobs/7170553410bba904ffb7edb4b231e3b3579b85542d84de717299980938f82c9d +13 -0
- package/skills/project-update/history/blobs/774b1e3a04ef0d49d33c44a2cfecd92eb6f6b738a12b6a681103ba7fc13e7b86 +67 -0
- package/skills/project-update/history/blobs/7f063e79195a5c85c37b7260dd20c184d3b9bea85e37202e0bbca73ad84bba49 +13 -0
- package/skills/project-update/history/blobs/c8573ca1f810ce6c4ac49456a4c1725b93e0d3b74c54ce95d46d8747777895f0 +13 -0
- package/skills/project-update/history/blobs/d6e5b34d475e7187d2a8cb2aac7e7f1a427142baf6461bda387d70ceb4d8a8c1 +30 -0
- package/skills/project-update/history/blobs/e120ff4e32b2e950fc94ada4e787d57dc9c790da37223e5a202d74f7e3aadf80 +13 -0
- package/skills/project-update/history/index.json +36 -15
- package/skills/project-update/migrations/0011_retire_risk_tiers.py +37 -0
- package/skills/project-update/migrations/__init__.py +6 -1
- package/skills/project-update/render_instructions.py +1 -1
- package/skills/project-update/update.py +374 -87
- package/skills/rr-build-all/SKILL.md +2 -2
- package/skills/rr-plan/SKILL.md +3 -1
- package/skills/rr-review/SKILL.md +13 -8
- package/skills/rr-setup/SKILL.md +15 -2
- package/skills/rr-setup/setup.py +7 -1
- package/skills/rr-spec/SKILL.md +4 -2
- package/skills/usage-report/usage-report.py +4 -2
- package/skills/ai-init/templates/.ai/policies/risk-tiers.json +0 -628
- package/skills/ai-init/templates/.ai/policies/risk-tiers.md +0 -180
|
@@ -146,8 +146,8 @@ EOF
|
|
|
146
146
|
- **pass** → §6.
|
|
147
147
|
- **pass_with_findings** → the in-scope HIGHs, grouped by file, one fixer per group in
|
|
148
148
|
parallel; `$STATE verify --scope all --after-fix "H1,H2: …"`; `$STATE review --closes "H1,H2"`
|
|
149
|
-
→ §6.
|
|
150
|
-
or a regression buys an `--after-fix` run.
|
|
149
|
+
→ §6. MEDIUM and LOW: `memory risk add` as `/rr-review` §4 says, for every verdict; only a
|
|
150
|
+
BLOCKER, a HIGH or a regression buys an `--after-fix` run.
|
|
151
151
|
- **blockers_open** → every in-scope BLOCKER and HIGH, grouped by file, one fixer per group in
|
|
152
152
|
parallel; `$STATE verify --scope all --after-fix "B1,H1: …"` (red: §4's batch); then
|
|
153
153
|
**§5 again, a full pass** — a fix batch across many files is a new change, not a scoped one.
|
package/skills/rr-plan/SKILL.md
CHANGED
|
@@ -24,7 +24,9 @@ first: a task already in flight is finished or abandoned before another starts.
|
|
|
24
24
|
|
|
25
25
|
When `$ARGUMENTS` is a spec (default: the newest `docs/sdlc/specs/*.md`):
|
|
26
26
|
|
|
27
|
-
1. `docs/sdlc/
|
|
27
|
+
1. `docs/sdlc/constitution.md` exists, else `/rr-setup`. The template is
|
|
28
|
+
`docs/sdlc/plans/TEMPLATE.md` when the project overrides it, else
|
|
29
|
+
`$AI_HOME/skills/project-init/templates/plan.md`. If the spec's
|
|
28
30
|
**Flagged concerns** holds unresolved items, list them and have the human
|
|
29
31
|
resolve or explicitly accept each one before planning.
|
|
30
32
|
2. If `superpowers:writing-plans` is available, use it for the step
|
|
@@ -60,7 +60,10 @@ guarded, about 80 in full, then FINDINGS and VERDICT.
|
|
|
60
60
|
|
|
61
61
|
Before you delegate, probe the change yourself for a minute: the few inputs its
|
|
62
62
|
own threat model makes interesting, through the real code, and hand the
|
|
63
|
-
reviewer what you saw — it starts where you stopped.
|
|
63
|
+
reviewer what you saw — it starts where you stopped. When the change touches a
|
|
64
|
+
guard regex's running time, run the timed probe yourself (`/usr/bin/grep -E`,
|
|
65
|
+
or Python `timeit` on inputs of at most 4096 chars) and hand over the
|
|
66
|
+
measurement: the bounded reviewer may not run timing loops.
|
|
64
67
|
|
|
65
68
|
## 3. Record the verdict
|
|
66
69
|
|
|
@@ -81,16 +84,18 @@ task's record (`task.md`), so there is no separate report to write.
|
|
|
81
84
|
|
|
82
85
|
## 4. After the verdict
|
|
83
86
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
+
Continue from the verdict §3 recorded; do not record it again. Whatever the
|
|
88
|
+
verdict, each MEDIUM and LOW is one `$STATE memory risk add`
|
|
89
|
+
(`.ai/project/known-risks.md` amended into the task if missing), not a fix.
|
|
90
|
+
|
|
91
|
+
- **pass:** `/rr-ship`, i.e. `$STATE close` directly: the verdict is already
|
|
92
|
+
recorded. (To record and close in one call, §3's `review --verdict pass … <<'EOF' && $STATE close`;
|
|
93
|
+
`review` exits 0 for every verdict, so that chain is for `pass` only.)
|
|
87
94
|
- **pass_with_findings:** fix every in-scope HIGH in one batch, then
|
|
88
95
|
`$STATE verify --scope all --after-fix "H1,H2: <one line>"` and
|
|
89
96
|
`$STATE review --closes "H1,H2"`. The findings close on that green run, on a
|
|
90
|
-
tree the fix changed — no second review.
|
|
91
|
-
|
|
92
|
-
if missing), not a fix; only a BLOCKER, a HIGH or a regression buys an
|
|
93
|
-
`--after-fix` run.
|
|
97
|
+
tree the fix changed — no second review. MEDIUM and LOW: `memory risk add`
|
|
98
|
+
as above; only a BLOCKER, a HIGH or a regression buys an `--after-fix` run.
|
|
94
99
|
- **blockers_open:** fix every BLOCKER and HIGH together, `verify --scope all
|
|
95
100
|
--after-fix "…"`, then **one scoped re-review** (`/rr-review B1,H1`): brief a fresh `ai-reviewer`
|
|
96
101
|
with the named findings and the fix's diff only — do they close, and what did
|
package/skills/rr-setup/SKILL.md
CHANGED
|
@@ -133,12 +133,25 @@ it cannot.
|
|
|
133
133
|
each in one plain sentence and ask, unless `$ARGUMENTS` holds `--apply`.
|
|
134
134
|
4. `$UPDATE --apply`. Exit 3 stopped on a changed, non-regular or unwritable
|
|
135
135
|
file and names it; nothing after it was written — run the dry run again.
|
|
136
|
-
**A `delete?` is the human's.** Never pass `--confirm-delete`, not even with
|
|
136
|
+
**A `delete?` is the human's.** Never pass `--confirm-delete` or `--confirm-cleanup`, not even with
|
|
137
137
|
`--apply`. Give them, with `$AI_HOME` and `$PWD` substituted, for their own
|
|
138
138
|
terminal (the `!` prefix is refused):
|
|
139
139
|
`python3 "<home>/skills/project-update/update.py" "<project>" --apply --confirm-delete "<your name>"`.
|
|
140
140
|
The schema stays put until it is settled — that command, or deleting the
|
|
141
|
-
file by hand; there is no third way.
|
|
141
|
+
file by hand; there is no third way. Two kinds are housekeeping, not
|
|
142
|
+
migrations: `[sdlc]` — an unedited `docs/sdlc/*/TEMPLATE.md`, which the plugin
|
|
143
|
+
now supplies (an edited one stays as the project's override); `[cleanup]` —
|
|
144
|
+
the `*.log` files of closed tasks, and the report and log files of an
|
|
145
|
+
abandoned task (its `state.json` stays) or of one unclosed for more than seven
|
|
146
|
+
days (never the task in flight; and none when `.ai/state/state.json` is unreadable).
|
|
147
|
+
`--confirm-delete` does not settle `[cleanup]` rows, and the rows differ by kind:
|
|
148
|
+
files under `.ai/state/logs/` are git-ignored and git cannot restore them; files
|
|
149
|
+
under `.ai/reports/` are usually tracked, and the row says "tracked: git can restore
|
|
150
|
+
a committed copy" or, when git holds no committed copy, "uncommitted" — then
|
|
151
|
+
commit `.ai/` first (the hint says so), and an `original/` copy is kept as for any
|
|
152
|
+
other deletion. They have their own command, the human's too, never passed by the agent:
|
|
153
|
+
`python3 "<home>/skills/project-update/update.py" "<project>" --apply --confirm-cleanup "<your name>"`.
|
|
154
|
+
Show both groups as printed. For 0006 (shared files) the order is:
|
|
142
155
|
`install.sh` for every runtime used, commit `.ai/`, read the `delete?` list,
|
|
143
156
|
then the command with no task in flight. Rollback is git:
|
|
144
157
|
`git restore --source=<commit before> --staged --worktree -- .ai`, before
|
package/skills/rr-setup/setup.py
CHANGED
|
@@ -182,7 +182,11 @@ def comment_purpose(lines):
|
|
|
182
182
|
|
|
183
183
|
|
|
184
184
|
def purpose_of(root, rel):
|
|
185
|
-
|
|
185
|
+
full = os.path.join(root, rel)
|
|
186
|
+
real, base = os.path.realpath(full), os.path.realpath(root)
|
|
187
|
+
if os.path.commonpath([real, base]) != base:
|
|
188
|
+
return None # a link out of the project: listed UNKNOWN, never read into toolbox.md
|
|
189
|
+
text = read_text(full)
|
|
186
190
|
if text is None:
|
|
187
191
|
return None
|
|
188
192
|
lines = text.splitlines()
|
|
@@ -225,6 +229,8 @@ def inventory(root, table):
|
|
|
225
229
|
for rel in paths:
|
|
226
230
|
if rel in seen or not pattern.match(rel):
|
|
227
231
|
continue
|
|
232
|
+
if "/hooks/" in rel and os.path.basename(rel).startswith("."):
|
|
233
|
+
continue
|
|
228
234
|
seen.add(rel)
|
|
229
235
|
if row["kind"] == "make":
|
|
230
236
|
for n, target, purpose in make_targets(root, rel):
|
package/skills/rr-spec/SKILL.md
CHANGED
|
@@ -19,7 +19,9 @@ STATE="python3 $AI_HOME/skills/ai-task/state.py"
|
|
|
19
19
|
|
|
20
20
|
## 1. Prerequisites
|
|
21
21
|
|
|
22
|
-
`docs/sdlc/
|
|
22
|
+
`docs/sdlc/constitution.md` exists, else run `/rr-setup` first. The template is
|
|
23
|
+
`docs/sdlc/specs/TEMPLATE.md` when the project overrides it, else
|
|
24
|
+
`$AI_HOME/skills/project-init/templates/spec.md`. Derive
|
|
23
25
|
`<slug>` from the topic (kebab-case, at most five words). If
|
|
24
26
|
`docs/sdlc/specs/<slug>.md` exists, offer to refine it instead of starting over.
|
|
25
27
|
When `$ARGUMENTS` is a path to an intent file, read it fully — it is small by
|
|
@@ -75,7 +77,7 @@ decision — moves this to the top tier.
|
|
|
75
77
|
|
|
76
78
|
## 5. Write
|
|
77
79
|
|
|
78
|
-
Copy
|
|
80
|
+
Copy the template (§1) to `docs/sdlc/specs/<slug>.md`, creating the folder, replace
|
|
79
81
|
`{{TITLE}}` and `{{SLUG}}`. Replace the template's `Intent:` line with:
|
|
80
82
|
|
|
81
83
|
```markdown
|
|
@@ -690,7 +690,8 @@ def task_report(args) -> int:
|
|
|
690
690
|
return 1
|
|
691
691
|
start = min(stamps)
|
|
692
692
|
closed = [parse_ts(e.get("ts")) for e in events if e.get("event") == "task_closed"]
|
|
693
|
-
|
|
693
|
+
unclosed = not any(closed)
|
|
694
|
+
end = max(stamps) if unclosed else max(c for c in closed if c) # unclosed: the last event, not now
|
|
694
695
|
tier, mode = "untiered", None
|
|
695
696
|
involved = []
|
|
696
697
|
for e in events:
|
|
@@ -729,7 +730,8 @@ def task_report(args) -> int:
|
|
|
729
730
|
|
|
730
731
|
label = f"mode {mode} (tier {tier})" if mode else f"tier {tier}"
|
|
731
732
|
print(f"task {args.task} {label} window {start.isoformat(timespec='seconds')}"
|
|
732
|
-
f"..{end.isoformat(timespec='seconds')}"
|
|
733
|
+
f"..{end.isoformat(timespec='seconds')}"
|
|
734
|
+
+ (" (unclosed: window ends at the last event)" if unclosed else ""))
|
|
733
735
|
print(" (by time window: any other session in this project inside it is counted too)")
|
|
734
736
|
for rt in involved or sorted(used):
|
|
735
737
|
inp, cache, out = used.get(rt, [0, 0, 0])
|