Vector retriever was disabled everywhere because it appeared to hang.
It was actually doing a first-time embedding index build for 57K files,
which takes ~60-90 min. Re-enable vector by increasing timeouts and
letting scope-aware retriever selection decide when vector is safe.
Changes:
- sift_search: retriever timeout 30s->300s, total 60s->600s
- codebase_search: total timeout 120s->600s
- warmup: retriever timeout 30s->300s, hard timeout 600s->3600s
- codebase_search now uses chooseSiftRetrievers() instead of hardcoded
bm25+phrase: repo-root -> bm25+phrase (fast), scoped subdirs -> vector
- Comments updated to reflect "slow first build" not "hang"
Tests: 178 files / 1845 tests, all pass.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Create web/middleware.ts to authenticate all API routes via bearer token
and origin checks (previously unauthenticated due to missing middleware file)
- Fix path traversal in browse-directories: replace startsWith with
realpathSync + relative + isAbsolute containment checks
- Fix XSS in session HTML export: escape raw HTML blocks via marked renderer
- Fix PTY process leak: destroy session on SSE stream cancellation
- Fix unhandled exception in terminal sessions POST: wrap getOrCreateSession
in try/catch with structured JSON error response
- Fix silent child-process failure in headless dispatch: add exit handler
to write failed claim when sf headless triage exits non-zero
- Fix TypeError on malformed claim JSON: add Array.isArray guard before
accessing claim.ids.length
All changes type-check cleanly.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- unit-runtime: fall back to STATE.md for nextActionAdvanced when DB is
unavailable (restores test compat for reconcileDurableCompleteUnitRuntime-
Records; DB path still preferred in production)
- browser-slash-command-dispatch: remove 'stop' from SF_PASSTHROUGH_COMMANDS
so /stop correctly returns { kind: 'reject' } in browser mode (was falling
through to prompt/rpc instead of builtin-reject)
- bg-events: export MAX_PENDING_ALERTS so process-manager can re-export it;
satisfies session-memory-leaks contract test
- commands-handlers: guard effectiveScope assignment — only use requestedScope
when mode=audit AND requestedScope is truthy (avoids undefined propagation)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
v1 no longer exists — the suffix is just noise. Update all import sites
and rename the test file to match.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Fix memory-embeddings-llm-gateway tests: add queryInstruction field to
expected config objects after loadGatewayConfigFromEnv was updated to
return it
- Add STYLEGUIDE.md: SF code standards adapted from ace-coder patterns
(purpose doctrine, principles, anti-patterns STY001-012, thresholds,
naming, patterns, documentation sections)
- Phase 2 /sf prefix removal: update all web components, browser dispatch,
and tests to use direct commands (/autonomous, /stop, /next, /discuss,
/init, /new-milestone) instead of /sf-prefixed forms
- workflow-actions.ts: all command strings updated
- chat-mode.tsx: SF_ACTIONS array updated
- project-welcome.tsx: primaryCommand values updated
- command-surface.tsx: fallback display updated
- remaining-command-panels.tsx: usage examples updated
- browser-slash-command-dispatch.ts: add stop/new-milestone/init to
SF_PASSTHROUGH_COMMANDS so they route correctly to the extension
- recovery-diagnostics-service.ts: suggestion commands updated
- welcome-screen.ts: hint text updated
- All affected tests updated to match new command strings
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Cherry-pick of gsd-build/gsd-2 65ca5aa2e — applies the security hardening
hunks that conflicted minimally:
- mcp-server/env-writer: validate writes against a strict allowlist
- web/api/files: enforce path containment via web/lib/secure-path
- vscode-extension: read binaryPath/autoStart only from trusted
global/default scopes (resolveTrustedSfStartupConfig), avoiding
workspace-controlled override (renamed Gsd → Sf for sf naming)
- New regression tests: mcp-client-security, vscode-startup-security,
web-files-symlink
Skipped hunks (drifted): mcp-server/server.ts, mcp-client/index.ts,
mcp-server/README.md.
Co-Authored-By: Jeremy <jeremy@fluxlabs.net>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
8 fixes from 3rd-pass scan:
1. web/components/sf/tempCodeRunnerFile.tsx: remove orphan VS Code
'Code Runner' artifact (850+ lines duplicated from shell-terminal.tsx).
Unreferenced but compiled into tsc project.
2. sf/phase-anchor.ts: writePhaseAnchor used plain writeFileSync — a crash
mid-write would corrupt the handoff checkpoint that readPhaseAnchor then
silently returns null for, losing cross-phase context. Switched to
atomicWriteSync (already used by sibling files).
3. sf/forensics.ts: same non-atomic writeFileSync on active-forensics.json
marker. Race with a concurrent reader produces an empty object and the
forensics session is lost. Switched to atomicWriteSync.
4. web/auto-dashboard-service.ts: paused-session.json existence was the
intended signal but a corrupt body silently dropped the paused flag so
the UI showed active. Now reports paused on file existence regardless
of body integrity, and warns on corruption.
5. sf/visualizer-data.ts: doctor-history.jsonl parser did .map(JSON.parse)
inside an outer catch. One corrupt line discarded 19 valid entries.
Per-line try/catch preserves the valid rows.
6. sf/files.ts: three parseInt calls without radix (step, total_steps,
totalSteps) — also missing || 0 fallback for NaN.
7. cli.ts: parseInt(process.versions.node) without radix. Split on '.' and
use radix 10 explicitly.
8. sf/slice-parallel-orchestrator.ts: silent 'catch {}' around spawn()
masked worker-spawn failures as 'no workers available'. Matches sibling
parallel-orchestrator.ts pattern — now logs via logWarning.
Skipped from the scan (need a real lock mechanism, not safe as a one-line
fix):
- sf/auto-dispatch.ts:164 (UAT counter race)
- sf/captures.ts:107 (CAPTURES.md append race)
Deferred (low-value):
- preferences-models.ts, key-manager.ts, auto-timers.ts silent catches
- dead variable in visualizer-data.ts
- google-gemini-cli.ts maxTokens clamp interaction
tsc --noEmit green at root.
Updates workflow tool names, documentation references, and internal naming
conventions across MCP server, CLI, tests, and web components to complete
the singularity-forge rebrand from gsd to sf.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Updates channel prefixes, log messages, comments, and configuration values
across daemon, mcp-server, and related packages to complete the rebrand from
gsd to sf-run naming.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Accept deletion of gsd-phase-state.ts (renamed to forge-phase-state.ts earlier)
- Accept deletion of create-gsd-extension/ (renamed to create-forge-extension/ earlier)
- These renames were part of the rebrand and are preserved in commit history
Stabilize git state after restoration operations.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The Next.js auth middleware (proxy.ts) was never wired in — it exported
`proxy` from a file named proxy.ts, but Next.js requires a `middleware`
export from middleware.ts. The middleware-manifest.json was empty,
leaving all 42 API routes accessible without authentication.
Fixes:
- Rename web/proxy.ts → web/middleware.ts, export `middleware` not `proxy`
- Add defense-in-depth auth-guard to /api/shutdown and /api/update routes
- Remove shell: true from update-service spawn (command injection surface)
- Update contract tests to verify middleware file name and export
Closes#4014
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Stream tool results in real-time during Claude Code SDK sessions
instead of deferring until session end. Tool calls (read, bash, write,
etc.) now show their output as they complete, not collapsed as "..."
- Stop suppressing toolcall_start/delta/end events from stream adapter
so the TUI can render tool call progress during streaming
- On SDK turn boundary (user message with tool results), push synthetic
toolcall_end events with externalResult attached for immediate rendering
- Chat controller checks for externalResult on toolcall_end message
updates and calls updateResult on pending ToolExecutionComponents
- Fix case-sensitive tool name matching (Read vs read, Bash vs bash)
in TUI ToolExecutionComponent rendering
- Auto-discover and pass GSD_WORKFLOW_EXECUTORS_MODULE and
GSD_WORKFLOW_WRITE_GATE_MODULE env vars in MCP server launch config
- Add /gsd mcp init command and auto-bootstrap .mcp.json for Claude
Code provider during auto-start
- Add tool_execution_update event type for web UI streaming updates
- Add setStderrLoggingEnabled toggle for workflow logger
Fixes identified by comprehensive state machine validation:
- M12: reopen-task/slice now deletes SUMMARY.md from disk, preventing
the DB-filesystem reconciler from auto-correcting tasks back to
"complete" — reopen was previously a no-op when artifacts existed
- H4: add 30s hard timeout to unitPromise via Promise.race — prevents
permanent hang if supervision fails to resolve agent_end
- H5: add handleReopenMilestone — milestone completion was irrevocable
- H6: pass ID as title when auto-creating phantom parent entities
- H7: guard loadRegistry() against missing/corrupt registry.json
- M4: report_blocker replay now sets blocker_discovered flag via
new setTaskBlockerDiscovered() DB function
- M5: insertVerificationEvidence uses INSERT OR IGNORE with unique
index on (task_id, slice_id, milestone_id, command, verdict)
- M11: complete-slice rollback preserves original status instead of
hardcoding "pending"
- M14: deriveWorkflowAction shows contextual labels for blocked,
paused, validating-milestone, completing-milestone, needs-discussion,
and replanning-slice phases instead of generic "Continue"
Includes 86 regression tests (49 unit + 37 integration) validating
every phase transition, completion guard, and edge case.
Closes#3161
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
Two root causes destroyed terminal state during normal navigation:
1. The pagehide handler fired a shutdown beacon unconditionally, but on
mobile/Safari tab switches pagehide fires with event.persisted=true
(bfcache entry). This killed the server and all PTY sessions when the
user merely switched browser tabs. Fix: check event.persisted and skip
the beacon when the page is being cached, not unloaded.
2. ShellTerminal used project-agnostic session IDs ("default"), so
switching projects and switching back either collided with the old
session or spawned a new one, losing terminal state. Fix: scope session
IDs by project path (e.g. "default:/path/to/project") so the server's
getOrCreateSession returns the existing live PTY on reconnect.
Closes#2701
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Closes#2711
Two changes fix the tab-reset-to-dashboard bug:
1. Remove the forced `gsd:navigate-view` dispatch to "dashboard" in
ProjectsPanel.handleSelectProject — this was unconditionally resetting
the view on every project switch.
2. Add a useEffect in WorkspaceChrome that resets `viewRestored` when
`projectPath` changes, so the per-project sessionStorage view restore
fires for the newly-selected project.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Three root causes addressed:
1. PtyChatParser: user input echoed after a bare prompt line (e.g. "❯ \n"
followed by "hello\n") was misclassified as assistant content. Added
_awaitingInput flag that flips true on prompt boundary and classifies the
next content line as role=user.
2. Chat mode "looks stuck": when the session is idle (connected, not
streaming, has timeline content), no visual cue indicated GSD was waiting
for input. Added a "Ready for your input" indicator with a pulsing dot.
3. Transcript overflow misalignment: chatUserMessages was not trimmed when
liveTranscript/completedTurnSegments overflowed MAX_TRANSCRIPT_BLOCKS,
causing index-based interleaving to pair user messages with wrong
assistant responses.
Also exposed isAwaitingInput() on PtyChatParser so chat UIs can query
whether the session is waiting for user input, and widened the > and $
prompt marker regexes to match bare prompts after trimEnd strips trailing
whitespace.
Closes#2707
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>