kind: WavePipeline metadata: name: recinq description: "Rethink and simplify code using divergent-convergent thinking (Double Diamond)" release: true input: source: cli example: "internal/pipeline" # Pipeline structure implements the Double Diamond: # # gather → diverge → converge → probe → distill → simplify → report # ╰─ Diamond 1 ─╯ ╰─ Diamond 2 ─╯ ╰implement╯ # (discover) (define) (develop) (deliver) # # Each step gets its own context window and cognitive mode. # Fresh memory at every boundary — no mode-switching within a step. steps: - id: gather persona: github-analyst workspace: mount: - source: ./ target: /project mode: readonly exec: type: prompt source: | CONTEXT GATHERING — parse input and fetch GitHub context if applicable. Input: {{ input }} ## Instructions Determine what kind of input this is: 1. **GitHub Issue URL**: Contains `github.com` and `/issues/` - Extract owner/repo and issue number from the URL - Run: `gh issue view --repo --json title,body,labels` - Extract a `focus_hint` summarizing what should be simplified 2. **GitHub PR URL**: Contains `github.com` and `/pull/` - Extract owner/repo and PR number from the URL - Run: `gh pr view --repo --json title,body,labels,files` - Extract a `focus_hint` summarizing what the PR is about 3. **Local path or description**: Anything else - Set `input_type` to `"local"` - Pass through the original input as-is ## Output IMPORTANT: The output MUST be valid JSON. Do NOT include markdown fencing. output_artifacts: - name: context path: .wave/output/context.json type: json handover: contract: type: json_schema source: .wave/output/context.json schema_path: .wave/contracts/recinq-context.schema.json must_pass: true on_failure: retry max_retries: 2 # ── Diamond 1: Discover (DIVERGENT) ────────────────────────────────── - id: diverge persona: provocateur dependencies: [gather] memory: inject_artifacts: - step: gather artifact: context as: context workspace: mount: - source: ./ target: /project mode: readonly exec: type: prompt source: | DIVERGENT THINKING — cast the widest net to find simplification opportunities. Target: {{ input }} ## Starting Point The context artifact contains input context. If `input_type` is `"issue"` or `"pr"`, the `focus_hint` tells you WHERE to start looking — but do NOT limit yourself to what the issue describes. Use it as a seed, then expand outward. Follow dependency chains, trace callers, explore adjacent modules. The issue author doesn't know what they don't know — that's YOUR job. If `input_type` is `"local"`, use the `original_input` field as the target path. If input is empty or "." — analyze the whole project. If input is a path — focus on that module/directory but consider its connections. ## Your Mission Challenge EVERYTHING. Question every assumption. Hunt complexity. ## What to Look For 1. **Premature abstractions**: Interfaces with one implementation. Generic code used once. "What if we just inlined this?" 2. **Unnecessary indirection**: Layers that pass-through without adding value. Wrappers around wrappers. "How many hops to get to the actual logic?" 3. **Overengineering**: Configuration for things that never change. Plugins with one plugin. Feature flags for features that are always on. "Is this complexity earning its keep?" 4. **YAGNI violations**: Code written for hypothetical future needs that never arrived. "When was this last changed? Does anyone actually use this path?" 5. **Accidental complexity**: Things that are hard because of how they're built, not because the problem is hard. "Could this be 10x simpler if we started over?" 6. **Copy-paste drift**: Similar-but-slightly-different code that should be unified or intentionally differentiated. "Are these differences meaningful or accidental?" 7. **Dead weight**: Unused exports, unreachable code, obsolete comments, stale TODOs. `grep -r` for references. If nothing uses it, flag it. 8. **Naming lies**: Names that don't match what the code actually does. "Does this 'manager' actually manage anything?" 9. **Dependency gravity**: Modules that pull in everything. Import graphs that are too dense. "What's the blast radius of changing this?" ## Evidence Requirements For EVERY finding, gather concrete metrics: - `wc -l` for line counts - `grep -r` for usage/reference counts - `git log --oneline | wc -l` for change frequency - List the actual files involved ## Output Each finding gets a unique ID: DVG-001, DVG-002, etc. Be AGGRESSIVE — flag everything suspicious. The convergent phase will filter. It's better to have 30 findings with 10 false positives than 5 findings that miss the big opportunities. Include a metrics_summary with totals by category and severity, plus hotspot files that appear in multiple findings. output_artifacts: - name: findings path: .wave/output/divergent-findings.json type: json handover: contract: type: json_schema source: .wave/output/divergent-findings.json schema_path: .wave/contracts/divergent-findings.schema.json must_pass: true on_failure: retry max_retries: 2 # ── Diamond 1: Define (CONVERGENT) ─────────────────────────────────── - id: converge persona: validator dependencies: [diverge] memory: inject_artifacts: - step: diverge artifact: findings as: divergent_findings workspace: mount: - source: ./ target: /project mode: readonly exec: type: prompt source: | CONVERGENT VALIDATION — separate signal from noise. This is a purely CONVERGENT step. Your job is analytical, not creative. Judge every finding on technical merit alone. No speculation, no new ideas. Target: {{ input }} ## For Every DVG-xxx Finding 1. **Read the actual code** cited as evidence — don't trust the provocateur's summary 2. **Verify the metrics** — check reference counts, line counts, change frequency 3. **Assess**: Is this a real problem or a false positive? - Does the "premature abstraction" actually have a second implementation planned? - Is the "dead weight" actually used via reflection or codegen? - Is the "unnecessary indirection" actually providing error handling or logging? 4. **Classify**: - `CONFIRMED` — real problem, metrics check out, code supports the claim - `PARTIALLY_CONFIRMED` — real concern but overstated, or scope is narrower than claimed - `REJECTED` — false positive, justified complexity, or incorrect metrics 5. **Explain**: For every classification, write WHY. For rejections, explain what the provocateur got wrong. Be RIGOROUS. The provocateur was told to be aggressive — your job is to be skeptical. A finding that survives your scrutiny is genuinely worth addressing. output_artifacts: - name: validated_findings path: .wave/output/validated-findings.json type: json handover: contract: type: json_schema source: .wave/output/validated-findings.json schema_path: .wave/contracts/validated-findings.schema.json must_pass: true on_failure: retry max_retries: 2 # ── Diamond 2: Develop (DIVERGENT) ─────────────────────────────────── - id: probe persona: provocateur dependencies: [converge] memory: inject_artifacts: - step: diverge artifact: findings as: divergent_findings - step: converge artifact: validated_findings as: validated_findings workspace: mount: - source: ./ target: /project mode: readonly exec: type: prompt source: | SECOND DIVERGENCE — probe deeper into confirmed findings. The first pass cast a wide net. The validator filtered it down. Now YOU go deeper on what survived. This is DIVERGENT thinking again — expand, connect, discover what the first pass missed. Focus on findings with status CONFIRMED or PARTIALLY_CONFIRMED. Target: {{ input }} ## Your Mission For each confirmed finding, probe OUTWARD: 1. **Trace the dependency graph**: What calls this code? What does it call? If we simplify X, what happens to its callers and callees? 2. **Find second-order effects**: If we remove abstraction A, does layer B also become unnecessary? Do test helpers simplify? Do error paths collapse? 3. **Spot patterns across findings**: Do three findings all stem from the same over-abstraction? Is there a root cause that would address multiple DVGs at once? 4. **Discover what was MISSED**: With the validated findings as context, look for related opportunities the first pass didn't see. The confirmed findings reveal the codebase's real pressure points — what else lurks nearby? 5. **Challenge the rejections**: Were any findings rejected too hastily? Read the validator's rationale — do you disagree? ## Evidence Requirements Same standard as the first diverge pass: - `wc -l` for line counts - `grep -r` for usage/reference counts - `git log --oneline | wc -l` for change frequency - Concrete file paths and code references ## Output Go DEEP. The first pass was wide, this pass is deep. Follow every thread. output_artifacts: - name: probed_findings path: .wave/output/probed-findings.json type: json handover: contract: type: json_schema source: .wave/output/probed-findings.json schema_path: .wave/contracts/probed-findings.schema.json must_pass: true on_failure: retry max_retries: 2 # ── Diamond 2: Deliver (CONVERGENT) ────────────────────────────────── - id: distill persona: synthesizer dependencies: [probe] memory: inject_artifacts: - step: gather artifact: context as: context - step: converge artifact: validated_findings as: validated_findings - step: probe artifact: probed_findings as: probed_findings workspace: mount: - source: ./ target: /project mode: readonly exec: type: prompt source: | FINAL CONVERGENCE — synthesize all findings into actionable proposals. This is the last convergent step before implementation. You have: - Validated findings (what survived scrutiny) - Probed findings (deeper connections, patterns, new discoveries) - Optional issue/PR context (from the gather step) Your job: synthesize everything into prioritized, implementable proposals. Target: {{ input }} ## Synthesis Transform the validated and probed findings into prioritized proposals: 1. **Group by pattern**: Use the `patterns` from the probe step. Findings that share a root cause become a single proposal addressing the root cause. 2. **Incorporate second-order effects**: The probe step found connections and cascading simplifications. Factor these into impact estimates. 3. **Include new discoveries**: The probe step may have found new findings (DVG-NEW-xxx). These are pre-validated by the provocateur's second pass — include them. 4. **Apply issue/PR context (if present)**: If the context artifact shows `input_type` is `"issue"` or `"pr"`, use the `focus_hint` as ONE input when assigning tiers. But do not discard strong proposals just because they fall outside the issue's scope. The best simplifications are often the ones the issue author didn't think to ask for. 5. **80/20 analysis**: which 20% of proposals yield 80% of the simplification? 6. **Dependency ordering**: what must be done first? ## Output Do NOT write a markdown summary. Write the complete JSON object with every proposal fully populated. output_artifacts: - name: proposals path: .wave/output/convergent-proposals.json type: json handover: contract: type: json_schema source: .wave/output/convergent-proposals.json schema_path: .wave/contracts/convergent-proposals.schema.json must_pass: true on_failure: retry max_retries: 2 # ── Implementation ─────────────────────────────────────────────────── - id: simplify persona: craftsman dependencies: [distill] memory: inject_artifacts: - step: converge artifact: validated_findings as: validated_findings - step: distill artifact: proposals as: proposals workspace: type: worktree branch: "refactor/{{ pipeline_id }}" exec: type: prompt source: | IMPLEMENTATION — apply the best simplification proposals. ## Process Apply ONLY tier-1 proposals, in dependency order. For each proposal (SMP-xxx): 1. **Announce**: Print which proposal you're applying and what it does 2. **Apply**: Make the code changes 3. **Build**: `go build ./...` — must succeed 4. **Test**: `go test ./...` — must pass 5. **Commit**: If build and tests pass: ```bash git add git commit -m "refactor: Applies SMP-xxx: Source findings: " ``` 6. **Revert if failing**: If tests fail after applying, revert: ```bash git checkout -- . ``` Log the failure and move to the next proposal. ## Final Verification After all tier-1 proposals are applied (or attempted): 1. Run the full test suite: `go test -race ./...` 2. Run the build: `go build ./...` 3. Summarize what was applied, what was skipped, and net lines changed ## Important - Each proposal gets its own atomic commit - Never combine proposals in a single commit - If a proposal depends on a failed proposal, skip it too - Commit each proposal as a separate atomic commit handover: contract: type: test_suite command: "{{ project.test_command }}" must_pass: true on_failure: retry max_retries: 3 output_artifacts: - name: result path: .wave/output/result.md type: markdown # ── Reporting ──────────────────────────────────────────────────────── - id: report persona: navigator dependencies: [simplify] memory: inject_artifacts: - step: distill artifact: proposals as: proposals - step: simplify artifact: result as: result workspace: type: worktree branch: "refactor/{{ pipeline_id }}" exec: type: prompt source: | REPORT — compose a summary of what recinq found and applied. Run `git log --oneline` to see the commits on this branch. ## Compose the Report Write a markdown report containing: - **Summary**: One-paragraph overview of what recinq found and applied - **Proposals**: List of all proposals with their tier, impact, and status (applied/skipped/failed) - **Changes Applied**: Summary of commits made, files changed, net lines removed - **Remaining Opportunities**: Tier-2 and tier-3 proposals for future consideration output_artifacts: - name: report path: .wave/output/report.md type: markdown # ── Publish ───────────────────────────────────────────────────────── - id: publish persona: craftsman dependencies: [report, gather] memory: inject_artifacts: - step: gather artifact: context as: context - step: report artifact: report as: report workspace: type: worktree branch: "refactor/{{ pipeline_id }}" exec: type: prompt source: | PUBLISH — push the branch and create a pull request. ## Steps 1. Push the branch: ```bash git push -u origin HEAD ``` 2. Create a pull request using the report as the body: ```bash gh pr create --title "refactor: $(git log --format=%s -1)" --body-file .wave/artifacts/report ``` 3. If the context artifact shows `input_type` is `"issue"` or `"pr"`, post the PR URL as a comment on the source: ```bash gh issue comment --repo --body "Refactoring PR: " ``` or for PRs: ```bash gh pr comment --repo --body "Refactoring PR: " ``` 4. Write the JSON status report to the output artifact path. If any `gh` command fails, log the error and continue. output_artifacts: - name: pr-result path: .wave/output/pr-result.json type: json handover: contract: type: json_schema source: .wave/output/pr-result.json schema_path: .wave/contracts/pr-result.schema.json must_pass: true on_failure: retry max_retries: 2 outcomes: - type: pr extract_from: .wave/output/pr-result.json json_path: .pr_url label: "Pull Request"