@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
package/skills/{evaluate-skill/scripts/lib/pi.mjs → evaluate-behavior/scripts/lib/subject.mjs}
RENAMED
|
@@ -1,23 +1,15 @@
|
|
|
1
|
+
// One subject: the host-neutral part of running an arm's agent. It materializes the declared environment, fixture,
|
|
2
|
+
// runtime and Freeflow settings, asks the arm's host adapter (hosts/) to launch the agent, and turns what the host
|
|
3
|
+
// observed into the arm's run record. Everything that depends on the host program lives in its adapter.
|
|
4
|
+
|
|
1
5
|
import { createHash } from "node:crypto";
|
|
2
|
-
import { spawn } from "node:child_process";
|
|
3
|
-
import { once } from "node:events";
|
|
4
|
-
import { createWriteStream } from "node:fs";
|
|
5
6
|
import { mkdir, readFile, realpath } from "node:fs/promises";
|
|
6
7
|
import path from "node:path";
|
|
7
|
-
import { fileURLToPath } from "node:url";
|
|
8
8
|
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
pipeStream,
|
|
14
|
-
processGroupExists,
|
|
15
|
-
signalProcessTree,
|
|
16
|
-
TERMINATION_GRACE_MS,
|
|
17
|
-
waitForForcedKill,
|
|
18
|
-
writeStream,
|
|
19
|
-
} from "./process.mjs";
|
|
20
|
-
import { runRpcBodySession, runRpcDescriptionSession } from "./rpc.mjs";
|
|
9
|
+
import { baseProcessEnvironment } from "./process.mjs";
|
|
10
|
+
import { writeFreeflowSettings } from "./freeflow.mjs";
|
|
11
|
+
import { runMetrics } from "./hooks.mjs";
|
|
12
|
+
import { hostAdapter } from "./hosts/index.mjs";
|
|
21
13
|
import {
|
|
22
14
|
fingerprintDirectory,
|
|
23
15
|
materializeEnvironment,
|
|
@@ -26,28 +18,17 @@ import {
|
|
|
26
18
|
snapshotWorkspace,
|
|
27
19
|
verifyEnvironment,
|
|
28
20
|
verifyRuntime,
|
|
21
|
+
WORKSPACE,
|
|
29
22
|
workspaceChanges,
|
|
30
23
|
} from "./sandbox.mjs";
|
|
31
24
|
|
|
32
|
-
const guardExtension = fileURLToPath(new URL("../pi-guard.mjs", import.meta.url));
|
|
33
|
-
const commandToolExtension = fileURLToPath(new URL("../pi-command-tool.mjs", import.meta.url));
|
|
34
|
-
const observerExtension = fileURLToPath(new URL("../pi-observer.mjs", import.meta.url));
|
|
35
|
-
const HOST_COMMANDS = { pi: "pi" };
|
|
36
|
-
const BASE_PROCESS_ENVIRONMENT_KEYS = [
|
|
37
|
-
"PATH",
|
|
38
|
-
"HOME",
|
|
39
|
-
"TMPDIR",
|
|
40
|
-
"TMP",
|
|
41
|
-
"TEMP",
|
|
42
|
-
"LANG",
|
|
43
|
-
"LC_ALL",
|
|
44
|
-
"XDG_CONFIG_HOME",
|
|
45
|
-
"XDG_DATA_HOME",
|
|
46
|
-
"XDG_CACHE_HOME",
|
|
47
|
-
"PI_PACKAGE_DIR",
|
|
48
|
-
"PI_OFFLINE",
|
|
49
|
-
];
|
|
50
25
|
const TURN_WORKSPACE_KINDS = new Set(["path", "changed-paths", "file-text", "json"]);
|
|
26
|
+
// Tools whose commands run in the subject's container when it has one: bash, and Freeflow's background commands.
|
|
27
|
+
const CONTAINER_SHELL_TOOLS = new Set(["bash", "bash_background", "monitor"]);
|
|
28
|
+
// Freeflow's background commands save their output under the subject's temp directory and name that file to the
|
|
29
|
+
// model, which reads it with read or from bash; with them declared, that directory is readable (and, in a container,
|
|
30
|
+
// mounted read-only at its own path).
|
|
31
|
+
const BACKGROUND_TOOLS = new Set(["bash_background", "monitor"]);
|
|
51
32
|
|
|
52
33
|
export class VariantSetupError extends Error {
|
|
53
34
|
constructor(message) {
|
|
@@ -56,39 +37,91 @@ export class VariantSetupError extends Error {
|
|
|
56
37
|
}
|
|
57
38
|
}
|
|
58
39
|
|
|
59
|
-
export async function runDescription({
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
40
|
+
export async function runDescription({
|
|
41
|
+
group,
|
|
42
|
+
variant,
|
|
43
|
+
root,
|
|
44
|
+
variantDirectory,
|
|
45
|
+
fixture,
|
|
46
|
+
runtime,
|
|
47
|
+
freeflow,
|
|
48
|
+
hostExtensions,
|
|
49
|
+
signal,
|
|
50
|
+
extendEnvironment = null,
|
|
51
|
+
}) {
|
|
52
|
+
const options = { group, variant, root, variantDirectory, fixture, runtime, freeflow, hostExtensions, signal };
|
|
53
|
+
options.extendEnvironment = extendEnvironment;
|
|
54
|
+
if (group.input.turns !== undefined) return runPersistentDescription(options);
|
|
55
|
+
return runOneShotDescription(options);
|
|
64
56
|
}
|
|
65
57
|
|
|
66
|
-
export async function runBody({
|
|
67
|
-
|
|
58
|
+
export async function runBody({
|
|
59
|
+
group,
|
|
60
|
+
variant,
|
|
61
|
+
root,
|
|
62
|
+
variantDirectory,
|
|
63
|
+
fixture,
|
|
64
|
+
runtime,
|
|
65
|
+
freeflow,
|
|
66
|
+
hostExtensions,
|
|
67
|
+
signal,
|
|
68
|
+
extendEnvironment = null,
|
|
69
|
+
nextPrompt = null,
|
|
70
|
+
}) {
|
|
71
|
+
const options = { group, variant, root, variantDirectory, fixture, runtime, freeflow, hostExtensions, signal };
|
|
72
|
+
options.extendEnvironment = extendEnvironment;
|
|
68
73
|
const subject = await prepareSubject(options, "rpc");
|
|
69
|
-
const before = await fingerprintDirectory(subject.workspace);
|
|
74
|
+
const before = await fingerprintDirectory(subject.workspace, WORKSPACE);
|
|
70
75
|
const declaredPrompts = group.input.prompt === undefined ? [...group.input.turns] : [group.input.prompt];
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
:
|
|
84
|
-
|
|
76
|
+
// A container environment runs the subject's bash and declared commands in a container of its own, removed even
|
|
77
|
+
// when the run is cancelled. A group with neither needs no subject container; its graders still run in the image.
|
|
78
|
+
const usesContainer =
|
|
79
|
+
group.tools.some((tool) => CONTAINER_SHELL_TOOLS.has(tool)) || (group.commands?.length ?? 0) > 0;
|
|
80
|
+
const declaredContainer = usesContainer ? group.variants[variant].shell?.container : undefined;
|
|
81
|
+
let container = null;
|
|
82
|
+
if (declaredContainer !== undefined) {
|
|
83
|
+
const { containerTarget, startContainer } = await import("./container.mjs");
|
|
84
|
+
// The subject's declared resources are mounted read-only at the paths it was given, so its bash can run a
|
|
85
|
+
// skill's scripts; the workspace is the only writable mount.
|
|
86
|
+
container = await startContainer({
|
|
87
|
+
container: declaredContainer,
|
|
88
|
+
workspace: subject.workspace,
|
|
89
|
+
resources: subject.resourceRoots,
|
|
90
|
+
});
|
|
91
|
+
subject.processEnvironment.SKILL_EVAL_CONTAINER = containerTarget(container);
|
|
92
|
+
}
|
|
93
|
+
let observation;
|
|
94
|
+
try {
|
|
95
|
+
observation = await subject.adapter.runSession({
|
|
96
|
+
subject,
|
|
97
|
+
command: subject.host.command,
|
|
98
|
+
settings: subject.isolation.settings,
|
|
99
|
+
args: subject.args,
|
|
100
|
+
cwd: subject.workspace,
|
|
101
|
+
eventsFile: subject.eventsFile,
|
|
102
|
+
stderrFile: subject.stderrFile,
|
|
103
|
+
signal,
|
|
104
|
+
prompts: declaredPrompts,
|
|
105
|
+
resumeBefore: group.input.resume_before ?? [],
|
|
106
|
+
targetPath: subject.environment.targetPath,
|
|
107
|
+
environment: subject.processEnvironment,
|
|
108
|
+
nextPrompt,
|
|
109
|
+
afterTurn: needsTurnWorkspaceEvidence(group)
|
|
110
|
+
? (turn) => snapshotWorkspace({ workspace: subject.workspace, variantDirectory, turn, before })
|
|
111
|
+
: null,
|
|
112
|
+
});
|
|
113
|
+
} finally {
|
|
114
|
+
await container?.remove();
|
|
115
|
+
}
|
|
85
116
|
const contextObservation = await readContextObservations(
|
|
86
117
|
subject.contextObservationPath,
|
|
87
118
|
subject.requiresContextObservation,
|
|
88
119
|
);
|
|
89
120
|
observation.contextObservationArtifact = contextObservation.artifact;
|
|
121
|
+
if (contextObservation.error) (observation.protocolErrors ??= []).push(contextObservation.error);
|
|
90
122
|
await verifySubjectResources(subject, observation);
|
|
91
|
-
|
|
123
|
+
// Links the subject made are recorded with their targets, never followed, so an installer's link cannot lose the run.
|
|
124
|
+
const after = await fingerprintDirectory(subject.workspace, WORKSPACE);
|
|
92
125
|
|
|
93
126
|
const turns = [];
|
|
94
127
|
for (const [index, turn] of observation.turns.entries()) {
|
|
@@ -105,6 +138,9 @@ export async function runBody({ group, variant, root, variantDirectory, fixture,
|
|
|
105
138
|
assistantError: turn.assistantError,
|
|
106
139
|
settled: turn.settled,
|
|
107
140
|
workspace: turn.workspace ?? null,
|
|
141
|
+
...(turn.resumed ? { resumed: turn.resumed } : {}),
|
|
142
|
+
// Runs Pi started on its own after this turn's prompt (an extension's notice), whose activity is part of it.
|
|
143
|
+
...(turn.unpromptedRuns ? { unpromptedRuns: turn.unpromptedRuns } : {}),
|
|
108
144
|
});
|
|
109
145
|
}
|
|
110
146
|
|
|
@@ -141,7 +177,7 @@ function bodyRun(options, subject, observation, input, effects) {
|
|
|
141
177
|
}
|
|
142
178
|
|
|
143
179
|
function subjectRun({ group, variant }, subject, observation) {
|
|
144
|
-
|
|
180
|
+
const run = {
|
|
145
181
|
schema_version: 1,
|
|
146
182
|
variant,
|
|
147
183
|
state: subjectRunState(observation),
|
|
@@ -151,7 +187,7 @@ function subjectRun({ group, variant }, subject, observation) {
|
|
|
151
187
|
tools: [...group.tools],
|
|
152
188
|
commands: group.commands ?? [],
|
|
153
189
|
model: {
|
|
154
|
-
declared: group.model ?? null,
|
|
190
|
+
declared: group.variants[variant].model ?? null,
|
|
155
191
|
observed: observation.model,
|
|
156
192
|
},
|
|
157
193
|
resources: {
|
|
@@ -160,9 +196,14 @@ function subjectRun({ group, variant }, subject, observation) {
|
|
|
160
196
|
skills: subject.environment.skills,
|
|
161
197
|
context: subject.environment.context,
|
|
162
198
|
runtime: subject.runtime,
|
|
199
|
+
freeflow: subject.freeflow,
|
|
200
|
+
hostExtensions: subject.hostExtensions,
|
|
163
201
|
contextDelivery: subject.environment.contextDelivery,
|
|
164
202
|
targetPath: subject.environment.targetPath,
|
|
203
|
+
// Everything the subject's tools could read: the workspace first, then its declared resources.
|
|
204
|
+
readableRoots: [subject.workspaceRoot, ...subject.resourceRoots],
|
|
165
205
|
},
|
|
206
|
+
isolation: subject.isolation,
|
|
166
207
|
contextObservationArtifact: observation.contextObservationArtifact ?? null,
|
|
167
208
|
response: observation.response,
|
|
168
209
|
transcript: observation.transcript,
|
|
@@ -181,17 +222,24 @@ function subjectRun({ group, variant }, subject, observation) {
|
|
|
181
222
|
stderr: subject.stderrFile,
|
|
182
223
|
},
|
|
183
224
|
};
|
|
225
|
+
// Run-metrics hooks derive their fields from what this run already recorded.
|
|
226
|
+
const metrics = runMetrics({ group, arm: variant, subject, observation, run });
|
|
227
|
+
if (metrics !== null) run.metrics = metrics;
|
|
228
|
+
return run;
|
|
184
229
|
}
|
|
185
230
|
|
|
186
231
|
async function runOneShotDescription(options) {
|
|
187
232
|
const subject = await prepareSubject(options, "json");
|
|
188
|
-
const observation = await
|
|
233
|
+
const observation = await subject.adapter.runOneShot({
|
|
234
|
+
subject,
|
|
189
235
|
command: subject.host.command,
|
|
190
236
|
args: subject.args,
|
|
191
237
|
cwd: subject.workspace,
|
|
192
238
|
eventsFile: subject.eventsFile,
|
|
193
239
|
stderrFile: subject.stderrFile,
|
|
194
240
|
signal: options.signal,
|
|
241
|
+
// Pi takes the prompt as its last argument (`args`); a host that reads prompts from stdin takes it here.
|
|
242
|
+
prompts: [options.group.input.prompt],
|
|
195
243
|
environment: subject.processEnvironment,
|
|
196
244
|
});
|
|
197
245
|
const contextObservation = await readContextObservations(
|
|
@@ -199,12 +247,14 @@ async function runOneShotDescription(options) {
|
|
|
199
247
|
subject.requiresContextObservation,
|
|
200
248
|
);
|
|
201
249
|
observation.contextObservationArtifact = contextObservation.artifact;
|
|
250
|
+
if (contextObservation.error) (observation.protocolErrors ??= []).push(contextObservation.error);
|
|
202
251
|
await verifySubjectResources(subject, observation);
|
|
203
252
|
const successfulReadPaths = await canonicalReadPaths(observation.successfulReads, subject.workspace);
|
|
204
253
|
const targetRead =
|
|
205
254
|
subject.environment.targetPath !== null && successfulReadPaths.includes(subject.environment.targetPath);
|
|
206
255
|
return descriptionRun(options, subject, observation, {
|
|
207
256
|
input: { prompt: options.group.input.prompt },
|
|
257
|
+
toolActivity: observation.toolActivity ?? [],
|
|
208
258
|
activation: {
|
|
209
259
|
targetRead,
|
|
210
260
|
firstReadTurn: targetRead ? 1 : null,
|
|
@@ -216,8 +266,10 @@ async function runOneShotDescription(options) {
|
|
|
216
266
|
|
|
217
267
|
async function runPersistentDescription(options) {
|
|
218
268
|
const subject = await prepareSubject(options, "rpc");
|
|
219
|
-
const observation = await
|
|
269
|
+
const observation = await subject.adapter.runSession({
|
|
270
|
+
subject,
|
|
220
271
|
command: subject.host.command,
|
|
272
|
+
settings: subject.isolation.settings,
|
|
221
273
|
args: subject.args,
|
|
222
274
|
cwd: subject.workspace,
|
|
223
275
|
eventsFile: subject.eventsFile,
|
|
@@ -231,6 +283,7 @@ async function runPersistentDescription(options) {
|
|
|
231
283
|
subject.requiresContextObservation,
|
|
232
284
|
);
|
|
233
285
|
observation.contextObservationArtifact = contextObservation.artifact;
|
|
286
|
+
if (contextObservation.error) (observation.protocolErrors ??= []).push(contextObservation.error);
|
|
234
287
|
await verifySubjectResources(subject, observation);
|
|
235
288
|
|
|
236
289
|
const turns = [];
|
|
@@ -264,59 +317,139 @@ async function runPersistentDescription(options) {
|
|
|
264
317
|
});
|
|
265
318
|
}
|
|
266
319
|
|
|
267
|
-
async function prepareSubject(
|
|
320
|
+
async function prepareSubject(
|
|
321
|
+
{
|
|
322
|
+
group,
|
|
323
|
+
variant,
|
|
324
|
+
root,
|
|
325
|
+
variantDirectory,
|
|
326
|
+
fixture: fixtureSnapshot,
|
|
327
|
+
runtime,
|
|
328
|
+
freeflow = null,
|
|
329
|
+
hostExtensions = [],
|
|
330
|
+
extendEnvironment = null,
|
|
331
|
+
},
|
|
332
|
+
mode,
|
|
333
|
+
) {
|
|
268
334
|
const workspace = path.join(variantDirectory, "workspace");
|
|
269
335
|
|
|
270
336
|
let environment;
|
|
271
337
|
let fixture;
|
|
272
338
|
let materializedRuntime;
|
|
339
|
+
let adapter;
|
|
340
|
+
let isolation;
|
|
273
341
|
try {
|
|
274
342
|
environment = await materializeEnvironment({
|
|
275
343
|
environment: group.variants[variant],
|
|
276
344
|
root,
|
|
277
345
|
variantDirectory,
|
|
278
346
|
});
|
|
347
|
+
// A pipeline stage adds what it declares it sees from earlier stages as further declared context.
|
|
348
|
+
if (extendEnvironment !== null) await extendEnvironment(environment, variantDirectory);
|
|
279
349
|
materializedRuntime = await materializeRuntime({ runtime, variantDirectory });
|
|
350
|
+
// Runtime environment literals may differ between arms (definitions.mjs); each subject gets its arm's own.
|
|
351
|
+
const literal = group.variants[variant].runtimeLiteral;
|
|
352
|
+
if (literal !== undefined) materializedRuntime.environment = { ...materializedRuntime.environment, literal };
|
|
280
353
|
fixture = await materializeFixture({ fixture: fixtureSnapshot, workspace });
|
|
354
|
+
// Written before the workspace's starting state is taken, so they never count as the subject's changes.
|
|
355
|
+
if (freeflow !== null) await writeFreeflowSettings(workspace, freeflow);
|
|
356
|
+
adapter = hostAdapter(materializedRuntime.host);
|
|
357
|
+
isolation = await adapter.prepareIsolation(variantDirectory, group.variants[variant].model?.model ?? null, {
|
|
358
|
+
settings: adapter.effectiveSettings(group.variants[variant].hostSettings ?? {}),
|
|
359
|
+
});
|
|
281
360
|
} catch (error) {
|
|
282
361
|
if (error instanceof VariantSetupError) throw error;
|
|
283
362
|
throw new VariantSetupError(error instanceof Error ? error.message : String(error));
|
|
284
363
|
}
|
|
285
364
|
|
|
286
|
-
const host = { name: materializedRuntime.host, command:
|
|
365
|
+
const host = { name: materializedRuntime.host, command: adapter.command };
|
|
287
366
|
const contextObservationPath = path.join(variantDirectory, "context-observations.jsonl");
|
|
288
367
|
const requiresContextObservation = group.expectations.some((expectation) => expectation.kind === "context-text");
|
|
289
368
|
const sessionDirectory = path.join(variantDirectory, "session");
|
|
290
369
|
if (materializedRuntime.session) await mkdir(sessionDirectory, { recursive: true });
|
|
291
|
-
const args = piArguments(group, environment, materializedRuntime, mode, requiresContextObservation, sessionDirectory);
|
|
292
370
|
const allowedRoots = [
|
|
293
371
|
await realpath(workspace),
|
|
294
372
|
...environment.skills.map((skill) => skill.path),
|
|
295
373
|
...environment.context.map((entry) => entry.path),
|
|
296
374
|
...materializedRuntime.extensions.flatMap((bundle) => bundle.resources.map((resource) => resource.path)),
|
|
375
|
+
// Freeflow points the subject at its own skills and references inside the package.
|
|
376
|
+
...(freeflow === null ? [] : [freeflow.packageRoot]),
|
|
377
|
+
...(group.tools.some((tool) => BACKGROUND_TOOLS.has(tool)) && isolation.environment.TMPDIR
|
|
378
|
+
? [isolation.environment.TMPDIR]
|
|
379
|
+
: []),
|
|
297
380
|
];
|
|
381
|
+
let launch;
|
|
382
|
+
try {
|
|
383
|
+
launch = await adapter.prepareLaunch({
|
|
384
|
+
group,
|
|
385
|
+
variant,
|
|
386
|
+
environment,
|
|
387
|
+
runtime: materializedRuntime,
|
|
388
|
+
mode,
|
|
389
|
+
observeContext: requiresContextObservation,
|
|
390
|
+
contextObservationPath,
|
|
391
|
+
sessionDirectory,
|
|
392
|
+
model: group.variants[variant].model,
|
|
393
|
+
freeflowEntry: freeflow?.entry ?? null,
|
|
394
|
+
hostExtensions,
|
|
395
|
+
workspace,
|
|
396
|
+
variantDirectory,
|
|
397
|
+
allowedRoots,
|
|
398
|
+
isolation: isolation.evidence,
|
|
399
|
+
});
|
|
400
|
+
} catch (error) {
|
|
401
|
+
if (error instanceof VariantSetupError) throw error;
|
|
402
|
+
throw new VariantSetupError(error instanceof Error ? error.message : String(error));
|
|
403
|
+
}
|
|
298
404
|
return {
|
|
299
|
-
|
|
405
|
+
adapter,
|
|
406
|
+
args: launch.args,
|
|
300
407
|
environment,
|
|
408
|
+
hostExtensions,
|
|
409
|
+
freeflow:
|
|
410
|
+
freeflow === null
|
|
411
|
+
? null
|
|
412
|
+
: {
|
|
413
|
+
ref: freeflow.ref,
|
|
414
|
+
commit: freeflow.commit,
|
|
415
|
+
package: freeflow.package,
|
|
416
|
+
tarballSha256: freeflow.tarballSha256,
|
|
417
|
+
metadata: freeflow.metadata,
|
|
418
|
+
repository: freeflow.repository,
|
|
419
|
+
personal: freeflow.personal,
|
|
420
|
+
},
|
|
421
|
+
// Where the built Freeflow package lies, so metrics can tell its skill reads apart; not recorded in run.json.
|
|
422
|
+
freeflowRoot: freeflow?.packageRoot ?? null,
|
|
301
423
|
runtime: materializedRuntime,
|
|
302
424
|
host,
|
|
303
425
|
fixture,
|
|
304
426
|
workspace,
|
|
427
|
+
workspaceRoot: allowedRoots[0],
|
|
428
|
+
// Every readable root but the workspace: the declared skills, context, runtime resources and Freeflow's package.
|
|
429
|
+
resourceRoots: allowedRoots.slice(1),
|
|
305
430
|
contextObservationPath,
|
|
306
431
|
requiresContextObservation,
|
|
307
432
|
sessionDirectory,
|
|
308
433
|
eventsFile: path.join(variantDirectory, "events.jsonl"),
|
|
309
434
|
stderrFile: path.join(variantDirectory, "stderr.log"),
|
|
310
435
|
startedAt: new Date().toISOString(),
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
436
|
+
isolation: isolation.evidence,
|
|
437
|
+
processEnvironment: {
|
|
438
|
+
...createProcessEnvironment({
|
|
439
|
+
runtime: materializedRuntime,
|
|
440
|
+
group,
|
|
441
|
+
workspace,
|
|
442
|
+
allowedRoots,
|
|
443
|
+
contextManifestPath: environment.contextDelivery.manifestPath,
|
|
444
|
+
contextObservationPath,
|
|
445
|
+
requiresContextObservation,
|
|
446
|
+
hostEnvironment: launch.environment,
|
|
447
|
+
}),
|
|
448
|
+
// A declared shell lets the guard allow bash; its isolation extension runs it.
|
|
449
|
+
...(group.variants[variant].shell ? { SKILL_EVAL_SHELL: JSON.stringify(group.variants[variant].shell) } : {}),
|
|
450
|
+
// Last, so nothing inherited or declared can point the subject back at the parent's home or Pi settings.
|
|
451
|
+
...isolation.environment,
|
|
452
|
+
},
|
|
320
453
|
};
|
|
321
454
|
}
|
|
322
455
|
|
|
@@ -328,13 +461,14 @@ function createProcessEnvironment({
|
|
|
328
461
|
contextManifestPath,
|
|
329
462
|
contextObservationPath,
|
|
330
463
|
requiresContextObservation,
|
|
464
|
+
hostEnvironment,
|
|
331
465
|
}) {
|
|
332
466
|
const processEnvironment = baseProcessEnvironment();
|
|
333
467
|
Object.assign(processEnvironment, {
|
|
334
468
|
PWD: workspace,
|
|
335
469
|
...runtime.environment.literal,
|
|
336
|
-
|
|
337
|
-
|
|
470
|
+
// The host's own variables, such as Pi's version check and telemetry switches, after declared literals.
|
|
471
|
+
...hostEnvironment,
|
|
338
472
|
SKILL_EVAL_ALLOWED_ROOTS: JSON.stringify(allowedRoots),
|
|
339
473
|
SKILL_EVAL_WRITABLE_ROOT: workspace,
|
|
340
474
|
SKILL_EVAL_ALLOWED_TOOLS: JSON.stringify(group.tools),
|
|
@@ -353,30 +487,39 @@ function createProcessEnvironment({
|
|
|
353
487
|
return processEnvironment;
|
|
354
488
|
}
|
|
355
489
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
BASE_PROCESS_ENVIRONMENT_KEYS.flatMap((key) => (process.env[key] === undefined ? [] : [[key, process.env[key]]])),
|
|
359
|
-
);
|
|
360
|
-
}
|
|
361
|
-
|
|
490
|
+
// A missing or malformed observation fails the subject but keeps everything the process already reported:
|
|
491
|
+
// transcript, response, usage, and process evidence stay in run.json.
|
|
362
492
|
async function readContextObservations(file, required) {
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
493
|
+
let contents;
|
|
494
|
+
try {
|
|
495
|
+
contents = await readFile(file, "utf8");
|
|
496
|
+
} catch (error) {
|
|
497
|
+
if (error?.code !== "ENOENT") throw error;
|
|
498
|
+
if (!required) return { observations: [], artifact: null, error: null };
|
|
499
|
+
return {
|
|
500
|
+
observations: [],
|
|
501
|
+
artifact: null,
|
|
502
|
+
error: { reason: "context-observer-missing", message: "context observer produced no evidence" },
|
|
503
|
+
};
|
|
504
|
+
}
|
|
370
505
|
const observations = [];
|
|
371
506
|
for (const line of contents.split("\n").filter(Boolean)) {
|
|
372
507
|
try {
|
|
373
508
|
observations.push(JSON.parse(line));
|
|
374
509
|
} catch (error) {
|
|
375
|
-
|
|
510
|
+
return {
|
|
511
|
+
observations: [],
|
|
512
|
+
artifact: null,
|
|
513
|
+
error: {
|
|
514
|
+
reason: "context-observation-malformed",
|
|
515
|
+
message: `context observation is malformed: ${error instanceof Error ? error.message : String(error)}`,
|
|
516
|
+
},
|
|
517
|
+
};
|
|
376
518
|
}
|
|
377
519
|
}
|
|
378
520
|
return {
|
|
379
521
|
observations,
|
|
522
|
+
error: null,
|
|
380
523
|
artifact:
|
|
381
524
|
contents === ""
|
|
382
525
|
? null
|
|
@@ -403,11 +546,12 @@ async function verifySubjectResources(subject, observation) {
|
|
|
403
546
|
}
|
|
404
547
|
}
|
|
405
548
|
|
|
406
|
-
function descriptionRun(options, subject, observation, { input, activation }) {
|
|
549
|
+
function descriptionRun(options, subject, observation, { input, activation, toolActivity }) {
|
|
407
550
|
return {
|
|
408
551
|
...subjectRun(options, subject, observation),
|
|
409
552
|
evaluationType: "description",
|
|
410
553
|
...input,
|
|
554
|
+
...(toolActivity === undefined ? {} : { toolActivity }),
|
|
411
555
|
activation,
|
|
412
556
|
};
|
|
413
557
|
}
|
|
@@ -426,180 +570,6 @@ function subjectRunState(observation) {
|
|
|
426
570
|
return "infrastructure-failed";
|
|
427
571
|
}
|
|
428
572
|
|
|
429
|
-
function piArguments(group, environment, runtime, mode, observeContext, sessionDirectory) {
|
|
430
|
-
const args = ["--mode", mode];
|
|
431
|
-
if (mode === "json") args.push("-p");
|
|
432
|
-
if (runtime.session) args.push("--session-dir", sessionDirectory);
|
|
433
|
-
else args.push("--no-session");
|
|
434
|
-
args.push("--no-extensions", "--extension", guardExtension);
|
|
435
|
-
if (group.commands !== undefined) args.push("--extension", commandToolExtension);
|
|
436
|
-
for (const bundle of runtime.extensions) args.push("--extension", bundle.entry);
|
|
437
|
-
if (observeContext) args.push("--extension", observerExtension);
|
|
438
|
-
args.push("--no-skills", "--no-prompt-templates", "--no-themes", "--no-context-files", "--no-approve");
|
|
439
|
-
if (group.tools.length === 0) args.push("--no-tools");
|
|
440
|
-
else args.push("--tools", group.tools.join(","));
|
|
441
|
-
for (const skill of environment.skills) args.push("--skill", skill.path);
|
|
442
|
-
if (group.model?.model) args.push("--model", group.model.model);
|
|
443
|
-
if (group.model?.thinking) args.push("--thinking", group.model.thinking);
|
|
444
|
-
if (mode === "json") args.push(group.input.prompt);
|
|
445
|
-
return args;
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
export async function runPiProcess({ command, args, cwd, eventsFile, stderrFile, signal, environment }) {
|
|
449
|
-
const child = spawn(command, args, {
|
|
450
|
-
cwd,
|
|
451
|
-
detached: process.platform !== "win32",
|
|
452
|
-
env: environment,
|
|
453
|
-
shell: false,
|
|
454
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
455
|
-
});
|
|
456
|
-
const events = createWriteStream(eventsFile, { encoding: "utf8" });
|
|
457
|
-
const stderr = createWriteStream(stderrFile, { encoding: "utf8" });
|
|
458
|
-
const transcript = [];
|
|
459
|
-
const calls = new Map();
|
|
460
|
-
const successfulReads = [];
|
|
461
|
-
const parseErrors = [];
|
|
462
|
-
const protocolErrors = [];
|
|
463
|
-
let settled = false;
|
|
464
|
-
let response = "";
|
|
465
|
-
let usage = null;
|
|
466
|
-
let assistantError = null;
|
|
467
|
-
let observedModel = null;
|
|
468
|
-
let buffer = "";
|
|
469
|
-
let eventLine = 0;
|
|
470
|
-
const processGroupId = child.pid;
|
|
471
|
-
let watchdog;
|
|
472
|
-
let forcedKill;
|
|
473
|
-
/** @type {Promise<void> | null} */
|
|
474
|
-
let forcedKillPromise = null;
|
|
475
|
-
let terminationReason = null;
|
|
476
|
-
|
|
477
|
-
const resetWatchdog = () => {
|
|
478
|
-
clearTimeout(watchdog);
|
|
479
|
-
watchdog = setTimeout(() => requestTermination("no-progress-watchdog"), NO_PROGRESS_MS);
|
|
480
|
-
watchdog.unref();
|
|
481
|
-
};
|
|
482
|
-
const requestTermination = (reason) => {
|
|
483
|
-
if (terminationReason !== null) return;
|
|
484
|
-
terminationReason = reason;
|
|
485
|
-
signalProcessTree(processGroupId, child, "SIGTERM");
|
|
486
|
-
if (process.platform !== "win32") {
|
|
487
|
-
forcedKillPromise = new Promise((resolve) => {
|
|
488
|
-
forcedKill = setTimeout(() => {
|
|
489
|
-
signalProcessTree(processGroupId, child, "SIGKILL");
|
|
490
|
-
resolve();
|
|
491
|
-
}, TERMINATION_GRACE_MS);
|
|
492
|
-
});
|
|
493
|
-
}
|
|
494
|
-
};
|
|
495
|
-
const onAbort = () => requestTermination("cancelled");
|
|
496
|
-
if (signal?.aborted) onAbort();
|
|
497
|
-
else signal?.addEventListener("abort", onAbort, { once: true });
|
|
498
|
-
resetWatchdog();
|
|
499
|
-
|
|
500
|
-
const stderrTask = pipeStream(child.stderr, stderr, resetWatchdog);
|
|
501
|
-
const stdoutTask = (async () => {
|
|
502
|
-
for await (const chunk of child.stdout) {
|
|
503
|
-
resetWatchdog();
|
|
504
|
-
buffer += chunk.toString("utf8");
|
|
505
|
-
while (true) {
|
|
506
|
-
const newline = buffer.indexOf("\n");
|
|
507
|
-
if (newline === -1) break;
|
|
508
|
-
const line = buffer.slice(0, newline);
|
|
509
|
-
buffer = buffer.slice(newline + 1);
|
|
510
|
-
await writeStream(events, `${line}\n`);
|
|
511
|
-
observeLine(line.endsWith("\r") ? line.slice(0, -1) : line);
|
|
512
|
-
}
|
|
513
|
-
}
|
|
514
|
-
if (buffer.length > 0) {
|
|
515
|
-
await writeStream(events, buffer);
|
|
516
|
-
observeLine(buffer.endsWith("\r") ? buffer.slice(0, -1) : buffer);
|
|
517
|
-
}
|
|
518
|
-
events.end();
|
|
519
|
-
await once(events, "finish");
|
|
520
|
-
})();
|
|
521
|
-
|
|
522
|
-
function observeLine(line) {
|
|
523
|
-
eventLine += 1;
|
|
524
|
-
if (line.trim() === "") return;
|
|
525
|
-
let event;
|
|
526
|
-
try {
|
|
527
|
-
event = JSON.parse(line);
|
|
528
|
-
} catch {
|
|
529
|
-
parseErrors.push({ line: eventLine, reason: "invalid-json" });
|
|
530
|
-
return;
|
|
531
|
-
}
|
|
532
|
-
if (event.type === "extension_error") {
|
|
533
|
-
protocolErrors.push({
|
|
534
|
-
reason: "extension-error",
|
|
535
|
-
extensionPath: event.extensionPath ?? null,
|
|
536
|
-
event: event.event ?? null,
|
|
537
|
-
error: event.error ?? null,
|
|
538
|
-
});
|
|
539
|
-
requestTermination("protocol-error");
|
|
540
|
-
}
|
|
541
|
-
if (event.type === "agent_settled") settled = true;
|
|
542
|
-
if (event.type === "tool_execution_start") {
|
|
543
|
-
calls.set(event.toolCallId, { toolName: event.toolName, args: event.args });
|
|
544
|
-
}
|
|
545
|
-
if (event.type === "tool_execution_end" && !event.isError) {
|
|
546
|
-
const call = calls.get(event.toolCallId);
|
|
547
|
-
if (call?.toolName === "read" && typeof call.args?.path === "string") {
|
|
548
|
-
successfulReads.push(call.args.path);
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
if (event.type === "message_end" && event.message) {
|
|
552
|
-
transcript.push(event.message);
|
|
553
|
-
if (event.message.role === "assistant") {
|
|
554
|
-
response = messageText(event.message);
|
|
555
|
-
usage = mergeUsage(usage, event.message.usage);
|
|
556
|
-
observedModel = {
|
|
557
|
-
provider: event.message.provider ?? null,
|
|
558
|
-
model: event.message.model ?? null,
|
|
559
|
-
};
|
|
560
|
-
assistantError =
|
|
561
|
-
event.message.stopReason === "error" || event.message.stopReason === "aborted"
|
|
562
|
-
? (event.message.errorMessage ?? `assistant stopped with ${event.message.stopReason}`)
|
|
563
|
-
: null;
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
let exitCode = null;
|
|
569
|
-
let exitSignal = null;
|
|
570
|
-
try {
|
|
571
|
-
const [code, closedSignal] = await once(child, "close");
|
|
572
|
-
exitCode = code;
|
|
573
|
-
exitSignal = closedSignal;
|
|
574
|
-
await Promise.all([stdoutTask, stderrTask]);
|
|
575
|
-
} catch (error) {
|
|
576
|
-
requestTermination("process-error");
|
|
577
|
-
throw error;
|
|
578
|
-
} finally {
|
|
579
|
-
clearTimeout(watchdog);
|
|
580
|
-
if (forcedKillPromise !== null) {
|
|
581
|
-
if (processGroupExists(processGroupId)) await waitForForcedKill(forcedKillPromise);
|
|
582
|
-
else clearTimeout(forcedKill);
|
|
583
|
-
}
|
|
584
|
-
signal?.removeEventListener("abort", onAbort);
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
return {
|
|
588
|
-
exitCode,
|
|
589
|
-
signal: exitSignal,
|
|
590
|
-
settled,
|
|
591
|
-
assistantError,
|
|
592
|
-
model: observedModel,
|
|
593
|
-
terminationReason,
|
|
594
|
-
parseErrors,
|
|
595
|
-
protocolErrors,
|
|
596
|
-
successfulReads,
|
|
597
|
-
transcript,
|
|
598
|
-
response,
|
|
599
|
-
usage,
|
|
600
|
-
};
|
|
601
|
-
}
|
|
602
|
-
|
|
603
573
|
async function canonicalReadPaths(paths, cwd) {
|
|
604
574
|
const canonical = [];
|
|
605
575
|
for (const rawPath of paths) {
|