@nikovirtala/adr 0.5.2 → 0.5.3

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":"server-CRmWjWqD.js","names":[],"sources":["../src/mcp/policy.ts","../src/mcp/resources.ts","../src/mcp/text.ts","../src/mcp/tools.ts","../src/mcp/prompt.ts","../src/mcp/server.ts"],"sourcesContent":["import type { Actor, Finding } from \"@nikovirtala/ledger\";\nimport type { AdrConfig } from \"../config.js\";\nimport { adrKind, type DecisionView } from \"../kind.js\";\nimport type { DecisionsRead } from \"../log.js\";\n\n/** The tools that decide; listed only with `[policy] mcp_can_decide = true`. */\nexport const DECISION_TOOLS = [\n \"adr_accept\",\n \"adr_reject\",\n \"adr_deprecate\",\n \"adr_supersede\",\n] as const;\n\n/** Whether `adr mcp` offers the decision tools (design §7.5, Table A). */\nexport function decisionToolsAvailable(adr: AdrConfig): boolean {\n return adr.mcpCanDecide;\n}\n\n/**\n * Who a proposal is for (design D5): its `proposed` event's actor, `on_behalf_of` for an agent\n * and `email` for a human, lower-cased; `null` when the event or the address is missing.\n */\nexport function proposalOwner(read: DecisionsRead, id: string): string | null {\n const proposed = read.folded.subjects\n .get(id)\n ?.applied.find((a) => a.event.type === adrKind.machine.initial.type);\n const actor = proposed?.event.actor;\n if (actor === undefined) return null;\n const owner = actor.kind === \"agent\" ? actor.on_behalf_of : actor.email;\n return typeof owner === \"string\" && owner.trim() !== \"\" ? owner.trim().toLowerCase() : null;\n}\n\n/** The writes `mcpWriteRefusal` judges: the ones whose ownership matters. */\nexport type PolicyTool = \"adr_scope\" | \"adr_update_draft\" | \"adr_withdraw\";\n\n/**\n * The MCP policy (design §7.5, Table B): `null` when the write may go ahead, else the\n * `decision/mcp-cannot-decide` finding. Without `mcp_can_decide` an agent may scope, edit and\n * withdraw only the proposals made for the person it acts for, and rescope no accepted or\n * deprecated decision.\n * Writes the state machine forbids anyway get `null`, so the library refuses them with the real\n * reason.\n */\nexport function mcpWriteRefusal(o: {\n readonly tool: PolicyTool;\n readonly view: DecisionView;\n readonly owner: string | null;\n readonly actor: Actor;\n readonly mcpCanDecide: boolean;\n readonly display: (id: string) => string;\n /** The finding's file when the decision has no body: its events directory. */\n readonly eventsDir: string;\n}): Finding | null {\n const { view } = o;\n if (o.tool === \"adr_scope\" && !adrKind.machine.allowed(view.status, \"scoped\")) return null;\n if (o.tool === \"adr_update_draft\" && view.status !== \"proposed\") return null;\n if (o.tool === \"adr_withdraw\" && !adrKind.machine.allowed(view.status, \"withdrawn\")) return null;\n if (o.mcpCanDecide) return null;\n const me = o.actor.on_behalf_of?.trim().toLowerCase() ?? null;\n if (view.status === \"proposed\" && o.owner !== null && o.owner === me) return null;\n const shown = o.display(view.id);\n const named = shown === view.id ? view.id : `${shown} (${view.id})`;\n const verb = o.tool === \"adr_withdraw\" ? \"withdrawing\" : \"changing\";\n const message =\n view.status === \"proposed\"\n ? `${named} was proposed for ${o.owner ?? \"someone else\"}, and you act for ${o.actor.on_behalf_of ?? \"nobody\"}; ${verb} another person's proposal needs [policy] mcp_can_decide = true. Add a note with adr_note instead.`\n : `${named} is ${view.status}; rescoping it needs [policy] mcp_can_decide = true, because narrowing a scope can switch a decision off. Ask a human to run adr scope ${shown} …, or propose a superseding decision.`;\n return {\n severity: \"error\",\n rule: \"decision/mcp-cannot-decide\",\n message,\n file: view.body_path ?? o.eventsDir,\n line: null,\n subject: view.id,\n kind: adrKind.name,\n };\n}\n","import { renderIndex, resolveSubjectInput, UsageError } from \"@nikovirtala/ledger\";\nimport type { McpResource, McpResourceTemplate } from \"@nikovirtala/ledger/mcp\";\nimport { adrKind } from \"../kind.js\";\nimport { type DecisionsRead, readDecisions, resolveDecision } from \"../log.js\";\nimport { DECISION_INDEX } from \"../log-index.js\";\nimport { showDecision } from \"../views.js\";\nimport { mcpHeader } from \"./text.js\";\nimport { type AdrMcpEnv, openLog } from \"./tools.js\";\n\nconst MAX_ID = 64;\n\n/**\n * Where an MCP client reads a decision: `adr://decision/ADR-0012` when numbered, else\n * `adr://decision/<id>`. The `refer` of every header the MCP texts show.\n */\nexport function decisionUri(read: DecisionsRead): (id: string) => string {\n return (id) => `adr://decision/${read.projection.views.get(id)?.display ?? id}`;\n}\n\n/** `adr://index`: the index table, numbered like every other read (design §7.7). */\nexport function indexResource(e: AdrMcpEnv): McpResource {\n return {\n uri: \"adr://index\",\n name: \"index\",\n title: \"Decision index\",\n description: \"All decisions, grouped by status, with numbers and dates\",\n mimeType: \"text/markdown\",\n async read() {\n const read = await readDecisions(await openLog(e));\n const views = read.projection.views;\n return {\n header: null,\n text: renderIndex(DECISION_INDEX(read.root, views), [...views.values()], read.numbering),\n };\n },\n };\n}\n\n/**\n * `adr://decision/{id}`: the decision's state header, then its body. `{id}` is the id, the number\n * (`12`, `0012`) or `ADR-0012`; an unknown one is not found, a malformed or qualified one is the\n * caller's error.\n */\nexport function decisionResource(e: AdrMcpEnv): McpResourceTemplate {\n return {\n uriTemplate: \"adr://decision/{id}\",\n name: \"decision\",\n title: \"Decision\",\n description:\n \"One decision: its state header, then its body. {id} is the id (k3f9q8a1), the number (12) or ADR-0012\",\n mimeType: \"text/markdown\",\n async read({ id = \"\" }) {\n if (id.length > MAX_ID) {\n throw new UsageError(\n `invalid decision ${JSON.stringify(`${id.slice(0, MAX_ID)}…`)}: an id or number is at most ${MAX_ID} characters`,\n );\n }\n const read = await readDecisions(await openLog(e));\n const r = resolveSubjectInput(id, {\n subjects: new Set(read.folded.subjects.keys()),\n kind: adrKind,\n numbering: read.numbering,\n });\n if (!r.ok && r.reason === \"not-found\") return null;\n const doc = await showDecision(read, resolveDecision(read, id));\n return {\n header: mcpHeader(doc.decision, read),\n text: doc.body === null ? \"(no body file)\\n\" : doc.body,\n };\n },\n };\n}\n","/**\n * The readable text of each MCP tool result (design §7.4, last column). The documents are the\n * CLI's; these texts are MCP's own, and their state headers point at `adr://decision/…`.\n */\nimport {\n type EventEnvelope,\n type Finding,\n renderStateHeader,\n type StateHeader,\n} from \"@nikovirtala/ledger\";\nimport type { McpToolResult } from \"@nikovirtala/ledger/mcp\";\nimport type { DecisionView } from \"../kind.js\";\nimport type { DecisionsRead } from \"../log.js\";\nimport type { DecisionsForJson } from \"../scope.js\";\nimport type { DecisionSearchJson } from \"../search.js\";\nimport type { TemplatesJson } from \"../templates/list.js\";\nimport { type DecisionListJson, type DecisionShowJson, stateHeader } from \"../views.js\";\nimport type { WriteResultJson } from \"../write.js\";\nimport { decisionUri } from \"./resources.js\";\n\ntype Text = Omit<McpToolResult, \"document\">;\n\nconst display = (read: DecisionsRead) => (id: string) =>\n read.projection.views.get(id)?.display ?? id;\n\nfunction named(read: DecisionsRead, id: string): string {\n const shown = display(read)(id);\n return shown === id ? id : `${shown} (${id})`;\n}\n\n/** The decision's state header with MCP's `adr://` references. */\nexport function mcpHeader(view: DecisionView, read: DecisionsRead): StateHeader {\n return stateHeader(view, read, { refer: decisionUri(read) });\n}\n\n/** `adr_search`: each result's header, title and excerpt, then the counts. */\nexport function searchText(doc: DecisionSearchJson, read: DecisionsRead): Text {\n if (doc.results.length === 0) {\n const more =\n doc.inactive_omitted > 0\n ? [`${inactiveLine(doc.inactive_omitted)}; pass include_inactive`]\n : [];\n return { headers: [], text: [\"No decisions match.\", ...more].join(\"\\n\") };\n }\n const lines: string[] = [];\n for (const r of doc.results) {\n lines.push(renderStateHeader(mcpHeader(r.decision, read)).trimEnd());\n lines.push(` ${r.decision.title}`);\n const where = r.matched.filter((f) => f === \"id\" || f === \"title\").join(\" and \");\n lines.push(r.excerpt === null ? ` (${where} match)` : ` ${r.excerpt}`);\n }\n lines.push(`${doc.results.length} of ${doc.total} shown`);\n if (doc.inactive_omitted > 0) {\n lines.push(`${inactiveLine(doc.inactive_omitted)}; pass include_inactive`);\n }\n return { headers: [], text: lines.join(\"\\n\") };\n}\n\nconst inactiveLine = (k: number) =>\n k === 1 ? \"1 inactive decision also matches\" : `${k} inactive decisions also match`;\n\nfunction listOf(read: DecisionsRead, ids: readonly string[]): string {\n return ids.length === 0 ? \"none\" : ids.map((id) => named(read, id)).join(\", \");\n}\n\nfunction historyLines(events: readonly EventEnvelope[]): string[] {\n return events.map((e) => {\n const a = e.actor;\n const who = a.kind === \"agent\" ? `${a.name} (agent for ${a.on_behalf_of})` : a.name;\n const why = typeof e.reason === \"string\" ? ` — ${e.reason}` : \"\";\n return ` ${e.at} ${e.type} ${who}${why}`;\n });\n}\n\n/** `adr_get`: the header, the decision's fields as `adr show` lists them, then the body. */\nexport function getText(doc: DecisionShowJson, read: DecisionsRead): Text {\n const v = doc.decision;\n const lines = [\n `Title: ${v.title}`,\n `Status: ${v.status} (${v.status_at.slice(0, 10)})`,\n `Effective: ${v.effective === null ? \"none (supersession cycle)\" : named(read, v.effective)}`,\n `Chain: ${v.chain.map(display(read)).join(\" → \")}`,\n `Supersedes: ${listOf(read, v.supersedes)}`,\n `Applies to: ${v.applies_to.length === 0 ? \"no globs recorded\" : v.applies_to.join(\", \")}`,\n ];\n if (doc.events !== null) lines.push(\"History:\", ...historyLines(doc.events));\n lines.push(\"\", doc.body === null ? \"(no body file)\" : doc.body.trimEnd());\n return { headers: [mcpHeader(v, read)], text: lines.join(\"\\n\") };\n}\n\n/** `adr_list`: one line per decision. */\nexport function listText(doc: DecisionListJson, read: DecisionsRead): Text {\n if (doc.decisions.length === 0) return { headers: [], text: \"No decisions.\" };\n const lines = doc.decisions.map((v) => {\n const head = v.number === null ? v.id : `${v.display} (${v.id})`;\n const to =\n v.effective !== null && v.effective !== v.id ? ` → ${display(read)(v.effective)}` : \"\";\n return `${head} · ${v.status} · ${v.title}${to}`;\n });\n return { headers: [], text: lines.join(\"\\n\") };\n}\n\n/** `adr_templates`: each template, then its sections. */\nexport function templatesText(doc: TemplatesJson): Text {\n const lines = doc.templates.flatMap((t) => [\n `${t.name} v${t.version} (${t.source})${t.name === doc.default ? \" default\" : \"\"}`,\n ...t.sections.map(\n (s) =>\n ` ${s.id}: ${s.heading} (${s.required ? \"required\" : \"optional\"})${s.guidance === null ? \"\" : ` — ${s.guidance}`}`,\n ),\n ]);\n return { headers: [], text: lines.length === 0 ? \"No templates.\" : lines.join(\"\\n\") };\n}\n\n/** `adr_for_path`: per path, each decision's header and how it matched. */\nexport function forText(doc: DecisionsForJson, read: DecisionsRead): Text {\n const lines: string[] = [];\n for (const p of doc.paths) {\n lines.push(p.tracked ? p.path : `${p.path} (not tracked)`);\n if (p.decisions.length === 0 && p.unresolved.length === 0) lines.push(\" no decisions\");\n for (const d of p.decisions) {\n const view = read.projection.views.get(d.id);\n const h =\n view === undefined\n ? { line: `${named(read, d.id)} · ${d.status}`, warning: d.warning }\n : mcpHeader(view, read);\n lines.push(` ${h.line}`);\n if (h.warning !== null) lines.push(` ${h.warning}`);\n for (const via of d.via) {\n lines.push(\n via.type === \"glob\" ? ` via glob ${via.glob}` : ` via anchor line ${via.line}`,\n );\n }\n }\n for (const u of p.unresolved) {\n const why = u.reason === \"other-log\" ? \"in another log\" : \"not in this log\";\n lines.push(` unresolved: ${u.ref} (line ${u.line}, ${why})`);\n }\n }\n return { headers: [], text: lines.join(\"\\n\") };\n}\n\nconst SECTION_FINDING =\n /^(?:required )?section (.+?) (is missing|is empty|still contains its guidance text)$/;\nconst REASONS: Readonly<Record<string, string>> = {\n \"is missing\": \"missing\",\n \"is empty\": \"empty\",\n \"still contains its guidance text\": \"guidance\",\n};\n\n/** Lint findings as `Fill in: <heading> (<reason>)`, others as `Draft: <message> [<rule>]`. */\nfunction lintLines(findings: readonly Finding[]): string[] {\n return findings.map((f) => {\n const m = SECTION_FINDING.exec(f.message);\n if (m === null) return `Draft: ${f.message} [${f.rule}]`;\n const [, heading = \"\", what = \"\"] = m;\n return `Fill in: ${heading} (${REASONS[what] ?? what})`;\n });\n}\n\nconst noteLines = (doc: WriteResultJson) => doc.notes.map((n) => `Note: ${n}`);\n\n/** What a write's text needs besides the document. */\nexport interface WriteTextOptions {\n /** The log read after the write, for the headers and how decisions display. */\n readonly read: DecisionsRead;\n /** For `adr_propose`: whether a human must accept. */\n readonly acceptRequiresHuman?: boolean;\n /** For `adr_scope`: the globs before the write. */\n readonly scopeBefore?: readonly string[];\n /** For `adr_update_draft`: the section ids sent. */\n readonly sections?: readonly string[];\n /** The tool, for the refusal's last line. */\n readonly tool: string;\n}\n\n/** A write's text: `Refused:` and the findings, or what was written; then the notes. */\nexport function writeText(doc: WriteResultJson, o: WriteTextOptions): Text {\n const { read } = o;\n const view =\n doc.decision === null ? null : (read.projection.views.get(doc.decision.id) ?? doc.decision);\n const headers = view === null ? [] : [mcpHeader(view, read), ...affectedHeaders(doc, read)];\n if (!doc.ok) {\n const lint =\n doc.findings.length > 0 && doc.findings.every((f) => f.rule.startsWith(\"template/\"));\n const again =\n lint && (o.tool === \"adr_propose\" || o.tool === \"adr_update_draft\")\n ? [`Fill in every required section and call ${o.tool} again.`]\n : [];\n const lines = [\n \"Refused:\",\n ...doc.findings.map(\n (f) => ` ${f.file === null ? \"\" : `${f.file}: `}${f.message} [${f.rule}]`,\n ),\n ...again,\n ...noteLines(doc),\n ];\n return { headers, text: lines.join(\"\\n\") };\n }\n if (view === null) return { headers, text: noteLines(doc).join(\"\\n\") };\n const lines = bodyLines(doc, view, o);\n return { headers, text: [...lines, ...noteLines(doc)].join(\"\\n\") };\n}\n\nfunction bodyLines(doc: WriteResultJson, v: DecisionView, o: WriteTextOptions): string[] {\n const { read } = o;\n const who = named(read, v.id);\n const recorded = doc.commit === null ? [] : [`Committed ${doc.commit.slice(0, 7)}.`];\n switch (doc.command) {\n case \"new\":\n return [\n `Proposed ${v.id}: ${v.title}`,\n ...(v.body_path === null ? [] : [` ${v.body_path}`]),\n ...lintLines(doc.findings),\n ...recorded,\n o.acceptRequiresHuman === true\n ? `Next: ask a human to review and accept it (adr accept ${v.id})`\n : `Next: adr_accept or adr accept ${v.id}`,\n ];\n case \"update\":\n return doc.written.length === 0\n ? [\"Unchanged\"]\n : [\n `Updated the draft of ${who}: ${(o.sections ?? []).join(\", \")}`,\n ...lintLines(doc.findings),\n ...recorded,\n ];\n case \"note\":\n return [`Noted on ${who}`, ...recorded];\n case \"link\": {\n const link = doc.written.length === 0 ? undefined : v.links.at(-1);\n if (link === undefined) return [`Links of ${who} unchanged`];\n return [`Linked ${who} ${link.rel} ${named(read, link.to)}`, ...recorded];\n }\n case \"scope\": {\n const before = new Set(o.scopeBefore ?? []);\n const after = new Set(v.applies_to);\n if (doc.written.length === 0) return [\"unchanged\"];\n return [\n ...v.applies_to.filter((g) => !before.has(g)).map((g) => `+ ${g}`),\n ...[...before].filter((g) => !after.has(g)).map((g) => `- ${g}`),\n `= ${v.applies_to.length === 0 ? \"no globs\" : v.applies_to.join(\", \")}`,\n ...recorded,\n ];\n }\n case \"accept\":\n return [\n `Accepted ${who}: ${v.title}`,\n ...doc.affected.map((a) => `Superseded ${named(read, a.id)}: ${a.title}`),\n ...recorded,\n ];\n case \"reject\":\n return [`Rejected ${who}`, ...recorded];\n case \"withdraw\":\n return [`Withdrawn ${who}`, ...recorded];\n case \"deprecate\":\n return [`Deprecated ${who}`, ...recorded];\n case \"supersede\":\n return [`Superseded ${who} by ${named(read, v.superseded_by ?? \"\")}`, ...recorded];\n default:\n return [`${doc.command} ${who}`, ...recorded];\n }\n}\n\n/** The headers of the decisions a write affected (superseded), other than its own. */\nfunction affectedHeaders(doc: WriteResultJson, read: DecisionsRead): StateHeader[] {\n return doc.affected\n .filter((a) => a.id !== doc.decision?.id)\n .map((a) => mcpHeader(read.projection.views.get(a.id) ?? a, read));\n}\n","import {\n type Attribution,\n eventDir,\n type JsonValue,\n MAX_GLOB_LENGTH,\n UsageError,\n} from \"@nikovirtala/ledger\";\nimport { type McpTool, type McpToolResult, mcpAttribution } from \"@nikovirtala/ledger/mcp\";\nimport { DECISION_STATUSES, type DecisionStatus } from \"../kind.js\";\nimport {\n type DecisionLog,\n type DecisionsRead,\n openDecisionLog,\n readDecisions,\n resolveDecision,\n} from \"../log.js\";\nimport { decisionsFor } from \"../scope.js\";\nimport { searchDecisions } from \"../search.js\";\nimport { readSourceDecisions } from \"../sources.js\";\nimport { listTemplates } from \"../templates/list.js\";\nimport { listDecisions, showDecision } from \"../views.js\";\nimport {\n acceptDecision,\n deprecateDecision,\n linkDecision,\n noteDecision,\n proposeDecision,\n rejectDecision,\n scopeDecision,\n supersedeDecision,\n updateDraft,\n type WriteResultJson,\n withdrawDecision,\n} from \"../write.js\";\nimport { mcpWriteRefusal, type PolicyTool, proposalOwner } from \"./policy.js\";\nimport {\n forText,\n getText,\n listText,\n searchText,\n templatesText,\n type WriteTextOptions,\n writeText,\n} from \"./text.js\";\n\n/** Where `adr mcp` runs: every call opens the log afresh from here (design D2). */\nexport interface AdrMcpEnv {\n readonly cwd: string;\n readonly root: string | null;\n readonly env: NodeJS.ProcessEnv;\n}\n\ntype Schema = Readonly<Record<string, JsonValue>>;\n\nexport const ID: Schema = { type: \"string\", minLength: 1, maxLength: 64 };\nconst TEXT: Schema = { type: \"string\", minLength: 1, maxLength: 65_536 };\nconst SECTIONS: Schema = {\n type: \"object\",\n propertyNames: { type: \"string\", pattern: \"^[a-z][a-z0-9-]*$\", maxLength: 64 },\n additionalProperties: { type: \"string\", maxLength: 65_536 },\n maxProperties: 50,\n};\nconst GLOBS: Schema = {\n type: \"array\",\n items: { type: \"string\", minLength: 1, maxLength: MAX_GLOB_LENGTH },\n maxItems: 200,\n};\n\nconst object = (properties: Record<string, Schema>, required: string[] = []): Schema => ({\n type: \"object\",\n properties,\n ...(required.length === 0 ? {} : { required }),\n additionalProperties: false,\n});\n\nexport const READ = { readOnlyHint: true, openWorldHint: false } as const;\nexport const WRITE = { readOnlyHint: false, destructiveHint: false, openWorldHint: false } as const;\n\n/** The log for one call, opened again so outside edits and `[policy]` changes are seen. */\nexport const openLog = (e: AdrMcpEnv, ref: string | null = null): Promise<DecisionLog> =>\n openDecisionLog({ cwd: e.cwd, root: e.root, ref, gitOptions: { env: e.env } });\n\nconst str = (v: JsonValue | undefined): string | undefined =>\n typeof v === \"string\" ? v : undefined;\nconst strings = (v: JsonValue | undefined): string[] | undefined =>\n Array.isArray(v) ? v.filter((x): x is string => typeof x === \"string\") : undefined;\nconst sectionsOf = (v: JsonValue | undefined): Record<string, string> =>\n typeof v === \"object\" && v !== null && !Array.isArray(v)\n ? Object.fromEntries(\n Object.entries(v).flatMap(([k, x]) => (typeof x === \"string\" ? [[k, x]] : [])),\n )\n : {};\n\nconst doc = (d: unknown): JsonValue => d as JsonValue;\n\n/**\n * A write tool's result: the library's document, and its text rendered from a read of the log\n * after the write.\n */\nasync function writeResult(\n log: DecisionLog,\n d: WriteResultJson,\n o: Omit<WriteTextOptions, \"read\">,\n): Promise<McpToolResult> {\n const read = await readDecisions(log);\n return { document: doc(d), ...writeText(d, { ...o, read }) };\n}\n\n/** The `adr-write/v1` command of each policy tool, as the CLI names it. */\nconst COMMAND: Record<PolicyTool, WriteResultJson[\"command\"]> = {\n adr_scope: \"scope\",\n adr_update_draft: \"update\",\n adr_withdraw: \"withdraw\",\n};\n\n/**\n * The MCP policy step of `adr_scope`, `adr_update_draft` and `adr_withdraw` (design §7.5): the refusal document\n * when the agent may not make this write, else `null`.\n */\nfunction policyRefusal(\n log: DecisionLog,\n read: DecisionsRead,\n tool: PolicyTool,\n id: string,\n attribution: Attribution,\n): WriteResultJson | null {\n const view = read.projection.views.get(id);\n if (view === undefined) return null;\n const finding = mcpWriteRefusal({\n tool,\n view,\n owner: proposalOwner(read, id),\n actor: attribution.actor,\n mcpCanDecide: log.adr.mcpCanDecide,\n display: (x) => read.projection.views.get(x)?.display ?? x,\n eventsDir: eventDir(read.layout, id),\n });\n if (finding === null) return null;\n return {\n format: \"adr-write/v1\",\n command: COMMAND[tool],\n ok: false,\n decision: view,\n affected: [],\n written: [],\n commit: null,\n findings: [finding],\n notes: [...log.notes, ...attribution.notes],\n };\n}\n\n/** The `source` input of `adr_list` and `adr_search`: a `[[sources]]` name, read from the cache. */\nconst SOURCE = { type: \"string\", pattern: \"^[a-z][a-z0-9-]{0,31}$\" } as const;\n\n/** The local log, or with `source` that `[[sources]]` entry's cached log. */\nasync function readFor(e: AdrMcpEnv, source: string | null) {\n const log = await openLog(e);\n return source === null ? readDecisions(log) : readSourceDecisions(log, source);\n}\n\n/** The eleven tools `adr mcp` always lists (design §7.4). */\nexport function alwaysOnTools(e: AdrMcpEnv): McpTool[] {\n return [\n {\n name: \"adr_search\",\n title: \"Search decisions\",\n description:\n \"Full-text search of the decision log: every word must appear in a decision's id, title, body or notes. Returns active (proposed or accepted) decisions unless include_inactive is true, each with its state header and an excerpt.\",\n inputSchema: object(\n {\n query: { type: \"string\", minLength: 1, maxLength: 200 },\n include_inactive: { type: \"boolean\" },\n limit: { type: \"integer\", minimum: 1, maximum: 100 },\n source: SOURCE,\n },\n [\"query\"],\n ),\n annotations: READ,\n async run(input) {\n const read = await readFor(e, str(input.source) ?? null);\n const d = searchDecisions(read, {\n query: str(input.query) ?? \"\",\n includeInactive: input.include_inactive === true,\n limit: typeof input.limit === \"number\" ? input.limit : 10,\n });\n return { document: doc(d), ...searchText(d, read) };\n },\n },\n {\n name: \"adr_get\",\n title: \"Get a decision\",\n description:\n \"One decision with its state header, computed status, supersession chain, effective decision and body. Use this or adr://decision/{id} instead of reading files under docs/adr. A SUPERSEDED or DEPRECATED header means: don't apply it, follow the warning.\",\n inputSchema: object(\n {\n id: ID,\n include_history: { type: \"boolean\" },\n ref: { type: \"string\", minLength: 1, maxLength: 256 },\n },\n [\"id\"],\n ),\n annotations: READ,\n async run(input) {\n const read = await readDecisions(await openLog(e, str(input.ref) ?? null));\n const id = resolveDecision(read, str(input.id) ?? \"\");\n const d = await showDecision(read, id, { history: input.include_history === true });\n return { document: doc(d), ...getText(d, read) };\n },\n },\n {\n name: \"adr_list\",\n title: \"List decisions\",\n description:\n \"All decisions with their computed status, for orientation. Filter by status; limit truncates.\",\n inputSchema: object({\n status: {\n type: \"array\",\n items: { type: \"string\", enum: [...DECISION_STATUSES] },\n uniqueItems: true,\n minItems: 1,\n maxItems: DECISION_STATUSES.length,\n },\n limit: { type: \"integer\", minimum: 1, maximum: 1000 },\n source: SOURCE,\n }),\n annotations: READ,\n async run(input) {\n const read = await readFor(e, str(input.source) ?? null);\n const status = strings(input.status) as DecisionStatus[] | undefined;\n const d = listDecisions(read, {\n ...(status === undefined ? {} : { status }),\n ...(typeof input.limit === \"number\" ? { limit: input.limit } : {}),\n });\n return { document: doc(d), ...listText(d, read) };\n },\n },\n {\n name: \"adr_templates\",\n title: \"List templates\",\n description:\n \"The templates adr_propose can use, with each section's id, heading, whether it is required, and guidance for filling it in.\",\n inputSchema: object({}),\n annotations: READ,\n async run() {\n const d = await listTemplates(await readDecisions(await openLog(e)));\n return { document: doc(d), ...templatesText(d) };\n },\n },\n {\n name: \"adr_propose\",\n title: \"Propose a decision\",\n description:\n \"Propose a decision: give the title and a sections map (section id → markdown) for the template; the tool renders and stages the draft. Lint findings come back in findings: fix them with adr_update_draft. With auto_commit on, an incomplete draft is refused; send every required section. You can't accept your own proposal; tell the user its id.\",\n inputSchema: object(\n {\n title: { type: \"string\", minLength: 1, maxLength: 200 },\n template: { type: \"string\", pattern: \"^[a-z][a-z0-9-]*$\", maxLength: 64 },\n sections: SECTIONS,\n supersedes: { type: \"array\", items: ID, maxItems: 20 },\n },\n [\"title\"],\n ),\n annotations: WRITE,\n async run(input, ctx) {\n const log = await openLog(e);\n const { actor, notes } = await mcpAttribution(log.git, ctx);\n const template = str(input.template);\n const supersedes = strings(input.supersedes);\n const d = await proposeDecision(\n log,\n {\n title: str(input.title) ?? \"\",\n sections: sectionsOf(input.sections),\n actor,\n ...(template === undefined ? {} : { template }),\n ...(supersedes === undefined ? {} : { supersedes }),\n },\n { notes },\n );\n return writeResult(log, d, {\n tool: \"adr_propose\",\n acceptRequiresHuman: log.adr.acceptRequiresHuman,\n });\n },\n },\n {\n name: \"adr_update_draft\",\n title: \"Update a draft\",\n description:\n \"Replace sections of a proposed decision's draft (section id → markdown). Only your own proposals unless mcp_can_decide is on. Returns the lint result. With auto_commit on, an incomplete draft is refused; send every required section.\",\n inputSchema: object({ id: ID, sections: { ...SECTIONS, minProperties: 1 } }, [\n \"id\",\n \"sections\",\n ]),\n annotations: WRITE,\n async run(input, ctx) {\n const log = await openLog(e);\n const read = await readDecisions(log);\n const id = resolveDecision(read, str(input.id) ?? \"\");\n const attribution = await mcpAttribution(log.git, ctx);\n const sections = sectionsOf(input.sections);\n const o = { tool: \"adr_update_draft\", sections: Object.keys(sections) };\n const refused = policyRefusal(log, read, \"adr_update_draft\", id, attribution);\n if (refused !== null) return writeResult(log, refused, o);\n const d = await updateDraft(log, { id, sections }, { notes: attribution.notes });\n return writeResult(log, d, o);\n },\n },\n {\n name: \"adr_note\",\n title: \"Note on a decision\",\n description:\n \"Add a note to a decision in any state. Notes clarify; a changed decision needs a superseding proposal.\",\n inputSchema: object({ id: ID, text: TEXT }, [\"id\", \"text\"]),\n annotations: WRITE,\n async run(input, ctx) {\n const log = await openLog(e);\n const { actor, notes } = await mcpAttribution(log.git, ctx);\n const d = await noteDecision(\n log,\n { id: str(input.id) ?? \"\", text: str(input.text) ?? \"\", actor },\n { notes },\n );\n return writeResult(log, d, { tool: \"adr_note\" });\n },\n },\n {\n name: \"adr_link\",\n title: \"Link decisions\",\n description:\n \"Record a relation (relates-to, refines, depends-on) from one decision to another.\",\n inputSchema: object(\n {\n id: ID,\n to: { type: \"string\", minLength: 1, maxLength: 100 },\n rel: { type: \"string\", enum: [\"relates-to\", \"refines\", \"depends-on\"] },\n },\n [\"id\", \"to\"],\n ),\n annotations: WRITE,\n async run(input, ctx) {\n const log = await openLog(e);\n const { actor, notes } = await mcpAttribution(log.git, ctx);\n const rel = str(input.rel);\n const d = await linkDecision(\n log,\n {\n id: str(input.id) ?? \"\",\n to: str(input.to) ?? \"\",\n actor,\n ...(rel === undefined ? {} : { rel }),\n },\n { notes },\n );\n return writeResult(log, d, { tool: \"adr_link\" });\n },\n },\n {\n name: \"adr_for_path\",\n title: \"Decisions for paths\",\n description:\n \"The decisions that govern each file, from scope globs and code anchors. Inactive ones carry a warning.\",\n inputSchema: object(\n {\n paths: {\n type: \"array\",\n items: { type: \"string\", minLength: 1, maxLength: 4096 },\n minItems: 1,\n maxItems: 100,\n },\n },\n [\"paths\"],\n ),\n annotations: READ,\n async run(input) {\n const log = await openLog(e);\n const read = await readDecisions(log);\n const d = await decisionsFor(read, log, { paths: strings(input.paths) ?? [] });\n return { document: doc(d), ...forText(d, read) };\n },\n },\n {\n name: \"adr_scope\",\n title: \"Scope a decision\",\n description:\n \"Set, add or remove the globs that map a decision to code. Allowed on your own proposals; rescoping someone else's proposal or an accepted or deprecated decision needs mcp_can_decide. If the decision's Scope section would no longer read true, propose a superseding decision instead.\",\n inputSchema: {\n ...object({ id: ID, set: GLOBS, add: GLOBS, remove: GLOBS }, [\"id\"]),\n minProperties: 2,\n },\n inputHint: \"adr_scope needs id and at least one of set, add or remove\",\n annotations: WRITE,\n async run(input, ctx) {\n const log = await openLog(e);\n const read = await readDecisions(log);\n const id = resolveDecision(read, str(input.id) ?? \"\");\n const attribution = await mcpAttribution(log.git, ctx);\n const scopeBefore = read.projection.views.get(id)?.applies_to ?? [];\n const o = { tool: \"adr_scope\", scopeBefore };\n const refused = policyRefusal(log, read, \"adr_scope\", id, attribution);\n if (refused !== null) return writeResult(log, refused, o);\n const set = strings(input.set);\n const op = {\n ...(set === undefined ? {} : { set }),\n add: strings(input.add) ?? [],\n remove: strings(input.remove) ?? [],\n };\n const d = await scopeDecision(\n log,\n { id, op, actor: attribution.actor },\n { notes: attribution.notes },\n );\n return writeResult(log, d, o);\n },\n },\n {\n name: \"adr_withdraw\",\n title: \"Withdraw a proposal\",\n description:\n \"Withdraw a proposed decision, with an optional reason, for example your own proposal when the user decides against it. Withdrawing someone else's proposal needs mcp_can_decide. Only proposals can be withdrawn; an accepted decision needs a superseding proposal.\",\n inputSchema: object({ id: ID, reason: TEXT }, [\"id\"]),\n annotations: WRITE,\n async run(input, ctx) {\n const log = await openLog(e);\n const read = await readDecisions(log);\n const id = resolveDecision(read, str(input.id) ?? \"\");\n const attribution = await mcpAttribution(log.git, ctx);\n const o = { tool: \"adr_withdraw\" };\n const refused = policyRefusal(log, read, \"adr_withdraw\", id, attribution);\n if (refused !== null) return writeResult(log, refused, o);\n const d = await withdrawDecision(\n log,\n { id, reason: str(input.reason) ?? null, actor: attribution.actor },\n { notes: attribution.notes },\n );\n return writeResult(log, d, o);\n },\n },\n ];\n}\n\n/**\n * The log for a decision tool's call. The tool list was fixed at startup, so a call after\n * `mcp_can_decide` was turned off is a usage error telling the user to restart (design §7.3).\n */\nasync function decidingLog(e: AdrMcpEnv): Promise<DecisionLog> {\n const log = await openLog(e);\n if (!log.adr.mcpCanDecide) {\n throw new UsageError(\n `[policy] mcp_can_decide is now false in ${log.configPath ?? \"adr.toml (not present)\"}; restart adr mcp to update its tool list`,\n );\n }\n return log;\n}\n\n/** The four tools `adr mcp` lists only with `[policy] mcp_can_decide = true` (design §7.4). */\nexport function decisionTools(e: AdrMcpEnv): McpTool[] {\n return [\n {\n name: \"adr_accept\",\n title: \"Accept a decision\",\n description:\n \"Accept a proposed decision (lints it, freezes the body, supersedes what it declares). Refused for agents while accept_requires_human is on.\",\n inputSchema: object({ id: ID, copy_scope: { type: \"boolean\" } }, [\"id\"]),\n annotations: WRITE,\n async run(input, ctx) {\n const log = await decidingLog(e);\n const { actor, notes } = await mcpAttribution(log.git, ctx);\n const copyScope =\n input.copy_scope === true ? \"copy\" : input.copy_scope === false ? \"skip\" : \"suggest\";\n const d = await acceptDecision(\n log,\n { id: str(input.id) ?? \"\", actor },\n { notes, copyScope },\n );\n return writeResult(log, d, { tool: \"adr_accept\" });\n },\n },\n {\n name: \"adr_reject\",\n title: \"Reject a decision\",\n description: \"Reject a proposed decision, with a reason.\",\n inputSchema: object({ id: ID, reason: TEXT }, [\"id\", \"reason\"]),\n annotations: WRITE,\n async run(input, ctx) {\n const log = await decidingLog(e);\n const { actor, notes } = await mcpAttribution(log.git, ctx);\n const d = await rejectDecision(\n log,\n { id: str(input.id) ?? \"\", reason: str(input.reason) ?? \"\", actor },\n { notes },\n );\n return writeResult(log, d, { tool: \"adr_reject\" });\n },\n },\n {\n name: \"adr_deprecate\",\n title: \"Deprecate a decision\",\n description: \"Deprecate an accepted decision that nothing replaces, with a reason.\",\n inputSchema: object({ id: ID, reason: TEXT }, [\"id\", \"reason\"]),\n annotations: WRITE,\n async run(input, ctx) {\n const log = await decidingLog(e);\n const { actor, notes } = await mcpAttribution(log.git, ctx);\n const d = await deprecateDecision(\n log,\n { id: str(input.id) ?? \"\", reason: str(input.reason) ?? \"\", actor },\n { notes },\n );\n return writeResult(log, d, { tool: \"adr_deprecate\" });\n },\n },\n {\n name: \"adr_supersede\",\n title: \"Supersede a decision\",\n description: \"Mark an accepted or deprecated decision superseded by an accepted one.\",\n inputSchema: object({ id: ID, by: ID, reason: TEXT }, [\"id\", \"by\"]),\n annotations: WRITE,\n async run(input, ctx) {\n const log = await decidingLog(e);\n const { actor, notes } = await mcpAttribution(log.git, ctx);\n const reason = str(input.reason);\n const d = await supersedeDecision(\n log,\n {\n id: str(input.id) ?? \"\",\n by: str(input.by) ?? \"\",\n actor,\n ...(reason === undefined ? {} : { reason }),\n },\n { notes },\n );\n return writeResult(log, d, { tool: \"adr_supersede\" });\n },\n },\n ];\n}\n","import { UsageError } from \"@nikovirtala/ledger\";\nimport type { McpPrompt } from \"@nikovirtala/ledger/mcp\";\nimport { readDecisions, resolveDecision } from \"../log.js\";\nimport { listTemplates } from \"../templates/list.js\";\nimport { type AdrMcpEnv, openLog } from \"./tools.js\";\n\n/**\n * `adr_draft_from_discussion` (design §7.8): the steps from a discussion to a proposal, with the\n * template's sections spelled out, ending with a human's `adr accept`.\n */\nexport function draftPrompt(e: AdrMcpEnv): McpPrompt {\n return {\n name: \"adr_draft_from_discussion\",\n title: \"Draft a decision from the discussion\",\n description:\n \"Turn the current discussion into a proposed architecture decision, checking the existing ones first.\",\n arguments: [\n { name: \"title\", description: \"Working title of the decision\", required: false },\n {\n name: \"template\",\n description: \"Template name; default [log] default_template\",\n required: false,\n },\n {\n name: \"supersedes\",\n description: \"A decision this proposal replaces: id or number\",\n required: false,\n },\n ],\n async get(args) {\n const read = await readDecisions(await openLog(e));\n const templates = await listTemplates(read);\n const name = args.template ?? templates.default;\n const t = templates.templates.find((x) => x.name === name);\n if (t === undefined)\n throw new UsageError(`unknown template ${name}; adr_templates lists them`);\n const replaced =\n args.supersedes === undefined ? null : resolveDecision(read, args.supersedes);\n const shown = (id: string) => {\n const display = read.projection.views.get(id)?.display ?? id;\n return display === id ? id : `${display} (${id})`;\n };\n const title =\n args.title === undefined\n ? 'a short title that states the decision, such as \"Use PostgreSQL for orders\"'\n : JSON.stringify(args.title);\n return [\n \"Turn the current discussion into an architecture decision proposal with adr.\",\n \"\",\n \"1. Call adr_search with the main subject of the discussion, and adr_for_path for the files it concerns. If an accepted decision already covers this, tell the user which one, and ask whether the proposal should supersede it.\",\n ...(replaced === null\n ? []\n : [\n `1a. The user named ${shown(replaced)} as the decision this replaces; read it with adr_get first.`,\n ]),\n `2. Use the template ${t.name} (version ${t.version}). Its sections:`,\n ...t.sections.map(\n (s) =>\n ` - ${s.id}: ${s.heading}, ${s.required ? \"required\" : \"optional\"}.${s.guidance === null ? \"\" : ` ${s.guidance}`}`,\n ),\n \"3. Fill every required section with facts from the discussion and the code only. Where something wasn't settled, write it as an open question in that section instead of inventing an answer. If the template has an options section, list at least two options with their trade-offs, including those the discussion rejected.\",\n `4. Call adr_propose with the title ${title}, template \"${t.name}\", the sections map${replaced === null ? \"\" : `, and supersedes [\"${replaced}\"]`}.`,\n \"5. If the result has ok: true with findings, fix those sections with adr_update_draft and the new decision's id. If it was refused (ok: false), fill in every section the findings name and call adr_propose again.\",\n \"6. Don't accept the proposal. Tell the user its id, and that they can review it and run: adr accept <id>\",\n ].join(\"\\n\");\n },\n };\n}\n","import { parseOnBehalfOf } from \"@nikovirtala/ledger\";\nimport { type McpServeOptions, serveMcp } from \"@nikovirtala/ledger/mcp\";\nimport { openDecisionLog } from \"../log.js\";\nimport { DECISION_TOOLS, decisionToolsAvailable } from \"./policy.js\";\nimport { draftPrompt } from \"./prompt.js\";\nimport { decisionResource, indexResource } from \"./resources.js\";\nimport { type AdrMcpEnv, alwaysOnTools, decisionTools } from \"./tools.js\";\n\nexport const INSTRUCTIONS =\n \"Architecture decisions in this repository are managed by adr. Decision files don't show their status: read decisions with adr_get or adr://decision/{id}, check adr_for_path and adr_search before changing architecture, and propose changes with adr_propose; a human accepts them.\";\n\n/**\n * `adr mcp` (design §7.2): checks `ARK_ON_BEHALF_OF` and opens the log first, so a bad\n * environment exits 2 before serving, then serves adr's tools over stdio until the client goes.\n */\nexport async function serveAdrMcp(o: {\n readonly cwd: string;\n readonly root: string | null;\n readonly env: NodeJS.ProcessEnv;\n readonly version: string;\n readonly stderr: { write(s: string): void };\n readonly transport?: McpServeOptions[\"transport\"];\n}): Promise<void> {\n parseOnBehalfOf(o.env.ARK_ON_BEHALF_OF);\n const log = await openDecisionLog({ cwd: o.cwd, root: o.root, gitOptions: { env: o.env } });\n const e: AdrMcpEnv = { cwd: o.cwd, root: o.root, env: o.env };\n const decide = decisionToolsAvailable(log.adr);\n const tools = [...alwaysOnTools(e), ...(decide ? decisionTools(e) : [])];\n const unavailable: Record<string, string> = {};\n if (decide && log.adr.acceptRequiresHuman) {\n o.stderr.write(\n \"adr: warning: adr_accept refuses agents while [policy] accept_requires_human is true\\n\",\n );\n }\n if (!decide) {\n const where = log.configPath ?? \"adr.toml (not present)\";\n for (const name of DECISION_TOOLS) {\n unavailable[name] =\n `[policy] mcp_can_decide is false in ${where}; a human decides with the adr CLI, or set it to true and restart adr mcp`;\n }\n }\n await serveMcp(\n {\n name: \"adr\",\n version: o.version,\n instructions: INSTRUCTIONS,\n tools,\n unavailable,\n resources: [indexResource(e)],\n resourceTemplates: [decisionResource(e)],\n prompts: [draftPrompt(e)],\n },\n {\n env: o.env,\n stderr: o.stderr,\n ...(o.transport === undefined ? {} : { transport: o.transport }),\n },\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"server-WidFQzlx.js","names":[],"sources":["../src/mcp/policy.ts","../src/mcp/resources.ts","../src/mcp/text.ts","../src/mcp/tools.ts","../src/mcp/prompt.ts","../src/mcp/server.ts"],"sourcesContent":["import type { Actor, Finding } from \"@nikovirtala/ledger\";\nimport type { AdrConfig } from \"../config.js\";\nimport { adrKind, type DecisionView } from \"../kind.js\";\nimport type { DecisionsRead } from \"../log.js\";\n\n/** The tools that decide; listed only with `[policy] mcp_can_decide = true`. */\nexport const DECISION_TOOLS = [\n \"adr_accept\",\n \"adr_reject\",\n \"adr_deprecate\",\n \"adr_supersede\",\n] as const;\n\n/** Whether `adr mcp` offers the decision tools (design §7.5, Table A). */\nexport function decisionToolsAvailable(adr: AdrConfig): boolean {\n return adr.mcpCanDecide;\n}\n\n/**\n * Who a proposal is for (design D5): its `proposed` event's actor, `on_behalf_of` for an agent\n * and `email` for a human, lower-cased; `null` when the event or the address is missing.\n */\nexport function proposalOwner(read: DecisionsRead, id: string): string | null {\n const proposed = read.folded.subjects\n .get(id)\n ?.applied.find((a) => a.event.type === adrKind.machine.initial.type);\n const actor = proposed?.event.actor;\n if (actor === undefined) return null;\n const owner = actor.kind === \"agent\" ? actor.on_behalf_of : actor.email;\n return typeof owner === \"string\" && owner.trim() !== \"\" ? owner.trim().toLowerCase() : null;\n}\n\n/** The writes `mcpWriteRefusal` judges: the ones whose ownership matters. */\nexport type PolicyTool = \"adr_scope\" | \"adr_update_draft\" | \"adr_withdraw\";\n\n/**\n * The MCP policy (design §7.5, Table B): `null` when the write may go ahead, else the\n * `decision/mcp-cannot-decide` finding. Without `mcp_can_decide` an agent may scope, edit and\n * withdraw only the proposals made for the person it acts for, and rescope no accepted or\n * deprecated decision.\n * Writes the state machine forbids anyway get `null`, so the library refuses them with the real\n * reason.\n */\nexport function mcpWriteRefusal(o: {\n readonly tool: PolicyTool;\n readonly view: DecisionView;\n readonly owner: string | null;\n readonly actor: Actor;\n readonly mcpCanDecide: boolean;\n readonly display: (id: string) => string;\n /** The finding's file when the decision has no body: its events directory. */\n readonly eventsDir: string;\n}): Finding | null {\n const { view } = o;\n if (o.tool === \"adr_scope\" && !adrKind.machine.allowed(view.status, \"scoped\")) return null;\n if (o.tool === \"adr_update_draft\" && view.status !== \"proposed\") return null;\n if (o.tool === \"adr_withdraw\" && !adrKind.machine.allowed(view.status, \"withdrawn\")) return null;\n if (o.mcpCanDecide) return null;\n const me = o.actor.on_behalf_of?.trim().toLowerCase() ?? null;\n if (view.status === \"proposed\" && o.owner !== null && o.owner === me) return null;\n const shown = o.display(view.id);\n const named = shown === view.id ? view.id : `${shown} (${view.id})`;\n const verb = o.tool === \"adr_withdraw\" ? \"withdrawing\" : \"changing\";\n const message =\n view.status === \"proposed\"\n ? `${named} was proposed for ${o.owner ?? \"someone else\"}, and you act for ${o.actor.on_behalf_of ?? \"nobody\"}; ${verb} another person's proposal needs [policy] mcp_can_decide = true. Add a note with adr_note instead.`\n : `${named} is ${view.status}; rescoping it needs [policy] mcp_can_decide = true, because narrowing a scope can switch a decision off. Ask a human to run adr scope ${shown} …, or propose a superseding decision.`;\n return {\n severity: \"error\",\n rule: \"decision/mcp-cannot-decide\",\n message,\n file: view.body_path ?? o.eventsDir,\n line: null,\n subject: view.id,\n kind: adrKind.name,\n };\n}\n","import { renderIndex, resolveSubjectInput, UsageError } from \"@nikovirtala/ledger\";\nimport type { McpResource, McpResourceTemplate } from \"@nikovirtala/ledger/mcp\";\nimport { adrKind } from \"../kind.js\";\nimport { type DecisionsRead, readDecisions, resolveDecision } from \"../log.js\";\nimport { DECISION_INDEX } from \"../log-index.js\";\nimport { showDecision } from \"../views.js\";\nimport { mcpHeader } from \"./text.js\";\nimport { type AdrMcpEnv, openLog } from \"./tools.js\";\n\nconst MAX_ID = 64;\n\n/**\n * Where an MCP client reads a decision: `adr://decision/ADR-0012` when numbered, else\n * `adr://decision/<id>`. The `refer` of every header the MCP texts show.\n */\nexport function decisionUri(read: DecisionsRead): (id: string) => string {\n return (id) => `adr://decision/${read.projection.views.get(id)?.display ?? id}`;\n}\n\n/** `adr://index`: the index table, numbered like every other read (design §7.7). */\nexport function indexResource(e: AdrMcpEnv): McpResource {\n return {\n uri: \"adr://index\",\n name: \"index\",\n title: \"Decision index\",\n description: \"All decisions, grouped by status, with numbers and dates\",\n mimeType: \"text/markdown\",\n async read() {\n const read = await readDecisions(await openLog(e));\n const views = read.projection.views;\n return {\n header: null,\n text: renderIndex(DECISION_INDEX(read.root, views), [...views.values()], read.numbering),\n };\n },\n };\n}\n\n/**\n * `adr://decision/{id}`: the decision's state header, then its body. `{id}` is the id, the number\n * (`12`, `0012`) or `ADR-0012`; an unknown one is not found, a malformed or qualified one is the\n * caller's error.\n */\nexport function decisionResource(e: AdrMcpEnv): McpResourceTemplate {\n return {\n uriTemplate: \"adr://decision/{id}\",\n name: \"decision\",\n title: \"Decision\",\n description:\n \"One decision: its state header, then its body. {id} is the id (k3f9q8a1), the number (12) or ADR-0012\",\n mimeType: \"text/markdown\",\n async read({ id = \"\" }) {\n if (id.length > MAX_ID) {\n throw new UsageError(\n `invalid decision ${JSON.stringify(`${id.slice(0, MAX_ID)}…`)}: an id or number is at most ${MAX_ID} characters`,\n );\n }\n const read = await readDecisions(await openLog(e));\n const r = resolveSubjectInput(id, {\n subjects: new Set(read.folded.subjects.keys()),\n kind: adrKind,\n numbering: read.numbering,\n });\n if (!r.ok && r.reason === \"not-found\") return null;\n const doc = await showDecision(read, resolveDecision(read, id));\n return {\n header: mcpHeader(doc.decision, read),\n text: doc.body === null ? \"(no body file)\\n\" : doc.body,\n };\n },\n };\n}\n","/**\n * The readable text of each MCP tool result (design §7.4, last column). The documents are the\n * CLI's; these texts are MCP's own, and their state headers point at `adr://decision/…`.\n */\nimport {\n type EventEnvelope,\n type Finding,\n renderStateHeader,\n type StateHeader,\n} from \"@nikovirtala/ledger\";\nimport type { McpToolResult } from \"@nikovirtala/ledger/mcp\";\nimport type { DecisionView } from \"../kind.js\";\nimport type { DecisionsRead } from \"../log.js\";\nimport type { DecisionsForJson } from \"../scope.js\";\nimport type { DecisionSearchJson } from \"../search.js\";\nimport type { TemplatesJson } from \"../templates/list.js\";\nimport { type DecisionListJson, type DecisionShowJson, stateHeader } from \"../views.js\";\nimport type { WriteResultJson } from \"../write.js\";\nimport { decisionUri } from \"./resources.js\";\n\ntype Text = Omit<McpToolResult, \"document\">;\n\nconst display = (read: DecisionsRead) => (id: string) =>\n read.projection.views.get(id)?.display ?? id;\n\nfunction named(read: DecisionsRead, id: string): string {\n const shown = display(read)(id);\n return shown === id ? id : `${shown} (${id})`;\n}\n\n/** The decision's state header with MCP's `adr://` references. */\nexport function mcpHeader(view: DecisionView, read: DecisionsRead): StateHeader {\n return stateHeader(view, read, { refer: decisionUri(read) });\n}\n\n/** `adr_search`: each result's header, title and excerpt, then the counts. */\nexport function searchText(doc: DecisionSearchJson, read: DecisionsRead): Text {\n if (doc.results.length === 0) {\n const more =\n doc.inactive_omitted > 0\n ? [`${inactiveLine(doc.inactive_omitted)}; pass include_inactive`]\n : [];\n return { headers: [], text: [\"No decisions match.\", ...more].join(\"\\n\") };\n }\n const lines: string[] = [];\n for (const r of doc.results) {\n lines.push(renderStateHeader(mcpHeader(r.decision, read)).trimEnd());\n lines.push(` ${r.decision.title}`);\n const where = r.matched.filter((f) => f === \"id\" || f === \"title\").join(\" and \");\n lines.push(r.excerpt === null ? ` (${where} match)` : ` ${r.excerpt}`);\n }\n lines.push(`${doc.results.length} of ${doc.total} shown`);\n if (doc.inactive_omitted > 0) {\n lines.push(`${inactiveLine(doc.inactive_omitted)}; pass include_inactive`);\n }\n return { headers: [], text: lines.join(\"\\n\") };\n}\n\nconst inactiveLine = (k: number) =>\n k === 1 ? \"1 inactive decision also matches\" : `${k} inactive decisions also match`;\n\nfunction listOf(read: DecisionsRead, ids: readonly string[]): string {\n return ids.length === 0 ? \"none\" : ids.map((id) => named(read, id)).join(\", \");\n}\n\nfunction historyLines(events: readonly EventEnvelope[]): string[] {\n return events.map((e) => {\n const a = e.actor;\n const who = a.kind === \"agent\" ? `${a.name} (agent for ${a.on_behalf_of})` : a.name;\n const why = typeof e.reason === \"string\" ? ` — ${e.reason}` : \"\";\n return ` ${e.at} ${e.type} ${who}${why}`;\n });\n}\n\n/** `adr_get`: the header, the decision's fields as `adr show` lists them, then the body. */\nexport function getText(doc: DecisionShowJson, read: DecisionsRead): Text {\n const v = doc.decision;\n const lines = [\n `Title: ${v.title}`,\n `Status: ${v.status} (${v.status_at.slice(0, 10)})`,\n `Effective: ${v.effective === null ? \"none (supersession cycle)\" : named(read, v.effective)}`,\n `Chain: ${v.chain.map(display(read)).join(\" → \")}`,\n `Supersedes: ${listOf(read, v.supersedes)}`,\n `Applies to: ${v.applies_to.length === 0 ? \"no globs recorded\" : v.applies_to.join(\", \")}`,\n ];\n if (doc.events !== null) lines.push(\"History:\", ...historyLines(doc.events));\n lines.push(\"\", doc.body === null ? \"(no body file)\" : doc.body.trimEnd());\n return { headers: [mcpHeader(v, read)], text: lines.join(\"\\n\") };\n}\n\n/** `adr_list`: one line per decision. */\nexport function listText(doc: DecisionListJson, read: DecisionsRead): Text {\n if (doc.decisions.length === 0) return { headers: [], text: \"No decisions.\" };\n const lines = doc.decisions.map((v) => {\n const head = v.number === null ? v.id : `${v.display} (${v.id})`;\n const to =\n v.effective !== null && v.effective !== v.id ? ` → ${display(read)(v.effective)}` : \"\";\n return `${head} · ${v.status} · ${v.title}${to}`;\n });\n return { headers: [], text: lines.join(\"\\n\") };\n}\n\n/** `adr_templates`: each template, then its sections. */\nexport function templatesText(doc: TemplatesJson): Text {\n const lines = doc.templates.flatMap((t) => [\n `${t.name} v${t.version} (${t.source})${t.name === doc.default ? \" default\" : \"\"}`,\n ...t.sections.map(\n (s) =>\n ` ${s.id}: ${s.heading} (${s.required ? \"required\" : \"optional\"})${s.guidance === null ? \"\" : ` — ${s.guidance}`}`,\n ),\n ]);\n return { headers: [], text: lines.length === 0 ? \"No templates.\" : lines.join(\"\\n\") };\n}\n\n/** `adr_for_path`: per path, each decision's header and how it matched. */\nexport function forText(doc: DecisionsForJson, read: DecisionsRead): Text {\n const lines: string[] = [];\n for (const p of doc.paths) {\n lines.push(p.tracked ? p.path : `${p.path} (not tracked)`);\n if (p.decisions.length === 0 && p.unresolved.length === 0) lines.push(\" no decisions\");\n for (const d of p.decisions) {\n const view = read.projection.views.get(d.id);\n const h =\n view === undefined\n ? { line: `${named(read, d.id)} · ${d.status}`, warning: d.warning }\n : mcpHeader(view, read);\n lines.push(` ${h.line}`);\n if (h.warning !== null) lines.push(` ${h.warning}`);\n for (const via of d.via) {\n lines.push(\n via.type === \"glob\" ? ` via glob ${via.glob}` : ` via anchor line ${via.line}`,\n );\n }\n }\n for (const u of p.unresolved) {\n const why = u.reason === \"other-log\" ? \"in another log\" : \"not in this log\";\n lines.push(` unresolved: ${u.ref} (line ${u.line}, ${why})`);\n }\n }\n return { headers: [], text: lines.join(\"\\n\") };\n}\n\nconst SECTION_FINDING =\n /^(?:required )?section (.+?) (is missing|is empty|still contains its guidance text)$/;\nconst REASONS: Readonly<Record<string, string>> = {\n \"is missing\": \"missing\",\n \"is empty\": \"empty\",\n \"still contains its guidance text\": \"guidance\",\n};\n\n/** Lint findings as `Fill in: <heading> (<reason>)`, others as `Draft: <message> [<rule>]`. */\nfunction lintLines(findings: readonly Finding[]): string[] {\n return findings.map((f) => {\n const m = SECTION_FINDING.exec(f.message);\n if (m === null) return `Draft: ${f.message} [${f.rule}]`;\n const [, heading = \"\", what = \"\"] = m;\n return `Fill in: ${heading} (${REASONS[what] ?? what})`;\n });\n}\n\nconst noteLines = (doc: WriteResultJson) => doc.notes.map((n) => `Note: ${n}`);\n\n/** What a write's text needs besides the document. */\nexport interface WriteTextOptions {\n /** The log read after the write, for the headers and how decisions display. */\n readonly read: DecisionsRead;\n /** For `adr_propose`: whether a human must accept. */\n readonly acceptRequiresHuman?: boolean;\n /** For `adr_scope`: the globs before the write. */\n readonly scopeBefore?: readonly string[];\n /** For `adr_update_draft`: the section ids sent. */\n readonly sections?: readonly string[];\n /** The tool, for the refusal's last line. */\n readonly tool: string;\n}\n\n/** A write's text: `Refused:` and the findings, or what was written; then the notes. */\nexport function writeText(doc: WriteResultJson, o: WriteTextOptions): Text {\n const { read } = o;\n const view =\n doc.decision === null ? null : (read.projection.views.get(doc.decision.id) ?? doc.decision);\n const headers = view === null ? [] : [mcpHeader(view, read), ...affectedHeaders(doc, read)];\n if (!doc.ok) {\n const lint =\n doc.findings.length > 0 && doc.findings.every((f) => f.rule.startsWith(\"template/\"));\n const again =\n lint && (o.tool === \"adr_propose\" || o.tool === \"adr_update_draft\")\n ? [`Fill in every required section and call ${o.tool} again.`]\n : [];\n const lines = [\n \"Refused:\",\n ...doc.findings.map(\n (f) => ` ${f.file === null ? \"\" : `${f.file}: `}${f.message} [${f.rule}]`,\n ),\n ...again,\n ...noteLines(doc),\n ];\n return { headers, text: lines.join(\"\\n\") };\n }\n if (view === null) return { headers, text: noteLines(doc).join(\"\\n\") };\n const lines = bodyLines(doc, view, o);\n return { headers, text: [...lines, ...noteLines(doc)].join(\"\\n\") };\n}\n\nfunction bodyLines(doc: WriteResultJson, v: DecisionView, o: WriteTextOptions): string[] {\n const { read } = o;\n const who = named(read, v.id);\n const recorded = doc.commit === null ? [] : [`Committed ${doc.commit.slice(0, 7)}.`];\n switch (doc.command) {\n case \"new\":\n return [\n `Proposed ${v.id}: ${v.title}`,\n ...(v.body_path === null ? [] : [` ${v.body_path}`]),\n ...lintLines(doc.findings),\n ...recorded,\n o.acceptRequiresHuman === true\n ? `Next: ask a human to review and accept it (adr accept ${v.id})`\n : `Next: adr_accept or adr accept ${v.id}`,\n ];\n case \"update\":\n return doc.written.length === 0\n ? [\"Unchanged\"]\n : [\n `Updated the draft of ${who}: ${(o.sections ?? []).join(\", \")}`,\n ...lintLines(doc.findings),\n ...recorded,\n ];\n case \"note\":\n return [`Noted on ${who}`, ...recorded];\n case \"link\": {\n const link = doc.written.length === 0 ? undefined : v.links.at(-1);\n if (link === undefined) return [`Links of ${who} unchanged`];\n return [`Linked ${who} ${link.rel} ${named(read, link.to)}`, ...recorded];\n }\n case \"scope\": {\n const before = new Set(o.scopeBefore ?? []);\n const after = new Set(v.applies_to);\n if (doc.written.length === 0) return [\"unchanged\"];\n return [\n ...v.applies_to.filter((g) => !before.has(g)).map((g) => `+ ${g}`),\n ...[...before].filter((g) => !after.has(g)).map((g) => `- ${g}`),\n `= ${v.applies_to.length === 0 ? \"no globs\" : v.applies_to.join(\", \")}`,\n ...recorded,\n ];\n }\n case \"accept\":\n return [\n `Accepted ${who}: ${v.title}`,\n ...doc.affected.map((a) => `Superseded ${named(read, a.id)}: ${a.title}`),\n ...recorded,\n ];\n case \"reject\":\n return [`Rejected ${who}`, ...recorded];\n case \"withdraw\":\n return [`Withdrawn ${who}`, ...recorded];\n case \"deprecate\":\n return [`Deprecated ${who}`, ...recorded];\n case \"supersede\":\n return [`Superseded ${who} by ${named(read, v.superseded_by ?? \"\")}`, ...recorded];\n default:\n return [`${doc.command} ${who}`, ...recorded];\n }\n}\n\n/** The headers of the decisions a write affected (superseded), other than its own. */\nfunction affectedHeaders(doc: WriteResultJson, read: DecisionsRead): StateHeader[] {\n return doc.affected\n .filter((a) => a.id !== doc.decision?.id)\n .map((a) => mcpHeader(read.projection.views.get(a.id) ?? a, read));\n}\n","import {\n type Attribution,\n eventDir,\n type JsonValue,\n MAX_GLOB_LENGTH,\n UsageError,\n} from \"@nikovirtala/ledger\";\nimport { type McpTool, type McpToolResult, mcpAttribution } from \"@nikovirtala/ledger/mcp\";\nimport { DECISION_STATUSES, type DecisionStatus } from \"../kind.js\";\nimport {\n type DecisionLog,\n type DecisionsRead,\n openDecisionLog,\n readDecisions,\n resolveDecision,\n} from \"../log.js\";\nimport { decisionsFor } from \"../scope.js\";\nimport { searchDecisions } from \"../search.js\";\nimport { readSourceDecisions } from \"../sources.js\";\nimport { listTemplates } from \"../templates/list.js\";\nimport { listDecisions, showDecision } from \"../views.js\";\nimport {\n acceptDecision,\n deprecateDecision,\n linkDecision,\n noteDecision,\n proposeDecision,\n rejectDecision,\n scopeDecision,\n supersedeDecision,\n updateDraft,\n type WriteResultJson,\n withdrawDecision,\n} from \"../write.js\";\nimport { mcpWriteRefusal, type PolicyTool, proposalOwner } from \"./policy.js\";\nimport {\n forText,\n getText,\n listText,\n searchText,\n templatesText,\n type WriteTextOptions,\n writeText,\n} from \"./text.js\";\n\n/** Where `adr mcp` runs: every call opens the log afresh from here (design D2). */\nexport interface AdrMcpEnv {\n readonly cwd: string;\n readonly root: string | null;\n readonly env: NodeJS.ProcessEnv;\n}\n\ntype Schema = Readonly<Record<string, JsonValue>>;\n\nexport const ID: Schema = { type: \"string\", minLength: 1, maxLength: 64 };\nconst TEXT: Schema = { type: \"string\", minLength: 1, maxLength: 65_536 };\nconst SECTIONS: Schema = {\n type: \"object\",\n propertyNames: { type: \"string\", pattern: \"^[a-z][a-z0-9-]*$\", maxLength: 64 },\n additionalProperties: { type: \"string\", maxLength: 65_536 },\n maxProperties: 50,\n};\nconst GLOBS: Schema = {\n type: \"array\",\n items: { type: \"string\", minLength: 1, maxLength: MAX_GLOB_LENGTH },\n maxItems: 200,\n};\n\nconst object = (properties: Record<string, Schema>, required: string[] = []): Schema => ({\n type: \"object\",\n properties,\n ...(required.length === 0 ? {} : { required }),\n additionalProperties: false,\n});\n\nexport const READ = { readOnlyHint: true, openWorldHint: false } as const;\nexport const WRITE = { readOnlyHint: false, destructiveHint: false, openWorldHint: false } as const;\n\n/** The log for one call, opened again so outside edits and `[policy]` changes are seen. */\nexport const openLog = (e: AdrMcpEnv, ref: string | null = null): Promise<DecisionLog> =>\n openDecisionLog({ cwd: e.cwd, root: e.root, ref, gitOptions: { env: e.env } });\n\nconst str = (v: JsonValue | undefined): string | undefined =>\n typeof v === \"string\" ? v : undefined;\nconst strings = (v: JsonValue | undefined): string[] | undefined =>\n Array.isArray(v) ? v.filter((x): x is string => typeof x === \"string\") : undefined;\nconst sectionsOf = (v: JsonValue | undefined): Record<string, string> =>\n typeof v === \"object\" && v !== null && !Array.isArray(v)\n ? Object.fromEntries(\n Object.entries(v).flatMap(([k, x]) => (typeof x === \"string\" ? [[k, x]] : [])),\n )\n : {};\n\nconst doc = (d: unknown): JsonValue => d as JsonValue;\n\n/**\n * A write tool's result: the library's document, and its text rendered from a read of the log\n * after the write.\n */\nasync function writeResult(\n log: DecisionLog,\n d: WriteResultJson,\n o: Omit<WriteTextOptions, \"read\">,\n): Promise<McpToolResult> {\n const read = await readDecisions(log);\n return { document: doc(d), ...writeText(d, { ...o, read }) };\n}\n\n/** The `adr-write/v1` command of each policy tool, as the CLI names it. */\nconst COMMAND: Record<PolicyTool, WriteResultJson[\"command\"]> = {\n adr_scope: \"scope\",\n adr_update_draft: \"update\",\n adr_withdraw: \"withdraw\",\n};\n\n/**\n * The MCP policy step of `adr_scope`, `adr_update_draft` and `adr_withdraw` (design §7.5): the refusal document\n * when the agent may not make this write, else `null`.\n */\nfunction policyRefusal(\n log: DecisionLog,\n read: DecisionsRead,\n tool: PolicyTool,\n id: string,\n attribution: Attribution,\n): WriteResultJson | null {\n const view = read.projection.views.get(id);\n if (view === undefined) return null;\n const finding = mcpWriteRefusal({\n tool,\n view,\n owner: proposalOwner(read, id),\n actor: attribution.actor,\n mcpCanDecide: log.adr.mcpCanDecide,\n display: (x) => read.projection.views.get(x)?.display ?? x,\n eventsDir: eventDir(read.layout, id),\n });\n if (finding === null) return null;\n return {\n format: \"adr-write/v1\",\n command: COMMAND[tool],\n ok: false,\n decision: view,\n affected: [],\n written: [],\n commit: null,\n findings: [finding],\n notes: [...log.notes, ...attribution.notes],\n };\n}\n\n/** The `source` input of `adr_list` and `adr_search`: a `[[sources]]` name, read from the cache. */\nconst SOURCE = { type: \"string\", pattern: \"^[a-z][a-z0-9-]{0,31}$\" } as const;\n\n/** The local log, or with `source` that `[[sources]]` entry's cached log. */\nasync function readFor(e: AdrMcpEnv, source: string | null) {\n const log = await openLog(e);\n return source === null ? readDecisions(log) : readSourceDecisions(log, source);\n}\n\n/** The eleven tools `adr mcp` always lists (design §7.4). */\nexport function alwaysOnTools(e: AdrMcpEnv): McpTool[] {\n return [\n {\n name: \"adr_search\",\n title: \"Search decisions\",\n description:\n \"Full-text search of the decision log: every word must appear in a decision's id, title, body or notes. Returns active (proposed or accepted) decisions unless include_inactive is true, each with its state header and an excerpt.\",\n inputSchema: object(\n {\n query: { type: \"string\", minLength: 1, maxLength: 200 },\n include_inactive: { type: \"boolean\" },\n limit: { type: \"integer\", minimum: 1, maximum: 100 },\n source: SOURCE,\n },\n [\"query\"],\n ),\n annotations: READ,\n async run(input) {\n const read = await readFor(e, str(input.source) ?? null);\n const d = searchDecisions(read, {\n query: str(input.query) ?? \"\",\n includeInactive: input.include_inactive === true,\n limit: typeof input.limit === \"number\" ? input.limit : 10,\n });\n return { document: doc(d), ...searchText(d, read) };\n },\n },\n {\n name: \"adr_get\",\n title: \"Get a decision\",\n description:\n \"One decision with its state header, computed status, supersession chain, effective decision and body. Use this or adr://decision/{id} instead of reading files under docs/adr. A SUPERSEDED or DEPRECATED header means: don't apply it, follow the warning.\",\n inputSchema: object(\n {\n id: ID,\n include_history: { type: \"boolean\" },\n ref: { type: \"string\", minLength: 1, maxLength: 256 },\n },\n [\"id\"],\n ),\n annotations: READ,\n async run(input) {\n const read = await readDecisions(await openLog(e, str(input.ref) ?? null));\n const id = resolveDecision(read, str(input.id) ?? \"\");\n const d = await showDecision(read, id, { history: input.include_history === true });\n return { document: doc(d), ...getText(d, read) };\n },\n },\n {\n name: \"adr_list\",\n title: \"List decisions\",\n description:\n \"All decisions with their computed status, for orientation. Filter by status; limit truncates.\",\n inputSchema: object({\n status: {\n type: \"array\",\n items: { type: \"string\", enum: [...DECISION_STATUSES] },\n uniqueItems: true,\n minItems: 1,\n maxItems: DECISION_STATUSES.length,\n },\n limit: { type: \"integer\", minimum: 1, maximum: 1000 },\n source: SOURCE,\n }),\n annotations: READ,\n async run(input) {\n const read = await readFor(e, str(input.source) ?? null);\n const status = strings(input.status) as DecisionStatus[] | undefined;\n const d = listDecisions(read, {\n ...(status === undefined ? {} : { status }),\n ...(typeof input.limit === \"number\" ? { limit: input.limit } : {}),\n });\n return { document: doc(d), ...listText(d, read) };\n },\n },\n {\n name: \"adr_templates\",\n title: \"List templates\",\n description:\n \"The templates adr_propose can use, with each section's id, heading, whether it is required, and guidance for filling it in.\",\n inputSchema: object({}),\n annotations: READ,\n async run() {\n const d = await listTemplates(await readDecisions(await openLog(e)));\n return { document: doc(d), ...templatesText(d) };\n },\n },\n {\n name: \"adr_propose\",\n title: \"Propose a decision\",\n description:\n \"Propose a decision: give the title and a sections map (section id → markdown) for the template; the tool renders and stages the draft. Lint findings come back in findings: fix them with adr_update_draft. With auto_commit on, an incomplete draft is refused; send every required section. You can't accept your own proposal; tell the user its id.\",\n inputSchema: object(\n {\n title: { type: \"string\", minLength: 1, maxLength: 200 },\n template: { type: \"string\", pattern: \"^[a-z][a-z0-9-]*$\", maxLength: 64 },\n sections: SECTIONS,\n supersedes: { type: \"array\", items: ID, maxItems: 20 },\n },\n [\"title\"],\n ),\n annotations: WRITE,\n async run(input, ctx) {\n const log = await openLog(e);\n const { actor, notes } = await mcpAttribution(log.git, ctx);\n const template = str(input.template);\n const supersedes = strings(input.supersedes);\n const d = await proposeDecision(\n log,\n {\n title: str(input.title) ?? \"\",\n sections: sectionsOf(input.sections),\n actor,\n ...(template === undefined ? {} : { template }),\n ...(supersedes === undefined ? {} : { supersedes }),\n },\n { notes },\n );\n return writeResult(log, d, {\n tool: \"adr_propose\",\n acceptRequiresHuman: log.adr.acceptRequiresHuman,\n });\n },\n },\n {\n name: \"adr_update_draft\",\n title: \"Update a draft\",\n description:\n \"Replace sections of a proposed decision's draft (section id → markdown). Only your own proposals unless mcp_can_decide is on. Returns the lint result. With auto_commit on, an incomplete draft is refused; send every required section.\",\n inputSchema: object({ id: ID, sections: { ...SECTIONS, minProperties: 1 } }, [\n \"id\",\n \"sections\",\n ]),\n annotations: WRITE,\n async run(input, ctx) {\n const log = await openLog(e);\n const read = await readDecisions(log);\n const id = resolveDecision(read, str(input.id) ?? \"\");\n const attribution = await mcpAttribution(log.git, ctx);\n const sections = sectionsOf(input.sections);\n const o = { tool: \"adr_update_draft\", sections: Object.keys(sections) };\n const refused = policyRefusal(log, read, \"adr_update_draft\", id, attribution);\n if (refused !== null) return writeResult(log, refused, o);\n const d = await updateDraft(log, { id, sections }, { notes: attribution.notes });\n return writeResult(log, d, o);\n },\n },\n {\n name: \"adr_note\",\n title: \"Note on a decision\",\n description:\n \"Add a note to a decision in any state. Notes clarify; a changed decision needs a superseding proposal.\",\n inputSchema: object({ id: ID, text: TEXT }, [\"id\", \"text\"]),\n annotations: WRITE,\n async run(input, ctx) {\n const log = await openLog(e);\n const { actor, notes } = await mcpAttribution(log.git, ctx);\n const d = await noteDecision(\n log,\n { id: str(input.id) ?? \"\", text: str(input.text) ?? \"\", actor },\n { notes },\n );\n return writeResult(log, d, { tool: \"adr_note\" });\n },\n },\n {\n name: \"adr_link\",\n title: \"Link decisions\",\n description:\n \"Record a relation (relates-to, refines, depends-on) from one decision to another.\",\n inputSchema: object(\n {\n id: ID,\n to: { type: \"string\", minLength: 1, maxLength: 100 },\n rel: { type: \"string\", enum: [\"relates-to\", \"refines\", \"depends-on\"] },\n },\n [\"id\", \"to\"],\n ),\n annotations: WRITE,\n async run(input, ctx) {\n const log = await openLog(e);\n const { actor, notes } = await mcpAttribution(log.git, ctx);\n const rel = str(input.rel);\n const d = await linkDecision(\n log,\n {\n id: str(input.id) ?? \"\",\n to: str(input.to) ?? \"\",\n actor,\n ...(rel === undefined ? {} : { rel }),\n },\n { notes },\n );\n return writeResult(log, d, { tool: \"adr_link\" });\n },\n },\n {\n name: \"adr_for_path\",\n title: \"Decisions for paths\",\n description:\n \"The decisions that govern each file, from scope globs and code anchors. Inactive ones carry a warning.\",\n inputSchema: object(\n {\n paths: {\n type: \"array\",\n items: { type: \"string\", minLength: 1, maxLength: 4096 },\n minItems: 1,\n maxItems: 100,\n },\n },\n [\"paths\"],\n ),\n annotations: READ,\n async run(input) {\n const log = await openLog(e);\n const read = await readDecisions(log);\n const d = await decisionsFor(read, log, { paths: strings(input.paths) ?? [] });\n return { document: doc(d), ...forText(d, read) };\n },\n },\n {\n name: \"adr_scope\",\n title: \"Scope a decision\",\n description:\n \"Set, add or remove the globs that map a decision to code. Allowed on your own proposals; rescoping someone else's proposal or an accepted or deprecated decision needs mcp_can_decide. If the decision's Scope section would no longer read true, propose a superseding decision instead.\",\n inputSchema: {\n ...object({ id: ID, set: GLOBS, add: GLOBS, remove: GLOBS }, [\"id\"]),\n minProperties: 2,\n },\n inputHint: \"adr_scope needs id and at least one of set, add or remove\",\n annotations: WRITE,\n async run(input, ctx) {\n const log = await openLog(e);\n const read = await readDecisions(log);\n const id = resolveDecision(read, str(input.id) ?? \"\");\n const attribution = await mcpAttribution(log.git, ctx);\n const scopeBefore = read.projection.views.get(id)?.applies_to ?? [];\n const o = { tool: \"adr_scope\", scopeBefore };\n const refused = policyRefusal(log, read, \"adr_scope\", id, attribution);\n if (refused !== null) return writeResult(log, refused, o);\n const set = strings(input.set);\n const op = {\n ...(set === undefined ? {} : { set }),\n add: strings(input.add) ?? [],\n remove: strings(input.remove) ?? [],\n };\n const d = await scopeDecision(\n log,\n { id, op, actor: attribution.actor },\n { notes: attribution.notes },\n );\n return writeResult(log, d, o);\n },\n },\n {\n name: \"adr_withdraw\",\n title: \"Withdraw a proposal\",\n description:\n \"Withdraw a proposed decision, with an optional reason, for example your own proposal when the user decides against it. Withdrawing someone else's proposal needs mcp_can_decide. Only proposals can be withdrawn; an accepted decision needs a superseding proposal.\",\n inputSchema: object({ id: ID, reason: TEXT }, [\"id\"]),\n annotations: WRITE,\n async run(input, ctx) {\n const log = await openLog(e);\n const read = await readDecisions(log);\n const id = resolveDecision(read, str(input.id) ?? \"\");\n const attribution = await mcpAttribution(log.git, ctx);\n const o = { tool: \"adr_withdraw\" };\n const refused = policyRefusal(log, read, \"adr_withdraw\", id, attribution);\n if (refused !== null) return writeResult(log, refused, o);\n const d = await withdrawDecision(\n log,\n { id, reason: str(input.reason) ?? null, actor: attribution.actor },\n { notes: attribution.notes },\n );\n return writeResult(log, d, o);\n },\n },\n ];\n}\n\n/**\n * The log for a decision tool's call. The tool list was fixed at startup, so a call after\n * `mcp_can_decide` was turned off is a usage error telling the user to restart (design §7.3).\n */\nasync function decidingLog(e: AdrMcpEnv): Promise<DecisionLog> {\n const log = await openLog(e);\n if (!log.adr.mcpCanDecide) {\n throw new UsageError(\n `[policy] mcp_can_decide is now false in ${log.configPath ?? \"adr.toml (not present)\"}; restart adr mcp to update its tool list`,\n );\n }\n return log;\n}\n\n/** The four tools `adr mcp` lists only with `[policy] mcp_can_decide = true` (design §7.4). */\nexport function decisionTools(e: AdrMcpEnv): McpTool[] {\n return [\n {\n name: \"adr_accept\",\n title: \"Accept a decision\",\n description:\n \"Accept a proposed decision (lints it, freezes the body, supersedes what it declares). Refused for agents while accept_requires_human is on.\",\n inputSchema: object({ id: ID, copy_scope: { type: \"boolean\" } }, [\"id\"]),\n annotations: WRITE,\n async run(input, ctx) {\n const log = await decidingLog(e);\n const { actor, notes } = await mcpAttribution(log.git, ctx);\n const copyScope =\n input.copy_scope === true ? \"copy\" : input.copy_scope === false ? \"skip\" : \"suggest\";\n const d = await acceptDecision(\n log,\n { id: str(input.id) ?? \"\", actor },\n { notes, copyScope },\n );\n return writeResult(log, d, { tool: \"adr_accept\" });\n },\n },\n {\n name: \"adr_reject\",\n title: \"Reject a decision\",\n description: \"Reject a proposed decision, with a reason.\",\n inputSchema: object({ id: ID, reason: TEXT }, [\"id\", \"reason\"]),\n annotations: WRITE,\n async run(input, ctx) {\n const log = await decidingLog(e);\n const { actor, notes } = await mcpAttribution(log.git, ctx);\n const d = await rejectDecision(\n log,\n { id: str(input.id) ?? \"\", reason: str(input.reason) ?? \"\", actor },\n { notes },\n );\n return writeResult(log, d, { tool: \"adr_reject\" });\n },\n },\n {\n name: \"adr_deprecate\",\n title: \"Deprecate a decision\",\n description: \"Deprecate an accepted decision that nothing replaces, with a reason.\",\n inputSchema: object({ id: ID, reason: TEXT }, [\"id\", \"reason\"]),\n annotations: WRITE,\n async run(input, ctx) {\n const log = await decidingLog(e);\n const { actor, notes } = await mcpAttribution(log.git, ctx);\n const d = await deprecateDecision(\n log,\n { id: str(input.id) ?? \"\", reason: str(input.reason) ?? \"\", actor },\n { notes },\n );\n return writeResult(log, d, { tool: \"adr_deprecate\" });\n },\n },\n {\n name: \"adr_supersede\",\n title: \"Supersede a decision\",\n description: \"Mark an accepted or deprecated decision superseded by an accepted one.\",\n inputSchema: object({ id: ID, by: ID, reason: TEXT }, [\"id\", \"by\"]),\n annotations: WRITE,\n async run(input, ctx) {\n const log = await decidingLog(e);\n const { actor, notes } = await mcpAttribution(log.git, ctx);\n const reason = str(input.reason);\n const d = await supersedeDecision(\n log,\n {\n id: str(input.id) ?? \"\",\n by: str(input.by) ?? \"\",\n actor,\n ...(reason === undefined ? {} : { reason }),\n },\n { notes },\n );\n return writeResult(log, d, { tool: \"adr_supersede\" });\n },\n },\n ];\n}\n","import { UsageError } from \"@nikovirtala/ledger\";\nimport type { McpPrompt } from \"@nikovirtala/ledger/mcp\";\nimport { readDecisions, resolveDecision } from \"../log.js\";\nimport { listTemplates } from \"../templates/list.js\";\nimport { type AdrMcpEnv, openLog } from \"./tools.js\";\n\n/**\n * `adr_draft_from_discussion` (design §7.8): the steps from a discussion to a proposal, with the\n * template's sections spelled out, ending with a human's `adr accept`.\n */\nexport function draftPrompt(e: AdrMcpEnv): McpPrompt {\n return {\n name: \"adr_draft_from_discussion\",\n title: \"Draft a decision from the discussion\",\n description:\n \"Turn the current discussion into a proposed architecture decision, checking the existing ones first.\",\n arguments: [\n { name: \"title\", description: \"Working title of the decision\", required: false },\n {\n name: \"template\",\n description: \"Template name; default [log] default_template\",\n required: false,\n },\n {\n name: \"supersedes\",\n description: \"A decision this proposal replaces: id or number\",\n required: false,\n },\n ],\n async get(args) {\n const read = await readDecisions(await openLog(e));\n const templates = await listTemplates(read);\n const name = args.template ?? templates.default;\n const t = templates.templates.find((x) => x.name === name);\n if (t === undefined)\n throw new UsageError(`unknown template ${name}; adr_templates lists them`);\n const replaced =\n args.supersedes === undefined ? null : resolveDecision(read, args.supersedes);\n const shown = (id: string) => {\n const display = read.projection.views.get(id)?.display ?? id;\n return display === id ? id : `${display} (${id})`;\n };\n const title =\n args.title === undefined\n ? 'a short title that states the decision, such as \"Use PostgreSQL for orders\"'\n : JSON.stringify(args.title);\n return [\n \"Turn the current discussion into an architecture decision proposal with adr.\",\n \"\",\n \"1. Call adr_search with the main subject of the discussion, and adr_for_path for the files it concerns. If an accepted decision already covers this, tell the user which one, and ask whether the proposal should supersede it.\",\n ...(replaced === null\n ? []\n : [\n `1a. The user named ${shown(replaced)} as the decision this replaces; read it with adr_get first.`,\n ]),\n `2. Use the template ${t.name} (version ${t.version}). Its sections:`,\n ...t.sections.map(\n (s) =>\n ` - ${s.id}: ${s.heading}, ${s.required ? \"required\" : \"optional\"}.${s.guidance === null ? \"\" : ` ${s.guidance}`}`,\n ),\n \"3. Fill every required section with facts from the discussion and the code only. Where something wasn't settled, write it as an open question in that section instead of inventing an answer. If the template has an options section, list at least two options with their trade-offs, including those the discussion rejected.\",\n `4. Call adr_propose with the title ${title}, template \"${t.name}\", the sections map${replaced === null ? \"\" : `, and supersedes [\"${replaced}\"]`}.`,\n \"5. If the result has ok: true with findings, fix those sections with adr_update_draft and the new decision's id. If it was refused (ok: false), fill in every section the findings name and call adr_propose again.\",\n \"6. Don't accept the proposal. Tell the user its id, and that they can review it and run: adr accept <id>\",\n ].join(\"\\n\");\n },\n };\n}\n","import { parseOnBehalfOf } from \"@nikovirtala/ledger\";\nimport { type McpServeOptions, serveMcp } from \"@nikovirtala/ledger/mcp\";\nimport { openDecisionLog } from \"../log.js\";\nimport { DECISION_TOOLS, decisionToolsAvailable } from \"./policy.js\";\nimport { draftPrompt } from \"./prompt.js\";\nimport { decisionResource, indexResource } from \"./resources.js\";\nimport { type AdrMcpEnv, alwaysOnTools, decisionTools } from \"./tools.js\";\n\nexport const INSTRUCTIONS =\n \"Architecture decisions in this repository are managed by adr. Decision files don't show their status: read decisions with adr_get or adr://decision/{id}, check adr_for_path and adr_search before changing architecture, and propose changes with adr_propose; a human accepts them.\";\n\n/**\n * `adr mcp` (design §7.2): checks `ARK_ON_BEHALF_OF` and opens the log first, so a bad\n * environment exits 2 before serving, then serves adr's tools over stdio until the client goes.\n */\nexport async function serveAdrMcp(o: {\n readonly cwd: string;\n readonly root: string | null;\n readonly env: NodeJS.ProcessEnv;\n readonly version: string;\n readonly stderr: { write(s: string): void };\n readonly transport?: McpServeOptions[\"transport\"];\n}): Promise<void> {\n parseOnBehalfOf(o.env.ARK_ON_BEHALF_OF);\n const log = await openDecisionLog({ cwd: o.cwd, root: o.root, gitOptions: { env: o.env } });\n const e: AdrMcpEnv = { cwd: o.cwd, root: o.root, env: o.env };\n const decide = decisionToolsAvailable(log.adr);\n const tools = [...alwaysOnTools(e), ...(decide ? decisionTools(e) : [])];\n const unavailable: Record<string, string> = {};\n if (decide && log.adr.acceptRequiresHuman) {\n o.stderr.write(\n \"adr: warning: adr_accept refuses agents while [policy] accept_requires_human is true\\n\",\n );\n }\n if (!decide) {\n const where = log.configPath ?? \"adr.toml (not present)\";\n for (const name of DECISION_TOOLS) {\n unavailable[name] =\n `[policy] mcp_can_decide is false in ${where}; a human decides with the adr CLI, or set it to true and restart adr mcp`;\n }\n }\n await serveMcp(\n {\n name: \"adr\",\n version: o.version,\n instructions: INSTRUCTIONS,\n tools,\n unavailable,\n resources: [indexResource(e)],\n resourceTemplates: [decisionResource(e)],\n prompts: [draftPrompt(e)],\n },\n {\n env: o.env,\n stderr: o.stderr,\n ...(o.transport === undefined ? {} : { transport: o.transport }),\n },\n );\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nikovirtala/adr",
3
- "version": "0.5.2",
3
+ "version": "0.5.3",
4
4
  "description": "Architecture decision records kept as event logs in git: frozen bodies, computed status and supersession chains. CLI and library.",
5
5
  "keywords": [
6
6
  "adr",
@@ -45,7 +45,7 @@
45
45
  "provenance": true
46
46
  },
47
47
  "dependencies": {
48
- "@nikovirtala/ledger": "^0.9.0"
48
+ "@nikovirtala/ledger": "^0.10.0"
49
49
  },
50
50
  "devDependencies": {
51
51
  "@modelcontextprotocol/sdk": "1.32.2"
@@ -1 +0,0 @@
1
- {"version":3,"file":"init-Bw0PZLnR.js","names":[],"sources":["../src/verify.ts","../src/hooks.ts","../src/skill.ts","../src/init.ts"],"sourcesContent":["import {\n anchorCheck,\n type Check,\n type CheckContext,\n type Finding,\n type FoldedLogOf,\n finding,\n foldChecks,\n type GovernedChange,\n gitTemplates,\n governedChanges,\n narrowedScopes,\n projectLog,\n type SourceStatus,\n scopeGlobCheck,\n sourceFindings,\n templateHistoryRef,\n type VerifyMode,\n verifyLog,\n} from \"@nikovirtala/ledger\";\nimport { adrKind, type DecisionView } from \"./kind.js\";\nimport { type DecisionLog, numberDecisions } from \"./log.js\";\nimport { decisionIndexCheck } from \"./log-index.js\";\nimport { type DecisionSources, readDecisionSources } from \"./sources.js\";\n\n/** At most this many paths are named in a `decision/scope-narrowed` message. */\nconst NARROWED_PATHS = 3;\n\n/** The head's decision views with the read's numbering, for the displays in messages. */\nasync function headViews(\n log: DecisionLog,\n ctx: CheckContext,\n): Promise<ReadonlyMap<string, DecisionView>> {\n const head = ctx.folded?.head;\n if (head === undefined) return new Map();\n return projectLog(adrKind, head as FoldedLogOf<typeof adrKind>, {\n numbering: await numberDecisions(log),\n }).views;\n}\n\n/**\n * `decision/governed-by-inactive` (`[verify] governed_by_inactive`, default warning): a changed\n * code file that a superseded or deprecated decision governs, by glob or anchor (01:366).\n */\nfunction governedByInactive(log: DecisionLog): Check {\n return {\n id: \"decision-governed-by-inactive\",\n async run(ctx) {\n const changes = await governedChanges(ctx, {\n keyword: log.adr.anchorKeyword,\n exclude: log.adr.anchorExclude,\n statuses: [\"superseded\", \"deprecated\"],\n });\n if (changes.length === 0) return [];\n const views = await headViews(log, ctx);\n const display = (id: string) => views.get(id)?.display ?? id;\n const message = (c: GovernedChange): string => {\n const what = `${c.path} is governed by ${display(c.subject)}`;\n if (c.status === \"deprecated\") {\n return `${what}, which is deprecated; check whether the change still needs it`;\n }\n const next = views.get(c.subject)?.superseded_by ?? null;\n return next === null\n ? `${what}, which is superseded; check the change against its successor`\n : `${what}, which is superseded by ${display(next)}; check the change against ${display(next)}`;\n };\n return changes.map((c) =>\n finding({\n severity: log.adr.governedByInactive,\n rule: \"decision/governed-by-inactive\",\n message: message(c),\n file: c.path,\n subject: c.subject,\n }),\n );\n },\n };\n}\n\n/**\n * `decision/scope-narrowed` (warning): an accepted decision whose new scope stops covering files\n * that still exist (01:367), which calls for a check against its Scope section.\n */\nfunction scopeNarrowed(log: DecisionLog): Check {\n return {\n id: \"decision-scope-narrowed\",\n async run(ctx) {\n const narrowed = await narrowedScopes(ctx, { statuses: [\"accepted\"] });\n if (narrowed.length === 0) return [];\n const views = await headViews(log, ctx);\n return narrowed.map((n) => {\n const count = n.lost.length;\n const files = count === 1 ? \"1 file that still exists\" : `${count} files that still exist`;\n const named = n.lost.slice(0, NARROWED_PATHS).join(\", \");\n const more = count > NARROWED_PATHS ? \", …\" : \"\";\n return finding({\n severity: \"warning\",\n rule: \"decision/scope-narrowed\",\n message: `${views.get(n.subject)?.display ?? n.subject}'s scope no longer covers ${files} (${named}${more}); check the change against its Scope section`,\n file: n.file,\n subject: n.subject,\n });\n });\n },\n };\n}\n\n/**\n * Every check for the log: ledger's mechanical and fold checks with adr's actor policy, template\n * lint against the templates in the head tree and, for older versions, the history of\n * `historyRef`, the scope-glob and anchor checks, and the decision checks over code\n * (`decision/governed-by-inactive`, `decision/scope-narrowed`). With `[log] index = \"committed\"`,\n * also the freshness of `<root>/index.md`. With `sources` (`readDecisionSources`), qualified\n * references are checked against the cached source logs, and each referenced source that isn't\n * cached gets one `sources/not-fetched` warning.\n */\nexport function adrChecks(\n log: DecisionLog,\n historyRef: string | null,\n sources?: DecisionSources,\n): readonly Check[] {\n return [\n ...foldChecks(adrKind, {\n options: {\n acceptRequiresHuman: log.adr.acceptRequiresHuman,\n sources: sources?.logs ?? null,\n },\n templates: gitTemplates(log.git, { historyRef }),\n }),\n scopeGlobCheck(),\n anchorCheck({ keyword: log.adr.anchorKeyword, exclude: log.adr.anchorExclude }),\n governedByInactive(log),\n scopeNarrowed(log),\n ...(log.adr.index === \"committed\" ? [decisionIndexCheck(log)] : []),\n ...(sources === undefined ? [] : [sourcesCheck(log, sources.statuses)]),\n ];\n}\n\n/** The source names that qualified references in a folded decision log name. */\nexport function referencedSources(head: FoldedLogOf<typeof adrKind>): Set<string> {\n const out = new Set<string>();\n const add = (ref: string) => {\n const at = ref.indexOf(\":\");\n if (at > 0) out.add(ref.slice(0, at));\n };\n for (const s of head.subjects.values()) {\n for (const { event } of s.applied) {\n if (event.type === \"proposed\") for (const ref of event.data.supersedes ?? []) add(ref);\n else if (event.type === \"superseded\") add(event.data.by);\n else if (event.type === \"linked\") add(event.data.to);\n }\n }\n return out;\n}\n\n/**\n * `sources/not-fetched` (warning) once per uncached source that a qualified reference in the head\n * names. It runs in every scope, because it is about the log, not about one decision.\n */\nfunction sourcesCheck(log: DecisionLog, statuses: readonly SourceStatus[]): Check {\n return {\n id: \"decision-sources\",\n async run(ctx) {\n const head = ctx.folded?.head;\n if (head === undefined) return [];\n return sourceFindings(statuses, {\n tool: \"adr\",\n file: log.configPath,\n referenced: referencedSources(head as FoldedLogOf<typeof adrKind>),\n });\n },\n };\n}\n\n/**\n * The inputs outside the decision events that adr's checks read: both candidate config paths (so\n * adding a config counts) and the log's templates. A staged change to one widens `verify --staged`\n * to every decision, because a policy, scope, severity, index or template change can make an\n * unchanged decision fail.\n */\nexport function decisionVerifyInputs(log: DecisionLog): string[] {\n const root = log.layout.root;\n return [\"adr.toml\", `${root}/adr.toml`, `${root}/templates/`];\n}\n\n/**\n * Verifies the decision log in `mode` (staged, range or full) with `adrChecks`, reading the\n * sources from the local cache only.\n */\nexport async function verifyDecisions(log: DecisionLog, mode: VerifyMode): Promise<Finding[]> {\n return verifyLog({\n git: log.git,\n kind: adrKind,\n layout: log.layout,\n mode,\n checks: adrChecks(\n log,\n await templateHistoryRef(log.git, mode),\n await readDecisionSources(log, { fetch: \"cache\" }),\n ),\n widenOn: decisionVerifyInputs(log),\n });\n}\n","import { access, constants } from \"node:fs/promises\";\nimport { relative, resolve, sep } from \"node:path\";\nimport {\n assertNoHookConflicts,\n classifyPath,\n type EventRef,\n eventTrailers,\n exitCode,\n type Finding,\n type Git,\n type HookInstallResult,\n type HookManager,\n type HookName,\n holdsText,\n hookSnippet,\n installHooks,\n parseEventFileName,\n resolveAttribution,\n type Severity,\n stagedRenames,\n UsageError,\n uninstallHooks,\n writeIndexFile,\n} from \"@nikovirtala/ledger\";\nimport { adrKind } from \"./kind.js\";\nimport type { DecisionLog } from \"./log.js\";\nimport { indexPath, renderDecisionIndex } from \"./log-index.js\";\nimport { verifyDecisions } from \"./verify.js\";\nimport { followScopeRenames } from \"./write.js\";\n\n/** The hooks adr registers, in the order the text output lists them. */\nconst HOOKS: readonly HookName[] = [\"pre-commit\", \"commit-msg\", \"pre-push\", \"post-merge\"];\n\n/** `adr hooks … --json` (design 2b §4.3); `hooks run` prints `ledger-findings/v1` instead. */\nexport interface HooksResultJson {\n readonly format: \"adr-hooks/v1\";\n readonly action: \"install\" | \"uninstall\" | \"print\" | \"trailers\";\n /** Repo-relative shim paths written or removed. */\n readonly written: readonly string[];\n readonly unchanged: readonly string[];\n readonly registrations: readonly { readonly hook: HookName; readonly argv: readonly string[] }[];\n /** `print` only. */\n readonly snippet: string | null;\n /** `trailers` only: the trailers added, in order. */\n readonly trailers: readonly (readonly [string, string])[];\n}\n\n/**\n * adr's command per hook (design 2b D4), after `adr`. `--root <root>` comes first only when the\n * root can't be found without it: no `<repo>/adr.toml` names it and it isn't `docs/adr`. So the\n * hooks see the same config as a plain `adr` run, and never print the root-override note.\n */\nexport function decisionHookCommands(\n log: DecisionLog,\n): Partial<Record<HookName, readonly string[]>> {\n const r =\n log.configPath === \"adr.toml\" || log.layout.root === adrKind.def.defaultRoot\n ? []\n : [\"--root\", log.layout.root];\n return {\n \"pre-commit\": [...r, \"hooks\", \"run\", \"pre-commit\"],\n \"commit-msg\": [...r, \"hooks\", \"trailers\", \"{args}\"],\n \"pre-push\": [...r, \"verify\", \"--base\", \"@{upstream}\", \"--ref\", \"HEAD\", \"--fetch-sources\"],\n \"post-merge\": [...r, \"list\", \"--since\", \"ORIG_HEAD\"],\n };\n}\n\nfunction registrations(log: DecisionLog): HooksResultJson[\"registrations\"] {\n const commands = decisionHookCommands(log);\n return HOOKS.flatMap((hook) => {\n const argv = commands[hook];\n return argv === undefined ? [] : [{ hook, argv }];\n });\n}\n\n/** A shim path as the user sees it: repo-relative, with `/`. */\nfunction shown(git: Git, path: string): string {\n return relative(git.root ?? git.gitDir, path)\n .split(sep)\n .join(\"/\");\n}\n\n/** The shims in hook order: `HOOKS`' order, as the text output lists them. */\nfunction inHookOrder(git: Git, paths: readonly string[]): string[] {\n const rank = (p: string) => HOOKS.findIndex((h) => p.endsWith(`/${h}`));\n return paths.map((p) => shown(git, p)).sort((a, b) => rank(a) - rank(b));\n}\n\nfunction result(\n log: DecisionLog,\n action: HooksResultJson[\"action\"],\n r: HookInstallResult | null,\n extra: Partial<Pick<HooksResultJson, \"snippet\" | \"trailers\">> = {},\n): HooksResultJson {\n return {\n format: \"adr-hooks/v1\",\n action,\n written: r === null ? [] : inHookOrder(log.git, r.written),\n unchanged: r === null ? [] : inHookOrder(log.git, r.unchanged),\n registrations: registrations(log),\n snippet: extra.snippet ?? null,\n trailers: extra.trailers ?? [],\n };\n}\n\n/**\n * Registers adr's four commands in ledger's shims, one per hook and shared with other ark tools\n * (design 2b D4). With `core.hooksPath` set or a foreign hook file present, it writes the rest and\n * then throws `HookConflictError` (exit 2), naming each conflict and the `print` command.\n */\nexport async function installDecisionHooks(log: DecisionLog): Promise<HooksResultJson> {\n const r = await installHooks(log.git, { tool: \"adr\", commands: decisionHookCommands(log) });\n assertNoHookConflicts(r, { tool: \"adr\" });\n return result(log, \"install\", r);\n}\n\n/** Removes adr from every shim; a shim left with no tool is deleted. */\nexport async function uninstallDecisionHooks(log: DecisionLog): Promise<HooksResultJson> {\n return result(log, \"uninstall\", await uninstallHooks(log.git, { tool: \"adr\" }));\n}\n\n/** The config to paste into a hook manager instead of installing shims. */\nexport function printDecisionHooks(log: DecisionLog, manager: HookManager): HooksResultJson {\n const regs = registrations(log).map((r) => ({ tool: \"adr\", ...r }));\n return result(log, \"print\", null, { snippet: hookSnippet(manager, regs) });\n}\n\n/** The `ADR-Event` trailer key as git compares keys: case-insensitively. */\nconst ADR_EVENT = /^adr-event[ \\t]*:/im;\n\n/**\n * The `commit-msg` step (P1 §7.1): appends one `ADR`/`ADR-Event` pair per decision and event type\n * among the staged added event files of the log (`eventTrailers`, ?6), in path order, keeping\n * pairs another tool already added (`ifExists: \"add\"`). It does nothing for a message that\n * already has an `ADR-Event:` trailer (an `adr … --commit` message), or during a merge, whose\n * events came with their own commits' trailers. Throws `UsageError` when the file is missing.\n */\nexport async function addHookTrailers(\n log: DecisionLog,\n messageFile: string,\n): Promise<HooksResultJson> {\n const { git, layout } = log;\n const file = resolve(git.root ?? git.gitDir, messageFile);\n try {\n await access(file, constants.R_OK | constants.W_OK);\n } catch {\n throw new UsageError(`no commit message file at ${messageFile}`);\n }\n const parsed = await git.run([\"interpret-trailers\", \"--parse\", \"--\", file]);\n if (ADR_EVENT.test(Buffer.from(parsed.stdout).toString(\"utf8\"))) {\n return result(log, \"trailers\", null);\n }\n if ((await git.resolveCommit(\"MERGE_HEAD\")) !== null) return result(log, \"trailers\", null);\n const added = await git.stagedPaths([`${layout.root}/${layout.events}`], { addedOnly: true });\n const refs = added.flatMap((p): EventRef[] => {\n const c = classifyPath(layout, p);\n const name = c.area === \"event\" && !c.file.includes(\"/\") ? parseEventFileName(c.file) : null;\n return c.area === \"event\" && c.subject !== null && name !== null\n ? [{ subject: c.subject, type: name.type }]\n : [];\n });\n const trailers = eventTrailers(refs, { subject: \"ADR\", event: \"ADR-Event\" });\n await git.appendTrailers(file, trailers, { ifExists: \"add\" });\n return result(log, \"trailers\", null, { trailers });\n}\n\n/**\n * Whether the hook may stage: only into the commit's real index (design 2b D8). `git commit\n * <paths>` and `--only`, adr's own `--commit` included, run hooks on a temporary index, and\n * staging there leaves the user's index showing the file as deleted.\n */\nfunction stagingSafe(git: Git, env: NodeJS.ProcessEnv): boolean {\n const file = env.GIT_INDEX_FILE;\n if (file === undefined || file === \"\") return true;\n const at = resolve(git.root ?? git.gitDir, file);\n return at === resolve(git.gitDir, \"index\") || at === resolve(git.gitDir, \"index.lock\");\n}\n\n/** `ADR-0003, ADR-0004` for the decisions a rename following changes. */\nconst displays = (views: readonly { readonly display: string }[]) =>\n views.map((v) => v.display).join(\", \");\n\n/**\n * `adr hooks run pre-commit` (design 2b D8): rename following, then the index, then `verify\n * --staged`, stopping at the first step that fails. `worktree` must be opened with the work-tree\n * reader, because rename following writes through `write()`; `index` with the index reader, for\n * the config as staged, the index render and verify. Only the index step stages `index.md`, and\n * only with `[hooks] index = \"stage\"`; rename following passes `index: \"skip\"`. Neither stages\n * into a temporary index (`stagingSafe`). A step that can't run throws (exit 2).\n */\nexport async function runPreCommitHook(o: {\n readonly worktree: DecisionLog;\n readonly index: DecisionLog;\n readonly env: NodeJS.ProcessEnv;\n}): Promise<{\n readonly exit: 0 | 1;\n readonly findings: readonly Finding[];\n readonly notes: readonly string[];\n readonly failOn: Severity;\n}> {\n const { worktree, index, env } = o;\n const config = index.adr;\n const failOn = config.failOn;\n const notes: string[] = [...index.notes];\n const done = (exit: 0 | 1, findings: readonly Finding[]) => ({\n exit,\n findings,\n notes: [...new Set(notes)],\n failOn,\n });\n const safe = stagingSafe(index.git, env);\n\n // 1. Renames, on the work-tree log.\n if (config.scopeFollowRenames !== \"off\" && (await stagedRenames(worktree.git)).length > 0) {\n const { actor, notes: attribution } = await resolveAttribution(worktree.git, { env });\n if (config.scopeFollowRenames === \"warn\") {\n const dry = await followScopeRenames(worktree, { actor }, { dryRun: true });\n for (const v of dry.affected) {\n notes.push(\n `${v.display}'s globs don't follow the renames in this commit (scope_follow_renames = \"warn\"); run adr scope --follow-renames`,\n );\n }\n } else if (safe) {\n const doc = await followScopeRenames(\n worktree,\n { actor },\n { index: \"skip\", notes: attribution },\n );\n notes.push(...doc.notes);\n if (!doc.ok) return done(1, doc.findings);\n } else {\n const dry = await followScopeRenames(worktree, { actor }, { dryRun: true });\n if (dry.affected.length > 0) {\n notes.push(\n `the renames in this commit change the scope of ${displays(dry.affected)}; git commit <paths> can't take the scoped events. Run adr scope --follow-renames, then commit again including the files it lists, or set [hooks] scope_follow_renames = \"warn\"`,\n );\n return done(1, []);\n }\n }\n }\n\n // 2. The index, on the index log: regenerated only with [hooks] index = \"stage\".\n if (config.index === \"committed\" && config.hookIndex === \"stage\" && safe) {\n const path = indexPath(index.layout);\n const text = await renderDecisionIndex(index.git, {\n layout: index.layout,\n adr: config,\n tree: index.tree,\n history: await index.git.resolveCommit(\"HEAD\"),\n });\n if (text !== null && !holdsText(await index.tree.read(path), text)) {\n await writeIndexFile(index.git, path, text);\n await index.git.add([path]);\n notes.push(`regenerated and staged ${path}`);\n }\n }\n\n // 3. verify --staged, which also reports a stale index.md in check mode.\n const findings = await verifyDecisions(index, { type: \"staged\" });\n return done(exitCode(findings, { failOn }), findings);\n}\n","/**\n * The agent skill `adr init --skill` writes (01, \"Agent skill (SKILL.md)\"): the judgment of when\n * to use adr's MCP tools. `skill.test.ts` keeps it equal to the block in docs/01-adr-v1.md.\n */\nexport const SKILL_MD = `---\nname: adr\ndescription: Use before changing architecture, data stores, integration patterns, dependencies or cross-cutting conventions, and whenever asked to record, propose or look up an architectural decision.\n---\n\n# Architectural decisions (adr)\n\nDecisions in this repo are managed by adr. Decision files do not\nshow their own status, so never judge from the raw files whether a\ndecision applies.\n\n## Before changing architecture\n\n1. Call adr_for_path for the files you will touch, and adr_search\n for the area you are about to change. adr_search returns active\n decisions only; adr_for_path also lists inactive ones, each with\n a warning.\n2. If your change conflicts with an accepted decision, stop and tell\n the user which ADR it conflicts with. Do not work around it silently.\n3. If the user still wants the change, propose a superseding ADR.\n\n## Reading decisions\n\n- Use adr_get or adr://decision/{id}, never docs/adr/decisions/*.md.\n- If a response says SUPERSEDED or DEPRECATED, follow it to the\n effective decision before acting.\n- If it says REJECTED or WITHDRAWN, the decision was never in force;\n do not apply it.\n\n## Proposing decisions\n\n1. Call adr_templates and fill every required section.\n2. Use only facts from the conversation and the code. Mark unknowns\n as open questions instead of inventing them.\n3. List at least two options considered when the template has that section.\n4. Set supersedes when the proposal replaces an existing decision.\n5. Do not accept your own proposal. Tell the user the ADR id and\n that they can review it and run: adr accept <id>\n6. If the user decides against your proposal, withdraw it with\n adr_withdraw and give their reason. Don't withdraw other\n people's proposals; tell the user instead.\n\n## Changing scope\n\n- When you move or rename code covered by a decision, let the\n pre-commit hook update its globs (adr hooks install). For your\n own proposals, you can use adr_scope. Rescoping an accepted\n decision needs mcp_can_decide; otherwise tell the user and\n suggest adr scope <id> ….\n- Before any scope change, read the decision's Scope section. If it\n would no longer read true after the change, do not rescope: tell\n the user the decision itself is changing and propose a\n superseding ADR.\n\n## Never\n\n- Edit an accepted decision body, any file under docs/adr/events/,\n or index.md by hand.\n- Use adr_note to change the meaning of a decision. Notes clarify;\n changed decisions need a superseding ADR.\n\n## Without the MCP server\n\nUse the CLI with --json: adr search, adr for, adr show, adr new,\nadr note. Set ARK_AGENT=<your name> and ARK_ON_BEHALF_OF=<the user's\nemail> so your writes are attributed.\n`;\n","import { rm } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport {\n ConfigError,\n commitWithRecovery,\n firstLine,\n headTree,\n InvalidArgumentError,\n overlayTree,\n readToolConfig,\n renderCommitMessage,\n replaceFile,\n UsageError,\n worktreeReader,\n writeIndexCopy,\n writeNewFile,\n} from \"@nikovirtala/ledger\";\nimport { adrKind } from \"./kind.js\";\nimport type { DecisionLog } from \"./log.js\";\nimport { INDEX_AFTER, indexPath, renderDecisionIndex } from \"./log-index.js\";\nimport { SKILL_MD } from \"./skill.js\";\nimport { BUILTIN_TEMPLATES } from \"./templates/builtin.js\";\n\n/** `adr init --json` (design §6.2). */\nexport interface InitResultJson {\n readonly format: \"adr-init/v1\";\n readonly root: string;\n /** The config file of the log after init, repo-relative; `null` if there is none. */\n readonly config: string | null;\n /** Repo-relative paths written, in write order. */\n readonly written: readonly string[];\n /** Files that were already there and were left as they are. */\n readonly kept: readonly string[];\n /** With `--skill`, the SKILL.md path (written or kept); else `null`. */\n readonly skill: string | null;\n readonly commit: string | null;\n readonly notes: readonly string[];\n}\n\n/**\n * What the recovery hint says about rerunning `adr init` after `git commit` failed (design 2b D5):\n * init keeps existing files, so it would commit nothing.\n */\nexport const INIT_RERUN =\n \"Running adr init again won't commit them: the files exist now, so it keeps them and commits nothing.\";\n\nconst CONFIG = \"adr.toml\";\nconst DEFAULT_ROOT = adrKind.def.defaultRoot;\nconst encoder = new TextEncoder();\nconst decoder = new TextDecoder();\nconst AGENTS = \"AGENTS.md\";\n\n/** The line `adr init --skill` adds to AGENTS.md for tools that don't load skills. */\nexport const agentsPointer = (skill: string): string =>\n `Architecture decisions in this repository are managed by adr: read ${skill} before changing architecture, and follow it.`;\n\n/** `text` with `line` appended after one blank line, ending with a newline. */\nfunction appendLine(text: string, line: string): string {\n if (text === \"\") return `${line}\\n`;\n const ended = text.endsWith(\"\\n\") ? text : `${text}\\n`;\n return `${ended.endsWith(\"\\n\\n\") ? ended : `${ended}\\n`}${line}\\n`;\n}\n\n/** The starter config; `root` only for a repo-level file naming a log elsewhere. */\nfunction configText(o: { readonly root: string | null; readonly template: string }): string {\n return [\n \"# adr configuration. Every key is optional: https://github.com/nikovirtala/ark/tree/main/packages/adr#config-adrtoml\",\n \"[log]\",\n ...(o.root === null ? [] : [`root = ${JSON.stringify(o.root)}`]),\n `default_template = ${JSON.stringify(o.template)}`,\n \"\",\n \"[commit]\",\n '# subject = \"docs(adr): {action} {title}\"',\n \"\",\n ].join(\"\\n\");\n}\n\n/**\n * `adr init` (design §6.2): writes a config for the log, unless one is found, and each built-in\n * template in `o.templates` (default `nygard`) to `<root>/templates/`, never overwriting a file.\n * A `--root` other than `docs/adr` gets a repo-level `adr.toml` naming it, so later commands find\n * the log without `--root`; when that file exists for another log, the config goes in the root.\n * With `[log] index = \"committed\"` it also writes `<root>/index.md` unless one exists. With\n * `commit` (default `[policy] auto_commit`) the written files are committed on their own;\n * nothing written means nothing committed. No events are written. With `o.skill` it also writes\n * the agent skill, unless a SKILL.md is there, and adds the pointer line to `AGENTS.md`, unless a\n * line already names the skill; an AGENTS.md with unstaged changes or not tracked is refused\n * with a commit and left unstaged without one.\n */\nexport async function initDecisionLog(\n log: DecisionLog,\n o: {\n readonly templates?: readonly string[];\n readonly commit?: boolean;\n readonly message?: string | null;\n /**\n * Also write `<dir>/SKILL.md` (`dir` repo-relative, `\"\"` for the root) and the AGENTS.md\n * pointer (design §9); `version` is adr's, for the note on a SKILL.md that differs.\n */\n readonly skill?: { readonly dir: string; readonly version: string };\n } = {},\n): Promise<InitResultJson> {\n if (log.ref !== null || log.tree.label !== \"worktree\") {\n throw new InvalidArgumentError(\"init writes the work tree; open the log without a ref\");\n }\n const known = Object.keys(BUILTIN_TEMPLATES);\n const templates = [...new Set(o.templates === undefined ? [\"nygard\"] : o.templates)];\n for (const name of templates) {\n if (!known.includes(name)) {\n throw new UsageError(`unknown built-in template ${name}; use nygard, madr or y-statement`);\n }\n }\n const root = log.layout.root;\n const notes = [...log.notes];\n const files: [string, string][] = [];\n const kept: string[] = [];\n let config = log.configPath;\n if (config !== null) {\n kept.push(config);\n } else {\n const template = templates[0] ?? \"nygard\";\n const repo = await readToolConfig(log.tree, CONFIG);\n if (root === DEFAULT_ROOT) {\n config = `${root}/${CONFIG}`;\n files.push([config, configText({ root: null, template })]);\n } else if (repo === null) {\n config = CONFIG;\n files.push([config, configText({ root, template })]);\n } else {\n // The repo file names another log (openToolLog ignored it with a note); leave it alone.\n const section = repo.raw.log as { root?: unknown } | undefined;\n const other = typeof section?.root === \"string\" ? section.root : DEFAULT_ROOT;\n config = `${root}/${CONFIG}`;\n files.push([config, configText({ root: null, template })]);\n notes.push(`${CONFIG} names ${other}; pass --root ${root} to use this log`);\n }\n }\n for (const name of templates) {\n const path = `${root}/templates/${name}.md`;\n if ((await log.tree.read(path)) !== null) kept.push(path);\n else files.push([path, BUILTIN_TEMPLATES[name] ?? \"\"]);\n }\n const commitRequested = o.commit ?? log.adr.autoCommit;\n const logFiles = files.length;\n\n // The skill (design §9.1): SKILL.md is never overwritten; AGENTS.md gets one pointer line.\n // Checked before anything is written.\n const skill =\n o.skill === undefined ? null : o.skill.dir === \"\" ? \"SKILL.md\" : `${o.skill.dir}/SKILL.md`;\n let agents: {\n readonly bytes: Uint8Array;\n readonly expected: Uint8Array | null;\n readonly stage: boolean;\n } | null = null;\n if (skill !== null) {\n const current = await log.tree.read(skill);\n if (current === null) {\n files.push([skill, SKILL_MD]);\n } else {\n kept.push(skill);\n if (decoder.decode(current) !== SKILL_MD) {\n notes.push(\n `${skill} differs from adr ${o.skill?.version ?? \"\"}'s skill; delete it and run adr init --skill again to replace it`,\n );\n }\n }\n const old = await log.tree.read(AGENTS);\n const text = old === null ? null : decoder.decode(old);\n if ((text ?? \"\").split(\"\\n\").some((l) => l.includes(skill))) {\n kept.push(AGENTS);\n } else {\n let stage = true;\n if (old !== null) {\n const unstaged = (await log.git.unstagedPaths([AGENTS])).length > 0;\n const untracked = (await log.git.untrackedPaths([AGENTS])).length > 0;\n if (commitRequested && unstaged) {\n throw new UsageError(\n `${AGENTS} has unstaged changes; stage or discard them, or run without --commit`,\n );\n }\n if (commitRequested && untracked) {\n throw new UsageError(`${AGENTS} is not tracked; git add it, or run without --commit`);\n }\n if (unstaged || untracked) {\n stage = false;\n notes.push(\n untracked\n ? `${AGENTS} is not tracked, so the pointer is added but not staged; review it and git add it`\n : `${AGENTS} had unstaged changes, so the pointer is added but not staged; review it and git add it`,\n );\n }\n }\n agents = {\n bytes: encoder.encode(appendLine(text ?? \"\", agentsPointer(skill))),\n expected: old,\n stage,\n };\n }\n }\n const at = indexPath(log.layout);\n let indexed = false;\n if (log.adr.index === \"committed\") {\n // Rendered before anything is written, from the tree the commit (or the work tree) will hold.\n if ((await log.tree.read(at)) !== null) {\n kept.push(at);\n } else {\n const head = await log.git.resolveCommit(\"HEAD\");\n const added = Object.fromEntries(files.map(([p, t]) => [p, encoder.encode(t)]));\n const base = commitRequested ? await headTree(log.git, head) : log.tree;\n const text = await renderDecisionIndex(log.git, {\n layout: log.layout,\n adr: log.adr,\n tree: overlayTree(base, added),\n history: head,\n });\n if (text === null) {\n notes.push(\n `${at} not updated: numbers need history in this shallow clone; run git fetch --unshallow, then adr index`,\n );\n } else {\n files.push([at, text]);\n indexed = true;\n }\n }\n }\n\n const commit = (files.length > 0 || agents !== null) && commitRequested;\n if (\n commit &&\n ((await log.git.identity()) === null || (await log.git.committerIdentity()) === null)\n ) {\n throw new ConfigError(\"--commit needs a git identity; set git user.name and user.email\");\n }\n const written: string[] = [];\n let replaced = false;\n try {\n for (const [path, text] of files) {\n await writeNewFile(log.git, path, encoder.encode(text));\n written.push(path);\n }\n if (agents !== null) {\n if (agents.expected === null) await writeNewFile(log.git, AGENTS, agents.bytes);\n else await replaceFile(log.git, AGENTS, agents.bytes, { expected: agents.expected });\n replaced = agents.expected !== null;\n written.push(AGENTS);\n }\n } catch (err) {\n const top = log.git.root ?? \"\";\n const restore = replaced ? (agents?.expected ?? null) : null;\n for (const path of written) {\n if (path === AGENTS && restore !== null && agents !== null) {\n await replaceFile(log.git, AGENTS, restore, { expected: agents.bytes }).catch(() => {});\n } else {\n await rm(join(top, path), { force: true });\n }\n }\n throw err;\n }\n const staged = written.filter((p) => p !== AGENTS || agents?.stage === true);\n if (staged.length > 0) await log.git.add(staged);\n let sha: string | null = null;\n if (commit) {\n const message =\n o.message ??\n renderCommitMessage(log.adr.commitSubject, {\n title: logFiles > 0 ? \"the decision log\" : \"the adr agent skill\",\n vars: { action: \"set up\", id: \"\", display: \"\", command: \"init\" },\n }).message;\n sha = await commitWithRecovery(log.git, {\n message,\n only: staged,\n rerun: INIT_RERUN,\n after: indexed ? INDEX_AFTER(root) : null,\n });\n if (indexed) {\n // The commit's index leaves out uncommitted log changes; the work tree and the index get\n // them back (design 2b §4.5 step 5).\n try {\n const again = await renderDecisionIndex(log.git, {\n layout: log.layout,\n adr: log.adr,\n tree: worktreeReader(log.git),\n history: sha,\n });\n if (again !== null) {\n const r = await writeIndexCopy(log.git, at, again);\n if (r.stage) await log.git.add([at]);\n }\n } catch (err) {\n notes.push(`${at} may be stale: ${firstLine(err)}; run adr index`);\n }\n }\n }\n return { format: \"adr-init/v1\", root, config, written, kept, skill, commit: sha, notes };\n}\n"],"mappings":"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"}