mdkg 0.0.5 → 0.0.7

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/README.md CHANGED
@@ -13,7 +13,7 @@ mdkg stays deliberately boring:
13
13
  - zero runtime dependencies
14
14
  - no sqlite, daemon, hosted index, or vector DB
15
15
 
16
- Current package version in source: `0.0.5`
16
+ Current package version in source: `0.0.6`
17
17
 
18
18
  ## The product shape
19
19
 
@@ -49,7 +49,7 @@ Initialize mdkg in a repo:
49
49
  mdkg init --llm
50
50
  ```
51
51
 
52
- This is the generic OSS bootstrap path. It creates `.mdkg/` and updates `.gitignore` / `.npmignore` by default. Use `--no-update-ignores` to opt out.
52
+ This is the generic OSS bootstrap path. It creates `.mdkg/` and updates `.gitignore` / `.npmignore` by default. Use `--no-update-ignores` to opt out of those ignore-file updates.
53
53
 
54
54
  Optional agent-ready scaffold:
55
55
 
@@ -57,7 +57,7 @@ Optional agent-ready scaffold:
57
57
  mdkg init --agent
58
58
  ```
59
59
 
60
- This adds strict-node `SOUL.md` / `HUMAN.md`, a skills scaffold, seeded events JSONL, core pin updates, and mirrored skill folders under `.agents/skills/` and `.claude/skills/`.
60
+ This adds strict-node `SOUL.md` / `HUMAN.md`, seeds the three default mdkg usage skills, creates `events.jsonl`, updates the skill registry, adds core pin updates, and creates mirrored skill folders under `.agents/skills/` and `.claude/skills/`.
61
61
 
62
62
  Create a task:
63
63
 
@@ -86,7 +86,7 @@ Validate before handoff or commit:
86
86
  mdkg validate
87
87
  ```
88
88
 
89
- Mutate a task-like node without manual markdown editing:
89
+ Update structured task state and evidence while keeping body and narrative edits in markdown:
90
90
 
91
91
  ```bash
92
92
  mdkg task start task-1 --run-id run_local_1
@@ -94,7 +94,7 @@ mdkg task update task-1 --add-artifacts tests://unit.txt --add-tags release
94
94
  mdkg task done task-1 --checkpoint "release readiness milestone"
95
95
  ```
96
96
 
97
- Enable and append baseline event memory:
97
+ Ensure and append baseline event memory:
98
98
 
99
99
  ```bash
100
100
  mdkg event enable
@@ -176,10 +176,13 @@ Current source behavior:
176
176
  - `mdkg skill show <slug>`
177
177
  - `mdkg skill validate [<slug>]`
178
178
  - `mdkg skill sync`
179
- - machine-readable skill discovery is available through:
179
+ - machine-readable skill discovery and inspection is available through:
180
180
  - `mdkg skill list --json`
181
181
  - `mdkg skill search "<query>" --json`
182
182
  - `mdkg skill show <slug> --json`
183
+ - `mdkg skill list --xml|--toon|--md`
184
+ - `mdkg skill search "<query>" --xml|--toon|--md`
185
+ - `mdkg skill show <slug> --xml|--toon|--md`
183
186
  - work items may reference `skills: [slug,...]`
184
187
  - packs may include skills with `--skills` and `--skills-depth`
185
188
  - mdkg indexes and discovers skills but does not execute skill scripts
@@ -200,12 +203,14 @@ This repo now dogfoods three internal skills:
200
203
 
201
204
  This release includes:
202
205
  - `init --agent`
203
- - default ignore updates with `--no-update-ignores`
206
+ - default ignore updates with `--no-update-ignores` for `.mdkg/index/` and `.mdkg/pack/`
207
+ - root-only published init seed config
204
208
  - skills indexing and search/show/list support
205
209
  - optional `skills: [...]` on work items
206
210
  - pack-time skill inclusion
207
211
  - latest-checkpoint resolver + index hint
208
212
  - events JSONL validation
213
+ - XML / TOON / Markdown output for node and skill list/search/show
209
214
  - product-specific skill mirrors for Codex/OpenAI and Claude
210
215
  - shared `AGENT_START.md` startup guidance
211
216
 
@@ -213,7 +218,8 @@ Current direction:
213
218
  - keep the OSS story generic around `init --llm`
214
219
  - use `init --agent` for deeper AI-agent bootstrap
215
220
  - keep `pack <id>` at the center of the human/agent loop
216
- - make task mutation and event logging guided instead of purely manual
221
+ - use `mdkg task ...` for structured state changes and markdown edits for narrative/body content
222
+ - make event logging guided instead of purely manual
217
223
  - dogfood real skills inside the repo
218
224
  - make skill authoring first-class through `mdkg skill`
219
225
  - make `CLI_COMMAND_MATRIX.md` the single source of truth for the live CLI surface
@@ -228,7 +234,7 @@ mdkg is not a secret store.
228
234
  Use these defaults:
229
235
  - keep `.mdkg/index/` gitignored
230
236
  - keep `.mdkg/pack/` gitignored
231
- - keep `.mdkg/work/events/*.jsonl` gitignored unless you deliberately opt in
237
+ - event logs are committed by default; ignore or delete them manually if a repo wants local-only provenance
232
238
  - do not ship `.mdkg/` into production builds or published packages
233
239
  - if an external orchestrator is writing mdkg state, keep one durable writer per run and batch commits at end-of-run or checkpoint boundaries
234
240
  - do not commit on every tool call
@@ -245,7 +251,7 @@ Suggested local loop:
245
251
  2. inspect truth with `search`, `show`, or `next`
246
252
  3. build context with `pack <id>`
247
253
  4. mutate task state with `mdkg task ...` when durable state changes
248
- 5. enable event logging if provenance should be captured in JSONL
254
+ 5. ensure event logging exists if the JSONL file was deleted or is missing
249
255
  6. implement and test
250
256
  7. run `mdkg validate`
251
257
 
package/dist/cli.js CHANGED
@@ -134,7 +134,7 @@ function printIndexHelp(log) {
134
134
  }
135
135
  function printShowHelp(log) {
136
136
  log("Usage:");
137
- log(" mdkg show <id-or-qid> [--ws <alias>] [--meta] [--json]");
137
+ log(" mdkg show <id-or-qid> [--ws <alias>] [--meta] [--json|--xml|--toon|--md]");
138
138
  log("\nWhen to use:");
139
139
  log(" Inspect one mdkg node exactly. Use `mdkg skill show <slug>` for skills.");
140
140
  log("\nDefault behavior:");
@@ -144,7 +144,8 @@ function printShowHelp(log) {
144
144
  function printListHelp(log) {
145
145
  log("Usage:");
146
146
  log(" mdkg list [--type <type>] [--status <status>] [--ws <alias>] [--epic <id>]");
147
- log(" [--priority <n>] [--blocked] [--tags <tag,tag,...>] [--tags-mode any|all] [--json]");
147
+ log(" [--priority <n>] [--blocked] [--tags <tag,tag,...>] [--tags-mode any|all]");
148
+ log(" [--json|--xml|--toon|--md]");
148
149
  log("\nWhen to use:");
149
150
  log(" List mdkg nodes. Use `mdkg skill list` for skills.");
150
151
  printGlobalOptions(log);
@@ -152,7 +153,7 @@ function printListHelp(log) {
152
153
  function printSearchHelp(log) {
153
154
  log("Usage:");
154
155
  log(' mdkg search "<query>" [--type <type>] [--status <status>] [--ws <alias>]');
155
- log(" [--tags <tag,tag,...>] [--tags-mode any|all] [--json]");
156
+ log(" [--tags <tag,tag,...>] [--tags-mode any|all] [--json|--xml|--toon|--md]");
156
157
  log("\nWhen to use:");
157
158
  log(" Search mdkg nodes by metadata. Use `mdkg skill search` for skills.");
158
159
  printGlobalOptions(log);
@@ -210,21 +211,21 @@ function printSkillHelp(log, subcommand) {
210
211
  return;
211
212
  case "list":
212
213
  log("Usage:");
213
- log(" mdkg skill list [--tags <tag,tag,...>] [--tags-mode any|all] [--json]");
214
+ log(" mdkg skill list [--tags <tag,tag,...>] [--tags-mode any|all] [--json|--xml|--toon|--md]");
214
215
  log("\nWhen to use:");
215
216
  log(" Discover skills directly, including stage-tagged orchestrator lookups.");
216
217
  printGlobalOptions(log);
217
218
  return;
218
219
  case "show":
219
220
  log("Usage:");
220
- log(" mdkg skill show <slug> [--meta] [--json]");
221
+ log(" mdkg skill show <slug> [--meta] [--json|--xml|--toon|--md]");
221
222
  log("\nWhen to use:");
222
223
  log(" Inspect one skill body or metadata after discovery.");
223
224
  printGlobalOptions(log);
224
225
  return;
225
226
  case "search":
226
227
  log("Usage:");
227
- log(' mdkg skill search "<query>" [--tags <tag,tag,...>] [--tags-mode any|all] [--json]');
228
+ log(' mdkg skill search "<query>" [--tags <tag,tag,...>] [--tags-mode any|all] [--json|--xml|--toon|--md]');
228
229
  log("\nWhen to use:");
229
230
  log(" Search skills by trigger text, tags, and stage conventions like `stage:plan`.");
230
231
  printGlobalOptions(log);
@@ -244,9 +245,9 @@ function printSkillHelp(log, subcommand) {
244
245
  default:
245
246
  log("Usage:");
246
247
  log(' mdkg skill new <slug> "<name>" --description "<description>" [options]');
247
- log(" mdkg skill list [--tags <tag,tag,...>] [--tags-mode any|all] [--json]");
248
- log(" mdkg skill show <slug> [--meta] [--json]");
249
- log(' mdkg skill search "<query>" [--tags <tag,tag,...>] [--tags-mode any|all] [--json]');
248
+ log(" mdkg skill list [--tags <tag,tag,...>] [--tags-mode any|all] [--json|--xml|--toon|--md]");
249
+ log(" mdkg skill show <slug> [--meta] [--json|--xml|--toon|--md]");
250
+ log(' mdkg skill search "<query>" [--tags <tag,tag,...>] [--tags-mode any|all] [--json|--xml|--toon|--md]');
250
251
  log(" mdkg skill validate [<slug>]");
251
252
  log(" mdkg skill sync [--force]");
252
253
  log("\nNotes:");
@@ -261,8 +262,8 @@ function printTaskHelp(log, subcommand) {
261
262
  log("Usage:");
262
263
  log(' mdkg task start <id-or-qid> [--ws <alias>] [--run-id <id>] [--note "<text>"]');
263
264
  log("\nWhen to use:");
264
- log(" Move a task, bug, or test into progress and emit a baseline event when logging is enabled.");
265
- log(" If events are disabled, mdkg prints a short reminder about `mdkg event enable`.");
265
+ log(" Move a task, bug, or test into progress as a structured state change.");
266
+ log(" If `events.jsonl` is missing, mdkg prints a short reminder about `mdkg event enable`.");
266
267
  printGlobalOptions(log);
267
268
  return;
268
269
  case "update":
@@ -272,7 +273,7 @@ function printTaskHelp(log, subcommand) {
272
273
  log(" [--add-skills <slug,...>] [--add-tags <tag,...>] [--add-blocked-by <id,...>]");
273
274
  log(' [--clear-blocked-by] [--run-id <id>] [--note "<text>"]');
274
275
  log("\nWhen to use:");
275
- log(" Update task metadata and evidence without editing markdown manually.");
276
+ log(" Update structured task metadata and evidence while keeping body and narrative edits in markdown.");
276
277
  printGlobalOptions(log);
277
278
  return;
278
279
  case "done":
@@ -299,9 +300,9 @@ function printEventHelp(log, subcommand) {
299
300
  switch ((subcommand ?? "").toLowerCase()) {
300
301
  case "enable":
301
302
  log("Usage:");
302
- log(" mdkg event enable [--ws <alias>] [--no-update-gitignore]");
303
+ log(" mdkg event enable [--ws <alias>]");
303
304
  log("\nWhen to use:");
304
- log(" Create the append-only JSONL event log for a workspace.");
305
+ log(" Create or ensure the append-only JSONL event log for a workspace.");
305
306
  printGlobalOptions(log);
306
307
  return;
307
308
  case "append":
@@ -315,7 +316,7 @@ function printEventHelp(log, subcommand) {
315
316
  return;
316
317
  default:
317
318
  log("Usage:");
318
- log(" mdkg event enable [--ws <alias>] [--no-update-gitignore]");
319
+ log(" mdkg event enable [--ws <alias>]");
319
320
  log(" mdkg event append --kind <kind> --status <ok|error|retry|skipped> --refs <id,...> [options]");
320
321
  printGlobalOptions(log);
321
322
  }
@@ -528,6 +529,25 @@ function parseTagsModeFlag(value) {
528
529
  }
529
530
  throw new errors_1.UsageError("--tags-mode must be any or all");
530
531
  }
532
+ function parseQueryOutputFormat(parsed) {
533
+ const enabled = [];
534
+ if (parseBooleanFlag("--json", parsed.flags["--json"])) {
535
+ enabled.push("json");
536
+ }
537
+ if (parseBooleanFlag("--xml", parsed.flags["--xml"])) {
538
+ enabled.push("xml");
539
+ }
540
+ if (parseBooleanFlag("--toon", parsed.flags["--toon"])) {
541
+ enabled.push("toon");
542
+ }
543
+ if (parseBooleanFlag("--md", parsed.flags["--md"])) {
544
+ enabled.push("md");
545
+ }
546
+ if (enabled.length > 1) {
547
+ throw new errors_1.UsageError("choose at most one output flag: --json, --xml, --toon, or --md");
548
+ }
549
+ return enabled[0];
550
+ }
531
551
  function handleCommandError(err, command, runtime) {
532
552
  const message = err instanceof Error ? err.message : String(err);
533
553
  if (err instanceof errors_1.UsageError) {
@@ -622,12 +642,12 @@ function runSkillSubcommand(parsed, root) {
622
642
  const tagsMode = parseTagsModeFlag(parsed.flags["--tags-mode"]);
623
643
  const noCache = parseBooleanFlag("--no-cache", parsed.flags["--no-cache"]);
624
644
  const noReindex = parseBooleanFlag("--no-reindex", parsed.flags["--no-reindex"]);
625
- const json = parseBooleanFlag("--json", parsed.flags["--json"]);
645
+ const format = parseQueryOutputFormat(parsed);
626
646
  (0, skill_1.runSkillListCommand)({
627
647
  root,
628
648
  tags,
629
649
  tagsMode,
630
- json,
650
+ format,
631
651
  noCache,
632
652
  noReindex,
633
653
  });
@@ -639,14 +659,14 @@ function runSkillSubcommand(parsed, root) {
639
659
  throw new errors_1.UsageError("skill show requires <slug>");
640
660
  }
641
661
  const metaOnly = parseBooleanFlag("--meta", parsed.flags["--meta"]);
642
- const json = parseBooleanFlag("--json", parsed.flags["--json"]);
662
+ const format = parseQueryOutputFormat(parsed);
643
663
  const noCache = parseBooleanFlag("--no-cache", parsed.flags["--no-cache"]);
644
664
  const noReindex = parseBooleanFlag("--no-reindex", parsed.flags["--no-reindex"]);
645
665
  (0, skill_1.runSkillShowCommand)({
646
666
  root,
647
667
  slug,
648
668
  metaOnly,
649
- json,
669
+ format,
650
670
  noCache,
651
671
  noReindex,
652
672
  });
@@ -659,7 +679,7 @@ function runSkillSubcommand(parsed, root) {
659
679
  const query = parsed.positionals.slice(2).join(" ");
660
680
  const tags = parseCsvFlag("--tags", parsed.flags["--tags"]);
661
681
  const tagsMode = parseTagsModeFlag(parsed.flags["--tags-mode"]);
662
- const json = parseBooleanFlag("--json", parsed.flags["--json"]);
682
+ const format = parseQueryOutputFormat(parsed);
663
683
  const noCache = parseBooleanFlag("--no-cache", parsed.flags["--no-cache"]);
664
684
  const noReindex = parseBooleanFlag("--no-reindex", parsed.flags["--no-reindex"]);
665
685
  (0, skill_1.runSkillSearchCommand)({
@@ -667,7 +687,7 @@ function runSkillSubcommand(parsed, root) {
667
687
  query,
668
688
  tags,
669
689
  tagsMode,
670
- json,
690
+ format,
671
691
  noCache,
672
692
  noReindex,
673
693
  });
@@ -779,8 +799,7 @@ function runEventSubcommand(parsed, root) {
779
799
  throw new errors_1.UsageError("event enable does not accept positional arguments");
780
800
  }
781
801
  const ws = requireFlagValue("--ws", parsed.flags["--ws"]);
782
- const noUpdateGitignore = parseBooleanFlag("--no-update-gitignore", parsed.flags["--no-update-gitignore"]);
783
- (0, event_1.runEventEnableCommand)({ root, ws, updateGitignore: !noUpdateGitignore });
802
+ (0, event_1.runEventEnableCommand)({ root, ws });
784
803
  return 0;
785
804
  }
786
805
  case "append": {
@@ -931,7 +950,7 @@ function runCommand(parsed, root, runtime) {
931
950
  }
932
951
  const ws = requireFlagValue("--ws", parsed.flags["--ws"]);
933
952
  const metaOnly = parseBooleanFlag("--meta", parsed.flags["--meta"]);
934
- const json = parseBooleanFlag("--json", parsed.flags["--json"]);
953
+ const format = parseQueryOutputFormat(parsed);
935
954
  const noCache = parseBooleanFlag("--no-cache", parsed.flags["--no-cache"]);
936
955
  const noReindex = parseBooleanFlag("--no-reindex", parsed.flags["--no-reindex"]);
937
956
  (0, show_1.runShowCommand)({
@@ -939,7 +958,7 @@ function runCommand(parsed, root, runtime) {
939
958
  id,
940
959
  ws,
941
960
  metaOnly,
942
- json,
961
+ format,
943
962
  noCache,
944
963
  noReindex,
945
964
  });
@@ -957,7 +976,7 @@ function runCommand(parsed, root, runtime) {
957
976
  const blocked = parseBooleanFlag("--blocked", parsed.flags["--blocked"]);
958
977
  const tags = parseCsvFlag("--tags", parsed.flags["--tags"]);
959
978
  const tagsMode = parseTagsModeFlag(parsed.flags["--tags-mode"]);
960
- const json = parseBooleanFlag("--json", parsed.flags["--json"]);
979
+ const format = parseQueryOutputFormat(parsed);
961
980
  const noCache = parseBooleanFlag("--no-cache", parsed.flags["--no-cache"]);
962
981
  const noReindex = parseBooleanFlag("--no-reindex", parsed.flags["--no-reindex"]);
963
982
  (0, list_1.runListCommand)({
@@ -970,7 +989,7 @@ function runCommand(parsed, root, runtime) {
970
989
  blocked,
971
990
  tags,
972
991
  tagsMode,
973
- json,
992
+ format,
974
993
  noCache,
975
994
  noReindex,
976
995
  });
@@ -986,7 +1005,7 @@ function runCommand(parsed, root, runtime) {
986
1005
  const status = requireFlagValue("--status", parsed.flags["--status"]);
987
1006
  const tags = parseCsvFlag("--tags", parsed.flags["--tags"]);
988
1007
  const tagsMode = parseTagsModeFlag(parsed.flags["--tags-mode"]);
989
- const json = parseBooleanFlag("--json", parsed.flags["--json"]);
1008
+ const format = parseQueryOutputFormat(parsed);
990
1009
  const noCache = parseBooleanFlag("--no-cache", parsed.flags["--no-cache"]);
991
1010
  const noReindex = parseBooleanFlag("--no-reindex", parsed.flags["--no-reindex"]);
992
1011
  (0, search_1.runSearchCommand)({
@@ -997,7 +1016,7 @@ function runCommand(parsed, root, runtime) {
997
1016
  status,
998
1017
  tags,
999
1018
  tagsMode,
1000
- json,
1019
+ format,
1001
1020
  noCache,
1002
1021
  noReindex,
1003
1022
  });
@@ -7,8 +7,7 @@ const errors_1 = require("../util/errors");
7
7
  function runEventEnableCommand(options) {
8
8
  const result = (0, event_support_1.ensureEventsEnabled)(options);
9
9
  const createdLabel = result.created ? "created" : "already present";
10
- const ignoreLabel = result.gitignoreUpdated ? "updated .gitignore" : "left .gitignore unchanged";
11
- console.log(`event logging enabled: ${result.ws} (${createdLabel}; ${ignoreLabel})`);
10
+ console.log(`event logging enabled: ${result.ws} (${createdLabel})`);
12
11
  }
13
12
  function normalizeEventStatus(value) {
14
13
  const normalized = value.trim().toLowerCase();
@@ -16,27 +16,6 @@ const fs_1 = __importDefault(require("fs"));
16
16
  const path_1 = __importDefault(require("path"));
17
17
  const config_1 = require("../core/config");
18
18
  const errors_1 = require("../util/errors");
19
- function appendIgnoreEntries(filePath, entries) {
20
- const normalizedEntries = entries.map((entry) => entry.trim()).filter(Boolean);
21
- if (normalizedEntries.length === 0) {
22
- return false;
23
- }
24
- let existing = "";
25
- if (fs_1.default.existsSync(filePath)) {
26
- existing = fs_1.default.readFileSync(filePath, "utf8");
27
- }
28
- const existingLines = new Set(existing
29
- .split(/\r?\n/)
30
- .map((line) => line.trim())
31
- .filter(Boolean));
32
- const additions = normalizedEntries.filter((entry) => !existingLines.has(entry));
33
- if (additions.length === 0) {
34
- return false;
35
- }
36
- const next = existing.length === 0 ? `${additions.join("\n")}\n` : `${existing.replace(/\s*$/, "\n")}${additions.join("\n")}\n`;
37
- fs_1.default.writeFileSync(filePath, next, "utf8");
38
- return true;
39
- }
40
19
  function normalizeWorkspaceForEvents(config, raw) {
41
20
  const normalized = (raw ?? "root").toLowerCase();
42
21
  if (normalized === "all") {
@@ -70,20 +49,13 @@ function ensureEventsEnabled(options) {
70
49
  const config = (0, config_1.loadConfig)(options.root);
71
50
  const ws = normalizeWorkspaceForEvents(config, options.ws);
72
51
  const eventsPath = resolveEventsPath(options.root, config, ws);
73
- const updateGitignore = options.updateGitignore !== false;
74
52
  let created = false;
75
53
  if (!fs_1.default.existsSync(eventsPath)) {
76
54
  fs_1.default.mkdirSync(path_1.default.dirname(eventsPath), { recursive: true });
77
55
  fs_1.default.writeFileSync(eventsPath, "", "utf8");
78
56
  created = true;
79
57
  }
80
- let gitignoreUpdated = false;
81
- if (updateGitignore) {
82
- gitignoreUpdated = appendIgnoreEntries(path_1.default.join(options.root, ".gitignore"), [
83
- ".mdkg/work/events/*.jsonl",
84
- ]);
85
- }
86
- return { ws, eventsPath, created, gitignoreUpdated };
58
+ return { ws, eventsPath, created };
87
59
  }
88
60
  function normalizeIdOrIdRef(value) {
89
61
  return value.trim().toLowerCase();
@@ -131,7 +103,7 @@ function appendEvent(options) {
131
103
  }
132
104
  const eventsPath = resolveEventsPath(options.root, config, record.workspace);
133
105
  if (!fs_1.default.existsSync(eventsPath)) {
134
- throw new errors_1.NotFoundError(`event logging is not enabled for workspace ${record.workspace}; run \`mdkg event enable --ws ${record.workspace}\``);
106
+ throw new errors_1.NotFoundError(`events.jsonl is missing for workspace ${record.workspace}; run \`mdkg event enable --ws ${record.workspace}\``);
135
107
  }
136
108
  fs_1.default.appendFileSync(eventsPath, `${JSON.stringify(record)}\n`, "utf8");
137
109
  return record;
@@ -235,6 +235,7 @@ function runInitCommand(options) {
235
235
  const seedAgentStart = path_1.default.join(seedRoot, "AGENT_START.md");
236
236
  const seedCliMatrix = path_1.default.join(seedRoot, "CLI_COMMAND_MATRIX.md");
237
237
  const seedReadme = path_1.default.join(seedRoot, "README.md");
238
+ const seedDefaultSkills = path_1.default.join(seedRoot, "skills", "default");
238
239
  if (!fs_1.default.existsSync(seedConfig) || !fs_1.default.existsSync(seedCore) || !fs_1.default.existsSync(seedTemplates)) {
239
240
  throw new errors_1.NotFoundError(`init assets not found at ${seedRoot} (try reinstalling mdkg)`);
240
241
  }
@@ -256,6 +257,9 @@ function runInitCommand(options) {
256
257
  if (!fs_1.default.existsSync(seedReadme)) {
257
258
  throw new errors_1.NotFoundError(`init assets missing README.md at ${seedRoot}`);
258
259
  }
260
+ if (options.agent && !fs_1.default.existsSync(seedDefaultSkills)) {
261
+ throw new errors_1.NotFoundError(`init assets missing default skills at ${seedRoot}`);
262
+ }
259
263
  const mdkgDir = path_1.default.join(root, ".mdkg");
260
264
  fs_1.default.mkdirSync(mdkgDir, { recursive: true });
261
265
  fs_1.default.mkdirSync(path_1.default.join(mdkgDir, "work"), { recursive: true });
@@ -286,6 +290,7 @@ function runInitCommand(options) {
286
290
  const eventsPath = path_1.default.join(eventsDir, "events.jsonl");
287
291
  fs_1.default.mkdirSync(skillsDir, { recursive: true });
288
292
  fs_1.default.mkdirSync(eventsDir, { recursive: true });
293
+ copySeedDir(seedDefaultSkills, skillsDir, force, stats);
289
294
  writeFileIfMissing(soulPath, soulTemplate(today), force, stats);
290
295
  writeFileIfMissing(humanPath, humanTemplate(today), force, stats);
291
296
  writeFileIfMissing(registryPath, (0, skill_support_1.registryTemplate)(), force, stats);
@@ -296,6 +301,7 @@ function runInitCommand(options) {
296
301
  ensureCorePins(coreListPath, [SOUL_PIN_ID, HUMAN_PIN_ID]);
297
302
  (0, skill_mirror_1.scaffoldMirrorRoots)(root);
298
303
  const config = (0, config_1.loadConfig)(root);
304
+ (0, skill_support_1.refreshSkillsRegistry)(root, config);
299
305
  (0, skill_mirror_1.syncSkillMirrors)({ root, config, createRoots: true, force });
300
306
  }
301
307
  const noUpdateIgnores = Boolean(options.noUpdateIgnores);
@@ -305,7 +311,6 @@ function runInitCommand(options) {
305
311
  appendIgnoreEntries(path_1.default.join(root, ".gitignore"), [
306
312
  ".mdkg/index/",
307
313
  ".mdkg/pack/",
308
- ".mdkg/work/events/*.jsonl",
309
314
  ]);
310
315
  }
311
316
  if (shouldUpdateNpmignore) {
@@ -53,13 +53,14 @@ function runListCommand(options) {
53
53
  tagsMode: options.tagsMode,
54
54
  });
55
55
  const sorted = (0, sort_1.sortNodesByQid)(filtered);
56
- if (options.json) {
57
- (0, query_output_1.writeJson)({
56
+ const format = options.format ?? (options.json ? "json" : undefined);
57
+ if (format) {
58
+ (0, query_output_1.writeStructuredOutput)({
58
59
  command: "list",
59
60
  kind: "node",
60
61
  count: sorted.length,
61
62
  items: sorted.map(query_output_1.toNodeSummaryJson),
62
- });
63
+ }, format);
63
64
  return;
64
65
  }
65
66
  (0, query_output_1.writeCount)(sorted.length, sorted.length === 0 ? "no nodes matched current filters" : undefined);
@@ -5,6 +5,7 @@ exports.toNodeDetailJson = toNodeDetailJson;
5
5
  exports.toSkillSummaryJson = toSkillSummaryJson;
6
6
  exports.toSkillDetailJson = toSkillDetailJson;
7
7
  exports.writeJson = writeJson;
8
+ exports.writeStructuredOutput = writeStructuredOutput;
8
9
  exports.writeCount = writeCount;
9
10
  function toNodeSummaryJson(node) {
10
11
  return {
@@ -76,6 +77,113 @@ function toSkillDetailJson(skill, body) {
76
77
  function writeJson(payload) {
77
78
  console.log(JSON.stringify(payload, null, 2));
78
79
  }
80
+ function escapeXml(value) {
81
+ return value
82
+ .replace(/&/g, "&amp;")
83
+ .replace(/</g, "&lt;")
84
+ .replace(/>/g, "&gt;")
85
+ .replace(/"/g, "&quot;")
86
+ .replace(/'/g, "&apos;");
87
+ }
88
+ function isPrimitive(value) {
89
+ return (value === null ||
90
+ typeof value === "string" ||
91
+ typeof value === "number" ||
92
+ typeof value === "boolean");
93
+ }
94
+ function objectToXml(tag, value, indent = "") {
95
+ if (value === undefined) {
96
+ return [];
97
+ }
98
+ if (Array.isArray(value)) {
99
+ const lines = [`${indent}<${tag}>`];
100
+ for (const item of value) {
101
+ lines.push(...objectToXml("item", item, `${indent} `));
102
+ }
103
+ lines.push(`${indent}</${tag}>`);
104
+ return lines;
105
+ }
106
+ if (isPrimitive(value)) {
107
+ return [`${indent}<${tag}>${escapeXml(value === null ? "" : String(value))}</${tag}>`];
108
+ }
109
+ const lines = [`${indent}<${tag}>`];
110
+ for (const [key, child] of Object.entries(value)) {
111
+ lines.push(...objectToXml(key, child, `${indent} `));
112
+ }
113
+ lines.push(`${indent}</${tag}>`);
114
+ return lines;
115
+ }
116
+ function formatMarkdownScalar(value) {
117
+ return value === null ? "null" : String(value);
118
+ }
119
+ function objectToMarkdown(value, lines, indent = "", key) {
120
+ if (value === undefined) {
121
+ return;
122
+ }
123
+ if (Array.isArray(value)) {
124
+ if (key) {
125
+ lines.push(`${indent}- ${key}:`);
126
+ }
127
+ const childIndent = key ? `${indent} ` : indent;
128
+ if (value.length === 0) {
129
+ lines.push(`${childIndent}- []`);
130
+ return;
131
+ }
132
+ for (const item of value) {
133
+ if (isPrimitive(item)) {
134
+ lines.push(`${childIndent}- ${formatMarkdownScalar(item)}`);
135
+ continue;
136
+ }
137
+ lines.push(`${childIndent}-`);
138
+ objectToMarkdown(item, lines, `${childIndent} `);
139
+ }
140
+ return;
141
+ }
142
+ if (isPrimitive(value)) {
143
+ if (!key) {
144
+ lines.push(`${indent}- ${formatMarkdownScalar(value)}`);
145
+ return;
146
+ }
147
+ lines.push(`${indent}- ${key}: ${formatMarkdownScalar(value)}`);
148
+ return;
149
+ }
150
+ if (key) {
151
+ lines.push(`${indent}- ${key}:`);
152
+ }
153
+ const childIndent = key ? `${indent} ` : indent;
154
+ for (const [childKey, childValue] of Object.entries(value)) {
155
+ objectToMarkdown(childValue, lines, childIndent, childKey);
156
+ }
157
+ }
158
+ function writeXml(payload) {
159
+ const lines = ['<?xml version="1.0" encoding="UTF-8"?>'];
160
+ lines.push(...objectToXml("response", payload));
161
+ console.log(lines.join("\n"));
162
+ }
163
+ function writeToon(payload) {
164
+ console.log(JSON.stringify(payload, null, 2));
165
+ }
166
+ function writeMarkdown(payload) {
167
+ const lines = ["# mdkg response"];
168
+ objectToMarkdown(payload, lines);
169
+ console.log(lines.join("\n"));
170
+ }
171
+ function writeStructuredOutput(payload, format) {
172
+ switch (format) {
173
+ case "json":
174
+ writeJson(payload);
175
+ return;
176
+ case "xml":
177
+ writeXml(payload);
178
+ return;
179
+ case "toon":
180
+ writeToon(payload);
181
+ return;
182
+ case "md":
183
+ writeMarkdown(payload);
184
+ return;
185
+ }
186
+ }
79
187
  function writeCount(count, note) {
80
188
  console.error(`count: ${count}`);
81
189
  if (note) {
@@ -71,13 +71,14 @@ function runSearchCommand(options) {
71
71
  tagsMode: options.tagsMode,
72
72
  }).filter((node) => matchesQuery(node, terms));
73
73
  const sorted = (0, sort_1.sortNodesByQid)(nodeResults);
74
- if (options.json) {
75
- (0, query_output_1.writeJson)({
74
+ const format = options.format ?? (options.json ? "json" : undefined);
75
+ if (format) {
76
+ (0, query_output_1.writeStructuredOutput)({
76
77
  command: "search",
77
78
  kind: "node",
78
79
  count: sorted.length,
79
80
  items: sorted.map(query_output_1.toNodeSummaryJson),
80
- });
81
+ }, format);
81
82
  return;
82
83
  }
83
84
  (0, query_output_1.writeCount)(sorted.length, sorted.length === 0 ? `no nodes matched query "${query}"` : undefined);
@@ -58,12 +58,13 @@ function runShowCommand(options) {
58
58
  const content = fs_1.default.readFileSync(filePath, "utf8");
59
59
  body = (0, frontmatter_1.parseFrontmatter)(content, filePath).body.trimEnd();
60
60
  }
61
- if (options.json) {
62
- (0, query_output_1.writeJson)({
61
+ const format = options.format ?? (options.json ? "json" : undefined);
62
+ if (format) {
63
+ (0, query_output_1.writeStructuredOutput)({
63
64
  command: "show",
64
65
  kind: "node",
65
66
  item: (0, query_output_1.toNodeDetailJson)(node, options.metaOnly ? undefined : body),
66
- });
67
+ }, format);
67
68
  return;
68
69
  }
69
70
  const lines = [];
@@ -205,13 +205,14 @@ function runSkillListCommand(options) {
205
205
  console.error("warning: skills index is stale; run mdkg index to refresh");
206
206
  }
207
207
  const skills = filterSkills(Object.values(index.skills), options.tags, options.tagsMode ?? "any").sort((a, b) => a.qid.localeCompare(b.qid));
208
- if (options.json) {
209
- (0, query_output_1.writeJson)({
208
+ const format = options.format ?? (options.json ? "json" : undefined);
209
+ if (format) {
210
+ (0, query_output_1.writeStructuredOutput)({
210
211
  command: "list",
211
212
  kind: "skill",
212
213
  count: skills.length,
213
214
  items: skills.map(query_output_1.toSkillSummaryJson),
214
- });
215
+ }, format);
215
216
  return;
216
217
  }
217
218
  (0, query_output_1.writeCount)(skills.length, skills.length === 0 ? "no skills matched current filters" : undefined);
@@ -243,12 +244,13 @@ function runSkillShowCommand(options) {
243
244
  }
244
245
  body = fs_1.default.readFileSync(skillPath, "utf8").trimEnd();
245
246
  }
246
- if (options.json) {
247
- (0, query_output_1.writeJson)({
247
+ const format = options.format ?? (options.json ? "json" : undefined);
248
+ if (format) {
249
+ (0, query_output_1.writeStructuredOutput)({
248
250
  command: "show",
249
251
  kind: "skill",
250
252
  item: (0, query_output_1.toSkillDetailJson)(skill, options.metaOnly ? undefined : body),
251
- });
253
+ }, format);
252
254
  return;
253
255
  }
254
256
  if (options.metaOnly) {
@@ -307,13 +309,14 @@ function runSkillSearchCommand(options) {
307
309
  const skills = filterSkills(Object.values(index.skills), options.tags, options.tagsMode ?? "any")
308
310
  .filter((skill) => matchesSkillQuery(skill, terms))
309
311
  .sort((a, b) => a.qid.localeCompare(b.qid));
310
- if (options.json) {
311
- (0, query_output_1.writeJson)({
312
+ const format = options.format ?? (options.json ? "json" : undefined);
313
+ if (format) {
314
+ (0, query_output_1.writeStructuredOutput)({
312
315
  command: "search",
313
316
  kind: "skill",
314
317
  count: skills.length,
315
318
  items: skills.map(query_output_1.toSkillSummaryJson),
316
- });
319
+ }, format);
317
320
  return;
318
321
  }
319
322
  (0, query_output_1.writeCount)(skills.length, skills.length === 0 ? `no skills matched query "${query}"` : undefined);
@@ -110,29 +110,62 @@ function loadCanonicalSources(root, config) {
110
110
  };
111
111
  });
112
112
  }
113
- function copyDir(srcDir, destDir) {
113
+ function writeFileIfChanged(srcPath, destPath) {
114
+ const next = fs_1.default.readFileSync(srcPath);
115
+ if (fs_1.default.existsSync(destPath) && fs_1.default.statSync(destPath).isFile()) {
116
+ const current = fs_1.default.readFileSync(destPath);
117
+ if (current.equals(next)) {
118
+ return;
119
+ }
120
+ }
121
+ fs_1.default.mkdirSync(path_1.default.dirname(destPath), { recursive: true });
122
+ fs_1.default.writeFileSync(destPath, next);
123
+ }
124
+ function syncDir(srcDir, destDir) {
114
125
  fs_1.default.mkdirSync(destDir, { recursive: true });
115
- const entries = fs_1.default.readdirSync(srcDir, { withFileTypes: true });
116
- for (const entry of entries) {
126
+ const sourceEntries = fs_1.default.readdirSync(srcDir, { withFileTypes: true });
127
+ const sourceNames = new Set(sourceEntries.map((entry) => entry.name));
128
+ if (fs_1.default.existsSync(destDir)) {
129
+ for (const existing of fs_1.default.readdirSync(destDir)) {
130
+ if (!sourceNames.has(existing)) {
131
+ fs_1.default.rmSync(path_1.default.join(destDir, existing), { recursive: true, force: true });
132
+ }
133
+ }
134
+ }
135
+ for (const entry of sourceEntries) {
117
136
  const srcPath = path_1.default.join(srcDir, entry.name);
118
137
  const destPath = path_1.default.join(destDir, entry.name);
119
138
  if (entry.isDirectory()) {
120
- copyDir(srcPath, destPath);
139
+ syncDir(srcPath, destPath);
121
140
  }
122
141
  else if (entry.isFile()) {
123
- fs_1.default.mkdirSync(path_1.default.dirname(destPath), { recursive: true });
124
- fs_1.default.copyFileSync(srcPath, destPath);
142
+ writeFileIfChanged(srcPath, destPath);
125
143
  }
126
144
  }
127
145
  }
128
146
  function materializeSkillMirror(source, destDir) {
129
- fs_1.default.rmSync(destDir, { recursive: true, force: true });
130
147
  fs_1.default.mkdirSync(destDir, { recursive: true });
131
- fs_1.default.copyFileSync(source.docPath, path_1.default.join(destDir, "SKILL.md"));
148
+ const expectedRootEntries = new Set(["SKILL.md"]);
149
+ for (const entry of ["references", "assets", "scripts"]) {
150
+ const srcPath = path_1.default.join(source.sourceDir, entry);
151
+ if (fs_1.default.existsSync(srcPath) && fs_1.default.statSync(srcPath).isDirectory()) {
152
+ expectedRootEntries.add(entry);
153
+ }
154
+ }
155
+ for (const existing of fs_1.default.readdirSync(destDir)) {
156
+ if (!expectedRootEntries.has(existing)) {
157
+ fs_1.default.rmSync(path_1.default.join(destDir, existing), { recursive: true, force: true });
158
+ }
159
+ }
160
+ writeFileIfChanged(source.docPath, path_1.default.join(destDir, "SKILL.md"));
132
161
  for (const entry of ["references", "assets", "scripts"]) {
133
162
  const srcPath = path_1.default.join(source.sourceDir, entry);
163
+ const destPath = path_1.default.join(destDir, entry);
134
164
  if (fs_1.default.existsSync(srcPath) && fs_1.default.statSync(srcPath).isDirectory()) {
135
- copyDir(srcPath, path_1.default.join(destDir, entry));
165
+ syncDir(srcPath, destPath);
166
+ }
167
+ else if (fs_1.default.existsSync(destPath)) {
168
+ fs_1.default.rmSync(destPath, { recursive: true, force: true });
136
169
  }
137
170
  }
138
171
  }
@@ -173,7 +173,7 @@ function maybeWarnEventsDisabled(root, config, ws) {
173
173
  if ((0, event_support_1.isEventLoggingEnabled)(root, config, ws)) {
174
174
  return;
175
175
  }
176
- console.error(`note: event logging not enabled for workspace ${ws}; run mdkg event enable --ws ${ws} if you want JSONL provenance`);
176
+ console.error(`note: events.jsonl is missing for workspace ${ws}; run mdkg event enable --ws ${ws} to restore JSONL provenance`);
177
177
  }
178
178
  function runTaskStartCommand(options) {
179
179
  const loaded = loadMutableTaskNode(options.root, options.id, options.ws);
@@ -6,3 +6,4 @@ Codex/OpenAI conventions for this repo:
6
6
  - use `AGENT_START.md` as the startup contract
7
7
  - use `.agents/skills/` for product-facing mirrored skills when present
8
8
  - use `mdkg skill ...` as the canonical skill command family
9
+ - use `mdkg task ...` for structured task fields and markdown edits for narrative/body changes
@@ -40,7 +40,14 @@ Conventions:
40
40
  - `.agents/skills/` and `.claude/skills/` mirror canonical skills from `.mdkg/skills/` when agent bootstrap is enabled.
41
41
  - mdkg does not execute skill scripts; runtimes decide when and whether to do that.
42
42
  - Prefer packs over ad-hoc file lists.
43
- - Prefer task/event commands over hand-editing routine work-state changes.
43
+ - Prefer task/event commands for structured work-state changes and use markdown edits for narrative/body updates.
44
44
  - Use `mdkg task done <id> --checkpoint "<title>"` for milestone compression, not every routine task completion.
45
- - Prefer checkpoints for feat/epic closeout summaries; parent status edits remain manual in 0.0.5.
46
- - If events are disabled, `mdkg task start` and `mdkg task done` will remind you how to enable JSONL provenance.
45
+ - Prefer checkpoints for feat/epic closeout summaries; parent status edits remain manual.
46
+ - If `events.jsonl` is missing, `mdkg task start` and `mdkg task done` will remind you how to recreate it.
47
+ - Files outside mdkg-managed skill mirrors, such as local tool permission files, are not managed by mdkg unless documented explicitly.
48
+
49
+ Structured discovery/show exports:
50
+ - `--json`
51
+ - `--xml`
52
+ - `--toon`
53
+ - `--md`
@@ -21,9 +21,16 @@ Agent bootstrap:
21
21
  - `mdkg init --llm`
22
22
  - `mdkg init --agent`
23
23
  - `mdkg init --llm --agent`
24
+ - published bootstrap config is root-only by default
24
25
 
25
26
  Skill discovery:
26
27
  - `mdkg skill list --tags stage:plan --json`
27
28
  - `mdkg skill search "<query>" --json`
28
29
  - `mdkg skill show <slug> --json`
29
30
  - `mdkg skill sync`
31
+
32
+ Discovery/show export flags:
33
+ - `--json`
34
+ - `--xml`
35
+ - `--toon`
36
+ - `--md`
@@ -52,16 +52,6 @@
52
52
  "path": ".",
53
53
  "enabled": true,
54
54
  "mdkg_dir": ".mdkg"
55
- },
56
- "polish": {
57
- "path": "polish",
58
- "enabled": true,
59
- "mdkg_dir": ".mdkg"
60
- },
61
- "smoke": {
62
- "path": "smoke",
63
- "enabled": true,
64
- "mdkg_dir": ".mdkg"
65
55
  }
66
56
  }
67
- }
57
+ }
@@ -88,7 +88,7 @@ If a user provides an unqualified ID and it is ambiguous globally:
88
88
  - Commands should be script-friendly:
89
89
  - concise outputs for single items
90
90
  - predictable formatting
91
- - `--json` output for supported discovery/show commands
91
+ - `--json`, `--xml`, `--toon`, and `--md` output for supported discovery/show commands
92
92
  - when printing node summaries (e.g., `show`/list results), outputs SHOULD surface key searchable frontmatter fields such as `links` and `artifacts`
93
93
 
94
94
  ## Command set (v1 target)
@@ -107,6 +107,10 @@ If a user provides an unqualified ID and it is ambiguous globally:
107
107
  - `--agent` adds strict-node bootstrap docs and scaffolding:
108
108
  - `.mdkg/core/SOUL.md` (`id: rule-soul`)
109
109
  - `.mdkg/core/HUMAN.md` (`id: rule-human`)
110
+ - seeded canonical skills:
111
+ - `.mdkg/skills/select-work-and-ground-context/SKILL.md`
112
+ - `.mdkg/skills/build-pack-and-execute-task/SKILL.md`
113
+ - `.mdkg/skills/verify-close-and-checkpoint/SKILL.md`
110
114
  - `.mdkg/skills/registry.md`
111
115
  - `.mdkg/work/events/events.jsonl`
112
116
  - `.agents/skills/`
@@ -160,18 +164,19 @@ Common flags:
160
164
  - `--template <set>` (default from config)
161
165
 
162
166
  ### Read/search
163
- - `mdkg show <id-or-qid> [--meta] [--json]`
167
+ - `mdkg show <id-or-qid> [--meta] [--json|--xml|--toon|--md]`
164
168
  - default behavior shows the full node body
165
169
  - `--meta` is the compact card-only view
166
- - `mdkg search "<query>" [--type <type>] [--status <status>] [--ws <alias>] [--tags <tag,tag,...>] [--tags-mode any|all] [--json]`
170
+ - `mdkg search "<query>" [--type <type>] [--status <status>] [--ws <alias>] [--tags <tag,tag,...>] [--tags-mode any|all] [--json|--xml|--toon|--md]`
167
171
  - search SHOULD match on IDs, titles, tags, path tokens, and searchable frontmatter lists (`links`, `artifacts`, `refs`, `aliases`)
168
- - `mdkg list [--type <type>] [--status <status>] [--ws <alias>] [--epic <id>] [--blocked] [--priority <n>] [--tags <tag,tag,...>] [--tags-mode any|all] [--json]`
172
+ - `mdkg list [--type <type>] [--status <status>] [--ws <alias>] [--epic <id>] [--blocked] [--priority <n>] [--tags <tag,tag,...>] [--tags-mode any|all] [--json|--xml|--toon|--md]`
169
173
  - skills are first-class under `mdkg skill ...` only:
170
- - `mdkg skill list [--tags <tag,tag,...>] [--tags-mode any|all] [--json]`
171
- - `mdkg skill show <slug> [--meta] [--json]`
172
- - `mdkg skill search "<query>" [--tags <tag,tag,...>] [--tags-mode any|all] [--json]`
174
+ - `mdkg skill list [--tags <tag,tag,...>] [--tags-mode any|all] [--json|--xml|--toon|--md]`
175
+ - `mdkg skill show <slug> [--meta] [--json|--xml|--toon|--md]`
176
+ - `mdkg skill search "<query>" [--tags <tag,tag,...>] [--tags-mode any|all] [--json|--xml|--toon|--md]`
173
177
  - `mdkg skill validate [<slug>]`
174
178
  - `mdkg skill sync [--force]`
179
+ - discovery/show output flags are mutually exclusive; text mode remains the default when none are supplied
175
180
 
176
181
  ### Task lifecycle mutation
177
182
  - `mdkg task start <id-or-qid> [--ws <alias>] [--run-id <id>] [--note "<text>"]`
@@ -219,9 +224,9 @@ Common flags:
219
224
  - designed as a phase summary / compression node
220
225
 
221
226
  ### Events
222
- - `mdkg event enable [--ws <alias>] [--no-update-gitignore]`
227
+ - `mdkg event enable [--ws <alias>]`
223
228
  - creates `.mdkg/work/events/events.jsonl` if missing
224
- - updates `.gitignore` by default
229
+ - leaves `.gitignore` unchanged
225
230
  - `mdkg event append --kind <kind> --status <ok|error|retry|skipped> --refs <id,...> [...]`
226
231
  - appends one JSONL provenance record
227
232
  - automatic command-level events append only when event logging is enabled for the target workspace
@@ -36,7 +36,6 @@ Recommended `.gitignore` entries:
36
36
  - `.mdkg/index/`
37
37
  - `.mdkg/index/**`
38
38
  - `.mdkg/pack/`
39
- - `.mdkg/work/events/*.jsonl` (when episodic logging is enabled)
40
39
 
41
40
  ## npm publish safety (required)
42
41
 
@@ -70,7 +69,7 @@ For application builds:
70
69
 
71
70
  `mdkg init` updates ignore files by default for safety:
72
71
 
73
- - `.gitignore` appends `.mdkg/index/`, `.mdkg/pack/`, `.mdkg/work/events/*.jsonl`
72
+ - `.gitignore` appends `.mdkg/index/`, `.mdkg/pack/`
74
73
  - `.npmignore` appends `.mdkg/`, `.mdkg/index/`, `.mdkg/pack/`
75
74
  - `--no-update-ignores` disables these default writes
76
75
 
@@ -97,7 +96,7 @@ Workspace-local `.mdkg/` directories (near code) should follow the same rules:
97
96
  ## Summary checklist
98
97
 
99
98
  - ✅ `.mdkg/index/` ignored
100
- - ✅ `.mdkg/work/events/*.jsonl` ignored when event logging is enabled
99
+ - ✅ event logs are committed by default unless a repo chooses to ignore them manually
101
100
  - ✅ npm publishes only `dist/`, `README.md`, `LICENSE`
102
101
  - ✅ optional `.npmignore` excludes `.mdkg/`
103
102
  - ✅ `.dockerignore` excludes `.mdkg/` when applicable
@@ -15,3 +15,5 @@ First commands:
15
15
  - `mdkg pack <id>`
16
16
  - `mdkg skill list --tags stage:plan --json`
17
17
  - `mdkg validate`
18
+
19
+ Discovery and show commands also support `--xml`, `--toon`, and `--md` when JSON is not the desired interchange format.
@@ -0,0 +1,57 @@
1
+ ---
2
+ name: build-pack-and-execute-task
3
+ description: Build a deterministic mdkg pack for the active work item and use it as the execution handoff when coding or delegating to another AI agent.
4
+ tags: [stage:execute, writer:patch-only, mdkg, pack-first, context]
5
+ version: 0.1.0
6
+ authors: [mdkg]
7
+ links: [README.md, PACK_EXAMPLES.md, llms.txt]
8
+ ---
9
+
10
+ # Goal
11
+
12
+ Use `mdkg pack <id>` as the default execution context instead of ad-hoc file gathering.
13
+
14
+ ## When To Use
15
+
16
+ - Before coding
17
+ - Before handing work to another AI agent
18
+ - Before review when precise linked context matters
19
+
20
+ ## Inputs
21
+
22
+ - Selected node id
23
+ - Optional profile choice
24
+ - Optional skills inclusion mode
25
+
26
+ ## Steps
27
+
28
+ 1. Start with `mdkg pack <id>`.
29
+ 2. For a preview, use `mdkg pack <id> --profile concise --dry-run --stats`.
30
+ 3. Use `--verbose` only when pinned core docs must be included in the pack body.
31
+ 4. Use `--skills auto` when the work item already references the right skills.
32
+ 5. Use `--skills-depth full` only for active execution, not early discovery.
33
+ 6. Discover skills by metadata first; load full skill bodies only for the selected execution procedures.
34
+ 7. Hand the pack, not a loose file list, to the next coding step or agent.
35
+ 8. Keep this stage patch-only: subagents and tools may produce patches, test output, and evidence, but not direct mdkg state writes or commits.
36
+ 9. If execution reveals new artifacts or blockers, hand them to the orchestrator stage for `mdkg task update ...` as structured field updates; keep narrative summaries in markdown.
37
+
38
+ ## Outputs
39
+
40
+ - Deterministic pack file or dry-run selection report
41
+ - Stable context bundle for execution or review
42
+ - Patch bundles, test output, or evidence artifacts ready for orchestrator review
43
+
44
+ ## Safety
45
+
46
+ - Prefer smaller packs first; expand only when the task requires it.
47
+ - Keep pinned rules ahead of opportunistic context.
48
+ - Do not treat raw event logs as primary execution context.
49
+ - Do not mutate task status, create checkpoints, or commit from this stage.
50
+ - mdkg indexes and discovers skills, but does not execute skill scripts.
51
+ - If event logging is enabled, rely on later task/checkpoint commands to append baseline events instead of writing ad-hoc log entries here.
52
+
53
+ ## Failure Handling
54
+
55
+ - If the pack is too broad, reduce profile or skill depth before continuing.
56
+ - If the required procedure is unclear, return to metadata discovery instead of loading every skill body.
57
+ - If execution requires a durable memory update, hand control back to the orchestrator stage instead of writing directly.
@@ -0,0 +1,55 @@
1
+ ---
2
+ name: select-work-and-ground-context
3
+ description: Select the right mdkg work item and ground execution before coding when the active task or context is still being established.
4
+ tags: [stage:plan, writer:read-only, mdkg, onboarding, context]
5
+ version: 0.1.0
6
+ authors: [mdkg]
7
+ links: [AGENT_START.md, README.md, CLI_COMMAND_MATRIX.md]
8
+ ---
9
+
10
+ # Goal
11
+
12
+ Choose the correct work item and load the smallest deterministic context needed to act.
13
+
14
+ ## When To Use
15
+
16
+ - At the start of a work session
17
+ - When the active task is unclear
18
+ - Before generating a pack or making code changes
19
+
20
+ ## Inputs
21
+
22
+ - Current repo root
23
+ - Optional task or epic id
24
+ - Optional user goal in plain language
25
+
26
+ ## Steps
27
+
28
+ 1. If a task id is already known, inspect it with `mdkg show <id>`.
29
+ 2. If the task is not known, read `AGENT_START.md` and use `mdkg next` or `mdkg search "<query>"` to narrow candidates.
30
+ 3. Use `mdkg show <id> --meta` when you only need the card and link metadata.
31
+ 4. Confirm the selected node has the right constraints, related design docs, and current status.
32
+ 5. If the task is ambiguous, resolve that before building a pack.
33
+ 6. If the chosen task is ready to be claimed, hand off to `mdkg task start <id>` in the writer stage for the structured status change.
34
+ 7. If resuming closeout work for a feat or epic, inspect the latest relevant checkpoint before deciding what remains open.
35
+ 8. Treat this stage as read-only: inspect and decide, but do not mutate mdkg state or commit.
36
+
37
+ ## Outputs
38
+
39
+ - One selected node id
40
+ - Clear understanding of the active task, related docs, and current state
41
+ - No durable mdkg writes or commits from this stage
42
+
43
+ ## Safety
44
+
45
+ - Do not start coding from chat memory alone.
46
+ - Prefer explicit rules, EDDs, DECs, and task nodes over informal notes.
47
+ - If multiple tasks appear valid, stop and choose deliberately instead of guessing.
48
+ - If writer ownership or policy boundaries are unclear, stop and resolve them before execution.
49
+ - mdkg indexes and discovers skills, but does not execute skill scripts.
50
+ - Event logging is committed by default in `init --agent` repos; use `mdkg event enable` only if `events.jsonl` is missing.
51
+
52
+ ## Failure Handling
53
+
54
+ - If no clear work item exists, stop and ask for clarification instead of guessing.
55
+ - If the selected task conflicts with current status or linked design docs, resolve the conflict before moving to pack generation.
@@ -0,0 +1,62 @@
1
+ ---
2
+ name: verify-close-and-checkpoint
3
+ description: Verify code and mdkg state, attach evidence, and close work cleanly when the single-writer AI agent or human orchestrator is ready to perform durable writes.
4
+ tags: [stage:review, writer:orchestrator, mdkg, validation, release]
5
+ version: 0.1.0
6
+ authors: [mdkg]
7
+ links: [README.md, AGENT_PROMPT_SNIPPET.md]
8
+ ---
9
+
10
+ # Goal
11
+
12
+ Finish work with evidence, validation, and minimal memory drift.
13
+
14
+ ## When To Use
15
+
16
+ - After implementation
17
+ - Before commit
18
+ - Before marking a task done
19
+ - Before creating a checkpoint
20
+
21
+ ## Inputs
22
+
23
+ - Active task id
24
+ - Test or build outputs
25
+ - Any new artifact references
26
+
27
+ ## Steps
28
+
29
+ 1. Run the relevant technical gates for the changed surface.
30
+ 2. Run `mdkg validate` before closing the task.
31
+ 3. Use `mdkg task update <id> ...` for additive evidence and structured metadata changes; keep narrative/body edits in markdown.
32
+ 4. Use `mdkg task done <id> --checkpoint "<title>"` when the task should close with milestone compression.
33
+ 5. Batch durable mdkg writes at one boundary: task status, artifact refs, optional checkpoint, and commit.
34
+ 6. Mark tasks done only after evidence exists.
35
+ 7. Create a checkpoint only for milestone-level transitions, not every small step.
36
+ 8. For feat or epic closeout, prefer a checkpoint body as the durable narrative summary of what changed and what is next.
37
+ 9. Use feat closeout scope as direct children with `parent: <feat-id>` and epic closeout scope as descendant work with `epic: <epic-id>`.
38
+ 10. Parent status edits remain manual; do not invent a hidden parent-closeout workflow.
39
+ 11. If the latest checkpoint is relevant, use it as durable recall; treat raw events as provenance/debugging, not primary execution context.
40
+ 12. If `events.jsonl` is missing, recreate it with `mdkg event enable` before expecting automatic JSONL provenance.
41
+
42
+ ## Outputs
43
+
44
+ - Verified mdkg graph state
45
+ - Attached evidence and artifact refs
46
+ - Task ready for review, done, or checkpointing
47
+ - One durable writer action at the selected run or milestone boundary
48
+
49
+ ## Safety
50
+
51
+ - Do not mark work done without validation.
52
+ - Do not create checkpoint spam.
53
+ - Keep commits event-driven and single-writer when agents are involved.
54
+ - Only the orchestrator performs durable mdkg writes or commit/push actions.
55
+ - Never commit on every tool call.
56
+ - mdkg indexes and discovers skills, but does not execute skill scripts.
57
+
58
+ ## Failure Handling
59
+
60
+ - If validation fails, stop and return the task to active work instead of closing it.
61
+ - If artifact or evidence refs are missing, attach them before status changes or checkpoint creation.
62
+ - If writer ownership is unclear, stop and resolve it before any durable mdkg update or commit.
@@ -79,10 +79,12 @@ const BOOLEAN_FLAGS = new Set([
79
79
  "--version",
80
80
  "--dry-run",
81
81
  "--json",
82
+ "--xml",
83
+ "--toon",
84
+ "--md",
82
85
  "--list-profiles",
83
86
  "--with-scripts",
84
87
  "--clear-blocked-by",
85
- "--no-update-gitignore",
86
88
  ]);
87
89
  const FLAG_ALIASES = {
88
90
  "--o": "--out",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mdkg",
3
- "version": "0.0.5",
3
+ "version": "0.0.7",
4
4
  "description": "Markdown Knowledge Graph",
5
5
  "license": "MIT",
6
6
  "bin": {