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]
|
## [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
|
## [1.9.0] - 2025-01-20
|
||||||
|
|
||||||
### Added
|
### 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
|
- **Model Profiles** — `/gsd:set-profile` for quality/balanced/budget agent configurations
|
||||||
- **Workflow Settings** — `/gsd:settings` command for toggling workflow behaviors interactively
|
- **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
|
### Fixed
|
||||||
- Orchestrators now inline file contents in Task prompts (fixes context issues with @ references)
|
- Orchestrators now inline file contents in Task prompts (fixes context issues with @ references)
|
||||||
- Tech debt from milestone audit addressed
|
- 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
|
## Summary: Core Meta-Patterns
|
||||||
|
|
||||||
1. **XML for semantic structure, Markdown for content**
|
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
|
## 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
|
### Context Engineering
|
||||||
|
|
||||||
Claude Code is incredibly powerful *if* you give it the context it needs. Most people don't.
|
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 |
|
| Command | What it does |
|
||||||
|---------|--------------|
|
|---------|--------------|
|
||||||
| `/gsd:map-codebase` | Analyze existing codebase before new-project |
|
| `/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
|
### 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.
|
Store `COMMIT_PLANNING_DOCS` for use in git operations.
|
||||||
</step>
|
</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">
|
<step name="load_plan">
|
||||||
Read the plan file provided in your prompt context.
|
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/ROADMAP.md
|
||||||
@.planning/STATE.md
|
@.planning/STATE.md
|
||||||
|
|
||||||
# Codebase intelligence (if exists)
|
|
||||||
@.planning/intel/summary.md
|
|
||||||
|
|
||||||
# Only reference prior plan SUMMARYs if genuinely needed
|
# Only reference prior plan SUMMARYs if genuinely needed
|
||||||
@path/to/relevant/source.ts
|
@path/to/relevant/source.ts
|
||||||
</context>
|
</context>
|
||||||
@@ -1039,25 +1036,6 @@ If exists, load relevant documents based on phase type:
|
|||||||
| (default) | STACK.md, ARCHITECTURE.md |
|
| (default) | STACK.md, ARCHITECTURE.md |
|
||||||
</step>
|
</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">
|
<step name="identify_phase">
|
||||||
Check roadmap and existing phases:
|
Check roadmap and existing phases:
|
||||||
|
|
||||||
|
|||||||
@@ -418,72 +418,6 @@ function install(isGlobal) {
|
|||||||
console.log(` ${green}✓${reset} Configured update check hook`);
|
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 };
|
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`
|
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
|
### Phase Planning
|
||||||
|
|
||||||
**`/gsd:discuss-phase <number>`**
|
**`/gsd:discuss-phase <number>`**
|
||||||
@@ -339,19 +328,6 @@ Quick switch model profile for GSD agents.
|
|||||||
|
|
||||||
Usage: `/gsd:set-profile budget`
|
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
|
### Utility Commands
|
||||||
|
|
||||||
**`/gsd:help`**
|
**`/gsd:help`**
|
||||||
@@ -389,10 +365,6 @@ Usage: `/gsd:update`
|
|||||||
│ └── done/ # Completed todos
|
│ └── done/ # Completed todos
|
||||||
├── debug/ # Active debug sessions
|
├── debug/ # Active debug sessions
|
||||||
│ └── resolved/ # Archived resolved issues
|
│ └── 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)
|
├── codebase/ # Codebase map (brownfield projects)
|
||||||
│ ├── STACK.md # Languages, frameworks, dependencies
|
│ ├── STACK.md # Languages, frameworks, dependencies
|
||||||
│ ├── ARCHITECTURE.md # Patterns, layers, data flow
|
│ ├── 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/PROJECT.md` — project context
|
||||||
- `.planning/config.json` — workflow preferences
|
- `.planning/config.json` — workflow preferences
|
||||||
- `.planning/research/` — domain research (optional)
|
- `.planning/research/` — domain research (optional)
|
||||||
- `.planning/intel/` — codebase intelligence (auto-populated by hooks)
|
|
||||||
- `.planning/REQUIREMENTS.md` — scoped requirements
|
- `.planning/REQUIREMENTS.md` — scoped requirements
|
||||||
- `.planning/ROADMAP.md` — phase structure
|
- `.planning/ROADMAP.md` — phase structure
|
||||||
- `.planning/STATE.md` — project memory
|
- `.planning/STATE.md` — project memory
|
||||||
@@ -58,14 +57,7 @@ This is the most leveraged moment in any project. Deep questioning here means be
|
|||||||
fi
|
fi
|
||||||
```
|
```
|
||||||
|
|
||||||
3. **Create intel directory for codebase intelligence:**
|
3. **Detect existing code (brownfield detection):**
|
||||||
```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):**
|
|
||||||
```bash
|
```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)
|
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")
|
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)
|
- Add `.planning/` to `.gitignore` (create if needed)
|
||||||
|
|
||||||
**If commit_docs = Yes:**
|
**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:**
|
**Commit config.json:**
|
||||||
|
|
||||||
@@ -981,7 +973,6 @@ Present completion with next steps:
|
|||||||
- `ARCHITECTURE.md`
|
- `ARCHITECTURE.md`
|
||||||
- `PITFALLS.md`
|
- `PITFALLS.md`
|
||||||
- `SUMMARY.md`
|
- `SUMMARY.md`
|
||||||
- `.planning/intel/` (created empty, populated by hooks during coding)
|
|
||||||
- `.planning/REQUIREMENTS.md`
|
- `.planning/REQUIREMENTS.md`
|
||||||
- `.planning/ROADMAP.md`
|
- `.planning/ROADMAP.md`
|
||||||
- `.planning/STATE.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)
|
# Gap closure files (only if --gaps mode)
|
||||||
VERIFICATION_CONTENT=$(cat "${PHASE_DIR}"/*-VERIFICATION.md 2>/dev/null)
|
VERIFICATION_CONTENT=$(cat "${PHASE_DIR}"/*-VERIFICATION.md 2>/dev/null)
|
||||||
UAT_CONTENT=$(cat "${PHASE_DIR}"/*-UAT.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
|
## 8. Spawn gsd-planner Agent
|
||||||
@@ -292,11 +289,6 @@ Fill prompt with inlined content and spawn:
|
|||||||
{verification_content}
|
{verification_content}
|
||||||
{uat_content}
|
{uat_content}
|
||||||
|
|
||||||
**Codebase Intel (if exists):**
|
|
||||||
<codebase-intel>
|
|
||||||
{intel_content}
|
|
||||||
</codebase-intel>
|
|
||||||
|
|
||||||
</planning_context>
|
</planning_context>
|
||||||
|
|
||||||
<downstream_consumer>
|
<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
|
- Continue implementing, applying rules as needed
|
||||||
- Run the verification
|
- Run the verification
|
||||||
- Confirm done criteria met
|
- Confirm done criteria met
|
||||||
- **Update intel entities** for modified files (see `<update_intel_entity>` below)
|
- **Commit the task** (see `<task_commit>` below)
|
||||||
- **Commit the task** (see `<task_commit>` below) - includes entity files in commit
|
|
||||||
- Track task completion and commit hash for Summary documentation
|
- Track task completion and commit hash for Summary documentation
|
||||||
- Continue to next task
|
- Continue to next task
|
||||||
|
|
||||||
@@ -928,148 +927,6 @@ None - plan executed exactly as written.
|
|||||||
|
|
||||||
</deviation_documentation>
|
</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>
|
||||||
## 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": {},
|
"dependencies": {},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"esbuild": "^0.24.0",
|
"esbuild": "^0.24.0"
|
||||||
"sql.js": "^1.12.0"
|
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build:hooks": "node scripts/build-hooks.js",
|
"build:hooks": "node scripts/build-hooks.js",
|
||||||
|
|||||||
@@ -1,77 +1,27 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
/**
|
/**
|
||||||
* Bundle GSD hooks with dependencies for zero-config installation.
|
* Copy GSD hooks to dist for 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.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const esbuild = require('esbuild');
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
const HOOKS_DIR = path.join(__dirname, '..', 'hooks');
|
const HOOKS_DIR = path.join(__dirname, '..', 'hooks');
|
||||||
const DIST_DIR = path.join(HOOKS_DIR, 'dist');
|
const DIST_DIR = path.join(HOOKS_DIR, 'dist');
|
||||||
|
|
||||||
// Hooks that need bundling (have npm dependencies)
|
// Hooks to copy (pure Node.js, no bundling needed)
|
||||||
const HOOKS_TO_BUNDLE = [
|
|
||||||
'gsd-intel-index.js'
|
|
||||||
];
|
|
||||||
|
|
||||||
// Hooks that are pure Node.js (just copy)
|
|
||||||
const HOOKS_TO_COPY = [
|
const HOOKS_TO_COPY = [
|
||||||
'gsd-intel-session.js',
|
|
||||||
'gsd-intel-prune.js',
|
|
||||||
'gsd-check-update.js',
|
'gsd-check-update.js',
|
||||||
'gsd-statusline.js'
|
'gsd-statusline.js'
|
||||||
];
|
];
|
||||||
|
|
||||||
async function build() {
|
function build() {
|
||||||
// Ensure dist directory exists
|
// Ensure dist directory exists
|
||||||
if (!fs.existsSync(DIST_DIR)) {
|
if (!fs.existsSync(DIST_DIR)) {
|
||||||
fs.mkdirSync(DIST_DIR, { recursive: true });
|
fs.mkdirSync(DIST_DIR, { recursive: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bundle hooks with dependencies
|
// Copy hooks to dist
|
||||||
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)
|
|
||||||
for (const hook of HOOKS_TO_COPY) {
|
for (const hook of HOOKS_TO_COPY) {
|
||||||
const src = path.join(HOOKS_DIR, hook);
|
const src = path.join(HOOKS_DIR, hook);
|
||||||
const dest = path.join(DIST_DIR, hook);
|
const dest = path.join(DIST_DIR, hook);
|
||||||
@@ -89,7 +39,4 @@ async function build() {
|
|||||||
console.log('\nBuild complete.');
|
console.log('\nBuild complete.');
|
||||||
}
|
}
|
||||||
|
|
||||||
build().catch(err => {
|
build();
|
||||||
console.error('Build failed:', err);
|
|
||||||
process.exit(1);
|
|
||||||
});
|
|
||||||
|
|||||||
Reference in New Issue
Block a user