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.
Files changed (81) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.codex-plugin/plugin.json +2 -2
  4. package/README.md +246 -812
  5. package/agents/ai-reviewer.md.tmpl +6 -4
  6. package/ai/policies/review-economy.md +7 -2
  7. package/ai/using-riskrails.md +15 -0
  8. package/bin/claude-1m +15 -14
  9. package/bin/riskrails.js +108 -32
  10. package/codex/hooks.json +25 -2
  11. package/hooks/AGENTS.md +2 -2
  12. package/hooks/CLAUDE.md +2 -2
  13. package/hooks/ai-guard.py +29 -8
  14. package/hooks/ai-path-guard-defaults.json +3 -1
  15. package/hooks/codex-hooks.json +25 -2
  16. package/hooks/context-guard.py +251 -35
  17. package/hooks/dialog-gate.py +105 -0
  18. package/hooks/guard/common.py +5 -0
  19. package/hooks/guard/decision.py +123 -0
  20. package/hooks/guard/dialog.py +598 -0
  21. package/hooks/guard/git.py +49 -3
  22. package/hooks/guard/paths.py +62 -3
  23. package/hooks/hooks.json +37 -2
  24. package/hooks/memory-pre-push.py +28 -0
  25. package/hooks/runtime-gate.py +59 -12
  26. package/hooks/update_notice.py +135 -0
  27. package/instructions/routing.md +4 -4
  28. package/instructions/stub.md +2 -2
  29. package/package.json +1 -1
  30. package/profiles/max.json +3 -1
  31. package/profiles/pro.json +3 -1
  32. package/scripts/merge-codex-config.py +134 -0
  33. package/scripts/resolve-profile.py +15 -3
  34. package/settings.common.json +39 -2
  35. package/skills/AGENTS.md +2 -2
  36. package/skills/CLAUDE.md +2 -2
  37. package/skills/ai-init/templates/.ai/AGENTS.md +2 -2
  38. package/skills/ai-init/templates/.ai/VERSION +1 -1
  39. package/skills/ai-init/templates/.ai/policies/dialog.json +1 -0
  40. package/skills/ai-init/templates/.ai/policies/safety.md +22 -2
  41. package/skills/ai-init/templates/.ai/policies/weight.json +1 -0
  42. package/skills/ai-init/templates/.ai/policies/weight.md +2 -2
  43. package/skills/ai-init/templates/.ai/state/README.md +9 -6
  44. package/skills/ai-init/templates/AGENTS.block.md +1 -1
  45. package/skills/ai-init/templates/CLAUDE.block.md +1 -1
  46. package/skills/ai-init/templates/GEMINI.block.md +1 -1
  47. package/skills/ai-init/templates/junie-guidelines.block.md +1 -1
  48. package/skills/ai-task/memory_compact.py +968 -0
  49. package/skills/ai-task/memory_format.py +775 -0
  50. package/skills/ai-task/memory_store.py +528 -0
  51. package/skills/ai-task/memory_sync.py +1571 -0
  52. package/skills/ai-task/sensors.py +2 -2
  53. package/skills/ai-task/state.py +967 -70
  54. package/skills/ai-task/weight.py +3 -3
  55. package/skills/project-init/templates/constitution.md +1 -1
  56. package/skills/project-update/history/blobs/164cd34c182de88c33de7df35beb29200d792419e1c13a5f0b2104f944e57be7 +1 -0
  57. package/skills/project-update/history/blobs/1d1d907449ec74594d0ee923ac142ae746b9aedf0a1eda9469f075a44d23e3d7 +13 -0
  58. package/skills/project-update/history/blobs/23a42febbacaa7b52a802d428033a99c0694391c81d51fe3b6e1dff608a641d5 +67 -0
  59. package/skills/project-update/history/blobs/5353ca529c46f2443e12947ec205a6887fb594a4de1f87f0eb1c0e6c0f826133 +49 -0
  60. package/skills/project-update/history/blobs/5f65bc7ab3fc3c4e75ae05d49eaf4331fafc398c661abe33c69f7380a720344c +32 -0
  61. package/skills/project-update/history/blobs/7be527cd648b27cca6e267de30f8e33a2ce17d5631a82694f23ae5c0623efe1f +15 -0
  62. package/skills/project-update/history/blobs/7ee99edafe7cec45ff577376c0d0178fdb2690134d4656488f46e129aba3cc5a +67 -0
  63. package/skills/project-update/history/blobs/8b3ef9586491a426767c01da5d01bdd6b0655c576c68c4cc6dfb093367817dc0 +67 -0
  64. package/skills/project-update/history/blobs/917df3320d778ddbaa5c5c7742bc4046bf803c36ed2b050f30844ed206783469 +1 -0
  65. package/skills/project-update/history/blobs/935af1019931058ec3a0b834fe230e127ec914f75edcc4a6c589cfe733b0b979 +13 -0
  66. package/skills/project-update/history/blobs/ae5ce131d6bae401199ff32d8c3dc4d8aec188010a9111624ac64506e2116ff4 +84 -0
  67. package/skills/project-update/history/blobs/ca4499d829268c8766fb3b825a515e88dc55c237e9d202816b50959b4dac031f +13 -0
  68. package/skills/project-update/history/blobs/e9adb7a9905eb719ac78ab96671f055da53e5001810f5ad6d6c94306b0323fe7 +74 -0
  69. package/skills/project-update/history/blobs/fae3064e648cdc55be4aeb1177525b302a5e34ebd752e4a904f47dc0f4557b96 +71 -0
  70. package/skills/project-update/history/index.json +32 -13
  71. package/skills/project-update/migrations/0009_state_file.py +25 -0
  72. package/skills/project-update/migrations/0010_dialog_switch.py +30 -0
  73. package/skills/project-update/migrations/README.md +2 -1
  74. package/skills/project-update/update.py +12 -3
  75. package/skills/rr-build/SKILL.md +14 -5
  76. package/skills/rr-build-all/SKILL.md +190 -0
  77. package/skills/rr-plan/SKILL.md +13 -3
  78. package/skills/rr-review/SKILL.md +18 -8
  79. package/skills/rr-ship/SKILL.md +16 -8
  80. package/skills/rr-status/SKILL.md +2 -2
  81. 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 human runs the `approve` command `/rr-ship` printed,
28
- in their own terminal; you cannot.
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
- if not project or not os.path.isfile(journal):
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
- with open(journal, encoding="utf-8", errors="replace") as fh:
650
- for line in fh:
651
- rec = _record(line)
652
- if rec is not None:
653
- events.append(rec)
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")