mdkg 0.5.0 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -8,6 +8,45 @@ mdkg is pre-v1 public alpha software. Command, graph, cache, bundle, and DAL con
8
8
 
9
9
  ## Unreleased
10
10
 
11
+ ## 0.5.2 - 2026-07-15
12
+
13
+ ### Added
14
+
15
+ - Added `mdkg git materialize --request <file|-> --json` with strict
16
+ `mdkg.git.materialize.request.v1` parsing, full-ref accepted-revision
17
+ verification, SHA-1/SHA-256 support, bounded auth capability checks, explicit
18
+ submodule/project-memory policies, and atomic contained publication.
19
+ - Added bounded `mdkg.git.materialize.receipt.v1` success and failure evidence,
20
+ installed-tarball consumer coverage, generated CLI contract metadata, and a
21
+ dedicated docs.mdkg.dev advanced-alpha guide.
22
+
23
+ ### Security
24
+
25
+ - Disabled Git prompts, repository hooks, push, and recursive submodules during
26
+ materialization; candidate project-memory validation does not index or execute
27
+ repository-controlled scripts, hooks, skills, or commands.
28
+ - Redacted credentials, environment values, helper output, socket paths, raw Git
29
+ output, repository contents, and absolute local paths from materialization
30
+ receipts while preserving bounded identity, policy, destination, and cleanup
31
+ evidence.
32
+
33
+ ## 0.5.1 - 2026-07-14
34
+
35
+ ### Changed
36
+
37
+ - Archive compression now derives writable ownership from enabled local
38
+ workspaces. `archive compress --all --ws <local-alias>` limits bulk selection,
39
+ and exact workspace-qualified archive qids are supported for direct targets.
40
+ - Archive compression JSON receipts preserve existing fields and add selected
41
+ workspace and read-only imported-projection exclusion evidence.
42
+
43
+ ### Fixed
44
+
45
+ - Fixed `archive compress --all` traversing imported subgraph ZIP-fragment paths
46
+ and potentially mutating earlier local archives before a later invalid target
47
+ failed. Imported archives remain discoverable but fail closed for direct
48
+ compression, and the complete local selection is preflighted before writes.
49
+
11
50
  ## 0.5.0 - 2026-07-11
12
51
 
13
52
  ### Added
@@ -1,7 +1,7 @@
1
1
  # CLI Command Matrix
2
2
 
3
- as_of: 2026-07-11
4
- package_version_in_source: 0.5.0
3
+ as_of: 2026-07-15
4
+ package_version_in_source: 0.5.2
5
5
  source: live help from `src/cli.ts`, runtime command handlers, and `dec-15`..`dec-18`
6
6
  status: canonical single-source command and flag reference for mdkg
7
7
 
@@ -657,9 +657,9 @@ Usage:
657
657
  - `mdkg archive show <id-or-archive-uri> [--ws <alias>] [--json]`
658
658
  - `mdkg archive verify [id-or-archive-uri] [--json]`
659
659
  - `mdkg archive verify [id-or-archive-uri] [--ws <alias>] [--json]`
660
- - `mdkg archive compress <id-or-archive-uri|--all> [--json]`
661
- - `mdkg archive compress <id-or-archive-uri> [--ws <alias>] [--json]`
662
- - `mdkg archive compress --all [--json]`
660
+ - `mdkg archive compress <id-or-archive-uri-or-qid|--all> [--ws <local-alias>] [--json]`
661
+ - `mdkg archive compress <id-or-archive-uri-or-qid> [--ws <local-alias>] [--json]`
662
+ - `mdkg archive compress --all [--ws <local-alias>] [--json]`
663
663
 
664
664
  Fields:
665
665
  - archive sidecars use `type: archive`
@@ -673,6 +673,18 @@ Notes:
673
673
  - archive visibility defaults to `private`
674
674
  - `archive://<archive.id>` refs are validated against local archive sidecars
675
675
  - `archive verify` and `validate` both check the ZIP hash, ZIP readability, payload SHA-256, and payload byte size
676
+ - archive compression is owned exclusively by enabled local workspaces; imported
677
+ archive projections remain visible to list/show/search but are read-only
678
+ - `archive compress --all` selects every locally writable archive, while
679
+ `--all --ws <local-alias>` limits selection to one enabled local workspace
680
+ - direct workspace-qualified qids such as `root:archive.example` are supported;
681
+ imported qids and `--ws <imported-alias>` fail before filesystem path
682
+ construction with source-workspace and bundle-refresh guidance
683
+ - compression preflights ownership, identity, containment, symlinks, raw input,
684
+ and destinations for the complete selected set before the first write
685
+ - JSON keeps `action`, `count`, and `archives`, and adds
686
+ `selection: { requested_workspace, selected_workspaces,
687
+ excluded_read_only: [{ workspace, qid, reason }] }`
676
688
  - `archive verify` passes when the raw local source file is missing but the committed sidecar and ZIP cache are valid
677
689
  - generated raw source copies live under `.mdkg/archive/**/source/` and are ignored by default
678
690
  - `doctor` warns when archive ZIP caches exceed `archive.large_cache_warning_bytes` (default `26214400`; `0` disables)
@@ -767,12 +779,14 @@ JSON receipts:
767
779
 
768
780
  When to use:
769
781
  - inspect the current Git-backed mdkg project and accepted revision evidence
782
+ - materialize a strict caller-selected Git ref only after commit, tree, and policy verification
770
783
  - clone or fetch real Git remotes through the system Git CLI with external auth
771
784
  - close out mdkg state to static receipts before an agent checkpoint commit
772
785
  - prove push readiness before any approval-gated real remote push
773
786
 
774
787
  Usage:
775
788
  - `mdkg git inspect [--json]`
789
+ - `mdkg git materialize --request <file|-> [--json]`
776
790
  - `mdkg git clone <repository-ref> --target <path> [--branch <name>] [--json]`
777
791
  - `mdkg git fetch [--remote <name>] [--branch <name>] [--json]`
778
792
  - `mdkg git closeout [--queue-policy drain|paused] [--output <path>] [--json]`
@@ -782,6 +796,7 @@ Usage:
782
796
  - `mdkg git push --remote <name> --branch <name> [--stage-all --message <text>] [--json]`
783
797
 
784
798
  Flags:
799
+ - `--request <file|->`
785
800
  - `--target <path>`
786
801
  - `--branch <name>`
787
802
  - `--remote <name>`
@@ -796,6 +811,10 @@ Notes:
796
811
  - v1 uses the system Git CLI; authentication stays external through credential helpers, SSH, `gh`, CI/runtime env, or shell state
797
812
  - mdkg rejects repository refs and push remotes with embedded URL credentials; inspected remotes with userinfo are redacted before receipts are printed
798
813
  - `git inspect` is read-only and emits sanitized source descriptors plus accepted-revision hashes
814
+ - `git materialize` accepts only `mdkg.git.materialize.request.v1` JSON, rejects unsafe input before Git, verifies a full ref and exact commit/tree, and atomically renames a same-parent temporary tree into a contained destination
815
+ - materialization disables prompts, repository hooks, push, and recursive submodules; project-memory checks do not index or execute repository-controlled behavior
816
+ - `deny|ignore` controls submodule acceptance and `required|optional|forbidden` controls project-memory presence
817
+ - materialization receipts never retain credentials, environment values, helper output, socket paths, raw Git output, repository contents, or absolute local paths
799
818
  - `git clone` writes only to an empty or absent contained `--target`; use `mdkg graph clone|fork` for bundle/template graph transport
800
819
  - `git closeout` validates mdkg state and writes static JSON and Markdown receipts under `.mdkg/git/closeouts` by default
801
820
  - when the project DB participated, `git closeout` also seals `.mdkg/db/state/project.sqlite` and writes a deterministic dump
@@ -805,6 +824,7 @@ Notes:
805
824
 
806
825
  JSON receipts:
807
826
  - `inspect`: `{ action: "git.inspect", ok, root, inside_work_tree, branch, head_sha, tree_hash, remotes, status, source_descriptor, accepted_revision, warnings }`
827
+ - `materialize`: `{ schema: "mdkg.git.materialize.receipt.v1", action: "git.materialize", ok, reason_code, request_hash, repository, source_ref, access_ref, correlation_ref, evidence_refs, target_ref, expected_revision, observed_revision, policies, destination, cleanup, warnings }`
808
828
  - `clone`: `{ action: "git.clone", ok, repository_ref, target, branch, source_descriptor, accepted_revision, inspect, warnings }`
809
829
  - `fetch`: `{ action: "git.fetch", ok, remote, branch, fetch_output, inspect, warnings }`
810
830
  - `closeout`: `{ action: "git.closeout", ok, root, output_dir, generated_at, git, validation, db_participated, db_snapshot_status, db_snapshot_seal, db_snapshot_dump, static_receipts, warnings }`
package/README.md CHANGED
@@ -14,7 +14,7 @@ mdkg stays deliberately boring:
14
14
  - first-class rebuildable SQLite cache through built-in `node:sqlite`
15
15
  - no daemon, hosted index, or vector DB
16
16
 
17
- Current package version in source: `0.5.0`
17
+ Current package version in source: `0.5.2`
18
18
 
19
19
  mdkg is still pre-v1 public alpha software. The public package is usable, but graph, cache, bundle, and DAL contracts may continue to change quickly while the project converges on a stable v1 surface.
20
20
 
@@ -242,11 +242,13 @@ Subgraph nodes are projected under the subgraph alias, for example `child_repo:t
242
242
 
243
243
  Use `mdkg graph refs <id-or-qid> --json` to inspect inbound and outbound scope, context, evidence, blocker, related, and structural links for local or read-only subgraph qids without mutating either graph.
244
244
 
245
- Use low-level Git lifecycle receipts when an agent run needs to close out local
246
- mdkg state and prove push readiness before an explicit remote update:
245
+ Use low-level Git lifecycle receipts when an agent run needs to accept an exact
246
+ source revision, close out local mdkg state, or prove push readiness before an
247
+ explicit remote update:
247
248
 
248
249
  ```bash
249
250
  mdkg git inspect --json
251
+ mdkg git materialize --request materialize-request.json --json
250
252
  mdkg git clone git@github.com:org/repo.git --target worktrees/repo --branch main --json
251
253
  mdkg git fetch --remote origin --branch main --json
252
254
  mdkg git closeout --json
@@ -257,7 +259,12 @@ mdkg git push --remote origin --branch main --stage-all --message "agent checkpo
257
259
  `mdkg git` uses the system Git CLI. Authentication stays external through SSH,
258
260
  credential helpers, `gh`, CI/runtime environment, or shell state; mdkg rejects
259
261
  embedded URL credentials and records only sanitized refs, hashes, policy names,
260
- and receipts. `closeout` validates mdkg state before writing static JSON and
262
+ and receipts. `materialize` accepts only strict
263
+ `mdkg.git.materialize.request.v1` JSON, verifies the full target ref and
264
+ accepted revision, and publishes a contained destination only after all checks
265
+ pass; see the [verified Git materialization
266
+ guide](https://docs.mdkg.dev/advanced-alpha/git-materialization/). `closeout`
267
+ validates mdkg state before writing static JSON and
261
268
  Markdown receipts, and when the project DB participated it also seals the
262
269
  SQLite state and writes a deterministic dump. Treat real `mdkg git push` as an
263
270
  approval-gated operation in agent runtimes.
@@ -653,6 +660,16 @@ When the source passed to `mdkg archive add` is inside the repo, `source_path` i
653
660
 
654
661
  Archive sidecar visibility defaults to `private`. Use `mdkg archive add --visibility public` only when the sidecar metadata and ZIP cache are safe for public packs or public bundles.
655
662
 
663
+ Archive compression follows workspace ownership. `mdkg archive compress --all`
664
+ compresses archives from enabled local workspaces and reports read-only imported
665
+ archive projections as exclusions; it never treats bundle ZIP fragments as
666
+ filesystem paths. Use `--all --ws <local-alias>` to limit bulk compression or a
667
+ workspace-qualified qid such as `root:archive.example` for an exact local
668
+ target. Direct imported qids and imported `--ws` aliases fail before writes with
669
+ guidance to compress in the source workspace and refresh its subgraph bundle.
670
+ The JSON receipt preserves `action`, `count`, and `archives` and adds the
671
+ requested workspace, selected local workspaces, and excluded read-only qids.
672
+
656
673
  By default, init/upgrade ignore generated raw archive source copies with `.mdkg/archive/**/source/`; sidecar `.md` files and compressed `.zip` caches remain commit-eligible. `mdkg doctor` warns when a committed archive ZIP cache exceeds `archive.large_cache_warning_bytes` in `.mdkg/config.json` (default `26214400`; set `0` to disable). Large-cache warnings do not block archive add or validation.
657
674
 
658
675
  ## Current direction
package/dist/cli.js CHANGED
@@ -30,6 +30,7 @@ const archive_1 = require("./commands/archive");
30
30
  const bundle_1 = require("./commands/bundle");
31
31
  const graph_1 = require("./commands/graph");
32
32
  const git_1 = require("./commands/git");
33
+ const git_materialize_1 = require("./commands/git_materialize");
33
34
  const subgraph_1 = require("./commands/subgraph");
34
35
  const checkpoint_1 = require("./commands/checkpoint");
35
36
  const init_1 = require("./commands/init");
@@ -79,7 +80,7 @@ function printUsage(log) {
79
80
  log(" archive Add, list, show, verify, and compress archive sidecars");
80
81
  log(" bundle Create, list, show, and verify full graph snapshot bundles");
81
82
  log(" graph Clone, fork, import, and inspect mdkg graph references");
82
- log(" git Clone, fetch, inspect, close out, and push Git-backed mdkg projects");
83
+ log(" git Materialize, clone, fetch, inspect, close out, and push Git-backed projects");
83
84
  log(" subgraph Register, audit, plan, sync, materialize, and verify read-only child graph snapshots");
84
85
  log(" work Create and update work contracts, orders, receipts, and artifacts");
85
86
  log(" loop List, show, fork, plan, and inspect first-class loop nodes");
@@ -583,8 +584,13 @@ function printArchiveHelp(log, subcommand) {
583
584
  break;
584
585
  case "compress":
585
586
  log("Usage:");
586
- log(" mdkg archive compress <id-or-archive-uri> [--ws <alias>] [--json]");
587
- log(" mdkg archive compress --all [--json]");
587
+ log(" mdkg archive compress <id-or-archive-uri-or-qid> [--ws <local-alias>] [--json]");
588
+ log(" mdkg archive compress --all [--ws <local-alias>] [--json]");
589
+ log("\nNotes:");
590
+ log(" - compression mutates archives owned by enabled local workspaces only");
591
+ log(" - --all excludes read-only imported archive projections and reports them in the receipt");
592
+ log(" - direct imported qids and --ws <imported-alias> fail with source-workspace guidance");
593
+ log(" - all selected archives pass ownership and path preflight before the first write");
588
594
  break;
589
595
  default:
590
596
  log("Usage:");
@@ -592,7 +598,7 @@ function printArchiveHelp(log, subcommand) {
592
598
  log(" mdkg archive list [--kind source|artifact] [--visibility private|internal|public] [--json]");
593
599
  log(" mdkg archive show <id-or-archive-uri> [--json]");
594
600
  log(" mdkg archive verify [id-or-archive-uri] [--json]");
595
- log(" mdkg archive compress <id-or-archive-uri|--all> [--json]");
601
+ log(" mdkg archive compress <id-or-archive-uri-or-qid|--all> [--ws <local-alias>] [--json]");
596
602
  log("\nNotes:");
597
603
  log(" - archive add copies the source, writes a sidecar, and writes a deterministic zip cache");
598
604
  log(" - archive visibility defaults to private");
@@ -704,6 +710,14 @@ function printGitHelp(log, subcommand) {
704
710
  log(" - --target must be empty or absent and stay inside the current repo");
705
711
  log(" - repository refs must not embed credentials");
706
712
  break;
713
+ case "materialize":
714
+ log("Usage:");
715
+ log(" mdkg git materialize --request <file|-> [--json]");
716
+ log("\nNotes:");
717
+ log(" - accepts only schema mdkg.git.materialize.request.v1 JSON");
718
+ log(" - verifies the full target ref, expected commit, optional tree, and policy checks before publishing");
719
+ log(" - uses external auth and an atomic contained destination; receipts never include credentials or raw Git output");
720
+ break;
707
721
  case "fetch":
708
722
  log("Usage:");
709
723
  log(" mdkg git fetch [--remote <name>] [--branch <name>] [--json]");
@@ -738,6 +752,7 @@ function printGitHelp(log, subcommand) {
738
752
  default:
739
753
  log("Usage:");
740
754
  log(" mdkg git inspect [--json]");
755
+ log(" mdkg git materialize --request <file|-> [--json]");
741
756
  log(" mdkg git clone <repository-ref> --target <path> [--branch <name>] [--json]");
742
757
  log(" mdkg git fetch [--remote <name>] [--branch <name>] [--json]");
743
758
  log(" mdkg git closeout [--queue-policy drain|paused] [--output <path>] [--json]");
@@ -2026,6 +2041,8 @@ function runGitSubcommand(parsed, root) {
2026
2041
  (0, git_1.runGitInspectCommand)({ root, json });
2027
2042
  return 0;
2028
2043
  }
2044
+ case "materialize":
2045
+ throw new errors_1.UsageError("git materialize requires the asynchronous CLI entrypoint");
2029
2046
  case "clone": {
2030
2047
  const repository = parsed.positionals[2];
2031
2048
  if (!repository || parsed.positionals.length > 3) {
@@ -2079,7 +2096,44 @@ function runGitSubcommand(parsed, root) {
2079
2096
  return 0;
2080
2097
  }
2081
2098
  default:
2082
- throw new errors_1.UsageError("git requires inspect/clone/fetch/closeout/push-ready/push");
2099
+ throw new errors_1.UsageError("git requires inspect/materialize/clone/fetch/closeout/push-ready/push");
2100
+ }
2101
+ }
2102
+ function printGitMaterializeReceipt(receipt, json, runtime) {
2103
+ if (json) {
2104
+ runtime.log(JSON.stringify(receipt, null, 2));
2105
+ return;
2106
+ }
2107
+ if (receipt.ok) {
2108
+ runtime.log("git materialize accepted");
2109
+ runtime.log(`destination: ${receipt.destination.path ?? "(none)"}`);
2110
+ runtime.log(`commit: ${receipt.observed_revision.commit ?? "(none)"}`);
2111
+ runtime.log(`tree: ${receipt.observed_revision.tree ?? "(none)"}`);
2112
+ return;
2113
+ }
2114
+ runtime.error(`git materialize failed: ${receipt.reason_code}`);
2115
+ runtime.error(`destination: ${receipt.destination.state}`);
2116
+ runtime.error(`cleanup: ${receipt.cleanup.state}`);
2117
+ }
2118
+ async function runGitMaterializeSubcommand(parsed, root, runtime) {
2119
+ if (parsed.positionals.length > 2) {
2120
+ throw new errors_1.UsageError("git materialize does not accept positional arguments");
2121
+ }
2122
+ const request = requireFlagValue("--request", parsed.flags["--request"]);
2123
+ if (!request)
2124
+ throw new errors_1.UsageError("git materialize requires --request <file|->");
2125
+ const json = parseBooleanFlag("--json", parsed.flags["--json"]);
2126
+ try {
2127
+ const receipt = await (0, git_materialize_1.collectGitMaterializeReceipt)({ root, request });
2128
+ printGitMaterializeReceipt(receipt, json, runtime);
2129
+ return 0;
2130
+ }
2131
+ catch (error) {
2132
+ if (error instanceof git_materialize_1.GitMaterializeError) {
2133
+ printGitMaterializeReceipt(error.receipt, json, runtime);
2134
+ return 2;
2135
+ }
2136
+ throw error;
2083
2137
  }
2084
2138
  }
2085
2139
  function runSubgraphSubcommand(parsed, root) {
@@ -3407,6 +3461,9 @@ async function runCliAsync(argv, runtime = {}) {
3407
3461
  if (command === "mcp") {
3408
3462
  return await runMcpSubcommand(parsed, root);
3409
3463
  }
3464
+ if (command === "git" && (parsed.positionals[1] ?? "").toLowerCase() === "materialize") {
3465
+ return await runGitMaterializeSubcommand(parsed, root, io);
3466
+ }
3410
3467
  return runCommand(parsed, root, io);
3411
3468
  }
3412
3469
  catch (err) {