humanish 0.49.0 → 0.50.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 (59) hide show
  1. package/README.md +52 -3
  2. package/dist/concurrent-shared-world-lab.d.ts +5 -0
  3. package/dist/concurrent-shared-world-lab.js +28 -0
  4. package/dist/concurrent-shared-world-lab.js.map +1 -1
  5. package/dist/cua-actor-lab.d.ts +7 -0
  6. package/dist/cua-actor-lab.js +46 -2
  7. package/dist/cua-actor-lab.js.map +1 -1
  8. package/dist/e2b-terminal-lab.d.ts +7 -0
  9. package/dist/e2b-terminal-lab.js +54 -0
  10. package/dist/e2b-terminal-lab.js.map +1 -1
  11. package/dist/init-templates.js +7 -2
  12. package/dist/init-templates.js.map +1 -1
  13. package/dist/lab-engine.d.ts +11 -0
  14. package/dist/lab-engine.js +18 -0
  15. package/dist/lab-engine.js.map +1 -1
  16. package/dist/oss-lab.d.ts +3 -0
  17. package/dist/oss-lab.js.map +1 -1
  18. package/dist/oss-meta-lab.d.ts +3 -0
  19. package/dist/oss-meta-lab.js +13 -0
  20. package/dist/oss-meta-lab.js.map +1 -1
  21. package/dist/program.d.ts +14 -0
  22. package/dist/program.js +127 -9
  23. package/dist/program.js.map +1 -1
  24. package/dist/run-detail.d.ts +59 -0
  25. package/dist/run-detail.js +108 -0
  26. package/dist/run-detail.js.map +1 -0
  27. package/dist/run-index.d.ts +71 -0
  28. package/dist/run-index.js +206 -0
  29. package/dist/run-index.js.map +1 -0
  30. package/dist/run-paths.js +16 -1
  31. package/dist/run-paths.js.map +1 -1
  32. package/dist/run-projection.d.ts +182 -0
  33. package/dist/run-projection.js +349 -0
  34. package/dist/run-projection.js.map +1 -0
  35. package/dist/run-status.d.ts +139 -0
  36. package/dist/run-status.js +218 -0
  37. package/dist/run-status.js.map +1 -0
  38. package/dist/run.d.ts +15 -0
  39. package/dist/run.js +91 -6
  40. package/dist/run.js.map +1 -1
  41. package/dist/scripted-browser-lab.d.ts +5 -0
  42. package/dist/scripted-browser-lab.js +27 -0
  43. package/dist/scripted-browser-lab.js.map +1 -1
  44. package/dist/shared-world-lab.d.ts +5 -0
  45. package/dist/shared-world-lab.js +27 -0
  46. package/dist/shared-world-lab.js.map +1 -1
  47. package/dist/tui-app.js +402 -0
  48. package/dist/tui-contract.d.ts +73 -0
  49. package/dist/tui-contract.js +32 -0
  50. package/dist/tui-contract.js.map +1 -0
  51. package/dist/tui-launch.d.ts +48 -0
  52. package/dist/tui-launch.js +159 -0
  53. package/dist/tui-launch.js.map +1 -0
  54. package/docs/contracts/run-bundle.md +8 -0
  55. package/docs/contracts/schemas.md +70 -1
  56. package/docs/goals/current.md +3 -2
  57. package/docs/ramp/README.md +1 -1
  58. package/package.json +8 -5
  59. package/skills/humanish/SKILL.md +19 -0
@@ -26,6 +26,7 @@ import { readFile, realpath, rm } from "node:fs/promises";
26
26
  import path from "node:path";
27
27
  import { runDesktopCommandOrThrow, toErrorMessage } from "./command-failure.js";
28
28
  import { pathToFileURL } from "node:url";
29
+ import { beginRunStatus } from "./run-status.js";
29
30
  import { adapterScoreFailureMessage, applyBrowserAdapterHooks } from "./adapter-extension.js";
30
31
  import { actorRegistry, isCuaActorDescriptor } from "./actor-registry.js";
31
32
  import { CHROMIUM_EVIDENCE_HYGIENE_FLAGS, chromiumEvidenceProfilePreferencesJson } from "./browser-evidence-hygiene.js";
@@ -2261,6 +2262,17 @@ export async function runCuaActorLab(options) {
2261
2262
  }
2262
2263
  const runId = options.runId ?? makeCuaRunId();
2263
2264
  const runPaths = await prepareRunArtifactPaths(cwd, runId);
2265
+ // Identity + liveness on disk from the first moment (#455): anything watching the runs
2266
+ // directory — the TUI, another terminal, an agent — can now tell which lab this is and that
2267
+ // it is alive, without waiting for the interactive observer flush that used to be the only
2268
+ // mid-run write. The success path finalizes it with the real outcome; the fail-closed returns
2269
+ // below do not, so `runLab`'s status scope finalizes those with no outcome. A crash reaches
2270
+ // neither and leaves the record stale, which reads as interrupted rather than as a lie.
2271
+ const runStatus = beginRunStatus(runPaths, {
2272
+ runId,
2273
+ mode: dryRun ? "dry-run" : "live",
2274
+ ...(options.lab === undefined ? {} : { lab: options.lab })
2275
+ });
2264
2276
  const artifactRoot = runPaths.absoluteRunRoot;
2265
2277
  const physicalArtifactRoot = runPaths.physicalRunRoot;
2266
2278
  const createdAt = new Date().toISOString();
@@ -2353,9 +2365,16 @@ export async function runCuaActorLab(options) {
2353
2365
  }));
2354
2366
  const inProgressAggregateSubject = inProgressLaneSubjects[0];
2355
2367
  const inProgressProvenance = subjectProvenanceArg(inProgressAggregateSubject, publicRepo, subjectEnvNames);
2356
- if (!dryRun && options.onObserverReady) {
2368
+ // A live run writes what it is doing AS IT DOES IT, whether or not anyone is currently watching.
2369
+ // This used to be gated on `options.onObserverReady` — the interactive Observer callback — so a
2370
+ // run launched by an agent (`lab run --json`), detached, or from the terminal surface recorded
2371
+ // nothing at all until it completed, and anything asking "what is this participant doing right
2372
+ // now" got silence for the whole run. Who reads the evidence is not the run's business; the
2373
+ // callback below stays conditional, the writing does not.
2374
+ if (!dryRun) {
2357
2375
  const inProgressBundle = laneCount === 1 && rerunLineage === undefined
2358
2376
  ? buildSingleLaneBundle({
2377
+ ...(options.lab === undefined ? {} : { lab: options.lab }),
2359
2378
  spec: laneSpecs[0],
2360
2379
  outcome: undefined,
2361
2380
  descriptor,
@@ -2372,6 +2391,7 @@ export async function runCuaActorLab(options) {
2372
2391
  localAppSubject
2373
2392
  })
2374
2393
  : buildCuaFanoutBundle({
2394
+ ...(options.lab === undefined ? {} : { lab: options.lab }),
2375
2395
  specs: laneSpecs,
2376
2396
  laneSubjects: inProgressLaneSubjects,
2377
2397
  aggregateSubject: inProgressAggregateSubject,
@@ -2394,7 +2414,8 @@ export async function runCuaActorLab(options) {
2394
2414
  liveObserver = observerResultForCuaArtifacts(cwd, runId, artifactRoot, [
2395
2415
  "Live CUA Observer is attached before final verification; stream auth URLs are runtime-only and are not persisted."
2396
2416
  ]);
2397
- await options.onObserverReady(liveObserver);
2417
+ if (options.onObserverReady)
2418
+ await options.onObserverReady(liveObserver);
2398
2419
  // Incremental live flush (#441): as each lane's loop reports its recorded-so-far items,
2399
2420
  // rewrite the in-progress bundle with per-stream `liveActor` partials so the attached
2400
2421
  // Observer's 5s poll sees the timeline grow. Throttled (one write per interval, trailing
@@ -2585,6 +2606,7 @@ export async function runCuaActorLab(options) {
2585
2606
  const finalProvenance = subjectProvenanceArg(aggregateSubject, publicRepo, subjectEnvNames);
2586
2607
  const bundle = laneCount === 1 && rerunLineage === undefined
2587
2608
  ? buildSingleLaneBundle({
2609
+ ...(options.lab === undefined ? {} : { lab: options.lab }),
2588
2610
  spec: laneSpecs[0],
2589
2611
  outcome: outcomes?.[0],
2590
2612
  descriptor,
@@ -2600,6 +2622,7 @@ export async function runCuaActorLab(options) {
2600
2622
  localAppSubject
2601
2623
  })
2602
2624
  : buildCuaFanoutBundle({
2625
+ ...(options.lab === undefined ? {} : { lab: options.lab }),
2603
2626
  specs: laneSpecs,
2604
2627
  ...(outcomes === undefined ? {} : { outcomes }),
2605
2628
  laneSubjects,
@@ -2639,6 +2662,24 @@ export async function runCuaActorLab(options) {
2639
2662
  ...(options.scorerProvenance === undefined ? {} : { scorerProvenance: options.scorerProvenance })
2640
2663
  });
2641
2664
  await writeCuaRunArtifacts(bundle, createdAt, runPaths);
2665
+ // Finalize the status record from the bundle that was just written, so the index can never
2666
+ // claim an outcome the evidence does not carry. A run that throws before reaching here leaves
2667
+ // its record `running` and goes stale — read as interrupted, which is the truth.
2668
+ await runStatus.finish({
2669
+ ...(bundle.review?.verdict === undefined ? {} : { verdict: bundle.review.verdict }),
2670
+ ...(bundle.review?.participants === undefined
2671
+ ? {}
2672
+ : {
2673
+ participants: {
2674
+ total: bundle.review.participants.total,
2675
+ reachedGoal: bundle.review.participants.reachedGoal,
2676
+ ...(bundle.review.participants.reportedFriction === undefined
2677
+ ? {}
2678
+ : { reportedFriction: bundle.review.participants.reportedFriction })
2679
+ }
2680
+ }),
2681
+ ...(bundle.cost?.estimatedTotalUsd === undefined ? {} : { estimatedCostUsd: bundle.cost.estimatedTotalUsd })
2682
+ });
2642
2683
  const observer = await render(cwd, runId, { open: options.open === true });
2643
2684
  if (observer.ok && runtimeStreamUrls.length > 0) {
2644
2685
  attachObserverRuntimeStreamUrls(observer, runtimeStreamUrls);
@@ -2801,6 +2842,7 @@ function observerResultForCuaArtifacts(cwd, runId, artifactRoot, warnings = [])
2801
2842
  function buildSingleLaneBundle(args) {
2802
2843
  const { spec, outcome, config } = args;
2803
2844
  return buildCuaBundle({
2845
+ ...(args.lab === undefined ? {} : { lab: args.lab }),
2804
2846
  actorId: args.descriptor.id,
2805
2847
  appUrl: args.appUrl,
2806
2848
  laneId: spec.laneId,
@@ -3606,6 +3648,7 @@ export function buildCuaBundle(args) {
3606
3648
  createdAt: args.createdAt,
3607
3649
  cwd: PUBLIC_TARGET_CWD,
3608
3650
  artifactRoot: path.join(".humanish", "runs", args.runId),
3651
+ ...(args.lab === undefined ? {} : { lab: args.lab }),
3609
3652
  source: args.source,
3610
3653
  persona: {
3611
3654
  id: args.persona.id,
@@ -4078,6 +4121,7 @@ export function buildCuaFanoutBundle(args) {
4078
4121
  createdAt: args.createdAt,
4079
4122
  cwd: PUBLIC_TARGET_CWD,
4080
4123
  artifactRoot: path.join(".humanish", "runs", args.runId),
4124
+ ...(args.lab === undefined ? {} : { lab: args.lab }),
4081
4125
  source: args.source,
4082
4126
  persona: {
4083
4127
  id: specs[0].persona.id,