Skip to content

feat: add flow.Mutator API; deprecate BuildStep#76

Merged
xuxife merged 32 commits into
mainfrom
worktree-redesign-build-step
May 12, 2026
Merged

feat: add flow.Mutator API; deprecate BuildStep#76
xuxife merged 32 commits into
mainfrom
worktree-redesign-build-step

Conversation

@xuxife
Copy link
Copy Markdown
Collaborator

@xuxife xuxife commented May 12, 2026

Summary

  • Add flow.Mutator — a type-dispatched, once-per-step configuration contributor — produced only via the generic constructor flow.Mutate[T Steper](fn).
  • Add Workflow.Mutators []Mutator; apply once per step at first-schedule (after upstream check, before state.Option()) inside Workflow.tick.
  • Add MutatorReceiver interface so parent workflows propagate Mutators into nested *Workflow / SubWorkflow-embedded composite steps.
  • Deprecate StepBuilder.BuildStep and SubWorkflow.Reset; replace the BuildStep pattern with Do()-time sub-workflow construction (ExampleMutate_subWorkflow).
  • Full OpenSpec change at openspec/changes/2026-05-06-step-mutator/ (proposal, design, three spec deltas, tasks).

Design highlights

  • Dispatch: Mutate[T] walks the step's Unwrap() chain; first matching layer wins. Walk stops at workflow boundaries (interface{ StateOf(Steper) *State }) — inner-workflow steps are reached via PrependMutators, never by descent.
  • Merge destination: the matched layer's StepConfig is merged into the wrapper key in the owning workflow's state map. Builder entries keyed on any other step are silently dropped.
  • Once-per-step: state.MutatorsApplied flag flips before invoking user fn (panic-safe under DontPanic).
  • Ordering: plan-declared Input/Before/After run before Mutator-contributed ones; multiple Mutators contribute in Workflow.Mutators slice order.
  • No new external deps. Generic constructor; tests use testify/assert; examples use stdlib Example* + // Output:.

Files

  • mutator.go / mutator_test.go — interface, constructor, dispatch
  • state.gomutatorsApplied bool + accessors
  • workflow.goMutators field, applyMutators helper, tick splice, PrependMutators on *Workflow and *SubWorkflow
  • workflow_mutator_test.go — black-box integration suite
  • build_step.go, workflow.go (SubWorkflow.Reset) — deprecation godoc
  • example/15_mutator_test.go — 7 runnable examples
  • example/13_composite_step_test.go — deprecation note on legacy composite example

Test plan

  • go build ./...
  • go vet ./...
  • go test ./... -count=1 (workflow + example packages, ~4.6s)
  • openspec validate 2026-05-06-step-mutator --strict
  • Coordinate with Step Interceptor change author on shared tick splice point and ordering before merge

Out of scope (deferred)

  • Removing BuildStep / SubWorkflow.Reset — next major version
  • Migrating downstream callers from BuildStep to Mutate
  • openspec archive (post-merge)

🤖 Generated with Claude Code

Xingfei Xu and others added 30 commits May 5, 2026 05:57
- ErrWorkflow.Unwrap(): skip nil errors (fixes errors.Is/As correctness)
- State.SetStepResult(): atomic write for Status+Err+FinishedAt under one lock
- reset(): clear full StepResult (not just Status) to avoid stale FinishedAt
- tests: guard strings.Index assertions with require >= 0
Adds the design-phase artifacts for the upcoming flow.Mutator feature:
- openspec/changes/2026-05-06-step-mutator/: proposal, design, tasks, and
  capability deltas (mutators / composite-steps / step-configuration)
- docs/superpowers/specs/2026-05-06-step-mutator-design.md: brainstorming notes
- docs/superpowers/plans/2026-05-11-step-mutator.md: TDD implementation plan
- example/15_mutator_test.go: reference example file (build-tagged out until
  the implementation lands)

No production code changes in this commit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…covery

Add three tests:
- TestMutator_receivesWorkflowCtx: verifies the workflow ctx passed to Do
  is forwarded into each mutator function.
- TestMutator_unrelatedBuilderEntryIgnored: verifies that a Builder keyed
  on a step not in the workflow is silently dropped (scope isolation).
- TestMutator_panicCaughtWhenDontPanic: verifies panics in mutators are
  caught when DontPanic=true and surface as the step's terminal error.

Production change: wrap each mutator call in catchPanicAsError when
DontPanic is set (mirrors the makeDoForStep `do` idiom). On panic,
SetError on the state and short-circuit in tick — marking the step Failed
immediately so the goroutine never overwrites the captured error.
…ld-step

# Conflicts:
#	build_step.go
#	error.go
#	example/13_composite_step_test.go
#	state.go
#	workflow.go
Xingfei Xu and others added 2 commits May 12, 2026 05:22
…test.go

- Rename 15_mutator_test.go → 13_mutators_test.go to fit the
  sequential learning path (after 12_testing_workflows).
- Adopt the same header/structure as 04_callbacks, 08_workflow_in_workflow,
  10_observability: "What you'll learn" → "Where they fit" → "When to
  reach for which mechanism" → progressive examples.
- Use a single coherent use case (release-pipeline *Notify steps with a
  cross-cutting Mutator) instead of disjoint Greet/Farewell fixtures.
- Five examples, each building on the previous:
    1. _fieldDefaults     — pure field mutation (return nil Builder)
    2. _contributeConfig  — Builder with BeforeStep
    3. _ctxValue          — Mutator receives the workflow ctx
    4. _subWorkflow       — parent Mutator reaches inner Steps via
                            MutatorReceiver
    5. _multipleInOrder   — plan-first, then Mutators in slice order
- Drop the old _retryOverride / _nilBuilder / _unwrap variants — they
  belonged to the design-doc stage; production users care about defaults,
  callbacks, ctx, propagation, and ordering.
- Update example/README.md to list 13_mutators in the "Operate, debug,
  test" section.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Apply MODIFIED and ADDED requirements from the 2026-05-06-step-mutator
change to the main capability specs:

  composite-steps:    BuildStep marked deprecated, added
                      "Sub-workflow construction inside Do" and
                      "MutatorReceiver propagation" requirements.
  step-configuration: added "Mutators field on Workflow" requirement.
  mutators:           new capability spec covering the Mutator interface,
                      first-schedule merge semantics, once-per-step
                      enforcement, dispatch via Unwrap, scope rules, and
                      MutatorReceiver propagation across workflow
                      boundaries.

The change directory moves to openspec/changes/archive/ dated 2026-05-12.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@xuxife xuxife added this pull request to the merge queue May 12, 2026
Merged via the queue into main with commit 7790878 May 12, 2026
2 checks passed
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.

2 participants