@abaigram/abai-stub 0.1.0 → 0.2.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/entry.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"entry.js","sourceRoot":"","sources":["../src/entry.ts"],"names":[],"mappings":"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","sourcesContent":["// The standard agent entry (abaigrammar section 4.4), the part the stub\n// provides itself: `<prog> abai manifest` prints the effective manifest and\n// `<prog> abai doctor` runs the offline conformance checks. The verbs that\n// need a harness (session, install, config, mcp, run) are delegated once a\n// harness binding exists; until then the usage says so. Never throws;\n// resolves to the exit code.\nimport { spawn } from \"node:child_process\";\nimport { accessSync, constants, existsSync, readFileSync, statSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { findRoot, MANIFEST_FILE } from \"./content.ts\";\nimport { ENV_HARNESS, ENV_MODE, expandHome } from \"./env.ts\";\nimport { validateManifest } from \"./manifest/manifest.ts\";\nimport { parseManifestYaml, renderManifestYaml } from \"./manifest/render.ts\";\nimport { type Abaigram, harnessBinary, importHarnessModule } from \"./program.ts\";\n\nexport const STUB_VERSION = \"0.1.0\";\n\nexport type CheckStatus = \"ok\" | \"fail\" | \"skip\";\n\nexport interface DoctorCheck {\n\tname: string;\n\tstatus: CheckStatus;\n\tdetail: string;\n}\n\nexport interface DoctorReport {\n\tok: boolean;\n\troot: string | null;\n\tchecks: DoctorCheck[];\n}\n\n/** Where the entry writes; injectable for tests. */\nexport interface EntryIo {\n\tout(text: string): void;\n\terr(text: string): void;\n\tenv: NodeJS.ProcessEnv;\n\tcwd: string;\n}\n\nexport const processIo: EntryIo = {\n\tout: (text) => {\n\t\tprocess.stdout.write(text);\n\t},\n\terr: (text) => {\n\t\tprocess.stderr.write(`${text}\\n`);\n\t},\n\tenv: process.env,\n\tget cwd() {\n\t\treturn process.cwd();\n\t},\n};\n\nfunction errorMessage(error: unknown): string {\n\treturn error instanceof Error ? error.message : String(error);\n}\n\nfunction usageLines(entry: string): string[] {\n\treturn [\n\t\t`usage: ${entry} open a session`,\n\t\t` ${entry} install run the install touchpoint`,\n\t\t` ${entry} manifest [--json] print the effective manifest`,\n\t\t` ${entry} doctor [--root <dir>] [--offline] [--json]`,\n\t\t` ${entry} config [set ...] the machine-level model configuration`,\n\t\t` ${entry} mcp serve the agent's tools to an MCP client over stdio`,\n\t\t` ${entry} run [--auto] -- ARGS the harness starts this program as its supervised child`,\n\t\t\"\",\n\t\t\"doctor offline conformance checks: the effective manifest, the checked-in\",\n\t\t` ${MANIFEST_FILE}, the identity content, the modes, the audit directory`,\n\t\t\"\",\n\t\t\"session and install attach a harness and return when none can attach; mcp needs no model,\",\n\t\t\"since the client's own agent is this program's; run is always sidecar launch, with the whole\",\n\t\t\"lifecycle channel and the program's output observed from outside.\",\n\t];\n}\n\ninterface Flags {\n\tjson: boolean;\n\troot: string | undefined;\n\toffline: boolean;\n}\n\n/** `--flag`, `--flag value` and `--flag=value`; anything else is a usage error. */\nfunction parseFlags(args: string[], allowed: readonly string[]): Flags | string {\n\tconst flags: Flags = { json: false, root: undefined, offline: false };\n\tfor (let i = 0; i < args.length; i++) {\n\t\tconst arg = args[i];\n\t\tconst eq = arg.indexOf(\"=\");\n\t\tconst name = eq === -1 ? arg : arg.slice(0, eq);\n\t\tif (!allowed.includes(name)) return `unknown option ${arg}`;\n\t\tconst takeValue = (): string | undefined => {\n\t\t\tif (eq !== -1) return arg.slice(eq + 1);\n\t\t\ti += 1;\n\t\t\treturn args[i];\n\t\t};\n\t\tswitch (name) {\n\t\t\tcase \"--json\":\n\t\t\t\tflags.json = true;\n\t\t\t\tbreak;\n\t\t\tcase \"--offline\":\n\t\t\t\tflags.offline = true;\n\t\t\t\tbreak;\n\t\t\tcase \"--root\": {\n\t\t\t\tconst value = takeValue();\n\t\t\t\tif (value === undefined || value === \"\") return \"--root needs a directory\";\n\t\t\t\tflags.root = value;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\treturn `unknown option ${arg}`;\n\t\t}\n\t}\n\treturn flags;\n}\n\n/** The first line at which two texts differ (1-based), or undefined when equal. */\nexport function firstDifferingLine(a: string, b: string): number | undefined {\n\tif (a === b) return undefined;\n\tconst linesA = a.split(\"\\n\");\n\tconst linesB = b.split(\"\\n\");\n\tconst n = Math.max(linesA.length, linesB.length);\n\tfor (let i = 0; i < n; i++) {\n\t\tif (linesA[i] !== linesB[i]) return i + 1;\n\t}\n\treturn n;\n}\n\n/** The first existing ancestor of a path (the path itself included). */\nfunction existingAncestor(path: string): string {\n\tlet current = path;\n\twhile (!existsSync(current)) {\n\t\tconst parent = dirname(current);\n\t\tif (parent === current) break;\n\t\tcurrent = parent;\n\t}\n\treturn current;\n}\n\n/** The offline half of `doctor` (section 4.4), plus the online half when the harness package is installed. Never throws. */\nexport async function runDoctor(\n\tapp: Abaigram,\n\toptions: { root?: string; io?: EntryIo; online?: boolean } = {},\n): Promise<DoctorReport> {\n\tconst io = options.io ?? processIo;\n\tconst checks: DoctorCheck[] = [];\n\tconst add = (name: string, status: CheckStatus, detail: string) => {\n\t\tchecks.push({ name, status, detail });\n\t};\n\tconst { manifest } = app;\n\n\tadd(\"entry\", \"ok\", `${manifest.entry} reached (abai stub ${STUB_VERSION})`);\n\n\tconst violations = validateManifest(manifest);\n\tlet rendered: string | undefined;\n\tif (violations.length === 0) {\n\t\trendered = renderManifestYaml(manifest);\n\t\tadd(\n\t\t\t\"manifest\",\n\t\t\t\"ok\",\n\t\t\t`the effective manifest validates (${manifest.cells.length} cells, ${manifest.events.length} events, ${manifest.capabilities.length} capabilities, ${manifest.decisions.length} decisions, ${manifest.turns.length} turns)`,\n\t\t);\n\t} else {\n\t\tadd(\"manifest\", \"fail\", `the effective manifest does not validate: ${violations.join(\"; \")}`);\n\t}\n\n\tconst root =\n\t\toptions.root !== undefined\n\t\t\t? resolve(io.cwd, options.root)\n\t\t\t: (findRoot(manifest.name, io.cwd) ??\n\t\t\t\t(existsSync(join(app.content.root, MANIFEST_FILE)) ? app.content.root : undefined));\n\tif (root === undefined) {\n\t\tadd(\"root\", \"skip\", `no checkout found (pass --root <dir> to check a checked-in ${MANIFEST_FILE})`);\n\t\tadd(MANIFEST_FILE, \"skip\", \"no checkout\");\n\t\tadd(\"identity\", \"skip\", \"no checkout\");\n\t} else {\n\t\tadd(\"root\", \"ok\", root);\n\t\tconst path = join(root, MANIFEST_FILE);\n\t\tif (!existsSync(path)) {\n\t\t\tadd(MANIFEST_FILE, \"fail\", `${path} is missing; run: ${manifest.entry} manifest > ${MANIFEST_FILE}`);\n\t\t} else {\n\t\t\tlet text: string | undefined;\n\t\t\ttry {\n\t\t\t\ttext = readFileSync(path, \"utf8\");\n\t\t\t} catch (error) {\n\t\t\t\tadd(MANIFEST_FILE, \"fail\", `${path} could not be read: ${errorMessage(error)}`);\n\t\t\t}\n\t\t\tif (text !== undefined) {\n\t\t\t\tlet parsed: unknown;\n\t\t\t\tlet parseError: string | undefined;\n\t\t\t\ttry {\n\t\t\t\t\tparsed = parseManifestYaml(text);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tparseError = errorMessage(error);\n\t\t\t\t}\n\t\t\t\tif (parseError !== undefined) {\n\t\t\t\t\tadd(MANIFEST_FILE, \"fail\", `${path} does not parse: ${parseError}`);\n\t\t\t\t} else {\n\t\t\t\t\tconst fileViolations = validateManifest(parsed);\n\t\t\t\t\tif (fileViolations.length > 0) {\n\t\t\t\t\t\tadd(MANIFEST_FILE, \"fail\", `${path} does not validate: ${fileViolations.join(\"; \")}`);\n\t\t\t\t\t} else if (rendered !== undefined && text !== rendered) {\n\t\t\t\t\t\tadd(\n\t\t\t\t\t\t\tMANIFEST_FILE,\n\t\t\t\t\t\t\t\"fail\",\n\t\t\t\t\t\t\t`${path} is stale: first difference at line ${firstDifferingLine(text, rendered)}; run: ${manifest.entry} manifest > ${MANIFEST_FILE}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t} else if (rendered !== undefined) {\n\t\t\t\t\t\tadd(MANIFEST_FILE, \"ok\", `${path} validates and agrees with the code`);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tadd(MANIFEST_FILE, \"fail\", `${path} validates but the effective manifest does not`);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tconst identity = join(root, manifest.content.identity);\n\t\ttry {\n\t\t\tif (!existsSync(identity)) add(\"identity\", \"fail\", `${identity} is missing`);\n\t\t\telse if (readFileSync(identity, \"utf8\").trim() === \"\") add(\"identity\", \"fail\", `${identity} is empty`);\n\t\t\telse add(\"identity\", \"ok\", identity);\n\t\t} catch (error) {\n\t\t\tadd(\"identity\", \"fail\", `${identity} could not be read: ${errorMessage(error)}`);\n\t\t}\n\t}\n\n\tif (app.harnessSelectionError !== undefined) add(\"harness\", \"fail\", app.harnessSelectionError);\n\telse add(\"harness\", \"ok\", `${ENV_HARNESS}: ${app.harnessSelection}`);\n\n\tconst modes = manifest.modes as string[];\n\tconst selected = io.env[ENV_MODE]?.trim();\n\tif (selected === undefined || selected === \"\") {\n\t\tadd(\"modes\", \"ok\", `declared: ${modes.join(\", \")}; default ${modes[0]}`);\n\t} else if (modes.includes(selected)) {\n\t\tadd(\"modes\", \"ok\", `${ENV_MODE}=${selected} is declared (declared: ${modes.join(\", \")})`);\n\t} else {\n\t\tadd(\n\t\t\t\"modes\",\n\t\t\t\"fail\",\n\t\t\t`${ENV_MODE}=${selected} is not declared (declared: ${modes.join(\", \")}); a plain run falls back and counts it`,\n\t\t);\n\t}\n\n\tif (app.endpoint !== undefined) {\n\t\t// under sidecar the endpoint has been listening since startup; doctor says where, or why not\n\t\ttry {\n\t\t\tawait app.endpoint.ready;\n\t\t\tadd(\"endpoint\", \"ok\", `listening at ${app.endpoint.socketPath}`);\n\t\t} catch (error) {\n\t\t\tadd(\"endpoint\", \"fail\", `the endpoint could not listen: ${errorMessage(error)}`);\n\t\t}\n\t}\n\n\ttry {\n\t\tconst auditPath = expandHome(manifest.audit.path, io.env.HOME ?? \"\");\n\t\tconst ancestor = existingAncestor(dirname(resolve(io.cwd, auditPath)));\n\t\tif (!statSync(ancestor).isDirectory()) {\n\t\t\tadd(\"audit\", \"fail\", `${ancestor} is not a directory`);\n\t\t} else {\n\t\t\taccessSync(ancestor, constants.W_OK);\n\t\t\tadd(\"audit\", \"ok\", `${auditPath} (${ancestor} is writable)`);\n\t\t}\n\t} catch (error) {\n\t\tadd(\"audit\", \"fail\", `the audit directory is not writable: ${errorMessage(error)}`);\n\t}\n\n\tif (options.online === false) {\n\t\tadd(\"online\", \"skip\", \"not asked (--offline)\");\n\t} else {\n\t\tconst harness = await importHarnessModule(io.env, manifest);\n\t\tif (!harness?.doctorOnline) {\n\t\t\tadd(\"online\", \"skip\", \"no harness is installed to check the model\");\n\t\t} else {\n\t\t\ttry {\n\t\t\t\tfor (const check of await harness.doctorOnline(manifest, io.env))\n\t\t\t\t\tadd(check.name, check.status, check.detail);\n\t\t\t} catch (error) {\n\t\t\t\tadd(\"online\", \"fail\", `the harness's check failed: ${errorMessage(error)}`);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { ok: checks.every((check) => check.status !== \"fail\"), root: root ?? null, checks };\n}\n\nfunction printReport(report: DoctorReport, io: EntryIo): void {\n\tfor (const check of report.checks) io.out(`${check.status.padEnd(4)} ${check.name}: ${check.detail}\\n`);\n\tio.out(report.ok ? \"doctor: ok\\n\" : \"doctor: failed\\n\");\n}\n\n/**\n * `<prog> abai <verb> ...`. `args` are the arguments after the program's\n * own name; the first must be `abai`. Resolves to the exit code; -1 means\n * the arguments were not an abai entry at all.\n */\nexport async function runEntry(app: Abaigram, args: string[], io: EntryIo = processIo): Promise<number> {\n\tif (args[0] !== \"abai\") {\n\t\t// the entry is one of the five attach places (4.3): a launched program takes up its connection here,\n\t\t// before its own work, so its first touchpoint finds the agent present\n\t\tif (app.launched) await app.attach();\n\t\treturn -1;\n\t}\n\tconst { manifest } = app;\n\tconst usage = (problem?: string): number => {\n\t\tif (problem !== undefined) io.err(`${manifest.entry}: ${problem}`);\n\t\tfor (const line of usageLines(manifest.entry)) io.err(line);\n\t\treturn 2;\n\t};\n\ttry {\n\t\tconst verb = args[1];\n\t\tswitch (verb) {\n\t\t\tcase \"manifest\": {\n\t\t\t\tconst flags = parseFlags(args.slice(2), [\"--json\"]);\n\t\t\t\tif (typeof flags === \"string\") return usage(flags);\n\t\t\t\t// a selected mode the manifest does not declare is an error at the entry (section 4.4)\n\t\t\t\tconst selected = io.env[ENV_MODE]?.trim();\n\t\t\t\tif (selected !== undefined && selected !== \"\" && !(manifest.modes as string[]).includes(selected)) {\n\t\t\t\t\tio.err(\n\t\t\t\t\t\t`${manifest.entry}: ${ENV_MODE}=${selected} is not a declared mode (declared: ${manifest.modes.join(\", \")})`,\n\t\t\t\t\t);\n\t\t\t\t\treturn 2;\n\t\t\t\t}\n\t\t\t\tio.out(flags.json ? `${JSON.stringify(manifest, null, 2)}\\n` : renderManifestYaml(manifest));\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\tcase \"doctor\": {\n\t\t\t\tconst flags = parseFlags(args.slice(2), [\"--json\", \"--root\", \"--offline\"]);\n\t\t\t\tif (typeof flags === \"string\") return usage(flags);\n\t\t\t\tconst report = await runDoctor(app, { root: flags.root, io, online: !flags.offline });\n\t\t\t\tif (flags.json) io.out(`${JSON.stringify(report, null, 2)}\\n`);\n\t\t\t\telse printReport(report, io);\n\t\t\t\treturn report.ok ? 0 : 1;\n\t\t\t}\n\t\t\tcase undefined:\n\t\t\tcase \"session\": {\n\t\t\t\tawait app.session();\n\t\t\t\tif (app.attached) return 0;\n\t\t\t\tio.err(`${manifest.entry}: no harness attached (${app.attachError ?? \"unknown reason\"})`);\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t\tcase \"install\": {\n\t\t\t\tawait app.install();\n\t\t\t\tif (app.attached) return 0;\n\t\t\t\tio.err(`${manifest.entry}: no harness attached (${app.attachError ?? \"unknown reason\"})`);\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t\tcase \"config\": {\n\t\t\t\tconst harness = await importHarnessModule(io.env, manifest);\n\t\t\t\tif (!harness?.runConfig) return usage(\"config needs the harness package, which is not installed\");\n\t\t\t\treturn await harness.runConfig(args.slice(2), io);\n\t\t\t}\n\t\t\tcase \"mcp\": {\n\t\t\t\t// the program at its entry serves an MCP client: under sidecar through the binary on this\n\t\t\t\t// process's stdio, otherwise in-process through the installed harness package (section 4.4).\n\t\t\t\t// ABAI_HARNESS is honoured like everywhere: off attaches nothing, a null harness is attached already\n\t\t\t\tif (app.harnessSelection === \"off\") {\n\t\t\t\t\tio.err(`${manifest.entry}: no harness attached (${ENV_HARNESS}=off)`);\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\t\t\t\tif (app.attached) {\n\t\t\t\t\tio.err(`${manifest.entry}: ${manifest.name} already has a harness attached`);\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\t\t\t\tif (app.endpoint !== undefined) {\n\t\t\t\t\tconst code = await app.serveMcpSidecar(app.endpoint);\n\t\t\t\t\tif (code >= 0) return code;\n\t\t\t\t\tio.err(`${manifest.entry}: no harness attached (${app.attachError ?? \"unknown reason\"})`);\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\t\t\t\tconst harness = await importHarnessModule(io.env, manifest);\n\t\t\t\tif (!harness?.serveMcpEmbedded) return usage(\"mcp needs the harness package, which is not installed\");\n\t\t\t\tconst binding = app.bind(\"mcp\");\n\t\t\t\tbinding.enterSafepoint();\n\t\t\t\ttry {\n\t\t\t\t\treturn await harness.serveMcpEmbedded(binding);\n\t\t\t\t} finally {\n\t\t\t\t\tbinding.leaveSafepoint();\n\t\t\t\t}\n\t\t\t}\n\t\t\tcase \"run\": {\n\t\t\t\t// sidecar launch (4.4, 6.3): the harness binary starts this very program again as its child\n\t\t\t\tif (!(manifest.modes as string[]).includes(\"sidecar\")) {\n\t\t\t\t\tio.err(\n\t\t\t\t\t\t`${manifest.entry}: run is sidecar launch, and ${manifest.name} declares ${manifest.modes.join(\", \")}`,\n\t\t\t\t\t);\n\t\t\t\t\treturn 2;\n\t\t\t\t}\n\t\t\t\tconst separator = args.indexOf(\"--\");\n\t\t\t\tconst flags = args.slice(2, separator === -1 ? undefined : separator);\n\t\t\t\tconst programArgs = separator === -1 ? [] : args.slice(separator + 1);\n\t\t\t\tfor (const flag of flags) {\n\t\t\t\t\tif (flag !== \"--auto\" && flag !== \"--deny-mutate\" && flag !== \"--all-events\") {\n\t\t\t\t\t\treturn usage(`unknown option ${flag} (run takes --auto, --deny-mutate, --all-events)`);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst binary = harnessBinary(io.env, app.content.root);\n\t\t\t\tconst script = process.argv[1];\n\t\t\t\tif (script === undefined) return usage(\"run cannot tell how this program was started\");\n\t\t\t\tconst command = [process.execPath, ...process.execArgv, script, ...programArgs];\n\t\t\t\tconst child = spawn(binary.command, [...binary.args, \"run\", ...flags, \"--\", ...command], {\n\t\t\t\t\tstdio: \"inherit\",\n\t\t\t\t\tenv: { ...process.env, ...io.env },\n\t\t\t\t});\n\t\t\t\t// whoever ends this process ends the launcher behind it, which ends the program it supervises\n\t\t\t\tconst forward = (signal: NodeJS.Signals): void => {\n\t\t\t\t\tif (child.exitCode === null && child.signalCode === null) child.kill(signal);\n\t\t\t\t};\n\t\t\t\tconst forwarded: NodeJS.Signals[] = [\"SIGTERM\", \"SIGINT\", \"SIGHUP\"];\n\t\t\t\tfor (const signal of forwarded) process.on(signal, forward);\n\t\t\t\ttry {\n\t\t\t\t\treturn await new Promise<number>((resolve) => {\n\t\t\t\t\t\tchild.once(\"error\", (error) => {\n\t\t\t\t\t\t\tio.err(`${manifest.entry}: the harness binary could not be started: ${errorMessage(error)}`);\n\t\t\t\t\t\t\tresolve(1);\n\t\t\t\t\t\t});\n\t\t\t\t\t\tchild.once(\"exit\", (code) => resolve(code ?? 1));\n\t\t\t\t\t});\n\t\t\t\t} finally {\n\t\t\t\t\tfor (const signal of forwarded) process.off(signal, forward);\n\t\t\t\t}\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\treturn usage(`unknown verb ${verb}`);\n\t\t}\n\t} catch (error) {\n\t\tio.err(`${manifest.entry}: ${errorMessage(error)}`);\n\t\treturn 2;\n\t}\n}\n"]}
1
+ {"version":3,"file":"entry.js","sourceRoot":"","sources":["../src/entry.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,4EAA4E;AAC5E,2EAA2E;AAC3E,2EAA2E;AAC3E,sEAAsE;AACtE,6BAA6B;AAC7B,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACpF,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC7E,OAAO,EAAiB,aAAa,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEjF,MAAM,CAAC,MAAM,YAAY,GAAG,OAAO,CAAC;AAwBpC,MAAM,CAAC,MAAM,SAAS,GAAY;IACjC,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC;QACd,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAAA,CAC3B;IACD,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC;QACd,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC;IAAA,CAClC;IACD,GAAG,EAAE,OAAO,CAAC,GAAG;IAChB,IAAI,GAAG,GAAG;QACT,OAAO,OAAO,CAAC,GAAG,EAAE,CAAC;IAAA,CACrB;CACD,CAAC;AAEF,SAAS,YAAY,CAAC,KAAc,EAAU;IAC7C,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAAA,CAC9D;AAED,SAAS,UAAU,CAAC,KAAa,EAAY;IAC5C,OAAO;QACN,UAAU,KAAK,sCAAsC;QACrD,UAAU,KAAK,kDAAkD;QACjE,UAAU,KAAK,oDAAoD;QACnE,UAAU,KAAK,6CAA6C;QAC5D,UAAU,KAAK,+DAA+D;QAC9E,UAAU,KAAK,2EAA2E;QAC1F,UAAU,KAAK,gFAAgF;QAC/F,EAAE;QACF,4EAA4E;QAC5E,WAAW,aAAa,wDAAwD;QAChF,EAAE;QACF,2FAA2F;QAC3F,8FAA8F;QAC9F,mEAAmE;KACnE,CAAC;AAAA,CACF;AAQD,mFAAmF;AACnF,SAAS,UAAU,CAAC,IAAc,EAAE,OAA0B,EAAkB;IAC/E,MAAM,KAAK,GAAU,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IACtE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,MAAM,EAAE,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC5B,MAAM,IAAI,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAChD,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,OAAO,kBAAkB,GAAG,EAAE,CAAC;QAC5D,MAAM,SAAS,GAAG,GAAuB,EAAE,CAAC;YAC3C,IAAI,EAAE,KAAK,CAAC,CAAC;gBAAE,OAAO,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;YACxC,CAAC,IAAI,CAAC,CAAC;YACP,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC;QAAA,CACf,CAAC;QACF,QAAQ,IAAI,EAAE,CAAC;YACd,KAAK,QAAQ;gBACZ,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC;gBAClB,MAAM;YACP,KAAK,WAAW;gBACf,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC;gBACrB,MAAM;YACP,KAAK,QAAQ,EAAE,CAAC;gBACf,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC;gBAC1B,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE;oBAAE,OAAO,0BAA0B,CAAC;gBAC3E,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC;gBACnB,MAAM;YACP,CAAC;YACD;gBACC,OAAO,kBAAkB,GAAG,EAAE,CAAC;QACjC,CAAC;IACF,CAAC;IACD,OAAO,KAAK,CAAC;AAAA,CACb;AAED,mFAAmF;AACnF,MAAM,UAAU,kBAAkB,CAAC,CAAS,EAAE,CAAS,EAAsB;IAC5E,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAC9B,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACjD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5B,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC;YAAE,OAAO,CAAC,GAAG,CAAC,CAAC;IAC3C,CAAC;IACD,OAAO,CAAC,CAAC;AAAA,CACT;AAED,wEAAwE;AACxE,SAAS,gBAAgB,CAAC,IAAY,EAAU;IAC/C,IAAI,OAAO,GAAG,IAAI,CAAC;IACnB,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC7B,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QAChC,IAAI,MAAM,KAAK,OAAO;YAAE,MAAM;QAC9B,OAAO,GAAG,MAAM,CAAC;IAClB,CAAC;IACD,OAAO,OAAO,CAAC;AAAA,CACf;AAED,4HAA4H;AAC5H,MAAM,CAAC,KAAK,UAAU,SAAS,CAC9B,GAAa,EACb,OAAO,GAAsD,EAAE,EACvC;IACxB,MAAM,EAAE,GAAG,OAAO,CAAC,EAAE,IAAI,SAAS,CAAC;IACnC,MAAM,MAAM,GAAkB,EAAE,CAAC;IACjC,MAAM,GAAG,GAAG,CAAC,IAAY,EAAE,MAAmB,EAAE,MAAc,EAAE,EAAE,CAAC;QAClE,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAAA,CACtC,CAAC;IACF,MAAM,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAC;IAEzB,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,GAAG,QAAQ,CAAC,KAAK,uBAAuB,YAAY,GAAG,CAAC,CAAC;IAE5E,MAAM,UAAU,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAC9C,IAAI,QAA4B,CAAC;IACjC,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,QAAQ,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;QACxC,GAAG,CACF,UAAU,EACV,IAAI,EACJ,qCAAqC,QAAQ,CAAC,KAAK,CAAC,MAAM,WAAW,QAAQ,CAAC,MAAM,CAAC,MAAM,YAAY,QAAQ,CAAC,YAAY,CAAC,MAAM,kBAAkB,QAAQ,CAAC,SAAS,CAAC,MAAM,eAAe,QAAQ,CAAC,KAAK,CAAC,MAAM,SAAS,CAC3N,CAAC;IACH,CAAC;SAAM,CAAC;QACP,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,6CAA6C,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC/F,CAAC;IAED,MAAM,IAAI,GACT,OAAO,CAAC,IAAI,KAAK,SAAS;QACzB,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,CAAC;QAC/B,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC;YACjC,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IACvF,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACxB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,8DAA8D,aAAa,GAAG,CAAC,CAAC;QACpG,GAAG,CAAC,aAAa,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC;QAC1C,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC;IACxC,CAAC;SAAM,CAAC;QACP,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QACxB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;QACvC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACvB,GAAG,CAAC,aAAa,EAAE,MAAM,EAAE,GAAG,IAAI,qBAAqB,QAAQ,CAAC,KAAK,eAAe,aAAa,EAAE,CAAC,CAAC;QACtG,CAAC;aAAM,CAAC;YACP,IAAI,IAAwB,CAAC;YAC7B,IAAI,CAAC;gBACJ,IAAI,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YACnC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,GAAG,CAAC,aAAa,EAAE,MAAM,EAAE,GAAG,IAAI,uBAAuB,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YACjF,CAAC;YACD,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gBACxB,IAAI,MAAe,CAAC;gBACpB,IAAI,UAA8B,CAAC;gBACnC,IAAI,CAAC;oBACJ,MAAM,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;gBAClC,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBAChB,UAAU,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;gBAClC,CAAC;gBACD,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;oBAC9B,GAAG,CAAC,aAAa,EAAE,MAAM,EAAE,GAAG,IAAI,oBAAoB,UAAU,EAAE,CAAC,CAAC;gBACrE,CAAC;qBAAM,CAAC;oBACP,MAAM,cAAc,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;oBAChD,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;wBAC/B,GAAG,CAAC,aAAa,EAAE,MAAM,EAAE,GAAG,IAAI,uBAAuB,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;oBACvF,CAAC;yBAAM,IAAI,QAAQ,KAAK,SAAS,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;wBACxD,GAAG,CACF,aAAa,EACb,MAAM,EACN,GAAG,IAAI,uCAAuC,kBAAkB,CAAC,IAAI,EAAE,QAAQ,CAAC,UAAU,QAAQ,CAAC,KAAK,eAAe,aAAa,EAAE,CACtI,CAAC;oBACH,CAAC;yBAAM,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;wBACnC,GAAG,CAAC,aAAa,EAAE,IAAI,EAAE,GAAG,IAAI,qCAAqC,CAAC,CAAC;oBACxE,CAAC;yBAAM,CAAC;wBACP,GAAG,CAAC,aAAa,EAAE,MAAM,EAAE,GAAG,IAAI,gDAAgD,CAAC,CAAC;oBACrF,CAAC;gBACF,CAAC;YACF,CAAC;QACF,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACvD,IAAI,CAAC;YACJ,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;gBAAE,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,QAAQ,aAAa,CAAC,CAAC;iBACxE,IAAI,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE;gBAAE,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,QAAQ,WAAW,CAAC,CAAC;;gBAClG,GAAG,CAAC,UAAU,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;QACtC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,QAAQ,uBAAuB,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAClF,CAAC;IACF,CAAC;IAED,IAAI,GAAG,CAAC,qBAAqB,KAAK,SAAS;QAAE,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,CAAC,qBAAqB,CAAC,CAAC;;QAC1F,GAAG,CAAC,SAAS,EAAE,IAAI,EAAE,GAAG,WAAW,KAAK,GAAG,CAAC,gBAAgB,EAAE,CAAC,CAAC;IAErE,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAiB,CAAC;IACzC,MAAM,QAAQ,GAAG,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,CAAC;IAC1C,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,EAAE,EAAE,CAAC;QAC/C,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,aAAa,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAC1E,CAAC;SAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QACrC,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,GAAG,QAAQ,IAAI,QAAQ,2BAA2B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC3F,CAAC;SAAM,CAAC;QACP,GAAG,CACF,OAAO,EACP,MAAM,EACN,GAAG,QAAQ,IAAI,QAAQ,+BAA+B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,yCAAyC,CAC/G,CAAC;IACH,CAAC;IAED,IAAI,GAAG,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QAChC,6FAA6F;QAC7F,IAAI,CAAC;YACJ,MAAM,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC;YACzB,GAAG,CAAC,UAAU,EAAE,IAAI,EAAE,gBAAgB,GAAG,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;QAClE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,kCAAkC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAClF,CAAC;IACF,CAAC;IAED,IAAI,CAAC;QACJ,MAAM,SAAS,GAAG,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;QACrE,MAAM,QAAQ,GAAG,gBAAgB,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;QACvE,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;YACvC,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,QAAQ,qBAAqB,CAAC,CAAC;QACxD,CAAC;aAAM,CAAC;YACP,UAAU,CAAC,QAAQ,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;YACrC,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,GAAG,SAAS,KAAK,QAAQ,eAAe,CAAC,CAAC;QAC9D,CAAC;IACF,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,wCAAwC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACrF,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;QAC9B,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,uBAAuB,CAAC,CAAC;IAChD,CAAC;SAAM,CAAC;QACP,MAAM,OAAO,GAAG,MAAM,mBAAmB,CAAC,EAAE,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QAC5D,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,CAAC;YAC5B,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,4CAA4C,CAAC,CAAC;QACrE,CAAC;aAAM,CAAC;YACP,IAAI,CAAC;gBACJ,KAAK,MAAM,KAAK,IAAI,MAAM,OAAO,CAAC,YAAY,CAAC,QAAQ,EAAE,EAAE,CAAC,GAAG,CAAC;oBAC/D,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;YAC9C,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,+BAA+B,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAC7E,CAAC;QACF,CAAC;IACF,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,IAAI,IAAI,EAAE,MAAM,EAAE,CAAC;AAAA,CAC5F;AAED,SAAS,WAAW,CAAC,MAAoB,EAAE,EAAW,EAAQ;IAC7D,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM;QAAE,EAAE,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC;IACxG,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC;AAAA,CACxD;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,GAAa,EAAE,IAAc,EAAE,EAAE,GAAY,SAAS,EAAmB;IACvG,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC;QACxB,qGAAqG;QACrG,uEAAuE;QACvE,IAAI,GAAG,CAAC,QAAQ;YAAE,MAAM,GAAG,CAAC,MAAM,EAAE,CAAC;QACrC,OAAO,CAAC,CAAC,CAAC;IACX,CAAC;IACD,MAAM,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAC;IACzB,MAAM,KAAK,GAAG,CAAC,OAAgB,EAAU,EAAE,CAAC;QAC3C,IAAI,OAAO,KAAK,SAAS;YAAE,EAAE,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,KAAK,KAAK,OAAO,EAAE,CAAC,CAAC;QACnE,KAAK,MAAM,IAAI,IAAI,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC5D,OAAO,CAAC,CAAC;IAAA,CACT,CAAC;IACF,IAAI,CAAC;QACJ,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACrB,QAAQ,IAAI,EAAE,CAAC;YACd,KAAK,UAAU,EAAE,CAAC;gBACjB,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;gBACpD,IAAI,OAAO,KAAK,KAAK,QAAQ;oBAAE,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC;gBACnD,uFAAuF;gBACvF,MAAM,QAAQ,GAAG,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,CAAC;gBAC1C,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,EAAE,IAAI,CAAE,QAAQ,CAAC,KAAkB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;oBACnG,EAAE,CAAC,GAAG,CACL,GAAG,QAAQ,CAAC,KAAK,KAAK,QAAQ,IAAI,QAAQ,sCAAsC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAC5G,CAAC;oBACF,OAAO,CAAC,CAAC;gBACV,CAAC;gBACD,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAC7F,OAAO,CAAC,CAAC;YACV,CAAC;YACD,KAAK,QAAQ,EAAE,CAAC;gBACf,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC,CAAC;gBAC3E,IAAI,OAAO,KAAK,KAAK,QAAQ;oBAAE,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC;gBACnD,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;gBACtF,IAAI,KAAK,CAAC,IAAI;oBAAE,EAAE,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;;oBAC1D,WAAW,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;gBAC7B,OAAO,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1B,CAAC;YACD,KAAK,SAAS,CAAC;YACf,KAAK,SAAS,EAAE,CAAC;gBAChB,MAAM,GAAG,CAAC,OAAO,EAAE,CAAC;gBACpB,IAAI,GAAG,CAAC,QAAQ;oBAAE,OAAO,CAAC,CAAC;gBAC3B,EAAE,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,KAAK,0BAA0B,GAAG,CAAC,WAAW,IAAI,gBAAgB,GAAG,CAAC,CAAC;gBAC1F,OAAO,CAAC,CAAC;YACV,CAAC;YACD,KAAK,SAAS,EAAE,CAAC;gBAChB,MAAM,GAAG,CAAC,OAAO,EAAE,CAAC;gBACpB,IAAI,GAAG,CAAC,QAAQ;oBAAE,OAAO,CAAC,CAAC;gBAC3B,EAAE,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,KAAK,0BAA0B,GAAG,CAAC,WAAW,IAAI,gBAAgB,GAAG,CAAC,CAAC;gBAC1F,OAAO,CAAC,CAAC;YACV,CAAC;YACD,KAAK,QAAQ,EAAE,CAAC;gBACf,MAAM,OAAO,GAAG,MAAM,mBAAmB,CAAC,EAAE,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;gBAC5D,IAAI,CAAC,OAAO,EAAE,SAAS;oBAAE,OAAO,KAAK,CAAC,0DAA0D,CAAC,CAAC;gBAClG,OAAO,MAAM,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;YAC/E,CAAC;YACD,KAAK,KAAK,EAAE,CAAC;gBACZ,0FAA0F;gBAC1F,6FAA6F;gBAC7F,qGAAqG;gBACrG,IAAI,GAAG,CAAC,gBAAgB,KAAK,KAAK,EAAE,CAAC;oBACpC,EAAE,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,KAAK,0BAA0B,WAAW,OAAO,CAAC,CAAC;oBACtE,OAAO,CAAC,CAAC;gBACV,CAAC;gBACD,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;oBAClB,EAAE,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,KAAK,KAAK,QAAQ,CAAC,IAAI,iCAAiC,CAAC,CAAC;oBAC7E,OAAO,CAAC,CAAC;gBACV,CAAC;gBACD,IAAI,GAAG,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;oBAChC,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;oBACrD,IAAI,IAAI,IAAI,CAAC;wBAAE,OAAO,IAAI,CAAC;oBAC3B,EAAE,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,KAAK,0BAA0B,GAAG,CAAC,WAAW,IAAI,gBAAgB,GAAG,CAAC,CAAC;oBAC1F,OAAO,CAAC,CAAC;gBACV,CAAC;gBACD,MAAM,OAAO,GAAG,MAAM,mBAAmB,CAAC,EAAE,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;gBAC5D,IAAI,CAAC,OAAO,EAAE,gBAAgB;oBAAE,OAAO,KAAK,CAAC,uDAAuD,CAAC,CAAC;gBACtG,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAChC,OAAO,CAAC,cAAc,EAAE,CAAC;gBACzB,IAAI,CAAC;oBACJ,OAAO,MAAM,OAAO,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;gBAChD,CAAC;wBAAS,CAAC;oBACV,OAAO,CAAC,cAAc,EAAE,CAAC;gBAC1B,CAAC;YACF,CAAC;YACD,KAAK,KAAK,EAAE,CAAC;gBACZ,4FAA4F;gBAC5F,IAAI,CAAE,QAAQ,CAAC,KAAkB,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;oBACvD,EAAE,CAAC,GAAG,CACL,GAAG,QAAQ,CAAC,KAAK,gCAAgC,QAAQ,CAAC,IAAI,aAAa,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACtG,CAAC;oBACF,OAAO,CAAC,CAAC;gBACV,CAAC;gBACD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;gBACrC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;gBACtE,MAAM,WAAW,GAAG,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC;gBACtE,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;oBAC1B,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,eAAe,IAAI,IAAI,KAAK,cAAc,EAAE,CAAC;wBAC9E,OAAO,KAAK,CAAC,kBAAkB,IAAI,kDAAkD,CAAC,CAAC;oBACxF,CAAC;gBACF,CAAC;gBACD,MAAM,MAAM,GAAG,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;gBACvD,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAC/B,IAAI,MAAM,KAAK,SAAS;oBAAE,OAAO,KAAK,CAAC,8CAA8C,CAAC,CAAC;gBACvF,MAAM,OAAO,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,WAAW,CAAC,CAAC;gBAChF,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,EAAE;oBACxF,KAAK,EAAE,SAAS;oBAChB,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE;iBAClC,CAAC,CAAC;gBACH,8FAA8F;gBAC9F,MAAM,OAAO,GAAG,CAAC,MAAsB,EAAQ,EAAE,CAAC;oBACjD,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,IAAI,KAAK,CAAC,UAAU,KAAK,IAAI;wBAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBAAA,CAC7E,CAAC;gBACF,MAAM,SAAS,GAAqB,CAAC,SAAS,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;gBACpE,KAAK,MAAM,MAAM,IAAI,SAAS;oBAAE,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBAC5D,IAAI,CAAC;oBACJ,OAAO,MAAM,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,EAAE,CAAC;wBAC7C,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC;4BAC9B,EAAE,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,KAAK,8CAA8C,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;4BAC7F,OAAO,CAAC,CAAC,CAAC,CAAC;wBAAA,CACX,CAAC,CAAC;wBACH,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;oBAAA,CACjD,CAAC,CAAC;gBACJ,CAAC;wBAAS,CAAC;oBACV,KAAK,MAAM,MAAM,IAAI,SAAS;wBAAE,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBAC9D,CAAC;YACF,CAAC;YACD;gBACC,OAAO,KAAK,CAAC,gBAAgB,IAAI,EAAE,CAAC,CAAC;QACvC,CAAC;IACF,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,EAAE,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,KAAK,KAAK,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACpD,OAAO,CAAC,CAAC;IACV,CAAC;AAAA,CACD","sourcesContent":["// The standard agent entry (abaigrammar section 4.4), the part the stub\n// provides itself: `<prog> abai manifest` prints the effective manifest and\n// `<prog> abai doctor` runs the offline conformance checks. The verbs that\n// need a harness (session, install, config, mcp, run) are delegated once a\n// harness binding exists; until then the usage says so. Never throws;\n// resolves to the exit code.\nimport { spawn } from \"node:child_process\";\nimport { accessSync, constants, existsSync, readFileSync, statSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { findRoot, MANIFEST_FILE } from \"./content.ts\";\nimport { ENV_HARNESS, ENV_MODE, expandHome } from \"./env.ts\";\nimport { validateManifest } from \"./manifest/manifest.ts\";\nimport { parseManifestYaml, renderManifestYaml } from \"./manifest/render.ts\";\nimport { type Abaigram, harnessBinary, importHarnessModule } from \"./program.ts\";\n\nexport const STUB_VERSION = \"0.2.0\";\n\nexport type CheckStatus = \"ok\" | \"fail\" | \"skip\";\n\nexport interface DoctorCheck {\n\tname: string;\n\tstatus: CheckStatus;\n\tdetail: string;\n}\n\nexport interface DoctorReport {\n\tok: boolean;\n\troot: string | null;\n\tchecks: DoctorCheck[];\n}\n\n/** Where the entry writes; injectable for tests. */\nexport interface EntryIo {\n\tout(text: string): void;\n\terr(text: string): void;\n\tenv: NodeJS.ProcessEnv;\n\tcwd: string;\n}\n\nexport const processIo: EntryIo = {\n\tout: (text) => {\n\t\tprocess.stdout.write(text);\n\t},\n\terr: (text) => {\n\t\tprocess.stderr.write(`${text}\\n`);\n\t},\n\tenv: process.env,\n\tget cwd() {\n\t\treturn process.cwd();\n\t},\n};\n\nfunction errorMessage(error: unknown): string {\n\treturn error instanceof Error ? error.message : String(error);\n}\n\nfunction usageLines(entry: string): string[] {\n\treturn [\n\t\t`usage: ${entry} open a session`,\n\t\t` ${entry} install run the install touchpoint`,\n\t\t` ${entry} manifest [--json] print the effective manifest`,\n\t\t` ${entry} doctor [--root <dir>] [--offline] [--json]`,\n\t\t` ${entry} config [set ...] the machine-level model configuration`,\n\t\t` ${entry} mcp serve the agent's tools to an MCP client over stdio`,\n\t\t` ${entry} run [--auto] -- ARGS the harness starts this program as its supervised child`,\n\t\t\"\",\n\t\t\"doctor offline conformance checks: the effective manifest, the checked-in\",\n\t\t` ${MANIFEST_FILE}, the identity content, the modes, the audit directory`,\n\t\t\"\",\n\t\t\"session and install attach a harness and return when none can attach; mcp needs no model,\",\n\t\t\"since the client's own agent is this program's; run is always sidecar launch, with the whole\",\n\t\t\"lifecycle channel and the program's output observed from outside.\",\n\t];\n}\n\ninterface Flags {\n\tjson: boolean;\n\troot: string | undefined;\n\toffline: boolean;\n}\n\n/** `--flag`, `--flag value` and `--flag=value`; anything else is a usage error. */\nfunction parseFlags(args: string[], allowed: readonly string[]): Flags | string {\n\tconst flags: Flags = { json: false, root: undefined, offline: false };\n\tfor (let i = 0; i < args.length; i++) {\n\t\tconst arg = args[i];\n\t\tconst eq = arg.indexOf(\"=\");\n\t\tconst name = eq === -1 ? arg : arg.slice(0, eq);\n\t\tif (!allowed.includes(name)) return `unknown option ${arg}`;\n\t\tconst takeValue = (): string | undefined => {\n\t\t\tif (eq !== -1) return arg.slice(eq + 1);\n\t\t\ti += 1;\n\t\t\treturn args[i];\n\t\t};\n\t\tswitch (name) {\n\t\t\tcase \"--json\":\n\t\t\t\tflags.json = true;\n\t\t\t\tbreak;\n\t\t\tcase \"--offline\":\n\t\t\t\tflags.offline = true;\n\t\t\t\tbreak;\n\t\t\tcase \"--root\": {\n\t\t\t\tconst value = takeValue();\n\t\t\t\tif (value === undefined || value === \"\") return \"--root needs a directory\";\n\t\t\t\tflags.root = value;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\treturn `unknown option ${arg}`;\n\t\t}\n\t}\n\treturn flags;\n}\n\n/** The first line at which two texts differ (1-based), or undefined when equal. */\nexport function firstDifferingLine(a: string, b: string): number | undefined {\n\tif (a === b) return undefined;\n\tconst linesA = a.split(\"\\n\");\n\tconst linesB = b.split(\"\\n\");\n\tconst n = Math.max(linesA.length, linesB.length);\n\tfor (let i = 0; i < n; i++) {\n\t\tif (linesA[i] !== linesB[i]) return i + 1;\n\t}\n\treturn n;\n}\n\n/** The first existing ancestor of a path (the path itself included). */\nfunction existingAncestor(path: string): string {\n\tlet current = path;\n\twhile (!existsSync(current)) {\n\t\tconst parent = dirname(current);\n\t\tif (parent === current) break;\n\t\tcurrent = parent;\n\t}\n\treturn current;\n}\n\n/** The offline half of `doctor` (section 4.4), plus the online half when the harness package is installed. Never throws. */\nexport async function runDoctor(\n\tapp: Abaigram,\n\toptions: { root?: string; io?: EntryIo; online?: boolean } = {},\n): Promise<DoctorReport> {\n\tconst io = options.io ?? processIo;\n\tconst checks: DoctorCheck[] = [];\n\tconst add = (name: string, status: CheckStatus, detail: string) => {\n\t\tchecks.push({ name, status, detail });\n\t};\n\tconst { manifest } = app;\n\n\tadd(\"entry\", \"ok\", `${manifest.entry} reached (abai stub ${STUB_VERSION})`);\n\n\tconst violations = validateManifest(manifest);\n\tlet rendered: string | undefined;\n\tif (violations.length === 0) {\n\t\trendered = renderManifestYaml(manifest);\n\t\tadd(\n\t\t\t\"manifest\",\n\t\t\t\"ok\",\n\t\t\t`the effective manifest validates (${manifest.cells.length} cells, ${manifest.events.length} events, ${manifest.capabilities.length} capabilities, ${manifest.decisions.length} decisions, ${manifest.turns.length} turns)`,\n\t\t);\n\t} else {\n\t\tadd(\"manifest\", \"fail\", `the effective manifest does not validate: ${violations.join(\"; \")}`);\n\t}\n\n\tconst root =\n\t\toptions.root !== undefined\n\t\t\t? resolve(io.cwd, options.root)\n\t\t\t: (findRoot(manifest.name, io.cwd) ??\n\t\t\t\t(existsSync(join(app.content.root, MANIFEST_FILE)) ? app.content.root : undefined));\n\tif (root === undefined) {\n\t\tadd(\"root\", \"skip\", `no checkout found (pass --root <dir> to check a checked-in ${MANIFEST_FILE})`);\n\t\tadd(MANIFEST_FILE, \"skip\", \"no checkout\");\n\t\tadd(\"identity\", \"skip\", \"no checkout\");\n\t} else {\n\t\tadd(\"root\", \"ok\", root);\n\t\tconst path = join(root, MANIFEST_FILE);\n\t\tif (!existsSync(path)) {\n\t\t\tadd(MANIFEST_FILE, \"fail\", `${path} is missing; run: ${manifest.entry} manifest > ${MANIFEST_FILE}`);\n\t\t} else {\n\t\t\tlet text: string | undefined;\n\t\t\ttry {\n\t\t\t\ttext = readFileSync(path, \"utf8\");\n\t\t\t} catch (error) {\n\t\t\t\tadd(MANIFEST_FILE, \"fail\", `${path} could not be read: ${errorMessage(error)}`);\n\t\t\t}\n\t\t\tif (text !== undefined) {\n\t\t\t\tlet parsed: unknown;\n\t\t\t\tlet parseError: string | undefined;\n\t\t\t\ttry {\n\t\t\t\t\tparsed = parseManifestYaml(text);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tparseError = errorMessage(error);\n\t\t\t\t}\n\t\t\t\tif (parseError !== undefined) {\n\t\t\t\t\tadd(MANIFEST_FILE, \"fail\", `${path} does not parse: ${parseError}`);\n\t\t\t\t} else {\n\t\t\t\t\tconst fileViolations = validateManifest(parsed);\n\t\t\t\t\tif (fileViolations.length > 0) {\n\t\t\t\t\t\tadd(MANIFEST_FILE, \"fail\", `${path} does not validate: ${fileViolations.join(\"; \")}`);\n\t\t\t\t\t} else if (rendered !== undefined && text !== rendered) {\n\t\t\t\t\t\tadd(\n\t\t\t\t\t\t\tMANIFEST_FILE,\n\t\t\t\t\t\t\t\"fail\",\n\t\t\t\t\t\t\t`${path} is stale: first difference at line ${firstDifferingLine(text, rendered)}; run: ${manifest.entry} manifest > ${MANIFEST_FILE}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t} else if (rendered !== undefined) {\n\t\t\t\t\t\tadd(MANIFEST_FILE, \"ok\", `${path} validates and agrees with the code`);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tadd(MANIFEST_FILE, \"fail\", `${path} validates but the effective manifest does not`);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tconst identity = join(root, manifest.content.identity);\n\t\ttry {\n\t\t\tif (!existsSync(identity)) add(\"identity\", \"fail\", `${identity} is missing`);\n\t\t\telse if (readFileSync(identity, \"utf8\").trim() === \"\") add(\"identity\", \"fail\", `${identity} is empty`);\n\t\t\telse add(\"identity\", \"ok\", identity);\n\t\t} catch (error) {\n\t\t\tadd(\"identity\", \"fail\", `${identity} could not be read: ${errorMessage(error)}`);\n\t\t}\n\t}\n\n\tif (app.harnessSelectionError !== undefined) add(\"harness\", \"fail\", app.harnessSelectionError);\n\telse add(\"harness\", \"ok\", `${ENV_HARNESS}: ${app.harnessSelection}`);\n\n\tconst modes = manifest.modes as string[];\n\tconst selected = io.env[ENV_MODE]?.trim();\n\tif (selected === undefined || selected === \"\") {\n\t\tadd(\"modes\", \"ok\", `declared: ${modes.join(\", \")}; default ${modes[0]}`);\n\t} else if (modes.includes(selected)) {\n\t\tadd(\"modes\", \"ok\", `${ENV_MODE}=${selected} is declared (declared: ${modes.join(\", \")})`);\n\t} else {\n\t\tadd(\n\t\t\t\"modes\",\n\t\t\t\"fail\",\n\t\t\t`${ENV_MODE}=${selected} is not declared (declared: ${modes.join(\", \")}); a plain run falls back and counts it`,\n\t\t);\n\t}\n\n\tif (app.endpoint !== undefined) {\n\t\t// under sidecar the endpoint has been listening since startup; doctor says where, or why not\n\t\ttry {\n\t\t\tawait app.endpoint.ready;\n\t\t\tadd(\"endpoint\", \"ok\", `listening at ${app.endpoint.socketPath}`);\n\t\t} catch (error) {\n\t\t\tadd(\"endpoint\", \"fail\", `the endpoint could not listen: ${errorMessage(error)}`);\n\t\t}\n\t}\n\n\ttry {\n\t\tconst auditPath = expandHome(manifest.audit.path, io.env.HOME ?? \"\");\n\t\tconst ancestor = existingAncestor(dirname(resolve(io.cwd, auditPath)));\n\t\tif (!statSync(ancestor).isDirectory()) {\n\t\t\tadd(\"audit\", \"fail\", `${ancestor} is not a directory`);\n\t\t} else {\n\t\t\taccessSync(ancestor, constants.W_OK);\n\t\t\tadd(\"audit\", \"ok\", `${auditPath} (${ancestor} is writable)`);\n\t\t}\n\t} catch (error) {\n\t\tadd(\"audit\", \"fail\", `the audit directory is not writable: ${errorMessage(error)}`);\n\t}\n\n\tif (options.online === false) {\n\t\tadd(\"online\", \"skip\", \"not asked (--offline)\");\n\t} else {\n\t\tconst harness = await importHarnessModule(io.env, manifest);\n\t\tif (!harness?.doctorOnline) {\n\t\t\tadd(\"online\", \"skip\", \"no harness is installed to check the model\");\n\t\t} else {\n\t\t\ttry {\n\t\t\t\tfor (const check of await harness.doctorOnline(manifest, io.env))\n\t\t\t\t\tadd(check.name, check.status, check.detail);\n\t\t\t} catch (error) {\n\t\t\t\tadd(\"online\", \"fail\", `the harness's check failed: ${errorMessage(error)}`);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { ok: checks.every((check) => check.status !== \"fail\"), root: root ?? null, checks };\n}\n\nfunction printReport(report: DoctorReport, io: EntryIo): void {\n\tfor (const check of report.checks) io.out(`${check.status.padEnd(4)} ${check.name}: ${check.detail}\\n`);\n\tio.out(report.ok ? \"doctor: ok\\n\" : \"doctor: failed\\n\");\n}\n\n/**\n * `<prog> abai <verb> ...`. `args` are the arguments after the program's\n * own name; the first must be `abai`. Resolves to the exit code; -1 means\n * the arguments were not an abai entry at all.\n */\nexport async function runEntry(app: Abaigram, args: string[], io: EntryIo = processIo): Promise<number> {\n\tif (args[0] !== \"abai\") {\n\t\t// the entry is one of the five attach places (4.3): a launched program takes up its connection here,\n\t\t// before its own work, so its first touchpoint finds the agent present\n\t\tif (app.launched) await app.attach();\n\t\treturn -1;\n\t}\n\tconst { manifest } = app;\n\tconst usage = (problem?: string): number => {\n\t\tif (problem !== undefined) io.err(`${manifest.entry}: ${problem}`);\n\t\tfor (const line of usageLines(manifest.entry)) io.err(line);\n\t\treturn 2;\n\t};\n\ttry {\n\t\tconst verb = args[1];\n\t\tswitch (verb) {\n\t\t\tcase \"manifest\": {\n\t\t\t\tconst flags = parseFlags(args.slice(2), [\"--json\"]);\n\t\t\t\tif (typeof flags === \"string\") return usage(flags);\n\t\t\t\t// a selected mode the manifest does not declare is an error at the entry (section 4.4)\n\t\t\t\tconst selected = io.env[ENV_MODE]?.trim();\n\t\t\t\tif (selected !== undefined && selected !== \"\" && !(manifest.modes as string[]).includes(selected)) {\n\t\t\t\t\tio.err(\n\t\t\t\t\t\t`${manifest.entry}: ${ENV_MODE}=${selected} is not a declared mode (declared: ${manifest.modes.join(\", \")})`,\n\t\t\t\t\t);\n\t\t\t\t\treturn 2;\n\t\t\t\t}\n\t\t\t\tio.out(flags.json ? `${JSON.stringify(manifest, null, 2)}\\n` : renderManifestYaml(manifest));\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\tcase \"doctor\": {\n\t\t\t\tconst flags = parseFlags(args.slice(2), [\"--json\", \"--root\", \"--offline\"]);\n\t\t\t\tif (typeof flags === \"string\") return usage(flags);\n\t\t\t\tconst report = await runDoctor(app, { root: flags.root, io, online: !flags.offline });\n\t\t\t\tif (flags.json) io.out(`${JSON.stringify(report, null, 2)}\\n`);\n\t\t\t\telse printReport(report, io);\n\t\t\t\treturn report.ok ? 0 : 1;\n\t\t\t}\n\t\t\tcase undefined:\n\t\t\tcase \"session\": {\n\t\t\t\tawait app.session();\n\t\t\t\tif (app.attached) return 0;\n\t\t\t\tio.err(`${manifest.entry}: no harness attached (${app.attachError ?? \"unknown reason\"})`);\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t\tcase \"install\": {\n\t\t\t\tawait app.install();\n\t\t\t\tif (app.attached) return 0;\n\t\t\t\tio.err(`${manifest.entry}: no harness attached (${app.attachError ?? \"unknown reason\"})`);\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t\tcase \"config\": {\n\t\t\t\tconst harness = await importHarnessModule(io.env, manifest);\n\t\t\t\tif (!harness?.runConfig) return usage(\"config needs the harness package, which is not installed\");\n\t\t\t\treturn await harness.runConfig(args.slice(2), io, { program: manifest.name });\n\t\t\t}\n\t\t\tcase \"mcp\": {\n\t\t\t\t// the program at its entry serves an MCP client: under sidecar through the binary on this\n\t\t\t\t// process's stdio, otherwise in-process through the installed harness package (section 4.4).\n\t\t\t\t// ABAI_HARNESS is honoured like everywhere: off attaches nothing, a null harness is attached already\n\t\t\t\tif (app.harnessSelection === \"off\") {\n\t\t\t\t\tio.err(`${manifest.entry}: no harness attached (${ENV_HARNESS}=off)`);\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\t\t\t\tif (app.attached) {\n\t\t\t\t\tio.err(`${manifest.entry}: ${manifest.name} already has a harness attached`);\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\t\t\t\tif (app.endpoint !== undefined) {\n\t\t\t\t\tconst code = await app.serveMcpSidecar(app.endpoint);\n\t\t\t\t\tif (code >= 0) return code;\n\t\t\t\t\tio.err(`${manifest.entry}: no harness attached (${app.attachError ?? \"unknown reason\"})`);\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\t\t\t\tconst harness = await importHarnessModule(io.env, manifest);\n\t\t\t\tif (!harness?.serveMcpEmbedded) return usage(\"mcp needs the harness package, which is not installed\");\n\t\t\t\tconst binding = app.bind(\"mcp\");\n\t\t\t\tbinding.enterSafepoint();\n\t\t\t\ttry {\n\t\t\t\t\treturn await harness.serveMcpEmbedded(binding);\n\t\t\t\t} finally {\n\t\t\t\t\tbinding.leaveSafepoint();\n\t\t\t\t}\n\t\t\t}\n\t\t\tcase \"run\": {\n\t\t\t\t// sidecar launch (4.4, 6.3): the harness binary starts this very program again as its child\n\t\t\t\tif (!(manifest.modes as string[]).includes(\"sidecar\")) {\n\t\t\t\t\tio.err(\n\t\t\t\t\t\t`${manifest.entry}: run is sidecar launch, and ${manifest.name} declares ${manifest.modes.join(\", \")}`,\n\t\t\t\t\t);\n\t\t\t\t\treturn 2;\n\t\t\t\t}\n\t\t\t\tconst separator = args.indexOf(\"--\");\n\t\t\t\tconst flags = args.slice(2, separator === -1 ? undefined : separator);\n\t\t\t\tconst programArgs = separator === -1 ? [] : args.slice(separator + 1);\n\t\t\t\tfor (const flag of flags) {\n\t\t\t\t\tif (flag !== \"--auto\" && flag !== \"--deny-mutate\" && flag !== \"--all-events\") {\n\t\t\t\t\t\treturn usage(`unknown option ${flag} (run takes --auto, --deny-mutate, --all-events)`);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst binary = harnessBinary(io.env, app.content.root);\n\t\t\t\tconst script = process.argv[1];\n\t\t\t\tif (script === undefined) return usage(\"run cannot tell how this program was started\");\n\t\t\t\tconst command = [process.execPath, ...process.execArgv, script, ...programArgs];\n\t\t\t\tconst child = spawn(binary.command, [...binary.args, \"run\", ...flags, \"--\", ...command], {\n\t\t\t\t\tstdio: \"inherit\",\n\t\t\t\t\tenv: { ...process.env, ...io.env },\n\t\t\t\t});\n\t\t\t\t// whoever ends this process ends the launcher behind it, which ends the program it supervises\n\t\t\t\tconst forward = (signal: NodeJS.Signals): void => {\n\t\t\t\t\tif (child.exitCode === null && child.signalCode === null) child.kill(signal);\n\t\t\t\t};\n\t\t\t\tconst forwarded: NodeJS.Signals[] = [\"SIGTERM\", \"SIGINT\", \"SIGHUP\"];\n\t\t\t\tfor (const signal of forwarded) process.on(signal, forward);\n\t\t\t\ttry {\n\t\t\t\t\treturn await new Promise<number>((resolve) => {\n\t\t\t\t\t\tchild.once(\"error\", (error) => {\n\t\t\t\t\t\t\tio.err(`${manifest.entry}: the harness binary could not be started: ${errorMessage(error)}`);\n\t\t\t\t\t\t\tresolve(1);\n\t\t\t\t\t\t});\n\t\t\t\t\t\tchild.once(\"exit\", (code) => resolve(code ?? 1));\n\t\t\t\t\t});\n\t\t\t\t} finally {\n\t\t\t\t\tfor (const signal of forwarded) process.off(signal, forward);\n\t\t\t\t}\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\treturn usage(`unknown verb ${verb}`);\n\t\t}\n\t} catch (error) {\n\t\tio.err(`${manifest.entry}: ${errorMessage(error)}`);\n\t\treturn 2;\n\t}\n}\n"]}
@@ -1,5 +1,5 @@
1
- import { type AuditTail } from "./audit.ts";
2
- import { type DecisionDecl, type FieldSchema, type Manifest, type TurnDecl } from "./manifest/manifest.ts";
1
+ import { type AuditTail, type MessageRecord } from "./audit.ts";
2
+ import { type DecisionDecl, type FieldSchema, type Manifest, type Mode, type TurnDecl } from "./manifest/manifest.ts";
3
3
  import type { Abaigram, AttachedHarness, CounterSnapshot } from "./program.ts";
4
4
  import type { WireErrorCode } from "./wire/protocol.ts";
5
5
  export interface DecisionRequest {
@@ -90,6 +90,8 @@ export interface HarnessBinding {
90
90
  readonly manifest: Manifest;
91
91
  readonly name: string;
92
92
  readonly connection: string;
93
+ /** The mode this run selected (section 4.4). A harness follows it, not the first declared mode. */
94
+ readonly mode: Mode;
93
95
  content(): {
94
96
  identity: string;
95
97
  install: string | undefined;
@@ -109,6 +111,14 @@ export interface HarnessBinding {
109
111
  path: string;
110
112
  failed: string | null;
111
113
  };
114
+ /**
115
+ * One message the agent sent to or received from a member of the run's
116
+ * network (section 10): written to the audit log as `act: message`. Not
117
+ * an act of control: no policy, no consent, no counter. Every string of
118
+ * the record is cut to a bound first. False when nothing was written: the
119
+ * log is closed (the binding detached) or has failed.
120
+ */
121
+ recordMessage(record: MessageRecord, conn?: string): boolean;
112
122
  takeCounters(): CounterSnapshot;
113
123
  on<K extends keyof BindingEvents>(type: K, listener: BindingEvents[K]): () => void;
114
124
  /** Answer a pending decision; `null` means "apply the default" with this reason. Throws when the answer is invalid. */
@@ -154,6 +164,7 @@ export declare class DirectBinding implements HarnessBinding, AttachedHarness {
154
164
  readonly manifest: Manifest;
155
165
  readonly name: string;
156
166
  readonly connection: string;
167
+ readonly mode: Mode;
157
168
  private readonly app;
158
169
  private readonly audit;
159
170
  private readonly listeners;
@@ -194,6 +205,7 @@ export declare class DirectBinding implements HarnessBinding, AttachedHarness {
194
205
  private live;
195
206
  writeKnob(name: string, value: unknown, reason: string, consent?: Consent, conn?: string): Promise<KnobWriteOutcome>;
196
207
  call(name: string, params: Record<string, unknown> | undefined, reason: string, consent?: Consent, conn?: string): Promise<unknown>;
208
+ recordMessage(record: MessageRecord, conn?: string): boolean;
197
209
  auditTail(limit: number): AuditTail;
198
210
  auditInfo(): {
199
211
  path: string;
@@ -1 +1 @@
1
- {"version":3,"file":"harness-binding.d.ts","sourceRoot":"","sources":["../src/harness-binding.ts"],"names":[],"mappings":"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","sourcesContent":["// The direct face (abaigrammar section 4.1): what the stub hands a harness\n// that attaches in-process. One object serves both sides. To the program it\n// is the AttachedHarness that decisions, turns, touchpoints and emits reach;\n// to the harness it is the channels: cells and events to read, knobs to\n// write, capabilities to call, decisions and turns to answer, the audit log\n// to tail, the counters to take. Every act of control is audited here, on\n// the program side, as section 10 says, with the consent the harness states\n// for an act whose policy is `confirm`.\nimport { resolve } from \"node:path\";\nimport { AuditLog, type AuditOutcome, type AuditTail, capValue, summarizeAnswer } from \"./audit.ts\";\nimport { validateKnobValue } from \"./cells/fit.ts\";\nimport { expandHome } from \"./env.ts\";\nimport {\n\ttype CapabilityDecl,\n\ttype DecisionDecl,\n\tdurationMs,\n\ttype FieldSchema,\n\tfieldOf,\n\ttype Manifest,\n\tmatchesType,\n\ttype TurnDecl,\n} from \"./manifest/manifest.ts\";\nimport type { Abaigram, AttachedHarness, CounterSnapshot } from \"./program.ts\";\nimport type { EventSlot } from \"./region.ts\";\nimport type { WireErrorCode } from \"./wire/protocol.ts\";\n\nexport interface DecisionRequest {\n\tid: string;\n\tname: string;\n\tdecision: DecisionDecl;\n\tcontext: Record<string, unknown>;\n\t/** Epoch milliseconds by which an answer must arrive. */\n\tdeadline: number;\n}\n\nexport interface TurnRequest {\n\tid: string;\n\tname: string;\n\tturn: TurnDecl;\n\tdeadline: number;\n\t/** The content slot for this turn, when the program has one. */\n\tcontent: string | undefined;\n}\n\nexport type TouchpointKind = \"install\" | \"session\";\n\nexport interface TouchpointRequest {\n\tid: string;\n\tkind: TouchpointKind;\n\tcontent: string | undefined;\n}\n\nexport interface LiveEvent {\n\tseq: number;\n\tname: string;\n\tpayload: Record<string, unknown> | undefined;\n\ttruncated: boolean;\n\tts: number;\n}\n\nexport interface EventBatch {\n\tevents: LiveEvent[];\n\t/** Events overwritten before they were read; the harness synthesizes `abai.events.dropped` from it. */\n\tdropped: number;\n\tnext: number;\n}\n\nexport interface CellReading {\n\tvalue: unknown;\n\tversion: number;\n}\n\nexport interface KnobWriteOutcome {\n\tvalue: unknown;\n\toutcome: \"done\" | \"failed\";\n\terror?: string;\n\t/** Why it failed, in the capability error vocabulary (the endpoint sends it under `call_codes`). */\n\tcode?: CallErrorCode;\n}\n\n/**\n * What the harness states about an act whose policy is `confirm` (section\n * 10): a person approved it, the harness approved it without asking (auto\n * mode, or the exercise form standing in for the abaigrammer), or it was\n * denied. An act under `auto` policy needs none.\n */\nexport type Consent = \"approved\" | \"auto\" | \"denied\";\n\n/** Why a call failed: the one vocabulary, in process and on the wire. */\nexport type CallErrorCode = WireErrorCode;\n\nexport type LifecycleOutcome = { ok: true; data?: unknown } | { ok: false; code: CallErrorCode; error: string };\n\n/** A capability call that did not return a result. */\nexport class CallError extends Error {\n\treadonly code: CallErrorCode;\n\tconstructor(code: CallErrorCode, message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"CallError\";\n\t\tthis.code = code;\n\t}\n}\n\nexport interface BindingEvents {\n\tevent: (event: LiveEvent) => void;\n\tdecision: (request: DecisionRequest) => void;\n\t/** The decision expired: the program applied the default. */\n\tdecision_timeout: (id: string, name: string) => void;\n\tturn: (request: TurnRequest) => void;\n\ttouchpoint: (request: TouchpointRequest) => void;\n\tdetach: (reason: string) => void;\n}\n\n/**\n * The harness's view of the stub, in-process. The optional trailing `conn`\n * of the acting methods names the connection that acts, for a front end\n * that multiplexes several (the sidecar endpoint); the audit record carries\n * it. An in-process harness passes none and is audited under the binding's\n * own label.\n */\nexport interface HarnessBinding {\n\treadonly manifest: Manifest;\n\treadonly name: string;\n\treadonly connection: string;\n\tcontent(): {\n\t\tidentity: string;\n\t\tinstall: string | undefined;\n\t\tuse: string | undefined;\n\t\tturn(name: string): string | undefined;\n\t};\n\treadCells(names?: string[]): { seq: number; cells: Record<string, CellReading> };\n\treadEvents(after: number): EventBatch;\n\twriteKnob(name: string, value: unknown, reason: string, consent?: Consent, conn?: string): Promise<KnobWriteOutcome>;\n\tcall(\n\t\tname: string,\n\t\tparams: Record<string, unknown> | undefined,\n\t\treason: string,\n\t\tconsent?: Consent,\n\t\tconn?: string,\n\t): Promise<unknown>;\n\tauditTail(limit: number): AuditTail;\n\t/** Where the audit log is, and the error that latched it off, if any. */\n\tauditInfo(): { path: string; failed: string | null };\n\ttakeCounters(): CounterSnapshot;\n\ton<K extends keyof BindingEvents>(type: K, listener: BindingEvents[K]): () => void;\n\t/** Answer a pending decision; `null` means \"apply the default\" with this reason. Throws when the answer is invalid. */\n\tanswerDecision(id: string, answer: unknown, reason: string, consent?: Consent, conn?: string): void;\n\t/**\n\t * Let a pending decision take its default now, for a cause of the front\n\t * end's: `no_harness` when nobody holds it, `timeout` when a claim's own\n\t * shorter wait ran out, `detached` when its claimant went away. Audited\n\t * like every other settlement, and `decision_timeout` is notified for a\n\t * timeout, so one path serves every cause.\n\t */\n\tdefaultDecision(id: string, cause: string, conn?: string): void;\n\t/** @internal Name the connection that was asked a pending decision, so its settlement is audited under it. */\n\tassignDecision(id: string, conn: string): void;\n\tpendingDecisions(): DecisionRequest[];\n\t/** End a turn. `cause` says why the agent did nothing with it (the grammar's `budget`), and is audited. */\n\tendTurn(id: string, conn?: string, cause?: string): void;\n\tendTouchpoint(id: string): void;\n\t/**\n\t * A lifecycle operation of the program's own (section 5.5): `status`,\n\t * `pause` and `resume` for a cooperative pause, `stop` for the declared\n\t * stop handler. Policy and consent are checked here like any act of\n\t * control, and the acts that change something are audited.\n\t */\n\tlifecycle(op: string, reason: string, consent?: Consent, conn?: string): LifecycleOutcome;\n\tdetach(reason: string): void;\n\treadonly attached: boolean;\n}\n\ninterface Pending<T> {\n\tresolve: (value: T) => void;\n\treject: (error: Error) => void;\n\ttimer: NodeJS.Timeout | undefined;\n\tstartedAt: number;\n\t/** The connection this was asked of, when a front end named one. */\n\tconn?: string;\n}\n\n/**\n * A touchpoint has no timeout of its own, so nothing of the program's holds\n * its event loop open while a harness in another process holds the\n * touchpoint; this ref'd timer does, and never fires in practice (the\n * longest delay a timer takes). Cleared when the touchpoint ends.\n */\nconst TOUCHPOINT_KEEPALIVE_MS = 2 ** 31 - 1;\n\nexport interface BindingOptions {\n\t/** Where the audit log goes; default: the manifest's path, `~` expanded, relative to the program's root. */\n\tauditPath?: string;\n\tconnection?: string;\n}\n\n/**\n * Check a value against a schema: an object with no undeclared field, whose\n * every present field is of its declared type. A declared field may be\n * absent (decided 2026-10-14: the schema language has no required marker,\n * and a manifest's own defaults omit fields); `nullable` governs an\n * explicit null. Nested objects and lists are checked by `matchesType`.\n */\nexport function schemaProblem(schema: Record<string, FieldSchema>, value: unknown, what: string): string | undefined {\n\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) return `${what} must be an object`;\n\tconst record = value as Record<string, unknown>;\n\tfor (const [key, field] of Object.entries(schema)) {\n\t\tconst item = record[key];\n\t\tif (item === undefined) continue;\n\t\tif (!matchesType(item, field)) return `${what}.${key} must be a ${fieldOf(field).type}`;\n\t}\n\tfor (const key of Object.keys(record)) {\n\t\tif (!(key in schema)) return `${what} has an undeclared field ${key}`;\n\t}\n\treturn undefined;\n}\n\nfunction errorMessage(error: unknown): string {\n\treturn error instanceof Error ? error.message : String(error);\n}\n\nfunction consentGranted(consent: Consent | undefined): boolean {\n\treturn consent === \"approved\" || consent === \"auto\";\n}\n\nexport class DirectBinding implements HarnessBinding, AttachedHarness {\n\treadonly manifest: Manifest;\n\treadonly name: string;\n\treadonly connection: string;\n\tprivate readonly app: Abaigram;\n\tprivate readonly audit: AuditLog;\n\tprivate readonly listeners: { [K in keyof BindingEvents]: Set<BindingEvents[K]> } = {\n\t\tevent: new Set(),\n\t\tdecision: new Set(),\n\t\tdecision_timeout: new Set(),\n\t\tturn: new Set(),\n\t\ttouchpoint: new Set(),\n\t\tdetach: new Set(),\n\t};\n\tprivate readonly decisions = new Map<string, Pending<unknown> & { request: DecisionRequest }>();\n\tprivate readonly turns = new Map<string, Pending<void> & { request: TurnRequest }>();\n\tprivate readonly touchpoints = new Map<string, Pending<void> & { request: TouchpointRequest }>();\n\tprivate readonly capabilityIndex = new Map<string, CapabilityDecl>();\n\t/** Touchpoints in progress: while one is open the program sits at a safepoint, so queued work runs at once (section 5.3). */\n\tprivate openTouchpoints = 0;\n\tprivate nextId = 1;\n\tprivate _attached = true;\n\n\tconstructor(app: Abaigram, options: BindingOptions = {}) {\n\t\tthis.app = app;\n\t\tthis.manifest = app.manifest;\n\t\tthis.name = app.manifest.name;\n\t\tthis.connection = options.connection ?? \"direct\";\n\t\tfor (const capability of this.manifest.capabilities) this.capabilityIndex.set(capability.name, capability);\n\t\tconst auditPath = options.auditPath ?? resolve(app.content.root, expandHome(this.manifest.audit.path));\n\t\tthis.audit = new AuditLog(auditPath, (error) => {\n\t\t\tapp.emitLibrary(\"abai.audit.failed\", { error });\n\t\t});\n\t}\n\n\tget attached(): boolean {\n\t\treturn this._attached;\n\t}\n\n\t/** @internal Called by the program once the binding is set: the counters go to the log first (section 10). */\n\tflushCounters(): void {\n\t\tconst counters = this.app.takeCounters();\n\t\tfor (const [name, count] of Object.entries(counters)) {\n\t\t\tif (count === 0) continue;\n\t\t\tconst cause = name === \"abai.mode_fallback\" ? \"mode_fallback\" : \"no_harness\";\n\t\t\tthis.audit.append({ act: \"counters\", name, outcome: \"default\", cause, count });\n\t\t}\n\t}\n\n\t/** Queue work for the program's next safepoint, or run it now when a touchpoint holds the program at one. */\n\tprivate atSafepoint(work: () => void): void {\n\t\tthis.app.enqueue(work);\n\t\tif (this.openTouchpoints > 0) this.app.drain();\n\t}\n\n\t/**\n\t * @internal The program is at a safepoint and will stay there (its entry\n\t * serving an MCP client): safepoint-dispatched work runs at once rather\n\t * than waiting for a safepoint the program would never reach. Paired\n\t * with `leaveSafepoint`.\n\t */\n\tenterSafepoint(): void {\n\t\tthis.openTouchpoints += 1;\n\t\tthis.app.drain();\n\t}\n\n\t/** @internal */\n\tleaveSafepoint(): void {\n\t\tif (this.openTouchpoints > 0) this.openTouchpoints -= 1;\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Harness side\n\t// -----------------------------------------------------------------------\n\n\tcontent(): {\n\t\tidentity: string;\n\t\tinstall: string | undefined;\n\t\tuse: string | undefined;\n\t\tturn(name: string): string | undefined;\n\t} {\n\t\tconst slots = this.app.content;\n\t\treturn {\n\t\t\tidentity: slots.identity(),\n\t\t\tinstall: slots.install(),\n\t\t\tuse: slots.use(),\n\t\t\tturn: (name) => slots.turn(name),\n\t\t};\n\t}\n\n\treadCells(names?: string[]): { seq: number; cells: Record<string, CellReading> } {\n\t\tconst all = this.app.readCells();\n\t\tconst cells: Record<string, CellReading> = {};\n\t\tfor (const name of names ?? Object.keys(all)) {\n\t\t\tif (!(name in all)) throw new Error(`unknown cell: ${name}`);\n\t\t\tcells[name] = { value: all[name], version: this.app.version(name) };\n\t\t}\n\t\treturn { seq: this.app.region.lastSeq, cells };\n\t}\n\n\treadEvents(after: number): EventBatch {\n\t\tconst read = this.app.region.readEvents(after);\n\t\treturn { events: read.slots.map((slot) => this.live(slot)), dropped: read.dropped, next: read.next };\n\t}\n\n\tprivate live(slot: EventSlot): LiveEvent {\n\t\treturn {\n\t\t\tseq: slot.seq,\n\t\t\tname: this.app.eventName(slot.event),\n\t\t\tpayload: slot.payload,\n\t\t\ttruncated: slot.truncated,\n\t\t\tts: slot.ts,\n\t\t};\n\t}\n\n\tasync writeKnob(\n\t\tname: string,\n\t\tvalue: unknown,\n\t\treason: string,\n\t\tconsent?: Consent,\n\t\tconn?: string,\n\t): Promise<KnobWriteOutcome> {\n\t\tconst decl = this.manifest.cells.find((cell) => cell.name === name);\n\t\tconst started = this.app.now();\n\t\tconst record = (\n\t\t\toutcome: AuditOutcome,\n\t\t\tlanded: unknown,\n\t\t\terror?: string,\n\t\t\tcause?: CallErrorCode,\n\t\t): KnobWriteOutcome => {\n\t\t\tthis.audit.append({\n\t\t\t\tconn: conn ?? this.connection,\n\t\t\t\tact: \"knob\",\n\t\t\t\tname,\n\t\t\t\tvalue: capValue(landed),\n\t\t\t\toutcome,\n\t\t\t\t...(cause === undefined ? {} : { cause }),\n\t\t\t\t...(consent === undefined ? {} : { consent }),\n\t\t\t\treason,\n\t\t\t\t...(error === undefined ? {} : { error }),\n\t\t\t\tms: this.app.now() - started,\n\t\t\t});\n\t\t\treturn outcome === \"ok\"\n\t\t\t\t? { value: landed, outcome: \"done\" }\n\t\t\t\t: { value: landed, outcome: \"failed\", error, ...(cause === undefined ? {} : { code: cause }) };\n\t\t};\n\t\tif (!decl) return record(\"error\", undefined, `unknown cell: ${name}`, \"unknown\");\n\t\tif (decl.access !== \"readwrite\") return record(\"error\", undefined, `${name} is read-only`, \"invalid\");\n\t\tif (decl.policy === \"confirm\" && !consentGranted(consent)) {\n\t\t\treturn record(\"error\", undefined, `${name} needs consent (its policy is confirm)`, \"denied\");\n\t\t}\n\t\tconst problem = validateKnobValue(decl, value);\n\t\tif (problem !== undefined) return record(\"error\", undefined, problem, \"invalid\");\n\t\tconst sized = decl.type === \"string\" || decl.type === \"object\" || decl.type === \"list\";\n\t\tif (!sized) {\n\t\t\tthis.app.knob(name).set(value);\n\t\t\treturn record(\"ok\", this.app.cell(name).get());\n\t\t}\n\t\t// a sized knob is delivered at the program's next safepoint, to its handler, within its delivery timeout (section 5.2)\n\t\tconst handler = this.app.knobHandler(name);\n\t\tif (!handler) {\n\t\t\treturn record(\"failed\", undefined, `no handler registered for ${name}: nothing can receive it`, \"error\");\n\t\t}\n\t\tconst timeoutMs = durationMs(decl.timeout ?? \"30s\");\n\t\treturn new Promise<KnobWriteOutcome>((done) => {\n\t\t\tlet settled = false;\n\t\t\tconst work = (): void => {\n\t\t\t\tif (settled) return;\n\t\t\t\tsettled = true;\n\t\t\t\tclearTimeout(timer);\n\t\t\t\tthis.app.cell(name).set(value);\n\t\t\t\tconst landed = this.app.cell(name).get();\n\t\t\t\ttry {\n\t\t\t\t\thandler(landed);\n\t\t\t\t\tdone(record(\"ok\", landed));\n\t\t\t\t} catch (error) {\n\t\t\t\t\tdone(record(\"error\", landed, errorMessage(error), \"error\"));\n\t\t\t\t}\n\t\t\t};\n\t\t\tconst timer = setTimeout(() => {\n\t\t\t\tif (settled) return;\n\t\t\t\tsettled = true;\n\t\t\t\tthis.app.dequeue(work);\n\t\t\t\tdone(\n\t\t\t\t\trecord(\n\t\t\t\t\t\t\"failed\",\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t`not delivered within ${decl.timeout ?? \"30s\"}: the program reached no safepoint`,\n\t\t\t\t\t\t\"timeout\",\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}, timeoutMs);\n\t\t\ttimer.unref();\n\t\t\tthis.atSafepoint(work);\n\t\t});\n\t}\n\n\tasync call(\n\t\tname: string,\n\t\tparams: Record<string, unknown> | undefined,\n\t\treason: string,\n\t\tconsent?: Consent,\n\t\tconn?: string,\n\t): Promise<unknown> {\n\t\tconst decl = this.capabilityIndex.get(name);\n\t\tconst started = this.app.now();\n\t\tconst record = (outcome: AuditOutcome, extra: { error?: string; cause?: string } = {}): void => {\n\t\t\tthis.audit.append({\n\t\t\t\tconn: conn ?? this.connection,\n\t\t\t\tact: \"capability\",\n\t\t\t\tname,\n\t\t\t\tparams: capValue(params),\n\t\t\t\toutcome,\n\t\t\t\t...(consent === undefined ? {} : { consent }),\n\t\t\t\treason,\n\t\t\t\t...extra,\n\t\t\t\tms: this.app.now() - started,\n\t\t\t});\n\t\t};\n\t\tconst fail = (code: CallErrorCode, message: string): CallError => {\n\t\t\trecord(code === \"forbidden\" ? \"forbidden\" : \"error\", { error: message, cause: code });\n\t\t\treturn new CallError(code, message);\n\t\t};\n\t\tif (!decl) throw fail(\"unknown\", `${this.name} declares no capability ${name}`);\n\t\tif (decl.policy === \"forbid\") throw fail(\"forbidden\", `the program's policy forbids ${name}`);\n\t\tif (decl.policy === \"confirm\" && !consentGranted(consent))\n\t\t\tthrow fail(\"denied\", `${name} needs consent (its policy is confirm)`);\n\t\tconst problem = schemaProblem(decl.params, params ?? {}, \"params\");\n\t\tif (problem !== undefined) throw fail(\"invalid\", problem);\n\t\tconst timeoutMs = durationMs(decl.timeout ?? \"30s\");\n\t\tconst result = await new Promise<unknown>((done, reject) => {\n\t\t\tlet settled = false;\n\t\t\tconst settle = (fn: () => void): void => {\n\t\t\t\tif (settled) return;\n\t\t\t\tsettled = true;\n\t\t\t\tclearTimeout(timer);\n\t\t\t\tfn();\n\t\t\t};\n\t\t\t// the handler is resolved at dispatch, so one registered after startup still serves\n\t\t\tconst run = (): void => {\n\t\t\t\tif (settled) return;\n\t\t\t\tconst handler = this.app.capabilityHandler(name);\n\t\t\t\tif (!handler) {\n\t\t\t\t\tsettle(() => reject(new CallError(\"error\", `${name} has no handler registered`)));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tlet outcome: unknown;\n\t\t\t\ttry {\n\t\t\t\t\toutcome = handler(params ?? {}); // synchronous part runs inside the safepoint, on the program's thread\n\t\t\t\t} catch (error) {\n\t\t\t\t\tsettle(() => reject(new CallError(\"error\", errorMessage(error))));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tPromise.resolve(outcome).then(\n\t\t\t\t\t(value) => settle(() => done(value)),\n\t\t\t\t\t(error) => settle(() => reject(new CallError(\"error\", errorMessage(error)))),\n\t\t\t\t);\n\t\t\t};\n\t\t\tconst timer = setTimeout(() => {\n\t\t\t\tif (settled) return;\n\t\t\t\tsettled = true;\n\t\t\t\tthis.app.dequeue(run);\n\t\t\t\treject(new CallError(\"timeout\", `${name} did not answer within ${decl.timeout ?? \"30s\"}`));\n\t\t\t}, timeoutMs);\n\t\t\ttimer.unref();\n\t\t\tif (decl.dispatch === \"immediate\") run();\n\t\t\telse this.atSafepoint(run);\n\t\t}).catch((error: CallError) => {\n\t\t\trecord(\"error\", { error: error.message, cause: error.code });\n\t\t\tthrow error;\n\t\t});\n\t\trecord(\"ok\");\n\t\treturn result;\n\t}\n\n\tauditTail(limit: number): AuditTail {\n\t\treturn this.audit.tail(limit);\n\t}\n\n\tauditInfo(): { path: string; failed: string | null } {\n\t\treturn { path: this.audit.path, failed: this.audit.failed ?? null };\n\t}\n\n\ttakeCounters(): CounterSnapshot {\n\t\treturn this.app.takeCounters();\n\t}\n\n\ton<K extends keyof BindingEvents>(type: K, listener: BindingEvents[K]): () => void {\n\t\tconst set = this.listeners[type] as Set<BindingEvents[K]>;\n\t\tset.add(listener);\n\t\treturn () => {\n\t\t\tset.delete(listener);\n\t\t};\n\t}\n\n\tprivate notify<K extends keyof BindingEvents>(type: K, ...args: Parameters<BindingEvents[K]>): void {\n\t\tfor (const listener of this.listeners[type]) {\n\t\t\ttry {\n\t\t\t\t(listener as (...a: Parameters<BindingEvents[K]>) => void)(...args);\n\t\t\t} catch {\n\t\t\t\t// a harness listener's failure never reaches the program\n\t\t\t}\n\t\t}\n\t}\n\n\tanswerDecision(id: string, answer: unknown, reason: string, consent?: Consent, conn?: string): void {\n\t\tconst pending = this.decisions.get(id);\n\t\tif (!pending) throw new Error(`no pending decision ${id}`);\n\t\tif (reason.trim() === \"\") throw new Error(\"a decision needs a reason\");\n\t\tif (conn !== undefined) pending.conn = conn;\n\t\tconst { decision } = pending.request;\n\t\tif (answer !== null) {\n\t\t\tconst problem = decision.options\n\t\t\t\t? decision.options.includes(answer as string)\n\t\t\t\t\t? undefined\n\t\t\t\t\t: `answer must be one of: ${decision.options.join(\", \")}`\n\t\t\t\t: schemaProblem(decision.answer ?? {}, answer, \"answer\");\n\t\t\tif (problem !== undefined) {\n\t\t\t\tthis.settleDecision(id, { source: \"default\", cause: \"invalid\", reason, answer });\n\t\t\t\tthrow new Error(problem);\n\t\t\t}\n\t\t\tif (decision.policy === \"confirm\" && !consentGranted(consent)) {\n\t\t\t\tthis.settleDecision(id, { source: \"default\", cause: \"denied\", reason, consent });\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tthis.settleDecision(\n\t\t\tid,\n\t\t\tanswer === null\n\t\t\t\t? { source: \"default\", cause: \"answered\", reason }\n\t\t\t\t: { source: \"agent\", reason, answer, consent },\n\t\t);\n\t}\n\n\tdefaultDecision(id: string, cause: string, conn?: string): void {\n\t\tconst pending = this.decisions.get(id);\n\t\tif (!pending) return;\n\t\tif (conn !== undefined) pending.conn = conn;\n\t\tthis.settleDecision(id, { source: \"default\", cause });\n\t}\n\n\tassignDecision(id: string, conn: string): void {\n\t\tconst pending = this.decisions.get(id);\n\t\tif (pending) pending.conn = conn;\n\t}\n\n\tpendingDecisions(): DecisionRequest[] {\n\t\treturn [...this.decisions.values()].map((p) => p.request);\n\t}\n\n\tprivate settleDecision(\n\t\tid: string,\n\t\toutcome: { source: \"agent\" | \"default\"; cause?: string; reason?: string; answer?: unknown; consent?: Consent },\n\t): void {\n\t\tconst pending = this.decisions.get(id);\n\t\tif (!pending) return;\n\t\tthis.decisions.delete(id);\n\t\tif (pending.timer) clearTimeout(pending.timer);\n\t\tthis.openTouchpoints -= 1;\n\t\tconst { decision } = pending.request;\n\t\tthis.audit.append({\n\t\t\tconn: pending.conn ?? this.connection,\n\t\t\tact: \"decision\",\n\t\t\tname: decision.name,\n\t\t\tid,\n\t\t\tvalue: summarizeAnswer(decision, outcome.source === \"agent\" ? outcome.answer : decision.default),\n\t\t\toutcome: outcome.source,\n\t\t\t...(outcome.cause === undefined ? {} : { cause: outcome.cause }),\n\t\t\t...(outcome.consent === undefined ? {} : { consent: outcome.consent }),\n\t\t\t...(outcome.reason === undefined ? {} : { reason: outcome.reason }),\n\t\t\tms: this.app.now() - pending.startedAt,\n\t\t});\n\t\tif (outcome.source === \"agent\") pending.resolve(outcome.answer);\n\t\telse pending.reject(new Error(outcome.cause ?? \"default\"));\n\t\tif (outcome.cause === \"timeout\") this.notify(\"decision_timeout\", id, decision.name);\n\t}\n\n\tendTurn(id: string, conn?: string, cause?: string): void {\n\t\tconst pending = this.turns.get(id);\n\t\tif (!pending) return;\n\t\tif (conn !== undefined) pending.conn = conn;\n\t\t// a turn the agent did nothing with (held back by its budget) is a default, with the cause it names\n\t\tif (cause === undefined) this.settleTurn(id, \"ok\");\n\t\telse this.settleTurn(id, \"default\", cause);\n\t}\n\n\t/** @internal Queue work for the program's next safepoint, running it now when one is held open. */\n\tatNextSafepoint(work: () => void): void {\n\t\tthis.atSafepoint(work);\n\t}\n\n\tlifecycle(op: string, reason: string, consent?: Consent, conn?: string): LifecycleOutcome {\n\t\tconst declared = this.manifest.lifecycle;\n\t\tconst started = this.app.now();\n\t\tconst record = (outcome: AuditOutcome, extra: { cause?: string; error?: string } = {}): void => {\n\t\t\tthis.audit.append({\n\t\t\t\tconn: conn ?? this.connection,\n\t\t\t\tact: \"lifecycle\",\n\t\t\t\tname: op,\n\t\t\t\toutcome,\n\t\t\t\t...(consent === undefined ? {} : { consent }),\n\t\t\t\treason,\n\t\t\t\t...extra,\n\t\t\t\tms: this.app.now() - started,\n\t\t\t});\n\t\t};\n\t\tconst refuse = (code: CallErrorCode, error: string): LifecycleOutcome => {\n\t\t\trecord(code === \"forbidden\" ? \"forbidden\" : \"error\", { cause: code, error });\n\t\t\treturn { ok: false, code, error };\n\t\t};\n\t\tif (op === \"status\") return { ok: true, data: this.app.lifecycleStatus() };\n\t\tif (op !== \"pause\" && op !== \"resume\" && op !== \"stop\" && op !== \"restart\" && op !== \"start\") {\n\t\t\treturn { ok: false, code: \"unknown\", error: `unknown lifecycle operation: ${op}` };\n\t\t}\n\t\t// section 10: pause and resume are auto, stop and restart confirm, unless the manifest says otherwise\n\t\tconst policy =\n\t\t\tdeclared?.policy?.[op as \"pause\" | \"resume\" | \"stop\" | \"restart\"] ??\n\t\t\t(op === \"stop\" || op === \"restart\" ? \"confirm\" : \"auto\");\n\t\tif (policy === \"forbid\") return refuse(\"forbidden\", `the program's policy forbids lifecycle ${op}`);\n\t\tif (policy === \"confirm\" && !consentGranted(consent)) {\n\t\t\treturn refuse(\"denied\", `lifecycle ${op} needs consent (its policy is confirm)`);\n\t\t}\n\t\tswitch (op) {\n\t\t\tcase \"pause\":\n\t\t\t\tif (declared?.pause !== \"cooperative\") {\n\t\t\t\t\treturn refuse(\n\t\t\t\t\t\t\"invalid\",\n\t\t\t\t\t\tdeclared?.pause === \"os\"\n\t\t\t\t\t\t\t? \"this program declares os pause, which its launcher performs\"\n\t\t\t\t\t\t\t: \"this program declares no cooperative pause\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tthis.app.requestPause();\n\t\t\t\trecord(\"ok\");\n\t\t\t\treturn { ok: true };\n\t\t\tcase \"resume\":\n\t\t\t\tthis.app.resumeFromPause();\n\t\t\t\trecord(\"ok\");\n\t\t\t\treturn { ok: true };\n\t\t\tcase \"stop\": {\n\t\t\t\tif (!this.app.stopHandler) return refuse(\"invalid\", \"this program declares no stop handler\");\n\t\t\t\t// a stop supersedes a pause: a program held at a touchpoint goes on to the safepoint where the handler runs\n\t\t\t\tthis.app.resumeFromPause();\n\t\t\t\t// at the next safepoint, on the thread that reaches it (5.5); the program is expected to exit\n\t\t\t\tconst handler = this.app.stopHandler;\n\t\t\t\tthis.atNextSafepoint(() => {\n\t\t\t\t\t// on the thread that reached the safepoint; a failing handler is the program's own matter, and the\n\t\t\t\t\t// launcher's window runs either way\n\t\t\t\t\ttry {\n\t\t\t\t\t\tPromise.resolve(handler()).catch(() => {});\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// same\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\trecord(\"ok\");\n\t\t\t\treturn { ok: true, data: { op, requested: true } };\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\treturn refuse(\"invalid\", `lifecycle ${op} is the launcher's, not the program's`);\n\t\t}\n\t}\n\n\tprivate settleTurn(id: string, outcome: AuditOutcome, cause?: string): void {\n\t\tconst pending = this.turns.get(id);\n\t\tif (!pending) return;\n\t\tthis.turns.delete(id);\n\t\tif (pending.timer) clearTimeout(pending.timer);\n\t\tthis.openTouchpoints -= 1;\n\t\tthis.audit.append({\n\t\t\tconn: pending.conn ?? this.connection,\n\t\t\tact: \"turn\",\n\t\t\tname: pending.request.name,\n\t\t\tid,\n\t\t\toutcome,\n\t\t\t...(cause === undefined ? {} : { cause }),\n\t\t\tms: this.app.now() - pending.startedAt,\n\t\t});\n\t\tpending.resolve();\n\t}\n\n\tendTouchpoint(id: string): void {\n\t\tconst pending = this.touchpoints.get(id);\n\t\tif (!pending) return;\n\t\tthis.touchpoints.delete(id);\n\t\tif (pending.timer) clearInterval(pending.timer);\n\t\tthis.openTouchpoints -= 1;\n\t\tpending.resolve();\n\t}\n\n\tdetach(reason: string): void {\n\t\tif (!this._attached) return;\n\t\tthis._attached = false;\n\t\tfor (const id of [...this.decisions.keys()])\n\t\t\tthis.settleDecision(id, { source: \"default\", cause: \"detached\", reason });\n\t\tfor (const id of [...this.turns.keys()]) this.settleTurn(id, \"default\", \"detached\");\n\t\tfor (const id of [...this.touchpoints.keys()]) this.endTouchpoint(id);\n\t\tthis.notify(\"detach\", reason);\n\t\tthis.app.clearHarness(reason);\n\t\tthis.audit.close();\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Program side (AttachedHarness)\n\t// -----------------------------------------------------------------------\n\n\tdecide(decision: DecisionDecl, context: Record<string, unknown>, deadline: number): Promise<unknown> {\n\t\tif (decision.policy === \"forbid\") {\n\t\t\tthis.audit.append({\n\t\t\t\tconn: this.connection,\n\t\t\t\tact: \"decision\",\n\t\t\t\tname: decision.name,\n\t\t\t\toutcome: \"default\",\n\t\t\t\tcause: \"forbidden\",\n\t\t\t});\n\t\t\treturn Promise.reject(new Error(\"forbidden\"));\n\t\t}\n\t\tconst id = `d${this.nextId++}`;\n\t\tconst request: DecisionRequest = { id, name: decision.name, decision, context, deadline };\n\t\treturn new Promise<unknown>((resolve, reject) => {\n\t\t\t// this timer bounds the program's own wait: it keeps the process alive until the answer or the default\n\t\t\tconst timer = setTimeout(\n\t\t\t\t() => this.settleDecision(id, { source: \"default\", cause: \"timeout\" }),\n\t\t\t\tMath.max(0, deadline - this.app.now()),\n\t\t\t);\n\t\t\tthis.decisions.set(id, { request, resolve, reject, timer, startedAt: this.app.now() });\n\t\t\tthis.openTouchpoints += 1;\n\t\t\tthis.notify(\"decision\", request);\n\t\t});\n\t}\n\n\tturn(turn: TurnDecl, deadline: number): Promise<void> {\n\t\tconst id = `t${this.nextId++}`;\n\t\tconst request: TurnRequest = { id, name: turn.name, turn, deadline, content: this.app.content.turn(turn.name) };\n\t\treturn new Promise<void>((resolve, reject) => {\n\t\t\tconst timer = setTimeout(\n\t\t\t\t() => this.settleTurn(id, \"default\", \"timeout\"),\n\t\t\t\tMath.max(0, deadline - this.app.now()),\n\t\t\t);\n\t\t\tthis.turns.set(id, { request, resolve, reject, timer, startedAt: this.app.now() });\n\t\t\tthis.openTouchpoints += 1;\n\t\t\tthis.notify(\"turn\", request);\n\t\t});\n\t}\n\n\t/** @internal A program-initiated `install` or `session`; resolves when the harness ends it or detaches. */\n\ttouchpoint(kind: TouchpointKind): Promise<void> {\n\t\tconst id = `p${this.nextId++}`;\n\t\tconst content = kind === \"install\" ? this.app.content.install() : this.app.content.use();\n\t\tconst request: TouchpointRequest = { id, kind, content };\n\t\treturn new Promise<void>((resolve, reject) => {\n\t\t\tconst timer = setInterval(() => {}, TOUCHPOINT_KEEPALIVE_MS);\n\t\t\tthis.touchpoints.set(id, { request, resolve, reject, timer, startedAt: this.app.now() });\n\t\t\tthis.openTouchpoints += 1;\n\t\t\tthis.notify(\"touchpoint\", request);\n\t\t});\n\t}\n\n\temitted(seq: number): void {\n\t\tconst read = this.app.region.readEvents(seq - 1);\n\t\tconst slot = read.slots.find((s) => s.seq === seq);\n\t\tif (slot) this.notify(\"event\", this.live(slot));\n\t}\n}\n"]}
1
+ {"version":3,"file":"harness-binding.d.ts","sourceRoot":"","sources":["../src/harness-binding.ts"],"names":[],"mappings":"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","sourcesContent":["// The direct face (abaigrammar section 4.1): what the stub hands a harness\n// that attaches in-process. One object serves both sides. To the program it\n// is the AttachedHarness that decisions, turns, touchpoints and emits reach;\n// to the harness it is the channels: cells and events to read, knobs to\n// write, capabilities to call, decisions and turns to answer, the audit log\n// to tail, the counters to take. Every act of control is audited here, on\n// the program side, as section 10 says, with the consent the harness states\n// for an act whose policy is `confirm`.\nimport { resolve } from \"node:path\";\nimport {\n\tAUDIT_VALUE_CAP,\n\tAuditLog,\n\ttype AuditOutcome,\n\ttype AuditTail,\n\tcapField,\n\tcapValue,\n\ttype MessageRecord,\n\tsummarizeAnswer,\n} from \"./audit.ts\";\nimport { validateKnobValue } from \"./cells/fit.ts\";\nimport { expandHome } from \"./env.ts\";\nimport {\n\ttype CapabilityDecl,\n\ttype DecisionDecl,\n\tdurationMs,\n\ttype FieldSchema,\n\tfieldOf,\n\ttype Manifest,\n\ttype Mode,\n\tmatchesType,\n\ttype TurnDecl,\n} from \"./manifest/manifest.ts\";\nimport type { Abaigram, AttachedHarness, CounterSnapshot } from \"./program.ts\";\nimport type { EventSlot } from \"./region.ts\";\nimport type { WireErrorCode } from \"./wire/protocol.ts\";\n\nexport interface DecisionRequest {\n\tid: string;\n\tname: string;\n\tdecision: DecisionDecl;\n\tcontext: Record<string, unknown>;\n\t/** Epoch milliseconds by which an answer must arrive. */\n\tdeadline: number;\n}\n\nexport interface TurnRequest {\n\tid: string;\n\tname: string;\n\tturn: TurnDecl;\n\tdeadline: number;\n\t/** The content slot for this turn, when the program has one. */\n\tcontent: string | undefined;\n}\n\nexport type TouchpointKind = \"install\" | \"session\";\n\nexport interface TouchpointRequest {\n\tid: string;\n\tkind: TouchpointKind;\n\tcontent: string | undefined;\n}\n\nexport interface LiveEvent {\n\tseq: number;\n\tname: string;\n\tpayload: Record<string, unknown> | undefined;\n\ttruncated: boolean;\n\tts: number;\n}\n\nexport interface EventBatch {\n\tevents: LiveEvent[];\n\t/** Events overwritten before they were read; the harness synthesizes `abai.events.dropped` from it. */\n\tdropped: number;\n\tnext: number;\n}\n\nexport interface CellReading {\n\tvalue: unknown;\n\tversion: number;\n}\n\nexport interface KnobWriteOutcome {\n\tvalue: unknown;\n\toutcome: \"done\" | \"failed\";\n\terror?: string;\n\t/** Why it failed, in the capability error vocabulary (the endpoint sends it under `call_codes`). */\n\tcode?: CallErrorCode;\n}\n\n/**\n * What the harness states about an act whose policy is `confirm` (section\n * 10): a person approved it, the harness approved it without asking (auto\n * mode, or the exercise form standing in for the abaigrammer), or it was\n * denied. An act under `auto` policy needs none.\n */\nexport type Consent = \"approved\" | \"auto\" | \"denied\";\n\n/** Why a call failed: the one vocabulary, in process and on the wire. */\nexport type CallErrorCode = WireErrorCode;\n\nexport type LifecycleOutcome = { ok: true; data?: unknown } | { ok: false; code: CallErrorCode; error: string };\n\n/** A capability call that did not return a result. */\nexport class CallError extends Error {\n\treadonly code: CallErrorCode;\n\tconstructor(code: CallErrorCode, message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"CallError\";\n\t\tthis.code = code;\n\t}\n}\n\nexport interface BindingEvents {\n\tevent: (event: LiveEvent) => void;\n\tdecision: (request: DecisionRequest) => void;\n\t/** The decision expired: the program applied the default. */\n\tdecision_timeout: (id: string, name: string) => void;\n\tturn: (request: TurnRequest) => void;\n\ttouchpoint: (request: TouchpointRequest) => void;\n\tdetach: (reason: string) => void;\n}\n\n/**\n * The harness's view of the stub, in-process. The optional trailing `conn`\n * of the acting methods names the connection that acts, for a front end\n * that multiplexes several (the sidecar endpoint); the audit record carries\n * it. An in-process harness passes none and is audited under the binding's\n * own label.\n */\nexport interface HarnessBinding {\n\treadonly manifest: Manifest;\n\treadonly name: string;\n\treadonly connection: string;\n\t/** The mode this run selected (section 4.4). A harness follows it, not the first declared mode. */\n\treadonly mode: Mode;\n\tcontent(): {\n\t\tidentity: string;\n\t\tinstall: string | undefined;\n\t\tuse: string | undefined;\n\t\tturn(name: string): string | undefined;\n\t};\n\treadCells(names?: string[]): { seq: number; cells: Record<string, CellReading> };\n\treadEvents(after: number): EventBatch;\n\twriteKnob(name: string, value: unknown, reason: string, consent?: Consent, conn?: string): Promise<KnobWriteOutcome>;\n\tcall(\n\t\tname: string,\n\t\tparams: Record<string, unknown> | undefined,\n\t\treason: string,\n\t\tconsent?: Consent,\n\t\tconn?: string,\n\t): Promise<unknown>;\n\tauditTail(limit: number): AuditTail;\n\t/** Where the audit log is, and the error that latched it off, if any. */\n\tauditInfo(): { path: string; failed: string | null };\n\t/**\n\t * One message the agent sent to or received from a member of the run's\n\t * network (section 10): written to the audit log as `act: message`. Not\n\t * an act of control: no policy, no consent, no counter. Every string of\n\t * the record is cut to a bound first. False when nothing was written: the\n\t * log is closed (the binding detached) or has failed.\n\t */\n\trecordMessage(record: MessageRecord, conn?: string): boolean;\n\ttakeCounters(): CounterSnapshot;\n\ton<K extends keyof BindingEvents>(type: K, listener: BindingEvents[K]): () => void;\n\t/** Answer a pending decision; `null` means \"apply the default\" with this reason. Throws when the answer is invalid. */\n\tanswerDecision(id: string, answer: unknown, reason: string, consent?: Consent, conn?: string): void;\n\t/**\n\t * Let a pending decision take its default now, for a cause of the front\n\t * end's: `no_harness` when nobody holds it, `timeout` when a claim's own\n\t * shorter wait ran out, `detached` when its claimant went away. Audited\n\t * like every other settlement, and `decision_timeout` is notified for a\n\t * timeout, so one path serves every cause.\n\t */\n\tdefaultDecision(id: string, cause: string, conn?: string): void;\n\t/** @internal Name the connection that was asked a pending decision, so its settlement is audited under it. */\n\tassignDecision(id: string, conn: string): void;\n\tpendingDecisions(): DecisionRequest[];\n\t/** End a turn. `cause` says why the agent did nothing with it (the grammar's `budget`), and is audited. */\n\tendTurn(id: string, conn?: string, cause?: string): void;\n\tendTouchpoint(id: string): void;\n\t/**\n\t * A lifecycle operation of the program's own (section 5.5): `status`,\n\t * `pause` and `resume` for a cooperative pause, `stop` for the declared\n\t * stop handler. Policy and consent are checked here like any act of\n\t * control, and the acts that change something are audited.\n\t */\n\tlifecycle(op: string, reason: string, consent?: Consent, conn?: string): LifecycleOutcome;\n\tdetach(reason: string): void;\n\treadonly attached: boolean;\n}\n\ninterface Pending<T> {\n\tresolve: (value: T) => void;\n\treject: (error: Error) => void;\n\ttimer: NodeJS.Timeout | undefined;\n\tstartedAt: number;\n\t/** The connection this was asked of, when a front end named one. */\n\tconn?: string;\n}\n\n/**\n * A touchpoint has no timeout of its own, so nothing of the program's holds\n * its event loop open while a harness in another process holds the\n * touchpoint; this ref'd timer does, and never fires in practice (the\n * longest delay a timer takes). Cleared when the touchpoint ends.\n */\nconst TOUCHPOINT_KEEPALIVE_MS = 2 ** 31 - 1;\n\nexport interface BindingOptions {\n\t/** Where the audit log goes; default: the manifest's path, `~` expanded, relative to the program's root. */\n\tauditPath?: string;\n\tconnection?: string;\n}\n\n/**\n * Check a value against a schema: an object with no undeclared field, whose\n * every present field is of its declared type. A declared field may be\n * absent (decided 2026-10-14: the schema language has no required marker,\n * and a manifest's own defaults omit fields); `nullable` governs an\n * explicit null. Nested objects and lists are checked by `matchesType`.\n */\nexport function schemaProblem(schema: Record<string, FieldSchema>, value: unknown, what: string): string | undefined {\n\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) return `${what} must be an object`;\n\tconst record = value as Record<string, unknown>;\n\tfor (const [key, field] of Object.entries(schema)) {\n\t\tconst item = record[key];\n\t\tif (item === undefined) continue;\n\t\tif (!matchesType(item, field)) return `${what}.${key} must be a ${fieldOf(field).type}`;\n\t}\n\tfor (const key of Object.keys(record)) {\n\t\tif (!(key in schema)) return `${what} has an undeclared field ${key}`;\n\t}\n\treturn undefined;\n}\n\nfunction errorMessage(error: unknown): string {\n\treturn error instanceof Error ? error.message : String(error);\n}\n\nfunction consentGranted(consent: Consent | undefined): boolean {\n\treturn consent === \"approved\" || consent === \"auto\";\n}\n\nexport class DirectBinding implements HarnessBinding, AttachedHarness {\n\treadonly manifest: Manifest;\n\treadonly name: string;\n\treadonly connection: string;\n\treadonly mode: Mode;\n\tprivate readonly app: Abaigram;\n\tprivate readonly audit: AuditLog;\n\tprivate readonly listeners: { [K in keyof BindingEvents]: Set<BindingEvents[K]> } = {\n\t\tevent: new Set(),\n\t\tdecision: new Set(),\n\t\tdecision_timeout: new Set(),\n\t\tturn: new Set(),\n\t\ttouchpoint: new Set(),\n\t\tdetach: new Set(),\n\t};\n\tprivate readonly decisions = new Map<string, Pending<unknown> & { request: DecisionRequest }>();\n\tprivate readonly turns = new Map<string, Pending<void> & { request: TurnRequest }>();\n\tprivate readonly touchpoints = new Map<string, Pending<void> & { request: TouchpointRequest }>();\n\tprivate readonly capabilityIndex = new Map<string, CapabilityDecl>();\n\t/** Touchpoints in progress: while one is open the program sits at a safepoint, so queued work runs at once (section 5.3). */\n\tprivate openTouchpoints = 0;\n\tprivate nextId = 1;\n\tprivate _attached = true;\n\n\tconstructor(app: Abaigram, options: BindingOptions = {}) {\n\t\tthis.app = app;\n\t\tthis.manifest = app.manifest;\n\t\tthis.name = app.manifest.name;\n\t\tthis.connection = options.connection ?? \"direct\";\n\t\tthis.mode = app.mode;\n\t\tfor (const capability of this.manifest.capabilities) this.capabilityIndex.set(capability.name, capability);\n\t\tconst auditPath = options.auditPath ?? resolve(app.content.root, expandHome(this.manifest.audit.path));\n\t\tthis.audit = new AuditLog(auditPath, (error) => {\n\t\t\tapp.emitLibrary(\"abai.audit.failed\", { error });\n\t\t});\n\t}\n\n\tget attached(): boolean {\n\t\treturn this._attached;\n\t}\n\n\t/** @internal Called by the program once the binding is set: the counters go to the log first (section 10). */\n\tflushCounters(): void {\n\t\tconst counters = this.app.takeCounters();\n\t\tfor (const [name, count] of Object.entries(counters)) {\n\t\t\tif (count === 0) continue;\n\t\t\tconst cause = name === \"abai.mode_fallback\" ? \"mode_fallback\" : \"no_harness\";\n\t\t\tthis.audit.append({ act: \"counters\", name, outcome: \"default\", cause, count });\n\t\t}\n\t}\n\n\t/** Queue work for the program's next safepoint, or run it now when a touchpoint holds the program at one. */\n\tprivate atSafepoint(work: () => void): void {\n\t\tthis.app.enqueue(work);\n\t\tif (this.openTouchpoints > 0) this.app.drain();\n\t}\n\n\t/**\n\t * @internal The program is at a safepoint and will stay there (its entry\n\t * serving an MCP client): safepoint-dispatched work runs at once rather\n\t * than waiting for a safepoint the program would never reach. Paired\n\t * with `leaveSafepoint`.\n\t */\n\tenterSafepoint(): void {\n\t\tthis.openTouchpoints += 1;\n\t\tthis.app.drain();\n\t}\n\n\t/** @internal */\n\tleaveSafepoint(): void {\n\t\tif (this.openTouchpoints > 0) this.openTouchpoints -= 1;\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Harness side\n\t// -----------------------------------------------------------------------\n\n\tcontent(): {\n\t\tidentity: string;\n\t\tinstall: string | undefined;\n\t\tuse: string | undefined;\n\t\tturn(name: string): string | undefined;\n\t} {\n\t\tconst slots = this.app.content;\n\t\treturn {\n\t\t\tidentity: slots.identity(),\n\t\t\tinstall: slots.install(),\n\t\t\tuse: slots.use(),\n\t\t\tturn: (name) => slots.turn(name),\n\t\t};\n\t}\n\n\treadCells(names?: string[]): { seq: number; cells: Record<string, CellReading> } {\n\t\tconst all = this.app.readCells();\n\t\tconst cells: Record<string, CellReading> = {};\n\t\tfor (const name of names ?? Object.keys(all)) {\n\t\t\tif (!(name in all)) throw new Error(`unknown cell: ${name}`);\n\t\t\tcells[name] = { value: all[name], version: this.app.version(name) };\n\t\t}\n\t\treturn { seq: this.app.region.lastSeq, cells };\n\t}\n\n\treadEvents(after: number): EventBatch {\n\t\tconst read = this.app.region.readEvents(after);\n\t\treturn { events: read.slots.map((slot) => this.live(slot)), dropped: read.dropped, next: read.next };\n\t}\n\n\tprivate live(slot: EventSlot): LiveEvent {\n\t\treturn {\n\t\t\tseq: slot.seq,\n\t\t\tname: this.app.eventName(slot.event),\n\t\t\tpayload: slot.payload,\n\t\t\ttruncated: slot.truncated,\n\t\t\tts: slot.ts,\n\t\t};\n\t}\n\n\tasync writeKnob(\n\t\tname: string,\n\t\tvalue: unknown,\n\t\treason: string,\n\t\tconsent?: Consent,\n\t\tconn?: string,\n\t): Promise<KnobWriteOutcome> {\n\t\tconst decl = this.manifest.cells.find((cell) => cell.name === name);\n\t\tconst started = this.app.now();\n\t\tconst record = (\n\t\t\toutcome: AuditOutcome,\n\t\t\tlanded: unknown,\n\t\t\terror?: string,\n\t\t\tcause?: CallErrorCode,\n\t\t): KnobWriteOutcome => {\n\t\t\tthis.audit.append({\n\t\t\t\tconn: conn ?? this.connection,\n\t\t\t\tact: \"knob\",\n\t\t\t\tname,\n\t\t\t\tvalue: capValue(landed),\n\t\t\t\toutcome,\n\t\t\t\t...(cause === undefined ? {} : { cause }),\n\t\t\t\t...(consent === undefined ? {} : { consent }),\n\t\t\t\treason,\n\t\t\t\t...(error === undefined ? {} : { error }),\n\t\t\t\tms: this.app.now() - started,\n\t\t\t});\n\t\t\treturn outcome === \"ok\"\n\t\t\t\t? { value: landed, outcome: \"done\" }\n\t\t\t\t: { value: landed, outcome: \"failed\", error, ...(cause === undefined ? {} : { code: cause }) };\n\t\t};\n\t\tif (!decl) return record(\"error\", undefined, `unknown cell: ${name}`, \"unknown\");\n\t\tif (decl.access !== \"readwrite\") return record(\"error\", undefined, `${name} is read-only`, \"invalid\");\n\t\tif (decl.policy === \"confirm\" && !consentGranted(consent)) {\n\t\t\treturn record(\"error\", undefined, `${name} needs consent (its policy is confirm)`, \"denied\");\n\t\t}\n\t\tconst problem = validateKnobValue(decl, value);\n\t\tif (problem !== undefined) return record(\"error\", undefined, problem, \"invalid\");\n\t\tconst sized = decl.type === \"string\" || decl.type === \"object\" || decl.type === \"list\";\n\t\tif (!sized) {\n\t\t\tthis.app.knob(name).set(value);\n\t\t\treturn record(\"ok\", this.app.cell(name).get());\n\t\t}\n\t\t// a sized knob is delivered at the program's next safepoint, to its handler, within its delivery timeout (section 5.2)\n\t\tconst handler = this.app.knobHandler(name);\n\t\tif (!handler) {\n\t\t\treturn record(\"failed\", undefined, `no handler registered for ${name}: nothing can receive it`, \"error\");\n\t\t}\n\t\tconst timeoutMs = durationMs(decl.timeout ?? \"30s\");\n\t\treturn new Promise<KnobWriteOutcome>((done) => {\n\t\t\tlet settled = false;\n\t\t\tconst work = (): void => {\n\t\t\t\tif (settled) return;\n\t\t\t\tsettled = true;\n\t\t\t\tclearTimeout(timer);\n\t\t\t\tthis.app.cell(name).set(value);\n\t\t\t\tconst landed = this.app.cell(name).get();\n\t\t\t\ttry {\n\t\t\t\t\thandler(landed);\n\t\t\t\t\tdone(record(\"ok\", landed));\n\t\t\t\t} catch (error) {\n\t\t\t\t\tdone(record(\"error\", landed, errorMessage(error), \"error\"));\n\t\t\t\t}\n\t\t\t};\n\t\t\tconst timer = setTimeout(() => {\n\t\t\t\tif (settled) return;\n\t\t\t\tsettled = true;\n\t\t\t\tthis.app.dequeue(work);\n\t\t\t\tdone(\n\t\t\t\t\trecord(\n\t\t\t\t\t\t\"failed\",\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t`not delivered within ${decl.timeout ?? \"30s\"}: the program reached no safepoint`,\n\t\t\t\t\t\t\"timeout\",\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}, timeoutMs);\n\t\t\ttimer.unref();\n\t\t\tthis.atSafepoint(work);\n\t\t});\n\t}\n\n\tasync call(\n\t\tname: string,\n\t\tparams: Record<string, unknown> | undefined,\n\t\treason: string,\n\t\tconsent?: Consent,\n\t\tconn?: string,\n\t): Promise<unknown> {\n\t\tconst decl = this.capabilityIndex.get(name);\n\t\tconst started = this.app.now();\n\t\tconst record = (outcome: AuditOutcome, extra: { error?: string; cause?: string } = {}): void => {\n\t\t\tthis.audit.append({\n\t\t\t\tconn: conn ?? this.connection,\n\t\t\t\tact: \"capability\",\n\t\t\t\tname,\n\t\t\t\tparams: capValue(params),\n\t\t\t\toutcome,\n\t\t\t\t...(consent === undefined ? {} : { consent }),\n\t\t\t\treason,\n\t\t\t\t...extra,\n\t\t\t\tms: this.app.now() - started,\n\t\t\t});\n\t\t};\n\t\tconst fail = (code: CallErrorCode, message: string): CallError => {\n\t\t\trecord(code === \"forbidden\" ? \"forbidden\" : \"error\", { error: message, cause: code });\n\t\t\treturn new CallError(code, message);\n\t\t};\n\t\tif (!decl) throw fail(\"unknown\", `${this.name} declares no capability ${name}`);\n\t\tif (decl.policy === \"forbid\") throw fail(\"forbidden\", `the program's policy forbids ${name}`);\n\t\tif (decl.policy === \"confirm\" && !consentGranted(consent))\n\t\t\tthrow fail(\"denied\", `${name} needs consent (its policy is confirm)`);\n\t\tconst problem = schemaProblem(decl.params, params ?? {}, \"params\");\n\t\tif (problem !== undefined) throw fail(\"invalid\", problem);\n\t\tconst timeoutMs = durationMs(decl.timeout ?? \"30s\");\n\t\tconst result = await new Promise<unknown>((done, reject) => {\n\t\t\tlet settled = false;\n\t\t\tconst settle = (fn: () => void): void => {\n\t\t\t\tif (settled) return;\n\t\t\t\tsettled = true;\n\t\t\t\tclearTimeout(timer);\n\t\t\t\tfn();\n\t\t\t};\n\t\t\t// the handler is resolved at dispatch, so one registered after startup still serves\n\t\t\tconst run = (): void => {\n\t\t\t\tif (settled) return;\n\t\t\t\tconst handler = this.app.capabilityHandler(name);\n\t\t\t\tif (!handler) {\n\t\t\t\t\tsettle(() => reject(new CallError(\"error\", `${name} has no handler registered`)));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tlet outcome: unknown;\n\t\t\t\ttry {\n\t\t\t\t\toutcome = handler(params ?? {}); // synchronous part runs inside the safepoint, on the program's thread\n\t\t\t\t} catch (error) {\n\t\t\t\t\tsettle(() => reject(new CallError(\"error\", errorMessage(error))));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tPromise.resolve(outcome).then(\n\t\t\t\t\t(value) => settle(() => done(value)),\n\t\t\t\t\t(error) => settle(() => reject(new CallError(\"error\", errorMessage(error)))),\n\t\t\t\t);\n\t\t\t};\n\t\t\tconst timer = setTimeout(() => {\n\t\t\t\tif (settled) return;\n\t\t\t\tsettled = true;\n\t\t\t\tthis.app.dequeue(run);\n\t\t\t\treject(new CallError(\"timeout\", `${name} did not answer within ${decl.timeout ?? \"30s\"}`));\n\t\t\t}, timeoutMs);\n\t\t\ttimer.unref();\n\t\t\tif (decl.dispatch === \"immediate\") run();\n\t\t\telse this.atSafepoint(run);\n\t\t}).catch((error: CallError) => {\n\t\t\trecord(\"error\", { error: error.message, cause: error.code });\n\t\t\tthrow error;\n\t\t});\n\t\trecord(\"ok\");\n\t\treturn result;\n\t}\n\n\trecordMessage(record: MessageRecord, conn?: string): boolean {\n\t\tconst cut = (value: string | undefined, cap?: number): string | undefined =>\n\t\t\tvalue === undefined ? undefined : capField(value, cap);\n\t\tconst thread = cut(record.thread);\n\t\tconst re = cut(record.re);\n\t\tconst reason = cut(record.reason, AUDIT_VALUE_CAP);\n\t\tconst error = cut(record.error, AUDIT_VALUE_CAP);\n\t\tconst id = cut(record.id);\n\t\treturn this.audit.append({\n\t\t\tconn: conn ?? this.connection,\n\t\t\tact: \"message\",\n\t\t\tname: capField(record.peer),\n\t\t\t...(id === undefined ? {} : { id }),\n\t\t\tparams: {\n\t\t\t\tdirection: record.direction,\n\t\t\t\tnetwork: capField(record.network),\n\t\t\t\taddr: capField(record.addr),\n\t\t\t\tkind: record.kind,\n\t\t\t\t...(thread === undefined ? {} : { thread }),\n\t\t\t\t...(re === undefined ? {} : { re }),\n\t\t\t},\n\t\t\tvalue: capValue(record.body),\n\t\t\toutcome: record.outcome,\n\t\t\t...(reason === undefined ? {} : { reason }),\n\t\t\t...(error === undefined ? {} : { error }),\n\t\t\t...(typeof record.ms === \"number\" && Number.isFinite(record.ms) ? { ms: record.ms } : {}),\n\t\t});\n\t}\n\n\tauditTail(limit: number): AuditTail {\n\t\treturn this.audit.tail(limit);\n\t}\n\n\tauditInfo(): { path: string; failed: string | null } {\n\t\treturn { path: this.audit.path, failed: this.audit.failed ?? null };\n\t}\n\n\ttakeCounters(): CounterSnapshot {\n\t\treturn this.app.takeCounters();\n\t}\n\n\ton<K extends keyof BindingEvents>(type: K, listener: BindingEvents[K]): () => void {\n\t\tconst set = this.listeners[type] as Set<BindingEvents[K]>;\n\t\tset.add(listener);\n\t\treturn () => {\n\t\t\tset.delete(listener);\n\t\t};\n\t}\n\n\tprivate notify<K extends keyof BindingEvents>(type: K, ...args: Parameters<BindingEvents[K]>): void {\n\t\tfor (const listener of this.listeners[type]) {\n\t\t\ttry {\n\t\t\t\t(listener as (...a: Parameters<BindingEvents[K]>) => void)(...args);\n\t\t\t} catch {\n\t\t\t\t// a harness listener's failure never reaches the program\n\t\t\t}\n\t\t}\n\t}\n\n\tanswerDecision(id: string, answer: unknown, reason: string, consent?: Consent, conn?: string): void {\n\t\tconst pending = this.decisions.get(id);\n\t\tif (!pending) throw new Error(`no pending decision ${id}`);\n\t\tif (reason.trim() === \"\") throw new Error(\"a decision needs a reason\");\n\t\tif (conn !== undefined) pending.conn = conn;\n\t\tconst { decision } = pending.request;\n\t\tif (answer !== null) {\n\t\t\tconst problem = decision.options\n\t\t\t\t? decision.options.includes(answer as string)\n\t\t\t\t\t? undefined\n\t\t\t\t\t: `answer must be one of: ${decision.options.join(\", \")}`\n\t\t\t\t: schemaProblem(decision.answer ?? {}, answer, \"answer\");\n\t\t\tif (problem !== undefined) {\n\t\t\t\tthis.settleDecision(id, { source: \"default\", cause: \"invalid\", reason, answer });\n\t\t\t\tthrow new Error(problem);\n\t\t\t}\n\t\t\tif (decision.policy === \"confirm\" && !consentGranted(consent)) {\n\t\t\t\tthis.settleDecision(id, { source: \"default\", cause: \"denied\", reason, consent });\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tthis.settleDecision(\n\t\t\tid,\n\t\t\tanswer === null\n\t\t\t\t? { source: \"default\", cause: \"answered\", reason }\n\t\t\t\t: { source: \"agent\", reason, answer, consent },\n\t\t);\n\t}\n\n\tdefaultDecision(id: string, cause: string, conn?: string): void {\n\t\tconst pending = this.decisions.get(id);\n\t\tif (!pending) return;\n\t\tif (conn !== undefined) pending.conn = conn;\n\t\tthis.settleDecision(id, { source: \"default\", cause });\n\t}\n\n\tassignDecision(id: string, conn: string): void {\n\t\tconst pending = this.decisions.get(id);\n\t\tif (pending) pending.conn = conn;\n\t}\n\n\tpendingDecisions(): DecisionRequest[] {\n\t\treturn [...this.decisions.values()].map((p) => p.request);\n\t}\n\n\tprivate settleDecision(\n\t\tid: string,\n\t\toutcome: { source: \"agent\" | \"default\"; cause?: string; reason?: string; answer?: unknown; consent?: Consent },\n\t): void {\n\t\tconst pending = this.decisions.get(id);\n\t\tif (!pending) return;\n\t\tthis.decisions.delete(id);\n\t\tif (pending.timer) clearTimeout(pending.timer);\n\t\tthis.openTouchpoints -= 1;\n\t\tconst { decision } = pending.request;\n\t\tthis.audit.append({\n\t\t\tconn: pending.conn ?? this.connection,\n\t\t\tact: \"decision\",\n\t\t\tname: decision.name,\n\t\t\tid,\n\t\t\tvalue: summarizeAnswer(decision, outcome.source === \"agent\" ? outcome.answer : decision.default),\n\t\t\toutcome: outcome.source,\n\t\t\t...(outcome.cause === undefined ? {} : { cause: outcome.cause }),\n\t\t\t...(outcome.consent === undefined ? {} : { consent: outcome.consent }),\n\t\t\t...(outcome.reason === undefined ? {} : { reason: outcome.reason }),\n\t\t\tms: this.app.now() - pending.startedAt,\n\t\t});\n\t\tif (outcome.source === \"agent\") pending.resolve(outcome.answer);\n\t\telse pending.reject(new Error(outcome.cause ?? \"default\"));\n\t\tif (outcome.cause === \"timeout\") this.notify(\"decision_timeout\", id, decision.name);\n\t}\n\n\tendTurn(id: string, conn?: string, cause?: string): void {\n\t\tconst pending = this.turns.get(id);\n\t\tif (!pending) return;\n\t\tif (conn !== undefined) pending.conn = conn;\n\t\t// a turn the agent did nothing with (held back by its budget) is a default, with the cause it names\n\t\tif (cause === undefined) this.settleTurn(id, \"ok\");\n\t\telse this.settleTurn(id, \"default\", cause);\n\t}\n\n\t/** @internal Queue work for the program's next safepoint, running it now when one is held open. */\n\tatNextSafepoint(work: () => void): void {\n\t\tthis.atSafepoint(work);\n\t}\n\n\tlifecycle(op: string, reason: string, consent?: Consent, conn?: string): LifecycleOutcome {\n\t\tconst declared = this.manifest.lifecycle;\n\t\tconst started = this.app.now();\n\t\tconst record = (outcome: AuditOutcome, extra: { cause?: string; error?: string } = {}): void => {\n\t\t\tthis.audit.append({\n\t\t\t\tconn: conn ?? this.connection,\n\t\t\t\tact: \"lifecycle\",\n\t\t\t\tname: op,\n\t\t\t\toutcome,\n\t\t\t\t...(consent === undefined ? {} : { consent }),\n\t\t\t\treason,\n\t\t\t\t...extra,\n\t\t\t\tms: this.app.now() - started,\n\t\t\t});\n\t\t};\n\t\tconst refuse = (code: CallErrorCode, error: string): LifecycleOutcome => {\n\t\t\trecord(code === \"forbidden\" ? \"forbidden\" : \"error\", { cause: code, error });\n\t\t\treturn { ok: false, code, error };\n\t\t};\n\t\tif (op === \"status\") return { ok: true, data: this.app.lifecycleStatus() };\n\t\tif (op !== \"pause\" && op !== \"resume\" && op !== \"stop\" && op !== \"restart\" && op !== \"start\") {\n\t\t\treturn { ok: false, code: \"unknown\", error: `unknown lifecycle operation: ${op}` };\n\t\t}\n\t\t// section 10: pause and resume are auto, stop and restart confirm, unless the manifest says otherwise\n\t\tconst policy =\n\t\t\tdeclared?.policy?.[op as \"pause\" | \"resume\" | \"stop\" | \"restart\"] ??\n\t\t\t(op === \"stop\" || op === \"restart\" ? \"confirm\" : \"auto\");\n\t\tif (policy === \"forbid\") return refuse(\"forbidden\", `the program's policy forbids lifecycle ${op}`);\n\t\tif (policy === \"confirm\" && !consentGranted(consent)) {\n\t\t\treturn refuse(\"denied\", `lifecycle ${op} needs consent (its policy is confirm)`);\n\t\t}\n\t\tswitch (op) {\n\t\t\tcase \"pause\":\n\t\t\t\tif (declared?.pause !== \"cooperative\") {\n\t\t\t\t\treturn refuse(\n\t\t\t\t\t\t\"invalid\",\n\t\t\t\t\t\tdeclared?.pause === \"os\"\n\t\t\t\t\t\t\t? \"this program declares os pause, which its launcher performs\"\n\t\t\t\t\t\t\t: \"this program declares no cooperative pause\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tthis.app.requestPause();\n\t\t\t\trecord(\"ok\");\n\t\t\t\treturn { ok: true };\n\t\t\tcase \"resume\":\n\t\t\t\tthis.app.resumeFromPause();\n\t\t\t\trecord(\"ok\");\n\t\t\t\treturn { ok: true };\n\t\t\tcase \"stop\": {\n\t\t\t\tif (!this.app.stopHandler) return refuse(\"invalid\", \"this program declares no stop handler\");\n\t\t\t\t// a stop supersedes a pause: a program held at a touchpoint goes on to the safepoint where the handler runs\n\t\t\t\tthis.app.resumeFromPause();\n\t\t\t\t// at the next safepoint, on the thread that reaches it (5.5); the program is expected to exit\n\t\t\t\tconst handler = this.app.stopHandler;\n\t\t\t\tthis.atNextSafepoint(() => {\n\t\t\t\t\t// on the thread that reached the safepoint; a failing handler is the program's own matter, and the\n\t\t\t\t\t// launcher's window runs either way\n\t\t\t\t\ttry {\n\t\t\t\t\t\tPromise.resolve(handler()).catch(() => {});\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// same\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\trecord(\"ok\");\n\t\t\t\treturn { ok: true, data: { op, requested: true } };\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\treturn refuse(\"invalid\", `lifecycle ${op} is the launcher's, not the program's`);\n\t\t}\n\t}\n\n\tprivate settleTurn(id: string, outcome: AuditOutcome, cause?: string): void {\n\t\tconst pending = this.turns.get(id);\n\t\tif (!pending) return;\n\t\tthis.turns.delete(id);\n\t\tif (pending.timer) clearTimeout(pending.timer);\n\t\tthis.openTouchpoints -= 1;\n\t\tthis.audit.append({\n\t\t\tconn: pending.conn ?? this.connection,\n\t\t\tact: \"turn\",\n\t\t\tname: pending.request.name,\n\t\t\tid,\n\t\t\toutcome,\n\t\t\t...(cause === undefined ? {} : { cause }),\n\t\t\tms: this.app.now() - pending.startedAt,\n\t\t});\n\t\tpending.resolve();\n\t}\n\n\tendTouchpoint(id: string): void {\n\t\tconst pending = this.touchpoints.get(id);\n\t\tif (!pending) return;\n\t\tthis.touchpoints.delete(id);\n\t\tif (pending.timer) clearInterval(pending.timer);\n\t\tthis.openTouchpoints -= 1;\n\t\tpending.resolve();\n\t}\n\n\tdetach(reason: string): void {\n\t\tif (!this._attached) return;\n\t\tthis._attached = false;\n\t\tfor (const id of [...this.decisions.keys()])\n\t\t\tthis.settleDecision(id, { source: \"default\", cause: \"detached\", reason });\n\t\tfor (const id of [...this.turns.keys()]) this.settleTurn(id, \"default\", \"detached\");\n\t\tfor (const id of [...this.touchpoints.keys()]) this.endTouchpoint(id);\n\t\tthis.notify(\"detach\", reason);\n\t\tthis.app.clearHarness(reason);\n\t\tthis.audit.close();\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Program side (AttachedHarness)\n\t// -----------------------------------------------------------------------\n\n\tdecide(decision: DecisionDecl, context: Record<string, unknown>, deadline: number): Promise<unknown> {\n\t\tif (decision.policy === \"forbid\") {\n\t\t\tthis.audit.append({\n\t\t\t\tconn: this.connection,\n\t\t\t\tact: \"decision\",\n\t\t\t\tname: decision.name,\n\t\t\t\toutcome: \"default\",\n\t\t\t\tcause: \"forbidden\",\n\t\t\t});\n\t\t\treturn Promise.reject(new Error(\"forbidden\"));\n\t\t}\n\t\tconst id = `d${this.nextId++}`;\n\t\tconst request: DecisionRequest = { id, name: decision.name, decision, context, deadline };\n\t\treturn new Promise<unknown>((resolve, reject) => {\n\t\t\t// this timer bounds the program's own wait: it keeps the process alive until the answer or the default\n\t\t\tconst timer = setTimeout(\n\t\t\t\t() => this.settleDecision(id, { source: \"default\", cause: \"timeout\" }),\n\t\t\t\tMath.max(0, deadline - this.app.now()),\n\t\t\t);\n\t\t\tthis.decisions.set(id, { request, resolve, reject, timer, startedAt: this.app.now() });\n\t\t\tthis.openTouchpoints += 1;\n\t\t\tthis.notify(\"decision\", request);\n\t\t});\n\t}\n\n\tturn(turn: TurnDecl, deadline: number): Promise<void> {\n\t\tconst id = `t${this.nextId++}`;\n\t\tconst request: TurnRequest = { id, name: turn.name, turn, deadline, content: this.app.content.turn(turn.name) };\n\t\treturn new Promise<void>((resolve, reject) => {\n\t\t\tconst timer = setTimeout(\n\t\t\t\t() => this.settleTurn(id, \"default\", \"timeout\"),\n\t\t\t\tMath.max(0, deadline - this.app.now()),\n\t\t\t);\n\t\t\tthis.turns.set(id, { request, resolve, reject, timer, startedAt: this.app.now() });\n\t\t\tthis.openTouchpoints += 1;\n\t\t\tthis.notify(\"turn\", request);\n\t\t});\n\t}\n\n\t/** @internal A program-initiated `install` or `session`; resolves when the harness ends it or detaches. */\n\ttouchpoint(kind: TouchpointKind): Promise<void> {\n\t\tconst id = `p${this.nextId++}`;\n\t\tconst content = kind === \"install\" ? this.app.content.install() : this.app.content.use();\n\t\tconst request: TouchpointRequest = { id, kind, content };\n\t\treturn new Promise<void>((resolve, reject) => {\n\t\t\tconst timer = setInterval(() => {}, TOUCHPOINT_KEEPALIVE_MS);\n\t\t\tthis.touchpoints.set(id, { request, resolve, reject, timer, startedAt: this.app.now() });\n\t\t\tthis.openTouchpoints += 1;\n\t\t\tthis.notify(\"touchpoint\", request);\n\t\t});\n\t}\n\n\temitted(seq: number): void {\n\t\tconst read = this.app.region.readEvents(seq - 1);\n\t\tconst slot = read.slots.find((s) => s.seq === seq);\n\t\tif (slot) this.notify(\"event\", this.live(slot));\n\t}\n}\n"]}
@@ -7,7 +7,7 @@
7
7
  // the program side, as section 10 says, with the consent the harness states
8
8
  // for an act whose policy is `confirm`.
9
9
  import { resolve } from "node:path";
10
- import { AuditLog, capValue, summarizeAnswer } from "./audit.js";
10
+ import { AUDIT_VALUE_CAP, AuditLog, capField, capValue, summarizeAnswer, } from "./audit.js";
11
11
  import { validateKnobValue } from "./cells/fit.js";
12
12
  import { expandHome } from "./env.js";
13
13
  import { durationMs, fieldOf, matchesType, } from "./manifest/manifest.js";
@@ -61,6 +61,7 @@ export class DirectBinding {
61
61
  manifest;
62
62
  name;
63
63
  connection;
64
+ mode;
64
65
  app;
65
66
  audit;
66
67
  listeners = {
@@ -84,6 +85,7 @@ export class DirectBinding {
84
85
  this.manifest = app.manifest;
85
86
  this.name = app.manifest.name;
86
87
  this.connection = options.connection ?? "direct";
88
+ this.mode = app.mode;
87
89
  for (const capability of this.manifest.capabilities)
88
90
  this.capabilityIndex.set(capability.name, capability);
89
91
  const auditPath = options.auditPath ?? resolve(app.content.root, expandHome(this.manifest.audit.path));
@@ -306,6 +308,33 @@ export class DirectBinding {
306
308
  record("ok");
307
309
  return result;
308
310
  }
311
+ recordMessage(record, conn) {
312
+ const cut = (value, cap) => value === undefined ? undefined : capField(value, cap);
313
+ const thread = cut(record.thread);
314
+ const re = cut(record.re);
315
+ const reason = cut(record.reason, AUDIT_VALUE_CAP);
316
+ const error = cut(record.error, AUDIT_VALUE_CAP);
317
+ const id = cut(record.id);
318
+ return this.audit.append({
319
+ conn: conn ?? this.connection,
320
+ act: "message",
321
+ name: capField(record.peer),
322
+ ...(id === undefined ? {} : { id }),
323
+ params: {
324
+ direction: record.direction,
325
+ network: capField(record.network),
326
+ addr: capField(record.addr),
327
+ kind: record.kind,
328
+ ...(thread === undefined ? {} : { thread }),
329
+ ...(re === undefined ? {} : { re }),
330
+ },
331
+ value: capValue(record.body),
332
+ outcome: record.outcome,
333
+ ...(reason === undefined ? {} : { reason }),
334
+ ...(error === undefined ? {} : { error }),
335
+ ...(typeof record.ms === "number" && Number.isFinite(record.ms) ? { ms: record.ms } : {}),
336
+ });
337
+ }
309
338
  auditTail(limit) {
310
339
  return this.audit.tail(limit);
311
340
  }