@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.
Files changed (112) hide show
  1. package/dist/{chunk-GOIBZQFJ.js → chunk-4NC73OUR.js} +13 -1
  2. package/dist/chunk-4NC73OUR.js.map +1 -0
  3. package/dist/{chunk-2VUVSW6T.js → chunk-PC3PMV3K.js} +7 -4
  4. package/dist/{chunk-2VUVSW6T.js.map → chunk-PC3PMV3K.js.map} +1 -1
  5. package/dist/{config-SJLBJX77.js → config-EP5JOR5X.js} +2 -2
  6. package/dist/index.js +221 -99
  7. package/dist/index.js.map +1 -1
  8. package/dist/renumber-LG6FUVOP.js +9 -0
  9. package/package.json +1 -1
  10. package/templates/awa/.agent/skills/awa-spec-deprecate/SKILL.md +3 -0
  11. package/templates/awa/.agent/skills/awa-spec-merge/SKILL.md +3 -0
  12. package/templates/awa/.agent/skills/awa-spec-tidy/SKILL.md +3 -0
  13. package/templates/awa/.agent/workflows/awa-spec-deprecate.md +3 -0
  14. package/templates/awa/.agent/workflows/awa-spec-merge.md +3 -0
  15. package/templates/awa/.agent/workflows/awa-spec-tidy.md +3 -0
  16. package/templates/awa/.agents/skills/awa-spec-deprecate/SKILL.md +3 -0
  17. package/templates/awa/.agents/skills/awa-spec-merge/SKILL.md +3 -0
  18. package/templates/awa/.agents/skills/awa-spec-tidy/SKILL.md +3 -0
  19. package/templates/awa/.awa/.agent/schemas/DEPRECATED.schema.yaml +42 -0
  20. package/templates/awa/.claude/skills/awa-spec-deprecate/SKILL.md +3 -0
  21. package/templates/awa/.claude/skills/awa-spec-merge/SKILL.md +3 -0
  22. package/templates/awa/.claude/skills/awa-spec-tidy/SKILL.md +3 -0
  23. package/templates/awa/.codex/prompts/awa-spec-deprecate.md +3 -0
  24. package/templates/awa/.cursor/rules/awa-spec-deprecate.md +8 -0
  25. package/templates/awa/.gemini/commands/awa-spec-deprecate.md +3 -0
  26. package/templates/awa/.gemini/commands/awa-spec-merge.md +3 -0
  27. package/templates/awa/.gemini/commands/awa-spec-tidy.md +3 -0
  28. package/templates/awa/.gemini/skills/awa-spec-deprecate/SKILL.md +3 -0
  29. package/templates/awa/.gemini/skills/awa-spec-merge/SKILL.md +3 -0
  30. package/templates/awa/.gemini/skills/awa-spec-tidy/SKILL.md +3 -0
  31. package/templates/awa/.github/prompts/awa.spec-deprecate.prompt.md +8 -0
  32. package/templates/awa/.github/prompts/awa.spec-tidy.prompt.md +1 -1
  33. package/templates/awa/.github/skills/awa-spec-deprecate/SKILL.md +8 -0
  34. package/templates/awa/.github/skills/awa-spec-merge/SKILL.md +3 -0
  35. package/templates/awa/.github/skills/awa-spec-tidy/SKILL.md +3 -0
  36. package/templates/awa/.kilocode/skills/awa-spec-deprecate/SKILL.md +3 -0
  37. package/templates/awa/.kilocode/skills/awa-spec-merge/SKILL.md +3 -0
  38. package/templates/awa/.kilocode/skills/awa-spec-tidy/SKILL.md +3 -0
  39. package/templates/awa/.kilocode/workflows/awa-spec-deprecate.md +3 -0
  40. package/templates/awa/.kilocode/workflows/awa-spec-merge.md +3 -0
  41. package/templates/awa/.kilocode/{skills/spec-merge/SKILL.md → workflows/awa-spec-tidy.md} +1 -1
  42. package/templates/awa/.opencode/commands/awa-spec-deprecate.md +3 -0
  43. package/templates/awa/.opencode/commands/awa-spec-merge.md +3 -0
  44. package/templates/awa/.opencode/commands/{spec-merge.md → awa-spec-tidy.md} +1 -1
  45. package/templates/awa/.opencode/skills/awa-spec-deprecate/SKILL.md +3 -0
  46. package/templates/awa/.opencode/skills/awa-spec-merge/SKILL.md +3 -0
  47. package/templates/awa/.opencode/skills/awa-spec-tidy/SKILL.md +3 -0
  48. package/templates/awa/.qwen/commands/awa-spec-deprecate.md +3 -0
  49. package/templates/awa/.qwen/commands/awa-spec-merge.md +3 -0
  50. package/templates/awa/.qwen/commands/awa-spec-tidy.md +3 -0
  51. package/templates/awa/.qwen/skills/awa-spec-deprecate/SKILL.md +3 -0
  52. package/templates/awa/.qwen/skills/awa-spec-merge/SKILL.md +3 -0
  53. package/templates/awa/.qwen/skills/awa-spec-tidy/SKILL.md +3 -0
  54. package/templates/awa/.roo/skills/awa-spec-deprecate/SKILL.md +3 -0
  55. package/templates/awa/.roo/skills/awa-spec-merge/SKILL.md +3 -0
  56. package/templates/awa/.roo/skills/awa-spec-tidy/SKILL.md +3 -0
  57. package/templates/awa/.windsurf/skills/awa-spec-deprecate/SKILL.md +3 -0
  58. package/templates/awa/.windsurf/skills/awa-spec-merge/SKILL.md +3 -0
  59. package/templates/awa/.windsurf/skills/awa-spec-tidy/SKILL.md +3 -0
  60. package/templates/awa/_delete.txt +108 -0
  61. package/templates/awa/_partials/_cmd.awa-spec-deprecate.md +6 -0
  62. package/templates/awa/_partials/{_cmd.spec-tidy.md → _cmd.awa-spec-tidy.md} +1 -1
  63. package/templates/awa/_partials/_skill.awa-spec-deprecate.md +6 -0
  64. package/templates/awa/_partials/{_skill.spec-merge.md → _skill.awa-spec-merge.md} +1 -1
  65. package/templates/awa/_partials/{_skill.spec-tidy.md → _skill.awa-spec-tidy.md} +2 -2
  66. package/templates/awa/_partials/awa.code.md +5 -4
  67. package/templates/awa/_partials/awa.core.md +10 -6
  68. package/templates/awa/_partials/awa.spec-deprecate.md +86 -0
  69. package/templates/awa/_partials/awa.usage.md +16 -7
  70. package/templates/awa/_tests/claude/.claude/skills/awa-spec-deprecate/SKILL.md +88 -0
  71. package/templates/awa/_tests/claude/.claude/skills/{spec-merge → awa-spec-merge}/SKILL.md +1 -1
  72. package/templates/awa/_tests/{copilot/.github/skills/spec-tidy → claude/.claude/skills/awa-spec-tidy}/SKILL.md +1 -1
  73. package/templates/awa/_tests/claude/.claude/skills/awa-usage/SKILL.md +14 -5
  74. package/templates/awa/_tests/copilot/.github/prompts/awa.spec-deprecate.prompt.md +88 -0
  75. package/templates/awa/_tests/copilot/.github/skills/awa-spec-deprecate/SKILL.md +88 -0
  76. package/templates/awa/_tests/copilot/.github/skills/{spec-merge → awa-spec-merge}/SKILL.md +1 -1
  77. package/templates/awa/_tests/{claude/.claude/skills/spec-tidy → copilot/.github/skills/awa-spec-tidy}/SKILL.md +1 -1
  78. package/templates/awa/_tests/copilot/.github/skills/awa-usage/SKILL.md +14 -5
  79. package/dist/chunk-GOIBZQFJ.js.map +0 -1
  80. package/dist/renumber-TGDI47IS.js +0 -9
  81. package/templates/awa/.agent/skills/spec-merge/SKILL.md +0 -3
  82. package/templates/awa/.agent/skills/spec-tidy/SKILL.md +0 -3
  83. package/templates/awa/.agent/workflows/spec-merge.md +0 -3
  84. package/templates/awa/.agent/workflows/spec-tidy.md +0 -3
  85. package/templates/awa/.agents/skills/spec-merge/SKILL.md +0 -3
  86. package/templates/awa/.agents/skills/spec-tidy/SKILL.md +0 -3
  87. package/templates/awa/.claude/skills/spec-merge/SKILL.md +0 -3
  88. package/templates/awa/.claude/skills/spec-tidy/SKILL.md +0 -3
  89. package/templates/awa/.gemini/commands/spec-merge.md +0 -3
  90. package/templates/awa/.gemini/commands/spec-tidy.md +0 -3
  91. package/templates/awa/.gemini/skills/spec-merge/SKILL.md +0 -3
  92. package/templates/awa/.gemini/skills/spec-tidy/SKILL.md +0 -3
  93. package/templates/awa/.github/skills/spec-merge/SKILL.md +0 -3
  94. package/templates/awa/.github/skills/spec-tidy/SKILL.md +0 -3
  95. package/templates/awa/.kilocode/skills/spec-tidy/SKILL.md +0 -3
  96. package/templates/awa/.kilocode/workflows/spec-merge.md +0 -3
  97. package/templates/awa/.kilocode/workflows/spec-tidy.md +0 -3
  98. package/templates/awa/.opencode/commands/spec-tidy.md +0 -3
  99. package/templates/awa/.opencode/skills/spec-merge/SKILL.md +0 -3
  100. package/templates/awa/.opencode/skills/spec-tidy/SKILL.md +0 -3
  101. package/templates/awa/.qwen/commands/spec-merge.md +0 -3
  102. package/templates/awa/.qwen/commands/spec-tidy.md +0 -3
  103. package/templates/awa/.qwen/skills/spec-merge/SKILL.md +0 -3
  104. package/templates/awa/.qwen/skills/spec-tidy/SKILL.md +0 -3
  105. package/templates/awa/.roo/skills/spec-merge/SKILL.md +0 -3
  106. package/templates/awa/.roo/skills/spec-tidy/SKILL.md +0 -3
  107. package/templates/awa/.windsurf/skills/spec-merge/SKILL.md +0 -3
  108. package/templates/awa/.windsurf/skills/spec-tidy/SKILL.md +0 -3
  109. /package/dist/{config-SJLBJX77.js.map → config-EP5JOR5X.js.map} +0 -0
  110. /package/dist/{renumber-TGDI47IS.js.map → renumber-LG6FUVOP.js.map} +0 -0
  111. /package/templates/awa/_partials/{_cmd.spec-merge.md → _cmd.awa-spec-merge.md} +0 -0
  112. /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-2VUVSW6T.js";
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-GOIBZQFJ.js";
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.8.4",
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 checkCodeAgainstSpec(markers, specs, config) {
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 = /* @__PURE__ */ new Map();
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 readFile3, writeFile as writeFile2 } from "fs/promises";
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 readFile3(filePath, "utf-8");
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 readFile3(filePath, "utf-8");
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 readFile4 } from "fs/promises";
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 = join(schemaDir, "*.schema.yaml");
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 readFile4(filePath, "utf-8");
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 readFile5 } from "fs/promises";
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 readFile5(spec2.filePath, "utf-8");
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 codeSpecResult = config.specOnly ? { findings: [] } : checkCodeAgainstSpec(markers, specs, config);
1752
- const specSpecResult = checkSpecAgainstSpec(specs, markers, config);
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 join4, relative as relative2 } from "path";
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 join2 } from "path";
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 = join2(templatePath, DELETE_LIST_FILENAME);
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 join3, relative } from "path";
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 = join3(outputPath, relPath);
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 join3(outputRoot, relativePath);
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 = join4(tempPath, relPath);
2484
- const targetFilePath = join4(targetPath, relPath);
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 = join4(systemTemp, `awa-diff-${timestamp}-${random}`);
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 join6 } from "path";
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 join5, resolve } from "path";
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 = join5(getTemplateDir(), "awa");
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 join5(cacheDir, hash);
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 = join6(tmpdir2(), `awa-overlay-${timestamp}-${random}`);
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 readFile6 } from "fs/promises";
3092
- import { join as join7, relative as relative3 } from "path";
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 = join7(dir, entry.name);
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 readFile6(filePath, "utf-8");
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 readFile7, rename, writeFile as writeFile3 } from "fs/promises";
3318
- import { basename as basename4, dirname, extname, join as join8 } from "path";
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 = join8(dir, newName);
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 = join8(dir, `${stem}-${String(i).padStart(3, "0")}${ext}`);
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 readFile7(sf.filePath, "utf-8");
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 readFile8, rename as rename2 } from "fs/promises";
3474
- import { basename as basename5, dirname as dirname2, join as join9 } from "path";
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 = join9(dirname2(sf.filePath), newName);
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 readFile8(r.oldPath, "utf-8");
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 readFile8(filePath, "utf-8");
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-TGDI47IS.js");
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 join10 } from "path";
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 = join10(templatePath, "_tests");
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 = join10(testsDir, filename);
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 join12 } from "path";
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 join11, relative as relative4 } from "path";
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 = join11(dir, entry.name);
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 = join11(renderedDir, file);
4107
- const snapshotPath = join11(snapshotDir, file);
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 = join11(renderedDir, file);
4134
- const destPath = join11(snapshotDir, file);
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 = join12(tmpdir3(), `awa-test-${fixture.name}-${Date.now()}`);
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 = join12(tempDir, expectedFile);
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 = join12(templatePath, "_tests", fixture.name);
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 readFile9 } from "fs/promises";
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 readFile9(filePath, "utf-8");
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 readFile10 } from "fs/promises";
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 readFile10(taskPath, "utf-8");
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 readFile10(filePath, "utf-8");
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 readFile11, writeFile as writeFile4 } from "fs/promises";
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 join13 } from "path";
5384
- var CACHE_DIR = join13(homedir(), ".cache", "awa");
5385
- var CACHE_FILE = join13(CACHE_DIR, "update-check.json");
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 readFile11(CACHE_FILE, "utf-8");
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-SJLBJX77.js");
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"];