mixdog 1.0.4 → 1.0.5

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 (158) hide show
  1. package/README.md +10 -5
  2. package/package.json +18 -17
  3. package/scripts/gate-local.mjs +93 -0
  4. package/scripts/lib/gate-scheduler.mjs +24 -0
  5. package/scripts/lib/run-node-tests.mjs +5 -1
  6. package/scripts/release-paths.mjs +22 -1
  7. package/scripts/test-direct.mjs +2 -1
  8. package/scripts/test.mjs +3 -1
  9. package/src/defaults/agents.json +0 -12
  10. package/src/defaults/mixdog-config.template.json +1 -2
  11. package/src/defaults/skills/docx/SKILL.md +7 -4
  12. package/src/defaults/skills/docx/references/html.md +46 -0
  13. package/src/defaults/skills/docx/references/native-authoring.md +18 -4
  14. package/src/defaults/skills/pdf/SKILL.md +10 -2
  15. package/src/defaults/skills/pdf/references/html.md +64 -0
  16. package/src/defaults/skills/pptx/references/html.md +1 -1
  17. package/src/defaults/skills/xlsx/SKILL.md +7 -3
  18. package/src/defaults/skills/xlsx/references/html.md +40 -0
  19. package/src/defaults/skills/xlsx/references/report-design.md +21 -4
  20. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/preset.mjs +1 -1
  21. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -3
  22. package/src/runtime/agent/orchestrator/internal-agents.mjs +1 -1
  23. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +6 -5
  24. package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +6 -3
  25. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +6 -2
  26. package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +50 -9
  27. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +28 -1
  28. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +4 -1
  29. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +34 -8
  30. package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +10 -2
  31. package/src/runtime/agent/orchestrator/session/transcript-restore/agent-envelope.mjs +1 -1
  32. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +1 -0
  33. package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +3 -1
  34. package/src/runtime/attachments/pdf-extract.mjs +7 -3
  35. package/src/runtime/computer-bridge/client.mjs +1 -1
  36. package/src/runtime/memory/index.mjs +4 -15
  37. package/src/runtime/memory/lib/core-memory-store.mjs +1 -1
  38. package/src/runtime/memory/lib/cycle-llm-adapters.mjs +0 -2
  39. package/src/runtime/memory/lib/cycle-scheduler/backlog-probe.mjs +3 -11
  40. package/src/runtime/memory/lib/cycle-scheduler/health-ledger.mjs +1 -3
  41. package/src/runtime/memory/lib/cycle-scheduler/scheduled-enqueue.mjs +1 -11
  42. package/src/runtime/memory/lib/cycle-scheduler/tick-loop.mjs +0 -2
  43. package/src/runtime/memory/lib/cycle-scheduler.mjs +4 -13
  44. package/src/runtime/memory/lib/cycle-signatures.mjs +0 -6
  45. package/src/runtime/memory/lib/cycle1/cycle1-rows.mjs +1 -1
  46. package/src/runtime/memory/lib/cycle1/cycle1-window.mjs +2 -2
  47. package/src/runtime/memory/lib/embedding-reindex.mjs +1 -1
  48. package/src/runtime/memory/lib/http-router/lifecycle-routes.mjs +0 -1
  49. package/src/runtime/memory/lib/memory-action-handlers/cycle-actions.mjs +7 -52
  50. package/src/runtime/memory/lib/memory-action-handlers/cycle-backfill-action.mjs +6 -22
  51. package/src/runtime/memory/lib/memory-action-handlers/cycle-rebuild-action.mjs +10 -17
  52. package/src/runtime/memory/lib/memory-action-handlers/maintenance-actions.mjs +1 -3
  53. package/src/runtime/memory/lib/memory-action-handlers/manage-actions.mjs +2 -4
  54. package/src/runtime/memory/lib/memory-action-handlers.mjs +2 -4
  55. package/src/runtime/memory/lib/memory-cycle-requests.mjs +1 -1
  56. package/src/runtime/memory/lib/{memory-cycle2-shared.mjs → memory-cycle-shared.mjs} +14 -16
  57. package/src/runtime/memory/lib/memory-cycle.mjs +3 -2
  58. package/src/runtime/memory/lib/memory-cycle1.mjs +1 -1
  59. package/src/runtime/memory/lib/memory-embed.mjs +14 -1
  60. package/src/runtime/memory/lib/memory-ops-policy.mjs +8 -11
  61. package/src/runtime/memory/lib/memory-schema/entries.mjs +0 -1
  62. package/src/runtime/memory/lib/memory.mjs +2 -6
  63. package/src/runtime/memory/lib/pg/adapter.mjs +1 -1
  64. package/src/runtime/memory/lib/query-handlers.mjs +1 -1
  65. package/src/runtime/memory/lib/query-hybrid-search.mjs +1 -1
  66. package/src/runtime/memory/lib/query-maintenance-handlers.mjs +0 -6
  67. package/src/runtime/memory/lib/recall-format.mjs +1 -1
  68. package/src/runtime/office/authoring/docx-html-build.mjs +375 -0
  69. package/src/runtime/office/authoring/docx-html-measure.mjs +561 -0
  70. package/src/runtime/office/authoring/docx-html-runner.mjs +102 -0
  71. package/src/runtime/office/authoring/html-browser.mjs +61 -0
  72. package/src/runtime/office/authoring/html-document-author.mjs +181 -0
  73. package/src/runtime/office/authoring/html-source-drift.mjs +36 -0
  74. package/src/runtime/office/authoring/pdf-author-action.mjs +266 -0
  75. package/src/runtime/office/authoring/pdf-html-charts.mjs +379 -0
  76. package/src/runtime/office/authoring/pdf-html-runner.mjs +317 -0
  77. package/src/runtime/office/authoring/pptx-author-action.mjs +44 -22
  78. package/src/runtime/office/authoring/pptx-author-session.mjs +12 -6
  79. package/src/runtime/office/authoring/pptx-html-build.mjs +23 -4
  80. package/src/runtime/office/authoring/pptx-html-measure.mjs +38 -44
  81. package/src/runtime/office/authoring/pptx-html-runner.mjs +18 -3
  82. package/src/runtime/office/authoring/pptx-receipt.mjs +39 -31
  83. package/src/runtime/office/authoring/pptx-review-artifacts.mjs +9 -1
  84. package/src/runtime/office/authoring/pptx-script-runner.mjs +6 -2
  85. package/src/runtime/office/authoring/xlsx-html-build.mjs +365 -0
  86. package/src/runtime/office/authoring/xlsx-html-measure.mjs +257 -0
  87. package/src/runtime/office/authoring/xlsx-html-runner.mjs +139 -0
  88. package/src/runtime/office/capabilities-catalog.mjs +8 -0
  89. package/src/runtime/office/capabilities-signatures.mjs +18 -6
  90. package/src/runtime/office/capabilities.mjs +26 -1
  91. package/src/runtime/office/com/office-com-host.ps1 +133 -17
  92. package/src/runtime/office/core/office-actions-batch.mjs +16 -1
  93. package/src/runtime/office/core/office-actions-inspect.mjs +3 -2
  94. package/src/runtime/office/core/office-actions-lifecycle.mjs +6 -2
  95. package/src/runtime/office/core/office-actions-render.mjs +4 -1
  96. package/src/runtime/office/core/office-finalize/review-stage.mjs +15 -2
  97. package/src/runtime/office/core/office-qa/design-review-stage.mjs +9 -0
  98. package/src/runtime/office/core/office-session-dispatch.mjs +3 -0
  99. package/src/runtime/office/core/office-sessionless-actions.mjs +7 -2
  100. package/src/runtime/office/core/office-sessions.mjs +19 -2
  101. package/src/runtime/office/pdf/pdf-writer.mjs +1 -1
  102. package/src/runtime/office/portable/docx-formatting.mjs +21 -0
  103. package/src/runtime/office/portable/ooxml-validator.mjs +22 -1
  104. package/src/runtime/office/portable/portable-chart.mjs +10 -2
  105. package/src/runtime/office/portable/portable-docx-edits.mjs +12 -6
  106. package/src/runtime/office/portable/portable-docx-operations.mjs +75 -1
  107. package/src/runtime/office/portable/portable-docx-xml.mjs +49 -6
  108. package/src/runtime/office/portable/portable-docx.mjs +2 -0
  109. package/src/runtime/office/portable/portable-snapshot-docx.mjs +2 -0
  110. package/src/runtime/office/portable/portable-validation.mjs +6 -3
  111. package/src/runtime/office/portable/portable-xlsx-cell-values.mjs +87 -0
  112. package/src/runtime/office/portable/portable-xlsx-charts.mjs +55 -13
  113. package/src/runtime/office/portable/portable-xlsx-sheet-edits.mjs +1 -1
  114. package/src/runtime/office/portable/xlsx-contract.mjs +82 -3
  115. package/src/runtime/office/quality/assurance-checklist.mjs +2 -2
  116. package/src/runtime/office/quality/assurance-rendered.mjs +27 -1
  117. package/src/runtime/office/quality/assurance-structure-docx.mjs +44 -0
  118. package/src/runtime/office/quality/assurance-structure-pptx.mjs +24 -6
  119. package/src/runtime/office/quality/assurance-structure-xlsx.mjs +50 -1
  120. package/src/runtime/office/quality/design-review-critique.mjs +3 -2
  121. package/src/runtime/office/quality/document-brief.mjs +44 -0
  122. package/src/runtime/office/quality/inline-audit.mjs +7 -2
  123. package/src/runtime/office/quality/quality-pipeline.mjs +9 -1
  124. package/src/runtime/office/tool-defs.mjs +2 -2
  125. package/src/runtime/shared/llm/quota-value-estimate.mjs +317 -0
  126. package/src/runtime/shared/llm/usage-ledger-quota.mjs +266 -63
  127. package/src/runtime/shared/llm/usage-ledger-rollup.mjs +35 -0
  128. package/src/runtime/shared/llm/usage-ledger-worker.mjs +2 -1
  129. package/src/runtime/shared/llm/usage-ledger.mjs +10 -1
  130. package/src/runtime/shared/provider-accounts.mjs +11 -1
  131. package/src/runtime/shared/statusline/statusline-segments.mjs +4 -4
  132. package/src/runtime/shared/tool-execution-contract.mjs +1 -1
  133. package/src/runtime/shared/wait-until.test-support.mjs +33 -0
  134. package/src/session-runtime/boot/apis.mjs +1 -1
  135. package/src/session-runtime/services/channel-admin.mjs +4 -3
  136. package/src/session-runtime/services/usage-stats-model.mjs +22 -0
  137. package/src/session-runtime/setup-tool/settings-contract.mjs +6 -1
  138. package/src/session-runtime/turn/session-ops.mjs +15 -9
  139. package/src/session-runtime/usage-stats-api.mjs +34 -2
  140. package/src/standalone/agent-dispatch-broker.mjs +1 -1
  141. package/src/standalone/local-session-runtime.mjs +488 -0
  142. package/src/standalone/session-protocol.mjs +1 -0
  143. package/src/standalone/session-runtime-inline-host.mjs +1 -1
  144. package/src/tui/hooks/useSession.mjs +1 -1
  145. package/src/tui/session/session-api/commands.mjs +1 -1
  146. package/src/tui/session/session-api/integrations.mjs +3 -0
  147. package/src/tui/session/session-flow/auto-clear.mjs +6 -7
  148. package/src/tui/session/tool-card-results.mjs +1 -1
  149. package/src/tui/session/turn.mjs +5 -0
  150. package/src/tui/session-local.mjs +3 -488
  151. package/src/tui/session.mjs +1 -1
  152. package/src/ui/statusline-agents.mjs +0 -1
  153. package/src/rules/agent/41-cycle2-agent.md +0 -24
  154. package/src/runtime/memory/lib/cycle-scheduler/cycle2-runs.mjs +0 -120
  155. package/src/runtime/memory/lib/memory-cycle2-mutations.mjs +0 -110
  156. package/src/runtime/memory/lib/memory-cycle2-quarantine.mjs +0 -99
  157. package/src/runtime/memory/lib/memory-cycle2-review.mjs +0 -240
  158. package/src/runtime/memory/lib/memory-cycle2.mjs +0 -191
@@ -15,7 +15,7 @@ import {
15
15
  emitCompactEvent,
16
16
  resolveHandoffSummaryModel,
17
17
  } from './loop/compact-policy.mjs';
18
- import { runFreshContextCompact } from './loop/fresh-context.mjs';
18
+ import { previewFreshContextCompaction, runFreshContextCompact } from './loop/fresh-context.mjs';
19
19
  import { estimateMessagesTokensSafe } from './loop/compact-debug.mjs';
20
20
  import { messagesArrayChanged } from './loop/tool-helpers.mjs';
21
21
  import { normalizeUsage, addUsage } from './loop/usage.mjs';
@@ -72,8 +72,8 @@ function transcriptPrefixHash(messages) {
72
72
  // same event. A pending reactive-overflow retry makes THIS compact pass the
73
73
  // recovery from a provider overflow refusal, not the proactive pressure
74
74
  // trigger — the emitted events are tagged so telemetry can tell them apart.
75
- // An agent whose 5m message cache expired compacts before the cold send
76
- // whatever its size (trigger 'cache_expired').
75
+ // Cache expiry arms a cold-send compact regardless of the threshold, but all
76
+ // proactive triggers still need a smaller predicted transcript.
77
77
  function preSendCompactDecision(state, compactPolicy) {
78
78
  const { messages, sessionRef } = state;
79
79
  const messageTokensEst = estimateMessagesTokensSafe(messages);
@@ -84,24 +84,45 @@ function preSendCompactDecision(state, compactPolicy) {
84
84
  sessionRef,
85
85
  });
86
86
  const cacheExpired = shouldCompactForExpiredAgentCache(sessionRef, state.opts);
87
- const shouldCompact =
87
+ const mediaPressure = shouldCompactForRequestMedia(messages);
88
+ const requireReduction = !reactivePending && !mediaPressure;
89
+ let shouldCompact =
88
90
  state.skipProactiveCompact !== true &&
89
91
  (cacheExpired ||
90
- shouldCompactForRequestMedia(messages) ||
92
+ mediaPressure ||
91
93
  shouldCompactForSession(messageTokensEst, compactPolicy, {
92
94
  forceReactive: reactivePending,
93
95
  messages,
94
96
  sessionRef,
95
97
  pressureTokens,
96
98
  }));
99
+ const compactBudgetTokens = shouldCompact
100
+ ? compactTargetBudget({ ...compactPolicy, pressureTokens }) || compactPolicy.boundaryTokens
101
+ : compactPolicy.boundaryTokens;
102
+ if (shouldCompact && requireReduction) {
103
+ // Price the same Goal reminder the real pass will attach, without marking
104
+ // or acknowledging it on a session whose compaction may be skipped.
105
+ const previewSession = { ...sessionRef };
106
+ markPendingGoalReminder(previewSession, 'compaction');
107
+ const reminder = snapshotPendingGoalReminder(previewSession);
108
+ shouldCompact = previewFreshContextCompaction({
109
+ sessionRef,
110
+ messages,
111
+ compactBudgetTokens,
112
+ compactPolicy,
113
+ sessionId: state.sessionId,
114
+ provider: state.provider,
115
+ goalReminderText: reminder?.content || '',
116
+ activeTurn: true,
117
+ }).reducesTokens;
118
+ }
97
119
  return {
98
120
  messageTokensEst,
99
121
  pressureTokens,
100
122
  shouldCompact,
123
+ requireReduction,
101
124
  compactTrigger: reactivePending ? 'reactive' : cacheExpired ? 'cache_expired' : 'auto',
102
- compactBudgetTokens: shouldCompact
103
- ? compactTargetBudget({ ...compactPolicy, pressureTokens }) || compactPolicy.boundaryTokens
104
- : compactPolicy.boundaryTokens,
125
+ compactBudgetTokens,
105
126
  };
106
127
  }
107
128
 
@@ -243,6 +264,7 @@ async function compactTranscript(ctx, run) {
243
264
  sendOpts: opts,
244
265
  goalReminderText: run.inlineGoalReminder?.content || '',
245
266
  activeTurn: true,
267
+ requireReduction: decision.requireReduction,
246
268
  });
247
269
  const freshMessages = Array.isArray(run.freshContextResult?.messages) ? run.freshContextResult.messages : null;
248
270
  if (!freshMessages) throw new Error('fresh-context compact produced no messages');
@@ -461,6 +483,10 @@ async function compactBeforeSend(ctx) {
461
483
  throwCompactFailure(ctx, run, compactErr);
462
484
  }
463
485
  await setStage(opts, 'requesting');
486
+ if (run.freshContextResult?.skipped) {
487
+ compactTelemetry(ctx, 'pre_send_check', { skipReason: 'no_token_reduction' });
488
+ return;
489
+ }
464
490
  ctx.compactChanged = messagesArrayChanged(messages, run.compacted);
465
491
  if (ctx.compactChanged) adoptCompactedTranscript(ctx, run);
466
492
  reportCompactOutcome(ctx, run);
@@ -190,10 +190,12 @@ function buildPreview(text, maxChars = TOOL_RESULT_PREVIEW_CHARS) {
190
190
  };
191
191
  }
192
192
 
193
- function artifactMeta(sessionId, toolCallId, channel, content) {
193
+ function artifactMeta(sessionId, toolCallId, channel, content, preview = false) {
194
194
  if (!sessionId || !toolCallId || typeof content !== 'string') return null;
195
195
  const sha256 = createHash('sha256').update(content, 'utf8').digest('hex');
196
- const dir = ensureToolResultsDir(sessionId);
196
+ const dir = preview
197
+ ? join(getPluginData(), 'tool-results', safeSessionSegment(sessionId))
198
+ : ensureToolResultsDir(sessionId);
197
199
  return {
198
200
  stream: channel,
199
201
  path: join(dir, artifactIdentity(sha256)),
@@ -208,6 +210,12 @@ function artifactShapeMatches(meta, info) {
208
210
  return info.isFile() && info.size === meta.bytes;
209
211
  }
210
212
 
213
+ // Same content-addressed reference as persistence, without creating a directory
214
+ // or a file. Compaction previews must not archive a transcript they will keep.
215
+ export function previewToolResultArtifact({ sessionId, toolCallId, channel = 'result', content } = {}) {
216
+ return artifactMeta(sessionId, toolCallId, channel, content, true);
217
+ }
218
+
211
219
  export function persistToolResultArtifactSync({ sessionId, toolCallId, channel = 'result', content } = {}) {
212
220
  let meta;
213
221
  try {
@@ -2,7 +2,7 @@
2
2
  * src/tui/session/agent-envelope.mjs - parse agent/background-task/shell
3
3
  * notification envelopes into synthetic tool-item shapes, and derive
4
4
  * status/result text. parseBackgroundTaskEnvelope
5
- * remains part of session-local.mjs's public surface.
5
+ * remains part of local-session-runtime.mjs's public surface.
6
6
  */
7
7
  import { isBackgroundErrorOnlyBody } from '../../../../shared/err-text.mjs';
8
8
  import { textBetweenTag } from '../../../../shared/tool-result-summary.mjs';
@@ -66,6 +66,7 @@ function restoredAssistantTranscriptItems(message, nextId) {
66
66
  kind: 'turndone',
67
67
  id: nextId(),
68
68
  ...completion,
69
+ ...(completion.status === 'done' ? { finalAssistantId: items[0].id } : {}),
69
70
  ...(metadata.at ? { at: metadata.at } : {}),
70
71
  });
71
72
  }
@@ -619,7 +619,9 @@ export function preflightPowerShellHygiene(command, { shellType, shellName } = {
619
619
  const POWERSHELL_ONLY_SYNTAX = [
620
620
  /\$(?:null|true|false|env:|_\b|args\b|host\b|profile\b|pwd\b|psversiontable\b|psscriptroot\b|lastexitcode\b|erroractionpreference\b)/i,
621
621
  /\$[A-Za-z_]\w*\s*=/,
622
- /\b(?:get|set|new|remove|select|where|foreach|invoke|out|write|start|stop|test|measure|sort|join|split|convert|import|export|add|copy|move|rename|resolve|compare|clear|push|pop)-[A-Za-z]+\b/i,
622
+ // A verb joined to the previous character by a path/word char (`mixdog-test-scratch`, `a/test-x`) is part of a
623
+ // path or name, not a cmdlet.
624
+ /(?<![\w\-./\\:])(?:get|set|new|remove|select|where|foreach|invoke|out|write|start|stop|test|measure|sort|join|split|convert|import|export|add|copy|move|rename|resolve|compare|clear|push|pop)-[A-Za-z]+\b/i,
623
625
  /\[[A-Za-z_][\w.]*\]::/,
624
626
  /(?:^|\s)-(?:eq|ne|gt|lt|ge|le|match|notmatch|like|notlike|contains|replace|not|and|or|is|as|ErrorAction|Recurse|Force|Encoding|TotalCount|Tail|Pattern|Path|LiteralPath)\b/,
625
627
  /2>\s*\$/,
@@ -48,13 +48,17 @@ function pageBodyText(content) {
48
48
  if (typeof item?.str !== 'string') continue;
49
49
  if (item.str) {
50
50
  const placement = runPlacement(item);
51
+ // A run on another baseline is another line even when the writer marked no line end (a browser's
52
+ // print does not): "784" over its label read as "784office". A baseline shift under half the
53
+ // smaller run's size (a superscript, a mixed-size run) stays on the line.
54
+ const shift = placement && cursor ? Math.abs(placement.line - cursor.line) : 0;
55
+ const newLine = shift > Math.min(placement?.size || 0, cursor?.size || 0) * 0.5;
56
+ if (newLine && body && !body.endsWith('\n')) body += '\n';
51
57
  // A writer splits one word into several runs for kerning, and a
52
58
  // Korean line into a run per token; joining those with a space
53
59
  // invents "2026 년". Only a gap the page itself leaves is a space.
54
60
  const separated =
55
- placement && cursor && placement.line === cursor.line
56
- ? placement.start - cursor.end > cursor.size * 0.22
57
- : !placement || !cursor;
61
+ placement && cursor && !newLine ? placement.start - cursor.end > cursor.size * 0.22 : !placement || !cursor;
58
62
  const glued = !body || body.endsWith('\n') || body.endsWith(' ') || item.str.startsWith(' ') || !separated;
59
63
  body += (glued ? '' : ' ') + item.str;
60
64
  cursor = placement;
@@ -411,7 +411,7 @@ function computerToolResult(value, args) {
411
411
  }
412
412
  return {
413
413
  content,
414
- ...(canonicalComputerResultIsError(text, args) ? { isError: true } : {}),
414
+ ...(value.isError === true || canonicalComputerResultIsError(text, args) ? { isError: true } : {}),
415
415
  };
416
416
  }
417
417
 
@@ -51,7 +51,7 @@ import {
51
51
  shutdownEmbeddingProvider,
52
52
  warmupEmbeddingProvider,
53
53
  } from './lib/embedding-provider.mjs';
54
- import { runCycle1, runCycle2, parseInterval, flushEmbeddingDirty, flushRawEmbeddings } from './lib/memory-cycle.mjs';
54
+ import { runCycle1, parseInterval, flushEmbeddingDirty, flushRawEmbeddings } from './lib/memory-cycle.mjs';
55
55
  import { callAgentDispatch } from './lib/agent-ipc.mjs';
56
56
  import {
57
57
  cancelCoalescedCycleRetries,
@@ -73,7 +73,7 @@ import {
73
73
  import { writeJsonAtomicSync } from '../shared/atomic-file.mjs';
74
74
  import { safeIpcSend } from '../shared/safe-ipc-send.mjs';
75
75
  import { resolvePluginData, mixdogHome } from '../shared/plugin-paths.mjs';
76
- import { scheduledCycle1Signature, scheduledCycle2Signature } from './lib/cycle-signatures.mjs';
76
+ import { scheduledCycle1Signature } from './lib/cycle-signatures.mjs';
77
77
  import { createTranscriptIngest } from './lib/transcript-ingest.mjs';
78
78
  import { createCycleLlmAdapters } from './lib/cycle-llm-adapters.mjs';
79
79
  import { createCycleScheduler } from './lib/cycle-scheduler.mjs';
@@ -333,20 +333,15 @@ async function getCycleLastRun() {
333
333
  const obj = JSON.parse(raw);
334
334
  return {
335
335
  cycle1: Number(obj.cycle1) || 0,
336
- cycle2: Number(obj.cycle2) || 0,
337
336
  // Heartbeat (every attempt, success or skip) is tracked separately from
338
337
  // the success timestamps above so a long string of failed/skipped runs
339
338
  // cannot disguise itself as a healthy keeper.
340
339
  cycle1_heartbeat: Number(obj.cycle1_heartbeat) || 0,
341
- // Last cycle2 failure message; cleared to '' on success.
342
- cycle2_last_error: typeof obj.cycle2_last_error === 'string' ? obj.cycle2_last_error : '',
343
340
  };
344
341
  } catch {
345
342
  return {
346
343
  cycle1: 0,
347
- cycle2: 0,
348
344
  cycle1_heartbeat: 0,
349
- cycle2_last_error: '',
350
345
  };
351
346
  }
352
347
  }
@@ -373,7 +368,7 @@ async function refreshCoreMemorySnapshot(reason = 'mutation') {
373
368
  const CYCLE_STATE_FILE = path.join(DATA_DIR, 'memory-cycle-state.json');
374
369
 
375
370
  const _cycleLlmAdapters = createCycleLlmAdapters({ callAgentDispatch });
376
- const { getCycle1CallLlm, getCycle2CallLlm } = _cycleLlmAdapters;
371
+ const { getCycle1CallLlm } = _cycleLlmAdapters;
377
372
 
378
373
  const _cycleScheduler = createCycleScheduler({
379
374
  getDb: () => db,
@@ -388,9 +383,7 @@ const _cycleScheduler = createCycleScheduler({
388
383
  readMainConfig,
389
384
  memoryCyclesEnabled,
390
385
  getCycle1CallLlm,
391
- getCycle2CallLlm,
392
386
  runCycle1,
393
- runCycle2,
394
387
  parseInterval,
395
388
  flushRawEmbeddings,
396
389
  claimAndMarkScheduledCycle,
@@ -398,13 +391,11 @@ const _cycleScheduler = createCycleScheduler({
398
391
  scheduleCoalescedCycleRetry,
399
392
  cancelCoalescedCycleRetries,
400
393
  scheduledCycle1Signature,
401
- scheduledCycle2Signature,
402
394
  cycleStateFile: CYCLE_STATE_FILE,
403
395
  });
404
- // Cycle1 run primitives + cycle2 finalize used by MCP action handlers below.
396
+ // Cycle1 run primitives used by MCP action handlers below.
405
397
  const _startCycle1Run = _cycleScheduler.startCycle1Run;
406
398
  const _awaitCycle1Run = _cycleScheduler.awaitCycle1Run;
407
- const _finalizeCycle2Run = _cycleScheduler.finalizeCycle2Run;
408
399
 
409
400
  // Transcript watcher lifecycle stays in the facade (owns _transcriptIngest);
410
401
  // the cycle tick loop start/stop is delegated to the scheduler.
@@ -509,10 +500,8 @@ const _actionHandlers = createMemoryActionHandlers({
509
500
  dumpSessionRootChunks,
510
501
  awaitCycle1Run: _awaitCycle1Run,
511
502
  startCycle1Run: _startCycle1Run,
512
- finalizeCycle2Run: _finalizeCycle2Run,
513
503
  refreshCoreMemoryFile: refreshCoreMemorySnapshot,
514
504
  getSchedulerCycle1InFlight: () => _cycleScheduler.getCycle1InFlight(),
515
- getCycle2CallLlm,
516
505
  ingestTranscriptFile,
517
506
  cwdFromTranscriptPath,
518
507
  });
@@ -9,7 +9,7 @@ import { getDatabase, embeddingToSql } from './memory.mjs';
9
9
  import { VALID_CATEGORY } from './memory-categories.mjs';
10
10
  import { cachedEmbedTextBatch } from './memory-embed.mjs';
11
11
  import { checkedConnect } from './pg/adapter.mjs';
12
- import { throwIfAborted } from './memory-cycle2-shared.mjs';
12
+ import { throwIfAborted } from './memory-cycle-shared.mjs';
13
13
  import { findCoreKeyRows } from './core-memory-uniqueness.mjs';
14
14
 
15
15
  const CORE_ELEMENT_DERIVE_LENGTH = 40;
@@ -30,9 +30,7 @@ export function createCycleLlmAdapters({ callAgentDispatch }) {
30
30
  // unhandled rejection that killed the memory runtime. Keep the factory
31
31
  // contract: each getter returns the (memoized) adapter function.
32
32
  const cycle1 = buildAdapter('cycle1-agent');
33
- const cycle2 = buildAdapter('cycle2-agent');
34
33
  return {
35
34
  getCycle1CallLlm: () => cycle1,
36
- getCycle2CallLlm: () => cycle2,
37
35
  };
38
36
  }
@@ -6,13 +6,6 @@ async function countRows(db, sql, params) {
6
6
  return Number((await db.query(sql, params)).rows[0]?.c ?? 0);
7
7
  }
8
8
 
9
- export function countPendingCycle2Roots(db) {
10
- return countRows(
11
- db,
12
- `SELECT COUNT(*) c FROM entries WHERE is_root = 1 AND cycle2_reviewed_at IS NULL AND duplicate_of IS NULL`
13
- );
14
- }
15
-
16
9
  // Per-tick backlog counts for the state file / statusline, the backlog
17
10
  // warning, and the opportunistic raw-embedding flush while rows are unchunked.
18
11
  export function createBacklogProbe({ getDb, ledger, log, flushRawEmbeddings }) {
@@ -46,10 +39,9 @@ export function createBacklogProbe({ getDb, ledger, log, flushRawEmbeddings }) {
46
39
  AND (reviewed_at IS NULL OR reviewed_at < $1)`,
47
40
  [now - CYCLE1_OMITTED_COOLDOWN_MS]
48
41
  );
49
- const cycle2Pending = await countPendingCycle2Roots(db);
50
- ledger.setBacklog({ unchunked, unchunked_eligible: unchunkedEligible, cycle2_pending: cycle2Pending, at: now });
51
- if (unchunked > BACKLOG_WARN_PENDING || cycle2Pending > BACKLOG_WARN_PENDING) {
52
- ledger.warn(`backlog unchunked=${unchunked} eligible=${unchunkedEligible} cycle2_pending=${cycle2Pending}`);
42
+ ledger.setBacklog({ unchunked, unchunked_eligible: unchunkedEligible, at: now });
43
+ if (unchunked > BACKLOG_WARN_PENDING) {
44
+ ledger.warn(`backlog unchunked=${unchunked} eligible=${unchunkedEligible}`);
53
45
  }
54
46
  if (unchunked > 0) flushRawEmbeddingsOnce(db);
55
47
  } catch {
@@ -9,10 +9,9 @@ const BACKLOG_WARN_FAILURES = 5;
9
9
  export function createCycleHealthLedger({ cycleStateFile, log }) {
10
10
  const health = {
11
11
  cycle1: { last_success_at: 0, last_error_at: 0, last_error: null, consecutive_failures: 0 },
12
- cycle2: { last_success_at: 0, last_error_at: 0, last_error: null, consecutive_failures: 0 },
13
12
  };
14
13
  let running = null; // { cycle, started_at, pid }
15
- let backlog = { unchunked: 0, cycle2_pending: 0, at: 0 };
14
+ let backlog = { unchunked: 0, at: 0 };
16
15
  let lastWarnAt = 0;
17
16
 
18
17
  function write() {
@@ -74,7 +73,6 @@ export function createCycleHealthLedger({ cycleStateFile, log }) {
74
73
  // state file reports 0 until the next run.
75
74
  function hydrateSuccess(last) {
76
75
  if (last?.cycle1 > 0 && !health.cycle1.last_success_at) health.cycle1.last_success_at = last.cycle1;
77
- if (last?.cycle2 > 0 && !health.cycle2.last_success_at) health.cycle2.last_success_at = last.cycle2;
78
76
  write();
79
77
  }
80
78
 
@@ -5,9 +5,7 @@ export function createScheduledEnqueue({
5
5
  getConfig,
6
6
  claimAndMarkScheduledCycle,
7
7
  scheduledCycle1Signature,
8
- scheduledCycle2Signature,
9
8
  scheduleScheduledCycle1,
10
- scheduleScheduledCycle2,
11
9
  }) {
12
10
  function periodicCycle1Config() {
13
11
  return {
@@ -38,13 +36,5 @@ export function createScheduledEnqueue({
38
36
  }
39
37
  }
40
38
 
41
- async function enqueueScheduledCycle2(intervalMs) {
42
- const config = getConfig()?.cycle2 || {};
43
- const signature = scheduledCycle2Signature(config);
44
- if (await claimScheduledSlot('cycle2', intervalMs, signature, config)) {
45
- scheduleScheduledCycle2(config, signature);
46
- }
47
- }
48
-
49
- return { periodicCycle1Config, enqueueScheduledCycle1, enqueueScheduledCycle2 };
39
+ return { periodicCycle1Config, enqueueScheduledCycle1 };
50
40
  }
@@ -30,12 +30,10 @@ export function createCycleTickLoop({
30
30
  setConfig(mainConfig);
31
31
  const cyclesOn = memoryCyclesEnabled();
32
32
  const cycle1Ms = parseInterval(mainConfig?.cycle1?.interval || '10m');
33
- const cycle2Ms = parseInterval(mainConfig?.cycle2?.interval || '1h');
34
33
  const now = Date.now();
35
34
  const last = await getCycleLastRun();
36
35
  if (cyclesOn) {
37
36
  if (periodicCycleDue(last.cycle1, startedAt, cycle1Ms, now)) await enqueue.enqueueScheduledCycle1(cycle1Ms);
38
- if (periodicCycleDue(last.cycle2, startedAt, cycle2Ms, now)) await enqueue.enqueueScheduledCycle2(cycle2Ms);
39
37
  }
40
38
  await probeBacklog(now);
41
39
  }
@@ -2,7 +2,7 @@
2
2
  //
3
3
  // Owns the mutually-referential cycle machinery: the cycle-health ledger and
4
4
  // run-state file, the cycle1 outer coalesce layer, the scheduled enqueue /
5
- // retry paths for cycle1/2, checkCycles(), and the self-rescheduling tick
5
+ // retry paths for cycle1, checkCycles(), and the self-rescheduling tick
6
6
  // loop. The phases live under cycle-scheduler/. index.mjs keeps lifecycle
7
7
  // ownership by injecting live getters (getDb/getConfig/setConfig) plus the
8
8
  // cycle runners and LLM adapters.
@@ -15,15 +15,14 @@
15
15
  // log -> __mixdogMemoryLog
16
16
  // getCycleLastRun / setCycleLastRun -> meta-backed cycle timestamps
17
17
  // readMainConfig / memoryCyclesEnabled -> config-flag helpers
18
- // getCycle{1,2}CallLlm -> in-process LLM adapters
19
- // runCycle1 / runCycle2 / parseInterval / flushRawEmbeddings
18
+ // getCycle1CallLlm -> in-process LLM adapter
19
+ // runCycle1 / parseInterval / flushRawEmbeddings
20
20
  // claimAndMarkScheduledCycle / resolveCoalesceMaxRetries /
21
21
  // scheduleCoalescedCycleRetry -> coalesced queue primitives
22
- // scheduledCycle{1,2}Signature -> queue signatures
22
+ // scheduledCycle1Signature -> queue signature
23
23
  // cycleStateFile -> path to memory-cycle-state.json
24
24
  import { createCycleHealthLedger } from './cycle-scheduler/health-ledger.mjs';
25
25
  import { createCycle1Runs } from './cycle-scheduler/cycle1-runs.mjs';
26
- import { createCycle2Runs } from './cycle-scheduler/cycle2-runs.mjs';
27
26
  import { createScheduledEnqueue } from './cycle-scheduler/scheduled-enqueue.mjs';
28
27
  import { createBacklogProbe } from './cycle-scheduler/backlog-probe.mjs';
29
28
  import { createCycleTickLoop } from './cycle-scheduler/tick-loop.mjs';
@@ -42,9 +41,7 @@ export function createCycleScheduler(deps) {
42
41
  readMainConfig,
43
42
  memoryCyclesEnabled,
44
43
  getCycle1CallLlm,
45
- getCycle2CallLlm,
46
44
  runCycle1,
47
- runCycle2,
48
45
  parseInterval,
49
46
  flushRawEmbeddings,
50
47
  claimAndMarkScheduledCycle,
@@ -52,7 +49,6 @@ export function createCycleScheduler(deps) {
52
49
  scheduleCoalescedCycleRetry,
53
50
  cancelCoalescedCycleRetries,
54
51
  scheduledCycle1Signature,
55
- scheduledCycle2Signature,
56
52
  cycleStateFile,
57
53
  } = deps;
58
54
 
@@ -68,15 +64,12 @@ export function createCycleScheduler(deps) {
68
64
  setCycleLastRun,
69
65
  ...queue,
70
66
  });
71
- const cycle2 = createCycle2Runs({ ledger, getDb, log, getCycle2CallLlm, runCycle2, setCycleLastRun, ...queue });
72
67
  const enqueue = createScheduledEnqueue({
73
68
  getDb,
74
69
  getConfig,
75
70
  claimAndMarkScheduledCycle,
76
71
  scheduledCycle1Signature,
77
- scheduledCycle2Signature,
78
72
  scheduleScheduledCycle1: cycle1.scheduleScheduledCycle1,
79
- scheduleScheduledCycle2: cycle2.scheduleScheduledCycle2,
80
73
  });
81
74
  const backlog = createBacklogProbe({ getDb, ledger, log, flushRawEmbeddings });
82
75
  const tick = createCycleTickLoop({
@@ -97,7 +90,6 @@ export function createCycleScheduler(deps) {
97
90
  // running state.
98
91
  function resetInFlight() {
99
92
  cycle1.reset();
100
- cycle2.reset();
101
93
  backlog.reset();
102
94
  tick.reset();
103
95
  ledger.resetRunning();
@@ -113,7 +105,6 @@ export function createCycleScheduler(deps) {
113
105
  // run primitives used by MCP action handlers
114
106
  startCycle1Run: cycle1.startCycle1Run,
115
107
  awaitCycle1Run: cycle1.awaitCycle1Run,
116
- finalizeCycle2Run: cycle2.finalizeCycle2Run,
117
108
  periodicCycle1Config: enqueue.periodicCycle1Config,
118
109
  // lifecycle
119
110
  startCycles: tick.start,
@@ -11,9 +11,3 @@ export function scheduledCycle1Signature(config) {
11
11
  maxConcurrent: undefined,
12
12
  });
13
13
  }
14
-
15
- export function scheduledCycle2Signature(config) {
16
- return makeCycleRequestSignature('cycle2', config, {
17
- concurrency: undefined,
18
- });
19
- }
@@ -3,7 +3,7 @@
3
3
  // session fetch with its starvation backfill, session grouping, and the
4
4
  // terminal / omitted sentinel updates.
5
5
  import { __mixdogMemoryLog } from '../memory-log.mjs';
6
- import { throwIfAborted } from '../memory-cycle2-shared.mjs';
6
+ import { throwIfAborted } from '../memory-cycle-shared.mjs';
7
7
  import { CYCLE1_OMITTED_COOLDOWN_MS } from './cycle1-plan.mjs';
8
8
 
9
9
  export function isStructurallyUnchunkableInput(row) {
@@ -3,7 +3,7 @@
3
3
  // through the LLM, commit each chunk as one transaction, and mark what was
4
4
  // left out. Rows within the window are one session in chronological order.
5
5
  import { __mixdogMemoryLog } from '../memory-log.mjs';
6
- import { throwIfAborted } from '../memory-cycle2-shared.mjs';
6
+ import { throwIfAborted } from '../memory-cycle-shared.mjs';
7
7
  import { assessChunkQuality, generateCycle1Chunks } from '../memory-chunk-quality.mjs';
8
8
  import { inferChunkProjectId, syncRootEmbedding } from '../memory-embed.mjs';
9
9
  import { isStructurallyUnchunkableInput, markOmittedRows, markTerminalRows, selectRootId } from './cycle1-rows.mjs';
@@ -42,7 +42,7 @@ async function commitCycle1Chunk(db, chunk, rootId, memberIds) {
42
42
  `UPDATE entries
43
43
  SET chunk_root = $1, is_root = 1, element = $2, category = $3, summary = $4,
44
44
  status = 'pending', project_id = $5,
45
- last_seen_at = $7, chunk_quality = $8::jsonb, cycle2_reviewed_at = NULL, duplicate_of = NULL
45
+ last_seen_at = $7, chunk_quality = $8::jsonb, duplicate_of = NULL
46
46
  WHERE id = $6`,
47
47
  [rootId, element, category, summary, projectId, rootId, Date.now(), JSON.stringify(quality)]
48
48
  );
@@ -1,4 +1,4 @@
1
- import { throwIfAborted } from './memory-cycle2-shared.mjs';
1
+ import { throwIfAborted } from './memory-cycle-shared.mjs';
2
2
 
3
3
  const DEFAULT_PASS_PAUSE_MS = 1_000;
4
4
 
@@ -60,7 +60,6 @@ export function createLifecycleRoutes({
60
60
  active_roots: stats.active_roots,
61
61
  archived_roots: stats.archived_roots,
62
62
  unchunked_leaves: stats.unchunked_leaves,
63
- cycle2_pending_roots: stats.cycle2_pending_roots,
64
63
  core_entries: stats.core_entries,
65
64
  core_embed_null: stats.core_embed_null,
66
65
  cycle_running: cycleScheduler.getCycleRunning(),
@@ -1,11 +1,11 @@
1
1
  /**
2
2
  * memory-action-handlers/cycle-actions.mjs — the cycle-driven memory actions:
3
- * cycle1, cycle2/sleep, flush, rebuild and backfill. Cycle scheduler
4
- * primitives and the cycle2 LLM adapter are injected; the whole-action
3
+ * cycle1, flush, rebuild and backfill. Cycle scheduler
4
+ * primitives are injected; the whole-action
5
5
  * backfill mutex lives here since it only guards this module's backfill path.
6
6
  */
7
- import { runCycle2 } from '../memory-cycle.mjs';
8
- import { throwIfAborted } from '../memory-cycle2-shared.mjs';
7
+ import { flushSearchEmbeddings } from '../memory-cycle.mjs';
8
+ import { throwIfAborted } from '../memory-cycle-shared.mjs';
9
9
  import { createBackfillAction } from './cycle-backfill-action.mjs';
10
10
  import { createRebuildAction } from './cycle-rebuild-action.mjs';
11
11
 
@@ -56,41 +56,15 @@ function cycle1SummaryText(result) {
56
56
  );
57
57
  }
58
58
 
59
- function cycle2SummaryResult(result) {
60
- const counts = {
61
- processed: result?.processed || 0,
62
- merged: result?.merged || 0,
63
- linked: result?.linked || 0,
64
- kept: result?.kept || 0,
65
- held: result?.held || 0,
66
- deferred: result?.deferred || 0,
67
- };
68
- const parts = Object.entries(counts)
69
- .filter(([, v]) => v > 0)
70
- .map(([k, v]) => `${k}=${v}`);
71
- if (result?.ok === false)
72
- return { text: `cycle2 failed: ${result.error || 'unknown'} ${parts.join(' ')}`.trim(), isError: true };
73
- if (parts.length) return { text: `cycle2 ${parts.join(' ')}` };
74
- // No applied counts — distinguish an in-flight skip from an empty queue.
75
- let cause = '';
76
- if (result?.skippedInFlight) cause = ' (skipped: in-flight)';
77
- return { text: `cycle2 noop${cause}` };
78
- }
79
-
80
59
  export function createCycleActions({
81
60
  getDb,
82
61
  dataDir,
83
62
  awaitCycle1Run,
84
63
  startCycle1Run,
85
- finalizeCycle2Run,
86
64
  getSchedulerCycle1InFlight,
87
- getCycle2CallLlm,
88
65
  ingestTranscriptFile,
89
66
  cwdFromTranscriptPath,
90
67
  }) {
91
- const withCycle2Llm = (options) =>
92
- typeof options.callLlm === 'function' ? options : { ...options, callLlm: getCycle2CallLlm() };
93
-
94
68
  async function cycle1(args, config, signal) {
95
69
  const cycle1Config = cycle1ConfigFromArgs(args, config?.cycle1 || {});
96
70
  const callerDeadlineMs = Number(args?._callerDeadlineMs) || 0;
@@ -104,50 +78,31 @@ export function createCycleActions({
104
78
  return { ...result, text: cycle1SummaryText(result) };
105
79
  }
106
80
 
107
- async function cycle2(args, config, signal) {
108
- const db = getDb();
109
- throwIfAborted(signal);
110
- const cycle2Config = { ...(config?.cycle2 || {}) };
111
- if (Number.isFinite(Number(args?.batch_size))) {
112
- cycle2Config.batch_size = Math.max(1, Math.floor(Number(args.batch_size)));
113
- }
114
- const result = await runCycle2(db, cycle2Config, withCycle2Llm({ signal }));
115
- throwIfAborted(signal);
116
- await finalizeCycle2Run(result);
117
- return cycle2SummaryResult(result);
118
- }
119
-
120
81
  async function flush(_args, config, signal) {
121
82
  const db = getDb();
122
83
  throwIfAborted(signal);
123
84
  const r1 = await awaitCycle1Run(config?.cycle1 || {}, { signal });
124
85
  throwIfAborted(signal);
125
- const r2 = await runCycle2(db, config?.cycle2 || {}, withCycle2Llm({ signal }));
86
+ const embeddings = await flushSearchEmbeddings(db, { signal });
126
87
  throwIfAborted(signal);
127
- await finalizeCycle2Run(r2);
128
88
  return {
129
- text: `flush: cycle1 chunks=${r1.chunks} processed=${r1.processed}, cycle2 ${JSON.stringify(r2)}`,
130
- isError: r2.ok === false,
89
+ text: `flush: cycle1 chunks=${r1.chunks} processed=${r1.processed}, embeddings=${embeddings.succeeded}`,
131
90
  };
132
91
  }
133
92
 
134
93
  const rebuild = createRebuildAction({
135
94
  getDb,
136
95
  startCycle1Run,
137
- finalizeCycle2Run,
138
96
  getSchedulerCycle1InFlight,
139
- withCycle2Llm,
140
97
  });
141
98
 
142
99
  const backfill = createBackfillAction({
143
100
  getDb,
144
101
  dataDir,
145
102
  awaitCycle1Run,
146
- finalizeCycle2Run,
147
- withCycle2Llm,
148
103
  ingestTranscriptFile,
149
104
  cwdFromTranscriptPath,
150
105
  });
151
106
 
152
- return { cycle1, cycle2, flush, rebuild, backfill };
107
+ return { cycle1, flush, rebuild, backfill };
153
108
  }