@synaplink/orqlaude 0.10.1 → 0.10.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -183,6 +183,171 @@ User says: *"Refactor the auth system — magic-link login, update the docs, add
183
183
  8. `orqlaude.collect` → three PR URLs and summaries.
184
184
  9. **NEW**: `orqlaude.review_prs(plan_id)` → spawns three reviewer agents, one per PR. Each reviews, runs tests, posts findings. You aggregate the second-round notes.
185
185
 
186
+ ## Asking the user (v0.10.4 pattern)
187
+
188
+ `ask_user` and its companion `wait_for_user_response` are the bounded-block loop primary Claude uses to put a question on Telegram and stay alive past the MCP host's 60s per-request timeout.
189
+
190
+ The split exists because Claude Desktop and Claude Code both use the SDK default `DEFAULT_REQUEST_TIMEOUT_MSEC = 60000`. v0.10.2's progress notifications turned out to be ignored unless the client passes `resetTimeoutOnProgress: true` (it doesn't), so a single blocking call can't outrun the host. Instead, `ask_user` blocks at most 45s (the new `initial_block_sec`, capped at 45). The question's overall lifetime is `total_timeout_sec` (default 900s, max 3600s) -- that's how long it stays answerable. If the user replies inside the first window, you get `status: "answered"`. Otherwise you get `status: "still_pending"` with a `short_id`, and the caller must invoke `wait_for_user_response(short_id)` to keep waiting.
191
+
192
+ Loop pattern (TS pseudocode):
193
+
194
+ ```ts
195
+ let result = await ask_user({
196
+ prompt: "Approve the auth refactor plan?",
197
+ options: ["Approve", "Hold off"],
198
+ total_timeout_sec: 1800,
199
+ });
200
+
201
+ while (result.status === "still_pending") {
202
+ result = await wait_for_user_response({ short_id: result.short_id });
203
+ }
204
+ // result.status is now "answered" / "timed_out" / "cancelled"
205
+ ```
206
+
207
+ Each call stays safely under 60s. A fast answer is one round-trip; a 5-minute wait is roughly 7 round-trips, no `ScheduleWakeup`-and-come-back required.
208
+
209
+ Telegram side is plain text only (no Markdown), so escaping bugs can't silently swallow a send. The notifier ships each question with `force_reply` enabled -- the user just types and their reply carries `reply_to_message.message_id`, which the bot matches back to the request. Inline-keyboard buttons fire the same answer path when `options` are provided; `/respond <short_id> <text>` remains as a manual fallback.
210
+
211
+ ## Autopilot daemon
212
+
213
+ A persistent orchestrator that ticks every 10 seconds, picks goals off the backlog, auto-reviews PRs, retries failed Agnets, and watches the budget. Opt-in -- nothing runs in the background unless you start it.
214
+
215
+ Five tick-loop phases:
216
+
217
+ 1. **Reconcile state** -- for every spawned Agnet, refresh from JSONL, PID, and exit-record; promote `died_at_launch` / `done` / `failed`.
218
+ 2. **Recover from failures** -- classify each failure via a Plan-billed `claude -p` turn, then retry with backoff, spawn a debugger Agnet, or escalate to the user via Telegram.
219
+ 3. **Auto-review PRs** -- fetch the diff, run a reviewer turn, apply the fleet template's auto-merge rule, and either `gh pr merge` or `gh pr comment`.
220
+ 4. **Pick the next goal** -- when the fleet is idle and autopilot is unpaused, pull the highest-priority unblocked goal from the backlog and prompt the user via Telegram.
221
+ 5. **Watch the budget** -- yellow / orange / red thresholds; auto-pause at orange.
222
+
223
+ CLI:
224
+
225
+ ```sh
226
+ orql autopilot start # foreground; daemonize with launchd / systemd / nohup
227
+ orql autopilot stop
228
+ orql autopilot pause # stop picking new work; in-flight Agnets keep running
229
+ orql autopilot resume
230
+ orql autopilot status
231
+ ```
232
+
233
+ Plan-billing note: the daemon **never** talks to the Anthropic API. Every intelligent decision (failure classifier, PR reviewer, Telegram intent classifier, template suggester) is a `claude -p` invocation. On the Max plan that bills like an interactive Claude Code session, and cache reads are free, so a full day of ticking burns a tiny fraction of quota.
234
+
235
+ ## Durable memory
236
+
237
+ A `memory.json` file at `<state_dir>/memory.json` holds long-lived facts that outlive plan lifecycles. Four spirit-themed categories, each with a different surfacing rule:
238
+
239
+ - **lore** -- facts about the user. Pinned, slow churn, injected into every spawned Agnet prompt. _Example: "Russian comments in CRM templates", "no auto-deploy on Fridays."_
240
+ - **playbook** -- code conventions. Scope-tagged by path-glob; injected when a fleet's scope overlaps. _Example: "migrations live in `<app>/migrations/`", "use AntD ConfigProvider for dark mode."_
241
+ - **ledger** -- decisions plus rationale. Append-only; surfaced when a similar decision recurs. _Example: "Sonnet over Opus for transcription, latency mattered more than depth."_
242
+ - **atlas** -- project map. Auto-updated by the post-PR review with one entry per touched file mapping path to purpose.
243
+
244
+ Pinned entries always load. Scope-tagged entries (typically playbook and atlas) auto-inject into a spawn prompt when the Agnet's worktree scope matches any of the entry's globs -- you don't have to remember to thread conventions through manually.
245
+
246
+ MCP tools:
247
+
248
+ ```
249
+ remember(category, key, value, { pinned?, scopeGlobs?, rationale? })
250
+ recall(category?, key?, scopeMatch?)
251
+ forget(category, key)
252
+ compose_memory_context(scopeGlobs?, max_tokens?)
253
+ ```
254
+
255
+ Older entries with the same `(category, key)` are soft-superseded: kept for history but invisible to read paths. `compose_memory_context` is the function the spawn pipeline uses internally; call it directly to preview the block that will be injected for a given scope before you commit to spawning.
256
+
257
+ ## Backlog
258
+
259
+ A `backlog.json` file holds `Goal` records -- durable task descriptions the daemon (or you) can pick from when idle.
260
+
261
+ Shape:
262
+
263
+ ```json
264
+ {
265
+ "id": "g_8f3...",
266
+ "title": "Rotate JWT signing keys quarterly",
267
+ "priority": 70,
268
+ "deadlineAt": "2026-06-30T00:00:00Z",
269
+ "dependsOn": ["g_5c1..."],
270
+ "createdAt": "2026-05-12T10:14:00Z",
271
+ "status": "pending"
272
+ }
273
+ ```
274
+
275
+ Priority is 0-100. `deadlineAt` boosts effective priority as the deadline approaches (linear ramp over the last 14 days, so something due tomorrow with priority 40 beats a no-deadline priority 70 item). `dependsOn` is a list of goal ids; a goal is blocked until every parent has `status: "done"`.
276
+
277
+ MCP tools:
278
+
279
+ ```
280
+ enqueue_goal(title, { priority?, deadlineAt?, dependsOn?, source? })
281
+ list_goals({ status?, includeBlocked? })
282
+ update_goal(id, { priority?, deadlineAt?, dependsOn?, status? })
283
+ pick_next_goal()
284
+ ```
285
+
286
+ `pick_next_goal` returns the highest-priority unblocked pending goal, factoring in deadline boost. The autopilot daemon calls this on every idle tick; when something comes back it surfaces the goal to the user via Telegram for confirmation before spawning a fleet, so you keep approval-in-the-loop even when the orchestrator is running unattended.
287
+
288
+ ## Fleet templates
289
+
290
+ Eight named patterns ship out of the box. Each defines a default Agnet layout, a suggested model per role (haiku / sonnet / opus), a default budget, and an `AutoMergeRule` the daemon applies to PRs produced by the fleet.
291
+
292
+ | id | what it does | auto-merge rule |
293
+ |---|---|---|
294
+ | `backend-feature` | Django/DRF: model + migration + serializer + viewset + admin + tests | requireCi, maxLoc 2500 |
295
+ | `frontend-feature` | React/AntD: components + hooks + i18n + tests | requireCi, maxLoc 2000 |
296
+ | `migration-only` | Schema change with backwards-compat reviewer (opus) | requireReviewerApprove; `blockOnMigrations: false` (migrations are the point) |
297
+ | `audit-sweep` | Multiple haiku auditors + sonnet synthesizer (read-only) | requireReviewerApprove (no merge) |
298
+ | `dep-upgrade` | Dep version bump + breaking-change patches + reviewer | requireCi, requireReviewerApprove |
299
+ | `i18n-pass` | Audit, then translator pass | requireCi, maxLoc 3000 |
300
+ | `test-coverage-fill` | Parallel testers; blocks PRs that touch prod code | requireCi, blockOnPaths globs for non-test files |
301
+ | `bug-hunt` | Reproducer Agnet then fixer Agnet (sequential) | requireReviewerApprove, requireCi |
302
+
303
+ MCP tools:
304
+
305
+ ```
306
+ list_fleet_templates()
307
+ suggest_fleet_template(goal_text) # Plan-billed turn picks the best fit
308
+ apply_fleet_template(template_id, { goal, scope, budget_override? })
309
+ ```
310
+
311
+ `suggest_fleet_template` makes a single `claude -p` call that returns `{ template_id, confidence, reason }`. The autopilot daemon uses this to turn a freeform goal description into a concrete fleet definition without manual plan authoring. `apply_fleet_template` then expands the chosen template into a real plan via `create_plan`, with the template's auto-merge rule attached for later use by the auto-review pipeline.
312
+
313
+ ## Auto-PR-review
314
+
315
+ When the autopilot daemon is running, every PR produced by a template-driven fleet gets a reviewer turn and an auto-merge attempt.
316
+
317
+ The reviewer turn runs `gh pr view` for the diff and metadata, feeds them into a strict-JSON `claude -p` prompt, and parses the response `{ verdict, blockers, suggestions, summary }` where `verdict` is `APPROVE` / `REQUEST_CHANGES` / `COMMENT`. The summary is appended as a PR comment regardless of verdict so you have a paper trail.
318
+
319
+ The fleet template's `AutoMergeRule` then decides whether to merge:
320
+
321
+ ```json
322
+ {
323
+ "requireReviewerApprove": true,
324
+ "requireCi": true,
325
+ "maxLoc": 2500,
326
+ "blockOnMigrations": false,
327
+ "blockOnPaths": ["**/settings.py", "**/secrets/**"]
328
+ }
329
+ ```
330
+
331
+ - `requireReviewerApprove` -- the reviewer's verdict must be `APPROVE`.
332
+ - `requireCi` -- `gh pr checks` must come back all-green.
333
+ - `maxLoc` -- additions plus deletions under cap. Larger PRs route to user.
334
+ - `blockOnMigrations` -- refuses PRs that add files under `*/migrations/` (used by templates that aren't supposed to touch schema).
335
+ - `blockOnPaths` -- refuses PRs touching specific globs.
336
+
337
+ If every check passes the daemon runs `gh pr merge --squash --auto --delete-branch`. Otherwise it `gh pr comment`s with the verdict and blockers and leaves the PR open. Each review writes a `ledger` memory entry so the next fleet inherits the rationale.
338
+
339
+ ## Cost guardrails
340
+
341
+ A `guardrails.json` rolling ledger tracks billed tokens against two windows: a 5-hour rolling window (matching Anthropic's Plan reset cadence) and a per-local-day soft cap (default 30M billed tokens).
342
+
343
+ Three threshold bands on the rolling window:
344
+
345
+ - **yellow** at 60% -- notify the user, daemon slows inter-tick interval.
346
+ - **orange** at 80% -- daemon auto-pauses; refuses to start new fleets; in-flight Agnets keep running but no new spawns happen.
347
+ - **red** at 95% -- halt entirely; await user `/resume` after the next 5h reset.
348
+
349
+ The day soft-cap applies independently of the rolling window -- you can sit comfortably in green on the 5h window and still cross the day cap if you've been running multiple windows back to back. Both checks happen on every autopilot tick, and the orange auto-pause uses the same code path as `orql autopilot pause`: it surfaces in `orql autopilot status` and is undone with `orql autopilot resume` once the window has rolled.
350
+
186
351
  ## State
187
352
 
188
353
  orqlaude resolves its state directory at startup using this order (first match wins):
@@ -101,6 +101,72 @@ test("v0.10.1: writing a response sets responded_at and persists", async () => {
101
101
  assert.equal(after?.response, "the answer");
102
102
  assert.ok(after?.respondedAt && after.respondedAt > 0);
103
103
  });
104
+ test("v0.10.3: findUserResponseRequest also searches orphan array", async () => {
105
+ // The bug: ask_user without plan_id puts the request in orphanResponseRequests.
106
+ // The bot's reply-to-message handler correctly searched both arrays, but
107
+ // findUserResponseRequest (used by poll_user_response and ask_user's own
108
+ // blocking poll) only searched plan-attached. Result: user answers an orphan
109
+ // question via Telegram, bot writes response into state, but the MCP-side
110
+ // discovery returns "unknown" and the blocking call times out — even though
111
+ // the answer exists in state.
112
+ const { findUserResponseRequest } = await import("../lib/state.js");
113
+ const dir = await tempDir("orphan-lookup");
114
+ const store = new StateStore(dir);
115
+ const id = "orphan-find-test-id-12345678";
116
+ await store.update((state) => {
117
+ state.orphanResponseRequests = state.orphanResponseRequests ?? [];
118
+ state.orphanResponseRequests.push({
119
+ id,
120
+ shortId: id.slice(0, 8),
121
+ prompt: "find me",
122
+ createdAt: Date.now(),
123
+ timeoutAt: Date.now() + 60_000,
124
+ delivered: false,
125
+ response: "the answer",
126
+ respondedAt: Date.now(),
127
+ });
128
+ });
129
+ const byFullId = await store.read((s) => findUserResponseRequest(s, id));
130
+ assert.ok(byFullId);
131
+ assert.equal(byFullId.req.response, "the answer");
132
+ assert.equal(byFullId.plan, undefined, "orphan requests have no parent plan");
133
+ const byShortId = await store.read((s) => findUserResponseRequest(s, id.slice(0, 8)));
134
+ assert.ok(byShortId);
135
+ assert.equal(byShortId.req.response, "the answer");
136
+ });
137
+ test("v0.10.3: plan-attached requests still take precedence over orphan", async () => {
138
+ // If somehow the same short_id collides (vanishingly unlikely with UUIDs
139
+ // but tests the resolution order), the plan-attached one wins because we
140
+ // walk plans first.
141
+ const { findUserResponseRequest, newPlan } = await import("../lib/state.js");
142
+ const dir = await tempDir("orphan-vs-plan");
143
+ const store = new StateStore(dir);
144
+ const sharedId = "collision-test-id-12345678abcd";
145
+ await store.update((state) => {
146
+ const plan = newPlan("test", 1000, [{ title: "t", tldr: "t", prompt: "p" }]);
147
+ plan.userResponseRequests.push({
148
+ id: sharedId,
149
+ shortId: sharedId.slice(0, 8),
150
+ prompt: "from plan",
151
+ createdAt: Date.now(),
152
+ timeoutAt: Date.now() + 60_000,
153
+ delivered: false,
154
+ });
155
+ state.plans[plan.id] = plan;
156
+ state.orphanResponseRequests = state.orphanResponseRequests ?? [];
157
+ state.orphanResponseRequests.push({
158
+ id: sharedId,
159
+ shortId: sharedId.slice(0, 8),
160
+ prompt: "from orphan",
161
+ createdAt: Date.now(),
162
+ timeoutAt: Date.now() + 60_000,
163
+ delivered: false,
164
+ });
165
+ });
166
+ const got = await store.read((s) => findUserResponseRequest(s, sharedId));
167
+ assert.equal(got.req.prompt, "from plan");
168
+ assert.ok(got.plan, "plan-attached match should include its plan");
169
+ });
104
170
  test("v0.10.1: cancelled requests short-circuit before answering", async () => {
105
171
  const dir = await tempDir("cancelled");
106
172
  const store = new StateStore(dir);
@@ -1 +1 @@
1
- {"version":3,"file":"v0101.test.js","sourceRoot":"","sources":["../../src/__tests__/v0101.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"v0101.test.js","sourceRoot":"","sources":["../../src/__tests__/v0101.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAEnD;;;;;;;;GAQG;AAEH,KAAK,UAAU,OAAO,CAAC,KAAa;IAClC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,kBAAkB,KAAK,GAAG,CAAC,CAAC,CAAC;AACxE,CAAC;AAED,IAAI,CAAC,oDAAoD,EAAE,GAAG,EAAE;IAC9D,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,6BAA6B,CAAC,EAAE,6BAA6B,CAAC,CAAC;IACrF,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC;IACzC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;AACjC,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,yEAAyE,EAAE,KAAK,IAAI,EAAE;IACzF,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,CAAC;IACpC,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC;IAClC,MAAM,EAAE,GAAG,2BAA2B,CAAC;IACvC,MAAM,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;QAC3B,KAAK,CAAC,sBAAsB,GAAG,KAAK,CAAC,sBAAsB,IAAI,EAAE,CAAC;QAClE,KAAK,CAAC,sBAAsB,CAAC,IAAI,CAAC;YAChC,EAAE;YACF,OAAO,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;YACvB,MAAM,EAAE,MAAM;YACd,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM;YAC9B,SAAS,EAAE,KAAK;SACjB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IACH,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,sBAAsB,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IACjG,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;IACjB,MAAM,CAAC,KAAK,CAAC,KAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACtC,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,sEAAsE,EAAE,KAAK,IAAI,EAAE;IACtF,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC;IACtC,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC;IAClC,2EAA2E;IAC3E,mDAAmD;IACnD,MAAM,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;QAC3B,KAAK,CAAC,sBAAsB,GAAG,KAAK,CAAC,sBAAsB,IAAI,EAAE,CAAC;QAClE,KAAK,CAAC,sBAAsB,CAAC,IAAI,CAAC;YAChC,EAAE,EAAE,OAAO;YACX,OAAO,EAAE,OAAO;YAChB,MAAM,EAAE,GAAG;YACX,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM;YAC9B,SAAS,EAAE,IAAI;YACf,iBAAiB,EAAE,EAAE;YACrB,cAAc,EAAE,GAAG;SACpB,CAAC,CAAC;QACH,KAAK,CAAC,sBAAsB,CAAC,IAAI,CAAC;YAChC,EAAE,EAAE,OAAO;YACX,OAAO,EAAE,OAAO;YAChB,MAAM,EAAE,GAAG;YACX,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM;YAC9B,SAAS,EAAE,IAAI;YACf,iBAAiB,EAAE,EAAE,EAAE,sBAAsB;YAC7C,cAAc,EAAE,GAAG,EAAE,yBAAyB;SAC/C,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IACH,oFAAoF;IACpF,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CACpC,CAAC,CAAC,CAAC,sBAAsB,IAAI,EAAE,CAAC,CAAC,IAAI,CACnC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,iBAAiB,KAAK,EAAE,IAAI,CAAC,CAAC,cAAc,KAAK,GAAG,CAC9D,CACF,CAAC;IACF,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CACpC,CAAC,CAAC,CAAC,sBAAsB,IAAI,EAAE,CAAC,CAAC,IAAI,CACnC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,iBAAiB,KAAK,EAAE,IAAI,CAAC,CAAC,cAAc,KAAK,GAAG,CAC9D,CACF,CAAC;IACF,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;IAClC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;AACpC,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;IAC5E,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC;IACtC,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC;IAClC,MAAM,EAAE,GAAG,gBAAgB,CAAC;IAC5B,MAAM,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;QAC3B,KAAK,CAAC,sBAAsB,GAAG,KAAK,CAAC,sBAAsB,IAAI,EAAE,CAAC;QAClE,KAAK,CAAC,sBAAsB,CAAC,IAAI,CAAC;YAChC,EAAE;YACF,OAAO,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;YACvB,MAAM,EAAE,GAAG;YACX,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM;YAC9B,SAAS,EAAE,KAAK;SACjB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IACH,MAAM,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;QAC3B,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,sBAAsB,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QAC1E,IAAI,GAAG,EAAE,CAAC;YACR,GAAG,CAAC,QAAQ,GAAG,YAAY,CAAC;YAC5B,GAAG,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC/B,CAAC;IACH,CAAC,CAAC,CAAC;IACH,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,sBAAsB,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IACjG,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC;IAC5C,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,IAAI,KAAK,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC;AACzD,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,6DAA6D,EAAE,KAAK,IAAI,EAAE;IAC7E,gFAAgF;IAChF,yEAAyE;IACzE,yEAAyE;IACzE,6EAA6E;IAC7E,0EAA0E;IAC1E,4EAA4E;IAC5E,8BAA8B;IAC9B,MAAM,EAAE,uBAAuB,EAAE,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAC;IACpE,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,eAAe,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC;IAClC,MAAM,EAAE,GAAG,8BAA8B,CAAC;IAC1C,MAAM,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;QAC3B,KAAK,CAAC,sBAAsB,GAAG,KAAK,CAAC,sBAAsB,IAAI,EAAE,CAAC;QAClE,KAAK,CAAC,sBAAsB,CAAC,IAAI,CAAC;YAChC,EAAE;YACF,OAAO,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;YACvB,MAAM,EAAE,SAAS;YACjB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM;YAC9B,SAAS,EAAE,KAAK;YAChB,QAAQ,EAAE,YAAY;YACtB,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;SACxB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,uBAAuB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IACzE,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;IACpB,MAAM,CAAC,KAAK,CAAC,QAAS,CAAC,GAAG,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IACnD,MAAM,CAAC,KAAK,CAAC,QAAS,CAAC,IAAI,EAAE,SAAS,EAAE,qCAAqC,CAAC,CAAC;IAC/E,MAAM,SAAS,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,uBAAuB,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACtF,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC;IACrB,MAAM,CAAC,KAAK,CAAC,SAAU,CAAC,GAAG,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;AACtD,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,mEAAmE,EAAE,KAAK,IAAI,EAAE;IACnF,yEAAyE;IACzE,yEAAyE;IACzE,oBAAoB;IACpB,MAAM,EAAE,uBAAuB,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAC;IAC7E,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC5C,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC;IAClC,MAAM,QAAQ,GAAG,gCAAgC,CAAC;IAClD,MAAM,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;QAC3B,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;QAC7E,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC;YAC7B,EAAE,EAAE,QAAQ;YACZ,OAAO,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;YAC7B,MAAM,EAAE,WAAW;YACnB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM;YAC9B,SAAS,EAAE,KAAK;SACjB,CAAC,CAAC;QACH,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC;QAC5B,KAAK,CAAC,sBAAsB,GAAG,KAAK,CAAC,sBAAsB,IAAI,EAAE,CAAC;QAClE,KAAK,CAAC,sBAAsB,CAAC,IAAI,CAAC;YAChC,EAAE,EAAE,QAAQ;YACZ,OAAO,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;YAC7B,MAAM,EAAE,aAAa;YACrB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM;YAC9B,SAAS,EAAE,KAAK;SACjB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,uBAAuB,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC1E,MAAM,CAAC,KAAK,CAAC,GAAI,CAAC,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC3C,MAAM,CAAC,EAAE,CAAC,GAAI,CAAC,IAAI,EAAE,6CAA6C,CAAC,CAAC;AACtE,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;IAC5E,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC;IAClC,MAAM,EAAE,GAAG,iBAAiB,CAAC;IAC7B,MAAM,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;QAC3B,KAAK,CAAC,sBAAsB,GAAG,KAAK,CAAC,sBAAsB,IAAI,EAAE,CAAC;QAClE,KAAK,CAAC,sBAAsB,CAAC,IAAI,CAAC;YAChC,EAAE;YACF,OAAO,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;YACvB,MAAM,EAAE,GAAG;YACX,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM;YAC9B,SAAS,EAAE,KAAK;YAChB,SAAS,EAAE,IAAI;SAChB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IACH,wCAAwC;IACxC,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE;QACxC,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,sBAAsB,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QAC1E,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC;QACtB,IAAI,GAAG,CAAC,SAAS;YAAE,OAAO,EAAE,IAAI,EAAE,WAAoB,EAAE,CAAC;QACzD,IAAI,GAAG,CAAC,QAAQ,KAAK,SAAS;YAAE,OAAO,EAAE,IAAI,EAAE,UAAmB,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC;QAC7F,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;IACH,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC;AAClD,CAAC,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,94 @@
1
+ import { test } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { promises as fs } from "node:fs";
4
+ import path from "node:path";
5
+ import os from "node:os";
6
+ /**
7
+ * v0.10.5 — spawn_via_cli pre-allocates session_id and embeds it in the
8
+ * fleet protocol prompt + checkin handler accepts rotation for freshly
9
+ * spawned tasks.
10
+ *
11
+ * Bug it fixes: orqlaude self-test fleet d47c0448 — Verdant tried to
12
+ * checkin with $CLAUDE_CODE_SESSION_ID (Claude Code's internal value)
13
+ * which differed from the --session-id flag orqlaude passed. The
14
+ * pre-allocation had already filled task.spawnedSessionId so
15
+ * unclaimedTaskById returned undefined, falling through to
16
+ * task_already_claimed rejection.
17
+ */
18
+ async function tempDir(label) {
19
+ return fs.mkdtemp(path.join(os.tmpdir(), `orqlaude-v0105-${label}-`));
20
+ }
21
+ test("v0.10.5: spawn_via_cli sessionId override flows through to --session-id flag", async () => {
22
+ // Verify the SpawnViaCliInput.sessionId field is honored. We can't actually
23
+ // spawn claude in unit tests (no binary), but we can confirm the type +
24
+ // pass-through logic by reading the source.
25
+ // import.meta.dirname under built dist/__tests__/ → ../../src/lib/spawn_cli.ts
26
+ // import.meta.dirname under built dist/__tests__/ → ../../src/lib/spawn_cli.ts
27
+ const src = await fs.readFile(path.join(import.meta.dirname, "..", "..", "src", "lib", "spawn_cli.ts"), "utf8");
28
+ // The fallback `?? randomUUID()` should be present so omitted sessionId
29
+ // still produces a uuid.
30
+ assert.ok(src.includes("input.sessionId ?? randomUUID()"), "sessionId fallback wiring missing");
31
+ assert.ok(src.includes("sessionId?:"), "sessionId field missing from SpawnViaCliInput");
32
+ });
33
+ test("v0.10.5: checkin accepts session-id rotation for freshly spawned tasks", async () => {
34
+ // Simulate the v0.10.4-and-earlier failure mode + verify v0.10.5 handles it.
35
+ const dir = await tempDir("checkin-rotate");
36
+ // Build a minimal state file with a pre-allocated spawnedSessionId.
37
+ const stateFile = path.join(dir, "orqlaude-state.json");
38
+ const planId = "plan-test-id-fixed";
39
+ const taskId = "task-test-id-fixed";
40
+ const preallocatedSessionId = "preallocated-session-id";
41
+ const agentSessionId = "agent-different-session-id";
42
+ const justStartedAt = Date.now() - 5_000; // 5s ago - within 60s grace
43
+ await fs.writeFile(stateFile, JSON.stringify({
44
+ schemaVersion: 3,
45
+ plans: {
46
+ [planId]: {
47
+ id: planId,
48
+ createdAt: Date.now(),
49
+ rootTask: "test",
50
+ budgetCapTokens: 1000,
51
+ perAgentCapTokens: 1000,
52
+ status: "running",
53
+ tasks: [
54
+ {
55
+ id: taskId,
56
+ title: "t",
57
+ prompt: "p",
58
+ tldr: "t",
59
+ status: "running",
60
+ spawnedSessionId: preallocatedSessionId,
61
+ startedAt: justStartedAt,
62
+ },
63
+ ],
64
+ notes: [],
65
+ messages: [],
66
+ claims: [],
67
+ userNotifications: [],
68
+ userResponseRequests: [],
69
+ userStreams: [],
70
+ },
71
+ },
72
+ }));
73
+ // We can't easily call the registered tool callback directly (it's wrapped
74
+ // through MCP). But we CAN verify the broker.ts source contains the
75
+ // rotation logic by reading it.
76
+ const brokerSrc = await fs.readFile(path.join(import.meta.dirname, "..", "..", "src", "tools", "broker.ts"), "utf8");
77
+ assert.ok(brokerSrc.includes("wasJustSpawned"), "broker.ts should have the wasJustSpawned rotation check");
78
+ assert.ok(brokerSrc.includes("noNotesYet"), "broker.ts should also gate rotation on no-notes-yet");
79
+ assert.ok(brokerSrc.includes("60_000"), "broker.ts should use 60s grace window for rotation");
80
+ });
81
+ test("v0.10.5: buildSpawnPrompt embeds session_id when provided", async () => {
82
+ // Pure source-level check that the prompt builder honors the sessionId arg.
83
+ const dispatchSrc = await fs.readFile(path.join(import.meta.dirname, "..", "..", "src", "tools", "dispatch.ts"), "utf8");
84
+ assert.ok(dispatchSrc.includes("sessionId?: string"), "buildSpawnPrompt should accept optional sessionId");
85
+ assert.ok(dispatchSrc.includes("EXACT value, pre-allocated by orqlaude"), "When sessionId is provided, the prompt should instruct the agent to use it exactly");
86
+ assert.ok(dispatchSrc.includes("NOT $CLAUDE_CODE_SESSION_ID"), "The protocol prompt should explicitly tell the agent NOT to use the env var");
87
+ });
88
+ test("v0.10.5: spawn_via_cli handler pre-generates session_id before buildSpawnPrompt", async () => {
89
+ const dispatchSrc = await fs.readFile(path.join(import.meta.dirname, "..", "..", "src", "tools", "dispatch.ts"), "utf8");
90
+ assert.ok(dispatchSrc.includes("presetSessionId = randomUUID()"), "spawn_via_cli handler should pre-allocate session_id with randomUUID");
91
+ assert.ok(/buildSpawnPrompt\([^)]*presetSessionId\)/.test(dispatchSrc), "presetSessionId should be passed into buildSpawnPrompt");
92
+ assert.ok(/sessionId:\s*presetSessionId/.test(dispatchSrc), "presetSessionId should be passed into spawnAgnetViaCli as sessionId");
93
+ });
94
+ //# sourceMappingURL=v0105.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"v0105.test.js","sourceRoot":"","sources":["../../src/__tests__/v0105.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB;;;;;;;;;;;GAWG;AAEH,KAAK,UAAU,OAAO,CAAC,KAAa;IAClC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,kBAAkB,KAAK,GAAG,CAAC,CAAC,CAAC;AACxE,CAAC;AAED,IAAI,CAAC,8EAA8E,EAAE,KAAK,IAAI,EAAE;IAC9F,4EAA4E;IAC5E,wEAAwE;IACxE,4CAA4C;IAC5C,+EAA+E;IAC/E,+EAA+E;IAC/E,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAAC;IAChH,wEAAwE;IACxE,yBAAyB;IACzB,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,iCAAiC,CAAC,EAAE,mCAAmC,CAAC,CAAC;IAChG,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,+CAA+C,CAAC,CAAC;AAC1F,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,wEAAwE,EAAE,KAAK,IAAI,EAAE;IACxF,6EAA6E;IAC7E,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC5C,oEAAoE;IACpE,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,qBAAqB,CAAC,CAAC;IACxD,MAAM,MAAM,GAAG,oBAAoB,CAAC;IACpC,MAAM,MAAM,GAAG,oBAAoB,CAAC;IACpC,MAAM,qBAAqB,GAAG,yBAAyB,CAAC;IACxD,MAAM,cAAc,GAAG,4BAA4B,CAAC;IACpD,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC,4BAA4B;IACtE,MAAM,EAAE,CAAC,SAAS,CAChB,SAAS,EACT,IAAI,CAAC,SAAS,CAAC;QACb,aAAa,EAAE,CAAC;QAChB,KAAK,EAAE;YACL,CAAC,MAAM,CAAC,EAAE;gBACR,EAAE,EAAE,MAAM;gBACV,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;gBACrB,QAAQ,EAAE,MAAM;gBAChB,eAAe,EAAE,IAAI;gBACrB,iBAAiB,EAAE,IAAI;gBACvB,MAAM,EAAE,SAAS;gBACjB,KAAK,EAAE;oBACL;wBACE,EAAE,EAAE,MAAM;wBACV,KAAK,EAAE,GAAG;wBACV,MAAM,EAAE,GAAG;wBACX,IAAI,EAAE,GAAG;wBACT,MAAM,EAAE,SAAS;wBACjB,gBAAgB,EAAE,qBAAqB;wBACvC,SAAS,EAAE,aAAa;qBACzB;iBACF;gBACD,KAAK,EAAE,EAAE;gBACT,QAAQ,EAAE,EAAE;gBACZ,MAAM,EAAE,EAAE;gBACV,iBAAiB,EAAE,EAAE;gBACrB,oBAAoB,EAAE,EAAE;gBACxB,WAAW,EAAE,EAAE;aAChB;SACF;KACF,CAAC,CACH,CAAC;IACF,2EAA2E;IAC3E,oEAAoE;IACpE,gCAAgC;IAChC,MAAM,SAAS,GAAG,MAAM,EAAE,CAAC,QAAQ,CACjC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,CAAC,EACvE,MAAM,CACP,CAAC;IACF,MAAM,CAAC,EAAE,CACP,SAAS,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EACpC,yDAAyD,CAC1D,CAAC;IACF,MAAM,CAAC,EAAE,CACP,SAAS,CAAC,QAAQ,CAAC,YAAY,CAAC,EAChC,qDAAqD,CACtD,CAAC;IACF,MAAM,CAAC,EAAE,CACP,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAC5B,oDAAoD,CACrD,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;IAC3E,4EAA4E;IAC5E,MAAM,WAAW,GAAG,MAAM,EAAE,CAAC,QAAQ,CACnC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,aAAa,CAAC,EACzE,MAAM,CACP,CAAC;IACF,MAAM,CAAC,EAAE,CACP,WAAW,CAAC,QAAQ,CAAC,oBAAoB,CAAC,EAC1C,mDAAmD,CACpD,CAAC;IACF,MAAM,CAAC,EAAE,CACP,WAAW,CAAC,QAAQ,CAAC,wCAAwC,CAAC,EAC9D,oFAAoF,CACrF,CAAC;IACF,MAAM,CAAC,EAAE,CACP,WAAW,CAAC,QAAQ,CAAC,6BAA6B,CAAC,EACnD,6EAA6E,CAC9E,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,iFAAiF,EAAE,KAAK,IAAI,EAAE;IACjG,MAAM,WAAW,GAAG,MAAM,EAAE,CAAC,QAAQ,CACnC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,aAAa,CAAC,EACzE,MAAM,CACP,CAAC;IACF,MAAM,CAAC,EAAE,CACP,WAAW,CAAC,QAAQ,CAAC,gCAAgC,CAAC,EACtD,sEAAsE,CACvE,CAAC;IACF,MAAM,CAAC,EAAE,CACP,0CAA0C,CAAC,IAAI,CAAC,WAAW,CAAC,EAC5D,wDAAwD,CACzD,CAAC;IACF,MAAM,CAAC,EAAE,CACP,8BAA8B,CAAC,IAAI,CAAC,WAAW,CAAC,EAChD,qEAAqE,CACtE,CAAC;AACJ,CAAC,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function cmdBacklog(stateDir: string, args: string[]): Promise<number>;