opencode-swarm 7.103.3 → 7.104.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.
Files changed (36) hide show
  1. package/dist/cli/{config-doctor-4rxjsg22.js → config-doctor-5m8z8jeg.js} +2 -2
  2. package/dist/cli/{guardrail-explain-7c857j83.js → guardrail-explain-2zat1bxh.js} +5 -5
  3. package/dist/cli/{guardrail-log-vg0atkrx.js → guardrail-log-zhshjbpk.js} +3 -3
  4. package/dist/cli/{index-9zb70qfe.js → index-0derejrq.js} +1 -1
  5. package/dist/cli/{index-h0h4qjmc.js → index-5tywmqeh.js} +1 -1
  6. package/dist/cli/{index-fhn62ce4.js → index-e7nhwa9k.js} +8 -6
  7. package/dist/cli/{index-60prdx3j.js → index-fk8ta8zw.js} +2 -2
  8. package/dist/cli/{index-m9keg83x.js → index-kcbcy6wq.js} +1 -1
  9. package/dist/cli/{index-ye6zt96v.js → index-n3ys2eny.js} +655 -55
  10. package/dist/cli/{index-ga7et2xw.js → index-t1vfvtg9.js} +21 -0
  11. package/dist/cli/index.js +4 -4
  12. package/dist/cli/{schema-az0hgfv0.js → schema-yxkdx5g5.js} +1 -1
  13. package/dist/commands/index.d.ts +1 -1
  14. package/dist/commands/memory.d.ts +1 -0
  15. package/dist/commands/registry.d.ts +8 -0
  16. package/dist/config/schema.d.ts +22 -0
  17. package/dist/council/types.d.ts +9 -0
  18. package/dist/graph/import-extractor.d.ts +1 -1
  19. package/dist/index.js +68 -33
  20. package/dist/lang/symbol-visibility.d.ts +2 -0
  21. package/dist/memory/config.d.ts +20 -0
  22. package/dist/memory/gateway.d.ts +1 -0
  23. package/dist/memory/index.d.ts +2 -1
  24. package/dist/memory/maintenance.d.ts +4 -1
  25. package/dist/memory/provider-pool.d.ts +23 -0
  26. package/dist/memory/provider.d.ts +53 -0
  27. package/dist/memory/reward.d.ts +39 -0
  28. package/dist/memory/schema.d.ts +2 -0
  29. package/dist/memory/scoring.d.ts +2 -0
  30. package/dist/memory/sqlite-provider.d.ts +53 -1
  31. package/dist/memory/types.d.ts +5 -0
  32. package/dist/tools/convene-council.d.ts +2 -0
  33. package/dist/tools/repo-graph/builder.d.ts +4 -2
  34. package/dist/tools/submit-phase-council-verdicts.d.ts +1 -0
  35. package/dist/tools/symbols.d.ts +2 -0
  36. package/package.json +1 -1
@@ -57,7 +57,7 @@ import {
57
57
  readDoctorArtifact,
58
58
  removeStraySwarmDir,
59
59
  runConfigDoctor
60
- } from "./index-h0h4qjmc.js";
60
+ } from "./index-5tywmqeh.js";
61
61
  import {
62
62
  AGENT_TOOL_MAP,
63
63
  ALL_SUBAGENT_NAMES,
@@ -70,7 +70,7 @@ import {
70
70
  TOOL_NAME_SET,
71
71
  resolveExternalSkillsConfig,
72
72
  stripKnownSwarmPrefix
73
- } from "./index-ga7et2xw.js";
73
+ } from "./index-t1vfvtg9.js";
74
74
  import {
75
75
  MAX_TRANSIENT_RETRIES,
76
76
  PlanSchema,
@@ -912,7 +912,7 @@ var init_executor = __esm(() => {
912
912
  // package.json
913
913
  var package_default = {
914
914
  name: "opencode-swarm",
915
- version: "7.103.3",
915
+ version: "7.104.0",
916
916
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
917
917
  main: "dist/index.js",
918
918
  types: "dist/index.d.ts",
@@ -3589,7 +3589,7 @@ function classifySwarmCommandToolUse(resolved) {
3589
3589
  return { allowed: true };
3590
3590
  return {
3591
3591
  allowed: false,
3592
- message: "Use `/swarm memory status`, `/swarm memory pending`, `/swarm memory recall-log`, `/swarm memory stale`, `/swarm memory export`, or `/swarm memory evaluate --json` through swarm_command. Memory import, migrate, and compact are intentionally excluded from chat-tool execution."
3592
+ message: "Use `/swarm memory status`, `/swarm memory pending`, `/swarm memory recall-log`, `/swarm memory value-log`, `/swarm memory stale`, `/swarm memory export`, or `/swarm memory evaluate --json` through swarm_command. Memory import, migrate, and compact are intentionally excluded from chat-tool execution."
3593
3593
  };
3594
3594
  }
3595
3595
  if (canonicalKey === "memory evaluate") {
@@ -3625,7 +3625,7 @@ function classifySwarmCommandToolUse(resolved) {
3625
3625
  message: "Usage through swarm_command: `/swarm sdd validate`, `/swarm sdd validate --json`, or `/swarm sdd validate --change <id>`."
3626
3626
  };
3627
3627
  }
3628
- if (canonicalKey === "memory pending" || canonicalKey === "memory recall-log" || canonicalKey === "memory stale") {
3628
+ if (canonicalKey === "memory pending" || canonicalKey === "memory recall-log" || canonicalKey === "memory value-log" || canonicalKey === "memory stale") {
3629
3629
  if (args.length === 0)
3630
3630
  return { allowed: true };
3631
3631
  if (args.length === 2 && args[0] === "--limit" && /^\d+$/.test(args[1])) {
@@ -13377,7 +13377,7 @@ async function runFinalizeStage(ctx) {
13377
13377
  }
13378
13378
  }
13379
13379
  try {
13380
- const { CuratorConfigSchema: CCS } = await import("./schema-az0hgfv0.js");
13380
+ const { CuratorConfigSchema: CCS } = await import("./schema-yxkdx5g5.js");
13381
13381
  const { config: pmLoadedConfig } = _internals20.loadPluginConfigWithMeta(ctx.directory);
13382
13382
  const curatorCfg = CCS.parse(pmLoadedConfig.curator ?? {});
13383
13383
  if (curatorCfg.enabled && curatorCfg.postmortem_enabled) {
@@ -17203,7 +17203,7 @@ async function handleDoctorCommand(directory, args) {
17203
17203
  const result = runConfigDoctor(config, directory);
17204
17204
  let output;
17205
17205
  if (enableAutoFix && result.hasAutoFixableIssues) {
17206
- const { runConfigDoctorWithFixes } = await import("./config-doctor-4rxjsg22.js");
17206
+ const { runConfigDoctorWithFixes } = await import("./config-doctor-5m8z8jeg.js");
17207
17207
  const fixResult = await runConfigDoctorWithFixes(directory, config, true);
17208
17208
  output = formatDoctorMarkdown(fixResult.result);
17209
17209
  } else {
@@ -20605,6 +20605,17 @@ var DEFAULT_CONSOLIDATION_CONFIG = {
20605
20605
  autoApplyMinConfidence: 0.6,
20606
20606
  decayHalfLifeDays: { ...DEFAULT_DECAY_HALF_LIFE_DAYS }
20607
20607
  };
20608
+ var DEFAULT_MEMORY_LEARNING_CONFIG = {
20609
+ learningRate: 0.1,
20610
+ propagationFactor: 0.3,
20611
+ qValueBoostWeight: 0.1,
20612
+ suppressionThreshold: 0.15,
20613
+ promotionThreshold: 0.85,
20614
+ propagationTokenOverlapThreshold: 0.4,
20615
+ propagationEmbeddingCosineThreshold: 0.7,
20616
+ propagationFanout: 20,
20617
+ propagationLookbackDays: 30
20618
+ };
20608
20619
  var DEFAULT_EMBEDDINGS_CONFIG = {
20609
20620
  enabled: false,
20610
20621
  model: "Xenova/all-MiniLM-L6-v2",
@@ -20643,6 +20654,7 @@ var DEFAULT_MEMORY_CONFIG = {
20643
20654
  tokenBudget: 1000
20644
20655
  }
20645
20656
  },
20657
+ learning: { ...DEFAULT_MEMORY_LEARNING_CONFIG },
20646
20658
  writes: {
20647
20659
  mode: "propose"
20648
20660
  },
@@ -20694,6 +20706,10 @@ function resolveMemoryConfig(input) {
20694
20706
  ...input?.recall?.injection ?? {}
20695
20707
  }
20696
20708
  },
20709
+ learning: {
20710
+ ...DEFAULT_MEMORY_CONFIG.learning,
20711
+ ...input?.learning ?? {}
20712
+ },
20697
20713
  writes: {
20698
20714
  ...DEFAULT_MEMORY_CONFIG.writes,
20699
20715
  ...input?.writes ?? {}
@@ -20887,6 +20903,7 @@ var MemoryRecordSchema = exports_external.object({
20887
20903
  updatedAt: exports_external.string().datetime(),
20888
20904
  lastAccessedAt: exports_external.string().datetime().optional(),
20889
20905
  expiresAt: exports_external.string().datetime().optional(),
20906
+ qValue: exports_external.number().min(0).max(1).optional(),
20890
20907
  supersedes: exports_external.array(exports_external.string()).optional(),
20891
20908
  supersededBy: exports_external.string().optional(),
20892
20909
  contentHash: exports_external.string().regex(/^[a-f0-9]{64}$/),
@@ -21242,6 +21259,7 @@ var SCORING_WEIGHTS = {
21242
21259
  roleBoost: 0.05,
21243
21260
  confidence: 0.08
21244
21261
  };
21262
+ var DEFAULT_MEMORY_Q_VALUE = 0.5;
21245
21263
  function tokenize(text) {
21246
21264
  return new Set(text.toLowerCase().replace(/[^\w\s-]/g, " ").split(/\s+/).map((token) => token.trim()).filter(Boolean));
21247
21265
  }
@@ -21320,6 +21338,11 @@ function scoreMemoryRecordDetailed(record, request, context) {
21320
21338
  if (record.metadata.deleted === true) {
21321
21339
  return { item: null, skipReason: "filtered" };
21322
21340
  }
21341
+ const qValue = memoryQValue(record);
21342
+ const suppressionThreshold = request.suppressionThreshold ?? 0;
21343
+ if (request.includeLowQ !== true && suppressionThreshold > 0 && qValue < suppressionThreshold) {
21344
+ return { item: null, skipReason: "filtered" };
21345
+ }
21323
21346
  if (!scopeAllowed(record.scope, request.scopes)) {
21324
21347
  return { item: null, skipReason: "filtered" };
21325
21348
  }
@@ -21355,7 +21378,7 @@ function scoreMemoryRecordDetailed(record, request, context) {
21355
21378
  if (request.mode === "injection" && request.requireQuerySignal !== false && !hasQuerySignal) {
21356
21379
  return { item: null, skipReason: "no_signal" };
21357
21380
  }
21358
- const score = textOverlap * SCORING_WEIGHTS.textOverlap + tagOverlap * SCORING_WEIGHTS.tagOverlap + fileOverlap * SCORING_WEIGHTS.fileOverlap + symbolOverlap * SCORING_WEIGHTS.symbolOverlap + taskTermOverlap * SCORING_WEIGHTS.taskTermOverlap + scopeSpecificityBoost(record.scope) * SCORING_WEIGHTS.scopeSpecificityBoost + kindProfileBoost(record.kind, request) * SCORING_WEIGHTS.kindProfileBoost + roleBoost * SCORING_WEIGHTS.roleBoost + record.confidence * SCORING_WEIGHTS.confidence;
21381
+ const score = textOverlap * SCORING_WEIGHTS.textOverlap + tagOverlap * SCORING_WEIGHTS.tagOverlap + fileOverlap * SCORING_WEIGHTS.fileOverlap + symbolOverlap * SCORING_WEIGHTS.symbolOverlap + taskTermOverlap * SCORING_WEIGHTS.taskTermOverlap + scopeSpecificityBoost(record.scope) * SCORING_WEIGHTS.scopeSpecificityBoost + kindProfileBoost(record.kind, request) * SCORING_WEIGHTS.kindProfileBoost + roleBoost * SCORING_WEIGHTS.roleBoost + record.confidence * SCORING_WEIGHTS.confidence + (qValue - DEFAULT_MEMORY_Q_VALUE) * (request.qValueBoostWeight ?? 0);
21359
21382
  const reasonParts = [
21360
21383
  textOverlap > 0 ? `text_overlap=${textOverlap.toFixed(2)}` : null,
21361
21384
  tagOverlap > 0 ? `tag_overlap=${tagOverlap.toFixed(2)}` : null,
@@ -21364,6 +21387,7 @@ function scoreMemoryRecordDetailed(record, request, context) {
21364
21387
  taskTermOverlap > 0 ? `task_terms=${taskTermOverlap.toFixed(2)}` : null,
21365
21388
  kindQueryOverlap > 0 ? `kind_query=${kindQueryOverlap.toFixed(2)}` : null,
21366
21389
  roleBoost > 0 ? "role_profile" : null,
21390
+ request.qValueBoostWeight && request.qValueBoostWeight > 0 ? `q_value=${qValue.toFixed(2)}` : null,
21367
21391
  `scope=${record.scope.type}`,
21368
21392
  `confidence=${record.confidence.toFixed(2)}`
21369
21393
  ].filter(Boolean);
@@ -21377,12 +21401,26 @@ function scoreMemoryRecordDetailed(record, request, context) {
21377
21401
  tagOverlap,
21378
21402
  fileOverlap,
21379
21403
  symbolOverlap,
21404
+ qValue,
21380
21405
  kindMatch,
21381
21406
  scopeMatch
21382
21407
  }
21383
21408
  }
21384
21409
  };
21385
21410
  }
21411
+ function memoryQValue(record) {
21412
+ if (typeof record.qValue === "number" && Number.isFinite(record.qValue)) {
21413
+ return clamp01(record.qValue);
21414
+ }
21415
+ const metadataValue = record.metadata.qValue;
21416
+ if (typeof metadataValue === "number" && Number.isFinite(metadataValue)) {
21417
+ return clamp01(metadataValue);
21418
+ }
21419
+ return DEFAULT_MEMORY_Q_VALUE;
21420
+ }
21421
+ function clamp01(value) {
21422
+ return Math.min(1, Math.max(0, value));
21423
+ }
21386
21424
  function scoreMemoryRecordsWithDiagnostics(records, request) {
21387
21425
  const minScore = request.minScore ?? 0;
21388
21426
  const context = createScoringContext(request);
@@ -21453,6 +21491,14 @@ async function buildMemoryMaintenanceReport(provider, options = {}) {
21453
21491
  });
21454
21492
  const proposals = await loadMaintenanceProposals(provider, limit);
21455
21493
  const recallUsage = provider.listRecallUsage ? await provider.listRecallUsage() : [];
21494
+ const suppressionValueLog = provider.listMemoryValueLog ? await provider.listMemoryValueLog({
21495
+ includeSuppressionCandidatesOnly: true,
21496
+ limit
21497
+ }) : [];
21498
+ const promotionValueLog = provider.listMemoryValueLog ? await provider.listMemoryValueLog({
21499
+ includePromotionCandidatesOnly: true,
21500
+ limit
21501
+ }) : [];
21456
21502
  const usageByMemory = summarizeRecallByMemory(recallUsage);
21457
21503
  const usageByRole = summarizeRecallByRole(recallUsage);
21458
21504
  const activeMemories = memories.filter((memory) => isActiveMemory(memory, now));
@@ -21475,6 +21521,8 @@ async function buildMemoryMaintenanceReport(provider, options = {}) {
21475
21521
  supersededMemories: supersededMemories.slice(0, limit),
21476
21522
  supersededChains: buildSupersededChains(memories).slice(0, limit),
21477
21523
  lowUtilityMemories: lowUtilityMemories.slice(0, limit),
21524
+ lowQValueMemories: suppressionValueLog.slice(0, limit),
21525
+ promotionCandidates: promotionValueLog.slice(0, limit),
21478
21526
  neverRecalledMemories: neverRecalledMemories.slice(0, limit),
21479
21527
  mostRecalledMemories: Array.from(usageByMemory.values()).sort((a, b) => b.count - a.count || b.lastRecalledAt.localeCompare(a.lastRecalledAt) || a.memoryId.localeCompare(b.memoryId)).slice(0, limit),
21480
21528
  recallByAgentRole: Array.from(usageByRole.values()).sort((a, b) => b.count - a.count || a.agentRole.localeCompare(b.agentRole)).slice(0, limit),
@@ -22740,6 +22788,23 @@ var MIGRATIONS2 = [
22740
22788
  value TEXT
22741
22789
  );
22742
22790
  `
22791
+ },
22792
+ {
22793
+ version: 7,
22794
+ name: "add_recall_learning_columns",
22795
+ sql: `
22796
+ ALTER TABLE memory_recall_usage ADD COLUMN q_value REAL DEFAULT 0.5;
22797
+ ALTER TABLE memory_recall_usage ADD COLUMN last_reward REAL;
22798
+ ALTER TABLE memory_recall_usage ADD COLUMN task_outcome TEXT;
22799
+ ALTER TABLE memory_recall_usage ADD COLUMN council_verdict_json TEXT;
22800
+ `
22801
+ },
22802
+ {
22803
+ version: 8,
22804
+ name: "add_recall_reward_idempotency_key",
22805
+ sql: `
22806
+ ALTER TABLE memory_recall_usage ADD COLUMN reward_key TEXT;
22807
+ `
22743
22808
  }
22744
22809
  ];
22745
22810
 
@@ -22760,36 +22825,15 @@ class SQLiteMemoryProvider {
22760
22825
  lastAutomaticJsonlMigration = null;
22761
22826
  recallCountSinceLastCompaction = 0;
22762
22827
  isCompacting = false;
22828
+ _internals = {
22829
+ writeMemory: (record) => this.writeMemory(record),
22830
+ setEmbeddingProvider: (provider) => {
22831
+ this.embeddingProvider = provider;
22832
+ }
22833
+ };
22763
22834
  constructor(rootDirectory, config = {}) {
22764
22835
  this.rootDirectory = rootDirectory;
22765
- this.config = {
22766
- ...DEFAULT_MEMORY_CONFIG,
22767
- ...config,
22768
- sqlite: {
22769
- ...DEFAULT_MEMORY_CONFIG.sqlite,
22770
- ...config.sqlite ?? {}
22771
- },
22772
- recall: {
22773
- ...DEFAULT_MEMORY_CONFIG.recall,
22774
- ...config.recall ?? {},
22775
- injection: {
22776
- ...DEFAULT_MEMORY_CONFIG.recall.injection,
22777
- ...config.recall?.injection ?? {}
22778
- }
22779
- },
22780
- writes: {
22781
- ...DEFAULT_MEMORY_CONFIG.writes,
22782
- ...config.writes ?? {}
22783
- },
22784
- redaction: {
22785
- ...DEFAULT_MEMORY_CONFIG.redaction,
22786
- ...config.redaction ?? {}
22787
- },
22788
- maintenance: {
22789
- ...DEFAULT_MEMORY_CONFIG.maintenance,
22790
- ...config.maintenance ?? {}
22791
- }
22792
- };
22836
+ this.config = resolveMemoryConfig(config);
22793
22837
  }
22794
22838
  databasePath() {
22795
22839
  const relativePath = this.config.sqlite.path.replace(/^\.swarm[/\\]?/, "");
@@ -23040,12 +23084,25 @@ class SQLiteMemoryProvider {
23040
23084
  }
23041
23085
  async recordRecallUsage(event) {
23042
23086
  await this.initialize();
23087
+ const recalledRecords = event.memoryIds.map((id) => this.memories.get(id)).filter(isMemoryRecord);
23088
+ const qValue = typeof event.qValue === "number" && Number.isFinite(event.qValue) ? clamp012(event.qValue) : averageMemoryQValue(recalledRecords);
23089
+ const eventWithQValue = {
23090
+ ...event,
23091
+ qValue
23092
+ };
23043
23093
  this.requireDb().run(`INSERT INTO memory_recall_usage (
23044
23094
  id,
23045
23095
  bundle_id,
23046
23096
  timestamp,
23047
- usage_json
23048
- ) VALUES (?, ?, ?, ?)`, [randomUUID6(), event.bundleId, event.timestamp, JSON.stringify(event)]);
23097
+ usage_json,
23098
+ q_value
23099
+ ) VALUES (?, ?, ?, ?, ?)`, [
23100
+ randomUUID6(),
23101
+ event.bundleId,
23102
+ event.timestamp,
23103
+ JSON.stringify(eventWithQValue),
23104
+ qValue
23105
+ ]);
23049
23106
  this.recallCountSinceLastCompaction++;
23050
23107
  const threshold = this.config.maintenance?.autoCompactEveryNRecalls ?? 50;
23051
23108
  if (threshold > 0 && this.recallCountSinceLastCompaction >= threshold && !this.isCompacting) {
@@ -23072,24 +23129,163 @@ class SQLiteMemoryProvider {
23072
23129
  }
23073
23130
  async listRecallUsage(filter = {}) {
23074
23131
  await this.initialize();
23075
- const rows = typeof filter.limit === "number" ? this.requireDb().query(`SELECT usage_json
23132
+ const rows = typeof filter.limit === "number" ? this.requireDb().query(`SELECT id, usage_json, q_value, last_reward, task_outcome, council_verdict_json, reward_key
23076
23133
  FROM memory_recall_usage
23077
23134
  ORDER BY timestamp DESC
23078
- LIMIT ?`).all(Math.max(1, Math.trunc(filter.limit))) : this.requireDb().query(`SELECT usage_json
23135
+ LIMIT ?`).all(Math.max(1, Math.trunc(filter.limit))) : this.requireDb().query(`SELECT id, usage_json, q_value, last_reward, task_outcome, council_verdict_json, reward_key
23079
23136
  FROM memory_recall_usage
23080
23137
  ORDER BY timestamp DESC
23081
23138
  `).all();
23082
23139
  const events = [];
23083
23140
  for (const row of rows) {
23084
- try {
23085
- const parsed = JSON.parse(row.usage_json);
23086
- if (Array.isArray(parsed.memoryIds) && typeof parsed.query === "string") {
23087
- events.push(parsed);
23088
- }
23089
- } catch {}
23141
+ const parsed = parseRecallUsageRow(row);
23142
+ if (parsed)
23143
+ events.push(parsed);
23090
23144
  }
23091
23145
  return events;
23092
23146
  }
23147
+ async applyRecallReward(input) {
23148
+ await this.initialize();
23149
+ const matches = this.matchingRecallUsageRows(input.runIds);
23150
+ if (matches.length === 0) {
23151
+ return emptyRewardResult(input.outcome, "no_recall_usage_for_run");
23152
+ }
23153
+ const rewardKey = deriveRewardKey(input.verdictPayload);
23154
+ const pending = rewardKey === null ? matches : matches.filter((match) => match.rewardKey !== rewardKey);
23155
+ if (pending.length === 0) {
23156
+ const first = matches[0];
23157
+ return {
23158
+ success: true,
23159
+ bundleId: first?.event.bundleId,
23160
+ bundleIds: matches.map((match) => match.event.bundleId),
23161
+ outcome: input.outcome,
23162
+ memoryIds: uniqueStrings(matches.flatMap((match) => match.event.memoryIds)),
23163
+ reward: rewardForOutcome(input.outcome),
23164
+ updatedMemoryIds: [],
23165
+ propagatedMemoryIds: [],
23166
+ qValue: first?.event.qValue,
23167
+ reason: "already_rewarded"
23168
+ };
23169
+ }
23170
+ const reward = rewardForOutcome(input.outcome);
23171
+ const updatedAt = input.timestamp ?? new Date().toISOString();
23172
+ const sourceIds = uniqueStrings(pending.flatMap((match) => match.event.memoryIds));
23173
+ const directUpdates = new Map;
23174
+ const propagatedUpdates = new Map;
23175
+ for (const memoryId of sourceIds) {
23176
+ const nextQValue = this.updateMemoryQValue(memoryId, reward, updatedAt);
23177
+ if (nextQValue !== null) {
23178
+ directUpdates.set(memoryId, nextQValue);
23179
+ }
23180
+ }
23181
+ const promotionThreshold = this.config.learning.promotionThreshold;
23182
+ const promotionRecallThreshold = 5;
23183
+ const usageSummary = summarizeRecallUsage(this.listRecallUsageSync());
23184
+ for (const [memoryId, nextQValue] of directUpdates) {
23185
+ const memory = this.memories.get(memoryId);
23186
+ const recallCount = usageSummary.get(memoryId)?.count ?? 0;
23187
+ if (memory && memory.stability === "session" && nextQValue > promotionThreshold && recallCount > promotionRecallThreshold) {
23188
+ memory.stability = "durable";
23189
+ this._internals.writeMemory(memory);
23190
+ }
23191
+ }
23192
+ const propagationTargets = await this.findPropagationTargets(sourceIds);
23193
+ const db = this.requireDb();
23194
+ const verdictJson = truncateJsonPayload(input.verdictPayload);
23195
+ const result = db.transaction(() => {
23196
+ for (const targetId of propagationTargets) {
23197
+ const propagatedSignal = propagatedRewardSignal(reward, this.config.learning.propagationFactor);
23198
+ const nextQValue = this.updateMemoryQValue(targetId, propagatedSignal, updatedAt);
23199
+ if (nextQValue !== null) {
23200
+ propagatedUpdates.set(targetId, nextQValue);
23201
+ }
23202
+ }
23203
+ const updatedMemoryIds = [...directUpdates.keys()];
23204
+ const propagatedMemoryIds = [...propagatedUpdates.keys()];
23205
+ const combinedQValues = [
23206
+ ...directUpdates.values(),
23207
+ ...propagatedUpdates.values()
23208
+ ];
23209
+ const qValue = combinedQValues.length > 0 ? averageNumbers(combinedQValues) : pending[0]?.event.qValue;
23210
+ for (const match of pending) {
23211
+ const updatedEvent = {
23212
+ ...match.event,
23213
+ qValue,
23214
+ lastReward: reward,
23215
+ taskOutcome: input.outcome
23216
+ };
23217
+ db.run(`UPDATE memory_recall_usage
23218
+ SET usage_json = ?,
23219
+ q_value = ?,
23220
+ last_reward = ?,
23221
+ task_outcome = ?,
23222
+ council_verdict_json = ?,
23223
+ reward_key = ?
23224
+ WHERE id = ?`, [
23225
+ JSON.stringify(updatedEvent),
23226
+ qValue ?? null,
23227
+ reward,
23228
+ input.outcome,
23229
+ verdictJson,
23230
+ rewardKey,
23231
+ match.id
23232
+ ]);
23233
+ }
23234
+ return {
23235
+ updatedMemoryIds,
23236
+ propagatedMemoryIds,
23237
+ qValue
23238
+ };
23239
+ })();
23240
+ for (const match of pending) {
23241
+ await this.event("recall", match.event.bundleId, `applied ${input.outcome} recall reward`);
23242
+ }
23243
+ return {
23244
+ success: true,
23245
+ bundleId: pending[0]?.event.bundleId,
23246
+ bundleIds: pending.map((match) => match.event.bundleId),
23247
+ outcome: input.outcome,
23248
+ memoryIds: sourceIds,
23249
+ reward,
23250
+ updatedMemoryIds: result.updatedMemoryIds,
23251
+ propagatedMemoryIds: result.propagatedMemoryIds,
23252
+ qValue: result.qValue
23253
+ };
23254
+ }
23255
+ async listMemoryValueLog(filter = {}) {
23256
+ await this.initialize();
23257
+ const usageSummary = summarizeRecallUsage(this.listRecallUsageSync());
23258
+ const threshold = this.config.learning.suppressionThreshold;
23259
+ const promotionThreshold = this.config.learning.promotionThreshold;
23260
+ const entries = Array.from(this.memories.values()).map((record) => {
23261
+ const recall = usageSummary.get(record.id);
23262
+ const qValue = memoryQValue(record);
23263
+ const recallCount = recall?.count ?? 0;
23264
+ return {
23265
+ memoryId: record.id,
23266
+ kind: record.kind,
23267
+ scopeKey: stableScopeKey(record.scope),
23268
+ textPreview: truncateText(record.text, 120),
23269
+ qValue,
23270
+ recallCount,
23271
+ lastRecalledAt: recall?.lastRecalledAt,
23272
+ lastReward: recall?.lastReward,
23273
+ taskOutcome: recall?.taskOutcome,
23274
+ promotionCandidate: qValue > promotionThreshold && recallCount > 5,
23275
+ suppressionCandidate: qValue < threshold
23276
+ };
23277
+ });
23278
+ const filtered = entries.filter((entry) => {
23279
+ if (filter.includePromotionCandidatesOnly) {
23280
+ return entry.promotionCandidate;
23281
+ }
23282
+ if (filter.includeSuppressionCandidatesOnly) {
23283
+ return entry.suppressionCandidate;
23284
+ }
23285
+ return true;
23286
+ }).sort((a, b) => (b.lastRecalledAt ?? "").localeCompare(a.lastRecalledAt ?? "") || b.qValue - a.qValue || a.memoryId.localeCompare(b.memoryId));
23287
+ return filtered.slice(0, Math.max(1, Math.trunc(filter.limit ?? 20)));
23288
+ }
23093
23289
  async list(filter = {}) {
23094
23290
  await this.initialize();
23095
23291
  const db = this.requireDb();
@@ -23314,6 +23510,145 @@ class SQLiteMemoryProvider {
23314
23510
  this.memories = new Map(kept.map((memory) => [memory.id, memory]));
23315
23511
  return result;
23316
23512
  }
23513
+ matchingRecallUsageRows(runIds) {
23514
+ const idSet = new Set(runIds.filter((id) => id.length > 0));
23515
+ if (idSet.size === 0)
23516
+ return [];
23517
+ const rows = this.requireDb().query(`SELECT id, usage_json, q_value, last_reward, task_outcome, council_verdict_json, reward_key
23518
+ FROM memory_recall_usage
23519
+ ORDER BY timestamp DESC
23520
+ LIMIT ?`).all(100);
23521
+ const matches = [];
23522
+ const seenRunIds = new Set;
23523
+ for (const row of rows) {
23524
+ if (!row.id)
23525
+ continue;
23526
+ const event = parseRecallUsageRow(row);
23527
+ if (!event?.runId || !idSet.has(event.runId))
23528
+ continue;
23529
+ if (seenRunIds.has(event.runId))
23530
+ continue;
23531
+ seenRunIds.add(event.runId);
23532
+ matches.push({ id: row.id, event, rewardKey: row.reward_key ?? null });
23533
+ }
23534
+ return matches;
23535
+ }
23536
+ updateMemoryQValue(memoryId, rewardSignal, updatedAt) {
23537
+ const current = this.memories.get(memoryId);
23538
+ if (!current)
23539
+ return null;
23540
+ if (current.metadata.deleted === true || current.supersededBy)
23541
+ return null;
23542
+ const eta = this.config.learning.learningRate;
23543
+ const nextQValue = clamp012((1 - eta) * memoryQValue(current) + eta * rewardSignal);
23544
+ const next = {
23545
+ ...current,
23546
+ updatedAt,
23547
+ qValue: nextQValue
23548
+ };
23549
+ this.memories.set(memoryId, next);
23550
+ this.writeMemory(next);
23551
+ return nextQValue;
23552
+ }
23553
+ async findPropagationTargets(sourceMemoryIds) {
23554
+ const lookbackIds = this.recentlyRecalledMemoryIds(this.config.learning.propagationLookbackDays);
23555
+ if (lookbackIds.size === 0)
23556
+ return [];
23557
+ const sourceRecords = sourceMemoryIds.map((id) => this.memories.get(id)).filter(isMemoryRecord);
23558
+ if (sourceRecords.length === 0)
23559
+ return [];
23560
+ const targets = [];
23561
+ const sourceTokenSets = sourceRecords.map((record) => tokenizeText(record.text));
23562
+ const cosineEnabled = this.config.embeddings.enabled && Boolean(this.embeddingProvider);
23563
+ const cosineThreshold = this.config.learning.propagationEmbeddingCosineThreshold;
23564
+ const sourceVectors = cosineEnabled ? await Promise.all(sourceRecords.map((record) => this.getCachedEmbeddingForPropagation(record.text))) : [];
23565
+ for (const candidate of this.memories.values()) {
23566
+ if (sourceMemoryIds.includes(candidate.id))
23567
+ continue;
23568
+ if (!lookbackIds.has(candidate.id))
23569
+ continue;
23570
+ if (candidate.metadata.deleted === true || candidate.supersededBy)
23571
+ continue;
23572
+ const candidateTokens = tokenizeText(candidate.text);
23573
+ let bestOverlap = 0;
23574
+ let sameScopeAsAnySource = false;
23575
+ const sameScopeBySourceIndex = [];
23576
+ for (let i = 0;i < sourceRecords.length; i++) {
23577
+ const source = sourceRecords[i];
23578
+ const sameScope2 = stableScopeKey(candidate.scope) === stableScopeKey(source.scope);
23579
+ sameScopeBySourceIndex[i] = sameScope2;
23580
+ if (sameScope2)
23581
+ sameScopeAsAnySource = true;
23582
+ if (!sameScope2 || candidate.kind !== source.kind)
23583
+ continue;
23584
+ bestOverlap = Math.max(bestOverlap, jaccard(sourceTokenSets[i] ?? new Set, candidateTokens));
23585
+ }
23586
+ let bestCosine = 0;
23587
+ if (cosineEnabled && sameScopeAsAnySource) {
23588
+ const candidateVector = await this.getCachedEmbeddingForPropagation(candidate.text);
23589
+ if (candidateVector) {
23590
+ for (let i = 0;i < sourceVectors.length; i++) {
23591
+ if (!sameScopeBySourceIndex[i])
23592
+ continue;
23593
+ const sourceVector = sourceVectors[i];
23594
+ if (!sourceVector)
23595
+ continue;
23596
+ bestCosine = Math.max(bestCosine, cosineSimilarity(sourceVector, candidateVector));
23597
+ }
23598
+ }
23599
+ }
23600
+ const qualifiesByOverlap = bestOverlap >= this.config.learning.propagationTokenOverlapThreshold;
23601
+ const qualifiesByCosine = cosineEnabled && bestCosine >= cosineThreshold;
23602
+ if (qualifiesByOverlap || qualifiesByCosine) {
23603
+ targets.push({
23604
+ id: candidate.id,
23605
+ overlap: Math.max(bestOverlap, bestCosine)
23606
+ });
23607
+ }
23608
+ }
23609
+ return targets.sort((a, b) => b.overlap - a.overlap || a.id.localeCompare(b.id)).slice(0, this.config.learning.propagationFanout).map((target) => target.id);
23610
+ }
23611
+ async getCachedEmbeddingForPropagation(text) {
23612
+ if (!this.embeddingProvider)
23613
+ return null;
23614
+ const modelVersion = this.embeddingProvider.modelVersion;
23615
+ const normalized = normalizeMemoryText(text).toLowerCase();
23616
+ if (!normalized)
23617
+ return null;
23618
+ const cached = this.embeddingCache?.get(modelVersion, normalized)?.vector;
23619
+ if (cached)
23620
+ return cached;
23621
+ try {
23622
+ const vector = await this.embeddingProvider.embed(normalized);
23623
+ this.embeddingCache?.set(modelVersion, normalized, {
23624
+ vector,
23625
+ modelVersion,
23626
+ queryHash: normalized
23627
+ });
23628
+ return vector;
23629
+ } catch {
23630
+ return null;
23631
+ }
23632
+ }
23633
+ recentlyRecalledMemoryIds(lookbackDays) {
23634
+ const cutoffMs = Date.now() - Math.max(0, lookbackDays) * 24 * 60 * 60 * 1000;
23635
+ const memoryIds = new Set;
23636
+ for (const event of this.listRecallUsageSync(500)) {
23637
+ const timestamp = Date.parse(event.timestamp);
23638
+ if (Number.isFinite(timestamp) && timestamp < cutoffMs)
23639
+ continue;
23640
+ for (const memoryId of event.memoryIds)
23641
+ memoryIds.add(memoryId);
23642
+ }
23643
+ return memoryIds;
23644
+ }
23645
+ listRecallUsageSync(limit = 1000) {
23646
+ const rows = this.requireDb().query(`SELECT id, usage_json, q_value, last_reward, task_outcome, council_verdict_json, reward_key
23647
+ FROM memory_recall_usage
23648
+ ORDER BY timestamp DESC
23649
+ LIMIT ?`).all(Math.max(1, Math.trunc(limit)));
23650
+ return rows.map((row) => parseRecallUsageRow(row)).filter(isRecallUsageEvent);
23651
+ }
23317
23652
  hasMigration(name) {
23318
23653
  const row = this.requireDb().query("SELECT version, name FROM schema_migrations WHERE name = ? LIMIT 1").get(name);
23319
23654
  return Boolean(row);
@@ -23413,7 +23748,13 @@ class SQLiteMemoryProvider {
23413
23748
  continue;
23414
23749
  const apply = db.transaction(() => {
23415
23750
  for (const statement of splitSql(migration.sql)) {
23416
- db.run(statement);
23751
+ try {
23752
+ db.run(statement);
23753
+ } catch (err) {
23754
+ const message = err instanceof Error ? err.message : String(err);
23755
+ if (!/duplicate column name/i.test(message))
23756
+ throw err;
23757
+ }
23417
23758
  }
23418
23759
  db.run("INSERT INTO schema_migrations (version, name) VALUES (?, ?)", [
23419
23760
  migration.version,
@@ -23845,6 +24186,178 @@ class SQLiteMemoryProvider {
23845
24186
  return this.db;
23846
24187
  }
23847
24188
  }
24189
+ function averageMemoryQValue(records) {
24190
+ if (records.length === 0)
24191
+ return DEFAULT_MEMORY_Q_VALUE;
24192
+ return averageNumbers(records.map((record) => memoryQValue(record)));
24193
+ }
24194
+ function averageNumbers(values) {
24195
+ const finite = values.filter((value) => Number.isFinite(value));
24196
+ if (finite.length === 0)
24197
+ return DEFAULT_MEMORY_Q_VALUE;
24198
+ return finite.reduce((sum, value) => sum + value, 0) / finite.length;
24199
+ }
24200
+ function isMemoryRecord(record) {
24201
+ return record !== undefined;
24202
+ }
24203
+ function isRecallUsageEvent(event) {
24204
+ return event !== null;
24205
+ }
24206
+ function rewardForOutcome(outcome) {
24207
+ switch (outcome) {
24208
+ case "approved":
24209
+ return 1;
24210
+ case "rejected":
24211
+ return -1;
24212
+ case "concerns":
24213
+ case "unknown":
24214
+ return 0;
24215
+ }
24216
+ }
24217
+ function propagatedRewardSignal(reward, propagationFactor) {
24218
+ const factor = Math.max(0, Math.min(1, propagationFactor));
24219
+ return DEFAULT_MEMORY_Q_VALUE + factor * (reward - DEFAULT_MEMORY_Q_VALUE);
24220
+ }
24221
+ function emptyRewardResult(outcome, reason) {
24222
+ return {
24223
+ success: false,
24224
+ outcome,
24225
+ memoryIds: [],
24226
+ reward: rewardForOutcome(outcome),
24227
+ updatedMemoryIds: [],
24228
+ propagatedMemoryIds: [],
24229
+ reason
24230
+ };
24231
+ }
24232
+ function parseRecallUsageRow(row) {
24233
+ try {
24234
+ const parsed = JSON.parse(row.usage_json);
24235
+ if (!Array.isArray(parsed.memoryIds) || typeof parsed.query !== "string") {
24236
+ return null;
24237
+ }
24238
+ const event = { ...parsed };
24239
+ if (typeof row.q_value === "number" && Number.isFinite(row.q_value)) {
24240
+ event.qValue = clamp012(row.q_value);
24241
+ }
24242
+ if (typeof row.last_reward === "number" && Number.isFinite(row.last_reward)) {
24243
+ event.lastReward = row.last_reward;
24244
+ }
24245
+ const taskOutcome = normalizeTaskOutcome(row.task_outcome);
24246
+ if (taskOutcome)
24247
+ event.taskOutcome = taskOutcome;
24248
+ return event;
24249
+ } catch {
24250
+ return null;
24251
+ }
24252
+ }
24253
+ function normalizeTaskOutcome(value) {
24254
+ if (value === "approved" || value === "rejected" || value === "concerns" || value === "unknown") {
24255
+ return value;
24256
+ }
24257
+ return;
24258
+ }
24259
+ function truncateJsonPayload(value) {
24260
+ if (value === undefined)
24261
+ return null;
24262
+ let json;
24263
+ try {
24264
+ json = JSON.stringify(value);
24265
+ } catch (err) {
24266
+ return JSON.stringify({
24267
+ unserializable: true,
24268
+ reason: err instanceof Error ? err.message : String(err)
24269
+ });
24270
+ }
24271
+ const maxLength = 8192;
24272
+ if (json.length <= maxLength)
24273
+ return json;
24274
+ return JSON.stringify({
24275
+ truncated: true,
24276
+ preview: json.slice(0, maxLength - 32)
24277
+ });
24278
+ }
24279
+ function deriveRewardKey(verdictPayload) {
24280
+ if (!verdictPayload || typeof verdictPayload !== "object")
24281
+ return null;
24282
+ const payload = verdictPayload;
24283
+ const swarmId = payload.swarmId;
24284
+ const roundNumber = payload.roundNumber;
24285
+ const unit = payload.taskId ?? payload.phaseNumber;
24286
+ const unitOk = typeof unit === "string" || typeof unit === "number";
24287
+ const roundOk = typeof roundNumber === "string" || typeof roundNumber === "number";
24288
+ if (typeof swarmId !== "string" || swarmId.length === 0 || !unitOk || !roundOk) {
24289
+ return null;
24290
+ }
24291
+ return `${swarmId}:${unit}:${roundNumber}`;
24292
+ }
24293
+ function summarizeRecallUsage(events) {
24294
+ const summary = new Map;
24295
+ for (const event of events) {
24296
+ for (const memoryId of event.memoryIds) {
24297
+ const existing = summary.get(memoryId) ?? {
24298
+ count: 0,
24299
+ lastRecalledAt: event.timestamp
24300
+ };
24301
+ existing.count++;
24302
+ if (event.timestamp >= existing.lastRecalledAt) {
24303
+ existing.lastRecalledAt = event.timestamp;
24304
+ existing.lastReward = event.lastReward;
24305
+ existing.taskOutcome = event.taskOutcome;
24306
+ }
24307
+ summary.set(memoryId, existing);
24308
+ }
24309
+ }
24310
+ return summary;
24311
+ }
24312
+ function uniqueStrings(values) {
24313
+ return Array.from(new Set(values.filter((value) => value.length > 0)));
24314
+ }
24315
+ function truncateText(value, maxLength) {
24316
+ if (value.length <= maxLength)
24317
+ return value;
24318
+ return `${value.slice(0, maxLength - 3)}...`;
24319
+ }
24320
+ function tokenizeText(value) {
24321
+ const tokens = new Set;
24322
+ for (const match of value.toLowerCase().matchAll(/[a-z0-9_]{3,}/g)) {
24323
+ const token = match[0];
24324
+ if (!FTS_STOP_WORDS.has(token))
24325
+ tokens.add(token);
24326
+ }
24327
+ return tokens;
24328
+ }
24329
+ function jaccard(left, right) {
24330
+ if (left.size === 0 || right.size === 0)
24331
+ return 0;
24332
+ let intersection = 0;
24333
+ for (const token of left) {
24334
+ if (right.has(token))
24335
+ intersection++;
24336
+ }
24337
+ const union = left.size + right.size - intersection;
24338
+ return union > 0 ? intersection / union : 0;
24339
+ }
24340
+ function cosineSimilarity(a, b) {
24341
+ if (a.length === 0 || a.length !== b.length)
24342
+ return 0;
24343
+ let dot = 0;
24344
+ let normA = 0;
24345
+ let normB = 0;
24346
+ for (let i = 0;i < a.length; i++) {
24347
+ dot += a[i] * b[i];
24348
+ normA += a[i] * a[i];
24349
+ normB += b[i] * b[i];
24350
+ }
24351
+ if (normA === 0 || normB === 0)
24352
+ return 0;
24353
+ const similarity = dot / (Math.sqrt(normA) * Math.sqrt(normB));
24354
+ return Number.isFinite(similarity) ? similarity : 0;
24355
+ }
24356
+ function clamp012(value) {
24357
+ if (!Number.isFinite(value))
24358
+ return DEFAULT_MEMORY_Q_VALUE;
24359
+ return Math.min(1, Math.max(0, value));
24360
+ }
23848
24361
  function splitSql(sql) {
23849
24362
  const statements = [];
23850
24363
  let current = "";
@@ -24154,6 +24667,21 @@ function resolvePoolKey(directory) {
24154
24667
  return path47.resolve(directory);
24155
24668
  }
24156
24669
  }
24670
+ function evictAndClose(directory) {
24671
+ const key = resolvePoolKey(directory);
24672
+ const active = entriesByKey.get(key);
24673
+ if (active) {
24674
+ entriesByKey.delete(key);
24675
+ unlinkEntry(active);
24676
+ callRealClose(active.provider);
24677
+ }
24678
+ for (const deferred of [...deferredEntries]) {
24679
+ if (deferred.key === key) {
24680
+ deferredEntries.delete(deferred);
24681
+ callRealClose(deferred.provider);
24682
+ }
24683
+ }
24684
+ }
24157
24685
 
24158
24686
  // src/memory/gateway.ts
24159
24687
  function createConfiguredMemoryProvider(directory, config) {
@@ -24256,7 +24784,8 @@ async function evaluateMemoryRecallFixtures(options) {
24256
24784
  } finally {
24257
24785
  await provider.close?.();
24258
24786
  if (!options.keepTempRoots) {
24259
- await fs19.rm(tempRoot, { recursive: true, force: true });
24787
+ evictAndClose(tempRoot);
24788
+ await rmTempRoot(tempRoot);
24260
24789
  }
24261
24790
  }
24262
24791
  }
@@ -24271,6 +24800,18 @@ async function evaluateMemoryRecallFixtures(options) {
24271
24800
  runs
24272
24801
  };
24273
24802
  }
24803
+ async function rmTempRoot(tempRoot) {
24804
+ for (let attempt = 0;attempt < 10; attempt++) {
24805
+ try {
24806
+ await fs19.rm(tempRoot, { recursive: true, force: true });
24807
+ return;
24808
+ } catch (err) {
24809
+ if (attempt === 9)
24810
+ throw err;
24811
+ await new Promise((resolve13) => setTimeout(resolve13, 50));
24812
+ }
24813
+ }
24814
+ }
24274
24815
  async function loadRecallEvaluationFixtures(fixtureDirectory) {
24275
24816
  const entries = await fs19.readdir(fixtureDirectory, { withFileTypes: true });
24276
24817
  const files = entries.filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name).sort((a, b) => a.localeCompare(b));
@@ -24585,6 +25126,7 @@ async function handleMemoryCommand(_directory, _args) {
24585
25126
  "- `/swarm memory status` - show provider, SQLite path, JSONL files, and last migration report",
24586
25127
  "- `/swarm memory pending` - show pending proposals and recent rejection reasons",
24587
25128
  "- `/swarm memory recall-log` - summarize recall usage by agent role and memory ID",
25129
+ "- `/swarm memory value-log` - show recent Q-value, reward, suppression, and promotion signals",
24588
25130
  "- `/swarm memory stale` - list expired scratch, superseded, deleted, and low-utility memories",
24589
25131
  "- `/swarm memory compact` - dry-run compaction; pass `--confirm` to remove deleted, superseded, and expired scratch records",
24590
25132
  "- `/swarm memory export` - export current memory and proposals to `.swarm/memory/export/*.jsonl`",
@@ -24679,10 +25221,12 @@ async function handleMemoryPendingCommand(directory, args) {
24679
25221
  "## Swarm Memory Pending",
24680
25222
  "",
24681
25223
  `- Pending proposals shown: \`${report.pendingProposals.length}\``,
24682
- `- Rejected proposal reasons shown: \`${report.rejectedProposalReasons.length}\``
25224
+ `- Rejected proposal reasons shown: \`${report.rejectedProposalReasons.length}\``,
25225
+ `- Promotion candidates shown: \`${report.promotionCandidates.length}\``
24683
25226
  ];
24684
25227
  appendProposalLines(lines, "Pending proposals", report.pendingProposals);
24685
25228
  appendProposalLines(lines, "Rejected proposal reasons", report.rejectedProposalReasons);
25229
+ appendValueLogLines(lines, "Promotion candidates", report.promotionCandidates);
24686
25230
  return lines.join(`
24687
25231
  `);
24688
25232
  } finally {
@@ -24719,6 +25263,39 @@ async function handleMemoryRecallLogCommand(directory, args) {
24719
25263
  await provider.close?.();
24720
25264
  }
24721
25265
  }
25266
+ async function handleMemoryValueLogCommand(directory, args) {
25267
+ const parsed = parseMaintenanceArgs(args, {
25268
+ usage: "Usage: /swarm memory value-log [--limit <n>]",
25269
+ allowConfirm: false
25270
+ });
25271
+ if ("error" in parsed)
25272
+ return parsed.error;
25273
+ const config = resolveCommandMemoryConfig(directory);
25274
+ const provider = createMaintenanceProvider(directory, config);
25275
+ try {
25276
+ await provider.initialize?.();
25277
+ if (!provider.listMemoryValueLog) {
25278
+ return "Memory provider does not support value-log reporting.";
25279
+ }
25280
+ const valueLog = await provider.listMemoryValueLog({ limit: parsed.limit });
25281
+ const promotionCandidates = valueLog.filter((entry) => entry.promotionCandidate);
25282
+ const suppressionCandidates = valueLog.filter((entry) => entry.suppressionCandidate);
25283
+ const lines = [
25284
+ "## Swarm Memory Value Log",
25285
+ "",
25286
+ `- Entries shown: \`${valueLog.length}\``,
25287
+ `- Promotion candidates shown: \`${promotionCandidates.length}\``,
25288
+ `- Suppression candidates shown: \`${suppressionCandidates.length}\``
25289
+ ];
25290
+ appendValueLogLines(lines, "Recent Q-value updates", valueLog);
25291
+ appendValueLogLines(lines, "Promotion candidates", promotionCandidates);
25292
+ appendValueLogLines(lines, "Suppression candidates", suppressionCandidates);
25293
+ return lines.join(`
25294
+ `);
25295
+ } finally {
25296
+ await provider.close?.();
25297
+ }
25298
+ }
24722
25299
  async function handleMemoryStaleCommand(directory, args) {
24723
25300
  const parsed = parseMaintenanceArgs(args, {
24724
25301
  usage: "Usage: /swarm memory stale [--limit <n>]",
@@ -24740,12 +25317,14 @@ async function handleMemoryStaleCommand(directory, args) {
24740
25317
  `- Expired scratch memories shown: \`${report.expiredScratchMemories.length}\``,
24741
25318
  `- Deleted tombstones shown: \`${report.deletedMemories.length}\``,
24742
25319
  `- Superseded memories shown: \`${report.supersededMemories.length}\``,
24743
- `- Low-utility memories shown: \`${report.lowUtilityMemories.length}\``
25320
+ `- Low-utility memories shown: \`${report.lowUtilityMemories.length}\``,
25321
+ `- Low-Q memories shown: \`${report.lowQValueMemories.length}\``
24744
25322
  ];
24745
25323
  appendMemoryLines(lines, "Expired scratch memories", report.expiredScratchMemories);
24746
25324
  appendMemoryLines(lines, "Deleted tombstones", report.deletedMemories);
24747
25325
  appendSupersededChains(lines, report);
24748
25326
  appendMemoryLines(lines, "Low-utility memories", report.lowUtilityMemories);
25327
+ appendValueLogLines(lines, "Low-Q memories", report.lowQValueMemories);
24749
25328
  return lines.join(`
24750
25329
  `);
24751
25330
  } finally {
@@ -25022,6 +25601,19 @@ function appendRecallMemoryLines(lines, memories) {
25022
25601
  lines.push(`- \`${memory.memoryId}\`: ${memory.count} hit(s), last=${memory.lastRecalledAt}, avgScore=${memory.averageScore.toFixed(3)}`);
25023
25602
  }
25024
25603
  }
25604
+ function appendValueLogLines(lines, title, entries) {
25605
+ lines.push("", `### ${title}`);
25606
+ if (entries.length === 0) {
25607
+ lines.push("- none");
25608
+ return;
25609
+ }
25610
+ for (const entry of entries) {
25611
+ const outcome = entry.taskOutcome ? ` outcome=${entry.taskOutcome}` : "";
25612
+ const reward = typeof entry.lastReward === "number" ? ` reward=${entry.lastReward.toFixed(2)}` : "";
25613
+ const last = entry.lastRecalledAt ? ` last=${entry.lastRecalledAt}` : "";
25614
+ lines.push(`- \`${entry.memoryId}\` ${entry.kind} q=${entry.qValue.toFixed(3)} recalls=${entry.recallCount}${reward}${outcome}${last} - ${entry.textPreview}`);
25615
+ }
25616
+ }
25025
25617
  function appendSupersededChains(lines, report) {
25026
25618
  lines.push("", "### Superseded chains");
25027
25619
  if (report.supersededChains.length === 0) {
@@ -33373,7 +33965,7 @@ function buildDetailedHelp(commandName, entry) {
33373
33965
  async function handleHelpCommand(ctx) {
33374
33966
  const targetCommand = ctx.args.join(" ");
33375
33967
  if (!targetCommand) {
33376
- const { buildHelpText } = await import("./index-fhn62ce4.js");
33968
+ const { buildHelpText } = await import("./index-e7nhwa9k.js");
33377
33969
  return buildHelpText();
33378
33970
  }
33379
33971
  const tokens = targetCommand.split(/\s+/);
@@ -33382,7 +33974,7 @@ async function handleHelpCommand(ctx) {
33382
33974
  return _internals47.buildDetailedHelp(resolved.key, resolved.entry);
33383
33975
  }
33384
33976
  const similar = _internals47.findSimilarCommands(targetCommand);
33385
- const { buildHelpText: fullHelp } = await import("./index-fhn62ce4.js");
33977
+ const { buildHelpText: fullHelp } = await import("./index-e7nhwa9k.js");
33386
33978
  if (similar.length > 0) {
33387
33979
  return `Command '/swarm ${targetCommand}' not found.
33388
33980
 
@@ -33515,7 +34107,7 @@ var COMMAND_REGISTRY = {
33515
34107
  },
33516
34108
  "guardrail explain": {
33517
34109
  handler: async (ctx) => {
33518
- const { handleGuardrailExplain } = await import("./guardrail-explain-7c857j83.js");
34110
+ const { handleGuardrailExplain } = await import("./guardrail-explain-2zat1bxh.js");
33519
34111
  return handleGuardrailExplain(ctx.directory, ctx.args);
33520
34112
  },
33521
34113
  description: "Dry-run: show what the guardrails would do to a command or write target (executes nothing)",
@@ -33525,7 +34117,7 @@ var COMMAND_REGISTRY = {
33525
34117
  },
33526
34118
  "guardrail-log": {
33527
34119
  handler: async (ctx) => {
33528
- const { handleGuardrailLog } = await import("./guardrail-log-vg0atkrx.js");
34120
+ const { handleGuardrailLog } = await import("./guardrail-log-zhshjbpk.js");
33529
34121
  return handleGuardrailLog(ctx.directory, ctx.args);
33530
34122
  },
33531
34123
  description: "Read the guardrail decision log (use --blocks-only for blocks)",
@@ -34184,6 +34776,14 @@ Subcommands:
34184
34776
  category: "diagnostics",
34185
34777
  toolPolicy: "agent"
34186
34778
  },
34779
+ "memory value-log": {
34780
+ handler: (ctx) => handleMemoryValueLogCommand(ctx.directory, ctx.args),
34781
+ description: "Show Swarm memory Q-value and reward updates",
34782
+ subcommandOf: "memory",
34783
+ args: "--limit <n>",
34784
+ category: "diagnostics",
34785
+ toolPolicy: "agent"
34786
+ },
34187
34787
  "memory compact": {
34188
34788
  handler: (ctx) => handleMemoryCompactCommand(ctx.directory, ctx.args),
34189
34789
  description: "Compact deleted, superseded, and expired scratch memories",
@@ -34459,4 +35059,4 @@ ${text}`;
34459
35059
  };
34460
35060
  }
34461
35061
 
34462
- export { package_default, handleAcknowledgeSpecDriftCommand, handleAgentsCommand, handleAnalyzeCommand, handleArchiveCommand, DC_SAFE_TARGETS, dcNormalizeCommand, dcUnwrapWrappers, dcSplitSegments, dcValidateTargets, dcCheckJunctionCreation, dcExtractWindowsCmdTargets, dcExtractPowerShellTargets, normalizeSwarmCommandInput, canonicalCommandKey, formatCommandNotFound, executeSwarmCommand, SWARM_COMMAND_TOOL_COMMANDS, SWARM_COMMAND_TOOL_ALLOWLIST, HUMAN_ONLY_SWARM_COMMANDS, classifySwarmCommandToolUse, classifySwarmCommandChatFallbackUse, detectPosixWrites, detectWindowsWrites, resolveWriteTargets, handleAutoProceedCommand, handleBenchmarkCommand, handleBrainstormCommand, handleCheckpointCommand, handleClarifyCommand, handleCloseCommand, handleCodebaseReviewCommand, handleConcurrencyCommand, handleConfigCommand, handleConsolidateCommand, handleCostsCommand, handleCouncilCommand, handleCurateCommand, handleDarkMatterCommand, handleDeepDiveCommand, handleDeepResearchCommand, getPluginConfigDir, getPluginCachePaths, getPluginLockFilePaths, handleDiagnoseCommand, handleDoctorCommand, handleEvidenceCommand, handleEvidenceSummaryCommand, handleExportCommand, handleFullAutoCommand, handleHandoffCommand, handleHistoryCommand, handleKnowledgeQuarantineCommand, handleKnowledgeRestoreCommand, handleKnowledgeMigrateCommand, handleKnowledgeListCommand, handleKnowledgeUnactionableCommand, handleKnowledgeRetryHardeningCommand, handleLearningCommand, handleLinkCommand, handleMemoryCommand, handleMemoryStatusCommand, handleMemoryMigrateCommand, handleMemoryImportCommand, handleMemoryExportCommand, handlePlanCommand, handlePreflightCommand, handlePromoteCommand, handleQaGatesCommand, handleResetCommand, handleResetSessionCommand, handleRetrieveCommand, handleRollbackCommand, handleSddStatusCommand, handleSddValidateCommand, handleSddProjectCommand, handleSddCommand, handleSimulateCommand, handleSpecifyCommand, handleStatusCommand, handleSyncPlanCommand, handleTurboCommand, handleUnlinkCommand, handleWriteRetroCommand, handleHelpCommand, COMMAND_REGISTRY, VALID_COMMANDS, _internals47 as _internals, resolveCommand };
35062
+ export { package_default, handleAcknowledgeSpecDriftCommand, handleAgentsCommand, handleAnalyzeCommand, handleArchiveCommand, DC_SAFE_TARGETS, dcNormalizeCommand, dcUnwrapWrappers, dcSplitSegments, dcValidateTargets, dcCheckJunctionCreation, dcExtractWindowsCmdTargets, dcExtractPowerShellTargets, normalizeSwarmCommandInput, canonicalCommandKey, formatCommandNotFound, executeSwarmCommand, SWARM_COMMAND_TOOL_COMMANDS, SWARM_COMMAND_TOOL_ALLOWLIST, HUMAN_ONLY_SWARM_COMMANDS, classifySwarmCommandToolUse, classifySwarmCommandChatFallbackUse, detectPosixWrites, detectWindowsWrites, resolveWriteTargets, handleAutoProceedCommand, handleBenchmarkCommand, handleBrainstormCommand, handleCheckpointCommand, handleClarifyCommand, handleCloseCommand, handleCodebaseReviewCommand, handleConcurrencyCommand, handleConfigCommand, handleConsolidateCommand, handleCostsCommand, handleCouncilCommand, handleCurateCommand, handleDarkMatterCommand, handleDeepDiveCommand, handleDeepResearchCommand, getPluginConfigDir, getPluginCachePaths, getPluginLockFilePaths, handleDiagnoseCommand, handleDoctorCommand, handleEvidenceCommand, handleEvidenceSummaryCommand, handleExportCommand, handleFullAutoCommand, handleHandoffCommand, handleHistoryCommand, handleKnowledgeQuarantineCommand, handleKnowledgeRestoreCommand, handleKnowledgeMigrateCommand, handleKnowledgeListCommand, handleKnowledgeUnactionableCommand, handleKnowledgeRetryHardeningCommand, handleLearningCommand, handleLinkCommand, handleMemoryCommand, handleMemoryStatusCommand, handleMemoryValueLogCommand, handleMemoryMigrateCommand, handleMemoryImportCommand, handleMemoryExportCommand, handlePlanCommand, handlePreflightCommand, handlePromoteCommand, handleQaGatesCommand, handleResetCommand, handleResetSessionCommand, handleRetrieveCommand, handleRollbackCommand, handleSddStatusCommand, handleSddValidateCommand, handleSddProjectCommand, handleSddCommand, handleSimulateCommand, handleSpecifyCommand, handleStatusCommand, handleSyncPlanCommand, handleTurboCommand, handleUnlinkCommand, handleWriteRetroCommand, handleHelpCommand, COMMAND_REGISTRY, VALID_COMMANDS, _internals47 as _internals, resolveCommand };