mdkg 0.1.6 → 0.1.7

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.
@@ -56,6 +56,13 @@ function normalizePortableId(value, flag) {
56
56
  }
57
57
  return normalized;
58
58
  }
59
+ function normalizePortableIdRef(value, flag) {
60
+ const normalized = value.toLowerCase();
61
+ if (!(0, id_1.isPortableIdRef)(normalized)) {
62
+ throw new errors_1.UsageError(`${flag} must be a lowercase portable id or qid`);
63
+ }
64
+ return normalized;
65
+ }
59
66
  function normalizeEnum(value, flag, allowed) {
60
67
  const normalized = value.toLowerCase();
61
68
  if (!allowed.has(normalized)) {
@@ -95,20 +102,14 @@ function maybeReindex(root, config) {
95
102
  }
96
103
  (0, reindex_1.writeDerivedIndexes)(root, config, (0, indexer_1.buildIndex)(root, config, { tolerant: config.index.tolerant }));
97
104
  }
98
- function findNodeById(index, ws, id, type) {
99
- const node = index.nodes[`${ws}:${id}`];
100
- if (!node) {
101
- return undefined;
102
- }
103
- if (type && node.type !== type) {
104
- return undefined;
105
+ function requireReferenceNode(index, ws, idOrQid, type, label) {
106
+ const resolved = (0, qid_1.resolveQid)(index, idOrQid, ws);
107
+ if (resolved.status !== "ok") {
108
+ throw new errors_1.NotFoundError((0, qid_1.formatResolveError)(label, idOrQid, resolved, ws));
105
109
  }
106
- return node;
107
- }
108
- function requireNodeById(index, ws, id, type, label) {
109
- const node = findNodeById(index, ws, id, type);
110
- if (!node) {
111
- throw new errors_1.NotFoundError(`${label} not found: ${id}`);
110
+ const node = index.nodes[resolved.qid];
111
+ if (!node || node.type !== type) {
112
+ throw new errors_1.NotFoundError(`${label} not found: ${idOrQid}`);
112
113
  }
113
114
  return node;
114
115
  }
@@ -214,8 +215,9 @@ function runWorkContractNewCommandLocked(options) {
214
215
  const config = (0, config_1.loadConfig)(options.root);
215
216
  const ws = normalizeWorkspace(options.ws);
216
217
  const { index } = (0, index_cache_1.loadIndex)({ root: options.root, config });
217
- const agentId = normalizePortableId(options.agentId, "--agent-id");
218
- const relates = findNodeById(index, ws, agentId, "spec") ? [agentId] : [];
218
+ const agentId = normalizePortableIdRef(options.agentId, "--agent-id");
219
+ const resolvedAgent = (0, qid_1.resolveQid)(index, agentId, ws);
220
+ const relates = resolvedAgent.status === "ok" && index.nodes[resolvedAgent.qid]?.type === "spec" ? [agentId] : [];
219
221
  const receipt = createAgentWorkflowNode({
220
222
  root: options.root,
221
223
  ws,
@@ -240,8 +242,8 @@ function runWorkOrderNewCommandLocked(options) {
240
242
  const config = (0, config_1.loadConfig)(options.root);
241
243
  const ws = normalizeWorkspace(options.ws);
242
244
  const { index } = (0, index_cache_1.loadIndex)({ root: options.root, config });
243
- const workId = normalizePortableId(options.workId, "--work-id");
244
- const workNode = requireNodeById(index, ws, workId, "work", "work contract");
245
+ const workId = normalizePortableIdRef(options.workId, "--work-id");
246
+ const workNode = requireReferenceNode(index, ws, workId, "work", "work contract");
245
247
  const workVersion = String(workNode.attributes.version ?? "0.1.0");
246
248
  const receipt = createAgentWorkflowNode({
247
249
  root: options.root,
@@ -281,8 +283,8 @@ function runWorkReceiptNewCommandLocked(options) {
281
283
  const config = (0, config_1.loadConfig)(options.root);
282
284
  const ws = normalizeWorkspace(options.ws);
283
285
  const { index } = (0, index_cache_1.loadIndex)({ root: options.root, config });
284
- const workOrderId = normalizePortableId(options.workOrderId, "--work-order-id");
285
- requireNodeById(index, ws, workOrderId, "work_order", "work order");
286
+ const workOrderId = normalizePortableIdRef(options.workOrderId, "--work-order-id");
287
+ requireReferenceNode(index, ws, workOrderId, "work_order", "work order");
286
288
  const receipt = createAgentWorkflowNode({
287
289
  root: options.root,
288
290
  ws,
@@ -9,6 +9,7 @@ const fs_1 = __importDefault(require("fs"));
9
9
  const paths_1 = require("./paths");
10
10
  const migrate_1 = require("./migrate");
11
11
  const workspace_path_1 = require("./workspace_path");
12
+ const project_db_1 = require("./project_db");
12
13
  const WORKSPACE_ALIAS_RE = /^[a-z][a-z0-9_]*$/;
13
14
  const PACK_EDGE_KEYS = new Set([
14
15
  "parent",
@@ -24,10 +25,22 @@ const WORKSPACE_VISIBILITY_VALUES = new Set(["private", "internal", "public"]);
24
25
  const BUNDLE_PROFILE_VALUES = new Set(["private", "public"]);
25
26
  const INDEX_BACKEND_VALUES = new Set(["json", "sqlite"]);
26
27
  const SUBGRAPH_PERMISSION_VALUES = new Set(["read", "request", "propose", "mutate"]);
28
+ const SQL_IDENTIFIER_RE = /^[a-z][a-z0-9_]*$/;
27
29
  const DEFAULT_ARCHIVE_LARGE_CACHE_WARNING_BYTES = 26214400;
28
30
  const DEFAULT_SQLITE_COMMIT_WARNING_BYTES = 52428800;
29
31
  const DEFAULT_LOCK_TIMEOUT_MS = 10000;
30
32
  const DEFAULT_SUBGRAPH_MAX_STALE_SECONDS = 3600;
33
+ const DEFAULT_PROJECT_DB_CONFIG = {
34
+ enabled: false,
35
+ schema_version: project_db_1.PROJECT_DB_CONFIG_SCHEMA_VERSION,
36
+ root_path: project_db_1.PROJECT_DB_RELATIVE_DIR,
37
+ schema_path: project_db_1.PROJECT_DB_SCHEMA_DIR,
38
+ migrations_path: project_db_1.PROJECT_DB_MIGRATIONS_DIR,
39
+ runtime_path: project_db_1.PROJECT_DB_RUNTIME_FILE,
40
+ state_path: project_db_1.PROJECT_DB_STATE_FILE,
41
+ receipts_path: project_db_1.PROJECT_DB_RECEIPTS_DIR,
42
+ migration_table: project_db_1.PROJECT_DB_MIGRATION_TABLE,
43
+ };
31
44
  function isObject(value) {
32
45
  return typeof value === "object" && value !== null && !Array.isArray(value);
33
46
  }
@@ -200,6 +213,40 @@ function requireContainedPath(value, path, errors) {
200
213
  return undefined;
201
214
  }
202
215
  }
216
+ function requireSqlIdentifier(value, path, errors) {
217
+ const raw = requireString(value, path, errors);
218
+ if (raw === undefined) {
219
+ return undefined;
220
+ }
221
+ if (!SQL_IDENTIFIER_RE.test(raw)) {
222
+ errors.push(`${path} must be a lowercase SQL identifier using [a-z0-9_]`);
223
+ return undefined;
224
+ }
225
+ return raw;
226
+ }
227
+ function isContainedConfigPath(rootPath, candidate) {
228
+ return candidate === rootPath || candidate.startsWith(`${rootPath}/`);
229
+ }
230
+ function defaultProjectDbChildPath(rootPath, suffix, fallback) {
231
+ if (!rootPath) {
232
+ return fallback;
233
+ }
234
+ if (rootPath === ".") {
235
+ return suffix;
236
+ }
237
+ return `${rootPath}/${suffix}`;
238
+ }
239
+ function requireProjectDbPath(value, path, rootPath, errors) {
240
+ const normalized = requireContainedPath(value, path, errors);
241
+ if (normalized === undefined || rootPath === undefined) {
242
+ return normalized;
243
+ }
244
+ if (!isContainedConfigPath(rootPath, normalized)) {
245
+ errors.push(`${path} must be inside db.root_path`);
246
+ return undefined;
247
+ }
248
+ return normalized;
249
+ }
203
250
  function validateConfigSchema(raw) {
204
251
  const errors = [];
205
252
  if (!isObject(raw)) {
@@ -218,6 +265,7 @@ function validateConfigSchema(raw) {
218
265
  const bundlesRaw = raw.bundles === undefined
219
266
  ? { output_dir: ".mdkg/bundles", default_profile: "private" }
220
267
  : requireObject(raw.bundles, "bundles", errors);
268
+ const dbRaw = raw.db === undefined ? DEFAULT_PROJECT_DB_CONFIG : requireObject(raw.db, "db", errors);
221
269
  if (raw.bundle_imports !== undefined && raw.subgraphs !== undefined) {
222
270
  errors.push("config must not define both subgraphs and legacy bundle_imports");
223
271
  }
@@ -268,6 +316,60 @@ function validateConfigSchema(raw) {
268
316
  default_profile: requireStringInSet(bundlesRaw.default_profile, "bundles.default_profile", BUNDLE_PROFILE_VALUES, errors),
269
317
  }
270
318
  : undefined;
319
+ let db;
320
+ if (dbRaw) {
321
+ if ("profile" in dbRaw || "profiles" in dbRaw || "profile_name" in dbRaw) {
322
+ errors.push("db profiles are not supported in this release");
323
+ }
324
+ const dbEnabled = dbRaw.enabled === undefined
325
+ ? DEFAULT_PROJECT_DB_CONFIG.enabled
326
+ : requireBoolean(dbRaw.enabled, "db.enabled", errors);
327
+ const dbSchemaVersion = dbRaw.schema_version === undefined
328
+ ? DEFAULT_PROJECT_DB_CONFIG.schema_version
329
+ : requirePositiveInteger(dbRaw.schema_version, "db.schema_version", errors);
330
+ const dbRootPath = dbRaw.root_path === undefined
331
+ ? DEFAULT_PROJECT_DB_CONFIG.root_path
332
+ : requireContainedPath(dbRaw.root_path, "db.root_path", errors);
333
+ const dbSchemaPath = requireProjectDbPath(dbRaw.schema_path === undefined
334
+ ? defaultProjectDbChildPath(dbRootPath, "schema", DEFAULT_PROJECT_DB_CONFIG.schema_path)
335
+ : dbRaw.schema_path, "db.schema_path", dbRootPath, errors);
336
+ const dbMigrationsPath = requireProjectDbPath(dbRaw.migrations_path === undefined
337
+ ? defaultProjectDbChildPath(dbRootPath, "schema/migrations", DEFAULT_PROJECT_DB_CONFIG.migrations_path)
338
+ : dbRaw.migrations_path, "db.migrations_path", dbRootPath, errors);
339
+ const dbRuntimePath = requireProjectDbPath(dbRaw.runtime_path === undefined
340
+ ? defaultProjectDbChildPath(dbRootPath, "runtime/project.sqlite", DEFAULT_PROJECT_DB_CONFIG.runtime_path)
341
+ : dbRaw.runtime_path, "db.runtime_path", dbRootPath, errors);
342
+ const dbStatePath = requireProjectDbPath(dbRaw.state_path === undefined
343
+ ? defaultProjectDbChildPath(dbRootPath, "state/project.sqlite", DEFAULT_PROJECT_DB_CONFIG.state_path)
344
+ : dbRaw.state_path, "db.state_path", dbRootPath, errors);
345
+ const dbReceiptsPath = requireProjectDbPath(dbRaw.receipts_path === undefined
346
+ ? defaultProjectDbChildPath(dbRootPath, "receipts", DEFAULT_PROJECT_DB_CONFIG.receipts_path)
347
+ : dbRaw.receipts_path, "db.receipts_path", dbRootPath, errors);
348
+ const dbMigrationTable = dbRaw.migration_table === undefined
349
+ ? DEFAULT_PROJECT_DB_CONFIG.migration_table
350
+ : requireSqlIdentifier(dbRaw.migration_table, "db.migration_table", errors);
351
+ if (dbEnabled !== undefined &&
352
+ dbSchemaVersion !== undefined &&
353
+ dbRootPath &&
354
+ dbSchemaPath &&
355
+ dbMigrationsPath &&
356
+ dbRuntimePath &&
357
+ dbStatePath &&
358
+ dbReceiptsPath &&
359
+ dbMigrationTable) {
360
+ db = {
361
+ enabled: dbEnabled,
362
+ schema_version: dbSchemaVersion,
363
+ root_path: dbRootPath,
364
+ schema_path: dbSchemaPath,
365
+ migrations_path: dbMigrationsPath,
366
+ runtime_path: dbRuntimePath,
367
+ state_path: dbStatePath,
368
+ receipts_path: dbReceiptsPath,
369
+ migration_table: dbMigrationTable,
370
+ };
371
+ }
372
+ }
271
373
  const packLimitsRaw = packRaw ? requireObject(packRaw.limits, "pack.limits", errors) : undefined;
272
374
  const pack = packRaw
273
375
  ? {
@@ -502,6 +604,7 @@ function validateConfigSchema(raw) {
502
604
  index: index,
503
605
  capabilities: capabilities,
504
606
  bundles: bundles,
607
+ db: db,
505
608
  subgraphs,
506
609
  pack: pack,
507
610
  templates: templates,
@@ -0,0 +1,108 @@
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.PROJECT_DB_GITIGNORE_ENTRIES = exports.PROJECT_DB_SUBDIRS = exports.PROJECT_DB_MIGRATION_TABLE = exports.PROJECT_DB_CONFIG_SCHEMA_VERSION = exports.PROJECT_DB_MANIFEST_FILE = exports.PROJECT_DB_STATE_MANIFEST_FILE = exports.PROJECT_DB_STATE_FILE = exports.PROJECT_DB_RUNTIME_FILE = exports.PROJECT_DB_RECEIPTS_DIR = exports.PROJECT_DB_STATE_DIR = exports.PROJECT_DB_RUNTIME_DIR = exports.PROJECT_DB_MIGRATIONS_DIR = exports.PROJECT_DB_SCHEMA_DIR = exports.PROJECT_DB_RELATIVE_DIR = void 0;
7
+ exports.resolveProjectDbLayout = resolveProjectDbLayout;
8
+ exports.resolveConfiguredProjectDbLayout = resolveConfiguredProjectDbLayout;
9
+ exports.listProjectDbRuntimePolicyFiles = listProjectDbRuntimePolicyFiles;
10
+ const fs_1 = __importDefault(require("fs"));
11
+ const path_1 = __importDefault(require("path"));
12
+ exports.PROJECT_DB_RELATIVE_DIR = ".mdkg/db";
13
+ exports.PROJECT_DB_SCHEMA_DIR = ".mdkg/db/schema";
14
+ exports.PROJECT_DB_MIGRATIONS_DIR = ".mdkg/db/schema/migrations";
15
+ exports.PROJECT_DB_RUNTIME_DIR = ".mdkg/db/runtime";
16
+ exports.PROJECT_DB_STATE_DIR = ".mdkg/db/state";
17
+ exports.PROJECT_DB_RECEIPTS_DIR = ".mdkg/db/receipts";
18
+ exports.PROJECT_DB_RUNTIME_FILE = ".mdkg/db/runtime/project.sqlite";
19
+ exports.PROJECT_DB_STATE_FILE = ".mdkg/db/state/project.sqlite";
20
+ exports.PROJECT_DB_STATE_MANIFEST_FILE = ".mdkg/db/state/project.manifest.json";
21
+ exports.PROJECT_DB_MANIFEST_FILE = ".mdkg/db/project-db.json";
22
+ exports.PROJECT_DB_CONFIG_SCHEMA_VERSION = 1;
23
+ exports.PROJECT_DB_MIGRATION_TABLE = "mdkg_schema_migration";
24
+ exports.PROJECT_DB_SUBDIRS = [
25
+ exports.PROJECT_DB_SCHEMA_DIR,
26
+ exports.PROJECT_DB_MIGRATIONS_DIR,
27
+ exports.PROJECT_DB_RUNTIME_DIR,
28
+ exports.PROJECT_DB_STATE_DIR,
29
+ exports.PROJECT_DB_RECEIPTS_DIR,
30
+ ];
31
+ exports.PROJECT_DB_GITIGNORE_ENTRIES = [
32
+ ".mdkg/db/runtime/",
33
+ ".mdkg/db/**/*.sqlite-wal",
34
+ ".mdkg/db/**/*.sqlite-shm",
35
+ ".mdkg/db/**/*.sqlite-journal",
36
+ ".mdkg/db/**/*.lock",
37
+ ".mdkg/db/**/*.tmp",
38
+ ];
39
+ const TRANSIENT_SUFFIXES = [
40
+ "-wal",
41
+ "-shm",
42
+ "-journal",
43
+ ".lock",
44
+ ".tmp",
45
+ ];
46
+ function toPosix(relativePath) {
47
+ return relativePath.split(path_1.default.sep).join("/");
48
+ }
49
+ function walkFiles(root) {
50
+ if (!fs_1.default.existsSync(root)) {
51
+ return [];
52
+ }
53
+ const entries = fs_1.default.readdirSync(root, { withFileTypes: true });
54
+ const files = [];
55
+ for (const entry of entries) {
56
+ const fullPath = path_1.default.join(root, entry.name);
57
+ if (entry.isDirectory()) {
58
+ files.push(...walkFiles(fullPath));
59
+ }
60
+ else if (entry.isFile()) {
61
+ files.push(fullPath);
62
+ }
63
+ }
64
+ return files;
65
+ }
66
+ function resolveProjectDbLayout(root) {
67
+ return {
68
+ root,
69
+ db: path_1.default.resolve(root, exports.PROJECT_DB_RELATIVE_DIR),
70
+ schema: path_1.default.resolve(root, exports.PROJECT_DB_SCHEMA_DIR),
71
+ migrations: path_1.default.resolve(root, exports.PROJECT_DB_MIGRATIONS_DIR),
72
+ runtime: path_1.default.resolve(root, exports.PROJECT_DB_RUNTIME_DIR),
73
+ state: path_1.default.resolve(root, exports.PROJECT_DB_STATE_DIR),
74
+ receipts: path_1.default.resolve(root, exports.PROJECT_DB_RECEIPTS_DIR),
75
+ };
76
+ }
77
+ function resolveConfiguredProjectDbLayout(root, config) {
78
+ const runtimeFile = path_1.default.resolve(root, config.runtime_path);
79
+ const stateFile = path_1.default.resolve(root, config.state_path);
80
+ const stateManifest = path_1.default.join(path_1.default.dirname(stateFile), `${path_1.default.basename(stateFile, path_1.default.extname(stateFile))}.manifest.json`);
81
+ return {
82
+ root,
83
+ db: path_1.default.resolve(root, config.root_path),
84
+ schema: path_1.default.resolve(root, config.schema_path),
85
+ migrations: path_1.default.resolve(root, config.migrations_path),
86
+ runtimeFile,
87
+ runtimeDir: path_1.default.dirname(runtimeFile),
88
+ stateFile,
89
+ stateManifest,
90
+ stateDir: path_1.default.dirname(stateFile),
91
+ receipts: path_1.default.resolve(root, config.receipts_path),
92
+ manifest: path_1.default.resolve(root, config.root_path, "project-db.json"),
93
+ };
94
+ }
95
+ function listProjectDbRuntimePolicyFiles(root) {
96
+ const layout = resolveProjectDbLayout(root);
97
+ const dbFiles = walkFiles(layout.db);
98
+ return dbFiles
99
+ .filter((filePath) => {
100
+ if (filePath.startsWith(`${layout.runtime}${path_1.default.sep}`)) {
101
+ return true;
102
+ }
103
+ const basename = path_1.default.basename(filePath);
104
+ return TRANSIENT_SUFFIXES.some((suffix) => basename.endsWith(suffix));
105
+ })
106
+ .map((filePath) => toPosix(path_1.default.relative(root, filePath)))
107
+ .sort();
108
+ }