mdkg 0.3.2 → 0.3.3
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 +35 -0
- package/CLI_COMMAND_MATRIX.md +8 -2
- package/README.md +2 -2
- package/dist/cli.js +35 -2
- package/dist/command-contract.json +171 -4
- package/dist/commands/goal.js +148 -12
- package/dist/commands/new.js +4 -3
- package/dist/graph/node.js +4 -3
- package/dist/graph/validate_graph.js +21 -0
- package/dist/init/AGENT_START.md +2 -2
- package/dist/init/CLI_COMMAND_MATRIX.md +6 -1
- package/dist/init/README.md +1 -1
- package/dist/init/init-manifest.json +5 -5
- package/dist/init/skills/default/pursue-mdkg-goal/SKILL.md +2 -1
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -12,6 +12,41 @@ mdkg is pre-v1 public alpha software. Command, graph, cache, bundle, and DAL con
|
|
|
12
12
|
|
|
13
13
|
- No changes yet.
|
|
14
14
|
|
|
15
|
+
## 0.3.3 - 2026-06-16
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- Added `mdkg goal activate <goal-id>` to make one local root goal active,
|
|
20
|
+
select it for goal routing, and pause competing active local root goals in the
|
|
21
|
+
same workspace.
|
|
22
|
+
- Added goal-only archived lifecycle support with `mdkg goal archive`, allowing
|
|
23
|
+
historical roadmap goals to remain readable through show/list/search while
|
|
24
|
+
being excluded from actionable current/next routing.
|
|
25
|
+
- Added parser and graph validation support for exactly one active local root
|
|
26
|
+
goal, while imported subgraph goals keep independent active-goal state in
|
|
27
|
+
their owning graphs.
|
|
28
|
+
- Added packed `smoke:goal-lifecycle` prepublish coverage for goal activation,
|
|
29
|
+
archived-goal routing, archived discovery filters, strict doctor behavior, and
|
|
30
|
+
imported subgraph active-goal independence.
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
|
|
34
|
+
- Updated README, init assets, agent startup guidance, command matrix, help
|
|
35
|
+
surfaces, generated command contract metadata, and publish-readiness assertions
|
|
36
|
+
to prefer `goal activate` for active goal selection.
|
|
37
|
+
- Archived superseded local roadmap goals `goal-11`, `goal-12`, and `goal-15`
|
|
38
|
+
in this repository after replacement versioned goals were created.
|
|
39
|
+
- Tightened the 0.3.3 graph hygiene path so the remaining release-candidate
|
|
40
|
+
sequence is smoke coverage followed by dry-run prepublish closeout.
|
|
41
|
+
|
|
42
|
+
### Security
|
|
43
|
+
|
|
44
|
+
- Archived goals are non-actionable historical context: they cannot be selected,
|
|
45
|
+
activated, claimed, resumed, or paused through the goal lifecycle surface.
|
|
46
|
+
- `goal activate` keeps single-writer planning safer by pausing competing local
|
|
47
|
+
root goals instead of allowing multiple active local root goals to remain
|
|
48
|
+
silently actionable.
|
|
49
|
+
|
|
15
50
|
## 0.3.2 - 2026-06-16
|
|
16
51
|
|
|
17
52
|
### Added
|
package/CLI_COMMAND_MATRIX.md
CHANGED
|
@@ -735,14 +735,16 @@ When to use:
|
|
|
735
735
|
Usage:
|
|
736
736
|
- `mdkg goal show <goal-id-or-qid> [--json]`
|
|
737
737
|
- `mdkg goal select <goal-id-or-qid> [--json]`
|
|
738
|
+
- `mdkg goal activate <goal-id-or-qid> [--json]`
|
|
738
739
|
- `mdkg goal current [--json]`
|
|
739
740
|
- `mdkg goal clear [--json]`
|
|
740
741
|
- `mdkg goal next [goal-id-or-qid] [--json]`
|
|
741
742
|
- `mdkg goal claim [goal-id-or-qid] <work-id-or-qid> [--json]`
|
|
742
743
|
- `mdkg goal evaluate <goal-id-or-qid> [--json]`
|
|
743
|
-
- `mdkg goal pause|resume|done <goal-id-or-qid> [--json]`
|
|
744
|
+
- `mdkg goal pause|resume|done|archive <goal-id-or-qid> [--json]`
|
|
744
745
|
- `mdkg goal show <goal-id-or-qid> [--ws <alias>] [--json]`
|
|
745
746
|
- `mdkg goal select <goal-id-or-qid> [--ws <alias>] [--json]`
|
|
747
|
+
- `mdkg goal activate <goal-id-or-qid> [--ws <alias>] [--json]`
|
|
746
748
|
- `mdkg goal current [--ws <alias>] [--json]`
|
|
747
749
|
- `mdkg goal next [goal-id-or-qid] [--ws <alias>] [--json]`
|
|
748
750
|
- `mdkg goal claim <work-id-or-qid> [--ws <alias>] [--json]`
|
|
@@ -751,27 +753,31 @@ Usage:
|
|
|
751
753
|
- `mdkg goal pause <goal-id-or-qid> [--ws <alias>] [--json]`
|
|
752
754
|
- `mdkg goal resume <goal-id-or-qid> [--ws <alias>] [--json]`
|
|
753
755
|
- `mdkg goal done <goal-id-or-qid> [--ws <alias>] [--json]`
|
|
756
|
+
- `mdkg goal archive <goal-id-or-qid> [--ws <alias>] [--json]`
|
|
754
757
|
|
|
755
758
|
Behavior:
|
|
756
759
|
- `goal show` reports goal condition, goal state, scope refs, active node, required skills, required checks, and source path.
|
|
757
760
|
- `goal select` writes local ignored selected-goal state so `goal next` can omit the goal id.
|
|
761
|
+
- `goal activate` makes one local root goal active, pauses competing local active goals in the same workspace, and writes selected-goal state.
|
|
758
762
|
- `goal current` shows the selected goal or unique active goal fallback.
|
|
759
763
|
- `goal clear` removes local selected-goal state.
|
|
760
764
|
- `goal next` is read-only and selects feature, task, bug, test, or spike work inside explicit `scope_refs`; epics are recursive containers, not executable returns.
|
|
761
765
|
- `goal claim` mutates only `active_node` after the work item is confirmed inside the goal scope.
|
|
762
766
|
- `goal evaluate` is report-only and never runs commands from `required_checks`.
|
|
763
767
|
- `goal pause`, `goal resume`, and `goal done` update `goal_state`, compatible work status, and `updated`.
|
|
768
|
+
- `goal archive` marks a superseded historical goal as `status: archived` and `goal_state: archived`; archived goals remain show/search/list readable but are excluded from active routing.
|
|
764
769
|
- subgraph goal qids are read-only; update the source workspace instead.
|
|
765
770
|
|
|
766
771
|
JSON receipts:
|
|
767
772
|
- `show`: `{ action: "showed", goal }`
|
|
768
773
|
- `select`: `{ action: "selected_goal", goal, selection }`
|
|
774
|
+
- `activate`: `{ action: "activated", goal, activated_goal, paused_goals, selection, warnings }`
|
|
769
775
|
- `current`: `{ action: "current", goal, source, warnings }`
|
|
770
776
|
- `clear`: `{ action: "cleared_goal", path, cleared }`
|
|
771
777
|
- `next`: `{ action: "selected", goal, goal_source, node, warnings }`
|
|
772
778
|
- `claim`: `{ action: "claimed", goal, node }`
|
|
773
779
|
- `evaluate`: `{ action: "evaluated", goal, report_only, runs_scripts, checks, completion_evidence_present }`
|
|
774
|
-
- `pause|resume|done`: `{ action, goal }`
|
|
780
|
+
- `pause|resume|done|archive`: `{ action, goal }`
|
|
775
781
|
|
|
776
782
|
### `mdkg task`
|
|
777
783
|
|
package/README.md
CHANGED
|
@@ -461,9 +461,9 @@ as sealed state.
|
|
|
461
461
|
|
|
462
462
|
Goal nodes are durable recursive objective contracts. Use `mdkg new goal "<objective>"` when a human or agent needs to keep working across multiple concrete nodes until a measurable end condition is achieved.
|
|
463
463
|
|
|
464
|
-
`goal` is work-like but distinct from `task`: it can have status, priority, graph links, skills, explicit `scope_refs`, and structured goal fields, but normal `mdkg next` does not select goals. Use `mdkg goal
|
|
464
|
+
`goal` is work-like but distinct from `task`: it can have status, priority, graph links, skills, explicit `scope_refs`, and structured goal fields, but normal `mdkg next` does not select goals. Use `mdkg goal activate <goal-id>` to make one local root goal active, pause competing local active goals, and select it for future `goal next` calls. Use `mdkg goal select <goal-id>` only when you want to change the local ignored selected-goal pointer without changing lifecycle state. `mdkg goal next <goal-id>` remains available for explicit selection. Epics organize goal scope recursively but are not returned as executable work.
|
|
465
465
|
|
|
466
|
-
Use `mdkg goal claim [goal-id] <work-id>` to durably set `active_node` after choosing the next scoped item. `goal next` is read-only. Use `mdkg goal pause|resume|done` to update goal state after review.
|
|
466
|
+
Use `mdkg goal claim [goal-id] <work-id>` to durably set `active_node` after choosing the next scoped item. `goal next` is read-only. Use `mdkg goal pause|resume|done` to update goal state after review, and `mdkg goal archive` for superseded historical roadmap goals that should remain readable but non-actionable.
|
|
467
467
|
|
|
468
468
|
Required checks are stored as report-only guidance. Agents should run the checks themselves, record evidence in the goal or active work item, then use `mdkg goal evaluate` to summarize the current evidence state. During normal goal execution, skill improvements should be recorded as improvement candidates or proposal nodes; edit `SKILL.md` files only when the active node is explicit skill-maintenance work.
|
|
469
469
|
|
package/dist/cli.js
CHANGED
|
@@ -752,6 +752,21 @@ function printGoalHelp(log, subcommand) {
|
|
|
752
752
|
log(" Store a local selected goal so `mdkg goal next` can omit the goal id.");
|
|
753
753
|
printGlobalOptions(log);
|
|
754
754
|
return;
|
|
755
|
+
case "activate":
|
|
756
|
+
log("Usage:");
|
|
757
|
+
log(" mdkg goal activate <goal-id-or-qid> [--ws <alias>] [--json]");
|
|
758
|
+
log("\nWhen to use:");
|
|
759
|
+
log(" Make one local root goal active, pause competing local active goals, and select it for `goal next`.");
|
|
760
|
+
log(" Imported subgraph goals are read-only and are not mutated by activation.");
|
|
761
|
+
printGlobalOptions(log);
|
|
762
|
+
return;
|
|
763
|
+
case "archive":
|
|
764
|
+
log("Usage:");
|
|
765
|
+
log(" mdkg goal archive <goal-id-or-qid> [--ws <alias>] [--json]");
|
|
766
|
+
log("\nWhen to use:");
|
|
767
|
+
log(" Mark a superseded historical goal archived so it remains readable but is excluded from active routing.");
|
|
768
|
+
printGlobalOptions(log);
|
|
769
|
+
return;
|
|
755
770
|
case "current":
|
|
756
771
|
log("Usage:");
|
|
757
772
|
log(" mdkg goal current [--ws <alias>] [--json]");
|
|
@@ -794,15 +809,17 @@ function printGoalHelp(log, subcommand) {
|
|
|
794
809
|
log("Usage:");
|
|
795
810
|
log(" mdkg goal show <goal-id-or-qid> [--json]");
|
|
796
811
|
log(" mdkg goal select <goal-id-or-qid> [--json]");
|
|
812
|
+
log(" mdkg goal activate <goal-id-or-qid> [--json]");
|
|
797
813
|
log(" mdkg goal current [--json]");
|
|
798
814
|
log(" mdkg goal next [goal-id-or-qid] [--json]");
|
|
799
815
|
log(" mdkg goal claim [goal-id-or-qid] <work-id-or-qid> [--json]");
|
|
800
816
|
log(" mdkg goal evaluate <goal-id-or-qid> [--json]");
|
|
801
817
|
log(" mdkg goal clear [--json]");
|
|
802
|
-
log(" mdkg goal pause|resume|done <goal-id-or-qid> [--json]");
|
|
818
|
+
log(" mdkg goal pause|resume|done|archive <goal-id-or-qid> [--json]");
|
|
803
819
|
log("\nNotes:");
|
|
804
820
|
log(" - goals orchestrate recursive progress; features, tasks, bugs, tests, and spikes are iterable work units");
|
|
805
821
|
log(" - `mdkg goal next` is read-only; use `mdkg goal claim` to update active_node");
|
|
822
|
+
log(" - `mdkg goal activate` enforces one active local root goal and pauses competing active goals");
|
|
806
823
|
log(" - goal evaluation is report-only and never executes required_checks");
|
|
807
824
|
log(" - subgraph goal qids are read-only; update the source workspace instead");
|
|
808
825
|
printGlobalOptions(log);
|
|
@@ -2090,6 +2107,14 @@ function runGoalSubcommand(parsed, root) {
|
|
|
2090
2107
|
(0, goal_1.runGoalSelectCommand)({ root, id, ws, json });
|
|
2091
2108
|
return 0;
|
|
2092
2109
|
}
|
|
2110
|
+
case "activate": {
|
|
2111
|
+
const id = parsed.positionals[2];
|
|
2112
|
+
if (!id || parsed.positionals.length > 3) {
|
|
2113
|
+
throw new errors_1.UsageError("goal activate requires <goal-id-or-qid>");
|
|
2114
|
+
}
|
|
2115
|
+
(0, goal_1.runGoalActivateCommand)({ root, id, ws, json });
|
|
2116
|
+
return 0;
|
|
2117
|
+
}
|
|
2093
2118
|
case "current":
|
|
2094
2119
|
if (parsed.positionals.length > 2) {
|
|
2095
2120
|
throw new errors_1.UsageError("goal current does not accept positional arguments");
|
|
@@ -2151,8 +2176,16 @@ function runGoalSubcommand(parsed, root) {
|
|
|
2151
2176
|
(0, goal_1.runGoalDoneCommand)({ root, id, ws, json });
|
|
2152
2177
|
return 0;
|
|
2153
2178
|
}
|
|
2179
|
+
case "archive": {
|
|
2180
|
+
const id = parsed.positionals[2];
|
|
2181
|
+
if (!id || parsed.positionals.length > 3) {
|
|
2182
|
+
throw new errors_1.UsageError("goal archive requires <goal-id-or-qid>");
|
|
2183
|
+
}
|
|
2184
|
+
(0, goal_1.runGoalArchiveCommand)({ root, id, ws, json });
|
|
2185
|
+
return 0;
|
|
2186
|
+
}
|
|
2154
2187
|
default:
|
|
2155
|
-
throw new errors_1.UsageError("goal requires show/select/current/clear/next/claim/evaluate/pause/resume/done");
|
|
2188
|
+
throw new errors_1.UsageError("goal requires show/select/activate/current/clear/next/claim/evaluate/pause/resume/done/archive");
|
|
2156
2189
|
}
|
|
2157
2190
|
}
|
|
2158
2191
|
function runTaskSubcommand(parsed, root) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema_version": 1,
|
|
3
3
|
"tool": "mdkg",
|
|
4
|
-
"package_version": "0.3.
|
|
4
|
+
"package_version": "0.3.3",
|
|
5
5
|
"source": {
|
|
6
6
|
"help_targets": "scripts/cli_help_targets.js",
|
|
7
7
|
"command_matrix": "CLI_COMMAND_MATRIX.md"
|
|
@@ -2430,12 +2430,13 @@
|
|
|
2430
2430
|
"usage": [
|
|
2431
2431
|
" mdkg goal show <goal-id-or-qid> [--json]",
|
|
2432
2432
|
" mdkg goal select <goal-id-or-qid> [--json]",
|
|
2433
|
+
" mdkg goal activate <goal-id-or-qid> [--json]",
|
|
2433
2434
|
" mdkg goal current [--json]",
|
|
2434
2435
|
" mdkg goal next [goal-id-or-qid] [--json]",
|
|
2435
2436
|
" mdkg goal claim [goal-id-or-qid] <work-id-or-qid> [--json]",
|
|
2436
2437
|
" mdkg goal evaluate <goal-id-or-qid> [--json]",
|
|
2437
2438
|
" mdkg goal clear [--json]",
|
|
2438
|
-
" mdkg goal pause|resume|done <goal-id-or-qid> [--json]"
|
|
2439
|
+
" mdkg goal pause|resume|done|archive <goal-id-or-qid> [--json]"
|
|
2439
2440
|
],
|
|
2440
2441
|
"args": [
|
|
2441
2442
|
{
|
|
@@ -2505,7 +2506,7 @@
|
|
|
2505
2506
|
}
|
|
2506
2507
|
],
|
|
2507
2508
|
"examples": [
|
|
2508
|
-
" mdkg goal
|
|
2509
|
+
" mdkg goal activate <goal-id-or-qid> [--json]",
|
|
2509
2510
|
" mdkg goal select <goal-id-or-qid> [--json]",
|
|
2510
2511
|
" mdkg goal show <goal-id-or-qid> [--json]"
|
|
2511
2512
|
],
|
|
@@ -2514,6 +2515,172 @@
|
|
|
2514
2515
|
"command_matrix": "CLI_COMMAND_MATRIX.md"
|
|
2515
2516
|
}
|
|
2516
2517
|
},
|
|
2518
|
+
{
|
|
2519
|
+
"key": "goal activate",
|
|
2520
|
+
"path": [
|
|
2521
|
+
"goal",
|
|
2522
|
+
"activate"
|
|
2523
|
+
],
|
|
2524
|
+
"category": "goal",
|
|
2525
|
+
"status": "stable",
|
|
2526
|
+
"visibility": "public",
|
|
2527
|
+
"summary": "mdkg goal activate command",
|
|
2528
|
+
"usage": [
|
|
2529
|
+
" mdkg goal activate <goal-id-or-qid> [--ws <alias>] [--json]"
|
|
2530
|
+
],
|
|
2531
|
+
"args": [
|
|
2532
|
+
{
|
|
2533
|
+
"name": "goal-id-or-qid",
|
|
2534
|
+
"required": true,
|
|
2535
|
+
"source": "<goal-id-or-qid>"
|
|
2536
|
+
}
|
|
2537
|
+
],
|
|
2538
|
+
"flags": [
|
|
2539
|
+
{
|
|
2540
|
+
"name": "--help",
|
|
2541
|
+
"value": null,
|
|
2542
|
+
"required": false,
|
|
2543
|
+
"description": "--help, -h Show help"
|
|
2544
|
+
},
|
|
2545
|
+
{
|
|
2546
|
+
"name": "--root",
|
|
2547
|
+
"value": null,
|
|
2548
|
+
"required": false,
|
|
2549
|
+
"description": "--root, -r <path> Run against a specific repo root"
|
|
2550
|
+
},
|
|
2551
|
+
{
|
|
2552
|
+
"name": "--version",
|
|
2553
|
+
"value": null,
|
|
2554
|
+
"required": false,
|
|
2555
|
+
"description": "--version, -V Show version"
|
|
2556
|
+
}
|
|
2557
|
+
],
|
|
2558
|
+
"output_formats": [
|
|
2559
|
+
"text",
|
|
2560
|
+
"json"
|
|
2561
|
+
],
|
|
2562
|
+
"json_schema_ref": "mdkg.command_output.v1",
|
|
2563
|
+
"side_effects": [
|
|
2564
|
+
"activate-goal-and-pause-competing-goals"
|
|
2565
|
+
],
|
|
2566
|
+
"read_paths": [
|
|
2567
|
+
".mdkg/**"
|
|
2568
|
+
],
|
|
2569
|
+
"write_paths": [
|
|
2570
|
+
".mdkg/**/*.md",
|
|
2571
|
+
".mdkg/index/**"
|
|
2572
|
+
],
|
|
2573
|
+
"dry_run": {
|
|
2574
|
+
"supported": false
|
|
2575
|
+
},
|
|
2576
|
+
"lock_policy": "mutation-lock-required",
|
|
2577
|
+
"atomic_write_policy": "atomic-file-writes",
|
|
2578
|
+
"receipts": [
|
|
2579
|
+
"goal-state-receipt"
|
|
2580
|
+
],
|
|
2581
|
+
"danger_level": "moderate",
|
|
2582
|
+
"aliases": [],
|
|
2583
|
+
"exit_codes": [
|
|
2584
|
+
{
|
|
2585
|
+
"code": 0,
|
|
2586
|
+
"meaning": "success"
|
|
2587
|
+
},
|
|
2588
|
+
{
|
|
2589
|
+
"code": 1,
|
|
2590
|
+
"meaning": "validation-or-runtime-error"
|
|
2591
|
+
}
|
|
2592
|
+
],
|
|
2593
|
+
"examples": [
|
|
2594
|
+
" mdkg goal activate <goal-id-or-qid> [--ws <alias>] [--json]"
|
|
2595
|
+
],
|
|
2596
|
+
"docs": {
|
|
2597
|
+
"help_target": "mdkg help goal activate",
|
|
2598
|
+
"command_matrix": "CLI_COMMAND_MATRIX.md"
|
|
2599
|
+
}
|
|
2600
|
+
},
|
|
2601
|
+
{
|
|
2602
|
+
"key": "goal archive",
|
|
2603
|
+
"path": [
|
|
2604
|
+
"goal",
|
|
2605
|
+
"archive"
|
|
2606
|
+
],
|
|
2607
|
+
"category": "goal",
|
|
2608
|
+
"status": "stable",
|
|
2609
|
+
"visibility": "public",
|
|
2610
|
+
"summary": "mdkg goal archive command",
|
|
2611
|
+
"usage": [
|
|
2612
|
+
" mdkg goal archive <goal-id-or-qid> [--ws <alias>] [--json]"
|
|
2613
|
+
],
|
|
2614
|
+
"args": [
|
|
2615
|
+
{
|
|
2616
|
+
"name": "goal-id-or-qid",
|
|
2617
|
+
"required": true,
|
|
2618
|
+
"source": "<goal-id-or-qid>"
|
|
2619
|
+
}
|
|
2620
|
+
],
|
|
2621
|
+
"flags": [
|
|
2622
|
+
{
|
|
2623
|
+
"name": "--help",
|
|
2624
|
+
"value": null,
|
|
2625
|
+
"required": false,
|
|
2626
|
+
"description": "--help, -h Show help"
|
|
2627
|
+
},
|
|
2628
|
+
{
|
|
2629
|
+
"name": "--root",
|
|
2630
|
+
"value": null,
|
|
2631
|
+
"required": false,
|
|
2632
|
+
"description": "--root, -r <path> Run against a specific repo root"
|
|
2633
|
+
},
|
|
2634
|
+
{
|
|
2635
|
+
"name": "--version",
|
|
2636
|
+
"value": null,
|
|
2637
|
+
"required": false,
|
|
2638
|
+
"description": "--version, -V Show version"
|
|
2639
|
+
}
|
|
2640
|
+
],
|
|
2641
|
+
"output_formats": [
|
|
2642
|
+
"text",
|
|
2643
|
+
"json"
|
|
2644
|
+
],
|
|
2645
|
+
"json_schema_ref": "mdkg.command_output.v1",
|
|
2646
|
+
"side_effects": [
|
|
2647
|
+
"archive-goal"
|
|
2648
|
+
],
|
|
2649
|
+
"read_paths": [
|
|
2650
|
+
".mdkg/**"
|
|
2651
|
+
],
|
|
2652
|
+
"write_paths": [
|
|
2653
|
+
".mdkg/**/*.md",
|
|
2654
|
+
".mdkg/index/**"
|
|
2655
|
+
],
|
|
2656
|
+
"dry_run": {
|
|
2657
|
+
"supported": false
|
|
2658
|
+
},
|
|
2659
|
+
"lock_policy": "mutation-lock-required",
|
|
2660
|
+
"atomic_write_policy": "atomic-file-writes",
|
|
2661
|
+
"receipts": [
|
|
2662
|
+
"goal-state-receipt"
|
|
2663
|
+
],
|
|
2664
|
+
"danger_level": "moderate",
|
|
2665
|
+
"aliases": [],
|
|
2666
|
+
"exit_codes": [
|
|
2667
|
+
{
|
|
2668
|
+
"code": 0,
|
|
2669
|
+
"meaning": "success"
|
|
2670
|
+
},
|
|
2671
|
+
{
|
|
2672
|
+
"code": 1,
|
|
2673
|
+
"meaning": "validation-or-runtime-error"
|
|
2674
|
+
}
|
|
2675
|
+
],
|
|
2676
|
+
"examples": [
|
|
2677
|
+
" mdkg goal archive <goal-id-or-qid> [--ws <alias>] [--json]"
|
|
2678
|
+
],
|
|
2679
|
+
"docs": {
|
|
2680
|
+
"help_target": "mdkg help goal archive",
|
|
2681
|
+
"command_matrix": "CLI_COMMAND_MATRIX.md"
|
|
2682
|
+
}
|
|
2683
|
+
},
|
|
2517
2684
|
{
|
|
2518
2685
|
"key": "goal claim",
|
|
2519
2686
|
"path": [
|
|
@@ -7469,5 +7636,5 @@
|
|
|
7469
7636
|
}
|
|
7470
7637
|
}
|
|
7471
7638
|
],
|
|
7472
|
-
"contract_hash": "
|
|
7639
|
+
"contract_hash": "be42c29b89c1c3e3d059a8f9cbc564908d4dd694d848cf3d1b1800e8b30705e5"
|
|
7473
7640
|
}
|
package/dist/commands/goal.js
CHANGED
|
@@ -7,12 +7,14 @@ exports.runGoalShowCommand = runGoalShowCommand;
|
|
|
7
7
|
exports.runGoalEvaluateCommand = runGoalEvaluateCommand;
|
|
8
8
|
exports.runGoalNextCommand = runGoalNextCommand;
|
|
9
9
|
exports.runGoalSelectCommand = runGoalSelectCommand;
|
|
10
|
+
exports.runGoalActivateCommand = runGoalActivateCommand;
|
|
10
11
|
exports.runGoalCurrentCommand = runGoalCurrentCommand;
|
|
11
12
|
exports.runGoalClearCommand = runGoalClearCommand;
|
|
12
13
|
exports.runGoalClaimCommand = runGoalClaimCommand;
|
|
13
14
|
exports.runGoalPauseCommand = runGoalPauseCommand;
|
|
14
15
|
exports.runGoalResumeCommand = runGoalResumeCommand;
|
|
15
16
|
exports.runGoalDoneCommand = runGoalDoneCommand;
|
|
17
|
+
exports.runGoalArchiveCommand = runGoalArchiveCommand;
|
|
16
18
|
const fs_1 = __importDefault(require("fs"));
|
|
17
19
|
const path_1 = __importDefault(require("path"));
|
|
18
20
|
const config_1 = require("../core/config");
|
|
@@ -35,11 +37,13 @@ const GOAL_STATE_BY_ACTION = {
|
|
|
35
37
|
pause: "paused",
|
|
36
38
|
resume: "active",
|
|
37
39
|
done: "achieved",
|
|
40
|
+
archive: "archived",
|
|
38
41
|
};
|
|
39
42
|
const STATUS_BY_ACTION = {
|
|
40
43
|
pause: "blocked",
|
|
41
44
|
resume: "progress",
|
|
42
45
|
done: "done",
|
|
46
|
+
archive: "archived",
|
|
43
47
|
};
|
|
44
48
|
function normalizeWorkspace(value) {
|
|
45
49
|
if (!value) {
|
|
@@ -95,6 +99,22 @@ function writeSelectedGoalState(root, node, now) {
|
|
|
95
99
|
};
|
|
96
100
|
(0, atomic_1.atomicWriteFile)(selectedGoalPath(root), `${JSON.stringify(state, null, 2)}\n`);
|
|
97
101
|
}
|
|
102
|
+
function readNodeFrontmatter(root, node) {
|
|
103
|
+
const filePath = path_1.default.resolve(root, node.path);
|
|
104
|
+
const parsed = (0, frontmatter_1.parseFrontmatter)(fs_1.default.readFileSync(filePath, "utf8"), filePath);
|
|
105
|
+
return {
|
|
106
|
+
filePath,
|
|
107
|
+
frontmatter: { ...parsed.frontmatter },
|
|
108
|
+
body: parsed.body,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
function writeNodeFrontmatterFile(filePath, frontmatter, body, now) {
|
|
112
|
+
frontmatter.updated = (0, date_1.formatDate)(now);
|
|
113
|
+
const lines = (0, frontmatter_1.formatFrontmatter)(frontmatter, frontmatter_1.DEFAULT_FRONTMATTER_KEY_ORDER);
|
|
114
|
+
const frontmatterBlock = ["---", ...lines, "---"].join("\n");
|
|
115
|
+
const content = body.length > 0 ? `${frontmatterBlock}\n${body}` : frontmatterBlock;
|
|
116
|
+
(0, atomic_1.atomicWriteFile)(filePath, content);
|
|
117
|
+
}
|
|
98
118
|
function removeSelectedGoalState(root) {
|
|
99
119
|
const filePath = selectedGoalPath(root);
|
|
100
120
|
if (!fs_1.default.existsSync(filePath)) {
|
|
@@ -125,6 +145,14 @@ function activeGoalCandidates(index, wsHint) {
|
|
|
125
145
|
.filter((node) => node.status === "progress" && node.attributes.goal_state === "active")
|
|
126
146
|
.sort((a, b) => a.qid.localeCompare(b.qid));
|
|
127
147
|
}
|
|
148
|
+
function activeGoalConflicts(index, target) {
|
|
149
|
+
return activeGoalCandidates(index, target.ws).filter((node) => node.qid !== target.qid);
|
|
150
|
+
}
|
|
151
|
+
function isArchivedGoal(node) {
|
|
152
|
+
return Boolean(node &&
|
|
153
|
+
node.type === "goal" &&
|
|
154
|
+
(node.status === "archived" || node.attributes.goal_state === "archived"));
|
|
155
|
+
}
|
|
128
156
|
function resolveGoalSelection(root, index, idOrQid, wsHint) {
|
|
129
157
|
const warnings = [];
|
|
130
158
|
if (idOrQid) {
|
|
@@ -137,19 +165,24 @@ function resolveGoalSelection(root, index, idOrQid, wsHint) {
|
|
|
137
165
|
const selected = readSelectedGoalState(root, warnings);
|
|
138
166
|
if (selected) {
|
|
139
167
|
const node = index.nodes[selected.qid];
|
|
140
|
-
if (node && node.type === "goal" && !node.source?.imported) {
|
|
168
|
+
if (node && node.type === "goal" && !node.source?.imported && !isArchivedGoal(node)) {
|
|
141
169
|
return { node, source: "selected", warnings };
|
|
142
170
|
}
|
|
143
|
-
|
|
171
|
+
if (isArchivedGoal(node)) {
|
|
172
|
+
warnings.push(`selected goal ${selected.qid} is archived; run \`mdkg goal activate <goal-id>\` or \`mdkg goal clear\``);
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
warnings.push(`selected goal ${selected.qid} is not available; run \`mdkg goal select <goal-id>\``);
|
|
176
|
+
}
|
|
144
177
|
}
|
|
145
178
|
const active = activeGoalCandidates(index, wsHint);
|
|
146
179
|
if (active.length === 1) {
|
|
147
180
|
return { node: active[0], source: "unique_active", warnings };
|
|
148
181
|
}
|
|
149
182
|
if (active.length > 1) {
|
|
150
|
-
throw new errors_1.UsageError(`multiple active goals found: ${active.map((node) => node.qid).join(", ")}; run \`mdkg goal
|
|
183
|
+
throw new errors_1.UsageError(`multiple active goals found: ${active.map((node) => node.qid).join(", ")}; run \`mdkg goal activate <goal-id>\``);
|
|
151
184
|
}
|
|
152
|
-
throw new errors_1.NotFoundError("no selected goal or unique active goal found; run `mdkg goal
|
|
185
|
+
throw new errors_1.NotFoundError("no selected goal or unique active goal found; run `mdkg goal activate <goal-id>`");
|
|
153
186
|
}
|
|
154
187
|
function loadGoal(root, idOrQid, wsHint) {
|
|
155
188
|
const config = (0, config_1.loadConfig)(root);
|
|
@@ -201,11 +234,7 @@ function goalReceipt(root, loaded) {
|
|
|
201
234
|
};
|
|
202
235
|
}
|
|
203
236
|
function writeGoalFile(loaded, now) {
|
|
204
|
-
loaded.frontmatter.
|
|
205
|
-
const lines = (0, frontmatter_1.formatFrontmatter)(loaded.frontmatter, frontmatter_1.DEFAULT_FRONTMATTER_KEY_ORDER);
|
|
206
|
-
const frontmatterBlock = ["---", ...lines, "---"].join("\n");
|
|
207
|
-
const content = loaded.body.length > 0 ? `${frontmatterBlock}\n${loaded.body}` : frontmatterBlock;
|
|
208
|
-
(0, atomic_1.atomicWriteFile)(loaded.filePath, content);
|
|
237
|
+
writeNodeFrontmatterFile(loaded.filePath, loaded.frontmatter, loaded.body, now);
|
|
209
238
|
}
|
|
210
239
|
function maybeReindex(root, config) {
|
|
211
240
|
if (!config.index.auto_reindex) {
|
|
@@ -215,6 +244,9 @@ function maybeReindex(root, config) {
|
|
|
215
244
|
}
|
|
216
245
|
function ensureStatusAllowed(config, status) {
|
|
217
246
|
const normalized = status.toLowerCase();
|
|
247
|
+
if (normalized === "archived") {
|
|
248
|
+
return normalized;
|
|
249
|
+
}
|
|
218
250
|
const allowed = new Set(config.work.status_enum.map((value) => value.toLowerCase()));
|
|
219
251
|
if (!allowed.has(normalized)) {
|
|
220
252
|
throw new errors_1.UsageError(`goal status ${normalized} is not allowed by work.status_enum`);
|
|
@@ -301,6 +333,24 @@ function runGoalEvaluateCommand(options) {
|
|
|
301
333
|
}
|
|
302
334
|
function runGoalNextCommand(options) {
|
|
303
335
|
const loaded = loadGoal(options.root, options.id, options.ws);
|
|
336
|
+
if (isArchivedGoal(loaded.node)) {
|
|
337
|
+
const warnings = [...loaded.warnings, `${loaded.node.qid} is archived and has no actionable next work`];
|
|
338
|
+
if (options.json) {
|
|
339
|
+
console.log(JSON.stringify({
|
|
340
|
+
action: "selected",
|
|
341
|
+
goal: goalReceipt(options.root, loaded),
|
|
342
|
+
goal_source: loaded.resolutionSource,
|
|
343
|
+
node: null,
|
|
344
|
+
warnings,
|
|
345
|
+
}, null, 2));
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
for (const warning of warnings) {
|
|
349
|
+
console.error(`warning: ${warning}`);
|
|
350
|
+
}
|
|
351
|
+
console.error("no actionable local work found for goal");
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
304
354
|
const statusPreference = loaded.config.work.next.status_preference.map((status) => status.toLowerCase());
|
|
305
355
|
const statusRanks = new Set(statusPreference);
|
|
306
356
|
const warnings = [...loaded.warnings];
|
|
@@ -362,6 +412,9 @@ function runGoalSelectCommand(options) {
|
|
|
362
412
|
const config = (0, config_1.loadConfig)(options.root);
|
|
363
413
|
return (0, lock_1.withMutationLock)(options.root, config.index.lock_timeout_ms, () => {
|
|
364
414
|
const loaded = loadGoal(options.root, options.id, options.ws);
|
|
415
|
+
if (isArchivedGoal(loaded.node)) {
|
|
416
|
+
throw new errors_1.UsageError(`cannot select archived goal ${loaded.node.qid}`);
|
|
417
|
+
}
|
|
365
418
|
const now = options.now ?? new Date();
|
|
366
419
|
writeSelectedGoalState(options.root, loaded.node, now);
|
|
367
420
|
const receipt = {
|
|
@@ -379,6 +432,74 @@ function runGoalSelectCommand(options) {
|
|
|
379
432
|
console.log(`selected goal: ${loaded.node.qid}`);
|
|
380
433
|
});
|
|
381
434
|
}
|
|
435
|
+
function runGoalActivateCommand(options) {
|
|
436
|
+
const config = (0, config_1.loadConfig)(options.root);
|
|
437
|
+
return (0, lock_1.withMutationLock)(options.root, config.index.lock_timeout_ms, () => {
|
|
438
|
+
const loaded = loadGoal(options.root, options.id, options.ws);
|
|
439
|
+
const currentState = String(loaded.frontmatter.goal_state ?? "");
|
|
440
|
+
const currentStatus = String(loaded.frontmatter.status ?? "");
|
|
441
|
+
if (loaded.node.status === "done" || currentStatus === "done" || currentState === "achieved") {
|
|
442
|
+
throw new errors_1.UsageError(`cannot activate achieved goal ${loaded.node.qid}`);
|
|
443
|
+
}
|
|
444
|
+
if (loaded.node.status === "archived" || currentStatus === "archived" || currentState === "archived") {
|
|
445
|
+
throw new errors_1.UsageError(`cannot activate archived goal ${loaded.node.qid}`);
|
|
446
|
+
}
|
|
447
|
+
const now = options.now ?? new Date();
|
|
448
|
+
const pausedGoals = [];
|
|
449
|
+
const conflicts = activeGoalConflicts(loaded.index, loaded.node);
|
|
450
|
+
for (const conflict of conflicts) {
|
|
451
|
+
const conflictFile = readNodeFrontmatter(options.root, conflict);
|
|
452
|
+
conflictFile.frontmatter.goal_state = "paused";
|
|
453
|
+
conflictFile.frontmatter.status = ensureStatusAllowed(config, "blocked");
|
|
454
|
+
writeNodeFrontmatterFile(conflictFile.filePath, conflictFile.frontmatter, conflictFile.body, now);
|
|
455
|
+
pausedGoals.push({
|
|
456
|
+
workspace: conflict.ws,
|
|
457
|
+
id: conflict.id,
|
|
458
|
+
qid: conflict.qid,
|
|
459
|
+
path: conflict.path,
|
|
460
|
+
previous_status: conflict.status ?? "",
|
|
461
|
+
previous_goal_state: String(conflict.attributes.goal_state ?? ""),
|
|
462
|
+
status: "blocked",
|
|
463
|
+
goal_state: "paused",
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
loaded.frontmatter.goal_state = "active";
|
|
467
|
+
loaded.frontmatter.status = ensureStatusAllowed(config, "progress");
|
|
468
|
+
writeGoalFile(loaded, now);
|
|
469
|
+
writeSelectedGoalState(options.root, loaded.node, now);
|
|
470
|
+
maybeReindex(options.root, loaded.config);
|
|
471
|
+
(0, event_support_1.appendAutomaticEvent)({
|
|
472
|
+
root: options.root,
|
|
473
|
+
ws: loaded.node.ws,
|
|
474
|
+
kind: "GOAL_ACTIVATE",
|
|
475
|
+
status: "ok",
|
|
476
|
+
refs: [loaded.node.id, ...conflicts.map((node) => node.id)],
|
|
477
|
+
notes: `goal activate via mdkg goal activate`,
|
|
478
|
+
now,
|
|
479
|
+
});
|
|
480
|
+
const receipt = {
|
|
481
|
+
action: "activated",
|
|
482
|
+
goal: goalReceipt(options.root, loaded),
|
|
483
|
+
activated_goal: goalReceipt(options.root, loaded),
|
|
484
|
+
paused_goals: pausedGoals,
|
|
485
|
+
selection: {
|
|
486
|
+
path: SELECTED_GOAL_STATE_PATH,
|
|
487
|
+
selected_at: now.toISOString(),
|
|
488
|
+
},
|
|
489
|
+
warnings: conflicts.length > 0
|
|
490
|
+
? [`paused ${conflicts.length} competing active goal(s) in workspace ${loaded.node.ws}`]
|
|
491
|
+
: [],
|
|
492
|
+
};
|
|
493
|
+
if (options.json) {
|
|
494
|
+
console.log(JSON.stringify(receipt, null, 2));
|
|
495
|
+
return;
|
|
496
|
+
}
|
|
497
|
+
for (const warning of receipt.warnings) {
|
|
498
|
+
console.error(`warning: ${warning}`);
|
|
499
|
+
}
|
|
500
|
+
console.log(`goal activate: ${loaded.node.qid}`);
|
|
501
|
+
});
|
|
502
|
+
}
|
|
382
503
|
function runGoalCurrentCommand(options) {
|
|
383
504
|
const config = (0, config_1.loadConfig)(options.root);
|
|
384
505
|
const { index } = (0, index_cache_1.loadIndex)({ root: options.root, config });
|
|
@@ -389,12 +510,17 @@ function runGoalCurrentCommand(options) {
|
|
|
389
510
|
const selected = readSelectedGoalState(options.root, warnings);
|
|
390
511
|
if (selected) {
|
|
391
512
|
const selectedNode = index.nodes[selected.qid];
|
|
392
|
-
if (selectedNode && selectedNode.type === "goal" && !selectedNode.source?.imported) {
|
|
513
|
+
if (selectedNode && selectedNode.type === "goal" && !selectedNode.source?.imported && !isArchivedGoal(selectedNode)) {
|
|
393
514
|
node = selectedNode;
|
|
394
515
|
source = "selected";
|
|
395
516
|
}
|
|
396
517
|
else {
|
|
397
|
-
|
|
518
|
+
if (isArchivedGoal(selectedNode)) {
|
|
519
|
+
warnings.push(`selected goal ${selected.qid} is archived; run \`mdkg goal activate <goal-id>\` or \`mdkg goal clear\``);
|
|
520
|
+
}
|
|
521
|
+
else {
|
|
522
|
+
warnings.push(`selected goal ${selected.qid} is not available; run \`mdkg goal select <goal-id>\``);
|
|
523
|
+
}
|
|
398
524
|
}
|
|
399
525
|
}
|
|
400
526
|
if (!node) {
|
|
@@ -405,7 +531,7 @@ function runGoalCurrentCommand(options) {
|
|
|
405
531
|
}
|
|
406
532
|
else if (active.length > 1) {
|
|
407
533
|
source = "ambiguous";
|
|
408
|
-
warnings.push(`multiple active goals found: ${active.map((goal) => goal.qid).join(", ")}
|
|
534
|
+
warnings.push(`multiple active goals found: ${active.map((goal) => goal.qid).join(", ")}; run \`mdkg goal activate <goal-id>\``);
|
|
409
535
|
}
|
|
410
536
|
}
|
|
411
537
|
const receipt = {
|
|
@@ -464,6 +590,9 @@ function runGoalClaimCommand(options) {
|
|
|
464
590
|
const config = (0, config_1.loadConfig)(options.root);
|
|
465
591
|
return (0, lock_1.withMutationLock)(options.root, config.index.lock_timeout_ms, () => {
|
|
466
592
|
const loaded = loadGoal(options.root, options.id, options.ws);
|
|
593
|
+
if (isArchivedGoal(loaded.node)) {
|
|
594
|
+
throw new errors_1.UsageError(`cannot claim work for archived goal ${loaded.node.qid}`);
|
|
595
|
+
}
|
|
467
596
|
const resolved = (0, qid_1.resolveQid)(loaded.index, options.workId, loaded.node.ws);
|
|
468
597
|
if (resolved.status !== "ok") {
|
|
469
598
|
throw new errors_1.NotFoundError((0, qid_1.formatResolveError)("work", options.workId, resolved, loaded.node.ws));
|
|
@@ -510,6 +639,9 @@ function runGoalClaimCommand(options) {
|
|
|
510
639
|
}
|
|
511
640
|
function runGoalStateMutationLocked(action, options) {
|
|
512
641
|
const loaded = loadGoal(options.root, options.id, options.ws);
|
|
642
|
+
if (action !== "archive" && isArchivedGoal(loaded.node)) {
|
|
643
|
+
throw new errors_1.UsageError(`cannot ${action} archived goal ${loaded.node.qid}`);
|
|
644
|
+
}
|
|
513
645
|
const now = options.now ?? new Date();
|
|
514
646
|
loaded.frontmatter.goal_state = GOAL_STATE_BY_ACTION[action];
|
|
515
647
|
loaded.frontmatter.status = ensureStatusAllowed(loaded.config, STATUS_BY_ACTION[action]);
|
|
@@ -546,3 +678,7 @@ function runGoalDoneCommand(options) {
|
|
|
546
678
|
const config = (0, config_1.loadConfig)(options.root);
|
|
547
679
|
return (0, lock_1.withMutationLock)(options.root, config.index.lock_timeout_ms, () => runGoalStateMutationLocked("done", options));
|
|
548
680
|
}
|
|
681
|
+
function runGoalArchiveCommand(options) {
|
|
682
|
+
const config = (0, config_1.loadConfig)(options.root);
|
|
683
|
+
return (0, lock_1.withMutationLock)(options.root, config.index.lock_timeout_ms, () => runGoalStateMutationLocked("archive", options));
|
|
684
|
+
}
|
package/dist/commands/new.js
CHANGED
|
@@ -228,11 +228,12 @@ function runNewCommandLocked(options) {
|
|
|
228
228
|
let status;
|
|
229
229
|
if (node_1.WORK_TYPES.has(type)) {
|
|
230
230
|
const allowed = new Set(config.work.status_enum.map((value) => value.toLowerCase()));
|
|
231
|
+
const allowedForType = type === "goal" ? new Set([...allowed, "archived"]) : allowed;
|
|
231
232
|
status = statusInput ?? (type === "goal" && allowed.has("progress")
|
|
232
233
|
? "progress"
|
|
233
234
|
: config.work.status_enum[0]?.toLowerCase());
|
|
234
|
-
if (!status || !
|
|
235
|
-
throw new errors_1.UsageError(`--status must be one of ${Array.from(
|
|
235
|
+
if (!status || !allowedForType.has(status)) {
|
|
236
|
+
throw new errors_1.UsageError(`--status must be one of ${Array.from(allowedForType).join(", ")}`);
|
|
236
237
|
}
|
|
237
238
|
}
|
|
238
239
|
else if (type === "dec") {
|
|
@@ -346,7 +347,7 @@ function runNewCommandLocked(options) {
|
|
|
346
347
|
skills: skills.length > 0 ? skills : undefined,
|
|
347
348
|
cases: cases.length > 0 ? cases : undefined,
|
|
348
349
|
supersedes: options.supersedes ? options.supersedes.toLowerCase() : undefined,
|
|
349
|
-
goal_state: type === "goal" ? (status === "done" ? "achieved" : status === "blocked" ? "blocked" : "active") : undefined,
|
|
350
|
+
goal_state: type === "goal" ? (status === "done" ? "achieved" : status === "blocked" ? "blocked" : status === "archived" ? "archived" : "active") : undefined,
|
|
350
351
|
goal_condition: type === "goal" ? title : undefined,
|
|
351
352
|
max_iterations: type === "goal" ? 25 : undefined,
|
|
352
353
|
blocked_after_attempts: type === "goal" ? 3 : undefined,
|
package/dist/graph/node.js
CHANGED
|
@@ -30,7 +30,7 @@ exports.ALLOWED_TYPES = new Set([
|
|
|
30
30
|
...agent_file_types_1.AGENT_FILE_TYPES,
|
|
31
31
|
]);
|
|
32
32
|
const DEC_STATUS = new Set(["proposed", "accepted", "rejected", "superseded"]);
|
|
33
|
-
const GOAL_STATE = new Set(["active", "paused", "achieved", "blocked", "budget_limited"]);
|
|
33
|
+
const GOAL_STATE = new Set(["active", "paused", "achieved", "blocked", "budget_limited", "archived"]);
|
|
34
34
|
const SKILL_SLUG_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
35
35
|
const GOAL_ATTRIBUTE_KEYS = [
|
|
36
36
|
"goal_state",
|
|
@@ -280,13 +280,14 @@ function parseNode(content, filePath, options) {
|
|
|
280
280
|
const statusValue = optionalString(frontmatter, "status", filePath);
|
|
281
281
|
let status = undefined;
|
|
282
282
|
const workStatus = new Set(options.workStatusEnum.map((value) => value.toLowerCase()));
|
|
283
|
+
const allowedWorkStatus = type === "goal" ? new Set([...workStatus, "archived"]) : workStatus;
|
|
283
284
|
if (exports.WORK_TYPES.has(type)) {
|
|
284
285
|
if (!statusValue) {
|
|
285
286
|
throw formatError(filePath, "status is required for work items");
|
|
286
287
|
}
|
|
287
288
|
const normalized = requireLowercase(statusValue, "status", filePath);
|
|
288
|
-
if (!
|
|
289
|
-
throw formatError(filePath, `status must be one of ${Array.from(
|
|
289
|
+
if (!allowedWorkStatus.has(normalized)) {
|
|
290
|
+
throw formatError(filePath, `status must be one of ${Array.from(allowedWorkStatus).join(", ")}`);
|
|
290
291
|
}
|
|
291
292
|
status = normalized;
|
|
292
293
|
}
|
|
@@ -485,6 +485,26 @@ function validateGoalRefs(index, allowMissing, errors) {
|
|
|
485
485
|
}
|
|
486
486
|
}
|
|
487
487
|
}
|
|
488
|
+
function validateSingleActiveRootGoals(index, errors) {
|
|
489
|
+
const activeByWorkspace = {};
|
|
490
|
+
for (const [qid, node] of Object.entries(index.nodes)) {
|
|
491
|
+
if (node.type !== "goal" || node.source?.imported) {
|
|
492
|
+
continue;
|
|
493
|
+
}
|
|
494
|
+
if (node.status === "progress" && node.attributes.goal_state === "active") {
|
|
495
|
+
if (!activeByWorkspace[node.ws]) {
|
|
496
|
+
activeByWorkspace[node.ws] = [];
|
|
497
|
+
}
|
|
498
|
+
activeByWorkspace[node.ws].push(qid);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
for (const [workspace, qids] of Object.entries(activeByWorkspace)) {
|
|
502
|
+
if (qids.length <= 1) {
|
|
503
|
+
continue;
|
|
504
|
+
}
|
|
505
|
+
pushError(errors, `${workspace}: multiple active root goals found: ${qids.sort().join(", ")}; run mdkg goal activate <goal-id> to select exactly one`);
|
|
506
|
+
}
|
|
507
|
+
}
|
|
488
508
|
function detectPrevNextCycles(index, errors) {
|
|
489
509
|
const nodes = index.nodes;
|
|
490
510
|
const seen = new Set();
|
|
@@ -533,6 +553,7 @@ function collectGraphErrors(index, options = {}) {
|
|
|
533
553
|
validateAgentWorkflowFeedbackProposalRefs(index, allowMissing, knownSkillSlugs, externalWorkspaces, errors);
|
|
534
554
|
validateArchiveUriRefs(index, allowMissing, errors);
|
|
535
555
|
validateGoalRefs(index, allowMissing, errors);
|
|
556
|
+
validateSingleActiveRootGoals(index, errors);
|
|
536
557
|
detectPrevNextCycles(index, errors);
|
|
537
558
|
return errors;
|
|
538
559
|
}
|
package/dist/init/AGENT_START.md
CHANGED
|
@@ -24,7 +24,7 @@ Agent operating prompt:
|
|
|
24
24
|
- Use `mdkg show <id>` for direct inspection and `mdkg show <id> --meta` for card-only inspection.
|
|
25
25
|
- Use `mdkg search "..."` and `mdkg next` to discover current work.
|
|
26
26
|
- Use `mdkg new goal "..."` for long-running recursive objectives that need an explicit end condition, active node, required skills, required checks, and completion evidence.
|
|
27
|
-
- Use `mdkg goal
|
|
27
|
+
- Use `mdkg goal activate <goal-id>` to make one local root goal active, then `mdkg goal next` to surface one scoped feature, task, bug, test, or spike at a time; normal `mdkg next` remains for non-goal concrete work.
|
|
28
28
|
- Use `mdkg goal claim [goal-id] <work-id>` only after accepting the surfaced work item; `mdkg goal next` is read-only.
|
|
29
29
|
- Treat goal `required_checks` as report-only guidance from mdkg. Run commands yourself, then record evidence in the goal or active work item.
|
|
30
30
|
- Record skill improvement candidates during normal goal execution; edit `SKILL.md` only when the active node is explicit skill-maintenance work.
|
|
@@ -78,7 +78,7 @@ If the active task is known:
|
|
|
78
78
|
- `mdkg validate`
|
|
79
79
|
|
|
80
80
|
If an active goal is known:
|
|
81
|
-
- `mdkg goal
|
|
81
|
+
- `mdkg goal activate <goal-id>`
|
|
82
82
|
- `mdkg goal current`
|
|
83
83
|
- `mdkg goal next`
|
|
84
84
|
- `mdkg goal claim <work-id>`
|
|
@@ -242,14 +242,16 @@ Work semantic mirrors:
|
|
|
242
242
|
Goal nodes:
|
|
243
243
|
- `mdkg goal show <goal-id-or-qid> [--json]`
|
|
244
244
|
- `mdkg goal select <goal-id-or-qid> [--json]`
|
|
245
|
+
- `mdkg goal activate <goal-id-or-qid> [--json]`
|
|
245
246
|
- `mdkg goal current [--json]`
|
|
246
247
|
- `mdkg goal clear [--json]`
|
|
247
248
|
- `mdkg goal next [goal-id-or-qid] [--json]`
|
|
248
249
|
- `mdkg goal claim [goal-id-or-qid] <work-id-or-qid> [--json]`
|
|
249
250
|
- `mdkg goal evaluate <goal-id-or-qid> [--json]`
|
|
250
|
-
- `mdkg goal pause|resume|done <goal-id-or-qid> [--json]`
|
|
251
|
+
- `mdkg goal pause|resume|done|archive <goal-id-or-qid> [--json]`
|
|
251
252
|
- `mdkg goal show <goal-id-or-qid> [--ws <alias>] [--json]`
|
|
252
253
|
- `mdkg goal select <goal-id-or-qid> [--ws <alias>] [--json]`
|
|
254
|
+
- `mdkg goal activate <goal-id-or-qid> [--ws <alias>] [--json]`
|
|
253
255
|
- `mdkg goal current [--ws <alias>] [--json]`
|
|
254
256
|
- `mdkg goal next [goal-id-or-qid] [--ws <alias>] [--json]`
|
|
255
257
|
- `mdkg goal claim <work-id-or-qid> [--ws <alias>] [--json]`
|
|
@@ -258,7 +260,10 @@ Goal nodes:
|
|
|
258
260
|
- `mdkg goal pause <goal-id-or-qid> [--ws <alias>] [--json]`
|
|
259
261
|
- `mdkg goal resume <goal-id-or-qid> [--ws <alias>] [--json]`
|
|
260
262
|
- `mdkg goal done <goal-id-or-qid> [--ws <alias>] [--json]`
|
|
263
|
+
- `mdkg goal archive <goal-id-or-qid> [--ws <alias>] [--json]`
|
|
261
264
|
- goals orchestrate recursive progress through explicit `scope_refs`; tasks, bugs, tests, spikes, and features remain concrete executable units
|
|
265
|
+
- `goal activate` makes one local root goal active, pauses competing local active goals in the same workspace, and writes selected-goal state
|
|
266
|
+
- `goal archive` marks a superseded historical goal archived so it remains readable but not actionable
|
|
262
267
|
- `goal next` is read-only; use `goal claim` to set `active_node`
|
|
263
268
|
- `mdkg goal evaluate` is report-only and never runs commands from `required_checks`
|
|
264
269
|
- skill improvements discovered during normal goal execution should be recorded as candidates or proposals unless the active node is skill-maintenance
|
package/dist/init/README.md
CHANGED
|
@@ -35,7 +35,7 @@ mdkg fix plan --json
|
|
|
35
35
|
mdkg validate
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
-
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
|
|
38
|
+
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 subgraph ...` to register read-only child graph planning views, `mdkg pack <id>` to build deterministic context, and `mdkg validate` before closeout.
|
|
39
39
|
|
|
40
40
|
Use `mdkg status --json` for a read-only operator summary of Git, graph,
|
|
41
41
|
selected-goal, project DB, and generated-cache health before mutating work. Use
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema_version": 1,
|
|
3
3
|
"tool": "mdkg",
|
|
4
|
-
"mdkg_version": "0.3.
|
|
4
|
+
"mdkg_version": "0.3.3",
|
|
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": "
|
|
64
|
+
"sha256": "68b5f4d2d04a4dc9a062e54a594d684b3816c0b614079eb6b08f0dca16fd0b47"
|
|
65
65
|
},
|
|
66
66
|
{
|
|
67
67
|
"path": ".mdkg/skills/build-pack-and-execute-task/SKILL.md",
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
{
|
|
72
72
|
"path": ".mdkg/skills/pursue-mdkg-goal/SKILL.md",
|
|
73
73
|
"category": "default_skill",
|
|
74
|
-
"sha256": "
|
|
74
|
+
"sha256": "2bc888092d95b362e402494af4dbe6909204bd5578613d6159753a84efaae16d"
|
|
75
75
|
},
|
|
76
76
|
{
|
|
77
77
|
"path": ".mdkg/skills/select-work-and-ground-context/SKILL.md",
|
|
@@ -246,7 +246,7 @@
|
|
|
246
246
|
{
|
|
247
247
|
"path": "AGENT_START.md",
|
|
248
248
|
"category": "startup_doc",
|
|
249
|
-
"sha256": "
|
|
249
|
+
"sha256": "46e734b6eae92eb957c3e29fb4d206e4be3fd6d32dd00e888e01a0dc75979428"
|
|
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": "
|
|
264
|
+
"sha256": "7f27715427a6762ef987fb872c9e09976075c76fddac68c4df89387e5b8a6909"
|
|
265
265
|
},
|
|
266
266
|
{
|
|
267
267
|
"path": "llms.txt",
|
|
@@ -27,7 +27,8 @@ Move one durable mdkg goal forward without losing scope, evidence, or user inten
|
|
|
27
27
|
## Steps
|
|
28
28
|
|
|
29
29
|
1. Resolve the goal:
|
|
30
|
-
- If a goal id is provided, run `mdkg goal
|
|
30
|
+
- If a goal id is provided and you are beginning durable work on it, run `mdkg goal activate <goal-id>`.
|
|
31
|
+
- Use `mdkg goal select <goal-id>` only when you need a local pointer without changing lifecycle state.
|
|
31
32
|
- Otherwise run `mdkg goal current`.
|
|
32
33
|
- If the result is missing or ambiguous, ask the user to select a goal.
|
|
33
34
|
2. Inspect the goal with `mdkg goal show <goal-id>` and build context with `mdkg pack <goal-id>`.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mdkg",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"description": "Markdown Knowledge Graph",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bin": {
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"smoke:branch-conflicts": "npm run build && node scripts/smoke-branch-conflicts.js",
|
|
31
31
|
"smoke:command-docs": "npm run build && node scripts/smoke-command-docs.js",
|
|
32
32
|
"smoke:spike": "npm run build && node scripts/smoke-spike.js",
|
|
33
|
+
"smoke:goal-lifecycle": "npm run build && node scripts/smoke-goal-lifecycle.js",
|
|
33
34
|
"smoke:bundle": "npm run build && node scripts/smoke-bundle.js",
|
|
34
35
|
"smoke:bundle-import": "npm run smoke:subgraph",
|
|
35
36
|
"smoke:visibility": "npm run build && node scripts/smoke-visibility.js",
|
|
@@ -40,7 +41,7 @@
|
|
|
40
41
|
"cli:check": "npm run build && node scripts/cli_help_snapshot.js --check",
|
|
41
42
|
"cli:contract": "npm run build && node scripts/generate-command-contract.js --check",
|
|
42
43
|
"prepack": "npm run build && node scripts/assert-publish-ready.js",
|
|
43
|
-
"prepublishOnly": "npm run test && npm run cli:check && npm run cli:contract && node dist/cli.js validate && npm run smoke:consumer && npm run smoke:matrix && npm run smoke:upgrade && npm run smoke:init && npm run smoke:capabilities && npm run smoke:db && npm run smoke:db-queue && npm run smoke:db-queue-cli && npm run smoke:db-events && npm run smoke:db-materializer && npm run smoke:db-snapshot && npm run smoke:archive-work && npm run smoke:work-invocation && npm run smoke:cli-ux-polish && npm run smoke:operator-health && npm run smoke:fix-plan && npm run smoke:branch-conflicts && npm run smoke:command-docs && npm run smoke:spike && npm run smoke:bundle && npm run smoke:subgraph && npm run smoke:visibility && npm run smoke:sqlite && npm run smoke:parallel && npm run smoke:goal && node scripts/assert-publish-ready.js",
|
|
44
|
+
"prepublishOnly": "npm run test && npm run cli:check && npm run cli:contract && node dist/cli.js validate && npm run smoke:consumer && npm run smoke:matrix && npm run smoke:upgrade && npm run smoke:init && npm run smoke:capabilities && npm run smoke:db && npm run smoke:db-queue && npm run smoke:db-queue-cli && npm run smoke:db-events && npm run smoke:db-materializer && npm run smoke:db-snapshot && npm run smoke:archive-work && npm run smoke:work-invocation && npm run smoke:cli-ux-polish && npm run smoke:operator-health && npm run smoke:fix-plan && npm run smoke:branch-conflicts && npm run smoke:command-docs && npm run smoke:spike && npm run smoke:goal-lifecycle && npm run smoke:bundle && npm run smoke:subgraph && npm run smoke:visibility && npm run smoke:sqlite && npm run smoke:parallel && npm run smoke:goal && node scripts/assert-publish-ready.js",
|
|
44
45
|
"postinstall": "node scripts/postinstall.js",
|
|
45
46
|
"smoke:subgraph": "npm run build && node scripts/smoke-subgraph.js"
|
|
46
47
|
},
|