humanish 0.88.0 → 0.88.1

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 CHANGED
@@ -201,9 +201,19 @@ Mobile viewport and touch flags do not certify gesture equivalence. The
201
201
  qualifies the historical phone-lane results: they describe Humanish's measured input path,
202
202
  not established physical-device app behavior.
203
203
 
204
- #### Adapters: drive a local app via its JS state contract (no E2B, no vision)
204
+ #### Drive an already-running local app
205
205
 
206
- See [state-driven local adapters](https://humanish.dev/docs/computer-use#state-driven-local-adapters).
206
+ Use a custom executor and non-vision provider to drive your app's state contract
207
+ without E2B. The [runnable npm example](docs/architecture/examples/state-driven-local-app/README.md)
208
+ includes a synthetic loopback app, deterministic provider, verification and cleanup:
209
+
210
+ ```bash
211
+ node node_modules/humanish/docs/architecture/examples/state-driven-local-app/runner.mjs
212
+ ```
213
+
214
+ Run it after installing `humanish`. It makes no model calls; it proves the
215
+ integration, not persona behavior. See [state-driven local adapters](https://humanish.dev/docs/computer-use#state-driven-local-adapters)
216
+ for the supported library seam.
207
217
 
208
218
  ## Browser Scenario Manifests
209
219
 
@@ -0,0 +1,5 @@
1
+ /** Presentation provenance for computer-use completion; never reclassifies the stored outcome. */
2
+ export type CuaGoalSource = "participant_report" | "condition_matched" | "unavailable";
3
+ export declare function isCuaTrace(value: unknown): boolean;
4
+ export declare function cuaGoalSource(value: unknown, recordedStatus?: unknown): CuaGoalSource | undefined;
5
+ export declare const CUA_COMPLETION_NOTE = "Participant reports alone do not establish task success. A matched stop condition establishes only its declared condition. Run gate and share-safety results are separate.";
@@ -0,0 +1,32 @@
1
+ export function isCuaTrace(value) {
2
+ if (typeof value !== "object" || value === null)
3
+ return false;
4
+ const trace = value;
5
+ return trace.lane === "computer-use" || trace.protocol === "cua-loop";
6
+ }
7
+ export function cuaGoalSource(value, recordedStatus) {
8
+ if (!isCuaTrace(value))
9
+ return undefined;
10
+ const trace = value;
11
+ if (trace.status !== "passed")
12
+ return recordedStatus === "passed" || recordedStatus === "complete" ? "unavailable" : undefined;
13
+ if (trace.lane !== "computer-use" || trace.protocol !== "cua-loop"
14
+ || trace.completionReason !== "goal_satisfied")
15
+ return "unavailable";
16
+ if (!Array.isArray(trace.items) || !trace.items.every((item) => typeof item === "object" && item !== null
17
+ && !Array.isArray(item) && typeof item.id === "string" && typeof item.kind === "string"
18
+ && typeof item.title === "string" && (item.lifecycle === "started" || item.lifecycle === "completed"))) {
19
+ return "unavailable";
20
+ }
21
+ // These notices are written by the loop after a matched predicate/window, not by the model.
22
+ if (trace.items.some((item) => item.kind === "notice"
23
+ && item.lifecycle === "completed" && item.status === "matched"
24
+ && typeof item.title === "string"
25
+ && (item.title.startsWith("stopWhen matched:") || item.title === "dwell window complete"))) {
26
+ return "condition_matched";
27
+ }
28
+ // A legacy trace without enough detail cannot establish which endpoint ended the loop.
29
+ return trace.items.length > 0 ? "participant_report" : "unavailable";
30
+ }
31
+ export const CUA_COMPLETION_NOTE = "Participant reports alone do not establish task success. A matched stop condition establishes only its declared condition. Run gate and share-safety results are separate.";
32
+ //# sourceMappingURL=actor-goal-source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actor-goal-source.js","sourceRoot":"","sources":["../src/actor-goal-source.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,UAAU,CAAC,KAAc;IACvC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC9D,MAAM,KAAK,GAAG,KAAgC,CAAC;IAC/C,OAAO,KAAK,CAAC,IAAI,KAAK,cAAc,IAAI,KAAK,CAAC,QAAQ,KAAK,UAAU,CAAC;AACxE,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAc,EAAE,cAAwB;IACpE,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IACzC,MAAM,KAAK,GAAG,KAAgC,CAAC;IAC/C,IAAI,KAAK,CAAC,MAAM,KAAK,QAAQ;QAAE,OAAO,cAAc,KAAK,QAAQ,IAAI,cAAc,KAAK,UAAU,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/H,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,IAAI,KAAK,CAAC,QAAQ,KAAK,UAAU;WAC7D,KAAK,CAAC,gBAAgB,KAAK,gBAAgB;QAAE,OAAO,aAAa,CAAC;IACvE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI;WACpG,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC,EAAE,KAAK,QAAQ,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ;WACpF,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,SAAS,KAAK,SAAS,IAAI,IAAI,CAAC,SAAS,KAAK,WAAW,CAAC,CAAC,EAAE,CAAC;QACzG,OAAO,aAAa,CAAC;IACvB,CAAC;IACD,4FAA4F;IAC5F,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAA6B,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,QAAQ;WACzE,IAAI,CAAC,SAAS,KAAK,WAAW,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS;WAC3D,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ;WAC9B,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,mBAAmB,CAAC,IAAI,IAAI,CAAC,KAAK,KAAK,uBAAuB,CAAC,CAAC,EAAE,CAAC;QAC7F,OAAO,mBAAmB,CAAC;IAC7B,CAAC;IACD,uFAAuF;IACvF,OAAO,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,aAAa,CAAC;AACvE,CAAC;AAED,MAAM,CAAC,MAAM,mBAAmB,GAAG,4KAA4K,CAAC"}
@@ -61,7 +61,7 @@ import { actorEnding } from "./actor-stop-cause.js";
61
61
  import { assertPreparedSelectedOutputDirectory, assertSafeOutputPathSegment, prepareContainedOutputDirectory, prepareSelectedOutputDirectory, writeContainedOutputFile, writePreparedRunLatestPointer } from "./selected-output-paths.js";
62
62
  import { prepareRunArtifactPaths, validatePreparedRunArtifactPaths } from "./run-paths.js";
63
63
  import { createLocalTreeArchive } from "./source-archive.js";
64
- import { buildRunSource, loadRunBundle, PUBLIC_TARGET_CWD, REVIEW_SCHEMA, RUN_BUNDLE_SCHEMA, aggregateTaskFunnels, formatParticipantOutcomes, formatStudyTaskFunnel, tallyParticipantOutcomes } from "./run.js";
64
+ import { buildRunSource, loadRunBundle, PUBLIC_TARGET_CWD, REVIEW_SCHEMA, RUN_BUNDLE_SCHEMA, aggregateTaskFunnels, formatParticipantOutcomes, formatStudyTaskFunnel, tallyParticipantOutcomes, withCuaReviewProvenance } from "./run.js";
65
65
  import { estimateActorCost, estimateDesktopCost, estimateAllocatedDesktopCost, MODEL_RATES, round6 } from "./pricing.js";
66
66
  import { observeDesktopResources } from "./e2b-desktop-resources.js";
67
67
  export const CUA_ACTOR_LAB_SCHEMA = "humanish.cua-lab-result.v2";
@@ -4465,7 +4465,7 @@ export function buildCuaBundle(args) {
4465
4465
  : args.credibility?.noEngagement === true
4466
4466
  ? "Not counted as a pass: the participant took no actions and said nothing."
4467
4467
  : "Not counted as a pass: the participant's final message described a blocker.";
4468
- const review = {
4468
+ const review = withCuaReviewProvenance({
4469
4469
  schema: REVIEW_SCHEMA,
4470
4470
  verdict: args.inProgress === true
4471
4471
  ? "contract_proof_only"
@@ -4486,7 +4486,7 @@ export function buildCuaBundle(args) {
4486
4486
  : args.inProgress === true
4487
4487
  ? ["Live desktop session is still running."]
4488
4488
  : ["Live desktop session not yet run (dry-run contract only)."]
4489
- };
4489
+ }, [stream]);
4490
4490
  return {
4491
4491
  schema: RUN_BUNDLE_SCHEMA,
4492
4492
  runId: args.runId,
@@ -4922,7 +4922,7 @@ export function buildCuaFanoutBundle(args) {
4922
4922
  const ending = actorEnding(outcome.session.trace);
4923
4923
  return { status: outcome.session.status, ...(ending === undefined ? {} : { label: ending.label }) };
4924
4924
  });
4925
- const review = {
4925
+ const review = withCuaReviewProvenance({
4926
4926
  schema: REVIEW_SCHEMA,
4927
4927
  verdict,
4928
4928
  ...(participants === undefined ? {} : { participants }),
@@ -4946,7 +4946,7 @@ export function buildCuaFanoutBundle(args) {
4946
4946
  || outcome.session === undefined
4947
4947
  || outcome.session.status !== "passed")
4948
4948
  .map(({ spec, outcome }) => `${spec.laneId}: ${outcome?.skippedReason ?? outcome?.sessionError ?? outcome?.session?.reason ?? "did not pass"}`)
4949
- };
4949
+ }, streams);
4950
4950
  const anyRaw = (outcomes ?? []).some((outcome) => outcome.session?.trace.redaction.screenshots === "raw");
4951
4951
  const ranLive = (outcomes ?? []).some((outcome) => outcome.session !== undefined || outcome.sessionError !== undefined);
4952
4952
  const configuredBrowser = config.execution?.desktop?.browser;
@@ -5130,7 +5130,7 @@ function renderCuaReviewMarkdown(bundle) {
5130
5130
  "",
5131
5131
  `- run: ${bundle.runId}`,
5132
5132
  `- mode: ${bundle.mode}`,
5133
- `- verdict: ${bundle.review.verdict}`,
5133
+ `- run gate: ${bundle.review.verdict}`,
5134
5134
  `- summary: ${bundle.review.summary}`,
5135
5135
  ...(provenance ? [`- subject: ${provenance.message}`] : []),
5136
5136
  ...(trace