@am_shork/attest 0.1.5 → 0.1.7
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 +246 -1
- package/README.md +56 -1
- package/dist/cli/index.js +81 -4
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/json.d.ts +8 -1
- package/dist/cli/json.d.ts.map +1 -1
- package/dist/cli/json.js +8 -0
- package/dist/cli/json.js.map +1 -1
- package/dist/core/apply.d.ts.map +1 -1
- package/dist/core/apply.js +7 -1
- package/dist/core/apply.js.map +1 -1
- package/dist/core/gate.d.ts +9 -0
- package/dist/core/gate.d.ts.map +1 -1
- package/dist/core/gate.js +25 -12
- package/dist/core/gate.js.map +1 -1
- package/dist/core/loader.d.ts.map +1 -1
- package/dist/core/loader.js +16 -1
- package/dist/core/loader.js.map +1 -1
- package/dist/core/locate.d.ts +29 -2
- package/dist/core/locate.d.ts.map +1 -1
- package/dist/core/locate.js +71 -28
- package/dist/core/locate.js.map +1 -1
- package/dist/core/order.d.ts +3 -0
- package/dist/core/order.d.ts.map +1 -0
- package/dist/core/order.js +13 -0
- package/dist/core/order.js.map +1 -0
- package/dist/core/pipeline.d.ts +33 -0
- package/dist/core/pipeline.d.ts.map +1 -1
- package/dist/core/pipeline.js +103 -24
- package/dist/core/pipeline.js.map +1 -1
- package/dist/core/render.d.ts +39 -0
- package/dist/core/render.d.ts.map +1 -0
- package/dist/core/render.js +168 -0
- package/dist/core/render.js.map +1 -0
- package/dist/core/validator.d.ts.map +1 -1
- package/dist/core/validator.js +16 -4
- package/dist/core/validator.js.map +1 -1
- package/package.json +4 -2
package/dist/core/gate.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../../src/core/gate.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEzE,MAAM,WAAW,UAAU;IACzB,yEAAyE;IACzE,QAAQ,EAAE,QAAQ,CAAC;IACnB,8CAA8C;IAC9C,IAAI,EAAE,UAAU,CAAC;IACjB,oDAAoD;IACpD,GAAG,EAAE,SAAS,CAAC;CAChB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,UAAU,GAAG,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../../src/core/gate.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEzE,MAAM,WAAW,UAAU;IACzB,yEAAyE;IACzE,QAAQ,EAAE,QAAQ,CAAC;IACnB,8CAA8C;IAC9C,IAAI,EAAE,UAAU,CAAC;IACjB,oDAAoD;IACpD,GAAG,EAAE,SAAS,CAAC;CAChB;AAED;;;;;;;;;;GAUG;AACH;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,SAAS,GAAG,KAAK,EAAE,CAe9E;AAED,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,UAAU,GAAG,KAAK,EAAE,CAqBzE"}
|
package/dist/core/gate.js
CHANGED
|
@@ -15,6 +15,30 @@ import { validateStructure } from './validator.js';
|
|
|
15
15
|
* 3. Static coverage vs runtime coverage: every declared scenario actually
|
|
16
16
|
* ran (catches skip/only false coverage).
|
|
17
17
|
*/
|
|
18
|
+
/**
|
|
19
|
+
* Declared-not-run: a scenario the static plan claims attests a requirement,
|
|
20
|
+
* which the runtime never executed (skipped, or excluded by an `.only`).
|
|
21
|
+
*
|
|
22
|
+
* Exported because `verify` and `archive` both make this call. While each owned
|
|
23
|
+
* a copy, the two verdicts agreed only by transcription — and the whole point of
|
|
24
|
+
* this framework is that agreement should be structural, not clerical.
|
|
25
|
+
*/
|
|
26
|
+
export function declaredNotRunIssues(plan, run) {
|
|
27
|
+
const issues = [];
|
|
28
|
+
for (const s of plan.scenarios) {
|
|
29
|
+
if (!run.runtimeCoverage.get(s.reqId)?.has(s.name)) {
|
|
30
|
+
issues.push({
|
|
31
|
+
level: 'ERROR',
|
|
32
|
+
code: 'declared-not-run',
|
|
33
|
+
reqId: s.reqId,
|
|
34
|
+
file: s.file,
|
|
35
|
+
line: s.line,
|
|
36
|
+
message: `scenario "${s.name}" statically declares it attests ${s.reqId}, but never executed (skipped, or excluded by an .only?).`,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return issues;
|
|
41
|
+
}
|
|
18
42
|
export function evaluateGate({ registry, plan, run }) {
|
|
19
43
|
const blocking = [];
|
|
20
44
|
// 1) Structure (end-state re-validation).
|
|
@@ -28,18 +52,7 @@ export function evaluateGate({ registry, plan, run }) {
|
|
|
28
52
|
});
|
|
29
53
|
}
|
|
30
54
|
// 3) Declared-not-run: static coverage claimed, runtime never executed it.
|
|
31
|
-
|
|
32
|
-
if (!run.runtimeCoverage.get(s.reqId)?.has(s.name)) {
|
|
33
|
-
blocking.push({
|
|
34
|
-
level: 'ERROR',
|
|
35
|
-
code: 'declared-not-run',
|
|
36
|
-
reqId: s.reqId,
|
|
37
|
-
file: s.file,
|
|
38
|
-
line: s.line,
|
|
39
|
-
message: `scenario "${s.name}" statically declares it attests ${s.reqId}, but never executed (skipped, or excluded by an .only?).`,
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
}
|
|
55
|
+
blocking.push(...declaredNotRunIssues(plan, run));
|
|
43
56
|
return blocking;
|
|
44
57
|
}
|
|
45
58
|
//# sourceMappingURL=gate.js.map
|
package/dist/core/gate.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gate.js","sourceRoot":"","sources":["../../src/core/gate.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,iFAAiF;AACjF,4EAA4E;AAC5E,6EAA6E;AAC7E,wDAAwD;AAExD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAYnD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"gate.js","sourceRoot":"","sources":["../../src/core/gate.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,iFAAiF;AACjF,4EAA4E;AAC5E,6EAA6E;AAC7E,wDAAwD;AAExD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAYnD;;;;;;;;;;GAUG;AACH;;;;;;;GAOG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAgB,EAAE,GAAc;IACnE,MAAM,MAAM,GAAY,EAAE,CAAC;IAC3B,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QAC/B,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;YACnD,MAAM,CAAC,IAAI,CAAC;gBACV,KAAK,EAAE,OAAO;gBACd,IAAI,EAAE,kBAAkB;gBACxB,KAAK,EAAE,CAAC,CAAC,KAAK;gBACd,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,OAAO,EAAE,aAAa,CAAC,CAAC,IAAI,oCAAoC,CAAC,CAAC,KAAK,2DAA2D;aACnI,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAc;IAC9D,MAAM,QAAQ,GAAY,EAAE,CAAC;IAE7B,0CAA0C;IAC1C,QAAQ,CAAC,IAAI,CACX,GAAG,iBAAiB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,OAAO,CAAC,CACxE,CAAC;IAEF,4BAA4B;IAC5B,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;QAChB,QAAQ,CAAC,IAAI,CAAC;YACZ,KAAK,EAAE,OAAO;YACd,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,wDAAwD;SAClE,CAAC,CAAC;IACL,CAAC;IAED,2EAA2E;IAC3E,QAAQ,CAAC,IAAI,CAAC,GAAG,oBAAoB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;IAElD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/core/loader.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/core/loader.ts"],"names":[],"mappings":"AAqBA,MAAM,WAAW,MAAM;IACrB,IAAI,CAAC,CAAC,GAAG,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAC/C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,wBAAsB,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC,CAmCpD"}
|
package/dist/core/loader.js
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
// throws. The stub sidesteps that without affecting any read value.
|
|
9
9
|
import { createServer } from 'vite';
|
|
10
10
|
import { mkdtempSync, writeFileSync } from 'node:fs';
|
|
11
|
+
import { rm } from 'node:fs/promises';
|
|
11
12
|
import { tmpdir } from 'node:os';
|
|
12
13
|
import { join } from 'node:path';
|
|
13
14
|
const VITEST_STUB = 'export const describe=()=>{};export const it=()=>{};export const test=()=>{};' +
|
|
@@ -27,12 +28,26 @@ export async function createLoader() {
|
|
|
27
28
|
ssr: { noExternal: ['vitest'] },
|
|
28
29
|
optimizeDeps: { noDiscovery: true },
|
|
29
30
|
});
|
|
31
|
+
let closed = false;
|
|
30
32
|
return {
|
|
31
33
|
async load(absPath) {
|
|
32
34
|
return (await server.ssrLoadModule(absPath));
|
|
33
35
|
},
|
|
36
|
+
// The scratch directory is the loader's, so the loader disposes of it.
|
|
37
|
+
// Leaving it behind meant one stray directory per `attest` invocation —
|
|
38
|
+
// i.e. per CI build — accumulating in the OS temp dir forever. `close` is
|
|
39
|
+
// idempotent because every pipeline calls it from a `finally`, which can
|
|
40
|
+
// run after an earlier explicit close on some paths.
|
|
34
41
|
async close() {
|
|
35
|
-
|
|
42
|
+
if (closed)
|
|
43
|
+
return;
|
|
44
|
+
closed = true;
|
|
45
|
+
try {
|
|
46
|
+
await server.close();
|
|
47
|
+
}
|
|
48
|
+
finally {
|
|
49
|
+
await rm(dir, { recursive: true, force: true });
|
|
50
|
+
}
|
|
36
51
|
},
|
|
37
52
|
};
|
|
38
53
|
}
|
package/dist/core/loader.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/core/loader.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,2EAA2E;AAC3E,6EAA6E;AAC7E,EAAE;AACF,sEAAsE;AACtE,yEAAyE;AACzE,6EAA6E;AAC7E,oEAAoE;AAEpE,OAAO,EAAE,YAAY,EAAsB,MAAM,MAAM,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,WAAW,GACf,+EAA+E;IAC/E,wFAAwF;IACxF,kFAAkF;IAClF,oBAAoB,CAAC;AAOvB,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC;IAC1D,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,iBAAiB,CAAC,CAAC;IAC1C,aAAa,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IAEjC,MAAM,MAAM,GAAkB,MAAM,YAAY,CAAC;QAC/C,UAAU,EAAE,KAAK;QACjB,QAAQ,EAAE,OAAO;QACjB,OAAO,EAAE,QAAQ;QACjB,MAAM,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE;QAChC,OAAO,EAAE,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE;QACpC,GAAG,EAAE,EAAE,UAAU,EAAE,CAAC,QAAQ,CAAC,EAAE;QAC/B,YAAY,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE;KACpC,CAAC,CAAC;IAEH,OAAO;QACL,KAAK,CAAC,IAAI,CAAI,OAAe;YAC3B,OAAO,CAAC,MAAM,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,CAAM,CAAC;QACpD,CAAC;QACD,KAAK,CAAC,KAAK;YACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/core/loader.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,2EAA2E;AAC3E,6EAA6E;AAC7E,EAAE;AACF,sEAAsE;AACtE,yEAAyE;AACzE,6EAA6E;AAC7E,oEAAoE;AAEpE,OAAO,EAAE,YAAY,EAAsB,MAAM,MAAM,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,WAAW,GACf,+EAA+E;IAC/E,wFAAwF;IACxF,kFAAkF;IAClF,oBAAoB,CAAC;AAOvB,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC;IAC1D,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,iBAAiB,CAAC,CAAC;IAC1C,aAAa,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IAEjC,MAAM,MAAM,GAAkB,MAAM,YAAY,CAAC;QAC/C,UAAU,EAAE,KAAK;QACjB,QAAQ,EAAE,OAAO;QACjB,OAAO,EAAE,QAAQ;QACjB,MAAM,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE;QAChC,OAAO,EAAE,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE;QACpC,GAAG,EAAE,EAAE,UAAU,EAAE,CAAC,QAAQ,CAAC,EAAE;QAC/B,YAAY,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE;KACpC,CAAC,CAAC;IAEH,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,OAAO;QACL,KAAK,CAAC,IAAI,CAAI,OAAe;YAC3B,OAAO,CAAC,MAAM,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,CAAM,CAAC;QACpD,CAAC;QACD,uEAAuE;QACvE,wEAAwE;QACxE,0EAA0E;QAC1E,yEAAyE;QACzE,qDAAqD;QACrD,KAAK,CAAC,KAAK;YACT,IAAI,MAAM;gBAAE,OAAO;YACnB,MAAM,GAAG,IAAI,CAAC;YACd,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;YACvB,CAAC;oBAAS,CAAC;gBACT,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YAClD,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/dist/core/locate.d.ts
CHANGED
|
@@ -2,17 +2,44 @@ import type { Loader } from './loader.js';
|
|
|
2
2
|
import type { AttestPlan, Issue, Registry } from './types.js';
|
|
3
3
|
export declare const isReqsFile: (name: string) => boolean;
|
|
4
4
|
export declare const isSpecFile: (name: string) => boolean;
|
|
5
|
-
/**
|
|
5
|
+
/**
|
|
6
|
+
* Recursively find files under root whose basename matches `match`.
|
|
7
|
+
*
|
|
8
|
+
* Sibling directories are walked concurrently — the tree is I/O bound, and a
|
|
9
|
+
* serial `for await` spent one filesystem round-trip per directory, which is
|
|
10
|
+
* the dominant cost of `check` on a large repo. The result is sorted, so the
|
|
11
|
+
* order never depends on which `readdir` happened to resolve first.
|
|
12
|
+
*/
|
|
6
13
|
export declare function findFiles(root: string, match: (name: string) => boolean): Promise<string[]>;
|
|
14
|
+
/** The two file sets every command needs, collected in one pass. */
|
|
15
|
+
export interface ProjectScan {
|
|
16
|
+
reqsFiles: string[];
|
|
17
|
+
specFiles: string[];
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Find the registry and spec files under root in a **single** traversal.
|
|
21
|
+
*
|
|
22
|
+
* Calling findFiles once per pattern meant `check` walked the tree twice and
|
|
23
|
+
* `archive` four times, over a tree that cannot change in between.
|
|
24
|
+
*/
|
|
25
|
+
export declare function scanProject(root: string): Promise<ProjectScan>;
|
|
7
26
|
/**
|
|
8
27
|
* Load and merge every `*.reqs.ts` registry under root. A malformed registry
|
|
9
28
|
* (defineRequirements throws) becomes a registry-invalid ERROR; a duplicate id
|
|
10
29
|
* across files becomes a duplicate-requirement ERROR.
|
|
30
|
+
*
|
|
31
|
+
* Pass `files` to reuse a {@link scanProject} result instead of re-walking.
|
|
11
32
|
*/
|
|
12
|
-
export declare function loadRegistry(root: string, loader: Loader): Promise<{
|
|
33
|
+
export declare function loadRegistry(root: string, loader: Loader, files?: string[]): Promise<{
|
|
13
34
|
registry: Registry;
|
|
14
35
|
issues: Issue[];
|
|
15
36
|
}>;
|
|
37
|
+
/**
|
|
38
|
+
* Parse the given spec files into one merged plan (paths shown relative to
|
|
39
|
+
* `displayRoot`). Files are read concurrently; the merge follows the input
|
|
40
|
+
* order, so the plan never depends on I/O timing.
|
|
41
|
+
*/
|
|
42
|
+
export declare function parseSpecs(files: string[], displayRoot: string): Promise<AttestPlan>;
|
|
16
43
|
/** Parse every `*.spec.ts` under root into one merged plan (file paths shown relative to root). */
|
|
17
44
|
export declare function parseAllSpecFiles(root: string): Promise<AttestPlan>;
|
|
18
45
|
/** Parse the spec files belonging to a single proposed change (design §8). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"locate.d.ts","sourceRoot":"","sources":["../../src/core/locate.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"locate.d.ts","sourceRoot":"","sources":["../../src/core/locate.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAe,MAAM,YAAY,CAAC;AAc3E,eAAO,MAAM,UAAU,GAAI,MAAM,MAAM,KAAG,OAAoC,CAAC;AAC/E,eAAO,MAAM,UAAU,GAAI,MAAM,MAAM,KAAG,OAAoC,CAAC;AAE/E;;;;;;;GAOG;AACH,wBAAsB,SAAS,CAC7B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,GAC/B,OAAO,CAAC,MAAM,EAAE,CAAC,CAiBnB;AAED,oEAAoE;AACpE,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CASpE;AAED;;;;;;GAMG;AACH,wBAAsB,YAAY,CAChC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,MAAM,EAAE,GACf,OAAO,CAAC;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,KAAK,EAAE,CAAA;CAAE,CAAC,CAyDlD;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAC9B,KAAK,EAAE,MAAM,EAAE,EACf,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,UAAU,CAAC,CASrB;AAED,mGAAmG;AACnG,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAEzE;AAED,8EAA8E;AAC9E,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,UAAU,CAAC,CAGrB;AAED,+DAA+D;AAC/D,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAOrE"}
|
package/dist/core/locate.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
// Locate layer (design §4, L1): find registry + spec files, load the registry
|
|
2
2
|
// via the TS loader, and parse all spec files into one merged AttestPlan.
|
|
3
3
|
import { readdir, readFile } from 'node:fs/promises';
|
|
4
|
-
import { join, relative } from 'node:path';
|
|
4
|
+
import { basename, join, relative } from 'node:path';
|
|
5
5
|
import { parseSpecFile } from './parser.js';
|
|
6
|
+
import { byCodeUnit } from './order.js';
|
|
6
7
|
// Proposed changes and archived changes are excluded from normal scanning:
|
|
7
8
|
// a change's requirements/specs only count once its gate passes and it is
|
|
8
9
|
// merged (design §7, §8). `attest archive <name>` includes them explicitly.
|
|
@@ -16,41 +17,78 @@ const SKIP_DIRS = new Set([
|
|
|
16
17
|
]);
|
|
17
18
|
export const isReqsFile = (name) => name.endsWith('.reqs.ts');
|
|
18
19
|
export const isSpecFile = (name) => name.endsWith('.spec.ts');
|
|
19
|
-
/**
|
|
20
|
+
/**
|
|
21
|
+
* Recursively find files under root whose basename matches `match`.
|
|
22
|
+
*
|
|
23
|
+
* Sibling directories are walked concurrently — the tree is I/O bound, and a
|
|
24
|
+
* serial `for await` spent one filesystem round-trip per directory, which is
|
|
25
|
+
* the dominant cost of `check` on a large repo. The result is sorted, so the
|
|
26
|
+
* order never depends on which `readdir` happened to resolve first.
|
|
27
|
+
*/
|
|
20
28
|
export async function findFiles(root, match) {
|
|
21
29
|
const out = [];
|
|
22
30
|
const walk = async (dir) => {
|
|
23
31
|
const entries = await readdir(dir, { withFileTypes: true });
|
|
32
|
+
const subdirs = [];
|
|
24
33
|
for (const e of entries) {
|
|
25
34
|
const full = join(dir, e.name);
|
|
26
35
|
if (e.isDirectory()) {
|
|
27
36
|
if (!SKIP_DIRS.has(e.name))
|
|
28
|
-
|
|
37
|
+
subdirs.push(full);
|
|
29
38
|
}
|
|
30
39
|
else if (e.isFile() && match(e.name)) {
|
|
31
40
|
out.push(full);
|
|
32
41
|
}
|
|
33
42
|
}
|
|
43
|
+
await Promise.all(subdirs.map(walk));
|
|
34
44
|
};
|
|
35
45
|
await walk(root);
|
|
36
|
-
return out.sort();
|
|
46
|
+
return out.sort(byCodeUnit);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Find the registry and spec files under root in a **single** traversal.
|
|
50
|
+
*
|
|
51
|
+
* Calling findFiles once per pattern meant `check` walked the tree twice and
|
|
52
|
+
* `archive` four times, over a tree that cannot change in between.
|
|
53
|
+
*/
|
|
54
|
+
export async function scanProject(root) {
|
|
55
|
+
const files = await findFiles(root, (n) => isReqsFile(n) || isSpecFile(n));
|
|
56
|
+
const reqsFiles = [];
|
|
57
|
+
const specFiles = [];
|
|
58
|
+
for (const f of files) {
|
|
59
|
+
if (isReqsFile(basename(f)))
|
|
60
|
+
reqsFiles.push(f);
|
|
61
|
+
else
|
|
62
|
+
specFiles.push(f);
|
|
63
|
+
}
|
|
64
|
+
return { reqsFiles, specFiles };
|
|
37
65
|
}
|
|
38
66
|
/**
|
|
39
67
|
* Load and merge every `*.reqs.ts` registry under root. A malformed registry
|
|
40
68
|
* (defineRequirements throws) becomes a registry-invalid ERROR; a duplicate id
|
|
41
69
|
* across files becomes a duplicate-requirement ERROR.
|
|
70
|
+
*
|
|
71
|
+
* Pass `files` to reuse a {@link scanProject} result instead of re-walking.
|
|
42
72
|
*/
|
|
43
|
-
export async function loadRegistry(root, loader) {
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
let mod;
|
|
73
|
+
export async function loadRegistry(root, loader, files) {
|
|
74
|
+
const paths = files ?? (await scanProject(root)).reqsFiles;
|
|
75
|
+
// Evaluate the modules concurrently, then fold the results in sorted file
|
|
76
|
+
// order: the issue list stays deterministic regardless of which module
|
|
77
|
+
// finished first.
|
|
78
|
+
const loaded = await Promise.all(paths.map(async (file) => {
|
|
50
79
|
try {
|
|
51
|
-
mod
|
|
80
|
+
return { file, mod: await loader.load(file) };
|
|
52
81
|
}
|
|
53
82
|
catch (err) {
|
|
83
|
+
return { file, err };
|
|
84
|
+
}
|
|
85
|
+
}));
|
|
86
|
+
const registry = {};
|
|
87
|
+
const issues = [];
|
|
88
|
+
for (const entry of loaded) {
|
|
89
|
+
const display = relative(root, entry.file);
|
|
90
|
+
if ('err' in entry) {
|
|
91
|
+
const { err } = entry;
|
|
54
92
|
issues.push({
|
|
55
93
|
level: 'ERROR',
|
|
56
94
|
code: 'registry-invalid',
|
|
@@ -59,7 +97,7 @@ export async function loadRegistry(root, loader) {
|
|
|
59
97
|
});
|
|
60
98
|
continue;
|
|
61
99
|
}
|
|
62
|
-
const reg = mod.default;
|
|
100
|
+
const reg = entry.mod.default;
|
|
63
101
|
if (!reg || typeof reg !== 'object') {
|
|
64
102
|
issues.push({
|
|
65
103
|
level: 'ERROR',
|
|
@@ -70,7 +108,7 @@ export async function loadRegistry(root, loader) {
|
|
|
70
108
|
continue;
|
|
71
109
|
}
|
|
72
110
|
for (const [id, req] of Object.entries(reg)) {
|
|
73
|
-
if (id
|
|
111
|
+
if (Object.hasOwn(registry, id)) {
|
|
74
112
|
issues.push({
|
|
75
113
|
level: 'ERROR',
|
|
76
114
|
code: 'duplicate-requirement',
|
|
@@ -86,33 +124,38 @@ export async function loadRegistry(root, loader) {
|
|
|
86
124
|
}
|
|
87
125
|
return { registry, issues };
|
|
88
126
|
}
|
|
127
|
+
/**
|
|
128
|
+
* Parse the given spec files into one merged plan (paths shown relative to
|
|
129
|
+
* `displayRoot`). Files are read concurrently; the merge follows the input
|
|
130
|
+
* order, so the plan never depends on I/O timing.
|
|
131
|
+
*/
|
|
132
|
+
export async function parseSpecs(files, displayRoot) {
|
|
133
|
+
const sources = await Promise.all(files.map((file) => readFile(file, 'utf8')));
|
|
134
|
+
const plan = { scenarios: [], paramRefs: [] };
|
|
135
|
+
for (const [i, file] of files.entries()) {
|
|
136
|
+
const parsed = parseSpecFile(relative(displayRoot, file), sources[i]);
|
|
137
|
+
plan.scenarios.push(...parsed.scenarios);
|
|
138
|
+
plan.paramRefs.push(...parsed.paramRefs);
|
|
139
|
+
}
|
|
140
|
+
return plan;
|
|
141
|
+
}
|
|
89
142
|
/** Parse every `*.spec.ts` under root into one merged plan (file paths shown relative to root). */
|
|
90
143
|
export async function parseAllSpecFiles(root) {
|
|
91
|
-
return
|
|
144
|
+
return parseSpecs(await findFiles(root, isSpecFile), root);
|
|
92
145
|
}
|
|
93
146
|
/** Parse the spec files belonging to a single proposed change (design §8). */
|
|
94
147
|
export async function parseChangeSpecs(root, changeName) {
|
|
95
|
-
|
|
148
|
+
const dir = join(root, 'changes', changeName);
|
|
149
|
+
return parseSpecs(await findFiles(dir, isSpecFile), root);
|
|
96
150
|
}
|
|
97
151
|
/** List the names of proposed changes under `root/changes`. */
|
|
98
152
|
export async function listChangeNames(root) {
|
|
99
153
|
try {
|
|
100
154
|
const entries = await readdir(join(root, 'changes'), { withFileTypes: true });
|
|
101
|
-
return entries.filter((e) => e.isDirectory()).map((e) => e.name).sort();
|
|
155
|
+
return entries.filter((e) => e.isDirectory()).map((e) => e.name).sort(byCodeUnit);
|
|
102
156
|
}
|
|
103
157
|
catch {
|
|
104
158
|
return [];
|
|
105
159
|
}
|
|
106
160
|
}
|
|
107
|
-
async function parseSpecsUnder(dir, displayRoot) {
|
|
108
|
-
const files = await findFiles(dir, isSpecFile);
|
|
109
|
-
const plan = { scenarios: [], paramRefs: [] };
|
|
110
|
-
for (const file of files) {
|
|
111
|
-
const source = await readFile(file, 'utf8');
|
|
112
|
-
const parsed = parseSpecFile(relative(displayRoot, file), source);
|
|
113
|
-
plan.scenarios.push(...parsed.scenarios);
|
|
114
|
-
plan.paramRefs.push(...parsed.paramRefs);
|
|
115
|
-
}
|
|
116
|
-
return plan;
|
|
117
|
-
}
|
|
118
161
|
//# sourceMappingURL=locate.js.map
|
package/dist/core/locate.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"locate.js","sourceRoot":"","sources":["../../src/core/locate.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,0EAA0E;AAE1E,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"locate.js","sourceRoot":"","sources":["../../src/core/locate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"order.d.ts","sourceRoot":"","sources":["../../src/core/order.ts"],"names":[],"mappings":"AASA,6EAA6E;AAC7E,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAEvD"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Deterministic ordering primitives.
|
|
2
|
+
//
|
|
3
|
+
// Anything Attest writes to disk or compares for equality has to sort on the
|
|
4
|
+
// strings themselves and nothing else. `localeCompare` does not: it returns 0
|
|
5
|
+
// for *distinct* strings (a precomposed "ä" against its combining-mark
|
|
6
|
+
// spelling), and since `Array#sort` is stable, whatever it calls equal keeps
|
|
7
|
+
// its insertion order — so the result encodes how the input happened to be
|
|
8
|
+
// written. Which strings collate equal is ICU-dependent on top of that.
|
|
9
|
+
/** Compare by UTF-16 code unit — the same order as a bare `Array#sort()`. */
|
|
10
|
+
export function byCodeUnit(a, b) {
|
|
11
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=order.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"order.js","sourceRoot":"","sources":["../../src/core/order.ts"],"names":[],"mappings":"AAAA,qCAAqC;AACrC,EAAE;AACF,6EAA6E;AAC7E,8EAA8E;AAC9E,uEAAuE;AACvE,6EAA6E;AAC7E,2EAA2E;AAC3E,wEAAwE;AAExE,6EAA6E;AAC7E,MAAM,UAAU,UAAU,CAAC,CAAS,EAAE,CAAS;IAC7C,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACpC,CAAC"}
|
package/dist/core/pipeline.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { RenderTarget } from './render.js';
|
|
1
2
|
import type { Issue } from './types.js';
|
|
2
3
|
/** Static structural check (design §9: `attest check`). */
|
|
3
4
|
export declare function runCheck(root: string): Promise<Issue[]>;
|
|
@@ -20,6 +21,38 @@ export interface CoverageRow {
|
|
|
20
21
|
}
|
|
21
22
|
/** Coverage-only report (design §9: `attest cover`). */
|
|
22
23
|
export declare function runCover(root: string): Promise<CoverageRow[]>;
|
|
24
|
+
export interface RenderResult {
|
|
25
|
+
/** The rendered document; empty string when `issues` contains an ERROR. */
|
|
26
|
+
markdown: string;
|
|
27
|
+
/** Registry-loading issues — rendering a half-loaded registry would lie. */
|
|
28
|
+
issues: Issue[];
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Markdown projection of the intent layer (design §9: `attest render`).
|
|
32
|
+
*
|
|
33
|
+
* Reads the registry and nothing else — no spec parse, no run — because the
|
|
34
|
+
* document is intent only. That is what keeps it a pure function of the
|
|
35
|
+
* `*.reqs.ts` files, so a committed rendering can be gated without going stale
|
|
36
|
+
* every time a line moves in a test file.
|
|
37
|
+
*/
|
|
38
|
+
export declare function runRender(root: string): Promise<RenderResult>;
|
|
39
|
+
/**
|
|
40
|
+
* Freshness gate for a committed rendering (`attest render --check`).
|
|
41
|
+
*
|
|
42
|
+
* A generated file checked into the repo is itself a drift surface — the exact
|
|
43
|
+
* failure mode Attest exists to remove — so the projection only earns its place
|
|
44
|
+
* alongside a gate that fails when the file no longer matches its source.
|
|
45
|
+
*/
|
|
46
|
+
export declare function runRenderCheck(root: string, outFile: string, target: RenderTarget): Promise<Issue[]>;
|
|
47
|
+
/**
|
|
48
|
+
* The globs that keep *other* proposals out of a change's gate run.
|
|
49
|
+
*
|
|
50
|
+
* Sibling names come from `readdir`, not from the guard above, so they are
|
|
51
|
+
* escaped: a directory called `feat(auth)` pasted in raw is a *pattern*, it
|
|
52
|
+
* matches nothing, and that sibling's specs silently join the run — quietly
|
|
53
|
+
* widening the scope of the one check that decides "done".
|
|
54
|
+
*/
|
|
55
|
+
export declare function changeExcludeGlobs(others: string[]): string[];
|
|
23
56
|
/** Archive gate for a change (design §8, §9: `attest archive <change>`). */
|
|
24
57
|
export declare function runArchive(root: string, changeName: string, options?: RunOptions): Promise<Issue[]>;
|
|
25
58
|
/** True when a spec suite exists at all (used by the CLI to warn on empty roots). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../src/core/pipeline.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../src/core/pipeline.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAMhD,OAAO,KAAK,EAAc,KAAK,EAAY,MAAM,YAAY,CAAC;AAE9D,2DAA2D;AAC3D,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,CAc7D;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB,EAAE,EAAE,OAAO,CAAC;CACb;AAED,oEAAoE;AACpE,MAAM,WAAW,UAAU;IACzB,4EAA4E;IAC5E,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,4DAA4D;AAC5D,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,UAAe,GAAG,OAAO,CAAC,YAAY,CAAC,CAyB7F;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,wDAAwD;AACxD,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAoBnE;AAED,MAAM,WAAW,YAAY;IAC3B,2EAA2E;IAC3E,QAAQ,EAAE,MAAM,CAAC;IACjB,4EAA4E;IAC5E,MAAM,EAAE,KAAK,EAAE,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAWnE;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,YAAY,GACnB,OAAO,CAAC,KAAK,EAAE,CAAC,CAOlB;AA2BD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAE7D;AAMD,4EAA4E;AAC5E,wBAAsB,UAAU,CAC9B,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,UAAe,GACvB,OAAO,CAAC,KAAK,EAAE,CAAC,CA2DlB;AAED,qFAAqF;AACrF,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAE7D"}
|