humanish 0.21.0 → 0.22.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.
@@ -0,0 +1,27 @@
1
+ import type { CommsMessage } from "./comms-types.js";
2
+ export declare const COMMS_THREAD_SCHEMA = "humanish.comms-thread.v1";
3
+ export interface CommsThreadEntry {
4
+ id: string;
5
+ channel: CommsMessage["channel"];
6
+ /** sha256-16 of the raw sender address. */
7
+ fromDigest: string;
8
+ /** sha256-16 of each recipient inbox address. */
9
+ toDigests: string[];
10
+ /** sha256-16 of the subject (non-reversible for a PII subject; correlates identical subjects). */
11
+ subjectDigest?: string;
12
+ /** sha256-16 of each actionable link (high-entropy → non-reversible). */
13
+ linkDigests: string[];
14
+ /** COUNT ONLY — a short OTP's digest is reversible, so the code itself never lands here. */
15
+ codeCount: number;
16
+ sentAt: number;
17
+ deliveredAt: number;
18
+ }
19
+ export interface CommsThreadArtifact {
20
+ schema: typeof COMMS_THREAD_SCHEMA;
21
+ channel: CommsMessage["channel"];
22
+ count: number;
23
+ thread: CommsThreadEntry[];
24
+ }
25
+ /** Project polled inbox messages into the digest-only thread artifact. Pure; the caller writes it into
26
+ * the run dir and registers it as an adapter-artifact. */
27
+ export declare function buildCommsThreadArtifact(messages: CommsMessage[]): CommsThreadArtifact;
@@ -0,0 +1,31 @@
1
+ // Digest-only evidence for a captured comms thread (#297). Proves "the verification mail arrived and
2
+ // the persona could act on it" WITHOUT persisting raw PHI. Written as an adapter-artifact
3
+ // (humanish.comms-thread.v1), so it inherits the bundle's existence-verify + public-safety scan.
4
+ //
5
+ // Digest discipline (deliberate, see below): addresses + links are digested (high entropy → the digest
6
+ // is not reversible). The subject is DIGESTED too, not stored as text — redactText only scrubs
7
+ // secret-SHAPED tokens/paths, not free-form PII (the #108 gap), so a subject like "results for <name>"
8
+ // would pass through verbatim; a sha256-16 keeps a PII subject non-reversible while still letting you
9
+ // correlate identical subjects. OTP CODES are a COUNT ONLY, never digested — a sha256 of a 6-digit code
10
+ // has ~10^6 preimages and is trivially brute-forced back to the code, so a "code digest" would leak it.
11
+ // Net: NO raw address/subject/link/OTP text ever lands in the artifact. Same caution as the lobby code.
12
+ import { digestText } from "./redaction.js";
13
+ export const COMMS_THREAD_SCHEMA = "humanish.comms-thread.v1";
14
+ /** Project polled inbox messages into the digest-only thread artifact. Pure; the caller writes it into
15
+ * the run dir and registers it as an adapter-artifact. */
16
+ export function buildCommsThreadArtifact(messages) {
17
+ const channel = messages[0]?.channel ?? "email";
18
+ const thread = messages.map((message) => ({
19
+ id: message.id,
20
+ channel: message.channel,
21
+ fromDigest: digestText(message.from, 16),
22
+ toDigests: message.to.map((address) => address.digest),
23
+ ...(message.subject === undefined ? {} : { subjectDigest: digestText(message.subject, 16) }),
24
+ linkDigests: message.links.map((link) => digestText(link, 16)),
25
+ codeCount: message.codes.length,
26
+ sentAt: message.sentAt,
27
+ deliveredAt: message.deliveredAt
28
+ }));
29
+ return { schema: COMMS_THREAD_SCHEMA, channel, count: thread.length, thread };
30
+ }
31
+ //# sourceMappingURL=comms-evidence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comms-evidence.js","sourceRoot":"","sources":["../src/comms-evidence.ts"],"names":[],"mappings":"AAAA,qGAAqG;AACrG,0FAA0F;AAC1F,iGAAiG;AACjG,EAAE;AACF,uGAAuG;AACvG,+FAA+F;AAC/F,uGAAuG;AACvG,sGAAsG;AACtG,wGAAwG;AACxG,wGAAwG;AACxG,wGAAwG;AAGxG,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE5C,MAAM,CAAC,MAAM,mBAAmB,GAAG,0BAA0B,CAAC;AA0B9D;2DAC2D;AAC3D,MAAM,UAAU,wBAAwB,CAAC,QAAwB;IAC/D,MAAM,OAAO,GAA4B,QAAQ,CAAC,CAAC,CAAC,EAAE,OAAO,IAAI,OAAO,CAAC;IACzE,MAAM,MAAM,GAAuB,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAC5D,EAAE,EAAE,OAAO,CAAC,EAAE;QACd,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,UAAU,EAAE,UAAU,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;QACxC,SAAS,EAAE,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC;QACtD,GAAG,CAAC,OAAO,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,UAAU,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC;QAC5F,WAAW,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC9D,SAAS,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM;QAC/B,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,WAAW,EAAE,OAAO,CAAC,WAAW;KACjC,CAAC,CAAC,CAAC;IACJ,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;AAChF,CAAC"}
@@ -0,0 +1,63 @@
1
+ import type { CommsChannel } from "./comms-types.js";
2
+ import { type EmailSendProfile } from "./comms-email-catch.js";
3
+ import { type DetachedTimers } from "./e2b-detached.js";
4
+ import type { E2BDesktopSandbox } from "./e2b-desktop-launch.js";
5
+ /** The default in-sandbox loopback port for the catch. Fixed (not ephemeral) so the injected base-URL
6
+ * env is known before `createDesktopSandbox`. 8025 is the conventional local-mail-UI port and is
7
+ * unlikely to collide with a subject app; override via config if it does. */
8
+ export declare const DEFAULT_SANDBOX_CATCH_PORT = 8025;
9
+ /**
10
+ * The self-contained in-sandbox capture server (a plain node ESM string — runs on the sandbox's own
11
+ * node, imports nothing from humanish). It is DELIBERATELY dumb: it records each POST verbatim as an
12
+ * NDJSON line `{t, path, body}` and returns a plausible provider success — all normalization/profile
13
+ * parsing happens host-side on the drained lines, so the typed, tested profiles stay in one place.
14
+ * argv: <port> <deliveriesFile>.
15
+ */
16
+ export declare const SANDBOX_CATCH_SCRIPT: string;
17
+ export interface DeployCommsCatchOptions {
18
+ /** Fixed loopback port the catch listens on (default 8025). Must be free inside the sandbox. */
19
+ port?: number;
20
+ /** In-sandbox working dir for the script + NDJSON (default /tmp/humanish-comms). */
21
+ dir?: string;
22
+ /** Detached-process name ([a-z0-9-]); default "comms-catch". */
23
+ name?: string;
24
+ /** Readiness-probe budget (ms) for the catch's /health (default 15000). */
25
+ readyTimeoutMs?: number;
26
+ requestTimeoutMs?: number;
27
+ timers?: DetachedTimers;
28
+ }
29
+ export interface DeployedCommsCatch {
30
+ port: number;
31
+ /** Inject THIS as the app's email-API base URL (e.g. RESEND_API_URL) — the sandbox's own loopback. */
32
+ baseUrl: string;
33
+ deliveriesPath: string;
34
+ /** Whether the catch's /health returned OUR service marker within the readiness budget. Callers MUST
35
+ * treat `ready === false` as fatal (do not inject baseUrl into a dead catch — the app's sends would
36
+ * silently fail with nothing captured). */
37
+ ready: boolean;
38
+ }
39
+ /** A raw send the in-sandbox catch captured (host-side parsing happens in routeCapturedSends). */
40
+ export interface RawCapturedSend {
41
+ path: string;
42
+ body: string;
43
+ t: number;
44
+ }
45
+ /**
46
+ * Write + launch the in-sandbox catch (detached), then probe it ready. Call AFTER the subject sandbox
47
+ * is created and BEFORE the subject app's serve.start, so the base URL resolves at the app's boot.
48
+ */
49
+ export declare function deployCommsCatch(desktop: E2BDesktopSandbox, options?: DeployCommsCatchOptions): Promise<DeployedCommsCatch>;
50
+ /**
51
+ * Drain new captured sends from the in-sandbox NDJSON since `cursor` (a line count). Returns the fresh
52
+ * sends and the new cursor. Cheap `cat` over commands.run; NDJSON is small for a run.
53
+ */
54
+ export declare function drainCommsCatch(desktop: E2BDesktopSandbox, deployed: Pick<DeployedCommsCatch, "deliveriesPath">, cursor?: number, requestTimeoutMs?: number): Promise<{
55
+ sends: RawCapturedSend[];
56
+ cursor: number;
57
+ }>;
58
+ /**
59
+ * Parse drained raw sends with the host profiles and route them into the CommsChannel (the host-side
60
+ * FauxInbox). Returns the number of inbox deliveries made. Same profiles as the host catch, so the
61
+ * in-sandbox and in-process routes normalize identically.
62
+ */
63
+ export declare function routeCapturedSends(sends: RawCapturedSend[], channel: CommsChannel, profiles?: EmailSendProfile[]): Promise<number>;
@@ -0,0 +1,157 @@
1
+ // Deploy the vendor-neutral email catch INSIDE the subject E2B sandbox and bridge captured sends back
2
+ // to the host bus (#297 config-block core). The host `startEmailCatchServer` binds the HOST's loopback,
3
+ // which a sandboxed app cannot reach — `127.0.0.1:PORT` from the app is the SANDBOX's loopback. So the
4
+ // listener must live in the sandbox: we write a tiny self-contained capture server (no deps, no host
5
+ // import) into the sandbox, launch it detached (the same substrate that serves the subject app), and
6
+ // each poll `cat` its append-only NDJSON of captured sends back to the host, where the real profiles
7
+ // parse them and route into the CommsChannel. A FIXED loopback port is chosen up front so the app's
8
+ // injected base-URL env (`http://127.0.0.1:<port>`) is known before the sandbox is created.
9
+ import { DEFAULT_EMAIL_PROFILES } from "./comms-email-catch.js";
10
+ import { startDetachedProcess } from "./e2b-detached.js";
11
+ /** The default in-sandbox loopback port for the catch. Fixed (not ephemeral) so the injected base-URL
12
+ * env is known before `createDesktopSandbox`. 8025 is the conventional local-mail-UI port and is
13
+ * unlikely to collide with a subject app; override via config if it does. */
14
+ export const DEFAULT_SANDBOX_CATCH_PORT = 8025;
15
+ const DEFAULT_CATCH_DIR = "/tmp/humanish-comms";
16
+ /** Single-quote for safe shell interpolation. */
17
+ function shq(value) {
18
+ return `'${value.replaceAll("'", "'\\''")}'`;
19
+ }
20
+ /**
21
+ * The self-contained in-sandbox capture server (a plain node ESM string — runs on the sandbox's own
22
+ * node, imports nothing from humanish). It is DELIBERATELY dumb: it records each POST verbatim as an
23
+ * NDJSON line `{t, path, body}` and returns a plausible provider success — all normalization/profile
24
+ * parsing happens host-side on the drained lines, so the typed, tested profiles stay in one place.
25
+ * argv: <port> <deliveriesFile>.
26
+ */
27
+ export const SANDBOX_CATCH_SCRIPT = [
28
+ 'import { createServer } from "node:http";',
29
+ 'import { appendFileSync, mkdirSync } from "node:fs";',
30
+ 'import { dirname } from "node:path";',
31
+ 'const port = Number(process.argv[2] || 8025);',
32
+ 'const outFile = process.argv[3] || "/tmp/humanish-comms/deliveries.ndjson";',
33
+ 'try { mkdirSync(dirname(outFile), { recursive: true }); } catch {}',
34
+ 'const MAX = 5 * 1024 * 1024;',
35
+ 'createServer((req, res) => {',
36
+ ' const path = (req.url || "/").split("?")[0];',
37
+ ' if (req.method === "GET" && (path === "/" || path === "/health")) { res.writeHead(200, { "content-type": "application/json" }); res.end(JSON.stringify({ ok: true, service: "humanish-comms-catch" })); return; }',
38
+ ' if (req.method !== "POST") { res.writeHead(404, { "content-type": "application/json" }); res.end(JSON.stringify({ error: "not found" })); return; }',
39
+ ' let size = 0; const chunks = [];',
40
+ ' req.on("data", (c) => { size += c.length; if (size > MAX) { req.destroy(); } else { chunks.push(c); } });',
41
+ ' req.on("end", () => {',
42
+ ' const body = Buffer.concat(chunks).toString("utf8");',
43
+ ' try { appendFileSync(outFile, JSON.stringify({ t: Date.now(), path, body }) + "\\n"); } catch {}',
44
+ ' const id = "humanish-catch-" + Date.now().toString(36) + Math.random().toString(36).slice(2, 8);',
45
+ ' if (path === "/v3/mail/send") { res.writeHead(202, { "x-message-id": id }); res.end(); }',
46
+ ' else if (path.endsWith("/batch")) { res.writeHead(200, { "content-type": "application/json" }); res.end(JSON.stringify({ data: [{ id }] })); }',
47
+ ' else { res.writeHead(200, { "content-type": "application/json" }); res.end(JSON.stringify({ id })); }',
48
+ ' });',
49
+ ' req.on("error", () => { try { res.writeHead(400); res.end(); } catch {} });',
50
+ '}).listen(port, "127.0.0.1");'
51
+ ].join("\n");
52
+ /** Readiness probe that asserts OUR service marker in the /health body (not merely any 2xx) — so a
53
+ * process squatting on the fixed port cannot produce a false "ready" while the app's sends bypass us. */
54
+ async function catchHealthy(desktop, port, options) {
55
+ const now = options.now ?? Date.now;
56
+ const sleep = options.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
57
+ const deadline = now() + options.timeoutMs;
58
+ for (;;) {
59
+ const result = await desktop.commands
60
+ .run(`curl -s --max-time 5 http://127.0.0.1:${port}/health 2>/dev/null || true`, { requestTimeoutMs: options.requestTimeoutMs })
61
+ .catch(() => ({ stdout: "" }));
62
+ if ((result.stdout ?? "").includes("humanish-comms-catch"))
63
+ return true;
64
+ if (now() >= deadline)
65
+ return false;
66
+ await sleep(1000);
67
+ }
68
+ }
69
+ /**
70
+ * Write + launch the in-sandbox catch (detached), then probe it ready. Call AFTER the subject sandbox
71
+ * is created and BEFORE the subject app's serve.start, so the base URL resolves at the app's boot.
72
+ */
73
+ export async function deployCommsCatch(desktop, options = {}) {
74
+ // Validate the port to an integer before it reaches the shell command (defense-in-depth: a future
75
+ // caller might cast a config value; the value is typed `number` but this makes injection impossible).
76
+ const port = Math.trunc(Number(options.port ?? DEFAULT_SANDBOX_CATCH_PORT));
77
+ if (!Number.isInteger(port) || port <= 0 || port > 65_535) {
78
+ throw new Error(`deployCommsCatch: invalid port ${JSON.stringify(options.port)}`);
79
+ }
80
+ const dir = options.dir ?? DEFAULT_CATCH_DIR;
81
+ const name = options.name ?? "comms-catch";
82
+ const requestTimeoutMs = options.requestTimeoutMs ?? 30_000;
83
+ const scriptPath = `${dir}/catch.mjs`;
84
+ const deliveriesPath = `${dir}/deliveries.ndjson`;
85
+ await desktop.commands.run(`mkdir -p ${shq(dir)}`, { requestTimeoutMs });
86
+ await desktop.files.write(scriptPath, SANDBOX_CATCH_SCRIPT);
87
+ await startDetachedProcess(desktop, {
88
+ name,
89
+ command: `node ${shq(scriptPath)} ${port} ${shq(deliveriesPath)}`,
90
+ requestTimeoutMs
91
+ });
92
+ const ready = await catchHealthy(desktop, port, {
93
+ timeoutMs: options.readyTimeoutMs ?? 15_000,
94
+ requestTimeoutMs,
95
+ ...(options.timers ?? {})
96
+ });
97
+ return { port, baseUrl: `http://127.0.0.1:${port}`, deliveriesPath, ready };
98
+ }
99
+ /**
100
+ * Drain new captured sends from the in-sandbox NDJSON since `cursor` (a line count). Returns the fresh
101
+ * sends and the new cursor. Cheap `cat` over commands.run; NDJSON is small for a run.
102
+ */
103
+ export async function drainCommsCatch(desktop, deployed, cursor = 0, requestTimeoutMs = 30_000) {
104
+ const result = await desktop.commands.run(`cat ${shq(deployed.deliveriesPath)} 2>/dev/null || true`, { requestTimeoutMs });
105
+ const stdout = result.stdout ?? "";
106
+ let lines = stdout.split("\n").filter((line) => line.trim().length > 0);
107
+ // If the file doesn't end in a newline, the last line may be a PARTIAL append (the host `cat` raced
108
+ // an in-sandbox append of a large body). Drop it and don't advance the cursor past it — it re-reads
109
+ // complete on the next poll, so a captured send is never lost to the race (the script only ever emits
110
+ // valid JSON, so an incomplete line is the only cause of a parse miss).
111
+ if (!stdout.endsWith("\n") && lines.length > 0)
112
+ lines = lines.slice(0, -1);
113
+ const sends = [];
114
+ for (const line of lines.slice(cursor)) {
115
+ try {
116
+ const parsed = JSON.parse(line);
117
+ if (typeof parsed.path === "string" && typeof parsed.body === "string") {
118
+ sends.push({ path: parsed.path, body: parsed.body, t: typeof parsed.t === "number" ? parsed.t : 0 });
119
+ }
120
+ }
121
+ catch {
122
+ // skip a malformed line
123
+ }
124
+ }
125
+ return { sends, cursor: lines.length };
126
+ }
127
+ /**
128
+ * Parse drained raw sends with the host profiles and route them into the CommsChannel (the host-side
129
+ * FauxInbox). Returns the number of inbox deliveries made. Same profiles as the host catch, so the
130
+ * in-sandbox and in-process routes normalize identically.
131
+ */
132
+ export async function routeCapturedSends(sends, channel, profiles = DEFAULT_EMAIL_PROFILES) {
133
+ let delivered = 0;
134
+ for (const send of sends) {
135
+ let parsed;
136
+ try {
137
+ parsed = JSON.parse(send.body.length > 0 ? send.body : "{}");
138
+ }
139
+ catch {
140
+ continue;
141
+ }
142
+ const profile = profiles.find((candidate) => candidate.sendPaths.includes(send.path)) ?? profiles[0];
143
+ if (profile === undefined)
144
+ continue;
145
+ for (const normalized of profile.parse(send.path, parsed)) {
146
+ const messages = await channel.deliverRaw({
147
+ from: normalized.from,
148
+ to: normalized.to,
149
+ ...(normalized.subject === undefined ? {} : { subject: normalized.subject }),
150
+ body: normalized.body
151
+ });
152
+ delivered += messages.length;
153
+ }
154
+ }
155
+ return delivered;
156
+ }
157
+ //# sourceMappingURL=comms-sandbox-catch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comms-sandbox-catch.js","sourceRoot":"","sources":["../src/comms-sandbox-catch.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -21,6 +21,10 @@ export { FauxInbox, extractLinks, extractOtpCodes } from "./comms-faux-inbox.js"
21
21
  export type { FauxInboxOptions } from "./comms-faux-inbox.js";
22
22
  export { DEFAULT_EMAIL_PROFILES, genericEmailProfile, sendgridEmailProfile, startEmailCatchServer } from "./comms-email-catch.js";
23
23
  export type { EmailCatchOptions, EmailCatchServer, EmailSendProfile, NormalizedSend } from "./comms-email-catch.js";
24
+ export { DEFAULT_SANDBOX_CATCH_PORT, SANDBOX_CATCH_SCRIPT, deployCommsCatch, drainCommsCatch, routeCapturedSends } from "./comms-sandbox-catch.js";
25
+ export type { DeployCommsCatchOptions, DeployedCommsCatch, RawCapturedSend } from "./comms-sandbox-catch.js";
26
+ export { COMMS_THREAD_SCHEMA, buildCommsThreadArtifact } from "./comms-evidence.js";
27
+ export type { CommsThreadArtifact, CommsThreadEntry } from "./comms-evidence.js";
24
28
  export type { CommsAddress, CommsChannel, CommsChannelKind, CommsMessage, InboundRaw, OutboundMessage } from "./comms-types.js";
25
29
  export { DESKTOP_RATE, MODEL_RATES, PRICING_SCHEMA, estimateActorCost, estimateDesktopCost } from "./pricing.js";
26
30
  export type { ActorEstimatedCost, DesktopCostEstimate, DesktopRate, ModelRate } from "./pricing.js";
package/dist/index.js CHANGED
@@ -13,6 +13,10 @@ export { adapterScoreFailureMessage, applyAdapterScoreFailureToReview, applyBrow
13
13
  // same CommsChannel port.
14
14
  export { FauxInbox, extractLinks, extractOtpCodes } from "./comms-faux-inbox.js";
15
15
  export { DEFAULT_EMAIL_PROFILES, genericEmailProfile, sendgridEmailProfile, startEmailCatchServer } from "./comms-email-catch.js";
16
+ // In-sandbox deployment of the catch + the host-side delivery bridge (the config-block core: the
17
+ // listener must live inside the subject sandbox, since 127.0.0.1 from the app is the sandbox loopback).
18
+ export { DEFAULT_SANDBOX_CATCH_PORT, SANDBOX_CATCH_SCRIPT, deployCommsCatch, drainCommsCatch, routeCapturedSends } from "./comms-sandbox-catch.js";
19
+ export { COMMS_THREAD_SCHEMA, buildCommsThreadArtifact } from "./comms-evidence.js";
16
20
  export { DESKTOP_RATE, MODEL_RATES, PRICING_SCHEMA, estimateActorCost, estimateDesktopCost } from "./pricing.js";
17
21
  export { normalizeCliArgv } from "./argv.js";
18
22
  export { CODEX_APP_SERVER_UI_SCHEMA, startCodexAppServerUi } from "./codex-app-server-ui.js";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -3,7 +3,7 @@
3
3
  Date: 2026-06-02 (current-state note updated 2026-07-14)
4
4
 
5
5
  Status: reference map for the major contracts shipped through source version
6
- `0.21.0`; it is not an exhaustive inventory of command/result envelopes. Exported types,
6
+ `0.22.0`; it is not an exhaustive inventory of command/result envelopes. Exported types,
7
7
  schema constants, parsers, and validators in `src/` are authoritative. Rows
8
8
  marked "reserved" name layering intent only — no code emits or validates them
9
9
  yet. Do not emit a reserved schema.
@@ -16,7 +16,7 @@ Humanish should be the open-source CLI that lets a maintainer ask:
16
16
  The answer should be observable, verifiable, public-safe, and easy to turn into
17
17
  actionable feedback.
18
18
 
19
- ## Current Program Truth (source `0.21.0`)
19
+ ## Current Program Truth (source `0.22.0`)
20
20
 
21
21
  The package source and repository implementation in this tree agree on these
22
22
  points:
@@ -2,7 +2,7 @@
2
2
 
3
3
  Status: public-safe contributor and agent ramp.
4
4
 
5
- Package/source version in this tree: `0.21.0` (2026-08-04). The containment boundary introduced in
5
+ Package/source version in this tree: `0.22.0` (2026-08-04). The containment boundary introduced in
6
6
  `0.15.1` remains in force: managed run and output paths bind to validated
7
7
  physical filesystem identities, and stored provider IDs are evidence, not
8
8
  cleanup authority. The bundled OSS meta-lab is dry-run only until
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "humanish",
3
- "version": "0.21.0",
3
+ "version": "0.22.0",
4
4
  "description": "Open-source-safe CLI for persona simulation, observer review, and public-safe feedback drafts.",
5
5
  "author": "Daniel G Wilson <daniel@danielgwilson.com>",
6
6
  "keywords": [