mdkg 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +51 -0
- package/README.md +31 -15
- package/dist/cli.js +182 -85
- package/dist/commands/archive.js +20 -8
- package/dist/commands/bundle.js +7 -7
- package/dist/commands/capability.js +118 -4
- package/dist/commands/checkpoint.js +31 -5
- package/dist/commands/doctor.js +61 -24
- package/dist/commands/index.js +12 -23
- package/dist/commands/init.js +7 -1
- package/dist/commands/list.js +1 -1
- package/dist/commands/new.js +33 -7
- package/dist/commands/next.js +1 -1
- package/dist/commands/node_card.js +1 -1
- package/dist/commands/pack.js +1 -1
- package/dist/commands/search.js +1 -1
- package/dist/commands/show.js +1 -1
- package/dist/commands/subgraph.js +312 -0
- package/dist/commands/task.js +21 -7
- package/dist/commands/upgrade.js +51 -4
- package/dist/commands/validate.js +12 -6
- package/dist/commands/work.js +44 -12
- package/dist/core/config.js +110 -39
- package/dist/graph/capabilities_index_cache.js +2 -2
- package/dist/graph/index_cache.js +14 -14
- package/dist/graph/indexer.js +1 -1
- package/dist/graph/reindex.js +46 -0
- package/dist/graph/skills_index_cache.js +2 -2
- package/dist/graph/sqlite_index.js +293 -0
- package/dist/graph/{bundle_imports.js → subgraphs.js} +216 -142
- package/dist/graph/visibility.js +3 -3
- package/dist/init/AGENT_START.md +5 -1
- package/dist/init/CLI_COMMAND_MATRIX.md +21 -7
- package/dist/init/README.md +20 -10
- package/dist/init/config.json +6 -2
- package/dist/init/core/rule-1-mdkg-conventions.md +2 -1
- package/dist/init/core/rule-3-cli-contract.md +32 -24
- package/dist/init/core/rule-4-repo-safety-and-ignores.md +28 -12
- package/dist/init/core/rule-5-release-and-versioning.md +4 -3
- package/dist/init/init-manifest.json +10 -10
- package/dist/init/skills/default/verify-close-and-checkpoint/SKILL.md +1 -1
- package/dist/util/argparse.js +2 -0
- package/dist/util/atomic.js +44 -0
- package/dist/util/lock.js +72 -0
- package/package.json +13 -9
- package/dist/commands/bundle_import.js +0 -243
|
@@ -1,243 +0,0 @@
|
|
|
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.runBundleImportAddCommand = runBundleImportAddCommand;
|
|
7
|
-
exports.runBundleImportListCommand = runBundleImportListCommand;
|
|
8
|
-
exports.runBundleImportRemoveCommand = runBundleImportRemoveCommand;
|
|
9
|
-
exports.runBundleImportEnableCommand = runBundleImportEnableCommand;
|
|
10
|
-
exports.runBundleImportDisableCommand = runBundleImportDisableCommand;
|
|
11
|
-
exports.runBundleImportVerifyCommand = runBundleImportVerifyCommand;
|
|
12
|
-
const fs_1 = __importDefault(require("fs"));
|
|
13
|
-
const path_1 = __importDefault(require("path"));
|
|
14
|
-
const config_1 = require("../core/config");
|
|
15
|
-
const migrate_1 = require("../core/migrate");
|
|
16
|
-
const workspace_path_1 = require("../core/workspace_path");
|
|
17
|
-
const bundle_imports_1 = require("../graph/bundle_imports");
|
|
18
|
-
const errors_1 = require("../util/errors");
|
|
19
|
-
const ALIAS_RE = /^[a-z][a-z0-9_]*$/;
|
|
20
|
-
function writeJson(value) {
|
|
21
|
-
console.log(JSON.stringify(value, null, 2));
|
|
22
|
-
}
|
|
23
|
-
function normalizeAlias(alias) {
|
|
24
|
-
if (alias === "all") {
|
|
25
|
-
throw new errors_1.UsageError("bundle import alias cannot be 'all'");
|
|
26
|
-
}
|
|
27
|
-
if (alias !== alias.toLowerCase() || !ALIAS_RE.test(alias)) {
|
|
28
|
-
throw new errors_1.UsageError("bundle import alias must be lowercase and use [a-z0-9_]");
|
|
29
|
-
}
|
|
30
|
-
return alias;
|
|
31
|
-
}
|
|
32
|
-
function normalizeVisibility(value) {
|
|
33
|
-
const normalized = (value ?? "private").toLowerCase();
|
|
34
|
-
if (normalized === "private" || normalized === "internal" || normalized === "public") {
|
|
35
|
-
return normalized;
|
|
36
|
-
}
|
|
37
|
-
throw new errors_1.UsageError("--visibility must be private, internal, or public");
|
|
38
|
-
}
|
|
39
|
-
function normalizeProfile(value) {
|
|
40
|
-
const normalized = (value ?? "private").toLowerCase();
|
|
41
|
-
if (normalized === "private" || normalized === "public") {
|
|
42
|
-
return normalized;
|
|
43
|
-
}
|
|
44
|
-
throw new errors_1.UsageError("--profile must be private or public");
|
|
45
|
-
}
|
|
46
|
-
function normalizeContained(value, label) {
|
|
47
|
-
try {
|
|
48
|
-
return (0, workspace_path_1.normalizeContainedWorkspacePath)(value, label);
|
|
49
|
-
}
|
|
50
|
-
catch (err) {
|
|
51
|
-
throw new errors_1.UsageError(err instanceof Error ? err.message : String(err));
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
function readRawConfig(root) {
|
|
55
|
-
const configPath = path_1.default.join(root, ".mdkg", "config.json");
|
|
56
|
-
if (!fs_1.default.existsSync(configPath)) {
|
|
57
|
-
throw new errors_1.NotFoundError(`config not found at ${configPath}`);
|
|
58
|
-
}
|
|
59
|
-
let parsed;
|
|
60
|
-
try {
|
|
61
|
-
parsed = JSON.parse(fs_1.default.readFileSync(configPath, "utf8"));
|
|
62
|
-
}
|
|
63
|
-
catch (err) {
|
|
64
|
-
throw new errors_1.UsageError(`failed to read config: ${err instanceof Error ? err.message : String(err)}`);
|
|
65
|
-
}
|
|
66
|
-
const migrated = (0, migrate_1.migrateConfig)(parsed).config;
|
|
67
|
-
(0, config_1.validateConfigSchema)(migrated);
|
|
68
|
-
if (typeof migrated !== "object" || migrated === null || Array.isArray(migrated)) {
|
|
69
|
-
throw new errors_1.UsageError("config must be a JSON object");
|
|
70
|
-
}
|
|
71
|
-
return { configPath, raw: migrated };
|
|
72
|
-
}
|
|
73
|
-
function writeRawConfig(configPath, raw) {
|
|
74
|
-
fs_1.default.writeFileSync(configPath, `${JSON.stringify(raw, null, 2)}\n`, "utf8");
|
|
75
|
-
}
|
|
76
|
-
function getImports(raw) {
|
|
77
|
-
const imports = raw.bundle_imports;
|
|
78
|
-
if (imports === undefined) {
|
|
79
|
-
raw.bundle_imports = {};
|
|
80
|
-
return raw.bundle_imports;
|
|
81
|
-
}
|
|
82
|
-
if (typeof imports !== "object" || imports === null || Array.isArray(imports)) {
|
|
83
|
-
throw new errors_1.UsageError("config.bundle_imports must be an object");
|
|
84
|
-
}
|
|
85
|
-
return imports;
|
|
86
|
-
}
|
|
87
|
-
function receiptForHealth(action, health) {
|
|
88
|
-
return {
|
|
89
|
-
action,
|
|
90
|
-
import: health,
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
function healthByAlias(root, alias) {
|
|
94
|
-
const config = (0, config_1.loadConfig)(root);
|
|
95
|
-
const health = (0, bundle_imports_1.buildBundleImportsIndex)(root, config).index.imports.find((item) => item.alias === alias);
|
|
96
|
-
if (!health) {
|
|
97
|
-
throw new errors_1.NotFoundError(`bundle import not found: ${alias}`);
|
|
98
|
-
}
|
|
99
|
-
return health;
|
|
100
|
-
}
|
|
101
|
-
function runBundleImportAddCommand(options) {
|
|
102
|
-
const alias = normalizeAlias(options.alias);
|
|
103
|
-
const bundlePath = normalizeContained(options.bundlePath, "bundle import path");
|
|
104
|
-
const visibility = normalizeVisibility(options.visibility);
|
|
105
|
-
const expected_profile = normalizeProfile(options.profile);
|
|
106
|
-
if (visibility !== "private" && expected_profile !== "public") {
|
|
107
|
-
throw new errors_1.UsageError("--profile public is required when --visibility is public or internal");
|
|
108
|
-
}
|
|
109
|
-
const source_path = options.sourcePath
|
|
110
|
-
? normalizeContained(options.sourcePath, "bundle import source path")
|
|
111
|
-
: undefined;
|
|
112
|
-
if (options.maxStaleSeconds !== undefined && (!Number.isInteger(options.maxStaleSeconds) || options.maxStaleSeconds <= 0)) {
|
|
113
|
-
throw new errors_1.UsageError("--max-stale-seconds must be a positive integer");
|
|
114
|
-
}
|
|
115
|
-
const { configPath, raw } = readRawConfig(options.root);
|
|
116
|
-
const imports = getImports(raw);
|
|
117
|
-
if (imports[alias]) {
|
|
118
|
-
throw new errors_1.UsageError(`bundle import already exists: ${alias}`);
|
|
119
|
-
}
|
|
120
|
-
const workspaces = raw.workspaces;
|
|
121
|
-
if (workspaces && workspaces[alias]) {
|
|
122
|
-
throw new errors_1.UsageError(`bundle import alias collides with workspace: ${alias}`);
|
|
123
|
-
}
|
|
124
|
-
imports[alias] = {
|
|
125
|
-
path: bundlePath,
|
|
126
|
-
enabled: true,
|
|
127
|
-
visibility,
|
|
128
|
-
expected_profile,
|
|
129
|
-
...(source_path ? { source_path } : {}),
|
|
130
|
-
...(options.sourceRepo ? { source_repo: options.sourceRepo } : {}),
|
|
131
|
-
...(options.maxStaleSeconds !== undefined ? { max_stale_seconds: options.maxStaleSeconds } : {}),
|
|
132
|
-
};
|
|
133
|
-
raw.bundle_imports = imports;
|
|
134
|
-
const validated = (0, config_1.validateConfigSchema)(raw);
|
|
135
|
-
const health = (0, bundle_imports_1.buildBundleImportsIndex)(options.root, validated).index.imports.find((item) => item.alias === alias);
|
|
136
|
-
if (!health) {
|
|
137
|
-
throw new errors_1.NotFoundError(`bundle import not found after validation: ${alias}`);
|
|
138
|
-
}
|
|
139
|
-
if (health.error_count > 0) {
|
|
140
|
-
throw new errors_1.ValidationError(`bundle import ${alias} is invalid:\n${health.errors.join("\n")}`);
|
|
141
|
-
}
|
|
142
|
-
writeRawConfig(configPath, raw);
|
|
143
|
-
const receipt = receiptForHealth("added", health);
|
|
144
|
-
if (options.json) {
|
|
145
|
-
writeJson(receipt);
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
148
|
-
console.log(`bundle import added: ${alias} (${bundlePath})`);
|
|
149
|
-
if (health.warning_count > 0) {
|
|
150
|
-
console.log(`warnings: ${health.warning_count}`);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
function runBundleImportListCommand(options) {
|
|
154
|
-
const config = (0, config_1.loadConfig)(options.root);
|
|
155
|
-
const imports = (0, bundle_imports_1.buildBundleImportsIndex)(options.root, config).index.imports;
|
|
156
|
-
if (options.json) {
|
|
157
|
-
writeJson({ action: "list", count: imports.length, imports });
|
|
158
|
-
return;
|
|
159
|
-
}
|
|
160
|
-
if (imports.length === 0) {
|
|
161
|
-
console.log("no bundle imports configured");
|
|
162
|
-
return;
|
|
163
|
-
}
|
|
164
|
-
for (const item of imports) {
|
|
165
|
-
const status = item.enabled ? item.error_count > 0 ? "invalid" : item.stale ? "stale" : "ok" : "disabled";
|
|
166
|
-
console.log(`${item.alias} | ${status} | ${item.visibility} | ${item.path}`);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
function runBundleImportRemoveCommand(options) {
|
|
170
|
-
const alias = normalizeAlias(options.alias);
|
|
171
|
-
const { configPath, raw } = readRawConfig(options.root);
|
|
172
|
-
const imports = getImports(raw);
|
|
173
|
-
const existing = imports[alias];
|
|
174
|
-
if (!existing) {
|
|
175
|
-
throw new errors_1.NotFoundError(`bundle import not found: ${alias}`);
|
|
176
|
-
}
|
|
177
|
-
delete imports[alias];
|
|
178
|
-
raw.bundle_imports = imports;
|
|
179
|
-
(0, config_1.validateConfigSchema)(raw);
|
|
180
|
-
writeRawConfig(configPath, raw);
|
|
181
|
-
const receipt = { action: "removed", import: { alias } };
|
|
182
|
-
if (options.json) {
|
|
183
|
-
writeJson(receipt);
|
|
184
|
-
return;
|
|
185
|
-
}
|
|
186
|
-
console.log(`bundle import removed: ${alias}`);
|
|
187
|
-
}
|
|
188
|
-
function setBundleImportEnabled(options, enabled) {
|
|
189
|
-
const alias = normalizeAlias(options.alias);
|
|
190
|
-
const { configPath, raw } = readRawConfig(options.root);
|
|
191
|
-
const imports = getImports(raw);
|
|
192
|
-
const existing = imports[alias];
|
|
193
|
-
if (!existing || typeof existing !== "object" || Array.isArray(existing)) {
|
|
194
|
-
throw new errors_1.NotFoundError(`bundle import not found: ${alias}`);
|
|
195
|
-
}
|
|
196
|
-
imports[alias] = { ...existing, enabled };
|
|
197
|
-
raw.bundle_imports = imports;
|
|
198
|
-
(0, config_1.validateConfigSchema)(raw);
|
|
199
|
-
writeRawConfig(configPath, raw);
|
|
200
|
-
const health = healthByAlias(options.root, alias);
|
|
201
|
-
const receipt = receiptForHealth(enabled ? "enabled" : "disabled", health);
|
|
202
|
-
if (options.json) {
|
|
203
|
-
writeJson(receipt);
|
|
204
|
-
return;
|
|
205
|
-
}
|
|
206
|
-
console.log(`bundle import ${enabled ? "enabled" : "disabled"}: ${alias}`);
|
|
207
|
-
}
|
|
208
|
-
function runBundleImportEnableCommand(options) {
|
|
209
|
-
setBundleImportEnabled(options, true);
|
|
210
|
-
}
|
|
211
|
-
function runBundleImportDisableCommand(options) {
|
|
212
|
-
setBundleImportEnabled(options, false);
|
|
213
|
-
}
|
|
214
|
-
function runBundleImportVerifyCommand(options) {
|
|
215
|
-
const config = (0, config_1.loadConfig)(options.root);
|
|
216
|
-
const all = options.all || !options.alias;
|
|
217
|
-
const imports = (0, bundle_imports_1.buildBundleImportsIndex)(options.root, config).index.imports.filter((item) => all ? true : item.alias === options.alias);
|
|
218
|
-
if (!all && imports.length === 0) {
|
|
219
|
-
throw new errors_1.NotFoundError(`bundle import not found: ${options.alias}`);
|
|
220
|
-
}
|
|
221
|
-
const ok = imports.every((item) => item.error_count === 0 && !item.stale);
|
|
222
|
-
const receipt = { action: "verified", ok, count: imports.length, imports };
|
|
223
|
-
if (options.json) {
|
|
224
|
-
writeJson(receipt);
|
|
225
|
-
}
|
|
226
|
-
else if (ok) {
|
|
227
|
-
console.log(`bundle imports verified: ${imports.length}`);
|
|
228
|
-
}
|
|
229
|
-
else {
|
|
230
|
-
console.log(`bundle import verify failed: ${imports.length}`);
|
|
231
|
-
for (const item of imports) {
|
|
232
|
-
for (const warning of item.warnings) {
|
|
233
|
-
console.log(`warning: ${item.alias}: ${warning}`);
|
|
234
|
-
}
|
|
235
|
-
for (const error of item.errors) {
|
|
236
|
-
console.log(`error: ${item.alias}: ${error}`);
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
if (!ok) {
|
|
241
|
-
throw new errors_1.ValidationError("bundle import verify failed");
|
|
242
|
-
}
|
|
243
|
-
}
|