@hiveai/cli 0.2.15 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Dashboard-HVELRRC7.js +336 -0
- package/dist/Dashboard-HVELRRC7.js.map +1 -0
- package/dist/index.js +237 -31
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/Dashboard-SRPCHP7Z.js +0 -194
- package/dist/Dashboard-SRPCHP7Z.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
import { Command as
|
|
4
|
+
import { Command as Command29 } from "commander";
|
|
5
5
|
|
|
6
6
|
// src/commands/briefing.ts
|
|
7
7
|
import { existsSync } from "fs";
|
|
@@ -11,8 +11,10 @@ import {
|
|
|
11
11
|
findProjectRoot,
|
|
12
12
|
literalMatchesAllTokens,
|
|
13
13
|
literalMatchesAnyToken,
|
|
14
|
+
loadCodeMap,
|
|
14
15
|
loadMemoriesFromDir,
|
|
15
16
|
memoryMatchesAnchorPaths,
|
|
17
|
+
queryCodeMap,
|
|
16
18
|
resolveHaivePaths,
|
|
17
19
|
tokenizeQuery,
|
|
18
20
|
trackReads
|
|
@@ -52,7 +54,7 @@ var ui = {
|
|
|
52
54
|
function registerBriefing(program2) {
|
|
53
55
|
program2.command("briefing").description(
|
|
54
56
|
"Print project context + relevant memories in one shot \u2014 ideal for agent onboarding"
|
|
55
|
-
).option("--task <text>", "what you are about to do \u2014 filters memories by relevance").option("--files <csv>", "comma-separated file paths being worked on (anchors memories)").option("--max-memories <n>", "cap on memories surfaced", "10").option(
|
|
57
|
+
).option("--task <text>", "what you are about to do \u2014 filters memories by relevance").option("--files <csv>", "comma-separated file paths being worked on (anchors memories)").option("--symbols <csv>", "symbol names to look up in the code-map (e.g. PaymentService,TenantFilter)").option("--max-memories <n>", "cap on memories surfaced", "10").option(
|
|
56
58
|
"--scope <scope>",
|
|
57
59
|
"personal | team | module | all (default: team)",
|
|
58
60
|
"team"
|
|
@@ -89,13 +91,24 @@ function registerBriefing(program2) {
|
|
|
89
91
|
}
|
|
90
92
|
if (existsSync(paths.projectContext)) {
|
|
91
93
|
const ctx = await readFile(paths.projectContext, "utf8");
|
|
92
|
-
|
|
94
|
+
const isTemplate = ctx.includes("TODO \u2014 high-level overview") || ctx.includes("Generated by `haive init`");
|
|
95
|
+
if (isTemplate) {
|
|
96
|
+
ui.warn(
|
|
97
|
+
"project-context.md still contains the default template \u2014 get_briefing will return little value."
|
|
98
|
+
);
|
|
99
|
+
ui.warn(
|
|
100
|
+
"Fix: in your AI client, invoke the MCP prompt bootstrap_project to auto-fill it from your codebase."
|
|
101
|
+
);
|
|
102
|
+
console.log();
|
|
103
|
+
} else {
|
|
104
|
+
console.log(`${ui.bold("=== Project Context ===")}
|
|
93
105
|
`);
|
|
94
|
-
|
|
95
|
-
|
|
106
|
+
console.log(ctx.trim());
|
|
107
|
+
console.log();
|
|
108
|
+
}
|
|
96
109
|
} else {
|
|
97
110
|
ui.warn(
|
|
98
|
-
"No project-context.md found. Run `haive init`
|
|
111
|
+
"No project-context.md found. Run `haive init` then invoke the bootstrap_project MCP prompt."
|
|
99
112
|
);
|
|
100
113
|
}
|
|
101
114
|
const candidates = all.filter(({ memory: mem }) => {
|
|
@@ -152,6 +165,34 @@ function registerBriefing(program2) {
|
|
|
152
165
|
await trackReads(paths, ids).catch(() => {
|
|
153
166
|
});
|
|
154
167
|
}
|
|
168
|
+
const requestedSymbols = (opts.symbols ?? "").split(",").map((s) => s.trim()).filter(Boolean);
|
|
169
|
+
if (requestedSymbols.length > 0) {
|
|
170
|
+
const codeMap = await loadCodeMap(paths);
|
|
171
|
+
if (!codeMap) {
|
|
172
|
+
ui.warn("No code-map found. Run `haive index code` first to enable symbol lookup.");
|
|
173
|
+
} else {
|
|
174
|
+
console.log(`
|
|
175
|
+
${ui.bold("=== Symbol Locations ===")}
|
|
176
|
+
`);
|
|
177
|
+
for (const sym of requestedSymbols) {
|
|
178
|
+
const { files } = queryCodeMap(codeMap, { symbol: sym });
|
|
179
|
+
if (files.length === 0) {
|
|
180
|
+
console.log(`${ui.dim(sym)} (not found in code-map)`);
|
|
181
|
+
} else {
|
|
182
|
+
for (const f of files) {
|
|
183
|
+
const exports = f.entry.exports.filter(
|
|
184
|
+
(e) => e.name.toLowerCase().includes(sym.toLowerCase())
|
|
185
|
+
);
|
|
186
|
+
for (const e of exports) {
|
|
187
|
+
const desc = e.description ? ` \u2014 ${e.description}` : "";
|
|
188
|
+
console.log(`${ui.bold(e.name)} ${ui.dim(f.path + ":" + e.line)} [${e.kind}]${desc}`);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
console.log();
|
|
194
|
+
}
|
|
195
|
+
}
|
|
155
196
|
});
|
|
156
197
|
}
|
|
157
198
|
function parseCsv(value) {
|
|
@@ -172,7 +213,7 @@ function registerTui(program2) {
|
|
|
172
213
|
const root = findProjectRoot2(opts.dir);
|
|
173
214
|
const { render } = await import("ink");
|
|
174
215
|
const { createElement } = await import("react");
|
|
175
|
-
const { Dashboard } = await import("./Dashboard-
|
|
216
|
+
const { Dashboard } = await import("./Dashboard-HVELRRC7.js");
|
|
176
217
|
const { waitUntilExit } = render(createElement(Dashboard, { root }));
|
|
177
218
|
await waitUntilExit();
|
|
178
219
|
});
|
|
@@ -338,12 +379,15 @@ on:
|
|
|
338
379
|
push:
|
|
339
380
|
branches: [main, master]
|
|
340
381
|
pull_request:
|
|
341
|
-
|
|
342
|
-
- '.ai/**'
|
|
382
|
+
branches: [main, master]
|
|
343
383
|
|
|
344
384
|
jobs:
|
|
345
|
-
sync
|
|
385
|
+
# On push to main/master: sync anchors + auto-promote + commit changes
|
|
386
|
+
sync-on-merge:
|
|
387
|
+
if: github.event_name == 'push'
|
|
346
388
|
runs-on: ubuntu-latest
|
|
389
|
+
permissions:
|
|
390
|
+
contents: write
|
|
347
391
|
steps:
|
|
348
392
|
- uses: actions/checkout@v4
|
|
349
393
|
with:
|
|
@@ -353,19 +397,58 @@ jobs:
|
|
|
353
397
|
with:
|
|
354
398
|
node-version: '20'
|
|
355
399
|
|
|
356
|
-
- name:
|
|
357
|
-
run: npm install -g @
|
|
400
|
+
- name: install haive
|
|
401
|
+
run: npm install -g @hiveai/cli
|
|
358
402
|
|
|
359
|
-
- name:
|
|
360
|
-
run: haive sync --
|
|
403
|
+
- name: refresh memory anchors + auto-promote
|
|
404
|
+
run: haive sync --since HEAD~1 || true
|
|
361
405
|
|
|
362
|
-
- name:
|
|
406
|
+
- name: commit updated memories (if any)
|
|
363
407
|
run: |
|
|
364
408
|
git config user.name "github-actions[bot]"
|
|
365
409
|
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
366
410
|
git add .ai/
|
|
367
411
|
git diff --cached --quiet || git commit -m "chore: haive sync [skip ci]"
|
|
368
412
|
git push
|
|
413
|
+
|
|
414
|
+
# On pull request: warn if PR touches files that would invalidate memories
|
|
415
|
+
pr-stale-check:
|
|
416
|
+
if: github.event_name == 'pull_request'
|
|
417
|
+
runs-on: ubuntu-latest
|
|
418
|
+
permissions:
|
|
419
|
+
pull-requests: write
|
|
420
|
+
steps:
|
|
421
|
+
- uses: actions/checkout@v4
|
|
422
|
+
with:
|
|
423
|
+
fetch-depth: 0
|
|
424
|
+
|
|
425
|
+
- uses: actions/setup-node@v4
|
|
426
|
+
with:
|
|
427
|
+
node-version: '20'
|
|
428
|
+
|
|
429
|
+
- name: install haive
|
|
430
|
+
run: npm install -g @hiveai/cli
|
|
431
|
+
|
|
432
|
+
- name: verify memory anchors touched by this PR
|
|
433
|
+
id: verify
|
|
434
|
+
run: |
|
|
435
|
+
haive memory verify 2>&1 | tee /tmp/haive-verify.txt || true
|
|
436
|
+
STALE=$(grep -c 'stale' /tmp/haive-verify.txt || echo 0)
|
|
437
|
+
echo "stale_count=$STALE" >> "$GITHUB_OUTPUT"
|
|
438
|
+
|
|
439
|
+
- name: comment on PR if stale memories detected
|
|
440
|
+
if: steps.verify.outputs.stale_count != '0'
|
|
441
|
+
uses: actions/github-script@v7
|
|
442
|
+
with:
|
|
443
|
+
script: |
|
|
444
|
+
const fs = require('fs');
|
|
445
|
+
const report = fs.readFileSync('/tmp/haive-verify.txt', 'utf8').trim();
|
|
446
|
+
await github.rest.issues.createComment({
|
|
447
|
+
owner: context.repo.owner,
|
|
448
|
+
repo: context.repo.repo,
|
|
449
|
+
issue_number: context.issue.number,
|
|
450
|
+
body: \`### haive \u2014 Stale memories detected\\n\\nSome memories anchored to code modified in this PR may be outdated:\\n\\n\\\`\\\`\\\`\\n\${report}\\n\\\`\\\`\\\`\\n\\nRun \\\`haive memory verify --update\\\` locally to refresh them before merging.\`
|
|
451
|
+
});
|
|
369
452
|
`;
|
|
370
453
|
function registerInit(program2) {
|
|
371
454
|
program2.command("init").description("Initialize a hAIve project (.ai/ structure + bridge files)").option("-d, --dir <dir>", "project root", process.cwd()).option("--no-bridges", "do not generate CLAUDE.md / .cursorrules / copilot-instructions.md").option("--with-ci", "write a GitHub Actions workflow (.github/workflows/haive-sync.yml)").action(async (opts) => {
|
|
@@ -813,6 +896,16 @@ function registerMemoryAdd(memory2) {
|
|
|
813
896
|
const autoTagsEnabled = opts.autoTag !== false;
|
|
814
897
|
const inferredTags = autoTagsEnabled ? inferModulesFromPaths(anchorPaths) : [];
|
|
815
898
|
const mergedTags = Array.from(/* @__PURE__ */ new Set([...userTags, ...inferredTags]));
|
|
899
|
+
if (anchorPaths.length > 0) {
|
|
900
|
+
const missing = anchorPaths.filter((p) => !existsSync7(path7.resolve(root, p)));
|
|
901
|
+
if (missing.length > 0) {
|
|
902
|
+
ui.warn(`Anchor path${missing.length > 1 ? "s" : ""} not found in project:`);
|
|
903
|
+
for (const p of missing) ui.warn(` \u2717 ${p}`);
|
|
904
|
+
ui.warn(
|
|
905
|
+
"Memories anchored to non-existent paths will be immediately marked stale by `haive sync`.\n Verify the paths are relative to the project root and the files/directories exist."
|
|
906
|
+
);
|
|
907
|
+
}
|
|
908
|
+
}
|
|
816
909
|
const title = opts.title ?? opts.slug;
|
|
817
910
|
let body;
|
|
818
911
|
if (opts.bodyFile !== void 0) {
|
|
@@ -2066,17 +2159,124 @@ function registerMemoryImport(memory2) {
|
|
|
2066
2159
|
});
|
|
2067
2160
|
}
|
|
2068
2161
|
|
|
2069
|
-
// src/commands/
|
|
2070
|
-
import { writeFile as writeFile12, mkdir as mkdir6 } from "fs/promises";
|
|
2162
|
+
// src/commands/memory-digest.ts
|
|
2071
2163
|
import { existsSync as existsSync25 } from "fs";
|
|
2164
|
+
import { writeFile as writeFile12 } from "fs/promises";
|
|
2072
2165
|
import path23 from "path";
|
|
2073
2166
|
import "commander";
|
|
2074
2167
|
import {
|
|
2075
|
-
|
|
2168
|
+
deriveConfidence as deriveConfidence4,
|
|
2076
2169
|
findProjectRoot as findProjectRoot27,
|
|
2170
|
+
getUsage as getUsage8,
|
|
2077
2171
|
loadMemoriesFromDir as loadMemoriesFromDir5,
|
|
2172
|
+
loadUsageIndex as loadUsageIndex10,
|
|
2173
|
+
resolveHaivePaths as resolveHaivePaths24
|
|
2174
|
+
} from "@hiveai/core";
|
|
2175
|
+
var CONFIDENCE_EMOJI = {
|
|
2176
|
+
unverified: "\u2B1C",
|
|
2177
|
+
low: "\u{1F7E1}",
|
|
2178
|
+
trusted: "\u{1F7E2}",
|
|
2179
|
+
authoritative: "\u2B50",
|
|
2180
|
+
stale: "\u{1F534}"
|
|
2181
|
+
};
|
|
2182
|
+
function registerMemoryDigest(program2) {
|
|
2183
|
+
program2.command("digest").description(
|
|
2184
|
+
"Generate a Markdown review digest of recently added/updated memories (default: last 7 days)"
|
|
2185
|
+
).option("--days <n>", "look-back window in days", "7").option("--scope <scope>", "personal | team | module | all", "team").option("--out <file>", "write digest to a file instead of stdout").option("-d, --dir <dir>", "project root").action(async (opts) => {
|
|
2186
|
+
const root = findProjectRoot27(opts.dir);
|
|
2187
|
+
const paths = resolveHaivePaths24(root);
|
|
2188
|
+
if (!existsSync25(paths.memoriesDir)) {
|
|
2189
|
+
ui.error("No .ai/memories found. Run `haive init` first.");
|
|
2190
|
+
process.exitCode = 1;
|
|
2191
|
+
return;
|
|
2192
|
+
}
|
|
2193
|
+
const days = Math.max(1, Number(opts.days ?? 7));
|
|
2194
|
+
const scopeFilter = opts.scope ?? "team";
|
|
2195
|
+
const cutoff = new Date(Date.now() - days * 24 * 60 * 60 * 1e3);
|
|
2196
|
+
const all = await loadMemoriesFromDir5(paths.memoriesDir);
|
|
2197
|
+
const usage = await loadUsageIndex10(paths);
|
|
2198
|
+
const recent = all.filter(({ memory: mem }) => {
|
|
2199
|
+
const fm = mem.frontmatter;
|
|
2200
|
+
if (fm.type === "session_recap") return false;
|
|
2201
|
+
if (fm.status === "rejected" || fm.status === "deprecated") return false;
|
|
2202
|
+
if (scopeFilter !== "all" && fm.scope !== scopeFilter) return false;
|
|
2203
|
+
return new Date(fm.created_at) >= cutoff;
|
|
2204
|
+
});
|
|
2205
|
+
const now = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
2206
|
+
const lines = [
|
|
2207
|
+
`# hAIve Memory Digest \u2014 ${now}`,
|
|
2208
|
+
``,
|
|
2209
|
+
`> **Period:** last ${days} day${days > 1 ? "s" : ""} | **Scope:** ${scopeFilter} | **Total:** ${recent.length} memor${recent.length === 1 ? "y" : "ies"}`,
|
|
2210
|
+
``,
|
|
2211
|
+
`---`,
|
|
2212
|
+
``
|
|
2213
|
+
];
|
|
2214
|
+
if (recent.length === 0) {
|
|
2215
|
+
lines.push(`_No new memories in the last ${days} days._`);
|
|
2216
|
+
} else {
|
|
2217
|
+
const byType = /* @__PURE__ */ new Map();
|
|
2218
|
+
for (const m of recent) {
|
|
2219
|
+
const t = m.memory.frontmatter.type;
|
|
2220
|
+
if (!byType.has(t)) byType.set(t, []);
|
|
2221
|
+
byType.get(t).push(m);
|
|
2222
|
+
}
|
|
2223
|
+
for (const [type, mems] of byType) {
|
|
2224
|
+
lines.push(`## ${type.charAt(0).toUpperCase() + type.slice(1)} (${mems.length})`);
|
|
2225
|
+
lines.push(``);
|
|
2226
|
+
for (const { memory: mem } of mems) {
|
|
2227
|
+
const fm = mem.frontmatter;
|
|
2228
|
+
const u = getUsage8(usage, fm.id);
|
|
2229
|
+
const confidence = deriveConfidence4(fm, u);
|
|
2230
|
+
const emoji = CONFIDENCE_EMOJI[confidence] ?? "\u2B1C";
|
|
2231
|
+
const anchor = fm.anchor.paths.length > 0 ? `\`${fm.anchor.paths[0]}\`` + (fm.anchor.paths.length > 1 ? ` +${fm.anchor.paths.length - 1}` : "") : "_no anchor_";
|
|
2232
|
+
lines.push(`### ${emoji} \`${fm.id}\``);
|
|
2233
|
+
lines.push(``);
|
|
2234
|
+
lines.push(`| Field | Value |`);
|
|
2235
|
+
lines.push(`|---|---|`);
|
|
2236
|
+
lines.push(`| **Status** | \`${fm.status}\` |`);
|
|
2237
|
+
lines.push(`| **Confidence** | ${confidence} |`);
|
|
2238
|
+
lines.push(`| **Scope** | ${fm.scope}${fm.module ? `/${fm.module}` : ""} |`);
|
|
2239
|
+
lines.push(`| **Tags** | ${fm.tags.length > 0 ? fm.tags.map((t) => `\`${t}\``).join(", ") : "_none_"} |`);
|
|
2240
|
+
lines.push(`| **Anchor** | ${anchor} |`);
|
|
2241
|
+
lines.push(`| **Reads** | ${u.read_count} |`);
|
|
2242
|
+
lines.push(`| **Created** | ${fm.created_at.slice(0, 10)} |`);
|
|
2243
|
+
lines.push(``);
|
|
2244
|
+
const bodyPreview = mem.body.split("\n").slice(0, 6).join("\n").trim();
|
|
2245
|
+
lines.push(bodyPreview);
|
|
2246
|
+
lines.push(``);
|
|
2247
|
+
lines.push(`**Action:** [ ] approve [ ] reject [ ] keep as-is`);
|
|
2248
|
+
lines.push(``);
|
|
2249
|
+
lines.push(`---`);
|
|
2250
|
+
lines.push(``);
|
|
2251
|
+
}
|
|
2252
|
+
}
|
|
2253
|
+
}
|
|
2254
|
+
lines.push(``);
|
|
2255
|
+
lines.push(
|
|
2256
|
+
`> _To take action: \`haive memory approve <id>\`, \`haive memory reject <id>\`, or open \`haive tui\` for interactive review._`
|
|
2257
|
+
);
|
|
2258
|
+
const digest = lines.join("\n");
|
|
2259
|
+
if (opts.out) {
|
|
2260
|
+
const outPath = path23.resolve(process.cwd(), opts.out);
|
|
2261
|
+
await writeFile12(outPath, digest, "utf8");
|
|
2262
|
+
ui.success(`Digest written to ${opts.out} (${recent.length} memor${recent.length === 1 ? "y" : "ies"})`);
|
|
2263
|
+
} else {
|
|
2264
|
+
console.log(digest);
|
|
2265
|
+
}
|
|
2266
|
+
});
|
|
2267
|
+
}
|
|
2268
|
+
|
|
2269
|
+
// src/commands/session-end.ts
|
|
2270
|
+
import { writeFile as writeFile13, mkdir as mkdir6 } from "fs/promises";
|
|
2271
|
+
import { existsSync as existsSync26 } from "fs";
|
|
2272
|
+
import path24 from "path";
|
|
2273
|
+
import "commander";
|
|
2274
|
+
import {
|
|
2275
|
+
buildFrontmatter as buildFrontmatter3,
|
|
2276
|
+
findProjectRoot as findProjectRoot28,
|
|
2277
|
+
loadMemoriesFromDir as loadMemoriesFromDir6,
|
|
2078
2278
|
memoryFilePath as memoryFilePath4,
|
|
2079
|
-
resolveHaivePaths as
|
|
2279
|
+
resolveHaivePaths as resolveHaivePaths25,
|
|
2080
2280
|
serializeMemory as serializeMemory10
|
|
2081
2281
|
} from "@hiveai/core";
|
|
2082
2282
|
function buildRecapBody(opts) {
|
|
@@ -2109,9 +2309,9 @@ function recapTopic(scope, module) {
|
|
|
2109
2309
|
}
|
|
2110
2310
|
function registerSessionEnd(session2) {
|
|
2111
2311
|
session2.command("end").description("Save a structured end-of-session recap (goal / accomplished / discoveries / next steps)").requiredOption("--goal <text>", "What you were trying to accomplish (1\u20132 sentences)").requiredOption("--accomplished <text>", "What was actually done (bullet list recommended)").option("--discoveries <text>", "Bugs, surprises, or inconsistencies found during this session").option("--files <csv>", "Key files touched, comma-separated").option("--next <text>", "What should happen next (for the next session or a teammate)").option("--scope <scope>", "personal | team | module", "personal").option("--module <name>", "module name (required when scope=module)").option("-d, --dir <dir>", "project root").action(async (opts) => {
|
|
2112
|
-
const root =
|
|
2113
|
-
const paths =
|
|
2114
|
-
if (!
|
|
2312
|
+
const root = findProjectRoot28(opts.dir);
|
|
2313
|
+
const paths = resolveHaivePaths25(root);
|
|
2314
|
+
if (!existsSync26(paths.haiveDir)) {
|
|
2115
2315
|
ui.error(`No .ai/ found at ${root}. Run \`haive init\` first.`);
|
|
2116
2316
|
process.exitCode = 1;
|
|
2117
2317
|
return;
|
|
@@ -2120,8 +2320,13 @@ function registerSessionEnd(session2) {
|
|
|
2120
2320
|
const body = buildRecapBody(opts);
|
|
2121
2321
|
const topic = recapTopic(scope, opts.module);
|
|
2122
2322
|
const filesTouched = parseCsv5(opts.files);
|
|
2123
|
-
|
|
2124
|
-
|
|
2323
|
+
const missingPaths = filesTouched.filter((p) => !existsSync26(path24.resolve(root, p)));
|
|
2324
|
+
if (missingPaths.length > 0) {
|
|
2325
|
+
ui.warn(`Anchor path${missingPaths.length > 1 ? "s" : ""} not found in project (will be stale):`);
|
|
2326
|
+
for (const p of missingPaths) ui.warn(` \u2717 ${p}`);
|
|
2327
|
+
}
|
|
2328
|
+
if (existsSync26(paths.memoriesDir)) {
|
|
2329
|
+
const existing = await loadMemoriesFromDir6(paths.memoriesDir);
|
|
2125
2330
|
const topicMatch = existing.find(
|
|
2126
2331
|
({ memory: memory2 }) => memory2.frontmatter.topic === topic && memory2.frontmatter.scope === scope && (!opts.module || memory2.frontmatter.module === opts.module)
|
|
2127
2332
|
);
|
|
@@ -2136,9 +2341,9 @@ function registerSessionEnd(session2) {
|
|
|
2136
2341
|
paths: filesTouched.length ? filesTouched : fm.anchor.paths
|
|
2137
2342
|
}
|
|
2138
2343
|
};
|
|
2139
|
-
await
|
|
2344
|
+
await writeFile13(topicMatch.filePath, serializeMemory10({ frontmatter: newFrontmatter, body }), "utf8");
|
|
2140
2345
|
ui.success(`Session recap updated (revision #${revisionCount})`);
|
|
2141
|
-
ui.info(`id=${fm.id} file=${
|
|
2346
|
+
ui.info(`id=${fm.id} file=${path24.relative(root, topicMatch.filePath)}`);
|
|
2142
2347
|
return;
|
|
2143
2348
|
}
|
|
2144
2349
|
}
|
|
@@ -2153,10 +2358,10 @@ function registerSessionEnd(session2) {
|
|
|
2153
2358
|
status: "validated"
|
|
2154
2359
|
});
|
|
2155
2360
|
const file = memoryFilePath4(paths, frontmatter.scope, frontmatter.id, frontmatter.module);
|
|
2156
|
-
await mkdir6(
|
|
2157
|
-
await
|
|
2361
|
+
await mkdir6(path24.dirname(file), { recursive: true });
|
|
2362
|
+
await writeFile13(file, serializeMemory10({ frontmatter, body }), "utf8");
|
|
2158
2363
|
ui.success(`Session recap created`);
|
|
2159
|
-
ui.info(`id=${frontmatter.id} scope=${scope} file=${
|
|
2364
|
+
ui.info(`id=${frontmatter.id} scope=${scope} file=${path24.relative(root, file)}`);
|
|
2160
2365
|
ui.info("Next session: call `get_briefing` \u2014 the recap will be surfaced automatically.");
|
|
2161
2366
|
});
|
|
2162
2367
|
}
|
|
@@ -2166,8 +2371,8 @@ function parseCsv5(value) {
|
|
|
2166
2371
|
}
|
|
2167
2372
|
|
|
2168
2373
|
// src/index.ts
|
|
2169
|
-
var program = new
|
|
2170
|
-
program.name("haive").description("hAIve \u2014 team-first persistent memory layer for AI coding agents").version("0.
|
|
2374
|
+
var program = new Command29();
|
|
2375
|
+
program.name("haive").description("hAIve \u2014 team-first persistent memory layer for AI coding agents").version("0.3.0");
|
|
2171
2376
|
registerInit(program);
|
|
2172
2377
|
registerMcp(program);
|
|
2173
2378
|
registerBriefing(program);
|
|
@@ -2195,6 +2400,7 @@ registerMemoryUpdate(memory);
|
|
|
2195
2400
|
registerMemoryHot(memory);
|
|
2196
2401
|
registerMemoryTried(memory);
|
|
2197
2402
|
registerMemoryImport(memory);
|
|
2403
|
+
registerMemoryDigest(memory);
|
|
2198
2404
|
var session = program.command("session").description("Manage session lifecycle");
|
|
2199
2405
|
registerSessionEnd(session);
|
|
2200
2406
|
program.parseAsync(process.argv).catch((err) => {
|