humanish 0.95.0 → 0.96.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/README.md +4 -2
- package/dist/comms-agentmail.d.ts +25 -0
- package/dist/comms-agentmail.js +418 -0
- package/dist/comms-agentmail.js.map +1 -0
- package/dist/comms-connections.d.ts +4 -2
- package/dist/comms-connections.js +3 -3
- package/dist/comms-connections.js.map +1 -1
- package/dist/comms-lease-store.d.ts +90 -0
- package/dist/comms-lease-store.js +489 -0
- package/dist/comms-lease-store.js.map +1 -0
- package/dist/comms-receiving-evidence.d.ts +46 -0
- package/dist/comms-receiving-evidence.js +35 -0
- package/dist/comms-receiving-evidence.js.map +1 -0
- package/dist/comms-receiving-inbox.d.ts +16 -0
- package/dist/comms-receiving-inbox.js +410 -0
- package/dist/comms-receiving-inbox.js.map +1 -0
- package/dist/comms-receiving-runtime.d.ts +25 -0
- package/dist/comms-receiving-runtime.js +45 -0
- package/dist/comms-receiving-runtime.js.map +1 -0
- package/dist/comms-receiving-types.d.ts +98 -0
- package/dist/comms-receiving-types.js +2 -0
- package/dist/comms-receiving-types.js.map +1 -0
- package/dist/comms-receiving.d.ts +58 -0
- package/dist/comms-receiving.js +554 -0
- package/dist/comms-receiving.js.map +1 -0
- package/dist/comms-setup.d.ts +40 -0
- package/dist/comms-setup.js +121 -0
- package/dist/comms-setup.js.map +1 -0
- package/dist/concurrent-shared-world-lab.js +662 -624
- package/dist/concurrent-shared-world-lab.js.map +1 -1
- package/dist/cua-actor-lab.d.ts +4 -1
- package/dist/cua-actor-lab.js +98 -17
- package/dist/cua-actor-lab.js.map +1 -1
- package/dist/doctor-lab.js +11 -0
- package/dist/doctor-lab.js.map +1 -1
- package/dist/e2b-terminal-lab.js +3 -0
- package/dist/e2b-terminal-lab.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/lab-config.d.ts +20 -3
- package/dist/lab-config.js +59 -6
- package/dist/lab-config.js.map +1 -1
- package/dist/lab-engine.js +8 -3
- package/dist/lab-engine.js.map +1 -1
- package/dist/lab-summary.d.ts +1 -0
- package/dist/lab-summary.js +8 -2
- package/dist/lab-summary.js.map +1 -1
- package/dist/observer-app.html +1 -1
- package/dist/observer-data.js +14 -1
- package/dist/observer-data.js.map +1 -1
- package/dist/oss-lab.d.ts +1 -1
- package/dist/oss-lab.js.map +1 -1
- package/dist/oss-meta-lab.d.ts +1 -1
- package/dist/oss-meta-lab.js.map +1 -1
- package/dist/program.d.ts +2 -0
- package/dist/program.js +100 -4
- package/dist/program.js.map +1 -1
- package/dist/run-narration-secrets.d.ts +5 -0
- package/dist/run-narration-secrets.js +68 -0
- package/dist/run-narration-secrets.js.map +1 -0
- package/dist/run.d.ts +7 -2
- package/dist/run.js +25 -3
- package/dist/run.js.map +1 -1
- package/dist/scripted-browser-lab.js +7 -0
- package/dist/scripted-browser-lab.js.map +1 -1
- package/dist/shared-world-lab.js +4 -0
- package/dist/shared-world-lab.js.map +1 -1
- package/dist/study-analysis-engine.js +30 -1
- package/dist/study-analysis-engine.js.map +1 -1
- package/dist/study-analysis-evidence.js +9 -1
- package/dist/study-analysis-evidence.js.map +1 -1
- package/dist/tui-app.js +134 -134
- package/dist/tui-contract.d.ts +13 -0
- package/dist/tui-contract.js.map +1 -1
- package/dist/tui-launch.d.ts +2 -0
- package/dist/tui-launch.js +9 -1
- package/dist/tui-launch.js.map +1 -1
- package/docs/architecture/comms-inbox.md +4 -0
- package/docs/architecture/real-email-receiving.md +135 -0
- package/docs/contracts/run-bundle.md +9 -1
- package/docs/contracts/schemas.md +20 -3
- package/docs/goals/current.md +5 -5
- package/docs/ramp/README.md +9 -5
- package/docs/release/0.96.0-real-email-receiving.md +47 -0
- package/package.json +2 -1
- package/skills/humanish/SKILL.md +33 -13
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Enclose both participant execution and its automatic analysis in one scope. Nested runs isolate too. */
|
|
2
|
+
export declare function withTransientCommsSecrets<T>(work: () => Promise<T>): Promise<T>;
|
|
3
|
+
export declare function registerTransientCommsSecrets(values: string[]): void;
|
|
4
|
+
/** Literal, longest-first replacement in one pass; replacement text is never matched recursively. */
|
|
5
|
+
export declare function scrubTransientCommsText(text: string): string;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2
|
+
const scopes = new AsyncLocalStorage();
|
|
3
|
+
const MAX_VALUES = 8192;
|
|
4
|
+
const MAX_BYTES = 1024 * 1024;
|
|
5
|
+
const MAX_VALUE_BYTES = 65_536;
|
|
6
|
+
function usable(scope) {
|
|
7
|
+
if (scope.closed)
|
|
8
|
+
throw new Error("TRANSIENT_NARRATION_SCOPE_CLOSED");
|
|
9
|
+
if (scope.failed)
|
|
10
|
+
throw new Error("TRANSIENT_NARRATION_SECRET_LIMIT");
|
|
11
|
+
}
|
|
12
|
+
function fail(scope) {
|
|
13
|
+
scope.failed = true;
|
|
14
|
+
scope.values.clear();
|
|
15
|
+
delete scope.pattern;
|
|
16
|
+
throw new Error("TRANSIENT_NARRATION_SECRET_LIMIT");
|
|
17
|
+
}
|
|
18
|
+
/** Enclose both participant execution and its automatic analysis in one scope. Nested runs isolate too. */
|
|
19
|
+
export async function withTransientCommsSecrets(work) {
|
|
20
|
+
const scope = { values: new Set(), bytes: 0, closed: false, failed: false };
|
|
21
|
+
try {
|
|
22
|
+
return await scopes.run(scope, work);
|
|
23
|
+
}
|
|
24
|
+
finally {
|
|
25
|
+
// Detached work can retain an async context after return. Clear its values and refuse future
|
|
26
|
+
// scrubbing/registration there; never turn an expired scope into an unprotected analysis.
|
|
27
|
+
scope.closed = true;
|
|
28
|
+
scope.values.clear();
|
|
29
|
+
scope.bytes = 0;
|
|
30
|
+
delete scope.pattern;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export function registerTransientCommsSecrets(values) {
|
|
34
|
+
const scope = scopes.getStore();
|
|
35
|
+
if (!scope)
|
|
36
|
+
return;
|
|
37
|
+
usable(scope);
|
|
38
|
+
for (const value of values) {
|
|
39
|
+
// Match the existing narration registry: short subjects such as "Hi" are ordinary prose.
|
|
40
|
+
// Received OTP extraction starts at four characters; management keys and addresses are longer.
|
|
41
|
+
if (value.length < 4 || scope.values.has(value))
|
|
42
|
+
continue;
|
|
43
|
+
const bytes = Buffer.byteLength(value);
|
|
44
|
+
if (bytes > MAX_VALUE_BYTES || scope.values.size >= MAX_VALUES || scope.bytes + bytes > MAX_BYTES)
|
|
45
|
+
fail(scope);
|
|
46
|
+
scope.values.add(value);
|
|
47
|
+
scope.bytes += bytes;
|
|
48
|
+
delete scope.pattern;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/** Literal, longest-first replacement in one pass; replacement text is never matched recursively. */
|
|
52
|
+
export function scrubTransientCommsText(text) {
|
|
53
|
+
const scope = scopes.getStore();
|
|
54
|
+
if (!scope)
|
|
55
|
+
return text;
|
|
56
|
+
usable(scope);
|
|
57
|
+
if (!scope.values.size)
|
|
58
|
+
return text;
|
|
59
|
+
try {
|
|
60
|
+
scope.pattern ??= new RegExp([...scope.values].sort((a, b) => b.length - a.length)
|
|
61
|
+
.map(value => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|"), "g");
|
|
62
|
+
return text.replace(scope.pattern, "[REDACTED_SECRET]");
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return fail(scope);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=run-narration-secrets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-narration-secrets.js","sourceRoot":"","sources":["../src/run-narration-secrets.ts"],"names":[],"mappings":"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"}
|
package/dist/run.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CommsReceivingEvidence } from "./comms-receiving-types.js";
|
|
1
2
|
import { type CodexAppServerTrace } from "./codex-app-server.js";
|
|
2
3
|
import { type ActorStatus, type ActorTrace, type ActorTraceItem } from "./actor-contract.js";
|
|
3
4
|
import { type CuaGoalSource } from "./actor-goal-source.js";
|
|
@@ -715,6 +716,10 @@ export interface SharedWorldEvidence {
|
|
|
715
716
|
outcomes?: SharedWorldOutcome[];
|
|
716
717
|
}
|
|
717
718
|
export interface RunBundle {
|
|
719
|
+
publication?: {
|
|
720
|
+
restrictions: ["real-communications"];
|
|
721
|
+
};
|
|
722
|
+
commsReceiving?: CommsReceivingEvidence;
|
|
718
723
|
schema: typeof RUN_BUNDLE_SCHEMA;
|
|
719
724
|
runId: string;
|
|
720
725
|
mode: "dry-run" | "live";
|
|
@@ -1065,7 +1070,7 @@ export interface RunResult {
|
|
|
1065
1070
|
latestPath?: string;
|
|
1066
1071
|
warnings: string[];
|
|
1067
1072
|
error?: {
|
|
1068
|
-
code: "HUMANISH_LAB_ANALYSIS_INVALID" | "HUMANISH_LAB_ANALYSIS_UNSUPPORTED" | "HUMANISH_LAB_TASKS_UNSUPPORTED" | "HUMANISH_ACTOR_FANOUT_UNIMPLEMENTED" | "HUMANISH_APP_URL_OPTION_CONFLICT" | "HUMANISH_BROWSER_APP_CAPTURE_FAILED" | "HUMANISH_CODEX_APP_SERVER_FAILED" | "HUMANISH_LIVE_RUN_UNIMPLEMENTED" | "HUMANISH_LOCAL_CODEX_EXEC_FAILED" | "HUMANISH_LOCAL_CODEX_TUI_FAILED" | "HUMANISH_INVALID_APP_URL" | "HUMANISH_INVALID_ACTOR_CONCURRENCY" | "HUMANISH_INVALID_CWD" | "HUMANISH_INVALID_SIM_COUNT" | "HUMANISH_INVALID_TIMEOUT" | "HUMANISH_INVALID_PORT" | "HUMANISH_UNSUPPORTED_ACTOR" | "HUMANISH_UNSUPPORTED_RERUN_FLAGS" | "HUMANISH_WATCH_OPTION_CONFLICT" | "HUMANISH_LAB_SCORER_BAD_REF" | "HUMANISH_LAB_SCORER_NOT_FOUND" | "HUMANISH_LAB_SCORER_LOAD_FAILED" | "HUMANISH_LAB_SCORER_NO_HOOKS" | "HUMANISH_LAB_SCORER_UNSUPPORTED_BACKEND";
|
|
1073
|
+
code: "HUMANISH_LAB_ANALYSIS_INVALID" | "HUMANISH_LAB_ANALYSIS_UNSUPPORTED" | "HUMANISH_LAB_TASKS_UNSUPPORTED" | "HUMANISH_LAB_COMMS_UNSUPPORTED" | "HUMANISH_ACTOR_FANOUT_UNIMPLEMENTED" | "HUMANISH_APP_URL_OPTION_CONFLICT" | "HUMANISH_BROWSER_APP_CAPTURE_FAILED" | "HUMANISH_CODEX_APP_SERVER_FAILED" | "HUMANISH_LIVE_RUN_UNIMPLEMENTED" | "HUMANISH_LOCAL_CODEX_EXEC_FAILED" | "HUMANISH_LOCAL_CODEX_TUI_FAILED" | "HUMANISH_INVALID_APP_URL" | "HUMANISH_INVALID_ACTOR_CONCURRENCY" | "HUMANISH_INVALID_CWD" | "HUMANISH_INVALID_SIM_COUNT" | "HUMANISH_INVALID_TIMEOUT" | "HUMANISH_INVALID_PORT" | "HUMANISH_UNSUPPORTED_ACTOR" | "HUMANISH_UNSUPPORTED_RERUN_FLAGS" | "HUMANISH_WATCH_OPTION_CONFLICT" | "HUMANISH_LAB_SCORER_BAD_REF" | "HUMANISH_LAB_SCORER_NOT_FOUND" | "HUMANISH_LAB_SCORER_LOAD_FAILED" | "HUMANISH_LAB_SCORER_NO_HOOKS" | "HUMANISH_LAB_SCORER_UNSUPPORTED_BACKEND";
|
|
1069
1074
|
message: string;
|
|
1070
1075
|
};
|
|
1071
1076
|
}
|
|
@@ -1085,7 +1090,7 @@ export interface VerifyResult {
|
|
|
1085
1090
|
shareSafety: {
|
|
1086
1091
|
status: "share_ready" | "local_only" | "blocked";
|
|
1087
1092
|
reasons: Array<{
|
|
1088
|
-
code: "VERIFY_FAILED" | "PUBLIC_SAFETY_FINDINGS" | "ANALYSIS_UNVERIFIED" | "RAW_SCREENSHOTS";
|
|
1093
|
+
code: "VERIFY_FAILED" | "PUBLIC_SAFETY_FINDINGS" | "ANALYSIS_UNVERIFIED" | "RAW_SCREENSHOTS" | "REAL_COMMUNICATIONS";
|
|
1089
1094
|
message: string;
|
|
1090
1095
|
}>;
|
|
1091
1096
|
};
|
package/dist/run.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isCommsReceivingEvidence } from "./comms-receiving-evidence.js";
|
|
1
2
|
import { randomUUID } from "node:crypto";
|
|
2
3
|
import { spawn } from "node:child_process";
|
|
3
4
|
import { lstat, readdir, readFile, realpath, stat } from "node:fs/promises";
|
|
@@ -3158,7 +3159,19 @@ export async function doctor(cwdInput, options = {}) {
|
|
|
3158
3159
|
};
|
|
3159
3160
|
const env = options.env ?? process.env;
|
|
3160
3161
|
const agents = await detectLocalAgents({ ...options.localAgents, env });
|
|
3161
|
-
const
|
|
3162
|
+
const keyNames = new Set(["OPENAI_API_KEY", "E2B_API_KEY", "GH_TOKEN", "CODEX_API_KEY"]);
|
|
3163
|
+
let receivingKey = null;
|
|
3164
|
+
if (options.lab) {
|
|
3165
|
+
const { resolveLabManifest } = await import("./labs.js");
|
|
3166
|
+
const resolved = await resolveLabManifest(cwd, options.lab);
|
|
3167
|
+
if (resolved.ok && resolved.config.comms?.email?.kind === "real") {
|
|
3168
|
+
const { receivingRequiredKey } = await import("./comms-setup.js");
|
|
3169
|
+
receivingKey = await receivingRequiredKey(cwd, resolved.config.comms.email.connection);
|
|
3170
|
+
if (receivingKey)
|
|
3171
|
+
keyNames.add(receivingKey);
|
|
3172
|
+
}
|
|
3173
|
+
}
|
|
3174
|
+
const probes = await probeKeySources([...keyNames], { cwd, env });
|
|
3162
3175
|
const setup = options.lab ? await labSetupChecks({ cwd, lab: options.lab, env, agents,
|
|
3163
3176
|
keyPresent: name => probes.some(probe => probe.name === name && probe.source !== null) }) : undefined;
|
|
3164
3177
|
const checks = [
|
|
@@ -3255,6 +3268,9 @@ export async function doctor(cwdInput, options = {}) {
|
|
|
3255
3268
|
...await (async () => {
|
|
3256
3269
|
return probes.map((probe) => {
|
|
3257
3270
|
const present = probe.source !== null;
|
|
3271
|
+
const hint = probe.name === receivingKey
|
|
3272
|
+
? `provide ${probe.name} through process env or --env-file`
|
|
3273
|
+
: probe.hint;
|
|
3258
3274
|
// GH_TOKEN is needed only for private clone subjects, so its absence is informational.
|
|
3259
3275
|
const required = setup ? setup.keys.includes(probe.name) : probe.name === "E2B_API_KEY"
|
|
3260
3276
|
|| probe.name === "OPENAI_API_KEY" && !agents.some(agent => agent.authStatus === "authenticated");
|
|
@@ -3264,8 +3280,8 @@ export async function doctor(cwdInput, options = {}) {
|
|
|
3264
3280
|
message: present
|
|
3265
3281
|
? `supplied by ${probe.source}; presence only, validity not tested`
|
|
3266
3282
|
: required
|
|
3267
|
-
? `missing from every source — ${
|
|
3268
|
-
: `not required for ${setup ? "the selected participant route" : "every route"}; ${
|
|
3283
|
+
? `missing from every source — ${hint}`
|
|
3284
|
+
: `not required for ${setup ? "the selected participant route" : "every route"}; ${hint}`
|
|
3269
3285
|
};
|
|
3270
3286
|
});
|
|
3271
3287
|
})(),
|
|
@@ -4170,6 +4186,9 @@ function buildShareSafety(args) {
|
|
|
4170
4186
|
message: "Text artifacts or public-proof paths matched known secret, token, local-path, browser-profile, or hosted-substrate URL patterns."
|
|
4171
4187
|
});
|
|
4172
4188
|
}
|
|
4189
|
+
if (args.bundle.publication !== undefined || args.bundle.commsReceiving !== undefined) {
|
|
4190
|
+
reasons.push({ code: "REAL_COMMUNICATIONS", message: "This study used real email. Message content may appear in recordings, narration or analysis. Local review is supported; screenshot blurring does not make it public-safe." });
|
|
4191
|
+
}
|
|
4173
4192
|
const rawStreamIds = rawScreenshotStreamIds(args.bundle);
|
|
4174
4193
|
if (rawStreamIds.length > 0) {
|
|
4175
4194
|
reasons.push({
|
|
@@ -5186,6 +5205,9 @@ function redactSensitiveText(text) {
|
|
|
5186
5205
|
function isRunBundle(value) {
|
|
5187
5206
|
return isRecord(value)
|
|
5188
5207
|
&& value.schema === RUN_BUNDLE_SCHEMA
|
|
5208
|
+
&& (value.commsReceiving === undefined || isCommsReceivingEvidence(value.commsReceiving))
|
|
5209
|
+
&& (value.publication === undefined || (isRecord(value.publication) && Array.isArray(value.publication.restrictions)
|
|
5210
|
+
&& value.publication.restrictions.length === 1 && value.publication.restrictions[0] === "real-communications"))
|
|
5189
5211
|
&& typeof value.runId === "string"
|
|
5190
5212
|
&& (value.mode === "dry-run" || value.mode === "live")
|
|
5191
5213
|
&& isPositiveSafeInteger(value.simCount)
|