@descent-vtt/spec-harness 0.19.0 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +325 -0
- package/README.md +39 -18
- package/dist/briefs.d.ts +45 -0
- package/dist/briefs.js +73 -0
- package/dist/briefs.js.map +1 -1
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +308 -142
- package/dist/cli.js.map +1 -1
- package/dist/commands.js +7 -2
- package/dist/commands.js.map +1 -1
- package/dist/config.d.ts +13 -1
- package/dist/config.js +14 -3
- package/dist/config.js.map +1 -1
- package/dist/configure.d.ts +94 -3
- package/dist/configure.js +204 -30
- package/dist/configure.js.map +1 -1
- package/dist/fs.d.ts +104 -1
- package/dist/fs.js +383 -11
- package/dist/fs.js.map +1 -1
- package/dist/git.d.ts +88 -2
- package/dist/git.js +155 -8
- package/dist/git.js.map +1 -1
- package/dist/guard.d.ts +20 -1
- package/dist/guard.js +31 -0
- package/dist/guard.js.map +1 -1
- package/dist/hooks.d.ts +59 -0
- package/dist/hooks.js +76 -3
- package/dist/hooks.js.map +1 -1
- package/dist/round.d.ts +27 -1
- package/dist/round.js +75 -17
- package/dist/round.js.map +1 -1
- package/dist/sandbox.js +4 -3
- package/dist/sandbox.js.map +1 -1
- package/dist/server.d.ts +25 -1
- package/dist/server.js +230 -28
- package/dist/server.js.map +1 -1
- package/dist/setup.js +40 -10
- package/dist/setup.js.map +1 -1
- package/dist/siblings.d.ts +29 -6
- package/dist/siblings.js +152 -39
- package/dist/siblings.js.map +1 -1
- package/dist/usage.d.ts +42 -7
- package/dist/usage.js +65 -6
- package/dist/usage.js.map +1 -1
- package/dist/workspace.d.ts +45 -3
- package/dist/workspace.js +143 -13
- package/dist/workspace.js.map +1 -1
- package/package.json +3 -3
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `spec-harness mcp`: the round's questions, served over the Model Context\n * Protocol on stdio (ADR-0008). The protocol is spec-core's `jsonrpc` module;\n * this file is the five tools, the four prompts, and nothing else. Every\n * request reads the repository afresh: a brief edited a minute ago is the\n * brief the next answer uses.\n */\n\nimport { readFileSync } from 'node:fs';\nimport { Readable } from 'node:stream';\nimport { fileURLToPath } from 'node:url';\n\nimport { describeMeasured } from './audit.js';\nimport { findActive } from './briefs.js';\nimport { briefIdFromBranch } from './branch.js';\nimport { titleOf } from './context.js';\nimport { createReader } from './reader.js';\nimport { buildContext, checkPaths, raiseEscalation, runAudit } from './round.js';\nimport type { EscalationOption } from './rulings.js';\nimport type { BriefRow } from './types.js';\nimport { emptyValue, isBlank, type ValuedOption } from './usage.js';\nimport {\n createMcpServer,\n serveLines,\n toolError,\n unknownArguments,\n type JsonObject,\n type PromptDefinition,\n type ToolDefinition,\n type ToolOutcome,\n} from './vendor/spec-core/jsonrpc/index.js';\nimport { describeActive, openWorkspace, version, type CliIO, type Options, type Workspace } from './workspace.js';\n\nconst reader = createReader();\n\nexport const INSTRUCTIONS =\n 'spec-harness keeps a round of work inside the brief a person approved. ' +\n 'Call start_round before working: it returns the brief, the scope you may write, what you must not touch, the rules in force and the documents the brief cites. ' +\n 'Call check_path before writing a file you are unsure of. A protected file needs a ruling: call request_escalation and stop until a person rules. ' +\n 'Call audit_round when the work is done, and fix what it reports; archiving is a person\\'s decision. ' +\n 'For the architecture rules themselves, spec-guard\\'s own server answers get_architectural_rules.';\n\nconst briefProperty = { type: 'string', description: 'The brief id. Omit to use the brief the branch or SPEC_BRIEF names; an empty id is refused.' };\nconst baseProperty = {\n type: 'string',\n description:\n 'The branch the round is measured from, whose allowed signers a ruling is verified against. Omit to use the configured base; an empty one is refused.',\n};\n\n/**\n * The tool error for an argument that is given and names nothing, in the\n * words the command line has for its option. Read as left out, an empty\n * `brief` was answered for the branch's brief and an empty `base` with no\n * ruling verified, and nothing told the agent that neither was the answer to\n * what it had asked.\n */\nfunction namesNothing(argument: string, option: ValuedOption, value: string): ToolOutcome {\n return toolError(`${emptyValue(`\"${argument}\"`, option, value)}.`);\n}\n\n/** The `base` argument, or the tool error for one that is not a string, or names no commit. */\nfunction baseOf(args: JsonObject): { base: string | undefined } | ToolOutcome {\n const base = args['base'];\n if (base !== undefined && typeof base !== 'string') return toolError('\"base\" must be a string.');\n if (base !== undefined && isBlank(base)) return namesNothing('base', 'base', base);\n return { base };\n}\n\n/** The `paths` argument, or the tool error for one that is no list of files, or has a place that names none. */\nfunction pathsOf(args: JsonObject): { paths: string[] } | ToolOutcome {\n const paths = args['paths'];\n if (!Array.isArray(paths) || !paths.every((p) => typeof p === 'string') || paths.length === 0) {\n return toolError('\"paths\" must be a non-empty array of strings.');\n }\n const empty = paths.findIndex(isBlank);\n if (empty !== -1) return namesNothing(`paths[${empty}]`, 'path', paths[empty] as string);\n return { paths };\n}\n\n/**\n * The `options` argument as the memo's choices, or the tool error for one\n * the memo cannot be written with: a choice is its label, and one without\n * was written as a number and two empty stars. What a choice costs may be\n * left out, and the memo then gives the choice alone.\n */\nfunction optionsOf(args: JsonObject): { options: EscalationOption[] } | ToolOutcome {\n const raw = args['options'] ?? [];\n if (!Array.isArray(raw)) return toolError('\"options\" must be an array.');\n const options: EscalationOption[] = [];\n for (const [index, item] of raw.entries()) {\n // An item that is no object has no label, and is refused for that.\n const entry: JsonObject = item ?? {};\n const label = entry['label'];\n const consequence = entry['consequence'] ?? '';\n if (typeof label !== 'string') return toolError(`\"options[${index}].label\" must be a string.`);\n if (isBlank(label)) return toolError(`\"options[${index}].label\" is ${JSON.stringify(label)}, which names no choice; give the option a label, or leave the option out.`);\n if (typeof consequence !== 'string') return toolError(`\"options[${index}].consequence\" must be a string.`);\n options.push({ label: label.trim(), consequence: consequence.trim() });\n }\n return { options };\n}\n\nasync function round(workspace: Workspace, env: CliIO['env'], id: unknown): Promise<{ brief: BriefRow; briefs: BriefRow[] } | ToolOutcome> {\n if (id !== undefined && typeof id !== 'string') return toolError('\"brief\" must be a string.');\n if (id !== undefined && isBlank(id)) return namesNothing('brief', 'brief', id);\n const briefs = await workspace.siblings.briefs();\n const fromBranch = briefIdFromBranch(workspace.config.branches, workspace.branch);\n const active = findActive(briefs, { argument: id, environment: env['SPEC_BRIEF'], branch: fromBranch });\n // Named as every argument of a tool is, where it was called the flag, and\n // a tool call has none.\n const { brief, note, problem } = describeActive(active, '\"brief\"');\n if (problem !== null) return toolError(problem);\n if (brief === null) return toolError(note);\n return { brief, briefs };\n}\n\nexport function tools(workspace: Workspace, env: CliIO['env']): ToolDefinition[] {\n const readOnly = { readOnlyHint: true, idempotentHint: true, openWorldHint: false };\n return [\n {\n descriptor: {\n name: 'start_round',\n title: 'Start a round',\n description:\n 'Everything needed to start the round: the brief in full, the files it may write and must not change, signed rulings, the briefs it depends on, the architecture rules in force for its scope, and the documents it cites.',\n inputSchema: { type: 'object', properties: { brief: briefProperty, base: baseProperty }, additionalProperties: false },\n annotations: readOnly,\n },\n async call(args: JsonObject): Promise<ToolOutcome> {\n const unknown = unknownArguments(args, ['brief', 'base']);\n if (unknown) return unknown;\n const base = baseOf(args);\n if ('text' in base) return base;\n const found = await round(workspace, env, args['brief']);\n if ('text' in found) return found;\n const packet = await buildContext(workspace, found.brief, found.briefs, reader, base.base);\n return {\n text: packet.markdown,\n structured: {\n brief: found.brief.id,\n included: [...packet.included],\n omitted: [...packet.omitted],\n unresolved: [...packet.unresolved],\n unclosedFrontMatter: [...packet.unclosedFrontMatter],\n unreadableFrontMatter: [...packet.unreadableFrontMatter],\n unreadableScope: [...packet.unreadableScope],\n unreadableProtections: [...packet.unreadableProtections],\n unreadableRulingPaths: [...packet.unreadableRulingPaths],\n unmatchedSpecs: [...packet.unmatchedSpecs],\n },\n };\n },\n },\n {\n descriptor: {\n name: 'check_path',\n title: 'May the round write these files',\n description:\n 'For each path: allowed (in scope, or covered by a signed ruling), outside the scope, or refused (protected by the brief). Works for files that do not exist yet.',\n inputSchema: {\n type: 'object',\n properties: {\n paths: { type: 'array', items: { type: 'string' }, description: 'Paths relative to the project root, or absolute inside it. An empty one is refused.' },\n brief: briefProperty,\n base: baseProperty,\n },\n required: ['paths'],\n additionalProperties: false,\n },\n annotations: readOnly,\n },\n async call(args: JsonObject): Promise<ToolOutcome> {\n const unknown = unknownArguments(args, ['paths', 'brief', 'base']);\n if (unknown) return unknown;\n const given = pathsOf(args);\n if ('text' in given) return given;\n const base = baseOf(args);\n if ('text' in base) return base;\n const found = await round(workspace, env, args['brief']);\n if ('text' in found) return found;\n const decisions = await checkPaths(workspace, found.brief, undefined, given.paths, workspace.root, reader, base.base);\n const text = decisions.map((d) => `${d.verdict}: ${d.message}${d.verdict === 'allow' ? '' : `. Next: ${d.hint}`}`).join('\\n');\n return { text, structured: { decisions: decisions.map((d) => ({ ...d })) } };\n },\n },\n {\n descriptor: {\n name: 'request_escalation',\n title: 'Ask a person to rule',\n description:\n 'When the round cannot be finished without changing something the brief protects, record the request and stop. A person reads the memo and rules; only a ruling they sign lets the change through.',\n inputSchema: {\n type: 'object',\n properties: {\n paths: { type: 'array', items: { type: 'string' }, description: 'The protected files the round needs to change. An empty one is refused.' },\n reason: { type: 'string', description: 'Why the round cannot be done without them. It is required, and may not be empty.' },\n options: {\n type: 'array',\n items: { type: 'object', properties: { label: { type: 'string' }, consequence: { type: 'string' } }, required: ['label', 'consequence'] },\n description: 'The choices the person has, each with what it costs. A choice whose label is empty is refused.',\n },\n recommendation: { type: 'string', description: 'Which option you recommend, and why. Omit it when there is none: an empty one is refused.' },\n brief: briefProperty,\n },\n required: ['paths', 'reason'],\n additionalProperties: false,\n },\n annotations: { readOnlyHint: false, idempotentHint: false, openWorldHint: false },\n },\n async call(args: JsonObject): Promise<ToolOutcome> {\n const unknown = unknownArguments(args, ['paths', 'reason', 'options', 'recommendation', 'brief']);\n if (unknown) return unknown;\n // Every part of the memo before anything is written: a person rules\n // on what it says, and cannot rule on a part that says nothing.\n const given = pathsOf(args);\n if ('text' in given) return given;\n const reason = args['reason'];\n if (typeof reason !== 'string' || isBlank(reason)) return toolError('\"reason\" is required.');\n const choices = optionsOf(args);\n if ('text' in choices) return choices;\n const recommendation = args['recommendation'];\n if (recommendation !== undefined && typeof recommendation !== 'string') return toolError('\"recommendation\" must be a string.');\n if (recommendation !== undefined && isBlank(recommendation)) return namesNothing('recommendation', 'recommend', recommendation);\n const found = await round(workspace, env, args['brief']);\n if ('text' in found) return found;\n const { request, memo } = await raiseEscalation(workspace, found.brief, {\n paths: given.paths,\n reason,\n options: choices.options,\n recommendation: recommendation ?? null,\n });\n return { text: `${memo}\\nStop here until a person rules on ${request.id}.`, structured: { id: request.id } };\n },\n },\n {\n descriptor: {\n name: 'audit_round',\n title: 'Audit the round',\n description:\n 'Did the round stay inside the lines: what the archive would refuse (open boxes, protected files, files outside the scope), the brief\\'s own assertions, unverified rulings, every dependency added and every package allowed to run install scripts.',\n inputSchema: { type: 'object', properties: { brief: briefProperty, base: baseProperty }, additionalProperties: false },\n annotations: readOnly,\n },\n async call(args: JsonObject): Promise<ToolOutcome> {\n const unknown = unknownArguments(args, ['brief', 'base']);\n if (unknown) return unknown;\n const base = baseOf(args);\n if ('text' in base) return base;\n const found = await round(workspace, env, args['brief']);\n if ('text' in found) return found;\n const result = await runAudit(workspace, found.brief, reader, base.base);\n const { counts, findings, measured } = result.report;\n // What was measured beside what was found: \"nothing found\" from an\n // audit that ran no goal is not a round that is done.\n const text =\n findings.length === 0\n ? 'The audit found nothing in what it measured.'\n : findings.map((f) => `${f.severity} ${f.rule}: ${f.message}. Next: ${f.hint}`).join('\\n');\n return {\n text: `${text}\\n\\n${describeMeasured(measured)}\\n\\n${counts.error} error(s), ${counts.warning} warning(s), ${counts.note} note(s)`,\n structured: { counts, measured: { ...measured }, findings: findings.map((f) => ({ ...f })) },\n };\n },\n },\n {\n descriptor: {\n name: 'list_rounds',\n title: 'List the rounds',\n description: 'The live briefs: status, wave, what each waits on, and which are ready to start.',\n inputSchema: { type: 'object', properties: {}, additionalProperties: false },\n annotations: readOnly,\n },\n async call(args: JsonObject): Promise<ToolOutcome> {\n const unknown = unknownArguments(args, []);\n if (unknown) return unknown;\n const live = (await workspace.siblings.briefs()).filter((brief) => brief.phase === 'live');\n const text = live\n .map((b) => `${[b.id, titleOf(b)].filter((part) => part !== null).join(' ')} - ${b.status ?? 'unknown'}, wave ${b.wave ?? '-'}, ${b.ready ? 'ready' : `waits on ${b.waitingOn.join(', ')}`}`)\n .join('\\n');\n return { text: text === '' ? 'No live brief.' : text, structured: { briefs: live.map((b) => ({ ...b, title: titleOf(b) })) } };\n },\n },\n ];\n}\n\nconst SKILLS: readonly { name: string; title: string; argument: string; description: string }[] = [\n { name: 'draft-brief', title: 'Draft a brief', argument: 'request', description: 'What the round should achieve, in the person\\'s words.' },\n { name: 'split-goal', title: 'Split a goal into rounds', argument: 'goal', description: 'The goal to split.' },\n { name: 'run-round', title: 'Run a round', argument: 'brief', description: 'The brief id.' },\n { name: 'close-round', title: 'Close a round', argument: 'brief', description: 'The brief id.' },\n];\n\nfunction skillText(name: string): string {\n // The package ships the skills beside dist/ (package.json's files), so one\n // that cannot be read is a broken install, and the request fails saying so\n // rather than serving an empty prompt.\n const text = readFileSync(fileURLToPath(new URL(`../skills/${name}/SKILL.md`, import.meta.url)), 'utf8');\n // Every skill opens with its front matter (tests/source.test.ts), so the\n // anchor is equivalent to its mutant here.\n return text.replace(/^---\\r?\\n[\\s\\S]*?\\r?\\n---\\r?\\n/, '').trim();\n}\n\nexport function prompts(): PromptDefinition[] {\n return SKILLS.map((skill) => ({\n descriptor: {\n name: skill.name,\n title: skill.title,\n arguments: [{ name: skill.argument, description: skill.description, required: false }],\n },\n async get(args: Readonly<Record<string, string>>): Promise<JsonObject> {\n const given = args[skill.argument];\n const text = `${skillText(skill.name)}${given === undefined || given === '' ? '' : `\\n\\n${skill.argument}: ${given}`}`;\n return { description: skill.title, messages: [{ role: 'user', content: { type: 'text', text } }] };\n },\n }));\n}\n\nexport async function mcpCommand(options: Options, io: CliIO): Promise<number> {\n // Claude Code starts a plugin's server in the plugin's directory, and names\n // the project in CLAUDE_PROJECT_DIR; the server answers for the project.\n const workspace = await openWorkspace({ ...options, root: options.root ?? (io.env['CLAUDE_PROJECT_DIR'] || undefined) }, io);\n const handle = createMcpServer({ name: 'spec-harness', version: version(), instructions: INSTRUCTIONS, tools: tools(workspace, io.env), prompts: prompts() });\n // A session handed over whole, as a test hands it, is served as a client\n // would stream it on stdin. Only the built command line serves\n // process.stdin, and the suite spawns it from dist/, outside the sweep\n // (tests/integration/mcp.test.ts), so a mutant that ignores it survives.\n const input = io.stdin === undefined ? process.stdin : Readable.from([Buffer.from(await io.stdin())]);\n await serveLines(input, (line) => io.stdout.write(`${line}\\n`), handle);\n return 0;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `spec-harness mcp`: the round's questions, served over the Model Context\n * Protocol on stdio (ADR-0008). The protocol is spec-core's `jsonrpc` module;\n * this file is the five tools, the four prompts, and nothing else. Every\n * request reads the repository afresh: a brief edited a minute ago is the\n * brief the next answer uses.\n */\n\nimport { readFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { Readable } from 'node:stream';\nimport { fileURLToPath } from 'node:url';\n\nimport { describeMeasured } from './audit.js';\nimport { findActive, type ActiveBrief } from './briefs.js';\nimport { briefIdFromBranch } from './branch.js';\nimport { titleOf } from './context.js';\nimport { createReader } from './reader.js';\nimport { outsideEvery, realSpelling } from './fs.js';\nimport { heldBy, type Decision } from './guard.js';\nimport { buildContext, checkPaths, raiseEscalation, runAudit } from './round.js';\nimport type { EscalationOption } from './rulings.js';\nimport type { BriefRow } from './types.js';\nimport { emptyValue, isBlank, type ValuedOption } from './usage.js';\nimport {\n CLIENT_CAPABILITIES_KEY,\n createMcpServer,\n isObject,\n serveLines,\n toolError,\n unknownArguments,\n type JsonObject,\n type PromptDefinition,\n type ToolDefinition,\n type ToolOutcome,\n} from './vendor/spec-core/jsonrpc/index.js';\nimport { describeActive, findTree, foundCommonDir, mayBeElsewhere, namedId, openFound, openWorkspace, version, writesBy, type CliIO, type Options, type Workspace } from './workspace.js';\n\nconst reader = createReader();\n\nexport const INSTRUCTIONS =\n 'spec-harness keeps a round of work inside the brief a person approved. ' +\n 'Call start_round before working: it returns the brief, the scope you may write, what you must not touch, the rules in force and the documents the brief cites. ' +\n 'Call check_path before writing a file you are unsure of. A protected file needs a ruling: call request_escalation and stop until a person rules. ' +\n 'Call audit_round when the work is done, and fix what it reports; archiving is a person\\'s decision. ' +\n 'For the architecture rules themselves, spec-guard\\'s own server answers get_architectural_rules.';\n\nconst briefProperty = { type: 'string', description: 'The brief id. Omit to use the brief the branch or SPEC_BRIEF names; an empty id is refused.' };\nconst baseProperty = {\n type: 'string',\n description:\n 'The branch the round is measured from, whose allowed signers a ruling is verified against. Omit to use the configured base; an empty one is refused.',\n};\n\n/**\n * The tool error for an argument that is given and names nothing, in the\n * words the command line has for its option. Read as left out, an empty\n * `brief` was answered for the branch's brief and an empty `base` with no\n * ruling verified, and nothing told the agent that neither was the answer to\n * what it had asked.\n */\nfunction namesNothing(argument: string, option: ValuedOption, value: string): ToolOutcome {\n return toolError(`${emptyValue(`\"${argument}\"`, option, value)}.`);\n}\n\nconst directoryProperty = {\n type: 'string',\n description:\n \"A directory in the work tree the round is in, such as the worktree you work in. Omit to use the work tree the client's roots name, where they name one of this repository, or else the project's.\",\n};\n\n/**\n * The directories a client's roots name, or `null` where it declared no\n * roots, answered with an error, or did not answer in time.\n */\nexport type Roots = () => Promise<readonly string[] | null>;\n\n/** No client to ask: the tools as a caller of the package builds them, with no server around them. */\nconst NO_ROOTS: Roots = async () => null;\n\n/** How long a client is given to answer `roots/list`: Claude Code answers from what it holds (its MCP page, below). */\nexport const ROOTS_MS = 5_000;\n\n/**\n * The client's roots, asked as MCP has a server ask them, with a request of\n * the server's own, `roots/list`, where the client declared the capability\n * as it started: in its `initialize`, or a later request's `_meta`. Claude\n * Code's MCP page (https://code.claude.com/docs/en/mcp, Option 3: Add a local\n * stdio server, read 2026-10-19) has it answer with the session's launch\n * directory and every working directory added to it, and\n * `CLAUDE_PROJECT_DIR` the stable project root, which does not move with\n * them. The answer arrives on the input as a response, which the protocol's\n * module passes over: it is read here first, by the id it was asked under.\n */\nexport interface RootsClient {\n /** Reads a message before the protocol's handler does: `true` where it was the answer to a request of this one's, which is then no one else's. */\n observe(message: unknown): boolean;\n readonly ask: Roots;\n}\n\nexport function rootsClient(write: (line: string) => void, limit = ROOTS_MS): RootsClient {\n let declared = false;\n let asked = 0;\n const waiting = new Map<string, (answer: unknown) => void>();\n const declares = (capabilities: unknown): boolean => isObject(capabilities) && isObject(capabilities['roots']);\n return {\n observe(message) {\n if (!isObject(message)) return false;\n const params = isObject(message['params']) ? message['params'] : {};\n const meta = isObject(params['_meta']) ? params['_meta'] : {};\n if ((message['method'] === 'initialize' && declares(params['capabilities'])) || declares(meta[CLIENT_CAPABILITIES_KEY])) declared = true;\n const id = message['id'];\n // The server's requests have strings for ids, so one that is no string\n // finds nothing waiting either way: the mutant that drops the test is\n // equivalent.\n const settle = typeof id === 'string' && message['method'] === undefined ? waiting.get(id) : undefined;\n if (settle === undefined) return false;\n settle(message);\n return true;\n },\n async ask() {\n if (!declared) return null;\n asked += 1;\n const id = `spec-harness-roots-${asked}`;\n const answer = await new Promise<unknown>((settled) => {\n const timer = setTimeout(() => settled(null), limit);\n waiting.set(id, (message) => {\n clearTimeout(timer);\n settled(message);\n });\n write(JSON.stringify({ jsonrpc: '2.0', id, method: 'roots/list' }));\n });\n waiting.delete(id);\n const result = isObject(answer) ? answer['result'] : undefined;\n const roots = isObject(result) ? result['roots'] : undefined;\n if (!Array.isArray(roots)) return null;\n // A root is a `file:` URI, by the protocol; Node refuses one of any other scheme, which names no directory here.\n return roots.flatMap((root: unknown) => {\n const uri = isObject(root) ? root['uri'] : undefined;\n if (typeof uri !== 'string') return [];\n try {\n return [fileURLToPath(uri)];\n } catch {\n return [];\n }\n });\n },\n };\n}\n\n/** Where a tool reads the round: the work tree, and what named it. */\ninterface Chosen {\n readonly workspace: Workspace;\n readonly from: 'argument' | 'roots' | 'server';\n}\n\n/**\n * The work tree of the server's repository that holds a directory: the\n * server's own where it is in that, with no `.git` between, and otherwise the\n * one git names, where it shares the git directory the server's repository\n * keeps; `null` where the directory is in another repository, or in none.\n */\nasync function treeOf(server: Workspace, io: CliIO, directory: string): Promise<Workspace | null> {\n // Asked anyway, git names the server's own top for a directory in it,\n // which answers the server's own below: the mutant that always asks is\n // equivalent, at a process's cost.\n if (!mayBeElsewhere(directory, server.root)) return server;\n const found = await findTree(directory);\n if (found === null) return null;\n // Its own work tree, opened again, reads every answer the same way: the\n // check saves a start of git, and its mutant is equivalent.\n if (realSpelling(found.root) === realSpelling(server.root)) return server;\n const common = await foundCommonDir(found);\n // git names a common directory wherever it names a top, so `null` is there for the type.\n if (common === null || realSpelling(common) !== realSpelling(server.commonDir)) return null;\n return openFound(found, io, () => [server.root]);\n}\n\n/**\n * The work tree a tool that reads a branch reads the round in (ADR-0008):\n * the one a `directory` given names; where none is given, the one the\n * client's roots name, where they name one work tree of this repository and\n * no other; and the server's own otherwise, as before. The server is started\n * once, for the project Claude Code names, and a session in a worktree\n * names that worktree to it in neither the project nor the server's root.\n */\nasync function chosen(server: Workspace, io: CliIO, roots: Roots, given: unknown): Promise<Chosen | ToolOutcome> {\n if (given !== undefined) {\n if (typeof given !== 'string') return toolError('\"directory\" must be a string.');\n if (isBlank(given)) return toolError(`\"directory\" is ${JSON.stringify(given)}, which names no directory; give it the directory the round is in, or leave it out.`);\n const workspace = await treeOf(server, io, resolve(server.root, given));\n if (workspace === null) return toolError(`\"directory\" is ${JSON.stringify(given)}, which is in no work tree of this repository; give a directory in the project or in one of its worktrees, or leave it out.`);\n return { workspace, from: 'argument' };\n }\n const named = await roots();\n if (named !== null) {\n const trees = new Map<string, Workspace>();\n for (const directory of named) {\n const workspace = await treeOf(server, io, directory);\n if (workspace !== null) trees.set(realSpelling(workspace.root), workspace);\n }\n const [only, ...more] = [...trees.values()];\n if (only !== undefined && more.length === 0) return { workspace: only, from: 'roots' };\n }\n return { workspace: server, from: 'server' };\n}\n\n/** What a tool's answer says of the work tree it read: always in its structured part, and in its text where it is not the server's own. */\nfunction readIn(where: Chosen): { readonly said: string; readonly workTree: JsonObject } {\n const how = where.from === 'argument' ? 'the \"directory\" given' : \"the client's roots\";\n return { said: where.from === 'server' ? '' : `\\n\\nRead in the work tree at ${where.workspace.root}, which ${how} name.`, workTree: { root: where.workspace.root, from: where.from } };\n}\n\n/** The `base` argument, or the tool error for one that is not a string, or names no commit. */\nfunction baseOf(args: JsonObject): { base: string | undefined } | ToolOutcome {\n const base = args['base'];\n if (base !== undefined && typeof base !== 'string') return toolError('\"base\" must be a string.');\n if (base !== undefined && isBlank(base)) return namesNothing('base', 'base', base);\n return { base };\n}\n\n/** The `paths` argument, or the tool error for one that is no list of files, or has a place that names none. */\nfunction pathsOf(args: JsonObject): { paths: string[] } | ToolOutcome {\n const paths = args['paths'];\n if (!Array.isArray(paths) || !paths.every((p) => typeof p === 'string') || paths.length === 0) {\n return toolError('\"paths\" must be a non-empty array of strings.');\n }\n const empty = paths.findIndex(isBlank);\n if (empty !== -1) return namesNothing(`paths[${empty}]`, 'path', paths[empty] as string);\n return { paths };\n}\n\n/**\n * The `options` argument as the memo's choices, or the tool error for one\n * the memo cannot be written with: a choice is its label, and one without\n * was written as a number and two empty stars. What a choice costs may be\n * left out, and the memo then gives the choice alone.\n */\nfunction optionsOf(args: JsonObject): { options: EscalationOption[] } | ToolOutcome {\n const raw = args['options'] ?? [];\n if (!Array.isArray(raw)) return toolError('\"options\" must be an array.');\n const options: EscalationOption[] = [];\n for (const [index, item] of raw.entries()) {\n // An item that is no object has no label, and is refused for that.\n const entry: JsonObject = item ?? {};\n const label = entry['label'];\n const consequence = entry['consequence'] ?? '';\n if (typeof label !== 'string') return toolError(`\"options[${index}].label\" must be a string.`);\n if (isBlank(label)) return toolError(`\"options[${index}].label\" is ${JSON.stringify(label)}, which names no choice; give the option a label, or leave the option out.`);\n if (typeof consequence !== 'string') return toolError(`\"options[${index}].consequence\" must be a string.`);\n options.push({ label: label.trim(), consequence: consequence.trim() });\n }\n return { options };\n}\n\nasync function round(workspace: Workspace, env: CliIO['env'], id: unknown): Promise<{ brief: BriefRow; briefs: BriefRow[] } | ToolOutcome> {\n if (id !== undefined && typeof id !== 'string') return toolError('\"brief\" must be a string.');\n if (id !== undefined && isBlank(id)) return namesNothing('brief', 'brief', id);\n const briefs = await workspace.siblings.briefs();\n const fromBranch = briefIdFromBranch(workspace.config.branches, workspace.branch);\n const active = findActive(briefs, { argument: id, environment: env['SPEC_BRIEF'], branch: fromBranch });\n // Named as every argument of a tool is, where it was called the flag, and\n // a tool call has none.\n const { brief, note, problem } = describeActive(active, '\"brief\"');\n if (problem !== null) return toolError(problem);\n if (brief === null) return toolError(note);\n return { brief, briefs };\n}\n\n/**\n * The brief the argument, `SPEC_BRIEF` or the branch names, as the hook\n * finds it: where nothing names one, spec-brief is not asked, and the answer\n * is no brief whatever spec-brief would say (ADR-0004), so the empty list is\n * equivalent to its mutant.\n */\nasync function namedBrief(workspace: Workspace, env: CliIO['env'], id: string | undefined): Promise<ActiveBrief> {\n if (namedId(workspace, { brief: id }, env) === null) return findActive([], {});\n const briefs = await workspace.siblings.briefs();\n return findActive(briefs, { argument: id, environment: env['SPEC_BRIEF'], branch: briefIdFromBranch(workspace.config.branches, workspace.branch) });\n}\n\n/**\n * Each path as the hook decides a write of it alone (ADR-0005, ADR-0008): one\n * outside every work tree of the repository as a file outside it, with no\n * brief asked about, whatever names one; the rest by the brief named, with\n * no brief where nothing names one, and held, in the hook's words, where\n * what names it names none a round can work under. spec-brief is asked only\n * where a path is inside, as the hook asks it.\n */\nasync function asTheHook(workspace: Workspace, env: CliIO['env'], id: string | undefined, paths: readonly string[], cwd: string, base: string | undefined): Promise<Decision[]> {\n const outside = paths.map((path) => outsideEvery([path], workspace.root, workspace.commonDir, cwd));\n // Paths all outside ask about no brief, and are answered as with none\n // named: the empty list is equivalent to its mutant, as in namedBrief.\n const { brief, note, problem } = describeActive(outside.every((each) => each) ? findActive([], {}) : await namedBrief(workspace, env, id), '\"brief\"');\n if (problem === null) return checkPaths(workspace, brief, note, paths, cwd, reader, base);\n // Decided by no brief, a path outside is decided as outside the\n // repository, and one inside is held, named as the repository names it.\n const decided = await checkPaths(workspace, null, undefined, paths, cwd, reader, base);\n return decided.map((decision, at) => (outside[at] ? decision : heldBy(decision.path, problem)));\n}\n\nexport function tools(workspace: Workspace, env: CliIO['env'], roots: Roots = NO_ROOTS): ToolDefinition[] {\n const readOnly = { readOnlyHint: true, idempotentHint: true, openWorldHint: false };\n // A tool writes nothing to the server's streams, so these are never\n // written to, and their mutants are equivalent: what a tool says is its\n // answer.\n const quiet = { write: (): boolean => true };\n const io: CliIO = { stdout: quiet, stderr: quiet, cwd: workspace.cwd, env };\n return [\n {\n descriptor: {\n name: 'start_round',\n title: 'Start a round',\n description:\n 'Everything needed to start the round: the brief in full, the files it may write and must not change, signed rulings, the briefs it depends on, the architecture rules in force for its scope, and the documents it cites.',\n inputSchema: { type: 'object', properties: { brief: briefProperty, base: baseProperty, directory: directoryProperty }, additionalProperties: false },\n annotations: readOnly,\n },\n async call(args: JsonObject): Promise<ToolOutcome> {\n const unknown = unknownArguments(args, ['brief', 'base', 'directory']);\n if (unknown) return unknown;\n const base = baseOf(args);\n if ('text' in base) return base;\n const where = await chosen(workspace, io, roots, args['directory']);\n if ('text' in where) return where;\n const found = await round(where.workspace, env, args['brief']);\n if ('text' in found) return found;\n const packet = await buildContext(where.workspace, found.brief, found.briefs, reader, base.base);\n const { said, workTree } = readIn(where);\n return {\n text: `${packet.markdown}${said}`,\n structured: {\n workTree,\n brief: found.brief.id,\n included: [...packet.included],\n omitted: [...packet.omitted],\n unresolved: [...packet.unresolved],\n unclosedFrontMatter: [...packet.unclosedFrontMatter],\n unreadableFrontMatter: [...packet.unreadableFrontMatter],\n unreadableScope: [...packet.unreadableScope],\n unreadableProtections: [...packet.unreadableProtections],\n unreadableRulingPaths: [...packet.unreadableRulingPaths],\n unmatchedSpecs: [...packet.unmatchedSpecs],\n },\n };\n },\n },\n {\n descriptor: {\n name: 'check_path',\n title: 'May the round write these files',\n description:\n 'For each path, as the guard hook decides a write of it: allowed (in scope, covered by a signed ruling, outside every work tree of the repository, or with no brief named), outside the scope, or refused (protected by the brief, or held where what names the brief names none a round can work under). Works for files that do not exist yet.',\n inputSchema: {\n type: 'object',\n properties: {\n paths: {\n type: 'array',\n items: { type: 'string' },\n description: 'Paths relative to the top of the work tree the round is in, or absolute; an absolute one in another work tree of this repository is decided by that one. An empty one is refused.',\n },\n brief: briefProperty,\n base: baseProperty,\n directory: directoryProperty,\n },\n required: ['paths'],\n additionalProperties: false,\n },\n annotations: readOnly,\n },\n async call(args: JsonObject): Promise<ToolOutcome> {\n const unknown = unknownArguments(args, ['paths', 'brief', 'base', 'directory']);\n if (unknown) return unknown;\n const given = pathsOf(args);\n if ('text' in given) return given;\n const base = baseOf(args);\n if ('text' in base) return base;\n const where = await chosen(workspace, io, roots, args['directory']);\n if ('text' in where) return where;\n const id = args['brief'];\n if (id !== undefined && typeof id !== 'string') return toolError('\"brief\" must be a string.');\n if (id !== undefined && isBlank(id)) return namesNothing('brief', 'brief', id);\n // Each path by the work tree of this repository that holds it, as the\n // hook decides a write: the one read, another, or the server's own.\n const decisions: Decision[] = [];\n for (const part of await writesBy(workspace, where.workspace.root, given.paths, io)) {\n decisions.push(...(await asTheHook(part.workspace, env, id, part.paths, where.workspace.root, base.base)));\n }\n const text = decisions.map((d) => `${d.verdict}: ${d.message}${d.verdict === 'allow' ? '' : `. Next: ${d.hint}`}`).join('\\n');\n const { said, workTree } = readIn(where);\n return { text: `${text}${said}`, structured: { workTree, decisions: decisions.map((d) => ({ ...d })) } };\n },\n },\n {\n descriptor: {\n name: 'request_escalation',\n title: 'Ask a person to rule',\n description:\n 'When the round cannot be finished without changing something the brief protects, record the request and stop. A person reads the memo and rules; only a ruling they sign lets the change through.',\n inputSchema: {\n type: 'object',\n properties: {\n paths: { type: 'array', items: { type: 'string' }, description: 'The protected files the round needs to change. An empty one is refused.' },\n reason: { type: 'string', description: 'Why the round cannot be done without them. It is required, and may not be empty.' },\n options: {\n type: 'array',\n items: { type: 'object', properties: { label: { type: 'string' }, consequence: { type: 'string' } }, required: ['label', 'consequence'] },\n description: 'The choices the person has, each with what it costs. A choice whose label is empty is refused.',\n },\n recommendation: { type: 'string', description: 'Which option you recommend, and why. Omit it when there is none: an empty one is refused.' },\n brief: briefProperty,\n directory: directoryProperty,\n },\n required: ['paths', 'reason'],\n additionalProperties: false,\n },\n annotations: { readOnlyHint: false, idempotentHint: false, openWorldHint: false },\n },\n async call(args: JsonObject): Promise<ToolOutcome> {\n const unknown = unknownArguments(args, ['paths', 'reason', 'options', 'recommendation', 'brief', 'directory']);\n if (unknown) return unknown;\n // Every part of the memo before anything is written: a person rules\n // on what it says, and cannot rule on a part that says nothing.\n const given = pathsOf(args);\n if ('text' in given) return given;\n const reason = args['reason'];\n if (typeof reason !== 'string' || isBlank(reason)) return toolError('\"reason\" is required.');\n const choices = optionsOf(args);\n if ('text' in choices) return choices;\n const recommendation = args['recommendation'];\n if (recommendation !== undefined && typeof recommendation !== 'string') return toolError('\"recommendation\" must be a string.');\n if (recommendation !== undefined && isBlank(recommendation)) return namesNothing('recommendation', 'recommend', recommendation);\n const where = await chosen(workspace, io, roots, args['directory']);\n if ('text' in where) return where;\n const found = await round(where.workspace, env, args['brief']);\n if ('text' in found) return found;\n const { request, memo } = await raiseEscalation(where.workspace, found.brief, {\n paths: given.paths,\n reason,\n options: choices.options,\n recommendation: recommendation ?? null,\n });\n const { said, workTree } = readIn(where);\n return { text: `${memo}\\nStop here until a person rules on ${request.id}.${said}`, structured: { id: request.id, workTree } };\n },\n },\n {\n descriptor: {\n name: 'audit_round',\n title: 'Audit the round',\n description:\n 'Did the round stay inside the lines: what the archive would refuse (open boxes, protected files, files outside the scope), the brief\\'s own assertions, unverified rulings, every dependency added and every package allowed to run install scripts.',\n inputSchema: { type: 'object', properties: { brief: briefProperty, base: baseProperty, directory: directoryProperty }, additionalProperties: false },\n annotations: readOnly,\n },\n async call(args: JsonObject): Promise<ToolOutcome> {\n const unknown = unknownArguments(args, ['brief', 'base', 'directory']);\n if (unknown) return unknown;\n const base = baseOf(args);\n if ('text' in base) return base;\n const where = await chosen(workspace, io, roots, args['directory']);\n if ('text' in where) return where;\n const found = await round(where.workspace, env, args['brief']);\n if ('text' in found) return found;\n const result = await runAudit(where.workspace, found.brief, reader, base.base);\n const { counts, findings, measured } = result.report;\n // What was measured beside what was found: \"nothing found\" from an\n // audit that ran no goal is not a round that is done.\n const text =\n findings.length === 0\n ? 'The audit found nothing in what it measured.'\n : findings.map((f) => `${f.severity} ${f.rule}: ${f.message}. Next: ${f.hint}`).join('\\n');\n const { said, workTree } = readIn(where);\n return {\n text: `${text}\\n\\n${describeMeasured(measured)}\\n\\n${counts.error} error(s), ${counts.warning} warning(s), ${counts.note} note(s)${said}`,\n structured: { workTree, counts, measured: { ...measured }, findings: findings.map((f) => ({ ...f })) },\n };\n },\n },\n {\n descriptor: {\n name: 'list_rounds',\n title: 'List the rounds',\n description: 'The live briefs: status, wave, what each waits on, and which are ready to start.',\n inputSchema: { type: 'object', properties: {}, additionalProperties: false },\n annotations: readOnly,\n },\n async call(args: JsonObject): Promise<ToolOutcome> {\n const unknown = unknownArguments(args, []);\n if (unknown) return unknown;\n const live = (await workspace.siblings.briefs()).filter((brief) => brief.phase === 'live');\n const text = live\n .map((b) => `${[b.id, titleOf(b)].filter((part) => part !== null).join(' ')} - ${b.status ?? 'unknown'}, wave ${b.wave ?? '-'}, ${b.ready ? 'ready' : `waits on ${b.waitingOn.join(', ')}`}`)\n .join('\\n');\n return { text: text === '' ? 'No live brief.' : text, structured: { briefs: live.map((b) => ({ ...b, title: titleOf(b) })) } };\n },\n },\n ];\n}\n\nconst SKILLS: readonly { name: string; title: string; argument: string; description: string }[] = [\n { name: 'draft-brief', title: 'Draft a brief', argument: 'request', description: 'What the round should achieve, in the person\\'s words.' },\n { name: 'split-goal', title: 'Split a goal into rounds', argument: 'goal', description: 'The goal to split.' },\n { name: 'run-round', title: 'Run a round', argument: 'brief', description: 'The brief id.' },\n { name: 'close-round', title: 'Close a round', argument: 'brief', description: 'The brief id.' },\n];\n\nfunction skillText(name: string): string {\n // The package ships the skills beside dist/ (package.json's files), so one\n // that cannot be read is a broken install, and the request fails saying so\n // rather than serving an empty prompt.\n const text = readFileSync(fileURLToPath(new URL(`../skills/${name}/SKILL.md`, import.meta.url)), 'utf8');\n // Every skill opens with its front matter (tests/source.test.ts), so the\n // anchor is equivalent to its mutant here.\n return text.replace(/^---\\r?\\n[\\s\\S]*?\\r?\\n---\\r?\\n/, '').trim();\n}\n\nexport function prompts(): PromptDefinition[] {\n return SKILLS.map((skill) => ({\n descriptor: {\n name: skill.name,\n title: skill.title,\n arguments: [{ name: skill.argument, description: skill.description, required: false }],\n },\n async get(args: Readonly<Record<string, string>>): Promise<JsonObject> {\n const given = args[skill.argument];\n const text = `${skillText(skill.name)}${given === undefined || given === '' ? '' : `\\n\\n${skill.argument}: ${given}`}`;\n return { description: skill.title, messages: [{ role: 'user', content: { type: 'text', text } }] };\n },\n }));\n}\n\nexport async function mcpCommand(options: Options, io: CliIO): Promise<number> {\n // Claude Code starts a plugin's server in the plugin's directory, and names\n // the project in CLAUDE_PROJECT_DIR; the server answers for the project.\n const workspace = await openWorkspace({ ...options, root: options.root ?? (io.env['CLAUDE_PROJECT_DIR'] || undefined) }, io);\n const write = (line: string): void => {\n io.stdout.write(`${line}\\n`);\n };\n // The work tree a session is in, where its client names it (ADR-0008).\n const roots = rootsClient(write);\n const handle = createMcpServer({ name: 'spec-harness', version: version(), instructions: INSTRUCTIONS, tools: tools(workspace, io.env, roots.ask), prompts: prompts() });\n // A session handed over whole, as a test hands it, is served as a client\n // would stream it on stdin. Only the built command line serves\n // process.stdin, and the suite spawns it from dist/, outside the sweep\n // (tests/integration/mcp.test.ts), so a mutant that ignores it survives.\n const input = io.stdin === undefined ? process.stdin : Readable.from([Buffer.from(await io.stdin())]);\n await serveLines(input, write, async (message) => (roots.observe(message) ? null : handle(message)));\n return 0;\n}\n"]}
|
package/dist/setup.js
CHANGED
|
@@ -15,7 +15,7 @@ import { accessSync, constants, existsSync, statSync } from 'node:fs';
|
|
|
15
15
|
import { chmod, mkdir, readFile } from 'node:fs/promises';
|
|
16
16
|
import { dirname, isAbsolute, join, relative, sep } from 'node:path';
|
|
17
17
|
import { CONFIG_FILE } from './config.js';
|
|
18
|
-
import { arrayMatcher, chooseBase, describeAbsent, describeArrayMatcher, describeGitHook, describeGraph, describeHooksOff, describePresence, describeSkipped, GIT_HOOK_LINE, gitHookNote, graphReadsBriefs, GUARD_HOOK, guardSwitchedOff, isStarted, loadsPlugin, matchingUnder, measuresArchive, mergeClaudeSettings, withSessionStart, mergeMcp, mergeSpecBrief, mergeSpecGraph, missingGitHook, ONE_STRING, patternReader, PLUGIN, PRE_COMMIT, PROJECT_SETTINGS, PROTECT_RULE_FILES, registersServer, SPEC_BRIEF_CONFIGS, SPEC_GRAPH_CONFIGS, } from './configure.js';
|
|
18
|
+
import { arrayMatcher, chooseBase, describeAbsent, describeArrayMatcher, describeGitHook, describeGraph, describeHooksOff, describePresence, describeSkipped, GIT_HOOK_LINE, gitHookNote, graphReadsBriefs, GUARD_HOOK, guardSwitchedOff, isStarted, loadsPlugin, matchingUnder, measuresArchive, mergeClaudeSettings, withOnFailure, withSessionStart, withTurnReport, reportsTurns, TURN_HOOK, mergeMcp, mergeSpecBrief, mergeSpecGraph, missingGitHook, ON_FAILURE_SINCE, ONE_STRING, patternReader, PLUGIN, PRE_COMMIT, PROJECT_SETTINGS, PROTECT_RULE_FILES, registersServer, SPEC_BRIEF_CONFIGS, SPEC_GRAPH_CONFIGS, } from './configure.js';
|
|
19
19
|
import { readJsonObject as readJson, writeAtomic } from './fs.js';
|
|
20
20
|
import { hookPath, localBranches, remoteDefault } from './git.js';
|
|
21
21
|
import { claudeCodeWiring, pluginFile } from './round.js';
|
|
@@ -135,7 +135,9 @@ export async function plan(workspace, options, io) {
|
|
|
135
135
|
const base = choice === null ? namedBase : choice.base;
|
|
136
136
|
// spec-brief first: every other setting is derived from its directories.
|
|
137
137
|
const briefConfig = SPEC_BRIEF_CONFIGS.find((name) => existsSync(join(root, name)));
|
|
138
|
-
|
|
138
|
+
// One name for the sibling found and for the sibling run, which a run that is stopped says.
|
|
139
|
+
const tool = 'spec-brief';
|
|
140
|
+
const brief = workspace.siblings.locate(tool);
|
|
139
141
|
let briefs = 'briefs';
|
|
140
142
|
let archive = 'briefs/archive';
|
|
141
143
|
if (briefConfig === undefined) {
|
|
@@ -147,7 +149,7 @@ export async function plan(workspace, options, io) {
|
|
|
147
149
|
action: 'run',
|
|
148
150
|
detail: 'spec-brief init: the brief and archive directories, every default spelled out',
|
|
149
151
|
apply: async () => {
|
|
150
|
-
const run = await runSibling(command, ['init'], root);
|
|
152
|
+
const run = await runSibling(tool, command, ['init'], root);
|
|
151
153
|
if (run.code !== 0)
|
|
152
154
|
throw new Error(`spec-brief init failed: ${run.stderr.trim()}`);
|
|
153
155
|
},
|
|
@@ -281,6 +283,14 @@ export async function plan(workspace, options, io) {
|
|
|
281
283
|
const detail = describeSkipped(plugin, 'hooks', present, wiring.hooks);
|
|
282
284
|
steps.push({ file: SETTINGS, action: wiring.hooks.length > 0 ? 'advise' : 'skip', detail: untold === null ? detail : `${detail}. ${untold}` });
|
|
283
285
|
}
|
|
286
|
+
// The plugin's hooks are the same for every project, and run the report
|
|
287
|
+
// for none: one that asks for it adds the entry, which guards nothing
|
|
288
|
+
// twice (ADR-0012). Only init's own line is known here, so a line a
|
|
289
|
+
// person wrote under the event has the entry advised beside it; an
|
|
290
|
+
// `undefined` reads as the `false` does, and that mutant is equivalent.
|
|
291
|
+
if (workspace.config.turnReport && !reportsTurns(settings, () => false)) {
|
|
292
|
+
steps.push({ file: SETTINGS, action: 'advise', detail: `"turnReport" is on, and the plugin brings no hook for the end of a turn: add ${JSON.stringify({ hooks: [TURN_HOOK] })} under "Stop"` });
|
|
293
|
+
}
|
|
284
294
|
}
|
|
285
295
|
else if (settings === 'unreadable') {
|
|
286
296
|
steps.push({ file: SETTINGS, action: 'advise', detail: `cannot be read as JSON; add the guard as a PreToolUse and a PostToolUse hook by hand: ${JSON.stringify(GUARD_HOOK)}` });
|
|
@@ -300,23 +310,43 @@ export async function plan(workspace, options, io) {
|
|
|
300
310
|
// them, or by itself in a file whose two an earlier release wrote. A file
|
|
301
311
|
// with a line of the person's is theirs to complete (ADR-0012).
|
|
302
312
|
const started = left === '' ? withSessionStart(guarded ?? settings ?? {}, isHook) : null;
|
|
303
|
-
|
|
313
|
+
// The report at the end of a turn, where the configuration asks for one,
|
|
314
|
+
// beside the entries as init writes them (ADR-0005, ADR-0012).
|
|
315
|
+
const turned = left === '' && workspace.config.turnReport ? withTurnReport(started ?? guarded ?? settings ?? {}, isHook) : null;
|
|
316
|
+
const merged = turned ?? started ?? guarded;
|
|
304
317
|
// A line that turns the guard off or holds every write is one doctor
|
|
305
318
|
// fails, and lines of which none is waited on before a write are no
|
|
306
319
|
// guard between them: left as they are, they are for the person to mend.
|
|
307
320
|
const broken = lines.some((line) => line.state === 'off' || line.state === 'held') || !lines.some((line) => isStarted(line.before));
|
|
308
321
|
const atStart = 'a SessionStart hook says, as a session starts, what would hold every write of it';
|
|
309
|
-
|
|
322
|
+
const atEnd = 'a Stop hook, in the background, tells Claude as each turn begins what the work tree held at the end of the last that the brief protects or that is outside its scope';
|
|
323
|
+
const beside = [started === null ? null : atStart, turned === null ? null : atEnd].filter((part) => part !== null);
|
|
324
|
+
// Asked for, onFailure "block" on init's own entries before and after a
|
|
325
|
+
// write and as a session starts, those it writes now and those a run
|
|
326
|
+
// before wrote, where it writes or keeps them: no page says what a
|
|
327
|
+
// Claude Code before 2.1.295 does with the key, so it is written only
|
|
328
|
+
// where asked for. The entry at the end of a turn runs in the
|
|
329
|
+
// background, where the hooks reference gives the field no effect, and
|
|
330
|
+
// is left without it (ADR-0012).
|
|
331
|
+
const blocked = options.blockOnFailure && (merged !== null || !broken) ? withOnFailure(merged ?? settings ?? {}) : null;
|
|
332
|
+
const written = blocked ?? merged;
|
|
333
|
+
const holds = `onFailure "block" on init's PreToolUse, PostToolUse and SessionStart entries, so that Claude Code ${ON_FAILURE_SINCE} or later holds a write where the hook cannot start or runs past its timeout`;
|
|
334
|
+
if (written === null)
|
|
310
335
|
steps.push({ file: SETTINGS, action: broken ? 'advise' : 'keep', detail: left === '' ? 'the guard hooks are installed' : left });
|
|
311
|
-
else
|
|
336
|
+
else {
|
|
337
|
+
// What onFailure adds is said after what else is written, and alone where nothing else is.
|
|
338
|
+
const what = merged === null
|
|
339
|
+
? holds
|
|
340
|
+
: guarded === null
|
|
341
|
+
? `beside the guard hooks, ${beside.join('; ')}`
|
|
342
|
+
: `the guard hooks, run with node from the project's install: a PreToolUse hook refuses writes to protected files; a PostToolUse hook warns about writes outside the scope${beside.map((part) => `; ${part}`).join('')}${left === '' ? '' : `; ${left}`}`;
|
|
312
343
|
steps.push({
|
|
313
344
|
file: SETTINGS,
|
|
314
345
|
action: settings === null ? 'create' : 'update',
|
|
315
|
-
detail:
|
|
316
|
-
|
|
317
|
-
: `the guard hooks, run with node from the project's install: a PreToolUse hook refuses writes to protected files; a PostToolUse hook warns about writes outside the scope${started === null ? '' : `; ${atStart}`}${left === '' ? '' : `; ${left}`}`,
|
|
318
|
-
apply: () => writeAtomic(settingsFile, stringify(merged)),
|
|
346
|
+
detail: blocked === null || merged === null ? what : `${what}; ${holds}`,
|
|
347
|
+
apply: () => writeAtomic(settingsFile, stringify(written)),
|
|
319
348
|
});
|
|
349
|
+
}
|
|
320
350
|
}
|
|
321
351
|
// disableAllHooks turns off whatever hooks there are, and those init
|
|
322
352
|
// writes with them: said of the file that holds the key, which is the
|
package/dist/setup.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `spec-harness init`: the family configured to agree, from the first day.\n *\n * The integration faults found when the tools were first run together were all\n * configuration: spec-graph read an archived brief as a retired decision and\n * reported every brief that depended on one; spec-guard executed an archived\n * brief's assertions. Each tool can be told the truth; `init` tells each of\n * them the same truth, derived from spec-brief's own settings.\n *\n * It prints a plan and changes nothing until `--write`. It merges into files\n * that exist and never replaces what a person wrote; a git hook the\n * repository already has is left alone, with the line to add printed instead.\n */\n\nimport { accessSync, constants, existsSync, statSync, type Stats } from 'node:fs';\nimport { chmod, mkdir, readFile } from 'node:fs/promises';\nimport { dirname, isAbsolute, join, relative, sep } from 'node:path';\n\nimport { CONFIG_FILE } from './config.js';\nimport {\n arrayMatcher,\n chooseBase,\n describeAbsent,\n describeArrayMatcher,\n describeGitHook,\n describeGraph,\n describeHooksOff,\n describePresence,\n describeSkipped,\n GIT_HOOK_LINE,\n gitHookNote,\n type GitHookState,\n graphReadsBriefs,\n GUARD_HOOK,\n guardSwitchedOff,\n isStarted,\n loadsPlugin,\n matchingUnder,\n measuresArchive,\n mergeClaudeSettings,\n withSessionStart,\n mergeMcp,\n mergeSpecBrief,\n mergeSpecGraph,\n missingGitHook,\n ONE_STRING,\n patternReader,\n PLUGIN,\n PRE_COMMIT,\n PROJECT_SETTINGS,\n PROTECT_RULE_FILES,\n registersServer,\n SPEC_BRIEF_CONFIGS,\n SPEC_GRAPH_CONFIGS,\n} from './configure.js';\nimport { readJsonObject as readJson, writeAtomic } from './fs.js';\nimport { hookPath, localBranches, remoteDefault } from './git.js';\nimport { claudeCodeWiring, pluginFile } from './round.js';\nimport { runSibling } from './siblings.js';\nimport { answerOf, EXIT_ERROR, EXIT_OK, json, openWorkspace, type CliIO, type Options, type Workspace } from './workspace.js';\n\n/** `skip`: a file init would write, left alone because Claude Code's plugin brings what init would add. */\nexport type Action = 'create' | 'update' | 'keep' | 'skip' | 'run' | 'advise';\n\nexport interface Step {\n readonly file: string;\n readonly action: Action;\n readonly detail: string;\n apply?: () => Promise<void>;\n}\n\ntype Json = Record<string, unknown>;\n\n/** The project's settings file for Claude Code, as a person finds it and as doctor names it. */\nconst SETTINGS = PROJECT_SETTINGS;\n\nfunction stringify(value: unknown): string {\n return `${JSON.stringify(value, null, 2)}\\n`;\n}\n\nconst PLUGIN_DETAIL = `load spec-harness's plugin, \"${PLUGIN}\": spec-brief's archive asks it whether a signed ruling allows a protected file, and refuses the file without it`;\n\n/** What init adds to spec-brief's configuration, said once for the plan. */\nfunction specBriefDetail(plugin: boolean, base: string | null): string {\n const parts = plugin ? [PLUGIN_DETAIL] : [];\n if (base !== null) parts.push(`measure the archive from ${base}, as spec-harness does: without a base, spec-brief's archive warns that the scope went unmeasured and checks no protected file`);\n return parts.join('; ');\n}\n\n/** A path as a person finds it: from the root when it is inside it, POSIX-separated, and as it is otherwise. */\nfunction shown(root: string, path: string): string {\n const inside = relative(root, path);\n return inside.startsWith('..') || isAbsolute(inside) ? path : inside.split(sep).join('/');\n}\n\n/**\n * Whether git takes what stands at a hook's path for a hook to run. git\n * asks the system whether the path can be executed, and skips one that\n * cannot, with no more than a hint: asked here the same way. On Windows the\n * question is only whether the path is there (Node's fs page, File access\n * constants, read 2026-10-14), and git there runs whatever is.\n */\nfunction executable(path: string): boolean {\n let may = true;\n try {\n accessSync(path, constants.X_OK);\n } catch {\n may = false;\n }\n return may;\n}\n\n/** What stands at a path, links followed, or `null` where nothing does: a link to nothing is nothing, to git as well. */\nfunction standing(path: string): Stats | null {\n try {\n return statSync(path);\n } catch {\n return null;\n }\n}\n\n/**\n * git's pre-commit hook, where git runs it from, and what is there: init and\n * doctor both read it. `path` is `null` when git cannot say where its hooks\n * are, which is said in git's own words: a `core.hooksPath` that names a\n * file is refused by git as no directory, and git then commits with no hook\n * (ADR-0005). `note` is what there is to say of how a hook that runs the\n * harness runs it, or `null`.\n *\n * Only a file is read. A directory under the hook's name, which a\n * repository whose `core.hooksPath` is in its work tree can hold, is not a\n * hook and is one to git all the same: it tries to run what it can execute\n * there, fails, and stops the commit (ADR-0005 has what was measured). Read\n * as a file, it ended this on Node's EISDIR and a stack, and a named pipe\n * would have kept it from ever coming back. A file the account may not read\n * ended it on EACCES and a stack: it is said with what git does with it.\n */\nexport async function gitHook(root: string): Promise<{ readonly hook: GitHookState; readonly path: string | null; readonly note: string | null }> {\n const where = await hookPath('pre-commit', root);\n if ('refused' in where) return { hook: { state: 'unknown', reason: `git rev-parse --git-path hooks/pre-commit failed: ${where.refused}` }, path: null, note: null };\n const { path } = where;\n const file = shown(root, path);\n const there = standing(path);\n if (there === null) return { hook: { state: 'absent', file }, path, note: null };\n const runs = executable(path);\n if (!there.isFile()) {\n const what = there.isDirectory() ? 'a directory' : 'neither a file nor a directory';\n return { hook: { state: runs ? 'stops' : 'ignored', file, what }, path, note: null };\n }\n let text: string;\n try {\n text = await readFile(path, 'utf8');\n } catch (error) {\n return { hook: { state: 'unreadable', file, runs, reason: (error as Error).message }, path, note: null };\n }\n if (!text.includes('spec-harness')) return { hook: { state: 'other', file }, path, note: null };\n return { hook: { state: runs ? 'runs' : 'inert', file }, path, note: gitHookNote(text) };\n}\n\nexport async function plan(workspace: Workspace, options: Options, io: CliIO): Promise<Step[]> {\n const { root } = workspace;\n const steps: Step[] = [];\n\n // The base rounds merge into, decided once: spec-harness verifies rulings\n // against the allowed signers on it, and spec-brief's archive measures the\n // round from it. A base a person wrote, in either file, is kept.\n // openWorkspace loaded this file and refused one that is not a JSON object,\n // so here it is one, or there is none.\n const harnessFile = join(root, CONFIG_FILE);\n const harness = (await readJson(harnessFile)) as Json | null;\n const namedBase = harness !== null && typeof harness['base'] === 'string' ? harness['base'] : null;\n // What the plan asks of git and of Claude Code's settings waits on the\n // root and on nothing of the rest, so it is asked at once: three of git's\n // processes side by side where each waited on the one before. Each is\n // read below where it was asked before, so a plan that fails still fails\n // on the first of them in that order. The matchers in the settings are\n // read with one reader, for the wiring and for what to write. Claude\n // Code's release is asked only where what is read of a line turns on it.\n const pattern = patternReader();\n const [factsAsked, wiringAsked, hookAsked] = await Promise.allSettled([\n namedBase === null ? Promise.all([remoteDefault(root), localBranches(root)]) : null,\n claudeCodeWiring(root, io, pattern, false),\n gitHook(root),\n ]);\n const facts = answerOf(factsAsked);\n const choice = facts === null ? null : chooseBase({ remoteDefault: facts[0], branch: workspace.branch, branches: facts[1] });\n const base = choice === null ? namedBase : choice.base;\n\n // spec-brief first: every other setting is derived from its directories.\n const briefConfig = SPEC_BRIEF_CONFIGS.find((name) => existsSync(join(root, name)));\n const brief = workspace.siblings.locate('spec-brief');\n let briefs = 'briefs';\n let archive = 'briefs/archive';\n if (briefConfig === undefined) {\n if (brief.kind === 'found') {\n const command = brief.command;\n const created = join(root, '.spec-brief.json');\n steps.push({\n file: '.spec-brief.json',\n action: 'run',\n detail: 'spec-brief init: the brief and archive directories, every default spelled out',\n apply: async () => {\n const run = await runSibling(command, ['init'], root);\n if (run.code !== 0) throw new Error(`spec-brief init failed: ${run.stderr.trim()}`);\n },\n });\n steps.push({\n file: '.spec-brief.json',\n action: 'update',\n detail: specBriefDetail(true, base),\n apply: async () => {\n const written = await readJson(created);\n if (written === null || written === 'unreadable') throw new Error('spec-brief init wrote no configuration JSON can read');\n const merged = mergeSpecBrief(written, base, pluginFile(root));\n if (merged !== null) await writeAtomic(created, stringify(merged));\n },\n });\n } else {\n steps.push({ file: '.spec-brief.json', action: 'advise', detail: brief.reason });\n }\n } else {\n const file = join(root, briefConfig);\n const config = await readJson(file);\n // The file was found a moment ago, so null is one removed in between; and\n // a string has neither key, so these checks are there for the type.\n if (config !== null && config !== 'unreadable') {\n if (typeof config['briefs'] === 'string') briefs = config['briefs'];\n archive = typeof config['archive'] === 'string' ? config['archive'] : `${briefs}/archive`;\n }\n steps.push({ file: briefConfig, action: 'keep', detail: `briefs in ${briefs}/, the archive in ${archive}/` });\n // spec-brief's archive learns that a signed ruling allows a protected file\n // only from this package's plugin (ADR-0006).\n if (config === 'unreadable' || config === null) {\n const measure = base === null ? '' : `, and \"archiving\": { \"base\": \"${base}\" }`;\n steps.push({ file: briefConfig, action: 'advise', detail: `cannot be read as JSON; add \"plugins\": [\"${PLUGIN}\"]${measure} by hand` });\n } else {\n const isPluginFile = pluginFile(root);\n const merged = mergeSpecBrief(config, base, isPluginFile);\n const measured = measuresArchive(config);\n if (merged === null) {\n const archiving = config['archiving'];\n const from = measured ? `, and the archive is measured from ${String((archiving as Json)['base'])}` : '';\n steps.push({ file: briefConfig, action: 'keep', detail: `spec-harness's plugin is loaded${from}` });\n } else {\n const detail = specBriefDetail(!loadsPlugin(config, isPluginFile), measured ? null : base);\n steps.push({ file: briefConfig, action: 'update', detail, apply: () => writeAtomic(file, stringify(merged)) });\n }\n }\n }\n\n // spec-graph: an archived brief is a record, not a retired decision. Its\n // configuration is the first of its files, then a key in package.json; a\n // file written beside that key would shadow it.\n const graph = workspace.siblings.locate('spec-graph');\n if (graph.kind === 'outdated') steps.push({ file: '.spec-graph.json', action: 'advise', detail: graph.reason });\n if (graph.kind === 'found') {\n const archiveGlob = `${archive}/**`;\n const graphName = SPEC_GRAPH_CONFIGS.find((name) => existsSync(join(root, name)));\n const manifest = graphName === undefined ? await readJson(join(root, 'package.json')) : null;\n if (manifest !== null && manifest !== 'unreadable' && 'spec-graph' in manifest) {\n steps.push({ file: 'package.json', action: 'advise', detail: `spec-graph reads its configuration from the \"spec-graph\" key here, which init does not edit: add \"${archiveGlob}\" to its \"historyPatterns\" by hand` });\n } else {\n const file = graphName ?? '.spec-graph.json';\n const current = await readJson(join(root, file));\n if (current === 'unreadable') {\n steps.push({ file, action: 'advise', detail: `cannot be read as JSON; add \"historyPatterns\": [\"${archiveGlob}\"] by hand` });\n } else {\n const merged = mergeSpecGraph(current ?? {}, archiveGlob);\n const detail = describeGraph(archiveGlob, briefs, graphReadsBriefs(current ?? {}, briefs), merged !== null);\n if (merged === null) steps.push({ file, action: 'keep', detail });\n else steps.push({ file, action: current === null ? 'create' : 'update', detail, apply: () => writeAtomic(join(root, file), stringify(merged)) });\n }\n }\n }\n\n // spec-harness's own file, naming the base the rounds merge into: every\n // ruling is verified against the allowed signers on it. No choice was made\n // only where the file names a base.\n if (choice === null) {\n steps.push({ file: CONFIG_FILE, action: 'keep', detail: `rounds are measured from ${namedBase}` });\n } else if (choice.base === null) {\n steps.push({ file: CONFIG_FILE, action: 'advise', detail: choice.detail });\n } else {\n const content: Json = { ...harness, base: choice.base };\n steps.push({ file: CONFIG_FILE, action: harness === null ? 'create' : 'update', detail: choice.detail, apply: () => writeAtomic(harnessFile, stringify(content)) });\n }\n\n // The agent's hooks and server, unless the plugin brings them: Claude Code\n // runs a plugin's hook beside the same hook in settings, so both would\n // guard every write twice (ADR-0012). The hook's lines are known as doctor\n // knows them, by the hook's own reading and by the writes Claude Code\n // starts each for, so that the two say the same of every file (ADR-0005).\n const wiring = answerOf(wiringAsked);\n const { plugin } = wiring;\n // A plugin that is not on this machine brings neither. init writes none\n // on that reading alone, which a plugin that is there after all would\n // make a second guard: it says what doctor says, and how to have the\n // entries here instead.\n const absent = wiring.presence?.state === 'absent' ? wiring.presence.detail : null;\n const settingsFile = join(root, '.claude', 'settings.json');\n const settings = await readJson(settingsFile);\n // An array for a matcher, under which Claude Code loads no hook of the file.\n const array = arrayMatcher(settings);\n const lines = wiring.lines.filter((line) => line.file === SETTINGS);\n // What doctor says of a line this file holds is said here too, with why\n // init leaves the line: one a person changed is theirs, and a second line\n // beside one that is started would run for every write as well.\n const said = lines.flatMap((line) => [line.detail, line.cover]).filter((note): note is string => note !== null);\n const left = said.length === 0 ? '' : `${said.join('; ')}; init rewrites no line of the hook it did not write, and writes none beside one Claude Code starts for a write`;\n if (plugin !== null) {\n // Doubled in this file or in one of the person's own, it is the double\n // install doctor fails: said here too, though init writes neither file.\n // This file's own entry is said first, so the others are named only\n // where it holds none.\n const present = wiring.hooks.includes(SETTINGS);\n if (absent !== null) steps.push({ file: SETTINGS, action: 'advise', detail: describeAbsent(plugin, absent, 'hooks', present) });\n else {\n // A plugin that cannot be told to be on this machine is no reason to\n // write either: said beside the reason, as doctor says it.\n const untold = describePresence(wiring);\n const detail = describeSkipped(plugin, 'hooks', present, wiring.hooks);\n steps.push({ file: SETTINGS, action: wiring.hooks.length > 0 ? 'advise' : 'skip', detail: untold === null ? detail : `${detail}. ${untold}` });\n }\n } else if (settings === 'unreadable') {\n steps.push({ file: SETTINGS, action: 'advise', detail: `cannot be read as JSON; add the guard as a PreToolUse and a PostToolUse hook by hand: ${JSON.stringify(GUARD_HOOK)}` });\n } else if (array !== null) {\n // A hook written into such a file would be one more that is not loaded:\n // the matcher is the person's to mend, and init is run again after.\n steps.push({ file: SETTINGS, action: 'advise', detail: `${describeArrayMatcher(SETTINGS, array)}, those init writes among them, so it writes none: ${ONE_STRING}, and run init again` });\n } else {\n // An entry is a line of the hook where doctor reports its words as one in this file.\n const reported = new Set(lines.map((line) => JSON.stringify(line.line)));\n const isHook = (words: readonly string[]): boolean => reported.has(JSON.stringify(words));\n const guarded = mergeClaudeSettings(settings ?? {}, isHook, pattern, matchingUnder(wiring.release));\n // The check as a session starts, beside init's two where they stand as\n // init writes them and doctor has nothing more to say of a line: with\n // them, or by itself in a file whose two an earlier release wrote. A file\n // with a line of the person's is theirs to complete (ADR-0012).\n const started = left === '' ? withSessionStart(guarded ?? settings ?? {}, isHook) : null;\n const merged = started ?? guarded;\n // A line that turns the guard off or holds every write is one doctor\n // fails, and lines of which none is waited on before a write are no\n // guard between them: left as they are, they are for the person to mend.\n const broken = lines.some((line) => line.state === 'off' || line.state === 'held') || !lines.some((line) => isStarted(line.before));\n const atStart = 'a SessionStart hook says, as a session starts, what would hold every write of it';\n if (merged === null) steps.push({ file: SETTINGS, action: broken ? 'advise' : 'keep', detail: left === '' ? 'the guard hooks are installed' : left });\n else\n steps.push({\n file: SETTINGS,\n action: settings === null ? 'create' : 'update',\n detail:\n guarded === null\n ? `beside the guard hooks, ${atStart}`\n : `the guard hooks, run with node from the project's install: a PreToolUse hook refuses writes to protected files; a PostToolUse hook warns about writes outside the scope${started === null ? '' : `; ${atStart}`}${left === '' ? '' : `; ${left}`}`,\n apply: () => writeAtomic(settingsFile, stringify(merged)),\n });\n }\n // disableAllHooks turns off whatever hooks there are, and those init\n // writes with them: said of the file that holds the key, which is the\n // person's to change. init writes what it would have written.\n if (wiring.hooksOff !== null) steps.push({ file: wiring.hooksOff, action: 'advise', detail: describeHooksOff(wiring.hooksOff, guardSwitchedOff(wiring)) });\n const mcpFile = join(root, '.mcp.json');\n const mcp = await readJson(mcpFile);\n if (plugin !== null) {\n const present = registersServer(mcp);\n if (absent !== null) steps.push({ file: '.mcp.json', action: 'advise', detail: describeAbsent(plugin, absent, 'server', present) });\n else steps.push({ file: '.mcp.json', action: present ? 'advise' : 'skip', detail: describeSkipped(plugin, 'server', present) });\n } else if (mcp === 'unreadable') {\n steps.push({ file: '.mcp.json', action: 'advise', detail: 'cannot be read as JSON; add the spec-harness server by hand' });\n } else {\n const merged = mergeMcp(mcp ?? {});\n if (merged === null) steps.push({ file: '.mcp.json', action: 'keep', detail: 'the spec-harness server is registered' });\n else\n steps.push({\n file: '.mcp.json',\n action: mcp === null ? 'create' : 'update',\n detail: 'the spec-harness MCP server, run with node from the project\\'s install: start_round, check_path, request_escalation, audit_round, list_rounds',\n apply: () => writeAtomic(mcpFile, stringify(merged)),\n });\n }\n\n // git's hook, where git runs it from: core.hooksPath as git reads it, and\n // a linked worktree's shared hooks. It is the guard for a write the agent's\n // hooks never see, one through a shell, so it is advised when not asked\n // for; it is configuration outside the tree, so it is written only then.\n const { hook, path: hookFile, note: hookNote } = answerOf(hookAsked);\n // git cannot name its hook where core.hooksPath names a file, and says so,\n // which is said here as doctor says it; git then commits with no hook.\n if (hook.state === 'unknown') {\n steps.push({ file: 'pre-commit', action: 'advise', detail: describeGitHook(hook) });\n } else if (hook.state === 'runs') {\n // A hook that runs it through npx is kept, as any hook that exists is,\n // with the line that runs it as init writes the hook now.\n steps.push({ file: hook.file, action: 'keep', detail: hookNote === null ? 'already runs spec-harness' : `already runs spec-harness; ${hookNote}` });\n } else if (hook.state === 'inert' || hook.state === 'stops' || hook.state === 'ignored' || hook.state === 'unreadable') {\n // What is there is the person's to mend or to take away: nothing is\n // written over it, and what doctor says of it is said.\n steps.push({ file: hook.file, action: 'advise', detail: describeGitHook(hook) });\n } else if (hook.state === 'other') {\n steps.push({ file: hook.file, action: 'advise', detail: `a pre-commit hook exists; add the line \"${GIT_HOOK_LINE}\" to it` });\n } else if (options.gitHook) {\n // A path is named for every state but the one asked about first.\n const target = hookFile!;\n steps.push({\n file: hook.file,\n action: 'create',\n detail: 'refuse a commit that changes what the active brief protects',\n apply: async () => {\n await mkdir(dirname(target), { recursive: true });\n await writeAtomic(target, PRE_COMMIT);\n await chmod(target, 0o755);\n },\n });\n } else {\n steps.push({ file: hook.file, action: 'advise', detail: missingGitHook(null) });\n }\n\n // The file the configuration names, which a ruling's signature is checked\n // against on the base branch (ADR-0006).\n steps.push({\n file: workspace.config.rulings.allowedSigners,\n action: 'advise',\n detail: `rulings count only when signed by a key listed here on the base branch: one line per person, <email> namespaces=\"git\" <public key>. Where an agent runs as the person, make it a FIDO2 key, ssh-keygen -t ed25519-sk, whose signature needs a touch no process can supply. ${PROTECT_RULE_FILES}`,\n });\n return steps;\n}\n\nexport async function initCommand(options: Options, io: CliIO): Promise<number> {\n const workspace = await openWorkspace(options, io);\n const steps = await plan(workspace, options, io);\n if (options.write) {\n for (const step of steps) {\n if (step.apply !== undefined) {\n try {\n await step.apply();\n } catch (error) {\n io.stderr.write(`spec-harness: ${step.file}: ${(error as Error).message}\\n`);\n return EXIT_ERROR;\n }\n }\n }\n }\n if (options.format === 'json') {\n io.stdout.write(json('init', { written: options.write, steps: steps.map(({ file, action, detail }) => ({ file, action, detail })) }));\n } else {\n for (const step of steps) io.stdout.write(`${step.action.padEnd(6)} ${step.file}\\n ${step.detail}\\n`);\n if (!options.write && steps.some((step) => step.apply !== undefined)) io.stdout.write('\\nNothing was changed. Run again with --write to apply the plan.\\n');\n }\n return EXIT_OK;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `spec-harness init`: the family configured to agree, from the first day.\n *\n * The integration faults found when the tools were first run together were all\n * configuration: spec-graph read an archived brief as a retired decision and\n * reported every brief that depended on one; spec-guard executed an archived\n * brief's assertions. Each tool can be told the truth; `init` tells each of\n * them the same truth, derived from spec-brief's own settings.\n *\n * It prints a plan and changes nothing until `--write`. It merges into files\n * that exist and never replaces what a person wrote; a git hook the\n * repository already has is left alone, with the line to add printed instead.\n */\n\nimport { accessSync, constants, existsSync, statSync, type Stats } from 'node:fs';\nimport { chmod, mkdir, readFile } from 'node:fs/promises';\nimport { dirname, isAbsolute, join, relative, sep } from 'node:path';\n\nimport { CONFIG_FILE } from './config.js';\nimport {\n arrayMatcher,\n chooseBase,\n describeAbsent,\n describeArrayMatcher,\n describeGitHook,\n describeGraph,\n describeHooksOff,\n describePresence,\n describeSkipped,\n GIT_HOOK_LINE,\n gitHookNote,\n type GitHookState,\n graphReadsBriefs,\n GUARD_HOOK,\n guardSwitchedOff,\n isStarted,\n loadsPlugin,\n matchingUnder,\n measuresArchive,\n mergeClaudeSettings,\n withOnFailure,\n withSessionStart,\n withTurnReport,\n reportsTurns,\n TURN_HOOK,\n mergeMcp,\n mergeSpecBrief,\n mergeSpecGraph,\n missingGitHook,\n ON_FAILURE_SINCE,\n ONE_STRING,\n patternReader,\n PLUGIN,\n PRE_COMMIT,\n PROJECT_SETTINGS,\n PROTECT_RULE_FILES,\n registersServer,\n SPEC_BRIEF_CONFIGS,\n SPEC_GRAPH_CONFIGS,\n} from './configure.js';\nimport { readJsonObject as readJson, writeAtomic } from './fs.js';\nimport { hookPath, localBranches, remoteDefault } from './git.js';\nimport { claudeCodeWiring, pluginFile } from './round.js';\nimport { runSibling } from './siblings.js';\nimport { answerOf, EXIT_ERROR, EXIT_OK, json, openWorkspace, type CliIO, type Options, type Workspace } from './workspace.js';\n\n/** `skip`: a file init would write, left alone because Claude Code's plugin brings what init would add. */\nexport type Action = 'create' | 'update' | 'keep' | 'skip' | 'run' | 'advise';\n\nexport interface Step {\n readonly file: string;\n readonly action: Action;\n readonly detail: string;\n apply?: () => Promise<void>;\n}\n\ntype Json = Record<string, unknown>;\n\n/** The project's settings file for Claude Code, as a person finds it and as doctor names it. */\nconst SETTINGS = PROJECT_SETTINGS;\n\nfunction stringify(value: unknown): string {\n return `${JSON.stringify(value, null, 2)}\\n`;\n}\n\nconst PLUGIN_DETAIL = `load spec-harness's plugin, \"${PLUGIN}\": spec-brief's archive asks it whether a signed ruling allows a protected file, and refuses the file without it`;\n\n/** What init adds to spec-brief's configuration, said once for the plan. */\nfunction specBriefDetail(plugin: boolean, base: string | null): string {\n const parts = plugin ? [PLUGIN_DETAIL] : [];\n if (base !== null) parts.push(`measure the archive from ${base}, as spec-harness does: without a base, spec-brief's archive warns that the scope went unmeasured and checks no protected file`);\n return parts.join('; ');\n}\n\n/** A path as a person finds it: from the root when it is inside it, POSIX-separated, and as it is otherwise. */\nfunction shown(root: string, path: string): string {\n const inside = relative(root, path);\n return inside.startsWith('..') || isAbsolute(inside) ? path : inside.split(sep).join('/');\n}\n\n/**\n * Whether git takes what stands at a hook's path for a hook to run. git\n * asks the system whether the path can be executed, and skips one that\n * cannot, with no more than a hint: asked here the same way. On Windows the\n * question is only whether the path is there (Node's fs page, File access\n * constants, read 2026-10-14), and git there runs whatever is.\n */\nfunction executable(path: string): boolean {\n let may = true;\n try {\n accessSync(path, constants.X_OK);\n } catch {\n may = false;\n }\n return may;\n}\n\n/** What stands at a path, links followed, or `null` where nothing does: a link to nothing is nothing, to git as well. */\nfunction standing(path: string): Stats | null {\n try {\n return statSync(path);\n } catch {\n return null;\n }\n}\n\n/**\n * git's pre-commit hook, where git runs it from, and what is there: init and\n * doctor both read it. `path` is `null` when git cannot say where its hooks\n * are, which is said in git's own words: a `core.hooksPath` that names a\n * file is refused by git as no directory, and git then commits with no hook\n * (ADR-0005). `note` is what there is to say of how a hook that runs the\n * harness runs it, or `null`.\n *\n * Only a file is read. A directory under the hook's name, which a\n * repository whose `core.hooksPath` is in its work tree can hold, is not a\n * hook and is one to git all the same: it tries to run what it can execute\n * there, fails, and stops the commit (ADR-0005 has what was measured). Read\n * as a file, it ended this on Node's EISDIR and a stack, and a named pipe\n * would have kept it from ever coming back. A file the account may not read\n * ended it on EACCES and a stack: it is said with what git does with it.\n */\nexport async function gitHook(root: string): Promise<{ readonly hook: GitHookState; readonly path: string | null; readonly note: string | null }> {\n const where = await hookPath('pre-commit', root);\n if ('refused' in where) return { hook: { state: 'unknown', reason: `git rev-parse --git-path hooks/pre-commit failed: ${where.refused}` }, path: null, note: null };\n const { path } = where;\n const file = shown(root, path);\n const there = standing(path);\n if (there === null) return { hook: { state: 'absent', file }, path, note: null };\n const runs = executable(path);\n if (!there.isFile()) {\n const what = there.isDirectory() ? 'a directory' : 'neither a file nor a directory';\n return { hook: { state: runs ? 'stops' : 'ignored', file, what }, path, note: null };\n }\n let text: string;\n try {\n text = await readFile(path, 'utf8');\n } catch (error) {\n return { hook: { state: 'unreadable', file, runs, reason: (error as Error).message }, path, note: null };\n }\n if (!text.includes('spec-harness')) return { hook: { state: 'other', file }, path, note: null };\n return { hook: { state: runs ? 'runs' : 'inert', file }, path, note: gitHookNote(text) };\n}\n\nexport async function plan(workspace: Workspace, options: Options, io: CliIO): Promise<Step[]> {\n const { root } = workspace;\n const steps: Step[] = [];\n\n // The base rounds merge into, decided once: spec-harness verifies rulings\n // against the allowed signers on it, and spec-brief's archive measures the\n // round from it. A base a person wrote, in either file, is kept.\n // openWorkspace loaded this file and refused one that is not a JSON object,\n // so here it is one, or there is none.\n const harnessFile = join(root, CONFIG_FILE);\n const harness = (await readJson(harnessFile)) as Json | null;\n const namedBase = harness !== null && typeof harness['base'] === 'string' ? harness['base'] : null;\n // What the plan asks of git and of Claude Code's settings waits on the\n // root and on nothing of the rest, so it is asked at once: three of git's\n // processes side by side where each waited on the one before. Each is\n // read below where it was asked before, so a plan that fails still fails\n // on the first of them in that order. The matchers in the settings are\n // read with one reader, for the wiring and for what to write. Claude\n // Code's release is asked only where what is read of a line turns on it.\n const pattern = patternReader();\n const [factsAsked, wiringAsked, hookAsked] = await Promise.allSettled([\n namedBase === null ? Promise.all([remoteDefault(root), localBranches(root)]) : null,\n claudeCodeWiring(root, io, pattern, false),\n gitHook(root),\n ]);\n const facts = answerOf(factsAsked);\n const choice = facts === null ? null : chooseBase({ remoteDefault: facts[0], branch: workspace.branch, branches: facts[1] });\n const base = choice === null ? namedBase : choice.base;\n\n // spec-brief first: every other setting is derived from its directories.\n const briefConfig = SPEC_BRIEF_CONFIGS.find((name) => existsSync(join(root, name)));\n // One name for the sibling found and for the sibling run, which a run that is stopped says.\n const tool = 'spec-brief';\n const brief = workspace.siblings.locate(tool);\n let briefs = 'briefs';\n let archive = 'briefs/archive';\n if (briefConfig === undefined) {\n if (brief.kind === 'found') {\n const command = brief.command;\n const created = join(root, '.spec-brief.json');\n steps.push({\n file: '.spec-brief.json',\n action: 'run',\n detail: 'spec-brief init: the brief and archive directories, every default spelled out',\n apply: async () => {\n const run = await runSibling(tool, command, ['init'], root);\n if (run.code !== 0) throw new Error(`spec-brief init failed: ${run.stderr.trim()}`);\n },\n });\n steps.push({\n file: '.spec-brief.json',\n action: 'update',\n detail: specBriefDetail(true, base),\n apply: async () => {\n const written = await readJson(created);\n if (written === null || written === 'unreadable') throw new Error('spec-brief init wrote no configuration JSON can read');\n const merged = mergeSpecBrief(written, base, pluginFile(root));\n if (merged !== null) await writeAtomic(created, stringify(merged));\n },\n });\n } else {\n steps.push({ file: '.spec-brief.json', action: 'advise', detail: brief.reason });\n }\n } else {\n const file = join(root, briefConfig);\n const config = await readJson(file);\n // The file was found a moment ago, so null is one removed in between; and\n // a string has neither key, so these checks are there for the type.\n if (config !== null && config !== 'unreadable') {\n if (typeof config['briefs'] === 'string') briefs = config['briefs'];\n archive = typeof config['archive'] === 'string' ? config['archive'] : `${briefs}/archive`;\n }\n steps.push({ file: briefConfig, action: 'keep', detail: `briefs in ${briefs}/, the archive in ${archive}/` });\n // spec-brief's archive learns that a signed ruling allows a protected file\n // only from this package's plugin (ADR-0006).\n if (config === 'unreadable' || config === null) {\n const measure = base === null ? '' : `, and \"archiving\": { \"base\": \"${base}\" }`;\n steps.push({ file: briefConfig, action: 'advise', detail: `cannot be read as JSON; add \"plugins\": [\"${PLUGIN}\"]${measure} by hand` });\n } else {\n const isPluginFile = pluginFile(root);\n const merged = mergeSpecBrief(config, base, isPluginFile);\n const measured = measuresArchive(config);\n if (merged === null) {\n const archiving = config['archiving'];\n const from = measured ? `, and the archive is measured from ${String((archiving as Json)['base'])}` : '';\n steps.push({ file: briefConfig, action: 'keep', detail: `spec-harness's plugin is loaded${from}` });\n } else {\n const detail = specBriefDetail(!loadsPlugin(config, isPluginFile), measured ? null : base);\n steps.push({ file: briefConfig, action: 'update', detail, apply: () => writeAtomic(file, stringify(merged)) });\n }\n }\n }\n\n // spec-graph: an archived brief is a record, not a retired decision. Its\n // configuration is the first of its files, then a key in package.json; a\n // file written beside that key would shadow it.\n const graph = workspace.siblings.locate('spec-graph');\n if (graph.kind === 'outdated') steps.push({ file: '.spec-graph.json', action: 'advise', detail: graph.reason });\n if (graph.kind === 'found') {\n const archiveGlob = `${archive}/**`;\n const graphName = SPEC_GRAPH_CONFIGS.find((name) => existsSync(join(root, name)));\n const manifest = graphName === undefined ? await readJson(join(root, 'package.json')) : null;\n if (manifest !== null && manifest !== 'unreadable' && 'spec-graph' in manifest) {\n steps.push({ file: 'package.json', action: 'advise', detail: `spec-graph reads its configuration from the \"spec-graph\" key here, which init does not edit: add \"${archiveGlob}\" to its \"historyPatterns\" by hand` });\n } else {\n const file = graphName ?? '.spec-graph.json';\n const current = await readJson(join(root, file));\n if (current === 'unreadable') {\n steps.push({ file, action: 'advise', detail: `cannot be read as JSON; add \"historyPatterns\": [\"${archiveGlob}\"] by hand` });\n } else {\n const merged = mergeSpecGraph(current ?? {}, archiveGlob);\n const detail = describeGraph(archiveGlob, briefs, graphReadsBriefs(current ?? {}, briefs), merged !== null);\n if (merged === null) steps.push({ file, action: 'keep', detail });\n else steps.push({ file, action: current === null ? 'create' : 'update', detail, apply: () => writeAtomic(join(root, file), stringify(merged)) });\n }\n }\n }\n\n // spec-harness's own file, naming the base the rounds merge into: every\n // ruling is verified against the allowed signers on it. No choice was made\n // only where the file names a base.\n if (choice === null) {\n steps.push({ file: CONFIG_FILE, action: 'keep', detail: `rounds are measured from ${namedBase}` });\n } else if (choice.base === null) {\n steps.push({ file: CONFIG_FILE, action: 'advise', detail: choice.detail });\n } else {\n const content: Json = { ...harness, base: choice.base };\n steps.push({ file: CONFIG_FILE, action: harness === null ? 'create' : 'update', detail: choice.detail, apply: () => writeAtomic(harnessFile, stringify(content)) });\n }\n\n // The agent's hooks and server, unless the plugin brings them: Claude Code\n // runs a plugin's hook beside the same hook in settings, so both would\n // guard every write twice (ADR-0012). The hook's lines are known as doctor\n // knows them, by the hook's own reading and by the writes Claude Code\n // starts each for, so that the two say the same of every file (ADR-0005).\n const wiring = answerOf(wiringAsked);\n const { plugin } = wiring;\n // A plugin that is not on this machine brings neither. init writes none\n // on that reading alone, which a plugin that is there after all would\n // make a second guard: it says what doctor says, and how to have the\n // entries here instead.\n const absent = wiring.presence?.state === 'absent' ? wiring.presence.detail : null;\n const settingsFile = join(root, '.claude', 'settings.json');\n const settings = await readJson(settingsFile);\n // An array for a matcher, under which Claude Code loads no hook of the file.\n const array = arrayMatcher(settings);\n const lines = wiring.lines.filter((line) => line.file === SETTINGS);\n // What doctor says of a line this file holds is said here too, with why\n // init leaves the line: one a person changed is theirs, and a second line\n // beside one that is started would run for every write as well.\n const said = lines.flatMap((line) => [line.detail, line.cover]).filter((note): note is string => note !== null);\n const left = said.length === 0 ? '' : `${said.join('; ')}; init rewrites no line of the hook it did not write, and writes none beside one Claude Code starts for a write`;\n if (plugin !== null) {\n // Doubled in this file or in one of the person's own, it is the double\n // install doctor fails: said here too, though init writes neither file.\n // This file's own entry is said first, so the others are named only\n // where it holds none.\n const present = wiring.hooks.includes(SETTINGS);\n if (absent !== null) steps.push({ file: SETTINGS, action: 'advise', detail: describeAbsent(plugin, absent, 'hooks', present) });\n else {\n // A plugin that cannot be told to be on this machine is no reason to\n // write either: said beside the reason, as doctor says it.\n const untold = describePresence(wiring);\n const detail = describeSkipped(plugin, 'hooks', present, wiring.hooks);\n steps.push({ file: SETTINGS, action: wiring.hooks.length > 0 ? 'advise' : 'skip', detail: untold === null ? detail : `${detail}. ${untold}` });\n }\n // The plugin's hooks are the same for every project, and run the report\n // for none: one that asks for it adds the entry, which guards nothing\n // twice (ADR-0012). Only init's own line is known here, so a line a\n // person wrote under the event has the entry advised beside it; an\n // `undefined` reads as the `false` does, and that mutant is equivalent.\n if (workspace.config.turnReport && !reportsTurns(settings, () => false)) {\n steps.push({ file: SETTINGS, action: 'advise', detail: `\"turnReport\" is on, and the plugin brings no hook for the end of a turn: add ${JSON.stringify({ hooks: [TURN_HOOK] })} under \"Stop\"` });\n }\n } else if (settings === 'unreadable') {\n steps.push({ file: SETTINGS, action: 'advise', detail: `cannot be read as JSON; add the guard as a PreToolUse and a PostToolUse hook by hand: ${JSON.stringify(GUARD_HOOK)}` });\n } else if (array !== null) {\n // A hook written into such a file would be one more that is not loaded:\n // the matcher is the person's to mend, and init is run again after.\n steps.push({ file: SETTINGS, action: 'advise', detail: `${describeArrayMatcher(SETTINGS, array)}, those init writes among them, so it writes none: ${ONE_STRING}, and run init again` });\n } else {\n // An entry is a line of the hook where doctor reports its words as one in this file.\n const reported = new Set(lines.map((line) => JSON.stringify(line.line)));\n const isHook = (words: readonly string[]): boolean => reported.has(JSON.stringify(words));\n const guarded = mergeClaudeSettings(settings ?? {}, isHook, pattern, matchingUnder(wiring.release));\n // The check as a session starts, beside init's two where they stand as\n // init writes them and doctor has nothing more to say of a line: with\n // them, or by itself in a file whose two an earlier release wrote. A file\n // with a line of the person's is theirs to complete (ADR-0012).\n const started = left === '' ? withSessionStart(guarded ?? settings ?? {}, isHook) : null;\n // The report at the end of a turn, where the configuration asks for one,\n // beside the entries as init writes them (ADR-0005, ADR-0012).\n const turned = left === '' && workspace.config.turnReport ? withTurnReport(started ?? guarded ?? settings ?? {}, isHook) : null;\n const merged = turned ?? started ?? guarded;\n // A line that turns the guard off or holds every write is one doctor\n // fails, and lines of which none is waited on before a write are no\n // guard between them: left as they are, they are for the person to mend.\n const broken = lines.some((line) => line.state === 'off' || line.state === 'held') || !lines.some((line) => isStarted(line.before));\n const atStart = 'a SessionStart hook says, as a session starts, what would hold every write of it';\n const atEnd = 'a Stop hook, in the background, tells Claude as each turn begins what the work tree held at the end of the last that the brief protects or that is outside its scope';\n const beside = [started === null ? null : atStart, turned === null ? null : atEnd].filter((part): part is string => part !== null);\n // Asked for, onFailure \"block\" on init's own entries before and after a\n // write and as a session starts, those it writes now and those a run\n // before wrote, where it writes or keeps them: no page says what a\n // Claude Code before 2.1.295 does with the key, so it is written only\n // where asked for. The entry at the end of a turn runs in the\n // background, where the hooks reference gives the field no effect, and\n // is left without it (ADR-0012).\n const blocked = options.blockOnFailure && (merged !== null || !broken) ? withOnFailure(merged ?? settings ?? {}) : null;\n const written = blocked ?? merged;\n const holds = `onFailure \"block\" on init's PreToolUse, PostToolUse and SessionStart entries, so that Claude Code ${ON_FAILURE_SINCE} or later holds a write where the hook cannot start or runs past its timeout`;\n if (written === null) steps.push({ file: SETTINGS, action: broken ? 'advise' : 'keep', detail: left === '' ? 'the guard hooks are installed' : left });\n else {\n // What onFailure adds is said after what else is written, and alone where nothing else is.\n const what =\n merged === null\n ? holds\n : guarded === null\n ? `beside the guard hooks, ${beside.join('; ')}`\n : `the guard hooks, run with node from the project's install: a PreToolUse hook refuses writes to protected files; a PostToolUse hook warns about writes outside the scope${beside.map((part) => `; ${part}`).join('')}${left === '' ? '' : `; ${left}`}`;\n steps.push({\n file: SETTINGS,\n action: settings === null ? 'create' : 'update',\n detail: blocked === null || merged === null ? what : `${what}; ${holds}`,\n apply: () => writeAtomic(settingsFile, stringify(written)),\n });\n }\n }\n // disableAllHooks turns off whatever hooks there are, and those init\n // writes with them: said of the file that holds the key, which is the\n // person's to change. init writes what it would have written.\n if (wiring.hooksOff !== null) steps.push({ file: wiring.hooksOff, action: 'advise', detail: describeHooksOff(wiring.hooksOff, guardSwitchedOff(wiring)) });\n const mcpFile = join(root, '.mcp.json');\n const mcp = await readJson(mcpFile);\n if (plugin !== null) {\n const present = registersServer(mcp);\n if (absent !== null) steps.push({ file: '.mcp.json', action: 'advise', detail: describeAbsent(plugin, absent, 'server', present) });\n else steps.push({ file: '.mcp.json', action: present ? 'advise' : 'skip', detail: describeSkipped(plugin, 'server', present) });\n } else if (mcp === 'unreadable') {\n steps.push({ file: '.mcp.json', action: 'advise', detail: 'cannot be read as JSON; add the spec-harness server by hand' });\n } else {\n const merged = mergeMcp(mcp ?? {});\n if (merged === null) steps.push({ file: '.mcp.json', action: 'keep', detail: 'the spec-harness server is registered' });\n else\n steps.push({\n file: '.mcp.json',\n action: mcp === null ? 'create' : 'update',\n detail: 'the spec-harness MCP server, run with node from the project\\'s install: start_round, check_path, request_escalation, audit_round, list_rounds',\n apply: () => writeAtomic(mcpFile, stringify(merged)),\n });\n }\n\n // git's hook, where git runs it from: core.hooksPath as git reads it, and\n // a linked worktree's shared hooks. It is the guard for a write the agent's\n // hooks never see, one through a shell, so it is advised when not asked\n // for; it is configuration outside the tree, so it is written only then.\n const { hook, path: hookFile, note: hookNote } = answerOf(hookAsked);\n // git cannot name its hook where core.hooksPath names a file, and says so,\n // which is said here as doctor says it; git then commits with no hook.\n if (hook.state === 'unknown') {\n steps.push({ file: 'pre-commit', action: 'advise', detail: describeGitHook(hook) });\n } else if (hook.state === 'runs') {\n // A hook that runs it through npx is kept, as any hook that exists is,\n // with the line that runs it as init writes the hook now.\n steps.push({ file: hook.file, action: 'keep', detail: hookNote === null ? 'already runs spec-harness' : `already runs spec-harness; ${hookNote}` });\n } else if (hook.state === 'inert' || hook.state === 'stops' || hook.state === 'ignored' || hook.state === 'unreadable') {\n // What is there is the person's to mend or to take away: nothing is\n // written over it, and what doctor says of it is said.\n steps.push({ file: hook.file, action: 'advise', detail: describeGitHook(hook) });\n } else if (hook.state === 'other') {\n steps.push({ file: hook.file, action: 'advise', detail: `a pre-commit hook exists; add the line \"${GIT_HOOK_LINE}\" to it` });\n } else if (options.gitHook) {\n // A path is named for every state but the one asked about first.\n const target = hookFile!;\n steps.push({\n file: hook.file,\n action: 'create',\n detail: 'refuse a commit that changes what the active brief protects',\n apply: async () => {\n await mkdir(dirname(target), { recursive: true });\n await writeAtomic(target, PRE_COMMIT);\n await chmod(target, 0o755);\n },\n });\n } else {\n steps.push({ file: hook.file, action: 'advise', detail: missingGitHook(null) });\n }\n\n // The file the configuration names, which a ruling's signature is checked\n // against on the base branch (ADR-0006).\n steps.push({\n file: workspace.config.rulings.allowedSigners,\n action: 'advise',\n detail: `rulings count only when signed by a key listed here on the base branch: one line per person, <email> namespaces=\"git\" <public key>. Where an agent runs as the person, make it a FIDO2 key, ssh-keygen -t ed25519-sk, whose signature needs a touch no process can supply. ${PROTECT_RULE_FILES}`,\n });\n return steps;\n}\n\nexport async function initCommand(options: Options, io: CliIO): Promise<number> {\n const workspace = await openWorkspace(options, io);\n const steps = await plan(workspace, options, io);\n if (options.write) {\n for (const step of steps) {\n if (step.apply !== undefined) {\n try {\n await step.apply();\n } catch (error) {\n io.stderr.write(`spec-harness: ${step.file}: ${(error as Error).message}\\n`);\n return EXIT_ERROR;\n }\n }\n }\n }\n if (options.format === 'json') {\n io.stdout.write(json('init', { written: options.write, steps: steps.map(({ file, action, detail }) => ({ file, action, detail })) }));\n } else {\n for (const step of steps) io.stdout.write(`${step.action.padEnd(6)} ${step.file}\\n ${step.detail}\\n`);\n if (!options.write && steps.some((step) => step.apply !== undefined)) io.stdout.write('\\nNothing was changed. Run again with --write to apply the plan.\\n');\n }\n return EXIT_OK;\n}\n"]}
|
package/dist/siblings.d.ts
CHANGED
|
@@ -57,19 +57,35 @@ export declare function declaredVersion(file: string): unknown;
|
|
|
57
57
|
*
|
|
58
58
|
* Never through a shell: an argument is a path or a brief id, and a shell
|
|
59
59
|
* would read it as syntax. `node` as a command's first word is this Node, so
|
|
60
|
-
* `["node", "path/to/bin.js"]` works on every host
|
|
61
|
-
*
|
|
62
|
-
* script
|
|
60
|
+
* `["node", "path/to/bin.js"]` works on every host. A program that cannot be
|
|
61
|
+
* started is answered on every host in one way, code -1 and a line that says
|
|
62
|
+
* to name the tool's script: one not found, a script named without `node`,
|
|
63
|
+
* a Windows `.cmd` shim such as `npx`, which cannot be started without a
|
|
64
|
+
* shell, a directory or a file the account may not run.
|
|
65
|
+
*
|
|
66
|
+
* A sibling that does not answer within `limit` is stopped, and rejected as
|
|
67
|
+
* a `SiblingError` that names it: what it was asked waits on it, the hook
|
|
68
|
+
* before a write among them, which then holds the write (ADR-0002).
|
|
63
69
|
*/
|
|
64
|
-
export declare function runSibling(command: readonly string[], args: readonly string[], root: string,
|
|
70
|
+
export declare function runSibling(name: string, command: readonly string[], args: readonly string[], root: string, limit?: number): Promise<SiblingRun>;
|
|
65
71
|
export declare class SiblingError extends Error {
|
|
66
72
|
constructor(message: string);
|
|
67
73
|
}
|
|
68
74
|
export interface Siblings {
|
|
69
75
|
readonly root: string;
|
|
70
76
|
locate(name: SiblingName): Sibling;
|
|
71
|
-
/**
|
|
72
|
-
|
|
77
|
+
/**
|
|
78
|
+
* Every brief, live and archived. Exit 2 from spec-brief is an error here
|
|
79
|
+
* too, and so is a spec-brief that does not answer within `limit`, the
|
|
80
|
+
* time a question is given unless a caller gives another.
|
|
81
|
+
*/
|
|
82
|
+
briefs(limit?: number): Promise<BriefRow[]>;
|
|
83
|
+
/**
|
|
84
|
+
* The same siblings, with spec-brief's list of the briefs kept for a
|
|
85
|
+
* session under the common directory and given again to that session's
|
|
86
|
+
* runs where every input it lists reads as listed (ADR-0002).
|
|
87
|
+
*/
|
|
88
|
+
keeping(commonDir: string, session: string): Siblings;
|
|
73
89
|
/** A sibling's JSON output for a command line, with its exit code and what it said on stderr; `absent` says why it cannot be run, missing or outdated. */
|
|
74
90
|
json(name: SiblingName, args: readonly string[]): Promise<{
|
|
75
91
|
readonly code: number;
|
|
@@ -79,5 +95,12 @@ export interface Siblings {
|
|
|
79
95
|
readonly absent: string;
|
|
80
96
|
}>;
|
|
81
97
|
}
|
|
98
|
+
/**
|
|
99
|
+
* What a kept answer is the answer to: the work tree, the session, the
|
|
100
|
+
* spec-brief that answered, by its command, its version and the Node it ran
|
|
101
|
+
* on, the command line, and the variables above, as spec-brief is started
|
|
102
|
+
* with them (runSibling). An answer is given again only for the same.
|
|
103
|
+
*/
|
|
104
|
+
export declare function answerKey(root: string, session: string, command: readonly string[], version: string, env?: Readonly<Record<string, string | undefined>>): string;
|
|
82
105
|
/** The siblings of the work tree at `root`, looked for in its install and then in each of `installs` (locate). */
|
|
83
106
|
export declare function createSiblings(root: string, config: HarnessConfig, installs?: readonly string[]): Siblings;
|