Releases: semsemyonoff/dwe
Release list
v0.5.0
v0.5.0 — Agent ergonomics
This release makes a DWE project legible to an AI coding agent working inside it, and adds the engine features that came out of that work.
Highlights
🤖 Navigation for agents
dwe docs llms-txtis a real briefing — project context, services, commands, builtin and predicate inventories, docs pointers. Project-aware inside a project, generic outside one.dwe docs searchis tokenized and ranked, with snippets and a resolvabletopic#anchoron every hit.dwe docs show --anchors/--toc/--anchoraddress a document's sections directly.dwe test list --output jsongainedcost_profile— host steps, isolation findings, shared volumes — so the cost of running the suite is knowable before running it.
🧩 Pipeline primitives
argv_append_from— build extra argv elements from a host command's output, one per line, no shell re-parse.check: auto— derive a step'scheck:by inverting its shellwhen:instead of writing the condition twice.source_clone— a self-gating clone builtin, with path containment and symlink checks on the destination.
🔤 ${vars.*} inside pipelines
Pipeline cmd:, with:, check:, timeout: and shell when: render at resolve time, so a deploy step can read project vars — and dwe deploy plan shows the command that will actually run. An unrecognized head (${HOME}, a typo) stays literal instead of collapsing to an empty string. Adds dwe deploy plan --output json.
✅ dwe validate
Three new checks — config.template_refs (a ${...} whose path doesn't resolve), config.container_name, config.ports_exports — and less noise: implicit defaults no longer report as findings. The summary and JSON now name the active scope.
🐚 Command surface
${args}pass-through — forwarded as positional parameters, never interpolated into the command text.dwe shell --tty/--no-tty,dwe services list, and a named diagnosis when a container lacks the configured shell.
🏗 Scaffold and tables
dwe init ships service defaults, a pipeline skeleton, an AI pack, and a starter test scenario. Every CLI table now adapts to terminal width — fits, shrinks, then breaks into record blocks; piped output is byte-identical to before.
Upgrade notes
[a-z0-9][a-z0-9_-]* while project.name / project.prefix / docker.yml's project_name are free-form, so cueBreaker now resolves to dwe-cuebreaker — and container names, the volume prefix, and the compose project label follow. If your project name carries uppercase, stop the stack with v0.4.1 before upgrading: the old containers and volumes belong to a different project as far as Compose is concerned, and would be orphaned rather than adopted. Already-lowercase projects are unaffected.
One-time full re-run. vars: is now part of the config hashes — it has to be, since a step's command can depend on it — so the first dwe deploy run after upgrading re-runs every step. Steps are idempotent and gated, so this is safe; it just isn't silent.
Everything else is additive and activates only when used.
Full changelog: v0.4.1...v0.5.0
v0.4.1
Changelog
- c6e1650: ci(docs): deploy the docs site on workflow_dispatch too (@semsemyonoff)
- 60bdf5a: docs(commands): note custom-network + partial-up/run ordering caveat (@semsemyonoff)
- 7c00fd9: docs(skill): address CodeRabbit review on #59 (@semsemyonoff)
- 8a608bd: docs(skill): cover 0.4.0 integration-tests + 0.3.0 TUI in the dwe agent skill (@semsemyonoff)
- 51e51f8: docs(skill): document the test host-port isolation rule (only services..ports) (@semsemyonoff)
- 1be5929: docs(skill): harden integration-tests reference with 5 live-use gotchas (@semsemyonoff)
- 3898b63: fix(test): propagate --verbose/--debug into scenario validate + deploy subprocesses (@semsemyonoff)
- e5e5a8b: fix(test): retry transient containers_running probe and surface compose stderr (@semsemyonoff)
v0.4.0
v0.4.0 — Integration tests (dwe test)
This release adds dwe test, a declarative integration-test runner that exercises your project's real deploy pipeline inside a fresh, fully isolated, disposable copy of the project — plus the engine features it's built on.
Highlights
🧪 dwe test — isolated, disposable integration tests
Run your actual deploy pipeline — and any assertions or project commands you declare — against a throwaway copy of the project, without touching the environment you work in.
dwe test run [scenario…]— one YAML file per scenario inworkspace/tests/<name>.yml: service toggles, var overrides, and ordered steps in the same schemadeploy.ymluses. Flags:--keep,--timeout,--skip-isolation-check,--parallel N.dwe test list— list scenarios with their descriptions.dwe test clean— sweep kept or leftover test environments (--dry-run); strictly manifest-driven, never guesses at compose-project names.- Full isolation — git-aware tree copy, per-run compose project name, automatic host-port remapping, its own
.dwe/state, and manifest-driven teardown (never-v). - Failure reports — on a failing run, the pipeline log,
compose ps, and container logs are captured automatically before teardown. --parallel N— run scenarios concurrently behind a compact aggregated live view.- CI-friendly: exit codes (
0pass /1fail /2couldn't prepare) and--output json.
🔌 New builtin: http_check
A predicate builtin that asserts an HTTP endpoint returns an expected status (and optional body substring), with retries — usable in deploy.yml, validate.yml, and test scenarios.
✅ Predicate builtins as step-body assertions
Any predicate builtin (file_exists, tcp_reachable, http_check, containers_running, env_keys_present, config_keys_present, executable_in_path, shell) can now be used directly as a step body, where it behaves as an assertion: a false result fails the step. Works in every pipeline; existing configs are unaffected.
⏱ Per-step timeout:
An opt-in wall-clock budget on a single step body, honored across deploy.yml, reset.yml, lifecycle.yml, and test scenarios.
🩺 dwe validate tests + compose isolation scanner
Statically check every scenario (schema, references, whole-phase step resolution) without touching Docker — and surface raw-compose constructs (container_name:, hardcoded host ports, external:/named volumes & networks) that would bypass test isolation.
🐳 docker build.prepull_bases
Optional (default: false) workaround for buildkit fetchers that can't reach LAN/private registries: pre-pulls the external FROM base images a build needs, via a plain daemon-side docker pull. Covers both dwe docker build and dwe docker up; advisory, never a hard failure.
Other changes
- Dependency maintenance:
golang.org/x/sync,x/term,x/sysbumped; the docs-site (web/) npm deps scoped asdevDependencies. - Documentation and Russian translations for all of the above.
Upgrade notes
No breaking changes — everything here is additive and opt-in. Existing projects work unchanged; dwe test activates only once you add a workspace/tests/ directory.
Full changelog: v0.3.0...v0.4.0
v0.3.0
This release lands the unified TUI framework & redesign — dwe's three full-screen interfaces (command browser, docs browser, status dashboard) are rebuilt on a single framework with mouse support, a redesigned frame, ?-invoked modal help, and in-TUI form overlays.
✨ Features
Unified TUI framework & redesign (#45)
The command browser, docs browser, and status dashboard now share one framework (internal/core/ui/tui) that owns layout, project-styled panel borders, focus, action-based keymaps, overlays, and mouse. The frame is redesigned: the brand/title moved to a bottom status line, help is promoted to a ?-invoked modal (no more permanent footer), and borders stay project-styled. Delivered across Stages 0–7 (#24, #33–#38, #42).
First-class mouse support
Wheel scroll and click work across all three TUIs — implemented once in the framework (hit-zone pointer routing, click-outside-to-close, and a wheel-coalescing input filter that kills the macOS momentum-scroll backlog).
In-TUI form overlays
Interactive forms now run inside the TUI instead of dropping to the terminal — the dwe commands parameter prompt and the dwe vars editor both open as in-frame overlays.
Under the hood
- Generic tree engine shared by the command and docs browsers (the two duplicated tree widgets are gone).
- Forms unification — the last three raw
huh.NewFormsites (deploy menu, setup port-overrides, setup service-toggles) collapse back into the sharedaskwrapper via declarative keymap overrides. - Charm stack standardised on v2 —
statustuimigrated off lipgloss v1.
🔒 Security & dependencies
golang.org/x/net→ 0.55.0, fixing a medium-severity HTML-parser DoS advisory (GHSA-5cv4-jp36-h3mw).- Charm stack patch bumps:
bubbletea2.0.8,lipgloss2.0.5,bubbles2.1.1 (emoji/grapheme rendering + textarea fixes) (#41).
Full changelog: v0.2.4...v0.3.0
v0.2.4
v0.2.4
This release is all about documentation. The dwe binary's behavior is unchanged — upgrading is safe and needs no changes to your project.
📖 New documentation site
The full reference and guides are now published as a searchable website:
https://semsemyonoff.github.io/dwe/ (Russian mirror at /ru/).
The same content stays available offline via dwe docs.
Documentation
- Refreshed the reference, guides, and both READMEs to match current behavior.
Minor fixes
validate: corrected the per-service deploy file path shown in diagnostics (workspace/services/<name>/deploy.yml).initscaffold: the generated.dwe/configheader now correctly describes the file as gitignored.
v0.2.3
Changelog
- 6dccd1a: docs(config): clarify non-Docker host process is also waited on (@semsemyonoff)
- a79bb80: feat(lifecycle): wait for host ports to release after stop (@semsemyonoff)
- 78cb4aa: feat(validate): warn on unknown nested keys under formal config blocks (@semsemyonoff)
v0.2.2
Changelog
- 5b8891b: fix(validate): absorb Docker Desktop host-port release lag in ports_free (@semsemyonoff)
v0.2.1
This patch release fixes container targeting for dwe logs/stop/restart/reset --service (now resolved by compose labels instead of guessed names), adds whole-stack dwe logs, corrects the files dwe init scaffolds, and expands the bundled dwe agent skill into a setup-and-authoring assistant.
🐛 Fixes
Label-based container resolution (#16)
Commands targeting a specific container (dwe logs, dwe stop <name>, dwe restart <name>, dwe reset run --service <name>) previously guessed the container name as <project>-<container>, which broke under compose's default <project>-<service>-<index> naming and failed with "No such container". They now resolve the real container via the com.docker.compose.project + com.docker.compose.service labels — like dwe status/dwe shell already did — so targeting works regardless of any container_name override or -N suffix. Also fixes a latent bug where reset --service silently left an un-pinned container behind.
dwe init scaffold fixes (#17)
/.envis now gitignored — the generated root env file (dwe render env --out .env) was previously committable, secrets included.- Init templates pointed at
dwe docs config <area>, which isn't a real command (rc=1); replaced everywhere with the workingdwe docs show config/<area>. .gitignoregained the render-pack override pattern (workspace/templates/*/*.local/), root-anchored/.dwe/, and a minimal editor/OS set (.DS_Store,/.idea/,/.vscode/,/.zed/, …) anchored so it never shadows tracked ide-pack files.
✨ Features
Whole-stack dwe logs (#16)
dwe logs with no argument now tails the whole stack instead of erroring: text via docker compose logs (native prefixes), JSON via a per-service multiplex with a service field on each NDJSON record. Whole-stack lookups run concurrently and always reap their subprocesses.
dwe shell cwd detection (#16)
Standing in a service's source directory now auto-selects that service; an explicit argument still wins, then single-enabled / interactive selection.
📚 Docs
- The bundled
dweagent skill (skills/dwe/) grew from a thin navigator into a navigator + authoring assistant, with six new on-demand reference guides (populate-init-repo, add-service-and-tools, authoring-commands, render-and-vars, pipelines-and-orchestration, snapshots-reset-troubleshoot). (#18) - The generated
AGENTS.mdnow documents--lang enand--output jsonconventions;containerfield reference anddwe logsusage updated (EN + RU). (#16, #17)
Full changelog: v0.2.0...v0.2.1
v0.2.0
This release lands the host bridge (run host dwe/docker/git from inside your containers), the new dwe vars command, a formalized and strictly-validated project config root, and a service config-rendering + generated-secrets subsystem — plus verbose/debug diagnostics and a reworked validation surface.
⚠️ Breaking changes
lifecycle.yml→ top-levelupdate:block. The self-update policy moved out oflifecycle.run.updateinto a formalized top-levelupdate: { mode: on|off }block. Enabling update no longer blanks yourrunphases. (#10)- Strict project root. The merged
workspace.yml→defaults.yml→local.ymlroot now rejects any unknown top-level key with a hard error. Free-form values belong in the newvars:sandbox. (#10) - Host bridge is opt-in.
bridge.enableddefaults to off for every service, and user commands are container-reachable only via an explicitbridge:block. (#9)
✨ Features
Host bridge (#9)
Run host-side dwe commands from inside a container through a host daemon + injected shim. Default-deny command allowlist, per-service opt-in (bridge.enabled, bridge.services), hardened env (strips LD_*/DYLD_*/PATH hijacking across the trust boundary), and a dwe bridge subtree (start/stop/status/logs). Container writes to vars: are gated by a deny-by-default bridge.vars_writable allowlist.
dwe vars (#14)
Inspect, edit, and trace the vars: sandbox: dwe vars (list), vars get, vars set (comment-preserving local.yml writer), and vars inspect with a field-aware usage scanner that shows exactly which config fields reference each variable. Includes a TUI vars browser.
Project config formalization (#10)
A strict, allowlisted top-level root; the vars: sandbox for arbitrary nestable values (${vars.db.host}, from: vars.db.x); and the formalized update: { mode } block, all 3-layer merged.
Service config rendering + generated-once values (#6)
Render per-service config files through the ${...} template substrate (render.config), and harvest service-generated secrets (e.g. php artisan key:generate) back into a write-once store via pattern. New dwe render config --harvest and reset --clear-generated. Replaces the legacy copy mechanism (now deprecation-warned).
Verbose / debug diagnostics (#8)
-v/--verbose echoes command actions and pipeline decisions; --debug (or DWE_DEBUG) adds docker probes, timings, exit codes, and compose env. All diagnostics go to stderr only — stdout (incl. --output json) stays clean.
Validation (#7, #13)
New post-setup check stage with a config_keys_present builtin, plus per-domain result tables, a severity filter, and cleaner linter output in dwe validate.
🐛 Fixes
- Skip
extends-alias children during whole-project config render to avoid false missing-key warnings. (#12) - Bound the prompt's stale-running trust cap and probe the configured daemon.
- Fall back to the project root for an untranslatable cwd across the bridge.
📚 Docs
- Host bridge concepts + reference, config render pack,
bridge.vars_writable, verbose/debug mode, and re-synced RU translations.
Full changelog: v0.1.3...v0.2.0
v0.1.3
Changelog
- 2dac1d1: docs(concepts): rework project-layout & gitignore conventions (@semsemyonoff)
- 16323da: fix(scaffold): ignore whole .dwe/, add /services/ and backups/, drop volumes/ (@semsemyonoff)
- 020415b: test(mermaid): deterministic singleflight dedup test (@semsemyonoff)