diff --git a/CHANGELOG.md b/CHANGELOG.md index 74de91229..1884dec66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [0.2.55.0] - 2026-10-28 (development candidate) + +Cycle 0059 pt2 ([Issue #147](https://github.com/laststance/codebook/issues/147)), the second of three parts of the feature cycle that saves a server run as a learning replay. This part reads a saved server history back: Saved studies lists it as a **Server replay** led by its learning title, request line and response status, the chat reads it through `codebook://node-history`, and it opens in the replay composition with the recorded request, output and response in the Application pane, the executed source and the recorded debugger state at each stop. Nothing writes a server history yet, so a server run is still refused at **Save learning replay** and you will not see one in this version. N59, the cycle's native trial, runs on the last part. + +**Saving the chat's learning material.** + +- **Two editor windows saving the learning material of the same test replay at once no longer overwrite each other.** The material is read, checked against its revision and written under the storage lock, so one save lands and the other answers with the revision conflict it would get against a newer revision. A save that meets the lock while another window holds it is refused with the storage lock's sentence. + ## [0.2.54.0] - 2026-10-28 (development candidate) Cycle 0059 pt1 ([Issue #147](https://github.com/laststance/codebook/issues/147)), the first of three parts of a feature cycle whose outcome is a server run saved as a learning replay. This part lays the storage a server replay will be written to and read from. Nothing writes one yet. A server run is still refused at **Save learning replay**, and nothing about server runs changes for you in this version. N59, the cycle's native trial, runs on the last part. diff --git a/README.md b/README.md index ab4bc65ab..ab41ec780 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Codebook contributes `debug.focusEditorOnBreak: false` as the native debugger de ## Implementation status -This is a preview, not a Marketplace or Open VSX release. The delivered version is **0.2.54.0** once the first pull request of [Cycle 0059](https://github.com/laststance/codebook/issues/147) is merged; until then 0.2.53.0 ([PR #144](https://github.com/laststance/codebook/pull/144), Cycle 0058) is the delivered one, and the active cycle Issue says where the delivery stands. Cycle 0059 is a feature cycle that saves a server run as a learning replay, in three pull requests: the first lays the storage a server replay is written to and read from (nothing writes one yet, so a server run is still refused at **Save learning replay**) and makes the saved study limit count test replays at a study's save, a run's start and a recording's start too; the second reads and replays a saved server history; the third records it during the run and carries the native trial. Cycle 0058 was a bug-fix cycle that closes the 13 defects Cycle 0057 carried: a stopped or retried server run signals and reports only what it did, what the chat and the learner read about a server run is true (skill 1.0.52), and the LLM Wiki view's message no longer flickers empty. Cycle 0057 was a feature cycle that explains a repository's own Node HTTP server live, in three pull requests: the first masks credentials in what every run captures and lays the server profile's launch parts; the second offers the `node-server` profile through MCP, which starts the server under the debugger, sends one declared request (confirmed by you when it changes data) and stops in the route handler's source; the third routes the bundled skill to it (skill 1.0.51), tightens stopping and what the run shows, and carries the native trial in VS Code and Cursor. Cycle 0056 was a bug-fix cycle that closed the defects Cycle 0055 carried, in three pull requests: the first makes an LLM Wiki start say what happens when it joins a start under way, is stopped or passes its bound, and release or write back what it claimed; the second the LLM Wiki view and the reader; the third a saved test replay that Cursor refused to open, with the native trial. [Cycle 0055](https://github.com/laststance/codebook/issues/132) is a feature cycle: **Codebook: Generate LLM Wiki** writes a project's first LLM Wiki through the editor's agent from Codebook's own entry (its first pull request), and an **LLM Wiki** view in the Activity Bar shows, opens and updates it (its second). Cycle 0053 was a feature cycle: a test inside a workspace package runs with that package's Vitest and config, as the package's own `vitest` would, while a test the repository root's config already selects keeps running from the root. Cycle 0054 is a bug-fix cycle that closes the three defects Cycle 0053 carried: a test that ends before a later declared stop says so, a package test's launch asks the repository root again whether its config now selects the test, and the native-trial bootstrap keeps a listing it could not release. Cycle 0051 opened a test replay in the learning-replay composition a browser replay has: the Learning summary in the chat's place, one transport for both replay families, and a Learning summary button that shows a hidden summary again. Cycle 0052 was a bug-fix cycle that closed every defect Cycle 0051 carried, in three pull requests: the first makes replays leave, open and reload without stale frames and makes their entries and exits behave as the learner chose; the second fixes a test replay's moves and its summary page; the third the live runtime's unreadable facts, a browser run's refusals and the tests' hygiene. The MCP API is 1.8. What each earlier cycle delivered, with its tests, trials and limits, is in the [change history](CHANGELOG.md) and in that cycle's record, kept under the tag [`docs-archive-2026-10-20`](https://github.com/laststance/codebook/tree/docs-archive-2026-10-20/docs/cycles); from Cycle 0048 on, the cycle's Issue holds its tasks and state, and its pull requests the results. +This is a preview, not a Marketplace or Open VSX release. The delivered version is **0.2.55.0** once the second pull request of [Cycle 0059](https://github.com/laststance/codebook/issues/147) is merged; until then 0.2.54.0 ([PR #148](https://github.com/laststance/codebook/pull/148), the first pull request of Cycle 0059) is the delivered one, and the active cycle Issue says where the delivery stands. Cycle 0059 is a feature cycle that saves a server run as a learning replay, in three pull requests: the first lays the storage a server replay is written to and read from and makes the saved study limit count test replays at a study's save, a run's start and a recording's start too; the second reads a saved server history back (Saved studies, `codebook://node-history` and the replay composition) and saves the chat's learning material under the storage lock, so two windows no longer overwrite each other's; the third records the history during the run, which is when a server run stops being refused at **Save learning replay**, and carries the native trial. Cycle 0058 was a bug-fix cycle that closes the 13 defects Cycle 0057 carried: a stopped or retried server run signals and reports only what it did, what the chat and the learner read about a server run is true (skill 1.0.52), and the LLM Wiki view's message no longer flickers empty. Cycle 0057 was a feature cycle that explains a repository's own Node HTTP server live, in three pull requests: the first masks credentials in what every run captures and lays the server profile's launch parts; the second offers the `node-server` profile through MCP, which starts the server under the debugger, sends one declared request (confirmed by you when it changes data) and stops in the route handler's source; the third routes the bundled skill to it (skill 1.0.51), tightens stopping and what the run shows, and carries the native trial in VS Code and Cursor. Cycle 0056 was a bug-fix cycle that closed the defects Cycle 0055 carried, in three pull requests: the first makes an LLM Wiki start say what happens when it joins a start under way, is stopped or passes its bound, and release or write back what it claimed; the second the LLM Wiki view and the reader; the third a saved test replay that Cursor refused to open, with the native trial. [Cycle 0055](https://github.com/laststance/codebook/issues/132) is a feature cycle: **Codebook: Generate LLM Wiki** writes a project's first LLM Wiki through the editor's agent from Codebook's own entry (its first pull request), and an **LLM Wiki** view in the Activity Bar shows, opens and updates it (its second). Cycle 0053 was a feature cycle: a test inside a workspace package runs with that package's Vitest and config, as the package's own `vitest` would, while a test the repository root's config already selects keeps running from the root. Cycle 0054 is a bug-fix cycle that closes the three defects Cycle 0053 carried: a test that ends before a later declared stop says so, a package test's launch asks the repository root again whether its config now selects the test, and the native-trial bootstrap keeps a listing it could not release. Cycle 0051 opened a test replay in the learning-replay composition a browser replay has: the Learning summary in the chat's place, one transport for both replay families, and a Learning summary button that shows a hidden summary again. Cycle 0052 was a bug-fix cycle that closed every defect Cycle 0051 carried, in three pull requests: the first makes replays leave, open and reload without stale frames and makes their entries and exits behave as the learner chose; the second fixes a test replay's moves and its summary page; the third the live runtime's unreadable facts, a browser run's refusals and the tests' hygiene. The MCP API is 1.8. What each earlier cycle delivered, with its tests, trials and limits, is in the [change history](CHANGELOG.md) and in that cycle's record, kept under the tag [`docs-archive-2026-10-20`](https://github.com/laststance/codebook/tree/docs-archive-2026-10-20/docs/cycles); from Cycle 0048 on, the cycle's Issue holds its tasks and state, and its pull requests the results. The specification is [goal version 10](PRODUCT_GOAL.md), and the implementation targets external repositories. Historical fixture or coupled-Wiki success is not proof of that destination. diff --git a/VERSION b/VERSION index 1bc9bc9eb..52e9e0c2f 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.2.54.0 +0.2.55.0 diff --git a/extension/README.md b/extension/README.md index 9ae08a3a5..baf836477 100644 --- a/extension/README.md +++ b/extension/README.md @@ -489,7 +489,7 @@ For actual-editor Playwright CLI video, set `CODEBOOK_EDITOR_CDP=1` only on the ## Run one configured repository action -Minimum versions: **extension 0.2.0+ / MCP API 1.4+**. The current preview is the version in this package's manifest (`extension/package.json`) with **MCP API 1.8** (`codebook_status` reports the installed build). API 1.8 changed what a `node-test` run reports: it reads `demonstrated` in `finalOutcome` once its test passed after every declared stop, and in `studyOutcome` and `recordedStudyOutcome` once its history sealed complete (before, it read `partial` at most); its run resource adds `nodeTest.testResult` (`passed`, `failed`, `signal` or `none`), `nodeTest.learningCoverage` (`complete`, `partial` or `none`) and `nodeTest.learningMissing`, and `nextActions` lists `save-node-learning` until the coverage is complete (and only for a history that holds an entry). Both the run resource and the node-history resource also list `nodeTest.captureMissing`, the recorded evidence the replay lacks (a stop whose debugger state was not captured, or an execution that ended before its result), which no explanation adds and which makes Save read partially saved; an agent claims saved learning only when `captureMissing` is empty. A node-history resource (`codebook://node-history/`, its events or its learning material) or a `codebook_explain_node_history` call that names a study id this workspace holds no history for (a mistyped id, for example, or a history removed while it is read) is refused as `NOT_FOUND` with a sentence that names the id and tells the agent to copy the `studyId` or `historyUri` from `codebook://node-history`; the published recovery of `NOT_FOUND` says the same. Causes the run resource shows (`nodeTest.historyReason`, `recording.reason`, `recording.contextReason`) are cut to 300 characters and name no private storage path. A node-test stop whose position does not fit its retained citation is refused during preparation with a sentence that names the stop (`source` or `additionalStops[n]`), its `anchorIndex`, the cited path and lines and the one condition that failed (anchor, path, hash, line or column), and what to send. The column of a declared node-test stop is a preference: when the debugger binds the declared line at another column, the stop is accepted and captured at that column, and only a binding on another line refuses it; that refusal names the declared and the bound position and says that the stop is captured on its declared line. A declared node-test stop in the cited test file itself is reached as well when the debugger reports no entry pause before it: its first pause is the stop, and Codebook captures it instead of continuing past it. A node-test start's checks (a changed stop source, a cited source the editor holds with other text, a changed test file, a path that is not a file, a test's Vitest missing, older than 4, unreadable, outside the repository or without its program, a Vitest root that holds a config-named folder or an outside link, a test path from the Vitest root that starts with `-`, a plan that changed before the launch) run during preparation and end the run with a typed `error` before its first stop, which records no history and frees the run's slot and key; `codebook_status` names a missing or older Vitest at the root or up to two levels below it before any start (`profiles['node-test'].vitestSearch`), and a `node_modules/vitest` that links outside the repository is not run. The node-test manifest's `vitestRoot`, `vitestRootReason`, `rootClaim`, `vitestConfigFiles` and `skippedConfigFiles` and `codebook_status`'s `vitestSearch` are additive output fields of API 1.8, and a node-test start no longer waits on `codebook_status`'s Vitest search. `codebook_stop` answers `HISTORY_SEAL_FAILED` when it could not seal the history of the run it ended, and `codebook_playback` refuses a test replay with `PLAYBACK_PROFILE_UNSUPPORTED`. `codebook_explain_node_history` refuses a step that cites another event than it claims with `INVALID_REFERENCE`, naming what that event is, and the node-test help (`codebook://help/node-test`) holds a complete start example and the ordered walkthrough of the calls. A test that ends with a non-zero exit code or a signal keeps that result even without Vitest's report, and a passing run whose first release failed seals complete once a retried Stop releases it. A test history whose seal fails with a transient file-system code (`EMFILE`, `ENFILE`, `EBUSY`, `EAGAIN` or `EPERM`) is sealed once more after 200 ms before the run reports `HISTORY_SEAL_FAILED`; a repeated `codebook_stop` makes no further attempt. No stored format changed in 1.8: test histories, learning materials and reader positions written by an earlier 0.2 version open unchanged. API 1.7 changed two answers: `codebook_source`, and `codebook_read_resource` for a book's cited source, answer the source's lines as `numberedText` and no longer as `text`, because the two copies doubled every source answer. An MCP `resources/read` of a cited source's URI still answers its exact text. No request states an API version, so a client written for API 1.6 gets these answers too: where it read `text`, it reads `numberedText` (each line after its one-based number and a tab, the lines joined by a line feed). API 1.7 also added a second reason a run resource names, and its evidence is refused with, once the run's saved study was removed: `The archive of this run's saved study is no longer in the study library: its files were removed by hand or by another Codebook window.`, beside `The learner moved this saved study to the Trash.` for a study deleted in this window (see [Delete a saved study](#delete-a-saved-study)). API 1.6 added, without changing the meaning of an existing field: `declaredSource`, the position you declared (`requestedSource` is its older name); `armed`, the place Codebook requested the breakpoint at when that differs; `place`, one sentence that names the line a stop paused on when the debugger bound it on another line than you declared; and `answer: "next"` in the run resource's `continueArguments`, with which a continuation answers with the next state (the next observation, the observed result or the failure). The same version also added `numberedText` to the answer of `codebook_source` and to the answer of `codebook_read_resource` for a book's cited source: the source's lines, each after its one-based number and a tab. Cycle 0029 delivered private preview **0.2.12** and Cycle 0018 **0.2.2**. `repository-browser` appears in `codebook_status.profiles` and its exact input schema at `codebook://help/repository-browser`. External-client execution, source/value pauses, recording/restart, interrupted evidence and native reader flows have separate development evidence in both editors. [Cycle 0017 installed evidence](https://github.com/laststance/codebook/blob/273660c49bb1aa5a88082ab6d43cd1ebae6ee7cf/docs/cycles/evidence/0017/native-validation.md) adds one unchanged real-repository action, live/replay modes and Wiki returns in both editors; its Cursor restart failure was later repaired in the bounded Cycle 0018 schedule. Neither result establishes G12 editor-chat use or full-product acceptance. +Minimum versions: **extension 0.2.0+ / MCP API 1.4+**. The current preview is the version in this package's manifest (`extension/package.json`) with **MCP API 1.8** (`codebook_status` reports the installed build). API 1.8 changed what a `node-test` run reports: it reads `demonstrated` in `finalOutcome` once its test passed after every declared stop, and in `studyOutcome` and `recordedStudyOutcome` once its history sealed complete (before, it read `partial` at most); its run resource adds `nodeTest.testResult` (`passed`, `failed`, `signal` or `none`), `nodeTest.learningCoverage` (`complete`, `partial` or `none`) and `nodeTest.learningMissing`, and `nextActions` lists `save-node-learning` until the coverage is complete (and only for a history that holds an entry). Both the run resource and the node-history resource also list `nodeTest.captureMissing`, the recorded evidence the replay lacks (a stop whose debugger state was not captured, or an execution that ended before its result), which no explanation adds and which makes Save read partially saved; an agent claims saved learning only when `captureMissing` is empty. A node-history resource (`codebook://node-history/`, its events or its learning material) or a `codebook_explain_node_history` call that names a study id this workspace holds no history for (a mistyped id, for example, or a history removed while it is read) is refused as `NOT_FOUND` with a sentence that names the id and tells the agent to copy the `studyId` or `historyUri` from `codebook://node-history`; the published recovery of `NOT_FOUND` says the same. Causes the run resource shows (`nodeTest.historyReason`, `recording.reason`, `recording.contextReason`) are cut to 300 characters and name no private storage path. A node-test stop whose position does not fit its retained citation is refused during preparation with a sentence that names the stop (`source` or `additionalStops[n]`), its `anchorIndex`, the cited path and lines and the one condition that failed (anchor, path, hash, line or column), and what to send. The column of a declared node-test stop is a preference: when the debugger binds the declared line at another column, the stop is accepted and captured at that column, and only a binding on another line refuses it; that refusal names the declared and the bound position and says that the stop is captured on its declared line. A declared node-test stop in the cited test file itself is reached as well when the debugger reports no entry pause before it: its first pause is the stop, and Codebook captures it instead of continuing past it. A node-test start's checks (a changed stop source, a cited source the editor holds with other text, a changed test file, a path that is not a file, a test's Vitest missing, older than 4, unreadable, outside the repository or without its program, a Vitest root that holds a config-named folder or an outside link, a test path from the Vitest root that starts with `-`, a plan that changed before the launch) run during preparation and end the run with a typed `error` before its first stop, which records no history and frees the run's slot and key; `codebook_status` names a missing or older Vitest at the root or up to two levels below it before any start (`profiles['node-test'].vitestSearch`), and a `node_modules/vitest` that links outside the repository is not run. The node-test manifest's `vitestRoot`, `vitestRootReason`, `rootClaim`, `vitestConfigFiles` and `skippedConfigFiles` and `codebook_status`'s `vitestSearch` are additive output fields of API 1.8, and a node-test start no longer waits on `codebook_status`'s Vitest search. `codebook_stop` answers `HISTORY_SEAL_FAILED` when it could not seal the history of the run it ended, and `codebook_playback` refuses a test replay with `PLAYBACK_PROFILE_UNSUPPORTED`. Two windows that save the learning material of the same test replay at once get one saved revision and one revision conflict, because the material is read, checked against its revision and written under the storage lock; a save that meets that lock while another window holds it is refused with the storage lock's sentence. `codebook_explain_node_history` refuses a step that cites another event than it claims with `INVALID_REFERENCE`, naming what that event is, and the node-test help (`codebook://help/node-test`) holds a complete start example and the ordered walkthrough of the calls. A test that ends with a non-zero exit code or a signal keeps that result even without Vitest's report, and a passing run whose first release failed seals complete once a retried Stop releases it. A test history whose seal fails with a transient file-system code (`EMFILE`, `ENFILE`, `EBUSY`, `EAGAIN` or `EPERM`) is sealed once more after 200 ms before the run reports `HISTORY_SEAL_FAILED`; a repeated `codebook_stop` makes no further attempt. No stored format changed in 1.8: test histories, learning materials and reader positions written by an earlier 0.2 version open unchanged. API 1.7 changed two answers: `codebook_source`, and `codebook_read_resource` for a book's cited source, answer the source's lines as `numberedText` and no longer as `text`, because the two copies doubled every source answer. An MCP `resources/read` of a cited source's URI still answers its exact text. No request states an API version, so a client written for API 1.6 gets these answers too: where it read `text`, it reads `numberedText` (each line after its one-based number and a tab, the lines joined by a line feed). API 1.7 also added a second reason a run resource names, and its evidence is refused with, once the run's saved study was removed: `The archive of this run's saved study is no longer in the study library: its files were removed by hand or by another Codebook window.`, beside `The learner moved this saved study to the Trash.` for a study deleted in this window (see [Delete a saved study](#delete-a-saved-study)). API 1.6 added, without changing the meaning of an existing field: `declaredSource`, the position you declared (`requestedSource` is its older name); `armed`, the place Codebook requested the breakpoint at when that differs; `place`, one sentence that names the line a stop paused on when the debugger bound it on another line than you declared; and `answer: "next"` in the run resource's `continueArguments`, with which a continuation answers with the next state (the next observation, the observed result or the failure). The same version also added `numberedText` to the answer of `codebook_source` and to the answer of `codebook_read_resource` for a book's cited source: the source's lines, each after its one-based number and a tab. Cycle 0029 delivered private preview **0.2.12** and Cycle 0018 **0.2.2**. `repository-browser` appears in `codebook_status.profiles` and its exact input schema at `codebook://help/repository-browser`. External-client execution, source/value pauses, recording/restart, interrupted evidence and native reader flows have separate development evidence in both editors. [Cycle 0017 installed evidence](https://github.com/laststance/codebook/blob/273660c49bb1aa5a88082ab6d43cd1ebae6ee7cf/docs/cycles/evidence/0017/native-validation.md) adds one unchanged real-repository action, live/replay modes and Wiki returns in both editors; its Cursor restart failure was later repaired in the bounded Cycle 0018 schedule. Neither result establishes G12 editor-chat use or full-product acceptance. The current adapter is `next-dev-webpack`: a trusted local Git root with dependencies already installed, an executable Next development server, a same-origin `entryPath` (default `/`), default `.next/dev` output, and webpack modules/maps that retain the exact original selected source. Codebook starts the owned server on `127.0.0.1` at the project's own port (Next is started with `--hostname 127.0.0.1`) and opens the app in the recorded browser at `http://localhost:`, the origin that `AUTH_URL`, OAuth callbacks and cookies usually name. `localhost`, `127.0.0.1` and `[::1]` at that port count as the same application origin, so a sign-in redirect between them keeps the run going while another port or host still ends it. Because a host may resolve `localhost` to `::1`, Codebook also listens on `[::1]:` for the whole run and forwards its bytes to the owned server (each direction ends as its source ends, so a client that half-closes still gets the reply), so no other process can answer there. The listener starts after the owned `next dev` has bound its port and reported ready, and never starts when that readiness fails or is cancelled; it closes with the run. If something else already holds `[::1]:`, preparation is refused as a busy port naming `[::1]`; if the system does not let Codebook listen there it is refused as not permitted, and any other listen failure is refused with its error code. On a host without IPv6 loopback no `[::1]` listener is made and `[::1]` is not accepted. The recorded browser resolves `localhost` as the system does, so the app's own calls to your other local services, on `::1` or `127.0.0.1`, reach them as they do in your own browser; Chrome itself runs on a dynamic loopback endpoint. The port is the one the project's own `dev` script would start `next dev` on, and Codebook asserts it only for a fixed set of forms. The `dev` script, and each script it runs, may be one or more statements joined by `&&` or `;`, each one of these: `export PORT=4000`, or a `PORT=4000` or plain `NAME=value` assignment as a prefix before a command; a `next dev` command reached by `next`, `npx next`, `bunx next`, `pnpm exec next`, `yarn next` or a `node_modules/.bin/next` path (the path form only on its own or after `pnpm exec`, since `npx` and `bunx` take a package name and fail on a path), optionally after `PORT=4000`, `cross-env` or `env` with assignments only, with Next's own `dev` flags and literal values (`-p`/`--port` as `-p 4000`, `-p4000`, `--port 4000` or `--port=4000`, the last one winning, `-H`/`--hostname`, `--turbo`, `--turbopack`, `--webpack`, `--experimental-https` and its `--experimental-https-*` options); a script run with no arguments (`npm run x`, `pnpm run x`, `yarn run x`, `bun run x`; `pnpm x` and `yarn x` without `run` are followed only for `dev`, `start`, `serve`, `web`, `app`, `client`, `frontend` and a name with a `:`, since pnpm and yarn have many commands and aliases of their own (`deploy`, `ci`, `t`, `access`, `rebuild`) that run before or instead of a script of that name, and some of them change between versions: write `pnpm run deploy`), followed two levels deep at most; or one `concurrently` whose quoted commands are each read the same way and exactly one of which is a `next dev` command. The port is the last `-p`/`--port`, else the `PORT` the script exports or assigns before the command, else Next's default 3000, and `PORT` from the editor's own environment is not consulted. The `dev` script is read as text and never run. A `package.json` that is not a regular file (a FIFO, for example) or is larger than 1 MiB is not read, and `applicationPortSource` says so. A `dev` script that runs more than 256 statements in all, counting every line of it and of each script it runs, is unread, and `applicationPortSource` says the dev script runs more statements than Codebook reads. The last statement may end with one `;`. The script is read with the meaning of the shell that runs it: `sh` on macOS and Linux, `cmd` on Windows, where npm, pnpm and yarn run scripts with `cmd`. On Windows only the forms that mean the same under `cmd` are read: bare `next` or an `npx`-style launcher with `next dev` and literal flags (a program written as a path with `/`, such as `node_modules/.bin/next`, is unread), `cross-env PORT=4000 next dev`, delegations and a `concurrently` with double-quoted commands; single quotes, a `PORT=4000` or `NAME=value` prefix, `export`, `env`, `;` and a variable named `port` in any case other than `PORT` (Windows ignores the case of variable names) are unread there, and `applicationPortSource` names `cmd`. An empty `dev` script is told as empty. A word that has a quote before its `=` (`"PORT=4000" next dev`) is no assignment. Everything else is unread: any other program or option, a pnpm command whose meaning depends on the installed pnpm version (`pnpm rebuild`), a pipe, `&` or `||`, a group or subshell, `$`, a backtick, a redirection or heredoc, a comment, a backslash or a line break, `if`/`while`/`!`/`time`, `sh -c`, `cmd /c`, `dotenv`, `node`, `set`, `unset`, a bare `PORT=4000;`, a `${PORT:-4000}` default, arguments given to a delegated script, and a script that never runs `next dev`. For an unread script no port is asserted: Next's default 3000 is taken and `applicationPortSource` says so and quotes the statement that left the forms above by its structure only. Only names from fixed lists are quoted (the words of the forms above by their base name, Next's `dev` flags, `PORT=…` and plain `NAME=…` assignment names before the program, and `package.json` script names, without control characters and cut); every value, operand, path, token, header, `user:pass@host` and base64 text is shown as `…`, so declare the port with `-p` in the `dev` script in one of the forms above to name it. `.env` files are not read for the port, because Next reads `PORT` before it loads them. Bun is the exception: it loads `.env` files into the environment of the scripts it runs, so a `next dev` without a `-p`/`--port` flag and without a `PORT` assigned in the script is unread (Next's default 3000 is taken and `applicationPortSource` names Bun's `.env` loading) when it is reached by `bun run ` + return `${escapeHtml(view.name)}

${escapeHtml(view.time)}

${view.profile === 'node-server' ? '' : `

${escapeHtml(view.test)}

`}
${view.profile === 'node-server' ? serverRegions(view) : ''}${muted('test-output-inspector', view.inspector)}${muted('test-output-cut', view.cut)}
${muted('test-output-placeholder', view.placeholder)}

${escapeHtml(view.end ?? '')}

` +} + +/** + * Writes a server replay's two fixed regions of the Application pane, outside the scrolling output: the request line with the claim the replay may make about it, and the response state with the recorded body in its own scrolling block. Called by {@link testOutputHtml}; {@link installNodeTestOutput} updates them in place. + * @param view - The server replay's Application view. + * @returns The markup of both regions, every text escaped. + * @example serverRegions(view) // => '
…' + */ +function serverRegions(view: NodeTestApplicationView): string { + const request = view.request + const response = view.response + return `

${escapeHtml(request?.line ?? '')}

${escapeHtml(request?.claim ?? '')}

${escapeHtml(response?.state ?? '')}

${escapeHtml(response?.body ?? '')}

${escapeHtml(response?.note ?? '')}

` } diff --git a/extension/test-timings.json b/extension/test-timings.json index 0aee64614..8c97c9603 100644 --- a/extension/test-timings.json +++ b/extension/test-timings.json @@ -33,6 +33,9 @@ "browserRecordingSealFailure.test.js": { "totalMs": 356 }, + "buildServerReplayModel.test.js": { + "totalMs": 595 + }, "buildWikiUpdatePrompt.test.js": { "totalMs": 1 }, @@ -526,6 +529,9 @@ "describeNodeRecordedSource.test.js": { "totalMs": 6 }, + "describeNodeServerReplay.test.js": { + "totalMs": 36 + }, "describeNodeTestReplay.test.js": { "totalMs": 1 }, @@ -838,6 +844,9 @@ "managedProfileRoot.test.js": { "totalMs": 1 }, + "maskNodeServerConfiguration.test.js": { + "totalMs": 82 + }, "maskNodeServerRequest.test.js": { "totalMs": 1 }, @@ -1087,6 +1096,9 @@ "nodeHistoryAdmission.test.js": { "totalMs": 159 }, + "nodeHistoryMaterialLock.test.js": { + "totalMs": 378 + }, "nodeHistoryPlaybackController.test.js": { "totalMs": 362 }, @@ -1110,9 +1122,15 @@ "output offered in one turn past the 1,000-entry queue is dropped under the same code and the structural entries still wait their turn": 5224 } }, + "nodeServerHistoryInterrupted.test.js": { + "totalMs": 202 + }, "nodeServerHistoryJournalIntegrity.test.js": { "totalMs": 434 }, + "nodeServerHistoryResources.test.js": { + "totalMs": 2706 + }, "nodeServerHistorySeal.test.js": { "totalMs": 1909 }, @@ -1122,6 +1140,9 @@ "nodeServerHistoryWriter.test.js": { "totalMs": 590 }, + "nodeServerHistoryWriterStates.test.js": { + "totalMs": 290 + }, "nodeStopSourceMatches.test.js": { "totalMs": 189 }, @@ -1239,6 +1260,9 @@ "projectRecording.test.js": { "totalMs": 17 }, + "projectServerApplication.test.js": { + "totalMs": 506 + }, "protocol.test.js": { "totalMs": 17467, "tests": { @@ -1796,9 +1820,18 @@ "serverBundle.test.js": { "totalMs": 29 }, + "serverHistoryRoutingFindings.test.js": { + "totalMs": 377 + }, "serverInspectorOwnership.test.js": { "totalMs": 140 }, + "serverReplayApplicationFindings.test.js": { + "totalMs": 417 + }, + "serverReplayPresentation.test.js": { + "totalMs": 408 + }, "service.test.js": { "totalMs": 3052 }, @@ -3532,6 +3565,34 @@ "studyWorkspaceRepositoryReader.test.js": { "totalMs": 6600 }, + "studyWorkspaceServerLibrary.test.js": { + "totalMs": 712 + }, + "studyWorkspaceServerReplay.test.js": { + "totalMs": 8875, + "tests": { + "Next and Previous stop visit each hit of a repeated stop and Next event moves on to the output and the response": 1547, + "Open replay of a sealed server history lands on its first stop with the stored source in the slot and the snapshot in the debugger": 335, + "a non-stop moment clears the debugger and says source and debugger are not recorded at this moment": 594, + "a saved playhead on a source entry restores the request before it": 318, + "a server history that is still being recorded opens only once its recording is interrupted": 279, + "a server history whose journal is damaged opens its verified prefix as an interrupted replay with its reason": 282, + "a server history without a stop opens at its request and Next stop answers that there is no next stop in this server replay": 321, + "a step citing the response moves the playhead there, and the explanation arriving while the replay is open keeps the playhead": 678, + "a stop whose executed source was too large to store says its recorded source is unavailable and why": 267, + "a stop with a lower frame presents it with its unavailable source reason": 272, + "an explanation saved from another window shows in this window as Saved and in the replay it opens": 374, + "moving through a server replay sends no request and starts no server": 652, + "opening a server replay and then a browser recording while a test replay presentation is still loading leaves only the recording shown": 907, + "seeking to the response and back to the stop presents the same snapshot and source and clears the response": 629, + "the Application pane of a server replay shows the sent request and no response yet at the first stop": 271, + "two hits at one time keep journal order and the slider ends at the end entry after the response": 320, + "understanding is saved only by the checkbox, and the playhead and understanding return when the replay is opened again": 829 + } + }, + "studyWorkspaceServerReplayFindings.test.js": { + "totalMs": 1461 + }, "studyWorkspaceStorage.test.js": { "totalMs": 15018, "tests": {