riskrails 3.0.0 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +2 -2
- package/README.md +246 -812
- package/agents/ai-reviewer.md.tmpl +6 -4
- package/ai/policies/review-economy.md +7 -2
- package/ai/using-riskrails.md +15 -0
- package/bin/claude-1m +15 -14
- package/bin/riskrails.js +108 -32
- package/codex/hooks.json +25 -2
- package/hooks/AGENTS.md +2 -2
- package/hooks/CLAUDE.md +2 -2
- package/hooks/ai-guard.py +29 -8
- package/hooks/ai-path-guard-defaults.json +3 -1
- package/hooks/codex-hooks.json +25 -2
- package/hooks/context-guard.py +251 -35
- package/hooks/dialog-gate.py +105 -0
- package/hooks/guard/common.py +5 -0
- package/hooks/guard/decision.py +123 -0
- package/hooks/guard/dialog.py +598 -0
- package/hooks/guard/git.py +49 -3
- package/hooks/guard/paths.py +62 -3
- package/hooks/hooks.json +37 -2
- package/hooks/memory-pre-push.py +28 -0
- package/hooks/runtime-gate.py +59 -12
- package/hooks/update_notice.py +135 -0
- package/instructions/routing.md +4 -4
- package/instructions/stub.md +2 -2
- package/package.json +1 -1
- package/profiles/max.json +3 -1
- package/profiles/pro.json +3 -1
- package/scripts/merge-codex-config.py +134 -0
- package/scripts/resolve-profile.py +15 -3
- package/settings.common.json +39 -2
- package/skills/AGENTS.md +2 -2
- package/skills/CLAUDE.md +2 -2
- package/skills/ai-init/templates/.ai/AGENTS.md +2 -2
- package/skills/ai-init/templates/.ai/VERSION +1 -1
- package/skills/ai-init/templates/.ai/policies/dialog.json +1 -0
- package/skills/ai-init/templates/.ai/policies/safety.md +22 -2
- package/skills/ai-init/templates/.ai/policies/weight.json +1 -0
- package/skills/ai-init/templates/.ai/policies/weight.md +2 -2
- package/skills/ai-init/templates/.ai/state/README.md +9 -6
- package/skills/ai-init/templates/AGENTS.block.md +1 -1
- package/skills/ai-init/templates/CLAUDE.block.md +1 -1
- package/skills/ai-init/templates/GEMINI.block.md +1 -1
- package/skills/ai-init/templates/junie-guidelines.block.md +1 -1
- package/skills/ai-task/memory_compact.py +968 -0
- package/skills/ai-task/memory_format.py +775 -0
- package/skills/ai-task/memory_store.py +528 -0
- package/skills/ai-task/memory_sync.py +1571 -0
- package/skills/ai-task/sensors.py +2 -2
- package/skills/ai-task/state.py +967 -70
- package/skills/ai-task/weight.py +3 -3
- package/skills/project-init/templates/constitution.md +1 -1
- package/skills/project-update/history/blobs/164cd34c182de88c33de7df35beb29200d792419e1c13a5f0b2104f944e57be7 +1 -0
- package/skills/project-update/history/blobs/1d1d907449ec74594d0ee923ac142ae746b9aedf0a1eda9469f075a44d23e3d7 +13 -0
- package/skills/project-update/history/blobs/23a42febbacaa7b52a802d428033a99c0694391c81d51fe3b6e1dff608a641d5 +67 -0
- package/skills/project-update/history/blobs/5353ca529c46f2443e12947ec205a6887fb594a4de1f87f0eb1c0e6c0f826133 +49 -0
- package/skills/project-update/history/blobs/5f65bc7ab3fc3c4e75ae05d49eaf4331fafc398c661abe33c69f7380a720344c +32 -0
- package/skills/project-update/history/blobs/7be527cd648b27cca6e267de30f8e33a2ce17d5631a82694f23ae5c0623efe1f +15 -0
- package/skills/project-update/history/blobs/7ee99edafe7cec45ff577376c0d0178fdb2690134d4656488f46e129aba3cc5a +67 -0
- package/skills/project-update/history/blobs/8b3ef9586491a426767c01da5d01bdd6b0655c576c68c4cc6dfb093367817dc0 +67 -0
- package/skills/project-update/history/blobs/917df3320d778ddbaa5c5c7742bc4046bf803c36ed2b050f30844ed206783469 +1 -0
- package/skills/project-update/history/blobs/935af1019931058ec3a0b834fe230e127ec914f75edcc4a6c589cfe733b0b979 +13 -0
- package/skills/project-update/history/blobs/ae5ce131d6bae401199ff32d8c3dc4d8aec188010a9111624ac64506e2116ff4 +84 -0
- package/skills/project-update/history/blobs/ca4499d829268c8766fb3b825a515e88dc55c237e9d202816b50959b4dac031f +13 -0
- package/skills/project-update/history/blobs/e9adb7a9905eb719ac78ab96671f055da53e5001810f5ad6d6c94306b0323fe7 +74 -0
- package/skills/project-update/history/blobs/fae3064e648cdc55be4aeb1177525b302a5e34ebd752e4a904f47dc0f4557b96 +71 -0
- package/skills/project-update/history/index.json +32 -13
- package/skills/project-update/migrations/0009_state_file.py +25 -0
- package/skills/project-update/migrations/0010_dialog_switch.py +30 -0
- package/skills/project-update/migrations/README.md +2 -1
- package/skills/project-update/update.py +12 -3
- package/skills/rr-build/SKILL.md +14 -5
- package/skills/rr-build-all/SKILL.md +190 -0
- package/skills/rr-plan/SKILL.md +13 -3
- package/skills/rr-review/SKILL.md +18 -8
- package/skills/rr-ship/SKILL.md +16 -8
- package/skills/rr-status/SKILL.md +2 -2
- package/skills/usage-report/usage-report.py +41 -8
|
@@ -24,8 +24,8 @@ After the output, at most one line, and only when a line asks for it:
|
|
|
24
24
|
- `questions: N pending` with N > 0: the task is halted until they are
|
|
25
25
|
answered — `/rr-build` shows them. The count can lag an `[Answer]:` line the
|
|
26
26
|
human filled in the file; `state.py handoff --print` re-reads the file.
|
|
27
|
-
- `gate: requested`: the
|
|
28
|
-
|
|
27
|
+
- `gate: requested`: the `approve` command `/rr-ship` printed is run by the human in their
|
|
28
|
+
own terminal, or by you only if they picked it in the dialog (verbatim, once).
|
|
29
29
|
|
|
30
30
|
Exit 1 with `root: none` means no `.ai/` governs this directory: `/rr-setup`
|
|
31
31
|
sets one up.
|
|
@@ -637,20 +637,53 @@ def find_project(start: str) -> str | None:
|
|
|
637
637
|
d = parent
|
|
638
638
|
|
|
639
639
|
|
|
640
|
+
def seal_events(project: str, task: str) -> list:
|
|
641
|
+
"""R20 (compact-project-memory): after cleanup only the record knows the
|
|
642
|
+
task — its seal's started_at, closed_at, mode and runtimes stand in for
|
|
643
|
+
the journal's first and last lines."""
|
|
644
|
+
base = os.path.join(project, ".ai", "memory")
|
|
645
|
+
seal = None
|
|
646
|
+
for name in sorted(os.listdir(base)) if os.path.isdir(base) else []:
|
|
647
|
+
if not name.endswith(".jsonl"):
|
|
648
|
+
continue
|
|
649
|
+
with open(os.path.join(base, name), encoding="utf-8", errors="replace") as fh:
|
|
650
|
+
for line in fh:
|
|
651
|
+
rec = _record(line)
|
|
652
|
+
if rec and rec.get("kind") == "task" and rec.get("task") == task:
|
|
653
|
+
if seal is None or (rec.get("inst") or 0) >= (seal.get("inst") or 0):
|
|
654
|
+
seal = rec
|
|
655
|
+
if not seal or not seal.get("started_at"):
|
|
656
|
+
return []
|
|
657
|
+
runtimes = [rt for rt in seal.get("runtimes") or [] if rt in RUNTIMES]
|
|
658
|
+
out = [{"ts": seal["started_at"], "event": "task_started", "runtime": rt} for rt in runtimes or [None]]
|
|
659
|
+
out.append({"ts": seal["started_at"], "event": "tier_set",
|
|
660
|
+
"data": {"tier": seal.get("legacy_tier") or "untiered", "mode": seal.get("mode")}})
|
|
661
|
+
if seal.get("closed_at"):
|
|
662
|
+
out.append({"ts": seal["closed_at"], "event": "task_closed"})
|
|
663
|
+
return out
|
|
664
|
+
|
|
665
|
+
|
|
640
666
|
def task_report(args) -> int:
|
|
641
667
|
"""One task's window from its journal, the tokens each runtime spent in it,
|
|
642
668
|
and each involved runtime's budget for the task's final tier."""
|
|
643
669
|
project = find_project(args.project or os.getcwd())
|
|
644
670
|
journal = os.path.join(project or "", ".ai", "reports", args.task, "events.jsonl")
|
|
645
|
-
|
|
646
|
-
print(f"no journal for {args.task} (looked for {journal})")
|
|
647
|
-
return 1
|
|
671
|
+
moved = os.path.join(project or "", ".ai", "state", "logs", args.task, "report", "events.jsonl")
|
|
648
672
|
events = []
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
673
|
+
if project and not os.path.isfile(journal) and os.path.isfile(moved):
|
|
674
|
+
journal = moved # cleanup moved the report directory into the local raw store
|
|
675
|
+
if not project or not os.path.isfile(journal):
|
|
676
|
+
events = seal_events(project, args.task) if project else []
|
|
677
|
+
if not events:
|
|
678
|
+
print(f"no journal for {args.task} (looked for {journal})")
|
|
679
|
+
return 1
|
|
680
|
+
print(f"(no journal: the window is the record's seal for {args.task})")
|
|
681
|
+
else:
|
|
682
|
+
with open(journal, encoding="utf-8", errors="replace") as fh:
|
|
683
|
+
for line in fh:
|
|
684
|
+
rec = _record(line)
|
|
685
|
+
if rec is not None:
|
|
686
|
+
events.append(rec)
|
|
654
687
|
stamps = [parse_ts(e.get("ts")) for e in events if parse_ts(e.get("ts"))]
|
|
655
688
|
if not stamps:
|
|
656
689
|
print(f"the journal of {args.task} has no timestamps")
|