docs: map existing codebase
This commit is contained in:
170
.planning/codebase/ARCHITECTURE.md
Normal file
170
.planning/codebase/ARCHITECTURE.md
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
# Architecture
|
||||||
|
|
||||||
|
**Analysis Date:** 2026-03-27
|
||||||
|
|
||||||
|
## Pattern Overview
|
||||||
|
|
||||||
|
**Overall:** Agent-orchestrated agentic code framework (GSD - Get Shit Done)
|
||||||
|
|
||||||
|
**Key Characteristics:**
|
||||||
|
- Multi-agent cooperative system: 18 specialized agents working in coordinated workflows
|
||||||
|
- Document-driven state management: All decisions and progress stored as Markdown files
|
||||||
|
- Workflow-based orchestration: 56 workflows guide agent interactions and user engagement
|
||||||
|
- Agentic code execution: Plans are executable prompts for Claude model execution
|
||||||
|
- Extensible per-runtime: Same architecture replicated across 7 IDE/agent providers (.claude, .agent, .gemini, .codex, .cursor, .windsurf, .opencode)
|
||||||
|
|
||||||
|
## Layers
|
||||||
|
|
||||||
|
**Orchestration Layer:**
|
||||||
|
- Purpose: Coordinate user commands, route to agents, manage phase/milestone progression
|
||||||
|
- Location: `.claude/get-shit-done/workflows/`
|
||||||
|
- Contains: 56 workflow definitions (markdown files), each defining a multi-step process
|
||||||
|
- Depends on: gsd-tools.cjs CLI for state management, git operations, config parsing
|
||||||
|
- Used by: All commands (user entry points)
|
||||||
|
|
||||||
|
**Agent Layer:**
|
||||||
|
- Purpose: Specialized reasoning for different task types (planning, execution, research, verification, mapping)
|
||||||
|
- Location: `.claude/agents/` (18 agents)
|
||||||
|
- Contains: Agent role definitions, instructions, tool access lists
|
||||||
|
- Agents: gsd-planner, gsd-executor, gsd-phase-researcher, gsd-verifier, gsd-debugger, gsd-codebase-mapper, gsd-integration-checker, gsd-ui-auditor, gsd-plan-checker, and 9 others
|
||||||
|
- Depends on: Workflow coordination, tools (Read, Write, Bash, Grep, Glob, WebFetch)
|
||||||
|
- Used by: Orchestration workflows, invoked via `@agent-name` or Task() calls
|
||||||
|
|
||||||
|
**State Management Layer:**
|
||||||
|
- Purpose: Persistent tracking of project progress, decisions, and configuration
|
||||||
|
- Location: `.planning/` (global state), phase directories (phase-local state)
|
||||||
|
- Contains: STATE.md (global), CONTEXT.md (decisions), ROADMAP.md (scope), PLAN.md (task breakdown), SUMMARY.md (execution results), VERIFICATION.md (quality gates)
|
||||||
|
- Depends on: gsd-tools.cjs for parsing, git for history
|
||||||
|
- Used by: All agents and orchestration layer
|
||||||
|
|
||||||
|
**Tool Layer:**
|
||||||
|
- Purpose: Provide execution capabilities for agents
|
||||||
|
- Location: Various (bash, file I/O, git, web)
|
||||||
|
- Tools: Read, Write, Edit, Bash, Grep, Glob, WebFetch, mcp__context7__*
|
||||||
|
- Depends on: Agent invocations
|
||||||
|
- Used by: Agents during execution
|
||||||
|
|
||||||
|
**CLI Tool Layer:**
|
||||||
|
- Purpose: Centralized state/config operations shared across 50+ workflow/agent files
|
||||||
|
- Location: `.claude/get-shit-done/bin/gsd-tools.cjs` (~1000 lines)
|
||||||
|
- Contains: 100+ commands for state management, phase operations, validation, progress tracking
|
||||||
|
- Depends on: Node.js built-ins, git, file system
|
||||||
|
- Used by: Every workflow and agent (called via bash subprocess)
|
||||||
|
|
||||||
|
## Data Flow
|
||||||
|
|
||||||
|
**Phase Planning Flow:**
|
||||||
|
|
||||||
|
1. User invokes `/gsd:plan-phase PHASE_NUMBER`
|
||||||
|
2. Orchestrator (plan-phase workflow) loads PHASE state via gsd-tools.cjs
|
||||||
|
3. Planner agent (gsd-planner) reads CONTEXT.md (user decisions), codebase structure, creates PLAN.md
|
||||||
|
4. Plan Checker agent validates PLAN.md structure and quality
|
||||||
|
5. PLAN.md written to phase directory
|
||||||
|
6. User reviews, optionally discusses via `/gsd:discuss-phase` → updates CONTEXT.md
|
||||||
|
7. Flow loops if plan changes needed
|
||||||
|
|
||||||
|
**Phase Execution Flow:**
|
||||||
|
|
||||||
|
1. User invokes `/gsd:execute-phase PHASE_NUMBER`
|
||||||
|
2. Executor orchestrator loads phase plans (multiple per phase)
|
||||||
|
3. Plans grouped by wave (dependency-aware parallelization)
|
||||||
|
4. For each wave:
|
||||||
|
- Executor agent loads PLAN.md
|
||||||
|
- Executes tasks sequentially (each task → code change → test verification)
|
||||||
|
- Commits per-task (atomic commits for rollback safety)
|
||||||
|
- Writes SUMMARY.md with results
|
||||||
|
5. Orchestrator collects all SUMMARY.md files
|
||||||
|
6. Verifier agent checks phase completion against VERIFICATION.md
|
||||||
|
7. STATE.md updated with completion status
|
||||||
|
8. Planning docs committed to git (if commit_docs: true)
|
||||||
|
|
||||||
|
**Verification Flow:**
|
||||||
|
|
||||||
|
1. Phase execution completes, SUMMARY.md produced
|
||||||
|
2. Verifier agent compares output against VERIFICATION.md (user-defined success criteria)
|
||||||
|
3. If gaps detected: Trigger `/gsd:plan-phase --gaps` for remedial planning
|
||||||
|
4. Remedial PLAN.md created with gap-closure tasks
|
||||||
|
5. Execute → Verify loop continues until no gaps
|
||||||
|
|
||||||
|
**State Management Flow:**
|
||||||
|
|
||||||
|
1. STATE.md maintains global position: current_phase, current_milestone, workstream, blockers
|
||||||
|
2. Phase directories contain CONTEXT.md (decisions), PLAN.md (tasks), SUMMARY.md (results), VERIFICATION.md (success gates)
|
||||||
|
3. ROADMAP.md holds master scope: all phases with descriptions
|
||||||
|
4. .planning/config.json: branching strategy, model profiles, search behavior
|
||||||
|
5. Each operation updates relevant state file, committed atomically
|
||||||
|
|
||||||
|
## Key Abstractions
|
||||||
|
|
||||||
|
**Phase:**
|
||||||
|
- Purpose: Logical unit of work scoped by user, contains multiple Plans
|
||||||
|
- Examples: `1`, `1.1`, `1.2` (decimal numbering for sub-phases)
|
||||||
|
- Pattern: Each phase has directory `.planning/phases/N/` with CONTEXT.md, PLAN.md, SUMMARY.md, VERIFICATION.md
|
||||||
|
|
||||||
|
**Plan:**
|
||||||
|
- Purpose: Executable task breakdown derived from phase scope (typically 2-3 tasks per plan)
|
||||||
|
- Examples: `PLAN-01.md`, `PLAN-02.md` within a phase directory
|
||||||
|
- Pattern: PLAN.md contains frontmatter (metadata), objective, context references, tasks array, success criteria
|
||||||
|
|
||||||
|
**Task:**
|
||||||
|
- Purpose: Atomic unit of work within a plan (code change, test, commit)
|
||||||
|
- Types: `type="auto"` (fully autonomous), `type="checkpoint"` (pause before), `type="review"` (requires human sign-off)
|
||||||
|
- Pattern: Task has action (what to do), verification criteria, expected artifacts
|
||||||
|
|
||||||
|
**Workflow:**
|
||||||
|
- Purpose: Multi-step process coordinating user input and agent actions
|
||||||
|
- Examples: `plan-phase.md`, `execute-phase.md`, `discuss-phase.md`
|
||||||
|
- Pattern: Workflows define steps with conditional branching, agent spawning, state updates
|
||||||
|
|
||||||
|
**Agent Profiles:**
|
||||||
|
- Purpose: Model selection strategy for agent execution (quality vs cost)
|
||||||
|
- Profiles: `quality` (Opus for all), `balanced` (Opus planning, Sonnet execution), `budget` (minimal Opus)
|
||||||
|
- Pattern: Resolved via gsd-tools.cjs based on `.planning/config.json` model_profile setting
|
||||||
|
|
||||||
|
## Entry Points
|
||||||
|
|
||||||
|
**Command Entry Point:**
|
||||||
|
- Location: `.claude/get-shit-done/workflows/` (any `.md` file)
|
||||||
|
- Triggers: User invokes `/gsd:WORKFLOW_NAME [args]`
|
||||||
|
- Responsibilities: Parse arguments, call gsd-tools.cjs init command, route to agents or inline execution
|
||||||
|
|
||||||
|
**Agent Entry Point:**
|
||||||
|
- Location: `.claude/agents/AGENT_NAME.md`
|
||||||
|
- Triggers: Spawned by orchestrator via `@AGENT_NAME` mention or Task() call
|
||||||
|
- Responsibilities: Load context, read mandatory files, execute role-specific logic, return results
|
||||||
|
|
||||||
|
**Tool Entry Point:**
|
||||||
|
- Location: `.claude/get-shit-done/bin/gsd-tools.cjs`
|
||||||
|
- Triggers: `node gsd-tools.cjs <command> [args]`
|
||||||
|
- Responsibilities: Parse subcommands, perform atomic state/git operations, output JSON
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
**Strategy:** Graceful degradation with checkpoint pauses
|
||||||
|
|
||||||
|
**Patterns:**
|
||||||
|
- **Auth Errors:** Executor pauses at checkpoint, waits for user to provide credentials
|
||||||
|
- **Verification Failures:** Verifier identifies gaps, planner creates remedial PLAN.md, executor runs gap-closure phase
|
||||||
|
- **Invalid State:** gsd-tools.cjs validate commands detect inconsistencies, suggest repairs
|
||||||
|
- **Parse Failures:** Frontmatter validation catches schema violations early
|
||||||
|
- **Git Conflicts:** Executor respects branching strategy, creates feature branches per config
|
||||||
|
|
||||||
|
## Cross-Cutting Concerns
|
||||||
|
|
||||||
|
**Logging:** Shell output captured from gsd-tools.cjs, bash task execution. Errors logged to console, summary tracked in SUMMARY.md.
|
||||||
|
|
||||||
|
**Validation:** gsd-tools.cjs provides `validate` commands for:
|
||||||
|
- Phase numbering consistency
|
||||||
|
- Plan structure (required fields, task arrays)
|
||||||
|
- References (@ paths resolve to existing files)
|
||||||
|
- Artifacts (must_haves tracked in PLAN.md)
|
||||||
|
|
||||||
|
**Authentication:** Config stored in `~/.gsd/` (outside repo), environment variable overrides for CI. Secrets never committed to git.
|
||||||
|
|
||||||
|
**Atomicity:** gsd-tools.cjs commit command handles commit_docs check and .gitignore detection. Each task commits separately for rollback safety.
|
||||||
|
|
||||||
|
**Determinism:** Model profiles ensure same agent type always gets same model (unless inherit mode). Frontmatter schema validation prevents parsing ambiguity.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Architecture analysis: 2026-03-27*
|
||||||
250
.planning/codebase/CONCERNS.md
Normal file
250
.planning/codebase/CONCERNS.md
Normal file
@@ -0,0 +1,250 @@
|
|||||||
|
# Codebase Concerns
|
||||||
|
|
||||||
|
**Analysis Date:** 2026-03-27
|
||||||
|
|
||||||
|
## Silent Error Handling (Critical)
|
||||||
|
|
||||||
|
**Widespread use of empty catch blocks:**
|
||||||
|
- Files: `/.claude/hooks/gsd-prompt-guard.js`, `/.claude/hooks/gsd-context-monitor.js`, `/.claude/hooks/gsd-workflow-guard.js`, `/.claude/hooks/gsd-statusline.js`, `/.claude/hooks/gsd-check-update.js`
|
||||||
|
- Issue: 14+ catch blocks across hooks swallow errors silently with `catch (e) {}` or `catch (e) { // comment }` without logging
|
||||||
|
- Impact: Failures in hook execution go undetected, making debugging difficult. When files are corrupted, config fails to parse, or file system errors occur, no indication is provided to users or developers
|
||||||
|
- Current mitigation: Comments explain intent (e.g., "Silent fail -- bridge is best-effort", "don't break statusline on parse errors"), but no logging mechanism exists
|
||||||
|
- Recommendation: Implement optional debug logging to stderr (only when hooks are invoked in debug mode) without breaking normal operation. Use environment variable like `GSD_HOOK_DEBUG=1` to enable error logging
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Fragile Hook Timeout Architecture
|
||||||
|
|
||||||
|
**Context-Monitor Hook (`.claude/hooks/gsd-context-monitor.js`)**:
|
||||||
|
- Issue: 10-second stdin timeout (line 35) is tight for slow systems. On Windows/Git Bash, pipe delays can exceed this
|
||||||
|
- Files: `/.claude/hooks/gsd-context-monitor.js` (line 35: `setTimeout(() => process.exit(0), 10000)`)
|
||||||
|
- Current mitigation: Comments reference issues #775, #1162 indicating this was a known problem
|
||||||
|
- Risk: On systems with slow I/O, the hook exits prematurely without reading input, potentially leaving metrics unprocessed
|
||||||
|
- Safe modification: Consider detecting platform and adjusting timeout accordingly, or make timeout configurable via environment variable
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Hardcoded Buffer Percentage
|
||||||
|
|
||||||
|
**Status Line Hook Context Normalization**:
|
||||||
|
- Issue: 16.5% buffer hardcoded for Claude Code autocompact (line 29)
|
||||||
|
- Files: `/.claude/hooks/gsd-statusline.js` (line 29: `const AUTO_COMPACT_BUFFER_PCT = 16.5`)
|
||||||
|
- Impact: If Claude Code changes autocompact behavior or other models have different buffers, context calculations become inaccurate
|
||||||
|
- Recommendation: Make this configurable via `.planning/config.json` with sensible defaults per model (Claude, Gemini, OpenCode)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Stale Hook Version Tracking
|
||||||
|
|
||||||
|
**Hook Version Header Validation**:
|
||||||
|
- Issue: Version detection depends on comment headers in JavaScript files (line 78 in `gsd-check-update.js`)
|
||||||
|
- Files: `/.claude/hooks/gsd-check-update.js` (lines 73-92)
|
||||||
|
- Risk: If hook files are minified, reformatted, or copied incorrectly, version headers can be lost, making stale hook detection fail silently
|
||||||
|
- Current state: Detects "unknown" version if header is missing, but this doesn't prevent the hook from running with wrong version
|
||||||
|
- Recommendation: Add a checksum or content hash validation in addition to version headers to detect unintended hook modifications
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Process Detachment on Windows
|
||||||
|
|
||||||
|
**Check-Update Hook Background Process**:
|
||||||
|
- Issue: Uses `spawn()` with `detached: true` (line 111 in `gsd-check-update.js`)
|
||||||
|
- Files: `/.claude/hooks/gsd-check-update.js` (lines 108-114)
|
||||||
|
- Impact: Background npm process can hang on Windows if not properly detached. Blocks are prevented by `unref()` (line 114), but edge cases remain if process fails
|
||||||
|
- Current state: `windowsHide: true` flag added, `stdio: 'ignore'` set
|
||||||
|
- Recommendation: Add timeout to background spawn, return immediately after unref, and consider writing to log file instead of silently ignoring errors
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Config File Parsing Without Validation
|
||||||
|
|
||||||
|
**Multiple Hooks Read `.planning/config.json`**:
|
||||||
|
- Issue: Config files are parsed with `JSON.parse()` but no schema validation exists
|
||||||
|
- Files: `/.claude/hooks/gsd-context-monitor.js` (line 53), `/.claude/hooks/gsd-workflow-guard.js` (line 65)
|
||||||
|
- Risk: Malformed JSON or missing expected fields cause silent failures. If config structure changes, old configs won't error but silently ignore new fields
|
||||||
|
- Recommendation: Implement a simple schema validation utility (even lightweight: check for required keys and types) and log warnings when config doesn't match expected shape
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Race Conditions in Metrics Bridge
|
||||||
|
|
||||||
|
**Context Metrics Between Statusline and Monitor Hooks**:
|
||||||
|
- Issue: Two separate hooks read/write to `/tmp/claude-ctx-{sessionId}.json` without file locking
|
||||||
|
- Files: `/.claude/hooks/gsd-statusline.js` (line 40-47 writes), `/.claude/hooks/gsd-context-monitor.js` (line 63-70 reads)
|
||||||
|
- Risk: On high-frequency tool use, write and read can race, causing monitor hook to read stale metrics or corrupted JSON
|
||||||
|
- Current mitigation: Both have try-catch around JSON.parse(), stale metrics are detected by timestamp (line 74)
|
||||||
|
- Recommendation: Use atomic writes (write-to-temp-then-rename pattern) for metrics file, or switch to a simpler shared state mechanism
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Missing Logging Infrastructure
|
||||||
|
|
||||||
|
**No Structured Logging**:
|
||||||
|
- Issue: Hooks only log to stdout via process.stdout.write() for hook outputs. No persistent logs for troubleshooting
|
||||||
|
- Files: All hook files (`/.claude/hooks/*.js`)
|
||||||
|
- Impact: When hooks fail silently, no audit trail exists to debug issues. Users cannot see what hooks detected or why they exited
|
||||||
|
- Recommendation: Create optional debug logs in `.planning/hooks-debug.log` (only when env var `GSD_DEBUG=1`), append structured JSON records with timestamp, hook name, and outcome
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Unbounded Memory in Warning State File
|
||||||
|
|
||||||
|
**Context Monitor Warning Debounce**:
|
||||||
|
- Issue: Warning state tracked in `/tmp/claude-ctx-{sessionId}-warned.json` accumulates indefinitely
|
||||||
|
- Files: `/.claude/hooks/gsd-context-monitor.js` (lines 87-117)
|
||||||
|
- Risk: Temporary directory might not clean this up, causing stale state from previous sessions to affect new sessions
|
||||||
|
- Current mitigation: State is per-session (uses sessionId), so scope is limited
|
||||||
|
- Recommendation: Add timestamp to warning state and treat state older than 1 hour as stale (auto-reset)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Regex Pattern Complexity in Prompt Guard
|
||||||
|
|
||||||
|
**Prompt Injection Detection Patterns**:
|
||||||
|
- Issue: 12 regex patterns for injection detection (lines 18-32 in `gsd-prompt-guard.js`) are not anchored and may be fragile
|
||||||
|
- Files: `/.claude/hooks/gsd-prompt-guard.js` (lines 18-32)
|
||||||
|
- Risk: Some patterns (e.g., `/you\s+are\s+now\s+/i`) could match benign documentation text about "You are now ready to..." and trigger false warnings
|
||||||
|
- Impact: While warnings are advisory-only, frequent false positives degrade user experience
|
||||||
|
- Recommendation: Review patterns for false positive risk, consider context (e.g., only in code blocks, not in comments), or add allowlist for common false positives
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Inconsistent Hook Version Across Environments
|
||||||
|
|
||||||
|
**Multi-Environment Hook Duplication**:
|
||||||
|
- Issue: Identical hooks duplicated across `.claude/`, `.agent/`, `.gemini/`, `.opencode/` directories
|
||||||
|
- Files: 4x each of `gsd-prompt-guard.js`, `gsd-context-monitor.js`, `gsd-workflow-guard.js`, `gsd-statusline.js`, `gsd-check-update.js`
|
||||||
|
- Risk: If one environment's hooks are updated, others can drift out of sync. Version check in `gsd-check-update.js` detects this (line 81-82) but doesn't auto-fix
|
||||||
|
- Impact: Users with multiple agent environments may see inconsistent behavior
|
||||||
|
- Recommendation: Consolidate hooks to a shared location or implement auto-sync mechanism in installer
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Resource Leaks in Timeouts
|
||||||
|
|
||||||
|
**Stdin Timeout Cleanup**:
|
||||||
|
- Issue: `setTimeout()` created for stdin timeout in all hooks, relies on `clearTimeout()` to clean up
|
||||||
|
- Files: `/.claude/hooks/gsd-prompt-guard.js`, `/.claude/hooks/gsd-context-monitor.js`, `/.claude/hooks/gsd-workflow-guard.js`, `/.claude/hooks/gsd-statusline.js`
|
||||||
|
- Risk: If process exits before reaching `process.stdin.on('end')`, timeout continues running until expiry (3-10 seconds)
|
||||||
|
- Current state: Process exits on timeout with code 0, but spawned processes inherit this timeout
|
||||||
|
- Recommendation: Add `unref()` call on timeout timers so they don't keep process alive
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Platform-Specific Path Separator
|
||||||
|
|
||||||
|
**Windows Path Handling in Guards**:
|
||||||
|
- Issue: Guards check for both `/` and `\\` in file paths (e.g., line 52 in `gsd-prompt-guard.js`)
|
||||||
|
- Files: `/.claude/hooks/gsd-prompt-guard.js` (line 52), `/.claude/hooks/gsd-workflow-guard.js` (line 43)
|
||||||
|
- Risk: Mixing separators when checking `.planning/` paths may not catch all variations on Windows (e.g., mixed slashes)
|
||||||
|
- Recommendation: Normalize paths using `path.normalize()` before comparison, or use `path.sep` for platform detection
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Missing Config Directory Override Documentation
|
||||||
|
|
||||||
|
**CLAUDE_CONFIG_DIR Environment Variable**:
|
||||||
|
- Issue: Support for `CLAUDE_CONFIG_DIR` environment variable is implemented (line 18 in `gsd-check-update.js`, line 73 in `gsd-statusline.js`) but not documented
|
||||||
|
- Files: `/.claude/hooks/gsd-check-update.js` (line 18), `/.claude/hooks/gsd-statusline.js` (line 73)
|
||||||
|
- Impact: Users with custom config directories won't know this variable exists, potentially breaking hook functionality
|
||||||
|
- Recommendation: Document in copilot-instructions.md or add reference in hook comments
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Temporary File Cleanup Strategy
|
||||||
|
|
||||||
|
**Metric Files Never Cleaned**:
|
||||||
|
- Issue: `/tmp/claude-ctx-{sessionId}.json` and `/tmp/claude-ctx-{sessionId}-warned.json` are never deleted
|
||||||
|
- Files: `/.claude/hooks/gsd-statusline.js` (writes), `/.claude/hooks/gsd-context-monitor.js` (reads)
|
||||||
|
- Risk: On long-running systems, /tmp fills up with stale session files
|
||||||
|
- Recommendation: Implement cleanup logic to delete temp files older than 7 days, or hook into session cleanup to delete files on logout
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Package.json Missing Dependencies
|
||||||
|
|
||||||
|
**Minimal Configuration**:
|
||||||
|
- Issue: `.claude/package.json` only contains `{"type":"commonjs"}`, no dependencies listed
|
||||||
|
- Files: `/.claude/package.json`
|
||||||
|
- Risk: Hooks use built-in Node modules (fs, path, os, child_process), so this is correct, but appears incomplete
|
||||||
|
- Current state: This is intentional (all hooks use only Node builtins), but unclear to maintainers
|
||||||
|
- Recommendation: Add comment in package.json explaining that hooks intentionally use no external dependencies for portability
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Potential Memory Bloat in Large Outputs
|
||||||
|
|
||||||
|
**No Stream Processing in Hooks**:
|
||||||
|
- Issue: All hooks read entire stdin into memory before processing (`let input = ''; process.stdin.on('data', chunk => input += chunk)`)
|
||||||
|
- Files: All hook files
|
||||||
|
- Risk: If a tool call writes gigabytes of content (e.g., massive file read), the hook process could run out of memory
|
||||||
|
- Current mitigation: Only tool writes/edits are inspected, and these are typically small
|
||||||
|
- Recommendation: For hooks processing large content (especially prompt injection guard), implement streaming regex matching or line-by-line processing
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Test Coverage Gaps
|
||||||
|
|
||||||
|
**No Unit Tests for Hooks**:
|
||||||
|
- What's not tested: None of the 5 hook files have automated tests
|
||||||
|
- Files: `/.claude/hooks/*.js` (all of them)
|
||||||
|
- Risk: Changes to hook logic have no regression protection. Timeout tweaks, path logic, or regex patterns could break without detection
|
||||||
|
- Impact: Hook failures are silent (by design), so broken hooks go unnoticed until users report issues
|
||||||
|
- Priority: High — hooks are critical path for agent context management
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Missing Error Recovery in Executor
|
||||||
|
|
||||||
|
**Deviation Rule Priority Conflicts**:
|
||||||
|
- Issue: Executor auto-applies Rules 1-3 without clear priority when multiple rules could apply
|
||||||
|
- Files: `/.github/agents/gsd-executor.agent.md` (line 150 mentions "RULE PRIORITY:")
|
||||||
|
- Risk: When a task has multiple issues (e.g., bug AND missing critical functionality), executor might fix bug first, missing that missing-function blocking task completion
|
||||||
|
- Recommendation: Clarify priority order: blocking issues (Rule 3) > missing critical functionality (Rule 2) > bugs (Rule 1)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Subprocess Error Propagation in Background Checks
|
||||||
|
|
||||||
|
**npm view Command Failure Silent**:
|
||||||
|
- Issue: `execSync('npm view get-shit-done-cc version')` wrapped in try-catch, timeout 10s (line 96 in `gsd-check-update.js`)
|
||||||
|
- Files: `/.claude/hooks/gsd-check-update.js` (lines 95-97)
|
||||||
|
- Risk: If npm is not installed, offline, or slow, fails silently. Users won't know update check failed
|
||||||
|
- Impact: Latest version is set to "unknown", update check becomes unreliable
|
||||||
|
- Recommendation: Log to file when update check fails (optional debug log), or retry with exponential backoff
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Missing Instrumentation for Decision Points
|
||||||
|
|
||||||
|
**No Audit Trail for Hook Decisions**:
|
||||||
|
- Issue: When context monitor injects critical warning or workflow guard injects advisory, no record of decision
|
||||||
|
- Files: `/.claude/hooks/gsd-context-monitor.js` (lines 125-142), `/.claude/hooks/gsd-workflow-guard.js` (lines 78-87)
|
||||||
|
- Risk: If user behavior doesn't match warning, no way to audit what warning was shown or when
|
||||||
|
- Recommendation: Write decision logs to `.planning/hooks-audit.log` with timestamp, hook name, decision, and reason (only in GSD active mode)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Scalability of Hook Frequency
|
||||||
|
|
||||||
|
**Hooks Run on Every Tool Use**:
|
||||||
|
- Issue: Context monitor (PostToolUse) runs after EVERY tool call, reads file, parses JSON, checks thresholds
|
||||||
|
- Files: `/.claude/hooks/gsd-context-monitor.js`
|
||||||
|
- Risk: On high-frequency tool sessions (100+ tools), accumulated overhead could impact performance
|
||||||
|
- Current mitigation: Debounce warnings (line 108), stale metric detection (line 74)
|
||||||
|
- Recommendation: Profile hook execution time under load, consider batching metrics or reducing check frequency
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Unclear Behavior on Missing Files
|
||||||
|
|
||||||
|
**Graceful Degradation Assumptions**:
|
||||||
|
- Issue: When `.planning/STATE.md`, `.planning/config.json`, or todo files don't exist, hooks silently skip functionality
|
||||||
|
- Files: All hooks that check for optional files
|
||||||
|
- Risk: Unclear to users whether missing files are "normal" or indicate misconfiguration
|
||||||
|
- Example: Statusline shows "no task" if todos not found, but user might think todos are lost
|
||||||
|
- Recommendation: Distinguish between "feature not enabled" (e.g., no .planning/ = not a GSD project) vs. "feature broken" (e.g., config.json exists but unparseable)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Concerns audit: 2026-03-27*
|
||||||
179
.planning/codebase/CONVENTIONS.md
Normal file
179
.planning/codebase/CONVENTIONS.md
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
# Coding Conventions
|
||||||
|
|
||||||
|
**Analysis Date:** 2026-03-27
|
||||||
|
|
||||||
|
## Language & Runtime
|
||||||
|
|
||||||
|
**Primary Language:** JavaScript (CommonJS)
|
||||||
|
- Node.js environment (no TypeScript transpilation)
|
||||||
|
- All hooks use `.js` extension with shebang: `#!/usr/bin/env node`
|
||||||
|
|
||||||
|
**Module System:**
|
||||||
|
- CommonJS (`require()` only, no ES6 imports)
|
||||||
|
- Node.js built-in modules: `fs`, `path`, `os`, `child_process`
|
||||||
|
- No external npm dependencies in hook files
|
||||||
|
|
||||||
|
## Naming Patterns
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Kebab-case: `gsd-hook-name.js`
|
||||||
|
- Pattern: `gsd-` prefix + feature name + `.js` extension
|
||||||
|
- Examples: `gsd-prompt-guard.js`, `gsd-context-monitor.js`, `gsd-statusline.js`
|
||||||
|
|
||||||
|
**Functions:**
|
||||||
|
- camelCase: `detectConfigDir()`, `clearTimeout()`, `writeFileSync()`
|
||||||
|
- Single-letter shorthand acceptable for simple operations: `f` for file in loops
|
||||||
|
|
||||||
|
**Constants:**
|
||||||
|
- UPPER_SNAKE_CASE for immutable values: `WARNING_THRESHOLD`, `CRITICAL_THRESHOLD`, `STALE_SECONDS`, `DEBOUNCE_CALLS`
|
||||||
|
- Inline comments after constants for clarity: `const WARNING_THRESHOLD = 35; // remaining_percentage <= 35%`
|
||||||
|
|
||||||
|
**Variables:**
|
||||||
|
- camelCase: `input`, `stdinTimeout`, `data`, `filePath`, `findings`, `configPath`
|
||||||
|
- Descriptive names: `remaining_percentage`, `callsSinceWarn`, `hookEventName`
|
||||||
|
- Single-letter loop variables: `f`, `e` (for errors), `p` (for patterns)
|
||||||
|
|
||||||
|
**Types/Objects:**
|
||||||
|
- Object keys use snake_case: `tool_name`, `tool_input`, `file_path`, `hook_version`, `installed_version`
|
||||||
|
- Array items plural: `staleHooks`, `findings`, `allowedPatterns`, `files`, `hookFiles`
|
||||||
|
|
||||||
|
## Code Style
|
||||||
|
|
||||||
|
**Formatting:**
|
||||||
|
- No linter configured (no eslintrc, prettier, or biome config files found)
|
||||||
|
- Line length: typically 80-120 characters, no strict enforced limit observed
|
||||||
|
- Indentation: 2 spaces consistently across all files
|
||||||
|
|
||||||
|
**Comments:**
|
||||||
|
- Single-line comments: `// comment`
|
||||||
|
- Multi-line blocks: Multiple `//` lines stacked (no `/* */` blocks found)
|
||||||
|
- Header comments with metadata: Version, purpose, triggers, behavior
|
||||||
|
- Pattern: `// gsd-hook-version: X.Y.Z` as first comment after shebang
|
||||||
|
- Purpose explanation follows immediately
|
||||||
|
|
||||||
|
**String Formatting:**
|
||||||
|
- Single quotes for regular strings: `'utf8'`, `'end'`
|
||||||
|
- Template literals for interpolation: `` `${variable}` ``
|
||||||
|
- Backticks for paths and code examples in comments: `` `${filePath}` ``
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
**Try-Catch Pattern:**
|
||||||
|
- All file I/O and JSON parsing wrapped in try-catch
|
||||||
|
- Silent failures preferred: catch blocks often empty or call `process.exit(0)`
|
||||||
|
- Examples from codebase:
|
||||||
|
- `try { const data = JSON.parse(input); } catch { process.exit(0); }`
|
||||||
|
- `try { ... } catch (e) { // Silent fail on parse errors }`
|
||||||
|
|
||||||
|
**Graceful Degradation:**
|
||||||
|
- Never block operations with errors
|
||||||
|
- Timeout guards prevent hanging: `const stdinTimeout = setTimeout(() => process.exit(0), 3000);`
|
||||||
|
- File existence checks before operations: `if (fs.existsSync(configPath)) { ... }`
|
||||||
|
- Return early on missing critical data: `if (!sessionId) { process.exit(0); }`
|
||||||
|
|
||||||
|
**Error Recovery:**
|
||||||
|
- Corrupted files reset to defaults: `catch (e) { warnData = { callsSinceWarn: 0, lastLevel: null }; }`
|
||||||
|
- Optional chain operators for safe access: `data.tool_input?.file_path || ''`
|
||||||
|
|
||||||
|
## Type Coercion & Checks
|
||||||
|
|
||||||
|
**Null/Undefined Handling:**
|
||||||
|
- Null coalescing default values: `data.session_id || ''`, `data.cwd || process.cwd()`
|
||||||
|
- Explicit null checks: `if (remaining != null)` (distinguishes null from undefined)
|
||||||
|
- Undefined/null fallbacks: `|| 'unknown'`, `|| []`, `|| {}`
|
||||||
|
|
||||||
|
**Truthiness Checks:**
|
||||||
|
- Explicit boolean comparisons: `if (config.hooks?.workflow_guard) { ... }`
|
||||||
|
- Array length checks: `if (files.length > 0) { ... }`, `if (findings.length === 0) { ... }`
|
||||||
|
|
||||||
|
**Number Conversions:**
|
||||||
|
- Explicit parsing: `Math.floor(Date.now() / 1000)`, `Math.round(100 - usableRemaining)`
|
||||||
|
- Clamping with Math: `Math.max(0, value)`, `Math.min(100, value)`
|
||||||
|
|
||||||
|
## Imports & Requires
|
||||||
|
|
||||||
|
**Order (when present):**
|
||||||
|
1. Node.js built-in modules: `fs`, `path`, `os`, `child_process`
|
||||||
|
2. Destructured imports grouped: `const { spawn } = require('child_process');`
|
||||||
|
3. No external package requires in hooks
|
||||||
|
|
||||||
|
**Require Pattern:**
|
||||||
|
```javascript
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const os = require('os');
|
||||||
|
const { spawn } = require('child_process');
|
||||||
|
```
|
||||||
|
|
||||||
|
## Object & Array Patterns
|
||||||
|
|
||||||
|
**Object Creation:**
|
||||||
|
- Literal syntax: `{ hookEventName: 'PreToolUse', additionalContext: message }`
|
||||||
|
- Computed properties from template literals: `` { [key]: value } `` (not observed, uses direct literals)
|
||||||
|
- Spread operators: Not used in codebase
|
||||||
|
|
||||||
|
**Array Operations:**
|
||||||
|
- `.filter()`: `files.filter(f => f.startsWith(session))`
|
||||||
|
- `.map()`: `files.map(f => ({ name: f, mtime: fs.statSync(...) }))`
|
||||||
|
- `.find()`: `todos.find(t => t.status === 'in_progress')`
|
||||||
|
- `.some()`: `allowedPatterns.some(p => p.test(filePath))`
|
||||||
|
- Arrow functions for callbacks: `chunk => input += chunk`
|
||||||
|
|
||||||
|
**Sorting & Ordering:**
|
||||||
|
- Reverse chronological: `files.sort((a, b) => b.mtime - a.mtime)`
|
||||||
|
- File system operations ordered first, then filtering
|
||||||
|
|
||||||
|
## Output Patterns
|
||||||
|
|
||||||
|
**JSON Output:**
|
||||||
|
- All hook output is JSON: `process.stdout.write(JSON.stringify(output));`
|
||||||
|
- Output structure includes `hookSpecificOutput` wrapper:
|
||||||
|
```javascript
|
||||||
|
const output = {
|
||||||
|
hookSpecificOutput: {
|
||||||
|
hookEventName: 'PreToolUse',
|
||||||
|
additionalContext: message
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
**Process Exit:**
|
||||||
|
- Success: `process.exit(0)` or implicit exit after writing output
|
||||||
|
- Error: `process.exit(0)` (never `process.exit(1)` to avoid breaking workflows)
|
||||||
|
- Cleanup: `clearTimeout()` called before operations
|
||||||
|
|
||||||
|
## File I/O Patterns
|
||||||
|
|
||||||
|
**Synchronous Operations:**
|
||||||
|
- `fs.readFileSync(path, 'utf8')` for reads
|
||||||
|
- `fs.writeFileSync(path, JSON.stringify(data))` for writes
|
||||||
|
- `fs.existsSync(path)` for checks
|
||||||
|
- `fs.readdirSync(path)` for directory listing
|
||||||
|
- `fs.statSync(path).mtime` for file metadata
|
||||||
|
|
||||||
|
**Path Operations:**
|
||||||
|
- `path.join()` for path concatenation: `path.join(cwd, '.planning', 'config.json')`
|
||||||
|
- `path.basename(dir)` for extracting final component
|
||||||
|
- `path.dirname()` for parent directory
|
||||||
|
|
||||||
|
## Regular Expressions
|
||||||
|
|
||||||
|
**Pattern Definition:**
|
||||||
|
- Captured in constants array at file top: `const INJECTION_PATTERNS = [ /pattern1/i, /pattern2/i ]`
|
||||||
|
- Case-insensitive flag commonly used: `/pattern/i`
|
||||||
|
- Multiline patterns use raw strings: `/[\u200B-\u200F]/` for Unicode detection
|
||||||
|
|
||||||
|
**Pattern Testing:**
|
||||||
|
- `.test()` method for boolean check: `if (pattern.test(content))`
|
||||||
|
- `.match()` for capture groups: `const versionMatch = content.match(/\\/\\/ gsd-hook-version:\\s*(.+)/)`
|
||||||
|
- `.source` property for pattern string: `findings.push(pattern.source)`
|
||||||
|
|
||||||
|
## No Additional Frameworks
|
||||||
|
|
||||||
|
**Testing:** Not detected - no test files exist
|
||||||
|
**Build Tools:** Not detected - runs directly as Node.js scripts
|
||||||
|
**Linting/Formatting:** Not detected - no .eslintrc, .prettierrc, or similar configs
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Convention analysis: 2026-03-27*
|
||||||
114
.planning/codebase/INTEGRATIONS.md
Normal file
114
.planning/codebase/INTEGRATIONS.md
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
# External Integrations
|
||||||
|
|
||||||
|
**Analysis Date:** 2026-03-27
|
||||||
|
|
||||||
|
## APIs & External Services
|
||||||
|
|
||||||
|
**Web Search:**
|
||||||
|
- Brave Search - Web search integration for research and discovery phases
|
||||||
|
- SDK/Client: Native `fetch` API (Node.js built-in)
|
||||||
|
- Auth: `BRAVE_API_KEY` environment variable or `~/.gsd/brave_api_key` file
|
||||||
|
- Endpoint: `https://api.search.brave.com/res/v1/web/search`
|
||||||
|
- Implementation: `cmdWebSearch()` in `/home/ys/family-repo/AgenticCode/.claude/get-shit-done/bin/lib/commands.cjs`
|
||||||
|
|
||||||
|
**Web Scraping (Optional):**
|
||||||
|
- Firecrawl - Web content extraction
|
||||||
|
- Auth: `FIRECRAWL_API_KEY` environment variable or `~/.gsd/firecrawl_api_key` file
|
||||||
|
- Status: Configuration detected, not actively used in codebase
|
||||||
|
|
||||||
|
**Search Alternative (Optional):**
|
||||||
|
- Exa Search - Alternative search API
|
||||||
|
- Auth: `~/.gsd/exa_api_key` file
|
||||||
|
- Status: Configuration detected, not actively used in codebase
|
||||||
|
|
||||||
|
## Data Storage
|
||||||
|
|
||||||
|
**Repositories:**
|
||||||
|
- Git - Primary version control system for all planning documents
|
||||||
|
- Client: Git CLI via `child_process.execSync()` and `execFileSync()`
|
||||||
|
- Operations: Commit, status, log, diff, tag management
|
||||||
|
- Integration points: `execGit()` in `core.cjs`, phase operations in `phase.cjs`
|
||||||
|
|
||||||
|
**File Storage:**
|
||||||
|
- Local filesystem only
|
||||||
|
- `.planning/` directory tree - All state, roadmaps, phases, requirements
|
||||||
|
- `~/.gsd/` directory - User-level API key storage
|
||||||
|
- Multi-workspace support via `.planning/config.json` sub_repos configuration
|
||||||
|
|
||||||
|
**Caching:**
|
||||||
|
- None detected
|
||||||
|
|
||||||
|
## Authentication & Identity
|
||||||
|
|
||||||
|
**Auth Provider:**
|
||||||
|
- Custom/API Key based
|
||||||
|
- No centralized identity provider
|
||||||
|
- Individual API keys per external service stored in files or environment variables
|
||||||
|
- Git authentication via system SSH/credentials configured externally
|
||||||
|
|
||||||
|
## Monitoring & Observability
|
||||||
|
|
||||||
|
**Error Tracking:**
|
||||||
|
- None detected - errors handled via console output
|
||||||
|
|
||||||
|
**Logs:**
|
||||||
|
- Console output via `output()` and `error()` functions in `/home/ys/family-repo/AgenticCode/.claude/get-shit-done/bin/lib/core.cjs`
|
||||||
|
- Support for structured JSON output via `--raw` flag
|
||||||
|
- Context monitoring hooks in `.claude/hooks/gsd-context-monitor.js`
|
||||||
|
|
||||||
|
## CI/CD & Deployment
|
||||||
|
|
||||||
|
**Hosting:**
|
||||||
|
- Self-hosted Node.js CLI
|
||||||
|
- IDE integration via Claude, Gemini, Agent, Cursor, OpenCode, Windsurf editors
|
||||||
|
- Editor-specific hooks and commands in `./.[editor]/.claude/hooks/`
|
||||||
|
|
||||||
|
**CI Pipeline:**
|
||||||
|
- Git hooks integration via Claude settings
|
||||||
|
- Post-tool-use monitoring: `gsd-context-monitor.js`
|
||||||
|
- Pre-write guards: `gsd-prompt-guard.js`
|
||||||
|
- Update checking: `gsd-check-update.js`
|
||||||
|
|
||||||
|
## Environment Configuration
|
||||||
|
|
||||||
|
**Required env vars:**
|
||||||
|
- `HOME` - User home directory (for API key storage and config)
|
||||||
|
- `BRAVE_API_KEY` - (optional) Brave Search API key for web search functionality
|
||||||
|
|
||||||
|
**Optional env vars:**
|
||||||
|
- `FIRECRAWL_API_KEY` - Web scraping capability
|
||||||
|
- `EXA_API_KEY` - Alternative search provider
|
||||||
|
|
||||||
|
**Secrets location:**
|
||||||
|
- Environment variables: `.env` or shell environment
|
||||||
|
- File-based: `~/.gsd/brave_api_key`, `~/.gsd/firecrawl_api_key`, `~/.gsd/exa_api_key`
|
||||||
|
- Git-ignored configuration: Not applicable (no local .env files in codebase)
|
||||||
|
|
||||||
|
## Webhooks & Callbacks
|
||||||
|
|
||||||
|
**Incoming:**
|
||||||
|
- None detected
|
||||||
|
|
||||||
|
**Outgoing:**
|
||||||
|
- Git commits via `execGit()` - Triggers CI/CD if configured
|
||||||
|
- Status updates via stdio - Display progress to Claude/editor interface
|
||||||
|
|
||||||
|
## Git Integration
|
||||||
|
|
||||||
|
**Operations Supported:**
|
||||||
|
- `git status` - Check working tree state
|
||||||
|
- `git add` - Stage files
|
||||||
|
- `git commit` - Create planning commits with auto-generated messages
|
||||||
|
- `git log` - Query commit history
|
||||||
|
- `git diff` - Compare changes
|
||||||
|
- `git tag` - Version marking for phases and milestones
|
||||||
|
- Commit routing for multi-repo workspaces
|
||||||
|
|
||||||
|
**Key Implementation:**
|
||||||
|
- Location: `execGit()` in `/home/ys/family-repo/AgenticCode/.claude/get-shit-done/bin/lib/core.cjs`
|
||||||
|
- Supports sub-repo commit routing via `commit-to-subrepo` command
|
||||||
|
- Automatic message generation with structured frontmatter
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Integration audit: 2026-03-27*
|
||||||
76
.planning/codebase/STACK.md
Normal file
76
.planning/codebase/STACK.md
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
# Technology Stack
|
||||||
|
|
||||||
|
**Analysis Date:** 2026-03-27
|
||||||
|
|
||||||
|
## Languages
|
||||||
|
|
||||||
|
**Primary:**
|
||||||
|
- JavaScript (Node.js) - Core framework and tooling
|
||||||
|
- CommonJS (`.cjs`) - Module format for all library files
|
||||||
|
- Markdown - Configuration, documentation, and state files
|
||||||
|
|
||||||
|
## Runtime
|
||||||
|
|
||||||
|
**Environment:**
|
||||||
|
- Node.js (version not explicitly specified, uses `#!/usr/bin/env node` shebang)
|
||||||
|
|
||||||
|
**Package Manager:**
|
||||||
|
- npm (inferred from package.json presence)
|
||||||
|
- Lockfile: Not detected in codebase
|
||||||
|
|
||||||
|
## Frameworks
|
||||||
|
|
||||||
|
**Core:**
|
||||||
|
- Get Shit Done (GSD) Framework v1.29.0 - Agentic code orchestration and planning
|
||||||
|
- Native Node.js APIs - `child_process`, `fs`, `path`
|
||||||
|
|
||||||
|
**Search & Web:**
|
||||||
|
- Brave Search API - Web search integration via HTTP fetch
|
||||||
|
|
||||||
|
**Build/Dev:**
|
||||||
|
- Node.js built-in utilities - No external build tool detected
|
||||||
|
|
||||||
|
## Key Dependencies
|
||||||
|
|
||||||
|
**Critical:**
|
||||||
|
- `child_process` - Subprocess execution for git commands and CLI operations
|
||||||
|
- `fs` - File system operations for planning document management
|
||||||
|
- `path` - Cross-platform path handling
|
||||||
|
- `os` - Environment detection (home directory, temp directories)
|
||||||
|
|
||||||
|
**Infrastructure:**
|
||||||
|
- `fetch` API (native Node.js) - HTTP requests for Brave Search API
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
**Environment:**
|
||||||
|
- Stored in `~/.gsd/` directory with separate API key files
|
||||||
|
- Environment variable overrides: `BRAVE_API_KEY`, `FIRECRAWL_API_KEY`, `EXA_API_KEY`
|
||||||
|
|
||||||
|
**Key Configuration Files:**
|
||||||
|
- `.planning/config.json` - Project-wide configuration and feature flags
|
||||||
|
- `settings.json` - Agent-specific settings (per `./.agent/`, `./.claude/`, `./.gemini/`, etc.)
|
||||||
|
- `.gsd-file-manifest.json` - File integrity tracking with SHA256 hashes
|
||||||
|
|
||||||
|
**Configuration Features:**
|
||||||
|
- Multi-repository workspace support
|
||||||
|
- Model profile resolution
|
||||||
|
- Milestone and workstream management
|
||||||
|
- Phase numbering strategies (decimal or custom)
|
||||||
|
|
||||||
|
## Platform Requirements
|
||||||
|
|
||||||
|
**Development:**
|
||||||
|
- Node.js with built-in ES2020+ support
|
||||||
|
- Git (for repository operations and commits)
|
||||||
|
- Bash/Shell environment for command execution
|
||||||
|
- File system with support for symlinks and deep directory structures
|
||||||
|
|
||||||
|
**Production:**
|
||||||
|
- Self-contained Node.js CLI tool
|
||||||
|
- No external runtime required beyond Node.js
|
||||||
|
- Execution via `node gsd-tools.cjs` or direct command invocation
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Stack analysis: 2026-03-27*
|
||||||
217
.planning/codebase/STRUCTURE.md
Normal file
217
.planning/codebase/STRUCTURE.md
Normal file
@@ -0,0 +1,217 @@
|
|||||||
|
# Codebase Structure
|
||||||
|
|
||||||
|
**Analysis Date:** 2026-03-27
|
||||||
|
|
||||||
|
## Directory Layout
|
||||||
|
|
||||||
|
```
|
||||||
|
/home/ys/family-repo/AgenticCode/
|
||||||
|
├── .agent/ # Anthropic Agent-specific GSD setup
|
||||||
|
│ ├── agents/ # Agent definitions (symlinks or copies)
|
||||||
|
│ ├── get-shit-done/ # Workflows, templates, references
|
||||||
|
│ ├── hooks/ # Post-tool integration hooks
|
||||||
|
│ ├── skills/ # Project skills (agent instructions)
|
||||||
|
│ └── package.json # CommonJS marker
|
||||||
|
├── .claude/ # Claude Code / Claude Web setup
|
||||||
|
│ ├── agents/ # 18 agent definition files (master)
|
||||||
|
│ ├── get-shit-done/ # Master workflows, references, commands
|
||||||
|
│ │ ├── bin/ # gsd-tools.cjs CLI (~1000 lines)
|
||||||
|
│ │ ├── commands/gsd/ # Command metadata (workstreams.md)
|
||||||
|
│ │ ├── references/ # Documentation and config specs
|
||||||
|
│ │ ├── templates/ # Scaffold templates for PLAN.md, SUMMARY.md
|
||||||
|
│ │ └── workflows/ # 56 orchestration workflows
|
||||||
|
│ ├── commands/gsd/ # Claude Code command overrides
|
||||||
|
│ ├── hooks/ # Post-tool hooks for linting/formatting
|
||||||
|
│ ├── package.json # CommonJS marker
|
||||||
|
│ └── settings.json # Per-runtime settings
|
||||||
|
├── .codex/ # Codeium Codex setup (mirrors .claude/)
|
||||||
|
├── .cursor/ # Cursor IDE setup (mirrors .claude/)
|
||||||
|
├── .gemini/ # Google Gemini setup (mirrors .claude/)
|
||||||
|
├── .opencode/ # OpenCode setup (mirrors .claude/)
|
||||||
|
├── .windsurf/ # Codeium Windsurf setup (mirrors .claude/)
|
||||||
|
├── .github/ # GitHub integration
|
||||||
|
│ ├── gsd-file-manifest.json # File integrity checksums
|
||||||
|
│ └── get-shit-done/ # GitHub action templates
|
||||||
|
├── .planning/ # Project state and planning documents
|
||||||
|
│ ├── codebase/ # Analysis documents (STACK.md, ARCHITECTURE.md, etc.)
|
||||||
|
│ ├── config.json # Project configuration (branching, model profiles)
|
||||||
|
│ ├── STATE.md # Global project state (current phase, milestone, blockers)
|
||||||
|
│ ├── ROADMAP.md # Full scope and phase definitions
|
||||||
|
│ ├── REQUIREMENTS.md # Traceability for feature requirements
|
||||||
|
│ └── phases/ # Phase execution directories
|
||||||
|
│ ├── 1/ # Phase 1
|
||||||
|
│ │ ├── CONTEXT.md # User decisions for this phase
|
||||||
|
│ │ ├── PLAN-01.md # Task breakdown (plan 1 of N)
|
||||||
|
│ │ ├── PLAN-02.md # Task breakdown (plan 2 of N)
|
||||||
|
│ │ ├── SUMMARY-01.md # Execution results (for PLAN-01)
|
||||||
|
│ │ ├── VERIFICATION.md # Success criteria and quality gates
|
||||||
|
│ │ └── WAITING.json # Optional: pause signal for checkpoints
|
||||||
|
│ ├── 1.1/ # Sub-phase 1.1
|
||||||
|
│ └── 2/ # Phase 2
|
||||||
|
├── .git/ # Git repository
|
||||||
|
├── .gitignore # Standard: excludes node_modules, .env, .planning (optional)
|
||||||
|
├── README.md # Project descriptor
|
||||||
|
└── .gsd-file-manifest.json # Root-level file integrity tracking
|
||||||
|
```
|
||||||
|
|
||||||
|
## Directory Purposes
|
||||||
|
|
||||||
|
**`.claude/` (Master Directory):**
|
||||||
|
- Purpose: Contains the canonical GSD system — agents, workflows, CLI tool, references
|
||||||
|
- Contains: Agent role definitions (18 files), 56 workflows, gsd-tools.cjs, documentation
|
||||||
|
- Key files: `agents/gsd-planner.md`, `agents/gsd-executor.md`, `agents/gsd-codebase-mapper.md`, `get-shit-done/bin/gsd-tools.cjs`
|
||||||
|
|
||||||
|
**`.claude/agents/`:**
|
||||||
|
- Purpose: Agent role definitions — instructions, tool access, execution patterns
|
||||||
|
- Contains: 18 agent files (one per agent type)
|
||||||
|
- File pattern: `gsd-{role-name}.md` (e.g., `gsd-planner.md`)
|
||||||
|
- Size: Large files (10KB-45KB), front-loaded with role definition, process steps
|
||||||
|
|
||||||
|
**`.claude/get-shit-done/workflows/`:**
|
||||||
|
- Purpose: Orchestration logic — multi-step processes coordinating agents and user input
|
||||||
|
- Contains: 56 markdown workflow files
|
||||||
|
- Naming: workflow names map to commands (e.g., `execute-phase.md` → `/gsd:execute-phase`)
|
||||||
|
- Pattern: Each workflow defines steps with conditional branching, gsd-tools.cjs calls, agent spawning
|
||||||
|
|
||||||
|
**`.claude/get-shit-done/bin/`:**
|
||||||
|
- Purpose: CLI tool providing centralized state/git operations
|
||||||
|
- Contains: `gsd-tools.cjs` (main tool, ~1000 lines), `lib/` (supporting utilities)
|
||||||
|
- Commands: 100+ subcommands for state, phases, roadmaps, validation, commits
|
||||||
|
- Called from: Every workflow and agent via `node gsd-tools.cjs <command>`
|
||||||
|
|
||||||
|
**`.claude/get-shit-done/references/`:**
|
||||||
|
- Purpose: Documentation and configuration specifications
|
||||||
|
- Contains: 15 reference files (model-profiles.md, planning-config.md, checkpoints.md, etc.)
|
||||||
|
- Usage: Read by agents to understand patterns, by implementers to understand system
|
||||||
|
|
||||||
|
**`.claude/get-shit-done/templates/`:**
|
||||||
|
- Purpose: Scaffold templates for plan and summary generation
|
||||||
|
- Contains: PLAN.md template, SUMMARY.md template, CONTEXT.md template
|
||||||
|
- Usage: Developers fill templates when creating new phases
|
||||||
|
|
||||||
|
**`.agent/`, `.gemini/`, `.codex/`, `.cursor/`, `.windsurf/`, `.opencode/`:**
|
||||||
|
- Purpose: Per-IDE setup directories (mirrors of `.claude/`)
|
||||||
|
- Contains: Symlinks or copies of agents/, workflows/, hooks/, settings.json
|
||||||
|
- Why separate: Each IDE has own credential storage, hook integration points, settings
|
||||||
|
|
||||||
|
**`.planning/`:**
|
||||||
|
- Purpose: Global project state and phase-local planning documents
|
||||||
|
- Contains: STATE.md (global), ROADMAP.md (full scope), config.json, phases/ directory tree
|
||||||
|
- Key files: `STATE.md` (current position), `ROADMAP.md` (phase definitions), `config.json` (branching strategy, model profiles)
|
||||||
|
|
||||||
|
**`.planning/phases/N/`:**
|
||||||
|
- Purpose: Per-phase execution directory — holds decisions, plans, summaries
|
||||||
|
- Contains: CONTEXT.md (user decisions), PLAN-*.md (task breakdowns), SUMMARY-*.md (results), VERIFICATION.md (success gates)
|
||||||
|
- Naming: Phase directories use number (1, 1.1, 1.2, 2) corresponding to ROADMAP.md phases
|
||||||
|
|
||||||
|
## Key File Locations
|
||||||
|
|
||||||
|
**Entry Points:**
|
||||||
|
- `.claude/get-shit-done/workflows/*.md` - User command entry points
|
||||||
|
- `.claude/agents/*.md` - Agent entry points (invoked by workflows)
|
||||||
|
- `.claude/get-shit-done/bin/gsd-tools.cjs` - CLI tool entry point
|
||||||
|
|
||||||
|
**Configuration:**
|
||||||
|
- `.planning/config.json` - Project-wide configuration (branching, model profiles, search behavior)
|
||||||
|
- `.claude/settings.json` - Per-runtime agent settings (model overrides, parallelization)
|
||||||
|
- `~/.gsd/defaults.json` - User-global GSD defaults (read-only in repo)
|
||||||
|
|
||||||
|
**Core Logic:**
|
||||||
|
- `.claude/agents/gsd-planner.md` - Phase planning logic (45KB, ~700 lines)
|
||||||
|
- `.claude/agents/gsd-executor.md` - Plan execution logic (21KB, ~450 lines)
|
||||||
|
- `.claude/agents/gsd-codebase-mapper.md` - Project analysis for architecture/tech docs
|
||||||
|
- `.claude/get-shit-done/bin/gsd-tools.cjs` - Centralized state/git operations
|
||||||
|
|
||||||
|
**State & Decisions:**
|
||||||
|
- `.planning/STATE.md` - Global state (current phase, milestone, workstream, blockers)
|
||||||
|
- `.planning/ROADMAP.md` - Master scope (phase numbers, descriptions, order)
|
||||||
|
- `.planning/phases/N/CONTEXT.md` - User decisions for phase N
|
||||||
|
- `.planning/phases/N/PLAN-*.md` - Task breakdowns (executable prompts)
|
||||||
|
|
||||||
|
**Execution & Verification:**
|
||||||
|
- `.planning/phases/N/SUMMARY-*.md` - Execution results, commit hashes, artifacts
|
||||||
|
- `.planning/phases/N/VERIFICATION.md` - Success criteria, quality gates, test requirements
|
||||||
|
- `.planning/REQUIREMENTS.md` - Requirement IDs (REQ-01, etc.) for traceability
|
||||||
|
|
||||||
|
**Documentation & References:**
|
||||||
|
- `.claude/get-shit-done/references/model-profiles.md` - Agent model selection strategies
|
||||||
|
- `.claude/get-shit-done/references/planning-config.md` - Configuration options spec
|
||||||
|
- `.claude/get-shit-done/references/checkpoints.md` - Pause point definition and usage
|
||||||
|
|
||||||
|
## Naming Conventions
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Workflows: kebab-case (e.g., `execute-phase.md`, `plan-phase.md`)
|
||||||
|
- Agents: kebab-case with gsd- prefix (e.g., `gsd-planner.md`, `gsd-executor.md`)
|
||||||
|
- Phase documents: UPPERCASE with phase number (e.g., `PLAN-01.md`, `SUMMARY-02.md`)
|
||||||
|
- Config files: lowercase (e.g., `config.json`, `settings.json`)
|
||||||
|
- State files: UPPERCASE (e.g., `STATE.md`, `ROADMAP.md`)
|
||||||
|
|
||||||
|
**Directories:**
|
||||||
|
- Hidden IDE-specific: dot-prefixed (`.claude`, `.agent`, `.gemini`)
|
||||||
|
- Planning: `.planning` with phase structure (phases/1/, phases/1.1/, etc.)
|
||||||
|
- Tools/resources: lowercase (agents, workflows, bin, lib, references, templates)
|
||||||
|
|
||||||
|
**Phase Numbering:**
|
||||||
|
- Integer phases: 1, 2, 3 (major phases)
|
||||||
|
- Decimal sub-phases: 1.1, 1.2, 1.3 (sub-divisions of phase 1)
|
||||||
|
- Directory structure mirrors numbering: `.planning/phases/1/`, `.planning/phases/1.1/`
|
||||||
|
|
||||||
|
## Where to Add New Code
|
||||||
|
|
||||||
|
**New Agent:**
|
||||||
|
1. Create ``.claude/agents/gsd-{agent-name}.md`` with role definition, process steps, tools
|
||||||
|
2. Size: Keep under 50KB (agents are consumed whole as context)
|
||||||
|
3. Register: List in agent registry within workflow files and orchestrator
|
||||||
|
4. Mirror: Copy to `.agent/agents/`, `.gemini/agents/`, etc. after validation
|
||||||
|
|
||||||
|
**New Workflow:**
|
||||||
|
1. Create `.claude/get-shit-done/workflows/{workflow-name}.md`
|
||||||
|
2. Define: `<purpose>`, `<process>` with numbered steps, subprocess calls to gsd-tools.cjs
|
||||||
|
3. Commands: If user-facing, add metadata entry in `.claude/commands/gsd/`
|
||||||
|
4. Routing: Document how workflow invokes agents (inline vs spawned via Task())
|
||||||
|
|
||||||
|
**New Reference Documentation:**
|
||||||
|
1. Create `.claude/get-shit-done/references/{topic}.md`
|
||||||
|
2. Purpose: Explain system patterns, configuration options, validation rules
|
||||||
|
3. Read by: Agents when implementing features, developers understanding system
|
||||||
|
4. Update: Link from agent files or workflow documentation
|
||||||
|
|
||||||
|
**New Phase (during project execution):**
|
||||||
|
1. Create phase directory: `.planning/phases/{N}/` (where N is next phase number)
|
||||||
|
2. Create CONTEXT.md (template in references/)
|
||||||
|
3. Planner creates PLAN-*.md files
|
||||||
|
4. Add phase to ROADMAP.md with description
|
||||||
|
5. Update STATE.md current_phase field
|
||||||
|
|
||||||
|
**Phase Documents (during planning):**
|
||||||
|
- PLAN.md: Created by gsd-planner agent (follows template in templates/)
|
||||||
|
- VERIFICATION.md: User creates to define success criteria (template available)
|
||||||
|
- CONTEXT.md: Created by gsd-discuss-phase agent from user decisions
|
||||||
|
|
||||||
|
## Special Directories
|
||||||
|
|
||||||
|
**`.planning/codebase/`:**
|
||||||
|
- Purpose: Analysis documents for executor reference (STACK.md, ARCHITECTURE.md, CONVENTIONS.md, TESTING.md, CONCERNS.md)
|
||||||
|
- Generated: By gsd-codebase-mapper agent via `/gsd:map-codebase`
|
||||||
|
- Committed: Yes, documents tracked in git for future reference
|
||||||
|
|
||||||
|
**`.planning/phases/N/`:**
|
||||||
|
- Purpose: Execution workspace for phase N (isolated state)
|
||||||
|
- Generated: Directories created by gsd-tools.cjs during phase setup
|
||||||
|
- Committed: Yes, all planning docs committed (unless .planning/ in .gitignore)
|
||||||
|
|
||||||
|
**`.claude/get-shit-done/bin/lib/`:**
|
||||||
|
- Purpose: Supporting utilities for gsd-tools.cjs
|
||||||
|
- Contents: Shared functions for JSON parsing, git operations, file I/O
|
||||||
|
- Generated: No, part of GSD system
|
||||||
|
- Committed: Yes, part of codebase
|
||||||
|
|
||||||
|
**`node_modules/`:**
|
||||||
|
- Purpose: NPM dependencies (if any)
|
||||||
|
- Generated: Yes, by `npm install`
|
||||||
|
- Committed: No, excluded via .gitignore
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Structure analysis: 2026-03-27*
|
||||||
209
.planning/codebase/TESTING.md
Normal file
209
.planning/codebase/TESTING.md
Normal file
@@ -0,0 +1,209 @@
|
|||||||
|
# Testing Patterns
|
||||||
|
|
||||||
|
**Analysis Date:** 2026-03-27
|
||||||
|
|
||||||
|
## Test Framework
|
||||||
|
|
||||||
|
**Status:** Not detected
|
||||||
|
- No test files (*.test.js, *.spec.js) found in codebase
|
||||||
|
- No test runner configured (no jest.config.js, vitest.config.js, or mocha configuration)
|
||||||
|
- No test dependencies listed in package.json files
|
||||||
|
|
||||||
|
**Code Context:**
|
||||||
|
- The codebase consists of 5 Node.js hook scripts (579 total lines across `.claude/hooks/`)
|
||||||
|
- Each hook is a standalone CLI tool that reads JSON from stdin and outputs JSON to stdout
|
||||||
|
- Hooks are event-driven (SessionStart, PreToolUse, PostToolUse, AfterTool lifecycle events)
|
||||||
|
- No application code beyond these hooks exists in the repository
|
||||||
|
|
||||||
|
## Script Type & Testing Approach
|
||||||
|
|
||||||
|
**Current Architecture:**
|
||||||
|
Each hook file (`gsd-*.js` in `/home/ys/family-repo/AgenticCode/.claude/hooks/`) follows the same structural pattern:
|
||||||
|
- Shebang: `#!/usr/bin/env node`
|
||||||
|
- Node.js built-in modules only (fs, path, os, child_process)
|
||||||
|
- JSON stdin → processing → JSON stdout
|
||||||
|
- Silent failure on errors (timeout guards, try-catch with exit(0))
|
||||||
|
|
||||||
|
**Hook Files:**
|
||||||
|
- `gsd-prompt-guard.js` (96 lines) - Detects prompt injection patterns in written files
|
||||||
|
- `gsd-statusline.js` (119 lines) - Renders context usage and task status
|
||||||
|
- `gsd-context-monitor.js` (156 lines) - Warns when context window is low
|
||||||
|
- `gsd-workflow-guard.js` (94 lines) - Advises on workflow compliance
|
||||||
|
- `gsd-check-update.js` (114 lines) - Checks for GSD updates in background
|
||||||
|
|
||||||
|
## Manual Testing Indicators
|
||||||
|
|
||||||
|
**Integration Points (evidence of real-world testing):**
|
||||||
|
- Comments referencing specific issues: `See #775`, `See #1162`, `See #870`, `See #884`
|
||||||
|
- Platform-specific workarounds: `windowsHide: true` for child_process to prevent console flash on Windows
|
||||||
|
- Timeout guards: `const stdinTimeout = setTimeout(() => process.exit(0), 3000);` prevents hanging on pipe issues
|
||||||
|
- Git Bash compatibility: explicit handling of stdin timeout on Windows Git Bash
|
||||||
|
|
||||||
|
**Behavioral Validation Patterns:**
|
||||||
|
- Config file validation: reads `.planning/config.json`, catches parse errors gracefully
|
||||||
|
- File existence checks before operations: `if (fs.existsSync(filePath))`
|
||||||
|
- Stale data detection: `if ((now - metrics.timestamp) > STALE_SECONDS)`
|
||||||
|
- Severity escalation tracking: debounce counter resets on warning level change
|
||||||
|
|
||||||
|
## Input Validation
|
||||||
|
|
||||||
|
**JSON Parsing with Error Handling:**
|
||||||
|
All hooks follow this pattern (example from `gsd-prompt-guard.js`):
|
||||||
|
```javascript
|
||||||
|
let input = '';
|
||||||
|
const stdinTimeout = setTimeout(() => process.exit(0), 3000);
|
||||||
|
process.stdin.setEncoding('utf8');
|
||||||
|
process.stdin.on('data', chunk => input += chunk);
|
||||||
|
process.stdin.on('end', () => {
|
||||||
|
clearTimeout(stdinTimeout);
|
||||||
|
try {
|
||||||
|
const data = JSON.parse(input);
|
||||||
|
// Process data
|
||||||
|
} catch {
|
||||||
|
// Silent fail — never block tool execution
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
**Defensive Checks:**
|
||||||
|
- Field existence: `const toolName = data.tool_name;` then `if (toolName !== 'Write' && toolName !== 'Edit')`
|
||||||
|
- Optional chaining: `data.tool_input?.file_path || ''`
|
||||||
|
- Null checks: `if (!sessionId) { process.exit(0); }`
|
||||||
|
- Default values: `data.cwd || process.cwd()`, `data.model?.display_name || 'Claude'`
|
||||||
|
|
||||||
|
## File I/O Testing
|
||||||
|
|
||||||
|
**Patterns for Reliability:**
|
||||||
|
- Synchronous I/O ensures order: `fs.readFileSync()` → process → `fs.writeFileSync()`
|
||||||
|
- Directory existence checked before writing: `if (!fs.existsSync(cacheDir)) { fs.mkdirSync(cacheDir, { recursive: true }); }`
|
||||||
|
- Try-catch wraps all file operations that could fail:
|
||||||
|
```javascript
|
||||||
|
try {
|
||||||
|
const bridgeData = JSON.stringify({ ... });
|
||||||
|
fs.writeFileSync(bridgePath, bridgeData);
|
||||||
|
} catch (e) {
|
||||||
|
// Silent fail -- bridge is best-effort, don't break statusline
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## State Machine / Behavior Testing
|
||||||
|
|
||||||
|
**Context Monitor Debounce Logic** (`gsd-context-monitor.js`):
|
||||||
|
- Tracks warning state in file: `/tmp/claude-ctx-{session_id}-warned.json`
|
||||||
|
- Debounce counter incremented: `warnData.callsSinceWarn = (warnData.callsSinceWarn || 0) + 1`
|
||||||
|
- Severity escalation bypasses debounce: `if (severityEscalated) { // emit immediately }`
|
||||||
|
- State reset on warn: `warnData.callsSinceWarn = 0`
|
||||||
|
|
||||||
|
This pattern validates behavior without formal tests:
|
||||||
|
```javascript
|
||||||
|
let warnData = { callsSinceWarn: 0, lastLevel: null };
|
||||||
|
const isCritical = remaining <= CRITICAL_THRESHOLD;
|
||||||
|
const currentLevel = isCritical ? 'critical' : 'warning';
|
||||||
|
const severityEscalated = currentLevel === 'critical' && warnData.lastLevel === 'warning';
|
||||||
|
if (!firstWarn && warnData.callsSinceWarn < DEBOUNCE_CALLS && !severityEscalated) {
|
||||||
|
process.exit(0); // Suppress warning
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Regex Pattern Testing
|
||||||
|
|
||||||
|
**Prompt Injection Detection** (`gsd-prompt-guard.js`):
|
||||||
|
Patterns tested against content without formal unit tests:
|
||||||
|
```javascript
|
||||||
|
const INJECTION_PATTERNS = [
|
||||||
|
/ignore\s+(all\s+)?previous\s+instructions/i,
|
||||||
|
/override\s+(system|previous)\s+(prompt|instructions)/i,
|
||||||
|
/you\s+are\s+now\s+(?:a|an|the)\s+/i,
|
||||||
|
/(?:print|output|reveal|show|display|repeat)\s+(?:your\s+)?(?:system\s+)?(?:prompt|instructions)/i,
|
||||||
|
/\[SYSTEM\]/i,
|
||||||
|
/<<\s*SYS\s*>>/i,
|
||||||
|
];
|
||||||
|
for (const pattern of INJECTION_PATTERNS) {
|
||||||
|
if (pattern.test(content)) {
|
||||||
|
findings.push(pattern.source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Unicode detection without regex: `if (/[\u200B-\u200F\u2028-\u202F\uFEFF\u00AD]/.test(content))`
|
||||||
|
|
||||||
|
## Environment & Configuration Testing
|
||||||
|
|
||||||
|
**Configuration Loading Safety** (all hooks):
|
||||||
|
- Try-catch with silent fail:
|
||||||
|
```javascript
|
||||||
|
const configPath = path.join(cwd, '.planning', 'config.json');
|
||||||
|
if (fs.existsSync(configPath)) {
|
||||||
|
try {
|
||||||
|
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
||||||
|
if (config.hooks?.context_warnings === false) {
|
||||||
|
process.exit(0); // Feature disabled
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// Ignore config parse errors
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- Optional chaining for nested config: `config.hooks?.workflow_guard`, `config.hooks?.context_warnings`
|
||||||
|
|
||||||
|
**Environment Variable Access:**
|
||||||
|
```javascript
|
||||||
|
const envDir = process.env.CLAUDE_CONFIG_DIR;
|
||||||
|
if (envDir && fs.existsSync(path.join(envDir, 'get-shit-done', 'VERSION'))) {
|
||||||
|
return envDir; // Custom config dir detected
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Performance & Resource Management
|
||||||
|
|
||||||
|
**Timeout Guards (prevent resource leaks):**
|
||||||
|
- All hooks implement stdin timeout: `const stdinTimeout = setTimeout(() => process.exit(0), 3000);`
|
||||||
|
- Longer timeout for high-volume operations: `const stdinTimeout = setTimeout(() => process.exit(0), 10000);` in context-monitor
|
||||||
|
- Always cleared before processing: `clearTimeout(stdinTimeout);`
|
||||||
|
|
||||||
|
**Background Process Management** (`gsd-check-update.js`):
|
||||||
|
- Child process spawned with `stdio: 'ignore'`: doesn't inherit parent's stdio
|
||||||
|
- Process detached on Windows: `detached: true` (required for proper cleanup)
|
||||||
|
- Parent calls `child.unref()`: parent doesn't wait for child to exit
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const child = spawn(process.execPath, ['-e', `...inline script...`], {
|
||||||
|
stdio: 'ignore',
|
||||||
|
windowsHide: true,
|
||||||
|
detached: true
|
||||||
|
});
|
||||||
|
child.unref();
|
||||||
|
```
|
||||||
|
|
||||||
|
## Test Coverage Gaps
|
||||||
|
|
||||||
|
**Areas Without Formal Testing:**
|
||||||
|
1. **Regex Pattern Accuracy** - Injection patterns untested against false positives/negatives
|
||||||
|
2. **Debounce Counter Edge Cases** - Corruption recovery, counter reset logic
|
||||||
|
3. **Platform-Specific Behavior** - Windows vs Linux path handling, process detachment
|
||||||
|
4. **Concurrent Access** - Multiple hooks writing to same state files simultaneously
|
||||||
|
5. **Large Input Handling** - No tests for multi-megabyte JSON on stdin
|
||||||
|
6. **Stale File Cleanup** - No validation that temp files are properly removed
|
||||||
|
7. **Spawn Child Behavior** - Background update check success/failure not validated
|
||||||
|
|
||||||
|
## Recommendation for Testing
|
||||||
|
|
||||||
|
**Given the architecture (CLI hooks, not library code):**
|
||||||
|
- Integration testing more valuable than unit tests
|
||||||
|
- Manual testing via real Claude Code sessions is current primary validation
|
||||||
|
- Would recommend:
|
||||||
|
1. Snapshot tests for JSON output structure
|
||||||
|
2. Mock file system for configuration loading paths
|
||||||
|
3. Integration tests simulating tool use hook flow
|
||||||
|
4. Platform-specific testing (Windows, macOS, Linux) for path handling
|
||||||
|
|
||||||
|
**Lack of tests is acceptable for:**
|
||||||
|
- Simple stdin/stdout data transformation scripts
|
||||||
|
- Hooks deployed once per installation (not on every tool call)
|
||||||
|
- Silent-fail-safe design (errors don't break workflows)
|
||||||
|
- Real-world testing via 50+ GitHub issues and fixes
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Testing analysis: 2026-03-27*
|
||||||
Reference in New Issue
Block a user