humanish 0.39.0 → 0.41.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 (60) hide show
  1. package/README.md +5 -2
  2. package/dist/actor-contract.d.ts +24 -1
  3. package/dist/actor-contract.js +4 -0
  4. package/dist/actor-contract.js.map +1 -1
  5. package/dist/claude-agent-sdk.js +4 -0
  6. package/dist/claude-agent-sdk.js.map +1 -1
  7. package/dist/comms-sandbox-catch.d.ts +8 -1
  8. package/dist/comms-sandbox-catch.js +128 -1
  9. package/dist/comms-sandbox-catch.js.map +1 -1
  10. package/dist/computer-use-actor.d.ts +1 -1
  11. package/dist/computer-use.d.ts +13 -1
  12. package/dist/computer-use.js +100 -14
  13. package/dist/computer-use.js.map +1 -1
  14. package/dist/concurrent-shared-world-lab.js +1 -1
  15. package/dist/concurrent-shared-world-lab.js.map +1 -1
  16. package/dist/cua-actor-lab.js +114 -9
  17. package/dist/cua-actor-lab.js.map +1 -1
  18. package/dist/e2b-desktop-executor.d.ts +21 -6
  19. package/dist/e2b-desktop-executor.js +65 -21
  20. package/dist/e2b-desktop-executor.js.map +1 -1
  21. package/dist/init-templates.js +4 -1
  22. package/dist/init-templates.js.map +1 -1
  23. package/dist/lab-config.d.ts +48 -1
  24. package/dist/lab-config.js +130 -2
  25. package/dist/lab-config.js.map +1 -1
  26. package/dist/observer-assets.js +8 -1
  27. package/dist/observer-assets.js.map +1 -1
  28. package/dist/observer-data.d.ts +12 -0
  29. package/dist/observer-data.js +13 -1
  30. package/dist/observer-data.js.map +1 -1
  31. package/dist/openai-responses-cu.js +10 -1
  32. package/dist/openai-responses-cu.js.map +1 -1
  33. package/dist/orientation.d.ts +29 -0
  34. package/dist/orientation.js +95 -0
  35. package/dist/orientation.js.map +1 -0
  36. package/dist/pi-agent-core.js +4 -0
  37. package/dist/pi-agent-core.js.map +1 -1
  38. package/dist/pricing.d.ts +8 -0
  39. package/dist/pricing.js +22 -6
  40. package/dist/pricing.js.map +1 -1
  41. package/dist/program.js +13 -0
  42. package/dist/program.js.map +1 -1
  43. package/dist/run.d.ts +55 -2
  44. package/dist/run.js +74 -1
  45. package/dist/run.js.map +1 -1
  46. package/dist/scripted-browser-lab.js +1 -1
  47. package/dist/scripted-browser-lab.js.map +1 -1
  48. package/dist/shared-world-lab.js +1 -1
  49. package/dist/shared-world-lab.js.map +1 -1
  50. package/dist/subject-runtime.d.ts +23 -0
  51. package/dist/subject-runtime.js +70 -0
  52. package/dist/subject-runtime.js.map +1 -0
  53. package/dist/tasks.d.ts +77 -0
  54. package/dist/tasks.js +101 -0
  55. package/dist/tasks.js.map +1 -0
  56. package/docs/contracts/schemas.md +1 -1
  57. package/docs/goals/current.md +2 -2
  58. package/docs/principles/three-roles.md +68 -0
  59. package/docs/ramp/README.md +1 -1
  60. package/package.json +1 -1
package/dist/tasks.js ADDED
@@ -0,0 +1,101 @@
1
+ // Tasks: the researcher's protocol, expressed as config (docs/principles/three-roles.md).
2
+ //
3
+ // A lab could declare a prose `mission` and nothing else. That is a brief, not a protocol — and it
4
+ // left "where did people get stuck" answerable only from an actor's own narration, which is the one
5
+ // source a study should not have to take on faith.
6
+ //
7
+ // Real usability studies are built from discrete TASKS, each with a written success criterion, and
8
+ // the result is a funnel: how far each participant got before they stopped. That funnel is the
9
+ // finding. A single pass/fail per participant throws it away.
10
+ //
11
+ // The criterion language is `stopWhen`, unchanged and already load-bearing elsewhere: a task is
12
+ // done when an observation satisfies it. Reusing it means a task criterion is exactly as expressive
13
+ // as a stop condition, and an author who knows one knows the other.
14
+ //
15
+ // A task's completion is CORROBORATED, not self-reported. The actor saying "I signed up" does not
16
+ // complete a task; the observed URL, page text, or app state does. That distinction is the whole
17
+ // reason to declare tasks at all.
18
+ import { evaluateStopWhen } from "./stop-conditions.js";
19
+ export const TASK_FUNNEL_SCHEMA = "humanish.task-funnel.v1";
20
+ /**
21
+ * Tracks task completion across a session. Stateful on purpose: a task completes ONCE, on the first
22
+ * observation that satisfies it, and stays complete even if the participant navigates away — you do
23
+ * not un-sign-up by going back to the home page.
24
+ */
25
+ export class TaskTracker {
26
+ tasks;
27
+ completions = new Map();
28
+ constructor(tasks) {
29
+ this.tasks = tasks;
30
+ }
31
+ /** Evaluate every still-incomplete task against one observation. Returns newly completed tasks. */
32
+ observe(observation, turn) {
33
+ const fresh = [];
34
+ for (const task of this.tasks) {
35
+ if (task.success === undefined || this.completions.has(task.id))
36
+ continue;
37
+ const match = evaluateStopWhen(task.success, observation);
38
+ if (!match)
39
+ continue;
40
+ const completion = {
41
+ id: task.id,
42
+ turn,
43
+ matchedRuleIndex: match.ruleIndex,
44
+ matchedKinds: match.kinds
45
+ };
46
+ this.completions.set(task.id, completion);
47
+ fresh.push(completion);
48
+ }
49
+ return fresh;
50
+ }
51
+ /** The funnel as it stands. */
52
+ funnel() {
53
+ const tasks = this.tasks.map((task) => {
54
+ const completion = this.completions.get(task.id);
55
+ return {
56
+ id: task.id,
57
+ completed: completion !== undefined,
58
+ observable: task.success !== undefined,
59
+ ...(completion === undefined ? {} : { turn: completion.turn })
60
+ };
61
+ });
62
+ // Where they stopped is the first task not observed complete — the thing a researcher reads
63
+ // first. An unobservable task cannot be "where they stopped", because nothing could have
64
+ // proven otherwise; skipping it avoids blaming a participant for a gap in the protocol.
65
+ const stoppedAt = tasks.find((task) => task.observable && !task.completed)?.id;
66
+ return {
67
+ schema: TASK_FUNNEL_SCHEMA,
68
+ total: tasks.length,
69
+ completed: tasks.filter((task) => task.completed).length,
70
+ unobservable: tasks.filter((task) => !task.observable).length,
71
+ ...(stoppedAt === undefined ? {} : { stoppedAt }),
72
+ tasks
73
+ };
74
+ }
75
+ }
76
+ /**
77
+ * The task list as the PARTICIPANT reads it: numbered, in order, in their own language.
78
+ *
79
+ * Reads `goal` and nothing else. The success criteria are the researcher's instrument and never
80
+ * appear here — a participant who is told how they will be measured optimizes for the measurement,
81
+ * and the study stops being about the product. A test pins this, because it is the kind of leak a
82
+ * later convenience change makes without noticing.
83
+ */
84
+ export function renderTaskPrompt(tasks) {
85
+ if (tasks.length === 0)
86
+ return undefined;
87
+ const lines = tasks.map((task, index) => `${index + 1}. ${task.goal}`);
88
+ return `Work through these in order:\n${lines.join("\n")}`;
89
+ }
90
+ /** One line a stakeholder can read, with the denominator attached. */
91
+ export function formatTaskFunnel(funnel) {
92
+ if (funnel.total === 0)
93
+ return "no tasks declared";
94
+ const base = `${funnel.completed}/${funnel.total} tasks completed`;
95
+ const stopped = funnel.stoppedAt === undefined ? "" : `, stopped at "${funnel.stoppedAt}"`;
96
+ const unobservable = funnel.unobservable === 0
97
+ ? ""
98
+ : `, ${funnel.unobservable} with no completion criterion`;
99
+ return `${base}${stopped}${unobservable}`;
100
+ }
101
+ //# sourceMappingURL=tasks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tasks.js","sourceRoot":"","sources":["../src/tasks.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAC1F,EAAE;AACF,mGAAmG;AACnG,oGAAoG;AACpG,mDAAmD;AACnD,EAAE;AACF,mGAAmG;AACnG,+FAA+F;AAC/F,8DAA8D;AAC9D,EAAE;AACF,gGAAgG;AAChG,oGAAoG;AACpG,oEAAoE;AACpE,EAAE;AACF,kGAAkG;AAClG,iGAAiG;AACjG,kCAAkC;AAElC,OAAO,EAAE,gBAAgB,EAAgD,MAAM,sBAAsB,CAAC;AAEtG,MAAM,CAAC,MAAM,kBAAkB,GAAG,yBAAkC,CAAC;AAkDrE;;;;GAIG;AACH,MAAM,OAAO,WAAW;IAGO;IAFZ,WAAW,GAAG,IAAI,GAAG,EAA0B,CAAC;IAEjE,YAA6B,KAAyB;QAAzB,UAAK,GAAL,KAAK,CAAoB;IAAG,CAAC;IAE1D,mGAAmG;IACnG,OAAO,CAAC,WAAqC,EAAE,IAAY;QACzD,MAAM,KAAK,GAAqB,EAAE,CAAC;QACnC,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC9B,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,IAAI,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBAAE,SAAS;YAC1E,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;YAC1D,IAAI,CAAC,KAAK;gBAAE,SAAS;YACrB,MAAM,UAAU,GAAmB;gBACjC,EAAE,EAAE,IAAI,CAAC,EAAE;gBACX,IAAI;gBACJ,gBAAgB,EAAE,KAAK,CAAC,SAAS;gBACjC,YAAY,EAAE,KAAK,CAAC,KAAK;aAC1B,CAAC;YACF,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;YAC1C,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACzB,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,+BAA+B;IAC/B,MAAM;QACJ,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YACpC,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACjD,OAAO;gBACL,EAAE,EAAE,IAAI,CAAC,EAAE;gBACX,SAAS,EAAE,UAAU,KAAK,SAAS;gBACnC,UAAU,EAAE,IAAI,CAAC,OAAO,KAAK,SAAS;gBACtC,GAAG,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,CAAC;aAC/D,CAAC;QACJ,CAAC,CAAC,CAAC;QACH,4FAA4F;QAC5F,yFAAyF;QACzF,wFAAwF;QACxF,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC;QAC/E,OAAO;YACL,MAAM,EAAE,kBAAkB;YAC1B,KAAK,EAAE,KAAK,CAAC,MAAM;YACnB,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM;YACxD,YAAY,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM;YAC7D,GAAG,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC;YACjD,KAAK;SACN,CAAC;IACJ,CAAC;CACF;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAyB;IACxD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IACzC,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,KAAK,GAAG,CAAC,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IACvE,OAAO,iCAAiC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AAC7D,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,gBAAgB,CAAC,MAAkB;IACjD,IAAI,MAAM,CAAC,KAAK,KAAK,CAAC;QAAE,OAAO,mBAAmB,CAAC;IACnD,MAAM,IAAI,GAAG,GAAG,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,KAAK,kBAAkB,CAAC;IACnE,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,iBAAiB,MAAM,CAAC,SAAS,GAAG,CAAC;IAC3F,MAAM,YAAY,GAAG,MAAM,CAAC,YAAY,KAAK,CAAC;QAC5C,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,KAAK,MAAM,CAAC,YAAY,+BAA+B,CAAC;IAC5D,OAAO,GAAG,IAAI,GAAG,OAAO,GAAG,YAAY,EAAE,CAAC;AAC5C,CAAC"}
@@ -3,7 +3,7 @@
3
3
  Date: 2026-06-02 (current-state note updated 2026-07-14)
4
4
 
5
5
  Status: reference map for the major contracts shipped through source version
6
- `0.39.0`; it is not an exhaustive inventory of command/result envelopes. Exported types,
6
+ `0.41.0`; it is not an exhaustive inventory of command/result envelopes. Exported types,
7
7
  schema constants, parsers, and validators in `src/` are authoritative. Rows
8
8
  marked "reserved" name layering intent only — no code emits or validates them
9
9
  yet. Do not emit a reserved schema.
@@ -16,7 +16,7 @@ Humanish should be the open-source CLI that lets a maintainer ask:
16
16
  The answer should be observable, verifiable, public-safe, and easy to turn into
17
17
  actionable feedback.
18
18
 
19
- ## Current Program Truth (source `0.39.0`)
19
+ ## Current Program Truth (source `0.41.0`)
20
20
 
21
21
  The package source and repository implementation in this tree agree on these
22
22
  points:
@@ -33,7 +33,7 @@ The immutable 2026-06-10 proof-roadmap packet is paired with a
33
33
  | Public proof | A legible four-persona Observer hero from a verified real public-application study (commit-pinned drawDB) shipped in the npm payload (`0.16.0`) | Coverage beyond a single studied subject; the stratified breadth panel remains unbuilt |
34
34
  | OSS meta-lab | Dry-run contract and separate disposable smoke harness | Live meta-lab execution; disabled until repository instructions and actor credentials have an isolated boundary |
35
35
  | Observer serving | `watch`/`observe` loopback servers plus `serve` — the run-library surface with loopback default, capability-link exposure, `share_ready`-gated open mode, and optional operator-run tunnel; streams never served remotely | A remote live-stream (`--live-streams`) design; a persistent capability-link store; a control plane that can start runs |
36
- | Off-app comms | Vendor-neutral in-sandbox email/SMS catch, a minimal persona inbox surface, and digest-only `humanish.comms-thread.v1` evidence; wired into the computer-use and shared-world routes and live-proven on computer-use | An adopter-hosted / app-url ingress plane; real-provider delivery |
36
+ | Off-app comms | Vendor-neutral in-sandbox email/SMS catch, a minimal persona inbox surface, and digest-only `humanish.comms-thread.v1` evidence; wired into the computer-use and shared-world routes over both HTTP and SMTP; live-proven end to end on 2026-08-08 — a persona signed up for a public app, read the emailed link in its inbox, and reached the signed-in product (`docs/goals/email-gated-signup/receipts/signup-verify-live-2026-08-08.md`) | An adopter-hosted / app-url ingress plane; real-provider delivery |
37
37
 
38
38
  Capability proof and adopter replacement are different gates. A deterministic
39
39
  test or kept live receipt proves that a Humanish mechanism works. The depth-axis
@@ -0,0 +1,68 @@
1
+ # Three roles: researcher, stakeholder, participant
2
+
3
+ Humanish runs user research. Every design decision should be checked against the
4
+ three people a study actually involves, because they want different things and
5
+ conflating any two of them produces a specific, recurring class of bug.
6
+
7
+ ## The roles
8
+
9
+ **The researcher** designs the study and runs it. In humanish this is usually an
10
+ agent invoking the CLI, not a person clicking. A researcher wants a protocol they
11
+ can express and defend: tasks with success criteria, a panel with declared
12
+ coverage, a pilot before the panel spends, and structured per-task outcomes back.
13
+ They care about rigor and control, and they need output they can reason over and
14
+ adjust.
15
+
16
+ **The stakeholder** watches. In a real study they sit behind the glass in the
17
+ viewing room; here they open Observer, `watch`, or `serve`. They want none of the
18
+ protocol. They want to know what happened, where people got stuck, how bad it is,
19
+ and whether anyone succeeded — moments, severity, and the denominator.
20
+
21
+ **The participant** is the persona. They have a goal, limited patience, and their
22
+ own idea of how the product works. They are the subject of the study, never its
23
+ instrument.
24
+
25
+ ## Why the distinction earns its place
26
+
27
+ Two of humanish's worst bugs were category errors between these roles, not
28
+ missing features.
29
+
30
+ **Fusing the participant into the harness** made abandonment look like a
31
+ malfunction. `gave_up` mapped to a `failed` status, so a persona giving up — the
32
+ single most valuable thing a usability study produces — dragged the run verdict
33
+ red as though the instrument had broken. A participant abandoning a task is a
34
+ finding. The harness only fails when the harness fails.
35
+
36
+ **Fusing the researcher's question with the stakeholder's** put one pass/fail
37
+ verdict on a bundle that answers two different questions. "Is this evidence
38
+ trustworthy?" is genuinely pass/fail: did the harness do what it claimed, with a
39
+ real sandbox, real actions, and cost lines nobody forged. "What did we learn?" has
40
+ no pass/fail at all — asking whether a study passed is a category error. Because
41
+ there was one slot, a session that stopped early had to be called `passed`, and a
42
+ truncated study was reported as a green one.
43
+
44
+ ## Checks worth applying
45
+
46
+ When adding a surface, a default, or a verdict, ask:
47
+
48
+ - **Which role is this for?** A knob that serves the researcher does not belong in
49
+ the stakeholder's view, and a highlight reel is not evidence.
50
+ - **Is this a participant outcome or a harness outcome?** Abandonment, confusion,
51
+ and running out of session are things that happened to a participant. Only a
52
+ broken sandbox, a forged artifact, or an unreachable service is a harness
53
+ failure.
54
+ - **Does the number travel with its denominator?** A stakeholder behind glass
55
+ forms conclusions from vivid moments; that is the classic failure of the viewing
56
+ room, and it is why researchers synthesize rather than letting the room decide.
57
+ Anything shown to a stakeholder carries its count and its confidence, or it
58
+ becomes a machine for manufacturing certainty from n=1.
59
+ - **Would a researcher recognize this as a study?** Budgets are recruiting
60
+ decisions made once, up front — how many participants can we afford. No
61
+ researcher has ever ended a session because it got expensive.
62
+
63
+ ## Related
64
+
65
+ - [invariants-and-defaults.md](invariants-and-defaults.md) — fail-closed rules and
66
+ what defaults are allowed to assume
67
+ - [actor-fidelity.md](actor-fidelity.md) — what a claim about persona realism can
68
+ and cannot mean
@@ -2,7 +2,7 @@
2
2
 
3
3
  Status: public-safe contributor and agent ramp.
4
4
 
5
- Package/source version in this tree: `0.39.0` (2026-08-08). The containment boundary introduced in
5
+ Package/source version in this tree: `0.41.0` (2026-08-11). The containment boundary introduced in
6
6
  `0.15.1` remains in force: managed run and output paths bind to validated
7
7
  physical filesystem identities, and stored provider IDs are evidence, not
8
8
  cleanup authority. The bundled OSS meta-lab is dry-run only until
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "humanish",
3
- "version": "0.39.0",
3
+ "version": "0.41.0",
4
4
  "description": "Open-source-safe CLI for persona simulation, observer review, and public-safe feedback drafts.",
5
5
  "author": "Daniel G Wilson <daniel@danielgwilson.com>",
6
6
  "keywords": [