humanish 0.115.0 → 0.116.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/CHANGELOG.md +22 -0
- package/README.md +7 -6
- package/TELEMETRY.md +6 -0
- package/dist/actors/codex/app-server-ui.js +11 -4
- package/dist/actors/computer-use/loop/debrief.js +61 -27
- package/dist/actors/scripted-browser/steps.js +6 -5
- package/dist/analysis/analysis-limits.d.ts +35 -0
- package/dist/analysis/analysis-limits.js +41 -0
- package/dist/analysis/validation.js +14 -21
- package/dist/cli/commands/analyze.js +2 -1
- package/dist/cli/commands/notes.js +2 -1
- package/dist/cli/commands/run-signals.js +5 -1
- package/dist/cli/commands/runs.js +2 -1
- package/dist/cli/commands/setup.js +3 -3
- package/dist/cli/commands/study-format.d.ts +5 -2
- package/dist/cli/commands/study-format.js +29 -9
- package/dist/cli/commands/study-route-computer-use.js +2 -2
- package/dist/cli/commands/study-route-scripted.js +1 -1
- package/dist/cli/commands/tui.js +59 -17
- package/dist/cli/doctor.js +9 -2
- package/dist/cli/findings-text.d.ts +5 -0
- package/dist/cli/findings-text.js +169 -0
- package/dist/cli/findings.d.ts +0 -4
- package/dist/cli/findings.js +5 -167
- package/dist/cli/io.js +6 -1
- package/dist/cli/update-check.js +4 -1
- package/dist/comms/connections.js +4 -3
- package/dist/comms/setup.js +18 -12
- package/dist/evidence/redaction.js +9 -1
- package/dist/evidence/secret-scrub.d.ts +15 -5
- package/dist/evidence/secret-scrub.js +67 -9
- package/dist/feedback/draft.js +1 -1
- package/dist/feedback/export-bundle.js +18 -14
- package/dist/feedback/feedback.js +25 -7
- package/dist/guest/desktop-keys.js +59 -5
- package/dist/keys/key-resolution.d.ts +9 -0
- package/dist/keys/key-resolution.js +60 -48
- package/dist/keys/key-status.d.ts +2 -0
- package/dist/keys/key-status.js +9 -16
- package/dist/observer/pinned-files.js +1 -1
- package/dist/observer/render.js +3 -2
- package/dist/observer-app.html +7 -7
- package/dist/routes/computer-use/bundle-parts.d.ts +4 -4
- package/dist/routes/computer-use/bundle-parts.js +2 -2
- package/dist/routes/computer-use/bundle.d.ts +4 -5
- package/dist/routes/computer-use/bundle.js +1 -3
- package/dist/routes/computer-use/fanout-records.js +10 -11
- package/dist/routes/computer-use/live-phase.d.ts +1 -1
- package/dist/routes/computer-use/live-phase.js +0 -1
- package/dist/routes/computer-use/participant-execution.d.ts +3 -2
- package/dist/routes/computer-use/participant-runs.d.ts +6 -2
- package/dist/routes/computer-use/participant-runs.js +9 -5
- package/dist/routes/computer-use/plan.d.ts +3 -0
- package/dist/routes/computer-use/plan.js +14 -11
- package/dist/routes/computer-use/rerun-selection.js +2 -2
- package/dist/routes/computer-use/result.js +3 -6
- package/dist/routes/computer-use/setup.d.ts +4 -6
- package/dist/routes/computer-use/setup.js +2 -6
- package/dist/routes/computer-use/single-bundle.d.ts +4 -5
- package/dist/routes/computer-use/single-bundle.js +22 -25
- package/dist/routes/computer-use/subject-projection.d.ts +4 -8
- package/dist/routes/computer-use/subject-projection.js +9 -31
- package/dist/routes/computer-use/types.d.ts +4 -41
- package/dist/routes/scripted/scenario.js +28 -12
- package/dist/routes/scripted/session-result.js +6 -3
- package/dist/routes/shared-world/bundle-records.js +2 -8
- package/dist/routes/shared-world/participant-specs.d.ts +0 -2
- package/dist/routes/shared-world/participant-specs.js +1 -20
- package/dist/routes/shared-world/plan.d.ts +3 -0
- package/dist/routes/shared-world/plan.js +23 -3
- package/dist/routes/shared-world/setup.js +2 -2
- package/dist/routes/terminal/ledger.d.ts +9 -9
- package/dist/routes/terminal/ledger.js +63 -40
- package/dist/routes/terminal/live-finish.js +7 -10
- package/dist/routes/terminal/plan.d.ts +3 -0
- package/dist/routes/terminal/plan.js +8 -5
- package/dist/routes/terminal/token-usage.d.ts +1 -2
- package/dist/routes/terminal/token-usage.js +4 -6
- package/dist/routes/terminal/types.d.ts +9 -1
- package/dist/run/bundle-shape.js +6 -1
- package/dist/run/bundle.d.ts +5 -3
- package/dist/run/contained-output.d.ts +53 -5
- package/dist/run/contained-output.js +141 -42
- package/dist/run/detail.d.ts +2 -1
- package/dist/run/detail.js +12 -7
- package/dist/run/escape-sequences.d.ts +11 -0
- package/dist/run/escape-sequences.js +93 -0
- package/dist/run/evidence-files.d.ts +8 -8
- package/dist/run/evidence-files.js +19 -23
- package/dist/run/locate.d.ts +32 -3
- package/dist/run/locate.js +45 -40
- package/dist/run/notes.d.ts +0 -8
- package/dist/run/notes.js +5 -51
- package/dist/run/outcomes.d.ts +24 -0
- package/dist/run/outcomes.js +19 -0
- package/dist/run/paths.d.ts +2 -0
- package/dist/run/paths.js +5 -1
- package/dist/run/preflight-receipts.js +13 -8
- package/dist/run/project.js +7 -4
- package/dist/run/reclaim-outcomes.d.ts +8 -6
- package/dist/run/reclaim-outcomes.js +10 -6
- package/dist/run/reclaim.d.ts +5 -0
- package/dist/run/reclaim.js +43 -16
- package/dist/run/run-clock.d.ts +50 -0
- package/dist/run/run-clock.js +66 -0
- package/dist/run/run.js +5 -2
- package/dist/run/sandbox-ids.d.ts +7 -2
- package/dist/run/sandbox-ids.js +27 -11
- package/dist/run/secrets.d.ts +2 -1
- package/dist/run/secrets.js +18 -22
- package/dist/run/stored-runs.js +14 -7
- package/dist/run/transient-comms-secrets.js +6 -17
- package/dist/run-study.js +22 -13
- package/dist/study/adapter-scorer-loader.js +6 -4
- package/dist/study/discover.js +9 -6
- package/dist/study/init-paths.js +7 -5
- package/dist/study/persona-resolve.d.ts +2 -2
- package/dist/study/persona-resolve.js +9 -5
- package/dist/study/plan-types.d.ts +2 -2
- package/dist/study/plan.d.ts +5 -3
- package/dist/study/plan.js +18 -9
- package/dist/study/preflight-probes.js +11 -3
- package/dist/study/preflight.js +9 -5
- package/dist/study/summary.d.ts +8 -2
- package/dist/study/summary.js +20 -22
- package/dist/study/warnings.d.ts +19 -12
- package/dist/study/warnings.js +38 -17
- package/dist/substrates/e2b/connection.d.ts +12 -0
- package/dist/substrates/e2b/connection.js +35 -0
- package/dist/substrates/e2b/desktop-executor.d.ts +1 -3
- package/dist/substrates/e2b/desktop-executor.js +42 -9
- package/dist/substrates/e2b/lifetime.d.ts +24 -4
- package/dist/substrates/e2b/lifetime.js +41 -4
- package/dist/substrates/e2b/sandbox.d.ts +4 -3
- package/dist/substrates/e2b/sandbox.js +13 -18
- package/dist/substrates/e2b/sdk.d.ts +20 -9
- package/dist/substrates/local/capacity.d.ts +18 -2
- package/dist/substrates/local/capacity.js +21 -2
- package/dist/substrates/local/runtime-host.js +21 -14
- package/dist/substrates/local/runtime.js +3 -11
- package/dist/tui/contract.d.ts +30 -5
- package/dist/tui/contract.js +4 -1
- package/dist/tui-app.js +149 -147
- package/dist/verify/artifacts.d.ts +9 -2
- package/dist/verify/artifacts.js +37 -13
- package/dist/verify/liveness.js +19 -5
- package/dist/verify/verify.js +54 -27
- package/docs/architecture/guest-desktop.md +7 -2
- package/docs/architecture/state-driven-executor.md +4 -2
- package/docs/contracts/run-bundle.md +18 -10
- package/docs/contracts/schemas.md +27 -18
- package/docs/contracts/study-analysis.md +10 -1
- package/docs/product/automatic-analysis.md +7 -1
- package/package.json +2 -2
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { type RunProviderResource, type RunSubjectProvenance } from "../../run/bundle.js";
|
|
2
2
|
import { type ParticipantIds } from "../../run/participant-records.js";
|
|
3
|
-
import { type
|
|
3
|
+
import { type ParticipantRunOutcome } from "./types.js";
|
|
4
4
|
/** The human-readable state story appended to the provenance event (and review.md via it). */
|
|
5
5
|
export declare function describeSubjectState(state: RunSubjectProvenance["state"], dryRun: boolean): string;
|
|
6
|
-
/** Human-readable provenance line for the single-participant subject.provenance event
|
|
7
|
-
* claims "cloned/packed and served" only when it actually happened. */
|
|
8
|
-
export declare function subjectProvenanceMessage(provenance:
|
|
6
|
+
/** Human-readable provenance line for the single-participant subject.provenance event of a clone
|
|
7
|
+
* or local-tree subject: claims "cloned/packed and served" only when it actually happened. */
|
|
8
|
+
export declare function subjectProvenanceMessage(provenance: RunSubjectProvenance, publicAppUrl: string, dryRun: boolean, hasSession: boolean): string;
|
|
9
9
|
export declare function providerResourcesForOutcome(args: {
|
|
10
10
|
outcome: ParticipantRunOutcome | undefined;
|
|
11
11
|
createdAt: string;
|
|
@@ -24,8 +24,8 @@ export function describeSubjectState(state, dryRun) {
|
|
|
24
24
|
return "external-public (operator-declared, operator-owned public deployment; neither provisioned nor seeded)";
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
|
-
/** Human-readable provenance line for the single-participant subject.provenance event
|
|
28
|
-
* claims "cloned/packed and served" only when it actually happened. */
|
|
27
|
+
/** Human-readable provenance line for the single-participant subject.provenance event of a clone
|
|
28
|
+
* or local-tree subject: claims "cloned/packed and served" only when it actually happened. */
|
|
29
29
|
export function subjectProvenanceMessage(provenance, publicAppUrl, dryRun, hasSession) {
|
|
30
30
|
if (provenance.source === "clone") {
|
|
31
31
|
if (dryRun) {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { CuaActorDescriptor } from "../../actors/registry.js";
|
|
2
2
|
import type { ComputerUsePlan } from "../../study/plan-types.js";
|
|
3
|
-
import type { BundleRun, RunBundle, RunRerunLineage } from "../../run/bundle.js";
|
|
3
|
+
import type { BundleRun, RunBundle, RunRerunLineage, RunSubjectProvenance } from "../../run/bundle.js";
|
|
4
4
|
import { type Judgment } from "../../run/judge.js";
|
|
5
|
-
import type { CuaParticipantPlan, DesktopParticipantRun,
|
|
5
|
+
import type { CuaParticipantPlan, DesktopParticipantRun, ParticipantRunOutcome } from "./types.js";
|
|
6
6
|
/** What every bundle of one run shares, in progress or final. */
|
|
7
7
|
export interface CuaRunBundleBase {
|
|
8
8
|
/** The run every bundle of it belongs to. */
|
|
@@ -32,9 +32,8 @@ interface CuaRunBundleState {
|
|
|
32
32
|
judgment: Judgment;
|
|
33
33
|
dryRun: boolean;
|
|
34
34
|
outcomes: ParticipantRunOutcome[] | undefined;
|
|
35
|
-
subjects:
|
|
36
|
-
aggregateSubject:
|
|
37
|
-
subjectProvenance: CuaSubjectProvenanceArg | undefined;
|
|
35
|
+
subjects: RunSubjectProvenance[];
|
|
36
|
+
aggregateSubject: RunSubjectProvenance;
|
|
38
37
|
failFastReason?: string;
|
|
39
38
|
inProgress?: true;
|
|
40
39
|
}
|
|
@@ -117,9 +117,7 @@ function singleParticipantArgs(base, state) {
|
|
|
117
117
|
}),
|
|
118
118
|
source: base.source,
|
|
119
119
|
...(state.inProgress === undefined ? {} : { inProgress: state.inProgress }),
|
|
120
|
-
|
|
121
|
-
? {}
|
|
122
|
-
: { subjectProvenance: state.subjectProvenance }),
|
|
120
|
+
subject: state.aggregateSubject,
|
|
123
121
|
...(desktopTemplate === undefined ? {} : { desktopTemplate }),
|
|
124
122
|
...(outcome?.desktopBrowser === undefined ? {} : { desktopBrowser: outcome.desktopBrowser }),
|
|
125
123
|
providerResources: providerResourcesForOutcome({
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { participantAssignment } from "../../study/participant-assignment.js";
|
|
4
4
|
import { participantEvent, participantRecord, participantStream, } from "../../run/participant-records.js";
|
|
5
5
|
import { participantCaption } from "../../run/participant-caption.js";
|
|
6
|
-
import {
|
|
6
|
+
import { participantSummary } from "../../run/outcomes.js";
|
|
7
7
|
import { declaredScreenForRender } from "../../substrates/e2b/desktop-geometry.js";
|
|
8
8
|
import { describeSubjectState, phaseEventIdSuffix, publicSafeAppUrlLabel } from "./bundle-parts.js";
|
|
9
9
|
import { participantSubjectEnv } from "./types.js";
|
|
@@ -60,15 +60,12 @@ function fanoutParticipantRecord(args, spec, index, view) {
|
|
|
60
60
|
mode: "browser-sim",
|
|
61
61
|
progress: args.inProgress === true && outcome === undefined ? 20 : 100,
|
|
62
62
|
currentStep: reason,
|
|
63
|
-
summary:
|
|
64
|
-
|
|
65
|
-
:
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
: outcome?.sessionError !== undefined
|
|
70
|
-
? `${name} did not finish a session: ${outcome.sessionError}`
|
|
71
|
-
: `${name} would use ${publicTargetUrl}; no session ran.`,
|
|
63
|
+
summary: participantSummary(name, { name: "the app", target: publicTargetUrl }, {
|
|
64
|
+
trace: session?.trace,
|
|
65
|
+
skippedReason: outcome?.skippedReason,
|
|
66
|
+
sessionError: outcome?.sessionError,
|
|
67
|
+
inProgress: args.inProgress === true && outcome === undefined,
|
|
68
|
+
}),
|
|
72
69
|
startedAt: args.run.createdAt,
|
|
73
70
|
updatedAt: args.run.createdAt,
|
|
74
71
|
});
|
|
@@ -208,7 +205,9 @@ function fanoutSubjectEvents(ctx, spec, view) {
|
|
|
208
205
|
at: args.run.createdAt,
|
|
209
206
|
level: "info",
|
|
210
207
|
type: "cua-lab.subject.declared",
|
|
211
|
-
message:
|
|
208
|
+
message: subject.source === "desktop-cli"
|
|
209
|
+
? `Participant ${spec.planned.id}: subject product declared: ${subject.product}, used from a terminal window inside the participant's own desktop sandbox.`
|
|
210
|
+
: `Participant ${spec.planned.id}: subject app declared at ${publicTargetUrl} (loopback inside the participant's own desktop sandbox).`,
|
|
212
211
|
});
|
|
213
212
|
}
|
|
214
213
|
return events;
|
|
@@ -31,7 +31,7 @@ export declare function runStudyParticipants(setup: CuaRunSetup, participants: C
|
|
|
31
31
|
killed: boolean;
|
|
32
32
|
streamUrlPresent: boolean;
|
|
33
33
|
};
|
|
34
|
-
subject?: import("
|
|
34
|
+
subject?: import("../../run/bundle.js").RunSubjectProvenance;
|
|
35
35
|
plan?: import("./types.js").CuaParticipantPlan;
|
|
36
36
|
lanes?: import("./types.js").CuaParticipantResult[];
|
|
37
37
|
laneSummary?: import("./types.js").CuaParticipantSummary;
|
|
@@ -37,7 +37,6 @@ export async function runStudyParticipants(setup, participants) {
|
|
|
37
37
|
outcomes: undefined,
|
|
38
38
|
subjects: inProgress.subjects,
|
|
39
39
|
aggregateSubject: inProgress.aggregateSubject,
|
|
40
|
-
subjectProvenance: inProgress.provenance,
|
|
41
40
|
inProgress: true,
|
|
42
41
|
});
|
|
43
42
|
await run.writeSnapshot(inProgressBundle);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type PreparedOutputRoot } from "../../run/contained-output.js";
|
|
2
|
-
import type { CuaParticipantDeps, CuaParticipantPlan, CuaParticipantResult, DesktopParticipantRun,
|
|
2
|
+
import type { CuaParticipantDeps, CuaParticipantPlan, CuaParticipantResult, DesktopParticipantRun, ParticipantRunOutcome } from "./types.js";
|
|
3
|
+
import type { RunSubjectProvenance } from "../../run/bundle.js";
|
|
3
4
|
/** Build a participant's writeScreenshot closure: writes under screenshots/<screenshotDir>/ and records
|
|
4
5
|
* the relative path the trace references (screenshots/<name> at N=1; screenshots/<laneId>/<name>
|
|
5
6
|
* at N>1). */
|
|
@@ -24,7 +25,7 @@ export declare function runCuaParticipants(runs: DesktopParticipantRun[], deps:
|
|
|
24
25
|
failFastReason?: string;
|
|
25
26
|
}>;
|
|
26
27
|
/** Project one participant outcome (or a dry-run contract spec) into the public CuaParticipantResult. */
|
|
27
|
-
export declare function toParticipantResult(spec: DesktopParticipantRun, outcome: ParticipantRunOutcome | undefined, subject:
|
|
28
|
+
export declare function toParticipantResult(spec: DesktopParticipantRun, outcome: ParticipantRunOutcome | undefined, subject: RunSubjectProvenance, dryRun: boolean): CuaParticipantResult;
|
|
28
29
|
/**
|
|
29
30
|
* Run every participant of a live run. The in-process route drives its single participant in this
|
|
30
31
|
* process; one hosted participant runs alone; a fan-out runs at the plan's concurrency and may stop early.
|
|
@@ -4,14 +4,18 @@ import { type ResolvedPersona } from "../../study/persona.js";
|
|
|
4
4
|
import { type RunRerunLineage } from "../../run/bundle.js";
|
|
5
5
|
import type { PreparedSelectedOutputDirectory } from "../../run/contained-output.js";
|
|
6
6
|
import { type CuaActorStudyErrorCode, type CuaParticipantPlan, type CuaParticipantPlanEntry, type DesktopParticipantRun, type ParticipantRunsAndPlan } from "./types.js";
|
|
7
|
-
|
|
7
|
+
/**
|
|
8
|
+
* The session budget of a study that declares no execution.timeoutMs. On a provisioned route it is
|
|
9
|
+
* what the `ceilingMs` sandbox ceiling leaves after provisioning, seeding and the teardown buffer.
|
|
10
|
+
*/
|
|
11
|
+
export declare function defaultSessionTimeoutMs(config: StudyConfig, ceilingMs: number): number;
|
|
8
12
|
/** Per-participant sandbox deadline (each one owns its own desktop). Mirrors the
|
|
9
13
|
* single-participant formula verbatim so N=1 stays byte-stable: explicit sandboxTimeoutMs, else session budget + (clone
|
|
10
14
|
* or local-tree: provision budget + Σ state-step budgets) + the server-side
|
|
11
15
|
* reclamation buffer. Local-tree shares the clone route's provisioning budget: it swaps a
|
|
12
16
|
* git clone for an upload+extract, but the shared install/build/state/start/probe pipeline
|
|
13
17
|
* costs the same wall-clock room either way. */
|
|
14
|
-
export declare function resolveParticipantSandboxMs(config: StudyConfig): number;
|
|
18
|
+
export declare function resolveParticipantSandboxMs(config: StudyConfig, ceilingMs: number): number;
|
|
15
19
|
/**
|
|
16
20
|
* The in-flight participant bound a study declares. Defaults to the participant count: every
|
|
17
21
|
* declared participant runs at once, because a throttle nobody asked for silently turns "N actors
|
|
@@ -12,18 +12,22 @@ import {} from "../../run/bundle.js";
|
|
|
12
12
|
import { participantAssignment } from "../../study/participant-assignment.js";
|
|
13
13
|
import { resolveCommittedPersonas } from "../../study/persona-resolve.js";
|
|
14
14
|
import { CUA_FANOUT_STRATEGY, CUA_MAX_CONCURRENCY_ENV, DEFAULT_APP_URL_SESSION_TIMEOUT_MS, MIN_DERIVED_SESSION_TIMEOUT_MS, } from "./types.js";
|
|
15
|
-
import {
|
|
15
|
+
import { SANDBOX_TIMEOUT_BUFFER_MS, SUBJECT_PROVISION_BUDGET_MS, } from "../../substrates/e2b/lifetime.js";
|
|
16
16
|
import { readPositiveInt } from "../../study/parse/values.js";
|
|
17
17
|
import { digestUrl } from "./bundle-parts.js";
|
|
18
18
|
import { composeParticipantInstructions, DEFAULT_MISSION } from "./participant-prompt.js";
|
|
19
19
|
import { resolveCuaRerunSelection } from "./rerun-selection.js";
|
|
20
20
|
import { plural } from "../../run/text.js";
|
|
21
|
-
|
|
21
|
+
/**
|
|
22
|
+
* The session budget of a study that declares no execution.timeoutMs. On a provisioned route it is
|
|
23
|
+
* what the `ceilingMs` sandbox ceiling leaves after provisioning, seeding and the teardown buffer.
|
|
24
|
+
*/
|
|
25
|
+
export function defaultSessionTimeoutMs(config, ceilingMs) {
|
|
22
26
|
const provisionedRoute = config.subject.source === "clone" || config.subject.source === "local-tree";
|
|
23
27
|
if (!provisionedRoute)
|
|
24
28
|
return DEFAULT_APP_URL_SESSION_TIMEOUT_MS;
|
|
25
29
|
const stateBudgetMs = (config.subject.state?.seed ?? []).reduce((sum, step) => sum + (step.timeoutMs ?? DEFAULT_STATE_STEP_TIMEOUT_MS), 0);
|
|
26
|
-
const room =
|
|
30
|
+
const room = ceilingMs - SUBJECT_PROVISION_BUDGET_MS - stateBudgetMs - SANDBOX_TIMEOUT_BUFFER_MS;
|
|
27
31
|
return Math.max(MIN_DERIVED_SESSION_TIMEOUT_MS, Math.min(DEFAULT_APP_URL_SESSION_TIMEOUT_MS, room));
|
|
28
32
|
}
|
|
29
33
|
/** Per-participant sandbox deadline (each one owns its own desktop). Mirrors the
|
|
@@ -32,10 +36,10 @@ export function defaultSessionTimeoutMs(config) {
|
|
|
32
36
|
* reclamation buffer. Local-tree shares the clone route's provisioning budget: it swaps a
|
|
33
37
|
* git clone for an upload+extract, but the shared install/build/state/start/probe pipeline
|
|
34
38
|
* costs the same wall-clock room either way. */
|
|
35
|
-
export function resolveParticipantSandboxMs(config) {
|
|
39
|
+
export function resolveParticipantSandboxMs(config, ceilingMs) {
|
|
36
40
|
if (isLocalBrowserStudy(config))
|
|
37
41
|
return LOCAL_BROWSER_LIFETIME_MS;
|
|
38
|
-
const timeoutMs = config.execution?.timeoutMs ?? defaultSessionTimeoutMs(config);
|
|
42
|
+
const timeoutMs = config.execution?.timeoutMs ?? defaultSessionTimeoutMs(config, ceilingMs);
|
|
39
43
|
const provisionedRoute = config.subject.source === "clone" || config.subject.source === "local-tree";
|
|
40
44
|
const stateBudgetMs = provisionedRoute
|
|
41
45
|
? (config.subject.state?.seed ?? []).reduce((sum, step) => sum + (step.timeoutMs ?? DEFAULT_STATE_STEP_TIMEOUT_MS), 0)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type CuaActorDescriptor } from "../../actors/registry.js";
|
|
2
2
|
import type { ComputerUsePlan, ComputerUseRunner, RoutePlanResult, RouteRefusal } from "../../study/plan-types.js";
|
|
3
3
|
import type { StudyConfig, StudySubjectState } from "../../study/types.js";
|
|
4
|
+
import { type SandboxCeiling } from "../../substrates/e2b/lifetime.js";
|
|
4
5
|
import { type ComputerUseRunInput, type CuaActorStudyErrorCode } from "./types.js";
|
|
5
6
|
/** The error a computer-use study returns before a run starts. */
|
|
6
7
|
export interface ComputerUseRefusal extends RouteRefusal<"computer-use", CuaActorStudyErrorCode> {
|
|
@@ -45,4 +46,6 @@ export declare function planComputerUseStudy(config: StudyConfig, input: {
|
|
|
45
46
|
readonly driving?: CallerDriving;
|
|
46
47
|
readonly countOverride?: number;
|
|
47
48
|
readonly rerun?: ComputerUseRunInput["rerun"];
|
|
49
|
+
/** The longest sandbox lifetime the operator's E2B plan allows (sandboxCeiling). */
|
|
50
|
+
readonly sandboxCeiling: SandboxCeiling;
|
|
48
51
|
}): ComputerUsePlanResult;
|
|
@@ -14,7 +14,7 @@ import { cloneTargetValidationReason, computerUseValidationReason, desktopMediaV
|
|
|
14
14
|
import { desktopCliProductReason } from "../../study/composition-rules.js";
|
|
15
15
|
import { isLocalBrowserStudy } from "../../substrates/local/runtime-config.js";
|
|
16
16
|
import { boundedConcurrency, defaultSessionTimeoutMs, resolveParticipantSandboxMs, } from "./participant-runs.js";
|
|
17
|
-
import {
|
|
17
|
+
import { ceilingAdvice } from "../../substrates/e2b/lifetime.js";
|
|
18
18
|
import {} from "./types.js";
|
|
19
19
|
/** The registered descriptor for a planned actor id; planComputerUseStudy checked the registry. */
|
|
20
20
|
export function cuaDescriptorOf(actor) {
|
|
@@ -74,12 +74,12 @@ const invalid = (message) => ({
|
|
|
74
74
|
* is touched. The parser enforces most of these too; the engine repeats them for library callers
|
|
75
75
|
* that hand it a config directly. The groups run in this order, and each returns its first reason.
|
|
76
76
|
*/
|
|
77
|
-
function cuaStudyRejection(config, hasRunSession, driving, subjectRoute) {
|
|
77
|
+
function cuaStudyRejection(config, hasRunSession, driving, subjectRoute, ceilingMs) {
|
|
78
78
|
return (unsupportedDeclarationReason(config, hasRunSession, driving, subjectRoute) ??
|
|
79
79
|
subjectStructureReason(config, subjectRoute) ??
|
|
80
80
|
entryTargetReason(config, subjectRoute) ??
|
|
81
81
|
driverReason(driving, subjectRoute) ??
|
|
82
|
-
rosterShapeReason(config));
|
|
82
|
+
rosterShapeReason(config, ceilingMs));
|
|
83
83
|
}
|
|
84
84
|
/** A declaration this route cannot honor, for any subject or with the caller's own driver. */
|
|
85
85
|
function unsupportedDeclarationReason(config, hasRunSession, driving, { inProcessRoute }) {
|
|
@@ -173,7 +173,7 @@ function driverReason(driving, { localAppSubject, inProcessRoute }) {
|
|
|
173
173
|
return undefined;
|
|
174
174
|
}
|
|
175
175
|
/** The participant roster, then the sandbox deadline its session budget derives. */
|
|
176
|
-
function rosterShapeReason(config) {
|
|
176
|
+
function rosterShapeReason(config, ceilingMs) {
|
|
177
177
|
// Device XOR raw resolution, cap, unique ids,
|
|
178
178
|
// allowPublicTargets with more than one participant, clone.fanout.
|
|
179
179
|
const fanoutReason = computerUseValidationReason(config);
|
|
@@ -182,13 +182,13 @@ function rosterShapeReason(config) {
|
|
|
182
182
|
// The sandbox deadline is derived from the session budget, so a study can ask for a session that
|
|
183
183
|
// cannot legally be provisioned. Show the arithmetic: the provider's own error names a limit
|
|
184
184
|
// but not which knob produced it.
|
|
185
|
-
const derivedSandboxMs = resolveParticipantSandboxMs(config);
|
|
186
|
-
if (derivedSandboxMs <=
|
|
185
|
+
const derivedSandboxMs = resolveParticipantSandboxMs(config, ceilingMs);
|
|
186
|
+
if (derivedSandboxMs <= ceilingMs)
|
|
187
187
|
return undefined;
|
|
188
188
|
const provisionedRoute = config.subject.source === "clone" || config.subject.source === "local-tree";
|
|
189
|
-
const sessionMs = config.execution?.timeoutMs ?? defaultSessionTimeoutMs(config);
|
|
189
|
+
const sessionMs = config.execution?.timeoutMs ?? defaultSessionTimeoutMs(config, ceilingMs);
|
|
190
190
|
const headroomMs = derivedSandboxMs - sessionMs;
|
|
191
|
-
return invalid(`execution.timeoutMs ${Math.round(sessionMs / 60_000)}m derives a ${Math.round(derivedSandboxMs / 60_000)}m sandbox deadline, and a sandbox may not live longer than ${
|
|
191
|
+
return invalid(`execution.timeoutMs ${Math.round(sessionMs / 60_000)}m derives a ${Math.round(derivedSandboxMs / 60_000)}m sandbox deadline, and a sandbox may not live longer than ${ceilingMs / 60_000}m. The deadline is the session budget plus ${Math.round(headroomMs / 60_000)}m of provisioning and teardown headroom${provisionedRoute ? " (this route clones, installs, builds and serves the subject before the actor starts)" : ""}. Lower execution.timeoutMs to at most ${Math.round((ceilingMs - headroomMs) / 60_000)}m, or set execution.desktop.sandboxTimeoutMs explicitly.${ceilingAdvice(derivedSandboxMs)}`);
|
|
192
192
|
}
|
|
193
193
|
/** The plan's rerun: the source run and, when given, the participants to rerun. */
|
|
194
194
|
function rerunPlan({ sourceRunId, participantIds, }) {
|
|
@@ -223,7 +223,10 @@ export function planComputerUseStudy(config, input) {
|
|
|
223
223
|
if (!descriptor || !isCuaActorDescriptor(descriptor))
|
|
224
224
|
return refuse("in-scope", "HUMANISH_COMPUTER_USE_ACTOR_UNSUPPORTED", `actor.type "${actorType}" is not a registered computer-use actor.`);
|
|
225
225
|
const actor = descriptor.id;
|
|
226
|
-
const
|
|
226
|
+
const ceiling = input.sandboxCeiling;
|
|
227
|
+
if (!ceiling.ok)
|
|
228
|
+
return refuse("in-scope", "HUMANISH_COMPUTER_USE_SUBJECT_INVALID", ceiling.message, actor);
|
|
229
|
+
const rejection = cuaStudyRejection(config, hasRunSession, driving, declaredSubjectRoute(config, driving), ceiling.ms);
|
|
227
230
|
if (rejection)
|
|
228
231
|
return refuse("in-scope", rejection.code, rejection.message, actor);
|
|
229
232
|
// A shared world runs every participant against one app; this route would run them as separate
|
|
@@ -288,8 +291,8 @@ export function planComputerUseStudy(config, input) {
|
|
|
288
291
|
actor,
|
|
289
292
|
runner,
|
|
290
293
|
concurrency: boundedConcurrency(declared, n),
|
|
291
|
-
sessionBudgetMs: config.execution?.timeoutMs ?? defaultSessionTimeoutMs(config),
|
|
292
|
-
sandboxMs: resolveParticipantSandboxMs(config),
|
|
294
|
+
sessionBudgetMs: config.execution?.timeoutMs ?? defaultSessionTimeoutMs(config, ceiling.ms),
|
|
295
|
+
sandboxMs: resolveParticipantSandboxMs(config, ceiling.ms),
|
|
293
296
|
caps: planCaps(config),
|
|
294
297
|
...(input.rerun === undefined ? {} : { rerun: rerunPlan(input.rerun) }),
|
|
295
298
|
requirements: base.dryRun || runner.desktop === "in-process"
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
// participants that failed, blocked, timed out or finished hollow are picked unless ids are given.
|
|
3
3
|
import {} from "../../run/bundle.js";
|
|
4
4
|
import { loadRunBundle } from "../../run/locate.js";
|
|
5
|
+
import { resolveLatestRunPointer } from "../../run/paths.js";
|
|
5
6
|
import {} from "../../run/streams.js";
|
|
6
7
|
import { plural } from "../../run/text.js";
|
|
7
8
|
import { access } from "node:fs/promises";
|
|
8
|
-
import path from "node:path";
|
|
9
9
|
import { cli } from "../../cli/invocation.js";
|
|
10
10
|
export async function resolveCuaRerunSelection(args) {
|
|
11
11
|
const { studyId, sourceRunId } = args;
|
|
@@ -16,7 +16,7 @@ export async function resolveCuaRerunSelection(args) {
|
|
|
16
16
|
const source = await loadRunBundle(args.cwd, sourceRunId);
|
|
17
17
|
if (!source) {
|
|
18
18
|
const noRuns = sourceRunId === "latest" &&
|
|
19
|
-
!(await access(
|
|
19
|
+
!(await access(resolveLatestRunPointer(args.cwd)).then(() => true, () => false));
|
|
20
20
|
return refuse(noRuns
|
|
21
21
|
? "--rerun-failed-from latest found no run: this project has no runs yet, and a rerun repeats the failed participants of an earlier live run."
|
|
22
22
|
: `--rerun-failed-from ${sourceRunId} names no run humanish can read in this project. ${cli("runs")} lists its runs.`);
|
|
@@ -7,8 +7,8 @@ import { participantCapWarning } from "./participant-model.js";
|
|
|
7
7
|
import { summarizeCuaDiagnostics } from "./diagnostics.js";
|
|
8
8
|
import { toParticipantResult } from "./participant-execution.js";
|
|
9
9
|
import { buildCuaRunBundle, judgeComputerUseRun } from "./bundle.js";
|
|
10
|
-
import { aggregateCuaSubject, projectParticipantSubjects
|
|
11
|
-
import { CUA_FANOUT_STRATEGY,
|
|
10
|
+
import { aggregateCuaSubject, projectParticipantSubjects } from "./subject-projection.js";
|
|
11
|
+
import { CUA_FANOUT_STRATEGY, } from "./types.js";
|
|
12
12
|
import { plannedAppUrl } from "./plan.js";
|
|
13
13
|
import { studyResultIdentity } from "../../run/study-result.js";
|
|
14
14
|
import { plural } from "../../run/text.js";
|
|
@@ -157,10 +157,9 @@ function cuaStudyResult(args) {
|
|
|
157
157
|
export async function finishCuaRun(setup, finish, ran) {
|
|
158
158
|
const { plan, input, cwd, streams, descriptor, run } = setup;
|
|
159
159
|
const { participantRuns, participantPlan, bundleBase } = setup;
|
|
160
|
-
const { rerunLineage,
|
|
160
|
+
const { rerunLineage, subjectArgs } = finish;
|
|
161
161
|
const { dryRun } = plan;
|
|
162
162
|
const appUrl = plannedAppUrl(plan.runner.subject);
|
|
163
|
-
const subjectEnvNames = [...participantSubjectEnv(plan.runner.subject)];
|
|
164
163
|
const { runId } = run;
|
|
165
164
|
const participantCount = participantRuns.length;
|
|
166
165
|
const { outcomes, failFastReason, receiving, receivingWarnings, externalCommsWarnings } = ran;
|
|
@@ -174,7 +173,6 @@ export async function finishCuaRun(setup, finish, ran) {
|
|
|
174
173
|
...(capWarning === undefined ? [] : [capWarning]),
|
|
175
174
|
...aggregate.warnings,
|
|
176
175
|
];
|
|
177
|
-
const finalProvenance = subjectProvenanceArg(aggregateSubject, publicRepo, subjectEnvNames);
|
|
178
176
|
// One judgment for the whole run: the bundle's verdict and the result's ok both read it.
|
|
179
177
|
const judgment = judgeComputerUseRun(bundleBase, { dryRun, outcomes });
|
|
180
178
|
const bundle = buildCuaRunBundle(bundleBase, {
|
|
@@ -183,7 +181,6 @@ export async function finishCuaRun(setup, finish, ran) {
|
|
|
183
181
|
outcomes,
|
|
184
182
|
subjects,
|
|
185
183
|
aggregateSubject,
|
|
186
|
-
subjectProvenance: finalProvenance,
|
|
187
184
|
...(failFastReason === undefined ? {} : { failFastReason }),
|
|
188
185
|
});
|
|
189
186
|
const adapterWarnings = [];
|
|
@@ -3,14 +3,14 @@ import type { RefusedStudy } from "../../run/route-shell.js";
|
|
|
3
3
|
import { RunSecrets } from "../../run/secrets.js";
|
|
4
4
|
import type { CuaActorDescriptor } from "../../actors/registry.js";
|
|
5
5
|
import type { StudyCommsEmail, StudyCommsExternal, StudyConfig } from "../../study/types.js";
|
|
6
|
-
import { type RunRerunLineage } from "../../run/bundle.js";
|
|
6
|
+
import { type RunRerunLineage, type RunSubjectProvenance } from "../../run/bundle.js";
|
|
7
7
|
import { type LocalTreeArchive } from "../../subject/local-tree-archive.js";
|
|
8
8
|
import { type ComputerUseRefusal } from "./plan.js";
|
|
9
9
|
import type { ComputerUsePlan } from "../../study/plan-types.js";
|
|
10
10
|
import { trackRuntimeStreams, type LiveTraceFlush } from "./live-flush.js";
|
|
11
11
|
import { type CuaRunBundleBase } from "./bundle.js";
|
|
12
12
|
import { projectParticipantSubjects } from "./subject-projection.js";
|
|
13
|
-
import { type CuaActorStudyErrorCode, type CuaActorStudyResult, type CuaParticipantDeps, type CuaParticipantPlan, type DesktopParticipantRun, type
|
|
13
|
+
import { type CuaActorStudyErrorCode, type CuaActorStudyResult, type CuaParticipantDeps, type CuaParticipantPlan, type DesktopParticipantRun, type ComputerUseRunInput } from "./types.js";
|
|
14
14
|
/**
|
|
15
15
|
* The envelope of a refusal the plan left for after the cwd checks. The participant cap and
|
|
16
16
|
* in-process fan-out refusals come after the committed personas are read, so a persona-file error still wins.
|
|
@@ -51,9 +51,8 @@ export interface CuaParticipantsSetup {
|
|
|
51
51
|
} | undefined;
|
|
52
52
|
/** The subjects of the in-progress bundle, written before any participant starts. */
|
|
53
53
|
inProgress: {
|
|
54
|
-
subjects:
|
|
55
|
-
aggregateSubject:
|
|
56
|
-
provenance: CuaSubjectProvenanceArg | undefined;
|
|
54
|
+
subjects: RunSubjectProvenance[];
|
|
55
|
+
aggregateSubject: RunSubjectProvenance;
|
|
57
56
|
};
|
|
58
57
|
/** The refusal envelope, for a run that stops before its bundle. */
|
|
59
58
|
fail: (code: CuaActorStudyErrorCode, message: string, actorLabel?: string) => CuaActorStudyResult;
|
|
@@ -61,7 +60,6 @@ export interface CuaParticipantsSetup {
|
|
|
61
60
|
/** What only finishCuaRun reads besides the participants' outcomes. */
|
|
62
61
|
export interface CuaFinishFacts {
|
|
63
62
|
rerunLineage: RunRerunLineage | undefined;
|
|
64
|
-
publicRepo: string | undefined;
|
|
65
63
|
subjectArgs: Omit<Parameters<typeof projectParticipantSubjects>[0], "outcomes" | "dryRun">;
|
|
66
64
|
}
|
|
67
65
|
type PreparedCuaRun = {
|
|
@@ -20,7 +20,7 @@ import { phaseEvent, planEvent } from "../../study/run-study-events.js";
|
|
|
20
20
|
import { defaultSubjectPhaseSink } from "../../subject/steps.js";
|
|
21
21
|
import {} from "./bundle.js";
|
|
22
22
|
import { packRunLocalTree } from "./local-tree-pack.js";
|
|
23
|
-
import { projectParticipantSubjects
|
|
23
|
+
import { projectParticipantSubjects } from "./subject-projection.js";
|
|
24
24
|
import { participantSubjectEnv, } from "./types.js";
|
|
25
25
|
import { capacityShortfall } from "../../substrates/local/capacity.js";
|
|
26
26
|
import { studyPersonaIds } from "../../study/persona-resolve.js";
|
|
@@ -248,9 +248,6 @@ export async function startCuaRun(plan, input, admitted, scope) {
|
|
|
248
248
|
dryRun: false,
|
|
249
249
|
});
|
|
250
250
|
const inProgressAggregateSubject = inProgressSubjects[0];
|
|
251
|
-
const inProgressProvenance = subjectProvenanceArg(inProgressAggregateSubject, publicRepo, [
|
|
252
|
-
...participantSubjectEnv(plan.runner.subject),
|
|
253
|
-
]);
|
|
254
251
|
const bundleBase = {
|
|
255
252
|
run,
|
|
256
253
|
participantRuns,
|
|
@@ -287,11 +284,10 @@ export async function startCuaRun(plan, input, admitted, scope) {
|
|
|
287
284
|
inProgress: {
|
|
288
285
|
subjects: inProgressSubjects,
|
|
289
286
|
aggregateSubject: inProgressAggregateSubject,
|
|
290
|
-
provenance: inProgressProvenance,
|
|
291
287
|
},
|
|
292
288
|
fail: admitted.fail,
|
|
293
289
|
},
|
|
294
|
-
finish: { rerunLineage: admitted.rerunLineage,
|
|
290
|
+
finish: { rerunLineage: admitted.rerunLineage, subjectArgs },
|
|
295
291
|
};
|
|
296
292
|
}
|
|
297
293
|
/** The participant deps every participant reads, with computer use's own overrides. */
|
|
@@ -3,11 +3,10 @@ import type { SubjectPhaseEvent } from "../../subject/steps.js";
|
|
|
3
3
|
import type { DesktopBrowserEvidence } from "../../substrates/e2b/desktop-browser.js";
|
|
4
4
|
import type { ActorPersonaRef } from "../../actors/contract.js";
|
|
5
5
|
import type { CuaLoopResult } from "../../actors/computer-use/loop.js";
|
|
6
|
-
import { type BundleRun, type RunBundle, type RunFeedbackCandidate, type RunProviderResource } from "../../run/bundle.js";
|
|
6
|
+
import { type BundleRun, type RunBundle, type RunFeedbackCandidate, type RunProviderResource, type RunSubjectProvenance } from "../../run/bundle.js";
|
|
7
7
|
import { type RunDesktopGeometry, type RunStream } from "../../run/streams.js";
|
|
8
8
|
import { type Verdict } from "../../run/judge.js";
|
|
9
9
|
import { type DesktopUsage } from "../../run/cost-summary.js";
|
|
10
|
-
import type { CuaSubjectProvenanceArg } from "./types.js";
|
|
11
10
|
/**
|
|
12
11
|
* The bundle of a single-participant run: one participant and no rerun. buildCuaRunBundle
|
|
13
12
|
* (bundle.ts) maps the run's base and state into these arguments.
|
|
@@ -70,9 +69,9 @@ export declare function buildSingleParticipantBundle(args: {
|
|
|
70
69
|
reportedFriction: boolean;
|
|
71
70
|
};
|
|
72
71
|
source: RunBundle["source"];
|
|
73
|
-
/**
|
|
74
|
-
*
|
|
75
|
-
|
|
72
|
+
/** The subject as subject-projection.ts projects it (names and digests only, never values or
|
|
73
|
+
* command text): run.json records it as `subject`, and the subject event describes it. */
|
|
74
|
+
subject: RunSubjectProvenance;
|
|
76
75
|
/**
|
|
77
76
|
* Entry kind for the non-clone subject.declared event, which declares what the subject
|
|
78
77
|
* was. "local-app": an already-running local dev server driven in-process, un-pinnable, and
|
|
@@ -2,7 +2,7 @@ import { participantAssignment } from "../../study/participant-assignment.js";
|
|
|
2
2
|
import { redactText } from "../../evidence/redaction.js";
|
|
3
3
|
import { REVIEW_SCHEMA, bundleArtifacts, bundleHead, } from "../../run/bundle.js";
|
|
4
4
|
import {} from "../../run/streams.js";
|
|
5
|
-
import { aggregateTaskFunnels, formatParticipantOutcomes, formatRunTaskFunnel,
|
|
5
|
+
import { aggregateTaskFunnels, formatParticipantOutcomes, formatRunTaskFunnel, participantSummary, withCuaReviewProvenance, } from "../../run/outcomes.js";
|
|
6
6
|
import { participantCaption } from "../../run/participant-caption.js";
|
|
7
7
|
import { actorEnding } from "../../actors/stop-cause.js";
|
|
8
8
|
import { describeSubjectState, phaseEventIdSuffix, publicSafeAppUrlLabel, subjectProvenanceMessage, } from "./bundle-parts.js";
|
|
@@ -103,13 +103,11 @@ function singleSimulation(args, view) {
|
|
|
103
103
|
mode: "browser-sim",
|
|
104
104
|
progress: args.inProgress === true ? 20 : 100,
|
|
105
105
|
currentStep: reason,
|
|
106
|
-
summary: args
|
|
107
|
-
|
|
108
|
-
: args.
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
? `${name} did not finish a session: ${args.sessionError}`
|
|
112
|
-
: `${name} would use ${publicAppUrl}; no session ran.`,
|
|
106
|
+
summary: participantSummary(name, { name: "the app", place: browserPlace(args), target: publicAppUrl }, {
|
|
107
|
+
trace: args.session?.trace,
|
|
108
|
+
sessionError: args.sessionError,
|
|
109
|
+
inProgress: args.inProgress === true,
|
|
110
|
+
}),
|
|
113
111
|
startedAt: args.run.createdAt,
|
|
114
112
|
updatedAt: args.run.createdAt,
|
|
115
113
|
});
|
|
@@ -183,6 +181,7 @@ function singleStream(args, view) {
|
|
|
183
181
|
}
|
|
184
182
|
function singleEvents(args, view) {
|
|
185
183
|
const { publicAppUrl, desktopGeometry } = view;
|
|
184
|
+
const { subject } = args;
|
|
186
185
|
const events = [
|
|
187
186
|
{
|
|
188
187
|
id: "event-000-created",
|
|
@@ -191,30 +190,32 @@ function singleEvents(args, view) {
|
|
|
191
190
|
type: "cua-lab.run.created",
|
|
192
191
|
message: `Created a computer-use run for ${args.studyId} (actor ${args.actorId}).`,
|
|
193
192
|
},
|
|
194
|
-
|
|
193
|
+
subject.source === "clone" || subject.source === "local-tree"
|
|
195
194
|
? participantEvent(SINGLE, {
|
|
196
195
|
id: "event-001-subject",
|
|
197
196
|
at: args.run.createdAt,
|
|
198
197
|
level: "info",
|
|
199
198
|
type: "cua-lab.subject.provenance",
|
|
200
199
|
// Claim "cloned/packed and served" only when it actually happened.
|
|
201
|
-
message: `${subjectProvenanceMessage(
|
|
200
|
+
message: `${subjectProvenanceMessage(subject, publicAppUrl, args.dryRun, args.session !== undefined)} (subject env names: ${subject.envNames !== undefined && subject.envNames.length > 0 ? subject.envNames.join(", ") : "none"}; values never persisted); state: ${describeSubjectState(subject.state, args.dryRun)}.`,
|
|
202
201
|
})
|
|
203
202
|
: participantEvent(SINGLE, {
|
|
204
203
|
id: "event-001-subject",
|
|
205
204
|
at: args.run.createdAt,
|
|
206
205
|
level: "info",
|
|
207
206
|
type: "cua-lab.subject.declared",
|
|
208
|
-
// Declare what the subject was, including the absence of a pin. A
|
|
209
|
-
// local-app / in-process subject is an already-running
|
|
210
|
-
// provisioned; it cannot be commit-pinned, so its provenance
|
|
211
|
-
// no E2B desktop was created. A plain app-url entry runs inside the
|
|
212
|
-
// on the local VM, reaches the host's loopback from the VM's browser.
|
|
213
|
-
message:
|
|
214
|
-
? `Subject
|
|
215
|
-
:
|
|
216
|
-
? `Subject app declared at ${publicAppUrl}
|
|
217
|
-
:
|
|
207
|
+
// Declare what the subject was, including the absence of a pin. A desktop-cli product
|
|
208
|
+
// is named, since it has no URL. A local-app / in-process subject is an already-running
|
|
209
|
+
// local dev server the caller provisioned; it cannot be commit-pinned, so its provenance
|
|
210
|
+
// is unpinned and no E2B desktop was created. A plain app-url entry runs inside the
|
|
211
|
+
// desktop sandbox, or, on the local VM, reaches the host's loopback from the VM's browser.
|
|
212
|
+
message: subject.source === "desktop-cli"
|
|
213
|
+
? `Subject product declared: ${subject.product}, used from a terminal window inside the desktop sandbox.`
|
|
214
|
+
: args.entryKind === "local-app"
|
|
215
|
+
? `Subject app declared at ${publicAppUrl}: a running local dev server driven in this process, with no clone and no E2B desktop. Provenance: provided by the caller and unpinned, because a running dev server has no commit to pin.`
|
|
216
|
+
: runnerSubstrate(args) === "local-desktop"
|
|
217
|
+
? `Subject app declared at ${publicAppUrl} (the host's loopback, opened from a browser on a local VM).`
|
|
218
|
+
: `Subject app declared at ${publicAppUrl} (loopback inside the desktop sandbox).`,
|
|
218
219
|
}),
|
|
219
220
|
args.session
|
|
220
221
|
? participantEvent(SINGLE, {
|
|
@@ -428,11 +429,7 @@ export function buildSingleParticipantBundle(args) {
|
|
|
428
429
|
...(args.providerResources === undefined || args.providerResources.length === 0
|
|
429
430
|
? {}
|
|
430
431
|
: { providerResources: args.providerResources }),
|
|
431
|
-
|
|
432
|
-
// stated on app-url bundles too: the caller minted the URL, its state is the caller's.
|
|
433
|
-
// CuaSubjectProvenanceArg's two variants (clone, local-tree) are already RunSubjectProvenance-
|
|
434
|
-
// shaped, so no reconstruction is needed beyond the app-url fallback.
|
|
435
|
-
subject: args.subjectProvenance ?? { source: "app-url", state: { provenance: "undeclared" } },
|
|
432
|
+
subject: args.subject,
|
|
436
433
|
...(cost === undefined ? {} : { cost }),
|
|
437
434
|
};
|
|
438
435
|
}
|
|
@@ -2,7 +2,7 @@ import type { ComputerUsePlan } from "../../study/plan-types.js";
|
|
|
2
2
|
import type { StudySubjectState } from "../../study/types.js";
|
|
3
3
|
import { type RunSubjectProvenance, type RunSubjectStateStepRecord } from "../../run/bundle.js";
|
|
4
4
|
import { type LocalTreeArchive } from "../../subject/local-tree-archive.js";
|
|
5
|
-
import { type DesktopParticipantRun, type
|
|
5
|
+
import { type DesktopParticipantRun, type ParticipantRunOutcome } from "./types.js";
|
|
6
6
|
/**
|
|
7
7
|
* Each participant's subject projection. A participant's outcome adds the subject commit it resolved and the
|
|
8
8
|
* state steps it executed; without outcomes (dry run, or a run still in progress) the declared
|
|
@@ -15,7 +15,7 @@ export declare function projectParticipantSubjects(args: {
|
|
|
15
15
|
runs: readonly DesktopParticipantRun[];
|
|
16
16
|
outcomes: readonly ParticipantRunOutcome[] | undefined;
|
|
17
17
|
dryRun: boolean;
|
|
18
|
-
}):
|
|
18
|
+
}): RunSubjectProvenance[];
|
|
19
19
|
/**
|
|
20
20
|
* Resolve the bundle's state marker from the declaration and what actually ran.
|
|
21
21
|
* Precedence: external declared → "unpinned" (seed records, if any, stay attached; a
|
|
@@ -28,10 +28,6 @@ export declare function resolveSubjectState(args: {
|
|
|
28
28
|
dryRun: boolean;
|
|
29
29
|
executed: RunSubjectStateStepRecord[];
|
|
30
30
|
}): RunSubjectProvenance["state"];
|
|
31
|
-
/** Narrow a resolved CuaSubjectProjection into the shape buildSingleParticipantBundle's
|
|
32
|
-
* subjectProvenance param wants (provisioned-route sources only; app-url stays undeclared, the
|
|
33
|
-
* default branch that builder already handles). */
|
|
34
|
-
export declare function subjectProvenanceArg(subject: CuaSubjectProjection, publicRepo: string | undefined, subjectEnvNames: string[]): CuaSubjectProvenanceArg | undefined;
|
|
35
31
|
/**
|
|
36
32
|
* The run-level subject for the top level and the bundle. Local-tree participants all pack from the
|
|
37
33
|
* same once-per-run archive, so every participant already carries the identical archiveSha256/commit/dirty and
|
|
@@ -39,11 +35,11 @@ export declare function subjectProvenanceArg(subject: CuaSubjectProjection, publ
|
|
|
39
35
|
* commit; the aggregate carries it only when every participant agrees, and warns when they diverge.
|
|
40
36
|
*/
|
|
41
37
|
export declare function aggregateCuaSubject(args: {
|
|
42
|
-
subjects: readonly
|
|
38
|
+
subjects: readonly RunSubjectProvenance[];
|
|
43
39
|
outcomes: readonly ParticipantRunOutcome[] | undefined;
|
|
44
40
|
participantCount: number;
|
|
45
41
|
dryRun: boolean;
|
|
46
42
|
}): {
|
|
47
|
-
subject:
|
|
43
|
+
subject: RunSubjectProvenance;
|
|
48
44
|
warnings: string[];
|
|
49
45
|
};
|