Every shared command now has ONE implementation in commands/,
parameterized by ProductProfile (the single source of per-product
config: endpoint, container, image, env prefix, control prefix,
display name). The gcp/az/oci command classes become ~8-line shims
(GcpStartCommand extends StartCommand { super(ProductProfile.GCP); })
that carry only their per-product help description; the three
near-identical *GlobalOptions clones are deleted. Each product tree
drops from ~1,360 to ~530 lines and copy-drift becomes impossible.
Mechanics: per-product option defaults are constructor-set field
values rendered in help via ${DEFAULT-VALUE} (annotation defaults are
compile-time constants); commands pre-initialize their GlobalOptions
mixin with the profile (picocli uses a non-null mixin field instance
as-is). Verified against a captured baseline of 480 CLI outputs
(every --help x 5 trees, env/status/doctor JSON, exit codes, routing)
plus new pinning tests: ProductProfileTest, ProductTreesParsingTest,
DoctorCheckListTest, GlobalOptionsTest.
Behavior changes, all deliberate:
- snapshot commands in gcp/az/oci trees now perform the real
/snapshots API calls with graceful degradation and exit 1 while the
server lacks the endpoints (previously: note + exit 0)
- product logs/services gained --service/--mode, and services now
resolves the endpoint from the container port mapping in all trees
- the AWS tree brands itself 'Floci AWS' in banners and help,
matching the other products
- snapshot errors link the product issue tracker instead of TODO.md
- completion generates from spec.root() instead of a hardcoded
FlociCli instance (output unchanged)
BREAKING CHANGE: 'floci gcp|az|oci snapshot export/import' (and bare
'floci snapshot ...' with a non-AWS default product) now exit 1
instead of 0 while server-side snapshot support is pending; CI
scripts relying on the silent success of stubbed snapshot commands
will fail.
Summary
Collapses the four near-identical product command trees into ONE implementation per shared command, parameterized by
ProductProfile— the single source of per-product config (endpoint, container, image, env prefix, control prefix, display name). Thegcp/az/ociclasses become ~8-line shims carrying only their per-product help description; the three*GlobalOptionsclones are deleted. Each product tree drops from ~1,360 to ~530 lines, the "apply every change to all four trees" rule is retired from AGENTS.md/CONTRIBUTING.md, and copy-drift (the source of several past bugs) becomes structurally impossible.Verified with a captured baseline of 480 CLI outputs (every
--help× 5 trees, env/status/doctor JSON, exit codes, default-product routing) diffed against main after every phase, plus native-image smoke tests across all trees.Deliberate behavior changes (all in CHANGELOG):
/snapshotsAPI calls with graceful degradation and exit 1 while server support is pending (previously note + exit 0) — see BREAKING CHANGE footer in the commitlogs/servicesgained--service/--mode(drift fix);servicesresolves the endpoint from the container port mapping in all trees (extends feat(oci): add floci oci command group for the Floci OCI emulator #15's OCI fix tree-wide)Type of change
fix:)feat:)feat!:orfix!:) — snapshot exit codes on stubbed treesProduct trees affected
commands/gcp/)commands/az/)Also
commands/oci/; the template predates the fourth tree.Checklist
mvn testpasses locally (66 tests)ProductProfileTest,ProductTreesParsingTest,DoctorCheckListTest,GlobalOptionsTest— first-ever coverage of the gcp/az/oci trees)CHANGELOG.mdentry added under[Unreleased]README.mdupdated (snapshot exit-code note)mvn package -Pnative) — per-tree smoke at the pilot phase and at the end