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.
- package/README.md +36 -8
- package/dist/actor-contract.d.ts +9 -0
- package/dist/actor-contract.js.map +1 -1
- package/dist/adapter-extension.js +1 -0
- package/dist/adapter-extension.js.map +1 -1
- package/dist/computer-use-actor.d.ts +11 -0
- package/dist/computer-use-actor.js +2 -0
- package/dist/computer-use-actor.js.map +1 -1
- package/dist/computer-use.d.ts +30 -0
- package/dist/computer-use.js +65 -3
- package/dist/computer-use.js.map +1 -1
- package/dist/concurrent-shared-world-lab.js +72 -42
- package/dist/concurrent-shared-world-lab.js.map +1 -1
- package/dist/cua-actor-lab.d.ts +64 -2
- package/dist/cua-actor-lab.js +327 -28
- package/dist/cua-actor-lab.js.map +1 -1
- package/dist/e2b-desktop-executor.d.ts +1 -1
- package/dist/e2b-desktop-executor.js +2 -1
- package/dist/e2b-desktop-executor.js.map +1 -1
- package/dist/e2b-terminal-lab.js +1 -0
- package/dist/e2b-terminal-lab.js.map +1 -1
- package/dist/feedback.js +55 -1
- package/dist/feedback.js.map +1 -1
- package/dist/image-evidence.js +36 -22
- package/dist/image-evidence.js.map +1 -1
- package/dist/init-templates.js +7 -2
- package/dist/init-templates.js.map +1 -1
- package/dist/lab-config.d.ts +26 -2
- package/dist/lab-config.js +49 -2
- package/dist/lab-config.js.map +1 -1
- package/dist/observer-assets.js +11 -1
- package/dist/observer-assets.js.map +1 -1
- package/dist/observer-data.d.ts +16 -0
- package/dist/observer-data.js +14 -1
- package/dist/observer-data.js.map +1 -1
- package/dist/program.js +5 -5
- package/dist/program.js.map +1 -1
- package/dist/redaction.js +4 -9
- package/dist/redaction.js.map +1 -1
- package/dist/run.d.ts +88 -2
- package/dist/run.js +92 -3
- package/dist/run.js.map +1 -1
- package/dist/screenshot-image.d.ts +11 -0
- package/dist/screenshot-image.js +26 -0
- package/dist/screenshot-image.js.map +1 -0
- package/dist/scripted-browser-lab.js +4 -2
- package/dist/scripted-browser-lab.js.map +1 -1
- package/dist/shared-world-lab.js +17 -3
- package/dist/shared-world-lab.js.map +1 -1
- package/dist/tasks.d.ts +77 -0
- package/dist/tasks.js +101 -0
- package/dist/tasks.js.map +1 -0
- package/docs/contracts/schemas.md +1 -1
- package/docs/goals/current.md +16 -3
- package/docs/ramp/README.md +1 -1
- 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.
|
|
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.
|
package/docs/goals/current.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Current Goals
|
|
2
2
|
|
|
3
|
-
Status date: 2026-08-
|
|
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
|
-
|
|
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`)
|
|
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
|
package/docs/ramp/README.md
CHANGED
|
@@ -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.
|
|
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