humanish 0.20.5 → 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.
- package/dist/comms-email-catch.d.ts +53 -0
- package/dist/comms-email-catch.js +209 -0
- package/dist/comms-email-catch.js.map +1 -0
- package/dist/comms-evidence.d.ts +27 -0
- package/dist/comms-evidence.js +31 -0
- package/dist/comms-evidence.js.map +1 -0
- package/dist/comms-faux-inbox.js +12 -2
- package/dist/comms-faux-inbox.js.map +1 -1
- package/dist/comms-sandbox-catch.d.ts +63 -0
- package/dist/comms-sandbox-catch.js +157 -0
- package/dist/comms-sandbox-catch.js.map +1 -0
- package/dist/comms-types.d.ts +2 -2
- package/dist/concurrent-shared-world-lab.js +9 -2
- package/dist/concurrent-shared-world-lab.js.map +1 -1
- package/dist/cua-actor-lab.d.ts +14 -0
- package/dist/cua-actor-lab.js +24 -2
- package/dist/cua-actor-lab.js.map +1 -1
- package/dist/index.d.ts +6 -2
- package/dist/index.js +8 -3
- package/dist/index.js.map +1 -1
- package/dist/init-templates.js +7 -4
- package/dist/init-templates.js.map +1 -1
- package/dist/run.d.ts +15 -0
- package/dist/run.js +9 -0
- package/dist/run.js.map +1 -1
- package/docs/architecture/external-public-shared-world.md +8 -5
- package/docs/contracts/run-bundle.md +7 -1
- package/docs/contracts/schemas.md +1 -1
- package/docs/goals/current.md +1 -1
- package/docs/product/cineguessr-3player-external-public.md +14 -5
- package/docs/ramp/README.md +1 -1
- package/package.json +1 -1
- package/dist/comms-resend-catch.d.ts +0 -30
- package/dist/comms-resend-catch.js +0 -120
- package/dist/comms-resend-catch.js.map +0 -1
|
@@ -102,11 +102,14 @@ e2b-URL / host-digest redaction discipline.
|
|
|
102
102
|
## Mobile fidelity caveat
|
|
103
103
|
|
|
104
104
|
The example roster runs mobile-LAYOUT seats (`device: mobile` 414×896, `small-mobile` 360×740). On the
|
|
105
|
-
E2B-desktop route
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
105
|
+
E2B-desktop route the rendered WIDTH is floored to `MIN_DESKTOP_RENDER_WIDTH` (500) because Chrome
|
|
106
|
+
refuses a narrower window and a narrower X screen clipped the page (0.20.3, #304), so both presets
|
|
107
|
+
render at 500 wide and are identical in layout; only HEIGHT renders as declared.
|
|
108
|
+
`desktopGeometry.screen.verified` compares the floored number with itself, so it does not attest the
|
|
109
|
+
preset width. There is NO touch input, and `isMobile`/DPR are prompt-signal + metadata (DPR renders
|
|
110
|
+
only via the CDP geometry path). "3 mobile personas" = 3 mobile-LAYOUT desktop-Chromium seats, not
|
|
111
|
+
touch devices. Do not over-read the results as true mobile-device coverage. True sub-500 rendering is
|
|
112
|
+
the #221 upgrade.
|
|
110
113
|
|
|
111
114
|
## Watch-from-phone
|
|
112
115
|
|
|
@@ -81,11 +81,17 @@ responses, but durable run bundles use the public-safe `[target-cwd]` marker.
|
|
|
81
81
|
|
|
82
82
|
## Hosted Desktop Geometry
|
|
83
83
|
|
|
84
|
-
Hosted browser streams may carry additive `desktopGeometry` evidence. Its fields keep
|
|
84
|
+
Hosted browser streams may carry additive `desktopGeometry` evidence. Its fields keep five
|
|
85
85
|
different facts separate:
|
|
86
86
|
|
|
87
87
|
- `screen.requested`: the E2B/X screen size requested by config;
|
|
88
88
|
- `screen.verified`: the screen size measured in-sandbox with `xdpyinfo`;
|
|
89
|
+
- `screen.declared`: the device preset the lab ASKED for, present only when it differs from
|
|
90
|
+
`screen.requested` because the rendered width was floored to Chrome's ~500px window minimum.
|
|
91
|
+
`verified` compares the floored number with itself and reports a match, so a matching
|
|
92
|
+
`verified` block is NOT evidence that the preset width rendered. When `declared` is present,
|
|
93
|
+
it did not: a `mobile` (414) and a `small-mobile` (360) seat both render at 500 and are
|
|
94
|
+
indistinguishable by rendered width;
|
|
89
95
|
- `browserWindow`: outer browser bounds measured after the window-fill attempt;
|
|
90
96
|
- `viewport`: the page's CSS layout viewport and device-pixel ratio measured through CDP on
|
|
91
97
|
Chromium-family hosted browsers.
|
|
@@ -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.
|
|
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.
|
package/docs/goals/current.md
CHANGED
|
@@ -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.
|
|
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:
|
|
@@ -18,11 +18,20 @@ a public deployment YOU own/operate.
|
|
|
18
18
|
## Mobile fidelity caveat (read before over-reading the results)
|
|
19
19
|
|
|
20
20
|
The seats are `device: mobile` (414×896) and `device: small-mobile` (360×740). On the E2B-desktop
|
|
21
|
-
route
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
route the rendered WIDTH is floored to `MIN_DESKTOP_RENDER_WIDTH` (500): Chrome refuses a window
|
|
22
|
+
narrower than ~500 CSS px, and a narrower X screen let the window overflow and clip the page
|
|
23
|
+
(0.20.3, #304). So both presets render at **500 wide**, `mobile` and `small-mobile` are identical in
|
|
24
|
+
layout on this route, and this example does NOT currently exercise two different mobile widths. Only
|
|
25
|
+
the HEIGHT renders as declared (896 and 740).
|
|
26
|
+
|
|
27
|
+
Note that `desktopGeometry.screen.verified` checks the FLOORED number against itself, so a matching
|
|
28
|
+
`verified` block is not evidence that the preset width rendered. Read `requested` against the preset
|
|
29
|
+
in `device-presets.ts` if you need to know.
|
|
30
|
+
|
|
31
|
+
There is NO touch input, and isMobile/DPR are prompt-signal + metadata (DPR renders only via the CDP
|
|
32
|
+
geometry path). So "3 mobile personas" means 3 mobile-LAYOUT desktop-Chromium seats, NOT touch
|
|
33
|
+
devices. If a flow needs true touch/tap semantics, these seats will not exercise it. True sub-500
|
|
34
|
+
CSS-viewport rendering is the #221 CDP-device-emulation upgrade.
|
|
26
35
|
|
|
27
36
|
## Run it
|
|
28
37
|
|
package/docs/ramp/README.md
CHANGED
|
@@ -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.
|
|
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,30 +0,0 @@
|
|
|
1
|
-
import type { CommsChannel } from "./comms-types.js";
|
|
2
|
-
/** A Resend send payload we accepted, normalized (runtime-only; for inspection/tests). */
|
|
3
|
-
export interface ResendEmailPayload {
|
|
4
|
-
from: string;
|
|
5
|
-
to: string[];
|
|
6
|
-
subject?: string;
|
|
7
|
-
html?: string;
|
|
8
|
-
text?: string;
|
|
9
|
-
}
|
|
10
|
-
export interface ResendCatchServer {
|
|
11
|
-
/** Point the app here: `RESEND_BASE_URL=<url>` (loopback only). */
|
|
12
|
-
readonly url: string;
|
|
13
|
-
readonly port: number;
|
|
14
|
-
/** Every payload accepted this run (runtime-only). */
|
|
15
|
-
readonly received: ResendEmailPayload[];
|
|
16
|
-
close(): Promise<void>;
|
|
17
|
-
}
|
|
18
|
-
export interface ResendCatchOptions {
|
|
19
|
-
/** Bind host. Default 127.0.0.1 (loopback ONLY — never bind a public interface). */
|
|
20
|
-
host?: string;
|
|
21
|
-
/** Port. Default 0 (ephemeral — read the chosen port off the returned server). */
|
|
22
|
-
port?: number;
|
|
23
|
-
/** Deterministic id for the Resend-shaped response (tests). Default a zero-padded counter. */
|
|
24
|
-
idFor?: (n: number) => string;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Start the Resend-shaped catch server, routing accepted sends into `channel`. Returns the loopback
|
|
28
|
-
* URL to hand the app as `RESEND_BASE_URL`. `close()` in a finally (mirror by-id teardown).
|
|
29
|
-
*/
|
|
30
|
-
export declare function startResendCatchServer(channel: CommsChannel, options?: ResendCatchOptions): Promise<ResendCatchServer>;
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
// A LOOPBACK catch server that speaks the Resend `POST /emails` wire shape, so an app hardwired to
|
|
2
|
-
// Resend is redirected into the faux bus with ONE env var and no code change: point the app at this
|
|
3
|
-
// server via `RESEND_BASE_URL=<url>` (the official `resend` Node SDK reads that env var / a `baseUrl`
|
|
4
|
-
// option). The app's real verification email POSTs here instead of api.resend.com; we route it into
|
|
5
|
-
// the CommsChannel and the persona reads it. Nothing is delivered onward. (#297 — the API-first
|
|
6
|
-
// analog of pointing SMTP at a local catcher, since Resend is HTTPS-first and its own SMTP delivers
|
|
7
|
-
// for real.) 127.0.0.1 only; bodies are never logged.
|
|
8
|
-
import { createServer } from "node:http";
|
|
9
|
-
/** "Name <email@host>" → "email@host"; a bare address passes through. */
|
|
10
|
-
function bareEmail(value) {
|
|
11
|
-
const angle = value.match(/<([^>]+)>/);
|
|
12
|
-
return (angle ? angle[1] ?? value : value).trim();
|
|
13
|
-
}
|
|
14
|
-
function asStringArray(value) {
|
|
15
|
-
if (Array.isArray(value))
|
|
16
|
-
return value.map((entry) => String(entry));
|
|
17
|
-
if (typeof value === "string")
|
|
18
|
-
return [value];
|
|
19
|
-
return [];
|
|
20
|
-
}
|
|
21
|
-
function normalizeResendPayload(payload) {
|
|
22
|
-
return {
|
|
23
|
-
from: typeof payload.from === "string" ? payload.from : "",
|
|
24
|
-
to: asStringArray(payload.to).map(bareEmail),
|
|
25
|
-
...(typeof payload.subject === "string" ? { subject: payload.subject } : {}),
|
|
26
|
-
...(typeof payload.html === "string" ? { html: payload.html } : {}),
|
|
27
|
-
...(typeof payload.text === "string" ? { text: payload.text } : {})
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
function readBody(req, limit) {
|
|
31
|
-
return new Promise((resolve, reject) => {
|
|
32
|
-
let size = 0;
|
|
33
|
-
const chunks = [];
|
|
34
|
-
req.on("data", (chunk) => {
|
|
35
|
-
size += chunk.length;
|
|
36
|
-
if (size > limit) {
|
|
37
|
-
req.destroy();
|
|
38
|
-
reject(new Error("request body too large"));
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
chunks.push(chunk);
|
|
42
|
-
});
|
|
43
|
-
req.on("end", () => resolve(Buffer.concat(chunks).toString("utf8")));
|
|
44
|
-
req.on("error", reject);
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
const MAX_BODY_BYTES = 5 * 1024 * 1024;
|
|
48
|
-
/**
|
|
49
|
-
* Start the Resend-shaped catch server, routing accepted sends into `channel`. Returns the loopback
|
|
50
|
-
* URL to hand the app as `RESEND_BASE_URL`. `close()` in a finally (mirror by-id teardown).
|
|
51
|
-
*/
|
|
52
|
-
export async function startResendCatchServer(channel, options = {}) {
|
|
53
|
-
const host = options.host ?? "127.0.0.1";
|
|
54
|
-
const received = [];
|
|
55
|
-
let idCounter = 0;
|
|
56
|
-
const idFor = options.idFor ?? ((n) => `humanish-catch-${n.toString().padStart(6, "0")}`);
|
|
57
|
-
const respondJson = (res, status, value) => {
|
|
58
|
-
res.statusCode = status;
|
|
59
|
-
res.setHeader("content-type", "application/json");
|
|
60
|
-
res.end(JSON.stringify(value));
|
|
61
|
-
};
|
|
62
|
-
const handle = async (req, res) => {
|
|
63
|
-
const path = (req.url ?? "/").split("?")[0];
|
|
64
|
-
if (req.method === "GET" && (path === "/" || path === "/health")) {
|
|
65
|
-
respondJson(res, 200, { ok: true, service: "humanish-resend-catch", channel: channel.channel });
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
// Resend's send endpoints: POST /emails (single) and /emails/batch. Batch is an array of sends.
|
|
69
|
-
if (req.method === "POST" && (path === "/emails" || path === "/emails/batch")) {
|
|
70
|
-
const raw = await readBody(req, MAX_BODY_BYTES);
|
|
71
|
-
let parsed;
|
|
72
|
-
try {
|
|
73
|
-
parsed = JSON.parse(raw.length > 0 ? raw : "{}");
|
|
74
|
-
}
|
|
75
|
-
catch {
|
|
76
|
-
respondJson(res, 422, { error: "invalid JSON body" });
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
const items = Array.isArray(parsed) ? parsed : [parsed];
|
|
80
|
-
const ids = [];
|
|
81
|
-
for (const item of items) {
|
|
82
|
-
if (typeof item !== "object" || item === null)
|
|
83
|
-
continue;
|
|
84
|
-
const payload = normalizeResendPayload(item);
|
|
85
|
-
received.push(payload);
|
|
86
|
-
const inbound = {
|
|
87
|
-
from: payload.from,
|
|
88
|
-
to: payload.to,
|
|
89
|
-
...(payload.subject === undefined ? {} : { subject: payload.subject }),
|
|
90
|
-
body: payload.html ?? payload.text ?? ""
|
|
91
|
-
};
|
|
92
|
-
await channel.deliverRaw(inbound);
|
|
93
|
-
idCounter += 1;
|
|
94
|
-
ids.push(idFor(idCounter));
|
|
95
|
-
}
|
|
96
|
-
// Resend-shaped response: a single send returns { id }; a batch returns { data: [{ id }, …] }.
|
|
97
|
-
if (path === "/emails/batch")
|
|
98
|
-
respondJson(res, 200, { data: ids.map((id) => ({ id })) });
|
|
99
|
-
else
|
|
100
|
-
respondJson(res, 200, { id: ids[0] ?? idFor(idCounter) });
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
respondJson(res, 404, { error: "not found" });
|
|
104
|
-
};
|
|
105
|
-
const server = createServer((req, res) => {
|
|
106
|
-
void handle(req, res).catch(() => {
|
|
107
|
-
if (!res.headersSent)
|
|
108
|
-
respondJson(res, 500, { error: "catch server error" });
|
|
109
|
-
});
|
|
110
|
-
});
|
|
111
|
-
await new Promise((resolve) => server.listen(options.port ?? 0, host, () => resolve()));
|
|
112
|
-
const port = server.address().port;
|
|
113
|
-
return {
|
|
114
|
-
url: `http://${host}:${port}`,
|
|
115
|
-
port,
|
|
116
|
-
received,
|
|
117
|
-
close: () => new Promise((resolve) => server.close(() => resolve()))
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
//# sourceMappingURL=comms-resend-catch.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"comms-resend-catch.js","sourceRoot":"","sources":["../src/comms-resend-catch.ts"],"names":[],"mappings":"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"}
|