@adhdev/daemon-core 1.0.18-rc.5 → 1.0.18-rc.7

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.
@@ -58,6 +58,8 @@ import {
58
58
  COMPLETED_FINALIZATION_MAX_WAIT_MS,
59
59
  NATIVE_HISTORY_MESH_IDLE_SETTLE_MS,
60
60
  PTY_PARSED_FINAL_ASSISTANT_QUIET_DWELL_MS,
61
+ ANTIGRAVITY_HOLD_QUIET_DWELL_MS,
62
+ ANTIGRAVITY_HOLD_HARD_CAP_MS,
61
63
  BACKGROUND_TASK_HOLD_MAX_MS,
62
64
  USER_INPUT_ACK_DEDUP_WINDOW_MS,
63
65
  STARTUP_GRACE_IDLE_COLLAPSE_WINDOW_MS,
@@ -1897,6 +1899,33 @@ export class CliProviderInstance implements ProviderInstance {
1897
1899
  return false;
1898
1900
  }
1899
1901
 
1902
+ // (ANTIGRAVITY-30S-CAP-PREMATURE) Discriminator gating the 30s-cap release of an antigravity
1903
+ // `holdForTranscript` block. Antigravity's idle verdict is PTY-screen-derived but its assistant
1904
+ // answer lands in native-history, which can legitimately lag past COMPLETED_FINALIZATION_MAX_WAIT_MS
1905
+ // (30s) on a long turn. The cap releases on elapsed time, not proof-of-idle, so it force-emitted a
1906
+ // premature weak completion WHILE THE PTY WAS STILL GENERATING. Returns true when the PTY is still
1907
+ // active — i.e. the adapter reports a pending response OR raw PTY output arrived within the last
1908
+ // ANTIGRAVITY_HOLD_QUIET_DWELL_MS — meaning the 30s cap must KEEP HOLDING (the turn is not proven
1909
+ // over). Returns false when the PTY is genuinely quiescent (no pending response AND no recent
1910
+ // output), so a real tool-only turn with no assistant bubble still force-emits a weak completion
1911
+ // rather than wedging. The absolute ANTIGRAVITY_HOLD_HARD_CAP_MS bound is enforced at the call site
1912
+ // so a runaway PTY that never falls quiet still eventually releases. Fails OPEN (returns false =
1913
+ // allow release) when lastOutputAt is unreadable, so the gate can never wedge a session.
1914
+ private antigravityHoldPtyStillActive(): boolean {
1915
+ if (this.hasAdapterPendingResponse()) return true;
1916
+ try {
1917
+ const outStatus = this.adapter.getStatus({ allowParse: false }) as any;
1918
+ const lastOutputAt = typeof outStatus?.lastOutputAt === 'number' && Number.isFinite(outStatus.lastOutputAt)
1919
+ ? outStatus.lastOutputAt as number
1920
+ : undefined;
1921
+ if (typeof lastOutputAt === 'number') {
1922
+ const quietMs = Date.now() - lastOutputAt;
1923
+ if (quietMs < ANTIGRAVITY_HOLD_QUIET_DWELL_MS) return true;
1924
+ }
1925
+ } catch { /* defensive: dwell read is best-effort — fall through to allow release */ }
1926
+ return false;
1927
+ }
1928
+
1900
1929
  private shouldSuppressStaleParsedBusyStatus(parsedStatus: any, adapterStatus: any): boolean {
1901
1930
  const parsedRawStatus = typeof parsedStatus?.status === 'string' ? parsedStatus.status.trim() : '';
1902
1931
  const adapterRawStatus = typeof adapterStatus?.status === 'string' ? adapterStatus.status.trim() : '';
@@ -2751,6 +2780,42 @@ export class CliProviderInstance implements ProviderInstance {
2751
2780
  this.scheduleCompletedDebounceFlush(COMPLETED_FINALIZATION_RETRY_MS);
2752
2781
  return;
2753
2782
  }
2783
+ // (ANTIGRAVITY-30S-CAP-PREMATURE) The 30s cap has been reached for an antigravity
2784
+ // `holdForTranscript` block. The cap releases on ELAPSED TIME, not proof-of-idle — but
2785
+ // antigravity is native-source (assistant answer in native-history) with a PTY-derived
2786
+ // idle verdict, so the transcript's final assistant bubble can legitimately land past 30s
2787
+ // on a long turn. Releasing here would fire a premature weak completed/idle to the
2788
+ // coordinator WHILE THE PTY IS STILL GENERATING (the live-reproduced defect). Gate the
2789
+ // release on the PTY being genuinely quiet: if it is still active (adapter pending
2790
+ // response OR raw output within ANTIGRAVITY_HOLD_QUIET_DWELL_MS) and we are under the
2791
+ // absolute ANTIGRAVITY_HOLD_HARD_CAP_MS bound, KEEP HOLDING (re-probe next retry — the
2792
+ // transcript branch above clears the block for a genuine emit once the answer lands).
2793
+ // A genuinely quiescent tool-only turn (no assistant bubble, PTY stable) falls through
2794
+ // to the existing weak force-emit; a runaway PTY that never quiets releases at the hard
2795
+ // cap so it cannot wedge forever. Scoped to antigravity holdForTranscript so
2796
+ // claude-cli/codex-cli completion timing is unchanged.
2797
+ if (this.type === 'antigravity-cli'
2798
+ && block.holdForTranscript === true
2799
+ && waitedMs < ANTIGRAVITY_HOLD_HARD_CAP_MS
2800
+ && this.antigravityHoldPtyStillActive()) {
2801
+ if (pending.loggedBlockReason !== 'antigravity_hold_pty_active') {
2802
+ LOG.info('CLI', `[${this.type}] 30s cap reached but PTY still generating; holding antigravity completion past cap (waitedMs=${waitedMs} hardCap=${ANTIGRAVITY_HOLD_HARD_CAP_MS}) (${blockReason})`);
2803
+ if (this.isMeshWorkerSession()) {
2804
+ traceMeshEventDrop('completion_gate_hold', this.meshTraceCtx(), `antigravity_hold_pty_active waited=${waitedMs}ms`);
2805
+ }
2806
+ if (this.completionTraceOn()) this.recordCompletionGateTrace('hold', {
2807
+ blockReason,
2808
+ latestVisibleStatus,
2809
+ terminal: block.terminal === true,
2810
+ holdForTranscript: true,
2811
+ antigravityPtyStillActive: true,
2812
+ waitedMs,
2813
+ });
2814
+ pending.loggedBlockReason = 'antigravity_hold_pty_active';
2815
+ }
2816
+ this.scheduleCompletedDebounceFlush(COMPLETED_FINALIZATION_RETRY_MS);
2817
+ return;
2818
+ }
2754
2819
  const emittedAfterFinalizationTimeout = waitedMs >= COMPLETED_FINALIZATION_MAX_WAIT_MS;
2755
2820
  const completionDiagnostic = this.buildCompletedFinalizationDiagnostic({
2756
2821
  blockReason,