@aladac/hu 0.1.0-a1
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/.tool-versions +1 -0
- package/CLAUDE.md +122 -0
- package/HOOKS-DATA-INTEGRATION.md +457 -0
- package/SAMPLE.md +378 -0
- package/TODO.md +25 -0
- package/biome.json +51 -0
- package/commands/bootstrap.md +13 -0
- package/commands/c.md +1 -0
- package/commands/check-name.md +62 -0
- package/commands/disk.md +141 -0
- package/commands/docs/archive.md +27 -0
- package/commands/docs/check-internal.md +53 -0
- package/commands/docs/cleanup.md +65 -0
- package/commands/docs/consolidate.md +72 -0
- package/commands/docs/get.md +101 -0
- package/commands/docs/list.md +61 -0
- package/commands/docs/sync.md +64 -0
- package/commands/docs/update.md +49 -0
- package/commands/plans/clear.md +23 -0
- package/commands/plans/create.md +71 -0
- package/commands/plans/list.md +21 -0
- package/commands/plans/sync.md +38 -0
- package/commands/reinstall.md +20 -0
- package/commands/replicate.md +303 -0
- package/commands/warp.md +0 -0
- package/doc/README.md +35 -0
- package/doc/claude-code/capabilities.md +202 -0
- package/doc/claude-code/directory-structure.md +246 -0
- package/doc/claude-code/hooks.md +348 -0
- package/doc/claude-code/overview.md +109 -0
- package/doc/claude-code/plugins.md +273 -0
- package/doc/claude-code/sdk-protocols.md +202 -0
- package/document-manifest.toml +29 -0
- package/justfile +39 -0
- package/package.json +33 -0
- package/plans/compiled-watching-feather.md +217 -0
- package/plans/crispy-crafting-pnueli.md +103 -0
- package/plans/greedy-booping-coral.md +146 -0
- package/plans/imperative-sleeping-flamingo.md +192 -0
- package/plans/jaunty-sprouting-marble.md +171 -0
- package/plans/jiggly-discovering-lake.md +68 -0
- package/plans/magical-nibbling-spark.md +144 -0
- package/plans/mellow-kindling-acorn.md +110 -0
- package/plans/recursive-questing-engelbart.md +65 -0
- package/plans/serialized-roaming-kernighan.md +227 -0
- package/plans/structured-wondering-wirth.md +230 -0
- package/plans/vectorized-dreaming-iverson.md +191 -0
- package/plans/velvety-enchanting-ocean.md +92 -0
- package/plans/wiggly-sparking-pixel.md +48 -0
- package/plans/zippy-shimmying-fox.md +188 -0
- package/plugins/installed_plugins.json +4 -0
- package/sample-hooks.json +298 -0
- package/settings.json +24 -0
- package/settings.local.json +7 -0
- package/src/commands/bump.ts +130 -0
- package/src/commands/disk.ts +419 -0
- package/src/commands/docs.ts +729 -0
- package/src/commands/plans.ts +259 -0
- package/src/commands/utils.ts +299 -0
- package/src/index.ts +26 -0
- package/src/lib/colors.ts +87 -0
- package/src/lib/exec.ts +25 -0
- package/src/lib/fs.ts +119 -0
- package/src/lib/html.ts +205 -0
- package/src/lib/spinner.ts +42 -0
- package/src/types/index.ts +61 -0
- package/tests/lib/colors.test.ts +69 -0
- package/tests/lib/fs.test.ts +65 -0
- package/tsconfig.json +20 -0
- package/vitest.config.ts +15 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# Plan: Convert Python Helper Scripts to Rust
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Convert 6 Python analysis scripts (~1,800 lines total) to Rust. These scripts analyze a Rails codebase for code quality issues, unused code, and test infrastructure problems.
|
|
6
|
+
|
|
7
|
+
**Difficulty Assessment: MEDIUM**
|
|
8
|
+
- No external APIs or HTTP calls
|
|
9
|
+
- All standard library dependencies (no pip packages)
|
|
10
|
+
- Main challenges: Ruby code parsing and regex patterns
|
|
11
|
+
|
|
12
|
+
## Scripts to Convert
|
|
13
|
+
|
|
14
|
+
| Script | Lines | Complexity | Effort |
|
|
15
|
+
|--------|-------|------------|--------|
|
|
16
|
+
| rspec-extraction-candidates.py | ~160 | Low | 1-2 days |
|
|
17
|
+
| vcr-cassettes-check.py | ~290 | Medium | 2-3 days |
|
|
18
|
+
| routes-check.py | ~320 | Medium-High | 2-3 days |
|
|
19
|
+
| n-plus-one-finder.py | ~280 | Medium | 2-3 days |
|
|
20
|
+
| dead-code-check.py | ~300 | Medium-High | 3-4 days |
|
|
21
|
+
| factories-analysis.py | ~450 | High | 4-5 days |
|
|
22
|
+
|
|
23
|
+
**Total Estimated Effort: 14-20 days**
|
|
24
|
+
|
|
25
|
+
## Recommended Approach
|
|
26
|
+
|
|
27
|
+
### Phase 1: Shared Library Foundation
|
|
28
|
+
|
|
29
|
+
Create a shared Rust library with common functionality used across all scripts:
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
helper-scripts-rs/
|
|
33
|
+
├── Cargo.toml
|
|
34
|
+
├── src/
|
|
35
|
+
│ ├── lib.rs # Re-exports
|
|
36
|
+
│ ├── cli.rs # Common CLI patterns
|
|
37
|
+
│ ├── table.rs # ANSI table formatting (box-drawing chars)
|
|
38
|
+
│ ├── colors.rs # ANSI color constants
|
|
39
|
+
│ ├── files.rs # File discovery, reading
|
|
40
|
+
│ ├── grep.rs # Grep-like search functionality
|
|
41
|
+
│ └── ruby_parser.rs # Ruby syntax parsing utilities
|
|
42
|
+
└── bin/
|
|
43
|
+
├── dead_code_check.rs
|
|
44
|
+
├── factories_analysis.rs
|
|
45
|
+
├── n_plus_one_finder.rs
|
|
46
|
+
├── routes_check.rs
|
|
47
|
+
├── rspec_extraction.rs
|
|
48
|
+
└── vcr_cassettes_check.rs
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Phase 2: Implement in Order of Complexity
|
|
52
|
+
|
|
53
|
+
**Order: Simplest first to build up shared utilities**
|
|
54
|
+
|
|
55
|
+
1. **rspec-extraction-candidates** (simplest)
|
|
56
|
+
- Grep for VCR tags
|
|
57
|
+
- Count lines and context blocks
|
|
58
|
+
- Format table output
|
|
59
|
+
|
|
60
|
+
2. **vcr-cassettes-check**
|
|
61
|
+
- Multi-format file discovery
|
|
62
|
+
- Cassette name matching (fuzzy)
|
|
63
|
+
- Size calculations
|
|
64
|
+
|
|
65
|
+
3. **n-plus-one-finder**
|
|
66
|
+
- 11 regex patterns (6 multiline, 5 single-line)
|
|
67
|
+
- Pattern matching and extraction
|
|
68
|
+
- Severity classification
|
|
69
|
+
|
|
70
|
+
4. **routes-check**
|
|
71
|
+
- Subprocess call to `bundle exec rails routes`
|
|
72
|
+
- Controller action parsing
|
|
73
|
+
- Route-action matching
|
|
74
|
+
|
|
75
|
+
5. **dead-code-check**
|
|
76
|
+
- Ruby method/class definition parsing
|
|
77
|
+
- Usage indexing via grep
|
|
78
|
+
- Nesting and indentation tracking
|
|
79
|
+
|
|
80
|
+
6. **factories-analysis** (most complex)
|
|
81
|
+
- FactoryBot syntax parsing
|
|
82
|
+
- Module/factory/trait stack tracking
|
|
83
|
+
- Dual analysis (methods + traits)
|
|
84
|
+
|
|
85
|
+
## Key Dependencies
|
|
86
|
+
|
|
87
|
+
```toml
|
|
88
|
+
[dependencies]
|
|
89
|
+
clap = { version = "4", features = ["derive"] } # CLI argument parsing
|
|
90
|
+
walkdir = "2" # Recursive file discovery
|
|
91
|
+
regex = "1" # Pattern matching
|
|
92
|
+
anyhow = "1" # Error handling
|
|
93
|
+
colored = "2" # ANSI colors (optional)
|
|
94
|
+
rayon = "1" # Parallel processing (optional)
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Technical Challenges & Solutions
|
|
98
|
+
|
|
99
|
+
### 1. Grep Functionality
|
|
100
|
+
**Problem:** Python scripts use `subprocess.run(['grep', ...])` heavily
|
|
101
|
+
|
|
102
|
+
**Solutions:**
|
|
103
|
+
- Option A: Continue using subprocess (easy, same behavior)
|
|
104
|
+
- Option B: Use Rust `regex` crate with ripgrep-style implementation (faster, no subprocess)
|
|
105
|
+
|
|
106
|
+
**Recommendation:** Option B for performance; build a reusable `grep.rs` module
|
|
107
|
+
|
|
108
|
+
### 2. Ruby Code Parsing
|
|
109
|
+
**Problem:** Several scripts parse Ruby syntax (methods, classes, modules)
|
|
110
|
+
|
|
111
|
+
**Current approach:** Regex-based pattern matching with indentation tracking
|
|
112
|
+
|
|
113
|
+
**Rust solution:**
|
|
114
|
+
- Port regex patterns carefully (Rust regex crate is compatible)
|
|
115
|
+
- Use `nom` crate if more robust parsing needed
|
|
116
|
+
- Handle Ruby's `end` keyword counting for block tracking
|
|
117
|
+
|
|
118
|
+
### 3. ANSI Table Formatting
|
|
119
|
+
**Problem:** All scripts output formatted tables with box-drawing characters
|
|
120
|
+
|
|
121
|
+
**Rust solution:** Create a generic `Table` struct:
|
|
122
|
+
```rust
|
|
123
|
+
struct Table {
|
|
124
|
+
headers: Vec<String>,
|
|
125
|
+
rows: Vec<Vec<String>>,
|
|
126
|
+
column_widths: Vec<usize>,
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
impl Table {
|
|
130
|
+
fn print(&self) { /* box-drawing output */ }
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### 4. Multiline Regex
|
|
135
|
+
**Problem:** n-plus-one-finder uses multiline patterns
|
|
136
|
+
|
|
137
|
+
**Rust solution:** Enable `(?m)` flag or use `regex::RegexBuilder::multi_line(true)`
|
|
138
|
+
|
|
139
|
+
## Benefits of Rust Conversion
|
|
140
|
+
|
|
141
|
+
1. **Performance**: 10-100x faster execution, especially for large codebases
|
|
142
|
+
2. **Single binary**: No Python runtime dependency
|
|
143
|
+
3. **Parallelization**: Easy to add with Rayon for file processing
|
|
144
|
+
4. **Type safety**: Catch errors at compile time
|
|
145
|
+
5. **Cross-platform**: Easy distribution as static binaries
|
|
146
|
+
|
|
147
|
+
## Risks & Mitigations
|
|
148
|
+
|
|
149
|
+
| Risk | Impact | Mitigation |
|
|
150
|
+
|------|--------|------------|
|
|
151
|
+
| Ruby parsing edge cases | Medium | Keep Python versions for comparison testing |
|
|
152
|
+
| Regex behavior differences | Low | Test extensively with same inputs |
|
|
153
|
+
| Development time | Medium | Start with simplest script, build incrementally |
|
|
154
|
+
|
|
155
|
+
## Success Criteria
|
|
156
|
+
|
|
157
|
+
- All 6 binaries produce identical output to Python versions
|
|
158
|
+
- Test with actual Rails codebase
|
|
159
|
+
- No external runtime dependencies (single binary)
|
|
160
|
+
- Performance improvement measurable
|
|
161
|
+
|
|
162
|
+
## Files to Create
|
|
163
|
+
|
|
164
|
+
1. `helper-scripts-rs/Cargo.toml` - Workspace configuration
|
|
165
|
+
2. `helper-scripts-rs/src/lib.rs` - Shared library
|
|
166
|
+
3. `helper-scripts-rs/src/table.rs` - Table formatting
|
|
167
|
+
4. `helper-scripts-rs/src/colors.rs` - ANSI colors
|
|
168
|
+
5. `helper-scripts-rs/src/files.rs` - File operations
|
|
169
|
+
6. `helper-scripts-rs/src/grep.rs` - Search functionality
|
|
170
|
+
7. `helper-scripts-rs/src/ruby_parser.rs` - Ruby parsing utilities
|
|
171
|
+
8. `helper-scripts-rs/bin/*.rs` - 6 binary entry points
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Plan: API Model Inventory
|
|
2
|
+
|
|
3
|
+
## Objective
|
|
4
|
+
|
|
5
|
+
Query all three OpenAI-compatible API servers and produce a concise inventory table of all models.
|
|
6
|
+
|
|
7
|
+
## Servers
|
|
8
|
+
|
|
9
|
+
| Server | Host | Service |
|
|
10
|
+
|--------|------|---------|
|
|
11
|
+
| junkpile | `192.168.0.26:11434` | Ollama |
|
|
12
|
+
| fuji (Ollama) | `127.0.0.1:11434` | Ollama |
|
|
13
|
+
| fuji (LMS) | `127.0.0.1:1234` | LM Studio |
|
|
14
|
+
|
|
15
|
+
## Output Format
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
| Model | Host | Type | Service | Size | Params |
|
|
19
|
+
|------------------------|-----------|---------|-----------|--------|--------|
|
|
20
|
+
| minicpm-v:8b | junkpile | vision | ollama | 5.5 GB | 8B |
|
|
21
|
+
| hermes3:latest | junkpile | text | ollama | 4.7 GB | 8B |
|
|
22
|
+
| qwen2-vl-7b-... | fuji | vision | lmstudio | 4.2 GB | 7B |
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Implementation
|
|
26
|
+
|
|
27
|
+
### Step 1: Add CLI Command
|
|
28
|
+
|
|
29
|
+
**File**: `src/prompts/ai/cli.py`
|
|
30
|
+
|
|
31
|
+
Add `prompts ai inventory` command that:
|
|
32
|
+
1. Queries all three endpoints via `/v1/models` (OpenAI API)
|
|
33
|
+
2. For Ollama servers, also query `/api/tags` for detailed model info (size, params)
|
|
34
|
+
3. For LM Studio, parse `lms ls` output for additional details
|
|
35
|
+
4. Outputs a markdown table
|
|
36
|
+
|
|
37
|
+
### Step 2: Implementation Details
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
@ai.command()
|
|
41
|
+
def inventory():
|
|
42
|
+
"""List all models across all API servers."""
|
|
43
|
+
|
|
44
|
+
SERVERS = [
|
|
45
|
+
("junkpile", "192.168.0.26:11434", "ollama"),
|
|
46
|
+
("fuji", "127.0.0.1:11434", "ollama"),
|
|
47
|
+
("fuji", "127.0.0.1:1234", "lmstudio"),
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
for name, host, service in SERVERS:
|
|
51
|
+
client = VisionClient(host=host, backend=service)
|
|
52
|
+
models = client.list_models_detailed()
|
|
53
|
+
# Format and print table rows
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Step 3: Model Type Detection
|
|
57
|
+
|
|
58
|
+
Detect vision vs text models by:
|
|
59
|
+
- Check if model name contains vision keywords: `vision`, `-v`, `vl`, `llava`, `minicpm-v`
|
|
60
|
+
- Default to "text" if no match
|
|
61
|
+
|
|
62
|
+
## Verification
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
uv run prompts ai inventory
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Expected: Table with all models from all three servers, showing host, type, service, size.
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# Implementation Plan: Claude Code Context Detection
|
|
2
|
+
|
|
3
|
+
## Summary
|
|
4
|
+
|
|
5
|
+
Implement two deferred features from TODO.md:
|
|
6
|
+
1. **Auto-detect project_id for memory storage** - Automatically scope memories, decisions, knowledge to the current project
|
|
7
|
+
2. **Claude Code session ID detection** - Detect the active Claude Code session from `~/.claude/session-env/`
|
|
8
|
+
|
|
9
|
+
## Critical Files to Modify
|
|
10
|
+
|
|
11
|
+
| File | Changes |
|
|
12
|
+
|------|---------|
|
|
13
|
+
| `src/personality/utils/claude_context.py` | **NEW** - Claude Code environment detection utilities |
|
|
14
|
+
| `src/personality/mcp/server.py` | Add project detection to lifespan, expand AppContext |
|
|
15
|
+
| `src/personality/mcp/tools.py` | Pass project_id when storing memory/knowledge/decisions/sessions |
|
|
16
|
+
|
|
17
|
+
## Implementation Details
|
|
18
|
+
|
|
19
|
+
### 1. Create `src/personality/utils/claude_context.py`
|
|
20
|
+
|
|
21
|
+
New utility module for Claude Code environment detection:
|
|
22
|
+
|
|
23
|
+
```python
|
|
24
|
+
def get_claude_session_id() -> str | None:
|
|
25
|
+
"""Get current Claude Code session ID from ~/.claude/session-env/"""
|
|
26
|
+
# Find most recently modified directory by mtime
|
|
27
|
+
# Returns UUID string or None
|
|
28
|
+
|
|
29
|
+
def get_claude_project_dir() -> Path | None:
|
|
30
|
+
"""Get Claude Code project directory for current working directory."""
|
|
31
|
+
# Maps cwd /Users/chi/Projects/foo -> ~/.claude/projects/-Users-chi-Projects-foo
|
|
32
|
+
|
|
33
|
+
def detect_claude_context() -> ClaudeContext:
|
|
34
|
+
"""Detect full Claude Code context (session_id, project_dir)."""
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### 2. Update `src/personality/mcp/server.py`
|
|
38
|
+
|
|
39
|
+
**Expand AppContext dataclass:**
|
|
40
|
+
```python
|
|
41
|
+
@dataclass
|
|
42
|
+
class AppContext:
|
|
43
|
+
db: AsyncSession
|
|
44
|
+
settings: Settings
|
|
45
|
+
persona: str
|
|
46
|
+
project_id: UUID | None = None # NEW: auto-detected project
|
|
47
|
+
claude_session_id: str | None = None # NEW: Claude Code session
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**Update `app_lifespan()`:**
|
|
51
|
+
```python
|
|
52
|
+
async def app_lifespan(...):
|
|
53
|
+
# ... existing code ...
|
|
54
|
+
|
|
55
|
+
# Auto-detect project context
|
|
56
|
+
from personality.utils.project_context import detect_project_context
|
|
57
|
+
from personality.utils.claude_context import get_claude_session_id
|
|
58
|
+
|
|
59
|
+
project_ctx = detect_project_context()
|
|
60
|
+
project_id = await _get_or_create_project_id(db, project_ctx)
|
|
61
|
+
claude_session_id = get_claude_session_id()
|
|
62
|
+
|
|
63
|
+
yield AppContext(
|
|
64
|
+
db=db,
|
|
65
|
+
settings=settings,
|
|
66
|
+
persona=persona,
|
|
67
|
+
project_id=project_id,
|
|
68
|
+
claude_session_id=claude_session_id,
|
|
69
|
+
)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**Add helper function:**
|
|
73
|
+
```python
|
|
74
|
+
async def _get_or_create_project_id(db: AsyncSession, ctx: ProjectContext) -> UUID | None:
|
|
75
|
+
"""Look up project by git_url or name, create if not exists."""
|
|
76
|
+
if not ctx["is_git_repo"]:
|
|
77
|
+
return None # Only scope git repos
|
|
78
|
+
|
|
79
|
+
# Query by git_url first (most reliable), then by name
|
|
80
|
+
# Create if not found
|
|
81
|
+
# Return project.id
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### 3. Update `src/personality/mcp/tools.py`
|
|
85
|
+
|
|
86
|
+
**Memory store:**
|
|
87
|
+
```python
|
|
88
|
+
async def _memory_store(...):
|
|
89
|
+
new_memory = Memory(
|
|
90
|
+
persona=persona,
|
|
91
|
+
project_id=app.project_id, # ADD THIS
|
|
92
|
+
category=cat,
|
|
93
|
+
content=content,
|
|
94
|
+
embedding=embedding,
|
|
95
|
+
)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
**Knowledge link:**
|
|
99
|
+
```python
|
|
100
|
+
async def _knowledge_link(...):
|
|
101
|
+
new_rel = Knowledge(
|
|
102
|
+
persona=persona,
|
|
103
|
+
project_id=app.project_id, # ADD THIS
|
|
104
|
+
# ...
|
|
105
|
+
)
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**Decision record:**
|
|
109
|
+
```python
|
|
110
|
+
async def _decision_record(...):
|
|
111
|
+
new_decision = Decision(
|
|
112
|
+
persona=persona,
|
|
113
|
+
project_id=app.project_id, # ADD THIS
|
|
114
|
+
# ...
|
|
115
|
+
)
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
**Session start:**
|
|
119
|
+
```python
|
|
120
|
+
async def _session_start(...):
|
|
121
|
+
new_session = SessionModel(
|
|
122
|
+
persona=persona,
|
|
123
|
+
project_id=app.project_id, # ADD THIS
|
|
124
|
+
name=name,
|
|
125
|
+
state="active",
|
|
126
|
+
)
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Verification Plan
|
|
130
|
+
|
|
131
|
+
1. **Type checking:** `just types`
|
|
132
|
+
2. **Lint:** `just lint`
|
|
133
|
+
3. **Unit tests:** `just test -k "claude" or test -k "project"`
|
|
134
|
+
4. **Manual verification:**
|
|
135
|
+
- Start Claude Code in the personality project directory
|
|
136
|
+
- Use `memory store` tool and verify project_id is populated in DB
|
|
137
|
+
- Use `project` tool to confirm project context is detected
|
|
138
|
+
- Check that the session MCP tool creates sessions with project_id
|
|
139
|
+
|
|
140
|
+
## Notes
|
|
141
|
+
|
|
142
|
+
- The Session model already has a `project_id` field (FK to projects.id)
|
|
143
|
+
- All models (Memory, Knowledge, Decision, Session) already support project_id - we just need to populate it
|
|
144
|
+
- Claude session detection is informational for now; could be used later to correlate sessions
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Documentation Indexing Implementation Plan
|
|
2
|
+
|
|
3
|
+
## Objective
|
|
4
|
+
Add support for indexing documentation files (Markdown, RST, AsciiDoc, plain text) to the personality project's indexer with header-based chunking.
|
|
5
|
+
|
|
6
|
+
## Files to Modify
|
|
7
|
+
|
|
8
|
+
### 1. Schema Updates
|
|
9
|
+
**`src/personality/schemas/project_index.py`**
|
|
10
|
+
|
|
11
|
+
Add to `Language` enum:
|
|
12
|
+
```python
|
|
13
|
+
MARKDOWN = "markdown"
|
|
14
|
+
RST = "rst"
|
|
15
|
+
ASCIIDOC = "asciidoc"
|
|
16
|
+
PLAINTEXT = "plaintext"
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Add to `SymbolType` enum:
|
|
20
|
+
```python
|
|
21
|
+
SECTION = "section"
|
|
22
|
+
HEADING = "heading"
|
|
23
|
+
SUBHEADING = "subheading"
|
|
24
|
+
PARAGRAPH = "paragraph"
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### 2. New DocumentParser Service
|
|
28
|
+
**`src/personality/services/doc_parser.py`** (NEW FILE)
|
|
29
|
+
|
|
30
|
+
Create `DocumentParser` class with:
|
|
31
|
+
- `DOC_EXTENSION_MAP`: Maps `.md`, `.rst`, `.txt`, `.adoc` to Language enums
|
|
32
|
+
- `parse_file()`: Dispatches to format-specific parser
|
|
33
|
+
- `_parse_markdown()`: Header-based parsing (ATX `#` and setext underlines)
|
|
34
|
+
- `_parse_rst()`: Underline-based header parsing
|
|
35
|
+
- `_parse_asciidoc()`: `=` prefix header parsing
|
|
36
|
+
- `_parse_plaintext()`: Paragraph-based chunking (fallback)
|
|
37
|
+
- `_sections_to_symbols()`: Converts DocSection to Symbol with parent hierarchy
|
|
38
|
+
|
|
39
|
+
Key design: Each section stores parent heading context (e.g., "Installation > Prerequisites") for better semantic search.
|
|
40
|
+
|
|
41
|
+
### 3. Extension Map Update
|
|
42
|
+
**`src/personality/services/ast_parser.py`**
|
|
43
|
+
|
|
44
|
+
Add to `EXTENSION_MAP` (after line 141):
|
|
45
|
+
```python
|
|
46
|
+
# Documentation extensions
|
|
47
|
+
".md": LangEnum.MARKDOWN,
|
|
48
|
+
".markdown": LangEnum.MARKDOWN,
|
|
49
|
+
".rst": LangEnum.RST,
|
|
50
|
+
".txt": LangEnum.PLAINTEXT,
|
|
51
|
+
".text": LangEnum.PLAINTEXT,
|
|
52
|
+
".adoc": LangEnum.ASCIIDOC,
|
|
53
|
+
".asciidoc": LangEnum.ASCIIDOC,
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Add helper:
|
|
57
|
+
```python
|
|
58
|
+
DOC_LANGUAGES = {LangEnum.MARKDOWN, LangEnum.RST, LangEnum.ASCIIDOC, LangEnum.PLAINTEXT}
|
|
59
|
+
|
|
60
|
+
def is_doc_language(lang: LangEnum) -> bool:
|
|
61
|
+
return lang in DOC_LANGUAGES
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### 4. ProjectIndexer Updates
|
|
65
|
+
**`src/personality/services/project_indexer.py`**
|
|
66
|
+
|
|
67
|
+
| Method | Change |
|
|
68
|
+
|--------|--------|
|
|
69
|
+
| `__init__` | Add `self._doc_parser = DocumentParser()` |
|
|
70
|
+
| `_index_file` | Check `is_doc_language()`, use DocumentParser for docs |
|
|
71
|
+
| `_store_symbol` | Add `is_doc` param, use `doc.{type}.{path}` category prefix |
|
|
72
|
+
| `_delete_file_data` | Add `category_type` param ("code" or "doc") |
|
|
73
|
+
| `search` | Add `search_type` param ("all", "code", "doc") |
|
|
74
|
+
| `remove_project_index` | Delete both `code.*` and `doc.*` categories |
|
|
75
|
+
|
|
76
|
+
### 5. Service Exports
|
|
77
|
+
**`src/personality/services/__init__.py`**
|
|
78
|
+
|
|
79
|
+
Add `DocumentParser` to exports.
|
|
80
|
+
|
|
81
|
+
### 6. Tests
|
|
82
|
+
**`tests/test_services/test_doc_parser.py`** (NEW FILE)
|
|
83
|
+
|
|
84
|
+
Test cases:
|
|
85
|
+
- Markdown ATX headers (`#`, `##`, `###`)
|
|
86
|
+
- Markdown setext headers (underlines)
|
|
87
|
+
- RST underline headers
|
|
88
|
+
- AsciiDoc `=` prefix headers
|
|
89
|
+
- Plain text paragraph splitting
|
|
90
|
+
- Parent hierarchy preservation
|
|
91
|
+
- Empty file handling
|
|
92
|
+
- Language detection
|
|
93
|
+
|
|
94
|
+
## Category Structure
|
|
95
|
+
|
|
96
|
+
| Type | Category Pattern | Example |
|
|
97
|
+
|------|-----------------|---------|
|
|
98
|
+
| Code | `code.{symbol}.{path}` | `code.function.src/utils.py` |
|
|
99
|
+
| Docs | `doc.{section}.{path}` | `doc.heading.docs/README.md` |
|
|
100
|
+
|
|
101
|
+
## Verification
|
|
102
|
+
|
|
103
|
+
1. Run type check: `just types`
|
|
104
|
+
2. Run tests: `just test -k "doc_parser"`
|
|
105
|
+
3. Manual test:
|
|
106
|
+
```bash
|
|
107
|
+
personality project index /path/to/project --force
|
|
108
|
+
personality project search "installation instructions"
|
|
109
|
+
```
|
|
110
|
+
4. Verify memories are stored with `doc.*` categories in database
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Plan: Remove Explicit CivitAI Command Naming - Use Provider Pattern
|
|
2
|
+
|
|
3
|
+
## Summary
|
|
4
|
+
|
|
5
|
+
Refactor CLI to remove explicit `civitai` command naming. All CivitAI functionality should be accessed through generic commands with `--provider civitai` option (which is already the default).
|
|
6
|
+
|
|
7
|
+
## Current State
|
|
8
|
+
|
|
9
|
+
- **Main CLI (`src/prompts/cli.py`)**: Already has provider-aware commands (`search`, `tags`, `identify`) with `--provider` option
|
|
10
|
+
- **CivitAI CLI (`src/prompts/civitai/cli.py`)**: Has `civitai` command group with subcommands
|
|
11
|
+
- **Problem**: Both paths work, creating duplication:
|
|
12
|
+
- `prompts search illustrious` → provider pattern ✓
|
|
13
|
+
- `prompts civitai search illustrious` → explicit naming (to remove)
|
|
14
|
+
- **Slash command** `civitai/identify.md` uses explicit `prompts civitai identify`
|
|
15
|
+
|
|
16
|
+
## Changes Required
|
|
17
|
+
|
|
18
|
+
### 1. Remove civitai subcommand registration from main CLI
|
|
19
|
+
|
|
20
|
+
**File:** `src/prompts/cli.py:185`
|
|
21
|
+
|
|
22
|
+
Remove line:
|
|
23
|
+
```python
|
|
24
|
+
main.add_command(civitai)
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
This stops exposing `prompts civitai` as a command group. The underlying functions remain available internally.
|
|
28
|
+
|
|
29
|
+
### 2. Update slash command to use provider pattern
|
|
30
|
+
|
|
31
|
+
**File:** `.claude/commands/civitai/identify.md`
|
|
32
|
+
|
|
33
|
+
Change from:
|
|
34
|
+
```bash
|
|
35
|
+
uv run prompts civitai identify $ARGUMENTS
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
To:
|
|
39
|
+
```bash
|
|
40
|
+
uv run prompts identify $ARGUMENTS
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Also update examples to use `prompts identify` instead of `prompts civitai identify`.
|
|
44
|
+
|
|
45
|
+
### 3. Move slash command out of civitai directory
|
|
46
|
+
|
|
47
|
+
Rename/move:
|
|
48
|
+
- `.claude/commands/civitai/identify.md` → `.claude/commands/models/identify.md`
|
|
49
|
+
|
|
50
|
+
This groups it with other model-related commands and removes the civitai-specific directory.
|
|
51
|
+
|
|
52
|
+
## Files to Modify
|
|
53
|
+
|
|
54
|
+
| File | Change |
|
|
55
|
+
|------|--------|
|
|
56
|
+
| `src/prompts/cli.py` | Remove `main.add_command(civitai)` |
|
|
57
|
+
| `.claude/commands/civitai/identify.md` | Delete after creating new file |
|
|
58
|
+
| `.claude/commands/models/identify.md` | Create with updated content |
|
|
59
|
+
|
|
60
|
+
## Verification
|
|
61
|
+
|
|
62
|
+
1. Test that `prompts civitai search` no longer works (removed)
|
|
63
|
+
2. Test that `prompts search` still works (provider pattern)
|
|
64
|
+
3. Test that `prompts identify` still works
|
|
65
|
+
4. Test `/models:identify` slash command
|