fix: align spec paths from .workflow/specs to .ccw/specs

- Fix path mismatch between command files and frontend/backend spec-index-builder
- Update init-specs.md, init-guidelines.md, sync.md, solidify.md to use .ccw/specs/
- Update init.md, start.md, clean.md, unified-execute-with-file.md, collaborative-plan-with-file.md
- Add scope field to architecture-constraints.md and coding-conventions.md
- Ensures specs created by commands are visible in frontend Spec Settings page
This commit is contained in:
catlog22
2026-03-01 13:28:54 +08:00
parent 8ceae6d6fd
commit ecf4e4d848
11 changed files with 65 additions and 68 deletions

View File

@@ -9,6 +9,7 @@ keywords:
- pattern - pattern
readMode: required readMode: required
priority: high priority: high
scope: project
--- ---
# Architecture Constraints # Architecture Constraints

View File

@@ -9,6 +9,7 @@ keywords:
- convention - convention
readMode: required readMode: required
priority: high priority: high
scope: project
--- ---
# Coding Conventions # Coding Conventions

View File

@@ -496,7 +496,7 @@ if (fileExists(projectPath)) {
} }
// Update specs/*.md: remove learnings referencing deleted sessions // Update specs/*.md: remove learnings referencing deleted sessions
const guidelinesPath = '.workflow/specs/*.md' const guidelinesPath = '.ccw/specs/*.md'
if (fileExists(guidelinesPath)) { if (fileExists(guidelinesPath)) {
const guidelines = JSON.parse(Read(guidelinesPath)) const guidelines = JSON.parse(Read(guidelinesPath))
const deletedSessionIds = results.deleted const deletedSessionIds = results.deleted

View File

@@ -208,7 +208,7 @@ Task(
### Project Context (MANDATORY) ### Project Context (MANDATORY)
Read and incorporate: Read and incorporate:
- \`.workflow/project-tech.json\` (if exists): Technology stack, architecture - \`.workflow/project-tech.json\` (if exists): Technology stack, architecture
- \`.workflow/specs/*.md\` (if exists): Constraints, conventions -- apply as HARD CONSTRAINTS on sub-domain splitting and plan structure - \`.ccw/specs/*.md\` (if exists): Constraints, conventions -- apply as HARD CONSTRAINTS on sub-domain splitting and plan structure
### Input Requirements ### Input Requirements
${taskDescription} ${taskDescription}
@@ -357,7 +357,7 @@ subDomains.map(sub =>
### Project Context (MANDATORY) ### Project Context (MANDATORY)
Read and incorporate: Read and incorporate:
- \`.workflow/project-tech.json\` (if exists): Technology stack, architecture - \`.workflow/project-tech.json\` (if exists): Technology stack, architecture
- \`.workflow/specs/*.md\` (if exists): Constraints, conventions -- apply as HARD CONSTRAINTS - \`.ccw/specs/*.md\` (if exists): Constraints, conventions -- apply as HARD CONSTRAINTS
## Dual Output Tasks ## Dual Output Tasks

View File

@@ -11,7 +11,7 @@ examples:
## Overview ## Overview
Interactive multi-round wizard that analyzes the current project (via `project-tech.json`) and asks targeted questions to populate `.workflow/specs/*.md` with coding conventions, constraints, and quality rules. Interactive multi-round wizard that analyzes the current project (via `project-tech.json`) and asks targeted questions to populate `.ccw/specs/*.md` with coding conventions, constraints, and quality rules.
**Design Principle**: Questions are dynamically generated based on the project's tech stack, architecture, and patterns — not generic boilerplate. **Design Principle**: Questions are dynamically generated based on the project's tech stack, architecture, and patterns — not generic boilerplate.
@@ -55,7 +55,7 @@ Step 5: Display Summary
```bash ```bash
bash(test -f .workflow/project-tech.json && echo "TECH_EXISTS" || echo "TECH_NOT_FOUND") bash(test -f .workflow/project-tech.json && echo "TECH_EXISTS" || echo "TECH_NOT_FOUND")
bash(test -f .workflow/specs/coding-conventions.md && echo "SPECS_EXISTS" || echo "SPECS_NOT_FOUND") bash(test -f .ccw/specs/coding-conventions.md && echo "SPECS_EXISTS" || echo "SPECS_NOT_FOUND")
``` ```
**If TECH_NOT_FOUND**: Exit with message **If TECH_NOT_FOUND**: Exit with message
@@ -332,9 +332,16 @@ For each category of collected answers, append rules to the corresponding spec M
```javascript ```javascript
// Helper: append rules to a spec MD file with category support // Helper: append rules to a spec MD file with category support
// Uses .ccw/specs/ directory (same as frontend/backend spec-index-builder)
function appendRulesToSpecFile(filePath, rules, defaultCategory = 'general') { function appendRulesToSpecFile(filePath, rules, defaultCategory = 'general') {
if (rules.length === 0) return if (rules.length === 0) return
// Ensure .ccw/specs/ directory exists
const specDir = path.dirname(filePath)
if (!fs.existsSync(specDir)) {
fs.mkdirSync(specDir, { recursive: true })
}
// Check if file exists // Check if file exists
if (!file_exists(filePath)) { if (!file_exists(filePath)) {
// Create file with frontmatter including category // Create file with frontmatter including category
@@ -360,19 +367,19 @@ keywords: [${defaultCategory}, ${filePath.includes('conventions') ? 'convention'
Write(filePath, newContent) Write(filePath, newContent)
} }
// Write conventions (general category) // Write conventions (general category) - use .ccw/specs/ (same as frontend/backend)
appendRulesToSpecFile('.workflow/specs/coding-conventions.md', appendRulesToSpecFile('.ccw/specs/coding-conventions.md',
[...newCodingStyle, ...newNamingPatterns, ...newFileStructure, ...newDocumentation], [...newCodingStyle, ...newNamingPatterns, ...newFileStructure, ...newDocumentation],
'general') 'general')
// Write constraints (planning category) // Write constraints (planning category)
appendRulesToSpecFile('.workflow/specs/architecture-constraints.md', appendRulesToSpecFile('.ccw/specs/architecture-constraints.md',
[...newArchitecture, ...newTechStack, ...newPerformance, ...newSecurity], [...newArchitecture, ...newTechStack, ...newPerformance, ...newSecurity],
'planning') 'planning')
// Write quality rules (execution category) // Write quality rules (execution category)
if (newQualityRules.length > 0) { if (newQualityRules.length > 0) {
const qualityPath = '.workflow/specs/quality-rules.md' const qualityPath = '.ccw/specs/quality-rules.md'
if (!file_exists(qualityPath)) { if (!file_exists(qualityPath)) {
Write(qualityPath, `--- Write(qualityPath, `---
title: Quality Rules title: Quality Rules

View File

@@ -54,7 +54,7 @@ Step 1: Gather Requirements (Interactive)
└─ Ask content (rule text) └─ Ask content (rule text)
Step 2: Determine Target File Step 2: Determine Target File
├─ specs dimension → .workflow/specs/coding-conventions.md or architecture-constraints.md ├─ specs dimension → .ccw/specs/coding-conventions.md or architecture-constraints.md
└─ personal dimension → ~/.ccw/specs/personal/ or .ccw/specs/personal/ └─ personal dimension → ~/.ccw/specs/personal/ or .ccw/specs/personal/
Step 3: Write Spec Step 3: Write Spec
@@ -109,7 +109,7 @@ if (!dimension) {
options: [ options: [
{ {
label: "Project Spec", label: "Project Spec",
description: "Coding conventions, constraints, quality rules for this project (stored in .workflow/specs/)" description: "Coding conventions, constraints, quality rules for this project (stored in .ccw/specs/)"
}, },
{ {
label: "Personal Spec", label: "Personal Spec",
@@ -234,19 +234,19 @@ let targetFile: string
let targetDir: string let targetDir: string
if (dimension === 'specs') { if (dimension === 'specs') {
// Project specs // Project specs - use .ccw/specs/ (same as frontend/backend spec-index-builder)
targetDir = '.workflow/specs' targetDir = '.ccw/specs'
if (isConstraint) { if (isConstraint) {
targetFile = path.join(targetDir, 'architecture-constraints.md') targetFile = path.join(targetDir, 'architecture-constraints.md')
} else { } else {
targetFile = path.join(targetDir, 'coding-conventions.md') targetFile = path.join(targetDir, 'coding-conventions.md')
} }
} else { } else {
// Personal specs // Personal specs - use .ccw/personal/ (same as backend spec-index-builder)
if (scope === 'global') { if (scope === 'global') {
targetDir = path.join(os.homedir(), '.ccw', 'specs', 'personal') targetDir = path.join(os.homedir(), '.ccw', 'personal')
} else { } else {
targetDir = path.join('.ccw', 'specs', 'personal') targetDir = path.join('.ccw', 'personal')
} }
// Create category-based filename // Create category-based filename
@@ -333,7 +333,7 @@ Use 'ccw spec load --category ${category}' to load specs by category
### Project Specs (dimension: specs) ### Project Specs (dimension: specs)
``` ```
.workflow/specs/ .ccw/specs/
├── coding-conventions.md ← conventions, learnings ├── coding-conventions.md ← conventions, learnings
├── architecture-constraints.md ← constraints ├── architecture-constraints.md ← constraints
└── quality-rules.md ← quality rules └── quality-rules.md ← quality rules
@@ -341,14 +341,14 @@ Use 'ccw spec load --category ${category}' to load specs by category
### Personal Specs (dimension: personal) ### Personal Specs (dimension: personal)
``` ```
# Global (~/.ccw/specs/personal/) # Global (~/.ccw/personal/)
~/.ccw/specs/personal/ ~/.ccw/personal/
├── conventions.md ← personal conventions (all projects) ├── conventions.md ← personal conventions (all projects)
├── constraints.md ← personal constraints (all projects) ├── constraints.md ← personal constraints (all projects)
└── learnings.md ← personal learnings (all projects) └── learnings.md ← personal learnings (all projects)
# Project-local (.ccw/specs/personal/) # Project-local (.ccw/personal/)
.ccw/specs/personal/ .ccw/personal/
├── conventions.md ← personal conventions (this project only) ├── conventions.md ← personal conventions (this project only)
├── constraints.md ← personal constraints (this project only) ├── constraints.md ← personal constraints (this project only)
└── learnings.md ← personal learnings (this project only) └── learnings.md ← personal learnings (this project only)

View File

@@ -11,7 +11,7 @@ examples:
# Workflow Init Command (/workflow:init) # Workflow Init Command (/workflow:init)
## Overview ## Overview
Initialize `.workflow/project-tech.json` and `.workflow/specs/*.md` with comprehensive project understanding by delegating analysis to **cli-explore-agent**. Initialize `.workflow/project-tech.json` and `.ccw/specs/*.md` with comprehensive project understanding by delegating analysis to **cli-explore-agent**.
**Dual File System**: **Dual File System**:
- `project-tech.json`: Auto-generated technical analysis (stack, architecture, components) - `project-tech.json`: Auto-generated technical analysis (stack, architecture, components)
@@ -58,7 +58,7 @@ Analysis Flow:
Output: Output:
├─ .workflow/project-tech.json (+ .backup if regenerate) ├─ .workflow/project-tech.json (+ .backup if regenerate)
└─ .workflow/specs/*.md (scaffold or configured, unless --skip-specs) └─ .ccw/specs/*.md (scaffold or configured, unless --skip-specs)
``` ```
## Implementation ## Implementation
@@ -75,14 +75,14 @@ const skipSpecs = $ARGUMENTS.includes('--skip-specs')
```bash ```bash
bash(test -f .workflow/project-tech.json && echo "TECH_EXISTS" || echo "TECH_NOT_FOUND") bash(test -f .workflow/project-tech.json && echo "TECH_EXISTS" || echo "TECH_NOT_FOUND")
bash(test -f .workflow/specs/coding-conventions.md && echo "SPECS_EXISTS" || echo "SPECS_NOT_FOUND") bash(test -f .ccw/specs/coding-conventions.md && echo "SPECS_EXISTS" || echo "SPECS_NOT_FOUND")
``` ```
**If BOTH_EXIST and no --regenerate**: Exit early **If BOTH_EXIST and no --regenerate**: Exit early
``` ```
Project already initialized: Project already initialized:
- Tech analysis: .workflow/project-tech.json - Tech analysis: .workflow/project-tech.json
- Guidelines: .workflow/specs/*.md - Guidelines: .ccw/specs/*.md
Use /workflow:init --regenerate to rebuild tech analysis Use /workflow:init --regenerate to rebuild tech analysis
Use /workflow:session:solidify to add guidelines Use /workflow:session:solidify to add guidelines
@@ -171,7 +171,7 @@ Project root: ${projectRoot}
// Skip spec initialization if --skip-specs flag is provided // Skip spec initialization if --skip-specs flag is provided
if (!skipSpecs) { if (!skipSpecs) {
// Initialize spec system if not already initialized // Initialize spec system if not already initialized
const specsCheck = Bash('test -f .workflow/specs/coding-conventions.md && echo EXISTS || echo NOT_FOUND') const specsCheck = Bash('test -f .ccw/specs/coding-conventions.md && echo EXISTS || echo NOT_FOUND')
if (specsCheck.includes('NOT_FOUND')) { if (specsCheck.includes('NOT_FOUND')) {
console.log('Initializing spec system...') console.log('Initializing spec system...')
Bash('ccw spec init') Bash('ccw spec init')
@@ -186,7 +186,7 @@ if (!skipSpecs) {
```javascript ```javascript
const projectTech = JSON.parse(Read('.workflow/project-tech.json')); const projectTech = JSON.parse(Read('.workflow/project-tech.json'));
const specsInitialized = !skipSpecs && file_exists('.workflow/specs/coding-conventions.md'); const specsInitialized = !skipSpecs && file_exists('.ccw/specs/coding-conventions.md');
console.log(` console.log(`
Project initialized successfully Project initialized successfully
@@ -206,7 +206,7 @@ Components: ${projectTech.overview.key_components.length} core modules
--- ---
Files created: Files created:
- Tech analysis: .workflow/project-tech.json - Tech analysis: .workflow/project-tech.json
${!skipSpecs ? `- Specs: .workflow/specs/ ${specsInitialized ? '(initialized)' : ''}` : '- Specs: (skipped via --skip-specs)'} ${!skipSpecs ? `- Specs: .ccw/specs/ ${specsInitialized ? '(initialized)' : ''}` : '- Specs: (skipped via --skip-specs)'}
${regenerate ? '- Backup: .workflow/project-tech.json.backup' : ''} ${regenerate ? '- Backup: .workflow/project-tech.json.backup' : ''}
`); `);
``` ```

View File

@@ -18,7 +18,7 @@ When `--yes` or `-y`: Auto-categorize and add guideline without confirmation.
## Overview ## Overview
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. Crystallizes ephemeral session context (insights, decisions, constraints) into permanent project guidelines stored in `.ccw/specs/*.md`. This ensures valuable learnings persist across sessions and inform future planning.
## Use Cases ## Use Cases
@@ -112,8 +112,10 @@ ELSE (convention/constraint/learning):
### Step 1: Ensure Guidelines File Exists ### Step 1: Ensure Guidelines File Exists
**Uses .ccw/specs/ directory (same as frontend/backend spec-index-builder)**
```bash ```bash
bash(test -f .workflow/specs/coding-conventions.md && echo "EXISTS" || echo "NOT_FOUND") bash(test -f .ccw/specs/coding-conventions.md && echo "EXISTS" || echo "NOT_FOUND")
``` ```
**If NOT_FOUND**, initialize spec system: **If NOT_FOUND**, initialize spec system:
@@ -187,9 +189,10 @@ function buildEntry(rule, type, category, sessionId) {
```javascript ```javascript
// Map type+category to target spec file // Map type+category to target spec file
// Uses .ccw/specs/ directory (same as frontend/backend spec-index-builder)
const specFileMap = { const specFileMap = {
convention: '.workflow/specs/coding-conventions.md', convention: '.ccw/specs/coding-conventions.md',
constraint: '.workflow/specs/architecture-constraints.md' constraint: '.ccw/specs/architecture-constraints.md'
} }
if (type === 'convention' || type === 'constraint') { if (type === 'convention' || type === 'constraint') {
@@ -204,7 +207,8 @@ if (type === 'convention' || type === 'constraint') {
} }
} else if (type === 'learning') { } else if (type === 'learning') {
// Learnings go to coding-conventions.md as a special section // Learnings go to coding-conventions.md as a special section
const targetFile = '.workflow/specs/coding-conventions.md' // Uses .ccw/specs/ directory (same as frontend/backend spec-index-builder)
const targetFile = '.ccw/specs/coding-conventions.md'
const existing = Read(targetFile) const existing = Read(targetFile)
const entry = buildEntry(rule, type, category, sessionId) const entry = buildEntry(rule, type, category, sessionId)
const learningText = `- [learning/${category}] ${entry.insight} (${entry.date})` const learningText = `- [learning/${category}] ${entry.insight} (${entry.date})`
@@ -228,7 +232,7 @@ Type: ${type}
Category: ${category} Category: ${category}
Rule: "${rule}" Rule: "${rule}"
Location: .workflow/specs/*.md -> ${type}s.${category} Location: .ccw/specs/*.md -> ${type}s.${category}
Total ${type}s in ${category}: ${count} Total ${type}s in ${category}: ${count}
``` ```
@@ -373,13 +377,9 @@ AskUserQuestion({
/workflow:session:solidify "Use async/await instead of callbacks" --type convention --category coding_style /workflow:session:solidify "Use async/await instead of callbacks" --type convention --category coding_style
``` ```
Result in `specs/*.md`: Result in `.ccw/specs/coding-conventions.md`:
```json ```markdown
{ - [coding_style] Use async/await instead of callbacks
"conventions": {
"coding_style": ["Use async/await instead of callbacks"]
}
}
``` ```
### Add an Architectural Constraint ### Add an Architectural Constraint
@@ -387,13 +387,9 @@ Result in `specs/*.md`:
/workflow:session:solidify "No direct DB access from controllers" --type constraint --category architecture /workflow:session:solidify "No direct DB access from controllers" --type constraint --category architecture
``` ```
Result: Result in `.ccw/specs/architecture-constraints.md`:
```json ```markdown
{ - [architecture] No direct DB access from controllers
"constraints": {
"architecture": ["No direct DB access from controllers"]
}
}
``` ```
### Capture a Session Learning ### Capture a Session Learning
@@ -401,18 +397,9 @@ Result:
/workflow:session:solidify "Cache invalidation requires event sourcing for consistency" --type learning /workflow:session:solidify "Cache invalidation requires event sourcing for consistency" --type learning
``` ```
Result: Result in `.ccw/specs/coding-conventions.md`:
```json ```markdown
{ - [learning/architecture] Cache invalidation requires event sourcing for consistency (2024-12-28)
"learnings": [
{
"date": "2024-12-28",
"session_id": "WFS-auth-feature",
"insight": "Cache invalidation requires event sourcing for consistency",
"category": "architecture"
}
]
}
``` ```
### Compress Recent Memories ### Compress Recent Memories

View File

@@ -44,7 +44,7 @@ ERROR: Invalid session type. Valid types: workflow, review, tdd, test, docs
```bash ```bash
# Check if project state exists (both files required) # 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-tech.json && echo "TECH_EXISTS" || echo "TECH_NOT_FOUND")
bash(test -f .workflow/specs/*.md && echo "GUIDELINES_EXISTS" || echo "GUIDELINES_NOT_FOUND") bash(test -f .ccw/specs/*.md && echo "GUIDELINES_EXISTS" || echo "GUIDELINES_NOT_FOUND")
``` ```
**If either NOT_FOUND**, delegate to `/workflow:init`: **If either NOT_FOUND**, delegate to `/workflow:init`:
@@ -60,7 +60,7 @@ Skill(skill="workflow:init");
- If BOTH_EXIST: `PROJECT_STATE: initialized` - If BOTH_EXIST: `PROJECT_STATE: initialized`
- If NOT_FOUND: Calls `/workflow:init` → creates: - If NOT_FOUND: Calls `/workflow:init` → creates:
- `.workflow/project-tech.json` with full technical analysis - `.workflow/project-tech.json` with full technical analysis
- `.workflow/specs/*.md` with empty scaffold - `.ccw/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. **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.

View File

@@ -124,7 +124,7 @@ Tech [${detectCategory(summary)}]:
${techEntry.title} ${techEntry.title}
Target files: Target files:
.workflow/specs/*.md .ccw/specs/*.md
.workflow/project-tech.json .workflow/project-tech.json
`) `)
@@ -138,12 +138,13 @@ if (!autoYes) {
```javascript ```javascript
// ── Update specs/*.md ── // ── Update specs/*.md ──
// Uses .ccw/specs/ directory (same as frontend/backend spec-index-builder)
if (guidelineUpdates.length > 0) { if (guidelineUpdates.length > 0) {
// Map guideline types to spec files // Map guideline types to spec files
const specFileMap = { const specFileMap = {
convention: '.workflow/specs/coding-conventions.md', convention: '.ccw/specs/coding-conventions.md',
constraint: '.workflow/specs/architecture-constraints.md', constraint: '.ccw/specs/architecture-constraints.md',
learning: '.workflow/specs/coding-conventions.md' // learnings appended to conventions learning: '.ccw/specs/coding-conventions.md' // learnings appended to conventions
} }
for (const g of guidelineUpdates) { for (const g of guidelineUpdates) {

View File

@@ -477,8 +477,8 @@ ${recommendations.map(r => \`- ${r}\`).join('\\n')}
const projectTech = file_exists('.workflow/project-tech.json') const projectTech = file_exists('.workflow/project-tech.json')
? JSON.parse(Read('.workflow/project-tech.json')) : null ? JSON.parse(Read('.workflow/project-tech.json')) : null
// Read specs/*.md (if exists) // Read specs/*.md (if exists)
const projectGuidelines = file_exists('.workflow/specs/*.md') const projectGuidelines = file_exists('.ccw/specs/*.md')
? JSON.parse(Read('.workflow/specs/*.md')) : null ? JSON.parse(Read('.ccw/specs/*.md')) : null
``` ```
```javascript ```javascript