@archstone/cli 0.19.0 → 0.20.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/index.js +29 -8
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -1214,19 +1214,40 @@ async function handleHttpRequest(handler, req, res) {
|
|
|
1214
1214
|
return;
|
|
1215
1215
|
}
|
|
1216
1216
|
const chunks = [];
|
|
1217
|
-
|
|
1217
|
+
const body = await new Promise((settle) => {
|
|
1218
1218
|
let received = 0;
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1219
|
+
let done = false;
|
|
1220
|
+
const finish = (outcome) => {
|
|
1221
|
+
if (done) return;
|
|
1222
|
+
done = true;
|
|
1223
|
+
req.off("data", onData);
|
|
1224
|
+
req.off("end", onEnd);
|
|
1225
|
+
req.off("error", onError);
|
|
1226
|
+
req.off("close", onClose);
|
|
1227
|
+
settle(outcome);
|
|
1228
|
+
};
|
|
1229
|
+
const onData = (chunk) => {
|
|
1230
|
+
received += chunk.length;
|
|
1222
1231
|
if (received > MAX_REQUEST_BODY_BYTES) {
|
|
1223
1232
|
chunks.length = 0;
|
|
1224
|
-
|
|
1233
|
+
finish("oversized");
|
|
1225
1234
|
return;
|
|
1226
1235
|
}
|
|
1227
|
-
chunks.push(
|
|
1228
|
-
}
|
|
1229
|
-
|
|
1236
|
+
chunks.push(chunk);
|
|
1237
|
+
};
|
|
1238
|
+
const onEnd = () => finish("ok");
|
|
1239
|
+
const onError = () => finish("aborted");
|
|
1240
|
+
const onClose = () => finish("aborted");
|
|
1241
|
+
req.on("data", onData);
|
|
1242
|
+
req.on("end", onEnd);
|
|
1243
|
+
req.on("error", onError);
|
|
1244
|
+
req.on("close", onClose);
|
|
1245
|
+
});
|
|
1246
|
+
if (body === "oversized") {
|
|
1247
|
+
refuseOversizedBody(res);
|
|
1248
|
+
return;
|
|
1249
|
+
}
|
|
1250
|
+
if (body === "aborted") {
|
|
1230
1251
|
endResponseQuietly(res, 400);
|
|
1231
1252
|
return;
|
|
1232
1253
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/init.ts","../src/audit-cmd.ts","../src/audit-report.ts","../src/doctor.ts","../src/adopt.ts","../src/adopt-edit.ts"],"sourcesContent":["#!/usr/bin/env node\n// @archstone/cli — `archstone apply` (#1) + `archstone serve` (#7, + `--http` ADD-0008 #29)\n// + `archstone verify` (#18-20) + `archstone build` (ADD-0008 #27)\n//\n// apply: parse → shape-validate (#2) → semantic-validate (#3) → compile IR (#4)\n// → index Registry (#5), and REPORT (human output, exits).\n// serve: build the registry and expose it as an MCP server over stdio (#7),\n// so Claude/Cursor/ChatGPT can discover and invoke the tools. Blocks.\n// serve --http: same registry, served over real Streamable-HTTP instead of stdio —\n// `@archstone/runtime/http`'s createHttpHandler (Web-standard Request/Response,\n// bearer-token gated, shared with @archstone/agent/mcp's mcpHandler(), ADD-0008 D-3)\n// behind a thin Node-http adapter. Blocks.\n// verify: replay each bound capability's golden fixture against the LIVE backend\n// and report a per-binding health status (ADD-18). The only command that\n// makes a network call outside a real MCP invocation — on demand, never\n// scheduled by Archstone itself (wire it into your own CI/cron). A replay IS an\n// invocation, so a `write`/`irreversible` binding is skipped by default and\n// re-included only by `--sandbox`, an assertion the operator makes (#124).\n// build: run the same compile pipeline as `apply`, strip each tool's `contract`\n// (D-8 — the fingerprint/golden-fixture path is meaningless once the fixture\n// file isn't shipping), and write the IR as a standalone JSON artifact —\n// the substrate `@archstone/agent`'s `fromIR()` will consume (RFC-0008).\n// init: read an existing API description, ask the human the questions no tool can answer\n// (is this a capability? is it `read`? what is it called?), and write a CDL manifest\n// the real compiler has already compiled (ADD-37). Thin by design — argv, the terminal\n// gate and report rendering only; everything of substance is in @archstone/init.\n\nimport { writeFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { createRequire } from \"node:module\";\nimport { createServer, type IncomingMessage, type ServerResponse } from \"node:http\";\nimport { load } from \"@archstone/schema\";\nimport { validateSemantics, compile, type IR } from \"@archstone/compiler\";\nimport { Registry, buildRegistry, serveStdio, runVerify, type HealthStatus } from \"@archstone/runtime\";\nimport { createHttpHandler } from \"@archstone/runtime/http\";\nimport { INIT_USAGE, runInitCmd } from \"./init\";\nimport { runAuditCmd } from \"./audit-cmd\";\nimport { diagnose, formatReport } from \"./doctor\";\nimport { runAdoptCmd } from \"./adopt\";\n\n/** `archstone --version` is the first thing a human types after installing, and until this\n * existed it printed the usage block and exited 2 — which reads as \"broken install\" at the\n * exact moment a new user is deciding whether this thing works.\n *\n * `../package.json` resolves correctly from BOTH layouts without a build step knowing about\n * it: in dev the entry is `src/index.ts`, and when published it is `dist/index.js` — both sit\n * one level under the package root. npm always ships `package.json` regardless of the `files`\n * allowlist, so the published resolution cannot break. */\nfunction cliVersion(): string {\n try {\n return (createRequire(import.meta.url)(\"../package.json\") as { version?: string }).version ?? \"unknown\";\n } catch {\n // Never let a version lookup be the thing that stops the CLI from running.\n return \"unknown\";\n }\n}\n\n/** One spelling of the usage block, shared by `--help` (stdout, exit 0 — the user asked) and by\n * the no-verb-matched fallthrough (stderr, exit 2 — the user got it wrong). Which stream and\n * which exit code is the ONLY difference between those two cases, and keeping the text in one\n * place is what stops them drifting. */\nfunction printUsage(opts?: { toStderr?: boolean }): void {\n const write = opts?.toStderr ? console.error : console.log;\n write(\n // `init` is named HERE, in the verb list, and not only in the block below it. It takes a\n // spec file rather than a manifest directory, so it cannot share the first line's shape —\n // which is exactly how it came to be missing from the one line a user actually scans.\n \"usage: archstone <apply|serve|verify|build|doctor|init|adopt|audit>\\n\\n\" +\n \" archstone <apply|serve|verify|build> <manifest-dir> [--json] [--out path]\\n\" +\n \" archstone verify <manifest-dir> [--json] [--sandbox]\\n\" +\n \" --sandbox: also replay `write`/`irreversible` fixtures — they are skipped by default,\\n\" +\n \" because a replay is a real invocation. Only for a backend you know is a sandbox tenant.\\n\" +\n \" archstone serve --http <manifest-dir> [--port <n>] [--token <value>]\\n\" +\n \" bearer token: --token <value>, or the ARCHSTONE_HTTP_TOKEN env var (required — never serves open)\\n\" +\n \" archstone doctor <manifest-dir> [--json] — pre-production checks, offline\\n\" +\n \" archstone init <spec-file> --out <dir> — start here if you have no manifest yet\\n\" +\n \" archstone adopt <manifest-dir>\\n\" +\n \" declare a field the backend started returning; asks before writing, needs a person\\n\\n\" +\n \" archstone audit <file...> [--since <date>] [--format summary|jsonl|csv]\\n\" +\n \" read your own Execution audit records; nothing is uploaded (audit --help for filters)\\n\\n\" +\n \" archstone --version | --help\\n\\n\" +\n INIT_USAGE,\n );\n}\n\nfunction runApply(dir: string): void {\n const res = load(dir);\n console.log(`\\narchstone apply ${dir}\\n`);\n\n if (res.capabilities) {\n const c = res.capabilities;\n console.log(` company ${c.company.name ?? c.company.id} (${c.company.id})`);\n console.log(` providers ${c.providers.join(\", \")}`);\n console.log(` declared ${c.capabilities.length} capabilities`);\n }\n console.log(` loaded ${res.capabilityDocs.length} capability docs, ${res.bindings.length} bindings`);\n for (const d of res.capabilityDocs) {\n console.log(` ✓ ${d.capability.id} [${d.capability.effect}] → ${d.capability.provider ?? \"?\"}`);\n }\n // #43: a policy the author believes is enforced must never be invisible here — the whole\n // point of the semantic pass's scope diagnostics is that \"attached to nothing\" is loud.\n if (res.policyDocs.length > 0) {\n console.log(` policies ${res.policyDocs.length} policy document(s)`);\n for (const p of res.policyDocs) {\n const target =\n p.metadata.scope === \"capability\"\n ? `capability ${p.metadata.capabilityId ?? \"?\"}`\n : p.metadata.scope === \"provider\"\n ? `provider ${p.metadata.provider ?? \"?\"}`\n : \"(no scope)\";\n console.log(` ✓ ${p.metadata.id} → ${target}`);\n }\n }\n\n // Shape (schema) issues from #2 — \"valid shapes\" is not \"deployable\".\n if (res.issues.length > 0) {\n console.log(`\\n ✗ ${res.issues.length} shape issue(s):`);\n for (const i of res.issues) console.log(` - ${i.file}: ${i.message}`);\n } else {\n console.log(`\\n ✓ shapes valid`);\n }\n\n // Semantic pass (#3) — cross-file resolution; errors block, warnings inform.\n const diags = validateSemantics(res);\n const errors = diags.filter((d) => d.severity === \"error\");\n const warnings = diags.filter((d) => d.severity === \"warning\");\n console.log(` semantic ${errors.length} error(s), ${warnings.length} warning(s)`);\n for (const d of errors) console.log(` ✗ ${d.message}`);\n for (const d of warnings) console.log(` ⚠ ${d.message}`);\n\n const shapesAndSemanticsOk = res.ok && errors.length === 0;\n\n // Compile to IR (#4) + index into the Registry (#5) — only when valid enough to emit.\n // ADD-30: a tool-name collision (two capability ids sanitizing to the same advertised\n // name) is checked here, before the final `ok`, alongside the semantic errors above —\n // 'apply' must refuse the same manifest 'build'/'serve' would refuse (D-2).\n const registry = shapesAndSemanticsOk ? new Registry(compile(res)) : undefined;\n const collisions = registry?.toolNameCollisions ?? [];\n if (collisions.length > 0) {\n console.log(`\\n ✗ ${collisions.length} tool-name collision(s):`);\n for (const c of collisions) {\n console.log(` - tool name '${c.name}' is ambiguous — capabilities ${c.ids.join(\", \")} all sanitize to it`);\n }\n }\n\n const ok = shapesAndSemanticsOk && collisions.length === 0;\n\n if (ok && registry) {\n const invocable = registry.listCapabilities().filter((t) => t.connector).length;\n console.log(` registry IR v${registry.ir.version} — ${registry.size} capabilities, ${invocable} invocable (bound)`);\n console.log(`\\n → run 'archstone serve ${dir}' to expose ${invocable} tool(s) to an AI agent over MCP`);\n }\n\n console.log(\"\");\n process.exit(ok ? 0 : 1);\n}\n\nfunction runBuild(dir: string, outPath: string | undefined): void {\n const res = load(dir);\n const diags = validateSemantics(res);\n const errors = diags.filter((d) => d.severity === \"error\");\n const ok = res.ok && errors.length === 0;\n\n if (!ok) {\n console.error(`archstone build ${dir}: manifest invalid — run 'archstone apply ${dir}' for details`);\n for (const i of res.issues) console.error(` - ${i.file}: ${i.message}`);\n for (const d of errors) console.error(` - ${d.message}`);\n process.exit(1);\n }\n\n const ir = compile(res);\n\n // ADD-30 R-2: `runBuild` didn't construct a Registry at all, so it could ship a broken\n // artifact whose ambiguous tool name only surfaces later, inside a third party's\n // `fromIR()` call. Refuse to write on a collision — fail at `build` time instead\n // (the same \"ambiguous is a compile-time error, never a guess\" pattern this repo already\n // applies to resource-name resolution, compiler/src/resolve.ts).\n const registry = new Registry(ir);\n if (registry.toolNameCollisions.length > 0) {\n console.error(`archstone build ${dir}: refusing to write artifact — tool-name collision(s):`);\n for (const c of registry.toolNameCollisions) {\n console.error(` - tool name '${c.name}' is ambiguous — capabilities ${c.ids.join(\", \")} all sanitize to it`);\n }\n process.exit(1);\n }\n\n // THE STRIP RULE, stated as a principle rather than a list (ADD-43 D-9), so the next field\n // added to `IRTool` is classified deliberately instead of by whichever example was copied:\n //\n // strip what the INVOCATION PATH cannot use.\n //\n // `contract` qualifies (ADD-0008 D-8): it is verify-time-only and carries an fs path that is\n // meaningless once the golden fixture is not shipping alongside the artifact.\n //\n // `policyRules` (#43) is the exact opposite and MUST survive: it is invocation-path data, read\n // by the evaluator on every `execute()` call. Stripping it would ship an unpoliced embedded\n // SDK beside a policed MCP surface — the precise cross-path drift #43 exists to prevent, and\n // silent, because `fromIR` validates only `version` and treats the rest as opaque.\n const stripped: IR = { ...ir, tools: ir.tools.map(({ contract: _contract, ...t }) => t) };\n\n const outFile = resolve(process.cwd(), outPath ?? \"archstone.ir.json\");\n writeFileSync(outFile, `${JSON.stringify(stripped, null, 2)}\\n`);\n console.log(`archstone build ${dir} → ${outFile} (${stripped.tools.length} tool(s))`);\n process.exit(0);\n}\n\nfunction runServeHttp(dir: string, port: number, token: string | undefined): void {\n // Rule #7 / ADD-0008 R-5: fail closed before touching the network — a missing token is a\n // startup error, never a silently-open endpoint. `--token` wins over the env var if both\n // are set; createHttpHandler itself would also throw on empty, but checking here first\n // gives a CLI-appropriate error message instead of an uncaught exception.\n if (!token) {\n console.error(\n \"archstone serve --http: bearer token required — set ARCHSTONE_HTTP_TOKEN or pass --token <value>\",\n );\n process.exit(1);\n }\n\n const built = buildRegistry(dir);\n if (!built.ok || !built.registry) {\n console.error(`archstone: cannot serve '${dir}' — manifest invalid:`);\n for (const i of built.issues) console.error(` - ${i.file}: ${i.message}`);\n for (const d of built.diagnostics.filter((x) => x.severity === \"error\")) console.error(` - ${d.message}`);\n process.exit(1);\n }\n\n const handler = createHttpHandler(built.registry, { bearerToken: token });\n const server = createServer((req, res) => {\n // #49 belt-and-braces: this used to be `void handleHttpRequest(...)`. Fire-and-forget\n // means nothing is attached to the returned promise, so ANY rejection escaping the\n // function became an unhandled rejection — fatal under Node's default\n // `--unhandled-rejections=throw`, killing the server on one aborted client connection.\n // handleHttpRequest now contains its own failures, but this `.catch` is the seam that\n // makes the fix independent of that catch staying exhaustive: a future throw added\n // outside its `try` cannot resurrect the process-death bug.\n handleHttpRequest(handler, req, res).catch((err: unknown) => {\n console.error(\"archstone serve --http: request handling failed —\", err);\n endResponseQuietly(res, 500);\n });\n });\n server.listen(port, () => {\n console.error(`archstone: serving MCP over HTTP on http://localhost:${port}/ (bearer-token gated)`);\n });\n}\n\n/**\n * Largest request body `archstone serve --http` will buffer, in bytes (#50).\n *\n * 4 MiB is not chosen by feel: it is the limit the MCP SDK itself applies to an MCP message\n * arriving over HTTP (`MAXIMUM_MESSAGE_SIZE = '4mb'` in the SDK's own Node SSE transport,\n * enforced via `raw-body`). Same protocol, same message class, same SDK version this package\n * already depends on — so the ceiling matches what an MCP client can reasonably expect to send\n * anywhere else in the ecosystem, rather than inventing an Archstone-specific number. The\n * Web-standard transport used here never reads the socket itself (this adapter hands it an\n * already-built `Request`), which is precisely why the SDK's limit does not apply on this path\n * and has to be reapplied here.\n *\n * For scale: an MCP `tools/call` body carries a capability's declared inputs as JSON. 4 MiB is\n * orders of magnitude above any manifest in `examples/`.\n */\nconst MAX_REQUEST_BODY_BYTES = 4 * 1024 * 1024;\n\n/**\n * Bounds on the \"lingering close\" that `refuseOversizedBody` performs: how many bytes of an\n * already-refused body are read and thrown away, and how long the socket is kept around, before\n * the client is cut off for good.\n *\n * Both exist to bound a courtesy, not a capability. Nothing here is ever buffered — the bytes\n * are discarded as they arrive and `chunks` is emptied the moment the cap trips — so the\n * allocation bound #50 established is untouched. What is being spent is socket time on a client\n * that already misbehaved, so it is capped rather than run to completion.\n */\nconst MAX_REFUSED_BODY_DRAIN_BYTES = 64 * 1024 * 1024;\nconst REFUSED_BODY_LINGER_MS = 5_000;\n\n/**\n * Refuse an oversized body with a 413 the client will actually receive, then let go of the\n * socket.\n *\n * Refusing turned out not to be the same as being heard. Ending the response the ordinary way\n * sets `Connection: close`, and Node then calls `destroySoon()` as soon as the response has\n * flushed — without waiting on the read side. The client is still mid-upload, so megabytes of\n * its body are sitting unread in this process's receive buffer, and a socket closed with unread\n * data does not send FIN, it sends RST. An RST makes the peer's stack DISCARD whatever is\n * already in its own receive buffer — the just-delivered 413 included. Measured against the\n * real CLI: 7 of 25 chunked oversize uploads ended in ECONNRESET/EPIPE with the response\n * destroyed in flight, and the rate climbed with machine load. The caller could not tell \"your\n * body is too large\" apart from \"the server fell over\" (measured 2026-08-26).\n *\n * Draining the body before closing is the obvious repair and it is not enough: under load the\n * event loop drains slower than the client fills, so the buffer is still dirty at close. It cut\n * the loss from 7/25 to 3/40 idle, and it was still 8/40 at load average 44.\n *\n * What is sufficient is to never call close() with the read side dirty. So the socket is taken\n * over from the response, the 413 is written by hand, and `socket.end()` issues a bare\n * shutdown(WR): the response and the FIN leave together, the read side stays open, and no RST\n * is ever generated. The remaining upload is then read and dropped until the client gives up,\n * the byte budget is spent, or the linger expires. This is nginx's `lingering_close`, and it is\n * why the caller may go on streaming without ever costing this process memory. Measured on the\n * same machine at load average 44: 60 of 60 uploads received their 413, including the\n * pathological client that never stops writing and never terminates its chunked body.\n *\n * Both refusal paths use this — the streaming guard and the declared-Content-Length fast path.\n * The fast path still decides on the header alone, before reading a byte; lingering afterwards\n * does not change what the decision was made from, only whether the caller gets to hear it.\n *\n * What this does NOT add is a cap on how many sockets may be lingering at once. Stated out\n * loud rather than left implicit, because #49/#50 treated this file's unauthenticated surface\n * carefully: a flood can now hold a refused connection for up to the bounds above where it\n * used to be dropped near-instantly. The exposure is file descriptors and time, never memory,\n * and it is what buys a caller the ability to learn why it was refused. If a global cap is\n * ever wanted it belongs at the server, alongside `maxConnections`, not here.\n *\n * Writing the status line by hand is deliberate. `res.detachSocket()` is the supported way to\n * take a socket out of Node's response machinery (it is what an HTTP upgrade does), and once\n * detached the ServerResponse must not be used — it no longer owns anything to write through.\n */\nfunction refuseOversizedBody(res: ServerResponse): void {\n const socket = res.socket;\n // No socket to linger on, or the response is already committed: fall back to the ordinary\n // ending. It may be lost to an RST, which is strictly better than throwing from here (#49).\n if (!socket || res.headersSent || res.writableEnded || res.destroyed || socket.destroyed) {\n endResponseQuietly(res, 413, { closeConnection: true });\n return;\n }\n try {\n res.detachSocket(socket);\n // No `Date`, which Node's ServerResponse would have added. Deliberate, and the only header\n // that differs from the old path: RFC 9110 recommends rather than requires it, and this\n // connection closes immediately, so nothing downstream can cache or age the response.\n socket.write(\"HTTP/1.1 413 Payload Too Large\\r\\nConnection: close\\r\\nContent-Length: 0\\r\\n\\r\\n\");\n socket.end(); // shutdown(WR) only — the read side deliberately stays open.\n\n let discarded = 0;\n socket.on(\"data\", (chunk: Buffer) => {\n discarded += chunk.length;\n if (discarded > MAX_REFUSED_BODY_DRAIN_BYTES) socket.destroy();\n });\n socket.resume();\n // Client faults are never logged (#49 BF-1) and a dead peer must not leak a socket, so the\n // two remaining exits are silent: the budget above, and this deadline.\n socket.on(\"error\", () => socket.destroy());\n const linger = setTimeout(() => socket.destroy(), REFUSED_BODY_LINGER_MS);\n linger.unref();\n socket.on(\"close\", () => clearTimeout(linger));\n } catch {\n // The socket went away between the guard above and the write. Nothing to say, no one to\n // say it to — same contract as endResponseQuietly.\n try {\n socket.destroy();\n } catch {\n /* already gone */\n }\n }\n}\n\n/**\n * Terminate a response without ever throwing (#49). Every exit path out of the adapter goes\n * through here, including the ones reached after the client is already gone: on an aborted\n * connection the socket is destroyed, and a naive `res.end()` there is at best pointless and\n * at worst a second error thrown out of an error path. Ending is still attempted whenever the\n * socket survives — a truncated body on a keep-alive connection has a live socket that would\n * otherwise hang until the client's own timeout.\n */\nfunction endResponseQuietly(\n res: ServerResponse,\n status: number,\n opts: { closeConnection?: boolean } = {},\n): void {\n try {\n if (res.writableEnded || res.destroyed) return;\n if (!res.headersSent) {\n res.statusCode = status;\n // #50: on a refused oversized body the connection must not be reused. The client is\n // mid-upload and the rest of its bytes are still in flight, so a keep-alive socket\n // would leave that remainder to be misparsed as the next request. `Connection: close`\n // lets Node flush the response first and then close — destroying the socket here\n // instead would race the 413 and the client would see nothing.\n if (opts.closeConnection) res.setHeader(\"connection\", \"close\");\n }\n res.end();\n } catch {\n // The socket went away between the checks above and the write. Nothing is left to\n // terminate and there is no one to tell — swallowing here is the whole point.\n }\n}\n\n// D-3's \"~20-line wrapper\": Node's http.IncomingMessage/ServerResponse <-> Web-standard\n// Request/Response, so createHttpHandler (already Web-standard, shared with\n// @archstone/agent/mcp's mcpHandler()) can serve real Node HTTP traffic without a second\n// transport implementation. CLI-level plumbing only — HTTP itself still lives in\n// providers/rest for business-backend calls; this adapter never touches a backend.\n//\n// #49 (P0, unauthenticated remote DoS): this function must never reject and must always\n// reach a terminal `res.end()`. It is invoked from a Node `request` listener, where an\n// escaping rejection is an unhandled rejection and therefore a fatal uncaught exception —\n// one client that declares a Content-Length and disconnects mid-body used to kill the\n// process, before any handler and therefore before any credential check ran.\nasync function handleHttpRequest(\n handler: (request: Request) => Promise<Response>,\n req: IncomingMessage,\n res: ServerResponse,\n): Promise<void> {\n // #50: the body is buffered BEFORE authentication (the bearer check lives inside\n // createHttpHandler, reached only once the Request is built), so an unauthenticated client\n // controls how much memory this allocates. Measured server-side: the body is held ~4x over\n // simultaneously — the chunk array, `Buffer.concat`'s copy, and undici's own copies inside\n // `new Request` — so a 256 MiB body peaked at 1,081 MiB RSS, essentially all of it in\n // `external`/`arrayBuffers`. Being external is what makes it nasty: `--max-old-space-size`\n // does not bound it, and the terminal symptom is an uncatchable OOM abort.\n //\n // A declared Content-Length over the cap is refused before a single byte is read; the\n // running total is then enforced during streaming as well, because Content-Length can lie\n // and chunked encoding omits it entirely. Like every other client fault in this adapter the\n // 413 is NOT logged — an unauthenticated caller must not be able to drive log volume (#49\n // BF-1).\n const declared = Number(req.headers[\"content-length\"]);\n if (Number.isFinite(declared) && declared > MAX_REQUEST_BODY_BYTES) {\n // Refused on the header, without reading a byte — then handed to the same lingering close\n // as the streaming guard below. Which bytes the SERVER chose to read is not what decides\n // whether the 413 survives: the RST is triggered by bytes sitting unread in the KERNEL\n // receive buffer when the write side closes, and a client that declares N and then sends N\n // — i.e. every real HTTP library — puts them there whether or not this function ever\n // looked. Measured on a warm server: 18/25 of these lost their 413 before this line\n // changed. (A fresh server loses none, which is why the test suite never caught it.)\n refuseOversizedBody(res);\n return;\n }\n\n const chunks: Buffer[] = [];\n try {\n let received = 0;\n for await (const chunk of req) {\n const buf = chunk as Buffer;\n received += buf.length;\n if (received > MAX_REQUEST_BODY_BYTES) {\n // Nothing downstream will ever read these; drop them before handing the socket over.\n chunks.length = 0;\n // Takes the socket out of `res` and answers on it directly, so returning here (which\n // tears the request stream down) can no longer cost the client its 413.\n refuseOversizedBody(res);\n return;\n }\n chunks.push(buf);\n }\n } catch {\n // The client went away mid-body (ECONNRESET / aborted), or delivered fewer bytes than\n // its declared Content-Length. On a public endpoint this is routine traffic — a closed\n // laptop, a cancelled fetch, a load-balancer health probe — NOT a server fault, so it is\n // deliberately not logged: turning an aborted-request flood into a log flood just trades\n // one denial of service for another.\n //\n // 400 is the deliberate status, not 500: the request was never completed, and nothing on\n // the server failed. In practice nobody reads it — this catch is reached only once the\n // socket is already dead. (Node does NOT surface a short body while the connection is\n // still open: it waits for the declared bytes until `server.requestTimeout`, 300 s by\n // default, and answers that itself.) The end is still attempted rather than skipped\n // because this code cannot tell from here whether `res` is writable — `req` erroring\n // does not by itself prove the response side is gone — and `endResponseQuietly` makes\n // the attempt free when it is.\n endResponseQuietly(res, 400);\n return;\n }\n\n // Translating the raw request into a Web `Request` is still CLIENT input handling, and it\n // runs BEFORE authentication (the bearer check lives inside createHttpHandler, reached only\n // at `handler(request)` below). `req.headers.host` and `req.url` are attacker-controlled and\n // a malformed value throws here — a bad `Host` was in fact a second unauthenticated kill\n // vector before #49's containment landed. So this gets its own client-fault arm, on exactly\n // the argument the body-read catch above makes: answering 500 and logging a stack trace per\n // request would hand an unauthenticated caller ~13x log amplification and trade the crash\n // for a disk-fill DoS. RFC 9112 §3.2 also makes 400 the required answer to an invalid Host.\n //\n // Classification is positional, not by error sniffing: what failed decides the class, so it\n // cannot drift when undici changes an error's shape between Node versions.\n let request: Request;\n try {\n const headers = new Headers();\n for (const [key, value] of Object.entries(req.headers)) {\n if (value !== undefined) headers.set(key, Array.isArray(value) ? value.join(\", \") : value);\n }\n const hasBody = req.method !== \"GET\" && req.method !== \"HEAD\" && chunks.length > 0;\n request = new Request(`http://${req.headers.host ?? \"localhost\"}${req.url ?? \"/\"}`, {\n method: req.method ?? \"GET\",\n headers,\n body: hasBody ? Buffer.concat(chunks) : undefined,\n });\n } catch {\n endResponseQuietly(res, 400);\n return;\n }\n\n try {\n const response = await handler(request);\n res.statusCode = response.status;\n response.headers.forEach((value, key) => res.setHeader(key, value));\n res.end(response.body ? Buffer.from(await response.arrayBuffer()) : undefined);\n } catch (err) {\n // A genuine server-side failure: the handler rejected, or serialising its Response threw.\n // Unlike a malformed or abandoned request this IS worth surfacing, so it is logged — and\n // answered with a 500 rather than left to hang the caller. Nothing attacker-controlled\n // reaches this arm without first passing through the handler, so it cannot be used as a\n // log-amplification primitive the way the pre-auth construction path above could.\n console.error(\"archstone serve --http: request handling failed —\", err);\n endResponseQuietly(res, 500);\n }\n}\n\nconst HEALTH_ICON: Record<HealthStatus, string> = { green: \"🟢\", yellow: \"🟡\", red: \"🔴\" };\n\n/** #124: deliberately NOT one of `HEALTH_ICON`'s three. A skipped binding was never inspected,\n * so it must not be scannable as a colour — no colour is earned (ADD-124 D-2). */\nconst SKIP_ICON = \"⏭\";\n\n/**\n * #124 / ADD-124 D-13 — printed once, only when something was skipped, and only to a human.\n *\n * It names the PATTERN and never a capability id: nothing in CDL or the IR links a `write`\n * capability to its `read` counterpart (`examples/manifests/bank`'s\n * `initiate-transfer`/`quote-transfer` pair is naming convention, not a declared relationship),\n * so guessing one would sometimes name the wrong capability with the same confidence as the\n * right one — worse than naming none (D-11). Same hedge as `doctor.ts`'s `no-contract-non-read`\n * advisory (\"Not every write has one…\") — these two must not drift apart.\n */\nconst READ_TWIN_TIP =\n \" Where one of these has a `read` capability against the same backend — the quote half of a\\n\" +\n \" quote → commit pair — verifying that instead hits the same host, auth and serialization,\\n\" +\n \" catching most infrastructure and schema drift at zero risk. Not every write has one, and\\n\" +\n \" Archstone cannot tell you which capability it is: nothing in CDL declares that relationship.\\n\" +\n \" If this backend really is a sandbox tenant, pass --sandbox.\";\n\nasync function runVerifyCmd(dir: string, json: boolean, sandbox: boolean): Promise<void> {\n const res = load(dir);\n const diags = validateSemantics(res);\n const errors = diags.filter((d) => d.severity === \"error\");\n const ok = res.ok && errors.length === 0;\n if (!ok) {\n if (json) {\n // ADD-20 D-2: this shape is strictly disjoint from the `{results}` shape below —\n // never add a shared \"envelope\" field (e.g. `ok`) to either.\n console.log(JSON.stringify({ error: \"manifest_invalid\", issues: res.issues, errors }));\n } else {\n console.error(`archstone verify ${dir}: manifest invalid — run 'archstone apply ${dir}' for details`);\n }\n process.exit(2);\n }\n\n const registry = new Registry(compile(res));\n // Two literal call sites rather than one with a computed 5th argument (#124 / ADD-124 D-3).\n // The DEFAULT path — what CI and every non-sandbox operator runs — stays the exact\n // three-argument form the two CLI surface tests pin: no `InvokeOptions` bag at all, so no\n // audit sink and no per-response callback can reach it. The `--sandbox` path passes an\n // explicit `undefined` in that slot for the same reason, so the scope argument can never be\n // the reason such a bag starts being constructed here.\n const { results, skipped } = sandbox\n ? await runVerify(registry.listCapabilities(), dir, registry.ir.resources, undefined, { includeNonRead: true })\n : await runVerify(registry.listCapabilities(), dir, registry.ir.resources);\n\n // ADD-124 D-6: computed from `results` ONLY, exactly as before. A skip never fails the gate —\n // an all-skipped run exits 0, the same code an all-empty run already produced. Inventing a\n // failure mode for \"every write/irreversible binding correctly declined to replay itself\"\n // would punish the manifests doing the safe, default thing.\n const exitCode = results.some((r) => r.status === \"red\") ? 1 : 0;\n\n if (json) {\n // ADD-20 D-2: strictly disjoint from the `{error, issues, errors}` shape above.\n //\n // `skipped` and `sandbox` are ADDITIVE (ADD-124 D-7). A consumer filtering `results` for red\n // is unaffected: skipped bindings were never in `results` to begin with. `sandbox` records\n // HOW verify was invoked, so a dashboard can tell \"nothing dangerous was replayed\" from\n // \"everything was replayed because someone asserted a sandbox\".\n console.log(JSON.stringify({ results, skipped, sandbox }));\n process.exit(exitCode);\n }\n\n console.log(`\\narchstone verify ${dir}\\n`);\n if (results.length === 0 && skipped.length === 0) {\n console.log(\" (no bindings declare a contract: — nothing to verify)\\n\");\n process.exit(0);\n }\n for (const r of results) {\n console.log(` ${HEALTH_ICON[r.status]} ${r.capabilityId} — ${r.detail}`);\n }\n for (const s of skipped) {\n console.log(` ${SKIP_ICON} ${s.capabilityId} — ${s.detail}`);\n }\n if (skipped.length > 0) {\n console.log(`\\n ${skipped.length} binding(s) were NOT verified against the backend.`);\n console.log(READ_TWIN_TIP);\n }\n console.log(\"\");\n process.exit(exitCode);\n}\n\n/** Value of a `--name value` flag pair, plus the index it was found at (-1 if absent) —\n * used both to read the value and to exclude both tokens from the positional args. */\nfunction flagArg(argv: string[], name: string): { value?: string; idx: number } {\n const idx = argv.indexOf(name);\n return { value: idx !== -1 ? argv[idx + 1] : undefined, idx };\n}\n\n/**\n * #102 — A-7 §5's pre-production checklist, run instead of read. Offline by construction: it\n * compiles the manifest and inspects the IR plus what sits beside it on disk. Nothing is\n * invoked and no backend is contacted — that is `verify`, and this is the question you ask\n * before pointing anything at production.\n */\nfunction runDoctor(dir: string, json: boolean): void {\n const res = load(dir);\n const diags = validateSemantics(res);\n const errors = diags.filter((d) => d.severity === \"error\");\n if (!res.ok || errors.length > 0) {\n console.error(`archstone doctor ${dir}: manifest invalid — run 'archstone apply ${dir}' for details`);\n process.exit(1);\n }\n\n const ir = compile(res);\n // Compare drift against what `build` would actually write, which strips `contract` (ADD-43\n // D-9's strip rule) — comparing against the unstripped IR would report drift on every\n // manifest that records a fixture, i.e. on every well-configured one.\n const stripped: IR = { ...ir, tools: ir.tools.map(({ contract: _contract, ...t }) => t) };\n const report = diagnose(ir, dir, { builtIr: `${JSON.stringify(stripped, null, 2)}\\n` });\n\n console.log(json ? JSON.stringify(report, null, 2) : formatReport(report, dir));\n process.exit(report.ok ? 0 : 1);\n}\n\nasync function main(): Promise<void> {\n const argv = process.argv.slice(2);\n\n // Before anything else: `--version`/`-V` and `--help`/`-h` are what a human types first, and\n // both used to fall through to the usage block with exit 2 — a non-zero exit for a question\n // that was answered correctly. Both now exit 0. `-V` is capitalised because `-v` is verbose\n // by long convention and should stay free.\n if (argv.includes(\"--version\") || argv.includes(\"-V\")) {\n console.log(cliVersion());\n return;\n }\n if (argv.includes(\"--help\") || argv.includes(\"-h\")) {\n printUsage();\n return;\n }\n\n const json = argv.includes(\"--json\");\n const http = argv.includes(\"--http\");\n // #124: boolean, takes no argument. NOT `--force`/`--yes`: those read as overriding a check\n // Archstone performed, and the honest situation is the opposite — Archstone performed no check\n // and structurally cannot (`doctor`'s own `env-baseurl` advisory already concedes that the\n // deployment, not the manifest, decides where `${VAR}` points). `--sandbox` is the operator\n // supplying the one fact only they hold. It takes no target string because a target would\n // imply Archstone validates it against something, and there is nothing to validate against.\n const sandbox = argv.includes(\"--sandbox\");\n const out = flagArg(argv, \"--out\");\n const port = flagArg(argv, \"--port\");\n const token = flagArg(argv, \"--token\");\n\n const consumed = new Set<number>();\n for (const f of [out, port, token]) {\n if (f.idx !== -1) {\n consumed.add(f.idx);\n consumed.add(f.idx + 1);\n }\n }\n const positional = argv.filter((a, i) => !consumed.has(i) && a !== \"--json\" && a !== \"--http\" && a !== \"--sandbox\");\n const [cmd, dir] = positional;\n\n if (cmd === \"apply\" && dir) {\n runApply(dir);\n return;\n }\n if (cmd === \"serve\" && dir && http) {\n // Bearer token: --token wins over ARCHSTONE_HTTP_TOKEN if both are set (Rule #7 —\n // required, never defaults open).\n runServeHttp(dir, Number(port.value ?? 8787), token.value ?? process.env.ARCHSTONE_HTTP_TOKEN);\n return; // blocks on the HTTP server\n }\n if (cmd === \"serve\" && dir) {\n await serveStdio(dir); // blocks on the stdio transport\n return;\n }\n if (cmd === \"verify\" && dir) {\n await runVerifyCmd(dir, json, sandbox);\n return;\n }\n if (cmd === \"build\" && dir) {\n runBuild(dir, out.value);\n return;\n }\n if (cmd === \"doctor\" && dir) {\n runDoctor(dir, json);\n return;\n }\n if (cmd === \"adopt\") {\n // Its own parser, and its own module: it is the only verb that WRITES a manifest a human\n // already owns, so keeping it apart from the read-only verbs above is deliberate.\n process.exit(await runAdoptCmd(argv));\n }\n if (cmd === \"audit\") {\n // Own parser, for the same reason `init` has one: this verb's flags outnumber the other\n // verbs' put together, and threading them through the positional logic above would make\n // both harder to read.\n process.exit(runAuditCmd(argv));\n }\n if (cmd === \"init\") {\n // Everything `init` needs is in its own argv parser: it has more flags than the other four\n // verbs put together, and threading them through this function's positional logic would\n // make both harder to read.\n process.exit(await runInitCmd(argv));\n }\n\n printUsage({ toStderr: true });\n process.exit(2);\n}\n\nmain();\n","// `archstone init` — THIN (ADD-37 §6 step 7, D-5).\n//\n// This file owns exactly three things: argv, the terminal gate, and rendering the report.\n// Every decision of substance lives elsewhere and is testable without a terminal:\n// - what a document says → `@archstone/init`'s adapters\n// - what becomes a manifest → `emit`, pure\n// - whether anything is written → `@archstone/init/loop`, one of two terminal states\n// - whether a request is ever made → the probe gate, two independent conditions\n//\n// The gate produces DATA — a Decision Record — and nothing else. That is what lets a hosted\n// \"point us at your spec\" flow (§9's forward constraint) supply the identical structure from a\n// web form and reuse the core verbatim, and it is why this file has no business logic to test.\n\nimport { createInterface } from \"node:readline/promises\";\nimport { existsSync, readFileSync, statSync, writeFileSync } from \"node:fs\";\nimport { dirname, isAbsolute, join, relative, resolve, sep } from \"node:path\";\nimport {\n CAPABILITY_ID_RE,\n COMPANY_ID_RE,\n formatReport,\n isKnown,\n locusCandidates,\n openApiAdapter,\n valueOrUndefined,\n type CapabilityDecision,\n validateDecisionRecord,\n type DecisionRecord,\n type DraftModel,\n type DraftOperation,\n type Effect,\n type SourceAdapter,\n type SourceInput,\n} from \"@archstone/init\";\nimport { runInit } from \"@archstone/init/loop\";\n\n/** Bounded so a malformed or hostile document cannot make the host loop forever fetching. */\nconst MAX_REFERENCE_ROUNDS = 8;\n\nexport interface InitArgs {\n spec: string;\n out: string;\n domain?: string;\n company?: string;\n probe: boolean;\n decisionsFile?: string;\n interactive: boolean;\n force: boolean;\n reportFile?: string;\n}\n\nexport const INIT_USAGE = [\n \"usage: archstone init <spec-file> --out <dir> [options]\",\n \"\",\n \" Read an API description, ask you the questions no tool can answer, and write a CDL\",\n \" manifest the real compiler has already compiled. No LLM is involved, on any path.\",\n \"\",\n \" --out <dir> where the manifest goes (required)\",\n \" --domain <name> the domain half of every capability id (e.g. 'framing')\",\n \" --company <id> company id, lowercase kebab (e.g. 'acme')\",\n \" --decisions <file> a Decision Record JSON file, instead of the interactive gate.\",\n \" Each entry's `operation` is the CANDIDATE KEY, which is\",\n \" `<METHOD> <path>` with the path INCLUDING the server base path\",\n \" from `servers[0].url` — so a document whose `paths:` reads\",\n \" `/catalog/frames` under a server of `https://api.x.test/api/v1`\",\n \" has the key `GET /api/v1/catalog/frames`. Run without --decisions\",\n \" once to see the real keys, or read them off a failed run's report.\",\n \" Not combinable with --company or --domain, which it answers.\",\n \" --report <file> also write the report here (default: <out>/INIT-REPORT.md)\",\n \" --probe OPT-IN, READ-ONLY. Record a golden fixture by making ONE live\",\n \" request per capability you consent to. Never issued for a\",\n \" capability whose confirmed effect is not `read`; a non-GET/HEAD\",\n \" method needs a second, separate confirmation, and is refused\",\n \" outright when there is no terminal. Off by default.\",\n \" --non-interactive no prompts. Requires --decisions: `init` never defaults an\",\n \" `effect`, so with no human and no record there is nothing to do.\",\n \" --force write into a non-empty directory\",\n].join(\"\\n\");\n\n// ---------------------------------------------------------------------------------------\n// D-11's host half: the host fetches, the adapter stays pure.\n// ---------------------------------------------------------------------------------------\n\n/**\n * Resolve one adapter-requested reference to a real path, or refuse.\n *\n * SUBTREE ONLY. The adapter already refuses to emit a `..`, and this refuses to follow one —\n * two independent checks, because the thing being prevented is a spec file turning into an\n * arbitrary file-read primitive, and one check is one bug away from none.\n */\nexport function resolveReference(specFile: string, key: string): string | undefined {\n if (isAbsolute(key) || key.split(/[\\\\/]/).includes(\"..\")) return undefined;\n const root = dirname(resolve(specFile));\n const target = resolve(root, key);\n if (target !== root && !target.startsWith(root + sep)) return undefined;\n return existsSync(target) && statSync(target).isFile() ? target : undefined;\n}\n\n/** Read the primary document and everything the adapter asks for, to closure. */\nexport function loadSource(adapter: SourceAdapter, specFile: string): { input: SourceInput; unresolved: string[] } {\n const input: SourceInput = { origin: relative(process.cwd(), specFile) || specFile, document: readFileSync(specFile, \"utf8\"), documents: {} };\n const unresolved: string[] = [];\n if (!adapter.references) return { input, unresolved };\n\n for (let round = 0; round < MAX_REFERENCE_ROUNDS; round += 1) {\n const wanted = adapter.references(input).filter((key) => input.documents![key] === undefined && !unresolved.includes(key));\n if (wanted.length === 0) break;\n for (const key of wanted) {\n const path = resolveReference(specFile, key);\n // Unresolvable is NOT fatal here. The adapter reports what it is still missing and fails\n // closed on the operations that needed it — that division of labour is the whole point\n // of `references()` being a question rather than a demand.\n if (path === undefined) unresolved.push(key);\n else input.documents![key] = readFileSync(path, \"utf8\");\n }\n }\n return { input, unresolved };\n}\n\n// ---------------------------------------------------------------------------------------\n// The gate\n// ---------------------------------------------------------------------------------------\n\n/** Everything the gate needs to ask, so the asking itself is trivial and the ORDER is\n * reviewable. Product §11.1: the minimum keystroke path for a large spec is the design. */\nexport interface Ask {\n question(text: string, fallback?: string): Promise<string>;\n}\n\n/**\n * Why the gate can no longer ask anything — or `undefined` if this is an ordinary bug.\n *\n * Both members end the run the same way (nothing written, one line, non-zero) and are kept\n * apart only so the line is true.\n *\n * `no-more-input` — `AbortError`. Ctrl+D at a TTY raises it from `_ttyWrite`\n * (`AbortError: Aborted with Ctrl+D`), and so does the signal\n * `terminalAsk` ties to the interface's `close` — which is the case a\n * question PENDING when stdin ends takes, i.e. the ordinary piped/CI one.\n * `terminal-closed` — `ERR_USE_AFTER_CLOSE`. Strictly the NEXT question after readline has\n * already closed.\n *\n * NAMED CAREFULLY, because the obvious split is wrong. \"Cancelled\" would read as \"the user\n * changed their mind\", and the same `AbortError` covers both that and a stdin that simply ran\n * out — which is the more common one in practice. The two are indistinguishable at this point,\n * so the label and the message say only what is actually known: there is no more input.\n *\n * Detected by `name`/`code` rather than `instanceof`, because the classes Node throws are\n * internal and not exported; the name and the code are the documented parts.\n *\n * Returning `undefined` for everything else is deliberate. Swallowing a real bug as \"the user\n * changed their mind\" would be a worse silence than the stack trace this replaces.\n */\nexport function promptFailureKind(error: unknown): \"no-more-input\" | \"terminal-closed\" | undefined {\n if (!(error instanceof Error)) return undefined;\n const code = (error as { code?: string }).code;\n if (error.name === \"AbortError\" || code === \"ABORT_ERR\") return \"no-more-input\";\n if (code === \"ERR_USE_AFTER_CLOSE\") return \"terminal-closed\";\n return undefined;\n}\n\n/**\n * The REAL terminal `Ask` — and the reason it has to exist.\n *\n * `readline/promises`' signature is `question(query[, options])`, where `options` is\n * `{signal}`. Passing a fallback STRING as the second argument is silently ignored: the call\n * type-checks against a `readline.Interface` — which structurally satisfies `Ask`, since\n * `question(text, anything?)` is assignable — resolves with `\"\"` on an empty line, and drops the\n * default on the floor.\n *\n * That is exactly what shipped: `runGate` was handed the `Interface` itself, so EVERY default in\n * the gate was dead. `--company` and `--domain` did nothing interactively, the\n * `${COMPANY}_API_URL` suggestion never appeared, and a computed capability id had to be retyped\n * in full. The minimum-keystroke path product §11.1 calls \"the design\" did not exist.\n *\n * It stayed invisible because the tests drive a fake `Ask` that honours the fallback — so they\n * implement the INTERFACE, and the interface is not where the bug is. The call site passes the\n * fallback correctly; it is dropped at the boundary. Nothing that substitutes for the boundary\n * can see a bug in the boundary.\n *\n * Two things this does, and both are load-bearing:\n * - SHOWS the default, the way `confirm` already shows `[Y/n]`. A default the user cannot see\n * is not a default, it is a coincidence.\n * - Treats an empty line as the default — the identical rule `confirm` applies at its own\n * prompt, which is precisely the logic every other prompt assumed someone else was doing.\n */\nexport function terminalAsk(rl: TerminalInterface): Ask {\n // A question already PENDING when stdin reaches EOF NEVER SETTLES — readline neither resolves\n // it nor rejects it. With no handle left to wait on, Node then drains the event loop and the\n // process exits 0, having asked a question nobody answered and written nothing. Exit 0 is the\n // worst available outcome: a script that pipes answers in reports success.\n //\n // That is exactly what `printf 'a\\nb\\n…' | archstone init` did, and the reason is structural\n // rather than a race: `question` registers a ONE-SHOT line handler, and readline has no queue,\n // so every line that arrives while no question is pending is discarded. A pipe delivers all\n // its lines in one chunk, so answer 1 is consumed and answers 2..n are dropped. Piping answers\n // into the gate has never worked and cannot be made to work here — `--decisions` is the\n // supported way to answer without a human.\n //\n // Tying a signal to the interface's own `close` turns that silent exit-0 into the same clean\n // refusal Ctrl+D gets: one line, nothing written, non-zero. It cannot fire on a healthy\n // terminal, where stdin stays open until the user closes it. `MAX_PROMPT_ATTEMPTS` cannot help\n // here — a bound on ATTEMPTS never fires when the first attempt never returns.\n const controller = new AbortController();\n rl.once?.(\"close\", () => controller.abort());\n return {\n async question(text: string, fallback?: string): Promise<string> {\n const suggestion = fallback !== undefined && fallback !== \"\" ? fallback : undefined;\n const prompt = suggestion === undefined ? text : `${text.trimEnd()} [${suggestion}] `;\n let answer: string;\n try {\n answer = await rl.question(prompt, { signal: controller.signal });\n } catch (error) {\n // TRANSLATED AT THE BOUNDARY, not at the caller. `runGateOverTerminal` used to classify\n // whatever escaped the whole of `runGate`, which meant a future `AbortController`\n // anywhere inside it — a fetch with a timeout, say — would have its abort silently\n // relabelled as \"the user pressed Ctrl+D\" and reported as a clean refusal. Throwing a\n // private sentinel makes that impossible by construction: only this boundary can produce\n // one, so only this boundary's failures can be read as \"no more input\".\n const kind = promptFailureKind(error);\n if (kind === undefined) throw error;\n throw new PromptUnavailable(kind);\n }\n return answer.trim() === \"\" && suggestion !== undefined ? suggestion : answer;\n },\n };\n}\n\n/** The gate cannot ask anything further. Private to this module on purpose — see `terminalAsk`. */\nclass PromptUnavailable extends Error {\n constructor(readonly kind: \"no-more-input\" | \"terminal-closed\") {\n super(kind);\n this.name = \"PromptUnavailable\";\n }\n}\n\n/** The slice of `readline.Interface` this file uses. Narrow on purpose: a wider type is what\n * let the interface itself be passed as an `Ask` in the first place. */\nexport interface TerminalInterface {\n question(query: string, options?: { signal?: AbortSignal }): Promise<string>;\n once?(event: \"close\", listener: () => void): unknown;\n}\n\n/**\n * Run the gate against a REAL readline interface, translating cancellation into a value.\n *\n * Extracted from the command so both halves of the terminal boundary are reachable by a test\n * that constructs an actual `readline.Interface` — which is the only kind of test that could\n * have caught either of the two defects here, since both live on the far side of `Ask` and a\n * substitute for `Ask` is by construction blind to them.\n */\nexport async function runGateOverTerminal(\n draft: DraftModel,\n rl: TerminalInterface,\n args: InitArgs,\n): Promise<DecisionRecord | \"no-more-input\" | \"terminal-closed\" | undefined> {\n try {\n // `terminalAsk`, NEVER the interface itself: `rl` structurally satisfies `Ask` and silently\n // ignores the fallback, which is how every default in the gate came to be dead.\n return await runGate(draft, terminalAsk(rl), args);\n } catch (error) {\n // ONLY the sentinel, which only `terminalAsk` can throw. An abort raised by anything else\n // inside `runGate` is a bug and must keep looking like one.\n if (error instanceof PromptUnavailable) return error.kind;\n throw error;\n }\n}\n\n/**\n * How many times a prompt re-asks before the gate gives up.\n *\n * NOT politeness — a bound on REPEATED INVALID ANSWERS, so a `while (!valid)` loop cannot spin.\n * Found by a test whose script ran out of answers: the worker hit an OOM abort rather than\n * failing.\n *\n * CORRECTED: this comment used to justify the bound with \"`readline.question` resolves with `\"\"`\n * forever once stdin reaches EOF\". That is not what `readline/promises` does — verified against\n * the real interface rather than the test double that stood in for it. At EOF a PENDING question\n * never settles at all, and a question asked AFTER the close throws `ERR_USE_AFTER_CLOSE`.\n * Neither is a spin, and neither is something a bound on attempts could ever have caught: the\n * first never returns, and the second is a rejection. `terminalAsk` handles both — see there.\n * The bound is still right, for the reason above and not for the reason it used to give.\n */\nconst MAX_PROMPT_ATTEMPTS = 5;\n\n/**\n * Ask until the answer validates, or give up.\n *\n * Giving up returns `undefined` and the gate refuses the whole run — which is the correct\n * terminal state, because the alternative is defaulting a value nobody supplied, and every\n * question this gate asks exists precisely because it must not be defaulted.\n */\nasync function askUntil<T>(\n ask: Ask,\n question: string,\n parse: (answer: string) => T | undefined,\n onInvalid: () => void,\n fallback?: string,\n): Promise<T | undefined> {\n for (let attempt = 0; attempt < MAX_PROMPT_ATTEMPTS; attempt += 1) {\n const parsed = parse((await ask.question(question, fallback)).trim());\n if (parsed !== undefined) return parsed;\n onInvalid();\n }\n return undefined;\n}\n\n/** `y`/`n` with an explicit default. Anything unrecognized takes the default — a gate that\n * re-asks forever on a typo is a gate people learn to `--non-interactive` around. */\nasync function confirm(ask: Ask, text: string, fallback: boolean): Promise<boolean> {\n const answer = (await ask.question(`${text} [${fallback ? \"Y/n\" : \"y/N\"}] `)).trim().toLowerCase();\n if (answer === \"\") return fallback;\n return answer.startsWith(\"y\");\n}\n\nconst EFFECTS = new Set<Effect>([\"read\", \"write\", \"irreversible\"]);\n\n/**\n * The interactive gate. Produces a Decision Record and NOTHING else — no files, no requests.\n *\n * Two rules from product §11.1 shape the keystrokes, and both are about a 40-operation spec:\n * DEFAULT-SKIP with a bulk-keep escape (`a`), because most operations in a spec are not\n * capabilities; and `effect` PRE-FILLED ONLY FOR `GET`, blank and mandatory for everything\n * else. A pre-filled `read` on a `DELETE` is the exact keystroke that would make the\n * consequence-bearing asymmetry — the developer runs `init`, the business pays for a wrong\n * `effect` months later, through an agent, in front of a customer — land on the wrong person.\n */\nexport async function runGate(draft: DraftModel, ask: Ask, args: InitArgs): Promise<DecisionRecord | undefined> {\n const companyId = (await ask.question(\"Company id (lowercase, kebab-case) \", args.company)).trim();\n if (!COMPANY_ID_RE.test(companyId)) {\n console.error(`archstone init: '${companyId}' is not a valid company id (^[a-z][a-z0-9-]*$).`);\n return undefined;\n }\n const companyName = (await ask.question(\"Company name (for the manifest header) \", valueOrUndefined(draft.company.name))).trim();\n const domain = (await ask.question(\"Domain for these capabilities (the first half of every id) \", args.domain)).trim();\n\n // Amendment 1 §A-5 gap 4, and NF-A from the re-review: the env-var names are not derivable\n // from any source construct, so they are human answers with sane defaults — the same shape\n // as every other question here. Asked once per run, not per capability, and only for auth\n // when the source actually declared a scheme, so a public API costs zero extra keystrokes.\n const envPrefix = companyId.replace(/-/g, \"_\").toUpperCase();\n const baseUrlEnvVar = (await ask.question(\"Env var holding the backend base URL \", `${envPrefix}_API_URL`)).trim();\n const declaresAuth = draft.auth !== undefined || draft.operations.some((o) => o.auth?.kind === \"header\");\n const authEnvVar = declaresAuth\n ? (await ask.question(\"Env var holding the API credential (never its value) \", `${envPrefix}_API_TOKEN`)).trim()\n : \"\";\n\n const decisions: CapabilityDecision[] = [];\n let keepAll = false;\n\n for (const [index, candidate] of draft.operations.entries()) {\n const operation: DraftOperation = candidate;\n const summary = valueOrUndefined(operation.description) ?? \"\";\n console.log(\"\");\n console.log(`[${index + 1}/${draft.operations.length}] ${operation.key}`);\n if (summary) console.log(` ${summary}`);\n const blocking = operation.notes.filter((n) => n.code.startsWith(\"unsupported\") || n.code === \"declined\");\n for (const n of blocking) console.log(` ! ${n.code}${n.detail ? `: ${n.detail}` : \"\"}`);\n\n let keep = keepAll;\n if (!keep) {\n const answer = (await ask.question(\" keep as a capability? [y/N/a=keep all remaining] \")).trim().toLowerCase();\n if (answer === \"a\") {\n keepAll = true;\n keep = true;\n } else keep = answer.startsWith(\"y\");\n }\n if (!keep) {\n decisions.push({ operation: operation.key, keep: false });\n continue;\n }\n\n const action = valueOrUndefined(operation.suggestedAction);\n const suggestedId = domain !== \"\" && action !== undefined ? `${domain}.${action}` : undefined;\n const capabilityId = (await ask.question(\" capability id (domain.action) \", suggestedId)).trim();\n if (!CAPABILITY_ID_RE.test(capabilityId)) {\n console.error(` '${capabilityId}' is not a valid capability id — skipping this candidate.`);\n decisions.push({ operation: operation.key, keep: false, note: `invalid id '${capabilityId}' supplied at the gate` });\n continue;\n }\n\n // PRE-FILLED ONLY FOR `GET`. `effectHint` exists solely to fill this prompt, and the\n // emitter cannot see it — \"no `effect` without human confirmation\" is a property of the\n // emission signature, not a runtime check someone can route around.\n const prefill = operation.method.toUpperCase() === \"GET\" && operation.effectHint ? operation.effectHint.value : undefined;\n const effect = await askUntil<Effect>(\n ask,\n \" effect (read | write | irreversible) \",\n (answer) => (EFFECTS.has(answer as Effect) ? (answer as Effect) : undefined),\n () => console.error(\" must be one of: read, write, irreversible\"),\n prefill,\n );\n if (effect === undefined) {\n console.error(\"archstone init: no valid `effect` after several attempts — refusing rather than defaulting one.\");\n return undefined;\n }\n\n // D-14 — THE LOCUS, ASKED BEFORE THE NAME. They are the same question at two altitudes:\n // \"it returns a PartQuote\" IS the root answer, \"it returns a list of QuoteWarning\" IS the\n // array answer, and the name is unanswerable until the locus is fixed because the name\n // names the locus.\n //\n // Only asked when a choice exists. On a nine-operation spec that is three questions, not\n // nine — the census is what keeps the keystroke cost proportional.\n let responseLocus: string | undefined;\n const census = locusCandidates(operation.response);\n if (census.candidates.length > 1) {\n // R-11 IS WHY THIS PROMPT LOOKS LIKE THIS, and it is the piece the architect is least\n // confident in: a badly-worded question yields confirmed-but-wrong loci that are WORSE\n // than the silent ones they replace, because a human signed them. Nobody can answer\n // \"$.warnings[*] or root?\" on an endpoint they did not write. They can answer\n // \"a list of (code, message)\" versus \"one thing with (quotedPrice, currency)\".\n // Count-agnostic. The fixed string \"two ways\" was wrong the moment a response carried\n // root scalars plus two lists — a real shape, not a hypothetical one — and it shipped\n // because nothing in the suite reached three candidates.\n console.log(` this response could be read ${census.candidates.length} ways — which one does this capability return?`);\n for (const [index, candidate] of census.candidates.entries()) {\n const shape = candidate.kind === \"root\" ? \"one object, with fields\" : `a list, each with fields`;\n console.log(` ${index + 1}. ${shape}: ${candidate.fields.join(\", \")}`);\n console.log(` (${candidate.id})`);\n }\n // Pre-filled with the sole array-of-objects when there is exactly one — today's answer,\n // so a paginated list costs one keypress. A PROPOSAL, never a decision: the emitter\n // reads the selection and can never re-derive it.\n const collections = census.candidates.filter((c) => c.kind === \"collection\");\n // Pre-filled ONLY when there is exactly one list — that is today's answer, so a\n // paginated list costs one keypress. With two or more lists there is no defensible\n // pre-fill, and offering one would be the branch-order guess D-14 exists to remove.\n const prefill = collections.length === 1 ? String(census.candidates.indexOf(collections[0]!) + 1) : undefined;\n const picked = await askUntil<number>(\n ask,\n ` which one? [1-${census.candidates.length}] `,\n (answer) => {\n const index = Number(answer);\n return Number.isInteger(index) && index >= 1 && index <= census.candidates.length ? index : undefined;\n },\n () => console.error(` answer with a number from 1 to ${census.candidates.length}`),\n prefill,\n );\n if (picked === undefined) {\n console.error(\"archstone init: no response locus chosen after several attempts — refusing rather than guessing one.\");\n return undefined;\n }\n responseLocus = census.candidates[picked - 1]!.id;\n }\n\n const resourceName = (await ask.question(\" resource name (blank = derive from the source) \")).trim();\n\n const decision: Extract<CapabilityDecision, { keep: true }> = {\n operation: operation.key,\n keep: true,\n capabilityId,\n effect: effect as Effect,\n ...(responseLocus !== undefined ? { responseLocus } : {}),\n ...(resourceName !== \"\" ? { resourceName } : {}),\n };\n\n if (args.probe && decision.effect === \"read\") {\n decision.probe = await confirm(ask, ` record a golden fixture with ONE live ${operation.method} to the real backend?`, false);\n if (decision.probe) {\n const method = operation.method.toUpperCase();\n if (method !== \"GET\" && method !== \"HEAD\") {\n // R-8's second, SEPARATE confirmation. Worded so the thing being confirmed is the\n // method and not the effect again — a re-phrasing of the same question is not a\n // second condition.\n decision.probeNonReadMethodConfirmed = await confirm(\n ask,\n ` ${method} is not a GET. Confirm again that this request changes nothing on the backend:`,\n false,\n );\n }\n // D-13: pre-fill from the document's own `example`/`default`, and make the human\n // confirm every value. A probe carries a value to a production backend, and an\n // `example` may name a real customer's record — `init` cannot tell.\n //\n // THE FALLBACK IS KEPT HERE DELIBERATELY, against this gate's usual rule that a\n // consequence-bearing answer is typed rather than Entered (`effect` carries no\n // fallback; a non-`GET` probe needs its own second confirmation). By the time this\n // prompt appears the operator has ALREADY authorised a live read of this capability:\n // `--probe` is opt-in and off by default, consent is per capability, and a non-`GET`\n // method has already been confirmed separately. A sample value is a parameter of a call\n // already authorised, not a fresh authorisation.\n //\n // What makes Enter-to-accept legitimate is that the value is on screen AND ITS ORIGIN\n // IS NAMED. D-13's own worry is that a spec example may name a real customer's record —\n // `id.example: AV45` is a real product code, `artwork_id.example` is a made-up UUID, and\n // `init` cannot tell them apart. Only the human can, and only if they know the value\n // came from the API description rather than from their own last run. The raw source\n // locator used to be printed here, which is not the same thing: it is long enough to\n // skim past and it never says \"somebody else wrote this\".\n const sample: Record<string, unknown> = {};\n for (const field of operation.input) {\n const suggested = isKnown(field.example) ? String(field.example.value) : undefined;\n const origin = suggested === undefined ? \"\" : \" (from the API description)\";\n const required = valueOrUndefined(field.required) === true || field.in === \"path\";\n const typed = (await ask.question(` sample value for ${field.name}${required ? \"\" : \" (optional)\"}${origin} `, suggested)).trim();\n if (typed !== \"\") sample[field.name] = coerce(typed);\n }\n if (Object.keys(sample).length > 0) decision.sampleInput = sample;\n }\n }\n decisions.push(decision);\n }\n\n return {\n version: \"0\",\n company: { id: companyId, ...(companyName !== \"\" ? { name: companyName } : {}) },\n ...(baseUrlEnvVar !== \"\" ? { baseUrlEnvVar } : {}),\n ...(authEnvVar !== \"\" ? { authEnvVar } : {}),\n decisions,\n };\n}\n\n/** A typed sample value from a terminal. JSON first (so `50`, `true`, `[\"a\"]` survive), then\n * the raw string — a backend that wants the string `\"50\"` gets it by quoting. */\nfunction coerce(text: string): unknown {\n try {\n return JSON.parse(text) as unknown;\n } catch {\n return text;\n }\n}\n\n// ---------------------------------------------------------------------------------------\n// argv\n// ---------------------------------------------------------------------------------------\n\nexport function parseInitArgs(argv: string[]): InitArgs | { error: string } {\n const flag = (name: string): string | undefined => {\n const idx = argv.indexOf(name);\n return idx === -1 ? undefined : argv[idx + 1];\n };\n const valued = [\"--out\", \"--domain\", \"--company\", \"--decisions\", \"--report\"];\n const consumed = new Set<number>();\n for (const name of valued) {\n const idx = argv.indexOf(name);\n if (idx !== -1) {\n consumed.add(idx);\n consumed.add(idx + 1);\n }\n }\n const positional = argv.filter((a, i) => !consumed.has(i) && !a.startsWith(\"--\"));\n const spec = positional[1]; // positional[0] is the verb itself\n if (spec === undefined) return { error: \"a spec file is required\" };\n const out = flag(\"--out\");\n if (out === undefined) return { error: \"--out <dir> is required\" };\n\n return {\n spec,\n out,\n ...(flag(\"--domain\") !== undefined ? { domain: flag(\"--domain\")! } : {}),\n ...(flag(\"--company\") !== undefined ? { company: flag(\"--company\")! } : {}),\n probe: argv.includes(\"--probe\"),\n ...(flag(\"--decisions\") !== undefined ? { decisionsFile: flag(\"--decisions\")! } : {}),\n interactive: !argv.includes(\"--non-interactive\"),\n force: argv.includes(\"--force\"),\n ...(flag(\"--report\") !== undefined ? { reportFile: flag(\"--report\")! } : {}),\n };\n}\n\n// ---------------------------------------------------------------------------------------\n// The verb\n// ---------------------------------------------------------------------------------------\n\nexport async function runInitCmd(argv: string[]): Promise<number> {\n if (argv.includes(\"--help\") || argv.includes(\"-h\")) {\n console.log(INIT_USAGE);\n return 0;\n }\n const parsed = parseInitArgs(argv);\n if (\"error\" in parsed) {\n console.error(`archstone init: ${parsed.error}\\n\\n${INIT_USAGE}`);\n return 2;\n }\n const args = parsed;\n\n const specFile = resolve(process.cwd(), args.spec);\n if (!existsSync(specFile)) {\n console.error(`archstone init: no such file: ${specFile}`);\n return 2;\n }\n\n const adapter = openApiAdapter;\n const { input, unresolved } = loadSource(adapter, specFile);\n for (const key of unresolved) {\n console.error(`archstone init: referenced document '${key}' could not be read from the spec's own directory — operations that need it will be skipped.`);\n }\n const draft = adapter.adapt(input);\n\n if (draft.operations.length === 0) {\n console.error(`archstone init: ${adapter.id} found no candidate operations in ${args.spec}.`);\n for (const n of draft.notes) console.error(` - ${n.code}${n.detail ? `: ${n.detail}` : \"\"}`);\n return 1;\n }\n\n let record: DecisionRecord | undefined;\n if (args.decisionsFile !== undefined) {\n // C-3: a flag that answers a question the record already answers is a CONFLICT, not a\n // default. Silently ignoring it is the failure mode the `interactive` fix already closed\n // once — the user said something and the tool pretended they had not.\n const ignored = [args.company !== undefined ? \"--company\" : undefined, args.domain !== undefined ? \"--domain\" : undefined].filter(\n (f): f is string => f !== undefined,\n );\n if (ignored.length > 0) {\n console.error(\n `archstone init: ${ignored.join(\" and \")} ${ignored.length === 1 ? \"is\" : \"are\"} answered by the Decision Record and cannot be combined with --decisions.\\n` +\n ` ${ignored.includes(\"--company\") ? \"Set `company.id` in the record\" : \"\"}${ignored.length === 2 ? \"; \" : \"\"}${ignored.includes(\"--domain\") ? \"the domain is the first half of each `capabilityId` in the record\" : \"\"}.`,\n );\n return 2;\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(readFileSync(resolve(process.cwd(), args.decisionsFile), \"utf8\"));\n } catch (err) {\n console.error(`archstone init: cannot read the Decision Record: ${(err as Error).message}`);\n return 2;\n }\n // C-2: the record used to be an unchecked cast, and it was the ONE input `init` trusted\n // completely while refusing to trust anything else. A missing `company` produced a raw\n // TypeError with a stack trace — on the `--non-interactive` path, which is CI, where a\n // stack trace is the least actionable output there is.\n const validation = validateDecisionRecord(parsed);\n if (!validation.ok) {\n console.error(`archstone init: the Decision Record at ${args.decisionsFile} is not valid:`);\n for (const problem of validation.problems) console.error(` - ${problem}`);\n return 2;\n }\n record = validation.record;\n } else if (!args.interactive) {\n // DoD-5(d), and the one refusal in this file that is not about the network: `init` never\n // defaults an `effect`. With no human to ask and no record to read, there is nothing to do\n // that would not be a guess about a value the business pays for months later.\n console.error(\"archstone init: --non-interactive requires --decisions <file>. `init` never defaults an `effect`.\");\n return 2;\n } else {\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n let outcome: DecisionRecord | \"no-more-input\" | \"terminal-closed\" | undefined;\n try {\n outcome = await runGateOverTerminal(draft, rl, args);\n } finally {\n rl.close();\n }\n // Ctrl+D is a user saying \"I changed my mind\"; a closed stdin is a terminal that went away.\n // Both deserve the clean terminal state the refusal paths already produce — nothing written,\n // one line, non-zero — rather than the unhandled error and Node stack trace they used to\n // produce. A retry bound cannot cover either: both arrive as a REJECTED PROMISE, and\n // `MAX_PROMPT_ATTEMPTS` counts answers, not failures to be able to ask.\n if (outcome === \"no-more-input\") {\n // Deliberately NOT \"cancelled\": the same `AbortError` covers Ctrl+D and a stdin that ran\n // out, and telling a CI runner it changed its mind is a small lie that costs someone an\n // hour. The hint names the supported way to answer without a human.\n console.error(\"\\narchstone init: no more input (Ctrl+D, or stdin ended) — nothing was written.\");\n console.error(\" To answer without a human, use --decisions <file> --non-interactive.\");\n return 2;\n }\n if (outcome === \"terminal-closed\") {\n console.error(\"\\narchstone init: the terminal closed before the gate finished — nothing was written.\");\n return 2;\n }\n record = outcome;\n if (!record) return 2;\n }\n\n const result = await runInit(draft, record, {\n targetDir: resolve(process.cwd(), args.out),\n force: args.force,\n probe: args.probe,\n // \"Interactive\" for R-8's purposes means A HUMAN WAS ACTUALLY ASKED, not \"the\n // --non-interactive flag was absent\". A Decision Record file supplies every answer up\n // front, so `--decisions` without `--non-interactive` has no prompt either — and treating\n // it as interactive would let a file-supplied `probeNonReadMethodConfirmed` authorize a\n // non-GET probe against a production backend with nobody at the terminal. The second\n // confirmation is a human act performed AT THE MOMENT OF THE CALL; that is the whole\n // reason it is separate from `effect`, which a file may legitimately carry.\n interactive: args.interactive && args.decisionsFile === undefined,\n });\n\n const report = formatReport({\n origin: draft.source.origin,\n adapter: draft.source.adapter,\n targetDir: resolve(process.cwd(), args.out),\n emitted: result.emitted,\n written: result.written,\n failures: result.failures,\n probes: result.probes.map((p) => ({ capabilityId: p.capabilityId, outcome: p.outcome, detail: p.detail })),\n verifications: result.verifications,\n candidates: draft.operations.length,\n });\n console.log(`\\n${report}`);\n\n if (result.ok) {\n // The report goes to a COMMITTABLE FILE as well as to stdout (product §11.2): the file is\n // the pull-request review surface, and a reviewer who was not at the terminal is the second\n // pair of eyes on the one risk automation cannot close (R-9).\n const reportFile = args.reportFile !== undefined ? resolve(process.cwd(), args.reportFile) : join(resolve(process.cwd(), args.out), \"INIT-REPORT.md\");\n try {\n writeFileSync(reportFile, report);\n console.log(`Report also written to ${reportFile}\\n`);\n } catch (err) {\n console.error(`archstone init: could not write the report file: ${(err as Error).message}`);\n }\n }\n\n return result.ok ? 0 : 1;\n}\n","// `archstone audit <file…>` — the I/O half of the audit reader (`audit-report.ts` holds the\n// pure half). Reads the deployer's own JSON Lines files, filters, and renders.\n//\n// Note what it is not: there is no service, no index, no daemon and no upload. The records live\n// on the deployer's disk, Archstone never receives them, and this verb is a reader over local\n// files — which is also why it needs no configuration beyond the paths.\n\nimport { readFileSync } from \"node:fs\";\nimport { applyFilter, parseAuditLines, summarize, toCsv, type AuditFilter } from \"./audit-report\";\n\nconst FORMATS = [\"summary\", \"jsonl\", \"csv\"] as const;\ntype Format = (typeof FORMATS)[number];\n\nfunction flag(argv: string[], name: string): string | undefined {\n const i = argv.indexOf(name);\n return i === -1 ? undefined : argv[i + 1];\n}\n\nfunction isoOrExit(value: string | undefined, name: string): string | undefined {\n if (value === undefined) return undefined;\n // Accept a date (2026-08-21) as well as a full timestamp: an auditor asks for \"August\", not\n // for an RFC 3339 instant. A bare date compares correctly against a stored ISO timestamp\n // because both are lexicographically ordered — which is the same property the records rely on.\n if (!/^\\d{4}-\\d{2}-\\d{2}([T ].*)?$/.test(value)) {\n console.error(`archstone audit: ${name} must be a date or ISO timestamp (e.g. 2026-08-21 or 2026-08-21T09:00:00Z), got '${value}'`);\n process.exit(2);\n }\n return value;\n}\n\nexport function printAuditUsage(): void {\n console.error(\n \"usage: archstone audit <file…> [--since <date>] [--until <date>] [--capability <id>]\\n\" +\n \" [--principal <p>] [--phase succeeded|failed|denied]\\n\" +\n \" [--format summary|jsonl|csv]\\n\" +\n \"\\n\" +\n \" Read Execution audit records (JSON Lines) that your own deployment wrote, and report on\\n\" +\n \" them. Nothing is uploaded: these are your files, read locally.\\n\" +\n \"\\n\" +\n \" --since <date> inclusive lower bound on startedAt (date or ISO timestamp)\\n\" +\n \" --until <date> exclusive upper bound — so adjacent ranges tile without overlap\\n\" +\n \" --capability <id> exact CDL capability id, e.g. framing.estimate-frame-price\\n\" +\n \" --principal <p> exact principal, e.g. user:alice\\n\" +\n \" --anonymous only invocations that carried no principal at all\\n\" +\n \" --phase <p> succeeded | failed | denied\\n\" +\n \" --format <f> summary (default) · jsonl (filtered passthrough) · csv (spreadsheet)\\n\" +\n \"\\n\" +\n \" Pass rotated generations too — the sink writes <path>.1, <path>.2, …:\\n\" +\n \" archstone audit audit.log audit.log.1 --since 2026-08-01 --format csv > q3.csv\\n\",\n );\n}\n\nexport function runAuditCmd(argv: string[]): number {\n const files = argv.slice(1).filter((a, i, all) => {\n if (a.startsWith(\"--\")) return false;\n const prev = all[i - 1];\n return !(prev?.startsWith(\"--\") && prev !== \"--json\"); // not a flag's value\n });\n\n if (files.length === 0) {\n printAuditUsage();\n return 2;\n }\n\n const format = (flag(argv, \"--format\") ?? \"summary\") as Format;\n if (!FORMATS.includes(format)) {\n console.error(`archstone audit: --format must be one of ${FORMATS.join(\" | \")}, got '${format}'`);\n return 2;\n }\n\n const filter: AuditFilter = {\n since: isoOrExit(flag(argv, \"--since\"), \"--since\"),\n until: isoOrExit(flag(argv, \"--until\"), \"--until\"),\n capability: flag(argv, \"--capability\"),\n principal: argv.includes(\"--principal\") ? (flag(argv, \"--principal\") ?? \"\") : undefined,\n anonymous: argv.includes(\"--anonymous\"),\n phase: flag(argv, \"--phase\"),\n };\n\n // An empty `--principal` used to be how anonymous invocations were selected (v0.12.0). It\n // reads like a mistake in a shell, and it is indistinguishable from one — so it is now an\n // error that names the right flag rather than a subtlety that quietly answers a different\n // question than the operator asked.\n if (filter.principal === \"\") {\n console.error(\n \"archstone audit: --principal '' is not how you select anonymous invocations — use --anonymous.\\n\" +\n \" (An empty principal would mean the host supplied the empty string, which is a different thing.)\",\n );\n return 2;\n }\n if (filter.anonymous && filter.principal !== undefined) {\n console.error(\"archstone audit: --anonymous and --principal are mutually exclusive — a call is one or the other.\");\n return 2;\n }\n\n const records = [];\n let skipped = 0;\n for (const file of files) {\n let text: string;\n try {\n text = readFileSync(file, \"utf8\");\n } catch (err) {\n console.error(`archstone audit: cannot read '${file}': ${(err as Error).message}`);\n return 1;\n }\n const outcome = parseAuditLines(text);\n records.push(...outcome.records);\n // Never silent: an unreadable line in an audit trail is either corruption or a record from a\n // version this reader does not understand, and both are the operator's business.\n for (const s of outcome.skipped) console.error(`archstone audit: ${file}:${s.line} skipped — ${s.reason}`);\n skipped += outcome.skipped.length;\n }\n\n // Chronological regardless of the order the files were given, so `audit.log.1 audit.log` and\n // `audit.log audit.log.1` produce the same report.\n const filtered = applyFilter(records, filter).sort((a, b) =>\n a.metadata.startedAt.localeCompare(b.metadata.startedAt),\n );\n\n if (format === \"jsonl\") console.log(filtered.map((r) => JSON.stringify(r)).join(\"\\n\"));\n else if (format === \"csv\") console.log(toCsv(filtered));\n else console.log(summarize(filtered));\n\n if (skipped > 0) console.error(`archstone audit: ${skipped} line(s) skipped — see above.`);\n return 0;\n}\n","// `archstone audit` — read a JSON Lines audit trail, filter it, and render it for someone who\n// has to answer a question about it (#44's records; see docs/ONBOARDING.md).\n//\n// The records are the deployer's own files, written by `rotatingFileAuditSink` or any sink they\n// wrote themselves. Archstone never receives them, so this is a local reader over local files —\n// no service, no index, no daemon.\n//\n// Everything here is pure and takes lines in, strings out: the CLI does the I/O.\n\nimport type { ExecutionRecord } from \"@archstone/emitter-support\";\n\nexport interface AuditFilter {\n since?: string;\n until?: string;\n capability?: string;\n /** Exact match. Anonymous invocations are selected with `anonymous`, not with `\"\"` — see\n * `applyFilter`. */\n principal?: string;\n /** Select only invocations that carried no principal at all. The absence of the field is a\n * real distinction (ADD-42 D-4: anonymous is not denied, but never privileged), so it gets\n * its own selector rather than being spelled as an empty principal. */\n anonymous?: boolean;\n phase?: string;\n}\n\nexport interface ParseOutcome {\n records: ExecutionRecord[];\n /** Lines that were not a parseable Execution record, with their 1-based position. */\n skipped: { line: number; reason: string }[];\n}\n\n/**\n * Parse JSON Lines into records, keeping what could not be read rather than discarding it.\n *\n * A silent skip is the wrong behaviour for an audit tool specifically: an unreadable line is\n * either corruption or a record written by a version this reader does not understand, and both\n * are things the person running the report needs told. Blank lines are not \"skipped\" — a\n * trailing newline is normal, not a defect.\n */\nexport function parseAuditLines(text: string): ParseOutcome {\n const records: ExecutionRecord[] = [];\n const skipped: { line: number; reason: string }[] = [];\n\n text.split(\"\\n\").forEach((raw, i) => {\n const line = raw.trim();\n if (!line) return;\n let parsed: unknown;\n try {\n parsed = JSON.parse(line);\n } catch {\n skipped.push({ line: i + 1, reason: \"not valid JSON\" });\n return;\n }\n const rec = parsed as Partial<ExecutionRecord>;\n if (rec?.kind !== \"Execution\" || !rec.metadata || !rec.status) {\n skipped.push({ line: i + 1, reason: \"not an Execution record\" });\n return;\n }\n records.push(rec as ExecutionRecord);\n });\n\n return { records, skipped };\n}\n\n/** Inclusive on `since`, exclusive on `until` — the convention that makes adjacent day ranges\n * tile without double-counting the boundary record. */\nexport function applyFilter(records: readonly ExecutionRecord[], f: AuditFilter): ExecutionRecord[] {\n return records.filter((r) => {\n if (f.since && r.metadata.startedAt < f.since) return false;\n if (f.until && r.metadata.startedAt >= f.until) return false;\n if (f.capability && r.metadata.capabilityId !== f.capability) return false;\n if (f.phase && r.status.phase !== f.phase) return false;\n // Two different questions, deliberately not one. `principal: \"\"` means \"the caller supplied\n // an empty string as its principal\", which is a present-but-empty value and a real thing a\n // host can do; `anonymous` means the field was absent. Conflating them — the shape this\n // filter shipped with in v0.12.0 — makes the more common question the harder one to ask,\n // and makes a plausible typo (`--principal \"\"`) silently answer the other one.\n if (f.anonymous && r.spec.principal !== undefined) return false;\n if (f.principal !== undefined && r.spec.principal !== f.principal) return false;\n return true;\n });\n}\n\nconst CSV_COLUMNS = [\n \"startedAt\",\n \"completedAt\",\n \"capabilityId\",\n \"provider\",\n \"phase\",\n \"denialReason\",\n \"principal\",\n \"consumer\",\n \"policyRuleIds\",\n \"sessionId\",\n \"id\",\n] as const;\n\nfunction csvCell(value: string | undefined): string {\n const v = value ?? \"\";\n // Quote when the value could otherwise change the shape of the row. Doubling the quote is the\n // RFC 4180 escape, and it is what every spreadsheet expects.\n return /[\",\\n]/.test(v) ? `\"${v.replace(/\"/g, '\"\"')}\"` : v;\n}\n\n/**\n * CSV, because the person who asks for an audit export opens it in a spreadsheet.\n *\n * The `input` field is deliberately absent: it is per-capability shaped, frequently large, and\n * carries whatever the caller sent — flattening it into a column would both break the row shape\n * and put payloads in a file that gets emailed around. `--format jsonl` keeps the full record\n * for anyone who needs it.\n */\nexport function toCsv(records: readonly ExecutionRecord[]): string {\n const rows = records.map((r) =>\n [\n r.metadata.startedAt,\n r.metadata.completedAt,\n r.metadata.capabilityId,\n r.metadata.provider,\n r.status.phase,\n r.status.denialReason,\n r.spec.principal,\n r.spec.consumer,\n r.spec.policyRuleIds?.join(\" \"),\n r.metadata.sessionId,\n r.metadata.id,\n ]\n .map(csvCell)\n .join(\",\"),\n );\n return [CSV_COLUMNS.join(\",\"), ...rows].join(\"\\n\");\n}\n\nfunction countBy<T>(items: readonly T[], key: (item: T) => string | undefined): [string, number][] {\n const counts = new Map<string, number>();\n for (const item of items) {\n const k = key(item);\n if (k === undefined) continue;\n counts.set(k, (counts.get(k) ?? 0) + 1);\n }\n // Descending by count, then by name — deterministic output, because a report that reorders\n // between runs on equal counts cannot be diffed against last month's.\n return [...counts.entries()].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]));\n}\n\nfunction table(title: string, rows: [string, number][], limit = 20): string[] {\n if (rows.length === 0) return [];\n const shown = rows.slice(0, limit);\n const width = Math.max(...shown.map(([name]) => name.length));\n const out = [``, title, ...shown.map(([name, n]) => ` ${name.padEnd(width)} ${String(n).padStart(6)}`)];\n if (rows.length > shown.length) out.push(` … and ${rows.length - shown.length} more`);\n return out;\n}\n\n/**\n * The default rendering: what happened, to what, and what was refused.\n *\n * Denials are reported separately from failures rather than folded into one \"not succeeded\"\n * bucket, because they answer different questions. A failure is the backend or the contract\n * going wrong; a denial is governance doing its job, and an auditor asking \"show me what was\n * refused and why\" is asking about the second one.\n */\nexport function summarize(records: readonly ExecutionRecord[]): string {\n if (records.length === 0) return \"No records matched.\";\n\n const times = records.map((r) => r.metadata.startedAt).sort();\n const denied = records.filter((r) => r.status.phase === \"denied\");\n const lines: string[] = [\n `${records.length} record${records.length === 1 ? \"\" : \"s\"}`,\n ` from ${times[0]}`,\n ` to ${times[times.length - 1]}`,\n ];\n\n lines.push(...table(\"By outcome\", countBy(records, (r) => r.status.phase)));\n lines.push(...table(\"By capability\", countBy(records, (r) => r.metadata.capabilityId)));\n lines.push(...table(\"Denials by reason\", countBy(denied, (r) => r.status.denialReason ?? \"(unstated)\")));\n lines.push(\n ...table(\n \"By principal\",\n countBy(records, (r) => r.spec.principal ?? \"(anonymous)\"),\n ),\n );\n\n return lines.join(\"\\n\");\n}\n","// `archstone doctor` — the pre-production checklist, made runnable (#102).\n//\n// A-7 §5 is a list a human reads before go-live, and a list a human reads is a list a human\n// skips. Everything on it except the two judgement steps is machine-checkable from the manifest\n// and the compiled IR, so it is checked here instead.\n//\n// Deliberately offline: no backend is contacted, nothing is invoked, nothing is uploaded. That\n// is `archstone verify`'s job and it already exists. `doctor` answers the question you ask\n// *before* pointing anything at production — is this manifest wired the way a deployment needs?\n\nimport { readFileSync, existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { IR, IRTool } from \"@archstone/compiler\";\n\nexport type Severity = \"error\" | \"warning\" | \"advisory\";\n\nexport interface Finding {\n severity: Severity;\n /** Stable machine key, so a CI job can allowlist a specific finding without regex-matching prose. */\n code: string;\n capability?: string;\n message: string;\n /** Why it matters — the part that makes a checklist worth reading rather than obeying. */\n because: string;\n}\n\nexport interface DoctorReport {\n findings: Finding[];\n checked: number;\n /** Errors block; warnings and advisories do not. */\n ok: boolean;\n}\n\n/** `${VAR}` (env) and `${caller.x}` — the two interpolations `providers/rest` resolves. */\nconst ENV_INTERP = /\\$\\{[A-Za-z_][A-Za-z0-9_]*\\}/;\nconst CALLER_INTERP = /\\$\\{caller\\./;\n\nfunction baseUrlOf(tool: IRTool): string | undefined {\n return tool.connector?.rest?.baseUrl;\n}\n\n/**\n * Every check is a pure function of the IR plus what is on disk beside it. The manifest\n * directory is needed for exactly two of them — fixture existence and IR drift — and nothing\n * here writes.\n */\nexport function diagnose(ir: IR, manifestDir: string, opts: { builtIr?: string } = {}): DoctorReport {\n const findings: Finding[] = [];\n const add = (f: Finding) => findings.push(f);\n\n for (const tool of ir.tools) {\n const bound = tool.connector !== undefined;\n\n // --- invocability -----------------------------------------------------------------\n if (!bound && tool.lifecycle !== \"retired\") {\n add({\n severity: \"warning\",\n code: \"unbound-capability\",\n capability: tool.id,\n message: \"declared but has no binding, so it is not invocable\",\n because:\n \"A capability with no binding compiles and then does nothing. That is fine while you are drafting and a defect at go-live.\",\n });\n }\n\n // --- contract / fixtures ----------------------------------------------------------\n // #125 (ADD-124 D-10): one trigger condition (`bound && !tool.contract`), two answers,\n // because the honest advice inverts with `effect`. Until this split, `doctor` told you to\n // record a fixture for `tourism.pay` and, fifty lines below, that the same capability must\n // never auto-retry — and `verify` wired into CI is an auto-retry, mechanically. An advisory\n // that recommends a dangerous action is worse than a missing check: it launders the action\n // as reviewed.\n //\n // The `read` branch is byte-identical to what shipped before — same code, same severity,\n // same prose — so no dashboard filtering `no-contract` changes behaviour for a read\n // capability. The non-read branch gets a DISTINCT code so one filtering on `no-contract`\n // cannot silently merge the two (#125's DoD).\n if (bound && !tool.contract && tool.effect === \"read\") {\n add({\n severity: \"warning\",\n code: \"no-contract\",\n capability: tool.id,\n message: \"bound, but records no contract fixture\",\n because:\n \"`archstone verify` replays a recorded fixture against the live backend. With no fixture there is nothing to replay, so backend drift is found by an agent, in front of a customer, instead of by CI.\",\n });\n }\n if (bound && !tool.contract && tool.effect !== \"read\") {\n add({\n // `advisory`, not `warning`: on a `write`/`irreversible` capability, having no contract\n // fixture is now the CORRECT state, not a gap to close. `warning` would keep asking for\n // the thing this advisory exists to stop recommending.\n severity: \"advisory\",\n code: \"no-contract-non-read\",\n capability: tool.id,\n message: `bound and \\`${tool.effect}\\`, so it records no contract fixture — and should not`,\n because:\n \"`archstone verify` replays a recorded fixture as a real invocation, so a fixture here would repeat this capability's effect against the live backend on every CI run. `verify` skips it by default for that reason. Where this capability has a `read` counterpart, cover the drift with that instead — the quote half of a quote → commit pair hits the same host, auth and serialization at zero risk. Not every write has one, and Archstone cannot tell you which capability it is: nothing in CDL declares that relationship. Only if this binding's `${VAR}` genuinely resolves to a sandbox tenant is recording one worthwhile, replayed with `archstone verify --sandbox`: the flag re-includes the binding, it does not make the backend safe.\",\n });\n }\n if (tool.contract?.probeFixture) {\n const fixture = join(manifestDir, tool.contract.probeFixture);\n if (!existsSync(fixture)) {\n add({\n severity: \"error\",\n code: \"missing-fixture-file\",\n capability: tool.id,\n message: `contract names a fixture that is not on disk: ${tool.contract.probeFixture}`,\n because:\n \"The contract points at a file that does not exist, so `verify` cannot run at all — a green pipeline that never checked anything.\",\n });\n }\n }\n if (tool.lifecycle === \"retired\" && tool.contract) {\n add({\n severity: \"advisory\",\n code: \"retired-with-contract\",\n capability: tool.id,\n message: \"is retired but still carries a contract fixture\",\n because:\n \"Retired capabilities are blocked on every surface, so the fixture is dead weight — harmless, but it makes the manifest read as though the capability is still live.\",\n });\n }\n\n // --- egress -----------------------------------------------------------------------\n const baseUrl = baseUrlOf(tool);\n if (baseUrl && CALLER_INTERP.test(baseUrl)) {\n add({\n severity: \"error\",\n code: \"caller-influenced-baseurl\",\n capability: tool.id,\n message: \"baseUrl interpolates caller-supplied data\",\n because:\n \"This is the SSRF shape: a caller who chooses part of the URL chooses where the request goes. Set `allowedHosts` on the provider, which constrains the resolved host to an allowlist.\",\n });\n } else if (baseUrl && ENV_INTERP.test(baseUrl)) {\n add({\n severity: \"advisory\",\n code: \"env-baseurl\",\n capability: tool.id,\n message: `baseUrl comes from the environment (${baseUrl})`,\n because:\n \"Nothing wrong with it — but the deployment, not the manifest, decides where this capability points. Confirm the variable is set to the intended backend in every environment that runs it.\",\n });\n }\n\n // --- effects ----------------------------------------------------------------------\n if (tool.effect === \"irreversible\") {\n add({\n severity: \"advisory\",\n code: \"irreversible-effect\",\n capability: tool.id,\n message: \"is declared `irreversible`\",\n because:\n // #125 (ADD-124 D-12) appends the last sentence — code and severity unchanged. Without\n // it, this advisory and the contract advisory above land on the same capability saying\n // opposite things (\"never auto-retry\" vs \"wire it into CI\"). Naming `verify`'s default\n // here is what makes the two agree wherever a reader starts.\n \"No API description states this, so it was a human judgement: an agent must confirm explicitly and must never auto-retry. Re-read it before go-live — `irreversible` is the difference between looking up a price and charging a card. `archstone verify` applies the same judgement: it will not replay this capability's fixture against the live backend unless you assert a sandbox with --sandbox.\",\n });\n }\n\n // --- governance wiring ------------------------------------------------------------\n if (tool.policyRules?.some((r) => r.rateLimit !== undefined)) {\n add({\n severity: \"advisory\",\n code: \"ratelimit-needs-counter\",\n capability: tool.id,\n message: \"declares a rate limit, which needs a counter supplied at runtime\",\n because:\n \"With no counter the call is denied, fail-closed, at the first invocation. On more than one instance the counter must be shared, or a declared 100/min becomes 100/min per instance.\",\n });\n }\n if (tool.policies?.includes(\"authenticated\")) {\n add({\n severity: \"advisory\",\n code: \"authenticated-needs-principal\",\n capability: tool.id,\n message: \"requires an authenticated caller\",\n because:\n \"The surface serving it must carry a per-request principal — `resolveCaller` on HTTP or the embedded SDK. `archstone serve` (stdio) has one static caller for the whole process, so it cannot serve this capability to more than one identity.\",\n });\n }\n if (tool.lifecycle === \"experimental\") {\n add({\n severity: \"advisory\",\n code: \"experimental-capability\",\n capability: tool.id,\n message: \"is `experimental`: hidden from tool listings but still invocable by id\",\n because:\n \"Deliberate behaviour, and easy to forget: an agent that knows the id can still call it. Confirm that is what you want in production.\",\n });\n }\n }\n\n // --- IR drift ------------------------------------------------------------------------\n if (opts.builtIr !== undefined) {\n const committed = join(manifestDir, \"archstone.ir.json\");\n if (existsSync(committed)) {\n const onDisk = readFileSync(committed, \"utf8\");\n if (onDisk.trim() !== opts.builtIr.trim()) {\n add({\n severity: \"error\",\n code: \"ir-drift\",\n message: \"the committed archstone.ir.json does not match a fresh build of this manifest\",\n because:\n \"The artifact is what runs. A stale one enforces stale policy and exposes stale tools, silently — rebuild it and commit the result.\",\n });\n }\n }\n }\n\n return {\n findings,\n checked: ir.tools.length,\n ok: !findings.some((f) => f.severity === \"error\"),\n };\n}\n\nconst ICON: Record<Severity, string> = { error: \"🔴\", warning: \"🟡\", advisory: \"🔵\" };\n\nexport function formatReport(report: DoctorReport, dir: string): string {\n const lines = [`\\narchstone doctor ${dir}\\n`];\n if (report.findings.length === 0) {\n lines.push(`🟢 ${report.checked} capabilities checked — nothing to flag.\\n`);\n return lines.join(\"\\n\");\n }\n // Errors first: a reader who stops after five lines should have seen what blocks.\n const order: Severity[] = [\"error\", \"warning\", \"advisory\"];\n for (const sev of order) {\n for (const f of report.findings.filter((x) => x.severity === sev)) {\n lines.push(`${ICON[sev]} ${f.capability ? `${f.capability} — ` : \"\"}${f.message}`);\n lines.push(` ${f.because}`);\n lines.push(` (${f.code})\\n`);\n }\n }\n const counts = order.map((s) => `${report.findings.filter((f) => f.severity === s).length} ${s}`).join(\" · \");\n lines.push(`${report.checked} capabilities checked — ${counts}.\\n`);\n return lines.join(\"\\n\");\n}\n","// @archstone/cli — `archstone adopt` (ADD-117 / ADR-0008).\n//\n// ADD-114 made `verify` NAME the fields a provider gained. This is the only way one of them\n// becomes a field a model can use — and it is deliberately a human act. ADR-0008 forbids\n// forwarding an undeclared field; adoption is the sanctioned crossing, with a person at the\n// gate typing a description for each one.\n//\n// A VERB, not `verify --adopt` (D-1). `verify` is a read-only CI gate; a mutating flag on it\n// invites someone to put `--adopt` in a pipeline, which is exactly how ADR-0008 R-1 says this\n// feature fails. There is no `--yes` either (D-2) — `terminalAsk` already aborts cleanly when\n// stdin ends with a question pending, so a piped or CI invocation writes nothing and exits\n// non-zero by construction. That is a property of the shipped gate, not a new guard.\n\nimport { readFileSync, writeFileSync, mkdtempSync, cpSync, rmSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join, resolve } from \"node:path\";\nimport { createInterface } from \"node:readline/promises\";\nimport { load } from \"@archstone/schema\";\nimport { compile, diffShape, validateSemantics, type IRTool, type ShapeMap } from \"@archstone/compiler\";\nimport { Registry } from \"@archstone/emitter-support\";\nimport { recordContract, adoptable, planAdoption, type GoldenFixture } from \"@archstone/runtime\";\nimport { terminalAsk, type Ask } from \"./init\";\nimport { applyAdoption, applyContractRecording, type AdoptionEdit } from \"./adopt-edit\";\n\ninterface Target {\n tool: IRTool;\n resourceFile: string;\n bindingFile: string;\n}\n\n/** Which files hold this capability's resource and binding. Both come from the loader, never\n * from guessing a filename off a resource name. */\nfunction locateFiles(dir: string, tool: IRTool): Target | { problem: string } {\n const res = load(dir);\n const wanted = tool.response?.resource;\n if (!wanted) return { problem: `${tool.id}: no response mapping — nothing to adopt into` };\n\n const bare = wanted.includes(\".\") ? wanted.slice(wanted.lastIndexOf(\".\") + 1) : wanted;\n const doc = res.resourceDocs.find((d) => d.resource.name === wanted || d.resource.name.endsWith(`.${bare}`) || d.resource.name === bare);\n if (!doc) return { problem: `${tool.id}: could not find the file declaring resource '${wanted}'` };\n\n const binding = res.bindings.find((b) => b.binding.capabilityId === tool.id);\n if (!binding) return { problem: `${tool.id}: could not find its binding file` };\n\n return { tool, resourceFile: join(dir, doc.file), bindingFile: join(dir, binding.file) };\n}\n\nfunction readFixture(dir: string, path: string): GoldenFixture | undefined {\n try {\n return JSON.parse(readFileSync(resolve(dir, path), \"utf8\")) as GoldenFixture;\n } catch {\n return undefined;\n }\n}\n\n/** y/N. Anything but an explicit yes is no — the default must never be \"declare it\". */\nasync function confirm(ask: Ask, question: string): Promise<boolean> {\n const answer = (await ask.question(`${question} [y/N] `)).trim().toLowerCase();\n return answer === \"y\" || answer === \"yes\";\n}\n\n/**\n * Prove the edit before keeping it.\n *\n * The modified documents are written into a COPY of the manifest and run through the real\n * loader and compiler — the same pipeline `apply` runs. Nothing reaches the user's files until\n * that passes, so a bug in the surgical append is a refused run rather than a corrupted\n * manifest (ADD-117 Challenge).\n */\nfunction compilesClean(dir: string, resourceFile: string, resourceYaml: string, bindingFile: string, bindingYaml: string): string | undefined {\n const scratch = mkdtempSync(join(tmpdir(), \"archstone-adopt-\"));\n try {\n cpSync(dir, scratch, { recursive: true });\n writeFileSync(join(scratch, resourceFile.slice(dir.length + 1)), resourceYaml);\n writeFileSync(join(scratch, bindingFile.slice(dir.length + 1)), bindingYaml);\n const res = load(scratch);\n if (!res.ok) return res.issues.map((i) => `${i.file}: ${i.message}`).join(\"; \");\n const errors = validateSemantics(res).filter((d) => d.severity === \"error\");\n if (errors.length > 0) return errors.map((e) => e.message).join(\"; \");\n compile(res);\n return undefined;\n } catch (err) {\n return (err as Error).message;\n } finally {\n rmSync(scratch, { recursive: true, force: true });\n }\n}\n\nasync function adoptOne(dir: string, target: Target, contractShape: ShapeMap | undefined, ask: Ask): Promise<number> {\n const { tool } = target;\n const fixture = readFixture(dir, tool.contract!.probeFixture);\n if (!fixture) {\n console.error(` ${tool.id}: fixture not found or unreadable — nothing to replay`);\n return 1;\n }\n\n // ONE request (R-4). The drift and the contract that may be written both describe this\n // response; a second probe could describe a backend that changed in between.\n const recording = await recordContract(tool, fixture.request, {}, {});\n if (recording.outcome !== \"green\" && recording.outcome !== \"yellow\") {\n console.error(` ${tool.id}: ${recording.detail}`);\n return 1;\n }\n const liveShape = recording.shape ?? {};\n\n // A contract with no recorded shape (one written before ADD-114) still works: every path\n // reads as added, and the planner refuses the ones already declared. That is exactly the\n // right answer, and it means adoption does not require a re-record first.\n const drift = diffShape(contractShape ?? {}, liveShape);\n const plan = planAdoption(tool, drift, new Registry(compile(load(dir))).ir.resources);\n\n const offers = adoptable(plan);\n const refused = plan.candidates.filter((c) => !c.adoptable);\n if (refused.length > 0) {\n console.log(`\\n ${tool.id} — not adoptable:`);\n for (const c of refused) if (!c.adoptable) console.log(` · ${c.path} (${c.observed}) — ${c.detail}`);\n }\n if (offers.length === 0) {\n console.log(`\\n ${tool.id} — nothing to adopt.`);\n return 0;\n }\n\n console.log(`\\n ${tool.id} — ${offers.length} field(s) the backend returns and the manifest does not declare:`);\n for (const o of offers) console.log(` · ${o.path} (${o.observed}) → ${o.field}: ${o.semantic}`);\n console.log(\"\");\n\n const edits: AdoptionEdit[] = [];\n for (const o of offers) {\n if (!(await confirm(ask, ` Declare ${o.field} (${o.semantic})?`))) continue;\n const description = (await ask.question(` Describe ${o.field} — an agent reads this to decide whether to use it:\\n > `)).trim();\n if (description === \"\") {\n // D-4: a field with no description is declared but not discoverable, which is Rule #6's\n // letter against its purpose. Refusing is better than shipping a placeholder.\n console.log(` ${o.field}: no description given — not adopted.`);\n continue;\n }\n edits.push({ field: o.field, itemPath: o.itemPath, semantic: o.semantic, description });\n }\n if (edits.length === 0) {\n console.log(`\\n ${tool.id} — nothing adopted.`);\n return 0;\n }\n\n const resourceYaml = readFileSync(target.resourceFile, \"utf8\");\n const bindingYaml = readFileSync(target.bindingFile, \"utf8\");\n const applied = applyAdoption(resourceYaml, bindingYaml, edits);\n if (!applied.ok) {\n console.error(` ${tool.id}: ${applied.problem}`);\n return 1;\n }\n const rewritten = applyContractRecording(applied.binding, recording.fingerprint!, liveShape as Record<string, string>);\n if (!rewritten.ok) {\n console.error(` ${tool.id}: ${rewritten.problem}`);\n return 1;\n }\n\n const problem = compilesClean(dir, target.resourceFile, applied.resource, target.bindingFile, rewritten.binding);\n if (problem) {\n console.error(`\\n ${tool.id}: the edit does not compile — nothing written.\\n ${problem}`);\n return 1;\n }\n\n writeFileSync(target.resourceFile, applied.resource);\n writeFileSync(target.bindingFile, rewritten.binding);\n console.log(`\\n ${tool.id} — declared ${edits.map((e) => e.field).join(\", \")}; contract re-recorded.`);\n return 0;\n}\n\nexport async function runAdoptCmd(argv: string[]): Promise<number> {\n const dir = argv.find((a, i) => i > 0 && !a.startsWith(\"-\"));\n if (!dir) {\n console.error(\"usage: archstone adopt <manifest-dir>\");\n return 2;\n }\n\n const res = load(dir);\n const errors = validateSemantics(res).filter((d) => d.severity === \"error\");\n if (!res.ok || errors.length > 0) {\n console.error(`archstone adopt ${dir}: manifest invalid — run 'archstone apply ${dir}' for details`);\n return 2;\n }\n\n const registry = new Registry(compile(res));\n const targets = registry.listCapabilities().filter((t) => t.contract);\n if (targets.length === 0) {\n console.log(`\\narchstone adopt ${dir}\\n\\n (no bindings declare a contract: — nothing to probe)\\n`);\n return 0;\n }\n\n console.log(`\\narchstone adopt ${dir}`);\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n const ask = terminalAsk(rl);\n let worst = 0;\n try {\n for (const tool of targets) {\n const located = locateFiles(dir, tool);\n if (\"problem\" in located) {\n console.error(` ${located.problem}`);\n worst = Math.max(worst, 1);\n continue;\n }\n worst = Math.max(worst, await adoptOne(dir, located, tool.contract!.shape, ask));\n }\n } catch (err) {\n // `terminalAsk` throws when stdin ends with a question pending — the piped/CI case. Nothing\n // has been written by then: every write happens after the last prompt for that capability.\n console.error(`\\narchstone adopt: no more input — nothing written. Adoption needs a person (${(err as Error).name}).`);\n return 1;\n } finally {\n rl.close();\n }\n console.log(\"\");\n return worst;\n}\n","// @archstone/cli — the surgical half of `archstone adopt` (ADD-117).\n//\n// These manifests are REVIEW SURFACES a human owns, and their comments were written by that\n// human. A YAML library would re-emit them and lose every one — trading the reviewability the\n// product sells for the convenience of the tool that sells it. So this appends text to two\n// known blocks and touches nothing else, byte for byte.\n//\n// Correctness is not argued from the edit; it is PROVED after it. The caller runs the real\n// loader, compiler and probe over the result and keeps nothing if any of them fails, exactly as\n// `init` already works. The blast radius of a bug in here is a refused run.\n\nimport { yamlKey, yamlScalar } from \"@archstone/init\";\nimport type { SemanticType } from \"@archstone/compiler\";\n\nexport interface AdoptionEdit {\n /** The resource field name, e.g. `boardType`. */\n field: string;\n /** The JSONPath written into the binding's `response.map`, relative to a collection item. */\n itemPath: string;\n semantic: SemanticType;\n /** Typed by a human at the gate — never generated (ADD-117 D-4). */\n description: string;\n}\n\nexport type ApplyResult = { ok: true; resource: string; binding: string } | { ok: false; problem: string };\n\n/** One document in, one document out — `applyAdoption`'s two-file result would leave a caller\n * holding an empty `resource` that means nothing. */\nexport type RewriteResult = { ok: true; binding: string } | { ok: false; problem: string };\n\n/** A located block: where its body ends, and the indent its children sit at. */\ninterface Block {\n /** Index of the first line AFTER the block's body — where an append goes. */\n end: number;\n /** The exact leading whitespace a child of this block carries. */\n indent: string;\n}\n\nfunction indentOf(line: string): number {\n return line.length - line.trimStart().length;\n}\n\n/**\n * Locate `key:` as a block header within `[from, to)`, and find where its body ends.\n *\n * REFUSES on anything but exactly one match. Appending to the first of two `map:` blocks\n * would corrupt a manifest in a way that still parses — the failure mode this whole module is\n * built to avoid — so ambiguity is an error, never a choice.\n */\nfunction locate(lines: string[], from: number, to: number, key: string): Block | { problem: string } {\n const header = new RegExp(`^(\\\\s*)${key.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")}:\\\\s*(#.*)?$`);\n const hits: number[] = [];\n for (let i = from; i < to; i++) if (header.test(lines[i])) hits.push(i);\n if (hits.length === 0) return { problem: `could not find a '${key}:' block to append to` };\n if (hits.length > 1) return { problem: `found ${hits.length} '${key}:' blocks; refusing to guess which one to extend` };\n\n const start = hits[0];\n const own = indentOf(lines[start]);\n let end = to;\n for (let i = start + 1; i < to; i++) {\n if (lines[i].trim() === \"\") continue;\n if (indentOf(lines[i]) <= own) {\n end = i;\n break;\n }\n }\n // Back off over trailing blank lines so the append lands inside the block, not after the gap\n // that separates it from whatever follows.\n while (end > start + 1 && lines[end - 1].trim() === \"\") end--;\n\n // Children set the indent; an empty block falls back to the convention every manifest uses.\n let indent = \" \".repeat(own + 2);\n for (let i = start + 1; i < end; i++) {\n if (lines[i].trim() === \"\") continue;\n indent = lines[i].slice(0, indentOf(lines[i]));\n break;\n }\n return { end, indent };\n}\n\nfunction nest(lines: string[], path: string[]): Block | { problem: string } {\n let from = 0;\n let to = lines.length;\n let block: Block | { problem: string } = { problem: \"empty path\" };\n for (const key of path) {\n block = locate(lines, from, to, key);\n if (\"problem\" in block) return block;\n // Descend: the next key must live inside this block's body.\n to = block.end;\n for (let i = from; i < to; i++) {\n const header = new RegExp(`^\\\\s*${key}:\\\\s*(#.*)?$`);\n if (header.test(lines[i])) {\n from = i + 1;\n break;\n }\n }\n }\n return block;\n}\n\nfunction insert(lines: string[], at: number, added: string[]): string[] {\n return [...lines.slice(0, at), ...added, ...lines.slice(at)];\n}\n\n/**\n * Append adopted fields to a resource document and to a binding's response map.\n *\n * `required: false` is written unconditionally (ADD-117 D-3): one observation is not evidence\n * the provider always returns the field, and a wrongly-required field turns the next absent\n * value into a fail-closed VIOLATION on a capability that worked yesterday.\n */\nexport function applyAdoption(resourceYaml: string, bindingYaml: string, edits: AdoptionEdit[]): ApplyResult {\n if (edits.length === 0) return { ok: true, resource: resourceYaml, binding: bindingYaml };\n\n let resourceLines = resourceYaml.split(\"\\n\");\n const fields = nest(resourceLines, [\"resource\", \"fields\"]);\n if (\"problem\" in fields) return { ok: false, problem: `resource: ${fields.problem}` };\n\n const added: string[] = [];\n for (const e of edits) {\n added.push(\n `${fields.indent}${yamlKey(e.field)}:`,\n `${fields.indent} type: ${yamlScalar(e.semantic)}`,\n `${fields.indent} required: false`,\n `${fields.indent} description: ${yamlScalar(e.description)}`,\n );\n }\n resourceLines = insert(resourceLines, fields.end, added);\n\n let bindingLines = bindingYaml.split(\"\\n\");\n const map = nest(bindingLines, [\"binding\", \"response\", \"map\"]);\n if (\"problem\" in map) return { ok: false, problem: `binding: ${map.problem}` };\n bindingLines = insert(\n bindingLines,\n map.end,\n edits.map((e) => `${map.indent}${yamlKey(e.field)}: ${yamlScalar(e.itemPath)}`),\n );\n\n return { ok: true, resource: resourceLines.join(\"\\n\"), binding: bindingLines.join(\"\\n\") };\n}\n\n/**\n * Replace a binding's recorded `fingerprint` and `shape` with a fresh recording.\n *\n * Same surgical posture as `applyAdoption`: these two values are the only ones in the file\n * written by machine rather than by a human, so they are the only ones rewritten. `verifiedAt`\n * is left alone — it is the human-meaningful \"when did we last check\", and `recordContract`\n * already owns stamping it through `init`.\n *\n * Both values come from ONE response (ADD-117 R-4). Recording them from a second probe would\n * let a backend that changed between the two produce a contract describing neither.\n */\nexport function applyContractRecording(bindingYaml: string, fingerprint: string, shape: Record<string, string>): RewriteResult {\n const lines = bindingYaml.split(\"\\n\");\n const fpIdx = lines.findIndex((l) => /^\\s*fingerprint:\\s/.test(l));\n if (fpIdx === -1) return { ok: false, problem: \"binding: no contract fingerprint to update\" };\n\n const indent = lines[fpIdx].slice(0, indentOf(lines[fpIdx]));\n const rendered = [\n `${indent}fingerprint: ${yamlScalar(fingerprint)}`,\n `${indent}shape:`,\n // Sorted, so re-adopting against an unchanged backend is a no-op diff rather than a\n // reshuffle a reviewer has to read.\n ...Object.keys(shape)\n .sort()\n .map((k) => `${indent} ${yamlKey(k)}: ${yamlScalar(shape[k])}`),\n ];\n\n // Drop the previous `shape:` block if there is one, so re-adoption replaces rather than\n // accumulates. Its body is every following line indented deeper than the header.\n const removeFrom = fpIdx;\n let removeTo = fpIdx + 1;\n const shapeIdx = lines.findIndex((l, i) => i > fpIdx && /^\\s*shape:\\s*$/.test(l));\n if (shapeIdx !== -1 && lines.slice(fpIdx + 1, shapeIdx).every((l) => l.trim() === \"\" || l.trim().startsWith(\"#\"))) {\n removeTo = shapeIdx + 1;\n const own = indentOf(lines[shapeIdx]);\n while (removeTo < lines.length && (lines[removeTo].trim() === \"\" || indentOf(lines[removeTo]) > own)) removeTo++;\n // Keep any comment lines that sat between the fingerprint and the shape header.\n const preserved = lines.slice(fpIdx + 1, shapeIdx);\n return {\n ok: true,\n binding: [...lines.slice(0, removeFrom), rendered[0], ...preserved, ...rendered.slice(1), ...lines.slice(removeTo)].join(\"\\n\"),\n };\n }\n\n return { ok: true, binding: [...lines.slice(0, fpIdx), ...rendered, ...lines.slice(fpIdx + 1)].join(\"\\n\") };\n}\n"],"mappings":"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","names":["writeFileSync","resolve","load","validateSemantics","compile","Registry","index","candidate","prefill","flag","parsed","readFileSync","readFileSync","readFileSync","existsSync","join","formatReport","readFileSync","writeFileSync","join","resolve","createInterface","join","readFileSync","resolve","confirm","writeFileSync","createInterface","load","validateSemantics","Registry","compile","resolve","writeFileSync","formatReport"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/init.ts","../src/audit-cmd.ts","../src/audit-report.ts","../src/doctor.ts","../src/adopt.ts","../src/adopt-edit.ts"],"sourcesContent":["#!/usr/bin/env node\n// @archstone/cli — `archstone apply` (#1) + `archstone serve` (#7, + `--http` ADD-0008 #29)\n// + `archstone verify` (#18-20) + `archstone build` (ADD-0008 #27)\n//\n// apply: parse → shape-validate (#2) → semantic-validate (#3) → compile IR (#4)\n// → index Registry (#5), and REPORT (human output, exits).\n// serve: build the registry and expose it as an MCP server over stdio (#7),\n// so Claude/Cursor/ChatGPT can discover and invoke the tools. Blocks.\n// serve --http: same registry, served over real Streamable-HTTP instead of stdio —\n// `@archstone/runtime/http`'s createHttpHandler (Web-standard Request/Response,\n// bearer-token gated, shared with @archstone/agent/mcp's mcpHandler(), ADD-0008 D-3)\n// behind a thin Node-http adapter. Blocks.\n// verify: replay each bound capability's golden fixture against the LIVE backend\n// and report a per-binding health status (ADD-18). The only command that\n// makes a network call outside a real MCP invocation — on demand, never\n// scheduled by Archstone itself (wire it into your own CI/cron). A replay IS an\n// invocation, so a `write`/`irreversible` binding is skipped by default and\n// re-included only by `--sandbox`, an assertion the operator makes (#124).\n// build: run the same compile pipeline as `apply`, strip each tool's `contract`\n// (D-8 — the fingerprint/golden-fixture path is meaningless once the fixture\n// file isn't shipping), and write the IR as a standalone JSON artifact —\n// the substrate `@archstone/agent`'s `fromIR()` will consume (RFC-0008).\n// init: read an existing API description, ask the human the questions no tool can answer\n// (is this a capability? is it `read`? what is it called?), and write a CDL manifest\n// the real compiler has already compiled (ADD-37). Thin by design — argv, the terminal\n// gate and report rendering only; everything of substance is in @archstone/init.\n\nimport { writeFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { createRequire } from \"node:module\";\nimport { createServer, type IncomingMessage, type ServerResponse } from \"node:http\";\nimport { load } from \"@archstone/schema\";\nimport { validateSemantics, compile, type IR } from \"@archstone/compiler\";\nimport { Registry, buildRegistry, serveStdio, runVerify, type HealthStatus } from \"@archstone/runtime\";\nimport { createHttpHandler } from \"@archstone/runtime/http\";\nimport { INIT_USAGE, runInitCmd } from \"./init\";\nimport { runAuditCmd } from \"./audit-cmd\";\nimport { diagnose, formatReport } from \"./doctor\";\nimport { runAdoptCmd } from \"./adopt\";\n\n/** `archstone --version` is the first thing a human types after installing, and until this\n * existed it printed the usage block and exited 2 — which reads as \"broken install\" at the\n * exact moment a new user is deciding whether this thing works.\n *\n * `../package.json` resolves correctly from BOTH layouts without a build step knowing about\n * it: in dev the entry is `src/index.ts`, and when published it is `dist/index.js` — both sit\n * one level under the package root. npm always ships `package.json` regardless of the `files`\n * allowlist, so the published resolution cannot break. */\nfunction cliVersion(): string {\n try {\n return (createRequire(import.meta.url)(\"../package.json\") as { version?: string }).version ?? \"unknown\";\n } catch {\n // Never let a version lookup be the thing that stops the CLI from running.\n return \"unknown\";\n }\n}\n\n/** One spelling of the usage block, shared by `--help` (stdout, exit 0 — the user asked) and by\n * the no-verb-matched fallthrough (stderr, exit 2 — the user got it wrong). Which stream and\n * which exit code is the ONLY difference between those two cases, and keeping the text in one\n * place is what stops them drifting. */\nfunction printUsage(opts?: { toStderr?: boolean }): void {\n const write = opts?.toStderr ? console.error : console.log;\n write(\n // `init` is named HERE, in the verb list, and not only in the block below it. It takes a\n // spec file rather than a manifest directory, so it cannot share the first line's shape —\n // which is exactly how it came to be missing from the one line a user actually scans.\n \"usage: archstone <apply|serve|verify|build|doctor|init|adopt|audit>\\n\\n\" +\n \" archstone <apply|serve|verify|build> <manifest-dir> [--json] [--out path]\\n\" +\n \" archstone verify <manifest-dir> [--json] [--sandbox]\\n\" +\n \" --sandbox: also replay `write`/`irreversible` fixtures — they are skipped by default,\\n\" +\n \" because a replay is a real invocation. Only for a backend you know is a sandbox tenant.\\n\" +\n \" archstone serve --http <manifest-dir> [--port <n>] [--token <value>]\\n\" +\n \" bearer token: --token <value>, or the ARCHSTONE_HTTP_TOKEN env var (required — never serves open)\\n\" +\n \" archstone doctor <manifest-dir> [--json] — pre-production checks, offline\\n\" +\n \" archstone init <spec-file> --out <dir> — start here if you have no manifest yet\\n\" +\n \" archstone adopt <manifest-dir>\\n\" +\n \" declare a field the backend started returning; asks before writing, needs a person\\n\\n\" +\n \" archstone audit <file...> [--since <date>] [--format summary|jsonl|csv]\\n\" +\n \" read your own Execution audit records; nothing is uploaded (audit --help for filters)\\n\\n\" +\n \" archstone --version | --help\\n\\n\" +\n INIT_USAGE,\n );\n}\n\nfunction runApply(dir: string): void {\n const res = load(dir);\n console.log(`\\narchstone apply ${dir}\\n`);\n\n if (res.capabilities) {\n const c = res.capabilities;\n console.log(` company ${c.company.name ?? c.company.id} (${c.company.id})`);\n console.log(` providers ${c.providers.join(\", \")}`);\n console.log(` declared ${c.capabilities.length} capabilities`);\n }\n console.log(` loaded ${res.capabilityDocs.length} capability docs, ${res.bindings.length} bindings`);\n for (const d of res.capabilityDocs) {\n console.log(` ✓ ${d.capability.id} [${d.capability.effect}] → ${d.capability.provider ?? \"?\"}`);\n }\n // #43: a policy the author believes is enforced must never be invisible here — the whole\n // point of the semantic pass's scope diagnostics is that \"attached to nothing\" is loud.\n if (res.policyDocs.length > 0) {\n console.log(` policies ${res.policyDocs.length} policy document(s)`);\n for (const p of res.policyDocs) {\n const target =\n p.metadata.scope === \"capability\"\n ? `capability ${p.metadata.capabilityId ?? \"?\"}`\n : p.metadata.scope === \"provider\"\n ? `provider ${p.metadata.provider ?? \"?\"}`\n : \"(no scope)\";\n console.log(` ✓ ${p.metadata.id} → ${target}`);\n }\n }\n\n // Shape (schema) issues from #2 — \"valid shapes\" is not \"deployable\".\n if (res.issues.length > 0) {\n console.log(`\\n ✗ ${res.issues.length} shape issue(s):`);\n for (const i of res.issues) console.log(` - ${i.file}: ${i.message}`);\n } else {\n console.log(`\\n ✓ shapes valid`);\n }\n\n // Semantic pass (#3) — cross-file resolution; errors block, warnings inform.\n const diags = validateSemantics(res);\n const errors = diags.filter((d) => d.severity === \"error\");\n const warnings = diags.filter((d) => d.severity === \"warning\");\n console.log(` semantic ${errors.length} error(s), ${warnings.length} warning(s)`);\n for (const d of errors) console.log(` ✗ ${d.message}`);\n for (const d of warnings) console.log(` ⚠ ${d.message}`);\n\n const shapesAndSemanticsOk = res.ok && errors.length === 0;\n\n // Compile to IR (#4) + index into the Registry (#5) — only when valid enough to emit.\n // ADD-30: a tool-name collision (two capability ids sanitizing to the same advertised\n // name) is checked here, before the final `ok`, alongside the semantic errors above —\n // 'apply' must refuse the same manifest 'build'/'serve' would refuse (D-2).\n const registry = shapesAndSemanticsOk ? new Registry(compile(res)) : undefined;\n const collisions = registry?.toolNameCollisions ?? [];\n if (collisions.length > 0) {\n console.log(`\\n ✗ ${collisions.length} tool-name collision(s):`);\n for (const c of collisions) {\n console.log(` - tool name '${c.name}' is ambiguous — capabilities ${c.ids.join(\", \")} all sanitize to it`);\n }\n }\n\n const ok = shapesAndSemanticsOk && collisions.length === 0;\n\n if (ok && registry) {\n const invocable = registry.listCapabilities().filter((t) => t.connector).length;\n console.log(` registry IR v${registry.ir.version} — ${registry.size} capabilities, ${invocable} invocable (bound)`);\n console.log(`\\n → run 'archstone serve ${dir}' to expose ${invocable} tool(s) to an AI agent over MCP`);\n }\n\n console.log(\"\");\n process.exit(ok ? 0 : 1);\n}\n\nfunction runBuild(dir: string, outPath: string | undefined): void {\n const res = load(dir);\n const diags = validateSemantics(res);\n const errors = diags.filter((d) => d.severity === \"error\");\n const ok = res.ok && errors.length === 0;\n\n if (!ok) {\n console.error(`archstone build ${dir}: manifest invalid — run 'archstone apply ${dir}' for details`);\n for (const i of res.issues) console.error(` - ${i.file}: ${i.message}`);\n for (const d of errors) console.error(` - ${d.message}`);\n process.exit(1);\n }\n\n const ir = compile(res);\n\n // ADD-30 R-2: `runBuild` didn't construct a Registry at all, so it could ship a broken\n // artifact whose ambiguous tool name only surfaces later, inside a third party's\n // `fromIR()` call. Refuse to write on a collision — fail at `build` time instead\n // (the same \"ambiguous is a compile-time error, never a guess\" pattern this repo already\n // applies to resource-name resolution, compiler/src/resolve.ts).\n const registry = new Registry(ir);\n if (registry.toolNameCollisions.length > 0) {\n console.error(`archstone build ${dir}: refusing to write artifact — tool-name collision(s):`);\n for (const c of registry.toolNameCollisions) {\n console.error(` - tool name '${c.name}' is ambiguous — capabilities ${c.ids.join(\", \")} all sanitize to it`);\n }\n process.exit(1);\n }\n\n // THE STRIP RULE, stated as a principle rather than a list (ADD-43 D-9), so the next field\n // added to `IRTool` is classified deliberately instead of by whichever example was copied:\n //\n // strip what the INVOCATION PATH cannot use.\n //\n // `contract` qualifies (ADD-0008 D-8): it is verify-time-only and carries an fs path that is\n // meaningless once the golden fixture is not shipping alongside the artifact.\n //\n // `policyRules` (#43) is the exact opposite and MUST survive: it is invocation-path data, read\n // by the evaluator on every `execute()` call. Stripping it would ship an unpoliced embedded\n // SDK beside a policed MCP surface — the precise cross-path drift #43 exists to prevent, and\n // silent, because `fromIR` validates only `version` and treats the rest as opaque.\n const stripped: IR = { ...ir, tools: ir.tools.map(({ contract: _contract, ...t }) => t) };\n\n const outFile = resolve(process.cwd(), outPath ?? \"archstone.ir.json\");\n writeFileSync(outFile, `${JSON.stringify(stripped, null, 2)}\\n`);\n console.log(`archstone build ${dir} → ${outFile} (${stripped.tools.length} tool(s))`);\n process.exit(0);\n}\n\nfunction runServeHttp(dir: string, port: number, token: string | undefined): void {\n // Rule #7 / ADD-0008 R-5: fail closed before touching the network — a missing token is a\n // startup error, never a silently-open endpoint. `--token` wins over the env var if both\n // are set; createHttpHandler itself would also throw on empty, but checking here first\n // gives a CLI-appropriate error message instead of an uncaught exception.\n if (!token) {\n console.error(\n \"archstone serve --http: bearer token required — set ARCHSTONE_HTTP_TOKEN or pass --token <value>\",\n );\n process.exit(1);\n }\n\n const built = buildRegistry(dir);\n if (!built.ok || !built.registry) {\n console.error(`archstone: cannot serve '${dir}' — manifest invalid:`);\n for (const i of built.issues) console.error(` - ${i.file}: ${i.message}`);\n for (const d of built.diagnostics.filter((x) => x.severity === \"error\")) console.error(` - ${d.message}`);\n process.exit(1);\n }\n\n const handler = createHttpHandler(built.registry, { bearerToken: token });\n const server = createServer((req, res) => {\n // #49 belt-and-braces: this used to be `void handleHttpRequest(...)`. Fire-and-forget\n // means nothing is attached to the returned promise, so ANY rejection escaping the\n // function became an unhandled rejection — fatal under Node's default\n // `--unhandled-rejections=throw`, killing the server on one aborted client connection.\n // handleHttpRequest now contains its own failures, but this `.catch` is the seam that\n // makes the fix independent of that catch staying exhaustive: a future throw added\n // outside its `try` cannot resurrect the process-death bug.\n handleHttpRequest(handler, req, res).catch((err: unknown) => {\n console.error(\"archstone serve --http: request handling failed —\", err);\n endResponseQuietly(res, 500);\n });\n });\n server.listen(port, () => {\n console.error(`archstone: serving MCP over HTTP on http://localhost:${port}/ (bearer-token gated)`);\n });\n}\n\n/**\n * Largest request body `archstone serve --http` will buffer, in bytes (#50).\n *\n * 4 MiB is not chosen by feel: it is the limit the MCP SDK itself applies to an MCP message\n * arriving over HTTP (`MAXIMUM_MESSAGE_SIZE = '4mb'` in the SDK's own Node SSE transport,\n * enforced via `raw-body`). Same protocol, same message class, same SDK version this package\n * already depends on — so the ceiling matches what an MCP client can reasonably expect to send\n * anywhere else in the ecosystem, rather than inventing an Archstone-specific number. The\n * Web-standard transport used here never reads the socket itself (this adapter hands it an\n * already-built `Request`), which is precisely why the SDK's limit does not apply on this path\n * and has to be reapplied here.\n *\n * For scale: an MCP `tools/call` body carries a capability's declared inputs as JSON. 4 MiB is\n * orders of magnitude above any manifest in `examples/`.\n */\nconst MAX_REQUEST_BODY_BYTES = 4 * 1024 * 1024;\n\n/**\n * Bounds on the \"lingering close\" that `refuseOversizedBody` performs: how many bytes of an\n * already-refused body are read and thrown away, and how long the socket is kept around, before\n * the client is cut off for good.\n *\n * Both exist to bound a courtesy, not a capability. Nothing here is ever buffered — the bytes\n * are discarded as they arrive and `chunks` is emptied the moment the cap trips — so the\n * allocation bound #50 established is untouched. What is being spent is socket time on a client\n * that already misbehaved, so it is capped rather than run to completion.\n */\nconst MAX_REFUSED_BODY_DRAIN_BYTES = 64 * 1024 * 1024;\nconst REFUSED_BODY_LINGER_MS = 5_000;\n\n/**\n * Refuse an oversized body with a 413 the client will actually receive, then let go of the\n * socket.\n *\n * Refusing turned out not to be the same as being heard. Ending the response the ordinary way\n * sets `Connection: close`, and Node then calls `destroySoon()` as soon as the response has\n * flushed — without waiting on the read side. The client is still mid-upload, so megabytes of\n * its body are sitting unread in this process's receive buffer, and a socket closed with unread\n * data does not send FIN, it sends RST. An RST makes the peer's stack DISCARD whatever is\n * already in its own receive buffer — the just-delivered 413 included. Measured against the\n * real CLI: 7 of 25 chunked oversize uploads ended in ECONNRESET/EPIPE with the response\n * destroyed in flight, and the rate climbed with machine load. The caller could not tell \"your\n * body is too large\" apart from \"the server fell over\" (measured 2026-08-26).\n *\n * Draining the body before closing is the obvious repair and it is not enough: under load the\n * event loop drains slower than the client fills, so the buffer is still dirty at close. It cut\n * the loss from 7/25 to 3/40 idle, and it was still 8/40 at load average 44.\n *\n * What is sufficient is to never call close() with the read side dirty. So the socket is taken\n * over from the response, the 413 is written by hand, and `socket.end()` issues a bare\n * shutdown(WR): the response and the FIN leave together, the read side stays open, and no RST\n * is ever generated. The remaining upload is then read and dropped until the client gives up,\n * the byte budget is spent, or the linger expires. This is nginx's `lingering_close`, and it is\n * why the caller may go on streaming without ever costing this process memory. Measured on the\n * same machine at load average 44: 60 of 60 uploads received their 413, including the\n * pathological client that never stops writing and never terminates its chunked body.\n *\n * Both refusal paths use this — the streaming guard and the declared-Content-Length fast path.\n * The fast path still decides on the header alone, before reading a byte; lingering afterwards\n * does not change what the decision was made from, only whether the caller gets to hear it.\n *\n * What this does NOT add is a cap on how many sockets may be lingering at once. Stated out\n * loud rather than left implicit, because #49/#50 treated this file's unauthenticated surface\n * carefully: a flood can now hold a refused connection for up to the bounds above where it\n * used to be dropped near-instantly. The exposure is file descriptors and time, never memory,\n * and it is what buys a caller the ability to learn why it was refused. If a global cap is\n * ever wanted it belongs at the server, alongside `maxConnections`, not here.\n *\n * Writing the status line by hand is deliberate. `res.detachSocket()` is the supported way to\n * take a socket out of Node's response machinery (it is what an HTTP upgrade does), and once\n * detached the ServerResponse must not be used — it no longer owns anything to write through.\n */\nfunction refuseOversizedBody(res: ServerResponse): void {\n const socket = res.socket;\n // No socket to linger on, or the response is already committed: fall back to the ordinary\n // ending. It may be lost to an RST, which is strictly better than throwing from here (#49).\n if (!socket || res.headersSent || res.writableEnded || res.destroyed || socket.destroyed) {\n endResponseQuietly(res, 413, { closeConnection: true });\n return;\n }\n try {\n res.detachSocket(socket);\n // No `Date`, which Node's ServerResponse would have added. Deliberate, and the only header\n // that differs from the old path: RFC 9110 recommends rather than requires it, and this\n // connection closes immediately, so nothing downstream can cache or age the response.\n socket.write(\"HTTP/1.1 413 Payload Too Large\\r\\nConnection: close\\r\\nContent-Length: 0\\r\\n\\r\\n\");\n socket.end(); // shutdown(WR) only — the read side deliberately stays open.\n\n let discarded = 0;\n socket.on(\"data\", (chunk: Buffer) => {\n discarded += chunk.length;\n if (discarded > MAX_REFUSED_BODY_DRAIN_BYTES) socket.destroy();\n });\n socket.resume();\n // Client faults are never logged (#49 BF-1) and a dead peer must not leak a socket, so the\n // two remaining exits are silent: the budget above, and this deadline.\n socket.on(\"error\", () => socket.destroy());\n const linger = setTimeout(() => socket.destroy(), REFUSED_BODY_LINGER_MS);\n linger.unref();\n socket.on(\"close\", () => clearTimeout(linger));\n } catch {\n // The socket went away between the guard above and the write. Nothing to say, no one to\n // say it to — same contract as endResponseQuietly.\n try {\n socket.destroy();\n } catch {\n /* already gone */\n }\n }\n}\n\n/**\n * Terminate a response without ever throwing (#49). Every exit path out of the adapter goes\n * through here, including the ones reached after the client is already gone: on an aborted\n * connection the socket is destroyed, and a naive `res.end()` there is at best pointless and\n * at worst a second error thrown out of an error path. Ending is still attempted whenever the\n * socket survives — a truncated body on a keep-alive connection has a live socket that would\n * otherwise hang until the client's own timeout.\n */\nfunction endResponseQuietly(\n res: ServerResponse,\n status: number,\n opts: { closeConnection?: boolean } = {},\n): void {\n try {\n if (res.writableEnded || res.destroyed) return;\n if (!res.headersSent) {\n res.statusCode = status;\n // #50: on a refused oversized body the connection must not be reused. The client is\n // mid-upload and the rest of its bytes are still in flight, so a keep-alive socket\n // would leave that remainder to be misparsed as the next request. `Connection: close`\n // lets Node flush the response first and then close — destroying the socket here\n // instead would race the 413 and the client would see nothing.\n if (opts.closeConnection) res.setHeader(\"connection\", \"close\");\n }\n res.end();\n } catch {\n // The socket went away between the checks above and the write. Nothing is left to\n // terminate and there is no one to tell — swallowing here is the whole point.\n }\n}\n\n// D-3's \"~20-line wrapper\": Node's http.IncomingMessage/ServerResponse <-> Web-standard\n// Request/Response, so createHttpHandler (already Web-standard, shared with\n// @archstone/agent/mcp's mcpHandler()) can serve real Node HTTP traffic without a second\n// transport implementation. CLI-level plumbing only — HTTP itself still lives in\n// providers/rest for business-backend calls; this adapter never touches a backend.\n//\n// #49 (P0, unauthenticated remote DoS): this function must never reject and must always\n// reach a terminal `res.end()`. It is invoked from a Node `request` listener, where an\n// escaping rejection is an unhandled rejection and therefore a fatal uncaught exception —\n// one client that declares a Content-Length and disconnects mid-body used to kill the\n// process, before any handler and therefore before any credential check ran.\nasync function handleHttpRequest(\n handler: (request: Request) => Promise<Response>,\n req: IncomingMessage,\n res: ServerResponse,\n): Promise<void> {\n // #50: the body is buffered BEFORE authentication (the bearer check lives inside\n // createHttpHandler, reached only once the Request is built), so an unauthenticated client\n // controls how much memory this allocates. Measured server-side: the body is held ~4x over\n // simultaneously — the chunk array, `Buffer.concat`'s copy, and undici's own copies inside\n // `new Request` — so a 256 MiB body peaked at 1,081 MiB RSS, essentially all of it in\n // `external`/`arrayBuffers`. Being external is what makes it nasty: `--max-old-space-size`\n // does not bound it, and the terminal symptom is an uncatchable OOM abort.\n //\n // A declared Content-Length over the cap is refused before a single byte is read; the\n // running total is then enforced during streaming as well, because Content-Length can lie\n // and chunked encoding omits it entirely. Like every other client fault in this adapter the\n // 413 is NOT logged — an unauthenticated caller must not be able to drive log volume (#49\n // BF-1).\n const declared = Number(req.headers[\"content-length\"]);\n if (Number.isFinite(declared) && declared > MAX_REQUEST_BODY_BYTES) {\n // Refused on the header, without reading a byte — then handed to the same lingering close\n // as the streaming guard below. Which bytes the SERVER chose to read is not what decides\n // whether the 413 survives: the RST is triggered by bytes sitting unread in the KERNEL\n // receive buffer when the write side closes, and a client that declares N and then sends N\n // — i.e. every real HTTP library — puts them there whether or not this function ever\n // looked. Measured on a warm server: 18/25 of these lost their 413 before this line\n // changed. (A fresh server loses none, which is why the test suite never caught it.)\n refuseOversizedBody(res);\n return;\n }\n\n const chunks: Buffer[] = [];\n // #134: this used to be `for await (const chunk of req)`, with the cap check inside the\n // loop body returning (and, for the aborted case, throwing out of the loop) to bail early.\n // Both a `break`/`return` and a `throw` out of a `for await...of` make the language runtime\n // call the async iterator's `return()` — which for a Node Readable, `req` included, destroys\n // the stream (documented Node behaviour, not a bug in the runtime). The comment that used to\n // sit here reasoned that this was harmless because `refuseOversizedBody` had already taken\n // `res`'s socket out of the response via `detachSocket()` — but `detachSocket` only unlinks\n // the RESPONSE's bookkeeping. `req.socket` is a separate live reference to the same shared\n // socket, and `IncomingMessage`'s own `_destroy` (run when the stream is torn down before\n // `end`) reaches through THAT reference and calls `this.socket.destroy(err)` — an immediate,\n // ungraceful close that can RST the connection out from under the 413 `refuseOversizedBody`\n // just wrote via a deliberate half-close (`socket.end()`, not `.destroy()`). Both closes are\n // scheduled back-to-back on the event loop, so which one actually reaches the kernel first —\n // whether the graceful FIN carrying the response, or the abort's hard RST — depends on\n // scheduling, which is exactly why this only ever showed up intermittently under real CPU\n // load and never in an isolated, idle run.\n //\n // Only the streaming guard (chunked framing, no declared Content-Length) can hit this: the\n // declared-oversize fast path above returns before `req` is ever iterated.\n //\n // The fix is to never let the runtime call `req`'s async-iterator `return()` in the first\n // place. Plain event listeners carry no such implicit-destroy contract — removing them is\n // just bookkeeping, not a stream teardown — so the accumulation below drives `req` by hand\n // instead of `for await`.\n const body = await new Promise<\"ok\" | \"aborted\" | \"oversized\">((settle) => {\n let received = 0;\n let done = false;\n const finish = (outcome: \"ok\" | \"aborted\" | \"oversized\"): void => {\n if (done) return;\n done = true;\n req.off(\"data\", onData);\n req.off(\"end\", onEnd);\n req.off(\"error\", onError);\n req.off(\"close\", onClose);\n settle(outcome);\n };\n const onData = (chunk: Buffer): void => {\n received += chunk.length;\n if (received > MAX_REQUEST_BODY_BYTES) {\n // Nothing downstream will ever read these; drop them before handing the socket over.\n chunks.length = 0;\n finish(\"oversized\");\n return;\n }\n chunks.push(chunk);\n };\n const onEnd = (): void => finish(\"ok\");\n // Registered synchronously alongside `onData`/`onEnd`, so `req` never has a tick without an\n // 'error' listener attached — an unlistened 'error' event throws and is exactly the #49\n // failure mode (an escaping exception fatal under Node's default unhandled-rejection/\n // exception handling) this adapter exists to prevent.\n const onError = (): void => finish(\"aborted\");\n // Belt-and-braces, not part of #134's reported failure: every abrupt-disconnect path this\n // adapter has actually observed also fires 'error' (ECONNRESET) on `req`, so `onClose` alone\n // would be redundant with it in practice. It exists so that if some Node-internal close ever\n // reached `req` without an 'error' first, this settles as \"aborted\" (400, unlogged) instead\n // of leaving the promise — and the request — hanging forever.\n const onClose = (): void => finish(\"aborted\");\n req.on(\"data\", onData);\n req.on(\"end\", onEnd);\n req.on(\"error\", onError);\n req.on(\"close\", onClose);\n });\n\n if (body === \"oversized\") {\n // Takes the socket out of `res` and answers on it directly. `req` itself is left alone —\n // no destroy, no cascade — so the graceful close below is the only thing that touches the\n // socket from here on.\n refuseOversizedBody(res);\n return;\n }\n if (body === \"aborted\") {\n // The client went away mid-body (ECONNRESET / aborted), or delivered fewer bytes than\n // its declared Content-Length. On a public endpoint this is routine traffic — a closed\n // laptop, a cancelled fetch, a load-balancer health probe — NOT a server fault, so it is\n // deliberately not logged: turning an aborted-request flood into a log flood just trades\n // one denial of service for another.\n //\n // 400 is the deliberate status, not 500: the request was never completed, and nothing on\n // the server failed. In practice nobody reads it — this arm is reached only once the\n // socket is already dead. (Node does NOT surface a short body while the connection is\n // still open: it waits for the declared bytes until `server.requestTimeout`, 300 s by\n // default, and answers that itself.) The end is still attempted rather than skipped\n // because this code cannot tell from here whether `res` is writable — `req` erroring\n // does not by itself prove the response side is gone — and `endResponseQuietly` makes\n // the attempt free when it is.\n endResponseQuietly(res, 400);\n return;\n }\n\n // Translating the raw request into a Web `Request` is still CLIENT input handling, and it\n // runs BEFORE authentication (the bearer check lives inside createHttpHandler, reached only\n // at `handler(request)` below). `req.headers.host` and `req.url` are attacker-controlled and\n // a malformed value throws here — a bad `Host` was in fact a second unauthenticated kill\n // vector before #49's containment landed. So this gets its own client-fault arm, on exactly\n // the argument the body-read catch above makes: answering 500 and logging a stack trace per\n // request would hand an unauthenticated caller ~13x log amplification and trade the crash\n // for a disk-fill DoS. RFC 9112 §3.2 also makes 400 the required answer to an invalid Host.\n //\n // Classification is positional, not by error sniffing: what failed decides the class, so it\n // cannot drift when undici changes an error's shape between Node versions.\n let request: Request;\n try {\n const headers = new Headers();\n for (const [key, value] of Object.entries(req.headers)) {\n if (value !== undefined) headers.set(key, Array.isArray(value) ? value.join(\", \") : value);\n }\n const hasBody = req.method !== \"GET\" && req.method !== \"HEAD\" && chunks.length > 0;\n request = new Request(`http://${req.headers.host ?? \"localhost\"}${req.url ?? \"/\"}`, {\n method: req.method ?? \"GET\",\n headers,\n body: hasBody ? Buffer.concat(chunks) : undefined,\n });\n } catch {\n endResponseQuietly(res, 400);\n return;\n }\n\n try {\n const response = await handler(request);\n res.statusCode = response.status;\n response.headers.forEach((value, key) => res.setHeader(key, value));\n res.end(response.body ? Buffer.from(await response.arrayBuffer()) : undefined);\n } catch (err) {\n // A genuine server-side failure: the handler rejected, or serialising its Response threw.\n // Unlike a malformed or abandoned request this IS worth surfacing, so it is logged — and\n // answered with a 500 rather than left to hang the caller. Nothing attacker-controlled\n // reaches this arm without first passing through the handler, so it cannot be used as a\n // log-amplification primitive the way the pre-auth construction path above could.\n console.error(\"archstone serve --http: request handling failed —\", err);\n endResponseQuietly(res, 500);\n }\n}\n\nconst HEALTH_ICON: Record<HealthStatus, string> = { green: \"🟢\", yellow: \"🟡\", red: \"🔴\" };\n\n/** #124: deliberately NOT one of `HEALTH_ICON`'s three. A skipped binding was never inspected,\n * so it must not be scannable as a colour — no colour is earned (ADD-124 D-2). */\nconst SKIP_ICON = \"⏭\";\n\n/**\n * #124 / ADD-124 D-13 — printed once, only when something was skipped, and only to a human.\n *\n * It names the PATTERN and never a capability id: nothing in CDL or the IR links a `write`\n * capability to its `read` counterpart (`examples/manifests/bank`'s\n * `initiate-transfer`/`quote-transfer` pair is naming convention, not a declared relationship),\n * so guessing one would sometimes name the wrong capability with the same confidence as the\n * right one — worse than naming none (D-11). Same hedge as `doctor.ts`'s `no-contract-non-read`\n * advisory (\"Not every write has one…\") — these two must not drift apart.\n */\nconst READ_TWIN_TIP =\n \" Where one of these has a `read` capability against the same backend — the quote half of a\\n\" +\n \" quote → commit pair — verifying that instead hits the same host, auth and serialization,\\n\" +\n \" catching most infrastructure and schema drift at zero risk. Not every write has one, and\\n\" +\n \" Archstone cannot tell you which capability it is: nothing in CDL declares that relationship.\\n\" +\n \" If this backend really is a sandbox tenant, pass --sandbox.\";\n\nasync function runVerifyCmd(dir: string, json: boolean, sandbox: boolean): Promise<void> {\n const res = load(dir);\n const diags = validateSemantics(res);\n const errors = diags.filter((d) => d.severity === \"error\");\n const ok = res.ok && errors.length === 0;\n if (!ok) {\n if (json) {\n // ADD-20 D-2: this shape is strictly disjoint from the `{results}` shape below —\n // never add a shared \"envelope\" field (e.g. `ok`) to either.\n console.log(JSON.stringify({ error: \"manifest_invalid\", issues: res.issues, errors }));\n } else {\n console.error(`archstone verify ${dir}: manifest invalid — run 'archstone apply ${dir}' for details`);\n }\n process.exit(2);\n }\n\n const registry = new Registry(compile(res));\n // Two literal call sites rather than one with a computed 5th argument (#124 / ADD-124 D-3).\n // The DEFAULT path — what CI and every non-sandbox operator runs — stays the exact\n // three-argument form the two CLI surface tests pin: no `InvokeOptions` bag at all, so no\n // audit sink and no per-response callback can reach it. The `--sandbox` path passes an\n // explicit `undefined` in that slot for the same reason, so the scope argument can never be\n // the reason such a bag starts being constructed here.\n const { results, skipped } = sandbox\n ? await runVerify(registry.listCapabilities(), dir, registry.ir.resources, undefined, { includeNonRead: true })\n : await runVerify(registry.listCapabilities(), dir, registry.ir.resources);\n\n // ADD-124 D-6: computed from `results` ONLY, exactly as before. A skip never fails the gate —\n // an all-skipped run exits 0, the same code an all-empty run already produced. Inventing a\n // failure mode for \"every write/irreversible binding correctly declined to replay itself\"\n // would punish the manifests doing the safe, default thing.\n const exitCode = results.some((r) => r.status === \"red\") ? 1 : 0;\n\n if (json) {\n // ADD-20 D-2: strictly disjoint from the `{error, issues, errors}` shape above.\n //\n // `skipped` and `sandbox` are ADDITIVE (ADD-124 D-7). A consumer filtering `results` for red\n // is unaffected: skipped bindings were never in `results` to begin with. `sandbox` records\n // HOW verify was invoked, so a dashboard can tell \"nothing dangerous was replayed\" from\n // \"everything was replayed because someone asserted a sandbox\".\n console.log(JSON.stringify({ results, skipped, sandbox }));\n process.exit(exitCode);\n }\n\n console.log(`\\narchstone verify ${dir}\\n`);\n if (results.length === 0 && skipped.length === 0) {\n console.log(\" (no bindings declare a contract: — nothing to verify)\\n\");\n process.exit(0);\n }\n for (const r of results) {\n console.log(` ${HEALTH_ICON[r.status]} ${r.capabilityId} — ${r.detail}`);\n }\n for (const s of skipped) {\n console.log(` ${SKIP_ICON} ${s.capabilityId} — ${s.detail}`);\n }\n if (skipped.length > 0) {\n console.log(`\\n ${skipped.length} binding(s) were NOT verified against the backend.`);\n console.log(READ_TWIN_TIP);\n }\n console.log(\"\");\n process.exit(exitCode);\n}\n\n/** Value of a `--name value` flag pair, plus the index it was found at (-1 if absent) —\n * used both to read the value and to exclude both tokens from the positional args. */\nfunction flagArg(argv: string[], name: string): { value?: string; idx: number } {\n const idx = argv.indexOf(name);\n return { value: idx !== -1 ? argv[idx + 1] : undefined, idx };\n}\n\n/**\n * #102 — A-7 §5's pre-production checklist, run instead of read. Offline by construction: it\n * compiles the manifest and inspects the IR plus what sits beside it on disk. Nothing is\n * invoked and no backend is contacted — that is `verify`, and this is the question you ask\n * before pointing anything at production.\n */\nfunction runDoctor(dir: string, json: boolean): void {\n const res = load(dir);\n const diags = validateSemantics(res);\n const errors = diags.filter((d) => d.severity === \"error\");\n if (!res.ok || errors.length > 0) {\n console.error(`archstone doctor ${dir}: manifest invalid — run 'archstone apply ${dir}' for details`);\n process.exit(1);\n }\n\n const ir = compile(res);\n // Compare drift against what `build` would actually write, which strips `contract` (ADD-43\n // D-9's strip rule) — comparing against the unstripped IR would report drift on every\n // manifest that records a fixture, i.e. on every well-configured one.\n const stripped: IR = { ...ir, tools: ir.tools.map(({ contract: _contract, ...t }) => t) };\n const report = diagnose(ir, dir, { builtIr: `${JSON.stringify(stripped, null, 2)}\\n` });\n\n console.log(json ? JSON.stringify(report, null, 2) : formatReport(report, dir));\n process.exit(report.ok ? 0 : 1);\n}\n\nasync function main(): Promise<void> {\n const argv = process.argv.slice(2);\n\n // Before anything else: `--version`/`-V` and `--help`/`-h` are what a human types first, and\n // both used to fall through to the usage block with exit 2 — a non-zero exit for a question\n // that was answered correctly. Both now exit 0. `-V` is capitalised because `-v` is verbose\n // by long convention and should stay free.\n if (argv.includes(\"--version\") || argv.includes(\"-V\")) {\n console.log(cliVersion());\n return;\n }\n if (argv.includes(\"--help\") || argv.includes(\"-h\")) {\n printUsage();\n return;\n }\n\n const json = argv.includes(\"--json\");\n const http = argv.includes(\"--http\");\n // #124: boolean, takes no argument. NOT `--force`/`--yes`: those read as overriding a check\n // Archstone performed, and the honest situation is the opposite — Archstone performed no check\n // and structurally cannot (`doctor`'s own `env-baseurl` advisory already concedes that the\n // deployment, not the manifest, decides where `${VAR}` points). `--sandbox` is the operator\n // supplying the one fact only they hold. It takes no target string because a target would\n // imply Archstone validates it against something, and there is nothing to validate against.\n const sandbox = argv.includes(\"--sandbox\");\n const out = flagArg(argv, \"--out\");\n const port = flagArg(argv, \"--port\");\n const token = flagArg(argv, \"--token\");\n\n const consumed = new Set<number>();\n for (const f of [out, port, token]) {\n if (f.idx !== -1) {\n consumed.add(f.idx);\n consumed.add(f.idx + 1);\n }\n }\n const positional = argv.filter((a, i) => !consumed.has(i) && a !== \"--json\" && a !== \"--http\" && a !== \"--sandbox\");\n const [cmd, dir] = positional;\n\n if (cmd === \"apply\" && dir) {\n runApply(dir);\n return;\n }\n if (cmd === \"serve\" && dir && http) {\n // Bearer token: --token wins over ARCHSTONE_HTTP_TOKEN if both are set (Rule #7 —\n // required, never defaults open).\n runServeHttp(dir, Number(port.value ?? 8787), token.value ?? process.env.ARCHSTONE_HTTP_TOKEN);\n return; // blocks on the HTTP server\n }\n if (cmd === \"serve\" && dir) {\n await serveStdio(dir); // blocks on the stdio transport\n return;\n }\n if (cmd === \"verify\" && dir) {\n await runVerifyCmd(dir, json, sandbox);\n return;\n }\n if (cmd === \"build\" && dir) {\n runBuild(dir, out.value);\n return;\n }\n if (cmd === \"doctor\" && dir) {\n runDoctor(dir, json);\n return;\n }\n if (cmd === \"adopt\") {\n // Its own parser, and its own module: it is the only verb that WRITES a manifest a human\n // already owns, so keeping it apart from the read-only verbs above is deliberate.\n process.exit(await runAdoptCmd(argv));\n }\n if (cmd === \"audit\") {\n // Own parser, for the same reason `init` has one: this verb's flags outnumber the other\n // verbs' put together, and threading them through the positional logic above would make\n // both harder to read.\n process.exit(runAuditCmd(argv));\n }\n if (cmd === \"init\") {\n // Everything `init` needs is in its own argv parser: it has more flags than the other four\n // verbs put together, and threading them through this function's positional logic would\n // make both harder to read.\n process.exit(await runInitCmd(argv));\n }\n\n printUsage({ toStderr: true });\n process.exit(2);\n}\n\nmain();\n","// `archstone init` — THIN (ADD-37 §6 step 7, D-5).\n//\n// This file owns exactly three things: argv, the terminal gate, and rendering the report.\n// Every decision of substance lives elsewhere and is testable without a terminal:\n// - what a document says → `@archstone/init`'s adapters\n// - what becomes a manifest → `emit`, pure\n// - whether anything is written → `@archstone/init/loop`, one of two terminal states\n// - whether a request is ever made → the probe gate, two independent conditions\n//\n// The gate produces DATA — a Decision Record — and nothing else. That is what lets a hosted\n// \"point us at your spec\" flow (§9's forward constraint) supply the identical structure from a\n// web form and reuse the core verbatim, and it is why this file has no business logic to test.\n\nimport { createInterface } from \"node:readline/promises\";\nimport { existsSync, readFileSync, statSync, writeFileSync } from \"node:fs\";\nimport { dirname, isAbsolute, join, relative, resolve, sep } from \"node:path\";\nimport {\n CAPABILITY_ID_RE,\n COMPANY_ID_RE,\n formatReport,\n isKnown,\n locusCandidates,\n openApiAdapter,\n valueOrUndefined,\n type CapabilityDecision,\n validateDecisionRecord,\n type DecisionRecord,\n type DraftModel,\n type DraftOperation,\n type Effect,\n type SourceAdapter,\n type SourceInput,\n} from \"@archstone/init\";\nimport { runInit } from \"@archstone/init/loop\";\n\n/** Bounded so a malformed or hostile document cannot make the host loop forever fetching. */\nconst MAX_REFERENCE_ROUNDS = 8;\n\nexport interface InitArgs {\n spec: string;\n out: string;\n domain?: string;\n company?: string;\n probe: boolean;\n decisionsFile?: string;\n interactive: boolean;\n force: boolean;\n reportFile?: string;\n}\n\nexport const INIT_USAGE = [\n \"usage: archstone init <spec-file> --out <dir> [options]\",\n \"\",\n \" Read an API description, ask you the questions no tool can answer, and write a CDL\",\n \" manifest the real compiler has already compiled. No LLM is involved, on any path.\",\n \"\",\n \" --out <dir> where the manifest goes (required)\",\n \" --domain <name> the domain half of every capability id (e.g. 'framing')\",\n \" --company <id> company id, lowercase kebab (e.g. 'acme')\",\n \" --decisions <file> a Decision Record JSON file, instead of the interactive gate.\",\n \" Each entry's `operation` is the CANDIDATE KEY, which is\",\n \" `<METHOD> <path>` with the path INCLUDING the server base path\",\n \" from `servers[0].url` — so a document whose `paths:` reads\",\n \" `/catalog/frames` under a server of `https://api.x.test/api/v1`\",\n \" has the key `GET /api/v1/catalog/frames`. Run without --decisions\",\n \" once to see the real keys, or read them off a failed run's report.\",\n \" Not combinable with --company or --domain, which it answers.\",\n \" --report <file> also write the report here (default: <out>/INIT-REPORT.md)\",\n \" --probe OPT-IN, READ-ONLY. Record a golden fixture by making ONE live\",\n \" request per capability you consent to. Never issued for a\",\n \" capability whose confirmed effect is not `read`; a non-GET/HEAD\",\n \" method needs a second, separate confirmation, and is refused\",\n \" outright when there is no terminal. Off by default.\",\n \" --non-interactive no prompts. Requires --decisions: `init` never defaults an\",\n \" `effect`, so with no human and no record there is nothing to do.\",\n \" --force write into a non-empty directory\",\n].join(\"\\n\");\n\n// ---------------------------------------------------------------------------------------\n// D-11's host half: the host fetches, the adapter stays pure.\n// ---------------------------------------------------------------------------------------\n\n/**\n * Resolve one adapter-requested reference to a real path, or refuse.\n *\n * SUBTREE ONLY. The adapter already refuses to emit a `..`, and this refuses to follow one —\n * two independent checks, because the thing being prevented is a spec file turning into an\n * arbitrary file-read primitive, and one check is one bug away from none.\n */\nexport function resolveReference(specFile: string, key: string): string | undefined {\n if (isAbsolute(key) || key.split(/[\\\\/]/).includes(\"..\")) return undefined;\n const root = dirname(resolve(specFile));\n const target = resolve(root, key);\n if (target !== root && !target.startsWith(root + sep)) return undefined;\n return existsSync(target) && statSync(target).isFile() ? target : undefined;\n}\n\n/** Read the primary document and everything the adapter asks for, to closure. */\nexport function loadSource(adapter: SourceAdapter, specFile: string): { input: SourceInput; unresolved: string[] } {\n const input: SourceInput = { origin: relative(process.cwd(), specFile) || specFile, document: readFileSync(specFile, \"utf8\"), documents: {} };\n const unresolved: string[] = [];\n if (!adapter.references) return { input, unresolved };\n\n for (let round = 0; round < MAX_REFERENCE_ROUNDS; round += 1) {\n const wanted = adapter.references(input).filter((key) => input.documents![key] === undefined && !unresolved.includes(key));\n if (wanted.length === 0) break;\n for (const key of wanted) {\n const path = resolveReference(specFile, key);\n // Unresolvable is NOT fatal here. The adapter reports what it is still missing and fails\n // closed on the operations that needed it — that division of labour is the whole point\n // of `references()` being a question rather than a demand.\n if (path === undefined) unresolved.push(key);\n else input.documents![key] = readFileSync(path, \"utf8\");\n }\n }\n return { input, unresolved };\n}\n\n// ---------------------------------------------------------------------------------------\n// The gate\n// ---------------------------------------------------------------------------------------\n\n/** Everything the gate needs to ask, so the asking itself is trivial and the ORDER is\n * reviewable. Product §11.1: the minimum keystroke path for a large spec is the design. */\nexport interface Ask {\n question(text: string, fallback?: string): Promise<string>;\n}\n\n/**\n * Why the gate can no longer ask anything — or `undefined` if this is an ordinary bug.\n *\n * Both members end the run the same way (nothing written, one line, non-zero) and are kept\n * apart only so the line is true.\n *\n * `no-more-input` — `AbortError`. Ctrl+D at a TTY raises it from `_ttyWrite`\n * (`AbortError: Aborted with Ctrl+D`), and so does the signal\n * `terminalAsk` ties to the interface's `close` — which is the case a\n * question PENDING when stdin ends takes, i.e. the ordinary piped/CI one.\n * `terminal-closed` — `ERR_USE_AFTER_CLOSE`. Strictly the NEXT question after readline has\n * already closed.\n *\n * NAMED CAREFULLY, because the obvious split is wrong. \"Cancelled\" would read as \"the user\n * changed their mind\", and the same `AbortError` covers both that and a stdin that simply ran\n * out — which is the more common one in practice. The two are indistinguishable at this point,\n * so the label and the message say only what is actually known: there is no more input.\n *\n * Detected by `name`/`code` rather than `instanceof`, because the classes Node throws are\n * internal and not exported; the name and the code are the documented parts.\n *\n * Returning `undefined` for everything else is deliberate. Swallowing a real bug as \"the user\n * changed their mind\" would be a worse silence than the stack trace this replaces.\n */\nexport function promptFailureKind(error: unknown): \"no-more-input\" | \"terminal-closed\" | undefined {\n if (!(error instanceof Error)) return undefined;\n const code = (error as { code?: string }).code;\n if (error.name === \"AbortError\" || code === \"ABORT_ERR\") return \"no-more-input\";\n if (code === \"ERR_USE_AFTER_CLOSE\") return \"terminal-closed\";\n return undefined;\n}\n\n/**\n * The REAL terminal `Ask` — and the reason it has to exist.\n *\n * `readline/promises`' signature is `question(query[, options])`, where `options` is\n * `{signal}`. Passing a fallback STRING as the second argument is silently ignored: the call\n * type-checks against a `readline.Interface` — which structurally satisfies `Ask`, since\n * `question(text, anything?)` is assignable — resolves with `\"\"` on an empty line, and drops the\n * default on the floor.\n *\n * That is exactly what shipped: `runGate` was handed the `Interface` itself, so EVERY default in\n * the gate was dead. `--company` and `--domain` did nothing interactively, the\n * `${COMPANY}_API_URL` suggestion never appeared, and a computed capability id had to be retyped\n * in full. The minimum-keystroke path product §11.1 calls \"the design\" did not exist.\n *\n * It stayed invisible because the tests drive a fake `Ask` that honours the fallback — so they\n * implement the INTERFACE, and the interface is not where the bug is. The call site passes the\n * fallback correctly; it is dropped at the boundary. Nothing that substitutes for the boundary\n * can see a bug in the boundary.\n *\n * Two things this does, and both are load-bearing:\n * - SHOWS the default, the way `confirm` already shows `[Y/n]`. A default the user cannot see\n * is not a default, it is a coincidence.\n * - Treats an empty line as the default — the identical rule `confirm` applies at its own\n * prompt, which is precisely the logic every other prompt assumed someone else was doing.\n */\nexport function terminalAsk(rl: TerminalInterface): Ask {\n // A question already PENDING when stdin reaches EOF NEVER SETTLES — readline neither resolves\n // it nor rejects it. With no handle left to wait on, Node then drains the event loop and the\n // process exits 0, having asked a question nobody answered and written nothing. Exit 0 is the\n // worst available outcome: a script that pipes answers in reports success.\n //\n // That is exactly what `printf 'a\\nb\\n…' | archstone init` did, and the reason is structural\n // rather than a race: `question` registers a ONE-SHOT line handler, and readline has no queue,\n // so every line that arrives while no question is pending is discarded. A pipe delivers all\n // its lines in one chunk, so answer 1 is consumed and answers 2..n are dropped. Piping answers\n // into the gate has never worked and cannot be made to work here — `--decisions` is the\n // supported way to answer without a human.\n //\n // Tying a signal to the interface's own `close` turns that silent exit-0 into the same clean\n // refusal Ctrl+D gets: one line, nothing written, non-zero. It cannot fire on a healthy\n // terminal, where stdin stays open until the user closes it. `MAX_PROMPT_ATTEMPTS` cannot help\n // here — a bound on ATTEMPTS never fires when the first attempt never returns.\n const controller = new AbortController();\n rl.once?.(\"close\", () => controller.abort());\n return {\n async question(text: string, fallback?: string): Promise<string> {\n const suggestion = fallback !== undefined && fallback !== \"\" ? fallback : undefined;\n const prompt = suggestion === undefined ? text : `${text.trimEnd()} [${suggestion}] `;\n let answer: string;\n try {\n answer = await rl.question(prompt, { signal: controller.signal });\n } catch (error) {\n // TRANSLATED AT THE BOUNDARY, not at the caller. `runGateOverTerminal` used to classify\n // whatever escaped the whole of `runGate`, which meant a future `AbortController`\n // anywhere inside it — a fetch with a timeout, say — would have its abort silently\n // relabelled as \"the user pressed Ctrl+D\" and reported as a clean refusal. Throwing a\n // private sentinel makes that impossible by construction: only this boundary can produce\n // one, so only this boundary's failures can be read as \"no more input\".\n const kind = promptFailureKind(error);\n if (kind === undefined) throw error;\n throw new PromptUnavailable(kind);\n }\n return answer.trim() === \"\" && suggestion !== undefined ? suggestion : answer;\n },\n };\n}\n\n/** The gate cannot ask anything further. Private to this module on purpose — see `terminalAsk`. */\nclass PromptUnavailable extends Error {\n constructor(readonly kind: \"no-more-input\" | \"terminal-closed\") {\n super(kind);\n this.name = \"PromptUnavailable\";\n }\n}\n\n/** The slice of `readline.Interface` this file uses. Narrow on purpose: a wider type is what\n * let the interface itself be passed as an `Ask` in the first place. */\nexport interface TerminalInterface {\n question(query: string, options?: { signal?: AbortSignal }): Promise<string>;\n once?(event: \"close\", listener: () => void): unknown;\n}\n\n/**\n * Run the gate against a REAL readline interface, translating cancellation into a value.\n *\n * Extracted from the command so both halves of the terminal boundary are reachable by a test\n * that constructs an actual `readline.Interface` — which is the only kind of test that could\n * have caught either of the two defects here, since both live on the far side of `Ask` and a\n * substitute for `Ask` is by construction blind to them.\n */\nexport async function runGateOverTerminal(\n draft: DraftModel,\n rl: TerminalInterface,\n args: InitArgs,\n): Promise<DecisionRecord | \"no-more-input\" | \"terminal-closed\" | undefined> {\n try {\n // `terminalAsk`, NEVER the interface itself: `rl` structurally satisfies `Ask` and silently\n // ignores the fallback, which is how every default in the gate came to be dead.\n return await runGate(draft, terminalAsk(rl), args);\n } catch (error) {\n // ONLY the sentinel, which only `terminalAsk` can throw. An abort raised by anything else\n // inside `runGate` is a bug and must keep looking like one.\n if (error instanceof PromptUnavailable) return error.kind;\n throw error;\n }\n}\n\n/**\n * How many times a prompt re-asks before the gate gives up.\n *\n * NOT politeness — a bound on REPEATED INVALID ANSWERS, so a `while (!valid)` loop cannot spin.\n * Found by a test whose script ran out of answers: the worker hit an OOM abort rather than\n * failing.\n *\n * CORRECTED: this comment used to justify the bound with \"`readline.question` resolves with `\"\"`\n * forever once stdin reaches EOF\". That is not what `readline/promises` does — verified against\n * the real interface rather than the test double that stood in for it. At EOF a PENDING question\n * never settles at all, and a question asked AFTER the close throws `ERR_USE_AFTER_CLOSE`.\n * Neither is a spin, and neither is something a bound on attempts could ever have caught: the\n * first never returns, and the second is a rejection. `terminalAsk` handles both — see there.\n * The bound is still right, for the reason above and not for the reason it used to give.\n */\nconst MAX_PROMPT_ATTEMPTS = 5;\n\n/**\n * Ask until the answer validates, or give up.\n *\n * Giving up returns `undefined` and the gate refuses the whole run — which is the correct\n * terminal state, because the alternative is defaulting a value nobody supplied, and every\n * question this gate asks exists precisely because it must not be defaulted.\n */\nasync function askUntil<T>(\n ask: Ask,\n question: string,\n parse: (answer: string) => T | undefined,\n onInvalid: () => void,\n fallback?: string,\n): Promise<T | undefined> {\n for (let attempt = 0; attempt < MAX_PROMPT_ATTEMPTS; attempt += 1) {\n const parsed = parse((await ask.question(question, fallback)).trim());\n if (parsed !== undefined) return parsed;\n onInvalid();\n }\n return undefined;\n}\n\n/** `y`/`n` with an explicit default. Anything unrecognized takes the default — a gate that\n * re-asks forever on a typo is a gate people learn to `--non-interactive` around. */\nasync function confirm(ask: Ask, text: string, fallback: boolean): Promise<boolean> {\n const answer = (await ask.question(`${text} [${fallback ? \"Y/n\" : \"y/N\"}] `)).trim().toLowerCase();\n if (answer === \"\") return fallback;\n return answer.startsWith(\"y\");\n}\n\nconst EFFECTS = new Set<Effect>([\"read\", \"write\", \"irreversible\"]);\n\n/**\n * The interactive gate. Produces a Decision Record and NOTHING else — no files, no requests.\n *\n * Two rules from product §11.1 shape the keystrokes, and both are about a 40-operation spec:\n * DEFAULT-SKIP with a bulk-keep escape (`a`), because most operations in a spec are not\n * capabilities; and `effect` PRE-FILLED ONLY FOR `GET`, blank and mandatory for everything\n * else. A pre-filled `read` on a `DELETE` is the exact keystroke that would make the\n * consequence-bearing asymmetry — the developer runs `init`, the business pays for a wrong\n * `effect` months later, through an agent, in front of a customer — land on the wrong person.\n */\nexport async function runGate(draft: DraftModel, ask: Ask, args: InitArgs): Promise<DecisionRecord | undefined> {\n const companyId = (await ask.question(\"Company id (lowercase, kebab-case) \", args.company)).trim();\n if (!COMPANY_ID_RE.test(companyId)) {\n console.error(`archstone init: '${companyId}' is not a valid company id (^[a-z][a-z0-9-]*$).`);\n return undefined;\n }\n const companyName = (await ask.question(\"Company name (for the manifest header) \", valueOrUndefined(draft.company.name))).trim();\n const domain = (await ask.question(\"Domain for these capabilities (the first half of every id) \", args.domain)).trim();\n\n // Amendment 1 §A-5 gap 4, and NF-A from the re-review: the env-var names are not derivable\n // from any source construct, so they are human answers with sane defaults — the same shape\n // as every other question here. Asked once per run, not per capability, and only for auth\n // when the source actually declared a scheme, so a public API costs zero extra keystrokes.\n const envPrefix = companyId.replace(/-/g, \"_\").toUpperCase();\n const baseUrlEnvVar = (await ask.question(\"Env var holding the backend base URL \", `${envPrefix}_API_URL`)).trim();\n const declaresAuth = draft.auth !== undefined || draft.operations.some((o) => o.auth?.kind === \"header\");\n const authEnvVar = declaresAuth\n ? (await ask.question(\"Env var holding the API credential (never its value) \", `${envPrefix}_API_TOKEN`)).trim()\n : \"\";\n\n const decisions: CapabilityDecision[] = [];\n let keepAll = false;\n\n for (const [index, candidate] of draft.operations.entries()) {\n const operation: DraftOperation = candidate;\n const summary = valueOrUndefined(operation.description) ?? \"\";\n console.log(\"\");\n console.log(`[${index + 1}/${draft.operations.length}] ${operation.key}`);\n if (summary) console.log(` ${summary}`);\n const blocking = operation.notes.filter((n) => n.code.startsWith(\"unsupported\") || n.code === \"declined\");\n for (const n of blocking) console.log(` ! ${n.code}${n.detail ? `: ${n.detail}` : \"\"}`);\n\n let keep = keepAll;\n if (!keep) {\n const answer = (await ask.question(\" keep as a capability? [y/N/a=keep all remaining] \")).trim().toLowerCase();\n if (answer === \"a\") {\n keepAll = true;\n keep = true;\n } else keep = answer.startsWith(\"y\");\n }\n if (!keep) {\n decisions.push({ operation: operation.key, keep: false });\n continue;\n }\n\n const action = valueOrUndefined(operation.suggestedAction);\n const suggestedId = domain !== \"\" && action !== undefined ? `${domain}.${action}` : undefined;\n const capabilityId = (await ask.question(\" capability id (domain.action) \", suggestedId)).trim();\n if (!CAPABILITY_ID_RE.test(capabilityId)) {\n console.error(` '${capabilityId}' is not a valid capability id — skipping this candidate.`);\n decisions.push({ operation: operation.key, keep: false, note: `invalid id '${capabilityId}' supplied at the gate` });\n continue;\n }\n\n // PRE-FILLED ONLY FOR `GET`. `effectHint` exists solely to fill this prompt, and the\n // emitter cannot see it — \"no `effect` without human confirmation\" is a property of the\n // emission signature, not a runtime check someone can route around.\n const prefill = operation.method.toUpperCase() === \"GET\" && operation.effectHint ? operation.effectHint.value : undefined;\n const effect = await askUntil<Effect>(\n ask,\n \" effect (read | write | irreversible) \",\n (answer) => (EFFECTS.has(answer as Effect) ? (answer as Effect) : undefined),\n () => console.error(\" must be one of: read, write, irreversible\"),\n prefill,\n );\n if (effect === undefined) {\n console.error(\"archstone init: no valid `effect` after several attempts — refusing rather than defaulting one.\");\n return undefined;\n }\n\n // D-14 — THE LOCUS, ASKED BEFORE THE NAME. They are the same question at two altitudes:\n // \"it returns a PartQuote\" IS the root answer, \"it returns a list of QuoteWarning\" IS the\n // array answer, and the name is unanswerable until the locus is fixed because the name\n // names the locus.\n //\n // Only asked when a choice exists. On a nine-operation spec that is three questions, not\n // nine — the census is what keeps the keystroke cost proportional.\n let responseLocus: string | undefined;\n const census = locusCandidates(operation.response);\n if (census.candidates.length > 1) {\n // R-11 IS WHY THIS PROMPT LOOKS LIKE THIS, and it is the piece the architect is least\n // confident in: a badly-worded question yields confirmed-but-wrong loci that are WORSE\n // than the silent ones they replace, because a human signed them. Nobody can answer\n // \"$.warnings[*] or root?\" on an endpoint they did not write. They can answer\n // \"a list of (code, message)\" versus \"one thing with (quotedPrice, currency)\".\n // Count-agnostic. The fixed string \"two ways\" was wrong the moment a response carried\n // root scalars plus two lists — a real shape, not a hypothetical one — and it shipped\n // because nothing in the suite reached three candidates.\n console.log(` this response could be read ${census.candidates.length} ways — which one does this capability return?`);\n for (const [index, candidate] of census.candidates.entries()) {\n const shape = candidate.kind === \"root\" ? \"one object, with fields\" : `a list, each with fields`;\n console.log(` ${index + 1}. ${shape}: ${candidate.fields.join(\", \")}`);\n console.log(` (${candidate.id})`);\n }\n // Pre-filled with the sole array-of-objects when there is exactly one — today's answer,\n // so a paginated list costs one keypress. A PROPOSAL, never a decision: the emitter\n // reads the selection and can never re-derive it.\n const collections = census.candidates.filter((c) => c.kind === \"collection\");\n // Pre-filled ONLY when there is exactly one list — that is today's answer, so a\n // paginated list costs one keypress. With two or more lists there is no defensible\n // pre-fill, and offering one would be the branch-order guess D-14 exists to remove.\n const prefill = collections.length === 1 ? String(census.candidates.indexOf(collections[0]!) + 1) : undefined;\n const picked = await askUntil<number>(\n ask,\n ` which one? [1-${census.candidates.length}] `,\n (answer) => {\n const index = Number(answer);\n return Number.isInteger(index) && index >= 1 && index <= census.candidates.length ? index : undefined;\n },\n () => console.error(` answer with a number from 1 to ${census.candidates.length}`),\n prefill,\n );\n if (picked === undefined) {\n console.error(\"archstone init: no response locus chosen after several attempts — refusing rather than guessing one.\");\n return undefined;\n }\n responseLocus = census.candidates[picked - 1]!.id;\n }\n\n const resourceName = (await ask.question(\" resource name (blank = derive from the source) \")).trim();\n\n const decision: Extract<CapabilityDecision, { keep: true }> = {\n operation: operation.key,\n keep: true,\n capabilityId,\n effect: effect as Effect,\n ...(responseLocus !== undefined ? { responseLocus } : {}),\n ...(resourceName !== \"\" ? { resourceName } : {}),\n };\n\n if (args.probe && decision.effect === \"read\") {\n decision.probe = await confirm(ask, ` record a golden fixture with ONE live ${operation.method} to the real backend?`, false);\n if (decision.probe) {\n const method = operation.method.toUpperCase();\n if (method !== \"GET\" && method !== \"HEAD\") {\n // R-8's second, SEPARATE confirmation. Worded so the thing being confirmed is the\n // method and not the effect again — a re-phrasing of the same question is not a\n // second condition.\n decision.probeNonReadMethodConfirmed = await confirm(\n ask,\n ` ${method} is not a GET. Confirm again that this request changes nothing on the backend:`,\n false,\n );\n }\n // D-13: pre-fill from the document's own `example`/`default`, and make the human\n // confirm every value. A probe carries a value to a production backend, and an\n // `example` may name a real customer's record — `init` cannot tell.\n //\n // THE FALLBACK IS KEPT HERE DELIBERATELY, against this gate's usual rule that a\n // consequence-bearing answer is typed rather than Entered (`effect` carries no\n // fallback; a non-`GET` probe needs its own second confirmation). By the time this\n // prompt appears the operator has ALREADY authorised a live read of this capability:\n // `--probe` is opt-in and off by default, consent is per capability, and a non-`GET`\n // method has already been confirmed separately. A sample value is a parameter of a call\n // already authorised, not a fresh authorisation.\n //\n // What makes Enter-to-accept legitimate is that the value is on screen AND ITS ORIGIN\n // IS NAMED. D-13's own worry is that a spec example may name a real customer's record —\n // `id.example: AV45` is a real product code, `artwork_id.example` is a made-up UUID, and\n // `init` cannot tell them apart. Only the human can, and only if they know the value\n // came from the API description rather than from their own last run. The raw source\n // locator used to be printed here, which is not the same thing: it is long enough to\n // skim past and it never says \"somebody else wrote this\".\n const sample: Record<string, unknown> = {};\n for (const field of operation.input) {\n const suggested = isKnown(field.example) ? String(field.example.value) : undefined;\n const origin = suggested === undefined ? \"\" : \" (from the API description)\";\n const required = valueOrUndefined(field.required) === true || field.in === \"path\";\n const typed = (await ask.question(` sample value for ${field.name}${required ? \"\" : \" (optional)\"}${origin} `, suggested)).trim();\n if (typed !== \"\") sample[field.name] = coerce(typed);\n }\n if (Object.keys(sample).length > 0) decision.sampleInput = sample;\n }\n }\n decisions.push(decision);\n }\n\n return {\n version: \"0\",\n company: { id: companyId, ...(companyName !== \"\" ? { name: companyName } : {}) },\n ...(baseUrlEnvVar !== \"\" ? { baseUrlEnvVar } : {}),\n ...(authEnvVar !== \"\" ? { authEnvVar } : {}),\n decisions,\n };\n}\n\n/** A typed sample value from a terminal. JSON first (so `50`, `true`, `[\"a\"]` survive), then\n * the raw string — a backend that wants the string `\"50\"` gets it by quoting. */\nfunction coerce(text: string): unknown {\n try {\n return JSON.parse(text) as unknown;\n } catch {\n return text;\n }\n}\n\n// ---------------------------------------------------------------------------------------\n// argv\n// ---------------------------------------------------------------------------------------\n\nexport function parseInitArgs(argv: string[]): InitArgs | { error: string } {\n const flag = (name: string): string | undefined => {\n const idx = argv.indexOf(name);\n return idx === -1 ? undefined : argv[idx + 1];\n };\n const valued = [\"--out\", \"--domain\", \"--company\", \"--decisions\", \"--report\"];\n const consumed = new Set<number>();\n for (const name of valued) {\n const idx = argv.indexOf(name);\n if (idx !== -1) {\n consumed.add(idx);\n consumed.add(idx + 1);\n }\n }\n const positional = argv.filter((a, i) => !consumed.has(i) && !a.startsWith(\"--\"));\n const spec = positional[1]; // positional[0] is the verb itself\n if (spec === undefined) return { error: \"a spec file is required\" };\n const out = flag(\"--out\");\n if (out === undefined) return { error: \"--out <dir> is required\" };\n\n return {\n spec,\n out,\n ...(flag(\"--domain\") !== undefined ? { domain: flag(\"--domain\")! } : {}),\n ...(flag(\"--company\") !== undefined ? { company: flag(\"--company\")! } : {}),\n probe: argv.includes(\"--probe\"),\n ...(flag(\"--decisions\") !== undefined ? { decisionsFile: flag(\"--decisions\")! } : {}),\n interactive: !argv.includes(\"--non-interactive\"),\n force: argv.includes(\"--force\"),\n ...(flag(\"--report\") !== undefined ? { reportFile: flag(\"--report\")! } : {}),\n };\n}\n\n// ---------------------------------------------------------------------------------------\n// The verb\n// ---------------------------------------------------------------------------------------\n\nexport async function runInitCmd(argv: string[]): Promise<number> {\n if (argv.includes(\"--help\") || argv.includes(\"-h\")) {\n console.log(INIT_USAGE);\n return 0;\n }\n const parsed = parseInitArgs(argv);\n if (\"error\" in parsed) {\n console.error(`archstone init: ${parsed.error}\\n\\n${INIT_USAGE}`);\n return 2;\n }\n const args = parsed;\n\n const specFile = resolve(process.cwd(), args.spec);\n if (!existsSync(specFile)) {\n console.error(`archstone init: no such file: ${specFile}`);\n return 2;\n }\n\n const adapter = openApiAdapter;\n const { input, unresolved } = loadSource(adapter, specFile);\n for (const key of unresolved) {\n console.error(`archstone init: referenced document '${key}' could not be read from the spec's own directory — operations that need it will be skipped.`);\n }\n const draft = adapter.adapt(input);\n\n if (draft.operations.length === 0) {\n console.error(`archstone init: ${adapter.id} found no candidate operations in ${args.spec}.`);\n for (const n of draft.notes) console.error(` - ${n.code}${n.detail ? `: ${n.detail}` : \"\"}`);\n return 1;\n }\n\n let record: DecisionRecord | undefined;\n if (args.decisionsFile !== undefined) {\n // C-3: a flag that answers a question the record already answers is a CONFLICT, not a\n // default. Silently ignoring it is the failure mode the `interactive` fix already closed\n // once — the user said something and the tool pretended they had not.\n const ignored = [args.company !== undefined ? \"--company\" : undefined, args.domain !== undefined ? \"--domain\" : undefined].filter(\n (f): f is string => f !== undefined,\n );\n if (ignored.length > 0) {\n console.error(\n `archstone init: ${ignored.join(\" and \")} ${ignored.length === 1 ? \"is\" : \"are\"} answered by the Decision Record and cannot be combined with --decisions.\\n` +\n ` ${ignored.includes(\"--company\") ? \"Set `company.id` in the record\" : \"\"}${ignored.length === 2 ? \"; \" : \"\"}${ignored.includes(\"--domain\") ? \"the domain is the first half of each `capabilityId` in the record\" : \"\"}.`,\n );\n return 2;\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(readFileSync(resolve(process.cwd(), args.decisionsFile), \"utf8\"));\n } catch (err) {\n console.error(`archstone init: cannot read the Decision Record: ${(err as Error).message}`);\n return 2;\n }\n // C-2: the record used to be an unchecked cast, and it was the ONE input `init` trusted\n // completely while refusing to trust anything else. A missing `company` produced a raw\n // TypeError with a stack trace — on the `--non-interactive` path, which is CI, where a\n // stack trace is the least actionable output there is.\n const validation = validateDecisionRecord(parsed);\n if (!validation.ok) {\n console.error(`archstone init: the Decision Record at ${args.decisionsFile} is not valid:`);\n for (const problem of validation.problems) console.error(` - ${problem}`);\n return 2;\n }\n record = validation.record;\n } else if (!args.interactive) {\n // DoD-5(d), and the one refusal in this file that is not about the network: `init` never\n // defaults an `effect`. With no human to ask and no record to read, there is nothing to do\n // that would not be a guess about a value the business pays for months later.\n console.error(\"archstone init: --non-interactive requires --decisions <file>. `init` never defaults an `effect`.\");\n return 2;\n } else {\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n let outcome: DecisionRecord | \"no-more-input\" | \"terminal-closed\" | undefined;\n try {\n outcome = await runGateOverTerminal(draft, rl, args);\n } finally {\n rl.close();\n }\n // Ctrl+D is a user saying \"I changed my mind\"; a closed stdin is a terminal that went away.\n // Both deserve the clean terminal state the refusal paths already produce — nothing written,\n // one line, non-zero — rather than the unhandled error and Node stack trace they used to\n // produce. A retry bound cannot cover either: both arrive as a REJECTED PROMISE, and\n // `MAX_PROMPT_ATTEMPTS` counts answers, not failures to be able to ask.\n if (outcome === \"no-more-input\") {\n // Deliberately NOT \"cancelled\": the same `AbortError` covers Ctrl+D and a stdin that ran\n // out, and telling a CI runner it changed its mind is a small lie that costs someone an\n // hour. The hint names the supported way to answer without a human.\n console.error(\"\\narchstone init: no more input (Ctrl+D, or stdin ended) — nothing was written.\");\n console.error(\" To answer without a human, use --decisions <file> --non-interactive.\");\n return 2;\n }\n if (outcome === \"terminal-closed\") {\n console.error(\"\\narchstone init: the terminal closed before the gate finished — nothing was written.\");\n return 2;\n }\n record = outcome;\n if (!record) return 2;\n }\n\n const result = await runInit(draft, record, {\n targetDir: resolve(process.cwd(), args.out),\n force: args.force,\n probe: args.probe,\n // \"Interactive\" for R-8's purposes means A HUMAN WAS ACTUALLY ASKED, not \"the\n // --non-interactive flag was absent\". A Decision Record file supplies every answer up\n // front, so `--decisions` without `--non-interactive` has no prompt either — and treating\n // it as interactive would let a file-supplied `probeNonReadMethodConfirmed` authorize a\n // non-GET probe against a production backend with nobody at the terminal. The second\n // confirmation is a human act performed AT THE MOMENT OF THE CALL; that is the whole\n // reason it is separate from `effect`, which a file may legitimately carry.\n interactive: args.interactive && args.decisionsFile === undefined,\n });\n\n const report = formatReport({\n origin: draft.source.origin,\n adapter: draft.source.adapter,\n targetDir: resolve(process.cwd(), args.out),\n emitted: result.emitted,\n written: result.written,\n failures: result.failures,\n probes: result.probes.map((p) => ({ capabilityId: p.capabilityId, outcome: p.outcome, detail: p.detail })),\n verifications: result.verifications,\n candidates: draft.operations.length,\n });\n console.log(`\\n${report}`);\n\n if (result.ok) {\n // The report goes to a COMMITTABLE FILE as well as to stdout (product §11.2): the file is\n // the pull-request review surface, and a reviewer who was not at the terminal is the second\n // pair of eyes on the one risk automation cannot close (R-9).\n const reportFile = args.reportFile !== undefined ? resolve(process.cwd(), args.reportFile) : join(resolve(process.cwd(), args.out), \"INIT-REPORT.md\");\n try {\n writeFileSync(reportFile, report);\n console.log(`Report also written to ${reportFile}\\n`);\n } catch (err) {\n console.error(`archstone init: could not write the report file: ${(err as Error).message}`);\n }\n }\n\n return result.ok ? 0 : 1;\n}\n","// `archstone audit <file…>` — the I/O half of the audit reader (`audit-report.ts` holds the\n// pure half). Reads the deployer's own JSON Lines files, filters, and renders.\n//\n// Note what it is not: there is no service, no index, no daemon and no upload. The records live\n// on the deployer's disk, Archstone never receives them, and this verb is a reader over local\n// files — which is also why it needs no configuration beyond the paths.\n\nimport { readFileSync } from \"node:fs\";\nimport { applyFilter, parseAuditLines, summarize, toCsv, type AuditFilter } from \"./audit-report\";\n\nconst FORMATS = [\"summary\", \"jsonl\", \"csv\"] as const;\ntype Format = (typeof FORMATS)[number];\n\nfunction flag(argv: string[], name: string): string | undefined {\n const i = argv.indexOf(name);\n return i === -1 ? undefined : argv[i + 1];\n}\n\nfunction isoOrExit(value: string | undefined, name: string): string | undefined {\n if (value === undefined) return undefined;\n // Accept a date (2026-08-21) as well as a full timestamp: an auditor asks for \"August\", not\n // for an RFC 3339 instant. A bare date compares correctly against a stored ISO timestamp\n // because both are lexicographically ordered — which is the same property the records rely on.\n if (!/^\\d{4}-\\d{2}-\\d{2}([T ].*)?$/.test(value)) {\n console.error(`archstone audit: ${name} must be a date or ISO timestamp (e.g. 2026-08-21 or 2026-08-21T09:00:00Z), got '${value}'`);\n process.exit(2);\n }\n return value;\n}\n\nexport function printAuditUsage(): void {\n console.error(\n \"usage: archstone audit <file…> [--since <date>] [--until <date>] [--capability <id>]\\n\" +\n \" [--principal <p>] [--phase succeeded|failed|denied]\\n\" +\n \" [--format summary|jsonl|csv]\\n\" +\n \"\\n\" +\n \" Read Execution audit records (JSON Lines) that your own deployment wrote, and report on\\n\" +\n \" them. Nothing is uploaded: these are your files, read locally.\\n\" +\n \"\\n\" +\n \" --since <date> inclusive lower bound on startedAt (date or ISO timestamp)\\n\" +\n \" --until <date> exclusive upper bound — so adjacent ranges tile without overlap\\n\" +\n \" --capability <id> exact CDL capability id, e.g. framing.estimate-frame-price\\n\" +\n \" --principal <p> exact principal, e.g. user:alice\\n\" +\n \" --anonymous only invocations that carried no principal at all\\n\" +\n \" --phase <p> succeeded | failed | denied\\n\" +\n \" --format <f> summary (default) · jsonl (filtered passthrough) · csv (spreadsheet)\\n\" +\n \"\\n\" +\n \" Pass rotated generations too — the sink writes <path>.1, <path>.2, …:\\n\" +\n \" archstone audit audit.log audit.log.1 --since 2026-08-01 --format csv > q3.csv\\n\",\n );\n}\n\nexport function runAuditCmd(argv: string[]): number {\n const files = argv.slice(1).filter((a, i, all) => {\n if (a.startsWith(\"--\")) return false;\n const prev = all[i - 1];\n return !(prev?.startsWith(\"--\") && prev !== \"--json\"); // not a flag's value\n });\n\n if (files.length === 0) {\n printAuditUsage();\n return 2;\n }\n\n const format = (flag(argv, \"--format\") ?? \"summary\") as Format;\n if (!FORMATS.includes(format)) {\n console.error(`archstone audit: --format must be one of ${FORMATS.join(\" | \")}, got '${format}'`);\n return 2;\n }\n\n const filter: AuditFilter = {\n since: isoOrExit(flag(argv, \"--since\"), \"--since\"),\n until: isoOrExit(flag(argv, \"--until\"), \"--until\"),\n capability: flag(argv, \"--capability\"),\n principal: argv.includes(\"--principal\") ? (flag(argv, \"--principal\") ?? \"\") : undefined,\n anonymous: argv.includes(\"--anonymous\"),\n phase: flag(argv, \"--phase\"),\n };\n\n // An empty `--principal` used to be how anonymous invocations were selected (v0.12.0). It\n // reads like a mistake in a shell, and it is indistinguishable from one — so it is now an\n // error that names the right flag rather than a subtlety that quietly answers a different\n // question than the operator asked.\n if (filter.principal === \"\") {\n console.error(\n \"archstone audit: --principal '' is not how you select anonymous invocations — use --anonymous.\\n\" +\n \" (An empty principal would mean the host supplied the empty string, which is a different thing.)\",\n );\n return 2;\n }\n if (filter.anonymous && filter.principal !== undefined) {\n console.error(\"archstone audit: --anonymous and --principal are mutually exclusive — a call is one or the other.\");\n return 2;\n }\n\n const records = [];\n let skipped = 0;\n for (const file of files) {\n let text: string;\n try {\n text = readFileSync(file, \"utf8\");\n } catch (err) {\n console.error(`archstone audit: cannot read '${file}': ${(err as Error).message}`);\n return 1;\n }\n const outcome = parseAuditLines(text);\n records.push(...outcome.records);\n // Never silent: an unreadable line in an audit trail is either corruption or a record from a\n // version this reader does not understand, and both are the operator's business.\n for (const s of outcome.skipped) console.error(`archstone audit: ${file}:${s.line} skipped — ${s.reason}`);\n skipped += outcome.skipped.length;\n }\n\n // Chronological regardless of the order the files were given, so `audit.log.1 audit.log` and\n // `audit.log audit.log.1` produce the same report.\n const filtered = applyFilter(records, filter).sort((a, b) =>\n a.metadata.startedAt.localeCompare(b.metadata.startedAt),\n );\n\n if (format === \"jsonl\") console.log(filtered.map((r) => JSON.stringify(r)).join(\"\\n\"));\n else if (format === \"csv\") console.log(toCsv(filtered));\n else console.log(summarize(filtered));\n\n if (skipped > 0) console.error(`archstone audit: ${skipped} line(s) skipped — see above.`);\n return 0;\n}\n","// `archstone audit` — read a JSON Lines audit trail, filter it, and render it for someone who\n// has to answer a question about it (#44's records; see docs/ONBOARDING.md).\n//\n// The records are the deployer's own files, written by `rotatingFileAuditSink` or any sink they\n// wrote themselves. Archstone never receives them, so this is a local reader over local files —\n// no service, no index, no daemon.\n//\n// Everything here is pure and takes lines in, strings out: the CLI does the I/O.\n\nimport type { ExecutionRecord } from \"@archstone/emitter-support\";\n\nexport interface AuditFilter {\n since?: string;\n until?: string;\n capability?: string;\n /** Exact match. Anonymous invocations are selected with `anonymous`, not with `\"\"` — see\n * `applyFilter`. */\n principal?: string;\n /** Select only invocations that carried no principal at all. The absence of the field is a\n * real distinction (ADD-42 D-4: anonymous is not denied, but never privileged), so it gets\n * its own selector rather than being spelled as an empty principal. */\n anonymous?: boolean;\n phase?: string;\n}\n\nexport interface ParseOutcome {\n records: ExecutionRecord[];\n /** Lines that were not a parseable Execution record, with their 1-based position. */\n skipped: { line: number; reason: string }[];\n}\n\n/**\n * Parse JSON Lines into records, keeping what could not be read rather than discarding it.\n *\n * A silent skip is the wrong behaviour for an audit tool specifically: an unreadable line is\n * either corruption or a record written by a version this reader does not understand, and both\n * are things the person running the report needs told. Blank lines are not \"skipped\" — a\n * trailing newline is normal, not a defect.\n */\nexport function parseAuditLines(text: string): ParseOutcome {\n const records: ExecutionRecord[] = [];\n const skipped: { line: number; reason: string }[] = [];\n\n text.split(\"\\n\").forEach((raw, i) => {\n const line = raw.trim();\n if (!line) return;\n let parsed: unknown;\n try {\n parsed = JSON.parse(line);\n } catch {\n skipped.push({ line: i + 1, reason: \"not valid JSON\" });\n return;\n }\n const rec = parsed as Partial<ExecutionRecord>;\n if (rec?.kind !== \"Execution\" || !rec.metadata || !rec.status) {\n skipped.push({ line: i + 1, reason: \"not an Execution record\" });\n return;\n }\n records.push(rec as ExecutionRecord);\n });\n\n return { records, skipped };\n}\n\n/** Inclusive on `since`, exclusive on `until` — the convention that makes adjacent day ranges\n * tile without double-counting the boundary record. */\nexport function applyFilter(records: readonly ExecutionRecord[], f: AuditFilter): ExecutionRecord[] {\n return records.filter((r) => {\n if (f.since && r.metadata.startedAt < f.since) return false;\n if (f.until && r.metadata.startedAt >= f.until) return false;\n if (f.capability && r.metadata.capabilityId !== f.capability) return false;\n if (f.phase && r.status.phase !== f.phase) return false;\n // Two different questions, deliberately not one. `principal: \"\"` means \"the caller supplied\n // an empty string as its principal\", which is a present-but-empty value and a real thing a\n // host can do; `anonymous` means the field was absent. Conflating them — the shape this\n // filter shipped with in v0.12.0 — makes the more common question the harder one to ask,\n // and makes a plausible typo (`--principal \"\"`) silently answer the other one.\n if (f.anonymous && r.spec.principal !== undefined) return false;\n if (f.principal !== undefined && r.spec.principal !== f.principal) return false;\n return true;\n });\n}\n\nconst CSV_COLUMNS = [\n \"startedAt\",\n \"completedAt\",\n \"capabilityId\",\n \"provider\",\n \"phase\",\n \"denialReason\",\n \"principal\",\n \"consumer\",\n \"policyRuleIds\",\n \"sessionId\",\n \"id\",\n] as const;\n\nfunction csvCell(value: string | undefined): string {\n const v = value ?? \"\";\n // Quote when the value could otherwise change the shape of the row. Doubling the quote is the\n // RFC 4180 escape, and it is what every spreadsheet expects.\n return /[\",\\n]/.test(v) ? `\"${v.replace(/\"/g, '\"\"')}\"` : v;\n}\n\n/**\n * CSV, because the person who asks for an audit export opens it in a spreadsheet.\n *\n * The `input` field is deliberately absent: it is per-capability shaped, frequently large, and\n * carries whatever the caller sent — flattening it into a column would both break the row shape\n * and put payloads in a file that gets emailed around. `--format jsonl` keeps the full record\n * for anyone who needs it.\n */\nexport function toCsv(records: readonly ExecutionRecord[]): string {\n const rows = records.map((r) =>\n [\n r.metadata.startedAt,\n r.metadata.completedAt,\n r.metadata.capabilityId,\n r.metadata.provider,\n r.status.phase,\n r.status.denialReason,\n r.spec.principal,\n r.spec.consumer,\n r.spec.policyRuleIds?.join(\" \"),\n r.metadata.sessionId,\n r.metadata.id,\n ]\n .map(csvCell)\n .join(\",\"),\n );\n return [CSV_COLUMNS.join(\",\"), ...rows].join(\"\\n\");\n}\n\nfunction countBy<T>(items: readonly T[], key: (item: T) => string | undefined): [string, number][] {\n const counts = new Map<string, number>();\n for (const item of items) {\n const k = key(item);\n if (k === undefined) continue;\n counts.set(k, (counts.get(k) ?? 0) + 1);\n }\n // Descending by count, then by name — deterministic output, because a report that reorders\n // between runs on equal counts cannot be diffed against last month's.\n return [...counts.entries()].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]));\n}\n\nfunction table(title: string, rows: [string, number][], limit = 20): string[] {\n if (rows.length === 0) return [];\n const shown = rows.slice(0, limit);\n const width = Math.max(...shown.map(([name]) => name.length));\n const out = [``, title, ...shown.map(([name, n]) => ` ${name.padEnd(width)} ${String(n).padStart(6)}`)];\n if (rows.length > shown.length) out.push(` … and ${rows.length - shown.length} more`);\n return out;\n}\n\n/**\n * The default rendering: what happened, to what, and what was refused.\n *\n * Denials are reported separately from failures rather than folded into one \"not succeeded\"\n * bucket, because they answer different questions. A failure is the backend or the contract\n * going wrong; a denial is governance doing its job, and an auditor asking \"show me what was\n * refused and why\" is asking about the second one.\n */\nexport function summarize(records: readonly ExecutionRecord[]): string {\n if (records.length === 0) return \"No records matched.\";\n\n const times = records.map((r) => r.metadata.startedAt).sort();\n const denied = records.filter((r) => r.status.phase === \"denied\");\n const lines: string[] = [\n `${records.length} record${records.length === 1 ? \"\" : \"s\"}`,\n ` from ${times[0]}`,\n ` to ${times[times.length - 1]}`,\n ];\n\n lines.push(...table(\"By outcome\", countBy(records, (r) => r.status.phase)));\n lines.push(...table(\"By capability\", countBy(records, (r) => r.metadata.capabilityId)));\n lines.push(...table(\"Denials by reason\", countBy(denied, (r) => r.status.denialReason ?? \"(unstated)\")));\n lines.push(\n ...table(\n \"By principal\",\n countBy(records, (r) => r.spec.principal ?? \"(anonymous)\"),\n ),\n );\n\n return lines.join(\"\\n\");\n}\n","// `archstone doctor` — the pre-production checklist, made runnable (#102).\n//\n// A-7 §5 is a list a human reads before go-live, and a list a human reads is a list a human\n// skips. Everything on it except the two judgement steps is machine-checkable from the manifest\n// and the compiled IR, so it is checked here instead.\n//\n// Deliberately offline: no backend is contacted, nothing is invoked, nothing is uploaded. That\n// is `archstone verify`'s job and it already exists. `doctor` answers the question you ask\n// *before* pointing anything at production — is this manifest wired the way a deployment needs?\n\nimport { readFileSync, existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { IR, IRTool } from \"@archstone/compiler\";\n\nexport type Severity = \"error\" | \"warning\" | \"advisory\";\n\nexport interface Finding {\n severity: Severity;\n /** Stable machine key, so a CI job can allowlist a specific finding without regex-matching prose. */\n code: string;\n capability?: string;\n message: string;\n /** Why it matters — the part that makes a checklist worth reading rather than obeying. */\n because: string;\n}\n\nexport interface DoctorReport {\n findings: Finding[];\n checked: number;\n /** Errors block; warnings and advisories do not. */\n ok: boolean;\n}\n\n/** `${VAR}` (env) and `${caller.x}` — the two interpolations `providers/rest` resolves. */\nconst ENV_INTERP = /\\$\\{[A-Za-z_][A-Za-z0-9_]*\\}/;\nconst CALLER_INTERP = /\\$\\{caller\\./;\n\nfunction baseUrlOf(tool: IRTool): string | undefined {\n return tool.connector?.rest?.baseUrl;\n}\n\n/**\n * Every check is a pure function of the IR plus what is on disk beside it. The manifest\n * directory is needed for exactly two of them — fixture existence and IR drift — and nothing\n * here writes.\n */\nexport function diagnose(ir: IR, manifestDir: string, opts: { builtIr?: string } = {}): DoctorReport {\n const findings: Finding[] = [];\n const add = (f: Finding) => findings.push(f);\n\n for (const tool of ir.tools) {\n const bound = tool.connector !== undefined;\n\n // --- invocability -----------------------------------------------------------------\n if (!bound && tool.lifecycle !== \"retired\") {\n add({\n severity: \"warning\",\n code: \"unbound-capability\",\n capability: tool.id,\n message: \"declared but has no binding, so it is not invocable\",\n because:\n \"A capability with no binding compiles and then does nothing. That is fine while you are drafting and a defect at go-live.\",\n });\n }\n\n // --- contract / fixtures ----------------------------------------------------------\n // #125 (ADD-124 D-10): one trigger condition (`bound && !tool.contract`), two answers,\n // because the honest advice inverts with `effect`. Until this split, `doctor` told you to\n // record a fixture for `tourism.pay` and, fifty lines below, that the same capability must\n // never auto-retry — and `verify` wired into CI is an auto-retry, mechanically. An advisory\n // that recommends a dangerous action is worse than a missing check: it launders the action\n // as reviewed.\n //\n // The `read` branch is byte-identical to what shipped before — same code, same severity,\n // same prose — so no dashboard filtering `no-contract` changes behaviour for a read\n // capability. The non-read branch gets a DISTINCT code so one filtering on `no-contract`\n // cannot silently merge the two (#125's DoD).\n if (bound && !tool.contract && tool.effect === \"read\") {\n add({\n severity: \"warning\",\n code: \"no-contract\",\n capability: tool.id,\n message: \"bound, but records no contract fixture\",\n because:\n \"`archstone verify` replays a recorded fixture against the live backend. With no fixture there is nothing to replay, so backend drift is found by an agent, in front of a customer, instead of by CI.\",\n });\n }\n if (bound && !tool.contract && tool.effect !== \"read\") {\n add({\n // `advisory`, not `warning`: on a `write`/`irreversible` capability, having no contract\n // fixture is now the CORRECT state, not a gap to close. `warning` would keep asking for\n // the thing this advisory exists to stop recommending.\n severity: \"advisory\",\n code: \"no-contract-non-read\",\n capability: tool.id,\n message: `bound and \\`${tool.effect}\\`, so it records no contract fixture — and should not`,\n because:\n \"`archstone verify` replays a recorded fixture as a real invocation, so a fixture here would repeat this capability's effect against the live backend on every CI run. `verify` skips it by default for that reason. Where this capability has a `read` counterpart, cover the drift with that instead — the quote half of a quote → commit pair hits the same host, auth and serialization at zero risk. Not every write has one, and Archstone cannot tell you which capability it is: nothing in CDL declares that relationship. Only if this binding's `${VAR}` genuinely resolves to a sandbox tenant is recording one worthwhile, replayed with `archstone verify --sandbox`: the flag re-includes the binding, it does not make the backend safe.\",\n });\n }\n if (tool.contract?.probeFixture) {\n const fixture = join(manifestDir, tool.contract.probeFixture);\n if (!existsSync(fixture)) {\n add({\n severity: \"error\",\n code: \"missing-fixture-file\",\n capability: tool.id,\n message: `contract names a fixture that is not on disk: ${tool.contract.probeFixture}`,\n because:\n \"The contract points at a file that does not exist, so `verify` cannot run at all — a green pipeline that never checked anything.\",\n });\n }\n }\n if (tool.lifecycle === \"retired\" && tool.contract) {\n add({\n severity: \"advisory\",\n code: \"retired-with-contract\",\n capability: tool.id,\n message: \"is retired but still carries a contract fixture\",\n because:\n \"Retired capabilities are blocked on every surface, so the fixture is dead weight — harmless, but it makes the manifest read as though the capability is still live.\",\n });\n }\n\n // --- egress -----------------------------------------------------------------------\n const baseUrl = baseUrlOf(tool);\n if (baseUrl && CALLER_INTERP.test(baseUrl)) {\n add({\n severity: \"error\",\n code: \"caller-influenced-baseurl\",\n capability: tool.id,\n message: \"baseUrl interpolates caller-supplied data\",\n because:\n \"This is the SSRF shape: a caller who chooses part of the URL chooses where the request goes. Set `allowedHosts` on the provider, which constrains the resolved host to an allowlist.\",\n });\n } else if (baseUrl && ENV_INTERP.test(baseUrl)) {\n add({\n severity: \"advisory\",\n code: \"env-baseurl\",\n capability: tool.id,\n message: `baseUrl comes from the environment (${baseUrl})`,\n because:\n \"Nothing wrong with it — but the deployment, not the manifest, decides where this capability points. Confirm the variable is set to the intended backend in every environment that runs it.\",\n });\n }\n\n // --- effects ----------------------------------------------------------------------\n if (tool.effect === \"irreversible\") {\n add({\n severity: \"advisory\",\n code: \"irreversible-effect\",\n capability: tool.id,\n message: \"is declared `irreversible`\",\n because:\n // #125 (ADD-124 D-12) appends the last sentence — code and severity unchanged. Without\n // it, this advisory and the contract advisory above land on the same capability saying\n // opposite things (\"never auto-retry\" vs \"wire it into CI\"). Naming `verify`'s default\n // here is what makes the two agree wherever a reader starts.\n \"No API description states this, so it was a human judgement: an agent must confirm explicitly and must never auto-retry. Re-read it before go-live — `irreversible` is the difference between looking up a price and charging a card. `archstone verify` applies the same judgement: it will not replay this capability's fixture against the live backend unless you assert a sandbox with --sandbox.\",\n });\n }\n\n // --- governance wiring ------------------------------------------------------------\n if (tool.policyRules?.some((r) => r.rateLimit !== undefined)) {\n add({\n severity: \"advisory\",\n code: \"ratelimit-needs-counter\",\n capability: tool.id,\n message: \"declares a rate limit, which needs a counter supplied at runtime\",\n because:\n \"With no counter the call is denied, fail-closed, at the first invocation. On more than one instance the counter must be shared, or a declared 100/min becomes 100/min per instance.\",\n });\n }\n if (tool.policies?.includes(\"authenticated\")) {\n add({\n severity: \"advisory\",\n code: \"authenticated-needs-principal\",\n capability: tool.id,\n message: \"requires an authenticated caller\",\n because:\n \"The surface serving it must carry a per-request principal — `resolveCaller` on HTTP or the embedded SDK. `archstone serve` (stdio) has one static caller for the whole process, so it cannot serve this capability to more than one identity.\",\n });\n }\n if (tool.lifecycle === \"experimental\") {\n add({\n severity: \"advisory\",\n code: \"experimental-capability\",\n capability: tool.id,\n message: \"is `experimental`: hidden from tool listings but still invocable by id\",\n because:\n \"Deliberate behaviour, and easy to forget: an agent that knows the id can still call it. Confirm that is what you want in production.\",\n });\n }\n }\n\n // --- IR drift ------------------------------------------------------------------------\n if (opts.builtIr !== undefined) {\n const committed = join(manifestDir, \"archstone.ir.json\");\n if (existsSync(committed)) {\n const onDisk = readFileSync(committed, \"utf8\");\n if (onDisk.trim() !== opts.builtIr.trim()) {\n add({\n severity: \"error\",\n code: \"ir-drift\",\n message: \"the committed archstone.ir.json does not match a fresh build of this manifest\",\n because:\n \"The artifact is what runs. A stale one enforces stale policy and exposes stale tools, silently — rebuild it and commit the result.\",\n });\n }\n }\n }\n\n return {\n findings,\n checked: ir.tools.length,\n ok: !findings.some((f) => f.severity === \"error\"),\n };\n}\n\nconst ICON: Record<Severity, string> = { error: \"🔴\", warning: \"🟡\", advisory: \"🔵\" };\n\nexport function formatReport(report: DoctorReport, dir: string): string {\n const lines = [`\\narchstone doctor ${dir}\\n`];\n if (report.findings.length === 0) {\n lines.push(`🟢 ${report.checked} capabilities checked — nothing to flag.\\n`);\n return lines.join(\"\\n\");\n }\n // Errors first: a reader who stops after five lines should have seen what blocks.\n const order: Severity[] = [\"error\", \"warning\", \"advisory\"];\n for (const sev of order) {\n for (const f of report.findings.filter((x) => x.severity === sev)) {\n lines.push(`${ICON[sev]} ${f.capability ? `${f.capability} — ` : \"\"}${f.message}`);\n lines.push(` ${f.because}`);\n lines.push(` (${f.code})\\n`);\n }\n }\n const counts = order.map((s) => `${report.findings.filter((f) => f.severity === s).length} ${s}`).join(\" · \");\n lines.push(`${report.checked} capabilities checked — ${counts}.\\n`);\n return lines.join(\"\\n\");\n}\n","// @archstone/cli — `archstone adopt` (ADD-117 / ADR-0008).\n//\n// ADD-114 made `verify` NAME the fields a provider gained. This is the only way one of them\n// becomes a field a model can use — and it is deliberately a human act. ADR-0008 forbids\n// forwarding an undeclared field; adoption is the sanctioned crossing, with a person at the\n// gate typing a description for each one.\n//\n// A VERB, not `verify --adopt` (D-1). `verify` is a read-only CI gate; a mutating flag on it\n// invites someone to put `--adopt` in a pipeline, which is exactly how ADR-0008 R-1 says this\n// feature fails. There is no `--yes` either (D-2) — `terminalAsk` already aborts cleanly when\n// stdin ends with a question pending, so a piped or CI invocation writes nothing and exits\n// non-zero by construction. That is a property of the shipped gate, not a new guard.\n\nimport { readFileSync, writeFileSync, mkdtempSync, cpSync, rmSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join, resolve } from \"node:path\";\nimport { createInterface } from \"node:readline/promises\";\nimport { load } from \"@archstone/schema\";\nimport { compile, diffShape, validateSemantics, type IRTool, type ShapeMap } from \"@archstone/compiler\";\nimport { Registry } from \"@archstone/emitter-support\";\nimport { recordContract, adoptable, planAdoption, type GoldenFixture } from \"@archstone/runtime\";\nimport { terminalAsk, type Ask } from \"./init\";\nimport { applyAdoption, applyContractRecording, type AdoptionEdit } from \"./adopt-edit\";\n\ninterface Target {\n tool: IRTool;\n resourceFile: string;\n bindingFile: string;\n}\n\n/** Which files hold this capability's resource and binding. Both come from the loader, never\n * from guessing a filename off a resource name. */\nfunction locateFiles(dir: string, tool: IRTool): Target | { problem: string } {\n const res = load(dir);\n const wanted = tool.response?.resource;\n if (!wanted) return { problem: `${tool.id}: no response mapping — nothing to adopt into` };\n\n const bare = wanted.includes(\".\") ? wanted.slice(wanted.lastIndexOf(\".\") + 1) : wanted;\n const doc = res.resourceDocs.find((d) => d.resource.name === wanted || d.resource.name.endsWith(`.${bare}`) || d.resource.name === bare);\n if (!doc) return { problem: `${tool.id}: could not find the file declaring resource '${wanted}'` };\n\n const binding = res.bindings.find((b) => b.binding.capabilityId === tool.id);\n if (!binding) return { problem: `${tool.id}: could not find its binding file` };\n\n return { tool, resourceFile: join(dir, doc.file), bindingFile: join(dir, binding.file) };\n}\n\nfunction readFixture(dir: string, path: string): GoldenFixture | undefined {\n try {\n return JSON.parse(readFileSync(resolve(dir, path), \"utf8\")) as GoldenFixture;\n } catch {\n return undefined;\n }\n}\n\n/** y/N. Anything but an explicit yes is no — the default must never be \"declare it\". */\nasync function confirm(ask: Ask, question: string): Promise<boolean> {\n const answer = (await ask.question(`${question} [y/N] `)).trim().toLowerCase();\n return answer === \"y\" || answer === \"yes\";\n}\n\n/**\n * Prove the edit before keeping it.\n *\n * The modified documents are written into a COPY of the manifest and run through the real\n * loader and compiler — the same pipeline `apply` runs. Nothing reaches the user's files until\n * that passes, so a bug in the surgical append is a refused run rather than a corrupted\n * manifest (ADD-117 Challenge).\n */\nfunction compilesClean(dir: string, resourceFile: string, resourceYaml: string, bindingFile: string, bindingYaml: string): string | undefined {\n const scratch = mkdtempSync(join(tmpdir(), \"archstone-adopt-\"));\n try {\n cpSync(dir, scratch, { recursive: true });\n writeFileSync(join(scratch, resourceFile.slice(dir.length + 1)), resourceYaml);\n writeFileSync(join(scratch, bindingFile.slice(dir.length + 1)), bindingYaml);\n const res = load(scratch);\n if (!res.ok) return res.issues.map((i) => `${i.file}: ${i.message}`).join(\"; \");\n const errors = validateSemantics(res).filter((d) => d.severity === \"error\");\n if (errors.length > 0) return errors.map((e) => e.message).join(\"; \");\n compile(res);\n return undefined;\n } catch (err) {\n return (err as Error).message;\n } finally {\n rmSync(scratch, { recursive: true, force: true });\n }\n}\n\nasync function adoptOne(dir: string, target: Target, contractShape: ShapeMap | undefined, ask: Ask): Promise<number> {\n const { tool } = target;\n const fixture = readFixture(dir, tool.contract!.probeFixture);\n if (!fixture) {\n console.error(` ${tool.id}: fixture not found or unreadable — nothing to replay`);\n return 1;\n }\n\n // ONE request (R-4). The drift and the contract that may be written both describe this\n // response; a second probe could describe a backend that changed in between.\n const recording = await recordContract(tool, fixture.request, {}, {});\n if (recording.outcome !== \"green\" && recording.outcome !== \"yellow\") {\n console.error(` ${tool.id}: ${recording.detail}`);\n return 1;\n }\n const liveShape = recording.shape ?? {};\n\n // A contract with no recorded shape (one written before ADD-114) still works: every path\n // reads as added, and the planner refuses the ones already declared. That is exactly the\n // right answer, and it means adoption does not require a re-record first.\n const drift = diffShape(contractShape ?? {}, liveShape);\n const plan = planAdoption(tool, drift, new Registry(compile(load(dir))).ir.resources);\n\n const offers = adoptable(plan);\n const refused = plan.candidates.filter((c) => !c.adoptable);\n if (refused.length > 0) {\n console.log(`\\n ${tool.id} — not adoptable:`);\n for (const c of refused) if (!c.adoptable) console.log(` · ${c.path} (${c.observed}) — ${c.detail}`);\n }\n if (offers.length === 0) {\n console.log(`\\n ${tool.id} — nothing to adopt.`);\n return 0;\n }\n\n console.log(`\\n ${tool.id} — ${offers.length} field(s) the backend returns and the manifest does not declare:`);\n for (const o of offers) console.log(` · ${o.path} (${o.observed}) → ${o.field}: ${o.semantic}`);\n console.log(\"\");\n\n const edits: AdoptionEdit[] = [];\n for (const o of offers) {\n if (!(await confirm(ask, ` Declare ${o.field} (${o.semantic})?`))) continue;\n const description = (await ask.question(` Describe ${o.field} — an agent reads this to decide whether to use it:\\n > `)).trim();\n if (description === \"\") {\n // D-4: a field with no description is declared but not discoverable, which is Rule #6's\n // letter against its purpose. Refusing is better than shipping a placeholder.\n console.log(` ${o.field}: no description given — not adopted.`);\n continue;\n }\n edits.push({ field: o.field, itemPath: o.itemPath, semantic: o.semantic, description });\n }\n if (edits.length === 0) {\n console.log(`\\n ${tool.id} — nothing adopted.`);\n return 0;\n }\n\n const resourceYaml = readFileSync(target.resourceFile, \"utf8\");\n const bindingYaml = readFileSync(target.bindingFile, \"utf8\");\n const applied = applyAdoption(resourceYaml, bindingYaml, edits);\n if (!applied.ok) {\n console.error(` ${tool.id}: ${applied.problem}`);\n return 1;\n }\n const rewritten = applyContractRecording(applied.binding, recording.fingerprint!, liveShape as Record<string, string>);\n if (!rewritten.ok) {\n console.error(` ${tool.id}: ${rewritten.problem}`);\n return 1;\n }\n\n const problem = compilesClean(dir, target.resourceFile, applied.resource, target.bindingFile, rewritten.binding);\n if (problem) {\n console.error(`\\n ${tool.id}: the edit does not compile — nothing written.\\n ${problem}`);\n return 1;\n }\n\n writeFileSync(target.resourceFile, applied.resource);\n writeFileSync(target.bindingFile, rewritten.binding);\n console.log(`\\n ${tool.id} — declared ${edits.map((e) => e.field).join(\", \")}; contract re-recorded.`);\n return 0;\n}\n\nexport async function runAdoptCmd(argv: string[]): Promise<number> {\n const dir = argv.find((a, i) => i > 0 && !a.startsWith(\"-\"));\n if (!dir) {\n console.error(\"usage: archstone adopt <manifest-dir>\");\n return 2;\n }\n\n const res = load(dir);\n const errors = validateSemantics(res).filter((d) => d.severity === \"error\");\n if (!res.ok || errors.length > 0) {\n console.error(`archstone adopt ${dir}: manifest invalid — run 'archstone apply ${dir}' for details`);\n return 2;\n }\n\n const registry = new Registry(compile(res));\n const targets = registry.listCapabilities().filter((t) => t.contract);\n if (targets.length === 0) {\n console.log(`\\narchstone adopt ${dir}\\n\\n (no bindings declare a contract: — nothing to probe)\\n`);\n return 0;\n }\n\n console.log(`\\narchstone adopt ${dir}`);\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n const ask = terminalAsk(rl);\n let worst = 0;\n try {\n for (const tool of targets) {\n const located = locateFiles(dir, tool);\n if (\"problem\" in located) {\n console.error(` ${located.problem}`);\n worst = Math.max(worst, 1);\n continue;\n }\n worst = Math.max(worst, await adoptOne(dir, located, tool.contract!.shape, ask));\n }\n } catch (err) {\n // `terminalAsk` throws when stdin ends with a question pending — the piped/CI case. Nothing\n // has been written by then: every write happens after the last prompt for that capability.\n console.error(`\\narchstone adopt: no more input — nothing written. Adoption needs a person (${(err as Error).name}).`);\n return 1;\n } finally {\n rl.close();\n }\n console.log(\"\");\n return worst;\n}\n","// @archstone/cli — the surgical half of `archstone adopt` (ADD-117).\n//\n// These manifests are REVIEW SURFACES a human owns, and their comments were written by that\n// human. A YAML library would re-emit them and lose every one — trading the reviewability the\n// product sells for the convenience of the tool that sells it. So this appends text to two\n// known blocks and touches nothing else, byte for byte.\n//\n// Correctness is not argued from the edit; it is PROVED after it. The caller runs the real\n// loader, compiler and probe over the result and keeps nothing if any of them fails, exactly as\n// `init` already works. The blast radius of a bug in here is a refused run.\n\nimport { yamlKey, yamlScalar } from \"@archstone/init\";\nimport type { SemanticType } from \"@archstone/compiler\";\n\nexport interface AdoptionEdit {\n /** The resource field name, e.g. `boardType`. */\n field: string;\n /** The JSONPath written into the binding's `response.map`, relative to a collection item. */\n itemPath: string;\n semantic: SemanticType;\n /** Typed by a human at the gate — never generated (ADD-117 D-4). */\n description: string;\n}\n\nexport type ApplyResult = { ok: true; resource: string; binding: string } | { ok: false; problem: string };\n\n/** One document in, one document out — `applyAdoption`'s two-file result would leave a caller\n * holding an empty `resource` that means nothing. */\nexport type RewriteResult = { ok: true; binding: string } | { ok: false; problem: string };\n\n/** A located block: where its body ends, and the indent its children sit at. */\ninterface Block {\n /** Index of the first line AFTER the block's body — where an append goes. */\n end: number;\n /** The exact leading whitespace a child of this block carries. */\n indent: string;\n}\n\nfunction indentOf(line: string): number {\n return line.length - line.trimStart().length;\n}\n\n/**\n * Locate `key:` as a block header within `[from, to)`, and find where its body ends.\n *\n * REFUSES on anything but exactly one match. Appending to the first of two `map:` blocks\n * would corrupt a manifest in a way that still parses — the failure mode this whole module is\n * built to avoid — so ambiguity is an error, never a choice.\n */\nfunction locate(lines: string[], from: number, to: number, key: string): Block | { problem: string } {\n const header = new RegExp(`^(\\\\s*)${key.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")}:\\\\s*(#.*)?$`);\n const hits: number[] = [];\n for (let i = from; i < to; i++) if (header.test(lines[i])) hits.push(i);\n if (hits.length === 0) return { problem: `could not find a '${key}:' block to append to` };\n if (hits.length > 1) return { problem: `found ${hits.length} '${key}:' blocks; refusing to guess which one to extend` };\n\n const start = hits[0];\n const own = indentOf(lines[start]);\n let end = to;\n for (let i = start + 1; i < to; i++) {\n if (lines[i].trim() === \"\") continue;\n if (indentOf(lines[i]) <= own) {\n end = i;\n break;\n }\n }\n // Back off over trailing blank lines so the append lands inside the block, not after the gap\n // that separates it from whatever follows.\n while (end > start + 1 && lines[end - 1].trim() === \"\") end--;\n\n // Children set the indent; an empty block falls back to the convention every manifest uses.\n let indent = \" \".repeat(own + 2);\n for (let i = start + 1; i < end; i++) {\n if (lines[i].trim() === \"\") continue;\n indent = lines[i].slice(0, indentOf(lines[i]));\n break;\n }\n return { end, indent };\n}\n\nfunction nest(lines: string[], path: string[]): Block | { problem: string } {\n let from = 0;\n let to = lines.length;\n let block: Block | { problem: string } = { problem: \"empty path\" };\n for (const key of path) {\n block = locate(lines, from, to, key);\n if (\"problem\" in block) return block;\n // Descend: the next key must live inside this block's body.\n to = block.end;\n for (let i = from; i < to; i++) {\n const header = new RegExp(`^\\\\s*${key}:\\\\s*(#.*)?$`);\n if (header.test(lines[i])) {\n from = i + 1;\n break;\n }\n }\n }\n return block;\n}\n\nfunction insert(lines: string[], at: number, added: string[]): string[] {\n return [...lines.slice(0, at), ...added, ...lines.slice(at)];\n}\n\n/**\n * Append adopted fields to a resource document and to a binding's response map.\n *\n * `required: false` is written unconditionally (ADD-117 D-3): one observation is not evidence\n * the provider always returns the field, and a wrongly-required field turns the next absent\n * value into a fail-closed VIOLATION on a capability that worked yesterday.\n */\nexport function applyAdoption(resourceYaml: string, bindingYaml: string, edits: AdoptionEdit[]): ApplyResult {\n if (edits.length === 0) return { ok: true, resource: resourceYaml, binding: bindingYaml };\n\n let resourceLines = resourceYaml.split(\"\\n\");\n const fields = nest(resourceLines, [\"resource\", \"fields\"]);\n if (\"problem\" in fields) return { ok: false, problem: `resource: ${fields.problem}` };\n\n const added: string[] = [];\n for (const e of edits) {\n added.push(\n `${fields.indent}${yamlKey(e.field)}:`,\n `${fields.indent} type: ${yamlScalar(e.semantic)}`,\n `${fields.indent} required: false`,\n `${fields.indent} description: ${yamlScalar(e.description)}`,\n );\n }\n resourceLines = insert(resourceLines, fields.end, added);\n\n let bindingLines = bindingYaml.split(\"\\n\");\n const map = nest(bindingLines, [\"binding\", \"response\", \"map\"]);\n if (\"problem\" in map) return { ok: false, problem: `binding: ${map.problem}` };\n bindingLines = insert(\n bindingLines,\n map.end,\n edits.map((e) => `${map.indent}${yamlKey(e.field)}: ${yamlScalar(e.itemPath)}`),\n );\n\n return { ok: true, resource: resourceLines.join(\"\\n\"), binding: bindingLines.join(\"\\n\") };\n}\n\n/**\n * Replace a binding's recorded `fingerprint` and `shape` with a fresh recording.\n *\n * Same surgical posture as `applyAdoption`: these two values are the only ones in the file\n * written by machine rather than by a human, so they are the only ones rewritten. `verifiedAt`\n * is left alone — it is the human-meaningful \"when did we last check\", and `recordContract`\n * already owns stamping it through `init`.\n *\n * Both values come from ONE response (ADD-117 R-4). Recording them from a second probe would\n * let a backend that changed between the two produce a contract describing neither.\n */\nexport function applyContractRecording(bindingYaml: string, fingerprint: string, shape: Record<string, string>): RewriteResult {\n const lines = bindingYaml.split(\"\\n\");\n const fpIdx = lines.findIndex((l) => /^\\s*fingerprint:\\s/.test(l));\n if (fpIdx === -1) return { ok: false, problem: \"binding: no contract fingerprint to update\" };\n\n const indent = lines[fpIdx].slice(0, indentOf(lines[fpIdx]));\n const rendered = [\n `${indent}fingerprint: ${yamlScalar(fingerprint)}`,\n `${indent}shape:`,\n // Sorted, so re-adopting against an unchanged backend is a no-op diff rather than a\n // reshuffle a reviewer has to read.\n ...Object.keys(shape)\n .sort()\n .map((k) => `${indent} ${yamlKey(k)}: ${yamlScalar(shape[k])}`),\n ];\n\n // Drop the previous `shape:` block if there is one, so re-adoption replaces rather than\n // accumulates. Its body is every following line indented deeper than the header.\n const removeFrom = fpIdx;\n let removeTo = fpIdx + 1;\n const shapeIdx = lines.findIndex((l, i) => i > fpIdx && /^\\s*shape:\\s*$/.test(l));\n if (shapeIdx !== -1 && lines.slice(fpIdx + 1, shapeIdx).every((l) => l.trim() === \"\" || l.trim().startsWith(\"#\"))) {\n removeTo = shapeIdx + 1;\n const own = indentOf(lines[shapeIdx]);\n while (removeTo < lines.length && (lines[removeTo].trim() === \"\" || indentOf(lines[removeTo]) > own)) removeTo++;\n // Keep any comment lines that sat between the fingerprint and the shape header.\n const preserved = lines.slice(fpIdx + 1, shapeIdx);\n return {\n ok: true,\n binding: [...lines.slice(0, removeFrom), rendered[0], ...preserved, ...rendered.slice(1), ...lines.slice(removeTo)].join(\"\\n\"),\n };\n }\n\n return { ok: true, binding: [...lines.slice(0, fpIdx), ...rendered, ...lines.slice(fpIdx + 1)].join(\"\\n\") };\n}\n"],"mappings":";;;AA2BA,SAAS,iBAAAA,sBAAqB;AAC9B,SAAS,WAAAC,gBAAe;AACxB,SAAS,qBAAqB;AAC9B,SAAS,oBAA+D;AACxE,SAAS,QAAAC,aAAY;AACrB,SAAS,qBAAAC,oBAAmB,WAAAC,gBAAwB;AACpD,SAAS,YAAAC,WAAU,eAAe,YAAY,iBAAoC;AAClF,SAAS,yBAAyB;;;ACrBlC,SAAS,uBAAuB;AAChC,SAAS,YAAY,cAAc,UAAU,qBAAqB;AAClE,SAAS,SAAS,YAAY,MAAM,UAAU,SAAS,WAAW;AAClE;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,OAOK;AACP,SAAS,eAAe;AAGxB,IAAM,uBAAuB;AActB,IAAM,aAAa;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,EAAE,KAAK,IAAI;AAaJ,SAAS,iBAAiB,UAAkB,KAAiC;AAClF,MAAI,WAAW,GAAG,KAAK,IAAI,MAAM,OAAO,EAAE,SAAS,IAAI,EAAG,QAAO;AACjE,QAAM,OAAO,QAAQ,QAAQ,QAAQ,CAAC;AACtC,QAAM,SAAS,QAAQ,MAAM,GAAG;AAChC,MAAI,WAAW,QAAQ,CAAC,OAAO,WAAW,OAAO,GAAG,EAAG,QAAO;AAC9D,SAAO,WAAW,MAAM,KAAK,SAAS,MAAM,EAAE,OAAO,IAAI,SAAS;AACpE;AAGO,SAAS,WAAW,SAAwB,UAAgE;AACjH,QAAM,QAAqB,EAAE,QAAQ,SAAS,QAAQ,IAAI,GAAG,QAAQ,KAAK,UAAU,UAAU,aAAa,UAAU,MAAM,GAAG,WAAW,CAAC,EAAE;AAC5I,QAAM,aAAuB,CAAC;AAC9B,MAAI,CAAC,QAAQ,WAAY,QAAO,EAAE,OAAO,WAAW;AAEpD,WAAS,QAAQ,GAAG,QAAQ,sBAAsB,SAAS,GAAG;AAC5D,UAAM,SAAS,QAAQ,WAAW,KAAK,EAAE,OAAO,CAAC,QAAQ,MAAM,UAAW,GAAG,MAAM,UAAa,CAAC,WAAW,SAAS,GAAG,CAAC;AACzH,QAAI,OAAO,WAAW,EAAG;AACzB,eAAW,OAAO,QAAQ;AACxB,YAAM,OAAO,iBAAiB,UAAU,GAAG;AAI3C,UAAI,SAAS,OAAW,YAAW,KAAK,GAAG;AAAA,UACtC,OAAM,UAAW,GAAG,IAAI,aAAa,MAAM,MAAM;AAAA,IACxD;AAAA,EACF;AACA,SAAO,EAAE,OAAO,WAAW;AAC7B;AAoCO,SAAS,kBAAkB,OAAiE;AACjG,MAAI,EAAE,iBAAiB,OAAQ,QAAO;AACtC,QAAM,OAAQ,MAA4B;AAC1C,MAAI,MAAM,SAAS,gBAAgB,SAAS,YAAa,QAAO;AAChE,MAAI,SAAS,sBAAuB,QAAO;AAC3C,SAAO;AACT;AA2BO,SAAS,YAAY,IAA4B;AAiBtD,QAAM,aAAa,IAAI,gBAAgB;AACvC,KAAG,OAAO,SAAS,MAAM,WAAW,MAAM,CAAC;AAC3C,SAAO;AAAA,IACL,MAAM,SAAS,MAAc,UAAoC;AAC/D,YAAM,aAAa,aAAa,UAAa,aAAa,KAAK,WAAW;AAC1E,YAAM,SAAS,eAAe,SAAY,OAAO,GAAG,KAAK,QAAQ,CAAC,KAAK,UAAU;AACjF,UAAI;AACJ,UAAI;AACF,iBAAS,MAAM,GAAG,SAAS,QAAQ,EAAE,QAAQ,WAAW,OAAO,CAAC;AAAA,MAClE,SAAS,OAAO;AAOd,cAAM,OAAO,kBAAkB,KAAK;AACpC,YAAI,SAAS,OAAW,OAAM;AAC9B,cAAM,IAAI,kBAAkB,IAAI;AAAA,MAClC;AACA,aAAO,OAAO,KAAK,MAAM,MAAM,eAAe,SAAY,aAAa;AAAA,IACzE;AAAA,EACF;AACF;AAGA,IAAM,oBAAN,cAAgC,MAAM;AAAA,EACpC,YAAqB,MAA2C;AAC9D,UAAM,IAAI;AADS;AAEnB,SAAK,OAAO;AAAA,EACd;AAAA,EAHqB;AAIvB;AAiBA,eAAsB,oBACpB,OACA,IACA,MAC2E;AAC3E,MAAI;AAGF,WAAO,MAAM,QAAQ,OAAO,YAAY,EAAE,GAAG,IAAI;AAAA,EACnD,SAAS,OAAO;AAGd,QAAI,iBAAiB,kBAAmB,QAAO,MAAM;AACrD,UAAM;AAAA,EACR;AACF;AAiBA,IAAM,sBAAsB;AAS5B,eAAe,SACb,KACA,UACA,OACA,WACA,UACwB;AACxB,WAAS,UAAU,GAAG,UAAU,qBAAqB,WAAW,GAAG;AACjE,UAAM,SAAS,OAAO,MAAM,IAAI,SAAS,UAAU,QAAQ,GAAG,KAAK,CAAC;AACpE,QAAI,WAAW,OAAW,QAAO;AACjC,cAAU;AAAA,EACZ;AACA,SAAO;AACT;AAIA,eAAe,QAAQ,KAAU,MAAc,UAAqC;AAClF,QAAM,UAAU,MAAM,IAAI,SAAS,GAAG,IAAI,KAAK,WAAW,QAAQ,KAAK,IAAI,GAAG,KAAK,EAAE,YAAY;AACjG,MAAI,WAAW,GAAI,QAAO;AAC1B,SAAO,OAAO,WAAW,GAAG;AAC9B;AAEA,IAAM,UAAU,oBAAI,IAAY,CAAC,QAAQ,SAAS,cAAc,CAAC;AAYjE,eAAsB,QAAQ,OAAmB,KAAU,MAAqD;AAC9G,QAAM,aAAa,MAAM,IAAI,SAAS,uCAAuC,KAAK,OAAO,GAAG,KAAK;AACjG,MAAI,CAAC,cAAc,KAAK,SAAS,GAAG;AAClC,YAAQ,MAAM,oBAAoB,SAAS,kDAAkD;AAC7F,WAAO;AAAA,EACT;AACA,QAAM,eAAe,MAAM,IAAI,SAAS,2CAA2C,iBAAiB,MAAM,QAAQ,IAAI,CAAC,GAAG,KAAK;AAC/H,QAAM,UAAU,MAAM,IAAI,SAAS,+DAA+D,KAAK,MAAM,GAAG,KAAK;AAMrH,QAAM,YAAY,UAAU,QAAQ,MAAM,GAAG,EAAE,YAAY;AAC3D,QAAM,iBAAiB,MAAM,IAAI,SAAS,yCAAyC,GAAG,SAAS,UAAU,GAAG,KAAK;AACjH,QAAM,eAAe,MAAM,SAAS,UAAa,MAAM,WAAW,KAAK,CAAC,MAAM,EAAE,MAAM,SAAS,QAAQ;AACvG,QAAM,aAAa,gBACd,MAAM,IAAI,SAAS,yDAAyD,GAAG,SAAS,YAAY,GAAG,KAAK,IAC7G;AAEJ,QAAM,YAAkC,CAAC;AACzC,MAAI,UAAU;AAEd,aAAW,CAAC,OAAO,SAAS,KAAK,MAAM,WAAW,QAAQ,GAAG;AAC3D,UAAM,YAA4B;AAClC,UAAM,UAAU,iBAAiB,UAAU,WAAW,KAAK;AAC3D,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAI,IAAI,QAAQ,CAAC,IAAI,MAAM,WAAW,MAAM,KAAK,UAAU,GAAG,EAAE;AACxE,QAAI,QAAS,SAAQ,IAAI,WAAW,OAAO,EAAE;AAC7C,UAAM,WAAW,UAAU,MAAM,OAAO,CAAC,MAAM,EAAE,KAAK,WAAW,aAAa,KAAK,EAAE,SAAS,UAAU;AACxG,eAAW,KAAK,SAAU,SAAQ,IAAI,aAAa,EAAE,IAAI,GAAG,EAAE,SAAS,KAAK,EAAE,MAAM,KAAK,EAAE,EAAE;AAE7F,QAAI,OAAO;AACX,QAAI,CAAC,MAAM;AACT,YAAM,UAAU,MAAM,IAAI,SAAS,2DAA2D,GAAG,KAAK,EAAE,YAAY;AACpH,UAAI,WAAW,KAAK;AAClB,kBAAU;AACV,eAAO;AAAA,MACT,MAAO,QAAO,OAAO,WAAW,GAAG;AAAA,IACrC;AACA,QAAI,CAAC,MAAM;AACT,gBAAU,KAAK,EAAE,WAAW,UAAU,KAAK,MAAM,MAAM,CAAC;AACxD;AAAA,IACF;AAEA,UAAM,SAAS,iBAAiB,UAAU,eAAe;AACzD,UAAM,cAAc,WAAW,MAAM,WAAW,SAAY,GAAG,MAAM,IAAI,MAAM,KAAK;AACpF,UAAM,gBAAgB,MAAM,IAAI,SAAS,0CAA0C,WAAW,GAAG,KAAK;AACtG,QAAI,CAAC,iBAAiB,KAAK,YAAY,GAAG;AACxC,cAAQ,MAAM,YAAY,YAAY,gEAA2D;AACjG,gBAAU,KAAK,EAAE,WAAW,UAAU,KAAK,MAAM,OAAO,MAAM,eAAe,YAAY,yBAAyB,CAAC;AACnH;AAAA,IACF;AAKA,UAAM,UAAU,UAAU,OAAO,YAAY,MAAM,SAAS,UAAU,aAAa,UAAU,WAAW,QAAQ;AAChH,UAAM,SAAS,MAAM;AAAA,MACnB;AAAA,MACA;AAAA,MACA,CAAC,WAAY,QAAQ,IAAI,MAAgB,IAAK,SAAoB;AAAA,MAClE,MAAM,QAAQ,MAAM,mDAAmD;AAAA,MACvE;AAAA,IACF;AACA,QAAI,WAAW,QAAW;AACxB,cAAQ,MAAM,sGAAiG;AAC/G,aAAO;AAAA,IACT;AASA,QAAI;AACJ,UAAM,SAAS,gBAAgB,UAAU,QAAQ;AACjD,QAAI,OAAO,WAAW,SAAS,GAAG;AAShC,cAAQ,IAAI,uCAAuC,OAAO,WAAW,MAAM,qDAAgD;AAC3H,iBAAW,CAACC,QAAOC,UAAS,KAAK,OAAO,WAAW,QAAQ,GAAG;AAC5D,cAAM,QAAQA,WAAU,SAAS,SAAS,4BAA4B;AACtE,gBAAQ,IAAI,aAAaD,SAAQ,CAAC,KAAK,KAAK,KAAKC,WAAU,OAAO,KAAK,IAAI,CAAC,EAAE;AAC9E,gBAAQ,IAAI,iBAAiBA,WAAU,EAAE,GAAG;AAAA,MAC9C;AAIA,YAAM,cAAc,OAAO,WAAW,OAAO,CAAC,MAAM,EAAE,SAAS,YAAY;AAI3E,YAAMC,WAAU,YAAY,WAAW,IAAI,OAAO,OAAO,WAAW,QAAQ,YAAY,CAAC,CAAE,IAAI,CAAC,IAAI;AACpG,YAAM,SAAS,MAAM;AAAA,QACnB;AAAA,QACA,yBAAyB,OAAO,WAAW,MAAM;AAAA,QACjD,CAAC,WAAW;AACV,gBAAMF,SAAQ,OAAO,MAAM;AAC3B,iBAAO,OAAO,UAAUA,MAAK,KAAKA,UAAS,KAAKA,UAAS,OAAO,WAAW,SAASA,SAAQ;AAAA,QAC9F;AAAA,QACA,MAAM,QAAQ,MAAM,0CAA0C,OAAO,WAAW,MAAM,EAAE;AAAA,QACxFE;AAAA,MACF;AACA,UAAI,WAAW,QAAW;AACxB,gBAAQ,MAAM,2GAAsG;AACpH,eAAO;AAAA,MACT;AACA,sBAAgB,OAAO,WAAW,SAAS,CAAC,EAAG;AAAA,IACjD;AAEA,UAAM,gBAAgB,MAAM,IAAI,SAAS,yDAAyD,GAAG,KAAK;AAE1G,UAAM,WAAwD;AAAA,MAC5D,WAAW,UAAU;AAAA,MACrB,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA,GAAI,kBAAkB,SAAY,EAAE,cAAc,IAAI,CAAC;AAAA,MACvD,GAAI,iBAAiB,KAAK,EAAE,aAAa,IAAI,CAAC;AAAA,IAChD;AAEA,QAAI,KAAK,SAAS,SAAS,WAAW,QAAQ;AAC5C,eAAS,QAAQ,MAAM,QAAQ,KAAK,iDAAiD,UAAU,MAAM,yBAAyB,KAAK;AACnI,UAAI,SAAS,OAAO;AAClB,cAAM,SAAS,UAAU,OAAO,YAAY;AAC5C,YAAI,WAAW,SAAS,WAAW,QAAQ;AAIzC,mBAAS,8BAA8B,MAAM;AAAA,YAC3C;AAAA,YACA,WAAW,MAAM;AAAA,YACjB;AAAA,UACF;AAAA,QACF;AAoBA,cAAM,SAAkC,CAAC;AACzC,mBAAW,SAAS,UAAU,OAAO;AACnC,gBAAM,YAAY,QAAQ,MAAM,OAAO,IAAI,OAAO,MAAM,QAAQ,KAAK,IAAI;AACzE,gBAAM,SAAS,cAAc,SAAY,KAAK;AAC9C,gBAAM,WAAW,iBAAiB,MAAM,QAAQ,MAAM,QAAQ,MAAM,OAAO;AAC3E,gBAAM,SAAS,MAAM,IAAI,SAAS,4BAA4B,MAAM,IAAI,GAAG,WAAW,KAAK,aAAa,GAAG,MAAM,KAAK,SAAS,GAAG,KAAK;AACvI,cAAI,UAAU,GAAI,QAAO,MAAM,IAAI,IAAI,OAAO,KAAK;AAAA,QACrD;AACA,YAAI,OAAO,KAAK,MAAM,EAAE,SAAS,EAAG,UAAS,cAAc;AAAA,MAC7D;AAAA,IACF;AACA,cAAU,KAAK,QAAQ;AAAA,EACzB;AAEA,SAAO;AAAA,IACL,SAAS;AAAA,IACT,SAAS,EAAE,IAAI,WAAW,GAAI,gBAAgB,KAAK,EAAE,MAAM,YAAY,IAAI,CAAC,EAAG;AAAA,IAC/E,GAAI,kBAAkB,KAAK,EAAE,cAAc,IAAI,CAAC;AAAA,IAChD,GAAI,eAAe,KAAK,EAAE,WAAW,IAAI,CAAC;AAAA,IAC1C;AAAA,EACF;AACF;AAIA,SAAS,OAAO,MAAuB;AACrC,MAAI;AACF,WAAO,KAAK,MAAM,IAAI;AAAA,EACxB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAMO,SAAS,cAAc,MAA8C;AAC1E,QAAMC,QAAO,CAAC,SAAqC;AACjD,UAAM,MAAM,KAAK,QAAQ,IAAI;AAC7B,WAAO,QAAQ,KAAK,SAAY,KAAK,MAAM,CAAC;AAAA,EAC9C;AACA,QAAM,SAAS,CAAC,SAAS,YAAY,aAAa,eAAe,UAAU;AAC3E,QAAM,WAAW,oBAAI,IAAY;AACjC,aAAW,QAAQ,QAAQ;AACzB,UAAM,MAAM,KAAK,QAAQ,IAAI;AAC7B,QAAI,QAAQ,IAAI;AACd,eAAS,IAAI,GAAG;AAChB,eAAS,IAAI,MAAM,CAAC;AAAA,IACtB;AAAA,EACF;AACA,QAAM,aAAa,KAAK,OAAO,CAAC,GAAG,MAAM,CAAC,SAAS,IAAI,CAAC,KAAK,CAAC,EAAE,WAAW,IAAI,CAAC;AAChF,QAAM,OAAO,WAAW,CAAC;AACzB,MAAI,SAAS,OAAW,QAAO,EAAE,OAAO,0BAA0B;AAClE,QAAM,MAAMA,MAAK,OAAO;AACxB,MAAI,QAAQ,OAAW,QAAO,EAAE,OAAO,0BAA0B;AAEjE,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,GAAIA,MAAK,UAAU,MAAM,SAAY,EAAE,QAAQA,MAAK,UAAU,EAAG,IAAI,CAAC;AAAA,IACtE,GAAIA,MAAK,WAAW,MAAM,SAAY,EAAE,SAASA,MAAK,WAAW,EAAG,IAAI,CAAC;AAAA,IACzE,OAAO,KAAK,SAAS,SAAS;AAAA,IAC9B,GAAIA,MAAK,aAAa,MAAM,SAAY,EAAE,eAAeA,MAAK,aAAa,EAAG,IAAI,CAAC;AAAA,IACnF,aAAa,CAAC,KAAK,SAAS,mBAAmB;AAAA,IAC/C,OAAO,KAAK,SAAS,SAAS;AAAA,IAC9B,GAAIA,MAAK,UAAU,MAAM,SAAY,EAAE,YAAYA,MAAK,UAAU,EAAG,IAAI,CAAC;AAAA,EAC5E;AACF;AAMA,eAAsB,WAAW,MAAiC;AAChE,MAAI,KAAK,SAAS,QAAQ,KAAK,KAAK,SAAS,IAAI,GAAG;AAClD,YAAQ,IAAI,UAAU;AACtB,WAAO;AAAA,EACT;AACA,QAAM,SAAS,cAAc,IAAI;AACjC,MAAI,WAAW,QAAQ;AACrB,YAAQ,MAAM,mBAAmB,OAAO,KAAK;AAAA;AAAA,EAAO,UAAU,EAAE;AAChE,WAAO;AAAA,EACT;AACA,QAAM,OAAO;AAEb,QAAM,WAAW,QAAQ,QAAQ,IAAI,GAAG,KAAK,IAAI;AACjD,MAAI,CAAC,WAAW,QAAQ,GAAG;AACzB,YAAQ,MAAM,iCAAiC,QAAQ,EAAE;AACzD,WAAO;AAAA,EACT;AAEA,QAAM,UAAU;AAChB,QAAM,EAAE,OAAO,WAAW,IAAI,WAAW,SAAS,QAAQ;AAC1D,aAAW,OAAO,YAAY;AAC5B,YAAQ,MAAM,wCAAwC,GAAG,mGAA8F;AAAA,EACzJ;AACA,QAAM,QAAQ,QAAQ,MAAM,KAAK;AAEjC,MAAI,MAAM,WAAW,WAAW,GAAG;AACjC,YAAQ,MAAM,mBAAmB,QAAQ,EAAE,qCAAqC,KAAK,IAAI,GAAG;AAC5F,eAAW,KAAK,MAAM,MAAO,SAAQ,MAAM,OAAO,EAAE,IAAI,GAAG,EAAE,SAAS,KAAK,EAAE,MAAM,KAAK,EAAE,EAAE;AAC5F,WAAO;AAAA,EACT;AAEA,MAAI;AACJ,MAAI,KAAK,kBAAkB,QAAW;AAIpC,UAAM,UAAU,CAAC,KAAK,YAAY,SAAY,cAAc,QAAW,KAAK,WAAW,SAAY,aAAa,MAAS,EAAE;AAAA,MACzH,CAAC,MAAmB,MAAM;AAAA,IAC5B;AACA,QAAI,QAAQ,SAAS,GAAG;AACtB,cAAQ;AAAA,QACN,mBAAmB,QAAQ,KAAK,OAAO,CAAC,IAAI,QAAQ,WAAW,IAAI,OAAO,KAAK;AAAA,IACxE,QAAQ,SAAS,WAAW,IAAI,mCAAmC,EAAE,GAAG,QAAQ,WAAW,IAAI,OAAO,EAAE,GAAG,QAAQ,SAAS,UAAU,IAAI,sEAAsE,EAAE;AAAA,MAC3N;AACA,aAAO;AAAA,IACT;AAEA,QAAIC;AACJ,QAAI;AACF,MAAAA,UAAS,KAAK,MAAM,aAAa,QAAQ,QAAQ,IAAI,GAAG,KAAK,aAAa,GAAG,MAAM,CAAC;AAAA,IACtF,SAAS,KAAK;AACZ,cAAQ,MAAM,oDAAqD,IAAc,OAAO,EAAE;AAC1F,aAAO;AAAA,IACT;AAKA,UAAM,aAAa,uBAAuBA,OAAM;AAChD,QAAI,CAAC,WAAW,IAAI;AAClB,cAAQ,MAAM,0CAA0C,KAAK,aAAa,gBAAgB;AAC1F,iBAAW,WAAW,WAAW,SAAU,SAAQ,MAAM,OAAO,OAAO,EAAE;AACzE,aAAO;AAAA,IACT;AACA,aAAS,WAAW;AAAA,EACtB,WAAW,CAAC,KAAK,aAAa;AAI5B,YAAQ,MAAM,mGAAmG;AACjH,WAAO;AAAA,EACT,OAAO;AACL,UAAM,KAAK,gBAAgB,EAAE,OAAO,QAAQ,OAAO,QAAQ,QAAQ,OAAO,CAAC;AAC3E,QAAI;AACJ,QAAI;AACF,gBAAU,MAAM,oBAAoB,OAAO,IAAI,IAAI;AAAA,IACrD,UAAE;AACA,SAAG,MAAM;AAAA,IACX;AAMA,QAAI,YAAY,iBAAiB;AAI/B,cAAQ,MAAM,sFAAiF;AAC/F,cAAQ,MAAM,wEAAwE;AACtF,aAAO;AAAA,IACT;AACA,QAAI,YAAY,mBAAmB;AACjC,cAAQ,MAAM,4FAAuF;AACrG,aAAO;AAAA,IACT;AACA,aAAS;AACT,QAAI,CAAC,OAAQ,QAAO;AAAA,EACtB;AAEA,QAAM,SAAS,MAAM,QAAQ,OAAO,QAAQ;AAAA,IAC1C,WAAW,QAAQ,QAAQ,IAAI,GAAG,KAAK,GAAG;AAAA,IAC1C,OAAO,KAAK;AAAA,IACZ,OAAO,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQZ,aAAa,KAAK,eAAe,KAAK,kBAAkB;AAAA,EAC1D,CAAC;AAED,QAAM,SAAS,aAAa;AAAA,IAC1B,QAAQ,MAAM,OAAO;AAAA,IACrB,SAAS,MAAM,OAAO;AAAA,IACtB,WAAW,QAAQ,QAAQ,IAAI,GAAG,KAAK,GAAG;AAAA,IAC1C,SAAS,OAAO;AAAA,IAChB,SAAS,OAAO;AAAA,IAChB,UAAU,OAAO;AAAA,IACjB,QAAQ,OAAO,OAAO,IAAI,CAAC,OAAO,EAAE,cAAc,EAAE,cAAc,SAAS,EAAE,SAAS,QAAQ,EAAE,OAAO,EAAE;AAAA,IACzG,eAAe,OAAO;AAAA,IACtB,YAAY,MAAM,WAAW;AAAA,EAC/B,CAAC;AACD,UAAQ,IAAI;AAAA,EAAK,MAAM,EAAE;AAEzB,MAAI,OAAO,IAAI;AAIb,UAAM,aAAa,KAAK,eAAe,SAAY,QAAQ,QAAQ,IAAI,GAAG,KAAK,UAAU,IAAI,KAAK,QAAQ,QAAQ,IAAI,GAAG,KAAK,GAAG,GAAG,gBAAgB;AACpJ,QAAI;AACF,oBAAc,YAAY,MAAM;AAChC,cAAQ,IAAI,0BAA0B,UAAU;AAAA,CAAI;AAAA,IACtD,SAAS,KAAK;AACZ,cAAQ,MAAM,oDAAqD,IAAc,OAAO,EAAE;AAAA,IAC5F;AAAA,EACF;AAEA,SAAO,OAAO,KAAK,IAAI;AACzB;;;ACzrBA,SAAS,gBAAAC,qBAAoB;;;ACgCtB,SAAS,gBAAgB,MAA4B;AAC1D,QAAM,UAA6B,CAAC;AACpC,QAAM,UAA8C,CAAC;AAErD,OAAK,MAAM,IAAI,EAAE,QAAQ,CAAC,KAAK,MAAM;AACnC,UAAM,OAAO,IAAI,KAAK;AACtB,QAAI,CAAC,KAAM;AACX,QAAI;AACJ,QAAI;AACF,eAAS,KAAK,MAAM,IAAI;AAAA,IAC1B,QAAQ;AACN,cAAQ,KAAK,EAAE,MAAM,IAAI,GAAG,QAAQ,iBAAiB,CAAC;AACtD;AAAA,IACF;AACA,UAAM,MAAM;AACZ,QAAI,KAAK,SAAS,eAAe,CAAC,IAAI,YAAY,CAAC,IAAI,QAAQ;AAC7D,cAAQ,KAAK,EAAE,MAAM,IAAI,GAAG,QAAQ,0BAA0B,CAAC;AAC/D;AAAA,IACF;AACA,YAAQ,KAAK,GAAsB;AAAA,EACrC,CAAC;AAED,SAAO,EAAE,SAAS,QAAQ;AAC5B;AAIO,SAAS,YAAY,SAAqC,GAAmC;AAClG,SAAO,QAAQ,OAAO,CAAC,MAAM;AAC3B,QAAI,EAAE,SAAS,EAAE,SAAS,YAAY,EAAE,MAAO,QAAO;AACtD,QAAI,EAAE,SAAS,EAAE,SAAS,aAAa,EAAE,MAAO,QAAO;AACvD,QAAI,EAAE,cAAc,EAAE,SAAS,iBAAiB,EAAE,WAAY,QAAO;AACrE,QAAI,EAAE,SAAS,EAAE,OAAO,UAAU,EAAE,MAAO,QAAO;AAMlD,QAAI,EAAE,aAAa,EAAE,KAAK,cAAc,OAAW,QAAO;AAC1D,QAAI,EAAE,cAAc,UAAa,EAAE,KAAK,cAAc,EAAE,UAAW,QAAO;AAC1E,WAAO;AAAA,EACT,CAAC;AACH;AAEA,IAAM,cAAc;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,SAAS,QAAQ,OAAmC;AAClD,QAAM,IAAI,SAAS;AAGnB,SAAO,SAAS,KAAK,CAAC,IAAI,IAAI,EAAE,QAAQ,MAAM,IAAI,CAAC,MAAM;AAC3D;AAUO,SAAS,MAAM,SAA6C;AACjE,QAAM,OAAO,QAAQ;AAAA,IAAI,CAAC,MACxB;AAAA,MACE,EAAE,SAAS;AAAA,MACX,EAAE,SAAS;AAAA,MACX,EAAE,SAAS;AAAA,MACX,EAAE,SAAS;AAAA,MACX,EAAE,OAAO;AAAA,MACT,EAAE,OAAO;AAAA,MACT,EAAE,KAAK;AAAA,MACP,EAAE,KAAK;AAAA,MACP,EAAE,KAAK,eAAe,KAAK,GAAG;AAAA,MAC9B,EAAE,SAAS;AAAA,MACX,EAAE,SAAS;AAAA,IACb,EACG,IAAI,OAAO,EACX,KAAK,GAAG;AAAA,EACb;AACA,SAAO,CAAC,YAAY,KAAK,GAAG,GAAG,GAAG,IAAI,EAAE,KAAK,IAAI;AACnD;AAEA,SAAS,QAAW,OAAqB,KAA0D;AACjG,QAAM,SAAS,oBAAI,IAAoB;AACvC,aAAW,QAAQ,OAAO;AACxB,UAAM,IAAI,IAAI,IAAI;AAClB,QAAI,MAAM,OAAW;AACrB,WAAO,IAAI,IAAI,OAAO,IAAI,CAAC,KAAK,KAAK,CAAC;AAAA,EACxC;AAGA,SAAO,CAAC,GAAG,OAAO,QAAQ,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC;AACrF;AAEA,SAAS,MAAM,OAAe,MAA0B,QAAQ,IAAc;AAC5E,MAAI,KAAK,WAAW,EAAG,QAAO,CAAC;AAC/B,QAAM,QAAQ,KAAK,MAAM,GAAG,KAAK;AACjC,QAAM,QAAQ,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC,CAAC,IAAI,MAAM,KAAK,MAAM,CAAC;AAC5D,QAAM,MAAM,CAAC,IAAI,OAAO,GAAG,MAAM,IAAI,CAAC,CAAC,MAAM,CAAC,MAAM,KAAK,KAAK,OAAO,KAAK,CAAC,KAAK,OAAO,CAAC,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC;AACxG,MAAI,KAAK,SAAS,MAAM,OAAQ,KAAI,KAAK,gBAAW,KAAK,SAAS,MAAM,MAAM,OAAO;AACrF,SAAO;AACT;AAUO,SAAS,UAAU,SAA6C;AACrE,MAAI,QAAQ,WAAW,EAAG,QAAO;AAEjC,QAAM,QAAQ,QAAQ,IAAI,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,KAAK;AAC5D,QAAM,SAAS,QAAQ,OAAO,CAAC,MAAM,EAAE,OAAO,UAAU,QAAQ;AAChE,QAAM,QAAkB;AAAA,IACtB,GAAG,QAAQ,MAAM,UAAU,QAAQ,WAAW,IAAI,KAAK,GAAG;AAAA,IAC1D,WAAW,MAAM,CAAC,CAAC;AAAA,IACnB,WAAW,MAAM,MAAM,SAAS,CAAC,CAAC;AAAA,EACpC;AAEA,QAAM,KAAK,GAAG,MAAM,cAAc,QAAQ,SAAS,CAAC,MAAM,EAAE,OAAO,KAAK,CAAC,CAAC;AAC1E,QAAM,KAAK,GAAG,MAAM,iBAAiB,QAAQ,SAAS,CAAC,MAAM,EAAE,SAAS,YAAY,CAAC,CAAC;AACtF,QAAM,KAAK,GAAG,MAAM,qBAAqB,QAAQ,QAAQ,CAAC,MAAM,EAAE,OAAO,gBAAgB,YAAY,CAAC,CAAC;AACvG,QAAM;AAAA,IACJ,GAAG;AAAA,MACD;AAAA,MACA,QAAQ,SAAS,CAAC,MAAM,EAAE,KAAK,aAAa,aAAa;AAAA,IAC3D;AAAA,EACF;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;;;AD9KA,IAAM,UAAU,CAAC,WAAW,SAAS,KAAK;AAG1C,SAAS,KAAK,MAAgB,MAAkC;AAC9D,QAAM,IAAI,KAAK,QAAQ,IAAI;AAC3B,SAAO,MAAM,KAAK,SAAY,KAAK,IAAI,CAAC;AAC1C;AAEA,SAAS,UAAU,OAA2B,MAAkC;AAC9E,MAAI,UAAU,OAAW,QAAO;AAIhC,MAAI,CAAC,+BAA+B,KAAK,KAAK,GAAG;AAC/C,YAAQ,MAAM,oBAAoB,IAAI,oFAAoF,KAAK,GAAG;AAClI,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,SAAO;AACT;AAEO,SAAS,kBAAwB;AACtC,UAAQ;AAAA,IACN;AAAA,EAiBF;AACF;AAEO,SAAS,YAAY,MAAwB;AAClD,QAAM,QAAQ,KAAK,MAAM,CAAC,EAAE,OAAO,CAAC,GAAG,GAAG,QAAQ;AAChD,QAAI,EAAE,WAAW,IAAI,EAAG,QAAO;AAC/B,UAAM,OAAO,IAAI,IAAI,CAAC;AACtB,WAAO,EAAE,MAAM,WAAW,IAAI,KAAK,SAAS;AAAA,EAC9C,CAAC;AAED,MAAI,MAAM,WAAW,GAAG;AACtB,oBAAgB;AAChB,WAAO;AAAA,EACT;AAEA,QAAM,SAAU,KAAK,MAAM,UAAU,KAAK;AAC1C,MAAI,CAAC,QAAQ,SAAS,MAAM,GAAG;AAC7B,YAAQ,MAAM,4CAA4C,QAAQ,KAAK,KAAK,CAAC,UAAU,MAAM,GAAG;AAChG,WAAO;AAAA,EACT;AAEA,QAAM,SAAsB;AAAA,IAC1B,OAAO,UAAU,KAAK,MAAM,SAAS,GAAG,SAAS;AAAA,IACjD,OAAO,UAAU,KAAK,MAAM,SAAS,GAAG,SAAS;AAAA,IACjD,YAAY,KAAK,MAAM,cAAc;AAAA,IACrC,WAAW,KAAK,SAAS,aAAa,IAAK,KAAK,MAAM,aAAa,KAAK,KAAM;AAAA,IAC9E,WAAW,KAAK,SAAS,aAAa;AAAA,IACtC,OAAO,KAAK,MAAM,SAAS;AAAA,EAC7B;AAMA,MAAI,OAAO,cAAc,IAAI;AAC3B,YAAQ;AAAA,MACN;AAAA,IAEF;AACA,WAAO;AAAA,EACT;AACA,MAAI,OAAO,aAAa,OAAO,cAAc,QAAW;AACtD,YAAQ,MAAM,wGAAmG;AACjH,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,CAAC;AACjB,MAAI,UAAU;AACd,aAAW,QAAQ,OAAO;AACxB,QAAI;AACJ,QAAI;AACF,aAAOC,cAAa,MAAM,MAAM;AAAA,IAClC,SAAS,KAAK;AACZ,cAAQ,MAAM,iCAAiC,IAAI,MAAO,IAAc,OAAO,EAAE;AACjF,aAAO;AAAA,IACT;AACA,UAAM,UAAU,gBAAgB,IAAI;AACpC,YAAQ,KAAK,GAAG,QAAQ,OAAO;AAG/B,eAAW,KAAK,QAAQ,QAAS,SAAQ,MAAM,oBAAoB,IAAI,IAAI,EAAE,IAAI,mBAAc,EAAE,MAAM,EAAE;AACzG,eAAW,QAAQ,QAAQ;AAAA,EAC7B;AAIA,QAAM,WAAW,YAAY,SAAS,MAAM,EAAE;AAAA,IAAK,CAAC,GAAG,MACrD,EAAE,SAAS,UAAU,cAAc,EAAE,SAAS,SAAS;AAAA,EACzD;AAEA,MAAI,WAAW,QAAS,SAAQ,IAAI,SAAS,IAAI,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC;AAAA,WAC5E,WAAW,MAAO,SAAQ,IAAI,MAAM,QAAQ,CAAC;AAAA,MACjD,SAAQ,IAAI,UAAU,QAAQ,CAAC;AAEpC,MAAI,UAAU,EAAG,SAAQ,MAAM,oBAAoB,OAAO,oCAA+B;AACzF,SAAO;AACT;;;AEnHA,SAAS,gBAAAC,eAAc,cAAAC,mBAAkB;AACzC,SAAS,QAAAC,aAAY;AAuBrB,IAAM,aAAa;AACnB,IAAM,gBAAgB;AAEtB,SAAS,UAAU,MAAkC;AACnD,SAAO,KAAK,WAAW,MAAM;AAC/B;AAOO,SAAS,SAAS,IAAQ,aAAqB,OAA6B,CAAC,GAAiB;AACnG,QAAM,WAAsB,CAAC;AAC7B,QAAM,MAAM,CAAC,MAAe,SAAS,KAAK,CAAC;AAE3C,aAAW,QAAQ,GAAG,OAAO;AAC3B,UAAM,QAAQ,KAAK,cAAc;AAGjC,QAAI,CAAC,SAAS,KAAK,cAAc,WAAW;AAC1C,UAAI;AAAA,QACF,UAAU;AAAA,QACV,MAAM;AAAA,QACN,YAAY,KAAK;AAAA,QACjB,SAAS;AAAA,QACT,SACE;AAAA,MACJ,CAAC;AAAA,IACH;AAcA,QAAI,SAAS,CAAC,KAAK,YAAY,KAAK,WAAW,QAAQ;AACrD,UAAI;AAAA,QACF,UAAU;AAAA,QACV,MAAM;AAAA,QACN,YAAY,KAAK;AAAA,QACjB,SAAS;AAAA,QACT,SACE;AAAA,MACJ,CAAC;AAAA,IACH;AACA,QAAI,SAAS,CAAC,KAAK,YAAY,KAAK,WAAW,QAAQ;AACrD,UAAI;AAAA;AAAA;AAAA;AAAA,QAIF,UAAU;AAAA,QACV,MAAM;AAAA,QACN,YAAY,KAAK;AAAA,QACjB,SAAS,eAAe,KAAK,MAAM;AAAA,QACnC,SACE;AAAA,MACJ,CAAC;AAAA,IACH;AACA,QAAI,KAAK,UAAU,cAAc;AAC/B,YAAM,UAAUA,MAAK,aAAa,KAAK,SAAS,YAAY;AAC5D,UAAI,CAACD,YAAW,OAAO,GAAG;AACxB,YAAI;AAAA,UACF,UAAU;AAAA,UACV,MAAM;AAAA,UACN,YAAY,KAAK;AAAA,UACjB,SAAS,iDAAiD,KAAK,SAAS,YAAY;AAAA,UACpF,SACE;AAAA,QACJ,CAAC;AAAA,MACH;AAAA,IACF;AACA,QAAI,KAAK,cAAc,aAAa,KAAK,UAAU;AACjD,UAAI;AAAA,QACF,UAAU;AAAA,QACV,MAAM;AAAA,QACN,YAAY,KAAK;AAAA,QACjB,SAAS;AAAA,QACT,SACE;AAAA,MACJ,CAAC;AAAA,IACH;AAGA,UAAM,UAAU,UAAU,IAAI;AAC9B,QAAI,WAAW,cAAc,KAAK,OAAO,GAAG;AAC1C,UAAI;AAAA,QACF,UAAU;AAAA,QACV,MAAM;AAAA,QACN,YAAY,KAAK;AAAA,QACjB,SAAS;AAAA,QACT,SACE;AAAA,MACJ,CAAC;AAAA,IACH,WAAW,WAAW,WAAW,KAAK,OAAO,GAAG;AAC9C,UAAI;AAAA,QACF,UAAU;AAAA,QACV,MAAM;AAAA,QACN,YAAY,KAAK;AAAA,QACjB,SAAS,uCAAuC,OAAO;AAAA,QACvD,SACE;AAAA,MACJ,CAAC;AAAA,IACH;AAGA,QAAI,KAAK,WAAW,gBAAgB;AAClC,UAAI;AAAA,QACF,UAAU;AAAA,QACV,MAAM;AAAA,QACN,YAAY,KAAK;AAAA,QACjB,SAAS;AAAA,QACT;AAAA;AAAA;AAAA;AAAA;AAAA,UAKE;AAAA;AAAA,MACJ,CAAC;AAAA,IACH;AAGA,QAAI,KAAK,aAAa,KAAK,CAAC,MAAM,EAAE,cAAc,MAAS,GAAG;AAC5D,UAAI;AAAA,QACF,UAAU;AAAA,QACV,MAAM;AAAA,QACN,YAAY,KAAK;AAAA,QACjB,SAAS;AAAA,QACT,SACE;AAAA,MACJ,CAAC;AAAA,IACH;AACA,QAAI,KAAK,UAAU,SAAS,eAAe,GAAG;AAC5C,UAAI;AAAA,QACF,UAAU;AAAA,QACV,MAAM;AAAA,QACN,YAAY,KAAK;AAAA,QACjB,SAAS;AAAA,QACT,SACE;AAAA,MACJ,CAAC;AAAA,IACH;AACA,QAAI,KAAK,cAAc,gBAAgB;AACrC,UAAI;AAAA,QACF,UAAU;AAAA,QACV,MAAM;AAAA,QACN,YAAY,KAAK;AAAA,QACjB,SAAS;AAAA,QACT,SACE;AAAA,MACJ,CAAC;AAAA,IACH;AAAA,EACF;AAGA,MAAI,KAAK,YAAY,QAAW;AAC9B,UAAM,YAAYC,MAAK,aAAa,mBAAmB;AACvD,QAAID,YAAW,SAAS,GAAG;AACzB,YAAM,SAASD,cAAa,WAAW,MAAM;AAC7C,UAAI,OAAO,KAAK,MAAM,KAAK,QAAQ,KAAK,GAAG;AACzC,YAAI;AAAA,UACF,UAAU;AAAA,UACV,MAAM;AAAA,UACN,SAAS;AAAA,UACT,SACE;AAAA,QACJ,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,SAAS,GAAG,MAAM;AAAA,IAClB,IAAI,CAAC,SAAS,KAAK,CAAC,MAAM,EAAE,aAAa,OAAO;AAAA,EAClD;AACF;AAEA,IAAM,OAAiC,EAAE,OAAO,aAAM,SAAS,aAAM,UAAU,YAAK;AAE7E,SAASG,cAAa,QAAsB,KAAqB;AACtE,QAAM,QAAQ,CAAC;AAAA,mBAAsB,GAAG;AAAA,CAAI;AAC5C,MAAI,OAAO,SAAS,WAAW,GAAG;AAChC,UAAM,KAAK,aAAM,OAAO,OAAO;AAAA,CAA4C;AAC3E,WAAO,MAAM,KAAK,IAAI;AAAA,EACxB;AAEA,QAAM,QAAoB,CAAC,SAAS,WAAW,UAAU;AACzD,aAAW,OAAO,OAAO;AACvB,eAAW,KAAK,OAAO,SAAS,OAAO,CAAC,MAAM,EAAE,aAAa,GAAG,GAAG;AACjE,YAAM,KAAK,GAAG,KAAK,GAAG,CAAC,IAAI,EAAE,aAAa,GAAG,EAAE,UAAU,aAAQ,EAAE,GAAG,EAAE,OAAO,EAAE;AACjF,YAAM,KAAK,MAAM,EAAE,OAAO,EAAE;AAC5B,YAAM,KAAK,OAAO,EAAE,IAAI;AAAA,CAAK;AAAA,IAC/B;AAAA,EACF;AACA,QAAM,SAAS,MAAM,IAAI,CAAC,MAAM,GAAG,OAAO,SAAS,OAAO,CAAC,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC,EAAE,EAAE,KAAK,QAAK;AAC5G,QAAM,KAAK,GAAG,OAAO,OAAO,gCAA2B,MAAM;AAAA,CAAK;AAClE,SAAO,MAAM,KAAK,IAAI;AACxB;;;AClOA,SAAS,gBAAAC,eAAc,iBAAAC,gBAAe,aAAa,QAAQ,cAAc;AACzE,SAAS,cAAc;AACvB,SAAS,QAAAC,OAAM,WAAAC,gBAAe;AAC9B,SAAS,mBAAAC,wBAAuB;AAChC,SAAS,YAAY;AACrB,SAAS,SAAS,WAAW,yBAAqD;AAClF,SAAS,gBAAgB;AACzB,SAAS,gBAAgB,WAAW,oBAAwC;;;ACT5E,SAAS,SAAS,kBAAkB;AA2BpC,SAAS,SAAS,MAAsB;AACtC,SAAO,KAAK,SAAS,KAAK,UAAU,EAAE;AACxC;AASA,SAAS,OAAO,OAAiB,MAAc,IAAY,KAA0C;AACnG,QAAM,SAAS,IAAI,OAAO,UAAU,IAAI,QAAQ,uBAAuB,MAAM,CAAC,cAAc;AAC5F,QAAM,OAAiB,CAAC;AACxB,WAAS,IAAI,MAAM,IAAI,IAAI,IAAK,KAAI,OAAO,KAAK,MAAM,CAAC,CAAC,EAAG,MAAK,KAAK,CAAC;AACtE,MAAI,KAAK,WAAW,EAAG,QAAO,EAAE,SAAS,qBAAqB,GAAG,wBAAwB;AACzF,MAAI,KAAK,SAAS,EAAG,QAAO,EAAE,SAAS,SAAS,KAAK,MAAM,KAAK,GAAG,mDAAmD;AAEtH,QAAM,QAAQ,KAAK,CAAC;AACpB,QAAM,MAAM,SAAS,MAAM,KAAK,CAAC;AACjC,MAAI,MAAM;AACV,WAAS,IAAI,QAAQ,GAAG,IAAI,IAAI,KAAK;AACnC,QAAI,MAAM,CAAC,EAAE,KAAK,MAAM,GAAI;AAC5B,QAAI,SAAS,MAAM,CAAC,CAAC,KAAK,KAAK;AAC7B,YAAM;AACN;AAAA,IACF;AAAA,EACF;AAGA,SAAO,MAAM,QAAQ,KAAK,MAAM,MAAM,CAAC,EAAE,KAAK,MAAM,GAAI;AAGxD,MAAI,SAAS,IAAI,OAAO,MAAM,CAAC;AAC/B,WAAS,IAAI,QAAQ,GAAG,IAAI,KAAK,KAAK;AACpC,QAAI,MAAM,CAAC,EAAE,KAAK,MAAM,GAAI;AAC5B,aAAS,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,MAAM,CAAC,CAAC,CAAC;AAC7C;AAAA,EACF;AACA,SAAO,EAAE,KAAK,OAAO;AACvB;AAEA,SAAS,KAAK,OAAiB,MAA6C;AAC1E,MAAI,OAAO;AACX,MAAI,KAAK,MAAM;AACf,MAAI,QAAqC,EAAE,SAAS,aAAa;AACjE,aAAW,OAAO,MAAM;AACtB,YAAQ,OAAO,OAAO,MAAM,IAAI,GAAG;AACnC,QAAI,aAAa,MAAO,QAAO;AAE/B,SAAK,MAAM;AACX,aAAS,IAAI,MAAM,IAAI,IAAI,KAAK;AAC9B,YAAM,SAAS,IAAI,OAAO,QAAQ,GAAG,cAAc;AACnD,UAAI,OAAO,KAAK,MAAM,CAAC,CAAC,GAAG;AACzB,eAAO,IAAI;AACX;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,OAAO,OAAiB,IAAY,OAA2B;AACtE,SAAO,CAAC,GAAG,MAAM,MAAM,GAAG,EAAE,GAAG,GAAG,OAAO,GAAG,MAAM,MAAM,EAAE,CAAC;AAC7D;AASO,SAAS,cAAc,cAAsB,aAAqB,OAAoC;AAC3G,MAAI,MAAM,WAAW,EAAG,QAAO,EAAE,IAAI,MAAM,UAAU,cAAc,SAAS,YAAY;AAExF,MAAI,gBAAgB,aAAa,MAAM,IAAI;AAC3C,QAAM,SAAS,KAAK,eAAe,CAAC,YAAY,QAAQ,CAAC;AACzD,MAAI,aAAa,OAAQ,QAAO,EAAE,IAAI,OAAO,SAAS,aAAa,OAAO,OAAO,GAAG;AAEpF,QAAM,QAAkB,CAAC;AACzB,aAAW,KAAK,OAAO;AACrB,UAAM;AAAA,MACJ,GAAG,OAAO,MAAM,GAAG,QAAQ,EAAE,KAAK,CAAC;AAAA,MACnC,GAAG,OAAO,MAAM,WAAW,WAAW,EAAE,QAAQ,CAAC;AAAA,MACjD,GAAG,OAAO,MAAM;AAAA,MAChB,GAAG,OAAO,MAAM,kBAAkB,WAAW,EAAE,WAAW,CAAC;AAAA,IAC7D;AAAA,EACF;AACA,kBAAgB,OAAO,eAAe,OAAO,KAAK,KAAK;AAEvD,MAAI,eAAe,YAAY,MAAM,IAAI;AACzC,QAAM,MAAM,KAAK,cAAc,CAAC,WAAW,YAAY,KAAK,CAAC;AAC7D,MAAI,aAAa,IAAK,QAAO,EAAE,IAAI,OAAO,SAAS,YAAY,IAAI,OAAO,GAAG;AAC7E,iBAAe;AAAA,IACb;AAAA,IACA,IAAI;AAAA,IACJ,MAAM,IAAI,CAAC,MAAM,GAAG,IAAI,MAAM,GAAG,QAAQ,EAAE,KAAK,CAAC,KAAK,WAAW,EAAE,QAAQ,CAAC,EAAE;AAAA,EAChF;AAEA,SAAO,EAAE,IAAI,MAAM,UAAU,cAAc,KAAK,IAAI,GAAG,SAAS,aAAa,KAAK,IAAI,EAAE;AAC1F;AAaO,SAAS,uBAAuB,aAAqB,aAAqB,OAA8C;AAC7H,QAAM,QAAQ,YAAY,MAAM,IAAI;AACpC,QAAM,QAAQ,MAAM,UAAU,CAAC,MAAM,qBAAqB,KAAK,CAAC,CAAC;AACjE,MAAI,UAAU,GAAI,QAAO,EAAE,IAAI,OAAO,SAAS,6CAA6C;AAE5F,QAAM,SAAS,MAAM,KAAK,EAAE,MAAM,GAAG,SAAS,MAAM,KAAK,CAAC,CAAC;AAC3D,QAAM,WAAW;AAAA,IACf,GAAG,MAAM,gBAAgB,WAAW,WAAW,CAAC;AAAA,IAChD,GAAG,MAAM;AAAA;AAAA;AAAA,IAGT,GAAG,OAAO,KAAK,KAAK,EACjB,KAAK,EACL,IAAI,CAAC,MAAM,GAAG,MAAM,KAAK,QAAQ,CAAC,CAAC,KAAK,WAAW,MAAM,CAAC,CAAC,CAAC,EAAE;AAAA,EACnE;AAIA,QAAM,aAAa;AACnB,MAAI,WAAW,QAAQ;AACvB,QAAM,WAAW,MAAM,UAAU,CAAC,GAAG,MAAM,IAAI,SAAS,iBAAiB,KAAK,CAAC,CAAC;AAChF,MAAI,aAAa,MAAM,MAAM,MAAM,QAAQ,GAAG,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,MAAM,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,CAAC,GAAG;AACjH,eAAW,WAAW;AACtB,UAAM,MAAM,SAAS,MAAM,QAAQ,CAAC;AACpC,WAAO,WAAW,MAAM,WAAW,MAAM,QAAQ,EAAE,KAAK,MAAM,MAAM,SAAS,MAAM,QAAQ,CAAC,IAAI,KAAM;AAEtG,UAAM,YAAY,MAAM,MAAM,QAAQ,GAAG,QAAQ;AACjD,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,SAAS,CAAC,GAAG,MAAM,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC,GAAG,GAAG,WAAW,GAAG,SAAS,MAAM,CAAC,GAAG,GAAG,MAAM,MAAM,QAAQ,CAAC,EAAE,KAAK,IAAI;AAAA,IAC/H;AAAA,EACF;AAEA,SAAO,EAAE,IAAI,MAAM,SAAS,CAAC,GAAG,MAAM,MAAM,GAAG,KAAK,GAAG,GAAG,UAAU,GAAG,MAAM,MAAM,QAAQ,CAAC,CAAC,EAAE,KAAK,IAAI,EAAE;AAC5G;;;AD1JA,SAAS,YAAY,KAAa,MAA4C;AAC5E,QAAM,MAAM,KAAK,GAAG;AACpB,QAAM,SAAS,KAAK,UAAU;AAC9B,MAAI,CAAC,OAAQ,QAAO,EAAE,SAAS,GAAG,KAAK,EAAE,qDAAgD;AAEzF,QAAM,OAAO,OAAO,SAAS,GAAG,IAAI,OAAO,MAAM,OAAO,YAAY,GAAG,IAAI,CAAC,IAAI;AAChF,QAAM,MAAM,IAAI,aAAa,KAAK,CAAC,MAAM,EAAE,SAAS,SAAS,UAAU,EAAE,SAAS,KAAK,SAAS,IAAI,IAAI,EAAE,KAAK,EAAE,SAAS,SAAS,IAAI;AACvI,MAAI,CAAC,IAAK,QAAO,EAAE,SAAS,GAAG,KAAK,EAAE,iDAAiD,MAAM,IAAI;AAEjG,QAAM,UAAU,IAAI,SAAS,KAAK,CAAC,MAAM,EAAE,QAAQ,iBAAiB,KAAK,EAAE;AAC3E,MAAI,CAAC,QAAS,QAAO,EAAE,SAAS,GAAG,KAAK,EAAE,oCAAoC;AAE9E,SAAO,EAAE,MAAM,cAAcC,MAAK,KAAK,IAAI,IAAI,GAAG,aAAaA,MAAK,KAAK,QAAQ,IAAI,EAAE;AACzF;AAEA,SAAS,YAAY,KAAa,MAAyC;AACzE,MAAI;AACF,WAAO,KAAK,MAAMC,cAAaC,SAAQ,KAAK,IAAI,GAAG,MAAM,CAAC;AAAA,EAC5D,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGA,eAAeC,SAAQ,KAAU,UAAoC;AACnE,QAAM,UAAU,MAAM,IAAI,SAAS,GAAG,QAAQ,SAAS,GAAG,KAAK,EAAE,YAAY;AAC7E,SAAO,WAAW,OAAO,WAAW;AACtC;AAUA,SAAS,cAAc,KAAa,cAAsB,cAAsB,aAAqB,aAAyC;AAC5I,QAAM,UAAU,YAAYH,MAAK,OAAO,GAAG,kBAAkB,CAAC;AAC9D,MAAI;AACF,WAAO,KAAK,SAAS,EAAE,WAAW,KAAK,CAAC;AACxC,IAAAI,eAAcJ,MAAK,SAAS,aAAa,MAAM,IAAI,SAAS,CAAC,CAAC,GAAG,YAAY;AAC7E,IAAAI,eAAcJ,MAAK,SAAS,YAAY,MAAM,IAAI,SAAS,CAAC,CAAC,GAAG,WAAW;AAC3E,UAAM,MAAM,KAAK,OAAO;AACxB,QAAI,CAAC,IAAI,GAAI,QAAO,IAAI,OAAO,IAAI,CAAC,MAAM,GAAG,EAAE,IAAI,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,IAAI;AAC9E,UAAM,SAAS,kBAAkB,GAAG,EAAE,OAAO,CAAC,MAAM,EAAE,aAAa,OAAO;AAC1E,QAAI,OAAO,SAAS,EAAG,QAAO,OAAO,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,IAAI;AACpE,YAAQ,GAAG;AACX,WAAO;AAAA,EACT,SAAS,KAAK;AACZ,WAAQ,IAAc;AAAA,EACxB,UAAE;AACA,WAAO,SAAS,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,EAClD;AACF;AAEA,eAAe,SAAS,KAAa,QAAgB,eAAqC,KAA2B;AACnH,QAAM,EAAE,KAAK,IAAI;AACjB,QAAM,UAAU,YAAY,KAAK,KAAK,SAAU,YAAY;AAC5D,MAAI,CAAC,SAAS;AACZ,YAAQ,MAAM,KAAK,KAAK,EAAE,4DAAuD;AACjF,WAAO;AAAA,EACT;AAIA,QAAM,YAAY,MAAM,eAAe,MAAM,QAAQ,SAAS,CAAC,GAAG,CAAC,CAAC;AACpE,MAAI,UAAU,YAAY,WAAW,UAAU,YAAY,UAAU;AACnE,YAAQ,MAAM,KAAK,KAAK,EAAE,KAAK,UAAU,MAAM,EAAE;AACjD,WAAO;AAAA,EACT;AACA,QAAM,YAAY,UAAU,SAAS,CAAC;AAKtC,QAAM,QAAQ,UAAU,iBAAiB,CAAC,GAAG,SAAS;AACtD,QAAM,OAAO,aAAa,MAAM,OAAO,IAAI,SAAS,QAAQ,KAAK,GAAG,CAAC,CAAC,EAAE,GAAG,SAAS;AAEpF,QAAM,SAAS,UAAU,IAAI;AAC7B,QAAM,UAAU,KAAK,WAAW,OAAO,CAAC,MAAM,CAAC,EAAE,SAAS;AAC1D,MAAI,QAAQ,SAAS,GAAG;AACtB,YAAQ,IAAI;AAAA,IAAO,KAAK,EAAE,wBAAmB;AAC7C,eAAW,KAAK,QAAS,KAAI,CAAC,EAAE,UAAW,SAAQ,IAAI,YAAS,EAAE,IAAI,KAAK,EAAE,QAAQ,YAAO,EAAE,MAAM,EAAE;AAAA,EACxG;AACA,MAAI,OAAO,WAAW,GAAG;AACvB,YAAQ,IAAI;AAAA,IAAO,KAAK,EAAE,2BAAsB;AAChD,WAAO;AAAA,EACT;AAEA,UAAQ,IAAI;AAAA,IAAO,KAAK,EAAE,WAAM,OAAO,MAAM,kEAAkE;AAC/G,aAAW,KAAK,OAAQ,SAAQ,IAAI,YAAS,EAAE,IAAI,KAAK,EAAE,QAAQ,YAAO,EAAE,KAAK,KAAK,EAAE,QAAQ,EAAE;AACjG,UAAQ,IAAI,EAAE;AAEd,QAAM,QAAwB,CAAC;AAC/B,aAAW,KAAK,QAAQ;AACtB,QAAI,CAAE,MAAMG,SAAQ,KAAK,aAAa,EAAE,KAAK,KAAK,EAAE,QAAQ,IAAI,EAAI;AACpE,UAAM,eAAe,MAAM,IAAI,SAAS,cAAc,EAAE,KAAK;AAAA,KAA2D,GAAG,KAAK;AAChI,QAAI,gBAAgB,IAAI;AAGtB,cAAQ,IAAI,KAAK,EAAE,KAAK,4CAAuC;AAC/D;AAAA,IACF;AACA,UAAM,KAAK,EAAE,OAAO,EAAE,OAAO,UAAU,EAAE,UAAU,UAAU,EAAE,UAAU,YAAY,CAAC;AAAA,EACxF;AACA,MAAI,MAAM,WAAW,GAAG;AACtB,YAAQ,IAAI;AAAA,IAAO,KAAK,EAAE,0BAAqB;AAC/C,WAAO;AAAA,EACT;AAEA,QAAM,eAAeF,cAAa,OAAO,cAAc,MAAM;AAC7D,QAAM,cAAcA,cAAa,OAAO,aAAa,MAAM;AAC3D,QAAM,UAAU,cAAc,cAAc,aAAa,KAAK;AAC9D,MAAI,CAAC,QAAQ,IAAI;AACf,YAAQ,MAAM,KAAK,KAAK,EAAE,KAAK,QAAQ,OAAO,EAAE;AAChD,WAAO;AAAA,EACT;AACA,QAAM,YAAY,uBAAuB,QAAQ,SAAS,UAAU,aAAc,SAAmC;AACrH,MAAI,CAAC,UAAU,IAAI;AACjB,YAAQ,MAAM,KAAK,KAAK,EAAE,KAAK,UAAU,OAAO,EAAE;AAClD,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,cAAc,KAAK,OAAO,cAAc,QAAQ,UAAU,OAAO,aAAa,UAAU,OAAO;AAC/G,MAAI,SAAS;AACX,YAAQ,MAAM;AAAA,IAAO,KAAK,EAAE;AAAA,MAAuD,OAAO,EAAE;AAC5F,WAAO;AAAA,EACT;AAEA,EAAAG,eAAc,OAAO,cAAc,QAAQ,QAAQ;AACnD,EAAAA,eAAc,OAAO,aAAa,UAAU,OAAO;AACnD,UAAQ,IAAI;AAAA,IAAO,KAAK,EAAE,oBAAe,MAAM,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,IAAI,CAAC,yBAAyB;AACtG,SAAO;AACT;AAEA,eAAsB,YAAY,MAAiC;AACjE,QAAM,MAAM,KAAK,KAAK,CAAC,GAAG,MAAM,IAAI,KAAK,CAAC,EAAE,WAAW,GAAG,CAAC;AAC3D,MAAI,CAAC,KAAK;AACR,YAAQ,MAAM,uCAAuC;AACrD,WAAO;AAAA,EACT;AAEA,QAAM,MAAM,KAAK,GAAG;AACpB,QAAM,SAAS,kBAAkB,GAAG,EAAE,OAAO,CAAC,MAAM,EAAE,aAAa,OAAO;AAC1E,MAAI,CAAC,IAAI,MAAM,OAAO,SAAS,GAAG;AAChC,YAAQ,MAAM,mBAAmB,GAAG,kDAA6C,GAAG,eAAe;AACnG,WAAO;AAAA,EACT;AAEA,QAAM,WAAW,IAAI,SAAS,QAAQ,GAAG,CAAC;AAC1C,QAAM,UAAU,SAAS,iBAAiB,EAAE,OAAO,CAAC,MAAM,EAAE,QAAQ;AACpE,MAAI,QAAQ,WAAW,GAAG;AACxB,YAAQ,IAAI;AAAA,kBAAqB,GAAG;AAAA;AAAA;AAAA,CAA8D;AAClG,WAAO;AAAA,EACT;AAEA,UAAQ,IAAI;AAAA,kBAAqB,GAAG,EAAE;AACtC,QAAM,KAAKC,iBAAgB,EAAE,OAAO,QAAQ,OAAO,QAAQ,QAAQ,OAAO,CAAC;AAC3E,QAAM,MAAM,YAAY,EAAE;AAC1B,MAAI,QAAQ;AACZ,MAAI;AACF,eAAW,QAAQ,SAAS;AAC1B,YAAM,UAAU,YAAY,KAAK,IAAI;AACrC,UAAI,aAAa,SAAS;AACxB,gBAAQ,MAAM,KAAK,QAAQ,OAAO,EAAE;AACpC,gBAAQ,KAAK,IAAI,OAAO,CAAC;AACzB;AAAA,MACF;AACA,cAAQ,KAAK,IAAI,OAAO,MAAM,SAAS,KAAK,SAAS,KAAK,SAAU,OAAO,GAAG,CAAC;AAAA,IACjF;AAAA,EACF,SAAS,KAAK;AAGZ,YAAQ,MAAM;AAAA,kFAAiF,IAAc,IAAI,IAAI;AACrH,WAAO;AAAA,EACT,UAAE;AACA,OAAG,MAAM;AAAA,EACX;AACA,UAAQ,IAAI,EAAE;AACd,SAAO;AACT;;;ALrKA,SAAS,aAAqB;AAC5B,MAAI;AACF,WAAQ,cAAc,YAAY,GAAG,EAAE,iBAAiB,EAA2B,WAAW;AAAA,EAChG,QAAQ;AAEN,WAAO;AAAA,EACT;AACF;AAMA,SAAS,WAAW,MAAqC;AACvD,QAAM,QAAQ,MAAM,WAAW,QAAQ,QAAQ,QAAQ;AACvD;AAAA;AAAA;AAAA;AAAA,IAIE,snCAcE;AAAA,EACJ;AACF;AAEA,SAAS,SAAS,KAAmB;AACnC,QAAM,MAAMC,MAAK,GAAG;AACpB,UAAQ,IAAI;AAAA,kBAAqB,GAAG;AAAA,CAAI;AAExC,MAAI,IAAI,cAAc;AACpB,UAAM,IAAI,IAAI;AACd,YAAQ,IAAI,gBAAgB,EAAE,QAAQ,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG;AAC9E,YAAQ,IAAI,gBAAgB,EAAE,UAAU,KAAK,IAAI,CAAC,EAAE;AACpD,YAAQ,IAAI,gBAAgB,EAAE,aAAa,MAAM,eAAe;AAAA,EAClE;AACA,UAAQ,IAAI,gBAAgB,IAAI,eAAe,MAAM,qBAAqB,IAAI,SAAS,MAAM,WAAW;AACxG,aAAW,KAAK,IAAI,gBAAgB;AAClC,YAAQ,IAAI,cAAS,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,MAAM,YAAO,EAAE,WAAW,YAAY,GAAG,EAAE;AAAA,EACpG;AAGA,MAAI,IAAI,WAAW,SAAS,GAAG;AAC7B,YAAQ,IAAI,gBAAgB,IAAI,WAAW,MAAM,qBAAqB;AACtE,eAAW,KAAK,IAAI,YAAY;AAC9B,YAAM,SACJ,EAAE,SAAS,UAAU,eACjB,cAAc,EAAE,SAAS,gBAAgB,GAAG,KAC5C,EAAE,SAAS,UAAU,aACnB,YAAY,EAAE,SAAS,YAAY,GAAG,KACtC;AACR,cAAQ,IAAI,cAAS,EAAE,SAAS,EAAE,YAAO,MAAM,EAAE;AAAA,IACnD;AAAA,EACF;AAGA,MAAI,IAAI,OAAO,SAAS,GAAG;AACzB,YAAQ,IAAI;AAAA,WAAS,IAAI,OAAO,MAAM,kBAAkB;AACxD,eAAW,KAAK,IAAI,OAAQ,SAAQ,IAAI,SAAS,EAAE,IAAI,KAAK,EAAE,OAAO,EAAE;AAAA,EACzE,OAAO;AACL,YAAQ,IAAI;AAAA,sBAAoB;AAAA,EAClC;AAGA,QAAM,QAAQC,mBAAkB,GAAG;AACnC,QAAM,SAAS,MAAM,OAAO,CAAC,MAAM,EAAE,aAAa,OAAO;AACzD,QAAM,WAAW,MAAM,OAAO,CAAC,MAAM,EAAE,aAAa,SAAS;AAC7D,UAAQ,IAAI,gBAAgB,OAAO,MAAM,cAAc,SAAS,MAAM,aAAa;AACnF,aAAW,KAAK,OAAQ,SAAQ,IAAI,cAAS,EAAE,OAAO,EAAE;AACxD,aAAW,KAAK,SAAU,SAAQ,IAAI,cAAS,EAAE,OAAO,EAAE;AAE1D,QAAM,uBAAuB,IAAI,MAAM,OAAO,WAAW;AAMzD,QAAM,WAAW,uBAAuB,IAAIC,UAASC,SAAQ,GAAG,CAAC,IAAI;AACrE,QAAM,aAAa,UAAU,sBAAsB,CAAC;AACpD,MAAI,WAAW,SAAS,GAAG;AACzB,YAAQ,IAAI;AAAA,WAAS,WAAW,MAAM,0BAA0B;AAChE,eAAW,KAAK,YAAY;AAC1B,cAAQ,IAAI,oBAAoB,EAAE,IAAI,sCAAiC,EAAE,IAAI,KAAK,IAAI,CAAC,qBAAqB;AAAA,IAC9G;AAAA,EACF;AAEA,QAAM,KAAK,wBAAwB,WAAW,WAAW;AAEzD,MAAI,MAAM,UAAU;AAClB,UAAM,YAAY,SAAS,iBAAiB,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE;AACzE,YAAQ,IAAI,oBAAoB,SAAS,GAAG,OAAO,WAAM,SAAS,IAAI,kBAAkB,SAAS,oBAAoB;AACrH,YAAQ,IAAI;AAAA,gCAA8B,GAAG,eAAe,SAAS,kCAAkC;AAAA,EACzG;AAEA,UAAQ,IAAI,EAAE;AACd,UAAQ,KAAK,KAAK,IAAI,CAAC;AACzB;AAEA,SAAS,SAAS,KAAa,SAAmC;AAChE,QAAM,MAAMH,MAAK,GAAG;AACpB,QAAM,QAAQC,mBAAkB,GAAG;AACnC,QAAM,SAAS,MAAM,OAAO,CAAC,MAAM,EAAE,aAAa,OAAO;AACzD,QAAM,KAAK,IAAI,MAAM,OAAO,WAAW;AAEvC,MAAI,CAAC,IAAI;AACP,YAAQ,MAAM,mBAAmB,GAAG,kDAA6C,GAAG,eAAe;AACnG,eAAW,KAAK,IAAI,OAAQ,SAAQ,MAAM,OAAO,EAAE,IAAI,KAAK,EAAE,OAAO,EAAE;AACvE,eAAW,KAAK,OAAQ,SAAQ,MAAM,OAAO,EAAE,OAAO,EAAE;AACxD,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,KAAKE,SAAQ,GAAG;AAOtB,QAAM,WAAW,IAAID,UAAS,EAAE;AAChC,MAAI,SAAS,mBAAmB,SAAS,GAAG;AAC1C,YAAQ,MAAM,mBAAmB,GAAG,6DAAwD;AAC5F,eAAW,KAAK,SAAS,oBAAoB;AAC3C,cAAQ,MAAM,kBAAkB,EAAE,IAAI,sCAAiC,EAAE,IAAI,KAAK,IAAI,CAAC,qBAAqB;AAAA,IAC9G;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AAcA,QAAM,WAAe,EAAE,GAAG,IAAI,OAAO,GAAG,MAAM,IAAI,CAAC,EAAE,UAAU,WAAW,GAAG,EAAE,MAAM,CAAC,EAAE;AAExF,QAAM,UAAUE,SAAQ,QAAQ,IAAI,GAAG,WAAW,mBAAmB;AACrE,EAAAC,eAAc,SAAS,GAAG,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC;AAAA,CAAI;AAC/D,UAAQ,IAAI,mBAAmB,GAAG,WAAM,OAAO,KAAK,SAAS,MAAM,MAAM,WAAW;AACpF,UAAQ,KAAK,CAAC;AAChB;AAEA,SAAS,aAAa,KAAa,MAAc,OAAiC;AAKhF,MAAI,CAAC,OAAO;AACV,YAAQ;AAAA,MACN;AAAA,IACF;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,QAAQ,cAAc,GAAG;AAC/B,MAAI,CAAC,MAAM,MAAM,CAAC,MAAM,UAAU;AAChC,YAAQ,MAAM,4BAA4B,GAAG,4BAAuB;AACpE,eAAW,KAAK,MAAM,OAAQ,SAAQ,MAAM,OAAO,EAAE,IAAI,KAAK,EAAE,OAAO,EAAE;AACzE,eAAW,KAAK,MAAM,YAAY,OAAO,CAAC,MAAM,EAAE,aAAa,OAAO,EAAG,SAAQ,MAAM,OAAO,EAAE,OAAO,EAAE;AACzG,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,UAAU,kBAAkB,MAAM,UAAU,EAAE,aAAa,MAAM,CAAC;AACxE,QAAM,SAAS,aAAa,CAAC,KAAK,QAAQ;AAQxC,sBAAkB,SAAS,KAAK,GAAG,EAAE,MAAM,CAAC,QAAiB;AAC3D,cAAQ,MAAM,0DAAqD,GAAG;AACtE,yBAAmB,KAAK,GAAG;AAAA,IAC7B,CAAC;AAAA,EACH,CAAC;AACD,SAAO,OAAO,MAAM,MAAM;AACxB,YAAQ,MAAM,wDAAwD,IAAI,wBAAwB;AAAA,EACpG,CAAC;AACH;AAiBA,IAAM,yBAAyB,IAAI,OAAO;AAY1C,IAAM,+BAA+B,KAAK,OAAO;AACjD,IAAM,yBAAyB;AA4C/B,SAAS,oBAAoB,KAA2B;AACtD,QAAM,SAAS,IAAI;AAGnB,MAAI,CAAC,UAAU,IAAI,eAAe,IAAI,iBAAiB,IAAI,aAAa,OAAO,WAAW;AACxF,uBAAmB,KAAK,KAAK,EAAE,iBAAiB,KAAK,CAAC;AACtD;AAAA,EACF;AACA,MAAI;AACF,QAAI,aAAa,MAAM;AAIvB,WAAO,MAAM,kFAAkF;AAC/F,WAAO,IAAI;AAEX,QAAI,YAAY;AAChB,WAAO,GAAG,QAAQ,CAAC,UAAkB;AACnC,mBAAa,MAAM;AACnB,UAAI,YAAY,6BAA8B,QAAO,QAAQ;AAAA,IAC/D,CAAC;AACD,WAAO,OAAO;AAGd,WAAO,GAAG,SAAS,MAAM,OAAO,QAAQ,CAAC;AACzC,UAAM,SAAS,WAAW,MAAM,OAAO,QAAQ,GAAG,sBAAsB;AACxE,WAAO,MAAM;AACb,WAAO,GAAG,SAAS,MAAM,aAAa,MAAM,CAAC;AAAA,EAC/C,QAAQ;AAGN,QAAI;AACF,aAAO,QAAQ;AAAA,IACjB,QAAQ;AAAA,IAER;AAAA,EACF;AACF;AAUA,SAAS,mBACP,KACA,QACA,OAAsC,CAAC,GACjC;AACN,MAAI;AACF,QAAI,IAAI,iBAAiB,IAAI,UAAW;AACxC,QAAI,CAAC,IAAI,aAAa;AACpB,UAAI,aAAa;AAMjB,UAAI,KAAK,gBAAiB,KAAI,UAAU,cAAc,OAAO;AAAA,IAC/D;AACA,QAAI,IAAI;AAAA,EACV,QAAQ;AAAA,EAGR;AACF;AAaA,eAAe,kBACb,SACA,KACA,KACe;AAcf,QAAM,WAAW,OAAO,IAAI,QAAQ,gBAAgB,CAAC;AACrD,MAAI,OAAO,SAAS,QAAQ,KAAK,WAAW,wBAAwB;AAQlE,wBAAoB,GAAG;AACvB;AAAA,EACF;AAEA,QAAM,SAAmB,CAAC;AAyB1B,QAAM,OAAO,MAAM,IAAI,QAAwC,CAAC,WAAW;AACzE,QAAI,WAAW;AACf,QAAI,OAAO;AACX,UAAM,SAAS,CAAC,YAAkD;AAChE,UAAI,KAAM;AACV,aAAO;AACP,UAAI,IAAI,QAAQ,MAAM;AACtB,UAAI,IAAI,OAAO,KAAK;AACpB,UAAI,IAAI,SAAS,OAAO;AACxB,UAAI,IAAI,SAAS,OAAO;AACxB,aAAO,OAAO;AAAA,IAChB;AACA,UAAM,SAAS,CAAC,UAAwB;AACtC,kBAAY,MAAM;AAClB,UAAI,WAAW,wBAAwB;AAErC,eAAO,SAAS;AAChB,eAAO,WAAW;AAClB;AAAA,MACF;AACA,aAAO,KAAK,KAAK;AAAA,IACnB;AACA,UAAM,QAAQ,MAAY,OAAO,IAAI;AAKrC,UAAM,UAAU,MAAY,OAAO,SAAS;AAM5C,UAAM,UAAU,MAAY,OAAO,SAAS;AAC5C,QAAI,GAAG,QAAQ,MAAM;AACrB,QAAI,GAAG,OAAO,KAAK;AACnB,QAAI,GAAG,SAAS,OAAO;AACvB,QAAI,GAAG,SAAS,OAAO;AAAA,EACzB,CAAC;AAED,MAAI,SAAS,aAAa;AAIxB,wBAAoB,GAAG;AACvB;AAAA,EACF;AACA,MAAI,SAAS,WAAW;AAetB,uBAAmB,KAAK,GAAG;AAC3B;AAAA,EACF;AAaA,MAAI;AACJ,MAAI;AACF,UAAM,UAAU,IAAI,QAAQ;AAC5B,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,IAAI,OAAO,GAAG;AACtD,UAAI,UAAU,OAAW,SAAQ,IAAI,KAAK,MAAM,QAAQ,KAAK,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK;AAAA,IAC3F;AACA,UAAM,UAAU,IAAI,WAAW,SAAS,IAAI,WAAW,UAAU,OAAO,SAAS;AACjF,cAAU,IAAI,QAAQ,UAAU,IAAI,QAAQ,QAAQ,WAAW,GAAG,IAAI,OAAO,GAAG,IAAI;AAAA,MAClF,QAAQ,IAAI,UAAU;AAAA,MACtB;AAAA,MACA,MAAM,UAAU,OAAO,OAAO,MAAM,IAAI;AAAA,IAC1C,CAAC;AAAA,EACH,QAAQ;AACN,uBAAmB,KAAK,GAAG;AAC3B;AAAA,EACF;AAEA,MAAI;AACF,UAAM,WAAW,MAAM,QAAQ,OAAO;AACtC,QAAI,aAAa,SAAS;AAC1B,aAAS,QAAQ,QAAQ,CAAC,OAAO,QAAQ,IAAI,UAAU,KAAK,KAAK,CAAC;AAClE,QAAI,IAAI,SAAS,OAAO,OAAO,KAAK,MAAM,SAAS,YAAY,CAAC,IAAI,MAAS;AAAA,EAC/E,SAAS,KAAK;AAMZ,YAAQ,MAAM,0DAAqD,GAAG;AACtE,uBAAmB,KAAK,GAAG;AAAA,EAC7B;AACF;AAEA,IAAM,cAA4C,EAAE,OAAO,aAAM,QAAQ,aAAM,KAAK,YAAK;AAIzF,IAAM,YAAY;AAYlB,IAAM,gBACJ;AAMF,eAAe,aAAa,KAAa,MAAe,SAAiC;AACvF,QAAM,MAAML,MAAK,GAAG;AACpB,QAAM,QAAQC,mBAAkB,GAAG;AACnC,QAAM,SAAS,MAAM,OAAO,CAAC,MAAM,EAAE,aAAa,OAAO;AACzD,QAAM,KAAK,IAAI,MAAM,OAAO,WAAW;AACvC,MAAI,CAAC,IAAI;AACP,QAAI,MAAM;AAGR,cAAQ,IAAI,KAAK,UAAU,EAAE,OAAO,oBAAoB,QAAQ,IAAI,QAAQ,OAAO,CAAC,CAAC;AAAA,IACvF,OAAO;AACL,cAAQ,MAAM,oBAAoB,GAAG,kDAA6C,GAAG,eAAe;AAAA,IACtG;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,WAAW,IAAIC,UAASC,SAAQ,GAAG,CAAC;AAO1C,QAAM,EAAE,SAAS,QAAQ,IAAI,UACzB,MAAM,UAAU,SAAS,iBAAiB,GAAG,KAAK,SAAS,GAAG,WAAW,QAAW,EAAE,gBAAgB,KAAK,CAAC,IAC5G,MAAM,UAAU,SAAS,iBAAiB,GAAG,KAAK,SAAS,GAAG,SAAS;AAM3E,QAAM,WAAW,QAAQ,KAAK,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,IAAI;AAE/D,MAAI,MAAM;AAOR,YAAQ,IAAI,KAAK,UAAU,EAAE,SAAS,SAAS,QAAQ,CAAC,CAAC;AACzD,YAAQ,KAAK,QAAQ;AAAA,EACvB;AAEA,UAAQ,IAAI;AAAA,mBAAsB,GAAG;AAAA,CAAI;AACzC,MAAI,QAAQ,WAAW,KAAK,QAAQ,WAAW,GAAG;AAChD,YAAQ,IAAI,gEAA2D;AACvE,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,aAAW,KAAK,SAAS;AACvB,YAAQ,IAAI,KAAK,YAAY,EAAE,MAAM,CAAC,IAAI,EAAE,YAAY,WAAM,EAAE,MAAM,EAAE;AAAA,EAC1E;AACA,aAAW,KAAK,SAAS;AACvB,YAAQ,IAAI,KAAK,SAAS,IAAI,EAAE,YAAY,WAAM,EAAE,MAAM,EAAE;AAAA,EAC9D;AACA,MAAI,QAAQ,SAAS,GAAG;AACtB,YAAQ,IAAI;AAAA,IAAO,QAAQ,MAAM,oDAAoD;AACrF,YAAQ,IAAI,aAAa;AAAA,EAC3B;AACA,UAAQ,IAAI,EAAE;AACd,UAAQ,KAAK,QAAQ;AACvB;AAIA,SAAS,QAAQ,MAAgB,MAA+C;AAC9E,QAAM,MAAM,KAAK,QAAQ,IAAI;AAC7B,SAAO,EAAE,OAAO,QAAQ,KAAK,KAAK,MAAM,CAAC,IAAI,QAAW,IAAI;AAC9D;AAQA,SAAS,UAAU,KAAa,MAAqB;AACnD,QAAM,MAAMH,MAAK,GAAG;AACpB,QAAM,QAAQC,mBAAkB,GAAG;AACnC,QAAM,SAAS,MAAM,OAAO,CAAC,MAAM,EAAE,aAAa,OAAO;AACzD,MAAI,CAAC,IAAI,MAAM,OAAO,SAAS,GAAG;AAChC,YAAQ,MAAM,oBAAoB,GAAG,kDAA6C,GAAG,eAAe;AACpG,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,KAAKE,SAAQ,GAAG;AAItB,QAAM,WAAe,EAAE,GAAG,IAAI,OAAO,GAAG,MAAM,IAAI,CAAC,EAAE,UAAU,WAAW,GAAG,EAAE,MAAM,CAAC,EAAE;AACxF,QAAM,SAAS,SAAS,IAAI,KAAK,EAAE,SAAS,GAAG,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC;AAAA,EAAK,CAAC;AAEtF,UAAQ,IAAI,OAAO,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAIG,cAAa,QAAQ,GAAG,CAAC;AAC9E,UAAQ,KAAK,OAAO,KAAK,IAAI,CAAC;AAChC;AAEA,eAAe,OAAsB;AACnC,QAAM,OAAO,QAAQ,KAAK,MAAM,CAAC;AAMjC,MAAI,KAAK,SAAS,WAAW,KAAK,KAAK,SAAS,IAAI,GAAG;AACrD,YAAQ,IAAI,WAAW,CAAC;AACxB;AAAA,EACF;AACA,MAAI,KAAK,SAAS,QAAQ,KAAK,KAAK,SAAS,IAAI,GAAG;AAClD,eAAW;AACX;AAAA,EACF;AAEA,QAAM,OAAO,KAAK,SAAS,QAAQ;AACnC,QAAM,OAAO,KAAK,SAAS,QAAQ;AAOnC,QAAM,UAAU,KAAK,SAAS,WAAW;AACzC,QAAM,MAAM,QAAQ,MAAM,OAAO;AACjC,QAAM,OAAO,QAAQ,MAAM,QAAQ;AACnC,QAAM,QAAQ,QAAQ,MAAM,SAAS;AAErC,QAAM,WAAW,oBAAI,IAAY;AACjC,aAAW,KAAK,CAAC,KAAK,MAAM,KAAK,GAAG;AAClC,QAAI,EAAE,QAAQ,IAAI;AAChB,eAAS,IAAI,EAAE,GAAG;AAClB,eAAS,IAAI,EAAE,MAAM,CAAC;AAAA,IACxB;AAAA,EACF;AACA,QAAM,aAAa,KAAK,OAAO,CAAC,GAAG,MAAM,CAAC,SAAS,IAAI,CAAC,KAAK,MAAM,YAAY,MAAM,YAAY,MAAM,WAAW;AAClH,QAAM,CAAC,KAAK,GAAG,IAAI;AAEnB,MAAI,QAAQ,WAAW,KAAK;AAC1B,aAAS,GAAG;AACZ;AAAA,EACF;AACA,MAAI,QAAQ,WAAW,OAAO,MAAM;AAGlC,iBAAa,KAAK,OAAO,KAAK,SAAS,IAAI,GAAG,MAAM,SAAS,QAAQ,IAAI,oBAAoB;AAC7F;AAAA,EACF;AACA,MAAI,QAAQ,WAAW,KAAK;AAC1B,UAAM,WAAW,GAAG;AACpB;AAAA,EACF;AACA,MAAI,QAAQ,YAAY,KAAK;AAC3B,UAAM,aAAa,KAAK,MAAM,OAAO;AACrC;AAAA,EACF;AACA,MAAI,QAAQ,WAAW,KAAK;AAC1B,aAAS,KAAK,IAAI,KAAK;AACvB;AAAA,EACF;AACA,MAAI,QAAQ,YAAY,KAAK;AAC3B,cAAU,KAAK,IAAI;AACnB;AAAA,EACF;AACA,MAAI,QAAQ,SAAS;AAGnB,YAAQ,KAAK,MAAM,YAAY,IAAI,CAAC;AAAA,EACtC;AACA,MAAI,QAAQ,SAAS;AAInB,YAAQ,KAAK,YAAY,IAAI,CAAC;AAAA,EAChC;AACA,MAAI,QAAQ,QAAQ;AAIlB,YAAQ,KAAK,MAAM,WAAW,IAAI,CAAC;AAAA,EACrC;AAEA,aAAW,EAAE,UAAU,KAAK,CAAC;AAC7B,UAAQ,KAAK,CAAC;AAChB;AAEA,KAAK;","names":["writeFileSync","resolve","load","validateSemantics","compile","Registry","index","candidate","prefill","flag","parsed","readFileSync","readFileSync","readFileSync","existsSync","join","formatReport","readFileSync","writeFileSync","join","resolve","createInterface","join","readFileSync","resolve","confirm","writeFileSync","createInterface","load","validateSemantics","Registry","compile","resolve","writeFileSync","formatReport"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@archstone/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Archstone CLI — compile a business capability definition (CDL) into tools an AI agent can call: apply, build, serve over MCP, and verify against the live backend.",
|
|
@@ -37,11 +37,11 @@
|
|
|
37
37
|
"access": "public"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@archstone/compiler": "0.
|
|
41
|
-
"@archstone/
|
|
42
|
-
"@archstone/
|
|
43
|
-
"@archstone/
|
|
44
|
-
"@archstone/schema": "0.
|
|
40
|
+
"@archstone/compiler": "0.20.0",
|
|
41
|
+
"@archstone/emitter-support": "0.20.0",
|
|
42
|
+
"@archstone/init": "0.20.0",
|
|
43
|
+
"@archstone/runtime": "0.20.0",
|
|
44
|
+
"@archstone/schema": "0.20.0"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"tsup": "^8.5.1"
|