feat: standardize request_user_input schema across all codex skills and add config reminder

- Update all 68 .codex/skills files to use correct request_user_input schema
  (header, id, question, options with label/description)
- Remove deprecated multiSelect, type, value, prompt fields
- Add mandatory confirmation gates to planning-only skills
- Add Codex config.toml reminder to ccw install CLI
- Add Codex configuration section to README.md and README_CN.md

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
catlog22
2026-03-24 15:19:18 +08:00
parent ccb5f1e615
commit fe7945eaa2
72 changed files with 1020 additions and 901 deletions

View File

@@ -1,7 +1,7 @@
---
name: spec-generator
description: Specification generator - 7 phase document chain producing product brief, PRD, architecture, epics, and issues. Agent-delegated heavy phases (2-5, 6.5) with Codex review gates. Triggers on "generate spec", "create specification", "spec generator", "workflow:spec".
allowed-tools: Agent, AskUserQuestion, TaskCreate, TaskUpdate, TaskList, Read, Write, Edit, Bash, Glob, Grep, Skill
allowed-tools: Agent, request_user_input, TaskCreate, TaskUpdate, TaskList, Read, Write, Edit, Bash, Glob, Grep, Skill
---
# Spec Generator
@@ -260,7 +260,7 @@ Bash(`mkdir -p "${workDir}"`);
3. **Auto-Continue**: All phases run autonomously; check TaskList to execute next pending phase
4. **Parse Every Output**: Extract required data from each phase for next phase context
5. **DO NOT STOP**: Continuous 7-phase pipeline until all phases complete or user exits
6. **Respect -y Flag**: When auto mode, skip all AskUserQuestion calls, use recommended defaults
6. **Respect -y Flag**: When auto mode, skip all request_user_input calls, use recommended defaults
7. **Respect -c Flag**: When continue mode, load spec-config.json and resume from checkpoint
8. **Inject Glossary**: From Phase 3 onward, inject glossary.json terms into every CLI prompt
9. **Load Profile**: Read templates/profiles/{spec_type}-profile.md and inject requirements into Phase 2-5 prompts

View File

@@ -140,12 +140,12 @@ while (!userSatisfied && requirementState.discussion_rounds < 5) {
// Format questions and suggestions from gapAnalysis for display
// Present as a structured summary to the user
AskUserQuestion({
request_user_input({
questions: [
{
question: buildDiscussionPrompt(gapAnalysis, requirementState),
header: "Req Expand",
multiSelect: false,
id: "req_expand",
question: buildDiscussionPrompt(gapAnalysis, requirementState),
options: [
{ label: "I'll answer", description: "I have answers/feedback to provide (type in 'Other')" },
{ label: "Accept all suggestions", description: "Accept all expansion recommendations as-is" },
@@ -194,12 +194,12 @@ CONSTRAINTS: 避免重复已回答的问题,聚焦未覆盖的领域
// If status === "ready_for_confirmation", break to confirmation step
// If status === "need_more_discussion", present follow-up questions
AskUserQuestion({
request_user_input({
questions: [
{
question: buildFollowUpPrompt(followUpAnalysis, requirementState),
header: "Follow-up",
multiSelect: false,
id: "follow_up",
question: buildFollowUpPrompt(followUpAnalysis, requirementState),
options: [
{ label: "I'll answer", description: "I have more feedback (type in 'Other')" },
{ label: "Looks good", description: "Requirements are sufficiently clear now" },
@@ -300,14 +300,14 @@ if (!autoMode) {
// Build confirmation summary from requirementState
const summary = buildConfirmationSummary(requirementState);
AskUserQuestion({
request_user_input({
questions: [
{
question: `## Requirement Confirmation\n\n${summary}\n\nConfirm and proceed to specification generation?`,
header: "Confirm",
multiSelect: false,
id: "confirm",
question: `## Requirement Confirmation\n\n${summary}\n\nConfirm and proceed to specification generation?`,
options: [
{ label: "Confirm & proceed", description: "Requirements confirmed, start spec generation" },
{ label: "Confirm & proceed(Recommended)", description: "Requirements confirmed, start spec generation" },
{ label: "Need adjustments", description: "Go back and refine further" }
]
}

View File

@@ -159,42 +159,35 @@ Schema:
```javascript
if (!autoMode) {
// Confirm problem statement and select depth
AskUserQuestion({
request_user_input({
questions: [
{
question: `Problem statement: "${seedAnalysis.problem_statement}" - Is this accurate?`,
header: "Problem",
multiSelect: false,
id: "problem",
question: `Problem statement: "${seedAnalysis.problem_statement}" - Is this accurate?`,
options: [
{ label: "Accurate", description: "Proceed with this problem statement" },
{ label: "Accurate(Recommended)", description: "Proceed with this problem statement" },
{ label: "Needs adjustment", description: "I'll refine the problem statement" }
]
},
{
question: "What specification depth do you need?",
header: "Depth",
multiSelect: false,
id: "depth",
question: "What specification depth do you need?",
options: [
{ label: "Standard(Recommended)", description: "Balanced detail for most projects" },
{ label: "Light", description: "Quick overview - key decisions only" },
{ label: "Standard (Recommended)", description: "Balanced detail for most projects" },
{ label: "Comprehensive", description: "Maximum detail for complex/critical projects" }
]
},
{
question: "Which areas should we focus on?",
header: "Focus",
multiSelect: true,
options: seedAnalysis.dimensions.map(d => ({ label: d, description: `Explore ${d} in depth` }))
},
{
question: "What type of specification is this?",
header: "Spec Type",
multiSelect: false,
id: "spec_type",
question: "What type of specification is this?",
options: [
{ label: "Service (Recommended)", description: "Long-running service with lifecycle, state machine, observability" },
{ label: "Service(Recommended)", description: "Long-running service with lifecycle, state machine, observability" },
{ label: "API", description: "REST/GraphQL API with endpoints, auth, rate limiting" },
{ label: "Library/SDK", description: "Reusable package with public API surface, examples" },
{ label: "Platform", description: "Multi-component system, uses Service profile" }
{ label: "Library/SDK", description: "Reusable package with public API surface, examples" }
]
}
]

View File

@@ -174,18 +174,18 @@ const synthesis = {
```javascript
if (!autoMode) {
// Present synthesis summary to user
// AskUserQuestion with:
// request_user_input with:
// - Confirm vision statement
// - Resolve any conflicts between perspectives
// - Adjust scope if needed
AskUserQuestion({
request_user_input({
questions: [
{
question: "Review the synthesized product brief. Any adjustments needed?",
header: "Review",
multiSelect: false,
id: "review",
question: "Review the synthesized product brief. Any adjustments needed?",
options: [
{ label: "Looks good", description: "Proceed to PRD generation" },
{ label: "Looks good(Recommended)", description: "Proceed to PRD generation" },
{ label: "Adjust scope", description: "Narrow or expand the scope" },
{ label: "Revise vision", description: "Refine the vision statement" }
]

View File

@@ -123,24 +123,24 @@ CONSTRAINTS: Be genuinely critical. Focus on requirements that would block imple
if (!autoMode) {
// Present requirements grouped by initial priority
// Allow user to adjust MoSCoW labels
AskUserQuestion({
request_user_input({
questions: [
{
question: "Review the Must-Have requirements. Any that should be reprioritized?",
header: "Must-Have",
multiSelect: false,
id: "must_have",
question: "Review the Must-Have requirements. Any that should be reprioritized?",
options: [
{ label: "All correct", description: "Must-have requirements are accurate" },
{ label: "All correct(Recommended)", description: "Must-have requirements are accurate" },
{ label: "Too many", description: "Some should be Should/Could" },
{ label: "Missing items", description: "Some Should requirements should be Must" }
]
},
{
question: "What is the target MVP scope?",
header: "MVP Scope",
multiSelect: false,
id: "mvp_scope",
question: "What is the target MVP scope?",
options: [
{ label: "Must-Have only (Recommended)", description: "MVP includes only Must requirements" },
{ label: "Must-Have only(Recommended)", description: "MVP includes only Must requirements" },
{ label: "Must + key Should", description: "Include critical Should items in MVP" },
{ label: "Comprehensive", description: "Include all Must and Should" }
]

View File

@@ -154,14 +154,14 @@ CONSTRAINTS: Be genuinely critical, not just validating. Focus on actionable imp
if (!autoMode) {
// Present ADRs with review feedback to user
// For each ADR where review raised concerns:
AskUserQuestion({
request_user_input({
questions: [
{
question: "Architecture review raised concerns. How should we proceed?",
header: "ADR Review",
multiSelect: false,
id: "adr_review",
question: "Architecture review raised concerns. How should we proceed?",
options: [
{ label: "Accept as-is", description: "Architecture is sound, proceed" },
{ label: "Accept as-is(Recommended)", description: "Architecture is sound, proceed" },
{ label: "Incorporate feedback", description: "Adjust ADRs based on review" },
{ label: "Simplify", description: "Reduce complexity, fewer components" }
]

View File

@@ -133,17 +133,16 @@ CONSTRAINTS: Focus on issues that would block execution planning. Be specific ab
```javascript
if (!autoMode) {
// Present Epic overview table and dependency diagram
AskUserQuestion({
request_user_input({
questions: [
{
question: "Review the Epic breakdown. Any adjustments needed?",
header: "Epics",
multiSelect: false,
id: "epics",
question: "Review the Epic breakdown. Any adjustments needed?",
options: [
{ label: "Looks good", description: "Epic structure is appropriate" },
{ label: "Looks good(Recommended)", description: "Epic structure is appropriate" },
{ label: "Merge epics", description: "Some epics should be combined" },
{ label: "Split epic", description: "An epic is too large, needs splitting" },
{ label: "Adjust MVP", description: "Change which epics are in MVP" }
{ label: "Split epic", description: "An epic is too large, needs splitting" }
]
}
]

View File

@@ -312,29 +312,21 @@ Write(`${workDir}/spec-config.json`, JSON.stringify(specConfig, null, 2));
### Step 6: Handoff Options
```javascript
AskUserQuestion({
request_user_input({
questions: [
{
question: "Specification package is complete. What would you like to do next?",
header: "Next Step",
multiSelect: false,
id: "next_step",
question: "Specification package is complete. What would you like to do next?",
options: [
{
label: "Export Issues(Recommended)",
description: "Create issues per Epic with spec links and wave assignment (Phase 7)"
},
{
label: "Execute via lite-plan",
description: "Start implementing with /workflow-lite-plan, one Epic at a time"
},
{
label: "Create roadmap",
description: "Generate execution roadmap with /workflow:req-plan-with-file"
},
{
label: "Full planning",
description: "Detailed planning with /workflow-plan for the full scope"
},
{
label: "Export Issues (Phase 7)",
description: "Create issues per Epic with spec links and wave assignment"
},
{
label: "Iterate & improve",
description: "Re-run failed phases based on readiness report issues (max 2 iterations)"
@@ -344,7 +336,8 @@ AskUserQuestion({
]
});
// Based on user selection, execute the corresponding handoff:
// Based on user selection (answer.answers.next_step.answers[0]), execute the corresponding handoff:
const selection = answer.answers.next_step.answers[0];
if (selection === "Execute via lite-plan") {
// lite-plan accepts a text description directly
@@ -489,7 +482,7 @@ ${extractSection(epicContent, "Architecture")}
}
}
if (selection === "Export Issues (Phase 7)") {
if (selection === "Export Issues(Recommended)") {
// Proceed to Phase 7: Issue Export
// Read phases/07-issue-export.md and execute
}

View File

@@ -253,25 +253,21 @@ Write(`${workDir}/spec-config.json`, JSON.stringify(specConfig, null, 2));
### Step 7: Handoff Options
```javascript
AskUserQuestion({
const answer = request_user_input({
questions: [
{
question: `${createdIssues.length} issues created from ${epicWaves.length} Epics. What would you like to do next?`,
header: "Next Step",
multiSelect: false,
id: "next_step",
question: `${createdIssues.length} issues created from ${epicWaves.length} Epics. What would you like to do next?`,
options: [
{
label: "Execute via team-planex",
label: "Execute via team-planex(Recommended)",
description: `Execute all ${createdIssues.length} issues with coordinated team workflow`
},
{
label: "Wave 1 only",
description: `Execute ${wave1.length} MVP issues first`
},
{
label: "View issues",
description: "Browse created issues before deciding"
},
{
label: "Done",
description: "Export complete, handle manually"
@@ -282,7 +278,8 @@ AskUserQuestion({
});
// Based on user selection:
if (selection === "Execute via team-planex") {
const selection = answer.answers.next_step.answers[0];
if (selection === "Execute via team-planex(Recommended)") {
const issueIds = createdIssues.map(i => i.issue_id).join(',');
Skill({ skill: "team-planex", args: `--issues ${issueIds}` });
}
@@ -292,8 +289,8 @@ if (selection === "Wave 1 only") {
Skill({ skill: "team-planex", args: `--issues ${wave1Ids}` });
}
if (selection === "View issues") {
Bash(`ccw issue list --tag spec:${specConfig.session_id}`);
if (selection === "Done") {
// Export complete, handle manually
}
```