@gajae-code/coding-agent 0.12.0 → 0.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (223) hide show
  1. package/CHANGELOG.md +82 -1
  2. package/dist/types/async/job-manager.d.ts +17 -3
  3. package/dist/types/config/settings-schema.d.ts +54 -0
  4. package/dist/types/exa/mcp-client.d.ts +10 -1
  5. package/dist/types/exec/bash-executor.d.ts +45 -12
  6. package/dist/types/extensibility/extensions/types.d.ts +16 -2
  7. package/dist/types/extensibility/gjc-plugins/index.d.ts +12 -2
  8. package/dist/types/extensibility/gjc-plugins/installer.d.ts +63 -7
  9. package/dist/types/extensibility/gjc-plugins/lifecycle-reconciliation.d.ts +55 -0
  10. package/dist/types/extensibility/gjc-plugins/lifecycle.d.ts +64 -0
  11. package/dist/types/extensibility/gjc-plugins/runtime-quarantine.d.ts +67 -0
  12. package/dist/types/extensibility/gjc-plugins/session-validation.d.ts +3 -1
  13. package/dist/types/extensibility/gjc-plugins/types.d.ts +124 -0
  14. package/dist/types/gjc-runtime/launch-tmux.d.ts +1 -0
  15. package/dist/types/gjc-runtime/ralplan-runtime.d.ts +18 -0
  16. package/dist/types/gjc-runtime/team-launch.d.ts +1 -1
  17. package/dist/types/gjc-runtime/team-runtime.d.ts +25 -0
  18. package/dist/types/gjc-runtime/team-worker-heartbeat.d.ts +43 -0
  19. package/dist/types/gjc-runtime/tmux-owner-isolation.d.ts +10 -0
  20. package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +31 -80
  21. package/dist/types/modes/acp/acp-agent.d.ts +2 -19
  22. package/dist/types/modes/components/gjc-bundle-settings.d.ts +34 -0
  23. package/dist/types/modes/components/notifications-settings-editor.d.ts +1 -0
  24. package/dist/types/modes/components/session-observer-overlay.d.ts +18 -0
  25. package/dist/types/modes/components/settings-selector.d.ts +9 -0
  26. package/dist/types/modes/components/status-line/gh.d.ts +5 -0
  27. package/dist/types/modes/components/transcript-viewer-overlay.d.ts +18 -1
  28. package/dist/types/reminders/star-reminder.d.ts +3 -13
  29. package/dist/types/runtime-mcp/manager.d.ts +1 -0
  30. package/dist/types/sdk/acp/adapter.d.ts +3 -1
  31. package/dist/types/sdk/broker/transport.d.ts +2 -0
  32. package/dist/types/sdk/bus/attachment-registry.d.ts +1 -0
  33. package/dist/types/sdk/bus/chat-daemon-control.d.ts +4 -1
  34. package/dist/types/sdk/bus/config.d.ts +6 -2
  35. package/dist/types/sdk/bus/index.d.ts +29 -0
  36. package/dist/types/sdk/bus/kind-aware-reconciliation.d.ts +8 -1
  37. package/dist/types/sdk/bus/lifecycle-control-runtime.d.ts +4 -0
  38. package/dist/types/sdk/bus/reconciliation-store.d.ts +7 -3
  39. package/dist/types/sdk/bus/rich-draft.d.ts +1 -0
  40. package/dist/types/sdk/bus/rich-render.d.ts +2 -0
  41. package/dist/types/sdk/bus/telegram-adoption-intent.d.ts +165 -0
  42. package/dist/types/sdk/bus/telegram-cli.d.ts +12 -0
  43. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +11 -4
  44. package/dist/types/sdk/bus/telegram-daemon.d.ts +25 -1
  45. package/dist/types/sdk/bus/telegram-reference.d.ts +11 -1
  46. package/dist/types/sdk/bus/threaded-render.d.ts +3 -2
  47. package/dist/types/sdk/bus/topic-registry.d.ts +11 -1
  48. package/dist/types/sdk/host/query/revision-store.d.ts +2 -0
  49. package/dist/types/sdk/host/reverse-leases.d.ts +1 -1
  50. package/dist/types/sdk/prompt-status.d.ts +23 -3
  51. package/dist/types/sdk/session.d.ts +6 -0
  52. package/dist/types/session/agent-session.d.ts +38 -2
  53. package/dist/types/session/artifacts.d.ts +8 -0
  54. package/dist/types/session/blob-store.d.ts +57 -4
  55. package/dist/types/session/internal/managed-session-storage.d.ts +8 -1
  56. package/dist/types/session/session-manager.d.ts +23 -6
  57. package/dist/types/session/session-storage.d.ts +4 -0
  58. package/dist/types/session/streaming-output.d.ts +36 -7
  59. package/dist/types/setup/credential-import.d.ts +12 -0
  60. package/dist/types/skill-state/active-state.d.ts +12 -0
  61. package/dist/types/skill-state/workflow-hud.d.ts +6 -0
  62. package/dist/types/task/executor.d.ts +3 -2
  63. package/dist/types/task/index.d.ts +3 -1
  64. package/dist/types/task/provider-retry-status.d.ts +8 -0
  65. package/dist/types/task/receipt.d.ts +7 -1
  66. package/dist/types/task/types.d.ts +23 -0
  67. package/dist/types/tools/ask-answer-registry.d.ts +2 -2
  68. package/dist/types/tools/bash-interactive.d.ts +4 -1
  69. package/dist/types/tools/bash.d.ts +3 -1
  70. package/dist/types/tools/image-gen.d.ts +4 -0
  71. package/dist/types/tools/index.d.ts +4 -0
  72. package/dist/types/tools/output-meta.d.ts +23 -2
  73. package/dist/types/tools/path-utils.d.ts +1 -0
  74. package/dist/types/tools/read.d.ts +0 -6
  75. package/dist/types/tools/review.d.ts +5 -7
  76. package/dist/types/tools/subagent.d.ts +2 -0
  77. package/dist/types/utils/gh.d.ts +13 -0
  78. package/dist/types/utils/image-resize.d.ts +1 -0
  79. package/dist/types/web/search/providers/kimi.d.ts +2 -0
  80. package/dist/types/web/search/providers/searxng.d.ts +7 -0
  81. package/dist/types/web/search/providers/xai.d.ts +2 -0
  82. package/package.json +10 -8
  83. package/scripts/acp-conformance-agent.ts +218 -0
  84. package/scripts/capture-gjc-bundle-settings.ts +306 -0
  85. package/scripts/generate-sdk-operation-inventory.ts +3 -0
  86. package/scripts/resident-memory-bench.ts +1341 -0
  87. package/scripts/run-acp-conformance.ts +285 -0
  88. package/src/async/job-manager.ts +78 -20
  89. package/src/cli/fast-help.ts +1 -1
  90. package/src/cli/plugin-cli.ts +176 -18
  91. package/src/commands/team.ts +19 -1
  92. package/src/config/file-lock.ts +11 -2
  93. package/src/config/settings-schema.ts +51 -0
  94. package/src/coordinator-mcp/question-gate-codec.ts +1 -1
  95. package/src/coordinator-mcp/server.ts +5 -12
  96. package/src/defaults/gjc/skills/deep-interview/SKILL.md +1 -0
  97. package/src/defaults/gjc/skills/ralplan/SKILL.md +19 -16
  98. package/src/defaults/gjc/skills/team/SKILL.md +2 -0
  99. package/src/defaults/gjc/skills/ultragoal/SKILL.md +37 -24
  100. package/src/defaults/gjc/skills/ultragoal/validation-batch-contracts.md +12 -0
  101. package/src/defaults/gjc-defaults.ts +4 -4
  102. package/src/exa/mcp-client.ts +12 -3
  103. package/src/exec/bash-executor.ts +144 -27
  104. package/src/extensibility/extensions/runner.ts +15 -0
  105. package/src/extensibility/extensions/types.ts +18 -1
  106. package/src/extensibility/gjc-plugins/constrained-hooks.ts +8 -2
  107. package/src/extensibility/gjc-plugins/index.ts +19 -2
  108. package/src/extensibility/gjc-plugins/installer.ts +189 -50
  109. package/src/extensibility/gjc-plugins/lifecycle-reconciliation.ts +199 -0
  110. package/src/extensibility/gjc-plugins/lifecycle.ts +626 -0
  111. package/src/extensibility/gjc-plugins/observability.ts +3 -3
  112. package/src/extensibility/gjc-plugins/prompt-appendix.ts +5 -1
  113. package/src/extensibility/gjc-plugins/runtime-adapters.ts +12 -2
  114. package/src/extensibility/gjc-plugins/runtime-quarantine.ts +121 -0
  115. package/src/extensibility/gjc-plugins/schema.ts +84 -12
  116. package/src/extensibility/gjc-plugins/session-validation.ts +9 -3
  117. package/src/extensibility/gjc-plugins/types.ts +141 -0
  118. package/src/extensibility/gjc-plugins/validation.ts +9 -0
  119. package/src/gjc-runtime/launch-tmux.ts +25 -6
  120. package/src/gjc-runtime/managed-owner-admission.ts +1 -1
  121. package/src/gjc-runtime/ralplan-runtime.ts +411 -17
  122. package/src/gjc-runtime/team-launch.ts +8 -0
  123. package/src/gjc-runtime/team-runtime.ts +140 -32
  124. package/src/gjc-runtime/team-worker-heartbeat.ts +149 -0
  125. package/src/gjc-runtime/tmux-owner-isolation.ts +10 -0
  126. package/src/gjc-runtime/tmux-sessions.ts +58 -13
  127. package/src/gjc-runtime/ultragoal-runtime.ts +401 -611
  128. package/src/gjc-runtime/workflow-manifest.generated.json +8 -99
  129. package/src/gjc-runtime/workflow-manifest.ts +4 -68
  130. package/src/internal-urls/docs-index.generated.ts +15 -15
  131. package/src/modes/DESIGN.md +51 -0
  132. package/src/modes/acp/acp-agent.ts +298 -186
  133. package/src/modes/components/gjc-bundle-settings.ts +508 -0
  134. package/src/modes/components/notifications-settings-editor.ts +12 -1
  135. package/src/modes/components/oauth-selector.ts +68 -30
  136. package/src/modes/components/session-observer-overlay.ts +305 -86
  137. package/src/modes/components/settings-selector.ts +56 -5
  138. package/src/modes/components/status-line/gh.ts +16 -0
  139. package/src/modes/components/tool-status-header.ts +3 -14
  140. package/src/modes/components/transcript-viewer-overlay.ts +99 -24
  141. package/src/modes/controllers/command-controller.ts +4 -0
  142. package/src/modes/controllers/extension-ui-controller.ts +7 -0
  143. package/src/modes/controllers/selector-controller.ts +45 -0
  144. package/src/modes/runtime-init.ts +3 -0
  145. package/src/prompts/agent-fragments/ralplan-persistence.md +4 -3
  146. package/src/prompts/system/eager-todo.md +8 -4
  147. package/src/prompts/system/system-prompt.md +11 -4
  148. package/src/prompts/tools/bash.md +5 -5
  149. package/src/prompts/tools/search-tool-bm25.md +5 -0
  150. package/src/prompts/tools/task.md +1 -1
  151. package/src/reminders/star-reminder.ts +4 -42
  152. package/src/runtime-mcp/manager.ts +19 -4
  153. package/src/sdk/acp/adapter.ts +22 -6
  154. package/src/sdk/broker/transport.ts +35 -3
  155. package/src/sdk/bus/attachment-registry.ts +5 -1
  156. package/src/sdk/bus/chat-daemon-cli.ts +4 -39
  157. package/src/sdk/bus/chat-daemon-control.ts +6 -3
  158. package/src/sdk/bus/config.ts +18 -2
  159. package/src/sdk/bus/index.ts +661 -126
  160. package/src/sdk/bus/kind-aware-reconciliation.ts +148 -73
  161. package/src/sdk/bus/lifecycle-commands.ts +4 -1
  162. package/src/sdk/bus/lifecycle-control-runtime.ts +403 -88
  163. package/src/sdk/bus/reconciliation-store.ts +95 -16
  164. package/src/sdk/bus/rich-draft.ts +1 -1
  165. package/src/sdk/bus/rich-render.ts +2 -2
  166. package/src/sdk/bus/telegram-adoption-intent.ts +574 -0
  167. package/src/sdk/bus/telegram-cli.ts +33 -8
  168. package/src/sdk/bus/telegram-daemon-cli.ts +1 -0
  169. package/src/sdk/bus/telegram-daemon-contract.ts +11 -4
  170. package/src/sdk/bus/telegram-daemon.ts +916 -23
  171. package/src/sdk/bus/telegram-reference.ts +40 -3
  172. package/src/sdk/bus/threaded-render.ts +48 -3
  173. package/src/sdk/bus/topic-registry.ts +20 -0
  174. package/src/sdk/host/query/revision-store.ts +36 -2
  175. package/src/sdk/host/reverse-leases.ts +44 -7
  176. package/src/sdk/prompt-status.ts +16 -3
  177. package/src/sdk/protocol/operation-inventory.generated.json +22 -0
  178. package/src/sdk/session.ts +88 -9
  179. package/src/session/agent-session.ts +822 -172
  180. package/src/session/artifacts.ts +22 -0
  181. package/src/session/auth-broker-config.ts +10 -3
  182. package/src/session/blob-store.ts +915 -24
  183. package/src/session/internal/managed-session-scope.ts +44 -6
  184. package/src/session/internal/managed-session-storage.ts +48 -6
  185. package/src/session/session-manager.ts +1614 -435
  186. package/src/session/session-storage.ts +9 -1
  187. package/src/session/streaming-output.ts +238 -68
  188. package/src/setup/credential-import.ts +75 -13
  189. package/src/skill-state/active-state.ts +32 -0
  190. package/src/skill-state/workflow-hud.ts +17 -0
  191. package/src/skill-state/workflow-mutation-guard.ts +496 -2
  192. package/src/task/executor.ts +122 -39
  193. package/src/task/index.ts +23 -14
  194. package/src/task/provider-retry-status.ts +16 -0
  195. package/src/task/receipt.ts +23 -7
  196. package/src/task/render.ts +6 -2
  197. package/src/task/types.ts +108 -0
  198. package/src/tools/ask-answer-registry.ts +12 -6
  199. package/src/tools/ask.ts +86 -55
  200. package/src/tools/ast-edit.ts +1 -0
  201. package/src/tools/ast-grep.ts +1 -0
  202. package/src/tools/bash-interactive.ts +8 -3
  203. package/src/tools/bash.ts +503 -60
  204. package/src/tools/find.ts +1 -0
  205. package/src/tools/image-gen.ts +29 -5
  206. package/src/tools/index.ts +4 -0
  207. package/src/tools/output-meta.ts +108 -14
  208. package/src/tools/path-utils.ts +3 -2
  209. package/src/tools/read.ts +18 -0
  210. package/src/tools/review.ts +5 -7
  211. package/src/tools/search.ts +1 -0
  212. package/src/tools/subagent-render.ts +6 -2
  213. package/src/tools/subagent.ts +6 -0
  214. package/src/tools/telegram-send.ts +6 -3
  215. package/src/utils/gh.ts +39 -0
  216. package/src/utils/image-resize.ts +3 -0
  217. package/src/web/search/providers/anthropic.ts +4 -4
  218. package/src/web/search/providers/kimi.ts +15 -5
  219. package/src/web/search/providers/searxng.ts +47 -4
  220. package/src/web/search/providers/xai.ts +7 -2
  221. package/dist/types/gjc-runtime/ultragoal-pipeline.d.ts +0 -23
  222. package/src/defaults/gjc/skills/ultragoal/pipeline-validation-contracts.md +0 -30
  223. package/src/gjc-runtime/ultragoal-pipeline.ts +0 -306
@@ -6,11 +6,13 @@
6
6
  *
7
7
  * Safe session ids only: /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/
8
8
  * Atomic write: temp + fsync + rename + 0600. Corrupt → quarantine + empty.
9
- * Non-terminal records settle to failed/process_restart on bootstrap (recon incomplete).
9
+ * Non-terminal skill records settle to failed/process_restart on bootstrap; prompt
10
+ * records finalize their pending outcome or a prompt_failed fallback.
10
11
  */
11
12
  import * as fs from "node:fs/promises";
12
13
  import * as path from "node:path";
13
- import type { PromptCorrelation, PromptReconciliationStatus } from "./prompt-reconciliation";
14
+ import type { PromptReconciliationStatus, SdkPromptTerminalOutcome } from "../prompt-status";
15
+ import type { PromptCorrelation } from "./prompt-reconciliation";
14
16
 
15
17
  export const RECONCILIATION_STORE_VERSION = 1;
16
18
  export const RECONCILIATION_SESSION_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
@@ -26,6 +28,8 @@ export interface DurableReconciliationRecord extends PromptCorrelation {
26
28
  acceptedAt: number;
27
29
  startedAt?: number;
28
30
  terminalAt?: number;
31
+ outcome?: SdkPromptTerminalOutcome;
32
+ pendingOutcome?: SdkPromptTerminalOutcome;
29
33
  /** Skill-only safe token; never skill args bodies. */
30
34
  skillName?: string;
31
35
  }
@@ -78,18 +82,68 @@ function isRecord(value: unknown): value is Record<string, unknown> {
78
82
  return typeof value === "object" && value !== null && !Array.isArray(value);
79
83
  }
80
84
 
85
+ /** Record-level validation: JSON-valid but malformed entries must be quarantined too. */
86
+ function isValidRecord(value: unknown): boolean {
87
+ if (!isRecord(value)) return false;
88
+ const { kind, commandId, turnId, status, acceptedAt, terminalAt, outcome, pendingOutcome } = value;
89
+ if (kind !== "prompt" && kind !== "skill") return false;
90
+ if (typeof commandId !== "string" || !commandId || typeof turnId !== "string" || !turnId) return false;
91
+ if (status !== "accepted" && status !== "in_flight" && status !== "terminal_ok" && status !== "failed") return false;
92
+ if (typeof acceptedAt !== "number" || !Number.isFinite(acceptedAt)) return false;
93
+ if (terminalAt !== undefined && (typeof terminalAt !== "number" || !Number.isFinite(terminalAt))) return false;
94
+ // Durable invariants: only prompts carry a pending claim, a finalized record has no
95
+ // pending claim left, and terminal/active status must agree with `terminalAt`.
96
+ if (pendingOutcome !== undefined && kind !== "prompt") return false;
97
+ if (pendingOutcome !== undefined && terminalAt !== undefined) return false;
98
+ const isTerminalStatus = status === "terminal_ok" || status === "failed";
99
+ if (isTerminalStatus !== (terminalAt !== undefined)) return false;
100
+ if (outcome !== undefined && !isTerminalStatus) return false;
101
+ if (
102
+ outcome !== undefined &&
103
+ ((status === "terminal_ok" && (!isRecord(outcome) || outcome.kind !== "stopped")) ||
104
+ (status === "failed" && (!isRecord(outcome) || outcome.kind !== "failed")))
105
+ )
106
+ return false;
107
+ if (value.startedAt !== undefined && (typeof value.startedAt !== "number" || !Number.isFinite(value.startedAt)))
108
+ return false;
109
+ if (value.clientRef !== undefined && typeof value.clientRef !== "string") return false;
110
+ if (value.skillName !== undefined && typeof value.skillName !== "string") return false;
111
+ if (value.error !== undefined) {
112
+ if (!isRecord(value.error)) return false;
113
+ if (typeof value.error.code !== "string" || typeof value.error.message !== "string") return false;
114
+ }
115
+ return [outcome, pendingOutcome].every(candidate => {
116
+ if (candidate === undefined) return true;
117
+ if (!isRecord(candidate)) return false;
118
+ if (candidate.kind === "stopped")
119
+ return (
120
+ ["end_turn", "max_tokens", "max_turn_requests", "refusal", "cancelled"].includes(
121
+ candidate.reason as string,
122
+ ) && ["agent", "client_cancel"].includes(candidate.provenance as string)
123
+ );
124
+ return (
125
+ candidate.kind === "failed" &&
126
+ ["prompt_failed", "prompt_deadline_exceeded"].includes(candidate.code as string) &&
127
+ typeof candidate.message === "string" &&
128
+ ["agent_failed", "deadline"].includes(candidate.provenance as string)
129
+ );
130
+ });
131
+ }
132
+
81
133
  function parseDocument(raw: string, expectedSessionId: string): ReconciliationStoreDocument {
82
134
  const value = JSON.parse(raw) as unknown;
83
135
  if (!isRecord(value) || value.version !== RECONCILIATION_STORE_VERSION)
84
136
  throw new Error("invalid reconciliation store version");
85
137
  if (value.sessionId !== expectedSessionId) throw new Error("session id mismatch");
86
138
  if (!Array.isArray(value.records)) throw new Error("invalid records");
139
+ if (!value.records.every(isValidRecord)) throw new Error("invalid reconciliation record");
87
140
  return value as unknown as ReconciliationStoreDocument;
88
141
  }
89
142
 
90
143
  /**
91
- * Settle non-terminal durable records after process death: failed/process_restart.
92
- * Meaning: reconciliation incomplete — not proof of agent failure.
144
+ * Settle non-terminal durable records after process death.
145
+ * Prompt records preserve a durable pending outcome; skills retain the existing
146
+ * reconciliation-incomplete result.
93
147
  */
94
148
  export function settleProcessRestart(
95
149
  records: DurableReconciliationRecord[],
@@ -97,6 +151,22 @@ export function settleProcessRestart(
97
151
  ): DurableReconciliationRecord[] {
98
152
  return records.map(record => {
99
153
  if (record.terminalAt !== undefined) return record;
154
+ if (record.kind === "prompt") {
155
+ const outcome: SdkPromptTerminalOutcome = record.pendingOutcome ?? {
156
+ kind: "failed",
157
+ code: "prompt_failed",
158
+ message: "Prompt did not complete before process restart.",
159
+ provenance: "agent_failed",
160
+ };
161
+ return {
162
+ ...record,
163
+ status: outcome.kind === "stopped" ? "terminal_ok" : "failed",
164
+ terminalAt: now,
165
+ outcome,
166
+ pendingOutcome: undefined,
167
+ ...(outcome.kind === "failed" ? { error: { code: outcome.code, message: outcome.message } } : {}),
168
+ };
169
+ }
100
170
  return {
101
171
  ...record,
102
172
  status: "failed",
@@ -165,19 +235,20 @@ export function createReconciliationStore(options: {
165
235
  memory = [];
166
236
  return memory;
167
237
  }
238
+ let raw: string;
168
239
  try {
169
- const raw = await fileFs.readFile(filePath, "utf8");
170
- const document = parseDocument(raw, sessionId);
171
- memory = settleProcessRestart(document.records, now());
172
- // Persist settled state so restart is sticky.
173
- if (memory.some((r, i) => r !== document.records[i]))
174
- await writeAtomic({ version: RECONCILIATION_STORE_VERSION, sessionId, records: memory });
175
- return memory;
240
+ raw = await fileFs.readFile(filePath, "utf8");
176
241
  } catch (error) {
177
- if ((error as NodeJS.ErrnoException).code === "ENOENT") {
178
- memory = [];
179
- return memory;
180
- }
242
+ // Only a missing file is an empty store. Permission/IO failures must propagate
243
+ // so the endpoint never becomes ready as if no prompt had been accepted.
244
+ if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
245
+ memory = [];
246
+ return memory;
247
+ }
248
+ let document: ReconciliationStoreDocument;
249
+ try {
250
+ document = parseDocument(raw, sessionId);
251
+ } catch {
181
252
  // Corrupt → quarantine
182
253
  try {
183
254
  await fileFs.rename(filePath, `${filePath}.corrupt.${now()}`);
@@ -187,6 +258,14 @@ export function createReconciliationStore(options: {
187
258
  memory = [];
188
259
  return memory;
189
260
  }
261
+ const settled = settleProcessRestart(document.records, now());
262
+ // Restart settlement must be durable before it is observable: a failed rewrite
263
+ // propagates so the endpoint stays unready instead of serving empty state as if
264
+ // no prompt had ever been accepted.
265
+ if (settled.some((record, index) => record !== document.records[index]))
266
+ await writeAtomic({ version: RECONCILIATION_STORE_VERSION, sessionId, records: settled });
267
+ memory = settled;
268
+ return memory;
190
269
  };
191
270
 
192
271
  const transact = async (
@@ -194,8 +273,8 @@ export function createReconciliationStore(options: {
194
273
  ): Promise<void> => {
195
274
  const run = async () => {
196
275
  const next = mutator(memory.map(r => ({ ...r })));
276
+ await writeAtomic({ version: RECONCILIATION_STORE_VERSION, sessionId, records: next });
197
277
  memory = next;
198
- await writeAtomic({ version: RECONCILIATION_STORE_VERSION, sessionId, records: memory });
199
278
  };
200
279
  const pending = chain.then(run, run);
201
280
  chain = pending.then(
@@ -88,7 +88,7 @@ export class DraftStreamState {
88
88
  */
89
89
  export async function deliverDraft(
90
90
  botApi: BotApi,
91
- base: { chat_id: string | number; message_thread_id?: number },
91
+ base: { chat_id: string | number; message_thread_id?: number; disable_notification?: true },
92
92
  draftId: number,
93
93
  raw: string,
94
94
  log?: { warn(msg: string): void },
@@ -62,7 +62,7 @@ export function shouldPromoteRich(input: { enabled?: boolean; send: ThreadedSend
62
62
  */
63
63
  export async function deliverRichWithFallback(
64
64
  botApi: BotApi,
65
- base: { chat_id: string | number; message_thread_id?: number },
65
+ base: { chat_id: string | number; message_thread_id?: number; disable_notification?: true },
66
66
  send: ThreadedSend,
67
67
  signal: AbortSignal,
68
68
  fallbackDeliver: () => Promise<void>,
@@ -99,7 +99,7 @@ export async function deliverRichWithFallback(
99
99
  */
100
100
  export async function deliverRichActionWithFallback(
101
101
  botApi: BotApi,
102
- base: { chat_id: string | number; message_thread_id?: number },
102
+ base: { chat_id: string | number; message_thread_id?: number; disable_notification?: true },
103
103
  opts: { markdown: string; replyMarkup?: unknown },
104
104
  signal: AbortSignal,
105
105
  htmlFallback: () => Promise<number | undefined>,