@somewhere-cloud/cli 0.38.14 → 0.38.16

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/CHANGELOG.md ADDED
@@ -0,0 +1,1378 @@
1
+ # Changelog
2
+
3
+ ## 0.38.16
4
+
5
+ ### Added
6
+
7
+ - `somewhere upgrade [--json]` moves every recorded CLI pin to the running CLI
8
+ and prints the `CHANGELOG.md` entries in between (`CHANGELOG.md` now ships in
9
+ the package). To reach the newest release: `npx -y @somewhere-cloud/cli@latest
10
+ upgrade`, then `npm install`.
11
+ - New projects pin the CLI version they were created with (`init`, `project
12
+ create` and the temporary deploy record it, and send it to the platform as
13
+ `cli_version`). A different CLI run inside the project prints one line and
14
+ runs the installed pin. Skills are never updated on their own; `upgrade`
15
+ leaves them alone and says `skills update` is the explicit step.
16
+ - The starter `AGENTS.md` names the data-and-code exits (`somewhere pull`,
17
+ `somewhere db dump`, CSV export, PostgreSQL in your own Neon account) and
18
+ points at `somewhere docs portability`.
19
+
20
+ ### Changed
21
+
22
+ - README, LICENSE, the starter and `browser` help no longer name the old
23
+ package scope, the old domain or "legacy"; the copyright holder is
24
+ Somewhere HQ, Inc. A test refuses those words in what ships.
25
+
26
+ ## 0.38.15
27
+
28
+ ### Changed
29
+
30
+ - `somewhere deploy` (and the patch path) waits up to 5 s for the blank-page check
31
+ that runs after the platform answers (`post_live_render: pending`), reading the
32
+ settled result from `GET /deploy/log?release_id=`. A page the check finds blank
33
+ fails the deploy with `DEPLOY_BLANK_PAGE` and the rejection, instead of being
34
+ rolled back silently after the command returned.
35
+ - `somewhere rollback` prints the database notice in its plain-text output: a
36
+ code-only rollback across a schema change says the tables and columns added
37
+ since stay, with their data, and the target version ignores them.
38
+
39
+ ## 0.38.14
40
+
41
+ ### Added
42
+
43
+ - `somewhere tasks delete <id> --reason <text>`, `somewhere tasks restore <id>
44
+ [--reason <text>]` and `somewhere tasks deleted`: delete a task from the
45
+ board, bring it back, and list deleted tasks. Only the board owner can use
46
+ them; anyone else is refused with `TASK_DELETE_FORBIDDEN`.
47
+
48
+ ### Changed
49
+
50
+ - `somewhere deploy`: once the target project is known (a linked folder or
51
+ `--project`), the CLI asks the platform to start the project's compile
52
+ container while it packs and uploads, so a cold redeploy no longer waits for
53
+ that container after the upload. The request is sent once and never awaited;
54
+ any answer, including an older platform's 404, leaves the deploy unchanged.
55
+ `--dry-run` sends none.
56
+
57
+ ## 0.38.13
58
+
59
+ ### Changed
60
+
61
+ - `somewhere init`: the starter's `AGENTS.md` points to `grant()` for sharing
62
+ your own rows with specific people (read-only sharing, co-authors):
63
+ `somewhere docs declared-data --section per-owner-sharing`. The agent
64
+ workflow names `anyOf(owner(), grant())` beside the other scopes, and the
65
+ green starter's access paragraph carries the same pointer.
66
+ - The bundled skills pack is refreshed to the platform's current pack.
67
+
68
+ ## 0.38.12
69
+
70
+ ### Changed
71
+
72
+ - `somewhere deploy --project <id>` from a folder with no recorded base: when
73
+ `<id>` is already a canonical project id, the live release it deploys against
74
+ is read alongside the project lookup instead of after it. The lookup still
75
+ binds the target first, a folder linked to a different project is still
76
+ refused before anything is uploaded, and the read is used only when the
77
+ lookup confirms the same project.
78
+
79
+ ## 0.38.11
80
+
81
+ ### Changed
82
+
83
+ - `somewhere init`: the starter's `AGENTS.md` public-form example declares its
84
+ request body schema with `sw.endpoint`, and the agent workflow text is
85
+ re-synced to the platform's.
86
+
87
+ ### Fixed
88
+
89
+ - `somewhere deploy-check --json` keeps the platform's error code, message and
90
+ request id instead of replacing them with `CLI_ERROR`.
91
+
92
+ ## 0.38.10
93
+
94
+ ### Added
95
+
96
+ - `somewhere ai keys --project <project>` (also `list`, `ls`),
97
+ `somewhere ai keys set <anthropic|openai> --project <project> [--stdin]` and
98
+ `somewhere ai keys remove <anthropic|openai> --project <project>` (alias `rm`)
99
+ manage a project's own AI provider keys. `--project` is required on all
100
+ three; the destination is never taken from the linked folder.
101
+ - The key is never a command-line argument: `set` reads it from a hidden
102
+ prompt or, with `--stdin`, from a pipe. Unknown options and stray values are
103
+ refused without being repeated, and a key is checked locally (not empty, no
104
+ spaces or line breaks, at most 4096 characters) before any request.
105
+ - Until the platform serves the key-status read, `ai keys` reports
106
+ `AI_KEY_STATUS_UNAVAILABLE` instead of an empty list; `set` and `remove`
107
+ work now.
108
+
109
+ ## 0.38.9
110
+
111
+ ### Fixed
112
+
113
+ - The sign-in code step in the starter that `somewhere init` writes now asks
114
+ for the 6-digit code from the email (heading "Check your email"), instead of
115
+ an "Authenticator or backup code". "Send a new code" requests a fresh code a
116
+ minute after each send and never sends automatically; the newest code is the
117
+ one to use, and a new code does not extend the 5-minute step. Refusals (send
118
+ limit, lockout, expired step, failed send) show the platform's own message.
119
+ "Sign in again" leaves the step.
120
+ - The feature and minimal starters pin `@somewhere-cloud/sdk` 0.14.1, which
121
+ provides `resendMfaCode()`.
122
+
123
+ ## 0.38.8
124
+
125
+ ### Changed
126
+
127
+ - The starter that `somewhere init` writes no longer shows a whole-page loading
128
+ screen ("Checking your session…"). Until sign-in is known, the app frame
129
+ renders at once with the app's name and no account controls.
130
+ - The starter pins `@somewhere-cloud/sdk` 0.14.0 (the minimal template
131
+ `^0.14.0`). With 0.14.0 the platform's early session script starts the
132
+ sign-in check while the page is still loading.
133
+
134
+ ## 0.38.7
135
+
136
+ ### Changed
137
+
138
+ - Before any command runs, the CLI deletes `last-run.json` (and
139
+ `last-run.json.tmp`) in the config directory (default `~/.somewhere`, or
140
+ `SOMEWHERE_CONFIG_DIR`). Versions before 0.38.6 saved command arguments and
141
+ output there in plain text. The file is never read or printed; only its path
142
+ and an error code are shown if it cannot be removed. At exit the CLI writes
143
+ the metadata-only record introduced in 0.38.6.
144
+ - The `AGENTS.md` that `somewhere init` writes (default and `--bare`) points to
145
+ the declared-access recipes, readable with
146
+ `somewhere docs sw.db --section owner-or-member-and-parent-access`.
147
+
148
+ ## 0.38.6
149
+
150
+ ### Fixed
151
+
152
+ - An expired temporary session (from deploying without logging in) no longer
153
+ blocks `init` or a fresh `deploy`. `init` writes the starter offline and
154
+ names the folder it wrote to; `deploy` says in one line that it replaced the
155
+ expired session.
156
+ - Signed out, a deploy that names an existing project (`--project` or a linked
157
+ folder) now stops before contacting Somewhere with `SIGN_IN_REQUIRED` and
158
+ the two ways forward (sign in, or drop the target to start a new temporary
159
+ project), instead of creating a temporary account and then failing.
160
+ - A file over the 5 MB per-file limit that would be published now stops
161
+ `deploy` and `preview` before any request (`FILE_TOO_LARGE`), instead of
162
+ being left out while the deploy goes live. `.gitignore` and
163
+ `.somewhereignore` still keep large files out on purpose.
164
+ - When a deploy request may have reached Somewhere but no answer came back,
165
+ the CLI never sends it again. It reports the outcome as unknown
166
+ (`deployment_outcome: "unknown"` with `--json`) and says how to check.
167
+ - `somewhere` needs Node.js 22.19.0 or newer and now says so on older Node.js,
168
+ instead of failing with a TypeError.
169
+ - `auth set` reports only an HTTP 401 as an invalid token; an outage or other
170
+ failure says the token could not be verified and saves nothing. `whoami`
171
+ reports only a 401 as a login problem.
172
+ - Commands piped into a reader that closes early (`docs | head -1`) end
173
+ quietly instead of reporting a network failure.
174
+ - Anonymous deploy errors keep Somewhere's error code, status and request ids.
175
+
176
+ ### Changed
177
+
178
+ - `typecheck` is read-only: it never installs packages. Missing type packages
179
+ stop it with an `npm install` instruction, it announces when it fetches
180
+ TypeScript with npx, and every check runs under a deadline
181
+ (`SOMEWHERE_TYPECHECK_TIMEOUT_MS`, default 300 s) that stops its processes.
182
+ - `deploy --json` keeps stdout for the deploy result and lists every file left
183
+ out locally on stderr, by path and reason.
184
+ - `preview` judges each save like a deploy: ignored files are not uploaded and
185
+ an oversize file holds the save without changing the last preview.
186
+ - `somewhere api` refuses full URLs, control characters, `..` segments and
187
+ unsupported methods before sending anything; the request always stays on the
188
+ configured API.
189
+ - `logs --tail` takes a whole number from 1 up. `dev` refuses extra arguments.
190
+ - The local `last-run.json` records only the command, option names, exit code,
191
+ time and CLI version, never values or output. `env set` with a value on the
192
+ command line points to `--stdin`.
193
+ - Declared-data and runtime types and the source lint are refreshed from the
194
+ live platform.
195
+ - README and help text describe `dev`, `init`, `typecheck` and project delete
196
+ as they actually behave.
197
+
198
+ ## 0.38.5
199
+
200
+ ### Changed
201
+
202
+ - Files blocked by the deploy's sensitive-path policy never leave your
203
+ machine. The CLI now applies the same policy Somewhere applies to every
204
+ uploaded path, while it collects files: before any file is read into an
205
+ upload and before any request. The policy matches file names only, in any
206
+ folder: private-key files (`id_rsa`, `*.pem`, `*.key`, `*.p12`, `*.pfx`),
207
+ `credentials` data files (`credentials.json`, `credentials.yaml`, …), secrets
208
+ files (`secrets.json`, `secrets.yaml`, …), `service-account.json`,
209
+ `service-account-key.json` and the Firebase Admin SDK key file
210
+ (`<project>-firebase-adminsdk-<id>.json`). Dotfiles such as `.env` were
211
+ already never uploaded. This filename policy does not detect secrets under
212
+ other names. Held-back files are listed under "Never uploaded", and neither
213
+ `--include` nor a `!` line in `.somewhereignore` or `.gitignore` publishes
214
+ them. `credentials.ts`,
215
+ `credentials.tsx`, `credentials.md`, `.well-known/` and ordinary config such
216
+ as `firebase.json` and `google-services.json` are not affected by this policy.
217
+ - When your published code mentions one of those files by name, `deploy`,
218
+ `deploy --dry-run`, `deploy-check` and `preview` stop before contacting
219
+ Somewhere, name the file and the code that mentions it, and suggest storing it
220
+ as a project secret (`somewhere env set NAME --stdin < file`, read with
221
+ `sw.env.NAME` in a function). This is a filename match in your code, not an
222
+ import analysis; documentation such as `README.md` is not searched. If nothing
223
+ loads the file, add it to `.somewhereignore` or move it out of the folder.
224
+ - `somewhere deploy --dry-run` now says, in its help and in its human-readable
225
+ output before it runs, that the files a deploy would publish are sent to
226
+ Somewhere to compute the change and that nothing is published. A dry run
227
+ still works this way. `--dry-run --json` output is unchanged.
228
+
229
+ ## 0.38.4
230
+
231
+ ### Changed
232
+
233
+ - `somewhere deploy --dry-run` no longer creates anything. When there is no
234
+ usable credential (signed out, with no live temporary workspace) or no
235
+ existing project to compare against (no linked project, no `--project`), it
236
+ stops before contacting Somewhere: no temporary workspace, no project, no link
237
+ and no change to project or login files. It says so and points to
238
+ `somewhere typecheck` and `somewhere lint`, which check your code without
239
+ contacting Somewhere, or to `somewhere deploy`. With a usable credential and
240
+ an existing project it shows the deploy's changes as before, and it no longer
241
+ records the one-time "not published" notice in `.somewhere.json`.
242
+ - Tests stay on your machine by default: `*.test.*` and `*.spec.*` source
243
+ files, and anything in a `tests/` or `__tests__/` folder, are listed under
244
+ "Not published". To publish one, use `somewhere deploy --include <path>` or a
245
+ `!<path>` line in `.somewhereignore`. `--include tests` or `!tests/` publishes
246
+ the helpers in that folder, for an app that imports them; a test-named file
247
+ inside it still needs its own opt-in. `.env` files stay excluded either way,
248
+ and `.well-known` keeps publishing.
249
+ - No new commands, options or dependencies. `--include` now also takes a test
250
+ folder, as above.
251
+
252
+ ## 0.38.3
253
+
254
+ ### Changed
255
+
256
+ - The starter's AGENTS.md shows webhook and streaming handlers with their
257
+ parameter types, `(req: Request, sw: SomewhereRuntimeContext)`, instead of
258
+ saying `somewhere typecheck` types unannotated handlers, which it does not:
259
+ under the starter's strict settings an unannotated handler is a type error.
260
+ - The bundled realtime-and-background skill's example handler carries the
261
+ same annotation. The bundled skills match the platform's served pack.
262
+ - No command, option or dependency changes.
263
+
264
+ ## 0.38.2
265
+
266
+ ### Changed
267
+
268
+ - The bundled schema-changes skill says that `removedTable()` retires a deployed
269
+ table with 30-day data retention, instead of pointing to a description "above"
270
+ that the skill does not include. The bundled skills match the platform's served
271
+ pack.
272
+ - The minimal starter's README keeps the booking and help-desk recipe command on
273
+ one line.
274
+ - No command, option or dependency changes.
275
+
276
+ ## 0.38.1
277
+
278
+ ### Changed
279
+
280
+ - `somewhere init` writes the current agent workflow, skills and minimal starter
281
+ guidance. `AGENTS.md` matches the published platform workflow: `id()` is a
282
+ random text key referenced with `text()`, fitting declared scopes stay in place
283
+ when an exceptional write needs `sw.db.server.tx`, and the sign-in starter modes
284
+ are listed on one line. The bundled skills match the platform's served pack.
285
+ - The minimal starter's README says to delete a table declaration that was never
286
+ deployed and to use `removedTable()` for a deployed table, even an empty one.
287
+ It also notes that the greeting's `serverOnly()` scope is a demonstration, not
288
+ the default for app data, and points to the booking and help-desk recipes.
289
+ - No command, option or dependency changes.
290
+
291
+ ## 0.38.0
292
+
293
+ ### Changed
294
+
295
+ - The CLI is now published as `@somewhere-cloud/cli` (install with
296
+ `npm i -g @somewhere-cloud/cli`, or run `npx @somewhere-cloud/cli <command>`).
297
+ `@somewhere-tech/cli` stays installable at its existing versions. The command
298
+ name is still `somewhere`.
299
+ - Defaults target somewhere.cloud: the API at `https://api.somewhere.cloud` and
300
+ MCP at `https://mcp.somewhere.cloud`.
301
+ - An app's function URL comes from the platform (`app_url` in `.somewhere.json`,
302
+ printed by `somewhere status --json`), never from a project slug.
303
+ - `somewhere init` writes the project contract (`AGENTS.md`, "somewhere.cloud
304
+ project contract") and the bundled skills pack from the current platform docs.
305
+ They name `@somewhere-cloud/cli` and `@somewhere-cloud/sdk`. Starters depend on
306
+ `@somewhere-cloud/sdk` 0.13.0.
307
+
308
+ ## 0.37.86
309
+
310
+ ### Fixed
311
+
312
+ - The CLI now talks to Somewhere's current hosts (`api.somewhere.cloud`, `mcp.somewhere.cloud`, runner and site defaults). The previous release still defaulted to `api.somewhere.tech`, which has moved, so `somewhere deploy` from a fresh folder failed immediately. `init` → `deploy` works again with no login and no environment overrides.
313
+ - The README quick start marks `somewhere login` as optional; `init` and `deploy` run anonymously and print a claim link.
314
+
315
+ ## 0.37.77
316
+
317
+ ### Fixed
318
+
319
+ - `somewhere deploy --project <ref>` from a folder that is not linked to that project no longer fails with `BASE_REQUIRED` on every attempt. The CLI first resolves the ref to its project and reads the project's live release, declares that release as the deploy's base, and lets the platform's existing stale-overwrite check decide: a release that lands between that read and the publish is still refused (`STALE_RELEASE_BASE`), never overwritten, and the CLI never retries or forces. A linked folder keeps sending its own recorded base; a folder linked to a different project than `--project` names is refused with a clear message instead of being redeployed elsewhere; `--force` behaviour is unchanged. When the live release cannot be read, the `BASE_REQUIRED` recovery now names a path that terminates (`init --link`, `pull`, `deploy`) instead of a bare `somewhere pull`.
320
+
321
+ ## 0.37.76
322
+
323
+ ### Changed
324
+
325
+ - The bundled agent skills pack is refreshed from the platform docs and gains a seventh skill, `design`: the UI kit in `src/ui`, the token rules, the `AuthCard` slots, and the two mistakes that make a generated page look unfinished. New starters install it in `.agents/skills/design`; `somewhere skills update` brings it to an existing project.
326
+
327
+ ## 0.37.75
328
+
329
+ ### Fixed
330
+
331
+ - `somewhere init`: the generated `index.html` escapes `"` as `&quot;` in the app name, which is both the `<title>` text and the `description` attribute value, so a quote in a project name no longer ends the attribute.
332
+
333
+ ## 0.37.74
334
+
335
+ ### Added
336
+
337
+ - `somewhere init` auth starters ship a UI kit in `src/ui` (`Button`, `TextField`, `SelectField`, `TextareaField`, `CheckboxField`, `FormRow`, `Card`, `Table`, `Stat`, `Badge`, `Tabs`, `Dialog`, `Notice`, `Skeleton`, `Stack`, `Grid`, `Inline`, `PageHeader`) with styled and headless twins that share props, and `src/pages/HomePage.tsx` is a worked example of them (header, stats, table in a card, dialog form) instead of an empty state. The README gains a "Look" section with the rules that keep generated pages consistent (tokens only, no global tag styles, one primary action, cards for peers).
338
+ - Social sign-in is a config toggle: `SIGN_IN_PROVIDERS` (`src/config.ts`) starts as `['google']`, so a new app shows "Continue with Google" out of the box (the platform owns the OAuth client; nothing to configure); set it to `[]` for email-only sign-in or add `github` / `discord`. The "Continue with …" buttons, `src/auth/useProviderSignIn.ts` and the `/auth/callback` page (the SDK's `AuthCallback`) are already wired. `APP_TAGLINE` sets the sign-in page's one-line description.
339
+ - `src/styles/tokens.css` gets a `prefers-color-scheme: dark` block, semantic tones (success/warning/danger/info), shadows and a cross-platform font stack, so the starter no longer falls back to Arial/Georgia off macOS. `index.html` gets description, `theme-color` and an SVG favicon.
340
+
341
+ ### Changed
342
+
343
+ - `AuthCard` has permanent `providers` (above the form) and `children` (below it) slots; the magic-link module passes its form as a child instead of patching the card's markup, and nothing else is a sibling of the two-column `.auth` grid.
344
+ - The "Verify your email" panel is a quiet notice with secondary buttons, not the page's loudest call to action. `MfaStep` uses the starter's panel and field classes.
345
+ - Starter stylesheet: the notes status line is `.note-status` (`.notice` is the kit's notice component); `.alert` and `.section-title` live in the base stylesheet, so removing a module leaves no orphaned rules.
346
+ - Social sign-in sends the browser to `/auth/callback?provider=<name>` and the callback page passes that provider to the SDK's `AuthCallback`, so a GitHub or Discord code is exchanged with the provider that issued it (the SDK defaults to Google). An unknown `?provider=` is ignored. With `SIGN_IN_PROVIDERS = []` the sign-in card has no providers slot, so no "or use email" divider is shown.
347
+
348
+ ## 0.37.72
349
+
350
+ ### Fixed
351
+
352
+ - New apps from `somewhere init` use SDK 0.12.6. It keeps session verification outages as an unavailable response instead of reporting that the user signed out, and uses browser keepalive for refresh requests to reduce interruption during navigation. Keepalive is a limited mitigation, not full recovery from a lost refresh response (#96).
353
+
354
+ ## 0.37.71
355
+
356
+ ### Fixed
357
+
358
+ - `somewhere logs` text output: every recorded stack line now starts with a fixed `stack | ` marker under its log row, so stack text can never pass as a log row. A stack longer than 30 lines ends with "… N more lines (--json shows the whole stack)". `--json` is unchanged (#90).
359
+ - `somewhere support packet`: the packet's `omitted` list no longer names `emails`, `tokens` or `passwords`. The list names only the parts of a failure the packet builder never reads; it was never a guarantee that a collected field cannot contain such a value, so review a packet before you submit it (#92).
360
+
361
+ ## 0.37.70
362
+
363
+ ### Fixed
364
+
365
+ - `somewhere support packet --trace`: the packet keeps a failure code only when it is one of the function runtime's own failure codes (the server-recorded response code first, then the logged code). Any other code, including an app-chosen `err.code`, is recorded as `APP_ERROR_CODE`, so a code-shaped value from your app never enters the packet. Your own logs still show the code as written (#88).
366
+ - `somewhere logs` and `somewhere errors` text output: control characters in stored messages and stack frames (newlines, carriage returns, ESC/ANSI sequences, BEL, C1 controls, line/paragraph separators and bidi overrides) are shown as visible escapes, so each stored row prints as exactly one line and a message cannot fake another row or change the terminal. `--json` output is unchanged (#88).
367
+ - `somewhere support packet --help` names exactly which fields the packet reads and how the code is restricted, instead of a blanket "never holds tokens or passwords" claim (#88).
368
+ - `somewhere verify --keep-actors` help states the real lifetimes: a kept browser closes after 5 minutes idle, and at most 10 minutes after it started (#87).
369
+
370
+ ## 0.37.69
371
+
372
+ ### Added
373
+
374
+ - `somewhere verify --keep-actors --resume-page`: an explicit warm continuation. A kept actor whose first segment starts at exactly the page path the last passed run left it on keeps that page as it was (no reload); any other actor, flow, project or start path, a start path with a query or fragment, or a kept browser that is gone reloads normally. `--resume-page` without `--keep-actors` is refused. The report lists resumed actors under `keep_actors.resumed_pages` with a note that the run does not prove the latest deployed code; run without `--resume-page` for that. The keep record stores the page pathname only (#85).
375
+ - `somewhere logs --trace <trace id>` shows only that request's log lines, with any recorded stack under its line, so the `trace_id` from a `500 FUNCTION_ERROR` leads straight to the crash. Anything but a 32-hex id is refused before any request; plain `somewhere logs` is unchanged.
376
+ - `somewhere support packet --trace <trace id> [--project <ref>]` builds the `somewhere.repro/1` packet for that failed request from the owner's log rows. It keeps only the error code, HTTP status, request and trace ids, method and a templated path (route words become `:id`/`:seg`); never the message, stack, body, query or headers. A failed mutating request is recorded as `unknown` and never rerun. It is written locally and submitted only if you choose (#83).
377
+
378
+ ## 0.37.68
379
+
380
+ ### Fixed
381
+
382
+ - `somewhere verify --keep-actors`: when nothing is kept yet for this flow file and its actors in this folder (a first run, a new or renamed flow file, or a changed cast), one stderr line says the run starts fresh and will keep them for the next run of the same file. If other flows in the folder have kept actors, it also says they are not reused and that `--close-actors` closes them. No behaviour change (#82).
383
+
384
+ ## 0.37.67
385
+
386
+ ### Fixed
387
+
388
+ - Starter apps from `somewhere init`: when the session check fails, the "We can't confirm your sign-in" panel says what broke (couldn't reach the server, the server had a problem (HTTP 5xx), too many checks (HTTP 429, wait a minute), an unreadable answer, or a refused check (HTTP 4xx)), that the sign-in may still be valid so try again before signing in again or asking for a new link, and a status-only code to report (`SESSION_CHECK_FAILED, HTTP n` or `no response`). It used to always blame the connection. Only the SDK's typed status is shown, never server text (#80).
389
+
390
+ ## 0.37.66
391
+
392
+ ### Added
393
+
394
+ - `somewhere verify --keep-actors`: after a fully passed multi-user run, each actor's signed-in browser and test user are kept for the next run of the same flow (same owner, project, folder and cast). That run signs each actor in again and starts from each segment's path, but the browser keeps its earlier state, so a pass on a kept browser is a warm re-check; run without `--keep-actors` for a fresh first load. Any stop, failure or unconfirmed call cleans up as before. `--close-actors` closes the browsers and deletes the identities. The project folder's private `.somewhere/test/verify-actors.json` records ids and emails only (#74).
395
+
396
+ ### Fixed
397
+
398
+ - After a failed `somewhere call`, `somewhere support packet` records the platform's HTTP status and trace id, so a definite refusal (for example a 404) is recorded as `refused` with its status, the same as the MCP packet, instead of `unknown` with no status or ids. A call that got no response at all (network or timeout) stays `unknown`, with no status invented. Only validated status and ids are kept (#76).
399
+
400
+ ### Changed
401
+
402
+ - Internal: the `somewhere support packet` repro record uses the platform's shared `somewhere.repro/1` module (vendored byte-identical, with a checksum check). No behaviour change (#73).
403
+
404
+ ## 0.37.65
405
+
406
+ ### Added
407
+
408
+ - `somewhere support packet [--json] [--out <file>]`: builds a local, redacted repro packet for the last failed command from typed fields only (CLI version, command names, validated error code, HTTP status, an id-templated operation, validated request/trace/project ids, retry verdict, outcome and duration). It never includes the message, hint, data, arguments, bodies, headers, SQL, URL query, emails, tokens, source or env. Nothing is uploaded (#67).
409
+
410
+ ### Fixed
411
+
412
+ - A refused `somewhere verify` names the invalid field and limit (`start_error_details`: code, status, path such as `actions[2].timeout_ms`, `limit_ms`) instead of echoing the platform message (#67).
413
+ - Text-mode output for a platform failure adds one line with its code and request/trace ids (for example `code PROJECT_NOT_FOUND · request req_… · trace …`). The message stays the platform's own; `--json` is unchanged (#71).
414
+ - `somewhere lint` vendors the platform's source lint at somewhere-tech#714: a file exempted from the request-ownership trace by a genuine verifier call reports `coverage.request_ownership` as `partial` instead of `checked`. Warning metadata only; findings and exit codes are unchanged (#72).
415
+ - `somewhere test-users prepare --help` no longer promises "about 1 hour" sessions or 24-hour identities. It says the session starts with the expiry prepare prints, that a refresh with saved-back state can renew it, and not to rely on expiry: remove the identities with `somewhere test-users cleanup`. A state copied before cleanup may keep working until its access token (JWT) expires (#70).
416
+
417
+ ## 0.37.64
418
+
419
+ ### Added
420
+
421
+ - `somewhere verify` multi-user journeys report where their time went: each segment carries `timing` (the platform's own browser-call timing numbers and `browser_reused`, plus this CLI's `request_wall_ms`), and the journey adds `test_users_create_ms`, `segments_ms`, `cleanup_ms` and `test_users_delete_ms`. Reporting only; no behaviour, ordering or cleanup change (#68).
422
+
423
+ ### Fixed
424
+
425
+ - Starter apps from `somewhere init` adopt `@somewhere-tech/sdk` 0.12.4 (feature starter exact `0.12.4`, basic starter `^0.12.4`), which issues an expiry on every cookie reply and reconciles an orphaned refresh marker without a rotation replay (#64).
426
+
427
+ ## 0.37.63
428
+
429
+ ### Added
430
+
431
+ - `somewhere test-users prepare|address|inbox|cleanup`: prepares signed-in managed test users as standard Playwright `storageState` files (production origin only; state kept under `<project>/.somewhere/test/`, never the developer key, no token printed), gives a fresh `test.somewhere.site` address for real signup tests, reads only test-inbox mail newer than `--since` (the magic link only with `--json --include-link` or `--link-out`), and cleans up only the identities it created, with a readback receipt (#63).
432
+
433
+ ### Fixed
434
+
435
+ - `somewhere whoami` says what its project count counts, so it reconciles with `somewhere projects` (for example "6 projects you own (`somewhere projects` lists 5 of them; not listed: 1 archived)"); `--json` still prints the raw account response. Shipped in 0.37.63; this entry was added afterwards (#66).
436
+ - `somewhere deploy`: when the after-live reference check is still pending, text output names the existing read for this exact version (`somewhere call project_deploy_log '{"version":N}'`). `--json` is unchanged (#62).
437
+
438
+ ## 0.37.62
439
+
440
+ ### Fixed
441
+
442
+ - `somewhere verify` reports and their printed text mask credential-bearing parts of URLs: URL userinfo; in the query or fragment, the value of a credential parameter (`token`, `access_token`, `refresh_token`, `auth_token`, `code`, `secret`, `signature`, `sig`, `key`, `api_key`, `apikey`, `creator_secret`, `dsn`, `password`, also percent-encoded or nested encoded in another parameter) or a JWT/key-shaped value under any name; and credential-shaped path segments. This covers a journey segment's `path` and `final_url`, each viewport's `final_url`, `target` and `goto` step labels. The browser still opens the original URL. Error messages and reports saved earlier are not rewritten (#57).
443
+ - Starter apps from `somewhere init`: the email-verification panel offers "I already have a code" beside "Email me a code". It opens the code form without sending another email, so a code already received still works after a new tab or reload. A failed or rate-limited send still does not open the form (#59).
444
+
445
+ ## 0.37.61
446
+
447
+ ### Fixed
448
+
449
+ - `somewhere verify --out <existing file>` still never overwrites a report, and now names the next free path to rerun with (for example `--out flows/run2-report-3.json`) (#56).
450
+ - `somewhere pull` writes the starters' `.gitignore` when the folder has none, so the declarations `somewhere typecheck` generates (`__somewhere_data.d.ts`, `__somewhere_files.d.ts`) stay untracked in a pulled app. An existing `.gitignore` is never changed (#55).
451
+ - `somewhere lint`: quoted verifier text can no longer hide a row-ownership warning; the exception now covers only executable verifier member calls. Vendored with the platform's source lint (#53).
452
+
453
+ ## 0.37.60
454
+
455
+ ### Fixed
456
+
457
+ - `somewhere verify --out` no longer summarises a run in which no browser started as "0 failed steps": it says "Verify FAIL: no browser ran (<codes>); nothing was checked, so this is not an app result", and a partial journey names its unstarted segments. `--json` summaries add `segments_not_started` and `start_errors` (error codes only) (#50).
458
+
459
+ ## 0.37.59
460
+
461
+ ### Fixed
462
+
463
+ - `somewhere deploy` in a folder whose `.somewhere.json` links a project this sign-in can't open (for example an expired, unclaimed temporary project) now explains that, says nothing was deployed, and lists the next steps: see your projects, `somewhere init --link --project <name-or-id>`, or delete the link and `somewhere init --bare --name <name>`. `--json` adds `linked_project_id`, `deployed: false` and `next_steps` (#51).
464
+ - Project commands run in an unlinked folder (logs, errors, env, project view, open, verify, browser open, db, db rows, status, pull, rollback, run, git) name the exact link and create commands instead of "run from a linked directory" (#51).
465
+
466
+ ## 0.37.58
467
+
468
+ ### Fixed
469
+
470
+ - `somewhere browser --actions` and `somewhere verify` flows keep an action's `"frame"` (frame name, URL substring, child index, or iframe CSS selector) and send it to the platform, so a framed `fill`, `eval` or `expect` runs inside the iframe instead of on the top page. Before, `frame` was dropped, and a framed `eval` could pass against the top page. Whole-page actions (`goto`, `dialog`, a fixed `wait`) and malformed frames are refused; the local browser refuses framed actions; `verify --schema` lists `frame` (#48).
471
+
472
+ ## 0.37.57
473
+
474
+ ### Changed
475
+
476
+ - `somewhere lint --help` names every warning the lint reports: credentials in source, schema declarations, directory index routes, request input choosing row ownership on server writes, and `sw.email.send` awaited inside a loop (#47).
477
+
478
+ ## 0.37.56
479
+
480
+ ### Fixed
481
+
482
+ - `somewhere docs constructor` (and other built-in object names such as `__proto__` or `toString`) now answers that no such documentation topic exists, instead of a false "Could not reach https://somewhere.tech — check your connection." Quick-link topic and alias lookups use own keys only.
483
+
484
+ ## 0.37.55
485
+
486
+ ### Added
487
+
488
+ - `somewhere lint`: a new warning when `sw.email.send` is awaited inside a loop (each email waits for the previous delivery); it advises bounded batches only for independent emails (#43).
489
+
490
+ ## 0.37.54
491
+
492
+ ### Fixed
493
+
494
+ - Signed out, `somewhere docs <topic>` resolves the same topic names the docs tool does: after an exact page id, it looks the name up in the public docs manifest's `aliases` (lowercased, then with non-alphanumeric runs as `-`), so `somewhere docs schema-changes` opens `sw.db`. A manifest without `aliases` keeps today's behavior, and a real page id always wins.
495
+
496
+ ## 0.37.53
497
+
498
+ ### Changed
499
+
500
+ - `somewhere deploy --help` has a "No project yet?" section naming `somewhere init --bare --name <name>` (create a project in your account and link this folder), and `--project` now says it takes an existing project.
501
+ - `somewhere projects` help and its empty-list line name `somewhere init --bare --name <name>`.
502
+ - `somewhere project create` says how to deploy to the project it made (`somewhere init --link --project <id>` then `somewhere deploy`, or `somewhere deploy --project <id>`).
503
+ - When the platform reports no live URL, the CLI names `somewhere project view <id>` instead of "check the dashboard".
504
+
505
+ ### Fixed
506
+
507
+ - The signed-in "No project is linked" deploy message (since 0.37.49) recommended `somewhere link --project <name-or-id>`, which `link` does not accept. It now names `somewhere init --link --project <name-or-id>`, which does.
508
+
509
+ ## 0.37.52
510
+
511
+ ### Fixed
512
+
513
+ - The expired temporary-session deploy message no longer opens with "expired … without being claimed", which contradicted its next step for someone who did claim the workspace in the browser. It now says this machine has no record of a claim; the first step is still "sign in with `somewhere login` if you claimed it".
514
+ - `somewhere lint` no longer reads binary assets, and carries the vendored source-lint fix for a `user.id` false positive (#37).
515
+ - `somewhere verify`: when a request you declared with `expect_requests` came back with a different status, the verdict now leads with that mismatch ("Expected /api/deny to return 200; saw 403.") instead of only reporting the status as undeclared. The pass/fail result and exit code are unchanged (#36).
516
+
517
+ ## 0.37.51
518
+
519
+ ### Fixed
520
+
521
+ - Starter `AGENTS.md` (from `somewhere init`) follows the current platform agent workflow: test sign-in uses managed test identities, matching the platform docs (#32).
522
+ - `somewhere email test-inbox` prints a message's `verification_code` in its human output when one is present, not only with `--json` (#32).
523
+
524
+ ## 0.37.50
525
+
526
+ ### Fixed
527
+
528
+ - An expired temporary session's deploy message now first tells you to sign in with `somewhere login` if you claimed the workspace in the browser, before suggesting you delete `.somewhere.json`. The expiry message also appears only when the session's expiry time has actually passed (a session merely missing its token is no longer reported as "expired at" a future time).
529
+
530
+ ## 0.37.49
531
+
532
+ ### Fixed
533
+
534
+ - `somewhere deploy` with an expired, unclaimed temporary session and a linked (or `--project`) project now stops before sending anything and says the temporary workspace expired and nothing was deployed. Previously it created a new temporary account and failed with PROJECT_NOT_FOUND. `--json` answers `TEMPORARY_SESSION_EXPIRED` with `temp_expires_at`.
535
+ - Signed in with no linked project, `somewhere deploy` now names the exact next steps (`somewhere init --bare --name <name>`, `somewhere link --project <name-or-id>`, or `somewhere deploy --project <name-or-id>`) instead of "No project linked. Run `somewhere init`". It still never creates or links a project on its own.
536
+
537
+ ## 0.37.48
538
+
539
+ ### Fixed
540
+
541
+ - `somewhere deploy` no longer reports "Your deploy was NOT applied" when its own automatic retry, sent after the first attempt timed out or lost its connection, is refused as STALE_RELEASE_BASE: the first attempt may already be live, so the CLI now says that and asks you to check the live release. `--json` adds `first_attempt_outcome: "unknown"` and `first_attempt_failure`. Other stale-base answers are unchanged.
542
+
543
+ ## 0.37.47
544
+
545
+ ### Changed
546
+
547
+ - `somewhere init` starters use `@somewhere-tech/sdk` 0.12.3, which refreshes short-lived per-app sessions without making valid-token reads wait (0.12.1 could not refresh them). The feature starter keeps an exact pin; the basic starter keeps its caret range (#31).
548
+ - New projects' `.gitignore` excludes the generated `src/__somewhere_data.d.ts` and `src/__somewhere_files.d.ts`; `typecheck`, `dev` and `deploy` regenerate them from `db/schema.ts`. Existing projects are untouched (#31).
549
+
550
+ ## 0.37.46
551
+
552
+ ### Added
553
+
554
+ - `somewhere lint`: an offline, advisory source lint (warning-only; never blocks a deploy). Runs locally with no credentials; `--generic` also runs the project's own oxlint with a scrubbed environment and no shell (#26).
555
+ - `somewhere lint` carries the platform's source-lint version 2 rules, re-vendored with full parity against the platform (#29).
556
+ - `somewhere verify`: an actor may declare `{ "test_user": true }`. The run creates that many managed test identities in one request, signs each actor in once in its own browser, and deletes the identities after every browser closes (`--keep-test-users` keeps them; they expire after 24 h). No password or token is requested or reported (#27).
557
+ - `somewhere verify`: a journey item may be `{ "parallel": [segment, segment] }` — 2–3 segments by different actors whose browser calls run at the same time, for realtime checks. Reports carry `parallel_group` (#28).
558
+
559
+ ## 0.37.45
560
+
561
+ ### Changed
562
+
563
+ - `somewhere deploy` fetches project notices alongside the deploy instead of waiting for them first, so their round trip (about 0.1-0.9 s, up to a 3 s timeout) is no longer on every deploy's path. Notices still print once, on stderr, before the result or the failure and before a `--force` confirmation prompt.
564
+
565
+ ## 0.37.44
566
+
567
+ ### Fixed
568
+
569
+ - `somewhere deploy --json` in a temporary (signed-out) session now prints the server's deploy result with the claim fields (`claim_url`, `expires_at`, `claim_connects_agent`) added. Before, it replaced the result, so `version`, `release_id`, `warnings`, `stage_timing_ms` and `reference_check` were dropped. Signed-in output is unchanged.
570
+
571
+ ## 0.37.43
572
+
573
+ ### Fixed
574
+
575
+ - `sw.groups.add` and `sw.groups.delete` type-check in generated starters (TS2339 before): the vendored `runtime/declared-data.cjs` declaration is re-vendored from the platform (#22).
576
+
577
+ ## 0.37.42
578
+
579
+ ### Changed
580
+
581
+ - Local checks read a bare `id()` in `db/schema.ts` as a random text key, the platform default since 2026-10-18; `id({ uuid: false })` declares an integer key. A foreign key must use its parent's key type (`text({ references })` for a random key).
582
+ - `somewhere init --features private-data` keeps an integer key for notes, which its safe create retry needs. New starters otherwise get random text keys.
583
+
584
+ ## 0.37.41
585
+
586
+ ### Changed
587
+
588
+ - The `AGENTS.md` written by `somewhere init` now says to set `auth` on every `sw.endpoint` (`'required'`, `'optional'`, or `'none'` when public on purpose), because a deploy refuses an endpoint without it. Webhooks, streams and custom responses still use a bare `export default async function (req, sw)`.
589
+
590
+ ## 0.37.40
591
+
592
+ ### Changed
593
+
594
+ - Local declared-data checks understand `allOf(gate, who)` permission policies, matching the platform admission that is now live. The vendored declared-data code is refreshed from platform core ed285f7b.
595
+
596
+ ## 0.37.39
597
+
598
+ ### Fixed
599
+
600
+ - `somewhere init` refuses a directory that holds only unrelated files, with no app source, before creating a remote project. It names those files and keeps them; `--bare` and `--link` still accept such a directory.
601
+ - `somewhere verify` gives clearer guidance when a write gets a 409 in one viewport run but not another. Each viewport runs the flow separately, so creating the same record in each run is a possible cause. The run still fails and the 409 stays in the report.
602
+
603
+ ## 0.37.32
604
+
605
+ ### Changed
606
+
607
+ - `somewhere init` keeps AGENTS.md and useful skills without installing command-running agent hooks or MCP registration. Existing local and global agent configuration stays unchanged.
608
+ - The generated project guide asks agents to run `somewhere typecheck` after edits. Optional post-edit deploy-reference hooks remain available through explicit `somewhere hooks install --host <host>`; MCP setup remains explicit through `somewhere mcp install <host>`.
609
+
610
+
611
+ ## 0.37.9
612
+
613
+ ### Added
614
+
615
+ - Every auth starter (plain `somewhere init` and `--features auth`) includes a "Verify your email" code panel for password accounts. It uses the SDK cookie session through the packaged `/api/auth` route, so the session decides the account and no token reaches page code. The starter pins `@somewhere-tech/sdk` 0.11.6.
616
+ - `somewhere init --features magic-link` adds passwordless sign-in links: an "email me a sign-in link" form on the sign-in page and the `/auth/magic` page the email opens, routed in front of the sign-in gate. The page redeems the one-time token for the same cookie session, then opens the link's `redirect_uri` only when it is a page of this app. `sw.auth.invite` links land on the same page.
617
+ - `somewhere init --subdomain <slug>` names the new project's subdomain (default: derived from `--name`). It cannot be combined with `--link`.
618
+
619
+ ### Changed
620
+
621
+ - The bundled declared-data parser and generator are re-vendored from the current platform source.
622
+
623
+ ## 0.37.8
624
+
625
+ ### Fixed
626
+
627
+ - Generated `AGENTS.md` now matches the current app workflow: start with the relevant docs, keep owner-scoped queries tied to the signed-in user, and authorize custom endpoints and server queries.
628
+
629
+ ## 0.37.7
630
+
631
+ ### Fixed
632
+
633
+ - Self-update verifies the published provenance correctly. A refused update exits with an error and prints the npm installation fallback; versions at least one minor release behind get a daily warning.
634
+ - `somewhere call` uses the linked project for tools that take `project_id`. An explicit ID wins; `--all-projects` omits the default and leaves scope to the tool.
635
+ - `somewhere docs` opens the index instead of the entire manual. Use `docs search`, `--section`, or `--full` to read more.
636
+ - Text output from `verify` includes eval results.
637
+ - Browser commands support closing a named session and selecting an app user. User selection refuses an incomplete search rather than guessing.
638
+ - `preview --once` syncs and exits; `preview link` produces a fresh link for an open preview.
639
+
640
+ ## 0.37.6
641
+
642
+ ### Added
643
+
644
+ - `somewhere init --features agent` adds a signed-in assistant to the auth starter. It runs inline `sw.agent.run` with at most 4 steps and 10 cents per reply, and the conversation is saved on the server. It shows the tools each reply used. The assistant can read the user's tasks but only proposes new ones; a task is written when the user approves it. Approval and task creation are two writes, not one transaction: a task write that fails or whose outcome is unknown answers `TASK_CREATION_UNCONFIRMED` and never reopens the approval, so approving again cannot create a duplicate. Owner-scoped `tasks`/`proposals` tables are reached only through `api/chat.ts` and `api/proposals.ts`. `/fixtures?state=loading|empty|error|populated|long` renders preview states from static data without a request, and `flows/assistant-fixtures.json` screenshots them with `somewhere verify`. Durable runs, cancel, streaming and memory are not generated (`agent-durable` in `--catalog`).
645
+
646
+ ### Changed
647
+
648
+ - The default auth starter and `--features` starters pin `@somewhere-tech/sdk` 0.11.3. Its auth code is identical to 0.11.2.
649
+
650
+ ## 0.37.3
651
+
652
+ ### Added
653
+
654
+ - Advisor requests can reconnect to the same saved request after a terminal closes or a connection fails. Use `somewhere advisor --resume <request-id>`, `--status <request-id>`, or `--cancel <request-id>`. The CLI saves the receipt before starting paid work and keeps account and anonymous request ownership separate.
655
+ - When the platform enables durable Advisor requests, the ordinary `somewhere advisor` command adopts the returned request automatically and waits for its result. Earlier platform responses continue to work. Ctrl-C leaves the request available to resume.
656
+
657
+ ### Fixed
658
+
659
+ - Retrying a durable request uses its original receipt instead of creating another paid request. Cancellation records intent; an unknown dispatch remains an unknown outcome.
660
+
661
+ ## 0.31.12
662
+
663
+ ### Fixed
664
+
665
+ - **File uploads work with attribute selectors.** `somewhere browser --upload`
666
+ read the file path from the FIRST `=` in the mapping, so a selector that
667
+ contains its own equals sign — `[data-testid=file]` — was cut in half and the
668
+ leftover text was treated as the path. The path is now read from the LAST `=`,
669
+ which leaves `#avatar=./photo.png` behaving exactly as before. For the rare
670
+ path that itself contains `=`, `--upload '<selector>::<file>'` states the split
671
+ explicitly. `--fill` and `--select` are unchanged: their values often contain
672
+ `=`, so they still split at the first one.
673
+ - **`somewhere typecheck` no longer fails on a project you have not installed
674
+ yet.** A freshly created or freshly pulled project declares its type packages
675
+ in `package.json` but has nothing in place until dependencies are installed,
676
+ and the first check reported that absence as a dozen type errors in your own
677
+ code. The check now puts the type packages your project declares in place
678
+ before it runs, so the first answer is a real one. Only packages you already
679
+ declare are resolved, an import you never declared still fails with its real
680
+ error, and a project that is already installed does no extra work. If the
681
+ packages cannot be fetched, the check still runs and reports what it finds.
682
+
683
+ ### Added
684
+
685
+ - **Scheduled triggers can be created in your own time zone.**
686
+ `somewhere cron create --timezone <IANA>` — for example
687
+ `--timezone America/Los_Angeles` — reads the cron expression in that zone and
688
+ handles daylight saving for you, so `0 9 * * *` means 9am locally all year.
689
+ The platform has accepted this since scheduling shipped; only the CLI was
690
+ missing the flag and its help text called every expression UTC. Omit the flag
691
+ and nothing changes: schedules are still read in UTC.
692
+ - **Every command says it has started.** The CLI now prints
693
+ `starting somewhere CLI <version>` as its first line in an interactive
694
+ terminal, so a first run shows something immediately and names the version you
695
+ actually got. The line goes to the error stream and only ever appears on a
696
+ terminal, so piped output, `--json`, and scripts are byte-for-byte unchanged.
697
+ Note that a first `npx @somewhere-tech/cli …` on a cold cache can still sit
698
+ quiet for up to a minute BEFORE this line: npm downloads and installs the
699
+ package before running any of its code, and that download is silent by npm's
700
+ design — no code we ship can speak during it. Install once with
701
+ `npm i -g @somewhere-tech/cli` to skip that wait on every later run.
702
+
703
+ ## 0.31.11
704
+
705
+ ### Added
706
+
707
+ - **Test passwordless sign-in without sending mail to a real inbox.**
708
+ `somewhere email test-inbox` reads the stored auth messages for an address
709
+ owned by the project and shows the extracted magic-link URL alongside the
710
+ rendered message.
711
+ - **Browser checks can attach files and name screenshots.** `somewhere browser`
712
+ accepts repeatable `--upload <selector=file>` actions, while
713
+ `--screenshot <name>` saves a capture under the requested label. The same
714
+ actions work in shared browser and verification flow files.
715
+ - **Authenticated pages can be verified at desktop and phone sizes.**
716
+ `somewhere verify --session` seeds an existing app session, and repeatable
717
+ `--cookie <name=value>` options carry existing cookies into every viewport.
718
+ - **The catalog now explains how to call each tool.**
719
+ `somewhere catalog <tool>` prints the tool description and complete input
720
+ schema, including nested constraints and fields such as cron timezones.
721
+
722
+ ## 0.31.10
723
+
724
+ ### Fixed
725
+
726
+ - **A preview that cannot finish verifying now says so, and retries itself.**
727
+ When the platform could not yet confirm the uploaded preview build, the CLI
728
+ reported a generic internal error and dropped the session. That case is now a
729
+ named, retryable condition: `somewhere preview` replays the same save once on
730
+ its own, and only reports a failure — with a reference you can quote — if the
731
+ retry also does not complete. Nothing is created or changed on the failed
732
+ attempt, and whatever is live stays live.
733
+ - **`somewhere preview --json` always answers with JSON.** A refusal — the plan
734
+ does not include previews, or the project has never been published and
735
+ `--publish-first` was not passed — used to print human prose on a `--json`
736
+ run. It now returns the same typed JSON error shape as every other refusal,
737
+ so a script or agent can read the reason instead of parsing sentences.
738
+
739
+ ## 0.31.9
740
+
741
+ ### Added
742
+
743
+ - **Cron and email are first-class CLI command groups.** `somewhere cron`
744
+ exposes list, create, update, delete, and run-once commands, while
745
+ `somewhere email` exposes transactional send. `somewhere cron run` accepts a
746
+ cron ID or a task name and runs it once without changing its schedule. Each
747
+ group names its commands and includes a copyable example in `--help`. During
748
+ the platform rollout, run-once exits with a typed
749
+ `CRON_RUN_NOT_AVAILABLE` message on older platform versions.
750
+ - **Stale CLI installs get one concise update line.** The existing daily,
751
+ fail-open version check now has explicit newer/current and cache-throttling
752
+ coverage, and its notice fits on one line.
753
+
754
+ ### Fixed
755
+
756
+ - **Every registered command owns its help output.** Command help can no
757
+ longer silently look like the generic top-level banner, and the complete
758
+ non-pass-through command surface is fixture-covered.
759
+ - **Every bundled init template writes a valid `.gitignore`.** The current
760
+ green starter already emitted real line breaks; the older exported template
761
+ no longer carries literal `\\n` text.
762
+ - **A pending package verdict is described as pending.** npm installation
763
+ continues without waiting for a result, without presenting that non-blocking
764
+ fallback as a failed install.
765
+
766
+ ## 0.31.8
767
+
768
+ ### Added
769
+
770
+ - **`somewhere verify` runs a complete browser acceptance flow in one command.**
771
+ Give it a live or local URL and an optional flow file to get one report with
772
+ every named step, page/console/network health, and desktop and mobile
773
+ screenshots. `somewhere deploy --verify <flow.json>` can run the same check
774
+ immediately after publishing.
775
+ During the platform #24 rollout, hosted action flows on an older serving
776
+ release fail honestly with a missing-screenshot or unfiltered expected-
777
+ refusal health result; they do not crash or report a false pass. Re-run the
778
+ same command after the rollout reaches the project.
779
+ - **Browser action files now have one canonical shape everywhere.**
780
+ `somewhere browser --actions` and `somewhere verify --flow` use the same
781
+ concise action array, such as `{"fill":"#email","value":"a@b.co"}` followed
782
+ by `{"click":"#save"}`.
783
+
784
+ ### Fixed
785
+
786
+ - **Preview handoffs are directly runnable from any directory.** Every promote
787
+ command printed by `somewhere preview` carries its project context, and the
788
+ non-interactive form includes `--yes`. The watcher now notices a promotion
789
+ promptly and exits without consuming or silently dropping the next save.
790
+ - **A first preview no longer looks frozen while it publishes production.**
791
+ `somewhere preview --publish-first` reports each bootstrap phase, elapsed
792
+ heartbeats, retries, and the platform's typed failure state.
793
+ - **Preview access refusals are safe to automate.** Wrong-account lookups return
794
+ a stable `PROJECT_NOT_FOUND` result in human and `--json` output without
795
+ listing unrelated projects or attempting a deploy.
796
+ - **`somewhere status` keeps production visible on Free plans.** It reports the
797
+ live production version and release even when private preview status is
798
+ unavailable on the account's plan.
799
+
800
+ ## 0.31.7
801
+
802
+ ### Added
803
+
804
+ - **`somewhere init` now starts with a working full-stack TypeScript app.** In
805
+ an empty directory, the default starter includes a typed React page, a typed
806
+ server function, and a database schema, with exact dependency versions
807
+ installed before init reports success. Use `--bare` for the previous
808
+ metadata-only setup; existing source directories are still left untouched.
809
+
810
+ ### Fixed
811
+
812
+ - **Project deletion now follows the platform's two-step confirmation flow.**
813
+ The CLI recognizes the successful `needs_confirmation` response as well as
814
+ the older error-shaped response. At a terminal it asks for the project name;
815
+ without a terminal it prints the exact `--confirm-code` command to run next.
816
+ Unrelated server errors continue to surface unchanged.
817
+ - **A slow package verdict no longer turns into a failed install.** Verdict
818
+ lookups have a more realistic cold-start allowance. If that allowance is
819
+ exhausted, `somewhere npm install` says `verdict pending` and continues with
820
+ npm under the default fail-open policy.
821
+
822
+ ## 0.31.6
823
+
824
+ ### Added
825
+
826
+ - **Device login now shows what is asking for access.** The approval page can
827
+ show the machine name, CLI and runtime versions, operating system, and the
828
+ requested project scope before access is allowed or denied. After approval,
829
+ `somewhere login` prints that scope, `somewhere whoami` names the current
830
+ session and its access, and `somewhere logout` revokes the session on the
831
+ server before removing the local credential.
832
+ - **`somewhere browser` can drive routine flows without custom JavaScript.**
833
+ Repeatable `--fill`, `--select`, `--click`, and `--expect` flags run in command
834
+ order, while `--actions <file.json>` accepts the same shared action sequence
835
+ as the platform browser. `--expect-request <path:status>` treats an intended
836
+ response such as an authorization refusal as expected, and `--visible-only`
837
+ removes hidden controls from the page outline. Localhost session help now
838
+ says plainly that named sessions are unavailable there and points to a fresh
839
+ local browser run.
840
+ - **`somewhere db apply-schema` prepares a managed database before the first
841
+ deploy.** It reads `db/schema.ts` by default, applies the declaration to the
842
+ production database without publishing the app, reports an already-current
843
+ schema as a no-op, and preserves the planner's exact safety message when a
844
+ removal needs an explicit `removed()` or `removedTable()` marker.
845
+
846
+ ### Fixed
847
+
848
+ - **Local browser checks no longer stall when the CLI uses an isolated home on
849
+ macOS.** The headless browser still runs with a new scratch profile and no
850
+ extensions, while the CLI's credentials remain inside the isolated home.
851
+
852
+ ## 0.31.5
853
+
854
+ ### Fixed
855
+
856
+ - **`somewhere dev` now moves past a busy default port automatically.** If
857
+ 8787 is already in use, the local loop selects the next free port and prints
858
+ the choice before startup. Passing `--port` remains strict: a busy requested
859
+ port is an error, and the CLI names the process using it when the operating
860
+ system can identify one.
861
+ - **Local database requests now explain where their time went.** Each
862
+ database-backed request in the local loop prints the complete database
863
+ round-trip beside the request total and includes the database execution time
864
+ reported by the platform when it is available. Working responses without
865
+ that field keep working and say that the timing was not reported.
866
+
867
+ ## 0.31.4
868
+
869
+ ### Fixed
870
+
871
+ - **Status now shows which tested preview reached production.** When production
872
+ came from a promotion, `somewhere status` names the exact candidate and shows
873
+ a short content hash, so you can match the live app to the preview you tested.
874
+ - **Promotion now uses the platform's own data notice and exact function count.**
875
+ The notice about preview rows is printed exactly as the platform sends it,
876
+ and the release summary says how many functions reached production when that
877
+ count is available. Older platform responses keep working quietly.
878
+
879
+ ## 0.31.3
880
+
881
+ ### Added
882
+
883
+ - **`somewhere project allowed-origins list` and `… set` now exist.** Allowing
884
+ another web address to call your project from a browser was only possible
885
+ through the generic tool-call escape hatch with a raw project id — so the
886
+ command guidance told you to run was not a command the CLI had. It is now a
887
+ first-class command with the obvious spelling, it shows up in
888
+ `somewhere project --help`, and it takes `--project <ref>` like everything
889
+ else. `set` replaces the whole list (`--clear` empties it) and refuses an
890
+ address the allowlist could never match — a path, a query, a wildcard, a
891
+ trailing slash — before sending it, naming what is wrong. Your project's own
892
+ address and any verified custom domain are always trusted and never need
893
+ listing.
894
+
895
+ ### Fixed
896
+
897
+ - **The promote command the CLI prints can now be run in the shell that printed
898
+ it.** `somewhere preview` and `somewhere status` printed
899
+ `somewhere promote <session> <preview>`, and `somewhere promote` then refused
900
+ that exact command whenever there was no terminal to confirm with — so in a
901
+ script, an agent, or a piped terminal the CLI handed you a command it would
902
+ reject. The printed command now matches the shell reading it: without a
903
+ terminal you get the runnable form, with `--yes` on it; at a keyboard you get
904
+ the ordinary confirming form first and the unattended one named beneath it.
905
+ - **Promotion now says what happened to your data.** Promoting moved your app
906
+ and said nothing about the rows you created while previewing, which stay in
907
+ the preview database — the isolation is the point, but discovering it by
908
+ opening an empty production page and repeating your whole acceptance pass is
909
+ not. A successful promote now states that only the app was promoted, that
910
+ production is serving the data it already had, and that production is worth
911
+ checking and seeding before you call it shipped.
912
+ - **One project now reports one size of itself.** The same directory was
913
+ described three different ways: `somewhere deploy` counted static files and
914
+ functions separately, `somewhere preview` reported a single "3 files" with the
915
+ function hidden inside it, and `somewhere promote` said "3 files + functions",
916
+ replacing the count with the word. Worse, deploy's number did not match what
917
+ the project itself listed. All three now print the same shape — `3 static
918
+ files + 1 function` — off the same counting rule, and promote reports what
919
+ production actually holds rather than a tally that disagreed with it.
920
+ - **`--project` works on every command that names a project.** `logs`,
921
+ `errors`, `status`, `open` and `rollback` accepted only a positional project
922
+ and answered `unknown option '--project'`, while a dozen other commands took
923
+ the flag — so the syntax you learned on one command failed on the next. All of
924
+ them now take `--project <ref>`, the positional keeps working everywhere, and
925
+ naming two different projects in one command is refused rather than guessed.
926
+
927
+ ## 0.31.2
928
+
929
+ ### Fixed
930
+
931
+ - **`somewhere dev` now runs the same entry files `somewhere deploy`
932
+ publishes.** A project whose `index.html` points at
933
+ `<script type="module" src="/src/main.js">` deploys and serves perfectly —
934
+ the platform serves plain JavaScript modules exactly as you wrote them,
935
+ rather than compiling them — but the local loop refused to start on it at
936
+ all, insisting on `.tsx`. It now follows the same rule deploy follows: your
937
+ `index.html` names the entry, `.tsx` / `.ts` / `.jsx` / `.mts` / `.cts` are
938
+ compiled, `.js` / `.mjs` / `.cjs` are served as written, and a page with no
939
+ module script at all (a browser-Babel page, a static site) simply runs. The
940
+ loop stops only when `index.html` names a file that is not in the directory
941
+ — and then it says which file, and which forms it accepts.
942
+ - **The local runtime no longer suggests editing a package file outside your
943
+ project.** Running a function could print advice to add `"type": "module"` to
944
+ a `package.json` in a parent directory — on some machines, the one in your
945
+ home folder. The cause was a module-format lookup with no upper bound, which
946
+ walked straight past the project. The runtime now determines the format from
947
+ your project's own package file and your own source, stopping at the project
948
+ root, so no advice can ever name a file outside it. CommonJS and ES module
949
+ functions both keep working exactly as they do when deployed.
950
+ - **`somewhere browser --eval` prints the evaluated value in normal output.**
951
+ The value came back correctly with `--json` but was dropped from the default
952
+ text report, so the command you use to check a live page did not show what it
953
+ found. Text output now prints the value under the step — strings as
954
+ themselves, objects readably indented — and an expression that returned
955
+ nothing says so instead of leaving a blank line.
956
+ - **`somewhere deploy --temporary` means temporary, whether or not you are
957
+ signed in.** Being signed in used to override the flag and switch the deploy
958
+ to your account, which then failed in a directory with no linked project. The
959
+ flag is the request: it always deploys to a temporary workspace, never needs a
960
+ linked project, and prints the live URL, the claim link, and when the
961
+ workspace expires. Your account sign-in survives it untouched, the directory's
962
+ own link is left alone, and a second `--temporary` deploy in the same window
963
+ redeploys the same temporary app instead of creating another. A deploy without
964
+ the flag is unchanged.
965
+
966
+ ### Changed
967
+
968
+ - `somewhere init` closes by naming what to run next on the platform —
969
+ `somewhere dev` to run your app here, `somewhere deploy` to publish it — and
970
+ notes that any coding agent can drive this CLI, in place of the previous
971
+ line naming one specific tool.
972
+
973
+ ## 0.31.1
974
+
975
+ ### Fixed
976
+
977
+ - `tsk_5504e045` — **`somewhere preview` can no longer publish to production on
978
+ its own.** A preview builds on your app's live version, so a project that has
979
+ never been published needs one published first — and that publish is a real
980
+ production release, the one thing this command can do to your live site. It
981
+ was happening in two ways it should not have. On a project that was already
982
+ live, if the CLI could not read which version was live it treated the silence
983
+ as "this project has never been published" and went ahead and published your
984
+ working directory over the running app. And on a project that genuinely had
985
+ never been published, it published without asking at all.
986
+
987
+ Now: a version the CLI cannot read is unknown, and unknown never publishes —
988
+ the command stops, says what it could not read, and leaves your live site
989
+ exactly as it was. A publish happens only when the platform positively
990
+ confirms nothing is live AND you say so, either by answering the prompt or by
991
+ running `somewhere preview --publish-first`. A run that cannot be asked — a
992
+ script, an agent, a piped shell — is refused and told about the flag. Preview
993
+ on a project that is already live never publishes anything, as before.
994
+ - `tsk_5504e045` — **the plan refusal stopped claiming your project is
995
+ unpublished.** On a Free or Builder account, `somewhere preview` on a live
996
+ project refused with "Nothing was created — this project has not been
997
+ published", which was simply untrue and sent people to re-deploy an app that
998
+ was already running. The refusal now says only what it did: nothing was
999
+ created or changed, and whatever is live stays live.
1000
+
1001
+ ### Changed
1002
+
1003
+ - The dev compiler and function runtime are re-vendored from the platform at
1004
+ `3237dc1e`, picking up the faster dependency install — a project with a
1005
+ lockfile now installs the way the platform installs it, without development
1006
+ dependencies. `somewhere dev` compiles your app with the platform's own
1007
+ compiler, so this keeps what you see on localhost identical to what deploy
1008
+ produces.
1009
+
1010
+ ## 0.31.0
1011
+
1012
+ ### Added
1013
+
1014
+ - `tsk_5cfcfe00` — **`somewhere preview` is a command.** There are two loops and
1015
+ they are now named after where the app runs: `somewhere dev` runs your app on
1016
+ your machine, `somewhere preview` runs it on the platform. Every save goes to
1017
+ a private URL reachable only by you; production keeps serving what you last
1018
+ promoted until you run `somewhere promote`. Reach for it when you want the
1019
+ real hosted app in front of you, or when your agent cannot serve on
1020
+ localhost. `dev --cloud` still starts it and prints one line naming the new
1021
+ command.
1022
+
1023
+ ### Fixed
1024
+
1025
+ - `tsk_33023348` — **`somewhere promote` never reports an outcome it does not
1026
+ know.** It used to print "Promote failed / Unknown error" for a promote that
1027
+ had already shipped, and the obvious retry then said "Production was not
1028
+ changed" about production that the first command had changed. Promote is the
1029
+ one irreversible step in the loop, so it now separates a refusal the platform
1030
+ AUTHORED (reported as written) from a response the CLI could not READ. In the
1031
+ second case it reads what production is serving before and after and answers
1032
+ from whether that moved — and a refusal claiming production was unchanged is
1033
+ checked against the same evidence before it is allowed to stand. When neither
1034
+ side can be read it says the status is unknown and points at your production
1035
+ URL rather than guessing.
1036
+ - `tsk_74375b3c` — **a promote ends the preview cleanly.** Promoting closed the
1037
+ preview, but the loop kept watching, and your next save came back with a
1038
+ refusal written for an API client — then failed the same way on every save
1039
+ after that. The loop now recognises the end of a preview and stops on it, in
1040
+ two lines: what happened, and the one command that starts the next preview.
1041
+ - `tsk_5cfcfe00` — the preview copy no longer claims your preview has
1042
+ production's data. A preview runs against a separate copy of your schema with
1043
+ none of your production rows, which is exactly what makes it safe to try
1044
+ things in.
1045
+ - `tsk_d63b3b6a` — **an unresolvable import is reported, not a crash.**
1046
+ `somewhere dev` died on any import that could not be resolved — a typo'd
1047
+ package, one you had not installed yet — with an internal error naming the
1048
+ CLI's own bundler and nothing about your code, and every rebuild after that
1049
+ failed too. It only happened when the command's error output went to a file
1050
+ rather than a terminal, which is the normal case under an agent, a CI job, or
1051
+ a session recorder. Now an unresolved import reads like a syntax error:
1052
+ file:line:column, the specifier, and one sentence naming the fix — add it to
1053
+ your package.json and install it, or, for a module the platform provides,
1054
+ that it comes from the platform and should not be installed at all. The
1055
+ server survives, the last working page stays up, and a save that fixes it
1056
+ serves again.
1057
+ - `tsk_14c5408c` — a burst of saves stays one preview update. Saves inside the
1058
+ debounce window accumulate into a single update, and a save that lands while
1059
+ one is in flight re-arms instead of starting a second, so two previews are
1060
+ never building at once.
1061
+
1062
+ ### Changed
1063
+
1064
+ - The vendored platform runtime and compiler are re-synced to the current
1065
+ platform build. Content is unchanged from 0.30.2 apart from the provenance
1066
+ stamp — the compiler files hash identically — so this release changes no
1067
+ build behaviour.
1068
+
1069
+ ## 0.30.2
1070
+
1071
+ ### Fixed
1072
+
1073
+ - `tsk_a8cb3d23`, `tsk_f79d71ce` — `somewhere dev` and `somewhere deploy` now
1074
+ derive dependency versions from the SAME code, so a build on your machine and
1075
+ a build on deploy resolve the same libraries. The platform's compiler reads
1076
+ your lockfile as of today: a version your lockfile pins is the version that
1077
+ gets installed, provided it satisfies the range your `package.json` declares.
1078
+ This CLI carries that compiler, so `somewhere dev` follows the identical rule
1079
+ — it is one implementation, vendored, not two that agree by coincidence. A
1080
+ project with NO lockfile is unchanged: the declared range still floor-pins.
1081
+
1082
+ ### Known difference
1083
+
1084
+ - The JavaScript bundle `somewhere dev` builds and the one `somewhere deploy`
1085
+ builds are not byte-identical, and the reason is now only bookkeeping: build
1086
+ comments and source-map entries record where each module was read from, which
1087
+ is your machine locally and the build image on deploy. It has no effect on
1088
+ what your app does.
1089
+ - The dependencies your project DECLARES resolve the same on both sides. Their
1090
+ own transitive dependencies are still resolved by npm from the parents'
1091
+ ranges, so those can differ. Pin one exactly in `package.json` if it matters
1092
+ to you.
1093
+
1094
+ ## 0.30.1
1095
+
1096
+ ### Added
1097
+
1098
+ - `tsk_0e9e13b8` — `somewhere signup` exists. Someone who has never used the
1099
+ platform ran `somewhere login`, and the CLI's answer assumed they already had
1100
+ an account. `signup` prints the page that creates one, and `login` names it
1101
+ too, so the front door is a door.
1102
+ - `tsk_c166924f` — `somewhere deploy` publishes your **app**, not the folder it
1103
+ was built in. Notes, task lists, scratch files and agent instructions in your
1104
+ project root stay on your machine: the deploy prints `Not published (N): …`
1105
+ naming exactly what it held back, so the decision is visible rather than
1106
+ silent. Publish one on purpose with `somewhere deploy --include <file>`, or
1107
+ keep it permanently with a `!<file>` line in `.somewhereignore`.
1108
+
1109
+ ### Fixed
1110
+
1111
+ - `tsk_926fbf8e` — `somewhere docs <topic>` answers from the public corpus with
1112
+ no login. Reading the documentation used to require an account, which is the
1113
+ wrong order: you read the docs to decide whether to make one.
1114
+ - `tsk_f250e561` — `somewhere status` exits 0 when the platform answers a plan
1115
+ question. A feature your plan does not include is an ANSWER, not a failure;
1116
+ exiting non-zero made every scripted `status` on a Free account look like a
1117
+ broken command.
1118
+ - `tsk_a605ff7b`, `tsk_10be456b` — `somewhere browser` against a local URL now
1119
+ fails inside a bound instead of hanging. Every wait on the local path has a
1120
+ deadline, a port with nothing listening is reported as such with the remedy
1121
+ named, and the browser's own favicon request — which the page never made — no
1122
+ longer counts as your app returning a 404.
1123
+ - `tsk_9c5ed7f8` — a failed `somewhere deploy` now says something you can act
1124
+ on. When the platform answers `retry: true` — its own statement that the
1125
+ request changed nothing and the same one is safe to send again — the CLI
1126
+ retries once instead of stopping (it parsed that field and never read it).
1127
+ An error body it cannot classify prints the status and the response instead
1128
+ of the bare words "Unknown error". And every deploy failure now prints the
1129
+ request id from the response, so a failure you can see is a failure we can
1130
+ find.
1131
+ - `tsk_eef0a0ef` — `somewhere dev` prints your app's output, not the platform's
1132
+ telemetry. Database calls were emitting raw internal metrics JSON and a
1133
+ repeated "deferred flush failed: HTTP 403" from a background channel you did
1134
+ not ask for and cannot fix. Both are gone by default; set
1135
+ `SOMEWHERE_DEV_TELEMETRY=1` to see them.
1136
+ - `tsk_a8cb3d23` — the local loop resolves a dependency at the version the build
1137
+ image serves, for every package the image carries. This already held for
1138
+ React; it now holds for the whole baked set (router, query, state, forms,
1139
+ validation, http, dates, utils, styling, animation, charts, icons), so a
1140
+ declared `^3.23.0` no longer compiles against 3.23.0 on your machine and a
1141
+ newer one on deploy. A pin is taken only when the image's version satisfies
1142
+ the range you declared — a project on a major the image does not carry is
1143
+ untouched.
1144
+
1145
+ ### Known difference
1146
+
1147
+ - The JavaScript bundle `somewhere dev` builds and the one `somewhere deploy`
1148
+ builds are built by the same compiler, from the same source, with the same
1149
+ toolchain. They are not byte-identical, and there are two reasons rather than
1150
+ one. Build comments and source-map entries record where each module was read
1151
+ from — your machine locally, the build image on deploy — which has no effect
1152
+ on what your app does. Separately, the two builds can still resolve DIFFERENT
1153
+ VERSIONS of an app dependency: `somewhere dev` uses the tree you installed,
1154
+ while `somewhere deploy` resolves the range your `package.json` declares and
1155
+ does not yet read your lockfile. If that matters to a library you depend on,
1156
+ pin it exactly in `package.json` and both sides agree.
1157
+
1158
+ **Superseded by 0.30.2**, which closes the version difference. The paragraph
1159
+ above describes 0.30.1 only, and is kept because that version is published.
1160
+
1161
+ ## 0.30.0
1162
+
1163
+ ### Added
1164
+
1165
+ - `tsk_9ec50c84` — `somewhere browser` now drives a **localhost** target. The
1166
+ app `somewhere dev` is serving used to be the one address this CLI's own
1167
+ browser would not visit, so every visual and DOM check had to wait for a
1168
+ production deploy. A loopback URL is now driven by the browser already
1169
+ installed on your machine — no new dependency and nothing to download. Each
1170
+ run gets an empty throwaway profile, so it never reads or writes your real
1171
+ browser profile. If there is no browser at all, the CLI says so and names the
1172
+ environment variable to point at one. Flags only the hosted browser can honour
1173
+ (`--store`, `--session`, `--extract`, non-`dom` `--include`) are refused by
1174
+ name rather than silently dropped from a report that still looks complete.
1175
+ - `tsk_70fd0f63` — `somewhere errors` gained a `kind` column and an
1176
+ `--exceptions` flag, so you can see only what actually broke.
1177
+
1178
+ ### Fixed
1179
+
1180
+ - `tsk_bdd72f02` — `somewhere browser --snapshot` now asks for the map it
1181
+ prints. `--snapshot` renders the interactive-element outline, but it never
1182
+ requested that section, so it printed whatever the response happened to carry
1183
+ — usually nothing. `browser --wait button --snapshot` would match a button and
1184
+ then report "dom: 0 interactive elements" on a page with three buttons and two
1185
+ inputs. It now adds `dom` to the requested sections, merging with an explicit
1186
+ `--include` rather than replacing it. The local outline comes from the
1187
+ platform's own probe, so it is a preview of the hosted answer rather than a
1188
+ second opinion.
1189
+ - `tsk_ea4274ca` — `somewhere errors` no longer calls a working auth gate an
1190
+ exception. If you probed your own endpoint signed out — deliberately, to prove
1191
+ the gate holds — your 401 was listed as the only exception in 24 hours. Rows
1192
+ now show their kind: **refused** for a 4xx your handler returned on purpose,
1193
+ **exception** for an uncaught throw or a 5xx, with the summary line splitting
1194
+ the counts. Nothing is hidden by default.
1195
+ - `tsk_ea4274ca` — a stored screenshot printed as a storage path, which reads as
1196
+ a URL and is not one, so the one value the command handed back for "here is
1197
+ your screenshot" could not be used to see it. The report now leads with the
1198
+ link that opens it and keeps the stored path on its own line, because that is
1199
+ the handle for reading or replacing the file later.
1200
+ - `tsk_53badecf` — `somewhere dev --check` and `somewhere deploy` no longer
1201
+ report the `somewhere/db` import from our own managed-schema documentation as
1202
+ a missing npm package whose remedy is installing an unrelated package. The
1203
+ specifiers the platform provides are now treated as provided. A genuinely
1204
+ missing package still warns, and still names every file that imports it.
1205
+ - `tsk_a21bc829` — `somewhere dev` no longer asks you for a variable the
1206
+ platform writes. It warned that `APP_URL` had no local value on projects whose
1207
+ source never mentions `APP_URL` — it never would, because deploy writes that
1208
+ key. The local loop now fills it with the local origin, or with the project's
1209
+ public URL when nothing is being served locally. Keys you genuinely own are
1210
+ still named, which is the point of that warning.
1211
+ - `tsk_6a2a09bc` / `tsk_320a0bc6` — the local loop now declares tables the way
1212
+ deploy declares them. It kept only the owner column and dropped the intent, so
1213
+ `sw.db.from` on a `shared()` table answered "this table has no declared
1214
+ intent" locally while working fine on the same deployed project. Intents,
1215
+ owner scopes and the owner-identity mode now cross over exactly as the deploy
1216
+ bundle bakes them.
1217
+ - `tsk_4df056ea` — when your plan does not include reaching the project database
1218
+ from the local loop, `somewhere dev` now says so **once, at startup**, before
1219
+ you write a line of code. It previously started a clean serving loop and let
1220
+ you discover at the first request that every `sw.db` call was refused — with a
1221
+ message that called it a connection problem and suggested redeploying, which
1222
+ could never help. The loop still runs: the frontend compiles and serves, hot
1223
+ reload works, and every function that does not touch the database still runs.
1224
+ Deploying is unaffected on every plan, and the deployed app reads and writes
1225
+ its database normally. `somewhere status` reports the same answer, including a
1226
+ `local_dev_db` object in `--json`.
1227
+ - `tsk_a21bc829` — `--check`'s help now says what the documentation says: it
1228
+ needs a real `npm install`, because the typechecker reads package types out of
1229
+ `node_modules` and the CLI's dependency cache does not stand in for that.
1230
+
1231
+ ### Changed
1232
+
1233
+ - The vendored platform runtime and compiler are re-synced to the current
1234
+ platform. For the local loop this brings `owner()` scoping on visitor-mode
1235
+ projects, exact 64-bit integer fidelity on structured writes and batches, and
1236
+ the plan-derived local-database answer above.
1237
+
1238
+
1239
+ ## 0.29.1
1240
+
1241
+ ### Changed
1242
+
1243
+ - `tsk_0100d8e5` — the local loop now runs the CURRENT platform runtime. The
1244
+ copy the CLI carried had frozen several months behind, so `somewhere dev` was
1245
+ quietly running your `api/` functions against an older `sw.*` than your
1246
+ deployed ones. Re-synced deliberately, with a hash guard so it cannot drift
1247
+ silently again. What this changes for you is below.
1248
+ - `tsk_0100d8e5` — the structured database API works locally: `sw.db.from`,
1249
+ `.insert`, `.update`, `.delete`, `.count`. Tables need a scope declaration for
1250
+ the platform to scope them to the signed-in user; an undeclared table returns
1251
+ a clear error naming the table.
1252
+ - `tsk_0100d8e5` — also newly available in the local loop: sign-in with GitHub
1253
+ and Discord, roles and moderation (`sw.auth.requireRole`,
1254
+ `sw.auth.moderation.*`), plans and entitlements (`sw.billing`), scheduling
1255
+ (`sw.calendar`), contacts, and durable agents (`sw.agent`). Email gains
1256
+ delivery `status` and `history`, payments gains `quote` and a per-user billing
1257
+ portal, and search gains `add`.
1258
+ - `tsk_0312cf17` — `somewhere dev` now builds with the same React version the
1259
+ deploy image builds with. It previously installed the lowest version your
1260
+ range allowed (`^19.2.0` became 19.2.0) while deploy used 19.2.7, so the loop
1261
+ and production could differ by a patch release you would only discover in
1262
+ production.
1263
+ - `tsk_106f7ab1` — one vocabulary for previews across the CLI. Commands and
1264
+ messages say **preview** and **production**; `somewhere promote` names its
1265
+ arguments `preview_session_id` and `preview_id`. `--draft` still works as an
1266
+ alias of `--preview`, so nothing you already type breaks.
1267
+
1268
+ ### Fixed
1269
+
1270
+ - `tsk_8a9d2d1a` — `somewhere deploy` no longer tells you "Next.js apps don't
1271
+ run here" when your app is not a Next.js app. Any project with a `src/pages/`
1272
+ folder tripped it — including the app `somewhere init` creates, so this was
1273
+ often the first thing a new project printed. A Next.js app is now identified
1274
+ the way the platform identifies one: a `next` dependency or a `next.config`
1275
+ file.
1276
+ - `tsk_cf48f4ab` — `somewhere dev --cloud` on a plan without private previews
1277
+ now refuses before doing anything, instead of publishing a first production
1278
+ version and only then telling you the command is unavailable. Nothing is
1279
+ created.
1280
+
1281
+ ### Known difference
1282
+
1283
+ - The JavaScript bundle `somewhere dev` builds and the one `somewhere deploy`
1284
+ builds are the same code, built by the same compiler — but they are not
1285
+ byte-identical. Build comments and source-map entries record where each module
1286
+ was read from, which is your machine locally and the build image on deploy.
1287
+ It has no effect on what your app does.
1288
+
1289
+ **Correction (0.30.1):** this entry also said the two builds use the same
1290
+ dependency versions. That was not true — they can resolve different versions
1291
+ of a dependency whose range you left open. See the Known difference under
1292
+ 0.30.1 for what actually holds and what to do about it.
1293
+
1294
+ ## 0.29.0
1295
+
1296
+ ### Added
1297
+
1298
+ - `tsk_95377909` — `somewhere dev` is now a LOCAL loop. It serves your app on
1299
+ localhost and compiles it with the platform's own compiler — the same
1300
+ `compile-core` the deploy pipeline runs, vendored into the CLI at the exact
1301
+ esbuild version the compile container pins, with a hash manifest and a test
1302
+ that fails if anyone edits it. No install step, no build step, no deploy:
1303
+ a fresh `somewhere init` scaffold starts in a couple of seconds and a saved
1304
+ TSX or CSS edit is on the page in a few hundred milliseconds. Compile errors
1305
+ print file:line:column in the terminal and show on the page with the last
1306
+ working page still underneath; `api/` functions run in local Node with
1307
+ `sw.db` / `sw.fs` / `sw.ai` / `sw.auth` calling your real project.
1308
+ There is no dev version of your app — same app, same data, same build.
1309
+ Functions execute in your machine's Node during the loop rather than on the
1310
+ platform's runtime, so a deploy is still what proves a function in production.
1311
+ - `tsk_737ff0d2` — the local server now answers on both `127.0.0.1` and `::1`,
1312
+ so the `http://localhost:...` URL it prints opens in a browser that resolves
1313
+ `localhost` to IPv6 first. Non-loopback addresses are still refused.
1314
+ - `tsk_3269026d` — `api/` functions resolve npm packages through the same
1315
+ search path the compiler used, so a fresh scaffold's routes work with no
1316
+ `npm install`. The project's own `node_modules` always wins.
1317
+ - `tsk_8796c588` — the pre-start typecheck is skipped, with one line saying
1318
+ why, when the project has no `node_modules` — instead of reporting dozens of
1319
+ unresolvable-type errors about code you did not write.
1320
+
1321
+ ### Changed
1322
+
1323
+ - `tsk_95377909` — the cloud preview watcher, which used to be bare
1324
+ `somewhere dev`, is now `somewhere dev --cloud`. `--local` is still accepted
1325
+ and does what bare `somewhere dev` does. `somewhere dev <cmd...>` still runs
1326
+ your own command with the project's environment variables injected.
1327
+
1328
+ ### Fixed
1329
+
1330
+ - `tsk_8a3f6540` — `somewhere dev --cloud` on a project that has never been
1331
+ published now publishes the first version once, announced in plain words,
1332
+ instead of failing the initial sync. A private preview is a candidate built
1333
+ against your live version, so there was previously nothing for the first one
1334
+ to build on.
1335
+ - `tsk_e929774b` — the `--json` contract test no longer deploys to the live
1336
+ platform on every `npm test`. It ran logged out with no API URL, so
1337
+ `deploy`, `deploy-check` and `browser` reached production and minted a real
1338
+ temporary account and a real project per run — while asserting nothing about
1339
+ what those deploys did. The shape contract now runs against the local stub,
1340
+ and the one test that does deploy for real
1341
+ (`test/deploy-outcome-live.test.mjs`) uses an explicitly created throwaway,
1342
+ asserts the deploy outcome and what the live URL serves, purges the
1343
+ throwaway and confirms it is gone, and skips with a named reason when there
1344
+ is no signed-in credential.
1345
+
1346
+ ## 0.24.0
1347
+
1348
+ ### Security
1349
+
1350
+ - `tsk_f7ba3b57` — credential-at-rest hardening. Config is now written atomically at `0600` (a pre-existing world-readable `~/.somewhere/config.json` is tightened on every write, not just on create). `logout` now revokes the session server-side (best-effort) in addition to removing the local token.
1351
+
1352
+ ### Breaking
1353
+
1354
+ - `tsk_f7ba3b57` — `auth set <token>` no longer accepts the token as a positional argument (it was visible in the process table to other local users). Provide the token via the `SOMEWHERE_TOKEN` environment variable or stdin: `printf %s "$TOKEN" | somewhere auth set`.
1355
+
1356
+ ## 0.23.1
1357
+
1358
+ ### Fixed
1359
+
1360
+ - `tsk_e67bcc16` — made JSON mode a CLI-wide success/error contract, added JSON output to `docs`, `api`, and `init`, and covered every registered `--json` command with a parseability test.
1361
+ - `tsk_c6035afa` — duplicate of `tsk_06c1f77a`; rollback failures now remain structured JSON in JSON mode.
1362
+ - `tsk_41ee402b` — replaced the stale-era rollback snapshot wording with current recovery guidance; restoring the previous promoted release still requires the platform follow-up noted below.
1363
+ - `tsk_971775dc` — `logs --follow` now keeps polling after an empty initial query and suppresses overlapping records.
1364
+ - `tsk_8dc77749` — deploy requests now have an abortable long-call deadline, progress heartbeat, and one bounded retry instead of waiting without a terminal result.
1365
+ - `tsk_05a3cf11` — fixed the no-`node_modules` typecheck fallback to run `npx -y -p typescript tsc`.
1366
+ - `tsk_451eb155` — added non-interactive `init --link --project <ref>` with exact ID/name/slug/subdomain matching and JSON output.
1367
+ - `tsk_1584392a` — duplicate of `tsk_43fe9ff0`; corrected direct-run documentation for the multi-bin npm package.
1368
+ - `tsk_0160bfd4` — retained and regression-tested log-ID deduplication across follow polling cycles.
1369
+ - `tsk_208f7583` — replaced the confusing fresh-project rollback snapshot wording; the snapshot-selection platform follow-up is noted below.
1370
+ - `tsk_06c1f77a` — rollback API and network failures emit parseable JSON error envelopes.
1371
+ - `tsk_e6293ee2` — deploy warnings already present in the build log are no longer printed a second time.
1372
+ - `tsk_43fe9ff0` — documented the correct multi-bin invocation: `npx -y -p @somewhere-tech/cli@latest somewhere <command>` (or the equivalent `npm exec --package ... -- somewhere`).
1373
+ - `tsk_b210d436` — bare `somewhere docs` now streams the full reference; the topic menu remains available at `somewhere docs --list`.
1374
+ - `tsk_873f694c` — retained and regression-tested the real two-step project deletion confirmation flow and truthful server errors.
1375
+
1376
+ ### Platform follow-up
1377
+
1378
+ - `tsk_41ee402b`, `tsk_208f7583` — rollback must select and restore the previous live/promoted release snapshot, not an intermediate deploy version, and every fresh deploy/promote path must persist the restorable snapshot before changing the live pointer.