docs: map existing codebase

This commit is contained in:
local
2026-03-27 00:21:00 +00:00
parent f50d2f8446
commit d963902a28
7 changed files with 1215 additions and 0 deletions

View 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*

View 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*

View 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*

View 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*

View 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*

View 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*

View 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*