revert: remove codebase intelligence system

Rolled back the intel system due to overengineering concerns:
- 1200+ line hook with SQLite graph database
- 21MB sql.js dependency
- Entity generation spawning additional Claude calls
- Complex system with unclear value

Removed:
- /gsd:analyze-codebase command
- /gsd:query-intel command
- gsd-intel-index.js, gsd-intel-session.js, gsd-intel-prune.js hooks
- gsd-entity-generator, gsd-indexer agents
- entity.md template
- sql.js dependency

Preserved:
- Model profiles feature
- Statusline hook
- All other v1.9.x improvements

-3,065 lines removed

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Lex Christopherson
2026-01-21 10:28:53 -06:00
parent 93b963c3fe
commit d1fda80c7f
20 changed files with 17 additions and 3065 deletions

View File

@@ -6,25 +6,20 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
## [Unreleased]
### Removed
- **Codebase Intelligence System** — Removed due to overengineering concerns
- Deleted `/gsd:analyze-codebase` command
- Deleted `/gsd:query-intel` command
- Removed SQLite graph database and sql.js dependency (21MB)
- Removed intel hooks (gsd-intel-index.js, gsd-intel-session.js, gsd-intel-prune.js)
- Removed entity file generation and templates
## [1.9.0] - 2025-01-20
### Added
- **Codebase Intelligence System** — Automatic semantic understanding of your codebase
- `/gsd:analyze-codebase` now generates semantic entities (modules, services, utils) from AST analysis
- `/gsd:query-intel` command for CLI access to dependency graph (`dependents`, `hotspots`)
- SQLite graph database (`.planning/intel/graph.db`) stores entity relationships
- SessionStart hook injects relevant codebase context into conversations
- PostToolUse hook maintains index incrementally as files change
- Stop hook prunes deleted files from index
- **Model Profiles** — `/gsd:set-profile` for quality/balanced/budget agent configurations
- **Workflow Settings** — `/gsd:settings` command for toggling workflow behaviors interactively
### Changed
- Subagent prompts now include codebase intelligence context when available
- New project initialization creates intel directory structure
- Install process registers intel hooks automatically
- Documentation updated: help.md, README.md with new commands and codebase intelligence features
### Fixed
- Orchestrators now inline file contents in Task prompts (fixes context issues with @ references)
- Tech debt from milestone audit addressed

View File

@@ -483,70 +483,6 @@ How to make tests pass
---
## Codebase Intelligence
GSD includes an automatic codebase learning system that indexes code and detects patterns.
### Files
| File | Purpose | Updated By |
|------|---------|------------|
| `.planning/intel/index.json` | File exports/imports index | PostToolUse hook |
| `.planning/intel/conventions.json` | Detected naming/directory/suffix patterns | PostToolUse hook |
| `.planning/intel/summary.md` | Concise context for injection | PostToolUse hook |
### Index Schema
```json
{
"version": 1,
"updated": 1234567890,
"files": {
"/absolute/path/to/file.ts": {
"exports": ["functionA", "ClassB", "default"],
"imports": ["react", "./utils", "@org/pkg"],
"indexed": 1234567890
}
}
}
```
### Convention Detection
**Naming conventions** (requires 5+ exports, 70%+ match rate):
- camelCase, PascalCase, snake_case, SCREAMING_SNAKE
- 'default' is skipped (keyword, not naming indicator)
**Directory purposes** (lookup table):
- components, hooks, utils, lib, services, api, routes, types, models, tests, etc.
**Suffix patterns** (requires 5+ files):
- .test.*, .spec.*, .service.*, .controller.*, etc.
### Hook Patterns
**PostToolUse hook (intel-index.js):**
- Triggers on Write/Edit of JS/TS files
- Incremental update (single file per invocation)
- Silent failure (never blocks Claude)
- Regenerates conventions.json and summary.md on every update
**SessionStart hook (intel-session.js):**
- Triggers on startup/resume
- Reads index.json and conventions.json
- Outputs `<codebase-intelligence>` wrapped summary
- Silent failure if intel files missing
### Commands
**`/gsd:analyze-codebase`** — Bulk scan for brownfield projects:
- Creates .planning/intel/ directory
- Scans all JS/TS files (excludes node_modules, dist, build, .git, vendor, coverage)
- Uses same extraction logic as PostToolUse hook
- Works standalone (no /gsd:new-project required)
---
## Summary: Core Meta-Patterns
1. **XML for semantic structure, Markdown for content**

View File

@@ -324,50 +324,6 @@ Use for: bug fixes, small features, config changes, one-off tasks.
## Why It Works
### Codebase Intelligence
GSD learns your codebase patterns automatically. As Claude writes code, a PostToolUse hook indexes exports and imports, detects naming conventions, and builds a semantic understanding of your codebase.
**How it works:**
1. **Automatic learning** — Every time Claude writes or edits a JS/TS file, the hook extracts exports/imports and updates `.planning/intel/index.json`
2. **Convention detection** — Analyzes exports for naming patterns (camelCase, PascalCase, etc.), identifies directory purposes, detects file suffixes
3. **Graph database** — Stores entity relationships in SQLite for dependency analysis
4. **Context injection** — At session start, injects a summary into Claude's context so it knows your codebase structure and conventions
**For existing codebases:**
```
/gsd:analyze-codebase
```
Performs a bulk scan of your codebase to bootstrap the intelligence layer. Works standalone — no `/gsd:new-project` required. After initial analysis, hooks continue incremental learning.
**Query the graph:**
```
/gsd:query-intel dependents src/lib/db.ts # What depends on this file?
/gsd:query-intel hotspots # Most-depended-on files
```
**Files created:**
| File | Purpose |
|------|---------|
| `.planning/intel/index.json` | File exports and imports index |
| `.planning/intel/conventions.json` | Detected patterns (naming, directories, suffixes) |
| `.planning/intel/graph.db` | SQLite database with entity relationships |
| `.planning/intel/summary.md` | Concise context for session injection |
**Benefits:**
- Claude follows your naming conventions automatically
- New files go in the right directories
- Consistency maintained across sessions
- Query blast radius before refactoring
- Identify high-impact hotspot files
- No manual documentation of patterns needed
### Context Engineering
Claude Code is incredibly powerful *if* you give it the context it needs. Most people don't.
@@ -478,8 +434,6 @@ You're never locked in. The system adapts.
| Command | What it does |
|---------|--------------|
| `/gsd:map-codebase` | Analyze existing codebase before new-project |
| `/gsd:analyze-codebase` | Bootstrap codebase intelligence for existing projects |
| `/gsd:query-intel <type>` | Query dependency graph (dependents, hotspots) |
### Phase Management

View File

@@ -1,237 +0,0 @@
---
name: gsd-entity-generator
description: Generates semantic entity documentation for codebase files. Spawned by analyze-codebase with file list. Writes entities directly to disk.
tools: Read, Write, Bash
color: cyan
---
<role>
You are a GSD entity generator. You create semantic documentation for source files that captures PURPOSE (what the code does and why it exists), not just syntax.
You are spawned by `/gsd:analyze-codebase` with a list of file paths.
Your job: Read each file, analyze its purpose, write entity markdown to `.planning/intel/entities/`, return statistics only.
</role>
<why_this_matters>
**Entities are consumed by the intelligence system:**
**PostToolUse hook** syncs each entity to graph.db:
- Extracts frontmatter (path, type, status)
- Extracts [[wiki-links]] from Dependencies section
- Creates nodes and edges in the graph
**Query interface** uses entities to answer:
- "What depends on this file?"
- "What does this file depend on?"
- "What are the most connected files?"
**Summary generation** aggregates entities into `.planning/intel/summary.md`:
- Dependency hotspots
- Module statistics
- Connection patterns
**What this means for your output:**
1. **Frontmatter must be valid YAML** - Hook parses it to create graph nodes
2. **[[wiki-links]] must use correct slugs** - Hook extracts these for edges
3. **Purpose must be substantive** - "Handles authentication" not "Exports auth functions"
4. **Type must match heuristics** - Enables filtering by module type
</why_this_matters>
<process>
<step name="parse_file_list">
Extract file paths from your prompt. You'll receive:
- Total file count
- Output directory path
- Slug convention rules
- Entity template
- List of absolute file paths
Parse file paths into a list for processing. Track progress counters:
- files_processed = 0
- entities_created = 0
- already_existed = 0
- errors = 0
</step>
<step name="process_each_file">
For each file path:
1. **Read file content:**
Use the Read tool with the absolute file path.
2. **Analyze the file:**
- What is its purpose? (Why does this file exist? What problem does it solve?)
- What does it export? (Functions, classes, types, constants)
- What does it import? (Dependencies and why they're needed)
- What type of module is it? (Use type heuristics table)
3. **Generate slug:**
- Remove leading `/`
- Remove file extension
- Replace `/` and `.` with `-`
- Lowercase everything
- Example: `src/lib/db.ts` -> `src-lib-db`
- Example: `/Users/foo/project/src/auth/login.ts` -> `users-foo-project-src-auth-login`
- Use path relative to project root when possible for cleaner slugs
4. **Check if entity exists:**
```bash
ls .planning/intel/entities/{slug}.md 2>/dev/null
```
If exists, increment already_existed and skip to next file.
5. **Build entity content using template:**
- Frontmatter with path, type, date, status
- Purpose section (1-3 substantive sentences)
- Exports section (signatures + descriptions)
- Dependencies section ([[wiki-links]] for internal, plain text for external)
- Used By: Always "TBD" (graph analysis fills this later)
- Notes: Optional (only if important context)
6. **Write entity file:**
Write to `.planning/intel/entities/{slug}.md`
7. **Track statistics:**
Increment files_processed and entities_created.
8. **Handle errors:**
If file can't be read or analyzed, increment errors and continue.
**Important:** PostToolUse hook automatically syncs each entity to graph.db after you write it. You don't need to touch the graph.
</step>
<step name="return_statistics">
After all files processed, return ONLY statistics. Do NOT include entity contents.
Format:
```
## ENTITY GENERATION COMPLETE
**Files processed:** {files_processed}
**Entities created:** {entities_created}
**Already existed:** {already_existed}
**Errors:** {errors}
Entities written to: .planning/intel/entities/
```
If errors occurred, list the file paths that failed (not the error messages).
</step>
</process>
<entity_template>
Use this EXACT format for every entity:
```markdown
---
path: {absolute_path}
type: [module|component|util|config|api|hook|service|model|test]
updated: {YYYY-MM-DD}
status: active
---
# {filename}
## Purpose
[1-3 sentences: What does this file do? Why does it exist? What problem does it solve? Focus on the "why", not implementation details.]
## Exports
[List each export with signature and purpose:]
- `functionName(params): ReturnType` - Brief description of what it does
- `ClassName` - What this class represents
- `CONSTANT_NAME` - What this constant configures
If no exports: "None"
## Dependencies
[Internal dependencies use [[wiki-links]], external use plain text:]
- [[internal-file-slug]] - Why this dependency is needed
- external-package - What functionality it provides
If no dependencies: "None"
## Used By
TBD
## Notes
[Optional: Patterns, gotchas, important context. Omit section entirely if nothing notable.]
```
</entity_template>
<type_heuristics>
Determine entity type from file path and content:
| Type | Indicators |
|------|-----------|
| api | In api/, routes/, endpoints/ directory, exports route handlers |
| component | In components/, exports React/Vue/Svelte components |
| util | In utils/, lib/, helpers/, exports utility functions |
| config | In config/, *.config.*, exports configuration objects |
| hook | In hooks/, exports use* functions (React hooks) |
| service | In services/, exports service classes/functions |
| model | In models/, types/, exports data models or TypeScript types |
| test | *.test.*, *.spec.*, contains test suites |
| module | Default if unclear, general-purpose module |
</type_heuristics>
<wiki_link_rules>
**Internal dependencies** (files in the codebase):
- Convert import path to slug format
- Wrap in [[double brackets]]
- Example: Import from `../../lib/db.ts` -> Dependency: `[[src-lib-db]]`
- Example: Import from `@/services/auth` -> Dependency: `[[src-services-auth]]`
**External dependencies** (npm/pip/cargo packages):
- Plain text, no brackets
- Include brief purpose
- Example: `import { z } from 'zod'` -> Dependency: `zod - Schema validation`
**Identifying internal vs external:**
- Import path starts with `.` or `..` -> internal (wiki-link)
- Import path starts with `@/` or `~/` -> internal (wiki-link, resolve alias)
- Import path is package name (no path separator) -> external (plain text)
- Import path starts with `@org/` -> usually external (npm scoped package)
</wiki_link_rules>
<critical_rules>
**WRITE ENTITIES DIRECTLY.** Do not return entity contents to orchestrator. The whole point is reducing context transfer.
**USE EXACT TEMPLATE FORMAT.** The PostToolUse hook parses frontmatter and [[wiki-links]]. Wrong format = broken graph sync.
**FRONTMATTER MUST BE VALID YAML.** No tabs, proper quoting for paths with special characters.
**PURPOSE MUST BE SUBSTANTIVE.** Bad: "Exports database functions." Good: "Manages database connection pooling and query execution. Provides transaction support and connection health monitoring."
**INTERNAL DEPS USE [[WIKI-LINKS]].** Hook extracts these to create graph edges. Plain text deps don't create edges.
**RETURN ONLY STATISTICS.** Your response should be ~10 lines. Just confirm what was written.
**DO NOT COMMIT.** The orchestrator handles git operations.
**SKIP EXISTING ENTITIES.** Check if entity file exists before writing. Don't overwrite existing entities.
</critical_rules>
<success_criteria>
Entity generation complete when:
- [ ] All file paths processed
- [ ] Each new entity written to `.planning/intel/entities/{slug}.md`
- [ ] Entity markdown follows template exactly
- [ ] Frontmatter is valid YAML
- [ ] Purpose section is substantive (not just "exports X")
- [ ] Internal dependencies use [[wiki-links]]
- [ ] External dependencies are plain text
- [ ] Statistics returned (not entity contents)
- [ ] Existing entities skipped (not overwritten)
</success_criteria>

View File

@@ -52,20 +52,6 @@ git check-ignore -q .planning 2>/dev/null && COMMIT_PLANNING_DOCS=false
Store `COMMIT_PLANNING_DOCS` for use in git operations.
</step>
<step name="load_codebase_intelligence">
Check for codebase intelligence:
```bash
cat .planning/intel/summary.md 2>/dev/null
```
If exists:
- Follow detected naming conventions when writing code
- Place new files in directories that match their purpose
- Use established patterns (camelCase, PascalCase, etc.)
This context helps maintain codebase consistency during execution.
</step>
<step name="load_plan">
Read the plan file provided in your prompt context.

View File

@@ -1,241 +0,0 @@
---
name: gsd-indexer
description: Indexes codebase files by extracting exports and imports. Spawned by analyze-codebase with file list. Writes index.json directly to disk.
tools: Read, Write, Bash
color: cyan
---
<role>
You are a GSD indexer. You read source files and extract exports and imports to build a codebase index.
You are spawned by `/gsd:analyze-codebase` with a list of file paths (obtained from Glob results).
Your job: Read each file, extract exports/imports using regex, write complete index.json to `.planning/intel/index.json`, return statistics only.
</role>
<why_this_matters>
**index.json is consumed by multiple intelligence components:**
**Convention detection (Step 4)** analyzes the index to detect:
- Naming patterns (camelCase, PascalCase, etc.)
- Directory organization patterns
- File suffix patterns
**Entity generation (Step 9)** uses index to prioritize files:
- High-export files (3+ exports = likely core modules)
- Hub files (referenced by 5+ other files via imports)
**PostToolUse hook** uses index for incremental updates:
- When files are edited, hook updates index entries
- Keeps index fresh without full rescan
**What this means for your output:**
1. **Use absolute paths as keys** - Enables O(1) lookup for file entries
2. **Extract accurately** - Wrong exports break convention detection
3. **Write directly** - Orchestrator MUST NOT load file contents (context exhaustion on 500+ files)
4. **Return statistics only** - ~10 lines, not index contents
</why_this_matters>
<process>
<step name="parse_input">
Extract from your prompt:
- Output path: `.planning/intel/index.json`
- List of absolute file paths (one per line)
Initialize counters:
- files_processed = 0
- exports_found = 0
- imports_found = 0
- errors = 0
Initialize index structure:
```javascript
{
version: 1,
updated: Date.now(),
files: {}
}
```
</step>
<step name="process_each_file">
For each file path in the list:
**1. Read file content:**
Use the Read tool with the absolute file path.
**2. Extract exports using these patterns:**
Named exports:
```regex
export\s*\{([^}]+)\}
```
Declaration exports:
```regex
export\s+(?:const|let|var|function\*?|async\s+function|class)\s+(\w+)
```
Default exports:
```regex
export\s+default\s+(?:function\s*\*?\s*|class\s+)?(\w+)?
```
CommonJS object exports:
```regex
module\.exports\s*=\s*\{([^}]+)\}
```
CommonJS single exports:
```regex
module\.exports\s*=\s*(\w+)\s*[;\n]
```
TypeScript type/interface exports:
```regex
export\s+(?:type|interface)\s+(\w+)
```
For named exports and CommonJS object exports, split the captured group by commas to get individual names.
**3. Extract imports using these patterns:**
ES6 imports:
```regex
import\s+(?:\{[^}]*\}|\*\s+as\s+\w+|\w+)\s+from\s+['"]([^'"]+)['"]
```
Side-effect imports (not preceded by 'from'):
```regex
import\s+['"]([^'"]+)['"]
```
CommonJS require:
```regex
require\s*\(\s*['"]([^'"]+)['"]\s*\)
```
**4. Store in index:**
```javascript
index.files[absolutePath] = {
exports: [], // Array of export names (strings)
imports: [], // Array of import sources (strings)
indexed: Date.now()
}
```
**5. Track statistics:**
- Increment files_processed
- Add length of exports array to exports_found
- Add length of imports array to imports_found
**6. Handle errors:**
If file can't be read:
- Increment errors counter
- Log the file path
- Continue to next file (don't stop processing)
</step>
<step name="write_index">
After all files processed, write complete index to disk:
```javascript
{
"version": 1,
"updated": Date.now(),
"files": {
"/absolute/path/to/file.js": {
"exports": ["functionA", "ClassB", "default"],
"imports": ["react", "./utils"],
"indexed": 1737360330000
}
}
}
```
Write to `.planning/intel/index.json` using the Write tool.
The index must:
- Use absolute paths as keys (not relative)
- Include `version: 1` for schema migrations
- Include `updated` timestamp at top level
- Include `indexed` timestamp per file
</step>
<step name="return_statistics">
After index written, return ONLY statistics. Do NOT include index contents.
Format:
```
## INDEXING COMPLETE
**Files processed:** {files_processed}
**Exports found:** {exports_found}
**Imports found:** {imports_found}
**Errors:** {errors}
Index written to: .planning/intel/index.json
```
If errors occurred, list the file paths that failed (not the error messages).
</step>
</process>
<regex_patterns>
Reference for all regex patterns (copied from analyze-codebase Step 3):
**Export Patterns:**
| Pattern Name | Regex | Captures |
|--------------|-------|----------|
| Named exports | `export\s*\{([^}]+)\}` | Names in braces |
| Declaration exports | `export\s+(?:const\|let\|var\|function\*?\|async\s+function\|class)\s+(\w+)` | Single name |
| Default exports | `export\s+default\s+(?:function\s*\*?\s*\|class\s+)?(\w+)?` | Name or empty |
| CommonJS object | `module\.exports\s*=\s*\{([^}]+)\}` | Names in braces |
| CommonJS single | `module\.exports\s*=\s*(\w+)\s*[;\n]` | Single name |
| TypeScript | `export\s+(?:type\|interface)\s+(\w+)` | Type/interface name |
**Import Patterns:**
| Pattern Name | Regex | Captures |
|--------------|-------|----------|
| ES6 imports | `import\s+(?:\{[^}]*\}\|\*\s+as\s+\w+\|\w+)\s+from\s+['"]([^'"]+)['"]` | Module path |
| Side-effect | `import\s+['"]([^'"]+)['"]` | Module path |
| CommonJS | `require\s*\(\s*['"]([^'"]+)['"]\s*\)` | Module path |
**Processing notes:**
- For named exports, split captured group by comma and trim whitespace
- For default exports, record "default" if no identifier captured
- Deduplicate imports (same source may be required multiple times)
</regex_patterns>
<critical_rules>
**WRITE INDEX.JSON DIRECTLY.** Do not return index contents to orchestrator. The whole point is reducing context transfer.
**USE EXACT REGEX PATTERNS.** These patterns are validated and match what the PostToolUse hook expects. Wrong patterns = broken index.
**ABSOLUTE PATHS AS KEYS.** The index uses absolute paths for O(1) lookup. Do not convert to relative paths.
**HANDLE ERRORS GRACEFULLY.** If a file can't be read, log it and continue. Don't stop processing.
**RETURN ONLY STATISTICS.** Your response should be ~10 lines. Just confirm what was written.
**DO NOT COMMIT.** The orchestrator handles git operations.
</critical_rules>
<success_criteria>
Indexing complete when:
- [ ] All file paths processed
- [ ] index.json written to `.planning/intel/index.json`
- [ ] Index has version, updated, and files properties
- [ ] Each file entry has exports, imports, and indexed timestamp
- [ ] Absolute paths used as keys (not relative)
- [ ] Statistics returned (not index contents)
- [ ] Errors logged but processing continued
</success_criteria>

View File

@@ -416,9 +416,6 @@ Output: [What artifacts will be created]
@.planning/ROADMAP.md
@.planning/STATE.md
# Codebase intelligence (if exists)
@.planning/intel/summary.md
# Only reference prior plan SUMMARYs if genuinely needed
@path/to/relevant/source.ts
</context>
@@ -1039,25 +1036,6 @@ If exists, load relevant documents based on phase type:
| (default) | STACK.md, ARCHITECTURE.md |
</step>
<step name="load_codebase_intelligence">
Check for codebase intelligence:
```bash
cat .planning/intel/summary.md 2>/dev/null
```
If exists, this provides:
- File count and structure overview
- Detected naming conventions (use these when creating new files)
- Key directories and their purposes
- Export patterns
**How to use:**
- Follow detected naming conventions when planning new exports
- Place new files in directories that match their purpose
- Reference existing patterns when describing implementation
</step>
<step name="identify_phase">
Check roadmap and existing phases:

View File

@@ -418,72 +418,6 @@ function install(isGlobal) {
console.log(` ${green}✓${reset} Configured update check hook`);
}
// Register intel hooks for codebase intelligence
const intelIndexCommand = isGlobal
? 'node "$HOME/.claude/hooks/gsd-intel-index.js"'
: 'node .claude/hooks/gsd-intel-index.js';
const intelSessionCommand = isGlobal
? 'node "$HOME/.claude/hooks/gsd-intel-session.js"'
: 'node .claude/hooks/gsd-intel-session.js';
// PostToolUse hook for indexing
if (!settings.hooks.PostToolUse) {
settings.hooks.PostToolUse = [];
}
const hasIntelIndexHook = settings.hooks.PostToolUse.some(entry =>
entry.hooks && entry.hooks.some(h => h.command && h.command.includes('gsd-intel-index'))
);
if (!hasIntelIndexHook) {
settings.hooks.PostToolUse.push({
hooks: [{
type: 'command',
command: intelIndexCommand
}]
});
console.log(` ${green}✓${reset} Configured intel indexing hook`);
}
// SessionStart hook for context injection
const hasIntelSessionHook = settings.hooks.SessionStart.some(entry =>
entry.hooks && entry.hooks.some(h => h.command && h.command.includes('gsd-intel-session'))
);
if (!hasIntelSessionHook) {
settings.hooks.SessionStart.push({
hooks: [{
type: 'command',
command: intelSessionCommand
}]
});
console.log(` ${green}✓${reset} Configured intel session hook`);
}
// Stop hook for pruning deleted files
const intelPruneCommand = isGlobal
? 'node "$HOME/.claude/hooks/gsd-intel-prune.js"'
: 'node .claude/hooks/gsd-intel-prune.js';
if (!settings.hooks.Stop) {
settings.hooks.Stop = [];
}
const hasIntelPruneHook = settings.hooks.Stop.some(entry =>
entry.hooks && entry.hooks.some(h => h.command && h.command.includes('gsd-intel-prune'))
);
if (!hasIntelPruneHook) {
settings.hooks.Stop.push({
hooks: [{
type: 'command',
command: intelPruneCommand
}]
});
console.log(` ${green}✓${reset} Configured intel prune hook`);
}
return { settingsPath, settings, statuslineCommand };
}

View File

@@ -1,476 +0,0 @@
---
name: gsd:analyze-codebase
description: Scan existing codebase and populate .planning/intel/ with file index, conventions, and semantic entity files
argument-hint: ""
allowed-tools:
- Read
- Bash
- Glob
- Write
- Task
---
<objective>
Scan codebase to populate .planning/intel/ with file index, conventions, and semantic entity files.
Works standalone (without /gsd:new-project) for brownfield codebases. Creates summary.md for context injection at session start. Generates entity files that capture file PURPOSE (what it does, why it exists), not just syntax.
Output: .planning/intel/index.json, conventions.json, summary.md, entities/*.md
</objective>
<context>
This command performs bulk codebase scanning to bootstrap the Codebase Intelligence system.
**Use for:**
- Brownfield projects before /gsd:new-project
- Refreshing intel after major changes
- Standalone intel without full project setup
After initial scan, the PostToolUse hook (hooks/intel-index.js) maintains incremental updates.
**Execution model (Steps 2-3 - Indexing):**
- Orchestrator finds file paths via Glob (Step 2)
- Spawns `gsd-indexer` subagent with file paths only (Step 3)
- Subagent reads files in fresh 200k context, applies regex patterns
- Subagent writes index.json directly to disk
- Subagent returns statistics only (not file contents or index data)
- This prevents context exhaustion on large codebases (500+ files)
**Execution model (Step 9 - Entity Generation):**
- Orchestrator selects files for entity generation (up to 50 based on priority)
- Spawns `gsd-entity-generator` subagent with file list (paths only, not contents)
- Subagent reads files in fresh 200k context, generates entities, writes to disk
- PostToolUse hook automatically syncs entities to graph.db
- Subagent returns statistics only (not entity contents)
- This preserves orchestrator context for large codebases (500+ files)
- Users can skip Step 9 if they only want the index (faster)
</context>
<process>
## Step 1: Create directory structure
```bash
mkdir -p .planning/intel
```
## Step 2: Find all indexable files
Use Glob tool with pattern: `**/*.{js,ts,jsx,tsx,mjs,cjs}`
Exclude directories (skip any path containing):
- node_modules
- dist
- build
- .git
- vendor
- coverage
- .next
- __pycache__
Filter results to remove excluded paths. Store as `file_paths` array.
**Output:** List of absolute file paths for indexing. Do NOT read file contents.
## Step 3: Spawn indexer subagent
Spawn `gsd-indexer` subagent with the file paths from Step 2.
**Why subagent delegation:**
- Orchestrator would exhaust context reading 500+ files inline
- Subagent gets fresh 200k context for file reading
- Orchestrator only handles file paths (small)
- Subagent writes index.json directly (large)
**Task tool invocation:**
```python
file_list = "\n".join(file_paths) # From Step 2 Glob results
Task(
prompt=f"""Index codebase files by extracting exports and imports.
You are a GSD indexer. Read source files and extract exports/imports using regex patterns.
**Parameters:**
- Files to process: {len(file_paths)}
- Output path: .planning/intel/index.json
**Export patterns:**
- Named: export\\s*\\{{([^}}]+)\\}}
- Declaration: export\\s+(?:const|let|var|function\\*?|async\\s+function|class)\\s+(\\w+)
- Default: export\\s+default\\s+(?:function\\s*\\*?\\s*|class\\s+)?(\w+)?
- CommonJS object: module\\.exports\\s*=\\s*\\{{([^}}]+)\\}}
- CommonJS single: module\\.exports\\s*=\\s*(\\w+)\\s*[;\\n]
- TypeScript: export\\s+(?:type|interface)\\s+(\\w+)
**Import patterns:**
- ES6: import\\s+(?:\\{{[^}}]*\\}}|\\*\\s+as\\s+\\w+|\\w+)\\s+from\\s+['\"]([^'\"]+)['\"]
- Side-effect: import\\s+['\"]([^'\"]+)['\"]
- CommonJS: require\\s*\\(\\s*['\"]([^'\"]+)['\"]\\s*\\)
**Index schema:**
```json
{{
"version": 1,
"updated": {{timestamp}},
"files": {{
"/absolute/path/file.js": {{
"exports": ["name1", "name2"],
"imports": ["source1", "source2"],
"indexed": {{timestamp}}
}}
}}
}}
```
**Process:**
For each file path below:
1. Read file content using Read tool
2. Apply export regex patterns, collect export names
3. Apply import regex patterns, collect import sources
4. Store in index structure with absolute path as key
**Files:**
{file_list}
**Return format:**
When complete, return ONLY statistics:
## INDEXING COMPLETE
**Files processed:** {{N}}
**Exports found:** {{M}}
**Imports found:** {{K}}
**Errors:** {{E}}
Index written to: .planning/intel/index.json
Do NOT return index contents.
""",
subagent_type="gsd-indexer"
)
```
**Wait for completion:** Task() blocks until subagent finishes.
**Verify index created:**
```bash
ls -la .planning/intel/index.json
```
## Step 4: Detect conventions
Analyze the collected index for patterns.
**Naming conventions** (require 5+ exports, 70%+ match rate):
- camelCase: `^[a-z][a-z0-9]*(?:[A-Z][a-z0-9]+)+$` or single lowercase `^[a-z][a-z0-9]*$`
- PascalCase: `^[A-Z][a-z0-9]+(?:[A-Z][a-z0-9]+)*$` or single `^[A-Z][a-z0-9]+$`
- snake_case: `^[a-z][a-z0-9]*(?:_[a-z0-9]+)+$`
- SCREAMING_SNAKE: `^[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)+$` or single `^[A-Z][A-Z0-9]*$`
- Skip 'default' when counting (it's a keyword, not naming convention)
**Directory patterns** (use lookup table):
```
components -> UI components
hooks -> React/custom hooks
utils, lib -> Utility functions
services -> Service layer
api, routes -> API endpoints
types -> TypeScript types
models -> Data models
tests, __tests__, test, spec -> Test files
controllers -> Controllers
middleware -> Middleware
config -> Configuration
constants -> Constants
pages -> Page components
views -> View templates
```
**Suffix patterns** (require 5+ occurrences):
```
.test.*, .spec.* -> Test files
.service.* -> Service layer
.controller.* -> Controllers
.model.* -> Data models
.util.*, .utils.* -> Utility functions
.helper.*, .helpers.* -> Helper functions
.config.* -> Configuration
.types.*, .type.* -> TypeScript types
.hook.*, .hooks.* -> React/custom hooks
.context.* -> React context
.store.* -> State store
.slice.* -> Redux slice
.reducer.* -> Redux reducer
.action.*, .actions.* -> Redux actions
.api.* -> API layer
.route.*, .routes.* -> Route definitions
.middleware.* -> Middleware
.schema.* -> Schema definitions
.mock.*, .mocks.* -> Mock data
.fixture.*, .fixtures.* -> Test fixtures
```
## Step 5: Read index.json
The `gsd-indexer` subagent wrote index.json in Step 3. Read it back for convention detection and statistics.
```bash
cat .planning/intel/index.json
```
Expected schema:
```json
{
"version": 1,
"updated": 1737360330000,
"files": {
"/absolute/path/to/file.js": {
"exports": ["functionA", "ClassB"],
"imports": ["react", "./utils"],
"indexed": 1737360330000
}
}
}
```
## Step 6: Write conventions.json
Write to `.planning/intel/conventions.json`:
```javascript
{
"version": 1,
"updated": 1737360330000,
"naming": {
"exports": {
"dominant": "camelCase",
"count": 42,
"percentage": 85
}
},
"directories": {
"components": { "purpose": "UI components", "files": 15 },
"hooks": { "purpose": "React/custom hooks", "files": 8 }
},
"suffixes": {
".test.js": { "purpose": "Test files", "count": 12 }
}
}
```
## Step 7: Generate summary.md
Write to `.planning/intel/summary.md`:
```markdown
# Codebase Intelligence Summary
Last updated: [ISO timestamp]
Indexed files: [N]
## Naming Conventions
- Export naming: [case] ([percentage]% of [count] exports)
## Key Directories
- `[dir]/`: [purpose] ([N] files)
- ... (top 5)
## File Patterns
- `*[suffix]`: [purpose] ([count] files)
- ... (top 3)
Total exports: [N]
```
Target: < 500 tokens. Keep concise for context injection.
## Step 8: Report completion
Display summary statistics:
```
Codebase Analysis Complete
Files indexed: [N]
Exports found: [N]
Imports found: [N]
Conventions detected:
- Naming: [dominant case] ([percentage]%)
- Directories: [list]
- Patterns: [list]
Files created:
- .planning/intel/index.json
- .planning/intel/conventions.json
- .planning/intel/summary.md
```
## Step 9: Generate semantic entities (optional)
Generate entity files that capture semantic understanding of key files. These provide PURPOSE, not just syntax.
**Skip this step if:** User only wants the index, or codebase has < 10 files.
### 9.1 Create entities directory
```bash
mkdir -p .planning/intel/entities
```
### 9.2 Select files for entity generation
Select up to 50 files based on these criteria (in priority order):
1. **High-export files:** 3+ exports (likely core modules)
2. **Hub files:** Referenced by 5+ other files (via imports analysis)
3. **Key directories:** Entry points (index.js, main.js, app.js), config files
4. **Structural files:** Files matching convention patterns (services, controllers, models)
From the index.json, identify candidates and limit to 50 files maximum per run.
### 9.3 Spawn entity generator subagent
Spawn `gsd-entity-generator` with the selected file list.
**Pass to subagent:**
- Total file count
- Output directory: `.planning/intel/entities/`
- Slug convention: `src/lib/db.ts` -> `src-lib-db` (replace / with -, remove extension, lowercase)
- Entity template (include full template from agent definition)
- List of absolute file paths (one per line)
**Task tool invocation:**
```python
# Build file list (one absolute path per line)
file_list = "\n".join(selected_files)
today = date.today().isoformat()
Task(
prompt=f"""Generate semantic entity documentation for key codebase files.
You are a GSD entity generator. Read source files and create semantic documentation that captures PURPOSE (what/why), not just syntax.
**Parameters:**
- Files to process: {len(selected_files)}
- Output directory: .planning/intel/entities/
- Date: {today}
**Slug convention:**
- Remove leading /
- Remove file extension
- Replace / and . with -
- Lowercase everything
- Example: src/lib/db.ts -> src-lib-db
**Entity template:**
```markdown
---
path: {{absolute_path}}
type: [module|component|util|config|api|hook|service|model|test]
updated: {today}
status: active
---
# {{filename}}
## Purpose
[1-3 sentences: What does this file do? Why does it exist? What problem does it solve?]
## Exports
- `functionName(params): ReturnType` - Brief description
- `ClassName` - What this class represents
If no exports: "None"
## Dependencies
- [[internal-file-slug]] - Why needed (for internal deps)
- external-package - What it provides (for npm packages)
If no dependencies: "None"
## Used By
TBD
```
**Process:**
For each file path below:
1. Read file content using Read tool
2. Analyze purpose, exports, dependencies
3. Check if entity already exists (skip if so)
4. Write entity to .planning/intel/entities/{{slug}}.md
5. PostToolUse hook syncs to graph.db automatically
**Files:**
{file_list}
**Return format:**
When complete, return ONLY statistics:
## ENTITY GENERATION COMPLETE
**Files processed:** {{N}}
**Entities created:** {{M}}
**Already existed:** {{K}}
**Errors:** {{E}}
Entities written to: .planning/intel/entities/
Do NOT include entity contents in your response.
""",
subagent_type="gsd-entity-generator"
)
```
**Wait for completion:** Task() blocks until subagent finishes.
**Parse result:** Extract entities_created count from response for final report.
### 9.4 Verify entity generation
Confirm entities were written:
```bash
ls .planning/intel/entities/*.md 2>/dev/null | wc -l
```
### 9.5 Report entity statistics
```
Entity Generation Complete
Entity files created: [N] (from subagent response)
Location: .planning/intel/entities/
Graph database: Updated automatically via PostToolUse hook
Next: Intel hooks will continue incremental updates as you code.
```
</process>
<output>
- .planning/intel/index.json - File index with exports and imports
- .planning/intel/conventions.json - Detected naming and structural patterns
- .planning/intel/summary.md - Concise summary for context injection
- .planning/intel/entities/*.md - Semantic entity files (optional, Step 9)
</output>
<success_criteria>
- [ ] .planning/intel/ directory created
- [ ] All JS/TS files scanned (excluding node_modules, dist, build, .git, vendor, coverage)
- [ ] index.json populated with exports and imports for each file
- [ ] conventions.json has detected patterns (naming, directories, suffixes)
- [ ] summary.md is concise (< 500 tokens)
- [ ] Statistics reported to user
- [ ] Entity files generated for key files (if Step 9 executed)
- [ ] Entity files contain Purpose section with semantic understanding
</success_criteria>

View File

@@ -76,17 +76,6 @@ Map an existing codebase for brownfield projects.
Usage: `/gsd:map-codebase`
**`/gsd:analyze-codebase`**
Bootstrap codebase intelligence for existing projects.
- Scans all JS/TS files and extracts exports/imports
- Detects naming conventions, directory patterns, file suffixes
- Creates `.planning/intel/` with index, conventions, and summary
- Works standalone (no `/gsd:new-project` required)
- After initial scan, PostToolUse hook continues incremental learning
Usage: `/gsd:analyze-codebase`
### Phase Planning
**`/gsd:discuss-phase <number>`**
@@ -339,19 +328,6 @@ Quick switch model profile for GSD agents.
Usage: `/gsd:set-profile budget`
### Codebase Intelligence
**`/gsd:query-intel <type> [path]`**
Query the codebase intelligence graph database.
- `dependents <file>` — What files depend on this? (blast radius)
- `hotspots` — Which files have the most dependents?
Requires `/gsd:analyze-codebase` to build the graph first.
Usage: `/gsd:query-intel dependents src/lib/db.ts`
Usage: `/gsd:query-intel hotspots`
### Utility Commands
**`/gsd:help`**
@@ -389,10 +365,6 @@ Usage: `/gsd:update`
│ └── done/ # Completed todos
├── debug/ # Active debug sessions
│ └── resolved/ # Archived resolved issues
├── intel/ # Codebase intelligence (auto-populated)
│ ├── index.json # File exports and imports
│ ├── conventions.json # Detected patterns
│ └── summary.md # Context for session injection
├── codebase/ # Codebase map (brownfield projects)
│ ├── STACK.md # Languages, frameworks, dependencies
│ ├── ARCHITECTURE.md # Patterns, layers, data flow

View File

@@ -19,7 +19,6 @@ This is the most leveraged moment in any project. Deep questioning here means be
- `.planning/PROJECT.md` — project context
- `.planning/config.json` — workflow preferences
- `.planning/research/` — domain research (optional)
- `.planning/intel/` — codebase intelligence (auto-populated by hooks)
- `.planning/REQUIREMENTS.md` — scoped requirements
- `.planning/ROADMAP.md` — phase structure
- `.planning/STATE.md` — project memory
@@ -58,14 +57,7 @@ This is the most leveraged moment in any project. Deep questioning here means be
fi
```
3. **Create intel directory for codebase intelligence:**
```bash
mkdir -p .planning/intel
```
This prepares the directory for the PostToolUse hook to populate with index.json, conventions.json, and summary.md as Claude writes code.
4. **Detect existing code (brownfield detection):**
3. **Detect existing code (brownfield detection):**
```bash
CODE_FILES=$(find . -name "*.ts" -o -name "*.js" -o -name "*.py" -o -name "*.go" -o -name "*.rs" -o -name "*.swift" -o -name "*.java" 2>/dev/null | grep -v node_modules | grep -v .git | head -20)
HAS_PACKAGE=$([ -f package.json ] || [ -f requirements.txt ] || [ -f Cargo.toml ] || [ -f go.mod ] || [ -f Package.swift ] && echo "yes")
@@ -365,7 +357,7 @@ Create `.planning/config.json` with all settings:
- Add `.planning/` to `.gitignore` (create if needed)
**If commit_docs = Yes:**
- Add `.planning/intel/` to `.gitignore` (intel is always local — changes constantly, can be regenerated)
- No additional gitignore entries needed
**Commit config.json:**
@@ -981,7 +973,6 @@ Present completion with next steps:
- `ARCHITECTURE.md`
- `PITFALLS.md`
- `SUMMARY.md`
- `.planning/intel/` (created empty, populated by hooks during coding)
- `.planning/REQUIREMENTS.md`
- `.planning/ROADMAP.md`
- `.planning/STATE.md`

View File

@@ -249,9 +249,6 @@ RESEARCH_CONTENT=$(cat "${PHASE_DIR}"/*-RESEARCH.md 2>/dev/null)
# Gap closure files (only if --gaps mode)
VERIFICATION_CONTENT=$(cat "${PHASE_DIR}"/*-VERIFICATION.md 2>/dev/null)
UAT_CONTENT=$(cat "${PHASE_DIR}"/*-UAT.md 2>/dev/null)
# Codebase intelligence (if exists)
INTEL_CONTENT=$(cat .planning/intel/summary.md 2>/dev/null)
```
## 8. Spawn gsd-planner Agent
@@ -292,11 +289,6 @@ Fill prompt with inlined content and spawn:
{verification_content}
{uat_content}
**Codebase Intel (if exists):**
<codebase-intel>
{intel_content}
</codebase-intel>
</planning_context>
<downstream_consumer>

View File

@@ -1,128 +0,0 @@
---
name: gsd:query-intel
description: Query codebase intelligence graph for dependencies and hotspots
argument-hint: "<dependents|hotspots> [file-path]"
allowed-tools:
- Bash
---
<objective>
Query the codebase intelligence graph database for relationship information.
**Query types:**
- `dependents <file>` — What files depend on this file? (blast radius)
- `hotspots` — Which files have the most dependents? (change carefully)
Output: Formatted query results from graph.db
</objective>
<context>
This command exposes the graph query capabilities built by Phase 4 (Semantic Intelligence).
**Use for:**
- Checking blast radius before refactoring a core file
- Identifying high-impact files that need careful changes
- Understanding dependency relationships in the codebase
**Requires:** `.planning/intel/graph.db` (created by `/gsd:analyze-codebase` with entity generation)
If graph.db doesn't exist, the command will return an error suggesting to run analyze-codebase first.
</context>
<process>
## Step 1: Parse arguments
Extract query type and optional file path from arguments.
**Arguments:** $ARGUMENTS
**Expected formats:**
- `dependents src/lib/db.ts` — query what depends on this file
- `hotspots` — query most-depended-on files
- `hotspots 10` — query top 10 hotspots (default: 5)
## Step 2: Convert file path to entity ID
For `dependents` queries, convert the file path to entity ID format:
- `src/lib/db.ts` → `src-lib-db`
- Replace `/` with `-`, remove extension
```bash
# Example conversion
FILE_PATH="src/lib/db.ts"
ENTITY_ID=$(echo "$FILE_PATH" | sed 's/\.[^.]*$//' | tr '/' '-')
```
## Step 3: Execute query
Run the appropriate query against the graph database:
**For dependents:**
```bash
echo '{"action":"query","type":"dependents","target":"'$ENTITY_ID'","limit":20}' | node hooks/gsd-intel-index.js
```
**For hotspots:**
```bash
echo '{"action":"query","type":"hotspots","limit":5}' | node hooks/gsd-intel-index.js
```
## Step 4: Format and present results
Parse the JSON response and present in readable format.
**For dependents:**
```
## Files that depend on {file-path}
Found {count} dependents:
1. src/api/users.ts
2. src/api/auth.ts
3. src/services/payment.ts
...
**Blast radius:** {count} files would be affected by changes.
```
**For hotspots:**
```
## Dependency Hotspots
These files have the most dependents — change carefully:
| Rank | File | Dependents |
|------|------|------------|
| 1 | src/lib/db.ts | 42 |
| 2 | src/types/user.ts | 35 |
| 3 | src/utils/format.ts | 28 |
```
## Step 5: Handle errors
**If graph.db doesn't exist:**
```
No graph database found at .planning/intel/graph.db
Run /gsd:analyze-codebase first to build the dependency graph.
```
**If entity not found:**
```
No entity found for: {file-path}
The file may not be indexed yet. Try:
- /gsd:analyze-codebase to rebuild the index
- Check the file path is correct
```
</process>
<success_criteria>
- [ ] Query type parsed from arguments
- [ ] File path converted to entity ID (for dependents)
- [ ] Query executed against graph.db
- [ ] Results formatted in readable markdown
- [ ] Errors handled gracefully with helpful messages
</success_criteria>

View File

@@ -1,173 +0,0 @@
# Entity Template
Template for `.planning/codebase/{entity-slug}.md` - file-level intelligence documentation.
---
## File Template
```markdown
---
path: {path}
type: {type}
updated: {updated}
status: {status}
---
# {filename}
## Purpose
{purpose}
## Exports
{exports}
## Dependencies
{dependencies}
## Used By
{used_by}
## Notes
{notes}
```
---
## Field Reference
### Frontmatter
| Field | Values | Description |
|-------|--------|-------------|
| `path` | Absolute path | Full path to the file |
| `type` | module, component, util, config, test, api, hook | Primary classification |
| `updated` | YYYY-MM-DD | Last time this entity was updated |
| `status` | active, deprecated, stub | Current state |
### Sections
**Purpose** (required)
1-3 sentences covering:
- What this file does
- Why it exists
- Who/what uses it (high-level)
**Exports** (required for modules with exports)
List each export with signature and description:
```markdown
- `functionName(arg: Type): ReturnType` - What it does
- `ClassName` - What it represents
- `CONSTANT_NAME` - What value it holds
```
For files without exports (config, tests), write "None" or describe what the file defines.
**Dependencies** (required)
Internal dependencies use wiki-links (slugified paths):
```markdown
- [[src-lib-db]] - Database client
- [[src-types-user]] - User type definitions
```
External dependencies use plain text:
```markdown
- react - Component framework
- jose - JWT handling
```
**Used By** (grows over time)
Files that import this one, using wiki-links:
```markdown
- [[src-app-api-auth-route]]
- [[src-components-dashboard]]
```
Initially may be empty or incomplete. Updated as Claude encounters imports.
**Notes** (optional)
Patterns, gotchas, or context:
```markdown
- Uses singleton pattern for connection pooling
- WARNING: Must call `init()` before any other method
- Related: See [[src-lib-cache]] for caching layer
```
---
## Slug Convention
Entity slugs are derived from file paths:
- `src/lib/db.ts` becomes `src-lib-db`
- `src/app/api/auth/route.ts` becomes `src-app-api-auth-route`
Rule: Replace `/` and `.` with `-`, drop file extension.
---
## Example
```markdown
---
path: /project/src/lib/auth.ts
type: util
updated: 2025-01-15
status: active
---
# auth.ts
## Purpose
JWT token management using jose library. Handles token creation, verification, and refresh rotation. Used by all protected API routes via middleware.
## Exports
- `createAccessToken(userId: string): Promise<string>` - Creates 15-min access token
- `createRefreshToken(userId: string): Promise<string>` - Creates 7-day refresh token
- `verifyToken(token: string): Promise<TokenPayload>` - Validates and decodes token
- `rotateRefresh(oldToken: string): Promise<TokenPair>` - Issues new token pair
## Dependencies
- [[src-lib-db]] - Stores refresh tokens for revocation
- [[src-types-auth]] - TokenPayload, TokenPair types
- jose - JWT signing and verification
- bcrypt - Password hashing
## Used By
- [[src-middleware]]
- [[src-app-api-auth-login-route]]
- [[src-app-api-auth-logout-route]]
- [[src-app-api-auth-refresh-route]]
## Notes
- Access tokens are stateless; refresh tokens stored in DB for revocation
- Uses RS256 algorithm with keys from environment
- WARNING: Never log token values, even in debug mode
```
---
## Guidelines
**When to create/update:**
- After modifying a file during plan execution
- When encountering a file that lacks documentation
- When relationships change (new imports, exports)
**Minimal viable entity:**
At minimum, an entity needs frontmatter + Purpose. Other sections can be "TBD" if unknown.
**Accuracy over completeness:**
Better to have partial accurate info than complete guesses. Mark unknowns explicitly.
**Link discovery:**
The hook that processes entities extracts all `[[wiki-links]]` to build the relationship graph. Ensure links use correct slug format.

View File

@@ -598,8 +598,7 @@ Execute each task in the prompt. **Deviations are normal** - handle them automat
- Continue implementing, applying rules as needed
- Run the verification
- Confirm done criteria met
- **Update intel entities** for modified files (see `<update_intel_entity>` below)
- **Commit the task** (see `<task_commit>` below) - includes entity files in commit
- **Commit the task** (see `<task_commit>` below)
- Track task completion and commit hash for Summary documentation
- Continue to next task
@@ -928,148 +927,6 @@ None - plan executed exactly as written.
</deviation_documentation>
<update_intel_entity>
## Update Codebase Intelligence Entity
**Trigger:** After each task's `<done>` criteria met, BEFORE committing.
This step documents your understanding of modified files. The knowledge base self-evolves as you work.
**1. Get files from the just-completed task:**
Check the task's `<files>` list. If no `<files>` attribute, use `git status --short` to identify modified files.
**2. For each file, determine if significant:**
**Skip these patterns (not worth indexing):**
```bash
# Build/generated
node_modules/*, .next/*, dist/*, build/*, .git/*
# Tests (their targets are more valuable)
*.test.*, *.spec.*, __tests__/*, __mocks__/*
# Config files (change rarely, low context value)
package.json, package-lock.json, tsconfig.json, *.config.*, *.config.js, *.config.ts
# Environment and locks
.env*, *.lock, *.log, yarn.lock, pnpm-lock.yaml
```
If file matches skip pattern: continue to next file.
**3. Derive entity path:**
```bash
# Convert file path to entity filename
# src/lib/auth.ts → src-lib-auth.md
# app/api/users/route.ts → app-api-users-route.md
FILE_PATH="$1"
ENTITY_NAME=$(echo "$FILE_PATH" | sed 's|^[./]*||' | tr '/' '-' | sed 's/\.[^.]*$//')
ENTITY_PATH=".planning/intel/entities/${ENTITY_NAME}.md"
```
**4. Create intel directory if needed:**
```bash
mkdir -p .planning/intel/entities
```
**5. Check if entity exists:**
```bash
if [ -f "$ENTITY_PATH" ]; then
ACTION="update"
else
ACTION="create"
fi
```
**6. Create or update entity:**
Use template from `~/.claude/get-shit-done/templates/entity.md`.
Fill fields based on what you just built:
| Field | Source |
|-------|--------|
| `path` | Absolute path to file |
| `type` | Infer: module, component, util, config, api, hook |
| `updated` | Today's date (YYYY-MM-DD) |
| `status` | active (unless you're deprecating) |
| **Purpose** | What you understand this file does |
| **Exports** | Extract from the code you just wrote |
| **Dependencies** | `[[slugified-path]]` for internal, plain for external |
| **Used By** | Add callers if you know them from this session |
| **Notes** | Gotchas, patterns, warnings discovered |
**If updating existing entity:**
- Read current content first
- Preserve Used By entries you didn't touch
- Update sections that changed
- Don't remove information unless it's wrong
**7. Write entity file:**
```bash
# Write the entity content
cat > "$ENTITY_PATH" << 'EOF'
---
path: {path}
type: {type}
updated: {today}
status: active
---
# {filename}
## Purpose
{purpose}
## Exports
{exports}
## Dependencies
{dependencies}
## Used By
{used_by}
## Notes
{notes}
EOF
```
**8. Verify entity was created/updated:**
```bash
head -10 "$ENTITY_PATH"
```
**9. Stage entity file:**
Entity files are staged along with task code files in the task commit.
```bash
git add "$ENTITY_PATH"
```
**Error handling:**
- If entity creation fails: Log warning, continue to task_commit
- Entity update is NOT blocking - a failed entity shouldn't stop code from being committed
- Log: `"Warning: Could not update entity for {file}: {reason}"`
**Target size:** Keep entities concise (30-50 lines). Purpose and Exports are most valuable.
</update_intel_entity>
<tdd_plan_execution>
## TDD Plan Execution

File diff suppressed because it is too large Load Diff

View File

@@ -1,78 +0,0 @@
#!/usr/bin/env node
/**
* Intel Prune Hook (Stop event)
*
* Removes stale entries from index.json when files no longer exist.
* Runs after each Claude response to keep intel fresh.
*
* Fast: Only does fs.existsSync checks, no file reading.
* Silent: Never blocks or errors, always exits 0.
*/
const fs = require('fs');
const path = require('path');
function pruneIndex() {
const intelDir = path.join(process.cwd(), '.planning', 'intel');
const indexPath = path.join(intelDir, 'index.json');
// Only run if intel directory exists (opt-in check)
if (!fs.existsSync(intelDir)) {
return { pruned: 0, total: 0 };
}
// Read existing index
let index;
try {
const content = fs.readFileSync(indexPath, 'utf8');
index = JSON.parse(content);
} catch (e) {
// No index or invalid JSON
return { pruned: 0, total: 0 };
}
if (!index.files || typeof index.files !== 'object') {
return { pruned: 0, total: 0 };
}
// Check each file and collect deleted ones
const filePaths = Object.keys(index.files);
const deleted = filePaths.filter(filePath => !fs.existsSync(filePath));
if (deleted.length === 0) {
return { pruned: 0, total: filePaths.length };
}
// Remove deleted entries
for (const filePath of deleted) {
delete index.files[filePath];
}
index.updated = Date.now();
// Write updated index
fs.writeFileSync(indexPath, JSON.stringify(index, null, 2));
// Regenerate conventions and summary after pruning
// Import detection logic from intel-index.js would be complex,
// so we just update the index. Conventions/summary stay until
// next PostToolUse or /gsd:analyze-codebase refresh.
return { pruned: deleted.length, total: filePaths.length };
}
// Read JSON from stdin (standard hook pattern)
let input = '';
process.stdin.setEncoding('utf8');
process.stdin.on('data', chunk => input += chunk);
process.stdin.on('end', () => {
try {
// Stop hook receives session data, but we don't need it
// Just prune stale entries
pruneIndex();
process.exit(0);
} catch (error) {
// Silent failure - never block Claude
process.exit(0);
}
});

View File

@@ -1,39 +0,0 @@
#!/usr/bin/env node
// Codebase Intelligence - SessionStart Context Injection Hook
// Reads pre-generated summary.md and injects into Claude's context
const fs = require('fs');
const path = require('path');
// Read JSON from stdin (standard hook pattern)
let input = '';
process.stdin.setEncoding('utf8');
process.stdin.on('data', chunk => input += chunk);
process.stdin.on('end', () => {
try {
const data = JSON.parse(input);
// Only inject on startup or resume
if (!['startup', 'resume'].includes(data.source)) {
process.exit(0);
}
// Read pre-generated summary (created by gsd-intel-index.js)
const summaryPath = path.join(process.cwd(), '.planning', 'intel', 'summary.md');
if (!fs.existsSync(summaryPath)) {
process.exit(0); // No intel, skip silently
}
const summary = fs.readFileSync(summaryPath, 'utf8').trim();
if (summary) {
process.stdout.write(`<codebase-intelligence>\n${summary}\n</codebase-intelligence>`);
}
process.exit(0);
} catch (error) {
// Silent failure - never block Claude
process.exit(0);
}
});

View File

@@ -36,8 +36,7 @@
},
"dependencies": {},
"devDependencies": {
"esbuild": "^0.24.0",
"sql.js": "^1.12.0"
"esbuild": "^0.24.0"
},
"scripts": {
"build:hooks": "node scripts/build-hooks.js",

View File

@@ -1,77 +1,27 @@
#!/usr/bin/env node
/**
* Bundle GSD hooks with dependencies for zero-config installation.
*
* sql.js includes a WASM binary that must be inlined for portability.
* This script bundles hooks into self-contained files that work from any cwd.
* Copy GSD hooks to dist for installation.
*/
const esbuild = require('esbuild');
const fs = require('fs');
const path = require('path');
const HOOKS_DIR = path.join(__dirname, '..', 'hooks');
const DIST_DIR = path.join(HOOKS_DIR, 'dist');
// Hooks that need bundling (have npm dependencies)
const HOOKS_TO_BUNDLE = [
'gsd-intel-index.js'
];
// Hooks that are pure Node.js (just copy)
// Hooks to copy (pure Node.js, no bundling needed)
const HOOKS_TO_COPY = [
'gsd-intel-session.js',
'gsd-intel-prune.js',
'gsd-check-update.js',
'gsd-statusline.js'
];
async function build() {
function build() {
// Ensure dist directory exists
if (!fs.existsSync(DIST_DIR)) {
fs.mkdirSync(DIST_DIR, { recursive: true });
}
// Bundle hooks with dependencies
for (const hook of HOOKS_TO_BUNDLE) {
const entryPoint = path.join(HOOKS_DIR, hook);
const outfile = path.join(DIST_DIR, hook);
if (!fs.existsSync(entryPoint)) {
console.warn(`Warning: ${hook} not found, skipping`);
continue;
}
console.log(`Bundling ${hook}...`);
await esbuild.build({
entryPoints: [entryPoint],
bundle: true,
platform: 'node',
target: 'node18',
outfile,
format: 'cjs',
// Inline WASM as base64 for sql.js
loader: {
'.wasm': 'binary'
},
// Don't externalize anything - bundle it all
external: [],
// Minify for smaller package size
minify: true,
// Keep function names for debugging
keepNames: true,
// Handle sql.js WASM loading
define: {
'process.env.NODE_ENV': '"production"'
}
// Note: shebang preserved from source file by esbuild
});
console.log(` → ${outfile}`);
}
// Copy pure Node.js hooks (no bundling needed)
// Copy hooks to dist
for (const hook of HOOKS_TO_COPY) {
const src = path.join(HOOKS_DIR, hook);
const dest = path.join(DIST_DIR, hook);
@@ -89,7 +39,4 @@ async function build() {
console.log('\nBuild complete.');
}
build().catch(err => {
console.error('Build failed:', err);
process.exit(1);
});
build();