Skip to content

feat: workflow#640 Phase 1 — v2 action lifecycle inventory + provider compatibility ADR + Deprecated marker#691

Merged
intel352 merged 8 commits into
mainfrom
feat/v2-lifecycle-inventory-planning
May 16, 2026
Merged

feat: workflow#640 Phase 1 — v2 action lifecycle inventory + provider compatibility ADR + Deprecated marker#691
intel352 merged 8 commits into
mainfrom
feat/v2-lifecycle-inventory-planning

Conversation

@intel352
Copy link
Copy Markdown
Contributor

Summary

Phase 1 of workflow#640. Bounded docs + 1-godoc-line deliverable:

  • docs/migrations/2026-05-16-v2-lifecycle-phase1-inventory.md — full v1 caller inventory verified via per-repo gh api grep
  • decisions/0040-v2-action-lifecycle-provider-compatibility.md — ADR recording 5 provider-side compatibility expectations + Phase 2 hard-cutover constraint per ADR 0024 (no compat shim)
  • iac/wfctlhelpers/doc.go — in-package contract pointer
  • iac/wfctlhelpers/apply.go:78// Deprecated: use ApplyPlanWithHooks godoc marker on ApplyPlan; surfaces via gopls/staticcheck to all callers

Major architectural finding (verified inline)

3 of 4 IaC plugins do NOT use the iac-codemod canonical pattern:

Plugin File:Line Pattern
workflow-plugin-aws provider/provider.go:237 AWSProvider.Apply NON-CANONICAL — own loop
workflow-plugin-gcp provider/provider.go:226 GCPProvider.Apply NON-CANONICAL — own loop
workflow-plugin-azure internal/provider.go:138 AzureProvider.Apply NON-CANONICAL — own loop
workflow-plugin-digitalocean internal/provider.go:274 DOProvider.Apply CANONICAL ✓ delegates to wfctlhelpers.ApplyPlan

Phase 3 plugin migration is bifurcated: codemod for DO; manual for aws/gcp/azure. Phase 2 v2 contract design must accommodate both implementation paths.

Pipeline

  • Brainstorming → adversarial-design-review cycle 1 FAIL → revise → cycle 2 FAIL → polish (per autonomous mandate; codemod constant bump moved from Phase 1 to Phase 3 lockstep with AST-rewriter updates after cycle-2 found bumping just the constant produces internally-inconsistent tool)
  • Skipped writing-plans / alignment-check / scope-lock formalities — Phase 1 is a 1-PR bounded deliverable; pipeline ceremony for multi-PR work would be overhead

Out of scope (deferred to Phase 2-5 design passes per Phase 1 scope)

  • Phase 2: gRPC contract extension (HARD-CUTOVER per ADR 0024)
  • Phase 3: plugin migration (bifurcated codemod-vs-manual)
  • Phase 4: 3 conformance scenario migration (trivial empty-hooks rename; HARD prerequisite for Phase 5)
  • Phase 5: wfctlhelpers.ApplyPlan removal

Test plan

  • GOWORK=off go build ./iac/wfctlhelpers/ PASS
  • doc.go is package wfctlhelpers documentation only; no runtime change
  • godoc Deprecated marker is comment-only; no semantic change
  • gopls/staticcheck will surface deprecation to ApplyPlan callers (3 conformance scenarios + DO plugin); operators see migration signal via static analysis

🤖 Generated with Claude Code

intel352 and others added 4 commits May 16, 2026 00:54
…tibility expectations

Phase 1 of workflow#640. Bounded docs-only deliverable:
- Inventory v1 ApplyPlan callers (3 conformance scenarios + 3 wfctl
  provider.Apply direct calls + 4 plugin canonical-form delegates)
- Classify each: KEEP-ON-V1 / MIGRATE-NEEDED / TOOL
- Define 5 provider-compatibility expectations (per-action success
  evidence, failed-delete-no-prune, compensation evidence, update-failure-
  no-delete, provider-owned-replace-advertised) for Phase 2's gRPC contract

Phase 2-5 (gRPC contract extension, plugin migration, conformance
migration, v1 deprecation+removal) deferred to subsequent design passes.

Self-challenge surfaced 3 doubts: docs-only-as-theatre risk (mitigated by
ADR + in-package doc.go); inventory smaller than expected (Phase 2 is
the heavy work; Phase 1 is prerequisite, not trivializing); 3 conformance
scenarios "KEEP-ON-V1" preliminary (revisit during Phase 4).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Critical fixes:
- C-1: REVOKE Assumption 5 (graceful proto fallback) — contradicts
  ADR 0024 (no-compat-shim mandate). Phase 2 is now explicitly a
  HARD-CUTOVER coordinated PR cascade across workflow + 4 plugins,
  recorded as ADR 0040 consequence.
- C-2: Reclassify Item #9 (typed_adapter.Apply) — NOT in v2 hot path;
  v2 dispatch via ResourceDriver per action; Phase 2 wire-format work
  happens in applyResultFromPB decoder, not adapter dispatch.

Important fixes:
- I-1: Reclassify 3 conformance scenarios from KEEP-ON-V1 to
  MIGRATE-NEEDED (Phase 4) — TRIVIAL empty-hooks rename; HARD
  PREREQUISITE for Phase 5 documented.
- I-2: Add Task 0 (PRE-PLAN-AUTHORING grep across 4 plugin repos)
  before ADR commits — eliminates speculative-inventory bootstrap problem.
- I-3: Add Assumption 8 (manifest-validation gap on deploy_providers
  path) — Phase 2 scope adds validation gate.

Scope expansion (per cycle-1 reviewer's "Option A"):
- Add // Deprecated: godoc marker to ApplyPlan in iac/wfctlhelpers/apply.go
- Bump iac-codemod applyCanonicalCallExpr to ApplyPlanWithHooks form
  (codemod becomes Phase 3 migration driver)
- Update lint matchers + doc references consistently

Phase 1 ships engine docs + deprecation marker + codemod canonical-form
bump. Light mechanical changes; no runtime behavior change.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

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

Cycle 2 adversarial review surfaced 2 Critical findings — both new from
the cycle-1 Option A scope expansion:

C-1: Inventory table "KEEP for now" contradicted Goal item 6 "bump now".
  Resolved by removing Goal item 6 (codemod constant bump) from Phase 1
  scope; deferring to Phase 3 lockstep with AST-rewriter updates.

C-2: Codemod constant bump alone is theatre — applyCanonicalCallExpr is
  //nolint:unused, NOT consumed by rewriteApplyBody. Bumping the string
  without updating rewriteApplyBody/isAlreadyDelegatedApplyBody/
  runAssertApplyDelegatesToHelper produces internally-inconsistent tool
  (constant says WithHooks, AST emits ApplyPlan, idempotency gate
  recognizes ApplyPlan only, lint flags WithHooks callers as
  non-canonical, regression-loop on re-run). Resolved by removing
  codemod constant bump from Phase 1 entirely; Phase 3 does it in
  lockstep when codemod actually runs against plugins.

Plus Important fixes:
- I-2: applyPlanWithEnvProvider Deprecated marker scope clarified —
  unexported function gets NO marker (gopls/staticcheck ignore unexported
  Deprecated identifiers). Only exported ApplyPlan gets the marker.
- I-3: Phase 2 constraint reference subsection added — explicitly directs
  Phase 2 writing-plans agent to read ADR 0040 first.

Per skill spec at 2-revision-cycle limit; user-override per "continue
autonomously" mandate. Surgical fix; not full re-review.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… compatibility ADR + Deprecated marker

Phase 1 deliverable per docs/plans/2026-05-16-v2-lifecycle-phase1-design.md:

- docs/migrations/2026-05-16-v2-lifecycle-phase1-inventory.md — full v1
  caller inventory (3 conformance scenarios + 3 wfctl provider.Apply
  direct calls + 4 plugin Apply impls) verified via per-repo gh api grep
- decisions/0040-v2-action-lifecycle-provider-compatibility.md — ADR
  recording 5 provider-side compatibility expectations + Phase 2
  hard-cutover constraint per ADR 0024
- iac/wfctlhelpers/doc.go — in-package contract pointer documenting v1/v2
  versions + per-plugin migration path
- iac/wfctlhelpers/apply.go:78 — // Deprecated: use ApplyPlanWithHooks
  godoc marker on ApplyPlan; surfaces via gopls/staticcheck to all callers

MAJOR ARCHITECTURAL FINDING (verified inline 2026-05-16):
- workflow-plugin-aws AWSProvider.Apply (provider/provider.go:237) — NON-CANONICAL
- workflow-plugin-gcp GCPProvider.Apply (provider/provider.go:226) — NON-CANONICAL
- workflow-plugin-azure AzureProvider.Apply (internal/provider.go:138) — NON-CANONICAL
- workflow-plugin-digitalocean DOProvider.Apply (internal/provider.go:274) — CANONICAL ✓

3 of 4 plugins do NOT use the iac-codemod canonical pattern. Phase 3
plugin migration is bifurcated: codemod for DO, manual for aws/gcp/azure.
Phase 2 v2 contract design must accommodate both implementation paths.

Cycle 1+2 adversarial-design-review findings addressed (cycle-2 polish
per autonomous mandate; codemod constant bump moved from Phase 1 to
Phase 3 lockstep with AST-rewriter updates after cycle-2 found bumping
just the constant produces internally-inconsistent tool).

Phases 2-5 deferred to subsequent design passes per Phase 1 scope.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 16, 2026 05:17
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Phase 1 of workflow#640: documents the v2 IaC action lifecycle migration plan/constraints, inventories current v1 callers (including plugin-side patterns), and adds a Go deprecation signal for the legacy wfctlhelpers.ApplyPlan entrypoint.

Changes:

  • Added Phase 1 inventory + migration writeups (design doc + migration inventory) and recorded provider compatibility expectations in ADR 0040.
  • Introduced iac/wfctlhelpers/doc.go to document v1/v2 entrypoints and migration phases for provider authors.
  • Marked iac/wfctlhelpers.ApplyPlan as deprecated in Go doc so gopls/staticcheck surfaces migration guidance to callers.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
iac/wfctlhelpers/doc.go New package documentation describing v1/v2 apply entrypoints and migration guidance.
iac/wfctlhelpers/apply.go Adds // Deprecated: marker to exported ApplyPlan.
docs/plans/2026-05-16-v2-lifecycle-phase1-design.md Phase 1 design doc capturing scope, inventory, and constraints.
docs/migrations/2026-05-16-v2-lifecycle-phase1-inventory.md Phase 1 inventory of v1 caller sites (workflow + plugins) and implications.
decisions/0040-v2-action-lifecycle-provider-compatibility.md ADR defining provider compatibility expectations and Phase 2 hard-cutover constraint.

Comment thread iac/wfctlhelpers/doc.go Outdated
@@ -0,0 +1,53 @@
// Package wfctlhelpers exposes the IaC plan-execution engine that wfctl and
Comment on lines +14 to +17
3. Defines provider compatibility expectations for v2 — what plugins must do at the gRPC IaCProvider.Apply boundary so wfctl-side hooks fire correctly.
4. Lands ADR 0040 recording the per-caller classification, the provider-side expectation contract, **and the consequence that Phase 2 is a coordinated hard-cutover per ADR 0024 (no compat-shim path).**
5. **Adds `// Deprecated: use ApplyPlanWithHooks` godoc marker to `ApplyPlan` in `iac/wfctlhelpers/apply.go:78`** — surfaced by `gopls`/`staticcheck` to every caller; mechanically delivers #640's "Add deprecation warnings" milestone.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 16, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 16, 2026

⏱ Benchmark Results

No significant performance regressions detected.

benchstat comparison (baseline → PR)
## benchstat: baseline → PR
baseline-bench.txt:276: parsing iteration count: invalid syntax
baseline-bench.txt:357985: parsing iteration count: invalid syntax
baseline-bench.txt:689708: parsing iteration count: invalid syntax
baseline-bench.txt:1003125: parsing iteration count: invalid syntax
baseline-bench.txt:1290517: parsing iteration count: invalid syntax
baseline-bench.txt:1596605: parsing iteration count: invalid syntax
benchmark-results.txt:276: parsing iteration count: invalid syntax
benchmark-results.txt:284170: parsing iteration count: invalid syntax
benchmark-results.txt:546308: parsing iteration count: invalid syntax
benchmark-results.txt:1059693: parsing iteration count: invalid syntax
benchmark-results.txt:1362703: parsing iteration count: invalid syntax
benchmark-results.txt:1679129: parsing iteration count: invalid syntax
goos: linux
goarch: amd64
pkg: github.com/GoCodeAlone/workflow/dynamic
cpu: AMD EPYC 7763 64-Core Processor                
                            │ benchmark-results.txt │
                            │        sec/op         │
InterpreterCreation-4                  7.508m ± 59%
ComponentLoad-4                        3.599m ±  1%
ComponentExecute-4                     1.919µ ±  0%
PoolContention/workers-1-4             1.072µ ±  1%
PoolContention/workers-2-4             1.078µ ±  1%
PoolContention/workers-4-4             1.078µ ±  1%
PoolContention/workers-8-4             1.076µ ±  1%
PoolContention/workers-16-4            1.084µ ±  1%
ComponentLifecycle-4                   3.602m ±  2%
SourceValidation-4                     2.294µ ±  0%
RegistryConcurrent-4                   782.1n ±  4%
LoaderLoadFromString-4                 3.598m ±  0%
geomean                                18.63µ

                            │ benchmark-results.txt │
                            │         B/op          │
InterpreterCreation-4                  2.027Mi ± 0%
ComponentLoad-4                        2.180Mi ± 0%
ComponentExecute-4                     1.203Ki ± 0%
PoolContention/workers-1-4             1.203Ki ± 0%
PoolContention/workers-2-4             1.203Ki ± 0%
PoolContention/workers-4-4             1.203Ki ± 0%
PoolContention/workers-8-4             1.203Ki ± 0%
PoolContention/workers-16-4            1.203Ki ± 0%
ComponentLifecycle-4                   2.183Mi ± 0%
SourceValidation-4                     1.984Ki ± 0%
RegistryConcurrent-4                   1.133Ki ± 0%
LoaderLoadFromString-4                 2.182Mi ± 0%
geomean                                15.25Ki

                            │ benchmark-results.txt │
                            │       allocs/op       │
InterpreterCreation-4                   15.68k ± 0%
ComponentLoad-4                         18.02k ± 0%
ComponentExecute-4                       25.00 ± 0%
PoolContention/workers-1-4               25.00 ± 0%
PoolContention/workers-2-4               25.00 ± 0%
PoolContention/workers-4-4               25.00 ± 0%
PoolContention/workers-8-4               25.00 ± 0%
PoolContention/workers-16-4              25.00 ± 0%
ComponentLifecycle-4                    18.07k ± 0%
SourceValidation-4                       32.00 ± 0%
RegistryConcurrent-4                     2.000 ± 0%
LoaderLoadFromString-4                  18.06k ± 0%
geomean                                  183.3

cpu: AMD EPYC 9V74 80-Core Processor                
                            │ baseline-bench.txt │
                            │       sec/op       │
InterpreterCreation-4               7.126m ± 58%
ComponentLoad-4                     3.481m ±  1%
ComponentExecute-4                  1.834µ ±  0%
PoolContention/workers-1-4          1.014µ ±  2%
PoolContention/workers-2-4          1.010µ ±  1%
PoolContention/workers-4-4          1.008µ ±  0%
PoolContention/workers-8-4          1.013µ ±  1%
PoolContention/workers-16-4         1.013µ ±  0%
ComponentLifecycle-4                3.497m ±  1%
SourceValidation-4                  2.103µ ±  0%
RegistryConcurrent-4                727.9n ±  6%
LoaderLoadFromString-4              3.543m ±  1%
geomean                             17.65µ

                            │ baseline-bench.txt │
                            │        B/op        │
InterpreterCreation-4               2.027Mi ± 0%
ComponentLoad-4                     2.180Mi ± 0%
ComponentExecute-4                  1.203Ki ± 0%
PoolContention/workers-1-4          1.203Ki ± 0%
PoolContention/workers-2-4          1.203Ki ± 0%
PoolContention/workers-4-4          1.203Ki ± 0%
PoolContention/workers-8-4          1.203Ki ± 0%
PoolContention/workers-16-4         1.203Ki ± 0%
ComponentLifecycle-4                2.183Mi ± 0%
SourceValidation-4                  1.984Ki ± 0%
RegistryConcurrent-4                1.133Ki ± 0%
LoaderLoadFromString-4              2.182Mi ± 0%
geomean                             15.25Ki

                            │ baseline-bench.txt │
                            │     allocs/op      │
InterpreterCreation-4                15.68k ± 0%
ComponentLoad-4                      18.02k ± 0%
ComponentExecute-4                    25.00 ± 0%
PoolContention/workers-1-4            25.00 ± 0%
PoolContention/workers-2-4            25.00 ± 0%
PoolContention/workers-4-4            25.00 ± 0%
PoolContention/workers-8-4            25.00 ± 0%
PoolContention/workers-16-4           25.00 ± 0%
ComponentLifecycle-4                 18.07k ± 0%
SourceValidation-4                    32.00 ± 0%
RegistryConcurrent-4                  2.000 ± 0%
LoaderLoadFromString-4               18.06k ± 0%
geomean                               183.3

pkg: github.com/GoCodeAlone/workflow/middleware
cpu: AMD EPYC 7763 64-Core Processor                
                                  │ benchmark-results.txt │
                                  │        sec/op         │
CircuitBreakerDetection-4                     285.2n ± 7%
CircuitBreakerExecution_Success-4             21.39n ± 0%
CircuitBreakerExecution_Failure-4             66.22n ± 0%
geomean                                       73.92n

                                  │ benchmark-results.txt │
                                  │         B/op          │
CircuitBreakerDetection-4                    144.0 ± 0%
CircuitBreakerExecution_Success-4            0.000 ± 0%
CircuitBreakerExecution_Failure-4            0.000 ± 0%
geomean                                                 ¹
¹ summaries must be >0 to compute geomean

                                  │ benchmark-results.txt │
                                  │       allocs/op       │
CircuitBreakerDetection-4                    1.000 ± 0%
CircuitBreakerExecution_Success-4            0.000 ± 0%
CircuitBreakerExecution_Failure-4            0.000 ± 0%
geomean                                                 ¹
¹ summaries must be >0 to compute geomean

cpu: AMD EPYC 9V74 80-Core Processor                
                                  │ baseline-bench.txt │
                                  │       sec/op       │
CircuitBreakerDetection-4                  298.4n ± 4%
CircuitBreakerExecution_Success-4          22.68n ± 1%
CircuitBreakerExecution_Failure-4          70.91n ± 0%
geomean                                    78.30n

                                  │ baseline-bench.txt │
                                  │        B/op        │
CircuitBreakerDetection-4                 144.0 ± 0%
CircuitBreakerExecution_Success-4         0.000 ± 0%
CircuitBreakerExecution_Failure-4         0.000 ± 0%
geomean                                              ¹
¹ summaries must be >0 to compute geomean

                                  │ baseline-bench.txt │
                                  │     allocs/op      │
CircuitBreakerDetection-4                 1.000 ± 0%
CircuitBreakerExecution_Success-4         0.000 ± 0%
CircuitBreakerExecution_Failure-4         0.000 ± 0%
geomean                                              ¹
¹ summaries must be >0 to compute geomean

pkg: github.com/GoCodeAlone/workflow/module
cpu: AMD EPYC 7763 64-Core Processor                
                                 │ benchmark-results.txt │
                                 │        sec/op         │
IaCStateBackend_InProcess-4                 321.1n ± 28%
IaCStateBackend_GRPC-4                      9.455m ±  3%
JQTransform_Simple-4                        654.7n ± 37%
JQTransform_ObjectConstruction-4            1.494µ ±  1%
JQTransform_ArraySelect-4                   3.414µ ±  1%
JQTransform_Complex-4                       38.92µ ±  1%
JQTransform_Throughput-4                    1.816µ ±  0%
SSEPublishDelivery-4                        65.33n ±  1%
geomean                                     3.835µ

                                 │ benchmark-results.txt │
                                 │         B/op          │
IaCStateBackend_InProcess-4                416.0 ±  0%
IaCStateBackend_GRPC-4                   5.844Mi ± 10%
JQTransform_Simple-4                     1.273Ki ±  0%
JQTransform_ObjectConstruction-4         1.773Ki ±  0%
JQTransform_ArraySelect-4                2.625Ki ±  0%
JQTransform_Complex-4                    16.22Ki ±  0%
JQTransform_Throughput-4                 1.984Ki ±  0%
SSEPublishDelivery-4                       0.000 ±  0%
geomean                                                ¹
¹ summaries must be >0 to compute geomean

                                 │ benchmark-results.txt │
                                 │       allocs/op       │
IaCStateBackend_InProcess-4                 2.000 ± 0%
IaCStateBackend_GRPC-4                     6.832k ± 0%
JQTransform_Simple-4                        10.00 ± 0%
JQTransform_ObjectConstruction-4            15.00 ± 0%
JQTransform_ArraySelect-4                   30.00 ± 0%
JQTransform_Complex-4                       324.0 ± 0%
JQTransform_Throughput-4                    17.00 ± 0%
SSEPublishDelivery-4                        0.000 ± 0%
geomean                                                ¹
¹ summaries must be >0 to compute geomean

cpu: AMD EPYC 9V74 80-Core Processor                
                                 │ baseline-bench.txt │
                                 │       sec/op       │
IaCStateBackend_InProcess-4              294.9n ± 34%
IaCStateBackend_GRPC-4                   10.21m ±  1%
JQTransform_Simple-4                     641.1n ± 60%
JQTransform_ObjectConstruction-4         1.621µ ±  1%
JQTransform_ArraySelect-4                3.659µ ±  0%
JQTransform_Complex-4                    43.30µ ±  1%
JQTransform_Throughput-4                 1.946µ ±  0%
SSEPublishDelivery-4                     64.63n ±  1%
geomean                                  3.975µ

                                 │ baseline-bench.txt │
                                 │        B/op        │
IaCStateBackend_InProcess-4              416.0 ± 0%
IaCStateBackend_GRPC-4                 5.908Mi ± 5%
JQTransform_Simple-4                   1.273Ki ± 0%
JQTransform_ObjectConstruction-4       1.773Ki ± 0%
JQTransform_ArraySelect-4              2.625Ki ± 0%
JQTransform_Complex-4                  16.22Ki ± 0%
JQTransform_Throughput-4               1.984Ki ± 0%
SSEPublishDelivery-4                     0.000 ± 0%
geomean                                             ¹
¹ summaries must be >0 to compute geomean

                                 │ baseline-bench.txt │
                                 │     allocs/op      │
IaCStateBackend_InProcess-4              2.000 ± 0%
IaCStateBackend_GRPC-4                  6.858k ± 0%
JQTransform_Simple-4                     10.00 ± 0%
JQTransform_ObjectConstruction-4         15.00 ± 0%
JQTransform_ArraySelect-4                30.00 ± 0%
JQTransform_Complex-4                    324.0 ± 0%
JQTransform_Throughput-4                 17.00 ± 0%
SSEPublishDelivery-4                     0.000 ± 0%
geomean                                             ¹
¹ summaries must be >0 to compute geomean

pkg: github.com/GoCodeAlone/workflow/schema
cpu: AMD EPYC 7763 64-Core Processor                
                                    │ benchmark-results.txt │
                                    │        sec/op         │
SchemaValidation_Simple-4                       1.117µ ± 5%
SchemaValidation_AllFields-4                    1.672µ ± 2%
SchemaValidation_FormatValidation-4             1.603µ ± 3%
SchemaValidation_ManySchemas-4                  1.804µ ± 4%
geomean                                         1.524µ

                                    │ benchmark-results.txt │
                                    │         B/op          │
SchemaValidation_Simple-4                      0.000 ± 0%
SchemaValidation_AllFields-4                   0.000 ± 0%
SchemaValidation_FormatValidation-4            0.000 ± 0%
SchemaValidation_ManySchemas-4                 0.000 ± 0%
geomean                                                   ¹
¹ summaries must be >0 to compute geomean

                                    │ benchmark-results.txt │
                                    │       allocs/op       │
SchemaValidation_Simple-4                      0.000 ± 0%
SchemaValidation_AllFields-4                   0.000 ± 0%
SchemaValidation_FormatValidation-4            0.000 ± 0%
SchemaValidation_ManySchemas-4                 0.000 ± 0%
geomean                                                   ¹
¹ summaries must be >0 to compute geomean

cpu: AMD EPYC 9V74 80-Core Processor                
                                    │ baseline-bench.txt │
                                    │       sec/op       │
SchemaValidation_Simple-4                    1.088µ ± 2%
SchemaValidation_AllFields-4                 1.646µ ± 2%
SchemaValidation_FormatValidation-4          1.580µ ± 4%
SchemaValidation_ManySchemas-4               1.597µ ± 1%
geomean                                      1.458µ

                                    │ baseline-bench.txt │
                                    │        B/op        │
SchemaValidation_Simple-4                   0.000 ± 0%
SchemaValidation_AllFields-4                0.000 ± 0%
SchemaValidation_FormatValidation-4         0.000 ± 0%
SchemaValidation_ManySchemas-4              0.000 ± 0%
geomean                                                ¹
¹ summaries must be >0 to compute geomean

                                    │ baseline-bench.txt │
                                    │     allocs/op      │
SchemaValidation_Simple-4                   0.000 ± 0%
SchemaValidation_AllFields-4                0.000 ± 0%
SchemaValidation_FormatValidation-4         0.000 ± 0%
SchemaValidation_ManySchemas-4              0.000 ± 0%
geomean                                                ¹
¹ summaries must be >0 to compute geomean

pkg: github.com/GoCodeAlone/workflow/store
cpu: AMD EPYC 7763 64-Core Processor                
                                   │ benchmark-results.txt │
                                   │        sec/op         │
EventStoreAppend_InMemory-4                   1.168µ ± 25%
EventStoreAppend_SQLite-4                     1.306m ±  2%
GetTimeline_InMemory/events-10-4              13.50µ ±  5%
GetTimeline_InMemory/events-50-4              76.06µ ±  3%
GetTimeline_InMemory/events-100-4             149.1µ ± 19%
GetTimeline_InMemory/events-500-4             622.8µ ±  1%
GetTimeline_InMemory/events-1000-4            1.271m ±  1%
GetTimeline_SQLite/events-10-4                105.6µ ±  1%
GetTimeline_SQLite/events-50-4                245.4µ ±  0%
GetTimeline_SQLite/events-100-4               422.5µ ±  2%
GetTimeline_SQLite/events-500-4               1.771m ±  1%
GetTimeline_SQLite/events-1000-4              3.456m ±  1%
geomean                                       219.3µ

                                   │ benchmark-results.txt │
                                   │         B/op          │
EventStoreAppend_InMemory-4                     848.0 ± 6%
EventStoreAppend_SQLite-4                     1.985Ki ± 2%
GetTimeline_InMemory/events-10-4              7.953Ki ± 0%
GetTimeline_InMemory/events-50-4              46.62Ki ± 0%
GetTimeline_InMemory/events-100-4             94.48Ki ± 0%
GetTimeline_InMemory/events-500-4             472.8Ki ± 0%
GetTimeline_InMemory/events-1000-4            944.3Ki ± 0%
GetTimeline_SQLite/events-10-4                16.74Ki ± 0%
GetTimeline_SQLite/events-50-4                87.14Ki ± 0%
GetTimeline_SQLite/events-100-4               175.4Ki ± 0%
GetTimeline_SQLite/events-500-4               846.1Ki ± 0%
GetTimeline_SQLite/events-1000-4              1.639Mi ± 0%
geomean                                       67.74Ki

                                   │ benchmark-results.txt │
                                   │       allocs/op       │
EventStoreAppend_InMemory-4                     7.000 ± 0%
EventStoreAppend_SQLite-4                       53.00 ± 0%
GetTimeline_InMemory/events-10-4                125.0 ± 0%
GetTimeline_InMemory/events-50-4                653.0 ± 0%
GetTimeline_InMemory/events-100-4              1.306k ± 0%
GetTimeline_InMemory/events-500-4              6.514k ± 0%
GetTimeline_InMemory/events-1000-4             13.02k ± 0%
GetTimeline_SQLite/events-10-4                  382.0 ± 0%
GetTimeline_SQLite/events-50-4                 1.852k ± 0%
GetTimeline_SQLite/events-100-4                3.681k ± 0%
GetTimeline_SQLite/events-500-4                18.54k ± 0%
GetTimeline_SQLite/events-1000-4               37.29k ± 0%
geomean                                        1.162k

cpu: AMD EPYC 9V74 80-Core Processor                
                                   │ baseline-bench.txt │
                                   │       sec/op       │
EventStoreAppend_InMemory-4                1.171µ ± 13%
EventStoreAppend_SQLite-4                  1.020m ±  1%
GetTimeline_InMemory/events-10-4           13.40µ ±  4%
GetTimeline_InMemory/events-50-4           72.80µ ± 20%
GetTimeline_InMemory/events-100-4          118.4µ ±  1%
GetTimeline_InMemory/events-500-4          606.7µ ±  2%
GetTimeline_InMemory/events-1000-4         1.218m ±  1%
GetTimeline_SQLite/events-10-4             88.57µ ±  3%
GetTimeline_SQLite/events-50-4             232.3µ ±  2%
GetTimeline_SQLite/events-100-4            410.2µ ±  2%
GetTimeline_SQLite/events-500-4            1.769m ±  1%
GetTimeline_SQLite/events-1000-4           3.470m ±  2%
geomean                                    204.3µ

                                   │ baseline-bench.txt │
                                   │        B/op        │
EventStoreAppend_InMemory-4                 767.5 ± 12%
EventStoreAppend_SQLite-4                 1.985Ki ±  2%
GetTimeline_InMemory/events-10-4          7.953Ki ±  0%
GetTimeline_InMemory/events-50-4          46.62Ki ±  0%
GetTimeline_InMemory/events-100-4         94.48Ki ±  0%
GetTimeline_InMemory/events-500-4         472.8Ki ±  0%
GetTimeline_InMemory/events-1000-4        944.3Ki ±  0%
GetTimeline_SQLite/events-10-4            16.74Ki ±  0%
GetTimeline_SQLite/events-50-4            87.14Ki ±  0%
GetTimeline_SQLite/events-100-4           175.4Ki ±  0%
GetTimeline_SQLite/events-500-4           846.1Ki ±  0%
GetTimeline_SQLite/events-1000-4          1.639Mi ±  0%
geomean                                   67.18Ki

                                   │ baseline-bench.txt │
                                   │     allocs/op      │
EventStoreAppend_InMemory-4                  7.000 ± 0%
EventStoreAppend_SQLite-4                    53.00 ± 0%
GetTimeline_InMemory/events-10-4             125.0 ± 0%
GetTimeline_InMemory/events-50-4             653.0 ± 0%
GetTimeline_InMemory/events-100-4           1.306k ± 0%
GetTimeline_InMemory/events-500-4           6.514k ± 0%
GetTimeline_InMemory/events-1000-4          13.02k ± 0%
GetTimeline_SQLite/events-10-4               382.0 ± 0%
GetTimeline_SQLite/events-50-4              1.852k ± 0%
GetTimeline_SQLite/events-100-4             3.681k ± 0%
GetTimeline_SQLite/events-500-4             18.54k ± 0%
GetTimeline_SQLite/events-1000-4            37.29k ± 0%
geomean                                     1.162k

Benchmarks run with go test -bench=. -benchmem -count=6.
Regressions ≥ 20% are flagged. Results compared via benchstat.

intel352 and others added 2 commits May 16, 2026 01:35
Lint blocker (4 SA1019 staticcheck deprecation hits — proves the godoc
marker is working):
- cmd/wfctl/infra_apply_in_process_test.go:77 (was missing from inventory)
- iac/conformance/scenario_delete_action.go:74
- iac/conformance/scenario_replace_cascade_preserves_dependents.go:92
- iac/conformance/scenario_upsert_on_already_exists.go:88

Folded the trivial Phase 4 mechanical migration (4 single-line renames
ApplyPlan → ApplyPlanWithHooks(..., ApplyPlanHooks{})) into this Phase 1
PR. Separate followup PR for 4 single-line renames would be silly.

Copilot finding 1: doc.go duplicate package comment — DELETED doc.go;
extended apply.go's existing package-level comment with the v1/v2
contract pointer paragraph (single source of truth).

Copilot finding 2: design doc hard-coded line:78 reference will drift —
acknowledged but not changed (file:line will rot, but the godoc marker
itself is symbol-anchored; design doc is an artifact-of-record from the
specific commit, not a long-lived contract).

Verification:
- GOWORK=off go build ./... PASS
- GOWORK=off go vet ./iac/wfctlhelpers/ ./iac/conformance/ ./cmd/wfctl/ PASS

🤖 Generated with [Claude Code](https://claude.com/claude-code)

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

Internal superpowers state file slipped in via git add -A in the prior
fixup commit. Add .claude/ to .gitignore + remove from index.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 16, 2026 05:35
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 9 changed files in this pull request and generated 4 comments.

Comments suppressed due to low confidence (2)

docs/migrations/2026-05-16-v2-lifecycle-phase1-inventory.md:25

  • This section is titled “v1 wfctlhelpers.ApplyPlan callers” and the table entries are described as needing a Phase 4 rename, but the referenced conformance files now call ApplyPlanWithHooks. Please update the heading/table/classifications to match the post-change reality (e.g., note they’ve already migrated and ApplyPlan has no remaining in-repo callers outside wfctlhelpers’ own tests).
### v1 `wfctlhelpers.ApplyPlan` callers (production)

| File:Line | Classification | Notes |
|-----------|----------------|-------|
| `iac/conformance/scenario_upsert_on_already_exists.go:88` | MIGRATE-NEEDED (Phase 4) — TRIVIAL | Conformance scenario; `ApplyPlanWithHooks(..., ApplyPlanHooks{})` rename suffices. **Phase 5 prerequisite** — Phase 5 removes ApplyPlan, so Phase 4 must precede. |

docs/plans/2026-05-16-v2-lifecycle-phase1-design.md:36

  • The artifact list references iac/wfctlhelpers/doc.go and hard-codes iac/wfctlhelpers/apply.go:78, but there is no doc.go file in-tree and the ApplyPlan declaration/Deprecated marker aren’t at that line anymore. Consider either adding the missing doc.go (if intended) and/or avoiding line-number pinning in docs (prefer symbol names/links) to keep these references stable.
Single-repo (workflow), 1-PR deliverable. Four artifacts:
- `docs/migrations/2026-05-16-v2-lifecycle-phase1-inventory.md` — the inventory document (per-caller table + classification rationale)
- `decisions/0040-v2-action-lifecycle-provider-compatibility.md` — ADR recording: (a) the provider-side compatibility contract; (b) the explicit consequence that Phase 2 is a coordinated hard-cutover per ADR 0024
- `iac/wfctlhelpers/doc.go` — Go doc.go file embedding a SHORT version of the inventory + provider-expectation pointer to the migration doc
- **`iac/wfctlhelpers/apply.go:78` — add `// Deprecated: use ApplyPlanWithHooks` godoc to the EXPORTED `ApplyPlan` function only** (the `applyPlanWithEnvProvider` and `applyPlanWithEnvProviderAndHooks` helpers are unexported — `gopls`/`staticcheck` ignore Deprecated markers on unexported identifiers, so they get NO marker)

Comment on lines +13 to +17
- **Phase 1 (this document)**: inventory + provider-compatibility ADR + Deprecated marker
- **Phase 2**: design + ship v2-hooks-over-gRPC contract (HARD-CUTOVER per ADR 0024)
- **Phase 3**: migrate plugins to v2 contract (per-plugin manual + codemod for canonical-form plugins)
- **Phase 4**: migrate 3 conformance scenarios from `ApplyPlan` to `ApplyPlanWithHooks`
- **Phase 5**: remove `wfctlhelpers.ApplyPlan` entirely
- ADR 0040 (`decisions/0040-v2-action-lifecycle-provider-compatibility.md`) — provider-side compatibility contract
- PR #639 — v2 hooks engine landing
- `iac/wfctlhelpers/apply.go` — engine source (with `// Deprecated:` marker on `ApplyPlan` per Phase 1)
- `iac/wfctlhelpers/doc.go` — in-package contract pointer
Comment on lines +18 to +22
**Explicitly out of scope for Phase 1** (deferred to Phase 2-5 design passes):
- Phase 2: design + ship the v2-hooks-over-gRPC contract — must be a HARD-CUTOVER coordinated PR cascade across workflow + 4 plugin repos per ADR 0024 (no compat shim, no graceful fallback)
- Phase 3: migrate plugins to emit hooks-aware Apply responses (per-repo PRs). **Phase 3 also bumps `iac-codemod`'s `applyCanonicalCallExpr` constant + updates `rewriteApplyBody` + `isAlreadyDelegatedApplyBody` + `runAssertApplyDelegatesToHelper` AST functions in lockstep** so the codemod becomes the migration driver. (Cycle-2 review correctly flagged that bumping ONLY the constant in Phase 1 is theatre — constant is `//nolint:unused`, not consumed by rewriter; risks leaving codemod internally inconsistent.)
- Phase 4: migrate the 3 conformance scenarios from `ApplyPlan(...)` to `ApplyPlanWithHooks(..., ApplyPlanHooks{})` (trivial mechanical rename; HARD PREREQUISITE for Phase 5 since Phase 5 removes ApplyPlan)
- Phase 5: remove `wfctlhelpers.ApplyPlan` entirely (after Phase 4 + plugin canonical-form propagation)
Comment on lines +48 to +50
- **Phase 4 conformance scenario migration is a trivial 6-line PR** (rename 3 call sites). HARD prerequisite for Phase 5.

- **Phase 5 ApplyPlan removal** gates on Phase 4 + plugin canonical-form propagation (DO already canonical; aws/gcp/azure must migrate to either canonical OR Phase-2-direct path).
intel352 and others added 2 commits May 16, 2026 01:49
…ed into Phase 1

5 Copilot findings — all doc-consistency about Phase 4 status:
- Design doc still listed Phase 4 as out-of-scope; updated to SHIPPED
- Inventory doc claimed Phase 4 future work; updated to SHIPPED
- Inventory doc referenced deleted iac/wfctlhelpers/doc.go; removed
- ADR 0040 said Phase 4 future trivial 6-line PR; updated to SHIPPED
- Phase 5 gating updated: was Phase 4 prerequisite, now only Phase 2+3

Inventory now lists 4 migrated callers (3 conformance + 1 test file).
Symbol references (iac/wfctlhelpers.ApplyPlan) replace file:line where
the design doc was hard-coding apply.go:78.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…e-work refs with shipped status

5 remaining stale refs in design doc:
- apply.go:78 hard-coded → iac/wfctlhelpers.ApplyPlan symbol
- 3 conformance row classifications → MIGRATED in this PR
- Self-challenge doubt 2 → updated to reflect mid-execution fold-in
- Out-of-scope Phase 4 → struck through SHIPPED
- Phase 5 gating → references Phase 2+3 (Phase 4 already shipped)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 16, 2026 06:02
@intel352 intel352 merged commit f5ec18e into main May 16, 2026
28 checks passed
@intel352 intel352 deleted the feat/v2-lifecycle-inventory-planning branch May 16, 2026 06:02
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 9 changed files in this pull request and generated 2 comments.

Comment on lines +34 to +38
Single-repo (workflow), 1-PR deliverable. Four artifacts:
- `docs/migrations/2026-05-16-v2-lifecycle-phase1-inventory.md` — the inventory document (per-caller table + classification rationale)
- `decisions/0040-v2-action-lifecycle-provider-compatibility.md` — ADR recording: (a) the provider-side compatibility contract; (b) the explicit consequence that Phase 2 is a coordinated hard-cutover per ADR 0024
- `iac/wfctlhelpers/doc.go` — Go doc.go file embedding a SHORT version of the inventory + provider-expectation pointer to the migration doc
- **`iac/wfctlhelpers.ApplyPlan` symbol — add `// Deprecated: use ApplyPlanWithHooks` godoc** (grep `^func ApplyPlan` in `iac/wfctlhelpers/apply.go`). The EXPORTED `ApplyPlan` function only — `applyPlanWithEnvProvider` + `applyPlanWithEnvProviderAndHooks` helpers are unexported and `gopls`/`staticcheck` ignore Deprecated markers on unexported identifiers.
Comment on lines +80 to +81
- Phase 4 conformance scenario migration — separate trivial PR
- Phase 5 ApplyPlan removal — gates on Phase 4 completion + plugin canonical-form propagation
intel352 added a commit that referenced this pull request May 20, 2026
#743)

* feat(iac): workflow#640 Phase 5 — remove legacy wfctlhelpers.ApplyPlan

Per docs/migrations/2026-05-16-v2-lifecycle-phase1-inventory.md.

Phase 1 (PR #691) + Phase 2 (PR #694) + Phase 2.5 (PR #697) +
Phase 3 (per-plugin migration) all shipped. Production code has
been on ApplyPlanWithHooks for weeks. This PR closes the loop by
removing the deprecated symbol.

Changes:

iac/wfctlhelpers/apply.go:
- Delete func ApplyPlan (the 2-line wrapper that delegated to
  applyPlanWithEnvProvider with nil hooks).
- Keep applyPlanWithEnvProvider as the postcondition-test seam —
  retained for apply_postcondition_test.go's panicky-env injection.

iac/wfctlhelpers/*_test.go:
- 10 test files migrated from `ApplyPlan(ctx, p, plan)` to
  `ApplyPlanWithHooks(ctx, p, plan, ApplyPlanHooks{})`. Empty-hooks
  form is semantically identical to the pre-deletion ApplyPlan call.

docs/migrations/2026-05-16-v2-lifecycle-phase1-inventory.md:
- Phase 5 marker flipped to SHIPPED.

Verification:
  GOWORK=off go test ./... -count=1 (all green)

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

* docs(iac): close v2 lifecycle migration notes

* docs(iac): clarify manifest lifecycle metadata

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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