feat(ide): generate devcontainer + workspace + launch configs (spec 17) - #98
Merged
Conversation
Add `devstack ide`, the spec-17 editor/IDE generation sink. It rides the existing deterministic pipeline (typed struct -> stable encoding/json -> atomic writeIfChanged) and the two-file config + name index to author, byte-deterministically, the artifacts that point editors at devstack's already-generated compose stacks: - <repo>/.devcontainer/devcontainer.json in the dockerComposeFile+service+ workspaceFolder ATTACH form, referencing the generated project compose (../.devstack/docker-compose.yaml), forwardPorts from declared host ports, runServices scoped to the repo, overrideCommand:false + shutdownAction:none so the IDE never hijacks the entrypoint or tears down the shared stack, and an opt-in postCreateCommand reconcile. The referenced compose carries `name: devstack-<name>` + the external devstack_shared network, so the IDE lands in the SAME tool-owned project (no forked network/containers). - <workspace-root>/<name>.code-workspace multi-root file listing each repo in declared order + the generated .devstack/ tree, with yaml.schemas mappings and the Dev Containers extension recommendation. - <repo>/.vscode/launch.json + settings.json stubs (schema-map authoring aid; debug-attach configs are a follow-up gated on flock port allocation). Selection via --devcontainer / --vscode / --all (default all); --check reports drift without writing; --json emits a written-paths manifest. Pure file authorship: no Docker, no ledger, no flock. Exports generate.ProjectStackName so the name index is the single source of truth for the compose project name. Removes the ide stub from stubs.go. Tests: golden devcontainer.json + .code-workspace + launch/settings, byte-determinism across builds, idempotent re-write (nothing changes second run), target-flag paths, devcontainer wiring, service-rename reflow, and a no-secret-leak assertion. `make determinism` stays green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
gustavobertoi
force-pushed
the
feat/ide-integration
branch
from
July 1, 2026 12:47
447ba3e to
e16b255
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds
devstack ide, the spec-17 editor/IDE generation sink. It rides the existing deterministic pipeline (typed struct → stableencoding/json→ atomicwriteIfChanged) and the two-file config + name index to author, byte-deterministically, the artifacts that point editors at devstack's already-generated compose stacks. New packageinternal/ide; theidestub is removed frominternal/cli/stubs.go.Artifacts emitted
<repo>/.devcontainer/devcontainer.json— thedockerComposeFile+service+workspaceFolderattach form (notimage/build), referencing the generated project compose (../.devstack/docker-compose.yaml),forwardPortsfrom declared host ports,runServicesscoped to the repo,overrideCommand:false+shutdownAction:"none"so the IDE never hijacks the entrypoint or tears down the shared stack, plus an opt-inpostCreateCommandreconcile. Because the referenced compose carriesname: devstack-<name>+ the externaldevstack_sharednetwork, the IDE lands in the same tool-owned project — no forked network/containers.<workspace-root>/<name>.code-workspace— VS Code multi-root file listing each repo in declared order + the generated.devstack/tree, withyaml.schemasmappings and the Dev Containers extension recommendation.<repo>/.vscode/launch.json+settings.json— schema-map + debugger-attach stubs (full per-language attach configs need flock-guarded port allocation, out of this pure-authorship sink's scope).CLI contract
ide [--devcontainer|--vscode|--all](default--all);--checkreports drift without writing (CI);--jsonemits a written-paths manifest. Mirrors thegeneratecommand. Pure file authorship: no Docker, no ledger, no flock.Why
Spec 17 — meet developers in their editor by emitting, from the same resolved config, artifacts that attach to the exact stacks devstack runs. Exports
generate.ProjectStackNameso the name index stays the single source of truth for the compose project name (a rename re-flows into every artifact).How tested
internal/idetable-driven tests: goldendevcontainer.json+.code-workspace+launch/settings.json, byte-determinism across independent builds, idempotent re-write (second run changes nothing), the--devcontainer/--vscode/--alltarget-flag paths, devcontainer wiring (project name/compose/network/forwardPorts), service-rename reflow, and a no-secret-leak assertion (nosecret:///containerEnv/remoteEnvin any artifact). Full gate green:CGO_ENABLED=0 go build ./...,CGO_ENABLED=1 go test ./internal/...,go vet ./...,gofmt -lclean, andmake determinism..gitignoregains a scoped negation so the.vscode/.devcontainergolden fixtures stay tracked.🤖 Generated with Claude Code