@rasensio/aidlc 1.16.0 → 1.18.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 (235) hide show
  1. package/README.md +9 -1
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +4 -0
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/compliance.d.ts +36 -0
  6. package/dist/commands/compliance.d.ts.map +1 -0
  7. package/dist/commands/compliance.js +275 -0
  8. package/dist/commands/compliance.js.map +1 -0
  9. package/dist/commands/constitution.d.ts +26 -0
  10. package/dist/commands/constitution.d.ts.map +1 -0
  11. package/dist/commands/constitution.js +145 -0
  12. package/dist/commands/constitution.js.map +1 -0
  13. package/dist/commands/cost.d.ts.map +1 -1
  14. package/dist/commands/cost.js +54 -35
  15. package/dist/commands/cost.js.map +1 -1
  16. package/dist/commands/doctor.js +7 -0
  17. package/dist/commands/doctor.js.map +1 -1
  18. package/dist/commands/gate.d.ts.map +1 -1
  19. package/dist/commands/gate.js +13 -0
  20. package/dist/commands/gate.js.map +1 -1
  21. package/dist/commands/init.d.ts +14 -0
  22. package/dist/commands/init.d.ts.map +1 -1
  23. package/dist/commands/init.js +140 -17
  24. package/dist/commands/init.js.map +1 -1
  25. package/dist/commands/metrics.d.ts.map +1 -1
  26. package/dist/commands/metrics.js +6 -1
  27. package/dist/commands/metrics.js.map +1 -1
  28. package/dist/commands/review.d.ts +2 -27
  29. package/dist/commands/review.d.ts.map +1 -1
  30. package/dist/commands/review.js +10 -166
  31. package/dist/commands/review.js.map +1 -1
  32. package/dist/commands/status.d.ts.map +1 -1
  33. package/dist/commands/status.js +7 -0
  34. package/dist/commands/status.js.map +1 -1
  35. package/dist/commands/transition.d.ts.map +1 -1
  36. package/dist/commands/transition.js +24 -1
  37. package/dist/commands/transition.js.map +1 -1
  38. package/dist/compile/adapters/claude-code.d.ts.map +1 -1
  39. package/dist/compile/adapters/claude-code.js +5 -69
  40. package/dist/compile/adapters/claude-code.js.map +1 -1
  41. package/dist/compile/adapters/codex.d.ts +22 -1
  42. package/dist/compile/adapters/codex.d.ts.map +1 -1
  43. package/dist/compile/adapters/codex.js +61 -27
  44. package/dist/compile/adapters/codex.js.map +1 -1
  45. package/dist/compile/adapters/copilot.d.ts +64 -0
  46. package/dist/compile/adapters/copilot.d.ts.map +1 -0
  47. package/dist/compile/adapters/copilot.js +272 -0
  48. package/dist/compile/adapters/copilot.js.map +1 -0
  49. package/dist/compile/adapters/cursor.d.ts.map +1 -1
  50. package/dist/compile/adapters/cursor.js +2 -19
  51. package/dist/compile/adapters/cursor.js.map +1 -1
  52. package/dist/compile/adapters/index.d.ts.map +1 -1
  53. package/dist/compile/adapters/index.js +2 -0
  54. package/dist/compile/adapters/index.js.map +1 -1
  55. package/dist/compile/adapters/kiro.d.ts.map +1 -1
  56. package/dist/compile/adapters/kiro.js +1 -19
  57. package/dist/compile/adapters/kiro.js.map +1 -1
  58. package/dist/compile/adapters/windsurf.d.ts.map +1 -1
  59. package/dist/compile/adapters/windsurf.js +2 -1
  60. package/dist/compile/adapters/windsurf.js.map +1 -1
  61. package/dist/compile/capability-resolve.d.ts +34 -0
  62. package/dist/compile/capability-resolve.d.ts.map +1 -0
  63. package/dist/compile/capability-resolve.js +85 -0
  64. package/dist/compile/capability-resolve.js.map +1 -0
  65. package/dist/compile/guidance-install.d.ts +16 -19
  66. package/dist/compile/guidance-install.d.ts.map +1 -1
  67. package/dist/compile/guidance-install.js +26 -111
  68. package/dist/compile/guidance-install.js.map +1 -1
  69. package/dist/compile/layer-install.d.ts +122 -0
  70. package/dist/compile/layer-install.d.ts.map +1 -0
  71. package/dist/compile/layer-install.js +195 -0
  72. package/dist/compile/layer-install.js.map +1 -0
  73. package/dist/compile/limits.d.ts +10 -0
  74. package/dist/compile/limits.d.ts.map +1 -1
  75. package/dist/compile/limits.js +10 -0
  76. package/dist/compile/limits.js.map +1 -1
  77. package/dist/compile/loaders.d.ts +14 -0
  78. package/dist/compile/loaders.d.ts.map +1 -1
  79. package/dist/compile/loaders.js +23 -18
  80. package/dist/compile/loaders.js.map +1 -1
  81. package/dist/compile/naming.d.ts +23 -0
  82. package/dist/compile/naming.d.ts.map +1 -1
  83. package/dist/compile/naming.js +19 -1
  84. package/dist/compile/naming.js.map +1 -1
  85. package/dist/compile/skill-format.d.ts +39 -0
  86. package/dist/compile/skill-format.d.ts.map +1 -0
  87. package/dist/compile/skill-format.js +50 -0
  88. package/dist/compile/skill-format.js.map +1 -0
  89. package/dist/compliance/check.d.ts +79 -0
  90. package/dist/compliance/check.d.ts.map +1 -0
  91. package/dist/compliance/check.js +224 -0
  92. package/dist/compliance/check.js.map +1 -0
  93. package/dist/compliance/config.d.ts +91 -0
  94. package/dist/compliance/config.d.ts.map +1 -0
  95. package/dist/compliance/config.js +173 -0
  96. package/dist/compliance/config.js.map +1 -0
  97. package/dist/compliance/findings.d.ts +70 -0
  98. package/dist/compliance/findings.d.ts.map +1 -0
  99. package/dist/compliance/findings.js +132 -0
  100. package/dist/compliance/findings.js.map +1 -0
  101. package/dist/compliance/gate-criterion.d.ts +87 -0
  102. package/dist/compliance/gate-criterion.d.ts.map +1 -0
  103. package/dist/compliance/gate-criterion.js +168 -0
  104. package/dist/compliance/gate-criterion.js.map +1 -0
  105. package/dist/compliance/install.d.ts +135 -0
  106. package/dist/compliance/install.d.ts.map +1 -0
  107. package/dist/compliance/install.js +291 -0
  108. package/dist/compliance/install.js.map +1 -0
  109. package/dist/compliance/report.d.ts +144 -0
  110. package/dist/compliance/report.d.ts.map +1 -0
  111. package/dist/compliance/report.js +347 -0
  112. package/dist/compliance/report.js.map +1 -0
  113. package/dist/compliance/resolver.d.ts +65 -0
  114. package/dist/compliance/resolver.d.ts.map +1 -0
  115. package/dist/compliance/resolver.js +176 -0
  116. package/dist/compliance/resolver.js.map +1 -0
  117. package/dist/compliance/schema.d.ts +74 -0
  118. package/dist/compliance/schema.d.ts.map +1 -0
  119. package/dist/compliance/schema.js +474 -0
  120. package/dist/compliance/schema.js.map +1 -0
  121. package/dist/compliance/types.d.ts +140 -0
  122. package/dist/compliance/types.d.ts.map +1 -0
  123. package/dist/compliance/types.js +29 -0
  124. package/dist/compliance/types.js.map +1 -0
  125. package/dist/constitution/check.d.ts +22 -0
  126. package/dist/constitution/check.d.ts.map +1 -0
  127. package/dist/constitution/check.js +89 -0
  128. package/dist/constitution/check.js.map +1 -0
  129. package/dist/constitution/docx.d.ts +51 -0
  130. package/dist/constitution/docx.d.ts.map +1 -0
  131. package/dist/constitution/docx.js +157 -0
  132. package/dist/constitution/docx.js.map +1 -0
  133. package/dist/constitution/entries.d.ts +27 -0
  134. package/dist/constitution/entries.d.ts.map +1 -0
  135. package/dist/constitution/entries.js +65 -0
  136. package/dist/constitution/entries.js.map +1 -0
  137. package/dist/constitution/extract.d.ts +34 -0
  138. package/dist/constitution/extract.d.ts.map +1 -0
  139. package/dist/constitution/extract.js +117 -0
  140. package/dist/constitution/extract.js.map +1 -0
  141. package/dist/constitution/snapshot.d.ts +47 -0
  142. package/dist/constitution/snapshot.d.ts.map +1 -0
  143. package/dist/constitution/snapshot.js +159 -0
  144. package/dist/constitution/snapshot.js.map +1 -0
  145. package/dist/constitution/statements.d.ts +37 -0
  146. package/dist/constitution/statements.d.ts.map +1 -0
  147. package/dist/constitution/statements.js +64 -0
  148. package/dist/constitution/statements.js.map +1 -0
  149. package/dist/constitution/types.d.ts +80 -0
  150. package/dist/constitution/types.d.ts.map +1 -0
  151. package/dist/constitution/types.js +9 -0
  152. package/dist/constitution/types.js.map +1 -0
  153. package/dist/core/gate.d.ts +10 -0
  154. package/dist/core/gate.d.ts.map +1 -1
  155. package/dist/core/gate.js.map +1 -1
  156. package/dist/core/paths.d.ts +48 -0
  157. package/dist/core/paths.d.ts.map +1 -0
  158. package/dist/core/paths.js +57 -0
  159. package/dist/core/paths.js.map +1 -0
  160. package/dist/core/types.d.ts +13 -2
  161. package/dist/core/types.d.ts.map +1 -1
  162. package/dist/cost/hooks/registry.d.ts +44 -0
  163. package/dist/cost/hooks/registry.d.ts.map +1 -0
  164. package/dist/cost/hooks/registry.js +66 -0
  165. package/dist/cost/hooks/registry.js.map +1 -0
  166. package/dist/cost/pin.d.ts +63 -0
  167. package/dist/cost/pin.d.ts.map +1 -0
  168. package/dist/cost/pin.js +95 -0
  169. package/dist/cost/pin.js.map +1 -0
  170. package/dist/cost/providers/claude-code.d.ts +9 -2
  171. package/dist/cost/providers/claude-code.d.ts.map +1 -1
  172. package/dist/cost/providers/claude-code.js +10 -5
  173. package/dist/cost/providers/claude-code.js.map +1 -1
  174. package/dist/cost/providers/codex.d.ts +107 -0
  175. package/dist/cost/providers/codex.d.ts.map +1 -0
  176. package/dist/cost/providers/codex.js +283 -0
  177. package/dist/cost/providers/codex.js.map +1 -0
  178. package/dist/cost/providers/index.d.ts.map +1 -1
  179. package/dist/cost/providers/index.js +6 -0
  180. package/dist/cost/providers/index.js.map +1 -1
  181. package/dist/cost/rates.d.ts.map +1 -1
  182. package/dist/cost/rates.js +14 -0
  183. package/dist/cost/rates.js.map +1 -1
  184. package/dist/cost/report.d.ts +23 -1
  185. package/dist/cost/report.d.ts.map +1 -1
  186. package/dist/cost/report.js +26 -5
  187. package/dist/cost/report.js.map +1 -1
  188. package/dist/cost/sessions.d.ts +10 -1
  189. package/dist/cost/sessions.d.ts.map +1 -1
  190. package/dist/cost/sessions.js +10 -2
  191. package/dist/cost/sessions.js.map +1 -1
  192. package/dist/cost/sync.d.ts.map +1 -1
  193. package/dist/cost/sync.js +190 -5
  194. package/dist/cost/sync.js.map +1 -1
  195. package/dist/doctor/migrations/compliance-pack-drift.d.ts +62 -0
  196. package/dist/doctor/migrations/compliance-pack-drift.d.ts.map +1 -0
  197. package/dist/doctor/migrations/compliance-pack-drift.js +255 -0
  198. package/dist/doctor/migrations/compliance-pack-drift.js.map +1 -0
  199. package/dist/doctor/migrations/index.d.ts.map +1 -1
  200. package/dist/doctor/migrations/index.js +11 -0
  201. package/dist/doctor/migrations/index.js.map +1 -1
  202. package/dist/doctor/migrations/legacy-cost-hooks.d.ts.map +1 -1
  203. package/dist/doctor/migrations/legacy-cost-hooks.js +7 -4
  204. package/dist/doctor/migrations/legacy-cost-hooks.js.map +1 -1
  205. package/dist/doctor/migrations/missing-cost-shim.d.ts.map +1 -1
  206. package/dist/doctor/migrations/missing-cost-shim.js +5 -4
  207. package/dist/doctor/migrations/missing-cost-shim.js.map +1 -1
  208. package/dist/doctor/migrations/outdated-cost-hooks.d.ts.map +1 -1
  209. package/dist/doctor/migrations/outdated-cost-hooks.js +7 -4
  210. package/dist/doctor/migrations/outdated-cost-hooks.js.map +1 -1
  211. package/dist/doctor/migrations/stale-idea-skill.d.ts.map +1 -1
  212. package/dist/doctor/migrations/stale-idea-skill.js +2 -1
  213. package/dist/doctor/migrations/stale-idea-skill.js.map +1 -1
  214. package/dist/doctor/runner.js +14 -0
  215. package/dist/doctor/runner.js.map +1 -1
  216. package/dist/doctor/types.d.ts +35 -3
  217. package/dist/doctor/types.d.ts.map +1 -1
  218. package/dist/menu/roster.d.ts.map +1 -1
  219. package/dist/menu/roster.js +5 -0
  220. package/dist/menu/roster.js.map +1 -1
  221. package/dist/metrics/report.d.ts.map +1 -1
  222. package/dist/metrics/report.js +11 -2
  223. package/dist/metrics/report.js.map +1 -1
  224. package/dist/operational/packagers.d.ts.map +1 -1
  225. package/dist/operational/packagers.js +32 -0
  226. package/dist/operational/packagers.js.map +1 -1
  227. package/dist/review/findings-parser.d.ts +92 -0
  228. package/dist/review/findings-parser.d.ts.map +1 -0
  229. package/dist/review/findings-parser.js +196 -0
  230. package/dist/review/findings-parser.js.map +1 -0
  231. package/dist/setup/setup-compute.d.ts +10 -15
  232. package/dist/setup/setup-compute.d.ts.map +1 -1
  233. package/dist/setup/setup-compute.js +39 -0
  234. package/dist/setup/setup-compute.js.map +1 -1
  235. package/package.json +2 -2
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Capability-map validation and activation-directive resolution.
3
+ *
4
+ * Extracted verbatim from `adapters/claude-code.ts`, which held the only
5
+ * validating implementation, at the moment a second adapter (copilot) needed the
6
+ * same behaviour. The one generalisation is that `resolveActivation` now takes
7
+ * the platform id instead of hardcoding `'claude-code'` when reading
8
+ * `native_mode_hint`.
9
+ *
10
+ * Note for anyone adding a third consumer: `adapters/codex.ts` has its own
11
+ * `getCapabilityDirective`, which does NOT validate the map and emits no
12
+ * warnings for a malformed one. It is deliberately left alone here — migrating it
13
+ * would change codex's emitted warnings, which is a behaviour change, not an
14
+ * extraction. Prefer this module for anything new.
15
+ *
16
+ * Requirements: copilot-platform-support/AC-24
17
+ *
18
+ * @module
19
+ */
20
+ /** Valid lifecycle phase names for capability map validation. */
21
+ const VALID_PHASES = new Set([
22
+ 'ideation',
23
+ 'requirements',
24
+ 'design',
25
+ 'implementation',
26
+ 'testing',
27
+ 'deployment',
28
+ 'maintenance',
29
+ ]);
30
+ /**
31
+ * Validate and sanitize a capability map. Returns a clean map with only valid
32
+ * entries, or null if the map is entirely unusable. Emits warnings for problems.
33
+ */
34
+ export function validateCapabilityMap(caps, warnings) {
35
+ const phaseMap = new Map();
36
+ if (!caps.capabilities || typeof caps.capabilities !== 'object') {
37
+ warnings.push(`capability map for '${caps.platform}': malformed capabilities object; proceeding capability-free`);
38
+ return null;
39
+ }
40
+ let hasValidEntry = false;
41
+ for (const [capName, entry] of Object.entries(caps.capabilities)) {
42
+ if (!entry || typeof entry !== 'object') {
43
+ warnings.push(`capability map '${caps.platform}': capability '${capName}' is malformed; skipping`);
44
+ continue;
45
+ }
46
+ if (!Array.isArray(entry.phases)) {
47
+ warnings.push(`capability map '${caps.platform}': capability '${capName}' has invalid phases; skipping`);
48
+ continue;
49
+ }
50
+ if (!entry.activation || typeof entry.activation !== 'string') {
51
+ warnings.push(`capability map '${caps.platform}': capability '${capName}' missing activation text; skipping`);
52
+ continue;
53
+ }
54
+ for (const phase of entry.phases) {
55
+ if (!VALID_PHASES.has(phase)) {
56
+ warnings.push(`capability map '${caps.platform}': unknown phase '${phase}' in capability '${capName}'; skipping phase`);
57
+ continue;
58
+ }
59
+ phaseMap.set(phase, entry);
60
+ hasValidEntry = true;
61
+ }
62
+ }
63
+ return hasValidEntry ? phaseMap : null;
64
+ }
65
+ /**
66
+ * Derive the activation directive for a skill given the resolution precedence:
67
+ *
68
+ * 1. `skill.meta.native_mode_hint[platform]` → use it
69
+ * 2. Capability map entry covering the skill's phase → its activation text
70
+ * 3. Otherwise → null, meaning full structured guidance with no native reference
71
+ */
72
+ export function resolveActivation(skill, platform, phaseMap) {
73
+ const hint = skill.meta.native_mode_hint?.[platform];
74
+ if (hint) {
75
+ return hint;
76
+ }
77
+ if (phaseMap) {
78
+ const entry = phaseMap.get(skill.meta.phase);
79
+ if (entry) {
80
+ return entry.activation;
81
+ }
82
+ }
83
+ return null;
84
+ }
85
+ //# sourceMappingURL=capability-resolve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capability-resolve.js","sourceRoot":"","sources":["../../src/compile/capability-resolve.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAUH,iEAAiE;AACjE,MAAM,YAAY,GAAwB,IAAI,GAAG,CAAS;IACxD,UAAU;IACV,cAAc;IACd,QAAQ;IACR,gBAAgB;IAChB,SAAS;IACT,YAAY;IACZ,aAAa;CACd,CAAC,CAAC;AAEH;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CACnC,IAAmB,EACnB,QAAkB;IAElB,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA8B,CAAC;IAEvD,IAAI,CAAC,IAAI,CAAC,YAAY,IAAI,OAAO,IAAI,CAAC,YAAY,KAAK,QAAQ,EAAE,CAAC;QAChE,QAAQ,CAAC,IAAI,CACX,uBAAuB,IAAI,CAAC,QAAQ,8DAA8D,CACnG,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,aAAa,GAAG,KAAK,CAAC;IAE1B,KAAK,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;QACjE,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YACxC,QAAQ,CAAC,IAAI,CACX,mBAAmB,IAAI,CAAC,QAAQ,kBAAkB,OAAO,0BAA0B,CACpF,CAAC;YACF,SAAS;QACX,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;YACjC,QAAQ,CAAC,IAAI,CACX,mBAAmB,IAAI,CAAC,QAAQ,kBAAkB,OAAO,gCAAgC,CAC1F,CAAC;YACF,SAAS;QACX,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,UAAU,IAAI,OAAO,KAAK,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;YAC9D,QAAQ,CAAC,IAAI,CACX,mBAAmB,IAAI,CAAC,QAAQ,kBAAkB,OAAO,qCAAqC,CAC/F,CAAC;YACF,SAAS;QACX,CAAC;QAED,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YACjC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC7B,QAAQ,CAAC,IAAI,CACX,mBAAmB,IAAI,CAAC,QAAQ,qBAAqB,KAAK,oBAAoB,OAAO,mBAAmB,CACzG,CAAC;gBACF,SAAS;YACX,CAAC;YACD,QAAQ,CAAC,GAAG,CAAC,KAAkB,EAAE,KAAK,CAAC,CAAC;YACxC,aAAa,GAAG,IAAI,CAAC;QACvB,CAAC;IACH,CAAC;IAED,OAAO,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;AACzC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAC/B,KAAY,EACZ,QAAoB,EACpB,QAAgD;IAEhD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC,QAAQ,CAAC,CAAC;IACrD,IAAI,IAAI,EAAE,CAAC;QACT,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC7C,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,KAAK,CAAC,UAAU,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -13,27 +13,24 @@
13
13
  * replaced so registrations the project owns (notably the retrospective-fed
14
14
  * `lessons` layer) survive.
15
15
  *
16
+ * The mechanics now live in `./layer-install.ts`, which takes an explicit entry
17
+ * list. This module is the framework's caller of it: it passes the content
18
+ * package's whole guidance index and the bundled-body comparison. Compliance
19
+ * packs deliberately do **not** come through here — a pack layer registered in
20
+ * the content guidance index would be installed by every caller of this function,
21
+ * and one of those callers is a `safe`-tier doctor migration that auto-applies
22
+ * without prompting (compliance-packs/AC-53, AC-54).
23
+ *
16
24
  * Requirements: guidance-layers-never-resolve/AC-1, AC-3, AC-4
17
25
  */
18
- /** Outcome of an installation pass. */
19
- export interface GuidanceInstallReport {
20
- /** Layer names newly written to disk. */
21
- installed: string[];
22
- /**
23
- * Repo-relative paths newly written, including `index.yaml` when it changed.
24
- * Kept alongside `installed` so callers never have to reconstruct a filename
25
- * from a layer name — the two differ whenever a layer registers a filename
26
- * that is not `<name>.md`.
27
- */
28
- installedPaths: string[];
29
- /** Layer names already present with identical content. */
30
- alreadyCurrent: string[];
31
- /** Layer names present but locally edited — left untouched. */
32
- locallyModified: string[];
33
- /** True when the project's `index.yaml` gained entries. */
34
- indexUpdated: boolean;
35
- warnings: string[];
36
- }
26
+ import { type LayerInstallReport } from './layer-install.js';
27
+ /**
28
+ * Outcome of an installation pass.
29
+ *
30
+ * Structurally identical to `LayerInstallReport`; kept as a named alias because
31
+ * `init`, `update` and the doctor migration all import this name.
32
+ */
33
+ export type GuidanceInstallReport = LayerInstallReport;
37
34
  /**
38
35
  * Install every guidance layer registered in the content package into a project.
39
36
  *
@@ -1 +1 @@
1
- {"version":3,"file":"guidance-install.d.ts","sourceRoot":"","sources":["../../src/compile/guidance-install.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAcH,uCAAuC;AACvC,MAAM,WAAW,qBAAqB;IACpC,yCAAyC;IACzC,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB;;;;;OAKG;IACH,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,0DAA0D;IAC1D,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,+DAA+D;IAC/D,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,2DAA2D;IAC3D,YAAY,EAAE,OAAO,CAAC;IACtB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAuDD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GAC9B,qBAAqB,CAgFvB;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,qBAAqB,GAAG,MAAM,GAAG,IAAI,CASrF"}
1
+ {"version":3,"file":"guidance-install.d.ts","sourceRoot":"","sources":["../../src/compile/guidance-install.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAIH,OAAO,EAIL,KAAK,kBAAkB,EACxB,MAAM,oBAAoB,CAAC;AAE5B;;;;;GAKG;AACH,MAAM,MAAM,qBAAqB,GAAG,kBAAkB,CAAC;AAEvD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GAC9B,qBAAqB,CAuBvB;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,qBAAqB,GAAG,MAAM,GAAG,IAAI,CASrF"}
@@ -13,58 +13,18 @@
13
13
  * replaced so registrations the project owns (notably the retrospective-fed
14
14
  * `lessons` layer) survive.
15
15
  *
16
- * Requirements: guidance-layers-never-resolve/AC-1, AC-3, AC-4
17
- */
18
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
19
- import { isAbsolute, join, resolve, sep } from 'node:path';
20
- import { parse as parseYaml } from 'yaml';
21
- import { serializeYaml } from '../state/yaml-helpers.js';
22
- /**
23
- * Read and validate a guidance `index.yaml`, returning its entries.
24
- *
25
- * @returns Entries, or null when the file is absent or unusable.
26
- */
27
- function readIndexEntries(indexPath) {
28
- if (!existsSync(indexPath)) {
29
- return null;
30
- }
31
- let parsed;
32
- try {
33
- parsed = parseYaml(readFileSync(indexPath, 'utf8'));
34
- }
35
- catch {
36
- return null;
37
- }
38
- if (typeof parsed !== 'object' || parsed === null || !('layers' in parsed)) {
39
- return null;
40
- }
41
- const layers = parsed.layers;
42
- if (!Array.isArray(layers)) {
43
- return null;
44
- }
45
- return layers.filter((e) => typeof e === 'object' &&
46
- e !== null &&
47
- typeof e.name === 'string' &&
48
- typeof e.file === 'string');
49
- }
50
- /**
51
- * True when `file` is a safe relative name that stays inside `dir`.
16
+ * The mechanics now live in `./layer-install.ts`, which takes an explicit entry
17
+ * list. This module is the framework's caller of it: it passes the content
18
+ * package's whole guidance index and the bundled-body comparison. Compliance
19
+ * packs deliberately do **not** come through here — a pack layer registered in
20
+ * the content guidance index would be installed by every caller of this function,
21
+ * and one of those callers is a `safe`-tier doctor migration that auto-applies
22
+ * without prompting (compliance-packs/AC-53, AC-54).
52
23
  *
53
- * `file` comes out of a YAML index, so it is data, not a constant: an absolute
54
- * path or a `..` segment would make `join` escape `.aidlc/guidance/` and, on the
55
- * target side, write outside it. Checked lexically **before** any disk access —
56
- * ordering this after an existence check is how a sibling defect in this repo
57
- * turned an error path into an out-of-bounds oracle.
24
+ * Requirements: guidance-layers-never-resolve/AC-1, AC-3, AC-4
58
25
  */
59
- function isContainedRelative(dir, file) {
60
- if (file === '' || isAbsolute(file))
61
- return false;
62
- if (file.split(/[\\/]/).includes('..'))
63
- return false;
64
- const root = resolve(dir);
65
- const target = resolve(dir, file);
66
- return target !== root && target.startsWith(root + sep);
67
- }
26
+ import { join } from 'node:path';
27
+ import { bundledBodyDiffers, installLayers, readIndexEntries, } from './layer-install.js';
68
28
  /**
69
29
  * Install every guidance layer registered in the content package into a project.
70
30
  *
@@ -73,71 +33,26 @@ function isContainedRelative(dir, file) {
73
33
  * @param opts.dryRun - Compute the report without writing anything.
74
34
  */
75
35
  export function installBundledGuidance(projectRoot, contentRoot, opts = {}) {
76
- const report = {
77
- installed: [],
78
- installedPaths: [],
79
- alreadyCurrent: [],
80
- locallyModified: [],
81
- indexUpdated: false,
82
- warnings: [],
83
- };
84
36
  const bundledDir = join(contentRoot, 'guidance');
85
37
  const bundledEntries = readIndexEntries(join(bundledDir, 'index.yaml'));
86
38
  if (!bundledEntries) {
87
- report.warnings.push(`content package has no readable guidance index at ${join(bundledDir, 'index.yaml')}`);
88
- return report;
89
- }
90
- const targetDir = join(projectRoot, '.aidlc', 'guidance');
91
- const existingEntries = readIndexEntries(join(targetDir, 'index.yaml'));
92
- const mergedEntries = existingEntries ? [...existingEntries] : [];
93
- const registeredNames = new Set(mergedEntries.map((e) => e.name));
94
- for (const entry of bundledEntries) {
95
- // Bounds before existence: a registration naming an absolute path or a `..`
96
- // segment is rejected outright rather than resolved and then stat'd.
97
- if (!isContainedRelative(bundledDir, entry.file) || !isContainedRelative(targetDir, entry.file)) {
98
- report.warnings.push(`guidance layer '${entry.name}' registers an out-of-bounds file and was skipped: ${entry.file}`);
99
- continue;
100
- }
101
- const source = join(bundledDir, entry.file);
102
- if (!existsSync(source)) {
103
- report.warnings.push(`guidance layer '${entry.name}' is registered in the content package but its file is missing: ${entry.file}`);
104
- continue;
105
- }
106
- const bundledBody = readFileSync(source, 'utf8');
107
- const target = join(targetDir, entry.file);
108
- if (existsSync(target)) {
109
- // A layer the project has edited is the project's, not ours (AC-4).
110
- if (readFileSync(target, 'utf8') === bundledBody) {
111
- report.alreadyCurrent.push(entry.name);
112
- }
113
- else {
114
- report.locallyModified.push(entry.name);
115
- }
116
- }
117
- else {
118
- report.installed.push(entry.name);
119
- report.installedPaths.push(`.aidlc/guidance/${entry.file}`);
120
- if (!opts.dryRun) {
121
- mkdirSync(targetDir, { recursive: true });
122
- writeFileSync(target, bundledBody, 'utf8');
123
- }
124
- }
125
- // Register by name regardless of whether the body was written, so a
126
- // locally-modified layer that is missing from the index still becomes active.
127
- if (!registeredNames.has(entry.name)) {
128
- mergedEntries.push({ name: entry.name, file: entry.file });
129
- registeredNames.add(entry.name);
130
- report.indexUpdated = true;
131
- }
132
- }
133
- if (report.indexUpdated) {
134
- report.installedPaths.push('.aidlc/guidance/index.yaml');
135
- if (!opts.dryRun) {
136
- mkdirSync(targetDir, { recursive: true });
137
- writeFileSync(join(targetDir, 'index.yaml'), serializeYaml({ layers: mergedEntries }), 'utf8');
138
- }
39
+ return {
40
+ installed: [],
41
+ installedPaths: [],
42
+ alreadyCurrent: [],
43
+ locallyModified: [],
44
+ indexUpdated: false,
45
+ warnings: [
46
+ `content package has no readable guidance index at ${join(bundledDir, 'index.yaml')}`,
47
+ ],
48
+ };
139
49
  }
140
- return report;
50
+ return installLayers(bundledDir, join(projectRoot, '.aidlc', 'guidance'), bundledEntries, {
51
+ isModified: bundledBodyDiffers,
52
+ relPrefix: '.aidlc/guidance',
53
+ label: 'guidance layer',
54
+ ...(opts.dryRun !== undefined && { dryRun: opts.dryRun }),
55
+ });
141
56
  }
142
57
  /**
143
58
  * Render a one-line summary of an installation pass, or null when nothing happened.
@@ -1 +1 @@
1
- {"version":3,"file":"guidance-install.js","sourceRoot":"","sources":["../../src/compile/guidance-install.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,MAAM,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AA6BzD;;;;GAIG;AACH,SAAS,gBAAgB,CAAC,SAAiB;IACzC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,SAAS,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;IACtD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,CAAC,CAAC,QAAQ,IAAI,MAAM,CAAC,EAAE,CAAC;QAC3E,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,MAAM,GAAI,MAA8B,CAAC,MAAM,CAAC;IACtD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,MAAM,CAAC,MAAM,CAClB,CAAC,CAAC,EAA2B,EAAE,CAC7B,OAAO,CAAC,KAAK,QAAQ;QACrB,CAAC,KAAK,IAAI;QACV,OAAQ,CAA6B,CAAC,IAAI,KAAK,QAAQ;QACvD,OAAQ,CAA6B,CAAC,IAAI,KAAK,QAAQ,CAC1D,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,mBAAmB,CAAC,GAAW,EAAE,IAAY;IACpD,IAAI,IAAI,KAAK,EAAE,IAAI,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAClD,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAErD,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAC1B,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAClC,OAAO,MAAM,KAAK,IAAI,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC;AAC1D,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB,CACpC,WAAmB,EACnB,WAAmB,EACnB,OAA6B,EAAE;IAE/B,MAAM,MAAM,GAA0B;QACpC,SAAS,EAAE,EAAE;QACb,cAAc,EAAE,EAAE;QAClB,cAAc,EAAE,EAAE;QAClB,eAAe,EAAE,EAAE;QACnB,YAAY,EAAE,KAAK;QACnB,QAAQ,EAAE,EAAE;KACb,CAAC;IAEF,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;IACjD,MAAM,cAAc,GAAG,gBAAgB,CAAC,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC,CAAC;IAExE,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,MAAM,CAAC,QAAQ,CAAC,IAAI,CAClB,qDAAqD,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,EAAE,CACtF,CAAC;QACF,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;IAC1D,MAAM,eAAe,GAAG,gBAAgB,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC,CAAC;IACxE,MAAM,aAAa,GAAyB,eAAe,CAAC,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACxF,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAElE,KAAK,MAAM,KAAK,IAAI,cAAc,EAAE,CAAC;QACnC,4EAA4E;QAC5E,qEAAqE;QACrE,IAAI,CAAC,mBAAmB,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YAChG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAClB,mBAAmB,KAAK,CAAC,IAAI,sDAAsD,KAAK,CAAC,IAAI,EAAE,CAChG,CAAC;YACF,SAAS;QACX,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAC5C,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YACxB,MAAM,CAAC,QAAQ,CAAC,IAAI,CAClB,mBAAmB,KAAK,CAAC,IAAI,mEAAmE,KAAK,CAAC,IAAI,EAAE,CAC7G,CAAC;YACF,SAAS;QACX,CAAC;QAED,MAAM,WAAW,GAAG,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACjD,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAE3C,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YACvB,oEAAoE;YACpE,IAAI,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,WAAW,EAAE,CAAC;gBACjD,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACzC,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC1C,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAClC,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,mBAAmB,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;YAC5D,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;gBACjB,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC1C,aAAa,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;YAC7C,CAAC;QACH,CAAC;QAED,oEAAoE;QACpE,8EAA8E;QAC9E,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YACrC,aAAa,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;YAC3D,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAChC,MAAM,CAAC,YAAY,GAAG,IAAI,CAAC;QAC7B,CAAC;IACH,CAAC;IAED,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;QACxB,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;QACzD,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC1C,aAAa,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,EAAE,aAAa,CAAC,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;QACjG,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,wBAAwB,CAAC,MAA6B;IACpE,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChC,KAAK,CAAC,IAAI,CAAC,aAAa,MAAM,CAAC,SAAS,CAAC,MAAM,uBAAuB,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACvG,CAAC;IACD,IAAI,MAAM,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtC,KAAK,CAAC,IAAI,CAAC,QAAQ,MAAM,CAAC,eAAe,CAAC,MAAM,sBAAsB,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC7G,CAAC;IACD,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,aAAa,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACnE,CAAC"}
1
+ {"version":3,"file":"guidance-install.js","sourceRoot":"","sources":["../../src/compile/guidance-install.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,gBAAgB,GAEjB,MAAM,oBAAoB,CAAC;AAU5B;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB,CACpC,WAAmB,EACnB,WAAmB,EACnB,OAA6B,EAAE;IAE/B,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;IACjD,MAAM,cAAc,GAAG,gBAAgB,CAAC,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC,CAAC;IAExE,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,OAAO;YACL,SAAS,EAAE,EAAE;YACb,cAAc,EAAE,EAAE;YAClB,cAAc,EAAE,EAAE;YAClB,eAAe,EAAE,EAAE;YACnB,YAAY,EAAE,KAAK;YACnB,QAAQ,EAAE;gBACR,qDAAqD,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,EAAE;aACtF;SACF,CAAC;IACJ,CAAC;IAED,OAAO,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,EAAE,QAAQ,EAAE,UAAU,CAAC,EAAE,cAAc,EAAE;QACxF,UAAU,EAAE,kBAAkB;QAC9B,SAAS,EAAE,iBAAiB;QAC5B,KAAK,EAAE,gBAAgB;QACvB,GAAG,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;KAC1D,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,wBAAwB,CAAC,MAA6B;IACpE,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChC,KAAK,CAAC,IAAI,CAAC,aAAa,MAAM,CAAC,SAAS,CAAC,MAAM,uBAAuB,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACvG,CAAC;IACD,IAAI,MAAM,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtC,KAAK,CAAC,IAAI,CAAC,QAAQ,MAAM,CAAC,eAAe,CAAC,MAAM,sBAAsB,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC7G,CAAC;IACD,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,aAAa,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACnE,CAAC"}
@@ -0,0 +1,122 @@
1
+ /**
2
+ * The guidance-layer install primitive.
3
+ *
4
+ * Extracted from `guidance-install.ts` so compliance packs can reuse the copy,
5
+ * the containment check and the index merge without reusing its entry point.
6
+ * `installBundledGuidance` installs *every* layer registered in the content
7
+ * package's guidance index and is called from `init`, `update`, and a `safe`-tier
8
+ * doctor migration that auto-applies without prompting — so a pack layer
9
+ * registered in that index would land in every upgrading project with no pack
10
+ * requested. This primitive takes an explicit entry list and has no
11
+ * install-everything mode.
12
+ *
13
+ * **The modified-detector is injected, not shared.** `installBundledGuidance`
14
+ * decides "locally modified" by comparing the on-disk body against the
15
+ * *currently bundled* body. That is right for framework layers, whose bundled
16
+ * body is the only reference available, and wrong for packs: a pack whose content
17
+ * is updated upstream would make every installed layer read as locally edited, so
18
+ * `remove` would refuse to delete anything and corrected control text would never
19
+ * land. Packs compare against the hash recorded at install instead. A primitive
20
+ * that hard-coded either rule would be wrong for one caller.
21
+ *
22
+ * Requirements: compliance-packs/AC-63 (single containment definition), and the
23
+ * behaviour `guidance-layers-never-resolve/AC-1, AC-3, AC-4, AC-5, AC-14`
24
+ * established, which this file now carries.
25
+ */
26
+ /** One entry in a guidance `index.yaml`. Extra keys are data and are preserved. */
27
+ export interface GuidanceIndexEntry {
28
+ name: string;
29
+ file: string;
30
+ [key: string]: unknown;
31
+ }
32
+ /** Outcome of an installation pass. */
33
+ export interface LayerInstallReport {
34
+ /** Layer names newly written to disk. */
35
+ installed: string[];
36
+ /**
37
+ * Repo-relative paths newly written, including `index.yaml` when it changed.
38
+ * Kept alongside `installed` so callers never have to reconstruct a filename
39
+ * from a layer name — the two differ whenever a layer registers a filename
40
+ * that is not `<name>.md`.
41
+ */
42
+ installedPaths: string[];
43
+ /** Layer names already present with identical content. */
44
+ alreadyCurrent: string[];
45
+ /** Layer names present but modified per the injected detector — left untouched. */
46
+ locallyModified: string[];
47
+ /** True when the target `index.yaml` gained entries. */
48
+ indexUpdated: boolean;
49
+ warnings: string[];
50
+ }
51
+ /** How a caller decides a layer on disk is not ours to overwrite. */
52
+ export type ModifiedDetector = (targetPath: string, bundledBody: string) => boolean;
53
+ export interface InstallLayersOptions {
54
+ /** Decides whether an existing target counts as locally modified. */
55
+ isModified: ModifiedDetector;
56
+ /** Repo-relative prefix for `installedPaths`, e.g. `.aidlc/guidance`. */
57
+ relPrefix: string;
58
+ /** Compute the report without writing anything. */
59
+ dryRun?: boolean;
60
+ /** Label used in warnings, e.g. `guidance layer` or `pack 'soc2' layer`. */
61
+ label?: string;
62
+ }
63
+ /**
64
+ * Read and validate a guidance `index.yaml`, returning its entries.
65
+ *
66
+ * @returns Entries, or null when the file is absent or unusable.
67
+ */
68
+ export declare function readIndexEntries(indexPath: string): GuidanceIndexEntry[] | null;
69
+ /**
70
+ * True when `file` is a safe relative name that stays inside `dir`.
71
+ *
72
+ * `file` comes out of a YAML index, so it is data, not a constant: an absolute
73
+ * path or a `..` segment would make `join` escape the guidance directory and, on
74
+ * the target side, write outside it. Checked lexically **before** any disk access
75
+ * — ordering this after an existence check is how a sibling defect in this repo
76
+ * turned an error path into an out-of-bounds oracle.
77
+ *
78
+ * Exported so there is exactly one definition of the rule; a pack loader calls
79
+ * this rather than writing a second one (compliance-packs/AC-63).
80
+ */
81
+ export declare function isContainedRelative(dir: string, file: string): boolean;
82
+ /**
83
+ * Copy an explicit list of layers into `targetDir` and merge the target index.
84
+ *
85
+ * Non-destructive by construction: a layer the injected detector reports as
86
+ * modified is left alone, and existing index entries are preserved wholesale
87
+ * rather than rebuilt, so fields the target owns (notably the retrospective-fed
88
+ * `lessons` layer's `last_consolidated`) survive.
89
+ *
90
+ * @param sourceDir - Directory holding the layer bodies to copy from.
91
+ * @param targetDir - Directory to install into, e.g. `<root>/.aidlc/guidance`.
92
+ * @param entries - The layers to install. There is no "everything" mode.
93
+ * @param opts - Injected detector, path prefix, dry-run flag, warning label.
94
+ */
95
+ export declare function installLayers(sourceDir: string, targetDir: string, entries: GuidanceIndexEntry[], opts: InstallLayersOptions): LayerInstallReport;
96
+ /**
97
+ * The framework's modified-detector: the on-disk body differs from the bundled one.
98
+ *
99
+ * Correct for bundled framework layers, whose bundled body is the only reference
100
+ * that exists. Deliberately **not** used for packs — see the module note.
101
+ */
102
+ export declare const bundledBodyDiffers: ModifiedDetector;
103
+ /**
104
+ * Drop layer registrations from a target index by name.
105
+ *
106
+ * Removing the registration is what makes a layer *inert*, and it is separate from
107
+ * deleting the file on purpose. When a pack is removed but one of its layers has
108
+ * been locally edited, the bytes stay (they are the project's now) while the
109
+ * registration goes — otherwise `loadGuidanceLayers` keeps handing an uninstalled
110
+ * pack's constraints to every agent, which is the drift state `doctor` classifies
111
+ * as a defect.
112
+ *
113
+ * Never touches the files themselves, and never touches a registration it was not
114
+ * asked about.
115
+ *
116
+ * @returns The names actually removed, so a caller can report accurately rather
117
+ * than assuming.
118
+ */
119
+ export declare function unregisterLayers(targetDir: string, names: string[], opts?: {
120
+ dryRun?: boolean;
121
+ }): string[];
122
+ //# sourceMappingURL=layer-install.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layer-install.d.ts","sourceRoot":"","sources":["../../src/compile/layer-install.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAOH,mFAAmF;AACnF,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,uCAAuC;AACvC,MAAM,WAAW,kBAAkB;IACjC,yCAAyC;IACzC,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB;;;;;OAKG;IACH,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,0DAA0D;IAC1D,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,mFAAmF;IACnF,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,wDAAwD;IACxD,YAAY,EAAE,OAAO,CAAC;IACtB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,qEAAqE;AACrE,MAAM,MAAM,gBAAgB,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC;AAEpF,MAAM,WAAW,oBAAoB;IACnC,qEAAqE;IACrE,UAAU,EAAE,gBAAgB,CAAC;IAC7B,yEAAyE;IACzE,SAAS,EAAE,MAAM,CAAC;IAClB,mDAAmD;IACnD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,4EAA4E;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,kBAAkB,EAAE,GAAG,IAAI,CA4B/E;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAOtE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,kBAAkB,EAAE,EAC7B,IAAI,EAAE,oBAAoB,GACzB,kBAAkB,CA4EpB;AAED;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,EAAE,gBACiB,CAAC;AAEnD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EAAE,EACf,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GAC9B,MAAM,EAAE,CAaV"}
@@ -0,0 +1,195 @@
1
+ /**
2
+ * The guidance-layer install primitive.
3
+ *
4
+ * Extracted from `guidance-install.ts` so compliance packs can reuse the copy,
5
+ * the containment check and the index merge without reusing its entry point.
6
+ * `installBundledGuidance` installs *every* layer registered in the content
7
+ * package's guidance index and is called from `init`, `update`, and a `safe`-tier
8
+ * doctor migration that auto-applies without prompting — so a pack layer
9
+ * registered in that index would land in every upgrading project with no pack
10
+ * requested. This primitive takes an explicit entry list and has no
11
+ * install-everything mode.
12
+ *
13
+ * **The modified-detector is injected, not shared.** `installBundledGuidance`
14
+ * decides "locally modified" by comparing the on-disk body against the
15
+ * *currently bundled* body. That is right for framework layers, whose bundled
16
+ * body is the only reference available, and wrong for packs: a pack whose content
17
+ * is updated upstream would make every installed layer read as locally edited, so
18
+ * `remove` would refuse to delete anything and corrected control text would never
19
+ * land. Packs compare against the hash recorded at install instead. A primitive
20
+ * that hard-coded either rule would be wrong for one caller.
21
+ *
22
+ * Requirements: compliance-packs/AC-63 (single containment definition), and the
23
+ * behaviour `guidance-layers-never-resolve/AC-1, AC-3, AC-4, AC-5, AC-14`
24
+ * established, which this file now carries.
25
+ */
26
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
27
+ import { isAbsolute, join, resolve, sep } from 'node:path';
28
+ import { parse as parseYaml } from 'yaml';
29
+ import { serializeYaml } from '../state/yaml-helpers.js';
30
+ /**
31
+ * Read and validate a guidance `index.yaml`, returning its entries.
32
+ *
33
+ * @returns Entries, or null when the file is absent or unusable.
34
+ */
35
+ export function readIndexEntries(indexPath) {
36
+ if (!existsSync(indexPath)) {
37
+ return null;
38
+ }
39
+ let parsed;
40
+ try {
41
+ parsed = parseYaml(readFileSync(indexPath, 'utf8'));
42
+ }
43
+ catch {
44
+ return null;
45
+ }
46
+ if (typeof parsed !== 'object' || parsed === null || !('layers' in parsed)) {
47
+ return null;
48
+ }
49
+ const layers = parsed.layers;
50
+ if (!Array.isArray(layers)) {
51
+ return null;
52
+ }
53
+ return layers.filter((e) => typeof e === 'object' &&
54
+ e !== null &&
55
+ typeof e.name === 'string' &&
56
+ typeof e.file === 'string');
57
+ }
58
+ /**
59
+ * True when `file` is a safe relative name that stays inside `dir`.
60
+ *
61
+ * `file` comes out of a YAML index, so it is data, not a constant: an absolute
62
+ * path or a `..` segment would make `join` escape the guidance directory and, on
63
+ * the target side, write outside it. Checked lexically **before** any disk access
64
+ * — ordering this after an existence check is how a sibling defect in this repo
65
+ * turned an error path into an out-of-bounds oracle.
66
+ *
67
+ * Exported so there is exactly one definition of the rule; a pack loader calls
68
+ * this rather than writing a second one (compliance-packs/AC-63).
69
+ */
70
+ export function isContainedRelative(dir, file) {
71
+ if (file === '' || isAbsolute(file))
72
+ return false;
73
+ if (file.split(/[\\/]/).includes('..'))
74
+ return false;
75
+ const root = resolve(dir);
76
+ const target = resolve(dir, file);
77
+ return target !== root && target.startsWith(root + sep);
78
+ }
79
+ /**
80
+ * Copy an explicit list of layers into `targetDir` and merge the target index.
81
+ *
82
+ * Non-destructive by construction: a layer the injected detector reports as
83
+ * modified is left alone, and existing index entries are preserved wholesale
84
+ * rather than rebuilt, so fields the target owns (notably the retrospective-fed
85
+ * `lessons` layer's `last_consolidated`) survive.
86
+ *
87
+ * @param sourceDir - Directory holding the layer bodies to copy from.
88
+ * @param targetDir - Directory to install into, e.g. `<root>/.aidlc/guidance`.
89
+ * @param entries - The layers to install. There is no "everything" mode.
90
+ * @param opts - Injected detector, path prefix, dry-run flag, warning label.
91
+ */
92
+ export function installLayers(sourceDir, targetDir, entries, opts) {
93
+ const label = opts.label ?? 'guidance layer';
94
+ const report = {
95
+ installed: [],
96
+ installedPaths: [],
97
+ alreadyCurrent: [],
98
+ locallyModified: [],
99
+ indexUpdated: false,
100
+ warnings: [],
101
+ };
102
+ const indexPath = join(targetDir, 'index.yaml');
103
+ const existingEntries = readIndexEntries(indexPath);
104
+ const mergedEntries = existingEntries ? [...existingEntries] : [];
105
+ const registeredNames = new Set(mergedEntries.map((e) => e.name));
106
+ for (const entry of entries) {
107
+ // Bounds before existence: a registration naming an absolute path or a `..`
108
+ // segment is rejected outright rather than resolved and then stat'd.
109
+ if (!isContainedRelative(sourceDir, entry.file) || !isContainedRelative(targetDir, entry.file)) {
110
+ report.warnings.push(`${label} '${entry.name}' registers an out-of-bounds file and was skipped: ${entry.file}`);
111
+ continue;
112
+ }
113
+ const source = join(sourceDir, entry.file);
114
+ if (!existsSync(source)) {
115
+ report.warnings.push(`${label} '${entry.name}' is registered but its file is missing: ${entry.file}`);
116
+ continue;
117
+ }
118
+ const bundledBody = readFileSync(source, 'utf8');
119
+ const target = join(targetDir, entry.file);
120
+ if (existsSync(target)) {
121
+ // A layer the project has changed is the project's, not ours.
122
+ if (opts.isModified(target, bundledBody)) {
123
+ report.locallyModified.push(entry.name);
124
+ }
125
+ else {
126
+ report.alreadyCurrent.push(entry.name);
127
+ }
128
+ }
129
+ else {
130
+ report.installed.push(entry.name);
131
+ report.installedPaths.push(`${opts.relPrefix}/${entry.file}`);
132
+ if (!opts.dryRun) {
133
+ mkdirSync(targetDir, { recursive: true });
134
+ writeFileSync(target, bundledBody, 'utf8');
135
+ }
136
+ }
137
+ // Register by name regardless of whether the body was written, so a
138
+ // locally-modified layer that is missing from the index still becomes active.
139
+ //
140
+ // The whole entry is spread rather than rebuilt as `{name, file}`: rebuilding
141
+ // silently drops every other key on first registration, which is where a pack
142
+ // layer's `always_pointer` flag would be lost. Safe because `readIndexEntries`
143
+ // already guarantees `name` and `file` are strings.
144
+ if (!registeredNames.has(entry.name)) {
145
+ mergedEntries.push({ ...entry });
146
+ registeredNames.add(entry.name);
147
+ report.indexUpdated = true;
148
+ }
149
+ }
150
+ if (report.indexUpdated) {
151
+ report.installedPaths.push(`${opts.relPrefix}/index.yaml`);
152
+ if (!opts.dryRun) {
153
+ mkdirSync(targetDir, { recursive: true });
154
+ writeFileSync(indexPath, serializeYaml({ layers: mergedEntries }), 'utf8');
155
+ }
156
+ }
157
+ return report;
158
+ }
159
+ /**
160
+ * The framework's modified-detector: the on-disk body differs from the bundled one.
161
+ *
162
+ * Correct for bundled framework layers, whose bundled body is the only reference
163
+ * that exists. Deliberately **not** used for packs — see the module note.
164
+ */
165
+ export const bundledBodyDiffers = (targetPath, bundledBody) => readFileSync(targetPath, 'utf8') !== bundledBody;
166
+ /**
167
+ * Drop layer registrations from a target index by name.
168
+ *
169
+ * Removing the registration is what makes a layer *inert*, and it is separate from
170
+ * deleting the file on purpose. When a pack is removed but one of its layers has
171
+ * been locally edited, the bytes stay (they are the project's now) while the
172
+ * registration goes — otherwise `loadGuidanceLayers` keeps handing an uninstalled
173
+ * pack's constraints to every agent, which is the drift state `doctor` classifies
174
+ * as a defect.
175
+ *
176
+ * Never touches the files themselves, and never touches a registration it was not
177
+ * asked about.
178
+ *
179
+ * @returns The names actually removed, so a caller can report accurately rather
180
+ * than assuming.
181
+ */
182
+ export function unregisterLayers(targetDir, names, opts = {}) {
183
+ const indexPath = join(targetDir, 'index.yaml');
184
+ const entries = readIndexEntries(indexPath);
185
+ if (!entries)
186
+ return [];
187
+ const wanted = new Set(names);
188
+ const kept = entries.filter((e) => !wanted.has(e.name));
189
+ const removed = entries.filter((e) => wanted.has(e.name)).map((e) => e.name);
190
+ if (removed.length > 0 && !opts.dryRun) {
191
+ writeFileSync(indexPath, serializeYaml({ layers: kept }), 'utf8');
192
+ }
193
+ return removed;
194
+ }
195
+ //# sourceMappingURL=layer-install.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layer-install.js","sourceRoot":"","sources":["../../src/compile/layer-install.ts"],"names":[],"mappings":"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"}