mdkg 0.1.1 → 0.1.3
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 +104 -0
- package/README.md +124 -18
- package/dist/cli.js +567 -15
- package/dist/commands/archive.js +486 -0
- package/dist/commands/bundle.js +743 -0
- package/dist/commands/bundle_import.js +255 -0
- package/dist/commands/capability.js +162 -0
- package/dist/commands/checkpoint.js +31 -5
- package/dist/commands/doctor.js +269 -9
- package/dist/commands/format.js +38 -9
- package/dist/commands/index.js +12 -12
- package/dist/commands/init.js +194 -63
- package/dist/commands/init_manifest.js +19 -6
- package/dist/commands/list.js +5 -2
- package/dist/commands/new.js +36 -7
- package/dist/commands/next.js +7 -0
- package/dist/commands/node_card.js +4 -1
- package/dist/commands/pack.js +62 -2
- package/dist/commands/query_output.js +1 -0
- package/dist/commands/search.js +5 -2
- package/dist/commands/show.js +7 -14
- package/dist/commands/skill_mirror.js +22 -0
- package/dist/commands/task.js +23 -6
- package/dist/commands/upgrade.js +24 -1
- package/dist/commands/validate.js +20 -1
- package/dist/commands/work.js +397 -0
- package/dist/commands/workspace.js +12 -2
- package/dist/core/config.js +115 -1
- package/dist/graph/agent_file_types.js +78 -5
- package/dist/graph/archive_file.js +125 -0
- package/dist/graph/archive_integrity.js +66 -0
- package/dist/graph/bundle_imports.js +418 -0
- package/dist/graph/capabilities_index_cache.js +103 -0
- package/dist/graph/capabilities_indexer.js +231 -0
- package/dist/graph/frontmatter.js +19 -0
- package/dist/graph/index_cache.js +23 -6
- package/dist/graph/indexer.js +4 -1
- package/dist/graph/node.js +23 -4
- package/dist/graph/node_body.js +37 -0
- package/dist/graph/reindex.js +46 -0
- package/dist/graph/skills_index_cache.js +2 -2
- package/dist/graph/skills_indexer.js +8 -3
- package/dist/graph/sqlite_index.js +293 -0
- package/dist/graph/validate_graph.js +83 -7
- package/dist/graph/visibility.js +214 -0
- package/dist/graph/workspace_files.js +22 -0
- package/dist/init/AGENT_START.md +24 -0
- package/dist/init/CLI_COMMAND_MATRIX.md +61 -3
- package/dist/init/README.md +70 -4
- package/dist/init/config.json +18 -2
- package/dist/init/core/guide.md +6 -2
- package/dist/init/core/rule-1-mdkg-conventions.md +2 -1
- package/dist/init/core/rule-3-cli-contract.md +72 -4
- package/dist/init/core/rule-4-repo-safety-and-ignores.md +47 -11
- package/dist/init/core/rule-5-release-and-versioning.md +4 -3
- package/dist/init/core/rule-6-templates-and-schemas.md +7 -0
- package/dist/init/init-manifest.json +21 -16
- package/dist/init/skills/default/build-pack-and-execute-task/SKILL.md +2 -1
- package/dist/init/skills/default/verify-close-and-checkpoint/SKILL.md +26 -0
- package/dist/init/templates/default/archive.md +33 -0
- package/dist/init/templates/default/receipt.md +15 -1
- package/dist/init/templates/default/work.md +6 -1
- package/dist/init/templates/default/work_order.md +15 -1
- package/dist/pack/export_md.js +3 -0
- package/dist/pack/export_xml.js +3 -0
- package/dist/pack/order.js +1 -0
- package/dist/pack/pack.js +3 -13
- package/dist/util/argparse.js +30 -0
- package/dist/util/atomic.js +44 -0
- package/dist/util/lock.js +72 -0
- package/dist/util/refs.js +40 -0
- package/dist/util/zip.js +153 -0
- package/package.json +14 -5
package/dist/commands/init.js
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
228
|
-
const createClaude = Boolean(options.
|
|
229
|
-
const createStartupDocs = Boolean(options.
|
|
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
|
|
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,137 @@ 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
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
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
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
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
|
-
|
|
287
|
-
|
|
288
|
-
|
|
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
|
-
|
|
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
|
-
|
|
315
|
-
|
|
316
|
-
".
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
409
|
+
try {
|
|
410
|
+
if (shouldUpdateGitignore) {
|
|
411
|
+
if (appendIgnoreEntries(path_1.default.join(root, ".gitignore"), [
|
|
412
|
+
".mdkg/index/*.json",
|
|
413
|
+
".mdkg/index/*.tmp",
|
|
414
|
+
".mdkg/index/*.lock",
|
|
415
|
+
".mdkg/index/write.lock/",
|
|
416
|
+
".mdkg/index/*.sqlite-wal",
|
|
417
|
+
".mdkg/index/*.sqlite-shm",
|
|
418
|
+
".mdkg/index/*.sqlite-journal",
|
|
419
|
+
".mdkg/pack/",
|
|
420
|
+
".mdkg/archive/**/source/",
|
|
421
|
+
])) {
|
|
422
|
+
stats.ignoreFilesUpdated.push(".gitignore");
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
if (shouldUpdateNpmignore) {
|
|
426
|
+
if (appendIgnoreEntries(path_1.default.join(root, ".npmignore"), [".mdkg/", ".mdkg/index/", ".mdkg/pack/"])) {
|
|
427
|
+
stats.ignoreFilesUpdated.push(".npmignore");
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
if (options.updateDockerignore) {
|
|
431
|
+
if (appendIgnoreEntries(path_1.default.join(root, ".dockerignore"), [".mdkg/"])) {
|
|
432
|
+
stats.ignoreFilesUpdated.push(".dockerignore");
|
|
433
|
+
}
|
|
434
|
+
}
|
|
322
435
|
}
|
|
323
|
-
|
|
324
|
-
|
|
436
|
+
catch (err) {
|
|
437
|
+
if (stats.created > 0 || stats.skipped > 0) {
|
|
438
|
+
emitPartialInitFailure(root, stats, err);
|
|
439
|
+
}
|
|
440
|
+
throw err;
|
|
325
441
|
}
|
|
326
442
|
console.log(`mdkg init complete: ${stats.created} file(s) created, ${stats.skipped} skipped`);
|
|
443
|
+
if (stats.manifestWritten) {
|
|
444
|
+
console.log("managed manifest: .mdkg/init-manifest.json");
|
|
445
|
+
}
|
|
446
|
+
if (stats.ignoreFilesUpdated.length > 0) {
|
|
447
|
+
console.log(`ignore files updated: ${stats.ignoreFilesUpdated.join(", ")}`);
|
|
448
|
+
}
|
|
449
|
+
if (options.agent) {
|
|
450
|
+
console.log("agent bootstrap: AGENT_START.md, AGENTS.md, CLAUDE.md, llms.txt, CLI_COMMAND_MATRIX.md");
|
|
451
|
+
console.log("agent core pins: rule-soul, rule-human");
|
|
452
|
+
console.log("agent event log: .mdkg/work/events/events.jsonl");
|
|
453
|
+
console.log(`skill mirrors: ${stats.mirroredSkills} sync operation(s) across ${stats.mirrorTargets} target(s)`);
|
|
454
|
+
if (stats.registryRefreshed) {
|
|
455
|
+
console.log("skill registry: .mdkg/skills/registry.md");
|
|
456
|
+
}
|
|
457
|
+
}
|
|
327
458
|
console.log("next:");
|
|
328
459
|
if (createStartupDocs) {
|
|
329
460
|
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
|
-
|
|
93
|
-
|
|
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
|
-
|
|
96
|
-
|
|
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",
|
package/dist/commands/list.js
CHANGED
|
@@ -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);
|
package/dist/commands/new.js
CHANGED
|
@@ -16,6 +16,10 @@ const date_1 = require("../util/date");
|
|
|
16
16
|
const errors_1 = require("../util/errors");
|
|
17
17
|
const qid_1 = require("../util/qid");
|
|
18
18
|
const id_1 = require("../util/id");
|
|
19
|
+
const atomic_1 = require("../util/atomic");
|
|
20
|
+
const lock_1 = require("../util/lock");
|
|
21
|
+
const sqlite_index_1 = require("../graph/sqlite_index");
|
|
22
|
+
const reindex_1 = require("../graph/reindex");
|
|
19
23
|
const event_support_1 = require("./event_support");
|
|
20
24
|
const DEC_ID_RE = /^dec-[0-9]+$/;
|
|
21
25
|
const DEC_STATUS = new Set(["proposed", "accepted", "rejected", "superseded"]);
|
|
@@ -97,6 +101,9 @@ function slugifyTitle(title) {
|
|
|
97
101
|
return slug.length > maxLen ? slug.slice(0, maxLen).replace(/-+$/g, "") : slug;
|
|
98
102
|
}
|
|
99
103
|
function nextIdForPrefix(index, ws, prefix) {
|
|
104
|
+
return `${prefix}-${maxIdForPrefix(index, ws, prefix) + 1}`;
|
|
105
|
+
}
|
|
106
|
+
function maxIdForPrefix(index, ws, prefix) {
|
|
100
107
|
let max = 0;
|
|
101
108
|
const pattern = new RegExp(`^${prefix}-(\\d+)$`);
|
|
102
109
|
for (const node of Object.values(index)) {
|
|
@@ -112,7 +119,7 @@ function nextIdForPrefix(index, ws, prefix) {
|
|
|
112
119
|
max = parsed;
|
|
113
120
|
}
|
|
114
121
|
}
|
|
115
|
-
return
|
|
122
|
+
return max;
|
|
116
123
|
}
|
|
117
124
|
function idPrefixForType(type) {
|
|
118
125
|
if (type === "checkpoint") {
|
|
@@ -150,12 +157,15 @@ function ensureExists(index, value, ws, label) {
|
|
|
150
157
|
throw new errors_1.NotFoundError((0, qid_1.formatResolveError)(label, value, resolved, ws));
|
|
151
158
|
}
|
|
152
159
|
}
|
|
153
|
-
function
|
|
160
|
+
function runNewCommandLocked(options) {
|
|
154
161
|
const title = options.title.trim();
|
|
155
162
|
if (!title) {
|
|
156
163
|
throw new errors_1.UsageError("title cannot be empty");
|
|
157
164
|
}
|
|
158
165
|
const type = options.type.toLowerCase();
|
|
166
|
+
if (type === "archive") {
|
|
167
|
+
throw new errors_1.UsageError("use `mdkg archive add <file>` to create archive sidecars");
|
|
168
|
+
}
|
|
159
169
|
if (!node_1.ALLOWED_TYPES.has(type)) {
|
|
160
170
|
throw new errors_1.UsageError(`type must be one of ${Array.from(node_1.ALLOWED_TYPES).join(", ")}`);
|
|
161
171
|
}
|
|
@@ -178,7 +188,15 @@ function runNewCommand(options) {
|
|
|
178
188
|
const prefix = idPrefixForType(type);
|
|
179
189
|
const id = options.id !== undefined
|
|
180
190
|
? normalizeAgentFileId(options.id)
|
|
181
|
-
:
|
|
191
|
+
: (0, sqlite_index_1.isSqliteBackend)(config)
|
|
192
|
+
? (0, sqlite_index_1.reserveSqliteNumericId)({
|
|
193
|
+
root: options.root,
|
|
194
|
+
config,
|
|
195
|
+
ws,
|
|
196
|
+
prefix,
|
|
197
|
+
currentMax: maxIdForPrefix(index.nodes, ws, prefix),
|
|
198
|
+
}) ?? nextIdForPrefix(index.nodes, ws, prefix)
|
|
199
|
+
: nextIdForPrefix(index.nodes, ws, prefix);
|
|
182
200
|
if (index.nodes[`${ws}:${id}`]) {
|
|
183
201
|
throw new errors_1.UsageError(`node already exists: ${ws}:${id}`);
|
|
184
202
|
}
|
|
@@ -314,12 +332,19 @@ function runNewCommand(options) {
|
|
|
314
332
|
created: today,
|
|
315
333
|
updated: today,
|
|
316
334
|
});
|
|
317
|
-
|
|
318
|
-
|
|
335
|
+
try {
|
|
336
|
+
(0, atomic_1.writeFileExclusive)(filePath, content);
|
|
337
|
+
}
|
|
338
|
+
catch (err) {
|
|
339
|
+
const code = typeof err === "object" && err !== null && "code" in err ? String(err.code) : "";
|
|
340
|
+
if (code === "EEXIST") {
|
|
341
|
+
throw new errors_1.UsageError(`node already exists: ${path_1.default.relative(options.root, filePath)}`);
|
|
342
|
+
}
|
|
343
|
+
throw err;
|
|
344
|
+
}
|
|
319
345
|
if (config.index.auto_reindex && !noReindex) {
|
|
320
346
|
const updatedIndex = (0, indexer_1.buildIndex)(options.root, config, { tolerant: config.index.tolerant });
|
|
321
|
-
|
|
322
|
-
(0, index_cache_1.writeIndex)(outputPath, updatedIndex);
|
|
347
|
+
(0, reindex_1.writeDerivedIndexes)(options.root, config, updatedIndex);
|
|
323
348
|
}
|
|
324
349
|
(0, event_support_1.appendAutomaticEvent)({
|
|
325
350
|
root: options.root,
|
|
@@ -351,3 +376,7 @@ function runNewCommand(options) {
|
|
|
351
376
|
}
|
|
352
377
|
console.log(`node created: ${receipt.qid} (${receipt.path})`);
|
|
353
378
|
}
|
|
379
|
+
function runNewCommand(options) {
|
|
380
|
+
const config = (0, config_1.loadConfig)(options.root);
|
|
381
|
+
return (0, lock_1.withMutationLock)(options.root, config.index.lock_timeout_ms, () => runNewCommandLocked(options));
|
|
382
|
+
}
|
package/dist/commands/next.js
CHANGED
|
@@ -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
|
}
|
package/dist/commands/pack.js
CHANGED
|
@@ -11,6 +11,7 @@ const index_cache_1 = require("../graph/index_cache");
|
|
|
11
11
|
const frontmatter_1 = require("../graph/frontmatter");
|
|
12
12
|
const skills_index_cache_1 = require("../graph/skills_index_cache");
|
|
13
13
|
const node_1 = require("../graph/node");
|
|
14
|
+
const visibility_1 = require("../graph/visibility");
|
|
14
15
|
const budget_1 = require("../pack/budget");
|
|
15
16
|
const export_json_1 = require("../pack/export_json");
|
|
16
17
|
const export_md_1 = require("../pack/export_md");
|
|
@@ -217,6 +218,53 @@ function applyNodeCountLimit(pack, maxNodes) {
|
|
|
217
218
|
nodes: included,
|
|
218
219
|
};
|
|
219
220
|
}
|
|
221
|
+
function packNodeVisibility(node, index, config) {
|
|
222
|
+
const indexNode = index.nodes[node.qid];
|
|
223
|
+
if (indexNode) {
|
|
224
|
+
return (0, visibility_1.effectiveNodeVisibility)(indexNode, config);
|
|
225
|
+
}
|
|
226
|
+
return (0, visibility_1.normalizeVisibility)(config.workspaces[node.workspace]?.visibility, "workspace visibility");
|
|
227
|
+
}
|
|
228
|
+
function applyVisibilityFilter(pack, index, config, scope) {
|
|
229
|
+
if (scope === "private") {
|
|
230
|
+
return {
|
|
231
|
+
...pack,
|
|
232
|
+
meta: {
|
|
233
|
+
...pack.meta,
|
|
234
|
+
visibility: scope,
|
|
235
|
+
},
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
const includedNodes = pack.nodes.filter((node) => (0, visibility_1.isVisibleAt)(packNodeVisibility(node, index, config), scope));
|
|
239
|
+
if (includedNodes.length === 0 || includedNodes[0].qid !== pack.nodes[0]?.qid) {
|
|
240
|
+
throw new errors_1.ValidationError(`pack root ${pack.meta.root} is not visible at ${scope}`);
|
|
241
|
+
}
|
|
242
|
+
const includedQids = new Set(includedNodes.map((node) => node.qid));
|
|
243
|
+
const graphIncludedQids = new Set(includedNodes.filter((node) => Boolean(index.nodes[node.qid])).map((node) => node.qid));
|
|
244
|
+
const violations = (0, visibility_1.collectVisibilityViolations)(index, config, {
|
|
245
|
+
includedQids: graphIncludedQids,
|
|
246
|
+
scope,
|
|
247
|
+
});
|
|
248
|
+
if (violations.length > 0) {
|
|
249
|
+
throw new errors_1.ValidationError(`${scope} pack contains less-visible references:\n${(0, visibility_1.visibilityViolationMessages)(violations).join("\n")}`);
|
|
250
|
+
}
|
|
251
|
+
const dropped = pack.nodes
|
|
252
|
+
.filter((node) => !includedQids.has(node.qid))
|
|
253
|
+
.map((node) => node.qid);
|
|
254
|
+
return {
|
|
255
|
+
...pack,
|
|
256
|
+
meta: {
|
|
257
|
+
...pack.meta,
|
|
258
|
+
visibility: scope,
|
|
259
|
+
node_count: includedNodes.length,
|
|
260
|
+
truncated: {
|
|
261
|
+
...pack.meta.truncated,
|
|
262
|
+
dropped: [...pack.meta.truncated.dropped, ...dropped],
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
nodes: includedNodes,
|
|
266
|
+
};
|
|
267
|
+
}
|
|
220
268
|
function writeJsonFile(outPath, payload) {
|
|
221
269
|
fs_1.default.mkdirSync(path_1.default.dirname(outPath), { recursive: true });
|
|
222
270
|
fs_1.default.writeFileSync(outPath, JSON.stringify(payload, null, 2), "utf8");
|
|
@@ -243,6 +291,9 @@ function printDryRunSummary(pack, stats, format) {
|
|
|
243
291
|
console.log(`root: ${pack.meta.root}`);
|
|
244
292
|
console.log(`profile: ${pack.meta.profile ?? "standard"}`);
|
|
245
293
|
console.log(`body_mode: ${pack.meta.body_mode ?? "full"}`);
|
|
294
|
+
if (pack.meta.visibility) {
|
|
295
|
+
console.log(`visibility: ${pack.meta.visibility}`);
|
|
296
|
+
}
|
|
246
297
|
console.log(`format: ${format}`);
|
|
247
298
|
console.log(`nodes: ${pack.nodes.length}`);
|
|
248
299
|
if (pack.meta.latest_checkpoint_qid) {
|
|
@@ -267,10 +318,10 @@ function printDryRunSummary(pack, stats, format) {
|
|
|
267
318
|
function runPackCommand(options) {
|
|
268
319
|
const config = (0, config_1.loadConfig)(options.root);
|
|
269
320
|
const ws = normalizeWorkspace(options.ws);
|
|
270
|
-
if (ws && !config.workspaces[ws]) {
|
|
321
|
+
if (ws && !config.workspaces[ws] && !config.bundle_imports[ws]) {
|
|
271
322
|
throw new errors_1.NotFoundError(`workspace not found: ${ws}`);
|
|
272
323
|
}
|
|
273
|
-
const { index, rebuilt, stale } = (0, index_cache_1.loadIndex)({
|
|
324
|
+
const { index, rebuilt, stale, warnings } = (0, index_cache_1.loadIndex)({
|
|
274
325
|
root: options.root,
|
|
275
326
|
config,
|
|
276
327
|
useCache: !options.noCache,
|
|
@@ -279,6 +330,9 @@ function runPackCommand(options) {
|
|
|
279
330
|
if (stale && !rebuilt && !options.noCache) {
|
|
280
331
|
console.error("warning: index is stale; run mdkg index to refresh");
|
|
281
332
|
}
|
|
333
|
+
for (const warning of warnings) {
|
|
334
|
+
console.error(`warning: ${warning}`);
|
|
335
|
+
}
|
|
282
336
|
const resolved = (0, qid_1.resolveQid)(index, options.id, ws);
|
|
283
337
|
if (resolved.status !== "ok") {
|
|
284
338
|
throw new errors_1.NotFoundError((0, qid_1.formatResolveError)("id", options.id, resolved, ws));
|
|
@@ -291,6 +345,9 @@ function runPackCommand(options) {
|
|
|
291
345
|
const edges = normalizeEdges([...config.pack.default_edges, ...extraEdges]);
|
|
292
346
|
const skillsPolicy = resolveSkillsPolicy(options.skills);
|
|
293
347
|
const skillsDepth = resolveSkillsDepth(options.skillsDepth);
|
|
348
|
+
const visibility = options.visibility
|
|
349
|
+
? (0, visibility_1.normalizeVisibility)(options.visibility)
|
|
350
|
+
: undefined;
|
|
294
351
|
let resolvedProfile;
|
|
295
352
|
try {
|
|
296
353
|
resolvedProfile = (0, profile_1.resolvePackProfile)({
|
|
@@ -350,6 +407,9 @@ function runPackCommand(options) {
|
|
|
350
407
|
packWithSkills = appendSkillsToPack(packWithSkills, selectedEntries, skillsDepth, options.root);
|
|
351
408
|
packWithSkills = applyNodeCountLimit(packWithSkills, config.pack.limits.max_nodes);
|
|
352
409
|
}
|
|
410
|
+
if (visibility) {
|
|
411
|
+
packWithSkills = applyVisibilityFilter(packWithSkills, index, config, visibility);
|
|
412
|
+
}
|
|
353
413
|
const templateHeadingMap = resolvedProfile.bodyMode === "summary"
|
|
354
414
|
? (0, headings_1.loadTemplateHeadingMap)(options.root, config, Array.from(node_1.ALLOWED_TYPES))
|
|
355
415
|
: {};
|