mdkg 0.1.3 → 0.1.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.
- package/CHANGELOG.md +27 -1
- package/README.md +11 -10
- package/dist/cli.js +180 -86
- package/dist/commands/bundle.js +7 -7
- package/dist/commands/capability.js +118 -4
- package/dist/commands/doctor.js +15 -15
- package/dist/commands/index.js +1 -1
- package/dist/commands/list.js +1 -1
- package/dist/commands/next.js +1 -1
- package/dist/commands/node_card.js +1 -1
- package/dist/commands/pack.js +1 -1
- package/dist/commands/search.js +1 -1
- package/dist/commands/show.js +1 -1
- package/dist/commands/subgraph.js +312 -0
- package/dist/commands/task.js +1 -1
- package/dist/commands/upgrade.js +51 -4
- package/dist/commands/validate.js +6 -6
- package/dist/commands/work.js +1 -1
- package/dist/core/config.js +95 -39
- package/dist/graph/index_cache.js +12 -12
- package/dist/graph/indexer.js +1 -1
- package/dist/graph/reindex.js +6 -6
- package/dist/graph/sqlite_index.js +6 -6
- package/dist/graph/{bundle_imports.js → subgraphs.js} +214 -140
- package/dist/graph/visibility.js +3 -3
- package/dist/init/AGENT_START.md +2 -1
- package/dist/init/CLI_COMMAND_MATRIX.md +16 -7
- package/dist/init/README.md +9 -8
- package/dist/init/config.json +1 -1
- package/dist/init/core/rule-3-cli-contract.md +30 -23
- package/dist/init/core/rule-4-repo-safety-and-ignores.md +1 -1
- package/dist/init/init-manifest.json +8 -8
- package/dist/init/skills/default/verify-close-and-checkpoint/SKILL.md +1 -1
- package/dist/util/argparse.js +2 -0
- package/package.json +7 -6
- package/dist/commands/bundle_import.js +0 -255
package/CHANGELOG.md
CHANGED
|
@@ -4,7 +4,33 @@ All notable changes to mdkg are documented here.
|
|
|
4
4
|
|
|
5
5
|
This project follows a pragmatic changelog style inspired by Keep a Changelog. Versions use npm package versions.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
mdkg is pre-v1 public alpha software. Command, graph, cache, bundle, and DAL contracts may change quickly while the project converges on a stable v1 surface.
|
|
8
|
+
|
|
9
|
+
## 0.1.4 - Unreleased
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- Added `mdkg subgraph add/list/show/rm/enable/disable/verify/refresh` as the public read-only child graph orchestration command family.
|
|
14
|
+
- Added `subgraphs` config with multi-source bundle transport, advisory visibility, read permissions, source metadata, and a default 60 minute freshness policy.
|
|
15
|
+
- Added `.mdkg/index/subgraphs.json` as the derived subgraph projection and health cache.
|
|
16
|
+
- Added `mdkg capability resolve [query] [--requires <capability>] [--fresh-only] [--json]` for deterministic local plus subgraph capability ranking.
|
|
17
|
+
- Added packed-package `smoke:subgraph` coverage for root, child, and grandchild orchestration flows.
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- Replaced the public `mdkg bundle import ...` surface with `mdkg subgraph ...`; legacy calls now exit with migration guidance.
|
|
22
|
+
- `mdkg upgrade --apply` migrates legacy `bundle_imports` config into `subgraphs`.
|
|
23
|
+
- Read commands, `pack`, and capability discovery now project enabled child bundles as read-only subgraph qids such as `child_repo:work.example`.
|
|
24
|
+
- `mdkg index`, SQLite cache rebuilds, `doctor`, and `validate` now use subgraph naming and metadata instead of bundle-import naming.
|
|
25
|
+
- Stale subgraphs remain usable for planning reads with warnings, fail `mdkg subgraph verify`, and are excluded from `capability resolve --fresh-only`.
|
|
26
|
+
- Public/internal subgraphs require public bundle profiles and public bundle creation fails closed on private/internal subgraph references.
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
|
|
30
|
+
- Mutation commands now reject subgraph qids with explicit guidance to update the source workspace for the owning subgraph.
|
|
31
|
+
- Seeded init docs, command matrix, and release skills now teach `subgraph` and `capability resolve` instead of onboarding users through `bundle import`.
|
|
32
|
+
|
|
33
|
+
## 0.1.3 - 2026-05-20
|
|
8
34
|
|
|
9
35
|
### Added
|
|
10
36
|
|
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.1.
|
|
17
|
+
Current package version in source: `0.1.4`
|
|
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
|
|
|
@@ -110,20 +110,21 @@ mdkg bundle verify .mdkg/bundles/private/all.mdkg.zip
|
|
|
110
110
|
mdkg bundle list --json
|
|
111
111
|
```
|
|
112
112
|
|
|
113
|
-
Bundles are explicit graph transport artifacts, separate from task context packs. Before a commit in repos that track archives or bundles, refresh compressed archive caches first, then create the private bundle so the committed graph state is self-consistent. Private bundles are the default and may be committed in private repos when configured. Public bundles require at least one selected workspace with `visibility: public` and include only public workspace content and public archive sidecars; bundle creation fails if public content points at private graph, archive, or
|
|
113
|
+
Bundles are explicit graph transport artifacts, separate from task context packs. Before a commit in repos that track archives or bundles, refresh compressed archive caches first, then create the private bundle so the committed graph state is self-consistent. Private bundles are the default and may be committed in private repos when configured. Public bundles require at least one selected workspace with `visibility: public` and include only public workspace content and public archive sidecars; bundle creation fails if public content points at private graph, archive, or subgraph records.
|
|
114
114
|
|
|
115
|
-
|
|
115
|
+
Register a child repo bundle as a read-only subgraph planning view:
|
|
116
116
|
|
|
117
117
|
```bash
|
|
118
|
-
mdkg
|
|
119
|
-
mdkg
|
|
118
|
+
mdkg subgraph add child_repo child-repo/.mdkg/bundles/private/all.mdkg.zip --source-path child-repo
|
|
119
|
+
mdkg subgraph list --json
|
|
120
120
|
mdkg search "child capability"
|
|
121
121
|
mdkg show child_repo:work.example
|
|
122
122
|
mdkg pack child_repo:work.example --dry-run --stats
|
|
123
|
-
mdkg
|
|
123
|
+
mdkg capability resolve "child capability" --json
|
|
124
|
+
mdkg subgraph verify child_repo --json
|
|
124
125
|
```
|
|
125
126
|
|
|
126
|
-
|
|
127
|
+
Subgraph nodes are projected under the subgraph alias, for example `child_repo:task-1`. They are available to `list`, `search`, `show`, `pack`, capability discovery, and `capability resolve`, but remain read-only; mutate the child repo and refresh its bundle to change subgraph content. Stale subgraphs warn during planning reads and fail `mdkg subgraph verify`. Public or internal subgraphs must be backed by public bundle profiles; private subgraphs stay private planning context.
|
|
127
128
|
|
|
128
129
|
Validate before handoff or commit:
|
|
129
130
|
|
|
@@ -158,7 +159,7 @@ mdkg work artifact add receipt.generate-image-1 ./outputs/image.png --id archive
|
|
|
158
159
|
```
|
|
159
160
|
|
|
160
161
|
Receipt statuses are `recorded`, `verified`, `rejected`, and `superseded`.
|
|
161
|
-
Update and artifact commands accept local ids or local qids;
|
|
162
|
+
Update and artifact commands accept local ids or local qids; subgraph qids are read-only and must be changed in their source workspace.
|
|
162
163
|
|
|
163
164
|
Update structured task state and evidence while keeping body and narrative edits in markdown:
|
|
164
165
|
|
|
@@ -206,7 +207,7 @@ mdkg lives under a hidden root directory:
|
|
|
206
207
|
- `.mdkg/archive/` sidecar metadata plus deterministic compressed source/artifact caches
|
|
207
208
|
- `.mdkg/bundles/` optional committed full graph snapshot bundles
|
|
208
209
|
- `.mdkg/index/mdkg.sqlite` optional committed, rebuildable SQLite access cache
|
|
209
|
-
- `.mdkg/index/
|
|
210
|
+
- `.mdkg/index/subgraphs.json` generated read-only subgraph projection cache
|
|
210
211
|
- `.agents/skills/` Codex/OpenAI-facing mirrored skills
|
|
211
212
|
- `.claude/skills/` Claude-facing mirrored skills
|
|
212
213
|
- `.mdkg/index/*.json` generated JSON compatibility cache files
|
|
@@ -300,7 +301,7 @@ Capability records aggregate enabled registered workspaces and include determini
|
|
|
300
301
|
|
|
301
302
|
Fresh `mdkg init` workspaces default to `index.backend: sqlite`, which writes `.mdkg/index/mdkg.sqlite` as a rebuildable access cache using Node's built-in `node:sqlite`. Existing workspaces that are migrated from older configs default to `index.backend: json` until they opt in. Markdown files, archive sidecars, bundle manifests, and config remain source of truth in both modes.
|
|
302
303
|
|
|
303
|
-
`mdkg index` still writes JSON compatibility caches (`global.json`, `skills.json`, `capabilities.json`, and
|
|
304
|
+
`mdkg index` still writes JSON compatibility caches (`global.json`, `skills.json`, `capabilities.json`, and subgraph projections when configured). In SQLite mode it also rebuilds the SQLite cache with nodes, edges, skills, capabilities, archive metadata, subgraphs, source hashes, and schema metadata. Deleting the SQLite file is recoverable with `mdkg index`.
|
|
304
305
|
|
|
305
306
|
Mutating commands use a workspace mutation lock plus atomic writes. SQLite mode additionally reserves numeric ids in a SQLite transaction before writing Markdown so parallel `mdkg new` and checkpoint calls avoid naming conflicts. Skipped ids after failed writes are acceptable because Markdown remains canonical.
|
|
306
307
|
|
package/dist/cli.js
CHANGED
|
@@ -21,7 +21,7 @@ const doctor_1 = require("./commands/doctor");
|
|
|
21
21
|
const capability_1 = require("./commands/capability");
|
|
22
22
|
const archive_1 = require("./commands/archive");
|
|
23
23
|
const bundle_1 = require("./commands/bundle");
|
|
24
|
-
const
|
|
24
|
+
const subgraph_1 = require("./commands/subgraph");
|
|
25
25
|
const checkpoint_1 = require("./commands/checkpoint");
|
|
26
26
|
const init_1 = require("./commands/init");
|
|
27
27
|
const new_1 = require("./commands/new");
|
|
@@ -60,9 +60,10 @@ function printUsage(log) {
|
|
|
60
60
|
log(" search Search nodes by query");
|
|
61
61
|
log(" pack Generate a context pack");
|
|
62
62
|
log(" skill Create, list, show, search, and validate skills");
|
|
63
|
-
log(" capability List, search, and
|
|
63
|
+
log(" capability List, search, show, and resolve cached capability surfaces");
|
|
64
64
|
log(" archive Add, list, show, verify, and compress archive sidecars");
|
|
65
65
|
log(" bundle Create, list, show, and verify full graph snapshot bundles");
|
|
66
|
+
log(" subgraph Register and verify read-only child graph snapshots");
|
|
66
67
|
log(" work Create and update work contracts, orders, receipts, and artifacts");
|
|
67
68
|
log(" task Start, update, and complete task-like nodes");
|
|
68
69
|
log(" next Suggest the next work item");
|
|
@@ -171,7 +172,7 @@ function printIndexHelp(log) {
|
|
|
171
172
|
log(" - .mdkg/index/global.json");
|
|
172
173
|
log(" - .mdkg/index/skills.json");
|
|
173
174
|
log(" - .mdkg/index/capabilities.json");
|
|
174
|
-
log(" - .mdkg/index/
|
|
175
|
+
log(" - .mdkg/index/subgraphs.json when subgraphs are configured");
|
|
175
176
|
log(" - .mdkg/index/mdkg.sqlite when index.backend is sqlite");
|
|
176
177
|
printGlobalOptions(log);
|
|
177
178
|
}
|
|
@@ -322,14 +323,23 @@ function printCapabilityHelp(log, subcommand) {
|
|
|
322
323
|
log(" mdkg capability show <id-or-qid-or-slug> [--json]");
|
|
323
324
|
printGlobalOptions(log);
|
|
324
325
|
return;
|
|
326
|
+
case "resolve":
|
|
327
|
+
log("Usage:");
|
|
328
|
+
log(' mdkg capability resolve [query] [--requires <capability>] [--fresh-only] [--json]');
|
|
329
|
+
log("\nNotes:");
|
|
330
|
+
log(" Resolves local and subgraph capabilities with deterministic ranking.");
|
|
331
|
+
printGlobalOptions(log);
|
|
332
|
+
return;
|
|
325
333
|
default:
|
|
326
334
|
log("Usage:");
|
|
327
335
|
log(" mdkg capability list [--kind <kind>] [--visibility <level>] [--json]");
|
|
328
336
|
log(' mdkg capability search "<query>" [--kind <kind>] [--visibility <level>] [--json]');
|
|
329
337
|
log(" mdkg capability show <id-or-qid-or-slug> [--json]");
|
|
338
|
+
log(' mdkg capability resolve [query] [--requires <capability>] [--fresh-only] [--json]');
|
|
330
339
|
log("\nNotes:");
|
|
331
340
|
log(" Capability records are deterministic cache projections from Markdown.");
|
|
332
341
|
log(" Cached kinds: skill, spec, work, core, design.");
|
|
342
|
+
log(" Resolve includes read-only subgraph capability records when configured.");
|
|
333
343
|
printGlobalOptions(log);
|
|
334
344
|
}
|
|
335
345
|
}
|
|
@@ -375,12 +385,8 @@ function printBundleHelp(log, subcommand) {
|
|
|
375
385
|
switch ((subcommand ?? "").toLowerCase()) {
|
|
376
386
|
case "import":
|
|
377
387
|
log("Usage:");
|
|
378
|
-
log(" mdkg
|
|
379
|
-
log("
|
|
380
|
-
log(" mdkg bundle import rm <alias> [--json]");
|
|
381
|
-
log(" mdkg bundle import enable <alias> [--json]");
|
|
382
|
-
log(" mdkg bundle import disable <alias> [--json]");
|
|
383
|
-
log(" mdkg bundle import verify [alias|--all] [--json]");
|
|
388
|
+
log(" mdkg subgraph add/list/show/rm/enable/disable/verify/refresh ...");
|
|
389
|
+
log("\n`mdkg bundle import` has been replaced by `mdkg subgraph`.");
|
|
384
390
|
break;
|
|
385
391
|
case "create":
|
|
386
392
|
log("Usage:");
|
|
@@ -404,15 +410,66 @@ function printBundleHelp(log, subcommand) {
|
|
|
404
410
|
log(" mdkg bundle verify [bundle-path] [--json]");
|
|
405
411
|
log(" mdkg bundle show <bundle-path> [--json]");
|
|
406
412
|
log(" mdkg bundle list [--json]");
|
|
407
|
-
log(" mdkg bundle import add/list/rm/enable/disable/verify ...");
|
|
408
413
|
log("\nNotes:");
|
|
409
414
|
log(" - bundles are explicit full .mdkg graph snapshots, not task context packs");
|
|
410
|
-
log(" - bundle
|
|
415
|
+
log(" - use `mdkg subgraph ...` to register bundle snapshots as read-only planning views");
|
|
411
416
|
log(" - private is the default profile; public bundles fail closed on private refs");
|
|
412
417
|
log(" - .mdkg/bundles/ is commit-eligible when your repo tracks snapshot bundles");
|
|
413
418
|
}
|
|
414
419
|
printGlobalOptions(log);
|
|
415
420
|
}
|
|
421
|
+
function printSubgraphHelp(log, subcommand) {
|
|
422
|
+
switch ((subcommand ?? "").toLowerCase()) {
|
|
423
|
+
case "add":
|
|
424
|
+
log("Usage:");
|
|
425
|
+
log(" mdkg subgraph add <alias> <bundle-path> [--visibility private|internal|public] [--profile private|public] [--source-path <path>] [--source-repo <ref>] [--max-stale-seconds <seconds>] [--json]");
|
|
426
|
+
break;
|
|
427
|
+
case "list":
|
|
428
|
+
log("Usage:");
|
|
429
|
+
log(" mdkg subgraph list [--json]");
|
|
430
|
+
break;
|
|
431
|
+
case "show":
|
|
432
|
+
log("Usage:");
|
|
433
|
+
log(" mdkg subgraph show <alias> [--json]");
|
|
434
|
+
break;
|
|
435
|
+
case "rm":
|
|
436
|
+
case "remove":
|
|
437
|
+
log("Usage:");
|
|
438
|
+
log(" mdkg subgraph rm <alias> [--json]");
|
|
439
|
+
break;
|
|
440
|
+
case "enable":
|
|
441
|
+
log("Usage:");
|
|
442
|
+
log(" mdkg subgraph enable <alias> [--json]");
|
|
443
|
+
break;
|
|
444
|
+
case "disable":
|
|
445
|
+
log("Usage:");
|
|
446
|
+
log(" mdkg subgraph disable <alias> [--json]");
|
|
447
|
+
break;
|
|
448
|
+
case "verify":
|
|
449
|
+
log("Usage:");
|
|
450
|
+
log(" mdkg subgraph verify [alias|--all] [--json]");
|
|
451
|
+
break;
|
|
452
|
+
case "refresh":
|
|
453
|
+
log("Usage:");
|
|
454
|
+
log(" mdkg subgraph refresh [alias|--all] [--json]");
|
|
455
|
+
break;
|
|
456
|
+
default:
|
|
457
|
+
log("Usage:");
|
|
458
|
+
log(" mdkg subgraph add <alias> <bundle-path> [--visibility private|internal|public] [--profile private|public] [--source-path <path>] [--source-repo <ref>] [--max-stale-seconds <seconds>] [--json]");
|
|
459
|
+
log(" mdkg subgraph list [--json]");
|
|
460
|
+
log(" mdkg subgraph show <alias> [--json]");
|
|
461
|
+
log(" mdkg subgraph rm <alias> [--json]");
|
|
462
|
+
log(" mdkg subgraph enable <alias> [--json]");
|
|
463
|
+
log(" mdkg subgraph disable <alias> [--json]");
|
|
464
|
+
log(" mdkg subgraph verify [alias|--all] [--json]");
|
|
465
|
+
log(" mdkg subgraph refresh [alias|--all] [--json]");
|
|
466
|
+
log("\nNotes:");
|
|
467
|
+
log(" - subgraphs are read-only graph views backed by explicit bundle snapshots");
|
|
468
|
+
log(" - default permissions are read-only and default freshness is 3600 seconds");
|
|
469
|
+
log(" - refresh reloads configured bundle sources only; it does not build child bundles");
|
|
470
|
+
}
|
|
471
|
+
printGlobalOptions(log);
|
|
472
|
+
}
|
|
416
473
|
function printWorkHelp(log, subcommand) {
|
|
417
474
|
switch ((subcommand ?? "").toLowerCase()) {
|
|
418
475
|
case "contract":
|
|
@@ -444,7 +501,7 @@ function printWorkHelp(log, subcommand) {
|
|
|
444
501
|
log(" - production order, receipt, feedback, dispute, payment, ledger, marketplace inventory, fulfillment, and execution state remains canonical outside mdkg");
|
|
445
502
|
log(" - do not store raw secrets, credentials, live payment state, ledger mutations, or canonical marketplace state in work mirrors");
|
|
446
503
|
log(" - artifact:// refs identify external/runtime-managed artifacts; archive:// refs identify committed mdkg archive sidecars");
|
|
447
|
-
log(" - update and artifact commands accept local ids or local qids;
|
|
504
|
+
log(" - update and artifact commands accept local ids or local qids; subgraph qids are read-only");
|
|
448
505
|
}
|
|
449
506
|
printGlobalOptions(log);
|
|
450
507
|
}
|
|
@@ -599,6 +656,9 @@ function printCommandHelp(log, command, subcommand) {
|
|
|
599
656
|
case "bundle":
|
|
600
657
|
printBundleHelp(log, subcommand);
|
|
601
658
|
return;
|
|
659
|
+
case "subgraph":
|
|
660
|
+
printSubgraphHelp(log, subcommand);
|
|
661
|
+
return;
|
|
602
662
|
case "work":
|
|
603
663
|
printWorkHelp(log, subcommand);
|
|
604
664
|
return;
|
|
@@ -871,8 +931,20 @@ function runCapabilitySubcommand(parsed, root) {
|
|
|
871
931
|
(0, capability_1.runCapabilityShowCommand)({ root, id, json, noCache, noReindex });
|
|
872
932
|
return 0;
|
|
873
933
|
}
|
|
934
|
+
case "resolve": {
|
|
935
|
+
const query = parsed.positionals.slice(2).join(" ") || undefined;
|
|
936
|
+
const kind = requireFlagValue("--kind", parsed.flags["--kind"]);
|
|
937
|
+
const visibility = requireFlagValue("--visibility", parsed.flags["--visibility"]);
|
|
938
|
+
const requires = requireFlagValue("--requires", parsed.flags["--requires"]);
|
|
939
|
+
const freshOnly = parseBooleanFlag("--fresh-only", parsed.flags["--fresh-only"]);
|
|
940
|
+
const json = parseBooleanFlag("--json", parsed.flags["--json"]);
|
|
941
|
+
const noCache = parseBooleanFlag("--no-cache", parsed.flags["--no-cache"]);
|
|
942
|
+
const noReindex = parseBooleanFlag("--no-reindex", parsed.flags["--no-reindex"]);
|
|
943
|
+
(0, capability_1.runCapabilityResolveCommand)({ root, query, kind, visibility, requires, freshOnly, json, noCache, noReindex });
|
|
944
|
+
return 0;
|
|
945
|
+
}
|
|
874
946
|
default:
|
|
875
|
-
throw new errors_1.UsageError("capability requires list/search/show");
|
|
947
|
+
throw new errors_1.UsageError("capability requires list/search/show/resolve");
|
|
876
948
|
}
|
|
877
949
|
}
|
|
878
950
|
function runArchiveSubcommand(parsed, root) {
|
|
@@ -944,78 +1016,7 @@ function runBundleSubcommand(parsed, root) {
|
|
|
944
1016
|
const subcommand = (parsed.positionals[1] ?? "").toLowerCase();
|
|
945
1017
|
switch (subcommand) {
|
|
946
1018
|
case "import": {
|
|
947
|
-
|
|
948
|
-
const json = parseBooleanFlag("--json", parsed.flags["--json"]);
|
|
949
|
-
switch (action) {
|
|
950
|
-
case "add": {
|
|
951
|
-
const alias = parsed.positionals[3];
|
|
952
|
-
const bundlePath = parsed.positionals[4];
|
|
953
|
-
if (!alias || !bundlePath || parsed.positionals.length > 5) {
|
|
954
|
-
throw new errors_1.UsageError("bundle import add requires <alias> <bundle-path>");
|
|
955
|
-
}
|
|
956
|
-
const visibility = requireFlagValue("--visibility", parsed.flags["--visibility"]);
|
|
957
|
-
const profile = requireFlagValue("--profile", parsed.flags["--pack-profile"]);
|
|
958
|
-
const sourcePath = requireFlagValue("--source-path", parsed.flags["--source-path"]);
|
|
959
|
-
const sourceRepo = requireFlagValue("--source-repo", parsed.flags["--source-repo"]);
|
|
960
|
-
const maxStaleRaw = requireFlagValue("--max-stale-seconds", parsed.flags["--max-stale-seconds"]);
|
|
961
|
-
const maxStaleSeconds = maxStaleRaw === undefined ? undefined : Number.parseInt(maxStaleRaw, 10);
|
|
962
|
-
(0, bundle_import_1.runBundleImportAddCommand)({
|
|
963
|
-
root,
|
|
964
|
-
alias,
|
|
965
|
-
bundlePath,
|
|
966
|
-
visibility,
|
|
967
|
-
profile,
|
|
968
|
-
sourcePath,
|
|
969
|
-
sourceRepo,
|
|
970
|
-
maxStaleSeconds,
|
|
971
|
-
json,
|
|
972
|
-
});
|
|
973
|
-
return 0;
|
|
974
|
-
}
|
|
975
|
-
case "list": {
|
|
976
|
-
if (parsed.positionals.length > 3) {
|
|
977
|
-
throw new errors_1.UsageError("bundle import list does not accept positional arguments");
|
|
978
|
-
}
|
|
979
|
-
(0, bundle_import_1.runBundleImportListCommand)({ root, json });
|
|
980
|
-
return 0;
|
|
981
|
-
}
|
|
982
|
-
case "rm":
|
|
983
|
-
case "remove": {
|
|
984
|
-
const alias = parsed.positionals[3];
|
|
985
|
-
if (!alias || parsed.positionals.length > 4) {
|
|
986
|
-
throw new errors_1.UsageError("bundle import rm requires <alias>");
|
|
987
|
-
}
|
|
988
|
-
(0, bundle_import_1.runBundleImportRemoveCommand)({ root, alias, json });
|
|
989
|
-
return 0;
|
|
990
|
-
}
|
|
991
|
-
case "enable": {
|
|
992
|
-
const alias = parsed.positionals[3];
|
|
993
|
-
if (!alias || parsed.positionals.length > 4) {
|
|
994
|
-
throw new errors_1.UsageError("bundle import enable requires <alias>");
|
|
995
|
-
}
|
|
996
|
-
(0, bundle_import_1.runBundleImportEnableCommand)({ root, alias, json });
|
|
997
|
-
return 0;
|
|
998
|
-
}
|
|
999
|
-
case "disable": {
|
|
1000
|
-
const alias = parsed.positionals[3];
|
|
1001
|
-
if (!alias || parsed.positionals.length > 4) {
|
|
1002
|
-
throw new errors_1.UsageError("bundle import disable requires <alias>");
|
|
1003
|
-
}
|
|
1004
|
-
(0, bundle_import_1.runBundleImportDisableCommand)({ root, alias, json });
|
|
1005
|
-
return 0;
|
|
1006
|
-
}
|
|
1007
|
-
case "verify": {
|
|
1008
|
-
if (parsed.positionals.length > 4) {
|
|
1009
|
-
throw new errors_1.UsageError("bundle import verify accepts at most one alias");
|
|
1010
|
-
}
|
|
1011
|
-
const alias = parsed.positionals[3];
|
|
1012
|
-
const all = parseBooleanFlag("--all", parsed.flags["--all"]);
|
|
1013
|
-
(0, bundle_import_1.runBundleImportVerifyCommand)({ root, alias, all, json });
|
|
1014
|
-
return 0;
|
|
1015
|
-
}
|
|
1016
|
-
default:
|
|
1017
|
-
throw new errors_1.UsageError("bundle import requires add/list/rm/enable/disable/verify");
|
|
1018
|
-
}
|
|
1019
|
+
throw new errors_1.UsageError("mdkg bundle import has been replaced by mdkg subgraph; run `mdkg upgrade --apply` to migrate legacy bundle_imports config");
|
|
1019
1020
|
}
|
|
1020
1021
|
case "create": {
|
|
1021
1022
|
if (parsed.positionals.length > 2) {
|
|
@@ -1055,7 +1056,98 @@ function runBundleSubcommand(parsed, root) {
|
|
|
1055
1056
|
return 0;
|
|
1056
1057
|
}
|
|
1057
1058
|
default:
|
|
1058
|
-
throw new errors_1.UsageError("bundle requires create/list/show/verify
|
|
1059
|
+
throw new errors_1.UsageError("bundle requires create/list/show/verify");
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
function runSubgraphSubcommand(parsed, root) {
|
|
1063
|
+
const subcommand = (parsed.positionals[1] ?? "").toLowerCase();
|
|
1064
|
+
const json = parseBooleanFlag("--json", parsed.flags["--json"]);
|
|
1065
|
+
switch (subcommand) {
|
|
1066
|
+
case "add": {
|
|
1067
|
+
const alias = parsed.positionals[2];
|
|
1068
|
+
const bundlePath = parsed.positionals[3];
|
|
1069
|
+
if (!alias || !bundlePath || parsed.positionals.length > 4) {
|
|
1070
|
+
throw new errors_1.UsageError("subgraph add requires <alias> <bundle-path>");
|
|
1071
|
+
}
|
|
1072
|
+
const visibility = requireFlagValue("--visibility", parsed.flags["--visibility"]);
|
|
1073
|
+
const profile = requireFlagValue("--profile", parsed.flags["--pack-profile"]);
|
|
1074
|
+
const sourcePath = requireFlagValue("--source-path", parsed.flags["--source-path"]);
|
|
1075
|
+
const sourceRepo = requireFlagValue("--source-repo", parsed.flags["--source-repo"]);
|
|
1076
|
+
const maxStaleRaw = requireFlagValue("--max-stale-seconds", parsed.flags["--max-stale-seconds"]);
|
|
1077
|
+
const maxStaleSeconds = maxStaleRaw === undefined ? undefined : Number.parseInt(maxStaleRaw, 10);
|
|
1078
|
+
(0, subgraph_1.runSubgraphAddCommand)({
|
|
1079
|
+
root,
|
|
1080
|
+
alias,
|
|
1081
|
+
bundlePath,
|
|
1082
|
+
visibility,
|
|
1083
|
+
profile,
|
|
1084
|
+
sourcePath,
|
|
1085
|
+
sourceRepo,
|
|
1086
|
+
maxStaleSeconds,
|
|
1087
|
+
json,
|
|
1088
|
+
});
|
|
1089
|
+
return 0;
|
|
1090
|
+
}
|
|
1091
|
+
case "list": {
|
|
1092
|
+
if (parsed.positionals.length > 2) {
|
|
1093
|
+
throw new errors_1.UsageError("subgraph list does not accept positional arguments");
|
|
1094
|
+
}
|
|
1095
|
+
(0, subgraph_1.runSubgraphListCommand)({ root, json });
|
|
1096
|
+
return 0;
|
|
1097
|
+
}
|
|
1098
|
+
case "show": {
|
|
1099
|
+
const alias = parsed.positionals[2];
|
|
1100
|
+
if (!alias || parsed.positionals.length > 3) {
|
|
1101
|
+
throw new errors_1.UsageError("subgraph show requires <alias>");
|
|
1102
|
+
}
|
|
1103
|
+
(0, subgraph_1.runSubgraphShowCommand)({ root, alias, json });
|
|
1104
|
+
return 0;
|
|
1105
|
+
}
|
|
1106
|
+
case "rm":
|
|
1107
|
+
case "remove": {
|
|
1108
|
+
const alias = parsed.positionals[2];
|
|
1109
|
+
if (!alias || parsed.positionals.length > 3) {
|
|
1110
|
+
throw new errors_1.UsageError("subgraph rm requires <alias>");
|
|
1111
|
+
}
|
|
1112
|
+
(0, subgraph_1.runSubgraphRemoveCommand)({ root, alias, json });
|
|
1113
|
+
return 0;
|
|
1114
|
+
}
|
|
1115
|
+
case "enable": {
|
|
1116
|
+
const alias = parsed.positionals[2];
|
|
1117
|
+
if (!alias || parsed.positionals.length > 3) {
|
|
1118
|
+
throw new errors_1.UsageError("subgraph enable requires <alias>");
|
|
1119
|
+
}
|
|
1120
|
+
(0, subgraph_1.runSubgraphEnableCommand)({ root, alias, json });
|
|
1121
|
+
return 0;
|
|
1122
|
+
}
|
|
1123
|
+
case "disable": {
|
|
1124
|
+
const alias = parsed.positionals[2];
|
|
1125
|
+
if (!alias || parsed.positionals.length > 3) {
|
|
1126
|
+
throw new errors_1.UsageError("subgraph disable requires <alias>");
|
|
1127
|
+
}
|
|
1128
|
+
(0, subgraph_1.runSubgraphDisableCommand)({ root, alias, json });
|
|
1129
|
+
return 0;
|
|
1130
|
+
}
|
|
1131
|
+
case "verify": {
|
|
1132
|
+
if (parsed.positionals.length > 3) {
|
|
1133
|
+
throw new errors_1.UsageError("subgraph verify accepts at most one alias");
|
|
1134
|
+
}
|
|
1135
|
+
const alias = parsed.positionals[2];
|
|
1136
|
+
const all = parseBooleanFlag("--all", parsed.flags["--all"]);
|
|
1137
|
+
(0, subgraph_1.runSubgraphVerifyCommand)({ root, alias, all, json });
|
|
1138
|
+
return 0;
|
|
1139
|
+
}
|
|
1140
|
+
case "refresh": {
|
|
1141
|
+
if (parsed.positionals.length > 3) {
|
|
1142
|
+
throw new errors_1.UsageError("subgraph refresh accepts at most one alias");
|
|
1143
|
+
}
|
|
1144
|
+
const alias = parsed.positionals[2];
|
|
1145
|
+
const all = parseBooleanFlag("--all", parsed.flags["--all"]);
|
|
1146
|
+
(0, subgraph_1.runSubgraphRefreshCommand)({ root, alias, all, json });
|
|
1147
|
+
return 0;
|
|
1148
|
+
}
|
|
1149
|
+
default:
|
|
1150
|
+
throw new errors_1.UsageError("subgraph requires add/list/show/rm/enable/disable/verify/refresh");
|
|
1059
1151
|
}
|
|
1060
1152
|
}
|
|
1061
1153
|
function runWorkSubcommand(parsed, root) {
|
|
@@ -1567,6 +1659,8 @@ function runCommand(parsed, root, runtime) {
|
|
|
1567
1659
|
return runArchiveSubcommand(parsed, root);
|
|
1568
1660
|
case "bundle":
|
|
1569
1661
|
return runBundleSubcommand(parsed, root);
|
|
1662
|
+
case "subgraph":
|
|
1663
|
+
return runSubgraphSubcommand(parsed, root);
|
|
1570
1664
|
case "work":
|
|
1571
1665
|
return runWorkSubcommand(parsed, root);
|
|
1572
1666
|
case "task":
|
package/dist/commands/bundle.js
CHANGED
|
@@ -13,7 +13,7 @@ const path_1 = __importDefault(require("path"));
|
|
|
13
13
|
const child_process_1 = require("child_process");
|
|
14
14
|
const config_1 = require("../core/config");
|
|
15
15
|
const capabilities_indexer_1 = require("../graph/capabilities_indexer");
|
|
16
|
-
const
|
|
16
|
+
const subgraphs_1 = require("../graph/subgraphs");
|
|
17
17
|
const indexer_1 = require("../graph/indexer");
|
|
18
18
|
const skills_indexer_1 = require("../graph/skills_indexer");
|
|
19
19
|
const zip_1 = require("../util/zip");
|
|
@@ -386,11 +386,11 @@ function collectStringValues(value, out) {
|
|
|
386
386
|
}
|
|
387
387
|
}
|
|
388
388
|
}
|
|
389
|
-
function
|
|
390
|
-
const
|
|
389
|
+
function publicSubgraphReferenceErrors(config, index, includedQids) {
|
|
390
|
+
const privateSubgraphAliases = new Set(Object.entries(config.subgraphs)
|
|
391
391
|
.filter(([, entry]) => entry.enabled && entry.visibility !== "public")
|
|
392
392
|
.map(([alias]) => alias));
|
|
393
|
-
if (
|
|
393
|
+
if (privateSubgraphAliases.size === 0) {
|
|
394
394
|
return [];
|
|
395
395
|
}
|
|
396
396
|
const errors = [];
|
|
@@ -404,8 +404,8 @@ function publicImportReferenceErrors(config, index, includedQids) {
|
|
|
404
404
|
values.push(...node.links, ...node.artifacts, ...node.refs, ...node.aliases);
|
|
405
405
|
for (const value of values) {
|
|
406
406
|
const [alias] = value.split(":");
|
|
407
|
-
if (alias &&
|
|
408
|
-
errors.push(`${node.qid} references private
|
|
407
|
+
if (alias && privateSubgraphAliases.has(alias)) {
|
|
408
|
+
errors.push(`${node.qid} references private subgraph ${value}`);
|
|
409
409
|
}
|
|
410
410
|
}
|
|
411
411
|
}
|
|
@@ -465,7 +465,7 @@ function buildBundle(options) {
|
|
|
465
465
|
const filteredIndex = filterIndex(index, config, selectedSet, profile);
|
|
466
466
|
if (profile === "public") {
|
|
467
467
|
const includedQids = new Set(Object.keys(filteredIndex.nodes));
|
|
468
|
-
const mergedIndex = (0,
|
|
468
|
+
const mergedIndex = (0, subgraphs_1.mergeSubgraphsIntoIndex)(index, (0, subgraphs_1.buildSubgraphsIndex)(options.root, config));
|
|
469
469
|
const errors = (0, visibility_1.visibilityViolationMessages)((0, visibility_1.collectVisibilityViolations)(mergedIndex, config, {
|
|
470
470
|
includedQids,
|
|
471
471
|
scope: "public",
|
|
@@ -3,10 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.runCapabilityListCommand = runCapabilityListCommand;
|
|
4
4
|
exports.runCapabilitySearchCommand = runCapabilitySearchCommand;
|
|
5
5
|
exports.runCapabilityShowCommand = runCapabilityShowCommand;
|
|
6
|
+
exports.runCapabilityResolveCommand = runCapabilityResolveCommand;
|
|
6
7
|
const config_1 = require("../core/config");
|
|
7
8
|
const capabilities_indexer_1 = require("../graph/capabilities_indexer");
|
|
8
9
|
const capabilities_index_cache_1 = require("../graph/capabilities_index_cache");
|
|
9
|
-
const
|
|
10
|
+
const subgraphs_1 = require("../graph/subgraphs");
|
|
10
11
|
const errors_1 = require("../util/errors");
|
|
11
12
|
function normalizeKind(value) {
|
|
12
13
|
if (value === undefined) {
|
|
@@ -39,11 +40,11 @@ function loadRecords(options) {
|
|
|
39
40
|
if (stale && !rebuilt && !options.noCache) {
|
|
40
41
|
console.error("warning: capabilities index is stale; run mdkg index to refresh");
|
|
41
42
|
}
|
|
42
|
-
const
|
|
43
|
-
for (const warning of
|
|
43
|
+
const subgraph = (0, subgraphs_1.buildSubgraphCapabilityRecords)(options.root, config);
|
|
44
|
+
for (const warning of subgraph.warnings) {
|
|
44
45
|
console.error(`warning: ${warning}`);
|
|
45
46
|
}
|
|
46
|
-
return [...index.records, ...
|
|
47
|
+
return [...index.records, ...subgraph.records];
|
|
47
48
|
}
|
|
48
49
|
function applyFilters(records, options) {
|
|
49
50
|
const kind = normalizeKind(options.kind);
|
|
@@ -95,6 +96,89 @@ function matchesQuery(record, query) {
|
|
|
95
96
|
const text = capabilitySearchText(record);
|
|
96
97
|
return terms.every((term) => text.includes(term));
|
|
97
98
|
}
|
|
99
|
+
function recordSource(record) {
|
|
100
|
+
const source = record.source;
|
|
101
|
+
return source ?? {};
|
|
102
|
+
}
|
|
103
|
+
function isStale(record) {
|
|
104
|
+
return recordSource(record).stale === true;
|
|
105
|
+
}
|
|
106
|
+
function hasReadPermission(record) {
|
|
107
|
+
const permissions = recordSource(record).permissions;
|
|
108
|
+
return !Array.isArray(permissions) || permissions.includes("read");
|
|
109
|
+
}
|
|
110
|
+
function requirementMatch(record, required) {
|
|
111
|
+
if (!required) {
|
|
112
|
+
return 0;
|
|
113
|
+
}
|
|
114
|
+
const normalized = required.toLowerCase();
|
|
115
|
+
const haystack = [
|
|
116
|
+
...record.refs,
|
|
117
|
+
...record.tags,
|
|
118
|
+
JSON.stringify(record.spec ?? {}),
|
|
119
|
+
JSON.stringify(record.work ?? {}),
|
|
120
|
+
JSON.stringify(record.skill ?? {}),
|
|
121
|
+
]
|
|
122
|
+
.join(" ")
|
|
123
|
+
.toLowerCase();
|
|
124
|
+
return haystack.includes(normalized) ? 1 : 0;
|
|
125
|
+
}
|
|
126
|
+
function linkageScore(record) {
|
|
127
|
+
let score = 0;
|
|
128
|
+
if (record.kind === "work") {
|
|
129
|
+
score += 2;
|
|
130
|
+
}
|
|
131
|
+
if (record.kind === "spec") {
|
|
132
|
+
score += 1;
|
|
133
|
+
}
|
|
134
|
+
if (record.work || record.spec) {
|
|
135
|
+
score += 1;
|
|
136
|
+
}
|
|
137
|
+
return score;
|
|
138
|
+
}
|
|
139
|
+
function resolveScore(record, options) {
|
|
140
|
+
let score = 0;
|
|
141
|
+
if (record.workspace === "root") {
|
|
142
|
+
score += 1000;
|
|
143
|
+
}
|
|
144
|
+
if (!isStale(record)) {
|
|
145
|
+
score += 500;
|
|
146
|
+
}
|
|
147
|
+
if (hasReadPermission(record)) {
|
|
148
|
+
score += 100;
|
|
149
|
+
}
|
|
150
|
+
if (options.query && matchesQuery(record, options.query)) {
|
|
151
|
+
score += 50;
|
|
152
|
+
}
|
|
153
|
+
score += requirementMatch(record, options.requires) * 25;
|
|
154
|
+
score += linkageScore(record);
|
|
155
|
+
return score;
|
|
156
|
+
}
|
|
157
|
+
function resolveCapabilities(records, options) {
|
|
158
|
+
const filtered = records.filter((record) => {
|
|
159
|
+
if (options.freshOnly && isStale(record)) {
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
if (options.query && !matchesQuery(record, options.query)) {
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
if (options.requires && requirementMatch(record, options.requires) === 0) {
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
return true;
|
|
169
|
+
});
|
|
170
|
+
return filtered.sort((a, b) => {
|
|
171
|
+
const scoreDelta = resolveScore(b, options) - resolveScore(a, options);
|
|
172
|
+
if (scoreDelta !== 0) {
|
|
173
|
+
return scoreDelta;
|
|
174
|
+
}
|
|
175
|
+
const qidDelta = a.qid.localeCompare(b.qid);
|
|
176
|
+
if (qidDelta !== 0) {
|
|
177
|
+
return qidDelta;
|
|
178
|
+
}
|
|
179
|
+
return a.path.localeCompare(b.path);
|
|
180
|
+
});
|
|
181
|
+
}
|
|
98
182
|
function printCapabilityList(records, json, query) {
|
|
99
183
|
if (json) {
|
|
100
184
|
console.log(JSON.stringify({
|
|
@@ -160,3 +244,33 @@ function runCapabilityShowCommand(options) {
|
|
|
160
244
|
const records = loadRecords(options);
|
|
161
245
|
printCapability(resolveCapability(records, options.id), options.json);
|
|
162
246
|
}
|
|
247
|
+
function runCapabilityResolveCommand(options) {
|
|
248
|
+
const records = applyFilters(loadRecords(options), options);
|
|
249
|
+
const items = resolveCapabilities(records, options).map((record, rank) => ({
|
|
250
|
+
rank: rank + 1,
|
|
251
|
+
score: resolveScore(record, options),
|
|
252
|
+
stale: isStale(record),
|
|
253
|
+
item: record,
|
|
254
|
+
}));
|
|
255
|
+
if (options.json) {
|
|
256
|
+
console.log(JSON.stringify({
|
|
257
|
+
kind: "capability.resolve",
|
|
258
|
+
query: options.query,
|
|
259
|
+
requires: options.requires,
|
|
260
|
+
fresh_only: options.freshOnly === true,
|
|
261
|
+
count: items.length,
|
|
262
|
+
items,
|
|
263
|
+
}, null, 2));
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
if (items.length === 0) {
|
|
267
|
+
console.log("no capabilities resolved");
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
console.log(`resolved capabilities: ${items.length}`);
|
|
271
|
+
for (const result of items) {
|
|
272
|
+
const record = result.item;
|
|
273
|
+
const stale = result.stale ? " stale" : "";
|
|
274
|
+
console.log(`${result.rank}. ${record.qid} | score ${result.score}${stale} | ${record.kind} | ${record.title}`);
|
|
275
|
+
}
|
|
276
|
+
}
|