mdkg 0.1.0 → 0.1.2

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 (68) hide show
  1. package/CHANGELOG.md +93 -0
  2. package/README.md +108 -15
  3. package/dist/cli.js +566 -15
  4. package/dist/commands/archive.js +474 -0
  5. package/dist/commands/bundle.js +743 -0
  6. package/dist/commands/bundle_import.js +243 -0
  7. package/dist/commands/capability.js +162 -0
  8. package/dist/commands/doctor.js +233 -2
  9. package/dist/commands/format.js +38 -9
  10. package/dist/commands/index.js +11 -0
  11. package/dist/commands/init.js +188 -63
  12. package/dist/commands/init_manifest.js +19 -6
  13. package/dist/commands/list.js +5 -2
  14. package/dist/commands/new.js +6 -0
  15. package/dist/commands/next.js +7 -0
  16. package/dist/commands/node_card.js +4 -1
  17. package/dist/commands/pack.js +62 -2
  18. package/dist/commands/query_output.js +1 -0
  19. package/dist/commands/search.js +5 -2
  20. package/dist/commands/show.js +7 -14
  21. package/dist/commands/skill_mirror.js +22 -0
  22. package/dist/commands/task.js +3 -0
  23. package/dist/commands/upgrade.js +151 -13
  24. package/dist/commands/validate.js +19 -2
  25. package/dist/commands/work.js +365 -0
  26. package/dist/commands/workspace.js +12 -2
  27. package/dist/core/config.js +100 -1
  28. package/dist/graph/agent_file_types.js +78 -5
  29. package/dist/graph/archive_file.js +125 -0
  30. package/dist/graph/archive_integrity.js +66 -0
  31. package/dist/graph/bundle_imports.js +418 -0
  32. package/dist/graph/capabilities_index_cache.js +103 -0
  33. package/dist/graph/capabilities_indexer.js +231 -0
  34. package/dist/graph/frontmatter.js +19 -0
  35. package/dist/graph/index_cache.js +21 -4
  36. package/dist/graph/indexer.js +4 -1
  37. package/dist/graph/node.js +23 -4
  38. package/dist/graph/node_body.js +37 -0
  39. package/dist/graph/skills_indexer.js +8 -3
  40. package/dist/graph/template_schema.js +33 -5
  41. package/dist/graph/validate_graph.js +83 -7
  42. package/dist/graph/visibility.js +214 -0
  43. package/dist/graph/workspace_files.js +22 -0
  44. package/dist/init/AGENT_START.md +21 -0
  45. package/dist/init/CLI_COMMAND_MATRIX.md +58 -3
  46. package/dist/init/README.md +60 -3
  47. package/dist/init/config.json +13 -1
  48. package/dist/init/core/guide.md +6 -2
  49. package/dist/init/core/rule-3-cli-contract.md +71 -4
  50. package/dist/init/core/rule-4-repo-safety-and-ignores.md +20 -0
  51. package/dist/init/core/rule-6-templates-and-schemas.md +10 -1
  52. package/dist/init/init-manifest.json +19 -14
  53. package/dist/init/skills/default/build-pack-and-execute-task/SKILL.md +2 -1
  54. package/dist/init/skills/default/verify-close-and-checkpoint/SKILL.md +26 -0
  55. package/dist/init/templates/default/archive.md +33 -0
  56. package/dist/init/templates/default/receipt.md +15 -1
  57. package/dist/init/templates/default/work.md +6 -1
  58. package/dist/init/templates/default/work_order.md +15 -1
  59. package/dist/pack/export_md.js +3 -0
  60. package/dist/pack/export_xml.js +3 -0
  61. package/dist/pack/order.js +1 -0
  62. package/dist/pack/pack.js +3 -13
  63. package/dist/templates/builtin.js +38 -0
  64. package/dist/templates/loader.js +9 -16
  65. package/dist/util/argparse.js +30 -0
  66. package/dist/util/refs.js +40 -0
  67. package/dist/util/zip.js +153 -0
  68. package/package.json +8 -2
@@ -10,16 +10,34 @@ const config_1 = require("../core/config");
10
10
  const frontmatter_1 = require("../graph/frontmatter");
11
11
  const template_schema_1 = require("../graph/template_schema");
12
12
  const node_1 = require("../graph/node");
13
+ const agent_file_types_1 = require("../graph/agent_file_types");
14
+ const archive_file_1 = require("../graph/archive_file");
13
15
  const workspace_files_1 = require("../graph/workspace_files");
14
16
  const errors_1 = require("../util/errors");
15
17
  const date_1 = require("../util/date");
16
18
  const id_1 = require("../util/id");
19
+ const refs_1 = require("../util/refs");
17
20
  const DEC_ID_RE = /^dec-[0-9]+$/;
18
21
  const DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
19
22
  const ID_LIST_KEYS = new Set(["refs", "scope"]);
20
23
  const ID_REF_LIST_KEYS = new Set(["relates", "blocked_by", "blocks"]);
21
24
  const ID_REF_SCALAR_KEYS = new Set(["epic", "parent", "prev", "next"]);
22
- const PRESERVE_CASE_LIST_KEYS = new Set(["links", "artifacts"]);
25
+ const PRESERVE_CASE_LIST_KEYS = new Set([
26
+ "links",
27
+ "artifacts",
28
+ "work_contracts",
29
+ "input_refs",
30
+ "constraint_refs",
31
+ "proof_refs",
32
+ "attestation_refs",
33
+ ]);
34
+ const EXTERNAL_REF_LIST_KEYS = new Set([
35
+ "input_refs",
36
+ "constraint_refs",
37
+ "proof_refs",
38
+ "attestation_refs",
39
+ ]);
40
+ const HASH_REF_LIST_KEYS = new Set(["input_hashes", "output_hashes"]);
23
41
  function isValidId(value) {
24
42
  return (0, id_1.isCanonicalId)(value);
25
43
  }
@@ -48,7 +66,7 @@ function sortList(values) {
48
66
  return 0;
49
67
  });
50
68
  }
51
- function normalizeList(values, key, errors, filePath) {
69
+ function normalizeList(values, key, errors, filePath, allowPortableRefs = false) {
52
70
  const trimmed = values.map((value) => normalizeScalar(value));
53
71
  const shouldLowercase = !PRESERVE_CASE_LIST_KEYS.has(key);
54
72
  const normalized = shouldLowercase ? trimmed.map((value) => value.toLowerCase()) : trimmed;
@@ -57,12 +75,18 @@ function normalizeList(values, key, errors, filePath) {
57
75
  errors.push(`${filePath}: ${key} entries must be non-empty`);
58
76
  continue;
59
77
  }
60
- if (ID_LIST_KEYS.has(key) && !isValidId(entry)) {
78
+ if (ID_LIST_KEYS.has(key) && !(allowPortableRefs ? (0, id_1.isPortableId)(entry) : isValidId(entry))) {
61
79
  errors.push(`${filePath}: ${key} entries must match <prefix>-<number> or reserved id`);
62
80
  }
63
- if (ID_REF_LIST_KEYS.has(key) && !(0, id_1.isCanonicalIdRef)(entry)) {
81
+ if (ID_REF_LIST_KEYS.has(key) && !(allowPortableRefs ? (0, id_1.isPortableIdRef)(entry) : (0, id_1.isCanonicalIdRef)(entry))) {
64
82
  errors.push(`${filePath}: ${key} entries must be valid id references`);
65
83
  }
84
+ if (EXTERNAL_REF_LIST_KEYS.has(key) && !(0, refs_1.validatePortableOrUriRef)(entry)) {
85
+ errors.push(`${filePath}: ${key} entries must be portable ids or URI refs`);
86
+ }
87
+ if (HASH_REF_LIST_KEYS.has(key) && !(0, refs_1.isSha256Ref)(entry)) {
88
+ errors.push(`${filePath}: ${key} entries must be sha256:<64 lowercase hex chars>`);
89
+ }
66
90
  }
67
91
  return sortList(normalized);
68
92
  }
@@ -73,14 +97,15 @@ function normalizeIdRef(value, key, errors, filePath) {
73
97
  }
74
98
  return normalized;
75
99
  }
76
- function normalizeFrontmatterValue(key, value, schema, errors, filePath) {
100
+ function normalizeFrontmatterValue(key, value, schema, errors, filePath, type) {
77
101
  const expected = schema.keyKinds[key];
78
102
  if (expected === "list") {
79
103
  if (!Array.isArray(value)) {
80
104
  errors.push(`${filePath}: ${key} must be a list`);
81
105
  return [];
82
106
  }
83
- return normalizeList(value, key, errors, filePath);
107
+ const allowPortableRefs = (0, agent_file_types_1.isAgentFileType)(type) || (0, archive_file_1.isArchiveType)(type);
108
+ return normalizeList(value, key, errors, filePath, allowPortableRefs);
84
109
  }
85
110
  if (expected === "boolean") {
86
111
  if (typeof value !== "boolean") {
@@ -111,7 +136,7 @@ function normalizeFrontmatter(frontmatter, schema, type, workStatusEnum, priorit
111
136
  }
112
137
  continue;
113
138
  }
114
- const normalizedValue = normalizeFrontmatterValue(key, value, schema, errors, filePath);
139
+ const normalizedValue = normalizeFrontmatterValue(key, value, schema, errors, filePath, type);
115
140
  if (normalizedValue !== undefined) {
116
141
  normalized[key] = normalizedValue;
117
142
  }
@@ -122,8 +147,12 @@ function normalizeFrontmatter(frontmatter, schema, type, workStatusEnum, priorit
122
147
  }
123
148
  else {
124
149
  const normalizedId = idValue.toLowerCase();
125
- if (!isValidId(normalizedId)) {
126
- errors.push(`${filePath}: id must match <prefix>-<number> or reserved id`);
150
+ const allowPortableId = (0, agent_file_types_1.isAgentFileType)(type) || (0, archive_file_1.isArchiveType)(type);
151
+ if (!(allowPortableId ? (0, id_1.isPortableId)(normalizedId) : isValidId(normalizedId))) {
152
+ const requirement = allowPortableId
153
+ ? "<prefix>-<number>, reserved id, or allowed portable id"
154
+ : "<prefix>-<number> or reserved id";
155
+ errors.push(`${filePath}: id must match ${requirement}`);
127
156
  }
128
157
  normalized.id = normalizedId;
129
158
  }
@@ -10,14 +10,25 @@ const indexer_1 = require("../graph/indexer");
10
10
  const index_cache_1 = require("../graph/index_cache");
11
11
  const skills_index_cache_1 = require("../graph/skills_index_cache");
12
12
  const skills_indexer_1 = require("../graph/skills_indexer");
13
+ const capabilities_indexer_1 = require("../graph/capabilities_indexer");
14
+ const capabilities_index_cache_1 = require("../graph/capabilities_index_cache");
15
+ const bundle_imports_1 = require("../graph/bundle_imports");
13
16
  function runIndexCommand(options) {
14
17
  const config = (0, config_1.loadConfig)(options.root);
15
18
  const nodeIndex = (0, indexer_1.buildIndex)(options.root, config, { tolerant: options.tolerant });
16
19
  const skillsIndex = (0, skills_indexer_1.buildSkillsIndex)(options.root, config);
20
+ const capabilitiesIndex = (0, capabilities_indexer_1.buildCapabilitiesIndex)(options.root, config, nodeIndex);
21
+ const importsIndex = (0, bundle_imports_1.buildBundleImportsIndex)(options.root, config);
17
22
  const nodesOutputPath = path_1.default.resolve(options.root, config.index.global_index_path);
18
23
  const skillsOutputPath = (0, skills_indexer_1.resolveSkillsIndexPath)(options.root);
24
+ const capabilitiesOutputPath = (0, capabilities_indexer_1.resolveCapabilitiesIndexPath)(options.root, config);
25
+ const importsOutputPath = (0, bundle_imports_1.resolveBundleImportsIndexPath)(options.root);
19
26
  (0, index_cache_1.writeIndex)(nodesOutputPath, nodeIndex);
20
27
  (0, skills_index_cache_1.writeSkillsIndex)(skillsOutputPath, skillsIndex);
28
+ (0, capabilities_index_cache_1.writeCapabilitiesIndex)(capabilitiesOutputPath, capabilitiesIndex);
29
+ (0, bundle_imports_1.writeBundleImportsIndex)(importsOutputPath, importsIndex.index);
21
30
  console.log(`index written: ${path_1.default.relative(options.root, nodesOutputPath)}`);
22
31
  console.log(`skills index written: ${path_1.default.relative(options.root, skillsOutputPath)}`);
32
+ console.log(`capabilities index written: ${path_1.default.relative(options.root, capabilitiesOutputPath)}`);
33
+ console.log(`bundle imports index written: ${path_1.default.relative(options.root, importsOutputPath)}`);
23
34
  }
@@ -7,6 +7,7 @@ exports.runInitCommand = runInitCommand;
7
7
  const fs_1 = __importDefault(require("fs"));
8
8
  const path_1 = __importDefault(require("path"));
9
9
  const config_1 = require("../core/config");
10
+ const migrate_1 = require("../core/migrate");
10
11
  const errors_1 = require("../util/errors");
11
12
  const date_1 = require("../util/date");
12
13
  const version_1 = require("../core/version");
@@ -39,16 +40,28 @@ function listFiles(dir) {
39
40
  }
40
41
  return files;
41
42
  }
42
- function copySeedFile(src, dest, force, stats) {
43
+ function displayPath(root, filePath) {
44
+ const relPath = path_1.default.relative(root, filePath).split(path_1.default.sep).join("/");
45
+ return relPath.length > 0 ? relPath : ".";
46
+ }
47
+ function recordCreated(root, dest, stats) {
48
+ stats.created += 1;
49
+ stats.createdPaths.push(displayPath(root, dest));
50
+ }
51
+ function recordSkipped(root, dest, stats) {
52
+ stats.skipped += 1;
53
+ stats.skippedPaths.push(displayPath(root, dest));
54
+ }
55
+ function copySeedFile(root, src, dest, force, stats) {
43
56
  if (fs_1.default.existsSync(dest) && !force) {
44
- stats.skipped += 1;
57
+ recordSkipped(root, dest, stats);
45
58
  return;
46
59
  }
47
60
  fs_1.default.mkdirSync(path_1.default.dirname(dest), { recursive: true });
48
61
  fs_1.default.copyFileSync(src, dest);
49
- stats.created += 1;
62
+ recordCreated(root, dest, stats);
50
63
  }
51
- function copySeedDir(srcDir, destDir, force, stats) {
64
+ function copySeedDir(root, srcDir, destDir, force, stats) {
52
65
  if (!fs_1.default.existsSync(srcDir)) {
53
66
  return;
54
67
  }
@@ -56,7 +69,7 @@ function copySeedDir(srcDir, destDir, force, stats) {
56
69
  for (const filePath of files) {
57
70
  const relPath = path_1.default.relative(srcDir, filePath);
58
71
  const destPath = path_1.default.join(destDir, relPath);
59
- copySeedFile(filePath, destPath, force, stats);
72
+ copySeedFile(root, filePath, destPath, force, stats);
60
73
  }
61
74
  }
62
75
  function appendIgnoreEntries(filePath, entries) {
@@ -73,14 +86,14 @@ function appendIgnoreEntries(filePath, entries) {
73
86
  fs_1.default.writeFileSync(filePath, updated, "utf8");
74
87
  return true;
75
88
  }
76
- function writeFileIfMissing(filePath, content, force, stats) {
89
+ function writeFileIfMissing(root, filePath, content, force, stats) {
77
90
  if (fs_1.default.existsSync(filePath) && !force) {
78
- stats.skipped += 1;
91
+ recordSkipped(root, filePath, stats);
79
92
  return;
80
93
  }
81
94
  fs_1.default.mkdirSync(path_1.default.dirname(filePath), { recursive: true });
82
95
  fs_1.default.writeFileSync(filePath, content, "utf8");
83
- stats.created += 1;
96
+ recordCreated(root, filePath, stats);
84
97
  }
85
98
  function soulTemplate(created) {
86
99
  return [
@@ -176,6 +189,48 @@ function seededInitEvent(nowIso) {
176
189
  };
177
190
  return `${JSON.stringify(event)}\n`;
178
191
  }
192
+ function listSeedSkillSlugs(seedDefaultSkills) {
193
+ if (!fs_1.default.existsSync(seedDefaultSkills)) {
194
+ return [];
195
+ }
196
+ return fs_1.default
197
+ .readdirSync(seedDefaultSkills, { withFileTypes: true })
198
+ .filter((entry) => entry.isDirectory() && fs_1.default.existsSync(path_1.default.join(seedDefaultSkills, entry.name, "SKILL.md")))
199
+ .map((entry) => entry.name.toLowerCase())
200
+ .sort();
201
+ }
202
+ function listExistingCanonicalSkillSlugs(root) {
203
+ const skillsDir = path_1.default.join(root, ".mdkg", "skills");
204
+ if (!fs_1.default.existsSync(skillsDir)) {
205
+ return [];
206
+ }
207
+ return fs_1.default
208
+ .readdirSync(skillsDir, { withFileTypes: true })
209
+ .filter((entry) => entry.isDirectory() && fs_1.default.existsSync(path_1.default.join(skillsDir, entry.name, "SKILL.md")))
210
+ .map((entry) => entry.name.toLowerCase())
211
+ .sort();
212
+ }
213
+ function preflightSeedConfig(seedConfig) {
214
+ const raw = JSON.parse(fs_1.default.readFileSync(seedConfig, "utf8"));
215
+ (0, config_1.validateConfigSchema)((0, migrate_1.migrateConfig)(raw).config);
216
+ }
217
+ function emitPartialInitFailure(root, stats, err) {
218
+ const message = err instanceof Error ? err.message : String(err);
219
+ console.error("mdkg init failed after partial writes");
220
+ console.error(`error: ${message}`);
221
+ console.error(`created: ${stats.created}`);
222
+ for (const created of stats.createdPaths) {
223
+ console.error(` created: ${created}`);
224
+ }
225
+ console.error(`skipped: ${stats.skipped}`);
226
+ for (const skipped of stats.skippedPaths) {
227
+ console.error(` skipped: ${skipped}`);
228
+ }
229
+ console.error("recovery:");
230
+ console.error(" inspect the created paths above");
231
+ console.error(" rerun `mdkg init --agent` after resolving the reported error");
232
+ console.error(` root: ${root}`);
233
+ }
179
234
  function parseCoreList(raw) {
180
235
  const lines = raw.split(/\r?\n/);
181
236
  const header = [];
@@ -224,9 +279,9 @@ function ensureCorePins(coreListPath, requiredPins) {
224
279
  function runInitCommand(options) {
225
280
  const root = path_1.default.resolve(options.root);
226
281
  const seedRoot = options.seedRoot ? path_1.default.resolve(options.seedRoot) : DEFAULT_SEED_SUBDIR;
227
- const createAgents = Boolean(options.createAgents || options.createLlm);
228
- const createClaude = Boolean(options.createClaude || options.createLlm);
229
- const createStartupDocs = Boolean(options.createLlm || options.agent);
282
+ const createAgents = Boolean(options.agent);
283
+ const createClaude = Boolean(options.agent);
284
+ const createStartupDocs = Boolean(options.agent);
230
285
  const force = Boolean(options.force);
231
286
  const seedConfig = path_1.default.join(seedRoot, "config.json");
232
287
  const seedCore = path_1.default.join(seedRoot, "core");
@@ -238,7 +293,13 @@ function runInitCommand(options) {
238
293
  const seedCliMatrix = path_1.default.join(seedRoot, "CLI_COMMAND_MATRIX.md");
239
294
  const seedReadme = path_1.default.join(seedRoot, "README.md");
240
295
  const seedDefaultSkills = path_1.default.join(seedRoot, "skills", "default");
241
- const seedManifest = (0, init_manifest_1.createInitManifest)(seedRoot, (0, version_1.readPackageVersion)());
296
+ const seedSoul = path_1.default.join(seedCore, "SOUL.md");
297
+ const seedHuman = path_1.default.join(seedCore, "HUMAN.md");
298
+ const seedManifest = (0, init_manifest_1.createInitManifest)(seedRoot, (0, version_1.readPackageVersion)(), {
299
+ includeAgentDocs: Boolean(options.agent),
300
+ includeStartupDocs: Boolean(options.agent),
301
+ includeDefaultSkills: Boolean(options.agent),
302
+ });
242
303
  if (!fs_1.default.existsSync(seedConfig) || !fs_1.default.existsSync(seedCore) || !fs_1.default.existsSync(seedTemplates)) {
243
304
  throw new errors_1.NotFoundError(`init assets not found at ${seedRoot} (try reinstalling mdkg)`);
244
305
  }
@@ -263,67 +324,131 @@ function runInitCommand(options) {
263
324
  if (options.agent && !fs_1.default.existsSync(seedDefaultSkills)) {
264
325
  throw new errors_1.NotFoundError(`init assets missing default skills at ${seedRoot}`);
265
326
  }
266
- const mdkgDir = path_1.default.join(root, ".mdkg");
267
- fs_1.default.mkdirSync(mdkgDir, { recursive: true });
268
- fs_1.default.mkdirSync(path_1.default.join(mdkgDir, "work"), { recursive: true });
269
- fs_1.default.mkdirSync(path_1.default.join(mdkgDir, "design"), { recursive: true });
270
- const stats = { created: 0, skipped: 0 };
271
- copySeedFile(seedConfig, path_1.default.join(mdkgDir, "config.json"), force, stats);
272
- copySeedFile(seedReadme, path_1.default.join(mdkgDir, "README.md"), force, stats);
273
- copySeedDir(seedCore, path_1.default.join(mdkgDir, "core"), force, stats);
274
- copySeedDir(seedTemplates, path_1.default.join(mdkgDir, "templates"), force, stats);
275
- if (createAgents) {
276
- copySeedFile(seedAgents, path_1.default.join(root, "AGENTS.md"), force, stats);
277
- }
278
- if (createClaude) {
279
- copySeedFile(seedClaude, path_1.default.join(root, "CLAUDE.md"), force, stats);
327
+ preflightSeedConfig(seedConfig);
328
+ if (options.agent) {
329
+ (0, skill_mirror_1.preflightSkillMirrorTargets)({
330
+ root,
331
+ slugs: [...listSeedSkillSlugs(seedDefaultSkills), ...listExistingCanonicalSkillSlugs(root)],
332
+ force,
333
+ });
280
334
  }
281
- if (createStartupDocs) {
282
- copySeedFile(seedLlms, path_1.default.join(root, "llms.txt"), force, stats);
283
- copySeedFile(seedAgentStart, path_1.default.join(root, "AGENT_START.md"), force, stats);
284
- copySeedFile(seedCliMatrix, path_1.default.join(root, "CLI_COMMAND_MATRIX.md"), force, stats);
335
+ const stats = {
336
+ created: 0,
337
+ skipped: 0,
338
+ createdPaths: [],
339
+ skippedPaths: [],
340
+ ignoreFilesUpdated: [],
341
+ manifestWritten: false,
342
+ registryRefreshed: false,
343
+ mirrorTargets: 0,
344
+ mirroredSkills: 0,
345
+ };
346
+ const mdkgDir = path_1.default.join(root, ".mdkg");
347
+ try {
348
+ fs_1.default.mkdirSync(mdkgDir, { recursive: true });
349
+ fs_1.default.mkdirSync(path_1.default.join(mdkgDir, "work"), { recursive: true });
350
+ fs_1.default.mkdirSync(path_1.default.join(mdkgDir, "design"), { recursive: true });
351
+ copySeedFile(root, seedConfig, path_1.default.join(mdkgDir, "config.json"), force, stats);
352
+ copySeedFile(root, seedReadme, path_1.default.join(mdkgDir, "README.md"), force, stats);
353
+ copySeedDir(root, seedCore, path_1.default.join(mdkgDir, "core"), force, stats);
354
+ copySeedDir(root, seedTemplates, path_1.default.join(mdkgDir, "templates"), force, stats);
355
+ if (createAgents) {
356
+ copySeedFile(root, seedAgents, path_1.default.join(root, "AGENTS.md"), force, stats);
357
+ }
358
+ if (createClaude) {
359
+ copySeedFile(root, seedClaude, path_1.default.join(root, "CLAUDE.md"), force, stats);
360
+ }
361
+ if (createStartupDocs) {
362
+ copySeedFile(root, seedLlms, path_1.default.join(root, "llms.txt"), force, stats);
363
+ copySeedFile(root, seedAgentStart, path_1.default.join(root, "AGENT_START.md"), force, stats);
364
+ copySeedFile(root, seedCliMatrix, path_1.default.join(root, "CLI_COMMAND_MATRIX.md"), force, stats);
365
+ }
366
+ if (options.agent) {
367
+ const today = (0, date_1.formatDate)(new Date());
368
+ const soulPath = path_1.default.join(mdkgDir, "core", "SOUL.md");
369
+ const humanPath = path_1.default.join(mdkgDir, "core", "HUMAN.md");
370
+ const skillsDir = path_1.default.join(mdkgDir, "skills");
371
+ const registryPath = path_1.default.join(skillsDir, "registry.md");
372
+ const eventsDir = path_1.default.join(mdkgDir, "work", "events");
373
+ const eventsPath = path_1.default.join(eventsDir, "events.jsonl");
374
+ fs_1.default.mkdirSync(skillsDir, { recursive: true });
375
+ fs_1.default.mkdirSync(eventsDir, { recursive: true });
376
+ copySeedDir(root, seedDefaultSkills, skillsDir, force, stats);
377
+ if (!fs_1.default.existsSync(seedSoul)) {
378
+ writeFileIfMissing(root, soulPath, soulTemplate(today), force, stats);
379
+ }
380
+ if (!fs_1.default.existsSync(seedHuman)) {
381
+ writeFileIfMissing(root, humanPath, humanTemplate(today), force, stats);
382
+ }
383
+ writeFileIfMissing(root, registryPath, (0, skill_support_1.registryTemplate)(), force, stats);
384
+ if (!fs_1.default.existsSync(eventsPath) || force) {
385
+ writeFileIfMissing(root, eventsPath, seededInitEvent(new Date().toISOString()), force, stats);
386
+ }
387
+ const coreListPath = path_1.default.join(mdkgDir, "core", "core.md");
388
+ ensureCorePins(coreListPath, [SOUL_PIN_ID, HUMAN_PIN_ID]);
389
+ (0, skill_mirror_1.scaffoldMirrorRoots)(root);
390
+ const config = (0, config_1.loadConfig)(root);
391
+ (0, skill_support_1.refreshSkillsRegistry)(root, config);
392
+ stats.registryRefreshed = true;
393
+ const mirrorResult = (0, skill_mirror_1.syncSkillMirrors)({ root, config, createRoots: true, force });
394
+ stats.mirrorTargets = mirrorResult.targets;
395
+ stats.mirroredSkills = mirrorResult.synced;
396
+ }
397
+ (0, init_manifest_1.writeInitManifest)(path_1.default.join(mdkgDir, init_manifest_1.INIT_MANIFEST_FILE), seedManifest);
398
+ stats.manifestWritten = true;
285
399
  }
286
- if (options.agent) {
287
- const today = (0, date_1.formatDate)(new Date());
288
- const soulPath = path_1.default.join(mdkgDir, "core", "SOUL.md");
289
- const humanPath = path_1.default.join(mdkgDir, "core", "HUMAN.md");
290
- const skillsDir = path_1.default.join(mdkgDir, "skills");
291
- const registryPath = path_1.default.join(skillsDir, "registry.md");
292
- const eventsDir = path_1.default.join(mdkgDir, "work", "events");
293
- const eventsPath = path_1.default.join(eventsDir, "events.jsonl");
294
- fs_1.default.mkdirSync(skillsDir, { recursive: true });
295
- fs_1.default.mkdirSync(eventsDir, { recursive: true });
296
- copySeedDir(seedDefaultSkills, skillsDir, force, stats);
297
- writeFileIfMissing(soulPath, soulTemplate(today), force, stats);
298
- writeFileIfMissing(humanPath, humanTemplate(today), force, stats);
299
- writeFileIfMissing(registryPath, (0, skill_support_1.registryTemplate)(), force, stats);
300
- if (!fs_1.default.existsSync(eventsPath) || force) {
301
- writeFileIfMissing(eventsPath, seededInitEvent(new Date().toISOString()), force, stats);
400
+ catch (err) {
401
+ if (stats.created > 0 || stats.skipped > 0) {
402
+ emitPartialInitFailure(root, stats, err);
302
403
  }
303
- const coreListPath = path_1.default.join(mdkgDir, "core", "core.md");
304
- ensureCorePins(coreListPath, [SOUL_PIN_ID, HUMAN_PIN_ID]);
305
- (0, skill_mirror_1.scaffoldMirrorRoots)(root);
306
- const config = (0, config_1.loadConfig)(root);
307
- (0, skill_support_1.refreshSkillsRegistry)(root, config);
308
- (0, skill_mirror_1.syncSkillMirrors)({ root, config, createRoots: true, force });
404
+ throw err;
309
405
  }
310
- (0, init_manifest_1.writeInitManifest)(path_1.default.join(mdkgDir, init_manifest_1.INIT_MANIFEST_FILE), seedManifest);
311
406
  const noUpdateIgnores = Boolean(options.noUpdateIgnores);
312
407
  const shouldUpdateGitignore = Boolean(options.updateGitignore || !noUpdateIgnores);
313
408
  const shouldUpdateNpmignore = Boolean(options.updateNpmignore || !noUpdateIgnores);
314
- if (shouldUpdateGitignore) {
315
- appendIgnoreEntries(path_1.default.join(root, ".gitignore"), [
316
- ".mdkg/index/",
317
- ".mdkg/pack/",
318
- ]);
319
- }
320
- if (shouldUpdateNpmignore) {
321
- appendIgnoreEntries(path_1.default.join(root, ".npmignore"), [".mdkg/", ".mdkg/index/", ".mdkg/pack/"]);
409
+ try {
410
+ if (shouldUpdateGitignore) {
411
+ if (appendIgnoreEntries(path_1.default.join(root, ".gitignore"), [
412
+ ".mdkg/index/",
413
+ ".mdkg/pack/",
414
+ ".mdkg/archive/**/source/",
415
+ ])) {
416
+ stats.ignoreFilesUpdated.push(".gitignore");
417
+ }
418
+ }
419
+ if (shouldUpdateNpmignore) {
420
+ if (appendIgnoreEntries(path_1.default.join(root, ".npmignore"), [".mdkg/", ".mdkg/index/", ".mdkg/pack/"])) {
421
+ stats.ignoreFilesUpdated.push(".npmignore");
422
+ }
423
+ }
424
+ if (options.updateDockerignore) {
425
+ if (appendIgnoreEntries(path_1.default.join(root, ".dockerignore"), [".mdkg/"])) {
426
+ stats.ignoreFilesUpdated.push(".dockerignore");
427
+ }
428
+ }
322
429
  }
323
- if (options.updateDockerignore) {
324
- appendIgnoreEntries(path_1.default.join(root, ".dockerignore"), [".mdkg/"]);
430
+ catch (err) {
431
+ if (stats.created > 0 || stats.skipped > 0) {
432
+ emitPartialInitFailure(root, stats, err);
433
+ }
434
+ throw err;
325
435
  }
326
436
  console.log(`mdkg init complete: ${stats.created} file(s) created, ${stats.skipped} skipped`);
437
+ if (stats.manifestWritten) {
438
+ console.log("managed manifest: .mdkg/init-manifest.json");
439
+ }
440
+ if (stats.ignoreFilesUpdated.length > 0) {
441
+ console.log(`ignore files updated: ${stats.ignoreFilesUpdated.join(", ")}`);
442
+ }
443
+ if (options.agent) {
444
+ console.log("agent bootstrap: AGENT_START.md, AGENTS.md, CLAUDE.md, llms.txt, CLI_COMMAND_MATRIX.md");
445
+ console.log("agent core pins: rule-soul, rule-human");
446
+ console.log("agent event log: .mdkg/work/events/events.jsonl");
447
+ console.log(`skill mirrors: ${stats.mirroredSkills} sync operation(s) across ${stats.mirrorTargets} target(s)`);
448
+ if (stats.registryRefreshed) {
449
+ console.log("skill registry: .mdkg/skills/registry.md");
450
+ }
451
+ }
327
452
  console.log("next:");
328
453
  if (createStartupDocs) {
329
454
  console.log(" read AGENT_START.md");
@@ -83,19 +83,32 @@ function seedSourcePath(seedRoot, file) {
83
83
  }
84
84
  return path_1.default.join(seedRoot, file.path);
85
85
  }
86
- function createInitManifest(seedRoot, mdkgVersion) {
86
+ function createInitManifest(seedRoot, mdkgVersion, options = {
87
+ includeAgentDocs: true,
88
+ includeStartupDocs: true,
89
+ includeDefaultSkills: true,
90
+ }) {
91
+ const includeAgentDocs = Boolean(options.includeAgentDocs);
92
+ const includeStartupDocs = Boolean(options.includeStartupDocs);
93
+ const includeDefaultSkills = Boolean(options.includeDefaultSkills);
87
94
  const files = [];
88
95
  addSeedFile(files, seedRoot, "config.json", ".mdkg/config.json", "config");
89
96
  addSeedFile(files, seedRoot, "README.md", ".mdkg/README.md", "mdkg_doc");
90
97
  addSeedDir(files, seedRoot, "core", ".mdkg/core", "core");
91
98
  addSeedDir(files, seedRoot, "templates", ".mdkg/templates", "template");
92
- for (const doc of AGENT_DOCS) {
93
- addSeedFile(files, seedRoot, doc, doc, "agent_doc");
99
+ if (includeAgentDocs) {
100
+ for (const doc of AGENT_DOCS) {
101
+ addSeedFile(files, seedRoot, doc, doc, "agent_doc");
102
+ }
103
+ }
104
+ if (includeStartupDocs) {
105
+ for (const doc of STARTUP_DOCS) {
106
+ addSeedFile(files, seedRoot, doc, doc, "startup_doc");
107
+ }
94
108
  }
95
- for (const doc of STARTUP_DOCS) {
96
- addSeedFile(files, seedRoot, doc, doc, "startup_doc");
109
+ if (includeDefaultSkills) {
110
+ addSeedDir(files, seedRoot, path_1.default.join("skills", "default"), ".mdkg/skills", "default_skill");
97
111
  }
98
- addSeedDir(files, seedRoot, path_1.default.join("skills", "default"), ".mdkg/skills", "default_skill");
99
112
  return {
100
113
  schema_version: exports.INIT_MANIFEST_SCHEMA_VERSION,
101
114
  tool: "mdkg",
@@ -18,14 +18,14 @@ function normalizeWorkspace(value) {
18
18
  function runListCommand(options) {
19
19
  const config = (0, config_1.loadConfig)(options.root);
20
20
  const ws = normalizeWorkspace(options.ws);
21
- if (ws && !config.workspaces[ws]) {
21
+ if (ws && !config.workspaces[ws] && !config.bundle_imports[ws]) {
22
22
  throw new errors_1.NotFoundError(`workspace not found: ${ws}`);
23
23
  }
24
24
  const normalizedType = options.type?.toLowerCase();
25
25
  if (normalizedType === "skill") {
26
26
  throw new errors_1.UsageError("--type skill is no longer supported here; use `mdkg skill list`");
27
27
  }
28
- const { index, rebuilt, stale } = (0, index_cache_1.loadIndex)({
28
+ const { index, rebuilt, stale, warnings } = (0, index_cache_1.loadIndex)({
29
29
  root: options.root,
30
30
  config,
31
31
  useCache: !options.noCache,
@@ -34,6 +34,9 @@ function runListCommand(options) {
34
34
  if (stale && !rebuilt && !options.noCache) {
35
35
  console.error("warning: index is stale; run mdkg index to refresh");
36
36
  }
37
+ for (const warning of warnings) {
38
+ console.error(`warning: ${warning}`);
39
+ }
37
40
  let epicQid;
38
41
  if (options.epic) {
39
42
  const resolved = (0, qid_1.resolveQid)(index, options.epic, ws);
@@ -156,6 +156,9 @@ function runNewCommand(options) {
156
156
  throw new errors_1.UsageError("title cannot be empty");
157
157
  }
158
158
  const type = options.type.toLowerCase();
159
+ if (type === "archive") {
160
+ throw new errors_1.UsageError("use `mdkg archive add <file>` to create archive sidecars");
161
+ }
159
162
  if (!node_1.ALLOWED_TYPES.has(type)) {
160
163
  throw new errors_1.UsageError(`type must be one of ${Array.from(node_1.ALLOWED_TYPES).join(", ")}`);
161
164
  }
@@ -286,6 +289,9 @@ function runNewCommand(options) {
286
289
  }
287
290
  const today = (0, date_1.formatDate)(options.now ?? new Date());
288
291
  const template = (0, loader_1.loadTemplate)(options.root, config, type, options.template);
292
+ if (template.source === "bundled") {
293
+ console.error(`warning: using bundled template fallback for ${type}; run \`mdkg upgrade --apply\` to vendor missing local templates`);
294
+ }
289
295
  const content = (0, loader_1.renderTemplate)(template, {
290
296
  id,
291
297
  type,
@@ -21,6 +21,9 @@ function selectNextByPriority(index, ws, statusPreference, priorityMax) {
21
21
  if (ws && node.ws !== ws) {
22
22
  return false;
23
23
  }
24
+ if (node.source?.imported) {
25
+ return false;
26
+ }
24
27
  if (!NEXT_TYPES.has(node.type)) {
25
28
  return false;
26
29
  }
@@ -59,6 +62,10 @@ function runNextCommand(options) {
59
62
  throw new errors_1.NotFoundError((0, qid_1.formatResolveError)("id", options.id, resolved, ws));
60
63
  }
61
64
  const node = index.nodes[resolved.qid];
65
+ if (node.source?.imported) {
66
+ console.error("no local next item: imported bundle nodes are read-only planning context");
67
+ return;
68
+ }
62
69
  const nextQid = node.edges.next;
63
70
  if (nextQid && index.nodes[nextQid]) {
64
71
  console.log((0, node_card_1.formatNodeCard)(index.nodes[nextQid]));
@@ -7,11 +7,14 @@ function formatStatusPriority(node) {
7
7
  return `${status}/${priority}`;
8
8
  }
9
9
  function formatNodeCard(node) {
10
+ const sourceLabel = node.source?.imported
11
+ ? ` | import:${node.source.import_alias}${node.source.stale ? ":stale" : ""} | read-only`
12
+ : "";
10
13
  return [
11
14
  node.qid,
12
15
  node.type,
13
16
  formatStatusPriority(node),
14
17
  node.title,
15
18
  node.path,
16
- ].join(" | ");
19
+ ].join(" | ") + sourceLabel;
17
20
  }