codemem 0.37.1 → 0.38.0-alpha.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.
package/README.md CHANGED
@@ -24,6 +24,7 @@ codemem --help
24
24
  codemem setup --opencode-only
25
25
  codemem stats
26
26
  codemem search "query"
27
+ codemem distill --limit 10
27
28
  codemem serve start
28
29
  codemem mcp
29
30
  ```
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { DEDUP_KEY_BACKFILL_JOB, DEFAULT_COORDINATOR_DB_PATH, DedupKeyBackfillRunner, MUTATING_TOOL_NAMES, MemoryStore, ObserverClient, REF_BACKFILL_JOB, RawEventSweeper, RefBackfillRunner, SCOPE_BACKFILL_JOB, SESSION_CONTEXT_BACKFILL_JOB, SUMMARY_DEDUP_BACKFILL_JOB, ScopeBackfillRunner, SessionContextBackfillRunner, SummaryDedupBackfillRunner, SyncRetentionRunner, VERSION, VectorModelMigrationRunner, aiBackfillStructuredContent, applyBootstrapSnapshot, backfillMemoryDedupKeys, backfillNarrativeFromBody, backfillTagsText, backfillVectors, buildAuthHeaders, buildBaseUrl, buildRawEventEnvelopeFromCodexHook, buildRawEventEnvelopeFromHook, compareMemoryRoleReports, connect, coordinatorCreateGroupAction, coordinatorCreateInviteAction, coordinatorCreateScopeAction, coordinatorDisableDeviceAction, coordinatorEnrollDeviceAction, coordinatorGrantScopeMembershipAction, coordinatorImportInviteAction, coordinatorListBootstrapGrantsAction, coordinatorListDevicesAction, coordinatorListGroupsAction, coordinatorListJoinRequestsAction, coordinatorListScopeMembershipsAction, coordinatorListScopesAction, coordinatorRemoveDeviceAction, coordinatorRenameDeviceAction, coordinatorReviewJoinRequestAction, coordinatorRevokeBootstrapGrantAction, coordinatorRevokeScopeMembershipAction, coordinatorUpdateScopeAction, createBetterSqliteCoordinatorApp, deactivateLowSignalMemories, deactivateLowSignalObservations, dedupNearDuplicateMemories, ensureDeviceIdentity, ensureSchemaBootstrapped, exportMemories, extractApplyPatchPaths, fetchAllSnapshotPages, fingerprintPublicKey, flushRawEvents, formatHostPort, getExtractionBenchmarkProfile, getInjectionEvalScenarioPack, getInjectionEvalScenarioPrompts, getMaintenanceJob, getMemoryRoleReport, getRawEventRelinkPlan, getRawEventRelinkReport, getRawEventStatus, getSemanticIndexDiagnostics, getSessionExtractionEval, getSessionExtractionEvalScenario, getWorkspaceCodememConfigPath, hasPendingDedupKeyBackfill, hasPendingRefBackfill, hasPendingScopeBackfill, hasPendingSessionContextBackfill, hasPendingSummaryDedupBackfill, hasUnsyncedSharedMemoryChanges, importMemories, initDatabase, isEmbeddingDisabled, listMaintenanceJobs, listPerPeerScopeSyncState, listRetentionScopeIds, loadObserverConfig, loadPublicKey, loadSqliteVec, mdnsEnabled, planReplicationOpsAgePrune, pruneReplicationOpsUntilCaughtUp, rawEventsGate, readCodememConfigFile, readCodememConfigFileAtPath, readCoordinatorSyncConfig, readImportPayload, replayBatchExtraction, replayBatchExtractionWithTierRouting, requestJson, resolveCodememConfigPath, resolveDbPath, resolveHookProject, resolveProject, retryRawEventFailures, runSyncDaemon, runSyncPass, scanSecretsRetroactive, schema, setPeerProjectFilter, stripJsonComments, stripPrivateObj, stripTrailingCommas, syncPassPreflight, updatePeerAddresses, vacuumDatabase, writeCodememConfigFile } from "@codemem/core";
2
+ import { DEDUP_KEY_BACKFILL_JOB, DEFAULT_COORDINATOR_DB_PATH, DedupKeyBackfillRunner, MUTATING_TOOL_NAMES, MemoryStore, ObserverClient, REF_BACKFILL_JOB, RawEventSweeper, RefBackfillRunner, SCOPE_BACKFILL_JOB, SESSION_CONTEXT_BACKFILL_JOB, SUMMARY_DEDUP_BACKFILL_JOB, ScopeBackfillRunner, SessionContextBackfillRunner, SummaryDedupBackfillRunner, SyncRetentionRunner, VERSION, VectorModelMigrationRunner, aiBackfillStructuredContent, applyBootstrapSnapshot, applyDistillRule, backfillMemoryDedupKeys, backfillNarrativeFromBody, backfillTagsText, backfillVectors, buildAuthHeaders, buildBaseUrl, buildDistillReport, buildRawEventEnvelopeFromCodexHook, buildRawEventEnvelopeFromHook, compareMemoryRoleReports, connect, coordinatorCreateGroupAction, coordinatorCreateInviteAction, coordinatorCreateScopeAction, coordinatorDisableDeviceAction, coordinatorEnrollDeviceAction, coordinatorGrantScopeMembershipAction, coordinatorImportInviteAction, coordinatorListBootstrapGrantsAction, coordinatorListDevicesAction, coordinatorListGroupsAction, coordinatorListJoinRequestsAction, coordinatorListScopeMembershipsAction, coordinatorListScopesAction, coordinatorRemoveDeviceAction, coordinatorRenameDeviceAction, coordinatorReviewJoinRequestAction, coordinatorRevokeBootstrapGrantAction, coordinatorRevokeScopeMembershipAction, coordinatorUpdateScopeAction, createBetterSqliteCoordinatorApp, deactivateLowSignalMemories, deactivateLowSignalObservations, dedupNearDuplicateMemories, draftDistillRule, ensureDeviceIdentity, ensureSchemaBootstrapped, exportMemories, extractApplyPatchPaths, fetchAllSnapshotPages, fingerprintPublicKey, flushRawEvents, formatHostPort, getExtractionBenchmarkProfile, getInjectionEvalScenarioPack, getInjectionEvalScenarioPrompts, getMaintenanceJob, getMemoryArtifactReport, getMemoryRoleReport, getRawEventRelinkPlan, getRawEventRelinkReport, getRawEventStatus, getSemanticIndexDiagnostics, getSessionExtractionEval, getSessionExtractionEvalScenario, getWorkspaceCodememConfigPath, hasPendingDedupKeyBackfill, hasPendingRefBackfill, hasPendingScopeBackfill, hasPendingSessionContextBackfill, hasPendingSummaryDedupBackfill, hasUnsyncedSharedMemoryChanges, importMemories, initDatabase, isEmbeddingDisabled, judgeDistillReport, listMaintenanceJobs, listPerPeerScopeSyncState, listRetentionScopeIds, loadObserverConfig, loadPublicKey, loadSqliteVec, mdnsEnabled, planReplicationOpsAgePrune, projectMatchesFilter, pruneReplicationOpsUntilCaughtUp, rawEventsGate, readCodememConfigFile, readCodememConfigFileAtPath, readCoordinatorSyncConfig, readImportPayload, renderUnifiedDiff, replayBatchExtraction, replayBatchExtractionWithTierRouting, requestJson, resolveCodememConfigPath, resolveDbPath, resolveHookProject, resolveProject, resolveProjectRoot, retryRawEventFailures, runSyncDaemon, runSyncPass, scanSecretsRetroactive, schema, setPeerProjectFilter, stripJsonComments, stripPrivateObj, stripTrailingCommas, syncPassPreflight, updatePeerAddresses, vacuumDatabase, writeCodememConfigFile } from "@codemem/core";
3
3
  import { Command, Option } from "commander";
4
4
  import omelette from "omelette";
5
5
  import { appendFileSync, copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, rmdirSync, statSync, unlinkSync, writeFileSync } from "node:fs";
@@ -3722,6 +3722,272 @@ scanSecretsCmd.action((opts) => {
3722
3722
  });
3723
3723
  dbCommand.addCommand(scanSecretsCmd);
3724
3724
  //#endregion
3725
+ //#region src/commands/distill.ts
3726
+ var DistillUsageError = class extends Error {};
3727
+ function collectKind(value, previous) {
3728
+ return [...previous, ...value.split(",")].map((kind) => kind.trim()).filter(Boolean);
3729
+ }
3730
+ function parsePositiveInteger(value, name) {
3731
+ const parsed = Number.parseInt(value, 10);
3732
+ if (!Number.isFinite(parsed) || parsed < 1 || String(parsed) !== value.trim()) throw new DistillUsageError(`${name} must be a positive integer`);
3733
+ return parsed;
3734
+ }
3735
+ function readContextFile(path, displayPath, scope) {
3736
+ if (!existsSync(path)) return null;
3737
+ const text = readFileSync(path, "utf8");
3738
+ return text.trim() ? {
3739
+ path: displayPath,
3740
+ text,
3741
+ scope
3742
+ } : null;
3743
+ }
3744
+ function loadDefaultContextDocuments(includeProjectContext, cwd = process.cwd()) {
3745
+ const projectRoot = resolveProjectRoot(cwd) ?? cwd;
3746
+ return [includeProjectContext ? readContextFile(join(projectRoot, "AGENTS.md"), "AGENTS.md", "project") : null, readContextFile(join(homedir(), ".config", "opencode", "AGENTS.md"), "~/.config/opencode/AGENTS.md", "user")].filter((document) => document != null);
3747
+ }
3748
+ function shouldIncludeProjectContext(opts) {
3749
+ if (opts.allProjects) return false;
3750
+ const currentProject = resolveProject(process.cwd());
3751
+ if (!currentProject) return false;
3752
+ const targetProject = opts.project ? resolveProject(process.cwd(), opts.project) : process.env.CODEMEM_PROJECT?.trim() || currentProject;
3753
+ if (!targetProject) return false;
3754
+ return projectMatchesFilter(targetProject, currentProject);
3755
+ }
3756
+ function buildFilters(opts) {
3757
+ if (opts.allProjects && opts.project) throw new DistillUsageError("--project cannot be combined with --all-projects");
3758
+ if (opts.allProjects) return void 0;
3759
+ const defaultProject = process.env.CODEMEM_PROJECT?.trim() || null;
3760
+ const project = opts.project ? resolveProject(process.cwd(), opts.project) : defaultProject ?? resolveProject(process.cwd());
3761
+ return project ? { project } : void 0;
3762
+ }
3763
+ var JUDGE_OVERFETCH_FACTOR = 3;
3764
+ var JUDGE_OVERFETCH_MAX_EXTRA = 20;
3765
+ function judgeFetchLimit(limit) {
3766
+ return Math.min(limit * JUDGE_OVERFETCH_FACTOR, limit + JUDGE_OVERFETCH_MAX_EXTRA);
3767
+ }
3768
+ async function runDistill(store, opts, limit) {
3769
+ const minRecurrence = parsePositiveInteger(opts.minRecurrence, "min recurrence");
3770
+ return buildDistillReport(store, {
3771
+ candidate: {
3772
+ includeDocumented: opts.includeDocumented ?? false,
3773
+ maxEvidenceItems: opts.explain ? 10 : 5
3774
+ },
3775
+ contextDocuments: loadDefaultContextDocuments(shouldIncludeProjectContext(opts)),
3776
+ corpus: {
3777
+ filters: buildFilters(opts) ?? null,
3778
+ kinds: opts.kind.length > 0 ? opts.kind : void 0
3779
+ },
3780
+ limit,
3781
+ minRecurrence
3782
+ });
3783
+ }
3784
+ /**
3785
+ * B-side worthiness gate: an LLM judges each deterministic candidate and
3786
+ * routine-activity clusters are dropped. Recurrence alone cannot make this
3787
+ * call — releases, review passes, and context lookups recur by definition.
3788
+ */
3789
+ async function judgeReport(report) {
3790
+ const client = new ObserverClient();
3791
+ return judgeDistillReport(report, async (system, user) => {
3792
+ return (await client.observe(system, user)).raw;
3793
+ });
3794
+ }
3795
+ function renderDistillReport(report, explain = false) {
3796
+ if (report.candidates.length === 0) return "No distill candidates found.";
3797
+ const lines = [`Distill candidates (${report.candidates.length})`, ""];
3798
+ for (const [index, candidate] of report.candidates.entries()) {
3799
+ lines.push(`${index + 1}. [${candidate.scope}] score=${candidate.score.toFixed(3)} recurrence=${candidate.recurrence} target=${candidate.suggested_target}`);
3800
+ lines.push(` projects: ${candidate.projects.join(", ") || "(none)"}`);
3801
+ lines.push(` concepts: ${candidate.concepts.join(", ") || "(none)"}`);
3802
+ lines.push(` members: ${candidate.member_ids.join(", ")}`);
3803
+ const judge = candidate.judge;
3804
+ if (judge) lines.push(` judge: ${judge.verdict}${judge.reason ? ` — ${judge.reason}` : ""}`);
3805
+ if (explain) for (const evidence of candidate.evidence) lines.push(` - ${evidence}`);
3806
+ lines.push("");
3807
+ }
3808
+ return lines.join("\n").trimEnd();
3809
+ }
3810
+ function resolveCandidateTarget(candidate) {
3811
+ if (candidate.scope === "user") return {
3812
+ path: join(homedir(), ".config", "opencode", "AGENTS.md"),
3813
+ display: "~/.config/opencode/AGENTS.md"
3814
+ };
3815
+ return {
3816
+ path: join(resolveProjectRoot(process.cwd()) ?? process.cwd(), "AGENTS.md"),
3817
+ display: "AGENTS.md"
3818
+ };
3819
+ }
3820
+ async function draftTopCandidate(report, opts) {
3821
+ const candidate = report.candidates[0];
3822
+ if (!candidate) {
3823
+ if (opts.json) console.log(JSON.stringify({
3824
+ draft: null,
3825
+ reason: "no_candidates"
3826
+ }, null, 2));
3827
+ else {
3828
+ p.intro("codemem distill");
3829
+ p.log.warn("No distill candidates to draft.");
3830
+ p.outro("done");
3831
+ }
3832
+ return;
3833
+ }
3834
+ if (candidate.scope === "project") {
3835
+ const currentProject = resolveProject(process.cwd());
3836
+ if (!(currentProject != null && candidate.projects.every((project) => projectMatchesFilter(project, currentProject)))) {
3837
+ const projects = candidate.projects.join(", ") || "(unknown)";
3838
+ if (opts.json) console.log(JSON.stringify({
3839
+ draft: null,
3840
+ reason: "project_mismatch",
3841
+ representative_id: candidate.representative_id,
3842
+ projects: candidate.projects
3843
+ }, null, 2));
3844
+ else {
3845
+ p.intro("codemem distill draft");
3846
+ p.log.warn(`The top candidate belongs to project "${projects}", not this checkout. Run distill from that repo to draft its AGENTS.md rule.`);
3847
+ p.outro("nothing written");
3848
+ }
3849
+ return;
3850
+ }
3851
+ }
3852
+ const target = resolveCandidateTarget(candidate);
3853
+ const current = existsSync(target.path) ? readFileSync(target.path, "utf8") : "";
3854
+ let rule;
3855
+ let raw;
3856
+ try {
3857
+ const client = new ObserverClient();
3858
+ const drafted = await draftDistillRule(candidate, async (system, user) => {
3859
+ return (await client.observe(system, user)).raw;
3860
+ });
3861
+ rule = drafted.rule;
3862
+ raw = drafted.raw;
3863
+ } catch (error) {
3864
+ const guidance = `drafting needs a configured observer model: ${error instanceof Error ? error.message : String(error)}`;
3865
+ if (opts.json) emitJsonError("draft_failed", guidance, 1);
3866
+ else {
3867
+ p.log.error(guidance);
3868
+ process.exitCode = 1;
3869
+ }
3870
+ return;
3871
+ }
3872
+ if (!rule) {
3873
+ if (opts.json) console.log(JSON.stringify({
3874
+ draft: null,
3875
+ reason: "model_declined",
3876
+ representative_id: candidate.representative_id,
3877
+ raw
3878
+ }, null, 2));
3879
+ else {
3880
+ p.intro("codemem distill draft");
3881
+ p.log.warn("The model declined to draft a rule for the top candidate (too vague).");
3882
+ p.outro("done");
3883
+ }
3884
+ return;
3885
+ }
3886
+ const applied = applyDistillRule(current, rule);
3887
+ const diff = renderUnifiedDiff(target.display, current, applied.text);
3888
+ if (opts.json) {
3889
+ const wrote = Boolean(opts.apply && applied.changed);
3890
+ if (wrote) {
3891
+ mkdirSync(dirname(target.path), { recursive: true });
3892
+ writeFileSync(target.path, applied.text);
3893
+ }
3894
+ console.log(JSON.stringify({ draft: {
3895
+ target: target.display,
3896
+ scope: candidate.scope,
3897
+ representative_id: candidate.representative_id,
3898
+ recurrence: candidate.recurrence,
3899
+ score: candidate.score,
3900
+ rule,
3901
+ diff,
3902
+ already_present: !applied.changed,
3903
+ applied: wrote
3904
+ } }, null, 2));
3905
+ return;
3906
+ }
3907
+ p.intro("codemem distill draft");
3908
+ p.log.info(`Top candidate [${candidate.scope}] recurrence=${candidate.recurrence} → ${target.display}`);
3909
+ p.log.step(`Proposed rule:\n ${rule}`);
3910
+ if (!applied.changed) {
3911
+ p.log.warn("This rule is already present in the target file.");
3912
+ p.outro("nothing to apply");
3913
+ return;
3914
+ }
3915
+ console.log(diff);
3916
+ if (!opts.apply) {
3917
+ p.outro(`dry run — re-run with --apply to write ${target.display}`);
3918
+ return;
3919
+ }
3920
+ const confirmed = await p.confirm({ message: `Apply this change to ${target.display}?` });
3921
+ if (p.isCancel(confirmed) || !confirmed) {
3922
+ p.outro("aborted — nothing written");
3923
+ return;
3924
+ }
3925
+ mkdirSync(dirname(target.path), { recursive: true });
3926
+ writeFileSync(target.path, applied.text);
3927
+ p.outro(`wrote ${target.display}`);
3928
+ }
3929
+ async function distillAction(opts) {
3930
+ let store = null;
3931
+ try {
3932
+ store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));
3933
+ const limit = parsePositiveInteger(opts.limit, "limit");
3934
+ const judging = opts.judge !== false;
3935
+ let result = await runDistill(store, opts, judging ? judgeFetchLimit(limit) : limit);
3936
+ if (judging) {
3937
+ try {
3938
+ result = await judgeReport(result);
3939
+ } catch (error) {
3940
+ const message = error instanceof Error ? error.message : String(error);
3941
+ result = {
3942
+ ...result,
3943
+ metadata: {
3944
+ ...result.metadata,
3945
+ judged: false,
3946
+ judge_error: message
3947
+ }
3948
+ };
3949
+ }
3950
+ if (result.candidates.length > limit) result = {
3951
+ ...result,
3952
+ candidates: result.candidates.slice(0, limit),
3953
+ metadata: {
3954
+ ...result.metadata,
3955
+ candidate_count: limit
3956
+ }
3957
+ };
3958
+ }
3959
+ if (opts.draft || opts.apply) {
3960
+ await draftTopCandidate(result, opts);
3961
+ return;
3962
+ }
3963
+ if (opts.json) {
3964
+ console.log(JSON.stringify(result, null, 2));
3965
+ return;
3966
+ }
3967
+ p.intro("codemem distill");
3968
+ console.log(renderDistillReport(result, opts.explain ?? false));
3969
+ if (result.metadata.judged) p.log.info(`judge dropped ${result.metadata.routine_filtered_count ?? 0} routine-activity candidate(s)`);
3970
+ else if (result.metadata.judge_error) p.log.warn(`worthiness judgment skipped (needs a configured observer model): ${result.metadata.judge_error}. Candidates are unfiltered; recurring routine activity may rank high.`);
3971
+ p.outro("review candidates before editing context files");
3972
+ } catch (error) {
3973
+ const message = error instanceof Error ? error.message : String(error);
3974
+ const usageError = error instanceof DistillUsageError;
3975
+ if (opts.json) {
3976
+ emitJsonError(usageError ? "usage_error" : "distill_failed", message, usageError ? 2 : 1);
3977
+ return;
3978
+ }
3979
+ p.log.error(message);
3980
+ process.exitCode = usageError ? 2 : 1;
3981
+ } finally {
3982
+ store?.close();
3983
+ }
3984
+ }
3985
+ var cmd$3 = new Command("distill").configureHelp(helpStyle).description("Mine recurring memories into reviewable context candidates").option("-p, --project <project>", "project identifier (defaults to git repo root)").option("-A, --all-projects", "mine memories across all projects").option("-k, --kind <kind>", "memory kind to mine (repeat or comma-separate)", collectKind, []).option("-m, --min-recurrence <n>", "minimum member count per candidate", "2").option("-l, --limit <n>", "max candidates", "10").option("-e, --explain", "include evidence snippets in human output").option("--include-documented", "include candidates already represented in context files").option("--no-judge", "skip the observer-model worthiness judgment that drops routine-activity clusters").option("-D, --draft", "draft an AGENTS.md rule for the top candidate and show the diff").option("--apply", "write the drafted rule to the target file (implies --draft; prompts to confirm; with --json applies immediately without prompting)");
3986
+ addDbOption(cmd$3);
3987
+ addJsonOption(cmd$3);
3988
+ cmd$3.action(distillAction);
3989
+ var distillCommand = cmd$3;
3990
+ //#endregion
3725
3991
  //#region src/commands/embed.ts
3726
3992
  function parseOptionalPositiveInt(value) {
3727
3993
  if (!value) return void 0;
@@ -4654,6 +4920,51 @@ function createMemoryRoleCompareCommand() {
4654
4920
  });
4655
4921
  return cmd;
4656
4922
  }
4923
+ function createMemoryArtifactReportCommand() {
4924
+ const cmd = new Command("artifact-report").configureHelp(helpStyle).description("Analyze legacy memory artifacts in a DB snapshot without mutating rows").option("--project <project>", "project identifier (defaults to git repo root)").option("--all-projects", "analyze across all projects").option("--inactive", "include inactive memories");
4925
+ addDbOption(cmd);
4926
+ addJsonOption(cmd);
4927
+ cmd.action((opts) => {
4928
+ try {
4929
+ const project = opts.allProjects === true ? null : opts.project?.trim() || process.env.CODEMEM_PROJECT?.trim() || resolveProject(process.cwd(), null);
4930
+ const result = getMemoryArtifactReport(resolveDbOpt(opts), {
4931
+ project,
4932
+ allProjects: opts.allProjects === true,
4933
+ includeInactive: opts.inactive === true
4934
+ });
4935
+ if (opts.json) {
4936
+ console.log(JSON.stringify(result, null, 2));
4937
+ return;
4938
+ }
4939
+ p.intro("codemem memory artifact-report");
4940
+ p.log.info([
4941
+ `Memories: ${result.totals.memories}`,
4942
+ `Active: ${result.totals.active}`,
4943
+ `Sessions: ${result.totals.sessions}`
4944
+ ].join("\n"));
4945
+ p.log.info("Counts by artifact:");
4946
+ for (const [artifact, count] of Object.entries(result.counts_by_artifact)) p.log.message(` ${artifact.padEnd(16)} ${String(count)}`);
4947
+ p.log.info("Counts by action:");
4948
+ for (const [action, count] of Object.entries(result.counts_by_action)) p.log.message(` ${action.padEnd(14)} ${String(count)}`);
4949
+ const topReasons = Object.entries(result.counts_by_reason).sort(([, a], [, b]) => b - a).slice(0, 10);
4950
+ if (topReasons.length > 0) {
4951
+ p.log.info("Top reasons:");
4952
+ for (const [reason, count] of topReasons) p.log.message(` ${reason.padEnd(36)} ${String(count)}`);
4953
+ }
4954
+ p.log.info(`High-confidence telemetry: ${result.high_confidence_telemetry.total}`);
4955
+ p.outro("done");
4956
+ } catch (error) {
4957
+ const message = error instanceof Error ? error.message : "Artifact report failed";
4958
+ if (opts.json) emitJsonError("artifact_report_failed", message);
4959
+ else {
4960
+ p.log.error(message);
4961
+ process.exitCode = 1;
4962
+ }
4963
+ return;
4964
+ }
4965
+ });
4966
+ return cmd;
4967
+ }
4657
4968
  function createMemoryExtractionReportCommand() {
4658
4969
  const cmd = new Command("extraction-report").configureHelp(helpStyle).description("Score extracted memories for a session against a built-in extraction eval rubric").option("--session-id <id>", "session ID to evaluate").option("--batch-id <id>", "raw-event flush batch ID to evaluate").requiredOption("--scenario <id>", "built-in extraction eval scenario ID").option("--inactive", "include inactive memories");
4659
4970
  addDbOption(cmd);
@@ -5036,6 +5347,7 @@ memoryCommand.addCommand(createRememberMemoryCommand());
5036
5347
  memoryCommand.addCommand(createInjectMemoryCommand());
5037
5348
  memoryCommand.addCommand(createMemoryRoleReportCommand());
5038
5349
  memoryCommand.addCommand(createMemoryRoleCompareCommand());
5350
+ memoryCommand.addCommand(createMemoryArtifactReportCommand());
5039
5351
  memoryCommand.addCommand(createMemoryExtractionReportCommand());
5040
5352
  memoryCommand.addCommand(createMemoryExtractionReplayCommand());
5041
5353
  memoryCommand.addCommand(createMemoryExtractionBenchmarkCommand());
@@ -7408,6 +7720,7 @@ completion.on("command", ({ reply }) => {
7408
7720
  "config",
7409
7721
  "coordinator",
7410
7722
  "db",
7723
+ "distill",
7411
7724
  "embed",
7412
7725
  "enqueue-raw-event",
7413
7726
  "export-memories",
@@ -7489,6 +7802,7 @@ program.addCommand(claudeHookFileContextCommand);
7489
7802
  program.addCommand(codexHookInjectCommand);
7490
7803
  program.addCommand(codexHookIngestCommand);
7491
7804
  program.addCommand(dbCommand);
7805
+ program.addCommand(distillCommand);
7492
7806
  program.addCommand(exportMemoriesCommand);
7493
7807
  program.addCommand(importMemoriesCommand);
7494
7808
  program.addCommand(statsCommand);