@tacuchi/agent-workflow-cli 23.0.0 → 25.0.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 (164) hide show
  1. package/README.md +37 -1
  2. package/dist/adapters/postgres-readonly-tools.js +277 -0
  3. package/dist/adapters/postgres-readonly-tools.js.map +1 -0
  4. package/dist/application/checkpoint/markdown.js +85 -5
  5. package/dist/application/checkpoint/markdown.js.map +1 -1
  6. package/dist/application/checkpoint-service.js +7 -6
  7. package/dist/application/checkpoint-service.js.map +1 -1
  8. package/dist/application/checkpoint-write-service.js +270 -16
  9. package/dist/application/checkpoint-write-service.js.map +1 -1
  10. package/dist/application/database-mcp-server.js +168 -0
  11. package/dist/application/database-mcp-server.js.map +1 -0
  12. package/dist/application/database-mcp-stdio.js +137 -0
  13. package/dist/application/database-mcp-stdio.js.map +1 -0
  14. package/dist/application/database-tool-catalog.js +226 -0
  15. package/dist/application/database-tool-catalog.js.map +1 -0
  16. package/dist/application/dsn-reader-service.js +1 -1
  17. package/dist/application/flow/advance.js +60 -10
  18. package/dist/application/flow/advance.js.map +1 -1
  19. package/dist/application/flow/internal-actions.js +1 -1
  20. package/dist/application/flow/internal-actions.js.map +1 -1
  21. package/dist/application/flow/submit.js +256 -9
  22. package/dist/application/flow/submit.js.map +1 -1
  23. package/dist/application/lifecycle-target.js +16 -19
  24. package/dist/application/lifecycle-target.js.map +1 -1
  25. package/dist/application/lock-service.js +96 -31
  26. package/dist/application/lock-service.js.map +1 -1
  27. package/dist/application/logging/log-events.js +19 -3
  28. package/dist/application/logging/log-events.js.map +1 -1
  29. package/dist/application/logging/logger.js +2 -2
  30. package/dist/application/logging/logger.js.map +1 -1
  31. package/dist/application/markdown.js +6 -2
  32. package/dist/application/markdown.js.map +1 -1
  33. package/dist/application/mcp-connections-service.js +115 -41
  34. package/dist/application/mcp-connections-service.js.map +1 -1
  35. package/dist/application/mcp-doctor-service.js +98 -54
  36. package/dist/application/mcp-doctor-service.js.map +1 -1
  37. package/dist/application/mcp-entry-classification.js +60 -0
  38. package/dist/application/mcp-entry-classification.js.map +1 -0
  39. package/dist/application/mcp-host-reader.js +102 -86
  40. package/dist/application/mcp-host-reader.js.map +1 -1
  41. package/dist/application/mcp-host-receipt-service.js +399 -0
  42. package/dist/application/mcp-host-receipt-service.js.map +1 -0
  43. package/dist/application/mcp-host-receipt-store.js +122 -0
  44. package/dist/application/mcp-host-receipt-store.js.map +1 -0
  45. package/dist/application/mcp-host-receipts.js +28 -0
  46. package/dist/application/mcp-host-receipts.js.map +1 -0
  47. package/dist/application/mcp-host-writer.js +209 -38
  48. package/dist/application/mcp-host-writer.js.map +1 -1
  49. package/dist/application/mcp-launch-probe-service.js +142 -0
  50. package/dist/application/mcp-launch-probe-service.js.map +1 -0
  51. package/dist/application/mcp-migration-service.js +351 -0
  52. package/dist/application/mcp-migration-service.js.map +1 -0
  53. package/dist/application/mcp-native-host-check-service.js +154 -0
  54. package/dist/application/mcp-native-host-check-service.js.map +1 -0
  55. package/dist/application/mcp-receipt-registration-service.js +105 -0
  56. package/dist/application/mcp-receipt-registration-service.js.map +1 -0
  57. package/dist/application/mcp-receipt-removal-service.js +62 -0
  58. package/dist/application/mcp-receipt-removal-service.js.map +1 -0
  59. package/dist/application/mcp-remove-service.js +83 -24
  60. package/dist/application/mcp-remove-service.js.map +1 -1
  61. package/dist/application/mcp-scope-common.js +1 -1
  62. package/dist/application/mcp-scope-common.js.map +1 -1
  63. package/dist/application/mcp-setup-service.js +59 -24
  64. package/dist/application/mcp-setup-service.js.map +1 -1
  65. package/dist/application/mcp-stdio-probe.js +526 -0
  66. package/dist/application/mcp-stdio-probe.js.map +1 -0
  67. package/dist/application/mcp-test-connection-service.js +23 -50
  68. package/dist/application/mcp-test-connection-service.js.map +1 -1
  69. package/dist/application/parsers/spec-functional.js +220 -0
  70. package/dist/application/parsers/spec-functional.js.map +1 -0
  71. package/dist/application/parsers/spec-relation.js +142 -5
  72. package/dist/application/parsers/spec-relation.js.map +1 -1
  73. package/dist/application/paths-service.js +13 -0
  74. package/dist/application/paths-service.js.map +1 -1
  75. package/dist/application/plan-exec-decision-service.js +57 -4
  76. package/dist/application/plan-exec-decision-service.js.map +1 -1
  77. package/dist/application/reseal-service.js +300 -0
  78. package/dist/application/reseal-service.js.map +1 -0
  79. package/dist/application/self/host-states.js.map +1 -1
  80. package/dist/application/self/install-skill.js +4 -34
  81. package/dist/application/self/install-skill.js.map +1 -1
  82. package/dist/application/self/mcp-config.js +369 -59
  83. package/dist/application/self/mcp-config.js.map +1 -1
  84. package/dist/application/self/mcp-via-state.js +9 -6
  85. package/dist/application/self/mcp-via-state.js.map +1 -1
  86. package/dist/application/self/uninstall-skill.js +3 -18
  87. package/dist/application/self/uninstall-skill.js.map +1 -1
  88. package/dist/application/self/uninstall.js +4 -23
  89. package/dist/application/self/uninstall.js.map +1 -1
  90. package/dist/application/workline-index-service.js +64 -6
  91. package/dist/application/workline-index-service.js.map +1 -1
  92. package/dist/application/workspace-init-service.js +4 -6
  93. package/dist/application/workspace-init-service.js.map +1 -1
  94. package/dist/cli/commands/checkpoint-write.js +24 -22
  95. package/dist/cli/commands/checkpoint-write.js.map +1 -1
  96. package/dist/cli/commands/index.js +7 -0
  97. package/dist/cli/commands/index.js.map +1 -1
  98. package/dist/cli/commands/mcp.js +642 -55
  99. package/dist/cli/commands/mcp.js.map +1 -1
  100. package/dist/cli/commands/reseal.js +140 -0
  101. package/dist/cli/commands/reseal.js.map +1 -0
  102. package/dist/cli/commands/status.js +5 -1
  103. package/dist/cli/commands/status.js.map +1 -1
  104. package/dist/cli/commands/tool.js +141 -0
  105. package/dist/cli/commands/tool.js.map +1 -0
  106. package/dist/cli/help-groups.js +7 -1
  107. package/dist/cli/help-groups.js.map +1 -1
  108. package/dist/cli/main.js +189 -57
  109. package/dist/cli/main.js.map +1 -1
  110. package/dist/cli/parser.js +5 -1
  111. package/dist/cli/parser.js.map +1 -1
  112. package/dist/cli/registry.js.map +1 -1
  113. package/dist/cli/render.js +15 -2
  114. package/dist/cli/render.js.map +1 -1
  115. package/dist/cli/tui/components/host-admin-section.js +2 -46
  116. package/dist/cli/tui/components/host-admin-section.js.map +1 -1
  117. package/dist/cli/tui/tabs/mcp-tab-helpers.js +71 -0
  118. package/dist/cli/tui/tabs/mcp-tab-helpers.js.map +1 -1
  119. package/dist/cli/tui/tabs/mcp-tab.js +101 -42
  120. package/dist/cli/tui/tabs/mcp-tab.js.map +1 -1
  121. package/dist/domain/database-tools.js +445 -0
  122. package/dist/domain/database-tools.js.map +1 -0
  123. package/dist/domain/effective-contract.js +10 -2
  124. package/dist/domain/effective-contract.js.map +1 -1
  125. package/dist/domain/flow/answer.js +4 -0
  126. package/dist/domain/flow/answer.js.map +1 -1
  127. package/dist/domain/flow/authority.js +103 -14
  128. package/dist/domain/flow/authority.js.map +1 -1
  129. package/dist/domain/flow/directive.js +2 -0
  130. package/dist/domain/flow/directive.js.map +1 -1
  131. package/dist/domain/flow/run-state.js +42 -0
  132. package/dist/domain/flow/run-state.js.map +1 -1
  133. package/dist/domain/lineage.js +38 -11
  134. package/dist/domain/lineage.js.map +1 -1
  135. package/dist/domain/mcp-entry.js +131 -17
  136. package/dist/domain/mcp-entry.js.map +1 -1
  137. package/dist/domain/postgres-object-search.js +320 -0
  138. package/dist/domain/postgres-object-search.js.map +1 -0
  139. package/dist/domain/redaction.js +47 -0
  140. package/dist/domain/redaction.js.map +1 -0
  141. package/dist/domain/workline-mcp-entry.js +6 -9
  142. package/dist/domain/workline-mcp-entry.js.map +1 -1
  143. package/dist/ports/postgres-tools.js +10 -0
  144. package/dist/ports/postgres-tools.js.map +1 -0
  145. package/package.json +5 -1
  146. package/skills/w/commands/plan-exec.md +1 -1
  147. package/skills/w/commands/spec-new.md +6 -5
  148. package/skills/w/context/MANIFEST.json +1 -1
  149. package/skills/w/harness/HARNESS.md +1 -1
  150. package/skills/w/hooks/README.md +13 -9
  151. package/skills/w/hooks/hooks.template.json +2 -2
  152. package/skills/w/loops/CHASSIS.md +1 -1
  153. package/skills/w/loops/plan-exec-loop/LOOP.md +7 -5
  154. package/skills/w/loops/plan-new-loop/LOOP.md +46 -41
  155. package/skills/w/loops/plan-refine-loop/LOOP.md +4 -4
  156. package/skills/w/loops/quick-loop/LOOP.md +12 -13
  157. package/skills/w/loops/spec-refine-loop/LOOP.md +7 -3
  158. package/skills/w/modules/COMPACTION.md +1 -1
  159. package/skills/w/modules/PLAN-INPUT.md +3 -3
  160. package/skills/w/modules/PROMPT-CONTINUITY.md +1 -1
  161. package/dist/application/mcp-dbhub-launcher.js +0 -216
  162. package/dist/application/mcp-dbhub-launcher.js.map +0 -1
  163. package/dist/application/self/mcp-offer.js +0 -96
  164. package/dist/application/self/mcp-offer.js.map +0 -1
@@ -1,10 +1,14 @@
1
1
  import { join } from "node:path";
2
2
  import { findActiveSessions } from "./checkpoint-service.js";
3
3
  import { totalInScope } from "./checkpoint/files-touched.js";
4
- import { formatCheckpointMd, isPristineCheckpoint } from "./checkpoint/markdown.js";
4
+ import { appendSealedBlock, blocksUnder, formatCheckpointMd, isPristineCheckpoint, } from "./checkpoint/markdown.js";
5
5
  import { extractSessionState } from "./checkpoint/state-reader.js";
6
- import { resolveLifecycleTarget, unresolvedDetail, } from "./lifecycle-target.js";
6
+ import { localMinuteIso } from "./dates.js";
7
+ import { resolveLifecycleTarget, } from "./lifecycle-target.js";
8
+ import { parseMdValue } from "./markdown.js";
7
9
  import { resolveWorkspaceRoot } from "./paths-service.js";
10
+ import { relpath } from "./paths.js";
11
+ import { hashContextId } from "./session-binding-service.js";
8
12
  import { writeSessionNarrative } from "./session-narrative.js";
9
13
  // This module deliberately owns NO placeholder marker of its own. `_[AI:` used
10
14
  // to be declared here as well as in `checkpoint-service.ts`, with incompatible
@@ -27,18 +31,26 @@ export async function runCheckpointWrite(fs, env, git, paths, options = {}) {
27
31
  // the association to land on the same one.
28
32
  const target = await resolveLifecycleTarget(fs, paths, options, "bind");
29
33
  if (target.outcome !== "resolved")
30
- return unresolved(fs, paths, target);
34
+ return unresolved(fs, paths, target, options);
31
35
  const session = target.session;
32
36
  const cpPath = join(session.path, "CHECKPOINT.md");
33
37
  if (await hasContentToPreserve(fs, cpPath, options.force === true)) {
38
+ // Adoption runs even here: preservation protects written prose from being
39
+ // REGENERATED, and folding a refuge in only appends to it.
40
+ const adopted = await adoptRefuge(fs, paths, session, adoptionScope(options));
34
41
  return {
35
42
  session: session.folder,
36
43
  checkpoint_path: cpPath,
37
44
  skipped: true,
38
45
  preserved: true,
39
46
  reason: PRESERVED_REASON,
47
+ ...adoptedField(adopted.adopted),
40
48
  };
41
49
  }
50
+ // Read BEFORE the write that replaces it: an adopted refuge is not part of any
51
+ // template, so regenerating without carrying it across would drop the state
52
+ // the refuge existed to save (its file on disk is long gone).
53
+ const carried = await carriedAdoptions(fs, cpPath);
42
54
  // The workspace root rather than the raw cwd. Today the two coincide by
43
55
  // construction — session resolution already refuses to run from a
44
56
  // subdirectory, so nothing reaches here with a deeper cwd — and what actually
@@ -48,13 +60,16 @@ export async function runCheckpointWrite(fs, env, git, paths, options = {}) {
48
60
  // widen to the parent repository along with it.
49
61
  const workspaceRoot = await resolveWorkspaceRoot(fs, env, paths);
50
62
  const state = await extractSessionState(fs, git, workspaceRoot, session.path);
51
- const md = formatCheckpointMd(state);
63
+ const md = withCarried(formatCheckpointMd(state), carried);
52
64
  await fs.mkdirp(session.path);
53
65
  await fs.writeText(cpPath, md);
54
66
  // The CHECKPOINT is where progress lives, so writing one is exactly when the
55
67
  // session's entry point stops being current. Refreshed here and never on a
56
68
  // read, which is what keeps a `status` or a `resume` from rewriting history.
57
69
  await writeSessionNarrative(fs, paths, { folder: session.folder, path: session.path });
70
+ // Last, never first: a refuge is folded into the checkpoint this run just
71
+ // produced, so the file it appends to is already there.
72
+ const adopted = await adoptRefuge(fs, paths, session, adoptionScope(options));
58
73
  return {
59
74
  session: session.folder,
60
75
  checkpoint_path: cpPath,
@@ -63,33 +78,40 @@ export async function runCheckpointWrite(fs, env, git, paths, options = {}) {
63
78
  tasks_open: state.tasks.open,
64
79
  tasks_closed: state.tasks.closed,
65
80
  files_touched_count: totalInScope(state.files_touched),
81
+ ...adoptedField(adopted.adopted),
66
82
  };
67
83
  }
68
84
  /**
69
85
  * SessionEnd. It used to iterate EVERY active session, so closing one host
70
86
  * conversation wrote checkpoints over lines belonging to others. It now
71
- * checkpoints the resolved target and nothing else; with no sufficient
72
- * identity it writes nothing at all. The host is exiting, so there is nobody
73
- * left to answer a selection prompt: this surface always degrades, never blocks.
87
+ * checkpoints the resolved target and nothing else; with no sufficient identity
88
+ * it writes no session line at all and parks a refuge instead.
74
89
  */
75
90
  export async function runAutoCompactOnClose(fs, env, git, paths, options = {}) {
76
91
  // Does NOT bind: the host is exiting, so there is no later turn the
77
92
  // association could serve, and establishing one is a locked write that fails
78
93
  // the whole resolution when it cannot be taken — which would cost the
79
94
  // checkpoint this surface exists to save.
80
- const target = await resolveLifecycleTarget(fs, paths, { ...options, canPauseCompaction: false }, "read-only");
95
+ const target = await resolveLifecycleTarget(fs, paths, options, "read-only");
81
96
  if (target.outcome !== "resolved") {
82
- const detail = unresolvedDetail(target);
83
97
  return {
84
98
  checkpoints_written: [],
85
99
  continuity: "degraded",
86
100
  primary_session: null,
87
- candidates: detail.candidates,
88
- action: detail.action,
101
+ candidates: target.candidates,
102
+ action: target.action,
103
+ refuge_path: await parkRefuge(fs, paths, target, options.contextId),
89
104
  };
90
105
  }
91
106
  const workspaceRoot = await resolveWorkspaceRoot(fs, env, paths);
92
107
  const entry = await writeCheckpointForTarget(fs, git, workspaceRoot, target.session);
108
+ // Only over a checkpoint that exists: `writeCheckpointForTarget` reports its
109
+ // own failure instead of throwing, and appending a refuge to a file that was
110
+ // never written would file the parked state under a session line nobody wrote.
111
+ if (entry.error === undefined) {
112
+ const adopted = await adoptRefuge(fs, paths, target.session, adoptionScope(options));
113
+ return { checkpoints_written: [{ ...entry, ...adoptedField(adopted.adopted) }] };
114
+ }
93
115
  return { checkpoints_written: [entry] };
94
116
  }
95
117
  async function writeCheckpointForTarget(fs, git, workspaceRoot, session) {
@@ -106,8 +128,9 @@ async function writeCheckpointForTarget(fs, git, workspaceRoot, session) {
106
128
  };
107
129
  }
108
130
  try {
131
+ const carried = await carriedAdoptions(fs, cpPath);
109
132
  const state = await extractSessionState(fs, git, workspaceRoot, session.path);
110
- const md = formatCheckpointMd(state);
133
+ const md = withCarried(formatCheckpointMd(state), carried);
111
134
  await fs.mkdirp(session.path);
112
135
  await fs.writeText(cpPath, md);
113
136
  return {
@@ -138,10 +161,23 @@ async function hasContentToPreserve(fs, cpPath, force) {
138
161
  return false;
139
162
  return !isPristineCheckpoint(await fs.readText(cpPath));
140
163
  }
141
- async function unresolved(fs, paths, target) {
142
- if (target.outcome === "blocked") {
143
- return { blocked: true, selection_required: true, sessionError: target.error };
144
- }
164
+ /**
165
+ * The refuge sections an existing CHECKPOINT already carries.
166
+ *
167
+ * Read before every regeneration and written back after it (see
168
+ * {@link withCarried}). "Preserve" protects somebody's prose; carrying protects
169
+ * the CLI's own folded-in state, which preservation deliberately does NOT cover
170
+ * because a checkpoint the CLI wrote must stay regenerable.
171
+ */
172
+ async function carriedAdoptions(fs, cpPath) {
173
+ if (!(await fs.exists(cpPath)))
174
+ return [];
175
+ return blocksUnder(await fs.readText(cpPath), ADOPTED_HEADING);
176
+ }
177
+ function withCarried(md, carried) {
178
+ return carried.reduce((text, block) => appendSealedBlock(text, block), md);
179
+ }
180
+ async function unresolved(fs, paths, target, options) {
145
181
  const actives = await findActiveSessions(fs, paths);
146
182
  return {
147
183
  skipped: true,
@@ -151,6 +187,224 @@ async function unresolved(fs, paths, target) {
151
187
  active_sessions: actives.map((a) => a.folder),
152
188
  candidates: target.candidates,
153
189
  action: target.action,
190
+ refuge_path: await parkRefuge(fs, paths, target, options.contextId),
154
191
  };
155
192
  }
193
+ // ── the refuge: state a lifecycle surface saves when no session resolves ─────
194
+ //
195
+ // This exists because the PreCompact hook stopped being allowed to block (see
196
+ // `resolveLifecycleTarget`). Losing the protective pause without replacing it
197
+ // would mean the compaction that follows an unresolved target takes the run's
198
+ // context away and leaves nothing behind. So the reason, the candidates and the
199
+ // way out are written to a file OUTSIDE any session — nothing has to be guessed
200
+ // to place it — and the first invocation that does resolve the session folds it
201
+ // into that session's CHECKPOINT.
202
+ /** `- Fecha:` / `- Conversación:` — the two lines adoption reads back. */
203
+ const REFUGE_DATE_KEY = "Fecha";
204
+ const REFUGE_CONVERSATION_KEY = "Conversación";
205
+ /** The heading an adopted refuge lands under, inside the CHECKPOINT's sealed body. */
206
+ const ADOPTED_HEADING = "## Refugio adoptado";
207
+ /**
208
+ * What `- Conversación:` says — and what the file is called — when the host gave
209
+ * no conversation id.
210
+ *
211
+ * Such a refuge cannot be matched to anybody, so only an explicit `--code`
212
+ * adopts it: a person naming the session IS the missing identity. The name
213
+ * carries no instant on purpose: stamping it would make every compaction of
214
+ * every id-less invocation pile up another file in a directory nothing sweeps,
215
+ * where the digest case leaves exactly one. One file, latest reason, same rule.
216
+ */
217
+ const REFUGE_NO_CONVERSATION = "desconocida";
218
+ /**
219
+ * The conversation is named by the SHA-256 of its id, never by the id.
220
+ *
221
+ * Same rule as the bindings registry (`hashContextId`): the host's opaque
222
+ * conversation id never reaches disk in the clear. It also makes the file name
223
+ * safe by construction — 64 hex characters cannot escape a directory — and
224
+ * stable, so a conversation that compacts five times leaves ONE refuge with its
225
+ * latest reason instead of five.
226
+ */
227
+ const REFUGE_DIGEST_PREFIX = "sha256:";
228
+ /** Where the parked state goes, and its workspace-relative path for the caller. */
229
+ export async function writeRefugeCheckpoint(fs, paths, input) {
230
+ const now = input.now ?? new Date();
231
+ const digest = input.contextId !== undefined ? hashContextId(input.contextId) : null;
232
+ const dir = paths.cwdSessionsRefugeDir();
233
+ const path = join(dir, `${digest ?? REFUGE_NO_CONVERSATION}.md`);
234
+ await fs.mkdirp(dir);
235
+ await fs.writeText(path, refugeBody(input, now, digest));
236
+ return relpath(path, paths.workspaceDir());
237
+ }
238
+ /**
239
+ * A refuge, but ONLY when somebody could adopt it later.
240
+ *
241
+ * With no candidate at all — a workspace between runs, which is the ordinary
242
+ * state — the parked file would name no session anybody could resolve it to,
243
+ * and every compaction of every session-less conversation would leave one
244
+ * behind. The notice on stderr is the whole answer there.
245
+ */
246
+ async function parkRefuge(fs, paths, target, contextId) {
247
+ if (target.candidates.length === 0)
248
+ return null;
249
+ return writeRefugeCheckpoint(fs, paths, {
250
+ reason: target.reason,
251
+ action: target.action,
252
+ candidates: target.candidates,
253
+ ...(contextId !== undefined ? { contextId } : {}),
254
+ });
255
+ }
256
+ /**
257
+ * Fold every refuge that belongs to this conversation into the session's
258
+ * CHECKPOINT, and remove it.
259
+ *
260
+ * Adding a section is what makes this safe next to the preservation guard: that
261
+ * guard refuses to REGENERATE a written checkpoint, and folding text in takes
262
+ * nothing away from one. It goes in through {@link appendSealedBlock} rather
263
+ * than by appending past the seal, so a checkpoint that was still the CLI's own
264
+ * output stays that way — otherwise the first adoption would freeze the file
265
+ * forever behind "there is content to preserve". Removing the refuge afterwards
266
+ * is not tidying: it is what keeps the next invocation from adopting the same
267
+ * text again — but ONLY once the block is demonstrably in the file, because two
268
+ * concurrent hooks read the same `existing` and the loser's append is not in
269
+ * what finally lands. Removing on the strength of its own write would delete the
270
+ * parked state from both places it existed in. A refuge left on disk costs one
271
+ * more adoption attempt; a refuge deleted for nothing is irrecoverable.
272
+ */
273
+ export async function adoptRefuge(fs, paths, session, scope = {}) {
274
+ const wanted = digestOfContext(scope.contextId);
275
+ const cpPath = join(session.path, "CHECKPOINT.md");
276
+ const adopted = [];
277
+ // Nothing that happens in here may throw out of a lifecycle surface: a
278
+ // non-zero exit is how a host HOLDS its compaction, and holding it was the
279
+ // irrecoverable trap these surfaces stopped being allowed to set. A failure
280
+ // reports "nothing adopted" and leaves the refuge for the next invocation.
281
+ try {
282
+ for (const refuge of await listRefugeCheckpoints(fs, paths)) {
283
+ if (!adoptable(refuge, wanted, scope.explicitCode === true))
284
+ continue;
285
+ const block = adoptedBlock(refuge);
286
+ // The block as it reads BACK: the plain-append path collapses the trailing
287
+ // blank line, so only the text up to its last character is what both
288
+ // append paths leave verbatim in the file.
289
+ const folded = block.trimEnd();
290
+ const existing = (await fs.exists(cpPath)) ? await fs.readText(cpPath) : "";
291
+ // Already in there — an earlier run adopted it and could not remove the
292
+ // file, or the run this one raced got there first. The state is safe, so
293
+ // the refuge is spent and appending again would only duplicate it.
294
+ if (existing.includes(folded)) {
295
+ await discardRefuge(fs, refuge.path);
296
+ continue;
297
+ }
298
+ await fs.mkdirp(session.path);
299
+ await fs.writeText(cpPath, appendSealedBlock(existing, block));
300
+ if (!(await fs.readText(cpPath)).includes(folded))
301
+ continue;
302
+ await discardRefuge(fs, refuge.path);
303
+ adopted.push(refuge.relative);
304
+ }
305
+ }
306
+ catch {
307
+ // Deliberately silent: the caller's contract is the checkpoint it already
308
+ // wrote, and `refuge_adopted` is simply absent.
309
+ }
310
+ return { adopted };
311
+ }
312
+ /**
313
+ * Drop a refuge whose text is in the CHECKPOINT.
314
+ *
315
+ * Cleanup, not the adoption itself: the state is already saved, so a removal
316
+ * that fails must not cost the run. The next invocation finds the file again,
317
+ * recognises its own block and retries the removal.
318
+ */
319
+ async function discardRefuge(fs, path) {
320
+ try {
321
+ await fs.remove(path);
322
+ }
323
+ catch {
324
+ // Left on disk on purpose. It is re-read, not re-adopted.
325
+ }
326
+ }
327
+ /**
328
+ * The refuge waiting for this conversation, for a surface that only reports.
329
+ *
330
+ * Symmetric with {@link parkRefuge} on purpose: an invocation with no
331
+ * conversation id parks an ANONYMOUS refuge, so that is exactly the one it must
332
+ * be told about. Cutting off at "no id, no answer" made the one invocation
333
+ * shape that can create such a refuge the only one unable to report it — and in
334
+ * the single channel the model reads, `refuge: null` does not say "I don't
335
+ * know", it says there is none.
336
+ */
337
+ export async function findRefugeForContext(fs, paths, contextId) {
338
+ const wanted = digestOfContext(contextId);
339
+ const refuges = await listRefugeCheckpoints(fs, paths);
340
+ const found = refuges.find((refuge) => refuge.conversation === wanted);
341
+ return found !== undefined ? { path: found.relative, date: found.date } : null;
342
+ }
343
+ export async function listRefugeCheckpoints(fs, paths) {
344
+ const dir = paths.cwdSessionsRefugeDir();
345
+ if (!(await fs.exists(dir)))
346
+ return [];
347
+ const refuges = [];
348
+ for (const entry of await fs.list(dir)) {
349
+ if (entry.type !== "file" || !entry.name.endsWith(".md"))
350
+ continue;
351
+ const body = await fs.readText(entry.path);
352
+ const conversation = parseMdValue(body, REFUGE_CONVERSATION_KEY);
353
+ refuges.push({
354
+ path: entry.path,
355
+ relative: relpath(entry.path, paths.workspaceDir()),
356
+ date: parseMdValue(body, REFUGE_DATE_KEY) ?? "sin fecha",
357
+ conversation: conversation?.startsWith(REFUGE_DIGEST_PREFIX) ? conversation : null,
358
+ body,
359
+ });
360
+ }
361
+ // Deterministic order, so an adoption of several refuges reads the same way twice.
362
+ return refuges.sort((a, b) => a.path.localeCompare(b.path));
363
+ }
364
+ /** Whose refuge this is: the conversation's own, or anybody's under an explicit `--code`. */
365
+ function adoptable(refuge, wanted, explicitCode) {
366
+ if (refuge.conversation === null)
367
+ return explicitCode;
368
+ return refuge.conversation === wanted;
369
+ }
370
+ function digestOfContext(contextId) {
371
+ return contextId !== undefined && contextId.trim().length > 0
372
+ ? `${REFUGE_DIGEST_PREFIX}${hashContextId(contextId)}`
373
+ : null;
374
+ }
375
+ function adoptionScope(options) {
376
+ return {
377
+ ...(options.contextId !== undefined ? { contextId: options.contextId } : {}),
378
+ explicitCode: (options.code?.trim().length ?? 0) > 0,
379
+ };
380
+ }
381
+ function adoptedBlock(refuge) {
382
+ // The refuge's own H1 would land as a second title inside the CHECKPOINT, and
383
+ // the heading below already says where the text came from. Everything else
384
+ // goes in verbatim: an adoption that summarised would be an adoption that loses.
385
+ const body = refuge.body.replace(/^#[^\n]*\n/, "").trim();
386
+ return `${ADOPTED_HEADING} (${refuge.date})\n\n${body}\n\n`;
387
+ }
388
+ function refugeBody(input, now, digest) {
389
+ const candidates = input.candidates.map((c) => `${c.folder} (${c.state})`).join(" · ");
390
+ return `${[
391
+ "# CHECKPOINT de refugio",
392
+ "",
393
+ "> Lo escribió un hook de ciclo de vida (PreCompact o SessionEnd): la",
394
+ "> compactación —o el cierre— siguió adelante, pero no se pudo resolver a qué",
395
+ "> sesión pertenece esta conversación, así que su estado queda acá en vez de",
396
+ "> perderse. Se adopta en el CHECKPOINT.md de la sesión en cuanto alguien la",
397
+ "> resuelva (`aw checkpoint-write --code <NNN>`).",
398
+ "",
399
+ `- ${REFUGE_DATE_KEY}: ${localMinuteIso(now)}`,
400
+ `- ${REFUGE_CONVERSATION_KEY}: ${digest !== null ? `${REFUGE_DIGEST_PREFIX}${digest}` : REFUGE_NO_CONVERSATION}`,
401
+ `- Motivo: ${input.reason}`,
402
+ `- Candidatas: ${candidates.length > 0 ? candidates : "ninguna"}`,
403
+ `- Acción: ${input.action}`,
404
+ ].join("\n")}\n`;
405
+ }
406
+ /** Present only when something was actually adopted — an empty list says nothing. */
407
+ function adoptedField(adopted) {
408
+ return adopted.length > 0 ? { refuge_adopted: adopted } : {};
409
+ }
156
410
  //# sourceMappingURL=checkpoint-write-service.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"checkpoint-write-service.js","sourceRoot":"","sources":["../../src/application/checkpoint-write-service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"checkpoint-write-service.js","sourceRoot":"","sources":["../../src/application/checkpoint-write-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,168 @@
1
+ import { encodeToolResponse, toolFailure } from "../domain/database-tools.js";
2
+ const PROTOCOL_VERSION = "2025-06-18";
3
+ /** JSON-RPC adapter over the shared catalog. It owns no tool rules. */
4
+ export function createDatabaseMcpServer(deps) {
5
+ let lifecycle = "new";
6
+ const activeCalls = new Map();
7
+ const cancelledBeforeStart = new Set();
8
+ function reply(id, result) {
9
+ if (!isJsonRpcResponseId(id))
10
+ return;
11
+ deps.send({ jsonrpc: "2.0", id, result });
12
+ }
13
+ function replyError(id, code, message) {
14
+ if (!isJsonRpcResponseId(id))
15
+ return;
16
+ deps.send({ jsonrpc: "2.0", id, error: { code, message } });
17
+ }
18
+ function toolResult(response) {
19
+ return {
20
+ content: [{ type: "text", text: encodeToolResponse(response), mimeType: "application/json" }],
21
+ ...(response.success ? {} : { isError: true }),
22
+ };
23
+ }
24
+ async function dispatchToolCall(message) {
25
+ const params = isRecord(message.params) ? message.params : {};
26
+ const name = typeof params.name === "string" ? params.name : "";
27
+ const requestKey = requestIdKey(message.id);
28
+ // tools/call is a request, not a notification. Rejecting an id-less call
29
+ // prevents an untracked database operation that the client cannot cancel.
30
+ if (requestKey === undefined) {
31
+ replyError(message.id, -32600, "tools/call requiere un id de solicitud válido");
32
+ return true;
33
+ }
34
+ if (cancelledBeforeStart.delete(requestKey)) {
35
+ reply(message.id, toolResult(toolFailure("QUERY_CANCELLED", "La consulta fue cancelada.")));
36
+ return true;
37
+ }
38
+ const controller = new AbortController();
39
+ activeCalls.set(requestKey, controller);
40
+ try {
41
+ const outcome = await deps.catalog.call({
42
+ tool: name,
43
+ connection: deps.connection,
44
+ input: params.arguments,
45
+ signal: controller.signal,
46
+ });
47
+ reply(message.id, toolResult(outcome.response));
48
+ }
49
+ catch {
50
+ reply(message.id, toolResult(toolFailure("TOOL_EXECUTION_FAILED", "La tool no pudo completar la solicitud.")));
51
+ }
52
+ finally {
53
+ if (activeCalls.get(requestKey) === controller) {
54
+ activeCalls.delete(requestKey);
55
+ }
56
+ }
57
+ return true;
58
+ }
59
+ async function cancelToolCall(message) {
60
+ const params = isRecord(message.params) ? message.params : {};
61
+ const key = requestIdKey(params.requestId);
62
+ if (key === undefined)
63
+ return true;
64
+ const active = activeCalls.get(key);
65
+ if (active !== undefined) {
66
+ active.abort();
67
+ return true;
68
+ }
69
+ // A stdio transport may receive cancellation while an earlier call keeps a
70
+ // later request queued. Retain bounded intent so that later call never
71
+ // reaches PostgreSQL once it starts.
72
+ cancelledBeforeStart.add(key);
73
+ if (cancelledBeforeStart.size > 1_000) {
74
+ const oldest = cancelledBeforeStart.values().next().value;
75
+ if (oldest !== undefined)
76
+ cancelledBeforeStart.delete(oldest);
77
+ }
78
+ return true;
79
+ }
80
+ async function initialize(message) {
81
+ if (lifecycle !== "new") {
82
+ replyError(message.id, -32600, "initialize sólo puede llamarse una vez por sesión");
83
+ return true;
84
+ }
85
+ lifecycle = "awaiting-initialized";
86
+ reply(message.id, {
87
+ protocolVersion: PROTOCOL_VERSION,
88
+ capabilities: { tools: {} },
89
+ serverInfo: { name: "agent-workflow-db", version: "1" },
90
+ });
91
+ return true;
92
+ }
93
+ async function initialized() {
94
+ if (lifecycle === "awaiting-initialized") {
95
+ lifecycle = "ready";
96
+ await deps.onHostLoadObserved?.();
97
+ }
98
+ return true;
99
+ }
100
+ function readyOrReply(message) {
101
+ if (lifecycle === "ready")
102
+ return true;
103
+ replyError(message.id, -32002, "Server not initialized");
104
+ return false;
105
+ }
106
+ async function listTools(message) {
107
+ if (!readyOrReply(message))
108
+ return true;
109
+ try {
110
+ const list = deps.catalog.list(deps.connection);
111
+ reply(message.id, "tools" in list.payload ? list.payload : toolResult(list.payload));
112
+ }
113
+ catch {
114
+ reply(message.id, toolResult(toolFailure("MCP_CONNECTION_INVALID", "No se pudo resolver la conexión solicitada.")));
115
+ }
116
+ return true;
117
+ }
118
+ async function callTool(message) {
119
+ if (!readyOrReply(message))
120
+ return true;
121
+ return await dispatchToolCall(message);
122
+ }
123
+ const handlers = {
124
+ initialize,
125
+ "notifications/initialized": async () => await initialized(),
126
+ "notifications/cancelled": async (message) => await cancelToolCall(message),
127
+ "tools/list": listTools,
128
+ "tools/call": callTool,
129
+ };
130
+ return {
131
+ async handle(message) {
132
+ if (!isJsonRpcEnvelope(message))
133
+ return false;
134
+ const handler = handlers[message.method];
135
+ if (handler !== undefined)
136
+ return await handler(message);
137
+ replyError(message.id, -32601, "Method not found");
138
+ return true;
139
+ },
140
+ };
141
+ }
142
+ /** Accept only envelopes for which every response remains valid JSON-RPC. */
143
+ function isJsonRpcEnvelope(value) {
144
+ return (isRecord(value) &&
145
+ value.jsonrpc === "2.0" &&
146
+ typeof value.method === "string" &&
147
+ isJsonRpcId(value.id));
148
+ }
149
+ function isJsonRpcId(value) {
150
+ return value === undefined || isJsonRpcResponseId(value);
151
+ }
152
+ function isJsonRpcResponseId(value) {
153
+ return value === null || typeof value === "string" || isFiniteId(value);
154
+ }
155
+ function isFiniteId(value) {
156
+ return typeof value === "number" && Number.isFinite(value);
157
+ }
158
+ function requestIdKey(value) {
159
+ if (typeof value === "string")
160
+ return `string:${value}`;
161
+ if (typeof value === "number" && Number.isFinite(value))
162
+ return `number:${value}`;
163
+ return undefined;
164
+ }
165
+ function isRecord(value) {
166
+ return value !== null && typeof value === "object" && !Array.isArray(value);
167
+ }
168
+ //# sourceMappingURL=database-mcp-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database-mcp-server.js","sourceRoot":"","sources":["../../src/application/database-mcp-server.ts"],"names":[],"mappings":"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"}