mdkg 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +171 -151
- package/dist/cli.js +920 -422
- package/dist/commands/checkpoint.js +17 -6
- package/dist/commands/doctor.js +156 -0
- package/dist/commands/event.js +46 -0
- package/dist/commands/event_support.js +146 -0
- package/dist/commands/format.js +6 -7
- package/dist/commands/index.js +10 -4
- package/dist/commands/init.js +202 -11
- package/dist/commands/list.js +18 -1
- package/dist/commands/new.js +30 -5
- package/dist/commands/pack.js +332 -10
- package/dist/commands/query_output.js +84 -0
- package/dist/commands/search.js +22 -5
- package/dist/commands/show.js +26 -11
- package/dist/commands/skill.js +359 -0
- package/dist/commands/skill_support.js +121 -0
- package/dist/commands/task.js +270 -0
- package/dist/commands/validate.js +104 -7
- package/dist/graph/edges.js +2 -2
- package/dist/graph/frontmatter.js +1 -0
- package/dist/graph/indexer.js +21 -0
- package/dist/graph/node.js +20 -4
- package/dist/graph/skills_index_cache.js +94 -0
- package/dist/graph/skills_indexer.js +160 -0
- package/dist/init/README.md +43 -0
- package/dist/init/core/rule-1-mdkg-conventions.md +9 -2
- package/dist/init/core/rule-3-cli-contract.md +73 -14
- package/dist/init/core/rule-4-repo-safety-and-ignores.md +9 -3
- package/dist/init/core/rule-6-templates-and-schemas.md +6 -2
- package/dist/init/skills/SKILL.md.example +41 -0
- package/dist/init/templates/default/bug.md +1 -0
- package/dist/init/templates/default/chk.md +1 -0
- package/dist/init/templates/default/epic.md +1 -0
- package/dist/init/templates/default/feat.md +1 -0
- package/dist/init/templates/default/task.md +1 -0
- package/dist/init/templates/default/test.md +1 -0
- package/dist/pack/budget.js +186 -0
- package/dist/pack/export_md.js +17 -1
- package/dist/pack/export_xml.js +15 -0
- package/dist/pack/metrics.js +66 -0
- package/dist/pack/pack.js +35 -0
- package/dist/pack/profile.js +222 -0
- package/dist/pack/stats.js +37 -0
- package/dist/templates/headings.js +34 -0
- package/dist/util/argparse.js +47 -1
- package/dist/util/filter.js +18 -0
- package/dist/util/id.js +23 -0
- package/dist/util/output.js +2 -2
- package/package.json +6 -2
|
@@ -11,8 +11,8 @@ const index_cache_1 = require("../graph/index_cache");
|
|
|
11
11
|
const loader_1 = require("../templates/loader");
|
|
12
12
|
const date_1 = require("../util/date");
|
|
13
13
|
const errors_1 = require("../util/errors");
|
|
14
|
-
const
|
|
15
|
-
const
|
|
14
|
+
const id_1 = require("../util/id");
|
|
15
|
+
const event_support_1 = require("./event_support");
|
|
16
16
|
function parseCsvList(raw) {
|
|
17
17
|
if (!raw) {
|
|
18
18
|
return [];
|
|
@@ -24,14 +24,14 @@ function parseCsvList(raw) {
|
|
|
24
24
|
}
|
|
25
25
|
function normalizeId(value, key) {
|
|
26
26
|
const normalized = value.toLowerCase();
|
|
27
|
-
if (!
|
|
28
|
-
throw new errors_1.UsageError(`${key} entries must match <prefix>-<number
|
|
27
|
+
if (!(0, id_1.isCanonicalId)(normalized)) {
|
|
28
|
+
throw new errors_1.UsageError(`${key} entries must match <prefix>-<number> or reserved id: ${value}`);
|
|
29
29
|
}
|
|
30
30
|
return normalized;
|
|
31
31
|
}
|
|
32
32
|
function normalizeIdRef(value, key) {
|
|
33
33
|
const normalized = value.toLowerCase();
|
|
34
|
-
if (!
|
|
34
|
+
if (!(0, id_1.isCanonicalIdRef)(normalized)) {
|
|
35
35
|
throw new errors_1.UsageError(`${key} entries must match <id> or <ws>:<id>: ${value}`);
|
|
36
36
|
}
|
|
37
37
|
return normalized;
|
|
@@ -115,7 +115,8 @@ function runCheckpointNewCommand(options) {
|
|
|
115
115
|
}
|
|
116
116
|
}
|
|
117
117
|
const scope = parseCsvList(options.scope).map((value) => normalizeId(value, "--scope"));
|
|
118
|
-
const
|
|
118
|
+
const now = options.now ?? new Date();
|
|
119
|
+
const today = (0, date_1.formatDate)(now);
|
|
119
120
|
const template = (0, loader_1.loadTemplate)(options.root, config, "checkpoint", options.template);
|
|
120
121
|
const content = (0, loader_1.renderTemplate)(template, {
|
|
121
122
|
id,
|
|
@@ -129,5 +130,15 @@ function runCheckpointNewCommand(options) {
|
|
|
129
130
|
});
|
|
130
131
|
fs_1.default.mkdirSync(workDir, { recursive: true });
|
|
131
132
|
fs_1.default.writeFileSync(filePath, content, "utf8");
|
|
133
|
+
(0, event_support_1.appendAutomaticEvent)({
|
|
134
|
+
root: options.root,
|
|
135
|
+
ws,
|
|
136
|
+
kind: "CHECKPOINT_CREATED",
|
|
137
|
+
status: "ok",
|
|
138
|
+
refs: [id],
|
|
139
|
+
notes: options.note ?? `checkpoint created via mdkg checkpoint new`,
|
|
140
|
+
runId: options.runId,
|
|
141
|
+
now,
|
|
142
|
+
});
|
|
132
143
|
console.log(`checkpoint created: ${ws}:${id} (${path_1.default.relative(options.root, filePath)})`);
|
|
133
144
|
}
|
|
@@ -0,0 +1,156 @@
|
|
|
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.runDoctorCommand = runDoctorCommand;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const config_1 = require("../core/config");
|
|
10
|
+
const index_cache_1 = require("../graph/index_cache");
|
|
11
|
+
const node_1 = require("../graph/node");
|
|
12
|
+
const template_schema_1 = require("../graph/template_schema");
|
|
13
|
+
const errors_1 = require("../util/errors");
|
|
14
|
+
const REQUIRED_NODE_MAJOR = 18;
|
|
15
|
+
function parseNodeMajor(version) {
|
|
16
|
+
const major = Number.parseInt(version.split(".")[0] ?? "", 10);
|
|
17
|
+
if (!Number.isInteger(major)) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
return major;
|
|
21
|
+
}
|
|
22
|
+
function runNodeVersionCheck() {
|
|
23
|
+
const nodeVersion = process.versions.node;
|
|
24
|
+
const major = parseNodeMajor(nodeVersion);
|
|
25
|
+
if (major === null) {
|
|
26
|
+
return {
|
|
27
|
+
name: "node-version",
|
|
28
|
+
ok: false,
|
|
29
|
+
detail: `unable to parse Node.js version: ${nodeVersion}`,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
if (major < REQUIRED_NODE_MAJOR) {
|
|
33
|
+
return {
|
|
34
|
+
name: "node-version",
|
|
35
|
+
ok: false,
|
|
36
|
+
detail: `Node.js ${nodeVersion} is unsupported (requires >=${REQUIRED_NODE_MAJOR})`,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
name: "node-version",
|
|
41
|
+
ok: true,
|
|
42
|
+
detail: `Node.js ${nodeVersion} (ok)`,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function runDoctorCommand(options) {
|
|
46
|
+
const results = [];
|
|
47
|
+
results.push(runNodeVersionCheck());
|
|
48
|
+
const configPath = path_1.default.resolve(options.root, ".mdkg", "config.json");
|
|
49
|
+
if (!fs_1.default.existsSync(configPath)) {
|
|
50
|
+
results.push({
|
|
51
|
+
name: "config",
|
|
52
|
+
ok: false,
|
|
53
|
+
detail: `missing config at ${configPath}`,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
results.push({
|
|
58
|
+
name: "config",
|
|
59
|
+
ok: true,
|
|
60
|
+
detail: `found ${configPath}`,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
let config;
|
|
64
|
+
try {
|
|
65
|
+
config = (0, config_1.loadConfig)(options.root);
|
|
66
|
+
results.push({
|
|
67
|
+
name: "config-schema",
|
|
68
|
+
ok: true,
|
|
69
|
+
detail: "config schema valid",
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
74
|
+
results.push({
|
|
75
|
+
name: "config-schema",
|
|
76
|
+
ok: false,
|
|
77
|
+
detail: message,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
if (config) {
|
|
81
|
+
try {
|
|
82
|
+
(0, template_schema_1.loadTemplateSchemas)(options.root, config, node_1.ALLOWED_TYPES);
|
|
83
|
+
results.push({
|
|
84
|
+
name: "templates",
|
|
85
|
+
ok: true,
|
|
86
|
+
detail: "template schema set loaded",
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
91
|
+
results.push({
|
|
92
|
+
name: "templates",
|
|
93
|
+
ok: false,
|
|
94
|
+
detail: message,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
try {
|
|
98
|
+
const { rebuilt, stale } = (0, index_cache_1.loadIndex)({
|
|
99
|
+
root: options.root,
|
|
100
|
+
config,
|
|
101
|
+
useCache: !options.noCache,
|
|
102
|
+
allowReindex: !options.noReindex,
|
|
103
|
+
});
|
|
104
|
+
if (rebuilt) {
|
|
105
|
+
results.push({
|
|
106
|
+
name: "index",
|
|
107
|
+
ok: true,
|
|
108
|
+
detail: "index cache rebuilt and loaded",
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
else if (stale) {
|
|
112
|
+
results.push({
|
|
113
|
+
name: "index",
|
|
114
|
+
ok: true,
|
|
115
|
+
detail: "index cache is stale (run mdkg index to refresh)",
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
results.push({
|
|
120
|
+
name: "index",
|
|
121
|
+
ok: true,
|
|
122
|
+
detail: "index cache loaded",
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
catch (err) {
|
|
127
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
128
|
+
results.push({
|
|
129
|
+
name: "index",
|
|
130
|
+
ok: false,
|
|
131
|
+
detail: message,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
const failures = results.filter((result) => !result.ok);
|
|
136
|
+
if (options.json) {
|
|
137
|
+
const payload = {
|
|
138
|
+
ok: failures.length === 0,
|
|
139
|
+
checks: results,
|
|
140
|
+
failure_count: failures.length,
|
|
141
|
+
};
|
|
142
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
for (const result of results) {
|
|
146
|
+
const prefix = result.ok ? "ok" : "fail";
|
|
147
|
+
console.log(`${prefix}: ${result.name} - ${result.detail}`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
if (failures.length > 0) {
|
|
151
|
+
throw new errors_1.ValidationError(`doctor failed with ${failures.length} issue(s)`);
|
|
152
|
+
}
|
|
153
|
+
if (!options.json) {
|
|
154
|
+
console.log("doctor ok");
|
|
155
|
+
}
|
|
156
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runEventEnableCommand = runEventEnableCommand;
|
|
4
|
+
exports.runEventAppendCommand = runEventAppendCommand;
|
|
5
|
+
const event_support_1 = require("./event_support");
|
|
6
|
+
const errors_1 = require("../util/errors");
|
|
7
|
+
function runEventEnableCommand(options) {
|
|
8
|
+
const result = (0, event_support_1.ensureEventsEnabled)(options);
|
|
9
|
+
const createdLabel = result.created ? "created" : "already present";
|
|
10
|
+
const ignoreLabel = result.gitignoreUpdated ? "updated .gitignore" : "left .gitignore unchanged";
|
|
11
|
+
console.log(`event logging enabled: ${result.ws} (${createdLabel}; ${ignoreLabel})`);
|
|
12
|
+
}
|
|
13
|
+
function normalizeEventStatus(value) {
|
|
14
|
+
const normalized = value.trim().toLowerCase();
|
|
15
|
+
if (normalized === "ok" ||
|
|
16
|
+
normalized === "error" ||
|
|
17
|
+
normalized === "retry" ||
|
|
18
|
+
normalized === "skipped") {
|
|
19
|
+
return normalized;
|
|
20
|
+
}
|
|
21
|
+
throw new errors_1.UsageError("--status must be one of ok, error, retry, skipped");
|
|
22
|
+
}
|
|
23
|
+
function runEventAppendCommand(options) {
|
|
24
|
+
const kind = options.kind.trim();
|
|
25
|
+
if (!kind) {
|
|
26
|
+
throw new errors_1.UsageError("--kind is required");
|
|
27
|
+
}
|
|
28
|
+
const refs = (0, event_support_1.normalizeEventRefList)(options.refs);
|
|
29
|
+
if (refs.length === 0) {
|
|
30
|
+
throw new errors_1.UsageError("--refs requires at least one id or qid");
|
|
31
|
+
}
|
|
32
|
+
const record = (0, event_support_1.appendEvent)({
|
|
33
|
+
root: options.root,
|
|
34
|
+
ws: options.ws,
|
|
35
|
+
kind,
|
|
36
|
+
status: normalizeEventStatus(options.status),
|
|
37
|
+
refs,
|
|
38
|
+
artifacts: (0, event_support_1.normalizeEventStringList)(options.artifacts),
|
|
39
|
+
notes: options.notes,
|
|
40
|
+
runId: options.runId,
|
|
41
|
+
agent: options.agent,
|
|
42
|
+
skill: options.skill,
|
|
43
|
+
tool: options.tool,
|
|
44
|
+
});
|
|
45
|
+
console.log(`event appended: ${record.workspace}:${record.kind} (${record.run_id})`);
|
|
46
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
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.normalizeWorkspaceForEvents = normalizeWorkspaceForEvents;
|
|
7
|
+
exports.resolveEventsPath = resolveEventsPath;
|
|
8
|
+
exports.createLocalRunId = createLocalRunId;
|
|
9
|
+
exports.isEventLoggingEnabled = isEventLoggingEnabled;
|
|
10
|
+
exports.ensureEventsEnabled = ensureEventsEnabled;
|
|
11
|
+
exports.normalizeEventRefList = normalizeEventRefList;
|
|
12
|
+
exports.normalizeEventStringList = normalizeEventStringList;
|
|
13
|
+
exports.appendEvent = appendEvent;
|
|
14
|
+
exports.appendAutomaticEvent = appendAutomaticEvent;
|
|
15
|
+
const fs_1 = __importDefault(require("fs"));
|
|
16
|
+
const path_1 = __importDefault(require("path"));
|
|
17
|
+
const config_1 = require("../core/config");
|
|
18
|
+
const errors_1 = require("../util/errors");
|
|
19
|
+
function appendIgnoreEntries(filePath, entries) {
|
|
20
|
+
const normalizedEntries = entries.map((entry) => entry.trim()).filter(Boolean);
|
|
21
|
+
if (normalizedEntries.length === 0) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
let existing = "";
|
|
25
|
+
if (fs_1.default.existsSync(filePath)) {
|
|
26
|
+
existing = fs_1.default.readFileSync(filePath, "utf8");
|
|
27
|
+
}
|
|
28
|
+
const existingLines = new Set(existing
|
|
29
|
+
.split(/\r?\n/)
|
|
30
|
+
.map((line) => line.trim())
|
|
31
|
+
.filter(Boolean));
|
|
32
|
+
const additions = normalizedEntries.filter((entry) => !existingLines.has(entry));
|
|
33
|
+
if (additions.length === 0) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
const next = existing.length === 0 ? `${additions.join("\n")}\n` : `${existing.replace(/\s*$/, "\n")}${additions.join("\n")}\n`;
|
|
37
|
+
fs_1.default.writeFileSync(filePath, next, "utf8");
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
function normalizeWorkspaceForEvents(config, raw) {
|
|
41
|
+
const normalized = (raw ?? "root").toLowerCase();
|
|
42
|
+
if (normalized === "all") {
|
|
43
|
+
throw new errors_1.UsageError("--ws all is not valid here");
|
|
44
|
+
}
|
|
45
|
+
if (!config.workspaces[normalized]) {
|
|
46
|
+
throw new errors_1.NotFoundError(`workspace not found: ${normalized}`);
|
|
47
|
+
}
|
|
48
|
+
return normalized;
|
|
49
|
+
}
|
|
50
|
+
function resolveEventsPath(root, config, ws = "root") {
|
|
51
|
+
const entry = config.workspaces[ws];
|
|
52
|
+
if (!entry) {
|
|
53
|
+
throw new errors_1.NotFoundError(`workspace not found: ${ws}`);
|
|
54
|
+
}
|
|
55
|
+
return path_1.default.resolve(root, entry.path, entry.mdkg_dir, "work", "events", "events.jsonl");
|
|
56
|
+
}
|
|
57
|
+
function formatRunIdTimestamp(now) {
|
|
58
|
+
const iso = now.toISOString().replace(/[-:]/g, "").replace(/\./g, "").replace("Z", "Z");
|
|
59
|
+
return iso;
|
|
60
|
+
}
|
|
61
|
+
function createLocalRunId(kind, now = new Date()) {
|
|
62
|
+
const normalizedKind = kind.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
63
|
+
return `run_mdkg_cli_${normalizedKind}_${formatRunIdTimestamp(now)}`;
|
|
64
|
+
}
|
|
65
|
+
function isEventLoggingEnabled(root, config, ws) {
|
|
66
|
+
const normalizedWs = normalizeWorkspaceForEvents(config, ws);
|
|
67
|
+
return fs_1.default.existsSync(resolveEventsPath(root, config, normalizedWs));
|
|
68
|
+
}
|
|
69
|
+
function ensureEventsEnabled(options) {
|
|
70
|
+
const config = (0, config_1.loadConfig)(options.root);
|
|
71
|
+
const ws = normalizeWorkspaceForEvents(config, options.ws);
|
|
72
|
+
const eventsPath = resolveEventsPath(options.root, config, ws);
|
|
73
|
+
const updateGitignore = options.updateGitignore !== false;
|
|
74
|
+
let created = false;
|
|
75
|
+
if (!fs_1.default.existsSync(eventsPath)) {
|
|
76
|
+
fs_1.default.mkdirSync(path_1.default.dirname(eventsPath), { recursive: true });
|
|
77
|
+
fs_1.default.writeFileSync(eventsPath, "", "utf8");
|
|
78
|
+
created = true;
|
|
79
|
+
}
|
|
80
|
+
let gitignoreUpdated = false;
|
|
81
|
+
if (updateGitignore) {
|
|
82
|
+
gitignoreUpdated = appendIgnoreEntries(path_1.default.join(options.root, ".gitignore"), [
|
|
83
|
+
".mdkg/work/events/*.jsonl",
|
|
84
|
+
]);
|
|
85
|
+
}
|
|
86
|
+
return { ws, eventsPath, created, gitignoreUpdated };
|
|
87
|
+
}
|
|
88
|
+
function normalizeIdOrIdRef(value) {
|
|
89
|
+
return value.trim().toLowerCase();
|
|
90
|
+
}
|
|
91
|
+
function normalizeEventRefList(raw) {
|
|
92
|
+
if (!raw) {
|
|
93
|
+
return [];
|
|
94
|
+
}
|
|
95
|
+
return raw
|
|
96
|
+
.split(",")
|
|
97
|
+
.map((value) => normalizeIdOrIdRef(value))
|
|
98
|
+
.filter(Boolean);
|
|
99
|
+
}
|
|
100
|
+
function normalizeEventStringList(raw) {
|
|
101
|
+
if (!raw) {
|
|
102
|
+
return [];
|
|
103
|
+
}
|
|
104
|
+
return raw
|
|
105
|
+
.split(",")
|
|
106
|
+
.map((value) => value.trim())
|
|
107
|
+
.filter(Boolean);
|
|
108
|
+
}
|
|
109
|
+
function buildEventRecord(config, options) {
|
|
110
|
+
const now = options.now ?? new Date();
|
|
111
|
+
const ws = normalizeWorkspaceForEvents(config, options.ws);
|
|
112
|
+
return {
|
|
113
|
+
ts: now.toISOString(),
|
|
114
|
+
run_id: options.runId?.trim() || createLocalRunId(options.kind, now),
|
|
115
|
+
workspace: ws,
|
|
116
|
+
agent: options.agent?.trim() || "mdkg-cli",
|
|
117
|
+
kind: options.kind,
|
|
118
|
+
status: options.status,
|
|
119
|
+
refs: options.refs.map(normalizeIdOrIdRef).filter(Boolean),
|
|
120
|
+
artifacts: (options.artifacts ?? []).map((value) => value.trim()).filter(Boolean),
|
|
121
|
+
notes: options.notes?.trim() ?? "",
|
|
122
|
+
...(options.skill ? { skill: options.skill.trim().toLowerCase() } : {}),
|
|
123
|
+
...(options.tool ? { tool: options.tool.trim() } : {}),
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
function appendEvent(options) {
|
|
127
|
+
const config = (0, config_1.loadConfig)(options.root);
|
|
128
|
+
const record = buildEventRecord(config, options);
|
|
129
|
+
if (record.refs.length === 0) {
|
|
130
|
+
throw new errors_1.UsageError("--refs requires at least one id or qid");
|
|
131
|
+
}
|
|
132
|
+
const eventsPath = resolveEventsPath(options.root, config, record.workspace);
|
|
133
|
+
if (!fs_1.default.existsSync(eventsPath)) {
|
|
134
|
+
throw new errors_1.NotFoundError(`event logging is not enabled for workspace ${record.workspace}; run \`mdkg event enable --ws ${record.workspace}\``);
|
|
135
|
+
}
|
|
136
|
+
fs_1.default.appendFileSync(eventsPath, `${JSON.stringify(record)}\n`, "utf8");
|
|
137
|
+
return record;
|
|
138
|
+
}
|
|
139
|
+
function appendAutomaticEvent(options) {
|
|
140
|
+
const config = (0, config_1.loadConfig)(options.root);
|
|
141
|
+
const ws = normalizeWorkspaceForEvents(config, options.ws);
|
|
142
|
+
if (!isEventLoggingEnabled(options.root, config, ws)) {
|
|
143
|
+
return undefined;
|
|
144
|
+
}
|
|
145
|
+
return appendEvent({ ...options, ws });
|
|
146
|
+
}
|
package/dist/commands/format.js
CHANGED
|
@@ -13,8 +13,7 @@ const node_1 = require("../graph/node");
|
|
|
13
13
|
const workspace_files_1 = require("../graph/workspace_files");
|
|
14
14
|
const errors_1 = require("../util/errors");
|
|
15
15
|
const date_1 = require("../util/date");
|
|
16
|
-
const
|
|
17
|
-
const ID_REF_RE = /^([a-z][a-z0-9_]*:)?[a-z]+-[0-9]+$/;
|
|
16
|
+
const id_1 = require("../util/id");
|
|
18
17
|
const DEC_ID_RE = /^dec-[0-9]+$/;
|
|
19
18
|
const DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
|
|
20
19
|
const ID_LIST_KEYS = new Set(["refs", "scope"]);
|
|
@@ -22,7 +21,7 @@ const ID_REF_LIST_KEYS = new Set(["relates", "blocked_by", "blocks"]);
|
|
|
22
21
|
const ID_REF_SCALAR_KEYS = new Set(["epic", "parent", "prev", "next"]);
|
|
23
22
|
const PRESERVE_CASE_LIST_KEYS = new Set(["links", "artifacts"]);
|
|
24
23
|
function isValidId(value) {
|
|
25
|
-
return
|
|
24
|
+
return (0, id_1.isCanonicalId)(value);
|
|
26
25
|
}
|
|
27
26
|
function isCoreListFile(filePath) {
|
|
28
27
|
return path_1.default.basename(filePath) === "core.md" && path_1.default.basename(path_1.default.dirname(filePath)) === "core";
|
|
@@ -59,9 +58,9 @@ function normalizeList(values, key, errors, filePath) {
|
|
|
59
58
|
continue;
|
|
60
59
|
}
|
|
61
60
|
if (ID_LIST_KEYS.has(key) && !isValidId(entry)) {
|
|
62
|
-
errors.push(`${filePath}: ${key} entries must match <prefix>-<number
|
|
61
|
+
errors.push(`${filePath}: ${key} entries must match <prefix>-<number> or reserved id`);
|
|
63
62
|
}
|
|
64
|
-
if (ID_REF_LIST_KEYS.has(key) && !
|
|
63
|
+
if (ID_REF_LIST_KEYS.has(key) && !(0, id_1.isCanonicalIdRef)(entry)) {
|
|
65
64
|
errors.push(`${filePath}: ${key} entries must be valid id references`);
|
|
66
65
|
}
|
|
67
66
|
}
|
|
@@ -69,7 +68,7 @@ function normalizeList(values, key, errors, filePath) {
|
|
|
69
68
|
}
|
|
70
69
|
function normalizeIdRef(value, key, errors, filePath) {
|
|
71
70
|
const normalized = normalizeScalar(value).toLowerCase();
|
|
72
|
-
if (!
|
|
71
|
+
if (!(0, id_1.isCanonicalIdRef)(normalized)) {
|
|
73
72
|
errors.push(`${filePath}: ${key} must be a valid id reference`);
|
|
74
73
|
}
|
|
75
74
|
return normalized;
|
|
@@ -124,7 +123,7 @@ function normalizeFrontmatter(frontmatter, schema, type, workStatusEnum, priorit
|
|
|
124
123
|
else {
|
|
125
124
|
const normalizedId = idValue.toLowerCase();
|
|
126
125
|
if (!isValidId(normalizedId)) {
|
|
127
|
-
errors.push(`${filePath}: id must match <prefix>-<number
|
|
126
|
+
errors.push(`${filePath}: id must match <prefix>-<number> or reserved id`);
|
|
128
127
|
}
|
|
129
128
|
normalized.id = normalizedId;
|
|
130
129
|
}
|
package/dist/commands/index.js
CHANGED
|
@@ -8,10 +8,16 @@ const path_1 = __importDefault(require("path"));
|
|
|
8
8
|
const config_1 = require("../core/config");
|
|
9
9
|
const indexer_1 = require("../graph/indexer");
|
|
10
10
|
const index_cache_1 = require("../graph/index_cache");
|
|
11
|
+
const skills_index_cache_1 = require("../graph/skills_index_cache");
|
|
12
|
+
const skills_indexer_1 = require("../graph/skills_indexer");
|
|
11
13
|
function runIndexCommand(options) {
|
|
12
14
|
const config = (0, config_1.loadConfig)(options.root);
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
const nodeIndex = (0, indexer_1.buildIndex)(options.root, config, { tolerant: options.tolerant });
|
|
16
|
+
const skillsIndex = (0, skills_indexer_1.buildSkillsIndex)(options.root, config);
|
|
17
|
+
const nodesOutputPath = path_1.default.resolve(options.root, config.index.global_index_path);
|
|
18
|
+
const skillsOutputPath = (0, skills_indexer_1.resolveSkillsIndexPath)(options.root);
|
|
19
|
+
(0, index_cache_1.writeIndex)(nodesOutputPath, nodeIndex);
|
|
20
|
+
(0, skills_index_cache_1.writeSkillsIndex)(skillsOutputPath, skillsIndex);
|
|
21
|
+
console.log(`index written: ${path_1.default.relative(options.root, nodesOutputPath)}`);
|
|
22
|
+
console.log(`skills index written: ${path_1.default.relative(options.root, skillsOutputPath)}`);
|
|
17
23
|
}
|