mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-03-01 13:43:54 +08:00
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:
@@ -111,7 +111,7 @@ rm -f .workflow/archives/$SESSION_ID/.archiving
|
||||
|
||||
### Phase 4: Auto-Sync Project State
|
||||
|
||||
Execute `/workflow:session:sync -y "{description}"` to update both `project-guidelines.json` and `project-tech.json` from session context.
|
||||
Execute `/workflow:session:sync -y "{description}"` to update both `specs/*.md` and `project-tech.json` from session context.
|
||||
|
||||
Description 取自 Phase 2 的 `workflow-session.json` description 字段。
|
||||
|
||||
@@ -135,5 +135,5 @@ When `--yes` or `-y` flag is used:
|
||||
Phase 1: find session → create .archiving marker
|
||||
Phase 2: read key files → build manifest entry (no writes)
|
||||
Phase 3: mkdir → mv → update manifest.json → rm marker
|
||||
Phase 4: /workflow:session:sync -y → update project-guidelines + project-tech
|
||||
Phase 4: /workflow:session:sync -y → update specs/*.md + project-tech
|
||||
```
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -44,7 +44,7 @@ ERROR: Invalid session type. Valid types: workflow, review, tdd, test, docs
|
||||
```bash
|
||||
# Check if project state exists (both files required)
|
||||
bash(test -f .workflow/project-tech.json && echo "TECH_EXISTS" || echo "TECH_NOT_FOUND")
|
||||
bash(test -f .workflow/project-guidelines.json && echo "GUIDELINES_EXISTS" || echo "GUIDELINES_NOT_FOUND")
|
||||
bash(test -f .workflow/specs/*.md && echo "GUIDELINES_EXISTS" || echo "GUIDELINES_NOT_FOUND")
|
||||
```
|
||||
|
||||
**If either NOT_FOUND**, delegate to `/workflow:init`:
|
||||
@@ -53,14 +53,14 @@ bash(test -f .workflow/project-guidelines.json && echo "GUIDELINES_EXISTS" || ec
|
||||
Skill(skill="workflow:init");
|
||||
|
||||
// Wait for init completion
|
||||
// project-tech.json and project-guidelines.json will be created
|
||||
// project-tech.json and specs/*.md will be created
|
||||
```
|
||||
|
||||
**Output**:
|
||||
- If BOTH_EXIST: `PROJECT_STATE: initialized`
|
||||
- If NOT_FOUND: Calls `/workflow:init` → creates:
|
||||
- `.workflow/project-tech.json` with full technical analysis
|
||||
- `.workflow/project-guidelines.json` with empty scaffold
|
||||
- `.workflow/specs/*.md` with empty scaffold
|
||||
|
||||
**Note**: `/workflow:init` uses cli-explore-agent to build comprehensive project understanding (technology stack, architecture, key components). This step runs once per project. Subsequent executions skip initialization.
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
---
|
||||
name: sync
|
||||
description: Quick-sync session work to project-guidelines and project-tech
|
||||
description: Quick-sync session work to specs/*.md and project-tech
|
||||
argument-hint: "[-y|--yes] [\"what was done\"]"
|
||||
allowed-tools: Bash(*), Read(*), Write(*), Edit(*)
|
||||
---
|
||||
|
||||
# Session Sync (/workflow:session:sync)
|
||||
|
||||
One-shot update `project-guidelines.json` + `project-tech.json` from current session context.
|
||||
One-shot update `specs/*.md` + `project-tech.json` from current session context.
|
||||
|
||||
**Design**: Scan context → extract → write. No interactive wizards.
|
||||
|
||||
@@ -73,7 +73,8 @@ Analyze context and produce two update payloads. Use LLM reasoning (current agen
|
||||
// RULE: Only extract genuinely reusable insights. Skip trivial/obvious items.
|
||||
// RULE: Deduplicate against existing guidelines before adding.
|
||||
|
||||
const existingGuidelines = JSON.parse(Read('.workflow/project-guidelines.json'))
|
||||
// Load existing specs via ccw spec load
|
||||
const existingSpecs = Bash('ccw spec load --dimension specs 2>/dev/null || echo ""')
|
||||
const guidelineUpdates = [] // populated by agent analysis
|
||||
|
||||
// ── Tech extraction ──
|
||||
@@ -123,7 +124,7 @@ Tech [${detectCategory(summary)}]:
|
||||
${techEntry.title}
|
||||
|
||||
Target files:
|
||||
.workflow/project-guidelines.json
|
||||
.workflow/specs/*.md
|
||||
.workflow/project-tech.json
|
||||
`)
|
||||
|
||||
@@ -136,33 +137,31 @@ if (!autoYes) {
|
||||
## Step 4: Write
|
||||
|
||||
```javascript
|
||||
// ── Update project-guidelines.json ──
|
||||
// ── Update specs/*.md ──
|
||||
if (guidelineUpdates.length > 0) {
|
||||
const guidelines = JSON.parse(Read('.workflow/project-guidelines.json'))
|
||||
// Map guideline types to spec files
|
||||
const specFileMap = {
|
||||
convention: '.workflow/specs/coding-conventions.md',
|
||||
constraint: '.workflow/specs/architecture-constraints.md',
|
||||
learning: '.workflow/specs/coding-conventions.md' // learnings appended to conventions
|
||||
}
|
||||
|
||||
for (const g of guidelineUpdates) {
|
||||
if (g.type === 'learning') {
|
||||
// Deduplicate by insight text
|
||||
if (!guidelines.learnings.some(l => l.insight === g.text)) {
|
||||
guidelines.learnings.push({
|
||||
date: new Date().toISOString().split('T')[0],
|
||||
session_id: techEntry.session_id,
|
||||
insight: g.text,
|
||||
category: g.category
|
||||
})
|
||||
}
|
||||
} else {
|
||||
// convention or constraint
|
||||
const section = g.type === 'convention' ? 'conventions' : 'constraints'
|
||||
if (!guidelines[section][g.category]) guidelines[section][g.category] = []
|
||||
if (!guidelines[section][g.category].includes(g.text)) {
|
||||
guidelines[section][g.category].push(g.text)
|
||||
}
|
||||
const targetFile = specFileMap[g.type]
|
||||
const existing = Read(targetFile)
|
||||
const ruleText = g.type === 'learning'
|
||||
? `- [${g.category}] ${g.text} (learned: ${new Date().toISOString().split('T')[0]})`
|
||||
: `- [${g.category}] ${g.text}`
|
||||
|
||||
// Deduplicate: skip if text already in file
|
||||
if (!existing.includes(g.text)) {
|
||||
const newContent = existing.trimEnd() + '\n' + ruleText + '\n'
|
||||
Write(targetFile, newContent)
|
||||
}
|
||||
}
|
||||
|
||||
guidelines._metadata.updated_at = new Date().toISOString()
|
||||
Write('.workflow/project-guidelines.json', JSON.stringify(guidelines, null, 2))
|
||||
// Rebuild spec index after writing
|
||||
Bash('ccw spec rebuild')
|
||||
}
|
||||
|
||||
// ── Update project-tech.json ──
|
||||
|
||||
Reference in New Issue
Block a user