cc-devflow 2.4.6 → 4.1.0
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/.claude/CLAUDE.md +1065 -48
- package/.claude/agents/dev-implementer.md +195 -0
- package/.claude/commands/{flow-archive.md → flow/archive.md} +46 -11
- package/.claude/commands/flow/context.md +150 -0
- package/.claude/commands/flow/delta.md +245 -0
- package/.claude/commands/{flow-dev.md → flow/dev.md} +112 -11
- package/.claude/commands/flow/init.md +45 -0
- package/.claude/commands/flow/quality.md +159 -0
- package/.claude/commands/flow/spec.md +186 -0
- package/.claude/commands/flow/workspace.md +146 -0
- package/.claude/commands/{cancel-ralph.md → util/cancel-ralph.md} +1 -0
- package/.claude/config/quality-gates.yml +305 -0
- package/.claude/docs/guides/TEAM_MODE_GUIDE.md +313 -0
- package/.claude/docs/templates/DELTA_SPEC_TEMPLATE.md +91 -0
- package/.claude/docs/templates/DESIGN_DECISIONS_TEMPLATE.md +151 -0
- package/.claude/docs/templates/JOURNAL_TEMPLATE.md +75 -0
- package/.claude/docs/templates/_shared/CLAUDE.md +36 -0
- package/.claude/docs/templates/_shared/CONSTITUTION_CHECK.md +125 -0
- package/.claude/docs/templates/_shared/VALIDATION_CHECKLIST.md +187 -0
- package/.claude/docs/templates/_shared/YAML_FRONTMATTER.md +164 -0
- package/.claude/docs/templates/context/dev.jsonl.template +6 -0
- package/.claude/docs/templates/context/epic.jsonl.template +5 -0
- package/.claude/docs/templates/context/prd.jsonl.template +4 -0
- package/.claude/docs/templates/context/research.jsonl.template +4 -0
- package/.claude/docs/templates/context/review.jsonl.template +5 -0
- package/.claude/docs/templates/context/tech.jsonl.template +5 -0
- package/.claude/hooks/CLAUDE.md +342 -0
- package/.claude/hooks/inject-agent-context.ts +480 -0
- package/.claude/hooks/inject-skill-context.ts +359 -0
- package/.claude/hooks/ralph-loop.ts +931 -0
- package/.claude/hooks/task-completed-hook.ts +593 -0
- package/.claude/hooks/teammate-idle-hook.ts +690 -0
- package/.claude/hooks/types/team-types.d.ts +238 -0
- package/.claude/rules/devflow-conventions.md +82 -9
- package/.claude/scripts/archive-requirement.sh +44 -1
- package/.claude/scripts/common.sh +670 -3
- package/.claude/scripts/delta-parser.ts +527 -0
- package/.claude/scripts/detect-file-conflicts.sh +151 -0
- package/.claude/scripts/flow-context-add.sh +134 -0
- package/.claude/scripts/flow-context-init.sh +133 -0
- package/.claude/scripts/flow-context-validate.sh +144 -0
- package/.claude/scripts/flow-delta-apply.sh +297 -0
- package/.claude/scripts/flow-delta-archive.sh +71 -0
- package/.claude/scripts/flow-delta-create.sh +202 -0
- package/.claude/scripts/flow-delta-list.sh +142 -0
- package/.claude/scripts/flow-delta-status.sh +235 -0
- package/.claude/scripts/flow-quality-full.sh +184 -0
- package/.claude/scripts/flow-quality-quick.sh +64 -0
- package/.claude/scripts/flow-workspace-init.sh +117 -0
- package/.claude/scripts/flow-workspace-record.sh +164 -0
- package/.claude/scripts/flow-workspace-start.sh +88 -0
- package/.claude/scripts/get-workflow-status.sh +415 -0
- package/.claude/scripts/parse-task-dependencies.js +334 -0
- package/.claude/scripts/record-quality-error.sh +165 -0
- package/.claude/scripts/run-quality-gates.sh +242 -0
- package/.claude/scripts/team-dev-init.sh +319 -0
- package/.claude/scripts/team-state-recovery.sh +229 -0
- package/.claude/scripts/workflow-status.ts +433 -0
- package/.claude/settings.json +19 -0
- package/.claude/skills/cc-devflow-orchestrator/SKILL.md +85 -200
- package/.claude/skills/domain/using-git-worktrees/SKILL.md +252 -0
- package/.claude/skills/domain/using-git-worktrees/assets/SHELL_ALIASES.md +133 -0
- package/.claude/skills/domain/using-git-worktrees/context.jsonl +4 -0
- package/.claude/skills/domain/using-git-worktrees/scripts/worktree-cleanup.sh +218 -0
- package/.claude/skills/domain/using-git-worktrees/scripts/worktree-create.sh +232 -0
- package/.claude/skills/domain/using-git-worktrees/scripts/worktree-list.sh +130 -0
- package/.claude/skills/domain/using-git-worktrees/scripts/worktree-status.sh +140 -0
- package/.claude/skills/domain/using-git-worktrees/scripts/worktree-switch.sh +70 -0
- package/.claude/skills/skill-rules.json +72 -1
- package/.claude/skills/utility/journey-checker/SKILL.md +199 -0
- package/.claude/skills/utility/journey-checker/pressure-scenarios.md +164 -0
- package/.claude/skills/utility/skill-creator/LICENSE.txt +202 -0
- package/.claude/skills/utility/skill-creator/SKILL.md +356 -0
- package/.claude/skills/utility/skill-creator/references/output-patterns.md +82 -0
- package/.claude/skills/utility/skill-creator/references/workflows.md +28 -0
- package/.claude/skills/utility/skill-creator/scripts/init_skill.py +303 -0
- package/.claude/skills/utility/skill-creator/scripts/package_skill.py +110 -0
- package/.claude/skills/utility/skill-creator/scripts/quick_validate.py +95 -0
- package/.claude/skills/workflow/flow-dev/CLAUDE.md +78 -0
- package/.claude/skills/workflow/flow-dev/SKILL.md +96 -0
- package/.claude/skills/workflow/flow-dev/assets/IMPLEMENTATION_PLAN_TEMPLATE.md +71 -0
- package/.claude/skills/workflow/flow-dev/context.jsonl +8 -0
- package/.claude/skills/workflow/flow-dev/dev-implementer.jsonl +8 -0
- package/.claude/skills/workflow/flow-dev/scripts/entry-gate.sh +116 -0
- package/.claude/skills/workflow/flow-dev/scripts/exit-gate.sh +101 -0
- package/.claude/skills/workflow/flow-dev/scripts/task-orchestrator.sh +106 -0
- package/.claude/skills/workflow/flow-fix/SKILL.md +105 -0
- package/.claude/skills/workflow/flow-fix/context.jsonl +6 -0
- package/.claude/skills/workflow/flow-fix/references/bug-analyzer.md +381 -0
- package/.claude/skills/workflow/flow-init/SKILL.md +211 -0
- package/.claude/skills/workflow/flow-init/assets/BRAINSTORM_TEMPLATE.md +148 -0
- package/.claude/skills/workflow/flow-init/assets/INIT_FLOW_TEMPLATE.md +198 -0
- package/.claude/skills/workflow/flow-init/assets/RESEARCH_TEMPLATE.md +276 -0
- package/.claude/skills/workflow/flow-init/context.jsonl +5 -0
- package/.claude/skills/workflow/flow-init/references/flow-researcher.md +132 -0
- package/.claude/skills/workflow/flow-init/scripts/check-prerequisites.sh +232 -0
- package/.claude/skills/workflow/flow-init/scripts/consolidate-research.sh +182 -0
- package/.claude/skills/workflow/flow-init/scripts/create-requirement.sh +515 -0
- package/.claude/skills/workflow/flow-init/scripts/generate-research-tasks.sh +157 -0
- package/.claude/skills/workflow/flow-init/scripts/populate-research-tasks.sh +284 -0
- package/.claude/skills/workflow/flow-init/scripts/validate-research.sh +332 -0
- package/.claude/skills/workflow/flow-quality/SKILL.md +94 -0
- package/.claude/skills/workflow/flow-quality/context.jsonl +6 -0
- package/.claude/skills/workflow/flow-quality/references/code-quality-reviewer.md +205 -0
- package/.claude/skills/workflow/flow-quality/references/qa-tester.md +313 -0
- package/.claude/skills/workflow/flow-quality/references/security-reviewer.md +314 -0
- package/.claude/skills/workflow/flow-quality/references/spec-reviewer.md +221 -0
- package/.claude/skills/workflow/flow-release/SKILL.md +126 -0
- package/.claude/skills/workflow/flow-release/context.jsonl +7 -0
- package/.claude/skills/workflow/flow-release/references/release-manager.md +295 -0
- package/.claude/skills/workflow/flow-spec/CLAUDE.md +103 -0
- package/.claude/skills/workflow/flow-spec/SKILL.md +545 -0
- package/.claude/skills/workflow/flow-spec/context.jsonl +7 -0
- package/.claude/skills/workflow/flow-spec/scripts/entry-gate.sh +194 -0
- package/.claude/skills/workflow/flow-spec/scripts/exit-gate.sh +244 -0
- package/.claude/skills/workflow/flow-spec/scripts/parallel-orchestrator.sh +205 -0
- package/.claude/skills/workflow/flow-spec/scripts/team-communication.sh +353 -0
- package/.claude/skills/workflow/flow-spec/scripts/team-init.sh +195 -0
- package/.claude/skills/workflow/flow-spec/scripts/test-team-mode.sh +496 -0
- package/.claude/skills/workflow/flow-spec/team-config.json +165 -0
- package/.claude/skills/workflow.yaml +417 -0
- package/CHANGELOG.md +254 -0
- package/README.md +193 -33
- package/README.zh-CN.md +206 -46
- package/lib/compiler/CLAUDE.md +77 -46
- package/lib/compiler/__tests__/multi-module-emitters.test.js +508 -0
- package/lib/compiler/context-expander.js +179 -0
- package/lib/compiler/emitters/antigravity-emitter.js +195 -5
- package/lib/compiler/emitters/base-emitter.js +217 -2
- package/lib/compiler/emitters/codex-emitter.js +200 -4
- package/lib/compiler/emitters/cursor-emitter.js +307 -3
- package/lib/compiler/emitters/qwen-emitter.js +196 -4
- package/lib/compiler/index.js +197 -2
- package/lib/compiler/platforms.js +270 -21
- package/package.json +1 -1
- package/.claude/commands/flow-epic.md +0 -183
- package/.claude/commands/flow-init.md +0 -370
- package/.claude/commands/flow-prd.md +0 -144
- package/.claude/commands/flow-qa.md +0 -93
- package/.claude/commands/flow-review.md +0 -257
- package/.claude/commands/flow-tech.md +0 -142
- package/.claude/commands/flow-ui.md +0 -189
- package/.claude/skills/file-header-guardian/SKILL.md +0 -56
- package/.claude/skills/skill-developer/ADVANCED.md +0 -197
- package/.claude/skills/skill-developer/HOOK_MECHANISMS.md +0 -306
- package/.claude/skills/skill-developer/PATTERNS_LIBRARY.md +0 -152
- package/.claude/skills/skill-developer/SKILL.md +0 -426
- package/.claude/skills/skill-developer/SKILL_RULES_REFERENCE.md +0 -315
- package/.claude/skills/skill-developer/TRIGGER_TYPES.md +0 -305
- package/.claude/skills/skill-developer/TROUBLESHOOTING.md +0 -514
- package/.claude/skills/writing-skills/SKILL.md +0 -655
- package/.claude/skills/writing-skills/anthropic-best-practices.md +0 -1150
- package/.claude/skills/writing-skills/examples/CLAUDE_MD_TESTING.md +0 -189
- package/.claude/skills/writing-skills/graphviz-conventions.dot +0 -172
- package/.claude/skills/writing-skills/persuasion-principles.md +0 -187
- package/.claude/skills/writing-skills/render-graphs.js +0 -168
- package/.claude/skills/writing-skills/testing-skills-with-subagents.md +0 -384
- package/.claude/tsc-cache/795ba6e3-b98a-423b-bab2-51aa62812569/affected-repos.txt +0 -1
- package/.claude/tsc-cache/ae335694-be5a-4ba4-a1a0-b676c09a7906/affected-repos.txt +0 -1
- /package/.claude/commands/{core-architecture.md → core/architecture.md} +0 -0
- /package/.claude/commands/{core-guidelines.md → core/guidelines.md} +0 -0
- /package/.claude/commands/{core-roadmap.md → core/roadmap.md} +0 -0
- /package/.claude/commands/{core-style.md → core/style.md} +0 -0
- /package/.claude/commands/{flow-checklist.md → flow/checklist.md} +0 -0
- /package/.claude/commands/{flow-clarify.md → flow/clarify.md} +0 -0
- /package/.claude/commands/{flow-constitution.md → flow/constitution.md} +0 -0
- /package/.claude/commands/{flow-fix.md → flow/fix.md} +0 -0
- /package/.claude/commands/{flow-ideate.md → flow/ideate.md} +0 -0
- /package/.claude/commands/{flow-new.md → flow/new.md} +0 -0
- /package/.claude/commands/{flow-release.md → flow/release.md} +0 -0
- /package/.claude/commands/{flow-restart.md → flow/restart.md} +0 -0
- /package/.claude/commands/{flow-status.md → flow/status.md} +0 -0
- /package/.claude/commands/{flow-update.md → flow/update.md} +0 -0
- /package/.claude/commands/{flow-upgrade.md → flow/upgrade.md} +0 -0
- /package/.claude/commands/{flow-verify.md → flow/verify.md} +0 -0
- /package/.claude/commands/{code-review-high.md → util/code-review.md} +0 -0
- /package/.claude/commands/{git-commit.md → util/git-commit.md} +0 -0
- /package/.claude/commands/{problem-analyzer.md → util/problem-analyzer.md} +0 -0
- /package/.claude/skills/{flow-attention-refresh → domain/attention-refresh}/SKILL.md +0 -0
- /package/.claude/skills/{flow-brainstorming → domain/brainstorming}/SKILL.md +0 -0
- /package/.claude/skills/{flow-debugging → domain/debugging}/SKILL.md +0 -0
- /package/.claude/skills/{flow-finishing-branch → domain/finishing-branch}/SKILL.md +0 -0
- /package/.claude/skills/{flow-receiving-review → domain/receiving-review}/SKILL.md +0 -0
- /package/.claude/skills/{flow-tdd → domain/tdd}/SKILL.md +0 -0
- /package/.claude/skills/{verification-before-completion → domain/verification}/SKILL.md +0 -0
- /package/.claude/skills/{constitution-guardian → guardrail/constitution-guardian}/SKILL.md +0 -0
- /package/.claude/skills/{devflow-tdd-enforcer → guardrail/tdd-enforcer}/SKILL.md +0 -0
- /package/.claude/skills/{devflow-constitution-quick-ref → utility/constitution-quick-ref}/SKILL.md +0 -0
- /package/.claude/skills/{devflow-file-standards → utility/file-standards}/SKILL.md +0 -0
- /package/.claude/skills/{fractal-docs-generator → utility/fractal-docs}/SKILL.md +0 -0
- /package/.claude/skills/{npm-release → utility/npm-release}/SKILL.md +0 -0
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: flow-researcher
|
|
3
|
+
description: Executes mandatory /flow-init deep research using MCP services (Context7/WebSearch/WebFetch) with file-based memory. Produces research artifacts under devflow/requirements/$REQ_ID/research/ and returns only a short summary + file paths (no long pastes).
|
|
4
|
+
tools: Read, Write, Grep, Glob, WebFetch, WebSearch, mcp__context7__resolve-library-id, mcp__context7__get-library-docs
|
|
5
|
+
model: inherit
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
You are a requirement research runner invoked by `/flow-init`.
|
|
9
|
+
|
|
10
|
+
Your job is to do **research work** without exhausting the main session context:
|
|
11
|
+
- Put large content into files under `devflow/requirements/$REQ_ID/research/`
|
|
12
|
+
- Return only a **short** summary + **paths**, never paste long docs into chat
|
|
13
|
+
|
|
14
|
+
## MCP Research Requirement
|
|
15
|
+
|
|
16
|
+
This agent MUST use **MCP services** to fetch external materials for deep research:
|
|
17
|
+
- **Context7 MCP**: official documentation for detected frameworks/libraries (`mcp__context7__resolve-library-id` + `mcp__context7__get-library-docs`)
|
|
18
|
+
- **WebSearch + WebFetch**: tutorials, guides, examples, case studies, and plan URLs
|
|
19
|
+
|
|
20
|
+
All fetched content MUST be written to `research/mcp/YYYYMMDD/**` (not pasted into chat).
|
|
21
|
+
|
|
22
|
+
## Hard Rules
|
|
23
|
+
|
|
24
|
+
1. **NO USER INTERACTION**
|
|
25
|
+
- Never ask the user questions.
|
|
26
|
+
- If information is missing, record it under `## Unresolved Questions` in `research/research-summary.md`.
|
|
27
|
+
|
|
28
|
+
2. **FILE-BASED MEMORY (MANDATORY)**
|
|
29
|
+
- Any fetched/long content must be written to files in `research/`.
|
|
30
|
+
- Chat output must stay small (decision bullets + file paths).
|
|
31
|
+
|
|
32
|
+
3. **NO PLACEHOLDERS**
|
|
33
|
+
- Do not leave `TODO`, `FIXME`, `{{PLACEHOLDER}}`.
|
|
34
|
+
- Ensure `validate-research.sh --strict` passes.
|
|
35
|
+
|
|
36
|
+
4. **TRACEABILITY**
|
|
37
|
+
- Every decision must include a concrete `Source` (file path + section/line if possible).
|
|
38
|
+
|
|
39
|
+
## Input Contract (provided via prompt)
|
|
40
|
+
|
|
41
|
+
You will receive a JSON payload in the prompt:
|
|
42
|
+
|
|
43
|
+
```json
|
|
44
|
+
{
|
|
45
|
+
"reqId": "REQ-123",
|
|
46
|
+
"reqDir": "devflow/requirements/REQ-123",
|
|
47
|
+
"title": "User Authentication",
|
|
48
|
+
"planUrls": ["https://..."],
|
|
49
|
+
"contextFiles": {
|
|
50
|
+
"brainstorm": "devflow/requirements/REQ-123/BRAINSTORM.md",
|
|
51
|
+
"roadmap": "devflow/ROADMAP.md",
|
|
52
|
+
"architecture": "devflow/ARCHITECTURE.md"
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Required Outputs (MUST create/update)
|
|
58
|
+
|
|
59
|
+
Under `${reqDir}/research/`:
|
|
60
|
+
- `internal/codebase-overview.md`
|
|
61
|
+
- `mcp/YYYYMMDD/official/*.md` (if applicable)
|
|
62
|
+
- `mcp/YYYYMMDD/guides/*.md` (if applicable)
|
|
63
|
+
- `mcp/YYYYMMDD/tutorials/*.md` (if applicable)
|
|
64
|
+
- `mcp/YYYYMMDD/examples/*.md` (if applicable)
|
|
65
|
+
- `research-summary.md` (human-readable decisions)
|
|
66
|
+
- `tasks.json` (decision/rationale/alternatives filled)
|
|
67
|
+
- `research.md` (consolidated, Decision/Rationale/Alternatives format)
|
|
68
|
+
|
|
69
|
+
## Execution Procedure (follow in order)
|
|
70
|
+
|
|
71
|
+
### Step 1: Validate Paths & Prepare Directories
|
|
72
|
+
- Ensure `${reqDir}` exists.
|
|
73
|
+
- Ensure `${reqDir}/research/` exists, create missing subfolders:
|
|
74
|
+
- `research/internal/`
|
|
75
|
+
- `research/mcp/YYYYMMDD/{official,guides,tutorials,examples}/`
|
|
76
|
+
- Read `${reqDir}/BRAINSTORM.md` and `${reqDir}/README.md` if present.
|
|
77
|
+
|
|
78
|
+
### Step 2: Internal Codebase Research (S0)
|
|
79
|
+
Goal: produce a **useful** `research/internal/codebase-overview.md` with:
|
|
80
|
+
- Repo tech stack snapshot (from `package.json`, lockfiles, etc.)
|
|
81
|
+
- Relevant modules/entry points you will likely touch
|
|
82
|
+
- Existing patterns for auth/data validation/error handling/tests
|
|
83
|
+
- Constraints you must not violate (existing conventions, CI, tooling)
|
|
84
|
+
|
|
85
|
+
### Step 3: External Research (Task 1-5)
|
|
86
|
+
Do not paste docs into chat; store them as files.
|
|
87
|
+
|
|
88
|
+
1) **Official docs (Context7 MCP)** for the detected key libraries/frameworks
|
|
89
|
+
2) **Tutorials/guides (WebSearch + WebFetch)** for practical patterns
|
|
90
|
+
3) **Examples/case studies (WebSearch + WebFetch)** similar to this requirement
|
|
91
|
+
4) Write short per-source notes at top of each saved file:
|
|
92
|
+
- What it answers
|
|
93
|
+
- What it recommends
|
|
94
|
+
- Any caveats
|
|
95
|
+
|
|
96
|
+
If planUrls exist:
|
|
97
|
+
- Fetch each URL and store content under `research/mcp/YYYYMMDD/guides/plan-*.md` (or `tutorials/` if more appropriate).
|
|
98
|
+
|
|
99
|
+
### Step 4: Write `research/research-summary.md`
|
|
100
|
+
Use `.claude/docs/templates/RESEARCH_TEMPLATE.md` as the format baseline.
|
|
101
|
+
- Create **at least 3** Decision blocks `### R001`, `### R002`, `### R003`.
|
|
102
|
+
- Each decision must cite sources under `research/` (internal or external).
|
|
103
|
+
- Add unresolved questions only when genuinely blocked.
|
|
104
|
+
|
|
105
|
+
### Step 5: Generate & Fill `tasks.json`
|
|
106
|
+
- Run:
|
|
107
|
+
- `bash .claude/scripts/generate-research-tasks.sh "${reqDir}"`
|
|
108
|
+
- Ensure `tasks.json` contains at least **1** task.
|
|
109
|
+
- If the generator produced 0 tasks, append baseline tasks matching your decision blocks (`R001..R003`).
|
|
110
|
+
- Fill each task's `decision`, `rationale`, `alternatives` based on `research-summary.md`.
|
|
111
|
+
- Prefer using `bash .claude/scripts/populate-research-tasks.sh "${reqDir}"` if it matches the ID format.
|
|
112
|
+
|
|
113
|
+
### Step 6: Consolidate & Validate
|
|
114
|
+
- Run:
|
|
115
|
+
- `bash .claude/scripts/consolidate-research.sh "${reqDir}"`
|
|
116
|
+
- `bash .claude/scripts/validate-research.sh "${reqDir}" --strict`
|
|
117
|
+
- If validation fails:
|
|
118
|
+
- Fix the files (do not weaken validation).
|
|
119
|
+
- Re-run validation until it passes.
|
|
120
|
+
|
|
121
|
+
## Return Format (chat output)
|
|
122
|
+
|
|
123
|
+
Return ONLY:
|
|
124
|
+
- 3–6 bullet decisions (R001..), one line each
|
|
125
|
+
- Paths created/updated
|
|
126
|
+
- Any unresolved questions (≤5)
|
|
127
|
+
|
|
128
|
+
Never paste long fetched content.
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
**[PROTOCOL]**: 变更时更新此头部,然后检查 CLAUDE.md
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
# Consolidated prerequisite checking script for cc-devflow
|
|
4
|
+
#
|
|
5
|
+
# This script provides unified prerequisite checking for development workflow.
|
|
6
|
+
# Based on spec-kit design principles with cc-devflow enhancements.
|
|
7
|
+
#
|
|
8
|
+
# Usage: ./check-prerequisites.sh [OPTIONS]
|
|
9
|
+
#
|
|
10
|
+
# OPTIONS:
|
|
11
|
+
# --json Output in JSON format
|
|
12
|
+
# --require-epic Require EPIC.md to exist (for task generation phase)
|
|
13
|
+
# --require-tasks Require tasks/ to exist (for implementation phase)
|
|
14
|
+
# --include-tasks Include tasks/ in AVAILABLE_DOCS list
|
|
15
|
+
# --paths-only Only output path variables (no validation)
|
|
16
|
+
# --help, -h Show help message
|
|
17
|
+
#
|
|
18
|
+
# OUTPUTS:
|
|
19
|
+
# JSON mode: {"REQ_ID":"...", "REQ_DIR":"...", "AVAILABLE_DOCS":["..."]}
|
|
20
|
+
# Text mode: REQ_ID:... \n REQ_DIR:... \n AVAILABLE_DOCS: \n ✓/✗ file.md
|
|
21
|
+
# Paths only: REPO_ROOT: ... \n REQ_ID: ... \n REQ_DIR: ... etc.
|
|
22
|
+
|
|
23
|
+
set -e
|
|
24
|
+
|
|
25
|
+
# Parse command line arguments
|
|
26
|
+
JSON_MODE=false
|
|
27
|
+
REQUIRE_EPIC=false
|
|
28
|
+
REQUIRE_TASKS=false
|
|
29
|
+
INCLUDE_TASKS=false
|
|
30
|
+
PATHS_ONLY=false
|
|
31
|
+
|
|
32
|
+
for arg in "$@"; do
|
|
33
|
+
case "$arg" in
|
|
34
|
+
--json)
|
|
35
|
+
JSON_MODE=true
|
|
36
|
+
;;
|
|
37
|
+
--require-epic)
|
|
38
|
+
REQUIRE_EPIC=true
|
|
39
|
+
;;
|
|
40
|
+
--require-tasks)
|
|
41
|
+
REQUIRE_TASKS=true
|
|
42
|
+
;;
|
|
43
|
+
--include-tasks)
|
|
44
|
+
INCLUDE_TASKS=true
|
|
45
|
+
;;
|
|
46
|
+
--paths-only)
|
|
47
|
+
PATHS_ONLY=true
|
|
48
|
+
;;
|
|
49
|
+
--help|-h)
|
|
50
|
+
cat << 'EOF'
|
|
51
|
+
Usage: check-prerequisites.sh [OPTIONS]
|
|
52
|
+
|
|
53
|
+
Consolidated prerequisite checking for cc-devflow workflow.
|
|
54
|
+
|
|
55
|
+
OPTIONS:
|
|
56
|
+
--json Output in JSON format
|
|
57
|
+
--require-epic Require EPIC.md to exist (for task generation phase)
|
|
58
|
+
--require-tasks Require tasks/ to exist (for implementation phase)
|
|
59
|
+
--include-tasks Include tasks/ in AVAILABLE_DOCS list
|
|
60
|
+
--paths-only Only output path variables (no prerequisite validation)
|
|
61
|
+
--help, -h Show this help message
|
|
62
|
+
|
|
63
|
+
EXAMPLES:
|
|
64
|
+
# Check planning prerequisites (PRD.md required)
|
|
65
|
+
./check-prerequisites.sh --json
|
|
66
|
+
|
|
67
|
+
# Check task generation prerequisites (PRD.md + EPIC.md required)
|
|
68
|
+
./check-prerequisites.sh --json --require-epic
|
|
69
|
+
|
|
70
|
+
# Check implementation prerequisites (PRD.md + EPIC.md + tasks/ required)
|
|
71
|
+
./check-prerequisites.sh --json --require-epic --require-tasks --include-tasks
|
|
72
|
+
|
|
73
|
+
# Get requirement paths only (no validation)
|
|
74
|
+
./check-prerequisites.sh --paths-only
|
|
75
|
+
|
|
76
|
+
EOF
|
|
77
|
+
exit 0
|
|
78
|
+
;;
|
|
79
|
+
*)
|
|
80
|
+
echo "ERROR: Unknown option '$arg'. Use --help for usage information." >&2
|
|
81
|
+
exit 1
|
|
82
|
+
;;
|
|
83
|
+
esac
|
|
84
|
+
done
|
|
85
|
+
|
|
86
|
+
# Source common functions
|
|
87
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
88
|
+
source "$SCRIPT_DIR/common.sh"
|
|
89
|
+
|
|
90
|
+
# Get requirement paths
|
|
91
|
+
eval $(get_requirement_paths)
|
|
92
|
+
|
|
93
|
+
# Validate requirement ID exists
|
|
94
|
+
if [[ -z "$REQ_ID" ]]; then
|
|
95
|
+
echo "ERROR: No requirement ID found" >&2
|
|
96
|
+
echo "Please ensure you are on a feature branch (feature/REQ-XXX-title)" >&2
|
|
97
|
+
echo "Or set DEVFLOW_REQ_ID environment variable" >&2
|
|
98
|
+
exit 1
|
|
99
|
+
fi
|
|
100
|
+
|
|
101
|
+
# Validate requirement ID format
|
|
102
|
+
validate_req_id "$REQ_ID" || exit 1
|
|
103
|
+
|
|
104
|
+
# If paths-only mode, output paths and exit (support JSON + paths-only combined)
|
|
105
|
+
if $PATHS_ONLY; then
|
|
106
|
+
if $JSON_MODE; then
|
|
107
|
+
# Minimal JSON paths payload (no validation performed)
|
|
108
|
+
printf '{"%s":"%s","%s":"%s","%s":"%s","%s":"%s","%s":"%s","%s":"%s"}\n' \
|
|
109
|
+
"REPO_ROOT" "$REPO_ROOT" \
|
|
110
|
+
"REQ_ID" "$REQ_ID" \
|
|
111
|
+
"REQ_TYPE" "$REQ_TYPE" \
|
|
112
|
+
"REQ_DIR" "$REQ_DIR" \
|
|
113
|
+
"PRD_FILE" "$PRD_FILE" \
|
|
114
|
+
"EPIC_FILE" "$EPIC_FILE"
|
|
115
|
+
else
|
|
116
|
+
echo "REPO_ROOT: $REPO_ROOT"
|
|
117
|
+
echo "REQ_ID: $REQ_ID"
|
|
118
|
+
echo "REQ_TYPE: $REQ_TYPE"
|
|
119
|
+
echo "REQ_DIR: $REQ_DIR"
|
|
120
|
+
echo "PRD_FILE: $PRD_FILE"
|
|
121
|
+
echo "EPIC_FILE: $EPIC_FILE"
|
|
122
|
+
fi
|
|
123
|
+
exit 0
|
|
124
|
+
fi
|
|
125
|
+
|
|
126
|
+
# Validate required directories and files
|
|
127
|
+
if [[ ! -d "$REQ_DIR" ]]; then
|
|
128
|
+
echo "ERROR: Requirement directory not found: $REQ_DIR" >&2
|
|
129
|
+
echo "Run /flow-new first to create the requirement structure." >&2
|
|
130
|
+
exit 1
|
|
131
|
+
fi
|
|
132
|
+
|
|
133
|
+
if [[ ! -f "$PRD_FILE" ]]; then
|
|
134
|
+
echo "ERROR: PRD.md not found in $REQ_DIR" >&2
|
|
135
|
+
echo "Run prd-writer agent first to create the PRD." >&2
|
|
136
|
+
exit 1
|
|
137
|
+
fi
|
|
138
|
+
|
|
139
|
+
# Check for EPIC.md if required
|
|
140
|
+
if $REQUIRE_EPIC && [[ ! -f "$EPIC_FILE" ]]; then
|
|
141
|
+
echo "ERROR: EPIC.md not found in $REQ_DIR" >&2
|
|
142
|
+
echo "Run planner agent first to create the Epic." >&2
|
|
143
|
+
exit 1
|
|
144
|
+
fi
|
|
145
|
+
|
|
146
|
+
# Check for tasks/ or TASKS.md if required
|
|
147
|
+
# Support both tasks/ directory (old format) and TASKS.md file (new format)
|
|
148
|
+
if $REQUIRE_TASKS; then
|
|
149
|
+
TASKS_FILE="$REQ_DIR/TASKS.md"
|
|
150
|
+
if [[ ! -d "$TASKS_DIR" || -z "$(ls -A "$TASKS_DIR" 2>/dev/null)" ]] && [[ ! -f "$TASKS_FILE" ]]; then
|
|
151
|
+
echo "ERROR: Neither tasks/ directory nor TASKS.md file found in $REQ_DIR" >&2
|
|
152
|
+
echo "Run planner agent first to create the task breakdown." >&2
|
|
153
|
+
exit 1
|
|
154
|
+
fi
|
|
155
|
+
fi
|
|
156
|
+
|
|
157
|
+
# Build list of available documents
|
|
158
|
+
docs=()
|
|
159
|
+
|
|
160
|
+
# Check optional docs
|
|
161
|
+
[[ -d "$RESEARCH_DIR" && -n "$(ls -A "$RESEARCH_DIR" 2>/dev/null)" ]] && docs+=("research/")
|
|
162
|
+
[[ -f "$TEST_PLAN_FILE" ]] && docs+=("TEST_PLAN.md")
|
|
163
|
+
[[ -f "$SECURITY_PLAN_FILE" ]] && docs+=("SECURITY_PLAN.md")
|
|
164
|
+
[[ -f "$TEST_REPORT_FILE" ]] && docs+=("TEST_REPORT.md")
|
|
165
|
+
[[ -f "$SECURITY_REPORT_FILE" ]] && docs+=("SECURITY_REPORT.md")
|
|
166
|
+
[[ -f "$RELEASE_PLAN_FILE" ]] && docs+=("RELEASE_PLAN.md")
|
|
167
|
+
[[ -f "$LOG_FILE" ]] && docs+=("EXECUTION_LOG.md")
|
|
168
|
+
|
|
169
|
+
# Include tasks/ or TASKS.md if requested and it exists
|
|
170
|
+
# Support both tasks/ directory (old format) and TASKS.md file (new format)
|
|
171
|
+
if $INCLUDE_TASKS; then
|
|
172
|
+
TASKS_FILE="$REQ_DIR/TASKS.md"
|
|
173
|
+
if [[ -d "$TASKS_DIR" && -n "$(ls -A "$TASKS_DIR" 2>/dev/null)" ]]; then
|
|
174
|
+
docs+=("tasks/")
|
|
175
|
+
elif [[ -f "$TASKS_FILE" ]]; then
|
|
176
|
+
docs+=("TASKS.md")
|
|
177
|
+
fi
|
|
178
|
+
fi
|
|
179
|
+
|
|
180
|
+
# For BUG type, check BUG-specific files
|
|
181
|
+
if [[ "$REQ_TYPE" == "bug" ]]; then
|
|
182
|
+
[[ -f "$ANALYSIS_FILE" ]] && docs+=("ANALYSIS.md")
|
|
183
|
+
[[ -f "$PLAN_FILE" ]] && docs+=("PLAN.md")
|
|
184
|
+
fi
|
|
185
|
+
|
|
186
|
+
# Output results
|
|
187
|
+
if $JSON_MODE; then
|
|
188
|
+
# Build JSON array of documents
|
|
189
|
+
if [[ ${#docs[@]} -eq 0 ]]; then
|
|
190
|
+
json_docs="[]"
|
|
191
|
+
else
|
|
192
|
+
json_docs=$(printf '"%s",' "${docs[@]}")
|
|
193
|
+
json_docs="[${json_docs%,}]"
|
|
194
|
+
fi
|
|
195
|
+
|
|
196
|
+
printf '{"%s":"%s","%s":"%s","%s":"%s","%s":%s}\n' \
|
|
197
|
+
"REQ_ID" "$REQ_ID" \
|
|
198
|
+
"REQ_TYPE" "$REQ_TYPE" \
|
|
199
|
+
"REQ_DIR" "$REQ_DIR" \
|
|
200
|
+
"AVAILABLE_DOCS" "$json_docs"
|
|
201
|
+
else
|
|
202
|
+
# Text output
|
|
203
|
+
echo "REQ_ID: $REQ_ID"
|
|
204
|
+
echo "REQ_TYPE: $REQ_TYPE"
|
|
205
|
+
echo "REQ_DIR: $REQ_DIR"
|
|
206
|
+
echo "AVAILABLE_DOCS:"
|
|
207
|
+
|
|
208
|
+
# Show status of each potential document
|
|
209
|
+
check_dir "$RESEARCH_DIR" "research/"
|
|
210
|
+
check_file "$TEST_PLAN_FILE" "TEST_PLAN.md"
|
|
211
|
+
check_file "$SECURITY_PLAN_FILE" "SECURITY_PLAN.md"
|
|
212
|
+
check_file "$TEST_REPORT_FILE" "TEST_REPORT.md"
|
|
213
|
+
check_file "$SECURITY_REPORT_FILE" "SECURITY_REPORT.md"
|
|
214
|
+
check_file "$RELEASE_PLAN_FILE" "RELEASE_PLAN.md"
|
|
215
|
+
check_file "$LOG_FILE" "EXECUTION_LOG.md"
|
|
216
|
+
|
|
217
|
+
if $INCLUDE_TASKS; then
|
|
218
|
+
TASKS_FILE="$REQ_DIR/TASKS.md"
|
|
219
|
+
# Check for tasks/ directory first, fallback to TASKS.md
|
|
220
|
+
if [[ -d "$TASKS_DIR" && -n "$(ls -A "$TASKS_DIR" 2>/dev/null)" ]]; then
|
|
221
|
+
check_dir "$TASKS_DIR" "tasks/"
|
|
222
|
+
else
|
|
223
|
+
check_file "$TASKS_FILE" "TASKS.md"
|
|
224
|
+
fi
|
|
225
|
+
fi
|
|
226
|
+
|
|
227
|
+
# BUG-specific files
|
|
228
|
+
if [[ "$REQ_TYPE" == "bug" ]]; then
|
|
229
|
+
check_file "$ANALYSIS_FILE" "ANALYSIS.md"
|
|
230
|
+
check_file "$PLAN_FILE" "PLAN.md"
|
|
231
|
+
fi
|
|
232
|
+
fi
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# shellcheck disable=SC2312
|
|
3
|
+
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
|
|
6
|
+
usage() {
|
|
7
|
+
cat <<'USAGE'
|
|
8
|
+
Usage: scripts/bash/consolidate-research.sh <requirement-dir>
|
|
9
|
+
|
|
10
|
+
Aggregates research findings into research/research.md using the standard
|
|
11
|
+
Decision/Rationale/Alternatives format. Existing files are overwritten.
|
|
12
|
+
USAGE
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
|
|
16
|
+
usage
|
|
17
|
+
exit 0
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
if [[ $# -lt 1 ]]; then
|
|
21
|
+
echo "Error: requirement directory is required." >&2
|
|
22
|
+
usage
|
|
23
|
+
exit 1
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
REQ_DIR="$1"
|
|
27
|
+
if [[ ! -d "$REQ_DIR" ]]; then
|
|
28
|
+
echo "Error: requirement directory '$REQ_DIR' does not exist." >&2
|
|
29
|
+
exit 1
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
python3 - "$REQ_DIR" <<'PY'
|
|
33
|
+
from __future__ import annotations
|
|
34
|
+
|
|
35
|
+
import json
|
|
36
|
+
import os
|
|
37
|
+
import sys
|
|
38
|
+
from datetime import datetime, timezone
|
|
39
|
+
from pathlib import Path
|
|
40
|
+
|
|
41
|
+
req_dir = Path(sys.argv[1]).resolve()
|
|
42
|
+
research_dir = req_dir / "research"
|
|
43
|
+
research_dir.mkdir(exist_ok=True, parents=True)
|
|
44
|
+
summary_path = research_dir / "research.md"
|
|
45
|
+
tasks_path = research_dir / "tasks.json"
|
|
46
|
+
|
|
47
|
+
def detect_feature_title() -> str:
|
|
48
|
+
readme = req_dir / "README.md"
|
|
49
|
+
if readme.exists():
|
|
50
|
+
for line in readme.read_text(encoding="utf-8").splitlines():
|
|
51
|
+
line = line.strip("# ").strip()
|
|
52
|
+
if line:
|
|
53
|
+
return line
|
|
54
|
+
return req_dir.name
|
|
55
|
+
|
|
56
|
+
def validate_task_completeness(tasks: list) -> tuple[int, int, list]:
|
|
57
|
+
"""Validate tasks have decision/rationale/alternatives fields.
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
(total_tasks, completed_tasks, incomplete_task_ids)
|
|
61
|
+
"""
|
|
62
|
+
total = len(tasks)
|
|
63
|
+
completed = 0
|
|
64
|
+
incomplete = []
|
|
65
|
+
|
|
66
|
+
for task in tasks:
|
|
67
|
+
task_id = task.get("id", "???")
|
|
68
|
+
decision = task.get("decision", "")
|
|
69
|
+
rationale = task.get("rationale", "")
|
|
70
|
+
alternatives = task.get("alternatives", "")
|
|
71
|
+
|
|
72
|
+
# 字段完整的条件:非空 + 不是 TODO 占位符
|
|
73
|
+
has_decision = bool(decision and decision.strip() and decision != "TODO - fill decision outcome")
|
|
74
|
+
has_rationale = bool(rationale and rationale.strip() and rationale != "TODO - explain why this decision was chosen")
|
|
75
|
+
has_alternatives = bool(alternatives and alternatives.strip() and alternatives != "TODO - list evaluated alternatives")
|
|
76
|
+
|
|
77
|
+
if has_decision and has_rationale and has_alternatives:
|
|
78
|
+
completed += 1
|
|
79
|
+
else:
|
|
80
|
+
incomplete.append(task_id)
|
|
81
|
+
|
|
82
|
+
return total, completed, incomplete
|
|
83
|
+
|
|
84
|
+
feature_title = detect_feature_title()
|
|
85
|
+
generated_at = datetime.now(timezone.utc).isoformat()
|
|
86
|
+
|
|
87
|
+
tasks_data = {}
|
|
88
|
+
if tasks_path.exists():
|
|
89
|
+
try:
|
|
90
|
+
tasks_data = json.loads(tasks_path.read_text(encoding="utf-8"))
|
|
91
|
+
except json.JSONDecodeError:
|
|
92
|
+
print(f"ERROR: {tasks_path} is not valid JSON", file=sys.stderr)
|
|
93
|
+
sys.exit(1)
|
|
94
|
+
|
|
95
|
+
tasks = tasks_data.get("tasks", [])
|
|
96
|
+
|
|
97
|
+
# Validate task completion
|
|
98
|
+
if tasks:
|
|
99
|
+
total, completed, incomplete = validate_task_completeness(tasks)
|
|
100
|
+
completion_rate = completed / total if total > 0 else 0
|
|
101
|
+
|
|
102
|
+
print(f"Research Tasks: {completed}/{total} completed ({completion_rate:.0%})", file=sys.stderr)
|
|
103
|
+
|
|
104
|
+
if completion_rate < 0.5:
|
|
105
|
+
print(f"WARNING: Research incomplete. Only {completed}/{total} tasks have decisions.", file=sys.stderr)
|
|
106
|
+
print(f"Incomplete tasks: {', '.join(incomplete)}", file=sys.stderr)
|
|
107
|
+
print(f"Generated research.md will contain TODO placeholders.", file=sys.stderr)
|
|
108
|
+
print(f"Fix: Add decision/rationale/alternatives fields to tasks.json", file=sys.stderr)
|
|
109
|
+
|
|
110
|
+
sources = []
|
|
111
|
+
for path in research_dir.rglob("*.md"):
|
|
112
|
+
if path.name in {"research.md"}:
|
|
113
|
+
continue
|
|
114
|
+
sources.append(str(path.relative_to(req_dir)))
|
|
115
|
+
|
|
116
|
+
lines = []
|
|
117
|
+
lines.append(f"# Research Summary — {feature_title}")
|
|
118
|
+
lines.append("")
|
|
119
|
+
lines.append(f"Generated: {generated_at}")
|
|
120
|
+
lines.append("")
|
|
121
|
+
lines.append("## Decisions")
|
|
122
|
+
lines.append("")
|
|
123
|
+
|
|
124
|
+
if not tasks:
|
|
125
|
+
lines.append("_No research tasks detected. Populate research/tasks.json to track clarifications._")
|
|
126
|
+
else:
|
|
127
|
+
for task in tasks:
|
|
128
|
+
task_id = task.get("id", "R???")
|
|
129
|
+
prompt = task.get("prompt", "(unknown prompt)")
|
|
130
|
+
lines.append(f"### {task_id} — {prompt}")
|
|
131
|
+
|
|
132
|
+
# 处理空字符串,替换为 TODO 占位符
|
|
133
|
+
decision = task.get("decision", "")
|
|
134
|
+
rationale = task.get("rationale", "")
|
|
135
|
+
alternatives = task.get("alternatives", "")
|
|
136
|
+
|
|
137
|
+
decision = decision.strip() if decision.strip() else "TODO - fill decision outcome"
|
|
138
|
+
rationale = rationale.strip() if rationale.strip() else "TODO - explain why this decision was chosen"
|
|
139
|
+
alternatives = alternatives.strip() if alternatives.strip() else "TODO - list evaluated alternatives"
|
|
140
|
+
|
|
141
|
+
lines.append(f"- Decision: {decision}")
|
|
142
|
+
lines.append(f"- Rationale: {rationale}")
|
|
143
|
+
lines.append(f"- Alternatives considered: {alternatives}")
|
|
144
|
+
source = task.get("source")
|
|
145
|
+
if source:
|
|
146
|
+
lines.append(f"- Source: {source}")
|
|
147
|
+
lines.append("")
|
|
148
|
+
|
|
149
|
+
lines.append("## Source Library")
|
|
150
|
+
lines.append("")
|
|
151
|
+
if sources:
|
|
152
|
+
for src in sorted(sources):
|
|
153
|
+
lines.append(f"- {src}")
|
|
154
|
+
else:
|
|
155
|
+
lines.append("_No research source files detected yet._")
|
|
156
|
+
|
|
157
|
+
summary_path.write_text("\n".join(lines) + "\n", encoding="utf-8")
|
|
158
|
+
|
|
159
|
+
# Post-write validation: detect TODO placeholders
|
|
160
|
+
content = summary_path.read_text(encoding="utf-8")
|
|
161
|
+
todo_count = content.count("TODO")
|
|
162
|
+
placeholder_count = content.count("{{") + content.count("}}")
|
|
163
|
+
|
|
164
|
+
if todo_count > 0 or placeholder_count > 0:
|
|
165
|
+
print(f"⚠️ WARNING: Generated research.md contains quality issues:", file=sys.stderr)
|
|
166
|
+
if todo_count > 0:
|
|
167
|
+
print(f" - {todo_count} TODO marker(s) found", file=sys.stderr)
|
|
168
|
+
if placeholder_count > 0:
|
|
169
|
+
print(f" - Placeholder markers {{{{ }}}} found", file=sys.stderr)
|
|
170
|
+
print(f"", file=sys.stderr)
|
|
171
|
+
print(f"This will cause validate-research.sh to FAIL.", file=sys.stderr)
|
|
172
|
+
print(f"", file=sys.stderr)
|
|
173
|
+
print(f"Fix Options:", file=sys.stderr)
|
|
174
|
+
print(f" 1. Update tasks.json with actual decision/rationale/alternatives", file=sys.stderr)
|
|
175
|
+
print(f" 2. Manually edit {summary_path.relative_to(req_dir)}", file=sys.stderr)
|
|
176
|
+
print(f" 3. Use .claude/docs/templates/RESEARCH_TEMPLATE.md as reference", file=sys.stderr)
|
|
177
|
+
print(f"", file=sys.stderr)
|
|
178
|
+
print(f"Wrote research summary → {summary_path} (WITH WARNINGS)", file=sys.stderr)
|
|
179
|
+
else:
|
|
180
|
+
print(f"✅ Wrote research summary → {summary_path}", file=sys.stderr)
|
|
181
|
+
print(f" Quality check: No TODO/PLACEHOLDER markers detected", file=sys.stderr)
|
|
182
|
+
PY
|