mdkg 0.0.2 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +171 -151
  2. package/dist/cli.js +920 -422
  3. package/dist/commands/checkpoint.js +17 -6
  4. package/dist/commands/doctor.js +156 -0
  5. package/dist/commands/event.js +46 -0
  6. package/dist/commands/event_support.js +146 -0
  7. package/dist/commands/format.js +6 -7
  8. package/dist/commands/index.js +10 -4
  9. package/dist/commands/init.js +202 -11
  10. package/dist/commands/list.js +18 -1
  11. package/dist/commands/new.js +30 -5
  12. package/dist/commands/pack.js +332 -10
  13. package/dist/commands/query_output.js +84 -0
  14. package/dist/commands/search.js +22 -5
  15. package/dist/commands/show.js +26 -11
  16. package/dist/commands/skill.js +359 -0
  17. package/dist/commands/skill_support.js +121 -0
  18. package/dist/commands/task.js +270 -0
  19. package/dist/commands/validate.js +104 -7
  20. package/dist/graph/edges.js +2 -2
  21. package/dist/graph/frontmatter.js +1 -0
  22. package/dist/graph/indexer.js +21 -0
  23. package/dist/graph/node.js +20 -4
  24. package/dist/graph/skills_index_cache.js +94 -0
  25. package/dist/graph/skills_indexer.js +160 -0
  26. package/dist/init/README.md +43 -0
  27. package/dist/init/core/rule-1-mdkg-conventions.md +9 -2
  28. package/dist/init/core/rule-3-cli-contract.md +73 -14
  29. package/dist/init/core/rule-4-repo-safety-and-ignores.md +9 -3
  30. package/dist/init/core/rule-6-templates-and-schemas.md +6 -2
  31. package/dist/init/skills/SKILL.md.example +41 -0
  32. package/dist/init/templates/default/bug.md +1 -0
  33. package/dist/init/templates/default/chk.md +1 -0
  34. package/dist/init/templates/default/epic.md +1 -0
  35. package/dist/init/templates/default/feat.md +1 -0
  36. package/dist/init/templates/default/task.md +1 -0
  37. package/dist/init/templates/default/test.md +1 -0
  38. package/dist/pack/budget.js +186 -0
  39. package/dist/pack/export_md.js +17 -1
  40. package/dist/pack/export_xml.js +15 -0
  41. package/dist/pack/metrics.js +66 -0
  42. package/dist/pack/pack.js +35 -0
  43. package/dist/pack/profile.js +222 -0
  44. package/dist/pack/stats.js +37 -0
  45. package/dist/templates/headings.js +34 -0
  46. package/dist/util/argparse.js +47 -1
  47. package/dist/util/filter.js +18 -0
  48. package/dist/util/id.js +23 -0
  49. package/dist/util/output.js +2 -2
  50. package/package.json +6 -2
@@ -0,0 +1,160 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.SKILL_SLUG_RE = exports.SKILLS_INDEX_RELATIVE_PATH = void 0;
7
+ exports.resolveSkillsRoot = resolveSkillsRoot;
8
+ exports.resolveSkillsIndexPath = resolveSkillsIndexPath;
9
+ exports.buildSkillIndexEntry = buildSkillIndexEntry;
10
+ exports.buildSkillsIndex = buildSkillsIndex;
11
+ const fs_1 = __importDefault(require("fs"));
12
+ const path_1 = __importDefault(require("path"));
13
+ const frontmatter_1 = require("./frontmatter");
14
+ exports.SKILLS_INDEX_RELATIVE_PATH = ".mdkg/index/skills.json";
15
+ exports.SKILL_SLUG_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
16
+ function listSkillMarkdownFiles(dir) {
17
+ if (!fs_1.default.existsSync(dir)) {
18
+ return [];
19
+ }
20
+ const entries = fs_1.default.readdirSync(dir, { withFileTypes: true });
21
+ const files = [];
22
+ for (const entry of entries) {
23
+ if (!entry.isDirectory()) {
24
+ continue;
25
+ }
26
+ const slug = entry.name.toLowerCase();
27
+ const skillDir = path_1.default.join(dir, entry.name);
28
+ const canonicalPath = path_1.default.join(skillDir, "SKILL.md");
29
+ const compatPath = path_1.default.join(skillDir, "SKILLS.md");
30
+ if (fs_1.default.existsSync(canonicalPath) && fs_1.default.existsSync(compatPath)) {
31
+ throw new Error(`${skillDir}: both SKILL.md and SKILLS.md exist`);
32
+ }
33
+ if (fs_1.default.existsSync(canonicalPath)) {
34
+ files.push({ slug, filePath: canonicalPath });
35
+ continue;
36
+ }
37
+ if (fs_1.default.existsSync(compatPath)) {
38
+ files.push({ slug, filePath: compatPath });
39
+ }
40
+ }
41
+ files.sort((a, b) => a.slug.localeCompare(b.slug));
42
+ return files;
43
+ }
44
+ function requireString(frontmatter, key, filePath) {
45
+ const value = frontmatter[key];
46
+ if (typeof value !== "string" || value.trim().length === 0) {
47
+ throw new Error(`${filePath}: ${key} is required and must be a non-empty string`);
48
+ }
49
+ return value;
50
+ }
51
+ function optionalString(frontmatter, key, filePath) {
52
+ const value = frontmatter[key];
53
+ if (value === undefined) {
54
+ return undefined;
55
+ }
56
+ if (typeof value !== "string" || value.trim().length === 0) {
57
+ throw new Error(`${filePath}: ${key} must be a non-empty string when set`);
58
+ }
59
+ return value;
60
+ }
61
+ function optionalList(frontmatter, key, filePath) {
62
+ const value = frontmatter[key];
63
+ if (value === undefined) {
64
+ return [];
65
+ }
66
+ if (!Array.isArray(value)) {
67
+ throw new Error(`${filePath}: ${key} must be a list`);
68
+ }
69
+ return value;
70
+ }
71
+ function toLowercaseList(values) {
72
+ return values.map((value) => value.toLowerCase());
73
+ }
74
+ function extractOchatr(frontmatter) {
75
+ const keys = Object.keys(frontmatter)
76
+ .filter((key) => key.startsWith("ochatr_"))
77
+ .sort();
78
+ const extracted = {};
79
+ for (const key of keys) {
80
+ extracted[key] = frontmatter[key];
81
+ }
82
+ return extracted;
83
+ }
84
+ function hasDirectory(dirPath) {
85
+ if (!fs_1.default.existsSync(dirPath)) {
86
+ return false;
87
+ }
88
+ return fs_1.default.statSync(dirPath).isDirectory();
89
+ }
90
+ function rootWorkspaceMdkgPath(root, config) {
91
+ const rootWs = config.workspaces.root;
92
+ if (rootWs && rootWs.enabled) {
93
+ return path_1.default.resolve(root, rootWs.path, rootWs.mdkg_dir);
94
+ }
95
+ return path_1.default.resolve(root, ".mdkg");
96
+ }
97
+ function resolveSkillsRoot(root, config) {
98
+ return path_1.default.join(rootWorkspaceMdkgPath(root, config), "skills");
99
+ }
100
+ function resolveSkillsIndexPath(root) {
101
+ return path_1.default.resolve(root, exports.SKILLS_INDEX_RELATIVE_PATH);
102
+ }
103
+ function buildSkillIndexEntry(root, slug, filePath) {
104
+ if (!exports.SKILL_SLUG_RE.test(slug)) {
105
+ throw new Error(`${filePath}: skill slug must be kebab-case`);
106
+ }
107
+ const content = fs_1.default.readFileSync(filePath, "utf8");
108
+ const { frontmatter } = (0, frontmatter_1.parseFrontmatter)(content, filePath);
109
+ const name = requireString(frontmatter, "name", filePath);
110
+ const description = requireString(frontmatter, "description", filePath);
111
+ const version = optionalString(frontmatter, "version", filePath);
112
+ const tags = toLowercaseList(optionalList(frontmatter, "tags", filePath));
113
+ const authors = toLowercaseList(optionalList(frontmatter, "authors", filePath));
114
+ const links = optionalList(frontmatter, "links", filePath);
115
+ const skillDir = path_1.default.dirname(filePath);
116
+ return {
117
+ slug,
118
+ id: `skill:${slug}`,
119
+ qid: `root:skill:${slug}`,
120
+ ws: "root",
121
+ type: "skill",
122
+ name,
123
+ description,
124
+ tags,
125
+ version,
126
+ authors,
127
+ links,
128
+ path: path_1.default.relative(root, filePath),
129
+ has_scripts: hasDirectory(path_1.default.join(skillDir, "scripts")),
130
+ has_references: hasDirectory(path_1.default.join(skillDir, "references")),
131
+ ochatr: extractOchatr(frontmatter),
132
+ };
133
+ }
134
+ function buildSkillsIndex(root, config) {
135
+ const skillsRoot = resolveSkillsRoot(root, config);
136
+ const files = listSkillMarkdownFiles(skillsRoot);
137
+ const skills = {};
138
+ for (const file of files) {
139
+ const { slug, filePath } = file;
140
+ if (skills[slug]) {
141
+ throw new Error(`${filePath}: duplicate skill slug ${slug}`);
142
+ }
143
+ skills[slug] = buildSkillIndexEntry(root, slug, filePath);
144
+ }
145
+ const sortedSkills = {};
146
+ for (const slug of Object.keys(skills).sort()) {
147
+ sortedSkills[slug] = skills[slug];
148
+ }
149
+ return {
150
+ meta: {
151
+ tool: config.tool,
152
+ schema_version: config.schema_version,
153
+ generated_at: new Date().toISOString(),
154
+ root,
155
+ skills_root: path_1.default.relative(root, skillsRoot),
156
+ skill_count: Object.keys(sortedSkills).length,
157
+ },
158
+ skills: sortedSkills,
159
+ };
160
+ }
@@ -0,0 +1,43 @@
1
+ # mdkg Workspace Guide
2
+
3
+ This repository is initialized for mdkg.
4
+
5
+ ## Layout
6
+
7
+ - `core/`: rules, operating guide, and pinned docs
8
+ - `design/`: product/engineering decision records
9
+ - `work/`: epics, tasks, bugs, tests, checkpoints
10
+ - `templates/`: default node templates
11
+ - `index/`: generated index cache (do not commit)
12
+ - `pack/`: generated context packs (do not commit)
13
+
14
+ ## First Commands
15
+
16
+ ```bash
17
+ mdkg index
18
+ mdkg new task "..." --status todo --priority 1
19
+ mdkg list --status todo
20
+ mdkg pack <id> --verbose
21
+ mdkg validate
22
+ ```
23
+
24
+ ## Pack Profiles
25
+
26
+ - `--pack-profile standard`: full body (current default behavior)
27
+ - `--pack-profile concise`: summary body with code stripped by default
28
+ - `--pack-profile headers`: metadata-only body (`none`)
29
+
30
+ `--max-tokens` is a heuristic limit based on `chars / 4`.
31
+
32
+ ## Safety
33
+
34
+ Ensure ignore files include:
35
+
36
+ - `.mdkg/index/`
37
+ - `.mdkg/pack/`
38
+
39
+ Recommended:
40
+
41
+ ```bash
42
+ mdkg init --update-gitignore --update-npmignore
43
+ ```
@@ -10,7 +10,7 @@ relates: []
10
10
  refs: []
11
11
  aliases: []
12
12
  created: 2026-01-06
13
- updated: 2026-01-22
13
+ updated: 2026-03-05
14
14
  ---
15
15
 
16
16
  # mdkg conventions
@@ -87,6 +87,11 @@ Canonical ID format:
87
87
 
88
88
  `<prefix>-<number>`
89
89
 
90
+ Reserved rule IDs allowed by contract:
91
+ - `rule-guide`
92
+ - `rule-soul`
93
+ - `rule-human`
94
+
90
95
  Examples:
91
96
  - `task-183`
92
97
  - `edd-14`
@@ -153,11 +158,12 @@ All nodes MUST include:
153
158
  - `created` (YYYY-MM-DD)
154
159
  - `updated` (YYYY-MM-DD)
155
160
 
156
- Work items (`epic/feat/task/bug/chk/test`) MUST include:
161
+ Work items (`epic/feat/task/bug/checkpoint/test`) MUST include:
157
162
  - `status`
158
163
 
159
164
  Work items MAY include:
160
165
  - `priority`
166
+ - `skills: [slug, ...]` (kebab-case skill references)
161
167
 
162
168
  Optional searchable metadata
163
169
 
@@ -222,6 +228,7 @@ They SHOULD include:
222
228
  The cache is enabled by default.
223
229
 
224
230
  - Root global index lives at `.mdkg/index/global.json`
231
+ - Root skills index lives at `.mdkg/index/skills.json`
225
232
  - Index is rebuilt automatically when stale unless disabled by flag/config.
226
233
  - `.mdkg/index/` is generated and MUST be gitignored.
227
234
 
@@ -10,7 +10,7 @@ relates: []
10
10
  refs: []
11
11
  aliases: []
12
12
  created: 2026-01-06
13
- updated: 2026-01-22
13
+ updated: 2026-03-08
14
14
  ---
15
15
 
16
16
  # mdkg CLI contract
@@ -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
- - optional `--json` output later (not required for v1)
91
+ - `--json` 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)
@@ -99,10 +99,17 @@ If a user provides an unqualified ID and it is ambiguous globally:
99
99
  - creates `.mdkg/config.json` if missing
100
100
  - creates core docs and templates if missing
101
101
  - does NOT overwrite existing docs unless `--force`
102
- - optional agent files:
103
- - `--agents` creates `AGENTS.md`
104
- - `--claude` creates `CLAUDE.md`
105
- - `--llm` creates both
102
+ - updates `.gitignore` and `.npmignore` by default
103
+ - `--no-update-ignores` disables default ignore writes
104
+ - explicit flags (`--update-gitignore`, `--update-npmignore`, `--update-dockerignore`) force writes even with global opt-out
105
+ - `--llm` is the canonical documented path for creating `AGENTS.md` and `CLAUDE.md`
106
+ - `--agents` / `--claude` remain compatibility flags, but are not part of the primary onboarding story
107
+ - `--omni` adds strict-node bootstrap docs and scaffolding:
108
+ - `.mdkg/core/SOUL.md` (`id: rule-soul`)
109
+ - `.mdkg/core/HUMAN.md` (`id: rule-human`)
110
+ - `.mdkg/skills/registry.md`
111
+ - `.mdkg/work/events/events.jsonl`
112
+ - deterministic `core.md` pin insertion (`rule-soul`, then `rule-human`)
106
113
 
107
114
  ### Guide
108
115
  - `mdkg guide`
@@ -116,6 +123,9 @@ If a user provides an unqualified ID and it is ambiguous globally:
116
123
  ### Indexing
117
124
  - `mdkg index`
118
125
  - rebuild global cache `.mdkg/index/global.json`
126
+ - rebuild skills cache `.mdkg/index/skills.json` from `.mdkg/skills/<slug>/SKILL.md`
127
+ - tolerate `.mdkg/skills/<slug>/SKILLS.md` on read with warning
128
+ - fail validation if both `SKILL.md` and `SKILLS.md` exist in one skill directory
119
129
  - strict by default (fails on invalid frontmatter)
120
130
  - optional `--tolerant` to skip invalid nodes (escape hatch)
121
131
 
@@ -140,24 +150,56 @@ Common flags:
140
150
  - `--artifacts <ref,ref,...>`
141
151
  - `--refs <id,id,...>`
142
152
  - `--aliases <text,text,...>`
153
+ - `--skills <slug,slug,...>` (work items)
143
154
  - `--template <set>` (default from config)
144
155
 
145
156
  ### Read/search
146
- - `mdkg show <id-or-qid>`
147
- - `mdkg search "<query>" [--type <type>] [--status <status>] [--ws <alias>]`
157
+ - `mdkg show <id-or-qid> [--meta] [--json]`
158
+ - default behavior shows the full node body
159
+ - `--meta` is the compact card-only view
160
+ - `mdkg search "<query>" [--type <type>] [--status <status>] [--ws <alias>] [--tags <tag,tag,...>] [--tags-mode any|all] [--json]`
148
161
  - search SHOULD match on IDs, titles, tags, path tokens, and searchable frontmatter lists (`links`, `artifacts`, `refs`, `aliases`)
149
- - `mdkg list [--type <type>] [--status <status>] [--ws <alias>] [--epic <id>] [--blocked] [--priority <n>]`
150
-
151
- ### Graph views
152
- - `mdkg tree <epic-id-or-qid> [--ws <alias>]`
153
- - `mdkg neighbors <id-or-qid> --depth <n> [--edges <...>]`
162
+ - `mdkg list [--type <type>] [--status <status>] [--ws <alias>] [--epic <id>] [--blocked] [--priority <n>] [--tags <tag,tag,...>] [--tags-mode any|all] [--json]`
163
+ - skills are first-class under `mdkg skill ...` only:
164
+ - `mdkg skill list [--tags <tag,tag,...>] [--tags-mode any|all] [--json]`
165
+ - `mdkg skill show <slug> [--meta] [--json]`
166
+ - `mdkg skill search "<query>" [--tags <tag,tag,...>] [--tags-mode any|all] [--json]`
167
+ - `mdkg skill validate [<slug>]`
168
+
169
+ ### Task lifecycle mutation
170
+ - `mdkg task start <id-or-qid> [--ws <alias>] [--run-id <id>] [--note "<text>"]`
171
+ - supports `task`, `bug`, and `test` nodes only
172
+ - sets `status: progress`
173
+ - `mdkg task update <id-or-qid> [...]`
174
+ - supports additive list mutation for `artifacts`, `links`, `refs`, `skills`, `tags`, and `blocked_by`
175
+ - supports scalar replacement for `status` and `priority`
176
+ - `--clear-blocked-by` resets blockers before optional re-add
177
+ - `mdkg task done <id-or-qid> [--checkpoint "<title>"] [...]`
178
+ - supports `task`, `bug`, and `test` nodes only
179
+ - sets `status: done`
180
+ - optional checkpoint creation is explicit only
154
181
 
155
182
  ### Packs (core feature)
156
- - `mdkg pack <id-or-qid> [--depth <n>] [--verbose] [--edges <keys>] [--format md|json|toon|xml] [--out <path>] [--ws <alias>]`
183
+ - `mdkg pack <id-or-qid> [--profile <name>] [--verbose] [--format md|json|toon|xml] [--out <path>] [--ws <alias>]`
184
+ - optional skill inclusion flags:
185
+ - `--skills none|auto|<slug,slug,...>`
186
+ - `--skills-depth meta|full`
187
+ - advanced shaping/debug flags remain supported but de-emphasized:
188
+ - `--depth <n>`
189
+ - `--edges <keys>`
190
+ - `--strip-code`
191
+ - `--max-code-lines <n>`
192
+ - `--max-chars <n>`
193
+ - `--max-lines <n>`
194
+ - `--max-tokens <n>`
195
+ - `--truncation-report <path>`
196
+ - `--stats-out <path>`
157
197
  - `--edges` adds to the default edge set
158
198
  - `--out` writes to a file (create parent dirs; overwrite if exists)
159
199
  - if `--out` is omitted, write to `.mdkg/pack/pack_<kind>_<id>_<timestamp>.<ext>`
160
200
  - short flags supported: `-o`, `-f`, `-v`, `-d`, `-e`, `-w`, `-r`
201
+ - `--profile` is the primary documented alias for `--pack-profile`
202
+ - pack selection includes latest checkpoint by pack-time resolver; index hint `latest_checkpoint_qid` is optimization-only
161
203
 
162
204
  ### Next priority
163
205
  - `mdkg next [<id-or-qid>] [--ws <alias>]`
@@ -169,9 +211,26 @@ Common flags:
169
211
  - creates a `chk-*` node from template
170
212
  - designed as a phase summary / compression node
171
213
 
214
+ ### Events
215
+ - `mdkg event enable [--ws <alias>] [--no-update-gitignore]`
216
+ - creates `.mdkg/work/events/events.jsonl` if missing
217
+ - updates `.gitignore` by default
218
+ - `mdkg event append --kind <kind> --status <ok|error|retry|skipped> --refs <id,...> [...]`
219
+ - appends one JSONL provenance record
220
+ - automatic command-level events append only when event logging is enabled for the target workspace
221
+ - current automatic mutation events:
222
+ - `NODE_CREATED`
223
+ - `SKILL_CREATED`
224
+ - `CHECKPOINT_CREATED`
225
+ - `TASK_STARTED`
226
+ - `TASK_UPDATED`
227
+ - `TASK_DONE`
228
+
172
229
  ### Validation and formatting
173
230
  - `mdkg validate`
174
231
  - strict frontmatter + graph integrity checks (exit code 2 on failure)
232
+ - validates optional node->skill references
233
+ - validates optional `.mdkg/work/events/events.jsonl` record shape when file exists
175
234
  - `mdkg format`
176
235
  - normalize frontmatter formatting and casing
177
236
  - avoid destructive body edits
@@ -36,6 +36,7 @@ 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)
39
40
 
40
41
  ## npm publish safety (required)
41
42
 
@@ -67,14 +68,18 @@ For application builds:
67
68
 
68
69
  ## mdkg init behavior
69
70
 
70
- `mdkg init` MAY offer optional flags to append ignore entries:
71
+ `mdkg init` updates ignore files by default for safety:
72
+
73
+ - `.gitignore` appends `.mdkg/index/`, `.mdkg/pack/`, `.mdkg/work/events/*.jsonl`
74
+ - `.npmignore` appends `.mdkg/`, `.mdkg/index/`, `.mdkg/pack/`
75
+ - `--no-update-ignores` disables these default writes
76
+
77
+ Explicit flags remain available and take precedence:
71
78
 
72
79
  - `--update-gitignore`
73
80
  - `--update-npmignore`
74
81
  - `--update-dockerignore`
75
82
 
76
- In v1, mdkg should default to **not** editing user files without an explicit flag.
77
-
78
83
  ## Index safety
79
84
 
80
85
  - `.mdkg/index/` is generated.
@@ -92,6 +97,7 @@ Workspace-local `.mdkg/` directories (near code) should follow the same rules:
92
97
  ## Summary checklist
93
98
 
94
99
  - ✅ `.mdkg/index/` ignored
100
+ - ✅ `.mdkg/work/events/*.jsonl` ignored when event logging is enabled
95
101
  - ✅ npm publishes only `dist/`, `README.md`, `LICENSE`
96
102
  - ✅ optional `.npmignore` excludes `.mdkg/`
97
103
  - ✅ `.dockerignore` excludes `.mdkg/` when applicable
@@ -10,7 +10,7 @@ relates: []
10
10
  refs: []
11
11
  aliases: []
12
12
  created: 2026-01-06
13
- updated: 2026-01-22
13
+ updated: 2026-03-05
14
14
  ---
15
15
 
16
16
  # Templates and schemas
@@ -65,6 +65,7 @@ Optional tokens (nice-to-have, may be empty):
65
65
  - `{{artifacts}}` (list)
66
66
  - `{{refs}}` (list)
67
67
  - `{{aliases}}` (list)
68
+ - `{{skills}}` (list; work items)
68
69
  - `{{cases}}` (list)
69
70
 
70
71
  ## Frontmatter requirements by type
@@ -90,9 +91,10 @@ All nodes MAY include the following searchable frontmatter lists:
90
91
  List fields SHOULD be written as `[]` when empty.
91
92
  Optional scalar graph fields (like `epic`, `parent`, `prev`, `next`) should be omitted when empty.
92
93
 
93
- Work items (`epic/feat/task/bug/chk/test`):
94
+ Work items (`epic/feat/task/bug/checkpoint/test`):
94
95
  - `status` (enum)
95
96
  - optional `priority` (0..9)
97
+ - optional `skills: [slug, ...]` (kebab-case skill slugs)
96
98
  - optional graph edges: `epic`, `parent`, `relates`, `blocked_by`, `blocks`, `prev`, `next`
97
99
 
98
100
  Decision records (`dec-*`):
@@ -182,5 +184,7 @@ Body headings are strongly recommended for agent usability but should not be har
182
184
 
183
185
  - Frontmatter: strict, hard fail if invalid.
184
186
  - Body headings: warn only (do not break indexing).
187
+ - Node -> skill references in `skills: [...]` are validated against `.mdkg/skills/<slug>/SKILL.md`.
188
+ - `.mdkg/work/events/events.jsonl` is optional; when present, records are schema-validated by `mdkg validate`.
185
189
  - If a template is missing:
186
190
  - `mdkg new` must fail with a helpful error (exit code 3).
@@ -0,0 +1,41 @@
1
+ ---
2
+ name: {{name}}
3
+ description: {{description}}
4
+ {{tags_block}}{{authors_block}}{{links_block}}---
5
+
6
+ # Goal
7
+
8
+ Describe the deterministic outcome this skill should achieve.
9
+
10
+ ## When To Use
11
+
12
+ - Use this skill when the workflow is triggered and the needed outcome is clear.
13
+ - Prefer this skill over ad-hoc instructions when the procedure should be repeatable.
14
+
15
+ ## Inputs
16
+
17
+ - Repo root
18
+ - Current task, node, or user goal
19
+ - Any required references or artifacts
20
+
21
+ ## Steps
22
+
23
+ 1. Confirm the triggering task or need before acting.
24
+ 2. Load only the references and artifacts required for this run.
25
+ 3. Execute the smallest deterministic workflow that satisfies the request.
26
+
27
+ ## Outputs
28
+
29
+ - Deterministic result, patch, or artifact
30
+ - Evidence needed for review or orchestration
31
+
32
+ ## Safety
33
+
34
+ - Prefer repo truth over chat memory.
35
+ - Keep secrets out of skills, references, and generated artifacts.
36
+ - Stop and resolve ambiguity instead of guessing.
37
+
38
+ ## Failure Handling
39
+
40
+ - If required context or policy is unclear, stop and ask before proceeding.
41
+ - If the procedure needs more detail, load the specific reference rather than broad context.
@@ -17,6 +17,7 @@ blocked_by: []
17
17
  blocks: []
18
18
  refs: []
19
19
  aliases: []
20
+ skills: []
20
21
  created: {{created}}
21
22
  updated: {{updated}}
22
23
  ---
@@ -17,6 +17,7 @@ blocked_by: []
17
17
  blocks: []
18
18
  refs: []
19
19
  aliases: []
20
+ skills: []
20
21
  scope: []
21
22
  created: {{created}}
22
23
  updated: {{updated}}
@@ -13,6 +13,7 @@ blocked_by: []
13
13
  blocks: []
14
14
  refs: []
15
15
  aliases: []
16
+ skills: []
16
17
  created: {{created}}
17
18
  updated: {{updated}}
18
19
  ---
@@ -17,6 +17,7 @@ blocked_by: []
17
17
  blocks: []
18
18
  refs: []
19
19
  aliases: []
20
+ skills: []
20
21
  created: {{created}}
21
22
  updated: {{updated}}
22
23
  ---
@@ -17,6 +17,7 @@ blocked_by: []
17
17
  blocks: []
18
18
  refs: []
19
19
  aliases: []
20
+ skills: []
20
21
  created: {{created}}
21
22
  updated: {{updated}}
22
23
  ---
@@ -17,6 +17,7 @@ blocked_by: []
17
17
  blocks: []
18
18
  refs: []
19
19
  aliases: []
20
+ skills: []
20
21
  cases: []
21
22
  created: {{created}}
22
23
  updated: {{updated}}