@descent-vtt/spec-harness 0.8.0 → 0.9.1
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 +41 -0
- package/dist/answers.d.ts +54 -0
- package/dist/answers.js +139 -0
- package/dist/answers.js.map +1 -0
- package/dist/branch.d.ts +2 -2
- package/dist/branch.js +3 -1
- package/dist/branch.js.map +1 -1
- package/dist/cli.js +47 -32
- package/dist/cli.js.map +1 -1
- package/dist/commands.js +6 -2
- package/dist/commands.js.map +1 -1
- package/dist/context.d.ts +1 -0
- package/dist/context.js +6 -4
- package/dist/context.js.map +1 -1
- package/dist/formats.js +3 -1
- package/dist/formats.js.map +1 -1
- package/dist/fs.js +8 -5
- package/dist/fs.js.map +1 -1
- package/dist/git.d.ts +12 -6
- package/dist/git.js +25 -11
- package/dist/git.js.map +1 -1
- package/dist/junit.js +13 -2
- package/dist/junit.js.map +1 -1
- package/dist/plugin.js +10 -17
- package/dist/plugin.js.map +1 -1
- package/dist/premises.js +6 -10
- package/dist/premises.js.map +1 -1
- package/dist/round.d.ts +1 -1
- package/dist/round.js +48 -38
- package/dist/round.js.map +1 -1
- package/dist/server.js +16 -6
- package/dist/server.js.map +1 -1
- package/dist/setup.js +14 -14
- package/dist/setup.js.map +1 -1
- package/dist/siblings.js +11 -3
- package/dist/siblings.js.map +1 -1
- package/dist/workspace.d.ts +16 -3
- package/dist/workspace.js +12 -2
- package/dist/workspace.js.map +1 -1
- package/package.json +3 -3
package/dist/round.js
CHANGED
|
@@ -9,12 +9,14 @@ import { existsSync, readFileSync, realpathSync } from 'node:fs';
|
|
|
9
9
|
import { readdir, readFile, rm } from 'node:fs/promises';
|
|
10
10
|
import { join, resolve } from 'node:path';
|
|
11
11
|
import { fileURLToPath } from 'node:url';
|
|
12
|
+
import { readArchivePlan, readGuardRun } from './answers.js';
|
|
12
13
|
import { audit, tally } from './audit.js';
|
|
14
|
+
import { SiblingOutputError } from './briefs.js';
|
|
13
15
|
import { sameId } from './branch.js';
|
|
14
16
|
import { enabledPlugin, exportedFile, holdsGuard, loadsPlugin, registersServer, SPEC_BRIEF_CONFIGS, } from './configure.js';
|
|
15
17
|
import { readRules, renderContext } from './context.js';
|
|
16
18
|
import { readJsonObject, readText, repositoryPath, stateDirectory, writeAtomic } from './fs.js';
|
|
17
|
-
import { blameLine, changes, mergeBase, remoteDefault, revision, show, verifyCommit } from './git.js';
|
|
19
|
+
import { blameLine, changes, isUncommitted, mergeBase, remoteDefault, revision, show, verifyCommit } from './git.js';
|
|
18
20
|
import { decide } from './guard.js';
|
|
19
21
|
import { diffManifest, ecosystemOf, readManifestNames } from './manifests.js';
|
|
20
22
|
import { addRulingRow, nextId, readRulings, renderMemo, renderRow, } from './rulings.js';
|
|
@@ -30,9 +32,11 @@ export async function resolveBase(workspace, flag) {
|
|
|
30
32
|
return { kind: 'unresolved', reason: 'no base is named and the remote has no default branch; pass --base <ref> or set "base"' };
|
|
31
33
|
}
|
|
32
34
|
const sha = await revision(ref, workspace.root);
|
|
33
|
-
|
|
34
|
-
if (sha === null || head === null)
|
|
35
|
+
if (sha === null)
|
|
35
36
|
return { kind: 'unresolved', reason: `"${ref}" names no commit` };
|
|
37
|
+
const head = await revision('HEAD', workspace.root);
|
|
38
|
+
if (head === null)
|
|
39
|
+
return { kind: 'unresolved', reason: 'HEAD names no commit: nothing is committed on this branch yet' };
|
|
36
40
|
const common = await mergeBase(sha, head, workspace.root);
|
|
37
41
|
if (common === null)
|
|
38
42
|
return { kind: 'unresolved', reason: `"${ref}" and HEAD share no history` };
|
|
@@ -54,6 +58,8 @@ export async function checkRulings(workspace, brief, text, reader, base) {
|
|
|
54
58
|
line: problem.line,
|
|
55
59
|
}));
|
|
56
60
|
const allows = rows.filter((row) => row.decision === 'allow');
|
|
61
|
+
// Nothing below verifies a row that allows nothing, so this saves a git
|
|
62
|
+
// show and is equivalent to its mutants.
|
|
57
63
|
if (allows.length === 0)
|
|
58
64
|
return { rows, verified: [], unverified: [], problems: findings };
|
|
59
65
|
if (base.kind === 'unresolved') {
|
|
@@ -64,6 +70,8 @@ export async function checkRulings(workspace, brief, text, reader, base) {
|
|
|
64
70
|
const reason = `${base.ref} has no ${workspace.config.rulings.allowedSigners}, so no signature can count`;
|
|
65
71
|
return { rows, verified: [], unverified: allows.map((row) => ({ id: row.id, reason })), problems: findings };
|
|
66
72
|
}
|
|
73
|
+
// Only verify-commit below reads this copy, so where it is kept, and under
|
|
74
|
+
// what name, is equivalent to its mutants.
|
|
67
75
|
const directory = await stateDirectory(workspace.commonDir, 'signers');
|
|
68
76
|
const file = join(directory, `${createHash('sha256').update(signers).digest('hex').slice(0, 16)}`);
|
|
69
77
|
await writeAtomic(file, signers);
|
|
@@ -74,12 +82,12 @@ export async function checkRulings(workspace, brief, text, reader, base) {
|
|
|
74
82
|
// HEAD the same number can be another line, one a signed commit wrote,
|
|
75
83
|
// and an uncommitted row would borrow that commit's signature.
|
|
76
84
|
const commit = await blameLine(null, brief.file, row.line, workspace.root);
|
|
77
|
-
if (commit === null ||
|
|
85
|
+
if (commit === null || isUncommitted(commit)) {
|
|
78
86
|
unverified.push({ id: row.id, reason: 'its row is not committed' });
|
|
79
87
|
continue;
|
|
80
88
|
}
|
|
81
89
|
const signature = await verifyCommit(commit, file, workspace.root);
|
|
82
|
-
if (signature.good
|
|
90
|
+
if (signature.good)
|
|
83
91
|
verified.push({ id: row.id, paths: row.paths, signer: signature.principal });
|
|
84
92
|
else
|
|
85
93
|
unverified.push({ id: row.id, reason: `commit ${commit.slice(0, 12)} last changed its row, and ${signature.detail || 'it is not signed'}` });
|
|
@@ -95,21 +103,18 @@ export async function briefText(workspace, brief) {
|
|
|
95
103
|
}
|
|
96
104
|
/** Decides paths against the brief, with the rulings verified against the base `baseFlag` names, or the configured one. */
|
|
97
105
|
export async function checkPaths(workspace, brief, noBrief, given, cwd, reader, baseFlag) {
|
|
98
|
-
let rulings = [];
|
|
99
106
|
const resolved = given.map((path) => ({ given: path, path: repositoryPath(path, workspace.root, cwd) }));
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
}
|
|
112
|
-
return resolved.map(({ path, given: g }) => decide({ path, given: g, brief, noBrief, rulings, outOfScope: workspace.config.outOfScope }));
|
|
107
|
+
const decideAll = (rulings) => resolved.map(({ path, given: g }) => decide({ path, given: g, brief, noBrief, rulings, outOfScope: workspace.config.outOfScope }));
|
|
108
|
+
const first = decideAll([]);
|
|
109
|
+
// Rulings cost a blame and a signature check each, so they are read only
|
|
110
|
+
// when a write reaches a protected file. Read anyway, they decide the same,
|
|
111
|
+
// since a ruling allows only a protected path, so mutants that always read
|
|
112
|
+
// them are equivalent; and with no brief nothing is protected, so the null
|
|
113
|
+
// check is there for the type.
|
|
114
|
+
if (brief === null || !first.some((decision) => decision.reason === 'protected'))
|
|
115
|
+
return first;
|
|
116
|
+
const base = await resolveBase(workspace, baseFlag);
|
|
117
|
+
return decideAll((await checkRulings(workspace, brief, await briefText(workspace, brief), reader, base)).verified);
|
|
113
118
|
}
|
|
114
119
|
/* ----------------------------------------------------------------- context */
|
|
115
120
|
/**
|
|
@@ -160,9 +165,10 @@ async function rulesFor(workspace, brief) {
|
|
|
160
165
|
return 'absent' in answer ? { unavailable: answer.absent } : readRules(answer);
|
|
161
166
|
}
|
|
162
167
|
catch (error) {
|
|
163
|
-
// spec-guard printed no JSON
|
|
164
|
-
// the
|
|
165
|
-
|
|
168
|
+
// spec-guard printed no JSON, or a document of another shape: what it
|
|
169
|
+
// said instead, or what was wrong, is the reason, and the rest of the
|
|
170
|
+
// packet stands without the rules.
|
|
171
|
+
if (error instanceof SiblingError || error instanceof SiblingOutputError)
|
|
166
172
|
return { unavailable: error.message };
|
|
167
173
|
throw error;
|
|
168
174
|
}
|
|
@@ -181,7 +187,7 @@ async function citedDocuments(workspace, brief, text, reader) {
|
|
|
181
187
|
// A destination that is not valid percent-encoding is read as written.
|
|
182
188
|
}
|
|
183
189
|
const path = resolveInside(dirname(brief.file), target);
|
|
184
|
-
if (path === null || path ===
|
|
190
|
+
if (path === null || path === brief.file || seen.has(path))
|
|
185
191
|
continue;
|
|
186
192
|
seen.add(path);
|
|
187
193
|
const document = /\.(?:md|markdown|mdx|txt)$/i.test(path);
|
|
@@ -190,6 +196,8 @@ async function citedDocuments(workspace, brief, text, reader) {
|
|
|
190
196
|
if (!document && existsSync(join(workspace.root, path)))
|
|
191
197
|
continue;
|
|
192
198
|
const content = document ? await readText(join(workspace.root, path)) : null;
|
|
199
|
+
// A document that cannot be read is listed by its path alone, so its
|
|
200
|
+
// title and status are never read, and an empty object is equivalent.
|
|
193
201
|
const meta = content === null ? { title: null, status: null } : reader.titleAndStatus(content);
|
|
194
202
|
out.push({ path, ...meta, text: content });
|
|
195
203
|
}
|
|
@@ -208,14 +216,9 @@ export async function buildContext(workspace, brief, briefs, reader, baseFlag) {
|
|
|
208
216
|
briefText: text,
|
|
209
217
|
dependencies: brief.dependsOn.map((id) =>
|
|
210
218
|
// spec-brief reports a dependency as its front matter spells it, `7` for brief 007.
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
title: '(no such brief)',
|
|
215
|
-
file: '',
|
|
216
|
-
phase: 'live',
|
|
217
|
-
status: 'unknown',
|
|
218
|
-
}),
|
|
219
|
+
// The context reads a dependency's id, title, status and phase, and
|
|
220
|
+
// the brief copied here is live.
|
|
221
|
+
briefs.find((candidate) => sameId(candidate.id, id)) ?? { ...brief, id, title: '(no such brief)', status: 'unknown' }),
|
|
219
222
|
cited,
|
|
220
223
|
rules,
|
|
221
224
|
rulings: rulings.verified,
|
|
@@ -242,8 +245,10 @@ async function dependencyChanges(workspace, base) {
|
|
|
242
245
|
unread.push(change.path);
|
|
243
246
|
continue;
|
|
244
247
|
}
|
|
245
|
-
|
|
246
|
-
|
|
248
|
+
// git shows nothing where a file is not: an added manifest has no before,
|
|
249
|
+
// and a deleted one no after.
|
|
250
|
+
const before = await show(base.mergeBase, change.from ?? change.path, workspace.root);
|
|
251
|
+
const after = await show(base.head, change.path, workspace.root);
|
|
247
252
|
const diff = diffManifest(change.path, ecosystem, before, after);
|
|
248
253
|
if ('error' in diff)
|
|
249
254
|
unread.push(change.path);
|
|
@@ -298,6 +303,8 @@ export async function specBriefPlugin(root) {
|
|
|
298
303
|
if (file === undefined)
|
|
299
304
|
return { kind: 'unconfigured' };
|
|
300
305
|
const config = await readJsonObject(join(root, file));
|
|
306
|
+
// The file was found a moment ago, so null is one removed in between, and
|
|
307
|
+
// reads as the unreadable one it has become.
|
|
301
308
|
if (config === null || config === 'unreadable')
|
|
302
309
|
return { kind: 'unreadable', file };
|
|
303
310
|
return { kind: loadsPlugin(config, pluginFile(root)) ? 'loaded' : 'not-loaded', file };
|
|
@@ -338,12 +345,13 @@ async function archiveReasons(workspace, brief, base) {
|
|
|
338
345
|
if (base.kind === 'resolved')
|
|
339
346
|
args.push('--base', base.ref);
|
|
340
347
|
const answer = await workspace.siblings.json('spec-brief', args);
|
|
348
|
+
// The audit listed the briefs through spec-brief before it asks this, so
|
|
349
|
+
// an absent one stopped it there; the check is for the type.
|
|
341
350
|
if ('absent' in answer)
|
|
342
351
|
return { unavailable: answer.absent };
|
|
343
352
|
if (answer.code === 2)
|
|
344
353
|
return { unavailable: 'spec-brief could not plan the archive' };
|
|
345
|
-
|
|
346
|
-
return { blocking: plan?.blocking ?? [], warnings: plan?.warnings ?? [] };
|
|
354
|
+
return readArchivePlan(answer.document);
|
|
347
355
|
}
|
|
348
356
|
/** The brief's assertions as spec-guard ran them, and those it could not read, which it lists apart as `errors`. */
|
|
349
357
|
async function briefAssertions(workspace, brief, text, reader) {
|
|
@@ -352,15 +360,15 @@ async function briefAssertions(workspace, brief, text, reader) {
|
|
|
352
360
|
return { unavailable: answer.absent };
|
|
353
361
|
if (answer.code === 2)
|
|
354
362
|
return { unavailable: 'spec-guard could not run the brief\'s assertions' };
|
|
355
|
-
const report = answer.document;
|
|
363
|
+
const report = readGuardRun(answer.document);
|
|
356
364
|
const own = (spec) => spec === undefined || spec.file.replace(/\\/g, '/') === brief.file;
|
|
357
|
-
const outcomes =
|
|
365
|
+
const outcomes = report.results
|
|
358
366
|
.filter((result) => own(result.spec))
|
|
359
367
|
.map((result) => {
|
|
360
368
|
const line = result.spec?.line ?? 0;
|
|
361
369
|
return { ok: result.ok, description: result.description, message: result.message, line, section: reader.sectionAt(text, line), enclosing: reader.sectionsAt(text, line) };
|
|
362
370
|
});
|
|
363
|
-
const unreadable =
|
|
371
|
+
const unreadable = report.errors.filter((error) => own(error.spec)).map((error) => ({ message: error.message, line: error.spec?.line ?? 0, raw: error.raw }));
|
|
364
372
|
return { outcomes, unreadable };
|
|
365
373
|
}
|
|
366
374
|
export async function runAudit(workspace, brief, reader, baseFlag) {
|
|
@@ -440,6 +448,8 @@ export async function recordRuling(workspace, escalationId, decision, note, read
|
|
|
440
448
|
const id = nextId('R', request.brief, taken);
|
|
441
449
|
const row = renderRow(id, request.paths, decision, note);
|
|
442
450
|
await writeAtomic(path, addRulingRow(text, workspace.config.rulings.section, row, where));
|
|
451
|
+
// Listed a moment ago; forced, a request another process retired in
|
|
452
|
+
// between is not an error, so the option is equivalent to its mutants.
|
|
443
453
|
await rm(join(await escalationDirectory(workspace), `${request.id}.json`), { force: true });
|
|
444
454
|
return { id, file: request.briefFile, row };
|
|
445
455
|
}
|
package/dist/round.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"round.js","sourceRoot":"","sources":["../src/round.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A round, measured: the operations the command line and the MCP server\n * share. Each gathers what a pure module needs - from git, the disk and the\n * siblings - and hands it over; the decisions are made in `context.ts`,\n * `audit.ts`, `guard.ts` and `rulings.ts`.\n */\n\nimport { createHash } from 'node:crypto';\nimport { existsSync, readFileSync, realpathSync } from 'node:fs';\nimport { readdir, readFile, rm } from 'node:fs/promises';\nimport { join, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nimport { audit, tally, type ArchiveReason, type AssertionOutcome, type AuditInput, type AuditReport, type UnreadableAssertion } from './audit.js';\nimport { sameId } from './branch.js';\nimport {\n enabledPlugin,\n exportedFile,\n holdsGuard,\n loadsPlugin,\n registersServer,\n SPEC_BRIEF_CONFIGS,\n type BaseSource,\n type ClaudeCodeWiring,\n type ClaudeSettings,\n type PluginState,\n} from './configure.js';\nimport { readRules, renderContext, type CitedDocument, type ContextPacket, type Rules } from './context.js';\nimport type { DocumentReader } from './document.js';\nimport { readJsonObject, readText, repositoryPath, stateDirectory, writeAtomic } from './fs.js';\nimport { blameLine, changes, mergeBase, remoteDefault, revision, show, verifyCommit } from './git.js';\nimport { decide, type Decision, type VerifiedRuling } from './guard.js';\nimport { diffManifest, ecosystemOf, readManifestNames, type DependencyChange } from './manifests.js';\nimport {\n addRulingRow,\n nextId,\n readRulings,\n renderMemo,\n renderRow,\n type EscalationOption,\n type EscalationRequest,\n type RulingRow,\n} from './rulings.js';\nimport type { BriefRow, Finding } from './types.js';\nimport { compileGlob, type LiteralReading } from './vendor/spec-core/pattern/index.js';\nimport { dirname, isRelativeReference, resolveInside, splitReference } from './vendor/spec-core/path/index.js';\nimport { SiblingError } from './siblings.js';\nimport { UsageError, type CliIO, type Workspace } from './workspace.js';\n\n/* -------------------------------------------------------------------- base */\n\nexport type Base =\n | { readonly kind: 'resolved'; readonly ref: string; readonly source: BaseSource; readonly sha: string; readonly mergeBase: string; readonly head: string }\n | { readonly kind: 'unresolved'; readonly reason: string };\n\n/** What the round is measured from: the flag, the configuration, then the remote's default branch. */\nexport async function resolveBase(workspace: Workspace, flag: string | undefined): Promise<Base> {\n const source: BaseSource = flag !== undefined ? 'flag' : workspace.config.base !== null ? 'config' : 'remote';\n const ref = flag ?? workspace.config.base ?? (await remoteDefault(workspace.root));\n if (ref === null) {\n return { kind: 'unresolved', reason: 'no base is named and the remote has no default branch; pass --base <ref> or set \"base\"' };\n }\n const sha = await revision(ref, workspace.root);\n const head = await revision('HEAD', workspace.root);\n if (sha === null || head === null) return { kind: 'unresolved', reason: `\"${ref}\" names no commit` };\n const common = await mergeBase(sha, head, workspace.root);\n if (common === null) return { kind: 'unresolved', reason: `\"${ref}\" and HEAD share no history` };\n return { kind: 'resolved', ref, source, sha, mergeBase: common, head };\n}\n\n/* ----------------------------------------------------------------- rulings */\n\nexport interface RulingCheck {\n readonly rows: readonly RulingRow[];\n readonly verified: readonly VerifiedRuling[];\n readonly unverified: readonly { readonly id: string; readonly reason: string }[];\n readonly problems: readonly Finding[];\n}\n\n/**\n * The brief's rulings, each checked against its signature: the commit that\n * last changed its row must be signed by a principal the base branch's\n * allowed-signers file lists (ADR-0006).\n */\nexport async function checkRulings(workspace: Workspace, brief: BriefRow, text: string, reader: DocumentReader, base: Base): Promise<RulingCheck> {\n const { rulings: rows, problems } = readRulings(reader.sectionTables(text, workspace.config.rulings.section).tables);\n const findings: Finding[] = problems.map((problem) => ({\n rule: 'ruling-unreadable',\n severity: 'warning',\n message: problem.message,\n hint: 'a ruling row is | id | `paths` | allow or deny | note |',\n file: brief.file,\n line: problem.line,\n }));\n const allows = rows.filter((row) => row.decision === 'allow');\n if (allows.length === 0) return { rows, verified: [], unverified: [], problems: findings };\n if (base.kind === 'unresolved') {\n return { rows, verified: [], unverified: allows.map((row) => ({ id: row.id, reason: `no base to read the allowed signers from: ${base.reason}` })), problems: findings };\n }\n const signers = await show(base.sha, workspace.config.rulings.allowedSigners, workspace.root);\n if (signers === null) {\n const reason = `${base.ref} has no ${workspace.config.rulings.allowedSigners}, so no signature can count`;\n return { rows, verified: [], unverified: allows.map((row) => ({ id: row.id, reason })), problems: findings };\n }\n const directory = await stateDirectory(workspace.commonDir, 'signers');\n const file = join(directory, `${createHash('sha256').update(signers).digest('hex').slice(0, 16)}`);\n await writeAtomic(file, signers);\n const verified: VerifiedRuling[] = [];\n const unverified: { id: string; reason: string }[] = [];\n for (const row of allows) {\n // The row's line is a line of the text on disk, so it is blamed there: at\n // HEAD the same number can be another line, one a signed commit wrote,\n // and an uncommitted row would borrow that commit's signature.\n const commit = await blameLine(null, brief.file, row.line, workspace.root);\n if (commit === null || /^0+$/.test(commit)) {\n unverified.push({ id: row.id, reason: 'its row is not committed' });\n continue;\n }\n const signature = await verifyCommit(commit, file, workspace.root);\n if (signature.good && signature.principal !== null) verified.push({ id: row.id, paths: row.paths, signer: signature.principal });\n else unverified.push({ id: row.id, reason: `commit ${commit.slice(0, 12)} last changed its row, and ${signature.detail || 'it is not signed'}` });\n }\n return { rows, verified, unverified, problems: findings };\n}\n\n/* ------------------------------------------------------------------- guard */\n\nexport async function briefText(workspace: Workspace, brief: BriefRow): Promise<string> {\n const text = await readText(join(workspace.root, brief.file));\n if (text === null) throw new UsageError(`${brief.file} cannot be read`);\n return text;\n}\n\n/** Decides paths against the brief, with the rulings verified against the base `baseFlag` names, or the configured one. */\nexport async function checkPaths(\n workspace: Workspace,\n brief: BriefRow | null,\n noBrief: string | undefined,\n given: readonly string[],\n cwd: string,\n reader: DocumentReader,\n baseFlag: string | undefined,\n): Promise<Decision[]> {\n let rulings: readonly VerifiedRuling[] = [];\n const resolved = given.map((path) => ({ given: path, path: repositoryPath(path, workspace.root, cwd) }));\n if (brief !== null) {\n // Rulings cost a blame and a signature check each, so they are read only\n // when a write reaches a protected file.\n const first = resolved.map(({ path, given: g }) =>\n decide({ path, given: g, brief, noBrief, rulings: [], outOfScope: workspace.config.outOfScope }),\n );\n if (first.some((decision) => decision.reason === 'protected')) {\n const base = await resolveBase(workspace, baseFlag);\n rulings = (await checkRulings(workspace, brief, await briefText(workspace, brief), reader, base)).verified;\n } else {\n return first;\n }\n }\n return resolved.map(({ path, given: g }) => decide({ path, given: g, brief, noBrief, rulings, outOfScope: workspace.config.outOfScope }));\n}\n\n/* ----------------------------------------------------------------- context */\n\n/**\n * The paths spec-guard is asked about for a scope: where its patterns can\n * match. A name with no glob syntax that exists is asked about as itself,\n * since spec-guard reads from the disk whether a path is a file or a\n * directory. One the round has yet to create may become either, and\n * spec-guard would read it as a file, leaving out the rules over a\n * directory of that name; it is asked about through the directory that will\n * hold it, the root for a name at the top, which covers both.\n */\nfunction scopeBases(root: string, patterns: readonly string[]): string[] {\n // Read as a directory, a name's base is the name itself; read any other\n // way, it is the directory holding it, so which other reading a missing\n // name gets changes nothing. The glob is compiled for its bases and never\n // matched: a file read as a directory narrows the question and nothing\n // else.\n const literal = (path: string): LiteralReading => (existsSync(join(root, path)) ? 'directory' : 'either');\n const bases = new Set<string>();\n for (const pattern of patterns) {\n try {\n // Case is read only in matching, which this compile never does: its\n // bases are the same either way, so `caseSensitive: false` is equivalent.\n for (const base of compileGlob(pattern, { dialect: 'path', caseSensitive: true, literal }).bases) {\n // A rooted alternative's base, `/docs` or `/`, is outside the\n // repository: it puts no path in the scope, and spec-guard refuses\n // the whole question for it, with the rules for every other base.\n // The packet names the pattern.\n if (base.startsWith('/')) continue;\n bases.add(base === '' ? '.' : base);\n }\n } catch {\n // The packet names a pattern the guard cannot read, with spec-core's\n // reason, and says so when it is every pattern; the rules for the rest\n // still count.\n }\n }\n return [...bases].sort();\n}\n\nasync function rulesFor(workspace: Workspace, brief: BriefRow): Promise<Rules> {\n const paths = scopeBases(workspace.root, brief.affectedFiles);\n if (paths.length === 0) return [];\n try {\n const answer = await workspace.siblings.json('spec-guard', ['query', ...paths, '--json']);\n return 'absent' in answer ? { unavailable: answer.absent } : readRules(answer);\n } catch (error) {\n // spec-guard printed no JSON: what it said instead is the reason, and\n // the rest of the packet stands without the rules.\n if (error instanceof SiblingError) return { unavailable: error.message };\n throw error;\n }\n}\n\nasync function citedDocuments(workspace: Workspace, brief: BriefRow, text: string, reader: DocumentReader): Promise<CitedDocument[]> {\n const seen = new Set<string>();\n const out: CitedDocument[] = [];\n for (const citation of reader.citations(text)) {\n if (!isRelativeReference(citation.target)) continue;\n let target = splitReference(citation.target).path;\n try {\n target = decodeURIComponent(target);\n } catch {\n // A destination that is not valid percent-encoding is read as written.\n }\n const path = resolveInside(dirname(brief.file), target);\n if (path === null || path === '' || path === brief.file || seen.has(path)) continue;\n seen.add(path);\n const document = /\\.(?:md|markdown|mdx|txt)$/i.test(path);\n // A link to code or a directory that exists is not a document to include,\n // and must not be reported as a link that resolves to nothing.\n if (!document && existsSync(join(workspace.root, path))) continue;\n const content = document ? await readText(join(workspace.root, path)) : null;\n const meta = content === null ? { title: null, status: null } : reader.titleAndStatus(content);\n out.push({ path, ...meta, text: content });\n }\n return out;\n}\n\nexport async function buildContext(\n workspace: Workspace,\n brief: BriefRow,\n briefs: readonly BriefRow[],\n reader: DocumentReader,\n baseFlag: string | undefined,\n): Promise<ContextPacket> {\n const text = await briefText(workspace, brief);\n const base = await resolveBase(workspace, baseFlag);\n const [rules, cited, rulings] = await Promise.all([\n rulesFor(workspace, brief),\n citedDocuments(workspace, brief, text, reader),\n checkRulings(workspace, brief, text, reader, base),\n ]);\n return renderContext({\n brief,\n briefText: text,\n dependencies: brief.dependsOn.map(\n (id) =>\n // spec-brief reports a dependency as its front matter spells it, `7` for brief 007.\n briefs.find((candidate) => sameId(candidate.id, id)) ?? {\n ...brief,\n id,\n title: '(no such brief)',\n file: '',\n phase: 'live',\n status: 'unknown',\n },\n ),\n cited,\n rules,\n rulings: rulings.verified,\n branch: workspace.branch,\n base: base.kind === 'resolved' ? base.ref : null,\n budget: workspace.config.context.budget,\n });\n}\n\n/* ------------------------------------------------------------------- audit */\n\nasync function dependencyChanges(workspace: Workspace, base: Base): Promise<AuditInput['dependencies']> {\n // A name that cannot be read is reported with or without a base: it would\n // leave its manifests out of every audit measured from one.\n const names = readManifestNames(workspace.config.dependencies.manifests);\n if (base.kind === 'unresolved') return { changes: [], unread: [], unreadNames: names.unread, rootedNames: names.rooted };\n const isManifest = names.match;\n const out: DependencyChange[] = [];\n const unread: string[] = [];\n for (const change of await changes(base.mergeBase, base.head, workspace.root)) {\n if (!isManifest(change.path) && !(change.from !== undefined && isManifest(change.from))) continue;\n const ecosystem = ecosystemOf(change.path);\n if (ecosystem === null) {\n unread.push(change.path);\n continue;\n }\n const before = change.status === 'A' ? null : await show(base.mergeBase, change.from ?? change.path, workspace.root);\n const after = change.status === 'D' ? null : await show(base.head, change.path, workspace.root);\n const diff = diffManifest(change.path, ecosystem, before, after);\n if ('error' in diff) unread.push(change.path);\n else out.push(...diff.changes);\n }\n return { changes: out, unread, unreadNames: names.unread, rootedNames: names.rooted };\n}\n\n/** A file's real path, links and the filesystem's case resolved, or `null` when there is no such file. */\nfunction realFile(path: string): string | null {\n try {\n return realpathSync.native(path);\n } catch {\n return null;\n }\n}\n\n/**\n * Whether a path spec-brief's `plugins` names, read from the root, is this\n * package's plugin: the file its `./spec-brief-plugin` export names, as the\n * project installed the package, or as this copy of it ships. spec-brief\n * loads a plugin by a path as well as by its name, and a path to the plugin\n * read as another plugin would say the archive cannot accept a ruling it can.\n */\nexport function pluginFile(root: string): (path: string) => boolean {\n const installed = join(root, 'node_modules', '@descent-vtt', 'spec-harness');\n const candidates: string[] = [fileURLToPath(new URL('../dist/plugin.js', import.meta.url))];\n try {\n // A manifest with no exports, or none for the plugin, throws in `join`\n // or on the missing key inside this block, which the catch reads as no\n // installed copy: `exports?.` and `target !== null` are equivalent to\n // their mutants here.\n const manifest = JSON.parse(readFileSync(join(installed, 'package.json'), 'utf8')) as { exports?: Record<string, unknown> };\n const target = exportedFile(manifest.exports?.['./spec-brief-plugin']);\n if (target !== null) candidates.push(join(installed, target));\n } catch {\n // Not installed at the root, or its manifest cannot be read: this copy's file is the one to compare.\n }\n // A candidate that names no file is `null` here, and so is a path that\n // names none, which is never the plugin.\n const files = new Set(candidates.map(realFile));\n return (path) => {\n const file = realFile(resolve(root, path));\n return file !== null && files.has(file);\n };\n}\n\n/** Whether spec-brief loads this package's plugin, as its configuration at the root says. */\nexport async function specBriefPlugin(root: string): Promise<PluginState> {\n const file = SPEC_BRIEF_CONFIGS.find((name) => existsSync(join(root, name)));\n if (file === undefined) return { kind: 'unconfigured' };\n const config = await readJsonObject(join(root, file));\n if (config === null || config === 'unreadable') return { kind: 'unreadable', file };\n return { kind: loadsPlugin(config, pluginFile(root)) ? 'loaded' : 'not-loaded', file };\n}\n\n/**\n * Claude Code's settings files that can turn a plugin on or hold a hook,\n * lowest precedence first: the user's, the project's, and the person's own\n * for the project. The user's is in `CLAUDE_CONFIG_DIR` when that is set,\n * otherwise in `.claude` under the home directory Claude Code uses,\n * `USERPROFILE` on Windows and `HOME` elsewhere; with neither it is not read.\n * Managed settings and `--settings` are not files a project can see.\n */\nexport function claudeSettingsFiles(root: string, env: CliIO['env'], platform: NodeJS.Platform = process.platform): { file: string; path: string }[] {\n const home = (platform === 'win32' ? env['USERPROFILE'] : env['HOME']) || undefined;\n const configDir = env['CLAUDE_CONFIG_DIR'] || (home === undefined ? undefined : join(home, '.claude'));\n const user = configDir === undefined ? null : join(configDir, 'settings.json');\n return [\n ...(user === null ? [] : [{ file: user, path: user }]),\n { file: '.claude/settings.json', path: join(root, '.claude', 'settings.json') },\n { file: '.claude/settings.local.json', path: join(root, '.claude', 'settings.local.json') },\n ];\n}\n\n/** The settings files Claude Code reads here, as read; one that is missing or cannot be read as JSON holds nothing. */\nexport async function claudeSettings(root: string, env: CliIO['env']): Promise<ClaudeSettings[]> {\n return Promise.all(claudeSettingsFiles(root, env).map(async ({ file, path }) => ({ file, settings: await readJsonObject(path) })));\n}\n\n/** Whether the plugin, init's entries, both or neither wire Claude Code to the harness here. */\nexport async function claudeCodeWiring(root: string, env: CliIO['env']): Promise<ClaudeCodeWiring> {\n const sources = await claudeSettings(root, env);\n return {\n plugin: enabledPlugin(sources),\n hooks: sources.filter(({ settings }) => holdsGuard(settings)).map(({ file }) => file),\n server: registersServer(await readJsonObject(join(root, '.mcp.json'))),\n };\n}\n\nasync function archiveReasons(workspace: Workspace, brief: BriefRow, base: Base): Promise<{ blocking: ArchiveReason[]; warnings: ArchiveReason[] } | { unavailable: string }> {\n const args = ['archive', brief.id, '--dry-run', '--format', 'json', '--no-color'];\n if (base.kind === 'resolved') args.push('--base', base.ref);\n const answer = await workspace.siblings.json('spec-brief', args);\n if ('absent' in answer) return { unavailable: answer.absent };\n if (answer.code === 2) return { unavailable: 'spec-brief could not plan the archive' };\n const plan = (answer.document as { plan?: { blocking?: ArchiveReason[]; warnings?: ArchiveReason[] } }).plan;\n return { blocking: plan?.blocking ?? [], warnings: plan?.warnings ?? [] };\n}\n\ninterface GuardRun {\n readonly results?: readonly { readonly ok: boolean; readonly description: string; readonly message: string; readonly spec?: { readonly file: string; readonly line: number } }[];\n readonly errors?: readonly { readonly message: string; readonly raw?: string; readonly spec?: { readonly file: string; readonly line: number } }[];\n}\n\n/** The brief's assertions as spec-guard ran them, and those it could not read, which it lists apart as `errors`. */\nasync function briefAssertions(\n workspace: Workspace,\n brief: BriefRow,\n text: string,\n reader: DocumentReader,\n): Promise<{ outcomes: AssertionOutcome[]; unreadable: UnreadableAssertion[] } | { unavailable: string }> {\n const answer = await workspace.siblings.json('spec-guard', [brief.file, '--ignore-status', '--json']);\n if ('absent' in answer) return { unavailable: answer.absent };\n if (answer.code === 2) return { unavailable: 'spec-guard could not run the brief\\'s assertions' };\n const report = answer.document as GuardRun;\n const own = (spec: { readonly file: string } | undefined): boolean => spec === undefined || spec.file.replace(/\\\\/g, '/') === brief.file;\n const outcomes = (report.results ?? [])\n .filter((result) => own(result.spec))\n .map((result) => {\n const line = result.spec?.line ?? 0;\n return { ok: result.ok, description: result.description, message: result.message, line, section: reader.sectionAt(text, line), enclosing: reader.sectionsAt(text, line) };\n });\n const unreadable = (report.errors ?? []).filter((error) => own(error.spec)).map((error) => ({ message: error.message, line: error.spec?.line ?? 0, raw: error.raw ?? '' }));\n return { outcomes, unreadable };\n}\n\nexport interface AuditResult {\n readonly brief: BriefRow;\n readonly base: Base;\n readonly report: AuditReport;\n readonly dependencies: readonly DependencyChange[];\n}\n\nexport async function runAudit(workspace: Workspace, brief: BriefRow, reader: DocumentReader, baseFlag: string | undefined): Promise<AuditResult> {\n const base = await resolveBase(workspace, baseFlag);\n const text = await briefText(workspace, brief);\n const [dependencies, archive, assertions, rulings, plugin] = await Promise.all([\n dependencyChanges(workspace, base),\n archiveReasons(workspace, brief, base),\n briefAssertions(workspace, brief, text, reader),\n checkRulings(workspace, brief, text, reader, base),\n specBriefPlugin(workspace.root),\n ]);\n const unmeasured =\n base.kind === 'unresolved' ? base.reason : base.mergeBase === base.head ? `${base.ref} and HEAD are the same commit: there is nothing to measure` : null;\n const report = audit({\n brief,\n unmeasured,\n dependencies,\n archive,\n assertions: 'unavailable' in assertions ? assertions : assertions.outcomes,\n // The audit reads no list as an empty one, and a run spec-guard could not\n // make has none, so a mutant of this test reads the same.\n unreadableAssertions: 'unavailable' in assertions ? [] : assertions.unreadable,\n premiseSections: workspace.config.assertions.premises,\n unverifiedRulings: rulings.unverified,\n verifiedRulings: rulings.verified,\n pluginLoaded: plugin.kind === 'loaded',\n });\n const findings = [...rulings.problems, ...report.findings];\n return { brief, base, dependencies: dependencies.changes, report: { findings, counts: tally(findings), measured: report.measured } };\n}\n\n/* -------------------------------------------------------------- escalation */\n\nasync function escalationDirectory(workspace: Workspace): Promise<string> {\n return stateDirectory(workspace.commonDir, 'escalations');\n}\n\nexport async function listEscalations(workspace: Workspace): Promise<EscalationRequest[]> {\n const directory = await escalationDirectory(workspace);\n const out: EscalationRequest[] = [];\n for (const name of (await readdir(directory)).filter((n) => n.endsWith('.json')).sort()) {\n try {\n out.push(JSON.parse(await readFile(join(directory, name), 'utf8')) as EscalationRequest);\n } catch {\n // A request that cannot be read is skipped; listing it would list nothing true.\n }\n }\n return out;\n}\n\nexport async function raiseEscalation(\n workspace: Workspace,\n brief: BriefRow,\n request: { paths: readonly string[]; reason: string; options: readonly EscalationOption[]; recommendation: string | null },\n): Promise<{ request: EscalationRequest; memo: string }> {\n const existing = await listEscalations(workspace);\n const id = nextId('E', brief.id, existing.map((e) => e.id));\n const full: EscalationRequest = {\n id,\n brief: brief.id,\n briefFile: brief.file,\n paths: request.paths,\n reason: request.reason,\n options: request.options,\n recommendation: request.recommendation,\n created: new Date().toISOString(),\n branch: workspace.branch,\n head: await revision('HEAD', workspace.root),\n };\n await writeAtomic(join(await escalationDirectory(workspace), `${id}.json`), `${JSON.stringify(full, null, 2)}\\n`);\n return { request: full, memo: renderMemo(full) };\n}\n\n/** Writes a person's ruling into the brief and retires the request. Never commits: the signature is the person's. */\nexport async function recordRuling(\n workspace: Workspace,\n escalationId: string,\n decision: 'allow' | 'deny',\n note: string,\n reader: DocumentReader,\n): Promise<{ id: string; file: string; row: string }> {\n const request = (await listEscalations(workspace)).find((candidate) => candidate.id === escalationId.toUpperCase() || candidate.id === escalationId);\n if (request === undefined) throw new UsageError(`no escalation \"${escalationId}\" is waiting; spec-harness escalate --list shows those that are`);\n const path = join(workspace.root, request.briefFile);\n const text = await readText(path);\n if (text === null) throw new UsageError(`${request.briefFile} cannot be read`);\n const where = reader.sectionTables(text, workspace.config.rulings.section);\n const taken = readRulings(where.tables).rulings.map((row) => row.id);\n const id = nextId('R', request.brief, taken);\n const row = renderRow(id, request.paths, decision, note);\n await writeAtomic(path, addRulingRow(text, workspace.config.rulings.section, row, where));\n await rm(join(await escalationDirectory(workspace), `${request.id}.json`), { force: true });\n return { id, file: request.briefFile, row };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"round.js","sourceRoot":"","sources":["../src/round.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A round, measured: the operations the command line and the MCP server\n * share. Each gathers what a pure module needs - from git, the disk and the\n * siblings - and hands it over; the decisions are made in `context.ts`,\n * `audit.ts`, `guard.ts` and `rulings.ts`.\n */\n\nimport { createHash } from 'node:crypto';\nimport { existsSync, readFileSync, realpathSync } from 'node:fs';\nimport { readdir, readFile, rm } from 'node:fs/promises';\nimport { join, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nimport { readArchivePlan, readGuardRun } from './answers.js';\nimport { audit, tally, type ArchiveReason, type AssertionOutcome, type AuditInput, type AuditReport, type UnreadableAssertion } from './audit.js';\nimport { SiblingOutputError } from './briefs.js';\nimport { sameId } from './branch.js';\nimport {\n enabledPlugin,\n exportedFile,\n holdsGuard,\n loadsPlugin,\n registersServer,\n SPEC_BRIEF_CONFIGS,\n type BaseSource,\n type ClaudeCodeWiring,\n type ClaudeSettings,\n type PluginState,\n} from './configure.js';\nimport { readRules, renderContext, type CitedDocument, type ContextPacket, type Rules } from './context.js';\nimport type { DocumentReader } from './document.js';\nimport { readJsonObject, readText, repositoryPath, stateDirectory, writeAtomic } from './fs.js';\nimport { blameLine, changes, isUncommitted, mergeBase, remoteDefault, revision, show, verifyCommit } from './git.js';\nimport { decide, type Decision, type VerifiedRuling } from './guard.js';\nimport { diffManifest, ecosystemOf, readManifestNames, type DependencyChange } from './manifests.js';\nimport {\n addRulingRow,\n nextId,\n readRulings,\n renderMemo,\n renderRow,\n type EscalationOption,\n type EscalationRequest,\n type RulingRow,\n} from './rulings.js';\nimport type { BriefRow, Finding } from './types.js';\nimport { compileGlob, type LiteralReading } from './vendor/spec-core/pattern/index.js';\nimport { dirname, isRelativeReference, resolveInside, splitReference } from './vendor/spec-core/path/index.js';\nimport { SiblingError } from './siblings.js';\nimport { UsageError, type CliIO, type Workspace } from './workspace.js';\n\n/* -------------------------------------------------------------------- base */\n\nexport type Base =\n | { readonly kind: 'resolved'; readonly ref: string; readonly source: BaseSource; readonly sha: string; readonly mergeBase: string; readonly head: string }\n | { readonly kind: 'unresolved'; readonly reason: string };\n\n/** What the round is measured from: the flag, the configuration, then the remote's default branch. */\nexport async function resolveBase(workspace: Workspace, flag: string | undefined): Promise<Base> {\n const source: BaseSource = flag !== undefined ? 'flag' : workspace.config.base !== null ? 'config' : 'remote';\n const ref = flag ?? workspace.config.base ?? (await remoteDefault(workspace.root));\n if (ref === null) {\n return { kind: 'unresolved', reason: 'no base is named and the remote has no default branch; pass --base <ref> or set \"base\"' };\n }\n const sha = await revision(ref, workspace.root);\n if (sha === null) return { kind: 'unresolved', reason: `\"${ref}\" names no commit` };\n const head = await revision('HEAD', workspace.root);\n if (head === null) return { kind: 'unresolved', reason: 'HEAD names no commit: nothing is committed on this branch yet' };\n const common = await mergeBase(sha, head, workspace.root);\n if (common === null) return { kind: 'unresolved', reason: `\"${ref}\" and HEAD share no history` };\n return { kind: 'resolved', ref, source, sha, mergeBase: common, head };\n}\n\n/* ----------------------------------------------------------------- rulings */\n\nexport interface RulingCheck {\n readonly rows: readonly RulingRow[];\n readonly verified: readonly VerifiedRuling[];\n readonly unverified: readonly { readonly id: string; readonly reason: string }[];\n readonly problems: readonly Finding[];\n}\n\n/**\n * The brief's rulings, each checked against its signature: the commit that\n * last changed its row must be signed by a principal the base branch's\n * allowed-signers file lists (ADR-0006).\n */\nexport async function checkRulings(workspace: Workspace, brief: Pick<BriefRow, 'file'>, text: string, reader: DocumentReader, base: Base): Promise<RulingCheck> {\n const { rulings: rows, problems } = readRulings(reader.sectionTables(text, workspace.config.rulings.section).tables);\n const findings: Finding[] = problems.map((problem) => ({\n rule: 'ruling-unreadable',\n severity: 'warning',\n message: problem.message,\n hint: 'a ruling row is | id | `paths` | allow or deny | note |',\n file: brief.file,\n line: problem.line,\n }));\n const allows = rows.filter((row) => row.decision === 'allow');\n // Nothing below verifies a row that allows nothing, so this saves a git\n // show and is equivalent to its mutants.\n if (allows.length === 0) return { rows, verified: [], unverified: [], problems: findings };\n if (base.kind === 'unresolved') {\n return { rows, verified: [], unverified: allows.map((row) => ({ id: row.id, reason: `no base to read the allowed signers from: ${base.reason}` })), problems: findings };\n }\n const signers = await show(base.sha, workspace.config.rulings.allowedSigners, workspace.root);\n if (signers === null) {\n const reason = `${base.ref} has no ${workspace.config.rulings.allowedSigners}, so no signature can count`;\n return { rows, verified: [], unverified: allows.map((row) => ({ id: row.id, reason })), problems: findings };\n }\n // Only verify-commit below reads this copy, so where it is kept, and under\n // what name, is equivalent to its mutants.\n const directory = await stateDirectory(workspace.commonDir, 'signers');\n const file = join(directory, `${createHash('sha256').update(signers).digest('hex').slice(0, 16)}`);\n await writeAtomic(file, signers);\n const verified: VerifiedRuling[] = [];\n const unverified: { id: string; reason: string }[] = [];\n for (const row of allows) {\n // The row's line is a line of the text on disk, so it is blamed there: at\n // HEAD the same number can be another line, one a signed commit wrote,\n // and an uncommitted row would borrow that commit's signature.\n const commit = await blameLine(null, brief.file, row.line, workspace.root);\n if (commit === null || isUncommitted(commit)) {\n unverified.push({ id: row.id, reason: 'its row is not committed' });\n continue;\n }\n const signature = await verifyCommit(commit, file, workspace.root);\n if (signature.good) verified.push({ id: row.id, paths: row.paths, signer: signature.principal });\n else unverified.push({ id: row.id, reason: `commit ${commit.slice(0, 12)} last changed its row, and ${signature.detail || 'it is not signed'}` });\n }\n return { rows, verified, unverified, problems: findings };\n}\n\n/* ------------------------------------------------------------------- guard */\n\nexport async function briefText(workspace: Workspace, brief: BriefRow): Promise<string> {\n const text = await readText(join(workspace.root, brief.file));\n if (text === null) throw new UsageError(`${brief.file} cannot be read`);\n return text;\n}\n\n/** Decides paths against the brief, with the rulings verified against the base `baseFlag` names, or the configured one. */\nexport async function checkPaths(\n workspace: Workspace,\n brief: BriefRow | null,\n noBrief: string | undefined,\n given: readonly string[],\n cwd: string,\n reader: DocumentReader,\n baseFlag: string | undefined,\n): Promise<Decision[]> {\n const resolved = given.map((path) => ({ given: path, path: repositoryPath(path, workspace.root, cwd) }));\n const decideAll = (rulings: readonly VerifiedRuling[]): Decision[] =>\n resolved.map(({ path, given: g }) => decide({ path, given: g, brief, noBrief, rulings, outOfScope: workspace.config.outOfScope }));\n const first = decideAll([]);\n // Rulings cost a blame and a signature check each, so they are read only\n // when a write reaches a protected file. Read anyway, they decide the same,\n // since a ruling allows only a protected path, so mutants that always read\n // them are equivalent; and with no brief nothing is protected, so the null\n // check is there for the type.\n if (brief === null || !first.some((decision) => decision.reason === 'protected')) return first;\n const base = await resolveBase(workspace, baseFlag);\n return decideAll((await checkRulings(workspace, brief, await briefText(workspace, brief), reader, base)).verified);\n}\n\n/* ----------------------------------------------------------------- context */\n\n/**\n * The paths spec-guard is asked about for a scope: where its patterns can\n * match. A name with no glob syntax that exists is asked about as itself,\n * since spec-guard reads from the disk whether a path is a file or a\n * directory. One the round has yet to create may become either, and\n * spec-guard would read it as a file, leaving out the rules over a\n * directory of that name; it is asked about through the directory that will\n * hold it, the root for a name at the top, which covers both.\n */\nfunction scopeBases(root: string, patterns: readonly string[]): string[] {\n // Read as a directory, a name's base is the name itself; read any other\n // way, it is the directory holding it, so which other reading a missing\n // name gets changes nothing. The glob is compiled for its bases and never\n // matched: a file read as a directory narrows the question and nothing\n // else.\n const literal = (path: string): LiteralReading => (existsSync(join(root, path)) ? 'directory' : 'either');\n const bases = new Set<string>();\n for (const pattern of patterns) {\n try {\n // Case is read only in matching, which this compile never does: its\n // bases are the same either way, so `caseSensitive: false` is equivalent.\n for (const base of compileGlob(pattern, { dialect: 'path', caseSensitive: true, literal }).bases) {\n // A rooted alternative's base, `/docs` or `/`, is outside the\n // repository: it puts no path in the scope, and spec-guard refuses\n // the whole question for it, with the rules for every other base.\n // The packet names the pattern.\n if (base.startsWith('/')) continue;\n bases.add(base === '' ? '.' : base);\n }\n } catch {\n // The packet names a pattern the guard cannot read, with spec-core's\n // reason, and says so when it is every pattern; the rules for the rest\n // still count.\n }\n }\n return [...bases].sort();\n}\n\nasync function rulesFor(workspace: Workspace, brief: BriefRow): Promise<Rules> {\n const paths = scopeBases(workspace.root, brief.affectedFiles);\n if (paths.length === 0) return [];\n try {\n const answer = await workspace.siblings.json('spec-guard', ['query', ...paths, '--json']);\n return 'absent' in answer ? { unavailable: answer.absent } : readRules(answer);\n } catch (error) {\n // spec-guard printed no JSON, or a document of another shape: what it\n // said instead, or what was wrong, is the reason, and the rest of the\n // packet stands without the rules.\n if (error instanceof SiblingError || error instanceof SiblingOutputError) return { unavailable: error.message };\n throw error;\n }\n}\n\nasync function citedDocuments(workspace: Workspace, brief: BriefRow, text: string, reader: DocumentReader): Promise<CitedDocument[]> {\n const seen = new Set<string>();\n const out: CitedDocument[] = [];\n for (const citation of reader.citations(text)) {\n if (!isRelativeReference(citation.target)) continue;\n let target = splitReference(citation.target).path;\n try {\n target = decodeURIComponent(target);\n } catch {\n // A destination that is not valid percent-encoding is read as written.\n }\n const path = resolveInside(dirname(brief.file), target);\n if (path === null || path === brief.file || seen.has(path)) continue;\n seen.add(path);\n const document = /\\.(?:md|markdown|mdx|txt)$/i.test(path);\n // A link to code or a directory that exists is not a document to include,\n // and must not be reported as a link that resolves to nothing.\n if (!document && existsSync(join(workspace.root, path))) continue;\n const content = document ? await readText(join(workspace.root, path)) : null;\n // A document that cannot be read is listed by its path alone, so its\n // title and status are never read, and an empty object is equivalent.\n const meta = content === null ? { title: null, status: null } : reader.titleAndStatus(content);\n out.push({ path, ...meta, text: content });\n }\n return out;\n}\n\nexport async function buildContext(\n workspace: Workspace,\n brief: BriefRow,\n briefs: readonly BriefRow[],\n reader: DocumentReader,\n baseFlag: string | undefined,\n): Promise<ContextPacket> {\n const text = await briefText(workspace, brief);\n const base = await resolveBase(workspace, baseFlag);\n const [rules, cited, rulings] = await Promise.all([\n rulesFor(workspace, brief),\n citedDocuments(workspace, brief, text, reader),\n checkRulings(workspace, brief, text, reader, base),\n ]);\n return renderContext({\n brief,\n briefText: text,\n dependencies: brief.dependsOn.map(\n (id) =>\n // spec-brief reports a dependency as its front matter spells it, `7` for brief 007.\n // The context reads a dependency's id, title, status and phase, and\n // the brief copied here is live.\n briefs.find((candidate) => sameId(candidate.id, id)) ?? { ...brief, id, title: '(no such brief)', status: 'unknown' },\n ),\n cited,\n rules,\n rulings: rulings.verified,\n branch: workspace.branch,\n base: base.kind === 'resolved' ? base.ref : null,\n budget: workspace.config.context.budget,\n });\n}\n\n/* ------------------------------------------------------------------- audit */\n\nasync function dependencyChanges(workspace: Workspace, base: Base): Promise<AuditInput['dependencies']> {\n // A name that cannot be read is reported with or without a base: it would\n // leave its manifests out of every audit measured from one.\n const names = readManifestNames(workspace.config.dependencies.manifests);\n if (base.kind === 'unresolved') return { changes: [], unread: [], unreadNames: names.unread, rootedNames: names.rooted };\n const isManifest = names.match;\n const out: DependencyChange[] = [];\n const unread: string[] = [];\n for (const change of await changes(base.mergeBase, base.head, workspace.root)) {\n if (!isManifest(change.path) && !(change.from !== undefined && isManifest(change.from))) continue;\n const ecosystem = ecosystemOf(change.path);\n if (ecosystem === null) {\n unread.push(change.path);\n continue;\n }\n // git shows nothing where a file is not: an added manifest has no before,\n // and a deleted one no after.\n const before = await show(base.mergeBase, change.from ?? change.path, workspace.root);\n const after = await show(base.head, change.path, workspace.root);\n const diff = diffManifest(change.path, ecosystem, before, after);\n if ('error' in diff) unread.push(change.path);\n else out.push(...diff.changes);\n }\n return { changes: out, unread, unreadNames: names.unread, rootedNames: names.rooted };\n}\n\n/** A file's real path, links and the filesystem's case resolved, or `null` when there is no such file. */\nfunction realFile(path: string): string | null {\n try {\n return realpathSync.native(path);\n } catch {\n return null;\n }\n}\n\n/**\n * Whether a path spec-brief's `plugins` names, read from the root, is this\n * package's plugin: the file its `./spec-brief-plugin` export names, as the\n * project installed the package, or as this copy of it ships. spec-brief\n * loads a plugin by a path as well as by its name, and a path to the plugin\n * read as another plugin would say the archive cannot accept a ruling it can.\n */\nexport function pluginFile(root: string): (path: string) => boolean {\n const installed = join(root, 'node_modules', '@descent-vtt', 'spec-harness');\n const candidates: string[] = [fileURLToPath(new URL('../dist/plugin.js', import.meta.url))];\n try {\n // A manifest with no exports, or none for the plugin, throws in `join`\n // or on the missing key inside this block, which the catch reads as no\n // installed copy: `exports?.` and `target !== null` are equivalent to\n // their mutants here.\n const manifest = JSON.parse(readFileSync(join(installed, 'package.json'), 'utf8')) as { exports?: Record<string, unknown> };\n const target = exportedFile(manifest.exports?.['./spec-brief-plugin']);\n if (target !== null) candidates.push(join(installed, target));\n } catch {\n // Not installed at the root, or its manifest cannot be read: this copy's file is the one to compare.\n }\n // A candidate that names no file is `null` here, and so is a path that\n // names none, which is never the plugin.\n const files = new Set(candidates.map(realFile));\n return (path) => {\n const file = realFile(resolve(root, path));\n return file !== null && files.has(file);\n };\n}\n\n/** Whether spec-brief loads this package's plugin, as its configuration at the root says. */\nexport async function specBriefPlugin(root: string): Promise<PluginState> {\n const file = SPEC_BRIEF_CONFIGS.find((name) => existsSync(join(root, name)));\n if (file === undefined) return { kind: 'unconfigured' };\n const config = await readJsonObject(join(root, file));\n // The file was found a moment ago, so null is one removed in between, and\n // reads as the unreadable one it has become.\n if (config === null || config === 'unreadable') return { kind: 'unreadable', file };\n return { kind: loadsPlugin(config, pluginFile(root)) ? 'loaded' : 'not-loaded', file };\n}\n\n/**\n * Claude Code's settings files that can turn a plugin on or hold a hook,\n * lowest precedence first: the user's, the project's, and the person's own\n * for the project. The user's is in `CLAUDE_CONFIG_DIR` when that is set,\n * otherwise in `.claude` under the home directory Claude Code uses,\n * `USERPROFILE` on Windows and `HOME` elsewhere; with neither it is not read.\n * Managed settings and `--settings` are not files a project can see.\n */\nexport function claudeSettingsFiles(root: string, env: CliIO['env'], platform: NodeJS.Platform = process.platform): { file: string; path: string }[] {\n const home = (platform === 'win32' ? env['USERPROFILE'] : env['HOME']) || undefined;\n const configDir = env['CLAUDE_CONFIG_DIR'] || (home === undefined ? undefined : join(home, '.claude'));\n const user = configDir === undefined ? null : join(configDir, 'settings.json');\n return [\n ...(user === null ? [] : [{ file: user, path: user }]),\n { file: '.claude/settings.json', path: join(root, '.claude', 'settings.json') },\n { file: '.claude/settings.local.json', path: join(root, '.claude', 'settings.local.json') },\n ];\n}\n\n/** The settings files Claude Code reads here, as read; one that is missing or cannot be read as JSON holds nothing. */\nexport async function claudeSettings(root: string, env: CliIO['env']): Promise<ClaudeSettings[]> {\n return Promise.all(claudeSettingsFiles(root, env).map(async ({ file, path }) => ({ file, settings: await readJsonObject(path) })));\n}\n\n/** Whether the plugin, init's entries, both or neither wire Claude Code to the harness here. */\nexport async function claudeCodeWiring(root: string, env: CliIO['env']): Promise<ClaudeCodeWiring> {\n const sources = await claudeSettings(root, env);\n return {\n plugin: enabledPlugin(sources),\n hooks: sources.filter(({ settings }) => holdsGuard(settings)).map(({ file }) => file),\n server: registersServer(await readJsonObject(join(root, '.mcp.json'))),\n };\n}\n\nasync function archiveReasons(workspace: Workspace, brief: BriefRow, base: Base): Promise<{ blocking: ArchiveReason[]; warnings: ArchiveReason[] } | { unavailable: string }> {\n const args = ['archive', brief.id, '--dry-run', '--format', 'json', '--no-color'];\n if (base.kind === 'resolved') args.push('--base', base.ref);\n const answer = await workspace.siblings.json('spec-brief', args);\n // The audit listed the briefs through spec-brief before it asks this, so\n // an absent one stopped it there; the check is for the type.\n if ('absent' in answer) return { unavailable: answer.absent };\n if (answer.code === 2) return { unavailable: 'spec-brief could not plan the archive' };\n return readArchivePlan(answer.document);\n}\n\n/** The brief's assertions as spec-guard ran them, and those it could not read, which it lists apart as `errors`. */\nasync function briefAssertions(\n workspace: Workspace,\n brief: BriefRow,\n text: string,\n reader: DocumentReader,\n): Promise<{ outcomes: AssertionOutcome[]; unreadable: UnreadableAssertion[] } | { unavailable: string }> {\n const answer = await workspace.siblings.json('spec-guard', [brief.file, '--ignore-status', '--json']);\n if ('absent' in answer) return { unavailable: answer.absent };\n if (answer.code === 2) return { unavailable: 'spec-guard could not run the brief\\'s assertions' };\n const report = readGuardRun(answer.document);\n const own = (spec: { readonly file: string } | undefined): boolean => spec === undefined || spec.file.replace(/\\\\/g, '/') === brief.file;\n const outcomes = report.results\n .filter((result) => own(result.spec))\n .map((result) => {\n const line = result.spec?.line ?? 0;\n return { ok: result.ok, description: result.description, message: result.message, line, section: reader.sectionAt(text, line), enclosing: reader.sectionsAt(text, line) };\n });\n const unreadable = report.errors.filter((error) => own(error.spec)).map((error) => ({ message: error.message, line: error.spec?.line ?? 0, raw: error.raw }));\n return { outcomes, unreadable };\n}\n\nexport interface AuditResult {\n readonly brief: BriefRow;\n readonly base: Base;\n readonly report: AuditReport;\n readonly dependencies: readonly DependencyChange[];\n}\n\nexport async function runAudit(workspace: Workspace, brief: BriefRow, reader: DocumentReader, baseFlag: string | undefined): Promise<AuditResult> {\n const base = await resolveBase(workspace, baseFlag);\n const text = await briefText(workspace, brief);\n const [dependencies, archive, assertions, rulings, plugin] = await Promise.all([\n dependencyChanges(workspace, base),\n archiveReasons(workspace, brief, base),\n briefAssertions(workspace, brief, text, reader),\n checkRulings(workspace, brief, text, reader, base),\n specBriefPlugin(workspace.root),\n ]);\n const unmeasured =\n base.kind === 'unresolved' ? base.reason : base.mergeBase === base.head ? `${base.ref} and HEAD are the same commit: there is nothing to measure` : null;\n const report = audit({\n brief,\n unmeasured,\n dependencies,\n archive,\n assertions: 'unavailable' in assertions ? assertions : assertions.outcomes,\n // The audit reads no list as an empty one, and a run spec-guard could not\n // make has none, so a mutant of this test reads the same.\n unreadableAssertions: 'unavailable' in assertions ? [] : assertions.unreadable,\n premiseSections: workspace.config.assertions.premises,\n unverifiedRulings: rulings.unverified,\n verifiedRulings: rulings.verified,\n pluginLoaded: plugin.kind === 'loaded',\n });\n const findings = [...rulings.problems, ...report.findings];\n return { brief, base, dependencies: dependencies.changes, report: { findings, counts: tally(findings), measured: report.measured } };\n}\n\n/* -------------------------------------------------------------- escalation */\n\nasync function escalationDirectory(workspace: Workspace): Promise<string> {\n return stateDirectory(workspace.commonDir, 'escalations');\n}\n\nexport async function listEscalations(workspace: Workspace): Promise<EscalationRequest[]> {\n const directory = await escalationDirectory(workspace);\n const out: EscalationRequest[] = [];\n for (const name of (await readdir(directory)).filter((n) => n.endsWith('.json')).sort()) {\n try {\n out.push(JSON.parse(await readFile(join(directory, name), 'utf8')) as EscalationRequest);\n } catch {\n // A request that cannot be read is skipped; listing it would list nothing true.\n }\n }\n return out;\n}\n\nexport async function raiseEscalation(\n workspace: Workspace,\n brief: BriefRow,\n request: { paths: readonly string[]; reason: string; options: readonly EscalationOption[]; recommendation: string | null },\n): Promise<{ request: EscalationRequest; memo: string }> {\n const existing = await listEscalations(workspace);\n const id = nextId('E', brief.id, existing.map((e) => e.id));\n const full: EscalationRequest = {\n id,\n brief: brief.id,\n briefFile: brief.file,\n paths: request.paths,\n reason: request.reason,\n options: request.options,\n recommendation: request.recommendation,\n created: new Date().toISOString(),\n branch: workspace.branch,\n head: await revision('HEAD', workspace.root),\n };\n await writeAtomic(join(await escalationDirectory(workspace), `${id}.json`), `${JSON.stringify(full, null, 2)}\\n`);\n return { request: full, memo: renderMemo(full) };\n}\n\n/** Writes a person's ruling into the brief and retires the request. Never commits: the signature is the person's. */\nexport async function recordRuling(\n workspace: Workspace,\n escalationId: string,\n decision: 'allow' | 'deny',\n note: string,\n reader: DocumentReader,\n): Promise<{ id: string; file: string; row: string }> {\n const request = (await listEscalations(workspace)).find((candidate) => candidate.id === escalationId.toUpperCase() || candidate.id === escalationId);\n if (request === undefined) throw new UsageError(`no escalation \"${escalationId}\" is waiting; spec-harness escalate --list shows those that are`);\n const path = join(workspace.root, request.briefFile);\n const text = await readText(path);\n if (text === null) throw new UsageError(`${request.briefFile} cannot be read`);\n const where = reader.sectionTables(text, workspace.config.rulings.section);\n const taken = readRulings(where.tables).rulings.map((row) => row.id);\n const id = nextId('R', request.brief, taken);\n const row = renderRow(id, request.paths, decision, note);\n await writeAtomic(path, addRulingRow(text, workspace.config.rulings.section, row, where));\n // Listed a moment ago; forced, a request another process retired in\n // between is not an error, so the option is equivalent to its mutants.\n await rm(join(await escalationDirectory(workspace), `${request.id}.json`), { force: true });\n return { id, file: request.briefFile, row };\n}\n"]}
|
package/dist/server.js
CHANGED
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
* request reads the repository afresh: a brief edited a minute ago is the
|
|
6
6
|
* brief the next answer uses.
|
|
7
7
|
*/
|
|
8
|
-
import {
|
|
8
|
+
import { readFileSync } from 'node:fs';
|
|
9
|
+
import { Readable } from 'node:stream';
|
|
9
10
|
import { fileURLToPath } from 'node:url';
|
|
10
11
|
import { describeMeasured } from './audit.js';
|
|
11
12
|
import { findActive } from './briefs.js';
|
|
@@ -37,13 +38,13 @@ async function round(workspace, env, id) {
|
|
|
37
38
|
if (id !== undefined && typeof id !== 'string')
|
|
38
39
|
return toolError('"brief" must be a string.');
|
|
39
40
|
const briefs = await workspace.siblings.briefs();
|
|
40
|
-
const fromBranch =
|
|
41
|
+
const fromBranch = briefIdFromBranch(workspace.config.branches, workspace.branch);
|
|
41
42
|
const active = findActive(briefs, { flag: id, environment: env['SPEC_BRIEF'], branch: fromBranch });
|
|
42
43
|
const { brief, note, problem } = describeActive(active);
|
|
43
44
|
if (problem !== null)
|
|
44
45
|
return toolError(problem);
|
|
45
46
|
if (brief === null)
|
|
46
|
-
return toolError(note
|
|
47
|
+
return toolError(note);
|
|
47
48
|
return { brief, briefs };
|
|
48
49
|
}
|
|
49
50
|
export function tools(workspace, env) {
|
|
@@ -226,8 +227,12 @@ const SKILLS = [
|
|
|
226
227
|
{ name: 'close-round', title: 'Close a round', argument: 'brief', description: 'The brief id.' },
|
|
227
228
|
];
|
|
228
229
|
function skillText(name) {
|
|
229
|
-
|
|
230
|
-
|
|
230
|
+
// The package ships the skills beside dist/ (package.json's files), so one
|
|
231
|
+
// that cannot be read is a broken install, and the request fails saying so
|
|
232
|
+
// rather than serving an empty prompt.
|
|
233
|
+
const text = readFileSync(fileURLToPath(new URL(`../skills/${name}/SKILL.md`, import.meta.url)), 'utf8');
|
|
234
|
+
// Every skill opens with its front matter (tests/source.test.ts), so the
|
|
235
|
+
// anchor is equivalent to its mutant here.
|
|
231
236
|
return text.replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n/, '').trim();
|
|
232
237
|
}
|
|
233
238
|
export function prompts() {
|
|
@@ -249,7 +254,12 @@ export async function mcpCommand(options, io) {
|
|
|
249
254
|
// the project in CLAUDE_PROJECT_DIR; the server answers for the project.
|
|
250
255
|
const workspace = await openWorkspace({ ...options, root: options.root ?? (io.env['CLAUDE_PROJECT_DIR'] || undefined) }, io);
|
|
251
256
|
const handle = createMcpServer({ name: 'spec-harness', version: version(), instructions: INSTRUCTIONS, tools: tools(workspace, io.env), prompts: prompts() });
|
|
252
|
-
|
|
257
|
+
// A session handed over whole, as a test hands it, is served as a client
|
|
258
|
+
// would stream it on stdin. Only the built command line serves
|
|
259
|
+
// process.stdin, and the suite spawns it from dist/, outside the sweep
|
|
260
|
+
// (tests/integration/mcp.test.ts), so a mutant that ignores it survives.
|
|
261
|
+
const input = io.stdin === undefined ? process.stdin : Readable.from([Buffer.from(await io.stdin())]);
|
|
262
|
+
await serveLines(input, (line) => io.stdout.write(`${line}\n`), handle);
|
|
253
263
|
return 0;
|
|
254
264
|
}
|
|
255
265
|
//# sourceMappingURL=server.js.map
|