humanish 0.84.0 → 0.85.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 (41) hide show
  1. package/dist/cua-actor-lab.js +3 -2
  2. package/dist/cua-actor-lab.js.map +1 -1
  3. package/dist/export.js +17 -10
  4. package/dist/export.js.map +1 -1
  5. package/dist/feedback-proof.d.ts +8 -0
  6. package/dist/feedback-proof.js +44 -0
  7. package/dist/feedback-proof.js.map +1 -0
  8. package/dist/feedback.js +6 -5
  9. package/dist/feedback.js.map +1 -1
  10. package/dist/observer-app.html +55 -9
  11. package/dist/observer-data.d.ts +12 -0
  12. package/dist/observer-data.js +8 -0
  13. package/dist/observer-data.js.map +1 -1
  14. package/dist/observer-library.d.ts +2 -0
  15. package/dist/observer-library.js.map +1 -1
  16. package/dist/observer-static.js +52 -1
  17. package/dist/observer-static.js.map +1 -1
  18. package/dist/observer.d.ts +5 -0
  19. package/dist/observer.js +90 -34
  20. package/dist/observer.js.map +1 -1
  21. package/dist/oss-meta-lab.js +6 -5
  22. package/dist/oss-meta-lab.js.map +1 -1
  23. package/dist/program.js +48 -47
  24. package/dist/program.js.map +1 -1
  25. package/dist/serve-http.d.ts +4 -0
  26. package/dist/serve-http.js +9 -1
  27. package/dist/serve-http.js.map +1 -1
  28. package/dist/tui-actions.d.ts +12 -7
  29. package/dist/tui-actions.js +72 -56
  30. package/dist/tui-actions.js.map +1 -1
  31. package/dist/tui-app.js +1 -1
  32. package/dist/tui-contract.d.ts +1 -1
  33. package/docs/architecture/observer-review.md +130 -0
  34. package/docs/architecture/observer.md +88 -2
  35. package/docs/contracts/feedback.md +9 -0
  36. package/docs/contracts/schemas.md +1 -1
  37. package/docs/goals/current.md +6 -2
  38. package/docs/ramp/README.md +1 -1
  39. package/docs/release/0.84.1-portable-feedback.md +20 -0
  40. package/docs/release/0.85.0-observer-review.md +56 -0
  41. package/package.json +4 -2
package/dist/program.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { existsSync, readFileSync } from "node:fs";
2
2
  import { formatOrientationHuman, readOrientation } from "./orientation.js";
3
3
  import { readFile } from "node:fs/promises";
4
- import { dirname, join, resolve } from "node:path";
4
+ import { dirname, resolve } from "node:path";
5
5
  import { fileURLToPath } from "node:url";
6
6
  import { Command, Option } from "commander";
7
7
  import { startCodexAppServerUi } from "./codex-app-server-ui.js";
@@ -20,7 +20,6 @@ import { runLab, resolveLabDryRun, selectLabBackend } from "./lab-engine.js";
20
20
  import { loadAdapterScorer } from "./adapter-scorer-loader.js";
21
21
  import { CUA_ACTOR_LAB_SCHEMA } from "./cua-actor-lab.js";
22
22
  import { openTarget, renderObserver, serveObserver } from "./observer.js";
23
- import { serveObserverStatic } from "./observer-static.js";
24
23
  import { SERVE_SCHEMA, serveObserverLibrary } from "./observer-serve.js";
25
24
  import { startExposedObserver, validateExposure } from "./serve-exposure.js";
26
25
  import { ServeTunnelError } from "./serve-tunnel.js";
@@ -31,7 +30,7 @@ import { reclaimRunSandboxes } from "./reclaim.js";
31
30
  import { RunIndexCache, readRunIndex } from "./run-index.js";
32
31
  import { readLabSummary } from "./lab-summary.js";
33
32
  import { readProjectState } from "./tui-project.js";
34
- import { openObserverArtifact, stopRun, TUI_ACTION_SCHEMA } from "./tui-actions.js";
33
+ import { createTuiObserverSession, stopRun, TUI_ACTION_SCHEMA } from "./tui-actions.js";
35
34
  import { readRunDetail } from "./run-detail.js";
36
35
  import { launchRun, readLaunchLogTail } from "./tui-launch.js";
37
36
  import { TUI_MIN_NODE_MAJOR, nodeSupportsTui, tuiBundleUrl } from "./tui-contract.js";
@@ -613,40 +612,47 @@ function registerTuiCommand(parent, io) {
613
612
  });
614
613
  return;
615
614
  }
616
- const exitCode = await loaded.startTui({
617
- cwd: resolve(options.cwd),
618
- version: { cli: CLI_VERSION },
619
- capabilities: {
620
- // One cache for the life of the surface: it refreshes on a cadence, and re-walking every
621
- // run tree each tick is the cost this index exists to avoid.
622
- readRunIndex: (target, readOptions) => readRunIndex(target, { ...readOptions, cache: runIndexCache }),
623
- listLabs: listLabManifests,
624
- startRun: launchRun,
625
- readLaunchLog: readLaunchLogTail,
626
- readRunDetail,
627
- readLabSummary,
628
- readProjectState,
629
- openObserver: openObserverArtifact,
630
- reclaimRun: (target, runId) => reclaimRunSandboxes(target, runId),
631
- stopRun,
632
- initProject: async (target) => {
633
- const result = await runInit({ cwd: target, yes: true });
634
- return result.ok
635
- ? {
636
- schema: TUI_ACTION_SCHEMA,
637
- ok: true,
638
- message: `set up humanish here — ${result.changes.filter((change) => change.action !== "skip").length} files written`
639
- }
640
- : {
641
- schema: TUI_ACTION_SCHEMA,
642
- ok: false,
643
- message: result.error?.message ?? "humanish init could not set this directory up"
644
- };
645
- }
646
- },
647
- stdin,
648
- stdout
649
- });
615
+ const observerSession = createTuiObserverSession(resolve(options.cwd));
616
+ let exitCode;
617
+ try {
618
+ exitCode = await loaded.startTui({
619
+ cwd: resolve(options.cwd),
620
+ version: { cli: CLI_VERSION },
621
+ capabilities: {
622
+ // One cache for the life of the surface: it refreshes on a cadence, and re-walking every
623
+ // run tree each tick is the cost this index exists to avoid.
624
+ readRunIndex: (target, readOptions) => readRunIndex(target, { ...readOptions, cache: runIndexCache }),
625
+ listLabs: listLabManifests,
626
+ startRun: launchRun,
627
+ readLaunchLog: readLaunchLogTail,
628
+ readRunDetail,
629
+ readLabSummary,
630
+ readProjectState,
631
+ openObserver: (target, observerPath) => observerSession.open(target, observerPath),
632
+ reclaimRun: (target, runId) => reclaimRunSandboxes(target, runId),
633
+ stopRun,
634
+ initProject: async (target) => {
635
+ const result = await runInit({ cwd: target, yes: true });
636
+ return result.ok
637
+ ? {
638
+ schema: TUI_ACTION_SCHEMA,
639
+ ok: true,
640
+ message: `set up humanish here — ${result.changes.filter((change) => change.action !== "skip").length} files written`
641
+ }
642
+ : {
643
+ schema: TUI_ACTION_SCHEMA,
644
+ ok: false,
645
+ message: result.error?.message ?? "humanish init could not set this directory up"
646
+ };
647
+ }
648
+ },
649
+ stdin,
650
+ stdout
651
+ });
652
+ }
653
+ finally {
654
+ await observerSession.close();
655
+ }
650
656
  // The surface owned the screen; it has already told the operator whatever there was to say.
651
657
  markInvocationEnvelopeWritten(command);
652
658
  io.setExitCode(exitCode);
@@ -1419,8 +1425,8 @@ function registerWatchCommand(parent, io) {
1419
1425
  function registerObserveCommand(parent, io) {
1420
1426
  parent
1421
1427
  .command("observe")
1422
- .description("Serve a finished run's Observer over loopback http://127.0.0.1 instead of a file:// path.")
1423
- .summary("Serve a finished run's Observer over loopback http.")
1428
+ .description("Follow a run's saved evidence in Observer over loopback http://127.0.0.1.")
1429
+ .summary("Follow a run's saved evidence over loopback http.")
1424
1430
  .option("--run <id>", "Run id or latest pointer.", "latest")
1425
1431
  .option("--port <port>", "Loopback port to bind on 127.0.0.1. Defaults to an ephemeral port.", "0")
1426
1432
  .option("--cwd <path>", "Target project directory.", ".")
@@ -1462,20 +1468,15 @@ function registerObserveCommand(parent, io) {
1462
1468
  io.setExitCode(2);
1463
1469
  return;
1464
1470
  }
1465
- // Serve the run's bundle directory so the Observer's relative artifact
1466
- // links (../run.json, ../review.json, ../events.ndjson) resolve, then land
1467
- // visitors on observer/index.html. The loopback root is the run dir; the
1468
- // traversal guard still refuses anything above it (sibling runs, the
1469
- // .humanish/runs/ parent, etc.).
1470
- const observerIndexAbs = join(resolve(options.cwd), rendered.observerPath);
1471
- const runDir = dirname(dirname(observerIndexAbs));
1471
+ // Reuse the contained current-data projection, scoped to this run. A raw static
1472
+ // server would miss runtime status and could replay stored iframe grants.
1472
1473
  const wantsMachine = wantsJson(command);
1473
1474
  const shouldOpen = options.open === false
1474
1475
  ? false
1475
1476
  : options.open === true
1476
1477
  ? true
1477
1478
  : !wantsMachine && process.stdout.isTTY === true;
1478
- const server = await serveObserverStatic({ root: runDir, port, entryPath: "observer/index.html" });
1479
+ const server = await serveObserver(rendered, { open: false, port, scope: "run" });
1479
1480
  const openResult = shouldOpen ? openTarget(server.url) : { opened: false };
1480
1481
  const result = {
1481
1482
  ...rendered,