Commit graph

874 commits

Author SHA1 Message Date
Jeremy McSpadden
084fb35c1e ci: trigger CI run after force push 2026-03-16 13:57:29 -05:00
Jeremy McSpadden
8d56ab2893 feat: add MCP server mode, /lint skill, E2E smoke tests
- Add native MCP server mode (--mode mcp): exposes GSD's tools via
  Model Context Protocol over stdin/stdout for Claude Desktop, VS Code,
  and other MCP-compatible clients. Uses @modelcontextprotocol/sdk.
- Add /lint skill: auto-detects ESLint, Biome, Prettier, rustfmt,
  gofmt, Black, Ruff and runs with structured output
- Add 6 E2E smoke tests: --version, --help, config --help, update
  --help, --list-models, and --mode text --print startup
- Fix diff-context.ts stdio type for CI compatibility
- Fix token-counter.ts tiktoken import for extensions typecheck
- Update help text and CLI to include --mode mcp
2026-03-16 13:56:31 -05:00
Jeremy McSpadden
973b8992e5 feat: add GitHub API client, diff-aware context, tiktoken token counting
- Add GitHub API integration via @octokit/rest: createGitHubClient,
  getRepoInfo (parses HTTPS/SSH remotes), createPullRequest,
  getPullRequest, listPullRequestReviews, createIssueComment
- Add diff-aware context module: getRecentlyChangedFiles,
  getChangedFilesWithContext, rankFilesByRelevance — prioritizes
  recently-changed files for context window budget allocation
- Add accurate token counting via tiktoken: countTokens (async),
  countTokensSync, initTokenCounter — falls back to chars/4 heuristic
  when tiktoken is unavailable
- 27 new tests across 3 test files
2026-03-16 13:50:00 -05:00
Jeremy McSpadden
0b3163d297 feat: add /review skill, /test skill, chokidar file watcher, subcommand help
- Add /review skill: reviews staged/unstaged/commit changes for security,
  performance, bugs, and quality with structured findings by severity
- Add /test skill: auto-detects test framework, generates comprehensive
  tests for source files, or runs suites with failure analysis
- Add chokidar file watcher: watches ~/.gsd/agent/ for config changes
  (settings.json, auth.json, models.json, extensions/) with debounced
  events on an EventBus
- Add --help per subcommand: `gsd config --help` and `gsd update --help`
  show subcommand-specific usage information
- 8 new file-watcher tests (start/stop, event emission, debouncing,
  unrelated file filtering)
2026-03-16 13:47:25 -05:00
TÂCHES
a90aa0c8d6 Merge pull request #666 from jeremymcs/fix/v2.19.0-phase1-quick-wins
fix: v2.20 Phase 1+2 — bugs, security, performance, code quality
2026-03-16 12:44:17 -06:00
TÂCHES
0a43e6de4e Merge pull request #671 from gsd-build/fix/665-auto-resume-recovery
fix: auto-mode resume preserves context from paused session
2026-03-16 12:44:08 -06:00
Jeremy McSpadden
6a46c9df1a fix: resolve browser-tools TypeScript type errors in CI
Fix type compatibility issues introduced in the JS→TS conversion:
- Restore PageEntry.page to `any` (holds Playwright Page instance)
- Use Record<string, any> for session parameters in
  buildFailureHypothesis and summarizeBrowserSession (callers pass
  rich objects with extra properties)
- Use Record<string, unknown> for formatTimelineEntries options
- Add explicit type annotations to local variables and callbacks
  to satisfy noImplicitAny in tsconfig.extensions.json
2026-03-16 13:39:14 -05:00
TÂCHES
26b4e483bd Merge pull request #669 from gsd-build/fix/662-task-count-display
fix: clamp task counter to prevent display overflow after loop recovery
2026-03-16 12:36:02 -06:00
Jeremy McSpadden
ebbcbe363a security: add SSRF protection to fetch_page tool
Block requests to private/internal addresses in the fetch_page tool:
- Private IP ranges (10.x, 172.16-31.x, 192.168.x, 127.x, 169.254.x)
- Cloud metadata endpoints (metadata.google.internal, instance-data)
- localhost
- Non-HTTP protocols (file://, ftp://)
- IPv6 private ranges (::1, fc00:, fd, fe80:)

Add isBlockedUrl() to url-utils.ts with 11 new tests covering all
blocked and allowed URL patterns.
2026-03-16 13:35:48 -05:00
TÂCHES
970479d5b4 Merge pull request #668 from gsd-build/fix/663-small-issues
fix: resolve 4 small issues (#663)
2026-03-16 12:35:48 -06:00
Lex Christopherson
38c300fd80 fix: reuse crash recovery infrastructure for pause/resume context (#665)
Capture the session file path on pause and synthesize a recovery briefing
on resume, so the next agent knows what already happened instead of
restarting the unit from scratch.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 12:35:03 -06:00
Jeremy McSpadden
d41338cafb refactor: extract inline build scripts from package.json to files
- Extract copy-resources, copy-themes, copy-export-html from root
  package.json inline node -e commands to proper .cjs script files
- Extract pi-coding-agent copy-assets (356-char inline command) to
  scripts/copy-assets.cjs with readable multi-line formatting
- All scripts use .cjs extension for CommonJS compatibility in ESM
  package context
2026-03-16 13:34:05 -05:00
Jeremy McSpadden
4af3e5b741 fix: move @types/mime-types to devDependencies, align chalk versions
- Move @types/mime-types from dependencies to devDependencies in pi-tui
  (type declarations are only needed at compile time)
- Align chalk version: upgrade root from ^5.5.0 to ^5.6.2 to match
  pi-ai and avoid version skew
2026-03-16 13:31:15 -05:00
Jeremy McSpadden
a79e953caa refactor: deduplicate help text, cross-platform validate-pack, fix dev.js
- Extract duplicated help text from loader.ts and cli.ts into shared
  help-text.ts module (single source of truth)
- Convert validate-pack.sh to Node.js for Windows compatibility
- Fix dev.js using unnecessary npx for tsc (it's a devDependency,
  use node_modules/.bin/tsc directly)
2026-03-16 13:29:31 -05:00
Lex Christopherson
3399852f6d fix: clamp task counter to prevent "task 5/4" display after loop recovery
When auto-mode loop recovery marks tasks as [x] in the plan file and
auto is restarted, the done count can equal total. The display always
showed done+1 (assuming "currently working on next task"), causing
values like "task 5/4". Clamp to total so it never exceeds the max.

Closes #662

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 12:26:06 -06:00
TÂCHES
1a856ec109 Merge pull request #667 from gsd-build/fix/664-cancel-stale-async-jobs
fix: cancel stale async jobs after source edits (#664)
2026-03-16 12:25:53 -06:00
Jeremy McSpadden
9c8a24042f feat: convert browser-tools/core.js to TypeScript, add c8 test coverage
- Convert browser-tools/core.js (1058 lines) to native TypeScript with
  full type annotations from the existing .d.ts file. Remove the
  separate .d.ts declaration file (types are now inline).
- Add c8 test coverage reporting: `npm run test:coverage` generates
  text + lcov reports with 50% statement threshold baseline.
- Add coverage/ to .gitignore

All 712 unit tests, 63 browser-tools tests, and 11 integration tests
pass with zero regressions.
2026-03-16 13:25:52 -05:00
Lex Christopherson
a58e256e42 fix: resolve 4 small issues reported in #663
1. Windows: `start` command opens CMD instead of browser during GitHub
   Copilot login — pass empty title arg so URL is treated as target
2. Launch banner missing Tavily provider in web search status display
3. MCPorter auto-installs via npm when not found (like ripgrep auto-download)
4. Notification prefs showing [object Object] — guard against non-boolean values

Closes #663

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 12:23:20 -06:00
Lex Christopherson
d6cf8b4358 fix: add stale async job cancellation heuristic to system prompt (#664)
Agent now cancels in-flight async_bash jobs after editing source files
before re-running them, preventing stale results from polluting context.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 12:20:54 -06:00
Jeremy McSpadden
2c926c12e3 fix: Phase 1 quick wins — bug fixes, security hardening, and performance
- Fix loadStoredEnvKeys divergent provider lists: add telegram_bot and
  custom-openai to wizard.ts (the canonical copy used by CLI), remove
  dead duplicate from onboarding.ts
- Security: add SAFE_COMMAND_PREFIXES allowlist to resolveConfigValue
  to prevent arbitrary RCE via settings.json shell commands
- Security: add TOFU (Trust On First Use) model for project-local
  extensions — skip untrusted .pi/extensions/ with stderr warning
- Performance: debounce sql.js MemoryStorage persistence (500ms window)
  so rapid mutations coalesce into a single db.export()+writeFileSync
- Fix double lstatSync call in tool-bootstrap.ts isRegularFile
- Add 26 new tests covering all changes
2026-03-16 13:18:02 -05:00
Lex Christopherson
2966be30cb 2.20.0 2026-03-16 12:16:27 -06:00
Lex Christopherson
04424de6b2 docs: update changelog and README for v2.20.0
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 12:16:05 -06:00
TÂCHES
26facfca51 Merge pull request #661 from gsd-build/fix/456-milestone-detection-loop
fix: prevent infinite loop when milestone detection silently fails (#456)
2026-03-16 12:08:06 -06:00
Lex Christopherson
2da97b2382 merge: sync with main 2026-03-16 12:03:54 -06:00
TÂCHES
445528e865 Merge pull request #573 from gsd-build/test/extension-smoke-test
test: add extension smoke test to catch import failures in CI
2026-03-16 12:02:00 -06:00
Lex Christopherson
cae7d08879 fix: prevent infinite loop when milestone detection silently fails (#456)
findMilestoneIds() had a bare catch that returned [] on any error,
causing showSmartEntry() to think no milestones exist and restart
the new-project discuss flow in a loop. Add error logging when the
directory exists but scanning fails, and a sanity check that warns
the user instead of looping when the directory has entries that
weren't recognized.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 11:57:54 -06:00
Lex Christopherson
3d2f294f6a fix: google-search OAuth test mock and Windows path separator in smoke test
- google-search test: mock getApiKeyForProvider to return JSON string
  matching real OAuth provider behavior (token+projectId), instead of
  using AuthStorage.inMemory which bypasses the OAuth getApiKey transform
- smoke test: split on /[/\\]/ for Windows path separator compatibility

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 11:56:46 -06:00
Lex Christopherson
e66c73daae fix: add missing ProjectTotals fields in visualizer-views test fixture
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 11:49:58 -06:00
Lex Christopherson
20e0fe2460 Merge remote-tracking branch 'origin/main' into test/extension-smoke-test 2026-03-16 11:48:44 -06:00
Lex Christopherson
d187a1ed2d fix: use file:// URL for dynamic imports in smoke test (Windows compat)
On Windows, raw paths like D:\... are interpreted as protocol "d:" by
the ESM loader. Convert via pathToFileURL before dynamic import.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 11:46:04 -06:00
TÂCHES
c6ec4eef50 Merge pull request #660 from gsd-build/copilot/add-blacklist-feature
[WIP] Add blacklist feature for certain directories in chat
2026-03-16 11:34:38 -06:00
Lex Christopherson
8715b5f604 merge: add Google OAuth search support (#466)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 11:33:56 -06:00
Lex Christopherson
02ff88d711 Merge remote-tracking branch 'origin/main' into feat-google-oauth-search 2026-03-16 11:33:50 -06:00
Lex Christopherson
413dbe48eb Merge branch 'main' of https://github.com/gsd-build/GSD-2 2026-03-16 11:27:20 -06:00
TÂCHES
9c62cb97df Merge pull request #657 from gsd-build/merge-fix/594-context-budget
feat(gsd): context-window budget engine — proportional prompt sizing for 1M context models
2026-03-16 11:26:39 -06:00
Lex Christopherson
a0397682a4 merge: fix CPU spinning from regex backtracking (#495)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 11:26:33 -06:00
Lex Christopherson
79d3765379 merge: resolve conflicts with upstream main
Kept both health gate (main) and debug timer (PR) in auto.ts.
Added agentInstructionsBlock to fullSystem composition in index.ts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 11:26:13 -06:00
Lex Christopherson
545ccf58d7 merge: resolve metrics.ts conflict with main
Combine budget fields (contextWindowTokens, truncationSections,
continueHereFired) from PR #594 with prompt char tracking fields
(promptCharCount, baselineCharCount) from main.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 11:25:53 -06:00
copilot-swe-agent[bot]
73fc14c440 Initial plan 2026-03-16 17:23:36 +00:00
TÂCHES
011ed1df71 feat: add Telegram as remote questions channel (#645) (#655)
Add Telegram Bot API as a third remote questions channel alongside
Discord and Slack. Implements the ChannelAdapter interface with inline
keyboard buttons, callback query handling, text reply polling, and
supergroup message URL generation.

Closes #645

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 11:09:39 -06:00
Rebecca Chernoff
17fbf7d925 fix: skip onboarding wizard when extension provider already configured (#589)
Extension-based providers like pi-claude-cli may not require credentials
in auth.json, causing shouldRunOnboarding() to always return true and
repeat the wizard every launch. Now checks if a defaultProvider is
already set in settings before triggering the wizard.
2026-03-16 11:07:15 -06:00
Lex Christopherson
daf36d2b7a fix: resolve merge conflicts with main for PR #594
Merge main into feat/context-window-budget, combining:
- Budget fields (contextWindowTokens, truncationSections, continueHereFired)
  from the PR with routing fields (tier, modelDowngraded) from main in
  UnitMetrics interface
- Unified opts parameter pattern in snapshotUnitMetrics
- KNOWLEDGE.md step from main with template path references from the PR
  in execute-task.md

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 11:04:58 -06:00
Jeremy McSpadden
2042a30232 feat: workflow mode system (solo/team) with /gsd mode command (#651)
* feat: add workflow mode system (solo/team) with /gsd mode command

Introduces a `mode` preference that bundles sensible defaults for solo
developers vs team workflows, replacing the need to manually configure
5-8 individual git preferences.

* fix: resolve TS2339 — use string narrowing for ctx.ui.select return type
2026-03-16 11:04:51 -06:00
Tom Boucher
cdf42fe001 fix: prevent model config bleed between concurrent GSD instances (#650) (#652)
Two fixes for the model configuration bleeding between simultaneous
GSD instances that share the same global settings.json.

## Root Cause

1. `setDefaultModelAndProvider()` always persisted to `~/.gsd/agent/settings.json`
   (global), so when either instance's interactive mode changed models (via
   Ctrl+P or /model), it overwrote the other instance's saved default.

2. When auto-mode dispatched a new unit (after context wipe), if no
   per-unit-type model preference was configured, the session picked up
   the default from the now-contaminated global settings file.

## Fix 1: Project-scoped model persistence (settings-manager.ts)

`setDefaultModelAndProvider()`, `setDefaultModel()`, and `setDefaultProvider()`
now persist to project-level settings (`.pi/settings.json`) when a project
settings file exists, falling back to global only when no project context
is available. This prevents concurrent instances from overwriting each
other's model choice.

Added `hasProjectSettingsFile()` helper to detect project context.

## Fix 2: Auto-mode model capture (auto.ts)

Captures the session's model at auto-mode start (`autoModeStartModel`).
At each unit dispatch, if no model preference is configured for the unit
type, the captured model is re-applied with `persist: false`. This
ensures each auto-mode session maintains its own model regardless of
what other instances write to the shared settings file.

## Tests

3 new tests covering:
- Project settings file isolates model from global
- Two projects have independent model configs
- autoModeStartModel concept prevents model drift

All 448 existing tests pass.

Fixes #650
2026-03-16 10:59:12 -06:00
Jeremy McSpadden
53edf284fa feat: /gsd quick command & agent-instructions.md injection (#437)
* fix: bg_shell ready_port timeout and error handling (#428)

When a server fails to bind to the configured ready_port, the process
would stay in "starting" status indefinitely after the probing interval
cleared, with no error surfaced to the agent. This fixes the hang by:

- Transitioning process to "error" status when port probing times out
- Detecting process exit during port polling and reporting stderr context
- Adding ready_timeout parameter for custom timeout values
- Including stderr output in waitForReady timeout/error responses
- Registering SIGTERM/SIGINT handlers to clean up bg processes on exit

Closes #428

* feat: add /gsd quick command and agent-instructions.md injection (#425)

Implements two features from issue #425:

1. `/gsd quick <task>` — lightweight task execution with GSD guarantees
   (atomic commits, state tracking) without the full milestone ceremony.
   Creates `.gsd/quick/<num>-<slug>/` directory, a git branch, and
   dispatches a focused prompt for in-session execution.

2. Agent instructions file — loads `~/.gsd/agent-instructions.md` (global)
   and `.gsd/agent-instructions.md` (project), injects into every GSD
   agent session via the before_agent_start hook. Lets users add durable
   instructions like notification preferences or environment constraints.

Closes #425

---------

Co-authored-by: TÂCHES <afromanguy@me.com>
2026-03-16 10:45:50 -06:00
Jeremy McSpadden
061d826a4e feat(doctor): add 7 runtime health checks with auto-fix (#646)
* feat(doctor): add 7 runtime health checks with auto-fix

Add comprehensive runtime health monitoring to /gsd doctor:

- stale_crash_lock: detect dead auto.lock from crashed sessions, auto-clear
- orphaned_completed_units: find completed-unit keys referencing missing artifacts, auto-remove
- stale_hook_state: detect residual hook cycle counts with no running session, auto-clear
- activity_log_bloat: flag activity/ dir exceeding 500 files or 100MB, auto-prune (7-day retention)
- state_file_missing: detect missing STATE.md when milestones exist, auto-generate
- state_file_stale: detect STATE.md drift (wrong phase/milestone/slice), auto-rebuild
- gitignore_missing_patterns: detect missing critical GSD runtime patterns in .gitignore, auto-fix

All checks are non-fatal (gracefully degrade on read errors) and respect
the existing fix/fixLevel system. Includes 34 new test assertions across
9 test scenarios in doctor-runtime.test.ts.

* feat(doctor): add proactive healing layer for auto-mode

Three new mechanisms for automatic health monitoring:

1. Pre-dispatch health gate: runs before each unit dispatch in auto-mode.
   Checks for stale crash locks (auto-clears) and corrupt merge state
   (auto-heals via abortAndReset). Pauses auto-mode if critical issues
   can't be resolved.

2. Health score tracking: records error/warning/fix counts after each
   post-unit doctor run. Tracks trends (improving/stable/degrading)
   across a sliding window of 50 snapshots. Monitors consecutive
   error unit streaks.

3. Auto-heal escalation: when deterministic fixes can't resolve errors
   after 5 consecutive units AND health trend is not improving,
   automatically dispatches LLM-assisted heal (dispatchDoctorHeal).
   Single-fire per session to prevent spam. Defers escalation when
   trend is improving (fixes are working, just slowly).

Integration points in auto.ts:
- resetProactiveHealing() on start/stop
- preDispatchHealthGate() before deriveState in dispatchNextUnit
- recordHealthSnapshot() + checkHealEscalation() in post-unit hook
- formatHealthSummary() available for dashboard display

Includes 30 test assertions across 15 scenarios.
2026-03-16 10:34:26 -06:00
Tom Boucher
cb9191fa4f chore: remove .gsd/ planning artifacts from tracking (#648)
Development planning artifacts (.gsd/) are project-specific state that
lives in worktree branches during active development. Tracking them on
main causes merge conflicts with worktree-isolated auto-mode and leaves
stale snapshots that mislead.

- Remove 157 .gsd/ files from git tracking (kept on disk)
- Replace granular .gsd/ gitignore rules with single .gsd/ entry
- Files remain available locally for reference

Closes #647
2026-03-16 10:33:34 -06:00
Tom Boucher
2a250b8eb0 feat: skill lifecycle management — telemetry, health dashboard, heal-skill (#599) (#649)
Implements the core skill lifecycle management feature requested in #599,
incorporating glittercowboy's heal-skill concept from taches-cc-resources.

## What's included

### Phase 1: Skill Usage Telemetry
- Added optional `skills?: string[]` field to `UnitMetrics` interface
- New `skill-telemetry.ts` module captures available/loaded skills per unit
- `captureAvailableSkills()` called at dispatch time in auto.ts
- `getAndClearSkills()` auto-called by `snapshotUnitMetrics()` — zero changes
  needed at existing call sites
- Tracks both 'available' and 'actively loaded' (via SKILL.md reads) skills

### Phase 2: Skill Health Dashboard
- New `/gsd skill-health` command with three modes:
  - Overview table: name, uses, success%, avg tokens, trend, last used
  - `/gsd skill-health <name>` — detailed view for a single skill
  - `/gsd skill-health --declining` — only flagged skills
  - `/gsd skill-health --stale N` — skills unused for N+ days
- Aggregation from metrics.json: pass rate, token trends, staleness warnings
- Declining performance flags (success <70%, token usage rising 20%+)

### Phase 3: Staleness Detection
- `skill_staleness_days` preference (default: 60, 0 = disabled)
- `detectStaleSkills()` identifies skills unused beyond threshold
- `computeStaleAvoidList()` for auto-excluding stale skills

### Heal-Skill Integration (glittercowboy's concept)
- New `heal-skill.md` prompt template for post-unit hook integration
- `buildHealSkillPrompt()` generates analysis prompts that:
  1. Detect which skill was loaded during a unit
  2. Compare agent execution against skill guidance
  3. Assess drift severity (none/minor/significant)
  4. Write suggestions to `.gsd/skill-review-queue.md` for human review
- Critically: does NOT auto-modify skills (SkillsBench lesson)

### Tests
- 10 new tests covering telemetry, health, preferences validation
- All 455 existing tests continue to pass

Ref #599
Incorporates feedback from @glittercowboy (heal-skill concept)
2026-03-16 10:32:55 -06:00
Flux Labs
34a99fbeba merge: resolve conflicts with main, remove copyright headers
Merge origin/main, keeping debug mode features while adopting
projectRoot() usage. Removed all copyright headers per project
conventions.
2026-03-16 11:13:43 -05:00
Jeremy McSpadden
30b688bee0 feat: add worktree post-create hook for environment setup (#597) (#617)
* feat: add worktree post-create hook for environment setup (#597)

Add git.worktree_post_create preference — a script path that GSD
runs after creating any worktree (both auto-mode and manual /worktree).
The script receives SOURCE_DIR and WORKTREE_DIR as environment
variables, enabling users to copy .env files, symlink asset
directories, or run other setup commands that git worktrees don't
inherit from the main tree.

Implementation:
- Add worktree_post_create field to GitPreferences interface
- Add validation in validatePreferences (must be non-empty string)
- Add runWorktreePostCreateHook() in auto-worktree.ts — resolves
  relative paths against project root, runs with 30s timeout,
  failure is non-fatal (warning only)
- Integrate hook call in createAutoWorktree() (auto-mode path)
- Integrate hook call in worktree-command.ts (manual /worktree path)
- Update docs/configuration.md with full usage guide and example
  hook script
- Update preferences-reference.md with field documentation

Example configuration:
  git:
    worktree_post_create: .gsd/hooks/post-worktree-create

Example hook script:
  #!/bin/bash
  cp "$SOURCE_DIR/.env" "$WORKTREE_DIR/.env"
  ln -sf "$SOURCE_DIR/assets" "$WORKTREE_DIR/assets"

Closes #597

* fix: use Node.js scripts in hook tests for Windows compatibility

Replace bash hook scripts with cross-platform Node.js scripts in
worktree-post-create-hook.test.ts. On macOS/Linux, scripts use
#!/usr/bin/env node shebang. On Windows, generates batch files
that invoke node -e. Fixes windows-portability CI failures.

* fix: Windows CI failures in worktree post-create hook tests

- Use path.isAbsolute() instead of startsWith("/") to detect absolute
  paths on Windows (fixes double-path bug like C:\...\C:\...)
- Add .bat extension to hook scripts on Windows so they are recognized
  as executable by cmd.exe
- Extract isWin constant and hookPath() helper for consistent
  platform-aware test setup

Fixes 3 failing tests in windows-portability CI job:
  - executes hook script with correct env vars
  - supports absolute hook paths
  - hook can copy files from source to worktree

* fix: adopt main's help command and error message in commands.ts

The auto-merge missed main's addition of the help handler, showHelp
function, and updated description/subcommands array. Added them
manually and updated the visualizer help text to reflect 7-tab TUI.

* fix: write Windows hook scripts as .bat + companion .js file

The previous approach embedded multi-line JavaScript in a node -e "..."
argument inside the .bat file. cmd.exe splits on newlines, so each JS
line was interpreted as a separate batch command ('const' is not
recognized...).

Now writes the JS code to a companion .js file and the .bat invokes
it with `node "%~dp0<file>.js"`, which works reliably on Windows.

---------

Co-authored-by: TÂCHES <afromanguy@me.com>
2026-03-16 09:50:45 -06:00