Skip to content

feat: structured dead-code detection pipeline with multi-mode output#149

Closed
nextlevelshit wants to merge 470 commits intomainfrom
135-dead-code-pipeline
Closed

feat: structured dead-code detection pipeline with multi-mode output#149
nextlevelshit wants to merge 470 commits intomainfrom
135-dead-code-pipeline

Conversation

@nextlevelshit
Copy link
Copy Markdown
Collaborator

Summary

  • Rewrote the dead-code detection pipeline into a family of 4 pipelines: scan-only (dead-code.yaml), PR comment (dead-code-pr.yaml), GitHub issue (dead-code-issue.yaml), and heal (dead-code-heal.yaml)
  • Expanded the dead-code-scan.schema.json contract with new detection categories (duplicate, stale_glue, hardcoded_value), line range support, and suggested actions
  • Added three new output contract schemas: dead-code-report, dead-code-pr-result, and dead-code-issue-result
  • Extended the github-commenter persona permissions in wave.yaml to support PR commenting
  • Added comprehensive unit tests for schema validation and pipeline YAML parsing

Closes #135

Changes

  • .wave/contracts/dead-code-scan.schema.json — Expanded with new categories, line_range, suggested_action fields
  • .wave/contracts/dead-code-report.schema.json — New schema for formatted markdown report output
  • .wave/contracts/dead-code-pr-result.schema.json — New schema for PR comment posting result
  • .wave/contracts/dead-code-issue-result.schema.json — New schema for GitHub issue creation result
  • .wave/pipelines/dead-code.yaml — Rewritten as scan-only + local format pipeline (removed clean/verify/create-pr steps)
  • .wave/pipelines/dead-code-pr.yaml — New pipeline: scan + format + publish PR comment
  • .wave/pipelines/dead-code-issue.yaml — New pipeline: scan + format + create GitHub issue
  • .wave/pipelines/dead-code-heal.yaml — New pipeline: extracted heal flow from original dead-code pipeline
  • wave.yaml — Extended github-commenter persona with gh pr comment* permission
  • internal/contract/dead_code_schemas_test.go — Schema validation tests for all contract schemas
  • internal/pipeline/dead_code_pipelines_test.go — Pipeline YAML parse and dependency resolution tests
  • specs/135-dead-code-pipeline/ — Spec, plan, and task artifacts

Test Plan

  • Schema validation tests cover all new categories (duplicate, stale_glue, hardcoded_value), new fields (line_range, suggested_action), and backward compatibility with existing payloads
  • Pipeline YAML parse tests verify all 4 pipelines load correctly, resolve step dependencies, and reference valid personas
  • All tests located in internal/contract/ and internal/pipeline/ packages

nextlevelshit and others added 30 commits February 6, 2026 16:07
…order

Replace map[string]string with ordered slice for test data inserts so
parent rows (pipeline_run) are always inserted before child rows
(performance_metric) that reference them via foreign key.
…fact output

Persona constraints like "NEVER write any files" prevented LLMs from
writing pipeline output artifacts. Permission enforcement is handled
mechanically by the executor via AllowedTools, not by prompt-level
restrictions. Replace blanket prohibitions with role-focused guidance.
Sync 5 personas (3 mismatched, 2 missing), 2 pipelines (missing),
and 17 contracts (1 mismatched, 16 missing) that had drifted between
.wave/ and internal/defaults/.
…ipeline

Completely rewrites the speckit-flow pipeline with fixes discovered through
iterative end-to-end testing of all 6 spec-building steps. Adds speckit
slash commands as .claude/commands for use by pipeline personas.

Key fixes:
- Switch all spec steps to implementer persona (philosopher has Bash denied)
- Add cd to project root instruction in every prompt (workspace is isolated)
- Inject specify output artifact into all subsequent steps for context
- Each step writes structured JSON status report as output artifact

Steps 1-6 (specify→clarify→plan→tasks→checklist→analyze) tested and
confirmed working end-to-end with consistent ~270-540s step times.
Replace buffered json output with stream-json NDJSON format for real-time
visibility into Claude Code tool calls. Add StreamEvent type, OnStreamEvent
callback, and line-by-line scanner with parseStreamLine/extractToolTarget.
Also adds --verbose and --dangerously-skip-permissions flags.
Add StateStreamActivity constant and ToolName/ToolTarget fields to Event.
Wire OnStreamEvent callback in executor's runStepExecution() to emit
stream_activity events for real-time tool call visibility. Render tool
events in dim formatting for human-readable output.
Used by speckit-flow, docs-to-impl, gh-poor-issues, and umami pipelines.
Without it, users get "persona not found" errors on wave init projects.
Used by issue-research pipeline for deep codebase analysis.
Read-only permissions with gh and git log access.
Used by docs-to-impl, gh-poor-issues, umami, and doc-loop pipelines.
Read-only with test runner and git diff access.
Used by issue-research pipeline to post analysis comments on GitHub issues.
Security logger was writing [SECURITY] lines to stdout, polluting
pipeline output. Move all security logging to stderr where diagnostic
output belongs.
…ut and -v/--verbose

Consolidate three negative output flags into two positive persistent flags
on the root command:

  -o, --output <format>  Output format: auto, json, text, quiet (default: auto)
  -v, --verbose          Include real-time tool activity

Modes: auto (BubbleTea TUI if TTY, plain text if pipe), json (clean NDJSON
to stdout), text (plain text to stderr), quiet (final result only).

Key rule: stdout is either NDJSON or nothing, never mixed.

- Create output.go with CreateEmitter() factory and OutputConfig
- Update run.go, do.go, meta.go to use CreateEmitter()
- Gate completion summary and deliverables on auto/text format only
- Remove humanReadable field and NewNDJSONEmitterWithHumanReadable() from emitter
- Fix meta.go completion message writing to stdout instead of stderr
… output

- Add verbose field to BasicProgressDisplay and BubbleTea for tool activity
- Add QuietProgressDisplay that only renders pipeline-level events
- Add WAVE_FORCE_TTY env var to override TTY detection for testing/CI
- Show CurrentAction instead of fake 25%/75% percentages in text mode
- Skip blank step-start lines for running events without persona
- Add LastToolName/LastToolTarget to PipelineContext for TUI verbose
Remove local --verbose flag from validate command (was shadowing the
persistent -v/--verbose). Now reads the persistent flag from root command.
Update tests to use root command wrapper for persistent flag propagation.
…to stderr

- Security logger only enabled when --debug flag is set (prevents
  [SECURITY] noise on stderr in json/text modes)
- Migration messages use fmt.Fprintf(os.Stderr) instead of fmt.Printf
  to avoid corrupting stdout in -o json mode
- Add omitempty to Event.DurationMs so progress events omit duration_ms:0
- Update README flag listing
- Update cli.md run examples with -o json, -o text -v, -o quiet
- Update environment.md: remove stale WAVE_LOG_FORMAT, add WAVE_FORCE_TTY
- Update quick-start.md: show text progress as default output example
test_suite contracts now support a `dir` field to control where commands
run. Defaults to project_root (via git rev-parse) since test commands
almost always need project context (go.mod, package.json, etc).

Supported values: project_root, absolute path, relative to workspace.
When an adapter process exits non-zero (e.g. Claude Code JS crash after
tool calls completed), emit a warning event instead of failing the step.
Contract validation decides whether the work was actually completed.

All three display modes (bubbletea, progress, basic) now handle the
warning event type.
Default pipelines should be language-agnostic. Commented out Go-specific
test commands so users customize per-project in .wave/pipelines/.
Wave spawns Claude Code and gh via exec.CommandContext with os.Environ().
GH_TOKEN from keyring doesn't propagate (D-Bus session lost), and Claude
Code OAuth can expire silently. The shellHook now:
- Extracts GH_TOKEN from gh auth at shell entry
- Warns about missing ANTHROPIC_API_KEY or GH_TOKEN
- Update persona count 10→14 across README and personas guide
- Update pipeline count 9/16→18 across README and pipelines guide
- Add missing personas to tables: implementer, reviewer, researcher,
  github-analyst, github-commenter, github-enhancer, github-pr-creator
- Add missing pipelines to tables: prototype, docs-to-impl, doc-loop,
  github-issue-enhancer, gh-poor-issues, issue-research, hello-world,
  smoke-test, umami
- Fix speckit-flow steps to actual 8-step flow
- Remove unimplemented env vars (WAVE_DEBUG, WAVE_MANIFEST,
  WAVE_WORKSPACE_ROOT), add migration env vars
- Add template and format contract types to reference
- Add markdown_spec to contract type descriptions
- Fix Go version 1.22→1.25 in installation guide
- Remove incorrect planner temperature from persona example
- Clarify --verbose as global -v flag in CLI reference
…E_ROOT

These env vars have no os.Getenv calls in the codebase. Remove from
integration docs (github-actions, gitlab-ci) and workspaces concept doc.
Add readonly workspace mounts to pipeline steps that need repo access
(plan/explore, doc-loop/scan-changes, doc-loop/analyze-consistency).
Update gh CLI prompts to use --body-file instead of inline --body to
avoid shell escaping and CLI length limit issues.
Keep --body-file approach over inline --body for gh CLI robustness.
Rewrite speckit-flow pipeline with proven 8-step workflow
…ore casts

- Fix hardcoded --repo re-cinq/wave in github-issue-enhancer verify step
- Sync .wave/pipelines/issue-research.yaml with --body-file fix
- Add *.cast to .gitignore (terminal recordings kept locally)
- Remove test pipelines (speckit-flow-test, speckit-impl-test)
… isolation

Three research reports covering Nix+bubblewrap, Docker/OCI containers, and
emerging sandbox approaches for running Claude Code sessions safely. Includes
comparison matrix of 25+ approaches, Wave-specific gap analysis, and phased
implementation recommendations.
nextlevelshit and others added 24 commits February 23, 2026 09:11
…pliance handle it

Strip all artifact.json / .wave/artifact.json path references from
pipeline step prompts and persona definitions. The auto-generated
Contract Compliance section in CLAUDE.md now handles telling the
persona exactly where and how to write output. This cleanly separates
concerns: prompts describe WHAT to do, contracts describe HOW to
validate, and Wave handles the plumbing.
fix(pipeline): outcome display, contract compliance, artifact path normalization
Phase 1 of the interactive control plane. Spawns Claude Code in
interactive mode with rich context from completed pipeline runs:
run summary, step results, artifact inventory, and workspace paths.

Read-only permissions enforced via settings.json. Extension points
for Phase 2 (step manipulation) and Phase 3 (cascade control).
Phase 2: StepController with continue, extend, revert, and rewrite
operations. Chat workspace now supports analysis and manipulate modes
with appropriate permission sets. Slash commands provisioned for
manipulate mode.

Phase 3: CascadeDetector walks inject_artifacts DAG to find stale
downstream steps. Supports mtime-based verification and selective
cascade targeting. Works with any pipeline (not just prototype).

Closes #147, closes #148
…ision

When multiple steps in a shared worktree declare the same output path
(e.g., .wave/artifact.json), each step overwrites the previous and the
DB records identical absolute paths for all steps.

Fix: after confirming a file-based artifact exists, copy it to
.wave/artifacts/<step-id>/<name> before DB registration. The injection
system keeps using the workspace-relative path, but the DB gets the
archived copy which survives subsequent step overwrites.

Also removes duplicate DB registration from trackStepDeliverables
(writeOutputArtifacts already handles it).
buildStepPrompt unconditionally injected "save to .wave/artifact.json"
for any step with a json_schema contract, conflicting with the correct
output path from OutputArtifacts. Personas got two conflicting paths and
sometimes followed the wrong one (distill step writing to artifact.json
instead of convergent-proposals.json).

- Remove redundant schema injection block from buildStepPrompt
- Convert buildContractPrompt to executor method with security validation
- Add loadSecureSchemaContent and sanitizeSchemaContent helpers
- Auto-generate "Available Artifacts" section from inject_artifacts
- Update all executor/contract tests for new behavior
Strip 130+ violations of CLAUDE.md rule #1 across 24 pipeline YAML
files and 12 prompt templates. The executor now handles artifact
injection and output path guidance via buildContractPrompt, so prompts
no longer need to specify where to read/write.

Removed: output path directives, artifact read instructions, inline
JSON schema examples, and "matching the contract schema" phrases.
Kept: semantic task descriptions and field meaning explanations.
The converge step had an inline JSON example but no contract validation.
Add a proper json_schema contract so buildContractPrompt generates the
correct output guidance and the executor validates the output.
…tadata

buildContractPrompt now generates Output Requirements for any step with
output_artifacts, even without a handover contract. This ensures personas
always know where to write and in what format (JSON/markdown/text).

Previously, steps without a contract got zero output guidance, causing
personas to write prose instead of JSON (e.g. gh-issue-impl create-pr).
ClassifyFailure matched "rate limit" as a substring of "rate limiting"
in security review content, and claude.go re-scanned ResultContent even
on exit code 0 (success). This caused successful steps to be marked as
rate-limited when their output mentioned rate limiting as a finding.

- Remove exit-code-0 content re-scan in claude.go
- Tighten rate limit patterns: "rate limit exceeded", "rate limit
  reached", "rate limited" instead of bare "rate limit"
- Add regression test for security review false positive
Two bugs caused `step "" failed:` errors with empty step ID:

1. executeStep never set execution.States to StateFailed on error
   (non-matrix path). Only saved to store, leaving in-memory state as
   StateRunning. Fixed by adding the missing state update.

2. Batch error handler only checked StateFailed/StateRunning but missed
   StateRetrying. Added StateRetrying to the check and a defensive
   fallback to use ready[0].ID when no state match is found.
Steps with inject_artifacts now explicitly reference their injected
artifacts in the prompt text, preventing personas from attempting to
fetch data from external sources when the data is already available
locally. Also syncs internal/defaults copies and adds missing
validated-findings schema to embedded defaults.
Tell personas that injected artifacts contain ALL needed data and to
read them instead of re-fetching from external sources.
… YAMLs

Remove inline output path instructions, artifact read commands, and
JSON schema examples from all pipeline step prompts. The executor
injects schemas and artifact references automatically.
Replace hardcoded JSON output examples with references to the injected
output schema. Wave's executor injects schemas at runtime so prompts
must not duplicate them.
CLI commands like gh pr create --body-file need literal artifact paths.
Clarify that rule #1 permits these while still forbidding inline schemas.
…d-prompt-cleanup

fix(pipeline): eliminate conflicting schema injection and clean all prompts
Create 13 new schemas:
- pr-result: shared by 8 PR-producing pipeline steps
- publish-result: code-review publish step
- 6 speckit-flow status schemas (specify, clarify, plan, tasks, checklist, analysis)
- 3 recinq schemas (context, validated-findings, probed-findings)
- hello-world-result: verification step
Wire json_schema contracts into 20 pipeline steps that produce JSON
output artifacts but previously had no schema validation. Remove all
inline field-list descriptions from prompts — the executor injects
schemas at runtime via buildContractPrompt.
Clean specify.md and clarify.md which still had inline field lists.
All prompts now reference the injected output schema exclusively.
feat(contracts): complete schema coverage for all JSON output steps
…ulti-mode output

Rewrite the dead-code detection pipeline into a family of 4 pipelines
supporting structured JSON output, PR comments, and GitHub issue creation.

Schema changes:
- Expand dead-code-scan schema with new categories (duplicate, stale_glue,
  hardcoded_value), line_range object, and suggested_action field
- Create dead-code-report schema for formatted markdown reports
- Create dead-code-pr-result schema for PR comment results
- Create dead-code-issue-result schema for GitHub issue results

Pipeline changes:
- Rewrite dead-code.yaml as scan + format (local JSON report)
- Create dead-code-pr.yaml: scan + format + publish PR comment
- Create dead-code-issue.yaml: scan + format + create GitHub issue
- Create dead-code-heal.yaml: preserves existing clean/verify/create-pr flow

Persona changes:
- Extend github-commenter with gh pr comment and gh issue create permissions
- Replace overly broad gh pr* deny with specific denials

Tests:
- Schema validation tests covering all new categories, fields, and backward
  compatibility
- Pipeline YAML parse tests verifying loading, DAG validation, persona
  references, and tool requirements
@nextlevelshit nextlevelshit marked this pull request as draft February 24, 2026 14:02
@nextlevelshit
Copy link
Copy Markdown
Collaborator Author

Code Review (Wave Pipeline)

Verdict: REQUEST_CHANGES

Blocking Issues

  1. Missing BasicProgressDisplay guard test — both reviewers flagged this independently, confirming it's a real coverage gap
  2. Silent observability regression from unstaged executor.go change — artifact injection messages are dropped in CI/non-TTY output

Non-Blocking Improvements

Four non-blocking improvements were also surfaced:

  • Test safety with t.Chdir
  • Fragile timeouts
  • PipelineID inconsistency
  • State tracking type inconsistency

Positive Observations

Overall quality of the committed fix was noted positively by both reviewers.

Assessment

The implementation is too shallow and too destructive; may need full re-implementation.


Generated by Wave code-review pipeline

@nextlevelshit nextlevelshit deleted the 135-dead-code-pipeline branch March 30, 2026 16:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Improve dead-code detection pipeline: multi-mode output, PR review comments, and issue creation

2 participants