@ncoderz/awa 1.8.4 → 1.9.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/{chunk-GOIBZQFJ.js → chunk-4NC73OUR.js} +13 -1
- package/dist/chunk-4NC73OUR.js.map +1 -0
- package/dist/{chunk-2VUVSW6T.js → chunk-PC3PMV3K.js} +7 -4
- package/dist/{chunk-2VUVSW6T.js.map → chunk-PC3PMV3K.js.map} +1 -1
- package/dist/{config-SJLBJX77.js → config-EP5JOR5X.js} +2 -2
- package/dist/index.js +221 -99
- package/dist/index.js.map +1 -1
- package/dist/renumber-LG6FUVOP.js +9 -0
- package/package.json +1 -1
- package/templates/awa/.agent/skills/awa-spec-deprecate/SKILL.md +3 -0
- package/templates/awa/.agent/skills/awa-spec-merge/SKILL.md +3 -0
- package/templates/awa/.agent/skills/awa-spec-tidy/SKILL.md +3 -0
- package/templates/awa/.agent/workflows/awa-spec-deprecate.md +3 -0
- package/templates/awa/.agent/workflows/awa-spec-merge.md +3 -0
- package/templates/awa/.agent/workflows/awa-spec-tidy.md +3 -0
- package/templates/awa/.agents/skills/awa-spec-deprecate/SKILL.md +3 -0
- package/templates/awa/.agents/skills/awa-spec-merge/SKILL.md +3 -0
- package/templates/awa/.agents/skills/awa-spec-tidy/SKILL.md +3 -0
- package/templates/awa/.awa/.agent/schemas/DEPRECATED.schema.yaml +42 -0
- package/templates/awa/.claude/skills/awa-spec-deprecate/SKILL.md +3 -0
- package/templates/awa/.claude/skills/awa-spec-merge/SKILL.md +3 -0
- package/templates/awa/.claude/skills/awa-spec-tidy/SKILL.md +3 -0
- package/templates/awa/.codex/prompts/awa-spec-deprecate.md +3 -0
- package/templates/awa/.cursor/rules/awa-spec-deprecate.md +8 -0
- package/templates/awa/.gemini/commands/awa-spec-deprecate.md +3 -0
- package/templates/awa/.gemini/commands/awa-spec-merge.md +3 -0
- package/templates/awa/.gemini/commands/awa-spec-tidy.md +3 -0
- package/templates/awa/.gemini/skills/awa-spec-deprecate/SKILL.md +3 -0
- package/templates/awa/.gemini/skills/awa-spec-merge/SKILL.md +3 -0
- package/templates/awa/.gemini/skills/awa-spec-tidy/SKILL.md +3 -0
- package/templates/awa/.github/prompts/awa.spec-deprecate.prompt.md +8 -0
- package/templates/awa/.github/prompts/awa.spec-tidy.prompt.md +1 -1
- package/templates/awa/.github/skills/awa-spec-deprecate/SKILL.md +8 -0
- package/templates/awa/.github/skills/awa-spec-merge/SKILL.md +3 -0
- package/templates/awa/.github/skills/awa-spec-tidy/SKILL.md +3 -0
- package/templates/awa/.kilocode/skills/awa-spec-deprecate/SKILL.md +3 -0
- package/templates/awa/.kilocode/skills/awa-spec-merge/SKILL.md +3 -0
- package/templates/awa/.kilocode/skills/awa-spec-tidy/SKILL.md +3 -0
- package/templates/awa/.kilocode/workflows/awa-spec-deprecate.md +3 -0
- package/templates/awa/.kilocode/workflows/awa-spec-merge.md +3 -0
- package/templates/awa/.kilocode/{skills/spec-merge/SKILL.md → workflows/awa-spec-tidy.md} +1 -1
- package/templates/awa/.opencode/commands/awa-spec-deprecate.md +3 -0
- package/templates/awa/.opencode/commands/awa-spec-merge.md +3 -0
- package/templates/awa/.opencode/commands/{spec-merge.md → awa-spec-tidy.md} +1 -1
- package/templates/awa/.opencode/skills/awa-spec-deprecate/SKILL.md +3 -0
- package/templates/awa/.opencode/skills/awa-spec-merge/SKILL.md +3 -0
- package/templates/awa/.opencode/skills/awa-spec-tidy/SKILL.md +3 -0
- package/templates/awa/.qwen/commands/awa-spec-deprecate.md +3 -0
- package/templates/awa/.qwen/commands/awa-spec-merge.md +3 -0
- package/templates/awa/.qwen/commands/awa-spec-tidy.md +3 -0
- package/templates/awa/.qwen/skills/awa-spec-deprecate/SKILL.md +3 -0
- package/templates/awa/.qwen/skills/awa-spec-merge/SKILL.md +3 -0
- package/templates/awa/.qwen/skills/awa-spec-tidy/SKILL.md +3 -0
- package/templates/awa/.roo/skills/awa-spec-deprecate/SKILL.md +3 -0
- package/templates/awa/.roo/skills/awa-spec-merge/SKILL.md +3 -0
- package/templates/awa/.roo/skills/awa-spec-tidy/SKILL.md +3 -0
- package/templates/awa/.windsurf/skills/awa-spec-deprecate/SKILL.md +3 -0
- package/templates/awa/.windsurf/skills/awa-spec-merge/SKILL.md +3 -0
- package/templates/awa/.windsurf/skills/awa-spec-tidy/SKILL.md +3 -0
- package/templates/awa/_delete.txt +108 -0
- package/templates/awa/_partials/_cmd.awa-spec-deprecate.md +6 -0
- package/templates/awa/_partials/{_cmd.spec-tidy.md → _cmd.awa-spec-tidy.md} +1 -1
- package/templates/awa/_partials/_skill.awa-spec-deprecate.md +6 -0
- package/templates/awa/_partials/{_skill.spec-merge.md → _skill.awa-spec-merge.md} +1 -1
- package/templates/awa/_partials/{_skill.spec-tidy.md → _skill.awa-spec-tidy.md} +2 -2
- package/templates/awa/_partials/awa.code.md +5 -4
- package/templates/awa/_partials/awa.core.md +10 -6
- package/templates/awa/_partials/awa.spec-deprecate.md +86 -0
- package/templates/awa/_partials/awa.usage.md +16 -7
- package/templates/awa/_tests/claude/.claude/skills/awa-spec-deprecate/SKILL.md +88 -0
- package/templates/awa/_tests/claude/.claude/skills/{spec-merge → awa-spec-merge}/SKILL.md +1 -1
- package/templates/awa/_tests/{copilot/.github/skills/spec-tidy → claude/.claude/skills/awa-spec-tidy}/SKILL.md +1 -1
- package/templates/awa/_tests/claude/.claude/skills/awa-usage/SKILL.md +14 -5
- package/templates/awa/_tests/copilot/.github/prompts/awa.spec-deprecate.prompt.md +88 -0
- package/templates/awa/_tests/copilot/.github/skills/awa-spec-deprecate/SKILL.md +88 -0
- package/templates/awa/_tests/copilot/.github/skills/{spec-merge → awa-spec-merge}/SKILL.md +1 -1
- package/templates/awa/_tests/{claude/.claude/skills/spec-tidy → copilot/.github/skills/awa-spec-tidy}/SKILL.md +1 -1
- package/templates/awa/_tests/copilot/.github/skills/awa-usage/SKILL.md +14 -5
- package/dist/chunk-GOIBZQFJ.js.map +0 -1
- package/dist/renumber-TGDI47IS.js +0 -9
- package/templates/awa/.agent/skills/spec-merge/SKILL.md +0 -3
- package/templates/awa/.agent/skills/spec-tidy/SKILL.md +0 -3
- package/templates/awa/.agent/workflows/spec-merge.md +0 -3
- package/templates/awa/.agent/workflows/spec-tidy.md +0 -3
- package/templates/awa/.agents/skills/spec-merge/SKILL.md +0 -3
- package/templates/awa/.agents/skills/spec-tidy/SKILL.md +0 -3
- package/templates/awa/.claude/skills/spec-merge/SKILL.md +0 -3
- package/templates/awa/.claude/skills/spec-tidy/SKILL.md +0 -3
- package/templates/awa/.gemini/commands/spec-merge.md +0 -3
- package/templates/awa/.gemini/commands/spec-tidy.md +0 -3
- package/templates/awa/.gemini/skills/spec-merge/SKILL.md +0 -3
- package/templates/awa/.gemini/skills/spec-tidy/SKILL.md +0 -3
- package/templates/awa/.github/skills/spec-merge/SKILL.md +0 -3
- package/templates/awa/.github/skills/spec-tidy/SKILL.md +0 -3
- package/templates/awa/.kilocode/skills/spec-tidy/SKILL.md +0 -3
- package/templates/awa/.kilocode/workflows/spec-merge.md +0 -3
- package/templates/awa/.kilocode/workflows/spec-tidy.md +0 -3
- package/templates/awa/.opencode/commands/spec-tidy.md +0 -3
- package/templates/awa/.opencode/skills/spec-merge/SKILL.md +0 -3
- package/templates/awa/.opencode/skills/spec-tidy/SKILL.md +0 -3
- package/templates/awa/.qwen/commands/spec-merge.md +0 -3
- package/templates/awa/.qwen/commands/spec-tidy.md +0 -3
- package/templates/awa/.qwen/skills/spec-merge/SKILL.md +0 -3
- package/templates/awa/.qwen/skills/spec-tidy/SKILL.md +0 -3
- package/templates/awa/.roo/skills/spec-merge/SKILL.md +0 -3
- package/templates/awa/.roo/skills/spec-tidy/SKILL.md +0 -3
- package/templates/awa/.windsurf/skills/spec-merge/SKILL.md +0 -3
- package/templates/awa/.windsurf/skills/spec-tidy/SKILL.md +0 -3
- /package/dist/{config-SJLBJX77.js.map → config-EP5JOR5X.js.map} +0 -0
- /package/dist/{renumber-TGDI47IS.js.map → renumber-LG6FUVOP.js.map} +0 -0
- /package/templates/awa/_partials/{_cmd.spec-merge.md → _cmd.awa-spec-merge.md} +0 -0
- /package/templates/awa/_partials/{awa.spec.tidy.md → awa.spec-tidy.md} +0 -0
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
renumberCommand,
|
|
11
11
|
scan,
|
|
12
12
|
scanMarkers
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-PC3PMV3K.js";
|
|
14
14
|
import {
|
|
15
15
|
ConfigError,
|
|
16
16
|
DiffError,
|
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
rmDir,
|
|
29
29
|
walkDirectory,
|
|
30
30
|
writeTextFile
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-4NC73OUR.js";
|
|
32
32
|
|
|
33
33
|
// src/cli/index.ts
|
|
34
34
|
import { Command, Option } from "commander";
|
|
@@ -36,14 +36,42 @@ import { Command, Option } from "commander";
|
|
|
36
36
|
// src/_generated/package_info.ts
|
|
37
37
|
var PACKAGE_INFO = {
|
|
38
38
|
"name": "@ncoderz/awa",
|
|
39
|
-
"version": "1.
|
|
39
|
+
"version": "1.9.0",
|
|
40
40
|
"author": "Richard Sewell <richard.sewell@ncoderz.com>",
|
|
41
41
|
"license": "BSD-3-Clause",
|
|
42
42
|
"description": "awa is an Agent Workflow for AIs. It is also a CLI tool to powerfully manage agent workflow files using templates."
|
|
43
43
|
};
|
|
44
44
|
|
|
45
45
|
// src/core/check/code-spec-checker.ts
|
|
46
|
-
function
|
|
46
|
+
function buildComponentAttribution(markers) {
|
|
47
|
+
const result = /* @__PURE__ */ new Map();
|
|
48
|
+
for (const m of markers) {
|
|
49
|
+
if (m.type === "component" && !result.has(m.id)) {
|
|
50
|
+
result.set(m.id, /* @__PURE__ */ new Set());
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
const byFile = /* @__PURE__ */ new Map();
|
|
54
|
+
for (const m of markers) {
|
|
55
|
+
const list = byFile.get(m.filePath) ?? [];
|
|
56
|
+
list.push(m);
|
|
57
|
+
byFile.set(m.filePath, list);
|
|
58
|
+
}
|
|
59
|
+
for (const fileMarkers of byFile.values()) {
|
|
60
|
+
const sorted = [...fileMarkers].sort((a, b) => a.line - b.line);
|
|
61
|
+
let activeComponent = null;
|
|
62
|
+
for (const m of sorted) {
|
|
63
|
+
if (m.type === "component") {
|
|
64
|
+
activeComponent = m.id;
|
|
65
|
+
} else {
|
|
66
|
+
if (activeComponent) {
|
|
67
|
+
result.get(activeComponent)?.add(m.id);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return result;
|
|
73
|
+
}
|
|
74
|
+
function checkCodeAgainstSpec(markers, specs, config, deprecatedIds = /* @__PURE__ */ new Set()) {
|
|
47
75
|
const findings = [];
|
|
48
76
|
const idRegex = new RegExp(`^${config.idPattern}$`);
|
|
49
77
|
for (const marker of markers.markers) {
|
|
@@ -64,6 +92,19 @@ function checkCodeAgainstSpec(markers, specs, config) {
|
|
|
64
92
|
for (const marker of markers.markers) {
|
|
65
93
|
if (marker.type === "component") {
|
|
66
94
|
if (!specs.componentNames.has(marker.id)) {
|
|
95
|
+
if (deprecatedIds.has(marker.id)) {
|
|
96
|
+
if (config.deprecated) {
|
|
97
|
+
findings.push({
|
|
98
|
+
severity: "warning",
|
|
99
|
+
code: "deprecated-ref",
|
|
100
|
+
message: `Component marker '${marker.id}' references a deprecated ID`,
|
|
101
|
+
filePath: marker.filePath,
|
|
102
|
+
line: marker.line,
|
|
103
|
+
id: marker.id
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
67
108
|
findings.push({
|
|
68
109
|
severity: "error",
|
|
69
110
|
code: "orphaned-marker",
|
|
@@ -75,6 +116,19 @@ function checkCodeAgainstSpec(markers, specs, config) {
|
|
|
75
116
|
}
|
|
76
117
|
} else {
|
|
77
118
|
if (!specs.allIds.has(marker.id)) {
|
|
119
|
+
if (deprecatedIds.has(marker.id)) {
|
|
120
|
+
if (config.deprecated) {
|
|
121
|
+
findings.push({
|
|
122
|
+
severity: "warning",
|
|
123
|
+
code: "deprecated-ref",
|
|
124
|
+
message: `Marker '${marker.id}' references a deprecated ID`,
|
|
125
|
+
filePath: marker.filePath,
|
|
126
|
+
line: marker.line,
|
|
127
|
+
id: marker.id
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
78
132
|
findings.push({
|
|
79
133
|
severity: "error",
|
|
80
134
|
code: "orphaned-marker",
|
|
@@ -88,6 +142,7 @@ function checkCodeAgainstSpec(markers, specs, config) {
|
|
|
88
142
|
}
|
|
89
143
|
const testedIds = new Set(markers.markers.filter((m) => m.type === "test").map((m) => m.id));
|
|
90
144
|
for (const acId of specs.acIds) {
|
|
145
|
+
if (deprecatedIds.has(acId)) continue;
|
|
91
146
|
if (!testedIds.has(acId)) {
|
|
92
147
|
const loc = specs.idLocations.get(acId);
|
|
93
148
|
const specFile = loc ? void 0 : specs.specFiles.find((sf) => sf.acIds.includes(acId));
|
|
@@ -105,6 +160,7 @@ function checkCodeAgainstSpec(markers, specs, config) {
|
|
|
105
160
|
markers.markers.filter((m) => m.type === "component").map((m) => m.id)
|
|
106
161
|
);
|
|
107
162
|
for (const componentName of specs.componentNames) {
|
|
163
|
+
if (deprecatedIds.has(componentName)) continue;
|
|
108
164
|
if (!implementedComponents.has(componentName)) {
|
|
109
165
|
const loc = specs.idLocations.get(componentName);
|
|
110
166
|
const specFile = loc ? void 0 : specs.specFiles.find((sf) => sf.componentNames.includes(componentName));
|
|
@@ -120,6 +176,7 @@ function checkCodeAgainstSpec(markers, specs, config) {
|
|
|
120
176
|
}
|
|
121
177
|
const implementedIds = new Set(markers.markers.filter((m) => m.type === "impl").map((m) => m.id));
|
|
122
178
|
for (const acId of specs.acIds) {
|
|
179
|
+
if (deprecatedIds.has(acId)) continue;
|
|
123
180
|
if (!implementedIds.has(acId)) {
|
|
124
181
|
const loc = specs.idLocations.get(acId);
|
|
125
182
|
const specFile = loc ? void 0 : specs.specFiles.find((sf) => sf.acIds.includes(acId));
|
|
@@ -134,6 +191,7 @@ function checkCodeAgainstSpec(markers, specs, config) {
|
|
|
134
191
|
}
|
|
135
192
|
}
|
|
136
193
|
for (const propId of specs.propertyIds) {
|
|
194
|
+
if (deprecatedIds.has(propId)) continue;
|
|
137
195
|
if (!testedIds.has(propId)) {
|
|
138
196
|
const loc = specs.idLocations.get(propId);
|
|
139
197
|
const specFile = loc ? void 0 : specs.specFiles.find((sf) => sf.propertyIds.includes(propId));
|
|
@@ -147,32 +205,7 @@ function checkCodeAgainstSpec(markers, specs, config) {
|
|
|
147
205
|
});
|
|
148
206
|
}
|
|
149
207
|
}
|
|
150
|
-
const componentFiles =
|
|
151
|
-
for (const marker of markers.markers) {
|
|
152
|
-
if (marker.type === "component") {
|
|
153
|
-
if (!componentFiles.has(marker.id)) {
|
|
154
|
-
componentFiles.set(marker.id, /* @__PURE__ */ new Set());
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
const fileToComponents = /* @__PURE__ */ new Map();
|
|
159
|
-
for (const marker of markers.markers) {
|
|
160
|
-
if (marker.type === "component") {
|
|
161
|
-
const existing = fileToComponents.get(marker.filePath) ?? [];
|
|
162
|
-
existing.push(marker.id);
|
|
163
|
-
fileToComponents.set(marker.filePath, existing);
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
for (const marker of markers.markers) {
|
|
167
|
-
if (marker.type === "impl") {
|
|
168
|
-
const components = fileToComponents.get(marker.filePath);
|
|
169
|
-
if (components) {
|
|
170
|
-
for (const comp of components) {
|
|
171
|
-
componentFiles.get(comp)?.add(marker.id);
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
}
|
|
208
|
+
const componentFiles = buildComponentAttribution(markers.markers);
|
|
176
209
|
const designImplements = /* @__PURE__ */ new Map();
|
|
177
210
|
for (const specFile of specs.specFiles) {
|
|
178
211
|
if (specFile.componentImplements) {
|
|
@@ -514,8 +547,37 @@ function replaceFeatureCodesSection(content, sectionStart, newSection) {
|
|
|
514
547
|
return result.join("\n");
|
|
515
548
|
}
|
|
516
549
|
|
|
550
|
+
// src/core/check/deprecated-parser.ts
|
|
551
|
+
import { readFile as readFile3 } from "fs/promises";
|
|
552
|
+
import { join } from "path";
|
|
553
|
+
var DEPRECATED_PATH = "deprecated/DEPRECATED.md";
|
|
554
|
+
async function parseDeprecated(specDir) {
|
|
555
|
+
const filePath = join(specDir, DEPRECATED_PATH);
|
|
556
|
+
let content;
|
|
557
|
+
try {
|
|
558
|
+
content = await readFile3(filePath, "utf-8");
|
|
559
|
+
} catch {
|
|
560
|
+
return { deprecatedIds: /* @__PURE__ */ new Set() };
|
|
561
|
+
}
|
|
562
|
+
const deprecatedIds = /* @__PURE__ */ new Set();
|
|
563
|
+
const idPattern = /[A-Z][A-Z0-9]*(?:-\d+(?:\.\d+)?(?:_AC-\d+)?|_P-\d+|-[A-Za-z][A-Za-z0-9]*)/g;
|
|
564
|
+
for (const line of content.split("\n")) {
|
|
565
|
+
const trimmed = line.trim();
|
|
566
|
+
if (trimmed === "" || /^#\s/.test(trimmed)) continue;
|
|
567
|
+
for (const segment of trimmed.split(",")) {
|
|
568
|
+
const match = segment.trim().match(idPattern);
|
|
569
|
+
if (match) {
|
|
570
|
+
for (const id of match) {
|
|
571
|
+
deprecatedIds.add(id);
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
return { deprecatedIds };
|
|
577
|
+
}
|
|
578
|
+
|
|
517
579
|
// src/core/check/matrix-fixer.ts
|
|
518
|
-
import { readFile as
|
|
580
|
+
import { readFile as readFile4, writeFile as writeFile2 } from "fs/promises";
|
|
519
581
|
import { basename as basename3 } from "path";
|
|
520
582
|
async function fixMatrices(specs, crossRefPatterns) {
|
|
521
583
|
const reqFileMaps = buildReqFileMaps(specs.specFiles);
|
|
@@ -590,7 +652,7 @@ async function fixDesignMatrix(filePath, reqFileMaps, crossRefPatterns, cachedCo
|
|
|
590
652
|
content = cachedContent;
|
|
591
653
|
} else {
|
|
592
654
|
try {
|
|
593
|
-
content = await
|
|
655
|
+
content = await readFile4(filePath, "utf-8");
|
|
594
656
|
} catch {
|
|
595
657
|
return false;
|
|
596
658
|
}
|
|
@@ -694,7 +756,7 @@ async function fixTaskMatrix(filePath, reqFileMaps, specs, crossRefPatterns, cac
|
|
|
694
756
|
content = cachedContent;
|
|
695
757
|
} else {
|
|
696
758
|
try {
|
|
697
|
-
content = await
|
|
759
|
+
content = await readFile4(filePath, "utf-8");
|
|
698
760
|
} catch {
|
|
699
761
|
return false;
|
|
700
762
|
}
|
|
@@ -941,12 +1003,31 @@ function printRuleContext(f) {
|
|
|
941
1003
|
console.log(chalk.dim(` rule: ${parts.join(" \u2014 ")}`));
|
|
942
1004
|
}
|
|
943
1005
|
|
|
1006
|
+
// src/core/check/reservation-checker.ts
|
|
1007
|
+
function checkReservations(specs, deprecatedIds) {
|
|
1008
|
+
const findings = [];
|
|
1009
|
+
for (const id of deprecatedIds) {
|
|
1010
|
+
if (specs.allIds.has(id)) {
|
|
1011
|
+
const loc = specs.idLocations.get(id);
|
|
1012
|
+
findings.push({
|
|
1013
|
+
severity: "error",
|
|
1014
|
+
code: "deprecated-id-conflict",
|
|
1015
|
+
message: `ID '${id}' is defined in active specs but is reserved by the deprecated file`,
|
|
1016
|
+
filePath: loc?.filePath,
|
|
1017
|
+
line: loc?.line,
|
|
1018
|
+
id
|
|
1019
|
+
});
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
return { findings };
|
|
1023
|
+
}
|
|
1024
|
+
|
|
944
1025
|
// src/core/check/rule-loader.ts
|
|
945
|
-
import { readFile as
|
|
946
|
-
import { join } from "path";
|
|
1026
|
+
import { readFile as readFile5 } from "fs/promises";
|
|
1027
|
+
import { join as join2 } from "path";
|
|
947
1028
|
import { parse as parseYaml } from "yaml";
|
|
948
1029
|
async function loadRules(schemaDir) {
|
|
949
|
-
const pattern =
|
|
1030
|
+
const pattern = join2(schemaDir, "*.schema.yaml");
|
|
950
1031
|
const files = await collectFiles([pattern], []);
|
|
951
1032
|
const results = [];
|
|
952
1033
|
for (const filePath of files) {
|
|
@@ -963,7 +1044,7 @@ function matchesTargetGlob(filePath, targetGlob) {
|
|
|
963
1044
|
async function loadRuleFile(filePath) {
|
|
964
1045
|
let content;
|
|
965
1046
|
try {
|
|
966
|
-
content = await
|
|
1047
|
+
content = await readFile5(filePath, "utf-8");
|
|
967
1048
|
} catch {
|
|
968
1049
|
return null;
|
|
969
1050
|
}
|
|
@@ -1155,7 +1236,7 @@ var RuleValidationError = class extends Error {
|
|
|
1155
1236
|
};
|
|
1156
1237
|
|
|
1157
1238
|
// src/core/check/schema-checker.ts
|
|
1158
|
-
import { readFile as
|
|
1239
|
+
import { readFile as readFile6 } from "fs/promises";
|
|
1159
1240
|
import remarkGfm from "remark-gfm";
|
|
1160
1241
|
import remarkParse from "remark-parse";
|
|
1161
1242
|
import { unified } from "unified";
|
|
@@ -1205,7 +1286,7 @@ async function checkSchemasAsync(specFiles, ruleSets) {
|
|
|
1205
1286
|
content = spec2.content;
|
|
1206
1287
|
} else {
|
|
1207
1288
|
try {
|
|
1208
|
-
content = await
|
|
1289
|
+
content = await readFile6(spec2.filePath, "utf-8");
|
|
1209
1290
|
} catch {
|
|
1210
1291
|
continue;
|
|
1211
1292
|
}
|
|
@@ -1651,12 +1732,25 @@ function collectAllCodeBlocks(section) {
|
|
|
1651
1732
|
}
|
|
1652
1733
|
|
|
1653
1734
|
// src/core/check/spec-spec-checker.ts
|
|
1654
|
-
function checkSpecAgainstSpec(specs, markers, config) {
|
|
1735
|
+
function checkSpecAgainstSpec(specs, markers, config, deprecatedIds = /* @__PURE__ */ new Set()) {
|
|
1655
1736
|
const findings = [];
|
|
1656
1737
|
for (const specFile of specs.specFiles) {
|
|
1657
1738
|
for (const crossRef of specFile.crossRefs) {
|
|
1658
1739
|
for (const refId of crossRef.ids) {
|
|
1659
1740
|
if (!specs.allIds.has(refId)) {
|
|
1741
|
+
if (deprecatedIds.has(refId)) {
|
|
1742
|
+
if (config.deprecated) {
|
|
1743
|
+
findings.push({
|
|
1744
|
+
severity: "warning",
|
|
1745
|
+
code: "deprecated-ref",
|
|
1746
|
+
message: `Cross-reference '${refId}' (${crossRef.type}) targets a deprecated ID`,
|
|
1747
|
+
filePath: crossRef.filePath,
|
|
1748
|
+
line: crossRef.line,
|
|
1749
|
+
id: refId
|
|
1750
|
+
});
|
|
1751
|
+
}
|
|
1752
|
+
continue;
|
|
1753
|
+
}
|
|
1660
1754
|
findings.push({
|
|
1661
1755
|
severity: "error",
|
|
1662
1756
|
code: "broken-cross-ref",
|
|
@@ -1687,7 +1781,16 @@ function checkSpecAgainstSpec(specs, markers, config) {
|
|
|
1687
1781
|
}
|
|
1688
1782
|
}
|
|
1689
1783
|
}
|
|
1784
|
+
const deprecatedReqIds = /* @__PURE__ */ new Set();
|
|
1785
|
+
for (const id of deprecatedIds) {
|
|
1786
|
+
if (/^[A-Z][A-Z0-9]*-\d+(?:\.\d+)?$/.test(id)) {
|
|
1787
|
+
deprecatedReqIds.add(id);
|
|
1788
|
+
}
|
|
1789
|
+
}
|
|
1690
1790
|
for (const acId of reqAcIds) {
|
|
1791
|
+
if (deprecatedIds.has(acId)) continue;
|
|
1792
|
+
const parentMatch = /^([A-Z][A-Z0-9]*-\d+(?:\.\d+)?)_AC-\d+$/.exec(acId);
|
|
1793
|
+
if (parentMatch?.[1] && deprecatedReqIds.has(parentMatch[1])) continue;
|
|
1691
1794
|
if (!implementedAcIds.has(acId)) {
|
|
1692
1795
|
const loc = specs.idLocations.get(acId);
|
|
1693
1796
|
findings.push({
|
|
@@ -1748,8 +1851,10 @@ async function checkCommand(cliOptions) {
|
|
|
1748
1851
|
parseSpecs(config),
|
|
1749
1852
|
config.schemaEnabled ? loadRules(config.schemaDir) : Promise.resolve([])
|
|
1750
1853
|
]);
|
|
1751
|
-
const
|
|
1752
|
-
const
|
|
1854
|
+
const { deprecatedIds } = await parseDeprecated(".awa/specs");
|
|
1855
|
+
const codeSpecResult = config.specOnly ? { findings: [] } : checkCodeAgainstSpec(markers, specs, config, deprecatedIds);
|
|
1856
|
+
const specSpecResult = checkSpecAgainstSpec(specs, markers, config, deprecatedIds);
|
|
1857
|
+
const reservationResult = deprecatedIds.size > 0 ? checkReservations(specs, deprecatedIds) : { findings: [] };
|
|
1753
1858
|
if (config.fix) {
|
|
1754
1859
|
const fixResult = await fixMatrices(specs, config.crossRefPatterns);
|
|
1755
1860
|
if (fixResult.filesFixed > 0) {
|
|
@@ -1770,6 +1875,7 @@ async function checkCommand(cliOptions) {
|
|
|
1770
1875
|
...markers.findings,
|
|
1771
1876
|
...codeSpecResult.findings,
|
|
1772
1877
|
...specSpecResult.findings,
|
|
1878
|
+
...reservationResult.findings,
|
|
1773
1879
|
...schemaResult.findings
|
|
1774
1880
|
];
|
|
1775
1881
|
const allFindings = config.allowWarnings ? combinedFindings : combinedFindings.map(
|
|
@@ -1820,6 +1926,7 @@ function buildCheckConfig(fileConfig, cliOptions) {
|
|
|
1820
1926
|
const allowWarnings = cliOptions.allowWarnings === true ? true : typeof section?.["allow-warnings"] === "boolean" ? section["allow-warnings"] : DEFAULT_CHECK_CONFIG.allowWarnings;
|
|
1821
1927
|
const specOnly = cliOptions.specOnly === true ? true : typeof section?.["spec-only"] === "boolean" ? section["spec-only"] : DEFAULT_CHECK_CONFIG.specOnly;
|
|
1822
1928
|
const fix = cliOptions.fix === false ? false : DEFAULT_CHECK_CONFIG.fix;
|
|
1929
|
+
const deprecated = cliOptions.deprecated === true ? true : DEFAULT_CHECK_CONFIG.deprecated;
|
|
1823
1930
|
const extraSpecGlobs = toStringArray(section?.["extra-spec-globs"]) ?? [
|
|
1824
1931
|
...DEFAULT_CHECK_CONFIG.extraSpecGlobs
|
|
1825
1932
|
];
|
|
@@ -1842,7 +1949,8 @@ function buildCheckConfig(fileConfig, cliOptions) {
|
|
|
1842
1949
|
schemaEnabled,
|
|
1843
1950
|
allowWarnings,
|
|
1844
1951
|
specOnly,
|
|
1845
|
-
fix
|
|
1952
|
+
fix,
|
|
1953
|
+
deprecated
|
|
1846
1954
|
};
|
|
1847
1955
|
}
|
|
1848
1956
|
function toStringArray(value) {
|
|
@@ -1991,6 +2099,9 @@ var BatchRunner = class {
|
|
|
1991
2099
|
}
|
|
1992
2100
|
return results;
|
|
1993
2101
|
}
|
|
2102
|
+
// @awa-component: MULTI-Reporter
|
|
2103
|
+
// @awa-impl: MULTI-4_AC-1, MULTI-4_AC-2, MULTI-5_AC-1
|
|
2104
|
+
// @awa-impl: MULTI-8_AC-1, MULTI-9_AC-1, MULTI-11_AC-1
|
|
1994
2105
|
// Log a message prefixed with target name
|
|
1995
2106
|
logForTarget(targetName, message) {
|
|
1996
2107
|
logger.info(`[${targetName}] ${message}`);
|
|
@@ -2006,12 +2117,12 @@ var batchRunner = new BatchRunner();
|
|
|
2006
2117
|
|
|
2007
2118
|
// src/core/differ.ts
|
|
2008
2119
|
import { tmpdir } from "os";
|
|
2009
|
-
import { join as
|
|
2120
|
+
import { join as join5, relative as relative2 } from "path";
|
|
2010
2121
|
import { structuredPatch } from "diff";
|
|
2011
2122
|
import { isBinaryFile as detectBinaryFile } from "isbinaryfile";
|
|
2012
2123
|
|
|
2013
2124
|
// src/core/delete-list.ts
|
|
2014
|
-
import { join as
|
|
2125
|
+
import { join as join3 } from "path";
|
|
2015
2126
|
var DELETE_LIST_FILENAME = "_delete.txt";
|
|
2016
2127
|
function parseDeleteList(content) {
|
|
2017
2128
|
const entries = [];
|
|
@@ -2038,7 +2149,7 @@ function resolveDeleteList(entries, activeFeatures) {
|
|
|
2038
2149
|
return entries.filter((e) => e.features === void 0 || !e.features.some((f) => activeSet.has(f))).map((e) => e.path);
|
|
2039
2150
|
}
|
|
2040
2151
|
async function loadDeleteList(templatePath) {
|
|
2041
|
-
const deleteListPath =
|
|
2152
|
+
const deleteListPath = join3(templatePath, DELETE_LIST_FILENAME);
|
|
2042
2153
|
if (!await pathExists(deleteListPath)) {
|
|
2043
2154
|
return [];
|
|
2044
2155
|
}
|
|
@@ -2047,7 +2158,7 @@ async function loadDeleteList(templatePath) {
|
|
|
2047
2158
|
}
|
|
2048
2159
|
|
|
2049
2160
|
// src/core/generator.ts
|
|
2050
|
-
import { join as
|
|
2161
|
+
import { join as join4, relative } from "path";
|
|
2051
2162
|
|
|
2052
2163
|
// src/core/resolver.ts
|
|
2053
2164
|
import { MultiSelectPrompt } from "@clack/core";
|
|
@@ -2117,8 +2228,9 @@ ${chalk3.cyan(_BAR_END)}
|
|
|
2117
2228
|
var ConflictResolver = class {
|
|
2118
2229
|
// @awa-impl: GEN-4_AC-1, GEN-4_AC-2, GEN-4_AC-3
|
|
2119
2230
|
// @awa-impl: GEN-5_AC-1, GEN-5_AC-2, GEN-5_AC-3, GEN-5_AC-4, GEN-5_AC-5, GEN-5_AC-6, GEN-5_AC-7
|
|
2120
|
-
// @awa-impl: CLI-5_AC-2, CLI-5_AC-3
|
|
2121
|
-
// @awa-impl: GEN-6_AC-3
|
|
2231
|
+
// @awa-impl: CLI-5_AC-2, CLI-5_AC-3, CLI-12_AC-3
|
|
2232
|
+
// @awa-impl: GEN-6_AC-3, GEN-10_AC-3
|
|
2233
|
+
// @awa-impl: GEN-12_AC-3, GEN-12_AC-4, GEN-12_AC-5
|
|
2122
2234
|
async resolveBatch(conflicts, force, dryRun) {
|
|
2123
2235
|
const identicalPaths = conflicts.filter((c) => c.newContent === c.existingContent).map((c) => c.outputPath);
|
|
2124
2236
|
const differentFiles = conflicts.filter((c) => c.newContent !== c.existingContent);
|
|
@@ -2171,6 +2283,11 @@ var DeleteResolver = class {
|
|
|
2171
2283
|
* Prompt user to confirm which files to delete.
|
|
2172
2284
|
* Returns the list of absolute paths confirmed for deletion.
|
|
2173
2285
|
*/
|
|
2286
|
+
// @awa-impl: GEN-12_AC-3, GEN-12_AC-4, GEN-12_AC-5, CLI-12_AC-3
|
|
2287
|
+
// @awa-impl: CLI-5_AC-2, CLI-5_AC-3
|
|
2288
|
+
// @awa-impl: GEN-4_AC-1, GEN-4_AC-2, GEN-4_AC-3
|
|
2289
|
+
// @awa-impl: GEN-5_AC-1, GEN-5_AC-2, GEN-5_AC-3, GEN-5_AC-4, GEN-5_AC-5, GEN-5_AC-6, GEN-5_AC-7
|
|
2290
|
+
// @awa-impl: GEN-6_AC-3, GEN-10_AC-3
|
|
2174
2291
|
async resolveDeletes(candidates, force, dryRun) {
|
|
2175
2292
|
if (candidates.length === 0) {
|
|
2176
2293
|
return [];
|
|
@@ -2376,7 +2493,7 @@ var FileGenerator = class {
|
|
|
2376
2493
|
const generatedOutputPaths = new Set(filesToProcess.map((f) => f.outputFile));
|
|
2377
2494
|
const deleteCandidates = [];
|
|
2378
2495
|
for (const relPath of deleteList) {
|
|
2379
|
-
const absPath =
|
|
2496
|
+
const absPath = join4(outputPath, relPath);
|
|
2380
2497
|
if (generatedOutputPaths.has(absPath)) {
|
|
2381
2498
|
logger.warn(
|
|
2382
2499
|
`Delete list entry '${relPath}' conflicts with generated file \u2014 skipping deletion`
|
|
@@ -2438,7 +2555,7 @@ var FileGenerator = class {
|
|
|
2438
2555
|
// @awa-impl: GEN-1_AC-1, GEN-1_AC-2, GEN-1_AC-3
|
|
2439
2556
|
computeOutputPath(templatePath, templateRoot, outputRoot) {
|
|
2440
2557
|
const relativePath = relative(templateRoot, templatePath);
|
|
2441
|
-
return
|
|
2558
|
+
return join4(outputRoot, relativePath);
|
|
2442
2559
|
}
|
|
2443
2560
|
};
|
|
2444
2561
|
var fileGenerator = new FileGenerator();
|
|
@@ -2480,8 +2597,8 @@ var DiffEngine = class {
|
|
|
2480
2597
|
}
|
|
2481
2598
|
const files = [];
|
|
2482
2599
|
for (const relPath of generatedFiles) {
|
|
2483
|
-
const generatedFilePath =
|
|
2484
|
-
const targetFilePath =
|
|
2600
|
+
const generatedFilePath = join5(tempPath, relPath);
|
|
2601
|
+
const targetFilePath = join5(targetPath, relPath);
|
|
2485
2602
|
if (targetFiles.has(relPath)) {
|
|
2486
2603
|
const fileDiff = await this.compareFiles(generatedFilePath, targetFilePath, relPath);
|
|
2487
2604
|
files.push(fileDiff);
|
|
@@ -2545,7 +2662,7 @@ var DiffEngine = class {
|
|
|
2545
2662
|
const systemTemp = tmpdir();
|
|
2546
2663
|
const timestamp = Date.now();
|
|
2547
2664
|
const random = Math.random().toString(36).substring(2, 8);
|
|
2548
|
-
const tempPath =
|
|
2665
|
+
const tempPath = join5(systemTemp, `awa-diff-${timestamp}-${random}`);
|
|
2549
2666
|
await ensureDir(tempPath);
|
|
2550
2667
|
return tempPath;
|
|
2551
2668
|
}
|
|
@@ -2698,18 +2815,18 @@ function writeJsonOutput(data) {
|
|
|
2698
2815
|
// src/core/overlay.ts
|
|
2699
2816
|
import { cp } from "fs/promises";
|
|
2700
2817
|
import { tmpdir as tmpdir2 } from "os";
|
|
2701
|
-
import { join as
|
|
2818
|
+
import { join as join7 } from "path";
|
|
2702
2819
|
|
|
2703
2820
|
// src/core/template-resolver.ts
|
|
2704
2821
|
import { createHash } from "crypto";
|
|
2705
2822
|
import { rm } from "fs/promises";
|
|
2706
|
-
import { isAbsolute, join as
|
|
2823
|
+
import { isAbsolute, join as join6, resolve } from "path";
|
|
2707
2824
|
import degit from "degit";
|
|
2708
2825
|
var TemplateResolver = class {
|
|
2709
2826
|
// @awa-impl: CLI-3_AC-2, TPL-10_AC-1
|
|
2710
2827
|
async resolve(source, refresh) {
|
|
2711
2828
|
if (!source) {
|
|
2712
|
-
const bundledPath =
|
|
2829
|
+
const bundledPath = join6(getTemplateDir(), "awa");
|
|
2713
2830
|
return {
|
|
2714
2831
|
type: "bundled",
|
|
2715
2832
|
localPath: bundledPath,
|
|
@@ -2786,7 +2903,7 @@ var TemplateResolver = class {
|
|
|
2786
2903
|
getCachePath(source) {
|
|
2787
2904
|
const hash = createHash("sha256").update(source).digest("hex").substring(0, 16);
|
|
2788
2905
|
const cacheDir = getCacheDir();
|
|
2789
|
-
return
|
|
2906
|
+
return join6(cacheDir, hash);
|
|
2790
2907
|
}
|
|
2791
2908
|
};
|
|
2792
2909
|
var templateResolver = new TemplateResolver();
|
|
@@ -2803,7 +2920,7 @@ async function resolveOverlays(overlays, refresh) {
|
|
|
2803
2920
|
async function buildMergedDir(baseDir, overlayDirs) {
|
|
2804
2921
|
const timestamp = Date.now();
|
|
2805
2922
|
const random = Math.random().toString(36).substring(2, 8);
|
|
2806
|
-
const tempPath =
|
|
2923
|
+
const tempPath = join7(tmpdir2(), `awa-overlay-${timestamp}-${random}`);
|
|
2807
2924
|
await ensureDir(tempPath);
|
|
2808
2925
|
await cp(baseDir, tempPath, { recursive: true });
|
|
2809
2926
|
for (const overlayDir of overlayDirs) {
|
|
@@ -3088,13 +3205,13 @@ var FeaturesReporter = class {
|
|
|
3088
3205
|
var featuresReporter = new FeaturesReporter();
|
|
3089
3206
|
|
|
3090
3207
|
// src/core/features/scanner.ts
|
|
3091
|
-
import { readdir, readFile as
|
|
3092
|
-
import { join as
|
|
3208
|
+
import { readdir, readFile as readFile7 } from "fs/promises";
|
|
3209
|
+
import { join as join8, relative as relative3 } from "path";
|
|
3093
3210
|
var FEATURE_PATTERN = /it\.features\.(?:includes|indexOf)\(\s*['"]([^'"]+)['"]\s*\)/g;
|
|
3094
3211
|
async function* walkAllFiles(dir) {
|
|
3095
3212
|
const entries = await readdir(dir, { withFileTypes: true });
|
|
3096
3213
|
for (const entry of entries) {
|
|
3097
|
-
const fullPath =
|
|
3214
|
+
const fullPath = join8(dir, entry.name);
|
|
3098
3215
|
if (entry.isDirectory()) {
|
|
3099
3216
|
yield* walkAllFiles(fullPath);
|
|
3100
3217
|
} else if (entry.isFile()) {
|
|
@@ -3122,7 +3239,7 @@ var FeatureScanner = class {
|
|
|
3122
3239
|
for await (const filePath of walkAllFiles(templatePath)) {
|
|
3123
3240
|
filesScanned++;
|
|
3124
3241
|
try {
|
|
3125
|
-
const content = await
|
|
3242
|
+
const content = await readFile7(filePath, "utf-8");
|
|
3126
3243
|
const flags = this.extractFlags(content);
|
|
3127
3244
|
const relPath = relative3(templatePath, filePath);
|
|
3128
3245
|
for (const flag of flags) {
|
|
@@ -3314,21 +3431,21 @@ async function generateCommand(cliOptions) {
|
|
|
3314
3431
|
}
|
|
3315
3432
|
|
|
3316
3433
|
// src/core/merge/content-merger.ts
|
|
3317
|
-
import { readFile as
|
|
3318
|
-
import { basename as basename4, dirname, extname, join as
|
|
3434
|
+
import { readFile as readFile8, rename, writeFile as writeFile3 } from "fs/promises";
|
|
3435
|
+
import { basename as basename4, dirname, extname, join as join9 } from "path";
|
|
3319
3436
|
var MERGE_PREFIXES = ["FEAT", "REQ", "DESIGN", "API", "EXAMPLE", "TASK"];
|
|
3320
3437
|
function resolveMovePath(sourceFilePath, prefix, sourceCode, targetCode, existingPaths, plannedPaths) {
|
|
3321
3438
|
const dir = dirname(sourceFilePath);
|
|
3322
3439
|
const name = basename4(sourceFilePath);
|
|
3323
3440
|
const newName = name.replace(`${prefix}-${sourceCode}-`, `${prefix}-${targetCode}-`);
|
|
3324
|
-
const newPath =
|
|
3441
|
+
const newPath = join9(dir, newName);
|
|
3325
3442
|
if (!existingPaths.has(newPath) && !plannedPaths.has(newPath)) {
|
|
3326
3443
|
return newPath;
|
|
3327
3444
|
}
|
|
3328
3445
|
const ext = extname(newName);
|
|
3329
3446
|
const stem = newName.slice(0, -ext.length);
|
|
3330
3447
|
for (let i = 1; i < 1e3; i++) {
|
|
3331
|
-
const indexed =
|
|
3448
|
+
const indexed = join9(dir, `${stem}-${String(i).padStart(3, "0")}${ext}`);
|
|
3332
3449
|
if (!existingPaths.has(indexed) && !plannedPaths.has(indexed)) {
|
|
3333
3450
|
return indexed;
|
|
3334
3451
|
}
|
|
@@ -3387,7 +3504,7 @@ async function executeMoves(sourceCode, targetCode, specFiles, dryRun) {
|
|
|
3387
3504
|
docType: matchedPrefix
|
|
3388
3505
|
});
|
|
3389
3506
|
if (!dryRun) {
|
|
3390
|
-
const content = await
|
|
3507
|
+
const content = await readFile8(sf.filePath, "utf-8");
|
|
3391
3508
|
const updated = updateHeading(content, sourceCode, targetCode);
|
|
3392
3509
|
await rename(sf.filePath, targetPath);
|
|
3393
3510
|
if (updated !== content) {
|
|
@@ -3470,8 +3587,8 @@ function formatJson2(result) {
|
|
|
3470
3587
|
}
|
|
3471
3588
|
|
|
3472
3589
|
// src/core/merge/spec-mover.ts
|
|
3473
|
-
import { readFile as
|
|
3474
|
-
import { basename as basename5, dirname as dirname2, join as
|
|
3590
|
+
import { readFile as readFile9, rename as rename2 } from "fs/promises";
|
|
3591
|
+
import { basename as basename5, dirname as dirname2, join as join10 } from "path";
|
|
3475
3592
|
|
|
3476
3593
|
// src/core/merge/types.ts
|
|
3477
3594
|
var MergeError = class extends Error {
|
|
@@ -3504,7 +3621,7 @@ function planRenames(sourceCode, targetCode, specFiles) {
|
|
|
3504
3621
|
const oldSuffix = name.slice(oldPrefix.length);
|
|
3505
3622
|
const newSuffix = targetFeature ? replaceFeaturePart(oldSuffix, targetFeature) : oldSuffix;
|
|
3506
3623
|
const newName = `${prefix}-${targetCode}-${newSuffix}`;
|
|
3507
|
-
const newPath =
|
|
3624
|
+
const newPath = join10(dirname2(sf.filePath), newName);
|
|
3508
3625
|
renames.push({ oldPath: sf.filePath, newPath });
|
|
3509
3626
|
break;
|
|
3510
3627
|
}
|
|
@@ -3546,7 +3663,7 @@ function updateHeading2(content, sourceCode, targetCode) {
|
|
|
3546
3663
|
async function executeRenames(renames, sourceCode, targetCode, dryRun) {
|
|
3547
3664
|
if (dryRun) return renames;
|
|
3548
3665
|
for (const r of renames) {
|
|
3549
|
-
const content = await
|
|
3666
|
+
const content = await readFile9(r.oldPath, "utf-8");
|
|
3550
3667
|
const updated = updateHeading2(content, sourceCode, targetCode);
|
|
3551
3668
|
await rename2(r.oldPath, r.newPath);
|
|
3552
3669
|
if (updated !== content) {
|
|
@@ -3562,7 +3679,7 @@ async function findStaleRefs(sourceCode, filePaths) {
|
|
|
3562
3679
|
for (const filePath of filePaths) {
|
|
3563
3680
|
let content;
|
|
3564
3681
|
try {
|
|
3565
|
-
content = await
|
|
3682
|
+
content = await readFile9(filePath, "utf-8");
|
|
3566
3683
|
} catch {
|
|
3567
3684
|
continue;
|
|
3568
3685
|
}
|
|
@@ -3775,7 +3892,7 @@ async function mergeCommand(options) {
|
|
|
3775
3892
|
return 2;
|
|
3776
3893
|
}
|
|
3777
3894
|
if (options.renumber && !dryRun && !noChange) {
|
|
3778
|
-
const { renumberCommand: renumberCommand2 } = await import("./renumber-
|
|
3895
|
+
const { renumberCommand: renumberCommand2 } = await import("./renumber-LG6FUVOP.js");
|
|
3779
3896
|
await renumberCommand2({
|
|
3780
3897
|
code: options.targetCode,
|
|
3781
3898
|
dryRun: false,
|
|
@@ -3963,10 +4080,10 @@ import { intro as intro4, outro as outro4 } from "@clack/prompts";
|
|
|
3963
4080
|
|
|
3964
4081
|
// src/core/template-test/fixture-loader.ts
|
|
3965
4082
|
import { readdir as readdir2 } from "fs/promises";
|
|
3966
|
-
import { basename as basename6, extname as extname2, join as
|
|
4083
|
+
import { basename as basename6, extname as extname2, join as join11 } from "path";
|
|
3967
4084
|
import { parse } from "smol-toml";
|
|
3968
4085
|
async function discoverFixtures(templatePath) {
|
|
3969
|
-
const testsDir =
|
|
4086
|
+
const testsDir = join11(templatePath, "_tests");
|
|
3970
4087
|
let entries;
|
|
3971
4088
|
try {
|
|
3972
4089
|
const dirEntries = await readdir2(testsDir, { withFileTypes: true });
|
|
@@ -3976,7 +4093,7 @@ async function discoverFixtures(templatePath) {
|
|
|
3976
4093
|
}
|
|
3977
4094
|
const fixtures = [];
|
|
3978
4095
|
for (const filename of entries) {
|
|
3979
|
-
const filePath =
|
|
4096
|
+
const filePath = join11(testsDir, filename);
|
|
3980
4097
|
const fixture = await parseFixture(filePath);
|
|
3981
4098
|
fixtures.push(fixture);
|
|
3982
4099
|
}
|
|
@@ -4077,16 +4194,16 @@ function reportFixture(fixture) {
|
|
|
4077
4194
|
// src/core/template-test/runner.ts
|
|
4078
4195
|
import { mkdir as mkdir2, rm as rm3 } from "fs/promises";
|
|
4079
4196
|
import { tmpdir as tmpdir3 } from "os";
|
|
4080
|
-
import { join as
|
|
4197
|
+
import { join as join13 } from "path";
|
|
4081
4198
|
|
|
4082
4199
|
// src/core/template-test/snapshot.ts
|
|
4083
4200
|
import { mkdir, readdir as readdir3, rm as rm2 } from "fs/promises";
|
|
4084
|
-
import { join as
|
|
4201
|
+
import { join as join12, relative as relative4 } from "path";
|
|
4085
4202
|
async function walkRelative(dir, base) {
|
|
4086
4203
|
const results = [];
|
|
4087
4204
|
const entries = await readdir3(dir, { withFileTypes: true });
|
|
4088
4205
|
for (const entry of entries) {
|
|
4089
|
-
const fullPath =
|
|
4206
|
+
const fullPath = join12(dir, entry.name);
|
|
4090
4207
|
if (entry.isDirectory()) {
|
|
4091
4208
|
const sub = await walkRelative(fullPath, base);
|
|
4092
4209
|
results.push(...sub);
|
|
@@ -4103,8 +4220,8 @@ async function compareSnapshots(renderedDir, snapshotDir) {
|
|
|
4103
4220
|
const snapshotSet = new Set(snapshotFiles);
|
|
4104
4221
|
const renderedSet = new Set(renderedFiles);
|
|
4105
4222
|
for (const file of renderedFiles) {
|
|
4106
|
-
const renderedPath =
|
|
4107
|
-
const snapshotPath =
|
|
4223
|
+
const renderedPath = join12(renderedDir, file);
|
|
4224
|
+
const snapshotPath = join12(snapshotDir, file);
|
|
4108
4225
|
if (!snapshotSet.has(file)) {
|
|
4109
4226
|
results.push({ path: file, status: "missing-snapshot" });
|
|
4110
4227
|
continue;
|
|
@@ -4130,8 +4247,8 @@ async function updateSnapshots(renderedDir, snapshotDir) {
|
|
|
4130
4247
|
await mkdir(snapshotDir, { recursive: true });
|
|
4131
4248
|
const files = await walkRelative(renderedDir, renderedDir);
|
|
4132
4249
|
for (const file of files) {
|
|
4133
|
-
const srcPath =
|
|
4134
|
-
const destPath =
|
|
4250
|
+
const srcPath = join12(renderedDir, file);
|
|
4251
|
+
const destPath = join12(snapshotDir, file);
|
|
4135
4252
|
const content = await readTextFile(srcPath);
|
|
4136
4253
|
await writeTextFile(destPath, content);
|
|
4137
4254
|
}
|
|
@@ -4139,7 +4256,7 @@ async function updateSnapshots(renderedDir, snapshotDir) {
|
|
|
4139
4256
|
|
|
4140
4257
|
// src/core/template-test/runner.ts
|
|
4141
4258
|
async function runFixture(fixture, templatePath, options, presetDefinitions = {}) {
|
|
4142
|
-
const tempDir =
|
|
4259
|
+
const tempDir = join13(tmpdir3(), `awa-test-${fixture.name}-${Date.now()}`);
|
|
4143
4260
|
try {
|
|
4144
4261
|
await mkdir2(tempDir, { recursive: true });
|
|
4145
4262
|
const features = featureResolver.resolve({
|
|
@@ -4158,12 +4275,12 @@ async function runFixture(fixture, templatePath, options, presetDefinitions = {}
|
|
|
4158
4275
|
});
|
|
4159
4276
|
const fileResults = [];
|
|
4160
4277
|
for (const expectedFile of fixture.expectedFiles) {
|
|
4161
|
-
const fullPath =
|
|
4278
|
+
const fullPath = join13(tempDir, expectedFile);
|
|
4162
4279
|
const found = await pathExists(fullPath);
|
|
4163
4280
|
fileResults.push({ path: expectedFile, found });
|
|
4164
4281
|
}
|
|
4165
4282
|
const missingFiles = fileResults.filter((r) => !r.found);
|
|
4166
|
-
const snapshotDir =
|
|
4283
|
+
const snapshotDir = join13(templatePath, "_tests", fixture.name);
|
|
4167
4284
|
let snapshotResults = [];
|
|
4168
4285
|
if (options.updateSnapshots) {
|
|
4169
4286
|
await updateSnapshots(tempDir, snapshotDir);
|
|
@@ -4280,7 +4397,7 @@ async function testCommand(options) {
|
|
|
4280
4397
|
}
|
|
4281
4398
|
|
|
4282
4399
|
// src/core/trace/content-assembler.ts
|
|
4283
|
-
import { readFile as
|
|
4400
|
+
import { readFile as readFile10 } from "fs/promises";
|
|
4284
4401
|
var DEFAULT_BEFORE_CONTEXT = 5;
|
|
4285
4402
|
var DEFAULT_AFTER_CONTEXT = 20;
|
|
4286
4403
|
async function assembleContent(result, taskPath, contextOptions) {
|
|
@@ -4488,7 +4605,7 @@ async function cachedReadFile(cache, filePath) {
|
|
|
4488
4605
|
if (cache.has(filePath)) return cache.get(filePath) ?? null;
|
|
4489
4606
|
let content;
|
|
4490
4607
|
try {
|
|
4491
|
-
content = await
|
|
4608
|
+
content = await readFile10(filePath, "utf-8");
|
|
4492
4609
|
} catch {
|
|
4493
4610
|
content = null;
|
|
4494
4611
|
}
|
|
@@ -4838,7 +4955,7 @@ function pushToMap(map, key, value) {
|
|
|
4838
4955
|
}
|
|
4839
4956
|
|
|
4840
4957
|
// src/core/trace/input-resolver.ts
|
|
4841
|
-
import { readFile as
|
|
4958
|
+
import { readFile as readFile11 } from "fs/promises";
|
|
4842
4959
|
function resolveIds(ids, index) {
|
|
4843
4960
|
const resolved = [];
|
|
4844
4961
|
const warnings = [];
|
|
@@ -4854,7 +4971,7 @@ function resolveIds(ids, index) {
|
|
|
4854
4971
|
async function resolveTaskFile(taskPath, index) {
|
|
4855
4972
|
let content;
|
|
4856
4973
|
try {
|
|
4857
|
-
content = await
|
|
4974
|
+
content = await readFile11(taskPath, "utf-8");
|
|
4858
4975
|
} catch {
|
|
4859
4976
|
return { ids: [], warnings: [`Task file not found: ${taskPath}`] };
|
|
4860
4977
|
}
|
|
@@ -4905,7 +5022,7 @@ async function resolveTaskFile(taskPath, index) {
|
|
|
4905
5022
|
async function resolveSourceFile(filePath, index) {
|
|
4906
5023
|
let content;
|
|
4907
5024
|
try {
|
|
4908
|
-
content = await
|
|
5025
|
+
content = await readFile11(filePath, "utf-8");
|
|
4909
5026
|
} catch {
|
|
4910
5027
|
return { ids: [], warnings: [`Source file not found: ${filePath}`] };
|
|
4911
5028
|
}
|
|
@@ -5378,15 +5495,15 @@ function printUpdateWarning(log, result) {
|
|
|
5378
5495
|
}
|
|
5379
5496
|
|
|
5380
5497
|
// src/utils/update-check-cache.ts
|
|
5381
|
-
import { mkdir as mkdir3, readFile as
|
|
5498
|
+
import { mkdir as mkdir3, readFile as readFile12, writeFile as writeFile4 } from "fs/promises";
|
|
5382
5499
|
import { homedir } from "os";
|
|
5383
|
-
import { dirname as dirname3, join as
|
|
5384
|
-
var CACHE_DIR =
|
|
5385
|
-
var CACHE_FILE =
|
|
5500
|
+
import { dirname as dirname3, join as join14 } from "path";
|
|
5501
|
+
var CACHE_DIR = join14(homedir(), ".cache", "awa");
|
|
5502
|
+
var CACHE_FILE = join14(CACHE_DIR, "update-check.json");
|
|
5386
5503
|
var DEFAULT_INTERVAL_MS = 864e5;
|
|
5387
5504
|
async function shouldCheck(intervalMs = DEFAULT_INTERVAL_MS) {
|
|
5388
5505
|
try {
|
|
5389
|
-
const raw = await
|
|
5506
|
+
const raw = await readFile12(CACHE_FILE, "utf-8");
|
|
5390
5507
|
const data = JSON.parse(raw);
|
|
5391
5508
|
if (typeof data.timestamp !== "number" || typeof data.latestVersion !== "string") {
|
|
5392
5509
|
return true;
|
|
@@ -5501,6 +5618,10 @@ program.command("check").description(
|
|
|
5501
5618
|
).option(
|
|
5502
5619
|
"--no-fix",
|
|
5503
5620
|
"Skip regeneration of Requirements Traceability sections in DESIGN and TASK files"
|
|
5621
|
+
).option(
|
|
5622
|
+
"--deprecated",
|
|
5623
|
+
"Surface warnings for code markers and cross-references targeting deprecated IDs",
|
|
5624
|
+
false
|
|
5504
5625
|
).action(async (options, command) => {
|
|
5505
5626
|
const cliOptions = {
|
|
5506
5627
|
config: cliProvidedOption(command, options, "config"),
|
|
@@ -5511,7 +5632,8 @@ program.command("check").description(
|
|
|
5511
5632
|
summary: cliProvidedOption(command, options, "summary"),
|
|
5512
5633
|
allowWarnings: cliProvidedOption(command, options, "allowWarnings"),
|
|
5513
5634
|
specOnly: cliProvidedOption(command, options, "specOnly"),
|
|
5514
|
-
fix: cliProvidedOption(command, options, "fix")
|
|
5635
|
+
fix: cliProvidedOption(command, options, "fix"),
|
|
5636
|
+
deprecated: cliProvidedOption(command, options, "deprecated")
|
|
5515
5637
|
};
|
|
5516
5638
|
const exitCode = await checkCommand(cliOptions);
|
|
5517
5639
|
process.exit(exitCode);
|
|
@@ -5632,7 +5754,7 @@ var isDisabledByEnv = !!process.env.NO_UPDATE_NOTIFIER;
|
|
|
5632
5754
|
if (!isJsonOrSummary && isTTY && !isDisabledByEnv) {
|
|
5633
5755
|
updateCheckPromise = (async () => {
|
|
5634
5756
|
try {
|
|
5635
|
-
const { configLoader: configLoader2 } = await import("./config-
|
|
5757
|
+
const { configLoader: configLoader2 } = await import("./config-EP5JOR5X.js");
|
|
5636
5758
|
const configPath = process.argv.indexOf("-c") !== -1 ? process.argv[process.argv.indexOf("-c") + 1] : process.argv.indexOf("--config") !== -1 ? process.argv[process.argv.indexOf("--config") + 1] : void 0;
|
|
5637
5759
|
const fileConfig = await configLoader2.load(configPath ?? null);
|
|
5638
5760
|
const updateCheckConfig = fileConfig?.["update-check"];
|