mdkg 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,20 @@ All notable changes to mdkg are documented here.
4
4
 
5
5
  This project follows a pragmatic changelog style inspired by Keep a Changelog. Versions use npm package versions.
6
6
 
7
+ ## 0.1.1 - 2026-05-12
8
+
9
+ ### Added
10
+
11
+ - Added bundled template schema fallback so older workspaces can keep using graph inspection while missing newly introduced built-in templates.
12
+ - Added `safe_to_apply`, `will_write_paths`, `preserved_customizations`, `blocking_conflicts`, and `apply_side_effects` fields to `mdkg upgrade --json`.
13
+
14
+ ### Changed
15
+
16
+ - `mdkg new <built-in-type>` can use the installed package template when the workspace has not yet vendored that local template.
17
+ - `mdkg doctor` and `mdkg validate` warn, rather than fail, when packaged fallback schemas cover missing local built-in templates.
18
+ - `mdkg upgrade` human output now states whether the receipt is safe to apply and what paths would be written.
19
+ - `mdkg upgrade` skips ignored event logs and points users to `mdkg event enable` instead of creating ignored `.mdkg/work/events/events.jsonl` files.
20
+
7
21
  ## 0.1.0 - 2026-05-12
8
22
 
9
23
  ### Added
package/README.md CHANGED
@@ -13,7 +13,7 @@ mdkg stays deliberately boring:
13
13
  - zero runtime dependencies
14
14
  - no sqlite, daemon, hosted index, or vector DB
15
15
 
16
- Current package version in source: `0.1.0`
16
+ Current package version in source: `0.1.1`
17
17
 
18
18
  ## The product shape
19
19
 
@@ -70,7 +70,9 @@ Apply only after reviewing the receipt:
70
70
  mdkg upgrade --apply
71
71
  ```
72
72
 
73
- Upgrade is intentionally conservative. It creates missing managed startup docs and updates unchanged mdkg seed assets, but preserves customized docs, templates, skills, and core files as reported conflicts. Agent-enabled workspaces also get safe default skill upgrades and skill mirror refreshes; non-agent workspaces do not gain skills, events, or mirrors implicitly.
73
+ Upgrade is intentionally conservative. It creates missing managed startup docs and templates, updates unchanged mdkg seed assets, and preserves customized docs, templates, skills, and core files as reported preserved customizations. Review `safe_to_apply`, `will_write_paths`, and `apply_side_effects` in the JSON receipt before applying. Agent-enabled workspaces can receive safe default skill upgrades and skill mirror refreshes; ignored event logs are skipped with guidance to run `mdkg event enable` if provenance should be restored.
74
+
75
+ Older workspaces can continue to inspect and validate current graph nodes before applying an upgrade. When local templates are missing for newly introduced built-in mdkg types, mdkg uses the installed package's bundled templates as a read-only schema fallback and warns that `mdkg upgrade --apply` can vendor the missing templates.
74
76
 
75
77
  Create a task:
76
78
 
package/dist/cli.js CHANGED
@@ -108,7 +108,9 @@ function printUpgradeHelp(log) {
108
108
  log(" --json Emit machine-readable upgrade receipt");
109
109
  log("\nNotes:");
110
110
  log(" - preserves customized docs, templates, skills, and core files");
111
+ log(" - json receipts include safe_to_apply, will_write_paths, and apply_side_effects");
111
112
  log(" - upgrades default mdkg skills only when they match managed seed fingerprints");
113
+ log(" - skips ignored event logs; run mdkg event enable if provenance should be restored");
112
114
  log(" - run without flags first, then rerun with --apply when the receipt looks right");
113
115
  printGlobalOptions(log);
114
116
  }
@@ -79,12 +79,20 @@ function runDoctorCommand(options) {
79
79
  }
80
80
  if (config) {
81
81
  try {
82
- (0, template_schema_1.loadTemplateSchemas)(options.root, config, node_1.ALLOWED_TYPES);
82
+ const templateSchemaInfo = (0, template_schema_1.loadTemplateSchemasWithInfo)(options.root, config, node_1.ALLOWED_TYPES);
83
83
  results.push({
84
84
  name: "templates",
85
85
  ok: true,
86
86
  detail: "template schema set loaded",
87
87
  });
88
+ if (templateSchemaInfo.fallbackTypes.length > 0) {
89
+ results.push({
90
+ name: "local-templates",
91
+ ok: true,
92
+ level: "warn",
93
+ detail: `missing local template schema(s) covered by bundled fallback: ${templateSchemaInfo.fallbackTypes.join(", ")}; run \`mdkg upgrade --apply\` to vendor them`,
94
+ });
95
+ }
88
96
  }
89
97
  catch (err) {
90
98
  const message = err instanceof Error ? err.message : String(err);
@@ -143,7 +151,7 @@ function runDoctorCommand(options) {
143
151
  }
144
152
  else {
145
153
  for (const result of results) {
146
- const prefix = result.ok ? "ok" : "fail";
154
+ const prefix = result.ok ? result.level ?? "ok" : "fail";
147
155
  console.log(`${prefix}: ${result.name} - ${result.detail}`);
148
156
  }
149
157
  }
@@ -286,6 +286,9 @@ function runNewCommand(options) {
286
286
  }
287
287
  const today = (0, date_1.formatDate)(options.now ?? new Date());
288
288
  const template = (0, loader_1.loadTemplate)(options.root, config, type, options.template);
289
+ if (template.source === "bundled") {
290
+ console.error(`warning: using bundled template fallback for ${type}; run \`mdkg upgrade --apply\` to vendor missing local templates`);
291
+ }
289
292
  const content = (0, loader_1.renderTemplate)(template, {
290
293
  id,
291
294
  type,
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.runUpgradeCommand = runUpgradeCommand;
7
7
  const fs_1 = __importDefault(require("fs"));
8
8
  const path_1 = __importDefault(require("path"));
9
+ const child_process_1 = require("child_process");
9
10
  const migrate_1 = require("../core/migrate");
10
11
  const config_1 = require("../core/config");
11
12
  const paths_1 = require("../core/paths");
@@ -85,6 +86,9 @@ function record(summary, changes, change) {
85
86
  summary.skipped += 1;
86
87
  summary.conflicted += 1;
87
88
  break;
89
+ case "skip":
90
+ summary.skipped += 1;
91
+ break;
88
92
  }
89
93
  }
90
94
  function buildKnownHashes(manifests) {
@@ -185,11 +189,59 @@ function migrateConfigIfNeeded(root, dryRun, summary, changes) {
185
189
  writeFile(cfgPath, `${JSON.stringify(migrated.config, null, 2)}\n`);
186
190
  }
187
191
  }
192
+ function isIgnoredBySimpleGitignore(root, relativePath) {
193
+ const ignorePath = path_1.default.join(root, ".gitignore");
194
+ if (!fs_1.default.existsSync(ignorePath)) {
195
+ return false;
196
+ }
197
+ const normalized = relativePath.replace(/\\/g, "/");
198
+ const lines = fs_1.default.readFileSync(ignorePath, "utf8").split(/\r?\n/);
199
+ let ignored = false;
200
+ for (const rawLine of lines) {
201
+ const line = rawLine.trim();
202
+ if (!line || line.startsWith("#")) {
203
+ continue;
204
+ }
205
+ const negated = line.startsWith("!");
206
+ const pattern = negated ? line.slice(1) : line;
207
+ const normalizedPattern = pattern.replace(/\\/g, "/").replace(/^\/+/, "");
208
+ const matches = normalizedPattern === normalized ||
209
+ (normalizedPattern.endsWith("/") && normalized.startsWith(normalizedPattern)) ||
210
+ (normalizedPattern.endsWith("/*") && normalized.startsWith(normalizedPattern.slice(0, -1)));
211
+ if (matches) {
212
+ ignored = !negated;
213
+ }
214
+ }
215
+ return ignored;
216
+ }
217
+ function isGitIgnored(root, relativePath) {
218
+ const result = (0, child_process_1.spawnSync)("git", ["check-ignore", "--quiet", "--", relativePath], {
219
+ cwd: root,
220
+ stdio: "ignore",
221
+ });
222
+ if (result.status === 0) {
223
+ return true;
224
+ }
225
+ if (result.status === 1) {
226
+ return false;
227
+ }
228
+ return isIgnoredBySimpleGitignore(root, relativePath);
229
+ }
188
230
  function ensureAgentRuntimeFiles(root, dryRun, summary, changes) {
189
231
  const eventsPath = path_1.default.join(root, ".mdkg", "work", "events", "events.jsonl");
232
+ const relEventsPath = ".mdkg/work/events/events.jsonl";
190
233
  if (!fs_1.default.existsSync(eventsPath)) {
234
+ if (isGitIgnored(root, relEventsPath)) {
235
+ record(summary, changes, {
236
+ path: relEventsPath,
237
+ category: "event_log",
238
+ action: "skip",
239
+ reason: "event log path is ignored; run `mdkg event enable` if local event provenance should be restored",
240
+ });
241
+ return;
242
+ }
191
243
  record(summary, changes, {
192
- path: ".mdkg/work/events/events.jsonl",
244
+ path: relEventsPath,
193
245
  category: "event_log",
194
246
  action: "create",
195
247
  reason: "agent workspace is missing event log",
@@ -202,9 +254,50 @@ function ensureAgentRuntimeFiles(root, dryRun, summary, changes) {
202
254
  summary.unchanged += 1;
203
255
  }
204
256
  }
257
+ function isWritableChange(change) {
258
+ return change.action === "create" || change.action === "update" || change.action === "migrate" || change.action === "sync";
259
+ }
260
+ function buildApplySideEffects(options) {
261
+ const hasDirectWrites = options.changes.some(isWritableChange);
262
+ if (!hasDirectWrites && options.existingManifest) {
263
+ return [];
264
+ }
265
+ const effects = [
266
+ {
267
+ path: ".mdkg/init-manifest.json",
268
+ category: "init_manifest",
269
+ action: options.existingManifest ? "update" : "create",
270
+ reason: "records managed init asset fingerprints after apply",
271
+ },
272
+ ];
273
+ if (options.agentWorkspace) {
274
+ effects.push({
275
+ path: ".mdkg/skills/registry.md",
276
+ category: "skill_registry",
277
+ action: "update",
278
+ reason: "refreshes canonical skill registry after apply",
279
+ }, {
280
+ path: ".agents/skills,.claude/skills",
281
+ category: "skill_mirror",
282
+ action: "sync",
283
+ reason: "syncs managed skill mirrors after apply",
284
+ });
285
+ }
286
+ return effects;
287
+ }
205
288
  function emitHumanReceipt(receipt) {
206
289
  const mode = receipt.dry_run ? "dry-run" : "apply";
207
290
  console.log(`mdkg upgrade ${mode}: ${receipt.summary.created} create, ${receipt.summary.updated} update, ${receipt.summary.migrated} migrate, ${receipt.summary.synced} sync, ${receipt.summary.conflicted} conflict`);
291
+ console.log(`safe to apply: ${receipt.safe_to_apply ? "yes" : "no"}`);
292
+ if (receipt.will_write_paths.length > 0) {
293
+ console.log(`will write: ${receipt.will_write_paths.join(", ")}`);
294
+ }
295
+ if (receipt.preserved_customizations.length > 0) {
296
+ console.log(`preserved customizations: ${receipt.preserved_customizations.length}`);
297
+ }
298
+ if (receipt.blocking_conflicts.length > 0) {
299
+ console.log(`blocking conflicts: ${receipt.blocking_conflicts.length}`);
300
+ }
208
301
  if (receipt.changes.length === 0) {
209
302
  console.log("no upgrade changes pending");
210
303
  }
@@ -213,8 +306,18 @@ function emitHumanReceipt(receipt) {
213
306
  console.log(` ${change.action}: ${change.path} (${change.reason})`);
214
307
  }
215
308
  }
216
- if (receipt.dry_run && receipt.changes.some((change) => change.action !== "conflict")) {
217
- console.log("next: mdkg upgrade --apply");
309
+ if (receipt.apply_side_effects.length > 0) {
310
+ for (const effect of receipt.apply_side_effects) {
311
+ console.log(` apply-side-effect: ${effect.path} (${effect.reason})`);
312
+ }
313
+ }
314
+ if (receipt.dry_run && receipt.will_write_paths.length > 0) {
315
+ if (receipt.safe_to_apply) {
316
+ console.log("next: mdkg upgrade --apply (writes only safe managed paths; preserves customized files)");
317
+ }
318
+ else {
319
+ console.log("next: resolve blocking conflicts before running mdkg upgrade --apply");
320
+ }
218
321
  }
219
322
  }
220
323
  function runUpgradeCommand(options) {
@@ -250,30 +353,42 @@ function runUpgradeCommand(options) {
250
353
  if (agentWorkspace) {
251
354
  ensureAgentRuntimeFiles(root, dryRun, summary, changes);
252
355
  }
356
+ const applySideEffects = buildApplySideEffects({
357
+ existingManifest,
358
+ agentWorkspace,
359
+ changes,
360
+ });
361
+ for (const effect of applySideEffects) {
362
+ record(summary, changes, effect);
363
+ }
253
364
  if (!dryRun) {
254
365
  const appliedManifest = {
255
366
  ...currentManifest,
256
367
  files: managedCurrentFiles.sort((a, b) => a.path.localeCompare(b.path)),
257
368
  };
258
- (0, init_manifest_1.writeInitManifest)(path_1.default.join(root, ".mdkg", init_manifest_1.INIT_MANIFEST_FILE), appliedManifest);
259
- if (agentWorkspace) {
369
+ if (applySideEffects.length > 0) {
370
+ (0, init_manifest_1.writeInitManifest)(path_1.default.join(root, ".mdkg", init_manifest_1.INIT_MANIFEST_FILE), appliedManifest);
371
+ }
372
+ if (agentWorkspace && applySideEffects.length > 0) {
260
373
  const config = (0, config_1.validateConfigSchema)((0, migrate_1.migrateConfig)(JSON.parse(fs_1.default.readFileSync((0, paths_1.configPath)(root), "utf8"))).config);
261
374
  (0, skill_support_1.refreshSkillsRegistry)(root, config);
262
375
  (0, skill_mirror_1.scaffoldMirrorRoots)(root);
263
- const result = (0, skill_mirror_1.syncSkillMirrors)({ root, config, createRoots: true });
264
- record(summary, changes, {
265
- path: ".agents/skills,.claude/skills",
266
- category: "skill_mirror",
267
- action: "sync",
268
- reason: `${result.synced} mirrored skill(s), ${result.pruned} stale mirror(s) pruned`,
269
- });
376
+ (0, skill_mirror_1.syncSkillMirrors)({ root, config, createRoots: true });
270
377
  }
271
378
  }
379
+ const preservedCustomizations = changes.filter((change) => change.action === "conflict");
380
+ const blockingConflicts = [];
381
+ const willWritePaths = changes.filter(isWritableChange).map((change) => change.path);
272
382
  const receipt = {
273
383
  action: "upgrade",
274
384
  dry_run: dryRun,
275
385
  version,
386
+ safe_to_apply: blockingConflicts.length === 0,
276
387
  summary,
388
+ will_write_paths: Array.from(new Set(willWritePaths)),
389
+ preserved_customizations: preservedCustomizations,
390
+ blocking_conflicts: blockingConflicts,
391
+ apply_side_effects: applySideEffects,
277
392
  changes,
278
393
  };
279
394
  if (options.json) {
@@ -200,10 +200,14 @@ function validateEventsJsonl(root, config, errors) {
200
200
  }
201
201
  function runValidateCommand(options) {
202
202
  const config = (0, config_1.loadConfig)(options.root);
203
- const templateSchemas = (0, template_schema_1.loadTemplateSchemas)(options.root, config, node_1.ALLOWED_TYPES);
203
+ const templateSchemaInfo = (0, template_schema_1.loadTemplateSchemasWithInfo)(options.root, config, node_1.ALLOWED_TYPES);
204
+ const templateSchemas = templateSchemaInfo.schemas;
204
205
  const filesByAlias = (0, workspace_files_1.listWorkspaceDocFilesByAlias)(options.root, config);
205
206
  const errors = [];
206
207
  const warnings = [];
208
+ if (templateSchemaInfo.fallbackTypes.length > 0) {
209
+ warnings.push(`using bundled template schema fallback for missing local type(s): ${templateSchemaInfo.fallbackTypes.join(", ")}; run \`mdkg upgrade --apply\` to vendor built-in templates`);
210
+ }
207
211
  const nodes = {};
208
212
  const idsByWorkspace = {};
209
213
  for (const [alias, files] of Object.entries(filesByAlias)) {
@@ -4,9 +4,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.loadTemplateSchemas = loadTemplateSchemas;
7
+ exports.loadTemplateSchemasWithInfo = loadTemplateSchemasWithInfo;
7
8
  const fs_1 = __importDefault(require("fs"));
8
9
  const path_1 = __importDefault(require("path"));
9
10
  const frontmatter_1 = require("./frontmatter");
11
+ const builtin_1 = require("../templates/builtin");
10
12
  function listMarkdownFiles(dir) {
11
13
  if (!fs_1.default.existsSync(dir)) {
12
14
  return [];
@@ -45,9 +47,12 @@ function addKeyToSchema(schema, key, kind, filePath) {
45
47
  }
46
48
  }
47
49
  function loadTemplateSchemas(root, config, requiredTypes) {
50
+ return loadTemplateSchemasWithInfo(root, config, requiredTypes).schemas;
51
+ }
52
+ function loadTemplateSchemasWithInfo(root, config, requiredTypes) {
48
53
  const templateRoot = path_1.default.resolve(root, config.templates.root_path, config.templates.default_set);
49
54
  const files = listMarkdownFiles(templateRoot);
50
- if (files.length === 0) {
55
+ if (files.length === 0 && !requiredTypes) {
51
56
  throw new Error(`no templates found at ${templateRoot}`);
52
57
  }
53
58
  const schemas = {};
@@ -75,12 +80,35 @@ function loadTemplateSchemas(root, config, requiredTypes) {
75
80
  addKeyToSchema(schema, key, kind, filePath);
76
81
  }
77
82
  }
83
+ const fallbackTypes = [];
78
84
  if (requiredTypes) {
79
85
  const required = Array.from(requiredTypes, (value) => value.toLowerCase());
80
- const missing = required.filter((value) => !schemas[value]);
81
- if (missing.length > 0) {
82
- throw new Error(`template schema missing for type(s): ${missing.join(", ")}`);
86
+ for (const missingType of required.filter((value) => !schemas[value])) {
87
+ const bundledPath = (0, builtin_1.requireBundledTemplatePath)(missingType);
88
+ const content = fs_1.default.readFileSync(bundledPath, "utf8");
89
+ const { frontmatter } = (0, frontmatter_1.parseFrontmatter)(content, bundledPath);
90
+ const typeValue = frontmatter.type;
91
+ if (typeValue !== missingType) {
92
+ throw new Error(`bundled template fallback type mismatch for ${missingType}: ${bundledPath}`);
93
+ }
94
+ const schema = {
95
+ type: missingType,
96
+ allowedKeys: new Set(),
97
+ keyKinds: {},
98
+ listKeys: new Set(),
99
+ };
100
+ schemas[missingType] = schema;
101
+ for (const [key, value] of Object.entries(frontmatter)) {
102
+ const kind = getValueKind(value);
103
+ addKeyToSchema(schema, key, kind, bundledPath);
104
+ }
105
+ fallbackTypes.push(missingType);
83
106
  }
84
107
  }
85
- return schemas;
108
+ return {
109
+ schemas,
110
+ templateRoot,
111
+ bundledTemplateRoot: (0, builtin_1.resolveBundledTemplateRoot)(),
112
+ fallbackTypes,
113
+ };
86
114
  }
@@ -68,7 +68,9 @@ Agent bootstrap:
68
68
  Upgrade:
69
69
  - `mdkg upgrade` previews safe scaffold updates and writes nothing by default
70
70
  - `mdkg upgrade --apply` updates only managed or unchanged init assets
71
+ - JSON receipts include `safe_to_apply`, `will_write_paths`, `preserved_customizations`, `blocking_conflicts`, and `apply_side_effects`
71
72
  - customized docs, templates, skills, and core files are preserved and reported
73
+ - ignored event logs are skipped with guidance to run `mdkg event enable`
72
74
 
73
75
  Skill discovery:
74
76
  - `mdkg skill list --tags stage:plan --json`
@@ -56,4 +56,4 @@ mdkg init --update-gitignore --update-npmignore
56
56
 
57
57
  `mdkg upgrade` previews safe scaffold updates for existing workspaces and writes nothing by default.
58
58
 
59
- Use `mdkg upgrade --apply` only after reviewing the receipt. Local customizations are preserved and reported instead of overwritten.
59
+ Use `mdkg upgrade --apply` only after reviewing `safe_to_apply`, `will_write_paths`, and `apply_side_effects` in the receipt. Local customizations are preserved and reported instead of overwritten. Missing built-in templates can be loaded from the installed package as a read-only fallback until you vendor them with upgrade.
@@ -187,4 +187,6 @@ Body headings are strongly recommended for agent usability but should not be har
187
187
  - Node -> skill references in `skills: [...]` are validated against `.mdkg/skills/<slug>/SKILL.md`.
188
188
  - `.mdkg/work/events/events.jsonl` is optional; when present, records are schema-validated by `mdkg validate`.
189
189
  - If a template is missing:
190
- - `mdkg new` must fail with a helpful error (exit code 3).
190
+ - built-in mdkg node types may use the installed package's bundled default template as a read-only schema fallback.
191
+ - commands should warn when bundled fallback is used and recommend `mdkg upgrade --apply` to vendor missing templates.
192
+ - missing non-built-in templates or missing packaged fallback assets must fail with a helpful error.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schema_version": 1,
3
3
  "tool": "mdkg",
4
- "mdkg_version": "0.1.0",
4
+ "mdkg_version": "0.1.1",
5
5
  "files": [
6
6
  {
7
7
  "path": ".mdkg/config.json",
@@ -51,7 +51,7 @@
51
51
  {
52
52
  "path": ".mdkg/core/rule-6-templates-and-schemas.md",
53
53
  "category": "core",
54
- "sha256": "0d6da477c12e3492f43c571a6e4daa373bf05005ef703ad5166b7c8786e553b0"
54
+ "sha256": "7f0a92ccd35f378b487969f06820a61790b02a59aeb14755fe506278f056fd59"
55
55
  },
56
56
  {
57
57
  "path": ".mdkg/core/SOUL.md",
@@ -61,7 +61,7 @@
61
61
  {
62
62
  "path": ".mdkg/README.md",
63
63
  "category": "mdkg_doc",
64
- "sha256": "26e99be382b48682b7841f14404576f79bf6876b64a90aefa6c99c2440701d2a"
64
+ "sha256": "f4078fef50e6866d6f7e3a40351e72fc15d3e1abd334e7119d89c696bc4a9100"
65
65
  },
66
66
  {
67
67
  "path": ".mdkg/skills/build-pack-and-execute-task/SKILL.md",
@@ -186,7 +186,7 @@
186
186
  {
187
187
  "path": "CLI_COMMAND_MATRIX.md",
188
188
  "category": "startup_doc",
189
- "sha256": "eb441dd11b31270ddb31f0a77c75fc744671754cffac3aa8ac6f60e30a1f324f"
189
+ "sha256": "5ac721d2569c4da2a3b7f18e62c816eb3898e8deb06429f17f0615f4a8da2183"
190
190
  },
191
191
  {
192
192
  "path": "llms.txt",
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.BUILTIN_TEMPLATE_SET = void 0;
7
+ exports.templateNameForType = templateNameForType;
8
+ exports.resolveLocalTemplatePath = resolveLocalTemplatePath;
9
+ exports.resolveBundledTemplateRoot = resolveBundledTemplateRoot;
10
+ exports.resolveBundledTemplatePath = resolveBundledTemplatePath;
11
+ exports.requireBundledTemplatePath = requireBundledTemplatePath;
12
+ const fs_1 = __importDefault(require("fs"));
13
+ const path_1 = __importDefault(require("path"));
14
+ exports.BUILTIN_TEMPLATE_SET = "default";
15
+ function templateNameForType(type) {
16
+ const normalized = type.toLowerCase();
17
+ if (normalized === "checkpoint") {
18
+ return "chk";
19
+ }
20
+ return normalized;
21
+ }
22
+ function resolveLocalTemplatePath(root, config, type, templateSet) {
23
+ const setName = (templateSet ?? config.templates.default_set).toLowerCase();
24
+ return path_1.default.resolve(root, config.templates.root_path, setName, `${templateNameForType(type)}.md`);
25
+ }
26
+ function resolveBundledTemplateRoot() {
27
+ return path_1.default.resolve(__dirname, "..", "init", "templates", exports.BUILTIN_TEMPLATE_SET);
28
+ }
29
+ function resolveBundledTemplatePath(type) {
30
+ return path_1.default.join(resolveBundledTemplateRoot(), `${templateNameForType(type)}.md`);
31
+ }
32
+ function requireBundledTemplatePath(type) {
33
+ const templatePath = resolveBundledTemplatePath(type);
34
+ if (!fs_1.default.existsSync(templatePath)) {
35
+ throw new Error(`bundled template fallback missing for type ${type}: ${templatePath} (try reinstalling mdkg)`);
36
+ }
37
+ return templatePath;
38
+ }
@@ -6,26 +6,19 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.loadTemplate = loadTemplate;
7
7
  exports.renderTemplate = renderTemplate;
8
8
  const fs_1 = __importDefault(require("fs"));
9
- const path_1 = __importDefault(require("path"));
10
9
  const frontmatter_1 = require("../graph/frontmatter");
11
10
  const errors_1 = require("../util/errors");
12
- function templateNameForType(type) {
13
- const normalized = type.toLowerCase();
14
- if (normalized === "checkpoint") {
15
- return "chk";
16
- }
17
- return normalized;
18
- }
11
+ const builtin_1 = require("./builtin");
19
12
  function loadTemplate(root, config, type, templateSet) {
20
- const setName = (templateSet ?? config.templates.default_set).toLowerCase();
21
- const templateName = templateNameForType(type);
22
- const templatePath = path_1.default.resolve(root, config.templates.root_path, setName, `${templateName}.md`);
23
- if (!fs_1.default.existsSync(templatePath)) {
24
- throw new errors_1.NotFoundError(`template not found: ${setName}/${templateName}.md`);
13
+ const templatePath = (0, builtin_1.resolveLocalTemplatePath)(root, config, type, templateSet);
14
+ if (!fs_1.default.existsSync(templatePath) && templateSet !== undefined) {
15
+ throw new errors_1.NotFoundError(`template not found: ${templateSet.toLowerCase()}/${(0, builtin_1.templateNameForType)(type)}.md`);
25
16
  }
26
- const content = fs_1.default.readFileSync(templatePath, "utf8");
27
- const { frontmatter, body } = (0, frontmatter_1.parseFrontmatter)(content, templatePath);
28
- return { templatePath, frontmatter, body };
17
+ const source = fs_1.default.existsSync(templatePath) ? "local" : "bundled";
18
+ const resolvedPath = source === "local" ? templatePath : (0, builtin_1.requireBundledTemplatePath)(type);
19
+ const content = fs_1.default.readFileSync(resolvedPath, "utf8");
20
+ const { frontmatter, body } = (0, frontmatter_1.parseFrontmatter)(content, resolvedPath);
21
+ return { templatePath: resolvedPath, source, frontmatter, body };
29
22
  }
30
23
  function isTokenPlaceholder(value) {
31
24
  return typeof value === "string" && /^\{\{[a-z0-9_]+\}\}$/.test(value);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mdkg",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Markdown Knowledge Graph",
5
5
  "license": "MIT",
6
6
  "bin": {