Commit graph

1503 commits

Author SHA1 Message Date
TÂCHES
bdeec039c0 fix: validate CWD instead of project root when running from a GSD worktree (#1317) (#1504)
When the user's home directory is a git repo, resolveProjectRoot() correctly
returns $HOME as the main tree root. assertSafeDirectory() then hard-blocks it
with the home-directory guard added in #1053, even though the session is running
from a valid GSD worktree (e.g. ~/.gsd/worktrees/M001) — not from $HOME itself.

Fix: in projectRoot(), detect when CWD diverges from the resolved root (i.e. we
are inside a git worktree) and validate the CWD instead. The worktree path is
never $HOME, so the guard no longer fires. When not in a worktree cwd === root,
preserving the existing behaviour unchanged.

Adds a regression test: validateDirectory() on a ~/.gsd/worktrees/M001 path
must return { safe: true, severity: "ok" }.

Co-authored-by: Jeremy McSpadden <jeremy@fluxlabs.net>
2026-03-19 16:53:34 -06:00
Derek Pearson
5eed57f876 fix(gsd): detect initialized health widget projects (#1432)
* fix(gsd extension): detect initialized projects in health widget

Use .gsd presence plus project-state detection for the health widget so bootstrapped projects no longer appear as unloaded before metrics exist.

* fix(gsd extension): make health widget execution-aware

Lead the health widget with current GSD execution state so it explains what the project is doing before surfacing provider and environment diagnostics. Keep issue, budget, and progress details as secondary context and cover the new output with focused widget tests.

* fix(gsd extension): address review feedback on health widget PR

- Replace em dash with ASCII hyphen in headline for terminal safety
- Reformat catch/finally to standard single-line style
- Replace computeProgressScore() status with direct phase labels so
  the status reflects the actual execution phase, not a global health
  aggregate
- Use lightweight milestone-dir scan instead of full detectProjectState()
  to avoid unnecessary filesystem work on the 60s refresh
- Add cache warm-up comment on updateSliceProgressCache call
- Add safety comment on early void refresh() call
- Update test assertions for new phase labels and ASCII separator
2026-03-19 16:50:13 -06:00
Jeremy McSpadden
96b94065ff fix: smarter .gsd root discovery — git-root anchor + walk-up replaces symlink hack (#1386)
* fix: replace symlink-follow in gsdRoot() with git-root-anchored walk-up discovery

The old implementation blindly assumed .gsd lived at basePath and only
followed symlinks as a migration escape hatch. This caused the health
widget to show "No project loaded" when:
- .gsd was moved to a non-default location
- cwd was a subdirectory of the project root
- the session started inside a worktree path

New probe chain in gsdRoot():
  1. basePath/.gsd         — fast path (common case, zero overhead)
  2. git rev-parse root    — anchors to the repo root regardless of cwd
  3. Walk up from basePath — finds .gsd in an ancestor (bounded by git root)
  4. basePath/.gsd         — creation fallback for init/new projects

Key correctness detail: basePath is normalized via realpathSync before
any comparisons, ensuring the git-root boundary check works on macOS
where /var is a symlink to /private/var. Walk-up only runs when inside
a git repo and only when basePath != gitRoot — preventing escape into
unrelated filesystem directories.

Result is cached per-basePath for the process lifetime. All 52 callers
of gsdRoot() benefit with no call-site changes.

Adds tests/paths.test.ts covering all 6 probe cases.

* fix: correct report() call signature in paths.test.ts — takes no arguments

* fix: normalize git output paths and use realpathSync.native for Windows compatibility

- Use path.normalize() on git rev-parse output to convert forward slashes
  to backslashes on Windows, so the git-root boundary check fires correctly
- Use realpathSync.native() instead of realpathSync() to resolve both
  symlinks (macOS /var→/private/var) and 8.3 short names (Windows RUNNER~1)
- Update test tmp() helper to use realpathSync.native so expected paths
  match the resolved paths returned by probeGsdRoot
2026-03-19 16:50:10 -06:00
HyperDev1
fecf32dc1e fix: correct GSD-WORKFLOW.md fallback path and sync to agentDir (#1375)
The fallback path for GSD-WORKFLOW.md still referenced the legacy .pi
directory (~/.pi/GSD-WORKFLOW.md) instead of the correct .gsd/agent
location. This broke workflow dispatch when GSD_WORKFLOW_PATH env var
was not set.

- Update fallback path from ~/.pi/ to ~/.gsd/agent/ in three call sites
  (dispatchWorkflow, dispatchDoctorHeal, handleTriage)
- Sync GSD-WORKFLOW.md to agentDir during initResources() as a fallback
  for alternative entry points that may not set the env var

Co-authored-by: Berat Can <berat@hyperlab.games>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 16:50:08 -06:00
TÂCHES
ad01d0ada4 Merge pull request #1365 from jbrahy/fix/openai-reasoning-encrypted-content-always-include
fix: always include reasoning.encrypted_content for OpenAI reasoning models
2026-03-19 16:38:24 -06:00
TÂCHES
d3d682cf00 Merge pull request #1359 from jbrahy/fix/loadfile-eisdir-guard
fix: avoid EISDIR crash in GSD file loader
2026-03-19 16:38:11 -06:00
TÂCHES
0028ceef26 Merge pull request #1357 from jbrahy/fix/inspect-open-existing-db
fix: open existing GSD database on /gsd inspect
2026-03-19 16:30:56 -06:00
github-actions[bot]
290b2b2a25 release: v2.35.0 2026-03-19 22:05:29 +00:00
TÂCHES
efc23a2342 Merge pull request #1498 from gsd-build/fix/lsp-get-server-for-file
fix: restore LSP single-server selector export
2026-03-19 15:53:26 -06:00
TÂCHES
cc17d20820 Merge pull request #1457 from frizynn/refactor/agent-session-model-switching
refactor: consolidate model switching logic in agent-session
2026-03-19 15:52:12 -06:00
TÂCHES
45193d5499 Merge pull request #1458 from frizynn/refactor/resource-loader-generics
refactor: consolidate resource-loader duplicate methods into generics
2026-03-19 15:52:01 -06:00
TÂCHES
b5563e18c6 Merge pull request #1459 from frizynn/refactor/shared-lock-utils
refactor: extract shared file lock utilities
2026-03-19 15:51:47 -06:00
TÂCHES
a23c69aaae Merge pull request #1468 from frizynn/refactor/oauth-utils-consolidation
refactor: consolidate Google OAuth callback server and helper utilities
2026-03-19 15:50:59 -06:00
TÂCHES
0259f0f2e3 Merge pull request #1479 from frizynn/refactor/rpc-mode-dedup
refactor: deduplicate RPC mode shared patterns
2026-03-19 15:50:03 -06:00
TÂCHES
00b18460e9 Merge pull request #1481 from frizynn/refactor/tui-rendering-dedup
refactor: deduplicate rendering patterns in markdown and keys
2026-03-19 15:49:29 -06:00
TÂCHES
0c2105d71d Merge pull request #1484 from frizynn/refactor/agent-session-decomposition
refactor: extract retry handler and compaction orchestrator from agent-session
2026-03-19 15:48:59 -06:00
TÂCHES
86ada3a345 Merge pull request #1480 from frizynn/refactor/openai-providers-shared-base
refactor: consolidate shared code between OpenAI providers
2026-03-19 15:48:17 -06:00
Lex Christopherson
5e501d59a0 fix: restore lsp single-server selector export 2026-03-19 15:46:20 -06:00
TÂCHES
5ab6fa2853 Merge pull request #1448 from frizynn/refactor/deduplicate-small-utilities
refactor: deduplicate toPosixPath, ZERO_USAGE, and shortenPath utilities
2026-03-19 15:46:13 -06:00
TÂCHES
dea2f1a426 Merge pull request #1449 from frizynn/refactor/compaction-helpers-extraction
refactor: extract shared helpers in compaction module
2026-03-19 15:45:21 -06:00
TÂCHES
cb9bd2bc99 Merge pull request #1447 from frizynn/refactor/extension-runner-emit-consolidation
refactor: consolidate extension runner emit methods into shared invokeHandlers
2026-03-19 15:44:37 -06:00
TÂCHES
671b72b684 Merge pull request #1446 from frizynn/refactor/extension-type-guards-consolidation
refactor: consolidate extension type guards and inline handler aliases
2026-03-19 15:44:17 -06:00
TÂCHES
66bca9c8a2 Merge pull request #1477 from frizynn/refactor/tree-render-shared-utils
refactor: extract shared tree rendering utilities
2026-03-19 15:40:26 -06:00
TÂCHES
e01536c8a3 Merge pull request #1445 from frizynn/refactor/lsp-deduplication
refactor: consolidate duplicate patterns in LSP module
2026-03-19 15:40:07 -06:00
TÂCHES
d0dc31220b Merge pull request #1360 from jbrahy/docs/issue-templates
docs: add structured issue templates
2026-03-19 15:40:00 -06:00
TÂCHES
add2cfaed8 Merge pull request #1355 from jbrahy/docs/local-mcp-setup
docs: add first-class guidance for local custom MCP setup
2026-03-19 15:39:56 -06:00
TÂCHES
aa6f41c256 Merge pull request #1424 from jeremymcs/fix/doctor-gap-coverage
fix: close 5 doctor coverage gaps — providers, lock dir, integration branch, orphaned worktrees
2026-03-19 15:39:52 -06:00
TÂCHES
9ac9cb06e2 Merge pull request #1390 from jeremymcs/fix/prefs-gaps
fix(prefs): close merge, validation, serialization, and docs gaps
2026-03-19 15:39:48 -06:00
TÂCHES
f029ae6f64 Merge pull request #1409 from trek-e/fix/1398-crash-lock-pid-check
fix: add PID self-check to guided-flow crash lock detection (#1398)
2026-03-19 15:39:23 -06:00
TÂCHES
364bd5b65b Merge pull request #1430 from trek-e/fix/1423-session-cost-compaction
fix: accumulate session cost independently of message array (#1423)
2026-03-19 15:39:19 -06:00
Juan Francisco Lebrero
da2af65971 refactor: deduplicate error emission and message patterns in agent-core (#1444)
- Extract emitMessagePair() to consolidate 6 message_start/message_end push pairs in agent-loop.ts
- Extract emitErrorSequence() to deduplicate identical catch blocks in agentLoop and agentLoopContinue
- Export ZERO_USAGE constant and reuse it in agent.ts instead of inline object literals
- Merge identical message_start/message_update switch cases in Agent._runLoop
- Extract Agent._updatePendingToolCalls() to consolidate tool_execution_start/end Set mutation
2026-03-19 15:39:12 -06:00
Juan Francisco Lebrero
54b1446fb2 refactor: simplify settings manager with generic setter helpers (#1461)
Replace 30+ repetitive setter method bodies with four generic private
helpers: setGlobalSetting, setScopedSetting, setNestedGlobalSetting,
and setProjectSetting. Each setter method retains its original public
signature and behavior — only the internal implementation is consolidated.

Methods with custom logic (setEditorPaddingX, setAutocompleteMaxVisible,
setSearchExcludeDirs, setFallbackChain, removeFallbackChain,
setDefaultModelAndProvider) are left unchanged or minimally adapted.

Net reduction: 79 lines (164 deleted, 85 added).
2026-03-19 15:37:24 -06:00
Jean-Dominique Stepek
29a1882c04 feat(gsd): add /gsd changelog command with LLM-summarized release notes (#1465)
Add a new /gsd changelog command that fetches releases from the GitHub API,
filters by version, and sends the raw changelog into the conversation for the
LLM to summarize the most important changes.

- New changelog.ts module: GitHub API fetch, semver filtering, body parsing
- Routing block in commands.ts with lazy import (same pattern as forensics)
- Tab completion in commands-bootstrap.ts TOP_LEVEL_SUBCOMMANDS
- Help text under VISIBILITY section in showHelp()
- No new npm dependencies — uses built-in fetch()
2026-03-19 15:36:43 -06:00
Juan Francisco Lebrero
988ef61488 refactor: consolidate theme files and remove manual schema (#1478)
- Delete theme-schema.json (335 lines): redundant with the TypeBox
  schema already defined in theme.ts, only referenced via $schema URLs
  in the JSON files for editor autocomplete.
- Delete dark.json (85 lines) and light.json (84 lines): move built-in
  theme definitions into themes.ts as TypeScript objects, eliminating
  runtime filesystem reads and the getThemesDir() dependency.
- Export ThemeJson type from theme.ts so themes.ts can reference it.
- Net reduction: ~319 lines removed.
2026-03-19 15:35:56 -06:00
Juan Francisco Lebrero
aa85e99dc0 refactor: extract overlay layout and compositing from TUI into separate module (#1482)
Move overlay positioning (resolveOverlayLayout, resolveAnchorRow/Col),
line compositing (compositeLineAt, compositeOverlays, applyLineResets),
cursor extraction, and size parsing into overlay-layout.ts. These are
pure functions with no TUI state dependencies, reducing tui.ts from
1,200 to 899 lines.
2026-03-19 15:35:00 -06:00
Juan Francisco Lebrero
334a7cf076 refactor: extract slash command handlers from interactive-mode (#1485)
Move slash command dispatch logic and 12 individual command handlers
(/export, /share, /copy, /name, /session, /changelog, /hotkeys,
/compact, /thinking, /edit-mode, /arminsayshi, plus showThinkingSelector)
into a new slash-command-handlers.ts module.

InteractiveMode now delegates to dispatchSlashCommand() via a
SlashCommandContext interface, keeping the integration surface minimal.
Handlers that are also invoked from keybindings/events remain on
InteractiveMode and are accessed through the context.

Reduces interactive-mode.ts from 4,783 to 4,272 lines (-511).
2026-03-19 15:34:14 -06:00
Juan Francisco Lebrero
4e29ca4544 refactor: remove dead code (unused exports) (#1486)
Remove exported functions/constants/classes that are never imported
anywhere else in the codebase:

Fully removed (not used anywhere):
- nativeAvailable (native)
- getApiProviders, unregisterApiProviders (pi-ai/api-registry)
- createAssistantMessageEventStream (pi-ai/event-stream)
- getOverflowPatterns (pi-ai/overflow)
- validateToolCall (pi-ai/validation)
- getToolsDir (pi-coding-agent/config)
- emitSessionShutdownEvent (extensions/runner)
- syncContent, notifySaved (lsp/client)
- getServerForFile, hasCapability (lsp/config)
- severityToIcon, formatPosition, formatTextEdit, symbolKindToName (lsp/utils)
- clearApiKeyCache (model-registry)
- restoreModelFromSession (model-resolver)
- isLightTheme (theme)
- loadPhoton + all internal helpers (photon)
- extractAnsiCode (pi-tui/utils)

De-exported (used locally, not externally):
- extractRetryAfterMs, inferCopilotInitiator, extractRetryDelay,
  buildRequest, requiresToolCallId, registerBuiltInApiProviders,
  streamProxy, isBunRuntime, detectInstallMethod, getPackageDir,
  getPackageJsonPath, ansiToHtml, DEFAULT_APP_KEYBINDINGS,
  DEFAULT_KEYBINDINGS, shutdownClient, sendNotification, shutdownAll,
  applyTextEditsToString, wrapWithLspmux, severityToString,
  COMPACTION_SUMMARY_PREFIX/SUFFIX, BRANCH_SUMMARY_PREFIX/SUFFIX,
  bashExecutionToText, defaultModelPerProvider, parseModelPattern,
  parseCommandArgs, substituteArgs, loadEntriesFromFile,
  findMostRecentSession, FileSettingsStorage, InMemorySettingsStorage,
  migrateAuthToAuthJson, migrateSessionsFromAgentRoot,
  parseSearchQuery, matchSession, compareVersions, isWaylandSession,
  getToolPath, wordWrapLine
2026-03-19 15:33:32 -06:00
John Brahy
c10e42b392 fix(mcp): preserve args for mcp_call tool invocations (#1354) 2026-03-19 15:29:19 -06:00
Alan Alwakeel
3764cc615a Respect CARGO_TARGET_DIR in native build script (#1441) 2026-03-19 15:28:44 -06:00
github-actions[bot]
f196309295 release: v2.34.0 2026-03-19 21:08:44 +00:00
TÂCHES
d761e45a41 M001: The Minimal Machine — linear auto-loop, sole-authority state, sidecar queue, WorktreeResolver (#1419)
* refactor: replace recursive auto-dispatch with linear autoLoop, delete ~3k lines of dead code

Replace the complex recursive dispatch system (dispatchNextUnit, reentrancy
guards, stall detection, idempotency tracking, skip-depth machinery) with a
simple linear while(s.active) loop in auto-loop.ts.

Key changes:
- New auto-loop.ts with autoLoop(), runUnit(), resolveAgentEnd()
- Deleted auto-idempotency.ts, auto-stuck-detection.ts, session-lock.ts,
  mechanical-completion.ts, progress-score.ts, auto-constants.ts, unit-id.ts
- Extracted WorktreeResolver class for worktree path resolution
- Added auto-worktree-sync.ts for worktree synchronization
- Simplified auto.ts from ~1400 lines to ~400 lines
- Fixed 9 TypeScript errors (NotifyCtx type widening, capture typing)
- Comprehensive test coverage: 32 auto-loop tests + worktree resolver/DB tests

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: address 6 audit findings in auto-loop refactor

1. CRITICAL: Move pendingResolve to AutoSession + queue orphaned agent_end
   events instead of silently dropping them. Prevents permanent stalls when
   error-recovery sendMessage retries fire between loop iterations.

2. HIGH: Scope pendingResolve per-session via _activeSession ref, preventing
   concurrent /gsd auto sessions from corrupting each other's promises.

3. HIGH: Replace console.log in dispatchHookUnit with debugLog to prevent
   hook prompt content (potentially containing secrets) from leaking to stdout.

4. HIGH: Restore parked milestone handling in state.ts — Phase 1 skips
   parked milestones so they don't satisfy depends_on, Phase 2 registers
   them as 'parked' status. Add 'parked' to MilestoneRegistryEntry type.

5. MEDIUM: Restore queuePhaseActive parameter in shouldBlockContextWrite
   and re-export setQueuePhaseActive for guided-flow-queue.ts consumers.

6. MEDIUM: Add MAX_LOOP_ITERATIONS (500) lifetime cap to autoLoop to prevent
   runaway loops when units alternate between IDs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: resolve build breakers, add correctness fixes, and graduated recovery

Build breakers (CRITICAL):
- Restore unit-id.ts (deleted but still imported by complexity-classifier.ts, metrics.ts)
- Restore progress-score.ts (deleted but still imported by commands.ts, dashboard-overlay.ts, doctor.ts)
- Rewrite worktree-sync-milestones.test.ts to use new syncProjectRootToWorktree API

Correctness fixes (MEDIUM):
- Cap pendingAgentEndQueue to 3 entries to prevent unbounded growth from stale events
- Add milestoneId path traversal validation in WorktreeResolver
- Clear depthVerificationDone on session_start to prevent cross-session leaks in RPC mode
- Add verification gate for non-hook sidecar units (triage, quick-tasks)
- Remove dead handleAgentEnd import from index.ts

Graduated recovery (Jeremy's feedback):
- Blanket try/catch around loop body — one bad iteration no longer kills the session
- Graduated stuck recovery: at count 3 try artifact verification + cache invalidation,
  at count 5 hard stop (was: binary stop at 5 with no recovery attempt)
- Graduated error recovery: 1st error retries, 2nd invalidates caches, 3rd stops

Test results: 32/32 auto-loop, 28/28 worktree-resolver, 11/11 sidecar-queue, tsc clean.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: restore copyWorktreeDb/reconcileWorktreeDb exports and fix loadToolApiKeys import

Two missing exports caused ~90% of the 120 pre-existing test failures:

1. copyWorktreeDb + reconcileWorktreeDb — imported by auto-worktree.ts but
   never added to gsd-db.ts. Restored with the original implementations.
2. loadToolApiKeys — moved to commands-config.ts but index.ts still imported
   from commands.ts. Fixed the import path.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: move loadToolApiKeys import to commands-config.js

loadToolApiKeys was moved to commands-config.ts but index.ts still
imported it from commands.ts, causing runtime failures in all tests
that transitively load the extension entry point.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: fix provider error assertion on windows

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 14:56:00 -06:00
frizynn
3090f968f4 refactor: extract retry handler and compaction orchestrator from agent-session
Extract two self-contained subsystems from agent-session.ts (3,367 -> 2,737 lines):

- RetryHandler: auto-retry with exponential backoff, credential rotation,
  and cross-provider fallback logic
- CompactionOrchestrator: manual/auto compaction, overflow recovery, and
  extension integration for custom compaction providers

Also add shared getErrorMessage() utility to replace repeated
`err instanceof Error ? err.message : String(err)` patterns.

The extracted modules receive AgentSession state via dependency injection
interfaces, avoiding state duplication. AgentSession remains the coordinator
that delegates to these modules.
2026-03-19 16:46:14 -03:00
frizynn
9938fb3730 refactor: deduplicate rendering patterns in markdown and keys
markdown.ts: Extract renderCodeBlock() helper to eliminate duplicated
code block rendering between renderToken and renderListItem.

keys.ts: Consolidate LEGACY_KEY_SEQUENCES, LEGACY_SHIFT_SEQUENCES, and
LEGACY_CTRL_SEQUENCES into a single LEGACY_SEQUENCES structure with
plain/shift/ctrl variants per key. Auto-generate LEGACY_SEQUENCE_KEY_IDS
from this structure instead of hand-maintaining a 50+ entry reverse
lookup. Extract hasKittyEventType() to deduplicate isKeyRelease and
isKeyRepeat. Net reduction of ~80 lines.
2026-03-19 16:39:18 -03:00
frizynn
1c5fdc9144 refactor: consolidate shared code between OpenAI providers
Extract duplicated patterns from openai-completions.ts,
openai-responses.ts, and azure-openai-responses.ts into a new
openai-shared.ts module:

- getOpenAIClass: unified lazy SDK loading (was duplicated in both)
- createOpenAIClient: shared client creation with Copilot headers,
  options header merging, and lazy loading (was ~30 lines each)
- buildInitialOutput: AssistantMessage initialization (was ~15 lines x3)
- assertStreamSuccess / finalizeStream / handleStreamError: stream
  lifecycle helpers (was ~10 lines each x3)
- clampReasoningForModel: reasoning effort clamping for gpt-5.x models
  (was duplicated in openai-responses.ts and azure-openai-responses.ts)

Net reduction: ~185 lines removed across the three provider files.
2026-03-19 16:39:12 -03:00
frizynn
502067c213 refactor: deduplicate RPC mode shared patterns
Extract the duplicated commandContextActions implementations from
rpc-mode.ts and print-mode.ts into a shared
createDefaultCommandContextActions() factory in
modes/shared/command-context-actions.ts.

Both headless modes (RPC and print) had identical implementations of
waitForIdle, newSession, fork, navigateTree, switchSession, and reload
that simply delegate to AgentSession. The shared factory provides these
defaults; interactive mode continues to layer TUI-specific behavior on
top via its own overrides.

Also fixes a subtle redundancy in print mode where newSession manually
called options.setup after session.newSession(), even though
session.newSession() already handles the setup callback internally.
2026-03-19 16:38:51 -03:00
frizynn
6cb8e3c524 refactor: extract shared tree rendering utilities
Extract duplicated tree rendering logic from tree-selector.ts and
session-selector.ts into tree-render-utils.ts:

- computeScrollWindow: centered scroll window calculation
- renderCursor: accent-colored selection cursor indicator
- applyRowHighlight: selected-row background + truncation
- renderScrollPosition: muted (current/total) position indicator
- buildTreePrefix: tree connector prefix from ancestor-continuation flags
- TREE_BRANCH/TREE_LAST/TREE_PIPE/TREE_SPACE connector character constants
2026-03-19 16:37:40 -03:00
frizynn
d0cd3451fd refactor: consolidate OAuth callback server and helper utilities
Extract duplicated implementations of startCallbackServer, parseRedirectUrl,
getUserEmail, and token refresh logic from google-antigravity.ts and
google-gemini-cli.ts into a shared google-oauth-utils.ts module.
2026-03-19 15:55:10 -03:00
frizynn
23d0ea656d refactor: extract shared file lock utilities
Extract the duplicated file lock mechanism from auth-storage.ts and
session-manager.ts into a shared lock-utils.ts module.

- acquireLockSyncWithRetry(): throwing variant (used by auth-storage)
- tryAcquireLockSync(): non-throwing variant (used by session-manager)
- acquireLockAsync(): async lock with retries and staleness detection

Removes ~55 lines of duplicated retry-loop logic. The shared module
also provides a foundation for deduplicating identical patterns in
settings-manager.ts and models-json-writer.ts.
2026-03-19 15:16:56 -03:00
frizynn
a78121b35c refactor: consolidate resource loader with generic update/dedupe methods
- Replace dedupePrompts() and dedupeThemes() with generic dedupeResources<T>()
  that accepts getName/getPath/resourceType callbacks
- Replace discoverSystemPromptFile() and discoverAppendSystemPromptFile() with
  generic discoverFileInSearchPaths(filename)
- Import ResourceCollision type for use in dedupeResources signature
- Net reduction of 24 lines (868 → 844) with elimination of duplicated logic
2026-03-19 15:16:21 -03:00
frizynn
c6c45cb1c0 refactor: consolidate model switching logic in agent-session
Extract the duplicated model-switching sequence (set model, append
session change, persist settings, re-clamp thinking level, emit event)
from setModel(), _cycleScopedModel(), and _cycleAvailableModel() into a
shared _applyModelChange() helper. Removes ~30 lines of repeated code.
2026-03-19 15:16:18 -03:00