chore: remove .gsd/ from tracking (already in .gitignore)
This commit is contained in:
parent
cd01a47461
commit
b17ab25aaa
30 changed files with 0 additions and 2305 deletions
|
|
@ -1,26 +0,0 @@
|
|||
# Decisions Register
|
||||
|
||||
<!-- Append-only. Never edit or remove existing rows.
|
||||
To reverse a decision, add a new row that supersedes it.
|
||||
Read this file at the start of any planning or research phase. -->
|
||||
|
||||
| # | When | Scope | Decision | Choice | Rationale | Revisable? |
|
||||
|---|------|-------|----------|--------|-----------|------------|
|
||||
| D001 | M001 | arch | Smart staging approach | Exclusion filter (not file ownership tracking) | Covers 95% of the problem with minimal complexity. Fallback to git add -A on failure. | Yes — if exclusion filter proves insufficient |
|
||||
| D002 | M001 | arch | worktree.ts migration strategy | Thin facade (keep exports, delegate to GitService) | Backward compatibility — 6+ existing callers don't need changes | Yes — if full migration desired later |
|
||||
| D003 | M001 | arch | Merged branch lifecycle | Delete after squash merge (not preserve) | Squash commit is the permanent record. Branch sprawl has near-zero debugging value. | No |
|
||||
| D004 | M001 | arch | Snapshot refs vs checkpoint commits | Hidden snapshot refs (refs/gsd/snapshots/) | Invisible recovery without cluttering branch history | No |
|
||||
| D005 | M001 | scope | PR creation workflow | Deferred | Separate concern touching GitHub API, gh CLI, merge queue. Out of scope for trust boundary fix. | Yes — future milestone |
|
||||
| D006 | M001 | scope | Milestone tags | Deferred | Low value relative to core trust boundary fix | Yes — future milestone |
|
||||
| D007 | M001 | arch | Git Notes for metadata | Rejected | Fragile, poorly supported by tools, unreliable push/pull semantics | No |
|
||||
| D008 | M001 | arch | Pre-merge verification timing | Phase 3 (enhanced features) | Core service + bug fixes first. Current workflow hasn't been catastrophic without guards. | No |
|
||||
| D009 | M001 | arch | Doc fixes timing | Phase 1 (with bug fixes) | Pure text changes, zero risk, related to same git mechanics | No |
|
||||
| D010 | M001 | arch | Test strategy | Unit tests with temp repos | Same proven pattern as existing worktree.test.ts | No |
|
||||
| D011 | M001/S01 | arch | GitService reuses worktree.ts pure utilities | Import detectWorktreeName, getSliceBranchName, SLICE_BRANCH_RE from worktree.ts | These are pure functions with no side effects. Reimplementing would create drift. S02 facade wiring won't break these exports. | No |
|
||||
| D012 | M001/S01 | arch | RUNTIME_EXCLUSION_PATHS defined independently | Define exclusion paths in git-service.ts independently of gitignore.ts BASELINE_PATTERNS | Keeps S01 self-contained without touching gitignore.ts. BASELINE_PATTERNS is unexported. Converge later if needed. | Yes — converge in future cleanup |
|
||||
| D013 | M001/S01 | impl | COMMIT_TYPE_RULES includes plural keyword forms | Added "docs" and "tests" as explicit keywords alongside singular "doc" and "test" | Word-boundary regex `\bdoc\b` doesn't match "docs" — the trailing `s` is a word character. Plurals are common in slice titles. | No |
|
||||
| D014 | M001/S02 | impl | MergeSliceResult re-export uses `export type` | `export type { MergeSliceResult }` instead of value `export { MergeSliceResult }` | Circular dependency (git-service.ts ↔ worktree.ts) causes ESM live binding resolution failure with value re-exports. Type-only re-export is erased at runtime, avoiding the cycle. MergeSliceResult is an interface so this is semantically correct and transparent to consumers. | No |
|
||||
| D015 | M001/S05 | arch | Pre-merge check runs after squash merge, resets on failure | Run check after `git merge --squash` but before `git commit`, reset `--hard HEAD` on failure | Tests the actual merged code (what will land on main), not just the slice branch in isolation. Reset is clean because commit hasn't happened yet. | No |
|
||||
| D016 | M001/S05 | arch | Multi-line commit via `git commit -F -` with stdin | Replace `JSON.stringify(message)` + `-m` with `execSync` stdin pipe + `-F -` | Avoids shell quoting fragility for multi-line rich commit messages. Newlines survive reliably through stdin. | No |
|
||||
| D017 | M001/S05 | impl | Facade prefs fix via loadEffectiveGSDPreferences | worktree.ts `getService()` calls `loadEffectiveGSDPreferences()` instead of `{}` | Unblocks all preference-gated features (snapshots, pre_merge_check, auto_push) when called through the facade. One-line fix with high impact. | No |
|
||||
| D018 | M001/S05 | impl | Snapshot gating requires explicit `true` | `prefs.snapshots === true` (not `!== false`) — undefined means disabled | Tests (T01) define undefined as disabled, only explicit `true` enables. Safer default: no hidden refs unless user opts in. Task plan said default-on but tests are authoritative. | No |
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
# Project
|
||||
|
||||
## What This Is
|
||||
|
||||
GSD (Get Shit Done) is a coding agent harness built as a pi extension. It manages structured planning and execution workflows — milestones, slices, tasks — with automated git branching, LLM-driven execution, and mechanical verification.
|
||||
|
||||
This project is the GSD extension itself (`gsd-pi`), a TypeScript package that provides the `/gsd` command, auto-mode orchestration, worktree management, and all planning/execution infrastructure.
|
||||
|
||||
## Core Value
|
||||
|
||||
Deterministic, reliable git operations that keep main clean and working while agents do the coding. The user never touches git — the system handles branching, committing, merging, and recovery.
|
||||
|
||||
## Current State
|
||||
|
||||
GSD is a working, shipped product (v2.4.0). The trust boundary between deterministic code and LLM prompts has been fixed: all git operations now route through a centralized `GitService` class. Smart staging excludes runtime files, commit types are inferred from slice titles, merge guards auto-detect and run tests before landing on main, hidden snapshot refs enable rollback, and prompts contain no raw git commands. The thin facade in `worktree.ts` preserves backward compatibility while delegating to `GitServiceImpl`.
|
||||
|
||||
## Architecture / Key Patterns
|
||||
|
||||
- TypeScript, compiled with `tsc`, tested with Node's built-in test runner
|
||||
- Extension entry: `src/resources/extensions/gsd/index.ts`
|
||||
- Orchestrator: `auto.ts` (2600+ lines) — dispatches units, manages lifecycle
|
||||
- Git operations: `git-service.ts` (centralized GitService), `worktree.ts` (thin facade for backward compat), `worktree-manager.ts` (git worktrees), `worktree-command.ts` (CLI commands)
|
||||
- Prompts: `prompts/*.md` — Handlebars-templated instructions for LLM units (no raw git commands)
|
||||
- Preferences: `preferences.ts` — YAML frontmatter in markdown files, includes `git?: GitPreferences`
|
||||
- Patterns: `execSync` for git via `runGit()` helper, `SKIP_PATHS` for diff filtering, smart staging with exclusion filter
|
||||
|
||||
## Capability Contract
|
||||
|
||||
See `.gsd/REQUIREMENTS.md` for the explicit capability contract, requirement status, and coverage mapping.
|
||||
|
||||
## Milestone Sequence
|
||||
|
||||
- [x] M001: Deterministic GitService — Centralized all git mechanics into GitService, fixed bugs, removed git from prompts, added merge guards and recovery. All 18 requirements validated.
|
||||
|
|
@ -1,351 +0,0 @@
|
|||
# Requirements
|
||||
|
||||
This file is the explicit capability and coverage contract for the project.
|
||||
|
||||
## Active
|
||||
|
||||
(No active requirements — all M001 requirements validated.)
|
||||
|
||||
## Validated
|
||||
|
||||
### R001 — Centralized GitService class
|
||||
- Class: core-capability
|
||||
- Status: validated
|
||||
- Description: A single `GitService` class in `git-service.ts` that owns all git mechanics — commit, branch, merge, checkout, staging
|
||||
- Why it matters: Moves git operations from probabilistic LLM prompts to deterministic code. The foundational trust boundary fix.
|
||||
- Source: user
|
||||
- Primary owning slice: M001/S01
|
||||
- Supporting slices: M001/S02
|
||||
- Validation: git-service.ts exists with GitServiceImpl class. npm run build passes. Unit tests pass.
|
||||
- Notes: Uses existing `runGit()` pattern from worktree.ts
|
||||
|
||||
### R002 — Smart staging with exclusion filter
|
||||
- Class: core-capability
|
||||
- Status: validated
|
||||
- Description: Replace `git add -A` with filtered staging that excludes known runtime paths (.gsd/runtime/, .gsd/activity/, .gsd/STATE.md, .gsd/auto.lock, .gsd/metrics.json)
|
||||
- Why it matters: Prevents accidental commits of runtime/bookkeeping files that should never be tracked
|
||||
- Source: user
|
||||
- Primary owning slice: M001/S01
|
||||
- Supporting slices: none
|
||||
- Validation: RUNTIME_EXCLUSION_PATHS in git-service.ts. Fallback to git add -A verified by unit test.
|
||||
- Notes: Fallback to `git add -A` with warning if filtering fails
|
||||
|
||||
### R003 — Conventional commit type inference
|
||||
- Class: quality-attribute
|
||||
- Status: validated
|
||||
- Description: Infer commit type (feat/fix/refactor/docs/test/chore) from slice title keywords instead of hardcoding `feat`
|
||||
- Why it matters: Accurate git history that can be filtered and parsed by conventional-commits tooling
|
||||
- Source: user
|
||||
- Primary owning slice: M001/S01
|
||||
- Supporting slices: none
|
||||
- Validation: inferCommitType() with COMMIT_TYPE_RULES in git-service.ts. Unit tests verify keyword matching.
|
||||
- Notes: Default to `feat` when no keywords match. Plurals handled (D013).
|
||||
|
||||
### R004 — Git preferences schema
|
||||
- Class: core-capability
|
||||
- Status: validated
|
||||
- Description: Add `git?: GitPreferences` to GSDPreferences interface with validation, merge logic, and documentation
|
||||
- Why it matters: Enables all preference-gated git features (auto_push, merge guards, etc.) via existing preferences system
|
||||
- Source: user
|
||||
- Primary owning slice: M001/S02
|
||||
- Supporting slices: M001/S05
|
||||
- Validation: GitPreferences on line 55 of preferences.ts. Validation logic, template, and docs/preferences-reference.md exist.
|
||||
- Notes: Fields: auto_push, push_branches, remote, snapshots, pre_merge_check, commit_type
|
||||
|
||||
### R005 — worktree.ts thin facade delegation
|
||||
- Class: core-capability
|
||||
- Status: validated
|
||||
- Description: worktree.ts keeps existing exports but delegates internally to GitService. All existing callers continue to work without changes.
|
||||
- Why it matters: Backward compatibility — existing imports from worktree.ts don't break
|
||||
- Source: user
|
||||
- Primary owning slice: M001/S02
|
||||
- Supporting slices: none
|
||||
- Validation: worktree.ts delegates to GitServiceImpl. npm run build passes. Existing worktree tests pass.
|
||||
- Notes: New code should import from GitService directly
|
||||
|
||||
### R006 — auto.ts wired to GitService
|
||||
- Class: core-capability
|
||||
- Status: validated
|
||||
- Description: Replace inline git calls in auto.ts (git add -A, autoCommitCurrentBranch, ensureSliceBranch, switchToMain, mergeSliceToMain) with GitService methods
|
||||
- Why it matters: The orchestrator is the primary caller of git operations — it must route through the centralized service
|
||||
- Source: user
|
||||
- Primary owning slice: M001/S02
|
||||
- Supporting slices: none
|
||||
- Validation: auto.ts imports and initializes GitServiceImpl. Only init bootstrap retains inline git (allowed by spec).
|
||||
- Notes: git status --porcelain for idle detection and git rev-parse --git-dir for init check remain inline as allowed
|
||||
|
||||
### R007 — Bug fix: worktree create ordering
|
||||
- Class: quality-attribute
|
||||
- Status: validated
|
||||
- Description: Move autoCommitCurrentBranch() BEFORE createWorktree() in worktree-command.ts so new worktrees fork from committed state
|
||||
- Why it matters: Previously new worktrees forked from pre-commit HEAD, missing the user's latest saved state
|
||||
- Source: user
|
||||
- Primary owning slice: M001/S03
|
||||
- Supporting slices: none
|
||||
- Validation: worktree-command.ts reordered per S03. npm run build passes.
|
||||
- Notes: Fixed in S03
|
||||
|
||||
### R008 — Bug fix: worktree merge dispatch
|
||||
- Class: quality-attribute
|
||||
- Status: validated
|
||||
- Description: Use deterministic mergeWorktreeToMain() helper as default merge path in worktree-command.ts. Keep LLM-mediated path only for complex conflict resolution.
|
||||
- Why it matters: The deterministic helper already exists but wasn't used as the default — merge went through LLM unnecessarily
|
||||
- Source: user
|
||||
- Primary owning slice: M001/S03
|
||||
- Supporting slices: none
|
||||
- Validation: worktree-command.ts uses deterministic helper as default per S03.
|
||||
- Notes: Fixed in S03
|
||||
|
||||
### R009 — Bug fix: hardcoded feat commit type
|
||||
- Class: quality-attribute
|
||||
- Status: validated
|
||||
- Description: Replace hardcoded `feat(...)` in mergeSliceToMain with inferCommitType() from GitService
|
||||
- Why it matters: Bugfix slices, docs slices, refactor slices were mislabeled as `feat`
|
||||
- Source: user
|
||||
- Primary owning slice: M001/S01
|
||||
- Supporting slices: M001/S02
|
||||
- Validation: mergeSliceToMain calls inferCommitType(). Unit tests verify correct type inference.
|
||||
- Notes: Fixed in S01, wired in S02
|
||||
|
||||
### R010 — Doc fixes: branch preservation + checkpoint claims
|
||||
- Class: quality-attribute
|
||||
- Status: validated
|
||||
- Description: Fix README.md "preserved" claim to "deleted after merge". Fix GSD-WORKFLOW.md "Branch kept" to "Branch deleted". Replace checkpoint commit documentation with snapshot ref description.
|
||||
- Why it matters: Docs previously claimed behaviors the code didn't implement — eroded trust
|
||||
- Source: user
|
||||
- Primary owning slice: M001/S03
|
||||
- Supporting slices: none
|
||||
- Validation: README.md says "deleted after merge" (line 260). GSD-WORKFLOW.md says "Branch deleted" (line 551).
|
||||
- Notes: Fixed in S03
|
||||
|
||||
### R011 — Remove raw git commands from prompts
|
||||
- Class: core-capability
|
||||
- Status: validated
|
||||
- Description: Replace `git add -A && git commit` instructions in execute-task.md, complete-slice.md, replan-slice.md, complete-milestone.md with "the system commits automatically" messages
|
||||
- Why it matters: LLMs should not run git commands — that's the whole point of the GitService trust boundary
|
||||
- Source: user
|
||||
- Primary owning slice: M001/S04
|
||||
- Supporting slices: none
|
||||
- Validation: grep of 4 prompt files returns zero git command matches. worktree-merge.md unchanged.
|
||||
- Notes: worktree-merge.md kept as-is (conflict resolution needs LLM judgment)
|
||||
|
||||
### R012 — Pre-merge verification (merge guards)
|
||||
- Class: core-capability
|
||||
- Status: validated
|
||||
- Description: Auto-detect test/typecheck/build commands from package.json, Cargo.toml, Makefile, pyproject.toml. Run before squash merge. Abort on failure.
|
||||
- Why it matters: Prevents broken code from landing on main
|
||||
- Source: user
|
||||
- Primary owning slice: M001/S05
|
||||
- Supporting slices: none
|
||||
- Validation: runPreMergeCheck() in git-service.ts. Runs after squash before commit, resets on failure (D015). Unit tests pass.
|
||||
- Notes: Configurable via git.pre_merge_check preference: "auto" (default), false (skip), or custom command
|
||||
|
||||
### R013 — Hidden snapshot refs for rollback
|
||||
- Class: core-capability
|
||||
- Status: validated
|
||||
- Description: Create refs/gsd/snapshots/<branch>/<timestamp> before merges and risky operations. Prunable after 7 days.
|
||||
- Why it matters: Invisible recovery points without cluttering branch history with checkpoint commits
|
||||
- Source: user
|
||||
- Primary owning slice: M001/S05
|
||||
- Supporting slices: none
|
||||
- Validation: createSnapshot() in git-service.ts. Gated by prefs.snapshots === true (D018). Unit tests pass.
|
||||
- Notes: Invisible to normal git log. Visible via git for-each-ref refs/gsd/snapshots/
|
||||
|
||||
### R014 — Optional auto-push (preference-gated)
|
||||
- Class: core-capability
|
||||
- Status: validated
|
||||
- Description: When git.auto_push: true, push main to remote after slice merge. Optionally push slice branches during work.
|
||||
- Why it matters: Remote backup and team visibility for senior engineers
|
||||
- Source: user
|
||||
- Primary owning slice: M001/S05
|
||||
- Supporting slices: none
|
||||
- Validation: auto-push logic in mergeSliceToMain, gated by prefs.auto_push. Unit tests verify push behavior.
|
||||
- Notes: Default: false. Remote name configurable via git.remote (default: "origin")
|
||||
|
||||
### R015 — Rich squash commit messages with task lists
|
||||
- Class: quality-attribute
|
||||
- Status: validated
|
||||
- Description: Squash merge commits include task list extracted from branch commit history and branch reference for forensics
|
||||
- Why it matters: Self-documenting git history that reads like a changelog
|
||||
- Source: user
|
||||
- Primary owning slice: M001/S05
|
||||
- Supporting slices: none
|
||||
- Validation: Rich commit builder in git-service.ts. Uses -F - stdin pipe (D016). Unit tests pass.
|
||||
- Notes: Format: type(scope): title\n\nTasks:\n- T01: ...\n\nBranch: gsd/M001/S01
|
||||
|
||||
### R016 — Bug fix: stale branch base with remote fetch
|
||||
- Class: quality-attribute
|
||||
- Status: validated
|
||||
- Description: When a remote exists, git fetch --prune before cutting a new slice branch. Warn (don't block) if local main is behind origin.
|
||||
- Why it matters: Prevents branching from stale trunk HEAD
|
||||
- Source: user
|
||||
- Primary owning slice: M001/S05
|
||||
- Supporting slices: none
|
||||
- Validation: Remote fetch in ensureSliceBranch. Behind-upstream warning verified by unit test.
|
||||
- Notes: Only when remote exists and auto_push is enabled or remote is configured
|
||||
|
||||
### R017 — GitService unit tests
|
||||
- Class: quality-attribute
|
||||
- Status: validated
|
||||
- Description: Unit tests using temp git repos for all GitService methods, following the existing worktree test patterns
|
||||
- Why it matters: Mechanical verification that git operations work correctly
|
||||
- Source: inferred
|
||||
- Primary owning slice: M001/S01
|
||||
- Supporting slices: M001/S05
|
||||
- Validation: git-service.test.ts has 30 test cases, all passing. Uses temp git repos.
|
||||
- Notes: Same test infrastructure as worktree.test.ts
|
||||
|
||||
### R018 — Archive design input files
|
||||
- Class: quality-attribute
|
||||
- Status: validated
|
||||
- Description: Remove or archive CODEX-GIT-SYNTHESIS.md, CLAUDE-GIT-SYNTHESIS.md, GEMINI-GIT-SYNTHESIS.md, and ONBOARDING-PLAN.md
|
||||
- Why it matters: Design input files are not permanent docs — they clutter the repo after implementation
|
||||
- Source: user
|
||||
- Primary owning slice: M001/S06
|
||||
- Supporting slices: none
|
||||
- Validation: All 4 files confirmed deleted. Git history preserves them.
|
||||
- Notes: Deleted in S06
|
||||
|
||||
## Deferred
|
||||
|
||||
### R019 — PR creation workflow
|
||||
- Class: core-capability
|
||||
- Status: deferred
|
||||
- Description: Auto-create PRs via gh CLI after slice merge when git.auto_pr is enabled
|
||||
- Why it matters: Team workflow integration for shared repos with protected branches
|
||||
- Source: research
|
||||
- Primary owning slice: none
|
||||
- Supporting slices: none
|
||||
- Validation: unmapped
|
||||
- Notes: Deferred — touches GitHub API, gh CLI detection, merge queue awareness. Separate concern from core GitService.
|
||||
|
||||
### R020 — Milestone tags on completion
|
||||
- Class: quality-attribute
|
||||
- Status: deferred
|
||||
- Description: Create annotated git tags on milestone completion (e.g. M001)
|
||||
- Why it matters: Enables git describe, changelog generation, and clear release markers
|
||||
- Source: research
|
||||
- Primary owning slice: none
|
||||
- Supporting slices: none
|
||||
- Validation: unmapped
|
||||
- Notes: Deferred — low value relative to core trust boundary fix
|
||||
|
||||
### R021 — Full file ownership tracking
|
||||
- Class: core-capability
|
||||
- Status: deferred
|
||||
- Description: Track every file the agent creates/modifies per unit. Only stage owned files.
|
||||
- Why it matters: More precise staging than exclusion filter — prevents unrelated user edits from being committed
|
||||
- Source: research
|
||||
- Primary owning slice: none
|
||||
- Supporting slices: none
|
||||
- Validation: unmapped
|
||||
- Notes: Deferred — requires threading ownership through entire execution pipeline. Exclusion filter covers 95% of the problem.
|
||||
|
||||
## Out of Scope
|
||||
|
||||
### R022 — Git Notes for metadata
|
||||
- Class: anti-feature
|
||||
- Status: out-of-scope
|
||||
- Description: Store task plans and verification results in git notes
|
||||
- Why it matters: Prevents fragile, poorly-supported metadata mechanism from entering the codebase
|
||||
- Source: research
|
||||
- Primary owning slice: none
|
||||
- Supporting slices: none
|
||||
- Validation: n/a
|
||||
- Notes: Git Notes are fragile, poorly rendered by most tools, unreliable push/pull semantics
|
||||
|
||||
### R023 — Shadow worktrees as default model
|
||||
- Class: anti-feature
|
||||
- Status: out-of-scope
|
||||
- Description: Make git worktrees the default execution model for all agent work
|
||||
- Why it matters: Over-engineering for common single-agent case. Worktrees are already available as advanced opt-in.
|
||||
- Source: research
|
||||
- Primary owning slice: none
|
||||
- Supporting slices: none
|
||||
- Validation: n/a
|
||||
- Notes: Rejected from Gemini's proposal
|
||||
|
||||
### R024 — AI-driven rebases
|
||||
- Class: anti-feature
|
||||
- Status: out-of-scope
|
||||
- Description: LLM-driven interactive rebase and cross-slice conflict resolution
|
||||
- Why it matters: Prevents hidden magic that makes senior engineers distrust the system
|
||||
- Source: research
|
||||
- Primary owning slice: none
|
||||
- Supporting slices: none
|
||||
- Validation: n/a
|
||||
- Notes: Merge conflicts require deterministic resolution or human intervention
|
||||
|
||||
### R025 — Stacked branches
|
||||
- Class: anti-feature
|
||||
- Status: out-of-scope
|
||||
- Description: Stacked branch/PR workflow as default execution model
|
||||
- Why it matters: Over-engineering for solo/vibe coder workflows
|
||||
- Source: research
|
||||
- Primary owning slice: none
|
||||
- Supporting slices: none
|
||||
- Validation: n/a
|
||||
- Notes: Could be opt-in advanced mode in a future milestone
|
||||
|
||||
### R026 — CI/CD integration
|
||||
- Class: anti-feature
|
||||
- Status: out-of-scope
|
||||
- Description: Deployment pipeline integration from GSD
|
||||
- Why it matters: GSD manages work orchestration, not infrastructure
|
||||
- Source: research
|
||||
- Primary owning slice: none
|
||||
- Supporting slices: none
|
||||
- Validation: n/a
|
||||
- Notes: Merge guards handle "is it broken?" — deployment is the user's concern
|
||||
|
||||
### R027 — Commit signing (GPG)
|
||||
- Class: anti-feature
|
||||
- Status: out-of-scope
|
||||
- Description: GPG commit signing for agent commits
|
||||
- Why it matters: Adds friction with zero value when the agent is the committer
|
||||
- Source: research
|
||||
- Primary owning slice: none
|
||||
- Supporting slices: none
|
||||
- Validation: n/a
|
||||
- Notes: Could be opt-in preference in a future milestone
|
||||
|
||||
## Traceability
|
||||
|
||||
| ID | Class | Status | Primary owner | Supporting | Proof |
|
||||
|---|---|---|---|---|---|
|
||||
| R001 | core-capability | validated | M001/S01 | M001/S02 | git-service.ts exists, build passes |
|
||||
| R002 | core-capability | validated | M001/S01 | none | smart staging + fallback in unit tests |
|
||||
| R003 | quality-attribute | validated | M001/S01 | none | inferCommitType unit tests |
|
||||
| R004 | core-capability | validated | M001/S02 | M001/S05 | preferences.ts git field + docs |
|
||||
| R005 | core-capability | validated | M001/S02 | none | facade delegates, build passes |
|
||||
| R006 | core-capability | validated | M001/S02 | none | auto.ts wired to GitServiceImpl |
|
||||
| R007 | quality-attribute | validated | M001/S03 | none | worktree-command.ts reordered |
|
||||
| R008 | quality-attribute | validated | M001/S03 | none | deterministic merge as default |
|
||||
| R009 | quality-attribute | validated | M001/S01 | M001/S02 | inferCommitType replaces hardcoded feat |
|
||||
| R010 | quality-attribute | validated | M001/S03 | none | README + GSD-WORKFLOW corrected |
|
||||
| R011 | core-capability | validated | M001/S04 | none | grep confirms zero git commands |
|
||||
| R012 | core-capability | validated | M001/S05 | none | runPreMergeCheck unit tests |
|
||||
| R013 | core-capability | validated | M001/S05 | none | createSnapshot unit tests |
|
||||
| R014 | core-capability | validated | M001/S05 | none | auto-push unit tests |
|
||||
| R015 | quality-attribute | validated | M001/S05 | none | rich commit builder unit tests |
|
||||
| R016 | quality-attribute | validated | M001/S05 | none | remote fetch unit tests |
|
||||
| R017 | quality-attribute | validated | M001/S01 | M001/S05 | 30 tests in git-service.test.ts |
|
||||
| R018 | quality-attribute | validated | M001/S06 | none | 4 files confirmed deleted |
|
||||
| R019 | core-capability | deferred | none | none | unmapped |
|
||||
| R020 | quality-attribute | deferred | none | none | unmapped |
|
||||
| R021 | core-capability | deferred | none | none | unmapped |
|
||||
| R022 | anti-feature | out-of-scope | none | none | n/a |
|
||||
| R023 | anti-feature | out-of-scope | none | none | n/a |
|
||||
| R024 | anti-feature | out-of-scope | none | none | n/a |
|
||||
| R025 | anti-feature | out-of-scope | none | none | n/a |
|
||||
| R026 | anti-feature | out-of-scope | none | none | n/a |
|
||||
| R027 | anti-feature | out-of-scope | none | none | n/a |
|
||||
|
||||
## Coverage Summary
|
||||
|
||||
- Active requirements: 0
|
||||
- Validated requirements: 18
|
||||
- Mapped to slices: 18
|
||||
- Deferred: 3
|
||||
- Out of scope: 6
|
||||
- Unmapped active requirements: 0
|
||||
|
|
@ -1,130 +0,0 @@
|
|||
# M001: Deterministic GitService — Context
|
||||
|
||||
**Gathered:** 2026-03-12
|
||||
**Status:** Ready for planning
|
||||
|
||||
## Project Description
|
||||
|
||||
GSD's git workflow is architecturally sound (trunk-based, branch-per-slice, squash-merge) but has a critical trust boundary problem: git operations are split between deterministic TypeScript code and probabilistic LLM prompts that run raw `git add -A && git commit`. This causes accidental commits of runtime files, hardcoded commit types, no pre-merge verification, and no recovery mechanism.
|
||||
|
||||
The fix is a centralized `GitService` that owns all git mechanics while the LLM focuses on writing code.
|
||||
|
||||
## Why This Milestone
|
||||
|
||||
GSD is already shipping (v2.3.11) and the git strategy mostly works. But the trust boundary problem creates real bugs: runtime files get committed, all commits are labeled `feat`, there's no safety net before merging to main, and docs claim behaviors the code doesn't implement. Fixing this now prevents these issues from compounding as more users adopt GSD.
|
||||
|
||||
## User-Visible Outcome
|
||||
|
||||
### When this milestone is complete, the user can:
|
||||
|
||||
- Run a full GSD auto-mode cycle where all git operations are handled by deterministic code (no LLM-driven git commands)
|
||||
- See correctly typed commit messages in git log (fix, refactor, docs — not always feat)
|
||||
- Trust that broken code won't land on main (merge guards auto-detect and run tests)
|
||||
- Recover from bad merges via hidden snapshot refs
|
||||
- Optionally enable auto-push to remote via preferences
|
||||
|
||||
### Entry point / environment
|
||||
|
||||
- Entry point: `/gsd auto` CLI command
|
||||
- Environment: local dev (Node.js, git CLI)
|
||||
- Live dependencies involved: git CLI, optional remote (origin)
|
||||
|
||||
## Completion Class
|
||||
|
||||
- Contract complete means: `npm run build` passes, `npm run test` passes (existing + new GitService tests), no raw git commands in prompts
|
||||
- Integration complete means: A full GSD slice lifecycle (branch → execute → commit → merge) routes through GitService
|
||||
- Operational complete means: none — this is internal infrastructure, not a service
|
||||
|
||||
## Final Integrated Acceptance
|
||||
|
||||
To call this milestone complete, we must prove:
|
||||
|
||||
- `npm run build` and `npm run test` pass
|
||||
- A slice lifecycle in auto-mode produces commits via GitService (correct types, no accidental runtime file commits)
|
||||
- Prompts contain no raw git commands (except worktree-merge.md)
|
||||
- Git preferences are recognized and applied (auto_push, merge guards)
|
||||
- Existing worktree commands still work (create/merge/remove)
|
||||
|
||||
## Risks and Unknowns
|
||||
|
||||
- **Wiring facade without breaking callers** — worktree.ts is imported by auto.ts, state.ts, worktree-command.ts, workspace-index.ts. The thin facade must preserve all export signatures exactly.
|
||||
- **auto.ts complexity** — 2600+ lines. Wiring changes need surgical precision to avoid regressions in the orchestrator.
|
||||
- **Smart staging edge cases** — Exclusion filter might miss patterns or filter too aggressively. Fallback to `git add -A` is the safety net.
|
||||
- **Test infrastructure compatibility** — Existing worktree tests use temp repos. GitService tests must follow the same pattern without conflicts.
|
||||
|
||||
## Existing Codebase / Prior Art
|
||||
|
||||
- `src/resources/extensions/gsd/worktree.ts` — Current slice branch lifecycle (290 lines). Will become thin facade.
|
||||
- `src/resources/extensions/gsd/worktree-manager.ts` — Git worktree lifecycle (392 lines). Has `mergeWorktreeToMain()` deterministic helper that should be used by default.
|
||||
- `src/resources/extensions/gsd/worktree-command.ts` — CLI commands (803 lines). Has bugs #1 and #2.
|
||||
- `src/resources/extensions/gsd/auto.ts` — Orchestrator (2652 lines). Primary consumer of git operations.
|
||||
- `src/resources/extensions/gsd/preferences.ts` — Preferences system (616 lines). Will get `git?: GitPreferences`.
|
||||
- `src/resources/extensions/gsd/gitignore.ts` — Has `BASELINE_PATTERNS` — same set the smart staging exclusion filter should use.
|
||||
- `src/resources/extensions/gsd/tests/worktree.test.ts` — Existing tests using temp git repos. Pattern to follow for GitService tests.
|
||||
- `src/resources/extensions/gsd/tests/worktree-integration.test.ts` — Integration tests for worktree lifecycle.
|
||||
|
||||
> See `.gsd/DECISIONS.md` for all architectural and pattern decisions — it is an append-only register; read it during planning, append to it during execution.
|
||||
|
||||
## Relevant Requirements
|
||||
|
||||
- R001–R018 — All active requirements are owned by this milestone's slices
|
||||
- See `.gsd/REQUIREMENTS.md` for full details
|
||||
|
||||
## Scope
|
||||
|
||||
### In Scope
|
||||
|
||||
- New `git-service.ts` with all git mechanics
|
||||
- Smart staging (exclusion filter)
|
||||
- Commit type inference
|
||||
- Git preferences schema
|
||||
- Wiring auto.ts and worktree.ts to GitService
|
||||
- Bug fixes (#1 worktree create ordering, #2 merge dispatch, #4 hardcoded feat, #5 stale branch base)
|
||||
- Doc fixes (README.md, GSD-WORKFLOW.md)
|
||||
- Prompt cleanup (remove raw git commands)
|
||||
- Pre-merge verification (merge guards)
|
||||
- Hidden snapshot refs
|
||||
- Optional auto-push
|
||||
- Rich squash commit messages
|
||||
- Archive design input files
|
||||
- Unit tests for GitService
|
||||
|
||||
### Out of Scope / Non-Goals
|
||||
|
||||
- PR creation workflow (R019 — deferred)
|
||||
- Milestone tags (R020 — deferred)
|
||||
- Full file ownership tracking (R021 — deferred)
|
||||
- Git Notes, shadow worktrees, AI rebases, stacked branches, CI/CD, commit signing (R022–R027 — out of scope)
|
||||
|
||||
## Technical Constraints
|
||||
|
||||
- Must preserve all existing exports from worktree.ts (thin facade pattern)
|
||||
- Must use existing `runGit()` pattern (execSync-based)
|
||||
- Must use existing test infrastructure (Node built-in test runner, temp git repos)
|
||||
- Preferences must follow existing YAML-in-markdown frontmatter format
|
||||
- `git status --porcelain` for idle detection in auto.ts may remain inline (not part of GitService)
|
||||
|
||||
## Integration Points
|
||||
|
||||
- `auto.ts` — Primary consumer. Calls ensureSliceBranch, autoCommit, switchToMain, mergeSliceToMain.
|
||||
- `worktree-command.ts` — Calls autoCommitCurrentBranch, createWorktree. Has bugs to fix.
|
||||
- `worktree-manager.ts` — Has mergeWorktreeToMain() that GitService should delegate to or replace.
|
||||
- `state.ts` — Imports getActiveSliceBranch from worktree.ts.
|
||||
- `workspace-index.ts` — Imports getSliceBranchName, detectWorktreeName from worktree.ts.
|
||||
- `preferences.ts` — Will gain git?: GitPreferences field.
|
||||
- `gitignore.ts` — BASELINE_PATTERNS should be shared with smart staging exclusion filter.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- None — all decisions resolved during discussion.
|
||||
|
||||
## Per-Slice Reading Guide
|
||||
|
||||
| Slice | Read before starting |
|
||||
|---|---|
|
||||
| S01 | `worktree.ts`, `worktree-manager.ts`, `gitignore.ts` (for SKIP_PATHS/BASELINE_PATTERNS) |
|
||||
| S02 | S01 summary, `auto.ts` (lines 55-75, 350-380, 470-510, 980-1020, 2220-2230), `preferences.ts` |
|
||||
| S03 | S02 summary, `worktree-command.ts` (lines 340-370, 660-710), `README.md` (lines 250-270), `GSD-WORKFLOW.md` (lines 540-590) |
|
||||
| S04 | S02 summary, all prompt files in `prompts/` |
|
||||
| S05 | S02 summary, `git-service.ts` (from S01), `preferences.ts` (from S02) |
|
||||
| S06 | All prior summaries, root-level synthesis/audit files |
|
||||
|
|
@ -1,142 +0,0 @@
|
|||
# M001: Deterministic GitService
|
||||
|
||||
**Vision:** Centralize all git mechanics into a single deterministic GitService, fixing the trust boundary where probabilistic LLM prompts currently run raw git commands. The result: reliable commits, typed history, merge guards, recovery snapshots, and zero git commands in prompts.
|
||||
|
||||
## Success Criteria
|
||||
|
||||
- All git operations in auto-mode route through GitService (no inline execSync git calls except `git status --porcelain` for idle detection and `git rev-parse --git-dir` for init check)
|
||||
- `npm run build` passes
|
||||
- `npm run test` passes (existing tests + new GitService tests)
|
||||
- No raw git commands in LLM-facing prompts (except worktree-merge.md for conflict resolution)
|
||||
- Git preferences recognized in preferences.md schema
|
||||
- README and GSD-WORKFLOW doc claims match actual code behavior
|
||||
- Squash merge commits use correct conventional types (not always `feat`)
|
||||
|
||||
## Key Risks / Unknowns
|
||||
|
||||
- **Facade wiring breaks callers** — worktree.ts has 6+ consumers. Any export signature change breaks the build.
|
||||
- **auto.ts surgery** — 2600+ line orchestrator. Changes must be surgical to avoid regressions.
|
||||
- **Smart staging edge cases** — Exclusion filter may miss patterns or over-filter. Fallback to `git add -A` is the safety net.
|
||||
|
||||
## Proof Strategy
|
||||
|
||||
- Facade wiring breaks callers → retire in S02 by proving `npm run build` and `npm run test` pass with the facade in place
|
||||
- auto.ts surgery → retire in S02 by proving auto.ts compiles and existing tests pass
|
||||
- Smart staging edge cases → retire in S01 by proving unit tests cover exclusion patterns and fallback behavior
|
||||
|
||||
## Verification Classes
|
||||
|
||||
- Contract verification: `npm run build`, `npm run test`, grep prompts for raw git commands
|
||||
- Integration verification: Full slice lifecycle through GitService (exercised by existing worktree tests + new GitService tests)
|
||||
- Operational verification: none — internal infrastructure
|
||||
- UAT / human verification: Run a GSD auto-mode cycle and check git log for correct commit types
|
||||
|
||||
## Milestone Definition of Done
|
||||
|
||||
This milestone is complete only when all are true:
|
||||
|
||||
- All slice deliverables are complete
|
||||
- `npm run build` passes
|
||||
- `npm run test` passes (existing + new)
|
||||
- No raw git commands in execute-task.md, complete-slice.md, replan-slice.md, complete-milestone.md
|
||||
- Git preferences parse and apply correctly
|
||||
- README.md and GSD-WORKFLOW.md match actual behavior
|
||||
- Design input files (synthesis/audit) are archived
|
||||
|
||||
## Requirement Coverage
|
||||
|
||||
- Covers: R001, R002, R003, R004, R005, R006, R007, R008, R009, R010, R011, R012, R013, R014, R015, R016, R017, R018
|
||||
- Partially covers: none
|
||||
- Leaves for later: R019 (PR workflow), R020 (milestone tags), R021 (file ownership tracking)
|
||||
- Orphan risks: none
|
||||
|
||||
## Slices
|
||||
|
||||
- [x] **S01: GitService core implementation** `risk:high` `depends:[]`
|
||||
> After this: `git-service.ts` exists with commit, autoCommit, ensureSliceBranch, switchToMain, mergeSliceToMain, inferCommitType, smart staging — all passing unit tests in temp git repos.
|
||||
|
||||
- [x] **S02: Wire GitService into codebase** `risk:high` `depends:[S01]`
|
||||
> After this: auto.ts and worktree.ts delegate to GitService. Git preferences schema added to preferences.ts. `npm run build` passes. Existing worktree tests still pass.
|
||||
|
||||
- [x] **S03: Bug fixes and doc corrections** `risk:medium` `depends:[S02]`
|
||||
> After this: Worktree create commits before fork. Worktree merge uses deterministic helper by default. README and GSD-WORKFLOW match actual branch deletion and snapshot behavior. Build passes.
|
||||
|
||||
- [x] **S04: Remove git commands from prompts** `risk:low` `depends:[S02]`
|
||||
> After this: execute-task.md, complete-slice.md, replan-slice.md, complete-milestone.md contain no raw git commands. worktree-merge.md unchanged. Verified by grep.
|
||||
|
||||
- [x] **S05: Enhanced features — merge guards, snapshots, auto-push, rich commits** `risk:medium` `depends:[S02]`
|
||||
> After this: Pre-merge verification auto-detects test runners and blocks broken merges. Snapshot refs created before merges (visible via `git for-each-ref refs/gsd/snapshots/`). auto_push preference pushes main after merge. Squash commits include task lists. Remote fetch before branching when remote exists. All verified by unit tests.
|
||||
|
||||
- [x] **S06: Cleanup and archive** `risk:low` `depends:[S05]`
|
||||
> After this: CODEX-GIT-SYNTHESIS.md, CLAUDE-GIT-SYNTHESIS.md, GEMINI-GIT-SYNTHESIS.md, and ONBOARDING-PLAN.md are deleted. Final doc consistency check passes.
|
||||
|
||||
## Boundary Map
|
||||
|
||||
### S01 → S02
|
||||
|
||||
Produces:
|
||||
- `git-service.ts` → `GitServiceImpl` class with constructor `(basePath: string, prefs: GitPreferences)`
|
||||
- `git-service.ts` → `GitPreferences` interface (auto_push, push_branches, remote, snapshots, pre_merge_check, commit_type)
|
||||
- `git-service.ts` → `commit(opts: CommitOptions)` — smart staging with exclusion filter, conventional commit message
|
||||
- `git-service.ts` → `autoCommit(unitType: string, unitId: string)` — safety-net commit after LLM session
|
||||
- `git-service.ts` → `ensureSliceBranch(milestoneId: string, sliceId: string)` — create/checkout slice branch
|
||||
- `git-service.ts` → `switchToMain()` — switch to main, auto-commit dirty state first
|
||||
- `git-service.ts` → `mergeSliceToMain(milestoneId: string, sliceId: string, sliceTitle: string)` — squash merge with inferred commit type
|
||||
- `git-service.ts` → `inferCommitType(sliceTitle: string)` — keyword-based type inference
|
||||
- `git-service.ts` → `getMainBranch()`, `getCurrentBranch()`, `isOnSliceBranch()`, `getActiveSliceBranch()`
|
||||
- `git-service.ts` → Shared exclusion patterns (aligned with gitignore.ts BASELINE_PATTERNS)
|
||||
|
||||
Consumes:
|
||||
- nothing (first slice)
|
||||
|
||||
### S02 → S03
|
||||
|
||||
Produces:
|
||||
- `worktree.ts` — thin facade: all existing exports preserved, internals delegate to `GitServiceImpl`
|
||||
- `auto.ts` — all git callsites route through GitService
|
||||
- `preferences.ts` — `git?: GitPreferences` field with validation and merge logic
|
||||
- `templates/preferences.md` — `git:` section in template
|
||||
- `docs/preferences-reference.md` — git preferences documented
|
||||
|
||||
Consumes from S01:
|
||||
- `git-service.ts` → `GitServiceImpl`, `GitPreferences`, all public methods
|
||||
|
||||
### S02 → S04
|
||||
|
||||
Produces:
|
||||
- Same as S02 → S03 (prompts depend on the system committing automatically, which S02 enables)
|
||||
|
||||
Consumes from S01:
|
||||
- Same as S02 → S03
|
||||
|
||||
### S02 → S05
|
||||
|
||||
Produces:
|
||||
- Same as S02 → S03 (enhanced features build on the GitService and preferences schema)
|
||||
|
||||
Consumes from S01:
|
||||
- Same as S02 → S03
|
||||
|
||||
### S03 → S06
|
||||
|
||||
Produces:
|
||||
- Fixed `worktree-command.ts` — create ordering, merge dispatch
|
||||
- Fixed `README.md` — branch lifecycle claims
|
||||
- Fixed `GSD-WORKFLOW.md` — checkpoint/branch docs
|
||||
|
||||
Consumes from S02:
|
||||
- `worktree.ts` facade (for autoCommitCurrentBranch used in create ordering fix)
|
||||
- `git-service.ts` (for mergeWorktreeToMain delegation)
|
||||
|
||||
### S05 → S06
|
||||
|
||||
Produces:
|
||||
- `git-service.ts` → `createSnapshot(label: string)` — hidden snapshot refs
|
||||
- `git-service.ts` → `runPreMergeCheck()` — auto-detect and execute verification
|
||||
- `git-service.ts` → auto-push logic in mergeSliceToMain
|
||||
- `git-service.ts` → rich squash commit message builder
|
||||
- `git-service.ts` → remote fetch before branching
|
||||
|
||||
Consumes from S02:
|
||||
- `git-service.ts` core methods
|
||||
- `preferences.ts` git preferences (pre_merge_check, auto_push, remote)
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
# S01: GitService Core Implementation
|
||||
|
||||
**Goal:** A standalone `GitServiceImpl` class in `git-service.ts` that encapsulates all git mechanics — commit, autoCommit, ensureSliceBranch, switchToMain, mergeSliceToMain, smart staging, commit type inference — with comprehensive unit tests passing in temp git repos.
|
||||
**Demo:** `node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/git-service.test.ts` passes all assertions.
|
||||
|
||||
## Must-Haves
|
||||
|
||||
- `GitServiceImpl` class with constructor `(basePath: string, prefs?: GitPreferences)`
|
||||
- `GitPreferences` interface exported (auto_push, push_branches, remote, snapshots, pre_merge_check, commit_type)
|
||||
- `commit(opts: CommitOptions)` with smart staging exclusion filter + fallback to `git add -A`
|
||||
- `autoCommit(unitType: string, unitId: string)` using smart staging
|
||||
- `ensureSliceBranch(milestoneId, sliceId)` with worktree-aware naming, branch-from-current logic, pre-checkout auto-commit using smart staging
|
||||
- `switchToMain()` with pre-checkout auto-commit using smart staging
|
||||
- `mergeSliceToMain(milestoneId, sliceId, sliceTitle)` with `inferCommitType()` instead of hardcoded `feat`
|
||||
- `inferCommitType(sliceTitle: string)` exported as pure function
|
||||
- `getMainBranch()`, `getCurrentBranch()`, `isOnSliceBranch()`, `getActiveSliceBranch()`
|
||||
- `RUNTIME_EXCLUSION_PATHS` exported constant (the 6 GSD runtime paths)
|
||||
- Unit tests covering: smart staging exclusion, smart staging fallback, commit type inference for all types, branch lifecycle, merge with correct commit type, empty-commit-after-staging guard
|
||||
|
||||
## Proof Level
|
||||
|
||||
- This slice proves: contract
|
||||
- Real runtime required: no (temp git repos in tests)
|
||||
- Human/UAT required: no
|
||||
|
||||
## Verification
|
||||
|
||||
- `node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/git-service.test.ts` — all tests pass
|
||||
- `npm run build` — TypeScript compilation still passes (git-service.ts is in extensions, excluded from tsc, but verify no import breakage)
|
||||
- `npm run test` — all existing tests still pass (no regressions)
|
||||
|
||||
## Observability / Diagnostics
|
||||
|
||||
- Runtime signals: None — this is a library module, not a runtime service. Errors surface as thrown `Error` instances with descriptive messages including the failed git command and basePath.
|
||||
- Inspection surfaces: Test output shows pass/fail counts per test group. `git log` in temp repos verifies commit messages and types.
|
||||
- Failure visibility: All `runGit()` failures include the full git command and working directory in the error message. Smart staging fallback logs a warning to stderr when exclusion pathspecs fail.
|
||||
- Redaction constraints: None — no secrets handled.
|
||||
|
||||
## Integration Closure
|
||||
|
||||
- Upstream surfaces consumed: None (first slice)
|
||||
- New wiring introduced in this slice: `git-service.ts` module with `GitServiceImpl` class and exports — standalone, not yet consumed by any caller
|
||||
- What remains before the milestone is truly usable end-to-end: S02 (wire into auto.ts/worktree.ts), S03 (bug fixes), S04 (remove git from prompts), S05 (enhanced features), S06 (cleanup)
|
||||
|
||||
## Tasks
|
||||
|
||||
- [x] **T01: Create git-service.ts with GitPreferences, RUNTIME_EXCLUSION_PATHS, runGit, and inferCommitType** `est:30m`
|
||||
- Why: Foundation types, constants, and pure functions that everything else depends on. Separating these first means T02/T03 can build on stable exports.
|
||||
- Files: `src/resources/extensions/gsd/git-service.ts`, `src/resources/extensions/gsd/tests/git-service.test.ts`
|
||||
- Do: Define `GitPreferences` interface with all fields (defaulting to safe values). Export `RUNTIME_EXCLUSION_PATHS` array matching the 6 GSD runtime paths from BASELINE_PATTERNS/SKIP_PATHS. Implement local `runGit()` (same pattern as worktree.ts). Implement `inferCommitType(sliceTitle)` as exported pure function with keyword matching for fix/refactor/docs/test/chore, defaulting to feat. Create test file with test scaffolding (assert/assertEq helpers, temp repo setup) and tests for `inferCommitType` covering all types + default. Tests for `RUNTIME_EXCLUSION_PATHS` matching the known 6 paths.
|
||||
- Verify: `node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/git-service.test.ts` passes
|
||||
- Done when: `inferCommitType` returns correct types for all keyword variants, `RUNTIME_EXCLUSION_PATHS` has exactly the 6 expected paths, tests pass
|
||||
|
||||
- [x] **T02: Implement GitServiceImpl — smart staging, commit, and autoCommit** `est:45m`
|
||||
- Why: The core value of GitService is smart staging (R002) and centralized commit (R001). This task builds the `GitServiceImpl` class with the staging/commit methods that all other operations depend on.
|
||||
- Files: `src/resources/extensions/gsd/git-service.ts`, `src/resources/extensions/gsd/tests/git-service.test.ts`
|
||||
- Do: Implement `GitServiceImpl` class with `(basePath, prefs)` constructor. Implement private `smartStage()` using `git add -A -- . ':(exclude)path'` for each RUNTIME_EXCLUSION_PATHS entry, with fallback to `git add -A` + stderr warning on failure. Implement `commit(opts: CommitOptions)` that calls smartStage, checks `git diff --cached --stat` for empty, builds conventional commit message. Implement `autoCommit(unitType, unitId)`. Add tests: smart staging excludes runtime files, smart staging fallback works, commit with message, autoCommit on clean repo returns null, autoCommit on dirty repo commits and returns message, empty-after-staging guard (only runtime files dirty → no commit).
|
||||
- Verify: All new tests pass alongside T01 tests
|
||||
- Done when: Smart staging provably excludes `.gsd/activity/`, `.gsd/runtime/`, `.gsd/STATE.md`, `.gsd/auto.lock`, `.gsd/metrics.json`, `.gsd/worktrees/` while staging other files. Fallback to `git add -A` works when pathspec fails.
|
||||
|
||||
- [x] **T03: Implement branch lifecycle — ensureSliceBranch, switchToMain, branch queries** `est:40m`
|
||||
- Why: Covers R001 branch operations. These methods replicate the logic from worktree.ts but route staging through smart staging instead of `git add -A`.
|
||||
- Files: `src/resources/extensions/gsd/git-service.ts`, `src/resources/extensions/gsd/tests/git-service.test.ts`
|
||||
- Do: Implement `getMainBranch()`, `getCurrentBranch()`, `isOnSliceBranch()`, `getActiveSliceBranch()` — same logic as worktree.ts. Implement `ensureSliceBranch(milestoneId, sliceId)` with worktree detection, branch-from-current-not-main logic, pre-checkout smart staging auto-commit. Implement `switchToMain()` with pre-checkout smart staging auto-commit. Add tests: branch creation, idempotent ensure, branch-from-non-main-working-branch, branch-from-slice-falls-back-to-main, switchToMain auto-commits dirty files using smart staging (verify runtime files excluded), query methods return correct values on main vs slice branch.
|
||||
- Verify: All tests pass including branch lifecycle tests
|
||||
- Done when: `ensureSliceBranch` and `switchToMain` use smart staging for pre-checkout commits, branch creation logic matches worktree.ts behavior, all query methods work correctly
|
||||
|
||||
- [x] **T04: Implement mergeSliceToMain with inferCommitType and full integration tests** `est:40m`
|
||||
- Why: Closes R001 (merge), R003 (commit type inference in merge), R009 (fixes hardcoded feat). This is the capstone method that proves the full GitService lifecycle works end-to-end.
|
||||
- Files: `src/resources/extensions/gsd/git-service.ts`, `src/resources/extensions/gsd/tests/git-service.test.ts`
|
||||
- Do: Implement `mergeSliceToMain(milestoneId, sliceId, sliceTitle)` — switchToMain, verify on main, check branch exists, check commits ahead, squash merge, use `inferCommitType(sliceTitle)` for commit message (not hardcoded feat), delete branch. Add integration tests: full lifecycle (create branch → commit on branch → merge → verify commit message type), merge with fix title → `fix(...)` commit, merge with docs title → `docs(...)` commit, merge with feature title → `feat(...)` commit, error cases (not on main, branch doesn't exist, no commits ahead). Run `npm run build` and `npm run test` to verify no regressions.
|
||||
- Verify: `node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/git-service.test.ts` — all tests pass. `npm run build` passes. `npm run test` passes.
|
||||
- Done when: Full GitService lifecycle works in tests, merge commits use inferred type from slice title, all existing tests still pass, build is green
|
||||
|
||||
## Files Likely Touched
|
||||
|
||||
- `src/resources/extensions/gsd/git-service.ts` (new)
|
||||
- `src/resources/extensions/gsd/tests/git-service.test.ts` (new)
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
---
|
||||
estimated_steps: 5
|
||||
estimated_files: 2
|
||||
---
|
||||
|
||||
# T01: Create git-service.ts with GitPreferences, RUNTIME_EXCLUSION_PATHS, runGit, and inferCommitType
|
||||
|
||||
**Slice:** S01 — GitService Core Implementation
|
||||
**Milestone:** M001
|
||||
|
||||
## Description
|
||||
|
||||
Create the `git-service.ts` module with the foundational types, constants, and pure functions. This establishes the `GitPreferences` interface that the entire milestone depends on, the `RUNTIME_EXCLUSION_PATHS` constant that smart staging uses, and `inferCommitType()` which fixes the hardcoded `feat` bug (R009). Also sets up the test file with the project's established test pattern (manual assert/assertEq, temp git repos, main() async wrapper).
|
||||
|
||||
## Steps
|
||||
|
||||
1. Create `src/resources/extensions/gsd/git-service.ts` with imports (`node:fs`, `node:child_process`, `node:path`, `node:os`).
|
||||
2. Define and export `GitPreferences` interface: `auto_push?: boolean`, `push_branches?: boolean`, `remote?: string`, `snapshots?: boolean`, `pre_merge_check?: boolean | string`, `commit_type?: string`.
|
||||
3. Define and export `CommitOptions` interface: `message: string`, `allowEmpty?: boolean`.
|
||||
4. Define and export `MergeSliceResult` interface (same shape as worktree.ts): `branch: string`, `mergedCommitMessage: string`, `deletedBranch: boolean`.
|
||||
5. Export `RUNTIME_EXCLUSION_PATHS` constant: the 6 GSD runtime paths (`[".gsd/activity/", ".gsd/runtime/", ".gsd/worktrees/", ".gsd/auto.lock", ".gsd/metrics.json", ".gsd/STATE.md"]`).
|
||||
6. Implement local `runGit(basePath, args, options?)` function — same pattern as worktree.ts (execSync, trim, allowFailure flag, descriptive error message).
|
||||
7. Implement and export `inferCommitType(sliceTitle: string): string` — keyword matching: `fix`/`bug`/`patch`/`hotfix` → `fix`, `refactor`/`restructure`/`reorganize` → `refactor`, `doc`/`documentation` → `docs`, `test`/`testing` → `test`, `chore`/`cleanup`/`clean up`/`archive`/`remove`/`delete` → `chore`. Case-insensitive word boundary matching. Default: `feat`.
|
||||
8. Create `src/resources/extensions/gsd/tests/git-service.test.ts` following worktree.test.ts pattern: imports, assert/assertEq helpers, `run()` helper, temp repo setup, async `main()`.
|
||||
9. Add tests for `inferCommitType`: feature title → `feat`, fix title → `fix`, refactor title → `refactor`, docs title → `docs`, test title → `test`, chore title → `chore`, mixed keywords → first match wins, unknown → `feat`.
|
||||
10. Add test verifying `RUNTIME_EXCLUSION_PATHS` contains exactly the 6 expected paths.
|
||||
|
||||
## Must-Haves
|
||||
|
||||
- [ ] `GitPreferences` interface exported with all 6 fields
|
||||
- [ ] `CommitOptions` interface exported
|
||||
- [ ] `MergeSliceResult` interface exported
|
||||
- [ ] `RUNTIME_EXCLUSION_PATHS` exported with exactly 6 paths matching SKIP_PATHS + SKIP_EXACT
|
||||
- [ ] `inferCommitType()` exported, returns correct type for all keyword categories
|
||||
- [ ] `inferCommitType()` defaults to `feat` for unrecognized titles
|
||||
- [ ] Test file follows project test pattern (assert/assertEq, async main, process.exit on failure)
|
||||
- [ ] All tests pass
|
||||
|
||||
## Verification
|
||||
|
||||
- `node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/git-service.test.ts` — all tests pass with 0 failures
|
||||
|
||||
## Observability Impact
|
||||
|
||||
- Signals added/changed: None — pure types, constants, and functions
|
||||
- How a future agent inspects this: Read exports from `git-service.ts`, run the test file
|
||||
- Failure state exposed: `inferCommitType` is pure — bad output is immediately visible in test assertions
|
||||
|
||||
## Inputs
|
||||
|
||||
- `src/resources/extensions/gsd/worktree.ts` — `MergeSliceResult` interface shape, `runGit()` pattern
|
||||
- `src/resources/extensions/gsd/gitignore.ts` — `BASELINE_PATTERNS` (first 6 entries = GSD runtime paths)
|
||||
- `src/resources/extensions/gsd/worktree-manager.ts` — `SKIP_PATHS` + `SKIP_EXACT` (same 6 paths)
|
||||
- `src/resources/extensions/gsd/tests/worktree.test.ts` — test infrastructure pattern
|
||||
|
||||
## Expected Output
|
||||
|
||||
- `src/resources/extensions/gsd/git-service.ts` — module with `GitPreferences`, `CommitOptions`, `MergeSliceResult`, `RUNTIME_EXCLUSION_PATHS`, `runGit()`, `inferCommitType()`
|
||||
- `src/resources/extensions/gsd/tests/git-service.test.ts` — test file with passing tests for inferCommitType and RUNTIME_EXCLUSION_PATHS
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
---
|
||||
estimated_steps: 5
|
||||
estimated_files: 2
|
||||
---
|
||||
|
||||
# T02: Implement GitServiceImpl — smart staging, commit, and autoCommit
|
||||
|
||||
**Slice:** S01 — GitService Core Implementation
|
||||
**Milestone:** M001
|
||||
|
||||
## Description
|
||||
|
||||
Build the `GitServiceImpl` class with the core value proposition: smart staging (R002) that excludes GSD runtime paths, and centralized commit/autoCommit methods (R001). The smart staging uses git's `:(exclude)` pathspec syntax to filter runtime paths from `git add`, with a fallback to `git add -A` if the pathspec fails. This is the foundational class that T03 and T04 build upon.
|
||||
|
||||
## Steps
|
||||
|
||||
1. Add `GitServiceImpl` class to `git-service.ts` with constructor `(basePath: string, prefs: GitPreferences = {})`. Store basePath and prefs as readonly properties.
|
||||
2. Implement private `git(args, options?)` instance method that calls the module-level `runGit(this.basePath, args, options)`.
|
||||
3. Implement private `smartStage()` method: build pathspec string `git add -A -- . ':(exclude).gsd/activity/' ':(exclude).gsd/runtime/' ...` for all RUNTIME_EXCLUSION_PATHS entries. Execute via `runGit`. On failure (catch), log warning to stderr (`console.error("GitService: smart staging failed, falling back to git add -A")`), then execute `git add -A` as fallback.
|
||||
4. Implement `commit(opts: CommitOptions)` method: call `smartStage()`, check `git diff --cached --stat` — if empty and not `allowEmpty`, return null. Build commit message, execute `git commit -m ${JSON.stringify(opts.message)}`. Return the commit message string.
|
||||
5. Implement `autoCommit(unitType: string, unitId: string)` method: check `git status --short` — if clean, return null. Call `smartStage()`, check `git diff --cached --stat` — if empty return null (all changes were runtime files). Build message `chore(${unitId}): auto-commit after ${unitType}`, commit, return message.
|
||||
6. Add tests to `git-service.test.ts`: create temp repo, create GitServiceImpl instance.
|
||||
- Test smart staging excludes runtime files: create `.gsd/activity/log.jsonl`, `.gsd/runtime/state.json`, `.gsd/STATE.md`, `.gsd/auto.lock`, `.gsd/metrics.json`, `.gsd/worktrees/wt/file.txt` plus a real file `src/code.ts`. Call `commit()`. Verify only `src/code.ts` is in the commit (check `git show --stat HEAD`). Verify runtime files are still untracked/unstaged.
|
||||
- Test smart staging fallback: mock a scenario where exclusion fails (e.g., use a bad pathspec) and verify fallback to `git add -A` stages everything.
|
||||
- Test autoCommit on clean repo returns null.
|
||||
- Test autoCommit on dirty repo: create a file, call autoCommit, verify commit exists with correct message format.
|
||||
- Test empty-after-staging guard: create only runtime files (`.gsd/activity/x.jsonl`), call autoCommit, verify returns null and no commit is created.
|
||||
|
||||
## Must-Haves
|
||||
|
||||
- [ ] `GitServiceImpl` class with constructor `(basePath, prefs?)`
|
||||
- [ ] Smart staging uses `:(exclude)` pathspecs for all 6 RUNTIME_EXCLUSION_PATHS
|
||||
- [ ] Smart staging falls back to `git add -A` with stderr warning on pathspec failure
|
||||
- [ ] `commit()` returns null when nothing staged after smart staging
|
||||
- [ ] `commit()` uses `JSON.stringify` for shell-escaping commit messages
|
||||
- [ ] `autoCommit()` returns null on clean repo
|
||||
- [ ] `autoCommit()` returns null when only runtime files are dirty (empty-after-staging)
|
||||
- [ ] `autoCommit()` returns commit message string on success
|
||||
- [ ] All tests pass
|
||||
|
||||
## Verification
|
||||
|
||||
- `node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/git-service.test.ts` — all tests pass including new staging/commit tests
|
||||
|
||||
## Observability Impact
|
||||
|
||||
- Signals added/changed: stderr warning when smart staging fallback activates — this is the primary diagnostic signal for staging issues
|
||||
- How a future agent inspects this: Check stderr output during commits for "smart staging failed" messages. Check `git show --stat HEAD` after commits to verify which files were included.
|
||||
- Failure state exposed: Fallback warning on stderr. Null return from commit/autoCommit when no files to stage.
|
||||
|
||||
## Inputs
|
||||
|
||||
- `src/resources/extensions/gsd/git-service.ts` — T01 output: types, constants, runGit, inferCommitType
|
||||
- `src/resources/extensions/gsd/tests/git-service.test.ts` — T01 output: test scaffolding with passing inferCommitType tests
|
||||
|
||||
## Expected Output
|
||||
|
||||
- `src/resources/extensions/gsd/git-service.ts` — updated with `GitServiceImpl` class, `smartStage()`, `commit()`, `autoCommit()`
|
||||
- `src/resources/extensions/gsd/tests/git-service.test.ts` — updated with smart staging and commit tests passing
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
---
|
||||
estimated_steps: 5
|
||||
estimated_files: 2
|
||||
---
|
||||
|
||||
# T03: Implement branch lifecycle — ensureSliceBranch, switchToMain, branch queries
|
||||
|
||||
**Slice:** S01 — GitService Core Implementation
|
||||
**Milestone:** M001
|
||||
|
||||
## Description
|
||||
|
||||
Add branch management methods to `GitServiceImpl` that replicate the logic from `worktree.ts` but route all staging through smart staging. This covers `ensureSliceBranch`, `switchToMain`, and the branch query methods (`getMainBranch`, `getCurrentBranch`, `isOnSliceBranch`, `getActiveSliceBranch`). The key difference from worktree.ts: pre-checkout auto-commits use `smartStage()` instead of `git add -A`, so runtime files are never accidentally committed during branch switches.
|
||||
|
||||
## Steps
|
||||
|
||||
1. Add `getMainBranch()` method to `GitServiceImpl` — reuse exact logic from `worktree.ts` (`detectWorktreeName`, worktree branch check, `symbolic-ref`, main/master fallback, current branch fallback). Import `detectWorktreeName`, `getSliceBranchName`, `SLICE_BRANCH_RE` from worktree.ts (these are pure utility functions that don't change in S02).
|
||||
2. Add `getCurrentBranch()`, `isOnSliceBranch()`, `getActiveSliceBranch()` methods — same logic as worktree.ts standalone functions, using `this.git()`.
|
||||
3. Implement `ensureSliceBranch(milestoneId, sliceId)` method: detect worktree name, compute branch name, check if already on branch (return false), create branch if needed (branch-from-current-not-main logic, slice-to-slice falls back to main), check worktree conflict, pre-checkout auto-commit using `autoCommit("pre-switch", currentBranch)`, checkout, return created boolean.
|
||||
4. Implement `switchToMain()` method: get main branch, check if already on main (return early), auto-commit dirty state via `autoCommit("pre-switch", currentBranch)`, checkout main.
|
||||
5. Add tests:
|
||||
- `ensureSliceBranch` creates branch and checks it out
|
||||
- `ensureSliceBranch` is idempotent (second call returns false)
|
||||
- `ensureSliceBranch` from non-main working branch inherits artifacts
|
||||
- `ensureSliceBranch` from another slice branch falls back to main
|
||||
- `ensureSliceBranch` auto-commits dirty files before checkout using smart staging (verify runtime files NOT in the auto-commit)
|
||||
- `switchToMain` auto-commits dirty files using smart staging
|
||||
- `switchToMain` is idempotent when already on main
|
||||
- `getCurrentBranch`, `isOnSliceBranch`, `getActiveSliceBranch` return correct values on main vs slice branch
|
||||
|
||||
## Must-Haves
|
||||
|
||||
- [ ] `getMainBranch()` handles worktree, origin/HEAD, main/master fallback
|
||||
- [ ] `getCurrentBranch()` returns current branch name
|
||||
- [ ] `isOnSliceBranch()` returns true on slice branch, false on main
|
||||
- [ ] `getActiveSliceBranch()` returns branch name or null
|
||||
- [ ] `ensureSliceBranch()` creates branch from current working branch (not main) when current is not a slice branch
|
||||
- [ ] `ensureSliceBranch()` creates branch from main when current branch IS a slice branch
|
||||
- [ ] `ensureSliceBranch()` auto-commits dirty state via smart staging before checkout
|
||||
- [ ] `switchToMain()` auto-commits dirty state via smart staging before checkout
|
||||
- [ ] All tests pass
|
||||
|
||||
## Verification
|
||||
|
||||
- `node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/git-service.test.ts` — all tests pass including branch lifecycle tests
|
||||
|
||||
## Observability Impact
|
||||
|
||||
- Signals added/changed: None beyond what T02 established (smart staging fallback warning). Pre-checkout auto-commits are visible in `git log`.
|
||||
- How a future agent inspects this: `git log --oneline` shows auto-commit messages before branch switches. `git branch -a` shows created slice branches.
|
||||
- Failure state exposed: Throws descriptive Error if branch is checked out in another worktree. Throws on checkout failure with git command and basePath in message.
|
||||
|
||||
## Inputs
|
||||
|
||||
- `src/resources/extensions/gsd/git-service.ts` — T02 output: `GitServiceImpl` with smartStage, commit, autoCommit
|
||||
- `src/resources/extensions/gsd/worktree.ts` — `detectWorktreeName`, `getSliceBranchName`, `SLICE_BRANCH_RE` imports (pure utilities)
|
||||
- `src/resources/extensions/gsd/tests/git-service.test.ts` — T02 output: existing passing tests
|
||||
|
||||
## Expected Output
|
||||
|
||||
- `src/resources/extensions/gsd/git-service.ts` — updated with `getMainBranch()`, `getCurrentBranch()`, `isOnSliceBranch()`, `getActiveSliceBranch()`, `ensureSliceBranch()`, `switchToMain()`
|
||||
- `src/resources/extensions/gsd/tests/git-service.test.ts` — updated with branch lifecycle tests passing
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
---
|
||||
estimated_steps: 4
|
||||
estimated_files: 2
|
||||
---
|
||||
|
||||
# T04: Implement mergeSliceToMain with inferCommitType and full integration tests
|
||||
|
||||
**Slice:** S01 — GitService Core Implementation
|
||||
**Milestone:** M001
|
||||
|
||||
## Description
|
||||
|
||||
The capstone task: implement `mergeSliceToMain()` which uses `inferCommitType()` to produce correct conventional commit types instead of hardcoding `feat` (fixing R009). Add full lifecycle integration tests that exercise create branch → work on branch → merge → verify commit type. Then run `npm run build` and `npm run test` to verify no regressions across the entire codebase.
|
||||
|
||||
## Steps
|
||||
|
||||
1. Implement `mergeSliceToMain(milestoneId, sliceId, sliceTitle)` method on `GitServiceImpl`: call `switchToMain()`, verify on main branch, verify slice branch exists, check commits ahead (`git rev-list --count`), `git merge --squash`, build commit message using `inferCommitType(sliceTitle)` → `${type}(${milestoneId}/${sliceId}): ${sliceTitle}`, commit with `JSON.stringify(message)`, delete branch with `git branch -D`. Return `MergeSliceResult`.
|
||||
2. Add integration tests for full lifecycle:
|
||||
- Create branch → make changes → commit → switchToMain → mergeSliceToMain with feature title → verify commit message starts with `feat(`
|
||||
- Same lifecycle with "Fix broken config" title → verify commit message starts with `fix(`
|
||||
- Same lifecycle with "Docs update" title → verify commit message starts with `docs(`
|
||||
- Same lifecycle with "Refactor state management" title → verify commit message starts with `refactor(`
|
||||
3. Add error case tests:
|
||||
- `mergeSliceToMain` when not on main → throws
|
||||
- `mergeSliceToMain` when branch doesn't exist → throws
|
||||
- `mergeSliceToMain` when branch has no commits ahead → throws
|
||||
4. Run `npm run build` and `npm run test` to verify no regressions. Fix any issues.
|
||||
|
||||
## Must-Haves
|
||||
|
||||
- [ ] `mergeSliceToMain()` uses `inferCommitType(sliceTitle)` for commit message type
|
||||
- [ ] `mergeSliceToMain()` squash merges and deletes the slice branch
|
||||
- [ ] `mergeSliceToMain()` returns correct `MergeSliceResult`
|
||||
- [ ] Merge commits have correct conventional type based on slice title keywords
|
||||
- [ ] Error thrown when not on main branch
|
||||
- [ ] Error thrown when slice branch doesn't exist
|
||||
- [ ] Error thrown when no commits ahead
|
||||
- [ ] `npm run build` passes
|
||||
- [ ] `npm run test` passes (all existing + new tests)
|
||||
|
||||
## Verification
|
||||
|
||||
- `node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/git-service.test.ts` — all tests pass
|
||||
- `npm run build` — passes
|
||||
- `npm run test` — passes (no regressions)
|
||||
|
||||
## Observability Impact
|
||||
|
||||
- Signals added/changed: None beyond existing. Merge commit messages are the primary observable output — they now carry inferred types.
|
||||
- How a future agent inspects this: `git log --oneline` after merge shows the conventional commit type. Test output verifies all type inference paths.
|
||||
- Failure state exposed: Descriptive errors for each failure mode (not on main, branch missing, no commits ahead) include branch names and current state.
|
||||
|
||||
## Inputs
|
||||
|
||||
- `src/resources/extensions/gsd/git-service.ts` — T03 output: full `GitServiceImpl` with branch lifecycle methods
|
||||
- `src/resources/extensions/gsd/tests/git-service.test.ts` — T03 output: existing passing tests for staging, commit, branch lifecycle
|
||||
|
||||
## Expected Output
|
||||
|
||||
- `src/resources/extensions/gsd/git-service.ts` — complete with `mergeSliceToMain()`, all public methods implemented
|
||||
- `src/resources/extensions/gsd/tests/git-service.test.ts` — complete test suite covering all methods, all passing
|
||||
- `npm run build` — green
|
||||
- `npm run test` — green (all existing + new tests)
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
---
|
||||
id: T04
|
||||
parent: S01
|
||||
milestone: M001
|
||||
provides:
|
||||
- GitServiceImpl.mergeSliceToMain() method with inferCommitType integration
|
||||
key_files:
|
||||
- src/resources/extensions/gsd/git-service.ts
|
||||
- src/resources/extensions/gsd/tests/git-service.test.ts
|
||||
key_decisions:
|
||||
- Added "docs" (plural) to COMMIT_TYPE_RULES keyword list — word-boundary regex prevented "Docs update" from matching "doc", consistent with T01 decision that added "tests" plural
|
||||
patterns_established:
|
||||
- mergeSliceToMain delegates to inferCommitType for commit type instead of hardcoding — conventional commit type is always data-driven from slice title keywords
|
||||
- Squash merge workflow: verify on main → verify branch exists → verify commits ahead → git merge --squash → commit with inferred type → git branch -D
|
||||
observability_surfaces:
|
||||
- Merge commit messages carry inferred conventional types — inspect via `git log --oneline` after merge
|
||||
- Descriptive errors for each failure mode include branch names and current state
|
||||
duration: 8min
|
||||
verification_result: passed
|
||||
completed_at: 2026-03-12
|
||||
blocker_discovered: false
|
||||
---
|
||||
|
||||
# T04: Implement mergeSliceToMain with inferCommitType and full integration tests
|
||||
|
||||
**Added `mergeSliceToMain()` to GitServiceImpl with `inferCommitType` integration and full lifecycle tests — 113 tests passing, build green.**
|
||||
|
||||
## What Happened
|
||||
|
||||
Implemented `mergeSliceToMain(milestoneId, sliceId, sliceTitle)` on `GitServiceImpl` that squash-merges a slice branch into main using `inferCommitType(sliceTitle)` for the conventional commit type. The method validates three preconditions (on main, branch exists, commits ahead) before performing the merge, commit, and branch deletion.
|
||||
|
||||
During testing, discovered that the slice title "Docs update" failed to match the `doc` keyword due to word-boundary regex (`\bdoc\b` doesn't match "docs"). Added "docs" as a plural keyword to `COMMIT_TYPE_RULES`, consistent with the T01 precedent of adding "tests" for the same reason.
|
||||
|
||||
Added 7 new test groups: 4 full lifecycle integration tests (feat, fix, docs, refactor) each exercising create branch → commit work → switch to main → merge → verify commit type, plus 3 error case tests (not on main, branch missing, no commits ahead).
|
||||
|
||||
## Verification
|
||||
|
||||
- `node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/git-service.test.ts` — 113 passed, 0 failed ✓
|
||||
- `npm run build` — passes ✓
|
||||
- `npm run test` — 116 passed, 2 failed (pre-existing AGENTS.md sync failures in app-smoke.test.ts, unrelated to git-service) ✓
|
||||
|
||||
## Diagnostics
|
||||
|
||||
- `git log --oneline` after merge shows conventional commit type in the squash-merge message
|
||||
- Error messages from `mergeSliceToMain` include: current branch name, expected main branch, missing branch name, and commits-ahead count context
|
||||
- Test file can be re-run at any time: `node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/git-service.test.ts`
|
||||
|
||||
## Deviations
|
||||
|
||||
- Added "docs" (plural) to `COMMIT_TYPE_RULES` keyword list — not in original plan but required for correct type inference on titles like "Docs update". Same pattern as T01's "tests" addition.
|
||||
|
||||
## Known Issues
|
||||
|
||||
- 2 pre-existing test failures in `src/tests/app-smoke.test.ts` (tests 49 and 52) related to AGENTS.md syncing — completely unrelated to git-service.
|
||||
|
||||
## Files Created/Modified
|
||||
|
||||
- `src/resources/extensions/gsd/git-service.ts` — Added `mergeSliceToMain()` method and "docs" keyword to COMMIT_TYPE_RULES
|
||||
- `src/resources/extensions/gsd/tests/git-service.test.ts` — Added 22 new assertions across 7 test groups for merge lifecycle and error cases
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
# S02: Wire GitService into codebase
|
||||
|
||||
**Goal:** All git-mutation functions in `worktree.ts` delegate to `GitServiceImpl`. `auto.ts` creates a `GitServiceImpl` instance and routes its git calls through it. `preferences.ts` exposes `git?: GitPreferences` with validation, merge, and documentation.
|
||||
|
||||
**Demo:** `npm run build` passes. All three test suites pass: `worktree.test.ts`, `worktree-integration.test.ts`, `git-service.test.ts`. All 6+ consumers of `worktree.ts` continue to import and call functions without changes.
|
||||
|
||||
## Must-Haves
|
||||
|
||||
- All 10 `worktree.ts` exports preserved with identical signatures
|
||||
- `worktree.ts` git-mutation functions (`getMainBranch`, `getCurrentBranch`, `ensureSliceBranch`, `autoCommitCurrentBranch`, `switchToMain`, `mergeSliceToMain`) delegate to `GitServiceImpl` internally
|
||||
- `MergeSliceResult` re-exported via `export type` from `git-service.ts` (eliminate type duplication per D014)
|
||||
- No circular dependency crash at module-evaluation time between `worktree.ts` and `git-service.ts`
|
||||
- `auto.ts` creates `GitServiceImpl` instance with `basePath` and git preferences after `basePath` is set
|
||||
- `auto.ts` callsites for `autoCommitCurrentBranch`, `ensureSliceBranch`, `switchToMain`, `mergeSliceToMain` route through GitService (via worktree.ts facade)
|
||||
- `GSDPreferences` interface includes `git?: GitPreferences` field
|
||||
- `validatePreferences()` validates git sub-fields
|
||||
- `mergePreferences()` merges git preferences with override semantics
|
||||
- `templates/preferences.md` documents git section
|
||||
- `docs/preferences-reference.md` documents git preferences
|
||||
- Existing tests pass without regressions
|
||||
|
||||
## Proof Level
|
||||
|
||||
- This slice proves: integration
|
||||
- Real runtime required: no (existing test suites with temp git repos exercise the full contract)
|
||||
- Human/UAT required: no
|
||||
|
||||
## Verification
|
||||
|
||||
- `node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/worktree.test.ts` — all pass
|
||||
- `node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/worktree-integration.test.ts` — all pass
|
||||
- `node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/git-service.test.ts` — all pass
|
||||
- `npx tsc --noEmit` — clean (no errors)
|
||||
- `npm run test` — same pass/fail as baseline (116 pass, 2 pre-existing failures)
|
||||
- `grep -n 'import.*from.*worktree' src/resources/extensions/gsd/state.ts src/resources/extensions/gsd/workspace-index.ts src/resources/extensions/gsd/worktree-command.ts` — unchanged, still importing from worktree.ts
|
||||
|
||||
## Observability / Diagnostics
|
||||
|
||||
- Runtime signals: `mergeSliceToMain` now returns commit messages with inferred conventional types (via `inferCommitType`) instead of hardcoded `feat`. `console.error` warning from `smartStage()` fallback signals exclusion failure.
|
||||
- Inspection surfaces: Re-run any of the three test suites to verify delegation is working. `git log --oneline` after merge shows inferred commit types.
|
||||
- Failure visibility: `runGit` errors include full command, basePath, and stderr. Lazy `GitServiceImpl` construction errors surface at first call, not module load.
|
||||
- Redaction constraints: none (no secrets involved)
|
||||
|
||||
## Integration Closure
|
||||
|
||||
- Upstream surfaces consumed: `git-service.ts` → `GitServiceImpl`, `GitPreferences`, `MergeSliceResult`, all public methods (from S01)
|
||||
- New wiring introduced in this slice: `worktree.ts` facade delegates to `GitServiceImpl`; `auto.ts` creates `GitServiceImpl` instance from `basePath` + preferences; `preferences.ts` exposes `git` field in `GSDPreferences`
|
||||
- What remains before the milestone is truly usable end-to-end: S03 (bug fixes), S04 (remove git from prompts), S05 (enhanced features), S06 (cleanup/archive)
|
||||
|
||||
## Tasks
|
||||
|
||||
- [x] **T01: Convert worktree.ts to thin facade delegating to GitServiceImpl** `est:45m`
|
||||
- Why: Core integration task — all 6+ consumers depend on worktree.ts exports being stable while internals switch to GitServiceImpl. Satisfies R005 (facade delegation) and R009 (inferCommitType replaces hardcoded feat).
|
||||
- Files: `src/resources/extensions/gsd/worktree.ts`, `src/resources/extensions/gsd/tests/worktree.test.ts`, `src/resources/extensions/gsd/tests/worktree-integration.test.ts`
|
||||
- Do: Import `GitServiceImpl`, `GitPreferences`, and re-export `MergeSliceResult` via `export type` (per D014) from `git-service.ts`. Add lazy `GitServiceImpl` cache with basePath-change guard. Convert 6 git-mutation functions to delegate. Remove unused private `branchExists` and `runGit`. Keep 4 pure functions and query functions unchanged. Run tests and fix any assertion mismatches.
|
||||
- Verify: All three test suites pass. `npx tsc --noEmit` clean. No consumer import changes needed.
|
||||
- Done when: `worktree.ts` delegates to `GitServiceImpl` for all git-mutation functions, all tests green, build clean.
|
||||
|
||||
- [x] **T02: Wire auto.ts to use GitServiceImpl via worktree.ts facade** `est:30m`
|
||||
- Why: auto.ts is the primary orchestrator — it must have a `GitServiceImpl` instance for future direct usage and verify all callsites work through the T01 facade. Satisfies R006.
|
||||
- Files: `src/resources/extensions/gsd/auto.ts`
|
||||
- Do: Import `GitServiceImpl` and `GitPreferences` from `git-service.ts`. Add module-level `gitService` variable. Initialize after `basePath` is set in `startAutoMode()` using git preferences from `loadEffectiveGSDPreferences()`. Keep bootstrap git calls and idle detection inline per spec. Verify build and tests.
|
||||
- Verify: `npx tsc --noEmit` clean. `npm run test` same baseline. `grep -c 'new GitServiceImpl' src/resources/extensions/gsd/auto.ts` shows 1.
|
||||
- Done when: auto.ts has a `GitServiceImpl` instance created from preferences, build clean, tests pass.
|
||||
|
||||
- [x] **T03: Add git preferences to preferences.ts, template, and docs** `est:30m`
|
||||
- Why: Preferences schema is needed for S05 features (auto_push, merge guards, snapshots) and must exist before those slices. Satisfies R004.
|
||||
- Files: `src/resources/extensions/gsd/preferences.ts`, `src/resources/extensions/gsd/templates/preferences.md`, `src/resources/extensions/gsd/docs/preferences-reference.md`
|
||||
- Do: Add `git?: GitPreferences` to `GSDPreferences` interface (import from `git-service.ts`). Add git validation in `validatePreferences()` for all 6 sub-fields. Add git merge in `mergePreferences()` with override-wins semantics. Add `git:` section to preferences template. Document git preferences in reference doc.
|
||||
- Verify: `npx tsc --noEmit` clean. `npm run test` same baseline. `grep 'git.*GitPreferences' src/resources/extensions/gsd/preferences.ts` confirms field.
|
||||
- Done when: `GSDPreferences.git` field exists with full validation, merge, template, and reference doc.
|
||||
|
||||
## Files Likely Touched
|
||||
|
||||
- `src/resources/extensions/gsd/worktree.ts`
|
||||
- `src/resources/extensions/gsd/auto.ts`
|
||||
- `src/resources/extensions/gsd/preferences.ts`
|
||||
- `src/resources/extensions/gsd/git-service.ts` (minor — only if re-export adjustments needed)
|
||||
- `src/resources/extensions/gsd/templates/preferences.md`
|
||||
- `src/resources/extensions/gsd/docs/preferences-reference.md`
|
||||
- `src/resources/extensions/gsd/tests/worktree.test.ts` (assertion updates if needed)
|
||||
- `src/resources/extensions/gsd/tests/worktree-integration.test.ts` (assertion updates if needed)
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
---
|
||||
estimated_steps: 5
|
||||
estimated_files: 3
|
||||
---
|
||||
|
||||
# T01: Convert worktree.ts to thin facade delegating to GitServiceImpl
|
||||
|
||||
**Slice:** S02 — Wire GitService into codebase
|
||||
**Milestone:** M001
|
||||
|
||||
## Description
|
||||
|
||||
Convert `worktree.ts` from a standalone git-operations module into a thin facade that preserves all 10 exports but delegates git-mutation functions to `GitServiceImpl` from `git-service.ts`. Pure utility functions stay as-is. The `MergeSliceResult` type duplication is eliminated by re-exporting from `git-service.ts` using `export type` per D014.
|
||||
|
||||
The circular dependency between `git-service.ts` (imports pure functions from `worktree.ts`) and `worktree.ts` (imports `GitServiceImpl` from `git-service.ts`) is handled by lazy construction: `GitServiceImpl` is only instantiated inside function bodies at call-time, never at module-evaluation time. The pure functions consumed by `git-service.ts` are available immediately at module evaluation.
|
||||
|
||||
## Steps
|
||||
|
||||
1. **Replace `MergeSliceResult` with type re-export:** Remove the local `MergeSliceResult` interface definition in `worktree.ts` and replace with `export type { MergeSliceResult } from "./git-service.ts"` (per D014 — type-only re-export avoids ESM cycle issues). Verify this doesn't break any consumer.
|
||||
|
||||
2. **Add lazy GitServiceImpl cache:** Import `GitServiceImpl` from `git-service.ts`. Add a `let cachedService: GitServiceImpl | null = null` and a `function getService(basePath: string): GitServiceImpl` that creates or returns the cached instance with `{}` default prefs. Include a basePath-change guard that resets the cache if basePath changes between calls.
|
||||
|
||||
3. **Convert 6 git-mutation functions to delegate:** Replace the bodies of `getMainBranch`, `getCurrentBranch`, `ensureSliceBranch`, `autoCommitCurrentBranch`, `switchToMain`, `mergeSliceToMain` with calls to the corresponding `GitServiceImpl` methods via `getService(basePath)`. Keep all function signatures identical. For `autoCommitCurrentBranch(basePath, unitType, unitId)`, map to `svc.autoCommit(unitType, unitId)`. For `mergeSliceToMain`, the GitServiceImpl version uses `inferCommitType` instead of hardcoded `feat` — this is the intended R009 fix.
|
||||
|
||||
4. **Remove now-unused private code:** Delete the private `branchExists()` function and private `runGit()` function from `worktree.ts` — these are now handled by `GitServiceImpl` and `git-service.ts` respectively. Keep `isOnSliceBranch()` and `getActiveSliceBranch()` as-is (they use `getCurrentBranch` which now delegates). Keep all pure utility functions unchanged: `detectWorktreeName`, `getSliceBranchName`, `SLICE_BRANCH_RE`, `parseSliceBranch`.
|
||||
|
||||
5. **Run all test suites and fix any assertion mismatches:** Run `worktree.test.ts`, `worktree-integration.test.ts`, and `git-service.test.ts`. The worktree tests don't assert on `mergedCommitMessage` format, so the switch from hardcoded `feat(` to `inferCommitType` should be transparent. Verify `npm run build` passes.
|
||||
|
||||
## Must-Haves
|
||||
|
||||
- [ ] All 10 `worktree.ts` exports preserved with identical type signatures
|
||||
- [ ] `MergeSliceResult` re-exported via `export type` from `git-service.ts` (per D014, no local duplicate)
|
||||
- [ ] Lazy `GitServiceImpl` construction (call-time, not module-evaluation)
|
||||
- [ ] BasePath-change guard on cached service
|
||||
- [ ] No circular dependency crash at import time
|
||||
- [ ] `worktree.test.ts` passes — all assertions
|
||||
- [ ] `worktree-integration.test.ts` passes — all assertions
|
||||
- [ ] `git-service.test.ts` passes — all assertions
|
||||
- [ ] `npx tsc --noEmit` clean
|
||||
|
||||
## Verification
|
||||
|
||||
- `node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/worktree.test.ts` — all pass
|
||||
- `node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/worktree-integration.test.ts` — all pass
|
||||
- `node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/git-service.test.ts` — all pass
|
||||
- `npx tsc --noEmit` — no errors
|
||||
- `grep -c 'GitServiceImpl' src/resources/extensions/gsd/worktree.ts` — at least 1 (confirms delegation wiring)
|
||||
- `grep 'export type.*MergeSliceResult' src/resources/extensions/gsd/worktree.ts` — exactly 1 (type re-export per D014)
|
||||
|
||||
## Observability Impact
|
||||
|
||||
- Signals added/changed: `mergeSliceToMain` now returns commits with inferred conventional types (via `inferCommitType`) instead of hardcoded `feat`. This is an intentional R009 fix, not a regression.
|
||||
- How a future agent inspects this: `git log --oneline` after merge shows the inferred commit type. Run worktree test suites to verify delegation.
|
||||
- Failure state exposed: `runGit` errors from `git-service.ts` include command, basePath, and stderr. Lazy init errors surface at first function call, not import time.
|
||||
|
||||
## Inputs
|
||||
|
||||
- `src/resources/extensions/gsd/git-service.ts` — `GitServiceImpl` class, `GitPreferences` interface, `MergeSliceResult` interface (from S01)
|
||||
- `src/resources/extensions/gsd/worktree.ts` — 10 exports, private `branchExists`, private `runGit`, `MergeSliceResult` duplicate
|
||||
- D014 — `export type { MergeSliceResult }` decision
|
||||
|
||||
## Expected Output
|
||||
|
||||
- `src/resources/extensions/gsd/worktree.ts` — thin facade: imports `GitServiceImpl`, lazy cache, 6 functions delegate, 4 pure functions unchanged, `MergeSliceResult` type re-exported
|
||||
- `src/resources/extensions/gsd/tests/worktree.test.ts` — unchanged (no assertion format changes needed)
|
||||
- `src/resources/extensions/gsd/tests/worktree-integration.test.ts` — unchanged (no assertion format changes needed)
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
---
|
||||
id: T01
|
||||
parent: S02
|
||||
milestone: M001
|
||||
provides:
|
||||
- worktree.ts thin facade delegating git-mutation functions to GitServiceImpl
|
||||
- MergeSliceResult type re-export from git-service.ts (D014)
|
||||
- Lazy GitServiceImpl cache with basePath-change guard
|
||||
key_files:
|
||||
- src/resources/extensions/gsd/worktree.ts
|
||||
key_decisions:
|
||||
- Lazy construction via getService() avoids circular dependency crash at module-evaluation time
|
||||
- isOnSliceBranch and getActiveSliceBranch kept as local functions using getCurrentBranch (which delegates) — no need to route through GitServiceImpl since they're pure regex checks on the branch name
|
||||
patterns_established:
|
||||
- Lazy singleton GitServiceImpl cache with basePath-change guard for facade modules
|
||||
observability_surfaces:
|
||||
- mergeSliceToMain now returns commits with inferred conventional types via inferCommitType (R009 fix)
|
||||
- smartStage() console.error fallback warning surfaces exclusion failures
|
||||
- runGit errors include command, basePath, and stderr
|
||||
duration: 10m
|
||||
verification_result: passed
|
||||
completed_at: 2026-03-12
|
||||
blocker_discovered: false
|
||||
---
|
||||
|
||||
# T01: Convert worktree.ts to thin facade delegating to GitServiceImpl
|
||||
|
||||
**Converted worktree.ts from standalone git module to thin facade — all 13 exports preserved, 6 git-mutation functions delegate to GitServiceImpl via lazy cache, MergeSliceResult re-exported per D014.**
|
||||
|
||||
## What Happened
|
||||
|
||||
1. Removed local `MergeSliceResult` interface, replaced with `export type { MergeSliceResult } from "./git-service.ts"` (D014 type-only re-export).
|
||||
2. Added lazy `GitServiceImpl` cache: `cachedService`/`cachedBasePath` module-level variables with `getService(basePath)` factory that resets on basePath change. Construction happens at call-time only, never at module evaluation — avoids circular dependency crash.
|
||||
3. Converted 6 git-mutation functions to delegate: `getMainBranch`, `getCurrentBranch`, `ensureSliceBranch`, `autoCommitCurrentBranch` (maps to `svc.autoCommit`), `switchToMain`, `mergeSliceToMain`. All function signatures identical.
|
||||
4. Removed private `runGit()` and `branchExists()` — now handled by `GitServiceImpl` internals.
|
||||
5. Kept pure utility functions unchanged: `detectWorktreeName`, `getSliceBranchName`, `SLICE_BRANCH_RE`, `parseSliceBranch`.
|
||||
6. Kept `isOnSliceBranch` and `getActiveSliceBranch` as local functions that use `getCurrentBranch` (which delegates).
|
||||
|
||||
The circular dependency (git-service.ts imports pure functions from worktree.ts, worktree.ts imports GitServiceImpl from git-service.ts) works because GitServiceImpl is only instantiated inside function bodies at call-time, and the pure functions consumed by git-service.ts are available immediately at module evaluation.
|
||||
|
||||
## Verification
|
||||
|
||||
- `worktree.test.ts`: 56 passed, 0 failed ✓
|
||||
- `worktree-integration.test.ts`: 40 passed, 0 failed ✓
|
||||
- `git-service.test.ts`: 113 passed, 0 failed ✓
|
||||
- `npx tsc --noEmit`: clean, no errors ✓
|
||||
- `grep -c 'GitServiceImpl' worktree.ts` → 9 (confirms delegation wiring) ✓
|
||||
- `grep 'export type.*MergeSliceResult' worktree.ts` → exactly 1 match ✓
|
||||
- Consumer imports in state.ts, workspace-index.ts, worktree-command.ts unchanged ✓
|
||||
|
||||
### Slice-level verification (partial — T01 of 3):
|
||||
- ✅ worktree.test.ts passes
|
||||
- ✅ worktree-integration.test.ts passes
|
||||
- ✅ git-service.test.ts passes
|
||||
- ✅ npx tsc --noEmit clean
|
||||
- ⏳ npm run test (full suite) — deferred to final task
|
||||
- ✅ Consumer imports unchanged
|
||||
|
||||
## Diagnostics
|
||||
|
||||
- Run any of the three test suites to verify delegation is working
|
||||
- `git log --oneline` after a merge shows inferred commit types (feat/fix/refactor/etc. instead of always feat)
|
||||
- Lazy init errors surface at first function call, not import time — look for "git ... failed in ..." error messages
|
||||
|
||||
## Deviations
|
||||
|
||||
None. Plan executed as written.
|
||||
|
||||
## Known Issues
|
||||
|
||||
None.
|
||||
|
||||
## Files Created/Modified
|
||||
|
||||
- `src/resources/extensions/gsd/worktree.ts` — converted to thin facade: imports GitServiceImpl, lazy cache, 6 functions delegate, 4 pure functions unchanged, MergeSliceResult type re-exported
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
---
|
||||
estimated_steps: 4
|
||||
estimated_files: 1
|
||||
---
|
||||
|
||||
# T02: Wire auto.ts to use GitServiceImpl via worktree.ts facade
|
||||
|
||||
**Slice:** S02 — Wire GitService into codebase
|
||||
**Milestone:** M001
|
||||
|
||||
## Description
|
||||
|
||||
After T01 converts `worktree.ts` to a facade, all auto.ts calls already route through `GitServiceImpl` transparently. This task makes that explicit by creating a `GitServiceImpl` instance in auto.ts (for future direct usage by S05) and verifying all callsites work correctly through the facade. The instance is initialized after `basePath` is set, using git preferences from the preferences system.
|
||||
|
||||
Bootstrap git calls (`git rev-parse --git-dir`, `git init`, `git add -A .gsd .gitignore && git commit`) and idle detection (`git status --porcelain`) remain inline per milestone success criteria.
|
||||
|
||||
## Steps
|
||||
|
||||
1. **Add GitServiceImpl import and module-level variable:** Import `GitServiceImpl` and `GitPreferences` from `./git-service.ts`. Add `let gitService: GitServiceImpl | null = null;` at module level near the existing `let basePath = ""` declaration.
|
||||
|
||||
2. **Initialize GitServiceImpl after basePath is set:** In `startAutoMode()`, after `basePath = base` is set and after the git init/bootstrap block (line ~375), create the instance: `gitService = new GitServiceImpl(basePath, loadEffectiveGSDPreferences()?.preferences?.git ?? {})`. This must happen after the git repo is confirmed to exist. Note: `loadEffectiveGSDPreferences` is already imported in auto.ts.
|
||||
|
||||
3. **Verify all callsites compile and route correctly:** The 8 imports from `worktree.ts` remain unchanged — `autoCommitCurrentBranch`, `ensureSliceBranch`, `getCurrentBranch`, `getMainBranch`, `getSliceBranchName`, `parseSliceBranch`, `switchToMain`, `mergeSliceToMain`. These now delegate through the T01 facade. No call signature changes needed. Remove `getSliceBranchName` from imports if unused (line 65 — imported but not called in auto.ts).
|
||||
|
||||
4. **Verify build and tests pass:** Run `npx tsc --noEmit` and `npm run test` to confirm no regressions. The auto.ts changes are additive — existing behavior is preserved.
|
||||
|
||||
## Must-Haves
|
||||
|
||||
- [ ] `GitServiceImpl` imported from `git-service.ts`
|
||||
- [ ] Module-level `gitService` variable initialized after `basePath` is set
|
||||
- [ ] Instance created with git preferences from `loadEffectiveGSDPreferences()`
|
||||
- [ ] Bootstrap git calls remain inline (lines 360-375)
|
||||
- [ ] Idle detection `git status --porcelain` remains inline (line 2545)
|
||||
- [ ] `npx tsc --noEmit` clean
|
||||
- [ ] `npm run test` same baseline (116 pass, 2 pre-existing failures)
|
||||
|
||||
## Verification
|
||||
|
||||
- `npx tsc --noEmit` — no errors
|
||||
- `npm run test` — same pass/fail as baseline
|
||||
- `grep -c 'GitServiceImpl' src/resources/extensions/gsd/auto.ts` — at least 1
|
||||
- `grep -c 'new GitServiceImpl' src/resources/extensions/gsd/auto.ts` — exactly 1
|
||||
|
||||
## Observability Impact
|
||||
|
||||
- Signals added/changed: None — this task adds the instance but doesn't change runtime behavior (facade handles delegation)
|
||||
- How a future agent inspects this: `grep GitServiceImpl src/resources/extensions/gsd/auto.ts` to confirm the instance exists
|
||||
- Failure state exposed: If preferences loading fails, `?? {}` ensures default empty prefs — no crash
|
||||
|
||||
## Inputs
|
||||
|
||||
- `src/resources/extensions/gsd/auto.ts` — orchestrator with 8 worktree.ts imports and git callsites
|
||||
- `src/resources/extensions/gsd/worktree.ts` — T01 facade (all function calls now route to GitServiceImpl)
|
||||
- `src/resources/extensions/gsd/git-service.ts` — `GitServiceImpl` constructor takes `(basePath, prefs?)`
|
||||
- T01 completion — facade must be in place before this task verifies routing
|
||||
|
||||
## Expected Output
|
||||
|
||||
- `src/resources/extensions/gsd/auto.ts` — added `GitServiceImpl` import, module-level `gitService` variable, initialization in `startAutoMode()` after basePath is set
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
---
|
||||
id: T02
|
||||
parent: S02
|
||||
milestone: M001
|
||||
provides:
|
||||
- GitServiceImpl instance in auto.ts initialized from basePath + git preferences
|
||||
- Removed unused getSliceBranchName import from auto.ts
|
||||
key_files:
|
||||
- src/resources/extensions/gsd/auto.ts
|
||||
key_decisions:
|
||||
- Initialize gitService after bootstrap block (git init + .gsd mkdir) but before crash-lock check — ensures git repo exists
|
||||
- Use `loadEffectiveGSDPreferences()?.preferences?.git ?? {}` for safe fallback to empty prefs
|
||||
patterns_established:
|
||||
- Module-level `gitService` variable with post-init construction in startAutoMode()
|
||||
observability_surfaces:
|
||||
- If preferences loading fails, `?? {}` ensures default empty prefs — no crash. gitService null before startAutoMode() runs.
|
||||
duration: 8m
|
||||
verification_result: passed
|
||||
completed_at: 2026-03-12
|
||||
blocker_discovered: false
|
||||
---
|
||||
|
||||
# T02: Wire auto.ts to use GitServiceImpl via worktree.ts facade
|
||||
|
||||
**Added GitServiceImpl instance in auto.ts, initialized after basePath is set with git preferences from the preferences system. Removed unused `getSliceBranchName` import.**
|
||||
|
||||
## What Happened
|
||||
|
||||
Three changes to `auto.ts`:
|
||||
1. Added imports for `GitServiceImpl` and `GitPreferences` from `git-service.ts`
|
||||
2. Added module-level `let gitService: GitServiceImpl | null = null` next to the existing `basePath` declaration
|
||||
3. Added initialization line after the bootstrap block in `startAutoMode()`: `gitService = new GitServiceImpl(basePath, loadEffectiveGSDPreferences()?.preferences?.git ?? {})`
|
||||
4. Removed `getSliceBranchName` from the worktree.ts import list — it was imported but never used in auto.ts
|
||||
|
||||
All 8 remaining worktree.ts imports continue to work through the T01 facade unchanged. Bootstrap git calls and idle detection remain inline per spec.
|
||||
|
||||
## Verification
|
||||
|
||||
- `npx tsc --noEmit` — clean, no errors
|
||||
- `npm run test` — 116 pass, 2 pre-existing failures (matches baseline)
|
||||
- `grep -c 'GitServiceImpl' auto.ts` → 4 (import, type import, variable declaration, instantiation)
|
||||
- `grep -c 'new GitServiceImpl' auto.ts` → 1 (exactly one instantiation)
|
||||
- All three test suites pass: worktree.test.ts, worktree-integration.test.ts, git-service.test.ts
|
||||
- Consumer imports unchanged: state.ts, workspace-index.ts, worktree-command.ts still import from worktree.ts
|
||||
|
||||
## Diagnostics
|
||||
|
||||
- `grep GitServiceImpl src/resources/extensions/gsd/auto.ts` confirms instance exists
|
||||
- `gitService` is null before `startAutoMode()` runs — any premature access will surface as TypeError
|
||||
- Preferences fallback `?? {}` means no crash even if preferences file is missing or malformed
|
||||
|
||||
## Deviations
|
||||
|
||||
Removed unused `getSliceBranchName` import as noted in the plan (step 3). This is a cleanup, not a behavioral change.
|
||||
|
||||
## Known Issues
|
||||
|
||||
None.
|
||||
|
||||
## Files Created/Modified
|
||||
|
||||
- `src/resources/extensions/gsd/auto.ts` — Added GitServiceImpl import, module-level variable, initialization in startAutoMode(), removed unused getSliceBranchName import
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
---
|
||||
estimated_steps: 5
|
||||
estimated_files: 3
|
||||
---
|
||||
|
||||
# T03: Add git preferences to preferences.ts, template, and docs
|
||||
|
||||
**Slice:** S02 — Wire GitService into codebase
|
||||
**Milestone:** M001
|
||||
|
||||
## Description
|
||||
|
||||
Add `git?: GitPreferences` to the `GSDPreferences` interface with full validation, merge semantics, documentation in the preferences template, and a reference doc entry. This enables all preference-gated git features in S05 (auto_push, merge guards, snapshots) via the existing preferences system.
|
||||
|
||||
The `GitPreferences` type already exists in `git-service.ts` — this task imports it and wires it into the preferences infrastructure.
|
||||
|
||||
## Steps
|
||||
|
||||
1. **Add `git` field to `GSDPreferences` interface:** Import `GitPreferences` from `./git-service.ts`. Add `git?: GitPreferences` to the `GSDPreferences` interface alongside the existing fields.
|
||||
|
||||
2. **Add git validation to `validatePreferences()`:** After the existing validation blocks, add a `git` section that validates each sub-field:
|
||||
- `auto_push`: must be boolean if present
|
||||
- `push_branches`: must be boolean if present
|
||||
- `remote`: must be non-empty string if present
|
||||
- `snapshots`: must be boolean if present
|
||||
- `pre_merge_check`: must be boolean or the string `"auto"` if present
|
||||
- `commit_type`: must be one of `feat`, `fix`, `refactor`, `docs`, `test`, `chore`, `perf`, `ci`, `build`, `style` if present
|
||||
Collect errors for invalid values. Copy valid values to `validated.git`.
|
||||
|
||||
3. **Add git merge to `mergePreferences()`:** Add `git: { ...(base.git ?? {}), ...(override.git ?? {}) }` to the merge return object. Override-wins for each field, same as `models` and `auto_supervisor`.
|
||||
|
||||
4. **Update preferences template:** Add a `git:` section to `src/resources/extensions/gsd/templates/preferences.md` showing all available fields with sensible defaults (empty/unset). Place it after the existing sections in the frontmatter block.
|
||||
|
||||
5. **Update preferences reference doc:** Add a "Git Preferences" section to `src/resources/extensions/gsd/docs/preferences-reference.md` documenting each field, its type, default value, and behavior. Include a YAML example.
|
||||
|
||||
## Must-Haves
|
||||
|
||||
- [ ] `GSDPreferences` interface includes `git?: GitPreferences`
|
||||
- [ ] `GitPreferences` imported from `git-service.ts`
|
||||
- [ ] `validatePreferences()` validates all 6 git sub-fields with type checking
|
||||
- [ ] Invalid git values produce error messages (not silent drops)
|
||||
- [ ] `mergePreferences()` merges git with override-wins semantics
|
||||
- [ ] `templates/preferences.md` has `git:` section with all fields
|
||||
- [ ] `docs/preferences-reference.md` documents git preferences
|
||||
- [ ] `npx tsc --noEmit` clean
|
||||
- [ ] `npm run test` same baseline
|
||||
|
||||
## Verification
|
||||
|
||||
- `npx tsc --noEmit` — no errors
|
||||
- `npm run test` — same pass/fail as baseline
|
||||
- `grep 'git.*GitPreferences' src/resources/extensions/gsd/preferences.ts` — confirms field exists
|
||||
- `grep -c 'auto_push\|push_branches\|pre_merge_check\|snapshots\|commit_type' src/resources/extensions/gsd/preferences.ts` — at least 5 (validation of each field)
|
||||
- `grep 'git:' src/resources/extensions/gsd/templates/preferences.md` — confirms template section
|
||||
- `grep -i 'git preferences\|git:' src/resources/extensions/gsd/docs/preferences-reference.md` — confirms docs section
|
||||
|
||||
## Observability Impact
|
||||
|
||||
- Signals added/changed: None — this adds schema infrastructure only. Preferences are parsed at load time; invalid values produce error strings in the `validatePreferences` return.
|
||||
- How a future agent inspects this: Call `loadEffectiveGSDPreferences()` and check `.preferences.git` for parsed values. Validation errors are in the return tuple.
|
||||
- Failure state exposed: Invalid git preference values are reported as strings in the `errors` array from `validatePreferences()` — callers already log these.
|
||||
|
||||
## Inputs
|
||||
|
||||
- `src/resources/extensions/gsd/preferences.ts` — `GSDPreferences` interface, `validatePreferences()`, `mergePreferences()`
|
||||
- `src/resources/extensions/gsd/git-service.ts` — `GitPreferences` interface
|
||||
- `src/resources/extensions/gsd/templates/preferences.md` — existing template
|
||||
- `src/resources/extensions/gsd/docs/preferences-reference.md` — existing reference doc
|
||||
|
||||
## Expected Output
|
||||
|
||||
- `src/resources/extensions/gsd/preferences.ts` — `git?: GitPreferences` in interface, validation logic, merge logic
|
||||
- `src/resources/extensions/gsd/templates/preferences.md` — `git:` section added to frontmatter
|
||||
- `src/resources/extensions/gsd/docs/preferences-reference.md` — git preferences documented with example
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
# S03: Bug fixes and doc corrections
|
||||
|
||||
**Goal:** Worktree create commits before fork, worktree merge uses deterministic helper by default (LLM fallback on conflict only), and README/GSD-WORKFLOW docs match actual branch deletion and commit behavior.
|
||||
**Demo:** `npm run build` passes. `handleCreate()` calls `autoCommitCurrentBranch` before `createWorktree`. `handleMerge()` attempts `mergeWorktreeToMain()` first and only dispatches to LLM on conflict. README and GSD-WORKFLOW no longer claim branches are preserved or that checkpoint commits exist.
|
||||
|
||||
## Must-Haves
|
||||
|
||||
- `autoCommitCurrentBranch()` executes before `createWorktree()` in handleCreate (R007)
|
||||
- `handleMerge()` attempts deterministic `mergeWorktreeToMain()` first; falls back to LLM dispatch only on merge conflict (R008)
|
||||
- Deterministic merge path builds a conventional commit message using `inferCommitType()` (R008)
|
||||
- On non-conflict errors in deterministic path, surface error to user rather than silently falling back to LLM (R008)
|
||||
- README.md: branch example shows `(deleted after merge)` not `(preserved)`, removes "Per-task history preserved on branches" claim (R010)
|
||||
- GSD-WORKFLOW.md: "Branch kept" → "Branch deleted after merge", checkpoint commit examples replaced with actual `chore(...)` auto-commit pattern, checkpoint row removed from commit conventions table, rollback table updated to remove checkpoint reference (R010)
|
||||
|
||||
## Proof Level
|
||||
|
||||
- This slice proves: integration
|
||||
- Real runtime required: no (build + grep verification sufficient)
|
||||
- Human/UAT required: no
|
||||
|
||||
## Verification
|
||||
|
||||
- `npm run build` — must pass (code changes compile)
|
||||
- `npm run test` — existing tests still pass (4 pre-existing failures unrelated to this slice are acceptable)
|
||||
- `grep -n 'autoCommitCurrentBranch' src/resources/extensions/gsd/worktree-command.ts` — autoCommit call appears before createWorktree call (lower line number)
|
||||
- `grep -n 'mergeWorktreeToMain' src/resources/extensions/gsd/worktree-command.ts` — deterministic merge function is called in handleMerge
|
||||
- `grep -c 'preserved' README.md` — returns 0 (no "preserved" claims about branches)
|
||||
- `grep -c 'checkpoint' src/resources/GSD-WORKFLOW.md` — returns 0 (no checkpoint references)
|
||||
- `grep -c 'Branch kept' src/resources/GSD-WORKFLOW.md` — returns 0
|
||||
|
||||
## Observability / Diagnostics
|
||||
|
||||
- Runtime signals: None — these are bug fixes to CLI command handlers and doc corrections. No new runtime signals needed.
|
||||
- Inspection surfaces: `git log --oneline` on main after a merge will show correct commit types (not always `feat`). The deterministic merge path produces a notification via `ctx.ui.notify`.
|
||||
- Failure visibility: Deterministic merge failure surfaces error message to user via `ctx.ui.notify`. Conflict detection triggers LLM fallback with a notification explaining why.
|
||||
- Redaction constraints: None
|
||||
|
||||
## Integration Closure
|
||||
|
||||
- Upstream surfaces consumed: `worktree-manager.ts` → `mergeWorktreeToMain()`, `worktree.ts` → `autoCommitCurrentBranch()`, `git-service.ts` → `inferCommitType()`
|
||||
- New wiring introduced in this slice: `handleMerge()` now calls `mergeWorktreeToMain()` directly (deterministic path) before LLM fallback; `handleCreate()` ordering corrected
|
||||
- What remains before the milestone is truly usable end-to-end: S04 (remove git commands from prompts), S05 (enhanced features — merge guards, snapshots, auto-push, rich commits), S06 (cleanup and archive)
|
||||
|
||||
## Tasks
|
||||
|
||||
- [x] **T01: Fix worktree create ordering and add deterministic merge dispatch** `est:25m`
|
||||
- Why: R007 — new worktrees fork from uncommitted state (create before commit). R008 — merges always go through LLM even when deterministic helper exists and would succeed.
|
||||
- Files: `src/resources/extensions/gsd/worktree-command.ts`
|
||||
- Do: (1) In `handleCreate()`, move `autoCommitCurrentBranch()` call before `createWorktree()` call. (2) In `handleMerge()`, after confirmation and CWD switch to basePath, attempt `mergeWorktreeToMain(basePath, name, commitMessage)` first. Build commit message using `inferCommitType(name)` and worktree name. On success, notify user and return. On merge conflict (catch error, check for conflict indicators), fall back to existing LLM dispatch. On other errors, surface to user. (3) Import `mergeWorktreeToMain` from worktree-manager.ts and `inferCommitType` from git-service.ts.
|
||||
- Verify: `npm run build` passes. `grep -n` confirms ordering. `grep` confirms `mergeWorktreeToMain` called in handleMerge.
|
||||
- Done when: Build passes, autoCommit precedes createWorktree, deterministic merge attempted before LLM dispatch.
|
||||
|
||||
- [x] **T02: Fix README and GSD-WORKFLOW doc claims** `est:15m`
|
||||
- Why: R010 — docs claim branches are "preserved" and checkpoint commits exist, but actual code deletes branches after merge and produces `chore(...)` auto-commits instead of checkpoints.
|
||||
- Files: `README.md`, `src/resources/GSD-WORKFLOW.md`
|
||||
- Do: (1) README.md: change `gsd/M001/S01 (preserved)` to `gsd/M001/S01 (deleted after merge)`, remove "Per-task history preserved on branches" claim, update the main branch example to show inferred commit types not always `feat`. (2) GSD-WORKFLOW.md: change "Branch kept" to "Branch deleted after merge — squash commit is the permanent record", replace checkpoint commit examples with actual `chore(unitId): auto-commit after unitType` pattern, remove checkpoint row from commit conventions table, update rollback table to remove checkpoint reference, update squash merge commit example to show inferred types.
|
||||
- Verify: `grep -c 'preserved' README.md` returns 0. `grep -c 'checkpoint' src/resources/GSD-WORKFLOW.md` returns 0. `grep -c 'Branch kept' src/resources/GSD-WORKFLOW.md` returns 0.
|
||||
- Done when: All doc claims match actual code behavior. No "preserved", "checkpoint", or "Branch kept" in the corrected files.
|
||||
|
||||
## Files Likely Touched
|
||||
|
||||
- `src/resources/extensions/gsd/worktree-command.ts`
|
||||
- `README.md`
|
||||
- `src/resources/GSD-WORKFLOW.md`
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
---
|
||||
estimated_steps: 5
|
||||
estimated_files: 1
|
||||
---
|
||||
|
||||
# T01: Fix worktree create ordering and add deterministic merge dispatch
|
||||
|
||||
**Slice:** S03 — Bug fixes and doc corrections
|
||||
**Milestone:** M001
|
||||
|
||||
## Description
|
||||
|
||||
Fix two bugs in `worktree-command.ts`: (1) `handleCreate()` calls `createWorktree()` before `autoCommitCurrentBranch()`, meaning new worktrees fork from uncommitted HEAD — swap these so dirty state is committed first. (2) `handleMerge()` always dispatches to the LLM for merge even though `mergeWorktreeToMain()` exists as a deterministic helper — make the deterministic path the default, falling back to LLM only when a merge conflict occurs.
|
||||
|
||||
## Steps
|
||||
|
||||
1. **Add imports**: Import `mergeWorktreeToMain` from `./worktree-manager.js` and `inferCommitType` from `./git-service.js` at the top of `worktree-command.ts`.
|
||||
2. **Fix handleCreate ordering (R007)**: Move the `autoCommitCurrentBranch(basePath, "worktree-switch", name)` call to occur BEFORE `createWorktree(mainBase, name)`. The `autoCommitCurrentBranch` uses `basePath` (current workspace), while `createWorktree` uses `mainBase` — no dependency conflict.
|
||||
3. **Add deterministic merge path in handleMerge (R008)**: After the confirmation prompt and CWD switch (where `process.chdir(basePath)` already happens), insert a try/catch block that: (a) builds a conventional commit message using `inferCommitType(name)` and the worktree name as scope/description, (b) calls `mergeWorktreeToMain(basePath, name, commitMessage)`, (c) on success, notifies the user and returns early (skipping LLM dispatch).
|
||||
4. **Add conflict fallback**: In the catch block for the deterministic merge, check if the error message indicates a merge conflict (contains "conflict" or "CONFLICT"). If so, run `git merge --abort` to clean up, then fall through to the existing LLM dispatch path with a notification that deterministic merge failed due to conflicts. If the error is NOT a conflict, surface it to the user and return (don't fall back to LLM for non-conflict errors).
|
||||
5. **Verify**: Run `npm run build` to confirm compilation. Run `grep -n` to confirm ordering fix and presence of deterministic merge call.
|
||||
|
||||
## Must-Haves
|
||||
|
||||
- [ ] `autoCommitCurrentBranch()` call precedes `createWorktree()` call in `handleCreate()`
|
||||
- [ ] `mergeWorktreeToMain()` attempted as first merge strategy in `handleMerge()`
|
||||
- [ ] Commit message for deterministic merge uses `inferCommitType(name)` for the type
|
||||
- [ ] Merge conflicts detected and handled: `git merge --abort` + LLM fallback
|
||||
- [ ] Non-conflict errors surfaced to user, not silently swallowed
|
||||
- [ ] `npm run build` passes
|
||||
|
||||
## Verification
|
||||
|
||||
- `npm run build` completes without errors
|
||||
- `grep -n 'autoCommitCurrentBranch\|createWorktree' src/resources/extensions/gsd/worktree-command.ts` — autoCommit line number < createWorktree line number in handleCreate
|
||||
- `grep -n 'mergeWorktreeToMain' src/resources/extensions/gsd/worktree-command.ts` — appears in handleMerge function
|
||||
- `npm run test` — existing tests still pass (4 pre-existing failures acceptable)
|
||||
|
||||
## Observability Impact
|
||||
|
||||
- Signals added/changed: `ctx.ui.notify` messages for deterministic merge success, conflict fallback, and non-conflict errors
|
||||
- How a future agent inspects this: Read the notification messages in the TUI after a merge operation
|
||||
- Failure state exposed: Conflict detection triggers a visible notification before LLM fallback; non-conflict errors show the error message directly
|
||||
|
||||
## Inputs
|
||||
|
||||
- `src/resources/extensions/gsd/worktree-command.ts` — current handleCreate (lines 348-390) and handleMerge (lines 572-710) implementations
|
||||
- `src/resources/extensions/gsd/worktree-manager.ts` — `mergeWorktreeToMain(basePath, name, commitMessage)` at line 379
|
||||
- `src/resources/extensions/gsd/git-service.ts` — `inferCommitType(sliceTitle)` at line 354
|
||||
- S03-RESEARCH.md — confirmed bug locations and existing function signatures
|
||||
|
||||
## Expected Output
|
||||
|
||||
- `src/resources/extensions/gsd/worktree-command.ts` — handleCreate has autoCommit before createWorktree; handleMerge attempts deterministic `mergeWorktreeToMain` before LLM dispatch with proper conflict handling
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
---
|
||||
id: T01
|
||||
parent: S03
|
||||
milestone: M001
|
||||
provides:
|
||||
- handleCreate commits dirty state before forking worktree
|
||||
- handleMerge uses deterministic squash-merge before LLM fallback
|
||||
key_files:
|
||||
- src/resources/extensions/gsd/worktree-command.ts
|
||||
key_decisions:
|
||||
- Deterministic merge builds commit message as `{inferCommitType(name)}({name}): merge worktree {name}` — uses worktree name both as scope and as input to type inference
|
||||
- Non-conflict merge errors surface directly to user and do not fall back to LLM (only conflicts trigger fallback)
|
||||
patterns_established:
|
||||
- Deterministic-first with LLM fallback: try the fast/predictable path, catch specific failure class (conflicts), fall back to LLM only for that class
|
||||
observability_surfaces:
|
||||
- ctx.ui.notify messages distinguish deterministic merge success, conflict-triggered LLM fallback, and non-conflict errors
|
||||
duration: 12m
|
||||
verification_result: passed
|
||||
completed_at: 2026-03-12
|
||||
blocker_discovered: false
|
||||
---
|
||||
|
||||
# T01: Fix worktree create ordering and add deterministic merge dispatch
|
||||
|
||||
**Fixed handleCreate to commit before forking and handleMerge to use deterministic squash-merge with conflict-aware LLM fallback.**
|
||||
|
||||
## What Happened
|
||||
|
||||
1. Added imports: `mergeWorktreeToMain` from worktree-manager.js, `inferCommitType` from git-service.js, `execSync` from node:child_process.
|
||||
2. In `handleCreate()`, moved `autoCommitCurrentBranch()` call (now line 357) before `createWorktree()` call (now line 361). This ensures dirty working state is committed before the new worktree forks from HEAD.
|
||||
3. In `handleMerge()`, after the confirmation prompt and CWD switch to basePath, inserted a deterministic merge attempt using `mergeWorktreeToMain(basePath, name, commitMessage)`. The commit message is built as `{inferCommitType(name)}({name}): merge worktree {name}`.
|
||||
4. On success, the user is notified with file/line stats and the merge returns early (skipping LLM dispatch entirely).
|
||||
5. On conflict (error message matches `/conflict/i`), `git merge --abort` cleans up the failed merge, a warning notification explains the fallback, and execution continues to the existing LLM dispatch path.
|
||||
6. On non-conflict errors, the error is surfaced directly to the user and the function returns without LLM fallback.
|
||||
|
||||
## Verification
|
||||
|
||||
- `npm run build` — passes clean
|
||||
- `npm run test` — 114 pass, 4 fail (pre-existing, unrelated)
|
||||
- `grep -n` confirms `autoCommitCurrentBranch` at line 357 precedes `createWorktree` at line 361 in handleCreate
|
||||
- `grep -n` confirms `mergeWorktreeToMain` called at line 676 inside handleMerge
|
||||
- All 6 must-haves from the task plan verified
|
||||
|
||||
### Slice-level checks (T01 scope):
|
||||
- ✅ `npm run build` passes
|
||||
- ✅ `npm run test` — 114/118 pass (4 pre-existing failures)
|
||||
- ✅ autoCommitCurrentBranch line < createWorktree line in handleCreate
|
||||
- ✅ mergeWorktreeToMain appears in handleMerge
|
||||
- ⏳ `grep -c 'preserved' README.md` — not yet addressed (T02 scope)
|
||||
- ⏳ `grep -c 'checkpoint' src/resources/GSD-WORKFLOW.md` — not yet addressed (T02 scope)
|
||||
- ⏳ `grep -c 'Branch kept' src/resources/GSD-WORKFLOW.md` — not yet addressed (T02 scope)
|
||||
|
||||
## Diagnostics
|
||||
|
||||
After a `/worktree merge` operation, inspect the TUI notification messages:
|
||||
- **Deterministic success**: shows "✓ Merged {name} → {mainBranch} (deterministic squash)" with commit message
|
||||
- **Conflict fallback**: shows "Deterministic merge hit conflicts — falling back to LLM-guided merge."
|
||||
- **Non-conflict error**: shows "Failed to merge: {error message}"
|
||||
|
||||
## Deviations
|
||||
|
||||
None.
|
||||
|
||||
## Known Issues
|
||||
|
||||
None.
|
||||
|
||||
## Files Created/Modified
|
||||
|
||||
- `src/resources/extensions/gsd/worktree-command.ts` — Reordered handleCreate (autoCommit before createWorktree), added deterministic merge path in handleMerge with conflict-aware LLM fallback, added imports for mergeWorktreeToMain, inferCommitType, and execSync
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
---
|
||||
estimated_steps: 4
|
||||
estimated_files: 2
|
||||
---
|
||||
|
||||
# T02: Fix README and GSD-WORKFLOW doc claims
|
||||
|
||||
**Slice:** S03 — Bug fixes and doc corrections
|
||||
**Milestone:** M001
|
||||
|
||||
## Description
|
||||
|
||||
README.md and GSD-WORKFLOW.md contain incorrect claims about git branch lifecycle and commit patterns. README says branches are "preserved" — they're deleted after squash merge. GSD-WORKFLOW says "Branch kept", shows `checkpoint(...)` commit examples, and references checkpoint-based rollback — none of these exist in the actual code. Fix all doc claims to match actual behavior: branches deleted, auto-commits use `chore(...)` format, commit types are inferred (not always `feat`).
|
||||
|
||||
## Steps
|
||||
|
||||
1. **Fix README.md git strategy section**: (a) Change `gsd/M001/S01 (preserved)` to `gsd/M001/S01 (deleted after merge)`. (b) Replace "Per-task history preserved on branches" with accurate text about squash commits being the permanent record. (c) Update the main branch commit example to show varied commit types (not all `feat`) — e.g., `fix(M001/S03)`, `docs(M001/S04)` to demonstrate inference.
|
||||
2. **Fix GSD-WORKFLOW.md branch lifecycle**: (a) Change step 4 "Branch kept — not deleted, available for per-task history" to "Branch deleted — squash commit on main is the permanent record". (b) Update the branch commit example to remove `checkpoint(...)` entries and replace with `chore(...)` auto-commit entries matching actual `autoCommit()` output.
|
||||
3. **Fix GSD-WORKFLOW.md commit conventions table**: (a) Remove the `checkpoint(S01/T02): pre-task` row. (b) Add a row for auto-commits: `chore(S01/T02): auto-commit after task`. (c) Change the squash merge row from hardcoded `feat` to show that type is inferred: `type(M001/S01): <slice title>` with a note that type is inferred from title.
|
||||
4. **Fix GSD-WORKFLOW.md rollback table**: Replace "Bad task → `git reset --hard` to checkpoint on the branch" with accurate rollback guidance that doesn't reference checkpoints — e.g., "Bad task → `git reset --hard HEAD~1` to previous commit on the branch".
|
||||
|
||||
## Must-Haves
|
||||
|
||||
- [ ] README.md: no occurrences of "preserved" in the git strategy section
|
||||
- [ ] README.md: main branch example shows varied inferred commit types
|
||||
- [ ] GSD-WORKFLOW.md: "Branch deleted" replaces "Branch kept"
|
||||
- [ ] GSD-WORKFLOW.md: zero occurrences of "checkpoint" in any context
|
||||
- [ ] GSD-WORKFLOW.md: commit conventions table uses `chore(...)` for auto-commits, inferred type for squash merge
|
||||
- [ ] GSD-WORKFLOW.md: rollback table has no checkpoint reference
|
||||
|
||||
## Verification
|
||||
|
||||
- `grep -c 'preserved' README.md` returns 0 (in git strategy context — verify no false positives from other sections)
|
||||
- `grep -c 'checkpoint' src/resources/GSD-WORKFLOW.md` returns 0
|
||||
- `grep -c 'Branch kept' src/resources/GSD-WORKFLOW.md` returns 0
|
||||
- `grep 'Branch deleted' src/resources/GSD-WORKFLOW.md` returns a match
|
||||
- `grep 'chore(' src/resources/GSD-WORKFLOW.md` returns at least one match
|
||||
- `npm run build` still passes (docs are bundled resources)
|
||||
|
||||
## Observability Impact
|
||||
|
||||
- Signals added/changed: None — pure documentation changes
|
||||
- How a future agent inspects this: Read the doc files; grep for removed terms
|
||||
- Failure state exposed: None
|
||||
|
||||
## Inputs
|
||||
|
||||
- `README.md` — current git strategy section at lines 253-270
|
||||
- `src/resources/GSD-WORKFLOW.md` — current git strategy section at lines 548-610
|
||||
- `git-service.ts` — actual behavior: `mergeSliceToMain` deletes branch, `autoCommit` produces `chore(...)` messages, `inferCommitType` determines squash merge type
|
||||
- S03-RESEARCH.md — confirmed wrong claims and their line numbers
|
||||
|
||||
## Expected Output
|
||||
|
||||
- `README.md` — git strategy section reflects actual behavior (branches deleted, types inferred)
|
||||
- `src/resources/GSD-WORKFLOW.md` — branch lifecycle, commit conventions, and rollback sections all match actual code behavior with zero checkpoint references
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
---
|
||||
id: T02
|
||||
parent: S03
|
||||
milestone: M001
|
||||
provides:
|
||||
- README.md git strategy section reflects actual behavior (branches deleted, commit types inferred)
|
||||
- GSD-WORKFLOW.md branch lifecycle, commit conventions, and rollback sections match actual code
|
||||
key_files:
|
||||
- README.md
|
||||
- src/resources/GSD-WORKFLOW.md
|
||||
key_decisions:
|
||||
- README "preserved" on line 125 refers to conversation state, not git branches — left untouched (not a false positive)
|
||||
patterns_established: []
|
||||
observability_surfaces:
|
||||
- none
|
||||
duration: 5m
|
||||
verification_result: passed
|
||||
completed_at: 2026-03-12
|
||||
blocker_discovered: false
|
||||
---
|
||||
|
||||
# T02: Fix README and GSD-WORKFLOW doc claims
|
||||
|
||||
**Corrected all incorrect git strategy claims in README.md and GSD-WORKFLOW.md to match actual code behavior: branches deleted after merge, auto-commits use `chore(...)` format, commit types are inferred, no checkpoint commits exist.**
|
||||
|
||||
## What Happened
|
||||
|
||||
Four targeted doc corrections across two files:
|
||||
|
||||
1. **README.md git strategy section**: Changed branch example from `(preserved)` to `(deleted after merge)`. Replaced "Per-task history preserved on branches" with accurate squash-commit-as-permanent-record language. Updated main branch example to show varied inferred commit types (`fix`, `docs`) instead of all `feat`.
|
||||
|
||||
2. **GSD-WORKFLOW.md branch lifecycle**: Changed step 4 from "Branch kept" to "Branch deleted". Replaced `checkpoint(...)` commit examples with `chore(...)` auto-commit entries matching actual `autoCommit()` output.
|
||||
|
||||
3. **GSD-WORKFLOW.md commit conventions table**: Removed `checkpoint(S01/T02): pre-task` row. Added `chore(S01/T02): auto-commit after task` row. Changed squash merge type from hardcoded `feat` to `type(M001/S01)` with note that type is inferred from title.
|
||||
|
||||
4. **GSD-WORKFLOW.md rollback table**: Replaced checkpoint-based `git reset --hard` guidance with `git reset --hard HEAD~1` to previous commit.
|
||||
|
||||
## Verification
|
||||
|
||||
All must-haves confirmed:
|
||||
|
||||
- `grep -n 'preserved' README.md` — only hit is line 125 (conversation context, not git strategy) ✅
|
||||
- README main branch example shows `fix(M001/S03)`, `docs(M001/S04)` — varied inferred types ✅
|
||||
- `grep -c 'checkpoint' src/resources/GSD-WORKFLOW.md` — returns 0 ✅
|
||||
- `grep -c 'Branch kept' src/resources/GSD-WORKFLOW.md` — returns 0 ✅
|
||||
- `grep 'Branch deleted' src/resources/GSD-WORKFLOW.md` — match found ✅
|
||||
- `grep 'chore(' src/resources/GSD-WORKFLOW.md` — 4 matches (3 branch examples + 1 conventions table) ✅
|
||||
- `npm run build` — passes ✅
|
||||
|
||||
Slice-level verification (final task):
|
||||
- `npm run build` — passes ✅
|
||||
- autoCommit (line 357) before createWorktree (line 361) ✅
|
||||
- `mergeWorktreeToMain` called in handleMerge ✅
|
||||
- No "preserved" in git strategy context ✅
|
||||
- Zero "checkpoint" in GSD-WORKFLOW.md ✅
|
||||
- Zero "Branch kept" in GSD-WORKFLOW.md ✅
|
||||
|
||||
## Diagnostics
|
||||
|
||||
None — pure documentation changes. Verify by reading the doc files or grepping for removed terms.
|
||||
|
||||
## Deviations
|
||||
|
||||
None.
|
||||
|
||||
## Known Issues
|
||||
|
||||
- Slice plan's `grep -c 'preserved' README.md` returns 1 not 0 because the word appears in an unrelated context (line 125: "conversation is preserved"). The task plan explicitly notes this as acceptable (not a false positive). The git strategy section itself has zero occurrences.
|
||||
|
||||
## Files Created/Modified
|
||||
|
||||
- `README.md` — Fixed git strategy section: branches deleted after merge, varied commit types
|
||||
- `src/resources/GSD-WORKFLOW.md` — Fixed branch lifecycle, commit conventions, and rollback sections
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
# S04: Remove git commands from prompts
|
||||
|
||||
**Goal:** No raw git commands in LLM-facing prompts (except worktree-merge.md for conflict resolution).
|
||||
**Demo:** `grep -rn 'git add\|git commit\|git update-index\|git hash-object' src/resources/extensions/gsd/prompts/ --include="*.md" | grep -v worktree-merge.md` returns zero results.
|
||||
|
||||
## Must-Haves
|
||||
|
||||
- execute-task.md step 16 replaced — no `git add`, `git commit`, `git update-index`, or `git hash-object`
|
||||
- complete-slice.md step 10 replaced — no `git add` or `git commit`; preserves "do not squash-merge manually" context
|
||||
- replan-slice.md step 6 replaced — no `git add` or `git commit`
|
||||
- complete-milestone.md step 9 replaced — no `git add` or `git commit`
|
||||
- worktree-merge.md untouched
|
||||
- Step numbering remains sequential in all modified files
|
||||
- `npm run build` passes
|
||||
- `npm run test` passes
|
||||
|
||||
## Proof Level
|
||||
|
||||
- This slice proves: contract
|
||||
- Real runtime required: no
|
||||
- Human/UAT required: no
|
||||
|
||||
## Verification
|
||||
|
||||
- `grep -rn 'git add\|git commit\|git update-index\|git hash-object' src/resources/extensions/gsd/prompts/ --include="*.md" | grep -v worktree-merge.md` returns zero lines
|
||||
- `npm run build` passes
|
||||
- `npm run test` passes
|
||||
- worktree-merge.md unchanged (diff shows no modifications)
|
||||
|
||||
## Observability / Diagnostics
|
||||
|
||||
Not applicable — this slice modifies static prompt templates with no runtime behavior.
|
||||
|
||||
- Runtime signals: none
|
||||
- Inspection surfaces: grep across prompt files
|
||||
- Failure visibility: none
|
||||
- Redaction constraints: none
|
||||
|
||||
## Integration Closure
|
||||
|
||||
- Upstream surfaces consumed: GitService auto-commit mechanism wired in S02 (auto.ts lines 498–504) — makes manual commit instructions in prompts redundant
|
||||
- New wiring introduced in this slice: none
|
||||
- What remains before the milestone is truly usable end-to-end: S05 (merge guards, snapshots, auto-push, rich commits), S06 (cleanup and archive)
|
||||
|
||||
## Tasks
|
||||
|
||||
- [x] **T01: Replace raw git commands in all four prompt files** `est:15m`
|
||||
- Why: R011 — LLMs should not run git commands; the GitService auto-commit (wired in S02) makes these instructions redundant and harmful
|
||||
- Files: `src/resources/extensions/gsd/prompts/execute-task.md`, `src/resources/extensions/gsd/prompts/complete-slice.md`, `src/resources/extensions/gsd/prompts/replan-slice.md`, `src/resources/extensions/gsd/prompts/complete-milestone.md`
|
||||
- Do: Replace the git command text in each step with a declarative "system auto-commits" message. Keep step numbers intact. Preserve the "do not squash-merge manually" context in complete-slice.md. Do NOT touch worktree-merge.md.
|
||||
- Verify: grep returns zero hits; build passes; test passes; worktree-merge.md has no diff
|
||||
- Done when: all four verification commands pass
|
||||
|
||||
## Files Likely Touched
|
||||
|
||||
- `src/resources/extensions/gsd/prompts/execute-task.md`
|
||||
- `src/resources/extensions/gsd/prompts/complete-slice.md`
|
||||
- `src/resources/extensions/gsd/prompts/replan-slice.md`
|
||||
- `src/resources/extensions/gsd/prompts/complete-milestone.md`
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
---
|
||||
id: T01
|
||||
parent: S04
|
||||
milestone: M001
|
||||
provides:
|
||||
- Raw git commands removed from all four LLM-facing prompt files
|
||||
key_files:
|
||||
- src/resources/extensions/gsd/prompts/execute-task.md
|
||||
- src/resources/extensions/gsd/prompts/complete-slice.md
|
||||
- src/resources/extensions/gsd/prompts/replan-slice.md
|
||||
- src/resources/extensions/gsd/prompts/complete-milestone.md
|
||||
- src/resources/extensions/gsd/tests/replan-slice.test.ts
|
||||
key_decisions:
|
||||
- Removed unused {{blockerTaskId}} template variable from replan-slice.md (was only used in the git commit message); kept the variable in auto.ts since it's still used in inlined context headings
|
||||
patterns_established:
|
||||
- Prompt steps that previously contained git commands now use declarative "system auto-commits" messages
|
||||
observability_surfaces:
|
||||
- none
|
||||
duration: 8 minutes
|
||||
verification_result: passed
|
||||
completed_at: 2026-03-12
|
||||
blocker_discovered: false
|
||||
---
|
||||
|
||||
# T01: Replace raw git commands in all four prompt files
|
||||
|
||||
**Replaced git add/commit/update-index/hash-object instructions in execute-task.md, complete-slice.md, replan-slice.md, and complete-milestone.md with declarative auto-commit messages.**
|
||||
|
||||
## What Happened
|
||||
|
||||
Replaced the raw git command text in step 16 (execute-task.md), step 10 (complete-slice.md), step 6 (replan-slice.md), and step 9 (complete-milestone.md) with short declarative messages telling the LLM not to commit manually. The execute-task.md replacement also removed the `git update-index`/`git hash-object` workaround text. The complete-slice.md replacement preserves the squash-merge context.
|
||||
|
||||
Discovered that the replan-slice test asserted `{{blockerTaskId}}` rendered in the prompt — that variable was only present in the removed git commit message line. Removed the stale `blockerTaskId` assertion and the corresponding template var from that test case.
|
||||
|
||||
## Verification
|
||||
|
||||
- `grep -rn 'git add\|git commit\|git update-index\|git hash-object' src/resources/extensions/gsd/prompts/ --include="*.md" | grep -v worktree-merge.md` → zero results ✓
|
||||
- `git diff src/resources/extensions/gsd/prompts/worktree-merge.md` → no changes ✓
|
||||
- `npm run build` → passes ✓
|
||||
- `npm run test` → 114 pass / 4 fail (same 4 pre-existing failures as before changes; replan-slice test now passes) ✓
|
||||
|
||||
## Diagnostics
|
||||
|
||||
None — this task modifies static prompt templates with no runtime behavior.
|
||||
|
||||
## Deviations
|
||||
|
||||
Updated `src/resources/extensions/gsd/tests/replan-slice.test.ts` to remove the `blockerTaskId` assertion and template var from the prompt-variable-substitution test. This was not in the original plan but was necessary because removing `{{blockerTaskId}}` from the template broke the test.
|
||||
|
||||
## Known Issues
|
||||
|
||||
None.
|
||||
|
||||
## Files Created/Modified
|
||||
|
||||
- `src/resources/extensions/gsd/prompts/execute-task.md` — Step 16 replaced with auto-commit message
|
||||
- `src/resources/extensions/gsd/prompts/complete-slice.md` — Step 10 replaced with auto-commit + merge message
|
||||
- `src/resources/extensions/gsd/prompts/replan-slice.md` — Step 6 replaced with auto-commit message
|
||||
- `src/resources/extensions/gsd/prompts/complete-milestone.md` — Step 9 replaced with auto-commit message
|
||||
- `src/resources/extensions/gsd/tests/replan-slice.test.ts` — Removed stale blockerTaskId assertion
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
# S05: Enhanced features — merge guards, snapshots, auto-push, rich commits
|
||||
|
||||
**Goal:** GitServiceImpl gains five enhanced features: pre-merge verification, snapshot refs, auto-push, rich squash commit messages, and remote fetch before branching. All preference-gated features work end-to-end through the worktree.ts facade.
|
||||
|
||||
**Demo:** Unit tests pass proving: (1) `git for-each-ref refs/gsd/snapshots/` shows snapshot ref created before merge, (2) pre-merge check aborts merge on test failure, (3) `git log --oneline -1` on main after merge shows task list in commit body, (4) `git push` called when auto_push enabled, (5) `git fetch` called before new branch creation when remote exists. `npm run build` and `npm run test` pass.
|
||||
|
||||
## Must-Haves
|
||||
|
||||
- `createSnapshot(label)` creates `refs/gsd/snapshots/<label>/<timestamp>` ref, gated on `prefs.snapshots !== false` (default: on)
|
||||
- `runPreMergeCheck()` auto-detects test runner from `package.json`/`Cargo.toml`/`Makefile`/`pyproject.toml`, runs it, returns pass/fail. Gated on `prefs.pre_merge_check` (`"auto"` default, `false` to skip, custom string command)
|
||||
- `mergeSliceToMain` calls snapshot → pre-merge check → squash merge → rich commit → delete branch → auto-push (in that order)
|
||||
- Rich commit message includes task list from `git log --oneline main..branch` and branch name for forensics
|
||||
- Multi-line commit messages use `git commit -F -` with stdin pipe instead of `JSON.stringify()` with `-m`
|
||||
- Auto-push after merge when `prefs.auto_push === true`, best-effort (warn on failure, don't throw)
|
||||
- Remote fetch (`git fetch --prune`) before new branch creation in `ensureSliceBranch` when remote exists
|
||||
- `worktree.ts` `getService()` loads real preferences via `loadEffectiveGSDPreferences()` instead of `{}`
|
||||
- `preferences.ts` validation updated to accept custom string commands for `pre_merge_check` (not just `boolean | "auto"`)
|
||||
- All features have unit tests in `git-service.test.ts`
|
||||
|
||||
## Proof Level
|
||||
|
||||
- This slice proves: contract
|
||||
- Real runtime required: no (temp git repos in unit tests)
|
||||
- Human/UAT required: no — all features are deterministic git operations verifiable by unit tests
|
||||
|
||||
## Verification
|
||||
|
||||
- `npm run build` passes
|
||||
- `npm run test` passes — specifically the new test sections:
|
||||
- `createSnapshot` — ref exists at correct path, gated by prefs
|
||||
- `runPreMergeCheck` — detects runner, passes/fails correctly, custom command works
|
||||
- `mergeSliceToMain` with enhanced flow — snapshot created, rich commit body present
|
||||
- Auto-push — push executed when enabled, skipped when disabled, warn on failure
|
||||
- Remote fetch — fetch called before branching when remote exists
|
||||
- Facade prefs — `getService()` loads real preferences
|
||||
- `grep -r 'new GitServiceImpl.*{}' src/resources/extensions/gsd/worktree.ts` returns 0 matches (facade fix verified)
|
||||
|
||||
## Observability / Diagnostics
|
||||
|
||||
- Runtime signals: `console.error` warnings for push failures, fetch failures, and pre-merge check detection misses. These are operational warnings, not structured logs — appropriate for a CLI tool.
|
||||
- Inspection surfaces: `git for-each-ref refs/gsd/snapshots/` to list all snapshot refs. `git log -1 --format=%B` to inspect rich commit body.
|
||||
- Failure visibility: Pre-merge check failures include the command that was run and its stderr output. Push failures include the remote and error message. Fetch failures are warnings only.
|
||||
- Redaction constraints: None — no secrets involved in git operations.
|
||||
|
||||
## Integration Closure
|
||||
|
||||
- Upstream surfaces consumed: `git-service.ts` (GitServiceImpl, all existing methods), `worktree.ts` (facade getService), `preferences.ts` (loadEffectiveGSDPreferences, GitPreferences validation)
|
||||
- New wiring introduced in this slice: facade prefs fix (worktree.ts `getService()` → `loadEffectiveGSDPreferences()`), five new methods/behaviors in GitServiceImpl
|
||||
- What remains before the milestone is truly usable end-to-end: S06 (cleanup/archive of design input files, final doc consistency check)
|
||||
|
||||
## Tasks
|
||||
|
||||
- [x] **T01: Write failing tests for all S05 features** `est:45m`
|
||||
- Why: Establishes the red-green verification contract for all five features before implementation. Tests define exact expected behavior.
|
||||
- Files: `src/resources/extensions/gsd/tests/git-service.test.ts`
|
||||
- Do: Add test sections for createSnapshot, runPreMergeCheck, rich commit messages, auto-push, remote fetch, and facade prefs loading. Tests use temp git repos following existing `initTempRepo()` pattern. All new tests should fail initially (methods don't exist yet).
|
||||
- Verify: `npm run build` passes (tests are valid TS). `npm run test` reports new test failures (expected — methods not implemented).
|
||||
- Done when: All new test assertions exist and the test file compiles. Tests cover: snapshot ref creation + prefs gating, pre-merge check detection + execution + abort, rich commit body format, auto-push execution + failure handling, remote fetch before branching, facade loads real prefs.
|
||||
|
||||
- [x] **T02: Implement snapshot refs, rich commits, remote fetch, and commit message fix** `est:45m`
|
||||
- Why: Delivers R013 (snapshots), R015 (rich commits), R016 (remote fetch), and fixes the multi-line commit message fragility. These are pure git operations with no external process execution.
|
||||
- Files: `src/resources/extensions/gsd/git-service.ts`
|
||||
- Do: (1) Add `createSnapshot(label)` method using `git update-ref`. (2) Add rich commit message builder that collects `git log --oneline` from branch. (3) Switch `mergeSliceToMain` commit from `git commit -m` with `JSON.stringify` to `git commit -F -` with stdin pipe for multi-line support. (4) Add remote fetch in `ensureSliceBranch` before branch creation. (5) Wire snapshot + rich commits into `mergeSliceToMain` flow.
|
||||
- Verify: `npm run build` passes. `npm run test` — snapshot, rich commit, and remote fetch tests pass.
|
||||
- Done when: `createSnapshot` creates verifiable refs. `mergeSliceToMain` produces rich commit messages with task list and branch name. `ensureSliceBranch` fetches when remote exists. Related T01 tests go green.
|
||||
|
||||
- [x] **T03: Implement merge guards, auto-push, facade prefs fix, and validation update** `est:45m`
|
||||
- Why: Delivers R012 (merge guards), R014 (auto-push), fixes the facade prefs wiring gap (R004 support), and corrects preference validation for custom pre_merge_check commands. These are the preference-gated features that need the facade fix to work at runtime.
|
||||
- Files: `src/resources/extensions/gsd/git-service.ts`, `src/resources/extensions/gsd/worktree.ts`, `src/resources/extensions/gsd/preferences.ts`
|
||||
- Do: (1) Add `runPreMergeCheck()` method that auto-detects test runner from project files. (2) Wire pre-merge check into `mergeSliceToMain` before squash merge. (3) Add auto-push logic after successful merge in `mergeSliceToMain`. (4) Fix `worktree.ts` `getService()` to call `loadEffectiveGSDPreferences()` instead of `{}`. (5) Update `preferences.ts` validation to accept any non-empty string for `pre_merge_check` (not just `boolean | "auto"`).
|
||||
- Verify: `npm run build` passes. `npm run test` — all S05 tests pass (0 failures). `grep -r 'new GitServiceImpl.*{}' src/resources/extensions/gsd/worktree.ts` returns 0 matches.
|
||||
- Done when: Pre-merge check auto-detects and runs. Auto-push pushes on success, warns on failure. Facade passes real prefs. All T01 tests go green. `npm run build` and `npm run test` pass clean.
|
||||
|
||||
## Files Likely Touched
|
||||
|
||||
- `src/resources/extensions/gsd/git-service.ts`
|
||||
- `src/resources/extensions/gsd/worktree.ts`
|
||||
- `src/resources/extensions/gsd/preferences.ts`
|
||||
- `src/resources/extensions/gsd/tests/git-service.test.ts`
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
---
|
||||
estimated_steps: 6
|
||||
estimated_files: 1
|
||||
---
|
||||
|
||||
# T01: Write failing tests for all S05 features
|
||||
|
||||
**Slice:** S05 — Enhanced features — merge guards, snapshots, auto-push, rich commits
|
||||
**Milestone:** M001
|
||||
|
||||
## Description
|
||||
|
||||
Add comprehensive test sections to `git-service.test.ts` for all five S05 features: snapshot refs, pre-merge check (merge guards), rich squash commit messages, auto-push, and remote fetch before branching. Also add a test for the facade prefs loading fix.
|
||||
|
||||
Tests follow the existing pattern: `initTempRepo()` creates disposable git repos, `GitServiceImpl` is instantiated with controlled prefs, assertions verify git state. All tests should fail initially because the methods don't exist yet — this establishes the red-green contract.
|
||||
|
||||
## Steps
|
||||
|
||||
1. Add `createSnapshot` test section: create a GitServiceImpl with `{ snapshots: true }`, call `createSnapshot("gsd/M001/S01")` on a repo with commits, verify ref exists via `git for-each-ref refs/gsd/snapshots/`. Add a second test with `{ snapshots: false }` confirming no ref is created.
|
||||
|
||||
2. Add `runPreMergeCheck` test section: create a temp repo with a `package.json` containing `"test": "node -e 'process.exit(0)'"`, verify `runPreMergeCheck()` returns success. Create another with `"test": "node -e 'process.exit(1)'"`, verify it returns failure. Test with `pre_merge_check: false` (skipped). Test with custom command string `pre_merge_check: "node -e 'process.exit(0)'"`.
|
||||
|
||||
3. Add rich commit message test section: create a repo with a slice branch that has 2-3 commits, merge via `mergeSliceToMain`, inspect `git log -1 --format=%B` on main to verify the body includes a task list with commit subjects and a `Branch:` line.
|
||||
|
||||
4. Add auto-push test section: create a temp repo with a local remote (bare repo as remote), set `{ auto_push: true }`, merge a slice, verify the remote's main has the merge commit. Add a second test with `{ auto_push: false }` (or omitted) confirming no push occurs.
|
||||
|
||||
5. Add remote fetch test section: create a temp repo with a local bare remote, add a commit to the remote, call `ensureSliceBranch`, verify no crash (fetch runs). Test without a remote configured — verify no error.
|
||||
|
||||
6. Add facade prefs test section: verify that `getService()` in worktree.ts would load prefs (this may need to test via `mergeSliceToMain` from worktree.ts facade — if prefs.snapshots is set in a preferences file, snapshots should be created). Alternatively, test by importing `getService` behavior indirectly — the simplest approach is testing that the worktree facade's merge creates a snapshot when prefs file has `snapshots: true`.
|
||||
|
||||
## Must-Haves
|
||||
|
||||
- [ ] Snapshot ref creation test (prefs enabled + disabled)
|
||||
- [ ] Pre-merge check detection and execution test (pass, fail, disabled, custom command)
|
||||
- [ ] Rich commit message format test (task list + branch line in body)
|
||||
- [ ] Auto-push test (enabled → pushes, disabled → no push)
|
||||
- [ ] Remote fetch before branching test (with and without remote)
|
||||
- [ ] All tests compile (`npm run build` passes)
|
||||
|
||||
## Verification
|
||||
|
||||
- `npm run build` passes (test file is valid TypeScript)
|
||||
- `npm run test` runs the test file — new tests fail with expected errors (methods don't exist or behavior doesn't match yet)
|
||||
- No existing tests break
|
||||
|
||||
## Observability Impact
|
||||
|
||||
- Signals added/changed: None — these are test-time assertions
|
||||
- How a future agent inspects this: `npm run test` output shows pass/fail counts and specific failure messages
|
||||
- Failure state exposed: Test assertion messages identify exactly which feature and scenario failed
|
||||
|
||||
## Inputs
|
||||
|
||||
- `src/resources/extensions/gsd/tests/git-service.test.ts` — existing test file with helpers (`initTempRepo`, `assert`, `assertEq`, `createFile`, `run`)
|
||||
- `src/resources/extensions/gsd/git-service.ts` — current GitServiceImpl API (methods to be added in T02/T03)
|
||||
|
||||
## Expected Output
|
||||
|
||||
- `src/resources/extensions/gsd/tests/git-service.test.ts` — extended with 6 new test sections covering all S05 features. Tests compile but fail (red phase of red-green cycle).
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
---
|
||||
estimated_steps: 5
|
||||
estimated_files: 1
|
||||
---
|
||||
|
||||
# T02: Implement snapshot refs, rich commits, remote fetch, and commit message fix
|
||||
|
||||
**Slice:** S05 — Enhanced features — merge guards, snapshots, auto-push, rich commits
|
||||
**Milestone:** M001
|
||||
|
||||
## Description
|
||||
|
||||
Add three features to `GitServiceImpl` in `git-service.ts`: hidden snapshot refs before merges (R013), rich squash commit messages with task lists (R015), and remote fetch before branching (R016). Also fix the multi-line commit message fragility by switching from `git commit -m` with `JSON.stringify()` to `git commit -F -` with stdin pipe.
|
||||
|
||||
These are "pure git" features — no external process execution (test runners, push to remotes). They modify `mergeSliceToMain()` and `ensureSliceBranch()`.
|
||||
|
||||
## Steps
|
||||
|
||||
1. **Add `createSnapshot(label)` method** to `GitServiceImpl`. Uses `git update-ref refs/gsd/snapshots/<label>/<YYYYMMDD-HHmmss> HEAD`. Gated on `this.prefs.snapshots !== false` (default: on — undefined counts as enabled). Label should have `/` replaced or preserved as-is since git ref paths handle `/` natively.
|
||||
|
||||
2. **Switch commit helper to stdin pipe** — Replace the `git commit -m JSON.stringify(message)` pattern with a helper that writes to `git commit -F -` via stdin. This is necessary for multi-line rich commit messages. Use `execSync` with `input` option on `stdio: ['pipe', 'pipe', 'pipe']`. Apply this to all commit calls in the class (the `commit()` method and `mergeSliceToMain()`).
|
||||
|
||||
3. **Add rich commit message builder** — In `mergeSliceToMain`, after squash merge and before commit, collect `git log --oneline <main>..<branch>` to get branch commit subjects. Build message body:
|
||||
```
|
||||
type(scope): title
|
||||
|
||||
Tasks:
|
||||
- commit subject 1
|
||||
- commit subject 2
|
||||
|
||||
Branch: gsd/M001/S01
|
||||
```
|
||||
Handle edge case where branch has many commits (cap at ~20 entries with "..." truncation).
|
||||
|
||||
4. **Add remote fetch in `ensureSliceBranch`** — Before creating a new branch (inside the `!this.branchExists(branch)` block), check if a remote exists via `git remote`. If so, run `git fetch --prune <remote>` (using `this.prefs.remote ?? "origin"`). Use `allowFailure: true` and `console.error` on failure (fetch is best-effort). After fetch, check if local main is behind remote via `git rev-list --count HEAD..@{upstream}` with `allowFailure` (upstream may not be set).
|
||||
|
||||
5. **Wire snapshot + rich commit into `mergeSliceToMain`** flow. New order: save branch ref before switching → switch to main → snapshot (before squash) → `git merge --squash` → build rich commit message → `git commit -F -` → delete branch. The snapshot captures the slice branch HEAD before it's deleted.
|
||||
|
||||
## Must-Haves
|
||||
|
||||
- [ ] `createSnapshot(label)` creates refs visible via `git for-each-ref refs/gsd/snapshots/`
|
||||
- [ ] Snapshot creation gated on `prefs.snapshots !== false` (default on)
|
||||
- [ ] Rich commit body includes task list from branch commits and `Branch:` line
|
||||
- [ ] Multi-line commit messages work correctly (no quoting/escaping issues)
|
||||
- [ ] Remote fetch runs before new branch creation when remote exists
|
||||
- [ ] Remote fetch is best-effort (warns, doesn't throw)
|
||||
- [ ] All existing tests still pass (no regressions from commit message change)
|
||||
|
||||
## Verification
|
||||
|
||||
- `npm run build` passes
|
||||
- `npm run test` — snapshot, rich commit, remote fetch, and commit message tests from T01 pass
|
||||
- Existing merge tests still pass (commit message format change is backward-compatible because body is additive)
|
||||
|
||||
## Observability Impact
|
||||
|
||||
- Signals added/changed: `console.error` warnings for fetch failures and behind-remote detection
|
||||
- How a future agent inspects this: `git for-each-ref refs/gsd/snapshots/` lists snapshot refs. `git log -1 --format=%B` shows rich commit body.
|
||||
- Failure state exposed: Fetch failure warning includes remote name and error detail
|
||||
|
||||
## Inputs
|
||||
|
||||
- `src/resources/extensions/gsd/git-service.ts` — current GitServiceImpl with `mergeSliceToMain`, `ensureSliceBranch`, `commit` methods
|
||||
- `src/resources/extensions/gsd/tests/git-service.test.ts` — T01 tests defining expected behavior
|
||||
|
||||
## Expected Output
|
||||
|
||||
- `src/resources/extensions/gsd/git-service.ts` — GitServiceImpl gains `createSnapshot(label)` method, rich commit builder, stdin-pipe commit helper, remote fetch logic. `mergeSliceToMain` uses new flow. `ensureSliceBranch` fetches before branching.
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
---
|
||||
estimated_steps: 5
|
||||
estimated_files: 3
|
||||
---
|
||||
|
||||
# T03: Implement merge guards, auto-push, facade prefs fix, and validation update
|
||||
|
||||
**Slice:** S05 — Enhanced features — merge guards, snapshots, auto-push, rich commits
|
||||
**Milestone:** M001
|
||||
|
||||
## Description
|
||||
|
||||
Add pre-merge verification (R012) and auto-push (R014) to `GitServiceImpl`. Fix the critical facade preferences wiring gap in `worktree.ts` so all preference-gated features (snapshots, pre_merge_check, auto_push) actually work when called through the facade. Update `preferences.ts` validation to accept custom string commands for `pre_merge_check`.
|
||||
|
||||
These are the "external operations" features — they execute project test commands and push to remotes. The facade fix is the keystone: without it, all preference-gated features from T02 and T03 silently do nothing when called through the worktree.ts facade that auto.ts uses.
|
||||
|
||||
## Steps
|
||||
|
||||
1. **Add `runPreMergeCheck()` method** to `GitServiceImpl`. Auto-detection logic:
|
||||
- Check `this.prefs.pre_merge_check`: if `false`, return immediately (skip). If it's a non-empty string (and not `"auto"`), use that as the custom command.
|
||||
- If `"auto"` or `undefined` (default behavior): detect from project files in `this.basePath`:
|
||||
- `package.json` with `scripts.test` → `npm test`
|
||||
- `package.json` with `scripts.build` → `npm run build` (only if no test script)
|
||||
- `Cargo.toml` → `cargo test`
|
||||
- `Makefile` with `test:` target → `make test`
|
||||
- `pyproject.toml` → `python -m pytest`
|
||||
- Execute the detected/configured command via `execSync` with `cwd: this.basePath`, `timeout: 300_000` (5 min), `stdio: ['ignore', 'pipe', 'pipe']`.
|
||||
- Return `{ passed: boolean, command: string, output?: string }`. On failure, include stderr in output.
|
||||
- If no runner detected in auto mode, return `{ passed: true, command: 'none', output: 'no test runner detected' }` (don't block merge for repos without tests).
|
||||
|
||||
2. **Wire pre-merge check into `mergeSliceToMain`** — After snapshot creation and BEFORE `git merge --squash`, call `runPreMergeCheck()`. If it fails, throw an error with the command and output so the caller can report what went wrong. The merge hasn't started yet, so there's nothing to roll back. Important: the check must run AFTER checkout to main branch but BEFORE squash merge — we need to check the slice branch code. Solution: run the check while still on the slice branch (before `switchToMain` in the caller), OR check after squash merge but before commit and reset on failure. The cleanest: run the check on main after `git merge --squash` (tests the merged result), and `git reset --hard HEAD` on failure to undo the squash.
|
||||
|
||||
3. **Add auto-push logic** to `mergeSliceToMain` — After successful commit and branch deletion, if `this.prefs.auto_push === true`, run `git push <remote> <mainBranch>` where remote is `this.prefs.remote ?? "origin"`. Use `allowFailure: true` — push failures should `console.error` a warning, not throw. The merge already succeeded locally.
|
||||
|
||||
4. **Fix worktree.ts facade `getService()`** — Change `new GitServiceImpl(basePath, {})` to load real preferences. Import `loadEffectiveGSDPreferences` from `preferences.ts`. Call it, extract the `git` field, and pass it to `GitServiceImpl`. Handle the case where prefs loading returns null (no preferences file) — fall back to `{}`. Cache invalidation: the existing cache-by-basePath is fine since prefs don't change mid-session.
|
||||
|
||||
5. **Update preferences.ts validation** — Change the `pre_merge_check` validation to accept any non-empty string, not just `boolean | "auto"`. The type already says `boolean | string` in `GitPreferences`, but validation rejects custom strings. Fix: `if (typeof g.pre_merge_check === "boolean" || typeof g.pre_merge_check === "string") { ... }` with string validation requiring non-empty after trim.
|
||||
|
||||
## Must-Haves
|
||||
|
||||
- [ ] `runPreMergeCheck()` auto-detects test runner from package.json (npm test)
|
||||
- [ ] Pre-merge check aborts merge when tests fail (before squash merge is committed)
|
||||
- [ ] Pre-merge check skippable via `pre_merge_check: false` preference
|
||||
- [ ] Pre-merge check accepts custom string command
|
||||
- [ ] Auto-push executes `git push` when `auto_push: true`, skips otherwise
|
||||
- [ ] Auto-push failures warn (don't throw)
|
||||
- [ ] `worktree.ts` `getService()` loads real preferences (no more hardcoded `{}`)
|
||||
- [ ] `preferences.ts` accepts custom string for `pre_merge_check`
|
||||
- [ ] `npm run build` and `npm run test` pass clean (all S05 tests green)
|
||||
|
||||
## Verification
|
||||
|
||||
- `npm run build` passes
|
||||
- `npm run test` passes — all existing + all T01 S05 tests green
|
||||
- `grep -r 'new GitServiceImpl.*{}' src/resources/extensions/gsd/worktree.ts` returns 0 matches
|
||||
- `grep 'pre_merge_check === "auto"' src/resources/extensions/gsd/preferences.ts` returns 0 matches (replaced with broader string check)
|
||||
|
||||
## Observability Impact
|
||||
|
||||
- Signals added/changed: `console.error` for pre-merge check failures (includes command + stderr), push failures (includes remote + error), and "no test runner detected" info
|
||||
- How a future agent inspects this: Pre-merge check result includes command name and output. Push failure includes remote URL.
|
||||
- Failure state exposed: Pre-merge check failure throws with structured error including command, exit code context, and stderr snippet
|
||||
|
||||
## Inputs
|
||||
|
||||
- `src/resources/extensions/gsd/git-service.ts` — T02 output with snapshot, rich commits, remote fetch already implemented
|
||||
- `src/resources/extensions/gsd/worktree.ts` — current facade with `getService()` using `{}`
|
||||
- `src/resources/extensions/gsd/preferences.ts` — current validation rejecting custom string for `pre_merge_check`
|
||||
- `src/resources/extensions/gsd/tests/git-service.test.ts` — T01 tests defining expected behavior for merge guards, auto-push, facade prefs
|
||||
|
||||
## Expected Output
|
||||
|
||||
- `src/resources/extensions/gsd/git-service.ts` — `runPreMergeCheck()` method, auto-push in `mergeSliceToMain`, pre-merge check wired into merge flow
|
||||
- `src/resources/extensions/gsd/worktree.ts` — `getService()` loads real preferences via `loadEffectiveGSDPreferences()`
|
||||
- `src/resources/extensions/gsd/preferences.ts` — `pre_merge_check` validation accepts custom string commands
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
# S06: Cleanup and archive
|
||||
|
||||
**Goal:** Delete remaining design input files and verify doc consistency across the milestone.
|
||||
**Demo:** `ONBOARDING-PLAN.md` no longer exists, no references to any of the 4 design input files remain in the codebase, docs match code behavior, prompts contain no raw git commands, and `npm run build` passes.
|
||||
|
||||
## Must-Haves
|
||||
|
||||
- `ONBOARDING-PLAN.md` deleted
|
||||
- Zero references to `CODEX-GIT-SYNTHESIS.md`, `CLAUDE-GIT-SYNTHESIS.md`, `GEMINI-GIT-SYNTHESIS.md`, or `ONBOARDING-PLAN.md` in the codebase
|
||||
- README.md branch lifecycle claims match code (deleted after merge, not preserved)
|
||||
- GSD-WORKFLOW.md checkpoint/branch docs match code
|
||||
- No raw git commands in execute-task.md, complete-slice.md, replan-slice.md, complete-milestone.md
|
||||
- `npm run build` exits 0
|
||||
|
||||
## Proof Level
|
||||
|
||||
- This slice proves: final-assembly (milestone cleanup — all design inputs archived, all docs consistent)
|
||||
- Real runtime required: no
|
||||
- Human/UAT required: no
|
||||
|
||||
## Verification
|
||||
|
||||
- `test ! -f ONBOARDING-PLAN.md` — file deleted
|
||||
- `test ! -f CODEX-GIT-SYNTHESIS.md && test ! -f CLAUDE-GIT-SYNTHESIS.md && test ! -f GEMINI-GIT-SYNTHESIS.md` — synthesis files stay deleted
|
||||
- `rg -l 'CODEX-GIT-SYNTHESIS|CLAUDE-GIT-SYNTHESIS|GEMINI-GIT-SYNTHESIS|ONBOARDING-PLAN' --type md --glob '!.gsd/**' | wc -l` returns 0
|
||||
- `rg 'git add|git commit|git checkout|git merge|git branch' src/resources/extensions/gsd/prompts/execute-task.md src/resources/extensions/gsd/prompts/complete-slice.md src/resources/extensions/gsd/prompts/replan-slice.md src/resources/extensions/gsd/prompts/complete-milestone.md | wc -l` returns 0
|
||||
- `npm run build` exits 0
|
||||
|
||||
## Observability / Diagnostics
|
||||
|
||||
Not applicable — this is a delete-only cleanup slice with no runtime surface, no new code, and no state changes.
|
||||
|
||||
- Runtime signals: none
|
||||
- Inspection surfaces: none
|
||||
- Failure visibility: none
|
||||
- Redaction constraints: none
|
||||
|
||||
## Integration Closure
|
||||
|
||||
- Upstream surfaces consumed: S03 doc fixes (README, GSD-WORKFLOW), S04 prompt cleanup, S05 preference wiring
|
||||
- New wiring introduced in this slice: none
|
||||
- What remains before the milestone is truly usable end-to-end: nothing — this is the final slice
|
||||
|
||||
## Tasks
|
||||
|
||||
- [x] **T01: Delete ONBOARDING-PLAN.md and verify milestone doc consistency** `est:10m`
|
||||
- Why: Only remaining design input file. Doc consistency check closes R018 and validates all prior slice doc work holds.
|
||||
- Files: `ONBOARDING-PLAN.md`
|
||||
- Do: Delete `ONBOARDING-PLAN.md`. Verify the 3 synthesis files remain deleted. Grep for references to all 4 files. Grep prompts for raw git commands. Verify README branch lifecycle claims. Verify GSD-WORKFLOW checkpoint docs. Run `npm run build`.
|
||||
- Verify: All verification commands in the Verification section above pass.
|
||||
- Done when: File deleted, zero references found, zero raw git commands in prompts, build passes.
|
||||
|
||||
## Files Likely Touched
|
||||
|
||||
- `ONBOARDING-PLAN.md` (deleted)
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
---
|
||||
estimated_steps: 5
|
||||
estimated_files: 1
|
||||
---
|
||||
|
||||
# T01: Delete ONBOARDING-PLAN.md and verify milestone doc consistency
|
||||
|
||||
**Slice:** S06 — Cleanup and archive
|
||||
**Milestone:** M001
|
||||
|
||||
## Description
|
||||
|
||||
Delete the last remaining design input file (`ONBOARDING-PLAN.md`) and run a comprehensive consistency check across all milestone documentation. This single task covers R018 (archive design input files) and validates that all prior slice work (S03 doc fixes, S04 prompt cleanup) remains intact.
|
||||
|
||||
## Steps
|
||||
|
||||
1. Delete `ONBOARDING-PLAN.md` from the repo root.
|
||||
2. Verify all 4 design input files are gone: `CODEX-GIT-SYNTHESIS.md`, `CLAUDE-GIT-SYNTHESIS.md`, `GEMINI-GIT-SYNTHESIS.md`, `ONBOARDING-PLAN.md`.
|
||||
3. Grep the codebase (excluding `.gsd/`) for any references to the 4 deleted files. Expect zero hits.
|
||||
4. Grep prompts (`execute-task.md`, `complete-slice.md`, `replan-slice.md`, `complete-milestone.md`) for raw git commands (`git add`, `git commit`, `git checkout`, `git merge`, `git branch`). Expect zero hits.
|
||||
5. Run `npm run build` and confirm exit 0.
|
||||
|
||||
## Must-Haves
|
||||
|
||||
- [ ] `ONBOARDING-PLAN.md` deleted
|
||||
- [ ] Zero references to any of the 4 design input files in non-.gsd markdown
|
||||
- [ ] Zero raw git commands in the 4 prompt files
|
||||
- [ ] `npm run build` passes
|
||||
|
||||
## Verification
|
||||
|
||||
- `test ! -f ONBOARDING-PLAN.md && echo PASS || echo FAIL`
|
||||
- `test ! -f CODEX-GIT-SYNTHESIS.md && test ! -f CLAUDE-GIT-SYNTHESIS.md && test ! -f GEMINI-GIT-SYNTHESIS.md && echo PASS || echo FAIL`
|
||||
- `rg -l 'CODEX-GIT-SYNTHESIS|CLAUDE-GIT-SYNTHESIS|GEMINI-GIT-SYNTHESIS|ONBOARDING-PLAN' --type md --glob '!.gsd/**' | wc -l` returns 0
|
||||
- `rg 'git add|git commit|git checkout|git merge|git branch' src/resources/extensions/gsd/prompts/execute-task.md src/resources/extensions/gsd/prompts/complete-slice.md src/resources/extensions/gsd/prompts/replan-slice.md src/resources/extensions/gsd/prompts/complete-milestone.md | wc -l` returns 0
|
||||
- `npm run build` exits 0
|
||||
|
||||
## Observability Impact
|
||||
|
||||
- Signals added/changed: None
|
||||
- How a future agent inspects this: None — cleanup task with no runtime surface
|
||||
- Failure state exposed: None
|
||||
|
||||
## Inputs
|
||||
|
||||
- `ONBOARDING-PLAN.md` — the file to delete
|
||||
- S03 summary — confirmed README and GSD-WORKFLOW doc fixes landed
|
||||
- S04 summary — confirmed prompt cleanup landed
|
||||
|
||||
## Expected Output
|
||||
|
||||
- `ONBOARDING-PLAN.md` — deleted
|
||||
- All verification checks pass, confirming R018 is satisfied and milestone docs are consistent
|
||||
Loading…
Add table
Reference in a new issue