mdkg 0.3.8 → 0.3.9
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 +26 -0
- package/CLI_COMMAND_MATRIX.md +5 -3
- package/README.md +2 -2
- package/dist/cli.js +2 -1
- package/dist/command-contract.json +2 -2
- package/dist/commands/init.js +84 -3
- package/dist/commands/skill.js +1 -1
- package/dist/commands/skill_mirror.js +22 -17
- package/dist/commands/skill_support.js +1 -1
- package/dist/commands/upgrade.js +67 -24
- package/dist/core/config.js +132 -0
- package/dist/init/AGENT_START.md +5 -4
- package/dist/init/CLI_COMMAND_MATRIX.md +1 -1
- package/dist/init/config.json +15 -0
- package/dist/init/core/COLLABORATION.md +45 -0
- package/dist/init/core/HUMAN.md +7 -1
- package/dist/init/core/core.md +1 -0
- package/dist/init/core/rule-1-mdkg-conventions.md +3 -0
- package/dist/init/core/rule-3-cli-contract.md +5 -5
- package/dist/init/init-manifest.json +22 -12
- package/dist/init/llms.txt +2 -1
- package/dist/init/skills/default/author-mdkg-skill/SKILL.md +211 -0
- package/dist/init/skills/default/pursue-mdkg-goal/SKILL.md +10 -0
- package/dist/init/skills/default/select-work-and-ground-context/SKILL.md +8 -0
- package/dist/init/skills/default/verify-close-and-checkpoint/SKILL.md +73 -9
- package/package.json +6 -4
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,32 @@ mdkg is pre-v1 public alpha software. Command, graph, cache, bundle, and DAL con
|
|
|
8
8
|
|
|
9
9
|
## Unreleased
|
|
10
10
|
|
|
11
|
+
## 0.3.9 - 2026-06-27
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- Added `.mdkg/config.json` customization overlays for organization standards,
|
|
16
|
+
custom core docs, and configured skill mirror target paths while keeping the
|
|
17
|
+
mdkg CLI kernel upgradable through `mdkg upgrade --apply`.
|
|
18
|
+
- Added configurable skill mirror support so repos can mirror canonical
|
|
19
|
+
`.mdkg/skills` into arbitrary contained agent-local skill roots, with
|
|
20
|
+
`.agents/skills` and `.claude/skills` preserved as defaults.
|
|
21
|
+
- Added `COLLABORATION.md` as the canonical collaboration/operator profile core
|
|
22
|
+
doc while keeping `HUMAN.md` as a one-release legacy alias.
|
|
23
|
+
- Added deterministic release-notes data generation from `CHANGELOG.md` for
|
|
24
|
+
public docs and future per-release cards.
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
|
|
28
|
+
- Updated `mdkg init --agent` and `mdkg upgrade --apply` to seed and preserve
|
|
29
|
+
customization overlays, configurable mirrors, `COLLABORATION.md`, legacy
|
|
30
|
+
`HUMAN.md`, and accurate managed init-manifest hashes.
|
|
31
|
+
- Refreshed first-party mdkg skills and default init seed skills for current CLI
|
|
32
|
+
coverage, MANIFEST authoring, configured mirror targets, pre-publish gates,
|
|
33
|
+
and explicit no-publish/no-tag/no-push approval boundaries.
|
|
34
|
+
- Expanded `npm run docs:check` and `prepublishOnly` to verify generated CLI
|
|
35
|
+
docs, generated release-note data, and public command examples before publish.
|
|
36
|
+
|
|
11
37
|
## 0.3.8 - 2026-06-25
|
|
12
38
|
|
|
13
39
|
### Added
|
package/CLI_COMMAND_MATRIX.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# CLI Command Matrix
|
|
2
2
|
|
|
3
3
|
as_of: 2026-06-21
|
|
4
|
-
package_version_in_source: 0.3.
|
|
4
|
+
package_version_in_source: 0.3.9
|
|
5
5
|
source: live help from `src/cli.ts`, runtime command handlers, and `dec-15`..`dec-18`
|
|
6
6
|
status: canonical single-source command and flag reference for mdkg
|
|
7
7
|
|
|
@@ -118,7 +118,7 @@ Notes:
|
|
|
118
118
|
- `--agent` is the canonical complete AI-agent bootstrap path
|
|
119
119
|
- removed flags `--llm`, `--agents`, `--claude`, and `--omni` fail before mutation with guidance to use `mdkg init --agent`
|
|
120
120
|
- published bootstrap config is root-only by default
|
|
121
|
-
- `--agent` creates `AGENT_START.md`, `AGENTS.md`, `CLAUDE.md`, `llms.txt`, `CLI_COMMAND_MATRIX.md`, strict-node core docs, default mdkg usage skills, `events.jsonl`, registry, and skill mirrors
|
|
121
|
+
- `--agent` creates `AGENT_START.md`, `AGENTS.md`, `CLAUDE.md`, `llms.txt`, `CLI_COMMAND_MATRIX.md`, strict-node `SOUL.md` / `COLLABORATION.md` core docs, legacy `HUMAN.md`, default mdkg usage skills, `events.jsonl`, registry, and configured skill mirrors
|
|
122
122
|
- run `mdkg index` after fresh init before treating `mdkg doctor --strict --json` as a clean health gate; init writes source scaffold files and index writes generated caches
|
|
123
123
|
|
|
124
124
|
### `mdkg upgrade`
|
|
@@ -443,7 +443,9 @@ JSON receipt:
|
|
|
443
443
|
- `{ action: "synced", sync: { synced, pruned, targets } }`
|
|
444
444
|
|
|
445
445
|
Notes:
|
|
446
|
-
- syncs canonical `.mdkg/skills/` into
|
|
446
|
+
- syncs canonical `.mdkg/skills/` into configured
|
|
447
|
+
`customization.skill_mirrors.targets` paths from `.mdkg/config.json`
|
|
448
|
+
- defaults are `.agents/skills` and `.claude/skills`
|
|
447
449
|
- preserves unrelated existing folders
|
|
448
450
|
- same-slug collisions fail unless forced
|
|
449
451
|
|
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ mdkg stays deliberately boring:
|
|
|
14
14
|
- first-class rebuildable SQLite cache through built-in `node:sqlite`
|
|
15
15
|
- no daemon, hosted index, or vector DB
|
|
16
16
|
|
|
17
|
-
Current package version in source: `0.3.
|
|
17
|
+
Current package version in source: `0.3.9`
|
|
18
18
|
|
|
19
19
|
mdkg is still pre-v1 public alpha software. The public package is usable, but graph, cache, bundle, and DAL contracts may continue to change quickly while the project converges on a stable v1 surface.
|
|
20
20
|
|
|
@@ -82,7 +82,7 @@ mdkg init --agent
|
|
|
82
82
|
mdkg index
|
|
83
83
|
```
|
|
84
84
|
|
|
85
|
-
This is the canonical AI-agent bootstrap path. It creates `.mdkg/`, `AGENT_START.md`, `AGENTS.md`, `CLAUDE.md`, `llms.txt`, `CLI_COMMAND_MATRIX.md`, strict-node `SOUL.md` / `
|
|
85
|
+
This is the canonical AI-agent bootstrap path. It creates `.mdkg/`, `AGENT_START.md`, `AGENTS.md`, `CLAUDE.md`, `llms.txt`, `CLI_COMMAND_MATRIX.md`, strict-node `SOUL.md` / `COLLABORATION.md`, legacy `HUMAN.md` for one release, the default mdkg usage skills, `events.jsonl`, the skill registry, core pin updates, and configured skill mirrors under `.agents/skills/` and `.claude/skills/` by default. It also updates `.gitignore` / `.npmignore` by default. Use `--no-update-ignores` to opt out of those ignore-file updates.
|
|
86
86
|
|
|
87
87
|
Run `mdkg index` after a fresh init before using `mdkg status --json` or
|
|
88
88
|
`mdkg doctor --strict --json` as health gates. Init writes source scaffold
|
package/dist/cli.js
CHANGED
|
@@ -414,7 +414,8 @@ function printSkillHelp(log, subcommand) {
|
|
|
414
414
|
log("Usage:");
|
|
415
415
|
log(" mdkg skill sync [--force] [--json]");
|
|
416
416
|
log("\nWhen to use:");
|
|
417
|
-
log(" Rebuild
|
|
417
|
+
log(" Rebuild configured skill mirror targets from canonical .mdkg/skills.");
|
|
418
|
+
log(" Defaults are .agents/skills and .claude/skills; add custom targets in .mdkg/config.json.");
|
|
418
419
|
printGlobalOptions(log);
|
|
419
420
|
return;
|
|
420
421
|
default:
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema_version": 1,
|
|
3
3
|
"tool": "mdkg",
|
|
4
|
-
"package_version": "0.3.
|
|
4
|
+
"package_version": "0.3.9",
|
|
5
5
|
"source": {
|
|
6
6
|
"help_targets": "scripts/cli_help_targets.js",
|
|
7
7
|
"command_matrix": "CLI_COMMAND_MATRIX.md"
|
|
@@ -9128,5 +9128,5 @@
|
|
|
9128
9128
|
}
|
|
9129
9129
|
}
|
|
9130
9130
|
],
|
|
9131
|
-
"contract_hash": "
|
|
9131
|
+
"contract_hash": "3c13c572c740f1e40db33fa5867fa227a8347df0750ef3beb0696d5931761a6c"
|
|
9132
9132
|
}
|
package/dist/commands/init.js
CHANGED
|
@@ -17,6 +17,7 @@ const skill_support_1 = require("./skill_support");
|
|
|
17
17
|
const skill_mirror_1 = require("./skill_mirror");
|
|
18
18
|
const DEFAULT_SEED_SUBDIR = path_1.default.resolve(__dirname, "..", "init");
|
|
19
19
|
const SOUL_PIN_ID = "rule-soul";
|
|
20
|
+
const COLLABORATION_PIN_ID = "rule-7";
|
|
20
21
|
const HUMAN_PIN_ID = "rule-human";
|
|
21
22
|
const DEFAULT_CORE_LIST_HEADER = [
|
|
22
23
|
"# mdkg verbose core list",
|
|
@@ -175,6 +176,52 @@ function humanTemplate(created) {
|
|
|
175
176
|
"",
|
|
176
177
|
].join("\n");
|
|
177
178
|
}
|
|
179
|
+
function collaborationTemplate(created) {
|
|
180
|
+
return [
|
|
181
|
+
"---",
|
|
182
|
+
`id: ${COLLABORATION_PIN_ID}`,
|
|
183
|
+
"type: rule",
|
|
184
|
+
"title: collaboration profile and operator preferences",
|
|
185
|
+
"tags: [collaboration, preferences, operator]",
|
|
186
|
+
"owners: []",
|
|
187
|
+
"links: []",
|
|
188
|
+
"artifacts: []",
|
|
189
|
+
"relates: [rule-human]",
|
|
190
|
+
"refs: [dec-53]",
|
|
191
|
+
"aliases: [collaboration, operator-profile]",
|
|
192
|
+
`created: ${created}`,
|
|
193
|
+
`updated: ${created}`,
|
|
194
|
+
"---",
|
|
195
|
+
"",
|
|
196
|
+
"# Purpose",
|
|
197
|
+
"",
|
|
198
|
+
"Capture stable collaboration preferences, operating boundaries, and repo-specific human expectations so agents can work with less ambiguity.",
|
|
199
|
+
"",
|
|
200
|
+
"# Scope",
|
|
201
|
+
"",
|
|
202
|
+
"Applies to planning, implementation, review, release, and handoff interactions in this repository.",
|
|
203
|
+
"",
|
|
204
|
+
"# Compatibility",
|
|
205
|
+
"",
|
|
206
|
+
"`COLLABORATION.md` is canonical. `HUMAN.md` remains a one-release legacy alias for repos and agent prompts that still reference it; read `COLLABORATION.md` first and then use `HUMAN.md` only for compatibility notes not yet migrated.",
|
|
207
|
+
"",
|
|
208
|
+
"# Requirements",
|
|
209
|
+
"",
|
|
210
|
+
"- Keep top goals, boundaries, and style preferences current.",
|
|
211
|
+
"- Include ask-before-doing constraints for risky or high-impact actions.",
|
|
212
|
+
"- Record preferred environment assumptions and validation commands.",
|
|
213
|
+
"- Preserve local operator customizations during `mdkg upgrade --apply`.",
|
|
214
|
+
"",
|
|
215
|
+
"# Notes",
|
|
216
|
+
"",
|
|
217
|
+
"Suggested prompts:",
|
|
218
|
+
"- What are your top 3 goals in this repo right now?",
|
|
219
|
+
"- What should never happen without confirmation?",
|
|
220
|
+
"- What coding/review style should the agent prefer?",
|
|
221
|
+
"- What OS/runtime/test commands should be assumed?",
|
|
222
|
+
"",
|
|
223
|
+
].join("\n");
|
|
224
|
+
}
|
|
178
225
|
function seededInitEvent(nowIso) {
|
|
179
226
|
const event = {
|
|
180
227
|
ts: nowIso,
|
|
@@ -277,6 +324,31 @@ function ensureCorePins(coreListPath, requiredPins) {
|
|
|
277
324
|
fs_1.default.mkdirSync(path_1.default.dirname(coreListPath), { recursive: true });
|
|
278
325
|
fs_1.default.writeFileSync(coreListPath, output, "utf8");
|
|
279
326
|
}
|
|
327
|
+
function refreshManifestHash(root, manifest, relPath) {
|
|
328
|
+
const entry = manifest.files.find((file) => file.path === relPath);
|
|
329
|
+
if (!entry) {
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
const targetPath = path_1.default.join(root, relPath);
|
|
333
|
+
if (fs_1.default.existsSync(targetPath) && fs_1.default.statSync(targetPath).isFile()) {
|
|
334
|
+
entry.sha256 = (0, init_manifest_1.sha256File)(targetPath);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
function ensureCreatedCoreManifestEntry(root, manifest, relPath, stats) {
|
|
338
|
+
if (manifest.files.some((file) => file.path === relPath) || !stats.createdPaths.includes(relPath)) {
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
const targetPath = path_1.default.join(root, relPath);
|
|
342
|
+
if (!fs_1.default.existsSync(targetPath) || !fs_1.default.statSync(targetPath).isFile()) {
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
manifest.files.push({
|
|
346
|
+
path: relPath,
|
|
347
|
+
category: "core",
|
|
348
|
+
sha256: (0, init_manifest_1.sha256File)(targetPath),
|
|
349
|
+
});
|
|
350
|
+
manifest.files.sort((a, b) => a.path.localeCompare(b.path));
|
|
351
|
+
}
|
|
280
352
|
function runInitCommand(options) {
|
|
281
353
|
const root = path_1.default.resolve(options.root);
|
|
282
354
|
const seedRoot = options.seedRoot ? path_1.default.resolve(options.seedRoot) : DEFAULT_SEED_SUBDIR;
|
|
@@ -295,6 +367,7 @@ function runInitCommand(options) {
|
|
|
295
367
|
const seedReadme = path_1.default.join(seedRoot, "README.md");
|
|
296
368
|
const seedDefaultSkills = path_1.default.join(seedRoot, "skills", "default");
|
|
297
369
|
const seedSoul = path_1.default.join(seedCore, "SOUL.md");
|
|
370
|
+
const seedCollaboration = path_1.default.join(seedCore, "COLLABORATION.md");
|
|
298
371
|
const seedHuman = path_1.default.join(seedCore, "HUMAN.md");
|
|
299
372
|
const seedManifest = (0, init_manifest_1.createInitManifest)(seedRoot, (0, version_1.readPackageVersion)(), {
|
|
300
373
|
includeAgentDocs: Boolean(options.agent),
|
|
@@ -367,6 +440,7 @@ function runInitCommand(options) {
|
|
|
367
440
|
if (options.agent) {
|
|
368
441
|
const today = (0, date_1.formatDate)(new Date());
|
|
369
442
|
const soulPath = path_1.default.join(mdkgDir, "core", "SOUL.md");
|
|
443
|
+
const collaborationPath = path_1.default.join(mdkgDir, "core", "COLLABORATION.md");
|
|
370
444
|
const humanPath = path_1.default.join(mdkgDir, "core", "HUMAN.md");
|
|
371
445
|
const skillsDir = path_1.default.join(mdkgDir, "skills");
|
|
372
446
|
const registryPath = path_1.default.join(skillsDir, "registry.md");
|
|
@@ -378,6 +452,9 @@ function runInitCommand(options) {
|
|
|
378
452
|
if (!fs_1.default.existsSync(seedSoul)) {
|
|
379
453
|
writeFileIfMissing(root, soulPath, soulTemplate(today), force, stats);
|
|
380
454
|
}
|
|
455
|
+
if (!fs_1.default.existsSync(seedCollaboration)) {
|
|
456
|
+
writeFileIfMissing(root, collaborationPath, collaborationTemplate(today), force, stats);
|
|
457
|
+
}
|
|
381
458
|
if (!fs_1.default.existsSync(seedHuman)) {
|
|
382
459
|
writeFileIfMissing(root, humanPath, humanTemplate(today), force, stats);
|
|
383
460
|
}
|
|
@@ -386,9 +463,13 @@ function runInitCommand(options) {
|
|
|
386
463
|
writeFileIfMissing(root, eventsPath, seededInitEvent(new Date().toISOString()), force, stats);
|
|
387
464
|
}
|
|
388
465
|
const coreListPath = path_1.default.join(mdkgDir, "core", "core.md");
|
|
389
|
-
ensureCorePins(coreListPath, [SOUL_PIN_ID, HUMAN_PIN_ID]);
|
|
390
|
-
(
|
|
466
|
+
ensureCorePins(coreListPath, [SOUL_PIN_ID, COLLABORATION_PIN_ID, HUMAN_PIN_ID]);
|
|
467
|
+
refreshManifestHash(root, seedManifest, ".mdkg/core/core.md");
|
|
468
|
+
ensureCreatedCoreManifestEntry(root, seedManifest, ".mdkg/core/SOUL.md", stats);
|
|
469
|
+
ensureCreatedCoreManifestEntry(root, seedManifest, ".mdkg/core/COLLABORATION.md", stats);
|
|
470
|
+
ensureCreatedCoreManifestEntry(root, seedManifest, ".mdkg/core/HUMAN.md", stats);
|
|
391
471
|
const config = (0, config_1.loadConfig)(root);
|
|
472
|
+
(0, skill_mirror_1.scaffoldMirrorRoots)(root, config);
|
|
392
473
|
(0, skill_support_1.refreshSkillsRegistry)(root, config);
|
|
393
474
|
stats.registryRefreshed = true;
|
|
394
475
|
const mirrorResult = (0, skill_mirror_1.syncSkillMirrors)({ root, config, createRoots: true, force });
|
|
@@ -452,7 +533,7 @@ function runInitCommand(options) {
|
|
|
452
533
|
}
|
|
453
534
|
if (options.agent) {
|
|
454
535
|
console.log("agent bootstrap: AGENT_START.md, AGENTS.md, CLAUDE.md, llms.txt, CLI_COMMAND_MATRIX.md");
|
|
455
|
-
console.log("agent core pins: rule-soul, rule-human");
|
|
536
|
+
console.log("agent core pins: rule-soul, rule-7, rule-human");
|
|
456
537
|
console.log("agent event log: .mdkg/work/events/events.jsonl");
|
|
457
538
|
console.log(`skill mirrors: ${stats.mirroredSkills} sync operation(s) across ${stats.mirrorTargets} target(s)`);
|
|
458
539
|
if (stats.registryRefreshed) {
|
package/dist/commands/skill.js
CHANGED
|
@@ -186,7 +186,7 @@ function runSkillNewCommandLocked(options) {
|
|
|
186
186
|
(0, atomic_1.atomicWriteFile)(canonicalPath, content);
|
|
187
187
|
(0, skill_support_1.ensureSkillsRegistry)(root, config);
|
|
188
188
|
(0, skill_support_1.refreshSkillsRegistry)(root, config);
|
|
189
|
-
if ((0, skill_mirror_1.shouldMaintainSkillMirrors)(root)) {
|
|
189
|
+
if ((0, skill_mirror_1.shouldMaintainSkillMirrors)(root, config)) {
|
|
190
190
|
(0, skill_mirror_1.syncSkillMirrors)({ root, config, createRoots: true, force });
|
|
191
191
|
}
|
|
192
192
|
if (config.index.auto_reindex) {
|
|
@@ -3,6 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.configuredSkillMirrorTargets = configuredSkillMirrorTargets;
|
|
6
7
|
exports.syncSkillMirrors = syncSkillMirrors;
|
|
7
8
|
exports.preflightSkillMirrorTargets = preflightSkillMirrorTargets;
|
|
8
9
|
exports.shouldMaintainSkillMirrors = shouldMaintainSkillMirrors;
|
|
@@ -10,22 +11,26 @@ exports.auditSkillMirrors = auditSkillMirrors;
|
|
|
10
11
|
exports.scaffoldMirrorRoots = scaffoldMirrorRoots;
|
|
11
12
|
const fs_1 = __importDefault(require("fs"));
|
|
12
13
|
const path_1 = __importDefault(require("path"));
|
|
14
|
+
const config_1 = require("../core/config");
|
|
13
15
|
const skills_indexer_1 = require("../graph/skills_indexer");
|
|
14
16
|
const errors_1 = require("../util/errors");
|
|
15
|
-
const MIRROR_PRODUCTS = ["agents", "claude"];
|
|
16
17
|
const MANIFEST_FILE = ".mdkg-managed.json";
|
|
17
18
|
const MANAGED_ROOT_MARKERS = [
|
|
18
19
|
path_1.default.join(".mdkg", "core", "SOUL.md"),
|
|
20
|
+
path_1.default.join(".mdkg", "core", "COLLABORATION.md"),
|
|
19
21
|
path_1.default.join(".mdkg", "core", "HUMAN.md"),
|
|
20
22
|
];
|
|
21
23
|
const ALLOWED_ROOT_ENTRIES = ["SKILL.md", "references", "assets", "scripts"];
|
|
22
|
-
function
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
function configuredSkillMirrorTargets(config) {
|
|
25
|
+
const configured = config?.customization.skill_mirrors.targets ?? (0, config_1.defaultCustomizationConfig)().skill_mirrors.targets;
|
|
26
|
+
return Array.from(new Set(configured.map((value) => value.trim()).filter(Boolean)));
|
|
27
|
+
}
|
|
28
|
+
function resolveMirrorTargets(root, config) {
|
|
29
|
+
return configuredSkillMirrorTargets(config).map((configuredPath) => {
|
|
30
|
+
const skillsRoot = path_1.default.join(root, configuredPath);
|
|
26
31
|
return {
|
|
27
|
-
|
|
28
|
-
rootDir,
|
|
32
|
+
configuredPath,
|
|
33
|
+
rootDir: path_1.default.dirname(skillsRoot),
|
|
29
34
|
skillsRoot,
|
|
30
35
|
manifestPath: path_1.default.join(skillsRoot, MANIFEST_FILE),
|
|
31
36
|
};
|
|
@@ -55,11 +60,11 @@ function writeManifest(target, managed) {
|
|
|
55
60
|
fs_1.default.mkdirSync(target.skillsRoot, { recursive: true });
|
|
56
61
|
fs_1.default.writeFileSync(target.manifestPath, `${JSON.stringify(payload, null, 2)}\n`, "utf8");
|
|
57
62
|
}
|
|
58
|
-
function shouldCreateMirrorRoots(root) {
|
|
63
|
+
function shouldCreateMirrorRoots(root, config) {
|
|
59
64
|
if (MANAGED_ROOT_MARKERS.some((relPath) => fs_1.default.existsSync(path_1.default.join(root, relPath)))) {
|
|
60
65
|
return true;
|
|
61
66
|
}
|
|
62
|
-
return resolveMirrorTargets(root).some((target) => fs_1.default.existsSync(target.rootDir) || fs_1.default.existsSync(target.skillsRoot));
|
|
67
|
+
return resolveMirrorTargets(root, config).some((target) => fs_1.default.existsSync(target.rootDir) || fs_1.default.existsSync(target.skillsRoot));
|
|
63
68
|
}
|
|
64
69
|
function listAllowedEntries(dirPath) {
|
|
65
70
|
if (!fs_1.default.existsSync(dirPath)) {
|
|
@@ -235,7 +240,7 @@ function syncSkillMirrors(options) {
|
|
|
235
240
|
const sources = loadCanonicalSources(options.root, options.config);
|
|
236
241
|
const createRoots = Boolean(options.createRoots);
|
|
237
242
|
const force = Boolean(options.force);
|
|
238
|
-
const targets = resolveMirrorTargets(options.root);
|
|
243
|
+
const targets = resolveMirrorTargets(options.root, options.config);
|
|
239
244
|
let synced = 0;
|
|
240
245
|
let pruned = 0;
|
|
241
246
|
let touchedTargets = 0;
|
|
@@ -280,7 +285,7 @@ function preflightSkillMirrorTargets(options) {
|
|
|
280
285
|
if (slugs.length === 0) {
|
|
281
286
|
return;
|
|
282
287
|
}
|
|
283
|
-
for (const target of resolveMirrorTargets(options.root)) {
|
|
288
|
+
for (const target of resolveMirrorTargets(options.root, options.config)) {
|
|
284
289
|
if (!fs_1.default.existsSync(target.rootDir) && !fs_1.default.existsSync(target.skillsRoot)) {
|
|
285
290
|
continue;
|
|
286
291
|
}
|
|
@@ -293,18 +298,18 @@ function preflightSkillMirrorTargets(options) {
|
|
|
293
298
|
}
|
|
294
299
|
}
|
|
295
300
|
}
|
|
296
|
-
function shouldMaintainSkillMirrors(root) {
|
|
297
|
-
return shouldCreateMirrorRoots(root);
|
|
301
|
+
function shouldMaintainSkillMirrors(root, config) {
|
|
302
|
+
return shouldCreateMirrorRoots(root, config);
|
|
298
303
|
}
|
|
299
304
|
function auditSkillMirrors(root, config) {
|
|
300
|
-
const shouldAudit = shouldCreateMirrorRoots(root);
|
|
305
|
+
const shouldAudit = shouldCreateMirrorRoots(root, config);
|
|
301
306
|
if (!shouldAudit) {
|
|
302
307
|
return [];
|
|
303
308
|
}
|
|
304
309
|
const warnings = [];
|
|
305
310
|
const sources = loadCanonicalSources(root, config);
|
|
306
311
|
const sourceBySlug = new Map(sources.map((source) => [source.slug, source]));
|
|
307
|
-
for (const target of resolveMirrorTargets(root)) {
|
|
312
|
+
for (const target of resolveMirrorTargets(root, config)) {
|
|
308
313
|
if (!fs_1.default.existsSync(target.skillsRoot)) {
|
|
309
314
|
warnings.push(`${path_1.default.relative(root, target.skillsRoot)}: mirror root missing; run \`mdkg skill sync\``);
|
|
310
315
|
continue;
|
|
@@ -335,8 +340,8 @@ function auditSkillMirrors(root, config) {
|
|
|
335
340
|
}
|
|
336
341
|
return warnings;
|
|
337
342
|
}
|
|
338
|
-
function scaffoldMirrorRoots(root) {
|
|
339
|
-
for (const target of resolveMirrorTargets(root)) {
|
|
343
|
+
function scaffoldMirrorRoots(root, config) {
|
|
344
|
+
for (const target of resolveMirrorTargets(root, config)) {
|
|
340
345
|
fs_1.default.mkdirSync(target.skillsRoot, { recursive: true });
|
|
341
346
|
if (!fs_1.default.existsSync(target.manifestPath)) {
|
|
342
347
|
writeManifest(target, []);
|
|
@@ -52,7 +52,7 @@ function registryTemplate() {
|
|
|
52
52
|
"This directory stores Agent Skills packages used by mdkg tooling and orchestrators.",
|
|
53
53
|
"",
|
|
54
54
|
"Use `mdkg skill new <slug> \"<name>\" --description \"...\"` to scaffold a new skill from the built-in Anthropic-aligned template.",
|
|
55
|
-
"Use `mdkg skill sync` to mirror canonical skills into `.agents/skills/` and `.claude/skills
|
|
55
|
+
"Use `mdkg skill sync` to mirror canonical skills into configured `.mdkg/config.json` targets; defaults are `.agents/skills/` and `.claude/skills/`.",
|
|
56
56
|
"Use `CLI_COMMAND_MATRIX.md` as the canonical command and flag reference when updating skill procedures.",
|
|
57
57
|
"",
|
|
58
58
|
"## Conventions",
|
package/dist/commands/upgrade.js
CHANGED
|
@@ -21,7 +21,7 @@ const init_manifest_1 = require("./init_manifest");
|
|
|
21
21
|
const skill_support_1 = require("./skill_support");
|
|
22
22
|
const skill_mirror_1 = require("./skill_mirror");
|
|
23
23
|
const DEFAULT_SEED_SUBDIR = path_1.default.resolve(__dirname, "..", "init");
|
|
24
|
-
const PROTECTED_CORE_DOCS = new Set([".mdkg/core/SOUL.md", ".mdkg/core/HUMAN.md"]);
|
|
24
|
+
const PROTECTED_CORE_DOCS = new Set([".mdkg/core/SOUL.md", ".mdkg/core/COLLABORATION.md", ".mdkg/core/HUMAN.md"]);
|
|
25
25
|
const CREATE_ONLY_PRESERVED = new Set([".mdkg/core/core.md"]);
|
|
26
26
|
const LOCAL_STATE_IGNORE_ENTRIES = [
|
|
27
27
|
".mdkg/state/",
|
|
@@ -51,12 +51,11 @@ function requireSeedAssets(seedRoot) {
|
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
|
-
function isAgentWorkspace(root) {
|
|
54
|
+
function isAgentWorkspace(root, config) {
|
|
55
55
|
return [
|
|
56
56
|
path_1.default.join(root, ".mdkg", "skills"),
|
|
57
|
-
path_1.default.join(root, ".agents", "skills"),
|
|
58
|
-
path_1.default.join(root, ".claude", "skills"),
|
|
59
57
|
path_1.default.join(root, ".mdkg", "work", "events", "events.jsonl"),
|
|
58
|
+
...(0, skill_mirror_1.configuredSkillMirrorTargets)(config).map((target) => path_1.default.join(root, target)),
|
|
60
59
|
].some((candidate) => fs_1.default.existsSync(candidate));
|
|
61
60
|
}
|
|
62
61
|
function copyFile(src, dest) {
|
|
@@ -157,15 +156,6 @@ function planSeedFile(options) {
|
|
|
157
156
|
options.summary.unchanged += 1;
|
|
158
157
|
return false;
|
|
159
158
|
}
|
|
160
|
-
if (PROTECTED_CORE_DOCS.has(options.file.path)) {
|
|
161
|
-
record(options.summary, options.changes, {
|
|
162
|
-
path: options.file.path,
|
|
163
|
-
category: options.file.category,
|
|
164
|
-
action: "conflict",
|
|
165
|
-
reason: "protected core document exists; local content preserved",
|
|
166
|
-
});
|
|
167
|
-
return false;
|
|
168
|
-
}
|
|
169
159
|
const known = options.knownHashes.get(options.file.path);
|
|
170
160
|
if (known?.has(currentHash)) {
|
|
171
161
|
record(options.summary, options.changes, {
|
|
@@ -180,6 +170,15 @@ function planSeedFile(options) {
|
|
|
180
170
|
options.managedCurrentFiles.push(options.file);
|
|
181
171
|
return true;
|
|
182
172
|
}
|
|
173
|
+
if (PROTECTED_CORE_DOCS.has(options.file.path)) {
|
|
174
|
+
record(options.summary, options.changes, {
|
|
175
|
+
path: options.file.path,
|
|
176
|
+
category: options.file.category,
|
|
177
|
+
action: "conflict",
|
|
178
|
+
reason: "protected core document exists; local content preserved",
|
|
179
|
+
});
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
183
182
|
record(options.summary, options.changes, {
|
|
184
183
|
path: options.file.path,
|
|
185
184
|
category: options.file.category,
|
|
@@ -253,14 +252,26 @@ function migrateProjectDbConfig(input) {
|
|
|
253
252
|
};
|
|
254
253
|
return { config: raw, changed: true };
|
|
255
254
|
}
|
|
255
|
+
function migrateCustomizationConfig(input) {
|
|
256
|
+
if (typeof input !== "object" || input === null || Array.isArray(input)) {
|
|
257
|
+
return { config: input, changed: false };
|
|
258
|
+
}
|
|
259
|
+
const raw = { ...input };
|
|
260
|
+
if (raw.customization !== undefined) {
|
|
261
|
+
return { config: raw, changed: false };
|
|
262
|
+
}
|
|
263
|
+
raw.customization = (0, config_1.defaultCustomizationConfig)();
|
|
264
|
+
return { config: raw, changed: true };
|
|
265
|
+
}
|
|
256
266
|
function migrateConfigIfNeeded(root, dryRun, summary, changes) {
|
|
257
267
|
const cfgPath = (0, paths_1.configPath)(root);
|
|
258
268
|
const raw = JSON.parse(fs_1.default.readFileSync(cfgPath, "utf8"));
|
|
259
269
|
const migrated = (0, migrate_1.migrateConfig)(raw);
|
|
260
270
|
const bundleConfig = migrateLegacyBundleImportsConfig(migrated.config);
|
|
261
271
|
const nextConfig = migrateProjectDbConfig(bundleConfig.config);
|
|
262
|
-
|
|
263
|
-
|
|
272
|
+
const customizationConfig = migrateCustomizationConfig(nextConfig.config);
|
|
273
|
+
(0, config_1.validateConfigSchema)(customizationConfig.config);
|
|
274
|
+
if (migrated.from === migrated.to && !bundleConfig.changed && !nextConfig.changed && !customizationConfig.changed) {
|
|
264
275
|
summary.unchanged += 1;
|
|
265
276
|
return;
|
|
266
277
|
}
|
|
@@ -271,6 +282,9 @@ function migrateConfigIfNeeded(root, dryRun, summary, changes) {
|
|
|
271
282
|
if (nextConfig.changed) {
|
|
272
283
|
reasons.push("project db config defaults");
|
|
273
284
|
}
|
|
285
|
+
if (customizationConfig.changed) {
|
|
286
|
+
reasons.push("customization overlay defaults");
|
|
287
|
+
}
|
|
274
288
|
if (migrated.from !== migrated.to) {
|
|
275
289
|
reasons.push(`schema_version ${migrated.from} -> ${migrated.to}`);
|
|
276
290
|
}
|
|
@@ -281,9 +295,32 @@ function migrateConfigIfNeeded(root, dryRun, summary, changes) {
|
|
|
281
295
|
reason: reasons.join(" and "),
|
|
282
296
|
});
|
|
283
297
|
if (!dryRun) {
|
|
284
|
-
writeFile(cfgPath, `${JSON.stringify(
|
|
298
|
+
writeFile(cfgPath, `${JSON.stringify(customizationConfig.config, null, 2)}\n`);
|
|
285
299
|
}
|
|
286
300
|
}
|
|
301
|
+
function sameStringArray(left, right) {
|
|
302
|
+
return left.length === right.length && left.every((value, index) => value === right[index]);
|
|
303
|
+
}
|
|
304
|
+
function hasOperatorCustomization(customization) {
|
|
305
|
+
const defaults = (0, config_1.defaultCustomizationConfig)();
|
|
306
|
+
return (customization.standards.profile !== defaults.standards.profile ||
|
|
307
|
+
customization.standards.refs.length > 0 ||
|
|
308
|
+
customization.core_docs.custom_paths.length > 0 ||
|
|
309
|
+
!sameStringArray(customization.skill_mirrors.targets, defaults.skill_mirrors.targets));
|
|
310
|
+
}
|
|
311
|
+
function reportPreservedCustomizationOverlay(root, summary, changes) {
|
|
312
|
+
const config = (0, config_1.validateConfigSchema)((0, migrate_1.migrateConfig)(JSON.parse(fs_1.default.readFileSync((0, paths_1.configPath)(root), "utf8"))).config);
|
|
313
|
+
if (!hasOperatorCustomization(config.customization)) {
|
|
314
|
+
summary.unchanged += 1;
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
record(summary, changes, {
|
|
318
|
+
path: ".mdkg/config.json",
|
|
319
|
+
category: "customization_overlay",
|
|
320
|
+
action: "skip",
|
|
321
|
+
reason: "operator customization overlay is preserved; upgrade does not replace organization standards, custom core docs, or configured skill mirror targets",
|
|
322
|
+
});
|
|
323
|
+
}
|
|
287
324
|
function migrateClosedGoalActiveNodes(root, dryRun, summary, changes) {
|
|
288
325
|
const config = (0, config_1.validateConfigSchema)((0, migrate_1.migrateConfig)(JSON.parse(fs_1.default.readFileSync((0, paths_1.configPath)(root), "utf8"))).config);
|
|
289
326
|
const filesByAlias = (0, workspace_files_1.listWorkspaceDocFilesByAlias)(root, config);
|
|
@@ -503,12 +540,15 @@ function buildApplySideEffects(options) {
|
|
|
503
540
|
category: "skill_registry",
|
|
504
541
|
action: "update",
|
|
505
542
|
reason: "refreshes canonical skill registry after apply",
|
|
506
|
-
}, {
|
|
507
|
-
path: ".agents/skills,.claude/skills",
|
|
508
|
-
category: "skill_mirror",
|
|
509
|
-
action: "sync",
|
|
510
|
-
reason: "syncs managed skill mirrors after apply",
|
|
511
543
|
});
|
|
544
|
+
if (options.mirrorTargets.length > 0) {
|
|
545
|
+
effects.push({
|
|
546
|
+
path: options.mirrorTargets.join(","),
|
|
547
|
+
category: "skill_mirror",
|
|
548
|
+
action: "sync",
|
|
549
|
+
reason: "syncs configured managed skill mirrors after apply",
|
|
550
|
+
});
|
|
551
|
+
}
|
|
512
552
|
}
|
|
513
553
|
return effects;
|
|
514
554
|
}
|
|
@@ -560,9 +600,11 @@ function runUpgradeCommand(options) {
|
|
|
560
600
|
const knownHashes = buildKnownHashes([existingManifest, ...legacyManifests]);
|
|
561
601
|
const summary = createSummary();
|
|
562
602
|
const changes = [];
|
|
563
|
-
const
|
|
603
|
+
const initialConfig = (0, config_1.validateConfigSchema)((0, migrate_1.migrateConfig)(JSON.parse(fs_1.default.readFileSync((0, paths_1.configPath)(root), "utf8"))).config);
|
|
604
|
+
const agentWorkspace = isAgentWorkspace(root, initialConfig);
|
|
564
605
|
const managedCurrentFiles = [];
|
|
565
606
|
migrateConfigIfNeeded(root, dryRun, summary, changes);
|
|
607
|
+
reportPreservedCustomizationOverlay(root, summary, changes);
|
|
566
608
|
migrateClosedGoalActiveNodes(root, dryRun, summary, changes);
|
|
567
609
|
migrateLegacySpecManifests(root, dryRun, summary, changes);
|
|
568
610
|
for (const file of currentManifest.files) {
|
|
@@ -587,6 +629,7 @@ function runUpgradeCommand(options) {
|
|
|
587
629
|
const applySideEffects = buildApplySideEffects({
|
|
588
630
|
existingManifest,
|
|
589
631
|
agentWorkspace,
|
|
632
|
+
mirrorTargets: (0, skill_mirror_1.configuredSkillMirrorTargets)(initialConfig),
|
|
590
633
|
changes,
|
|
591
634
|
});
|
|
592
635
|
for (const effect of applySideEffects) {
|
|
@@ -603,11 +646,11 @@ function runUpgradeCommand(options) {
|
|
|
603
646
|
if (agentWorkspace && applySideEffects.length > 0) {
|
|
604
647
|
const config = (0, config_1.validateConfigSchema)((0, migrate_1.migrateConfig)(JSON.parse(fs_1.default.readFileSync((0, paths_1.configPath)(root), "utf8"))).config);
|
|
605
648
|
(0, skill_support_1.refreshSkillsRegistry)(root, config);
|
|
606
|
-
(0, skill_mirror_1.scaffoldMirrorRoots)(root);
|
|
649
|
+
(0, skill_mirror_1.scaffoldMirrorRoots)(root, config);
|
|
607
650
|
(0, skill_mirror_1.syncSkillMirrors)({ root, config, createRoots: true });
|
|
608
651
|
}
|
|
609
652
|
}
|
|
610
|
-
const preservedCustomizations = changes.filter((change) => change.action === "conflict");
|
|
653
|
+
const preservedCustomizations = changes.filter((change) => change.action === "conflict" || change.category === "customization_overlay");
|
|
611
654
|
const blockingConflicts = changes.filter((change) => change.action === "conflict" && change.category === "manifest_migration");
|
|
612
655
|
const willWritePaths = changes.filter(isWritableChange).map(writablePathForChange);
|
|
613
656
|
const receipt = {
|