diff --git a/default/skills/codereview/SKILL.md b/default/skills/codereview/SKILL.md index b4da7bd7..52efbbbf 100644 --- a/default/skills/codereview/SKILL.md +++ b/default/skills/codereview/SKILL.md @@ -3,6 +3,7 @@ name: ring:codereview description: | Gate 4 of development cycle - dispatches 8 specialized reviewers (code, business-logic, security, test, nil-safety, consequences, dead-code, performance) in parallel for comprehensive code review feedback. + Runs at TASK cadence — reviewers see cumulative diff, not per-subtask fragments. trigger: | - Gate 4 of development cycle @@ -30,15 +31,30 @@ related: input_schema: required: [] # All inputs optional for standalone usage optional: + - name: scope + type: string + enum: [task, subtask] + default: task + description: "Review scope granularity. Default 'task' — reviewers see the cumulative diff of all subtasks of a task. 'subtask' is only for standalone/legacy usage." + - name: task_id + type: string + description: "Task identifier (when scope=task). This is the task whose cumulative diff is under review." + - name: subtask_ids + type: array + items: string + description: "All subtask identifiers covered by this task-level review." + - name: cumulative_diff_range + type: object + description: "Cumulative diff range for the task: {base_sha, head_sha}. base_sha is HEAD before the first subtask, head_sha is HEAD after the last subtask." - name: unit_id type: string - description: "Task or subtask identifier (auto-generated if not provided)" + description: "Task or subtask identifier (auto-generated if not provided). When scope=task, this equals task_id." - name: base_sha type: string - description: "Git SHA before implementation (auto-detected via git merge-base HEAD main)" + description: "Git SHA before implementation (auto-detected via git merge-base HEAD main). When scope=task, equals cumulative_diff_range.base_sha." - name: head_sha type: string - description: "Git SHA after implementation (auto-detected via git rev-parse HEAD)" + description: "Git SHA after implementation (auto-detected via git rev-parse HEAD). When scope=task, equals cumulative_diff_range.head_sha." - name: implementation_summary type: string description: "Summary of what was implemented (auto-generated from git log if not provided)" @@ -494,6 +510,10 @@ NOTE: Input collection failures are NOT blockers. ## Step 3: Dispatch All 8 Reviewers in Parallel +> **Standards Source (Cache-First Pattern):** Reviewer prompts below instruct agents to load Ring standards. When invoked inside a dev-cycle, those standards are available via `state.cached_standards` (populated by dev-cycle Step 1.5). Each reviewer reads from cache when available and falls back to direct WebFetch (with a warning) only when invoked standalone. See `shared-patterns/standards-cache-protocol.md` for protocol details. +> +> NOTE: The reviewer agents themselves live in `*/agents/*-reviewer.md`. The cache-first pattern inside the dispatch prompts below is the source of truth for the SKILL layer. Full cache-aware loading in the agent definitions will be addressed in a separate stream. + **⛔ CRITICAL: All 8 reviewers MUST be dispatched in a SINGLE message with 8 Task calls.** ### Step 3 Mode Selection @@ -601,6 +621,21 @@ AFTER ALL SLICES COMPLETE: The following dispatch is used when `review_state.slicing.enabled == false` (unchanged from current flow): +**⛔ MANDATORY SCOPE HEADER — inject into every reviewer prompt below.** + +When `scope == "task"` (the default, set by `ring:dev-cycle` orchestrator), the orchestrator MUST inject the following block into each of the 8 reviewer prompts, immediately after the `## Code Review Request` / `## Business Logic Review Request` / etc. header: + +```markdown +**REVIEW SCOPE: TASK-LEVEL** +This review covers the CUMULATIVE diff of task {task_id}, which includes changes from +{N} subtasks: {subtask_ids}. Review the full task as an integrated unit; subtask +boundaries are implementation detail, not review boundaries. +``` + +Substitution: `{task_id}` = `task_id` input, `{N}` = `len(subtask_ids)`, `{subtask_ids}` = comma-separated `subtask_ids`. When `scope == "subtask"` (standalone/legacy), omit the block entirely. + +Additionally, when `scope == "task"`, each reviewer prompt's `**Base SHA:**` and `**Head SHA:**` MUST be populated from `cumulative_diff_range.base_sha` and `cumulative_diff_range.head_sha` respectively. + ```yaml # Task 1: Code Reviewer Task: @@ -608,7 +643,9 @@ Task: description: "Code review for [unit_id]" prompt: | ## Code Review Request - + + [INJECT REVIEW SCOPE: TASK-LEVEL block here when scope=task] + **Unit ID:** [unit_id] **Base SHA:** [base_sha] **Head SHA:** [head_sha] @@ -647,9 +684,19 @@ Task: ## ⛔ Ring Standards Verification (MANDATORY) - **WebFetch the relevant standards modules and verify the changed code against them.** + **Load the relevant standards modules using the cache-first pattern and verify the changed code against them.** - For Go projects, WebFetch these modules based on changed files: + ```yaml + For each required standards URL below: + IF state.cached_standards[url] exists: + → Read content from state.cached_standards[url].content + → Log: "Using cached standard: {url} (fetched {state.cached_standards[url].fetched_at})" + ELSE: + → WebFetch url (fallback — should not happen if orchestrator ran Step 1.5) + → Log warning: "Standard {url} was not pre-cached; fetched inline" + ``` + + For Go projects, load these modules based on changed files: Base URL: `https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/golang/` **Always load:** @@ -665,7 +712,7 @@ Task: - `security.md` (if auth/middleware/validation code changed) - `messaging.md` (if RabbitMQ/message queue code changed) - For TypeScript: WebFetch `typescript.md` + For TypeScript: load `typescript.md` via the same cache-first pattern **Check the changed code against ALL applicable sections.** Use the section index from `standards-coverage-table.md`. @@ -780,7 +827,19 @@ Task: ## ⛔ Ring Security Standards Verification (MANDATORY) - **WebFetch the security standards and verify changed code against them:** + **Load the security standards using the cache-first pattern and verify changed code against them:** + + ```yaml + For each required standards URL below: + IF state.cached_standards[url] exists: + → Read content from state.cached_standards[url].content + → Log: "Using cached standard: {url} (fetched {state.cached_standards[url].fetched_at})" + ELSE: + → WebFetch url (fallback — should not happen if orchestrator ran Step 1.5) + → Log warning: "Standard {url} was not pre-cached; fetched inline" + ``` + + Required URLs: - `https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/golang/security.md` **Check ALL applicable sections from standards-coverage-table.md → ring:backend-engineer-golang:** @@ -1087,9 +1146,19 @@ Task: ## ⛔ Ring Standards Verification (MANDATORY) - **WebFetch the relevant standards and verify the changed code against them.** + **Load the relevant standards using the cache-first pattern and verify the changed code against them.** - For Go projects, WebFetch these modules based on changed files: + ```yaml + For each required standards URL below: + IF state.cached_standards[url] exists: + → Read content from state.cached_standards[url].content + → Log: "Using cached standard: {url} (fetched {state.cached_standards[url].fetched_at})" + ELSE: + → WebFetch url (fallback — should not happen if orchestrator ran Step 1.5) + → Log warning: "Standard {url} was not pre-cached; fetched inline" + ``` + + For Go projects, load these modules based on changed files: Base URL: `https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/golang/` **Always load:** @@ -1097,8 +1166,8 @@ Task: - `core.md` (Dependency Management) - `bootstrap.md` (Connection Management, Graceful Shutdown) - For TypeScript: WebFetch `typescript.md` (Testing, Frameworks & Libraries) - For SRE/Infra (Layer 2): WebFetch `sre.md` (Health Checks, Observability) + For TypeScript: load `typescript.md` (Testing, Frameworks & Libraries) via the same cache-first pattern + For SRE/Infra (Layer 2): load `sre.md` (Health Checks, Observability) via the same cache-first pattern **Include a Standards Compliance section in your output** listing which standards were verified and any violations found. diff --git a/dev-team/skills/dev-chaos-testing/SKILL.md b/dev-team/skills/dev-chaos-testing/SKILL.md index 94985b9b..34064d64 100644 --- a/dev-team/skills/dev-chaos-testing/SKILL.md +++ b/dev-team/skills/dev-chaos-testing/SKILL.md @@ -3,6 +3,8 @@ name: ring:dev-chaos-testing description: | Gate 7 of development cycle - ensures chaos tests exist using Toxiproxy to verify graceful degradation under connection loss, latency, and partitions. + Runs at TASK cadence (after all subtasks complete Gate 0 + Gate 3 + Gate 9): + write mode runs per task, execute mode runs per cycle. trigger: | - After integration testing complete (Gate 6) @@ -31,7 +33,7 @@ input_schema: required: - name: unit_id type: string - description: "Task or subtask identifier" + description: "TASK identifier (not a subtask id). This skill's write mode runs at TASK cadence — unit_id is always a task id. Execute mode runs per cycle." - name: external_dependencies type: array items: string @@ -40,6 +42,13 @@ input_schema: type: string enum: [go, typescript] description: "Programming language" + - name: implementation_files + type: array + items: string + description: "Union of changed files across all subtasks of this task." + - name: gate0_handoffs + type: array + description: "Array of per-subtask implementation handoffs (one entry per subtask). NOT a single gate0_handoff object." optional: - name: gate6_handoff type: object @@ -111,9 +120,24 @@ Ensure code handles **failure conditions gracefully** by injecting faults using --- +## Standards Source (Cache-First Pattern) + +**Standards Source (Cache-First Pattern):** This sub-skill reads standards from `state.cached_standards` populated by dev-cycle Step 1.5. If invoked outside a cycle (standalone), it falls back to direct WebFetch with a warning. See `shared-patterns/standards-cache-protocol.md` for protocol details. + ## Standards Reference -**MANDATORY:** Load testing-chaos.md standards via WebFetch. +**MANDATORY:** Load testing-chaos.md standards via the cache-first pattern below. + +URL: https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/golang/testing-chaos.md + +**Cache-first loading protocol:** +For each required standards URL: + IF state.cached_standards[url] exists: + → Read content from state.cached_standards[url].content + → Log: "Using cached standard: {url} (fetched {state.cached_standards[url].fetched_at})" + ELSE: + → WebFetch url (fallback — should not happen if orchestrator ran Step 1.5) + → Log warning: "Standard {url} was not pre-cached; fetched inline" https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/golang/testing-chaos.md @@ -173,9 +197,11 @@ PM team task files often omit external_dependencies. If the codebase uses postgr ```text REQUIRED INPUT: -- unit_id: [task/subtask being tested] +- unit_id: [TASK id — write mode runs at task cadence, not per subtask] - external_dependencies: [postgres, mongodb, valkey, redis, rabbitmq, etc.] (from input OR auto-detected in Step 0) - language: [go|typescript] +- implementation_files: [union of changed files across all subtasks of this task] +- gate0_handoffs: [array of per-subtask Gate 0 handoffs — one entry per subtask] OPTIONAL INPUT: - gate6_handoff: [full Gate 6 output] diff --git a/dev-team/skills/dev-cycle-frontend/SKILL.md b/dev-team/skills/dev-cycle-frontend/SKILL.md index 54119f4b..a41e138e 100644 --- a/dev-team/skills/dev-cycle-frontend/SKILL.md +++ b/dev-team/skills/dev-cycle-frontend/SKILL.md @@ -178,6 +178,42 @@ Store result in state file under `ui_library_mode`. --- +## Step 1.5: Standards Pre-Cache (MANDATORY) + +Cache all standards URLs the cycle will need, ONCE, into `state.cached_standards`. +Sub-skills read from this cache instead of calling WebFetch themselves. + +**Required URLs to pre-fetch (MUST succeed all):** + +1. `https://raw.githubusercontent.com/LerianStudio/ring/main/CLAUDE.md` +2. `https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/frontend.md` +3. `https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/frontend/testing-accessibility.md` +4. `https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/frontend/testing-visual.md` +5. `https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/frontend/testing-e2e.md` +6. `https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/frontend/testing-performance.md` +7. `https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/devops.md` +8. `https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/sre.md` +9. `https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/typescript.md` (if BFF layer detected) + +**Protocol:** + +```text +For each URL in the required list: + WebFetch: [URL] + Write to state.cached_standards[URL] = { + "fetched_at": current_iso_timestamp, + "content": + } +``` + +**MANDATORY:** Save state to file after cache populated — Write tool → [state.state_path] + +**Blocker:** If ANY URL fails to fetch, STOP cycle and report. Cache MUST be complete. Sub-skills downstream rely on `state.cached_standards` being populated; a partial cache causes WebFetch fallback warnings and defeats the purpose of pre-caching. + +**Rationale:** Before this step existed, every sub-skill dispatch triggered its own WebFetch of the same standards. The 5-minute prompt cache TTL is regularly exceeded, producing 15–25+ redundant network fetches per cycle. A single pre-cache at cycle start reduces that to one fetch per unique URL. + +--- + ## Backend Handoff Loading (Optional) If the frontend cycle follows a backend `ring:dev-cycle`, load the handoff file: @@ -387,17 +423,19 @@ No negotiation. No exceptions. No "special cases". ## The 9 Gates -| Gate | Skill | Purpose | Agent | Standards Module | -|------|-------|---------|-------|------------------| -| 0 | ring:dev-implementation | Write code following TDD | ring:frontend-engineer / ring:ui-engineer / ring:frontend-bff-engineer-typescript | frontend.md | -| 1 | ring:dev-devops | Docker/compose/Nginx setup | ring:devops-engineer | devops.md | -| 2 | ring:dev-frontend-accessibility | WCAG 2.1 AA compliance | ring:qa-analyst-frontend (test_mode: accessibility) | testing-accessibility.md | -| 3 | ring:dev-unit-testing | Unit tests 85%+ coverage | ring:qa-analyst-frontend (test_mode: unit) | frontend.md | -| 4 | ring:dev-frontend-visual | Snapshot/visual regression tests | ring:qa-analyst-frontend (test_mode: visual) | testing-visual.md | -| 5 | ring:dev-frontend-e2e | E2E tests with Playwright | ring:qa-analyst-frontend (test_mode: e2e) | testing-e2e.md | -| 6 | ring:dev-frontend-performance | Core Web Vitals + Lighthouse | ring:qa-analyst-frontend (test_mode: performance) | testing-performance.md | -| 7 | ring:codereview | Parallel code review (5 reviewers) | ring:code-reviewer, ring:business-logic-reviewer, ring:security-reviewer, ring:test-reviewer, ring:frontend-engineer (review mode) | N/A | -| 8 | ring:dev-validation | Final acceptance validation | N/A (verification) | N/A | +| Gate | Cadence | Skill | Purpose | Agent | Standards Module | +|------|---------|-------|---------|-------|------------------| +| 0 | subtask | ring:dev-implementation | Write code following TDD | ring:frontend-engineer / ring:ui-engineer / ring:frontend-bff-engineer-typescript | frontend.md | +| 1 | task | ring:dev-devops | Docker/compose/Nginx setup | ring:devops-engineer | devops.md | +| 2 | task | ring:dev-frontend-accessibility | WCAG 2.1 AA compliance | ring:qa-analyst-frontend (test_mode: accessibility) | testing-accessibility.md | +| 3 | subtask | ring:dev-unit-testing | Unit tests 85%+ coverage | ring:qa-analyst-frontend (test_mode: unit) | frontend.md | +| 4 | task | ring:dev-frontend-visual | Snapshot/visual regression tests | ring:qa-analyst-frontend (test_mode: visual) | testing-visual.md | +| 5 | task | ring:dev-frontend-e2e | E2E tests with Playwright | ring:qa-analyst-frontend (test_mode: e2e) | testing-e2e.md | +| 6 | task | ring:dev-frontend-performance | Core Web Vitals + Lighthouse | ring:qa-analyst-frontend (test_mode: performance) | testing-performance.md | +| 7 | task | ring:codereview | Parallel code review (5 reviewers, cumulative task diff) | ring:code-reviewer, ring:business-logic-reviewer, ring:security-reviewer, ring:test-reviewer, ring:frontend-engineer (review mode) | N/A | +| 8 | subtask | ring:dev-validation | Final acceptance validation | N/A (verification) | N/A | + +**Cadence column:** `subtask` = runs once per subtask (execution unit). `task` = runs ONCE per task, after all subtasks complete their Gate 0/3/8. **All gates are MANDATORY. No exceptions. No skip reasons.** @@ -474,19 +512,21 @@ Task 5: { subagent_type: "ring:frontend-engineer", prompt: "REVIEW MODE: Review **A gate is COMPLETE only when all components finish successfully:** -| Gate | Components Required | Partial = FAIL | -|------|---------------------|----------------| -| 0.1 | TDD-RED: Failing test written + failure output captured (behavioral components only - see [Frontend TDD Policy](#gate-0-frontend-tdd-policy)) | Test exists but no failure output = FAIL. Visual-only components skip to 0.2 | -| 0.2 | TDD-GREEN: Implementation passes test (behavioral) OR implementation complete (visual) | Code exists but test fails = FAIL | -| 0 | Both 0.1 and 0.2 complete (behavioral) OR 0.2 complete (visual - snapshots deferred to Gate 4) | 0.1 done without 0.2 = FAIL | -| 1 | Dockerfile + docker-compose/nginx + .env.example | Missing any = FAIL | -| 2 | 0 WCAG AA violations + keyboard navigation tested + screen reader tested | Any violation = FAIL | -| 3 | Unit test coverage >= 85% + all AC tested | 84% = FAIL | -| 4 | All state snapshots pass + responsive breakpoints covered | Missing snapshots = FAIL | -| 5 | All user flows tested + cross-browser (Chromium, Firefox, WebKit) + 3x stable pass | Flaky = FAIL | -| 6 | LCP < 2.5s + CLS < 0.1 + INP < 200ms + Lighthouse >= 90 | Any threshold missed = FAIL | -| 7 | All 5 reviewers PASS | 4/5 reviewers = FAIL | -| 8 | Explicit "APPROVED" from user | "Looks good" = not approved | +| Gate | Cadence | Components Required | Partial = FAIL | +|------|---------|---------------------|----------------| +| 0.1 | subtask | TDD-RED: Failing test written + failure output captured (behavioral components only - see [Frontend TDD Policy](#gate-0-frontend-tdd-policy)) | Test exists but no failure output = FAIL. Visual-only components skip to 0.2 | +| 0.2 | subtask | TDD-GREEN: Implementation passes test (behavioral) OR implementation complete (visual) | Code exists but test fails = FAIL | +| 0 | subtask | Both 0.1 and 0.2 complete (behavioral) OR 0.2 complete (visual - snapshots deferred to Gate 4) | 0.1 done without 0.2 = FAIL | +| 1 | task | Dockerfile + docker-compose/nginx + .env.example (produced once per task) | Missing any = FAIL | +| 2 | task | 0 WCAG AA violations + keyboard navigation tested + screen reader tested (on cumulative task diff) | Any violation = FAIL | +| 3 | subtask | Unit test coverage >= 85% + all AC tested (per subtask) | 84% = FAIL | +| 4 | task | All state snapshots pass + responsive breakpoints covered (cumulative task components) | Missing snapshots = FAIL | +| 5 | task | All user flows tested + cross-browser (Chromium, Firefox, WebKit) + 3x stable pass (task-level flows) | Flaky = FAIL | +| 6 | task | LCP < 2.5s + CLS < 0.1 + INP < 200ms + Lighthouse >= 90 (task-level measurement) | Any threshold missed = FAIL | +| 7 | task | All 5 reviewers PASS on cumulative task diff | 4/5 reviewers = FAIL | +| 8 | subtask | Explicit "APPROVED" from user (per subtask) | "Looks good" = not approved | + +**Cadence column:** `subtask` = runs per subtask. `task` = runs ONCE per task on the UNION of all subtasks' changed files. All quality thresholds (WCAG AA, 85% coverage, CWV, Lighthouse ≥ 90) remain unchanged — only the execution frequency changes. **CRITICAL for Gate 7:** Running 4 of 5 reviewers is not a partial pass - it's a FAIL. Re-run all 5 reviewers. @@ -527,14 +567,55 @@ Task 5: { subagent_type: "ring:frontend-engineer", prompt: "REVIEW MODE: Review ## Execution Order -**Core Principle:** Each execution unit passes through all 9 gates. All gates execute and complete per unit. +**Core Principle:** Each task passes through all 9 gates. Gates 0, 3, 8 execute per subtask (execution unit). Gates 1, 2, 4, 5, 6, 7 execute ONCE per task after all subtasks complete their subtask-level gates. -**Per-Unit Flow:** Unit -> Gate 0->1->2->3->4->5->6->7->8 -> Unit Checkpoint -> Task Checkpoint -> Next Unit +**Per-Task Flow:** +``` +Task → (for each subtask: Gate 0 → Gate 3 → Gate 8) + → Gate 1 → Gate 2 → Gate 4 → Gate 5 → Gate 6 → Gate 7 + → Task-level visual report → Task Checkpoint → Next Task +``` -| Scenario | Execution Unit | Gates Per Unit | -|----------|----------------|----------------| -| Task without subtasks | Task itself | 9 gates | -| Task with subtasks | Each subtask | 9 gates per subtask | +| Scenario | Execution Unit | Subtask-level Gates | Task-level Gates | +|----------|----------------|---------------------|------------------| +| Task without subtasks | Task itself (treated as single subtask) | 0, 3, 8 | 1, 2, 4, 5, 6, 7 | +| Task with subtasks | Each subtask | 0, 3, 8 (per subtask) | 1, 2, 4, 5, 6, 7 (once per task) | + +## Execution Loop Structure (the "Prancy Bentley" cadence model) + +```yaml +for each task in state.tasks: + # ===== SUBTASK-LEVEL GATES ===== + for each subtask in task.subtasks: + Execute Gate 0 (Implementation) + Execute Gate 3 (Unit Testing) + Execute Gate 8 (Validation) + [per-subtask visual report — OPT-IN only via state.visual_report_granularity] + end for + + # ===== TASK-LEVEL GATES ===== + # Input aggregation: implementation_files = UNION across subtasks + Execute Gate 1 (DevOps) + Execute Gate 2 (Accessibility) + Execute Gate 4 (Visual) + Execute Gate 5 (E2E) + Execute Gate 6 (Performance) + Execute Gate 7 (Review — 5 parallel reviewers on cumulative task diff) + + Generate task-level visual report + Accumulate metrics into state.tasks[i].accumulated_metrics + [task checkpoint] +end for + +# Cycle-level (minimal for frontend) +Final Commit +``` + +**Key properties:** +- Subtask-level gates (0, 3, 8) establish working, tested, validated code per subtask. +- Task-level gates (1, 2, 4, 5, 6, 7) run on the UNION of all subtasks' changed files — one pass per task, not N passes. +- Reviewers at Gate 7 see the cumulative task diff, so cross-subtask interaction bugs become MORE visible, not less. +- Per-subtask visual reports are opt-in; the default task-level aggregate report covers all subtasks' diffs. ## Commit Timing @@ -586,7 +667,7 @@ State is persisted to `docs/ring:dev-cycle-frontend/current-cycle.json`: ```json { - "version": "1.0.0", + "version": "1.1.0", "cycle_id": "uuid", "started_at": "ISO timestamp", "updated_at": "ISO timestamp", @@ -594,6 +675,10 @@ State is persisted to `docs/ring:dev-cycle-frontend/current-cycle.json`: "state_path": "docs/ring:dev-cycle-frontend/current-cycle.json", "cycle_type": "frontend", "ui_library_mode": "sindarian-ui | fallback-only", + "_comment_cached_standards": "Populated by Step 1.5 (Standards Pre-Cache). Dictionary of URL → {fetched_at, content}. Sub-skills MUST read from here instead of calling WebFetch. See plan Section 3.1.", + "cached_standards": {}, + "_comment_visual_report_granularity": "Default 'task' (generate visual report once per task). Opt-in 'subtask' to generate per-subtask reports. See plan Section 3.3.", + "visual_report_granularity": "task", "backend_handoff": { "loaded": true, "source": "docs/ring:dev-cycle/handoff-frontend.json", @@ -625,9 +710,16 @@ State is persisted to `docs/ring:dev-cycle-frontend/current-cycle.json`: { "id": "ST-001-01", "file": "subtasks/T-001/ST-001-01.md", - "status": "pending|completed" + "status": "pending|completed", + "_comment_subtask_gate_progress": "Per-subtask tracking of subtask-level gates (0, 3, 8). Added in plan Section 3 / Edit 4.2.4. Task-level gates (1,2,4,5,6,7) live on state.tasks[i].gate_progress instead.", + "gate_progress": { + "implementation": {"status": "pending|completed"}, + "unit_testing": {"status": "pending|completed", "coverage_actual": 0.0}, + "validation": {"status": "pending|completed", "result": "approved|rejected"} + } } ], + "_comment_task_gate_progress": "Task-level gates (1, 2, 4, 5, 6, 7) run ONCE per task on the UNION of all subtasks' changed files. Subtask-level gates (0, 3, 8) live on state.tasks[i].subtasks[j].gate_progress.", "gate_progress": { "implementation": { "status": "pending|in_progress|completed", @@ -798,7 +890,15 @@ State is persisted to `docs/ring:dev-cycle-frontend/current-cycle.json`: "result": "approved|rejected", "timestamp": "ISO timestamp" } - } + }, + "_comment_accumulated_metrics": "Task-level rollup of gate metrics. Populated after the task-level gates complete. Cycle-end dev-report reads accumulated_metrics from all tasks. See plan Section 3 / Edit 4.2.4.", + "accumulated_metrics": { + "gate_durations_ms": {}, + "review_iterations": 0, + "testing_iterations": 0, + "issues_by_severity": {"CRITICAL": 0, "HIGH": 0, "MEDIUM": 0, "LOW": 0} + }, + "feedback_loop_completed": false } ], "metrics": { @@ -848,11 +948,6 @@ state.updated_at = "[ISO timestamp]" Write tool: file_path: "docs/ring:dev-cycle-frontend/current-cycle.json" content: [full JSON state] - -# Step 3: Verify persistence (MANDATORY - use Read tool) -Read tool: - file_path: "docs/ring:dev-cycle-frontend/current-cycle.json" -# Confirm current_gate and gate_progress match expected values ``` ### State Persistence Checkpoints @@ -900,22 +995,12 @@ Read tool: **Unit Checkpoint (after subtask completes Gate 8):** -**VISUAL CHANGE REPORT (MANDATORY - before checkpoint question):** -- MANDATORY: Invoke `Skill("ring:visualize")` to generate a code-diff HTML report for this execution unit -- Read `default/skills/visualize/templates/code-diff.html` to absorb the patterns before generating -- Content sourced from state JSON `agent_outputs` for the current unit: - * **TDD Output:** `tdd_red` (failing test) + `tdd_green` (implementation) - * **Files Changed:** Per-file before/after diff panels using `git diff` data from the implementation (do not read source files directly — use diff output provided by the implementation agent) - * **Frontend-Specific Metrics:** WCAG violations resolved (Gate 2), visual snapshot pass rate (Gate 4), LCP/CLS/INP values (Gate 6), Lighthouse score (Gate 6) - * **Review Verdicts:** Summary of all 5 reviewer verdicts from Gate 7 -- Save to: `docs/ring:dev-cycle-frontend/reports/unit-{unit_id}-report.html` -- Open in browser: - ```text - macOS: open docs/ring:dev-cycle-frontend/reports/unit-{unit_id}-report.html - Linux: xdg-open docs/ring:dev-cycle-frontend/reports/unit-{unit_id}-report.html - ``` -- Tell the user the file path -- See [shared-patterns/anti-rationalization-visual-report.md](../shared-patterns/anti-rationalization-visual-report.md) for anti-rationalization table +**VISUAL CHANGE REPORT (subtask-level — OPT-IN ONLY):** +- Default: SKIP per-subtask visual report. Task-level aggregate report is generated at the Task Checkpoint below. +- Opt-in: If `state.visual_report_granularity == "subtask"`, generate per-subtask report + as previously documented. Default value is "task". +- Rationale: Task-level aggregate covers all subtasks' diffs; per-subtask reports are + rarely consumed and cost one visualize dispatch each. ```text Subtask {id} complete. All 9 gates passed. @@ -1025,24 +1110,68 @@ Check: Does docs/PROJECT_RULES.md exist? --- -## Step 2-10: Gate Execution (Per Unit) +## Step 2-10: Gate Execution -### Step 2: Gate 0 - Implementation +**See [Execution Loop Structure](#execution-loop-structure-the-prancy-bentley-cadence-model) below for the full subtask/task cadence model.** Step headings below indicate cadence explicitly. + +### Step 2: Gate 0 - Implementation (Per Execution Unit) + +**Cadence:** Runs once per subtask (execution unit = subtask, or task-itself if no subtasks). **REQUIRED SUB-SKILL:** `Skill("ring:dev-implementation")` Dispatch appropriate frontend agent based on task type. Agent follows TDD (RED then GREEN) with frontend.md standards. -### Step 3: Gate 1 - DevOps +### Step 3: Gate 1 - DevOps (Per Task — after all subtasks complete 0/3/8) + +⛔ CADENCE: This gate runs ONCE per task, NOT per subtask. +Input `implementation_files` is the UNION of all subtasks' changed files. **REQUIRED SUB-SKILL:** `Skill("ring:dev-devops")` +**Prepare Input (task-level aggregation):** + +```yaml +devops_input = { + unit_id: state.tasks[current_task_index].id, # TASK id + implementation_files: [ + ...flatten(state.tasks[current_task_index].subtasks.map(st => + st.gate_progress.implementation.files_changed + )) + ], + gate0_handoffs: state.tasks[current_task_index].subtasks.map(st => + st.gate_progress.implementation + ), + # preserve other fields (language, service_type, ui_library_mode, etc.) +} +``` + Dispatch `ring:devops-engineer` for Dockerfile, docker-compose, Nginx configuration, and .env.example. -### Step 4: Gate 2 - Accessibility +### Step 4: Gate 2 - Accessibility (Per Task) + +⛔ CADENCE: This gate runs ONCE per task, NOT per subtask. +Input `implementation_files` is the UNION of all subtasks' changed files. **REQUIRED SUB-SKILL:** `Skill("ring:dev-frontend-accessibility")` +**Prepare Input (task-level aggregation):** + +```yaml +accessibility_input = { + unit_id: state.tasks[current_task_index].id, # TASK id + implementation_files: [ + ...flatten(state.tasks[current_task_index].subtasks.map(st => + st.gate_progress.implementation.files_changed + )) + ], + gate0_handoffs: state.tasks[current_task_index].subtasks.map(st => + st.gate_progress.implementation + ), + # preserve other fields +} +``` + Dispatch `ring:qa-analyst-frontend` with `test_mode="accessibility"`. MUST verify: - 0 WCAG 2.1 AA violations (axe-core scan) - Keyboard navigation works for all interactive elements @@ -1050,7 +1179,9 @@ Dispatch `ring:qa-analyst-frontend` with `test_mode="accessibility"`. MUST verif - Focus management is proper - Color contrast ratios meet AA thresholds -### Step 5: Gate 3 - Unit Testing +### Step 5: Gate 3 - Unit Testing (Per Execution Unit) + +**Cadence:** Runs once per subtask (unchanged). Coverage threshold (85%) applies per subtask. **REQUIRED SUB-SKILL:** `Skill("ring:dev-unit-testing")` @@ -1060,30 +1191,90 @@ Dispatch `ring:qa-analyst-frontend` with `test_mode="unit"`. MUST verify: - Component rendering, state management, and event handlers tested - Edge cases covered (empty states, error states, loading states) -### Step 6: Gate 4 - Visual Testing +### Step 6: Gate 4 - Visual Testing (Per Task) + +⛔ CADENCE: This gate runs ONCE per task, NOT per subtask. +Input `implementation_files` is the UNION of all subtasks' changed files. **REQUIRED SUB-SKILL:** `Skill("ring:dev-frontend-visual")` +**Prepare Input (task-level aggregation):** + +```yaml +visual_input = { + unit_id: state.tasks[current_task_index].id, # TASK id + implementation_files: [ + ...flatten(state.tasks[current_task_index].subtasks.map(st => + st.gate_progress.implementation.files_changed + )) + ], + gate0_handoffs: state.tasks[current_task_index].subtasks.map(st => + st.gate_progress.implementation + ), + # preserve other fields +} +``` + Dispatch `ring:qa-analyst-frontend` with `test_mode="visual"`. MUST verify: - All component states have snapshots (default, hover, active, disabled, error, loading) - Responsive breakpoints covered (mobile, tablet, desktop) - Design system compliance verified - Visual regression baseline established -### Step 7: Gate 5 - E2E Testing +### Step 7: Gate 5 - E2E Testing (Per Task) + +⛔ CADENCE: This gate runs ONCE per task, NOT per subtask. +Input `implementation_files` is the UNION of all subtasks' changed files. **REQUIRED SUB-SKILL:** `Skill("ring:dev-frontend-e2e")` +**Prepare Input (task-level aggregation):** + +```yaml +e2e_input = { + unit_id: state.tasks[current_task_index].id, # TASK id + implementation_files: [ + ...flatten(state.tasks[current_task_index].subtasks.map(st => + st.gate_progress.implementation.files_changed + )) + ], + gate0_handoffs: state.tasks[current_task_index].subtasks.map(st => + st.gate_progress.implementation + ), + # preserve other fields +} +``` + Dispatch `ring:qa-analyst-frontend` with `test_mode="e2e"`. MUST verify: - All user flows tested end-to-end - Cross-browser: Chromium, Firefox, WebKit - 3x consecutive stable pass (no flakiness) - Page object pattern used for maintainability -### Step 8: Gate 6 - Performance Testing +### Step 8: Gate 6 - Performance Testing (Per Task) + +⛔ CADENCE: This gate runs ONCE per task, NOT per subtask. +Input `implementation_files` is the UNION of all subtasks' changed files. **REQUIRED SUB-SKILL:** `Skill("ring:dev-frontend-performance")` +**Prepare Input (task-level aggregation):** + +```yaml +performance_input = { + unit_id: state.tasks[current_task_index].id, # TASK id + implementation_files: [ + ...flatten(state.tasks[current_task_index].subtasks.map(st => + st.gate_progress.implementation.files_changed + )) + ], + gate0_handoffs: state.tasks[current_task_index].subtasks.map(st => + st.gate_progress.implementation + ), + # preserve other fields +} +``` + Dispatch `ring:qa-analyst-frontend` with `test_mode="performance"`. MUST verify: - LCP (Largest Contentful Paint) < 2.5s - CLS (Cumulative Layout Shift) < 0.1 @@ -1091,13 +1282,36 @@ Dispatch `ring:qa-analyst-frontend` with `test_mode="performance"`. MUST verify: - Lighthouse Performance score >= 90 - Bundle size within budget (if defined in PROJECT_RULES.md) -### Step 9: Gate 7 - Code Review +### Step 9: Gate 7 - Code Review (Per Task) + +⛔ CADENCE: This gate runs ONCE per task, NOT per subtask. +Input `implementation_files` is the UNION of all subtasks' changed files. +**Reviewers see CUMULATIVE diff of all subtasks; cross-subtask bugs more visible.** **REQUIRED SUB-SKILL:** `Skill("ring:codereview")` +**Prepare Input (task-level aggregation):** + +```yaml +review_input = { + unit_id: state.tasks[current_task_index].id, # TASK id + implementation_files: [ + ...flatten(state.tasks[current_task_index].subtasks.map(st => + st.gate_progress.implementation.files_changed + )) + ], + gate0_handoffs: state.tasks[current_task_index].subtasks.map(st => + st.gate_progress.implementation + ), + # preserve other fields +} +``` + Dispatch all 5 reviewers in parallel (see Gate 7: Code Review Adaptation above). -### Step 10: Gate 8 - Validation +### Step 10: Gate 8 - Validation (Per Execution Unit) + +**Cadence:** Runs once per subtask (unchanged). User approval is per subtask. **REQUIRED SUB-SKILL:** `Skill("ring:dev-validation")` diff --git a/dev-team/skills/dev-cycle/SKILL.md b/dev-team/skills/dev-cycle/SKILL.md index 4eb6a265..dd3fb9c7 100644 --- a/dev-team/skills/dev-cycle/SKILL.md +++ b/dev-team/skills/dev-cycle/SKILL.md @@ -159,8 +159,7 @@ This is not negotiable: **Before dispatching any agent, you MUST load the corresponding sub-skill first.** -- Gate 0: `Skill("ring:dev-implementation")` → then `Task(subagent_type="ring:backend-engineer-*", ...)` -- Gate 0.5: `Skill("ring:dev-delivery-verification")` → Verify all requirements are DELIVERED (not just created). Catches dead code, unwired structs, unregistered middleware. Also runs 7 automated checks: (A) file size ≤300 lines, (B) license headers, (C) linting, (D) migration safety, (E) vulnerability scanning, (F) API backward compatibility, (G) multi-tenant dual-mode. FAIL → return to Gate 0 with explicit fix instructions. +- Gate 0: `Skill("ring:dev-implementation")` → then `Task(subagent_type="ring:backend-engineer-*", ...)`. **Gate 0 includes delivery verification exit check inline** (formerly Gate 0.5 — now a sub-check of ring:dev-implementation Step 7): verifies all requirements are DELIVERED (not just created), catches dead code, unwired structs, unregistered middleware, and runs 7 automated checks: (A) file size ≤300 lines, (B) license headers, (C) linting, (D) migration safety, (E) vulnerability scanning, (F) API backward compatibility, (G) multi-tenant dual-mode. FAIL → ring:dev-implementation re-iterates with fix instructions. - Gate 1: `Skill("ring:dev-devops")` → then `Task(subagent_type="ring:devops-engineer", ...)` - Gate 2: `Skill("ring:dev-sre")` → then `Task(subagent_type="ring:sre", ...)` - Gate 3: `Skill("ring:dev-unit-testing")` → then `Task(subagent_type="ring:qa-analyst", test_mode="unit", ...)` @@ -360,6 +359,8 @@ See [shared-patterns/shared-anti-rationalization.md](../shared-patterns/shared-a | "Defense in depth exists (frontend validates)" | Frontend can be bypassed. Backend is the last line. Fix at source. | | "Backlog the Medium issue, it's documented" | Documented risk ≠ mitigated risk. Medium in Gate 4 = fix NOW, not later. | | "Risk-based prioritization allows deferral" | Gates ARE the risk-based system. Reviewers define severity, not you. | +| "I'll WebFetch standards again for this gate" | Standards are pre-cached at Step 1.5 in `state.cached_standards`. Read from state, do not re-fetch. | +| "Task-level Gate 8 misses bugs from subtask 2" | Cumulative task diff shows ALL subtasks' changes. Cross-subtask interactions are MORE visible, not less. | --- @@ -398,7 +399,7 @@ Day 4: Production incident from Day 1 code |------|---------------------|----------------| | 0.1 | TDD-RED: Failing test written + failure output captured | Test exists but no failure output = FAIL | | 0.2 | TDD-GREEN: Implementation passes test | Code exists but test fails = FAIL | -| 0 | Both 0.1 and 0.2 complete | 0.1 done without 0.2 = FAIL | +| 0 | Both 0.1 and 0.2 complete + Delivery verification: all requirements delivered, 0 dead code items | 0.1 done without 0.2 = FAIL; missing/dead code = FAIL | | 1 | Dockerfile + docker-compose + .env.example | Missing any = FAIL | | 2 | Structured JSON logs with trace correlation | Partial structured logs = FAIL | | 3 | Unit test coverage ≥ 85% + all AC tested | 84% = FAIL | @@ -426,14 +427,38 @@ Day 4: Production incident from Day 1 code ## Gate Order Enforcement (HARD GATE) -**Gates MUST execute in order: 0 → 0.5 → 1 → 2 → 3 → 4 → 5 → 6(write) → 7(write) → 8 → 9. All 11 gates are MANDATORY.** +**Gates MUST execute in this order within each task:** + +1. **Subtask loop** (per subtask OR per task-itself if no subtasks): + - Gate 0 (Implementation — INCLUDES delivery verification exit check inline) + - Gate 3 (Unit Testing) + - Gate 9 (Validation) + +2. **After all subtasks complete their subtask-level gates — task-level gates** (once per task): + - Gate 1 (DevOps) + - Gate 2 (SRE) + - Gate 4 (Fuzz) + - Gate 5 (Property) + - Gate 6 (Integration — write mode) + - Gate 7 (Chaos — write mode) + - Gate 8 (Review — 8 reviewers) + +3. **End of cycle** (once per cycle): + - Gate 6 (Integration — execute mode) + - Gate 7 (Chaos — execute mode) + - Multi-Tenant Verify + - dev-report (aggregate) + - Final Commit **Deferred Execution Model for Gates 6-7:** -- **Per unit:** Write/update test code + verify compilation (no container execution) -- **End of cycle:** Execute all integration and chaos tests (containers spun up once), then verify multi-tenant dual-mode compliance (already implemented at Gate 0, verified at Gate 0.5G) +- **Write mode (task-level):** Write/update test code + verify compilation (no container execution) +- **Execute mode (end of cycle):** Execute all integration and chaos tests (containers spun up once), then verify multi-tenant dual-mode compliance (already implemented at Gate 0, verified at Gate 0.5G) | Violation | Why It's WRONG | Consequence | |-----------|----------------|-------------| +| Dispatching Gate 1 during subtask loop | Gate 1 is task-level; MUST wait until all subtasks done | DevOps validated N times instead of once | +| Dispatching Gate 2/4/5/6(write)/7(write)/8 during subtask loop | These are task-cadence; MUST wait until ALL subtasks of the current task complete Gate 0 + Gate 3 + Gate 9 | Redundant reviewer/QA runs; broken input aggregation (missing UNION of files) | +| Dispatching Gate 0.5 as separate gate | Gate 0.5 was REMOVED; delivery verification runs inline as Gate 0 exit criteria | Duplicate dispatch; broken gate accounting | | Skip Gate 1 (DevOps) | "No infra changes" | Code without container = works on my machine only | | Skip Gate 2 (SRE) | "Observability later" | Blind production = debugging nightmare | | Skip Gate 4 (Fuzz) | "Unit tests are enough" | Edge cases and crashes not discovered | @@ -445,7 +470,7 @@ Day 4: Production incident from Day 1 code **All testing gates (3-7) are MANDATORY. No exceptions. No skip reasons.** -**Gates are not parallelizable across different gates. Sequential execution is MANDATORY.** +**Gates are not parallelizable across different gates. Sequential execution is MANDATORY within each cadence layer.** ## The 10 Gates @@ -464,6 +489,8 @@ Day 4: Production incident from Day 1 code **All gates are MANDATORY. No exceptions. No skip reasons.** +**Note:** Gate 0 includes delivery verification exit criteria (formerly Gate 0.5). See Step 2.3.1. + **Gates 6-7 Deferred Execution:** Test code is written/updated per unit to stay current. Actual test execution (with containers) happens once at end of cycle. ## Integrated PM → Dev Workflow @@ -477,21 +504,70 @@ Day 4: Production incident from Day 1 code ## Execution Order -**Core Principle:** Each execution unit passes through all 11 gates. Gates 6-7 write test code per unit but defer execution to end of cycle. +**Core Principle (two-level cadence — the "Prancy Bentley" model):** -**Per-Unit Flow:** Unit → Gate 0→0.5(delivery verify)→1→2→3→4→5→6(write)→7(write)→8→9 → 🔒 Unit Checkpoint → 🔒 Task Checkpoint → Next Unit -**End-of-Cycle Flow:** All units done → Gate 6(execute)→7(execute) → **Multi-Tenant Adaptation** → Final Commit → Feedback +- **Subtask-level gates** run per execution unit (subtask, or task-itself if no subtasks): Gate 0 (Implementation, incl. delivery verification exit check), Gate 3 (Unit Testing), Gate 9 (Validation). +- **Task-level gates** run ONCE per task, after all its subtasks finish their subtask-level gates: Gate 1 (DevOps), Gate 2 (SRE), Gate 4 (Fuzz), Gate 5 (Property), Gate 6 write (Integration), Gate 7 write (Chaos), Gate 8 (Review — 8 reviewers on cumulative task diff). +- **Cycle-level gates** run ONCE per cycle, after all tasks are done: Gate 6 execute, Gate 7 execute, Multi-Tenant Verify, ring:dev-report (aggregate), Final Commit. -| Scenario | Execution Unit | Gates Per Unit | End of Cycle | -|----------|----------------|----------------|--------------| -| Task without subtasks | Task itself | 11 gates (6-7 write only) | Gate 6-7 execute | -| Task with subtasks | Each subtask | 11 gates per subtask (6-7 write only) | Gate 6-7 execute | +**Per-Subtask Flow:** Subtask → Gate 0 (incl. delivery verification exit check) → Gate 3 → Gate 9 → [opt-in subtask visual report] → [subtask checkpoint if `execution_mode = manual_per_subtask`] +**Per-Task Flow (after all subtasks done):** Gate 1 → Gate 2 → Gate 4 → Gate 5 → Gate 6 (write) → Gate 7 (write) → Gate 8 (Review) → Task-level visual report → Accumulate metrics → [task checkpoint if `execution_mode in {manual_per_task, manual_per_subtask}`] +**End-of-Cycle Flow:** All tasks done → Gate 6 (execute) → Gate 7 (execute) → Multi-Tenant Verify → ring:dev-report (ONE dispatch, reads accumulated_metrics) → Final Commit + +| Scenario | Execution Unit | Subtask-Level Gates (0, 3, 9) | Task-Level Gates (1, 2, 4, 5, 6w, 7w, 8) | +|----------|----------------|-------------------------------|-------------------------------------------| +| Task without subtasks | Task itself (single unit) | 3 gates per unit | 7 gates once (same scope as the unit) | +| Task with subtasks | Each subtask | 3 gates per subtask | 7 gates once per task (UNION of all subtasks' files) | **Why deferred execution for Gates 6-7:** - Integration tests require testcontainers (slow to spin up/tear down) - Chaos tests require Toxiproxy infrastructure - Running containers per subtask is wasteful when subsequent subtasks modify the same code -- Test code stays current (written per unit), infrastructure cost is paid once +- Test code stays current (written per task), infrastructure cost is paid once + +## Execution Loop Structure (the "Prancy Bentley" cadence model) + +```yaml +for each task in state.tasks: + # ===== SUBTASK-LEVEL GATES ===== + for each subtask in task.subtasks (or task-itself if no subtasks): + Execute Gate 0 (Implementation, includes delivery verification exit check) + Execute Gate 3 (Unit Testing) + Execute Gate 9 (Validation) + [per-subtask visual report — OPT-IN only via state.visual_report_granularity == "subtask"] + [subtask checkpoint if execution_mode == manual_per_subtask] + end for + + # ===== TASK-LEVEL GATES ===== + # Input aggregation: implementation_files = UNION across all subtasks of this task. + # gate0_handoffs = ARRAY of per-subtask implementation handoffs (one per subtask). + Execute Gate 1 (DevOps) + Execute Gate 2 (SRE) + Execute Gate 4 (Fuzz) + Execute Gate 5 (Property) + Execute Gate 6 (Integration — write mode) + Execute Gate 7 (Chaos — write mode) + Execute Gate 8 (Review — 8 parallel reviewers on cumulative task diff) + + Generate task-level visual report + Accumulate metrics into state.tasks[i].accumulated_metrics (no dev-report dispatch here) + [task checkpoint if execution_mode in {manual_per_task, manual_per_subtask}] +end for + +# ===== CYCLE-LEVEL GATES ===== +Execute Gate 6 (Integration — execute mode) +Execute Gate 7 (Chaos — execute mode) +Execute Multi-Tenant Verify +Dispatch ring:dev-report (ONE AND ONLY dispatch per cycle — reads accumulated_metrics) +Execute Final Commit +``` + +⛔ **CADENCE RULE:** Gates 1, 2, 4, 5, 6w, 7w, 8 MUST NOT be dispatched during the subtask loop. They are task-cadence — wait until ALL subtasks of the current task have completed Gates 0, 3, and 9 before dispatching them. + +**Why task-level cadence for Gates 1, 2, 4, 5, 6w, 7w, 8:** +- **DevOps / SRE / Fuzz / Property:** Container configs, observability, edge-case coverage, and invariants are coherent at the task boundary, not at each subtask. Running them per subtask duplicates work against an in-flight feature. +- **Integration / Chaos (write):** Test scenarios span multiple subtasks; writing them once per task avoids churn as later subtasks land. +- **Review (Gate 8):** Cumulative task diff shows ALL subtasks' changes at once. Cross-subtask interactions (contract drift, hidden coupling) are MORE visible at this cadence, not less. ## Commit Timing @@ -555,7 +631,7 @@ State is persisted to `{state_path}` (either `docs/ring:dev-cycle/current-cycle. ```json { - "version": "1.0.0", + "version": "1.1.0", "cycle_id": "uuid", "started_at": "ISO timestamp", "updated_at": "ISO timestamp", @@ -564,6 +640,10 @@ State is persisted to `{state_path}` (either `docs/ring:dev-cycle/current-cycle. "cycle_type": "feature | refactor", "execution_mode": "manual_per_subtask|manual_per_task|automatic", "commit_timing": "per_subtask|per_task|at_end", + "_comment_cached_standards": "Populated by Step 1.5 (Standards Pre-Cache). Dictionary of URL → {fetched_at, content}. Sub-skills MUST read from here instead of calling WebFetch. See plan Section 3.1.", + "cached_standards": {}, + "_comment_visual_report_granularity": "Default 'task' (generate visual report once per task). Opt-in 'subtask' to generate per-subtask reports. See plan Section 3.3.", + "visual_report_granularity": "task", "custom_prompt": { "type": "string", "optional": true, @@ -582,54 +662,82 @@ State is persisted to `{state_path}` (either `docs/ring:dev-cycle/current-cycle. "title": "Task title", "status": "pending|in_progress|completed|failed|blocked", "feedback_loop_completed": false, + "_comment_accumulated_metrics": "Populated at Step 11.2 (Task Approval Checkpoint). Aggregated at cycle end by ring:dev-report (Step 12.1). See plan Section 4.1.7 / R4.", + "accumulated_metrics": { + "gate_durations_ms": {}, + "review_iterations": 0, + "testing_iterations": 0, + "issues_by_severity": { + "CRITICAL": 0, + "HIGH": 0, + "MEDIUM": 0, + "LOW": 0 + } + }, + "_comment_subtask_gate_progress": "Per plan Section 3.2 / R5B — subtask-level gate_progress holds SUBTASK-CADENCE gates only: implementation (Gate 0), unit_testing (Gate 3), validation (Gate 9). Task-cadence gates (1, 2, 4, 5, 6w, 7w, 8) live in task.gate_progress, not here.", "subtasks": [ { "id": "ST-001-01", "file": "subtasks/T-001/ST-001-01.md", - "status": "pending|completed" + "status": "pending|completed", + "gate_progress": { + "implementation": { + "status": "pending|in_progress|completed", + "started_at": "ISO timestamp", + "tdd_red": { + "status": "pending|in_progress|completed", + "test_file": "path/to/test_file.go", + "failure_output": "FAIL: TestFoo - expected X got nil", + "completed_at": "ISO timestamp" + }, + "tdd_green": { + "status": "pending|in_progress|completed", + "implementation_file": "path/to/impl.go", + "test_pass_output": "PASS: TestFoo (0.003s)", + "completed_at": "ISO timestamp" + }, + "delivery_verified": false, + "files_changed": [] + }, + "unit_testing": { + "status": "pending|in_progress|completed", + "coverage_actual": 0.0, + "coverage_threshold": 85 + }, + "validation": { + "status": "pending|in_progress|completed", + "result": "pending|approved|rejected" + } + } } ], + "_comment_task_gate_progress": "Per plan Section 3.2 / R5B — task-level gate_progress holds TASK-CADENCE gates only: devops (1), sre (2), fuzz_testing (4), property_testing (5), integration_testing (6w), chaos_testing (7w), review (8). Subtask-cadence gates (0, 3, 9) live in each subtask's gate_progress, not here. Gates 6/7 keep write_mode and execute_mode phases; execute_mode transitions at cycle end (Step 12.1).", "gate_progress": { - "implementation": { - "status": "in_progress", - "started_at": "...", - "tdd_red": { - "status": "pending|in_progress|completed", - "test_file": "path/to/test_file.go", - "failure_output": "FAIL: TestFoo - expected X got nil", - "completed_at": "ISO timestamp" - }, - "tdd_green": { - "status": "pending|in_progress|completed", - "implementation_file": "path/to/impl.go", - "test_pass_output": "PASS: TestFoo (0.003s)", - "completed_at": "ISO timestamp" - } - }, - "delivery_verification": { - "status": "pending|in_progress|completed", - "requirements_total": 0, - "requirements_delivered": 0, - "requirements_missing": 0, - "dead_code_items": 0, - "remediation_items": 0, - "completed_at": "ISO timestamp" - }, "devops": {"status": "pending"}, "sre": {"status": "pending"}, - "unit_testing": {"status": "pending"}, "fuzz_testing": {"status": "pending"}, "property_testing": {"status": "pending"}, "integration_testing": { - "status": "pending|in_progress|completed", + "write_mode": { + "status": "pending|in_progress|completed", + "test_files": [], + "compilation_passed": false + }, + "execute_mode": "pending|completed", "scenarios_tested": 0, "tests_passed": 0, "tests_failed": 0, "flaky_tests_detected": 0 }, - "chaos_testing": {"status": "pending"}, - "review": {"status": "pending"}, - "validation": {"status": "pending"} + "chaos_testing": { + "write_mode": { + "status": "pending|in_progress|completed", + "test_files": [], + "compilation_passed": false + }, + "execute_mode": "pending|completed" + }, + "review": {"status": "pending"} }, "artifacts": {}, "agent_outputs": { @@ -948,33 +1056,31 @@ state.updated_at = "[ISO timestamp]" Write tool: file_path: [state.state_path] # Use state_path from state object content: [full JSON state] - -# Step 3: Verify persistence (MANDATORY - use Read tool) -Read tool: - file_path: [state.state_path] # Use state_path from state object -# Confirm current_gate and gate_progress match expected values ``` ### State Persistence Checkpoints -| Checkpoint | MUST Update | MUST Write File | -|------------|-------------|-----------------| -| **Before Gate 0 (task start)** | `task.status = "in_progress"` in JSON **+ tasks.md Status → `🔄 Doing`** | ✅ YES | -| Gate 0.1 (TDD-RED) | `tdd_red.status`, `tdd_red.failure_output` | ✅ YES | -| Gate 0.2 (TDD-GREEN) | `tdd_green.status`, `implementation.status` | ✅ YES | -| Gate 0.5 (Delivery Verification) | `delivery_verification.status`, `delivery_verification.requirements_total`, `delivery_verification.requirements_delivered`, `delivery_verification.dead_code_items` | ✅ YES | -| Gate 1 (DevOps) | `devops.status`, `agent_outputs.devops` | ✅ YES | -| Gate 2 (SRE) | `sre.status`, `agent_outputs.sre` | ✅ YES | -| Gate 3 (Unit Testing) | `unit_testing.status`, `agent_outputs.unit_testing` | ✅ YES | -| Gate 4 (Fuzz Testing) | `fuzz_testing.status`, `agent_outputs.fuzz_testing` | ✅ YES | -| Gate 5 (Property Testing) | `property_testing.status`, `agent_outputs.property_testing` | ✅ YES | -| Gate 6 (Integration Testing) | `integration_testing.status`, `agent_outputs.integration_testing` | ✅ YES | -| Gate 7 (Chaos Testing) | `chaos_testing.status`, `agent_outputs.chaos_testing` | ✅ YES | -| Gate 8 (Review) | `review.status`, `agent_outputs.review` | ✅ YES | -| Gate 9 (Validation) | `validation.status` (execution unit only — do NOT touch task-level status here) | ✅ YES | -| Step 11.1 (Unit Approval) | `status = "paused_for_approval"` | ✅ YES | -| Step 11.2 (Task Approval) | `task.status = "completed"` in JSON **+ tasks.md Status → `✅ Done`** | ✅ YES | -| HARD BLOCK (any gate) | `task.status = "failed"` in JSON **+ tasks.md Status → `❌ Failed`** | ✅ YES | +⛔ **Cadence-aware write paths.** Subtask-level gates (0, 3, 9) write to `state.tasks[i].subtasks[j].gate_progress.`. Task-level gates (1, 2, 4, 5, 6w, 7w, 8) write to `state.tasks[i].gate_progress.`. Never write task-level gate status under a subtask and never write subtask-level gate status under the task. + +| Checkpoint | Cadence | MUST Update | MUST Write File | +|------------|---------|-------------|-----------------| +| **Before Gate 0 (task start)** | Task | `task.status = "in_progress"` in JSON **+ tasks.md Status → `🔄 Doing`** | ✅ YES | +| Gate 0.1 (TDD-RED) | Subtask | `state.tasks[i].subtasks[j].gate_progress.implementation.tdd_red.status` + `.failure_output` | ✅ YES | +| Gate 0.2 (TDD-GREEN) | Subtask | `state.tasks[i].subtasks[j].gate_progress.implementation.tdd_green.status` + `.implementation.status` | ✅ YES | +| Gate 0 exit (Delivery Verification) | Subtask | `state.tasks[i].subtasks[j].gate_progress.implementation.delivery_verified = true` (absorbed from former Gate 0.5) | ✅ YES | +| Gate 3 (Unit Testing) | Subtask | `state.tasks[i].subtasks[j].gate_progress.unit_testing.status` + `.coverage_actual` + `agent_outputs.unit_testing` | ✅ YES | +| Gate 9 (Validation) | Subtask | `state.tasks[i].subtasks[j].gate_progress.validation.status` + `.result` (do NOT touch task-level status here) | ✅ YES | +| Gate 1 (DevOps) | Task | `state.tasks[i].gate_progress.devops.status` + `agent_outputs.devops` | ✅ YES | +| Gate 2 (SRE) | Task | `state.tasks[i].gate_progress.sre.status` + `agent_outputs.sre` | ✅ YES | +| Gate 4 (Fuzz Testing) | Task | `state.tasks[i].gate_progress.fuzz_testing.status` + `agent_outputs.fuzz_testing` | ✅ YES | +| Gate 5 (Property Testing) | Task | `state.tasks[i].gate_progress.property_testing.status` + `agent_outputs.property_testing` | ✅ YES | +| Gate 6 (Integration — write) | Task | `state.tasks[i].gate_progress.integration_testing.write_mode.status` + `.test_files` + `.compilation_passed` | ✅ YES | +| Gate 7 (Chaos — write) | Task | `state.tasks[i].gate_progress.chaos_testing.write_mode.status` + `.test_files` + `.compilation_passed` | ✅ YES | +| Gate 8 (Review) | Task | `state.tasks[i].gate_progress.review.status` + `agent_outputs.review` (reviewers see cumulative task diff) | ✅ YES | +| Step 11.1 (Subtask Approval) | Subtask | `status = "paused_for_approval"` (subtask-level checkpoint; set only when `execution_mode = manual_per_subtask`) | ✅ YES | +| Step 11.2 (Task Approval) | Task | `task.status = "completed"` in JSON **+ tasks.md Status → `✅ Done`** + `task.accumulated_metrics` populated (gate_durations_ms, review_iterations, testing_iterations, issues_by_severity); NO dev-report dispatch here (runs ONCE at Step 12.1) | ✅ YES | +| Step 12.1 (Cycle end — Gate 6/7 execute + dev-report) | Cycle | `state.tasks[i].gate_progress.integration_testing.execute_mode = "completed"` + `.chaos_testing.execute_mode = "completed"`; `state.feedback_loop_completed = true` after the ONE AND ONLY `ring:dev-report` dispatch | ✅ YES | +| HARD BLOCK (any gate) | Task | `task.status = "failed"` in JSON **+ tasks.md Status → `❌ Failed`** | ✅ YES | **tasks.md Status update rules (apply at the three checkpoints above):** @@ -1005,15 +1111,6 @@ Use Edit tool on state.source_file (tasks.md): | "Write tool is slow" | Write takes <100ms. Lost progress takes hours. | **Write after every gate** | | "I updated the state variable" | Variable ≠ file. Without Write tool, nothing persists. | **Use Write tool explicitly** | -### Verification Command - -After each gate, the state file MUST reflect: -- `current_gate` = next gate number -- `updated_at` = recent timestamp -- Previous gate `status` = "completed" - -**If verification fails → State was not persisted. Re-execute Write tool.** - --- ## Step 0: Verify PROJECT_RULES.md Exists (HARD GATE) @@ -1716,7 +1813,55 @@ Task files are generated by `/pre-dev-*` or `/ring:dev-refactor`, which handle c | Task ID format | `## Task: {ID} - {Title}` | Warning: use line number as ID | | Acceptance criteria | At least one `- [ ]` per task | Warning: task may fail validation gate | -## Step 1.5: Detect External Dependencies (Cycle-Level Auto-Detection) +## Step 1.5: Standards Pre-Cache (MANDATORY) + +Cache all standards URLs the cycle will need, ONCE, into `state.cached_standards`. +Sub-skills read from this cache instead of calling WebFetch themselves. + +**Required URLs to pre-fetch (MUST succeed all):** + +1. `https://raw.githubusercontent.com/LerianStudio/ring/main/CLAUDE.md` +2. Language-specific (based on detected project stack): + - **If Go project:** + - `https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/golang.md` + - `https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/golang/core.md` + - `https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/golang/bootstrap.md` + - `https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/golang/domain.md` + - `https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/golang/api-patterns.md` + - `https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/golang/security.md` + - `https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/golang/quality.md` + - `https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/golang/multi-tenant.md` + - `https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/golang/testing-fuzz.md` + - `https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/golang/testing-property.md` + - `https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/golang/testing-integration.md` + - `https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/golang/testing-chaos.md` + - **If TypeScript backend:** + - `https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/typescript.md` + - `https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/typescript/multi-tenant.md` +3. `https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/devops.md` +4. `https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/sre.md` +5. `https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/migration-safety.md` (if SQL migrations detected in project) + +**Protocol:** + +```text +For each URL in the required list: + WebFetch: [URL] + Write to state.cached_standards[URL] = { + "fetched_at": current_iso_timestamp, + "content": + } +``` + +**MANDATORY:** Save state to file after cache populated — Write tool → [state.state_path] + +**Blocker:** If ANY URL fails to fetch, STOP cycle and report. Cache MUST be complete. Sub-skills downstream rely on `state.cached_standards` being populated; a partial cache causes WebFetch fallback warnings and defeats the purpose of pre-caching. + +**Rationale:** Before this step existed, every sub-skill dispatch triggered its own WebFetch of the same standards. The 5-minute prompt cache TTL is regularly exceeded, producing 15–25+ redundant network fetches per cycle. A single pre-cache at cycle start reduces that to one fetch per unique URL. + +--- + +## Step 1.6: Detect External Dependencies (Cycle-Level Auto-Detection) **MANDATORY:** Scan the codebase once at cycle start to detect external dependencies. Store in `state.detected_dependencies` for use by Gates 2, 6, and 7. @@ -1835,9 +1980,11 @@ Detect the repository license at cycle start. This check is advisory — it does ## Step 2: Gate 0 - Implementation (Per Execution Unit) +ℹ️ **CADENCE:** Subtask-level. Execution unit is always a subtask (or the task-itself when the task has no subtasks). Writes to `state.tasks[i].subtasks[j].gate_progress.implementation`. Task-level gates (1, 2, 4, 5, 6w, 7w, 8) MUST NOT be dispatched from inside this step — they run after the subtask loop. + **REQUIRED SUB-SKILL:** Use ring:dev-implementation -**Execution Unit:** Task (if no subtasks) or Subtask (if task has subtasks) +**Execution Unit:** Task-itself (if no subtasks) or a Subtask (if task has subtasks). Either way, the unit is a SUBTASK-LEVEL scope. ### Pre-Dispatch: Before Gate 0 Checkpoint (MANDATORY) @@ -1866,7 +2013,7 @@ After ring:dev-implementation completes, verify generated code: | No Must* helpers | `grep -rn "Must[A-Z]" --include="*.go" \| grep -v "regexp\.MustCompile"` | 0 results | Return to Gate 0 with fix instructions | | No os.Exit() | `grep -rn "os.Exit" --include="*.go" --exclude="main.go"` | 0 results | Return to Gate 0 with fix instructions | -**If any check fails: DO NOT proceed to Gate 0.5. Return to Gate 0 with specific fix instructions.** +**If any check fails: DO NOT proceed to Gate 1. Return to Gate 0 with specific fix instructions.** ### ⛔ File Size Enforcement (MANDATORY — All Gates) @@ -1875,7 +2022,7 @@ See [shared-patterns/file-size-enforcement.md](../shared-patterns/file-size-enfo **Summary:** No source file may exceed 300 lines (>300 = loop back to agent; >500 = hard block). Implementation agents MUST split proactively. Enforcement points: - **Gate 0:** Implementation agent receives file-size instructions; orchestrator runs verification command after agent completes and loops back if any file > 300 lines. -- **Gate 0.5:** Delivery verification skill runs 7 checks: (A) file-size, (B) license headers, (C) linting, (D) migration safety, (E) vulnerability scanning, (F) API backward compatibility, (G) multi-tenant dual-mode. Any FAIL → return to Gate 0 with specific fix instructions. +- **Gate 0 exit check (formerly Gate 0.5, now inline in ring:dev-implementation Step 7):** Delivery verification runs 7 checks as exit criteria: (A) file-size, (B) license headers, (C) linting, (D) migration safety, (E) vulnerability scanning, (F) API backward compatibility, (G) multi-tenant dual-mode. Any FAIL → ring:dev-implementation re-iterates with specific fix instructions. - **Gate 8:** Code reviewers MUST flag any file > 300 lines as a MEDIUM+ issue (blocking). ### Step 2.1: Prepare Input for ring:dev-implementation Skill @@ -1995,77 +2142,45 @@ implementation_input = { 7. MANDATORY: ⛔ Save state to file — Write tool → [state.state_path] See "State Persistence Rule" section. -8. Proceed to Gate 0.5 +8. Proceed to Step 2.3.1 (Delivery Verification Exit Check) ``` -## Step 2.5: Gate 0.5 - Delivery Verification (Per Execution Unit) +### Step 2.3.1: Delivery Verification Exit Check (MANDATORY before Gate 1) -```text -1. Load Skill: - Skill("ring:dev-delivery-verification") +After Gate 0 PASS, delivery verification runs AS EXIT CRITERIA (not as a separate gate). +This check is performed inside `ring:dev-implementation` as its Step 7 (Delivery +Verification Exit Check). The orchestrator DOES NOT dispatch a separate skill. -2. Invoke with Gate 0 outputs: - - unit_id: current task/subtask ID - - requirements: original task requirements from tasks.md - - files_changed: from Gate 0 agent_outputs.implementation (## Files Changed) - - gate0_handoff: full Gate 0 output +Verify that the dev-implementation handoff includes `delivery_verification` field: -3. Parse result from skill output: - - result: PASS | PARTIAL | FAIL - - requirements_total: from "## Requirement Coverage Matrix" - - requirements_delivered: count of ✅ DELIVERED rows - - requirements_missing: count of ❌ NOT DELIVERED rows - - dead_code_items: count from "## Dead Code Detection" - - remediation_items: count from "## Return to Gate 0" (0 if PASS) + required_handoff_fields: + - implementation_summary + - files_changed + - tests_written + - tdd_red_evidence + - tdd_green_evidence + - delivery_verification: # NEW — added in R3 + result: "PASS|PARTIAL|FAIL" + requirements_total: int + requirements_delivered: int + requirements_missing: int + dead_code_items: int -4. Update state: - - gate_progress.delivery_verification = { - status: "completed", - requirements_total: [N], - requirements_delivered: [N], - requirements_missing: [N], - dead_code_items: [N], - remediation_items: [N], - completed_at: "[ISO timestamp]" - } +IF delivery_verification.result == "PASS": + → Update state.tasks[current].subtasks[current].gate_progress.implementation.delivery_verified = true + → Proceed to Gate 1 (DevOps) -5. Control flow based on result: +IF delivery_verification.result == "PARTIAL" or "FAIL": + → Return control to dev-implementation with remediation instructions (max 2 retries) + → After 2 retries → escalate to user - IF PASS: - → Display ✓ GATE 0.5 COMPLETE, proceed to Gate 1 - - IF PARTIAL: - → Extract undelivered requirements from "## Return to Gate 0" - → Display ⚠ GATE 0.5 PARTIAL — [N] of [M] requirements not delivered - → Return to Gate 0 (Step 2) with explicit fix instructions: - "Deliver the following requirements: [list from Return to Gate 0]" - → After Gate 0 re-run, re-execute Gate 0.5 - → Max 2 retries. If still PARTIAL after 2 retries → escalate to user - - IF FAIL: - → Extract all gaps from "## Return to Gate 0" - → Display ✗ GATE 0.5 FAIL — critical requirements not delivered - → Return to Gate 0 (Step 2) with full remediation list - → After Gate 0 re-run, re-execute Gate 0.5 - → Max 2 retries. If still FAIL after 2 retries → escalate to user +Anti-Rationalization: +| Rationalization | Why It's WRONG | Required Action | +|---|---|---| +| "Gate 0.5 still exists, just renamed" | Gate 0.5 was DELETED as a separate dispatch. Checks now run inline in Gate 0. | **Read `delivery_verification` from Gate 0 handoff; do NOT dispatch a separate skill.** | +| "I'll just skip this check if Gate 0 passed" | Gate 0 passing without `delivery_verification` means Gate 0 is incomplete. | **Verify `delivery_verification` exists in handoff. If absent → Gate 0 failed.** | -6. Display to user: - ┌─────────────────────────────────────────────────┐ - │ ✓ GATE 0.5 COMPLETE │ - ├─────────────────────────────────────────────────┤ - │ Skill: ring:dev-delivery-verification │ - │ Requirements: [delivered]/[total] DELIVERED │ - │ Dead Code: [N] items │ - │ Verdict: [PASS|PARTIAL|FAIL] │ - │ │ - │ Proceeding to Gate 1 (DevOps)... │ - └─────────────────────────────────────────────────┘ - -7. MANDATORY: ⛔ Save state to file — Write tool → [state.state_path] - See "State Persistence Rule" section. - -8. Proceed to Gate 1 -``` +No separate `state.gate_progress.delivery_verification` field — delivery verification is a sub-check of implementation, tracked inline. ### Anti-Rationalization: Gate 0 Skill Invocation @@ -2080,7 +2195,9 @@ implementation_input = { --- -## Step 3: Gate 1 - DevOps (Per Execution Unit) +## Step 3: Gate 1 - DevOps (Per Task — after all subtasks complete Gate 0 + Gate 3 + Gate 9) + +⛔ **CADENCE:** This gate runs ONCE per task, NOT per subtask. Do NOT dispatch during the subtask loop. Input `implementation_files` is the UNION of all subtasks' changed files; `gate0_handoffs` is an ARRAY of per-subtask implementation handoffs. **REQUIRED SUB-SKILLS:** Use ring:dev-devops, then ring:dev-docker-security (audit) @@ -2103,23 +2220,31 @@ implementation_input = { ### Step 3.1: Prepare Input for ring:dev-devops Skill +⛔ **Input scope:** TASK-level. `implementation_files` is the UNION of `files_changed` across all subtasks of the current task; `gate0_handoffs` is an ARRAY (one per subtask). + ```text -Gather from previous gates: +Gather from completed subtask-level gates of the current task: + +task = state.tasks[state.current_task_index] devops_input = { - // REQUIRED - from current execution unit - unit_id: state.current_unit.id, - - // REQUIRED - from Gate 0 context - language: state.current_unit.language, // "go" | "typescript" | "python" - service_type: state.current_unit.service_type, // "api" | "worker" | "batch" | "cli" - implementation_files: agent_outputs.implementation.files_changed, // list of files from Gate 0 - - // OPTIONAL - additional context - gate0_handoff: agent_outputs.implementation, // full Gate 0 output - new_dependencies: state.current_unit.new_deps || [], // new deps added in Gate 0 - new_env_vars: state.current_unit.env_vars || [], // env vars needed - new_services: state.current_unit.services || [], // postgres, redis, etc. + // REQUIRED - TASK-level identifiers (NOT subtask) + unit_id: task.id, // TASK id (e.g., "T-001"), not subtask id + language: task.language, // "go" | "typescript" | "python" + service_type: task.service_type, // "api" | "worker" | "batch" | "cli" + + // REQUIRED - UNION of files changed across all subtasks of this task + implementation_files: flatten(task.subtasks.map(st => + st.gate_progress.implementation.files_changed || [] + )), + + // REQUIRED - ARRAY of per-subtask Gate 0 handoffs (one per subtask) + gate0_handoffs: task.subtasks.map(st => st.gate_progress.implementation), + + // OPTIONAL - additional context (union across subtasks where applicable) + new_dependencies: union(task.subtasks.map(st => st.new_deps || [])), + new_env_vars: union(task.subtasks.map(st => st.env_vars || [])), + new_services: union(task.subtasks.map(st => st.services || [])), existing_dockerfile: [check if Dockerfile exists], existing_compose: [check if docker-compose.yml exists] } @@ -2133,11 +2258,11 @@ devops_input = { 2. Invoke ring:dev-devops skill with structured input: Skill("ring:dev-devops") with input: - unit_id: devops_input.unit_id + unit_id: devops_input.unit_id # TASK id language: devops_input.language service_type: devops_input.service_type - implementation_files: devops_input.implementation_files - gate0_handoff: devops_input.gate0_handoff + implementation_files: devops_input.implementation_files # UNION across subtasks + gate0_handoffs: devops_input.gate0_handoffs # ARRAY of subtask handoffs new_dependencies: devops_input.new_dependencies new_env_vars: devops_input.new_env_vars new_services: devops_input.new_services @@ -2237,29 +2362,41 @@ on the created/updated Dockerfile: | ".env.example can be added later" | .env.example documents required config NOW. | **Create .env.example** | | "Small service doesn't need all this" | Size is irrelevant. Standards apply uniformly. | **Create all artifacts** | -## Step 4: Gate 2 - SRE (Per Execution Unit) +## Step 4: Gate 2 - SRE (Per Task — after all subtasks complete Gate 0 + Gate 3 + Gate 9) + +⛔ **CADENCE:** This gate runs ONCE per task, NOT per subtask. Input `implementation_files` is the UNION of all subtasks' changed files; `gate0_handoffs` is an ARRAY. **REQUIRED SUB-SKILL:** Use `ring:dev-sre` ### Step 4.1: Prepare Input for ring:dev-sre Skill +⛔ **Input scope:** TASK-level. Aggregate from all subtasks of the current task. + ```text -Gather from previous gates: +Gather from completed subtask-level gates: + +task = state.tasks[state.current_task_index] sre_input = { - // REQUIRED - from current execution unit - unit_id: state.current_unit.id, - - // REQUIRED - from Gate 0 context - language: state.current_unit.language, // "go" | "typescript" | "python" - service_type: state.current_unit.service_type, // "api" | "worker" | "batch" | "cli" - implementation_agent: agent_outputs.implementation.agent, // e.g., "ring:backend-engineer-golang" - implementation_files: agent_outputs.implementation.files_changed, // list of files from Gate 0 - + // REQUIRED - TASK-level identifiers + unit_id: task.id, // TASK id + language: task.language, + service_type: task.service_type, + + // REQUIRED - UNION across subtasks + implementation_files: flatten(task.subtasks.map(st => + st.gate_progress.implementation.files_changed || [] + )), + + // REQUIRED - ARRAY of per-subtask Gate 0 handoffs + gate0_handoffs: task.subtasks.map(st => st.gate_progress.implementation), + + // REQUIRED - implementation_agent (consistent across subtasks of the same task) + implementation_agent: task.subtasks[0].gate_progress.implementation.agent, + // OPTIONAL - additional context - external_dependencies: state.current_unit.external_deps || state.detected_dependencies || [], // HTTP clients, gRPC, queues - gate0_handoff: agent_outputs.implementation, // full Gate 0 output - gate1_handoff: agent_outputs.devops // full Gate 1 output + external_dependencies: task.external_deps || state.detected_dependencies || [], + gate1_handoff: task.gate_progress.devops // task-level Gate 1 output (just completed) } ``` @@ -2271,13 +2408,13 @@ sre_input = { 2. Invoke ring:dev-sre skill with structured input: Skill("ring:dev-sre") with input: - unit_id: sre_input.unit_id + unit_id: sre_input.unit_id # TASK id language: sre_input.language service_type: sre_input.service_type implementation_agent: sre_input.implementation_agent - implementation_files: sre_input.implementation_files + implementation_files: sre_input.implementation_files # UNION across subtasks external_dependencies: sre_input.external_dependencies - gate0_handoff: sre_input.gate0_handoff + gate0_handoffs: sre_input.gate0_handoffs # ARRAY of subtask handoffs gate1_handoff: sre_input.gate1_handoff The skill handles: @@ -2354,6 +2491,8 @@ See [ring:dev-sre/SKILL.md](../dev-sre/SKILL.md) for complete anti-rationalizati ## Step 5: Gate 3 - Unit Testing (Per Execution Unit) +ℹ️ **CADENCE:** Subtask-level. Execution unit = a subtask (or the task itself when no subtasks). Writes to `state.tasks[i].subtasks[j].gate_progress.unit_testing`. + **REQUIRED SUB-SKILL:** Use `ring:dev-unit-testing` ### Step 5.1: Prepare Input for ring:dev-unit-testing Skill @@ -2492,7 +2631,9 @@ testing_input = { | "Skip testing, deadline" | "Testing is MANDATORY. ring:dev-unit-testing skill handles iterations." | | "Manual testing covers it" | "Gate 3 requires executable unit tests. Invoking ring:dev-unit-testing now." | -## Step 6: Gate 4 - Fuzz Testing (Per Execution Unit) +## Step 6: Gate 4 - Fuzz Testing (Per Task — after all subtasks complete Gate 0 + Gate 3 + Gate 9) + +⛔ **CADENCE:** This gate runs ONCE per task, NOT per subtask. Input `implementation_files` is the UNION of all subtasks' changed files. **REQUIRED SUB-SKILL:** Use `ring:dev-fuzz-testing` @@ -2500,17 +2641,23 @@ testing_input = { ### Step 6.1: Prepare Input for ring:dev-fuzz-testing Skill +⛔ **Input scope:** TASK-level. Aggregate from all subtasks of the current task. + ```text -Gather from previous gates: +task = state.tasks[state.current_task_index] fuzz_testing_input = { - // REQUIRED - from current execution unit - unit_id: state.current_unit.id, - implementation_files: agent_outputs.implementation.files_changed, - language: state.current_unit.language, // "go" | "typescript" + // REQUIRED - TASK-level + unit_id: task.id, // TASK id + language: task.language, // "go" | "typescript" - // OPTIONAL - additional context - gate3_handoff: agent_outputs.unit_testing // full Gate 3 output + // REQUIRED - UNION across subtasks + implementation_files: flatten(task.subtasks.map(st => + st.gate_progress.implementation.files_changed || [] + )), + + // REQUIRED - ARRAY of per-subtask unit-testing handoffs (Gate 3 is per subtask) + gate3_handoffs: task.subtasks.map(st => st.gate_progress.unit_testing) } ``` @@ -2522,10 +2669,10 @@ fuzz_testing_input = { 2. Invoke ring:dev-fuzz-testing skill with structured input: Skill("ring:dev-fuzz-testing") with input: - unit_id: fuzz_testing_input.unit_id - implementation_files: fuzz_testing_input.implementation_files + unit_id: fuzz_testing_input.unit_id # TASK id + implementation_files: fuzz_testing_input.implementation_files # UNION across subtasks language: fuzz_testing_input.language - gate3_handoff: fuzz_testing_input.gate3_handoff + gate3_handoffs: fuzz_testing_input.gate3_handoffs # ARRAY of per-subtask handoffs The skill handles: - Dispatching ring:qa-analyst agent (test_mode: fuzz) @@ -2558,7 +2705,9 @@ fuzz_testing_input = { --- -## Step 7: Gate 5 - Property-Based Testing (Per Execution Unit) +## Step 7: Gate 5 - Property-Based Testing (Per Task — after all subtasks complete Gate 0 + Gate 3 + Gate 9) + +⛔ **CADENCE:** This gate runs ONCE per task, NOT per subtask. Input `implementation_files` is the UNION of all subtasks' changed files; `domain_invariants` is the UNION across subtasks. **REQUIRED SUB-SKILL:** Use `ring:dev-property-testing` @@ -2566,17 +2715,23 @@ fuzz_testing_input = { ### Step 7.1: Prepare Input for ring:dev-property-testing Skill +⛔ **Input scope:** TASK-level. + ```text -Gather from previous gates: +task = state.tasks[state.current_task_index] property_testing_input = { - // REQUIRED - from current execution unit - unit_id: state.current_unit.id, - implementation_files: agent_outputs.implementation.files_changed, - language: state.current_unit.language, + // REQUIRED - TASK-level + unit_id: task.id, // TASK id + language: task.language, - // Domain invariants from requirements - domain_invariants: state.current_unit.domain_invariants || [] + // REQUIRED - UNION across subtasks + implementation_files: flatten(task.subtasks.map(st => + st.gate_progress.implementation.files_changed || [] + )), + + // Domain invariants — UNION across subtasks of the task + domain_invariants: union(task.subtasks.map(st => st.domain_invariants || [])) } ``` @@ -2624,34 +2779,44 @@ property_testing_input = { --- -## Step 8: Gate 6 - Integration Testing (Per Execution Unit — WRITE ONLY) +## Step 8: Gate 6 - Integration Testing (Per Task — WRITE ONLY) + +⛔ **CADENCE:** Write mode runs ONCE per task, NOT per subtask. Execute mode runs ONCE at cycle end (Step 12.1). Input `implementation_files` is the UNION of all subtasks' changed files. **REQUIRED SUB-SKILL:** Use `ring:dev-integration-testing` **MANDATORY GATE:** All code MUST have integration tests using testcontainers. -**⛔ DEFERRED EXECUTION:** Per unit, this gate writes/updates integration test code and verifies compilation. Tests are NOT executed here (no containers). Actual execution happens at end of cycle (Step 12.1). +**⛔ DEFERRED EXECUTION:** Per task, this gate writes/updates integration test code and verifies compilation. Tests are NOT executed here (no containers). Actual execution happens at end of cycle (Step 12.1). ### Step 8.1: Prepare Input for ring:dev-integration-testing Skill +⛔ **Input scope:** TASK-level. + ```text -Gather from previous gates: +task = state.tasks[state.current_task_index] integration_testing_input = { - // REQUIRED - from current execution unit - unit_id: state.current_unit.id, - integration_scenarios: state.current_unit.integration_scenarios || [], - external_dependencies: state.current_unit.external_dependencies || state.detected_dependencies || [], - language: state.current_unit.language, + // REQUIRED - TASK-level + unit_id: task.id, // TASK id + language: task.language, mode: "write_only", // CRITICAL: write tests, verify compilation, do NOT execute + // REQUIRED - UNION across subtasks of the task + integration_scenarios: union(task.subtasks.map(st => st.integration_scenarios || [])), + external_dependencies: union(task.subtasks.map(st => st.external_dependencies || [])) + || state.detected_dependencies + || [], + implementation_files: flatten(task.subtasks.map(st => + st.gate_progress.implementation.files_changed || [] + )), + // OPTIONAL - additional context - gate5_handoff: agent_outputs.property_testing, - implementation_files: agent_outputs.implementation.files_changed + gate5_handoff: task.gate_progress.property_testing // task-level Gate 5 output } // NOTE: external_dependencies falls back to state.detected_dependencies -// from Step 1.5 (cycle-level auto-detection) when the unit doesn't define them. +// from Step 1.6 (cycle-level auto-detection) when no subtask defines them. ``` ### Step 8.2: Invoke ring:dev-integration-testing Skill (Write Mode) @@ -2717,32 +2882,43 @@ integration_testing_input = { --- -## Step 9: Gate 7 - Chaos Testing (Per Execution Unit — WRITE ONLY) +## Step 9: Gate 7 - Chaos Testing (Per Task — WRITE ONLY) + +⛔ **CADENCE:** Write mode runs ONCE per task, NOT per subtask. Execute mode runs ONCE at cycle end (Step 12.1). `external_dependencies` is the UNION across all subtasks of the task. **REQUIRED SUB-SKILL:** Use `ring:dev-chaos-testing` **MANDATORY GATE:** All external dependencies MUST have chaos tests for failure scenarios. -**⛔ DEFERRED EXECUTION:** Per unit, this gate writes/updates chaos test code and verifies compilation. Tests are NOT executed here (no Toxiproxy). Actual execution happens at end of cycle (Step 12.1). +**⛔ DEFERRED EXECUTION:** Per task, this gate writes/updates chaos test code and verifies compilation. Tests are NOT executed here (no Toxiproxy). Actual execution happens at end of cycle (Step 12.1). ### Step 9.1: Prepare Input for ring:dev-chaos-testing Skill +⛔ **Input scope:** TASK-level. + ```text -Gather from previous gates: +task = state.tasks[state.current_task_index] chaos_testing_input = { - // REQUIRED - from current execution unit - unit_id: state.current_unit.id, - external_dependencies: state.current_unit.external_dependencies || state.detected_dependencies || [], - language: state.current_unit.language, + // REQUIRED - TASK-level + unit_id: task.id, // TASK id + language: task.language, mode: "write_only", // CRITICAL: write tests, verify compilation, do NOT execute + // REQUIRED - UNION across subtasks of the task + external_dependencies: union(task.subtasks.map(st => st.external_dependencies || [])) + || state.detected_dependencies + || [], + implementation_files: flatten(task.subtasks.map(st => + st.gate_progress.implementation.files_changed || [] + )), + // OPTIONAL - additional context - gate6_handoff: agent_outputs.integration_testing + gate6_handoff: task.gate_progress.integration_testing // task-level Gate 6 (write) output } // NOTE: external_dependencies falls back to state.detected_dependencies -// from Step 1.5 (cycle-level auto-detection) when the unit doesn't define them. +// from Step 1.6 (cycle-level auto-detection) when no subtask defines them. ``` ### Step 9.2: Invoke ring:dev-chaos-testing Skill (Write Mode) @@ -2801,26 +2977,36 @@ chaos_testing_input = { --- -## Step 10: Gate 8 - Review (Per Execution Unit) +## Step 10: Gate 8 - Review (Per Task — after all subtasks complete Gate 0 + Gate 3 + Gate 9) + +⛔ **CADENCE:** This gate runs ONCE per task, NOT per subtask. Reviewers see the CUMULATIVE diff of all subtasks in the task — cross-subtask interaction bugs (contract drift, hidden coupling, duplicated logic) are MORE visible at this cadence, not less. **REQUIRED SUB-SKILL:** Use `ring:codereview` ### Step 10.1: Prepare Input for ring:codereview Skill +⛔ **Input scope:** TASK-level. `base_sha` is the SHA before the FIRST subtask's Gate 0 (i.e., the task's starting commit); `head_sha` is the current HEAD after all subtasks and task-level gates up to this point. The resulting diff covers ALL subtasks of the task. + ```text -Gather from previous gates: +task = state.tasks[state.current_task_index] review_input = { - // REQUIRED - from current execution unit - unit_id: state.current_unit.id, - base_sha: state.current_unit.base_sha, // SHA before implementation - head_sha: [current HEAD], // SHA after all gates - implementation_summary: state.current_unit.title + requirements, - requirements: state.current_unit.acceptance_criteria, - + // REQUIRED - TASK-level + unit_id: task.id, // TASK id + base_sha: task.base_sha, // SHA before the FIRST subtask started + head_sha: [current HEAD], // SHA after all subtasks + task-level gates so far + + // REQUIRED - summary and requirements aggregated from task + subtasks + implementation_summary: task.title + "\n" + + task.subtasks.map(st => "- " + st.title + ": " + (st.summary || "")).join("\n"), + requirements: task.acceptance_criteria + || flatten(task.subtasks.map(st => st.acceptance_criteria || [])), + // OPTIONAL - additional context - implementation_files: agent_outputs.implementation.files_changed, - gate0_handoff: agent_outputs.implementation // full Gate 0 output + implementation_files: flatten(task.subtasks.map(st => + st.gate_progress.implementation.files_changed || [] + )), // UNION across subtasks + gate0_handoffs: task.subtasks.map(st => st.gate_progress.implementation) // ARRAY } ``` @@ -2832,13 +3018,13 @@ review_input = { 2. Invoke ring:codereview skill with structured input: Skill("ring:codereview") with input: - unit_id: review_input.unit_id - base_sha: review_input.base_sha - head_sha: review_input.head_sha + unit_id: review_input.unit_id # TASK id + base_sha: review_input.base_sha # SHA before first subtask + head_sha: review_input.head_sha # Current HEAD (cumulative diff) implementation_summary: review_input.implementation_summary requirements: review_input.requirements - implementation_files: review_input.implementation_files - gate0_handoff: review_input.gate0_handoff + implementation_files: review_input.implementation_files # UNION across subtasks + gate0_handoffs: review_input.gate0_handoffs # ARRAY of subtask handoffs The skill handles: - Dispatching all 8 reviewers in PARALLEL (single message with 8 Task calls) @@ -2972,6 +3158,8 @@ review_input = { ## Step 11: Gate 9 - Validation (Per Execution Unit) +ℹ️ **CADENCE:** Subtask-level. Runs after Gate 3 for the current subtask (or task-itself when no subtasks). Writes to `state.tasks[i].subtasks[j].gate_progress.validation`. Task-level gates (1, 2, 4, 5, 6w, 7w, 8) only run AFTER every subtask of the task has passed Gates 0, 3, and 9. + ```text For current execution unit: @@ -3013,23 +3201,12 @@ For current execution unit: - Include all changed files from this subtask - else: Skip commit (will happen at task or cycle end) -0b. **VISUAL CHANGE REPORT (MANDATORY - before checkpoint):** - - MANDATORY: Invoke `Skill("ring:visualize")` to generate a code-diff HTML report for this execution unit - - Read `default/skills/visualize/templates/code-diff.html` to absorb the patterns before generating - - Content sourced from state JSON `agent_outputs` for the current unit: - * **TDD Output:** `tdd_red` (failing test with failure_output) + `tdd_green` (implementation with pass_output) - * **Files Changed:** Per-file before/after using `git diff` data from the implementation (for new files, show "New File" in the before panel). Do not read source files directly — use diff output provided by the implementation agent. - * **Review Verdicts:** Summary of all 8 reviewer verdicts from Gate 8 - * **Acceptance Criteria:** Status from Gate 9 validation - - HTML includes: KPI cards (files changed, tests added, review iterations, gate pass/fail summary), per-file diff panels, review issues section (if any Medium+ issues were found and fixed) - - Save to: `docs/ring:dev-cycle/reports/unit-{unit_id}-report.html` - - Open in browser: - ```text - macOS: open docs/ring:dev-cycle/reports/unit-{unit_id}-report.html - Linux: xdg-open docs/ring:dev-cycle/reports/unit-{unit_id}-report.html - ``` - - Tell the user the file path - - See [shared-patterns/anti-rationalization-visual-report.md](../shared-patterns/anti-rationalization-visual-report.md) for anti-rationalization table +0b. **VISUAL CHANGE REPORT (subtask-level — OPT-IN ONLY):** + - Default: SKIP per-subtask visual report. Task-level aggregate report is generated in Step 11.2. + - Opt-in: If `state.visual_report_granularity == "subtask"`, generate per-subtask report + as previously documented. Default value is "task". + - Rationale: Task-level aggregate covers all subtasks' diffs; per-subtask reports are + rarely consumed and cost one visualize dispatch each. 1. Set `status = "paused_for_approval"`, save state 2. Present summary: Unit ID, Parent Task, Gates 0-9 status, Criteria X/X, Duration, Files Changed, Commit Status @@ -3084,37 +3261,25 @@ After completing all subtasks of a task: 1. Set task status = "completed" -2. **⛔ MANDATORY: Run ring:dev-report skill** +2. **Accumulate task metrics into state (NO dev-report dispatch here):** - ```yaml - Skill tool: - skill: "ring:dev-report" - ``` + Write into `state.tasks[current_task_index].accumulated_metrics`: + - `gate_durations_ms`: {gate_name: duration_ms for each completed gate} + - `review_iterations`: `state.tasks[current].gate_progress.review.iterations` + - `testing_iterations`: sum across all testing gates (unit, fuzz, property, integration, chaos) + - `issues_by_severity`: {CRITICAL, HIGH, MEDIUM, LOW counts from Gate 8 output} - **Note:** ring:dev-report manages its own TodoWrite tracking internally. - - The skill will: - - Add its own todo item for tracking - - Calculate assertiveness score for the task - - Dispatch prompt-quality-reviewer agent with agent_outputs from state - - Generate improvement suggestions - - Write feedback to docs/feedbacks/cycle-{date}/{agent}.md - - Mark its todo as completed + Set `state.tasks[current].feedback_loop_completed = true` + (Actual dev-report dispatch happens ONCE at cycle end in Step 12.1.) - **After feedback-loop completes, update state:** - - Set `tasks[current].feedback_loop_completed = true` in state file + MANDATORY: Save state to file. - **Anti-Rationalization for Feedback Loop:** + Rationale: Feedback analysis is stronger on aggregate data. A single cycle-end + dev-report run produces the same or better insights than N per-task runs. | Rationalization | Why It's WRONG | Required Action | |-----------------|----------------|-----------------| - | "Task was simple, skip feedback" | Simple tasks still contribute to patterns | **Execute Skill tool** | - | "Already at 100% score" | High scores need tracking for replication | **Execute Skill tool** | - | "User approved, feedback unnecessary" | Approval ≠ process quality metrics | **Execute Skill tool** | - | "No issues found, nothing to report" | Absence of issues IS data | **Execute Skill tool** | - | "Time pressure, skip metrics" | Metrics take <2 min, prevent future issues | **Execute Skill tool** | - - **⛔ HARD GATE: You CANNOT proceed to step 3 without executing the Skill tool above.** + | "Should dispatch dev-report now" | dev-report runs ONCE at cycle end (Step 12.1). Per-task metrics are accumulated into state, not analyzed here. | **Accumulate metrics into state, proceed to next task** | 3. Set cycle status = "paused_for_task_approval" 4. Save state @@ -3297,6 +3462,8 @@ All units have written/updated test code during their Gate 6-7 passes. Now execu 4. **⛔ MANDATORY: Run ring:dev-report skill for cycle metrics** + **IMPORTANT (since R4):** This is the ONE AND ONLY ring:dev-report dispatch in the cycle. Per-task runs were removed (see Step 11.2). ring:dev-report reads `accumulated_metrics` from ALL tasks in state and generates aggregate analysis. + ```yaml Skill tool: skill: "ring:dev-report" diff --git a/dev-team/skills/dev-delivery-verification/SKILL.md b/dev-team/skills/dev-delivery-verification/SKILL.md index 1fbe03be..21e93ee8 100644 --- a/dev-team/skills/dev-delivery-verification/SKILL.md +++ b/dev-team/skills/dev-delivery-verification/SKILL.md @@ -7,15 +7,9 @@ description: | functioning in the running application?" Applies to ANY task type: features, refactors, fixes, infrastructure, API endpoints, middleware, business logic, integrations. -trigger: | - - After Gate 0 (implementation) completes, before advancing to Gate 1 - - After any refactoring task claims completion - - When code is generated/scaffolded and needs integration verification +trigger: "Deprecated — use ring:dev-implementation instead (includes these checks as Gate 0 exit criteria)." -skip_when: | - - Not inside a development cycle (ring:dev-cycle or ring:dev-refactor) - - Task is documentation-only, configuration-only, or non-code - - No implementation was produced in Gate 0 (nothing to verify) +skip_when: "always — this skill is preserved but not dispatched in normal cycles." NOT_skip_when: | - "Code compiles" → Compilation ≠ integration. Dead code compiles. @@ -88,6 +82,23 @@ output_schema: description: "Number of fix instructions returned to Gate 0 (0 when PASS)" --- +--- + +> ⚠️ **DEPRECATION NOTICE (since "prancy Bentley" speedup)** +> +> This skill's functionality has been **inlined into `ring:dev-implementation` as Step 7: +> Delivery Verification Exit Check**. New cycles should NOT dispatch this skill as a +> separate gate — the checks run as exit criteria of Gate 0. +> +> This file is preserved for: +> 1. Historical reference of the full check list +> 2. External consumers that may still reference the skill by name +> 3. Potential future use as a standalone audit tool outside the cycle +> +> If you are modifying dev-cycle or dev-implementation, do NOT add dispatches to this skill. + +--- + # Delivery Verification Gate ## The Problem This Solves diff --git a/dev-team/skills/dev-devops/SKILL.md b/dev-team/skills/dev-devops/SKILL.md index bcc595cf..71fb702e 100644 --- a/dev-team/skills/dev-devops/SKILL.md +++ b/dev-team/skills/dev-devops/SKILL.md @@ -3,7 +3,8 @@ name: ring:dev-devops description: | Gate 1 of the development cycle. Creates/updates Docker configuration, docker-compose setup, and environment variables for local development - and deployment readiness. + and deployment readiness. Runs at TASK cadence (after all subtasks + complete Gate 0 + Gate 3 + Gate 9). trigger: | - Gate 1 of development cycle @@ -32,7 +33,7 @@ input_schema: required: - name: unit_id type: string - description: "Task or subtask identifier" + description: "TASK identifier (not a subtask id). This skill runs at TASK cadence — unit_id is always a task id." - name: language type: string enum: [go, typescript, python] @@ -44,11 +45,11 @@ input_schema: - name: implementation_files type: array items: string - description: "List of files from Gate 0 implementation" + description: "Union of changed files across all subtasks of this task." + - name: gate0_handoffs + type: array + description: "Array of per-subtask implementation handoffs (one entry per subtask). NOT a single gate0_handoff object." optional: - - name: gate0_handoff - type: object - description: "Full handoff from Gate 0" - name: new_dependencies type: array items: string @@ -152,13 +153,13 @@ This skill configures the development and deployment infrastructure: ```text REQUIRED INPUT (from ring:dev-cycle orchestrator): -- unit_id: [task/subtask being containerized] +- unit_id: [TASK id — runs at task cadence, not per subtask] - language: [go|typescript|python] - service_type: [api|worker|batch|cli] -- implementation_files: [files from Gate 0] +- implementation_files: [union of changed files across all subtasks of this task] +- gate0_handoffs: [array of per-subtask Gate 0 handoffs — one entry per subtask] OPTIONAL INPUT: -- gate0_handoff: [full Gate 0 output] - new_dependencies: [deps added in Gate 0] - new_env_vars: [env vars needed] - new_services: [postgres, redis, etc.] @@ -235,8 +236,22 @@ Task: - docker-compose.yml: [EXISTS/MISSING] - .env.example: [EXISTS/MISSING] + ## Standards Source (Cache-First Pattern) + + **Standards Source (Cache-First Pattern):** This sub-skill reads standards from `state.cached_standards` populated by dev-cycle Step 1.5. If invoked outside a cycle (standalone), it falls back to direct WebFetch with a warning. See `shared-patterns/standards-cache-protocol.md` for protocol details. + ## Standards Reference - WebFetch: https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/devops.md + + URL: https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/devops.md + + **Cache-first loading protocol:** + For each required standards URL: + IF state.cached_standards[url] exists: + → Read content from state.cached_standards[url].content + → Log: "Using cached standard: {url} (fetched {state.cached_standards[url].fetched_at})" + ELSE: + → WebFetch url (fallback — should not happen if orchestrator ran Step 1.5) + → Log warning: "Standard {url} was not pre-cached; fetched inline" You MUST implement all sections from devops.md. @@ -341,7 +356,17 @@ Task: [list ❌ sections and FAIL verifications] ## Standards Reference - WebFetch: https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/devops.md + + URL: https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/devops.md + + **Cache-first loading protocol:** + For each required standards URL: + IF state.cached_standards[url] exists: + → Read content from state.cached_standards[url].content + → Log: "Using cached standard: {url} (fetched {state.cached_standards[url].fetched_at})" + ELSE: + → WebFetch url (fallback — should not happen if orchestrator ran Step 1.5) + → Log warning: "Standard {url} was not pre-cached; fetched inline" Fix all issues and re-run verification commands. Return updated Standards Coverage Table with all ✅. diff --git a/dev-team/skills/dev-frontend-accessibility/SKILL.md b/dev-team/skills/dev-frontend-accessibility/SKILL.md index 3c2c964d..26105827 100644 --- a/dev-team/skills/dev-frontend-accessibility/SKILL.md +++ b/dev-team/skills/dev-frontend-accessibility/SKILL.md @@ -3,6 +3,7 @@ name: ring:dev-frontend-accessibility description: | Gate 2 of frontend development cycle - ensures all components pass axe-core automated accessibility scans with zero WCAG 2.1 AA violations. + Runs at TASK cadence (after all subtasks complete Gate 0 + Gate 3 + Gate 8). trigger: | - After DevOps setup complete (Gate 1) @@ -31,11 +32,15 @@ input_schema: required: - name: unit_id type: string - description: "Task or subtask identifier" + description: "Task identifier (always a TASK id; runs at task cadence)" - name: implementation_files type: array items: string - description: "Files from Gate 0 implementation" + description: "Union of changed files across all subtasks of this task" + - name: gate0_handoffs + type: array + items: object + description: "Array of per-subtask implementation handoffs (one per subtask). NOT a single gate0_handoff object." - name: language type: string enum: [typescript] @@ -112,7 +117,21 @@ Ensure all frontend components meet **WCAG 2.1 AA** accessibility standards thro ## Standards Reference -**MANDATORY:** Load testing-accessibility.md standards via WebFetch. +> **Standards Source (Cache-First Pattern):** This sub-skill reads standards from `state.cached_standards` populated by dev-cycle Step 1.5. If invoked outside a cycle (standalone), it falls back to direct WebFetch with a warning. See `shared-patterns/standards-cache-protocol.md` for protocol details. + +**MANDATORY:** Load testing-accessibility.md standards using the cache-first pattern below. + +Required URL: `https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/frontend/testing-accessibility.md` + +```yaml +For the required standards URL above: + IF state.cached_standards[url] exists: + → Read content from state.cached_standards[url].content + → Log: "Using cached standard: {url} (fetched {state.cached_standards[url].fetched_at})" + ELSE: + → WebFetch url (fallback — should not happen if orchestrator ran Step 1.5) + → Log warning: "Standard {url} was not pre-cached; fetched inline" +``` https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/frontend/testing-accessibility.md @@ -124,8 +143,9 @@ https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards ```text REQUIRED INPUT: -- unit_id: [task/subtask being tested] -- implementation_files: [files from Gate 0] +- unit_id: [TASK id — this gate runs at task cadence, aggregating all subtasks] +- implementation_files: [union of changed files across all subtasks of the task] +- gate0_handoffs: [array of per-subtask implementation handoffs, one per subtask] - language: [typescript only] OPTIONAL INPUT: @@ -134,6 +154,9 @@ OPTIONAL INPUT: if any REQUIRED input is missing: → STOP and report: "Missing required input: [field]" +if gate0_handoffs is not an array: + → STOP and report: "gate0_handoffs must be an array of per-subtask handoffs" + if language != "typescript": → STOP and report: "Frontend accessibility testing only supported for TypeScript/React" ``` @@ -149,10 +172,13 @@ Task tool: **Standards:** Load testing-accessibility.md **Input:** - - Unit ID: {unit_id} - - Implementation Files: {implementation_files} + - Task ID: {unit_id} (task-level — aggregates all subtasks) + - Implementation Files (union across all subtasks): {implementation_files} + - Per-Subtask Gate 0 Handoffs: {gate0_handoffs} - Language: typescript + **Scope:** Validate accessibility for the task (all subtasks aggregated), not a single subtask. + **Requirements:** 1. Run axe-core scans on all components (all states: default, loading, error, empty, disabled) 2. Test keyboard navigation (Tab, Enter, Escape, Arrow keys) diff --git a/dev-team/skills/dev-frontend-e2e/SKILL.md b/dev-team/skills/dev-frontend-e2e/SKILL.md index 24047683..2efc8d78 100644 --- a/dev-team/skills/dev-frontend-e2e/SKILL.md +++ b/dev-team/skills/dev-frontend-e2e/SKILL.md @@ -3,6 +3,7 @@ name: ring:dev-frontend-e2e description: | Gate 5 of frontend development cycle - ensures all user flows from product-designer have passing E2E tests with Playwright across browsers. + Runs at TASK cadence (after all subtasks complete Gate 0 + Gate 3 + Gate 8). trigger: | - After visual testing complete (Gate 4) @@ -31,11 +32,15 @@ input_schema: required: - name: unit_id type: string - description: "Task or subtask identifier" + description: "Task identifier (always a TASK id; runs at task cadence)" - name: implementation_files type: array items: string - description: "Files from Gate 0 implementation" + description: "Union of changed files across all subtasks of this task" + - name: gate0_handoffs + type: array + items: object + description: "Array of per-subtask implementation handoffs (one per subtask). NOT a single gate0_handoff object." optional: - name: user_flows_path type: string @@ -119,7 +124,21 @@ Ensure all user flows from `ring:product-designer` have passing **Playwright E2E ## Standards Reference -**MANDATORY:** Load testing-e2e.md standards via WebFetch. +> **Standards Source (Cache-First Pattern):** This sub-skill reads standards from `state.cached_standards` populated by dev-cycle Step 1.5. If invoked outside a cycle (standalone), it falls back to direct WebFetch with a warning. See `shared-patterns/standards-cache-protocol.md` for protocol details. + +**MANDATORY:** Load testing-e2e.md standards using the cache-first pattern below. + +Required URL: `https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/frontend/testing-e2e.md` + +```yaml +For the required standards URL above: + IF state.cached_standards[url] exists: + → Read content from state.cached_standards[url].content + → Log: "Using cached standard: {url} (fetched {state.cached_standards[url].fetched_at})" + ELSE: + → WebFetch url (fallback — should not happen if orchestrator ran Step 1.5) + → Log warning: "Standard {url} was not pre-cached; fetched inline" +``` https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/frontend/testing-e2e.md @@ -131,8 +150,9 @@ https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards ```text REQUIRED INPUT: -- unit_id: [task/subtask being tested] -- implementation_files: [files from Gate 0] +- unit_id: [TASK id — this gate runs at task cadence, aggregating all subtasks] +- implementation_files: [union of changed files across all subtasks of the task] +- gate0_handoffs: [array of per-subtask implementation handoffs, one per subtask] OPTIONAL INPUT: - user_flows_path: [path to user-flows.md] @@ -142,6 +162,9 @@ OPTIONAL INPUT: if any REQUIRED input is missing: → STOP and report: "Missing required input: [field]" +if gate0_handoffs is not an array: + → STOP and report: "gate0_handoffs must be an array of per-subtask handoffs" + if user_flows_path provided: → Load user flows as E2E test scenarios → All flows MUST be covered @@ -162,11 +185,14 @@ Task tool: **Standards:** Load testing-e2e.md **Input:** - - Unit ID: {unit_id} - - Implementation Files: {implementation_files} + - Task ID: {unit_id} (task-level — aggregates all subtasks) + - Implementation Files (union across all subtasks): {implementation_files} + - Per-Subtask Gate 0 Handoffs: {gate0_handoffs} - User Flows: {user_flows_path or "N/A"} - Backend Handoff: {backend_handoff or "N/A"} + **Scope:** Validate E2E flows for the task (all subtasks aggregated), not a single subtask. + **Requirements:** 1. Create Playwright tests for all user flows 2. Test happy path + error paths (API 500, timeout, validation) diff --git a/dev-team/skills/dev-frontend-performance/SKILL.md b/dev-team/skills/dev-frontend-performance/SKILL.md index c30f9a25..59dd6299 100644 --- a/dev-team/skills/dev-frontend-performance/SKILL.md +++ b/dev-team/skills/dev-frontend-performance/SKILL.md @@ -3,6 +3,7 @@ name: ring:dev-frontend-performance description: | Gate 6 of frontend development cycle - ensures Core Web Vitals compliance, Lighthouse performance score > 90, and bundle size within budget. + Runs at TASK cadence (after all subtasks complete Gate 0 + Gate 3 + Gate 8). trigger: | - After E2E testing complete (Gate 5) @@ -31,11 +32,15 @@ input_schema: required: - name: unit_id type: string - description: "Task or subtask identifier" + description: "Task identifier (always a TASK id; runs at task cadence)" - name: implementation_files type: array items: string - description: "Files from Gate 0 implementation" + description: "Union of changed files across all subtasks of this task" + - name: gate0_handoffs + type: array + items: object + description: "Array of per-subtask implementation handoffs (one per subtask). NOT a single gate0_handoff object." optional: - name: performance_baseline type: object @@ -119,7 +124,21 @@ Ensure all frontend pages meet **Core Web Vitals** thresholds, achieve **Lightho ## Standards Reference -**MANDATORY:** Load testing-performance.md standards via WebFetch. +> **Standards Source (Cache-First Pattern):** This sub-skill reads standards from `state.cached_standards` populated by dev-cycle Step 1.5. If invoked outside a cycle (standalone), it falls back to direct WebFetch with a warning. See `shared-patterns/standards-cache-protocol.md` for protocol details. + +**MANDATORY:** Load testing-performance.md standards using the cache-first pattern below. + +Required URL: `https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/frontend/testing-performance.md` + +```yaml +For the required standards URL above: + IF state.cached_standards[url] exists: + → Read content from state.cached_standards[url].content + → Log: "Using cached standard: {url} (fetched {state.cached_standards[url].fetched_at})" + ELSE: + → WebFetch url (fallback — should not happen if orchestrator ran Step 1.5) + → Log warning: "Standard {url} was not pre-cached; fetched inline" +``` https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/frontend/testing-performance.md @@ -131,8 +150,9 @@ https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards ```text REQUIRED INPUT: -- unit_id: [task/subtask being tested] -- implementation_files: [files from Gate 0] +- unit_id: [TASK id — this gate runs at task cadence, aggregating all subtasks] +- implementation_files: [union of changed files across all subtasks of the task] +- gate0_handoffs: [array of per-subtask implementation handoffs, one per subtask] OPTIONAL INPUT: - performance_baseline: [previous metrics for comparison] @@ -140,6 +160,9 @@ OPTIONAL INPUT: if any REQUIRED input is missing: → STOP and report: "Missing required input: [field]" + +if gate0_handoffs is not an array: + → STOP and report: "gate0_handoffs must be an array of per-subtask handoffs" ``` ## Step 2: Dispatch Frontend QA Analyst Agent (Performance Mode) @@ -153,10 +176,13 @@ Task tool: **Standards:** Load testing-performance.md **Input:** - - Unit ID: {unit_id} - - Implementation Files: {implementation_files} + - Task ID: {unit_id} (task-level — aggregates all subtasks) + - Implementation Files (union across all subtasks): {implementation_files} + - Per-Subtask Gate 0 Handoffs: {gate0_handoffs} - Baseline: {performance_baseline or "N/A"} + **Scope:** Validate performance for the task (all subtasks aggregated), not a single subtask. + **Requirements:** 1. Measure Core Web Vitals (LCP, CLS, INP) on all affected pages 2. Run Lighthouse audit (Performance score > 90) diff --git a/dev-team/skills/dev-frontend-visual/SKILL.md b/dev-team/skills/dev-frontend-visual/SKILL.md index a25187d7..446f1318 100644 --- a/dev-team/skills/dev-frontend-visual/SKILL.md +++ b/dev-team/skills/dev-frontend-visual/SKILL.md @@ -3,6 +3,7 @@ name: ring:dev-frontend-visual description: | Gate 4 of frontend development cycle - ensures all components have snapshot tests covering all states, viewports, and edge cases. + Runs at TASK cadence (after all subtasks complete Gate 0 + Gate 3 + Gate 8). trigger: | - After unit testing complete (Gate 3) @@ -31,11 +32,15 @@ input_schema: required: - name: unit_id type: string - description: "Task or subtask identifier" + description: "Task identifier (always a TASK id; runs at task cadence)" - name: implementation_files type: array items: string - description: "Files from Gate 0 implementation" + description: "Union of changed files across all subtasks of this task" + - name: gate0_handoffs + type: array + items: object + description: "Array of per-subtask implementation handoffs (one per subtask). NOT a single gate0_handoff object." optional: - name: ux_criteria_path type: string @@ -114,7 +119,21 @@ Ensure all frontend components have **snapshot tests** covering all states, resp ## Standards Reference -**MANDATORY:** Load testing-visual.md standards via WebFetch. +> **Standards Source (Cache-First Pattern):** This sub-skill reads standards from `state.cached_standards` populated by dev-cycle Step 1.5. If invoked outside a cycle (standalone), it falls back to direct WebFetch with a warning. See `shared-patterns/standards-cache-protocol.md` for protocol details. + +**MANDATORY:** Load testing-visual.md standards using the cache-first pattern below. + +Required URL: `https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/frontend/testing-visual.md` + +```yaml +For the required standards URL above: + IF state.cached_standards[url] exists: + → Read content from state.cached_standards[url].content + → Log: "Using cached standard: {url} (fetched {state.cached_standards[url].fetched_at})" + ELSE: + → WebFetch url (fallback — should not happen if orchestrator ran Step 1.5) + → Log warning: "Standard {url} was not pre-cached; fetched inline" +``` https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/frontend/testing-visual.md @@ -126,8 +145,9 @@ https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards ```text REQUIRED INPUT: -- unit_id: [task/subtask being tested] -- implementation_files: [files from Gate 0] +- unit_id: [TASK id — this gate runs at task cadence, aggregating all subtasks] +- implementation_files: [union of changed files across all subtasks of the task] +- gate0_handoffs: [array of per-subtask implementation handoffs, one per subtask] OPTIONAL INPUT: - ux_criteria_path: [path to ux-criteria.md] @@ -135,6 +155,9 @@ OPTIONAL INPUT: if any REQUIRED input is missing: → STOP and report: "Missing required input: [field]" + +if gate0_handoffs is not an array: + → STOP and report: "gate0_handoffs must be an array of per-subtask handoffs" ``` ## Step 2: Dispatch Frontend QA Analyst Agent (Visual Mode) @@ -148,10 +171,13 @@ Task tool: **Standards:** Load testing-visual.md **Input:** - - Unit ID: {unit_id} - - Implementation Files: {implementation_files} + - Task ID: {unit_id} (task-level — aggregates all subtasks) + - Implementation Files (union across all subtasks): {implementation_files} + - Per-Subtask Gate 0 Handoffs: {gate0_handoffs} - UX Criteria: {ux_criteria_path or "N/A"} + **Scope:** Validate visual/snapshot coverage for the task (all subtasks aggregated), not a single subtask. + **Requirements:** 1. Create snapshot tests for all components 2. Cover all states (Default, Empty, Loading, Error, Success, Disabled) diff --git a/dev-team/skills/dev-fuzz-testing/SKILL.md b/dev-team/skills/dev-fuzz-testing/SKILL.md index 0b54226f..a624beb2 100644 --- a/dev-team/skills/dev-fuzz-testing/SKILL.md +++ b/dev-team/skills/dev-fuzz-testing/SKILL.md @@ -3,6 +3,7 @@ name: ring:dev-fuzz-testing description: | Gate 4 of development cycle - ensures fuzz tests exist with proper seed corpus to discover edge cases, crashes, and unexpected input handling. + Runs at TASK cadence (after all subtasks complete Gate 0 + Gate 3 + Gate 9). trigger: | - After unit testing complete (Gate 3) @@ -31,15 +32,18 @@ input_schema: required: - name: unit_id type: string - description: "Task or subtask identifier" + description: "TASK identifier (not a subtask id). This skill runs at TASK cadence — unit_id is always a task id." - name: implementation_files type: array items: string - description: "Files from Gate 0 implementation" + description: "Union of changed files across all subtasks of this task." - name: language type: string enum: [go] description: "Programming language (Go only for native fuzz)" + - name: gate0_handoffs + type: array + description: "Array of per-subtask implementation handoffs (one entry per subtask). NOT a single gate0_handoff object." optional: - name: gate3_handoff type: object @@ -110,9 +114,24 @@ Ensure critical parsing and input handling code has **fuzz tests** to discover c --- +## Standards Source (Cache-First Pattern) + +**Standards Source (Cache-First Pattern):** This sub-skill reads standards from `state.cached_standards` populated by dev-cycle Step 1.5. If invoked outside a cycle (standalone), it falls back to direct WebFetch with a warning. See `shared-patterns/standards-cache-protocol.md` for protocol details. + ## Standards Reference -**MANDATORY:** Load testing-fuzz.md standards via WebFetch. +**MANDATORY:** Load testing-fuzz.md standards via the cache-first pattern below. + +URL: https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/golang/testing-fuzz.md + +**Cache-first loading protocol:** +For each required standards URL: + IF state.cached_standards[url] exists: + → Read content from state.cached_standards[url].content + → Log: "Using cached standard: {url} (fetched {state.cached_standards[url].fetched_at})" + ELSE: + → WebFetch url (fallback — should not happen if orchestrator ran Step 1.5) + → Log warning: "Standard {url} was not pre-cached; fetched inline" https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/golang/testing-fuzz.md @@ -124,9 +143,10 @@ https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards ```text REQUIRED INPUT: -- unit_id: [task/subtask being tested] -- implementation_files: [files from Gate 0] +- unit_id: [TASK id — runs at task cadence, not per subtask] +- implementation_files: [union of changed files across all subtasks of this task] - language: [go only for native fuzz] +- gate0_handoffs: [array of per-subtask Gate 0 handoffs — one entry per subtask] OPTIONAL INPUT: - gate3_handoff: [full Gate 3 output] diff --git a/dev-team/skills/dev-implementation/SKILL.md b/dev-team/skills/dev-implementation/SKILL.md index ed6a870e..ced6d956 100644 --- a/dev-team/skills/dev-implementation/SKILL.md +++ b/dev-team/skills/dev-implementation/SKILL.md @@ -4,6 +4,7 @@ description: | Gate 0 of the development cycle. Executes code implementation using the appropriate specialized agent based on task content and project language. Handles TDD workflow with RED-GREEN phases. Follows project standards defined in docs/PROJECT_RULES.md. + Includes delivery verification exit criteria (merged from deprecated ring:dev-delivery-verification). trigger: | - Gate 0 of development cycle @@ -215,12 +216,26 @@ Task: ## Project Standards Read and follow: [project_rules_path] + ## Standards Source (Cache-First Pattern) + + **Standards Source (Cache-First Pattern):** This sub-skill reads standards from `state.cached_standards` populated by dev-cycle Step 1.5. If invoked outside a cycle (standalone), it falls back to direct WebFetch with a warning. See `shared-patterns/standards-cache-protocol.md` for protocol details. + ## Ring Standards Reference (Modular) Go modules: `https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/golang/{module}.md` For TS: `https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/typescript.md` - **Go minimum for tests:** WebFetch `quality.md` → Testing section for test conventions. + + **Cache-first loading protocol:** + For each required standards URL: + IF state.cached_standards[url] exists: + → Read content from state.cached_standards[url].content + → Log: "Using cached standard: {url} (fetched {state.cached_standards[url].fetched_at})" + ELSE: + → WebFetch url (fallback — should not happen if orchestrator ran Step 1.5) + → Log warning: "Standard {url} was not pre-cached; fetched inline" + + **Go minimum for tests:** Load `quality.md` via cache-first pattern → Testing section for test conventions. Multi-Tenant: Implement DUAL-MODE from the start (Go only). Use resolvers for all resources — they work transparently in both single-tenant and multi-tenant mode. See TDD-GREEN prompt for full Dual-Mode Implementation section and the sub-package import table. - WebFetch `https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/golang/multi-tenant.md` for patterns. + Load `https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/golang/multi-tenant.md` via cache-first pattern for patterns. ## Frontend TDD Policy (React/Next.js only) If the component is purely visual/presentational (layout, styling, animations, @@ -323,15 +338,28 @@ Task: ## Project Standards Read and follow: [project_rules_path] + ## Standards Source (Cache-First Pattern) + + **Standards Source (Cache-First Pattern):** This sub-skill reads standards from `state.cached_standards` populated by dev-cycle Step 1.5. If invoked outside a cycle (standalone), it falls back to direct WebFetch with a warning. See `shared-patterns/standards-cache-protocol.md` for protocol details. + ## Ring Standards Reference (Modular — Load by Task Type) - - **⛔ MANDATORY: WebFetch the MODULAR standards files below, NOT the monolithic golang.md.** + + **⛔ MANDATORY: Load the MODULAR standards files below via the cache-first pattern, NOT the monolithic golang.md.** The standards are split into focused modules. Load the ones relevant to your task type. - + + **Cache-first loading protocol (applies to every URL listed below):** + For each required standards URL: + IF state.cached_standards[url] exists: + → Read content from state.cached_standards[url].content + → Log: "Using cached standard: {url} (fetched {state.cached_standards[url].fetched_at})" + ELSE: + → WebFetch url (fallback — should not happen if orchestrator ran Step 1.5) + → Log warning: "Standard {url} was not pre-cached; fetched inline" + ### Go — Module Loading Guide Base URL: `https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/golang/` - - | Task Type | REQUIRED Modules to WebFetch | + + | Task Type | REQUIRED Modules to Load (cache-first) | |-----------|----------------------------| | New feature (full) | `core.md` → `bootstrap.md` → `domain.md` → `quality.md` → `api-patterns.md` | | API endpoint | `core.md` → `api-patterns.md` → `domain.md` → `quality.md` | @@ -340,12 +368,12 @@ Task: | Messaging / RabbitMQ | `core.md` → `messaging.md` | | Infra / Bootstrap | `core.md` → `bootstrap.md` | | Any task | `core.md` is ALWAYS required (lib-commons, license headers, dependency management) | - + ### TypeScript URL: `https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/typescript.md` - + Multi-Tenant: Implement DUAL-MODE from the start. Use lib-commons v4 resolvers for ALL resources. - WebFetch: `https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/golang/multi-tenant.md` + Load via cache-first pattern: `https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/golang/multi-tenant.md` ## ⛔ Multi-Tenant Dual-Mode Implementation (Go backend only — skip for TypeScript/Frontend) @@ -448,7 +476,7 @@ Task: - 90%+ instrumentation coverage required - - WebFetch standards file before implementation + - Load standards file via cache-first pattern (state.cached_standards → fallback WebFetch) before implementation - Follow exact patterns from standards - Output Standards Coverage Table with evidence @@ -465,12 +493,12 @@ Task: ### Language-Specific Patterns (MANDATORY) - **⛔ HARD GATE: Agent MUST WebFetch modular standards files BEFORE writing any code.** - + **⛔ HARD GATE: Agent MUST load modular standards files (cache-first, WebFetch fallback) BEFORE writing any code.** + Use the Module Loading Guide above to determine which modules to load. **Minimum for ANY Go task:** `core.md` (lib-commons, license headers, deps, MongoDB patterns) - - | Language | Standards Modules | REQUIRED Sections to WebFetch | + + | Language | Standards Modules | REQUIRED Sections to Load (cache-first) | |----------|-------------------|-------------------------------| | **Go** | See Module Loading Guide above | ALL sections from loaded modules (use `standards-coverage-table.md` → `ring:backend-engineer-golang` section index) | | **TypeScript** | `typescript.md` | ALL 15 sections from `standards-coverage-table.md` → `ring:backend-engineer-typescript` | @@ -480,15 +508,15 @@ Task: | Requirement | Enforcement | |-------------|-------------| - | WebFetch modular standards files | MANDATORY before implementation | + | Load modular standards files (cache-first, WebFetch fallback) | MANDATORY before implementation | | Follow exact patterns | REQUIRED - copy structure from standards | | Output Standards Coverage Table | REQUIRED - with file:line evidence for ALL loaded sections | | 90%+ instrumentation coverage | HARD GATE - implementation REJECTED if below | | All loaded sections ✅ or N/A | HARD GATE - any ❌ = REJECTED | ### ⛔ FORBIDDEN Patterns (HARD BLOCK) - - **Agent MUST WebFetch standards and check Anti-Patterns table. Violations = REJECTED.** + + **Agent MUST load standards (cache-first, WebFetch fallback) and check Anti-Patterns table. Violations = REJECTED.** - **Go:** `golang.md` → "Anti-Patterns" table - MUST check all rows - **TypeScript:** `typescript.md` → "Anti-Patterns" table - MUST check all rows @@ -528,7 +556,7 @@ Task: ### Standards Coverage Table (MANDATORY) - **Standards Modules Loaded:** [list modules WebFetched] + **Standards Modules Loaded:** [list modules loaded via cache-first pattern; note cache hit/miss per module] **Total Sections Checked:** [N] | # | Section (from standards) | Status | Evidence | @@ -628,6 +656,54 @@ if pass_output contains "PASS" and all standards ✅ and Standards Coverage Tabl → Proceed to Step 8 ``` +## Step 7: Delivery Verification Exit Check (MANDATORY — absorbed from former Gate 0.5) + +Before emitting the "Ready for Gate 1: YES" handoff, verify that every requirement in the +task/subtask's acceptance criteria is DELIVERED (reachable, integrated, not dead code). + +### Checks to run (absorbed from deprecated ring:dev-delivery-verification skill) + +#### Check 1: Requirement Coverage Matrix (MANDATORY) +For each acceptance criterion in input.requirements: +- Locate the file(s) that implement it +- Verify it's callable from a public entry point (handler, route, CLI command) +- Mark as ✅ DELIVERED | ⚠️ PARTIAL | ❌ NOT DELIVERED + +#### Check 2: Dead Code Detection (MANDATORY) +For each newly-created struct/interface/function in files_changed: +- Verify it's referenced from at least one caller (other than tests) +- If created but uncalled → dead code item + +#### Check 3: Integration Verification (MANDATORY) +- New middleware MUST be wired into router/server +- New repositories MUST be registered in DI container +- New types MUST be exported where consumers expect them + +### Output (added to handoff to Gate 1) + +```yaml +delivery_verification: + result: "PASS" | "PARTIAL" | "FAIL" + requirements_total: N + requirements_delivered: N + requirements_missing: N + dead_code_items: N +``` + +### Decision gate + +IF `result != "PASS"`: +- Re-run Step 6 (TDD-GREEN) with remediation instructions +- Max 2 retries before escalating to orchestrator + +IF `result == "PASS"`: +- Proceed to Handoff to Next Gate + +### Reference +Full detailed check list preserved in `/Users/fredamaral/repos/lerianstudio/ring/dev-team/skills/dev-delivery-verification/SKILL.md` (deprecated but retained for reference). + +--- + ## Step 8: Prepare Output ```text @@ -667,6 +743,13 @@ Generate skill output: - Standards met: ✅ - Ready for Gate 1 (DevOps): YES - Environment needs: [list any new deps, env vars, services] + +delivery_verification: + result: "PASS|PARTIAL|FAIL" + requirements_total: integer + requirements_delivered: integer + requirements_missing: integer + dead_code_items: integer ``` --- diff --git a/dev-team/skills/dev-integration-testing/SKILL.md b/dev-team/skills/dev-integration-testing/SKILL.md index 92791c27..16af02ab 100644 --- a/dev-team/skills/dev-integration-testing/SKILL.md +++ b/dev-team/skills/dev-integration-testing/SKILL.md @@ -3,6 +3,8 @@ name: ring:dev-integration-testing description: | Gate 6 of development cycle - ensures integration tests pass for all external dependency interactions using real containers via testcontainers. + Runs at TASK cadence (after all subtasks complete Gate 0 + Gate 3 + Gate 9): + write mode runs per task, execute mode runs per cycle. trigger: | - After property-based testing complete (Gate 5) @@ -31,7 +33,7 @@ input_schema: required: - name: unit_id type: string - description: "Task or subtask identifier" + description: "TASK identifier (not a subtask id). This skill's write mode runs at TASK cadence — unit_id is always a task id. Execute mode runs per cycle." - name: integration_scenarios type: array items: string @@ -44,14 +46,17 @@ input_schema: type: string enum: [go, typescript] description: "Programming language" + - name: implementation_files + type: array + items: string + description: "Union of changed files across all subtasks of this task." + - name: gate0_handoffs + type: array + description: "Array of per-subtask implementation handoffs (one entry per subtask). NOT a single gate0_handoff object." optional: - name: gate3_handoff type: object description: "Full handoff from Gate 3 (unit testing)" - - name: implementation_files - type: array - items: string - description: "Files from Gate 0 implementation" output_schema: format: markdown @@ -176,15 +181,16 @@ PM team task files often omit external_dependencies. If the codebase uses postgr ```text REQUIRED INPUT (from ring:dev-cycle orchestrator): -- unit_id exists +- unit_id exists (TASK id — write mode runs at task cadence, not per subtask) - language is valid (go|typescript) +- implementation_files: [union of changed files across all subtasks of this task] +- gate0_handoffs: [array of per-subtask Gate 0 handoffs — one entry per subtask] OPTIONAL INPUT (determines if Gate 6 runs or skips): - integration_scenarios: [list of scenarios] - if provided and non-empty, Gate 6 runs - external_dependencies: [list of deps] (from input OR auto-detected in Step 0) - if non-empty, Gate 6 runs - gate3_handoff: [full Gate 3 output] -- implementation_files: [files from Gate 0] EXECUTION LOGIC: 1. if any REQUIRED input is missing: @@ -270,8 +276,22 @@ Task: ## External Dependencies [list external_dependencies with container requirements] + ## Standards Source (Cache-First Pattern) + + **Standards Source (Cache-First Pattern):** This sub-skill reads standards from `state.cached_standards` populated by dev-cycle Step 1.5. If invoked outside a cycle (standalone), it falls back to direct WebFetch with a warning. See `shared-patterns/standards-cache-protocol.md` for protocol details. + ## Standards Reference - WebFetch: https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/golang/testing-integration.md + + URL: https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/golang/testing-integration.md + + **Cache-first loading protocol:** + For each required standards URL: + IF state.cached_standards[url] exists: + → Read content from state.cached_standards[url].content + → Log: "Using cached standard: {url} (fetched {state.cached_standards[url].fetched_at})" + ELSE: + → WebFetch url (fallback — should not happen if orchestrator ran Step 1.5) + → Log warning: "Standard {url} was not pre-cached; fetched inline" Focus on: All sections, especially INT-5 (Build Tags), INT-6 (Testcontainers), INT-7 (No t.Parallel()) diff --git a/dev-team/skills/dev-property-testing/SKILL.md b/dev-team/skills/dev-property-testing/SKILL.md index 9f2cc589..43bf530b 100644 --- a/dev-team/skills/dev-property-testing/SKILL.md +++ b/dev-team/skills/dev-property-testing/SKILL.md @@ -3,6 +3,7 @@ name: ring:dev-property-testing description: | Gate 5 of development cycle - ensures property-based tests exist to verify domain invariants hold for all randomly generated inputs. + Runs at TASK cadence (after all subtasks complete Gate 0 + Gate 3 + Gate 9). trigger: | - After fuzz testing complete (Gate 4) @@ -31,15 +32,18 @@ input_schema: required: - name: unit_id type: string - description: "Task or subtask identifier" + description: "TASK identifier (not a subtask id). This skill runs at TASK cadence — unit_id is always a task id." - name: implementation_files type: array items: string - description: "Files from Gate 0 implementation" + description: "Union of changed files across all subtasks of this task." - name: language type: string enum: [go] description: "Programming language" + - name: gate0_handoffs + type: array + description: "Array of per-subtask implementation handoffs (one entry per subtask). NOT a single gate0_handoff object." optional: - name: domain_invariants type: array @@ -114,9 +118,24 @@ Ensure domain logic has **property-based tests** to verify invariants hold for a --- +## Standards Source (Cache-First Pattern) + +**Standards Source (Cache-First Pattern):** This sub-skill reads standards from `state.cached_standards` populated by dev-cycle Step 1.5. If invoked outside a cycle (standalone), it falls back to direct WebFetch with a warning. See `shared-patterns/standards-cache-protocol.md` for protocol details. + ## Standards Reference -**MANDATORY:** Load testing-property.md standards via WebFetch. +**MANDATORY:** Load testing-property.md standards via the cache-first pattern below. + +URL: https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/golang/testing-property.md + +**Cache-first loading protocol:** +For each required standards URL: + IF state.cached_standards[url] exists: + → Read content from state.cached_standards[url].content + → Log: "Using cached standard: {url} (fetched {state.cached_standards[url].fetched_at})" + ELSE: + → WebFetch url (fallback — should not happen if orchestrator ran Step 1.5) + → Log warning: "Standard {url} was not pre-cached; fetched inline" https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/golang/testing-property.md @@ -128,9 +147,10 @@ https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards ```text REQUIRED INPUT: -- unit_id: [task/subtask being tested] -- implementation_files: [files from Gate 0] +- unit_id: [TASK id — runs at task cadence, not per subtask] +- implementation_files: [union of changed files across all subtasks of this task] - language: [go] +- gate0_handoffs: [array of per-subtask Gate 0 handoffs — one entry per subtask] OPTIONAL INPUT: - domain_invariants: [list of invariants to verify] diff --git a/dev-team/skills/dev-refactor-frontend/SKILL.md b/dev-team/skills/dev-refactor-frontend/SKILL.md index bbe362df..283e9dc2 100644 --- a/dev-team/skills/dev-refactor-frontend/SKILL.md +++ b/dev-team/skills/dev-refactor-frontend/SKILL.md @@ -986,40 +986,66 @@ Total finding count MUST match total issues from Step 4.5 --- -## Step 6: Map Findings to Tasks (1:1) +## Step 6: Map Findings to Tasks (Clustered by file + pattern) **TodoWrite:** Mark "Map findings 1:1 to REFACTOR-XXX tasks" as `in_progress` -**HARD GATE: One FINDING-XXX = One REFACTOR-XXX task. No grouping.** +## Clustering Rule (replaces former 1:1 mapping) -Each finding becomes its own task. This prevents findings from being lost inside grouped tasks. +Findings are clustered into REFACTOR tasks by the tuple `(file_path, pattern_category)`. -**1:1 Mapping Rule:** -- FINDING-001 -> REFACTOR-001 -- FINDING-002 -> REFACTOR-002 -- FINDING-NNN -> REFACTOR-NNN +### Clustering Algorithm -**Ordering:** Sort tasks by severity (Critical first), then by dependency order. +1. Group all findings by their `file` field (from agent report). +2. Within each file group, sub-group by `pattern_category`: + - `pattern_category` is derived from the finding's "Category" field + - (e.g., "component-architecture", "ui-library", "styling", "accessibility", "testing", "performance", etc.) +3. Each `(file, pattern_category)` tuple becomes ONE REFACTOR-XXX task. +4. If a file has findings in 3 different pattern categories → 3 REFACTOR tasks for that file. +5. If a pattern category spans multiple files → one task per (file, pattern) pair (no cross-file clustering). + +### Traceability Preservation (MANDATORY) + +Every REFACTOR task MUST include a `findings:` array listing all FINDING-XXX IDs it covers: + +~~~markdown +## REFACTOR-005: Accessibility Pattern in src/components/UserForm.tsx + +**Cluster Key:** (src/components/UserForm.tsx, accessibility) +**Findings Covered:** [FINDING-012, FINDING-015, FINDING-018] +**Severity:** HIGH (max of covered findings' severities) +**Effort:** {sum of covered findings' effort estimates} + +### Findings Breakdown +| Finding | Line | Description | Status | +|---------|------|-------------|--------| +| FINDING-012 | UserForm.tsx:45 | missing aria-label on input | pending | +| FINDING-015 | UserForm.tsx:78 | missing aria-label on input | pending | +| FINDING-018 | UserForm.tsx:102 | missing aria-label on input | pending | +~~~ + +During dev-cycle-frontend execution, each finding's status is tracked per-line inside +the REFACTOR task. A REFACTOR task completes only when all covered findings are resolved. + +### Mapping Verification (updated) -**Mapping Verification:** -``` Before proceeding to Step 7, verify: - Total FINDING-XXX in findings.md: X -- Total REFACTOR-XXX in tasks.md: X (MUST MATCH exactly) -- Orphan findings (not mapped): 0 (MUST BE ZERO) -- Grouped tasks (multiple findings): 0 (MUST BE ZERO) -``` +- Total REFACTOR-XXX in tasks.md: Y (Y ≤ X — clustering reduces count) +- Every FINDING-XXX appears in exactly ONE REFACTOR task's `findings:` array +- NO FINDING-XXX is missing from all REFACTOR tasks +- NO FINDING-XXX appears in multiple REFACTOR tasks -**If counts don't match, STOP. Every finding MUST have its own task.** +If any finding is orphan or duplicated → STOP. Fix clustering. ### Anti-Rationalization Table for Step 6 | Rationalization | Why It's WRONG | Required Action | -|-----------------|----------------|-----------------| -| "These findings are in the same file, I'll group them" | Grouping hides findings. One fix may be done, others forgotten. | **One finding = One task. No exceptions.** | -| "Grouping reduces task count and is easier to manage" | Fewer tasks = less visibility. Each finding needs independent tracking. | **Create one REFACTOR-XXX per FINDING-XXX** | -| "These are related and should be fixed together" | Related is not same task. ring:dev-cycle-frontend can execute them sequentially. | **Separate tasks, use Dependencies field to link** | -| "Too many tasks will overwhelm the developer" | Missing fixes overwhelms production. Completeness > convenience. | **Create all tasks. Priority handles ordering.** | +|---|---|---| +| "Just keep 1:1 mapping, it's simpler" | 1:1 mapping multiplies cycle cost ~5x for typical refactors. Clustering preserves traceability. | **Apply (file, pattern) clustering** | +| "Cluster across files to reduce tasks more" | Cross-file clustering hides file-specific blast radius. Only cluster within a file. | **Cluster only within file** | +| "Skip the findings: array, it's redundant" | Without traceability array, findings get lost inside tasks. | **ALWAYS populate findings: array** | +| "One finding can be in multiple tasks" | Duplicates cause double-fix attempts. One finding → one task. | **Each FINDING in exactly one REFACTOR** | **TodoWrite:** Mark "Map findings 1:1 to REFACTOR-XXX tasks" as `completed` @@ -1038,16 +1064,17 @@ Before proceeding to Step 7, verify: **Total Tasks:** {count} **UI Library Mode:** {ui_library_mode} -## Mandatory 1:1 Mapping Verification +## Mandatory Clustering Traceability Verification -**Every FINDING-XXX has exactly one REFACTOR-XXX. No grouping.** +**Findings are clustered by (file, pattern_category). Every FINDING-XXX appears in exactly one REFACTOR-XXX via its `findings:` array.** | Metric | Count | |--------|-------| | Total FINDING-XXX in findings.md | {X} | -| Total REFACTOR-XXX in tasks.md | {X} | -| **Counts match exactly?** | YES (REQUIRED) | -| Grouped tasks (multiple findings) | 0 (REQUIRED) | +| Total REFACTOR-XXX in tasks.md | {Y} (Y ≤ X — clustering reduces count) | +| **Every finding appears in exactly one task?** | YES (REQUIRED) | +| Orphan findings (in zero tasks) | 0 (REQUIRED) | +| Duplicate findings (in 2+ tasks) | 0 (REQUIRED) | **Priority affects execution order, not whether to include:** - Critical/High tasks: Execute first @@ -1056,19 +1083,26 @@ Before proceeding to Step 7, verify: --- -## REFACTOR-001: {Finding Pattern Name} +## REFACTOR-001: {Finding Pattern Name} in {file_path} -**Finding:** FINDING-001 -**Severity:** Critical | High | Medium | Low (all ARE MANDATORY) +**Cluster Key:** ({file_path}, {pattern_category}) +**Findings Covered:** [FINDING-XXX, FINDING-YYY, ...] +**Severity:** Critical | High | Medium | Low (max of covered findings' severities; all ARE MANDATORY) **Category:** {component-architecture | ui-library | styling | accessibility | testing | performance | devops} **Agent:** {agent-name} -**Effort:** {hours}h +**Effort:** {hours}h (sum of covered findings' effort estimates) **Dependencies:** {other REFACTOR-XXX tasks or none} +### Findings Breakdown +| Finding | Line | Description | Status | +|---------|------|-------------|--------| +| FINDING-XXX | {file}:{line} | {short description} | pending | +| FINDING-YYY | {file}:{line} | {short description} | pending | + ### Current Code ```{lang} // file: {path}:{lines} -{actual code from FINDING-001} +{representative code from covered findings} ``` ### Ring Standard Reference @@ -1083,6 +1117,7 @@ Before proceeding to Step 7, verify: ### Acceptance Criteria - [ ] Code follows {standard}.md -> {section} pattern - [ ] No {anti-pattern} usage remains +- [ ] All covered findings resolved (status: done for each row in Findings Breakdown) - [ ] Tests pass after refactoring ``` @@ -1231,6 +1266,10 @@ Skill tool: skill: "ring:dev-cycle-frontend" ``` +Note: Each REFACTOR task covering N findings is treated as ONE execution unit with N +internal acceptance criteria. dev-cycle-frontend does not need to know about clustering — it +consumes the task as-if it were any other task. + **CRITICAL: Pass tasks file path in context:** After invoking the skill, provide: diff --git a/dev-team/skills/dev-refactor/SKILL.md b/dev-team/skills/dev-refactor/SKILL.md index 2d6dacb1..dee16edb 100644 --- a/dev-team/skills/dev-refactor/SKILL.md +++ b/dev-team/skills/dev-refactor/SKILL.md @@ -847,40 +847,66 @@ If counts don't match → STOP. Go back to Step 4.1. Map missing issues. --- -## Step 6: Map Findings to Tasks (1:1) +## Step 6: Map Findings to Tasks (Clustered by file + pattern) **TodoWrite:** Mark "Map findings 1:1 to REFACTOR-XXX tasks" as `in_progress` -**⛔ HARD GATE: One FINDING-XXX = One REFACTOR-XXX task. No grouping.** +## Clustering Rule (replaces former 1:1 mapping) -Each finding becomes its own task. This prevents findings from being lost inside grouped tasks. +Findings are clustered into REFACTOR tasks by the tuple `(file_path, pattern_category)`. -**1:1 Mapping Rule:** -- FINDING-001 → REFACTOR-001 -- FINDING-002 → REFACTOR-002 -- FINDING-NNN → REFACTOR-NNN +### Clustering Algorithm -**Ordering:** Sort tasks by severity (Critical first), then by dependency order. +1. Group all findings by their `file` field (from agent report). +2. Within each file group, sub-group by `pattern_category`: + - `pattern_category` is derived from the finding's "Category" field + - (e.g., "error-handling", "logging", "multi-tenant", "file-size", etc.) +3. Each `(file, pattern_category)` tuple becomes ONE REFACTOR-XXX task. +4. If a file has findings in 3 different pattern categories → 3 REFACTOR tasks for that file. +5. If a pattern category spans multiple files → one task per (file, pattern) pair (no cross-file clustering). + +### Traceability Preservation (MANDATORY) + +Every REFACTOR task MUST include a `findings:` array listing all FINDING-XXX IDs it covers: + +~~~markdown +## REFACTOR-005: Error Wrapping Pattern in internal/handler/user.go + +**Cluster Key:** (internal/handler/user.go, error-handling) +**Findings Covered:** [FINDING-012, FINDING-015, FINDING-018] +**Severity:** HIGH (max of covered findings' severities) +**Effort:** {sum of covered findings' effort estimates} + +### Findings Breakdown +| Finding | Line | Description | Status | +|---------|------|-------------|--------| +| FINDING-012 | user.go:45 | `return err` without wrap | pending | +| FINDING-015 | user.go:78 | `return err` without wrap | pending | +| FINDING-018 | user.go:102 | `return err` without wrap | pending | +~~~ + +During dev-cycle execution, each finding's status is tracked per-line inside the +REFACTOR task. A REFACTOR task completes only when all covered findings are resolved. + +### Mapping Verification (updated) -**Mapping Verification:** -``` Before proceeding to Step 7, verify: - Total FINDING-XXX in findings.md: X -- Total REFACTOR-XXX in tasks.md: X (MUST MATCH exactly) -- Orphan findings (not mapped): 0 (MUST BE ZERO) -- Grouped tasks (multiple findings): 0 (MUST BE ZERO) -``` +- Total REFACTOR-XXX in tasks.md: Y (Y ≤ X — clustering reduces count) +- Every FINDING-XXX appears in exactly ONE REFACTOR task's `findings:` array +- NO FINDING-XXX is missing from all REFACTOR tasks +- NO FINDING-XXX appears in multiple REFACTOR tasks -**If counts don't match → STOP. Every finding MUST have its own task.** +If any finding is orphan or duplicated → STOP. Fix clustering. ### Anti-Rationalization Table for Step 6 | Rationalization | Why It's WRONG | Required Action | -|-----------------|----------------|-----------------| -| "These findings are in the same file, I'll group them" | Grouping hides findings. One fix may be done, others forgotten. | **One finding = One task. No exceptions.** | -| "Grouping reduces task count and is easier to manage" | Fewer tasks = less visibility. Each finding needs independent tracking. | **Create one REFACTOR-XXX per FINDING-XXX** | -| "These are related and should be fixed together" | Related ≠ same task. Dev-cycle can execute them sequentially. | **Separate tasks, use Dependencies field to link** | -| "Too many tasks will overwhelm the developer" | Missing fixes overwhelms production. Completeness > convenience. | **Create all tasks. Priority handles ordering.** | +|---|---|---| +| "Just keep 1:1 mapping, it's simpler" | 1:1 mapping multiplies cycle cost ~5x for typical refactors. Clustering preserves traceability. | **Apply (file, pattern) clustering** | +| "Cluster across files to reduce tasks more" | Cross-file clustering hides file-specific blast radius. Only cluster within a file. | **Cluster only within file** | +| "Skip the findings: array, it's redundant" | Without traceability array, findings get lost inside tasks. | **ALWAYS populate findings: array** | +| "One finding can be in multiple tasks" | Duplicates cause double-fix attempts. One finding → one task. | **Each FINDING in exactly one REFACTOR** | **TodoWrite:** Mark "Map findings 1:1 to REFACTOR-XXX tasks" as `completed` @@ -898,16 +924,17 @@ Before proceeding to Step 7, verify: **Source:** findings.md **Total Tasks:** {count} -## ⛔ Mandatory 1:1 Mapping Verification +## ⛔ Mandatory Clustering Traceability Verification -**Every FINDING-XXX has exactly one REFACTOR-XXX. No grouping.** +**Findings are clustered by (file, pattern_category). Every FINDING-XXX appears in exactly one REFACTOR-XXX via its `findings:` array.** | Metric | Count | |--------|-------| | Total FINDING-XXX in findings.md | {X} | -| Total REFACTOR-XXX in tasks.md | {X} | -| **Counts match exactly?** | ✅ YES (REQUIRED) | -| Grouped tasks (multiple findings) | 0 (REQUIRED) | +| Total REFACTOR-XXX in tasks.md | {Y} (Y ≤ X — clustering reduces count) | +| **Every finding appears in exactly one task?** | ✅ YES (REQUIRED) | +| Orphan findings (in zero tasks) | 0 (REQUIRED) | +| Duplicate findings (in 2+ tasks) | 0 (REQUIRED) | **Priority affects execution order, not whether to include:** - Critical/High tasks: Execute first @@ -916,19 +943,26 @@ Before proceeding to Step 7, verify: --- -## REFACTOR-001: {Finding Pattern Name} +## REFACTOR-001: {Finding Pattern Name} in {file_path} -**Finding:** FINDING-001 -**Severity:** Critical | High | Medium | Low (all ARE MANDATORY) +**Cluster Key:** ({file_path}, {pattern_category}) +**Findings Covered:** [FINDING-XXX, FINDING-YYY, ...] +**Severity:** Critical | High | Medium | Low (max of covered findings' severities; all ARE MANDATORY) **Category:** {lib-commons | architecture | testing | devops} **Agent:** {agent-name} -**Effort:** {hours}h +**Effort:** {hours}h (sum of covered findings' effort estimates) **Dependencies:** {other REFACTOR-XXX tasks or none} +### Findings Breakdown +| Finding | Line | Description | Status | +|---------|------|-------------|--------| +| FINDING-XXX | {file}:{line} | {short description} | pending | +| FINDING-YYY | {file}:{line} | {short description} | pending | + ### Current Code ```{lang} // file: {path}:{lines} -{actual code from FINDING-001} +{representative code from covered findings} ``` ### Ring Standard Reference @@ -943,6 +977,7 @@ Before proceeding to Step 7, verify: ### Acceptance Criteria - [ ] Code follows {standard}.md → {section} pattern - [ ] No {anti-pattern} usage remains +- [ ] All covered findings resolved (status: done for each row in Findings Breakdown) - [ ] Tests pass after refactoring ``` @@ -1052,6 +1087,10 @@ Skill tool: skill: "ring:dev-cycle" ``` +Note: Each REFACTOR task covering N findings is treated as ONE execution unit with N +internal acceptance criteria. dev-cycle does not need to know about clustering — it +consumes the task as-if it were any other task. + **⛔ CRITICAL: Pass tasks file path in context:** After invoking the skill, provide: diff --git a/dev-team/skills/dev-report/SKILL.md b/dev-team/skills/dev-report/SKILL.md index decac6e8..fe3933ef 100644 --- a/dev-team/skills/dev-report/SKILL.md +++ b/dev-team/skills/dev-report/SKILL.md @@ -6,14 +6,12 @@ description: | on failures, and generates improvement reports to docs/feedbacks/cycle-{date}/. trigger: | - - After task completion (any gate outcome) - - After validation approval or rejection - - At end of development cycle - - When assertiveness drops below threshold + - Invoked EXACTLY ONCE per dev-cycle at Step 12.1 of ring:dev-cycle (and equivalent in ring:dev-cycle-frontend). + - Per-task invocations at Step 11.2 were REMOVED in R4 — per-task metrics are accumulated into state.tasks[*].accumulated_metrics and analyzed in aggregate here. skip_when: | - - Task still in progress -> wait for completion - - Feedback already recorded for this task -> proceed + - Cycle still in progress -> wait for Step 12.1 (cycle completion) + - Feedback already recorded for this cycle -> proceed NOT_skip_when: | - "Exploratory/spike work" → all work produces learnings. Track metrics for spikes too. @@ -32,6 +30,8 @@ related: See [CLAUDE.md](https://raw.githubusercontent.com/LerianStudio/ring/main/CLAUDE.md) for canonical validation and gate requirements. This skill collects metrics and generates improvement reports. +**Invocation Contract (since R4 of "prancy Bentley" speedup):** This skill is invoked EXACTLY ONCE per dev-cycle, at Step 12.1 of ring:dev-cycle (and equivalent in ring:dev-cycle-frontend). Per-task invocations at Step 11.2 have been REMOVED. This skill expects aggregated data spanning ALL tasks in the cycle. + Continuous improvement system that tracks development cycle effectiveness through assertiveness scores, identifies recurring failure patterns, and generates actionable improvement suggestions. **Core principle:** What gets measured gets improved. Track every gate transition to identify systemic issues. @@ -271,7 +271,34 @@ Base score of 100 points, with deductions for inefficiencies: **Anti-exemption check:** If you're thinking "perfect outcome, skip metrics" → STOP. This is Red Flag at line 75 ("Perfect outcome, skip the metrics"). -**After task completion, gather from `agent_outputs` in state file:** +**After cycle completion, gather from `agent_outputs` in state file:** + +### New (R4): `state.tasks[*].accumulated_metrics` + +Per-task metrics accumulated during the cycle at each task's approval checkpoint (Step 11.2 of ring:dev-cycle). Use these to construct the cycle-wide analysis instead of single-task analysis. + +**Semantic shift:** Analyze ALL tasks' aggregated metrics + the full `agent_outputs` for the cycle, not a single task's data. + +Per-task fields under `state.tasks[i].accumulated_metrics`: +- `gate_durations_ms`: {gate_name: duration_ms for each completed gate} +- `review_iterations`: review iterations for this task +- `testing_iterations`: sum across all testing gates (unit, fuzz, property, integration, chaos) +- `issues_by_severity`: {CRITICAL, HIGH, MEDIUM, LOW counts from Gate 8 output} + +**Aggregation pattern for cycle-wide analysis:** + +```yaml +# Sum across all tasks in the cycle: +cycle_gate_durations_ms = sum(t.accumulated_metrics.gate_durations_ms for t in state.tasks) +cycle_review_iterations = sum(t.accumulated_metrics.review_iterations for t in state.tasks) +cycle_testing_iterations = sum(t.accumulated_metrics.testing_iterations for t in state.tasks) +cycle_issues_by_severity = { + "CRITICAL": sum(t.accumulated_metrics.issues_by_severity.CRITICAL for t in state.tasks), + "HIGH": sum(t.accumulated_metrics.issues_by_severity.HIGH for t in state.tasks), + "MEDIUM": sum(t.accumulated_metrics.issues_by_severity.MEDIUM for t in state.tasks), + "LOW": sum(t.accumulated_metrics.issues_by_severity.LOW for t in state.tasks), +} +``` ### Structured Data Fields (NEW) @@ -339,7 +366,7 @@ extra_iterations = ( ## Step 3: Analyze Prompt Quality (Agents Only) -After calculating assertiveness, analyze prompt quality for all **agents** that executed in the task. +After calculating assertiveness, analyze prompt quality for all **agents** that executed in the cycle (across all tasks). ### 3.1 Load Agent Outputs @@ -364,20 +391,33 @@ Analyze prompt quality for all agents executed in this task. Task tool: subagent_type: "ring:prompt-quality-reviewer" prompt: | - Analyze prompt quality for agents in task [task_id]. + CONTEXT: You are analyzing a COMPLETE dev-cycle across N tasks (not a single task). + The data you receive spans all tasks in the cycle. Since R4 of the + "prancy Bentley" speedup, ring:dev-report is invoked exactly ONCE per cycle + (Step 12.1 of ring:dev-cycle), so aggregate-level analysis is the expected mode. - Agent outputs from state: - [agent_outputs] + Cycle: [cycle_id] + Tasks analyzed: [task_ids] (N total) - For each agent: + Aggregated cycle metrics (sum across all tasks' accumulated_metrics): + gate_durations_ms: [cycle_gate_durations_ms] + review_iterations: [cycle_review_iterations] + testing_iterations: [cycle_testing_iterations] + issues_by_severity: [cycle_issues_by_severity] + + Full agent_outputs history for the cycle (all tasks, all gates): + [agent_outputs] # from state.tasks[*].agent_outputs (not a single task subset) + + For each agent that executed in the cycle: 1. Load definition from dev-team/agents/ or default/agents/ 2. Extract rules: MUST, MUST not, ask_when, output_schema - 3. Compare output vs rules - 4. Calculate score - 5. Identify gaps with evidence - 6. Generate improvements + 3. Compare each output invocation vs rules (across all tasks) + 4. Calculate aggregate score (average across invocations) + 5. Identify recurring gaps with evidence (quote task IDs + gate) + 6. Generate cycle-level improvements prioritized by occurrence count - Return structured analysis per agent. + Return structured analysis per agent, with per-task evidence rolled into + cycle-wide patterns. ``` ### 3.3 Write Feedback Files diff --git a/dev-team/skills/dev-sre/SKILL.md b/dev-team/skills/dev-sre/SKILL.md index baf25ea7..73f26743 100644 --- a/dev-team/skills/dev-sre/SKILL.md +++ b/dev-team/skills/dev-sre/SKILL.md @@ -3,6 +3,7 @@ name: ring:dev-sre description: | Gate 2 of the development cycle. VALIDATES that observability was correctly implemented by developers. Does not implement observability code - only validates it. + Runs at TASK cadence (after all subtasks complete Gate 0 + Gate 3 + Gate 9). trigger: | - Gate 2 of development cycle @@ -32,7 +33,7 @@ input_schema: required: - name: unit_id type: string - description: "Task or subtask identifier being validated" + description: "TASK identifier (not a subtask id). This skill runs at TASK cadence — unit_id is always a task id." - name: language type: string enum: [go, typescript, python] @@ -47,15 +48,15 @@ input_schema: - name: implementation_files type: array items: string - description: "List of files created/modified in Gate 0" + description: "Union of changed files across all subtasks of this task." + - name: gate0_handoffs + type: array + description: "Array of per-subtask implementation handoffs (one entry per subtask). NOT a single gate0_handoff object." optional: - name: external_dependencies type: array items: string description: "External services called (HTTP, gRPC, queues)" - - name: gate0_handoff - type: object - description: "Summary from Gate 0 implementation" - name: gate1_handoff type: object description: "Summary from Gate 1 DevOps setup" @@ -142,15 +143,15 @@ This skill VALIDATES that observability was correctly implemented by developers: ```text REQUIRED INPUT (from ring:dev-cycle orchestrator): -- unit_id: [task/subtask being validated] +- unit_id: [TASK id — runs at task cadence, not per subtask] - language: [go|typescript|python] - service_type: [api|worker|batch|cli|library] - implementation_agent: [agent that did Gate 0] -- implementation_files: [list of files from Gate 0] +- implementation_files: [union of changed files across all subtasks of this task] +- gate0_handoffs: [array of per-subtask Gate 0 handoffs — one entry per subtask] OPTIONAL INPUT: - external_dependencies: [HTTP clients, gRPC clients, queues] -- gate0_handoff: [summary from Gate 0] - gate1_handoff: [summary from Gate 1] if any REQUIRED input is missing: @@ -191,8 +192,22 @@ Task: - **Files to Validate:** [implementation_files] - **External Dependencies:** [external_dependencies or "None"] + ## Standards Source (Cache-First Pattern) + + **Standards Source (Cache-First Pattern):** This sub-skill reads standards from `state.cached_standards` populated by dev-cycle Step 1.5. If invoked outside a cycle (standalone), it falls back to direct WebFetch with a warning. See `shared-patterns/standards-cache-protocol.md` for protocol details. + ## Standards Reference - WebFetch: https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/sre.md + + URL: https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/sre.md + + **Cache-first loading protocol:** + For each required standards URL: + IF state.cached_standards[url] exists: + → Read content from state.cached_standards[url].content + → Log: "Using cached standard: {url} (fetched {state.cached_standards[url].fetched_at})" + ELSE: + → WebFetch url (fallback — should not happen if orchestrator ran Step 1.5) + → Log warning: "Standard {url} was not pre-cached; fetched inline" ## Your Role - VALIDATE that observability is implemented correctly diff --git a/dev-team/skills/dev-unit-testing/SKILL.md b/dev-team/skills/dev-unit-testing/SKILL.md index ce5d4257..82da457c 100644 --- a/dev-team/skills/dev-unit-testing/SKILL.md +++ b/dev-team/skills/dev-unit-testing/SKILL.md @@ -204,10 +204,24 @@ Task: ## Implementation Files to Test [list implementation_files] + ## Standards Source (Cache-First Pattern) + + **Standards Source (Cache-First Pattern):** This sub-skill reads standards from `state.cached_standards` populated by dev-cycle Step 1.5. If invoked outside a cycle (standalone), it falls back to direct WebFetch with a warning. See `shared-patterns/standards-cache-protocol.md` for protocol details. + ## Standards Reference + For Go: https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/golang.md For TS: https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/typescript.md + **Cache-first loading protocol:** + For each required standards URL: + IF state.cached_standards[url] exists: + → Read content from state.cached_standards[url].content + → Log: "Using cached standard: {url} (fetched {state.cached_standards[url].fetched_at})" + ELSE: + → WebFetch url (fallback — should not happen if orchestrator ran Step 1.5) + → Log warning: "Standard {url} was not pre-cached; fetched inline" + Focus on: Testing Patterns section ## Requirements diff --git a/dev-team/skills/dev-validation/SKILL.md b/dev-team/skills/dev-validation/SKILL.md index ac0def87..abba9a9e 100644 --- a/dev-team/skills/dev-validation/SKILL.md +++ b/dev-team/skills/dev-validation/SKILL.md @@ -2,7 +2,8 @@ name: ring:dev-validation description: | Development cycle validation gate (Gate 5) - validates all acceptance criteria are met - and requires explicit user approval before completion. + and requires explicit user approval before completion. Runs at subtask (execution unit) + cadence. Task-level approval happens in dev-cycle Step 11.2. trigger: | - After review gate passes (Gate 4) diff --git a/dev-team/skills/shared-patterns/gate-cadence-classification.md b/dev-team/skills/shared-patterns/gate-cadence-classification.md new file mode 100644 index 00000000..85229c71 --- /dev/null +++ b/dev-team/skills/shared-patterns/gate-cadence-classification.md @@ -0,0 +1,46 @@ +--- +name: shared-pattern:gate-cadence-classification +description: Classification of dev-cycle gates by execution cadence (subtask/task/cycle). +--- + +# Gate Cadence Classification + +## Three Cadences + +### Subtask Cadence +Runs for every subtask (or task itself if no subtasks). Input scoped to a single unit. +- Backend: Gate 0 (Implementation + delivery verify), Gate 3 (Unit Testing), Gate 9 (Validation) +- Frontend: Gate 0 (Implementation), Gate 3 (Unit Testing), Gate 8 (Validation) + +### Task Cadence +Runs once per task, after all subtasks complete their subtask-level gates. Input is +UNION of all subtasks' changes. +- Backend: Gate 1 (DevOps), Gate 2 (SRE), Gate 4 (Fuzz), Gate 5 (Property), Gate 6 write + (Integration), Gate 7 write (Chaos), Gate 8 (Review — 8 reviewers) +- Frontend: Gate 1 (DevOps), Gate 2 (Accessibility), Gate 4 (Visual), Gate 5 (E2E), + Gate 6 (Performance), Gate 7 (Review — 5 reviewers) + +### Cycle Cadence +Runs once per cycle at cycle end. +- Backend: Gate 6 execute (Integration), Gate 7 execute (Chaos), Multi-Tenant Verify, + dev-report, Final Commit +- Frontend: Final Commit (minimal cycle-level processing) + +## Why Cadence Matters + +Running task-cadence gates at subtask cadence causes redundant work: Dockerfile +validation, observability coverage checks, fuzz seed generation, and cumulative diff +review all have outputs that stabilize at the task boundary, not the subtask boundary. +The task-level cumulative diff is strictly more informative for review than N +per-subtask fragments because interaction bugs between subtasks are visible only in +the cumulative view. + +## Implementation Requirement + +Sub-skills that run at task cadence MUST accept aggregated input: +- `implementation_files`: array (union across all subtasks of the task) +- `gate0_handoffs`: array (one entry per subtask) + +Sub-skills that run at subtask cadence MUST continue to accept scoped input: +- `implementation_files`: array (this subtask's changes only) +- `gate0_handoff`: object (this subtask's handoff) diff --git a/dev-team/skills/shared-patterns/shared-orchestrator-principle.md b/dev-team/skills/shared-patterns/shared-orchestrator-principle.md index be568f7b..df5cce49 100644 --- a/dev-team/skills/shared-patterns/shared-orchestrator-principle.md +++ b/dev-team/skills/shared-patterns/shared-orchestrator-principle.md @@ -96,6 +96,23 @@ This principle is NON-NEGOTIABLE for all dev-team skills. ✅ Task(subagent_type="ring:finops-automation", ...) ``` +## Gate Cadence Classification + +Gates in dev-cycle operate at three cadences: + +| Cadence | Gates (backend) | Gates (frontend) | +|---------|-----------------|------------------| +| **Subtask** | 0 (impl + delivery verify), 3 (unit test), 9 (validation) | 0, 3, 8 | +| **Task** | 1 (devops), 2 (sre), 4 (fuzz), 5 (property), 6 write, 7 write, 8 (review) | 1, 2, 4, 5, 6, 7 | +| **Cycle** | 6 execute, 7 execute, multi-tenant verify, dev-report, final commit | (minimal cycle-level) | + +Sub-skills that run at task cadence receive input aggregated across all subtasks of +the task (e.g., `implementation_files` = UNION of all subtasks' changed files). + +Sub-skills that run at subtask cadence receive input scoped to that single subtask. + +See `shared-patterns/gate-cadence-classification.md` for the full classification and rationale. + ## Gate/Step → Agent Mapping ### ring:dev-cycle Gates diff --git a/dev-team/skills/shared-patterns/standards-cache-protocol.md b/dev-team/skills/shared-patterns/standards-cache-protocol.md new file mode 100644 index 00000000..c2d88850 --- /dev/null +++ b/dev-team/skills/shared-patterns/standards-cache-protocol.md @@ -0,0 +1,57 @@ +--- +name: shared-pattern:standards-cache-protocol +description: Protocol for reading cached standards from cycle state instead of WebFetching directly. +--- + +# Standards Cache Protocol + +## Purpose + +Eliminate redundant WebFetch calls during a dev-cycle by pre-caching all required +standards at cycle start (dev-cycle Step 1.5) and having sub-skills read from state. + +## Protocol + +### For Sub-Skills + +When a sub-skill needs a standards document: + +```yaml +STEP 1: Check state cache + IF state.cached_standards[URL] exists: + content = state.cached_standards[URL].content + log: "Using cached standard: {URL} (fetched {fetched_at})" + proceed with content + ELSE: + goto STEP 2 + +STEP 2: Fallback WebFetch (only if cache miss) + log WARNING: "Standard {URL} not in cache; fetching inline" + content = WebFetch(URL) + proceed with content +``` + +### For Orchestrators (dev-cycle, dev-cycle-frontend) + +At Step 1.5 of the cycle: +1. Detect project stack (Go / TypeScript / Frontend) +2. Build URL list (see dev-cycle Step 1.5 for current list) +3. WebFetch each URL once +4. Write to `state.cached_standards[URL] = {fetched_at, content}` +5. MANDATORY: Save state to file +6. Blocker if ANY URL fails to fetch + +## Why + +Before: ~15–25 WebFetch calls per cycle (one per sub-skill dispatch). Prompt cache TTL +of 5 min is regularly exceeded, causing repeated network fetches of identical content. + +After: Exactly ONE WebFetch per unique URL per cycle. Same content, ~5x fewer network +operations. + +## Safety + +If the cache mechanism fails or is bypassed: +- Sub-skills fall back to direct WebFetch (with warning log). +- No correctness regression; only performance regression. +- Operators can monitor "Standard {URL} not in cache" warnings to detect misconfigurations. diff --git a/dev-team/skills/shared-patterns/standards-coverage-table.md b/dev-team/skills/shared-patterns/standards-coverage-table.md index bb59b53e..5b3e5b88 100644 --- a/dev-team/skills/shared-patterns/standards-coverage-table.md +++ b/dev-team/skills/shared-patterns/standards-coverage-table.md @@ -4,6 +4,18 @@ This file defines the MANDATORY output format for agents comparing codebases aga --- +## Standards Source (new, since "prancy Bentley" speedup) + +Agents and sub-skills MUST read standards from `state.cached_standards` (populated by +dev-cycle Step 1.5) instead of calling WebFetch directly. This eliminates ~15–25 +redundant network fetches per cycle. + +If a sub-skill is invoked outside of a dev-cycle context (standalone testing, manual +dispatch), it MAY fall back to direct WebFetch — but it MUST log a warning and +operators should expect slower execution. + +--- + ## ⛔ CRITICAL: All Sections Are Required **This is NON-NEGOTIABLE. Every section listed in the Agent → Standards Section Index below MUST be checked.**