Repository navigation
Migrate sync-versions.sh → wfctl registry sync subcommand (consolidates Layer 3b + deferred I3 capability gate) #762
Description
Context
workflow-registry/scripts/sync-versions.sh is bash + jq + gh CLI. workflow#758 added a strict-semver tag gate to it (PR #110, 940ecc405c) — but that regex is now duplicated with wfctl plugin validate-contract --for-publish (Layer 1). Two implementations of the same rule = drift risk.
Cycle-4 plan adversarial review flagged this as "tooling decision creep" (I1 in workflow-registry context); it was accepted pragmatically at the time to keep Layer 2 scoped down. Coming back to address it now.
Problems with the current bash sync
- Regex duplication between
sync-versions.shandwfctl plugin validate-contract --for-publish. Both define^v\d+\.\d+\.\d+$. Future changes (e.g. allowing-rc.NonceParseSemversupports it) require touching two places. - No test harness in workflow-registry repo. Layer 2 PR shipped without an automated test for the new gate — only an inline regex verification at PR time.
- Can't reach the next gate. The deferred binary-vs-file capability freshness gate (workflow#758 cycle 4-A1 I3) requires spawning the just-released plugin binary and calling its
GetContractRegistryRPC, then diffing against the committedplugin.json.capabilities. Bash + jq cannot do that;wfctlalready has plugin-spawn infrastructure (plugin/external/manager.go). - Two source-of-truth problem.
wfctlis the plugin-contract authority (it ownsPluginManifest.Validate,ParseSemver, the gRPC client). Registry sync logic that knows about plugin manifests, version semantics, and capability shapes belongs in the same domain. - Long-tail of bespoke shell logic —
fetch_plugin_jsonshellsgh api,downloads_match_versionis a custom jq filter,release_downloadsparses JSON via bash. Each has been a small regression hazard.
Proposed direction
New wfctl registry sync subcommand. Walks plugins/<name>/manifest.json in a checked-out workflow-registry repo, performs the same tag-fetch / version-compare / capability-fetch / manifest-rewrite logic as sync-versions.sh today, plus:
- Strict-semver tag gate (single regex; same source as
wfctl plugin validate-contract --for-publish). - (Future, deferred I3)
--verify-capabilitiesflag: pull the just-released plugin tarball, exec the binary, callGetContractRegistry, diff against committedplugin.json.capabilities. Reject if stale. - (Future)
--applywrites back; absent it's dry-run.
workflow-registry's GitHub Action becomes a one-line wfctl registry sync --apply (or whatever flag set).
Bundles with
This issue also bundles the related deferred work that all benefits from a Go-side migration:
Deferred from workflow#758
- Layer 3b: apply plugin-version discipline to remaining 56 plugin repos (workflow#760). Mechanical fan-out; the canonical pattern shipped 2026-05-23. Audit list enumerated in Layer 3b: apply plugin-version discipline to remaining 56 plugin repos (workflow#758 follow-up) #760.
- Binary-vs-file capability freshness gate at contract-check time (cycle 4-A1 I3). Natural fit for
wfctl registry sync --verify-capabilitiesANDwfctl plugin validate-contract --for-publish --verify-binary(operator-side). - Full SemVer 2.0.0 prerelease support: requires concerted
ParseSemver+sync-versions+wfctl installupdate. Naturally part of this scope if registry sync moves to Go. - Gap-repos: ~8 plugin repos lack release pipelines (agent, cms, compute, cloud-ui, data-protection, edge-compute, sandbox, waf). Separate from this migration but should be audited alongside.
Audit needed
Before brainstorming the design, an audit pass to inventory:
- Every shell-script in
workflow-registry/scripts/(not just sync-versions.sh) — what else lives there, what calls it? - Existing wfctl
pluginsubcommand surface — what's the precedent forwfctl registry <verb>vswfctl plugin registry-<verb>? - workflow-registry's CI invocations of these scripts — what's the actual contract Github Actions consume?
- Any in-tree consumers besides CI (cron, manual runs by operators, downstream tooling)?
- The 56 Layer 3b repos: per-repo variance preview so the fan-out doesn't hit surprises mid-sweep (DO/AWS/GCP/Azure/github pilot already revealed: Version var name varies, main.go path varies, IaC vs non-IaC split, capabilities-shape variance).
Acceptance criteria
-
wfctl registry syncsubcommand lands with table-driven tests -
workflow-registry/scripts/sync-versions.shdeleted (or reduced to a single-line wfctl invocation) - Same strict-semver tag gate sourced from one regex constant in Go
-
--verify-capabilities(or equivalent) closes cycle 4-A1 I3 - Layer 3b sweep (56 repos) completes
- Gap-repos audited; per-repo path forward documented
- Full SemVer 2.0.0 evaluated: ship the parser update OR explicitly defer with rationale
References
- workflow#758 (parent)
- workflow#760 (Layer 3b)
- workflow-registry PR fix(server): harden multi-workflow mode wiring based on review feedback #110 (the bash regex this would replace)
- workflow PR feat(sdk+wfctl): ResolveBuildVersion + WithBuildVersion + plugin validate-contract (#758 Layer 1) #759 (wfctl plugin validate-contract precedent)
- workflow
docs/retros/2026-05-23-workflow-758-plugin-version-discipline.md
Activity
feat(wfctl): plugin registry-sync subcommand + shared release-grade s…
docs(plan): wfctl plugin verify-capabilities design (workflow#765)
feat(wfctl): plugin verify-capabilities subcommand (workflow#765) (#766)
intel352 commentedon Jun 1, 2026
Audit result: still relevant, partially shipped.
Verified against latest
origin/main: PR #763 shippedwfctl plugin registry-sync, the shared publish-grade semver regex, and docs. Laterwfctl plugin verify-capabilitieswork also exists. Remaining scope is still real:registry-sync --verify-capabilitiesstill prints not implemented,registry-sync core/readmenative ports are still pending, and the Layer 3b/c sweep remains tracked by #760.intel352 commentedon Jun 2, 2026
Updated issue #762 cascade status after the registry-sync follow-up.
Completed/verified:
fix: keep registry sync from mutating builtins) at7a9dc544f980c821dc3af65b4adf30c05fbb0e45.wfctl plugin registry-syncnow skipsbuiltin/coremanifests.wfctl plugin registry-sync corenow treats straydownloadson core manifests as drift and removes them with--fix.v0.69.7; release workflow26794682772completed successfully and assets were verified.origin/main, fixed Copilot checksum feedback, all checks green, merged atd2e266701bc2d015ac2b7af2055b6ba0f2fd253d.Current open workflow PR state:
Go Mod Tidycheck. I did not merge them.Remaining #762 work to continue next:
intel352 commentedon Jun 2, 2026
Dependency PR cleanup from the previous status note is now complete.
Merged after fixing module tidy drift and verifying CI/review state:
golang.org/x/crypto0.52.0go.opentelemetry.io/otel1.44.0modernc.org/sqlite1.51.0go.opentelemetry.io/otel/sdk1.44.0Verification notes:
examplemodule tidy drift.cmd/wfctl/testdata/verify_capabilities/*fixture module tidy drift exposed by readonly fixture builds.copilot-pull-request-revieweris not a collaborator on this repository.Leaving #762 open because the broader registry-sync/fanout/gap-repo scope remains active.
intel352 commentedon Jun 2, 2026
Closing this as completed after re-audit on 2026-06-02.
Verified current state:
wfctl plugin registry-syncexists on workfloworigin/main(c5d6861) with native default,core, andreadmemodes.--verify-capabilitiesis implemented, not stubbed: it selects the current-platform release asset, downloads viagh release download, extracts tarballs, locates the binary, and reuses thewfctl plugin verify-capabilitiesmanifest check with registry-name alias handling.registry-sync coreremoves straydownloadsfrom builtin/core manifests and has regression coverage.workflow-registryorigin/main(23d3db2) now hasscripts/sync-versions.sh,scripts/sync-core-manifests.sh, andscripts/generate-readme.shreduced to thinwfctl plugin registry-synccompatibility wrappers. CI useswfctl plugin registry-sync,core, andreadmedirectly.workflow-plugin-agent,workflow-plugin-cms,workflow-plugin-compute, andworkflow-plugin-edge-computeall have.github/workflows/release.yml;workflow-plugin-cloud-ui,workflow-plugin-data-protection,workflow-plugin-sandbox, andworkflow-plugin-wafare no longer resolvable as repos.vMAJOR.MINOR.PATCHgate used by both validate-contract and registry-sync.Fresh verification:
intel352 commentedon Jun 2, 2026
Verification addendum for the close note above (the previous comment's test-command line was truncated by shell quoting):
Fresh checks run on workflow
origin/main(c5d6861):GOWORK=off go test ./cmd/wfctl -run 'TestPluginRegistrySync|TestPluginVerifyCapabilities' -count=1->ok github.com/GoCodeAlone/workflow/cmd/wfctl 1.984sGOWORK=off go test ./cmd/wfctl -run 'TestPluginRegistrySync' -count=1->ok github.com/GoCodeAlone/workflow/cmd/wfctl 1.067sAlso verified workflow-registry
origin/main(23d3db2) has no open issues/PRs, and workflow has no open PRs.I also attempted the broader
GOWORK=off go test ./cmd/wfctl -count=1; it produced no output for over two minutes and was stopped rather than left running. I am not claiming a broad package pass from that command. The focused registry-sync / verify-capabilities coverage above is the evidence for closing this issue.