agentic-compaction 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.orchestration/orchestration.md +52 -0
- package/.orchestration/workflows/react/bugfix.md +32 -0
- package/.orchestration/workflows/react/docs.md +59 -0
- package/.orchestration/workflows/react/feature.md +37 -0
- package/.orchestration/workflows/react/performance.md +59 -0
- package/.orchestration/workflows/react/pr.md +19 -0
- package/.orchestration/workflows/react/refactor.md +32 -0
- package/.orchestration/workflows/react/review.md +46 -0
- package/ORCHESTRATION.md +5 -0
- package/README.md +118 -0
- package/compacted_2026-02-12_15-24-24.txt +34 -0
- package/compacted_standalonecompaction_2026-02-12_15-26-38.md +34 -0
- package/compacted_standalonecompaction_2026-02-12_15-28-25.md +34 -0
- package/package.json +25 -0
- package/src/cli.js +59 -0
- package/src/formatter.js +33 -0
- package/src/index.js +75 -0
- package/src/parsers/babel.js +469 -0
- package/src/parsers/python.js +181 -0
- package/src/walker.js +54 -0
- package/test/fixtures/sample.js +18 -0
- package/test/fixtures/sample.py +25 -0
- package/test/test.js +102 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Orchestration Protocol
|
|
2
|
+
|
|
3
|
+
**MANDATORY: Process BEFORE any tool usage.**
|
|
4
|
+
|
|
5
|
+
## 1. CLASSIFY TASK
|
|
6
|
+
|
|
7
|
+
| Signal Words | Workflow |
|
|
8
|
+
|--------------|----------|
|
|
9
|
+
| build, create, add, implement, new | `feature.md` |
|
|
10
|
+
| fix, broken, error, crash, bug | `bugfix.md` |
|
|
11
|
+
| clean up, improve, restructure, rename | `refactor.md` |
|
|
12
|
+
| slow, optimize, performance, speed | `performance.md` |
|
|
13
|
+
| review, check, PR, merge | `review.md` |
|
|
14
|
+
| PR description, pull request title | `pr.md` |
|
|
15
|
+
| document, README, explain | `docs.md` |
|
|
16
|
+
| complex, multi-step, plan | `todo.md` |
|
|
17
|
+
|
|
18
|
+
**Complexity:** 1-2 ops = simple | 3+ ops = complex (add `todo.md`)
|
|
19
|
+
**Technology:** React (`.jsx`/`.tsx`, hooks) → `workflows/react/` | Other → `workflows/`
|
|
20
|
+
|
|
21
|
+
### Selection
|
|
22
|
+
- **Clear match:** Proceed to binding
|
|
23
|
+
- **Ambiguous:** Use `AskUserQuestion` (header: "Workflow", options: relevant workflows)
|
|
24
|
+
- **No match:** Ask user to clarify
|
|
25
|
+
|
|
26
|
+
## 2. BINDING (required before ANY tool use)
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
ORCHESTRATION_BINDING:
|
|
30
|
+
- Task: [description]
|
|
31
|
+
- Workflow: [path]
|
|
32
|
+
- Complexity: [simple/complex]
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## 3. EXEMPT TASKS
|
|
36
|
+
|
|
37
|
+
Requires ALL: single file, 1-2 ops, zero architecture impact, obvious correctness.
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
ORCHESTRATION_BINDING:
|
|
41
|
+
- Task: [description]
|
|
42
|
+
- Classification: EXEMPT
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## 4. COMPLETION
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
ORCHESTRATION_COMPLETE:
|
|
49
|
+
- Task: [description]
|
|
50
|
+
- Workflow: [used]
|
|
51
|
+
- Files: [modified]
|
|
52
|
+
```
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# React Bugfix Workflow
|
|
2
|
+
|
|
3
|
+
## 1. Reproduce
|
|
4
|
+
|
|
5
|
+
- Confirm bug exists | find minimal repro
|
|
6
|
+
- Check Strict Mode behavior
|
|
7
|
+
- Answer: Expected vs actual? React 18 concurrent issue?
|
|
8
|
+
|
|
9
|
+
## 2. Locate Root Cause
|
|
10
|
+
|
|
11
|
+
| Common React 18 Issues |
|
|
12
|
+
|------------------------|
|
|
13
|
+
| Effects missing cleanup |
|
|
14
|
+
| Stale closures in effects |
|
|
15
|
+
| Concurrent rendering race conditions |
|
|
16
|
+
| Automatic batching changes |
|
|
17
|
+
|
|
18
|
+
## 3. Fix
|
|
19
|
+
|
|
20
|
+
- Keep changes within affected feature folder
|
|
21
|
+
- Add cleanup: `return () => controller.abort()`
|
|
22
|
+
- Fix stale closures with proper deps
|
|
23
|
+
|
|
24
|
+
## 4. Verify
|
|
25
|
+
|
|
26
|
+
- Confirm fix | test with Strict Mode
|
|
27
|
+
- Add regression test
|
|
28
|
+
|
|
29
|
+
## Constraints
|
|
30
|
+
|
|
31
|
+
- Smallest fix only | NO refactoring
|
|
32
|
+
- NO barrel exports | note other issues separately
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# React Documentation Workflow
|
|
2
|
+
|
|
3
|
+
> Document architecture correctly. See orchestration.md for patterns.
|
|
4
|
+
|
|
5
|
+
## Before Writing
|
|
6
|
+
|
|
7
|
+
MUST answer:
|
|
8
|
+
- Who is the audience?
|
|
9
|
+
- What should they be able to do after reading?
|
|
10
|
+
- What existing docs need to stay in sync?
|
|
11
|
+
|
|
12
|
+
## Process
|
|
13
|
+
|
|
14
|
+
### 1. Understand the Subject
|
|
15
|
+
- Read the code being documented
|
|
16
|
+
- Try it yourself if possible
|
|
17
|
+
- Identify non-obvious behavior or gotchas
|
|
18
|
+
|
|
19
|
+
### 2. Check Existing Docs
|
|
20
|
+
- Find related documentation
|
|
21
|
+
- Identify what's missing or outdated
|
|
22
|
+
- Note the existing style and format
|
|
23
|
+
|
|
24
|
+
### 3. Write
|
|
25
|
+
|
|
26
|
+
Adapt this template as needed:
|
|
27
|
+
|
|
28
|
+
```markdown
|
|
29
|
+
# {Name}
|
|
30
|
+
|
|
31
|
+
Brief description.
|
|
32
|
+
|
|
33
|
+
## Location
|
|
34
|
+
`features/{feature}/components/{Name}/{Name}.tsx`
|
|
35
|
+
|
|
36
|
+
## Import
|
|
37
|
+
import { Name } from '@/features/{feature}/components/{Name}/{Name}'
|
|
38
|
+
|
|
39
|
+
## Usage
|
|
40
|
+
<Name prop="value" />
|
|
41
|
+
|
|
42
|
+
## Props/Parameters (if applicable)
|
|
43
|
+
| Name | Type | Required | Description |
|
|
44
|
+
|------|------|----------|-------------|
|
|
45
|
+
|
|
46
|
+
## Related
|
|
47
|
+
- Links to related components/hooks
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### 4. Validate
|
|
51
|
+
- Code examples actually work
|
|
52
|
+
- Import paths are direct (not barrel)
|
|
53
|
+
- Links are valid
|
|
54
|
+
|
|
55
|
+
## Constraints
|
|
56
|
+
|
|
57
|
+
- MUST explain why, not just what
|
|
58
|
+
- MUST show direct import paths in examples
|
|
59
|
+
- MUST update related docs to stay consistent
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# React Feature Workflow
|
|
2
|
+
|
|
3
|
+
## 1. Architecture
|
|
4
|
+
|
|
5
|
+
**IF not specified:** Use `AskUserQuestion` (header: "Architecture")
|
|
6
|
+
|
|
7
|
+
| Architecture | Structure |
|
|
8
|
+
|--------------|-----------|
|
|
9
|
+
| Feature-driven | `features/{name}/components\|hooks\|utils/` |
|
|
10
|
+
| Flat feature-driven | `features/{name}/` flat files |
|
|
11
|
+
| Atomic design | `atoms\|molecules\|organisms\|templates/` |
|
|
12
|
+
|
|
13
|
+
**IF project has patterns:** Follow existing, skip question.
|
|
14
|
+
|
|
15
|
+
## 2. Context
|
|
16
|
+
|
|
17
|
+
- Read related code, identify target folder
|
|
18
|
+
- Check similar implementations, reusable hooks/utils
|
|
19
|
+
- Answer: What problem? Minimal version? Which folder?
|
|
20
|
+
|
|
21
|
+
## 3. Implement
|
|
22
|
+
|
|
23
|
+
**Components:** Function only | `useState`/`useReducer` for local state
|
|
24
|
+
**Hooks:** Extract logic | `hooks/{feature}/{name}.ts` | descriptive names
|
|
25
|
+
**State:** Lift only as needed | composition over prop drilling
|
|
26
|
+
|
|
27
|
+
## 4. Validate
|
|
28
|
+
|
|
29
|
+
- Run tests for regressions
|
|
30
|
+
- Add tests for new code
|
|
31
|
+
- Test loading/error states
|
|
32
|
+
- Remove debug code
|
|
33
|
+
|
|
34
|
+
## Constraints
|
|
35
|
+
|
|
36
|
+
- NO `index.ts`/`index.tsx` | import from file directly
|
|
37
|
+
- Match existing style | no extra features
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# React Performance Workflow
|
|
2
|
+
|
|
3
|
+
> Architecture rules: See orchestration.md. Violations block merge.
|
|
4
|
+
|
|
5
|
+
## Before Coding
|
|
6
|
+
|
|
7
|
+
MUST answer:
|
|
8
|
+
- What is the specific performance problem?
|
|
9
|
+
- How will I measure improvement?
|
|
10
|
+
- Is this a real bottleneck or premature optimization?
|
|
11
|
+
|
|
12
|
+
## Process
|
|
13
|
+
|
|
14
|
+
### 1. Measure First
|
|
15
|
+
- Profile with React DevTools Profiler
|
|
16
|
+
- Identify components that re-render unnecessarily
|
|
17
|
+
- Check bundle size with build analyzer
|
|
18
|
+
- Measure actual user-facing metrics (not just hunches)
|
|
19
|
+
|
|
20
|
+
### 2. Identify Root Cause
|
|
21
|
+
|
|
22
|
+
**Common issues:**
|
|
23
|
+
- Components re-rendering when props haven't changed
|
|
24
|
+
- Expensive calculations on every render
|
|
25
|
+
- Large bundle from unused dependencies
|
|
26
|
+
- Missing code splitting on routes
|
|
27
|
+
|
|
28
|
+
### 3. Optimize
|
|
29
|
+
|
|
30
|
+
**Prevent unnecessary re-renders:**
|
|
31
|
+
```tsx
|
|
32
|
+
// Memoize components that receive stable props
|
|
33
|
+
const MemoizedList = memo(List)
|
|
34
|
+
|
|
35
|
+
// Memoize callbacks passed to children
|
|
36
|
+
const handleClick = useCallback(() => {
|
|
37
|
+
doSomething(id)
|
|
38
|
+
}, [id])
|
|
39
|
+
|
|
40
|
+
// Memoize expensive derived values
|
|
41
|
+
const sorted = useMemo(() => sortItems(items), [items])
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**Reduce bundle size:**
|
|
45
|
+
- Lazy load routes with `React.lazy` + `Suspense`
|
|
46
|
+
- Replace heavy libraries with lighter alternatives
|
|
47
|
+
- Use tree-shakeable imports
|
|
48
|
+
|
|
49
|
+
### 4. Verify
|
|
50
|
+
- Re-profile to confirm improvement
|
|
51
|
+
- Ensure no regressions in functionality
|
|
52
|
+
- Document the optimization and why it helped
|
|
53
|
+
|
|
54
|
+
## Constraints
|
|
55
|
+
|
|
56
|
+
- NEVER optimize without measuring first
|
|
57
|
+
- NEVER add memo/useMemo/useCallback everywhere "just in case"
|
|
58
|
+
- MUST prove the optimization helps with real measurements
|
|
59
|
+
- Keep optimizations minimal and targeted
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Pull Request Workflow
|
|
2
|
+
|
|
3
|
+
## Process
|
|
4
|
+
|
|
5
|
+
1. Read diff (current branch vs main/master)
|
|
6
|
+
2. Analyze changes
|
|
7
|
+
3. Output title + description
|
|
8
|
+
|
|
9
|
+
## Output
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
PR Title: <imperative mood>
|
|
13
|
+
Description: <2-3 sentences: what + why>
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Constraints
|
|
17
|
+
|
|
18
|
+
- Imperative mood ("Add" not "Added") | mention breaking changes
|
|
19
|
+
- Output only | NO branch/push/remote PR creation
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# React Refactor Workflow
|
|
2
|
+
|
|
3
|
+
## 1. Safety Net
|
|
4
|
+
|
|
5
|
+
- Run tests | add if coverage insufficient
|
|
6
|
+
- Answer: What improvement? How verify unchanged behavior?
|
|
7
|
+
|
|
8
|
+
## 2. Plan
|
|
9
|
+
|
|
10
|
+
- Map imports/dependencies | identify all callers
|
|
11
|
+
- Break into small, safe steps
|
|
12
|
+
|
|
13
|
+
## 3. Execute
|
|
14
|
+
|
|
15
|
+
One change type at a time | run tests after each:
|
|
16
|
+
|
|
17
|
+
| Change Types |
|
|
18
|
+
|--------------|
|
|
19
|
+
| Rename files to match folders |
|
|
20
|
+
| Barrel → direct imports |
|
|
21
|
+
| Extract logic into hooks |
|
|
22
|
+
| Split large components |
|
|
23
|
+
|
|
24
|
+
## 4. Validate
|
|
25
|
+
|
|
26
|
+
- All tests pass | no `index.ts`/`index.tsx`
|
|
27
|
+
- Entry points match folder names
|
|
28
|
+
|
|
29
|
+
## Constraints
|
|
30
|
+
|
|
31
|
+
- Structure only, NOT behavior | NO bug fixes
|
|
32
|
+
- One change type at a time | note issues separately
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# React Code Review Workflow
|
|
2
|
+
|
|
3
|
+
## 1. Understand
|
|
4
|
+
|
|
5
|
+
- Read PR description | review diff scope
|
|
6
|
+
- Answer: What is the goal? What files changed?
|
|
7
|
+
|
|
8
|
+
## 2. Architecture Checklist
|
|
9
|
+
|
|
10
|
+
| Check | Rule |
|
|
11
|
+
|-------|------|
|
|
12
|
+
| Barrels | No `index.ts`/`index.tsx` |
|
|
13
|
+
| Entry files | Match folder names (`Button/Button.tsx`) |
|
|
14
|
+
| Imports | Direct, not barrel |
|
|
15
|
+
| Colocation | Component + hooks + types + tests together |
|
|
16
|
+
| Placement | Correct feature folder |
|
|
17
|
+
|
|
18
|
+
## 3. React Patterns Checklist
|
|
19
|
+
|
|
20
|
+
| Check | Rule |
|
|
21
|
+
|-------|------|
|
|
22
|
+
| Components | Function only, no class |
|
|
23
|
+
| Hooks | No conditionals, proper deps |
|
|
24
|
+
| Effects | Cleanup where needed |
|
|
25
|
+
| Memory | No leaks (subscriptions, timers) |
|
|
26
|
+
| States | Loading + error handled |
|
|
27
|
+
|
|
28
|
+
## 4. Code Quality Checklist
|
|
29
|
+
|
|
30
|
+
| Check | Rule |
|
|
31
|
+
|-------|------|
|
|
32
|
+
| Debug | No console.log/debugger |
|
|
33
|
+
| Imports | No unused |
|
|
34
|
+
| Types | No unjustified `any` |
|
|
35
|
+
| Tests | Cover new functionality |
|
|
36
|
+
| Scope | No unrelated changes |
|
|
37
|
+
|
|
38
|
+
## 5. Feedback
|
|
39
|
+
|
|
40
|
+
- **Blocking:** Must fix (bugs, architecture violations)
|
|
41
|
+
- **Suggestion:** Improvements | **Question:** Clarification
|
|
42
|
+
|
|
43
|
+
## Constraints
|
|
44
|
+
|
|
45
|
+
- NO approval with violations | must understand code
|
|
46
|
+
- Specific + actionable | suggest fixes, not just problems
|
package/ORCHESTRATION.md
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# codebase-compact
|
|
2
|
+
|
|
3
|
+
Walks a project directory, parses JS/TS/Python files, and outputs a compact structural skeleton of the entire codebase. Designed for feeding project context into LLM prompts with minimal token usage.
|
|
4
|
+
|
|
5
|
+
Typical compaction rate: **~95%** token reduction.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install -g codebase-compact
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Or run directly from the repo:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
node src/cli.js /path/to/project
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## CLI Usage
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
codebase-compact [path] [options]
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**Options:**
|
|
26
|
+
|
|
27
|
+
| Flag | Description |
|
|
28
|
+
|------|-------------|
|
|
29
|
+
| `--json` | Save output as JSON (includes stats) |
|
|
30
|
+
| `--help`, `-h` | Show help |
|
|
31
|
+
|
|
32
|
+
If no path is given, it defaults to the current directory.
|
|
33
|
+
|
|
34
|
+
Output is saved to the target directory as `compacted_<project>_<date>.md`.
|
|
35
|
+
|
|
36
|
+
**Example:**
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
$ codebase-compact ~/projects/my-app
|
|
40
|
+
|
|
41
|
+
Saved to /home/user/projects/my-app/compacted_my-app_2026-02-12_15-30-00.md
|
|
42
|
+
|
|
43
|
+
Files: 96
|
|
44
|
+
Project tokens: 106.9K
|
|
45
|
+
Compacted tokens: 5.9K
|
|
46
|
+
Compaction rate: 94.4%
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Library Usage
|
|
50
|
+
|
|
51
|
+
```js
|
|
52
|
+
import { compactProject, compactFile } from 'codebase-compact';
|
|
53
|
+
|
|
54
|
+
// Compact an entire directory
|
|
55
|
+
const { output, stats } = compactProject('/path/to/project');
|
|
56
|
+
console.log(output);
|
|
57
|
+
console.log(stats); // { files, rawTokens, compactedTokens }
|
|
58
|
+
|
|
59
|
+
// Compact a single file
|
|
60
|
+
const { skeleton, formatted } = compactFile('app.tsx', sourceCode);
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Output Format
|
|
64
|
+
|
|
65
|
+
Each file is rendered as a markdown heading followed by its structural skeleton:
|
|
66
|
+
|
|
67
|
+
```
|
|
68
|
+
## src/components/App.jsx
|
|
69
|
+
imports: 3 ext, ./hooks/useAuth, ./api/client
|
|
70
|
+
exports: App*
|
|
71
|
+
components: App:12
|
|
72
|
+
fn: handleSubmit:24, validate:40
|
|
73
|
+
hooks: useState(2), useEffect([user]):18, useAuth
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
The skeleton captures:
|
|
77
|
+
- **Imports** (local paths shown, externals counted)
|
|
78
|
+
- **Exports** (default marked with `*`)
|
|
79
|
+
- **Components** (PascalCase functions, HOC-wrapped)
|
|
80
|
+
- **Functions** (with line numbers)
|
|
81
|
+
- **Hooks** (counts, useEffect deps, custom hooks)
|
|
82
|
+
- **Classes, interfaces, types** (TS)
|
|
83
|
+
- **Python**: imports, classes (with bases/decorators), functions, constants
|
|
84
|
+
|
|
85
|
+
## Supported Languages
|
|
86
|
+
|
|
87
|
+
| Language | Parser | Extensions |
|
|
88
|
+
|----------|--------|------------|
|
|
89
|
+
| JavaScript | `@babel/parser` | `.js`, `.jsx`, `.mjs`, `.cjs` |
|
|
90
|
+
| TypeScript | `@babel/parser` | `.ts`, `.tsx`, `.mts`, `.cts` |
|
|
91
|
+
| Python | Regex-based (zero deps) | `.py` |
|
|
92
|
+
|
|
93
|
+
## Skipped Directories
|
|
94
|
+
|
|
95
|
+
`node_modules`, `dist`, `.git`, `target`, `build`, `.next`, `.turbo`, `out`, `coverage`, `.cache`, `__pycache__`, `.venv`, `venv`, `.idea`, `.vscode`, and any dotfile directories.
|
|
96
|
+
|
|
97
|
+
## Project Structure
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
src/
|
|
101
|
+
cli.js # CLI entry point
|
|
102
|
+
index.js # Library API: compactProject, compactFile
|
|
103
|
+
walker.js # Recursive directory walker with filtering
|
|
104
|
+
formatter.js # Output formatting + token estimation
|
|
105
|
+
parsers/
|
|
106
|
+
babel.js # JS/TS parsing via Babel AST
|
|
107
|
+
python.js # Python parsing via regex (top-level only)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Tests
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
npm test
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## License
|
|
117
|
+
|
|
118
|
+
MIT
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
## src/cli.js
|
|
2
|
+
imports: 2 ext, ./index.js, ./formatter.js
|
|
3
|
+
fn: getDateStamp:8, pad:10
|
|
4
|
+
## src/formatter.js
|
|
5
|
+
imports: ./parsers/python.js, ./parsers/babel.js, ./parsers/python.js
|
|
6
|
+
exports: estimateTokens, formatTokenCount, formatOutput
|
|
7
|
+
fn: estimateTokens:5, formatTokenCount:10, formatOutput:16
|
|
8
|
+
## src/index.js
|
|
9
|
+
imports: 1 ext, ./walker.js, ./formatter.js, ./parsers/babel.js, ./parsers/python.js
|
|
10
|
+
exports: isBabelParseable, isPythonParseable, estimateTokens, formatTokenCount, compactFile, compactProject
|
|
11
|
+
fn: compactFile:17, compactProject:38
|
|
12
|
+
## src/parsers/babel.js
|
|
13
|
+
imports: 2 ext
|
|
14
|
+
exports: isBabelParseable, extractSignatures, extractSkeleton, formatSignaturesForPrompt, formatSkeletonForPrompt
|
|
15
|
+
fn: isBabelParseable:9, isPascalCase:13, getReactHOCInfo:17, isCreateContext:52, extractDependencyArray:69, getParamsString:97, getTypeName:123, getReturnType:141, extractSignatures:146, extractSkeleton:242, formatSignaturesForPrompt:402, formatSkeletonForPrompt:407
|
|
16
|
+
## src/parsers/python.js
|
|
17
|
+
exports: isPythonParseable, extractSkeleton, formatSkeletonForPrompt
|
|
18
|
+
fn: isPythonParseable:3, extractSkeleton:14, formatSkeletonForPrompt:148
|
|
19
|
+
## src/walker.js
|
|
20
|
+
imports: 2 ext, ./parsers/babel.js, ./parsers/python.js
|
|
21
|
+
exports: collectFiles
|
|
22
|
+
fn: collectFiles:24, SKIP_DIRS_OR_DOT:48, isParseable:52
|
|
23
|
+
## test/fixtures/sample.js
|
|
24
|
+
imports: 1 ext, ./api
|
|
25
|
+
exports: MyComponent, MyComponent*
|
|
26
|
+
components: MyComponent:6
|
|
27
|
+
fn: helper:16
|
|
28
|
+
hooks: useState(1), useEffect([id]):9
|
|
29
|
+
## test/fixtures/sample.py
|
|
30
|
+
imports: 4 ext
|
|
31
|
+
classes: BaseProcessor:9, Config @dataclass (BaseProcessor):13
|
|
32
|
+
fn: process_data:17, fetch_remote:20, @app.route api_handler:24
|
|
33
|
+
## test/test.js
|
|
34
|
+
imports: 5 ext, ../src/index.js, ../src/parsers/babel.js, ../src/parsers/python.js, ../src/walker.js
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
## src/cli.js
|
|
2
|
+
imports: 2 ext, ./index.js, ./formatter.js
|
|
3
|
+
fn: getDateStamp:8, pad:10
|
|
4
|
+
## src/formatter.js
|
|
5
|
+
imports: ./parsers/python.js, ./parsers/babel.js, ./parsers/python.js
|
|
6
|
+
exports: estimateTokens, formatTokenCount, formatOutput
|
|
7
|
+
fn: estimateTokens:5, formatTokenCount:10, formatOutput:16
|
|
8
|
+
## src/index.js
|
|
9
|
+
imports: 1 ext, ./walker.js, ./formatter.js, ./parsers/babel.js, ./parsers/python.js
|
|
10
|
+
exports: isBabelParseable, isPythonParseable, estimateTokens, formatTokenCount, compactFile, compactProject
|
|
11
|
+
fn: compactFile:17, compactProject:38
|
|
12
|
+
## src/parsers/babel.js
|
|
13
|
+
imports: 2 ext
|
|
14
|
+
exports: isBabelParseable, extractSignatures, extractSkeleton, formatSignaturesForPrompt, formatSkeletonForPrompt
|
|
15
|
+
fn: isBabelParseable:9, isPascalCase:13, getReactHOCInfo:17, isCreateContext:52, extractDependencyArray:69, getParamsString:97, getTypeName:123, getReturnType:141, extractSignatures:146, extractSkeleton:242, formatSignaturesForPrompt:402, formatSkeletonForPrompt:407
|
|
16
|
+
## src/parsers/python.js
|
|
17
|
+
exports: isPythonParseable, extractSkeleton, formatSkeletonForPrompt
|
|
18
|
+
fn: isPythonParseable:3, extractSkeleton:14, formatSkeletonForPrompt:148
|
|
19
|
+
## src/walker.js
|
|
20
|
+
imports: 2 ext, ./parsers/babel.js, ./parsers/python.js
|
|
21
|
+
exports: collectFiles
|
|
22
|
+
fn: collectFiles:24, SKIP_DIRS_OR_DOT:48, isParseable:52
|
|
23
|
+
## test/fixtures/sample.js
|
|
24
|
+
imports: 1 ext, ./api
|
|
25
|
+
exports: MyComponent, MyComponent*
|
|
26
|
+
components: MyComponent:6
|
|
27
|
+
fn: helper:16
|
|
28
|
+
hooks: useState(1), useEffect([id]):9
|
|
29
|
+
## test/fixtures/sample.py
|
|
30
|
+
imports: 4 ext
|
|
31
|
+
classes: BaseProcessor:9, Config @dataclass (BaseProcessor):13
|
|
32
|
+
fn: process_data:17, fetch_remote:20, @app.route api_handler:24
|
|
33
|
+
## test/test.js
|
|
34
|
+
imports: 5 ext, ../src/index.js, ../src/parsers/babel.js, ../src/parsers/python.js, ../src/walker.js
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
## src/cli.js
|
|
2
|
+
imports: 2 ext, ./index.js, ./formatter.js
|
|
3
|
+
fn: getDateStamp:8, pad:10
|
|
4
|
+
## src/formatter.js
|
|
5
|
+
imports: ./parsers/python.js, ./parsers/babel.js, ./parsers/python.js
|
|
6
|
+
exports: estimateTokens, formatTokenCount, formatOutput
|
|
7
|
+
fn: estimateTokens:5, formatTokenCount:10, formatOutput:16
|
|
8
|
+
## src/index.js
|
|
9
|
+
imports: 1 ext, ./walker.js, ./formatter.js, ./parsers/babel.js, ./parsers/python.js
|
|
10
|
+
exports: isBabelParseable, isPythonParseable, estimateTokens, formatTokenCount, compactFile, compactProject
|
|
11
|
+
fn: compactFile:17, compactProject:38
|
|
12
|
+
## src/parsers/babel.js
|
|
13
|
+
imports: 2 ext
|
|
14
|
+
exports: isBabelParseable, extractSignatures, extractSkeleton, formatSignaturesForPrompt, formatSkeletonForPrompt
|
|
15
|
+
fn: isBabelParseable:9, isPascalCase:13, getReactHOCInfo:17, isCreateContext:52, extractDependencyArray:69, getParamsString:97, getTypeName:123, getReturnType:141, extractSignatures:146, extractSkeleton:242, formatSignaturesForPrompt:402, formatSkeletonForPrompt:407
|
|
16
|
+
## src/parsers/python.js
|
|
17
|
+
exports: isPythonParseable, extractSkeleton, formatSkeletonForPrompt
|
|
18
|
+
fn: isPythonParseable:3, extractSkeleton:14, formatSkeletonForPrompt:148
|
|
19
|
+
## src/walker.js
|
|
20
|
+
imports: 2 ext, ./parsers/babel.js, ./parsers/python.js
|
|
21
|
+
exports: collectFiles
|
|
22
|
+
fn: collectFiles:24, SKIP_DIRS_OR_DOT:48, isParseable:52
|
|
23
|
+
## test/fixtures/sample.js
|
|
24
|
+
imports: 1 ext, ./api
|
|
25
|
+
exports: MyComponent, MyComponent*
|
|
26
|
+
components: MyComponent:6
|
|
27
|
+
fn: helper:16
|
|
28
|
+
hooks: useState(1), useEffect([id]):9
|
|
29
|
+
## test/fixtures/sample.py
|
|
30
|
+
imports: 4 ext
|
|
31
|
+
classes: BaseProcessor:9, Config @dataclass (BaseProcessor):13
|
|
32
|
+
fn: process_data:17, fetch_remote:20, @app.route api_handler:24
|
|
33
|
+
## test/test.js
|
|
34
|
+
imports: 5 ext, ../src/index.js, ../src/parsers/babel.js, ../src/parsers/python.js, ../src/walker.js
|
package/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "agentic-compaction",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Walk a project directory and output a compact structural skeleton of the entire codebase",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./src/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"codebase-compact": "./src/cli.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"test": "node --test test/"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"codebase",
|
|
15
|
+
"compact",
|
|
16
|
+
"skeleton",
|
|
17
|
+
"parser",
|
|
18
|
+
"ast"
|
|
19
|
+
],
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"@babel/parser": "^7.24.0",
|
|
23
|
+
"@babel/traverse": "^7.24.0"
|
|
24
|
+
}
|
|
25
|
+
}
|
package/src/cli.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { resolve, join, basename } from 'path';
|
|
4
|
+
import { writeFileSync } from 'fs';
|
|
5
|
+
import { compactProject } from './index.js';
|
|
6
|
+
import { formatTokenCount } from './formatter.js';
|
|
7
|
+
|
|
8
|
+
function getDateStamp() {
|
|
9
|
+
const now = new Date();
|
|
10
|
+
const pad = (n) => String(n).padStart(2, '0');
|
|
11
|
+
return `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}_${pad(now.getHours())}-${pad(now.getMinutes())}-${pad(now.getSeconds())}`;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const args = process.argv.slice(2);
|
|
15
|
+
|
|
16
|
+
let targetPath = process.cwd();
|
|
17
|
+
let jsonOutput = false;
|
|
18
|
+
|
|
19
|
+
for (let i = 0; i < args.length; i++) {
|
|
20
|
+
const arg = args[i];
|
|
21
|
+
if (arg === '--json') {
|
|
22
|
+
jsonOutput = true;
|
|
23
|
+
} else if (arg === '--help' || arg === '-h') {
|
|
24
|
+
console.log(`Usage: codebase-compact [path] [options]
|
|
25
|
+
|
|
26
|
+
Options:
|
|
27
|
+
--json Output as JSON instead of text
|
|
28
|
+
--help, -h Show this help message
|
|
29
|
+
|
|
30
|
+
Output is saved to compacted_<name>_<date>.md in the target directory.`);
|
|
31
|
+
process.exit(0);
|
|
32
|
+
} else if (!arg.startsWith('-')) {
|
|
33
|
+
targetPath = arg;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
targetPath = resolve(targetPath);
|
|
38
|
+
|
|
39
|
+
const { output, stats } = compactProject(targetPath);
|
|
40
|
+
|
|
41
|
+
const dirName = basename(targetPath);
|
|
42
|
+
const filename = `compacted_${dirName}_${getDateStamp()}.md`;
|
|
43
|
+
const outputPath = join(targetPath, filename);
|
|
44
|
+
|
|
45
|
+
if (jsonOutput) {
|
|
46
|
+
writeFileSync(outputPath, JSON.stringify({ output, stats }, null, 2));
|
|
47
|
+
} else {
|
|
48
|
+
writeFileSync(outputPath, output);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const compactionRate = stats.rawTokens > 0
|
|
52
|
+
? ((1 - stats.compactedTokens / stats.rawTokens) * 100).toFixed(1)
|
|
53
|
+
: '0';
|
|
54
|
+
|
|
55
|
+
console.log(`\nSaved to ${outputPath}\n`);
|
|
56
|
+
console.log(` Files: ${stats.files}`);
|
|
57
|
+
console.log(` Project tokens: ${formatTokenCount(stats.rawTokens)}`);
|
|
58
|
+
console.log(` Compacted tokens: ${formatTokenCount(stats.compactedTokens)}`);
|
|
59
|
+
console.log(` Compaction rate: ${compactionRate}%`);
|
package/src/formatter.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { isPythonParseable } from './parsers/python.js';
|
|
2
|
+
import { formatSkeletonForPrompt as formatBabelSkeleton } from './parsers/babel.js';
|
|
3
|
+
import { formatSkeletonForPrompt as formatPythonSkeleton } from './parsers/python.js';
|
|
4
|
+
|
|
5
|
+
export const estimateTokens = (text) => {
|
|
6
|
+
if (!text) return 0;
|
|
7
|
+
return Math.ceil(text.length / 4);
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const formatTokenCount = (count) => {
|
|
11
|
+
if (count >= 1000000) return `${(count / 1000000).toFixed(1)}M`;
|
|
12
|
+
if (count >= 1000) return `${(count / 1000).toFixed(1)}K`;
|
|
13
|
+
return count.toString();
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export function formatOutput(results) {
|
|
17
|
+
const lines = [];
|
|
18
|
+
|
|
19
|
+
results.sort((a, b) => a.relativePath.localeCompare(b.relativePath));
|
|
20
|
+
|
|
21
|
+
for (const result of results) {
|
|
22
|
+
lines.push(`## ${result.relativePath}`);
|
|
23
|
+
|
|
24
|
+
if (result.skeleton) {
|
|
25
|
+
const output = isPythonParseable(result.relativePath)
|
|
26
|
+
? formatPythonSkeleton(result.skeleton)
|
|
27
|
+
: formatBabelSkeleton(result.skeleton);
|
|
28
|
+
if (output) lines.push(output);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return lines.join('\n');
|
|
33
|
+
}
|