@devrouter/cli 0.0.30 → 0.0.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -59,8 +59,8 @@ apps:
59
59
 
60
60
  ```bash
61
61
  devrouter setup --yes
62
- devpod up .
63
- devrouter repo devcontainer verify --live --yes --json
62
+ devrouter ensure .
63
+ devrouter exec . -- pnpm seed
64
64
  ```
65
65
 
66
66
  Why prefer it: the environment is reproducible and runs anywhere the devcontainer
@@ -87,6 +87,9 @@ vars. Use it when you are not (yet) on a devcontainer. Fully supported.
87
87
  - `devrouter -V [--repo <path>]` (installed CLI version, local repo version, next upgrade target)
88
88
  - `devrouter upgrade [version] [--repo <path>]`
89
89
  - `devrouter setup --yes [--repo <path>] [--json]`
90
+ - `devrouter ensure [path] [--open] [--json]`
91
+ - `devrouter stop [path] [--json]`
92
+ - `devrouter exec [path] -- <command...>`
90
93
  - `devrouter up`
91
94
  - `devrouter down`
92
95
  - `devrouter status [--repo <path>] [--json]`
@@ -106,9 +109,11 @@ vars. Use it when you are not (yet) on a devcontainer. Fully supported.
106
109
  - `devrouter app rm <name> [--repo <path>]`
107
110
  - `devrouter logs [-f]`
108
111
  - `devrouter workspace up <branch> [--path <dir>] [--no-devpod] [--open] [--repo <path>]`
109
- - `devrouter workspace ensure [path] [--open]`
112
+ - `devrouter workspace ensure [path] [--open] [--json]` (compatible alias of `ensure`)
110
113
  - `devrouter workspace ls [--repo <path>] [--json]`
111
- - `devrouter workspace down <workspace|branch> [--keep-worktree] [--keep-devpod] [--repo <path>]`
114
+ - `devrouter workspace stop <workspace|branch> [--repo <path>]`
115
+ - `devrouter workspace down <workspace|branch> [--keep-worktree] [--repo <path>]`
116
+ - `devrouter workspace gc [--repo <path>] [--json] [--yes]`
112
117
 
113
118
  The current `devrouter repo devcontainer write` scaffold is intentionally narrow:
114
119
  Node + pnpm + Postgres. Other package managers stop with a JSON diagnostic
@@ -117,21 +122,21 @@ The generated image extracts `devrouter-process` from the exact Devrouter
117
122
  package tarball without installing the CLI dependency tree. Its `post-start.sh`
118
123
  uses that helper for locked, owned, idempotent background startup. Application
119
124
  commands and environment setup remain repository-owned; route readiness remains
120
- part of `devrouter workspace ensure`.
125
+ part of `devrouter ensure`.
121
126
  Use `devrouter repo devcontainer verify --json` for read-only PR evidence; add
122
- `--live --yes` only after the devcontainer is running and route probes should
123
- mutate local route state.
127
+ `--live --yes` only for compatibility checks. Normal startup uses `ensure`.
124
128
 
125
129
  ## Workspace isolation (parallel worktrees)
126
130
 
127
131
  A **workspace token** lets several git worktrees of the same repo run side-by-side without host or route collisions. The token is a single identity spanning three layers: the devpod workspace id, the routes devrouter registers, and the `${WORKSPACE}` placeholder in `.devrouter.yml` proxy upstreams and devcontainer compose network aliases.
128
132
 
129
- Each linked worktree stores one stable identity in its Git metadata. Once stored,
130
- that value is authoritative: an explicit flag or `DEVROUTER_WORKSPACE` may repeat
131
- it but cannot silently rename the environment. On first use, devrouter reuses the
132
- exact DevPod already bound to the worktree path or derives a sanitized identity
133
- from the linked branch/path. Ambiguous identities and DevPods owned by another
134
- worktree fail closed. The primary checkout keeps its plain, non-namespaced routes.
133
+ Each managed linked worktree keeps its local token in Git metadata and a durable
134
+ owner record under the repository's Git common directory. The record survives
135
+ out-of-band linked-worktree removal and ties the exact worktree path to its DevPod
136
+ ID. On first use, devrouter reuses an exact-path DevPod or derives a sanitized
137
+ identity from the linked branch/path. Ambiguous identities and DevPods owned by
138
+ another worktree fail closed. The primary checkout keeps its plain,
139
+ non-namespaced routes.
135
140
 
136
141
  **When a workspace token is active:**
137
142
 
@@ -148,35 +153,68 @@ worktree fail closed. The primary checkout keeps its plain, non-namespaced route
148
153
  # Bring up a feature branch as an isolated workspace
149
154
  devrouter workspace up feat/my-feature
150
155
 
151
- # Reconcile an existing linked worktree (canonical agent startup command)
152
- devrouter workspace ensure .
156
+ # Reconcile either a primary or linked checkout
157
+ devrouter ensure .
153
158
 
154
- # List git worktrees with workspace tokens and route counts
159
+ # List ownership, Git, DevPod, and route state
155
160
  devrouter workspace ls
156
161
 
157
- # Tear down a workspace (stop devpod, remove worktree, free routes)
162
+ # Pause runtime while preserving the checkout, owner record, and data
163
+ devrouter workspace stop feat/my-feature
164
+
165
+ # Delete runtime and routes, then remove the clean worktree and owner record
158
166
  devrouter workspace down feat/my-feature
167
+
168
+ # Review missing owners; add --yes only after reviewing the dry run
169
+ devrouter workspace gc
170
+ devrouter workspace gc --yes
159
171
  ```
160
172
 
161
173
  New worktrees default to the repository's ignored `trees/<workspace>` directory; use `--path` only when a repository intentionally follows another layout.
162
174
 
175
+ | Command | DevPod | Routes | Worktree and owner record |
176
+ | --- | --- | --- | --- |
177
+ | `workspace stop` | stop | remove | keep |
178
+ | `workspace down` | delete | remove | remove only when clean and unlocked |
179
+ | `workspace down --keep-worktree` | delete | remove | keep |
180
+ | `workspace gc` | report only | report only | never removes Git worktrees |
181
+ | `workspace gc --yes` | delete eligible missing owners | remove exact owned routes | remove only the owner record |
182
+
183
+ `workspace ls` reports owner status as `present`, `missing`, `locked`, or
184
+ `conflict`. Full `workspace down` checks ownership, the Git registration, lock,
185
+ and cleanliness before changing runtime or routes; dirty and locked worktrees fail
186
+ with zero teardown side effects.
187
+
188
+ Workspace lifecycle commands require a Git repository. Normal config, app,
189
+ status, and diagnostic commands remain usable from a `.devrouter.yml` directory
190
+ without Git. Git has no worktree-removal hook, so devrouter does not install one:
191
+ after manual removal, use `workspace ls`, `doctor`, or the dry-run
192
+ `workspace gc` report before applying cleanup with `--yes`.
193
+
163
194
  **devcontainer integration:** the devcontainer compose service exposes a devnet network alias `${WORKSPACE}-app` (defaulting to the project name in `devcontainer.env`); the proxy app uses `upstream: ${WORKSPACE}-app:<port>`. `.devcontainer/docker-compose.devrouter.yml` passes `WORKSPACE` and `DEVROUTER_WORKSPACE` into the app and bind-mounts `${DEVROUTER_GIT_COMMON_DIR}` to the same absolute container path, so linked-worktree `.git` pointers remain valid. Workspace `feat-a` → alias `feat-a-app`, host `app.feat-a.localhost`.
164
195
 
165
- `workspace ensure` is intentionally proof-driven: it verifies exact worktree
166
- ownership, the compose overlay and Git mount, workspace env, devnet aliases,
196
+ `ensure` is intentionally proof-driven: it verifies exact checkout ownership,
197
+ the required compose/Git mount contract, workspace env when linked, devnet aliases,
167
198
  container health, Git access, HTTP route reachability, and unique running TCP
168
199
  upstream ownership (plus health when configured) before reporting ready. It
169
200
  retries one stale DevPod with `--recreate`; failed proof does not leave new routes
170
201
  behind.
171
202
 
203
+ Use `devrouter stop .` to pause the exact environment without deleting data. Use
204
+ `devrouter exec . -- <command...>` for seeds, migrations, and other one-shot
205
+ container commands; it does not start a missing or stopped environment.
206
+
172
207
  **Try it:** [`examples/workspace/`](examples/workspace/) is a runnable showcase — `./run.sh` brings up one app in two parallel worktrees (`wsdemo.localhost` and `wsdemo.feat-a.localhost`) served at once, then `./run.sh down` tears it down.
173
208
 
174
209
  **DevPod example:** [`examples/devcontainer/`](examples/devcontainer/) is the
175
210
  agent-native devcontainer path end to end — `./run.sh` brings up a DevPod
176
- workspace, registers app/Postgres proxy routes, runs static/live verification,
177
- and prints the proof. `./run.sh down` tears it down.
211
+ workspace, runs static verification and `ensure`, proves exact-container `exec`,
212
+ and checks trusted app/Postgres routes. `./run.sh down` tears it down.
178
213
 
179
- **Orphan detection:** `devrouter doctor` check `routes.orphaned-workspace-routes` reports proxy routes whose worktree directory was removed without `devrouter workspace down`. It does not mutate route state.
214
+ **Missing-owner detection:** `devrouter doctor` reports ledger-owned workspaces
215
+ whose checkout disappeared or conflicts with live Git/DevPod evidence. It does
216
+ not mutate workspace state and prints the exact dry-run remediation command:
217
+ `devrouter workspace gc --repo <repo>`.
180
218
 
181
219
  ## Upgrade metadata and prompts
182
220
 
@@ -243,7 +281,7 @@ devrouter doctor --repo /absolute/path/to/repo --json
243
281
  For host apps that depend on postgres, `devrouter doctor` also checks host command wrapper precedence and warns with `repo.host-command-env-precedence` when `DATABASE_URI`/`DATABASE_URL` is assigned before a `run --` wrapper boundary.
244
282
  When TLS is enabled, `devrouter doctor` also checks TLS host coverage and warns with `repo.tls-host-coverage` if configured `.localhost` hosts are not covered by the current cert SANs.
245
283
  When `.devcontainer/` exists, `devrouter doctor` checks devnet aliases, published host ports, and proxy upstream alias matches.
246
- `devrouter doctor` reports stale host routes and orphaned workspace proxy routes without mutating route state.
284
+ `devrouter doctor` reports stale host routes and ownership cleanup candidates without mutating route state; workspace findings point to dry-run `devrouter workspace gc --repo <repo>`.
247
285
 
248
286
  ## `.devrouter.yml` example
249
287