Skip to content

feat(wfctl): interactive ci generate wizard + multisite real-world regen evidence (PR4/7)#802

Merged
intel352 merged 4 commits into
mainfrom
feat/wfctl-ci-wizard
May 30, 2026
Merged

feat(wfctl): interactive ci generate wizard + multisite real-world regen evidence (PR4/7)#802
intel352 merged 4 commits into
mainfrom
feat/wfctl-ci-wizard

Conversation

@intel352
Copy link
Copy Markdown
Contributor

What

PR4 of the wfctl secrets wizard + smart CI cascade. Adds the interactive ci generate wizard over cigen, and the honest real-world validation artifact (generate against our own gocodealone-multisite).

Task 17 — interactive ci wizard

wfctl ci generate with no --platform on a TTY (or --interactive) walks an analyzed CIPlan: select platform, runner, toggle smoke/migrations/plan-guard, shows Warnings[], confirms before write (diff preview if target exists). Override logic is a pure applyWizardOverrides(plan, choices) (unit-tested by injection); bubbletea is a thin front-end. Non-TTY + no --platform errors clearly (no hang).

Task 18 — multisite real-world regen evidence (demonstration-fidelity)

Ran the real built binary against the real gocodealone-multisite/{deploy,deploy.prereq}.yaml and committed the literal output under cigen/testdata/multisite/:

  • plan.json (real CIPlan incl. 3 honest warnings), generated-infra.yml (real ci generate output), GAP.md (honest analysis sourced from the measured 384-line diff + warnings).
  • Matched (functional): PR/push/dispatch triggers, plugin-install, two-phase prereq→deploy, secret env: block (1:1-named), plan-guard, healthz smoke, migrations step.
  • Not derivable (stays hand-authored): hash-suffixed DB secret MULTISITE_PG__URI_<hash>, SPACES_access_keySPACES_ACCESS_KEY case, GHCR image-wait, GHCR_CREDENTIALS derivation, GA4 apply step, multi-route smoke matrix, concurrency, SHA-pinned actions, dispatch inputs.
  • The live infra.yml is NOT modified (ADR 0004). The claim is exactly the measured diff + warnings — no faked equivalence.

Runtime defect fixed (found via the honest gap analysis)

The generated migrations step emitted wfctl ci run --phase migrate — but ci run only accepts build/test/deploy, so it would fail at runtime. Fixed in both GHA + GitLab renderers (shared migrationsUpCommand) to emit wfctl migrations up --config <cfg> (the real subcommand the live workflow uses). Added --config-path-alias/--phase-config-alias so committed artifacts show clean deploy.yaml paths.

Verification

  • GOWORK=off go test ./cigen/ ./cmd/wfctl/ok; golangci-lint0 issues.
  • New tests: applyWizardOverrides toggles, TestRenderGitHubActions_MigrationsStep/_WithEnv, TestAnalyze_MultisiteGolden.

Notes

  • Copilot review not requested (service down per operator).

🤖 Generated with Claude Code

intel352 and others added 3 commits May 30, 2026 17:24
When --platform is absent and stdin is a TTY, runCIGenerate drives an
interactive wizard that: selects platform (github_actions|gitlab_ci),
runner label (ubuntu-latest|self-hosted|custom), toggles smoke/migrations/
plan-guard from Analyze-derived defaults, surfaces plan.Warnings, and
confirms write before emitting files. Non-TTY + no --platform errors with
"specify --platform for non-interactive generation". The override logic
lives in the pure applyWizardOverrides(plan, wizardChoices) function so
it is fully unit-testable without a TTY; 7 new unit tests cover all toggles.

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

Copies gocodealone-multisite deploy.yaml + deploy.prereq.yaml verbatim into
cigen/testdata/multisite/ and commits the REAL outputs of:
  wfctl-pr4 ci plan -c ... --phase-config ... --out plan.json
  wfctl-pr4 ci generate -c ... --platform github_actions --write
  diff -u .../infra.yml generated-infra.yml

The real diff is 386 lines (249 removed from 283-line hand-written file,
100 added to produce 134-line generated file). GAP.md documents matched
derivations (two-phase plan/apply, plan-guard, secrets env block, migrations,
smoke URL, plugin install) and not-derivable features (hash-suffixed DB
secret, SPACES casing alias, image wait loop, GHCR_CREDENTIALS derivation,
phase selector inputs, concurrency, continue-on-error) sourced from the real
diff and real plan.json warnings[]. Two real bugs noted: paths: filter uses
testdata paths instead of repo-root paths when not run from project root;
migrations step uses wrong subcommand. Live infra.yml NOT modified (ADR 0004).

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

The generated migrations step emitted `wfctl ci run --config <cfg> --phase
migrate`, but `wfctl ci run` only accepts phases build|test|deploy and errors
on anything else ("unknown phase: migrate") — the step would fail at runtime
(looks-right-but-doesn't-run). Surfaced honestly in the multisite GAP.md.

Fix: render_gha.go + render_gitlab.go now emit `wfctl migrations up --config
'<cfg>'` via a shared migrationsUpCommand helper. The DB-url secret is already
wired into the apply job env: via the secrets union. A new MigrationsSpec.Env
field, when set, appends `--env <env>`; otherwise it is omitted. Adds two
render tests asserting the step contains `wfctl migrations up --config` and
does NOT contain `--phase migrate` (plus an --env variant).

Also adds `--config-path-alias` / `--phase-config-alias` flags to `ci plan`
and `ci generate` (wired to the existing cigen Options.ConfigPathAlias + new
PhaseConfigAlias) so generated CI shows clean repo-relative config paths.

Regenerated multisite evidence with the fixed binary + aliases:
- plan.json: clean deploy.yaml / deploy.prereq.yaml phase paths (warnings
  unchanged: DB hash-suffix + 2x SPACES casing)
- generated-infra.yml: migrations step now `wfctl migrations up --config
  'deploy.yaml'`; paths: filters now `deploy.yaml` / `deploy.prereq.yaml`
- diff vs live infra.yml: 384 lines (248 removed, 99 added)
- GAP.md: migrations + paths moved out of "got WRONG" (both FIXED); added
  `--env prod --format json` as a not-derivable operational refinement;
  genuinely-not-derivable items retained. Live infra.yml NOT modified (ADR 0004).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@codecov
Copy link
Copy Markdown

codecov Bot commented May 30, 2026

Codecov Report

❌ Patch coverage is 35.57692% with 67 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
cmd/wfctl/ci_wizard.go 12.90% 54 Missing ⚠️
cmd/wfctl/ci.go 56.52% 9 Missing and 1 partial ⚠️
cigen/analyze.go 25.00% 1 Missing and 2 partials ⚠️

📢 Thoughts on this report? Let us know!

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 30, 2026

⏱ Benchmark Results

No significant performance regressions detected.

benchstat comparison (baseline → PR)
## benchstat: baseline → PR
baseline-bench.txt:307: parsing iteration count: invalid syntax
baseline-bench.txt:304790: parsing iteration count: invalid syntax
baseline-bench.txt:586890: parsing iteration count: invalid syntax
baseline-bench.txt:911608: parsing iteration count: invalid syntax
baseline-bench.txt:1211720: parsing iteration count: invalid syntax
baseline-bench.txt:1496211: parsing iteration count: invalid syntax
benchmark-results.txt:307: parsing iteration count: invalid syntax
benchmark-results.txt:334610: parsing iteration count: invalid syntax
benchmark-results.txt:639747: parsing iteration count: invalid syntax
benchmark-results.txt:989983: parsing iteration count: invalid syntax
benchmark-results.txt:1302467: parsing iteration count: invalid syntax
benchmark-results.txt:1648194: parsing iteration count: invalid syntax
goos: linux
goarch: amd64
pkg: github.com/GoCodeAlone/workflow/dynamic
cpu: AMD EPYC 7763 64-Core Processor                
                            │ baseline-bench.txt │
                            │       sec/op       │
InterpreterCreation-4               10.85m ± 53%
ComponentLoad-4                     4.321m ±  8%
ComponentExecute-4                  2.065µ ±  3%
PoolContention/workers-1-4          1.128µ ±  3%
PoolContention/workers-2-4          1.122µ ±  4%
PoolContention/workers-4-4          1.123µ ±  2%
PoolContention/workers-8-4          1.132µ ±  1%
PoolContention/workers-16-4         1.121µ ±  1%
ComponentLifecycle-4                4.127m ±  3%
SourceValidation-4                  2.450µ ±  2%
RegistryConcurrent-4                825.6n ±  2%
LoaderLoadFromString-4              4.323m ±  5%
geomean                             20.73µ

                            │ 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

cpu: AMD EPYC 9V74 80-Core Processor                
                            │ benchmark-results.txt │
                            │        sec/op         │
InterpreterCreation-4                  9.185m ± 63%
ComponentLoad-4                        3.446m ±  1%
ComponentExecute-4                     1.818µ ±  2%
PoolContention/workers-1-4             1.014µ ±  2%
PoolContention/workers-2-4             1.036µ ±  2%
PoolContention/workers-4-4             1.032µ ±  2%
PoolContention/workers-8-4             1.009µ ±  1%
PoolContention/workers-16-4            1.018µ ±  1%
ComponentLifecycle-4                   3.483m ±  1%
SourceValidation-4                     2.087µ ±  1%
RegistryConcurrent-4                   729.4n ±  7%
LoaderLoadFromString-4                 3.510m ±  0%
geomean                                18.04µ

                            │ 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

pkg: github.com/GoCodeAlone/workflow/middleware
cpu: AMD EPYC 7763 64-Core Processor                
                                  │ baseline-bench.txt │
                                  │       sec/op       │
CircuitBreakerDetection-4                  294.1n ± 6%
CircuitBreakerExecution_Success-4          21.58n ± 0%
CircuitBreakerExecution_Failure-4          66.12n ± 0%
geomean                                    74.88n

                                  │ 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

cpu: AMD EPYC 9V74 80-Core Processor                
                                  │ benchmark-results.txt │
                                  │        sec/op         │
CircuitBreakerDetection-4                    302.1n ± 16%
CircuitBreakerExecution_Success-4            22.67n ±  0%
CircuitBreakerExecution_Failure-4            70.98n ±  0%
geomean                                      78.62n

                                  │ 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

pkg: github.com/GoCodeAlone/workflow/module
cpu: AMD EPYC 7763 64-Core Processor                
                                 │ baseline-bench.txt │
                                 │       sec/op       │
IaCStateBackend_InProcess-4              368.6n ± 15%
IaCStateBackend_GRPC-4                   10.16m ±  1%
JQTransform_Simple-4                     732.9n ± 35%
JQTransform_ObjectConstruction-4         1.630µ ±  3%
JQTransform_ArraySelect-4                3.713µ ±  1%
JQTransform_Complex-4                    40.34µ ±  2%
JQTransform_Throughput-4                 1.943µ ±  3%
SSEPublishDelivery-4                     64.61n ±  1%
geomean                                  4.127µ

                                 │ baseline-bench.txt │
                                 │        B/op        │
IaCStateBackend_InProcess-4              416.0 ± 0%
IaCStateBackend_GRPC-4                 5.792Mi ± 6%
JQTransform_Simple-4                   1.273Ki ± 0%
JQTransform_ObjectConstruction-4       1.773Ki ± 0%
JQTransform_ArraySelect-4              2.625Ki ± 0%
JQTransform_Complex-4                  16.31Ki ± 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.843k ± 0%
JQTransform_Simple-4                     10.00 ± 0%
JQTransform_ObjectConstruction-4         15.00 ± 0%
JQTransform_ArraySelect-4                30.00 ± 0%
JQTransform_Complex-4                    328.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                
                                 │ benchmark-results.txt │
                                 │        sec/op         │
IaCStateBackend_InProcess-4                 294.6n ± 30%
IaCStateBackend_GRPC-4                      10.25m ± 16%
JQTransform_Simple-4                        641.8n ± 30%
JQTransform_ObjectConstruction-4            1.403µ ±  1%
JQTransform_ArraySelect-4                   3.364µ ±  5%
JQTransform_Complex-4                       41.99µ ±  2%
JQTransform_Throughput-4                    1.717µ ±  0%
SSEPublishDelivery-4                        64.29n ±  0%
geomean                                     3.788µ

                                 │ benchmark-results.txt │
                                 │         B/op          │
IaCStateBackend_InProcess-4                416.0 ±  0%
IaCStateBackend_GRPC-4                   5.775Mi ± 12%
JQTransform_Simple-4                     1.273Ki ±  0%
JQTransform_ObjectConstruction-4         1.773Ki ±  0%
JQTransform_ArraySelect-4                2.625Ki ±  0%
JQTransform_Complex-4                    16.31Ki ±  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.854k ± 0%
JQTransform_Simple-4                        10.00 ± 0%
JQTransform_ObjectConstruction-4            15.00 ± 0%
JQTransform_ArraySelect-4                   30.00 ± 0%
JQTransform_Complex-4                       328.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                
                                    │ baseline-bench.txt │
                                    │       sec/op       │
SchemaValidation_Simple-4                    1.090µ ± 2%
SchemaValidation_AllFields-4                 1.651µ ± 2%
SchemaValidation_FormatValidation-4          1.581µ ± 1%
SchemaValidation_ManySchemas-4               1.812µ ± 4%
geomean                                      1.507µ

                                    │ 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

cpu: AMD EPYC 9V74 80-Core Processor                
                                    │ benchmark-results.txt │
                                    │        sec/op         │
SchemaValidation_Simple-4                      1.079µ ± 12%
SchemaValidation_AllFields-4                   1.623µ ±  2%
SchemaValidation_FormatValidation-4            1.559µ ±  1%
SchemaValidation_ManySchemas-4                 1.656µ ±  4%
geomean                                        1.458µ

                                    │ 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

pkg: github.com/GoCodeAlone/workflow/store
cpu: AMD EPYC 7763 64-Core Processor                
                                   │ baseline-bench.txt │
                                   │       sec/op       │
EventStoreAppend_InMemory-4                1.147µ ± 22%
EventStoreAppend_SQLite-4                  1.435m ±  3%
GetTimeline_InMemory/events-10-4           15.59µ ±  3%
GetTimeline_InMemory/events-50-4           86.45µ ±  5%
GetTimeline_InMemory/events-100-4          135.6µ ± 34%
GetTimeline_InMemory/events-500-4          687.7µ ±  1%
GetTimeline_InMemory/events-1000-4         1.412m ±  2%
GetTimeline_SQLite/events-10-4             123.4µ ±  1%
GetTimeline_SQLite/events-50-4             281.4µ ±  2%
GetTimeline_SQLite/events-100-4            451.6µ ±  2%
GetTimeline_SQLite/events-500-4            1.984m ±  2%
GetTimeline_SQLite/events-1000-4           3.952m ±  2%
geomean                                    239.7µ

                                   │ baseline-bench.txt │
                                   │        B/op        │
EventStoreAppend_InMemory-4                  757.5 ± 9%
EventStoreAppend_SQLite-4                  1.987Ki ± 1%
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.12Ki

                                   │ 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

cpu: AMD EPYC 9V74 80-Core Processor                
                                   │ benchmark-results.txt │
                                   │        sec/op         │
EventStoreAppend_InMemory-4                   1.051µ ± 13%
EventStoreAppend_SQLite-4                     1.020m ±  2%
GetTimeline_InMemory/events-10-4              13.80µ ±  4%
GetTimeline_InMemory/events-50-4              78.39µ ±  3%
GetTimeline_InMemory/events-100-4             160.9µ ± 14%
GetTimeline_InMemory/events-500-4             613.5µ ±  0%
GetTimeline_InMemory/events-1000-4            1.248m ±  1%
GetTimeline_SQLite/events-10-4                89.65µ ±  1%
GetTimeline_SQLite/events-50-4                238.5µ ±  1%
GetTimeline_SQLite/events-100-4               416.5µ ±  1%
GetTimeline_SQLite/events-500-4               1.784m ±  1%
GetTimeline_SQLite/events-1000-4              3.471m ±  1%
geomean                                       211.2µ

                                   │ benchmark-results.txt │
                                   │         B/op          │
EventStoreAppend_InMemory-4                     779.0 ± 6%
EventStoreAppend_SQLite-4                     1.982Ki ± 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.26Ki

                                   │ 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

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

…vidence + test

Code-review follow-up for PR4.

1. IMPORTANT: render_gha.go emitted a step-level `env:` on the migrations
   step re-declaring ${{ secrets.<DBEnv> }}, but deriveSecrets always adds the
   migrations DBEnv to the global secrets union (analyze.go), so it is already
   present in the apply job's job-level `env:` block. The step-level block was
   redundant and would have broken a minimal no-secrets plan. Removed it; the
   migration command still reads the DB secret via job-level env. (GitLab
   renderer relies on project CI/CD variables and had no step-level env.)

2. Added TestApplyWizardOverrides_MigrationsTruePreservesMigrations (symmetric
   to the existing Smoke-preserve test). Strengthened the GHA migrations test
   to assert the DBEnv is in the job-level env AND the step carries no
   step-level env block.

3. GAP.md: documented that the GLOBAL cross-phase secret union over-exposes
   secrets — e.g. MULTISITE_DB_URL appears in apply-prereq's env even though
   prereq runs no migrations. Honest known limitation; per-phase secret
   scoping is future work, NOT this PR's scope.

Regenerated multisite evidence with the fixed binary (plan.json byte-identical;
generated-infra.yml drops the 2 step-level env lines). Fresh regen matches the
committed generated-infra.yml byte-for-byte. Live infra.yml NOT modified.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@intel352 intel352 merged commit e76d0ed into main May 30, 2026
22 checks passed
@intel352 intel352 deleted the feat/wfctl-ci-wizard branch May 30, 2026 22:12
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.

1 participant