humanish 0.110.0 → 0.110.1
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 +14 -11
- package/CHANGELOG.md +13 -0
- package/CONTEXT.md +8 -6
- package/README.md +96 -47
- package/dist/actors/computer-use/loop/ending.js +4 -4
- package/dist/actors/local-agent/claude-participant.d.ts +74 -0
- package/dist/actors/local-agent/claude-participant.js +243 -0
- package/dist/actors/local-agent/claude-session.d.ts +16 -3
- package/dist/actors/local-agent/claude-session.js +64 -23
- package/dist/actors/local-agent/cli.d.ts +11 -0
- package/dist/actors/local-agent/cli.js +103 -24
- package/dist/actors/local-agent/readiness.d.ts +2 -2
- package/dist/actors/local-agent/readiness.js +18 -11
- package/dist/cli/commands/analyze.js +21 -5
- package/dist/cli/commands/run-signals.d.ts +2 -0
- package/dist/cli/commands/run-signals.js +96 -44
- package/dist/cli/commands/runs.d.ts +5 -0
- package/dist/cli/commands/runs.js +86 -70
- package/dist/cli/commands/study-route-computer-use.js +2 -0
- package/dist/cli/commands/study-route-scripted.js +2 -0
- package/dist/cli/commands/study-route-shared-world.js +2 -0
- package/dist/cli/commands/study-route-terminal.js +2 -0
- package/dist/cli/doctor.d.ts +4 -1
- package/dist/cli/doctor.js +42 -4
- package/dist/cli/findings.d.ts +103 -0
- package/dist/cli/findings.js +316 -0
- package/dist/cli/first-run-path.d.ts +5 -4
- package/dist/cli/first-run-path.js +14 -7
- package/dist/cli/io.js +2 -1
- package/dist/cli/product-sentence.d.ts +3 -3
- package/dist/cli/product-sentence.js +3 -3
- package/dist/keys/env-file.d.ts +4 -0
- package/dist/keys/env-file.js +17 -0
- package/dist/observer/data.d.ts +14 -1
- package/dist/observer/data.js +19 -9
- package/dist/observer/library.d.ts +4 -0
- package/dist/observer/library.js +18 -15
- package/dist/observer/render.js +8 -2
- package/dist/observer/run-routes.d.ts +2 -0
- package/dist/observer/run-routes.js +43 -34
- package/dist/observer-app.html +3 -3
- package/dist/routes/computer-use/bundle.js +3 -1
- package/dist/routes/computer-use/fanout-records.js +1 -1
- package/dist/routes/computer-use/participant-execution.js +3 -1
- package/dist/routes/computer-use/participant-model.js +5 -2
- package/dist/routes/computer-use/plan.js +4 -4
- package/dist/routes/computer-use/preflight.js +1 -1
- package/dist/routes/computer-use/result.js +17 -28
- package/dist/routes/computer-use/single-bundle.js +7 -1
- package/dist/routes/scripted/bundle.js +4 -2
- package/dist/routes/scripted/plan.js +2 -2
- package/dist/routes/scripted/result.d.ts +3 -5
- package/dist/routes/scripted/result.js +16 -22
- package/dist/routes/scripted/scenario.js +4 -4
- package/dist/routes/shared-world/bundle-records.js +6 -1
- package/dist/routes/shared-world/bundle.js +2 -0
- package/dist/routes/shared-world/plan.js +1 -1
- package/dist/routes/shared-world/result.js +22 -22
- package/dist/routes/terminal/bundle.js +4 -2
- package/dist/routes/terminal/dry-run.js +8 -12
- package/dist/routes/terminal/ledger.d.ts +3 -3
- package/dist/routes/terminal/ledger.js +6 -6
- package/dist/routes/terminal/live-finish.js +15 -13
- package/dist/routes/terminal/plan.js +4 -4
- package/dist/routes/terminal/result.d.ts +6 -7
- package/dist/routes/terminal/result.js +6 -22
- package/dist/routes/terminal/session.js +1 -1
- package/dist/run/bundle-shape.d.ts +3 -1
- package/dist/run/bundle-shape.js +25 -1
- package/dist/run/bundle.d.ts +24 -0
- package/dist/run/display.d.ts +59 -0
- package/dist/run/display.js +106 -0
- package/dist/run/dry-run.js +11 -7
- package/dist/run/judge.d.ts +3 -2
- package/dist/run/judge.js +10 -0
- package/dist/run/pricing.js +1 -1
- package/dist/run/projection.d.ts +0 -2
- package/dist/run/projection.js +0 -11
- package/dist/run/reclaim-outcomes.d.ts +89 -0
- package/dist/run/reclaim-outcomes.js +213 -0
- package/dist/run/reclaim.d.ts +18 -17
- package/dist/run/reclaim.js +180 -113
- package/dist/run/results.d.ts +10 -20
- package/dist/run/results.js +2 -2
- package/dist/run/run-index.d.ts +11 -1
- package/dist/run/run-index.js +11 -0
- package/dist/run/run.d.ts +34 -18
- package/dist/run/run.js +166 -67
- package/dist/run/sandbox-creates.d.ts +59 -0
- package/dist/run/sandbox-creates.js +138 -0
- package/dist/run/sandbox-receipts.d.ts +14 -0
- package/dist/run/sandbox-receipts.js +44 -0
- package/dist/run/stats.d.ts +5 -0
- package/dist/run/stats.js +8 -4
- package/dist/run/status.d.ts +6 -9
- package/dist/run/status.js +7 -23
- package/dist/run/stored-runs.d.ts +5 -14
- package/dist/run/stored-runs.js +31 -146
- package/dist/run/streams.d.ts +3 -2
- package/dist/study/doctor.d.ts +1 -1
- package/dist/study/doctor.js +5 -2
- package/dist/study/init.js +14 -3
- package/dist/study/keys.d.ts +12 -0
- package/dist/study/keys.js +32 -0
- package/dist/study/persona.d.ts +4 -0
- package/dist/study/persona.js +4 -2
- package/dist/substrates/e2b/peer-install.d.ts +51 -0
- package/dist/substrates/e2b/peer-install.js +161 -0
- package/dist/substrates/e2b/sandbox.d.ts +34 -6
- package/dist/substrates/e2b/sandbox.js +128 -35
- package/dist/substrates/e2b/sdk.d.ts +33 -0
- package/dist/substrates/e2b/sdk.js +21 -21
- package/dist/substrates/shell.d.ts +2 -0
- package/dist/substrates/shell.js +4 -0
- package/dist/tui-app.js +133 -133
- package/dist/verify/liveness.d.ts +19 -3
- package/dist/verify/liveness.js +46 -25
- package/dist/verify/verify.d.ts +3 -0
- package/dist/verify/verify.js +6 -2
- package/docs/architecture/actor-contract.md +2 -1
- package/docs/architecture/observer.md +22 -7
- package/docs/architecture/task-protocol-support.md +13 -13
- package/docs/architecture/terminal-product-route.md +1 -1
- package/docs/contracts/run-bundle.md +75 -6
- package/docs/contracts/schemas.md +39 -22
- package/docs/contracts/study-analysis.md +45 -0
- package/docs/contracts/study-costs.md +8 -0
- package/docs/decisions/0001-run-bundle-is-the-source-of-truth.md +3 -0
- package/docs/decisions/0003-contained-paths-and-cleanup-authority.md +9 -3
- package/docs/principles/invariants-and-defaults.md +11 -8
- package/package.json +4 -3
- package/skills/humanish/SKILL.md +16 -2
package/dist/observer/render.js
CHANGED
|
@@ -11,7 +11,8 @@ import { projectShareCheckedAnalysis } from "../analysis/sharing.js";
|
|
|
11
11
|
import { loadAnalysis } from "../analysis/load.js";
|
|
12
12
|
import { physicalCwdOf, runIdOf, bindExistingRunArtifactPaths, isSafeRunIdSegment, resolveLatestRunDirectory, validatePreparedRunArtifactPaths, } from "../run/paths.js";
|
|
13
13
|
import { writeContainedOutputFile } from "../run/contained-output.js";
|
|
14
|
-
import { loadRunBundlePrepared } from "../run/locate.js";
|
|
14
|
+
import { loadRunBundlePrepared, readRunJsonIfExists } from "../run/locate.js";
|
|
15
|
+
import { RUN_STATUS_FILE } from "../run/status.js";
|
|
15
16
|
import { verifyRunPrepared } from "../verify/verify.js";
|
|
16
17
|
import { renderObserverHtml } from "./artifact.js";
|
|
17
18
|
import { buildObserverData } from "./data.js";
|
|
@@ -99,7 +100,12 @@ export async function renderObserver(cwdInput, runInput, options = {}) {
|
|
|
99
100
|
...projectShareCheckedAnalysis(await loadAnalysis(preparedRunPaths)),
|
|
100
101
|
...(spend === null ? {} : { spend }),
|
|
101
102
|
};
|
|
102
|
-
|
|
103
|
+
// A run.json without an outcome is in progress, interrupted, or older than the field: its
|
|
104
|
+
// status.json says which, and holds an older run's ok.
|
|
105
|
+
const statusRecord = loaded.bundle.outcome === undefined
|
|
106
|
+
? await readRunJsonIfExists(preparedRunPaths, RUN_STATUS_FILE)
|
|
107
|
+
: undefined;
|
|
108
|
+
const observerData = buildObserverData(loaded.bundle, undefined, statusRecord);
|
|
103
109
|
observerData.publicSafety.share = {
|
|
104
110
|
status: verified.shareSafety.status,
|
|
105
111
|
verifiedAt: new Date().toISOString(),
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
2
|
+
import type { RunDisplay } from "../run/display.js";
|
|
2
3
|
import { type ObserverData } from "./data.js";
|
|
3
4
|
import { type PinnedDirectory } from "./pinned-files.js";
|
|
4
5
|
export interface ObserverRuntimeStreamUrl {
|
|
@@ -22,6 +23,7 @@ export declare function buildHistoryIndex(proofRoot: PinnedDirectory, admitRun?:
|
|
|
22
23
|
mode: string | null;
|
|
23
24
|
href: string;
|
|
24
25
|
status: string;
|
|
26
|
+
display?: RunDisplay;
|
|
25
27
|
runtimeState?: NonNullable<ObserverData["runtime"]>["state"];
|
|
26
28
|
streamCount: number;
|
|
27
29
|
estimatedCostUsd: number | null;
|
|
@@ -8,7 +8,7 @@ import { listRuns } from "../run/stored-runs.js";
|
|
|
8
8
|
import { readAnalysisAccounting } from "../run/costs.js";
|
|
9
9
|
import { bindExistingRunArtifactPaths, isPathInside, isSafeRunIdSegment, } from "../run/paths.js";
|
|
10
10
|
import { analysisCostOf, runCost, runCostLabel } from "../run/run-cost.js";
|
|
11
|
-
import { RUN_STATUS_FILE, RUN_STATUS_STALE_MS, isRunStatusRecord } from "../run/status.js";
|
|
11
|
+
import { RUN_STATUS_FILE, RUN_STATUS_STALE_MS, isRunStatusRecord, } from "../run/status.js";
|
|
12
12
|
import { renderObserverHtml } from "./artifact.js";
|
|
13
13
|
import { buildObserverData, recordedStreamEmbed, withObserverEndings, } from "./data.js";
|
|
14
14
|
import { buildArtifactSecurityHeaders } from "./http.js";
|
|
@@ -120,6 +120,7 @@ export async function serveRunPath(runRoot, relativePath, response, runtimeStrea
|
|
|
120
120
|
}
|
|
121
121
|
}
|
|
122
122
|
async function readObserverData(runRoot, runtimeStreamUrls = []) {
|
|
123
|
+
const record = await readLocalRunStatus(runRoot);
|
|
123
124
|
// Best-effort load from either source. Both reads swallow all errors on
|
|
124
125
|
// purpose: this runs on every browser poll of a live run, where run.json may
|
|
125
126
|
// be absent, still being written (a partial-JSON parse error), or superseded
|
|
@@ -130,57 +131,64 @@ async function readObserverData(runRoot, runtimeStreamUrls = []) {
|
|
|
130
131
|
if (!bundleBytes)
|
|
131
132
|
throw new Error("run.json unavailable");
|
|
132
133
|
const bundle = JSON.parse(bundleBytes.toString("utf8"));
|
|
133
|
-
return withRuntimeStreamUrls(
|
|
134
|
+
return withRuntimeStreamUrls(withLocalRunStatus(record, buildObserverData(bundle, undefined, record)), runtimeStreamUrls);
|
|
134
135
|
}
|
|
135
136
|
catch { }
|
|
136
137
|
try {
|
|
137
138
|
const observerBytes = await readContainedFile(runRoot, path.join(runRoot.physicalPath, "observer", "observer-data.json"));
|
|
138
139
|
if (!observerBytes)
|
|
139
140
|
throw new Error("observer-data.json unavailable");
|
|
140
|
-
return withRuntimeStreamUrls(
|
|
141
|
+
return withRuntimeStreamUrls(withLocalRunStatus(record, withObserverEndings(JSON.parse(observerBytes.toString("utf8")))), runtimeStreamUrls);
|
|
141
142
|
}
|
|
142
143
|
catch { }
|
|
143
144
|
return null;
|
|
144
145
|
}
|
|
145
|
-
/**
|
|
146
|
-
|
|
147
|
-
* A stale heartbeat means unknown: neither an old timestamp nor a persisted PID proves that a
|
|
148
|
-
* process died (the evidence may have been copied from another machine). No PID is served/probed.
|
|
149
|
-
*/
|
|
150
|
-
async function withLocalRunStatus(runRoot, input) {
|
|
151
|
-
// A served observation must never be inherited from a persisted projection or export.
|
|
152
|
-
const { runtime: _persistedRuntime, ...data } = input;
|
|
146
|
+
/** The run directory's own status record, when it is well formed and names that directory. */
|
|
147
|
+
async function readLocalRunStatus(runRoot) {
|
|
153
148
|
try {
|
|
154
149
|
const bytes = await readContainedFile(runRoot, path.join(runRoot.physicalPath, RUN_STATUS_FILE));
|
|
155
150
|
if (!bytes)
|
|
156
|
-
return
|
|
151
|
+
return undefined;
|
|
157
152
|
const record = JSON.parse(bytes.toString("utf8"));
|
|
158
|
-
|
|
159
|
-
record
|
|
160
|
-
|
|
161
|
-
record.runId !== path.basename(runRoot.physicalPath))
|
|
162
|
-
return data;
|
|
163
|
-
const now = Date.now();
|
|
164
|
-
const started = Date.parse(record.startedAt);
|
|
165
|
-
const updated = Date.parse(record.updatedAt);
|
|
166
|
-
const timestampsValid = Number.isFinite(started) && Number.isFinite(updated) && started <= updated && updated <= now;
|
|
167
|
-
let state = "unknown";
|
|
168
|
-
if (timestampsValid) {
|
|
169
|
-
if (record.state === "finished") {
|
|
170
|
-
state = "finished";
|
|
171
|
-
}
|
|
172
|
-
else if (record.state === "running" && now - updated <= RUN_STATUS_STALE_MS) {
|
|
173
|
-
state = "running";
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
return {
|
|
177
|
-
...data,
|
|
178
|
-
runtime: { state, observedAt: new Date(now).toISOString(), source: "local-run-status" },
|
|
179
|
-
};
|
|
153
|
+
return isRunStatusRecord(record) && record.runId === path.basename(runRoot.physicalPath)
|
|
154
|
+
? record
|
|
155
|
+
: undefined;
|
|
180
156
|
}
|
|
181
157
|
catch {
|
|
158
|
+
return undefined;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Liveness is a current read of a contained local status record, separate from run evidence.
|
|
163
|
+
* A stale heartbeat means unknown: neither an old timestamp nor a persisted PID proves that a
|
|
164
|
+
* process died (the evidence may have been copied from another machine). A record its stopped
|
|
165
|
+
* process wrote is interrupted. No PID is served/probed.
|
|
166
|
+
*/
|
|
167
|
+
function withLocalRunStatus(record, input) {
|
|
168
|
+
// A served observation must never be inherited from a persisted projection or export.
|
|
169
|
+
const { runtime: _persistedRuntime, ...data } = input;
|
|
170
|
+
if (record === undefined || record.runId !== data.run.runId || record.mode !== data.run.mode)
|
|
182
171
|
return data;
|
|
172
|
+
const now = Date.now();
|
|
173
|
+
const started = Date.parse(record.startedAt);
|
|
174
|
+
const updated = Date.parse(record.updatedAt);
|
|
175
|
+
const timestampsValid = Number.isFinite(started) && Number.isFinite(updated) && started <= updated && updated <= now;
|
|
176
|
+
let state = "unknown";
|
|
177
|
+
if (timestampsValid) {
|
|
178
|
+
if (record.state === "finished") {
|
|
179
|
+
state = "finished";
|
|
180
|
+
}
|
|
181
|
+
else if (record.state === "interrupted") {
|
|
182
|
+
state = "interrupted";
|
|
183
|
+
}
|
|
184
|
+
else if (record.state === "running" && now - updated <= RUN_STATUS_STALE_MS) {
|
|
185
|
+
state = "running";
|
|
186
|
+
}
|
|
183
187
|
}
|
|
188
|
+
return {
|
|
189
|
+
...data,
|
|
190
|
+
runtime: { state, observedAt: new Date(now).toISOString(), source: "local-run-status" },
|
|
191
|
+
};
|
|
184
192
|
}
|
|
185
193
|
/** internal: exported for the stream lifecycle tests. */
|
|
186
194
|
export function withRuntimeStreamUrls(data, runtimeStreamUrls) {
|
|
@@ -249,6 +257,7 @@ admitRun) {
|
|
|
249
257
|
mode: admitRun ? (data?.run.mode ?? null) : run.mode,
|
|
250
258
|
href: `/_humanish/runs/${encodeURIComponent(run.runId)}/observer/index.html`,
|
|
251
259
|
status: data?.run.status ?? "unknown",
|
|
260
|
+
...(data?.run.display === undefined ? {} : { display: data.run.display }),
|
|
252
261
|
...(data?.runtime ? { runtimeState: data.runtime.state } : {}),
|
|
253
262
|
streamCount: data?.streams.length ?? 0,
|
|
254
263
|
// Labeled run-total cost estimate (advisory; null when the run carries no cost summary).
|