Commit graph

2667 commits

Author SHA1 Message Date
Jeremy McSpadden
313658586a Merge pull request #3676 from Tibsfox/fix/stop-projection-overwriting-plan
fix(gsd): stop renderAllProjections from overwriting authoritative PLAN.md
2026-04-07 06:55:45 -05:00
Jeremy McSpadden
128ddba5df Merge pull request #3677 from Tibsfox/fix/pre-execution-checks-false-positives
fix(gsd): fix pre-execution-checks false positives from backticks and task.files
2026-04-07 06:03:44 -05:00
Jeremy McSpadden
69007b594f Merge pull request #3656 from Tibsfox/fix/auto-dispatch-planning-stuck 2026-04-07 04:22:49 -05:00
Tibsfox
6fa3a6ac94 test: move missing file refs from task.files to task.inputs per #3626 fix 2026-04-06 23:01:34 -07:00
Tibsfox
f8e98de19f fix(test): update stuck-planning test to expect executing after reconciliation
The fix reconciles plan-file tasks into the DB when the planner skips
persistence, so the phase correctly advances to executing instead of
remaining stuck in planning. Update the known-issue test to expect the
fixed behavior.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 22:42:17 -07:00
Tibsfox
9479fe07bd fix(test): update file path consistency tests for inputs-only checking
The fix changed checkFilePathConsistency to only check task.inputs, not
task.files, since files includes paths the task will create. Update tests
to use inputs instead of files for consistency checks.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 22:40:29 -07:00
Tibsfox
8dd8744b91 test: add regression test for pre-execution backtick strip and inputs-only check
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 22:26:53 -07:00
Tibsfox
08ebf3387d test: add regression test for projection plan overwrite prevention
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 22:26:06 -07:00
Tibsfox
9475757d9a test: add regression test for dispatcher stuck-planning reconciliation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 22:25:10 -07:00
github-actions[bot]
a1fb64a6ba release: v2.65.0 2026-04-07 04:25:48 +00:00
Jeremy McSpadden
97bd6bf0ee Merge pull request #3700 from jeremymcs/fix/notification-overlay-backdrop
fix(gsd): wrap notification messages and fit overlay to content
2026-04-06 23:05:27 -05:00
Jeremy
5b959648f9 test(gsd): add wrapText tests for notification overlay wrapping
Tests cover: short text, long wrapping, single-word truncation,
empty string, exact-fit, and word preservation across lines.
2026-04-06 22:52:46 -05:00
Jeremy
073a6dc546 fix(gsd): wrap long notification messages and fit overlay to content
Long messages now word-wrap onto continuation lines aligned with the
message start instead of being truncated with ellipsis. Overlay box
sizes to content height instead of padding to fill the viewport.
2026-04-06 22:49:14 -05:00
Jeremy McSpadden
bd574d412e Merge pull request #3666 from jeremymcs/fix/notification-overlay-backdrop
fix(gsd): notification overlay backdrop and truncation fixes
2026-04-06 21:01:17 -05:00
Tibsfox
08a79875bb fix(gsd): fix pre-execution-checks false positives from backticks and task.files
Three fixes:
1. Strip backtick wrapping in normalizeFilePath — LLM-generated paths
   like \`src/foo.ts\` resolve to nonexistent paths, causing false blocks
2. Exclude task.files from existence checks — it includes files the task
   will create, so they legitimately don't pre-exist
3. Lower minimum task count from 2 to 1 — single-task slices are valid
   per the planning prompt

Closes #3649
Closes #3626

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 19:00:47 -07:00
Tibsfox
bf0e3fb0e4 fix(gsd): stop renderAllProjections from overwriting authoritative PLAN.md
renderAllProjections called renderPlanProjection which overwrote the
complete PLAN.md (from markdown-renderer.js) with a simplified projection
missing Must-Haves, Verification, Files Likely Touched sections and
corrupting multi-line task descriptions.

Remove the plan projection call from renderAllProjections — the
authoritative renderer in plan-slice/replan-slice tools is the sole
writer. The renderIfMissing recovery path is preserved for when the
file is actually missing.

Closes #3651

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 18:59:00 -07:00
Jeremy
af158235eb fix(gsd): remove background color from backdrop, fix message truncation
Backdrop was painting empty lines with dark gray background (48;5;233),
making the entire screen go black. Now uses dim + gray foreground only.

Message truncation now measures actual prefix width with visibleWidth()
instead of hardcoded 20-char estimate, and uses truncateToWidth() for
proper Unicode handling.
2026-04-06 20:11:07 -05:00
Tibsfox
b1d9798e30 fix(gsd): reconcile plan-file tasks into DB when planner skips persistence (#3600)
When the planning agent writes S##-PLAN.md with task entries but never
calls the gsd_plan_slice persistence tool, the DB has zero task rows
even though the plan file on disk contains valid tasks. This causes
deriveState to return phase='planning' forever — the auto-mode
dispatcher re-dispatches plan-slice in an infinite loop.

Add a reconciliation step in deriveStateFromDb: when the DB returns zero
tasks but the plan file exists and contains parsed tasks, import them
into the DB so the state machine can advance past planning into
execution. This mirrors the existing #2514 reconciliation pattern for
stale task status.

Fixes #3600

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 17:51:33 -07:00
Jeremy
41d5189c4c fix(gsd): restore consistent overlay height to prevent ghost artifacts
Differential renderer can't clear old overlay positions when height
changes between filter cycles. Pad to maxVisibleRows so the overlay
stays the same size regardless of filter state.
2026-04-06 19:31:32 -05:00
Jeremy McSpadden
b4c6229360 Merge pull request #3646 from jeremymcs/fix/notification-overlay-backdrop
fix(gsd): notification overlay backdrop and sizing
2026-04-06 19:09:22 -05:00
Jeremy
2c91b8c6d8 test(tui): add test for 256-color backdrop codes 2026-04-06 18:57:02 -05:00
Jeremy
c35385fe53 fix(gsd): improve notification overlay backdrop and content-fit sizing
Use dark gray background + dim foreground for visible backdrop effect
instead of barely-perceptible SGR dim. Size overlay box to content
instead of padding to fill the entire viewport.
2026-04-06 18:53:26 -05:00
Jeremy McSpadden
6d2345e939 Merge pull request #3638 from jeremymcs/fix/notification-overlay-backdrop
fix(gsd): notification overlay backdrop dimming and viewport padding
2026-04-06 18:27:52 -05:00
Jeremy
9d1e343e41 test(gsd): add overlay backdrop and notification lock safety tests
- Overlay layout: verify backdrop dims base lines, no dim without flag,
  overlay composites on top of dimmed background
- Notification store: verify markAllRead and clearNotifications do not
  delete a foreign process's lock file
2026-04-06 17:44:34 -05:00
Jeremy
d553455732 fix(gsd): only unlink notification lock when owned, prevent foreign lock deletion
_withLock() was unconditionally unlinking the lock file in finally,
even when lock acquisition failed. This could delete another process's
lock and allow unlocked concurrent writes. Now tracks ownership and
only cleans up locks we created.
2026-04-06 17:39:44 -05:00
Jeremy
2c4ac844f1 fix(gsd): add backdrop dimming and viewport padding to notification overlay
The notification overlay was rendering too small with few entries, allowing
underlying content to bleed through. Added viewport padding to fill the
overlay box and a new `backdrop` option to OverlayOptions that dims the
background behind modal overlays.
2026-04-06 17:34:45 -05:00
Jeremy McSpadden
42caabdd0d Merge pull request #3563 from Tibsfox/fix/headless-discuss-multi-turn
fix(headless): treat discuss and plan as multi-turn commands
2026-04-06 15:58:04 -05:00
Jeremy McSpadden
d26efa47bc Merge pull request #3591 from jeremymcs/fix/complete-slice-provides-string-coercion
fix(gsd): coerce plain-string provides field to array in complete-slice
2026-04-06 15:57:16 -05:00
Jeremy McSpadden
c53f8ab471 Merge pull request #3608 from deseltrus/perf/session-memory-cpu-leaks
perf: fix CPU/memory leaks in long-running sessions
2026-04-06 15:56:22 -05:00
Jeremy McSpadden
d877e6e152 Merge pull request #3627 from jeremymcs/fix/3615-continue-context-injection
fix(gsd): inject task context for unstructured resume prompts (#3615)
2026-04-06 12:27:43 -05:00
Jeremy
04dc4a988b fix(gsd): add intent + phase guards to resume context fallback (#3615)
Tighten the deriveState fallback per adversarial review:
- Intent-gated: only fire for low-entropy resume prompts via
  RESUME_INTENT_PATTERNS (continue, ok, go ahead, resume, etc.)
- Phase-gated: only during state.phase === "executing"
- Non-resume prompts (help, status, abort, diagnostics) are not
  hijacked with execution context

Add behavioral tests: 24 positive matches + 17 negative rejections
for the intent pattern, alongside the 5 structural tests.
2026-04-06 12:14:36 -05:00
Jeremy
5b104897c8 fix(gsd): inject task context for unstructured resume prompts (#3615)
When a user types "continue" or bare text to resume an in-progress
session, buildGuidedExecuteContextInjection() only matched two
hardcoded regex patterns and returned null for anything else — causing
the agent to rebuild everything from scratch and burn ~86k tokens.

Add a phase-gated deriveState fallback that injects task execution
context when state.phase === "executing" and an active task exists.
The phase guard prevents misrouting during replanning, gate evaluation,
or other non-execution phases.
2026-04-06 12:10:08 -05:00
Jeremy McSpadden
0d87df94be Merge pull request #3619 from frizynn/fix/3618-schema-overload-bash-exit-code
fix(agent-loop): schema overload cap ignores bash execution errors (#3618)
2026-04-06 10:13:03 -05:00
Jeremy McSpadden
4aa7fe3940 Merge pull request #3621 from jeremymcs/fix/3616-db-tools-missing-subagent
fix(pi-coding-agent): restore extension tools after session switch (#3616)
2026-04-06 10:12:32 -05:00
Jeremy
90feebeccf fix(pi-coding-agent): restore extension tools after session switch (#3616)
newSession() only rebuilt the tool registry when cwd changed. When cwd
stayed the same (e.g., discuss → plan-slice in the same worktree), any
tool narrowing from setActiveTools() persisted — stripping gsd_plan_slice
and other DB tools from auto-mode subagent sessions.

Add an else-branch that calls _refreshToolRegistry with
includeAllExtensionTools:true on every session switch, regardless of cwd.

Also call resetExtensionLoaderCache() in DefaultResourceLoader.reload()
so hot-updated extension code on disk is re-compiled instead of served
from the stale jiti module cache.

Closes #3616
2026-04-06 09:51:58 -05:00
frizynn
cd14a4c765 fix(agent-loop): schema overload cap ignores bash execution errors (#3618)
The schema overload detector counted ALL isError tool results toward the
consecutive-failure cap, including bash commands that returned non-zero exit
codes (e.g. rg/grep exit 1 = 'no matches'). Three consecutive exploratory
searches with no matches would trigger the cap and abort the session.

Root cause: the allToolsFailed check used toolResults.every(r => r.isError)
which conflates preparation-phase errors (schema validation, tool-not-found,
tool-blocked) with execution-phase errors (the tool ran successfully but
returned a non-zero exit code).

Fix: track preparationErrorCount alongside tool results. Only preparation
errors (schema/validation failures) increment the consecutive failure
counter. Tool execution errors — like bash exit code 1 — are valid usage
and do not count toward the cap.

Also fixes pre-existing StopReason type mismatches in agent-loop tests
(end_turn → stop, tool_use → toolUse).
2026-04-06 11:35:41 -03:00
deseltrus
4744e86c8f test: structural regression tests for session memory/CPU leak fixes
Verifies that defensive guards (render-skip, chat cap, dispose, signal
handler cleanup, alert cap, orphan kill) are present in source. These
are structural tests because the leaks manifest over hours of real
usage, not in unit test timescales.
2026-04-06 09:57:40 +02:00
deseltrus
886c5837ff fix(bg-shell): prevent signal handler accumulation + cap alert queue
Signal handlers (SIGTERM, SIGINT, beforeExit) were registered on every
session_start but never removed. Over multiple sessions within the same
process, handlers accumulated — each adding another cleanupAll() call
and descendant kill sweep on exit.

Fix: session_shutdown now calls process.off() for each handler before
cleanupAll(), preventing accumulation.

Also: signalCleanup now kills ALL descendant processes (not just those
tracked by bg-shell) to catch bash-tool spawned children.

Alert queue: pendingAlerts is capped at 50 entries to prevent unbounded
growth when background processes generate rapid alerts faster than the
agent consumes them.

pushAlert signature updated to accept null bg parameter for system-level
alerts that don't originate from a tracked process.
2026-04-06 09:52:36 +02:00
deseltrus
0b40d39b0e perf(interactive): cap rendered chat components + kill orphan descendants
Chat component cap: After 100 rendered components, oldest are removed
from the container (session transcript persists on disk via
SessionManager). Prevents unbounded memory growth in long sessions
where thousands of tool calls accumulate DOM-like component trees.

Orphan process prevention: On shutdown, listDescendants(process.pid)
finds ALL child processes (including those spawned by the Bash tool
that bg-shell doesn't track) and kills them with SIGTERM + 500ms
grace + SIGKILL. Prevents orphaned dev servers, build processes, etc.
from persisting after session exit.
2026-04-06 09:52:20 +02:00
deseltrus
c5227f7570 perf(tui): render-skip, frame isolation, Text cache guard, dispose
Container.render() now returns a stable array reference when output is
unchanged — TUI.doRender() skips ALL post-processing (isImageLine scans,
applyLineResets, differential diffs) when the reference matches.

Loader decouples spinner frame rotation from Text content updates.
Previously every 80ms tick called setText() which invalidated Text's
wrapTextWithAnsi/visibleWidth caches. Now the frame is prepended in
render() while Text caches the message separately.

Text.setText() returns early when text is unchanged, avoiding cache
invalidation on redundant updates.

ToolExecutionComponent.dispose() clears heavy references (image maps,
diff previews, result data) so GC can reclaim memory when components
are removed from the chat history.
2026-04-06 09:52:08 +02:00
Jeremy McSpadden
6dfc422990 Merge pull request #3587 from jeremymcs/feat/persistent-notification-panel
feat(gsd): persistent notification panel
2026-04-05 22:53:30 -05:00
Jeremy
9616b02c58 fix(gsd): coerce plain-string provides field to array in complete-slice (#3585)
LLMs sometimes pass simple string-array fields (provides, keyFiles, etc.)
as a plain string instead of a single-element array, causing TypeBox schema
validation to reject the call before the execute function's coercion logic
can run. Fix by accepting Union([Array, String]) in the schema and adding
wrapArray() coercion for all 8 simple array fields in the execute function.
2026-04-05 22:15:13 -05:00
Jeremy
8078755e4b feat(gsd): persistent notification panel with TUI overlay, widget, and web API
Notifications from ctx.ui.notify() and workflow-logger now persist to
.gsd/notifications.jsonl instead of evaporating as transient toasts.

- notification-store: JSONL persistence with 500-entry rotation, atomic
  temp+rename rewrites, ref-counted suppress API, disk-synced counters
- notify-interceptor: WeakSet-guarded monkey-patch on ctx.ui.notify
  installed at session_start and session_switch
- notification-widget: always-on belowEditor strip showing unread count
- notification-overlay: scrollable Ctrl+Alt+N panel with severity filter
- /gsd notifications command: clear, tail, filter subcommands
- workflow-logger: warnings now also persist to notification store
- web API: GET/DELETE /api/notifications with ?countOnly support
- 16 unit tests covering store, suppress, project isolation, resync
2026-04-05 22:13:28 -05:00
Jeremy McSpadden
c9d358b8fe Merge pull request #3468 from OfficialDelta/feat/enhanced-verification
feat(gsd): add enhanced verification checks for auto-mode
2026-04-05 21:59:03 -05:00
Alan Alwakeel
7af983bda2 fix: address PR #3468 review findings
1. Post-execution retry bypass (auto-verification.ts)
   - When postExecBlockingFailure is true, skip retry and pause immediately
   - Post-exec failures are cross-task consistency issues that retrying won't fix
   - Added test in post-exec-retry-bypass.test.ts

2. File path normalization (pre-execution-checks.ts)
   - Added normalizeFilePath() to handle ./path vs path equivalence
   - Normalizes backslashes, removes duplicate slashes, strips leading ./
   - Applied to checkFilePathConsistency() and checkTaskOrdering()
   - Added tests for path normalization in pre-execution-checks.test.ts

3. Pre-exec fail-closed (auto-post-unit.ts)
   - Added try/catch around runPreExecutionChecks() inside runSafely block
   - If runPreExecutionChecks throws, set preExecPauseNeeded = true
   - Used logError from workflow-logger (not raw stderr)
   - Added test in pre-execution-fail-closed.test.ts
2026-04-05 22:44:15 -04:00
Jeremy McSpadden
7b7cad0de9 Merge pull request #3586 from jeremymcs/fix/elapsed-timer-lost-on-resume
fix(gsd): persist elapsed timer across session resume
2026-04-05 21:21:37 -05:00
github-actions[bot]
f6a1549edd release: v2.64.0 2026-04-06 02:11:42 +00:00
Jeremy
b6794956f8 test(gsd): add regression tests for autoStartTime persistence (#3585)
Source-code guards verifying autoStartTime is saved in paused-session.json,
restored on both resume paths, and falls back to Date.now() when missing.
2026-04-05 21:07:58 -05:00
Jeremy
a0a20599a0 fix(gsd): persist autoStartTime across session resume so elapsed timer survives /exit
autoStartTime was never saved to paused-session.json, so cross-session
resume always started with autoStartTime=0 and the widget showed no
elapsed timer. Now saved on pause, restored on resume with Date.now()
fallback for old files.

Also fixes widget layout: elapsed/ETA stays on the header line above
the milestone/branch info line.
2026-04-05 21:04:05 -05:00
Alan Alwakeel
9711ac3efa test(gsd): add pause wiring and integration tests for enhanced verification
- pre-execution-pause-wiring.test.ts: Tests blocking check → pause control flow
- enhanced-verification-integration.test.ts: End-to-end integration coverage

Verifies that blocking pre-execution failures trigger auto-mode pause and
that the enhanced verification pipeline integrates correctly with existing
verification infrastructure.
2026-04-05 20:25:27 -04:00