mdkg 0.0.8 → 0.1.0
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 +71 -0
- package/CONTRIBUTING.md +124 -0
- package/README.md +49 -14
- package/dist/cli.js +113 -32
- package/dist/commands/checkpoint.js +19 -2
- package/dist/commands/event.js +12 -0
- package/dist/commands/init.js +4 -0
- package/dist/commands/init_manifest.js +131 -0
- package/dist/commands/new.js +57 -21
- package/dist/commands/pack.js +14 -0
- package/dist/commands/query_output.js +2 -0
- package/dist/commands/search.js +8 -0
- package/dist/commands/show.js +7 -0
- package/dist/commands/skill.js +80 -12
- package/dist/commands/task.js +42 -12
- package/dist/commands/upgrade.js +286 -0
- package/dist/commands/validate.js +31 -3
- package/dist/commands/workspace.js +105 -13
- package/dist/core/config.js +217 -22
- package/dist/core/migrate.js +39 -5
- package/dist/core/version.js +31 -0
- package/dist/core/workspace_path.js +41 -0
- package/dist/graph/agent_file_types.js +392 -0
- package/dist/graph/edges.js +13 -10
- package/dist/graph/frontmatter.js +33 -0
- package/dist/graph/indexer.js +1 -0
- package/dist/graph/node.js +43 -16
- package/dist/graph/skills_indexer.js +14 -1
- package/dist/graph/template_schema.js +13 -126
- package/dist/graph/validate_graph.js +302 -2
- package/dist/init/AGENT_START.md +14 -2
- package/dist/init/CLI_COMMAND_MATRIX.md +49 -1
- package/dist/init/README.md +14 -0
- package/dist/init/core/rule-6-templates-and-schemas.md +1 -3
- package/dist/init/init-manifest.json +197 -0
- package/dist/init/legacy/v0.0.9-init-manifest.json +197 -0
- package/dist/init/skills/default/verify-close-and-checkpoint/SKILL.md +12 -11
- package/dist/init/templates/default/dispute.md +31 -0
- package/dist/init/templates/default/feedback.md +27 -0
- package/dist/init/templates/default/proposal.md +35 -0
- package/dist/init/templates/default/receipt.md +31 -0
- package/dist/init/templates/default/spec.md +43 -0
- package/dist/init/templates/default/work.md +44 -0
- package/dist/init/templates/default/work_order.md +32 -0
- package/dist/pack/export_json.js +3 -0
- package/dist/pack/export_md.js +9 -0
- package/dist/pack/export_xml.js +9 -0
- package/dist/pack/order.js +7 -0
- package/dist/pack/pack.js +1 -0
- package/dist/templates/loader.js +2 -2
- package/dist/util/argparse.js +2 -0
- package/dist/util/id.js +19 -0
- package/package.json +10 -2
- package/scripts/postinstall.js +89 -0
package/dist/commands/new.js
CHANGED
|
@@ -9,8 +9,8 @@ const path_1 = __importDefault(require("path"));
|
|
|
9
9
|
const config_1 = require("../core/config");
|
|
10
10
|
const index_cache_1 = require("../graph/index_cache");
|
|
11
11
|
const node_1 = require("../graph/node");
|
|
12
|
+
const agent_file_types_1 = require("../graph/agent_file_types");
|
|
12
13
|
const indexer_1 = require("../graph/indexer");
|
|
13
|
-
const template_schema_1 = require("../graph/template_schema");
|
|
14
14
|
const loader_1 = require("../templates/loader");
|
|
15
15
|
const date_1 = require("../util/date");
|
|
16
16
|
const errors_1 = require("../util/errors");
|
|
@@ -45,6 +45,13 @@ function normalizeIdRef(value, key) {
|
|
|
45
45
|
}
|
|
46
46
|
return normalized;
|
|
47
47
|
}
|
|
48
|
+
function normalizeAgentFileId(value) {
|
|
49
|
+
const normalized = value.toLowerCase();
|
|
50
|
+
if (!(0, id_1.isPortableId)(normalized)) {
|
|
51
|
+
throw new errors_1.UsageError("--id must be a lowercase portable id for agent workflow file types");
|
|
52
|
+
}
|
|
53
|
+
return normalized;
|
|
54
|
+
}
|
|
48
55
|
function normalizeList(raw) {
|
|
49
56
|
return parseCsvList(raw);
|
|
50
57
|
}
|
|
@@ -111,6 +118,9 @@ function idPrefixForType(type) {
|
|
|
111
118
|
if (type === "checkpoint") {
|
|
112
119
|
return "chk";
|
|
113
120
|
}
|
|
121
|
+
if (type === "work_order") {
|
|
122
|
+
return "order";
|
|
123
|
+
}
|
|
114
124
|
return type;
|
|
115
125
|
}
|
|
116
126
|
function folderForType(type) {
|
|
@@ -123,8 +133,17 @@ function folderForType(type) {
|
|
|
123
133
|
if (node_1.WORK_TYPES.has(type)) {
|
|
124
134
|
return "work";
|
|
125
135
|
}
|
|
136
|
+
if ((0, agent_file_types_1.isAgentFileType)(type)) {
|
|
137
|
+
return "work";
|
|
138
|
+
}
|
|
126
139
|
throw new errors_1.UsageError(`unsupported type: ${type}`);
|
|
127
140
|
}
|
|
141
|
+
function fileNameForType(type, id, slug) {
|
|
142
|
+
if ((0, agent_file_types_1.isAgentFileType)(type)) {
|
|
143
|
+
return path_1.default.join(`${id}-${slug}`, agent_file_types_1.AGENT_FILE_BASENAMES[type]);
|
|
144
|
+
}
|
|
145
|
+
return `${id}-${slug}.md`;
|
|
146
|
+
}
|
|
128
147
|
function ensureExists(index, value, ws, label) {
|
|
129
148
|
const resolved = (0, qid_1.resolveQid)(index, value, ws);
|
|
130
149
|
if (resolved.status !== "ok") {
|
|
@@ -153,10 +172,18 @@ function runNewCommand(options) {
|
|
|
153
172
|
useCache: !noCache,
|
|
154
173
|
allowReindex: !noReindex,
|
|
155
174
|
});
|
|
175
|
+
if (options.id !== undefined && !(0, agent_file_types_1.isAgentFileType)(type)) {
|
|
176
|
+
throw new errors_1.UsageError("--id is only valid for agent workflow file types");
|
|
177
|
+
}
|
|
156
178
|
const prefix = idPrefixForType(type);
|
|
157
|
-
const id =
|
|
179
|
+
const id = options.id !== undefined
|
|
180
|
+
? normalizeAgentFileId(options.id)
|
|
181
|
+
: nextIdForPrefix(index.nodes, ws, prefix);
|
|
182
|
+
if (index.nodes[`${ws}:${id}`]) {
|
|
183
|
+
throw new errors_1.UsageError(`node already exists: ${ws}:${id}`);
|
|
184
|
+
}
|
|
158
185
|
const slug = slugifyTitle(title);
|
|
159
|
-
const fileName =
|
|
186
|
+
const fileName = fileNameForType(type, id, slug);
|
|
160
187
|
const wsEntry = config.workspaces[ws];
|
|
161
188
|
const folder = folderForType(type);
|
|
162
189
|
const targetDir = path_1.default.resolve(options.root, wsEntry.path, wsEntry.mdkg_dir, folder);
|
|
@@ -173,7 +200,7 @@ function runNewCommand(options) {
|
|
|
173
200
|
throw new errors_1.UsageError(`--status must be one of ${Array.from(allowed).join(", ")}`);
|
|
174
201
|
}
|
|
175
202
|
}
|
|
176
|
-
else if (
|
|
203
|
+
else if (type === "dec") {
|
|
177
204
|
status = statusInput ?? "proposed";
|
|
178
205
|
if (!DEC_STATUS.has(status)) {
|
|
179
206
|
throw new errors_1.UsageError(`--status must be one of ${Array.from(DEC_STATUS).join(", ")}`);
|
|
@@ -197,20 +224,12 @@ function runNewCommand(options) {
|
|
|
197
224
|
else if (options.priority !== undefined) {
|
|
198
225
|
throw new errors_1.UsageError("--priority is only valid for work items");
|
|
199
226
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
["prev", options.prev],
|
|
204
|
-
["next", options.next],
|
|
205
|
-
["blocked_by", options.blockedBy],
|
|
206
|
-
["blocks", options.blocks],
|
|
207
|
-
];
|
|
208
|
-
for (const [key, raw] of graphFields) {
|
|
209
|
-
if (raw && !(0, template_schema_1.schemaAllowsKey)(type, key)) {
|
|
210
|
-
throw new errors_1.UsageError(`--${key.replace("_", "-")} is not valid for ${type} nodes`);
|
|
227
|
+
if (!node_1.WORK_TYPES.has(type)) {
|
|
228
|
+
if (options.epic || options.parent || options.prev || options.next || options.blockedBy || options.blocks) {
|
|
229
|
+
throw new errors_1.UsageError("epic/parent/prev/next/blocked-by/blocks are only valid for work items");
|
|
211
230
|
}
|
|
212
231
|
}
|
|
213
|
-
if (options.cases &&
|
|
232
|
+
if (options.cases && type !== "test") {
|
|
214
233
|
throw new errors_1.UsageError("--cases is only valid for test nodes");
|
|
215
234
|
}
|
|
216
235
|
const epic = options.epic ? normalizeIdRef(options.epic, "--epic") : undefined;
|
|
@@ -228,7 +247,7 @@ function runNewCommand(options) {
|
|
|
228
247
|
const skills = normalizeSkillList(options.skills);
|
|
229
248
|
const links = normalizeList(options.links);
|
|
230
249
|
const artifacts = normalizeList(options.artifacts);
|
|
231
|
-
if (skills.length > 0 && !
|
|
250
|
+
if (skills.length > 0 && !node_1.WORK_TYPES.has(type)) {
|
|
232
251
|
throw new errors_1.UsageError("--skills is only valid for work items");
|
|
233
252
|
}
|
|
234
253
|
if (type === "dec" && options.supersedes) {
|
|
@@ -267,7 +286,6 @@ function runNewCommand(options) {
|
|
|
267
286
|
}
|
|
268
287
|
const today = (0, date_1.formatDate)(options.now ?? new Date());
|
|
269
288
|
const template = (0, loader_1.loadTemplate)(options.root, config, type, options.template);
|
|
270
|
-
const schema = (0, template_schema_1.getNodeSchema)(type);
|
|
271
289
|
const content = (0, loader_1.renderTemplate)(template, {
|
|
272
290
|
id,
|
|
273
291
|
type,
|
|
@@ -292,8 +310,8 @@ function runNewCommand(options) {
|
|
|
292
310
|
supersedes: options.supersedes ? options.supersedes.toLowerCase() : undefined,
|
|
293
311
|
created: today,
|
|
294
312
|
updated: today,
|
|
295
|
-
}
|
|
296
|
-
fs_1.default.mkdirSync(
|
|
313
|
+
});
|
|
314
|
+
fs_1.default.mkdirSync(path_1.default.dirname(filePath), { recursive: true });
|
|
297
315
|
fs_1.default.writeFileSync(filePath, content, "utf8");
|
|
298
316
|
if (config.index.auto_reindex && !noReindex) {
|
|
299
317
|
const updatedIndex = (0, indexer_1.buildIndex)(options.root, config, { tolerant: config.index.tolerant });
|
|
@@ -310,5 +328,23 @@ function runNewCommand(options) {
|
|
|
310
328
|
runId: options.runId,
|
|
311
329
|
now: options.now,
|
|
312
330
|
});
|
|
313
|
-
|
|
331
|
+
const relativePath = path_1.default.relative(options.root, filePath);
|
|
332
|
+
const receipt = {
|
|
333
|
+
workspace: ws,
|
|
334
|
+
id,
|
|
335
|
+
qid: `${ws}:${id}`,
|
|
336
|
+
path: relativePath,
|
|
337
|
+
type,
|
|
338
|
+
title,
|
|
339
|
+
...(status ? { status } : {}),
|
|
340
|
+
...(priority !== undefined ? { priority } : {}),
|
|
341
|
+
};
|
|
342
|
+
if (options.json) {
|
|
343
|
+
console.log(JSON.stringify({
|
|
344
|
+
action: "created",
|
|
345
|
+
node: receipt,
|
|
346
|
+
}, null, 2));
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
console.log(`node created: ${receipt.qid} (${receipt.path})`);
|
|
314
350
|
}
|
package/dist/commands/pack.js
CHANGED
|
@@ -106,6 +106,19 @@ function renderSkillMetaBody(skill) {
|
|
|
106
106
|
}
|
|
107
107
|
lines.push(`has_scripts: ${skill.has_scripts ? "true" : "false"}`);
|
|
108
108
|
lines.push(`has_references: ${skill.has_references ? "true" : "false"}`);
|
|
109
|
+
for (const [namespace, values] of Object.entries(skill.extensions).sort(([a], [b]) => a.localeCompare(b))) {
|
|
110
|
+
for (const [key, value] of Object.entries(values).sort(([a], [b]) => a.localeCompare(b))) {
|
|
111
|
+
if (Array.isArray(value)) {
|
|
112
|
+
lines.push(`extensions.${namespace}.${key}: ${value.join(", ")}`);
|
|
113
|
+
}
|
|
114
|
+
else if (typeof value === "boolean") {
|
|
115
|
+
lines.push(`extensions.${namespace}.${key}: ${value ? "true" : "false"}`);
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
lines.push(`extensions.${namespace}.${key}: ${value}`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
109
122
|
for (const [key, value] of Object.entries(skill.ochatr).sort(([a], [b]) => a.localeCompare(b))) {
|
|
110
123
|
if (Array.isArray(value)) {
|
|
111
124
|
lines.push(`${key}: ${value.join(", ")}`);
|
|
@@ -170,6 +183,7 @@ function appendSkillsToPack(pack, skillEntries, depth, root) {
|
|
|
170
183
|
artifacts: [],
|
|
171
184
|
refs: [],
|
|
172
185
|
aliases: [skill.slug, ...skill.tags],
|
|
186
|
+
attributes: {},
|
|
173
187
|
body: depth === "full" ? loadSkillFullBody(root, skill) : renderSkillMetaBody(skill),
|
|
174
188
|
}));
|
|
175
189
|
if (newNodes.length === 0) {
|
|
@@ -25,6 +25,7 @@ function toNodeSummaryJson(node) {
|
|
|
25
25
|
refs: [...node.refs],
|
|
26
26
|
aliases: [...node.aliases],
|
|
27
27
|
skills: [...node.skills],
|
|
28
|
+
attributes: { ...(node.attributes ?? {}) },
|
|
28
29
|
path: node.path,
|
|
29
30
|
edges: {
|
|
30
31
|
epic: node.edges.epic,
|
|
@@ -62,6 +63,7 @@ function toSkillSummaryJson(skill) {
|
|
|
62
63
|
path: skill.path,
|
|
63
64
|
has_scripts: skill.has_scripts,
|
|
64
65
|
has_references: skill.has_references,
|
|
66
|
+
extensions: JSON.parse(JSON.stringify(skill.extensions)),
|
|
65
67
|
ochatr: { ...skill.ochatr },
|
|
66
68
|
};
|
|
67
69
|
}
|
package/dist/commands/search.js
CHANGED
|
@@ -15,9 +15,16 @@ function normalizeWorkspace(value) {
|
|
|
15
15
|
return value;
|
|
16
16
|
}
|
|
17
17
|
function buildSearchText(node) {
|
|
18
|
+
const attributeTokens = Object.entries(node.attributes ?? {}).flatMap(([key, value]) => {
|
|
19
|
+
if (Array.isArray(value)) {
|
|
20
|
+
return [key, ...value];
|
|
21
|
+
}
|
|
22
|
+
return [key, String(value)];
|
|
23
|
+
});
|
|
18
24
|
const tokens = [
|
|
19
25
|
node.id,
|
|
20
26
|
node.qid,
|
|
27
|
+
node.type,
|
|
21
28
|
node.title,
|
|
22
29
|
node.path,
|
|
23
30
|
...node.tags,
|
|
@@ -27,6 +34,7 @@ function buildSearchText(node) {
|
|
|
27
34
|
...node.refs,
|
|
28
35
|
...node.aliases,
|
|
29
36
|
...node.skills,
|
|
37
|
+
...attributeTokens,
|
|
30
38
|
];
|
|
31
39
|
return tokens.join(" ").toLowerCase();
|
|
32
40
|
}
|
package/dist/commands/show.js
CHANGED
|
@@ -25,6 +25,12 @@ function maybeLine(label, values) {
|
|
|
25
25
|
}
|
|
26
26
|
return `${label}: ${values.join(", ")}`;
|
|
27
27
|
}
|
|
28
|
+
function formatAttributeLine(key, value) {
|
|
29
|
+
if (Array.isArray(value)) {
|
|
30
|
+
return `${key}: ${value.join(", ")}`;
|
|
31
|
+
}
|
|
32
|
+
return `${key}: ${String(value)}`;
|
|
33
|
+
}
|
|
28
34
|
function runShowCommand(options) {
|
|
29
35
|
const config = (0, config_1.loadConfig)(options.root);
|
|
30
36
|
const ws = normalizeWorkspace(options.ws);
|
|
@@ -79,6 +85,7 @@ function runShowCommand(options) {
|
|
|
79
85
|
maybeLine("skills", node.skills),
|
|
80
86
|
].filter((line) => Boolean(line));
|
|
81
87
|
lines.push(...metaLines);
|
|
88
|
+
lines.push(...Object.entries(node.attributes ?? {}).map(([key, value]) => formatAttributeLine(key, value)));
|
|
82
89
|
if (node.edges.epic) {
|
|
83
90
|
lines.push(`epic: ${node.edges.epic}`);
|
|
84
91
|
}
|
package/dist/commands/skill.js
CHANGED
|
@@ -99,6 +99,16 @@ function filterSkills(skills, tags, tagsMode = "any") {
|
|
|
99
99
|
});
|
|
100
100
|
}
|
|
101
101
|
function buildSkillSearchText(skill) {
|
|
102
|
+
const extensionTokens = Object.entries(skill.extensions).flatMap(([namespace, values]) => Object.entries(values).flatMap(([key, value]) => {
|
|
103
|
+
const field = `extensions.${namespace}.${key}`;
|
|
104
|
+
if (Array.isArray(value)) {
|
|
105
|
+
return [field, ...value];
|
|
106
|
+
}
|
|
107
|
+
if (typeof value === "boolean") {
|
|
108
|
+
return [field, value ? "true" : "false"];
|
|
109
|
+
}
|
|
110
|
+
return [field, value];
|
|
111
|
+
}));
|
|
102
112
|
const ochatrTokens = Object.entries(skill.ochatr).flatMap(([key, value]) => {
|
|
103
113
|
if (Array.isArray(value)) {
|
|
104
114
|
return [key, ...value];
|
|
@@ -118,6 +128,7 @@ function buildSkillSearchText(skill) {
|
|
|
118
128
|
...skill.tags,
|
|
119
129
|
...skill.authors,
|
|
120
130
|
...skill.links,
|
|
131
|
+
...extensionTokens,
|
|
121
132
|
...ochatrTokens,
|
|
122
133
|
];
|
|
123
134
|
return tokens.join(" ").toLowerCase();
|
|
@@ -191,7 +202,23 @@ function runSkillNewCommand(options) {
|
|
|
191
202
|
skill: slug,
|
|
192
203
|
now: options.now,
|
|
193
204
|
});
|
|
194
|
-
|
|
205
|
+
const receipt = {
|
|
206
|
+
workspace: "root",
|
|
207
|
+
id: `skill:${slug}`,
|
|
208
|
+
qid: `root:skill:${slug}`,
|
|
209
|
+
slug,
|
|
210
|
+
name,
|
|
211
|
+
path: path_1.default.relative(root, canonicalPath),
|
|
212
|
+
with_scripts: Boolean(options.withScripts),
|
|
213
|
+
};
|
|
214
|
+
if (options.json) {
|
|
215
|
+
console.log(JSON.stringify({
|
|
216
|
+
action: "created",
|
|
217
|
+
skill: receipt,
|
|
218
|
+
}, null, 2));
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
console.log(`skill created: ${receipt.qid} (${receipt.path})`);
|
|
195
222
|
}
|
|
196
223
|
function runSkillListCommand(options) {
|
|
197
224
|
const config = (0, config_1.loadConfig)(options.root);
|
|
@@ -274,6 +301,19 @@ function runSkillShowCommand(options) {
|
|
|
274
301
|
}
|
|
275
302
|
lines.push(`has_scripts: ${skill.has_scripts ? "true" : "false"}`);
|
|
276
303
|
lines.push(`has_references: ${skill.has_references ? "true" : "false"}`);
|
|
304
|
+
for (const [namespace, values] of Object.entries(skill.extensions).sort(([a], [b]) => a.localeCompare(b))) {
|
|
305
|
+
for (const [key, value] of Object.entries(values).sort(([a], [b]) => a.localeCompare(b))) {
|
|
306
|
+
if (Array.isArray(value)) {
|
|
307
|
+
lines.push(`extensions.${namespace}.${key}: ${value.join(", ")}`);
|
|
308
|
+
continue;
|
|
309
|
+
}
|
|
310
|
+
if (typeof value === "boolean") {
|
|
311
|
+
lines.push(`extensions.${namespace}.${key}: ${value ? "true" : "false"}`);
|
|
312
|
+
continue;
|
|
313
|
+
}
|
|
314
|
+
lines.push(`extensions.${namespace}.${key}: ${value}`);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
277
317
|
for (const [key, value] of Object.entries(skill.ochatr).sort(([a], [b]) => a.localeCompare(b))) {
|
|
278
318
|
if (Array.isArray(value)) {
|
|
279
319
|
lines.push(`${key}: ${value.join(", ")}`);
|
|
@@ -329,8 +369,11 @@ function runSkillValidateCommand(options) {
|
|
|
329
369
|
const targetSlug = options.slug?.trim().toLowerCase();
|
|
330
370
|
const warnings = [];
|
|
331
371
|
const errors = [];
|
|
372
|
+
let checkedCount = 0;
|
|
332
373
|
if (targetSlug) {
|
|
333
|
-
const
|
|
374
|
+
const normalizedSlug = normalizeSlug(targetSlug);
|
|
375
|
+
const result = validateSingleSkill(options.root, normalizedSlug);
|
|
376
|
+
checkedCount = 1;
|
|
334
377
|
warnings.push(...result.warnings);
|
|
335
378
|
errors.push(...result.errors);
|
|
336
379
|
}
|
|
@@ -338,31 +381,49 @@ function runSkillValidateCommand(options) {
|
|
|
338
381
|
const skillsRoot = (0, skills_indexer_1.resolveSkillsRoot)(options.root, config);
|
|
339
382
|
if (fs_1.default.existsSync(skillsRoot)) {
|
|
340
383
|
const entries = fs_1.default.readdirSync(skillsRoot, { withFileTypes: true });
|
|
341
|
-
|
|
384
|
+
const skillDirs = entries
|
|
385
|
+
.filter((value) => value.isDirectory())
|
|
386
|
+
.sort((a, b) => a.name.localeCompare(b.name));
|
|
387
|
+
checkedCount = skillDirs.length;
|
|
388
|
+
for (const entry of skillDirs) {
|
|
342
389
|
const result = validateSingleSkill(options.root, entry.name.toLowerCase());
|
|
343
390
|
warnings.push(...result.warnings);
|
|
344
391
|
errors.push(...result.errors);
|
|
345
392
|
}
|
|
346
393
|
}
|
|
347
394
|
}
|
|
348
|
-
|
|
395
|
+
const uniqueWarnings = Array.from(new Set(warnings));
|
|
396
|
+
const uniqueErrors = Array.from(new Set(errors));
|
|
397
|
+
const receipt = {
|
|
398
|
+
action: "validated",
|
|
399
|
+
ok: uniqueErrors.length === 0,
|
|
400
|
+
checked_count: checkedCount,
|
|
401
|
+
warning_count: uniqueWarnings.length,
|
|
402
|
+
error_count: uniqueErrors.length,
|
|
403
|
+
warnings: uniqueWarnings,
|
|
404
|
+
errors: uniqueErrors,
|
|
405
|
+
...(targetSlug ? { target: normalizeSlug(targetSlug) } : {}),
|
|
406
|
+
};
|
|
407
|
+
if (options.json) {
|
|
408
|
+
console.log(JSON.stringify(receipt, null, 2));
|
|
409
|
+
if (uniqueErrors.length > 0) {
|
|
410
|
+
throw new errors_1.ValidationError(`skill validation failed with ${uniqueErrors.length} error(s)`);
|
|
411
|
+
}
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
for (const warning of uniqueWarnings) {
|
|
349
415
|
console.error(`warning: ${warning}`);
|
|
350
416
|
}
|
|
351
|
-
if (
|
|
352
|
-
for (const error of
|
|
417
|
+
if (uniqueErrors.length > 0) {
|
|
418
|
+
for (const error of uniqueErrors) {
|
|
353
419
|
console.error(error);
|
|
354
420
|
}
|
|
355
|
-
throw new errors_1.ValidationError(`skill validation failed with ${
|
|
421
|
+
throw new errors_1.ValidationError(`skill validation failed with ${uniqueErrors.length} error(s)`);
|
|
356
422
|
}
|
|
357
423
|
if (targetSlug) {
|
|
358
424
|
console.log(`skill validation ok: ${targetSlug} (1 skill checked)`);
|
|
359
425
|
return;
|
|
360
426
|
}
|
|
361
|
-
const checkedCount = fs_1.default.existsSync((0, skills_indexer_1.resolveSkillsRoot)(options.root, config))
|
|
362
|
-
? fs_1.default
|
|
363
|
-
.readdirSync((0, skills_indexer_1.resolveSkillsRoot)(options.root, config), { withFileTypes: true })
|
|
364
|
-
.filter((value) => value.isDirectory()).length
|
|
365
|
-
: 0;
|
|
366
427
|
console.log(`skill validation ok: ${checkedCount} skill${checkedCount === 1 ? "" : "s"} checked`);
|
|
367
428
|
}
|
|
368
429
|
function runSkillSyncCommand(options) {
|
|
@@ -373,5 +434,12 @@ function runSkillSyncCommand(options) {
|
|
|
373
434
|
createRoots: true,
|
|
374
435
|
force: options.force,
|
|
375
436
|
});
|
|
437
|
+
if (options.json) {
|
|
438
|
+
console.log(JSON.stringify({
|
|
439
|
+
action: "synced",
|
|
440
|
+
sync: result,
|
|
441
|
+
}, null, 2));
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
376
444
|
console.log(`skill mirror sync ok: ${result.synced} synced, ${result.pruned} pruned across ${result.targets} target${result.targets === 1 ? "" : "s"}`);
|
|
377
445
|
}
|
package/dist/commands/task.js
CHANGED
|
@@ -9,12 +9,10 @@ exports.runTaskDoneCommand = runTaskDoneCommand;
|
|
|
9
9
|
const fs_1 = __importDefault(require("fs"));
|
|
10
10
|
const path_1 = __importDefault(require("path"));
|
|
11
11
|
const config_1 = require("../core/config");
|
|
12
|
-
const node_1 = require("../graph/node");
|
|
13
12
|
const indexer_1 = require("../graph/indexer");
|
|
14
13
|
const index_cache_1 = require("../graph/index_cache");
|
|
15
14
|
const frontmatter_1 = require("../graph/frontmatter");
|
|
16
15
|
const skills_indexer_1 = require("../graph/skills_indexer");
|
|
17
|
-
const template_schema_1 = require("../graph/template_schema");
|
|
18
16
|
const date_1 = require("../util/date");
|
|
19
17
|
const errors_1 = require("../util/errors");
|
|
20
18
|
const qid_1 = require("../util/qid");
|
|
@@ -114,12 +112,7 @@ function loadMutableTaskNode(root, idOrQid, wsHint) {
|
|
|
114
112
|
}
|
|
115
113
|
const filePath = path_1.default.resolve(root, node.path);
|
|
116
114
|
const content = fs_1.default.readFileSync(filePath, "utf8");
|
|
117
|
-
const parsed = (0,
|
|
118
|
-
workStatusEnum: config.work.status_enum,
|
|
119
|
-
priorityMin: config.work.priority_min,
|
|
120
|
-
priorityMax: config.work.priority_max,
|
|
121
|
-
templateSchemas: (0, template_schema_1.loadTemplateSchemas)(root, config, node_1.ALLOWED_TYPES),
|
|
122
|
-
});
|
|
115
|
+
const parsed = (0, frontmatter_1.parseFrontmatter)(content, filePath);
|
|
123
116
|
return {
|
|
124
117
|
config,
|
|
125
118
|
index,
|
|
@@ -182,6 +175,30 @@ function maybeWarnEventsDisabled(root, config, ws) {
|
|
|
182
175
|
}
|
|
183
176
|
console.error(`note: events.jsonl is missing for workspace ${ws}; run mdkg event enable --ws ${ws} to restore JSONL provenance`);
|
|
184
177
|
}
|
|
178
|
+
function taskReceipt(root, loaded) {
|
|
179
|
+
const rawPriority = loaded.frontmatter.priority;
|
|
180
|
+
const priority = rawPriority === undefined ? undefined : Number.parseInt(String(rawPriority), 10);
|
|
181
|
+
return {
|
|
182
|
+
workspace: loaded.ws,
|
|
183
|
+
id: loaded.id,
|
|
184
|
+
qid: loaded.qid,
|
|
185
|
+
path: path_1.default.relative(root, loaded.filePath),
|
|
186
|
+
type: loaded.type,
|
|
187
|
+
status: String(loaded.frontmatter.status ?? ""),
|
|
188
|
+
...(Number.isInteger(priority) ? { priority } : {}),
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
function printTaskMutationReceipt(action, root, loaded, json, checkpoint) {
|
|
192
|
+
if (json) {
|
|
193
|
+
console.log(JSON.stringify({
|
|
194
|
+
action,
|
|
195
|
+
task: taskReceipt(root, loaded),
|
|
196
|
+
...(checkpoint ? { checkpoint } : {}),
|
|
197
|
+
}, null, 2));
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
console.log(`task ${action}: ${loaded.qid}`);
|
|
201
|
+
}
|
|
185
202
|
function runTaskStartCommand(options) {
|
|
186
203
|
const loaded = loadMutableTaskNode(options.root, options.id, options.ws);
|
|
187
204
|
const now = options.now ?? new Date();
|
|
@@ -200,7 +217,7 @@ function runTaskStartCommand(options) {
|
|
|
200
217
|
now,
|
|
201
218
|
});
|
|
202
219
|
maybeWarnEventsDisabled(options.root, loaded.config, loaded.ws);
|
|
203
|
-
|
|
220
|
+
printTaskMutationReceipt("started", options.root, loaded, options.json);
|
|
204
221
|
}
|
|
205
222
|
function runTaskUpdateCommand(options) {
|
|
206
223
|
const loaded = loadMutableTaskNode(options.root, options.id, options.ws);
|
|
@@ -242,7 +259,7 @@ function runTaskUpdateCommand(options) {
|
|
|
242
259
|
runId: options.runId,
|
|
243
260
|
now,
|
|
244
261
|
});
|
|
245
|
-
|
|
262
|
+
printTaskMutationReceipt("updated", options.root, loaded, options.json);
|
|
246
263
|
}
|
|
247
264
|
function runTaskDoneCommand(options) {
|
|
248
265
|
const loaded = loadMutableTaskNode(options.root, options.id, options.ws);
|
|
@@ -267,7 +284,20 @@ function runTaskDoneCommand(options) {
|
|
|
267
284
|
runId: options.runId,
|
|
268
285
|
now,
|
|
269
286
|
});
|
|
270
|
-
|
|
287
|
+
let checkpoint;
|
|
288
|
+
if (options.checkpoint && options.json) {
|
|
289
|
+
checkpoint = (0, checkpoint_1.createCheckpoint)({
|
|
290
|
+
root: options.root,
|
|
291
|
+
title: options.checkpoint,
|
|
292
|
+
ws: loaded.ws,
|
|
293
|
+
relates: loaded.id,
|
|
294
|
+
scope: loaded.id,
|
|
295
|
+
runId: options.runId,
|
|
296
|
+
note: `checkpoint created from mdkg task done for ${loaded.id}`,
|
|
297
|
+
now,
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
else if (options.checkpoint) {
|
|
271
301
|
(0, checkpoint_1.runCheckpointNewCommand)({
|
|
272
302
|
root: options.root,
|
|
273
303
|
title: options.checkpoint,
|
|
@@ -281,5 +311,5 @@ function runTaskDoneCommand(options) {
|
|
|
281
311
|
}
|
|
282
312
|
maybeReindex(options.root, loaded.config);
|
|
283
313
|
maybeWarnEventsDisabled(options.root, loaded.config, loaded.ws);
|
|
284
|
-
|
|
314
|
+
printTaskMutationReceipt("done", options.root, loaded, options.json, checkpoint);
|
|
285
315
|
}
|