@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.
- package/.agents/plugins/marketplace.json +2 -2
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +2 -2
- package/.codex-plugin/plugin.json +3 -3
- package/.cursor-plugin/plugin.json +1 -1
- package/README.md +96 -149
- package/capabilities/cognitive-routing/SKILL.md +21 -129
- package/capabilities/cognitive-routing/references/coordinator.md +163 -0
- package/capabilities/cognitive-routing/references/worker.md +38 -0
- package/capabilities/compaction/SKILL.md +3 -3
- package/capabilities/compaction/references/summary-format.md +26 -15
- package/capabilities/messaging/SKILL.md +49 -0
- package/capabilities/task-memory/SKILL.md +87 -0
- package/command-surface.json +6 -54
- package/gemini-extension.json +1 -1
- package/hooks/claude/hooks.json +13 -3
- package/hooks/codex/hooks.json +2 -1
- package/hooks/shared/runtime-context.mjs +69 -77
- package/package.json +25 -8
- package/pi-extension/dist/ask-user/ask.js +108 -0
- package/pi-extension/dist/ask-user/form.js +250 -0
- package/pi-extension/dist/ask-user/questions.js +66 -0
- package/pi-extension/dist/ask-user/tool.js +124 -0
- package/pi-extension/dist/cognitive-routing/assembler.js +35 -11
- package/pi-extension/dist/cognitive-routing/bootstrap.js +90 -0
- package/pi-extension/dist/cognitive-routing/config.js +3 -4
- package/pi-extension/dist/cognitive-routing/event-store.js +4 -1
- package/pi-extension/dist/cognitive-routing/gate.js +20 -5
- package/pi-extension/dist/cognitive-routing/handlers.js +15 -13
- package/pi-extension/dist/cognitive-routing/model-control.js +17 -8
- package/pi-extension/dist/cognitive-routing/projection.js +23 -6
- package/pi-extension/dist/cognitive-routing/provenance.js +3 -1
- package/pi-extension/dist/cognitive-routing/render.js +15 -15
- package/pi-extension/dist/cognitive-routing/runtime.js +4 -2
- package/pi-extension/dist/cognitive-routing/schemas.js +4 -4
- package/pi-extension/dist/cognitive-routing/session.js +3 -1
- package/pi-extension/dist/cognitive-routing/sources.js +29 -4
- package/pi-extension/dist/cognitive-routing/state.js +18 -8
- package/pi-extension/dist/cognitive-routing/status.js +4 -3
- package/pi-extension/dist/cognitive-routing/tools.js +29 -15
- package/pi-extension/dist/cognitive-routing/types.js +10 -1
- package/pi-extension/dist/compaction/carry.js +36 -22
- package/pi-extension/dist/compaction/config.js +4 -2
- package/pi-extension/dist/compaction/controller.js +52 -29
- package/pi-extension/dist/compaction/harness.js +19 -3
- package/pi-extension/dist/compaction/results.js +14 -13
- package/pi-extension/dist/compaction/tool.js +6 -6
- package/pi-extension/dist/host/catalog.js +20 -35
- package/pi-extension/dist/host/config-validation.js +233 -0
- package/pi-extension/dist/host/config.js +78 -91
- package/pi-extension/dist/host/inbound.js +142 -0
- package/pi-extension/dist/host/projection-tags.js +1 -1
- package/pi-extension/dist/host/prompts.js +24 -13
- package/pi-extension/dist/host/read-only-session.js +6 -1
- package/pi-extension/dist/host/request-history.js +7 -3
- package/pi-extension/dist/host/rows.js +25 -0
- package/pi-extension/dist/host/runtime-state.js +17 -2
- package/pi-extension/dist/host/section-keeper.js +85 -0
- package/pi-extension/dist/host/settings/freeflow-command.js +846 -93
- package/pi-extension/dist/host/settings/settings-view.js +27 -8
- package/pi-extension/dist/host/status.js +19 -5
- package/pi-extension/dist/index.js +638 -72
- package/pi-extension/dist/messaging/config.js +27 -0
- package/pi-extension/dist/messaging/messaging.js +398 -0
- package/pi-extension/dist/messaging/registry.js +57 -0
- package/pi-extension/dist/messaging/render.js +90 -0
- package/pi-extension/dist/messaging/tools.js +109 -0
- package/pi-extension/dist/messaging/transport.js +101 -0
- package/pi-extension/dist/provider-support/cache/keepalive.js +16 -4
- package/pi-extension/dist/task-memory/config.js +49 -0
- package/pi-extension/dist/task-memory/registry.js +119 -0
- package/pi-extension/dist/task-memory/render.js +107 -0
- package/pi-extension/dist/task-memory/runtime.js +994 -0
- package/pi-extension/dist/task-memory/tool.js +233 -0
- package/pi-extension/dist/tool-execution/apply-patch/tool.js +1 -1
- package/pi-extension/dist/tool-execution/background.js +220 -28
- package/pi-extension/dist/tool-execution/config.js +14 -3
- package/pi-extension/dist/tool-execution/file-tracking.js +24 -4
- package/pi-extension/dist/tool-execution/guidance-notices.js +124 -0
- package/pi-extension/dist/tool-execution/skill-reads.js +143 -0
- package/pi-extension/dist/tool-execution/tools.js +2 -2
- package/runtime/prompts/cognitive-routing.md +4 -4
- package/runtime/prompts/core.md +24 -14
- package/runtime/prompts/interaction-contract.md +7 -4
- package/runtime/prompts/tool-execution.md +3 -16
- package/runtime/prompts/working-method.md +16 -99
- package/skills/deliver-work/SKILL.md +76 -0
- package/skills/deliver-work/references/branch-closeout.md +134 -0
- package/skills/deliver-work/references/commit.md +83 -0
- package/skills/deliver-work/references/launch.md +94 -0
- package/skills/deliver-work/references/release.md +85 -0
- package/skills/deliver-work/scripts/commit-state.mjs +139 -0
- package/skills/deliver-work/scripts/delivery-state.mjs +107 -0
- package/skills/deliver-work/scripts/lib/git-state.mjs +178 -0
- package/skills/deliver-work/scripts/push-route.mjs +122 -0
- package/skills/deliver-work/scripts/release-preflight.mjs +177 -0
- package/skills/discuss-work/SKILL.md +148 -0
- package/skills/{discuss → discuss-work}/references/discussion-continuity.md +10 -27
- package/skills/discuss-work/references/learning-action.md +36 -0
- package/skills/discuss-work/scripts/choices.mjs +101 -0
- package/skills/discuss-work/scripts/lib/choices.mjs +159 -0
- package/skills/evaluate-behavior/SKILL.md +107 -0
- package/skills/evaluate-behavior/references/authoring.md +381 -0
- package/skills/evaluate-behavior/references/coding-tasks.md +145 -0
- package/skills/evaluate-behavior/references/conversations-pipelines-judges.md +177 -0
- package/skills/evaluate-behavior/references/design-and-measurement.md +273 -0
- package/skills/evaluate-behavior/references/running-and-evidence.md +245 -0
- package/skills/evaluate-behavior/scripts/claude-guard.mjs +76 -0
- package/skills/evaluate-behavior/scripts/guard-rules.mjs +309 -0
- package/skills/evaluate-behavior/scripts/lib/agreement.mjs +90 -0
- package/skills/evaluate-behavior/scripts/lib/arms.mjs +55 -0
- package/skills/evaluate-behavior/scripts/lib/budget.mjs +87 -0
- package/skills/evaluate-behavior/scripts/lib/build-source.mjs +287 -0
- package/skills/evaluate-behavior/scripts/lib/clear.mjs +74 -0
- package/skills/evaluate-behavior/scripts/lib/container.mjs +395 -0
- package/skills/evaluate-behavior/scripts/lib/decision.mjs +418 -0
- package/skills/evaluate-behavior/scripts/lib/definitions.mjs +1072 -0
- package/skills/evaluate-behavior/scripts/lib/freeflow.mjs +103 -0
- package/skills/evaluate-behavior/scripts/lib/grade-command.mjs +591 -0
- package/skills/evaluate-behavior/scripts/lib/grade-comparison.mjs +90 -0
- package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/grade-interaction.mjs +19 -18
- package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/grade-support.mjs +32 -5
- package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/grade-workspace.mjs +28 -12
- package/skills/evaluate-behavior/scripts/lib/grade.mjs +101 -0
- package/skills/evaluate-behavior/scripts/lib/hooks.mjs +98 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/confinement.mjs +196 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/constraints.mjs +111 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/index.mjs +48 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/isolation.mjs +74 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/launch.mjs +123 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/model-call.mjs +73 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/recorder.mjs +178 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/session.mjs +494 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/skills.mjs +81 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/index.mjs +31 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/names.mjs +3 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/pi/confinement.mjs +173 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/pi/host.mjs +148 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/pi/index.mjs +70 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/pi/isolation.mjs +81 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/pi/model-call.mjs +79 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/pi/process.mjs +241 -0
- package/skills/{evaluate-skill/scripts/lib → evaluate-behavior/scripts/lib/hosts/pi}/rpc.mjs +144 -26
- package/skills/evaluate-behavior/scripts/lib/identity.mjs +82 -0
- package/skills/evaluate-behavior/scripts/lib/judge.mjs +688 -0
- package/skills/evaluate-behavior/scripts/lib/metrics.mjs +332 -0
- package/skills/evaluate-behavior/scripts/lib/model-call.mjs +17 -0
- package/skills/evaluate-behavior/scripts/lib/participants.mjs +616 -0
- package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/process.mjs +22 -0
- package/skills/evaluate-behavior/scripts/lib/queue.mjs +54 -0
- package/skills/evaluate-behavior/scripts/lib/reference.mjs +343 -0
- package/skills/evaluate-behavior/scripts/lib/reuse.mjs +277 -0
- package/skills/evaluate-behavior/scripts/lib/review.mjs +933 -0
- package/skills/evaluate-behavior/scripts/lib/runner.mjs +732 -0
- package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/sandbox.mjs +119 -14
- package/skills/evaluate-behavior/scripts/lib/scan-shell.mjs +457 -0
- package/skills/evaluate-behavior/scripts/lib/scan.mjs +479 -0
- package/skills/evaluate-behavior/scripts/lib/seal.mjs +91 -0
- package/skills/evaluate-behavior/scripts/lib/shell.mjs +560 -0
- package/skills/evaluate-behavior/scripts/lib/source-override.mjs +64 -0
- package/skills/evaluate-behavior/scripts/lib/subject-file.mjs +88 -0
- package/skills/{evaluate-skill/scripts/lib/pi.mjs → evaluate-behavior/scripts/lib/subject.mjs} +235 -265
- package/skills/evaluate-behavior/scripts/lib/task-copy.mjs +124 -0
- package/skills/evaluate-behavior/scripts/lib/trials.mjs +524 -0
- package/skills/evaluate-behavior/scripts/lib/validity.mjs +68 -0
- package/skills/evaluate-behavior/scripts/lib/view-html.mjs +454 -0
- package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/view.mjs +159 -18
- package/skills/{evaluate-skill → evaluate-behavior}/scripts/pi-command-tool.mjs +21 -6
- package/skills/evaluate-behavior/scripts/pi-container-route.mjs +23 -0
- package/skills/evaluate-behavior/scripts/pi-guard.mjs +77 -0
- package/skills/evaluate-behavior/scripts/pi-login-refresh.mjs +31 -0
- package/skills/evaluate-behavior/scripts/skill-eval.mjs +586 -0
- package/skills/execute-work/SKILL.md +96 -104
- package/skills/execute-work/references/code-practices.md +27 -51
- package/skills/execute-work/references/design.md +271 -0
- package/skills/execute-work/references/diagnose.md +117 -0
- package/skills/execute-work/references/migration.md +108 -0
- package/skills/execute-work/references/simplify.md +65 -0
- package/skills/execute-work/scripts/self-review.mjs +422 -0
- package/skills/execute-work/scripts/touch-map.mjs +290 -0
- package/skills/review-work/SKILL.md +89 -65
- package/skills/review-work/references/adjudication.md +94 -0
- package/skills/review-work/references/artifact.md +198 -0
- package/skills/review-work/references/evals-and-judges.md +66 -0
- package/skills/review-work/references/work.md +177 -0
- package/skills/review-work/scripts/check-brief.mjs +128 -0
- package/skills/review-work/scripts/review-packet.mjs +233 -0
- package/skills/setup-freeflow/SKILL.md +68 -17
- package/skills/track-work/SKILL.md +52 -20
- package/skills/track-work/references/handoff.md +190 -0
- package/skills/track-work/references/projects.md +51 -0
- package/skills/track-work/references/working-record-format.md +36 -18
- package/skills/track-work/scripts/lib/document.mjs +17 -13
- package/skills/track-work/scripts/lib/format.mjs +2 -0
- package/skills/track-work/scripts/lib/recover.mjs +254 -0
- package/skills/track-work/scripts/lib/registry.mjs +656 -0
- package/skills/track-work/scripts/lib/search.mjs +40 -0
- package/skills/track-work/scripts/lib/store.mjs +46 -15
- package/skills/track-work/scripts/lib/views.mjs +50 -1
- package/skills/track-work/scripts/working-record.mjs +232 -13
- package/skills/verify-work/SKILL.md +45 -37
- package/skills/verify-work/references/feature-map.md +120 -0
- package/skills/verify-work/references/runtime-evidence.md +203 -0
- package/skills/verify-work/references/test-design.md +25 -6
- package/skills/verify-work/scripts/test-changes.mjs +246 -0
- package/skills/write-docs/SKILL.md +113 -25
- package/skills/write-docs/references/documentation-shapes.md +68 -3
- package/skills/write-docs/references/spec-and-plan-shapes.md +308 -0
- package/skills/write-docs/scripts/artifact-check.mjs +148 -0
- package/skills/write-docs/scripts/docs-check.mjs +96 -6
- package/skills/write-docs/scripts/plan-lint.mjs +123 -0
- package/skills/write-skill/SKILL.md +92 -52
- package/skills/write-skill/references/activation-and-wording.md +143 -0
- package/skills/write-skill/references/placement-and-dependencies.md +154 -0
- package/skills/write-skill/scripts/lib/compare.mjs +701 -0
- package/skills/write-skill/scripts/lib/skill-author.mjs +197 -3
- package/skills/write-skill/scripts/skill-author.mjs +51 -8
- package/capabilities/cognitive-routing/references/both-mode.md +0 -36
- package/capabilities/cognitive-routing/references/executor-mode.md +0 -48
- package/capabilities/cognitive-routing/references/helper-mode.md +0 -47
- package/plugin.json +0 -33
- package/skills/action-selection/SKILL.md +0 -92
- package/skills/action-selection/references/trajectory-stalls.md +0 -73
- package/skills/bypass/SKILL.md +0 -153
- package/skills/commit-work/SKILL.md +0 -93
- package/skills/commit-work/references/git-state-edges.md +0 -94
- package/skills/commit-work/references/simple-push.md +0 -94
- package/skills/commit-work/references/staging-decisions.md +0 -106
- package/skills/decision-gate/SKILL.md +0 -87
- package/skills/design-for-depth/SKILL.md +0 -108
- package/skills/design-for-depth/references/design-pressure-signals.md +0 -84
- package/skills/design-for-depth/references/implementation-decisions.md +0 -76
- package/skills/design-for-depth/references/interface-design-loop.md +0 -105
- package/skills/design-for-depth/references/module-and-dependency-design.md +0 -117
- package/skills/design-for-depth/references/state-and-failure-boundaries.md +0 -125
- package/skills/diagnose-failure/SKILL.md +0 -140
- package/skills/diagnose-failure/references/diagnostic-loop-catalog.md +0 -50
- package/skills/diagnose-failure/references/flaky-and-performance-diagnosis.md +0 -51
- package/skills/discuss/SKILL.md +0 -140
- package/skills/evaluate-skill/SKILL.md +0 -188
- package/skills/evaluate-skill/references/evaluation-definition-schema.md +0 -415
- package/skills/evaluate-skill/references/evaluation-design.md +0 -112
- package/skills/evaluate-skill/references/execution-and-evidence.md +0 -111
- package/skills/evaluate-skill/references/review-and-revision.md +0 -94
- package/skills/evaluate-skill/scripts/lib/definitions.mjs +0 -448
- package/skills/evaluate-skill/scripts/lib/grade-comparison.mjs +0 -60
- package/skills/evaluate-skill/scripts/lib/grade.mjs +0 -64
- package/skills/evaluate-skill/scripts/lib/review.mjs +0 -196
- package/skills/evaluate-skill/scripts/lib/runner.mjs +0 -405
- package/skills/evaluate-skill/scripts/lib/trials.mjs +0 -103
- package/skills/evaluate-skill/scripts/pi-guard.mjs +0 -181
- package/skills/evaluate-skill/scripts/skill-eval.mjs +0 -182
- package/skills/execute-work/references/execute-work-edges.md +0 -78
- package/skills/finish-branch/SKILL.md +0 -117
- package/skills/finish-branch/references/integration-options.md +0 -80
- package/skills/handoff/SKILL.md +0 -82
- package/skills/handoff/references/handoff-templates.md +0 -150
- package/skills/launch-work/SKILL.md +0 -116
- package/skills/launch-work/references/launch-readiness.md +0 -85
- package/skills/migration-work/SKILL.md +0 -115
- package/skills/migration-work/references/migration-lifecycle.md +0 -82
- package/skills/release-work/SKILL.md +0 -118
- package/skills/release-work/references/release-evidence.md +0 -78
- package/skills/review-artifact/SKILL.md +0 -143
- package/skills/review-artifact/references/adjudicate-artifact-review.md +0 -101
- package/skills/review-artifact/references/independent-artifact-reviewer-contract.md +0 -159
- package/skills/review-work/references/adjudicate-work-review.md +0 -97
- package/skills/review-work/references/independent-work-reviewer-contract.md +0 -139
- package/skills/review-work/references/security-risk-lens.md +0 -67
- package/skills/setup-freeflow/references/activation-contract.md +0 -103
- package/skills/setup-freeflow/references/host-setup.md +0 -67
- package/skills/simplify-code/SKILL.md +0 -85
- package/skills/simplify-code/references/simplification-patterns.md +0 -70
- package/skills/verify-work/references/browser-runtime-evidence.md +0 -51
- package/skills/verify-work/references/integration-evidence.md +0 -49
- package/skills/verify-work/references/performance-evidence.md +0 -59
- package/skills/workflow/SKILL.md +0 -171
- package/skills/workflow/references/domain-skill-composition.md +0 -45
- package/skills/write-plan/SKILL.md +0 -92
- package/skills/write-plan/references/plan-shapes.md +0 -156
- package/skills/write-skill/references/activation-boundaries.md +0 -106
- package/skills/write-skill/references/agent-first-instructions.md +0 -133
- package/skills/write-skill/references/progressive-disclosure.md +0 -129
- package/skills/write-skill/references/skill-dependency-graphs.md +0 -192
- package/skills/write-spec/SKILL.md +0 -85
- package/skills/write-spec/references/artifact-standards.md +0 -86
- package/skills/write-spec/references/decision-records.md +0 -80
- package/skills/write-spec/references/spec-shapes.md +0 -143
- /package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/evidence.mjs +0 -0
- /package/skills/{evaluate-skill → evaluate-behavior}/scripts/pi-observer.mjs +0 -0
|
@@ -0,0 +1,586 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { realpath } from "node:fs/promises";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { createInterface } from "node:readline/promises";
|
|
6
|
+
|
|
7
|
+
import { extensionLabel } from "./lib/build-source.mjs";
|
|
8
|
+
import { clearRun } from "./lib/clear.mjs";
|
|
9
|
+
import { loadDefinition, selectDefinition } from "./lib/definitions.mjs";
|
|
10
|
+
import "./lib/metrics.mjs";
|
|
11
|
+
import { createBudget } from "./lib/budget.mjs";
|
|
12
|
+
import { createLimiter, setCpuJobs } from "./lib/queue.mjs";
|
|
13
|
+
import { checkSelection } from "./lib/reference.mjs";
|
|
14
|
+
import { applySourceOverrides, parseSourceOverrides } from "./lib/source-override.mjs";
|
|
15
|
+
import { createRunReuse, resultsDirectory, runEvaluation } from "./lib/runner.mjs";
|
|
16
|
+
import { armSealing } from "./lib/seal.mjs";
|
|
17
|
+
import { calibrateJudges, reviewResult, reviewRubric } from "./lib/review.mjs";
|
|
18
|
+
import { runTrials } from "./lib/trials.mjs";
|
|
19
|
+
import { renderResult } from "./lib/view.mjs";
|
|
20
|
+
import { writeHtml } from "./lib/view-html.mjs";
|
|
21
|
+
|
|
22
|
+
const OPTIONS = {
|
|
23
|
+
run: [
|
|
24
|
+
"--group",
|
|
25
|
+
"--variant",
|
|
26
|
+
"--trials",
|
|
27
|
+
"--max-cost",
|
|
28
|
+
"--yes",
|
|
29
|
+
"--dry-run",
|
|
30
|
+
"--skip-reference-check",
|
|
31
|
+
"--jobs",
|
|
32
|
+
"--cpu-jobs",
|
|
33
|
+
"--results",
|
|
34
|
+
"--reuse",
|
|
35
|
+
"--pilot",
|
|
36
|
+
"--source",
|
|
37
|
+
],
|
|
38
|
+
"check-tasks": ["--group"],
|
|
39
|
+
clear: ["--group", "--variant", "--flag", "--all", "--reason", "--results"],
|
|
40
|
+
view: ["--group", "--variant", "--html", "--results"],
|
|
41
|
+
review: [
|
|
42
|
+
"--results",
|
|
43
|
+
"--group",
|
|
44
|
+
"--model",
|
|
45
|
+
"--thinking",
|
|
46
|
+
"--configuration",
|
|
47
|
+
"--swap",
|
|
48
|
+
"--swap-sample",
|
|
49
|
+
"--limit",
|
|
50
|
+
"--rubric",
|
|
51
|
+
"--calibrate",
|
|
52
|
+
],
|
|
53
|
+
};
|
|
54
|
+
const argv = process.argv.slice(2);
|
|
55
|
+
const [command] = argv;
|
|
56
|
+
|
|
57
|
+
function printUsage() {
|
|
58
|
+
process.stdout.write(
|
|
59
|
+
`Usage:
|
|
60
|
+
skill-eval run <suite-or-group-path> [options]
|
|
61
|
+
skill-eval view <result-id-or-directory> [options]
|
|
62
|
+
skill-eval review <result-id-or-directory> --model <provider/model> [options]
|
|
63
|
+
skill-eval check-tasks <suite-or-group-path> [--group <id-or-position>]
|
|
64
|
+
skill-eval review <result-or-aggregate-id> --rubric [options]
|
|
65
|
+
skill-eval review <result-or-aggregate-id> --calibrate <labels.json>
|
|
66
|
+
skill-eval clear <result-id-or-directory> [--group <id>] [--variant <arm>] (--flag <id>... | --all) --reason <text>
|
|
67
|
+
|
|
68
|
+
Commands:
|
|
69
|
+
run Execute selected evaluation groups
|
|
70
|
+
view Render selected stored evidence or a trial aggregate
|
|
71
|
+
review Record an advisory, arm-blind model answer to each group's review questions
|
|
72
|
+
check-tasks Check that each group's reference_solution passes its workspace and command checks, which must fail before it,
|
|
73
|
+
and list what each task's copy lacks against its original setting (Git history, ignored files, tools,
|
|
74
|
+
network); no model
|
|
75
|
+
clear Record that a person read a run's transcript-scan flags and they do not taint it (with --reason), then
|
|
76
|
+
rebuild the aggregates that list the run; until then a flagged run is held out of every count and decision
|
|
77
|
+
|
|
78
|
+
Selectors:
|
|
79
|
+
--group <id-or-position>
|
|
80
|
+
--variant <baseline|candidate> (run, view) or any other arm the selected groups declare
|
|
81
|
+
|
|
82
|
+
Run options:
|
|
83
|
+
--trials <n> Run n independent complete invocations and record an aggregate
|
|
84
|
+
(a suite's decision always aggregates; its trials schedule sets n)
|
|
85
|
+
--max-cost <total> Stop starting subjects once host-reported cost reaches the total
|
|
86
|
+
--yes Start without asking (the plan is printed either way; scripts never ask)
|
|
87
|
+
--dry-run Allow uncommitted inputs; the result is marked as a dry run and supports no claim
|
|
88
|
+
--skip-reference-check Run even when a declared reference_solution fails check-tasks (the result records it)
|
|
89
|
+
--jobs <n> Run up to n subjects at once across groups, arms and trials (default 1)
|
|
90
|
+
--cpu-jobs <n> Run up to n local CPU tasks at once, such as hidden test commands (default 2)
|
|
91
|
+
--reuse Count matching complete canonical runs from the results index as trials instead of
|
|
92
|
+
running them again (each once per run, listed as reused), and index this run's own
|
|
93
|
+
--pilot <n> Run the first n groups once first; stop with a report on any failed or invalid run,
|
|
94
|
+
check error, or comparison no arm passed; otherwise continue (the pilot counts as a trial)
|
|
95
|
+
--source <arm>=<sha> For this run only, use the commit for every Git source ref the arm declares (its subject,
|
|
96
|
+
Freeflow and source-built extensions); recorded, never written to the definition (repeatable)
|
|
97
|
+
|
|
98
|
+
Result location (run, view, review):
|
|
99
|
+
--results <dir> Store and find results under <dir> instead of <cwd>/.skill-eval/runs
|
|
100
|
+
|
|
101
|
+
Review options:
|
|
102
|
+
--model <provider/model> Required reviewer model
|
|
103
|
+
--thinking <level> Optional reviewer thinking level
|
|
104
|
+
--configuration <file> A schema 2 configuration file for the reviewer: its model, host extensions and settings
|
|
105
|
+
--swap Review again with the run labels in reverse order, and record agreement
|
|
106
|
+
--swap-sample <fraction> Swap only on a random sample of the groups (the fraction, rounded up), recorded
|
|
107
|
+
--rubric Judge each run alone, blind to its arm, against its group's rubric; the group's
|
|
108
|
+
judges, or --model, answer; judged evidence is stored beside each run; an
|
|
109
|
+
aggregate judges every trial
|
|
110
|
+
--calibrate <labels.json> Score judges against hand labels ({ "<run path>": { "<dimension>": answer } })
|
|
111
|
+
and record each judge configuration's calibration in the target's judged evidence
|
|
112
|
+
--limit <name>=<chars> Show the reviewer more or less: response, argument, file or materials (repeatable;
|
|
113
|
+
defaults 8000, 300, 20000, 60000). Anything cut is recorded as a contract gap.
|
|
114
|
+
|
|
115
|
+
Paths:
|
|
116
|
+
Definition paths resolve from the current working directory.
|
|
117
|
+
Suite group references resolve relative to the suite file.
|
|
118
|
+
Results are stored under <cwd>/.skill-eval/runs/<result-id>, or under --results.
|
|
119
|
+
view accepts a stored result or aggregate ID or an explicit directory.
|
|
120
|
+
|
|
121
|
+
Selection:
|
|
122
|
+
No selectors choose every suite group and every arm.
|
|
123
|
+
--group is invalid for a direct group definition or result.
|
|
124
|
+
|
|
125
|
+
Current run support:
|
|
126
|
+
Description and explicit-body groups with prompt or ordered turns
|
|
127
|
+
Working-tree or Git-backed ordered skills/context; optional fresh fixture copies
|
|
128
|
+
Description tools: read; body tools: read, write, edit, run_command for declared commands, or declared extension tools
|
|
129
|
+
Runtime profiles: Pi hosts, isolated or host system prompt, ordered immutable extension bundles, environment overrides
|
|
130
|
+
Deterministic reads, paths, changed paths, text, JSON, tool calls, context observations, and factual comparisons
|
|
131
|
+
Ordered suites run serially (or --jobs subjects at once) and continue after isolated variant, group, or
|
|
132
|
+
post-processing failures
|
|
133
|
+
Grade-first views show compact criterion details, usage, and result-relative artifact paths
|
|
134
|
+
`,
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function fail(message, exitCode = 2) {
|
|
139
|
+
process.stderr.write(`${message}\n`);
|
|
140
|
+
process.exitCode = exitCode;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function parseOperation(values) {
|
|
144
|
+
const [target, ...options] = values;
|
|
145
|
+
if (!target) throw new Error(`skill-eval ${command} requires a target`);
|
|
146
|
+
const allowed = OPTIONS[command];
|
|
147
|
+
const parsed = {
|
|
148
|
+
group: null,
|
|
149
|
+
variant: null,
|
|
150
|
+
trials: null,
|
|
151
|
+
maxCost: null,
|
|
152
|
+
model: null,
|
|
153
|
+
thinking: null,
|
|
154
|
+
configuration: null,
|
|
155
|
+
swapSample: null,
|
|
156
|
+
calibrate: null,
|
|
157
|
+
html: null,
|
|
158
|
+
reason: null,
|
|
159
|
+
jobs: null,
|
|
160
|
+
cpuJobs: null,
|
|
161
|
+
results: null,
|
|
162
|
+
pilot: null,
|
|
163
|
+
};
|
|
164
|
+
let swap = false;
|
|
165
|
+
let rubric = false;
|
|
166
|
+
const limits = {};
|
|
167
|
+
let yes = false;
|
|
168
|
+
let dryRun = false;
|
|
169
|
+
let reuse = false;
|
|
170
|
+
let skipReferenceCheck = false;
|
|
171
|
+
let all = false;
|
|
172
|
+
const sourceValues = [];
|
|
173
|
+
const flags = [];
|
|
174
|
+
const keys = {
|
|
175
|
+
"--jobs": "jobs",
|
|
176
|
+
"--cpu-jobs": "cpuJobs",
|
|
177
|
+
"--results": "results",
|
|
178
|
+
"--pilot": "pilot",
|
|
179
|
+
"--group": "group",
|
|
180
|
+
"--variant": "variant",
|
|
181
|
+
"--trials": "trials",
|
|
182
|
+
"--max-cost": "maxCost",
|
|
183
|
+
"--model": "model",
|
|
184
|
+
"--configuration": "configuration",
|
|
185
|
+
"--thinking": "thinking",
|
|
186
|
+
"--swap-sample": "swapSample",
|
|
187
|
+
"--calibrate": "calibrate",
|
|
188
|
+
"--html": "html",
|
|
189
|
+
"--reason": "reason",
|
|
190
|
+
};
|
|
191
|
+
for (let index = 0; index < options.length; index += 1) {
|
|
192
|
+
const option = options[index];
|
|
193
|
+
const value = options[index + 1];
|
|
194
|
+
if (!allowed.includes(option)) throw new Error(`Unknown option: ${option}`);
|
|
195
|
+
if (option === "--swap") {
|
|
196
|
+
swap = true;
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
if (option === "--rubric") {
|
|
200
|
+
rubric = true;
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
if (option === "--all") {
|
|
204
|
+
all = true;
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
if (option === "--flag") {
|
|
208
|
+
if (!value || value.startsWith("--")) throw new Error("--flag requires a flag ID, such as network-1");
|
|
209
|
+
flags.push(value);
|
|
210
|
+
index += 1;
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
if (option === "--source") {
|
|
214
|
+
if (!value || value.startsWith("--")) throw new Error("--source requires <arm>=<commit SHA>");
|
|
215
|
+
sourceValues.push(value);
|
|
216
|
+
index += 1;
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
if (option === "--limit") {
|
|
220
|
+
const [, name, chars] = /^([a-z]+)=(\d+)$/.exec(value ?? "") ?? [];
|
|
221
|
+
if (!name) throw new Error("--limit requires <name>=<chars>, such as file=40000");
|
|
222
|
+
if (Object.hasOwn(limits, name)) throw new Error(`--limit ${name} may be supplied only once`);
|
|
223
|
+
limits[name] = Number(chars);
|
|
224
|
+
index += 1;
|
|
225
|
+
continue;
|
|
226
|
+
}
|
|
227
|
+
if (option === "--yes") {
|
|
228
|
+
yes = true;
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
if (option === "--dry-run") {
|
|
232
|
+
dryRun = true;
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
if (option === "--reuse") {
|
|
236
|
+
reuse = true;
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
if (option === "--skip-reference-check") {
|
|
240
|
+
skipReferenceCheck = true;
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
if (!value || value.startsWith("--")) throw new Error(`${option} requires a value`);
|
|
244
|
+
const key = keys[option];
|
|
245
|
+
if (parsed[key] !== null) throw new Error(`${option} may be supplied only once`);
|
|
246
|
+
parsed[key] = value;
|
|
247
|
+
index += 1;
|
|
248
|
+
}
|
|
249
|
+
// Null when omitted: one trial, unless the suite's decision schedules its own.
|
|
250
|
+
let trials = null;
|
|
251
|
+
if (parsed.trials !== null) {
|
|
252
|
+
trials = Number(parsed.trials);
|
|
253
|
+
if (!/^\d+$/.test(parsed.trials) || trials < 1) throw new Error("--trials must be a positive integer");
|
|
254
|
+
}
|
|
255
|
+
let maxCost = null;
|
|
256
|
+
if (parsed.maxCost !== null) {
|
|
257
|
+
maxCost = Number(parsed.maxCost);
|
|
258
|
+
if (!Number.isFinite(maxCost) || maxCost <= 0) throw new Error("--max-cost must be a positive number");
|
|
259
|
+
}
|
|
260
|
+
const positive = (name, value, fallback) => {
|
|
261
|
+
if (value === null) return fallback;
|
|
262
|
+
if (!/^\d+$/.test(value) || Number(value) < 1) throw new Error(`${name} must be a positive integer`);
|
|
263
|
+
return Number(value);
|
|
264
|
+
};
|
|
265
|
+
const jobs = positive("--jobs", parsed.jobs, 1);
|
|
266
|
+
const cpuJobs = positive("--cpu-jobs", parsed.cpuJobs, null);
|
|
267
|
+
const pilot = positive("--pilot", parsed.pilot, null);
|
|
268
|
+
const swapSample = parsed.swapSample === null ? null : Number(parsed.swapSample);
|
|
269
|
+
if (swapSample !== null && !(swapSample > 0 && swapSample <= 1)) {
|
|
270
|
+
throw new Error("--swap-sample must be a fraction greater than 0 and at most 1");
|
|
271
|
+
}
|
|
272
|
+
if ([rubric, parsed.calibrate !== null, swap || swapSample !== null].filter(Boolean).length > 1) {
|
|
273
|
+
throw new Error("--rubric, --calibrate and swapping are separate review modes; use one");
|
|
274
|
+
}
|
|
275
|
+
// A rubric's judges may be declared by its group, and calibration starts no judge.
|
|
276
|
+
const needsModel = command === "review" && !rubric && parsed.calibrate === null;
|
|
277
|
+
if (needsModel && parsed.model === null && parsed.configuration === null) {
|
|
278
|
+
throw new Error("skill-eval review requires --model or --configuration");
|
|
279
|
+
}
|
|
280
|
+
if (command === "clear") {
|
|
281
|
+
if (all === flags.length > 0) throw new Error("skill-eval clear needs either --flag <id> (repeatable) or --all");
|
|
282
|
+
if (parsed.reason === null) throw new Error("skill-eval clear needs --reason, the person's reason for clearing");
|
|
283
|
+
}
|
|
284
|
+
return {
|
|
285
|
+
target,
|
|
286
|
+
clear: { flags: all ? "all" : flags, reason: parsed.reason },
|
|
287
|
+
selectors: { group: parsed.group, variant: parsed.variant },
|
|
288
|
+
trials,
|
|
289
|
+
maxCost,
|
|
290
|
+
model: parsed.model,
|
|
291
|
+
thinking: parsed.thinking,
|
|
292
|
+
configuration: parsed.configuration,
|
|
293
|
+
html: parsed.html,
|
|
294
|
+
swap,
|
|
295
|
+
swapSample,
|
|
296
|
+
rubric,
|
|
297
|
+
calibrate: parsed.calibrate,
|
|
298
|
+
limits,
|
|
299
|
+
yes,
|
|
300
|
+
dryRun,
|
|
301
|
+
jobs,
|
|
302
|
+
cpuJobs,
|
|
303
|
+
pilot,
|
|
304
|
+
reuse,
|
|
305
|
+
results: parsed.results,
|
|
306
|
+
skipReferenceCheck,
|
|
307
|
+
sources: parseSourceOverrides(sourceValues),
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
async function withCancellation(run) {
|
|
312
|
+
const controller = new AbortController();
|
|
313
|
+
const abort = () => controller.abort();
|
|
314
|
+
process.once("SIGINT", abort);
|
|
315
|
+
process.once("SIGTERM", abort);
|
|
316
|
+
try {
|
|
317
|
+
return await run(controller.signal);
|
|
318
|
+
} finally {
|
|
319
|
+
process.removeListener("SIGINT", abort);
|
|
320
|
+
process.removeListener("SIGTERM", abort);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
function printResult(result) {
|
|
325
|
+
process.stdout.write(`Result: ${result.id}\nPath: ${result.path}\nState: ${result.state}\n`);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* What a run will start, from the definition alone: subjects, the models they use, and any Freeflow builds.
|
|
330
|
+
* Printed before anything starts; an interactive terminal is asked to confirm unless --yes was given.
|
|
331
|
+
* Returns null when not confirmed, else the selected suite's decision rule (null when it declares none).
|
|
332
|
+
*/
|
|
333
|
+
async function planRun(operation, root) {
|
|
334
|
+
// Resolved the way the runner resolves it, so the plan loads exactly what will run.
|
|
335
|
+
const definitionPath = await realpath(path.resolve(root, operation.target));
|
|
336
|
+
const definition = await loadDefinition(definitionPath, { root });
|
|
337
|
+
const selection = selectDefinition(definition, operation.selectors);
|
|
338
|
+
// Refused here, before the plan, exactly as the runner would refuse it.
|
|
339
|
+
applySourceOverrides(selection, operation.sources);
|
|
340
|
+
const decision = definition.kind === "suite" ? (definition.decision ?? null) : null;
|
|
341
|
+
const schedule = decision?.trials ?? null;
|
|
342
|
+
if (schedule !== null && operation.trials !== null && operation.trials !== schedule.initial) {
|
|
343
|
+
throw new Error(
|
|
344
|
+
`the suite's decision schedules ${schedule.initial} initial trials; omit --trials or set it to ${schedule.initial}`,
|
|
345
|
+
);
|
|
346
|
+
}
|
|
347
|
+
const trials = schedule?.initial ?? operation.trials ?? 1;
|
|
348
|
+
let arms = 0;
|
|
349
|
+
let unsealed = 0;
|
|
350
|
+
const models = new Set();
|
|
351
|
+
const freeflow = new Set();
|
|
352
|
+
const extensions = new Set();
|
|
353
|
+
for (const { group, variants } of selection.groups) {
|
|
354
|
+
for (const [arm, state] of Object.entries(variants)) {
|
|
355
|
+
if (state !== "selected") continue;
|
|
356
|
+
arms += 1;
|
|
357
|
+
if (armSealing(group, arm).network === "host") unsealed += 1;
|
|
358
|
+
const model = group.variants[arm].model;
|
|
359
|
+
models.add(model ? `${model.model}${model.thinking ? ` (${model.thinking})` : ""}` : "host default");
|
|
360
|
+
if (group.variants[arm].freeflow) freeflow.add(group.variants[arm].freeflow.source.ref);
|
|
361
|
+
for (const extension of group.variants[arm].hostExtensions ?? []) {
|
|
362
|
+
extensions.add(extensionLabel(extension));
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
const groups = selection.groups.length;
|
|
367
|
+
let counts = `${groups} group${groups === 1 ? "" : "s"}, ${arms} arm${arms === 1 ? "" : "s"}, ${trials} trial${trials === 1 ? "" : "s"}`;
|
|
368
|
+
let subjects = `${arms * trials}`;
|
|
369
|
+
if (schedule !== null && schedule.max > schedule.initial) {
|
|
370
|
+
// Adaptive rounds add trials only to undecided cases, so the count is a range up to every case at max.
|
|
371
|
+
counts += `, adaptive up to ${schedule.max} per case`;
|
|
372
|
+
subjects += ` to ${arms * schedule.max}`;
|
|
373
|
+
}
|
|
374
|
+
let line = `Plan: ${subjects} subjects (${counts}); models: ${[...models].join(", ")}`;
|
|
375
|
+
if (freeflow.size > 0) line += `; Freeflow builds: ${[...freeflow].join(", ")}`;
|
|
376
|
+
if (extensions.size > 0) line += `; extensions: ${[...extensions].join(", ")}`;
|
|
377
|
+
if (operation.jobs > 1) line += `; ${operation.jobs} subjects at once`;
|
|
378
|
+
if (operation.pilot !== null) line += `; pilot of the first ${Math.min(operation.pilot, groups)} groups`;
|
|
379
|
+
if (operation.reuse) line += "; reusing matching runs";
|
|
380
|
+
// Said before anything starts: code the subject writes will run on this machine, with its network and files.
|
|
381
|
+
if (unsealed > 0) {
|
|
382
|
+
line += `; unsealed: ${unsealed} arm${unsealed === 1 ? " runs" : "s run"} declared commands or graders on the host`;
|
|
383
|
+
}
|
|
384
|
+
const overridden = Object.entries(operation.sources ?? {});
|
|
385
|
+
if (overridden.length > 0) line += `; sources: ${overridden.map(([arm, commit]) => `${arm}=${commit}`).join(", ")}`;
|
|
386
|
+
if (operation.dryRun) line += "; dry run";
|
|
387
|
+
process.stdout.write(`${line}\n`);
|
|
388
|
+
if (operation.yes || !process.stdin.isTTY || !process.stdout.isTTY) return { decision };
|
|
389
|
+
const readline = createInterface({ input: process.stdin, output: process.stdout });
|
|
390
|
+
const answer = await readline.question("Start? [y/N] ");
|
|
391
|
+
readline.close();
|
|
392
|
+
return /^y(es)?$/i.test(answer.trim()) ? { decision } : null;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
async function run(operation) {
|
|
396
|
+
const root = process.cwd();
|
|
397
|
+
const plan = await planRun(operation, root);
|
|
398
|
+
if (plan === null) {
|
|
399
|
+
process.stdout.write("Not started.\n");
|
|
400
|
+
process.exitCode = 1;
|
|
401
|
+
return;
|
|
402
|
+
}
|
|
403
|
+
if (operation.cpuJobs !== null) setCpuJobs(operation.cpuJobs);
|
|
404
|
+
await withCancellation(async (signal) => {
|
|
405
|
+
const common = {
|
|
406
|
+
root,
|
|
407
|
+
signal,
|
|
408
|
+
dryRun: operation.dryRun,
|
|
409
|
+
jobs: operation.jobs,
|
|
410
|
+
results: operation.results,
|
|
411
|
+
skipReferenceCheck: operation.skipReferenceCheck,
|
|
412
|
+
sources: operation.sources,
|
|
413
|
+
};
|
|
414
|
+
// A suite's decision is reached over an aggregate, so it always runs as trials, even a single one; so does a
|
|
415
|
+
// pilot, which then counts as the first part of that one trial instead of being paid for twice.
|
|
416
|
+
if (plan.decision === null && (operation.trials ?? 1) === 1 && operation.pilot === null) {
|
|
417
|
+
const shared = {
|
|
418
|
+
...common,
|
|
419
|
+
budget: createBudget(operation.maxCost),
|
|
420
|
+
subjects: createLimiter(operation.jobs),
|
|
421
|
+
reuse: createRunReuse(resultsDirectory(root, operation.results), operation.reuse),
|
|
422
|
+
};
|
|
423
|
+
const result = await runEvaluation(operation.target, operation.selectors, shared);
|
|
424
|
+
printResult(result);
|
|
425
|
+
if (result.state !== "complete") process.exitCode = 1;
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
const aggregate = await runTrials(operation.target, operation.selectors, {
|
|
429
|
+
...common,
|
|
430
|
+
trials: operation.trials,
|
|
431
|
+
maxCost: operation.maxCost,
|
|
432
|
+
onTrial: printResult,
|
|
433
|
+
reuse: operation.reuse,
|
|
434
|
+
pilot: operation.pilot,
|
|
435
|
+
});
|
|
436
|
+
if (aggregate.state === "pilot-stopped") {
|
|
437
|
+
reportPilot(aggregate.pilot.id, aggregate.pilot.problems);
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
if (aggregate.aggregate.pilot) reportPilot(aggregate.aggregate.pilot.id, []);
|
|
441
|
+
process.stdout.write(`Aggregate: ${aggregate.id}\nPath: ${aggregate.path}\nState: ${aggregate.state}\n`);
|
|
442
|
+
if (aggregate.state !== "complete") process.exitCode = 1;
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/** Prints a pilot's outcome; false (and a failing exit) when its problems stop the run. */
|
|
447
|
+
function reportPilot(id, problems) {
|
|
448
|
+
if (problems.length === 0) {
|
|
449
|
+
process.stdout.write(`Pilot: ${id} passed\n`);
|
|
450
|
+
return true;
|
|
451
|
+
}
|
|
452
|
+
process.stdout.write(`Pilot: ${id} stopped the run\n${problems.map((problem) => ` - ${problem}\n`).join("")}`);
|
|
453
|
+
process.exitCode = 1;
|
|
454
|
+
return false;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
/** Checks each selected group's reference_solution against its graders. Runs no subject; exits 1 if any is unsolvable. */
|
|
458
|
+
async function checkTasks(operation) {
|
|
459
|
+
const root = process.cwd();
|
|
460
|
+
const definitionPath = await realpath(path.resolve(root, operation.target));
|
|
461
|
+
const selection = selectDefinition(await loadDefinition(definitionPath, { root }), operation.selectors);
|
|
462
|
+
const results = await checkSelection(selection, { root });
|
|
463
|
+
for (const [index, result] of results.entries()) {
|
|
464
|
+
// Each group is named with its file, so a suite with many groups shows which one to fix.
|
|
465
|
+
const file = path.relative(root, selection.groups[index].group.files[0]);
|
|
466
|
+
process.stdout.write(`${result.id} (${file}): ${result.state}${result.reason ? ` (${result.reason})` : ""}\n`);
|
|
467
|
+
for (const arm of result.arms ?? []) process.stdout.write(` ${arm.arm}: ${arm.state}\n`);
|
|
468
|
+
// What the task's copy lacks against its original setting; reported for the author to judge, never refused.
|
|
469
|
+
for (const gap of result.copy?.gaps ?? []) process.stdout.write(` copy lacks: ${gap}\n`);
|
|
470
|
+
for (const [arm, tools] of Object.entries(result.copy?.tools ?? {})) {
|
|
471
|
+
process.stdout.write(` ${arm} tools: ${tools.join(", ") || "none"}; network: ${result.copy.network[arm]}\n`);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
if (results.some((result) => result.state === "unsolvable" || result.state === "already-solved")) {
|
|
475
|
+
process.exitCode = 1;
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
async function review(operation) {
|
|
480
|
+
if (operation.calibrate !== null) return calibrate(operation);
|
|
481
|
+
if (operation.rubric) return judge(operation);
|
|
482
|
+
const outcome = await withCancellation((signal) =>
|
|
483
|
+
reviewResult(operation.target, operation.selectors, {
|
|
484
|
+
root: process.cwd(),
|
|
485
|
+
results: operation.results,
|
|
486
|
+
signal,
|
|
487
|
+
model: operation.model,
|
|
488
|
+
thinking: operation.thinking,
|
|
489
|
+
configuration: operation.configuration,
|
|
490
|
+
swap: operation.swap,
|
|
491
|
+
swapSample: operation.swapSample,
|
|
492
|
+
limits: operation.limits,
|
|
493
|
+
}),
|
|
494
|
+
);
|
|
495
|
+
for (const group of outcome.groups) {
|
|
496
|
+
process.stdout.write(`Review ${group.id}: ${group.state}${group.artifact ? ` (${group.artifact})` : ""}\n`);
|
|
497
|
+
}
|
|
498
|
+
if (outcome.groups.some((group) => group.state === "review-error")) process.exitCode = 1;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
function printAggregate(aggregate) {
|
|
502
|
+
if (aggregate === null) return;
|
|
503
|
+
process.stdout.write(`Aggregate: rebuilt; claim: ${aggregate.claim ?? "none"}\n`);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
async function judge(operation) {
|
|
507
|
+
const outcome = await withCancellation((signal) =>
|
|
508
|
+
reviewRubric(operation.target, operation.selectors, {
|
|
509
|
+
root: process.cwd(),
|
|
510
|
+
results: operation.results,
|
|
511
|
+
signal,
|
|
512
|
+
model: operation.model,
|
|
513
|
+
thinking: operation.thinking,
|
|
514
|
+
configuration: operation.configuration,
|
|
515
|
+
limits: operation.limits,
|
|
516
|
+
}),
|
|
517
|
+
);
|
|
518
|
+
for (const entry of outcome.groups) {
|
|
519
|
+
const where = entry.artifact ? ` (${entry.artifact})` : entry.reason ? ` (${entry.reason})` : "";
|
|
520
|
+
process.stdout.write(`Judged ${entry.id}${entry.arm ? ` ${entry.arm}` : ""}: ${entry.state}${where}\n`);
|
|
521
|
+
}
|
|
522
|
+
printAggregate(outcome.aggregate);
|
|
523
|
+
if (outcome.groups.some((entry) => entry.state === "judge-error")) process.exitCode = 1;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
async function calibrate(operation) {
|
|
527
|
+
const outcome = await calibrateJudges(operation.target, operation.calibrate, {
|
|
528
|
+
root: process.cwd(),
|
|
529
|
+
results: operation.results,
|
|
530
|
+
});
|
|
531
|
+
const number = (value) => (value === null ? "-" : value.toFixed(2));
|
|
532
|
+
for (const calibration of outcome.calibrations) {
|
|
533
|
+
const name = `${calibration.model}${calibration.thinking ? ` (${calibration.thinking})` : ""}`;
|
|
534
|
+
const dimensions = Object.entries(calibration.dimensions).map(
|
|
535
|
+
([id, { items, agreement, kappa }]) =>
|
|
536
|
+
`${id}: agreement=${number(agreement)} kappa=${number(kappa)} over ${items}`,
|
|
537
|
+
);
|
|
538
|
+
process.stdout.write(`Calibration ${name} [${calibration.configuration}]: ${dimensions.join("; ")}\n`);
|
|
539
|
+
}
|
|
540
|
+
process.stdout.write(`Judged grades updated: ${outcome.updated}\n`);
|
|
541
|
+
printAggregate(outcome.aggregate);
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
if (!command || command === "--help" || command === "-h") {
|
|
545
|
+
printUsage();
|
|
546
|
+
} else if (Object.hasOwn(OPTIONS, command)) {
|
|
547
|
+
try {
|
|
548
|
+
const operation = parseOperation(argv.slice(1));
|
|
549
|
+
if (command === "view" && operation.html !== null) {
|
|
550
|
+
const written = await writeHtml(operation.target, operation.html, {
|
|
551
|
+
root: process.cwd(),
|
|
552
|
+
results: operation.results,
|
|
553
|
+
selectors: operation.selectors,
|
|
554
|
+
});
|
|
555
|
+
process.stdout.write(`Wrote ${written}\n`);
|
|
556
|
+
} else if (command === "view") {
|
|
557
|
+
process.stdout.write(
|
|
558
|
+
await renderResult(operation.target, operation.selectors, { root: process.cwd(), results: operation.results }),
|
|
559
|
+
);
|
|
560
|
+
} else if (command === "review") {
|
|
561
|
+
await review(operation);
|
|
562
|
+
} else if (command === "check-tasks") {
|
|
563
|
+
await checkTasks(operation);
|
|
564
|
+
} else if (command === "clear") {
|
|
565
|
+
const outcome = await clearRun(operation.target, {
|
|
566
|
+
group: operation.selectors.group,
|
|
567
|
+
variant: operation.selectors.variant,
|
|
568
|
+
flags: operation.clear.flags,
|
|
569
|
+
reason: operation.clear.reason,
|
|
570
|
+
root: process.cwd(),
|
|
571
|
+
results: operation.results,
|
|
572
|
+
});
|
|
573
|
+
process.stdout.write(
|
|
574
|
+
`Cleared ${outcome.result} ${outcome.group} ${outcome.arm}: ${outcome.cleared.join(", ") || "nothing new"}\n` +
|
|
575
|
+
`Still held by: ${outcome.remaining.join(", ") || "nothing"}\n` +
|
|
576
|
+
`Aggregates rebuilt: ${outcome.rebuilt.join(", ") || "none"}\n`,
|
|
577
|
+
);
|
|
578
|
+
} else {
|
|
579
|
+
await run(operation);
|
|
580
|
+
}
|
|
581
|
+
} catch (error) {
|
|
582
|
+
fail(error instanceof Error ? error.message : String(error), 1);
|
|
583
|
+
}
|
|
584
|
+
} else {
|
|
585
|
+
fail(`Unknown command: ${command}`);
|
|
586
|
+
}
|