Commit graph

3806 commits

Author SHA1 Message Date
Lex Christopherson
f8b286c66a fix: repair native module test assertions
- highlight: remove quotes from "bar" assertion (ANSI codes split the string)
- ps: skip listDescendants child test (proc_listchildpids unreliable on macOS)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 13:06:47 -06:00
TÂCHES
6acd001a59 feat(bg-shell): add env action to query shell session state (#238)
Enables querying the current working directory and environment variables
of a persistent shell session. Sends introspection commands to the shell's
stdin, captures output via sentinel-demarcated blocks, and parses key
environment variables. Useful for understanding accumulated shell state
after cd, source, or export commands.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 13:05:18 -06:00
Lex Christopherson
df39cea85e feat: add native ast module with ast-grep structural search and rewrite
Adds the `gsd-ast` crate providing AST-aware code search (`astGrep`) and
rewrite (`astEdit`) via ast-grep with tree-sitter grammars for 38+ languages.
Replaces Oh My Pi's fs_cache/task dependencies with the `ignore` crate for
.gitignore-respecting file walking. Includes TypeScript type declarations
and wrappers in packages/native.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 13:02:29 -06:00
Lex Christopherson
ab5b9e949a fix: copy lsp.md to dist during build
The copy-assets script was missing lsp.md from src/core/lsp/, causing
ENOENT at startup after the defaults.json fix landed.

Closes #233, closes #234

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 13:02:29 -06:00
TÂCHES
aaa96e1d1a feat: add run action to bg_shell for blocking command execution on persistent shells (#237)
Adds sentinel-based output demarcation to execute commands on existing
shell sessions, block until completion, and return structured output
with exit codes. Enables using bg-shell as a persistent execution
environment where shell state (env vars, cwd, virtualenvs) accumulates
across commands.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 13:02:11 -06:00
TÂCHES
df1c2b5b54 feat: add shell process type to bg-shell for persistent interactive sessions (#236)
Shell-type processes provide a persistent execution environment where shell
state accumulates across commands. Key behaviors:
- Auto-transitions to ready status after spawn (200ms delay)
- Defaults to user's shell when no command specified
- Extended dead process TTL (6x normal) for potential restart
- Command history tracking via commandHistory field
- Prompt guideline for discoverability

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 13:01:58 -06:00
Lex Christopherson
75fe5d3319 feat: add native image module — decode, encode, and resize via Rust image crate
Port image processing from Oh My Pi's pi-natives crate, adapted for napi-rs v2.
Exposes NativeImage class with async parse/encode/resize methods backed by the
Rust `image` crate (PNG, JPEG, WebP, GIF support).

Includes:
- task.rs: lightweight async task scheduling for libuv thread pool
- image.rs: NativeImage class with SamplingFilter enum
- TypeScript types and wrapper (parseImage, ImageFormat, SamplingFilter)
- 8 passing tests covering decode, encode, resize, round-trip, error cases

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 12:51:49 -06:00
TÂCHES
daca368ba2 feat: add native clipboard module with arboard backend (#228)
Cross-platform clipboard access (text read/write, image read) via the
arboard Rust crate. No external tools (pbcopy, xclip, etc.) required.

Ported from Oh My Pi's clipboard module with adaptations for GSD's
architecture (direct AsyncTask instead of task::blocking wrapper).

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 12:48:27 -06:00
Lex Christopherson
e05292f772 feat: add native ast module — AST-aware structural search and rewrite via ast-grep
Port ast-grep integration from Oh My Pi with 38+ language support via tree-sitter
grammars. Exposes `astGrep` (search) and `astEdit` (rewrite) as N-API functions
with TypeScript wrappers.

Key changes:
- New `gsd-ast` crate with language definitions, glob utilities, and ast-grep core
- Replaces fs_cache/task dependencies with `ignore` crate for file walking
- Synchronous API matching the existing grep module pattern
- Full TypeScript type declarations in packages/native/src/ast/

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 12:47:27 -06:00
TÂCHES
d64575cd3c feat: add syntect-based syntax highlighting module to native engine (#227)
Port the highlight module from Oh My Pi's pi-natives crate. Provides
ANSI-colored syntax highlighting with scope-based semantic token matching
across 11 categories (comment, keyword, function, variable, string, number,
type, operator, punctuation, inserted, deleted).

Exposed N-API functions:
- highlightCode(code, lang, colors) -> ANSI-highlighted string
- supportsLanguage(lang) -> boolean
- getSupportedLanguages() -> string[]

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 12:47:02 -06:00
TÂCHES
c36c8bd0b0 feat: add native glob and fs_cache modules with gitignore-aware discovery (#226)
Port glob, glob_util, and fs_cache modules from Oh My Pi's pi-natives crate,
adapted for napi-rs v2. Provides gitignore-respecting filesystem discovery
with a TTL-based scan cache, mtime sorting, file-type filtering, and
node_modules exclusion.

Includes a task module for async N-API work scheduling with cooperative
cancellation (timeout-based), TypeScript type declarations and wrapper,
and 12 integration tests covering pattern matching, recursion, gitignore,
maxResults, sortByMtime, fileType filtering, and cache invalidation.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 12:45:56 -06:00
TÂCHES
c5bc8625a4 feat: add cross-platform process tree kill module (ps) (#225)
Port Oh My Pi's ps module providing efficient process tree enumeration
and termination using platform-native APIs (libproc on macOS, /proc on
Linux, Toolhelp32 on Windows).

Exposes four napi functions: killTree, listDescendants, processGroupId,
and killProcessGroup.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 12:43:50 -06:00
Lex Christopherson
b669f9f580 feat: add ANSI-aware text measurement and slicing native module
Port Oh My Pi's optimized text utilities to GSD's native engine:
- wrapTextWithAnsi: word-wrap preserving ANSI codes across breaks
- truncateToWidth: truncate with ellipsis options
- sliceWithWidth: column-range extraction
- extractSegments: split around overlay regions
- sanitizeText: strip ANSI, remove control chars, normalize CR
- visibleWidth: display width excluding ANSI sequences

Single-pass ANSI scanning, ASCII fast-path, grapheme-aware Unicode
width measurement, and zero-copy input via UTF-16 JsString interop.

Includes 19 Rust unit tests and 33 Node.js integration tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 12:42:42 -06:00
Lex Christopherson
a74d2061c1 feat: add html-to-markdown native module
Port HTML-to-Markdown conversion from Oh My Pi's html module using
html-to-markdown-rs. Exposes `htmlToMarkdown()` via N-API with options
for content cleaning (strip nav/forms/headers/footers) and image skipping.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 12:40:42 -06:00
Lex Christopherson
0b288f389f feat: add html-to-markdown native module
Port HTML-to-Markdown conversion from Oh My Pi's html module using
html-to-markdown-rs. Exposes `htmlToMarkdown()` via N-API with options
for content cleaning (strip nav/forms/headers/footers) and image skipping.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 12:40:22 -06:00
Lex Christopherson
fab9ad390d feat: add native clipboard module with arboard backend
Cross-platform clipboard access (text read/write, image read) via the
arboard Rust crate. No external tools (pbcopy, xclip, etc.) required.

Ported from Oh My Pi's clipboard module with adaptations for GSD's
architecture (direct AsyncTask instead of task::blocking wrapper).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 12:36:23 -06:00
TÂCHES
0d390688e3 fix: prevent move operation from silently overwriting existing files (#219) (#223)
Check if the destination file exists before performing a move in
hashline-edit. If it does, return an error instead of silently
overwriting the file.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 12:27:39 -06:00
TÂCHES
3906331b1b fix: copy lsp defaults.json to dist during build (#224)
Closes #221

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 12:27:38 -06:00
TÂCHES
f7b3144291 fix: separate access/unlink error handling in delete path (#219) (#222)
The delete operation in hashline-edit.ts wrapped both access() and
unlink() in a single try/catch. If access succeeded but unlink failed
(e.g., permissions), the error was silently swallowed and "Deleted" was
falsely reported. Now access and unlink have separate error handling:
access failures indicate the file doesn't exist, while unlink failures
propagate to the caller.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 12:27:28 -06:00
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