feat: add SpecDialog component for editing spec frontmatter

- Implement SpecDialog for managing spec details including title, read mode, priority, and keywords.
- Add validation and keyword management functionality.
- Integrate SpecDialog into SpecsSettingsPage for editing specs.

feat: create index file for specs components

- Export SpecCard, SpecDialog, and related types from a new index file for better organization.

feat: implement SpecsSettingsPage for managing specs and hooks

- Create main settings page with tabs for Project Specs, Personal Specs, Hooks, Injection, and Settings.
- Integrate SpecDialog and HookDialog for editing specs and hooks.
- Add search functionality and mock data for specs and hooks.

feat: add spec management API routes

- Implement API endpoints for listing specs, getting spec details, updating frontmatter, rebuilding indices, and initializing the spec system.
- Handle errors and responses appropriately for each endpoint.
This commit is contained in:
catlog22
2026-02-26 22:03:13 +08:00
parent 430d817e43
commit 6155fcc7b8
115 changed files with 4883 additions and 21127 deletions

View File

@@ -18,7 +18,7 @@ When `--yes` or `-y`: Auto-categorize and add guideline without confirmation.
## Overview
Crystallizes ephemeral session context (insights, decisions, constraints) into permanent project guidelines stored in `.workflow/project-guidelines.json`. This ensures valuable learnings persist across sessions and inform future planning.
Crystallizes ephemeral session context (insights, decisions, constraints) into permanent project guidelines stored in `.workflow/specs/*.md`. This ensures valuable learnings persist across sessions and inform future planning.
## Use Cases
@@ -113,34 +113,14 @@ ELSE (convention/constraint/learning):
### Step 1: Ensure Guidelines File Exists
```bash
bash(test -f .workflow/project-guidelines.json && echo "EXISTS" || echo "NOT_FOUND")
bash(test -f .workflow/specs/coding-conventions.md && echo "EXISTS" || echo "NOT_FOUND")
```
**If NOT_FOUND**, create scaffold:
**If NOT_FOUND**, initialize spec system:
```javascript
const scaffold = {
conventions: {
coding_style: [],
naming_patterns: [],
file_structure: [],
documentation: []
},
constraints: {
architecture: [],
tech_stack: [],
performance: [],
security: []
},
quality_rules: [],
learnings: [],
_metadata: {
created_at: new Date().toISOString(),
version: "1.0.0"
}
};
Write('.workflow/project-guidelines.json', JSON.stringify(scaffold, null, 2));
```bash
Bash('ccw spec init')
Bash('ccw spec rebuild')
```
### Step 2: Auto-detect Type (if not specified)
@@ -203,33 +183,40 @@ function buildEntry(rule, type, category, sessionId) {
}
```
### Step 4: Update Guidelines File
### Step 4: Update Spec Files
```javascript
const guidelines = JSON.parse(Read('.workflow/project-guidelines.json'));
if (type === 'convention') {
if (!guidelines.conventions[category]) {
guidelines.conventions[category] = [];
}
if (!guidelines.conventions[category].includes(rule)) {
guidelines.conventions[category].push(rule);
}
} else if (type === 'constraint') {
if (!guidelines.constraints[category]) {
guidelines.constraints[category] = [];
}
if (!guidelines.constraints[category].includes(rule)) {
guidelines.constraints[category].push(rule);
}
} else if (type === 'learning') {
guidelines.learnings.push(buildEntry(rule, type, category, sessionId));
// Map type+category to target spec file
const specFileMap = {
convention: '.workflow/specs/coding-conventions.md',
constraint: '.workflow/specs/architecture-constraints.md'
}
guidelines._metadata.updated_at = new Date().toISOString();
guidelines._metadata.last_solidified_by = sessionId;
if (type === 'convention' || type === 'constraint') {
const targetFile = specFileMap[type]
const existing = Read(targetFile)
Write('.workflow/project-guidelines.json', JSON.stringify(guidelines, null, 2));
// Deduplicate: skip if rule text already exists in the file
if (!existing.includes(rule)) {
const ruleText = `- [${category}] ${rule}`
const newContent = existing.trimEnd() + '\n' + ruleText + '\n'
Write(targetFile, newContent)
}
} else if (type === 'learning') {
// Learnings go to coding-conventions.md as a special section
const targetFile = '.workflow/specs/coding-conventions.md'
const existing = Read(targetFile)
const entry = buildEntry(rule, type, category, sessionId)
const learningText = `- [learning/${category}] ${entry.insight} (${entry.date})`
if (!existing.includes(entry.insight)) {
const newContent = existing.trimEnd() + '\n' + learningText + '\n'
Write(targetFile, newContent)
}
}
// Rebuild spec index after modification
Bash('ccw spec rebuild')
```
### Step 5: Display Confirmation
@@ -241,7 +228,7 @@ Type: ${type}
Category: ${category}
Rule: "${rule}"
Location: .workflow/project-guidelines.json -> ${type}s.${category}
Location: .workflow/specs/*.md -> ${type}s.${category}
Total ${type}s in ${category}: ${count}
```
@@ -386,7 +373,7 @@ AskUserQuestion({
/workflow:session:solidify "Use async/await instead of callbacks" --type convention --category coding_style
```
Result in `project-guidelines.json`:
Result in `specs/*.md`:
```json
{
"conventions": {
@@ -444,7 +431,7 @@ Result: Creates a new CMEM with consolidated content from the 10 most recent non
## Integration with Planning
The `project-guidelines.json` is consumed by:
The `specs/*.md` is consumed by:
1. **`workflow-plan` skill (context-gather phase)**: Loads guidelines into context-package.json
2. **`workflow-plan` skill**: Passes guidelines to task generation agent
@@ -462,4 +449,4 @@ This ensures all future planning respects solidified rules without users needing
- `/workflow:session:start` - Start a session (may prompt for solidify at end)
- `/workflow:session:complete` - Complete session (prompts for learnings to solidify)
- `/workflow:init` - Creates project-guidelines.json scaffold if missing
- `/workflow:init` - Creates specs/*.md scaffold if missing