humanish 0.109.0 → 0.110.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 (66) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +1 -1
  3. package/dist/analysis/automatic-config.d.ts +1 -1
  4. package/dist/cli/commands/comms.js +25 -7
  5. package/dist/cli/commands/migrate.js +15 -4
  6. package/dist/cli/commands/observe.js +4 -2
  7. package/dist/cli/commands/run-command.js +4 -3
  8. package/dist/cli/commands/runs.js +13 -3
  9. package/dist/cli/commands/setup.js +19 -5
  10. package/dist/cli/commands/study-format.js +29 -2
  11. package/dist/cli/commands/study.js +4 -3
  12. package/dist/cli/commands/tui.js +4 -3
  13. package/dist/cli/commands/watch.js +2 -2
  14. package/dist/cli/doctor.d.ts +3 -1
  15. package/dist/cli/doctor.js +5 -4
  16. package/dist/cli/io.d.ts +17 -3
  17. package/dist/cli/io.js +20 -3
  18. package/dist/comms/receiving-runtime.js +1 -1
  19. package/dist/comms/setup.js +1 -1
  20. package/dist/evidence/redaction.d.ts +15 -0
  21. package/dist/evidence/redaction.js +87 -0
  22. package/dist/feedback/export-bundle.js +11 -5
  23. package/dist/feedback/export.js +3 -0
  24. package/dist/keys/key-resolution.d.ts +7 -0
  25. package/dist/keys/key-resolution.js +10 -8
  26. package/dist/routes/computer-use/in-process-desktop.js +1 -1
  27. package/dist/routes/computer-use/live-phase.d.ts +1 -0
  28. package/dist/routes/computer-use/plan.js +3 -3
  29. package/dist/routes/computer-use/preflight.js +1 -1
  30. package/dist/routes/computer-use/setup.js +1 -1
  31. package/dist/routes/computer-use/types.d.ts +6 -0
  32. package/dist/routes/scripted/types.d.ts +1 -0
  33. package/dist/routes/shared-world/route.js +1 -1
  34. package/dist/routes/shared-world/types.d.ts +2 -0
  35. package/dist/routes/terminal/credentials.js +1 -1
  36. package/dist/routes/terminal/live-finish.js +8 -4
  37. package/dist/routes/terminal/types.d.ts +3 -0
  38. package/dist/run/bundle-shape.js +1 -0
  39. package/dist/run/bundle.d.ts +6 -0
  40. package/dist/run/reclaim.d.ts +3 -0
  41. package/dist/run/reclaim.js +10 -3
  42. package/dist/run/results.d.ts +3 -0
  43. package/dist/run/run.js +14 -8
  44. package/dist/run/sandbox-ids.d.ts +53 -0
  45. package/dist/run/sandbox-ids.js +198 -0
  46. package/dist/run/sandbox-receipts.d.ts +2 -0
  47. package/dist/run/sandbox-receipts.js +26 -0
  48. package/dist/run/status.js +5 -2
  49. package/dist/run/stored-runs.js +10 -1
  50. package/dist/run-study.js +6 -1
  51. package/dist/study/doctor.js +2 -2
  52. package/dist/study/init-templates.js +2 -2
  53. package/dist/study/migrate.d.ts +7 -2
  54. package/dist/study/migrate.js +60 -4
  55. package/dist/study/run-study-events.js +1 -1
  56. package/dist/study/run-study-options.js +3 -3
  57. package/dist/study/types.d.ts +1 -1
  58. package/dist/verify/artifacts.d.ts +4 -0
  59. package/dist/verify/artifacts.js +8 -0
  60. package/dist/verify/liveness.js +8 -4
  61. package/dist/verify/verify.d.ts +1 -1
  62. package/dist/verify/verify.js +21 -1
  63. package/docs/architecture/restricted-codex-analysis.md +1 -1
  64. package/docs/contracts/run-bundle.md +20 -1
  65. package/package.json +4 -2
  66. package/skills/humanish/SKILL.md +2 -2
@@ -2,7 +2,8 @@ import path from "node:path";
2
2
  import { listAnalysisExecutions } from "../analysis/store-executions.js";
3
3
  import { loadAnalysis } from "../analysis/load.js";
4
4
  import { analysisSharingProblems } from "../analysis/sharing.js";
5
- import { containsSensitive } from "../evidence/redaction.js";
5
+ import { containsSensitive, REDACTED_SANDBOX_ID } from "../evidence/redaction.js";
6
+ import { keyedSandboxIds, readRunSandboxIds } from "../run/sandbox-ids.js";
6
7
  import { validatePreparedRunArtifactPaths } from "../run/paths.js";
7
8
  import { RUN_BUNDLE_FILE, RUN_BUNDLE_SCHEMA } from "../run/bundle.js";
8
9
  import { isCleanupResult, isRunBundle } from "../run/bundle-shape.js";
@@ -83,11 +84,17 @@ export async function verifyResolvedRun(cwd, runInput, runPaths) {
83
84
  }));
84
85
  const derivedPublicSafetyFindings = [];
85
86
  const unscannedArtifacts = [];
87
+ const sandboxIdFiles = [];
86
88
  const publicSafetyFindings = await scanRunPublicSafetyArtifacts(runPaths, derivedPublicSafetyFindings, {
87
89
  recordingPaths: new Set(isRunBundle(bundle)
88
90
  ? bundle.streams.flatMap((stream) => (stream.recording ? [stream.recording.path] : []))
89
91
  : []),
90
92
  screenshotPaths: isRunBundle(bundle) ? streamScreenshotPaths(bundle) : new Set(),
93
+ // A run from before 0.110 with no receipts still names its ids in run.json.
94
+ sandboxIds: [
95
+ ...new Set([...(await readRunSandboxIds(runPaths)), ...keyedSandboxIds(bundle)]),
96
+ ],
97
+ sandboxIdFiles,
91
98
  }, unscannedArtifacts);
92
99
  // JSON escapes can hide a sensitive value from the byte scan while the
93
100
  // decoded recording exposes it to Observer, feedback, or analysis input.
@@ -146,6 +153,7 @@ export async function verifyResolvedRun(cwd, runInput, runPaths) {
146
153
  publicSafetyFindings,
147
154
  unscannedArtifacts,
148
155
  redactedShapeFrames,
156
+ sandboxIdFiles,
149
157
  })
150
158
  : {
151
159
  status: "blocked",
@@ -366,6 +374,18 @@ function buildShareSafety(args) {
366
374
  message: `The public-safety scan cannot read ${plural(paths.length, "file")} as text that ${paths.length === 1 ? "is not a stream screenshot under screenshots/ or a registered recording" : "are not stream screenshots under screenshots/ or registered recordings"}: ${shown}${more > 0 ? ` and ${more} more` : ""}. Review them before sharing.`,
367
375
  });
368
376
  }
377
+ // Runs from 0.110 keep raw sandbox ids only in sandbox-receipts.ndjson. An earlier run records
378
+ // them in run.json, and any file that names one is not share-ready as it is.
379
+ const rawResources = (args.bundle.providerResources ?? []).some((resource) => resource.id !== REDACTED_SANDBOX_ID);
380
+ if (rawResources || args.sandboxIdFiles.length > 0) {
381
+ const files = [
382
+ ...new Set([...(rawResources ? [RUN_BUNDLE_FILE] : []), ...args.sandboxIdFiles]),
383
+ ];
384
+ reasons.push({
385
+ code: "RAW_SANDBOX_ID",
386
+ message: `Raw sandbox ids appear in ${files.sort().join(", ")}. Runs from 0.110 keep them only in sandbox-receipts.ndjson; \`humanish export --format bundle --redact-screenshots\` writes a copy without them.`,
387
+ });
388
+ }
369
389
  const rawStreamIds = rawScreenshotStreamIds(args.bundle, args.redactedShapeFrames);
370
390
  if (rawStreamIds.length > 0) {
371
391
  reasons.push({
@@ -176,7 +176,7 @@ the following, on Linux x64:
176
176
  runs this check; see "The qualifier" below.
177
177
  3. One hosted participant study with the candidate first on `PATH` (for example
178
178
  `PATH=<evidence>/npm-<version>/node_modules/.bin:$PATH pnpm humanish run <study>
179
- --env-file <file with E2B_API_KEY only>`) reached its goal in the final capture, with a
179
+ --dotenv <file with E2B_API_KEY only>`) reached its goal in the final capture, with a
180
180
  verified request receipt, `humanish verify --run <id>` passing and the automatic Codex
181
181
  analysis recording the release. Keep `OPENAI_API_KEY` out of that environment so the
182
182
  participant stays on ChatGPT-account billing.
@@ -525,6 +525,10 @@ bundle is safe to promote into a public issue. Public promotion should branch on
525
525
 
526
526
  - `share_ready`: feedback draft commands may render public issue payloads;
527
527
  - `local_only`: keep the run local; only supported redaction-only cases can produce a shareable derivative;
528
+ `RAW_SANDBOX_ID` is one: a file other than `sandbox-receipts.ndjson` names one of the run's raw
529
+ sandbox ids, which verify reads from the receipts and from any raw `providerResources[].id` in
530
+ `run.json`, or a JSON file holds a raw id at a sandbox-id key. Runs from 0.110 keep raw ids only in the receipts, so it fires on runs recorded
531
+ before 0.110, whose `run.json` holds them, until they are exported;
528
532
  - `blocked`: fix the verification or public-safety failure first.
529
533
 
530
534
  `ok: true` also does not mean the run finished. A run killed mid-way leaves an
@@ -540,7 +544,9 @@ writing; an older one reads as interrupted. The warning names what verify saw:
540
544
  there is no usable record;
541
545
  - how many streams are still `running`;
542
546
  - what `reclaim-receipt.json` records: how many of the run's sandboxes are gone
543
- (killed or already gone), and how many journaled sandboxes it does not cover;
547
+ (killed or already gone), and how many journaled sandboxes it does not cover. It
548
+ matches its outcomes to the receipts by `sandboxIdDigest`; a reclaim receipt from
549
+ before 0.110 names raw ids, which are digested to match;
544
550
  - with journaled sandboxes and no reclaim receipt, the command that stops them:
545
551
  `humanish reclaim --run <id>`.
546
552
 
@@ -633,6 +639,19 @@ The receipt describes the transformation; it does not attest that a participant'
633
639
  finding is true. Its own bytes are not included in its hash inventory. Feedback
634
640
  commands can subsequently generate new derivative-local artifacts.
635
641
 
642
+ The derivative names no sandbox. In every JSON and NDJSON file it copies, the
643
+ values at `sandboxId`, `subjectSandboxId`, each `providerResources[].id` and each
644
+ cleanup.json `resources[].id` read `[redacted-sandbox-id]`, with the id's digest
645
+ beside them. In every text file it copies, Markdown, logs and YAML included, each
646
+ id the source names becomes `[redacted-sandbox-id <digest>]`: the ids in its
647
+ `sandbox-receipts.ndjson`, and any raw id at one of those keys, which is where a
648
+ run recorded before 0.110 with no receipts names them. Only those exact ids are
649
+ replaced, so the rest of each file is unchanged. In YAML the label is
650
+ `redacted-sandbox-id-<digest>`, without brackets, so a value keeps its type.
651
+ An id that appears only in free text, in a run with no receipts, is not known to
652
+ export. `sandbox-receipts.ndjson` is omitted, and the source keeps its raw ids,
653
+ which reclaim reads.
654
+
636
655
  PNG files that actor traces reference as stream screenshots are re-encoded as
637
656
  blurred thumbnails. A PNG that nothing in `run.json` cites is omitted and
638
657
  inventoried. Export refuses a run whose feedback candidates, adapter artifacts or
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "humanish",
3
- "version": "0.109.0",
3
+ "version": "0.110.0",
4
4
  "description": "Synthetic user research for apps, CLIs, and agent-facing product flows.",
5
5
  "keywords": [
6
6
  "cli",
@@ -56,9 +56,10 @@
56
56
  },
57
57
  "scripts": {
58
58
  "build": "tsc -p tsconfig.build.json && pnpm --filter humanish-observer build && pnpm --filter humanish-tui build && node scripts/finish-build.mjs",
59
- "check": "pnpm format:check && pnpm lint && pnpm knip && pnpm prose:check && pnpm vocabulary:check && pnpm site-css:check && pnpm typecheck && pnpm test && pnpm tui:test && pnpm build && pnpm guest-media:startup:proof && pnpm cli:startup:test && pnpm cli:preflight:test && pnpm tui:smoke",
59
+ "check": "pnpm format:check && pnpm lint && pnpm knip && pnpm prose:check && pnpm vocabulary:check && pnpm site-css:check && pnpm typecheck && pnpm test && pnpm tui:test && pnpm build && pnpm guest-media:startup:proof && pnpm cli:startup:test && pnpm cli:preflight:test && pnpm cli:dotenv:test && pnpm tui:smoke",
60
60
  "cli:startup:test": "node scripts/terminal-startup-exit-proof.mjs",
61
61
  "cli:preflight:test": "node scripts/task-route-preflight-proof.mjs",
62
+ "cli:dotenv:test": "node scripts/dotenv-proof.mjs",
62
63
  "humanish": "tsx src/cli.ts",
63
64
  "pack:dry-run": "npm pack --dry-run",
64
65
  "prepack": "pnpm build",
@@ -91,6 +92,7 @@
91
92
  "prose:check": "node scripts/check-code-prose.mjs",
92
93
  "vocabulary:check": "tsx scripts/check-retired-words.ts",
93
94
  "site-css:check": "node scripts/check-site-css.mjs",
95
+ "site:tour": "tsx scripts/site-tour.ts",
94
96
  "site:hero:proof": "node scripts/site-hero-wrap-proof.mjs"
95
97
  },
96
98
  "dependencies": {
@@ -16,7 +16,7 @@ patient data, or private upstream artifacts.
16
16
 
17
17
  Do not edit `.env` or secret files. Do not paste credential values. Use env var
18
18
  names only, usually `OPENAI_API_KEY` and `E2B_API_KEY`. For live local runs,
19
- prefer an explicit ignored env file passed with `--env-file <path>`; do not
19
+ prefer an explicit ignored env file passed with `--dotenv <path>`; do not
20
20
  assume broad inherited job env is safe. Stop before live provider spend,
21
21
  hosted execution, deploys, public tunnels, or GitHub mutation unless the user
22
22
  explicitly approves that exact action.
@@ -442,7 +442,7 @@ Do not paste values into files, prompts, run bundles, issue drafts, or logs.
442
442
  Load local values only at invocation time:
443
443
 
444
444
  ```bash
445
- npx humanish watch .humanish/studies/local-live.yaml --env-file .humanish/local/provider.env
445
+ npx humanish watch .humanish/studies/local-live.yaml --dotenv .humanish/local/provider.env
446
446
  ```
447
447
 
448
448
  When choosing dogfood targets, prefer apps, CLIs, or agent-facing tools with a