codealmanac 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +96 -91
- package/dist/{chunk-D3B2EEHL.js → chunk-B2AGSRXL.js} +2 -2
- package/dist/{chunk-3C5SY5SE.js → chunk-KQUVMF27.js} +5 -2
- package/dist/chunk-KQUVMF27.js.map +1 -0
- package/dist/{cli-CMGYLJSN.js → cli-MZEXRV6E.js} +189 -14
- package/dist/cli-MZEXRV6E.js.map +1 -0
- package/dist/codealmanac.js +1 -1
- package/dist/{doctor-BTH7GCFV.js → doctor-3BYSF3JD.js} +2 -2
- package/dist/{register-commands-7SKQLQW4.js → register-commands-DPH4ZWEE.js} +294 -31
- package/dist/register-commands-DPH4ZWEE.js.map +1 -0
- package/dist/{wiki-IPSRRGOT.js → wiki-IGNRNLUZ.js} +2 -2
- package/package.json +3 -2
- package/dist/chunk-3C5SY5SE.js.map +0 -1
- package/dist/cli-CMGYLJSN.js.map +0 -1
- package/dist/register-commands-7SKQLQW4.js.map +0 -1
- /package/dist/{chunk-D3B2EEHL.js.map → chunk-B2AGSRXL.js.map} +0 -0
- /package/dist/{doctor-BTH7GCFV.js.map → doctor-3BYSF3JD.js.map} +0 -0
- /package/dist/{wiki-IPSRRGOT.js.map → wiki-IGNRNLUZ.js.map} +0 -0
|
@@ -33,10 +33,10 @@ import {
|
|
|
33
33
|
titleCase,
|
|
34
34
|
toKebabCase,
|
|
35
35
|
writeTopicsFile
|
|
36
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-KQUVMF27.js";
|
|
37
37
|
import {
|
|
38
38
|
runDoctor
|
|
39
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-B2AGSRXL.js";
|
|
40
40
|
import "./chunk-V3QOQSXI.js";
|
|
41
41
|
import "./chunk-4CODZRHH.js";
|
|
42
42
|
import {
|
|
@@ -1905,6 +1905,7 @@ async function loadPrompt(name) {
|
|
|
1905
1905
|
// src/agent/sdk.ts
|
|
1906
1906
|
import { spawn } from "child_process";
|
|
1907
1907
|
import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
1908
|
+
var DEFAULT_AGENT_MODEL = "claude-sonnet-4-6";
|
|
1908
1909
|
async function runAgent(opts) {
|
|
1909
1910
|
const provider = opts.provider ?? "claude";
|
|
1910
1911
|
if (provider === "codex") {
|
|
@@ -1924,7 +1925,7 @@ async function runClaudeAgent(opts) {
|
|
|
1924
1925
|
allowedTools: opts.allowedTools,
|
|
1925
1926
|
agents: opts.agents ?? {},
|
|
1926
1927
|
cwd: opts.cwd,
|
|
1927
|
-
model: opts.model ??
|
|
1928
|
+
model: opts.model ?? DEFAULT_AGENT_MODEL,
|
|
1928
1929
|
maxTurns: opts.maxTurns ?? 100,
|
|
1929
1930
|
...claudeExecutable !== void 0 ? { pathToClaudeCodeExecutable: claudeExecutable } : {},
|
|
1930
1931
|
env: {
|
|
@@ -2558,12 +2559,219 @@ function isRecord(value) {
|
|
|
2558
2559
|
import { createHash } from "crypto";
|
|
2559
2560
|
import {
|
|
2560
2561
|
createWriteStream as createWriteStream2,
|
|
2561
|
-
existsSync as
|
|
2562
|
+
existsSync as existsSync7,
|
|
2562
2563
|
statSync
|
|
2563
2564
|
} from "fs";
|
|
2564
|
-
import { mkdir as
|
|
2565
|
+
import { mkdir as mkdir4, readFile as readFile7, readdir as readdir3, stat } from "fs/promises";
|
|
2565
2566
|
import { homedir } from "os";
|
|
2566
|
-
import { basename as basename3, join as
|
|
2567
|
+
import { basename as basename3, join as join8, relative as relative3 } from "path";
|
|
2568
|
+
|
|
2569
|
+
// src/commands/captureStatus.ts
|
|
2570
|
+
import { existsSync as existsSync6 } from "fs";
|
|
2571
|
+
import { mkdir as mkdir3, readFile as readFile6, readdir as readdir2, rename as rename2, writeFile as writeFile3 } from "fs/promises";
|
|
2572
|
+
import { dirname, join as join7, relative as relative2 } from "path";
|
|
2573
|
+
function captureStatePath(dir, stem) {
|
|
2574
|
+
return join7(dir, `.capture-${stem}.state.json`);
|
|
2575
|
+
}
|
|
2576
|
+
async function writeCaptureRunRecord(path2, record) {
|
|
2577
|
+
await mkdir3(dirname(path2), { recursive: true });
|
|
2578
|
+
const tmp = `${path2}.tmp-${process.pid}`;
|
|
2579
|
+
await writeFile3(tmp, `${JSON.stringify(record, null, 2)}
|
|
2580
|
+
`, "utf8");
|
|
2581
|
+
await rename2(tmp, path2);
|
|
2582
|
+
}
|
|
2583
|
+
function buildStartedCaptureRecord(args) {
|
|
2584
|
+
return {
|
|
2585
|
+
version: 1,
|
|
2586
|
+
kind: "capture",
|
|
2587
|
+
status: "running",
|
|
2588
|
+
sessionId: args.sessionId ?? args.stem,
|
|
2589
|
+
repoRoot: args.repoRoot,
|
|
2590
|
+
pid: process.pid,
|
|
2591
|
+
model: args.model ?? DEFAULT_AGENT_MODEL,
|
|
2592
|
+
transcriptPath: args.transcriptPath,
|
|
2593
|
+
startedAt: args.startedAt.toISOString(),
|
|
2594
|
+
logPath: join7(args.almanacDir, `.capture-${args.stem}.log`),
|
|
2595
|
+
jsonlPath: join7(args.almanacDir, `.capture-${args.stem}.jsonl`)
|
|
2596
|
+
};
|
|
2597
|
+
}
|
|
2598
|
+
function finishCaptureRecord(args) {
|
|
2599
|
+
const started = Date.parse(args.record.startedAt);
|
|
2600
|
+
const finished = args.finishedAt.getTime();
|
|
2601
|
+
return {
|
|
2602
|
+
...args.record,
|
|
2603
|
+
status: args.status,
|
|
2604
|
+
finishedAt: args.finishedAt.toISOString(),
|
|
2605
|
+
durationMs: Number.isFinite(started) ? Math.max(0, finished - started) : void 0,
|
|
2606
|
+
summary: args.summary,
|
|
2607
|
+
error: args.error
|
|
2608
|
+
};
|
|
2609
|
+
}
|
|
2610
|
+
async function runCaptureStatus(options) {
|
|
2611
|
+
const repoRoot = findNearestAlmanacDir(options.cwd);
|
|
2612
|
+
if (repoRoot === null) {
|
|
2613
|
+
return {
|
|
2614
|
+
stdout: "",
|
|
2615
|
+
stderr: "almanac: no .almanac/ found in this directory or any parent. Run 'almanac bootstrap' first.\n",
|
|
2616
|
+
exitCode: 1
|
|
2617
|
+
};
|
|
2618
|
+
}
|
|
2619
|
+
const almanacDir = getRepoAlmanacDir(repoRoot);
|
|
2620
|
+
const records = await readCaptureRecords(almanacDir);
|
|
2621
|
+
const now = options.now?.() ?? /* @__PURE__ */ new Date();
|
|
2622
|
+
const isPidAlive = options.isPidAlive ?? defaultIsPidAlive;
|
|
2623
|
+
const views = records.map((record) => toView(record, repoRoot, now, isPidAlive)).sort((a, b) => b.sortTime - a.sortTime);
|
|
2624
|
+
if (options.json === true) {
|
|
2625
|
+
return {
|
|
2626
|
+
stdout: `${JSON.stringify(
|
|
2627
|
+
{
|
|
2628
|
+
repo: repoRoot,
|
|
2629
|
+
captures: views.map(({ sortTime: _sortTime, ...v }) => v)
|
|
2630
|
+
},
|
|
2631
|
+
null,
|
|
2632
|
+
2
|
|
2633
|
+
)}
|
|
2634
|
+
`,
|
|
2635
|
+
stderr: "",
|
|
2636
|
+
exitCode: 0
|
|
2637
|
+
};
|
|
2638
|
+
}
|
|
2639
|
+
return {
|
|
2640
|
+
stdout: formatCaptureStatus(views),
|
|
2641
|
+
stderr: "",
|
|
2642
|
+
exitCode: 0
|
|
2643
|
+
};
|
|
2644
|
+
}
|
|
2645
|
+
async function readCaptureRecords(almanacDir) {
|
|
2646
|
+
if (!existsSync6(almanacDir)) return [];
|
|
2647
|
+
const out = [];
|
|
2648
|
+
const dirs = [join7(almanacDir, "logs"), almanacDir];
|
|
2649
|
+
for (const dir of dirs) {
|
|
2650
|
+
let entries;
|
|
2651
|
+
try {
|
|
2652
|
+
entries = await readdir2(dir);
|
|
2653
|
+
} catch {
|
|
2654
|
+
continue;
|
|
2655
|
+
}
|
|
2656
|
+
for (const entry of entries) {
|
|
2657
|
+
if (!entry.startsWith(".capture-") || !entry.endsWith(".state.json")) {
|
|
2658
|
+
continue;
|
|
2659
|
+
}
|
|
2660
|
+
try {
|
|
2661
|
+
const parsed = JSON.parse(await readFile6(join7(dir, entry), "utf8"));
|
|
2662
|
+
if (isCaptureRunRecord(parsed)) out.push(parsed);
|
|
2663
|
+
} catch {
|
|
2664
|
+
continue;
|
|
2665
|
+
}
|
|
2666
|
+
}
|
|
2667
|
+
}
|
|
2668
|
+
return out;
|
|
2669
|
+
}
|
|
2670
|
+
function isCaptureRunRecord(value) {
|
|
2671
|
+
if (value === null || typeof value !== "object") return false;
|
|
2672
|
+
const v = value;
|
|
2673
|
+
return v.version === 1 && v.kind === "capture" && (v.status === "running" || v.status === "done" || v.status === "failed") && typeof v.sessionId === "string" && typeof v.repoRoot === "string" && typeof v.pid === "number" && typeof v.model === "string" && typeof v.transcriptPath === "string" && typeof v.startedAt === "string" && typeof v.logPath === "string" && typeof v.jsonlPath === "string";
|
|
2674
|
+
}
|
|
2675
|
+
function toView(record, repoRoot, now, isPidAlive) {
|
|
2676
|
+
const started = Date.parse(record.startedAt);
|
|
2677
|
+
const finished = record.finishedAt !== void 0 ? Date.parse(record.finishedAt) : void 0;
|
|
2678
|
+
const elapsedMs = record.durationMs ?? (Number.isFinite(started) ? Math.max(0, (finished ?? now.getTime()) - started) : 0);
|
|
2679
|
+
const status = record.status === "running" && !isPidAlive(record.pid) ? "stale" : record.status;
|
|
2680
|
+
return {
|
|
2681
|
+
status,
|
|
2682
|
+
sessionId: record.sessionId,
|
|
2683
|
+
model: record.model,
|
|
2684
|
+
elapsedMs,
|
|
2685
|
+
startedAt: record.startedAt,
|
|
2686
|
+
finishedAt: record.finishedAt,
|
|
2687
|
+
pid: record.pid,
|
|
2688
|
+
logPath: relative2(repoRoot, record.logPath),
|
|
2689
|
+
jsonlPath: relative2(repoRoot, record.jsonlPath),
|
|
2690
|
+
summary: record.summary,
|
|
2691
|
+
error: status === "stale" ? "process ended without a final status" : record.error,
|
|
2692
|
+
sortTime: finished ?? (Number.isFinite(started) ? started : 0)
|
|
2693
|
+
};
|
|
2694
|
+
}
|
|
2695
|
+
function formatCaptureStatus(views) {
|
|
2696
|
+
const lines = ["Capture jobs", ""];
|
|
2697
|
+
if (views.length === 0) {
|
|
2698
|
+
lines.push("No capture jobs found.");
|
|
2699
|
+
return `${lines.join("\n")}
|
|
2700
|
+
`;
|
|
2701
|
+
}
|
|
2702
|
+
const active = views.filter((v) => v.status === "running" || v.status === "stale");
|
|
2703
|
+
const finished = views.filter((v) => v.status === "done" || v.status === "failed");
|
|
2704
|
+
if (active.length === 0) {
|
|
2705
|
+
lines.push("No active captures.", "");
|
|
2706
|
+
} else {
|
|
2707
|
+
for (const view of active) {
|
|
2708
|
+
lines.push(formatRow(view));
|
|
2709
|
+
lines.push(` log: ${view.logPath}`);
|
|
2710
|
+
if (view.error !== void 0) lines.push(` error: ${view.error}`);
|
|
2711
|
+
lines.push("");
|
|
2712
|
+
}
|
|
2713
|
+
}
|
|
2714
|
+
if (finished.length > 0) {
|
|
2715
|
+
lines.push(active.length === 0 ? "Last capture:" : "Last finished:");
|
|
2716
|
+
for (const view of finished.slice(0, 3)) {
|
|
2717
|
+
lines.push(formatRow(view));
|
|
2718
|
+
if (view.status === "failed") {
|
|
2719
|
+
lines.push(` log: ${view.logPath}`);
|
|
2720
|
+
if (view.error !== void 0) lines.push(` error: ${view.error}`);
|
|
2721
|
+
}
|
|
2722
|
+
}
|
|
2723
|
+
}
|
|
2724
|
+
return `${trimTrailingBlank(lines).join("\n")}
|
|
2725
|
+
`;
|
|
2726
|
+
}
|
|
2727
|
+
function formatRow(view) {
|
|
2728
|
+
const status = view.status.padEnd(7, " ");
|
|
2729
|
+
const session = view.sessionId.padEnd(12, " ");
|
|
2730
|
+
const model = view.model.padEnd(17, " ");
|
|
2731
|
+
const elapsed = formatDuration(view.elapsedMs);
|
|
2732
|
+
const summary = formatSummary(view);
|
|
2733
|
+
return `${status} ${session} ${model} ${elapsed}${summary.length > 0 ? ` ${summary}` : ""}`;
|
|
2734
|
+
}
|
|
2735
|
+
function formatSummary(view) {
|
|
2736
|
+
if (view.status === "failed") return "failed; see log";
|
|
2737
|
+
if (view.summary === void 0) return "";
|
|
2738
|
+
const parts = [];
|
|
2739
|
+
if (view.summary.updated > 0) {
|
|
2740
|
+
parts.push(`${view.summary.updated} updated`);
|
|
2741
|
+
}
|
|
2742
|
+
if (view.summary.created > 0) {
|
|
2743
|
+
parts.push(`${view.summary.created} created`);
|
|
2744
|
+
}
|
|
2745
|
+
if (view.summary.archived > 0) {
|
|
2746
|
+
parts.push(`${view.summary.archived} archived`);
|
|
2747
|
+
}
|
|
2748
|
+
return parts.length > 0 ? parts.join(", ") : "0 pages written";
|
|
2749
|
+
}
|
|
2750
|
+
function formatDuration(ms) {
|
|
2751
|
+
const totalSeconds = Math.max(0, Math.floor(ms / 1e3));
|
|
2752
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
2753
|
+
const seconds = totalSeconds % 60;
|
|
2754
|
+
if (minutes < 60) return `${minutes}m${seconds.toString().padStart(2, "0")}s`;
|
|
2755
|
+
const hours = Math.floor(minutes / 60);
|
|
2756
|
+
const restMinutes = minutes % 60;
|
|
2757
|
+
return `${hours}h${restMinutes.toString().padStart(2, "0")}m`;
|
|
2758
|
+
}
|
|
2759
|
+
function trimTrailingBlank(lines) {
|
|
2760
|
+
while (lines.length > 0 && lines[lines.length - 1] === "") {
|
|
2761
|
+
lines.pop();
|
|
2762
|
+
}
|
|
2763
|
+
return lines;
|
|
2764
|
+
}
|
|
2765
|
+
function defaultIsPidAlive(pid) {
|
|
2766
|
+
try {
|
|
2767
|
+
process.kill(pid, 0);
|
|
2768
|
+
return true;
|
|
2769
|
+
} catch {
|
|
2770
|
+
return false;
|
|
2771
|
+
}
|
|
2772
|
+
}
|
|
2773
|
+
|
|
2774
|
+
// src/commands/capture.ts
|
|
2567
2775
|
var WRITER_TOOLS = ["Read", "Write", "Edit", "Glob", "Grep", "Bash", "Agent"];
|
|
2568
2776
|
var REVIEWER_TOOLS = ["Read", "Grep", "Glob", "Bash"];
|
|
2569
2777
|
var REVIEWER_DESCRIPTION = "Reviews proposed wiki changes against the full knowledge base for cohesion, duplication, missing links, notability, and writing conventions.";
|
|
@@ -2601,7 +2809,7 @@ async function runCapture(options) {
|
|
|
2601
2809
|
};
|
|
2602
2810
|
}
|
|
2603
2811
|
const almanacDir = getRepoAlmanacDir(repoRoot);
|
|
2604
|
-
const pagesDir =
|
|
2812
|
+
const pagesDir = join8(almanacDir, "pages");
|
|
2605
2813
|
const transcriptResolution = await resolveTranscript({
|
|
2606
2814
|
repoRoot,
|
|
2607
2815
|
explicit: options.transcriptPath,
|
|
@@ -2627,12 +2835,24 @@ async function runCapture(options) {
|
|
|
2627
2835
|
tools: REVIEWER_TOOLS
|
|
2628
2836
|
}
|
|
2629
2837
|
};
|
|
2630
|
-
const
|
|
2631
|
-
const logStem = options.sessionId !== void 0 && options.sessionId.length > 0 ? options.sessionId : formatTimestamp2(
|
|
2632
|
-
const logsDir =
|
|
2633
|
-
await
|
|
2838
|
+
const startedAt = options.now?.() ?? /* @__PURE__ */ new Date();
|
|
2839
|
+
const logStem = options.sessionId !== void 0 && options.sessionId.length > 0 ? options.sessionId : formatTimestamp2(startedAt);
|
|
2840
|
+
const logsDir = join8(almanacDir, "logs");
|
|
2841
|
+
await mkdir4(logsDir, { recursive: true });
|
|
2634
2842
|
const logName = `.capture-${logStem}.jsonl`;
|
|
2635
|
-
const logPath =
|
|
2843
|
+
const logPath = join8(logsDir, logName);
|
|
2844
|
+
const statePath = captureStatePath(logsDir, logStem);
|
|
2845
|
+
const stateRecord = buildStartedCaptureRecord({
|
|
2846
|
+
repoRoot,
|
|
2847
|
+
almanacDir: logsDir,
|
|
2848
|
+
stem: logStem,
|
|
2849
|
+
sessionId: options.sessionId,
|
|
2850
|
+
transcriptPath,
|
|
2851
|
+
model: options.model,
|
|
2852
|
+
startedAt
|
|
2853
|
+
});
|
|
2854
|
+
await writeCaptureRunRecord(statePath, stateRecord).catch(() => {
|
|
2855
|
+
});
|
|
2636
2856
|
const logStream = createWriteStream2(logPath, { flags: "w" });
|
|
2637
2857
|
const out = process.stdout;
|
|
2638
2858
|
const formatter = new StreamingFormatter({
|
|
@@ -2674,16 +2894,43 @@ Working directory: ${repoRoot}.`;
|
|
|
2674
2894
|
}
|
|
2675
2895
|
const snapshotAfter = await snapshotPages(pagesDir);
|
|
2676
2896
|
const delta = diffSnapshots(snapshotBefore, snapshotAfter);
|
|
2897
|
+
const finishedAt = options.now?.() ?? /* @__PURE__ */ new Date();
|
|
2898
|
+
const captureSummary = {
|
|
2899
|
+
...delta,
|
|
2900
|
+
cost: result.cost,
|
|
2901
|
+
turns: result.turns
|
|
2902
|
+
};
|
|
2677
2903
|
if (!result.success) {
|
|
2904
|
+
await writeCaptureRunRecord(
|
|
2905
|
+
statePath,
|
|
2906
|
+
finishCaptureRecord({
|
|
2907
|
+
record: stateRecord,
|
|
2908
|
+
status: "failed",
|
|
2909
|
+
finishedAt,
|
|
2910
|
+
summary: captureSummary,
|
|
2911
|
+
error: result.error ?? "unknown error"
|
|
2912
|
+
})
|
|
2913
|
+
).catch(() => {
|
|
2914
|
+
});
|
|
2678
2915
|
return {
|
|
2679
2916
|
stdout: "",
|
|
2680
2917
|
stderr: `almanac: capture failed: ${result.error ?? "unknown error"}
|
|
2681
|
-
(transcript: ${
|
|
2918
|
+
(transcript: ${relative3(repoRoot, logPath)})
|
|
2682
2919
|
`,
|
|
2683
2920
|
exitCode: 1
|
|
2684
2921
|
};
|
|
2685
2922
|
}
|
|
2686
|
-
|
|
2923
|
+
await writeCaptureRunRecord(
|
|
2924
|
+
statePath,
|
|
2925
|
+
finishCaptureRecord({
|
|
2926
|
+
record: stateRecord,
|
|
2927
|
+
status: "done",
|
|
2928
|
+
finishedAt,
|
|
2929
|
+
summary: captureSummary
|
|
2930
|
+
})
|
|
2931
|
+
).catch(() => {
|
|
2932
|
+
});
|
|
2933
|
+
const summary = formatSummary2(result, delta, logPath, repoRoot);
|
|
2687
2934
|
return {
|
|
2688
2935
|
stdout: `${summary}
|
|
2689
2936
|
`,
|
|
@@ -2706,7 +2953,7 @@ async function resolveAgentSelection2(args) {
|
|
|
2706
2953
|
}
|
|
2707
2954
|
async function resolveTranscript(args) {
|
|
2708
2955
|
if (args.explicit !== void 0 && args.explicit.length > 0) {
|
|
2709
|
-
if (!
|
|
2956
|
+
if (!existsSync7(args.explicit)) {
|
|
2710
2957
|
return {
|
|
2711
2958
|
ok: false,
|
|
2712
2959
|
error: `transcript not found: ${args.explicit}`
|
|
@@ -2714,8 +2961,8 @@ async function resolveTranscript(args) {
|
|
|
2714
2961
|
}
|
|
2715
2962
|
return { ok: true, path: args.explicit };
|
|
2716
2963
|
}
|
|
2717
|
-
const projectsDir = args.claudeProjectsDir ??
|
|
2718
|
-
if (!
|
|
2964
|
+
const projectsDir = args.claudeProjectsDir ?? join8(homedir(), ".claude", "projects");
|
|
2965
|
+
if (!existsSync7(projectsDir)) {
|
|
2719
2966
|
return {
|
|
2720
2967
|
ok: false,
|
|
2721
2968
|
error: `could not auto-resolve transcript; ${projectsDir} does not exist. Pass --session <id> or <transcript-path>.`
|
|
@@ -2747,21 +2994,21 @@ async function collectTranscripts(projectsDir) {
|
|
|
2747
2994
|
const out = [];
|
|
2748
2995
|
let topLevel;
|
|
2749
2996
|
try {
|
|
2750
|
-
topLevel = await
|
|
2997
|
+
topLevel = await readdir3(projectsDir);
|
|
2751
2998
|
} catch {
|
|
2752
2999
|
return out;
|
|
2753
3000
|
}
|
|
2754
3001
|
for (const name of topLevel) {
|
|
2755
|
-
const projectDir =
|
|
3002
|
+
const projectDir = join8(projectsDir, name);
|
|
2756
3003
|
let entries;
|
|
2757
3004
|
try {
|
|
2758
|
-
entries = await
|
|
3005
|
+
entries = await readdir3(projectDir);
|
|
2759
3006
|
} catch {
|
|
2760
3007
|
continue;
|
|
2761
3008
|
}
|
|
2762
3009
|
for (const entry of entries) {
|
|
2763
3010
|
if (!entry.endsWith(".jsonl")) continue;
|
|
2764
|
-
const full =
|
|
3011
|
+
const full = join8(projectDir, entry);
|
|
2765
3012
|
try {
|
|
2766
3013
|
const st = await stat(full);
|
|
2767
3014
|
if (st.isFile()) {
|
|
@@ -2776,7 +3023,7 @@ async function collectTranscripts(projectsDir) {
|
|
|
2776
3023
|
async function filterTranscriptsByCwd(transcripts, repoRoot) {
|
|
2777
3024
|
const dirHash = `-${repoRoot.replace(/^\/+/, "").replace(/\//g, "-")}`;
|
|
2778
3025
|
const byDirName = transcripts.filter((t) => {
|
|
2779
|
-
const parent = basename3(
|
|
3026
|
+
const parent = basename3(join8(t.path, ".."));
|
|
2780
3027
|
return parent === dirHash || parent.endsWith(dirHash);
|
|
2781
3028
|
});
|
|
2782
3029
|
if (byDirName.length > 0) return byDirName;
|
|
@@ -2793,26 +3040,26 @@ async function filterTranscriptsByCwd(transcripts, repoRoot) {
|
|
|
2793
3040
|
return hits;
|
|
2794
3041
|
}
|
|
2795
3042
|
async function readHead(path2, bytes) {
|
|
2796
|
-
const content = await
|
|
3043
|
+
const content = await readFile7(path2, "utf8");
|
|
2797
3044
|
return content.length > bytes ? content.slice(0, bytes) : content;
|
|
2798
3045
|
}
|
|
2799
3046
|
async function snapshotPages(pagesDir) {
|
|
2800
3047
|
const out = /* @__PURE__ */ new Map();
|
|
2801
|
-
if (!
|
|
3048
|
+
if (!existsSync7(pagesDir)) return out;
|
|
2802
3049
|
let entries;
|
|
2803
3050
|
try {
|
|
2804
|
-
entries = await
|
|
3051
|
+
entries = await readdir3(pagesDir);
|
|
2805
3052
|
} catch {
|
|
2806
3053
|
return out;
|
|
2807
3054
|
}
|
|
2808
3055
|
for (const entry of entries) {
|
|
2809
3056
|
if (!entry.endsWith(".md")) continue;
|
|
2810
3057
|
const slug = entry.slice(0, -3);
|
|
2811
|
-
const full =
|
|
3058
|
+
const full = join8(pagesDir, entry);
|
|
2812
3059
|
try {
|
|
2813
3060
|
const st = statSync(full);
|
|
2814
3061
|
if (!st.isFile()) continue;
|
|
2815
|
-
const content = await
|
|
3062
|
+
const content = await readFile7(full, "utf8");
|
|
2816
3063
|
const hash = createHash("sha256").update(content).digest("hex");
|
|
2817
3064
|
const fm = parseFrontmatter(content);
|
|
2818
3065
|
out.set(slug, {
|
|
@@ -2846,8 +3093,8 @@ function diffSnapshots(before, after) {
|
|
|
2846
3093
|
}
|
|
2847
3094
|
return { created, updated, archived };
|
|
2848
3095
|
}
|
|
2849
|
-
function
|
|
2850
|
-
const rel =
|
|
3096
|
+
function formatSummary2(result, delta, logPath, repoRoot) {
|
|
3097
|
+
const rel = relative3(repoRoot, logPath);
|
|
2851
3098
|
const cost = `$${result.cost.toFixed(3)}`;
|
|
2852
3099
|
const { created, updated, archived } = delta;
|
|
2853
3100
|
if (created === 0 && updated === 0 && archived === 0) {
|
|
@@ -2894,7 +3141,7 @@ function registerWikiLifecycleCommands(program) {
|
|
|
2894
3141
|
emit(result);
|
|
2895
3142
|
}
|
|
2896
3143
|
);
|
|
2897
|
-
program.command("capture [transcript]").description("run the writer/reviewer pipeline on a session (usually automatic)").option("--session <id>", "target a specific session by ID").option("--quiet", "suppress per-tool streaming; print only the final summary").option("--agent <agent>", "agent provider: claude, codex, or cursor").option("--model <model>", "override the agent model").action(
|
|
3144
|
+
const capture = program.command("capture [transcript]").alias("c").description("run the writer/reviewer pipeline on a session (usually automatic)").option("--session <id>", "target a specific session by ID").option("--quiet", "suppress per-tool streaming; print only the final summary").option("--agent <agent>", "agent provider: claude, codex, or cursor").option("--model <model>", "override the agent model").action(
|
|
2898
3145
|
async (transcript, opts) => {
|
|
2899
3146
|
await autoRegisterIfNeeded(process.cwd());
|
|
2900
3147
|
const result = await runCapture({
|
|
@@ -2908,6 +3155,22 @@ function registerWikiLifecycleCommands(program) {
|
|
|
2908
3155
|
emit(result);
|
|
2909
3156
|
}
|
|
2910
3157
|
);
|
|
3158
|
+
capture.command("status").description("show running and recent capture jobs").option("--json", "emit structured JSON").action(async (opts) => {
|
|
3159
|
+
await autoRegisterIfNeeded(process.cwd());
|
|
3160
|
+
const result = await runCaptureStatus({
|
|
3161
|
+
cwd: process.cwd(),
|
|
3162
|
+
json: opts.json
|
|
3163
|
+
});
|
|
3164
|
+
emit(result);
|
|
3165
|
+
});
|
|
3166
|
+
program.command("ps").description("show running and recent capture jobs").option("--json", "emit structured JSON").action(async (opts) => {
|
|
3167
|
+
await autoRegisterIfNeeded(process.cwd());
|
|
3168
|
+
const result = await runCaptureStatus({
|
|
3169
|
+
cwd: process.cwd(),
|
|
3170
|
+
json: opts.json
|
|
3171
|
+
});
|
|
3172
|
+
emit(result);
|
|
3173
|
+
});
|
|
2911
3174
|
const hook = program.command("hook").description("manage the SessionEnd auto-capture hook");
|
|
2912
3175
|
hook.command("install").description("add a SessionEnd entry that runs 'almanac capture' on session end").option("--source <source>", "claude, codex, cursor, or all").action(async (opts) => {
|
|
2913
3176
|
const result = await runHookInstall({
|
|
@@ -2950,4 +3213,4 @@ function registerCommands(program) {
|
|
|
2950
3213
|
export {
|
|
2951
3214
|
registerCommands
|
|
2952
3215
|
};
|
|
2953
|
-
//# sourceMappingURL=register-commands-
|
|
3216
|
+
//# sourceMappingURL=register-commands-DPH4ZWEE.js.map
|