@nimiplatform/nimi-coding 0.4.0 → 0.6.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/CHANGELOG.md +16 -0
- package/CONTRIBUTING.md +1 -1
- package/README.md +92 -55
- package/README.zh-CN.md +93 -56
- package/cli/commands/authority.mjs +80 -125
- package/cli/commands/clear.mjs +3 -2
- package/cli/commands/code.mjs +225 -0
- package/cli/commands/start.mjs +3 -2
- package/cli/constants.mjs +2 -1
- package/cli/dev/check-authority-surface.mjs +17 -8
- package/cli/dev/check-product-conformance.mjs +4 -32
- package/cli/dev/run-cli-smoke.mjs +6 -0
- package/cli/help.mjs +8 -3
- package/cli/index.mjs +3 -2
- package/cli/lib/authority/audit.mjs +262 -185
- package/cli/lib/authority/change-candidates.mjs +807 -0
- package/cli/lib/authority/closed-sets.mjs +7 -8
- package/cli/lib/authority/compile.mjs +6 -24
- package/cli/lib/authority/compiled-snapshot.mjs +143 -0
- package/cli/lib/authority/consumers.mjs +69 -19
- package/cli/lib/authority/diagnostics.mjs +10 -2
- package/cli/lib/authority/diff.mjs +77 -54
- package/cli/lib/authority/format.mjs +4 -32
- package/cli/lib/authority/git-snapshot.mjs +34 -379
- package/cli/lib/authority/graph.mjs +10 -10
- package/cli/lib/authority/impact.mjs +17 -144
- package/cli/lib/authority/review.mjs +33 -43
- package/cli/lib/authority/sarif.mjs +1 -8
- package/cli/lib/authority/source-yaml.mjs +0 -4
- package/cli/lib/authority/surface.mjs +19 -1
- package/cli/lib/authority/terms.mjs +10 -9
- package/cli/lib/authority/validate.mjs +6 -14
- package/cli/lib/code/authority-annotation-response.mjs +43 -0
- package/cli/lib/code/authority-annotation-scan.mjs +162 -0
- package/cli/lib/code/authority-annotations.mjs +293 -0
- package/cli/lib/code/context.mjs +710 -0
- package/cli/lib/code/response.mjs +165 -0
- package/cli/lib/doctor.mjs +3 -2
- package/cli/lib/entrypoints.mjs +13 -5
- package/cli/seeds/seed-policy.yaml +2 -2
- package/contracts/authority-source.schema.yaml +0 -6
- package/contracts/authority-verifier-bindings.schema.yaml +21 -10
- package/methodology/authority-authoring.yaml +68 -70
- package/methodology/core.yaml +10 -6
- package/package.json +5 -3
- package/spec/authority-audit.yaml +56 -52
- package/spec/authority-authoring.yaml +3 -16
- package/spec/authority-change-candidates.yaml +146 -0
- package/spec/authority-consumers.yaml +7 -0
- package/spec/authority-discovery.yaml +2 -2
- package/spec/authority-graph.yaml +1 -1
- package/spec/authority-impact.yaml +16 -39
- package/spec/authority-review.yaml +29 -47
- package/spec/authority-terms.yaml +5 -1
- package/spec/code-authority-annotations.yaml +42 -0
- package/spec/code-context.yaml +38 -0
- package/spec/product-scope.yaml +15 -9
- package/cli/commands/validate-ai-governance.mjs +0 -335
- package/cli/lib/authority/evidence-snapshot.mjs +0 -1
- package/cli/lib/authority/evidence.mjs +0 -1432
- package/cli/lib/internal/governance/ai/ai-context-budget-core.mjs +0 -377
- package/cli/lib/internal/governance/ai/ai-structure-budget-core.mjs +0 -376
- package/cli/lib/internal/governance/ai/check-agents-freshness.mjs +0 -155
- package/cli/lib/internal/governance/ai/check-high-risk-doc-metadata-core.mjs +0 -173
- package/cli/lib/internal/governance/config.mjs +0 -114
- package/cli/lib/internal/governance/shared/read-yaml-with-fragments.mjs +0 -49
- package/contracts/authority-evidence-bindings.schema.yaml +0 -53
- package/contracts/authority-evidence-probe-results.schema.yaml +0 -38
- package/contracts/authority-impact-dispositions.schema.yaml +0 -13
- package/spec/authority-evidence.yaml +0 -200
|
@@ -3,6 +3,7 @@ import { stat } from "node:fs/promises";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
|
|
5
5
|
import { compileAuthorityPath } from "./compile.mjs";
|
|
6
|
+
import { createCompiledAuthoritySnapshot } from "./compiled-snapshot.mjs";
|
|
6
7
|
import { compareText, makeDiagnostic, portablePath, sortDiagnostics } from "./diagnostics.mjs";
|
|
7
8
|
|
|
8
9
|
const DIFF_FORMAT = "nimicoding.authority-diff/v1";
|
|
@@ -46,14 +47,14 @@ function portableMapping(mapping, basePath) {
|
|
|
46
47
|
return { ...mapping, file: portablePath(mapping.file, basePath) };
|
|
47
48
|
}
|
|
48
49
|
|
|
49
|
-
function mappedAt(
|
|
50
|
-
const exact = compiled.sourceMap.fields[`/units/${unitIndex}${pointer}`];
|
|
51
|
-
if (exact) return portableMapping(exact,
|
|
50
|
+
function mappedAt(snapshot, unitIndex, pointer) {
|
|
51
|
+
const exact = snapshot.compiled.sourceMap.fields[`/units/${unitIndex}${pointer}`];
|
|
52
|
+
if (exact) return portableMapping(exact, snapshot.inputRoot);
|
|
52
53
|
const prefix = `/units/${unitIndex}${pointer}/`;
|
|
53
|
-
const nested = Object.entries(compiled.sourceMap.fields)
|
|
54
|
+
const nested = Object.entries(snapshot.compiled.sourceMap.fields)
|
|
54
55
|
.filter(([candidate]) => candidate.startsWith(prefix))
|
|
55
56
|
.sort(([left], [right]) => compareText(left, right))[0]?.[1];
|
|
56
|
-
return portableMapping(nested,
|
|
57
|
+
return portableMapping(nested, snapshot.inputRoot);
|
|
57
58
|
}
|
|
58
59
|
|
|
59
60
|
function addChange(changes, { unitId, operation = "modified", pointer, before, after, beforeSource = null, afterSource = null }) {
|
|
@@ -68,7 +69,7 @@ function addChange(changes, { unitId, operation = "modified", pointer, before, a
|
|
|
68
69
|
});
|
|
69
70
|
}
|
|
70
71
|
|
|
71
|
-
function compareScalar(changes,
|
|
72
|
+
function compareScalar(changes, beforeSnapshot, afterSnapshot, beforeEntry, afterEntry, pointer) {
|
|
72
73
|
const before = beforeEntry.unit;
|
|
73
74
|
const after = afterEntry.unit;
|
|
74
75
|
const read = (value, parts) => parts.reduce((current, part) => current?.[part], value);
|
|
@@ -81,21 +82,21 @@ function compareScalar(changes, beforeEntry, afterEntry, pointer, beforeBase, af
|
|
|
81
82
|
pointer,
|
|
82
83
|
before: left,
|
|
83
84
|
after: right,
|
|
84
|
-
beforeSource: mappedAt(
|
|
85
|
-
afterSource: mappedAt(
|
|
85
|
+
beforeSource: mappedAt(beforeSnapshot, beforeEntry.unitIndex, pointer),
|
|
86
|
+
afterSource: mappedAt(afterSnapshot, afterEntry.unitIndex, pointer),
|
|
86
87
|
});
|
|
87
88
|
}
|
|
88
89
|
|
|
89
|
-
function compareValueSet(changes,
|
|
90
|
+
function compareValueSet(changes, beforeSnapshot, afterSnapshot, beforeEntry, afterEntry, pointer) {
|
|
90
91
|
const parts = pointer.slice(1).split("/");
|
|
91
92
|
const read = (unit) => parts.reduce((current, part) => current?.[part], unit) ?? [];
|
|
92
93
|
const beforeValues = read(beforeEntry.unit);
|
|
93
94
|
const afterValues = read(afterEntry.unit);
|
|
94
95
|
const beforeSet = new Set(beforeValues.map((value) => JSON.stringify(value)));
|
|
95
96
|
const afterSet = new Set(afterValues.map((value) => JSON.stringify(value)));
|
|
96
|
-
for (const [operation, values, otherSet,
|
|
97
|
-
["removed", beforeValues, afterSet,
|
|
98
|
-
["added", afterValues, beforeSet,
|
|
97
|
+
for (const [operation, values, otherSet, snapshot, entry, sourceSide] of [
|
|
98
|
+
["removed", beforeValues, afterSet, beforeSnapshot, beforeEntry, "beforeSource"],
|
|
99
|
+
["added", afterValues, beforeSet, afterSnapshot, afterEntry, "afterSource"],
|
|
99
100
|
]) {
|
|
100
101
|
values.forEach((value, index) => {
|
|
101
102
|
if (otherSet.has(JSON.stringify(value))) return;
|
|
@@ -105,20 +106,20 @@ function compareValueSet(changes, beforeEntry, afterEntry, pointer, beforeBase,
|
|
|
105
106
|
pointer,
|
|
106
107
|
before: operation === "removed" ? value : null,
|
|
107
108
|
after: operation === "added" ? value : null,
|
|
108
|
-
[sourceSide]: mappedAt(
|
|
109
|
+
[sourceSide]: mappedAt(snapshot, entry.unitIndex, `${pointer}/${index}`),
|
|
109
110
|
});
|
|
110
111
|
});
|
|
111
112
|
}
|
|
112
113
|
}
|
|
113
114
|
|
|
114
|
-
function compareRelations(changes,
|
|
115
|
+
function compareRelations(changes, beforeSnapshot, afterSnapshot, beforeEntry, afterEntry) {
|
|
115
116
|
const beforeRelations = beforeEntry.unit.relations;
|
|
116
117
|
const afterRelations = afterEntry.unit.relations;
|
|
117
118
|
const beforeSet = new Set(beforeRelations.map((edge) => `${edge.type}\0${edge.target}`));
|
|
118
119
|
const afterSet = new Set(afterRelations.map((edge) => `${edge.type}\0${edge.target}`));
|
|
119
|
-
for (const [operation, edges, otherSet,
|
|
120
|
-
["removed", beforeRelations, afterSet,
|
|
121
|
-
["added", afterRelations, beforeSet,
|
|
120
|
+
for (const [operation, edges, otherSet, snapshot, entry, sourceSide] of [
|
|
121
|
+
["removed", beforeRelations, afterSet, beforeSnapshot, beforeEntry, "beforeSource"],
|
|
122
|
+
["added", afterRelations, beforeSet, afterSnapshot, afterEntry, "afterSource"],
|
|
122
123
|
]) {
|
|
123
124
|
edges.forEach((edge, index) => {
|
|
124
125
|
if (otherSet.has(`${edge.type}\0${edge.target}`)) return;
|
|
@@ -128,23 +129,23 @@ function compareRelations(changes, beforeEntry, afterEntry, beforeBase, afterBas
|
|
|
128
129
|
pointer: "/relations",
|
|
129
130
|
before: operation === "removed" ? edge : null,
|
|
130
131
|
after: operation === "added" ? edge : null,
|
|
131
|
-
[sourceSide]: mappedAt(
|
|
132
|
+
[sourceSide]: mappedAt(snapshot, entry.unitIndex, `/relations/${index}`),
|
|
132
133
|
});
|
|
133
134
|
});
|
|
134
135
|
}
|
|
135
136
|
}
|
|
136
137
|
|
|
137
|
-
function sideMappedAt(
|
|
138
|
-
const mapped = mappedAt(
|
|
138
|
+
function sideMappedAt(snapshot, unitIndex, pointer, side) {
|
|
139
|
+
const mapped = mappedAt(snapshot, unitIndex, pointer);
|
|
139
140
|
return { ...mapped, file: path.posix.join(side, mapped.file) };
|
|
140
141
|
}
|
|
141
142
|
|
|
142
|
-
function transitionDiagnostics(before, after
|
|
143
|
+
function transitionDiagnostics(before, after) {
|
|
143
144
|
const diagnostics = [];
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
if (
|
|
147
|
-
const mapped = sideMappedAt(before,
|
|
145
|
+
for (const entry of before.byId.values()) {
|
|
146
|
+
const { unit, unitIndex } = entry;
|
|
147
|
+
if (after.byId.has(unit.id)) continue;
|
|
148
|
+
const mapped = sideMappedAt(before, unitIndex, "/id", "before");
|
|
148
149
|
diagnostics.push(makeDiagnostic({
|
|
149
150
|
code: "AUTH_DIFF_TRANSITION_INVALID",
|
|
150
151
|
file: mapped.file,
|
|
@@ -155,12 +156,12 @@ function transitionDiagnostics(before, after, beforeBase, afterBase) {
|
|
|
155
156
|
? "retain the removed tombstone; permanent reserved-ID storage is not admitted"
|
|
156
157
|
: "replace the active unit with a valid removed tombstone carrying an explicit reason",
|
|
157
158
|
}));
|
|
158
|
-
}
|
|
159
|
-
const
|
|
160
|
-
|
|
161
|
-
const previous =
|
|
162
|
-
if (!previous)
|
|
163
|
-
const mapped = sideMappedAt(after,
|
|
159
|
+
}
|
|
160
|
+
for (const entry of after.byId.values()) {
|
|
161
|
+
const { unit, unitIndex } = entry;
|
|
162
|
+
const previous = before.byId.get(unit.id)?.unit;
|
|
163
|
+
if (!previous) continue;
|
|
164
|
+
const mapped = sideMappedAt(after, unitIndex, "/id", "after");
|
|
164
165
|
if (previous.lifecycle === "removed" && unit.lifecycle !== "removed") diagnostics.push(makeDiagnostic({
|
|
165
166
|
code: "AUTH_DIFF_TRANSITION_INVALID",
|
|
166
167
|
file: mapped.file,
|
|
@@ -177,18 +178,16 @@ function transitionDiagnostics(before, after, beforeBase, afterBase) {
|
|
|
177
178
|
reason: `authority identity cannot change kind from ${previous.kind} to ${unit.kind}: ${unit.id}`,
|
|
178
179
|
repair: "retain the original identity and declare a distinct ID for the new kind",
|
|
179
180
|
}));
|
|
180
|
-
}
|
|
181
|
+
}
|
|
181
182
|
return sortDiagnostics(diagnostics);
|
|
182
183
|
}
|
|
183
184
|
|
|
184
|
-
function compareUnits(before, after
|
|
185
|
+
function compareUnits(before, after) {
|
|
185
186
|
const changes = [];
|
|
186
|
-
const
|
|
187
|
-
const afterById = new Map(after.ir.units.map((unit, index) => [unit.id, { unit, index, compiled: after }]));
|
|
188
|
-
const ids = [...new Set([...beforeById.keys(), ...afterById.keys()])].sort(compareText);
|
|
187
|
+
const ids = [...new Set([...before.byId.keys(), ...after.byId.keys()])].sort(compareText);
|
|
189
188
|
for (const id of ids) {
|
|
190
|
-
const left =
|
|
191
|
-
const right =
|
|
189
|
+
const left = before.byId.get(id);
|
|
190
|
+
const right = after.byId.get(id);
|
|
192
191
|
if (!left) {
|
|
193
192
|
addChange(changes, {
|
|
194
193
|
unitId: id,
|
|
@@ -196,16 +195,16 @@ function compareUnits(before, after, beforeBase, afterBase) {
|
|
|
196
195
|
pointer: "",
|
|
197
196
|
before: null,
|
|
198
197
|
after: right.unit,
|
|
199
|
-
afterSource: mappedAt(after, right.
|
|
198
|
+
afterSource: mappedAt(after, right.unitIndex, "/id"),
|
|
200
199
|
});
|
|
201
200
|
continue;
|
|
202
201
|
}
|
|
203
202
|
if (!right) continue;
|
|
204
203
|
for (const pointer of ["/kind", "/owner", "/lifecycle", "/metadata/title", "/metadata/reason", "/semantic/meaning", "/semantic/modality", "/semantic/statement", "/semantic/condition", "/semantic/failure"]) {
|
|
205
|
-
compareScalar(changes,
|
|
204
|
+
compareScalar(changes, before, after, left, right, pointer);
|
|
206
205
|
}
|
|
207
|
-
compareValueSet(changes, left, right, "/semantic/scope"
|
|
208
|
-
compareRelations(changes,
|
|
206
|
+
compareValueSet(changes, before, after, left, right, "/semantic/scope");
|
|
207
|
+
compareRelations(changes, before, after, left, right);
|
|
209
208
|
}
|
|
210
209
|
return changes.sort((left, right) => (
|
|
211
210
|
compareText(left.unitId, right.unitId)
|
|
@@ -231,7 +230,7 @@ function budgetDiagnostic(requiredBytes, maxBytes) {
|
|
|
231
230
|
});
|
|
232
231
|
}
|
|
233
232
|
|
|
234
|
-
export async function
|
|
233
|
+
export async function diffAuthorityPathsWithSnapshots(beforePath, afterPath, { maxBytes = null } = {}) {
|
|
235
234
|
const [before, after, beforeBase, afterBase] = await Promise.all([
|
|
236
235
|
compileAuthorityPath(beforePath),
|
|
237
236
|
compileAuthorityPath(afterPath),
|
|
@@ -239,24 +238,46 @@ export async function diffAuthorityPaths(beforePath, afterPath, { maxBytes = nul
|
|
|
239
238
|
sourceRoot(afterPath),
|
|
240
239
|
]);
|
|
241
240
|
if (!before.ok || !after.ok) return {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
241
|
+
beforeSnapshot: null,
|
|
242
|
+
afterSnapshot: null,
|
|
243
|
+
result: {
|
|
244
|
+
ok: false,
|
|
245
|
+
diagnostics: sortDiagnostics([
|
|
246
|
+
...sideDiagnostics(before.diagnostics, beforeBase, "before"),
|
|
247
|
+
...sideDiagnostics(after.diagnostics, afterBase, "after"),
|
|
248
|
+
]),
|
|
249
|
+
fileCount: before.fileCount + after.fileCount,
|
|
250
|
+
unitCount: 0,
|
|
251
|
+
diff: null,
|
|
252
|
+
partial: false,
|
|
253
|
+
},
|
|
254
|
+
};
|
|
255
|
+
const beforeSnapshot = createCompiledAuthoritySnapshot(before, beforeBase);
|
|
256
|
+
const afterSnapshot = createCompiledAuthoritySnapshot(after, afterBase);
|
|
257
|
+
return {
|
|
258
|
+
beforeSnapshot,
|
|
259
|
+
afterSnapshot,
|
|
260
|
+
result: diffAuthoritySnapshots(beforeSnapshot, afterSnapshot, { maxBytes }),
|
|
250
261
|
};
|
|
251
|
-
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
export async function diffAuthorityPaths(beforePath, afterPath, options = {}) {
|
|
265
|
+
return (await diffAuthorityPathsWithSnapshots(beforePath, afterPath, options)).result;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export function diffAuthoritySnapshots(beforeSnapshot, afterSnapshot, { maxBytes = null } = {}) {
|
|
269
|
+
const before = beforeSnapshot.compiled;
|
|
270
|
+
const after = afterSnapshot.compiled;
|
|
271
|
+
const invalidTransitions = transitionDiagnostics(beforeSnapshot, afterSnapshot);
|
|
252
272
|
if (invalidTransitions.length > 0) return {
|
|
253
273
|
ok: false,
|
|
254
274
|
diagnostics: invalidTransitions,
|
|
255
275
|
fileCount: before.fileCount + after.fileCount,
|
|
256
276
|
unitCount: 0,
|
|
257
277
|
diff: null,
|
|
278
|
+
partial: false,
|
|
258
279
|
};
|
|
259
|
-
const changes = compareUnits(
|
|
280
|
+
const changes = compareUnits(beforeSnapshot, afterSnapshot);
|
|
260
281
|
const diff = {
|
|
261
282
|
format: DIFF_FORMAT,
|
|
262
283
|
changes,
|
|
@@ -273,15 +294,17 @@ export async function diffAuthorityPaths(beforePath, afterPath, { maxBytes = nul
|
|
|
273
294
|
unitCount: 0,
|
|
274
295
|
payloadBytes,
|
|
275
296
|
diff: null,
|
|
297
|
+
partial: false,
|
|
276
298
|
};
|
|
277
299
|
return {
|
|
278
300
|
ok: true,
|
|
279
301
|
diagnostics: [],
|
|
280
302
|
fileCount: before.fileCount + after.fileCount,
|
|
281
|
-
unitCount: new Set([...
|
|
303
|
+
unitCount: new Set([...beforeSnapshot.byId.keys(), ...afterSnapshot.byId.keys()]).size,
|
|
282
304
|
payloadBytes,
|
|
283
305
|
diff,
|
|
284
306
|
before,
|
|
285
307
|
after,
|
|
308
|
+
partial: false,
|
|
286
309
|
};
|
|
287
310
|
}
|
|
@@ -3,7 +3,7 @@ import path from "node:path";
|
|
|
3
3
|
|
|
4
4
|
import { compareText, createLocator, makeDiagnostic, portablePath, REPAIRS, sortDiagnostics } from "./diagnostics.mjs";
|
|
5
5
|
import { parseMarkdownAuthority, stringifyCanonicalMarkdown } from "./source-markdown.mjs";
|
|
6
|
-
import {
|
|
6
|
+
import { loadAuthorityContract, parseYamlAuthority, stringifyCanonicalYaml } from "./source-yaml.mjs";
|
|
7
7
|
import { validateFormatStructure } from "./validate.mjs";
|
|
8
8
|
|
|
9
9
|
export class AuthorityInputError extends Error {
|
|
@@ -107,35 +107,7 @@ export async function parseAuthorityPath(inputPath, options = {}) {
|
|
|
107
107
|
return { contract, files, documents, sources };
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
-
function
|
|
111
|
-
return values.length > 0 && values.every((value) => value === values[0]) ? values[0] : null;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
function upgradedYamlData(document, contract) {
|
|
115
|
-
const units = document.units.map((source) => structuredClone(source.data));
|
|
116
|
-
const identifier = new RegExp(contract.identifier_pattern);
|
|
117
|
-
const uniformOwner = uniformValue(units.map((unit) => unit.owner));
|
|
118
|
-
const activeRules = units.filter((unit) => unit.kind === "rule" && unit.lifecycle === "active");
|
|
119
|
-
const uniformScope = uniformValue(activeRules.map((unit) => (
|
|
120
|
-
Array.isArray(unit.scope) && unit.scope.length === 1 ? unit.scope[0] : null
|
|
121
|
-
)));
|
|
122
|
-
return {
|
|
123
|
-
format: AUTHORITY_FORMAT_V2,
|
|
124
|
-
...((typeof uniformOwner === "string" && identifier.test(uniformOwner))
|
|
125
|
-
? { owner: uniformOwner }
|
|
126
|
-
: document.data.format === AUTHORITY_FORMAT_V2 && Object.hasOwn(document.data, "owner") ? { owner: document.data.owner } : {}),
|
|
127
|
-
...((typeof uniformScope === "string" && identifier.test(uniformScope))
|
|
128
|
-
? { scope: uniformScope }
|
|
129
|
-
: document.data.format === AUTHORITY_FORMAT_V2 && Object.hasOwn(document.data, "scope") ? { scope: document.data.scope } : {}),
|
|
130
|
-
units,
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
export function canonicalText(document, options = {}) {
|
|
135
|
-
if (options.upgrade) {
|
|
136
|
-
if (document.profile !== "yaml") throw new AuthorityInputError("authority fmt --upgrade requires one YAML authority container");
|
|
137
|
-
return stringifyCanonicalYaml(upgradedYamlData(document, options.contract), { container: true });
|
|
138
|
-
}
|
|
110
|
+
export function canonicalText(document) {
|
|
139
111
|
return document.profile === "yaml"
|
|
140
112
|
? stringifyCanonicalYaml(document.data, { container: true })
|
|
141
113
|
: stringifyCanonicalMarkdown(document.data);
|
|
@@ -178,7 +150,7 @@ export async function formatAuthorityFile(inputPath, options = {}) {
|
|
|
178
150
|
const document = documents[0];
|
|
179
151
|
const diagnostics = validateFormatStructure(document, contract);
|
|
180
152
|
if (diagnostics.length > 0) return { ok: false, changed: false, diagnostics, fileCount: 1 };
|
|
181
|
-
const canonical = canonicalText(document
|
|
153
|
+
const canonical = canonicalText(document);
|
|
182
154
|
const changed = canonical !== document.sourceText;
|
|
183
155
|
if (options.check && changed) return {
|
|
184
156
|
ok: false,
|
|
@@ -187,7 +159,7 @@ export async function formatAuthorityFile(inputPath, options = {}) {
|
|
|
187
159
|
code: "AUTH_FORMAT_DRIFT",
|
|
188
160
|
file: document.file,
|
|
189
161
|
range: document.locations.get("") ?? document.locator.range(0, document.sourceText.length),
|
|
190
|
-
reason:
|
|
162
|
+
reason: "authority source is not byte-canonical",
|
|
191
163
|
repair: REPAIRS.format,
|
|
192
164
|
})],
|
|
193
165
|
fileCount: 1,
|