Add TDD Structure Validation and Verification Phases with Comprehensive Reporting

- Introduced Phase 6: TDD Structure Validation to ensure compliance with TDD workflow standards, including task structure validation, dependency checks, and user configuration verification.
- Implemented Phase 7: TDD Verification for full compliance checks, including task chain structure validation, coverage analysis, and TDD cycle verification.
- Generated detailed TDD compliance reports with quality gate recommendations based on objective criteria.
- Added documentation for new commands and workflows in the Claude Commands index.
This commit is contained in:
catlog22
2026-02-28 20:41:06 +08:00
parent 4a89f626fc
commit 65763c76e9
92 changed files with 643 additions and 525 deletions

View File

@@ -102,7 +102,7 @@ function HomeEmptyState({ className }: HomeEmptyStateProps) {
</div>
<div className="flex flex-col gap-2 w-full">
<code className="px-3 py-2 bg-muted rounded text-xs font-mono text-center">
/workflow:plan
/workflow-plan
</code>
<p className="text-xs text-muted-foreground text-center">
{formatMessage({ id: 'home.emptyState.noSessions.hint' })}

View File

@@ -272,7 +272,7 @@
"confirmDeleteTemplate": "Delete template \"{name}\"?",
"placeholders": {
"nodeLabel": "Node label",
"instruction": "e.g., Execute /workflow:plan for login feature\nor: Analyze code architecture\nor: Save {{analysis}} to ./output/result.json",
"instruction": "e.g., Execute /workflow-plan for login feature\nor: Analyze code architecture\nor: Save {{analysis}} to ./output/result.json",
"outputName": "e.g., analysis, plan, result",
"slashCommand": "Select a command...",
"slashArgs": "Enter arguments...",

View File

@@ -272,7 +272,7 @@
"confirmDeleteTemplate": "确定删除模板 \"{name}\"",
"placeholders": {
"nodeLabel": "节点标签",
"instruction": "例如: 执行 /workflow:plan 用于登录功能\n或: 分析代码架构\n或: 将 {{analysis}} 保存到 ./output/result.json",
"instruction": "例如: 执行 /workflow-plan 用于登录功能\n或: 分析代码架构\n或: 将 {{analysis}} 保存到 ./output/result.json",
"outputName": "例如: analysis, plan, result",
"slashCommand": "选择命令...",
"slashArgs": "输入参数...",

View File

@@ -48,7 +48,7 @@ export type ExecutionMode = 'analysis' | 'write' | 'mainprocess' | 'async';
* - prompt -> instruction (direct)
*
* @example Slash command equivalent
* { instruction: "Execute /workflow:plan for login feature", outputName: "plan", mode: "mainprocess" }
* { instruction: "Execute /workflow-plan for login feature", outputName: "plan", mode: "mainprocess" }
*
* @example CLI command equivalent
* { instruction: "Analyze code architecture", outputName: "analysis", tool: "gemini", mode: "analysis" }
@@ -132,7 +132,7 @@ export interface PromptTemplateNodeData {
skillName?: string;
/**
* Selected slash command name (e.g., "workflow:plan", "review-code")
* Selected slash command name (e.g., "workflow-plan", "review-code")
* When set, overrides instruction during execution.
* Used when mode is 'mainprocess' or 'async'.
*/

View File

@@ -43,7 +43,7 @@ export type StepStatus = 'pending' | 'running' | 'completed' | 'failed' | 'skipp
* Defines the type of execution for an orchestration step.
* - 'frontend-cli': Execute a command directly in the frontend CLI (e.g., via a pseudo-terminal).
* - 'backend-flow': Execute a sub-flow defined on the backend.
* - 'slash-command': Execute a predefined slash command (e.g., /workflow:plan).
* - 'slash-command': Execute a predefined slash command (e.g., /workflow-plan).
*/
export type ExecutionType = 'frontend-cli' | 'backend-flow' | 'slash-command';

View File

@@ -113,7 +113,7 @@ async function startAction(taskId: string, options: { session?: string }): Promi
sessionDir = findActiveSession(currentCwd);
if (!sessionDir) {
console.error(chalk.red('\n Error: No active workflow session found.'));
console.error(chalk.gray(' Run "ccw workflow:plan" first to create a session.\n'));
console.error(chalk.gray(' Run "ccw workflow-plan" first to create a session.\n'));
process.exit(1);
}
}

View File

@@ -225,7 +225,7 @@ invalid yaml content without colons
expect(result).toEqual({
name: 'lite-plan',
command: '/workflow:lite-plan',
command: '/workflow-lite-plan',
description: 'Quick planning for simple features',
argumentHint: '"feature description"',
allowedTools: ['Task(*)', 'Read(*)', 'Write(*)', 'Bash(*)'],
@@ -239,7 +239,7 @@ invalid yaml content without colons
mockReadFileSync.mockReturnValue(sampleLitePlanYaml);
const registry = new CommandRegistry(cmdDir);
const result = registry.getCommand('/workflow:lite-plan');
const result = registry.getCommand('/workflow-lite-plan');
expect(result?.name).toBe('lite-plan');
});
@@ -330,8 +330,8 @@ description: Minimal command
const result = registry.getCommands(['lite-plan', 'execute', 'nonexistent']);
expect(result.size).toBe(2);
expect(result.has('/workflow:lite-plan')).toBe(true);
expect(result.has('/workflow:execute')).toBe(true);
expect(result.has('/workflow-lite-plan')).toBe(true);
expect(result.has('/workflow-execute')).toBe(true);
});
it('should skip nonexistent commands', () => {
@@ -362,7 +362,7 @@ description: Minimal command
const result = registry.getAllCommandsSummary();
expect(result.size).toBe(3);
expect(result.get('/workflow:lite-plan')).toEqual({
expect(result.get('/workflow-lite-plan')).toEqual({
name: 'lite-plan',
description: 'Quick planning for simple features'
});
@@ -483,9 +483,9 @@ allowed-tools: Task(*)
const json = registry.toJSON();
expect(json['/workflow:lite-plan']).toEqual({
expect(json['/workflow-lite-plan']).toEqual({
name: 'lite-plan',
command: '/workflow:lite-plan',
command: '/workflow-lite-plan',
description: 'Quick planning for simple features',
argumentHint: '"feature description"',
allowedTools: ['Task(*)', 'Read(*)', 'Write(*)', 'Bash(*)'],
@@ -508,8 +508,8 @@ allowed-tools: Task(*)
const json = registry.toJSON();
expect(Object.keys(json).length).toBe(1);
expect(json['/workflow:lite-plan']).toBeDefined();
expect(json['/workflow:execute']).toBeUndefined();
expect(json['/workflow-lite-plan']).toBeDefined();
expect(json['/workflow-execute']).toBeUndefined();
});
});

View File

@@ -118,7 +118,7 @@ export class CommandRegistry {
/**
* Get single command metadata
* @param commandName Command name (e.g., "lite-plan" or "/workflow:lite-plan")
* @param commandName Command name (e.g., "lite-plan" or "/workflow-lite-plan")
* @returns Command metadata or null
*/
public getCommand(commandName: string): CommandMetadata | null {