humanish 0.145.0 → 0.147.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.
Files changed (83) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/actors/computer-use/loop/spend.js +5 -4
  3. package/dist/actors/computer-use/loop/trace.js +3 -0
  4. package/dist/actors/computer-use/loop/types.d.ts +5 -0
  5. package/dist/actors/computer-use/loop/usage.js +10 -2
  6. package/dist/actors/computer-use/openai-conversation.d.ts +7 -0
  7. package/dist/actors/computer-use/openai-conversation.js +19 -2
  8. package/dist/actors/computer-use/openai-provider.d.ts +2 -0
  9. package/dist/actors/computer-use/openai-provider.js +2 -0
  10. package/dist/actors/computer-use/openai-wire.d.ts +4 -0
  11. package/dist/actors/computer-use/openai-wire.js +9 -1
  12. package/dist/actors/contract.d.ts +5 -0
  13. package/dist/analysis/admission.d.ts +8 -3
  14. package/dist/analysis/admission.js +7 -3
  15. package/dist/analysis/automatic-config.js +2 -1
  16. package/dist/analysis/automatic.js +2 -2
  17. package/dist/analysis/evidence.js +8 -4
  18. package/dist/analysis/execute.d.ts +7 -10
  19. package/dist/analysis/execute.js +79 -49
  20. package/dist/analysis/image-tokens.js +9 -3
  21. package/dist/analysis/output-limit.d.ts +12 -0
  22. package/dist/analysis/output-limit.js +34 -0
  23. package/dist/analysis/output-retry.d.ts +20 -0
  24. package/dist/analysis/output-retry.js +63 -0
  25. package/dist/analysis/provider.d.ts +1 -1
  26. package/dist/analysis/provider.js +3 -3
  27. package/dist/analysis/responses.js +1 -1
  28. package/dist/analysis/service.js +2 -2
  29. package/dist/cli/commands/analyze.js +1 -1
  30. package/dist/cli/io.js +2 -0
  31. package/dist/cli/run-findings.js +10 -2
  32. package/dist/evidence/image.d.ts +2 -0
  33. package/dist/evidence/image.js +24 -3
  34. package/dist/evidence/webp-encode-worker.d.ts +1 -0
  35. package/dist/evidence/webp-encode-worker.js +31 -0
  36. package/dist/evidence/webp-transcoder.d.ts +15 -0
  37. package/dist/evidence/webp-transcoder.js +98 -0
  38. package/dist/evidence/webp.d.ts +31 -0
  39. package/dist/evidence/webp.js +94 -0
  40. package/dist/feedback/derivative-text.d.ts +7 -2
  41. package/dist/feedback/derivative-text.js +20 -1
  42. package/dist/feedback/export-bundle.js +79 -25
  43. package/dist/observer-app.html +1 -1
  44. package/dist/remote/launch.js +93 -48
  45. package/dist/remote/runner.d.ts +47 -14
  46. package/dist/remote/runner.js +199 -64
  47. package/dist/routes/computer-use/e2b-desktop/desktop.js +47 -7
  48. package/dist/routes/computer-use/e2b-desktop/prepare.d.ts +4 -2
  49. package/dist/routes/computer-use/e2b-desktop/prepare.js +4 -2
  50. package/dist/routes/computer-use/e2b-desktop/start.d.ts +14 -6
  51. package/dist/routes/computer-use/e2b-desktop/start.js +72 -34
  52. package/dist/routes/computer-use/participant-execution.d.ts +0 -7
  53. package/dist/routes/computer-use/participant-execution.js +6 -28
  54. package/dist/routes/computer-use/participant-frames.d.ts +32 -0
  55. package/dist/routes/computer-use/participant-frames.js +93 -0
  56. package/dist/routes/computer-use/participant-model.js +3 -0
  57. package/dist/routes/computer-use/participant-runs.js +4 -0
  58. package/dist/routes/computer-use/plan.js +5 -1
  59. package/dist/routes/computer-use/result.js +6 -0
  60. package/dist/routes/computer-use/types.d.ts +4 -0
  61. package/dist/routes/shared-world/plan.js +4 -1
  62. package/dist/run/pricing.d.ts +7 -0
  63. package/dist/run/pricing.js +58 -15
  64. package/dist/study/config.js +4 -1
  65. package/dist/study/keys.d.ts +1 -0
  66. package/dist/study/keys.js +1 -0
  67. package/dist/study/parse/actors.js +5 -0
  68. package/dist/study/plan-participants.d.ts +2 -0
  69. package/dist/study/plan-participants.js +2 -0
  70. package/dist/study/types.d.ts +7 -0
  71. package/dist/study/validation.d.ts +5 -0
  72. package/dist/study/validation.js +23 -0
  73. package/dist/substrates/e2b/cdp-probe.d.ts +16 -1
  74. package/dist/substrates/e2b/cdp-probe.js +67 -5
  75. package/dist/substrates/e2b/desktop-browser.js +4 -2
  76. package/dist/substrates/e2b/desktop-cdp.d.ts +9 -2
  77. package/dist/substrates/e2b/desktop-cdp.js +26 -4
  78. package/dist/verify/artifacts.js +2 -1
  79. package/docs/contracts/run-bundle.md +29 -11
  80. package/docs/contracts/schemas.md +20 -12
  81. package/docs/contracts/study-analysis.md +64 -11
  82. package/docs/product/automatic-analysis.md +9 -6
  83. package/package.json +6 -5
@@ -76,17 +76,17 @@ map each one to its v3 key.
76
76
  A study declares its route and composes code primitives; it is not a hardcoded kind. The
77
77
  top-level keys:
78
78
 
79
- | Key | Meaning |
80
- | ----------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
81
- | `schema`, `id`, `title`, `description` | the document's identity |
82
- | `route` | required: `preview`, `computer-use`, `shared-world`, `terminal` or `scripted` |
83
- | `mode` | `dry-run` (the default) or `live` |
84
- | `actor` | who drives it, one object: `type`, `model`, `localAgent`, `persona`, `mission`, `tasks`, `maxOutputTokens`, `maxWaitMs`, `idleWaitMs`, `reasoningEffort`, `stopWhen`, `dwell` |
85
- | `participants` | a count, a homogeneous `{ count, instruction }`, or a list of entries (below) |
86
- | `surfaces` | scripted only: `[desktop]` or `[desktop, mobile]` |
87
- | `caps` | the route's budget (below) |
88
- | `scenario` | scripted only: a committed scenario id or path |
89
- | `subject`, `execution`, `policies`, `review`, `defaults`, `comms` | as below |
79
+ | Key | Meaning |
80
+ | ----------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
81
+ | `schema`, `id`, `title`, `description` | the document's identity |
82
+ | `route` | required: `preview`, `computer-use`, `shared-world`, `terminal` or `scripted` |
83
+ | `mode` | `dry-run` (the default) or `live` |
84
+ | `actor` | who drives it, one object: `type`, `model`, `localAgent`, `persona`, `mission`, `tasks`, `maxOutputTokens`, `maxWaitMs`, `idleWaitMs`, `reasoningEffort`, `serviceTier`, `stopWhen`, `dwell` |
85
+ | `participants` | a count, a homogeneous `{ count, instruction }`, or a list of entries (below) |
86
+ | `surfaces` | scripted only: `[desktop]` or `[desktop, mobile]` |
87
+ | `caps` | the route's budget (below) |
88
+ | `scenario` | scripted only: a committed scenario id or path |
89
+ | `subject`, `execution`, `policies`, `review`, `defaults`, `comms` | as below |
90
90
 
91
91
  The parser reads only the declared route's keys. A key that route never reads is an error that
92
92
  names the route, such as "route: computer-use does not read scenario. Remove it.", and an
@@ -212,7 +212,7 @@ The rest of this section names keys by their v3 spelling:
212
212
  browser target; `entry` is a shared-world participant's same-origin path;
213
213
  - `participants[].files` (computer-use on `execution.target: e2b-desktop` only):
214
214
  1 to 20 `{ from, as }` entries, each a file copied onto that participant's desktop
215
- before its browser opens. `from` is relative to the folder that holds the study file
215
+ before its session starts. `from` is relative to the folder that holds the study file
216
216
  (`cwd` for a library config); `as` is relative to the desktop user's home folder.
217
217
  The parser refuses an absolute path, a `.`, `..` or empty part, a backslash, an `as`
218
218
  that starts with `~`, lands in `subject/` or on a name starting with `.humanish`, looks
@@ -1148,6 +1148,14 @@ Core-owned fields:
1148
1148
  is part of who the participant was rather than of how the instrument was tuned
1149
1149
  (docs/principles/actor-fidelity.md), so a trace without it is a result missing
1150
1150
  half its sample description
1151
+ - optional `modelSettings.serviceTier`: `fast` when the study declared
1152
+ `actor.serviceTier: fast`, so every first-party OpenAI CUA request carried
1153
+ `service_tier: "fast"` (OpenAI Fast mode). Absent when undeclared. Each
1154
+ `tokenUsage.turns[]` record of such a trace has `serviceTier`, the tier the
1155
+ response says served it: `priority` or `fast` bill at the model's Fast mode rate
1156
+ in `src/run/pricing.ts`, and `default`, which OpenAI serves when Fast mode
1157
+ traffic ramps too fast, bills at the standard rate. `estimatedCost.breakdown.fastTurns`
1158
+ counts the requests priced at the fast rate.
1151
1159
  - optional `modelSettings.maxOutputTokens`: the declared positive integer
1152
1160
  `actor.maxOutputTokens`, passed to every first-party OpenAI CUA response
1153
1161
  request, including reasoning output. Absent when undeclared. The first request
@@ -27,8 +27,10 @@ cap; a refused dry run says why, and names the `--max-cost` that admits it.
27
27
 
28
28
  The default provider is `openai`; its default model is `gpt-6.1-sol`, at medium reasoning effort
29
29
  ([reasoning effort](#reasoning-effort)). A request sends selected retained text and
30
- captures to OpenAI, without tools, redirects, provider-side response storage, or
31
- automatic retries. `--question` adds a reviewer question; it never changes the
30
+ captures to OpenAI, without tools, redirects or provider-side response storage. A request that
31
+ runs out of output is sent once more while the cap admits it
32
+ ([a request that runs out of output](#a-request-that-runs-out-of-output)); no other failure is
33
+ sent again. `--question` adds a reviewer question; it never changes the
32
34
  participant assignment. For OpenAI API analysis, `--max-cost` is required, including for dry-run
33
35
  admission. Admission refuses the request when both its worst case and its expected cost plus a
34
36
  10% margin are over it; the provider bill is not limited by it.
@@ -60,12 +62,39 @@ times for those billed $1 or more.
60
62
  A refusal's message gives the expected cost, the worst case, the cap, and
61
63
  `humanish analyze --run <id> --max-cost <n>` with `n` the worst case rounded up.
62
64
 
63
- The default deadline is ten minutes for each request. With no explicit output-token limit, analysis
64
- uses 32,768 tokens if admission fits the declared budget, or retains the prior
65
- 16,384-token allowance otherwise. Explicit limits are never adjusted. Selection
66
- happens before dispatch; `admission.outputTokenAllowance` exposes it in dry-run,
67
- and the saved configuration, digest and automatic job bind the selected allowance.
68
- This selection never increases the spending limit or starts a retry.
65
+ The default deadline is ten minutes for each request. With no explicit output-token limit,
66
+ `src/analysis/output-limit.ts` sizes the allowance to the packet. An OpenAI analysis at none, low
67
+ or medium effort of up to 16 participants gets 12,288 tokens plus 2,048 per participant, at most
68
+ 32,768: 14,336 for one participant and 18,432 for three. A high-effort analysis, a Gemini
69
+ analysis and a run analysed in cohorts get 32,768. If admission refuses an allowance above
70
+ 16,384 under the declared budget, the analysis keeps 16,384. Explicit limits are never adjusted.
71
+ Selection happens before dispatch; `admission.outputTokenAllowance` exposes it in dry-run, and
72
+ the saved configuration, digest and automatic job bind the selected allowance. This selection
73
+ never increases the spending limit.
74
+
75
+ The sizes come from the finished reports on the 2026-10-22 and 2026-10-23 benchmark recordings:
76
+ the Taskly analyses listed in `docs/evidence/benchmark/2026-10-2*.json`, one participant with 8 to
77
+ 14 captures, and the movie-game analyses of
78
+ [analysis models on fixed recordings](https://github.com/danielgwilson/humanish/blob/main/docs/evidence/benchmark/2026-10-22-analysis-models.md), three
79
+ participants with 40 to 49 captures. Each analysis's output tokens are read from its retained
80
+ artifact.
81
+
82
+ | Analyst and effort | One participant: passed, most output | Three participants: passed, most output |
83
+ | -------------------- | ------------------------------------ | --------------------------------------- |
84
+ | `gpt-6.1-sol` low | 24, 4,308 | 6, 6,391 |
85
+ | `gpt-6.1-sol` medium | 142, 5,659 | 36, 9,000 |
86
+ | `gpt-6-luna` medium | 27, 8,354 | 2, 11,313 |
87
+ | `gpt-6.1-sol` high | 22, 10,086 | 6, 15,797 |
88
+ | `gpt-6-luna` high | 78, 19,880 | 9, 26,439 |
89
+ | `gemini-3.8-flash` | 23, 29,739 | 1, 26,154 |
90
+
91
+ At low and medium effort the sized limit is 1.7 times the most output of a finished report of
92
+ one participant and 1.6 times that of three; for `gpt-6.1-sol` at medium it is 2.5 and 2.0 times.
93
+ At high effort a finished `gpt-6-luna` report of three participants used 26,439 tokens, so 32,768
94
+ has no room to lower. A `gpt-6.1-sol` analysis at medium that ran out of output on a
95
+ one-participant run had used all 32,768 tokens in 374 seconds and cost $0.39; at 14,336 tokens the
96
+ same request stops at 44% of that output.
97
+
69
98
  The configured wall-clock deadline covers the entire request, including waiting
70
99
  for response headers and reading the body. A request-scoped dispatcher prevents
71
100
  Node's separate fetch timeout from cutting a longer configured deadline short;
@@ -77,6 +106,29 @@ success. Findings keep reported concerns and observed recovery distinct across
77
106
  participants. Other supported models can be selected explicitly, but evidence
78
107
  reference validation does not certify their interpretation of small visual details.
79
108
 
109
+ ## A request that runs out of output
110
+
111
+ When an OpenAI or Gemini request ends with `output_incomplete`, humanish sends the same request
112
+ once more, with a fresh deadline. It does so only when the spend so far, plus what admission
113
+ holds for the attempt's requests still running and admission's figure for one more request (its
114
+ expected cost plus 10%, or its worst case when that is lower), is within `maxCostUsd`. The spend
115
+ so far counts every response of the attempt, the one that ran out included. When a response did
116
+ not report its usage, the spend is unknown and the request is not sent again. A request is sent
117
+ again at most once; when the second one also runs out, the attempt fails with
118
+ `analysis_output_incomplete`. A cohort request and the merge request are each sent again the same
119
+ way. Codex account analysis has no dollar cap to check and is never sent again. A timeout, an HTTP
120
+ error and a rejected report are not sent again: a timed-out request has already used the
121
+ ten-minute deadline.
122
+
123
+ The attempt keeps one execution start, one receipt and one `analysis.json`. Their `usage` is the
124
+ sum of every response, both requests of a retry included, and `estimatedCostUsd` prices each
125
+ response as its own request. The schemas are unchanged. A warning in `warnings` (and in the human
126
+ output of `analyze` and of a live run, under its `analysis:` line) names the request, the input
127
+ and output tokens and the cost of the response that ran out, and says whether humanish sent it
128
+ again; a refused retry gives the spend, the held amount and the cap. The result is partial with
129
+ `analysis_admission_estimate_exceeded` only when the bill passes admission's worst case plus the
130
+ worst case of each request sent again, or the cap.
131
+
80
132
  ## Runs with more than 16 participants
81
133
 
82
134
  One analysis covers up to 128 participants, the most streams it reads from a run
@@ -104,7 +156,8 @@ whole packet as a single request's report does.
104
156
  The attempt has one execution start, one receipt and one `analysis.json`, with the
105
157
  run's participants, coverage and evidence and the summed usage of every request
106
158
  sent. The artifact schema is unchanged. Its stored limits grew to hold eight
107
- cohorts: 6,400 evidence items, 320 captures and 16 MiB. If a cohort request fails
159
+ cohorts: 6,400 evidence items, 320 captures and 16 MiB. A cohort request or the merge request that
160
+ runs out of output is sent once more under the rule above. If a cohort request fails
108
161
  or is rejected, no further request starts, requests already sent finish, no merge
109
162
  request is sent and the attempt fails with that request's code, with no findings;
110
163
  a warning names the cohort's size. A failed merge request fails the attempt the same way. The usage
@@ -261,8 +314,8 @@ stopped, an operator can remove the empty lock directory and retry.
261
314
 
262
315
  ## Evidence and findings
263
316
 
264
- Each request's packet admits up to 16 participants, 800 evidence items, 40 PNG
265
- captures, 160 KiB of text and 20 MiB of images. Individual source files, image
317
+ Each request's packet admits up to 16 participants, 800 evidence items, 40
318
+ captures (PNG or lossless WebP), 160 KiB of text and 20 MiB of images. Individual source files, image
266
319
  dimensions and result sizes have separate limits. Analysis reads run.json up to
267
320
  16 MiB and each participant's trace up to 32 MiB, as verify and the Observer do.
268
321
  It reads the traces one at a time and keeps of each only what selection can
@@ -16,15 +16,17 @@ expected cost and a 600-second timeout. A study or command that names a model bu
16
16
  that model at high; only the default analyst, with no model named, runs at medium. On the same
17
17
  recordings it matched `gpt-6-astra` at high, the earlier default, at about one seventh of the cost
18
18
  ([analysis models on fixed recordings](https://github.com/danielgwilson/humanish/blob/main/docs/evidence/benchmark/2026-10-22-analysis-models.md)). When no output limit is specified,
19
- humanish selects 32,768 tokens if the exact input's expected cost still fits that
20
- cap; otherwise it keeps the established 16,384-token allowance. This preserves
21
- previously admitted studies without increasing their spending limit. To customize it:
19
+ humanish sizes it to the analysis: at low or medium effort, 12,288 tokens plus 2,048 per
20
+ participant (14,336 for one), and 32,768 at high effort, on Gemini and past 16 participants. An
21
+ allowance above 16,384 that the cap would refuse falls back to 16,384, so a study its cap admitted
22
+ before stays admitted ([output limit](../contracts/study-analysis.md#invocation)). A
23
+ request that runs out of output is sent once more while the cap admits it. To customize it:
22
24
 
23
25
  ```yaml
24
26
  review:
25
27
  analysis:
26
28
  maxCostUsd: 10
27
- # Optional overrides. Omit maxOutputTokens for budget-aware selection.
29
+ # Optional overrides. Omit maxOutputTokens for a limit sized to the analysis.
28
30
  # A named model without reasoningEffort runs at high.
29
31
  model: gpt-6.1-sol
30
32
  reasoningEffort: medium
@@ -57,8 +59,9 @@ effort; on 24 Taskly analyses `gpt-6.1-sol` at medium wrote a mean 3,747 and cos
57
59
  evidence to inspect the expected cost, the worst case and the selected token
58
60
  allowance before deliberately choosing a larger budget. Explicit
59
61
  `maxOutputTokens` and `--max-output-tokens` limits are honored exactly. The output allowance
60
- includes reasoning as well as the report; exhausting it does not produce a usable
61
- report and never starts an automatic retry. Analysis
62
+ includes reasoning as well as the report; a request that exhausts it has no usable report. It
63
+ is sent once more when the spend so far and admission's figure for one more request fit the cap,
64
+ and the CLI says so under the analysis line; the attempt's usage counts both requests. Analysis
62
65
  sends selected retained text and captures to OpenAI using `OPENAI_API_KEY`, or to Google with
63
66
  `provider: gemini`.
64
67
  Analysis runs in the humanish runner using its credentials. This setting adds no
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "humanish",
3
- "version": "0.145.0",
3
+ "version": "0.147.0",
4
4
  "description": "Synthetic user research for apps, CLIs, and agent-facing product flows.",
5
5
  "keywords": [
6
6
  "cli",
@@ -105,6 +105,7 @@
105
105
  "site:hero:proof": "node scripts/site-hero-wrap-proof.mjs"
106
106
  },
107
107
  "dependencies": {
108
+ "@jsquash/webp": "1.5.0",
108
109
  "commander": "^15.0.0",
109
110
  "parse5": "^8.0.1",
110
111
  "playwright-core": "^1.63.0",
@@ -120,13 +121,13 @@
120
121
  "@types/pngjs": "^6.0.5",
121
122
  "axe-core": "4.14.0",
122
123
  "fast-check": "catalog:",
123
- "knip": "6.41.0",
124
+ "knip": "6.42.1",
124
125
  "modal": "^0.11.1",
125
126
  "oxc-parser": "catalog:",
126
- "oxfmt": "0.73.0",
127
- "oxlint": "1.88.0",
127
+ "oxfmt": "0.74.0",
128
+ "oxlint": "1.89.0",
128
129
  "oxlint-tsgolint": "7.0.2004",
129
- "skills": "1.7.2",
130
+ "skills": "1.7.4",
130
131
  "tsx": "^4.23.15",
131
132
  "typescript": "catalog:",
132
133
  "vitest": "catalog:"