squadrant 0.13.3 → 0.13.4

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.
@@ -1974,6 +1974,7 @@ var CaptainDelivery = class {
1974
1974
  // packages/core/dist/daemon/delivery-loop.js
1975
1975
  var CURSOR_SUBSCRIBER = "captain";
1976
1976
  var CAPTAIN_GONE_STREAK_K = 3;
1977
+ var TERMINAL_KINDS = /* @__PURE__ */ new Set(["task.done", "task.failed", "task.cancelled", "task.blocked"]);
1977
1978
  function discoverCaptainSurface(surfaces, captainTitle) {
1978
1979
  return surfaces.find((s) => s.title === captainTitle) ?? null;
1979
1980
  }
@@ -2066,13 +2067,19 @@ function createDelivery(ctx, daemonCmux) {
2066
2067
  }
2067
2068
  for await (const entry of readFromCursor({ stateRoot, project, fromSeq: lastAcked + 1 })) {
2068
2069
  if (new Date(entry.ts).getTime() < sessionStartMs - STALE_THRESHOLD_MS) {
2069
- await writeCursor({ stateRoot, project, subscriber: CURSOR_SUBSCRIBER, lastAckedSeq: entry.seq });
2070
- continue;
2070
+ if (!TERMINAL_KINDS.has(entry.kind)) {
2071
+ log(`delivery seq=${entry.seq} kind=${entry.kind} outcome=stale-skipped`);
2072
+ await writeCursor({ stateRoot, project, subscriber: CURSOR_SUBSCRIBER, lastAckedSeq: entry.seq });
2073
+ continue;
2074
+ }
2075
+ log(`delivery seq=${entry.seq} kind=${entry.kind} outcome=stale-terminal-deliver`);
2071
2076
  }
2072
2077
  const result = await d.deliver(entry, (text, sendOpts) => cmux2.send(surface, text, sendOpts));
2073
2078
  if ("delivered" in result) {
2079
+ log(`delivery seq=${entry.seq} kind=${entry.kind} outcome=delivered`);
2074
2080
  await writeCursor({ stateRoot, project, subscriber: CURSOR_SUBSCRIBER, lastAckedSeq: entry.seq });
2075
2081
  } else {
2082
+ log(`delivery seq=${entry.seq} kind=${entry.kind} outcome=deferred`);
2076
2083
  break;
2077
2084
  }
2078
2085
  }
@@ -4388,7 +4395,7 @@ function parseDraftFromScreen(screen) {
4388
4395
  }
4389
4396
  return "";
4390
4397
  }
4391
- function readInputBoxRaw(screen) {
4398
+ function readInputBoxRaw(screen, opts) {
4392
4399
  if (!screen)
4393
4400
  return null;
4394
4401
  const lines = screen.split(/\r?\n/);
@@ -4414,7 +4421,8 @@ function readInputBoxRaw(screen) {
4414
4421
  s = s.replace(/\s*[▌█▔▎▏]+\s*$/, "");
4415
4422
  parts.push(s);
4416
4423
  }
4417
- return parts.join("").replace(/\s+$/, "");
4424
+ const joined = parts.join("");
4425
+ return opts?.trim === false ? joined : joined.replace(/\s+$/, "");
4418
4426
  }
4419
4427
  function sendDebugEnabled() {
4420
4428
  return !!process.env.SQUADRANT_DEBUG_SEND;
@@ -4428,6 +4436,19 @@ function classifySendOutcome(payload, postBox) {
4428
4436
  return "stuck";
4429
4437
  return "unknown";
4430
4438
  }
4439
+ function classifyDraftLiveness(before, after) {
4440
+ if (before === null || after === null)
4441
+ return "inconclusive";
4442
+ if (after === "")
4443
+ return "no-draft";
4444
+ if (before.length > 0) {
4445
+ const segs = [...new Intl.Segmenter().segment(before)];
4446
+ const expected = segs.slice(0, -1).map((s) => s.segment).join("").replace(/\s+$/, "");
4447
+ if (after === expected)
4448
+ return "real-draft";
4449
+ }
4450
+ return "inconclusive";
4451
+ }
4431
4452
  function createCmuxDriver() {
4432
4453
  return {
4433
4454
  name: "cmux",
@@ -4625,18 +4646,38 @@ function createCmuxDriver() {
4625
4646
  if (!opts?.probe)
4626
4647
  throw new DeferDelivery(draft);
4627
4648
  const before = readInputBoxRaw(screen);
4649
+ const rawBefore = readInputBoxRaw(screen, { trim: false });
4628
4650
  await cmux(["send-key", "--workspace", ws, "--surface", sf, "backspace"]);
4651
+ await new Promise((r) => setTimeout(r, 50));
4629
4652
  let afterScreen = "";
4630
4653
  try {
4631
4654
  afterScreen = await cmux(["read-screen", "--workspace", ws, "--surface", sf]);
4632
4655
  } catch {
4633
4656
  }
4634
4657
  const after = readInputBoxRaw(afterScreen);
4635
- if (before !== null && after !== null && after.length > 0 && after === before.slice(0, -1)) {
4636
- await cmux(["send", "--workspace", ws, "--surface", sf, before.slice(-1)]);
4658
+ const rawAfter = readInputBoxRaw(afterScreen, { trim: false });
4659
+ const liveness = classifyDraftLiveness(before, after);
4660
+ if (liveness === "real-draft") {
4661
+ const segs = before ? [...new Intl.Segmenter().segment(before)] : [];
4662
+ const lastGrapheme = segs.length > 0 ? segs[segs.length - 1].segment : before.slice(-1);
4663
+ await cmux(["send", "--workspace", ws, "--surface", sf, lastGrapheme]);
4637
4664
  throw new DeferDelivery(draft);
4638
4665
  }
4639
- await deliver();
4666
+ if (liveness === "no-draft") {
4667
+ await deliver();
4668
+ return;
4669
+ }
4670
+ if (rawBefore !== null && rawAfter !== null) {
4671
+ if (rawBefore !== rawAfter) {
4672
+ const segs = [...new Intl.Segmenter().segment(rawBefore)];
4673
+ const lastGrapheme = segs.length > 0 ? segs[segs.length - 1].segment : rawBefore.slice(-1);
4674
+ await cmux(["send", "--workspace", ws, "--surface", sf, lastGrapheme]);
4675
+ throw new DeferDelivery(draft);
4676
+ }
4677
+ await deliver();
4678
+ return;
4679
+ }
4680
+ throw new DeferDelivery(draft);
4640
4681
  },
4641
4682
  async listSurfaces(workspaceId) {
4642
4683
  let output;