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:
21
CHANGELOG.md
21
CHANGELOG.md
@@ -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
|
||||
|
||||
64
GSD-STYLE.md
64
GSD-STYLE.md
@@ -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**
|
||||
|
||||
46
README.md
46
README.md
@@ -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
|
||||
|
||||
|
||||
@@ -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>
|
||||
@@ -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.
|
||||
|
||||
@@ -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>
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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 };
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
@@ -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
|
||||
|
||||
@@ -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`
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
@@ -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.
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
});
|
||||
@@ -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);
|
||||
}
|
||||
});
|
||||
@@ -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",
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user