humanish 0.40.0 → 0.42.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 (56) hide show
  1. package/README.md +36 -8
  2. package/dist/actor-contract.d.ts +9 -0
  3. package/dist/actor-contract.js.map +1 -1
  4. package/dist/adapter-extension.js +1 -0
  5. package/dist/adapter-extension.js.map +1 -1
  6. package/dist/computer-use-actor.d.ts +11 -0
  7. package/dist/computer-use-actor.js +2 -0
  8. package/dist/computer-use-actor.js.map +1 -1
  9. package/dist/computer-use.d.ts +30 -0
  10. package/dist/computer-use.js +65 -3
  11. package/dist/computer-use.js.map +1 -1
  12. package/dist/concurrent-shared-world-lab.js +72 -42
  13. package/dist/concurrent-shared-world-lab.js.map +1 -1
  14. package/dist/cua-actor-lab.d.ts +64 -2
  15. package/dist/cua-actor-lab.js +327 -28
  16. package/dist/cua-actor-lab.js.map +1 -1
  17. package/dist/e2b-desktop-executor.d.ts +1 -1
  18. package/dist/e2b-desktop-executor.js +2 -1
  19. package/dist/e2b-desktop-executor.js.map +1 -1
  20. package/dist/e2b-terminal-lab.js +1 -0
  21. package/dist/e2b-terminal-lab.js.map +1 -1
  22. package/dist/feedback.js +55 -1
  23. package/dist/feedback.js.map +1 -1
  24. package/dist/image-evidence.js +36 -22
  25. package/dist/image-evidence.js.map +1 -1
  26. package/dist/init-templates.js +7 -2
  27. package/dist/init-templates.js.map +1 -1
  28. package/dist/lab-config.d.ts +26 -2
  29. package/dist/lab-config.js +49 -2
  30. package/dist/lab-config.js.map +1 -1
  31. package/dist/observer-assets.js +11 -1
  32. package/dist/observer-assets.js.map +1 -1
  33. package/dist/observer-data.d.ts +16 -0
  34. package/dist/observer-data.js +14 -1
  35. package/dist/observer-data.js.map +1 -1
  36. package/dist/program.js +5 -5
  37. package/dist/program.js.map +1 -1
  38. package/dist/redaction.js +4 -9
  39. package/dist/redaction.js.map +1 -1
  40. package/dist/run.d.ts +88 -2
  41. package/dist/run.js +92 -3
  42. package/dist/run.js.map +1 -1
  43. package/dist/screenshot-image.d.ts +11 -0
  44. package/dist/screenshot-image.js +26 -0
  45. package/dist/screenshot-image.js.map +1 -0
  46. package/dist/scripted-browser-lab.js +4 -2
  47. package/dist/scripted-browser-lab.js.map +1 -1
  48. package/dist/shared-world-lab.js +17 -3
  49. package/dist/shared-world-lab.js.map +1 -1
  50. package/dist/tasks.d.ts +77 -0
  51. package/dist/tasks.js +101 -0
  52. package/dist/tasks.js.map +1 -0
  53. package/docs/contracts/schemas.md +1 -1
  54. package/docs/goals/current.md +16 -3
  55. package/docs/ramp/README.md +1 -1
  56. 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":"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"}
@@ -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.40.0`; it is not an exhaustive inventory of command/result envelopes. Exported types,
6
+ `0.42.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.
@@ -1,6 +1,6 @@
1
1
  # Current Goals
2
2
 
3
- Status date: 2026-08-05 (rev 17)
3
+ Status date: 2026-08-11 (rev 18)
4
4
 
5
5
  This page is the current public-safe operating goal for `humanish`. Keep it
6
6
  short enough to reread before a coding session and concrete enough that future
@@ -16,7 +16,20 @@ 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.40.0`)
19
+ What humanish runs is synthetic user research, and every surface is checked
20
+ against the three people a study involves — researcher, stakeholder,
21
+ participant ([docs/principles/three-roles.md](../principles/three-roles.md)).
22
+ The operational consequences: a study declares `tasks` with success criteria
23
+ the participant never sees and gets a per-task completion funnel back; budgets
24
+ are study-level recruiting decisions (`execution.caps.maxTotalUsd`) with
25
+ per-lane caps as backstops; sessions end because the participant finished, not
26
+ because a timer fired; abandonment and reported friction are findings that
27
+ become feedback candidates, not failures. Receipts: the email-gated signup
28
+ study completed, reproduced, and produced a real accessibility finding via a
29
+ keyboard-first participant
30
+ ([docs/goals/email-gated-signup/receipts/](email-gated-signup/receipts/)).
31
+
32
+ ## Current Program Truth (source `0.42.0`)
20
33
 
21
34
  The package source and repository implementation in this tree agree on these
22
35
  points:
@@ -33,7 +46,7 @@ The immutable 2026-06-10 proof-roadmap packet is paired with a
33
46
  | 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
47
  | 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
48
  | 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 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 |
49
+ | 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`); the adopter-hosted / app-url ingress plane is wired on the CUA and concurrent external-public routes (#387/#380, 2026-08-11) | Real-provider delivery; a live adopter-hosted receipt |
37
50
 
38
51
  Capability proof and adopter replacement are different gates. A deterministic
39
52
  test or kept live receipt proves that a Humanish mechanism works. The depth-axis
@@ -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.40.0` (2026-08-08). The containment boundary introduced in
5
+ Package/source version in this tree: `0.42.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.40.0",
3
+ "version": "0.42.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": [