@senticor/hive 1.49.2 → 1.51.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.
Files changed (4) hide show
  1. package/README.md +8 -6
  2. package/chive.cjs +1472 -0
  3. package/hive.cjs +886 -11
  4. package/package.json +4 -2
package/chive.cjs ADDED
@@ -0,0 +1,1472 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
29
+
30
+ // ../../node_modules/.pnpm/tsup@8.5.1_@swc+core@1.15.43_@swc+helpers@0.5.23__jiti@2.7.0_postcss@8.5.28_supports-co_ebdccb821406f648b54993c6aadaa9c1/node_modules/tsup/assets/cjs_shims.js
31
+ var getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.tagName.toUpperCase() === "SCRIPT" ? document.currentScript.src : new URL("main.js", document.baseURI).href;
32
+ var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
33
+
34
+ // src/chive.mts
35
+ var import_node_fs = __toESM(require("fs"), 1);
36
+ var import_node_path = __toESM(require("path"), 1);
37
+
38
+ // ../hive-kernel-code-context/src/index.ts
39
+ var src_exports = {};
40
+ __export(src_exports, {
41
+ BUILDER_VERSION: () => BUILDER_VERSION2,
42
+ EXT_LANG: () => EXT_LANG2,
43
+ buildContextPacket: () => buildContextPacket2,
44
+ buildDelta: () => buildDelta2,
45
+ buildGraph: () => buildGraph2,
46
+ parseFile: () => parseFile2,
47
+ projectContextPacket: () => projectContextPacket2,
48
+ projectDelta: () => projectDelta2,
49
+ projectGraph: () => projectGraph2,
50
+ scanRepository: () => scanRepository2
51
+ });
52
+
53
+ // ../hive-kernel-code-context/src/scanner.ts
54
+ var scanner_exports = {};
55
+ __export(scanner_exports, {
56
+ DEFAULT_IGNORES: () => DEFAULT_IGNORES,
57
+ EXT_LANG: () => EXT_LANG,
58
+ scanRepository: () => scanRepository
59
+ });
60
+ var fs = __toESM(require("fs"), 1);
61
+ var path = __toESM(require("path"), 1);
62
+ var DEFAULT_IGNORES = /* @__PURE__ */ new Set([
63
+ "node_modules",
64
+ ".git",
65
+ ".pnpm-store",
66
+ "dist",
67
+ "build",
68
+ "out",
69
+ ".next",
70
+ ".turbo",
71
+ ".cache",
72
+ "coverage",
73
+ ".venv",
74
+ "venv",
75
+ "__pycache__",
76
+ ".pytest_cache",
77
+ ".mypy_cache",
78
+ ".terraform"
79
+ ]);
80
+ var EXT_LANG = {
81
+ ".ts": "typescript",
82
+ ".tsx": "typescript",
83
+ ".mts": "typescript",
84
+ ".cts": "typescript",
85
+ ".js": "javascript",
86
+ ".jsx": "javascript",
87
+ ".mjs": "javascript",
88
+ ".cjs": "javascript",
89
+ ".py": "python",
90
+ ".tf": "terraform",
91
+ ".yaml": "yaml",
92
+ ".yml": "yaml"
93
+ };
94
+ function readGitignore(repoRoot) {
95
+ const file = path.join(repoRoot, ".gitignore");
96
+ if (!fs.existsSync(file)) return [];
97
+ const text = fs.readFileSync(file, "utf8");
98
+ return text.split(/\r?\n/).map((l) => l.trim()).filter((l) => l && !l.startsWith("#")).map((l) => l.replace(/^\//, "").replace(/\/$/, ""));
99
+ }
100
+ function matchesIgnore(name, ignorePatterns) {
101
+ if (DEFAULT_IGNORES.has(name)) return true;
102
+ for (const pat of ignorePatterns) {
103
+ if (!pat.includes("*") && pat === name) return true;
104
+ if (pat.includes("*")) {
105
+ const re = new RegExp("^" + pat.replace(/\./g, "\\.").replace(/\*/g, ".*") + "$");
106
+ if (re.test(name)) return true;
107
+ }
108
+ }
109
+ return false;
110
+ }
111
+ function scanRepository({ repositoryRoot, maxFiles = 5e3, extensions = null } = {}) {
112
+ if (!repositoryRoot || !fs.existsSync(repositoryRoot)) {
113
+ throw new Error(`repositoryRoot does not exist: ${repositoryRoot}`);
114
+ }
115
+ const absRoot = path.resolve(repositoryRoot);
116
+ const ignorePatterns = readGitignore(absRoot);
117
+ const wantExt = extensions ? new Set(extensions.map((e) => e.startsWith(".") ? e : "." + e)) : null;
118
+ const files = [];
119
+ let truncated = false;
120
+ const walk = (dir) => {
121
+ if (truncated) return;
122
+ let entries;
123
+ try {
124
+ entries = fs.readdirSync(dir, { withFileTypes: true });
125
+ } catch (_) {
126
+ return;
127
+ }
128
+ for (const entry of entries) {
129
+ if (truncated) return;
130
+ const name = entry.name;
131
+ if (matchesIgnore(name, ignorePatterns)) continue;
132
+ const full = path.join(dir, name);
133
+ if (entry.isDirectory()) {
134
+ walk(full);
135
+ } else if (entry.isFile()) {
136
+ const ext = path.extname(name).toLowerCase();
137
+ const lang = EXT_LANG[ext];
138
+ if (!lang) continue;
139
+ if (wantExt && !wantExt.has(ext)) continue;
140
+ if (files.length >= maxFiles) {
141
+ truncated = true;
142
+ return;
143
+ }
144
+ files.push({
145
+ filePath: path.relative(absRoot, full),
146
+ absPath: full,
147
+ language: lang,
148
+ ext
149
+ });
150
+ }
151
+ }
152
+ };
153
+ walk(absRoot);
154
+ return { files, truncated, repositoryRoot: absRoot };
155
+ }
156
+
157
+ // ../hive-kernel-code-context/src/ts-parser.ts
158
+ var ts_parser_exports = {};
159
+ __export(ts_parser_exports, {
160
+ isTsLang: () => isTsLang,
161
+ moduleIdFor: () => moduleIdFor,
162
+ parseFile: () => parseFile
163
+ });
164
+ var fs2 = __toESM(require("fs"), 1);
165
+ var path2 = __toESM(require("path"), 1);
166
+ var import_node_module = require("module");
167
+ var _require = (0, import_node_module.createRequire)(importMetaUrl);
168
+ var _ts = null;
169
+ function ts() {
170
+ if (_ts) return _ts;
171
+ const mod = _require("typescript");
172
+ _ts = mod;
173
+ return mod;
174
+ }
175
+ function isTsLang(lang) {
176
+ return lang === "typescript" || lang === "javascript";
177
+ }
178
+ function scriptKindForExt(ext) {
179
+ const T = ts();
180
+ switch (ext) {
181
+ case ".ts":
182
+ case ".mts":
183
+ case ".cts":
184
+ return T.ScriptKind.TS;
185
+ case ".tsx":
186
+ return T.ScriptKind.TSX;
187
+ case ".jsx":
188
+ return T.ScriptKind.JSX;
189
+ case ".js":
190
+ case ".mjs":
191
+ case ".cjs":
192
+ default:
193
+ return T.ScriptKind.JS;
194
+ }
195
+ }
196
+ function nodeIdFor(filePath, kind, name, pos2) {
197
+ return `${kind}:${filePath}#${name || "_"}@${pos2}`;
198
+ }
199
+ function moduleIdFor(filePath) {
200
+ return `module:${filePath}`;
201
+ }
202
+ function parseFile({ filePath, absPath, ext = path2.extname(absPath).toLowerCase(), repositoryRoot }) {
203
+ const T = ts();
204
+ const source = fs2.readFileSync(absPath, "utf8");
205
+ const sf = T.createSourceFile(
206
+ absPath,
207
+ source,
208
+ T.ScriptTarget.Latest,
209
+ /*setParentNodes*/
210
+ true,
211
+ scriptKindForExt(ext)
212
+ );
213
+ const nodes = [];
214
+ const edges = [];
215
+ const moduleNodeId = moduleIdFor(filePath);
216
+ const language = EXT_LANG[ext] || (ext === ".ts" || ext === ".tsx" ? "typescript" : "javascript");
217
+ nodes.push({
218
+ nodeId: moduleNodeId,
219
+ kind: "module",
220
+ label: filePath,
221
+ filePath,
222
+ spanStart: 0,
223
+ spanEnd: source.length,
224
+ language
225
+ });
226
+ const definedSymbols = /* @__PURE__ */ new Map();
227
+ function recordDecl(kind, name, node) {
228
+ if (!name) return null;
229
+ const id = nodeIdFor(filePath, kind, name, node.pos);
230
+ nodes.push({
231
+ nodeId: id,
232
+ kind,
233
+ label: name,
234
+ filePath,
235
+ spanStart: node.getStart(sf),
236
+ spanEnd: node.getEnd(),
237
+ language
238
+ });
239
+ edges.push({
240
+ edgeId: `${moduleNodeId}|defines|${id}`,
241
+ from: moduleNodeId,
242
+ to: id,
243
+ predicate: "defines"
244
+ });
245
+ definedSymbols.set(name, id);
246
+ return id;
247
+ }
248
+ function resolveImportPath(specifier) {
249
+ if (!specifier) return null;
250
+ if (specifier.startsWith(".")) {
251
+ const baseDir = path2.dirname(filePath);
252
+ let resolved = path2.normalize(path2.join(baseDir, specifier));
253
+ if (resolved.startsWith("./")) resolved = resolved.slice(2);
254
+ return resolved;
255
+ }
256
+ return specifier;
257
+ }
258
+ function recordImport(specifier, importedNames, node) {
259
+ if (!specifier) return;
260
+ const resolved = resolveImportPath(specifier);
261
+ const isLocal = specifier.startsWith(".");
262
+ const targetId = isLocal ? `module:${resolved}` : `extmodule:${specifier}`;
263
+ edges.push({
264
+ edgeId: `${moduleNodeId}|imports|${targetId}@${node.pos}`,
265
+ from: moduleNodeId,
266
+ to: targetId,
267
+ predicate: "imports",
268
+ meta: {
269
+ specifier,
270
+ importedNames: importedNames || [],
271
+ external: !isLocal
272
+ }
273
+ });
274
+ if (!isLocal) {
275
+ nodes.push({
276
+ nodeId: targetId,
277
+ kind: "external_module",
278
+ label: specifier,
279
+ meta: { external: true }
280
+ });
281
+ }
282
+ }
283
+ function recordTopLevelCall(callee, node) {
284
+ if (!callee) return;
285
+ const targetSymbol = definedSymbols.get(callee);
286
+ const targetId = targetSymbol || `symbol:${callee}@external`;
287
+ edges.push({
288
+ edgeId: `${moduleNodeId}|calls|${targetId}@${node.pos}`,
289
+ from: moduleNodeId,
290
+ to: targetId,
291
+ predicate: "calls",
292
+ meta: { callee, external: !targetSymbol }
293
+ });
294
+ }
295
+ function visit(node) {
296
+ if (T.isFunctionDeclaration(node)) {
297
+ const name = node.name ? node.name.text : null;
298
+ recordDecl("function", name, node);
299
+ return;
300
+ }
301
+ if (T.isClassDeclaration(node)) {
302
+ const name = node.name ? node.name.text : null;
303
+ recordDecl("class", name, node);
304
+ return;
305
+ }
306
+ if (T.isInterfaceDeclaration(node)) {
307
+ recordDecl("interface", node.name.text, node);
308
+ return;
309
+ }
310
+ if (T.isTypeAliasDeclaration(node)) {
311
+ recordDecl("type", node.name.text, node);
312
+ return;
313
+ }
314
+ if (T.isEnumDeclaration(node)) {
315
+ recordDecl("enum", node.name.text, node);
316
+ return;
317
+ }
318
+ if (T.isVariableStatement(node)) {
319
+ for (const decl of node.declarationList.declarations) {
320
+ if (T.isIdentifier(decl.name)) {
321
+ recordDecl("const", decl.name.text, decl);
322
+ }
323
+ }
324
+ return;
325
+ }
326
+ if (T.isImportDeclaration(node)) {
327
+ const moduleSpec = node.moduleSpecifier && T.isStringLiteral(node.moduleSpecifier) ? node.moduleSpecifier.text : null;
328
+ const names = [];
329
+ if (node.importClause) {
330
+ if (node.importClause.name) names.push(node.importClause.name.text);
331
+ const nb = node.importClause.namedBindings;
332
+ if (nb) {
333
+ if (T.isNamedImports(nb)) {
334
+ for (const e of nb.elements) names.push(e.name.text);
335
+ } else if (T.isNamespaceImport(nb)) {
336
+ names.push("* as " + nb.name.text);
337
+ }
338
+ }
339
+ }
340
+ recordImport(moduleSpec, names, node);
341
+ return;
342
+ }
343
+ if (T.isExpressionStatement(node) && T.isCallExpression(node.expression)) {
344
+ const call = node.expression;
345
+ let callee = null;
346
+ if (T.isIdentifier(call.expression)) callee = call.expression.text;
347
+ else if (T.isPropertyAccessExpression(call.expression)) callee = call.expression.name.text;
348
+ recordTopLevelCall(callee, node);
349
+ return;
350
+ }
351
+ }
352
+ sf.forEachChild(visit);
353
+ return { nodes, edges };
354
+ }
355
+
356
+ // ../hive-kernel-code-context/src/graph-builder.ts
357
+ var graph_builder_exports = {};
358
+ __export(graph_builder_exports, {
359
+ BUILDER_VERSION: () => BUILDER_VERSION,
360
+ buildGraph: () => buildGraph
361
+ });
362
+ var path4 = __toESM(require("path"), 1);
363
+
364
+ // ../hive-utils/dist/index.js
365
+ var import_node_crypto2 = require("crypto");
366
+
367
+ // ../hive-utils/dist/pagination.js
368
+ var import_node_crypto = require("crypto");
369
+
370
+ // ../hive-utils/dist/schema-org-records.js
371
+ var fs3 = __toESM(require("fs"), 1);
372
+ var path3 = __toESM(require("path"), 1);
373
+
374
+ // ../hive-utils/dist/ssrf.js
375
+ var import_node_net = __toESM(require("net"), 1);
376
+ var import_node_dns = __toESM(require("dns"), 1);
377
+
378
+ // ../hive-utils/dist/file-sniff.js
379
+ var PDF_SIG = Buffer.from("%PDF-", "latin1");
380
+
381
+ // ../hive-utils/dist/limits.js
382
+ var INGEST_LIMIT_SPEC = {
383
+ /**
384
+ * Max ids in a daily reconciliation manifest's job_application_ids[].
385
+ * `ceiling` is the hard wire-contract cap from the JSON schema's `maxItems`;
386
+ * an env override is clamped to it so the env-driven handler guard and the
387
+ * `/api/me/limits` advertisement can never exceed what the ajv validator
388
+ * accepts (otherwise a client following discovery would send a manifest the
389
+ * Kafka inline validator rejects as schema_mismatch — split behaviour).
390
+ */
391
+ manifestMaxApplicationIds: { env: "HIVE_MANIFEST_MAX_APPLICATION_IDS", default: 1e5, ceiling: 1e5 },
392
+ /** Max attached documents per application. */
393
+ maxDocsPerApplication: { env: "HIVE_MAX_DOCS_PER_APPLICATION", default: 50 },
394
+ // NOTE: a per-jobposting application ceiling is intentionally NOT advertised
395
+ // here yet — enforcing it needs a durable per-jobposting counter at ingest,
396
+ // deferred to a follow-up. Advertising an unenforced limit would mislead
397
+ // clients (#1218 review), so it stays out of the discovery surface until wired.
398
+ /** Max bytes for a single ingested file (file-drop / upload). */
399
+ maxIngestFileBytes: { env: "HIVE_MAX_INGEST_FILE_BYTES", default: 25 * 1024 * 1024 },
400
+ /** Max pages rendered from a single PDF. */
401
+ maxPdfPages: { env: "HIVE_PDF_MARKDOWN_MAX_PAGES", default: 50 },
402
+ /** Max request body bytes accepted by ingest routes. */
403
+ maxBodyBytes: { env: "HIVE_MAX_BODY_BYTES", default: 10 * 1024 * 1024 },
404
+ // PDF semantic-enrichment caps (#1379) — folded into the SoT so they are
405
+ // advertised at /api/me/limits and read from one place instead of being
406
+ // hardcoded in the enrichment service. Breaching any of these flags the
407
+ // parent application (APPLICATION_PROCESSING_INCOMPLETE) instead of silently
408
+ // truncating. The `ceiling` is the hard cap above which an env override is
409
+ // clamped (a single oversized ingest must not OOM the worker — the #1326 root cause).
410
+ /** Max input bytes admitted into PDF semantic enrichment (skip+flag above). */
411
+ maxPdfEnrichmentInputBytes: { env: "HIVE_PDF_MAX_ENRICH_BYTES", default: 50 * 1024 * 1024, ceiling: 256 * 1024 * 1024 },
412
+ /** Max extracted-text chars fed to PDF semantic enrichment (abort+flag above). */
413
+ maxPdfEnrichmentTextChars: { env: "HIVE_PDF_MAX_ENRICH_TEXT_CHARS", default: 5e5, ceiling: 8e6 },
414
+ /** Max per-stream decompressed bytes when extracting PDF text (zip-bomb guard). */
415
+ maxPdfStreamDecompressionBytes: { env: "HIVE_PDF_MAX_DECOMPRESSION_BYTES", default: 64 * 1024 * 1024, ceiling: 256 * 1024 * 1024 },
416
+ /**
417
+ * Max UTF-8 bytes of a Kafka binding's broker CA bundle (`tls.caPem`, #83).
418
+ * The ceiling mirrors the wire-contract cap the api-contracts validator
419
+ * enforces (MISSION_KAFKA_TLS_CA_MAX_BYTES) — an env override can only
420
+ * LOWER the effective limit, so `/api/me/limits` never advertises more
421
+ * than the validator accepts (same split-behaviour guard as
422
+ * manifestMaxApplicationIds).
423
+ */
424
+ maxKafkaTlsCaPemBytes: { env: "HIVE_MAX_KAFKA_TLS_CA_PEM_BYTES", default: 64 * 1024, ceiling: 64 * 1024 }
425
+ };
426
+
427
+ // ../hive-utils/dist/index.js
428
+ function sha256Hex(input) {
429
+ const h = (0, import_node_crypto2.createHash)("sha256");
430
+ h.update(input);
431
+ return h.digest("hex");
432
+ }
433
+ function nowIso() {
434
+ return (/* @__PURE__ */ new Date()).toISOString();
435
+ }
436
+
437
+ // ../hive-kernel-code-context/src/graph-builder.ts
438
+ var BUILDER_VERSION = "0.1.0";
439
+ function buildGraph(params) {
440
+ const p = params || {};
441
+ const {
442
+ repositoryRoot,
443
+ repositoryRev = null,
444
+ graphId,
445
+ graphType = "source",
446
+ maxFiles = 5e3,
447
+ extensions = null
448
+ } = p;
449
+ if (!repositoryRoot) {
450
+ throw new Error("repositoryRoot is required");
451
+ }
452
+ const scan = scanRepository({ repositoryRoot, maxFiles, extensions });
453
+ const nodes = [];
454
+ const edges = [];
455
+ const seenNodes = /* @__PURE__ */ new Set();
456
+ const seenEdges = /* @__PURE__ */ new Set();
457
+ for (const file of scan.files) {
458
+ if (!isTsLang(file.language)) continue;
459
+ let result;
460
+ try {
461
+ result = parseFile({
462
+ filePath: file.filePath,
463
+ absPath: file.absPath,
464
+ ext: file.ext,
465
+ repositoryRoot: scan.repositoryRoot
466
+ });
467
+ } catch {
468
+ continue;
469
+ }
470
+ for (const n of result.nodes) {
471
+ if (seenNodes.has(n.nodeId)) continue;
472
+ seenNodes.add(n.nodeId);
473
+ nodes.push(n);
474
+ }
475
+ for (const e of result.edges) {
476
+ if (seenEdges.has(e.edgeId)) continue;
477
+ seenEdges.add(e.edgeId);
478
+ edges.push(e);
479
+ }
480
+ }
481
+ const LOCAL_IMPORT_VARIANTS = [
482
+ "",
483
+ ".ts",
484
+ ".tsx",
485
+ ".mts",
486
+ ".cts",
487
+ ".js",
488
+ ".jsx",
489
+ ".mjs",
490
+ ".cjs",
491
+ "/index.ts",
492
+ "/index.tsx",
493
+ "/index.mts",
494
+ "/index.cts",
495
+ "/index.js",
496
+ "/index.jsx",
497
+ "/index.mjs",
498
+ "/index.cjs"
499
+ ];
500
+ for (const edge of edges) {
501
+ if (edge.predicate !== "imports") continue;
502
+ if (edge.meta && edge.meta.external) continue;
503
+ if (seenNodes.has(edge.to)) continue;
504
+ const base = edge.to.startsWith("module:") ? edge.to.slice("module:".length) : edge.to;
505
+ for (const variant of LOCAL_IMPORT_VARIANTS) {
506
+ const candidate = `module:${base}${variant}`;
507
+ if (seenNodes.has(candidate)) {
508
+ edge.to = candidate;
509
+ if (edge.meta) edge.meta.resolvedExtension = variant || null;
510
+ break;
511
+ }
512
+ }
513
+ }
514
+ const repoName = path4.basename(scan.repositoryRoot).toLowerCase().replace(/[^a-z0-9._-]/g, "-");
515
+ const finalGraphId = graphId || `cg.${repoName || "repo"}.v1`;
516
+ return {
517
+ schema: "hive.codeGraph.v1",
518
+ graphId: finalGraphId,
519
+ repositoryRoot: scan.repositoryRoot,
520
+ repositoryRev,
521
+ graphType,
522
+ builtAt: nowIso(),
523
+ builderVersion: BUILDER_VERSION,
524
+ nodes,
525
+ edges,
526
+ stats: {
527
+ nodeCount: nodes.length,
528
+ edgeCount: edges.length,
529
+ fileCount: scan.files.length,
530
+ truncated: scan.truncated
531
+ },
532
+ meta: {
533
+ builderLangs: ["typescript", "javascript"]
534
+ }
535
+ };
536
+ }
537
+
538
+ // ../hive-kernel-code-context/src/context-builder.ts
539
+ var context_builder_exports = {};
540
+ __export(context_builder_exports, {
541
+ APPROX_CHARS_PER_TOKEN: () => APPROX_CHARS_PER_TOKEN,
542
+ buildContextPacket: () => buildContextPacket
543
+ });
544
+ var fs4 = __toESM(require("fs"), 1);
545
+ var path5 = __toESM(require("path"), 1);
546
+ var APPROX_CHARS_PER_TOKEN = 4;
547
+ function _matchScope(node, scope) {
548
+ if (!scope) return false;
549
+ if (Array.isArray(scope.paths) && node.filePath) {
550
+ for (const p of scope.paths) {
551
+ if (node.filePath === p || node.filePath.startsWith(p + path5.sep) || node.filePath.startsWith(p + "/")) {
552
+ return true;
553
+ }
554
+ }
555
+ }
556
+ if (Array.isArray(scope.symbols) && node.label) {
557
+ if (scope.symbols.includes(node.label)) return true;
558
+ }
559
+ return false;
560
+ }
561
+ function _readSnippet(absRoot, node) {
562
+ if (!node.filePath) return null;
563
+ const abs = path5.isAbsolute(node.filePath) ? node.filePath : path5.join(absRoot || "", node.filePath);
564
+ let source;
565
+ try {
566
+ source = fs4.readFileSync(abs, "utf8");
567
+ } catch (_) {
568
+ return null;
569
+ }
570
+ const start = Math.max(0, node.spanStart || 0);
571
+ const end = Math.min(source.length, node.spanEnd || source.length);
572
+ return {
573
+ filePath: node.filePath,
574
+ spanStart: start,
575
+ spanEnd: end,
576
+ content: source.slice(start, end),
577
+ language: node.language || null,
578
+ reason: node.kind,
579
+ graphPath: [node.nodeId]
580
+ };
581
+ }
582
+ function buildContextPacket(params) {
583
+ const p = params || {};
584
+ const { graph, task, packetId, tokenBudgetHint = 4e3, repositoryRoot } = p;
585
+ if (!graph || graph.schema !== "hive.codeGraph.v1") {
586
+ throw new Error("graph must be a hive.codeGraph.v1 object");
587
+ }
588
+ if (!task || !task.objective) {
589
+ throw new Error("task.objective is required");
590
+ }
591
+ const absRoot = repositoryRoot || graph.repositoryRoot;
592
+ const nodesById = new Map(graph.nodes.map((n) => [n.nodeId, n]));
593
+ const seedIds = /* @__PURE__ */ new Set();
594
+ for (const n of graph.nodes) {
595
+ if (_matchScope(n, task.scope)) seedIds.add(n.nodeId);
596
+ }
597
+ const visited = new Set(seedIds);
598
+ for (const edge of graph.edges) {
599
+ if (seedIds.has(edge.from) || seedIds.has(edge.to)) {
600
+ visited.add(edge.from);
601
+ visited.add(edge.to);
602
+ }
603
+ }
604
+ const charBudget = Math.max(0, tokenBudgetHint * APPROX_CHARS_PER_TOKEN);
605
+ let usedChars = 0;
606
+ const snippets = [];
607
+ const ordered = [
608
+ ...[...seedIds].map((id) => nodesById.get(id)).filter((n) => Boolean(n)),
609
+ ...[...visited].filter((id) => !seedIds.has(id)).map((id) => nodesById.get(id)).filter((n) => Boolean(n))
610
+ ];
611
+ for (const node of ordered) {
612
+ if (node.kind === "external_module") continue;
613
+ const snip = _readSnippet(absRoot, node);
614
+ if (!snip) continue;
615
+ if (charBudget > 0 && usedChars + snip.content.length > charBudget && snippets.length > 0) {
616
+ break;
617
+ }
618
+ snippets.push(snip);
619
+ usedChars += snip.content.length;
620
+ }
621
+ const slug = (graph.graphId || "graph").replace(/^cg\./, "").replace(/\.v\d+$/, "");
622
+ const finalPacketId = packetId || `ccp.${slug || "task"}.v1`;
623
+ return {
624
+ schema: "hive.codeContextPacket.v1",
625
+ packetId: finalPacketId,
626
+ task: {
627
+ objective: task.objective,
628
+ kind: task.kind || "other",
629
+ scope: task.scope || {}
630
+ },
631
+ graphRefs: [
632
+ {
633
+ graphId: graph.graphId,
634
+ graphType: graph.graphType,
635
+ repositoryRev: graph.repositoryRev
636
+ }
637
+ ],
638
+ snippets,
639
+ findings: [],
640
+ tokenBudgetHint,
641
+ builtAt: nowIso(),
642
+ meta: {
643
+ seedCount: seedIds.size,
644
+ expandedCount: visited.size,
645
+ usedChars,
646
+ truncated: snippets.length < ordered.length
647
+ }
648
+ };
649
+ }
650
+
651
+ // ../hive-kernel-code-context/src/delta.ts
652
+ var delta_exports = {};
653
+ __export(delta_exports, {
654
+ buildDelta: () => buildDelta
655
+ });
656
+ function buildDelta({ baseGraph, headGraph, deltaId } = {}) {
657
+ if (!baseGraph || baseGraph.schema !== "hive.codeGraph.v1") {
658
+ throw new Error("baseGraph must be a hive.codeGraph.v1 object");
659
+ }
660
+ if (!headGraph || headGraph.schema !== "hive.codeGraph.v1") {
661
+ throw new Error("headGraph must be a hive.codeGraph.v1 object");
662
+ }
663
+ if (baseGraph.graphId !== headGraph.graphId) {
664
+ throw new Error(`graphId mismatch: ${baseGraph.graphId} vs ${headGraph.graphId}`);
665
+ }
666
+ const baseNodes = new Map(baseGraph.nodes.map((n) => [n.nodeId, n]));
667
+ const headNodes = new Map(headGraph.nodes.map((n) => [n.nodeId, n]));
668
+ const baseEdges = new Map(baseGraph.edges.map((e) => [e.edgeId, e]));
669
+ const headEdges = new Map(headGraph.edges.map((e) => [e.edgeId, e]));
670
+ const addedNodes = [];
671
+ const removedNodes = [];
672
+ for (const [id, n] of headNodes.entries()) {
673
+ if (!baseNodes.has(id)) addedNodes.push(n);
674
+ }
675
+ for (const id of baseNodes.keys()) {
676
+ if (!headNodes.has(id)) removedNodes.push(id);
677
+ }
678
+ const addedEdges = [];
679
+ const removedEdges = [];
680
+ for (const [id, e] of headEdges.entries()) {
681
+ if (!baseEdges.has(id)) addedEdges.push(e);
682
+ }
683
+ for (const id of baseEdges.keys()) {
684
+ if (!headEdges.has(id)) removedEdges.push(id);
685
+ }
686
+ const slug = (headGraph.graphId || "graph").replace(/^cg\./, "").replace(/\.v\d+$/, "");
687
+ const finalDeltaId = deltaId || `cgd.${slug || "graph"}.v1`;
688
+ return {
689
+ schema: "hive.codeGraphDelta.v1",
690
+ deltaId: finalDeltaId,
691
+ graphId: headGraph.graphId,
692
+ baseRev: baseGraph.repositoryRev || "unknown",
693
+ headRev: headGraph.repositoryRev || "unknown",
694
+ addedNodes,
695
+ removedNodes,
696
+ addedEdges,
697
+ removedEdges,
698
+ stats: {
699
+ addedNodes: addedNodes.length,
700
+ removedNodes: removedNodes.length,
701
+ addedEdges: addedEdges.length,
702
+ removedEdges: removedEdges.length
703
+ },
704
+ computedAt: nowIso()
705
+ };
706
+ }
707
+
708
+ // ../hive-kernel-code-context/src/projection.ts
709
+ var projection_exports = {};
710
+ __export(projection_exports, {
711
+ projectContextPacket: () => projectContextPacket,
712
+ projectDelta: () => projectDelta,
713
+ projectGraph: () => projectGraph
714
+ });
715
+ function _missionSlug(missionId) {
716
+ return String(missionId || "default").replace(/[^a-z0-9._-]/gi, "-");
717
+ }
718
+ function projectGraph({ graph, missionId, tenantId = "default" } = {}) {
719
+ if (!graph || graph.schema !== "hive.codeGraph.v1") {
720
+ throw new Error("graph must be a hive.codeGraph.v1 object");
721
+ }
722
+ if (!missionId) throw new Error("missionId is required");
723
+ const slug = _missionSlug(missionId);
724
+ const nodes = graph.nodes.map((n) => ({
725
+ nodeId: n.nodeId,
726
+ kind: n.kind,
727
+ label: n.label || n.nodeId,
728
+ layer: "code",
729
+ missionId,
730
+ tenantId,
731
+ meta: {
732
+ filePath: n.filePath || null,
733
+ spanStart: n.spanStart || null,
734
+ spanEnd: n.spanEnd || null,
735
+ language: n.language || null,
736
+ graphId: graph.graphId,
737
+ ...n.meta || {}
738
+ }
739
+ }));
740
+ const edges = graph.edges.map((e) => ({
741
+ edgeId: e.edgeId,
742
+ from: e.from,
743
+ predicate: e.predicate,
744
+ to: e.to,
745
+ layer: "code",
746
+ missionId,
747
+ weight: e.weight || null,
748
+ meta: {
749
+ graphId: graph.graphId,
750
+ ...e.meta || {}
751
+ }
752
+ }));
753
+ const cellWrites = [
754
+ {
755
+ cellId: `kc.code.${slug}.graph`,
756
+ records: [
757
+ {
758
+ recordType: "CodeGraphSnapshot",
759
+ recordId: `${graph.graphId}@${graph.repositoryRev || "unknown"}`,
760
+ payload: {
761
+ graphId: graph.graphId,
762
+ graphType: graph.graphType,
763
+ repositoryRoot: graph.repositoryRoot,
764
+ repositoryRev: graph.repositoryRev,
765
+ stats: graph.stats,
766
+ builtAt: graph.builtAt
767
+ }
768
+ }
769
+ ]
770
+ }
771
+ ];
772
+ return { graphMutations: { nodes, edges }, cellWrites };
773
+ }
774
+ function projectContextPacket({ packet, missionId, tenantId = "default" } = {}) {
775
+ if (!packet || packet.schema !== "hive.codeContextPacket.v1") {
776
+ throw new Error("packet must be a hive.codeContextPacket.v1 object");
777
+ }
778
+ if (!missionId) throw new Error("missionId is required");
779
+ const slug = _missionSlug(missionId);
780
+ const packetHash = sha256Hex(JSON.stringify({ task: packet.task, snippets: packet.snippets }));
781
+ const cellWrites = [
782
+ {
783
+ cellId: `kc.code.${slug}.context-packets`,
784
+ records: [
785
+ {
786
+ recordType: "CodeContextPacket",
787
+ recordId: packet.packetId,
788
+ payload: {
789
+ packetId: packet.packetId,
790
+ task: packet.task,
791
+ graphRefs: packet.graphRefs,
792
+ snippetCount: (packet.snippets || []).length,
793
+ findingCount: (packet.findings || []).length,
794
+ tokenBudgetHint: packet.tokenBudgetHint,
795
+ builtAt: packet.builtAt,
796
+ packetHash
797
+ }
798
+ }
799
+ ]
800
+ }
801
+ ];
802
+ if (Array.isArray(packet.findings) && packet.findings.length > 0) {
803
+ cellWrites.push({
804
+ cellId: `kc.code.${slug}.findings`,
805
+ records: packet.findings.map((f) => ({
806
+ recordType: "CodeFinding",
807
+ recordId: f.findingId,
808
+ payload: { ...f, packetId: packet.packetId }
809
+ }))
810
+ });
811
+ }
812
+ const evidence = (packet.snippets || []).map((s, i) => ({
813
+ evidenceId: `${packet.packetId}#snippet-${i}`,
814
+ type: "code_snippet",
815
+ payload: {
816
+ filePath: s.filePath,
817
+ spanStart: s.spanStart,
818
+ spanEnd: s.spanEnd,
819
+ language: s.language,
820
+ reason: s.reason,
821
+ graphPath: s.graphPath || [],
822
+ contentHash: sha256Hex(s.content || "")
823
+ }
824
+ }));
825
+ return { cellWrites, evidence };
826
+ }
827
+ function projectDelta({ delta, missionId } = {}) {
828
+ if (!delta || delta.schema !== "hive.codeGraphDelta.v1") {
829
+ throw new Error("delta must be a hive.codeGraphDelta.v1 object");
830
+ }
831
+ if (!missionId) throw new Error("missionId is required");
832
+ const slug = _missionSlug(missionId);
833
+ return {
834
+ eventType: "CodeGraphDeltaComputed",
835
+ eventBody: {
836
+ missionId,
837
+ deltaId: delta.deltaId,
838
+ graphId: delta.graphId,
839
+ baseRev: delta.baseRev,
840
+ headRev: delta.headRev,
841
+ stats: delta.stats
842
+ },
843
+ cellWrite: {
844
+ cellId: `kc.code.${slug}.deltas`,
845
+ records: [
846
+ {
847
+ recordType: "CodeGraphDelta",
848
+ recordId: delta.deltaId,
849
+ payload: delta
850
+ }
851
+ ]
852
+ }
853
+ };
854
+ }
855
+
856
+ // ../hive-kernel-code-context/src/index.ts
857
+ var { scanRepository: scanRepository2, EXT_LANG: EXT_LANG2 } = scanner_exports;
858
+ var { buildGraph: buildGraph2, BUILDER_VERSION: BUILDER_VERSION2 } = graph_builder_exports;
859
+ var { buildContextPacket: buildContextPacket2 } = context_builder_exports;
860
+ var { buildDelta: buildDelta2 } = delta_exports;
861
+ var { projectGraph: projectGraph2, projectContextPacket: projectContextPacket2, projectDelta: projectDelta2 } = projection_exports;
862
+ var { parseFile: parseFile2 } = ts_parser_exports;
863
+
864
+ // src/chive-http.mts
865
+ var ChiveHttpError = class extends Error {
866
+ code;
867
+ status;
868
+ body;
869
+ constructor(message, opts = {}) {
870
+ super(message);
871
+ this.name = "ChiveHttpError";
872
+ this.code = opts.code || "http_error";
873
+ this.status = opts.status || null;
874
+ this.body = opts.body || null;
875
+ }
876
+ };
877
+ function assertFlagRecord(flags2) {
878
+ if (flags2 == null) return void 0;
879
+ if (typeof flags2 !== "object" || Array.isArray(flags2)) {
880
+ throw new ChiveHttpError("CLI flags must be an object", { code: "invalid_flags" });
881
+ }
882
+ return flags2;
883
+ }
884
+ function optionalStringFlag(flags2, name) {
885
+ if (!flags2) return void 0;
886
+ const value = flags2[name];
887
+ if (value == null || value === false || value === "") return void 0;
888
+ if (typeof value !== "string") {
889
+ throw new ChiveHttpError(`--${name} requires a value`, { code: `invalid_${name.replace(/[^a-z0-9]/gi, "_")}_flag` });
890
+ }
891
+ return value;
892
+ }
893
+ function optionalEnvString(name) {
894
+ const value = process.env[name];
895
+ return value && value.length > 0 ? value : void 0;
896
+ }
897
+ function errorMessage(error) {
898
+ return error instanceof Error ? error.message : String(error);
899
+ }
900
+ function extractResponseMessage(parsed) {
901
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return null;
902
+ const obj = parsed;
903
+ if (typeof obj.error === "string" && obj.error) return obj.error;
904
+ if (typeof obj.message === "string" && obj.message) return obj.message;
905
+ return null;
906
+ }
907
+ function normalizeHeaders(headers) {
908
+ if (headers === void 0) return {};
909
+ if (!headers || typeof headers !== "object" || Array.isArray(headers)) {
910
+ throw new ChiveHttpError("headers must be an object", { code: "invalid_headers" });
911
+ }
912
+ return Object.fromEntries(
913
+ Object.entries(headers).map(([name, value]) => {
914
+ if (typeof value !== "string") {
915
+ throw new ChiveHttpError(`header ${name} must be a string`, { code: "invalid_headers" });
916
+ }
917
+ return [name, value];
918
+ })
919
+ );
920
+ }
921
+ function normalizeHttpOptions(options) {
922
+ if (!options || typeof options !== "object" || Array.isArray(options)) {
923
+ throw new ChiveHttpError("httpJson options must be an object", { code: "invalid_http_options" });
924
+ }
925
+ const method = options.method ?? "GET";
926
+ if (typeof method !== "string" || method.length === 0) {
927
+ throw new ChiveHttpError("HTTP method must be a non-empty string", { code: "invalid_method" });
928
+ }
929
+ if (typeof options.url !== "string" || options.url.length === 0) {
930
+ throw new ChiveHttpError("HTTP URL must be a non-empty string", { code: "invalid_url" });
931
+ }
932
+ if (options.token != null && typeof options.token !== "string") {
933
+ throw new ChiveHttpError("token must be a string", { code: "invalid_token" });
934
+ }
935
+ const timeoutMs = options.timeoutMs ?? 3e4;
936
+ if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
937
+ throw new ChiveHttpError("timeoutMs must be a positive number", { code: "invalid_timeout" });
938
+ }
939
+ return {
940
+ method,
941
+ url: options.url,
942
+ body: options.body,
943
+ token: options.token || null,
944
+ headers: normalizeHeaders(options.headers),
945
+ timeoutMs
946
+ };
947
+ }
948
+ function resolveApiBase(flags2) {
949
+ const flagRecord = assertFlagRecord(flags2);
950
+ const fromFlag = optionalStringFlag(flagRecord, "api") || optionalStringFlag(flagRecord, "api-base");
951
+ const fromEnv = optionalEnvString("HIVE_API_URL");
952
+ const base = (fromFlag || fromEnv || "").replace(/\/+$/, "");
953
+ if (!base) {
954
+ throw new ChiveHttpError(
955
+ "no API base URL \u2014 set HIVE_API_URL or pass --api <url>",
956
+ { code: "no_api_url" }
957
+ );
958
+ }
959
+ return base;
960
+ }
961
+ function resolveToken(flags2) {
962
+ const flagRecord = assertFlagRecord(flags2);
963
+ return optionalStringFlag(flagRecord, "token") || optionalEnvString("HIVE_API_TOKEN") || null;
964
+ }
965
+ async function httpJson(options) {
966
+ const { method, url, body, token, headers, timeoutMs } = normalizeHttpOptions(options);
967
+ const requestInit = {
968
+ method,
969
+ headers: {
970
+ accept: "application/json",
971
+ ...body !== void 0 ? { "content-type": "application/json" } : {},
972
+ ...token ? { authorization: `Bearer ${token}` } : {},
973
+ ...headers
974
+ }
975
+ };
976
+ if (body !== void 0) requestInit.body = JSON.stringify(body);
977
+ const controller = new AbortController();
978
+ const t = setTimeout(() => controller.abort(), timeoutMs);
979
+ requestInit.signal = controller.signal;
980
+ let res;
981
+ try {
982
+ res = await fetch(url, requestInit);
983
+ } catch (error) {
984
+ throw new ChiveHttpError(`network: ${errorMessage(error)}`, { code: "network" });
985
+ } finally {
986
+ clearTimeout(t);
987
+ }
988
+ const text = await res.text();
989
+ let parsed;
990
+ try {
991
+ parsed = text ? JSON.parse(text) : null;
992
+ } catch {
993
+ parsed = { raw: text };
994
+ }
995
+ if (!res.ok) {
996
+ const message = extractResponseMessage(parsed) || `HTTP ${res.status}`;
997
+ throw new ChiveHttpError(`${method} ${url} \u2192 ${res.status}: ${message}`, {
998
+ code: `http_${res.status}`,
999
+ status: res.status,
1000
+ body: parsed
1001
+ });
1002
+ }
1003
+ return parsed;
1004
+ }
1005
+ function mkRecordId(prefix) {
1006
+ if (typeof prefix !== "string" || prefix.length === 0) {
1007
+ throw new ChiveHttpError("record ID prefix must be a non-empty string", { code: "invalid_record_prefix" });
1008
+ }
1009
+ const ts2 = Date.now().toString(36);
1010
+ const rnd = Math.random().toString(36).slice(2, 8);
1011
+ return `${prefix}.${ts2}.${rnd}`;
1012
+ }
1013
+
1014
+ // src/chive.mts
1015
+ var VERSION = "0.2.0";
1016
+ var KNOWLEDGE_TOPICS = ["notes", "procedures", "examples", "post-mortems"];
1017
+ var KNOWLEDGE_RECORD_TYPES = {
1018
+ notes: "KnowledgeNote",
1019
+ procedures: "KnowledgeProcedure",
1020
+ examples: "KnowledgeExample",
1021
+ "post-mortems": "KnowledgePostMortem"
1022
+ };
1023
+ var KNOWLEDGE_TEMPLATE_ID = "mt.knowledge.base.v1";
1024
+ var codeContextKernel = src_exports;
1025
+ function parseArgs(argv) {
1026
+ const args = argv.slice(2);
1027
+ const positional = [];
1028
+ const flags2 = {};
1029
+ for (let i = 0; i < args.length; i++) {
1030
+ const a = args[i];
1031
+ if (a.startsWith("--")) {
1032
+ const eqIdx = a.indexOf("=");
1033
+ if (eqIdx > 0) {
1034
+ flags2[a.slice(2, eqIdx)] = a.slice(eqIdx + 1);
1035
+ } else if (i + 1 < args.length && !args[i + 1].startsWith("--")) {
1036
+ flags2[a.slice(2)] = args[++i];
1037
+ } else {
1038
+ flags2[a.slice(2)] = true;
1039
+ }
1040
+ } else {
1041
+ positional.push(a);
1042
+ }
1043
+ }
1044
+ return { positional, flags: flags2 };
1045
+ }
1046
+ var { positional: pos, flags } = parseArgs(process.argv);
1047
+ function printHelp() {
1048
+ console.log(`chive v${VERSION} \u2014 Cognitive Hive OS code-context CLI
1049
+
1050
+ OFFLINE (kernel-only):
1051
+ chive graph build --repo <path> [--rev <rev>] [--graph-id <id>] [--max-files N] [--out <file>]
1052
+ chive graph update --repo <path> --base <graph.json> [--rev <rev>] [--graph-id <id>] [--out <file>]
1053
+ chive context build --graph <graph.json> --task "..." [--paths a,b] [--symbols x,y]
1054
+ [--budget <tokens>] [--repo <path>] [--out <file>]
1055
+
1056
+ ONLINE (talks to HIVE_API_URL or --api <url>; bearer via HIVE_API_TOKEN or --token):
1057
+ chive memory remember --task "..." --kind bugfix [--outcome success|failure]
1058
+ [--packet <packet.json>] [--summary "..."] [--domain code]
1059
+ chive memory recall [--task "..."] [--kind ...] [--domain code] [--limit N]
1060
+ chive arch decide --mission <missionId> --title "..." --because "..."
1061
+ [--files a,b] [--packet <packet.json>]
1062
+ chive arch list --mission <missionId>
1063
+ chive todo add "<title>" --mission <missionId> [--file path:line]
1064
+ [--priority high|med|low]
1065
+ chive todo list --mission <missionId> [--status open|done]
1066
+ chive todo done <todoId> --mission <missionId>
1067
+ chive knowledge mission create --intent "..." [--title "..."]
1068
+ chive knowledge mission list
1069
+ chive knowledge note add --mission <missionId> --topic notes|procedures|examples|post-mortems
1070
+ --title "..." [--body "..."] [--body-file <file>]
1071
+ [--tags a,b,c]
1072
+ chive knowledge note list --mission <missionId> [--topic ...]
1073
+
1074
+ chive version | help
1075
+
1076
+ Offline JSON shapes follow specs/schemas/hive.codeGraph.v1, hive.codeContextPacket.v1,
1077
+ and hive.codeGraphDelta.v1. Online commands write JSON to stdout (or --out).
1078
+
1079
+ Examples:
1080
+ chive graph build --repo . --rev "$(git rev-parse HEAD)" --out graph.json
1081
+ chive context build --graph graph.json --task "Fix auth bug" --symbols login --out packet.json
1082
+ chive memory remember --task "Fix auth race" --kind bugfix --packet packet.json --outcome success
1083
+ chive arch decide --mission m-1 --title "Redis sessions" --because "1h TTL fits..."
1084
+ chive todo add "Validate JWT exp claim" --mission m-1 --file src/auth.ts:42 --priority high
1085
+ chive knowledge mission create --intent "Security knowledge base" --title "Security"
1086
+ chive knowledge note add --mission m-2 --topic procedures --title "Rotate keys" --body "..."
1087
+ `);
1088
+ }
1089
+ if (hasFlag("version") || pos[0] === "version") {
1090
+ console.log(`chive v${VERSION}`);
1091
+ process.exit(0);
1092
+ }
1093
+ if (hasFlag("help") || hasFlag("h") || !pos[0] || pos[0] === "help") {
1094
+ printHelp();
1095
+ process.exit(0);
1096
+ }
1097
+ function dieUsage(msg) {
1098
+ console.error(`chive: ${msg}
1099
+ Run \`chive help\` for usage.`);
1100
+ process.exit(2);
1101
+ }
1102
+ function errorMessage2(error) {
1103
+ return error instanceof Error ? error.message : String(error);
1104
+ }
1105
+ function dieRuntime(error) {
1106
+ console.error(`chive: ${errorMessage2(error)}`);
1107
+ if (hasFlag("verbose") && error instanceof Error && error.stack) console.error(error.stack);
1108
+ process.exit(3);
1109
+ }
1110
+ function hasFlag(name) {
1111
+ return flags[name] !== void 0 && flags[name] !== false;
1112
+ }
1113
+ function stringFlag(name) {
1114
+ const value = flags[name];
1115
+ if (value === void 0 || value === false || value === "") return void 0;
1116
+ if (typeof value !== "string") dieUsage(`--${name} requires a value`);
1117
+ return value;
1118
+ }
1119
+ function requiredStringFlag(name, command) {
1120
+ const value = stringFlag(name);
1121
+ if (!value) dieUsage(`--${name} is required for \`${command}\``);
1122
+ return value;
1123
+ }
1124
+ function splitList(value) {
1125
+ if (!value) return [];
1126
+ return value.split(",").map((x) => x.trim()).filter(Boolean);
1127
+ }
1128
+ function stringListFlag(name) {
1129
+ return splitList(stringFlag(name));
1130
+ }
1131
+ function readJsonFile(p, label) {
1132
+ if (!import_node_fs.default.existsSync(p)) dieUsage(`${label} not found at ${p}`);
1133
+ try {
1134
+ return JSON.parse(import_node_fs.default.readFileSync(p, "utf8"));
1135
+ } catch (error) {
1136
+ dieRuntime(new Error(`${label} is not valid JSON: ${errorMessage2(error)}`));
1137
+ }
1138
+ }
1139
+ function writeResult(obj) {
1140
+ const json = JSON.stringify(obj, null, 2);
1141
+ const out = stringFlag("out");
1142
+ if (out) {
1143
+ import_node_fs.default.writeFileSync(out, json + "\n");
1144
+ console.error(`chive: wrote ${import_node_path.default.resolve(out)}`);
1145
+ } else {
1146
+ process.stdout.write(json + "\n");
1147
+ }
1148
+ }
1149
+ function parseIntFlag(name, value, { min = 1 } = {}) {
1150
+ if (value === void 0 || value === false || value === "") return void 0;
1151
+ if (typeof value !== "string") dieUsage(`--${name} requires a value`);
1152
+ const n = Number.parseInt(value, 10);
1153
+ if (!Number.isFinite(n)) dieUsage(`--${name} must be an integer`);
1154
+ if (n < min) dieUsage(`--${name} must be at least ${min}`);
1155
+ return n;
1156
+ }
1157
+ function isKnowledgeTopic(value) {
1158
+ return KNOWLEDGE_TOPICS.includes(value);
1159
+ }
1160
+ function includesString(value, needle) {
1161
+ return Array.isArray(value) && value.some((item) => item === needle);
1162
+ }
1163
+ async function apiCall(method, urlPath, body) {
1164
+ const base = resolveApiBase(flags);
1165
+ const token = resolveToken(flags);
1166
+ return await httpJson({ method, url: `${base}${urlPath}`, body, token });
1167
+ }
1168
+ async function createRecord({ recordType, missionId, cellId, data }) {
1169
+ const recordId = mkRecordId(recordType.toLowerCase().replace(/[^a-z0-9]/g, "-"));
1170
+ return await apiCall("POST", "/api/records", {
1171
+ recordId,
1172
+ recordType,
1173
+ missionId,
1174
+ cellId: cellId || null,
1175
+ data
1176
+ });
1177
+ }
1178
+ async function listRecords({ recordType, missionId, extra = {} }) {
1179
+ const qs = new URLSearchParams({ recordType, ...missionId ? { missionId } : {}, ...extra });
1180
+ return await apiCall("GET", `/api/records?${qs.toString()}`, void 0);
1181
+ }
1182
+ async function patchRecord(recordId, patch) {
1183
+ return await apiCall("PATCH", `/api/records/${encodeURIComponent(recordId)}`, patch);
1184
+ }
1185
+ function readPacketIfSet() {
1186
+ const packetPath = stringFlag("packet");
1187
+ if (!packetPath) return null;
1188
+ if (!import_node_fs.default.existsSync(packetPath)) dieUsage(`packet file not found at ${packetPath}`);
1189
+ try {
1190
+ return JSON.parse(import_node_fs.default.readFileSync(packetPath, "utf8"));
1191
+ } catch (error) {
1192
+ dieRuntime(new Error(`packet is not valid JSON: ${errorMessage2(error)}`));
1193
+ }
1194
+ }
1195
+ function readBodyIfSet() {
1196
+ const body = stringFlag("body");
1197
+ if (body) return body;
1198
+ const bodyFile = stringFlag("body-file");
1199
+ if (bodyFile) {
1200
+ if (!import_node_fs.default.existsSync(bodyFile)) dieUsage(`body-file not found at ${bodyFile}`);
1201
+ return import_node_fs.default.readFileSync(bodyFile, "utf8");
1202
+ }
1203
+ return null;
1204
+ }
1205
+ var group = pos[0];
1206
+ var sub = pos[1];
1207
+ (function dispatch() {
1208
+ try {
1209
+ if (group === "graph" && sub === "build") {
1210
+ const repo = requiredStringFlag("repo", "graph build");
1211
+ const graph = codeContextKernel.buildGraph({
1212
+ repositoryRoot: repo,
1213
+ repositoryRev: stringFlag("rev") || null,
1214
+ graphId: stringFlag("graph-id") || null,
1215
+ maxFiles: parseIntFlag("max-files", flags["max-files"])
1216
+ });
1217
+ writeResult(graph);
1218
+ process.exit(0);
1219
+ }
1220
+ if (group === "graph" && sub === "update") {
1221
+ const repo = requiredStringFlag("repo", "graph update");
1222
+ const basePath = requiredStringFlag("base", "graph update");
1223
+ const base = readJsonFile(basePath, "base graph");
1224
+ const head = codeContextKernel.buildGraph({
1225
+ repositoryRoot: repo,
1226
+ repositoryRev: stringFlag("rev") || null,
1227
+ graphId: stringFlag("graph-id") || base.graphId || null
1228
+ });
1229
+ const delta = codeContextKernel.buildDelta({ baseGraph: base, headGraph: head });
1230
+ writeResult(delta);
1231
+ process.exit(0);
1232
+ }
1233
+ if (group === "context" && sub === "build") {
1234
+ const graphPath = requiredStringFlag("graph", "context build");
1235
+ const taskObjective = requiredStringFlag("task", "context build");
1236
+ const graph = readJsonFile(graphPath, "graph");
1237
+ const packet = codeContextKernel.buildContextPacket({
1238
+ graph,
1239
+ task: {
1240
+ objective: taskObjective,
1241
+ kind: stringFlag("kind") || "other",
1242
+ scope: {
1243
+ paths: stringListFlag("paths"),
1244
+ symbols: stringListFlag("symbols")
1245
+ }
1246
+ },
1247
+ tokenBudgetHint: parseIntFlag("budget", flags.budget, { min: 0 }) ?? 4e3,
1248
+ repositoryRoot: stringFlag("repo")
1249
+ });
1250
+ writeResult(packet);
1251
+ process.exit(0);
1252
+ }
1253
+ if (group === "memory") {
1254
+ handleMemory().catch(dieRuntime);
1255
+ return;
1256
+ }
1257
+ if (group === "arch") {
1258
+ handleArch().catch(dieRuntime);
1259
+ return;
1260
+ }
1261
+ if (group === "todo") {
1262
+ handleTodo().catch(dieRuntime);
1263
+ return;
1264
+ }
1265
+ if (group === "knowledge") {
1266
+ handleKnowledge().catch(dieRuntime);
1267
+ return;
1268
+ }
1269
+ dieUsage(`unknown command: ${group}${sub ? " " + sub : ""}`);
1270
+ } catch (e) {
1271
+ dieRuntime(e);
1272
+ }
1273
+ })();
1274
+ async function handleMemory() {
1275
+ if (sub === "remember") {
1276
+ const task = requiredStringFlag("task", "memory remember");
1277
+ const kind = requiredStringFlag("kind", "memory remember");
1278
+ const outcome = stringFlag("outcome");
1279
+ const summary = stringFlag("summary");
1280
+ const packet = readPacketIfSet();
1281
+ const content = summary ? summary : `task: ${task}${outcome ? ` \u2014 outcome: ${outcome}` : ""}`;
1282
+ const meta = {
1283
+ taskKind: kind,
1284
+ outcome: outcome || null,
1285
+ packetId: packet ? packet.packetId : null,
1286
+ graphRefs: packet ? packet.graphRefs || [] : [],
1287
+ taskObjective: task
1288
+ };
1289
+ const tags = ["code", kind];
1290
+ if (packet && Array.isArray(packet.graphRefs)) {
1291
+ for (const ref of packet.graphRefs) if (ref.graphId) tags.push(`graph:${ref.graphId}`);
1292
+ }
1293
+ const r = await apiCall("POST", "/api/cortex/promote", {
1294
+ domain: stringFlag("domain") || "code",
1295
+ entries: [{ entryType: "outcome", content, tags, meta, confidence: 0.7 }],
1296
+ source: "chive"
1297
+ });
1298
+ writeResult(r);
1299
+ return;
1300
+ }
1301
+ if (sub === "recall") {
1302
+ const limit = parseIntFlag("limit", flags.limit) ?? 20;
1303
+ const kind = stringFlag("kind");
1304
+ const fetchLimit = kind ? Math.max(limit * 5, 100) : limit;
1305
+ const body = {
1306
+ domain: stringFlag("domain") || "code",
1307
+ query: stringFlag("task") || null,
1308
+ entryType: stringFlag("entryType") || "outcome",
1309
+ limit: fetchLimit
1310
+ };
1311
+ const r = await apiCall("POST", "/api/cortex/query", body);
1312
+ if (kind && r && Array.isArray(r.entries)) {
1313
+ r.entries = r.entries.filter((e) => e.meta?.taskKind === kind);
1314
+ r.entries = r.entries.slice(0, limit);
1315
+ r.count = r.entries.length;
1316
+ }
1317
+ writeResult(r);
1318
+ return;
1319
+ }
1320
+ dieUsage(`unknown memory subcommand: ${sub || ""}`);
1321
+ }
1322
+ async function handleArch() {
1323
+ if (sub === "decide") {
1324
+ const mission = requiredStringFlag("mission", "arch decide");
1325
+ const title = requiredStringFlag("title", "arch decide");
1326
+ const because = requiredStringFlag("because", "arch decide");
1327
+ const packet = readPacketIfSet();
1328
+ const data = {
1329
+ kind: "adr",
1330
+ title,
1331
+ because,
1332
+ files: stringListFlag("files"),
1333
+ packetId: packet ? packet.packetId : null,
1334
+ graphRefs: packet ? packet.graphRefs || [] : [],
1335
+ decidedAt: (/* @__PURE__ */ new Date()).toISOString(),
1336
+ status: "accepted"
1337
+ };
1338
+ const r = await createRecord({
1339
+ recordType: "CodeArchitectureDecision",
1340
+ missionId: mission,
1341
+ data
1342
+ });
1343
+ writeResult(r);
1344
+ return;
1345
+ }
1346
+ if (sub === "list") {
1347
+ const mission = requiredStringFlag("mission", "arch list");
1348
+ const r = await listRecords({
1349
+ recordType: "CodeArchitectureDecision",
1350
+ missionId: mission
1351
+ });
1352
+ writeResult(r);
1353
+ return;
1354
+ }
1355
+ dieUsage(`unknown arch subcommand: ${sub || ""}`);
1356
+ }
1357
+ async function handleTodo() {
1358
+ if (sub === "add") {
1359
+ const title = pos[2];
1360
+ if (!title) dieUsage('title is required: `chive todo add "<title>"`');
1361
+ const mission = requiredStringFlag("mission", "todo add");
1362
+ const data = {
1363
+ kind: "todo",
1364
+ title,
1365
+ file: stringFlag("file") || null,
1366
+ priority: stringFlag("priority") || "med",
1367
+ status: "open",
1368
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
1369
+ };
1370
+ const r = await createRecord({
1371
+ recordType: "CodeTodo",
1372
+ missionId: mission,
1373
+ data
1374
+ });
1375
+ writeResult(r);
1376
+ return;
1377
+ }
1378
+ if (sub === "list") {
1379
+ const mission = requiredStringFlag("mission", "todo list");
1380
+ const r = await listRecords({
1381
+ recordType: "CodeTodo",
1382
+ missionId: mission
1383
+ });
1384
+ const status = stringFlag("status");
1385
+ if (status && r && Array.isArray(r.records)) {
1386
+ r.records = r.records.filter((rec) => rec.data?.status === status);
1387
+ }
1388
+ writeResult(r);
1389
+ return;
1390
+ }
1391
+ if (sub === "done") {
1392
+ const todoId = pos[2];
1393
+ if (!todoId) dieUsage("todoId is required: `chive todo done <todoId>`");
1394
+ const mission = requiredStringFlag("mission", "todo done");
1395
+ const r = await patchRecord(todoId, {
1396
+ missionId: mission,
1397
+ data: { status: "done", closedAt: (/* @__PURE__ */ new Date()).toISOString() }
1398
+ });
1399
+ writeResult(r);
1400
+ return;
1401
+ }
1402
+ dieUsage(`unknown todo subcommand: ${sub || ""}`);
1403
+ }
1404
+ async function handleKnowledge() {
1405
+ if (sub === "mission" && pos[2] === "create") {
1406
+ const intent = stringFlag("intent") || stringFlag("title");
1407
+ if (!intent) dieUsage("--intent (or --title) is required for `knowledge mission create`");
1408
+ const r = await apiCall("POST", `/api/mission-templates/${encodeURIComponent(KNOWLEDGE_TEMPLATE_ID)}/instantiate`, {
1409
+ userIntent: intent,
1410
+ instantiationConfig: {
1411
+ title: stringFlag("title") || intent
1412
+ }
1413
+ });
1414
+ writeResult(r);
1415
+ return;
1416
+ }
1417
+ if (sub === "mission" && pos[2] === "list") {
1418
+ const r = await apiCall("GET", "/api/missions", void 0);
1419
+ if (r && Array.isArray(r.missions)) {
1420
+ r.missions = r.missions.filter(
1421
+ (m) => (m.templateId || m.template_id) === KNOWLEDGE_TEMPLATE_ID || includesString(m.tags, "knowledge-base")
1422
+ );
1423
+ }
1424
+ writeResult(r);
1425
+ return;
1426
+ }
1427
+ if (sub === "note" && pos[2] === "add") {
1428
+ const mission = requiredStringFlag("mission", "knowledge note add");
1429
+ const topic = requiredStringFlag("topic", "knowledge note add");
1430
+ if (!isKnowledgeTopic(topic)) {
1431
+ dieUsage(`unknown topic "${topic}". Must be one of: ${KNOWLEDGE_TOPICS.join(", ")}`);
1432
+ }
1433
+ const title = requiredStringFlag("title", "knowledge note add");
1434
+ const recordType = KNOWLEDGE_RECORD_TYPES[topic];
1435
+ const body = readBodyIfSet();
1436
+ const data = {
1437
+ topic,
1438
+ title,
1439
+ body: body || "",
1440
+ tags: stringListFlag("tags"),
1441
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
1442
+ };
1443
+ const r = await createRecord({
1444
+ recordType,
1445
+ missionId: mission,
1446
+ data
1447
+ });
1448
+ writeResult(r);
1449
+ return;
1450
+ }
1451
+ if (sub === "note" && pos[2] === "list") {
1452
+ const mission = requiredStringFlag("mission", "knowledge note list");
1453
+ const topic = stringFlag("topic");
1454
+ let topics = KNOWLEDGE_TOPICS;
1455
+ if (topic) {
1456
+ if (!isKnowledgeTopic(topic)) {
1457
+ dieUsage(`unknown topic "${topic}". Must be one of: ${KNOWLEDGE_TOPICS.join(", ")}`);
1458
+ }
1459
+ topics = [topic];
1460
+ }
1461
+ const combined = { ok: true, records: [] };
1462
+ for (const t of topics) {
1463
+ const recordType = KNOWLEDGE_RECORD_TYPES[t];
1464
+ const r = await listRecords({ recordType, missionId: mission });
1465
+ if (r && Array.isArray(r.records)) combined.records?.push(...r.records);
1466
+ }
1467
+ combined.count = combined.records?.length ?? 0;
1468
+ writeResult(combined);
1469
+ return;
1470
+ }
1471
+ dieUsage(`unknown knowledge subcommand: ${sub || ""}${pos[2] ? " " + pos[2] : ""}`);
1472
+ }