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.
- package/CHANGELOG.md +20 -0
- package/README.md +1 -1
- package/dist/analysis/automatic-config.d.ts +1 -1
- package/dist/cli/commands/comms.js +25 -7
- package/dist/cli/commands/migrate.js +15 -4
- package/dist/cli/commands/observe.js +4 -2
- package/dist/cli/commands/run-command.js +4 -3
- package/dist/cli/commands/runs.js +13 -3
- package/dist/cli/commands/setup.js +19 -5
- package/dist/cli/commands/study-format.js +29 -2
- package/dist/cli/commands/study.js +4 -3
- package/dist/cli/commands/tui.js +4 -3
- package/dist/cli/commands/watch.js +2 -2
- package/dist/cli/doctor.d.ts +3 -1
- package/dist/cli/doctor.js +5 -4
- package/dist/cli/io.d.ts +17 -3
- package/dist/cli/io.js +20 -3
- package/dist/comms/receiving-runtime.js +1 -1
- package/dist/comms/setup.js +1 -1
- package/dist/evidence/redaction.d.ts +15 -0
- package/dist/evidence/redaction.js +87 -0
- package/dist/feedback/export-bundle.js +11 -5
- package/dist/feedback/export.js +3 -0
- package/dist/keys/key-resolution.d.ts +7 -0
- package/dist/keys/key-resolution.js +10 -8
- package/dist/routes/computer-use/in-process-desktop.js +1 -1
- package/dist/routes/computer-use/live-phase.d.ts +1 -0
- package/dist/routes/computer-use/plan.js +3 -3
- package/dist/routes/computer-use/preflight.js +1 -1
- package/dist/routes/computer-use/setup.js +1 -1
- package/dist/routes/computer-use/types.d.ts +6 -0
- package/dist/routes/scripted/types.d.ts +1 -0
- package/dist/routes/shared-world/route.js +1 -1
- package/dist/routes/shared-world/types.d.ts +2 -0
- package/dist/routes/terminal/credentials.js +1 -1
- package/dist/routes/terminal/live-finish.js +8 -4
- package/dist/routes/terminal/types.d.ts +3 -0
- package/dist/run/bundle-shape.js +1 -0
- package/dist/run/bundle.d.ts +6 -0
- package/dist/run/reclaim.d.ts +3 -0
- package/dist/run/reclaim.js +10 -3
- package/dist/run/results.d.ts +3 -0
- package/dist/run/run.js +14 -8
- package/dist/run/sandbox-ids.d.ts +53 -0
- package/dist/run/sandbox-ids.js +198 -0
- package/dist/run/sandbox-receipts.d.ts +2 -0
- package/dist/run/sandbox-receipts.js +26 -0
- package/dist/run/status.js +5 -2
- package/dist/run/stored-runs.js +10 -1
- package/dist/run-study.js +6 -1
- package/dist/study/doctor.js +2 -2
- package/dist/study/init-templates.js +2 -2
- package/dist/study/migrate.d.ts +7 -2
- package/dist/study/migrate.js +60 -4
- package/dist/study/run-study-events.js +1 -1
- package/dist/study/run-study-options.js +3 -3
- package/dist/study/types.d.ts +1 -1
- package/dist/verify/artifacts.d.ts +4 -0
- package/dist/verify/artifacts.js +8 -0
- package/dist/verify/liveness.js +8 -4
- package/dist/verify/verify.d.ts +1 -1
- package/dist/verify/verify.js +21 -1
- package/docs/architecture/restricted-codex-analysis.md +1 -1
- package/docs/contracts/run-bundle.md +20 -1
- package/package.json +4 -2
- package/skills/humanish/SKILL.md +2 -2
package/dist/verify/verify.js
CHANGED
|
@@ -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
|
-
--
|
|
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.
|
|
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": {
|
package/skills/humanish/SKILL.md
CHANGED
|
@@ -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 `--
|
|
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 --
|
|
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
|