Skip to content

Commit 08bf8ea

Browse files
Merge pull request #1424 from re-cinq/1286-merge-deliverable-state
refactor(state): merge internal/deliverable into state.OutcomeRecord
2 parents 53941e1 + 2edf5c7 commit 08bf8ea

32 files changed

Lines changed: 1357 additions & 1532 deletions

.agents/pipelines/audit-duplicates.yaml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,9 @@ steps:
7171
7272
4. **Routing** (internal/suggest/ vs internal/pipeline/routing.go): Both may route user intent to pipeline selection. Compare how each determines which pipeline to run. Check for duplicated scoring logic, keyword matching, or heuristic functions.
7373
74-
5. **State tracking** (internal/state/ vs internal/deliverable/): Both may track pipeline run status and outcomes. Compare their data models, storage mechanisms, and query patterns. Identify whether they track the same lifecycle events or serve different granularities of state.
74+
5. **Template variables** (internal/pipeline/context.go ProjectVars vs internal/manifest/types.go ProjectVars): Check whether both define or populate project template variables. Identify whether the same variable names are resolved in two different places, which could lead to inconsistent values.
7575
76-
6. **Template variables** (internal/pipeline/context.go ProjectVars vs internal/manifest/types.go ProjectVars): Check whether both define or populate project template variables. Identify whether the same variable names are resolved in two different places, which could lead to inconsistent values.
77-
78-
7. **Discovery of additional overlaps**: Beyond the known suspects, scan for:
76+
6. **Discovery of additional overlaps**: Beyond the known suspects, scan for:
7977
- Functions with identical or near-identical signatures across different packages.
8078
- Types that model the same domain concept under different names.
8179
- Utility functions (string manipulation, file I/O helpers, error wrapping) duplicated across packages rather than centralized.

.golangci.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ linters:
3232
- "**/internal/adapter/**"
3333
- "**/internal/contract/**"
3434
- "**/internal/relay/**"
35-
- "**/internal/deliverable/**"
3635
- "**/internal/preflight/**"
3736
- "**/internal/recovery/**"
3837
- "**/internal/skill/**"
@@ -90,8 +89,6 @@ linters:
9089
desc: "Layer violation: Infrastructure must not import Domain (ADR-003)"
9190
- pkg: "github.com/recinq/wave/internal/relay"
9291
desc: "Layer violation: Infrastructure must not import Domain (ADR-003)"
93-
- pkg: "github.com/recinq/wave/internal/deliverable"
94-
desc: "Layer violation: Infrastructure must not import Domain (ADR-003)"
9592
- pkg: "github.com/recinq/wave/internal/preflight"
9693
desc: "Layer violation: Infrastructure must not import Domain (ADR-003)"
9794
- pkg: "github.com/recinq/wave/internal/recovery"

cmd/wave/commands/resume.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -241,9 +241,9 @@ func runResume(opts ResumeOptions, debug bool) error {
241241

242242
executor := pipeline.NewDefaultPipelineExecutor(runner, execOpts...)
243243

244-
// Connect deliverable tracker to progress display.
244+
// Connect outcome tracker to progress display.
245245
if btpd, ok := progressDisplay.(*display.BubbleTeaProgressDisplay); ok {
246-
btpd.SetDeliverableTracker(executor.GetDeliverableTracker())
246+
btpd.SetOutcomeTracker(executor.GetOutcomeTracker())
247247
}
248248

249249
// Transition new run record to running.
@@ -335,7 +335,7 @@ func runResume(opts ResumeOptions, debug bool) error {
335335
}
336336

337337
if opts.Output.Format == OutputFormatJSON {
338-
tracker := executor.GetDeliverableTracker()
338+
tracker := executor.GetOutcomeTracker()
339339
outcome := display.BuildOutcome(tracker, p.Metadata.Name, resumeRunID, true, elapsed, executor.GetTotalTokens(), "", nil)
340340
outJSON := outcome.ToOutcomesJSON()
341341
emitter.Emit(event.Event{

cmd/wave/commands/run.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -519,9 +519,9 @@ func runRun(opts RunOptions, debug bool) error {
519519

520520
executor := pipeline.NewDefaultPipelineExecutor(runner, execOpts...)
521521

522-
// Connect deliverable tracker to progress display
522+
// Connect outcome tracker to progress display
523523
if btpd, ok := progressDisplay.(*display.BubbleTeaProgressDisplay); ok {
524-
btpd.SetDeliverableTracker(executor.GetDeliverableTracker())
524+
btpd.SetOutcomeTracker(executor.GetOutcomeTracker())
525525
}
526526

527527
if opts.Continuous {
@@ -716,8 +716,8 @@ func runRun(opts RunOptions, debug bool) error {
716716
fmt.Fprintf(os.Stderr, "\n ✓ Pipeline '%s' completed successfully (%.1fs)\n",
717717
p.Metadata.Name, elapsed.Seconds())
718718
}
719-
// Build structured outcome summary from deliverable tracker
720-
tracker := executor.GetDeliverableTracker()
719+
// Build structured outcome summary from outcome tracker
720+
tracker := executor.GetOutcomeTracker()
721721
outcome := display.BuildOutcome(tracker, p.Metadata.Name, runID, true, elapsed, totalTokens, "", nil)
722722
summary := display.RenderOutcomeSummary(outcome, opts.Output.Verbose, display.NewFormatter())
723723
if summary != "" {
@@ -736,7 +736,7 @@ func runRun(opts RunOptions, debug bool) error {
736736

737737
// For JSON output mode, emit structured outcomes in the final completion event
738738
if opts.Output.Format == OutputFormatJSON {
739-
tracker := executor.GetDeliverableTracker()
739+
tracker := executor.GetOutcomeTracker()
740740
outcome := display.BuildOutcome(tracker, p.Metadata.Name, runID, true, elapsed, executor.GetTotalTokens(), "", nil)
741741
outJSON := outcome.ToOutcomesJSON()
742742
emitter.Emit(event.Event{

docs/adr/003-layered-architecture.md

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ Accepted (Phase 1 — depguard rules live; package count drifted upward)
1111
Landed:
1212
- `depguard` rules in `.golangci.yml` enforce two layer constraints:
1313
- `no-presentation-reverse` blocks `display`, `tui`, `webui`, `onboarding` from being imported by domain or infrastructure code.
14-
- `infrastructure-no-domain` blocks `pipeline`, `adapter`, `contract`, `relay`, `deliverable`, `preflight`, `recovery`, `skill`, `defaults`, `suggest`, `doctor` from being imported by infrastructure.
15-
- Verified import constraints: `display``event`/`pathfmt`/`deliverable` only; `pipeline` does not import `display`/`tui`.
14+
- `infrastructure-no-domain` blocks `pipeline`, `adapter`, `contract`, `relay`, `preflight`, `recovery`, `skill`, `defaults`, `suggest`, `doctor` from being imported by infrastructure.
15+
- Verified import constraints: `display``event`/`pathfmt`/`state` only; `pipeline` does not import `display`/`tui`.
1616

1717
Drift since the original ADR was drafted:
1818
- `internal/` package count grew from 25 to 39 (additions include `attention`, `bench`, `classify`, `continuous`, `cost`, `fileutil`, `hooks`, `humanize`, `ontology`, `retro`, `sandbox`, `scope`, `testutil`, `timeouts`, `tools`).
@@ -21,7 +21,7 @@ Drift since the original ADR was drafted:
2121

2222
## Context
2323

24-
Wave's `internal/` directory contains 25 packages that have grown organically during rapid prototyping (v0.15.0 → v0.84.1). While the separation between presentation and backend is already reasonably clean — `display/` imports only `event/`, `pathfmt/`, and `deliverable/`; `pipeline/` does not import `display/` or `tui/` — some areas have accumulated cross-layer coupling that warrants formal documentation and enforcement.
24+
Wave's `internal/` directory contains 25 packages that have grown organically during rapid prototyping (v0.15.0 → v0.84.1). While the separation between presentation and backend is already reasonably clean — `display/` imports only `event/`, `pathfmt/`, and `state/`; `pipeline/` does not import `display/` or `tui/` — some areas have accumulated cross-layer coupling that warrants formal documentation and enforcement.
2525

2626
### Current State
2727

@@ -33,16 +33,15 @@ An audit of the codebase reveals the following import relationships among intern
3333
| `audit` | (none) |
3434
| `contract` | `pathfmt` |
3535
| `defaults` | `manifest`, `pipeline` |
36-
| `deliverable` | `pathfmt` |
37-
| `display` | `deliverable`, `event`, `pathfmt` |
36+
| `display` | `event`, `pathfmt`, `state` |
3837
| `doctor` | `forge`, `github`, `manifest`, `onboarding`, `pipeline` |
3938
| `event` | (none) |
4039
| `forge` | (none) |
4140
| `github` | (none) |
4241
| `manifest` | `skill` |
4342
| `onboarding` | `manifest`, `skill`, `tui` |
4443
| `pathfmt` | (none) |
45-
| `pipeline` | `adapter`, `audit`, `contract`, `deliverable`, `event`, `forge`, `manifest`, `preflight`, `recovery`, `relay`, `security`, `skill`, `state`, `workspace`, `worktree` |
44+
| `pipeline` | `adapter`, `audit`, `contract`, `event`, `forge`, `manifest`, `preflight`, `recovery`, `relay`, `security`, `skill`, `state`, `workspace`, `worktree` |
4645
| `preflight` | `skill` |
4746
| `recovery` | `contract`, `pathfmt`, `preflight`, `security` |
4847
| `relay` | (none) |
@@ -88,7 +87,6 @@ Adopt a four-layer architectural model for Wave's internal packages and enforce
8887
| `adapter` | Subprocess execution and adapter management |
8988
| `contract` | Output validation (JSON schema, TypeScript, test suites) |
9089
| `relay` | Context compaction and summarization |
91-
| `deliverable` | Pipeline deliverable tracking and output |
9290
| `preflight` | Pipeline dependency validation and auto-install |
9391
| `recovery` | Pipeline recovery hints and error guidance |
9492
| `skill` | Skill discovery, provisioning, and command management |

docs/architecture-audit.md

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ Wave's `internal/` directory contains **25 Go packages** totaling ~48,655 lines
1414
| `audit` | 133 | 709 | Audit logging with credential scrubbing |
1515
| `contract` | 4,030 | 3,498 | Output validation (JSON schema, TypeScript, test suites, markdown spec) |
1616
| `defaults` | 209 | 529 | Embedded default personas, pipelines, and contracts |
17-
| `deliverable` | 513 | 222 | Pipeline deliverable tracking and output formatting |
1817
| `display` | 5,294 | 5,605 | Terminal progress display and formatting |
1918
| `doctor` | 2,474 | 2,500 | Project health checking and optimization |
2019
| `event` | 200 | 642 | Progress event emission and monitoring (producer/consumer) |
@@ -46,16 +45,15 @@ Each row shows which internal packages are imported.
4645
| `audit` | *(none)* | 0 |
4746
| `contract` | `pathfmt` | 1 |
4847
| `defaults` | `manifest`, `pipeline` | 2 |
49-
| `deliverable` | `pathfmt` | 1 |
50-
| `display` | `deliverable`, `event`, `pathfmt` | 3 |
48+
| `display` | `event`, `pathfmt`, `state` | 3 |
5149
| `doctor` | `forge`, `github`, `manifest`, `onboarding`, `pipeline` | 5 |
5250
| `event` | *(none)* | 0 |
5351
| `forge` | *(none)* | 0 |
5452
| `github` | *(none)* | 0 |
5553
| `manifest` | `skill` | 1 |
5654
| `onboarding` | `manifest`, `skill`, `tui` | 3 |
5755
| `pathfmt` | *(none)* | 0 |
58-
| `pipeline` | `adapter`, `audit`, `contract`, `deliverable`, `event`, `forge`, `manifest`, `preflight`, `recovery`, `relay`, `security`, `skill`, `state`, `workspace`, `worktree` | 15 |
56+
| `pipeline` | `adapter`, `audit`, `contract`, `event`, `forge`, `manifest`, `preflight`, `recovery`, `relay`, `security`, `skill`, `state`, `workspace`, `worktree` | 14 |
5957
| `preflight` | `skill` | 1 |
6058
| `recovery` | `contract`, `pathfmt`, `preflight`, `security` | 4 |
6159
| `relay` | *(none)* | 0 |
@@ -75,7 +73,7 @@ Each row shows which internal packages are imported.
7573
| `manifest` | `defaults`, `doctor`, `onboarding`, `pipeline`, `tui`, `webui` | 6 |
7674
| `skill` | `manifest`, `onboarding`, `pipeline`, `preflight` | 4 |
7775
| `event` | `display`, `pipeline`, `tui`, `webui` | 4 |
78-
| `pathfmt` | `contract`, `deliverable`, `display`, `recovery`, `tui` | 5 |
76+
| `pathfmt` | `contract`, `display`, `recovery`, `state`, `tui` | 5 |
7977
| `pipeline` | `defaults`, `doctor`, `tui`, `webui` | 4 |
8078
| `forge` | `doctor`, `pipeline`, `suggest`, `tui` | 4 |
8179
| `state` | `pipeline`, `tui`, `webui` | 3 |
@@ -85,7 +83,6 @@ Each row shows which internal packages are imported.
8583
| `github` | `adapter`, `doctor`, `tui` | 3 |
8684
| `contract` | `pipeline`, `recovery` | 2 |
8785
| `workspace` | `pipeline`, `webui` | 2 |
88-
| `deliverable` | `display`, `pipeline` | 2 |
8986
| `audit` | `pipeline`, `webui` | 2 |
9087
| `preflight` | `pipeline`, `recovery` | 2 |
9188
| `doctor` | `suggest` | 1 |
@@ -219,7 +216,6 @@ Test-to-production ratio varies significantly:
219216
| `workspace` | 3.3:1 | Well-tested |
220217
| `tui` | 0.9:1 | Could use more test coverage |
221218
| `webui` | 0.4:1 | Low test coverage |
222-
| `deliverable` | 0.4:1 | Low test coverage |
223219

224220
## ADR-003 Discrepancies Found
225221

docs/changelog.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3939
- Unified forge-specific pipelines into forge-agnostic pipelines with template variables
4040
- `github_api_seconds``forge_api_seconds` in timeout configuration
4141
- All hardcoded timeout values replaced with configurable constants via `internal/timeouts`
42+
- `state.OutcomeRecord` extended with `Description`, `Metadata`, and typed `OutcomeType` (migration #24); new `state.OutcomeTracker` replaces `deliverable.Tracker` with persistence-on-add (#1286)
43+
- `executor.GetDeliverableTracker()``executor.GetOutcomeTracker()`; `BubbleTeaProgressDisplay.SetDeliverableTracker``SetOutcomeTracker` (#1286)
4244

4345
### Removed
4446
- Deprecated pipeline name resolution (`ResolveDeprecatedName`) — no backward-compat shims pre-1.0.0
4547
- Timeout constant re-exports from `manifest` package
4648
- Stale multiplatform pipeline tests referencing non-existent gl-*/gt-* YAML files
4749
- Nonexistent `timeout` and `retry` persona fields from custom-personas guide
50+
- `internal/deliverable` package — merged into `state.OutcomeRecord` and `state.OutcomeTracker`. Single outcome model backed by SQLite with persistence-on-add (#1286)
4851

4952
## [0.69.0] - 2026-03-10
5053

docs/scope/wave-scope.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@
5555
| `audit` | 388 | Audit logging and credential scrubbing | Active |
5656
| `scope` | 604 | Persona token scope validation | Active |
5757
| `cost` | 237 | Cost ledger and budget enforcement | Active |
58-
| `deliverable` | 513 | Pipeline deliverable tracking | Active |
5958
| `retro` | 659 | Run retrospective generation | Active |
6059
| `pathfmt` | 22 | Path formatting utilities | Active |
6160
| `timeouts` | 29 | Timeout constants | Active |

internal/defaults/pipelines/audit-duplicates.yaml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,9 @@ steps:
7070
7171
4. **Routing** (internal/suggest/ vs internal/pipeline/routing.go): Both may route user intent to pipeline selection. Compare how each determines which pipeline to run. Check for duplicated scoring logic, keyword matching, or heuristic functions.
7272
73-
5. **State tracking** (internal/state/ vs internal/deliverable/): Both may track pipeline run status and outcomes. Compare their data models, storage mechanisms, and query patterns. Identify whether they track the same lifecycle events or serve different granularities of state.
73+
5. **Template variables** (internal/pipeline/context.go ProjectVars vs internal/manifest/types.go ProjectVars): Check whether both define or populate project template variables. Identify whether the same variable names are resolved in two different places, which could lead to inconsistent values.
7474
75-
6. **Template variables** (internal/pipeline/context.go ProjectVars vs internal/manifest/types.go ProjectVars): Check whether both define or populate project template variables. Identify whether the same variable names are resolved in two different places, which could lead to inconsistent values.
76-
77-
7. **Discovery of additional overlaps**: Beyond the known suspects, scan for:
75+
6. **Discovery of additional overlaps**: Beyond the known suspects, scan for:
7876
- Functions with identical or near-identical signatures across different packages.
7977
- Types that model the same domain concept under different names.
8078
- Utility functions (string manipulation, file I/O helpers, error wrapping) duplicated across packages rather than centralized.

0 commit comments

Comments
 (0)