Honest headline: building all four pillars (shared services + git/aliases + secrets + networking) as a polished, cross-platform open-source product is a ~54 person-week (~1.2 person-year) program, not a "v1." At solo full-time (~40h/week) with a realistic 0.6–0.75 throughput factor on integration-heavy cross-platform work, that's a ~13–15 month calendar (range: 12 best-case → 18 if WSL2 trust/networking and the shared-data lifecycle prove as fiddly as the research warns).
You asked for all four pillars in v1. The internals sequence so that M0→M3 delivers the irreducible differentiator and a demoable tool, and secrets/networking/onboarding layer on without rework because each sits behind an interface. So:
1.0= M0–M3 (≈ 28 person-weeks ≈ 8–9 months solo): shared services + workspaces + templating + multi-repo git + aliases + HTTP-on-localhost. This is a tool people can adopt.1.1= M4 secrets ·1.2= M5 local HTTPS + proxy + tunnel ·1.3= M6 orchestrated onboarding/doctor/health/hooks.1.0GA polish = M7.
This is a sequencing recommendation, not a scope cut — every pillar still ships. If you truly want all four before any release, the calendar is the full ~13–15 months.
Effort is person-weeks at production OSS quality (tests + docs + cross-platform). Build cross-cutting foundations (locking, state, preflight) first — they are the spine, and retrofitting them is far costlier.
- Repo layout (
/cmd,/internal,/pkg,/templatesviago:embed), Go 1.25 floor, goreleaser + GitHub Actions skeleton withgovulncheckand a JSON-Schema↔struct drift check. - cobra+fang root,
argv[0]alias dispatch +--as, alias registry + symlink installer/uninstaller. - XDG paths + WSL2 detection +
/mntrefusal; SQLite state store (WAL/busy_timeout, versioned migrations + backup), keyed by Docker context. gofrs/flockglobal lock helper wrapping all mutations — the concurrency spine.internal/dockerpreflight (daemon, context, compose≥2.20, git≥2.30) + a mockablemoby/moby/clientinterface.- Decide & document: CLI-only (no daemon) model, the v1 cut-line, unknown-key/forward-compat policy, unified error/
--debug/--jsoncontract.
- Two-file schema (
workspace.yaml+devstack.yaml) withapiVersionheader; goccy parse w/ positions; jsonschema + validator/v10 + custom resolver (cross-refs, cycles). - Template engine with custom delimiters + ported filters;
renderText/renderYAML;extends-chain render-then-merge; layered merge with explicit list strategy. - Compose model +
compose-govalidate/normalize;${ref}resolution against the workspace graph;writeIfChanged+ atomic write; SHA-256 rebuild-hash ledger. - Golden-file conformance suite; deterministic-output CI check; (optional)
devstack importfrom devdockproject.yaml(spec 14internal/migrate— pure YAML→YAML, no lock, ships early).
- Tool-owned external network (pinned name, idempotent ensure/teardown); shared stack + per-project stacks with
shared-*aliases; collision lint. - Ref-counting in SQLite (inside the lock) + self-healing reconcile from live Compose labels (
All=true, exclude one-off); per-(engine,major-version)shared instances. - Provision-on-demand per-project Postgres role/db (pgx, idempotent, PG18 volume path), redis index/prefix, minio bucket+key; ownership ledger + orphan gc.
- Port allocation inside the lock (host bind-test unioned with SDK port bindings);
shared status/doctor/gc; never-recreate-stateful-shared guard. - The
up/bootstrap saga (spec 09) begins landing here — its network/shared/provision/compose-up phases sit on this milestone's workspace+provision substrate; the health/hooks/profiles phases complete in M6.
gitxsystem-git wrapper (hardened env,porcelain=v2status,GIT_ASKPASStoken shim, shorthand expansion, submodule/shallow opt-in).- errgroup bounded-parallel clone/sync/status with per-repo context; bubbletea TUI + plain non-TTY/
--jsonfallback. ws clone/sync/status(the headline status table) integrated with workspace + secrets token injection.
★
1.0core ships here (≈28w).
- Provider interface + Registry + Factory;
secret://URI parser; batched post-render resolution coupled to generation. - Two providers (confirm which — see OPEN-QUESTIONS): SOPS+age offline default + AWS (Secrets Manager + SSM via
aws-sdk-go-v2), or Infisical + AWS; keygen/login. - OS-keyring optional with in-memory fallback (WSL2 degrade); integration test asserting no secret value lands in any generated artifact.
- Caddy shared container via
caddy-docker-proxy, label-driven routing;<service>.<project>.localhostdefault. - Host CA trust via
mkcert+ WSL2certutil.exeinterop; trust status/install/uninstall; idempotent/etc/hostsedits for OS-resolver clients; local HTTPS opt-in. - cloudflared optional managed tunnel (default DOWN, loud confirm, manual wildcard CNAME doc, secret-bearing-service refusal).
Specs: 09 (saga) · 10 (health) · 11 (hooks) · 12 (profiles) · 13 (doctor/teardown) · 14 (self-update/migration).
- Multi-phase resumable
up/bootstrap saga with durable phase-state + compensating rollback; bubbletea checklist + plain fallback (spec 09). - Health/readiness gating (typed healthchecks,
dependsOn: healthy, spec 10); lifecycle hooks (preUp/postUp/preDown/firstRun/postPull) with idempotency ledger (solves theinitdb.dgap, spec 11); profiles/selective-up (spec 12). doctorcapability-probe matrix with remediations and--fix;doctor --rebuild-state(spec 13); self-update with install-method detection + alias relink + state migration (spec 14).workspace destroy/uninstallreversing all artifacts (network, volumes w/ confirm, CA from all stores, symlinks, keyring, cloudflared creds, cache) (spec 13).
- Integration tests via
testcontainers-go/dind lane (network/ref-count/provision/health) behind build tags; concurrency-race tests; documented manual macOS+WSL2 checklist. - macOS arm64 CI runner for trust/resolver/Desktop-VM behavior; cache GC; document Docker Desktop licensing + Podman/rootless out-of-scope.
- Quickstart + migration guide, secrets threat model, troubleshooting; goreleaser tap +
.deb/.rpm; tag 1.0.
Core M0–M7 has shipped (see PROGRESS). This lane is strictly additive over the existing substrate and stays on the 0.x beta line — it does NOT cut v1.0. The "tag 1.0" in M7 above is superseded by the beta decision: the project ships in beta (next release v0.2.0); 1.0 is a deliberate, later owner call, never reached by automation. "M8" is a sequencing label, not a version commitment. Specs: 25 (release automation) · 22 (init wizard) · 23 (template authoring) · 24 (.env ingestion). All TUIs are Bubble Tea v2 + Charm (
bubbles/lipgloss/v2/huh/v2), CGO-free, behind one sharedinternal/prompttheme with a non-TTY/--jsonfallback.
M8.0 — Release automation + 0.x versioning (the v0.2.0 gate) · 0.75w thin (+0.75w wizard). (spec 25)
.svu.yaml(v0: true) + a single rewrittenrelease.yml: push-to-main→svu next --v0→ tag + goreleaser in one job using the built-inGITHUB_TOKEN(no PAT), gated on theRELEASE_ENABLEDrepo variable; the same workflow also releases a human-cutv*tag.- Fix the ldflags v-prefix bug (un-mutes the shipped spec-14 self-update/notifier); add a grouped goreleaser changelog (
use: github+groups/filters); PR-title conventional-commit lint; CIv0.*guard. - Optional: the
devstack releasemaintainer wizard + an additiveupdate.channel(stable|prerelease) knob (extends spec 14, does not redefine it). - Sequence first — every later item ships through it; the thin slice (~0.75w) is all that is needed to cut v0.2.0.
M8.1 — internal/prompt + interactive init · 2w. (spec 22)
- Introduce the Bubble Tea v2 + Charm stack behind
internal/prompt(shared theme + non-TTY/--json/--no-inputfallback so the headline-output contract holds and CI never drives Bubble Tea). devstack initauthors a structurally-validworkspace.yamlvia a sharedscaffold.EmitWorkspaceYAMLordered emitter; refactorinternal/migrateonto the same emitter (re-baseline its golden output intentionally). No flock, no Docker.
M8.2 — template new authoring TUI · 2.5w. (spec 23)
- One
scaffold.Build(Spec)pure builder fed by both the wizard and the flag/--from/--jsonpath; livetemplate.Resolve→generate.LintResolvedpreview; app-vs-engine branch;writeIfChangedbyte-stability. - Implement the delimiter-collision / param-type / meta-templating lints once in shared lint code consumed by both
template newpreview andtemplate lint. Reconcile spec-19's overstatedtemplate initdescription.
M8.3 — .env ingestion + secrets Pusher · 2.5w. (spec 24)
secrets ingestover the shipped SOPS+age/AWS/Infisical providers; net-new Pusher write capability (aws-sm/ssm/infisical) reusing existing auth plumbing;compose-go/v2/dotenvparse; decrypt-and-compare idempotency; default-sops-provider scaffold intoworkspace.yaml. No flock.- Add a
doctorprobe for thesopsbinary min-version (stdin /--input-typesupport).
Sequencing within M8: M8.0 → M8.1 (lands internal/prompt + the shared emitter) → M8.2 (reuses both) → M8.3 (reuses prompt, adds the heaviest net-new backend). After each charm-dep add: re-run make vuln + the CGO_ENABLED=0 static cross-build; no build tags may creep in.
Generalizes provision-on-demand (Postgres-only today) into a full data-plane resource layer and adds cloud-emulation engines, turning the shared-infra tool into a local cloud. Strictly additive; stays 0.x. Specs: 26 (CLI/README reconcile) · 27 (resource model + Provisioner family) · 28 (cloud engines) · 29 (imperative verbs). Every mutation goes through
internal/lock; engine tools (mc/aws/nats/rpk) shell out behindinternal/interfaces (CGO-free rule); only generated artifacts are determinism-gated, ledger/runtime ops are not.
M9.0 — CLI completeness & README reconciliation (the credibility gate) · 2w. (spec 26)
- Reconcile README Commands/Status to the shipped surface (up/down/secrets/trust/dns/tunnel are shipped; mark
logshonestly v2/spec 16) — a truth-pass over merged code, lowest risk, ships first (cut v0.3.0). - Real interactive
shell(new docker seam:os.Stdin+ real-itTTY, no stderr capture, verbatim child exit code);up --rebuild/--skip-clone+ exposed--health-timeout;self update --force; standalonetunnel up/down(spec 05 secret-guard); machine-wideworkspaceregistry (thin pointer keyed by Docker context, written onupunder the flock,--prune-only removal) +workspace list; reserved post-1.0 stubs.
M9.1 — Data-plane resource substrate · ~4.5w. (spec 27)
internal/resource: Resource model +Provisionerinterface; refactor Postgres provisioning behind it (behavior-preserving) FIRST. Newcrypto/randkeygen ininternal/secrets; predictable|generated credential policy via the #16 Pusher.- Declarative
resources:block (additive, validated by the cross-ref resolver) + a new up-sagaresourcesphase subsuming the Postgres provision phase (drift reported, never auto-dropped).resource list|show|create|rm|gc; newRemoveProvisioned(project,kind,name)ledger op (free-text kind, no migration);workspace destroy --purge-data(opt-in, confirm-gated).
M9.2 — Cloud-emulation engine templates · 2.5w. (spec 28)
- Net-new localstack/ministack(AWS-emulation,
provides: aws)/nats/kafka(Redpanda default)/rabbitmq engine templates ondevstack_shared;template new --kind enginescaffold;shared status/gccoverage; info-level doctorbin.*probes. Confirm ministack.org image/port/SERVICES/health before authoring. - Resolve the secondary-port export-attr→port map (or drop monitor/admin attrs). Native NATS/Redpanda default; LocalStack opt-in.
M9.3 — Imperative resource verbs · ~5w (db+s3 ~2w, messaging ~3w gated on M9.2). (spec 29)
db+s3on the PG/MinIO substrate — ship in v0.x now (ownFreeHostPortpurpose/base per engine; avoid the 45432 pg-provision base). Thinaws --shim.queue/topic/stream(nats/redpanda native default, sqs/sns via LocalStack opt-in) — gated on M9.2 engines. Cross-kinddb gcwaits on spec 13's reaper.
Sequencing within M9: M9.0 (now) → M9.1 (the substrate everything needs) → M9.2 (engines) ‖ M9.3-db/s3 (parallel, no new engine) → M9.3-messaging (after engines). Re-run make vuln + the CGO=0 cross-build after each engine-tool/dep add.
| Phase group | Person-weeks | Solo calendar (≈) |
|---|---|---|
| Core 1.0 (M0–M3) | 28 | ~8–9 months |
| Secrets (M4) | 5 | +~1.5 months |
| Networking (M5) | 7 | +~2 months |
| Onboarding/glue (M6) | 8 | +~2.5 months |
| Hardening/GA (M7) | 6 | +~2 months |
| Full v1 (all pillars) | 54 | ~13–15 months |
| Beta DX lane (M8, 0.x — post-GA) | ~8 | +~2.5 months |
| Local-cloud platform lane (M9, 0.x) | ~14 | +~4 months |
| Interactive-DX lane (M10, 0.x) | ~14 | +~4 months |
M10 — Interactive-DX lane. ✅ SHIPPED. An active-context model + shell integration (
use/context/shell-initeval hook, completions, prompt segment), project + env authoring commands (comment-preserving), a console context header, ASCII-logo branding, top-levelexpose/ports, a JS/TS + monorepo template library with hot reload, and a devstack-native task-graph runner (devstack run). Specs: 30 (interactive DX & shell) · 31 (JS/monorepo templates +run). ADRs: D18 (active context & shell) · D19 (task graph). Strictly additive; stays 0.x; no change to the deterministicgeneratepipeline or lock-first concurrency.
Calendar applies a 0.6–0.75 throughput factor (context-switching, Docker/WSL2/macOS debugging, dependency churn, docs, CI). Treat as planning ranges, not commitments.
- Cross-platform is most of the cost. macOS resolver/trust quirks, the WSL2 dual trust store, and Desktop-VM networking each need their own testing; hosted Linux CI can't cover them.
- The shared-data lifecycle (provision and reclaim, version conflicts, partial-failure rollback) is genuinely novel work, not glue.
- Dependency treadmill on pre-1.0/risky deps (see DECISIONS risk register).
Build M0's locking/state/preflight before anything that mutates shared state. Everything that touches the ledger or the shared stack goes through the lock from the first commit — retrofitting concurrency safety is the most expensive mistake available here.