@rasensio/aidlc 1.3.0 → 1.4.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/dist/commands/gate.d.ts.map +1 -1
- package/dist/commands/gate.js +17 -0
- package/dist/commands/gate.js.map +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +30 -2
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/transition.d.ts.map +1 -1
- package/dist/commands/transition.js +21 -0
- package/dist/commands/transition.js.map +1 -1
- package/dist/core/gate.d.ts +7 -0
- package/dist/core/gate.d.ts.map +1 -1
- package/dist/core/gate.js.map +1 -1
- package/dist/core/types.d.ts +10 -1
- package/dist/core/types.d.ts.map +1 -1
- package/dist/traceability/cache.d.ts +21 -0
- package/dist/traceability/cache.d.ts.map +1 -0
- package/dist/traceability/cache.js +106 -0
- package/dist/traceability/cache.js.map +1 -0
- package/dist/traceability/coverage-block.d.ts +21 -0
- package/dist/traceability/coverage-block.d.ts.map +1 -0
- package/dist/traceability/coverage-block.js +41 -0
- package/dist/traceability/coverage-block.js.map +1 -0
- package/dist/traceability/gate-criterion.d.ts +34 -0
- package/dist/traceability/gate-criterion.d.ts.map +1 -0
- package/dist/traceability/gate-criterion.js +128 -0
- package/dist/traceability/gate-criterion.js.map +1 -0
- package/dist/traceability/matrix.d.ts +35 -0
- package/dist/traceability/matrix.d.ts.map +1 -0
- package/dist/traceability/matrix.js +93 -0
- package/dist/traceability/matrix.js.map +1 -0
- package/dist/traceability/parser.d.ts +27 -0
- package/dist/traceability/parser.d.ts.map +1 -0
- package/dist/traceability/parser.js +101 -0
- package/dist/traceability/parser.js.map +1 -0
- package/dist/traceability/scanner.d.ts +62 -0
- package/dist/traceability/scanner.d.ts.map +1 -0
- package/dist/traceability/scanner.js +198 -0
- package/dist/traceability/scanner.js.map +1 -0
- package/dist/traceability/types.d.ts +77 -0
- package/dist/traceability/types.d.ts.map +1 -0
- package/dist/traceability/types.js +8 -0
- package/dist/traceability/types.js.map +1 -0
- package/package.json +2 -2
- package/dist/commands/setup.d.ts +0 -24
- package/dist/commands/setup.d.ts.map +0 -1
- package/dist/commands/setup.js +0 -262
- package/dist/commands/setup.js.map +0 -1
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Traceability gate criterion (FR4): computed live at the command layer
|
|
3
|
+
* after `evaluateGate`, following the knowledge-criterion precedent — it
|
|
4
|
+
* therefore evaluates even when phase state is `complete` (AC-11) and never
|
|
5
|
+
* touches `evaluateGate`'s contract (DD1).
|
|
6
|
+
*
|
|
7
|
+
* Applicability tri-state (DD7):
|
|
8
|
+
* null phase ≠ testing, phase-testing.yaml absent, or
|
|
9
|
+
* zero AC-shaped lines (AC-3, AC-13)
|
|
10
|
+
* result, empty entries only near-misses — warnings surface (AC-22)
|
|
11
|
+
* result with entries ≥1 valid definition — full evaluation
|
|
12
|
+
*
|
|
13
|
+
* Requirements: traceability-ids/AC-3, AC-11..AC-15
|
|
14
|
+
*/
|
|
15
|
+
import type { ParsedRequirements, TraceabilityConfig, TraceabilityResult } from './types.js';
|
|
16
|
+
/** Message template callers use for unsatisfied criteria / violations. */
|
|
17
|
+
export declare function uncoveredMessage(acId: number): string;
|
|
18
|
+
/** Tolerant reader for the optional `traceability:` config section (AC-7). */
|
|
19
|
+
export declare function loadTraceabilityConfig(projectRoot: string): TraceabilityConfig | null;
|
|
20
|
+
/**
|
|
21
|
+
* Parse every instance's requirements.md — the registry backing the bare-
|
|
22
|
+
* reference uniqueness rule (AC-24, D5). Reads by explicit path; the
|
|
23
|
+
* scanner's `.aidlc` exclusion governs test discovery only.
|
|
24
|
+
*/
|
|
25
|
+
export declare function loadRegistry(projectRoot: string): Map<string, ParsedRequirements>;
|
|
26
|
+
/**
|
|
27
|
+
* Evaluate the traceability criterion for one instance.
|
|
28
|
+
*
|
|
29
|
+
* @returns null when the criterion does not evaluate (AC-3, AC-13); otherwise
|
|
30
|
+
* a result whose `uncoveredActive` entries the caller turns into
|
|
31
|
+
* unsatisfied criteria / gate violations via {@link uncoveredMessage}.
|
|
32
|
+
*/
|
|
33
|
+
export declare function evaluateTraceabilityCriterion(projectRoot: string, instanceName: string, phaseName: string): TraceabilityResult | null;
|
|
34
|
+
//# sourceMappingURL=gate-criterion.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gate-criterion.d.ts","sourceRoot":"","sources":["../../src/traceability/gate-criterion.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAMH,OAAO,KAAK,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAM7F,0EAA0E;AAC1E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,8EAA8E;AAC9E,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI,CAarF;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAkBjF;AAED;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAC3C,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,GAChB,kBAAkB,GAAG,IAAI,CAuD3B"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Traceability gate criterion (FR4): computed live at the command layer
|
|
3
|
+
* after `evaluateGate`, following the knowledge-criterion precedent — it
|
|
4
|
+
* therefore evaluates even when phase state is `complete` (AC-11) and never
|
|
5
|
+
* touches `evaluateGate`'s contract (DD1).
|
|
6
|
+
*
|
|
7
|
+
* Applicability tri-state (DD7):
|
|
8
|
+
* null phase ≠ testing, phase-testing.yaml absent, or
|
|
9
|
+
* zero AC-shaped lines (AC-3, AC-13)
|
|
10
|
+
* result, empty entries only near-misses — warnings surface (AC-22)
|
|
11
|
+
* result with entries ≥1 valid definition — full evaluation
|
|
12
|
+
*
|
|
13
|
+
* Requirements: traceability-ids/AC-3, AC-11..AC-15
|
|
14
|
+
*/
|
|
15
|
+
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
16
|
+
import { join } from 'node:path';
|
|
17
|
+
import { parse as parseYaml } from 'yaml';
|
|
18
|
+
import { parseRequirements } from './parser.js';
|
|
19
|
+
import { DEFAULT_TEST_GLOBS, discoverTestFiles, scanFiles } from './scanner.js';
|
|
20
|
+
import { parseCoverageBlock } from './coverage-block.js';
|
|
21
|
+
import { buildMatrix } from './matrix.js';
|
|
22
|
+
/** Message template callers use for unsatisfied criteria / violations. */
|
|
23
|
+
export function uncoveredMessage(acId) {
|
|
24
|
+
return `acceptance criterion AC-${acId} has no referencing test (traceability)`;
|
|
25
|
+
}
|
|
26
|
+
/** Tolerant reader for the optional `traceability:` config section (AC-7). */
|
|
27
|
+
export function loadTraceabilityConfig(projectRoot) {
|
|
28
|
+
const configPath = join(projectRoot, '.aidlc', 'config.yaml');
|
|
29
|
+
try {
|
|
30
|
+
if (!existsSync(configPath))
|
|
31
|
+
return null;
|
|
32
|
+
const config = parseYaml(readFileSync(configPath, 'utf8'));
|
|
33
|
+
const section = config?.traceability;
|
|
34
|
+
if (typeof section !== 'object' || section === null)
|
|
35
|
+
return null;
|
|
36
|
+
const globs = section.test_globs;
|
|
37
|
+
if (!Array.isArray(globs) || !globs.every((g) => typeof g === 'string'))
|
|
38
|
+
return {};
|
|
39
|
+
return { test_globs: globs };
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Parse every instance's requirements.md — the registry backing the bare-
|
|
47
|
+
* reference uniqueness rule (AC-24, D5). Reads by explicit path; the
|
|
48
|
+
* scanner's `.aidlc` exclusion governs test discovery only.
|
|
49
|
+
*/
|
|
50
|
+
export function loadRegistry(projectRoot) {
|
|
51
|
+
const registry = new Map();
|
|
52
|
+
const stateDir = join(projectRoot, '.aidlc', 'state');
|
|
53
|
+
let instances;
|
|
54
|
+
try {
|
|
55
|
+
instances = readdirSync(stateDir);
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return registry;
|
|
59
|
+
}
|
|
60
|
+
for (const name of instances.sort()) {
|
|
61
|
+
const reqPath = join(stateDir, name, 'requirements.md');
|
|
62
|
+
try {
|
|
63
|
+
registry.set(name, parseRequirements(readFileSync(reqPath, 'utf8'), name));
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
// No requirements.md — not an AC-bearing instance.
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return registry;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Evaluate the traceability criterion for one instance.
|
|
73
|
+
*
|
|
74
|
+
* @returns null when the criterion does not evaluate (AC-3, AC-13); otherwise
|
|
75
|
+
* a result whose `uncoveredActive` entries the caller turns into
|
|
76
|
+
* unsatisfied criteria / gate violations via {@link uncoveredMessage}.
|
|
77
|
+
*/
|
|
78
|
+
export function evaluateTraceabilityCriterion(projectRoot, instanceName, phaseName) {
|
|
79
|
+
if (phaseName !== 'testing')
|
|
80
|
+
return null;
|
|
81
|
+
const instanceDir = join(projectRoot, '.aidlc', 'state', instanceName);
|
|
82
|
+
if (!existsSync(join(instanceDir, 'phase-testing.yaml')))
|
|
83
|
+
return null;
|
|
84
|
+
const registry = loadRegistry(projectRoot);
|
|
85
|
+
const parsed = registry.get(instanceName);
|
|
86
|
+
if (!parsed || parsed.acShapedLines === 0)
|
|
87
|
+
return null;
|
|
88
|
+
const requirementsPath = `.aidlc/state/${instanceName}/requirements.md`;
|
|
89
|
+
const testingPath = `.aidlc/state/${instanceName}/testing.md`;
|
|
90
|
+
// Warnings ordered by phase: parse → glob/discovery → scan → block → matrix
|
|
91
|
+
// (NFR4). Registry parse warnings are scoped to the target instance only.
|
|
92
|
+
const warnings = [...parsed.warnings];
|
|
93
|
+
if (parsed.defs.length === 0) {
|
|
94
|
+
// Tri-state case 2: every criterion is a near-miss — visible, not silent.
|
|
95
|
+
return { requirementsPath, entries: [], warnings, uncoveredActive: [] };
|
|
96
|
+
}
|
|
97
|
+
const config = loadTraceabilityConfig(projectRoot);
|
|
98
|
+
const globs = config?.test_globs ?? DEFAULT_TEST_GLOBS;
|
|
99
|
+
const discovery = discoverTestFiles(projectRoot, globs);
|
|
100
|
+
warnings.push(...discovery.warnings);
|
|
101
|
+
const scan = scanFiles(projectRoot, discovery.files);
|
|
102
|
+
warnings.push(...scan.warnings);
|
|
103
|
+
let blockEntries = [];
|
|
104
|
+
try {
|
|
105
|
+
const block = parseCoverageBlock(readFileSync(join(instanceDir, 'testing.md'), 'utf8'));
|
|
106
|
+
blockEntries = block.entries;
|
|
107
|
+
warnings.push(...block.warnings);
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
// No testing.md yet — scan-only coverage.
|
|
111
|
+
}
|
|
112
|
+
const matrix = buildMatrix({
|
|
113
|
+
instance: instanceName,
|
|
114
|
+
parsed,
|
|
115
|
+
registry,
|
|
116
|
+
refs: scan.refs,
|
|
117
|
+
blockEntries,
|
|
118
|
+
testingPath,
|
|
119
|
+
});
|
|
120
|
+
warnings.push(...matrix.warnings);
|
|
121
|
+
return {
|
|
122
|
+
requirementsPath,
|
|
123
|
+
entries: matrix.entries,
|
|
124
|
+
warnings,
|
|
125
|
+
uncoveredActive: matrix.uncoveredActive,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=gate-criterion.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gate-criterion.js","sourceRoot":"","sources":["../../src/traceability/gate-criterion.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Coverage matrix builder: resolves references against the cross-instance
|
|
3
|
+
* registry (uniqueness rule, D5) and unions scan ∪ block coverage per AC.
|
|
4
|
+
*
|
|
5
|
+
* Bare `AC-n` counts only when exactly one AC-bearing instance defines id n
|
|
6
|
+
* (AC-24); qualified `<instance>/AC-n` always resolves to that instance
|
|
7
|
+
* (AC-25). Retired ACs never require coverage; references to them warn
|
|
8
|
+
* (AC-14). Only `uncoveredActive` fails gates — warnings are data (DD6).
|
|
9
|
+
*
|
|
10
|
+
* Requirements: traceability-ids/AC-9..AC-15, AC-24, AC-25
|
|
11
|
+
*/
|
|
12
|
+
import type { AcCoverageEntry, AcReference, ParsedRequirements } from './types.js';
|
|
13
|
+
import type { CoverageBlockEntry } from './coverage-block.js';
|
|
14
|
+
export interface MatrixInput {
|
|
15
|
+
/** Target instance name. */
|
|
16
|
+
instance: string;
|
|
17
|
+
/** Target instance's parsed requirements. */
|
|
18
|
+
parsed: ParsedRequirements;
|
|
19
|
+
/** All instances' parsed requirements (registry, keyed by instance). */
|
|
20
|
+
registry: Map<string, ParsedRequirements>;
|
|
21
|
+
/** Scanned references from test files. */
|
|
22
|
+
refs: AcReference[];
|
|
23
|
+
/** Entries from the target instance's ac-coverage block. */
|
|
24
|
+
blockEntries: CoverageBlockEntry[];
|
|
25
|
+
/** Posix-relative path of the target instance's testing.md. */
|
|
26
|
+
testingPath: string;
|
|
27
|
+
}
|
|
28
|
+
export interface MatrixOutput {
|
|
29
|
+
entries: AcCoverageEntry[];
|
|
30
|
+
warnings: string[];
|
|
31
|
+
uncoveredActive: number[];
|
|
32
|
+
}
|
|
33
|
+
/** Build the coverage matrix for one instance. */
|
|
34
|
+
export declare function buildMatrix(input: MatrixInput): MatrixOutput;
|
|
35
|
+
//# sourceMappingURL=matrix.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matrix.d.ts","sourceRoot":"","sources":["../../src/traceability/matrix.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EACV,eAAe,EAEf,WAAW,EACX,kBAAkB,EACnB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAE9D,MAAM,WAAW,WAAW;IAC1B,4BAA4B;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,6CAA6C;IAC7C,MAAM,EAAE,kBAAkB,CAAC;IAC3B,wEAAwE;IACxE,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IAC1C,0CAA0C;IAC1C,IAAI,EAAE,WAAW,EAAE,CAAC;IACpB,4DAA4D;IAC5D,YAAY,EAAE,kBAAkB,EAAE,CAAC;IACnC,+DAA+D;IAC/D,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAWD,kDAAkD;AAClD,wBAAgB,WAAW,CAAC,KAAK,EAAE,WAAW,GAAG,YAAY,CA+E5D"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Coverage matrix builder: resolves references against the cross-instance
|
|
3
|
+
* registry (uniqueness rule, D5) and unions scan ∪ block coverage per AC.
|
|
4
|
+
*
|
|
5
|
+
* Bare `AC-n` counts only when exactly one AC-bearing instance defines id n
|
|
6
|
+
* (AC-24); qualified `<instance>/AC-n` always resolves to that instance
|
|
7
|
+
* (AC-25). Retired ACs never require coverage; references to them warn
|
|
8
|
+
* (AC-14). Only `uncoveredActive` fails gates — warnings are data (DD6).
|
|
9
|
+
*
|
|
10
|
+
* Requirements: traceability-ids/AC-9..AC-15, AC-24, AC-25
|
|
11
|
+
*/
|
|
12
|
+
/** Instances (other than possibly the target) defining a given AC id. */
|
|
13
|
+
function definersOf(registry, acId) {
|
|
14
|
+
const definers = [];
|
|
15
|
+
for (const [name, parsed] of registry) {
|
|
16
|
+
if (parsed.defs.some((d) => d.id === acId))
|
|
17
|
+
definers.push(name);
|
|
18
|
+
}
|
|
19
|
+
return definers.sort();
|
|
20
|
+
}
|
|
21
|
+
/** Build the coverage matrix for one instance. */
|
|
22
|
+
export function buildMatrix(input) {
|
|
23
|
+
const { instance, parsed, registry, refs, blockEntries, testingPath } = input;
|
|
24
|
+
const warnings = [];
|
|
25
|
+
const byId = new Map(parsed.defs.map((d) => [d.id, d]));
|
|
26
|
+
const coverage = new Map();
|
|
27
|
+
const addRef = (acId, path, source) => {
|
|
28
|
+
let paths = coverage.get(acId);
|
|
29
|
+
if (!paths)
|
|
30
|
+
coverage.set(acId, (paths = new Map()));
|
|
31
|
+
if (!paths.has(path))
|
|
32
|
+
paths.set(path, source);
|
|
33
|
+
};
|
|
34
|
+
// Resolve scanned references.
|
|
35
|
+
for (const ref of refs) {
|
|
36
|
+
if (ref.instance !== null) {
|
|
37
|
+
// Qualified (AC-25): counts only for the named instance.
|
|
38
|
+
const target = registry.get(ref.instance);
|
|
39
|
+
if (!target || !target.defs.some((d) => d.id === ref.acId)) {
|
|
40
|
+
warnings.push(`${ref.path}:${ref.line}: ${ref.instance}/AC-${ref.acId} references unknown instance/id`);
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
if (ref.instance !== instance)
|
|
44
|
+
continue; // another instance's coverage
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
// Bare (AC-24): counts only when exactly one instance defines the id.
|
|
48
|
+
const definers = definersOf(registry, ref.acId);
|
|
49
|
+
if (definers.length === 0)
|
|
50
|
+
continue; // unknown id — not ours to warn about
|
|
51
|
+
if (definers.length > 1) {
|
|
52
|
+
warnings.push(`${ref.path}:${ref.line}: bare AC-${ref.acId} is ambiguous (defined by ${definers.join(', ')}); qualify as <instance>/AC-${ref.acId}`);
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
if (definers[0] !== instance)
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
const def = byId.get(ref.acId);
|
|
59
|
+
if (def?.status === 'retired') {
|
|
60
|
+
warnings.push(`${ref.path}:${ref.line}: AC-${ref.acId} is retired (stale reference)`);
|
|
61
|
+
}
|
|
62
|
+
addRef(ref.acId, ref.path, 'scan');
|
|
63
|
+
}
|
|
64
|
+
// Union in block entries (AC-9); unknown/retired ids warn, never fail (AC-10).
|
|
65
|
+
for (const entry of blockEntries) {
|
|
66
|
+
const def = byId.get(entry.acId);
|
|
67
|
+
if (!def) {
|
|
68
|
+
warnings.push(`${testingPath}:${entry.line}: ac-coverage entry AC-${entry.acId} references unknown id`);
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
if (def.status === 'retired') {
|
|
72
|
+
warnings.push(`${testingPath}:${entry.line}: ac-coverage entry AC-${entry.acId} is retired (stale reference)`);
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
addRef(entry.acId, testingPath, 'block');
|
|
76
|
+
}
|
|
77
|
+
// Assemble entries sorted by id; refs sorted by path (NFR4).
|
|
78
|
+
const entries = [...parsed.defs]
|
|
79
|
+
.sort((a, b) => a.id - b.id)
|
|
80
|
+
.map((def) => {
|
|
81
|
+
const paths = coverage.get(def.id);
|
|
82
|
+
const refList = paths
|
|
83
|
+
? [...paths.entries()]
|
|
84
|
+
.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
|
|
85
|
+
.map(([path, source]) => ({ path, source }))
|
|
86
|
+
: [];
|
|
87
|
+
const status = def.status === 'retired' ? 'retired' : refList.length > 0 ? 'covered' : 'uncovered';
|
|
88
|
+
return { id: def.id, status, refs: refList };
|
|
89
|
+
});
|
|
90
|
+
const uncoveredActive = entries.filter((e) => e.status === 'uncovered').map((e) => e.id);
|
|
91
|
+
return { entries, warnings, uncoveredActive };
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=matrix.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matrix.js","sourceRoot":"","sources":["../../src/traceability/matrix.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AC definition parser: closed grammar over requirements.md (FR1).
|
|
3
|
+
*
|
|
4
|
+
* Accepted forms (dash bullets only; emphasis coupled — unbalanced bold is a
|
|
5
|
+
* near-miss, AC-22/design F13):
|
|
6
|
+
* - AC-n: text
|
|
7
|
+
* - **AC-n**: text
|
|
8
|
+
* - **AC-n:** text
|
|
9
|
+
* - AC-n (retired YYYY-MM-DD[, superseded by AC-m]): text
|
|
10
|
+
* - **AC-n** (retired ...): text
|
|
11
|
+
* - **AC-n (retired ...):** text
|
|
12
|
+
* - **AC-n (retired ...)**: text
|
|
13
|
+
*
|
|
14
|
+
* Anything AC-shaped that fails the strict grammar warns rather than silently
|
|
15
|
+
* dropping out of required coverage (AC-22).
|
|
16
|
+
*
|
|
17
|
+
* Requirements: traceability-ids/AC-1, AC-2, AC-4, AC-22, AC-23
|
|
18
|
+
*/
|
|
19
|
+
import type { ParsedRequirements } from './types.js';
|
|
20
|
+
/**
|
|
21
|
+
* Parse one requirements.md for AC definitions.
|
|
22
|
+
*
|
|
23
|
+
* @param content - File content (UTF-8).
|
|
24
|
+
* @param instance - Owning instance name, recorded on each definition.
|
|
25
|
+
*/
|
|
26
|
+
export declare function parseRequirements(content: string, instance: string): ParsedRequirements;
|
|
27
|
+
//# sourceMappingURL=parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/traceability/parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAgB,kBAAkB,EAAE,MAAM,YAAY,CAAC;AA0BnE;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,kBAAkB,CAiEvF"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AC definition parser: closed grammar over requirements.md (FR1).
|
|
3
|
+
*
|
|
4
|
+
* Accepted forms (dash bullets only; emphasis coupled — unbalanced bold is a
|
|
5
|
+
* near-miss, AC-22/design F13):
|
|
6
|
+
* - AC-n: text
|
|
7
|
+
* - **AC-n**: text
|
|
8
|
+
* - **AC-n:** text
|
|
9
|
+
* - AC-n (retired YYYY-MM-DD[, superseded by AC-m]): text
|
|
10
|
+
* - **AC-n** (retired ...): text
|
|
11
|
+
* - **AC-n (retired ...):** text
|
|
12
|
+
* - **AC-n (retired ...)**: text
|
|
13
|
+
*
|
|
14
|
+
* Anything AC-shaped that fails the strict grammar warns rather than silently
|
|
15
|
+
* dropping out of required coverage (AC-22).
|
|
16
|
+
*
|
|
17
|
+
* Requirements: traceability-ids/AC-1, AC-2, AC-4, AC-22, AC-23
|
|
18
|
+
*/
|
|
19
|
+
// Active: the three bold/colon variants, coupled emphasis, non-empty text.
|
|
20
|
+
const ACTIVE_RE = /^\s*-\s+(?:AC-([1-9][0-9]*):|\*\*AC-([1-9][0-9]*)\*\*:|\*\*AC-([1-9][0-9]*):\*\*)\s+\S/;
|
|
21
|
+
// Retired: `R` = retired marker with optional supersession.
|
|
22
|
+
const R = String.raw `\(retired\s+(\d{4}-\d{2}-\d{2})(?:,\s*superseded by AC-([1-9][0-9]*))?\)`;
|
|
23
|
+
const RETIRED_RE = new RegExp(String.raw `^\s*-\s+(?:` +
|
|
24
|
+
String.raw `AC-([1-9][0-9]*)\s+${R}:|` +
|
|
25
|
+
String.raw `\*\*AC-([1-9][0-9]*)\*\*\s+${R}:|` +
|
|
26
|
+
String.raw `\*\*AC-([1-9][0-9]*)\s+${R}:\*\*|` +
|
|
27
|
+
String.raw `\*\*AC-([1-9][0-9]*)\s+${R}\*\*:` +
|
|
28
|
+
String.raw `)`);
|
|
29
|
+
// Loose pattern for the near-miss lint (AC-22): any bullet style, so `*`/`+`
|
|
30
|
+
// bullets and numbered items warn instead of vanishing (design F13).
|
|
31
|
+
const AC_SHAPED_RE = /^\s*(?:[-*+]|\d+\.)\s+\**AC-\d+/;
|
|
32
|
+
function excerpt(line) {
|
|
33
|
+
const trimmed = line.trim();
|
|
34
|
+
return trimmed.length > 60 ? `${trimmed.slice(0, 57)}...` : trimmed;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Parse one requirements.md for AC definitions.
|
|
38
|
+
*
|
|
39
|
+
* @param content - File content (UTF-8).
|
|
40
|
+
* @param instance - Owning instance name, recorded on each definition.
|
|
41
|
+
*/
|
|
42
|
+
export function parseRequirements(content, instance) {
|
|
43
|
+
const defs = [];
|
|
44
|
+
const warnings = [];
|
|
45
|
+
const byId = new Map();
|
|
46
|
+
let acShapedLines = 0;
|
|
47
|
+
const lines = content.split('\n');
|
|
48
|
+
for (let i = 0; i < lines.length; i++) {
|
|
49
|
+
const line = lines[i];
|
|
50
|
+
const lineNo = i + 1;
|
|
51
|
+
if (!AC_SHAPED_RE.test(line))
|
|
52
|
+
continue;
|
|
53
|
+
acShapedLines++;
|
|
54
|
+
let def = null;
|
|
55
|
+
const active = ACTIVE_RE.exec(line);
|
|
56
|
+
if (active) {
|
|
57
|
+
const id = Number(active[1] ?? active[2] ?? active[3]);
|
|
58
|
+
def = { id, instance, line: lineNo, status: 'active' };
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
const retired = RETIRED_RE.exec(line);
|
|
62
|
+
if (retired) {
|
|
63
|
+
// Four alternatives × (id, date, supersededBy) capture triplets.
|
|
64
|
+
for (let g = 1; g <= 10; g += 3) {
|
|
65
|
+
if (retired[g] !== undefined) {
|
|
66
|
+
def = {
|
|
67
|
+
id: Number(retired[g]),
|
|
68
|
+
instance,
|
|
69
|
+
line: lineNo,
|
|
70
|
+
status: 'retired',
|
|
71
|
+
retiredDate: retired[g + 1],
|
|
72
|
+
...(retired[g + 2] !== undefined && { supersededBy: Number(retired[g + 2]) }),
|
|
73
|
+
};
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (!def) {
|
|
80
|
+
warnings.push(`line ${lineNo}: "${excerpt(line)}" resembles an AC definition but does not match the grammar`);
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
const existing = byId.get(def.id);
|
|
84
|
+
if (existing) {
|
|
85
|
+
warnings.push(`duplicate AC-${def.id}: lines ${existing.line} and ${lineNo} (first occurrence wins)`);
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
byId.set(def.id, def);
|
|
89
|
+
defs.push(def);
|
|
90
|
+
}
|
|
91
|
+
// Sequence gaps (AC-23), computed over active ∪ retired ids.
|
|
92
|
+
if (byId.size > 0) {
|
|
93
|
+
const maxId = Math.max(...byId.keys());
|
|
94
|
+
for (let n = 1; n <= maxId; n++) {
|
|
95
|
+
if (!byId.has(n))
|
|
96
|
+
warnings.push(`AC-${n} is never defined (sequence gap)`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return { defs, warnings, acShapedLines };
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/traceability/parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test-file discovery and AC-reference scanning (FR2).
|
|
3
|
+
*
|
|
4
|
+
* Own walker + glob translator instead of `fs.globSync`: stdlib glob
|
|
5
|
+
* semantics are release-dependent while the Node floor is 22.13; the pinned
|
|
6
|
+
* semantics here are enforced by this module's tests (NFR1, design DD2).
|
|
7
|
+
*
|
|
8
|
+
* Pinned semantics (design Data Flow 4):
|
|
9
|
+
* - `**` matches zero or more path segments
|
|
10
|
+
* - `*` / `?` match within a segment, never a leading dot
|
|
11
|
+
* - dot-files and dot-directories are never traversed
|
|
12
|
+
* - exclusions (node_modules, .git, dist, build, .aidlc) prune before
|
|
13
|
+
* descent at any depth, regardless of glob source (AC-6/AC-7, DD4)
|
|
14
|
+
* - symlinks are never followed (AC-8, NFR3)
|
|
15
|
+
* - emitted paths are posix-separated and project-root-relative (design F7)
|
|
16
|
+
*
|
|
17
|
+
* Requirements: traceability-ids/AC-5..AC-8, AC-24, AC-25
|
|
18
|
+
*/
|
|
19
|
+
import type { AcReference } from './types.js';
|
|
20
|
+
/** D1 default test globs. */
|
|
21
|
+
export declare const DEFAULT_TEST_GLOBS: string[];
|
|
22
|
+
/** Scan caps (NFR2, AC-8). */
|
|
23
|
+
export declare const MAX_SCANNED_FILES = 10000;
|
|
24
|
+
/**
|
|
25
|
+
* Translate one glob into a RegExp over posix relative paths, or null when
|
|
26
|
+
* the pattern uses unsupported syntax (braces, extglobs, character classes).
|
|
27
|
+
*/
|
|
28
|
+
export declare function translateGlob(pattern: string): RegExp | null;
|
|
29
|
+
/**
|
|
30
|
+
* Validate configured globs (AC-7): absolute or `..`-containing patterns and
|
|
31
|
+
* unsupported syntax are rejected with a warning naming the glob.
|
|
32
|
+
*/
|
|
33
|
+
export declare function validateGlobs(patterns: string[]): {
|
|
34
|
+
matchers: RegExp[];
|
|
35
|
+
warnings: string[];
|
|
36
|
+
};
|
|
37
|
+
export interface DiscoveryResult {
|
|
38
|
+
/** Posix-separated project-root-relative paths, sorted. */
|
|
39
|
+
files: string[];
|
|
40
|
+
warnings: string[];
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Discover test files by glob against the project root.
|
|
44
|
+
*
|
|
45
|
+
* @param projectRoot - Directory containing `.aidlc/`.
|
|
46
|
+
* @param globs - Effective glob list (defaults or config).
|
|
47
|
+
*/
|
|
48
|
+
export declare function discoverTestFiles(projectRoot: string, globs: string[]): DiscoveryResult;
|
|
49
|
+
export interface ScanResult {
|
|
50
|
+
refs: AcReference[];
|
|
51
|
+
warnings: string[];
|
|
52
|
+
}
|
|
53
|
+
/** Scan one file's content for AC reference tokens (qualified, then bare). */
|
|
54
|
+
export declare function scanContent(content: string, path: string): AcReference[];
|
|
55
|
+
/**
|
|
56
|
+
* Scan discovered files, skipping unreadable/oversize/binary files with a
|
|
57
|
+
* warning (AC-8). Never throws.
|
|
58
|
+
*/
|
|
59
|
+
export declare function scanFiles(projectRoot: string, files: string[]): ScanResult;
|
|
60
|
+
/** Convert a native relative path to the canonical posix form (design F7). */
|
|
61
|
+
export declare function toPosix(relPath: string): string;
|
|
62
|
+
//# sourceMappingURL=scanner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../../src/traceability/scanner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,6BAA6B;AAC7B,eAAO,MAAM,kBAAkB,UAA8D,CAAC;AAK9F,8BAA8B;AAC9B,eAAO,MAAM,iBAAiB,QAAS,CAAC;AAgBxC;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAyB5D;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG;IAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CAoB5F;AAMD,MAAM,WAAW,eAAe;IAC9B,2DAA2D;IAC3D,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAsBD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,eAAe,CAYvF;AAMD,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,WAAW,EAAE,CAAC;IACpB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,8EAA8E;AAC9E,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW,EAAE,CAexE;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,UAAU,CA8B1E;AAED,8EAA8E;AAC9E,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE/C"}
|