mdkg 0.3.5 → 0.3.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.
Files changed (49) hide show
  1. package/CHANGELOG.md +97 -2
  2. package/CLI_COMMAND_MATRIX.md +90 -10
  3. package/README.md +54 -7
  4. package/dist/cli.js +222 -13
  5. package/dist/command-contract.json +587 -19
  6. package/dist/commands/bundle.js +2 -0
  7. package/dist/commands/checkpoint.js +139 -1
  8. package/dist/commands/db.js +8 -0
  9. package/dist/commands/format.js +116 -0
  10. package/dist/commands/goal.js +60 -0
  11. package/dist/commands/graph.js +280 -10
  12. package/dist/commands/handoff.js +295 -0
  13. package/dist/commands/mcp.js +656 -0
  14. package/dist/commands/pack.js +3 -1
  15. package/dist/commands/query_output.js +2 -0
  16. package/dist/commands/show.js +8 -0
  17. package/dist/commands/status.js +1 -0
  18. package/dist/commands/task.js +2 -0
  19. package/dist/commands/upgrade.js +61 -0
  20. package/dist/commands/validate.js +162 -3
  21. package/dist/commands/work.js +164 -0
  22. package/dist/core/project_db_queue_contract.js +101 -0
  23. package/dist/graph/edges.js +15 -0
  24. package/dist/graph/frontmatter.js +4 -1
  25. package/dist/graph/indexer.js +8 -0
  26. package/dist/graph/node.js +12 -1
  27. package/dist/graph/sqlite_index.js +2 -0
  28. package/dist/graph/subgraphs.js +2 -0
  29. package/dist/graph/validate_graph.js +5 -0
  30. package/dist/graph/visibility.js +6 -0
  31. package/dist/init/AGENT_START.md +4 -1
  32. package/dist/init/CLI_COMMAND_MATRIX.md +36 -4
  33. package/dist/init/README.md +26 -3
  34. package/dist/init/init-manifest.json +12 -12
  35. package/dist/init/templates/default/bug.md +2 -0
  36. package/dist/init/templates/default/chk.md +3 -0
  37. package/dist/init/templates/default/epic.md +2 -0
  38. package/dist/init/templates/default/feat.md +2 -0
  39. package/dist/init/templates/default/goal.md +3 -0
  40. package/dist/init/templates/default/spike.md +2 -0
  41. package/dist/init/templates/default/task.md +2 -0
  42. package/dist/init/templates/default/test.md +2 -0
  43. package/dist/pack/export_json.js +20 -8
  44. package/dist/pack/export_md.js +15 -4
  45. package/dist/pack/export_xml.js +9 -4
  46. package/dist/pack/metrics.js +12 -4
  47. package/dist/pack/pack.js +9 -1
  48. package/dist/util/argparse.js +1 -0
  49. package/package.json +7 -2
@@ -8,12 +8,14 @@ exports.DEFAULT_FRONTMATTER_KEY_ORDER = [
8
8
  "id",
9
9
  "type",
10
10
  "title",
11
+ "checkpoint_kind",
11
12
  "status",
12
13
  "priority",
13
14
  "goal_state",
14
15
  "goal_condition",
15
16
  "scope_refs",
16
17
  "active_node",
18
+ "last_active_node",
17
19
  "required_skills",
18
20
  "required_checks",
19
21
  "max_iterations",
@@ -60,7 +62,6 @@ exports.DEFAULT_FRONTMATTER_KEY_ORDER = [
60
62
  "severity",
61
63
  "proposal_status",
62
64
  "proposal_kind",
63
- "evidence_refs",
64
65
  "archive_kind",
65
66
  "source_path",
66
67
  "stored_path",
@@ -89,6 +90,8 @@ exports.DEFAULT_FRONTMATTER_KEY_ORDER = [
89
90
  "blocked_by",
90
91
  "blocks",
91
92
  "refs",
93
+ "context_refs",
94
+ "evidence_refs",
92
95
  "aliases",
93
96
  "skills",
94
97
  "cases",
@@ -25,6 +25,8 @@ function normalizeEdges(edges, ws) {
25
25
  relates: edges.relates.map((value) => normalizeEdgeTarget(value, ws)),
26
26
  blocked_by: edges.blocked_by.map((value) => normalizeEdgeTarget(value, ws)),
27
27
  blocks: edges.blocks.map((value) => normalizeEdgeTarget(value, ws)),
28
+ context_refs: (edges.context_refs ?? []).map((value) => normalizeEdgeTarget(value, ws)),
29
+ evidence_refs: (edges.evidence_refs ?? []).map((value) => normalizeEdgeTarget(value, ws)),
28
30
  };
29
31
  }
30
32
  function addReverseEdge(reverse, edgeKey, target, source) {
@@ -118,6 +120,12 @@ function buildIndex(root, config, options = {}) {
118
120
  for (const target of edges.blocks) {
119
121
  addReverseEdge(reverse_edges, "blocks", target, qid);
120
122
  }
123
+ for (const target of edges.context_refs ?? []) {
124
+ addReverseEdge(reverse_edges, "context_refs", target, qid);
125
+ }
126
+ for (const target of edges.evidence_refs ?? []) {
127
+ addReverseEdge(reverse_edges, "evidence_refs", target, qid);
128
+ }
121
129
  }
122
130
  for (const edgeKey of Object.keys(reverse_edges)) {
123
131
  for (const target of Object.keys(reverse_edges[edgeKey])) {
@@ -37,6 +37,7 @@ const GOAL_ATTRIBUTE_KEYS = [
37
37
  "goal_condition",
38
38
  "scope_refs",
39
39
  "active_node",
40
+ "last_active_node",
40
41
  "required_skills",
41
42
  "required_checks",
42
43
  "max_iterations",
@@ -180,6 +181,13 @@ function validateGoalFrontmatter(type, frontmatter, filePath) {
180
181
  throw formatError(filePath, "active_node must be a local id or qid");
181
182
  }
182
183
  }
184
+ const lastActiveNode = optionalString(frontmatter, "last_active_node", filePath);
185
+ if (lastActiveNode !== undefined) {
186
+ const normalized = requireLowercase(lastActiveNode, "last_active_node", filePath);
187
+ if (!(0, id_1.isPortableIdRef)(normalized)) {
188
+ throw formatError(filePath, "last_active_node must be a local id or qid");
189
+ }
190
+ }
183
191
  const scopeRefs = optionalList(frontmatter, "scope_refs", filePath);
184
192
  for (const [index, value] of scopeRefs.entries()) {
185
193
  if (typeof value !== "string" || value.trim().length === 0) {
@@ -334,7 +342,10 @@ function parseNode(content, filePath, options) {
334
342
  throw formatError(filePath, "supersedes must be a dec-# id");
335
343
  }
336
344
  }
337
- const edges = (0, edges_1.extractEdges)(frontmatter, filePath, { allowPortableRefs: true });
345
+ const edges = (0, edges_1.extractEdges)(frontmatter, filePath, {
346
+ allowPortableRefs: true,
347
+ includeSemanticRefs: exports.WORK_TYPES.has(type),
348
+ });
338
349
  const attributes = {
339
350
  ...extractGoalAttributes(type, frontmatter),
340
351
  ...(0, agent_file_types_1.extractAgentAttributes)(type, frontmatter),
@@ -205,6 +205,8 @@ function writeSqliteIndex(options) {
205
205
  ["relates", node.edges.relates],
206
206
  ["blocked_by", node.edges.blocked_by],
207
207
  ["blocks", node.edges.blocks],
208
+ ["context_refs", node.edges.context_refs ?? []],
209
+ ["evidence_refs", node.edges.evidence_refs ?? []],
208
210
  ]) {
209
211
  for (const target of values) {
210
212
  insertEdge.run(node.qid, kind, target);
@@ -278,6 +278,8 @@ function projectOneSubgraph(root, alias, subgraph) {
278
278
  relates: remapTargets(node.edges.relates, qidMap),
279
279
  blocked_by: remapTargets(node.edges.blocked_by, qidMap),
280
280
  blocks: remapTargets(node.edges.blocks, qidMap),
281
+ context_refs: remapTargets(node.edges.context_refs ?? [], qidMap),
282
+ evidence_refs: remapTargets(node.edges.evidence_refs ?? [], qidMap),
281
283
  },
282
284
  source: {
283
285
  imported: true,
@@ -19,6 +19,8 @@ function validateEdgeTargets(index, allowMissing, knownSkillSlugs, externalWorks
19
19
  ["relates", edges.relates],
20
20
  ["blocked_by", edges.blocked_by],
21
21
  ["blocks", edges.blocks],
22
+ ["context_refs", edges.context_refs ?? []],
23
+ ["evidence_refs", edges.evidence_refs ?? []],
22
24
  ];
23
25
  if (edges.epic) {
24
26
  edgeLists.push(["epic", [edges.epic]]);
@@ -34,6 +36,9 @@ function validateEdgeTargets(index, allowMissing, knownSkillSlugs, externalWorks
34
36
  }
35
37
  for (const [edgeKey, values] of edgeLists) {
36
38
  for (const value of values) {
39
+ if ((edgeKey === "context_refs" || edgeKey === "evidence_refs") && (0, refs_1.isUriRef)(value)) {
40
+ continue;
41
+ }
37
42
  const targetNode = nodes[value];
38
43
  if (targetNode &&
39
44
  ["epic", "parent", "prev", "next"].includes(edgeKey) &&
@@ -88,6 +88,12 @@ function collectNodeStringReferences(node) {
88
88
  for (const [index, value] of node.edges.blocks.entries()) {
89
89
  values.push({ field: `blocks[${index}]`, value });
90
90
  }
91
+ for (const [index, value] of (node.edges.context_refs ?? []).entries()) {
92
+ values.push({ field: `context_refs[${index}]`, value });
93
+ }
94
+ for (const [index, value] of (node.edges.evidence_refs ?? []).entries()) {
95
+ values.push({ field: `evidence_refs[${index}]`, value });
96
+ }
91
97
  for (const [index, value] of node.links.entries()) {
92
98
  values.push({ field: `links[${index}]`, value });
93
99
  }
@@ -39,7 +39,10 @@ Agent operating prompt:
39
39
  node:sqlite queue delivery, internal event/receipt/reducer, writer lease/CAS,
40
40
  and queue control migrations. Queue state is delivery infrastructure, not
41
41
  canonical event history; use `mdkg db queue ...` to create, pause, enqueue,
42
- claim, settle, inspect, and drain local queues. Event rows are durable local
42
+ claim, settle, inspect, and drain local queues. Use
43
+ `mdkg db queue contract --json` for the public adapter contract covering
44
+ payload hashing, dedupe, claim order, lease-owner settlement, retry,
45
+ dead-letter, release-expired, pause/resume, snapshot policy, and stats. Event rows are durable local
43
46
  project DB history; receipts, reducers, writer leases, and materializers are
44
47
  internal local helper surfaces, with no public `mdkg db event`,
45
48
  `mdkg db reducer`, `mdkg db lease`, or `mdkg db materializer` CLI yet. Use `mdkg db verify` and `mdkg db stats` for
@@ -17,6 +17,7 @@ Primary commands:
17
17
  - `mdkg list`
18
18
  - `mdkg search`
19
19
  - `mdkg pack`
20
+ - `mdkg handoff create <id-or-qid> [--ws <alias>] [--depth <n>] [--out <path>] [--json]`
20
21
  - `mdkg skill`
21
22
  - `mdkg capability`
22
23
  - `mdkg spec`
@@ -29,10 +30,19 @@ Primary commands:
29
30
  - `mdkg task`
30
31
  - `mdkg validate`
31
32
  - `mdkg status [--json]`
33
+ - `mdkg mcp serve --stdio`
32
34
  - `mdkg fix plan [--family index|refs|ids|all] [--target <id-or-qid>] [--base-ref <ref>] [--json]`
33
35
  - `mdkg fix apply [--family ids] [--target <id-or-qid>] [--base-ref <ref>] [--json]`
34
36
  - `mdkg fix ids [--target <id-or-qid>] [--base-ref <ref>] [--apply] [--json]`
35
37
 
38
+ Semantic refs:
39
+ - work nodes may use `context_refs` for non-executable background and `evidence_refs` for proof/audit refs
40
+ - semantic refs may point at local ids, subgraph qids, or URI refs
41
+ - use `mdkg pack <id> --edges context_refs,evidence_refs` when a handoff should traverse semantic refs
42
+ - use `mdkg handoff create <id-or-qid> --json` for sanitized copy-ready agent handoff prompts
43
+ - handoffs summarize graph state, latest checkpoint, boundaries, required checks, next actions, and raw-marker warnings without copying raw node bodies
44
+ - executable goal queues still belong in goal `scope_refs`
45
+
36
46
  Operator health:
37
47
  - `mdkg status [--json]` is a read-only summary for scripts and agents
38
48
  - reports mdkg version/config, git state, graph/index freshness, selected-goal state, project DB verification summary, and generated cache status
@@ -44,6 +54,15 @@ Operator health:
44
54
  - graph-reference and index/cache findings remain review-only guidance
45
55
  - `fix plan --json` returns a receipt-shaped plan with selected families, risk counts, paths, reason codes, and per-change `apply_supported` metadata
46
56
 
57
+ Local MCP server:
58
+ - `mdkg mcp serve --stdio`
59
+ - starts one local Model Context Protocol server bound to the selected `--root`
60
+ - stdio is the only transport in this release; no HTTP listener is opened
61
+ - exposes read-only tools for status, workspace/subgraph list, search, show, in-memory pack, goal current/next, and validate
62
+ - exposes no task, goal activation, graph import, queue, event, archive, format, SQL, shell, arbitrary file-read, filesystem mutation, environment, or secret-access tools
63
+ - use `--root <path>` when launching from outside the repo
64
+ - stdout is reserved for newline-delimited JSON-RPC MCP messages
65
+
47
66
  Index backend:
48
67
  - fresh mdkg workspaces default to `index.backend: sqlite`
49
68
  - `.mdkg/index/mdkg.sqlite` is rebuildable and commit-eligible when intentionally tracked
@@ -61,6 +80,7 @@ Project database commands:
61
80
  - `mdkg db verify [--json]`
62
81
  - `mdkg db stats [--json]`
63
82
  - `mdkg db queue create|pause|resume|enqueue|claim|ack|fail|dead-letter|release-expired|stats|list|show ... [--json]`
83
+ - `mdkg db queue contract [--json]`
64
84
  - `mdkg db snapshot seal [--queue-policy drain|paused] [--json]`
65
85
  - `mdkg db snapshot verify [--json]`
66
86
  - `mdkg db snapshot status [--json]`
@@ -77,6 +97,9 @@ Project database commands:
77
97
  in the configured migration table
78
98
  - `mdkg db queue ...` exposes durable local delivery operations backed by
79
99
  node:sqlite; queue rows are delivery state, not canonical event history
100
+ - `mdkg db queue contract --json` returns the public adapter contract for
101
+ payload hashes, dedupe, claim order, lease-owner settlement, retries,
102
+ dead-letter, release-expired, pause/resume, snapshot policy, and stats
80
103
  - paused queues reject enqueue and claim, but ack/fail/dead-letter and
81
104
  release-expired remain available so leased work can settle
82
105
  - event tables are durable local history for project DB state transitions;
@@ -95,7 +118,9 @@ Project database commands:
95
118
  - active `.mdkg/db/runtime/` files and `.mdkg/db` WAL/SHM/journal/lock/temp files are ignored by default
96
119
 
97
120
  Validation commands:
98
- - `mdkg validate [--out <path>] [--quiet] [--json]`
121
+ - `mdkg validate [--out <path>] [--quiet] [--changed-only] [--json]`
122
+ - `--changed-only` filters warning presentation to changed `.mdkg` files while full graph errors still run
123
+ - JSON receipts include `warning_diagnostics` with warning ids, categories, severity, paths, refs, and remediation text
99
124
 
100
125
  Node creation commands:
101
126
  - `mdkg new <type> "<title>" [options] [--json]`
@@ -136,11 +161,12 @@ Event log commands:
136
161
  Task mutation commands:
137
162
  - `mdkg task start <id-or-qid> [--ws <alias>] [--run-id <id>] [--note "<text>"] [--json]`
138
163
  - `mdkg task update <id-or-qid> [options] [--json]`
139
- - `mdkg task done <id-or-qid> [--checkpoint "<title>"] [options] [--json]`
164
+ - `mdkg task done <id-or-qid> [--checkpoint "<title>"] [--checkpoint-kind implementation|test-proof|goal-closeout|audit|handoff] [options] [--json]`
140
165
  - task commands support task-like `feat`, `task`, `bug`, `test`, and `spike` nodes
141
166
 
142
167
  Checkpoint commands:
143
- - `mdkg checkpoint new <title> [--ws <alias>] [--json]`
168
+ - `mdkg checkpoint new <title> [--kind implementation|test-proof|goal-closeout|audit|handoff] [--ws <alias>] [--json]`
169
+ - checkpoint kinds render bodies with command evidence, pass/fail status, known warnings, changed surfaces, boundaries, and follow-up refs
144
170
 
145
171
  Agent bootstrap:
146
172
  - `mdkg init --agent`
@@ -210,6 +236,7 @@ Graph clone, fork, and template import:
210
236
  - `mdkg graph clone <source-bundle-or-mdkg-dir> --target <path> [--json]`
211
237
  - `mdkg graph fork <source-bundle-or-mdkg-dir> --target <path> [--start-goal <goal-id>] [--json]`
212
238
  - `mdkg graph import-template <source-bundle-or-mdkg-dir> [--start-goal <goal-id>] [--select-goal] [--id-prefix <prefix>] [--dry-run] [--apply] [--json]`
239
+ - `mdkg graph refs <id-or-qid> [--ws <alias>] [--json]`
213
240
  - `graph clone` and `graph fork` preserve IDs because the target is a separate graph namespace
214
241
  - clone/fork targets must be empty or absent and stay under the current mdkg root
215
242
  - live directory sources are never mutated; clone/fork refuses targets nested inside a live source directory
@@ -218,7 +245,9 @@ Graph clone, fork, and template import:
218
245
  - `graph import-template` defaults to dry-run unless `--apply` is supplied
219
246
  - same-repo template import rewrites canonical numeric IDs to the next unused ID by type prefix and rewrites structured refs plus safe body-local id/qid mentions
220
247
  - colliding semantic template IDs require `--id-prefix`
221
- - `--select-goal` requires `--start-goal` and writes selected-goal state only after apply validation
248
+ - `--select-goal` requires `--start-goal`; on apply it activates the imported start goal, pauses competing active root goals, validates, then writes selected-goal state
249
+ - importing active template goals without `--select-goal` fails before writing when it would create multiple active root goals
250
+ - `graph refs` is read-only and summarizes inbound/outbound scope, context, evidence, blocker, related, and structural refs across local and subgraph qids
222
251
  - subgraphs remain read-only bundle projections for orchestration context; use `graph clone|fork|import-template` when authored graph state should be created
223
252
 
224
253
  Subgraph orchestration:
@@ -252,11 +281,13 @@ Work semantic mirrors:
252
281
  - `mdkg work receipt verify <id-or-qid> [--json]`
253
282
  - `mdkg work receipt update <id-or-qid> [--receipt-status <status>] [--add-artifacts <...>] [--add-proof-refs <...>] [--add-attestation-refs <...>] [--json]`
254
283
  - `mdkg work artifact add <order-or-receipt-id-or-qid> <file> [--id <archive.id>] [--kind source|artifact] [--json]`
284
+ - `mdkg work validate [<id-or-qid>] [--type spec|work|work_order|receipt|feedback|dispute|proposal] [--json]`
255
285
  - `work trigger` accepts a `WORK.md` ref directly or a `SPEC.md` capability ref with exactly one resolvable work contract; it creates a submitted order mirror and never executes work
256
286
  - example: `mdkg work trigger work.example --id order.example-1 --requester user://example --json`
257
287
  - `work trigger --enqueue <queue>` requires a valid project DB plus an explicitly created active queue, creates a submitted order mirror, and enqueues a local delivery message without executing work
258
288
  - `work order status` is read-only and reports deterministic order state plus linked receipts
259
289
  - `work receipt verify` is read-only and reports linkage, evidence, archive ref, hash, outcome, and redaction-policy checks
290
+ - `work validate` is read-only and reports typed diagnostics for agent workflow mirrors; obvious raw secret, prompt, token, or payload markers are warnings, not hard failures
260
291
  - work commands mutate mdkg semantic mirror files only; production order, receipt, feedback, dispute, payment, ledger, marketplace inventory, fulfillment, and execution state remains canonical outside mdkg
261
292
  - do not store raw secrets, credentials, live payment state, ledger mutations, or canonical marketplace state in work mirrors
262
293
  - `artifact://...` refs identify external/runtime-managed artifacts; `archive://...` refs identify committed mdkg archive sidecars
@@ -288,6 +319,7 @@ Goal nodes:
288
319
  - `goal activate` makes one local root goal active, pauses competing local active goals in the same workspace, and writes selected-goal state
289
320
  - `goal archive` marks a superseded historical goal archived so it remains readable but not actionable
290
321
  - `goal next` is read-only; use `goal claim` to set `active_node`
322
+ - `goal done` preserves the final actionable item as `last_active_node` and removes actionable `active_node`
291
323
  - `mdkg goal evaluate` is report-only and never runs commands from `required_checks`
292
324
  - skill improvements discovered during normal goal execution should be recorded as candidates or proposals unless the active node is skill-maintenance
293
325
 
@@ -25,6 +25,7 @@ mdkg new task "..." --status todo --priority 1
25
25
  mdkg search "..."
26
26
  mdkg show <id>
27
27
  mdkg pack <id>
28
+ mdkg handoff create <id-or-qid> --json
28
29
  mdkg capability search "..."
29
30
  mdkg spec list --json
30
31
  mdkg archive list
@@ -36,7 +37,14 @@ mdkg fix plan --json
36
37
  mdkg validate
37
38
  ```
38
39
 
39
- This repo is already initialized. Use `mdkg upgrade` to preview safe scaffold updates, `mdkg index` to create or refresh generated graph/skill/capability/subgraph and SQLite caches after init, `mdkg new` to create work, `mdkg new goal "..."` plus `mdkg goal activate/current/next/claim/evaluate` for recursive long-running objectives, `mdkg search`/`mdkg show` to inspect graph state, `mdkg capability ...` to inspect cached skill/spec/work/core/design capabilities, `mdkg spec ...` for focused optional SPEC records, `mdkg capability resolve ...` to rank local and subgraph capabilities, `mdkg archive ...` to register source/artifact sidecars, `mdkg work ...` to create work contract/order/receipt semantic mirrors and deterministic trigger/verification records, `mdkg bundle ...` to create full graph snapshot bundles, `mdkg graph ...` to clone/fork/import authored graph templates, `mdkg subgraph ...` to register read-only child graph planning views, `mdkg pack <id>` to build deterministic context, and `mdkg validate` before closeout.
40
+ This repo is already initialized. Use `mdkg upgrade` to preview safe scaffold updates, `mdkg index` to create or refresh generated graph/skill/capability/subgraph and SQLite caches after init, `mdkg new` to create work, `mdkg new goal "..."` plus `mdkg goal activate/current/next/claim/evaluate` for recursive long-running objectives, `mdkg search`/`mdkg show` to inspect graph state, `mdkg capability ...` to inspect cached skill/spec/work/core/design capabilities, `mdkg spec ...` for focused optional SPEC records, `mdkg capability resolve ...` to rank local and subgraph capabilities, `mdkg archive ...` to register source/artifact sidecars, `mdkg work ...` to create work contract/order/receipt semantic mirrors and deterministic trigger/verification records, `mdkg bundle ...` to create full graph snapshot bundles, `mdkg graph ...` to clone/fork/import authored graph templates, `mdkg subgraph ...` to register read-only child graph planning views, `mdkg pack <id>` to build deterministic context, `mdkg handoff create <id-or-qid> --json` to create a sanitized copy-ready agent handoff prompt, and `mdkg validate` before closeout.
41
+
42
+ `mdkg handoff create` summarizes goal/work state, included pack nodes, latest
43
+ checkpoint, boundaries, required checks, next actions, and raw-content marker
44
+ warnings without copying raw node bodies into the prompt. Use `--out` to write
45
+ the handoff artifact inside the repo root.
46
+
47
+ For large historical graphs, `mdkg validate --changed-only --json` keeps warning review focused on changed `.mdkg` files while full graph errors still run. `mdkg format --headings --dry-run --json` previews missing recommended heading additions before `--apply`.
40
48
 
41
49
  Use `mdkg status --json` for a read-only operator summary of Git, graph,
42
50
  selected-goal, project DB, and generated-cache health before mutating work. Use
@@ -124,7 +132,11 @@ infrastructure, not canonical event history; use `mdkg db queue ...` to create,
124
132
  pause, enqueue, claim, settle, inspect, and drain local queues. Event rows are
125
133
  durable local project DB history; receipts, reducers, writer leases, and
126
134
  materializers are internal local helper surfaces, with no public `mdkg db event`,
127
- `mdkg db reducer`, `mdkg db lease`, or `mdkg db materializer` CLI yet. Use `mdkg db verify` for non-mutating health checks and
135
+ `mdkg db reducer`, `mdkg db lease`, or `mdkg db materializer` CLI yet.
136
+ `mdkg db queue contract --json` returns the read-only public adapter contract
137
+ for canonical payload hashing, dedupe keys, oldest-ready claim order,
138
+ lease-owner checked settlement, retry/dead-letter behavior, release-expired,
139
+ pause/resume, snapshot queue policy, and stats. Use `mdkg db verify` for non-mutating health checks and
128
140
  `mdkg db stats` for table counts, DB size, migration state, and receipt-file
129
141
  counts. Use `mdkg db snapshot seal` to create an opt-in sealed checkpoint under
130
142
  `.mdkg/db/state`; the default queue policy is drain, and
@@ -173,7 +185,7 @@ mdkg graph import-template templates/website-template-mdkg --start-goal goal-1 -
173
185
  mdkg graph import-template templates/website-template-mdkg --start-goal goal-1 --select-goal --apply --json
174
186
  ```
175
187
 
176
- `graph clone` and `graph fork` preserve IDs because the target is a separate graph namespace. `graph import-template` rewrites canonical numeric IDs for same-repo imports and requires `--id-prefix` for colliding semantic IDs. Subgraphs remain read-only planning views; use `mdkg graph ...` when authored graph state should be created.
188
+ `graph clone` and `graph fork` preserve IDs because the target is a separate graph namespace. `graph import-template` rewrites canonical numeric IDs for same-repo imports and requires `--id-prefix` for colliding semantic IDs. With `--select-goal --apply`, import-template activates the rewritten imported start goal, pauses competing active root goals, validates the graph, and then writes selected-goal state. Subgraphs remain read-only planning views; use `mdkg graph ...` when authored graph state should be created.
177
189
 
178
190
  Register child bundle snapshots as read-only subgraphs with:
179
191
 
@@ -193,6 +205,14 @@ Use `mdkg subgraph materialize child_repo --target .mdkg/subgraphs --gitignore -
193
205
 
194
206
  Subgraph nodes use the subgraph alias as their qid prefix and can be inspected or packed, but mutations must happen in the owning child repo.
195
207
 
208
+ Launch a local read-only MCP server when an MCP-capable agent should inspect this graph without receiving mutation tools:
209
+
210
+ ```bash
211
+ mdkg mcp serve --stdio --root /path/to/repo
212
+ ```
213
+
214
+ The MCP server is stdio-only in this release. It exposes read-only tools for status, workspace/subgraph listing, search, show, in-memory pack generation, goal current/next, and validation. It does not expose task updates, goal activation, graph import, queue, event, archive, format, SQL, shell, arbitrary file reads, filesystem mutation, environment variables, or secret access. Future mutation allowlists remain design work.
215
+
196
216
  ## Archive and Work Mirrors
197
217
 
198
218
  Archive source/artifact files with:
@@ -227,6 +247,9 @@ Update and artifact commands accept local ids or local qids; subgraph qids are r
227
247
  `mdkg work trigger` creates a deterministic submitted `WORK_ORDER.md` from a
228
248
  WORK contract or a SPEC with exactly one resolvable work contract. `mdkg work
229
249
  order status` and `mdkg work receipt verify` are read-only review helpers.
250
+ `mdkg work validate [<id-or-qid>] [--type spec|work|work_order|receipt|feedback|dispute|proposal] --json`
251
+ is a read-only focused validator for agent workflow mirrors with typed diagnostics
252
+ and raw secret, prompt, token, or payload marker warnings.
230
253
  `mdkg work trigger --enqueue <queue>` optionally writes a local project DB queue
231
254
  delivery message after the queue has been explicitly created and is active; it
232
255
  still does not execute work.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schema_version": 1,
3
3
  "tool": "mdkg",
4
- "mdkg_version": "0.3.5",
4
+ "mdkg_version": "0.3.7",
5
5
  "files": [
6
6
  {
7
7
  "path": ".mdkg/config.json",
@@ -61,7 +61,7 @@
61
61
  {
62
62
  "path": ".mdkg/README.md",
63
63
  "category": "mdkg_doc",
64
- "sha256": "a3b059cb0ea5625f9888fbcee52ddf13491e033046d8c3f3846574d8667ad234"
64
+ "sha256": "5a03de7c4602936e6108b3e8f2916ead8320a4020c335ea9cfd083d59eabf083"
65
65
  },
66
66
  {
67
67
  "path": ".mdkg/skills/build-pack-and-execute-task/SKILL.md",
@@ -91,12 +91,12 @@
91
91
  {
92
92
  "path": ".mdkg/templates/default/bug.md",
93
93
  "category": "template",
94
- "sha256": "88e3f8d67aa3b2156be2006bd1c8139b7b16b46f2c05a4f4d840b3746a40f9c5"
94
+ "sha256": "27ed977c67030befccfc469d9db257fadc9ad5331963e259c489ba03754194cb"
95
95
  },
96
96
  {
97
97
  "path": ".mdkg/templates/default/chk.md",
98
98
  "category": "template",
99
- "sha256": "15f793e422009c76f8bda72c3609157acd7f03762d9c9bdb096c4aa2e2c3fb89"
99
+ "sha256": "9e32f46665fc7cc582c4695772f5d99799f574229e740fa8892c7b9e75324de9"
100
100
  },
101
101
  {
102
102
  "path": ".mdkg/templates/default/dec.md",
@@ -116,12 +116,12 @@
116
116
  {
117
117
  "path": ".mdkg/templates/default/epic.md",
118
118
  "category": "template",
119
- "sha256": "56697b69af027fe08c00866c0c0670f7d7e2a0857803bd4aabb99f4761311879"
119
+ "sha256": "0f515c046064771e3f9abaa3689634bfae3ffcf2ffe9825e8e3b7dc15c24fc50"
120
120
  },
121
121
  {
122
122
  "path": ".mdkg/templates/default/feat.md",
123
123
  "category": "template",
124
- "sha256": "99cfdd97b40b119cf899fd766d816c07b7daaafd8ec8e70e6c6de5c0d37f581c"
124
+ "sha256": "25c04ce41d8cf519d5c3009219eeed48f76c23600c6b7999264831aa92cefc4b"
125
125
  },
126
126
  {
127
127
  "path": ".mdkg/templates/default/feedback.md",
@@ -131,7 +131,7 @@
131
131
  {
132
132
  "path": ".mdkg/templates/default/goal.md",
133
133
  "category": "template",
134
- "sha256": "710252d8a2dc35be71661d6988007af127052fa8ad24b1fb00374c975ae117a2"
134
+ "sha256": "8f984580aefd02b34639fa7f5d2a834662656bbf2e12f14a285f5ae31aff74ce"
135
135
  },
136
136
  {
137
137
  "path": ".mdkg/templates/default/prd.md",
@@ -166,17 +166,17 @@
166
166
  {
167
167
  "path": ".mdkg/templates/default/spike.md",
168
168
  "category": "template",
169
- "sha256": "ac805dca7e6edcdad35e24b615dc7399cbae3bed676b9da57e24a393eb425245"
169
+ "sha256": "56e881fad20bd4fda8ae53cc78ce6f30f4dacd083f4eda40f9f2ba3723d52e0e"
170
170
  },
171
171
  {
172
172
  "path": ".mdkg/templates/default/task.md",
173
173
  "category": "template",
174
- "sha256": "f6385dd4f56f1c8df164ac3e79d82c5a3fde3f952dc9cdc78c0b8077caa62277"
174
+ "sha256": "2db6e56298b22e9da9121e2ac31f2fd68e370211218c5bcaae1014a9e63b7cde"
175
175
  },
176
176
  {
177
177
  "path": ".mdkg/templates/default/test.md",
178
178
  "category": "template",
179
- "sha256": "bdae53e5cb4bd77712da155bbcfc24409ced8162c977e6bc478a9d1e695ddef7"
179
+ "sha256": "59484d4cf397707d738ccbc2f788c08eab58d3d73f37591f7bde8f1533b828ce"
180
180
  },
181
181
  {
182
182
  "path": ".mdkg/templates/default/work_order.md",
@@ -246,7 +246,7 @@
246
246
  {
247
247
  "path": "AGENT_START.md",
248
248
  "category": "startup_doc",
249
- "sha256": "46e734b6eae92eb957c3e29fb4d206e4be3fd6d32dd00e888e01a0dc75979428"
249
+ "sha256": "d305f0e61c2401814bc51067c8129a3ad131c6217692038bc7ffad012c305451"
250
250
  },
251
251
  {
252
252
  "path": "AGENTS.md",
@@ -261,7 +261,7 @@
261
261
  {
262
262
  "path": "CLI_COMMAND_MATRIX.md",
263
263
  "category": "startup_doc",
264
- "sha256": "220b461553310a8248d53f01fae132d4ca433659da679e401e3ce6abe2592cb7"
264
+ "sha256": "84de4e06dd4d6d2b316e17c37bebcec373f1a9500d7107c8dd0ce5ca15048b7d"
265
265
  },
266
266
  {
267
267
  "path": "llms.txt",
@@ -16,6 +16,8 @@ relates: []
16
16
  blocked_by: []
17
17
  blocks: []
18
18
  refs: []
19
+ context_refs: []
20
+ evidence_refs: []
19
21
  aliases: []
20
22
  skills: []
21
23
  created: {{created}}
@@ -2,6 +2,7 @@
2
2
  id: {{id}}
3
3
  type: checkpoint
4
4
  title: {{title}}
5
+ checkpoint_kind: {{checkpoint_kind}}
5
6
  status: {{status}}
6
7
  priority: {{priority}}
7
8
  epic: {{epic}}
@@ -16,6 +17,8 @@ relates: []
16
17
  blocked_by: []
17
18
  blocks: []
18
19
  refs: []
20
+ context_refs: []
21
+ evidence_refs: []
19
22
  aliases: []
20
23
  skills: []
21
24
  scope: []
@@ -12,6 +12,8 @@ relates: []
12
12
  blocked_by: []
13
13
  blocks: []
14
14
  refs: []
15
+ context_refs: []
16
+ evidence_refs: []
15
17
  aliases: []
16
18
  skills: []
17
19
  created: {{created}}
@@ -16,6 +16,8 @@ relates: []
16
16
  blocked_by: []
17
17
  blocks: []
18
18
  refs: []
19
+ context_refs: []
20
+ evidence_refs: []
19
21
  aliases: []
20
22
  skills: []
21
23
  created: {{created}}
@@ -8,6 +8,7 @@ goal_state: {{goal_state}}
8
8
  goal_condition: {{goal_condition}}
9
9
  scope_refs: []
10
10
  active_node: {{active_node}}
11
+ last_active_node: {{last_active_node}}
11
12
  required_skills: []
12
13
  required_checks: []
13
14
  max_iterations: {{max_iterations}}
@@ -24,6 +25,8 @@ relates: []
24
25
  blocked_by: []
25
26
  blocks: []
26
27
  refs: []
28
+ context_refs: []
29
+ evidence_refs: []
27
30
  aliases: []
28
31
  skills: []
29
32
  created: {{created}}
@@ -16,6 +16,8 @@ relates: []
16
16
  blocked_by: []
17
17
  blocks: []
18
18
  refs: []
19
+ context_refs: []
20
+ evidence_refs: []
19
21
  aliases: []
20
22
  skills: []
21
23
  created: {{created}}
@@ -16,6 +16,8 @@ relates: []
16
16
  blocked_by: []
17
17
  blocks: []
18
18
  refs: []
19
+ context_refs: []
20
+ evidence_refs: []
19
21
  aliases: []
20
22
  skills: []
21
23
  created: {{created}}
@@ -16,6 +16,8 @@ relates: []
16
16
  blocked_by: []
17
17
  blocks: []
18
18
  refs: []
19
+ context_refs: []
20
+ evidence_refs: []
19
21
  aliases: []
20
22
  skills: []
21
23
  cases: []
@@ -2,18 +2,30 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.exportJson = exportJson;
4
4
  function buildFrontmatter(node) {
5
+ const links = node.links ?? [];
6
+ const artifacts = node.artifacts ?? [];
7
+ const refs = node.refs ?? [];
8
+ const contextRefs = node.context_refs ?? [];
9
+ const evidenceRefs = node.evidence_refs ?? [];
10
+ const aliases = node.aliases ?? [];
5
11
  const frontmatter = {};
6
- if (node.links.length > 0) {
7
- frontmatter.links = node.links;
12
+ if (links.length > 0) {
13
+ frontmatter.links = links;
8
14
  }
9
- if (node.artifacts.length > 0) {
10
- frontmatter.artifacts = node.artifacts;
15
+ if (artifacts.length > 0) {
16
+ frontmatter.artifacts = artifacts;
11
17
  }
12
- if (node.refs.length > 0) {
13
- frontmatter.refs = node.refs;
18
+ if (refs.length > 0) {
19
+ frontmatter.refs = refs;
14
20
  }
15
- if (node.aliases.length > 0) {
16
- frontmatter.aliases = node.aliases;
21
+ if (contextRefs.length > 0) {
22
+ frontmatter.context_refs = contextRefs;
23
+ }
24
+ if (evidenceRefs.length > 0) {
25
+ frontmatter.evidence_refs = evidenceRefs;
26
+ }
27
+ if (aliases.length > 0) {
28
+ frontmatter.aliases = aliases;
17
29
  }
18
30
  for (const [key, value] of Object.entries(node.attributes ?? {})) {
19
31
  frontmatter[key] = value;
@@ -48,6 +48,11 @@ function renderHeader(meta, nodes) {
48
48
  return lines;
49
49
  }
50
50
  function renderNode(node) {
51
+ const links = node.links ?? [];
52
+ const artifacts = node.artifacts ?? [];
53
+ const refs = node.refs ?? [];
54
+ const contextRefs = node.context_refs ?? [];
55
+ const evidenceRefs = node.evidence_refs ?? [];
51
56
  const lines = [];
52
57
  lines.push(`## ${node.qid}`);
53
58
  lines.push(`qid: ${node.qid}`);
@@ -60,10 +65,16 @@ function renderNode(node) {
60
65
  lines.push(`priority: ${node.priority}`);
61
66
  }
62
67
  lines.push(`path: ${node.path}`);
63
- lines.push(formatList("links", node.links));
64
- lines.push(formatList("artifacts", node.artifacts));
65
- if (node.refs.length > 0) {
66
- lines.push(formatList("refs", node.refs));
68
+ lines.push(formatList("links", links));
69
+ lines.push(formatList("artifacts", artifacts));
70
+ if (refs.length > 0) {
71
+ lines.push(formatList("refs", refs));
72
+ }
73
+ if (contextRefs.length > 0) {
74
+ lines.push(formatList("context_refs", contextRefs));
75
+ }
76
+ if (evidenceRefs.length > 0) {
77
+ lines.push(formatList("evidence_refs", evidenceRefs));
67
78
  }
68
79
  for (const [key, value] of Object.entries(node.attributes ?? {})) {
69
80
  lines.push(formatAttribute(key, value));
@@ -21,6 +21,9 @@ function listItems(tag, itemTag, items, indent) {
21
21
  lines.push(`${indent}</${tag}>`);
22
22
  return lines;
23
23
  }
24
+ function listValues(items) {
25
+ return items ?? [];
26
+ }
24
27
  function attributeLines(key, value, indent) {
25
28
  if (Array.isArray(value)) {
26
29
  return listItems(key, "item", value, indent);
@@ -83,10 +86,12 @@ function exportXml(pack) {
83
86
  }
84
87
  lines.push(` <path>${escapeXml(node.path)}</path>`);
85
88
  lines.push(" <frontmatter>");
86
- lines.push(...listItems("links", "link", node.links, " "));
87
- lines.push(...listItems("artifacts", "artifact", node.artifacts, " "));
88
- lines.push(...listItems("refs", "ref", node.refs, " "));
89
- lines.push(...listItems("aliases", "alias", node.aliases, " "));
89
+ lines.push(...listItems("links", "link", listValues(node.links), " "));
90
+ lines.push(...listItems("artifacts", "artifact", listValues(node.artifacts), " "));
91
+ lines.push(...listItems("refs", "ref", listValues(node.refs), " "));
92
+ lines.push(...listItems("context_refs", "context_ref", listValues(node.context_refs), " "));
93
+ lines.push(...listItems("evidence_refs", "evidence_ref", listValues(node.evidence_refs), " "));
94
+ lines.push(...listItems("aliases", "alias", listValues(node.aliases), " "));
90
95
  for (const [key, value] of Object.entries(node.attributes ?? {})) {
91
96
  lines.push(...attributeLines(key, value, " "));
92
97
  }