@design-intelligence/ghost 0.20.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 (269) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +75 -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 +45 -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 +74 -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 +152 -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 +79 -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 +224 -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 +257 -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 +77 -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 +30 -0
  64. package/dist/ghost-core/catalog/assemble.d.ts.map +1 -0
  65. package/dist/ghost-core/catalog/assemble.js +38 -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 +36 -0
  76. package/dist/ghost-core/catalog/menu.d.ts.map +1 -0
  77. package/dist/ghost-core/catalog/menu.js +27 -0
  78. package/dist/ghost-core/catalog/menu.js.map +1 -0
  79. package/dist/ghost-core/catalog/types.d.ts +37 -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 +38 -0
  116. package/dist/ghost-core/glossary.d.ts.map +1 -0
  117. package/dist/ghost-core/glossary.js +76 -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 +11 -0
  148. package/dist/ghost-core/node/serialize.d.ts.map +1 -0
  149. package/dist/ghost-core/node/serialize.js +21 -0
  150. package/dist/ghost-core/node/serialize.js.map +1 -0
  151. package/dist/ghost-core/node/steering.d.ts +18 -0
  152. package/dist/ghost-core/node/steering.d.ts.map +1 -0
  153. package/dist/ghost-core/node/steering.js +65 -0
  154. package/dist/ghost-core/node/steering.js.map +1 -0
  155. package/dist/ghost-core/node/types.d.ts +42 -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 +12 -0
  160. package/dist/ghost-core/package-manifest.d.ts.map +1 -0
  161. package/dist/ghost-core/package-manifest.js +14 -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/internal/fs.d.ts +4 -0
  172. package/dist/internal/fs.d.ts.map +1 -0
  173. package/dist/internal/fs.js +24 -0
  174. package/dist/internal/fs.js.map +1 -0
  175. package/dist/observability-events.d.ts +27 -0
  176. package/dist/observability-events.d.ts.map +1 -0
  177. package/dist/observability-events.js +56 -0
  178. package/dist/observability-events.js.map +1 -0
  179. package/dist/package-version.d.ts +3 -0
  180. package/dist/package-version.d.ts.map +1 -0
  181. package/dist/package-version.js +10 -0
  182. package/dist/package-version.js.map +1 -0
  183. package/dist/review/baseline.d.ts +11 -0
  184. package/dist/review/baseline.d.ts.map +1 -0
  185. package/dist/review/baseline.js +35 -0
  186. package/dist/review/baseline.js.map +1 -0
  187. package/dist/review/diff.d.ts +7 -0
  188. package/dist/review/diff.d.ts.map +1 -0
  189. package/dist/review/diff.js +41 -0
  190. package/dist/review/diff.js.map +1 -0
  191. package/dist/review/glob.d.ts +2 -0
  192. package/dist/review/glob.d.ts.map +1 -0
  193. package/dist/review/glob.js +2 -0
  194. package/dist/review/glob.js.map +1 -0
  195. package/dist/review/probes.d.ts +13 -0
  196. package/dist/review/probes.d.ts.map +1 -0
  197. package/dist/review/probes.js +45 -0
  198. package/dist/review/probes.js.map +1 -0
  199. package/dist/review/resolve.d.ts +29 -0
  200. package/dist/review/resolve.d.ts.map +1 -0
  201. package/dist/review/resolve.js +87 -0
  202. package/dist/review/resolve.js.map +1 -0
  203. package/dist/review/review-packet.d.ts +40 -0
  204. package/dist/review/review-packet.d.ts.map +1 -0
  205. package/dist/review/review-packet.js +139 -0
  206. package/dist/review/review-packet.js.map +1 -0
  207. package/dist/scan/check-files.d.ts +23 -0
  208. package/dist/scan/check-files.d.ts.map +1 -0
  209. package/dist/scan/check-files.js +90 -0
  210. package/dist/scan/check-files.js.map +1 -0
  211. package/dist/scan/check-scaffold.d.ts +7 -0
  212. package/dist/scan/check-scaffold.d.ts.map +1 -0
  213. package/dist/scan/check-scaffold.js +37 -0
  214. package/dist/scan/check-scaffold.js.map +1 -0
  215. package/dist/scan/constants.d.ts +21 -0
  216. package/dist/scan/constants.d.ts.map +1 -0
  217. package/dist/scan/constants.js +21 -0
  218. package/dist/scan/constants.js.map +1 -0
  219. package/dist/scan/file-kind.d.ts +12 -0
  220. package/dist/scan/file-kind.d.ts.map +1 -0
  221. package/dist/scan/file-kind.js +114 -0
  222. package/dist/scan/file-kind.js.map +1 -0
  223. package/dist/scan/fingerprint-package-loader.d.ts +5 -0
  224. package/dist/scan/fingerprint-package-loader.d.ts.map +1 -0
  225. package/dist/scan/fingerprint-package-loader.js +105 -0
  226. package/dist/scan/fingerprint-package-loader.js.map +1 -0
  227. package/dist/scan/fingerprint-package.d.ts +58 -0
  228. package/dist/scan/fingerprint-package.d.ts.map +1 -0
  229. package/dist/scan/fingerprint-package.js +301 -0
  230. package/dist/scan/fingerprint-package.js.map +1 -0
  231. package/dist/scan/index.d.ts +3 -0
  232. package/dist/scan/index.d.ts.map +1 -0
  233. package/dist/scan/index.js +3 -0
  234. package/dist/scan/index.js.map +1 -0
  235. package/dist/scan/lint.d.ts +15 -0
  236. package/dist/scan/lint.d.ts.map +1 -0
  237. package/dist/scan/lint.js +2 -0
  238. package/dist/scan/lint.js.map +1 -0
  239. package/dist/scan/node-files.d.ts +25 -0
  240. package/dist/scan/node-files.d.ts.map +1 -0
  241. package/dist/scan/node-files.js +114 -0
  242. package/dist/scan/node-files.js.map +1 -0
  243. package/dist/scan/package-paths.d.ts +10 -0
  244. package/dist/scan/package-paths.d.ts.map +1 -0
  245. package/dist/scan/package-paths.js +49 -0
  246. package/dist/scan/package-paths.js.map +1 -0
  247. package/dist/scan/steering-template.d.ts +8 -0
  248. package/dist/scan/steering-template.d.ts.map +1 -0
  249. package/dist/scan/steering-template.js +266 -0
  250. package/dist/scan/steering-template.js.map +1 -0
  251. package/dist/scan/tarball.d.ts +23 -0
  252. package/dist/scan/tarball.d.ts.map +1 -0
  253. package/dist/scan/tarball.js +145 -0
  254. package/dist/scan/tarball.js.map +1 -0
  255. package/dist/scan/templates.d.ts +24 -0
  256. package/dist/scan/templates.d.ts.map +1 -0
  257. package/dist/scan/templates.js +295 -0
  258. package/dist/scan/templates.js.map +1 -0
  259. package/dist/skill-bundle/SKILL.md +140 -0
  260. package/dist/skill-bundle/references/authoring-scenarios.md +147 -0
  261. package/dist/skill-bundle/references/blocks.md +180 -0
  262. package/dist/skill-bundle/references/brief.md +49 -0
  263. package/dist/skill-bundle/references/capture.md +377 -0
  264. package/dist/skill-bundle/references/recall.md +38 -0
  265. package/dist/skill-bundle/references/schema.md +119 -0
  266. package/dist/skill-bundle/references/self-check.md +65 -0
  267. package/dist/skill-bundle/references/steering-audit.md +61 -0
  268. package/dist/skill-bundle/references/wild.md +30 -0
  269. package/package.json +79 -0
@@ -0,0 +1,231 @@
1
+ import { readdir, readFile, stat } from "node:fs/promises";
2
+ import { isAbsolute, join, relative, resolve } from "node:path";
3
+ import { TextDecoder } from "node:util";
4
+ import { hasGlobMagic, matchesGlob, normalizeGlobPath } from "./glob.js";
5
+ import { classifyMaterialLocator } from "./materials.js";
6
+ const DEFAULT_MATERIALS_DIR = "materials";
7
+ const DEFAULT_GLOB_CAP = 12;
8
+ const DEFAULT_REFERENCED_INLINE_BYTES = 8 * 1024;
9
+ const textDecoder = new TextDecoder("utf-8", { fatal: true });
10
+ export async function transportMaterials(locators, options) {
11
+ const materials = [];
12
+ let inlined = 0;
13
+ let omitted = 0;
14
+ for (const locator of locators ?? []) {
15
+ const classified = classifyMaterialLocator(locator);
16
+ if (classified.kind === "url") {
17
+ materials.push({
18
+ locator,
19
+ tier: "url",
20
+ omitted: true,
21
+ reason: "HTTPS URL; fetch it only if the task requires it",
22
+ });
23
+ omitted += 1;
24
+ continue;
25
+ }
26
+ const expanded = await expandLocalMaterialLocator(locator, options, {
27
+ cap: options.globCap ?? DEFAULT_GLOB_CAP,
28
+ });
29
+ const globbed = hasGlobMagic(locator);
30
+ if (expanded.matches.length === 0) {
31
+ materials.push({
32
+ locator,
33
+ tier: expanded.tier,
34
+ omitted: true,
35
+ reason: "matched no local files",
36
+ });
37
+ omitted += 1;
38
+ continue;
39
+ }
40
+ for (const match of expanded.matches) {
41
+ const transported = await transportFile(globbed ? match.repoRelativePath : locator, match, expanded.tier, options);
42
+ materials.push(transported);
43
+ if (transported.inlined !== undefined)
44
+ inlined += 1;
45
+ if (transported.omitted)
46
+ omitted += 1;
47
+ }
48
+ if (expanded.truncated) {
49
+ materials.push({
50
+ locator,
51
+ tier: expanded.tier,
52
+ omitted: true,
53
+ reason: `glob matched more than ${options.globCap ?? DEFAULT_GLOB_CAP} files; omitted the rest`,
54
+ });
55
+ omitted += 1;
56
+ }
57
+ }
58
+ return { materials, inlined, omitted };
59
+ }
60
+ export async function expandLocalMaterialLocator(locator, options, expandOptions = {}) {
61
+ const resolved = resolveLocalMaterialLocator(locator, options);
62
+ const cap = expandOptions.cap ?? Number.POSITIVE_INFINITY;
63
+ if (!hasGlobMagic(locator)) {
64
+ const absolutePath = resolve(options.repoRoot, resolved.pattern);
65
+ try {
66
+ const s = await stat(absolutePath);
67
+ return {
68
+ locator,
69
+ tier: resolved.tier,
70
+ pattern: resolved.pattern,
71
+ matches: s.isFile()
72
+ ? [{ absolutePath, repoRelativePath: resolved.pattern }]
73
+ : [],
74
+ truncated: false,
75
+ };
76
+ }
77
+ catch {
78
+ return {
79
+ locator,
80
+ tier: resolved.tier,
81
+ pattern: resolved.pattern,
82
+ matches: [],
83
+ truncated: false,
84
+ };
85
+ }
86
+ }
87
+ const base = globLiteralBase(resolved.pattern);
88
+ const baseAbs = resolve(options.repoRoot, base);
89
+ const found = [];
90
+ await walkFiles(baseAbs, options.repoRoot, found, cap + 1, resolved.pattern);
91
+ return {
92
+ locator,
93
+ tier: resolved.tier,
94
+ pattern: resolved.pattern,
95
+ matches: found.slice(0, cap),
96
+ truncated: found.length > cap,
97
+ };
98
+ }
99
+ export async function listBundledMaterialFiles(options) {
100
+ const materialsDir = options.materialsDir ?? DEFAULT_MATERIALS_DIR;
101
+ const bundledDir = join(options.packageDir, materialsDir);
102
+ const files = [];
103
+ await walkFiles(bundledDir, options.repoRoot, files, Number.POSITIVE_INFINITY);
104
+ return files.map((file) => file.repoRelativePath).sort();
105
+ }
106
+ export function materialLocatorClaimsPath(locator, repoRelativePath, options) {
107
+ if (classifyMaterialLocator(locator).kind === "url")
108
+ return false;
109
+ const resolved = resolveLocalMaterialLocator(locator, options);
110
+ const normalizedPath = normalizeGlobPath(repoRelativePath);
111
+ return hasGlobMagic(locator)
112
+ ? matchesGlob(resolved.pattern, normalizedPath)
113
+ : resolved.pattern === normalizedPath;
114
+ }
115
+ export function resolveLocalMaterialLocator(locator, options) {
116
+ const materialsDir = options.materialsDir ?? DEFAULT_MATERIALS_DIR;
117
+ const normalized = normalizeGlobPath(locator);
118
+ const packageMaterialsDir = resolve(options.packageDir, materialsDir);
119
+ const packageRelative = normalized === materialsDir || normalized.startsWith(`${materialsDir}/`);
120
+ const pattern = packageRelative
121
+ ? toRepoRelative(resolve(options.packageDir, normalized), options.repoRoot)
122
+ : normalized;
123
+ const absolutePattern = resolve(options.repoRoot, pattern);
124
+ const tier = packageRelative || isInsideOrEqual(absolutePattern, packageMaterialsDir)
125
+ ? "bundled"
126
+ : "referenced";
127
+ return { tier, pattern };
128
+ }
129
+ async function transportFile(locator, match, tier, options) {
130
+ const base = { locator, tier, path: match.repoRelativePath };
131
+ let s;
132
+ try {
133
+ s = await stat(match.absolutePath);
134
+ }
135
+ catch {
136
+ return {
137
+ ...base,
138
+ omitted: true,
139
+ reason: "matched file could not be read",
140
+ };
141
+ }
142
+ if (!s.isFile()) {
143
+ return { ...base, omitted: true, reason: "not a file" };
144
+ }
145
+ const inlineLimit = options.referencedInlineBytes ?? DEFAULT_REFERENCED_INLINE_BYTES;
146
+ if (tier === "referenced" && s.size > inlineLimit) {
147
+ return {
148
+ ...base,
149
+ omitted: true,
150
+ reason: `exceeds ${formatBytes(inlineLimit)} inline limit`,
151
+ };
152
+ }
153
+ let buffer;
154
+ try {
155
+ buffer = await readFile(match.absolutePath);
156
+ }
157
+ catch {
158
+ return {
159
+ ...base,
160
+ omitted: true,
161
+ reason: "matched file could not be read",
162
+ };
163
+ }
164
+ if (isBinary(buffer)) {
165
+ return {
166
+ ...base,
167
+ omitted: true,
168
+ reason: "binary inspect-pointer",
169
+ };
170
+ }
171
+ try {
172
+ return { ...base, inlined: textDecoder.decode(buffer) };
173
+ }
174
+ catch {
175
+ return { ...base, omitted: true, reason: "not valid UTF-8 text" };
176
+ }
177
+ }
178
+ async function walkFiles(dir, repoRoot, files, limit, glob) {
179
+ if (files.length >= limit)
180
+ return;
181
+ let entries;
182
+ try {
183
+ entries = await readdir(dir, { withFileTypes: true });
184
+ }
185
+ catch {
186
+ return;
187
+ }
188
+ for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
189
+ if (files.length >= limit)
190
+ return;
191
+ if (entry.name === ".git")
192
+ continue;
193
+ const absolutePath = join(dir, entry.name);
194
+ if (entry.isDirectory()) {
195
+ await walkFiles(absolutePath, repoRoot, files, limit, glob);
196
+ continue;
197
+ }
198
+ if (!entry.isFile())
199
+ continue;
200
+ const repoRelativePath = toRepoRelative(absolutePath, repoRoot);
201
+ if (glob === undefined || matchesGlob(glob, repoRelativePath)) {
202
+ files.push({ absolutePath, repoRelativePath });
203
+ }
204
+ }
205
+ }
206
+ function globLiteralBase(pattern) {
207
+ const segments = normalizeGlobPath(pattern).split("/");
208
+ const literal = [];
209
+ for (const segment of segments) {
210
+ if (hasGlobMagic(segment))
211
+ break;
212
+ literal.push(segment);
213
+ }
214
+ const base = literal.join("/");
215
+ return base === "" ? "." : base;
216
+ }
217
+ function toRepoRelative(path, repoRoot) {
218
+ const rel = relative(repoRoot, path);
219
+ return normalizeGlobPath(rel === "" ? "." : rel);
220
+ }
221
+ function isInsideOrEqual(child, parent) {
222
+ const rel = relative(parent, child);
223
+ return rel === "" || (!rel.startsWith("..") && !isAbsolute(rel));
224
+ }
225
+ function isBinary(buffer) {
226
+ return buffer.includes(0);
227
+ }
228
+ function formatBytes(bytes) {
229
+ return bytes % 1024 === 0 ? `${bytes / 1024} KB` : `${bytes} bytes`;
230
+ }
231
+ //# sourceMappingURL=material-transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"material-transport.js","sourceRoot":"","sources":["../../src/ghost-core/material-transport.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /** Material locator support for fingerprint nodes. */
2
+ export type GhostMaterialLocatorKind = "local" | "url";
3
+ export interface ClassifiedGhostMaterialLocator {
4
+ kind: GhostMaterialLocatorKind;
5
+ value: string;
6
+ }
7
+ /**
8
+ * Classify a material locator. `https://…` locators point outside the repo;
9
+ * everything else is a repo-relative path/glob after validation.
10
+ */
11
+ export declare function classifyMaterialLocator(value: string): ClassifiedGhostMaterialLocator;
12
+ /** Return a human-readable validation error, or null when the locator is valid. */
13
+ export declare function validateMaterialLocator(value: string): string | null;
14
+ //# sourceMappingURL=materials.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"materials.d.ts","sourceRoot":"","sources":["../../src/ghost-core/materials.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,MAAM,MAAM,wBAAwB,GAAG,OAAO,GAAG,KAAK,CAAC;AAEvD,MAAM,WAAW,8BAA8B;IAC7C,IAAI,EAAE,wBAAwB,CAAC;IAC/B,KAAK,EAAE,MAAM,CAAC;CACf;AAID;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,MAAM,GACZ,8BAA8B,CAIhC;AAED,mFAAmF;AACnF,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA0CpE"}
@@ -0,0 +1,52 @@
1
+ const URL_SCHEME = /^[a-z][a-z0-9+.-]*:/i;
2
+ /**
3
+ * Classify a material locator. `https://…` locators point outside the repo;
4
+ * everything else is a repo-relative path/glob after validation.
5
+ */
6
+ export function classifyMaterialLocator(value) {
7
+ return value.startsWith("https://")
8
+ ? { kind: "url", value }
9
+ : { kind: "local", value };
10
+ }
11
+ /** Return a human-readable validation error, or null when the locator is valid. */
12
+ export function validateMaterialLocator(value) {
13
+ if (value.trim() !== value) {
14
+ return "material locator must not have leading or trailing whitespace";
15
+ }
16
+ if (value.length === 0) {
17
+ return "material locator must not be empty";
18
+ }
19
+ if (URL_SCHEME.test(value)) {
20
+ if (!value.startsWith("https://")) {
21
+ return "material URL locators must use https://";
22
+ }
23
+ try {
24
+ const url = new URL(value);
25
+ if (url.protocol !== "https:" || url.hostname.length === 0) {
26
+ return "material URL locators must be absolute https URLs";
27
+ }
28
+ return null;
29
+ }
30
+ catch {
31
+ return "material URL locator is not a valid URL";
32
+ }
33
+ }
34
+ if (value.startsWith("/") || value.startsWith("\\")) {
35
+ return "local material locators must be repo-relative, not absolute paths";
36
+ }
37
+ if (/^[a-zA-Z]:[\\/]/.test(value)) {
38
+ return "local material locators must be repo-relative, not absolute paths";
39
+ }
40
+ const normalized = value.replace(/\\/g, "/");
41
+ if (normalized === ".." ||
42
+ normalized.startsWith("../") ||
43
+ normalized.endsWith("/..") ||
44
+ normalized.includes("/../")) {
45
+ return "local material locators must not escape the repo with '..'";
46
+ }
47
+ if (normalized.startsWith("~/")) {
48
+ return "local material locators must be repo-relative, not home-relative paths";
49
+ }
50
+ return null;
51
+ }
52
+ //# sourceMappingURL=materials.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"materials.js","sourceRoot":"","sources":["../../src/ghost-core/materials.ts"],"names":[],"mappings":"AAQA,MAAM,UAAU,GAAG,sBAAsB,CAAC;AAE1C;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CACrC,KAAa;IAEb,OAAO,KAAK,CAAC,UAAU,CAAC,UAAU,CAAC;QACjC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE;QACxB,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAC/B,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,uBAAuB,CAAC,KAAa;IACnD,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,KAAK,EAAE,CAAC;QAC3B,OAAO,+DAA+D,CAAC;IACzE,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,oCAAoC,CAAC;IAC9C,CAAC;IAED,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3B,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAClC,OAAO,yCAAyC,CAAC;QACnD,CAAC;QACD,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;YAC3B,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,IAAI,GAAG,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC3D,OAAO,mDAAmD,CAAC;YAC7D,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,yCAAyC,CAAC;QACnD,CAAC;IACH,CAAC;IAED,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACpD,OAAO,mEAAmE,CAAC;IAC7E,CAAC;IACD,IAAI,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAClC,OAAO,mEAAmE,CAAC;IAC7E,CAAC;IACD,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC7C,IACE,UAAU,KAAK,IAAI;QACnB,UAAU,CAAC,UAAU,CAAC,KAAK,CAAC;QAC5B,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC;QAC1B,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,EAC3B,CAAC;QACD,OAAO,4DAA4D,CAAC;IACtE,CAAC;IACD,IAAI,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QAChC,OAAO,wEAAwE,CAAC;IAClF,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Public surface for `ghost.node/v1` — the node artifact: markdown +
3
+ * frontmatter, the single unit a fingerprint corpus is made of: schema +
4
+ * types + parse + serialize.
5
+ */
6
+ export { lintGhostNode, type ParseNodeResult, parseNode } from "./parse.js";
7
+ export { GhostNodeFrontmatterSchema, NodeIdSchema, NodeRefSchema, } from "./schema.js";
8
+ export { serializeNode } from "./serialize.js";
9
+ export { carriesConcreteMaterial, extractSkeletonFences, extractSkeletonSections, type FencedBlock, hasThreeLineFence, type SkeletonSection, stripSkeletonSections, } from "./steering.js";
10
+ export { GHOST_NODE_SCHEMA, type GhostNodeDocument, type GhostNodeFrontmatter, type GhostNodeLintIssue, type GhostNodeLintReport, type GhostNodeLintSeverity, } from "./types.js";
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ghost-core/node/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,aAAa,EAAE,KAAK,eAAe,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5E,OAAO,EACL,0BAA0B,EAC1B,YAAY,EACZ,aAAa,GACd,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,uBAAuB,EACvB,KAAK,WAAW,EAChB,iBAAiB,EACjB,KAAK,eAAe,EACpB,qBAAqB,GACtB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,iBAAiB,EACjB,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,GAC3B,MAAM,YAAY,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Public surface for `ghost.node/v1` — the node artifact: markdown +
3
+ * frontmatter, the single unit a fingerprint corpus is made of: schema +
4
+ * types + parse + serialize.
5
+ */
6
+ export { lintGhostNode, parseNode } from "./parse.js";
7
+ export { GhostNodeFrontmatterSchema, NodeIdSchema, NodeRefSchema, } from "./schema.js";
8
+ export { serializeNode } from "./serialize.js";
9
+ export { carriesConcreteMaterial, extractSkeletonFences, extractSkeletonSections, hasThreeLineFence, stripSkeletonSections, } from "./steering.js";
10
+ export { GHOST_NODE_SCHEMA, } from "./types.js";
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/ghost-core/node/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,aAAa,EAAwB,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5E,OAAO,EACL,0BAA0B,EAC1B,YAAY,EACZ,aAAa,GACd,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,uBAAuB,EAEvB,iBAAiB,EAEjB,qBAAqB,GACtB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,iBAAiB,GAMlB,MAAM,YAAY,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { GhostNodeDocument, GhostNodeLintReport } from "./types.js";
2
+ export interface ParseNodeResult {
3
+ /** The validated node, or null when the artifact failed to parse/validate. */
4
+ node: GhostNodeDocument | null;
5
+ report: GhostNodeLintReport;
6
+ }
7
+ /**
8
+ * Parse and validate a single `ghost.node/v1` markdown artifact (frontmatter +
9
+ * prose body) in isolation. Per-node only: frontmatter shape, material
10
+ * locators, and a non-empty prose body. Corpus-level rules (glossary kind
11
+ * prefixes, check references) are a later phase.
12
+ */
13
+ export declare function parseNode(raw: string): ParseNodeResult;
14
+ /** Lint a node artifact, returning only the report (per-node validation). */
15
+ export declare function lintGhostNode(raw: string): GhostNodeLintReport;
16
+ //# sourceMappingURL=parse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../../src/ghost-core/node/parse.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,iBAAiB,EAEjB,mBAAmB,EACpB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,eAAe;IAC9B,8EAA8E;IAC9E,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC/B,MAAM,EAAE,mBAAmB,CAAC;CAC7B;AAWD;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAuCtD;AAED,6EAA6E;AAC7E,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,mBAAmB,CAE9D"}
@@ -0,0 +1,55 @@
1
+ import { splitMarkdownFrontmatter } from "../markdown.js";
2
+ import { GhostNodeFrontmatterSchema } from "./schema.js";
3
+ function finalize(issues) {
4
+ return {
5
+ issues,
6
+ errors: issues.filter((i) => i.severity === "error").length,
7
+ warnings: issues.filter((i) => i.severity === "warning").length,
8
+ info: issues.filter((i) => i.severity === "info").length,
9
+ };
10
+ }
11
+ /**
12
+ * Parse and validate a single `ghost.node/v1` markdown artifact (frontmatter +
13
+ * prose body) in isolation. Per-node only: frontmatter shape, material
14
+ * locators, and a non-empty prose body. Corpus-level rules (glossary kind
15
+ * prefixes, check references) are a later phase.
16
+ */
17
+ export function parseNode(raw) {
18
+ const { frontmatter, body } = splitMarkdownFrontmatter(raw);
19
+ if (frontmatter === null) {
20
+ return {
21
+ node: null,
22
+ report: finalize([
23
+ {
24
+ severity: "error",
25
+ rule: "node-missing-frontmatter",
26
+ message: "node must begin with a YAML frontmatter block (---\\n<yaml>\\n---)",
27
+ },
28
+ ]),
29
+ };
30
+ }
31
+ // The body is design-expression content; surrounding blank lines are not
32
+ // meaningful. Normalize them so serialize → parse round-trips are stable.
33
+ const normalizedBody = body.replace(/^\n+/, "").replace(/\s+$/, "");
34
+ const result = GhostNodeFrontmatterSchema.safeParse(frontmatter);
35
+ if (!result.success) {
36
+ return {
37
+ node: null,
38
+ report: finalize(result.error.issues.map((issue) => ({
39
+ severity: "error",
40
+ rule: `schema/${issue.code}`,
41
+ message: issue.message,
42
+ path: issue.path.length ? issue.path.join(".") : undefined,
43
+ }))),
44
+ };
45
+ }
46
+ return {
47
+ node: { frontmatter: result.data, body: normalizedBody },
48
+ report: finalize([]),
49
+ };
50
+ }
51
+ /** Lint a node artifact, returning only the report (per-node validation). */
52
+ export function lintGhostNode(raw) {
53
+ return parseNode(raw).report;
54
+ }
55
+ //# sourceMappingURL=parse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.js","sourceRoot":"","sources":["../../../src/ghost-core/node/parse.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC;AAazD,SAAS,QAAQ,CAAC,MAA4B;IAC5C,OAAO;QACL,MAAM;QACN,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,MAAM;QAC3D,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,MAAM;QAC/D,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,MAAM,CAAC,CAAC,MAAM;KACzD,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,GAAW;IACnC,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,GAAG,wBAAwB,CAAC,GAAG,CAAC,CAAC;IAC5D,IAAI,WAAW,KAAK,IAAI,EAAE,CAAC;QACzB,OAAO;YACL,IAAI,EAAE,IAAI;YACV,MAAM,EAAE,QAAQ,CAAC;gBACf;oBACE,QAAQ,EAAE,OAAO;oBACjB,IAAI,EAAE,0BAA0B;oBAChC,OAAO,EACL,oEAAoE;iBACvE;aACF,CAAC;SACH,CAAC;IACJ,CAAC;IAED,yEAAyE;IACzE,0EAA0E;IAC1E,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAEpE,MAAM,MAAM,GAAG,0BAA0B,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IACjE,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO;YACL,IAAI,EAAE,IAAI;YACV,MAAM,EAAE,QAAQ,CACd,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBAClC,QAAQ,EAAE,OAAgB;gBAC1B,IAAI,EAAE,UAAU,KAAK,CAAC,IAAI,EAAE;gBAC5B,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS;aAC3D,CAAC,CAAC,CACJ;SACF,CAAC;IACJ,CAAC;IAED,OAAO;QACL,IAAI,EAAE,EAAE,WAAW,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,cAAc,EAAE;QACxD,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC;KACrB,CAAC;AACJ,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,aAAa,CAAC,GAAW;IACvC,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC;AAC/B,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { z } from "zod";
2
+ declare const NodeIdSchema: z.ZodString;
3
+ declare const NodeRefSchema: z.ZodString;
4
+ /**
5
+ * Zod schema for a `ghost.node/v1` frontmatter block.
6
+ *
7
+ * Validates a node in isolation. Identity and containment are not here: they
8
+ * come from the node's file path. Kind is the filename prefix, never a
9
+ * frontmatter field.
10
+ */
11
+ export declare const GhostNodeFrontmatterSchema: z.ZodObject<{
12
+ description: z.ZodOptional<z.ZodString>;
13
+ materials: z.ZodOptional<z.ZodArray<z.ZodString>>;
14
+ relates: z.ZodOptional<z.ZodNever>;
15
+ }, z.core.$loose>;
16
+ export { NodeIdSchema, NodeRefSchema };
17
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/ghost-core/node/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAaxB,QAAA,MAAM,YAAY,aAGhB,CAAC;AAEH,QAAA,MAAM,aAAa,aAEjB,CAAC;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B;;;;iBAuBvB,CAAC;AAEjB,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,CAAC"}
@@ -0,0 +1,49 @@
1
+ import { z } from "zod";
2
+ import { validateMaterialLocator } from "../materials.js";
3
+ /**
4
+ * A node id is its path within the package, `.md` dropped (`marketing/email`).
5
+ * Directory nesting is only file organization; it does not create parents,
6
+ * ancestors, or semantic hierarchy. A segment is a permissive lowercase slug
7
+ * (alphanumeric plus `.` `_` `-`); segments join with `/`. No leading,
8
+ * trailing, or doubled slash. Ids are computed by the loader from the file
9
+ * path, never authored in frontmatter.
10
+ */
11
+ const NODE_ID_PATTERN = /^[a-z0-9][a-z0-9._-]*(?:\/[a-z0-9][a-z0-9._-]*)*$/;
12
+ const NodeIdSchema = z.string().min(1).regex(NODE_ID_PATTERN, {
13
+ message: "node id must be a path of lowercase slug segments joined by '/' (alphanumeric plus . _ -, no leading/trailing/doubled slash)",
14
+ });
15
+ const NodeRefSchema = z.string().min(1).regex(NODE_ID_PATTERN, {
16
+ message: "node ref must be a path id like 'marketing/email'",
17
+ });
18
+ /**
19
+ * Zod schema for a `ghost.node/v1` frontmatter block.
20
+ *
21
+ * Validates a node in isolation. Identity and containment are not here: they
22
+ * come from the node's file path. Kind is the filename prefix, never a
23
+ * frontmatter field.
24
+ */
25
+ export const GhostNodeFrontmatterSchema = z
26
+ .object({
27
+ description: z.string().min(1).optional(),
28
+ materials: z
29
+ .array(z
30
+ .string()
31
+ .min(1)
32
+ .superRefine((locator, ctx) => {
33
+ const message = validateMaterialLocator(locator);
34
+ if (message !== null)
35
+ ctx.addIssue({ code: "custom", message });
36
+ }))
37
+ .optional(),
38
+ // `relates` (and all typed edges) were removed. Reject it with a message
39
+ // that names the key so authors get a clear signal.
40
+ relates: z
41
+ .never({ message: "`relates` is a removed key (edges no longer exist)" })
42
+ .optional(),
43
+ })
44
+ // Passthrough, not strict: authors may add free-form descriptive keys
45
+ // (e.g. `audience`, `stage`) that describe what the node is. Ghost does not
46
+ // gate on them — they ride along as part of the node's descriptive surface.
47
+ .passthrough();
48
+ export { NodeIdSchema, NodeRefSchema };
49
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/ghost-core/node/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAE1D;;;;;;;GAOG;AACH,MAAM,eAAe,GAAG,mDAAmD,CAAC;AAE5E,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,eAAe,EAAE;IAC5D,OAAO,EACL,8HAA8H;CACjI,CAAC,CAAC;AAEH,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,eAAe,EAAE;IAC7D,OAAO,EAAE,mDAAmD;CAC7D,CAAC,CAAC;AAEH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC;KACxC,MAAM,CAAC;IACN,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACzC,SAAS,EAAE,CAAC;SACT,KAAK,CACJ,CAAC;SACE,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,CAAC;SACN,WAAW,CAAC,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE;QAC5B,MAAM,OAAO,GAAG,uBAAuB,CAAC,OAAO,CAAC,CAAC;QACjD,IAAI,OAAO,KAAK,IAAI;YAAE,GAAG,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;IAClE,CAAC,CAAC,CACL;SACA,QAAQ,EAAE;IACb,yEAAyE;IACzE,oDAAoD;IACpD,OAAO,EAAE,CAAC;SACP,KAAK,CAAC,EAAE,OAAO,EAAE,oDAAoD,EAAE,CAAC;SACxE,QAAQ,EAAE;CACd,CAAC;IACF,sEAAsE;IACtE,4EAA4E;IAC5E,4EAA4E;KAC3E,WAAW,EAAE,CAAC;AAEjB,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { GhostNodeDocument, GhostNodeFrontmatter } from "./types.js";
2
+ /**
3
+ * Serialize a node back to its `---\n<yaml>\n---\n<body>` markdown form. Keys
4
+ * are emitted in a stable order (description) so round-trips and diffs are
5
+ * deterministic. Identity and kind are not serialized — they come from the
6
+ * node's file path and optional filename prefix. Undefined fields are omitted; a node
7
+ * with no frontmatter fields emits an empty block.
8
+ */
9
+ export declare function serializeNode(node: GhostNodeDocument): string;
10
+ export type { GhostNodeFrontmatter };
11
+ //# sourceMappingURL=serialize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serialize.d.ts","sourceRoot":"","sources":["../../../src/ghost-core/node/serialize.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAE1E;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,CAY7D;AAED,YAAY,EAAE,oBAAoB,EAAE,CAAC"}
@@ -0,0 +1,21 @@
1
+ import { stringify as stringifyYaml } from "yaml";
2
+ /**
3
+ * Serialize a node back to its `---\n<yaml>\n---\n<body>` markdown form. Keys
4
+ * are emitted in a stable order (description) so round-trips and diffs are
5
+ * deterministic. Identity and kind are not serialized — they come from the
6
+ * node's file path and optional filename prefix. Undefined fields are omitted; a node
7
+ * with no frontmatter fields emits an empty block.
8
+ */
9
+ export function serializeNode(node) {
10
+ const fm = node.frontmatter;
11
+ const ordered = {};
12
+ if (fm.description !== undefined)
13
+ ordered.description = fm.description;
14
+ // An empty frontmatter object stringifies to "{}"; emit a bare block instead.
15
+ const yaml = Object.keys(ordered).length === 0
16
+ ? ""
17
+ : `${stringifyYaml(ordered).trimEnd()}\n`;
18
+ const body = node.body.replace(/^\n+/, "");
19
+ return `---\n${yaml}---\n${body.length ? `\n${body}\n` : "\n"}`;
20
+ }
21
+ //# sourceMappingURL=serialize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serialize.js","sourceRoot":"","sources":["../../../src/ghost-core/node/serialize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,IAAI,aAAa,EAAE,MAAM,MAAM,CAAC;AAGlD;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,IAAuB;IACnD,MAAM,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC;IAC5B,MAAM,OAAO,GAA4B,EAAE,CAAC;IAC5C,IAAI,EAAE,CAAC,WAAW,KAAK,SAAS;QAAE,OAAO,CAAC,WAAW,GAAG,EAAE,CAAC,WAAW,CAAC;IAEvE,8EAA8E;IAC9E,MAAM,IAAI,GACR,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,KAAK,CAAC;QAC/B,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,IAAI,CAAC;IAC9C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC3C,OAAO,QAAQ,IAAI,QAAQ,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;AAClE,CAAC"}
@@ -0,0 +1,18 @@
1
+ export interface FencedBlock {
2
+ fence: string;
3
+ info?: string;
4
+ content: string;
5
+ }
6
+ export interface SkeletonSection {
7
+ body: string;
8
+ fences: FencedBlock[];
9
+ }
10
+ export declare function carriesConcreteMaterial(input: {
11
+ materials?: string[];
12
+ body: string;
13
+ }): boolean;
14
+ export declare function hasThreeLineFence(body: string): boolean;
15
+ export declare function extractSkeletonSections(body: string): SkeletonSection[];
16
+ export declare function extractSkeletonFences(body: string): FencedBlock[];
17
+ export declare function stripSkeletonSections(body: string): string;
18
+ //# sourceMappingURL=steering.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"steering.d.ts","sourceRoot":"","sources":["../../../src/ghost-core/node/steering.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,WAAW,EAAE,CAAC;CACvB;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE;IAC7C,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;CACd,GAAG,OAAO,CAMV;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAKvD;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,EAAE,CASvE;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,EAAE,CAEjE;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAc1D"}
@@ -0,0 +1,65 @@
1
+ const FENCED_BLOCK_PATTERN = /(^|\n)(`{3,}|~{3,})[^\n]*\n([\s\S]*?)\n\2[ \t]*(?=\n|$)/g;
2
+ const SKELETON_HEADING_PATTERN = /^##[ \t]+Skeleton[ \t]*$/gim;
3
+ export function carriesConcreteMaterial(input) {
4
+ return ((input.materials?.length ?? 0) > 0 ||
5
+ hasThreeLineFence(input.body) ||
6
+ extractSkeletonSections(input.body).length > 0);
7
+ }
8
+ export function hasThreeLineFence(body) {
9
+ for (const block of extractFencedBlocks(body)) {
10
+ if (block.content.split(/\r?\n/).length >= 3)
11
+ return true;
12
+ }
13
+ return false;
14
+ }
15
+ export function extractSkeletonSections(body) {
16
+ const headings = [...body.matchAll(SKELETON_HEADING_PATTERN)];
17
+ return headings.map((heading, index) => {
18
+ const start = (heading.index ?? 0) + heading[0].length;
19
+ const next = headings[index + 1];
20
+ const end = next?.index ?? findNextHeading(body, start);
21
+ const sectionBody = body.slice(start, end).trim();
22
+ return { body: sectionBody, fences: extractFencedBlocks(sectionBody) };
23
+ });
24
+ }
25
+ export function extractSkeletonFences(body) {
26
+ return extractSkeletonSections(body).flatMap((section) => section.fences);
27
+ }
28
+ export function stripSkeletonSections(body) {
29
+ const headings = [...body.matchAll(SKELETON_HEADING_PATTERN)];
30
+ if (headings.length === 0)
31
+ return body;
32
+ let stripped = "";
33
+ let cursor = 0;
34
+ for (const heading of headings) {
35
+ const start = heading.index ?? 0;
36
+ const end = findNextHeading(body, start + heading[0].length);
37
+ stripped += body.slice(cursor, start);
38
+ cursor = end;
39
+ }
40
+ stripped += body.slice(cursor);
41
+ return stripped.replace(/\n{3,}/g, "\n\n").trim();
42
+ }
43
+ function extractFencedBlocks(body) {
44
+ const blocks = [];
45
+ for (const match of body.matchAll(FENCED_BLOCK_PATTERN)) {
46
+ const openingLine = body
47
+ .slice((match.index ?? 0) + (match[1]?.length ?? 0))
48
+ .split(/\r?\n/, 1)[0];
49
+ const open = /^(?<fence>`{3,}|~{3,})(?<info>.*)$/.exec(openingLine);
50
+ const fence = open?.groups?.fence ?? match[2] ?? "```";
51
+ const info = open?.groups?.info?.trim();
52
+ blocks.push({
53
+ fence,
54
+ ...(info ? { info } : {}),
55
+ content: match[3] ?? "",
56
+ });
57
+ }
58
+ return blocks;
59
+ }
60
+ function findNextHeading(body, start) {
61
+ const rest = body.slice(start);
62
+ const match = /^#{1,6}[ \t]+.+$/m.exec(rest);
63
+ return match?.index === undefined ? body.length : start + match.index;
64
+ }
65
+ //# sourceMappingURL=steering.js.map