humanish 0.114.0 → 0.116.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 (204) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/CONTEXT.md +1 -1
  3. package/README.md +7 -6
  4. package/TELEMETRY.md +6 -0
  5. package/dist/actors/closing-report-limits.d.ts +11 -0
  6. package/dist/actors/closing-report-limits.js +13 -0
  7. package/dist/actors/closing-report.d.ts +68 -0
  8. package/dist/actors/closing-report.js +55 -0
  9. package/dist/actors/codex/app-server-ui.js +11 -4
  10. package/dist/actors/codex/restricted-participant-policy.d.ts +4 -47
  11. package/dist/actors/codex/restricted-participant-policy.js +12 -40
  12. package/dist/actors/computer-use/loop/debrief.d.ts +1 -10
  13. package/dist/actors/computer-use/loop/debrief.js +68 -70
  14. package/dist/actors/computer-use/loop/impressions.d.ts +2 -2
  15. package/dist/actors/computer-use/loop/impressions.js +6 -1
  16. package/dist/actors/computer-use/loop.d.ts +0 -1
  17. package/dist/actors/computer-use/loop.js +3 -3
  18. package/dist/actors/computer-use/openai-conversation.d.ts +1 -1
  19. package/dist/actors/computer-use/openai-conversation.js +3 -29
  20. package/dist/actors/computer-use/openai-provider.js +11 -5
  21. package/dist/actors/contract.d.ts +2 -20
  22. package/dist/actors/contract.js +0 -13
  23. package/dist/actors/scripted-browser/steps.js +6 -5
  24. package/dist/analysis/admission.d.ts +14 -4
  25. package/dist/analysis/admission.js +14 -9
  26. package/dist/analysis/analysis-limits.d.ts +35 -0
  27. package/dist/analysis/analysis-limits.js +41 -0
  28. package/dist/analysis/execute.d.ts +5 -0
  29. package/dist/analysis/execute.js +3 -0
  30. package/dist/analysis/finding-lead.d.ts +27 -0
  31. package/dist/analysis/finding-lead.js +23 -0
  32. package/dist/analysis/service.js +5 -3
  33. package/dist/analysis/validation.js +14 -21
  34. package/dist/cli/commands/analyze.js +2 -1
  35. package/dist/cli/commands/notes.js +5 -3
  36. package/dist/cli/commands/run-signals.js +5 -1
  37. package/dist/cli/commands/runs.js +2 -1
  38. package/dist/cli/commands/setup.js +3 -3
  39. package/dist/cli/commands/study-format.d.ts +5 -2
  40. package/dist/cli/commands/study-format.js +29 -9
  41. package/dist/cli/commands/study-route-computer-use.js +2 -2
  42. package/dist/cli/commands/study-route-scripted.js +1 -1
  43. package/dist/cli/commands/tui.js +59 -17
  44. package/dist/cli/doctor.js +9 -2
  45. package/dist/cli/findings-text.d.ts +5 -0
  46. package/dist/cli/findings-text.js +169 -0
  47. package/dist/cli/findings.d.ts +0 -4
  48. package/dist/cli/findings.js +11 -195
  49. package/dist/cli/io.js +10 -8
  50. package/dist/cli/telemetry.js +10 -22
  51. package/dist/cli/update-check.js +10 -19
  52. package/dist/cli/user-config.d.ts +11 -0
  53. package/dist/cli/user-config.js +25 -0
  54. package/dist/comms/connections.js +4 -3
  55. package/dist/comms/email-catch.js +7 -31
  56. package/dist/comms/setup.js +18 -12
  57. package/dist/evidence/encoded-text.d.ts +12 -11
  58. package/dist/evidence/encoded-text.js +81 -70
  59. package/dist/evidence/redaction.d.ts +11 -0
  60. package/dist/evidence/redaction.js +30 -11
  61. package/dist/evidence/secret-scrub.d.ts +26 -3
  62. package/dist/evidence/secret-scrub.js +172 -38
  63. package/dist/feedback/draft.d.ts +1 -1
  64. package/dist/feedback/draft.js +13 -16
  65. package/dist/feedback/export-bundle.js +21 -17
  66. package/dist/feedback/export.js +32 -46
  67. package/dist/feedback/feedback.js +31 -26
  68. package/dist/guest/desktop-keys.js +59 -5
  69. package/dist/keys/key-resolution.d.ts +9 -0
  70. package/dist/keys/key-resolution.js +62 -55
  71. package/dist/keys/key-status.d.ts +2 -0
  72. package/dist/keys/key-status.js +9 -16
  73. package/dist/observer/artifact.d.ts +1 -1
  74. package/dist/observer/http.d.ts +7 -0
  75. package/dist/observer/http.js +19 -1
  76. package/dist/observer/notes-route.d.ts +0 -1
  77. package/dist/observer/notes-route.js +24 -44
  78. package/dist/observer/pinned-files.js +4 -19
  79. package/dist/observer/render.js +6 -4
  80. package/dist/observer/run-routes.js +13 -28
  81. package/dist/observer/serve.js +2 -1
  82. package/dist/observer-app.html +7 -7
  83. package/dist/routes/computer-use/bundle-parts.d.ts +4 -4
  84. package/dist/routes/computer-use/bundle-parts.js +2 -2
  85. package/dist/routes/computer-use/bundle.d.ts +4 -5
  86. package/dist/routes/computer-use/bundle.js +1 -3
  87. package/dist/routes/computer-use/fanout-records.js +10 -11
  88. package/dist/routes/computer-use/live-phase.d.ts +1 -1
  89. package/dist/routes/computer-use/live-phase.js +0 -1
  90. package/dist/routes/computer-use/participant-execution.d.ts +3 -2
  91. package/dist/routes/computer-use/participant-runs.d.ts +6 -2
  92. package/dist/routes/computer-use/participant-runs.js +9 -5
  93. package/dist/routes/computer-use/plan.d.ts +3 -0
  94. package/dist/routes/computer-use/plan.js +14 -11
  95. package/dist/routes/computer-use/rerun-selection.js +2 -2
  96. package/dist/routes/computer-use/result.js +3 -6
  97. package/dist/routes/computer-use/setup.d.ts +4 -6
  98. package/dist/routes/computer-use/setup.js +2 -6
  99. package/dist/routes/computer-use/single-bundle.d.ts +4 -5
  100. package/dist/routes/computer-use/single-bundle.js +22 -25
  101. package/dist/routes/computer-use/subject-projection.d.ts +4 -8
  102. package/dist/routes/computer-use/subject-projection.js +9 -31
  103. package/dist/routes/computer-use/types.d.ts +4 -41
  104. package/dist/routes/scripted/scenario.js +28 -12
  105. package/dist/routes/scripted/session-result.js +6 -3
  106. package/dist/routes/shared-world/bundle-records.js +2 -8
  107. package/dist/routes/shared-world/participant-specs.d.ts +0 -2
  108. package/dist/routes/shared-world/participant-specs.js +1 -20
  109. package/dist/routes/shared-world/plan.d.ts +3 -0
  110. package/dist/routes/shared-world/plan.js +23 -3
  111. package/dist/routes/shared-world/setup.js +2 -2
  112. package/dist/routes/terminal/ledger.d.ts +9 -9
  113. package/dist/routes/terminal/ledger.js +63 -40
  114. package/dist/routes/terminal/live-finish.js +7 -10
  115. package/dist/routes/terminal/plan.d.ts +3 -0
  116. package/dist/routes/terminal/plan.js +8 -5
  117. package/dist/routes/terminal/token-usage.d.ts +1 -2
  118. package/dist/routes/terminal/token-usage.js +4 -6
  119. package/dist/routes/terminal/types.d.ts +9 -1
  120. package/dist/run/bundle-shape.js +6 -1
  121. package/dist/run/bundle.d.ts +5 -3
  122. package/dist/run/contained-output.d.ts +59 -10
  123. package/dist/run/contained-output.js +160 -68
  124. package/dist/run/detail.d.ts +2 -1
  125. package/dist/run/detail.js +12 -7
  126. package/dist/run/escape-sequences.d.ts +11 -0
  127. package/dist/run/escape-sequences.js +93 -0
  128. package/dist/run/evidence-files.d.ts +8 -1
  129. package/dist/run/evidence-files.js +24 -18
  130. package/dist/run/locate.d.ts +32 -3
  131. package/dist/run/locate.js +45 -40
  132. package/dist/run/note-files.d.ts +26 -45
  133. package/dist/run/note-files.js +86 -58
  134. package/dist/run/note-shape.d.ts +35 -0
  135. package/dist/run/note-shape.js +20 -0
  136. package/dist/run/notes.d.ts +3 -14
  137. package/dist/run/notes.js +23 -75
  138. package/dist/run/outcomes.d.ts +24 -0
  139. package/dist/run/outcomes.js +19 -0
  140. package/dist/run/participant-records.d.ts +2 -0
  141. package/dist/run/participant-records.js +17 -2
  142. package/dist/run/paths.d.ts +2 -0
  143. package/dist/run/paths.js +5 -1
  144. package/dist/run/preflight-receipts.js +13 -8
  145. package/dist/run/project.js +7 -4
  146. package/dist/run/reclaim-outcomes.d.ts +8 -6
  147. package/dist/run/reclaim-outcomes.js +10 -6
  148. package/dist/run/reclaim.d.ts +5 -0
  149. package/dist/run/reclaim.js +43 -16
  150. package/dist/run/run-clock.d.ts +50 -0
  151. package/dist/run/run-clock.js +66 -0
  152. package/dist/run/run.js +5 -2
  153. package/dist/run/sandbox-ids.d.ts +7 -2
  154. package/dist/run/sandbox-ids.js +27 -11
  155. package/dist/run/secrets.d.ts +2 -1
  156. package/dist/run/secrets.js +18 -22
  157. package/dist/run/stored-runs.js +14 -7
  158. package/dist/run/transient-comms-secrets.d.ts +6 -5
  159. package/dist/run/transient-comms-secrets.js +23 -39
  160. package/dist/run-study.js +22 -13
  161. package/dist/study/adapter-scorer-loader.js +6 -4
  162. package/dist/study/discover.js +9 -6
  163. package/dist/study/init-paths.js +7 -5
  164. package/dist/study/persona-resolve.d.ts +2 -2
  165. package/dist/study/persona-resolve.js +9 -5
  166. package/dist/study/plan-types.d.ts +2 -2
  167. package/dist/study/plan.d.ts +5 -3
  168. package/dist/study/plan.js +18 -9
  169. package/dist/study/preflight-probes.js +11 -3
  170. package/dist/study/preflight.js +9 -5
  171. package/dist/study/summary.d.ts +12 -7
  172. package/dist/study/summary.js +24 -24
  173. package/dist/study/warnings.d.ts +19 -12
  174. package/dist/study/warnings.js +39 -17
  175. package/dist/substrates/e2b/connection.d.ts +12 -0
  176. package/dist/substrates/e2b/connection.js +35 -0
  177. package/dist/substrates/e2b/desktop-executor.d.ts +1 -3
  178. package/dist/substrates/e2b/desktop-executor.js +42 -9
  179. package/dist/substrates/e2b/lifetime.d.ts +24 -4
  180. package/dist/substrates/e2b/lifetime.js +41 -4
  181. package/dist/substrates/e2b/sandbox.d.ts +4 -3
  182. package/dist/substrates/e2b/sandbox.js +13 -18
  183. package/dist/substrates/e2b/sdk.d.ts +20 -9
  184. package/dist/substrates/local/capacity.d.ts +18 -2
  185. package/dist/substrates/local/capacity.js +21 -2
  186. package/dist/substrates/local/runtime-host.js +21 -14
  187. package/dist/substrates/local/runtime.js +3 -11
  188. package/dist/tui/contract.d.ts +30 -5
  189. package/dist/tui/contract.js +4 -1
  190. package/dist/tui-app.js +149 -147
  191. package/dist/verify/artifacts.d.ts +9 -2
  192. package/dist/verify/artifacts.js +37 -13
  193. package/dist/verify/liveness.js +19 -5
  194. package/dist/verify/verify.js +54 -27
  195. package/docs/architecture/actor-contract.md +3 -3
  196. package/docs/architecture/guest-desktop.md +7 -2
  197. package/docs/architecture/restricted-codex-analysis.md +1 -1
  198. package/docs/architecture/state-driven-executor.md +5 -3
  199. package/docs/contracts/run-bundle.md +25 -13
  200. package/docs/contracts/schemas.md +38 -29
  201. package/docs/contracts/study-analysis.md +22 -5
  202. package/docs/product/automatic-analysis.md +7 -1
  203. package/package.json +8 -7
  204. package/skills/humanish/SKILL.md +1 -2
@@ -5,6 +5,7 @@ import { createHash } from "node:crypto";
5
5
  import { constants as fsConstants } from "node:fs";
6
6
  import { lstat, open, realpath } from "node:fs/promises";
7
7
  import path from "node:path";
8
+ import { readOpenedAtMost } from "../run/contained-output.js";
8
9
  import { isPathInside, isSafeRunIdSegment } from "../run/paths.js";
9
10
  /**
10
11
  * The file's bytes, or null when it cannot be read under the root's checks. With `maxBytes`, a
@@ -18,7 +19,9 @@ export async function readContainedFile(root, filePathInput, options = {}) {
18
19
  try {
19
20
  const body = options.maxBytes === undefined
20
21
  ? await opened.handle.readFile()
21
- : await readAtMost(opened.handle, opened.size, options.maxBytes);
22
+ : opened.size > options.maxBytes
23
+ ? null
24
+ : await readOpenedAtMost(opened.handle, options.maxBytes);
22
25
  if (body === null)
23
26
  return null;
24
27
  // A write that landed during the read changed the file's mtime and ctime.
@@ -79,24 +82,6 @@ export async function openContainedFile(root, filePathInput) {
79
82
  return null;
80
83
  }
81
84
  }
82
- /** At most `maxBytes` from the start of an opened file, or null when it holds more. */
83
- async function readAtMost(handle, size, maxBytes) {
84
- if (size > maxBytes)
85
- return null;
86
- const chunks = [];
87
- let total = 0;
88
- for (;;) {
89
- const chunk = Buffer.alloc(Math.min(64 * 1024, maxBytes + 1 - total));
90
- const { bytesRead } = await handle.read(chunk, 0, chunk.length, total);
91
- if (bytesRead === 0)
92
- return Buffer.concat(chunks, total);
93
- total += bytesRead;
94
- // The file grew past the limit after it was opened.
95
- if (total > maxBytes)
96
- return null;
97
- chunks.push(chunk.subarray(0, bytesRead));
98
- }
99
- }
100
85
  /** The sha256 of an opened file, read by position so the handle's own offset is untouched. */
101
86
  export async function sha256OfOpenedFile(handle) {
102
87
  const hash = createHash("sha256");
@@ -11,15 +11,16 @@ import { projectShareCheckedAnalysis } from "../analysis/sharing.js";
11
11
  import { loadAnalysis } from "../analysis/load.js";
12
12
  import { physicalCwdOf, runIdOf, bindExistingRunArtifactPaths, isSafeRunIdSegment, resolveLatestRunDirectory, validatePreparedRunArtifactPaths, } from "../run/paths.js";
13
13
  import { writeContainedOutputFile } from "../run/contained-output.js";
14
- import { loadRunBundlePrepared, readRunJsonIfExists } from "../run/locate.js";
15
- import { readRunNotes } from "../run/notes.js";
14
+ import { loadRunBundlePrepared, readRunJsonIfExists, runJsonValue } from "../run/locate.js";
15
+ import { readRunNotes } from "../run/note-files.js";
16
16
  import { RUN_STATUS_FILE } from "../run/status.js";
17
17
  import { verifyRunPrepared } from "../verify/verify.js";
18
18
  import { renderObserverHtml } from "./artifact.js";
19
19
  import { buildObserverData } from "./data.js";
20
20
  import { buildServeSecurityHeaders, hostAllowed, parsePublicOrigin } from "./http.js";
21
21
  import { listenOnLoopback } from "./listen.js";
22
- import { createNotesWriter, NOTES_PATH } from "./notes-route.js";
22
+ import { NOTES_PATH } from "../run/note-shape.js";
23
+ import { createNotesWriter } from "./notes-route.js";
23
24
  import { pinDirectChildDirectory, pinDirectory, readContainedFile, } from "./pinned-files.js";
24
25
  import { buildHistoryIndex, matchRunRoute, serveRunPath, writeResponse, } from "./run-routes.js";
25
26
  import { cli } from "../cli/invocation.js";
@@ -105,8 +106,9 @@ export async function renderObserver(cwdInput, runInput, options = {}) {
105
106
  };
106
107
  // A run.json without an outcome is in progress, interrupted, or older than the field: its
107
108
  // status.json says which, and holds an older run's ok.
109
+ // A status.json it refuses says nothing, as a missing one does: the bundle's own facts show.
108
110
  const statusRecord = loaded.bundle.outcome === undefined
109
- ? await readRunJsonIfExists(preparedRunPaths, RUN_STATUS_FILE)
111
+ ? runJsonValue(await readRunJsonIfExists(preparedRunPaths, RUN_STATUS_FILE))
110
112
  : undefined;
111
113
  const observerData = buildObserverData(loaded.bundle, undefined, statusRecord);
112
114
  observerData.publicSafety.share = {
@@ -9,7 +9,7 @@ import { listRuns } from "../run/stored-runs.js";
9
9
  import { readAnalysisAccounting } from "../run/costs.js";
10
10
  import { bindExistingRunArtifactPaths, isPathInside, isSafeRunIdSegment, } from "../run/paths.js";
11
11
  import { isRunOutcome } from "../run/bundle-shape.js";
12
- import { decodeRunNote, listNoteEntries, MAX_NOTE_FILE_BYTES, noteListing, RUN_NOTES_DIR, runNoteFile, } from "../run/note-files.js";
12
+ import { MAX_NOTE_FILE_BYTES, readRunNotes, RUN_NOTES_DIR, } from "../run/note-files.js";
13
13
  import { analysisCostOf, runCost, runCostLabel } from "../run/run-cost.js";
14
14
  import { RUN_STATUS_FILE, RUN_STATUS_STALE_MS, isRunStatusRecord, } from "../run/status.js";
15
15
  import { renderObserverHtml } from "./artifact.js";
@@ -59,33 +59,18 @@ async function readServedAnalysisSpend(runRoot) {
59
59
  }
60
60
  }
61
61
  /**
62
- * The run's reviewer notes as served: notes/ listed, and each note file read within
63
- * MAX_NOTE_FILE_BYTES through the root's checks, so a --safe root's admission and hash checks
64
- * apply to every note. A file that is not a readable note of the run is skipped and counted.
62
+ * The run's note files as served: each read through the root's checks, so a --safe root's
63
+ * admission and hash checks apply to every note.
65
64
  */
66
- async function readServedNotes(runRoot) {
67
- const runId = path.basename(runRoot.physicalPath);
68
- let listing;
69
- try {
70
- await assertPinnedDirectory(runRoot);
71
- listing = await listNoteEntries(path.join(runRoot.physicalPath, RUN_NOTES_DIR));
72
- }
73
- catch {
74
- return { runId, notes: [], skipped: [`${RUN_NOTES_DIR} is not a plain folder.`] };
75
- }
76
- if (listing === null)
77
- return { runId, notes: [], skipped: [] };
78
- const { ids, skipped } = noteListing(listing);
79
- const notes = [];
80
- for (const id of ids) {
81
- const bytes = await readContainedFile(runRoot, path.join(runRoot.physicalPath, runNoteFile(id)), { maxBytes: MAX_NOTE_FILE_BYTES });
82
- const note = bytes === null ? null : decodeRunNote(bytes, runId, id);
83
- if (note === null)
84
- skipped.push(`${runNoteFile(id)} was skipped.`);
85
- else
86
- notes.push(note);
87
- }
88
- return { runId, notes, skipped };
65
+ function servedNoteFiles(runRoot) {
66
+ return {
67
+ runId: path.basename(runRoot.physicalPath),
68
+ async directory() {
69
+ await assertPinnedDirectory(runRoot);
70
+ return runRoot.physicalPath;
71
+ },
72
+ read: (relativePath, maxBytes) => readContainedFile(runRoot, path.join(runRoot.physicalPath, relativePath), { maxBytes }),
73
+ };
89
74
  }
90
75
  /**
91
76
  * internal: consumed by src/observer/serve.ts. `notesToken` goes into the run's Observer page so
@@ -120,7 +105,7 @@ export async function serveRunPath(runRoot, relativePath, response, runtimeStrea
120
105
  return;
121
106
  }
122
107
  const analysis = await readObserverAnalysis(runRoot);
123
- const notes = await readServedNotes(runRoot);
108
+ const notes = await readRunNotes(servedNoteFiles(runRoot));
124
109
  writeResponse(response, 200, renderObserverHtml(observerData, {
125
110
  analysis,
126
111
  notes,
@@ -3,7 +3,8 @@ import { runNotFoundMessage } from "../run/run-not-found.js";
3
3
  import { createServer } from "node:http";
4
4
  import path from "node:path";
5
5
  import { pinDirectChildDirectory, pinDirectory } from "./pinned-files.js";
6
- import { createNotesWriter, NOTES_PATH } from "./notes-route.js";
6
+ import { NOTES_PATH } from "../run/note-shape.js";
7
+ import { createNotesWriter } from "./notes-route.js";
7
8
  import { renderObserver } from "./render.js";
8
9
  import { buildHistoryIndex, matchRunRoute, servedRunPaths, serveRunPath } from "./run-routes.js";
9
10
  import { hashRunInventory, inventoryRoot, readRunInventory, } from "./run-inventory.js";