mdkg 0.3.0 → 0.3.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 +90 -1
- package/CLI_COMMAND_MATRIX.md +1188 -0
- package/README.md +86 -5
- package/dist/cli.js +130 -10
- package/dist/command-contract.json +7473 -0
- package/dist/commands/doctor.js +370 -86
- package/dist/commands/fix.js +934 -0
- package/dist/commands/format.js +8 -2
- package/dist/commands/goal.js +1 -1
- package/dist/commands/next.js +2 -2
- package/dist/commands/skill.js +13 -3
- package/dist/commands/skill_support.js +3 -3
- package/dist/commands/status.js +270 -0
- package/dist/commands/subgraph.js +300 -0
- package/dist/commands/task.js +2 -2
- package/dist/commands/validate.js +12 -1
- package/dist/commands/workspace.js +19 -7
- package/dist/graph/goal_scope.js +1 -1
- package/dist/graph/node.js +2 -1
- package/dist/init/CLI_COMMAND_MATRIX.md +20 -2
- package/dist/init/README.md +35 -2
- package/dist/init/core/rule-5-release-and-versioning.md +13 -4
- package/dist/init/init-manifest.json +9 -4
- package/dist/init/templates/default/spike.md +81 -0
- package/dist/pack/order.js +3 -2
- package/dist/util/argparse.js +1 -0
- package/package.json +11 -3
package/dist/commands/format.js
CHANGED
|
@@ -17,6 +17,8 @@ const errors_1 = require("../util/errors");
|
|
|
17
17
|
const date_1 = require("../util/date");
|
|
18
18
|
const id_1 = require("../util/id");
|
|
19
19
|
const refs_1 = require("../util/refs");
|
|
20
|
+
const atomic_1 = require("../util/atomic");
|
|
21
|
+
const lock_1 = require("../util/lock");
|
|
20
22
|
const DEC_ID_RE = /^dec-[0-9]+$/;
|
|
21
23
|
const DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
|
|
22
24
|
const ID_LIST_KEYS = new Set(["refs", "scope"]);
|
|
@@ -248,7 +250,7 @@ function normalizeFrontmatter(frontmatter, schema, type, workStatusEnum, priorit
|
|
|
248
250
|
}
|
|
249
251
|
return { normalized, errors };
|
|
250
252
|
}
|
|
251
|
-
function
|
|
253
|
+
function runFormatCommandLocked(options) {
|
|
252
254
|
const config = (0, config_1.loadConfig)(options.root);
|
|
253
255
|
const templateSchemas = (0, template_schema_1.loadTemplateSchemas)(options.root, config, node_1.ALLOWED_TYPES);
|
|
254
256
|
const filesByAlias = (0, workspace_files_1.listWorkspaceDocFilesByAlias)(options.root, config);
|
|
@@ -324,7 +326,11 @@ function runFormatCommand(options) {
|
|
|
324
326
|
throw new errors_1.ValidationError(`format failed with ${errors.length} error(s)`);
|
|
325
327
|
}
|
|
326
328
|
for (const update of updates) {
|
|
327
|
-
|
|
329
|
+
(0, atomic_1.atomicWriteFile)(update.filePath, update.content);
|
|
328
330
|
}
|
|
329
331
|
console.log(`format updated ${updates.length} file(s)`);
|
|
330
332
|
}
|
|
333
|
+
function runFormatCommand(options) {
|
|
334
|
+
const config = (0, config_1.loadConfig)(options.root);
|
|
335
|
+
return (0, lock_1.withMutationLock)(options.root, config.index.lock_timeout_ms, () => runFormatCommandLocked(options));
|
|
336
|
+
}
|
package/dist/commands/goal.js
CHANGED
|
@@ -29,7 +29,7 @@ const qid_1 = require("../util/qid");
|
|
|
29
29
|
const sort_1 = require("../util/sort");
|
|
30
30
|
const event_support_1 = require("./event_support");
|
|
31
31
|
const node_card_1 = require("./node_card");
|
|
32
|
-
const CONCRETE_GOAL_NEXT_TYPES = new Set(["feat", "task", "bug", "test"]);
|
|
32
|
+
const CONCRETE_GOAL_NEXT_TYPES = new Set(["feat", "task", "bug", "test", "spike"]);
|
|
33
33
|
const SELECTED_GOAL_STATE_PATH = path_1.default.join(".mdkg", "state", "selected-goal.json");
|
|
34
34
|
const GOAL_STATE_BY_ACTION = {
|
|
35
35
|
pause: "paused",
|
package/dist/commands/next.js
CHANGED
|
@@ -7,8 +7,8 @@ const errors_1 = require("../util/errors");
|
|
|
7
7
|
const qid_1 = require("../util/qid");
|
|
8
8
|
const sort_1 = require("../util/sort");
|
|
9
9
|
const node_card_1 = require("./node_card");
|
|
10
|
-
const NEXT_TYPES = new Set(["feat", "task", "bug", "test"]);
|
|
11
|
-
const NO_MATCH_MESSAGE = 'no matching work items found; consider `mdkg new task "..."` or `mdkg new
|
|
10
|
+
const NEXT_TYPES = new Set(["feat", "task", "bug", "test", "spike"]);
|
|
11
|
+
const NO_MATCH_MESSAGE = 'no matching work items found; consider `mdkg new task "..."`, `mdkg new test "..."`, or `mdkg new spike "..."`';
|
|
12
12
|
function normalizeWorkspace(value) {
|
|
13
13
|
if (!value || value === "all") {
|
|
14
14
|
return undefined;
|
package/dist/commands/skill.js
CHANGED
|
@@ -20,6 +20,8 @@ const skill_support_1 = require("./skill_support");
|
|
|
20
20
|
const query_output_1 = require("./query_output");
|
|
21
21
|
const event_support_1 = require("./event_support");
|
|
22
22
|
const skill_mirror_1 = require("./skill_mirror");
|
|
23
|
+
const atomic_1 = require("../util/atomic");
|
|
24
|
+
const lock_1 = require("../util/lock");
|
|
23
25
|
function parseCsvList(raw) {
|
|
24
26
|
if (!raw) {
|
|
25
27
|
return [];
|
|
@@ -142,7 +144,7 @@ function matchesSkillQuery(skill, terms) {
|
|
|
142
144
|
}
|
|
143
145
|
return true;
|
|
144
146
|
}
|
|
145
|
-
function
|
|
147
|
+
function runSkillNewCommandLocked(options) {
|
|
146
148
|
const root = options.root;
|
|
147
149
|
const config = (0, config_1.loadConfig)(root);
|
|
148
150
|
const slug = normalizeSlug(options.slug);
|
|
@@ -181,7 +183,7 @@ function runSkillNewCommand(options) {
|
|
|
181
183
|
authors,
|
|
182
184
|
links,
|
|
183
185
|
});
|
|
184
|
-
|
|
186
|
+
(0, atomic_1.atomicWriteFile)(canonicalPath, content);
|
|
185
187
|
(0, skill_support_1.ensureSkillsRegistry)(root, config);
|
|
186
188
|
(0, skill_support_1.refreshSkillsRegistry)(root, config);
|
|
187
189
|
if ((0, skill_mirror_1.shouldMaintainSkillMirrors)(root)) {
|
|
@@ -220,6 +222,10 @@ function runSkillNewCommand(options) {
|
|
|
220
222
|
}
|
|
221
223
|
console.log(`skill created: ${receipt.qid} (${receipt.path})`);
|
|
222
224
|
}
|
|
225
|
+
function runSkillNewCommand(options) {
|
|
226
|
+
const config = (0, config_1.loadConfig)(options.root);
|
|
227
|
+
return (0, lock_1.withMutationLock)(options.root, config.index.lock_timeout_ms, () => runSkillNewCommandLocked(options));
|
|
228
|
+
}
|
|
223
229
|
function runSkillListCommand(options) {
|
|
224
230
|
const config = (0, config_1.loadConfig)(options.root);
|
|
225
231
|
const { index, rebuilt, stale } = (0, skills_index_cache_1.loadSkillsIndex)({
|
|
@@ -426,7 +432,7 @@ function runSkillValidateCommand(options) {
|
|
|
426
432
|
}
|
|
427
433
|
console.log(`skill validation ok: ${checkedCount} skill${checkedCount === 1 ? "" : "s"} checked`);
|
|
428
434
|
}
|
|
429
|
-
function
|
|
435
|
+
function runSkillSyncCommandLocked(options) {
|
|
430
436
|
const config = (0, config_1.loadConfig)(options.root);
|
|
431
437
|
const result = (0, skill_mirror_1.syncSkillMirrors)({
|
|
432
438
|
root: options.root,
|
|
@@ -443,3 +449,7 @@ function runSkillSyncCommand(options) {
|
|
|
443
449
|
}
|
|
444
450
|
console.log(`skill mirror sync ok: ${result.synced} synced, ${result.pruned} pruned across ${result.targets} target${result.targets === 1 ? "" : "s"}`);
|
|
445
451
|
}
|
|
452
|
+
function runSkillSyncCommand(options) {
|
|
453
|
+
const config = (0, config_1.loadConfig)(options.root);
|
|
454
|
+
return (0, lock_1.withMutationLock)(options.root, config.index.lock_timeout_ms, () => runSkillSyncCommandLocked(options));
|
|
455
|
+
}
|
|
@@ -14,6 +14,7 @@ exports.formatSkillCard = formatSkillCard;
|
|
|
14
14
|
const fs_1 = __importDefault(require("fs"));
|
|
15
15
|
const path_1 = __importDefault(require("path"));
|
|
16
16
|
const skills_indexer_1 = require("../graph/skills_indexer");
|
|
17
|
+
const atomic_1 = require("../util/atomic");
|
|
17
18
|
exports.SKILL_REGISTRY_START = "<!-- mdkg:skill-registry:start -->";
|
|
18
19
|
exports.SKILL_REGISTRY_END = "<!-- mdkg:skill-registry:end -->";
|
|
19
20
|
function renderYamlList(values) {
|
|
@@ -105,8 +106,7 @@ function ensureSkillsRegistry(root, config) {
|
|
|
105
106
|
const skillsRoot = (0, skills_indexer_1.resolveSkillsRoot)(root, config);
|
|
106
107
|
const registryPath = path_1.default.join(skillsRoot, "registry.md");
|
|
107
108
|
if (!fs_1.default.existsSync(registryPath)) {
|
|
108
|
-
|
|
109
|
-
fs_1.default.writeFileSync(registryPath, registryTemplate(), "utf8");
|
|
109
|
+
(0, atomic_1.atomicWriteFile)(registryPath, registryTemplate());
|
|
110
110
|
}
|
|
111
111
|
return registryPath;
|
|
112
112
|
}
|
|
@@ -115,7 +115,7 @@ function refreshSkillsRegistry(root, config) {
|
|
|
115
115
|
const raw = fs_1.default.readFileSync(registryPath, "utf8");
|
|
116
116
|
const index = (0, skills_indexer_1.buildSkillsIndex)(root, config);
|
|
117
117
|
const updated = replaceManagedSection(raw, renderRegistryLines(index));
|
|
118
|
-
|
|
118
|
+
(0, atomic_1.atomicWriteFile)(registryPath, updated);
|
|
119
119
|
}
|
|
120
120
|
function formatSkillCard(skill) {
|
|
121
121
|
return [skill.qid, "skill", "-/-", skill.name, skill.path].join(" | ");
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.collectStatus = collectStatus;
|
|
7
|
+
exports.runStatusCommand = runStatusCommand;
|
|
8
|
+
const child_process_1 = require("child_process");
|
|
9
|
+
const fs_1 = __importDefault(require("fs"));
|
|
10
|
+
const path_1 = __importDefault(require("path"));
|
|
11
|
+
const config_1 = require("../core/config");
|
|
12
|
+
const project_db_migrations_1 = require("../core/project_db_migrations");
|
|
13
|
+
const version_1 = require("../core/version");
|
|
14
|
+
const capabilities_indexer_1 = require("../graph/capabilities_indexer");
|
|
15
|
+
const capabilities_index_cache_1 = require("../graph/capabilities_index_cache");
|
|
16
|
+
const index_cache_1 = require("../graph/index_cache");
|
|
17
|
+
const skills_indexer_1 = require("../graph/skills_indexer");
|
|
18
|
+
const skills_index_cache_1 = require("../graph/skills_index_cache");
|
|
19
|
+
const staleness_1 = require("../graph/staleness");
|
|
20
|
+
const subgraphs_1 = require("../graph/subgraphs");
|
|
21
|
+
const validate_graph_1 = require("../graph/validate_graph");
|
|
22
|
+
function rel(root, target) {
|
|
23
|
+
return path_1.default.relative(root, target).replace(/\\/g, "/") || ".";
|
|
24
|
+
}
|
|
25
|
+
function runGit(root, args) {
|
|
26
|
+
const result = (0, child_process_1.spawnSync)("git", args, { cwd: root, encoding: "utf8" });
|
|
27
|
+
if (result.status !== 0) {
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
return result.stdout.trim();
|
|
31
|
+
}
|
|
32
|
+
function gitStatus(root) {
|
|
33
|
+
const inside = runGit(root, ["rev-parse", "--is-inside-work-tree"]) === "true";
|
|
34
|
+
if (!inside) {
|
|
35
|
+
return {
|
|
36
|
+
inside: false,
|
|
37
|
+
branch: null,
|
|
38
|
+
dirty: false,
|
|
39
|
+
dirty_count: 0,
|
|
40
|
+
untracked_count: 0,
|
|
41
|
+
ahead: null,
|
|
42
|
+
behind: null,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
const branch = runGit(root, ["rev-parse", "--abbrev-ref", "HEAD"]) ?? null;
|
|
46
|
+
const porcelain = runGit(root, ["status", "--porcelain"]) ?? "";
|
|
47
|
+
const lines = porcelain.split(/\r?\n/).filter(Boolean);
|
|
48
|
+
const untracked = lines.filter((line) => line.startsWith("??")).length;
|
|
49
|
+
const aheadBehindRaw = runGit(root, ["rev-list", "--left-right", "--count", "HEAD...@{upstream}"]);
|
|
50
|
+
const [aheadRaw, behindRaw] = aheadBehindRaw ? aheadBehindRaw.split(/\s+/) : [];
|
|
51
|
+
return {
|
|
52
|
+
inside: true,
|
|
53
|
+
branch,
|
|
54
|
+
dirty: lines.length > 0,
|
|
55
|
+
dirty_count: lines.length,
|
|
56
|
+
untracked_count: untracked,
|
|
57
|
+
ahead: aheadRaw === undefined ? null : Number.parseInt(aheadRaw, 10),
|
|
58
|
+
behind: behindRaw === undefined ? null : Number.parseInt(behindRaw, 10),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function cacheStatus(root, filePath, stale) {
|
|
62
|
+
let staleValue = null;
|
|
63
|
+
try {
|
|
64
|
+
staleValue = stale();
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
staleValue = null;
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
path: rel(root, filePath),
|
|
71
|
+
exists: fs_1.default.existsSync(filePath),
|
|
72
|
+
stale: staleValue,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
function readSelectedGoalState(root) {
|
|
76
|
+
const filePath = path_1.default.join(root, ".mdkg", "state", "selected-goal.json");
|
|
77
|
+
if (!fs_1.default.existsSync(filePath)) {
|
|
78
|
+
return { state: null };
|
|
79
|
+
}
|
|
80
|
+
try {
|
|
81
|
+
const parsed = JSON.parse(fs_1.default.readFileSync(filePath, "utf8"));
|
|
82
|
+
if (typeof parsed.qid === "string" &&
|
|
83
|
+
typeof parsed.id === "string" &&
|
|
84
|
+
typeof parsed.ws === "string" &&
|
|
85
|
+
typeof parsed.selected_at === "string") {
|
|
86
|
+
return {
|
|
87
|
+
state: {
|
|
88
|
+
qid: parsed.qid.toLowerCase(),
|
|
89
|
+
id: parsed.id.toLowerCase(),
|
|
90
|
+
ws: parsed.ws.toLowerCase(),
|
|
91
|
+
selected_at: parsed.selected_at,
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
return { state: null, warning: "selected goal state is malformed" };
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
return { state: null, warning: "selected goal state is unreadable" };
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
function releaseStatus(root) {
|
|
102
|
+
const version = (0, version_1.readPackageVersion)();
|
|
103
|
+
const changelogPath = path_1.default.join(root, "CHANGELOG.md");
|
|
104
|
+
const changelogHasVersion = fs_1.default.existsSync(changelogPath)
|
|
105
|
+
? fs_1.default.readFileSync(changelogPath, "utf8").includes(`## ${version}`) ||
|
|
106
|
+
fs_1.default.readFileSync(changelogPath, "utf8").includes(`## [${version}]`)
|
|
107
|
+
: false;
|
|
108
|
+
return {
|
|
109
|
+
package_version: version,
|
|
110
|
+
changelog_path: fs_1.default.existsSync(changelogPath) ? "CHANGELOG.md" : null,
|
|
111
|
+
changelog_has_version: changelogHasVersion,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
function collectStatus(root) {
|
|
115
|
+
const warnings = [];
|
|
116
|
+
const errors = [];
|
|
117
|
+
const config = (0, config_1.loadConfig)(root);
|
|
118
|
+
let index;
|
|
119
|
+
let graphStale = false;
|
|
120
|
+
let graphWarnings = [];
|
|
121
|
+
let graphErrors = [];
|
|
122
|
+
try {
|
|
123
|
+
const loaded = (0, index_cache_1.loadIndex)({
|
|
124
|
+
root,
|
|
125
|
+
config,
|
|
126
|
+
useCache: true,
|
|
127
|
+
allowReindex: false,
|
|
128
|
+
includeImports: true,
|
|
129
|
+
});
|
|
130
|
+
index = loaded.index;
|
|
131
|
+
graphStale = loaded.stale;
|
|
132
|
+
graphWarnings = loaded.warnings;
|
|
133
|
+
graphErrors = (0, validate_graph_1.collectGraphErrors)(loaded.index);
|
|
134
|
+
}
|
|
135
|
+
catch (err) {
|
|
136
|
+
graphStale = true;
|
|
137
|
+
graphErrors = [err instanceof Error ? err.message : String(err)];
|
|
138
|
+
}
|
|
139
|
+
const selected = readSelectedGoalState(root);
|
|
140
|
+
if (selected.warning) {
|
|
141
|
+
warnings.push(selected.warning);
|
|
142
|
+
}
|
|
143
|
+
const selectedNode = selected.state && index ? index.nodes[selected.state.qid] : undefined;
|
|
144
|
+
const selectedAchieved = selectedNode?.status === "done" || String(selectedNode?.attributes.goal_state ?? "") === "achieved";
|
|
145
|
+
const selectedMissing = selected.state !== null && !selectedNode;
|
|
146
|
+
if (selectedMissing) {
|
|
147
|
+
warnings.push("selected goal is missing from the graph index");
|
|
148
|
+
}
|
|
149
|
+
if (selectedAchieved) {
|
|
150
|
+
warnings.push("selected goal is already achieved");
|
|
151
|
+
}
|
|
152
|
+
const git = gitStatus(root);
|
|
153
|
+
if (git.inside && git.dirty) {
|
|
154
|
+
warnings.push(`git worktree is dirty (${git.dirty_count} changed paths)`);
|
|
155
|
+
}
|
|
156
|
+
const generated = {
|
|
157
|
+
index: cacheStatus(root, path_1.default.resolve(root, config.index.global_index_path), () => (0, staleness_1.isIndexStale)(root, config)),
|
|
158
|
+
skills: cacheStatus(root, (0, skills_indexer_1.resolveSkillsIndexPath)(root), () => (0, skills_index_cache_1.isSkillsIndexStale)(root, config)),
|
|
159
|
+
capabilities: cacheStatus(root, (0, capabilities_indexer_1.resolveCapabilitiesIndexPath)(root, config), () => (0, capabilities_index_cache_1.isCapabilitiesIndexStale)(root, config)),
|
|
160
|
+
subgraphs: cacheStatus(root, (0, subgraphs_1.resolveSubgraphsIndexPath)(root), () => (0, subgraphs_1.isSubgraphsIndexStale)(root, config)),
|
|
161
|
+
};
|
|
162
|
+
let db = {
|
|
163
|
+
enabled: false,
|
|
164
|
+
ok: null,
|
|
165
|
+
database: null,
|
|
166
|
+
failure_count: 0,
|
|
167
|
+
warning_count: 0,
|
|
168
|
+
};
|
|
169
|
+
if (config.db.enabled) {
|
|
170
|
+
const verification = (0, project_db_migrations_1.verifyProjectDb)(root, config);
|
|
171
|
+
db = {
|
|
172
|
+
enabled: verification.enabled,
|
|
173
|
+
ok: verification.ok,
|
|
174
|
+
database: verification.database,
|
|
175
|
+
failure_count: verification.failure_count,
|
|
176
|
+
warning_count: verification.warning_count,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
if (graphErrors.length > 0) {
|
|
180
|
+
errors.push(...graphErrors.map((error) => `graph: ${error}`));
|
|
181
|
+
}
|
|
182
|
+
if (db.enabled && db.ok === false) {
|
|
183
|
+
errors.push("db: project DB verification failed");
|
|
184
|
+
}
|
|
185
|
+
if (graphStale) {
|
|
186
|
+
warnings.push("graph index cache is stale");
|
|
187
|
+
}
|
|
188
|
+
warnings.push(...graphWarnings.map((warning) => `graph: ${warning}`));
|
|
189
|
+
const cacheEntries = [
|
|
190
|
+
["index", generated.index, true],
|
|
191
|
+
["skills", generated.skills, true],
|
|
192
|
+
["capabilities", generated.capabilities, true],
|
|
193
|
+
["subgraphs", generated.subgraphs, Object.keys(config.subgraphs).length > 0],
|
|
194
|
+
];
|
|
195
|
+
for (const [name, cache, required] of cacheEntries) {
|
|
196
|
+
if (!required) {
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
if (!cache.exists) {
|
|
200
|
+
warnings.push(`${name} cache is missing`);
|
|
201
|
+
}
|
|
202
|
+
else if (cache.stale) {
|
|
203
|
+
warnings.push(`${name} cache is stale`);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
const level = errors.length > 0 ? "fail" : warnings.length > 0 ? "warn" : "ok";
|
|
207
|
+
return {
|
|
208
|
+
action: "status",
|
|
209
|
+
ok: errors.length === 0,
|
|
210
|
+
level,
|
|
211
|
+
root,
|
|
212
|
+
mdkg: {
|
|
213
|
+
version: (0, version_1.readPackageVersion)(),
|
|
214
|
+
config_schema_version: config.schema_version,
|
|
215
|
+
index_backend: config.index.backend,
|
|
216
|
+
},
|
|
217
|
+
git,
|
|
218
|
+
release: releaseStatus(root),
|
|
219
|
+
graph: {
|
|
220
|
+
ok: graphErrors.length === 0,
|
|
221
|
+
node_count: index ? Object.keys(index.nodes).length : null,
|
|
222
|
+
workspace_count: index ? Object.keys(index.workspaces).length : null,
|
|
223
|
+
stale: graphStale,
|
|
224
|
+
warning_count: graphWarnings.length,
|
|
225
|
+
error_count: graphErrors.length,
|
|
226
|
+
},
|
|
227
|
+
goal: {
|
|
228
|
+
selected: selected.state,
|
|
229
|
+
selected_exists: selected.state === null ? null : !selectedMissing,
|
|
230
|
+
selected_achieved: selected.state === null ? null : selectedAchieved,
|
|
231
|
+
active_node: selectedNode?.attributes.active_node ?? null,
|
|
232
|
+
goal_state: selectedNode?.attributes.goal_state ?? null,
|
|
233
|
+
status: selectedNode?.status ?? null,
|
|
234
|
+
},
|
|
235
|
+
db,
|
|
236
|
+
generated,
|
|
237
|
+
summary: {
|
|
238
|
+
level,
|
|
239
|
+
warning_count: warnings.length,
|
|
240
|
+
error_count: errors.length,
|
|
241
|
+
warnings,
|
|
242
|
+
errors,
|
|
243
|
+
},
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
function runStatusCommand(options) {
|
|
247
|
+
const payload = collectStatus(options.root);
|
|
248
|
+
if (options.json) {
|
|
249
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
console.log(`status ${payload.level}`);
|
|
253
|
+
console.log(`root: ${payload.root}`);
|
|
254
|
+
console.log(`mdkg: ${payload.mdkg.version}`);
|
|
255
|
+
console.log(`git: ${payload.git.inside ? `${payload.git.branch ?? "detached"} dirty=${payload.git.dirty}` : "not a git repo"}`);
|
|
256
|
+
console.log(`graph: ${payload.graph.ok ? "ok" : "fail"} nodes=${payload.graph.node_count ?? "unknown"} stale=${payload.graph.stale}`);
|
|
257
|
+
console.log(`db: ${payload.db.enabled ? (payload.db.ok ? "ok" : "fail") : "disabled"}`);
|
|
258
|
+
if (payload.goal.selected) {
|
|
259
|
+
console.log(`goal: ${payload.goal.selected.qid} status=${payload.goal.status ?? "unknown"} state=${payload.goal.goal_state ?? "unknown"}`);
|
|
260
|
+
}
|
|
261
|
+
else {
|
|
262
|
+
console.log("goal: none selected");
|
|
263
|
+
}
|
|
264
|
+
for (const warning of payload.summary.warnings) {
|
|
265
|
+
console.log(`warn: ${warning}`);
|
|
266
|
+
}
|
|
267
|
+
for (const error of payload.summary.errors) {
|
|
268
|
+
console.log(`fail: ${error}`);
|
|
269
|
+
}
|
|
270
|
+
}
|