@hassangameryt/freeflow 0.7.3 → 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/NOTICE +14 -0
- package/README.md +101 -159
- package/capabilities/cognitive-routing/SKILL.md +47 -210
- package/capabilities/cognitive-routing/references/coordinator.md +163 -0
- package/capabilities/cognitive-routing/references/worker.md +38 -0
- package/capabilities/compaction/SKILL.md +49 -0
- package/capabilities/compaction/references/summary-format.md +250 -0
- package/capabilities/messaging/SKILL.md +49 -0
- package/capabilities/task-memory/SKILL.md +87 -0
- package/command-surface.json +8 -52
- 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 +73 -83
- package/licenses/Apache-2.0.txt +55 -0
- package/package.json +42 -12
- package/pi-extension/README.md +41 -0
- 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 +417 -0
- package/pi-extension/dist/cognitive-routing/bootstrap.js +90 -0
- package/pi-extension/dist/{cognitive-routing-v2 → cognitive-routing}/config.js +8 -6
- package/pi-extension/dist/cognitive-routing/economics.js +45 -0
- package/pi-extension/dist/cognitive-routing/event-schema.js +388 -0
- package/pi-extension/dist/{session-sources/events.js → cognitive-routing/event-store.js} +107 -41
- package/pi-extension/dist/cognitive-routing/gate.js +256 -0
- package/pi-extension/dist/cognitive-routing/handlers.js +901 -0
- package/pi-extension/dist/cognitive-routing/handoffs.js +350 -0
- package/pi-extension/dist/cognitive-routing/model-control.js +476 -0
- package/pi-extension/dist/cognitive-routing/projection.js +520 -0
- package/pi-extension/dist/cognitive-routing/provenance.js +83 -0
- package/pi-extension/dist/{cognitive-routing-v2 → cognitive-routing}/render.js +15 -15
- package/pi-extension/dist/cognitive-routing/runtime.js +398 -0
- package/pi-extension/dist/{cognitive-routing-v2 → cognitive-routing}/schemas.js +47 -11
- package/pi-extension/dist/cognitive-routing/session.js +223 -0
- package/pi-extension/dist/{session-sources → cognitive-routing}/sources.js +126 -87
- package/pi-extension/dist/{cognitive-routing-v2 → cognitive-routing}/state.js +55 -386
- package/pi-extension/dist/cognitive-routing/status.js +81 -0
- package/pi-extension/dist/cognitive-routing/tools.js +74 -0
- package/pi-extension/dist/{cognitive-routing-v2 → cognitive-routing}/types.js +14 -11
- package/pi-extension/dist/compaction/carry.js +205 -0
- package/pi-extension/dist/compaction/config.js +24 -0
- package/pi-extension/dist/compaction/controller.js +494 -0
- package/pi-extension/dist/compaction/harness.js +93 -0
- package/pi-extension/dist/compaction/results.js +159 -0
- package/pi-extension/dist/compaction/thresholds.js +35 -0
- package/pi-extension/dist/compaction/tool.js +57 -0
- package/pi-extension/dist/host/branch.js +13 -0
- package/pi-extension/dist/host/canonical.js +12 -0
- package/pi-extension/dist/host/catalog.js +62 -0
- package/pi-extension/dist/host/config-validation.js +233 -0
- package/pi-extension/dist/host/config.js +361 -0
- package/pi-extension/dist/host/inbound.js +142 -0
- package/pi-extension/dist/host/projection-tags.js +60 -0
- package/pi-extension/dist/host/prompts.js +93 -0
- package/pi-extension/dist/{session-sources → host}/read-only-session.js +117 -1
- package/pi-extension/dist/{runtime → host}/request-history.js +125 -39
- package/pi-extension/dist/host/rows.js +25 -0
- package/pi-extension/dist/host/runtime-state.js +204 -0
- package/pi-extension/dist/host/section-keeper.js +85 -0
- package/pi-extension/dist/host/settings/freeflow-command.js +2323 -0
- package/pi-extension/dist/{settings/settings-tui.js → host/settings/settings-view.js} +205 -73
- package/pi-extension/dist/host/staging.js +28 -0
- package/pi-extension/dist/host/status.js +115 -0
- package/pi-extension/dist/index.js +1004 -188
- 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/anchor.js +21 -0
- package/pi-extension/dist/provider-support/cache/anthropic.js +102 -0
- package/pi-extension/dist/provider-support/cache/health.js +73 -0
- package/pi-extension/dist/provider-support/cache/index.js +58 -0
- package/pi-extension/dist/provider-support/cache/keepalive.js +222 -0
- package/pi-extension/dist/provider-support/cache/monitor.js +17 -0
- package/pi-extension/dist/provider-support/cache/openai-responses.js +48 -0
- package/pi-extension/dist/provider-support/effort.js +13 -0
- package/pi-extension/dist/provider-support/index.js +44 -3
- package/pi-extension/dist/provider-support/{astra → openai}/adapter.js +46 -29
- package/pi-extension/dist/provider-support/{astra → openai}/history.js +10 -8
- package/pi-extension/dist/provider-support/{astra → openai}/index.js +8 -4
- package/pi-extension/dist/provider-support/{astra → openai}/session-state.js +29 -38
- package/pi-extension/dist/provider-support/routes.js +17 -0
- 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/grammar.js +23 -0
- package/pi-extension/dist/tool-execution/apply-patch/match.js +38 -0
- package/pi-extension/dist/tool-execution/apply-patch/parser.js +177 -0
- package/pi-extension/dist/tool-execution/apply-patch/plan.js +201 -0
- package/pi-extension/dist/tool-execution/apply-patch/tool.js +84 -0
- package/pi-extension/dist/tool-execution/background.js +430 -0
- package/pi-extension/dist/tool-execution/bash-guard.js +23 -0
- package/pi-extension/dist/tool-execution/config.js +33 -0
- package/pi-extension/dist/tool-execution/edit-messages.js +120 -0
- package/pi-extension/dist/tool-execution/file-state.js +138 -0
- package/pi-extension/dist/tool-execution/file-tracking.js +163 -0
- package/pi-extension/dist/tool-execution/guidance-notices.js +124 -0
- package/pi-extension/dist/tool-execution/prompt.js +54 -0
- package/pi-extension/dist/tool-execution/skill-reads.js +143 -0
- package/pi-extension/dist/tool-execution/tools.js +16 -0
- package/pi-extension/freeflow/README.md +9 -0
- package/runtime/prompts/cognitive-routing.md +4 -4
- package/runtime/prompts/core.md +29 -72
- package/runtime/prompts/interaction-contract.md +18 -8
- package/runtime/prompts/tool-execution.md +25 -0
- package/runtime/prompts/working-method.md +25 -0
- 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 +13 -50
- 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 +121 -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} +239 -262
- 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 +218 -11
- package/skills/evaluate-behavior/scripts/pi-command-tool.mjs +159 -0
- 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 -72
- package/skills/execute-work/references/code-practices.md +27 -49
- 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 +94 -64
- 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 +69 -16
- package/skills/track-work/SKILL.md +135 -151
- 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 +201 -344
- package/skills/track-work/scripts/lib/document.mjs +79 -19
- package/skills/track-work/scripts/lib/format.mjs +18 -1
- 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 +53 -21
- package/skills/track-work/scripts/lib/transitions.mjs +79 -4
- package/skills/track-work/scripts/lib/views.mjs +50 -1
- package/skills/track-work/scripts/working-record.mjs +263 -22
- package/skills/verify-work/SKILL.md +64 -47
- 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 +27 -6
- package/skills/verify-work/scripts/test-changes.mjs +246 -0
- package/skills/write-docs/SKILL.md +171 -0
- package/skills/write-docs/references/documentation-shapes.md +184 -0
- 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 +229 -0
- package/skills/write-docs/scripts/plan-lint.mjs +123 -0
- package/skills/write-skill/SKILL.md +165 -165
- 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/similarity.mjs +56 -0
- package/skills/write-skill/scripts/lib/skill-author.mjs +197 -3
- package/skills/write-skill/scripts/skill-author.mjs +67 -8
- package/capabilities/context-virtualization/SKILL.md +0 -103
- package/capabilities/conversation-history/SKILL.md +0 -53
- package/hooks/tests/check-host-adapters.test.mjs +0 -82
- package/hooks/tests/check-runtime-context-hook.sh +0 -212
- package/pi-extension/dist/cognitive-routing-v2/projection.js +0 -330
- package/pi-extension/dist/cognitive-routing-v2/runtime.js +0 -2181
- package/pi-extension/dist/cognitive-routing-v2/tools.js +0 -60
- package/pi-extension/dist/context-virtualization/commands.js +0 -89
- package/pi-extension/dist/context-virtualization/projector.js +0 -42
- package/pi-extension/dist/context-virtualization/runtime.js +0 -378
- package/pi-extension/dist/context-virtualization/state.js +0 -57
- package/pi-extension/dist/context-virtualization/types.js +0 -10
- package/pi-extension/dist/conversation-history/passages.js +0 -66
- package/pi-extension/dist/conversation-history/ranking.js +0 -105
- package/pi-extension/dist/conversation-history/runtime.js +0 -226
- package/pi-extension/dist/conversation-history/search.js +0 -56
- package/pi-extension/dist/conversation-history/types.js +0 -1
- package/pi-extension/dist/freeflow-context/resolver.js +0 -120
- package/pi-extension/dist/freeflow-context/runtime.js +0 -80
- package/pi-extension/dist/freeflow-context/source-projector.js +0 -95
- package/pi-extension/dist/freeflow-context/tool.js +0 -314
- package/pi-extension/dist/freeflow-context/types.js +0 -12
- package/pi-extension/dist/freeflow-context/visibility.js +0 -28
- package/pi-extension/dist/integrations/mcp-config.js +0 -29
- package/pi-extension/dist/runtime/runtime-context.js +0 -754
- package/pi-extension/dist/runtime/runtime-identity.js +0 -5
- package/pi-extension/dist/session-sources/provenance.js +0 -32
- package/pi-extension/dist/settings/settings-ui.js +0 -1360
- package/pi-extension/dist/ui/text-component.js +0 -57
- package/pi-extension/src/cognitive-routing-v2/budget.ts +0 -42
- package/pi-extension/src/cognitive-routing-v2/config.ts +0 -173
- package/pi-extension/src/cognitive-routing-v2/projection.ts +0 -375
- package/pi-extension/src/cognitive-routing-v2/render.ts +0 -277
- package/pi-extension/src/cognitive-routing-v2/runtime.ts +0 -2241
- package/pi-extension/src/cognitive-routing-v2/schemas.ts +0 -180
- package/pi-extension/src/cognitive-routing-v2/state.ts +0 -839
- package/pi-extension/src/cognitive-routing-v2/tools.ts +0 -62
- package/pi-extension/src/cognitive-routing-v2/types.ts +0 -254
- package/pi-extension/src/context-virtualization/commands.ts +0 -111
- package/pi-extension/src/context-virtualization/projector.ts +0 -62
- package/pi-extension/src/context-virtualization/runtime.ts +0 -428
- package/pi-extension/src/context-virtualization/state.ts +0 -79
- package/pi-extension/src/context-virtualization/types.ts +0 -92
- package/pi-extension/src/conversation-history/passages.ts +0 -81
- package/pi-extension/src/conversation-history/ranking.ts +0 -155
- package/pi-extension/src/conversation-history/runtime.ts +0 -250
- package/pi-extension/src/conversation-history/search.ts +0 -79
- package/pi-extension/src/conversation-history/types.ts +0 -31
- package/pi-extension/src/freeflow-context/resolver.ts +0 -139
- package/pi-extension/src/freeflow-context/runtime.ts +0 -100
- package/pi-extension/src/freeflow-context/source-projector.ts +0 -106
- package/pi-extension/src/freeflow-context/tool.ts +0 -366
- package/pi-extension/src/freeflow-context/types.ts +0 -70
- package/pi-extension/src/freeflow-context/visibility.ts +0 -53
- package/pi-extension/src/index.ts +0 -390
- package/pi-extension/src/integrations/mcp-config.ts +0 -32
- package/pi-extension/src/provider-support/astra/adapter.ts +0 -108
- package/pi-extension/src/provider-support/astra/history.ts +0 -145
- package/pi-extension/src/provider-support/astra/index.ts +0 -12
- package/pi-extension/src/provider-support/astra/session-state.ts +0 -113
- package/pi-extension/src/provider-support/index.ts +0 -5
- package/pi-extension/src/runtime/request-history.ts +0 -243
- package/pi-extension/src/runtime/runtime-context.ts +0 -860
- package/pi-extension/src/runtime/runtime-identity.ts +0 -8
- package/pi-extension/src/session-sources/events.ts +0 -230
- package/pi-extension/src/session-sources/provenance.ts +0 -39
- package/pi-extension/src/session-sources/read-only-session.ts +0 -170
- package/pi-extension/src/session-sources/sources.ts +0 -334
- package/pi-extension/src/settings/settings-tui.ts +0 -501
- package/pi-extension/src/settings/settings-ui.ts +0 -1652
- package/pi-extension/src/ui/text-component.ts +0 -66
- package/pi-extension/tests/cache-reuse/history.test.js +0 -117
- package/pi-extension/tests/cache-reuse/native.test.js +0 -91
- package/pi-extension/tests/cache-reuse/settings.test.js +0 -211
- package/pi-extension/tests/cognitive-routing-v2/communication.test.js +0 -577
- package/pi-extension/tests/cognitive-routing-v2/compaction-input.test.js +0 -183
- package/pi-extension/tests/cognitive-routing-v2/delegation.test.js +0 -557
- package/pi-extension/tests/cognitive-routing-v2/native.test.js +0 -474
- package/pi-extension/tests/cognitive-routing-v2/performance.test.js +0 -87
- package/pi-extension/tests/cognitive-routing-v2/persistence.test.js +0 -300
- package/pi-extension/tests/cognitive-routing-v2/projection.test.js +0 -241
- package/pi-extension/tests/cognitive-routing-v2/recovery.test.js +0 -1034
- package/pi-extension/tests/cognitive-routing-v2/render.test.js +0 -244
- package/pi-extension/tests/cognitive-routing-v2/runtime.test.js +0 -423
- package/pi-extension/tests/cognitive-routing-v2/stabilization.test.js +0 -521
- package/pi-extension/tests/cognitive-routing-v2/state.test.js +0 -586
- package/pi-extension/tests/context-virtualization/extension.test.js +0 -775
- package/pi-extension/tests/context-virtualization/projector.test.js +0 -110
- package/pi-extension/tests/context-virtualization/runtime.test.js +0 -230
- package/pi-extension/tests/conversation-history/runtime.test.js +0 -98
- package/pi-extension/tests/conversation-history/search.test.js +0 -97
- package/pi-extension/tests/fixtures/pi-host.js +0 -4
- package/pi-extension/tests/fixtures/routing-native.js +0 -191
- package/pi-extension/tests/integration/mode-free-core.test.js +0 -220
- package/pi-extension/tests/integration/pi-extension.test.js +0 -1447
- package/pi-extension/tests/integration/prompt-architecture.test.js +0 -447
- package/pi-extension/tests/integration/unaffected-regressions.test.js +0 -478
- package/pi-extension/tests/provider-support/astra-boundaries.test.js +0 -75
- package/pi-extension/tests/provider-support/astra.test.js +0 -306
- package/pi-extension/tests/provider-support/cli.test.js +0 -92
- package/pi-extension/tests/provider-support/native.test.js +0 -183
- package/pi-extension/tests/settings/settings-tui.test.js +0 -243
- package/pi-extension/tsconfig.json +0 -16
- package/plugin.json +0 -33
- package/runtime/prompts/context-virtualization.md +0 -3
- package/runtime/prompts/conversation-history.md +0 -3
- package/skills/action-selection/SKILL.md +0 -100
- package/skills/action-selection/references/trajectory-stalls.md +0 -71
- package/skills/bypass/SKILL.md +0 -153
- package/skills/commit-work/SKILL.md +0 -145
- package/skills/commit-work/references/git-state-edges.md +0 -94
- package/skills/commit-work/references/simple-push.md +0 -92
- package/skills/commit-work/references/staging-decisions.md +0 -106
- package/skills/decision-gate/SKILL.md +0 -106
- package/skills/design-for-depth/SKILL.md +0 -117
- package/skills/design-for-depth/references/design-pressure-signals.md +0 -182
- package/skills/design-for-depth/references/implementation-decisions.md +0 -76
- package/skills/design-for-depth/references/interface-design-loop.md +0 -136
- package/skills/design-for-depth/references/module-and-dependency-design.md +0 -147
- package/skills/design-for-depth/references/software-design-philosophy.md +0 -202
- package/skills/design-for-depth/references/state-and-failure-boundaries.md +0 -136
- package/skills/diagnose-failure/SKILL.md +0 -125
- package/skills/diagnose-failure/references/diagnostic-loop-catalog.md +0 -48
- package/skills/diagnose-failure/references/flaky-and-performance-diagnosis.md +0 -51
- package/skills/discuss/SKILL.md +0 -116
- package/skills/evaluate-skill/SKILL.md +0 -219
- package/skills/evaluate-skill/references/evaluation-definition-schema.md +0 -385
- package/skills/evaluate-skill/references/evaluation-design.md +0 -112
- package/skills/evaluate-skill/references/execution-and-evidence.md +0 -90
- package/skills/evaluate-skill/references/review-and-revision.md +0 -92
- package/skills/evaluate-skill/scripts/lib/definitions.mjs +0 -407
- 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/runner.mjs +0 -368
- package/skills/evaluate-skill/scripts/pi-guard.mjs +0 -164
- package/skills/evaluate-skill/scripts/skill-eval.mjs +0 -102
- package/skills/execute-work/references/execute-work-edges.md +0 -68
- 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 -142
- 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 -69
- package/skills/setup-freeflow/references/activation-contract.md +0 -109
- 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 -55
- package/skills/verify-work/references/integration-evidence.md +0 -47
- package/skills/verify-work/references/performance-evidence.md +0 -57
- package/skills/workflow/SKILL.md +0 -127
- package/skills/workflow/references/domain-skill-composition.md +0 -43
- 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 -104
- package/skills/write-skill/references/agent-first-instructions.md +0 -121
- package/skills/write-skill/references/progressive-disclosure.md +0 -127
- package/skills/write-skill/references/skill-dependency-graphs.md +0 -190
- package/skills/write-spec/SKILL.md +0 -92
- package/skills/write-spec/references/artifact-standards.md +0 -86
- package/skills/write-spec/references/decision-records.md +0 -78
- package/skills/write-spec/references/spec-shapes.md +0 -143
- /package/pi-extension/dist/{cognitive-routing-v2 → cognitive-routing}/budget.js +0 -0
- /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,381 @@
|
|
|
1
|
+
# Authoring Definitions
|
|
2
|
+
|
|
3
|
+
This reference is a contract: the shapes and constraints below are binding as written, for schema-version-2 group, suite, and configuration JSON. The loader checks them: it refuses a definition that breaks one when it loads, before any subject runs, by `run` and `check-tasks` alike, and the refusal names the group, its file and the field. Run `skill-eval check-tasks <path>`, which calls no model, after writing a definition and fix what it names; field rules it checks appear below as a pointer, and what stays is what its errors cannot teach: meanings, defaults and choices. Only an expectation of an unknown kind loads and surfaces afterward, as `grade-error` evidence.
|
|
4
|
+
|
|
5
|
+
Mode-specific fields are with their mode's guidance: [coding tasks](coding-tasks.md) (command graders, reference solutions, declared commands, shell, container, network, and the Claude Code host) and [conversations, pipelines and judges](conversations-pipelines-judges.md) (participants, rubric and judges, runtime profile). Commands, path resolution, run states, persistence, views, isolation, and safeguards are in [running and evidence](running-and-evidence.md).
|
|
6
|
+
|
|
7
|
+
## Definition Root
|
|
8
|
+
|
|
9
|
+
Run `skill-eval` from the repository or fixture root that owns the evaluation inputs.
|
|
10
|
+
|
|
11
|
+
| Input | Resolves from |
|
|
12
|
+
| --- | --- |
|
|
13
|
+
| `run <suite-or-group-path>` | current working directory |
|
|
14
|
+
| suite `groups` entries | directory containing the suite file |
|
|
15
|
+
| group `fixture` | definition root/current working directory |
|
|
16
|
+
| `configuration.extends` | directory containing the group file |
|
|
17
|
+
| subject `skills` and `context` | definition root/current working directory, then the selected working tree or Git commit |
|
|
18
|
+
|
|
19
|
+
Paths are relative and stay inside the root; the loader checks both.
|
|
20
|
+
|
|
21
|
+
## Common Group Shape
|
|
22
|
+
|
|
23
|
+
A group is a **task** (what the agent is asked to do and how it is graded) and a **configuration** (the agent environment that does it). Two or more named arms, usually `baseline` and `candidate`, each overlay the shared configuration, and `component` names the only places where an arm may differ from the reference arm; a group with one arm measures one setup and needs no `component`. Every group contains exactly these fields, plus optional `reference`, `commands` and `reference_solution` ([coding tasks](coding-tasks.md)), `revision`, `participants`, and the judged-evidence fields `rubric`, `judges` and `combine` ([conversations, pipelines and judges](conversations-pipelines-judges.md)):
|
|
24
|
+
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"schema_version": 2,
|
|
28
|
+
"kind": "group",
|
|
29
|
+
"id": "one-behavioral-question",
|
|
30
|
+
"type": "description",
|
|
31
|
+
"input": { "prompt": "Natural task prompt." },
|
|
32
|
+
"fixture": null,
|
|
33
|
+
"tools": ["read"],
|
|
34
|
+
"configuration": {
|
|
35
|
+
"host": { "name": "pi" },
|
|
36
|
+
"model": { "model": "xai/grok-4.7", "thinking": "low" },
|
|
37
|
+
"subject": { "kind": "skill", "source": { "kind": "working-tree" }, "context": [] }
|
|
38
|
+
},
|
|
39
|
+
"arms": {
|
|
40
|
+
"baseline": { "subject": { "skills": [], "target": null } },
|
|
41
|
+
"candidate": { "subject": { "skills": ["skills/target"], "target": 0 } }
|
|
42
|
+
},
|
|
43
|
+
"component": ["subject.skills", "subject.target"],
|
|
44
|
+
"expectations": [
|
|
45
|
+
{ "id": "baseline-read", "kind": "skill-read", "variant": "baseline", "expect": "by-turn", "turn": 1, "comparison": "target-read" },
|
|
46
|
+
{ "id": "candidate-read", "kind": "skill-read", "variant": "candidate", "expect": "by-turn", "turn": 1, "comparison": "target-read" }
|
|
47
|
+
],
|
|
48
|
+
"review_questions": []
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
The loader checks every field above (`schema_version` 2, `kind`, the `id` pattern, `type`, exactly one of `input.prompt` and `input.turns`, a contained `fixture` directory, unique `tools` and expectation IDs, at least one expectation, review question or rubric dimension) and names the one it refuses. What it cannot teach:
|
|
53
|
+
|
|
54
|
+
- `input.turns` may repeat a natural turn. The `fixture` directory's contents become the workspace.
|
|
55
|
+
- `input.resume_before` lists turns (from 2) before which the subject's Pi session is closed and resumed from its own file (Pi's RPC `switch_session`, so extensions see `session_shutdown`, then `session_start` with reason `resume`), as a user resuming it would; it needs a body group on `pi` with `configuration.runtime.session: true` and no participants. Each resumed turn records `resumed.sessionFile` in `run.json`.
|
|
56
|
+
- `review_questions` are rendered for the reviewer and never sent to the subject. The reviewer sees every arm's run as Run A, Run B, Run C, ... in a random order, must answer every question for every label, and its answers are mapped back to arm names; `review --swap` repeats the review with the order reversed and records agreement per question, and per arm when the arms are not `baseline` and `candidate`.
|
|
57
|
+
- A group with only review questions has no deterministic checks; its evidence comes from the advisory review alone. A group with only a rubric is graded by its judges alone.
|
|
58
|
+
- `revision: "description-only"`, for a description group whose two arms both name a target: before any subject runs, the evaluator snapshots both targets and refuses the group as `invalid` unless every file other than `SKILL.md` is byte-identical and `SKILL.md` differs only in its frontmatter `description`.
|
|
59
|
+
- Tools: a description group takes none or `read` (`skill-read` is its activation check); a body group takes `read`, `write`, `edit`, `ls`, `find`, `grep`, `run_command` for [declared commands](coding-tasks.md#declared-commands), and custom tools from a runtime extension bundle; `bash` needs a [shell](coding-tasks.md#shell) or a [container](coding-tasks.md#container-environment).
|
|
60
|
+
|
|
61
|
+
## Configuration And Arms
|
|
62
|
+
|
|
63
|
+
A configuration has these fields; each arm's effective configuration is the shared `configuration` with that arm's overlay merged in:
|
|
64
|
+
|
|
65
|
+
| Field | Required in the effective configuration | Meaning |
|
|
66
|
+
| --- | --- | --- |
|
|
67
|
+
| `host` | yes | `pi` or `claude-code`, with optional `version`, `extensions` and `settings`; see [Host Extensions And Settings](#host-extensions-and-settings) and [the Claude Code host](coding-tasks.md#claude-code-host). |
|
|
68
|
+
| `subject` | yes | What is under test: a `skill` (see [Subject](#subject)), or `none` when the comparison is about the environment, not a skill. |
|
|
69
|
+
| `model` | no | `model` names the provider/model; optional `thinking` selects its thinking level. The CLI has no model override, and a subject run without a model gets Pi's default and no copied login. |
|
|
70
|
+
| `runtime` | no | Host session, prompt mode, extension bundles and environment; see [Runtime Profile](conversations-pipelines-judges.md#runtime-profile). |
|
|
71
|
+
| `shell` | no | A confined `bash` for the subject; see [Shell](coding-tasks.md#shell). |
|
|
72
|
+
| `environment` | no | A container the subject's shell and the command graders run in; see [Container Environment](coding-tasks.md#container-environment). |
|
|
73
|
+
| `network` | no | What code the subject could have written may reach: `"none"` (sealed) or `"host"`; see [Network](coding-tasks.md#network). |
|
|
74
|
+
| `participants` | no | More than one participant in each arm: a conversation with a simulated user, or a pipeline of stages; shared, or different per arm when `component` names it; see [Participants](conversations-pipelines-judges.md#participants). |
|
|
75
|
+
| `freeflow` | no | Contributor-only (needs a Freeflow repository as the definition root): Freeflow as part of the environment; see [Freeflow](#freeflow). |
|
|
76
|
+
|
|
77
|
+
The loader checks each field's shape (host names, the arm-name pattern, `reference`, `component`, `extends`) and names the one it refuses. What it cannot teach:
|
|
78
|
+
|
|
79
|
+
- `configuration.extends` names a configuration file, relative to the group file; its configuration is merged first, then the group's own fields.
|
|
80
|
+
- Each arm overlays the shared configuration: objects merge key by key; an array, scalar, or `null` replaces the shared value.
|
|
81
|
+
- `reference` names the arm the others are compared with; it defaults to `baseline`. Evidence, views and the aggregate list the reference first, then the other arms in declaration order.
|
|
82
|
+
- `component` lists dot paths into the configuration, such as `subject.source` or `model.thinking`: the only places an arm may differ from the reference, compared leaf by leaf (an array is one leaf). The loader refuses an arm that differs elsewhere, and a `component` path no arm differs in. `component: []` declares an A/A comparison (or A/A/A): every arm identical, which measures run-to-run variation.
|
|
83
|
+
- **One arm** measures one setup: it is its own reference, with no `component` and no `comparison`. Checks, pass^k, metrics, judged scores (`review --rubric`), reference solutions and command graders work as usual; the aggregate's claim is a rate on the suite, and a suite `decision` or a pairwise `review` refuses it. Two or more arms need `component`.
|
|
84
|
+
- `host.name`, `host.version` and `runtime` are the same in every arm, except `runtime.environment.literal` (see [Runtime Profile](conversations-pipelines-judges.md#runtime-profile)); `host.extensions`, `host.settings`, `shell`, `environment` and `freeflow` may differ, as the component under test.
|
|
85
|
+
|
|
86
|
+
A group with exactly `baseline` and `candidate`, and `baseline` as the reference, keeps the evidence shapes it always had. Any other group records comparisons, transitions and pairs keyed by arm name. An A/A/B group, where `same` repeats the reference and `changed` adds the skill:
|
|
87
|
+
|
|
88
|
+
```json
|
|
89
|
+
{
|
|
90
|
+
"arms": {
|
|
91
|
+
"baseline": {},
|
|
92
|
+
"same": {},
|
|
93
|
+
"changed": { "subject": { "skills": ["skills/target"], "target": 0 } }
|
|
94
|
+
},
|
|
95
|
+
"component": ["subject.skills", "subject.target"]
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Body Group Example
|
|
100
|
+
|
|
101
|
+
A body group explicitly delivers each target on turn one and observes first-read or later-turn behavior:
|
|
102
|
+
|
|
103
|
+
```json
|
|
104
|
+
{
|
|
105
|
+
"schema_version": 2,
|
|
106
|
+
"kind": "group",
|
|
107
|
+
"id": "retained-artifact-behavior",
|
|
108
|
+
"type": "body",
|
|
109
|
+
"input": {
|
|
110
|
+
"turns": [
|
|
111
|
+
"Inspect the task and prepare the work.",
|
|
112
|
+
"Complete it and write result.json."
|
|
113
|
+
]
|
|
114
|
+
},
|
|
115
|
+
"fixture": "fixtures/task",
|
|
116
|
+
"tools": ["read", "write", "edit"],
|
|
117
|
+
"configuration": {
|
|
118
|
+
"host": { "name": "pi" },
|
|
119
|
+
"model": { "model": "xai/grok-4.7", "thinking": "medium" },
|
|
120
|
+
"subject": {
|
|
121
|
+
"kind": "skill",
|
|
122
|
+
"skills": ["skills/support", "skills/target"],
|
|
123
|
+
"target": 1,
|
|
124
|
+
"context": ["context/contract.md"]
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
"arms": {
|
|
128
|
+
"baseline": { "subject": { "source": { "kind": "git", "ref": "before-body-change" } } },
|
|
129
|
+
"candidate": { "subject": { "source": { "kind": "working-tree" } } }
|
|
130
|
+
},
|
|
131
|
+
"component": ["subject.source"],
|
|
132
|
+
"expectations": [
|
|
133
|
+
{
|
|
134
|
+
"id": "baseline-result",
|
|
135
|
+
"kind": "path",
|
|
136
|
+
"variant": "baseline",
|
|
137
|
+
"path": "result.json",
|
|
138
|
+
"turn": 2,
|
|
139
|
+
"expect": "exists",
|
|
140
|
+
"comparison": "result-exists"
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
"id": "candidate-result",
|
|
144
|
+
"kind": "path",
|
|
145
|
+
"variant": "candidate",
|
|
146
|
+
"path": "result.json",
|
|
147
|
+
"turn": 2,
|
|
148
|
+
"expect": "exists",
|
|
149
|
+
"comparison": "result-exists"
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
"id": "candidate-status",
|
|
153
|
+
"kind": "json",
|
|
154
|
+
"variant": "candidate",
|
|
155
|
+
"path": "result.json",
|
|
156
|
+
"turn": 2,
|
|
157
|
+
"expect": "field-equals",
|
|
158
|
+
"pointer": "/status",
|
|
159
|
+
"value": "complete"
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
"id": "candidate-changes",
|
|
163
|
+
"kind": "changed-paths",
|
|
164
|
+
"variant": "candidate",
|
|
165
|
+
"turn": 2,
|
|
166
|
+
"expect": "equals",
|
|
167
|
+
"paths": ["result.json"]
|
|
168
|
+
}
|
|
169
|
+
],
|
|
170
|
+
"review_questions": [
|
|
171
|
+
"Did the second turn apply the first-turn guidance without redelivery?"
|
|
172
|
+
]
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
The examples are complete definition shapes. Replace fixture, resource, model, and Git-ref values with paths and identities that exist under your definition root.
|
|
177
|
+
|
|
178
|
+
## Host Extensions And Settings
|
|
179
|
+
|
|
180
|
+
```json
|
|
181
|
+
{
|
|
182
|
+
"host": {
|
|
183
|
+
"name": "pi",
|
|
184
|
+
"extensions": [{ "package": "@gotgenes/pi-anthropic-auth", "version": "3.4.2" }],
|
|
185
|
+
"settings": { "retry": { "enabled": false }, "compaction": { "enabled": true } }
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
- `extensions` lists Pi packages by exact name and version, found among the user's installed Pi packages (`<Pi agent directory>/npm/node_modules`). They load right after the evaluator's guard, in order, and are recorded under `resources.hostExtensions`. Extensions can change what the host sends (an auth extension may reshape the system prompt), so they belong to the configuration, and arms that differ in them must declare it in `component`.
|
|
191
|
+
- `settings` is any object of Pi settings. It becomes the subject's `settings.json` in its isolated agent directory, merged over the evaluator's two defaults: `retry.enabled` and `compaction.enabled` are `false` unless declared, so a provider error or a compaction never happens silently inside a measured run. Any other setting it does not name takes Pi's default; the user's own settings never apply. `run.json` records the effective settings under `isolation.settings`, and body runs send the same retry and compaction values to Pi over RPC. Extensions load only from `extensions`.
|
|
192
|
+
- An extension can also be built from source, so arms can compare versions of an extension under development:
|
|
193
|
+
|
|
194
|
+
```json
|
|
195
|
+
{
|
|
196
|
+
"extensions": [
|
|
197
|
+
{ "source": { "kind": "git", "ref": "3f2a9c1", "path": "packages/my-extension" }, "build": ["npm", "run", "build"], "entry": "dist/index.js" },
|
|
198
|
+
{ "path": "extensions/local-probe", "entry": "index.mjs" }
|
|
199
|
+
]
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
- `source` takes a directory (`path`, or `"."`) at an exact commit (a branch or tag is refused, because it moves) of the Git repository holding the definition root, extracted with `git archive`. `path` instead takes a directory under the definition root from the working tree, snapshotted, never used live.
|
|
204
|
+
- Optional `build` runs once in the extracted copy, without a shell, in an isolated home, temp and Pi directory with no copied login, with a 10-minute timeout. A build that fails, times out or cannot start makes the group `invalid` before any subject runs.
|
|
205
|
+
- `entry` is the file Pi loads, relative to the built directory.
|
|
206
|
+
- Each distinct source and build is built once per group, under `resources/host-extensions/<n>/source` in the group directory. `resources.hostExtensions` records the source (with the resolved `commit` for a Git source), the entry, a `sha256` over the built directory's file list and contents, and the build's argv, exit code, duration and output tails.
|
|
207
|
+
- The advisory reviewer takes the same fields from a configuration file given with `review --configuration`.
|
|
208
|
+
|
|
209
|
+
## Subject
|
|
210
|
+
|
|
211
|
+
A `skill` subject:
|
|
212
|
+
|
|
213
|
+
```json
|
|
214
|
+
{
|
|
215
|
+
"kind": "skill",
|
|
216
|
+
"source": { "kind": "git", "ref": "v1.2.3" },
|
|
217
|
+
"skills": ["skills/target", "skills/support"],
|
|
218
|
+
"target": 0,
|
|
219
|
+
"context": ["context/base-guidance.md"]
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
A `none` subject is `{ "kind": "none" }`. `source` is `{ "kind": "working-tree" }` or `{ "kind": "git", "ref": "<exact-ref>" }`.
|
|
224
|
+
|
|
225
|
+
A source applies only to declared skill and context paths in that arm. It never supplies the group fixture: `fixture` is snapshotted once from the definition-root working tree, then copied independently for selected variants. `skills` preserves registration order, and `target` is a zero-based index into it (a non-reference arm that declares skills names one). `context` preserves declaration order and may name files or directories.
|
|
226
|
+
|
|
227
|
+
## Expectations
|
|
228
|
+
|
|
229
|
+
Every expectation has an `id`, a `kind` from the table below, a `variant` (the arm it checks), an optional `comparison` (see [Comparison](#comparison)) and an optional one-based `turn`. The loader runs each kind's own grader check on the definition, so a field, value, arm or turn that grader would refuse is refused before any subject runs.
|
|
230
|
+
|
|
231
|
+
Without `turn`, response checks use the final response and workspace checks use final state. Turn-scoped workspace checks cause an immutable workspace snapshot after each settled turn.
|
|
232
|
+
|
|
233
|
+
| `kind` | Group type | Kind-specific fields | `expect` |
|
|
234
|
+
| --- | --- | --- | --- |
|
|
235
|
+
| `skill-read` | description | timing `turn` except for `never` | `never`, `on-turn`, `by-turn`, `not-before-turn` |
|
|
236
|
+
| `resource-read` | either | `resource`, optional `index`, `path`, optional `turn` | `read`, `not-read` |
|
|
237
|
+
| `path` | body | workspace `path`, optional `turn` | `exists`, `absent` |
|
|
238
|
+
| `changed-paths` | body | unique workspace `paths`, optional `turn` | `equals`, `excludes` |
|
|
239
|
+
| `file-text` | body | workspace `path`, string `value`, optional `turn`, optional `line` | `contains`, `not-contains`, `equals` |
|
|
240
|
+
| `json` | body | workspace `path`, optional `turn`, conditional `pointer` and `value` | `available`, `missing`, `valid`, `malformed`, `field-present`, `field-absent`, `field-equals` |
|
|
241
|
+
| `response-text` | body | string `value`, optional `turn` | `contains`, `not-contains`, `equals` |
|
|
242
|
+
| `tool-call` | body | string `tool`, optional `turn`, optional `argumentContains`/`argumentNotContains` arrays | `called`, `succeeded`, `failed`, `not-called` |
|
|
243
|
+
| `context-text` | body | string `value`, optional `surface` (`system-prompt`, the default, or `provider-context`), optional `request` (`first`, `last`, the default, or a positive request number within the turn), optional `turn` | `contains`, `not-contains`, `equals` |
|
|
244
|
+
| `command` | body | `argv`, optional `files`, optional `timeout_seconds`, `pass`; no `turn` | none; see [command graders](coding-tasks.md#command-graders) |
|
|
245
|
+
|
|
246
|
+
With `line` (1-based), a `file-text` expectation compares only that line, without its line ending. A line the file does not have fails every expectation, including `not-contains`, so an empty file cannot pass by having nothing to read. Use it to check one line, such as a review's first-line judgment, when the rest of the file may quote the same text.
|
|
247
|
+
|
|
248
|
+
For `tool-call` with `expect: "not-called"`, omitted argument filters require zero calls to the named tool. Supplied filters scope the absence check to calls matching those argument predicates.
|
|
249
|
+
|
|
250
|
+
### Resource paths
|
|
251
|
+
|
|
252
|
+
- `resource: "workspace"`: omit `index`; `path` is relative to the writable workspace.
|
|
253
|
+
- `resource: "skill"`: `index` selects the zero-based declared skill; `path` is relative to that skill directory.
|
|
254
|
+
- `resource: "context"`: `index` selects the zero-based declared context item; `path` is relative to that materialized item.
|
|
255
|
+
|
|
256
|
+
### Changed paths
|
|
257
|
+
|
|
258
|
+
- `equals`: the complete changed-file set must equal `paths`.
|
|
259
|
+
- `excludes`: none of `paths` may appear in the changed-file set.
|
|
260
|
+
|
|
261
|
+
Directory-only presence does not count as a changed file.
|
|
262
|
+
|
|
263
|
+
### JSON states
|
|
264
|
+
|
|
265
|
+
```json
|
|
266
|
+
[
|
|
267
|
+
{
|
|
268
|
+
"id": "file-missing",
|
|
269
|
+
"kind": "json",
|
|
270
|
+
"variant": "candidate",
|
|
271
|
+
"path": "missing.json",
|
|
272
|
+
"expect": "missing"
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
"id": "file-malformed",
|
|
276
|
+
"kind": "json",
|
|
277
|
+
"variant": "candidate",
|
|
278
|
+
"path": "broken.json",
|
|
279
|
+
"expect": "malformed"
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
"id": "field-absent",
|
|
283
|
+
"kind": "json",
|
|
284
|
+
"variant": "candidate",
|
|
285
|
+
"path": "result.json",
|
|
286
|
+
"expect": "field-absent",
|
|
287
|
+
"pointer": "/optional"
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
"id": "field-null",
|
|
291
|
+
"kind": "json",
|
|
292
|
+
"variant": "candidate",
|
|
293
|
+
"path": "result.json",
|
|
294
|
+
"expect": "field-equals",
|
|
295
|
+
"pointer": "/value",
|
|
296
|
+
"value": null
|
|
297
|
+
}
|
|
298
|
+
]
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### Comparison
|
|
302
|
+
|
|
303
|
+
A comparison ID joins one expectation per arm, all the same check. For each non-reference arm the report records a factual transition from the reference, such as `fail-to-pass`, never a quality verdict. A `baseline`/`candidate` group records it as `transition`; any other group records `reference`, each arm's check and state under `arms`, and each non-reference arm's transition under `transitions`.
|
|
304
|
+
|
|
305
|
+
## Suite
|
|
306
|
+
|
|
307
|
+
```json
|
|
308
|
+
{
|
|
309
|
+
"schema_version": 2,
|
|
310
|
+
"kind": "suite",
|
|
311
|
+
"id": "workflow-core",
|
|
312
|
+
"groups": [
|
|
313
|
+
"groups/natural-activation.json",
|
|
314
|
+
"groups/body-behavior.json"
|
|
315
|
+
]
|
|
316
|
+
}
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
A suite's `groups` run in order and resolve from the suite's directory; `decision` is optional. The loader checks the rest.
|
|
320
|
+
|
|
321
|
+
### Decision
|
|
322
|
+
|
|
323
|
+
A suite may declare the rule its trials are judged by, before any run. Without one, an aggregate supports only a rate on the suite. A direct group run is one case and never yields "beats".
|
|
324
|
+
|
|
325
|
+
```json
|
|
326
|
+
"decision": {
|
|
327
|
+
"measure": { "comparison": "target-read" },
|
|
328
|
+
"arms": ["baseline", "candidate"],
|
|
329
|
+
"direction": "higher",
|
|
330
|
+
"method": "sign-test",
|
|
331
|
+
"alpha": 0.05,
|
|
332
|
+
"min_cases": 10,
|
|
333
|
+
"trials": { "initial": 3, "max": 9, "step": 3 }
|
|
334
|
+
}
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
- `measure` names exactly one of: `comparison`, a comparison ID from the groups' expectations (a pass counts 1, a fail 0); `metric`, a name in the aggregate's `metrics` section; `judged`, a dimension ID in its `judged` section; or `score`, the comparison ID of test-graded command expectations, read from the `scores` section (an expectation's own ID scores its one arm only). Section values are read from `perTrial` (`true` counts 1, `false` 0, numbers as given). Null and unavailable values are excluded and counted.
|
|
338
|
+
- `arms` names two arms, the reference first; every group needs both, and `--variant` is refused. The loader refuses a measure a group records in one decision arm only, or that no group records in both; a group that records it in neither arm, such as a control case, loads, and its case is excluded and counted.
|
|
339
|
+
- `direction`: whether `higher` or `lower` is better.
|
|
340
|
+
- `method` defaults to `sign-test`, `alpha` to 0.05, and `min_cases` to 10.
|
|
341
|
+
- The unit is the case. Each arm's values over a case's trials are averaged, and the second arm is better, worse or equal. An exact two-sided sign test over the better and worse cases (ties and excluded cases are counted, not tested) gives the verdict that [design and measurement](design-and-measurement.md#fix-the-decision-rule-first) defines, with `min_cases` as the minimum and `alpha` as the level.
|
|
342
|
+
- A suite with a decision always runs as trials and records an aggregate. `trials` is optional: without it, `--trials` sets the count (default 1). After `initial` trials, each case whose sign is not yet stable (the arms tie, or differ by less than one trial's worth: the observed range divided by the fewer values) runs up to `step` more trials of that group alone, until `max`. A case with an arm that has no usable value is not extended.
|
|
343
|
+
|
|
344
|
+
What the aggregate records for a decision is in [running and evidence](running-and-evidence.md#trials).
|
|
345
|
+
|
|
346
|
+
## Selection
|
|
347
|
+
|
|
348
|
+
`--group <id | position>` and `--variant <arm>` narrow what runs (`skill-eval --help`); with neither, every group and arm runs. Excluded arms are `not-selected`, never failed, and the saved definitions do not change.
|
|
349
|
+
|
|
350
|
+
## Freeflow
|
|
351
|
+
|
|
352
|
+
For Freeflow contributors only: this field builds Freeflow itself with `scripts/freeflow-snapshot.mjs`, so it works only when the definition root is a Freeflow repository; elsewhere the group is refused before any subject runs. To compare a host extension, declare it under `host.extensions`.
|
|
353
|
+
|
|
354
|
+
A configuration with `freeflow` runs the subject with Freeflow loaded, built from an exact commit:
|
|
355
|
+
|
|
356
|
+
```json
|
|
357
|
+
{
|
|
358
|
+
"configuration": {
|
|
359
|
+
"host": { "name": "pi" },
|
|
360
|
+
"model": { "model": "xai/grok-4.7", "thinking": "medium" },
|
|
361
|
+
"subject": { "kind": "none" },
|
|
362
|
+
"runtime": { "prompt": "host" },
|
|
363
|
+
"freeflow": {
|
|
364
|
+
"source": { "kind": "git", "ref": "<commit>" },
|
|
365
|
+
"repository": { "taskMemory": { "enabled": false } },
|
|
366
|
+
"personal": {}
|
|
367
|
+
}
|
|
368
|
+
},
|
|
369
|
+
"arms": {
|
|
370
|
+
"baseline": {},
|
|
371
|
+
"candidate": { "freeflow": { "repository": { "taskMemory": { "enabled": true } } } }
|
|
372
|
+
},
|
|
373
|
+
"component": ["freeflow.repository.taskMemory.enabled"]
|
|
374
|
+
}
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
- `source` is a Git commit; the package is built from that commit with the definition root's `scripts/freeflow-snapshot.mjs`, once per distinct ref per group, into the group's `resources/freeflow/`. The user's development snapshot is never used or changed.
|
|
378
|
+
- `repository` is written to the workspace's `.freeflow/config.json` and `personal`, when not empty, to `.freeflow/local.json`, before the workspace's starting state is taken, so neither counts as a subject change. Both default to `{}`, and that build's own validator checks them.
|
|
379
|
+
- `runtime.prompt` is `host`, because the isolated prompt replaces the host's system prompt, which would remove Freeflow's own instructions.
|
|
380
|
+
- Freeflow's extension loads right after the evaluator's guard, the package directory is readable by the subject, and Freeflow may register custom tools that `tools` then names.
|
|
381
|
+
- `run.json` records the ref, resolved commit, package name and version, tarball hash, and the settings under `resources.freeflow`.
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# Coding Tasks
|
|
2
|
+
|
|
3
|
+
This reference holds a coding task's guidance and the definition fields it uses, and the Claude Code host's. The guidance is judgment; the field shapes and constraints are a contract, binding as written, like the rest of [authoring](authoring.md), whose loader checks them: run `skill-eval check-tasks` and fix the field it names.
|
|
4
|
+
|
|
5
|
+
## Choose And Declare A Coding Task
|
|
6
|
+
|
|
7
|
+
- **Answers:** does the agent's change work, judged by running it rather than reading it?
|
|
8
|
+
- **Declare:** a body group with the repository as its fixture and tools to edit it; `command` expectations whose `argv` runs hidden tests, a linter or a build on a copy of the final workspace, with grader `files` kept outside the fixture and a `pass` rule (an exit code, or named required tests); declared `commands` and `run_command` when the subject should run tests itself; a `reference_solution` proving the task solvable; and a `shell` or a container `environment` only when the task needs `bash`, or a toolchain the host lacks.
|
|
9
|
+
- **Grade both directions:** tests of the new behavior, which fail on the unchanged fixture and must pass after the change, and the existing tests the change must not break, which pass before and must still pass. Passing only the first rewards a change that breaks something else.
|
|
10
|
+
- **Yields:** each command's exit code, output tails and per-test results, with the share of required tests passed as a score; a reference check per group.
|
|
11
|
+
- **Pitfalls:**
|
|
12
|
+
- Run `check-tasks` first: it applies the reference solution and runs the graders with no model (Reference Solution, below). A task the reference fails measures the grader, not the agent; a task already solved measures nothing. For every group it also lists what the copy lacks against the setting the task came from: Git history (a workspace is never a repository), ignored files the fixture holds (a clone lacks them) or the task names (such as `.env`), and tools or network the task refers to but the subject lacks. Judge each gap before running: give the subject what the task needs, or reword the task.
|
|
13
|
+
- A required test name that matches nothing fails every arm; the reference check catches it.
|
|
14
|
+
- Grader files inside the fixture, or named in the prompt, leak the answer.
|
|
15
|
+
- A subject can make tests pass by editing them. List every test you rely on, existing ones included, in the grader `files`: a grader file replaces whatever the subject left at that path. A `changed-paths` expectation with `excludes` also shows whether the subject touched them.
|
|
16
|
+
- A container image is pinned by digest and never pulled by the evaluator; when it is missing, relay the refusal and ask the user before pulling. Declare `network: "none"` when the subject's code must not reach the network, the host's files or the login (Network, below).
|
|
17
|
+
- Grader commands run with the evaluator's host permissions, and run whatever the subject wrote. Run only tasks whose fixture and graders you trust.
|
|
18
|
+
- A subject without a shell runs only the declared commands, which is often enough. A shell needs a confining isolation that the evaluator probes (Shell, below); when it needs software this machine lacks, relay the refusal to the user and ask before installing anything.
|
|
19
|
+
|
|
20
|
+
## Command Graders
|
|
21
|
+
|
|
22
|
+
A `command` expectation grades a body run's final work by running a program on it, such as hidden tests or a linter:
|
|
23
|
+
|
|
24
|
+
```json
|
|
25
|
+
{
|
|
26
|
+
"id": "candidate-hidden-tests",
|
|
27
|
+
"kind": "command",
|
|
28
|
+
"variant": "candidate",
|
|
29
|
+
"comparison": "hidden-tests",
|
|
30
|
+
"argv": ["node", "--test", "--test-reporter=tap", "test/hidden.test.mjs"],
|
|
31
|
+
"files": { "test/hidden.test.mjs": "graders/calc/hidden.test.mjs" },
|
|
32
|
+
"timeout_seconds": 600,
|
|
33
|
+
"pass": { "tests": { "format": "node-test", "required": ["adds two numbers", "adds negatives"] } }
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
- After the run, the final workspace is copied to `<arm>/commands/<id>/workspace`, each `files` entry is copied in (key: path in the copy; value: path under the definition root), and `argv` runs there without a shell, with the subject's isolated home, temp, XDG and Pi directories. The workspace itself is never changed, so file graders still verify its hashes.
|
|
38
|
+
- `files` sources resolve from the definition root like `fixture`, never from inside the fixture, which the subject sees; they are inputs of the run, so an uncommitted grader file makes the run non-canonical. A destination may not pass through a symlink the subject left in the workspace.
|
|
39
|
+
- `timeout_seconds` (default 600) stops the command's whole process tree. The loader checks these fields and names the one it refuses.
|
|
40
|
+
- `pass` is one rule. `{ "exit_code": 0 }` passes on that exit code. `{ "tests": { "format", "required", "report" } }` passes when every `required` test passed: `node-test` and `tap` read TAP from stdout (give Node `--test-reporter=tap`, since newer Node versions default to another reporter), and `junit` reads the JUnit XML file at `report` in the copy, or stdout without one. A required name matches a test's own name or its full name, parents joined by ` > ` (for JUnit, `<classname> > <name>`); skipped, missing and failed tests do not pass. The check records `score`, the passed share of `required`. The aggregate's `scores` section gives each such check's score per arm (`count`, `unavailable`, `mean`, `median`) and per trial as `score.<expectation id>`, and also as `score.<comparison id>` when the expectation belongs to a comparison, so a suite decision can measure it with `{ "score": "<comparison id>" }`.
|
|
41
|
+
- `run.json` records each command under `postRun.commands.<id>`: exit code, signal, timeout, duration, the last 20,000 characters of stdout and stderr, and parsed test results. A run that did not complete, or a command that could not start, grades `unavailable`; a timeout fails.
|
|
42
|
+
|
|
43
|
+
Commands are trusted author input with the evaluator's host permissions; whatever the subject wrote runs with them too when the command executes it.
|
|
44
|
+
|
|
45
|
+
## Reference Solution
|
|
46
|
+
|
|
47
|
+
`reference_solution` is optional: `{ "patch": "<file>" }`, a unified diff applied to the fixture copy with `git apply`, or `{ "files": "<dir>" }`, whose regular files overlay the fixture copy; both are inputs of the run, kept outside the fixture. The reference is one workspace shared by every arm, so `skill-eval check-tasks` grades each arm's workspace and command expectations with no model, reporting per arm: `solvable` only when every arm's applicable expectations pass on the reference and fail before it, `unsolvable` with the failing graders named per arm, `already-solved` when an arm's expectations all pass on the unchanged fixture (the task cannot show a change), or `not-checkable` when a check cannot run (interaction expectations need a transcript). The same graders run on the unchanged fixture: each arm records `before` with every check's state there and, for test graders, the required tests that fail before and pass on the reference (`failToPass`) and the ones that pass both times (`passToPass`). A pass-to-pass test is fine as long as some required test or the exit-code rule fails before. An optional `"arm"` restricts the check to one arm. `run` refuses an unsolvable or already-solved group before any subject starts (`--skip-reference-check` overrides); the result records the check in `groups/<id>/reference-check.json`.
|
|
48
|
+
|
|
49
|
+
## Declared Commands
|
|
50
|
+
|
|
51
|
+
A body group that must let the subject run tests or other programs lists the `run_command` tool and declares each allowed command:
|
|
52
|
+
|
|
53
|
+
```json
|
|
54
|
+
{
|
|
55
|
+
"tools": ["read", "edit", "run_command"],
|
|
56
|
+
"commands": [
|
|
57
|
+
{ "id": "unit-tests", "argv": ["node", "--test"], "timeout_ms": 120000 },
|
|
58
|
+
{ "id": "lint", "argv": ["npm", "run", "lint"] }
|
|
59
|
+
]
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
- The loader checks the pairing (`run_command` with `commands`, body groups only) and each command's `id`, `argv` and `timeout_ms` (default 120000).
|
|
64
|
+
- The subject chooses only a declared `id`; it cannot change `argv`. The argv runs without a shell, in the workspace (in the arm's container when it has a container environment), without evaluator control variables or a pointer to the login.
|
|
65
|
+
- Output is capped per stream and marked when truncated. A nonzero exit or timeout is an ordinary tool result, not a tool error.
|
|
66
|
+
- Grade calls with `tool-call` expectations, for example `tool: "run_command"` with `argumentContains: ["unit-tests"]`.
|
|
67
|
+
|
|
68
|
+
A command's argv is trusted author input, like an extension bundle, and the subject only selects among them; but what it runs, such as the workspace's tests, may be the subject's own code. Without a container it runs on the host with the user's permissions and network; declare `network: "none"` and a container environment to seal it (Network, below).
|
|
69
|
+
|
|
70
|
+
Group `commands` run only through the subject's `run_command` tool. Grading runs only the `argv` of `command` expectations, after the subject has finished.
|
|
71
|
+
|
|
72
|
+
## Shell
|
|
73
|
+
|
|
74
|
+
A body group may give its subject `bash` only through a host extension that runs the shell in isolation, such as a micro-VM. The evaluator does not choose or ship a sandbox; it verifies the one the configuration names:
|
|
75
|
+
|
|
76
|
+
```json
|
|
77
|
+
{
|
|
78
|
+
"tools": ["read", "write", "bash"],
|
|
79
|
+
"configuration": {
|
|
80
|
+
"host": { "name": "pi", "extensions": [{ "path": "isolation/vm-shell", "build": ["npm", "ci", "--ignore-scripts"], "entry": "index.ts" }] },
|
|
81
|
+
"shell": { "isolation": "isolation/vm-shell", "network": "none", "workspace": "/workspace", "requires": ["gondolin"] }
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
- `bash` needs a `shell` or a [container environment](#container-environment) in every arm; without one, `run` refuses it before any subject starts. The loader checks a declared `shell`'s fields: `isolation` names one of the arm's `host.extensions` by its label (the package name, a working-tree `path`, or a Git source's `path`), and `network` is `"none"`, so the shell cannot reach the network.
|
|
87
|
+
- Optional `workspace` is where the isolation shows the workspace (a micro-VM often mounts it at `/workspace`). The guard checks a path under it as the same path in the host workspace, so `/workspace/src/a.js` is allowed and `/etc/hosts` is not.
|
|
88
|
+
- Optional `requires` lists what the isolation needs on this machine: a known name (`gondolin` for QEMU and Node.js 23.6+, or `qemu` or `node-23.6` alone), or a custom entry naming the programs, the reason and how to install them.
|
|
89
|
+
|
|
90
|
+
Before an arm's first subject, the evaluator:
|
|
91
|
+
|
|
92
|
+
1. Checks `requires`. When something is missing, the group is `invalid` before any subject runs, and the refusal names each missing item, what was found, why the isolation needs it, the install command for this system (Homebrew on macOS, apt or dnf on Linux), and the expected download when known. Ask the user before installing anything.
|
|
93
|
+
2. Runs the probes: the subject's own Pi, with the guard and the arm's host extensions, `bash` as its only tool, and a local scripted model (an OpenAI-compatible endpoint the evaluator serves, so no model is called) that issues six bash calls. A control must succeed: writing a file inside the workspace. Five must fail: writing a host file outside the workspace, reading a marker beside the isolated home, reading a marker in the directory where the host keeps its login (Pi's agent directory), reaching the network (a listener on the host's own network address, plus `https://example.com/` unless `SKILL_EVAL_PROBE_PUBLIC_URL` names another URL or is empty), and printing a variable the evaluator plants in Pi's environment. Each is judged by what the host observes: files, connections and output.
|
|
94
|
+
|
|
95
|
+
Any probe that does not hold makes the group `invalid` before any subject runs. Each run records the arm's result under `confinement` (every probe's command, whether it ran and held, and its output), also kept in `confinement/<arm>/` in the group directory with Pi's events and stderr.
|
|
96
|
+
|
|
97
|
+
## Container Environment
|
|
98
|
+
|
|
99
|
+
A body group can run its subject's `bash` and its [command graders](#command-graders) in a task image with its own toolchain, as benchmark-style coding tasks need:
|
|
100
|
+
|
|
101
|
+
```json
|
|
102
|
+
{
|
|
103
|
+
"tools": ["read", "write", "edit", "bash"],
|
|
104
|
+
"configuration": {
|
|
105
|
+
"environment": { "kind": "container", "image": "example.org/task@sha256:<64 hex characters>", "workdir": "/testbed", "network": "none" }
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
- The image is pinned by digest, because a tag can change under the run. `workdir` names the workspace in the container, such as `/testbed`, and must be empty or absent in the image (checked when the container starts). The loader checks the rest: `network` `"none"`, and a container or a `shell`, not both, since the container provides the shell. Arms may differ in `environment` when `component` declares it, such as `environment.image`.
|
|
111
|
+
- The evaluator uses the standard `docker` command line (Docker Desktop, Colima, OrbStack or Podman's `docker` all provide it) and looks for it only for groups that declare a container. A missing CLI, a stopped engine, or an image that is not present locally makes the group `invalid` before any subject runs, with the same refusal as a shell prerequisite; for a missing image it gives the `docker pull` command and, when `docker manifest inspect` reports it, the compressed download size. The evaluator never pulls an image; ask the user first.
|
|
112
|
+
- With `bash` in `tools`, each subject gets its own container from the image (`--network none`, 4 GB of memory, 2 CPUs, 1024 processes), removed when the subject ends, cancelled or not. The workspace is mounted at its own host path, where `bash` and declared commands start, and `workdir` is a link to it, so `pwd`, the working directory the host reports and the paths its file tools take all agree, and the image's own references to `workdir` (such as `GIT_WORK_TREE=/testbed`) reach the workspace. Graders see their copy at `workdir`. Each declared resource the subject may read (its skills, context, runtime extension resources and Freeflow's package) is mounted read-only at the same path it has on the host, so a path the subject was given, such as `node <skill>/scripts/check.mjs`, works from bash as it does for `read`; the workspace is the only writable mount. The guard rewrites each bash call to `docker exec` into it, so the command runs in the image and Pi runs only the docker client; paths under `workdir` are checked as workspace paths. The [Shell](#shell) probes run first, in a container of their own, and must all hold.
|
|
113
|
+
- With Freeflow loaded on Pi, its Tool Execution tools may be declared in `tools` and are confined the same way: `bash_background` and `monitor` run their command in the subject's container (every arm must declare a container environment; a shell isolation extension does not confine them), the subject's temp folder, where their output is saved, becomes readable and is mounted read-only at its own path, `stop_background` needs nothing more, and `apply_patch` may name only paths inside the workspace. Every command the guard sends to the container is stopped there when the host stops its docker client (a timeout, an abort, `stop_background`, the session's end), when the image has `setsid`.
|
|
114
|
+
- Each `command` expectation runs in a fresh container from the same image on the graded copy of the workspace (`docker run --rm`, same mount, network and limits), removed afterwards even on a timeout. Its record names the image and container. `check-tasks` runs them in the image too, and reports the group `not-checkable`, with the same refusal, when docker or the image is missing.
|
|
115
|
+
|
|
116
|
+
## Network
|
|
117
|
+
|
|
118
|
+
Three paths run code the subject could have written: its `bash`, its [declared commands](#declared-commands) (which run the workspace's own tests and scripts), and [command graders](#command-graders) (hidden tests that import its code). `network` declares one policy for all three:
|
|
119
|
+
|
|
120
|
+
- `"none"`: sealed. `bash` runs behind a probed [Shell](#shell) or in the arm's container, and declared commands and command graders run in the arm's [container](#container-environment), each with no network and none of the host's files, so the provider login on disk is out of reach. `"none"` needs a container environment for declared commands and command graders.
|
|
121
|
+
- `"host"`: unsealed, on purpose. Declared commands and command graders run on the host as the user, with the network and the user's files, including the provider login on disk. A declared command gets no pointer to the login (no `PI_CODING_AGENT_DIR` or login variable), which keeps it out of easy reach, not out of reach.
|
|
122
|
+
|
|
123
|
+
Without `network`, an arm gets what its paths allow: sealed when every path it has is confined, unsealed when it runs declared commands or command graders without a container. The plan line names the unsealed arms before anything starts, and each run records `sealing`: the `network` its code had, the `declared` policy (or null), where `bash`, `commands` and `graders` ran (`container`, `shell`, `host`, or null when it has none), and whether the `login` was out of reach: with `bash`, only when the arm's login-directory probe held, and otherwise `not shown out of reach`. The subject's host process (Pi or Claude Code) always keeps the network, which it needs to reach its model, and reads only its own copied login.
|
|
124
|
+
|
|
125
|
+
## Claude Code Host
|
|
126
|
+
|
|
127
|
+
`"host": { "name": "claude-code" }` runs subjects, judges and simulated users in headless Claude Code (`claude -p` with stream-json input and output). A group runs on one host; compare hosts with one group per host.
|
|
128
|
+
|
|
129
|
+
```json
|
|
130
|
+
{
|
|
131
|
+
"host": { "name": "claude-code", "version": "2.1.296" },
|
|
132
|
+
"model": { "model": "anthropic/claude-haiku-5-5", "thinking": "low" },
|
|
133
|
+
"subject": { "kind": "none" },
|
|
134
|
+
"environment": { "kind": "container", "image": "python@sha256:<64 hex characters>", "workdir": "/testbed", "network": "none" }
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
- **Login.** Claude Code's login reaches a subject only from the evaluator's environment: `CLAUDE_CODE_OAUTH_TOKEN` (on a Mac whose login is in the keychain, `claude setup-token` prints one), `ANTHROPIC_API_KEY`, `ANTHROPIC_AUTH_TOKEN` or `CLAUDE_SESSION_INGRESS_TOKEN_FILE`, with `ANTHROPIC_BASE_URL` and proxy variables when set. No credential file is copied. `run.json` records the variable names under `isolation.credentials`, never their values. Without one, the arm is invalid before it starts.
|
|
139
|
+
- **Model.** Every arm declares a Claude model; `thinking` is Claude Code's `--effort`. The loader checks both.
|
|
140
|
+
- **Tools.** `read`, `write`, `edit` and `grep` run as Claude Code's Read, Write, Edit and Grep; `ls` and `find` as Glob. Nothing else is enabled: no Agent, web or MCP tools. A Glob or Grep pattern must be relative to its path. `bash` runs as Bash only in a [container environment](#container-environment), because Claude Code has no isolation extension.
|
|
141
|
+
- **Isolation.** Each process has its own home, temp and `CLAUDE_CONFIG_DIR`, and starts with `--setting-sources ""`, `--strict-mcp-config`, `--disable-slash-commands`, `--permission-mode dontAsk` and the evaluator's guard as a PreToolUse hook. CLAUDE.md files, auto memory, automatic compaction, the updater and nonessential traffic are off. Client retries stay at Claude Code's default.
|
|
142
|
+
- **Prompt.** `isolated` (the default) replaces Claude Code's system prompt with the evaluator's, which lists the declared tools, skills and context; `host` keeps Claude Code's and appends the skills listing and context. Claude Code still adds its own identity line and an environment note to every request; the note says whether a Git repository encloses the workspace, so keep results outside a repository (`--results`) when that matters. A local relay records each request in `<arm>/host-context.json`, with what Claude Code reported loading (`init`), and serves `context-text` expectations.
|
|
143
|
+
- **Skills.** Claude Code's own skill loader is off. Declared skills are listed in the system prompt; a body run's target arrives as the text Pi's `/skill:<name>` command expands to, recorded as an `explicit-skill-command` delivery.
|
|
144
|
+
- **Settings.** `settings` is a Claude Code settings object, passed with `--settings`; the loader refuses those that would replace the guard, permissions, login or environment, or load plugins, MCP servers or a status line.
|
|
145
|
+
- **Not supported yet:** `host.extensions`, runtime extension bundles, `freeflow`, `commands`, and `shell`; the loader names each.
|