humanish 0.123.0 → 0.124.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 +13 -0
- package/CONTEXT.md +1 -1
- package/dist/actors/computer-use/loop/trace.js +6 -1
- package/dist/actors/computer-use/openai-conversation.d.ts +0 -6
- package/dist/actors/computer-use/openai-conversation.js +0 -8
- package/dist/actors/computer-use/openai-provider.js +5 -8
- package/dist/evidence/image.js +82 -3
- package/dist/feedback/export-bundle.js +1 -5
- package/dist/feedback/export.js +30 -11
- package/dist/observer/artifact.js +2 -9
- package/dist/observer/data.d.ts +9 -2
- package/dist/observer/data.js +17 -2
- package/dist/observer/page-data.d.ts +5 -0
- package/dist/observer/page-data.js +21 -0
- package/dist/observer/participant-items.d.ts +45 -0
- package/dist/observer/participant-items.js +85 -0
- package/dist/observer/render.js +2 -1
- package/dist/observer/run-routes.js +14 -4
- package/dist/observer-app.html +4 -4
- package/dist/run/run.js +2 -1
- package/dist/study/plan.js +20 -0
- package/docs/architecture/observer.md +24 -5
- package/docs/contracts/run-bundle.md +3 -1
- package/docs/contracts/study-analysis.md +1 -1
- package/docs/decisions/0002-observer-is-one-self-contained-file.md +2 -1
- package/package.json +2 -2
package/dist/run/run.js
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import { randomBytes } from "node:crypto";
|
|
6
6
|
import { redactText } from "../evidence/redaction.js";
|
|
7
7
|
import { buildObserverData } from "../observer/data.js";
|
|
8
|
+
import { splitObserverData } from "../observer/participant-items.js";
|
|
8
9
|
import { renderObserver } from "../observer/render.js";
|
|
9
10
|
import { RUN_BUNDLE_FILE, PUBLIC_TARGET_CWD, buildRunSource, } from "./bundle.js";
|
|
10
11
|
import { judgeExecution, } from "./judge.js";
|
|
@@ -187,7 +188,7 @@ function runPublisher(args) {
|
|
|
187
188
|
await writeContainedOutputFile(paths, "review.md", options.renderReview(publicBundle, status), "utf8");
|
|
188
189
|
const events = publicBundle.events.map((event) => JSON.stringify(event)).join("\n");
|
|
189
190
|
await writeContainedOutputFile(paths, "events.ndjson", `${events}\n`, "utf8");
|
|
190
|
-
await writeContainedOutputFile(paths, "observer/observer-data.json", json(buildObserverData(publicBundle, undefined, status)), "utf8");
|
|
191
|
+
await writeContainedOutputFile(paths, "observer/observer-data.json", json(splitObserverData(buildObserverData(publicBundle, undefined, status)).shell), "utf8");
|
|
191
192
|
};
|
|
192
193
|
const snapshot = async (bundle) => {
|
|
193
194
|
await writeBundleFiles(bundle, undefined, async () => { });
|
package/dist/study/plan.js
CHANGED
|
@@ -15,6 +15,7 @@ import { routeOf } from "./routing.js";
|
|
|
15
15
|
import { automaticAnalysisRouteReason, taskProtocolValidationReason } from "./validation.js";
|
|
16
16
|
import { declaredParticipantCount } from "./study-fields.js";
|
|
17
17
|
import { recordedStudyWarnings } from "./warnings.js";
|
|
18
|
+
import { plural } from "../run/text.js";
|
|
18
19
|
export { routeOf } from "./routing.js";
|
|
19
20
|
/** Resolve dry-run: explicit override wins, else the scenario mode, else the given fallback. */
|
|
20
21
|
export function resolveStudyDryRun(config, override, fallback) {
|
|
@@ -85,10 +86,12 @@ export function planStudy(config, options, deps = {}) {
|
|
|
85
86
|
const bundle = plannedBundle(result.plan);
|
|
86
87
|
// The manifest the CLI resolved enters the plan here and nowhere else; the routes read
|
|
87
88
|
// plan.study for the run's status record and bundle, and plan.warnings for its bundle events.
|
|
89
|
+
const closing = closingReportWarning(result.plan);
|
|
88
90
|
const warnings = [
|
|
89
91
|
...recordedStudyWarnings(study),
|
|
90
92
|
...(result.plan.warnings ?? []),
|
|
91
93
|
...(bundle.warning === undefined ? [] : [bundle.warning]),
|
|
94
|
+
...(closing === undefined ? [] : [closing]),
|
|
92
95
|
];
|
|
93
96
|
const plan = {
|
|
94
97
|
...result.plan,
|
|
@@ -111,6 +114,23 @@ function plannedBundle(plan) {
|
|
|
111
114
|
const warning = plan.dryRun ? undefined : bundleLimitReason(estimate);
|
|
112
115
|
return warning === undefined ? { estimate } : { estimate, warning };
|
|
113
116
|
}
|
|
117
|
+
/**
|
|
118
|
+
* The warning for participants with a scheduled end on Claude as a local-agent participant model.
|
|
119
|
+
* Its session has no read-only closing request, so each such participant ends with the scheduled
|
|
120
|
+
* end as its reason and no account of its session.
|
|
121
|
+
*/
|
|
122
|
+
function closingReportWarning(plan) {
|
|
123
|
+
if (plan.route !== "computer-use")
|
|
124
|
+
return undefined;
|
|
125
|
+
const { brain } = plan.runner;
|
|
126
|
+
if (brain.kind !== "local-agent" || brain.agent !== "claude")
|
|
127
|
+
return undefined;
|
|
128
|
+
const scheduled = plan.runner.participants.filter((participant) => participant.endAfterMs !== undefined).length;
|
|
129
|
+
if (scheduled === 0)
|
|
130
|
+
return undefined;
|
|
131
|
+
const subject = scheduled === 1 ? "it ends" : "each ends";
|
|
132
|
+
return `${plural(scheduled, "participant")} ${scheduled === 1 ? "has" : "have"} a scheduled end (participants[].endAfterMs), and Claude as a local-agent participant model cannot be asked for a closing report, so ${subject} with the scheduled end as its reason and no closing account. A computer-use model (actor.type: openai-computer-use) or Codex (actor.localAgent: codex) writes one.`;
|
|
133
|
+
}
|
|
114
134
|
function planRoute(route, study, options, input, deps, e2b) {
|
|
115
135
|
const { sandboxCeiling } = e2b;
|
|
116
136
|
switch (route) {
|
|
@@ -24,9 +24,26 @@ Observer commands may add derived artifacts:
|
|
|
24
24
|
observer-data.json
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
-
`run.json` remains the source bundle. `observer/observer-data.json`
|
|
28
|
-
normalized view model consumed by the Observer
|
|
29
|
-
|
|
27
|
+
`run.json` remains the source bundle. `observer/observer-data.json`
|
|
28
|
+
(`humanish.observer-data.v2`) is the normalized view model consumed by the Observer,
|
|
29
|
+
with every participant except their trace items and the screenshot entries of their
|
|
30
|
+
artifact list. A participant working for hours records thousands of items and a
|
|
31
|
+
screenshot each turn, so these are most of a long run's bytes; apart, the saved file
|
|
32
|
+
stays small enough for `verify` to read. The items stay in the run's traces
|
|
33
|
+
(`actors/<stream>.json`). `events.ndjson` is the appendable event stream
|
|
34
|
+
contract that live adapters update while a run is active.
|
|
35
|
+
|
|
36
|
+
`observer/index.html` carries both parts: the data slot holds observer-data.json's
|
|
37
|
+
content, and `<script id="observer-items" type="application/octet-stream"
|
|
38
|
+
data-encoding="gzip">` holds the items and full artifact lists (`humanish.observer-items.v1`, by stream id)
|
|
39
|
+
gzip-compressed in base64, which a `file://` page decodes without a fetch. Real
|
|
40
|
+
trace items compress about eight times. The page joins the two before it renders
|
|
41
|
+
(`joinObserverData` in `src/observer/participant-items.ts`), so every view reads the
|
|
42
|
+
same data as before. A stream whose screenshot entries moved records how many in
|
|
43
|
+
`screenshotArtifacts`, and the page renders nothing from items that are another
|
|
44
|
+
run's or miss a participant's items or screenshot entries. The server answers a
|
|
45
|
+
saved v2 observer-data.json that leaves items out as unavailable, since it has no
|
|
46
|
+
items to join.
|
|
30
47
|
|
|
31
48
|
## Stream Model
|
|
32
49
|
|
|
@@ -55,7 +72,9 @@ public-safe metadata.
|
|
|
55
72
|
4. opens the served Observer URL;
|
|
56
73
|
5. keeps the shell attached until Ctrl-C.
|
|
57
74
|
|
|
58
|
-
The browser polls `observer-
|
|
75
|
+
The browser polls `observer-feed.json` with `no-store` caching: the server's
|
|
76
|
+
projection of the run as `{ data, items }`, observer-data.json's content and the
|
|
77
|
+
items, from one read of the run per poll. Static
|
|
59
78
|
`file://` opening still works for immutable review, but follow mode is the
|
|
60
79
|
operator path. Agents and CI should use `humanish watch --json --no-open` for
|
|
61
80
|
the same fresh evidence without browser open or a long-running process.
|
|
@@ -253,7 +272,7 @@ These remain adapter work:
|
|
|
253
272
|
## The rendering layer
|
|
254
273
|
|
|
255
274
|
The renderer is the `observer/` workspace: a Vite single-file build on the
|
|
256
|
-
`@humanish` registry tokens, frozen against `humanish.observer-data.
|
|
275
|
+
`@humanish` registry tokens, frozen against `humanish.observer-data.v2`
|
|
257
276
|
(`tests/observer/data-contract.test.ts`). The root build copies the workspace
|
|
258
277
|
artifact to `dist/observer-app.html`; in a repo checkout a missing or stale
|
|
259
278
|
artifact auto-builds, and an unconditional preflight at CLI startup makes a
|
|
@@ -77,7 +77,9 @@ used as a bundle answers 404 with the reason, never the saved projection. In saf
|
|
|
77
77
|
(`observe --all --safe`) every read is checked against the files admitted with the run's
|
|
78
78
|
share_ready verification, so a run.json changed after admission is refused and the admitted
|
|
79
79
|
projection is served.
|
|
80
|
-
observer-data.json is built from the loaded bundle
|
|
80
|
+
observer-data.json is built from the loaded bundle. From 0.124.0 it is
|
|
81
|
+
`humanish.observer-data.v2`: the same data without each participant's trace items, which stay in
|
|
82
|
+
the traces (docs/architecture/observer.md).
|
|
81
83
|
|
|
82
84
|
Compatibility: humanish 0.122.0 and earlier read only v1 and refuse a v2 run.json by its schema
|
|
83
85
|
(`run schema` fails in verify, analysis refuses the source). This release reads v1 bundles as
|
|
@@ -367,7 +367,7 @@ and an impression alone supports only a finding about what the participant said.
|
|
|
367
367
|
|
|
368
368
|
## Durable records
|
|
369
369
|
|
|
370
|
-
The
|
|
370
|
+
The `humanish.observer-data.v2` schema is unchanged by analysis. A companion
|
|
371
371
|
`humanish.study-analysis.v1` artifact records source/config/input hashes,
|
|
372
372
|
participant context, evidence manifest, coverage, provider/model/prompt version,
|
|
373
373
|
status, usage and validated findings. The Observer's projection of it,
|
|
@@ -13,7 +13,8 @@ exactly those cases.
|
|
|
13
13
|
The `observer/` workspace builds with Vite into a single HTML file with fonts inlined and no
|
|
14
14
|
network references. The root build copies it to `dist/observer-app.html`. `renderObserverHtml`
|
|
15
15
|
is the one path every surface (observe, observe --all, watch, studies) uses; it injects the run's
|
|
16
|
-
`humanish.observer-data.
|
|
16
|
+
`humanish.observer-data.v2` snapshot into that file, with the participants' trace items beside it
|
|
17
|
+
gzip-compressed (docs/architecture/observer.md). There is no second renderer and no feature
|
|
17
18
|
flag; rolling back means pinning an older package version.
|
|
18
19
|
|
|
19
20
|
## Consequences
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "humanish",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.124.0",
|
|
4
4
|
"description": "Synthetic user research for apps, CLIs, and agent-facing product flows.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
@@ -94,7 +94,7 @@
|
|
|
94
94
|
"comms:agentmail:contract": "node --import tsx scripts/agentmail-contract-check.mjs",
|
|
95
95
|
"format": "oxfmt",
|
|
96
96
|
"format:check": "oxfmt --check",
|
|
97
|
-
"lint": "node scripts/check-lint-cap.mjs --max-warnings=
|
|
97
|
+
"lint": "node scripts/check-lint-cap.mjs --max-warnings=424",
|
|
98
98
|
"knip": "knip",
|
|
99
99
|
"prose:check": "node scripts/check-code-prose.mjs",
|
|
100
100
|
"vocabulary:check": "tsx scripts/check-retired-words.ts",
|