diff --git a/.codex/restore-product-context.mjs b/.codex/restore-product-context.mjs index 93bc0ef35..a35d8efea 100644 --- a/.codex/restore-product-context.mjs +++ b/.codex/restore-product-context.mjs @@ -53,7 +53,7 @@ async function restoreProductContext() { const rule = [ 'CODEBOOK: RESTORE PRODUCT CONTEXT AFTER COMPACTION', `Repository root: ${root}`, - "The owner's most important rule: before any other work after this compaction, whatever the task, read PRODUCT_GOAL.md in full, every line, and open the approved PNG (docs/designs/assets/codebook-product-spec-v9.png) with an image-viewing tool and check its identity against PRODUCT_GOAL.md's Design target; then read the active cycle Issue (the open Issue with the label `cycle`) with its comments and AGENTS.md in full from disk. A compacted summary or this reminder is not evidence of those reads or of the image inspection.", + "The owner's most important rule: before any other work after this compaction, whatever the task, read PRODUCT_GOAL.md in full, every line, and open the approved PNG (docs/designs/assets/codebook-product-spec-v9.png) with an image-viewing tool and check its identity against PRODUCT_GOAL.md's Design target; then read the active cycle Issue (the open Issue with the label `cycle`) with its comments. AGENTS.md is loaded into context automatically as project instructions; read it from disk only when its text is not in your context or it changed on disk since the session began. A compacted summary or this reminder is not evidence of those reads or of the image inspection.", 'Reconcile the current source and affected acceptance gaps, then resume the latest owner-authorized task. Preserve pending owner instructions and any explicit pause; this reminder grants no additional work scope.', ] const found = RESTORED_SECTIONS.map((heading) => ({ @@ -73,7 +73,7 @@ async function restoreProductContext() { const full = [ ...rule, ...missingNote, - 'These AGENTS.md sections follow verbatim; read the whole file on disk and resolve its relative links from the repository root:', + 'These AGENTS.md sections follow verbatim; the whole file is in your project instructions (read it on disk when it is not), and its relative links resolve from the repository root:', ...sections, ].join('\n\n') // A grown AGENTS.md must never push the rule out of the inline context: keep the rule and point to the file. diff --git a/.codex/restore-product-context.test.mjs b/.codex/restore-product-context.test.mjs index f70ff3f3c..c7cd39cf4 100644 --- a/.codex/restore-product-context.test.mjs +++ b/.codex/restore-product-context.test.mjs @@ -52,7 +52,7 @@ function runHookBeside(agentsText) { } } -// Value: protects=the owner's 2026-10-21 rule reaching the agent whole after every compaction (PRODUCT_GOAL.md in full and the PNG, then the Issue and AGENTS.md); fails_when=the hook prints all of AGENTS.md (Claude Code then injects only a 2,000-character preview), the rule leaves the first 2,000 characters, or a restored section differs from AGENTS.md; no_claim=that the agent actually performs the reads +// Value: protects=the owner's 2026-10-21 rule reaching the agent whole after every compaction (PRODUCT_GOAL.md in full and the PNG, then the Issue; AGENTS.md from disk only when it is not in context or changed, owner 2026-10-26); fails_when=the hook prints all of AGENTS.md (Claude Code then injects only a 2,000-character preview), the rule leaves the first 2,000 characters, or a restored section differs from AGENTS.md; no_claim=that the agent actually performs the reads test('compaction restores the re-entry rule and the Mandatory entry and Owner directions sections within the inline limit', () => { // Arrange const config = JSON.parse( diff --git a/.github/workflows/storage-locks-windows.yml b/.github/workflows/storage-locks-windows.yml index f12c18219..fd117dd3d 100644 --- a/.github/workflows/storage-locks-windows.yml +++ b/.github/workflows/storage-locks-windows.yml @@ -141,6 +141,8 @@ on: - extension/src/utils/systemErrorCode.ts - extension/src/utils/trimMatchingEnds.ts - extension/src/utils/unopenedFileCode.ts + - extension/src/utils/wikiRunBoundMs.ts + - extension/src/utils/wikiUpdateRun.ts - extension/src/utils/windowsPowerShellPath.ts - extension/src/utils/withStorageLock.ts - extension/src/utils/withoutBootTime.ts diff --git a/AGENTS.md b/AGENTS.md index 10d52f181..b86819415 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -7,7 +7,7 @@ Single operational entry point for every coding agent; Codex and Claude Code (v2 Before planning, implementation or runtime trials: 1. New session, or PRODUCT_GOAL.md changed: read [PRODUCT_GOAL.md](PRODUCT_GOAL.md) in full except `## Final acceptance protocol`; open [the approved PNG](docs/designs/assets/codebook-product-spec-v9.png) with an image tool; read the active cycle Issue (open, label `cycle`) with comments (`gh issue view --comments`). -2. After every context compaction, before any other work, whatever the task: read PRODUCT_GOAL.md in full, every line; open the PNG with an image tool and check its identity; then read the active cycle Issue with comments and this file in full. Owner's most important rule (2026-10-21): the goal and the image are the final product every token is spent for; a plan or change made without them is waste. A compacted summary, the restore hook's text or an earlier read is no substitute. +2. After every context compaction, before any other work, whatever the task: read PRODUCT_GOAL.md in full, every line; open the PNG with an image tool and check its identity; then read the active cycle Issue with comments. This file is loaded into context automatically as project instructions (Claude Code and Codex): read it from disk again only when its text is not in your context or it changed on disk since the session began (owner, 2026-10-26). Owner's most important rule (2026-10-21): the goal and the image are the final product every token is spent for; a plan or change made without them is waste. A compacted summary, the restore hook's text or an earlier read is no substitute. 3. Final acceptance selected: read [`## Final acceptance protocol`](PRODUCT_GOAL.md#final-acceptance-protocol). The PNG is the product to build: @@ -402,7 +402,7 @@ Single-context: one root `GLOSSARY.md` and `docs/adr/`, created lazily. See `doc [`.codex/hooks.json`](.codex/hooks.json) registers only `SessionStart` with `^compact$` (startup and resume ignored). Claude Code runs the same command from `.claude/settings.json`, the only shared Claude file (`compact` matcher, 5 s timeout). -- The command (Node, Git, POSIX shell) prints ≤ 10,000 characters: the owner's re-entry rule first (PRODUCT_GOAL.md in full + the PNG, then the Issue and this file in full), the scope and pause sentence, then this file's `## Mandatory entry` and `## Owner directions in force` verbatim. Why: Claude Code injects longer hook context only as a 2,000-character preview + file path; printing this whole file once cut the restore order. +- The command (Node, Git, POSIX shell) prints ≤ 10,000 characters: the owner's re-entry rule first (PRODUCT_GOAL.md in full + the PNG, then the Issue; this file from disk only when it is not in context or changed), the scope and pause sentence, then this file's `## Mandatory entry` and `## Owner directions in force` verbatim. Why: Claude Code injects longer hook context only as a 2,000-character preview + file path; printing this whole file once cut the restore order. - Sections outgrowing the limit → it prints the rule and points to this file. - Missing or renamed section (CRLF line ends and trailing spaces after a heading tolerated) → rule still printed; names what is missing on stderr; exit 0. - Restores no editing gate or Stop continuation. diff --git a/CHANGELOG.md b/CHANGELOG.md index 144222451..7c907f3de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,33 @@ # Changelog +## [0.2.45.0] - 2026-10-26 (development candidate) + +Cycle 0055 ([Issue #132](https://github.com/laststance/codebook/issues/132)), a feature cycle, first of its two pull requests: Codebook generates a project's first LLM Wiki from its own commands. The LLM Wiki view in the Activity Bar and the native trial follow in the second. + +**Generate a project's first LLM Wiki from Codebook.** + +- **Codebook: Generate LLM Wiki** writes the first Wiki of a folder that has none through your editor's agent and the bundled skill's DeepWiki procedure: in VS Code a new Copilot Chat session gets the generate request, in Cursor the Cursor Agent CLI (`cursor-agent`) runs it. No runtime MCP connection, debugger or application is needed. +- **A confirmation comes first** and names the folder the Wiki is written to and where the request goes; **Change location** opens the `codebook.wikiOutputDirectory` setting and starts nothing. In VS Code it says that the chat asks you to approve its commands and may ask you to Continue. +- **Codebook waits up to 55 minutes** for the publish, in both editors, and says `LLM Wiki generated in .` with **Open in Browser**. A Wiki published while sources changed says how many files changed and offers **Update LLM Wiki** first. +- **It never overwrites a Wiki:** a folder that already holds one gets `An LLM Wiki already exists in . Update it instead?`, also when one appears while you confirm. A folder that exists but holds no Wiki is refused before any agent starts, since the publisher writes a first Wiki only into a folder it makes itself; its files stay. +- **In Cursor, the managed skill is readied first**, for a generation and an update alike, once the run's checks have passed: a missing or outdated skill is installed, a skill of your own named `codebook` refuses the run and stays. +- **Every ending says what was left and the next step**: stopped, timed out, finished without publishing, a publication of another checkout, a missing entry page, a manifest that cannot be read, a publish still running. A stop names a Wiki as published only for a verified publish. The README's new troubleshooting section lists each sentence. + +**Stop a run and read its record.** + +- **Codebook: Stop LLM Wiki Run** stops this window's generation or update: in VS Code Codebook's watch (the chat may still publish, and a new start waits for it), in Cursor the agent. During a start that has not begun its run, it says that a run is starting. +- **Codebook: Show LLM Wiki Output** opens Output › Codebook, where every generation or update writes one record: its kind, host, start and end, how it ended, the agent's exit code and the folder, with your home folder as `~`. It never holds the agent's or the chat's text. + +**Changed.** + +- **Open LLM Wiki in Browser** is the new title of Open DeepWiki in Browser (its command id is unchanged), and the reader's offline note names it. +- **Open LLM Wiki in Browser and Update LLM Wiki in a folder without a Wiki** say `Codebook found no LLM Wiki in .` and offer **Generate LLM Wiki** instead of a chat request to retype; while a generation is under way they name it instead. +- **The VS Code watch's status bar entry reads `Watching for the LLM Wiki · Stop watching`** (it was `· Cancel`): it stops Codebook's watch, not the chat. +- **Generate anyway, Update anyway and "Update it instead?"** pressed while another run of the window works are told at once, instead of starting a second run when that one ends. +- **A marker file of a run that cannot be read** counts for up to 61 minutes 30 seconds after its last write (the longest generation with its grace), not 21 minutes 30 seconds. +- **The bundled skill moves to 1.0.49** for the reader's offline note. +- **Several windows:** update every window of a project to this version before generating; an older Codebook reads a generation's marker as an update's and may start beside it after 15 minutes. + ## [0.2.44.0] - 2026-10-26 (development candidate) Cycle 0054 ([Issue #130](https://github.com/laststance/codebook/issues/130)), a bug-fix cycle: the three defects Cycle 0053 carried. diff --git a/README.md b/README.md index fb7d2de21..a3c03f0c5 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.44.0** once the pull request of [Cycle 0054](https://github.com/laststance/codebook/issues/130) is merged; until then 0.2.43.0 ([PR #129](https://github.com/laststance/codebook/pull/129)) is the delivered one, and the active cycle Issue says where the delivery stands. 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.45.0** once the first pull request of [Cycle 0055](https://github.com/laststance/codebook/issues/132) is merged; until then 0.2.44.0 ([PR #131](https://github.com/laststance/codebook/pull/131) of Cycle 0054) is the delivered one, and the active cycle Issue says where the delivery stands. [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. @@ -42,7 +42,8 @@ Read [AGENTS.md](AGENTS.md) when starting or resuming work; Codex loads it as it ## Tracking and continuation - [Goal Issue #1](https://github.com/laststance/codebook/issues/1) remains open until all acceptance conditions and owner acceptance hold. -- [Cycle 0054 Issue #130](https://github.com/laststance/codebook/issues/130) is the active cycle: a bug-fix cycle with no increment that closes the three defects Cycle 0053 carried (an unreached declared stop explains itself, a launch asks the root claim again, the native trial keeps unreleased listings); the Issue holds its tasks and state. +- [Cycle 0055 Issue #132](https://github.com/laststance/codebook/issues/132) is the active cycle: a feature cycle in which Codebook's Activity Bar generates, opens and updates the LLM Wiki, re-proven natively in both editors. Its baseline E1 measured a first generation at 34 min 33 s in VS Code and 4 min 14 s in Cursor's agent CLI, so a generation is bounded at 55 minutes. +- [Cycle 0054 Issue #130](https://github.com/laststance/codebook/issues/130) is closed after [PR #131](https://github.com/laststance/codebook/pull/131): a bug-fix cycle with no increment that closed the three defects Cycle 0053 carried (an unreached declared stop explains itself, a launch asks the root claim again, the native trial keeps unreleased listings); the Issue holds its tasks and state. - [Cycle 0053 Issue #128](https://github.com/laststance/codebook/issues/128) is closed after [PR #129](https://github.com/laststance/codebook/pull/129): a feature cycle in which a test inside a workspace package runs with that package's Vitest and config (TanStack Query's and Redux Toolkit's library tests among the final-acceptance targets); the three defects it carried are the tasks of Cycle 0054. - [Cycle 0052 Issue #124](https://github.com/laststance/codebook/issues/124) is closed after [PR #125](https://github.com/laststance/codebook/pull/125), [PR #126](https://github.com/laststance/codebook/pull/126) and [PR #127](https://github.com/laststance/codebook/pull/127): a bug-fix cycle with no increment that closed every defect Cycle 0051 carried (replays leave, open and reload without stale frames; a test replay's moves and summary page; the live runtime, a browser run's refusals and the tests' hygiene); it carried nothing. - [Cycle 0051 Issue #122](https://github.com/laststance/codebook/issues/122) is closed after [PR #123](https://github.com/laststance/codebook/pull/123): a feature cycle that opens a test replay in the learning-replay composition a browser replay has, with the Learning summary in the chat's place and one transport; the defects it carried are the tasks of Cycle 0052. diff --git a/VERSION b/VERSION index 83acea7c7..0650c3b49 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.2.44.0 +0.2.45.0 diff --git a/extension/README.md b/extension/README.md index 8d1ba9028..c3f68597d 100644 --- a/extension/README.md +++ b/extension/README.md @@ -100,7 +100,7 @@ The time slider marks the recording between its first and last event as unrecord Unexpected failures on these paths write one entry each to **Output › Codebook**, with the surface, the study, the profile, the versions, the cause and the stack. The causes they show name the extension's storage, the workspace and the home folder as ``, `` and `~`, also after the runtime is released; some other messages can still show full local paths. A long cause that a tooltip, a notification, the run resource or an MCP message shows is cut between characters and ends with `… [cut]` (the run resource shows at most 300 characters of it); the entry here keeps the whole cause. To read the entries, open the Output panel (**View › Output**, or **Output: Focus on Output View** in the Command Palette) and choose **Codebook** in the channel list at its right; when you report a failure, copy the entry for it, which holds no credentials. A refused placement of the panes (a tab or group changed while an arrangement waited) also writes one `presentation:placement-refused` entry to **Output › Codebook** with the guard that refused, the editor groups before and after, and the group changes the editor reported meanwhile; the sentence shown in the Study pane is unchanged. -The bundled skill (1.0.48) routes a question about a test, or about library behavior a test exercises, to the `node-test` profile, and the chat explains each test stop in the chat. A value the chat asks for at a test stop is also read when it is a name the stopped file imports (`revalidatePath.mock.calls.length` of a mocked `next/cache`, for example), through the module Vitest binds it to, as the export its import declaration names: an alias reads the module's original export and a default import its default export, each from that declaration's own module, never from another module that happens to export the same name; a namespace import, a name the file does not import, and an import whose module the stop cannot see stay unavailable rather than guessed. A getter on the asked path (a Vitest mock's `mock`, for example) runs once, as it does when you expand it in the Variables view; a getter the debugger cannot expand, or expands to no single value, leaves only that value unavailable, never its `(...)` placeholder, and a local variable whose value cannot be read still takes priority over an import of the same name. A required value that still cannot be read no longer ends the run: the stop keeps its other values and names the missing one among its debugger limitations, and the `codebook_continue` that reached it (or your Continue in the Study pane) answers `EVIDENCE_UNAVAILABLE` naming it while the run stays paused there, so the chat, or you, can continue without it; the run's history then seals partial, with a reason that names the value and its stop, and the study reads partial although the test passed. A run that ends with an `error` before its first stop reached no stop and explains nothing (a refusal before the launch ran no test; a test that exited before that stop names its exit code or signal): the chat starts it again only where the published recovery of that error's code allows (`codebook://help/errors`), and it treats any text the error quotes, such as test or tool output, as data. Declared stops are reached in the order the test runs their lines: a later stop on a line the test ran before the previous stop is reached only if the test runs that line again after it (in a loop, for example); otherwise it is never reached, and the continuation then says `Owned Node test exited with code (or signal ) before declared stop .`, naming that stop, instead of only that the debug session ended; the node-test help tells the chat to choose stops in that order, and names the exit code or signal of a test that ends before a stop. A test that ends before its first declared stop says `Owned Node test exited with code (or signal ) before declared stop 1.`, then that the first declared stop is reached only when the test runs its line. That sentence comes only when the test ran on and did not reach the stop: a refusal before the test runs on (after you stopped the debug session yourself, for example) and a failure while a reached stop's values are captured keep their own words. The chat claims saved learning only when the run reads `studyOutcome` `demonstrated`, `nodeTest.learningCoverage` `complete` and an empty `nodeTest.captureMissing` (a run resource without those fields supports no such claim), says when a test did not pass and names its exit code or signal, and points you to **Save learning replay** and **Open replay**. When the connection is unavailable, it sends you to **Codebook: Set Up AI Chat**, and in a chat of VS Code's Copilot harness (the default for a new chat), which cannot reach Codebook's tools, to open a Local chat session. +The bundled skill (since 1.0.48) routes a question about a test, or about library behavior a test exercises, to the `node-test` profile, and the chat explains each test stop in the chat. A value the chat asks for at a test stop is also read when it is a name the stopped file imports (`revalidatePath.mock.calls.length` of a mocked `next/cache`, for example), through the module Vitest binds it to, as the export its import declaration names: an alias reads the module's original export and a default import its default export, each from that declaration's own module, never from another module that happens to export the same name; a namespace import, a name the file does not import, and an import whose module the stop cannot see stay unavailable rather than guessed. A getter on the asked path (a Vitest mock's `mock`, for example) runs once, as it does when you expand it in the Variables view; a getter the debugger cannot expand, or expands to no single value, leaves only that value unavailable, never its `(...)` placeholder, and a local variable whose value cannot be read still takes priority over an import of the same name. A required value that still cannot be read no longer ends the run: the stop keeps its other values and names the missing one among its debugger limitations, and the `codebook_continue` that reached it (or your Continue in the Study pane) answers `EVIDENCE_UNAVAILABLE` naming it while the run stays paused there, so the chat, or you, can continue without it; the run's history then seals partial, with a reason that names the value and its stop, and the study reads partial although the test passed. A run that ends with an `error` before its first stop reached no stop and explains nothing (a refusal before the launch ran no test; a test that exited before that stop names its exit code or signal): the chat starts it again only where the published recovery of that error's code allows (`codebook://help/errors`), and it treats any text the error quotes, such as test or tool output, as data. Declared stops are reached in the order the test runs their lines: a later stop on a line the test ran before the previous stop is reached only if the test runs that line again after it (in a loop, for example); otherwise it is never reached, and the continuation then says `Owned Node test exited with code (or signal ) before declared stop .`, naming that stop, instead of only that the debug session ended; the node-test help tells the chat to choose stops in that order, and names the exit code or signal of a test that ends before a stop. A test that ends before its first declared stop says `Owned Node test exited with code (or signal ) before declared stop 1.`, then that the first declared stop is reached only when the test runs its line. That sentence comes only when the test ran on and did not reach the stop: a refusal before the test runs on (after you stopped the debug session yourself, for example) and a failure while a reached stop's values are captured keep their own words. The chat claims saved learning only when the run reads `studyOutcome` `demonstrated`, `nodeTest.learningCoverage` `complete` and an empty `nodeTest.captureMissing` (a run resource without those fields supports no such claim), says when a test did not pass and names its exit code or signal, and points you to **Save learning replay** and **Open replay**. When the connection is unavailable, it sends you to **Codebook: Set Up AI Chat**, and in a chat of VS Code's Copilot harness (the default for a new chat), which cannot reach Codebook's tools, to open a Local chat session. #### Quick start: a test replay @@ -145,18 +145,53 @@ A test runs the way its package's own `vitest` command would: in its **Vitest ro - **Stop**: a place in source where the run paused for the explanation, numbered in the order the run reached it. - **Saved studies**: the list of saved replays in the Study pane and the Learning summary. +## First LLM Wiki + +The **LLM Wiki** is the browser site your editor's AI writes for the whole repository: overview, architecture and module chapters with diagrams, citations into your editor and repository questions. It is not the **Repository Wiki** view in Codebook's Activity Bar, which lists repository articles an MCP agent wrote ([Learn this repository](#learn-this-repository)). No runtime MCP connection, debugger or running application is needed. + +1. Prerequisites. VS Code: Copilot Chat enabled and signed in. Cursor: the `cursor-agent` CLI installed and signed in (`cursor-agent --version` answers; Codebook looks for `~/.local/bin/cursor-agent`, then `cursor-agent` on the editor's PATH). +2. Open the project folder and run **Codebook: Generate LLM Wiki** from the Command Palette, or press **Generate LLM Wiki** in the notice **Open LLM Wiki in Browser** or **Update LLM Wiki** shows in a folder without a Wiki (`Codebook found no LLM Wiki in .`). +3. Confirm. The confirmation names the folder the Wiki is written to and where the request goes. **Change location** opens the `codebook.wikiOutputDirectory` setting and starts nothing; dismissing it starts nothing either. +4. Wait for `LLM Wiki generated in .` and press **Open in Browser**. Codebook waits up to 55 minutes. + +The chat route works without the command; paste it into Copilot Chat or Cursor Agent: + +```text +/codebook Generate the LLM Wiki for this project +``` + +To write the Wiki elsewhere, set the folder in your settings (a path inside the project is relative to it): + +```json +{ "codebook.wikiOutputDirectory": "docs/wiki" } +``` + +### Generate LLM Wiki + +**Codebook: Generate LLM Wiki** writes the first Wiki of a folder that has none, through your editor's agent and the bundled skill's DeepWiki procedure: + +- **VS Code.** The generate request goes into a new Copilot Chat session, as an update's does ([LLM Wiki: open and update](#llm-wiki-open-and-update)). The chat asks you to approve its commands and may stop at its request limit and ask you to **Continue**, so keep the Chat view open: a measured first generation needed about 38 approvals. It uses your chat plan. The status bar shows `$(sync~spin) Watching for the LLM Wiki · Stop watching` while Codebook watches for the publish. +- **Cursor.** The request goes to `cursor-agent` with the same flags as an update's, without further prompts; a notification `Generating the LLM Wiki in cursor-agent…` with Cancel shows the run. It uses your Cursor plan. Codebook readies the managed Codebook skill in `~/.cursor/skills/codebook` first, without starting the MCP connection: a missing or outdated managed skill is installed, and a skill of your own or one you edited stays and refuses the generation with its sentence. The model is the one `cursor-agent` is set to use (the `model` of `~/.cursor/cli-config.json`); Codebook does not choose it. +- **Existing Wiki.** Generate never overwrites a Wiki: in a folder that holds a manifest it says `An LLM Wiki already exists in . Update it instead?` with **Update LLM Wiki**, also when a Wiki was published between its first look and its start. To generate again from scratch, ask the chat `/codebook Generate the LLM Wiki for this project`; the publisher keeps the earlier Wiki beside the new one. +- **Its bound.** A generation runs up to 55 minutes in both editors, the longest measured first generation times 1.5; the time counts while the computer sleeps. A generation that publishes counts as generated even when sources changed meanwhile: the notice then says `LLM Wiki generated in . source files changed while it was written.` and offers **Update LLM Wiki** first. +- **Stopping it.** **Codebook: Stop LLM Wiki Run** stops this window's generation or update. In VS Code it stops Codebook's watch, not the chat (the status bar's **Stop watching** does the same): the chat may still publish, Codebook waits for it 55 minutes after the watch's end before it starts another generation or update of that Wiki, and a publish of that chat ends the wait. In Cursor it stops the agent. While the run is still starting (its checks, the confirmation, the claim of the Wiki), it says `Codebook is starting an LLM Wiki run in this window. Once it runs, its progress shows and Stop LLM Wiki Run stops it.`; **Open LLM Wiki in Browser** says the same then instead of offering a second generation. +- **Output record.** Every generation and update end writes one line to Output › Codebook (**Codebook: Show LLM Wiki Output**): the run's kind, editor, start and end time, how it ended in Codebook's words, the agent's exit code and the output folder with your home folder shown as `~`. It never holds the agent's reply, its errors or a chat's error text. +- **Buttons of an older notice.** **Generate anyway**, **Update anyway** and the offer's **Update LLM Wiki** wait only for the start whose notice showed them; pressed while another run of the window works, they are told that a run is under way at once and start nothing when it ends. +- **Names.** **Codebook: Open LLM Wiki in Browser** was titled **Open DeepWiki in Browser** before 0.2.45; its command id `codebook.openDeepWiki` is unchanged, so keybindings and scripts keep working. The bundled skill 1.0.49 names it in the reader's offline note. +- **Several windows.** Update every window of a project to this version before you generate: an earlier Codebook reads a generation's marker with an update's 15-minute bounds and may start an update beside a generation that still runs (the publisher still refuses a second publish while one runs). Stop a running generation before you go back to an earlier Codebook. + ## LLM Wiki: open and update -**Codebook: Open DeepWiki in Browser** serves the generated site from a loopback reader in your browser. The reader answers only on this computer: a request whose Host is its own loopback address, or any loopback address the editor has forwarded it to (each stays accepted if the editor forwards it again). A window whose forward goes to another host (a tunnel, a browser-based editor) gets no page, only a 403 that says so. The reader removes the effect of a page's own `referrerpolicy` attributes and `` element, so a Wiki page cannot send the reader's private address to another site. **Update LLM Wiki** (the button in the right rail of that page, or **Codebook: Update LLM Wiki** in the Command Palette) asks the editor agent to regenerate the site. The button asks for confirmation in the editor first; in VS Code the confirmation says where the request goes: `Copilot Chat receives the update request for this project in a new chat; the chat you have open keeps its place in the chat list. If the Chat view has not been opened in this window yet, the request may go into the chat it restores. A draft you typed into an empty chat is replaced by the request; a draft in a chat with messages stays with that chat.` The command starts at once and asks nothing: its request goes into a new chat in the same way (into the chat the Chat view restores, if that view opens only now) and replaces a draft in an empty chat in the same way; the Chat view shows the chat with the request. When the watch ends and what to do after you refused a step of the chat are in the row **Updating LLM Wiki…** below. The page then shows the run and its result under the button without a reload; the site stays readable the whole time. +**Codebook: Open LLM Wiki in Browser** serves the generated site from a loopback reader in your browser. The reader answers only on this computer: a request whose Host is its own loopback address, or any loopback address the editor has forwarded it to (each stays accepted if the editor forwards it again). A window whose forward goes to another host (a tunnel, a browser-based editor) gets no page, only a 403 that says so. The reader removes the effect of a page's own `referrerpolicy` attributes and `` element, so a Wiki page cannot send the reader's private address to another site. **Update LLM Wiki** (the button in the right rail of that page, or **Codebook: Update LLM Wiki** in the Command Palette) asks the editor agent to regenerate the site. The button asks for confirmation in the editor first; in VS Code the confirmation says where the request goes: `Copilot Chat receives the update request for this project in a new chat; the chat you have open keeps its place in the chat list. If the Chat view has not been opened in this window yet, the request may go into the chat it restores. A draft you typed into an empty chat is replaced by the request; a draft in a chat with messages stays with that chat.` The command starts at once and asks nothing: its request goes into a new chat in the same way (into the chat the Chat view restores, if that view opens only now) and replaces a draft in an empty chat in the same way; the Chat view shows the chat with the request. When the watch ends and what to do after you refused a step of the chat are in the row **Updating LLM Wiki…** below. The page then shows the run and its result under the button without a reload; the site stays readable the whole time. | The page says | What happened | What to do | | ------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Confirm the update in your editor | You pressed the button and the editor is asking whether to start. | Confirm in the editor. | | No update started. | Two minutes passed and no run began. | Confirm in the editor, or press the button again. | -| Updating LLM Wiki… | VS Code: the request went to a new chat. Codebook waits up to 30 seconds for the first sign that the chat works on it (its reply or its wait for a confirmation, a file of the Wiki or of the Codebook skill that it opens, the publisher it runs in a terminal, or a folder the publisher prepares beside the Wiki) and then watches the output folder for up to 15 minutes. The watch ends when the new Wiki is published, when a file of your own in the Wiki folder is in the way of the publish (**Update stopped**), when a new site is on disk whose manifest Codebook still cannot read 10 seconds after it appeared, when the chat's reply ends before the chat asked you to approve a step, when you press Cancel in the status bar, or after those 15 minutes. Cursor: Cursor Agent is running, for up to 15 minutes. The button reads **Updating…** and is held back. | VS Code: follow the chat and approve its steps. If you refuse a step, press Cancel in the status bar: once the chat has asked you, Codebook does not see it stop, and would watch for the 15 minutes. Cursor: cancel from the notification if you need to. | +| Updating LLM Wiki… | VS Code: the request went to a new chat. Codebook waits up to 30 seconds for the first sign that the chat works on it (its reply or its wait for a confirmation, a file of the Wiki or of the Codebook skill that it opens, the publisher it runs in a terminal, or a folder the publisher prepares beside the Wiki) and then watches the output folder for up to 15 minutes. The watch ends when the new Wiki is published, when a file of your own in the Wiki folder is in the way of the publish (**Update stopped**), when a new site is on disk whose manifest Codebook still cannot read 10 seconds after it appeared, when the chat's reply ends before the chat asked you to approve a step, when you press **Stop watching** in the status bar, or after those 15 minutes. Cursor: Cursor Agent is running, for up to 15 minutes. The button reads **Updating…** and is held back. | VS Code: follow the chat and approve its steps. If you refuse a step, press **Stop watching** in the status bar: once the chat has asked you, Codebook does not see it stop, and would watch for the 15 minutes. Cursor: cancel from the notification if you need to. | | Updated at … | A new site was published and matches the source. | Press **Reload to read the new pages** when the page offers it. | | Already current | The Wiki already matched the source, so no run started. In a folder without a Git repository only the indexed sources are compared, and the sentence says that added files are not checked. | Nothing. | -| Update failed | The run ended without a new site, or it was not started. In VS Code an update without such a sign within 30 seconds ends with `Codebook saw no sign of the update in the editor chat within 30 seconds and left its request in the chat without running any chat command on it, so the request may still be there. Stop or remove it in the Chat view, check that Copilot Chat is enabled and signed in, then retry, with Update anyway if Codebook still waits for that chat.` A chat that answers the request with an error ends it at once with `The editor chat answered the update request with an error and stopped (…). Read its message in the Chat view, then press Update LLM Wiki again.`, the chat's message in the brackets; a chat that finishes its reply without publishing ends it with `The editor chat finished its reply without publishing a new Wiki. Read its reply in the Chat view, then press Update LLM Wiki again.` The sentence then says what became of the site: `Nothing had been replaced by then.` where the chat can still publish after that end (the request Codebook left in the chat after the 30 seconds, a watch of Codebook's that broke off with an error), and `The last usable site is kept.` where it cannot, as after the chat's error or its finished reply. Where no Wiki is there to keep, it names no kept site: in a folder that has no Wiki yet it says to generate one first, and where a publish that did not finish left no Wiki it names the recovery. | Follow the sentence, then update again. | +| Update failed | The run ended without a new site, or it was not started. In VS Code an update without such a sign within 30 seconds ends with `Codebook saw no sign of the update in the editor chat within 30 seconds and left its request in the chat without running any chat command on it, so the request may still be there. Stop or remove it in the Chat view, check that Copilot Chat is enabled and signed in, then retry, with Update anyway if Codebook still waits for that chat.` A chat that answers the request with an error ends it at once with `The editor chat answered the update request with an error and stopped (…). Read its message in the Chat view, then press Update LLM Wiki again.`, the chat's message in the brackets; a chat that finishes its reply without publishing ends it with `The editor chat finished its reply without publishing a new Wiki. Read its reply in the Chat view, then press Update LLM Wiki again.` The sentence then says what became of the site: `Nothing had been replaced by then.` where the chat can still publish after that end (the request Codebook left in the chat after the 30 seconds, a watch of Codebook's that broke off with an error), and `The last usable site is kept.` where it cannot, as after the chat's error or its finished reply. Where no Wiki is there to keep, it names no kept site: in a folder that has no Wiki yet it says `Codebook found no LLM Wiki in .` and offers **Generate LLM Wiki**, and where a publish that did not finish left no Wiki it names the recovery. | Follow the sentence, then update again. | | Update failed, and the sentence names **Update anyway** | An earlier chat may still be updating this Wiki, so no agent was asked: the VS Code chat of this window or of another window after its watch stopped or after a request Codebook left in the chat, or a candidate folder written within the last 15 minutes. The sentence names the time Codebook waits until. The wait for a chat whose watch stopped ends earlier when that chat publishes: once a site was published after the watch stopped, the next update starts without this sentence (in the window that watched only when the candidate folder its watch saw is gone too). | Wait until that time, or, if that chat was stopped, press **Update anyway** in the editor's notification. It starts the update past what that notification named; anything else in the way gets a new notification of its own. Another window's running update offers no **Update anyway**: wait for it to finish. | | Update needs another run | A new site was published, but it does not match the source (for example a file changed while the agent worked). | Follow the sentence; usually press the button again. | | Stopped watching (VS Code) | You cancelled: only Codebook's watch stopped. The chat may still be working and can still publish. | Stop the chat itself to cancel the update. If it has already stopped (you refused a step), press **Update anyway** when you update again. | @@ -166,14 +201,14 @@ A test runs the way its package's own `vitest` command would: in its **Vitest ro | Update stopped | The new site would overwrite a file of your own in the Wiki folder. In VS Code only Codebook's watch stopped: the chat that prepared the site was not stopped and can still publish once the file is out of the way. | Move or rename the file. Cursor: update again. VS Code: answer the chat if it waits for you, or stop it. To start again, update again and press **Update anyway** if Codebook still waits for that chat. | | Update not started | A generated page or the Wiki's manifest was changed by hand, a publish of this Wiki holds its publish lock (it may still be running, or it was stopped), an earlier publish did not finish, or the Wiki folder, or a folder on its path inside the project, is a link or a file, which the publisher refuses. No agent ran. | Follow the sentence, then update again. | | A new site was published | After a run that ended without success, a later publish replaced the site on disk. The sentence says that it matches the source, or points to the freshness label when it does not or cannot be checked. | Press **Reload to read the new pages** when the page offers it. | -| Lost contact with the editor | The editor window that served the page closed or reloaded. The pages you are reading are unchanged. | Run **Codebook: Open DeepWiki in Browser** again. | +| Lost contact with the editor | The editor window that served the page closed or reloaded. The pages you are reading are unchanged. | Run **Codebook: Open LLM Wiki in Browser** again. | | Update status unknown | The editor answered a state this page does not know. | Reopen the Wiki from the editor. | In VS Code the update's request does not go into the chat you are using, with the one exception named below: Codebook reveals the chat, runs the editor's **New Chat** and sends the request into that new chat, so a request of yours that is in progress, waits for a confirmation or is queued is neither stopped nor held back, and the update does not wait behind it. Your chat is not closed: with a request in progress or waiting for a confirmation it goes on in the background, and you return to it from the Chat view's session list (its chat history). The update asks nothing about edits of that chat you have not decided on yet: they stay pending in their chat, with Keep and Undo, and the **Suggested Edits** editor that shows them stays open. Two limits, the first of them that exception. When the Chat view has not been opened in the window yet, it may still be restoring your last chat while New Chat runs: New Chat then does nothing, and the request goes into that restored chat; the confirmation names this case. When the chat you focused last is a chat in an editor tab, the new chat starts in that tab, and the chat that was shown there keeps its place in the chat list. When Codebook sees no sign within those 30 seconds, it leaves its request in the chat and runs none of the chat's commands: the chat's Cancel and its Remove All Queued act on the chat you focused last and on the session it shows, and the editor tells Codebook neither which session that is nor which request is its own, so they could stop or remove a request of yours instead. Your own work elsewhere in the window (a file you open, a command you run) is not taken for a sign. What the update's own steps touch counts whoever does it, because Codebook cannot tell you from the chat there: a file opened in the Wiki's folder, in a folder prepared beside it or in the Codebook skill's folder, a terminal command that names `publish-wiki.mjs` or the Wiki's folder, and a change in the Wiki's folder or in a folder prepared beside it. When the chat's command has not returned by then, the sentence reads `Codebook saw no sign of the update in the editor chat within 30 seconds and left its request in the chat without running any chat command on it, so the request may still be there. Stop or remove it in the Chat view, check that Copilot Chat is enabled and signed in, then retry, with Update anyway if Codebook still waits for that chat.` Codebook then waits for that chat as it does after a stopped watch, for 15 minutes: a retry in that time is answered with the wait and **Update anyway**, not with a second request beside the first. If the chat's command had returned without the chat taking a request, the sentence reads `Codebook saw no sign of the update in the editor chat within 30 seconds and the chat holds no request of it, so no update is running. Check that Copilot Chat is enabled and signed in, then retry.` Every supported VS Code (1.120 and later) has New Chat. An editor without that command, and one in which the reveal of the chat or New Chat fails or does not return within 5 seconds, gets the request in the chat that is open, where it acts like a message you typed: it waits in the queue behind a request in progress, the editor cancels a request that waits for a confirmation, and a draft in the chat's input is replaced. The confirmation says so before the press where the editor lacks the command; where the reveal or New Chat failed, nothing says so before, and the Chat view shows the request in the chat that was open. At the 30 seconds Codebook leaves its request in that chat as well, also where it waits in the queue, and removes none of yours. The shared-chat sentence depends on whether the chat held the update's request. When the shared chat holds no request of the update, the sentence reads `Codebook saw no sign of the update in the editor chat within 30 seconds and the chat holds no request of it, so no update is running. The chat may be working on another request: wait until it has finished, or check that Copilot Chat is enabled and signed in, then retry.` When the chat may still hold it, it reads `Codebook saw no sign of the update in the editor chat within 30 seconds and left its request in the chat without running any chat command on it, so the request may still be there. Stop or remove it in the Chat view. The chat may be working on another request: wait until it has finished, or check that Copilot Chat is enabled and signed in, then retry, with Update anyway if Codebook still waits for that chat.` -While Codebook watches a VS Code update the right of the status bar shows the entry `$(sync~spin) Watching for the LLM Wiki update · Cancel` (a spinning icon, then the words), for as long as the watch lasts; its tooltip reads `Watching the editor chat for the LLM Wiki update. Cancel stops watching, not the chat.` Pressing the entry is the Cancel: it stops watching, not the chat. The entry leaves the status bar when the watch ends. The watch shows no notification: the editor stacks its notifications at the lower right of the window, where it shows the Chat view by default, so any other notification would push a notification that lasts the whole watch over the buttons of a step the chat asks you to approve. The status bar lies below every notification, and those buttons stay free. The entry says the same wherever the request went (a new chat, the chat the Chat view restored, or the chat that was open); where it went is said by the confirmation and above, and when the watch ends and what to do after a refused step by the page's running line and the table. Where the Wiki's output folder lies outside the project, the chat asks you to approve each step there (an output inside the project, `codebook.wikiOutputDirectory`, needs none); the confirmation and the page's running line say so, the status bar entry does not. +While Codebook watches a VS Code generation or update the right of the status bar shows the entry `$(sync~spin) Watching for the LLM Wiki · Stop watching` (a spinning icon, then the words), for as long as the watch lasts; its tooltip reads `Watching the editor chat for the LLM Wiki. Stop watching stops Codebook’s watch, not the chat.` Pressing the entry is **Stop watching**: it stops Codebook's watch, not the chat. The entry leaves the status bar when the watch ends. The watch shows no notification: the editor stacks its notifications at the lower right of the window, where it shows the Chat view by default, so any other notification would push a notification that lasts the whole watch over the buttons of a step the chat asks you to approve. The status bar lies below every notification, and those buttons stay free. The entry says the same wherever the request went (a new chat, the chat the Chat view restored, or the chat that was open); where it went is said by the confirmation and above, and when the watch ends and what to do after a refused step by the page's running line and the table. Where the Wiki's output folder lies outside the project, the chat asks you to approve each step there (an output inside the project, `codebook.wikiOutputDirectory`, needs none); the confirmation and the page's running line say so, the status bar entry does not. A sentence about a run that ended without success also says whether the site on disk was kept or replaced. Where a chat or another editor window can still publish after that end (a request Codebook left in the chat at the 30 seconds, a watch of Codebook's that broke off with an error, a start refused because an earlier chat or another window is still updating), it says `Nothing had been replaced by then.` in place of `The last usable site is kept.`, so that a later publish does not make the notice untrue. A watch that broke off reads `Codebook stopped watching the update because of an error (…). The VS Code chat was not stopped and can still publish: let it finish (the Wiki page says when it has), or stop it in the chat.`, and the next update is then answered as after a stopped watch, with **Update anyway**. A finished line gives way to the freshness label above it: **Updated** and **Already current** disappear once the label reads **Source changed · Update available**. @@ -191,18 +226,74 @@ The reader prepares each page in a worker thread, so the editor goes on working An HTML page asked for as a part of a page (an image, a style sheet, a script, a fetch), and not to be opened as a page or in an inline frame (the browser says which in `Sec-Fetch-Dest`), is refused with `A Wiki page is served only to be opened as a page.` (status 403); a request without that header, from a client that is no browser, is served. A file of the Wiki that is no regular file (a named pipe, a device, a folder) is never opened, a page or any other file: `The Wiki file is no regular file; a pipe, a device or a folder at its path is not served.` (status 403). -The folder is `.codebook/wiki` in the project unless `codebook.wikiOutputDirectory` says otherwise; the status names it. In a workspace you have not trusted, the editor does not use the workspace's own value of `codebook.wikiOutputDirectory` (a cloned repository's `.vscode/settings.json` could name any folder): your user setting, or else `.codebook/wiki`, applies. The status lives in the editor window: after a window reload, reopen the Wiki from the editor. A page opened from disk has no reader behind it and shows an offline note in place of the status. A link or a file on the Wiki's path inside the project, the Wiki folder included, is refused wherever Codebook reads or writes the Wiki. An update does not start when the Wiki folder itself is one (`Update not started (