humanish 0.110.2 → 0.110.4
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/ARCHITECTURE.md +10 -15
- package/CHANGELOG.md +27 -0
- package/CONTEXT.md +1 -1
- package/dist/actors/computer-use/actor.js +2 -2
- package/dist/actors/computer-use/loop/ending.js +1 -1
- package/dist/actors/registry.js +1 -1
- package/dist/actors/scripted-browser/actor.js +17 -8
- package/dist/actors/scripted-browser/launch-env.d.ts +12 -0
- package/dist/actors/scripted-browser/launch-env.js +50 -0
- package/dist/analysis/automatic-completion.d.ts +2 -1
- package/dist/analysis/automatic-completion.js +15 -2
- package/dist/cli/commands/migrate.js +1 -1
- package/dist/cli/commands/observe.js +3 -2
- package/dist/cli/commands/runs.js +5 -2
- package/dist/cli/commands/study-route-computer-use.js +3 -2
- package/dist/cli/commands/study-route-preview.js +2 -1
- package/dist/cli/commands/study-route-shared-world.js +3 -3
- package/dist/cli/commands/study-run.js +9 -19
- package/dist/cli/commands/study.js +4 -1
- package/dist/cli/findings.d.ts +5 -0
- package/dist/cli/findings.js +21 -0
- package/dist/cli/io.d.ts +2 -1
- package/dist/cli/io.js +3 -2
- package/dist/cli/observer-follow.d.ts +6 -2
- package/dist/cli/observer-follow.js +15 -5
- package/dist/evidence/redaction.js +15 -4
- package/dist/routes/computer-use/live-phase.js +8 -1
- package/dist/routes/computer-use/local-vm.js +2 -1
- package/dist/routes/computer-use/participant-runs.d.ts +6 -9
- package/dist/routes/computer-use/participant-runs.js +16 -36
- package/dist/routes/computer-use/plan.d.ts +2 -2
- package/dist/routes/computer-use/plan.js +7 -6
- package/dist/routes/computer-use/route.d.ts +5 -18
- package/dist/routes/computer-use/route.js +19 -79
- package/dist/routes/computer-use/setup.d.ts +3 -2
- package/dist/routes/computer-use/setup.js +2 -1
- package/dist/routes/computer-use/types.d.ts +6 -10
- package/dist/routes/scripted/plan.js +5 -4
- package/dist/routes/scripted/route.d.ts +4 -17
- package/dist/routes/scripted/route.js +15 -43
- package/dist/routes/scripted/surface-sessions.d.ts +2 -0
- package/dist/routes/scripted/surface-sessions.js +2 -1
- package/dist/routes/scripted/types.d.ts +1 -6
- package/dist/routes/shared-world/participant-specs.js +5 -1
- package/dist/routes/shared-world/plan.js +7 -6
- package/dist/routes/shared-world/route.d.ts +5 -11
- package/dist/routes/shared-world/route.js +27 -66
- package/dist/routes/shared-world/types.d.ts +2 -6
- package/dist/routes/terminal/plan.js +4 -3
- package/dist/routes/terminal/route.d.ts +3 -13
- package/dist/routes/terminal/route.js +21 -60
- package/dist/routes/terminal/session.d.ts +2 -3
- package/dist/routes/terminal/session.js +3 -3
- package/dist/routes/terminal/types.d.ts +2 -7
- package/dist/run/display.d.ts +10 -0
- package/dist/run/display.js +22 -0
- package/dist/run/reclaim.d.ts +4 -2
- package/dist/run/reclaim.js +61 -18
- package/dist/run/route-shell.d.ts +60 -0
- package/dist/run/route-shell.js +51 -0
- package/dist/run/run.d.ts +16 -1
- package/dist/run/run.js +33 -5
- package/dist/run/status.d.ts +8 -0
- package/dist/run/status.js +6 -0
- package/dist/run/stored-runs.js +26 -11
- package/dist/study/composition-rules.js +33 -33
- package/dist/study/config.d.ts +9 -2
- package/dist/study/config.js +14 -5
- package/dist/study/doctor.js +5 -4
- package/dist/study/init-templates.d.ts +1 -1
- package/dist/study/init-templates.js +43 -34
- package/dist/study/init.js +1 -1
- package/dist/study/{convert.d.ts → migrate/convert.d.ts} +1 -1
- package/dist/study/{convert.js → migrate/convert.js} +29 -31
- package/dist/study/{migrate.d.ts → migrate/migrate.d.ts} +1 -1
- package/dist/study/{migrate.js → migrate/migrate.js} +2 -2
- package/dist/study/{owned-files.js → migrate/owned-files.js} +1 -1
- package/dist/study/migrate/v2.d.ts +68 -0
- package/dist/study/migrate/v2.js +480 -0
- package/dist/study/parse/actors.d.ts +46 -1
- package/dist/study/parse/actors.js +116 -69
- package/dist/study/parse/execution.js +2 -2
- package/dist/study/parse/study-v3.d.ts +26 -0
- package/dist/study/parse/study-v3.js +53 -35
- package/dist/study/parse/study.d.ts +38 -0
- package/dist/study/parse/study.js +225 -0
- package/dist/study/parse/subject.js +1 -1
- package/dist/study/persona-resolve.d.ts +2 -4
- package/dist/study/persona-resolve.js +2 -1
- package/dist/study/plan-base.d.ts +1 -1
- package/dist/study/plan-base.js +5 -4
- package/dist/study/plan-participants.js +12 -11
- package/dist/study/plan.js +4 -3
- package/dist/study/preflight-probes.js +2 -2
- package/dist/study/preflight.js +2 -2
- package/dist/study/routing.js +12 -15
- package/dist/study/run-study-options.js +3 -3
- package/dist/study/study-fields.d.ts +28 -0
- package/dist/study/study-fields.js +51 -0
- package/dist/study/summary.js +13 -17
- package/dist/study/types.d.ts +40 -0
- package/dist/study/url-credentials.js +2 -1
- package/dist/study/validation.d.ts +2 -0
- package/dist/study/validation.js +46 -41
- package/dist/study/warnings.js +5 -4
- package/dist/substrates/local/runtime-config.js +9 -9
- package/dist/tui-app.js +3 -3
- package/docs/architecture/actor-contract.md +1 -1
- package/docs/architecture/external-public-shared-world.md +1 -1
- package/docs/architecture/terminal-product-route.md +13 -13
- package/docs/contracts/schemas.md +13 -4
- package/docs/contracts/study-analysis.md +5 -2
- package/docs/product/automatic-analysis.md +1 -1
- package/package.json +1 -1
- /package/dist/study/{owned-files.d.ts → migrate/owned-files.d.ts} +0 -0
|
@@ -17,14 +17,13 @@
|
|
|
17
17
|
import { randomBytes } from "node:crypto";
|
|
18
18
|
import { realpath } from "node:fs/promises";
|
|
19
19
|
import path from "node:path";
|
|
20
|
-
import { completeAutomaticAnalysis } from "../../analysis/automatic-completion.js";
|
|
21
|
-
import { resolveAutomaticAnalysis } from "../../analysis/automatic-config.js";
|
|
22
20
|
import { redactText, toErrorMessage } from "../../evidence/redaction.js";
|
|
23
21
|
import { buildRunSource } from "../../run/bundle.js";
|
|
24
22
|
import { prepareSelectedOutputDirectory } from "../../run/contained-output.js";
|
|
25
|
-
import {
|
|
23
|
+
import {} from "../../run/run.js";
|
|
24
|
+
import { admitRoute, completeRefusalAnalysis } from "../../run/route-shell.js";
|
|
26
25
|
import { renderScriptedReviewMarkdown } from "./bundle.js";
|
|
27
|
-
import {
|
|
26
|
+
import {} from "./plan.js";
|
|
28
27
|
import { finishScriptedRun } from "./result.js";
|
|
29
28
|
import { UnsafeScriptedSessionResultError } from "./session-result.js";
|
|
30
29
|
import { prepareScriptedRun } from "./setup.js";
|
|
@@ -32,21 +31,7 @@ import { ScriptedSubject } from "./subject.js";
|
|
|
32
31
|
import { runScriptedSessions, writeSurfaceTraces } from "./surface-sessions.js";
|
|
33
32
|
import {} from "./types.js";
|
|
34
33
|
import { studyResultIdentity } from "../../run/study-result.js";
|
|
35
|
-
|
|
36
|
-
* The config-taking entry point. It plans, returns a refusal with the envelope the route has always
|
|
37
|
-
* returned at that refusal's stage, and otherwise runs the plan.
|
|
38
|
-
*/
|
|
39
|
-
export async function runScriptedBrowserStudy(options) {
|
|
40
|
-
const { config, dryRun, ...input } = options;
|
|
41
|
-
// planScriptedStudy makes every configuration refusal, in the order this route always has.
|
|
42
|
-
const planned = planScriptedStudy(config, {
|
|
43
|
-
dryRun,
|
|
44
|
-
injectedBrowser: injectedBrowser(input.deps),
|
|
45
|
-
});
|
|
46
|
-
if (planned.ok)
|
|
47
|
-
return runScriptedPlan(planned.plan, input);
|
|
48
|
-
return scriptedStudyRefusal(options, planned.refusal);
|
|
49
|
-
}
|
|
34
|
+
import { actorOf } from "../../study/study-fields.js";
|
|
50
35
|
/**
|
|
51
36
|
* A refused scripted study's result, at the refusal's stage: a before-scope refusal has its own field
|
|
52
37
|
* order and no analysis record; the others come after the output directory checks.
|
|
@@ -54,7 +39,7 @@ export async function runScriptedBrowserStudy(options) {
|
|
|
54
39
|
export async function scriptedStudyRefusal(options, refusal) {
|
|
55
40
|
const { config, dryRun } = options;
|
|
56
41
|
const cwd = path.resolve(options.cwd);
|
|
57
|
-
const actorType = config
|
|
42
|
+
const actorType = actorOf(config)?.type ?? "";
|
|
58
43
|
if (refusal.beforeScope)
|
|
59
44
|
return {
|
|
60
45
|
...studyResultIdentity("scripted", config.id),
|
|
@@ -83,35 +68,19 @@ export async function scriptedStudyRefusal(options, refusal) {
|
|
|
83
68
|
warnings: [],
|
|
84
69
|
error: { code: refusal.code, message: refusal.message },
|
|
85
70
|
};
|
|
86
|
-
|
|
87
|
-
return completeAutomaticAnalysis(refused, undefined, analysis.ok ? analysis.config : undefined, options, { trigger: config.review?.analysis === undefined ? "default" : "explicit" });
|
|
71
|
+
return completeRefusalAnalysis(refused, config, options);
|
|
88
72
|
}
|
|
89
73
|
/**
|
|
90
74
|
* runStudyWith's step for a scripted plan. It takes no scorer, and its local checks (keys, a browser)
|
|
91
75
|
* run inside the run, so it returns the run.
|
|
92
76
|
*/
|
|
93
77
|
export function admitScriptedPlan(plan, input) {
|
|
94
|
-
return {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
/**
|
|
103
|
-
* Run a scripted plan. The run scope gives a direct library caller the same status-record lifetime
|
|
104
|
-
* the CLI gets: returning from this function finalizes any record the run opened, whichever of its
|
|
105
|
-
* fail-closed exits it took. Each route opens its own scope; `runStudyWith` opens none. Without this a
|
|
106
|
-
* test or an adopter calling the route directly leaves
|
|
107
|
-
* the 5s cadence ticking into a directory something else is deleting, which surfaces as an
|
|
108
|
-
* unrelated ENOTEMPTY.
|
|
109
|
-
*/
|
|
110
|
-
export async function runScriptedPlan(plan, input) {
|
|
111
|
-
const { result, finished } = await runScope((scope) => runScriptedPlanInScope(plan, input, scope));
|
|
112
|
-
return completeAutomaticAnalysis(result, finished, plan.analysis?.config, input, {
|
|
113
|
-
...(plan.analysis === undefined ? {} : { trigger: plan.analysis.trigger }),
|
|
114
|
-
preferLargerOutput: plan.analysis?.preferLargerOutput === true,
|
|
78
|
+
return admitRoute({
|
|
79
|
+
route: "scripted",
|
|
80
|
+
analysis: plan.analysis,
|
|
81
|
+
input,
|
|
82
|
+
admit: () => ({ ok: true, admitted: plan }),
|
|
83
|
+
runInScope: runScriptedPlanInScope,
|
|
115
84
|
});
|
|
116
85
|
}
|
|
117
86
|
async function runScriptedPlanInScope(plan, input, scope) {
|
|
@@ -126,6 +95,8 @@ async function runScriptedPlanInScope(plan, input, scope) {
|
|
|
126
95
|
mintRunId: makeScriptedRunId,
|
|
127
96
|
mode: dryRun ? "dry-run" : "live",
|
|
128
97
|
study: plan.study,
|
|
98
|
+
// Only a clone subject is served from a sandbox; an app-url run drives a local browser.
|
|
99
|
+
sandboxes: setup.clone ? undefined : "none",
|
|
129
100
|
renderReview: renderScriptedReviewMarkdown,
|
|
130
101
|
observer: { open: input.open === true, render: setup.deps.renderObserver },
|
|
131
102
|
});
|
|
@@ -176,6 +147,7 @@ async function runScriptedPlanInScope(plan, input, scope) {
|
|
|
176
147
|
deps: setup.deps,
|
|
177
148
|
browserCommand: setup.browserCommand,
|
|
178
149
|
runPaths,
|
|
150
|
+
onSessionStart: () => run.participantStarted(),
|
|
179
151
|
});
|
|
180
152
|
}
|
|
181
153
|
catch (error) {
|
|
@@ -8,6 +8,8 @@ export declare function runScriptedSessions(session: Required<Pick<ScriptedBrows
|
|
|
8
8
|
deps: StudyDeps;
|
|
9
9
|
browserCommand: string | undefined;
|
|
10
10
|
runPaths: PreparedRunArtifactPaths;
|
|
11
|
+
/** Called as each surface's session starts, before it can throw or return. */
|
|
12
|
+
onSessionStart: () => void;
|
|
11
13
|
}): Promise<ScriptedBrowserSessionResult[]>;
|
|
12
14
|
/** Writes each surface's actor-<surface>.json, as the computer-use route writes actor.json. */
|
|
13
15
|
export declare function writeSurfaceTraces(runPaths: PreparedRunArtifactPaths, results: readonly ScriptedBrowserSessionResult[]): Promise<void>;
|
|
@@ -7,9 +7,10 @@ import { validateScriptedSessionResult } from "./session-result.js";
|
|
|
7
7
|
/** One session per surface, in parallel. */
|
|
8
8
|
export function runScriptedSessions(session, run) {
|
|
9
9
|
const { appUrl, evidenceAppUrl, urlPolicy, journey, persona, timeoutMs, artifactRoot } = session;
|
|
10
|
-
const { surfaces, deps, browserCommand, runPaths } = run;
|
|
10
|
+
const { surfaces, deps, browserCommand, runPaths, onSessionStart } = run;
|
|
11
11
|
const runSession = deps.runScriptedSession;
|
|
12
12
|
return Promise.all(surfaces.map((surface) => {
|
|
13
|
+
onSessionStart();
|
|
13
14
|
const sessionOptions = {
|
|
14
15
|
appUrl,
|
|
15
16
|
evidenceAppUrl,
|
|
@@ -1,23 +1,18 @@
|
|
|
1
1
|
import type { ActorCompletionReason, ActorStatus } from "../../actors/contract.js";
|
|
2
2
|
import type { StudyEvent } from "../../study/run-study-events.js";
|
|
3
3
|
import type { AutomaticAnalysisResult } from "../../analysis/automatic-completion.js";
|
|
4
|
-
import type { StudyConfig } from "../../study/types.js";
|
|
5
4
|
import type { ObserverResult } from "../../observer/render.js";
|
|
6
5
|
import type { RunSubjectProvenance } from "../../run/bundle.js";
|
|
7
6
|
import type { StudyDeps } from "../../study/study-deps.js";
|
|
8
7
|
import type { RunStudyHomes } from "../../study/run-study-homes.js";
|
|
9
8
|
import { type StudyResultIdentity } from "../../run/study-result.js";
|
|
10
9
|
/** What a scripted run takes besides its plan. The plan carries the config, dry run and study. */
|
|
11
|
-
export
|
|
12
|
-
export interface RunScriptedBrowserStudyOptions {
|
|
10
|
+
export interface ScriptedRunInput {
|
|
13
11
|
/** Cancels post-run analysis only. */
|
|
14
12
|
analysisSignal?: AbortSignal;
|
|
15
13
|
/** Reports the analysis window to onEvent; built by normalizeRunStudyOptions. */
|
|
16
14
|
emit?: (event: StudyEvent) => void;
|
|
17
15
|
cwd: string;
|
|
18
|
-
config: StudyConfig;
|
|
19
|
-
/** Resolved upstream (scenario.mode + CLI override); defaults safe (dry-run). */
|
|
20
|
-
dryRun: boolean;
|
|
21
16
|
open?: boolean;
|
|
22
17
|
runId?: string;
|
|
23
18
|
/** Keys and subject env for the run. Defaults to process.env. Values are scrubbed; names persist. */
|
|
@@ -167,7 +167,11 @@ export function participantRunDeps(ctx, live, scrubKnownValues) {
|
|
|
167
167
|
studyCwd: ctx.cwd,
|
|
168
168
|
redactScreenshots: ctx.redactScreenshots,
|
|
169
169
|
scrubKnownValues,
|
|
170
|
-
|
|
170
|
+
// A session that throws returns no trace; the run still records that it started.
|
|
171
|
+
runSession: (options) => {
|
|
172
|
+
ctx.run.participantStarted();
|
|
173
|
+
return ctx.runSession(options);
|
|
174
|
+
},
|
|
171
175
|
// A local-agent brain runs each participant on the operator's signed-in agent, as on computer
|
|
172
176
|
// use.
|
|
173
177
|
brain: ctx.plan.brain,
|
|
@@ -6,12 +6,13 @@ import { DEFAULT_OPENAI_CU_MODEL } from "../../actors/computer-use/openai-provid
|
|
|
6
6
|
import { studyUrlCredentialReason } from "../../study/url-credentials.js";
|
|
7
7
|
import { actorRegistry, isCuaActorDescriptor, } from "../../actors/registry.js";
|
|
8
8
|
import { resolveAutomaticAnalysis } from "../../analysis/automatic-config.js";
|
|
9
|
-
import { brainOf,
|
|
9
|
+
import { brainOf, planCaps, desktopRequirements, isNonEmpty, planBase, } from "../../study/plan-base.js";
|
|
10
10
|
import { sharedWorldParticipants } from "../../study/plan-participants.js";
|
|
11
11
|
import { PUBLIC_TARGET_OWNER_PATTERN } from "../../study/parse/subject.js";
|
|
12
12
|
import { REPO_SLUG_PATTERN } from "../../study/parse/values.js";
|
|
13
13
|
import { concurrentSharedWorldValidationReason, desktopMediaValidationReason, externalPublicSharedWorldValidationReason, outputTokenLimitValidationReason, receivingEmailValidationReason, scenarioCapsValidationReason, taskProtocolValidationReason, } from "../../study/validation.js";
|
|
14
14
|
import { MODEL_RATES, unpricedCapMessage } from "../../run/pricing.js";
|
|
15
|
+
import { actorOf, capsOf } from "../../study/study-fields.js";
|
|
15
16
|
/** The registered descriptor for a planned actor; planSharedWorldStudy checked the registry. */
|
|
16
17
|
export function sharedWorldDescriptorOf(actorType) {
|
|
17
18
|
const descriptor = actorRegistry[actorType];
|
|
@@ -38,7 +39,7 @@ export function planSharedWorldStudy(config, input) {
|
|
|
38
39
|
const tasksReason = taskProtocolValidationReason(config, false);
|
|
39
40
|
if (tasksReason)
|
|
40
41
|
return refuse("HUMANISH_STUDY_TASKS_UNSUPPORTED", tasksReason);
|
|
41
|
-
const actorType = config
|
|
42
|
+
const actorType = actorOf(config)?.type ?? "";
|
|
42
43
|
const descriptor = actorRegistry[actorType];
|
|
43
44
|
if (!descriptor || !isCuaActorDescriptor(descriptor))
|
|
44
45
|
return refuse("HUMANISH_SHARED_WORLD_ACTOR_UNSUPPORTED", `actor.type "${actorType}" is not a registered computer-use actor.`);
|
|
@@ -59,11 +60,11 @@ export function planSharedWorldStudy(config, input) {
|
|
|
59
60
|
: concurrentSharedWorldValidationReason(config));
|
|
60
61
|
if (invalidReason)
|
|
61
62
|
return refuse(invalid, invalidReason, actor);
|
|
62
|
-
if (config
|
|
63
|
+
if (actorOf(config)?.maxOutputTokens !== undefined && input.hasRunSession === true)
|
|
63
64
|
return refuse(invalid, "maxOutputTokens cannot be enforced by a custom runSession.", actor);
|
|
64
|
-
const caps = config
|
|
65
|
+
const caps = capsOf(config, "shared-world");
|
|
65
66
|
if (!input.dryRun && (caps?.maxUsd !== undefined || caps?.maxTotalUsd !== undefined)) {
|
|
66
|
-
const model = (config
|
|
67
|
+
const model = (actorOf(config)?.model ?? DEFAULT_OPENAI_CU_MODEL).trim().toLowerCase();
|
|
67
68
|
if (!MODEL_RATES[model])
|
|
68
69
|
return refuse("HUMANISH_SHARED_WORLD_UNPRICED_CAP", unpricedCapMessage(model), actor);
|
|
69
70
|
}
|
|
@@ -106,7 +107,7 @@ export function planSharedWorldStudy(config, input) {
|
|
|
106
107
|
? {}
|
|
107
108
|
: { sessionTimeoutMs: config.execution.timeoutMs }),
|
|
108
109
|
brain,
|
|
109
|
-
caps:
|
|
110
|
+
caps: planCaps(config, "shared-world"),
|
|
110
111
|
requirements: base.dryRun
|
|
111
112
|
? []
|
|
112
113
|
: [
|
|
@@ -1,21 +1,15 @@
|
|
|
1
|
+
import { type RefusedStudy } from "../../run/route-shell.js";
|
|
1
2
|
import { type SharedWorldRefusal } from "./plan.js";
|
|
2
3
|
import type { SharedWorldPlan } from "../../study/plan-types.js";
|
|
3
4
|
import type { AdmittedPlan } from "../../run-study.js";
|
|
4
5
|
import type { StudyConfig } from "../../study/types.js";
|
|
5
|
-
import { type ConcurrentSharedWorldStudyResult, type SharedWorldRunInput
|
|
6
|
-
/**
|
|
7
|
-
* The library entry for a shared-world study. It plans the config with planSharedWorldStudy and runs
|
|
8
|
-
* the plan with runSharedWorldPlan, whose run scope and withTransientCommsSecrets wrapper cover the
|
|
9
|
-
* run and its analysis.
|
|
10
|
-
*/
|
|
11
|
-
export declare function runConcurrentSharedWorld(options: RunConcurrentSharedWorldStudyOptions): Promise<ConcurrentSharedWorldStudyResult>;
|
|
6
|
+
import { type ConcurrentSharedWorldStudyResult, type SharedWorldRunInput } from "./types.js";
|
|
12
7
|
/** A refused shared-world study's result: the route's envelope, and a refusal's analysis record. */
|
|
13
|
-
export declare function sharedWorldStudyRefusal(options:
|
|
8
|
+
export declare function sharedWorldStudyRefusal(options: SharedWorldRunInput & RefusedStudy, refusal: SharedWorldRefusal): Promise<ConcurrentSharedWorldStudyResult>;
|
|
14
9
|
/**
|
|
15
10
|
* runStudyWith's step for a shared-world plan. It runs a live plan's local checks (the keys, a local
|
|
16
11
|
* agent's sign-in and the subject env) before any run scope opens, so the CLI can present their refusal before it loads a
|
|
17
|
-
* declared scorer, and returns the run that continues from them with that scorer.
|
|
12
|
+
* declared scorer, and returns the run that continues from them with that scorer. The run and its
|
|
13
|
+
* analysis share one scope for the email secrets it registers.
|
|
18
14
|
*/
|
|
19
15
|
export declare function admitSharedWorldPlan(plan: SharedWorldPlan, input: SharedWorldRunInput, config: StudyConfig): Promise<AdmittedPlan<"shared-world">>;
|
|
20
|
-
/** Run a shared-world plan: its local checks, then the run. */
|
|
21
|
-
export declare function runSharedWorldPlan(plan: SharedWorldPlan, input: SharedWorldRunInput, config: StudyConfig): Promise<ConcurrentSharedWorldStudyResult>;
|
|
@@ -34,15 +34,13 @@
|
|
|
34
34
|
// gate; humanish cannot tell synthetic from real data, so it makes no claim about real data.
|
|
35
35
|
import path from "node:path";
|
|
36
36
|
import { missingKeys, missingSubjectEnv } from "../../study/requirements.js";
|
|
37
|
-
import { completeAutomaticAnalysis } from "../../analysis/automatic-completion.js";
|
|
38
|
-
import { resolveAutomaticAnalysis } from "../../analysis/automatic-config.js";
|
|
39
37
|
import { scrubLiterals } from "../../evidence/redaction.js";
|
|
40
38
|
import { describeMissingKeys } from "../../keys/key-resolution.js";
|
|
41
|
-
import {
|
|
42
|
-
import {
|
|
39
|
+
import {} from "../../run/run.js";
|
|
40
|
+
import { admitRoute, completeRefusalAnalysis, } from "../../run/route-shell.js";
|
|
43
41
|
import { makeCuaRunBudget } from "../computer-use/participant-model.js";
|
|
44
42
|
import { runExternalPublicPlane } from "./external-public.js";
|
|
45
|
-
import {
|
|
43
|
+
import { sharedWorldDescriptorOf } from "./plan.js";
|
|
46
44
|
import { localAgentRefusal } from "../../actors/local-agent/readiness.js";
|
|
47
45
|
import { runProvisionedPlane } from "./provisioned.js";
|
|
48
46
|
import { concurrentStudyFailure, finishConcurrentRun } from "./result.js";
|
|
@@ -50,7 +48,7 @@ import { prepareConcurrentRun } from "./setup.js";
|
|
|
50
48
|
import { browserRouteScorer } from "../../study/adapter-scorer-loader.js";
|
|
51
49
|
import { withLateScorer } from "../../study/route-inputs.js";
|
|
52
50
|
import {} from "./types.js";
|
|
53
|
-
import {
|
|
51
|
+
import { actorOf, participantList } from "../../study/study-fields.js";
|
|
54
52
|
/** The shared-world code for each local-agent refusal, kind for kind with computer-use. */
|
|
55
53
|
const LOCAL_AGENT_REFUSAL_CODES = {
|
|
56
54
|
"agent-missing": "HUMANISH_SHARED_WORLD_AGENT_MISSING",
|
|
@@ -58,30 +56,14 @@ const LOCAL_AGENT_REFUSAL_CODES = {
|
|
|
58
56
|
unsupported: "HUMANISH_SHARED_WORLD_ACTOR_UNSUPPORTED",
|
|
59
57
|
"unpriced-cap": "HUMANISH_SHARED_WORLD_UNPRICED_CAP",
|
|
60
58
|
};
|
|
61
|
-
/**
|
|
62
|
-
* The library entry for a shared-world study. It plans the config with planSharedWorldStudy and runs
|
|
63
|
-
* the plan with runSharedWorldPlan, whose run scope and withTransientCommsSecrets wrapper cover the
|
|
64
|
-
* run and its analysis.
|
|
65
|
-
*/
|
|
66
|
-
export async function runConcurrentSharedWorld(options) {
|
|
67
|
-
const { config, dryRun, ...input } = options;
|
|
68
|
-
// planSharedWorldStudy makes every configuration refusal, in the order this route always has.
|
|
69
|
-
const planned = planSharedWorldStudy(config, {
|
|
70
|
-
dryRun,
|
|
71
|
-
hasRunSession: input.deps?.runSession !== undefined,
|
|
72
|
-
});
|
|
73
|
-
if (planned.ok)
|
|
74
|
-
return runSharedWorldPlan(planned.plan, input, config);
|
|
75
|
-
return sharedWorldStudyRefusal(options, planned.refusal);
|
|
76
|
-
}
|
|
77
59
|
/** A refused shared-world study's result: the route's envelope, and a refusal's analysis record. */
|
|
78
60
|
export function sharedWorldStudyRefusal(options, refusal) {
|
|
79
61
|
const { config, dryRun } = options;
|
|
80
|
-
const declared =
|
|
62
|
+
const declared = participantList(config) ?? [];
|
|
81
63
|
const fail = concurrentStudyFailure({
|
|
82
64
|
cwd: path.resolve(options.cwd),
|
|
83
65
|
studyId: config.id,
|
|
84
|
-
actor: config
|
|
66
|
+
actor: actorOf(config)?.type ?? "",
|
|
85
67
|
participantCount: declared.length,
|
|
86
68
|
// The parser fills concurrency for multi-participant studies, so this fallback serves only
|
|
87
69
|
// library callers: every declared participant runs at once unless the author declared a cap.
|
|
@@ -89,42 +71,38 @@ export function sharedWorldStudyRefusal(options, refusal) {
|
|
|
89
71
|
dryRun,
|
|
90
72
|
runId: options.runId,
|
|
91
73
|
});
|
|
92
|
-
|
|
93
|
-
const analysis = resolveAutomaticAnalysis(config.review?.analysis);
|
|
94
|
-
return completeAutomaticAnalysis(fail(refusal.code, refusal.message, refusal.actor), undefined, analysis.ok ? analysis.config : undefined, options, { trigger: config.review?.analysis === undefined ? "default" : "explicit" });
|
|
74
|
+
return completeRefusalAnalysis(fail(refusal.code, refusal.message, refusal.actor), config, options);
|
|
95
75
|
}
|
|
96
76
|
/**
|
|
97
77
|
* runStudyWith's step for a shared-world plan. It runs a live plan's local checks (the keys, a local
|
|
98
78
|
* agent's sign-in and the subject env) before any run scope opens, so the CLI can present their refusal before it loads a
|
|
99
|
-
* declared scorer, and returns the run that continues from them with that scorer.
|
|
79
|
+
* declared scorer, and returns the run that continues from them with that scorer. The run and its
|
|
80
|
+
* analysis share one scope for the email secrets it registers.
|
|
100
81
|
*/
|
|
101
|
-
export
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
return { route: "shared-world", result };
|
|
112
|
-
}
|
|
113
|
-
/** Run a shared-world plan: its local checks, then the run. */
|
|
114
|
-
export async function runSharedWorldPlan(plan, input, config) {
|
|
115
|
-
const refused = await admitSharedWorldRun(plan, input);
|
|
116
|
-
return refused ?? runAdmittedSharedWorldRun(plan, input, config);
|
|
82
|
+
export function admitSharedWorldPlan(plan, input, config) {
|
|
83
|
+
return admitRoute({
|
|
84
|
+
route: "shared-world",
|
|
85
|
+
analysis: plan.analysis,
|
|
86
|
+
input,
|
|
87
|
+
admit: () => admitSharedWorldRun(plan, input),
|
|
88
|
+
withScorer: (base, scorer) => withLateScorer(base, scorer, browserRouteScorer),
|
|
89
|
+
runInScope: (_admitted, running, scope) => runPlanInScope(plan, running, config, scope),
|
|
90
|
+
commsSecrets: true,
|
|
91
|
+
});
|
|
117
92
|
}
|
|
118
93
|
/**
|
|
119
94
|
* A live plan's local checks, made outside any run scope: the keys, a local agent's sign-in, then
|
|
120
|
-
* the subject env.
|
|
121
|
-
* record of a run that never started.
|
|
95
|
+
* the subject env.
|
|
122
96
|
*/
|
|
123
97
|
async function admitSharedWorldRun(plan, input) {
|
|
98
|
+
const admitted = { ok: true, admitted: undefined };
|
|
124
99
|
if (plan.dryRun)
|
|
125
|
-
return
|
|
100
|
+
return admitted;
|
|
126
101
|
const env = input.env ?? process.env;
|
|
127
|
-
const fail = (code, message) =>
|
|
102
|
+
const fail = (code, message) => ({
|
|
103
|
+
ok: false,
|
|
104
|
+
result: sharedWorldFailure(plan, input)(code, message, sharedWorldDescriptorOf(plan.actor).id),
|
|
105
|
+
});
|
|
128
106
|
// The plan lists OPENAI_API_KEY for an openai brain's participants and the external-public
|
|
129
107
|
// plane's lobby-code reader; a local-agent brain's participants run on the operator's signed-in
|
|
130
108
|
// agent instead.
|
|
@@ -143,24 +121,7 @@ async function admitSharedWorldRun(plan, input) {
|
|
|
143
121
|
if (unsetSubjectEnv.length > 0) {
|
|
144
122
|
return fail("HUMANISH_SHARED_WORLD_SUBJECT_ENV_MISSING", `subject.env declares ${unsetSubjectEnv.join(", ")} but the environment does not provide ${unsetSubjectEnv.length === 1 ? "it" : "them"} (pass via --dotenv; values are never persisted).`);
|
|
145
123
|
}
|
|
146
|
-
return
|
|
147
|
-
}
|
|
148
|
-
/**
|
|
149
|
-
* Runs an admitted plan in its own run scope, then its automatic analysis. The
|
|
150
|
-
* withTransientCommsSecrets wrapper scopes any email secret the run registers to this run and its
|
|
151
|
-
* analysis.
|
|
152
|
-
*/
|
|
153
|
-
function runAdmittedSharedWorldRun(plan, input, config) {
|
|
154
|
-
return withTransientCommsSecrets(async () => {
|
|
155
|
-
const { result, finished } = await runScope((scope) => runPlanInScope(plan, input, config, scope));
|
|
156
|
-
return completeSharedWorldAnalysis(plan, input, result, finished);
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
function completeSharedWorldAnalysis(plan, input, result, finished) {
|
|
160
|
-
return completeAutomaticAnalysis(result, finished, plan.analysis?.config, input, {
|
|
161
|
-
...(plan.analysis === undefined ? {} : { trigger: plan.analysis.trigger }),
|
|
162
|
-
preferLargerOutput: plan.analysis?.preferLargerOutput === true,
|
|
163
|
-
});
|
|
124
|
+
return admitted;
|
|
164
125
|
}
|
|
165
126
|
/** The route's envelope for a run that stops before its bundle. */
|
|
166
127
|
function sharedWorldFailure(plan, input) {
|
|
@@ -24,13 +24,11 @@ export declare const CONCURRENT_SHARED_WORLD_PROVIDER_METADATA: {
|
|
|
24
24
|
readonly tool: "humanish";
|
|
25
25
|
};
|
|
26
26
|
export declare const CONCURRENT_ATTRIBUTION_LIMITS: readonly ["concurrent", "best-effort-causal-attribution", "non-deterministic-shared-state", "window-and-snapshot-granularity", "contention-observed-not-proven-safe", "state-change-not-isolated-to-actors"];
|
|
27
|
-
|
|
27
|
+
/** What a shared-world run takes besides its plan. The plan carries the config, dry run and study. */
|
|
28
|
+
export interface SharedWorldRunInput {
|
|
28
29
|
/** Cancels post-run analysis only. */
|
|
29
30
|
analysisSignal?: AbortSignal;
|
|
30
31
|
cwd: string;
|
|
31
|
-
config: StudyConfig;
|
|
32
|
-
/** Resolved upstream (scenario.mode + CLI override); defaults safe (dry-run). */
|
|
33
|
-
dryRun: boolean;
|
|
34
32
|
open?: boolean;
|
|
35
33
|
runId?: string;
|
|
36
34
|
onObserverReady?: (observer: ObserverResult & {
|
|
@@ -56,8 +54,6 @@ export interface RunConcurrentSharedWorldStudyOptions {
|
|
|
56
54
|
* core-stamped onto the bundle as evidence. Absent for library callers. */
|
|
57
55
|
scorerProvenance?: RunScorerProvenance;
|
|
58
56
|
}
|
|
59
|
-
/** What a shared-world run takes besides its plan. The plan carries the config, dry run and study. */
|
|
60
|
-
export type SharedWorldRunInput = Omit<RunConcurrentSharedWorldStudyOptions, "config" | "dryRun">;
|
|
61
57
|
export type ConcurrentSharedWorldStudyErrorCode = "HUMANISH_STUDY_ANALYSIS_INVALID" | "HUMANISH_STUDY_TASKS_UNSUPPORTED" | "HUMANISH_STUDY_OPTION_UNSUPPORTED" | "HUMANISH_STUDY_V2_UNSUPPORTED" | "HUMANISH_SHARED_WORLD_FAILED" | "HUMANISH_SHARED_WORLD_ACTOR_UNSUPPORTED" | "HUMANISH_SHARED_WORLD_INVALID" | "HUMANISH_SHARED_WORLD_KEYS_MISSING"
|
|
62
58
|
/** A local-agent brain's CLI is not on `PATH`. */
|
|
63
59
|
| "HUMANISH_SHARED_WORLD_AGENT_MISSING"
|
|
@@ -13,6 +13,7 @@ import { NODE_BOOTSTRAP_TIMEOUT_MS } from "../../subject/node-bootstrap.js";
|
|
|
13
13
|
import { terminalSandboxTimeoutMs } from "./lifetime.js";
|
|
14
14
|
import { isExactRuntimeVersion, TERMINAL_RUNTIME_VERSION_TIMEOUT_MS } from "./runtime.js";
|
|
15
15
|
import { PRODUCT_SETUP_TIMEOUT_MS, TERMINAL_SANDBOX_TIMEOUT_BUFFER_MS, } from "./types.js";
|
|
16
|
+
import { actorOf, capsOf } from "../../study/study-fields.js";
|
|
16
17
|
/**
|
|
17
18
|
* Plan a terminal-product study. It is called for any config handed to the terminal runner, not
|
|
18
19
|
* only one routeOf sends here, so a config for another route gets this route's refusal.
|
|
@@ -40,12 +41,12 @@ export function planTerminalStudy(config, input) {
|
|
|
40
41
|
const tasksReason = taskProtocolValidationReason(config, false);
|
|
41
42
|
if (tasksReason)
|
|
42
43
|
return refuse("HUMANISH_STUDY_TASKS_UNSUPPORTED", tasksReason);
|
|
43
|
-
const actorType = config
|
|
44
|
+
const actorType = actorOf(config)?.type ?? "";
|
|
44
45
|
const descriptor = actorRegistry[actorType];
|
|
45
46
|
if (!descriptor || !isTerminalActorDescriptor(descriptor))
|
|
46
47
|
return refuse("HUMANISH_TERMINAL_ACTOR_UNSUPPORTED", `actor.type "${actorType}" is not a registered terminal actor.`);
|
|
47
48
|
const runtimeVersion = config.execution?.runtime?.version;
|
|
48
|
-
const actor = config
|
|
49
|
+
const actor = actorOf(config);
|
|
49
50
|
if ((config.execution?.runtime !== undefined && !isExactRuntimeVersion(runtimeVersion)) ||
|
|
50
51
|
(actor?.model !== undefined &&
|
|
51
52
|
(typeof actor.model !== "string" || actor.model.trim().length === 0)) ||
|
|
@@ -83,7 +84,7 @@ export function planTerminalStudy(config, input) {
|
|
|
83
84
|
...(egressAllow === undefined ? {} : { egressAllow }),
|
|
84
85
|
...(stdin === undefined ? {} : { stdin }),
|
|
85
86
|
};
|
|
86
|
-
const caps = config
|
|
87
|
+
const caps = capsOf(config, "terminal");
|
|
87
88
|
if (input.dryRun)
|
|
88
89
|
return { ok: true, plan: { ...shared, dryRun: true, ...(caps ? { caps } : {}) } };
|
|
89
90
|
// The live route injects the runtime key into one command only, and only a registered actor
|
|
@@ -1,20 +1,10 @@
|
|
|
1
|
+
import { type RefusedStudy } from "../../run/route-shell.js";
|
|
1
2
|
import { type TerminalRefusal } from "./plan.js";
|
|
2
3
|
import type { TerminalPlan } from "../../study/plan-types.js";
|
|
3
4
|
import type { AdmittedPlan } from "../../run-study.js";
|
|
4
|
-
import { type
|
|
5
|
-
/**
|
|
6
|
-
* The config-taking entry point. It plans, returns a refusal with the same envelope and analysis
|
|
7
|
-
* record the route has always returned, and otherwise runs the plan.
|
|
8
|
-
*/
|
|
9
|
-
export declare function runTerminalProductStudy(options: RunTerminalProductStudyOptions): Promise<TerminalProductStudyResult>;
|
|
5
|
+
import { type TerminalProductStudyResult, type TerminalRunInput } from "./types.js";
|
|
10
6
|
/** A refused terminal study's result: the route's envelope, and the analysis record a refusal gets. */
|
|
11
|
-
export declare function terminalStudyRefusal(options:
|
|
12
|
-
/**
|
|
13
|
-
* Run a terminal plan. The run scope gives a direct library caller the same run lifetime the CLI
|
|
14
|
-
* gets: whichever of its fail-closed exits the run takes, the run it started is closed, and only a
|
|
15
|
-
* run that published its final bundle reaches automatic analysis.
|
|
16
|
-
*/
|
|
17
|
-
export declare function runTerminalPlan(plan: TerminalPlan, input: TerminalRunInput): Promise<TerminalProductStudyResult>;
|
|
7
|
+
export declare function terminalStudyRefusal(options: TerminalRunInput & RefusedStudy, refusal: TerminalRefusal): Promise<TerminalProductStudyResult>;
|
|
18
8
|
/**
|
|
19
9
|
* runStudyWith's step for a terminal plan. It runs a live plan's local checks (checkLiveTerminalMachine)
|
|
20
10
|
* before any run scope opens, so the CLI can present their refusal before it loads a declared
|
|
@@ -44,31 +44,17 @@
|
|
|
44
44
|
// humanish never calls Sandbox.list to prove cleanup, so a shared operator key never reaches a
|
|
45
45
|
// sandbox it did not create. A live run that cannot prove teardown fails closed.
|
|
46
46
|
// Enforced in sandbox.ts.
|
|
47
|
-
import { resolveAutomaticAnalysis } from "../../analysis/automatic-config.js";
|
|
48
|
-
import { completeAutomaticAnalysis } from "../../analysis/automatic-completion.js";
|
|
49
47
|
import path from "node:path";
|
|
50
|
-
import {
|
|
51
|
-
import {
|
|
48
|
+
import {} from "../../run/run.js";
|
|
49
|
+
import { admitRoute, completeRefusalAnalysis, } from "../../run/route-shell.js";
|
|
50
|
+
import {} from "./plan.js";
|
|
52
51
|
import { runDryTerminalStudy } from "./dry-run.js";
|
|
53
52
|
import { checkLiveTerminalMachine, runLiveTerminalSession } from "./session.js";
|
|
54
53
|
import { terminalRouteScorer } from "../../study/adapter-scorer-loader.js";
|
|
55
54
|
import { withLateScorer } from "../../study/route-inputs.js";
|
|
56
55
|
import {} from "./types.js";
|
|
57
56
|
import { studyResultIdentity } from "../../run/study-result.js";
|
|
58
|
-
|
|
59
|
-
* The config-taking entry point. It plans, returns a refusal with the same envelope and analysis
|
|
60
|
-
* record the route has always returned, and otherwise runs the plan.
|
|
61
|
-
*/
|
|
62
|
-
export async function runTerminalProductStudy(options) {
|
|
63
|
-
const { config, dryRun, ...input } = options;
|
|
64
|
-
const planned = planTerminalStudy(config, {
|
|
65
|
-
dryRun,
|
|
66
|
-
hasCostProbe: input.deps?.costProbe !== undefined,
|
|
67
|
-
});
|
|
68
|
-
if (planned.ok)
|
|
69
|
-
return runTerminalPlan(planned.plan, input);
|
|
70
|
-
return terminalStudyRefusal(options, planned.refusal);
|
|
71
|
-
}
|
|
57
|
+
import { actorOf } from "../../study/study-fields.js";
|
|
72
58
|
/** A refused terminal study's result: the route's envelope, and the analysis record a refusal gets. */
|
|
73
59
|
export function terminalStudyRefusal(options, refusal) {
|
|
74
60
|
const { config, dryRun } = options;
|
|
@@ -76,67 +62,42 @@ export function terminalStudyRefusal(options, refusal) {
|
|
|
76
62
|
...studyResultIdentity("terminal", config.id),
|
|
77
63
|
ok: false,
|
|
78
64
|
cwd: path.resolve(options.cwd),
|
|
79
|
-
actor: refusal.actor ?? config
|
|
65
|
+
actor: refusal.actor ?? actorOf(config)?.type ?? "",
|
|
80
66
|
product: config.subject.product?.name ?? "",
|
|
81
67
|
dryRun,
|
|
82
68
|
runId: options.runId ?? "not-created",
|
|
83
69
|
warnings: [],
|
|
84
70
|
error: { code: refusal.code, message: refusal.message },
|
|
85
71
|
};
|
|
86
|
-
|
|
87
|
-
const analysis = resolveAutomaticAnalysis(config.review?.analysis);
|
|
88
|
-
return completeAutomaticAnalysis(refused, undefined, analysis.ok ? analysis.config : undefined, options, { trigger: config.review?.analysis === undefined ? "default" : "explicit" });
|
|
89
|
-
}
|
|
90
|
-
/**
|
|
91
|
-
* Run a terminal plan. The run scope gives a direct library caller the same run lifetime the CLI
|
|
92
|
-
* gets: whichever of its fail-closed exits the run takes, the run it started is closed, and only a
|
|
93
|
-
* run that published its final bundle reaches automatic analysis.
|
|
94
|
-
*/
|
|
95
|
-
export async function runTerminalPlan(plan, input) {
|
|
96
|
-
const admission = await admitTerminalRun(plan, input);
|
|
97
|
-
return admission.ok ? runAdmittedTerminalRun(admission.admitted, input) : admission.result;
|
|
72
|
+
return completeRefusalAnalysis(refused, config, options);
|
|
98
73
|
}
|
|
99
74
|
/**
|
|
100
75
|
* runStudyWith's step for a terminal plan. It runs a live plan's local checks (checkLiveTerminalMachine)
|
|
101
76
|
* before any run scope opens, so the CLI can present their refusal before it loads a declared
|
|
102
77
|
* scorer, and returns the run that continues from them with that scorer.
|
|
103
78
|
*/
|
|
104
|
-
export
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
}
|
|
113
|
-
function terminalOutcome(result) {
|
|
114
|
-
return { route: "terminal", result };
|
|
79
|
+
export function admitTerminalPlan(plan, input) {
|
|
80
|
+
return admitRoute({
|
|
81
|
+
route: "terminal",
|
|
82
|
+
analysis: plan.analysis,
|
|
83
|
+
input,
|
|
84
|
+
admit: () => admitTerminalRun(plan, input),
|
|
85
|
+
withScorer: (base, scorer) => withLateScorer(base, scorer, terminalRouteScorer),
|
|
86
|
+
runInScope: runTerminalPlanInScope,
|
|
87
|
+
});
|
|
115
88
|
}
|
|
116
|
-
/**
|
|
117
|
-
|
|
118
|
-
* returns for it, with the analysis record of a run that never started.
|
|
119
|
-
*/
|
|
120
|
-
async function admitTerminalRun(plan, input) {
|
|
89
|
+
/** A live plan's local checks, made outside any run scope. */
|
|
90
|
+
function admitTerminalRun(plan, input) {
|
|
121
91
|
const warnings = [];
|
|
122
92
|
if (plan.dryRun)
|
|
123
93
|
return { ok: true, admitted: { plan, warnings } };
|
|
124
94
|
const checked = checkLiveTerminalMachine(plan, input, warnings);
|
|
125
95
|
if (checked.ok)
|
|
126
96
|
return { ok: true, admitted: { plan, warnings, runtimeEnv: checked.runtimeEnv } };
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
async function runAdmittedTerminalRun(admitted, input) {
|
|
132
|
-
const { result, finished } = await runScope((scope) => runTerminalPlanInScope(admitted, input, scope));
|
|
133
|
-
return completeTerminalAnalysis(admitted.plan, input, result, finished);
|
|
134
|
-
}
|
|
135
|
-
function completeTerminalAnalysis(plan, input, result, finished) {
|
|
136
|
-
return completeAutomaticAnalysis(result, finished, plan.analysis?.config, input, {
|
|
137
|
-
...(plan.analysis === undefined ? {} : { trigger: plan.analysis.trigger }),
|
|
138
|
-
preferLargerOutput: plan.analysis?.preferLargerOutput === true,
|
|
139
|
-
});
|
|
97
|
+
return {
|
|
98
|
+
ok: false,
|
|
99
|
+
result: terminalFailure(plan, input, warnings)(checked.code, checked.message),
|
|
100
|
+
};
|
|
140
101
|
}
|
|
141
102
|
/** The route's envelope for a run that stops before its bundle. */
|
|
142
103
|
function terminalFailure(plan, input, warnings) {
|
|
@@ -13,9 +13,8 @@ export declare function checkLiveTerminalMachine(plan: LiveTerminalPlan, input:
|
|
|
13
13
|
readonly message: string;
|
|
14
14
|
};
|
|
15
15
|
/**
|
|
16
|
-
* The live in-sandbox agent session orchestrator
|
|
17
|
-
*
|
|
18
|
-
* precondition miss. Persists the substrate-lifecycle/command-log/interventions/cleanup ledgers,
|
|
16
|
+
* The live in-sandbox agent session orchestrator. Enforces the 8-point safety contract by
|
|
17
|
+
* construction; fails closed before any sandbox/key/spend on any precondition miss. Persists the substrate-lifecycle/command-log/interventions/cleanup ledgers,
|
|
19
18
|
* the redacted terminal event stream + normalized transcript, the agent report, and the
|
|
20
19
|
* provider-neutral actor trace; tears the sandbox down in a finally and proves the teardown.
|
|
21
20
|
*/
|
|
@@ -38,9 +38,8 @@ export function checkLiveTerminalMachine(plan, input, warnings) {
|
|
|
38
38
|
return { ok: true, runtimeEnv };
|
|
39
39
|
}
|
|
40
40
|
/**
|
|
41
|
-
* The live in-sandbox agent session orchestrator
|
|
42
|
-
*
|
|
43
|
-
* precondition miss. Persists the substrate-lifecycle/command-log/interventions/cleanup ledgers,
|
|
41
|
+
* The live in-sandbox agent session orchestrator. Enforces the 8-point safety contract by
|
|
42
|
+
* construction; fails closed before any sandbox/key/spend on any precondition miss. Persists the substrate-lifecycle/command-log/interventions/cleanup ledgers,
|
|
44
43
|
* the redacted terminal event stream + normalized transcript, the agent report, and the
|
|
45
44
|
* provider-neutral actor trace; tears the sandbox down in a finally and proves the teardown.
|
|
46
45
|
*/
|
|
@@ -112,6 +111,7 @@ export async function runLiveTerminalSession(args) {
|
|
|
112
111
|
if ((await session.bootstrap()) &&
|
|
113
112
|
(await session.verifyRuntimeVersion()) &&
|
|
114
113
|
(await session.prepareProduct())) {
|
|
114
|
+
run.participantStarted();
|
|
115
115
|
await session.execCodex();
|
|
116
116
|
}
|
|
117
117
|
}
|