gaia-framework 1.66.0 → 1.83.2

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.
Files changed (38) hide show
  1. package/.claude/commands/gaia-create-stakeholder.md +20 -0
  2. package/.claude/commands/gaia-test-gap-analysis.md +17 -0
  3. package/CLAUDE.md +87 -1
  4. package/README.md +2 -2
  5. package/_gaia/_config/global.yaml +5 -1
  6. package/_gaia/_config/lifecycle-sequence.yaml +20 -0
  7. package/_gaia/_config/skill-manifest.csv +2 -0
  8. package/_gaia/_config/workflow-manifest.csv +3 -1
  9. package/_gaia/core/engine/workflow.xml +5 -1
  10. package/_gaia/core/workflows/party-mode/steps/step-01-agent-loading.md +60 -9
  11. package/_gaia/creative/workflows/problem-solving/checklist.md +64 -14
  12. package/_gaia/creative/workflows/problem-solving/instructions.xml +367 -22
  13. package/_gaia/creative/workflows/problem-solving/workflow.yaml +31 -1
  14. package/_gaia/dev/agents/_base-dev.md +7 -1
  15. package/_gaia/dev/skills/_skill-index.yaml +9 -0
  16. package/_gaia/dev/skills/figma-integration.md +296 -0
  17. package/_gaia/lifecycle/templates/brownfield-scan-security-prompt.md +228 -0
  18. package/_gaia/lifecycle/templates/gap-entry-schema.md +39 -4
  19. package/_gaia/lifecycle/templates/story-template.md +22 -1
  20. package/_gaia/lifecycle/workflows/2-planning/create-ux-design/instructions.xml +52 -3
  21. package/_gaia/lifecycle/workflows/4-implementation/create-stakeholder/checklist.md +25 -0
  22. package/_gaia/lifecycle/workflows/4-implementation/create-stakeholder/instructions.xml +79 -0
  23. package/_gaia/lifecycle/workflows/4-implementation/create-stakeholder/workflow.yaml +22 -0
  24. package/_gaia/lifecycle/workflows/4-implementation/create-story/instructions.xml +10 -0
  25. package/_gaia/lifecycle/workflows/4-implementation/retrospective/instructions.xml +3 -3
  26. package/_gaia/lifecycle/workflows/4-implementation/validate-story/instructions.xml +11 -0
  27. package/_gaia/lifecycle/workflows/anytime/brownfield-onboarding/instructions.xml +11 -7
  28. package/_gaia/testing/workflows/test-gap-analysis/checklist.md +8 -0
  29. package/_gaia/testing/workflows/test-gap-analysis/instructions.xml +53 -0
  30. package/_gaia/testing/workflows/test-gap-analysis/workflow.yaml +38 -0
  31. package/bin/gaia-framework.js +36 -2
  32. package/bin/helpers/derive-bump-label.js +41 -0
  33. package/bin/helpers/validate-bump-labels.js +38 -0
  34. package/gaia-install.sh +71 -4
  35. package/package.json +1 -1
  36. package/_gaia/_memory/tier2-results/.gitkeep +0 -0
  37. package/_gaia/_memory/tier2-results/checkpoint-resume-2026-03-24.yaml +0 -6
  38. package/_gaia/_memory/tier2-results/engine-scenarios-2026-03-22.yaml +0 -14
@@ -12,6 +12,8 @@ points: "{story_points}"
12
12
  risk: "{high/medium/low}"
13
13
  sprint_id: null
14
14
  priority_flag: null
15
+ origin: null
16
+ origin_ref: null
15
17
  depends_on: []
16
18
  blocks: []
17
19
  traces_to: []
@@ -116,4 +118,23 @@ As a {role}, I want to {action}, so that {benefit}.
116
118
 
117
119
  ## Definition of Done
118
120
 
119
- - [ ] Define all the Definition of Done
121
+ ### Acceptance
122
+
123
+ - [ ] All acceptance criteria verified and checked off
124
+ - [ ] All subtasks marked complete
125
+
126
+ ### Testing
127
+
128
+ - [ ] All tests pass (unit, integration, e2e as applicable)
129
+ - [ ] No linting or formatting errors
130
+
131
+ ### Code Quality & CI
132
+
133
+ - [ ] Code compiles / builds without errors
134
+ - [ ] Code follows project conventions
135
+ - [ ] No hardcoded secrets or credentials
136
+ - [ ] PR merged to staging with all CI checks passing
137
+
138
+ ### Documentation
139
+
140
+ - [ ] Documentation updated (if applicable)
@@ -32,12 +32,61 @@
32
32
  <action>Plan keyboard navigation, screen reader support</action>
33
33
  <action>Define color contrast and text sizing standards</action>
34
34
  </step>
35
- <step n="7" title="Generate Output">
35
+ <step n="7" title="Figma MCP Detection and Mode Selection">
36
+ <action>Probe for available Figma MCP server. Load figma-integration.md detection section JIT to determine if a design tool adapter is available.</action>
37
+ <action if="figma_mcp_available">Present mode selection to user: [Generate] Create Figma frames alongside ux-design.md | [Import] Import existing Figma designs (read-only) | [Skip] Text-only UX spec, no Figma integration</action>
38
+ <action if="not figma_mcp_available">Skip Figma integration — proceed with text-only UX design output. Log: "No Figma MCP server detected. Generating markdown-only ux-design.md."</action>
39
+ </step>
40
+ <step n="8" title="Generate Mode — UI Kit Page Creation" if="figma_mcp_available AND user_selected_generate">
41
+ <critical>
42
+ <mandate>Generate mode is the ONLY mode that performs write operations to Figma (FR-140). All other modes are read-only. Write operations: create pages, create frames, create component instances. Minimum required Figma API scopes: files:read + file_content:read + files:write.</mandate>
43
+ </critical>
44
+ <action>Load figma-integration.md frames section JIT from _gaia/dev/skills/figma-integration.md</action>
45
+ <action>Create a UI Kit page named "UI Kit — Generated" in the Figma design file via MCP</action>
46
+ <action>Extract design tokens from {planning_artifacts}/design-system/design-tokens.json (W3C DTCG format)</action>
47
+ <action>Create color styles with semantic aliases from token definitions (e.g., color.surface.primary, color.text.primary)</action>
48
+ <action>Create typography styles from composite token specs (heading-1, heading-2, body, caption)</action>
49
+ <action>Create spacing grid tokens and base components with state variants (default, hover, active, disabled, focus)</action>
50
+ <action>Error handling: on HTTP 429 rate limit, perform a single retry after backoff. If 429 persists, graceful fallback to markdown-only flow — log warning and skip remaining Figma operations.</action>
51
+ </step>
52
+ <step n="9" title="Generate Mode — Per-Screen Frame Generation" if="figma_mcp_available AND user_selected_generate">
53
+ <action>Parse PRD user journeys to determine screens needing frames</action>
54
+ <action>For each screen, generate frames at 6 viewports: 280px (foldable inner, FR-174), 375px (mobile), 600px (foldable outer, FR-174), 768px (tablet portrait), 1024px (tablet landscape, FR-174), 1280px (desktop)</action>
55
+ <action>Compose frames using UI Kit components from the previous step — apply auto-layout with responsive constraints from component specs</action>
56
+ <action>Label frames using naming convention: {ScreenName}/{Viewport} (e.g., Dashboard/Desktop, Login/Mobile)</action>
57
+ <action>Collect all generated Figma node IDs for downstream recording in ux-design.md</action>
58
+ </step>
59
+ <step n="10" title="Generate Mode — Prototype Flow Setup" if="figma_mcp_available AND user_selected_generate">
60
+ <action>Map PRD user journey steps to the generated screen frames</action>
61
+ <action>Create prototype flow connections between frames via Figma MCP, linking screens in the order defined by each user journey</action>
62
+ <action>Validate flow completeness: every user journey step must map to a generated frame. Flag any unmapped journey steps as warnings.</action>
63
+ </step>
64
+ <step n="11" title="Generate Mode — Asset Export Configuration" if="figma_mcp_available AND user_selected_generate">
65
+ <action>Configure PNG export at 1x, 2x, 3x densities for raster assets (images, illustrations)</action>
66
+ <action>Configure SVG export for icon components</action>
67
+ <action>Generate platform-specific asset catalogs per FR-175: iOS .xcassets catalog structure with Contents.json manifests, Android drawable-mdpi/drawable-hdpi/drawable-xhdpi/drawable-xxhdpi/drawable-xxxhdpi directories</action>
68
+ <action>Write export configuration and asset manifest to {planning_artifacts}/design-system/assets/ directory</action>
69
+ <action>Check {project-path}/.figma-cache/ for cached responses (1h TTL) before making MCP read calls — use cached data if fresh, fetch and cache if stale or missing</action>
70
+ </step>
71
+ <step n="12" title="Generate Mode — Record Figma Node IDs and Enhance ux-design.md" if="figma_mcp_available AND user_selected_generate">
72
+ <action>Build Screen-to-Frame mapping table from all generated Figma node IDs: columns Screen Name | Viewport | Figma Node ID | Page</action>
73
+ <action>Add figma: YAML frontmatter block to ux-design.md containing: file_key, pages array with node IDs for each generated page, and last_synced ISO 8601 timestamp</action>
74
+ <action>Add Design Tokens reference section linking to {planning_artifacts}/design-system/design-tokens.json with token category summary</action>
75
+ <action>Add Component Inventory section listing all generated UI Kit components with their Figma node IDs, variant counts, and state definitions</action>
76
+ <action>Add Screen-to-Frame mapping table with all generated frames across all viewports</action>
77
+ <action>Ensure backward compatibility: existing text-only ux-design.md content is preserved. Figma sections are additive — they appear after the standard UX design sections.</action>
78
+ </step>
79
+ <step n="13" title="Generate Output">
36
80
  <template-output file="{planning_artifacts}/ux-design.md">
37
- Generate UX design document with: personas, information architecture, wireframe descriptions, interaction patterns, component specifications, accessibility plan, and FR-to-Screen Mapping table (FR ID | Screen/Page | Wireframe Section).
81
+ Generate UX design document with: personas, information architecture, wireframe descriptions, interaction patterns, component specifications, accessibility plan, FR-to-Screen Mapping table (FR ID | Screen/Page | Wireframe Section). If Generate mode was active: include figma: frontmatter block, Design Tokens section, Component Inventory with Figma node IDs, and Screen-to-Frame mapping table.
38
82
  </template-output>
39
83
  </step>
40
- <step n="8" title="Optional: Accessibility Review">
84
+ <step n="14" title="FR-140 Compliance Check" if="figma_mcp_available AND user_selected_generate">
85
+ <action>Audit all MCP calls executed during Generate mode: classify each as READ (get_file, get_styles, get_components, get_images, get_frames) or WRITE (create_frame, create_component_instance, create_page)</action>
86
+ <action>Verify FR-140 constraint: write operations only occurred during Generate mode steps (8–12). Import mode and Skip mode must have zero write calls.</action>
87
+ <action>Document minimum required Figma API scopes: files:read + file_content:read (default for all modes), files:write (Generate mode only)</action>
88
+ </step>
89
+ <step n="15" title="Optional: Accessibility Review">
41
90
  <ask>Would you like to review the UX design for WCAG 2.1 accessibility compliance? This spawns a subagent in a separate context. Recommended for user-facing applications. (yes / skip)</ask>
42
91
  <action>If yes: spawn a subagent using the Agent tool: "Load {project-root}/_gaia/core/tasks/review-accessibility.xml. Read its entire contents. Target: {planning_artifacts}/ux-design.md. Follow the flow steps EXACTLY. Generate accessibility findings report."</action>
43
92
  <action>If skip: accessibility review can be run anytime later with /gaia-review-a11y</action>
@@ -0,0 +1,25 @@
1
+ ---
2
+ title: 'Create Stakeholder Validation'
3
+ validation-target: 'Stakeholder file'
4
+ ---
5
+ ## Structure
6
+ - [ ] workflow.yaml present with agent: orchestrator
7
+ - [ ] instructions.xml present with sequential steps
8
+ - [ ] checklist.md present
9
+ - [ ] Registered in workflow-manifest.csv
10
+ - [ ] Slash command file exists at .claude/commands/gaia-create-stakeholder.md
11
+ ## Input Collection
12
+ - [ ] Required fields prompted: name, role, expertise, personality
13
+ - [ ] Optional fields prompted: perspective, tags
14
+ - [ ] Required field validation (non-empty check)
15
+ ## Validation Guards
16
+ - [ ] 50-file cap enforced before file creation
17
+ - [ ] Case-insensitive duplicate name detection against existing stakeholder name frontmatter
18
+ - [ ] custom/stakeholders/ directory auto-created if missing
19
+ ## Output
20
+ - [ ] Filename is kebab-case slug of name with .md extension
21
+ - [ ] File written to custom/stakeholders/{slug}.md
22
+ - [ ] YAML frontmatter includes all required fields
23
+ - [ ] Optional fields included only when provided
24
+ - [ ] Markdown body with ## Background section
25
+ - [ ] File does not exceed 100 lines
@@ -0,0 +1,79 @@
1
+ <workflow name="create-stakeholder">
2
+ <critical>
3
+ <mandate>Stakeholder files are written to custom/stakeholders/ — never to _gaia/</mandate>
4
+ <mandate>The 50-file cap and 100-line limit are hard gates (FR-164)</mandate>
5
+ <mandate>Duplicate name detection is case-insensitive against the name frontmatter field (FR-157)</mandate>
6
+ </critical>
7
+
8
+ <step n="1" title="Ensure Directory Exists">
9
+ <action>Check if {project-root}/custom/stakeholders/ directory exists</action>
10
+ <action if="directory does not exist">Create {project-root}/custom/stakeholders/ directory (and {project-root}/custom/ if needed)</action>
11
+ <action>Confirm directory is ready for writing</action>
12
+ </step>
13
+
14
+ <step n="2" title="Collect Required Inputs">
15
+ <ask>Provide the following required fields for the new stakeholder:
16
+
17
+ **Name** (display name, e.g., "Maria Santos"):
18
+ **Role** (title/function, e.g., "Housekeeper Manager"):
19
+ **Expertise** (domain skills, e.g., "Room turnover logistics"):
20
+ **Personality** (traits, e.g., "Pragmatic, detail-oriented"):
21
+ </ask>
22
+ <check if="any required field is empty">HALT: All four fields (name, role, expertise, personality) are required. Please provide all values.</check>
23
+ </step>
24
+
25
+ <step n="3" title="Collect Optional Inputs">
26
+ <ask>Optionally provide these additional fields (press Enter to skip):
27
+
28
+ **Perspective** (viewpoint/biases, e.g., "Focuses on operational efficiency"):
29
+ **Tags** (comma-separated, e.g., "operations, hospitality"):
30
+ </ask>
31
+ </step>
32
+
33
+ <step n="4" title="Validate Against Cap and Duplicates">
34
+ <action>Count existing .md files in {project-root}/custom/stakeholders/ directory</action>
35
+ <check if="count >= 50">HALT: The 50-file cap has been reached in custom/stakeholders/ (FR-164). There are already {count} stakeholder files. Remove unused stakeholders before creating new ones.</check>
36
+ <action>Scan all existing stakeholder files in custom/stakeholders/*.md — read the name field from each file's YAML frontmatter</action>
37
+ <action>Compare each existing name against the new stakeholder name using case-insensitive comparison</action>
38
+ <check if="duplicate name found (case-insensitive match)">HALT: A stakeholder with the name "{existing_name}" already exists at custom/stakeholders/{existing_file}. Name collision detected (case-insensitive). Choose a different name.</check>
39
+ </step>
40
+
41
+ <step n="5" title="Generate Filename Slug">
42
+ <action>Convert the stakeholder name to a kebab-case slug:
43
+ 1. Convert to lowercase
44
+ 2. Replace spaces with hyphens
45
+ 3. Strip all characters that are not alphanumeric or hyphens
46
+ 4. Collapse multiple consecutive hyphens into a single hyphen
47
+ 5. Trim leading/trailing hyphens
48
+ 6. Append .md extension
49
+ </action>
50
+ <action>Example: "Maria Santos" → "maria-santos.md", "Jean-Pierre O'Brien III" → "jean-pierre-obrien-iii.md"</action>
51
+ <action>Set output path: {project-root}/custom/stakeholders/{slug}.md</action>
52
+ <check if="file already exists at output path">HALT: File custom/stakeholders/{slug}.md already exists. This may indicate a slug collision from a different display name. Choose a different name or remove the existing file.</check>
53
+ </step>
54
+
55
+ <step n="6" title="Generate and Write Stakeholder File">
56
+ <action>Generate the stakeholder file with YAML frontmatter and Markdown body:
57
+
58
+ ```
59
+ ---
60
+ name: "{name}"
61
+ role: "{role}"
62
+ expertise: "{expertise}"
63
+ personality: "{personality}"
64
+ perspective: "{perspective}" # Only include if provided
65
+ tags: [{tags_as_yaml_array}] # Only include if provided
66
+ ---
67
+
68
+ ## Background
69
+
70
+ {A 2-3 sentence description synthesized from the provided fields, describing this stakeholder's viewpoint and discussion style.}
71
+ ```
72
+ </action>
73
+ <action>Verify the generated file does not exceed 100 lines. If it does, trim the Background section to fit within the limit.</action>
74
+ <action>Write the file to {project-root}/custom/stakeholders/{slug}.md</action>
75
+ <template-output file="{project-root}/custom/stakeholders/{slug}.md">
76
+ Stakeholder file with YAML frontmatter (name, role, expertise, personality, and optionally perspective and tags) plus a Markdown Background section.
77
+ </template-output>
78
+ </step>
79
+ </workflow>
@@ -0,0 +1,22 @@
1
+ name: create-stakeholder
2
+ description: 'Scaffold a new stakeholder file for Party Mode discussions'
3
+ module: lifecycle
4
+ agent: orchestrator
5
+ config_resolved: "{installed_path}/.resolved/create-stakeholder.yaml"
6
+ config_source: "{project-root}/_gaia/lifecycle/config.yaml"
7
+ installed_path: "{project-root}/_gaia/lifecycle/workflows/4-implementation/create-stakeholder"
8
+ instructions: "{installed_path}/instructions.xml"
9
+ validation: "{installed_path}/checklist.md"
10
+ quality_gates:
11
+ pre_start: []
12
+ post_complete:
13
+ - check: "stakeholder_file_line_count_valid == true"
14
+ on_fail: "HALT: Stakeholder file exceeds 100-line limit (FR-164). Edit {project-root}/custom/stakeholders/{slug}.md to reduce content or re-run /gaia-create-stakeholder."
15
+ - check: "stakeholder_count_in_directory_valid == true"
16
+ on_fail: "HALT: custom/stakeholders/ has more than 50 files (FR-164). Remove unused stakeholders from {project-root}/custom/stakeholders/ first."
17
+ on_error:
18
+ missing_file: "ask_user"
19
+ unresolved_variable: "halt"
20
+
21
+ output:
22
+ primary: "{project-root}/custom/stakeholders/{slug}.md"
@@ -94,6 +94,14 @@
94
94
  <step n="6" title="Generate Output">
95
95
  <action>Read the story template from the engine-resolved template path. The engine resolves this in Step 1 (Load and Resolve Config): if {project-root}/custom/templates/story-template.md exists and is non-empty, the custom template is used; otherwise it falls back to {project-root}/_gaia/lifecycle/templates/story-template.md. Use whichever path the engine resolved.</action>
96
96
  <action>Read sizing_map from {project-root}/_gaia/_config/global.yaml to resolve T-shirt size to story points (S→2, M→5, L→8, XL→13).</action>
97
+ <action>Detect invocation context to determine origin fields:
98
+ If invoked from problem-solving routing (E16-S3): set origin="problem-solving" and origin_ref to the path of the Problem Brief or problem-solving checkpoint artifact (e.g., docs/creative-artifacts/problem-solving-YYYY-MM-DD.md).
99
+ If invoked from triage routing: set origin="triage" and origin_ref to the triage artifact path.
100
+ If invoked from add-feature routing: set origin="add-feature" and origin_ref to the source artifact path.
101
+ If invoked from sprint-planning: set origin="sprint-planning" and origin_ref to the sprint plan artifact path.
102
+ If invoked with explicit origin parameters from caller: use the provided origin and origin_ref values.
103
+ If invoked normally (no routing context): set origin=null and origin_ref=null (planned work default).
104
+ </action>
97
105
  <action>Populate ALL YAML frontmatter fields from epics-and-stories.md data:
98
106
  - key: story key from epics (e.g., E1-S1)
99
107
  - title: story title
@@ -110,6 +118,8 @@
110
118
  - date: current date
111
119
  - author: agent name (e.g., "Nate (Scrum Master)")
112
120
  - priority_flag: null (default — set to "next-sprint" by add-feature for high-urgency stories)
121
+ - origin: workflow origin (null for planned work, "problem-solving" from problem-solving routing, "triage" from triage, "add-feature" from add-feature routing, "sprint-planning" from sprint planning, "manual" for explicit manual creation)
122
+ - origin_ref: path to source artifact that triggered story creation (null when origin is null)
113
123
  </action>
114
124
  <template-output file="{implementation_artifacts}/{story_key}-{story_title_slug}.md">
115
125
  Generate the story file following the story-template.md structure. The filename must use the story key and slugified title (e.g., E1-S1-user-login.md). Include complete YAML frontmatter with ALL 15 fields populated. Fill all template sections: User Story, Acceptance Criteria, Tasks/Subtasks (linked to AC numbers), Dev Notes, Technical Notes, Dependencies, Test Scenarios, Project Structure Notes, References, Dev Agent Record, and Estimate. IMPORTANT: The body "**Status:**" line MUST match the frontmatter status field exactly. Both must say the same status value.
@@ -108,14 +108,14 @@
108
108
 
109
109
  3. Apply the improvement: append to or modify the relevant section in custom/skills/{skill-name}.md with comment "<!-- Added from retro-{sprint_id}: {reason} -->".
110
110
 
111
- 4. Register in .customize.yaml: after writing the custom skill file, register it in {project-root}/_gaia/_config/agents/all-dev.customize.yaml so the engine loads from the custom path on subsequent runs.
112
- - If all-dev.customize.yaml does not exist: create it with proper YAML structure:
111
+ 4. Register in .customize.yaml: after writing the custom skill file, register it in {project-root}/custom/skills/all-dev.customize.yaml so the engine loads from the custom path on subsequent runs (ADR-020 — customization registries live alongside custom skills in custom/skills/).
112
+ - If custom/skills/all-dev.customize.yaml does not exist: create it with proper YAML structure:
113
113
  ```yaml
114
114
  skill_overrides:
115
115
  {skill-name}:
116
116
  source: "custom/skills/{skill-name}.md"
117
117
  ```
118
- - If all-dev.customize.yaml already exists: read current content, check if a skill_overrides entry for this skill already exists. If it does not exist, append the new entry under skill_overrides. Preserve all existing entries — only add the new one. If it already exists (duplicate), skip registration to prevent duplicate entries.
118
+ - If custom/skills/all-dev.customize.yaml already exists: read current content, check if a skill_overrides entry for this skill already exists. If it does not exist, append the new entry under skill_overrides. Preserve all existing entries — only add the new one. If it already exists (duplicate), skip registration to prevent duplicate entries.
119
119
  </action>
120
120
  <action>If no skill improvements identified, state: "No skill improvements identified this sprint."</action>
121
121
  </step>
@@ -45,6 +45,17 @@
45
45
  (file paths, component references, API endpoints, dependency versions).
46
46
  Verify against filesystem and ground truth (if available).
47
47
  Classify findings as CRITICAL (broken reference), WARNING (outdated), INFO (style).
48
+
49
+ (g) Origin Field Validation (optional fields — backward compatible):
50
+ The origin and origin_ref fields are OPTIONAL — stories without these fields
51
+ are valid (backward compatibility). Missing origin/origin_ref fields do NOT
52
+ cause errors and are accepted without warnings.
53
+ If the origin field IS present, validate:
54
+ - origin must be one of: "manual", "problem-solving", "triage", "add-feature",
55
+ "sprint-planning", or null. An invalid origin enum value is a CRITICAL finding.
56
+ - If origin is non-null, origin_ref must be non-empty (not null, not empty string).
57
+ A non-null origin with empty or null origin_ref is a WARNING finding.
58
+ If origin is null or absent, origin_ref is not validated (orphaned refs are acceptable).
48
59
  </action>
49
60
  </step>
50
61
  <step n="3" title="Validation Fix Loop">
@@ -124,23 +124,26 @@
124
124
  **Step 1 — Load all scan outputs:**
125
125
  Load gap entries from ALL of the following sources. For each file, if it exists, parse YAML gap entries matching the schema from gap-entry-schema.md. If a file is empty or missing, log a warning noting which scanner produced no results and continue processing the remaining files without error.
126
126
 
127
- Deep analysis scan outputs (7 files):
127
+ Deep analysis scan outputs (7 files — Step 2.5):
128
128
  - {planning_artifacts}/brownfield-scan-config-contradiction.md
129
129
  - {planning_artifacts}/brownfield-scan-dead-code.md
130
- - {planning_artifacts}/brownfield-scan-hard-coded-logic.md
131
- - {planning_artifacts}/brownfield-scan-security-endpoint.md
130
+ - {planning_artifacts}/brownfield-scan-hardcoded.md
131
+ - {planning_artifacts}/brownfield-scan-security.md
132
132
  - {planning_artifacts}/brownfield-scan-runtime-behavior.md
133
- - {planning_artifacts}/brownfield-scan-doc-code-drift.md
133
+ - {planning_artifacts}/brownfield-scan-doc-code.md
134
134
  - {planning_artifacts}/brownfield-scan-integration-seam.md
135
135
 
136
- Step 2 documentation subagent outputs:
136
+ Test execution scan output (1 file — Step 2.75):
137
+ - {planning_artifacts}/brownfield-scan-test-execution.md (failing tests as gap entries)
138
+
139
+ Step 2 documentation subagent outputs (4 files):
137
140
  - {planning_artifacts}/api-documentation.md (API gaps)
138
141
  - {planning_artifacts}/event-catalog.md (event/messaging gaps)
139
142
  - {planning_artifacts}/ux-design.md (frontend/UX gaps)
140
143
  - {planning_artifacts}/dependency-map.md (dependency gaps)
141
144
 
142
- Step 3 test execution results:
143
- - {test_artifacts}/nfr-assessment.md (test execution gap findings)
145
+ Step 3 NFR assessment:
146
+ - {test_artifacts}/nfr-assessment.md (NFR gap findings)
144
147
 
145
148
  **Step 2 — Validate entries against schema:**
146
149
  For each parsed gap entry, validate that all required fields are present: id, category, severity, title, description (or evidence), evidence_file, evidence_line, recommendation. Entries missing any required field are logged as warnings (noting the source file and which field is missing) and skipped from consolidation rather than causing a failure.
@@ -197,6 +200,7 @@
197
200
  — If infrastructure: use IR-### for infrastructure requirements, OR-### for operational requirements, and SR-### for security requirements exclusively. Do NOT use FR/NFR prefixes.
198
201
  — If platform: use BOTH ID scheme families — FR-###/NFR-### for application-layer requirements and IR-###/OR-###/SR-### for infrastructure-layer requirements. All requirement IDs are globally unique within the project — the prefix disambiguates (e.g., FR-001 and IR-001 are distinct, no collision).</action>
199
202
  <action>Read upstream artifacts to inform gap analysis:</action>
203
+ <action>— project-documentation.md → project context: tech stack, architecture patterns, conventions, detected capability flags, CI/CD summary. Use for PRD Overview section (existing project summary) and to ground gap requirements in the actual project structure.</action>
200
204
  <action>— consolidated-gaps.md → primary input: deduplicated, ranked, and code-verified gap list from Steps 3.5 and 5.5. If a '## Verification Corrections for PRD' section exists, use it to correct factual errors from contradicted claims.</action>
201
205
  <action>— nfr-assessment.md → NFR section gets real "Current Baseline" and "Target" columns</action>
202
206
  <action>— api-documentation.md (if exists) → extract API gaps (undocumented endpoints, missing validation)</action>
@@ -0,0 +1,8 @@
1
+ # Test Gap Analysis Checklist
2
+ - [ ] Execution mode determined (coverage or verification)
3
+ - [ ] Test plan scanned for test case IDs and story links
4
+ - [ ] Story files scanned for acceptance criteria
5
+ - [ ] Cross-reference completed — gaps identified
6
+ - [ ] Output follows FR-223 schema (summary count, per-story table, coverage %)
7
+ - [ ] Zero-gap case handled with "No coverage gaps detected" message
8
+ - [ ] Workflow completed within NFR-040 performance constraint (< 60 seconds)
@@ -0,0 +1,53 @@
1
+ <workflow name="test-gap-analysis">
2
+ <critical>
3
+ <mandate>Scan test-plan.md and story files to identify acceptance criteria gaps — NFR-040 requires completion in under 60 seconds</mandate>
4
+ <mandate>Output must follow the FR-223 schema: summary count, per-story gap table, coverage percentage</mandate>
5
+ <mandate>When no gaps are detected, output must state "No coverage gaps detected" with a summary count of zero</mandate>
6
+ </critical>
7
+
8
+ <step n="1" title="Determine Mode">
9
+ <action>Check the --mode argument: coverage or verification</action>
10
+ <action>If no mode specified, default to coverage mode</action>
11
+ <action>If mode is 'verification', skip to verification-mode steps (E19-S2 scope — not implemented yet)</action>
12
+ </step>
13
+
14
+ <step n="2" title="Scan Test Plan">
15
+ <action>Read {test_artifacts}/test-plan.md</action>
16
+ <action>Extract all test case IDs and their linked story keys from the test plan</action>
17
+ <action>Build a map of test_case_id -> [story_keys] for cross-referencing</action>
18
+ <action>If test-plan.md is missing, log warning: "test-plan.md not found — partial coverage analysis only" and continue with empty test case map</action>
19
+ </step>
20
+
21
+ <step n="3" title="Scan Story Files">
22
+ <action>Scan all story files in docs/implementation-artifacts/ matching pattern {story_key}-*.md</action>
23
+ <action>For each story file, extract all acceptance criteria (AC items) from the "Acceptance Criteria" section</action>
24
+ <action>Build a map of story_key -> [AC items] with their identifiers (AC1, AC2, etc.)</action>
25
+ <action>Track untested acceptance criteria — ACs that have no matching test case in the test plan map</action>
26
+ </step>
27
+
28
+ <step n="4" title="Cross-Reference and Identify Gaps">
29
+ <action>For each story's acceptance criteria, check if a corresponding test case exists in the test plan</action>
30
+ <action>Flag each AC as covered (has test case) or uncovered-ac (no test case found)</action>
31
+ <action>Calculate coverage rate per story: covered_ACs / total_ACs</action>
32
+ <action>Calculate overall coverage percentage across all stories</action>
33
+ </step>
34
+
35
+ <step n="5" title="Generate Output (FR-223 Schema)">
36
+ <action>Generate the output artifact at {test_artifacts}/test-gap-analysis-{date}.md</action>
37
+ <action>Output must include the following FR-223 schema sections:
38
+ - Summary section with total count of stories analyzed, ACs scanned, gaps found, and overall coverage percentage
39
+ - Per-story gap table listing each story, its ACs, and their coverage status
40
+ - Coverage rate breakdown showing covered vs uncovered acceptance criteria
41
+ </action>
42
+ <action>If zero gaps are detected (all ACs have corresponding test cases):
43
+ Output "No coverage gaps detected" in the summary section with a gap count of 0 and coverage rate of 100%</action>
44
+ <template-output file="{test_artifacts}/test-gap-analysis-{date}.md">
45
+ Gap analysis report following FR-223 schema with summary count, per-story gap table, and coverage percentage.
46
+ </template-output>
47
+ </step>
48
+
49
+ <step n="6" title="Performance Validation">
50
+ <action>Verify workflow completed within the NFR-040 constraint of under 60 seconds</action>
51
+ <action>Log total execution time in the output footer</action>
52
+ </step>
53
+ </workflow>
@@ -0,0 +1,38 @@
1
+ name: test-gap-analysis
2
+ description: 'Scan test suite against requirements to identify untested or under-tested areas'
3
+ module: testing
4
+ agent: test-architect
5
+ execution_mode: planning
6
+ modes:
7
+ - coverage
8
+ - verification
9
+ default_mode: coverage
10
+ config_resolved: "{installed_path}/.resolved/test-gap-analysis.yaml"
11
+ config_source: "{project-root}/_gaia/testing/config.yaml"
12
+ installed_path: "{project-root}/_gaia/testing/workflows/test-gap-analysis"
13
+ instructions: "{installed_path}/instructions.xml"
14
+ validation: "{installed_path}/checklist.md"
15
+ traces_to:
16
+ - FR-221
17
+ - FR-223
18
+ - NFR-040
19
+ performance_constraints:
20
+ max_duration_seconds: 60 # NFR-040 — workflow must complete in under 60 seconds
21
+ input_file_patterns:
22
+ test_plan:
23
+ whole: "{test_artifacts}/test-plan.md"
24
+ load_strategy: "FULL_LOAD"
25
+ story_files:
26
+ whole: "{implementation_artifacts}/*.md"
27
+ load_strategy: "INDEX_GUIDED"
28
+ architecture:
29
+ whole: "{planning_artifacts}/architecture.md"
30
+ load_strategy: "INDEX_GUIDED"
31
+ sprint_status:
32
+ whole: "{implementation_artifacts}/sprint-status.yaml"
33
+ load_strategy: "FULL_LOAD"
34
+ output:
35
+ primary: "{test_artifacts}/test-gap-analysis-{date}.md"
36
+ on_error:
37
+ missing_file: "warn_and_continue"
38
+ unresolved_variable: "halt"
@@ -158,6 +158,8 @@ Commands:
158
158
  status Show installation info
159
159
 
160
160
  Options:
161
+ --branch <name> Clone from a specific branch
162
+ --staging Shorthand for --branch staging
161
163
  --yes Skip confirmation prompts
162
164
  --dry-run Show what would be done without making changes
163
165
  --verbose Show detailed progress
@@ -207,6 +209,32 @@ function main(deps) {
207
209
  fail(`Unknown command: ${command}\n Run 'npx gaia-framework --help' for usage.`);
208
210
  }
209
211
 
212
+ // ─── Branch flag parsing (E14-S1) ─────────────────────────────────────────
213
+ // Extract --branch / --staging before building the passthrough array.
214
+ // These flags control which git branch is cloned — they are consumed by the
215
+ // JS CLI and forwarded as --branch <name> to gaia-install.sh.
216
+ let branchValue = null;
217
+ const remaining = args.slice(0);
218
+
219
+ const branchIdx = remaining.indexOf("--branch");
220
+ const hasStaging = remaining.includes("--staging");
221
+
222
+ if (branchIdx >= 0 && hasStaging) {
223
+ fail("Cannot use --branch and --staging together. Use --branch staging instead.");
224
+ }
225
+
226
+ if (branchIdx >= 0) {
227
+ const valueIdx = branchIdx + 1;
228
+ if (valueIdx >= remaining.length || remaining[valueIdx].startsWith("--")) {
229
+ fail("Missing value for --branch flag. Usage: --branch <name>");
230
+ }
231
+ branchValue = remaining[valueIdx];
232
+ remaining.splice(branchIdx, 2);
233
+ } else if (hasStaging) {
234
+ branchValue = "staging";
235
+ remaining.splice(remaining.indexOf("--staging"), 1);
236
+ }
237
+
210
238
  // Ensure git is available
211
239
  ensureGit();
212
240
 
@@ -237,8 +265,9 @@ function main(deps) {
237
265
 
238
266
  info("Cloning GAIA framework from GitHub...");
239
267
 
268
+ const branchCloneFlag = branchValue ? ` --branch ${branchValue}` : "";
240
269
  try {
241
- _exec(`git clone --depth 1 ${REPO_URL} "${tempDir}"`, {
270
+ _exec(`git clone --depth 1${branchCloneFlag} ${REPO_URL} "${tempDir}"`, {
242
271
  stdio: ["ignore", "ignore", "pipe"],
243
272
  });
244
273
  } catch (err) {
@@ -256,10 +285,15 @@ function main(deps) {
256
285
 
257
286
  // Build the shell command: inject --source pointing to the temp clone
258
287
  // so the shell script doesn't need to clone again
259
- const passthrough = args.slice(0);
288
+ const passthrough = remaining.slice(0);
260
289
  // Insert --source right after the command (convert to POSIX for bash on Windows)
261
290
  passthrough.splice(1, 0, "--source", toPosixPath(tempDir));
262
291
 
292
+ // Inject --branch flag for installer passthrough (E14-S1)
293
+ if (branchValue) {
294
+ passthrough.push("--branch", branchValue);
295
+ }
296
+
263
297
  // Locate bash (critical for Windows support)
264
298
  const bashPath = _findBash();
265
299
  if (!bashPath) {
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Derive bump label from PR title conventional commit prefix.
3
+ * Used by .github/workflows/pr-title-label.yml (E14-S11, ADR-025).
4
+ *
5
+ * @param {string} title - PR title
6
+ * @param {string} body - PR body
7
+ * @returns {{ label: string, type: string, breaking: boolean } | null}
8
+ * Returns the derived bump label info, or null if title doesn't match.
9
+ */
10
+
11
+ const TITLE_REGEX = /^(feat|fix|refactor|perf|test|docs|chore|ci|style)(\(.+\))?(!)?: .+$/;
12
+
13
+ const TYPE_TO_LABEL = Object.freeze({
14
+ feat: "bump:minor",
15
+ fix: "bump:patch",
16
+ perf: "bump:patch",
17
+ refactor: "bump:none",
18
+ test: "bump:none",
19
+ docs: "bump:none",
20
+ chore: "bump:none",
21
+ ci: "bump:none",
22
+ style: "bump:none",
23
+ });
24
+
25
+ function deriveBumpLabel(title, body) {
26
+ const match = title.match(TITLE_REGEX);
27
+ if (!match) return null;
28
+
29
+ const type = match[1];
30
+ const bang = match[3] === "!";
31
+ const bodyBreaking = typeof body === "string" && body.includes("BREAKING CHANGE");
32
+ const breaking = bang || bodyBreaking;
33
+
34
+ const label = breaking ? "bump:major" : TYPE_TO_LABEL[type];
35
+
36
+ return { label, type, breaking };
37
+ }
38
+
39
+ module.exports = deriveBumpLabel;
40
+ module.exports.TITLE_REGEX = TITLE_REGEX;
41
+ module.exports.TYPE_TO_LABEL = TYPE_TO_LABEL;
@@ -0,0 +1,38 @@
1
+ /**
2
+ * PR bump label validation for staging merge enforcement.
3
+ * Used by .github/workflows/label-check.yml (E14-S6, ADR-025).
4
+ */
5
+
6
+ const VALID_BUMP_LABELS = Object.freeze(["bump:major", "bump:minor", "bump:patch", "bump:none"]);
7
+
8
+ /**
9
+ * Validate that exactly one bump:* label is present on a PR.
10
+ *
11
+ * @param {string[]} labels - Array of label names from the PR
12
+ * @returns {{ pass: boolean, message: string }} Validation result
13
+ */
14
+ function validateBumpLabels(labels) {
15
+ const bumpLabels = labels.filter((label) => VALID_BUMP_LABELS.includes(label));
16
+
17
+ if (bumpLabels.length === 0) {
18
+ return {
19
+ pass: false,
20
+ message: `No bump label found. Add one of: ${VALID_BUMP_LABELS.join(", ")}`,
21
+ };
22
+ }
23
+
24
+ if (bumpLabels.length > 1) {
25
+ return {
26
+ pass: false,
27
+ message: `Multiple bump labels found: ${bumpLabels.join(", ")}. Exactly one required.`,
28
+ };
29
+ }
30
+
31
+ return {
32
+ pass: true,
33
+ message: `Valid bump label: ${bumpLabels[0]}`,
34
+ };
35
+ }
36
+
37
+ module.exports = validateBumpLabels;
38
+ module.exports.VALID_BUMP_LABELS = VALID_BUMP_LABELS;