@design-intelligence/ghost 0.0.0-next-20260715121453

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 (327) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +89 -0
  3. package/dist/bin.d.ts +3 -0
  4. package/dist/bin.d.ts.map +1 -0
  5. package/dist/bin.js +19 -0
  6. package/dist/bin.js.map +1 -0
  7. package/dist/cli.d.ts +4 -0
  8. package/dist/cli.d.ts.map +1 -0
  9. package/dist/cli.js +29 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/commands/checks-command.d.ts +9 -0
  12. package/dist/commands/checks-command.d.ts.map +1 -0
  13. package/dist/commands/checks-command.js +52 -0
  14. package/dist/commands/checks-command.js.map +1 -0
  15. package/dist/commands/command-discovery.d.ts +57 -0
  16. package/dist/commands/command-discovery.d.ts.map +1 -0
  17. package/dist/commands/command-discovery.js +220 -0
  18. package/dist/commands/command-discovery.js.map +1 -0
  19. package/dist/commands/errors.d.ts +7 -0
  20. package/dist/commands/errors.d.ts.map +1 -0
  21. package/dist/commands/errors.js +19 -0
  22. package/dist/commands/errors.js.map +1 -0
  23. package/dist/commands/export-command.d.ts +3 -0
  24. package/dist/commands/export-command.d.ts.map +1 -0
  25. package/dist/commands/export-command.js +157 -0
  26. package/dist/commands/export-command.js.map +1 -0
  27. package/dist/commands/fingerprint-commands.d.ts +10 -0
  28. package/dist/commands/fingerprint-commands.d.ts.map +1 -0
  29. package/dist/commands/fingerprint-commands.js +69 -0
  30. package/dist/commands/fingerprint-commands.js.map +1 -0
  31. package/dist/commands/gather-command.d.ts +3 -0
  32. package/dist/commands/gather-command.d.ts.map +1 -0
  33. package/dist/commands/gather-command.js +214 -0
  34. package/dist/commands/gather-command.js.map +1 -0
  35. package/dist/commands/init-command.d.ts +3 -0
  36. package/dist/commands/init-command.d.ts.map +1 -0
  37. package/dist/commands/init-command.js +89 -0
  38. package/dist/commands/init-command.js.map +1 -0
  39. package/dist/commands/manifest-command.d.ts +9 -0
  40. package/dist/commands/manifest-command.d.ts.map +1 -0
  41. package/dist/commands/manifest-command.js +33 -0
  42. package/dist/commands/manifest-command.js.map +1 -0
  43. package/dist/commands/pull-command.d.ts +3 -0
  44. package/dist/commands/pull-command.d.ts.map +1 -0
  45. package/dist/commands/pull-command.js +230 -0
  46. package/dist/commands/pull-command.js.map +1 -0
  47. package/dist/commands/pulse-command.d.ts +3 -0
  48. package/dist/commands/pulse-command.d.ts.map +1 -0
  49. package/dist/commands/pulse-command.js +248 -0
  50. package/dist/commands/pulse-command.js.map +1 -0
  51. package/dist/commands/review-command.d.ts +3 -0
  52. package/dist/commands/review-command.d.ts.map +1 -0
  53. package/dist/commands/review-command.js +78 -0
  54. package/dist/commands/review-command.js.map +1 -0
  55. package/dist/commands/skill-command.d.ts +3 -0
  56. package/dist/commands/skill-command.d.ts.map +1 -0
  57. package/dist/commands/skill-command.js +96 -0
  58. package/dist/commands/skill-command.js.map +1 -0
  59. package/dist/fingerprint.d.ts +5 -0
  60. package/dist/fingerprint.d.ts.map +1 -0
  61. package/dist/fingerprint.js +3 -0
  62. package/dist/fingerprint.js.map +1 -0
  63. package/dist/ghost-core/catalog/assemble.d.ts +26 -0
  64. package/dist/ghost-core/catalog/assemble.d.ts.map +1 -0
  65. package/dist/ghost-core/catalog/assemble.js +29 -0
  66. package/dist/ghost-core/catalog/assemble.js.map +1 -0
  67. package/dist/ghost-core/catalog/closest.d.ts +16 -0
  68. package/dist/ghost-core/catalog/closest.d.ts.map +1 -0
  69. package/dist/ghost-core/catalog/closest.js +63 -0
  70. package/dist/ghost-core/catalog/closest.js.map +1 -0
  71. package/dist/ghost-core/catalog/index.d.ts +10 -0
  72. package/dist/ghost-core/catalog/index.d.ts.map +1 -0
  73. package/dist/ghost-core/catalog/index.js +9 -0
  74. package/dist/ghost-core/catalog/index.js.map +1 -0
  75. package/dist/ghost-core/catalog/menu.d.ts +28 -0
  76. package/dist/ghost-core/catalog/menu.d.ts.map +1 -0
  77. package/dist/ghost-core/catalog/menu.js +23 -0
  78. package/dist/ghost-core/catalog/menu.js.map +1 -0
  79. package/dist/ghost-core/catalog/types.d.ts +33 -0
  80. package/dist/ghost-core/catalog/types.d.ts.map +1 -0
  81. package/dist/ghost-core/catalog/types.js +2 -0
  82. package/dist/ghost-core/catalog/types.js.map +1 -0
  83. package/dist/ghost-core/check/index.d.ts +12 -0
  84. package/dist/ghost-core/check/index.d.ts.map +1 -0
  85. package/dist/ghost-core/check/index.js +12 -0
  86. package/dist/ghost-core/check/index.js.map +1 -0
  87. package/dist/ghost-core/check/lint.d.ts +9 -0
  88. package/dist/ghost-core/check/lint.d.ts.map +1 -0
  89. package/dist/ghost-core/check/lint.js +119 -0
  90. package/dist/ghost-core/check/lint.js.map +1 -0
  91. package/dist/ghost-core/check/load.d.ts +7 -0
  92. package/dist/ghost-core/check/load.d.ts.map +1 -0
  93. package/dist/ghost-core/check/load.js +44 -0
  94. package/dist/ghost-core/check/load.js.map +1 -0
  95. package/dist/ghost-core/check/parse.d.ts +12 -0
  96. package/dist/ghost-core/check/parse.d.ts.map +1 -0
  97. package/dist/ghost-core/check/parse.js +13 -0
  98. package/dist/ghost-core/check/parse.js.map +1 -0
  99. package/dist/ghost-core/check/source-ref.d.ts +27 -0
  100. package/dist/ghost-core/check/source-ref.d.ts.map +1 -0
  101. package/dist/ghost-core/check/source-ref.js +58 -0
  102. package/dist/ghost-core/check/source-ref.js.map +1 -0
  103. package/dist/ghost-core/check/types.d.ts +48 -0
  104. package/dist/ghost-core/check/types.d.ts.map +1 -0
  105. package/dist/ghost-core/check/types.js +4 -0
  106. package/dist/ghost-core/check/types.js.map +1 -0
  107. package/dist/ghost-core/errors.d.ts +30 -0
  108. package/dist/ghost-core/errors.d.ts.map +1 -0
  109. package/dist/ghost-core/errors.js +33 -0
  110. package/dist/ghost-core/errors.js.map +1 -0
  111. package/dist/ghost-core/glob.d.ts +5 -0
  112. package/dist/ghost-core/glob.d.ts.map +1 -0
  113. package/dist/ghost-core/glob.js +68 -0
  114. package/dist/ghost-core/glob.js.map +1 -0
  115. package/dist/ghost-core/glossary.d.ts +25 -0
  116. package/dist/ghost-core/glossary.d.ts.map +1 -0
  117. package/dist/ghost-core/glossary.js +69 -0
  118. package/dist/ghost-core/glossary.js.map +1 -0
  119. package/dist/ghost-core/index.d.ts +13 -0
  120. package/dist/ghost-core/index.d.ts.map +1 -0
  121. package/dist/ghost-core/index.js +19 -0
  122. package/dist/ghost-core/index.js.map +1 -0
  123. package/dist/ghost-core/markdown.d.ts +15 -0
  124. package/dist/ghost-core/markdown.d.ts.map +1 -0
  125. package/dist/ghost-core/markdown.js +30 -0
  126. package/dist/ghost-core/markdown.js.map +1 -0
  127. package/dist/ghost-core/material-transport.d.ts +43 -0
  128. package/dist/ghost-core/material-transport.d.ts.map +1 -0
  129. package/dist/ghost-core/material-transport.js +231 -0
  130. package/dist/ghost-core/material-transport.js.map +1 -0
  131. package/dist/ghost-core/materials.d.ts +14 -0
  132. package/dist/ghost-core/materials.d.ts.map +1 -0
  133. package/dist/ghost-core/materials.js +52 -0
  134. package/dist/ghost-core/materials.js.map +1 -0
  135. package/dist/ghost-core/node/index.d.ts +11 -0
  136. package/dist/ghost-core/node/index.d.ts.map +1 -0
  137. package/dist/ghost-core/node/index.js +11 -0
  138. package/dist/ghost-core/node/index.js.map +1 -0
  139. package/dist/ghost-core/node/parse.d.ts +16 -0
  140. package/dist/ghost-core/node/parse.d.ts.map +1 -0
  141. package/dist/ghost-core/node/parse.js +55 -0
  142. package/dist/ghost-core/node/parse.js.map +1 -0
  143. package/dist/ghost-core/node/schema.d.ts +17 -0
  144. package/dist/ghost-core/node/schema.d.ts.map +1 -0
  145. package/dist/ghost-core/node/schema.js +49 -0
  146. package/dist/ghost-core/node/schema.js.map +1 -0
  147. package/dist/ghost-core/node/serialize.d.ts +12 -0
  148. package/dist/ghost-core/node/serialize.d.ts.map +1 -0
  149. package/dist/ghost-core/node/serialize.js +39 -0
  150. package/dist/ghost-core/node/serialize.js.map +1 -0
  151. package/dist/ghost-core/node/steering.d.ts +19 -0
  152. package/dist/ghost-core/node/steering.d.ts.map +1 -0
  153. package/dist/ghost-core/node/steering.js +68 -0
  154. package/dist/ghost-core/node/steering.js.map +1 -0
  155. package/dist/ghost-core/node/types.d.ts +43 -0
  156. package/dist/ghost-core/node/types.d.ts.map +1 -0
  157. package/dist/ghost-core/node/types.js +2 -0
  158. package/dist/ghost-core/node/types.js.map +1 -0
  159. package/dist/ghost-core/package-manifest.d.ts +19 -0
  160. package/dist/ghost-core/package-manifest.d.ts.map +1 -0
  161. package/dist/ghost-core/package-manifest.js +24 -0
  162. package/dist/ghost-core/package-manifest.js.map +1 -0
  163. package/dist/ghost-core/skill-bundle-loader.d.ts +28 -0
  164. package/dist/ghost-core/skill-bundle-loader.d.ts.map +1 -0
  165. package/dist/ghost-core/skill-bundle-loader.js +51 -0
  166. package/dist/ghost-core/skill-bundle-loader.js.map +1 -0
  167. package/dist/index.d.ts +5 -0
  168. package/dist/index.d.ts.map +1 -0
  169. package/dist/index.js +5 -0
  170. package/dist/index.js.map +1 -0
  171. package/dist/init-payloads/median/cliche.median.md +86 -0
  172. package/dist/init-payloads/median/median-tells.md +117 -0
  173. package/dist/init-payloads/skeleton/brand.md +23 -0
  174. package/dist/init-payloads/skeleton/context.conversation.md +24 -0
  175. package/dist/init-payloads/skeleton/foundation.color.md +39 -0
  176. package/dist/init-payloads/skeleton/foundation.composition.md +30 -0
  177. package/dist/init-payloads/skeleton/foundation.controls.md +29 -0
  178. package/dist/init-payloads/skeleton/foundation.layout.md +45 -0
  179. package/dist/init-payloads/skeleton/foundation.motion.md +34 -0
  180. package/dist/init-payloads/skeleton/foundation.type.md +44 -0
  181. package/dist/init-payloads/skeleton/foundation.voice.md +29 -0
  182. package/dist/init-payloads/skeleton/glossary.md +39 -0
  183. package/dist/init-payloads/vessel-light/anti-goal.median.md +86 -0
  184. package/dist/init-payloads/vessel-light/anti-goal.tells.md +38 -0
  185. package/dist/init-payloads/vessel-light/checks/conversation-grammar.md +20 -0
  186. package/dist/init-payloads/vessel-light/checks/median-tells.md +103 -0
  187. package/dist/init-payloads/vessel-light/checks/motion-restraint.md +20 -0
  188. package/dist/init-payloads/vessel-light/checks/relationships.md +33 -0
  189. package/dist/init-payloads/vessel-light/checks/shape-matches-job.md +43 -0
  190. package/dist/init-payloads/vessel-light/checks/values.md +51 -0
  191. package/dist/init-payloads/vessel-light/glossary.md +44 -0
  192. package/dist/init-payloads/vessel-light/grammar.color-roles.md +30 -0
  193. package/dist/init-payloads/vessel-light/grammar.conversation.md +30 -0
  194. package/dist/init-payloads/vessel-light/grammar.deletion.md +35 -0
  195. package/dist/init-payloads/vessel-light/grammar.hierarchy.md +58 -0
  196. package/dist/init-payloads/vessel-light/grammar.job.md +54 -0
  197. package/dist/init-payloads/vessel-light/grammar.motion.md +27 -0
  198. package/dist/init-payloads/vessel-light/grammar.rhythm.md +27 -0
  199. package/dist/init-payloads/vessel-light/grammar.surfaces.md +35 -0
  200. package/dist/init-payloads/vessel-light/index.md +33 -0
  201. package/dist/init-payloads/vessel-light/manifest.yml +3 -0
  202. package/dist/init-payloads/vessel-light/materials/fonts/HKGrotesk-Black.woff2 +0 -0
  203. package/dist/init-payloads/vessel-light/materials/fonts/HKGrotesk-Bold.woff2 +0 -0
  204. package/dist/init-payloads/vessel-light/materials/fonts/HKGrotesk-ExtraBold.woff2 +0 -0
  205. package/dist/init-payloads/vessel-light/materials/fonts/HKGrotesk-Light.woff2 +0 -0
  206. package/dist/init-payloads/vessel-light/materials/fonts/HKGrotesk-Medium.woff2 +0 -0
  207. package/dist/init-payloads/vessel-light/materials/fonts/HKGrotesk-Regular.woff2 +0 -0
  208. package/dist/init-payloads/vessel-light/materials/fonts/HKGrotesk-SemiBold.woff2 +0 -0
  209. package/dist/init-payloads/vessel-light/materials/primitives.css +351 -0
  210. package/dist/init-payloads/vessel-light/materials/ref/composition.conversation.html +63 -0
  211. package/dist/init-payloads/vessel-light/materials/ref/composition.editorial.html +74 -0
  212. package/dist/init-payloads/vessel-light/materials/ref/composition.form.html +89 -0
  213. package/dist/init-payloads/vessel-light/materials/ref/composition.overlay.html +66 -0
  214. package/dist/init-payloads/vessel-light/materials/ref/composition.table.html +104 -0
  215. package/dist/init-payloads/vessel-light/materials/ref/email.html +80 -0
  216. package/dist/init-payloads/vessel-light/materials/tokens.css +191 -0
  217. package/dist/init-payloads/vessel-light/register.data-density.md +39 -0
  218. package/dist/init-payloads/vessel-light/register.editorial.md +41 -0
  219. package/dist/init-payloads/vessel-light/register.email.md +43 -0
  220. package/dist/init-payloads/vessel-light/signature.palette.md +45 -0
  221. package/dist/init-payloads/vessel-light/signature.shape.md +27 -0
  222. package/dist/init-payloads/vessel-light/signature.temperature.md +44 -0
  223. package/dist/init-payloads/vessel-light/signature.type.md +37 -0
  224. package/dist/internal/fs.d.ts +4 -0
  225. package/dist/internal/fs.d.ts.map +1 -0
  226. package/dist/internal/fs.js +24 -0
  227. package/dist/internal/fs.js.map +1 -0
  228. package/dist/observability-events.d.ts +34 -0
  229. package/dist/observability-events.d.ts.map +1 -0
  230. package/dist/observability-events.js +68 -0
  231. package/dist/observability-events.js.map +1 -0
  232. package/dist/package-version.d.ts +3 -0
  233. package/dist/package-version.d.ts.map +1 -0
  234. package/dist/package-version.js +10 -0
  235. package/dist/package-version.js.map +1 -0
  236. package/dist/review/baseline.d.ts +11 -0
  237. package/dist/review/baseline.d.ts.map +1 -0
  238. package/dist/review/baseline.js +35 -0
  239. package/dist/review/baseline.js.map +1 -0
  240. package/dist/review/diff.d.ts +7 -0
  241. package/dist/review/diff.d.ts.map +1 -0
  242. package/dist/review/diff.js +41 -0
  243. package/dist/review/diff.js.map +1 -0
  244. package/dist/review/glob.d.ts +2 -0
  245. package/dist/review/glob.d.ts.map +1 -0
  246. package/dist/review/glob.js +2 -0
  247. package/dist/review/glob.js.map +1 -0
  248. package/dist/review/probes.d.ts +13 -0
  249. package/dist/review/probes.d.ts.map +1 -0
  250. package/dist/review/probes.js +45 -0
  251. package/dist/review/probes.js.map +1 -0
  252. package/dist/review/resolve.d.ts +28 -0
  253. package/dist/review/resolve.d.ts.map +1 -0
  254. package/dist/review/resolve.js +90 -0
  255. package/dist/review/resolve.js.map +1 -0
  256. package/dist/review/review-packet.d.ts +41 -0
  257. package/dist/review/review-packet.d.ts.map +1 -0
  258. package/dist/review/review-packet.js +128 -0
  259. package/dist/review/review-packet.js.map +1 -0
  260. package/dist/scan/check-files.d.ts +23 -0
  261. package/dist/scan/check-files.d.ts.map +1 -0
  262. package/dist/scan/check-files.js +75 -0
  263. package/dist/scan/check-files.js.map +1 -0
  264. package/dist/scan/check-scaffold.d.ts +8 -0
  265. package/dist/scan/check-scaffold.d.ts.map +1 -0
  266. package/dist/scan/check-scaffold.js +53 -0
  267. package/dist/scan/check-scaffold.js.map +1 -0
  268. package/dist/scan/constants.d.ts +21 -0
  269. package/dist/scan/constants.d.ts.map +1 -0
  270. package/dist/scan/constants.js +21 -0
  271. package/dist/scan/constants.js.map +1 -0
  272. package/dist/scan/file-kind.d.ts +12 -0
  273. package/dist/scan/file-kind.d.ts.map +1 -0
  274. package/dist/scan/file-kind.js +114 -0
  275. package/dist/scan/file-kind.js.map +1 -0
  276. package/dist/scan/fingerprint-package-lint.d.ts +8 -0
  277. package/dist/scan/fingerprint-package-lint.d.ts.map +1 -0
  278. package/dist/scan/fingerprint-package-lint.js +284 -0
  279. package/dist/scan/fingerprint-package-lint.js.map +1 -0
  280. package/dist/scan/fingerprint-package-loader.d.ts +5 -0
  281. package/dist/scan/fingerprint-package-loader.d.ts.map +1 -0
  282. package/dist/scan/fingerprint-package-loader.js +78 -0
  283. package/dist/scan/fingerprint-package-loader.js.map +1 -0
  284. package/dist/scan/fingerprint-package.d.ts +66 -0
  285. package/dist/scan/fingerprint-package.d.ts.map +1 -0
  286. package/dist/scan/fingerprint-package.js +101 -0
  287. package/dist/scan/fingerprint-package.js.map +1 -0
  288. package/dist/scan/index.d.ts +3 -0
  289. package/dist/scan/index.d.ts.map +1 -0
  290. package/dist/scan/index.js +3 -0
  291. package/dist/scan/index.js.map +1 -0
  292. package/dist/scan/lint.d.ts +15 -0
  293. package/dist/scan/lint.d.ts.map +1 -0
  294. package/dist/scan/lint.js +2 -0
  295. package/dist/scan/lint.js.map +1 -0
  296. package/dist/scan/node-files.d.ts +25 -0
  297. package/dist/scan/node-files.d.ts.map +1 -0
  298. package/dist/scan/node-files.js +112 -0
  299. package/dist/scan/node-files.js.map +1 -0
  300. package/dist/scan/package-paths.d.ts +10 -0
  301. package/dist/scan/package-paths.d.ts.map +1 -0
  302. package/dist/scan/package-paths.js +49 -0
  303. package/dist/scan/package-paths.js.map +1 -0
  304. package/dist/scan/packed-payloads.d.ts +4 -0
  305. package/dist/scan/packed-payloads.d.ts.map +1 -0
  306. package/dist/scan/packed-payloads.js +55 -0
  307. package/dist/scan/packed-payloads.js.map +1 -0
  308. package/dist/scan/tarball.d.ts +23 -0
  309. package/dist/scan/tarball.d.ts.map +1 -0
  310. package/dist/scan/tarball.js +145 -0
  311. package/dist/scan/tarball.js.map +1 -0
  312. package/dist/scan/templates.d.ts +42 -0
  313. package/dist/scan/templates.d.ts.map +1 -0
  314. package/dist/scan/templates.js +375 -0
  315. package/dist/scan/templates.js.map +1 -0
  316. package/dist/skill-bundle/SKILL.md +146 -0
  317. package/dist/skill-bundle/references/adapting-a-starter.md +104 -0
  318. package/dist/skill-bundle/references/authoring-scenarios.md +184 -0
  319. package/dist/skill-bundle/references/blocks.md +179 -0
  320. package/dist/skill-bundle/references/brief.md +50 -0
  321. package/dist/skill-bundle/references/capture.md +392 -0
  322. package/dist/skill-bundle/references/concrete-tiers.md +95 -0
  323. package/dist/skill-bundle/references/recall.md +36 -0
  324. package/dist/skill-bundle/references/schema.md +114 -0
  325. package/dist/skill-bundle/references/self-check.md +65 -0
  326. package/dist/skill-bundle/references/steering-audit.md +60 -0
  327. package/package.json +79 -0
@@ -0,0 +1,284 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { relative, resolve } from "node:path";
3
+ import { classifyMaterialLocator, closestIds, expandLocalMaterialLocator, extractSkeletonSections, listBundledMaterialFiles, materialLocatorClaimsPath, parseGlossary, parseSourceRef, sliceNodeSection, } from "#ghost-core";
4
+ import { isMissingPathError } from "../internal/fs.js";
5
+ import { GHOST_GLOSSARY_FILENAME, GHOST_MATERIALS_DIR } from "./constants.js";
6
+ import { resolveFingerprintPackage, } from "./fingerprint-package.js";
7
+ import { lintFingerprintPackageManifest, loadFingerprintPackage, } from "./fingerprint-package-loader.js";
8
+ import { resolveGitRoot } from "./package-paths.js";
9
+ /**
10
+ * `validate` for a package: artifact shape, per-node validity, and the
11
+ * deterministic kind-prefix lint enabled by glossary.md. The catalog is flat;
12
+ * loading collects malformed nodes so they can be surfaced as structured issues.
13
+ */
14
+ export async function lintFingerprintPackage(dirArg, cwd = process.cwd()) {
15
+ const paths = resolveFingerprintPackage(dirArg, cwd);
16
+ const issues = [];
17
+ const manifestRaw = await readRequired(paths.manifest, "manifest.yml", issues);
18
+ if (manifestRaw !== undefined) {
19
+ // shape pass: manifest well-formed.
20
+ const beforeManifestErrors = issues.filter((issue) => issue.severity === "error").length;
21
+ lintFingerprintPackageManifest(manifestRaw, issues);
22
+ const manifestHasErrors = issues.filter((issue) => issue.severity === "error").length >
23
+ beforeManifestErrors;
24
+ if (manifestHasErrors)
25
+ return finalize(issues);
26
+ // catalog pass: load + validate the node catalog.
27
+ try {
28
+ const { manifest, catalog, checks, invalid, invalidChecks } = await loadFingerprintPackage(paths);
29
+ // node pass: a node that failed its own schema was skipped while loading
30
+ // the catalog; surface it here so a malformed node is loud, not silent.
31
+ issues.push(...invalid.map((entry) => ({
32
+ severity: "error",
33
+ rule: "node-invalid",
34
+ message: entry.message,
35
+ path: entry.file,
36
+ })));
37
+ issues.push(...invalidChecks.map((entry) => ({
38
+ severity: "error",
39
+ rule: "check-invalid",
40
+ message: entry.message,
41
+ path: entry.file,
42
+ })));
43
+ await lintGlossary(paths.glossary, issues);
44
+ lintCover(manifest.cover, catalog, issues);
45
+ await lintKindPrefixes(paths, catalog, issues);
46
+ lintNodeDescriptions(catalog, issues);
47
+ lintSkeletonSections(catalog, issues);
48
+ await lintMaterialLocators(paths, catalog, issues, cwd);
49
+ lintCheckReferences(catalog, checks, issues);
50
+ }
51
+ catch (err) {
52
+ issues.push({
53
+ severity: "error",
54
+ rule: "package-catalog-invalid",
55
+ message: err instanceof Error ? err.message : String(err),
56
+ path: ".ghost",
57
+ });
58
+ }
59
+ }
60
+ return finalize(issues);
61
+ }
62
+ async function lintGlossary(glossaryPath, issues) {
63
+ let raw;
64
+ try {
65
+ raw = await readFile(glossaryPath, "utf-8");
66
+ }
67
+ catch (err) {
68
+ if (isMissingPathError(err))
69
+ return;
70
+ throw err;
71
+ }
72
+ const result = parseGlossary(raw);
73
+ if (result.glossary !== null)
74
+ return;
75
+ issues.push(...result.errors.map((message) => ({
76
+ severity: "error",
77
+ rule: "glossary-invalid",
78
+ message,
79
+ path: GHOST_GLOSSARY_FILENAME,
80
+ })));
81
+ }
82
+ function lintCover(coverId, catalog, issues) {
83
+ if (coverId === undefined) {
84
+ issues.push({
85
+ severity: "warning",
86
+ rule: "cover-undeclared",
87
+ message: 'no cover declared in manifest.yml — fingerprints steer better with one node guaranteed in context; add "cover: <node-id>"',
88
+ path: "manifest.yml.cover",
89
+ });
90
+ return;
91
+ }
92
+ const cover = catalog.nodes.get(coverId);
93
+ if (cover === undefined) {
94
+ issues.push({
95
+ severity: "error",
96
+ rule: "cover-missing",
97
+ message: `manifest cover "${coverId}" does not match any node`,
98
+ path: "manifest.yml.cover",
99
+ });
100
+ return;
101
+ }
102
+ const bytes = Buffer.byteLength(cover.body, "utf-8");
103
+ if (bytes > 1500) {
104
+ issues.push({
105
+ severity: "warning",
106
+ rule: "cover-oversized",
107
+ message: `cover node "${coverId}" body is ${bytes} bytes — the cover is a one-screen budget; element-scoped rules belong in foundation chapters`,
108
+ path: `${coverId}.md`,
109
+ });
110
+ }
111
+ }
112
+ async function lintKindPrefixes(paths, catalog, issues) {
113
+ const declaredKinds = await readDeclaredGlossaryKinds(paths.glossary);
114
+ if (declaredKinds === undefined)
115
+ return;
116
+ const declared = new Set(declaredKinds);
117
+ for (const node of catalog.nodes.values()) {
118
+ if (node.kind === undefined || declared.has(node.kind))
119
+ continue;
120
+ const suggestions = closestIds(node.kind, declaredKinds, 1);
121
+ const suggestion = suggestions[0];
122
+ issues.push({
123
+ severity: "warning",
124
+ rule: "kind-undeclared",
125
+ message: `Kind prefix \`${node.kind}\` is not declared in ${GHOST_GLOSSARY_FILENAME}.` +
126
+ (suggestion === undefined
127
+ ? " Drop the prefix if this node has no kind."
128
+ : ` Did you mean \`${suggestion}\`? Drop the prefix if this node has no kind.`),
129
+ path: `${node.id}.md`,
130
+ });
131
+ }
132
+ }
133
+ /**
134
+ * The `description` is a node's entire retrieval payload: `gather` lists it as
135
+ * the text the agent selects against. A node without one renders as a bare id
136
+ * and cannot show when it applies, so `validate` makes that loud. Warning,
137
+ * not error: an undescribed node is legal, just undiscoverable.
138
+ */
139
+ function lintNodeDescriptions(catalog, issues) {
140
+ for (const node of catalog.nodes.values()) {
141
+ if (node.description !== undefined && node.description.trim().length > 0) {
142
+ continue;
143
+ }
144
+ issues.push({
145
+ severity: "warning",
146
+ rule: "node-description-missing",
147
+ message: "node has no `description`, so `gather` lists it as a bare id without applicability context; add a one-line description of what this truth governs, when it applies, and what it contributes",
148
+ path: `${node.id}.md`,
149
+ });
150
+ }
151
+ }
152
+ function lintSkeletonSections(catalog, issues) {
153
+ for (const node of catalog.nodes.values()) {
154
+ const sections = extractSkeletonSections(node.body);
155
+ for (const section of sections) {
156
+ if (section.fences.length === 1)
157
+ continue;
158
+ issues.push({
159
+ severity: "warning",
160
+ rule: "skeleton-fence-count",
161
+ message: "## Skeleton section should contain exactly one fenced block; pull will emit all found skeleton fences",
162
+ path: `${node.id}.md`,
163
+ });
164
+ }
165
+ }
166
+ }
167
+ async function lintMaterialLocators(paths, catalog, issues, cwd) {
168
+ const repoRoot = await resolveGitRoot(cwd);
169
+ const options = {
170
+ repoRoot,
171
+ packageDir: paths.packageDir,
172
+ materialsDir: GHOST_MATERIALS_DIR,
173
+ };
174
+ const claimedLocators = [];
175
+ for (const node of catalog.nodes.values()) {
176
+ for (const locator of node.materials ?? []) {
177
+ if (classifyMaterialLocator(locator).kind === "url")
178
+ continue;
179
+ claimedLocators.push(locator);
180
+ const expanded = await expandLocalMaterialLocator(locator, options, {
181
+ cap: Number.POSITIVE_INFINITY,
182
+ });
183
+ if (expanded.matches.length > 0)
184
+ continue;
185
+ issues.push({
186
+ severity: "warning",
187
+ rule: "material-locator-dead",
188
+ message: `material locator '${locator}' matches no local files`,
189
+ path: `${node.id}.md.materials`,
190
+ });
191
+ }
192
+ }
193
+ const bundledFiles = await listBundledMaterialFiles(options);
194
+ for (const file of bundledFiles) {
195
+ const claimed = claimedLocators.some((locator) => materialLocatorClaimsPath(locator, file, options));
196
+ if (claimed)
197
+ continue;
198
+ issues.push({
199
+ severity: "warning",
200
+ rule: "material-orphaned",
201
+ message: "bundled material is not claimed by any node `materials` locator",
202
+ path: toPackageRelative(file, repoRoot, paths.packageDir),
203
+ });
204
+ }
205
+ }
206
+ function toPackageRelative(repoRelativePath, repoRoot, packageDir) {
207
+ const packageRelative = relative(packageDir, resolve(repoRoot, repoRelativePath))
208
+ .replace(/\\/g, "/")
209
+ .replace(/^\.\//, "");
210
+ return packageRelative.startsWith("../") ? repoRelativePath : packageRelative;
211
+ }
212
+ function lintCheckReferences(catalog, checks, issues) {
213
+ for (const check of checks.values()) {
214
+ for (const raw of check.references) {
215
+ const parsed = parseSourceRef(raw);
216
+ if (parsed === null) {
217
+ issues.push({
218
+ severity: "error",
219
+ rule: "check-reference-malformed",
220
+ message: `check reference '${raw}' is not a node id with optional '> Heading' anchor`,
221
+ path: `checks/${check.id}.md.references`,
222
+ });
223
+ continue;
224
+ }
225
+ const node = catalog.nodes.get(parsed.nodeId);
226
+ if (node === undefined) {
227
+ issues.push({
228
+ severity: "warning",
229
+ rule: "check-reference-unresolved",
230
+ message: `check reference '${raw}' does not resolve to a fingerprint node — if you pruned this rule from the node, delete its paired flag in the check too`,
231
+ path: `checks/${check.id}.md.references`,
232
+ });
233
+ continue;
234
+ }
235
+ if (parsed.heading !== undefined &&
236
+ sliceNodeSection(node.body, parsed.heading) === null) {
237
+ issues.push({
238
+ severity: "warning",
239
+ rule: "check-reference-heading-missing",
240
+ message: `check reference '${raw}' names a heading that was not found — if you pruned this rule from the node, delete its paired flag in the check too`,
241
+ path: `checks/${check.id}.md.references`,
242
+ });
243
+ }
244
+ }
245
+ }
246
+ }
247
+ async function readDeclaredGlossaryKinds(glossaryPath) {
248
+ let raw;
249
+ try {
250
+ raw = await readFile(glossaryPath, "utf-8");
251
+ }
252
+ catch (err) {
253
+ if (isMissingPathError(err))
254
+ return undefined;
255
+ throw err;
256
+ }
257
+ const result = parseGlossary(raw);
258
+ if (result.glossary === null)
259
+ return [];
260
+ return result.glossary.frontmatter.kinds.map((kind) => kind.name);
261
+ }
262
+ async function readRequired(path, label, issues) {
263
+ try {
264
+ return await readFile(path, "utf-8");
265
+ }
266
+ catch {
267
+ issues.push({
268
+ severity: "error",
269
+ rule: "package-artifact-missing",
270
+ message: `Fingerprint package is missing ${label}.`,
271
+ path: label,
272
+ });
273
+ return undefined;
274
+ }
275
+ }
276
+ function finalize(issues) {
277
+ return {
278
+ issues,
279
+ errors: issues.filter((issue) => issue.severity === "error").length,
280
+ warnings: issues.filter((issue) => issue.severity === "warning").length,
281
+ info: issues.filter((issue) => issue.severity === "info").length,
282
+ };
283
+ }
284
+ //# sourceMappingURL=fingerprint-package-lint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fingerprint-package-lint.js","sourceRoot":"","sources":["../../src/scan/fingerprint-package-lint.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { FingerprintPackagePaths, LoadedFingerprintPackage } from "./fingerprint-package.js";
2
+ import type { LintIssue } from "./lint.js";
3
+ export declare function loadFingerprintPackage(paths: FingerprintPackagePaths): Promise<LoadedFingerprintPackage>;
4
+ export declare function lintFingerprintPackageManifest(raw: string, issues: LintIssue[]): void;
5
+ //# sourceMappingURL=fingerprint-package-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fingerprint-package-loader.d.ts","sourceRoot":"","sources":["../../src/scan/fingerprint-package-loader.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EACV,uBAAuB,EACvB,wBAAwB,EACzB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAG3C,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,uBAAuB,GAC7B,OAAO,CAAC,wBAAwB,CAAC,CA8BnC;AAED,wBAAgB,8BAA8B,CAC5C,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,SAAS,EAAE,GAClB,IAAI,CAkBN"}
@@ -0,0 +1,78 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { parse as parseYaml } from "yaml";
3
+ import { assembleCatalog, GhostFingerprintPackageManifestSchema, UsageError, } from "#ghost-core";
4
+ import { isMissingPathError } from "../internal/fs.js";
5
+ import { loadCheckFiles } from "./check-files.js";
6
+ import { loadNodeFiles } from "./node-files.js";
7
+ export async function loadFingerprintPackage(paths) {
8
+ let manifestRaw;
9
+ try {
10
+ manifestRaw = await readFile(paths.manifest, "utf-8");
11
+ }
12
+ catch (err) {
13
+ // A missing package is a usage error (run `ghost init`), not a crash.
14
+ if (isMissingPathError(err)) {
15
+ throw new UsageError(`No Ghost fingerprint package found at ${paths.packageDir} (expected manifest.yml). Run \`ghost init\` or pass --package <dir>.`);
16
+ }
17
+ throw err;
18
+ }
19
+ const manifest = parseManifest(manifestRaw, "manifest.yml");
20
+ // The catalog is flat and valid by construction — no edges to resolve.
21
+ // Per-node schema failures are collected as `invalid`.
22
+ const { nodes: placedNodes, invalid } = await loadNodeFiles(paths.packageDir);
23
+ const checkFiles = await loadCheckFiles(paths.packageDir);
24
+ const catalog = assembleCatalog({ placedNodes });
25
+ return {
26
+ manifest,
27
+ manifestRaw,
28
+ catalog,
29
+ hasChecksDir: checkFiles.hasChecksDir,
30
+ checks: checkFiles.checks,
31
+ invalid,
32
+ invalidChecks: checkFiles.invalid,
33
+ };
34
+ }
35
+ export function lintFingerprintPackageManifest(raw, issues) {
36
+ const manifest = parseYamlSafe(raw, "manifest.yml", issues);
37
+ if (manifest === undefined)
38
+ return;
39
+ const manifestResult = GhostFingerprintPackageManifestSchema.safeParse(manifest);
40
+ if (!manifestResult.success) {
41
+ issues.push(...manifestResult.error.issues.map((issue) => ({
42
+ severity: "error",
43
+ rule: `schema/${issue.code}`,
44
+ message: issue.message,
45
+ path: issue.path.length
46
+ ? `manifest.yml.${issue.path.join(".")}`
47
+ : "manifest.yml",
48
+ })));
49
+ return;
50
+ }
51
+ }
52
+ function parseManifest(raw, label) {
53
+ const parsed = parseYamlStrict(raw, label);
54
+ return GhostFingerprintPackageManifestSchema.parse(parsed);
55
+ }
56
+ function parseYamlStrict(raw, label) {
57
+ try {
58
+ return parseYaml(raw);
59
+ }
60
+ catch (err) {
61
+ throw new Error(`${label} is not valid YAML: ${err instanceof Error ? err.message : String(err)}`);
62
+ }
63
+ }
64
+ function parseYamlSafe(raw, label, issues) {
65
+ try {
66
+ return parseYaml(raw);
67
+ }
68
+ catch (err) {
69
+ issues.push({
70
+ severity: "error",
71
+ rule: "package-yaml-invalid",
72
+ message: `${label} is not valid YAML: ${err instanceof Error ? err.message : String(err)}`,
73
+ path: label,
74
+ });
75
+ return undefined;
76
+ }
77
+ }
78
+ //# sourceMappingURL=fingerprint-package-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fingerprint-package-loader.js","sourceRoot":"","sources":["../../src/scan/fingerprint-package-loader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ import { type GhostCatalog, type GhostFingerprintPackageManifest } from "#ghost-core";
2
+ import type { LoadedCheck } from "./check-files.js";
3
+ import { loadFingerprintPackage } from "./fingerprint-package-loader.js";
4
+ export { lintFingerprintPackage } from "./fingerprint-package-lint.js";
5
+ export { loadFingerprintPackage };
6
+ export interface FingerprintPackagePaths {
7
+ dir: string;
8
+ packageDir: string;
9
+ manifest: string;
10
+ glossary: string;
11
+ /** Legacy facet paths — used only to detect pre-flat-corpus packages. */
12
+ intent: string;
13
+ inventory: string;
14
+ composition: string;
15
+ }
16
+ export interface LoadedFingerprintPackage {
17
+ manifest: GhostFingerprintPackageManifest;
18
+ manifestRaw: string;
19
+ /** The in-memory flat node catalog — the only fingerprint model. */
20
+ catalog: GhostCatalog;
21
+ /** Whether `.ghost/checks/` exists; `ghost review` requires it. */
22
+ hasChecksDir: boolean;
23
+ /** Checks from `.ghost/checks/`; never part of gather/pull. */
24
+ checks: Map<string, LoadedCheck>;
25
+ /**
26
+ * Nodes that failed per-node lint and were skipped while loading the catalog,
27
+ * each with its package-relative file path and first error message. Carried
28
+ * so `validate` can surface a malformed node instead of silently dropping it.
29
+ */
30
+ invalid: Array<{
31
+ file: string;
32
+ message: string;
33
+ }>;
34
+ /** Check files that failed lint/loading. */
35
+ invalidChecks: Array<{
36
+ file: string;
37
+ message: string;
38
+ }>;
39
+ }
40
+ export interface InitFingerprintPackageOptions {
41
+ /** Init template name (default: "skeleton"). Mutually exclusive with `body`. */
42
+ template?: string;
43
+ /**
44
+ * Init body name (e.g. "vessel-light"): a full inhabited package with
45
+ * answered dials, materials, and its own checks. Mutually exclusive with
46
+ * `template`.
47
+ */
48
+ body?: string;
49
+ force?: boolean;
50
+ }
51
+ export interface InitFingerprintPackageResult {
52
+ paths: FingerprintPackagePaths;
53
+ /** Package-relative paths of the files the template wrote. */
54
+ written: string[];
55
+ }
56
+ /**
57
+ * Resolve the fingerprint package directory. `dirArg` (an explicit
58
+ * `--package <dir>`) always wins and is used exactly as given — it may be
59
+ * absolute or relative, unlike `GHOST_PACKAGE_DIR`. When `dirArg` is
60
+ * omitted, `GHOST_PACKAGE_DIR` is honored so every command — not just `init`
61
+ * and `validate` — respects a host-configured package location. Falls back
62
+ * to the default `.ghost` when neither is set.
63
+ */
64
+ export declare function resolveFingerprintPackage(dirArg: string | undefined, cwd?: string): FingerprintPackagePaths;
65
+ export declare function initFingerprintPackage(dirArg: string | undefined, cwd?: string, options?: InitFingerprintPackageOptions): Promise<InitFingerprintPackageResult>;
66
+ //# sourceMappingURL=fingerprint-package.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fingerprint-package.d.ts","sourceRoot":"","sources":["../../src/scan/fingerprint-package.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,+BAA+B,EAErC,MAAM,aAAa,CAAC;AAErB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAQpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAazE,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EAAE,sBAAsB,EAAE,CAAC;AAElC,MAAM,WAAW,uBAAuB;IACtC,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,yEAAyE;IACzE,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,+BAA+B,CAAC;IAC1C,WAAW,EAAE,MAAM,CAAC;IACpB,oEAAoE;IACpE,OAAO,EAAE,YAAY,CAAC;IACtB,mEAAmE;IACnE,YAAY,EAAE,OAAO,CAAC;IACtB,+DAA+D;IAC/D,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACjC;;;;OAIG;IACH,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClD,4CAA4C;IAC5C,aAAa,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACzD;AAED,MAAM,WAAW,6BAA6B;IAC5C,gFAAgF;IAChF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,4BAA4B;IAC3C,KAAK,EAAE,uBAAuB,CAAC;IAC/B,8DAA8D;IAC9D,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,GAAG,SAAgB,GAClB,uBAAuB,CAYzB;AAED,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,GAAG,SAAgB,EACnB,OAAO,GAAE,6BAAkC,GAC1C,OAAO,CAAC,4BAA4B,CAAC,CAiDvC"}
@@ -0,0 +1,101 @@
1
+ import { access, mkdir, writeFile } from "node:fs/promises";
2
+ import { dirname, join, resolve } from "node:path";
3
+ import { UsageError, } from "#ghost-core";
4
+ import { isExistingPathError, isMissingPathError } from "../internal/fs.js";
5
+ import { FINGERPRINT_COMPOSITION_FILENAME, FINGERPRINT_INTENT_FILENAME, FINGERPRINT_INVENTORY_FILENAME, FINGERPRINT_MANIFEST_FILENAME, GHOST_GLOSSARY_FILENAME, } from "./constants.js";
6
+ import { loadFingerprintPackage } from "./fingerprint-package-loader.js";
7
+ import { resolveGhostDirDefault } from "./package-paths.js";
8
+ import { DEFAULT_TEMPLATE_NAME, getInitBody, getInitTemplate, listInitBodies, listInitTemplates, } from "./templates.js";
9
+ // The lint pass lives beside this module; re-export it so `validate` callers
10
+ // keep a single import site for package loading and linting.
11
+ export { lintFingerprintPackage } from "./fingerprint-package-lint.js";
12
+ export { loadFingerprintPackage };
13
+ /**
14
+ * Resolve the fingerprint package directory. `dirArg` (an explicit
15
+ * `--package <dir>`) always wins and is used exactly as given — it may be
16
+ * absolute or relative, unlike `GHOST_PACKAGE_DIR`. When `dirArg` is
17
+ * omitted, `GHOST_PACKAGE_DIR` is honored so every command — not just `init`
18
+ * and `validate` — respects a host-configured package location. Falls back
19
+ * to the default `.ghost` when neither is set.
20
+ */
21
+ export function resolveFingerprintPackage(dirArg, cwd = process.cwd()) {
22
+ const dir = resolve(cwd, dirArg ?? resolveGhostDirDefault());
23
+ const packageDir = dir;
24
+ return {
25
+ dir,
26
+ packageDir,
27
+ manifest: join(packageDir, FINGERPRINT_MANIFEST_FILENAME),
28
+ glossary: join(packageDir, GHOST_GLOSSARY_FILENAME),
29
+ intent: join(packageDir, FINGERPRINT_INTENT_FILENAME),
30
+ inventory: join(packageDir, FINGERPRINT_INVENTORY_FILENAME),
31
+ composition: join(packageDir, FINGERPRINT_COMPOSITION_FILENAME),
32
+ };
33
+ }
34
+ export async function initFingerprintPackage(dirArg, cwd = process.cwd(), options = {}) {
35
+ if (options.body !== undefined && options.template !== undefined) {
36
+ throw new UsageError("--body and --template are mutually exclusive. A template is a shape of emptiness; a body is a full inhabited package — pick one.");
37
+ }
38
+ let source;
39
+ if (options.body !== undefined) {
40
+ const body = getInitBody(options.body);
41
+ if (!body) {
42
+ throw new UsageError(`Unknown init body '${options.body}'. Available: ${listInitBodies().join(", ")}.`);
43
+ }
44
+ source = body;
45
+ }
46
+ else {
47
+ const templateName = options.template ?? DEFAULT_TEMPLATE_NAME;
48
+ const template = getInitTemplate(templateName);
49
+ if (!template) {
50
+ throw new UsageError(`Unknown init template '${templateName}'. Available: ${listInitTemplates().join(", ")}.`);
51
+ }
52
+ source = template;
53
+ }
54
+ const paths = resolveFingerprintPackage(dirArg, cwd);
55
+ await mkdir(paths.packageDir, { recursive: true });
56
+ const files = (await source.files()).map((file) => ({
57
+ relativePath: file.relativePath,
58
+ path: join(paths.packageDir, file.relativePath),
59
+ content: file.content,
60
+ }));
61
+ if (!options.force) {
62
+ await assertInitDoesNotOverwrite(files.map((file) => file.path));
63
+ }
64
+ // Create any nested directories the template needs (e.g. nodes/).
65
+ const dirs = new Set(files.map((file) => dirname(file.path)));
66
+ await Promise.all([...dirs].map((dir) => mkdir(dir, { recursive: true })));
67
+ await Promise.all(files.map((file) => writeInitFile(file.path, file.content, options.force)));
68
+ return { paths, written: files.map((file) => file.relativePath) };
69
+ }
70
+ async function writeInitFile(path, content, force = false) {
71
+ try {
72
+ await writeFile(path, content, typeof content === "string"
73
+ ? { encoding: "utf-8", flag: force ? "w" : "wx" }
74
+ : { flag: force ? "w" : "wx" });
75
+ }
76
+ catch (err) {
77
+ if (!force && isExistingPathError(err)) {
78
+ throw new UsageError(`Refusing to overwrite existing Ghost fingerprint file:\n ${path}\nPass --force to overwrite.`);
79
+ }
80
+ throw err;
81
+ }
82
+ }
83
+ async function assertInitDoesNotOverwrite(paths) {
84
+ const existing = [];
85
+ for (const path of paths) {
86
+ try {
87
+ await access(path);
88
+ existing.push(path);
89
+ }
90
+ catch (err) {
91
+ if (isMissingPathError(err))
92
+ continue;
93
+ throw err;
94
+ }
95
+ }
96
+ if (existing.length > 0) {
97
+ const formatted = existing.map((path) => ` ${path}`).join("\n");
98
+ throw new UsageError(`Refusing to overwrite existing Ghost fingerprint file(s):\n${formatted}\nPass --force to overwrite.`);
99
+ }
100
+ }
101
+ //# sourceMappingURL=fingerprint-package.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fingerprint-package.js","sourceRoot":"","sources":["../../src/scan/fingerprint-package.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { FINGERPRINT_PACKAGE_DIR } from "./constants.js";
2
+ export { GHOST_PACKAGE_DIR_ENV, normalizeGhostDir, resolveGhostDirDefault, resolveGitRoot, } from "./package-paths.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/scan/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,sBAAsB,EACtB,cAAc,GACf,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { FINGERPRINT_PACKAGE_DIR } from "./constants.js";
2
+ export { GHOST_PACKAGE_DIR_ENV, normalizeGhostDir, resolveGhostDirDefault, resolveGitRoot, } from "./package-paths.js";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/scan/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,sBAAsB,EACtB,cAAc,GACf,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,15 @@
1
+ export type LintSeverity = "error" | "warning" | "info";
2
+ export interface LintIssue {
3
+ severity: LintSeverity;
4
+ rule: string;
5
+ message: string;
6
+ /** Dotted path in the file (e.g. "intent.principles[0].evidence"). */
7
+ path?: string;
8
+ }
9
+ export interface LintReport {
10
+ issues: LintIssue[];
11
+ errors: number;
12
+ warnings: number;
13
+ info: number;
14
+ }
15
+ //# sourceMappingURL=lint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lint.d.ts","sourceRoot":"","sources":["../../src/scan/lint.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AAExD,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,YAAY,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,sEAAsE;IACtE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=lint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lint.js","sourceRoot":"","sources":["../../src/scan/lint.ts"],"names":[],"mappings":""}
@@ -0,0 +1,25 @@
1
+ import { type PlacedNode } from "#ghost-core";
2
+ export interface LoadedNodeFiles {
3
+ nodes: PlacedNode[];
4
+ /** Files that failed lint, with their first error message (path-relative id). */
5
+ invalid: Array<{
6
+ file: string;
7
+ message: string;
8
+ }>;
9
+ }
10
+ /**
11
+ * Load authored prose nodes from the package directory. The corpus is flat:
12
+ * there is no hierarchy, no inheritance, no edges. Nesting into directories is a
13
+ * browsing convenience only.
14
+ *
15
+ * Every `*.md` file under the package directory is a node. Its id is its path
16
+ * with `.md` dropped, uniformly (`marketing/email.md` → `marketing/email`,
17
+ * `index.md` → `index`). The reserved root entries — `manifest.yml`,
18
+ * `glossary.md`, `materials/`, and `checks/` — are skipped.
19
+ *
20
+ * A file that fails per-node lint is collected in `invalid` (with its first
21
+ * error) and skipped rather than throwing, so one bad node does not block
22
+ * loading the rest. A missing package directory or empty corpus yields no nodes.
23
+ */
24
+ export declare function loadNodeFiles(packageDir: string): Promise<LoadedNodeFiles>;
25
+ //# sourceMappingURL=node-files.d.ts.map