@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.
@@ -1 +1 @@
1
- {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/manifest/manifest.ts"],"names":[],"mappings":"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","sourcesContent":["// The abaigrammar 0.1 manifest: types, validation and helpers (spec/abaigrammar.md sections 5 and 7).\n//\n// The manifest exists in two forms that must agree: in code (the program's\n// declarations, the source of truth at runtime) and in the repo\n// (abaigram.yaml, rendered by render.ts). The validator here checks either\n// form, so `<entry> doctor` and the self-check test apply the same rules.\n// Fields beyond the grammar (`deviations`, `writes`, `nullable`) are\n// extensions a partial realization needs; the manifest's `deviations` list\n// names them.\n\nexport const ABAIGRAMMAR_VERSION = \"0.1\";\n\nexport type ScalarType = \"bool\" | \"int\" | \"float\" | \"enum\";\nexport type SizedType = \"string\" | \"object\" | \"list\";\nexport type ValueType = ScalarType | SizedType;\n\nexport type Mode = \"turns\" | \"thread\" | \"sidecar\";\nexport const MODES: readonly Mode[] = [\"turns\", \"thread\", \"sidecar\"];\n\nexport type Access = \"read\" | \"readwrite\";\nexport type Effect = \"read\" | \"mutate\";\nexport type Dispatch = \"immediate\" | \"safepoint\";\nexport type Policy = \"auto\" | \"confirm\" | \"forbid\";\nexport type Wakes = \"always\" | \"never\" | string;\n\n/** Default `max` sizes of the sized types (grammar section 5, common rules). */\nexport const DEFAULT_STRING_MAX = 256;\nexport const DEFAULT_SIZED_MAX = 1024;\n/** Payload bytes an event slot holds; a larger declared payload must be `large`. */\nexport const EVENT_SLOT_BYTES = 4096;\n/** Bytes counted for a scalar field. */\nexport const SCALAR_BYTES = 8;\n\n/**\n * A schema field: a bare type name when the defaults suffice, or an object\n * with `type` and `max` (and, beyond the grammar, `enum` values, an object's\n * `fields`, a list's `items`, `nullable` and a `doc`).\n */\nexport type FieldSchema =\n\t| ValueType\n\t| {\n\t\t\ttype: ValueType;\n\t\t\tmax?: number;\n\t\t\tenum?: string[];\n\t\t\tfields?: Schema;\n\t\t\titems?: FieldSchema;\n\t\t\tnullable?: boolean;\n\t\t\tdoc?: string;\n\t };\n\nexport type Schema = Record<string, FieldSchema>;\n\nexport interface CellDecl {\n\tname: string;\n\ttype: ValueType;\n\taccess: Access;\n\tdoc: string;\n\t/** Sized types only. */\n\tmax?: number;\n\t/** `enum` cells. */\n\tenum?: string[];\n\t/** `int` and `float` cells. */\n\trange?: [number, number];\n\t/** Required for `readwrite`. */\n\tdefault?: unknown;\n\t/** Hint in milliseconds. */\n\tcadence?: number;\n\t/** `readwrite` only; knobs are never `forbid`. */\n\tpolicy?: \"auto\" | \"confirm\";\n\t/** Sized knobs only: delivery timeout. */\n\ttimeout?: string;\n\t/** `object` cells: the fields. */\n\tfields?: Schema;\n\t/** `list` cells: the item schema. */\n\titems?: FieldSchema;\n\t/** Extension: the value may be null. */\n\tnullable?: boolean;\n}\n\nexport interface EventDecl {\n\tname: string;\n\tdoc: string;\n\tpayload: Schema;\n\twakes?: Wakes;\n\tlarge?: boolean;\n}\n\nexport interface CapabilityDecl {\n\tname: string;\n\tdoc: string;\n\tparams: Schema;\n\tresult: Schema;\n\teffect: Effect;\n\tdispatch: Dispatch;\n\ttimeout?: string;\n\tpolicy: Policy;\n\texample?: Record<string, unknown>;\n\t/** Extension: the knob this capability sets; such calls are audited as knob writes. */\n\twrites?: string;\n}\n\nexport interface DecisionDecl {\n\tname: string;\n\tdoc: string;\n\tcontext: Schema;\n\t/** Either `options` (an enum of choices) or `answer` (a schema). */\n\toptions?: string[];\n\tanswer?: Schema;\n\tdefault: unknown;\n\ttimeout: string;\n\tpolicy: Policy;\n}\n\nexport interface TurnDecl {\n\tname: string;\n\tdoc: string;\n\ttimeout: string;\n}\n\nexport interface Manifest {\n\tabaigrammar: string;\n\tname: string;\n\tentry: string;\n\tmodes: Mode[];\n\tharness?: { path: string | null };\n\tmodel?: Record<string, unknown>;\n\tcheck?: { run: string; overhead?: string };\n\tcontent: { identity: string; install?: string; use?: string; turns?: string };\n\taudit: { path: string };\n\tlifecycle?: {\n\t\tpause: \"cooperative\" | \"os\" | \"none\";\n\t\tstop?: { graceful: string; handler: string };\n\t\tpolicy?: Partial<Record<\"pause\" | \"resume\" | \"stop\" | \"restart\", Policy>>;\n\t};\n\tattention?: { budget?: { wakes_per_minute?: number; tokens_per_hour?: number } };\n\tpolicy?: { confirm_timeout?: string };\n\t/** Where this instantiation departs from the grammar, one sentence each (section 7); a program may add its own. */\n\tdeviations?: string[];\n\tcells: CellDecl[];\n\tevents: EventDecl[];\n\tcapabilities: CapabilityDecl[];\n\tdecisions: DecisionDecl[];\n\tturns: TurnDecl[];\n}\n\n/** Events the library (the stub) emits under the reserved `abai.` prefix. */\nexport const LIBRARY_EVENTS: readonly string[] = [\n\t\"abai.events.dropped\",\n\t\"abai.knob.reset\",\n\t\"abai.lifecycle.exited\",\n\t\"abai.pause.blocked\",\n\t\"abai.io.stdout\",\n\t\"abai.io.stderr\",\n\t\"abai.audit.failed\",\n];\n\nconst NAME = /^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)*$/;\nconst DURATION = /^[0-9]+(ms|s|m|h)$/;\nconst VALUE_TYPES: readonly string[] = [\"bool\", \"int\", \"float\", \"enum\", \"string\", \"object\", \"list\"];\nconst SIZED_TYPES: readonly string[] = [\"string\", \"object\", \"list\"];\nconst POLICIES: readonly string[] = [\"auto\", \"confirm\", \"forbid\"];\n\n/** A valid abai name: lowercase segments joined by dots, words joined by underscores. */\nexport function isValidName(name: unknown): name is string {\n\treturn typeof name === \"string\" && NAME.test(name);\n}\n\nexport function isDuration(value: unknown): value is string {\n\treturn typeof value === \"string\" && DURATION.test(value);\n}\n\n/** A duration string in milliseconds. */\nexport function durationMs(value: string): number {\n\tconst match = /^([0-9]+)(ms|s|m|h)$/.exec(value);\n\tif (!match) throw new Error(`not a duration: ${value}`);\n\tconst n = Number(match[1]);\n\tswitch (match[2]) {\n\t\tcase \"ms\":\n\t\t\treturn n;\n\t\tcase \"s\":\n\t\t\treturn n * 1000;\n\t\tcase \"m\":\n\t\t\treturn n * 60_000;\n\t\tdefault:\n\t\t\treturn n * 3_600_000;\n\t}\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isPositiveInt(value: unknown): value is number {\n\treturn typeof value === \"number\" && Number.isInteger(value) && value > 0;\n}\n\n/** Normalize a field schema to its object form. */\nexport function fieldOf(field: FieldSchema): Exclude<FieldSchema, string> {\n\treturn typeof field === \"string\" ? { type: field } : field;\n}\n\n/** Bytes a field counts toward an event slot: scalars 8, sized fields their `max`. */\nexport function fieldBytes(field: FieldSchema): number {\n\tconst f = fieldOf(field);\n\tif (f.type === \"string\") return f.max ?? DEFAULT_STRING_MAX;\n\tif (f.type === \"object\" || f.type === \"list\") return f.max ?? DEFAULT_SIZED_MAX;\n\treturn SCALAR_BYTES;\n}\n\n/** Bytes a payload counts toward an event slot (grammar section 5.1). */\nexport function payloadBytes(schema: Schema): number {\n\tlet total = 0;\n\tfor (const field of Object.values(schema)) total += fieldBytes(field);\n\treturn total;\n}\n\n/** Whether a value has a declared type. `int` accepts integers only; `float` any finite number. */\nexport function matchesType(value: unknown, field: FieldSchema): boolean {\n\tconst f = fieldOf(field);\n\tif (value === null) return f.nullable === true;\n\tswitch (f.type) {\n\t\tcase \"bool\":\n\t\t\treturn typeof value === \"boolean\";\n\t\tcase \"int\":\n\t\t\treturn typeof value === \"number\" && Number.isInteger(value);\n\t\tcase \"float\":\n\t\t\treturn typeof value === \"number\" && Number.isFinite(value);\n\t\tcase \"enum\":\n\t\t\treturn typeof value === \"string\" && (f.enum?.includes(value) ?? false);\n\t\tcase \"string\":\n\t\t\treturn typeof value === \"string\";\n\t\tcase \"object\":\n\t\t\tif (!isRecord(value)) return false;\n\t\t\tif (f.fields) {\n\t\t\t\tfor (const [key, sub] of Object.entries(f.fields)) {\n\t\t\t\t\tif (!matchesType(value[key], sub)) return false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\tcase \"list\":\n\t\t\tif (!Array.isArray(value)) return false;\n\t\t\tif (f.items) {\n\t\t\t\tconst items = f.items;\n\t\t\t\treturn value.every((item) => matchesType(item, items));\n\t\t\t}\n\t\t\treturn true;\n\t\tdefault:\n\t\t\treturn false;\n\t}\n}\n\n/** Encoded size of a value in bytes, as the wire would carry it. */\nexport function encodedBytes(value: unknown): number {\n\treturn Buffer.byteLength(typeof value === \"string\" ? value : JSON.stringify(value), \"utf8\");\n}\n\n/**\n * Cut a string to at most `maxBytes` of UTF-8 without splitting a code\n * point: one encode, a cut, a step back over continuation bytes, one decode.\n */\nexport function cutUtf8(value: string, maxBytes: number): string {\n\tconst bytes = Buffer.from(value, \"utf8\");\n\tif (bytes.length <= maxBytes) return value;\n\tlet end = Math.max(0, maxBytes);\n\twhile (end > 0 && (bytes[end] & 0xc0) === 0x80) end -= 1;\n\treturn bytes.toString(\"utf8\", 0, end);\n}\n\n// ---------------------------------------------------------------------------\n// Validation\n// ---------------------------------------------------------------------------\n\nclass Violations {\n\treadonly list: string[] = [];\n\tadd(where: string, what: string): void {\n\t\tthis.list.push(`${where}: ${what}`);\n\t}\n}\n\nfunction validateSchema(v: Violations, where: string, schema: unknown): void {\n\tif (!isRecord(schema)) {\n\t\tv.add(where, \"must be an object of fields\");\n\t\treturn;\n\t}\n\tfor (const [key, field] of Object.entries(schema)) {\n\t\tconst at = `${where}.${key}`;\n\t\tif (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) v.add(at, \"field names are identifiers\");\n\t\tif (typeof field === \"string\") {\n\t\t\tif (!VALUE_TYPES.includes(field)) v.add(at, `unknown type ${JSON.stringify(field)}`);\n\t\t\telse if (field === \"enum\") v.add(at, \"an enum field needs its values (use the object form)\");\n\t\t\tcontinue;\n\t\t}\n\t\tif (!isRecord(field) || typeof field.type !== \"string\" || !VALUE_TYPES.includes(field.type)) {\n\t\t\tv.add(at, \"must be a type name or an object with a valid type\");\n\t\t\tcontinue;\n\t\t}\n\t\tif (field.max !== undefined) {\n\t\t\tif (!isPositiveInt(field.max)) v.add(at, \"max must be a positive integer\");\n\t\t\tif (!SIZED_TYPES.includes(field.type)) v.add(at, \"max applies to sized types only\");\n\t\t}\n\t\tif (field.type === \"enum\") {\n\t\t\tif (!Array.isArray(field.enum) || field.enum.length === 0 || !field.enum.every((e) => typeof e === \"string\")) {\n\t\t\t\tv.add(at, \"enum fields need a non-empty list of string values\");\n\t\t\t}\n\t\t} else if (field.enum !== undefined) v.add(at, \"enum values belong to enum fields only\");\n\t\tif (field.fields !== undefined) {\n\t\t\tif (field.type !== \"object\") v.add(at, \"fields belong to object fields only\");\n\t\t\telse validateSchema(v, at, field.fields);\n\t\t}\n\t\tif (field.items !== undefined) {\n\t\t\tif (field.type !== \"list\") v.add(at, \"items belong to list fields only\");\n\t\t\telse validateSchema(v, at, { item: field.items });\n\t\t}\n\t\tif (field.nullable !== undefined && typeof field.nullable !== \"boolean\") v.add(at, \"nullable must be a boolean\");\n\t\tif (field.doc !== undefined && typeof field.doc !== \"string\") v.add(at, \"doc must be a string\");\n\t}\n}\n\nfunction validateNamed(v: Violations, where: string, items: unknown, seen: Set<string>): Record<string, unknown>[] {\n\tif (!Array.isArray(items)) {\n\t\tv.add(where, \"must be a list\");\n\t\treturn [];\n\t}\n\tconst valid: Record<string, unknown>[] = [];\n\titems.forEach((item, index) => {\n\t\tconst at = `${where}[${index}]`;\n\t\tif (!isRecord(item)) {\n\t\t\tv.add(at, \"must be an object\");\n\t\t\treturn;\n\t\t}\n\t\tif (!isValidName(item.name)) {\n\t\t\tv.add(at, `invalid name ${JSON.stringify(item.name)}`);\n\t\t\treturn;\n\t\t}\n\t\tif (seen.has(item.name)) v.add(`${where}.${item.name}`, \"duplicate name\");\n\t\tseen.add(item.name);\n\t\tif (item.name.startsWith(\"abai.\") && !(where === \"events\" && LIBRARY_EVENTS.includes(item.name))) {\n\t\t\tv.add(`${where}.${item.name}`, \"the abai. prefix is reserved for the library\");\n\t\t}\n\t\tif (typeof item.doc !== \"string\" || item.doc.trim() === \"\") v.add(`${where}.${item.name}`, \"doc is required\");\n\t\tvalid.push(item);\n\t});\n\treturn valid;\n}\n\nfunction validateCell(v: Violations, cell: Record<string, unknown>): void {\n\tconst at = `cells.${cell.name}`;\n\tconst type = cell.type;\n\tif (typeof type !== \"string\" || !VALUE_TYPES.includes(type)) {\n\t\tv.add(at, `unknown type ${JSON.stringify(type)}`);\n\t\treturn;\n\t}\n\tif (cell.access !== \"read\" && cell.access !== \"readwrite\") v.add(at, \"access must be read or readwrite\");\n\tif (cell.max !== undefined) {\n\t\tif (!isPositiveInt(cell.max)) v.add(at, \"max must be a positive integer\");\n\t\tif (!SIZED_TYPES.includes(type)) v.add(at, \"max applies to sized types only\");\n\t}\n\tif (type === \"enum\") {\n\t\tif (!Array.isArray(cell.enum) || cell.enum.length === 0 || !cell.enum.every((e) => typeof e === \"string\")) {\n\t\t\tv.add(at, \"enum cells need a non-empty list of string values\");\n\t\t}\n\t} else if (cell.enum !== undefined) v.add(at, \"enum values belong to enum cells only\");\n\tif (cell.range !== undefined) {\n\t\tconst range = cell.range;\n\t\tif (\n\t\t\t!Array.isArray(range) ||\n\t\t\trange.length !== 2 ||\n\t\t\ttypeof range[0] !== \"number\" ||\n\t\t\ttypeof range[1] !== \"number\" ||\n\t\t\trange[0] > range[1]\n\t\t) {\n\t\t\tv.add(at, \"range must be [min, max]\");\n\t\t}\n\t\tif (type !== \"int\" && type !== \"float\") v.add(at, \"range applies to int and float cells only\");\n\t}\n\tif (cell.cadence !== undefined && !isPositiveInt(cell.cadence)) v.add(at, \"cadence must be a positive integer\");\n\tif (cell.fields !== undefined) {\n\t\tif (type !== \"object\") v.add(at, \"fields belong to object cells only\");\n\t\telse validateSchema(v, at, cell.fields);\n\t}\n\tif (cell.items !== undefined) {\n\t\tif (type !== \"list\") v.add(at, \"items belong to list cells only\");\n\t\telse validateSchema(v, at, { item: cell.items });\n\t}\n\tif (cell.nullable !== undefined && typeof cell.nullable !== \"boolean\") v.add(at, \"nullable must be a boolean\");\n\tif (cell.access === \"readwrite\") {\n\t\tif (cell.default === undefined) v.add(at, \"a readwrite cell needs a default\");\n\t\telse if (!matchesType(cell.default, cell as unknown as FieldSchema))\n\t\t\tv.add(at, \"default is not of the cell's type\");\n\t\tif (cell.policy !== undefined && cell.policy !== \"auto\" && cell.policy !== \"confirm\") {\n\t\t\tv.add(at, \"a knob's policy is auto or confirm\");\n\t\t}\n\t\tif (cell.timeout !== undefined) {\n\t\t\tif (!isDuration(cell.timeout)) v.add(at, \"timeout must be a duration such as 30s\");\n\t\t\tif (!SIZED_TYPES.includes(type)) v.add(at, \"a delivery timeout applies to sized knobs only\");\n\t\t}\n\t} else {\n\t\tif (cell.policy !== undefined) v.add(at, \"policy applies to readwrite cells only\");\n\t\tif (cell.timeout !== undefined) v.add(at, \"timeout applies to readwrite cells only\");\n\t\tif (cell.default !== undefined) v.add(at, \"default applies to readwrite cells only\");\n\t}\n}\n\nfunction validateEvent(v: Violations, event: Record<string, unknown>): void {\n\tconst at = `events.${event.name}`;\n\tvalidateSchema(v, `${at}.payload`, event.payload);\n\tif (event.wakes !== undefined && (typeof event.wakes !== \"string\" || event.wakes.trim() === \"\")) {\n\t\tv.add(at, \"wakes must be always, never or a condition\");\n\t}\n\tif (event.large !== undefined && typeof event.large !== \"boolean\") v.add(at, \"large must be a boolean\");\n\tif (isRecord(event.payload)) {\n\t\tconst bytes = payloadBytes(event.payload as Schema);\n\t\tif (bytes > EVENT_SLOT_BYTES && event.large !== true) {\n\t\t\tv.add(at, `payload counts ${bytes} bytes, over ${EVENT_SLOT_BYTES}: declare large: true`);\n\t\t}\n\t}\n}\n\nfunction validateCapability(v: Violations, cap: Record<string, unknown>, knobs: ReadonlySet<string>): void {\n\tconst at = `capabilities.${cap.name}`;\n\tvalidateSchema(v, `${at}.params`, cap.params);\n\tvalidateSchema(v, `${at}.result`, cap.result);\n\tif (cap.effect !== \"read\" && cap.effect !== \"mutate\") v.add(at, \"effect must be read or mutate\");\n\tif (cap.dispatch !== \"immediate\" && cap.dispatch !== \"safepoint\") v.add(at, \"dispatch must be declared\");\n\tif (typeof cap.policy !== \"string\" || !POLICIES.includes(cap.policy)) v.add(at, \"policy must be declared\");\n\tif (cap.timeout !== undefined && !isDuration(cap.timeout)) v.add(at, \"timeout must be a duration such as 30s\");\n\tif (cap.example !== undefined) {\n\t\tif (!isRecord(cap.example)) v.add(at, \"example must be an object of parameters\");\n\t\telse if (isRecord(cap.params)) {\n\t\t\tfor (const key of Object.keys(cap.example)) {\n\t\t\t\tif (!(key in cap.params)) v.add(at, `example has an undeclared parameter ${key}`);\n\t\t\t}\n\t\t}\n\t}\n\tif (cap.writes !== undefined) {\n\t\tif (!isValidName(cap.writes)) v.add(at, \"writes must name a cell\");\n\t\telse if (!knobs.has(cap.writes)) v.add(at, `writes names ${cap.writes}, which is not a readwrite cell`);\n\t}\n}\n\nfunction validateDecision(v: Violations, decision: Record<string, unknown>): void {\n\tconst at = `decisions.${decision.name}`;\n\tvalidateSchema(v, `${at}.context`, decision.context);\n\tconst hasOptions = decision.options !== undefined;\n\tconst hasAnswer = decision.answer !== undefined;\n\tif (hasOptions === hasAnswer) v.add(at, \"declare either options or answer\");\n\tif (hasOptions) {\n\t\tconst options = decision.options;\n\t\tif (!Array.isArray(options) || options.length === 0 || !options.every((o) => typeof o === \"string\")) {\n\t\t\tv.add(at, \"options must be a non-empty list of strings\");\n\t\t} else if (decision.default !== \"abort\" && !options.includes(decision.default as string)) {\n\t\t\tv.add(at, \"default must be one of the options or abort\");\n\t\t}\n\t}\n\tif (hasAnswer) validateSchema(v, `${at}.answer`, decision.answer);\n\tif (decision.default === undefined) v.add(at, \"default is required\");\n\tif (!isDuration(decision.timeout)) v.add(at, \"timeout is required (a duration such as 30s)\");\n\tif (typeof decision.policy !== \"string\" || !POLICIES.includes(decision.policy)) v.add(at, \"policy must be declared\");\n}\n\nfunction validateTurn(v: Violations, turn: Record<string, unknown>): void {\n\tif (!isDuration(turn.timeout)) v.add(`turns.${turn.name}`, \"timeout is required (a duration such as 30s)\");\n}\n\n/**\n * Validate a manifest in either form. Returns the violations, each\n * `<where>: <what>`; an empty list means the manifest validates.\n */\nexport function validateManifest(value: unknown): string[] {\n\tconst v = new Violations();\n\tif (!isRecord(value)) return [\"manifest: must be an object\"];\n\tif (value.abaigrammar !== ABAIGRAMMAR_VERSION) {\n\t\tv.add(\"abaigrammar\", `must be ${JSON.stringify(ABAIGRAMMAR_VERSION)}`);\n\t}\n\tif (typeof value.name !== \"string\" || value.name.trim() === \"\") v.add(\"name\", \"is required\");\n\tif (typeof value.entry !== \"string\" || value.entry.trim() === \"\") v.add(\"entry\", \"is required\");\n\tconst modes = value.modes;\n\tif (!Array.isArray(modes) || modes.length === 0) v.add(\"modes\", \"must list at least one mode\");\n\telse {\n\t\tmodes.forEach((mode, index) => {\n\t\t\tif (!(MODES as readonly unknown[]).includes(mode))\n\t\t\t\tv.add(`modes[${index}]`, `unknown mode ${JSON.stringify(mode)}`);\n\t\t});\n\t\tif (new Set(modes).size !== modes.length) v.add(\"modes\", \"must not repeat a mode\");\n\t}\n\tif (!isRecord(value.content) || typeof value.content.identity !== \"string\" || value.content.identity === \"\") {\n\t\tv.add(\"content.identity\", \"is required\");\n\t}\n\tif (!isRecord(value.audit) || typeof value.audit.path !== \"string\" || value.audit.path === \"\") {\n\t\tv.add(\"audit.path\", \"is required\");\n\t}\n\tif (value.lifecycle !== undefined) {\n\t\tconst lifecycle = value.lifecycle;\n\t\tif (!isRecord(lifecycle) || ![\"cooperative\", \"os\", \"none\"].includes(lifecycle.pause as string)) {\n\t\t\tv.add(\"lifecycle.pause\", \"must be cooperative, os or none\");\n\t\t}\n\t}\n\tif (value.deviations !== undefined) {\n\t\tconst deviations = value.deviations;\n\t\tif (!Array.isArray(deviations) || !deviations.every((d) => typeof d === \"string\" && d.trim() !== \"\")) {\n\t\t\tv.add(\"deviations\", \"must be a list of non-empty strings\");\n\t\t}\n\t}\n\tif (value.check !== undefined && (!isRecord(value.check) || typeof value.check.run !== \"string\")) {\n\t\tv.add(\"check.run\", \"is required when check is declared\");\n\t}\n\n\tconst cells = validateNamed(v, \"cells\", value.cells, new Set());\n\tfor (const cell of cells) validateCell(v, cell);\n\tconst knobs = new Set(cells.filter((cell) => cell.access === \"readwrite\").map((cell) => cell.name as string));\n\tfor (const event of validateNamed(v, \"events\", value.events, new Set())) validateEvent(v, event);\n\tfor (const cap of validateNamed(v, \"capabilities\", value.capabilities, new Set())) {\n\t\tvalidateCapability(v, cap, knobs);\n\t}\n\tfor (const decision of validateNamed(v, \"decisions\", value.decisions, new Set())) validateDecision(v, decision);\n\tfor (const turn of validateNamed(v, \"turns\", value.turns, new Set())) validateTurn(v, turn);\n\treturn v.list;\n}\n\n/** Narrow an unknown value to a Manifest; throws with the violations otherwise. */\nexport function assertManifest(value: unknown): Manifest {\n\tconst violations = validateManifest(value);\n\tif (violations.length > 0) throw new Error(`manifest does not validate:\\n${violations.join(\"\\n\")}`);\n\treturn value as Manifest;\n}\n"]}
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/manifest/manifest.ts"],"names":[],"mappings":"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","sourcesContent":["// The abaigrammar 0.1 manifest: types, validation and helpers (spec/abaigrammar.md sections 5 and 7).\n//\n// The manifest exists in two forms that must agree: in code (the program's\n// declarations, the source of truth at runtime) and in the repo\n// (abaigram.yaml, rendered by render.ts). The validator here checks either\n// form, so `<entry> doctor` and the self-check test apply the same rules.\n// Fields beyond the grammar (`deviations`, `writes`, `nullable`) are\n// extensions a partial realization needs; the manifest's `deviations` list\n// names them.\n\nexport const ABAIGRAMMAR_VERSION = \"0.1\";\n\nexport type ScalarType = \"bool\" | \"int\" | \"float\" | \"enum\";\nexport type SizedType = \"string\" | \"object\" | \"list\";\nexport type ValueType = ScalarType | SizedType;\n\nexport type Mode = \"turns\" | \"thread\" | \"sidecar\";\nexport const MODES: readonly Mode[] = [\"turns\", \"thread\", \"sidecar\"];\n\nexport type Access = \"read\" | \"readwrite\";\nexport type Effect = \"read\" | \"mutate\";\nexport type Dispatch = \"immediate\" | \"safepoint\";\nexport type Policy = \"auto\" | \"confirm\" | \"forbid\";\nexport type Wakes = \"always\" | \"never\" | string;\n\n/** Default `max` sizes of the sized types (grammar section 5, common rules). */\nexport const DEFAULT_STRING_MAX = 256;\nexport const DEFAULT_SIZED_MAX = 1024;\n/** Payload bytes an event slot holds; a larger declared payload must be `large`. */\nexport const EVENT_SLOT_BYTES = 4096;\n/** Bytes counted for a scalar field. */\nexport const SCALAR_BYTES = 8;\n\n/**\n * A schema field: a bare type name when the defaults suffice, or an object\n * with `type` and `max` (and, beyond the grammar, `enum` values, an object's\n * `fields`, a list's `items`, `nullable` and a `doc`).\n */\nexport type FieldSchema =\n\t| ValueType\n\t| {\n\t\t\ttype: ValueType;\n\t\t\tmax?: number;\n\t\t\tenum?: string[];\n\t\t\tfields?: Schema;\n\t\t\titems?: FieldSchema;\n\t\t\tnullable?: boolean;\n\t\t\tdoc?: string;\n\t };\n\nexport type Schema = Record<string, FieldSchema>;\n\nexport interface CellDecl {\n\tname: string;\n\ttype: ValueType;\n\taccess: Access;\n\tdoc: string;\n\t/** Sized types only. */\n\tmax?: number;\n\t/** `enum` cells. */\n\tenum?: string[];\n\t/** `int` and `float` cells. */\n\trange?: [number, number];\n\t/** Required for `readwrite`. */\n\tdefault?: unknown;\n\t/** Hint in milliseconds. */\n\tcadence?: number;\n\t/** `readwrite` only; knobs are never `forbid`. */\n\tpolicy?: \"auto\" | \"confirm\";\n\t/** Sized knobs only: delivery timeout. */\n\ttimeout?: string;\n\t/** `object` cells: the fields. */\n\tfields?: Schema;\n\t/** `list` cells: the item schema. */\n\titems?: FieldSchema;\n\t/** Extension: the value may be null. */\n\tnullable?: boolean;\n}\n\nexport interface EventDecl {\n\tname: string;\n\tdoc: string;\n\tpayload: Schema;\n\twakes?: Wakes;\n\tlarge?: boolean;\n}\n\nexport interface CapabilityDecl {\n\tname: string;\n\tdoc: string;\n\tparams: Schema;\n\tresult: Schema;\n\teffect: Effect;\n\tdispatch: Dispatch;\n\ttimeout?: string;\n\tpolicy: Policy;\n\texample?: Record<string, unknown>;\n\t/** Extension: the knob this capability sets; such calls are audited as knob writes. */\n\twrites?: string;\n}\n\nexport interface DecisionDecl {\n\tname: string;\n\tdoc: string;\n\tcontext: Schema;\n\t/** Either `options` (an enum of choices) or `answer` (a schema). */\n\toptions?: string[];\n\tanswer?: Schema;\n\tdefault: unknown;\n\ttimeout: string;\n\tpolicy: Policy;\n}\n\nexport interface TurnDecl {\n\tname: string;\n\tdoc: string;\n\ttimeout: string;\n}\n\nexport interface Manifest {\n\tabaigrammar: string;\n\tname: string;\n\tentry: string;\n\tmodes: Mode[];\n\tharness?: { path: string | null };\n\tmodel?: Record<string, unknown>;\n\tcheck?: { run: string; overhead?: string };\n\tcontent: { identity: string; install?: string; use?: string; turns?: string };\n\taudit: { path: string };\n\tlifecycle?: {\n\t\tpause: \"cooperative\" | \"os\" | \"none\";\n\t\tstop?: { graceful: string; handler: string };\n\t\tpolicy?: Partial<Record<\"pause\" | \"resume\" | \"stop\" | \"restart\", Policy>>;\n\t};\n\tattention?: { budget?: { wakes_per_minute?: number; tokens_per_hour?: number } };\n\tpolicy?: { confirm_timeout?: string };\n\t/** The agent may be a member of an agent network (section 7); `doc` says how its members relate to this program's names. */\n\tnetwork?: { required?: boolean; doc: string };\n\t/** Where this instantiation departs from the grammar, one sentence each (section 7); a program may add its own. */\n\tdeviations?: string[];\n\tcells: CellDecl[];\n\tevents: EventDecl[];\n\tcapabilities: CapabilityDecl[];\n\tdecisions: DecisionDecl[];\n\tturns: TurnDecl[];\n}\n\n/** Events the library (the stub) emits under the reserved `abai.` prefix. */\nexport const LIBRARY_EVENTS: readonly string[] = [\n\t\"abai.events.dropped\",\n\t\"abai.knob.reset\",\n\t\"abai.lifecycle.exited\",\n\t\"abai.pause.blocked\",\n\t\"abai.io.stdout\",\n\t\"abai.io.stderr\",\n\t\"abai.audit.failed\",\n];\n\nconst NAME = /^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)*$/;\nconst DURATION = /^[0-9]+(ms|s|m|h)$/;\nconst VALUE_TYPES: readonly string[] = [\"bool\", \"int\", \"float\", \"enum\", \"string\", \"object\", \"list\"];\nconst SIZED_TYPES: readonly string[] = [\"string\", \"object\", \"list\"];\nconst POLICIES: readonly string[] = [\"auto\", \"confirm\", \"forbid\"];\n\n/** A valid abai name: lowercase segments joined by dots, words joined by underscores. */\nexport function isValidName(name: unknown): name is string {\n\treturn typeof name === \"string\" && NAME.test(name);\n}\n\nexport function isDuration(value: unknown): value is string {\n\treturn typeof value === \"string\" && DURATION.test(value);\n}\n\n/** A duration string in milliseconds. */\nexport function durationMs(value: string): number {\n\tconst match = /^([0-9]+)(ms|s|m|h)$/.exec(value);\n\tif (!match) throw new Error(`not a duration: ${value}`);\n\tconst n = Number(match[1]);\n\tswitch (match[2]) {\n\t\tcase \"ms\":\n\t\t\treturn n;\n\t\tcase \"s\":\n\t\t\treturn n * 1000;\n\t\tcase \"m\":\n\t\t\treturn n * 60_000;\n\t\tdefault:\n\t\t\treturn n * 3_600_000;\n\t}\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isPositiveInt(value: unknown): value is number {\n\treturn typeof value === \"number\" && Number.isInteger(value) && value > 0;\n}\n\n/** Normalize a field schema to its object form. */\nexport function fieldOf(field: FieldSchema): Exclude<FieldSchema, string> {\n\treturn typeof field === \"string\" ? { type: field } : field;\n}\n\n/** Bytes a field counts toward an event slot: scalars 8, sized fields their `max`. */\nexport function fieldBytes(field: FieldSchema): number {\n\tconst f = fieldOf(field);\n\tif (f.type === \"string\") return f.max ?? DEFAULT_STRING_MAX;\n\tif (f.type === \"object\" || f.type === \"list\") return f.max ?? DEFAULT_SIZED_MAX;\n\treturn SCALAR_BYTES;\n}\n\n/** Bytes a payload counts toward an event slot (grammar section 5.1). */\nexport function payloadBytes(schema: Schema): number {\n\tlet total = 0;\n\tfor (const field of Object.values(schema)) total += fieldBytes(field);\n\treturn total;\n}\n\n/** Whether a value has a declared type. `int` accepts integers only; `float` any finite number. */\nexport function matchesType(value: unknown, field: FieldSchema): boolean {\n\tconst f = fieldOf(field);\n\tif (value === null) return f.nullable === true;\n\tswitch (f.type) {\n\t\tcase \"bool\":\n\t\t\treturn typeof value === \"boolean\";\n\t\tcase \"int\":\n\t\t\treturn typeof value === \"number\" && Number.isInteger(value);\n\t\tcase \"float\":\n\t\t\treturn typeof value === \"number\" && Number.isFinite(value);\n\t\tcase \"enum\":\n\t\t\treturn typeof value === \"string\" && (f.enum?.includes(value) ?? false);\n\t\tcase \"string\":\n\t\t\treturn typeof value === \"string\";\n\t\tcase \"object\":\n\t\t\tif (!isRecord(value)) return false;\n\t\t\tif (f.fields) {\n\t\t\t\tfor (const [key, sub] of Object.entries(f.fields)) {\n\t\t\t\t\tif (!matchesType(value[key], sub)) return false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\tcase \"list\":\n\t\t\tif (!Array.isArray(value)) return false;\n\t\t\tif (f.items) {\n\t\t\t\tconst items = f.items;\n\t\t\t\treturn value.every((item) => matchesType(item, items));\n\t\t\t}\n\t\t\treturn true;\n\t\tdefault:\n\t\t\treturn false;\n\t}\n}\n\n/** Encoded size of a value in bytes, as the wire would carry it. */\nexport function encodedBytes(value: unknown): number {\n\treturn Buffer.byteLength(typeof value === \"string\" ? value : JSON.stringify(value), \"utf8\");\n}\n\n/**\n * Cut a string to at most `maxBytes` of UTF-8 without splitting a code\n * point: one encode, a cut, a step back over continuation bytes, one decode.\n */\nexport function cutUtf8(value: string, maxBytes: number): string {\n\tconst bytes = Buffer.from(value, \"utf8\");\n\tif (bytes.length <= maxBytes) return value;\n\tlet end = Math.max(0, maxBytes);\n\twhile (end > 0 && (bytes[end] & 0xc0) === 0x80) end -= 1;\n\treturn bytes.toString(\"utf8\", 0, end);\n}\n\n// ---------------------------------------------------------------------------\n// Validation\n// ---------------------------------------------------------------------------\n\nclass Violations {\n\treadonly list: string[] = [];\n\tadd(where: string, what: string): void {\n\t\tthis.list.push(`${where}: ${what}`);\n\t}\n}\n\nfunction validateSchema(v: Violations, where: string, schema: unknown): void {\n\tif (!isRecord(schema)) {\n\t\tv.add(where, \"must be an object of fields\");\n\t\treturn;\n\t}\n\tfor (const [key, field] of Object.entries(schema)) {\n\t\tconst at = `${where}.${key}`;\n\t\tif (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) v.add(at, \"field names are identifiers\");\n\t\tif (typeof field === \"string\") {\n\t\t\tif (!VALUE_TYPES.includes(field)) v.add(at, `unknown type ${JSON.stringify(field)}`);\n\t\t\telse if (field === \"enum\") v.add(at, \"an enum field needs its values (use the object form)\");\n\t\t\tcontinue;\n\t\t}\n\t\tif (!isRecord(field) || typeof field.type !== \"string\" || !VALUE_TYPES.includes(field.type)) {\n\t\t\tv.add(at, \"must be a type name or an object with a valid type\");\n\t\t\tcontinue;\n\t\t}\n\t\tif (field.max !== undefined) {\n\t\t\tif (!isPositiveInt(field.max)) v.add(at, \"max must be a positive integer\");\n\t\t\tif (!SIZED_TYPES.includes(field.type)) v.add(at, \"max applies to sized types only\");\n\t\t}\n\t\tif (field.type === \"enum\") {\n\t\t\tif (!Array.isArray(field.enum) || field.enum.length === 0 || !field.enum.every((e) => typeof e === \"string\")) {\n\t\t\t\tv.add(at, \"enum fields need a non-empty list of string values\");\n\t\t\t}\n\t\t} else if (field.enum !== undefined) v.add(at, \"enum values belong to enum fields only\");\n\t\tif (field.fields !== undefined) {\n\t\t\tif (field.type !== \"object\") v.add(at, \"fields belong to object fields only\");\n\t\t\telse validateSchema(v, at, field.fields);\n\t\t}\n\t\tif (field.items !== undefined) {\n\t\t\tif (field.type !== \"list\") v.add(at, \"items belong to list fields only\");\n\t\t\telse validateSchema(v, at, { item: field.items });\n\t\t}\n\t\tif (field.nullable !== undefined && typeof field.nullable !== \"boolean\") v.add(at, \"nullable must be a boolean\");\n\t\tif (field.doc !== undefined && typeof field.doc !== \"string\") v.add(at, \"doc must be a string\");\n\t}\n}\n\nfunction validateNamed(v: Violations, where: string, items: unknown, seen: Set<string>): Record<string, unknown>[] {\n\tif (!Array.isArray(items)) {\n\t\tv.add(where, \"must be a list\");\n\t\treturn [];\n\t}\n\tconst valid: Record<string, unknown>[] = [];\n\titems.forEach((item, index) => {\n\t\tconst at = `${where}[${index}]`;\n\t\tif (!isRecord(item)) {\n\t\t\tv.add(at, \"must be an object\");\n\t\t\treturn;\n\t\t}\n\t\tif (!isValidName(item.name)) {\n\t\t\tv.add(at, `invalid name ${JSON.stringify(item.name)}`);\n\t\t\treturn;\n\t\t}\n\t\tif (seen.has(item.name)) v.add(`${where}.${item.name}`, \"duplicate name\");\n\t\tseen.add(item.name);\n\t\tif (item.name.startsWith(\"abai.\") && !(where === \"events\" && LIBRARY_EVENTS.includes(item.name))) {\n\t\t\tv.add(`${where}.${item.name}`, \"the abai. prefix is reserved for the library\");\n\t\t}\n\t\tif (typeof item.doc !== \"string\" || item.doc.trim() === \"\") v.add(`${where}.${item.name}`, \"doc is required\");\n\t\tvalid.push(item);\n\t});\n\treturn valid;\n}\n\nfunction validateCell(v: Violations, cell: Record<string, unknown>): void {\n\tconst at = `cells.${cell.name}`;\n\tconst type = cell.type;\n\tif (typeof type !== \"string\" || !VALUE_TYPES.includes(type)) {\n\t\tv.add(at, `unknown type ${JSON.stringify(type)}`);\n\t\treturn;\n\t}\n\tif (cell.access !== \"read\" && cell.access !== \"readwrite\") v.add(at, \"access must be read or readwrite\");\n\tif (cell.max !== undefined) {\n\t\tif (!isPositiveInt(cell.max)) v.add(at, \"max must be a positive integer\");\n\t\tif (!SIZED_TYPES.includes(type)) v.add(at, \"max applies to sized types only\");\n\t}\n\tif (type === \"enum\") {\n\t\tif (!Array.isArray(cell.enum) || cell.enum.length === 0 || !cell.enum.every((e) => typeof e === \"string\")) {\n\t\t\tv.add(at, \"enum cells need a non-empty list of string values\");\n\t\t}\n\t} else if (cell.enum !== undefined) v.add(at, \"enum values belong to enum cells only\");\n\tif (cell.range !== undefined) {\n\t\tconst range = cell.range;\n\t\tif (\n\t\t\t!Array.isArray(range) ||\n\t\t\trange.length !== 2 ||\n\t\t\ttypeof range[0] !== \"number\" ||\n\t\t\ttypeof range[1] !== \"number\" ||\n\t\t\trange[0] > range[1]\n\t\t) {\n\t\t\tv.add(at, \"range must be [min, max]\");\n\t\t}\n\t\tif (type !== \"int\" && type !== \"float\") v.add(at, \"range applies to int and float cells only\");\n\t}\n\tif (cell.cadence !== undefined && !isPositiveInt(cell.cadence)) v.add(at, \"cadence must be a positive integer\");\n\tif (cell.fields !== undefined) {\n\t\tif (type !== \"object\") v.add(at, \"fields belong to object cells only\");\n\t\telse validateSchema(v, at, cell.fields);\n\t}\n\tif (cell.items !== undefined) {\n\t\tif (type !== \"list\") v.add(at, \"items belong to list cells only\");\n\t\telse validateSchema(v, at, { item: cell.items });\n\t}\n\tif (cell.nullable !== undefined && typeof cell.nullable !== \"boolean\") v.add(at, \"nullable must be a boolean\");\n\tif (cell.access === \"readwrite\") {\n\t\tif (cell.default === undefined) v.add(at, \"a readwrite cell needs a default\");\n\t\telse if (!matchesType(cell.default, cell as unknown as FieldSchema))\n\t\t\tv.add(at, \"default is not of the cell's type\");\n\t\tif (cell.policy !== undefined && cell.policy !== \"auto\" && cell.policy !== \"confirm\") {\n\t\t\tv.add(at, \"a knob's policy is auto or confirm\");\n\t\t}\n\t\tif (cell.timeout !== undefined) {\n\t\t\tif (!isDuration(cell.timeout)) v.add(at, \"timeout must be a duration such as 30s\");\n\t\t\tif (!SIZED_TYPES.includes(type)) v.add(at, \"a delivery timeout applies to sized knobs only\");\n\t\t}\n\t} else {\n\t\tif (cell.policy !== undefined) v.add(at, \"policy applies to readwrite cells only\");\n\t\tif (cell.timeout !== undefined) v.add(at, \"timeout applies to readwrite cells only\");\n\t\tif (cell.default !== undefined) v.add(at, \"default applies to readwrite cells only\");\n\t}\n}\n\nfunction validateEvent(v: Violations, event: Record<string, unknown>): void {\n\tconst at = `events.${event.name}`;\n\tvalidateSchema(v, `${at}.payload`, event.payload);\n\tif (event.wakes !== undefined && (typeof event.wakes !== \"string\" || event.wakes.trim() === \"\")) {\n\t\tv.add(at, \"wakes must be always, never or a condition\");\n\t}\n\tif (event.large !== undefined && typeof event.large !== \"boolean\") v.add(at, \"large must be a boolean\");\n\tif (isRecord(event.payload)) {\n\t\tconst bytes = payloadBytes(event.payload as Schema);\n\t\tif (bytes > EVENT_SLOT_BYTES && event.large !== true) {\n\t\t\tv.add(at, `payload counts ${bytes} bytes, over ${EVENT_SLOT_BYTES}: declare large: true`);\n\t\t}\n\t}\n}\n\nfunction validateCapability(v: Violations, cap: Record<string, unknown>, knobs: ReadonlySet<string>): void {\n\tconst at = `capabilities.${cap.name}`;\n\tvalidateSchema(v, `${at}.params`, cap.params);\n\tvalidateSchema(v, `${at}.result`, cap.result);\n\tif (cap.effect !== \"read\" && cap.effect !== \"mutate\") v.add(at, \"effect must be read or mutate\");\n\tif (cap.dispatch !== \"immediate\" && cap.dispatch !== \"safepoint\") v.add(at, \"dispatch must be declared\");\n\tif (typeof cap.policy !== \"string\" || !POLICIES.includes(cap.policy)) v.add(at, \"policy must be declared\");\n\tif (cap.timeout !== undefined && !isDuration(cap.timeout)) v.add(at, \"timeout must be a duration such as 30s\");\n\tif (cap.example !== undefined) {\n\t\tif (!isRecord(cap.example)) v.add(at, \"example must be an object of parameters\");\n\t\telse if (isRecord(cap.params)) {\n\t\t\tfor (const key of Object.keys(cap.example)) {\n\t\t\t\tif (!(key in cap.params)) v.add(at, `example has an undeclared parameter ${key}`);\n\t\t\t}\n\t\t}\n\t}\n\tif (cap.writes !== undefined) {\n\t\tif (!isValidName(cap.writes)) v.add(at, \"writes must name a cell\");\n\t\telse if (!knobs.has(cap.writes)) v.add(at, `writes names ${cap.writes}, which is not a readwrite cell`);\n\t}\n}\n\nfunction validateDecision(v: Violations, decision: Record<string, unknown>): void {\n\tconst at = `decisions.${decision.name}`;\n\tvalidateSchema(v, `${at}.context`, decision.context);\n\tconst hasOptions = decision.options !== undefined;\n\tconst hasAnswer = decision.answer !== undefined;\n\tif (hasOptions === hasAnswer) v.add(at, \"declare either options or answer\");\n\tif (hasOptions) {\n\t\tconst options = decision.options;\n\t\tif (!Array.isArray(options) || options.length === 0 || !options.every((o) => typeof o === \"string\")) {\n\t\t\tv.add(at, \"options must be a non-empty list of strings\");\n\t\t} else if (decision.default !== \"abort\" && !options.includes(decision.default as string)) {\n\t\t\tv.add(at, \"default must be one of the options or abort\");\n\t\t}\n\t}\n\tif (hasAnswer) validateSchema(v, `${at}.answer`, decision.answer);\n\tif (decision.default === undefined) v.add(at, \"default is required\");\n\tif (!isDuration(decision.timeout)) v.add(at, \"timeout is required (a duration such as 30s)\");\n\tif (typeof decision.policy !== \"string\" || !POLICIES.includes(decision.policy)) v.add(at, \"policy must be declared\");\n}\n\nfunction validateTurn(v: Violations, turn: Record<string, unknown>): void {\n\tif (!isDuration(turn.timeout)) v.add(`turns.${turn.name}`, \"timeout is required (a duration such as 30s)\");\n}\n\n/**\n * Validate a manifest in either form. Returns the violations, each\n * `<where>: <what>`; an empty list means the manifest validates.\n */\nexport function validateManifest(value: unknown): string[] {\n\tconst v = new Violations();\n\tif (!isRecord(value)) return [\"manifest: must be an object\"];\n\tif (value.abaigrammar !== ABAIGRAMMAR_VERSION) {\n\t\tv.add(\"abaigrammar\", `must be ${JSON.stringify(ABAIGRAMMAR_VERSION)}`);\n\t}\n\tif (typeof value.name !== \"string\" || value.name.trim() === \"\") v.add(\"name\", \"is required\");\n\tif (typeof value.entry !== \"string\" || value.entry.trim() === \"\") v.add(\"entry\", \"is required\");\n\tconst modes = value.modes;\n\tif (!Array.isArray(modes) || modes.length === 0) v.add(\"modes\", \"must list at least one mode\");\n\telse {\n\t\tmodes.forEach((mode, index) => {\n\t\t\tif (!(MODES as readonly unknown[]).includes(mode))\n\t\t\t\tv.add(`modes[${index}]`, `unknown mode ${JSON.stringify(mode)}`);\n\t\t});\n\t\tif (new Set(modes).size !== modes.length) v.add(\"modes\", \"must not repeat a mode\");\n\t}\n\tif (!isRecord(value.content) || typeof value.content.identity !== \"string\" || value.content.identity === \"\") {\n\t\tv.add(\"content.identity\", \"is required\");\n\t}\n\tif (!isRecord(value.audit) || typeof value.audit.path !== \"string\" || value.audit.path === \"\") {\n\t\tv.add(\"audit.path\", \"is required\");\n\t}\n\tif (value.lifecycle !== undefined) {\n\t\tconst lifecycle = value.lifecycle;\n\t\tif (!isRecord(lifecycle) || ![\"cooperative\", \"os\", \"none\"].includes(lifecycle.pause as string)) {\n\t\t\tv.add(\"lifecycle.pause\", \"must be cooperative, os or none\");\n\t\t}\n\t}\n\tif (value.deviations !== undefined) {\n\t\tconst deviations = value.deviations;\n\t\tif (!Array.isArray(deviations) || !deviations.every((d) => typeof d === \"string\" && d.trim() !== \"\")) {\n\t\t\tv.add(\"deviations\", \"must be a list of non-empty strings\");\n\t\t}\n\t}\n\tif (value.check !== undefined && (!isRecord(value.check) || typeof value.check.run !== \"string\")) {\n\t\tv.add(\"check.run\", \"is required when check is declared\");\n\t}\n\tif (value.network !== undefined) {\n\t\tconst network = value.network;\n\t\tif (!isRecord(network) || typeof network.doc !== \"string\" || network.doc.trim() === \"\") {\n\t\t\tv.add(\"network.doc\", \"is required when network is declared\");\n\t\t}\n\t\tif (isRecord(network) && network.required !== undefined && typeof network.required !== \"boolean\") {\n\t\t\tv.add(\"network.required\", \"must be a boolean\");\n\t\t}\n\t}\n\n\tconst cells = validateNamed(v, \"cells\", value.cells, new Set());\n\tfor (const cell of cells) validateCell(v, cell);\n\tconst knobs = new Set(cells.filter((cell) => cell.access === \"readwrite\").map((cell) => cell.name as string));\n\tfor (const event of validateNamed(v, \"events\", value.events, new Set())) validateEvent(v, event);\n\tfor (const cap of validateNamed(v, \"capabilities\", value.capabilities, new Set())) {\n\t\tvalidateCapability(v, cap, knobs);\n\t}\n\tfor (const decision of validateNamed(v, \"decisions\", value.decisions, new Set())) validateDecision(v, decision);\n\tfor (const turn of validateNamed(v, \"turns\", value.turns, new Set())) validateTurn(v, turn);\n\treturn v.list;\n}\n\n/** Narrow an unknown value to a Manifest; throws with the violations otherwise. */\nexport function assertManifest(value: unknown): Manifest {\n\tconst violations = validateManifest(value);\n\tif (violations.length > 0) throw new Error(`manifest does not validate:\\n${violations.join(\"\\n\")}`);\n\treturn value as Manifest;\n}\n"]}
package/dist/program.d.ts CHANGED
@@ -220,8 +220,9 @@ export declare class Abaigram {
220
220
  export declare const ENV_HARNESS_MODULE = "ABAI_HARNESS_MODULE";
221
221
  /**
222
222
  * The harness binary to spawn under sidecar: `ABAI_HARNESS_BIN` (a script
223
- * path runs under this very node), else the program's own
224
- * `node_modules/.bin/abai-embedded-harness`, else the name on PATH.
223
+ * path runs under this very node), else the nearest
224
+ * `node_modules/.bin/abai-embedded-harness` from the program's root
225
+ * upward, else the name on PATH.
225
226
  */
226
227
  export declare function harnessBinary(env: NodeJS.ProcessEnv, root: string): {
227
228
  command: string;
@@ -236,6 +237,10 @@ export interface HarnessModule {
236
237
  out(text: string): void;
237
238
  err(text: string): void;
238
239
  env: NodeJS.ProcessEnv;
240
+ },
241
+ /** The program the entry runs for, so `config net` finds its network directory. */
242
+ context?: {
243
+ program?: string;
239
244
  }) => Promise<number>;
240
245
  doctorOnline?: (manifest: Manifest, env: NodeJS.ProcessEnv) => Promise<Array<{
241
246
  name: string;
@@ -1 +1 @@
1
- {"version":3,"file":"program.d.ts","sourceRoot":"","sources":["../src/program.ts"],"names":[],"mappings":"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","sourcesContent":["// createAbaigram: the program-facing API of the stub (abaigrammar sections 4\n// and 5). The program declares its manifest in code, obtains cell, knob and\n// event handles once, and then writes cells, emits events, serves\n// capabilities and calls touchpoints. With no harness attached, every\n// operation here costs what section 11.1 says: cell writes store, emits and\n// safepoints load one flag, decisions and turns load the flag and count.\n//\n// Touchpoints are awaited promises (see the instantiation's deviations in\n// registry.ts). The attached paths arrive with the harness binding; this\n// file carries the detached behaviour and the seams the binding fills.\nimport { type ChildProcess, spawn } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fitValue } from \"./cells/fit.ts\";\nimport { type ContentSlots, createContent, findRoot } from \"./content.ts\";\nimport { Endpoint } from \"./endpoint.ts\";\nimport {\n\tattachWaitMsFrom,\n\tENV_HARNESS,\n\tENV_HARNESS_BIN,\n\tENV_LAUNCH_SOCKET,\n\ttype HarnessSelection,\n\trunDirFrom,\n\tselectHarness,\n\tselectMode,\n} from \"./env.ts\";\nimport { DirectBinding, type HarnessBinding, type TouchpointKind } from \"./harness-binding.ts\";\nimport {\n\ttype CellDecl,\n\tcutUtf8,\n\ttype DecisionDecl,\n\tdurationMs,\n\ttype EventDecl,\n\tencodedBytes,\n\tfieldOf,\n\tLIBRARY_EVENTS,\n\ttype Manifest,\n\ttype Mode,\n\ttype TurnDecl,\n} from \"./manifest/manifest.ts\";\nimport { attachNullHarness, type NullHarness } from \"./null-harness.ts\";\nimport { FLAG_ATTACHED, FLAG_PAUSED, FLAG_QUEUE, FLAG_WORK, LIBRARY_EVENT_BASE, Region } from \"./region.ts\";\nimport {\n\ttype AbaigramOptions,\n\tbuildManifest,\n\ttype CapabilityHandler,\n\ttype KnobHandler,\n\ttype StopHandler,\n} from \"./registry.ts\";\n\n/** Thrown by `decide` when the applied default is `abort` (section 5.4). */\nexport class AbaigramAbort extends Error {\n\treadonly decision: string;\n\tconstructor(decision: string, cause: string) {\n\t\tsuper(`decision ${decision} applied its default, abort (${cause})`);\n\t\tthis.name = \"AbaigramAbort\";\n\t\tthis.decision = decision;\n\t}\n}\n\nexport interface CellHandle<T = unknown> {\n\treadonly name: string;\n\tget(): T;\n\t/** One store to the value and one to the version. Enum values must be declared; nothing else is checked. */\n\tset(value: T): void;\n}\n\nexport interface KnobHandle<T = unknown> extends CellHandle<T> {\n\t/** Back to the declared default; a sized knob's reset reaches the harness as `abai.knob.reset`. */\n\treset(): void;\n\t/** Sized knobs only: the handler that receives a delivered value at a safepoint. */\n\tonChange(handler: KnobHandler): void;\n}\n\nexport interface EventHandle {\n\treadonly name: string;\n\t/** One load of the attached flag when no harness is attached. */\n\temit(payload?: Record<string, unknown>): void;\n}\n\nexport interface CounterSnapshot {\n\t[name: string]: number;\n}\n\n/** What a harness binding supplies once attached; undefined while detached. */\nexport interface AttachedHarness {\n\t/** Ask the harness; resolves to the answer, or rejects with the cause of a default. */\n\tdecide(decision: DecisionDecl, context: Record<string, unknown>, deadlineMs: number): Promise<unknown>;\n\t/** Give the harness a turn; resolves when it is done or the timeout passes. */\n\tturn(turn: TurnDecl, deadlineMs: number): Promise<void>;\n\t/** An event was published; `seq` is its sequence number. */\n\temitted(seq: number): void;\n\t/** The program detaches it. */\n\tdetach(reason: string): void;\n}\n\ninterface CellEntry {\n\tdecl: CellDecl;\n\t/** Position in `manifest.cells`: the index into `versions`. */\n\tordinal: number;\n\t/** Index into `values` (scalar) or `sized`. */\n\tslot: number;\n\tscalar: boolean;\n\tenumIndex?: Map<string, number>;\n\t/** Built once per cell: the typed store and load (section 11.2 rows). */\n\tset: (value: unknown) => void;\n\tget: () => unknown;\n}\n\ninterface EventEntry {\n\tdecl: EventDecl;\n\tordinal: number;\n\tfields: Array<{ key: string; type: string; max: number | undefined }>;\n}\n\n/** Attaches an in-process harness to the binding the stub hands it. */\nexport type HarnessFactory = (binding: HarnessBinding) => void | Promise<void>;\n\nexport interface AbaigramExtras {\n\t/** The program's root, where abaigram.yaml and the content live. Default: found from the cwd on first use, else the cwd. */\n\troot?: string;\n\tenv?: NodeJS.ProcessEnv;\n\t/** Injectable clock. */\n\tnow?: () => number;\n\t/** The in-process harness for turns mode; overrides the dynamic import of the harness package. */\n\tharness?: HarnessFactory;\n\t/** Where the audit log goes; default: the manifest's path. */\n\tauditPath?: string;\n\t/** For the exercise form: where its report goes at exit. Default: stderr. */\n\treport?: (text: string) => void;\n}\n\nexport class Abaigram {\n\treadonly manifest: Manifest;\n\treadonly mode: Mode;\n\treadonly modeFallback: boolean;\n\treadonly harnessSelection: HarnessSelection;\n\t/** A problem with the environment's harness selection, reported by doctor, never thrown. */\n\treadonly harnessSelectionError: string | undefined;\n\treadonly content: ContentSlots;\n\t/**\n\t * The sidecar endpoint, listening from startup when the selected mode is\n\t * sidecar and a real harness is wanted (section 6.3). A check run under\n\t * `ABAI_HARNESS` keeps its null harness in-process and opens no socket.\n\t */\n\treadonly endpoint: Endpoint | undefined;\n\t/** A launcher handed this program its connection (section 6.3): the full lifecycle is available to it. */\n\treadonly launched: boolean = false;\n\treadonly startedAt: string = new Date().toISOString();\n\t/** The root given at construction, if any; otherwise the root is found lazily. */\n\treadonly explicitRoot: string | undefined;\n\t/** @internal The region; tests and the binding reach it, programs do not. */\n\treadonly region: Region;\n\treadonly now: () => number;\n\n\tprivate readonly cellEntries = new Map<string, CellEntry>();\n\tprivate readonly eventEntries = new Map<string, EventEntry>();\n\tprivate readonly libraryEvents = new Map<string, number>();\n\tprivate readonly cellHandles = new Map<string, CellHandle>();\n\tprivate readonly eventHandles = new Map<string, EventHandle>();\n\tprivate readonly knobHandlers = new Map<string, KnobHandler>();\n\tprivate readonly capabilityHandlers = new Map<string, CapabilityHandler>();\n\tprivate readonly decisionIndex = new Map<string, number>();\n\tprivate readonly turnIndex = new Map<string, number>();\n\tprivate readonly queue: Array<() => void> = [];\n\tprivate harness: AttachedHarness | undefined;\n\tprivate binding: DirectBinding | undefined;\n\tprivate nullHarness: NullHarness | undefined;\n\tprivate lastAttachError: string | undefined;\n\tprivate readonly harnessFactory: HarnessFactory | undefined;\n\tprivate readonly auditPathOverride: string | undefined;\n\tprivate readonly report: (text: string) => void;\n\tprivate readonly env: NodeJS.ProcessEnv;\n\treadonly stopHandler: StopHandler | undefined;\n\t/** Who waits for a cooperative pause to lift, and the ref'd timer that keeps a paused program alive. */\n\tprivate resumeWaiters: Array<() => void> = [];\n\tprivate pauseKeepAlive: NodeJS.Timeout | undefined;\n\t/** Under launch: the launcher connected at least once, so nothing waits for it a second time. */\n\tprivate launcherSeen = false;\n\n\tconstructor(options: AbaigramOptions, extras: AbaigramExtras = {}) {\n\t\tthis.manifest = buildManifest(options);\n\t\tthis.now = extras.now ?? Date.now;\n\t\tconst env = extras.env ?? process.env;\n\t\tthis.env = env;\n\t\tconst selection = selectMode(this.manifest.modes, env);\n\t\tthis.mode = selection.mode;\n\t\tthis.modeFallback = selection.fallback;\n\t\tconst harness = selectHarness(env);\n\t\tthis.harnessSelection = harness.selection;\n\t\tthis.harnessSelectionError = harness.error;\n\t\tthis.stopHandler = options.lifecycle?.stop?.handler;\n\t\tthis.explicitRoot = extras.root;\n\t\tthis.harnessFactory = extras.harness;\n\t\tthis.auditPathOverride = extras.auditPath;\n\t\tthis.report =\n\t\t\textras.report ??\n\t\t\t((text) => {\n\t\t\t\tprocess.stderr.write(`${text}\\n`);\n\t\t\t});\n\n\t\tlet scalars = 0;\n\t\tlet sized = 0;\n\t\tconst pending: Array<[CellDecl, number, number, boolean]> = [];\n\t\tthis.manifest.cells.forEach((decl, ordinal) => {\n\t\t\tconst scalar = decl.type !== \"string\" && decl.type !== \"object\" && decl.type !== \"list\";\n\t\t\tpending.push([decl, ordinal, scalar ? scalars++ : sized++, scalar]);\n\t\t});\n\t\tthis.manifest.decisions.forEach((decl, i) => {\n\t\t\tthis.decisionIndex.set(decl.name, i);\n\t\t});\n\t\tthis.manifest.turns.forEach((decl, i) => {\n\t\t\tthis.turnIndex.set(decl.name, i);\n\t\t});\n\t\tthis.region = new Region({\n\t\t\tscalars,\n\t\t\tsized,\n\t\t\tcounters: this.manifest.decisions.length + this.manifest.turns.length + 1,\n\t\t});\n\t\tif (this.modeFallback) this.region.counters[this.region.counters.length - 1] += 1;\n\t\tfor (const [decl, ordinal, slot, scalar] of pending)\n\t\t\tthis.cellEntries.set(decl.name, this.makeEntry(decl, ordinal, slot, scalar));\n\n\t\tthis.manifest.events.forEach((decl, ordinal) => {\n\t\t\tconst fields = Object.entries(decl.payload).map(([key, field]) => {\n\t\t\t\tconst f = fieldOf(field);\n\t\t\t\treturn { key, type: f.type, max: f.max };\n\t\t\t});\n\t\t\tthis.eventEntries.set(decl.name, { decl, ordinal, fields });\n\t\t});\n\t\tLIBRARY_EVENTS.forEach((name, i) => {\n\t\t\tthis.libraryEvents.set(name, LIBRARY_EVENT_BASE - i);\n\t\t});\n\n\t\tfor (const [name, cell] of Object.entries(options.cells ?? {})) {\n\t\t\tif (cell.access === \"readwrite\") {\n\t\t\t\tthis.cellEntries.get(name)?.set(cell.default);\n\t\t\t\tif (cell.onChange) this.knobHandlers.set(name, cell.onChange);\n\t\t\t}\n\t\t}\n\t\tfor (const [name, capability] of Object.entries(options.capabilities ?? {})) {\n\t\t\tif (capability.handler) this.capabilityHandlers.set(name, capability.handler);\n\t\t}\n\t\t// the root is found on first use, so a program that never attaches never touches the filesystem\n\t\tthis.content = createContent(this.manifest, () => extras.root ?? findRoot(this.manifest.name) ?? process.cwd());\n\t\t// startup is one of the five places (section 4.3): a null harness attaches here\n\t\tif (this.harnessSelection === \"null\" || this.harnessSelection === \"exercise\")\n\t\t\tthis.attachNull(this.harnessSelection);\n\t\t// sidecar: the receiving end waits from startup (section 6.3); its failure to listen is a reason\n\t\t// the next attach reports, never a throw into the program\n\t\tconst launchSocket = env[ENV_LAUNCH_SOCKET]?.trim();\n\t\tif (this.mode === \"sidecar\" && this.harnessSelection === \"real\") {\n\t\t\t// launched: the parent chose the socket and is waiting on it. Read once and removed, so a program\n\t\t\t// that spawns a copy of itself never hands it this very socket\n\t\t\tthis.launched = launchSocket !== undefined && launchSocket !== \"\";\n\t\t\tif (this.launched && env === process.env) delete process.env[ENV_LAUNCH_SOCKET];\n\t\t\tthis.endpoint = new Endpoint(this, {\n\t\t\t\trunDir: this.launched ? dirname(launchSocket as string) : runDirFrom(env),\n\t\t\t\t...(this.launched ? { socketPath: launchSocket as string } : {}),\n\t\t\t});\n\t\t\tthis.endpoint.ready.catch((error: unknown) => {\n\t\t\t\tthis.lastAttachError = `the endpoint could not listen: ${error instanceof Error ? error.message : String(error)}`;\n\t\t\t});\n\t\t} else if (launchSocket !== undefined && launchSocket !== \"\") {\n\t\t\t// a launcher is waiting, but this program cannot take the connection up: it runs as itself, observed\n\t\t\t// from outside only (section 5.7), and says why when asked\n\t\t\tif (env === process.env) delete process.env[ENV_LAUNCH_SOCKET];\n\t\t\tthis.lastAttachError =\n\t\t\t\tthis.harnessSelection === \"real\"\n\t\t\t\t\t? `launched, but ${this.manifest.name} declares no sidecar mode (declared: ${this.manifest.modes.join(\", \")})`\n\t\t\t\t\t: `launched under ${ENV_HARNESS}=${this.harnessSelection}`;\n\t\t}\n\t}\n\n\tget name(): string {\n\t\treturn this.manifest.name;\n\t}\n\n\tget attached(): boolean {\n\t\treturn this.region.flags[FLAG_ATTACHED] !== 0;\n\t}\n\n\t/** Why the last attach did not happen, if it did not. */\n\tget attachError(): string | undefined {\n\t\treturn this.lastAttachError;\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Cells and knobs (section 5.2)\n\t// -----------------------------------------------------------------------\n\n\t/** The typed store and load of one cell, built once so the hot path is the store alone. */\n\tprivate makeEntry(decl: CellDecl, ordinal: number, slot: number, scalar: boolean): CellEntry {\n\t\tconst { values, versions, sized } = this.region;\n\t\tconst entry: CellEntry = { decl, ordinal, slot, scalar, set: () => {}, get: () => undefined };\n\t\tif (!scalar) {\n\t\t\tentry.set = (value) => {\n\t\t\t\tsized[slot] = fitValue(value, decl);\n\t\t\t\tversions[ordinal] += 1;\n\t\t\t};\n\t\t\tentry.get = () => sized[slot];\n\t\t\treturn entry;\n\t\t}\n\t\tswitch (decl.type) {\n\t\t\tcase \"bool\":\n\t\t\t\tentry.set = (value) => {\n\t\t\t\t\tvalues[slot] = value ? 1 : 0;\n\t\t\t\t\tversions[ordinal] += 1;\n\t\t\t\t};\n\t\t\t\tentry.get = () => values[slot] !== 0;\n\t\t\t\tbreak;\n\t\t\tcase \"enum\": {\n\t\t\t\tconst index = new Map((decl.enum ?? []).map((value, i) => [value, i]));\n\t\t\t\tconst names = decl.enum ?? [];\n\t\t\t\tentry.enumIndex = index;\n\t\t\t\tentry.set = (value) => {\n\t\t\t\t\tconst i = index.get(value as string);\n\t\t\t\t\tif (i === undefined) throw new Error(`${decl.name}: ${String(value)} is not a declared value`);\n\t\t\t\t\tvalues[slot] = i;\n\t\t\t\t\tversions[ordinal] += 1;\n\t\t\t\t};\n\t\t\t\tentry.get = () => names[values[slot]];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\tentry.set = (value) => {\n\t\t\t\t\tvalues[slot] = value as number;\n\t\t\t\t\tversions[ordinal] += 1;\n\t\t\t\t};\n\t\t\t\tentry.get = () => values[slot];\n\t\t}\n\t\treturn entry;\n\t}\n\n\tprivate entry(name: string): CellEntry {\n\t\tconst entry = this.cellEntries.get(name);\n\t\tif (!entry) throw new Error(`${this.name} declares no cell ${name}`);\n\t\treturn entry;\n\t}\n\n\t/** A handle, created once per cell and cached. */\n\tcell<T = unknown>(name: string): CellHandle<T> {\n\t\tconst cached = this.cellHandles.get(name);\n\t\tif (cached) return cached as CellHandle<T>;\n\t\tconst entry = this.entry(name);\n\t\tconst handle: CellHandle = { name, get: entry.get, set: entry.set };\n\t\tthis.cellHandles.set(name, handle);\n\t\treturn handle as CellHandle<T>;\n\t}\n\n\t/** A knob handle; the cell must be `readwrite`. */\n\tknob<T = unknown>(name: string): KnobHandle<T> {\n\t\tconst entry = this.entry(name);\n\t\tif (entry.decl.access !== \"readwrite\") throw new Error(`${name} is a read cell, not a knob`);\n\t\tconst handle = this.cell<T>(name) as KnobHandle<T>;\n\t\tif (handle.reset === undefined) {\n\t\t\thandle.reset = () => {\n\t\t\t\tentry.set(entry.decl.default);\n\t\t\t\tif (!entry.scalar) this.emitLibrary(\"abai.knob.reset\", { cell: name, value: entry.get() });\n\t\t\t};\n\t\t\thandle.onChange = (handler) => {\n\t\t\t\tif (entry.scalar) throw new Error(`${name} is a scalar knob; the program reads it, nothing is delivered`);\n\t\t\t\tthis.knobHandlers.set(name, handler);\n\t\t\t};\n\t\t}\n\t\treturn handle;\n\t}\n\n\t/** @internal The handler a sized knob delivers to, for the binding. */\n\tknobHandler(name: string): KnobHandler | undefined {\n\t\treturn this.knobHandlers.get(name);\n\t}\n\n\t/** @internal Every cell's current value, keyed by name, for the binding. */\n\treadCells(): Record<string, unknown> {\n\t\tconst cells: Record<string, unknown> = {};\n\t\tfor (const [name, entry] of this.cellEntries) cells[name] = entry.get();\n\t\treturn cells;\n\t}\n\n\t/** @internal A cell's version counter. */\n\tversion(name: string): number {\n\t\treturn this.region.versions[this.entry(name).ordinal];\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Lifecycle (section 5.5): what the program itself can do\n\t// -----------------------------------------------------------------------\n\n\t/** A cooperative pause is in effect. */\n\tget paused(): boolean {\n\t\treturn this.region.flags[FLAG_PAUSED] !== 0;\n\t}\n\n\t/**\n\t * @internal A cooperative pause: the flag is set, and the program is held\n\t * at its next touchpoint (this instantiation's deviation: a safepoint\n\t * cannot block the loop the resume arrives on). A ref'd timer keeps a\n\t * paused program alive, since nothing else of its own may be pending.\n\t */\n\trequestPause(): void {\n\t\tif (this.paused) return;\n\t\tthis.region.flags[FLAG_PAUSED] = 1;\n\t\tthis.region.flags[FLAG_WORK] = 1;\n\t\tthis.pauseKeepAlive = setInterval(() => {}, 2 ** 31 - 1);\n\t}\n\n\t/** @internal Lift the pause: whoever is held at a touchpoint goes on, their clocks starting now. */\n\tresumeFromPause(): void {\n\t\tif (!this.paused) return;\n\t\tthis.region.flags[FLAG_PAUSED] = 0;\n\t\tthis.region.flags[FLAG_WORK] = this.queue.length > 0 ? 1 : 0;\n\t\tif (this.pauseKeepAlive !== undefined) clearInterval(this.pauseKeepAlive);\n\t\tthis.pauseKeepAlive = undefined;\n\t\tfor (const waiter of this.resumeWaiters.splice(0)) waiter();\n\t}\n\n\t/** Hold here while a cooperative pause is in effect; the agent is told what the pause holds (4.3). */\n\tprivate awaitResume(touchpoint: string): Promise<void> {\n\t\tif (!this.paused) return Promise.resolve();\n\t\tthis.emitLibrary(\"abai.pause.blocked\", { touchpoint });\n\t\treturn new Promise<void>((resolve) => {\n\t\t\tthis.resumeWaiters.push(resolve);\n\t\t});\n\t}\n\n\t/** @internal What the stub knows of its own process, for `lifecycle status`. */\n\tlifecycleStatus(): {\n\t\tpid: number;\n\t\tname: string;\n\t\tmode: string;\n\t\tcwd: string;\n\t\tstartedAt: string;\n\t\tconnections: number;\n\t\tpaused: boolean;\n\t\tlaunched: boolean;\n\t} {\n\t\treturn {\n\t\t\tpid: process.pid,\n\t\t\tname: this.manifest.name,\n\t\t\tmode: this.mode,\n\t\t\tcwd: process.cwd(),\n\t\t\tstartedAt: this.startedAt,\n\t\t\tconnections: this.endpoint?.connectionCount ?? (this.attached ? 1 : 0),\n\t\t\tpaused: this.paused,\n\t\t\tlaunched: this.launched,\n\t\t};\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Events (section 5.1)\n\t// -----------------------------------------------------------------------\n\n\t/** A handle for a declared event, created once and cached; the name is checked here, never on the hot path. */\n\tevent(name: string): EventHandle {\n\t\tconst cached = this.eventHandles.get(name);\n\t\tif (cached) return cached;\n\t\tconst entry = this.eventEntries.get(name);\n\t\tif (!entry) throw new Error(`${this.name} declares no event ${name}`);\n\t\tconst flags = this.region.flags;\n\t\tconst handle: EventHandle = {\n\t\t\tname,\n\t\t\temit: (payload = {}) => {\n\t\t\t\tif (flags[FLAG_ATTACHED] === 0) return;\n\t\t\t\tthis.publish(entry, payload);\n\t\t\t},\n\t\t};\n\t\tthis.eventHandles.set(name, handle);\n\t\treturn handle;\n\t}\n\n\t/** Copy the declared fields, cut sized ones to their max, publish, and tell the harness. */\n\tprivate publish(entry: EventEntry, payload: Record<string, unknown>): void {\n\t\tlet truncated = false;\n\t\tconst copy: Record<string, unknown> = {};\n\t\tfor (const field of entry.fields) {\n\t\t\tconst value = payload[field.key];\n\t\t\tif (value === undefined) continue;\n\t\t\tswitch (field.type) {\n\t\t\t\tcase \"string\": {\n\t\t\t\t\tconst text = String(value);\n\t\t\t\t\tconst cut = cutUtf8(text, field.max ?? 256);\n\t\t\t\t\tif (cut !== text) truncated = true;\n\t\t\t\t\tcopy[field.key] = cut;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"object\":\n\t\t\t\tcase \"list\": {\n\t\t\t\t\tconst bytes = encodedBytes(value);\n\t\t\t\t\tif (bytes > (field.max ?? 1024)) {\n\t\t\t\t\t\ttruncated = true;\n\t\t\t\t\t\tcopy[field.key] = { truncated: true, bytes };\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcopy[field.key] = JSON.parse(JSON.stringify(value));\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tdefault:\n\t\t\t\t\tcopy[field.key] = value;\n\t\t\t}\n\t\t}\n\t\tconst seq = this.region.emit(entry.ordinal, copy, truncated, this.now());\n\t\tthis.harness?.emitted(seq);\n\t}\n\n\t/** @internal A library event under the reserved prefix. */\n\temitLibrary(name: string, payload: Record<string, unknown>): void {\n\t\tif (this.region.flags[FLAG_ATTACHED] === 0) return;\n\t\tconst ordinal = this.libraryEvents.get(name);\n\t\tif (ordinal === undefined) throw new Error(`${name} is not a library event`);\n\t\tconst seq = this.region.emit(ordinal, payload, false, this.now());\n\t\tthis.harness?.emitted(seq);\n\t}\n\n\t/** @internal The declared event for a ring slot's ordinal, or the library event's name. */\n\teventName(ordinal: number): string {\n\t\tif (ordinal < 0) return LIBRARY_EVENTS[LIBRARY_EVENT_BASE - ordinal] ?? `abai.unknown.${ordinal}`;\n\t\treturn this.manifest.events[ordinal]?.name ?? `unknown.${ordinal}`;\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Capabilities and safepoints (section 5.3)\n\t// -----------------------------------------------------------------------\n\n\t/** Register the handler of a declared capability (or replace one given at declaration). */\n\tcapability(name: string, handler: CapabilityHandler): void {\n\t\tif (!this.manifest.capabilities.some((c) => c.name === name)) {\n\t\t\tthrow new Error(`${this.name} declares no capability ${name}`);\n\t\t}\n\t\tthis.capabilityHandlers.set(name, handler);\n\t}\n\n\t/** @internal */\n\tcapabilityHandler(name: string): CapabilityHandler | undefined {\n\t\treturn this.capabilityHandlers.get(name);\n\t}\n\n\t/** @internal Queue work for the next safepoint; the binding uses it for safepoint dispatch. */\n\tenqueue(work: () => void): void {\n\t\tthis.queue.push(work);\n\t\tthis.region.flags[FLAG_QUEUE] = this.queue.length;\n\t\tthis.region.flags[FLAG_WORK] = 1;\n\t}\n\n\t/** One load of a flag when nothing is queued and no pause is in effect. */\n\tsafepoint(): void {\n\t\tif (this.region.flags[FLAG_WORK] === 0) return;\n\t\tthis.drain();\n\t}\n\n\t/** @internal Remove queued work that will not run (a timed-out dispatch). */\n\tdequeue(work: () => void): void {\n\t\tconst index = this.queue.indexOf(work);\n\t\tif (index === -1) return;\n\t\tthis.queue.splice(index, 1);\n\t\tconst flags = this.region.flags;\n\t\tflags[FLAG_QUEUE] = this.queue.length;\n\t\tif (this.queue.length === 0 && flags[FLAG_PAUSED] === 0) flags[FLAG_WORK] = 0;\n\t}\n\n\t/** @internal Run everything queued, now, on this thread: a touchpoint holds the program at a safepoint. */\n\tdrain(): void {\n\t\tconst flags = this.region.flags;\n\t\twhile (this.queue.length > 0) {\n\t\t\tconst work = this.queue.shift() as () => void;\n\t\t\tflags[FLAG_QUEUE] = this.queue.length;\n\t\t\ttry {\n\t\t\t\twork();\n\t\t\t} catch {\n\t\t\t\t// a handler's failure is reported through its reply, never through the program's safepoint\n\t\t\t}\n\t\t}\n\t\tflags[FLAG_WORK] = flags[FLAG_PAUSED] !== 0 ? 1 : 0;\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Decisions and turns (sections 5.4, 4.3)\n\t// -----------------------------------------------------------------------\n\n\tprivate applyDefault(decl: DecisionDecl, cause: string): unknown {\n\t\tif (decl.default === \"abort\") throw new AbaigramAbort(decl.name, cause);\n\t\treturn decl.default;\n\t}\n\n\t/** Ask which way to go. With no harness attached the default applies at once and is counted. */\n\tasync decide<T = unknown>(name: string, context: Record<string, unknown> = {}): Promise<T> {\n\t\tconst index = this.decisionIndex.get(name);\n\t\tif (index === undefined) throw new Error(`${this.name} declares no decision ${name}`);\n\t\tconst decl = this.manifest.decisions[index];\n\t\tconst harness = this.harness;\n\t\tif (this.region.flags[FLAG_ATTACHED] === 0 || harness === undefined) {\n\t\t\tthis.region.counters[index] += 1;\n\t\t\treturn this.applyDefault(decl, \"no_harness\") as T;\n\t\t}\n\t\t// a cooperative pause holds the decision here; its own clock starts when the pause lifts (4.3)\n\t\tif (this.paused) await this.awaitResume(name);\n\t\tif (this.region.flags[FLAG_ATTACHED] === 0 || this.harness === undefined) {\n\t\t\tthis.region.counters[index] += 1;\n\t\t\treturn this.applyDefault(decl, \"no_harness\") as T;\n\t\t}\n\t\tthis.drain();\n\t\ttry {\n\t\t\treturn (await this.harness.decide(decl, context, this.now() + durationMs(decl.timeout))) as T;\n\t\t} catch (error) {\n\t\t\treturn this.applyDefault(decl, error instanceof Error ? error.message : String(error)) as T;\n\t\t}\n\t}\n\n\t/** Give the agent a turn. With no harness attached it returns at once and is counted. */\n\tasync turn(name: string): Promise<void> {\n\t\tconst index = this.turnIndex.get(name);\n\t\tif (index === undefined) throw new Error(`${this.name} declares no turn ${name}`);\n\t\tconst decl = this.manifest.turns[index];\n\t\tconst harness = this.harness;\n\t\tif (this.region.flags[FLAG_ATTACHED] === 0 || harness === undefined) {\n\t\t\tthis.region.counters[this.manifest.decisions.length + index] += 1;\n\t\t\treturn;\n\t\t}\n\t\tif (this.paused) await this.awaitResume(name);\n\t\tif (this.region.flags[FLAG_ATTACHED] === 0 || this.harness === undefined) {\n\t\t\tthis.region.counters[this.manifest.decisions.length + index] += 1;\n\t\t\treturn;\n\t\t}\n\t\tthis.drain();\n\t\ttry {\n\t\t\tawait this.harness.turn(decl, this.now() + durationMs(decl.timeout));\n\t\t} catch {\n\t\t\t// a turn that fails is a turn that ended\n\t\t}\n\t\tthis.drain();\n\t}\n\n\t/** The counters, by kind and name: defaulted decisions, skipped turns, and the mode fallback. */\n\tcounters(): CounterSnapshot {\n\t\tconst snapshot: CounterSnapshot = {};\n\t\tthis.manifest.decisions.forEach((decl, i) => {\n\t\t\tsnapshot[`decision:${decl.name}`] = this.region.counters[i];\n\t\t});\n\t\tthis.manifest.turns.forEach((decl, i) => {\n\t\t\tsnapshot[`turn:${decl.name}`] = this.region.counters[this.manifest.decisions.length + i];\n\t\t});\n\t\tsnapshot[\"abai.mode_fallback\"] = this.region.counters[this.region.counters.length - 1];\n\t\treturn snapshot;\n\t}\n\n\t/** @internal Read and reset the counters, for the harness that attaches. */\n\ttakeCounters(): CounterSnapshot {\n\t\tconst snapshot = this.counters();\n\t\tthis.region.counters.fill(0);\n\t\treturn snapshot;\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Attaching (section 4.3)\n\t// -----------------------------------------------------------------------\n\n\t/** @internal The binding attaches a harness. */\n\tsetHarness(harness: AttachedHarness): void {\n\t\tthis.harness = harness;\n\t\tthis.region.flags[FLAG_ATTACHED] = 1;\n\t\tthis.lastAttachError = undefined;\n\t}\n\n\t/** @internal The binding detaches it; a decision in flight takes its default with `reason`. */\n\tclearHarness(reason: string): void {\n\t\tconst harness = this.harness;\n\t\tthis.harness = undefined;\n\t\tthis.binding = undefined;\n\t\tthis.nullHarness = undefined;\n\t\tthis.region.flags[FLAG_ATTACHED] = 0;\n\t\tthis.lastAttachError = reason;\n\t\t// a pause is the attached harness's: when the harness goes the program runs as itself again (6.3)\n\t\tthis.resumeFromPause();\n\t\tharness?.detach(reason);\n\t}\n\n\t/** The direct binding, while an in-process harness is attached. */\n\tget directBinding(): HarnessBinding | undefined {\n\t\treturn this.binding;\n\t}\n\n\t/** The null harness, while one is attached. */\n\tget attachedNullHarness(): NullHarness | undefined {\n\t\treturn this.nullHarness;\n\t}\n\n\tprivate createBinding(connection?: string): DirectBinding {\n\t\tconst binding = new DirectBinding(this, {\n\t\t\t...(this.auditPathOverride === undefined ? {} : { auditPath: this.auditPathOverride }),\n\t\t\t...(connection === undefined ? {} : { connection }),\n\t\t});\n\t\tthis.binding = binding;\n\t\tthis.setHarness(binding);\n\t\tbinding.flushCounters();\n\t\treturn binding;\n\t}\n\n\t/**\n\t * @internal A front end of the library's own (the sidecar endpoint)\n\t * attaches the program through a binding it then drives; the connection's\n\t * id labels its acts in the audit. Refused while something else is\n\t * attached: a second harness would take the program over silently.\n\t */\n\tbind(connection: string): DirectBinding {\n\t\tif (this.attached) {\n\t\t\tthrow new Error(`${this.name} already has a harness attached; this connection cannot take it over`);\n\t\t}\n\t\tif (this.launched) this.launcherSeen = true;\n\t\treturn this.createBinding(connection);\n\t}\n\n\tprivate attachNull(form: \"null\" | \"exercise\"): void {\n\t\tconst binding = this.createBinding();\n\t\tthis.nullHarness = attachNullHarness(binding, form);\n\t\tif (form === \"exercise\") {\n\t\t\tconst harness = this.nullHarness;\n\t\t\tprocess.once(\"exit\", () => {\n\t\t\t\tif (this.nullHarness === harness) this.report(JSON.stringify(harness.report()));\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Connect or spawn a harness (one of the five places). Resolves true when\n\t * attached. The real harness arrives through the `harness` extra, or the\n\t * harness package's dynamic import once it exists; until then the reason\n\t * is recorded.\n\t */\n\tasync attach(): Promise<boolean> {\n\t\tif (this.attached) return true;\n\t\tswitch (this.harnessSelection) {\n\t\t\tcase \"off\":\n\t\t\t\tthis.lastAttachError = `${ENV_HARNESS}=off`;\n\t\t\t\treturn false;\n\t\t\tcase \"null\":\n\t\t\tcase \"exercise\":\n\t\t\t\tthis.attachNull(this.harnessSelection);\n\t\t\t\treturn true;\n\t\t\tdefault:\n\t\t\t\tif (this.harnessSelectionError !== undefined) {\n\t\t\t\t\tthis.lastAttachError = this.harnessSelectionError;\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tif (this.endpoint) {\n\t\t\t\t\t// launched: the parent is already connecting; the program never spawns anything itself\n\t\t\t\t\treturn this.launched ? this.awaitLauncher(this.endpoint) : this.attachSidecar(this.endpoint);\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tconst factory =\n\t\t\t\t\t\tthis.harnessFactory ??\n\t\t\t\t\t\t(await installedHarness(\n\t\t\t\t\t\t\tthis.env[ENV_HARNESS_MODULE] || this.manifest.harness?.path || \"@abaigram/abai-embedded-harness\",\n\t\t\t\t\t\t));\n\t\t\t\t\tif (factory === undefined) {\n\t\t\t\t\t\tthis.lastAttachError =\n\t\t\t\t\t\t\t\"no harness is installed (the @abaigram/abai-embedded-harness package is not resolvable)\";\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\tconst binding = this.createBinding();\n\t\t\t\t\tawait factory(binding);\n\t\t\t\t\treturn this.attached;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst reason = error instanceof Error ? error.message : String(error);\n\t\t\t\t\tthis.binding?.detach(reason);\n\t\t\t\t\tthis.lastAttachError = reason;\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t}\n\t}\n\n\t/** Under launch: the launcher connects to the socket it chose; the program waits for it once, bounded. */\n\tprivate async awaitLauncher(endpoint: Endpoint): Promise<boolean> {\n\t\ttry {\n\t\t\tawait endpoint.ready;\n\t\t} catch (error) {\n\t\t\tthis.lastAttachError = `the endpoint could not listen: ${error instanceof Error ? error.message : String(error)}`;\n\t\t\treturn false;\n\t\t}\n\t\tif (this.attached) return true;\n\t\tif (this.launcherSeen) {\n\t\t\t// it was here and went: a later attach place returns at once, as 4.3 says of every touchpoint after a detach\n\t\t\tthis.lastAttachError = this.lastAttachError ?? \"the launcher disconnected\";\n\t\t\treturn false;\n\t\t}\n\t\tconst waitMs = attachWaitMsFrom(this.env);\n\t\tif (await endpoint.waitForConnection(waitMs)) {\n\t\t\tthis.launcherSeen = true;\n\t\t\treturn true;\n\t\t}\n\t\tthis.lastAttachError = `launched, but the launcher did not connect within ${waitMs} ms`;\n\t\treturn false;\n\t}\n\n\t/**\n\t * Sidecar attach (section 6.3): a harness already connected to the\n\t * endpoint means attached; otherwise the harness binary is spawned with\n\t * the terminal inherited and given `ABAI_ATTACH_WAIT_MS` to connect. A\n\t * child that exits first fails the attach at once with its code, so an\n\t * unconfigured machine costs well under a second (section 4.3); a child\n\t * that never connects is ended at the wait and the attach fails with the\n\t * reason. The child is unref'd: a program whose work is done exits, and\n\t * the closing socket tells the harness.\n\t */\n\tprivate async attachSidecar(endpoint: Endpoint): Promise<boolean> {\n\t\ttry {\n\t\t\tawait endpoint.ready;\n\t\t} catch {\n\t\t\t// spawnHarness reports it\n\t\t}\n\t\t// a harness that connected while the endpoint came up, or at any time before: attached already\n\t\tif (this.attached) return true;\n\t\tconst spawned = await this.spawnHarness(endpoint, \"attach\");\n\t\treturn spawned !== undefined;\n\t}\n\n\t/**\n\t * Spawn the harness binary with a verb against this program's endpoint\n\t * and wait for it to connect. Resolves to the child once attached, or to\n\t * undefined with the reason in `attachError`: the endpoint could not\n\t * listen, the child exited first (its code), it never connected within\n\t * the wait (it is ended), or it could not be started at all.\n\t */\n\tprivate async spawnHarness(endpoint: Endpoint, verb: \"attach\" | \"mcp\"): Promise<ChildProcess | undefined> {\n\t\ttry {\n\t\t\tawait endpoint.ready;\n\t\t} catch (error) {\n\t\t\tthis.lastAttachError = `the endpoint could not listen: ${error instanceof Error ? error.message : String(error)}`;\n\t\t\treturn undefined;\n\t\t}\n\t\tconst waitMs = attachWaitMsFrom(this.env);\n\t\tconst binary = harnessBinary(this.env, this.content.root);\n\t\tconst args = [...binary.args, verb, \"--target\", endpoint.socketPath, \"--run-dir\", endpoint.runDir];\n\t\tlet child: ChildProcess;\n\t\ttry {\n\t\t\tchild = spawn(binary.command, args, { stdio: \"inherit\", env: { ...process.env, ...this.env } });\n\t\t} catch (error) {\n\t\t\tthis.lastAttachError = `the harness binary could not be started: ${error instanceof Error ? error.message : String(error)}`;\n\t\t\treturn undefined;\n\t\t}\n\t\tchild.unref();\n\t\t// a ChildProcess with no error listener throws into the program; one stays for the child's whole life\n\t\tchild.on(\"error\", () => {});\n\t\tconst outcome = await new Promise<string>((resolve) => {\n\t\t\tlet settled = false;\n\t\t\tconst settle = (result: string): void => {\n\t\t\t\tif (settled) return;\n\t\t\t\tsettled = true;\n\t\t\t\tchild.off(\"exit\", onExit);\n\t\t\t\tchild.off(\"error\", onError);\n\t\t\t\tresolve(result);\n\t\t\t};\n\t\t\tconst onExit = (code: number | null, signal: NodeJS.Signals | null): void =>\n\t\t\t\tsettle(`exited:${code === null ? `signal ${signal ?? \"unknown\"}` : String(code)}`);\n\t\t\tconst onError = (error: NodeJS.ErrnoException): void => settle(`error:${error.code ?? error.message}`);\n\t\t\tchild.once(\"exit\", onExit);\n\t\t\tchild.once(\"error\", onError);\n\t\t\tvoid endpoint.waitForConnection(waitMs).then((connected) => settle(connected ? \"connected\" : \"timeout\"));\n\t\t});\n\t\tif (outcome === \"connected\") return child;\n\t\tif (outcome === \"timeout\") {\n\t\t\t// the one process this program started, by its own handle: nothing else is touched\n\t\t\tchild.kill();\n\t\t\tthis.lastAttachError = `the harness binary did not connect within ${waitMs} ms (${binary.command})`;\n\t\t\treturn undefined;\n\t\t}\n\t\tif (outcome.startsWith(\"exited:\")) {\n\t\t\tthis.lastAttachError = `the harness binary exited with ${outcome.slice(\"exited:\".length)} before connecting`;\n\t\t\treturn undefined;\n\t\t}\n\t\tthis.lastAttachError = `the harness binary could not be started: ${outcome.slice(\"error:\".length)} (${binary.command})`;\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * @internal `<prog> abai mcp` under sidecar: the binary's MCP server is\n\t * spawned against this program's endpoint with the terminal inherited, so\n\t * the MCP client on this process's stdin and stdout talks to it, and the\n\t * program waits at its entry, a safepoint it holds open, until the client\n\t * goes. Resolves to the child's exit code; -1 when nothing could be\n\t * spawned (the reason is in `attachError`).\n\t */\n\tasync serveMcpSidecar(endpoint: Endpoint): Promise<number> {\n\t\tif (this.attached) {\n\t\t\tthis.lastAttachError = `${this.name} already has a harness attached`;\n\t\t\treturn -1;\n\t\t}\n\t\tconst child = await this.spawnHarness(endpoint, \"mcp\");\n\t\tif (child === undefined) return -1;\n\t\t// the program's whole purpose now is to wait for its server: the child holds the event loop open,\n\t\t// where the spawn left it unref'd for the attach case, whose touchpoint holds the loop itself\n\t\tchild.ref();\n\t\t// the MCP client spawned this program and ends it with a signal; the server behind it must go too\n\t\tconst forward = (signal: NodeJS.Signals): void => {\n\t\t\tif (child.exitCode === null && child.signalCode === null) child.kill(signal);\n\t\t};\n\t\tconst forwarded: NodeJS.Signals[] = [\"SIGTERM\", \"SIGINT\", \"SIGHUP\"];\n\t\tfor (const signal of forwarded) process.on(signal, forward);\n\t\tconst binding = this.binding;\n\t\tbinding?.enterSafepoint();\n\t\ttry {\n\t\t\tif (child.exitCode !== null) return child.exitCode;\n\t\t\treturn await new Promise<number>((resolve) => {\n\t\t\t\tchild.once(\"exit\", (code) => resolve(code ?? 1));\n\t\t\t});\n\t\t} finally {\n\t\t\tfor (const signal of forwarded) process.off(signal, forward);\n\t\t\tbinding?.leaveSafepoint();\n\t\t}\n\t}\n\n\tprivate async touchpoint(kind: TouchpointKind): Promise<void> {\n\t\tif (!(await this.attach())) return;\n\t\tif (this.paused) await this.awaitResume(kind);\n\t\tconst binding = this.binding;\n\t\tif (!binding) return;\n\t\tthis.drain();\n\t\tawait binding.touchpoint(kind);\n\t\tthis.drain();\n\t}\n\n\t/** Run the install touchpoint; returns when the harness finishes, or at once when none can be attached. */\n\tinstall(): Promise<void> {\n\t\treturn this.touchpoint(\"install\");\n\t}\n\n\t/** Open a session; returns when the harness ends it, or at once when none can be attached. */\n\tsession(): Promise<void> {\n\t\treturn this.touchpoint(\"session\");\n\t}\n}\n\n/** Overrides where the in-process harness is imported from (a path or a package name). */\nexport const ENV_HARNESS_MODULE = \"ABAI_HARNESS_MODULE\";\n\n/**\n * The harness binary to spawn under sidecar: `ABAI_HARNESS_BIN` (a script\n * path runs under this very node), else the program's own\n * `node_modules/.bin/abai-embedded-harness`, else the name on PATH.\n */\nexport function harnessBinary(env: NodeJS.ProcessEnv, root: string): { command: string; args: string[] } {\n\tconst explicit = env[ENV_HARNESS_BIN]?.trim();\n\tif (explicit) {\n\t\treturn /\\.(?:[mc]?js|ts)$/.test(explicit)\n\t\t\t? { command: process.execPath, args: [explicit] }\n\t\t\t: { command: explicit, args: [] };\n\t}\n\tconst local = join(root, \"node_modules\", \".bin\", \"abai-embedded-harness\");\n\tif (existsSync(local)) return { command: local, args: [] };\n\treturn { command: \"abai-embedded-harness\", args: [] };\n}\n\n/** What the stub uses of the installed harness package. */\nexport interface HarnessModule {\n\tattachEmbedded?: (binding: HarnessBinding) => Promise<unknown>;\n\t/** `<prog> abai mcp` in-process: serve this binding to the MCP client on the process's stdio; resolves to the exit code. */\n\tserveMcpEmbedded?: (binding: HarnessBinding) => Promise<number>;\n\trunConfig?: (\n\t\targs: string[],\n\t\tio: { out(text: string): void; err(text: string): void; env: NodeJS.ProcessEnv },\n\t) => Promise<number>;\n\tdoctorOnline?: (\n\t\tmanifest: Manifest,\n\t\tenv: NodeJS.ProcessEnv,\n\t) => Promise<Array<{ name: string; status: \"ok\" | \"fail\" | \"skip\"; detail: string }>>;\n}\n\n/** The harness package, found by dynamic import when a program installed it; undefined when it does not resolve. */\nexport async function importHarnessModule(\n\tenv: NodeJS.ProcessEnv,\n\tmanifest: Manifest,\n): Promise<HarnessModule | undefined> {\n\tconst specifier = env[ENV_HARNESS_MODULE] || manifest.harness?.path || \"@abaigram/abai-embedded-harness\";\n\ttry {\n\t\treturn (await import(specifier)) as HarnessModule;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\n/** The harness package's in-process entry. */\nasync function installedHarness(specifier: string): Promise<HarnessFactory | undefined> {\n\tlet module: HarnessModule;\n\ttry {\n\t\tmodule = (await import(specifier)) as HarnessModule;\n\t} catch {\n\t\treturn undefined;\n\t}\n\tif (typeof module.attachEmbedded !== \"function\") return undefined;\n\tconst attach = module.attachEmbedded;\n\treturn async (binding) => {\n\t\tawait attach(binding);\n\t};\n}\n\n/** The program's one call: declarations in, the abaigram out. Throws when a declaration does not validate. */\nexport function createAbaigram(options: AbaigramOptions, extras: AbaigramExtras = {}): Abaigram {\n\treturn new Abaigram(options, extras);\n}\n"]}
1
+ {"version":3,"file":"program.d.ts","sourceRoot":"","sources":["../src/program.ts"],"names":[],"mappings":"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","sourcesContent":["// createAbaigram: the program-facing API of the stub (abaigrammar sections 4\n// and 5). The program declares its manifest in code, obtains cell, knob and\n// event handles once, and then writes cells, emits events, serves\n// capabilities and calls touchpoints. With no harness attached, every\n// operation here costs what section 11.1 says: cell writes store, emits and\n// safepoints load one flag, decisions and turns load the flag and count.\n//\n// Touchpoints are awaited promises (see the instantiation's deviations in\n// registry.ts). The attached paths arrive with the harness binding; this\n// file carries the detached behaviour and the seams the binding fills.\nimport { type ChildProcess, spawn } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fitValue } from \"./cells/fit.ts\";\nimport { type ContentSlots, createContent, findRoot } from \"./content.ts\";\nimport { Endpoint } from \"./endpoint.ts\";\nimport {\n\tattachWaitMsFrom,\n\tENV_HARNESS,\n\tENV_HARNESS_BIN,\n\tENV_LAUNCH_SOCKET,\n\ttype HarnessSelection,\n\trunDirFrom,\n\tselectHarness,\n\tselectMode,\n} from \"./env.ts\";\nimport { DirectBinding, type HarnessBinding, type TouchpointKind } from \"./harness-binding.ts\";\nimport {\n\ttype CellDecl,\n\tcutUtf8,\n\ttype DecisionDecl,\n\tdurationMs,\n\ttype EventDecl,\n\tencodedBytes,\n\tfieldOf,\n\tLIBRARY_EVENTS,\n\ttype Manifest,\n\ttype Mode,\n\ttype TurnDecl,\n} from \"./manifest/manifest.ts\";\nimport { attachNullHarness, type NullHarness } from \"./null-harness.ts\";\nimport { FLAG_ATTACHED, FLAG_PAUSED, FLAG_QUEUE, FLAG_WORK, LIBRARY_EVENT_BASE, Region } from \"./region.ts\";\nimport {\n\ttype AbaigramOptions,\n\tbuildManifest,\n\ttype CapabilityHandler,\n\ttype KnobHandler,\n\ttype StopHandler,\n} from \"./registry.ts\";\n\n/** Thrown by `decide` when the applied default is `abort` (section 5.4). */\nexport class AbaigramAbort extends Error {\n\treadonly decision: string;\n\tconstructor(decision: string, cause: string) {\n\t\tsuper(`decision ${decision} applied its default, abort (${cause})`);\n\t\tthis.name = \"AbaigramAbort\";\n\t\tthis.decision = decision;\n\t}\n}\n\nexport interface CellHandle<T = unknown> {\n\treadonly name: string;\n\tget(): T;\n\t/** One store to the value and one to the version. Enum values must be declared; nothing else is checked. */\n\tset(value: T): void;\n}\n\nexport interface KnobHandle<T = unknown> extends CellHandle<T> {\n\t/** Back to the declared default; a sized knob's reset reaches the harness as `abai.knob.reset`. */\n\treset(): void;\n\t/** Sized knobs only: the handler that receives a delivered value at a safepoint. */\n\tonChange(handler: KnobHandler): void;\n}\n\nexport interface EventHandle {\n\treadonly name: string;\n\t/** One load of the attached flag when no harness is attached. */\n\temit(payload?: Record<string, unknown>): void;\n}\n\nexport interface CounterSnapshot {\n\t[name: string]: number;\n}\n\n/** What a harness binding supplies once attached; undefined while detached. */\nexport interface AttachedHarness {\n\t/** Ask the harness; resolves to the answer, or rejects with the cause of a default. */\n\tdecide(decision: DecisionDecl, context: Record<string, unknown>, deadlineMs: number): Promise<unknown>;\n\t/** Give the harness a turn; resolves when it is done or the timeout passes. */\n\tturn(turn: TurnDecl, deadlineMs: number): Promise<void>;\n\t/** An event was published; `seq` is its sequence number. */\n\temitted(seq: number): void;\n\t/** The program detaches it. */\n\tdetach(reason: string): void;\n}\n\ninterface CellEntry {\n\tdecl: CellDecl;\n\t/** Position in `manifest.cells`: the index into `versions`. */\n\tordinal: number;\n\t/** Index into `values` (scalar) or `sized`. */\n\tslot: number;\n\tscalar: boolean;\n\tenumIndex?: Map<string, number>;\n\t/** Built once per cell: the typed store and load (section 11.2 rows). */\n\tset: (value: unknown) => void;\n\tget: () => unknown;\n}\n\ninterface EventEntry {\n\tdecl: EventDecl;\n\tordinal: number;\n\tfields: Array<{ key: string; type: string; max: number | undefined }>;\n}\n\n/** Attaches an in-process harness to the binding the stub hands it. */\nexport type HarnessFactory = (binding: HarnessBinding) => void | Promise<void>;\n\nexport interface AbaigramExtras {\n\t/** The program's root, where abaigram.yaml and the content live. Default: found from the cwd on first use, else the cwd. */\n\troot?: string;\n\tenv?: NodeJS.ProcessEnv;\n\t/** Injectable clock. */\n\tnow?: () => number;\n\t/** The in-process harness for turns mode; overrides the dynamic import of the harness package. */\n\tharness?: HarnessFactory;\n\t/** Where the audit log goes; default: the manifest's path. */\n\tauditPath?: string;\n\t/** For the exercise form: where its report goes at exit. Default: stderr. */\n\treport?: (text: string) => void;\n}\n\nexport class Abaigram {\n\treadonly manifest: Manifest;\n\treadonly mode: Mode;\n\treadonly modeFallback: boolean;\n\treadonly harnessSelection: HarnessSelection;\n\t/** A problem with the environment's harness selection, reported by doctor, never thrown. */\n\treadonly harnessSelectionError: string | undefined;\n\treadonly content: ContentSlots;\n\t/**\n\t * The sidecar endpoint, listening from startup when the selected mode is\n\t * sidecar and a real harness is wanted (section 6.3). A check run under\n\t * `ABAI_HARNESS` keeps its null harness in-process and opens no socket.\n\t */\n\treadonly endpoint: Endpoint | undefined;\n\t/** A launcher handed this program its connection (section 6.3): the full lifecycle is available to it. */\n\treadonly launched: boolean = false;\n\treadonly startedAt: string = new Date().toISOString();\n\t/** The root given at construction, if any; otherwise the root is found lazily. */\n\treadonly explicitRoot: string | undefined;\n\t/** @internal The region; tests and the binding reach it, programs do not. */\n\treadonly region: Region;\n\treadonly now: () => number;\n\n\tprivate readonly cellEntries = new Map<string, CellEntry>();\n\tprivate readonly eventEntries = new Map<string, EventEntry>();\n\tprivate readonly libraryEvents = new Map<string, number>();\n\tprivate readonly cellHandles = new Map<string, CellHandle>();\n\tprivate readonly eventHandles = new Map<string, EventHandle>();\n\tprivate readonly knobHandlers = new Map<string, KnobHandler>();\n\tprivate readonly capabilityHandlers = new Map<string, CapabilityHandler>();\n\tprivate readonly decisionIndex = new Map<string, number>();\n\tprivate readonly turnIndex = new Map<string, number>();\n\tprivate readonly queue: Array<() => void> = [];\n\tprivate harness: AttachedHarness | undefined;\n\tprivate binding: DirectBinding | undefined;\n\tprivate nullHarness: NullHarness | undefined;\n\tprivate lastAttachError: string | undefined;\n\tprivate readonly harnessFactory: HarnessFactory | undefined;\n\tprivate readonly auditPathOverride: string | undefined;\n\tprivate readonly report: (text: string) => void;\n\tprivate readonly env: NodeJS.ProcessEnv;\n\treadonly stopHandler: StopHandler | undefined;\n\t/** Who waits for a cooperative pause to lift, and the ref'd timer that keeps a paused program alive. */\n\tprivate resumeWaiters: Array<() => void> = [];\n\tprivate pauseKeepAlive: NodeJS.Timeout | undefined;\n\t/** Under launch: the launcher connected at least once, so nothing waits for it a second time. */\n\tprivate launcherSeen = false;\n\n\tconstructor(options: AbaigramOptions, extras: AbaigramExtras = {}) {\n\t\tthis.manifest = buildManifest(options);\n\t\tthis.now = extras.now ?? Date.now;\n\t\tconst env = extras.env ?? process.env;\n\t\tthis.env = env;\n\t\tconst selection = selectMode(this.manifest.modes, env);\n\t\tthis.mode = selection.mode;\n\t\tthis.modeFallback = selection.fallback;\n\t\tconst harness = selectHarness(env);\n\t\tthis.harnessSelection = harness.selection;\n\t\tthis.harnessSelectionError = harness.error;\n\t\tthis.stopHandler = options.lifecycle?.stop?.handler;\n\t\tthis.explicitRoot = extras.root;\n\t\tthis.harnessFactory = extras.harness;\n\t\tthis.auditPathOverride = extras.auditPath;\n\t\tthis.report =\n\t\t\textras.report ??\n\t\t\t((text) => {\n\t\t\t\tprocess.stderr.write(`${text}\\n`);\n\t\t\t});\n\n\t\tlet scalars = 0;\n\t\tlet sized = 0;\n\t\tconst pending: Array<[CellDecl, number, number, boolean]> = [];\n\t\tthis.manifest.cells.forEach((decl, ordinal) => {\n\t\t\tconst scalar = decl.type !== \"string\" && decl.type !== \"object\" && decl.type !== \"list\";\n\t\t\tpending.push([decl, ordinal, scalar ? scalars++ : sized++, scalar]);\n\t\t});\n\t\tthis.manifest.decisions.forEach((decl, i) => {\n\t\t\tthis.decisionIndex.set(decl.name, i);\n\t\t});\n\t\tthis.manifest.turns.forEach((decl, i) => {\n\t\t\tthis.turnIndex.set(decl.name, i);\n\t\t});\n\t\tthis.region = new Region({\n\t\t\tscalars,\n\t\t\tsized,\n\t\t\tcounters: this.manifest.decisions.length + this.manifest.turns.length + 1,\n\t\t});\n\t\tif (this.modeFallback) this.region.counters[this.region.counters.length - 1] += 1;\n\t\tfor (const [decl, ordinal, slot, scalar] of pending)\n\t\t\tthis.cellEntries.set(decl.name, this.makeEntry(decl, ordinal, slot, scalar));\n\n\t\tthis.manifest.events.forEach((decl, ordinal) => {\n\t\t\tconst fields = Object.entries(decl.payload).map(([key, field]) => {\n\t\t\t\tconst f = fieldOf(field);\n\t\t\t\treturn { key, type: f.type, max: f.max };\n\t\t\t});\n\t\t\tthis.eventEntries.set(decl.name, { decl, ordinal, fields });\n\t\t});\n\t\tLIBRARY_EVENTS.forEach((name, i) => {\n\t\t\tthis.libraryEvents.set(name, LIBRARY_EVENT_BASE - i);\n\t\t});\n\n\t\tfor (const [name, cell] of Object.entries(options.cells ?? {})) {\n\t\t\tif (cell.access === \"readwrite\") {\n\t\t\t\tthis.cellEntries.get(name)?.set(cell.default);\n\t\t\t\tif (cell.onChange) this.knobHandlers.set(name, cell.onChange);\n\t\t\t}\n\t\t}\n\t\tfor (const [name, capability] of Object.entries(options.capabilities ?? {})) {\n\t\t\tif (capability.handler) this.capabilityHandlers.set(name, capability.handler);\n\t\t}\n\t\t// the root is found on first use, so a program that never attaches never touches the filesystem\n\t\tthis.content = createContent(this.manifest, () => extras.root ?? findRoot(this.manifest.name) ?? process.cwd());\n\t\t// startup is one of the five places (section 4.3): a null harness attaches here\n\t\tif (this.harnessSelection === \"null\" || this.harnessSelection === \"exercise\")\n\t\t\tthis.attachNull(this.harnessSelection);\n\t\t// sidecar: the receiving end waits from startup (section 6.3); its failure to listen is a reason\n\t\t// the next attach reports, never a throw into the program\n\t\tconst launchSocket = env[ENV_LAUNCH_SOCKET]?.trim();\n\t\tif (this.mode === \"sidecar\" && this.harnessSelection === \"real\") {\n\t\t\t// launched: the parent chose the socket and is waiting on it. Read once and removed, so a program\n\t\t\t// that spawns a copy of itself never hands it this very socket\n\t\t\tthis.launched = launchSocket !== undefined && launchSocket !== \"\";\n\t\t\tif (this.launched && env === process.env) delete process.env[ENV_LAUNCH_SOCKET];\n\t\t\tthis.endpoint = new Endpoint(this, {\n\t\t\t\trunDir: this.launched ? dirname(launchSocket as string) : runDirFrom(env),\n\t\t\t\t...(this.launched ? { socketPath: launchSocket as string } : {}),\n\t\t\t});\n\t\t\tthis.endpoint.ready.catch((error: unknown) => {\n\t\t\t\tthis.lastAttachError = `the endpoint could not listen: ${error instanceof Error ? error.message : String(error)}`;\n\t\t\t});\n\t\t} else if (launchSocket !== undefined && launchSocket !== \"\") {\n\t\t\t// a launcher is waiting, but this program cannot take the connection up: it runs as itself, observed\n\t\t\t// from outside only (section 5.7), and says why when asked\n\t\t\tif (env === process.env) delete process.env[ENV_LAUNCH_SOCKET];\n\t\t\tthis.lastAttachError =\n\t\t\t\tthis.harnessSelection === \"real\"\n\t\t\t\t\t? `launched, but ${this.manifest.name} declares no sidecar mode (declared: ${this.manifest.modes.join(\", \")})`\n\t\t\t\t\t: `launched under ${ENV_HARNESS}=${this.harnessSelection}`;\n\t\t}\n\t}\n\n\tget name(): string {\n\t\treturn this.manifest.name;\n\t}\n\n\tget attached(): boolean {\n\t\treturn this.region.flags[FLAG_ATTACHED] !== 0;\n\t}\n\n\t/** Why the last attach did not happen, if it did not. */\n\tget attachError(): string | undefined {\n\t\treturn this.lastAttachError;\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Cells and knobs (section 5.2)\n\t// -----------------------------------------------------------------------\n\n\t/** The typed store and load of one cell, built once so the hot path is the store alone. */\n\tprivate makeEntry(decl: CellDecl, ordinal: number, slot: number, scalar: boolean): CellEntry {\n\t\tconst { values, versions, sized } = this.region;\n\t\tconst entry: CellEntry = { decl, ordinal, slot, scalar, set: () => {}, get: () => undefined };\n\t\tif (!scalar) {\n\t\t\tentry.set = (value) => {\n\t\t\t\tsized[slot] = fitValue(value, decl);\n\t\t\t\tversions[ordinal] += 1;\n\t\t\t};\n\t\t\tentry.get = () => sized[slot];\n\t\t\treturn entry;\n\t\t}\n\t\tswitch (decl.type) {\n\t\t\tcase \"bool\":\n\t\t\t\tentry.set = (value) => {\n\t\t\t\t\tvalues[slot] = value ? 1 : 0;\n\t\t\t\t\tversions[ordinal] += 1;\n\t\t\t\t};\n\t\t\t\tentry.get = () => values[slot] !== 0;\n\t\t\t\tbreak;\n\t\t\tcase \"enum\": {\n\t\t\t\tconst index = new Map((decl.enum ?? []).map((value, i) => [value, i]));\n\t\t\t\tconst names = decl.enum ?? [];\n\t\t\t\tentry.enumIndex = index;\n\t\t\t\tentry.set = (value) => {\n\t\t\t\t\tconst i = index.get(value as string);\n\t\t\t\t\tif (i === undefined) throw new Error(`${decl.name}: ${String(value)} is not a declared value`);\n\t\t\t\t\tvalues[slot] = i;\n\t\t\t\t\tversions[ordinal] += 1;\n\t\t\t\t};\n\t\t\t\tentry.get = () => names[values[slot]];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\tentry.set = (value) => {\n\t\t\t\t\tvalues[slot] = value as number;\n\t\t\t\t\tversions[ordinal] += 1;\n\t\t\t\t};\n\t\t\t\tentry.get = () => values[slot];\n\t\t}\n\t\treturn entry;\n\t}\n\n\tprivate entry(name: string): CellEntry {\n\t\tconst entry = this.cellEntries.get(name);\n\t\tif (!entry) throw new Error(`${this.name} declares no cell ${name}`);\n\t\treturn entry;\n\t}\n\n\t/** A handle, created once per cell and cached. */\n\tcell<T = unknown>(name: string): CellHandle<T> {\n\t\tconst cached = this.cellHandles.get(name);\n\t\tif (cached) return cached as CellHandle<T>;\n\t\tconst entry = this.entry(name);\n\t\tconst handle: CellHandle = { name, get: entry.get, set: entry.set };\n\t\tthis.cellHandles.set(name, handle);\n\t\treturn handle as CellHandle<T>;\n\t}\n\n\t/** A knob handle; the cell must be `readwrite`. */\n\tknob<T = unknown>(name: string): KnobHandle<T> {\n\t\tconst entry = this.entry(name);\n\t\tif (entry.decl.access !== \"readwrite\") throw new Error(`${name} is a read cell, not a knob`);\n\t\tconst handle = this.cell<T>(name) as KnobHandle<T>;\n\t\tif (handle.reset === undefined) {\n\t\t\thandle.reset = () => {\n\t\t\t\tentry.set(entry.decl.default);\n\t\t\t\tif (!entry.scalar) this.emitLibrary(\"abai.knob.reset\", { cell: name, value: entry.get() });\n\t\t\t};\n\t\t\thandle.onChange = (handler) => {\n\t\t\t\tif (entry.scalar) throw new Error(`${name} is a scalar knob; the program reads it, nothing is delivered`);\n\t\t\t\tthis.knobHandlers.set(name, handler);\n\t\t\t};\n\t\t}\n\t\treturn handle;\n\t}\n\n\t/** @internal The handler a sized knob delivers to, for the binding. */\n\tknobHandler(name: string): KnobHandler | undefined {\n\t\treturn this.knobHandlers.get(name);\n\t}\n\n\t/** @internal Every cell's current value, keyed by name, for the binding. */\n\treadCells(): Record<string, unknown> {\n\t\tconst cells: Record<string, unknown> = {};\n\t\tfor (const [name, entry] of this.cellEntries) cells[name] = entry.get();\n\t\treturn cells;\n\t}\n\n\t/** @internal A cell's version counter. */\n\tversion(name: string): number {\n\t\treturn this.region.versions[this.entry(name).ordinal];\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Lifecycle (section 5.5): what the program itself can do\n\t// -----------------------------------------------------------------------\n\n\t/** A cooperative pause is in effect. */\n\tget paused(): boolean {\n\t\treturn this.region.flags[FLAG_PAUSED] !== 0;\n\t}\n\n\t/**\n\t * @internal A cooperative pause: the flag is set, and the program is held\n\t * at its next touchpoint (this instantiation's deviation: a safepoint\n\t * cannot block the loop the resume arrives on). A ref'd timer keeps a\n\t * paused program alive, since nothing else of its own may be pending.\n\t */\n\trequestPause(): void {\n\t\tif (this.paused) return;\n\t\tthis.region.flags[FLAG_PAUSED] = 1;\n\t\tthis.region.flags[FLAG_WORK] = 1;\n\t\tthis.pauseKeepAlive = setInterval(() => {}, 2 ** 31 - 1);\n\t}\n\n\t/** @internal Lift the pause: whoever is held at a touchpoint goes on, their clocks starting now. */\n\tresumeFromPause(): void {\n\t\tif (!this.paused) return;\n\t\tthis.region.flags[FLAG_PAUSED] = 0;\n\t\tthis.region.flags[FLAG_WORK] = this.queue.length > 0 ? 1 : 0;\n\t\tif (this.pauseKeepAlive !== undefined) clearInterval(this.pauseKeepAlive);\n\t\tthis.pauseKeepAlive = undefined;\n\t\tfor (const waiter of this.resumeWaiters.splice(0)) waiter();\n\t}\n\n\t/** Hold here while a cooperative pause is in effect; the agent is told what the pause holds (4.3). */\n\tprivate awaitResume(touchpoint: string): Promise<void> {\n\t\tif (!this.paused) return Promise.resolve();\n\t\tthis.emitLibrary(\"abai.pause.blocked\", { touchpoint });\n\t\treturn new Promise<void>((resolve) => {\n\t\t\tthis.resumeWaiters.push(resolve);\n\t\t});\n\t}\n\n\t/** @internal What the stub knows of its own process, for `lifecycle status`. */\n\tlifecycleStatus(): {\n\t\tpid: number;\n\t\tname: string;\n\t\tmode: string;\n\t\tcwd: string;\n\t\tstartedAt: string;\n\t\tconnections: number;\n\t\tpaused: boolean;\n\t\tlaunched: boolean;\n\t} {\n\t\treturn {\n\t\t\tpid: process.pid,\n\t\t\tname: this.manifest.name,\n\t\t\tmode: this.mode,\n\t\t\tcwd: process.cwd(),\n\t\t\tstartedAt: this.startedAt,\n\t\t\tconnections: this.endpoint?.connectionCount ?? (this.attached ? 1 : 0),\n\t\t\tpaused: this.paused,\n\t\t\tlaunched: this.launched,\n\t\t};\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Events (section 5.1)\n\t// -----------------------------------------------------------------------\n\n\t/** A handle for a declared event, created once and cached; the name is checked here, never on the hot path. */\n\tevent(name: string): EventHandle {\n\t\tconst cached = this.eventHandles.get(name);\n\t\tif (cached) return cached;\n\t\tconst entry = this.eventEntries.get(name);\n\t\tif (!entry) throw new Error(`${this.name} declares no event ${name}`);\n\t\tconst flags = this.region.flags;\n\t\tconst handle: EventHandle = {\n\t\t\tname,\n\t\t\temit: (payload = {}) => {\n\t\t\t\tif (flags[FLAG_ATTACHED] === 0) return;\n\t\t\t\tthis.publish(entry, payload);\n\t\t\t},\n\t\t};\n\t\tthis.eventHandles.set(name, handle);\n\t\treturn handle;\n\t}\n\n\t/** Copy the declared fields, cut sized ones to their max, publish, and tell the harness. */\n\tprivate publish(entry: EventEntry, payload: Record<string, unknown>): void {\n\t\tlet truncated = false;\n\t\tconst copy: Record<string, unknown> = {};\n\t\tfor (const field of entry.fields) {\n\t\t\tconst value = payload[field.key];\n\t\t\tif (value === undefined) continue;\n\t\t\tswitch (field.type) {\n\t\t\t\tcase \"string\": {\n\t\t\t\t\tconst text = String(value);\n\t\t\t\t\tconst cut = cutUtf8(text, field.max ?? 256);\n\t\t\t\t\tif (cut !== text) truncated = true;\n\t\t\t\t\tcopy[field.key] = cut;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"object\":\n\t\t\t\tcase \"list\": {\n\t\t\t\t\tconst bytes = encodedBytes(value);\n\t\t\t\t\tif (bytes > (field.max ?? 1024)) {\n\t\t\t\t\t\ttruncated = true;\n\t\t\t\t\t\tcopy[field.key] = { truncated: true, bytes };\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcopy[field.key] = JSON.parse(JSON.stringify(value));\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tdefault:\n\t\t\t\t\tcopy[field.key] = value;\n\t\t\t}\n\t\t}\n\t\tconst seq = this.region.emit(entry.ordinal, copy, truncated, this.now());\n\t\tthis.harness?.emitted(seq);\n\t}\n\n\t/** @internal A library event under the reserved prefix. */\n\temitLibrary(name: string, payload: Record<string, unknown>): void {\n\t\tif (this.region.flags[FLAG_ATTACHED] === 0) return;\n\t\tconst ordinal = this.libraryEvents.get(name);\n\t\tif (ordinal === undefined) throw new Error(`${name} is not a library event`);\n\t\tconst seq = this.region.emit(ordinal, payload, false, this.now());\n\t\tthis.harness?.emitted(seq);\n\t}\n\n\t/** @internal The declared event for a ring slot's ordinal, or the library event's name. */\n\teventName(ordinal: number): string {\n\t\tif (ordinal < 0) return LIBRARY_EVENTS[LIBRARY_EVENT_BASE - ordinal] ?? `abai.unknown.${ordinal}`;\n\t\treturn this.manifest.events[ordinal]?.name ?? `unknown.${ordinal}`;\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Capabilities and safepoints (section 5.3)\n\t// -----------------------------------------------------------------------\n\n\t/** Register the handler of a declared capability (or replace one given at declaration). */\n\tcapability(name: string, handler: CapabilityHandler): void {\n\t\tif (!this.manifest.capabilities.some((c) => c.name === name)) {\n\t\t\tthrow new Error(`${this.name} declares no capability ${name}`);\n\t\t}\n\t\tthis.capabilityHandlers.set(name, handler);\n\t}\n\n\t/** @internal */\n\tcapabilityHandler(name: string): CapabilityHandler | undefined {\n\t\treturn this.capabilityHandlers.get(name);\n\t}\n\n\t/** @internal Queue work for the next safepoint; the binding uses it for safepoint dispatch. */\n\tenqueue(work: () => void): void {\n\t\tthis.queue.push(work);\n\t\tthis.region.flags[FLAG_QUEUE] = this.queue.length;\n\t\tthis.region.flags[FLAG_WORK] = 1;\n\t}\n\n\t/** One load of a flag when nothing is queued and no pause is in effect. */\n\tsafepoint(): void {\n\t\tif (this.region.flags[FLAG_WORK] === 0) return;\n\t\tthis.drain();\n\t}\n\n\t/** @internal Remove queued work that will not run (a timed-out dispatch). */\n\tdequeue(work: () => void): void {\n\t\tconst index = this.queue.indexOf(work);\n\t\tif (index === -1) return;\n\t\tthis.queue.splice(index, 1);\n\t\tconst flags = this.region.flags;\n\t\tflags[FLAG_QUEUE] = this.queue.length;\n\t\tif (this.queue.length === 0 && flags[FLAG_PAUSED] === 0) flags[FLAG_WORK] = 0;\n\t}\n\n\t/** @internal Run everything queued, now, on this thread: a touchpoint holds the program at a safepoint. */\n\tdrain(): void {\n\t\tconst flags = this.region.flags;\n\t\twhile (this.queue.length > 0) {\n\t\t\tconst work = this.queue.shift() as () => void;\n\t\t\tflags[FLAG_QUEUE] = this.queue.length;\n\t\t\ttry {\n\t\t\t\twork();\n\t\t\t} catch {\n\t\t\t\t// a handler's failure is reported through its reply, never through the program's safepoint\n\t\t\t}\n\t\t}\n\t\tflags[FLAG_WORK] = flags[FLAG_PAUSED] !== 0 ? 1 : 0;\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Decisions and turns (sections 5.4, 4.3)\n\t// -----------------------------------------------------------------------\n\n\tprivate applyDefault(decl: DecisionDecl, cause: string): unknown {\n\t\tif (decl.default === \"abort\") throw new AbaigramAbort(decl.name, cause);\n\t\treturn decl.default;\n\t}\n\n\t/** Ask which way to go. With no harness attached the default applies at once and is counted. */\n\tasync decide<T = unknown>(name: string, context: Record<string, unknown> = {}): Promise<T> {\n\t\tconst index = this.decisionIndex.get(name);\n\t\tif (index === undefined) throw new Error(`${this.name} declares no decision ${name}`);\n\t\tconst decl = this.manifest.decisions[index];\n\t\tconst harness = this.harness;\n\t\tif (this.region.flags[FLAG_ATTACHED] === 0 || harness === undefined) {\n\t\t\tthis.region.counters[index] += 1;\n\t\t\treturn this.applyDefault(decl, \"no_harness\") as T;\n\t\t}\n\t\t// a cooperative pause holds the decision here; its own clock starts when the pause lifts (4.3)\n\t\tif (this.paused) await this.awaitResume(name);\n\t\tif (this.region.flags[FLAG_ATTACHED] === 0 || this.harness === undefined) {\n\t\t\tthis.region.counters[index] += 1;\n\t\t\treturn this.applyDefault(decl, \"no_harness\") as T;\n\t\t}\n\t\tthis.drain();\n\t\ttry {\n\t\t\treturn (await this.harness.decide(decl, context, this.now() + durationMs(decl.timeout))) as T;\n\t\t} catch (error) {\n\t\t\treturn this.applyDefault(decl, error instanceof Error ? error.message : String(error)) as T;\n\t\t}\n\t}\n\n\t/** Give the agent a turn. With no harness attached it returns at once and is counted. */\n\tasync turn(name: string): Promise<void> {\n\t\tconst index = this.turnIndex.get(name);\n\t\tif (index === undefined) throw new Error(`${this.name} declares no turn ${name}`);\n\t\tconst decl = this.manifest.turns[index];\n\t\tconst harness = this.harness;\n\t\tif (this.region.flags[FLAG_ATTACHED] === 0 || harness === undefined) {\n\t\t\tthis.region.counters[this.manifest.decisions.length + index] += 1;\n\t\t\treturn;\n\t\t}\n\t\tif (this.paused) await this.awaitResume(name);\n\t\tif (this.region.flags[FLAG_ATTACHED] === 0 || this.harness === undefined) {\n\t\t\tthis.region.counters[this.manifest.decisions.length + index] += 1;\n\t\t\treturn;\n\t\t}\n\t\tthis.drain();\n\t\ttry {\n\t\t\tawait this.harness.turn(decl, this.now() + durationMs(decl.timeout));\n\t\t} catch {\n\t\t\t// a turn that fails is a turn that ended\n\t\t}\n\t\tthis.drain();\n\t}\n\n\t/** The counters, by kind and name: defaulted decisions, skipped turns, and the mode fallback. */\n\tcounters(): CounterSnapshot {\n\t\tconst snapshot: CounterSnapshot = {};\n\t\tthis.manifest.decisions.forEach((decl, i) => {\n\t\t\tsnapshot[`decision:${decl.name}`] = this.region.counters[i];\n\t\t});\n\t\tthis.manifest.turns.forEach((decl, i) => {\n\t\t\tsnapshot[`turn:${decl.name}`] = this.region.counters[this.manifest.decisions.length + i];\n\t\t});\n\t\tsnapshot[\"abai.mode_fallback\"] = this.region.counters[this.region.counters.length - 1];\n\t\treturn snapshot;\n\t}\n\n\t/** @internal Read and reset the counters, for the harness that attaches. */\n\ttakeCounters(): CounterSnapshot {\n\t\tconst snapshot = this.counters();\n\t\tthis.region.counters.fill(0);\n\t\treturn snapshot;\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Attaching (section 4.3)\n\t// -----------------------------------------------------------------------\n\n\t/** @internal The binding attaches a harness. */\n\tsetHarness(harness: AttachedHarness): void {\n\t\tthis.harness = harness;\n\t\tthis.region.flags[FLAG_ATTACHED] = 1;\n\t\tthis.lastAttachError = undefined;\n\t}\n\n\t/** @internal The binding detaches it; a decision in flight takes its default with `reason`. */\n\tclearHarness(reason: string): void {\n\t\tconst harness = this.harness;\n\t\tthis.harness = undefined;\n\t\tthis.binding = undefined;\n\t\tthis.nullHarness = undefined;\n\t\tthis.region.flags[FLAG_ATTACHED] = 0;\n\t\tthis.lastAttachError = reason;\n\t\t// a pause is the attached harness's: when the harness goes the program runs as itself again (6.3)\n\t\tthis.resumeFromPause();\n\t\tharness?.detach(reason);\n\t}\n\n\t/** The direct binding, while an in-process harness is attached. */\n\tget directBinding(): HarnessBinding | undefined {\n\t\treturn this.binding;\n\t}\n\n\t/** The null harness, while one is attached. */\n\tget attachedNullHarness(): NullHarness | undefined {\n\t\treturn this.nullHarness;\n\t}\n\n\tprivate createBinding(connection?: string): DirectBinding {\n\t\tconst binding = new DirectBinding(this, {\n\t\t\t...(this.auditPathOverride === undefined ? {} : { auditPath: this.auditPathOverride }),\n\t\t\t...(connection === undefined ? {} : { connection }),\n\t\t});\n\t\tthis.binding = binding;\n\t\tthis.setHarness(binding);\n\t\tbinding.flushCounters();\n\t\treturn binding;\n\t}\n\n\t/**\n\t * @internal A front end of the library's own (the sidecar endpoint)\n\t * attaches the program through a binding it then drives; the connection's\n\t * id labels its acts in the audit. Refused while something else is\n\t * attached: a second harness would take the program over silently.\n\t */\n\tbind(connection: string): DirectBinding {\n\t\tif (this.attached) {\n\t\t\tthrow new Error(`${this.name} already has a harness attached; this connection cannot take it over`);\n\t\t}\n\t\tif (this.launched) this.launcherSeen = true;\n\t\treturn this.createBinding(connection);\n\t}\n\n\tprivate attachNull(form: \"null\" | \"exercise\"): void {\n\t\tconst binding = this.createBinding();\n\t\tthis.nullHarness = attachNullHarness(binding, form);\n\t\tif (form === \"exercise\") {\n\t\t\tconst harness = this.nullHarness;\n\t\t\tprocess.once(\"exit\", () => {\n\t\t\t\tif (this.nullHarness === harness) this.report(JSON.stringify(harness.report()));\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Connect or spawn a harness (one of the five places). Resolves true when\n\t * attached. The real harness arrives through the `harness` extra, or the\n\t * harness package's dynamic import once it exists; until then the reason\n\t * is recorded.\n\t */\n\tasync attach(): Promise<boolean> {\n\t\tif (this.attached) return true;\n\t\tswitch (this.harnessSelection) {\n\t\t\tcase \"off\":\n\t\t\t\tthis.lastAttachError = `${ENV_HARNESS}=off`;\n\t\t\t\treturn false;\n\t\t\tcase \"null\":\n\t\t\tcase \"exercise\":\n\t\t\t\tthis.attachNull(this.harnessSelection);\n\t\t\t\treturn true;\n\t\t\tdefault:\n\t\t\t\tif (this.harnessSelectionError !== undefined) {\n\t\t\t\t\tthis.lastAttachError = this.harnessSelectionError;\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tif (this.endpoint) {\n\t\t\t\t\t// launched: the parent is already connecting; the program never spawns anything itself\n\t\t\t\t\treturn this.launched ? this.awaitLauncher(this.endpoint) : this.attachSidecar(this.endpoint);\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tconst factory =\n\t\t\t\t\t\tthis.harnessFactory ??\n\t\t\t\t\t\t(await installedHarness(\n\t\t\t\t\t\t\tthis.env[ENV_HARNESS_MODULE] || this.manifest.harness?.path || \"@abaigram/abai-embedded-harness\",\n\t\t\t\t\t\t));\n\t\t\t\t\tif (factory === undefined) {\n\t\t\t\t\t\tthis.lastAttachError =\n\t\t\t\t\t\t\t\"no harness is installed (the @abaigram/abai-embedded-harness package is not resolvable)\";\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\tconst binding = this.createBinding();\n\t\t\t\t\tawait factory(binding);\n\t\t\t\t\treturn this.attached;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst reason = error instanceof Error ? error.message : String(error);\n\t\t\t\t\tthis.binding?.detach(reason);\n\t\t\t\t\tthis.lastAttachError = reason;\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t}\n\t}\n\n\t/** Under launch: the launcher connects to the socket it chose; the program waits for it once, bounded. */\n\tprivate async awaitLauncher(endpoint: Endpoint): Promise<boolean> {\n\t\ttry {\n\t\t\tawait endpoint.ready;\n\t\t} catch (error) {\n\t\t\tthis.lastAttachError = `the endpoint could not listen: ${error instanceof Error ? error.message : String(error)}`;\n\t\t\treturn false;\n\t\t}\n\t\tif (this.attached) return true;\n\t\tif (this.launcherSeen) {\n\t\t\t// it was here and went: a later attach place returns at once, as 4.3 says of every touchpoint after a detach\n\t\t\tthis.lastAttachError = this.lastAttachError ?? \"the launcher disconnected\";\n\t\t\treturn false;\n\t\t}\n\t\tconst waitMs = attachWaitMsFrom(this.env);\n\t\tif (await endpoint.waitForConnection(waitMs)) {\n\t\t\tthis.launcherSeen = true;\n\t\t\treturn true;\n\t\t}\n\t\tthis.lastAttachError = `launched, but the launcher did not connect within ${waitMs} ms`;\n\t\treturn false;\n\t}\n\n\t/**\n\t * Sidecar attach (section 6.3): a harness already connected to the\n\t * endpoint means attached; otherwise the harness binary is spawned with\n\t * the terminal inherited and given `ABAI_ATTACH_WAIT_MS` to connect. A\n\t * child that exits first fails the attach at once with its code, so an\n\t * unconfigured machine costs well under a second (section 4.3); a child\n\t * that never connects is ended at the wait and the attach fails with the\n\t * reason. The child is unref'd: a program whose work is done exits, and\n\t * the closing socket tells the harness.\n\t */\n\tprivate async attachSidecar(endpoint: Endpoint): Promise<boolean> {\n\t\ttry {\n\t\t\tawait endpoint.ready;\n\t\t} catch {\n\t\t\t// spawnHarness reports it\n\t\t}\n\t\t// a harness that connected while the endpoint came up, or at any time before: attached already\n\t\tif (this.attached) return true;\n\t\tconst spawned = await this.spawnHarness(endpoint, \"attach\");\n\t\treturn spawned !== undefined;\n\t}\n\n\t/**\n\t * Spawn the harness binary with a verb against this program's endpoint\n\t * and wait for it to connect. Resolves to the child once attached, or to\n\t * undefined with the reason in `attachError`: the endpoint could not\n\t * listen, the child exited first (its code), it never connected within\n\t * the wait (it is ended), or it could not be started at all.\n\t */\n\tprivate async spawnHarness(endpoint: Endpoint, verb: \"attach\" | \"mcp\"): Promise<ChildProcess | undefined> {\n\t\ttry {\n\t\t\tawait endpoint.ready;\n\t\t} catch (error) {\n\t\t\tthis.lastAttachError = `the endpoint could not listen: ${error instanceof Error ? error.message : String(error)}`;\n\t\t\treturn undefined;\n\t\t}\n\t\tconst waitMs = attachWaitMsFrom(this.env);\n\t\tconst binary = harnessBinary(this.env, this.content.root);\n\t\tconst args = [...binary.args, verb, \"--target\", endpoint.socketPath, \"--run-dir\", endpoint.runDir];\n\t\tlet child: ChildProcess;\n\t\ttry {\n\t\t\tchild = spawn(binary.command, args, { stdio: \"inherit\", env: { ...process.env, ...this.env } });\n\t\t} catch (error) {\n\t\t\tthis.lastAttachError = `the harness binary could not be started: ${error instanceof Error ? error.message : String(error)}`;\n\t\t\treturn undefined;\n\t\t}\n\t\tchild.unref();\n\t\t// a ChildProcess with no error listener throws into the program; one stays for the child's whole life\n\t\tchild.on(\"error\", () => {});\n\t\tconst outcome = await new Promise<string>((resolve) => {\n\t\t\tlet settled = false;\n\t\t\tconst settle = (result: string): void => {\n\t\t\t\tif (settled) return;\n\t\t\t\tsettled = true;\n\t\t\t\tchild.off(\"exit\", onExit);\n\t\t\t\tchild.off(\"error\", onError);\n\t\t\t\tresolve(result);\n\t\t\t};\n\t\t\tconst onExit = (code: number | null, signal: NodeJS.Signals | null): void =>\n\t\t\t\tsettle(`exited:${code === null ? `signal ${signal ?? \"unknown\"}` : String(code)}`);\n\t\t\tconst onError = (error: NodeJS.ErrnoException): void => settle(`error:${error.code ?? error.message}`);\n\t\t\tchild.once(\"exit\", onExit);\n\t\t\tchild.once(\"error\", onError);\n\t\t\tvoid endpoint.waitForConnection(waitMs).then((connected) => settle(connected ? \"connected\" : \"timeout\"));\n\t\t});\n\t\tif (outcome === \"connected\") return child;\n\t\tif (outcome === \"timeout\") {\n\t\t\t// the one process this program started, by its own handle: nothing else is touched\n\t\t\tchild.kill();\n\t\t\tthis.lastAttachError = `the harness binary did not connect within ${waitMs} ms (${binary.command})`;\n\t\t\treturn undefined;\n\t\t}\n\t\tif (outcome.startsWith(\"exited:\")) {\n\t\t\tthis.lastAttachError = `the harness binary exited with ${outcome.slice(\"exited:\".length)} before connecting`;\n\t\t\treturn undefined;\n\t\t}\n\t\tthis.lastAttachError = `the harness binary could not be started: ${outcome.slice(\"error:\".length)} (${binary.command})`;\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * @internal `<prog> abai mcp` under sidecar: the binary's MCP server is\n\t * spawned against this program's endpoint with the terminal inherited, so\n\t * the MCP client on this process's stdin and stdout talks to it, and the\n\t * program waits at its entry, a safepoint it holds open, until the client\n\t * goes. Resolves to the child's exit code; -1 when nothing could be\n\t * spawned (the reason is in `attachError`).\n\t */\n\tasync serveMcpSidecar(endpoint: Endpoint): Promise<number> {\n\t\tif (this.attached) {\n\t\t\tthis.lastAttachError = `${this.name} already has a harness attached`;\n\t\t\treturn -1;\n\t\t}\n\t\tconst child = await this.spawnHarness(endpoint, \"mcp\");\n\t\tif (child === undefined) return -1;\n\t\t// the program's whole purpose now is to wait for its server: the child holds the event loop open,\n\t\t// where the spawn left it unref'd for the attach case, whose touchpoint holds the loop itself\n\t\tchild.ref();\n\t\t// the MCP client spawned this program and ends it with a signal; the server behind it must go too\n\t\tconst forward = (signal: NodeJS.Signals): void => {\n\t\t\tif (child.exitCode === null && child.signalCode === null) child.kill(signal);\n\t\t};\n\t\tconst forwarded: NodeJS.Signals[] = [\"SIGTERM\", \"SIGINT\", \"SIGHUP\"];\n\t\tfor (const signal of forwarded) process.on(signal, forward);\n\t\tconst binding = this.binding;\n\t\tbinding?.enterSafepoint();\n\t\ttry {\n\t\t\tif (child.exitCode !== null) return child.exitCode;\n\t\t\treturn await new Promise<number>((resolve) => {\n\t\t\t\tchild.once(\"exit\", (code) => resolve(code ?? 1));\n\t\t\t});\n\t\t} finally {\n\t\t\tfor (const signal of forwarded) process.off(signal, forward);\n\t\t\tbinding?.leaveSafepoint();\n\t\t}\n\t}\n\n\tprivate async touchpoint(kind: TouchpointKind): Promise<void> {\n\t\tif (!(await this.attach())) return;\n\t\tif (this.paused) await this.awaitResume(kind);\n\t\tconst binding = this.binding;\n\t\tif (!binding) return;\n\t\tthis.drain();\n\t\tawait binding.touchpoint(kind);\n\t\tthis.drain();\n\t}\n\n\t/** Run the install touchpoint; returns when the harness finishes, or at once when none can be attached. */\n\tinstall(): Promise<void> {\n\t\treturn this.touchpoint(\"install\");\n\t}\n\n\t/** Open a session; returns when the harness ends it, or at once when none can be attached. */\n\tsession(): Promise<void> {\n\t\treturn this.touchpoint(\"session\");\n\t}\n}\n\n/** Overrides where the in-process harness is imported from (a path or a package name). */\nexport const ENV_HARNESS_MODULE = \"ABAI_HARNESS_MODULE\";\n\n/**\n * The harness binary to spawn under sidecar: `ABAI_HARNESS_BIN` (a script\n * path runs under this very node), else the nearest\n * `node_modules/.bin/abai-embedded-harness` from the program's root\n * upward, else the name on PATH.\n */\nexport function harnessBinary(env: NodeJS.ProcessEnv, root: string): { command: string; args: string[] } {\n\tconst explicit = env[ENV_HARNESS_BIN]?.trim();\n\tif (explicit) {\n\t\treturn /\\.(?:[mc]?js|ts)$/.test(explicit)\n\t\t\t? { command: process.execPath, args: [explicit] }\n\t\t\t: { command: explicit, args: [] };\n\t}\n\tconst installed = installedHarnessBinary(root);\n\tif (installed !== undefined) return { command: installed, args: [] };\n\treturn { command: \"abai-embedded-harness\", args: [] };\n}\n\n/**\n * The installed harness's bin link: under the program's root, else under the\n * nearest ancestor that has one, the way Node resolves a package. npm hoists\n * a workspace's packages and their bin links to the workspace root, so a\n * program that is one package of a workspace has no `.bin` of its own. When\n * no manifest was found the root is the working directory, and the walk is\n * the one Node would make for a module imported from there.\n */\nfunction installedHarnessBinary(root: string): string | undefined {\n\tlet dir = resolve(root);\n\tlet candidate = join(dir, \"node_modules\", \".bin\", \"abai-embedded-harness\");\n\twhile (!existsSync(candidate)) {\n\t\tconst parent = dirname(dir);\n\t\tif (parent === dir) return undefined;\n\t\tdir = parent;\n\t\tcandidate = join(dir, \"node_modules\", \".bin\", \"abai-embedded-harness\");\n\t}\n\treturn candidate;\n}\n\n/** What the stub uses of the installed harness package. */\nexport interface HarnessModule {\n\tattachEmbedded?: (binding: HarnessBinding) => Promise<unknown>;\n\t/** `<prog> abai mcp` in-process: serve this binding to the MCP client on the process's stdio; resolves to the exit code. */\n\tserveMcpEmbedded?: (binding: HarnessBinding) => Promise<number>;\n\trunConfig?: (\n\t\targs: string[],\n\t\tio: { out(text: string): void; err(text: string): void; env: NodeJS.ProcessEnv },\n\t\t/** The program the entry runs for, so `config net` finds its network directory. */\n\t\tcontext?: { program?: string },\n\t) => Promise<number>;\n\tdoctorOnline?: (\n\t\tmanifest: Manifest,\n\t\tenv: NodeJS.ProcessEnv,\n\t) => Promise<Array<{ name: string; status: \"ok\" | \"fail\" | \"skip\"; detail: string }>>;\n}\n\n/** The harness package, found by dynamic import when a program installed it; undefined when it does not resolve. */\nexport async function importHarnessModule(\n\tenv: NodeJS.ProcessEnv,\n\tmanifest: Manifest,\n): Promise<HarnessModule | undefined> {\n\tconst specifier = env[ENV_HARNESS_MODULE] || manifest.harness?.path || \"@abaigram/abai-embedded-harness\";\n\ttry {\n\t\treturn (await import(specifier)) as HarnessModule;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\n/** The harness package's in-process entry. */\nasync function installedHarness(specifier: string): Promise<HarnessFactory | undefined> {\n\tlet module: HarnessModule;\n\ttry {\n\t\tmodule = (await import(specifier)) as HarnessModule;\n\t} catch {\n\t\treturn undefined;\n\t}\n\tif (typeof module.attachEmbedded !== \"function\") return undefined;\n\tconst attach = module.attachEmbedded;\n\treturn async (binding) => {\n\t\tawait attach(binding);\n\t};\n}\n\n/** The program's one call: declarations in, the abaigram out. Throws when a declaration does not validate. */\nexport function createAbaigram(options: AbaigramOptions, extras: AbaigramExtras = {}): Abaigram {\n\treturn new Abaigram(options, extras);\n}\n"]}
package/dist/program.js CHANGED
@@ -18,7 +18,7 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
18
18
  // file carries the detached behaviour and the seams the binding fills.
19
19
  import { spawn } from "node:child_process";
20
20
  import { existsSync } from "node:fs";
21
- import { dirname, join } from "node:path";
21
+ import { dirname, join, resolve } from "node:path";
22
22
  import { fitValue } from "./cells/fit.js";
23
23
  import { createContent, findRoot } from "./content.js";
24
24
  import { Endpoint } from "./endpoint.js";
@@ -829,8 +829,9 @@ export class Abaigram {
829
829
  export const ENV_HARNESS_MODULE = "ABAI_HARNESS_MODULE";
830
830
  /**
831
831
  * The harness binary to spawn under sidecar: `ABAI_HARNESS_BIN` (a script
832
- * path runs under this very node), else the program's own
833
- * `node_modules/.bin/abai-embedded-harness`, else the name on PATH.
832
+ * path runs under this very node), else the nearest
833
+ * `node_modules/.bin/abai-embedded-harness` from the program's root
834
+ * upward, else the name on PATH.
834
835
  */
835
836
  export function harnessBinary(env, root) {
836
837
  const explicit = env[ENV_HARNESS_BIN]?.trim();
@@ -839,11 +840,31 @@ export function harnessBinary(env, root) {
839
840
  ? { command: process.execPath, args: [explicit] }
840
841
  : { command: explicit, args: [] };
841
842
  }
842
- const local = join(root, "node_modules", ".bin", "abai-embedded-harness");
843
- if (existsSync(local))
844
- return { command: local, args: [] };
843
+ const installed = installedHarnessBinary(root);
844
+ if (installed !== undefined)
845
+ return { command: installed, args: [] };
845
846
  return { command: "abai-embedded-harness", args: [] };
846
847
  }
848
+ /**
849
+ * The installed harness's bin link: under the program's root, else under the
850
+ * nearest ancestor that has one, the way Node resolves a package. npm hoists
851
+ * a workspace's packages and their bin links to the workspace root, so a
852
+ * program that is one package of a workspace has no `.bin` of its own. When
853
+ * no manifest was found the root is the working directory, and the walk is
854
+ * the one Node would make for a module imported from there.
855
+ */
856
+ function installedHarnessBinary(root) {
857
+ let dir = resolve(root);
858
+ let candidate = join(dir, "node_modules", ".bin", "abai-embedded-harness");
859
+ while (!existsSync(candidate)) {
860
+ const parent = dirname(dir);
861
+ if (parent === dir)
862
+ return undefined;
863
+ dir = parent;
864
+ candidate = join(dir, "node_modules", ".bin", "abai-embedded-harness");
865
+ }
866
+ return candidate;
867
+ }
847
868
  /** The harness package, found by dynamic import when a program installed it; undefined when it does not resolve. */
848
869
  export async function importHarnessModule(env, manifest) {
849
870
  const specifier = env[ENV_HARNESS_MODULE] || manifest.harness?.path || "@abaigram/abai-embedded-harness";