* feat(#1135): migrate planning hooks to capabilities * chore(#1135): add phase 6 planning capabilities changeset * fix(#1135): satisfy lint for agent hook rendering
This commit is contained in:
@@ -7,6 +7,49 @@
|
||||
*/
|
||||
|
||||
const capabilities = {
|
||||
"ai-integration": {
|
||||
"id": "ai-integration",
|
||||
"role": "feature",
|
||||
"title": "AI design contract",
|
||||
"description": "AI-SPEC design contract workflow for phases that build AI systems; owns the AI integration command, agents, and workflow.ai_integration_phase activation key.",
|
||||
"tier": "full",
|
||||
"requires": [],
|
||||
"skills": [
|
||||
"ai-integration-phase"
|
||||
],
|
||||
"agents": [
|
||||
"gsd-framework-selector",
|
||||
"gsd-ai-researcher",
|
||||
"gsd-domain-researcher",
|
||||
"gsd-eval-planner"
|
||||
],
|
||||
"hooks": [],
|
||||
"config": {
|
||||
"workflow.ai_integration_phase": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Prompt for an AI-SPEC design contract before planning phases that involve AI systems."
|
||||
}
|
||||
},
|
||||
"steps": [
|
||||
{
|
||||
"point": "plan:pre",
|
||||
"ref": {
|
||||
"skill": "ai-integration-phase"
|
||||
},
|
||||
"produces": [
|
||||
"AI-SPEC.md"
|
||||
],
|
||||
"consumes": [
|
||||
"CONTEXT.md"
|
||||
],
|
||||
"when": "workflow.ai_integration_phase",
|
||||
"onError": "skip"
|
||||
}
|
||||
],
|
||||
"contributions": [],
|
||||
"gates": []
|
||||
},
|
||||
"antigravity": {
|
||||
"id": "antigravity",
|
||||
"role": "runtime",
|
||||
@@ -832,6 +875,50 @@ const capabilities = {
|
||||
"extendedHookEvents": []
|
||||
}
|
||||
},
|
||||
"pattern-mapper": {
|
||||
"id": "pattern-mapper",
|
||||
"role": "feature",
|
||||
"title": "Pattern mapping",
|
||||
"description": "Optional codebase-pattern mapping before planning; owns the pattern mapper agent and workflow.pattern_mapper activation key.",
|
||||
"tier": "full",
|
||||
"requires": [
|
||||
"research"
|
||||
],
|
||||
"skills": [],
|
||||
"agents": [
|
||||
"gsd-pattern-mapper"
|
||||
],
|
||||
"hooks": [],
|
||||
"config": {
|
||||
"workflow.pattern_mapper": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Run the pattern mapper before planning when context or research is available."
|
||||
}
|
||||
},
|
||||
"steps": [
|
||||
{
|
||||
"point": "plan:pre",
|
||||
"ref": {
|
||||
"agent": "gsd-pattern-mapper"
|
||||
},
|
||||
"fragment": {
|
||||
"path": "fragments/plan-pre.md",
|
||||
"inline": "<pattern_mapping_context>\n**Phase:** {phase_number} - {phase_name}\n**Phase directory:** {phase_dir}\n**Padded phase:** {padded_phase}\n\n<files_to_read>\n- {context_path} (USER DECISIONS from /gsd:discuss-phase)\n- {research_path} (Technical Research)\n</files_to_read>\n\n**Output file:** {phase_dir}/{padded_phase}-PATTERNS.md\n\nExtract the list of files to be created/modified from CONTEXT.md and RESEARCH.md. For each file, classify by role and data flow, find the closest existing analog in the codebase, extract concrete code excerpts, and produce PATTERNS.md.\n</pattern_mapping_context>\n"
|
||||
},
|
||||
"produces": [
|
||||
"PATTERNS.md"
|
||||
],
|
||||
"consumes": [
|
||||
"RESEARCH.md"
|
||||
],
|
||||
"when": "workflow.pattern_mapper",
|
||||
"onError": "skip"
|
||||
}
|
||||
],
|
||||
"contributions": [],
|
||||
"gates": []
|
||||
},
|
||||
"qwen": {
|
||||
"id": "qwen",
|
||||
"role": "runtime",
|
||||
@@ -885,6 +972,48 @@ const capabilities = {
|
||||
]
|
||||
}
|
||||
},
|
||||
"research": {
|
||||
"id": "research",
|
||||
"role": "feature",
|
||||
"title": "Phase research",
|
||||
"description": "Optional phase research before planning; owns the phase researcher agent and workflow.research activation key.",
|
||||
"tier": "standard",
|
||||
"requires": [],
|
||||
"skills": [],
|
||||
"agents": [
|
||||
"gsd-phase-researcher"
|
||||
],
|
||||
"hooks": [],
|
||||
"config": {
|
||||
"workflow.research": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Run phase research before planning when research artifacts are missing or explicitly refreshed."
|
||||
}
|
||||
},
|
||||
"steps": [
|
||||
{
|
||||
"point": "plan:pre",
|
||||
"ref": {
|
||||
"agent": "gsd-phase-researcher"
|
||||
},
|
||||
"fragment": {
|
||||
"path": "fragments/plan-pre.md",
|
||||
"inline": "<objective>\nResearch how to implement Phase {phase_number}: {phase_name}\nAnswer: \"What do I need to know to PLAN this phase well?\"\n</objective>\n\n<files_to_read>\n- {context_path} (USER DECISIONS from /gsd:discuss-phase)\n- {requirements_path} (Project requirements)\n- {state_path} (Project decisions and history)\n</files_to_read>\n\n${AGENT_SKILLS_RESEARCHER}\n\n<additional_context>\n**Phase description:** {phase_description}\n**Phase requirement IDs (MUST address):** {phase_req_ids}\n\n**Project instructions:** Read ./CLAUDE.md or ./.claude/CLAUDE.md if either exists; follow project-specific guidelines.\n**Project skills:** Check .claude/skills/ or .agents/skills/ directory if either exists. Read SKILL.md files and account for project skill patterns.\n</additional_context>\n\n<output>\nWrite to: {phase_dir}/{phase_num}-RESEARCH.md\n</output>\n"
|
||||
},
|
||||
"produces": [
|
||||
"RESEARCH.md"
|
||||
],
|
||||
"consumes": [
|
||||
"CONTEXT.md"
|
||||
],
|
||||
"when": "workflow.research",
|
||||
"onError": "skip"
|
||||
}
|
||||
],
|
||||
"contributions": [],
|
||||
"gates": []
|
||||
},
|
||||
"trae": {
|
||||
"id": "trae",
|
||||
"role": "runtime",
|
||||
@@ -1070,12 +1199,19 @@ const capabilities = {
|
||||
};
|
||||
|
||||
const bySkill = {
|
||||
"ai-integration-phase": "ai-integration",
|
||||
"graphify": "graphify",
|
||||
"ui-phase": "ui",
|
||||
"ui-review": "ui"
|
||||
};
|
||||
|
||||
const byAgent = {
|
||||
"gsd-framework-selector": "ai-integration",
|
||||
"gsd-ai-researcher": "ai-integration",
|
||||
"gsd-domain-researcher": "ai-integration",
|
||||
"gsd-eval-planner": "ai-integration",
|
||||
"gsd-pattern-mapper": "pattern-mapper",
|
||||
"gsd-phase-researcher": "research",
|
||||
"gsd-ui-checker": "ui",
|
||||
"gsd-ui-auditor": "ui"
|
||||
};
|
||||
@@ -1093,6 +1229,40 @@ const byLoopPoint = {
|
||||
},
|
||||
"plan:pre": {
|
||||
"steps": [
|
||||
{
|
||||
"capId": "ai-integration",
|
||||
"point": "plan:pre",
|
||||
"ref": {
|
||||
"skill": "ai-integration-phase"
|
||||
},
|
||||
"produces": [
|
||||
"AI-SPEC.md"
|
||||
],
|
||||
"consumes": [
|
||||
"CONTEXT.md"
|
||||
],
|
||||
"when": "workflow.ai_integration_phase",
|
||||
"onError": "skip"
|
||||
},
|
||||
{
|
||||
"capId": "research",
|
||||
"point": "plan:pre",
|
||||
"ref": {
|
||||
"agent": "gsd-phase-researcher"
|
||||
},
|
||||
"fragment": {
|
||||
"path": "fragments/plan-pre.md",
|
||||
"inline": "<objective>\nResearch how to implement Phase {phase_number}: {phase_name}\nAnswer: \"What do I need to know to PLAN this phase well?\"\n</objective>\n\n<files_to_read>\n- {context_path} (USER DECISIONS from /gsd:discuss-phase)\n- {requirements_path} (Project requirements)\n- {state_path} (Project decisions and history)\n</files_to_read>\n\n${AGENT_SKILLS_RESEARCHER}\n\n<additional_context>\n**Phase description:** {phase_description}\n**Phase requirement IDs (MUST address):** {phase_req_ids}\n\n**Project instructions:** Read ./CLAUDE.md or ./.claude/CLAUDE.md if either exists; follow project-specific guidelines.\n**Project skills:** Check .claude/skills/ or .agents/skills/ directory if either exists. Read SKILL.md files and account for project skill patterns.\n</additional_context>\n\n<output>\nWrite to: {phase_dir}/{phase_num}-RESEARCH.md\n</output>\n"
|
||||
},
|
||||
"produces": [
|
||||
"RESEARCH.md"
|
||||
],
|
||||
"consumes": [
|
||||
"CONTEXT.md"
|
||||
],
|
||||
"when": "workflow.research",
|
||||
"onError": "skip"
|
||||
},
|
||||
{
|
||||
"capId": "ui",
|
||||
"point": "plan:pre",
|
||||
@@ -1107,6 +1277,25 @@ const byLoopPoint = {
|
||||
],
|
||||
"when": "workflow.ui_phase",
|
||||
"onError": "skip"
|
||||
},
|
||||
{
|
||||
"capId": "pattern-mapper",
|
||||
"point": "plan:pre",
|
||||
"ref": {
|
||||
"agent": "gsd-pattern-mapper"
|
||||
},
|
||||
"fragment": {
|
||||
"path": "fragments/plan-pre.md",
|
||||
"inline": "<pattern_mapping_context>\n**Phase:** {phase_number} - {phase_name}\n**Phase directory:** {phase_dir}\n**Padded phase:** {padded_phase}\n\n<files_to_read>\n- {context_path} (USER DECISIONS from /gsd:discuss-phase)\n- {research_path} (Technical Research)\n</files_to_read>\n\n**Output file:** {phase_dir}/{padded_phase}-PATTERNS.md\n\nExtract the list of files to be created/modified from CONTEXT.md and RESEARCH.md. For each file, classify by role and data flow, find the closest existing analog in the codebase, extract concrete code excerpts, and produce PATTERNS.md.\n</pattern_mapping_context>\n"
|
||||
},
|
||||
"produces": [
|
||||
"PATTERNS.md"
|
||||
],
|
||||
"consumes": [
|
||||
"RESEARCH.md"
|
||||
],
|
||||
"when": "workflow.pattern_mapper",
|
||||
"onError": "skip"
|
||||
}
|
||||
],
|
||||
"contributions": [],
|
||||
@@ -1198,14 +1387,23 @@ const byLoopPoint = {
|
||||
};
|
||||
|
||||
const configKeys = {
|
||||
"workflow.ai_integration_phase": "ai-integration",
|
||||
"graphify.enabled": "graphify",
|
||||
"intel.enabled": "intel",
|
||||
"workflow.pattern_mapper": "pattern-mapper",
|
||||
"workflow.research": "research",
|
||||
"workflow.ui_phase": "ui",
|
||||
"workflow.ui_review": "ui",
|
||||
"workflow.ui_safety_gate": "ui"
|
||||
};
|
||||
|
||||
const configSchema = {
|
||||
"workflow.ai_integration_phase": {
|
||||
"owner": "ai-integration",
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Prompt for an AI-SPEC design contract before planning phases that involve AI systems."
|
||||
},
|
||||
"graphify.enabled": {
|
||||
"owner": "graphify",
|
||||
"type": "boolean",
|
||||
@@ -1218,6 +1416,18 @@ const configSchema = {
|
||||
"default": false,
|
||||
"description": "Enable the intel code-intelligence command."
|
||||
},
|
||||
"workflow.pattern_mapper": {
|
||||
"owner": "pattern-mapper",
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Run the pattern mapper before planning when context or research is available."
|
||||
},
|
||||
"workflow.research": {
|
||||
"owner": "research",
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Run phase research before planning when research artifacts are missing or explicitly refreshed."
|
||||
},
|
||||
"workflow.ui_phase": {
|
||||
"owner": "ui",
|
||||
"type": "boolean",
|
||||
@@ -2155,6 +2365,9 @@ const commandFamilies = {
|
||||
};
|
||||
|
||||
const capabilityClusters = {
|
||||
"ai-integration": [
|
||||
"ai-integration-phase"
|
||||
],
|
||||
"graphify": [
|
||||
"graphify"
|
||||
],
|
||||
@@ -2165,6 +2378,12 @@ const capabilityClusters = {
|
||||
};
|
||||
|
||||
const profileMembership = {
|
||||
"ai-integration": {
|
||||
"tier": "full",
|
||||
"profiles": [
|
||||
"full"
|
||||
]
|
||||
},
|
||||
"graphify": {
|
||||
"tier": "full",
|
||||
"profiles": [
|
||||
@@ -2180,6 +2399,7 @@ const profileMembership = {
|
||||
};
|
||||
|
||||
const _requiresGraph = {
|
||||
"ai-integration": [],
|
||||
"antigravity": [],
|
||||
"audit": [],
|
||||
"augment": [],
|
||||
@@ -2196,7 +2416,11 @@ const _requiresGraph = {
|
||||
"kilo": [],
|
||||
"kimi": [],
|
||||
"opencode": [],
|
||||
"pattern-mapper": [
|
||||
"research"
|
||||
],
|
||||
"qwen": [],
|
||||
"research": [],
|
||||
"trae": [],
|
||||
"ui": [],
|
||||
"windsurf": []
|
||||
|
||||
@@ -411,45 +411,20 @@ If "Run discuss-phase first":
|
||||
```
|
||||
**Exit the plan-phase workflow. Do not continue.**
|
||||
|
||||
## 4.5. Check AI-SPEC
|
||||
## 4.5. Resolve AI-SPEC Artifact
|
||||
|
||||
**Skip if:** `ai_integration_phase_enabled` from config is false, or `--skip-ai-spec` flag provided.
|
||||
AI integration activation is owned by the `ai-integration` capability's `plan:pre` step hook. The plan-phase host only discovers existing artifacts here so the planner can consume them; it must not read the capability's config key directly.
|
||||
|
||||
```bash
|
||||
AI_SPEC_FILE=$(ls "${PHASE_DIR}"/*-AI-SPEC.md 2>/dev/null | head -1)
|
||||
AI_PHASE_CFG=$(gsd_run query config-get workflow.ai_integration_phase 2>/dev/null || echo "true")
|
||||
AI_SPEC_PATH="${AI_SPEC_FILE}"
|
||||
FRAMEWORK_LINE=""
|
||||
if [ -n "$AI_SPEC_FILE" ]; then
|
||||
FRAMEWORK_LINE=$(grep "Selected Framework:" "${AI_SPEC_FILE}" | head -1)
|
||||
fi
|
||||
```
|
||||
|
||||
**Skip if `AI_PHASE_CFG` is `false`.**
|
||||
|
||||
**If `AI_SPEC_FILE` is empty:** Check phase goal for AI keywords:
|
||||
```bash
|
||||
echo "${phase_goal}" | grep -qi "agent\|llm\|rag\|chatbot\|embedding\|langchain\|llamaindex\|crewai\|langgraph\|openai\|anthropic\|vector\|eval\|ai system"
|
||||
```
|
||||
|
||||
**If AI keywords detected AND no AI-SPEC.md:**
|
||||
```
|
||||
◆ Note: This phase appears to involve AI system development.
|
||||
Consider running /gsd:ai-integration-phase {N} before planning to:
|
||||
- Select the right framework for your use case
|
||||
- Research its docs and best practices
|
||||
- Design an evaluation strategy
|
||||
|
||||
Continue planning without AI-SPEC? (non-blocking — /gsd:ai-integration-phase can be run after)
|
||||
```
|
||||
|
||||
Use AskUserQuestion with options:
|
||||
- "Continue — plan without AI-SPEC"
|
||||
- "Stop — I'll run /gsd:ai-integration-phase {N} first"
|
||||
|
||||
If "Stop": Exit with `/gsd:ai-integration-phase {N}` reminder.
|
||||
If "Continue": Proceed. (Non-blocking — planner will note AI-SPEC is absent.)
|
||||
|
||||
**If `AI_SPEC_FILE` is non-empty:** Extract framework for planner context:
|
||||
```bash
|
||||
FRAMEWORK_LINE=$(grep "Selected Framework:" "${AI_SPEC_FILE}" | head -1)
|
||||
```
|
||||
Pass `ai_spec_path` and `framework_line` to planner in step 7 so it can reference the AI design contract.
|
||||
If `AI_SPEC_FILE` is non-empty, pass `AI_SPEC_PATH` and `FRAMEWORK_LINE` to the planner in step 8 so it can reference the AI design contract. If it is empty, the active `ai-integration` capability hook in step 5.6 handles any AI-system nudge or `/gsd:ai-integration-phase` dispatch.
|
||||
|
||||
## 5. Handle Research
|
||||
|
||||
@@ -525,41 +500,21 @@ Display banner:
|
||||
|
||||
```bash
|
||||
PHASE_DESC=$(gsd_run query roadmap.get-phase "${PHASE}" --pick section)
|
||||
if [ -z "${PLAN_PRE_HOOKS_JSON:-}" ]; then
|
||||
PLAN_PRE_HOOKS_JSON=$(gsd_run loop render-hooks plan:pre --raw)
|
||||
fi
|
||||
```
|
||||
|
||||
Research prompt:
|
||||
Find the active `research` step hook in `PLAN_PRE_HOOKS_JSON`. Use the hook's `fragment.inline` as the prompt template and substitute the phase fields below before spawning its declared `ref.agent`.
|
||||
|
||||
```markdown
|
||||
<objective>
|
||||
Research how to implement Phase {phase_number}: {phase_name}
|
||||
Answer: "What do I need to know to PLAN this phase well?"
|
||||
</objective>
|
||||
|
||||
<files_to_read>
|
||||
- {context_path} (USER DECISIONS from /gsd:discuss-phase)
|
||||
- {requirements_path} (Project requirements)
|
||||
- {state_path} (Project decisions and history)
|
||||
</files_to_read>
|
||||
|
||||
${AGENT_SKILLS_RESEARCHER}
|
||||
|
||||
<additional_context>
|
||||
**Phase description:** {phase_description}
|
||||
**Phase requirement IDs (MUST address):** {phase_req_ids}
|
||||
|
||||
**Project instructions:** Read ./CLAUDE.md or ./.claude/CLAUDE.md if either exists — follow project-specific guidelines
|
||||
**Project skills:** Check .claude/skills/ or .agents/skills/ directory (if either exists) — read SKILL.md files, research should account for project skill patterns
|
||||
</additional_context>
|
||||
|
||||
<output>
|
||||
Write to: {phase_dir}/{phase_num}-RESEARCH.md
|
||||
</output>
|
||||
{research_hook.fragment.inline}
|
||||
```
|
||||
|
||||
```
|
||||
Agent(
|
||||
prompt=research_prompt,
|
||||
subagent_type="gsd-phase-researcher",
|
||||
prompt=filled_research_hook_fragment,
|
||||
subagent_type=research_hook.ref.agent,
|
||||
model="{researcher_model}",
|
||||
description="Research Phase {phase}"
|
||||
)
|
||||
@@ -646,21 +601,31 @@ Opt out: set security_enforcement: false in .planning/config.json
|
||||
|
||||
Continue to step 5.6. Security config is passed to the planner in step 8.
|
||||
|
||||
## 5.6. UI Design Contract Gate
|
||||
## 5.6. Plan:Pre Capability Dispatch and UI Design Contract Gate
|
||||
|
||||
> Capability-driven dispatch. Resolves active `plan:pre` hooks via the capability registry; each hook's `when` condition (`workflow.ui_phase` for step hooks, `workflow.ui_safety_gate` for gate hooks) is evaluated by the registry — no inline config-get needed.
|
||||
> Capability-driven dispatch. Resolves active `plan:pre` hooks via the capability registry; each hook's `when` condition is evaluated by the registry — no inline config-get needed. This section handles skill-based planning preflights such as `ai-integration`, agent-backed hooks through `ref.agent`, and the UI gate whose deterministic check comes from `check.query`.
|
||||
>
|
||||
> **Config semantics (cutover fix):** `workflow.ui_phase` gates UI-SPEC *generation* (step); `workflow.ui_safety_gate` gates the *planning block* (gate). Both-on = identical to OLD §5.6. Intended change: `{ui_phase:true, ui_safety_gate:false}` now auto-generates in pipelines but does NOT block manual planning (each key controls exactly what its description says).
|
||||
|
||||
```bash
|
||||
HOOKS_JSON=$(gsd_run loop render-hooks plan:pre --raw)
|
||||
PLAN_PRE_HOOKS_JSON=${PLAN_PRE_HOOKS_JSON:-$(gsd_run loop render-hooks plan:pre --raw)}
|
||||
HOOKS_JSON="$PLAN_PRE_HOOKS_JSON"
|
||||
```
|
||||
|
||||
Read the `activeHooks` array directly from `HOOKS_JSON` (in-context — do NOT invoke a shell pipeline).
|
||||
Read the `activeHooks` array directly from `PLAN_PRE_HOOKS_JSON` / `HOOKS_JSON` (in-context — do NOT invoke a shell pipeline).
|
||||
|
||||
**Branch 1 — both toggles off (`activeHooks` is empty or absent):** Skip to step 6.
|
||||
**Branch 1 — all plan:pre hooks inactive (`activeHooks` is empty or absent):** Skip to step 6.
|
||||
|
||||
Run whenever **any** `plan:pre` UI hook is active — including the step-only case (`workflow.ui_safety_gate` off). (`check.query` = `"ui.plan-gate"`; router normalizes dots→hyphens.)
|
||||
**Generic step hook dispatch contract:** For each active entry where `kind == "step"`:
|
||||
- If `ref.skill` is set, dispatch with `Skill(skill="gsd-${ref.skill}", args="${PHASE} --auto ${GSD_WS}")` when pipeline mode allows auto-chaining. Prepend `gsd-` to `ref.skill` — `ui-phase` → `gsd-ui-phase`.
|
||||
- If `ref.agent` is set, dispatch with `Agent(prompt=filled_hook_fragment, subagent_type=ref.agent, model="{researcher_model}")`. Use the hook's `fragment.inline` as the prompt body and fill phase fields before spawning.
|
||||
- The `research` hook is handled by §5.1's research decision. The `pattern-mapper` hook is handled by §7.8 after `RESEARCH_PATH` is known. Future plan:pre agent hooks use the same `ref.agent` fragment contract.
|
||||
|
||||
**AI integration capability:** If the active `ai-integration` step hook is present, `AI_SPEC_PATH` is empty, and the phase goal contains AI keywords (`agent`, `llm`, `rag`, `chatbot`, `embedding`, `langchain`, `llamaindex`, `crewai`, `langgraph`, `openai`, `anthropic`, `vector`, `eval`, `ai system`), then:
|
||||
- In pipeline / `--auto` mode, invoke the hook's `ref.skill` via `Skill(skill="gsd-${ref.skill}", args="${PHASE} --auto ${GSD_WS}")`.
|
||||
- In manual mode, display the existing non-blocking `/gsd:ai-integration-phase {N}` recommendation and let the user continue planning without AI-SPEC or stop to run the capability workflow first.
|
||||
|
||||
Run the UI deterministic gate whenever **any** `plan:pre` UI hook is active — including the step-only case (`workflow.ui_safety_gate` off). (`check.query` = `"ui.plan-gate"`; router normalizes dots→hyphens.)
|
||||
|
||||
```bash
|
||||
GATE=$(gsd_run check ui-plan-gate "${PHASE}" --raw)
|
||||
@@ -689,13 +654,13 @@ Read the ephemeral auto-chain flag:
|
||||
AUTO_CHAIN=$(gsd_run query check auto-mode --pick auto_chain_active 2>/dev/null || echo "false")
|
||||
```
|
||||
|
||||
**Branch 5 — `AUTO_CHAIN` is `true` (pipeline / `--auto`):** Fire each active **step** hook — runs independently of whether a gate is active (covers `{ui_phase:true, ui_safety_gate:false}`). For each entry in `activeHooks` (in array order) where `kind == "step"` and `ref.skill` is set:
|
||||
**Branch 5 — `AUTO_CHAIN` is `true` (pipeline / `--auto`):** Fire each active UI **step** hook — runs independently of whether a gate is active (covers `{ui_phase:true,ui_safety_gate:false}`). For each entry in `activeHooks` (in array order) where `kind == "step"` and `ref.skill` is set:
|
||||
|
||||
```
|
||||
Skill(skill="gsd-${ref.skill}", args="${PHASE} --auto ${GSD_WS}")
|
||||
```
|
||||
|
||||
(prepend `gsd-` to `ref.skill` — `ui-phase` → `gsd-ui-phase`.) After all step hooks return, re-read:
|
||||
After all UI step hooks return, re-read:
|
||||
|
||||
```bash
|
||||
UI_SPEC_FILE=$(ls "${PHASE_DIR}"/*-UI-SPEC.md 2>/dev/null | head -1)
|
||||
@@ -845,14 +810,7 @@ Proceed to Step 7.8 (or Step 8 if pattern mapper is disabled) only if user selec
|
||||
|
||||
## 7.8. Spawn gsd-pattern-mapper Agent (Optional)
|
||||
|
||||
**Skip if** `workflow.pattern_mapper` is explicitly set to `false` in config.json (absent key = enabled). Also skip if no CONTEXT.md and no RESEARCH.md exist for this phase (nothing to extract file lists from).
|
||||
|
||||
Check config:
|
||||
```bash
|
||||
PATTERN_MAPPER_CFG=$(gsd_run query config-get workflow.pattern_mapper 2>/dev/null || echo "true")
|
||||
```
|
||||
|
||||
**If `PATTERN_MAPPER_CFG` is `false`:** Skip to step 8.
|
||||
Pattern mapper activation is owned by the `pattern-mapper` capability's `plan:pre` step hook. Read `PLAN_PRE_HOOKS_JSON` and skip if no active step hook has `capId == "pattern-mapper"` and `ref.agent == "gsd-pattern-mapper"`. Also skip if no CONTEXT.md and no RESEARCH.md exist for this phase (nothing to extract file lists from).
|
||||
|
||||
**If PATTERNS.md already exists** (`PATTERNS_PATH` is non-empty from step 7): Skip to step 8 (use existing).
|
||||
|
||||
@@ -865,30 +823,17 @@ Display banner:
|
||||
◆ Spawning pattern mapper... (runs in a subagent — no output until it returns, ~1–5 min; expected, not a freeze)
|
||||
```
|
||||
|
||||
Pattern mapper prompt:
|
||||
Use the active `pattern-mapper` hook's `fragment.inline` as the prompt template and substitute the phase fields below before spawning its declared `ref.agent`.
|
||||
|
||||
```markdown
|
||||
<pattern_mapping_context>
|
||||
**Phase:** {phase_number} - {phase_name}
|
||||
**Phase directory:** {phase_dir}
|
||||
**Padded phase:** {padded_phase}
|
||||
|
||||
<files_to_read>
|
||||
- {context_path} (USER DECISIONS from /gsd:discuss-phase)
|
||||
- {research_path} (Technical Research)
|
||||
</files_to_read>
|
||||
|
||||
**Output file:** {phase_dir}/{padded_phase}-PATTERNS.md
|
||||
|
||||
Extract the list of files to be created/modified from CONTEXT.md and RESEARCH.md. For each file, classify by role and data flow, find the closest existing analog in the codebase, extract concrete code excerpts, and produce PATTERNS.md.
|
||||
</pattern_mapping_context>
|
||||
{pattern_mapper_hook.fragment.inline}
|
||||
```
|
||||
|
||||
Spawn with:
|
||||
```
|
||||
Agent(
|
||||
prompt="{above}",
|
||||
subagent_type="gsd-pattern-mapper",
|
||||
prompt=filled_pattern_mapper_hook_fragment,
|
||||
subagent_type=pattern_mapper_hook.ref.agent,
|
||||
model="{researcher_model}",
|
||||
)
|
||||
```
|
||||
@@ -944,6 +889,7 @@ Planner prompt:
|
||||
- {verification_path} (Verification Gaps - if --gaps)
|
||||
- {uat_path} (UAT Gaps - if --gaps)
|
||||
- {reviews_path} (Cross-AI Review Feedback - if --reviews; actionable findings must be incorporated or explicitly deferred/rejected in PLAN.md)
|
||||
- {AI_SPEC_PATH} (AI Design Contract — framework and evaluation strategy, if exists)
|
||||
- {UI_SPEC_PATH} (UI Design Contract — visual/interaction specs, if exists)
|
||||
- {SPEC_PATH} (Phase SPEC — carries the ## Edge Coverage section to lift covered/backstop edges from, if exists)
|
||||
- {SPIKE_FINDINGS_PATH} (Spike Findings — validated patterns, constraints, landmines from experiments, if exists)
|
||||
|
||||
Reference in New Issue
Block a user