Commit graph

4537 commits

Author SHA1 Message Date
TÂCHES
41418194e9 fix: untrack runtime files from slice branch before squash-merge (#218) (#220)
Squash-merges fail with conflicts in .gsd/metrics.json and
.gsd/completed-units.json because these runtime files get tracked on the
slice branch. The existing pre-merge untrack only runs on main, so the
squash-merge sees modify/delete conflicts.

Untrack runtime files from the slice branch before merging, matching the
existing main-branch untrack. Also switch runtime conflict auto-resolution
from --ours to --theirs as a more correct fallback.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 12:22:47 -06:00
TÂCHES
840a6918b9 Merge pull request #215 from gsd-build/feat/hashline-edits
feat: add hashline edits — line-hash-anchored file editing
2026-03-13 12:21:16 -06:00
TÂCHES
c669c6183a feat: Rust native engine scaffold with grep module
* feat: scaffold Rust native engine with grep module (napi-rs)

Adds a Rust N-API addon architecture inspired by Oh My Pi's pi-natives.
The grep module wraps ripgrep's core crates (grep-regex, grep-searcher,
grep-matcher) and exposes `search()` and `grep()` to Node.js via napi-rs.

Includes:
- Cargo workspace at native/ with engine (cdylib) and grep (lib) crates
- Build script (native/scripts/build.js) producing platform-tagged .node files
- TypeScript wrapper package (@gsd/native) with types and loader
- 6 Rust unit tests + 9 Node.js integration tests (all passing)

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

* fix: audit fixes for rust native engine PR

- Fix repository URL to gsd-build/gsd-2
- Remove dead add_custom_ignore_filename("") call
- Unify error model: search() now returns Result<> (throws) matching grep()
- Remove error field from NapiSearchResult and SearchResult types
- Use t.after() in integration tests for reliable temp dir cleanup

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

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 12:21:09 -06:00
TÂCHES
05868558e7 Merge pull request #217 from gsd-build/feat/universal-config-discovery-v2
feat: universal config discovery from 8 AI coding tools
2026-03-13 12:08:28 -06:00
Lex Christopherson
a0152d3709 v2.9.0 2026-03-13 12:06:19 -06:00
Lex Christopherson
5dc801c4d3 docs: update changelog for v2.9.0 2026-03-13 12:05:47 -06:00
Lex Christopherson
547610f016 feat: add universal config discovery extension
Auto-detects and normalizes configuration from 8 AI coding tools:
Claude Code, Cursor, Windsurf, Gemini CLI, Codex, Cline, GitHub
Copilot, and VS Code. Discovers MCP servers, rules/instructions,
context files, and settings from both user-level (~/) and project-level
(./) config directories.

Read-only — never modifies other tools' config files.

Provides:
- discover_configs tool (LLM-callable) with optional tool filter and
  session-scoped caching
- /configs slash command for quick overview
- 31 tests covering all 8 tool scanners, the discovery orchestrator,
  and output formatting

Config paths verified against Oh My Pi's discovery module
(can1357/oh-my-pi packages/coding-agent/src/discovery/).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 11:55:50 -06:00
Lex Christopherson
83445f4449 feat: add hashline edits — line-hash-anchored file editing
Implement hashline edit mode inspired by Oh My Pi's approach. Each line
in a file is identified by a content hash (xxHash32, 2-char nibble
alphabet), enabling the model to reference lines by stable LINE#ID tags
instead of reproducing full line text. This eliminates the most common
edit failure mode (slightly misquoted original text) and reduces output
tokens.

New files:
- hashline.ts: core hash computation, formatting, parsing, validation,
  and edit application engine (pure JS xxHash32, no native deps)
- hashline-edit.ts: AgentTool wrapper for hash-anchored file edits
- hashline-read.ts: read tool variant that outputs LINE#ID:CONTENT format
- hashline.test.ts: 54 tests covering all core operations

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 11:52:24 -06:00
Lex Christopherson
c9135da035 docs: add LSP extension to README bundled tools table 2026-03-13 11:47:02 -06:00
TÂCHES
9d8eca488d Merge pull request #214 from gsd-build/feat/lsp-tool
feat: port LSP tool from Oh My Pi
2026-03-13 11:46:16 -06:00
Lex Christopherson
2c4f5de321 fix: eliminate command injection and unhandled JSON.parse in LSP tool
- config.ts: Replace execSync(`which ${command}`) with spawnSync("which", [command])
  to prevent shell injection from malicious lsp.json config files
- client.ts: Wrap JSON.parse in parseMessage with try/catch and handle null messages
  in the stream reader to prevent process crashes from malformed LSP output

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 11:45:04 -06:00
Lex Christopherson
120ae367ad test: add LSP integration test against typescript-language-server
Tests initialize, hover, go-to-definition, references, document symbols,
diagnostics (type error detection), and clean shutdown against a real
typescript-language-server instance with a temp TypeScript project.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 11:37:49 -06:00
TÂCHES
61b7e62f39 fix: resolve TypeScript type errors in misc extension files (#204) (#213)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 11:36:17 -06:00
TÂCHES
a5eebd8d98 fix: resolve TypeScript type errors in browser-tools extension (#204) (#212)
- Create core.d.ts with type declarations for the untyped core.js module
- Create tsconfig.extensions.json for type-checking browser-tools in isolation
- Fix collectAssertionState adapter to match ToolDeps signature by wrapping with captureCompactPageState binding
- Fix captureAccessibilityMarkdown adapter to match ToolDeps signature by binding getActiveTarget()
- Add explicit Element | null type annotation to refs.ts parent variable (TS7022 circular inference)
- Fix session.ts timeline.count to timeline.retained (nonexistent property on formatTimelineEntries result)

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 11:35:47 -06:00
TÂCHES
940b6a38dc fix: resolve TypeScript type errors in gsd extension files (#204) (#211)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 11:34:34 -06:00
TÂCHES
5896cd2e2a fix: resolve TypeScript type errors in search-the-web extension (#204) (#210)
- Add .js extensions to all relative imports for NodeNext module resolution
- Cast pi.writeTempFile to (pi as any) since it exists at runtime but not on ExtensionAPI type
- Add details: undefined as unknown to return objects missing the required details field
- Fix onUpdate calls to include details field required by AgentToolResult

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 11:34:07 -06:00
Lex Christopherson
eb288233bc fix: convert LSP tool from Bun APIs to Node APIs
All Bun-specific APIs replaced with Node equivalents:
- Bun.spawn → child_process.spawn
- Bun.file/Bun.write → fs/promises readFile/writeFile
- Bun.Glob → glob package
- Bun.sleep → setTimeout promise
- Bun.which → execSync("which")
- Bun.env → process.env
- Bun.FileSink → Writable stream
- YAML/TOML from bun → yaml package (TOML stripped)
- import with { type: "json" } → createRequire
- Added .js extensions to all relative imports
- Fixed Timer type → ReturnType<typeof setInterval>
- Added explicit types to all implicit any params

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 11:33:57 -06:00
TÂCHES
8ecd8f6360 Merge pull request #209 from FacuVCanale/feat/auto-update-check
feat: add startup update check with 24h cache
2026-03-13 11:32:42 -06:00
Facu_Viñas
5a2ed4eb05 feat: add startup update check with 24h cache
Queries npm registry at most once per 24h to check if a newer version
of gsd-pi is available. Displays a non-blocking banner in interactive
mode when an update exists. The check is fire-and-forget — network
errors or timeouts never block startup.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 14:28:43 -03:00
Lex Christopherson
f51a080bcf wip: port LSP tool from Oh My Pi (needs type fixes)
All 10 LSP files ported and adapted. Wired into tools/index.ts.
Remaining work: fix TypeScript compilation errors (see below).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 11:19:43 -06:00
TÂCHES
1fc3a4ca77 Merge pull request #207 from gsd-build/feat/130-prefs-wizard
feat: add interactive wizard mode for /gsd prefs
2026-03-13 11:01:47 -06:00
TÂCHES
24f8cbc845 Merge pull request #206 from gsd-build/feat/129-thinking-command
feat: add /thinking slash command for toggling thinking level
2026-03-13 11:01:44 -06:00
TÂCHES
f6a942afd6 Merge pull request #205 from gsd-build/fix/177-milestone-id-generation
fix: use max-based milestone ID generation instead of length+1
2026-03-13 11:01:41 -06:00
Lex Christopherson
c622e1d3a6 fix: address audit findings for prefs wizard (#130)
- YAML-safe string quoting for values with special characters
- Preserve existing body content below frontmatter on wizard save
- Preserve existing version instead of hardcoding version: 1
- Update unknown-command fallback to include wizard|setup subcommands
- Show warning when timeout input is not a valid whole number

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:59:27 -06:00
Lex Christopherson
401397362f fix: deduplicate maxNum logic and add nextMilestoneId tests (#177)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:59:10 -06:00
Lex Christopherson
135390542a fix: handle non-thinking models correctly in /thinking command (#129)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:58:49 -06:00
Lex Christopherson
46a083fc5e feat: add interactive wizard mode for /gsd prefs (#130)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:52:55 -06:00
Lex Christopherson
bb10aacb23 feat: add /thinking slash command for toggling thinking level (#129)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:52:53 -06:00
Lex Christopherson
d2fd92f8fc fix: use max-based milestone ID generation instead of length+1 (#177)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:52:52 -06:00
TÂCHES
d9548cdf26 fix: pause auto-mode on provider errors to prevent reassess-roadmap loop (#95) (#202)
When a provider returns a fetch error, the agent_end hook now detects
stopReason === "error" and pauses auto-mode. This prevents the state
machine from silently re-dispatching the same phase until stuck
detection fires.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:39:00 -06:00
TÂCHES
7d64aac6bb fix: show TAB hint for notes input in discuss-mode survey (#192) (#203)
The "None of the above" option description said "add details in notes
below" without telling users to press TAB to reveal the notes input.
Updated the description to "Press TAB to add optional notes." and made
the footer "tab to add notes" hint always visible in single-select mode
(previously hidden until a selection was committed).

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:38:47 -06:00
Adam Dry
2ed7c830d9 fix: merge slice branches to integration branch instead of main (#200)
When working on a feature branch (e.g. f-123-new-thing), GSD creates
slice branches correctly from the current branch but merges them back
to main instead of the feature branch. This is because getMainBranch()
always resolved to the repo default branch with no concept of where
the user started.

Fix: record the current branch as the "integration branch" in a
per-milestone metadata file (.gsd/milestones/<MID>/<MID>-META.json)
when auto-mode starts. getMainBranch() checks this metadata before
falling back to repo defaults, so switchToMain() and mergeSliceToMain()
target the correct branch.

Key details:
- Integration branch is captured once per milestone (idempotent)
- Committed immediately so it survives branch switches (.gsd/ files
  are discarded during checkout)
- main_branch preference still takes highest priority
- Falls back to existing detection if metadata missing (backward compat)
- Per-milestone: different milestones can target different branches
- Validates branch still exists before using it

Tests: 41 new assertions across git-service.test.ts and worktree.test.ts
covering the full lifecycle, multi-slice workflows, resume scenarios,
backward compatibility, and edge cases.
2026-03-13 10:34:28 -06:00
Lex Christopherson
74e9f366bb 2.8.3 2026-03-13 10:30:05 -06:00
Lex Christopherson
4079a92146 docs: update changelog for v2.8.3
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:30:01 -06:00
TÂCHES
3084366d87 fix: handle undefined result from custom() in RPC mode for ask_user_questions (#156, #165, #171) (#199)
In RPC mode, `ctx.ui.custom()` returns `undefined as never`, causing
`showInterviewRound` to return undefined and `Object.keys(result.answers)`
to throw TypeError.

When `showInterviewRound` returns undefined (RPC mode), fall back to
sequential `ctx.ui.select()` calls for each question, forwarding the
abort signal (#171) and supporting `allowMultiple` (#165).

- Add `allowMultiple` to `ExtensionUIDialogOptions`
- Widen `select()` return type to `string | string[] | undefined`
- Add `allowMultiple` to RPC select request and `values` array to response
- Update RPC `select()` to forward `allowMultiple` and parse array responses
- Guard existing `ctx.ui.select()` callers against the widened return type

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:24:57 -06:00
TÂCHES
af27c5dd3c fix: provider-aware model resolution for per-phase preferences (#149) (#198)
Auto mode's model resolution used `allModels.find(m => m.id === modelId)`
which returns the first match regardless of provider. With 30+ duplicate
model IDs across providers, user preferences silently resolved to the
wrong provider.

Three fixes:
- Use `getAvailable()` instead of `getAll()` so only authenticated
  models are considered
- Support `provider/model` format (e.g. "google/gemini-2.5-pro") for
  explicit provider targeting
- For bare IDs, prefer the current session's provider, then first
  available match, with an ambiguity warning
- Store and restore original model provider instead of hardcoding
  "anthropic" when restoring the user's model after auto-mode

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:23:31 -06:00
TÂCHES
f2c6cad4dd fix: align execute-task artifact verification with deriveState and add self-repair (#133) (#195)
verifyExpectedArtifact only checked for the task summary file, but
deriveState determines the next task by finding the first unchecked
checkbox in the slice plan. When the agent writes the summary but
doesn't mark the checkbox, the dispatch loop re-sends the same unit
and gets stuck after max retries.

Part 1: verifyExpectedArtifact now also checks that the task checkbox
is marked [x] in the slice plan for execute-task units.

Part 2: At retry time, if the summary exists but the checkbox is
unmarked, the dispatch logic self-repairs by marking the checkbox
programmatically (via skipExecuteTask) and re-derives state instead
of re-dispatching the same unit.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:23:23 -06:00
TÂCHES
e68f486d8b fix: break research phase infinite loop and sync state on stop (#126) (#193)
Bug 1: resolveMilestoneFile/resolveSliceFile already check file existence
via readdirSync, so the additional loadFile content check was redundant.
Empty research files (exists on disk but no content) caused a loop where
verifyExpectedArtifact marked research complete while dispatch re-triggered
it because loadFile returned falsy for empty files.

Bug 2: stopAuto now calls rebuildState to synchronize disk state, matching
pauseAuto's pattern and preventing stale state on next resume.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:23:15 -06:00
TÂCHES
22cbd2bec3 fix: auto-resolve merge conflicts on .gsd/ runtime files (#189) (#194)
Auto mode exits when mergeSliceToMain() hits conflicts on runtime files
like completed-units.json that were manually committed via `gsd queue`.

Two-part fix:
- Untrack RUNTIME_EXCLUSION_PATHS from the index before merge starts
- If merge conflicts are limited to runtime files, auto-resolve by
  taking ours and removing from index instead of aborting

Closes #189

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:23:07 -06:00
TÂCHES
738444aeeb fix: auto-switch model after /login and /logout to prevent API key errors (#124) (#197)
After /login, if the current model has no valid API key, auto-switch to
a model from the newly authenticated provider. After /logout, if the
current model belongs to the logged-out provider, auto-switch to a
fallback model from a different provider.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:23:00 -06:00
TÂCHES
c344b0af54 fix: use provider field instead of model name prefix for Anthropic detection (#142) (#196)
The before_provider_request hook used model.startsWith("claude") to gate
native web search injection. This matched claude-* models served by any
provider (GitHub Copilot, AWS Bedrock, etc.), incorrectly injecting
Anthropic-only web_search_20250305 tool definitions into non-Anthropic
API requests.

The fix checks the isAnthropicProvider flag (set by model_select via the
provider field) instead of sniffing the model name.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:22:52 -06:00
Lex Christopherson
c87f15868a 2.8.2 2026-03-13 10:09:25 -06:00
Lex Christopherson
7ea7b025f1 docs: update changelog for v2.8.1 and v2.8.2
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:09:21 -06:00
Lex Christopherson
69d8baf17b chore: untrack .claude/ and .gsd/ directories, gitignore *.tgz
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:08:17 -06:00
Lex Christopherson
d9a9a73ab2 fix: replace hardcoded forward-slash path ops with node:path stdlib (#184)
Three locations used lastIndexOf("/") or includes("/") for path
manipulation, which fails on Windows where paths use backslashes.

- auto.ts: writeBlockerPlaceholder directory extraction → dirname()
- interactive-mode.ts: parent directory traversal → path.dirname() loop
- path-utils.ts: non-null assertion on MSYS drive letter access

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:02:20 -06:00
Lex Christopherson
74278ad865 fix: use relative paths in prompts to prevent Windows drive letter mangling (#184)
On Windows, LLMs convert absolute paths like F:\Projects\.gsd\... to
Unix-style /f/Projects/.gsd/... which Node's path.resolve interprets
as drive-root-relative, creating F:\f\Projects\.gsd\... instead.

Replace all *AbsPath template variables in prompt templates with
relative .gsd/... paths that resolve correctly on all platforms.
Add MSYS path normalization in resolveToCwd as defense-in-depth.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:55:15 -06:00
TÂCHES
83af235d86 Merge pull request #188 from gsd-build/worktree-agent-a3ed52d1
fix: untrack runtime files already in git index to prevent merge conflicts
2026-03-13 09:54:30 -06:00
Lex Christopherson
2846f9fcf7 fix: untrack runtime files already in git index to prevent merge conflicts (#187)
Repos that started tracking .gsd/completed-units.json before the
gitignore rule was added continue to see squash-merge conflicts because
.gitignore only prevents new tracking. This adds a bootstrap step that
runs `git rm --cached` on all RUNTIME_EXCLUSION_PATHS, eliminating the
conflict at its source.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:45:25 -06:00
TÂCHES
dde84fa248 Merge pull request #185 from Jamie-BitFlight/docs/preferences-clarification
docs: clarify preferences semantics and best practices
2026-03-13 09:34:36 -06:00
Lex Christopherson
02e2f97054 fix: respect HTTP_PROXY/HTTPS_PROXY env vars for all outbound requests (#131)
GSD bypasses pi-coding-agent's CLI entry point (which sets undici's
EnvHttpProxyAgent as the global dispatcher), so proxy env vars were
ignored — causing 403 errors for users behind HTTPS proxies.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:33:41 -06:00