@hassangameryt/freeflow 0.8.0 → 0.9.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 (290) hide show
  1. package/.agents/plugins/marketplace.json +2 -2
  2. package/.claude-plugin/marketplace.json +1 -1
  3. package/.claude-plugin/plugin.json +2 -2
  4. package/.codex-plugin/plugin.json +3 -3
  5. package/.cursor-plugin/plugin.json +1 -1
  6. package/README.md +96 -149
  7. package/capabilities/cognitive-routing/SKILL.md +21 -129
  8. package/capabilities/cognitive-routing/references/coordinator.md +163 -0
  9. package/capabilities/cognitive-routing/references/worker.md +38 -0
  10. package/capabilities/compaction/SKILL.md +3 -3
  11. package/capabilities/compaction/references/summary-format.md +26 -15
  12. package/capabilities/messaging/SKILL.md +49 -0
  13. package/capabilities/task-memory/SKILL.md +87 -0
  14. package/command-surface.json +6 -54
  15. package/gemini-extension.json +1 -1
  16. package/hooks/claude/hooks.json +13 -3
  17. package/hooks/codex/hooks.json +2 -1
  18. package/hooks/shared/runtime-context.mjs +69 -77
  19. package/package.json +25 -8
  20. package/pi-extension/dist/ask-user/ask.js +108 -0
  21. package/pi-extension/dist/ask-user/form.js +250 -0
  22. package/pi-extension/dist/ask-user/questions.js +66 -0
  23. package/pi-extension/dist/ask-user/tool.js +124 -0
  24. package/pi-extension/dist/cognitive-routing/assembler.js +35 -11
  25. package/pi-extension/dist/cognitive-routing/bootstrap.js +90 -0
  26. package/pi-extension/dist/cognitive-routing/config.js +3 -4
  27. package/pi-extension/dist/cognitive-routing/event-store.js +4 -1
  28. package/pi-extension/dist/cognitive-routing/gate.js +20 -5
  29. package/pi-extension/dist/cognitive-routing/handlers.js +15 -13
  30. package/pi-extension/dist/cognitive-routing/model-control.js +17 -8
  31. package/pi-extension/dist/cognitive-routing/projection.js +23 -6
  32. package/pi-extension/dist/cognitive-routing/provenance.js +3 -1
  33. package/pi-extension/dist/cognitive-routing/render.js +15 -15
  34. package/pi-extension/dist/cognitive-routing/runtime.js +4 -2
  35. package/pi-extension/dist/cognitive-routing/schemas.js +4 -4
  36. package/pi-extension/dist/cognitive-routing/session.js +3 -1
  37. package/pi-extension/dist/cognitive-routing/sources.js +29 -4
  38. package/pi-extension/dist/cognitive-routing/state.js +18 -8
  39. package/pi-extension/dist/cognitive-routing/status.js +4 -3
  40. package/pi-extension/dist/cognitive-routing/tools.js +29 -15
  41. package/pi-extension/dist/cognitive-routing/types.js +10 -1
  42. package/pi-extension/dist/compaction/carry.js +36 -22
  43. package/pi-extension/dist/compaction/config.js +4 -2
  44. package/pi-extension/dist/compaction/controller.js +52 -29
  45. package/pi-extension/dist/compaction/harness.js +19 -3
  46. package/pi-extension/dist/compaction/results.js +14 -13
  47. package/pi-extension/dist/compaction/tool.js +6 -6
  48. package/pi-extension/dist/host/catalog.js +20 -35
  49. package/pi-extension/dist/host/config-validation.js +233 -0
  50. package/pi-extension/dist/host/config.js +78 -91
  51. package/pi-extension/dist/host/inbound.js +142 -0
  52. package/pi-extension/dist/host/projection-tags.js +1 -1
  53. package/pi-extension/dist/host/prompts.js +24 -13
  54. package/pi-extension/dist/host/read-only-session.js +6 -1
  55. package/pi-extension/dist/host/request-history.js +7 -3
  56. package/pi-extension/dist/host/rows.js +25 -0
  57. package/pi-extension/dist/host/runtime-state.js +17 -2
  58. package/pi-extension/dist/host/section-keeper.js +85 -0
  59. package/pi-extension/dist/host/settings/freeflow-command.js +846 -93
  60. package/pi-extension/dist/host/settings/settings-view.js +27 -8
  61. package/pi-extension/dist/host/status.js +19 -5
  62. package/pi-extension/dist/index.js +638 -72
  63. package/pi-extension/dist/messaging/config.js +27 -0
  64. package/pi-extension/dist/messaging/messaging.js +398 -0
  65. package/pi-extension/dist/messaging/registry.js +57 -0
  66. package/pi-extension/dist/messaging/render.js +90 -0
  67. package/pi-extension/dist/messaging/tools.js +109 -0
  68. package/pi-extension/dist/messaging/transport.js +101 -0
  69. package/pi-extension/dist/provider-support/cache/keepalive.js +16 -4
  70. package/pi-extension/dist/task-memory/config.js +49 -0
  71. package/pi-extension/dist/task-memory/registry.js +119 -0
  72. package/pi-extension/dist/task-memory/render.js +107 -0
  73. package/pi-extension/dist/task-memory/runtime.js +994 -0
  74. package/pi-extension/dist/task-memory/tool.js +233 -0
  75. package/pi-extension/dist/tool-execution/apply-patch/tool.js +1 -1
  76. package/pi-extension/dist/tool-execution/background.js +220 -28
  77. package/pi-extension/dist/tool-execution/config.js +14 -3
  78. package/pi-extension/dist/tool-execution/file-tracking.js +24 -4
  79. package/pi-extension/dist/tool-execution/guidance-notices.js +124 -0
  80. package/pi-extension/dist/tool-execution/skill-reads.js +143 -0
  81. package/pi-extension/dist/tool-execution/tools.js +2 -2
  82. package/runtime/prompts/cognitive-routing.md +4 -4
  83. package/runtime/prompts/core.md +24 -14
  84. package/runtime/prompts/interaction-contract.md +7 -4
  85. package/runtime/prompts/tool-execution.md +3 -16
  86. package/runtime/prompts/working-method.md +16 -99
  87. package/skills/deliver-work/SKILL.md +76 -0
  88. package/skills/deliver-work/references/branch-closeout.md +134 -0
  89. package/skills/deliver-work/references/commit.md +83 -0
  90. package/skills/deliver-work/references/launch.md +94 -0
  91. package/skills/deliver-work/references/release.md +85 -0
  92. package/skills/deliver-work/scripts/commit-state.mjs +139 -0
  93. package/skills/deliver-work/scripts/delivery-state.mjs +107 -0
  94. package/skills/deliver-work/scripts/lib/git-state.mjs +178 -0
  95. package/skills/deliver-work/scripts/push-route.mjs +122 -0
  96. package/skills/deliver-work/scripts/release-preflight.mjs +177 -0
  97. package/skills/discuss-work/SKILL.md +148 -0
  98. package/skills/{discuss → discuss-work}/references/discussion-continuity.md +10 -27
  99. package/skills/discuss-work/references/learning-action.md +36 -0
  100. package/skills/discuss-work/scripts/choices.mjs +101 -0
  101. package/skills/discuss-work/scripts/lib/choices.mjs +159 -0
  102. package/skills/evaluate-behavior/SKILL.md +107 -0
  103. package/skills/evaluate-behavior/references/authoring.md +381 -0
  104. package/skills/evaluate-behavior/references/coding-tasks.md +145 -0
  105. package/skills/evaluate-behavior/references/conversations-pipelines-judges.md +177 -0
  106. package/skills/evaluate-behavior/references/design-and-measurement.md +273 -0
  107. package/skills/evaluate-behavior/references/running-and-evidence.md +245 -0
  108. package/skills/evaluate-behavior/scripts/claude-guard.mjs +76 -0
  109. package/skills/evaluate-behavior/scripts/guard-rules.mjs +309 -0
  110. package/skills/evaluate-behavior/scripts/lib/agreement.mjs +90 -0
  111. package/skills/evaluate-behavior/scripts/lib/arms.mjs +55 -0
  112. package/skills/evaluate-behavior/scripts/lib/budget.mjs +87 -0
  113. package/skills/evaluate-behavior/scripts/lib/build-source.mjs +287 -0
  114. package/skills/evaluate-behavior/scripts/lib/clear.mjs +74 -0
  115. package/skills/evaluate-behavior/scripts/lib/container.mjs +395 -0
  116. package/skills/evaluate-behavior/scripts/lib/decision.mjs +418 -0
  117. package/skills/evaluate-behavior/scripts/lib/definitions.mjs +1072 -0
  118. package/skills/evaluate-behavior/scripts/lib/freeflow.mjs +103 -0
  119. package/skills/evaluate-behavior/scripts/lib/grade-command.mjs +591 -0
  120. package/skills/evaluate-behavior/scripts/lib/grade-comparison.mjs +90 -0
  121. package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/grade-interaction.mjs +19 -18
  122. package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/grade-support.mjs +32 -5
  123. package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/grade-workspace.mjs +28 -12
  124. package/skills/evaluate-behavior/scripts/lib/grade.mjs +101 -0
  125. package/skills/evaluate-behavior/scripts/lib/hooks.mjs +98 -0
  126. package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/confinement.mjs +196 -0
  127. package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/constraints.mjs +111 -0
  128. package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/index.mjs +48 -0
  129. package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/isolation.mjs +74 -0
  130. package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/launch.mjs +123 -0
  131. package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/model-call.mjs +73 -0
  132. package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/recorder.mjs +178 -0
  133. package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/session.mjs +494 -0
  134. package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/skills.mjs +81 -0
  135. package/skills/evaluate-behavior/scripts/lib/hosts/index.mjs +31 -0
  136. package/skills/evaluate-behavior/scripts/lib/hosts/names.mjs +3 -0
  137. package/skills/evaluate-behavior/scripts/lib/hosts/pi/confinement.mjs +173 -0
  138. package/skills/evaluate-behavior/scripts/lib/hosts/pi/host.mjs +148 -0
  139. package/skills/evaluate-behavior/scripts/lib/hosts/pi/index.mjs +70 -0
  140. package/skills/evaluate-behavior/scripts/lib/hosts/pi/isolation.mjs +81 -0
  141. package/skills/evaluate-behavior/scripts/lib/hosts/pi/model-call.mjs +79 -0
  142. package/skills/evaluate-behavior/scripts/lib/hosts/pi/process.mjs +241 -0
  143. package/skills/{evaluate-skill/scripts/lib → evaluate-behavior/scripts/lib/hosts/pi}/rpc.mjs +144 -26
  144. package/skills/evaluate-behavior/scripts/lib/identity.mjs +82 -0
  145. package/skills/evaluate-behavior/scripts/lib/judge.mjs +688 -0
  146. package/skills/evaluate-behavior/scripts/lib/metrics.mjs +332 -0
  147. package/skills/evaluate-behavior/scripts/lib/model-call.mjs +17 -0
  148. package/skills/evaluate-behavior/scripts/lib/participants.mjs +616 -0
  149. package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/process.mjs +22 -0
  150. package/skills/evaluate-behavior/scripts/lib/queue.mjs +54 -0
  151. package/skills/evaluate-behavior/scripts/lib/reference.mjs +343 -0
  152. package/skills/evaluate-behavior/scripts/lib/reuse.mjs +277 -0
  153. package/skills/evaluate-behavior/scripts/lib/review.mjs +933 -0
  154. package/skills/evaluate-behavior/scripts/lib/runner.mjs +732 -0
  155. package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/sandbox.mjs +119 -14
  156. package/skills/evaluate-behavior/scripts/lib/scan-shell.mjs +457 -0
  157. package/skills/evaluate-behavior/scripts/lib/scan.mjs +479 -0
  158. package/skills/evaluate-behavior/scripts/lib/seal.mjs +91 -0
  159. package/skills/evaluate-behavior/scripts/lib/shell.mjs +560 -0
  160. package/skills/evaluate-behavior/scripts/lib/source-override.mjs +64 -0
  161. package/skills/evaluate-behavior/scripts/lib/subject-file.mjs +88 -0
  162. package/skills/{evaluate-skill/scripts/lib/pi.mjs → evaluate-behavior/scripts/lib/subject.mjs} +235 -265
  163. package/skills/evaluate-behavior/scripts/lib/task-copy.mjs +124 -0
  164. package/skills/evaluate-behavior/scripts/lib/trials.mjs +524 -0
  165. package/skills/evaluate-behavior/scripts/lib/validity.mjs +68 -0
  166. package/skills/evaluate-behavior/scripts/lib/view-html.mjs +454 -0
  167. package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/view.mjs +159 -18
  168. package/skills/{evaluate-skill → evaluate-behavior}/scripts/pi-command-tool.mjs +21 -6
  169. package/skills/evaluate-behavior/scripts/pi-container-route.mjs +23 -0
  170. package/skills/evaluate-behavior/scripts/pi-guard.mjs +77 -0
  171. package/skills/evaluate-behavior/scripts/pi-login-refresh.mjs +31 -0
  172. package/skills/evaluate-behavior/scripts/skill-eval.mjs +586 -0
  173. package/skills/execute-work/SKILL.md +96 -104
  174. package/skills/execute-work/references/code-practices.md +27 -51
  175. package/skills/execute-work/references/design.md +271 -0
  176. package/skills/execute-work/references/diagnose.md +117 -0
  177. package/skills/execute-work/references/migration.md +108 -0
  178. package/skills/execute-work/references/simplify.md +65 -0
  179. package/skills/execute-work/scripts/self-review.mjs +422 -0
  180. package/skills/execute-work/scripts/touch-map.mjs +290 -0
  181. package/skills/review-work/SKILL.md +89 -65
  182. package/skills/review-work/references/adjudication.md +94 -0
  183. package/skills/review-work/references/artifact.md +198 -0
  184. package/skills/review-work/references/evals-and-judges.md +66 -0
  185. package/skills/review-work/references/work.md +177 -0
  186. package/skills/review-work/scripts/check-brief.mjs +128 -0
  187. package/skills/review-work/scripts/review-packet.mjs +233 -0
  188. package/skills/setup-freeflow/SKILL.md +68 -17
  189. package/skills/track-work/SKILL.md +52 -20
  190. package/skills/track-work/references/handoff.md +190 -0
  191. package/skills/track-work/references/projects.md +51 -0
  192. package/skills/track-work/references/working-record-format.md +36 -18
  193. package/skills/track-work/scripts/lib/document.mjs +17 -13
  194. package/skills/track-work/scripts/lib/format.mjs +2 -0
  195. package/skills/track-work/scripts/lib/recover.mjs +254 -0
  196. package/skills/track-work/scripts/lib/registry.mjs +656 -0
  197. package/skills/track-work/scripts/lib/search.mjs +40 -0
  198. package/skills/track-work/scripts/lib/store.mjs +46 -15
  199. package/skills/track-work/scripts/lib/views.mjs +50 -1
  200. package/skills/track-work/scripts/working-record.mjs +232 -13
  201. package/skills/verify-work/SKILL.md +45 -37
  202. package/skills/verify-work/references/feature-map.md +120 -0
  203. package/skills/verify-work/references/runtime-evidence.md +203 -0
  204. package/skills/verify-work/references/test-design.md +25 -6
  205. package/skills/verify-work/scripts/test-changes.mjs +246 -0
  206. package/skills/write-docs/SKILL.md +113 -25
  207. package/skills/write-docs/references/documentation-shapes.md +68 -3
  208. package/skills/write-docs/references/spec-and-plan-shapes.md +308 -0
  209. package/skills/write-docs/scripts/artifact-check.mjs +148 -0
  210. package/skills/write-docs/scripts/docs-check.mjs +96 -6
  211. package/skills/write-docs/scripts/plan-lint.mjs +123 -0
  212. package/skills/write-skill/SKILL.md +92 -52
  213. package/skills/write-skill/references/activation-and-wording.md +143 -0
  214. package/skills/write-skill/references/placement-and-dependencies.md +154 -0
  215. package/skills/write-skill/scripts/lib/compare.mjs +701 -0
  216. package/skills/write-skill/scripts/lib/skill-author.mjs +197 -3
  217. package/skills/write-skill/scripts/skill-author.mjs +51 -8
  218. package/capabilities/cognitive-routing/references/both-mode.md +0 -36
  219. package/capabilities/cognitive-routing/references/executor-mode.md +0 -48
  220. package/capabilities/cognitive-routing/references/helper-mode.md +0 -47
  221. package/plugin.json +0 -33
  222. package/skills/action-selection/SKILL.md +0 -92
  223. package/skills/action-selection/references/trajectory-stalls.md +0 -73
  224. package/skills/bypass/SKILL.md +0 -153
  225. package/skills/commit-work/SKILL.md +0 -93
  226. package/skills/commit-work/references/git-state-edges.md +0 -94
  227. package/skills/commit-work/references/simple-push.md +0 -94
  228. package/skills/commit-work/references/staging-decisions.md +0 -106
  229. package/skills/decision-gate/SKILL.md +0 -87
  230. package/skills/design-for-depth/SKILL.md +0 -108
  231. package/skills/design-for-depth/references/design-pressure-signals.md +0 -84
  232. package/skills/design-for-depth/references/implementation-decisions.md +0 -76
  233. package/skills/design-for-depth/references/interface-design-loop.md +0 -105
  234. package/skills/design-for-depth/references/module-and-dependency-design.md +0 -117
  235. package/skills/design-for-depth/references/state-and-failure-boundaries.md +0 -125
  236. package/skills/diagnose-failure/SKILL.md +0 -140
  237. package/skills/diagnose-failure/references/diagnostic-loop-catalog.md +0 -50
  238. package/skills/diagnose-failure/references/flaky-and-performance-diagnosis.md +0 -51
  239. package/skills/discuss/SKILL.md +0 -140
  240. package/skills/evaluate-skill/SKILL.md +0 -188
  241. package/skills/evaluate-skill/references/evaluation-definition-schema.md +0 -415
  242. package/skills/evaluate-skill/references/evaluation-design.md +0 -112
  243. package/skills/evaluate-skill/references/execution-and-evidence.md +0 -111
  244. package/skills/evaluate-skill/references/review-and-revision.md +0 -94
  245. package/skills/evaluate-skill/scripts/lib/definitions.mjs +0 -448
  246. package/skills/evaluate-skill/scripts/lib/grade-comparison.mjs +0 -60
  247. package/skills/evaluate-skill/scripts/lib/grade.mjs +0 -64
  248. package/skills/evaluate-skill/scripts/lib/review.mjs +0 -196
  249. package/skills/evaluate-skill/scripts/lib/runner.mjs +0 -405
  250. package/skills/evaluate-skill/scripts/lib/trials.mjs +0 -103
  251. package/skills/evaluate-skill/scripts/pi-guard.mjs +0 -181
  252. package/skills/evaluate-skill/scripts/skill-eval.mjs +0 -182
  253. package/skills/execute-work/references/execute-work-edges.md +0 -78
  254. package/skills/finish-branch/SKILL.md +0 -117
  255. package/skills/finish-branch/references/integration-options.md +0 -80
  256. package/skills/handoff/SKILL.md +0 -82
  257. package/skills/handoff/references/handoff-templates.md +0 -150
  258. package/skills/launch-work/SKILL.md +0 -116
  259. package/skills/launch-work/references/launch-readiness.md +0 -85
  260. package/skills/migration-work/SKILL.md +0 -115
  261. package/skills/migration-work/references/migration-lifecycle.md +0 -82
  262. package/skills/release-work/SKILL.md +0 -118
  263. package/skills/release-work/references/release-evidence.md +0 -78
  264. package/skills/review-artifact/SKILL.md +0 -143
  265. package/skills/review-artifact/references/adjudicate-artifact-review.md +0 -101
  266. package/skills/review-artifact/references/independent-artifact-reviewer-contract.md +0 -159
  267. package/skills/review-work/references/adjudicate-work-review.md +0 -97
  268. package/skills/review-work/references/independent-work-reviewer-contract.md +0 -139
  269. package/skills/review-work/references/security-risk-lens.md +0 -67
  270. package/skills/setup-freeflow/references/activation-contract.md +0 -103
  271. package/skills/setup-freeflow/references/host-setup.md +0 -67
  272. package/skills/simplify-code/SKILL.md +0 -85
  273. package/skills/simplify-code/references/simplification-patterns.md +0 -70
  274. package/skills/verify-work/references/browser-runtime-evidence.md +0 -51
  275. package/skills/verify-work/references/integration-evidence.md +0 -49
  276. package/skills/verify-work/references/performance-evidence.md +0 -59
  277. package/skills/workflow/SKILL.md +0 -171
  278. package/skills/workflow/references/domain-skill-composition.md +0 -45
  279. package/skills/write-plan/SKILL.md +0 -92
  280. package/skills/write-plan/references/plan-shapes.md +0 -156
  281. package/skills/write-skill/references/activation-boundaries.md +0 -106
  282. package/skills/write-skill/references/agent-first-instructions.md +0 -133
  283. package/skills/write-skill/references/progressive-disclosure.md +0 -129
  284. package/skills/write-skill/references/skill-dependency-graphs.md +0 -192
  285. package/skills/write-spec/SKILL.md +0 -85
  286. package/skills/write-spec/references/artifact-standards.md +0 -86
  287. package/skills/write-spec/references/decision-records.md +0 -80
  288. package/skills/write-spec/references/spec-shapes.md +0 -143
  289. /package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/evidence.mjs +0 -0
  290. /package/skills/{evaluate-skill → evaluate-behavior}/scripts/pi-observer.mjs +0 -0
@@ -0,0 +1,245 @@
1
+ # Running And Evidence
2
+
3
+ Two parts. Running the evaluator, and what it stores, is a contract: it states how the evaluator behaves; rely on that behavior as written, and its requirements on you restate [Evaluate Behavior](../SKILL.md) Rules. Reading the evidence and deciding what to revise is judgment: adapt it to the evidence in hand.
4
+
5
+ ## Command And Path Contract
6
+
7
+ Run commands from the repository or fixture root that owns the definitions:
8
+
9
+ ```text
10
+ node <evaluate-behavior-directory>/scripts/skill-eval.mjs run <suite-or-group-path> [--group <id-or-position>] [--variant <arm>] [--trials <n>] [--max-cost <total>] [--jobs <n>] [--cpu-jobs <n>] [--reuse] [--pilot <n>] [--results <dir>] [--yes] [--dry-run] [--skip-reference-check] [--source <arm>=<commit>]
11
+ node <evaluate-behavior-directory>/scripts/skill-eval.mjs view <result-id-or-directory> [--group <id-or-position>] [--variant <arm>] [--results <dir>]
12
+ node <evaluate-behavior-directory>/scripts/skill-eval.mjs view <result-id-or-directory> --html <file> [--results <dir>]
13
+ node <evaluate-behavior-directory>/scripts/skill-eval.mjs check-tasks <suite-or-group-path> [--group <id-or-position>]
14
+ node <evaluate-behavior-directory>/scripts/skill-eval.mjs review <result-id-or-directory> (--model <provider/model> | --configuration <file>) [--group <id-or-position>] [--thinking <level>] [--swap | --swap-sample <fraction>] [--limit <name>=<chars>] [--results <dir>]
15
+ node <evaluate-behavior-directory>/scripts/skill-eval.mjs review <result-or-aggregate-id> --rubric [--model <provider/model>] [--configuration <file>] [--group <id-or-position>] [--thinking <level>] [--limit <name>=<chars>] [--results <dir>]
16
+ node <evaluate-behavior-directory>/scripts/skill-eval.mjs review <result-or-aggregate-id> --calibrate <labels.json> [--results <dir>]
17
+ node <evaluate-behavior-directory>/scripts/skill-eval.mjs clear <result-id-or-directory> [--group <id>] [--variant <arm>] (--flag <id>... | --all) --reason <text> [--results <dir>]
18
+ ```
19
+
20
+ - The current working directory is the definition root and result root.
21
+ - The `run` target resolves from that directory.
22
+ - Suite group references resolve relative to the suite file.
23
+ - Fixture, skill, and context declarations resolve from the definition root.
24
+ - Results are stored under `<cwd>/.skill-eval/runs/<result-id>`, or under `--results <dir>` (resolved from the working directory) when given; `invocation.json` records the directory. `view` and `review` take the same `--results` to find stored IDs there, and an aggregate's trials are found beside it.
25
+ - A bare `view` target is tried first as a stored result ID, then as a path from the working directory.
26
+ - An absolute or path-like `view` target resolves as a directory path.
27
+
28
+ Examples:
29
+
30
+ ```text
31
+ skill-eval run .skill-eval/my-skill/suite.json
32
+ skill-eval run .skill-eval/my-skill/suite.json --variant candidate
33
+ skill-eval view 20260720173209-a3649b8b
34
+ skill-eval view 20260720173209-a3649b8b --group 2 --variant candidate
35
+ skill-eval view /absolute/path/to/result
36
+ ```
37
+
38
+ With no selectors, `run` or `view` selects every suite group and every arm. `--group` is invalid for a direct group definition/result.
39
+
40
+ Before anything starts, `run` prints its plan: `Plan: <subjects> subjects (<groups>, <arms>, <trials>); models: <model (thinking)>`, plus the Freeflow refs it will build. On an interactive terminal it then asks `Start? [y/N]` unless `--yes` is given; any answer but yes starts nothing and exits nonzero. When either stdin or stdout is not a terminal, as in scripts and agents, it prints the plan and continues.
41
+
42
+ ## Current Execution Boundary
43
+
44
+ `run` executes description and body groups. Unsupported group types are rejected before subject execution. Description groups allow no tools or `read`; body groups allow no tools or path-guarded `read`, `write`, `edit`, `ls`, `find` and `grep`, the evaluator's `run_command` tool for declared commands, plus non-native custom tools supplied by a declared runtime extension bundle. `ls`, `find` and `grep` without a path work in the workspace; an explicit path must stay inside the readable roots, like a read. Native `bash` runs only through a declared shell isolation that the evaluator verifies with confinement probes before any subject runs (see [coding tasks](coding-tasks.md#shell)); without one, `run` refuses it before any subject starts and the guard blocks it, because the guard cannot confine a shell to the workspace. A container environment provides such a shell: bash and the declared commands run in a per-subject container from a digest-pinned image, started for a group that declares either, and command graders run in the same image. Before any container starts, the evaluator checks that the engine shares the folder the workspaces live under with its containers, by reading a marker back through the image: a VM-based engine (Colima, Docker Desktop, OrbStack, Podman's machine) mounts only the host folders it shares, and a workspace elsewhere would arrive empty. A refusal names the folder; run from one the engine shares, or for `check-tasks`, which works under the system temp folder, set `TMPDIR` to one. `powershell` is unsupported.
45
+
46
+ A [runtime profile](conversations-pipelines-judges.md#runtime-profile) selects the host's prompt mode, session, extension bundles and environment sources; missing inherited variables invalidate the variant. For body runs, delivery remains `unavailable` until target setup succeeds; `natural-prompt` or `explicit-skill-command` records a prompt attempt. After the evaluator's guard load the configuration's `host.extensions` (recorded under `resources.hostExtensions`), the command tool when the group declares commands, the arm's Freeflow build when declared, and declared extensions; when a group declares context assertions, a final non-mutating observer records the effective system prompt and each provider-neutral context message without replacing or sanitizing what extensions injected.
47
+
48
+ Use fresh JSON-mode execution for one-shot descriptions. Use one persistent RPC process per selected variant for ordered description turns and all body groups. RPC correlates responses, waits for `agent_settled`, disables automatic retry and compaction, preserves directly observed partial-turn evidence, and cleans the process tree. A run the host starts on its own between prompts, such as an extension's notice that a background command exited, is recorded in the turn before it (the turn's `unpromptedRuns` counts them), and the next prompt, a simulated user's reply and the end of the session wait for it to settle; each prompt is sent as a follow-up, so one that arrives during such a run waits its turn.
49
+
50
+ A body target is matched to the exact snapshotted `SKILL.md` and explicitly delivered on turn one. Later turns remain unchanged. Description groups use natural prompts and never explicit target delivery.
51
+
52
+ ## Isolation And Resources
53
+
54
+ For each selected variant:
55
+
56
+ - snapshot exact declared skills, context, and the shared runtime bundle resources;
57
+ - copy the shared runtime bundles identically into the variant and verify their fingerprints before and after execution;
58
+ - snapshot the group fixture once from the definition-root working tree—never from a variant Git source—then create an independent writable copy;
59
+ - preserve skill order and target index;
60
+ - preserve runtime host, session mode, and extension order;
61
+ - preserve runtime bundle and provider-context observation evidence when requested;
62
+ - replace ambient instructions with evaluator-owned declared context;
63
+ - keep criteria and review questions outside the subject prompt;
64
+ - allow reads only from workspace and declared immutable resources;
65
+ - allow writes and edits only inside the workspace;
66
+ - reject traversal, symlink escape, unsupported Git entries, and invalid UTF-8 in declared resources and the fixture;
67
+ - record a link the subject makes in its workspace as a link with its `target`, never following it, so a link to the container's workdir or outside the workspace neither fails the run nor copies anything in;
68
+ - verify immutable resource fingerprints after execution.
69
+
70
+ Working-tree sources snapshot current paths. Git sources resolve one exact commit and record both the declared ref and resolved identity.
71
+
72
+ A run is canonical only when every working-tree input it reads (the definition files and any `extends` file, the fixture, runtime bundle resources, command grader files, rubric reference files, a conversation's card, host extensions taken from a working-tree `path`, and the skills and context of working-tree subjects) is committed and unchanged in the definition root's Git repository: modified, untracked or ignored files all count as uncommitted. The run then records that commit in `summary.json` under `inputs` and on each working-tree source. Otherwise it is refused before anything starts, naming the uncommitted paths, unless `--dry-run` is given. A dry run is marked `dryRun: true` with its uncommitted inputs listed, and its aggregate supports no claim. Inputs outside any Git repository need `--dry-run` too. When a configuration declares `host.version`, the evaluator compares it with `pi --version` before anything starts, refuses a mismatch, and records the installed version as `hostVersion`.
73
+
74
+ Each host process, subject or reviewer, runs in its own isolation root (`isolation/` beside its evidence), with its own home, temp, XDG and Pi agent directories, so the user's home, temp files and Pi settings are not visible and two processes share nothing. Only the declared model's provider login is copied in, from `SKILL_EVAL_CREDENTIALS_DIR`, else `PI_CODING_AGENT_DIR`, else `~/.pi/agent`, with that provider's custom model entry when one exists; `run.json` records which entries were copied under `isolation`, never their values. No copy refreshes a login, which would rotate the user's own token away: the installed Pi refreshes every OAuth login the selected arms use, in the user's own agent directory, valid for at least 120 minutes before a batch, and again before a subject whose login has under 30 minutes left, one at a time, and a refresh that fails refuses the run with a pointer to log in again in Pi. The configuration's `host.settings`, merged over the evaluator's defaults (automatic retry and compaction off), become the agent directory's `settings.json`, recorded as `isolation.settings`; Pi uses its defaults for every other setting. A provider with no stored login runs with nothing copied.
75
+
76
+ ## Persistence And States
77
+
78
+ Each selected run is persisted before its counterpart. Grade and group evidence are persisted before later groups.
79
+
80
+ Run states are `complete`, `invalid`, `infrastructure-failed`, `cancelled`, and `not-selected`. Group and batch states are `complete`, `partially-complete`, `invalid` where applicable, and `cancelled`.
81
+
82
+ - Failed deterministic checks are ordinary complete behavioral evidence and exit zero when no infrastructure/grade failure exists.
83
+ - A grade whose every selected check is `unavailable` observed nothing, so its group is `partially-complete` and the command exits nonzero.
84
+ - A missing or malformed context observation makes the run `infrastructure-failed` but keeps its transcript, response, usage, and process evidence.
85
+ - **Transcript scan.** After each executed run, and over a pipeline's earlier stages, the evaluator records `postRun.scan.flags`: `outside-read` (a read, `ls`, `find` or `grep` of a path outside the workspace, the declared resources and the run's own arm directory, blocked or not, except the subject's scratch files under the temp directory; the arm's `isolation/`, which holds the login, is outside; also a bash command naming a host path under the user's home or the definition root that is none of these, or a credential location such as `~/.ssh` or `~/.pi`), `network` (a bash command whose target is external: an HTTP client, socket tool, remote shell or Git remote that is not this machine or the container's own network, or code that fetches an external URL; when the run's network was `none`, also an install that names a registry package; a URL in a payload or in tool output is not an attempt), `instruction-file` (`CLAUDE.md`, `AGENTS.md` or `.claude/` reached outside the workspace) and `answer-copy` (three consecutive distinctive lines of a hidden grader file, or a quarter of them, a hidden test's name, or most of the reference solution's distinctive lines in the subject's answer or written files; a distinctive line is long, has several words and is not an import). A file the subject wrote that the scan did not read, such as a link it made, is listed under `postRun.scan.skipped`. A flag is evidence for a person, not a verdict: the run is graded as usual, but until a person clears every flag it is held, counted as `unavailable` and named under `held` in the aggregate, its metrics, scores and judged answers count toward no claim or decision, and a pilot stops on it. `skill-eval clear` records the person's reason in `clearances.json` beside the run (the run's files never change) and rebuilds every aggregate that lists its result. Clear a flag only on the user's decision.
86
+ - **Validity gate.** A run the host reported complete is graded only when it shows a model at work: at least one assistant message, a nonzero token total, and an answer or something written in the workspace. Otherwise it becomes `invalid` before any grader runs, with `error.kind` `validity` and the failed conditions in `error.reasons`, and its group's `group.json` names the reason under `invalid`. An invalid run keeps everything it recorded, its checks are `unavailable` (never a fail), its metrics count toward no summary or decision, and a pilot stops on it. Tokens, not cost, are the signal: a model with no configured price reports zero cost for real work, while a provider that reports no token usage at all cannot be told apart from one that never answered. Tool use is not required: one answer without tools, such as a description run whose target did not activate, is behavior to grade.
87
+ - Variant-local invalidity or infrastructure failure preserves evidence and does not stop safe queued work.
88
+ - Shared fixture failure invalidates the group.
89
+ - Thrown grading or recoverable grade/group publication failure becomes explicit `grade-error` fallback evidence.
90
+ - If a run or required fallback cannot be preserved, queued work stops and no completed summary is published.
91
+ - Cancellation starts no queued subject and preserves observed diagnostics.
92
+
93
+ Invalidity, infrastructure failure, cancellation, or `grade-error` makes the final command exit nonzero after safe queued work finishes.
94
+
95
+ ## Views And Raw Evidence
96
+
97
+ Views can render a complete result, one arm across groups, one group, or one group's arm. Grade appears before selected run evidence. The displayed absolute result path anchors result-relative artifact and workspace paths.
98
+
99
+ Path cells escape literal backslashes before tab, carriage return, and newline. Arm views exclude expectation-owned errors from other arms while retaining comparison, group, and system errors.
100
+
101
+ Use ordinary file tools for raw `run.json`, events, transcript, final response, stderr, workspace, definition, grade, context observations, and group artifacts. Views remove transport noise; they do not replace canonical evidence. Tool-call grades distinguish attempted, succeeded, failed, and not-called outcomes.
102
+
103
+ ## Safeguards And Limits
104
+
105
+ Normal completion follows settlement. Path guards, no-progress detection, cancellation, process-tree cleanup, and very high emergency ceilings stop runaway or unsafe infrastructure. Subjects run until they settle, with no turn, token, output, or short time cap, because a guessed cap cuts off the behavior the evaluation is trying to observe.
106
+
107
+ `--max-cost <total>` is an explicit spend ceiling, not a subject cap, shared by every subject of a run and of all its trials. It is reserve-then-charge: before a subject starts it reserves the mean cost of the subjects finished so far (zero before any finished), and it may not start once spend plus the running subjects' reservations reaches the ceiling; such variants become `cancelled`. When a subject finishes, its host-reported `usage.cost.total` is charged. Subjects already running complete and are charged, so spend can pass the ceiling by at most the running set (one subject with one job). The aggregate records `budget` with the ceiling, the run's spend, whether it was exhausted, and the `overshoot` past the ceiling; a result's summary records the same `budget` with the run's total so far as `runTotal`, because the ceiling is shared by every trial. A host that reports no cost never exhausts the ceiling.
108
+
109
+ Each result's summary also records its own `cost`, with or without a ceiling: `spent`, the host-reported cost of the subjects this result ran (a reused run costs nothing again), `subjects`, how many ran, and `unmeasured`, how many have no measured cost: no cost reported, or a cost of 0 for a run that used tokens, as Pi reports for a model it has no price for. Such a run's `cost` metric is null too, so it is never read as free. An aggregate lists each trial's `cost`, so one trial's cost never has to be read off the run's running total.
110
+
111
+ ## Concurrency, Reuse And Pilot
112
+
113
+ - **`--jobs <n>`** (default 1) runs up to n subjects at once across groups, arms and trials, through one shared queue. Each group still prepares its fixture before its arms run, grades after all its arms, and each result's summary is written after all its groups; results are listed in plan order. With one job, groups, arms and trials run one after another as before. Cancellation (SIGINT or SIGTERM) stops queued subjects and terminates running ones; budget exhaustion only stops new ones.
114
+ - **`--cpu-jobs <n>`** (default 2) bounds local CPU work that is not a model call, such as command graders, through a shared queue (`withCpuSlot` in `lib/queue.mjs`).
115
+ - **Reuse.** Every complete run of a canonical (not dry) invocation whose group grade is readable is indexed, with or without `--reuse`, in `<results>/index.jsonl` under a key: sha256 over the group's task fields, the content of its fixture, runtime bundles and command-grader files, the arm's name and effective configuration, the content of its working-tree skills and context (or the commit its Git source resolves to, and its Freeflow ref's commit), its model, the installed host version, and the evaluator's own scripts. A run with `--reuse` takes a matching indexed run (still complete, grade still readable) instead of running that arm: the run is copied into the new trial, graded there like any other, and marked `reused` with where it came from; the group records `reused` and the aggregate lists every reused run. A run is reused at most once within one run or aggregate, and a reused copy is never indexed. Dry runs never reuse and are never indexed.
116
+ - **`--pilot <n>`** first runs the first n selected groups once, every arm. It stops with a report, before the batch and without an aggregate, if any of its runs is cancelled, infrastructure-failed or invalid, any grade is unreadable or has errors, or any comparison passed in no arm. Otherwise the batch continues: the pilot is the first trial of its groups and one invocation of the remaining groups completes that trial (the aggregate records `pilot` and each trial's `part`). A run with `--pilot` always records an aggregate, even with one trial, so no group runs twice.
117
+ - **`--source <arm>=<commit>`** (repeatable) runs the arm, for this run only, with every Git source ref it declares (its subject source, its Freeflow source and its source-built host extensions) replaced by the commit SHA. The definition files are not changed. `invocation.json` records `sources`, each overridden run records `sourceOverride` and the commit in its `resources.source`, and the reuse key follows the override. An arm with no Git source, or one that is not an arm of a selected group, is refused before the plan.
118
+
119
+ ## Trials
120
+
121
+ `--trials <n>` runs the selection as `n` independent complete invocations. Each trial is an ordinary result with its own ID. A separate aggregate under `.skill-eval/runs/<aggregate-id>/aggregate.json` lists the trials and, per group, counts pass, fail, and unavailable for every deterministic check and comparison, plus comparison transitions. A trial whose grade file cannot be read is counted in `unreadableGrades`; the other trials still aggregate. Grade errors are counted per group (`gradeErrors`), and run states per variant (`runStates`), so nothing that failed leaves the denominators silently. Each check also records `trials` and `passAll`, its pass^k: whether it passed in every one of the k trials that graded it. Each comparison records `pairs` for each non-reference arm, the per-trial outcomes against the reference: both pass, both fail, reference only, that arm only, or incomplete. Without a decision rule, the aggregate's `claim` is a rate on this suite at its k and states that no "beats" claim is supported. A suite that declares a [decision](authoring.md#decision) always runs as trials, even without `--trials`; the aggregate records `decision` (the rule with defaults applied, its `ruleSha256`, the split, ties, excluded cases and values, p, the verdict, and each case's per-arm mean and count), and its claim is the rule's verdict (`beats`, `worse` or `no-difference-shown`) with the split, p and the rule's hash; a dry run's claim stays `none`. When the decision declares a `trials` schedule, the plan states the initial trials and the most adaptive rounds could add; each added trial runs one undecided group alone and records its `round` and `group`, `requestedTrials` stays the initial count, and `schedule.rounds` records each round's cases and its scheduled and run trials. `--max-cost` is shared across trials, and exhaustion stops starting further trials. `view <aggregate-id>` renders the counts, pass^k, pairs, claim and decision, with initial and adaptive trials counted apart; view an individual trial for its evidence.
122
+
123
+ The aggregate's `scores` section summarizes test-graded command checks' `score` per arm and per trial (`score.<expectation id>`, and `score.<comparison id>` for a comparison's checks); a decision rule names one as `{ "score": "<id>" }`.
124
+
125
+ Each subject's `run.json` records `metrics` derived from evidence the run already holds: `durationMs`, `turns`, `toolCalls`, `toolErrors`, `tokens` (`input`, `output`, `cacheRead`, `cacheWrite`), `cost` (the host-reported cost), `cacheHitRate`, and, from a Pi transcript only, `peakContext` (the largest single request), `skillReads` and `skillReadTokens` (reads of declared skills' or the loaded Freeflow package's instruction files, re-reads counted; tokens estimated at 4 bytes each, since no tokenizer ships, and a skill delivered in the prompt rather than read is not counted). An arm with no skills and no Freeflow reads 0; any other metric without evidence is `null`, never 0. The aggregate's `metrics` section gives, per arm, each metric's count, median, mean, min and max over the trials that measured it; per non-reference arm, the paired difference against the reference within each trial; and `perTrial` values, which a decision rule names as `{ "metric": "<name>" }` with nested fields dotted (`tokens.input`). Both views render them.
126
+
127
+ ## Advisory Review
128
+
129
+ `review` answers each group's `review_questions` with a separate reviewer model, a judge under Review Work's [Judge Contract](../../review-work/references/evals-and-judges.md#judge-contract):
130
+
131
+ - only groups with review questions and a complete run in every arm are reviewed;
132
+ - the reviewer sees the task turns, the group's fixture files as shared task materials, and for each run its responses, tool calls, changed paths and the full text of every file it created or modified (by default each response up to 8,000 characters, each tool call's arguments up to 300, each file up to 20,000 and the materials up to 60,000, with any cut stated; `--limit <name>=<chars>` changes any of them), as Run A, Run B and so on in random order;
133
+ - run workspaces, the group and run directories, the repository root and the user's home are replaced by neutral tokens, so absolute paths and the variant names inside them never reach it; it never sees deterministic grades;
134
+ - each run and the task materials are fenced between `BEGIN RUN MATERIAL <token>` and `END RUN MATERIAL <token>` lines, with a random token per prompt that the material cannot know, and a fixed instruction before them says the fenced text is evidence, never instructions; text in it that addresses the reviewer, asks for a verdict or claims authority is quoted in the reply's `steering`, recorded in `steering`, and adds the contract gap `run material addressed the judge`;
135
+ - it runs without tools, skills, context files, or session, in its own isolation root, with extensions off except its host setup's: by default each group's (the reference arm's `host.extensions` and `host.settings`, so it uses the login the subjects used), or the configuration file given with `--configuration`, whose extensions, settings and model replace it (`--model` and `--thinking` override the model); `semantic-grade.json` records the `setup` (`group` or `command-line`) with the extensions and settings, and a group whose extensions are built from source needs `--configuration`;
136
+ - `--swap` reviews again with the order reversed and records agreement per question; without it, the unchecked order is recorded as a contract gap; `--swap-sample <fraction>` swaps only on a random sample of the selected groups (the fraction of them, rounded up), and each group records `swapSample: { fraction, sampled }`;
137
+ - `groups/<id>/semantic-grade.json` records the judge's model, provider, family (approximated by provider), thinking, extensions and isolation; the subject's providers and the family relation (`same`, `different` or `unknown`); the label mapping, prompt hash, answers mapped back to variants, swap results, the effective `limits` and how many cuts the view took (`truncated`), `contractGaps` (at least `calibration not checked`, and `materials truncated` when anything was cut), and errors; `groups/<id>/review/` keeps the prompt, events, final response, and stderr;
138
+ - malformed or incomplete reviewer output becomes `review-error` with the raw response preserved.
139
+
140
+ A review is advisory. It never changes run or deterministic grade evidence, and rerunning it replaces only the previous advisory review.
141
+
142
+ When an unsupported operation changes the question, reject it or run a clearly separate direct comparison with explicit limits. Never invoke archived evaluators as a fallback.
143
+
144
+ ## Use The Strongest Evidence
145
+
146
+ Prefer, in order:
147
+
148
+ 1. filesystem state, typed workspace manifests, diffs, and changed paths;
149
+ 2. structured events, tool activity, usage, process results, logs, and saved reports;
150
+ 3. final response;
151
+ 4. full transcript when stronger surfaces cannot answer the question;
152
+ 5. subject self-assessment.
153
+
154
+ Lower-priority evidence cannot repair a contradiction above it.
155
+
156
+ If a response claims success but a required file is absent, preserve both facts and judge from the stronger artifact evidence.
157
+
158
+ ## Keep Deterministic Facts Separate
159
+
160
+ Deterministic grades are appended only after canonical run evidence exists. Built-in checks establish exact observable facts, such as:
161
+
162
+ - skill or resource reads;
163
+ - file and path state;
164
+ - changed paths;
165
+ - file or response text;
166
+ - JSON validity or values;
167
+ - tool-call outcomes and argument predicates;
168
+ - context text at a selected surface, request, and turn;
169
+ - a grader command's exit code and which required tests passed;
170
+ - factual transitions from the reference arm to each other arm.
171
+
172
+ Missing evidence remains unavailable. A failed check remains behavioral evidence and does not relabel a complete run as infrastructure failure; an expectation of an unknown kind or a grading failure produces separate `grade-error` evidence and does not rewrite run evidence. A transition such as `fail-to-pass` is a factual comparison. It does not mean bad-to-good, not-ready-to-ready, or rejected-to-promotable.
173
+
174
+ The active agent or user may judge:
175
+
176
+ - reasoning quality;
177
+ - authority preservation;
178
+ - architectural fitness;
179
+ - recommendation quality;
180
+ - semantic completeness.
181
+
182
+ Keep semantic judgment, cited evidence, uncertainty, and limits outside canonical run and deterministic grade state. Judged evidence from `review` and `review --rubric` is already stored apart; read it with each judge's identity and calibration, and when it disagrees with deterministic facts, the facts stand and the disagreement is reported.
183
+
184
+ Do not turn semantic or judged evidence into evaluator-owned readiness or promotion status.
185
+
186
+ ## Diagnose The Failed Boundary
187
+
188
+ Classify before revising:
189
+
190
+ - activation timing;
191
+ - description language unavailable before body read;
192
+ - first-read body comprehension;
193
+ - undeclared, undelivered, unread, or ambient-only dependency;
194
+ - normal guidance hidden behind the wrong resource boundary;
195
+ - nearby behavior that hijacks the task;
196
+ - retained-use or multi-turn failure;
197
+ - wording, placement, example, repetition, or stop-condition pressure;
198
+ - a component that never reached the model;
199
+ - a stage, simulated user or judge rather than the subject: an earlier pipeline stage, a user that left its card, or a judge that misread the run;
200
+ - fixture, environment, isolation, host, runner, grader-command, or deterministic-check failure.
201
+
202
+ Do not add broad prose before identifying which boundary failed.
203
+
204
+ ## Return Revision To The Owner
205
+
206
+ When evidence supports changing the component:
207
+
208
+ 1. name the exact failed boundary;
209
+ 2. cite the canonical evidence;
210
+ 3. identify one measured pressure point;
211
+ 4. preserve unrelated instructions and fixed criteria;
212
+ 5. return the revision target to the component's owner.
213
+
214
+ [Write Skill](../../write-skill/SKILL.md) owns revision of a skill or other instruction text, such as an instruction file. Extension code goes to its owner; a choice of model, setting or extension goes to the user.
215
+
216
+ Evaluate Behavior does not change the component or replace its baseline while evaluating it.
217
+
218
+ When evidence proves the group, fixture, or criterion is wrong, revise the evaluation instead. Preserve the old result and state that it no longer answers the revised question.
219
+
220
+ ## Rerun The Complete Group
221
+
222
+ After a measured revision or resolved infrastructure cause:
223
+
224
+ - rerun the complete fixed group;
225
+ - run every arm;
226
+ - keep every result visible;
227
+ - do not hand-pick an earlier reference run as a fresh counterpart; `--reuse` stands one in only when its inputs match exactly, and lists it as reused;
228
+ - do not rerun only the preferred arm;
229
+ - do not use partial evidence as a comparable full result;
230
+ - do not rerun merely to erase failure.
231
+
232
+ For variance, use `--trials` to run independent complete invocations rather than repeated preferred arms.
233
+
234
+ ## Report A Revision
235
+
236
+ Report:
237
+
238
+ - failed boundary and evidence;
239
+ - exact revision or evaluation correction;
240
+ - criteria that remained fixed;
241
+ - old and new result paths;
242
+ - deterministic transitions, and the decision's verdict when the suite declares one;
243
+ - remaining unsupported claims.
244
+
245
+ The user decides whether to revise further, adopt, or reject the change.
@@ -0,0 +1,76 @@
1
+ #!/usr/bin/env node
2
+ // Claude Code's PreToolUse hook for an evaluation subject: the same confinement rules as Pi's guard
3
+ // (guard-rules.mjs), read from the same SKILL_EVAL_* variables, decided for Claude Code's tool names. It allows a
4
+ // declared call explicitly, rewrites bash to run in the subject's container, and denies everything else, including
5
+ // any call it cannot decide.
6
+
7
+ import { readFileSync, realpathSync } from "node:fs";
8
+ import { pathToFileURL } from "node:url";
9
+
10
+ import { decideToolCall, guardState } from "./guard-rules.mjs";
11
+
12
+ // Claude Code's built-in tools and the evaluator tool each one stands for, with where its path argument is, and
13
+ // which argument is a file pattern searched from that path.
14
+ const TOOLS = {
15
+ Read: { tool: "read", path: "file_path" },
16
+ Write: { tool: "write", path: "file_path" },
17
+ Edit: { tool: "edit", path: "file_path" },
18
+ Glob: { tool: "find", path: "path", pattern: "pattern" },
19
+ Grep: { tool: "grep", path: "path", pattern: "glob" },
20
+ Bash: { tool: "bash" },
21
+ };
22
+
23
+ // A pattern that starts at the root or climbs out of its path would search outside the checked path.
24
+ function escapingPattern(pattern) {
25
+ if (typeof pattern !== "string") return false;
26
+ return pattern.startsWith("/") || pattern.startsWith("~") || pattern.split(/[\\/]/).includes("..");
27
+ }
28
+
29
+ function respond(output) {
30
+ process.stdout.write(JSON.stringify({ hookSpecificOutput: { hookEventName: "PreToolUse", ...output } }));
31
+ }
32
+
33
+ function deny(reason) {
34
+ respond({ permissionDecision: "deny", permissionDecisionReason: reason });
35
+ }
36
+
37
+ /**
38
+ * The hook's decision for one PreToolUse input, as the response it writes. Exported for tests.
39
+ *
40
+ * @param {any} input Claude Code's hook input: tool_name, tool_input, cwd
41
+ * @param {Record<string, string | undefined>} environment
42
+ */
43
+ export function decide(input, environment) {
44
+ const known = TOOLS[input?.tool_name];
45
+ if (known === undefined) {
46
+ return {
47
+ permissionDecision: "deny",
48
+ permissionDecisionReason: `Tool is not declared for this evaluation: ${input?.tool_name}`,
49
+ };
50
+ }
51
+ const state = guardState(environment);
52
+ // Glob lists and finds files, so a group that declares only ls gets it too.
53
+ const tool = known.tool === "find" && !state.allowedTools.has("find") ? "ls" : known.tool;
54
+ const arguments_ = input.tool_input ?? {};
55
+ if (known.pattern !== undefined && escapingPattern(arguments_[known.pattern])) {
56
+ return {
57
+ permissionDecision: "deny",
58
+ permissionDecisionReason: `${tool} pattern must be relative to its path inside the evaluation environment: ${arguments_[known.pattern]}`,
59
+ };
60
+ }
61
+ const mapped = known.path === undefined ? arguments_ : { path: arguments_[known.path] };
62
+ const decision = decideToolCall(state, tool, mapped, input.cwd ?? process.cwd(), environment);
63
+ if (decision?.block) return { permissionDecision: "deny", permissionDecisionReason: decision.reason };
64
+ if (decision?.command !== undefined) {
65
+ return { permissionDecision: "allow", updatedInput: { ...arguments_, command: decision.command } };
66
+ }
67
+ return { permissionDecision: "allow" };
68
+ }
69
+
70
+ if (process.argv[1] !== undefined && import.meta.url === pathToFileURL(realpathSync(process.argv[1])).href) {
71
+ try {
72
+ respond(decide(JSON.parse(readFileSync(0, "utf8")), process.env));
73
+ } catch (error) {
74
+ deny(`the evaluation guard could not decide this call: ${error instanceof Error ? error.message : String(error)}`);
75
+ }
76
+ }