From de05f3eb24da3b94cd57580a67080740af5f7db9 Mon Sep 17 00:00:00 2001 From: Ryota Murakami Date: Tue, 27 Oct 2026 01:09:05 +0900 Subject: [PATCH 1/9] fix: Cycle 0056 pt2: the reader says the editor may ask for consent while a question waits (task 15) --- extension/README.md | 2 ++ extension/src/constants.ts | 4 ++++ extension/src/deepWikiReader.ts | 3 ++- extension/src/tests/wikiQuestionPage.test.ts | 8 ++++---- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/extension/README.md b/extension/README.md index 7a5c835d..04605f0e 100644 --- a/extension/README.md +++ b/extension/README.md @@ -184,6 +184,8 @@ To write the Wiki elsewhere, set the folder in your settings (a path inside the **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. +A question asked on the page waits with `Asking the editor model… The editor may first ask you to allow Codebook to use it; answer there.` in both editors, because the editor may ask for your consent before its model answers the first question; the page cannot know whether you gave it. + | 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. | diff --git a/extension/src/constants.ts b/extension/src/constants.ts index a18b52ba..b3eb2f4b 100644 --- a/extension/src/constants.ts +++ b/extension/src/constants.ts @@ -833,6 +833,10 @@ export const WIKI_UPDATE_STATUS_ROUTE = 'api/update-status' export const WIKI_FRESHNESS_ROUTE = 'api/freshness' /** Route of the Wiki reader that takes a repository question from its own page. */ export const WIKI_QUESTION_ROUTE = 'api/ask' + +/** The reader's status line while a question waits for the editor model; the editor may be asking for consent meanwhile. */ +export const WIKI_QUESTION_WAITING_STATUS = + 'Asking the editor model… The editor may first ask you to allow Codebook to use it; answer there.' /** The rules of the question status line of a Wiki page (`.qa-status`, the empty `role=status` line the progress of a question is told in): the bundled `reader-shell.html` carries the same rules, and the reader's page script adds them to a page published before the shell had the line, when it adds the line there. Empty, the line takes no room. */ export const WIKI_QUESTION_STATUS_STYLE = '.qa-status{font-size:.85rem;margin:.4rem 0 0;overflow-wrap:anywhere}.qa-status:empty{margin:0}' diff --git a/extension/src/deepWikiReader.ts b/extension/src/deepWikiReader.ts index b8e50f5a..f53c4b52 100644 --- a/extension/src/deepWikiReader.ts +++ b/extension/src/deepWikiReader.ts @@ -23,6 +23,7 @@ import { WIKI_PAGE_SERVE_DEADLINE_MS, WIKI_QUESTION_LIMIT_CHARS, WIKI_QUESTION_ROUTE, + WIKI_QUESTION_WAITING_STATUS, WIKI_QUESTION_STATUS_STYLE, WIKI_READER_FOREIGN_HOST_REFUSAL, WIKI_REFUSED_STEP_ADVICE, @@ -147,7 +148,7 @@ const qaClient = `(function () { // The answer's region is shown and emptied now, so the answer written after the request changes a region already in the page; the progress goes to the status line, which was there before it. output.style.display = 'block'; output.textContent = ''; var asked = ++questionsAsked; - questionStatus.textContent = 'Asking the editor model…'; + questionStatus.textContent = ${JSON.stringify(WIKI_QUESTION_WAITING_STATUS)}; // A hand-off or a failure can come back within the frame that showed the answer's region, which would enter the page together with that text: the sentence is the status line's, which was in the page before it, and the answer's empty disclosure leaves again. A newer question keeps its own progress and disclosure. var tell = function (sentence) { if (asked !== questionsAsked) return; diff --git a/extension/src/tests/wikiQuestionPage.test.ts b/extension/src/tests/wikiQuestionPage.test.ts index e9e80483..bded1a5b 100644 --- a/extension/src/tests/wikiQuestionPage.test.ts +++ b/extension/src/tests/wikiQuestionPage.test.ts @@ -45,7 +45,7 @@ function questionStatusOf(page: FakeWikiPage) { : 'no question status line' } -// Value: protects=a screen reader user who asks a question on a served Wiki published before this build: "Asking the editor model…" is written into a status line that was in the page, drawn and empty, before the question, and the answer into an answer region that was shown and empty before the answer; fails_when=the reader writes the progress sentence into the answer's status region in the same handler that shows its hidden, closed disclosure, so the region enters the page together with its first text and is not announced; why_new=D2; seam=openFakeWikiPage with the 0.2.29.0 shell's script and the served codebook-qa.js, the composer of a Wiki published before the question status line, holdNext('api/ask'); no_claim=what a given screen reader announces, and the timing of a browser's accessibility tree +// Value: protects=a screen reader user who asks a question on a served Wiki published before this build: "Asking the editor model… The editor may first ask you to allow Codebook to use it; answer there." is written into a status line that was in the page, drawn and empty, before the question, and the answer into an answer region that was shown and empty before the answer; fails_when=the reader writes the progress sentence into the answer's status region in the same handler that shows its hidden, closed disclosure, so the region enters the page together with its first text and is not announced; why_new=D2; seam=openFakeWikiPage with the 0.2.29.0 shell's script and the served codebook-qa.js, the composer of a Wiki published before the question status line, holdNext('api/ask'); no_claim=what a given screen reader announces, and the timing of a browser's accessibility tree test('a question asked on a served Wiki published before this build is announced from a status line the reader added, which was in the page, drawn and empty, before the question', async () => { // Arrange: the page of a Wiki published by 0.2.29.0 runs that shell's own script before the reader's. const script = `${await shellScriptOf('scripts/fixtures/reader-shell-0.2.29.0.txt')}\n${await readServedWikiScript()}` @@ -96,7 +96,7 @@ test('a question asked on a served Wiki published before this build is announced }, statusWhileAsking: { role: 'status/polite', - text: 'Asking the editor model…', + text: 'Asking the editor model… The editor may first ask you to allow Codebook to use it; answer there.', isShown: true, isInADisclosure: false, }, @@ -115,7 +115,7 @@ test('a question asked on a served Wiki published before this build is announced ) }) -// Value: protects=a screen reader user who asks a question on a Wiki this build publishes: the reader writes "Asking the editor model…" into the shell's own question status line, in the page and empty before the question, and adds no second line; fails_when=the reader keeps writing the progress sentence into the answer region it shows in the same handler, or adds a line of its own beside the shell's, so the progress is not announced or is announced twice; why_new=D2; seam=openFakeWikiPage with the bundled shell's script and the served codebook-qa.js, the current shell's composer, holdNext('api/ask'); no_claim=what a given screen reader announces +// Value: protects=a screen reader user who asks a question on a Wiki this build publishes: the reader writes "Asking the editor model… The editor may first ask you to allow Codebook to use it; answer there." into the shell's own question status line, in the page and empty before the question, and adds no second line; fails_when=the reader keeps writing the progress sentence into the answer region it shows in the same handler, or adds a line of its own beside the shell's, so the progress is not announced or is announced twice; why_new=D2; seam=openFakeWikiPage with the bundled shell's script and the served codebook-qa.js, the current shell's composer, holdNext('api/ask'); no_claim=what a given screen reader announces test('a question asked on a served Wiki of this build is announced from the shell’s own status line, and the reader adds no second one', async () => { // Arrange: the page runs the bundled shell's script before the reader's. const script = `${await shellScriptOf('skills/codebook/reader-shell.html')}\n${await readServedWikiScript()}` @@ -151,7 +151,7 @@ test('a question asked on a served Wiki of this build is announced from the shel }, statusWhileAsking: { role: 'status/polite', - text: 'Asking the editor model…', + text: 'Asking the editor model… The editor may first ask you to allow Codebook to use it; answer there.', isShown: true, isInADisclosure: false, }, From a68c512a2e7ebcfd4fda8e5d475deb5f66757411 Mon Sep 17 00:00:00 2001 From: Ryota Murakami Date: Tue, 27 Oct 2026 01:20:23 +0900 Subject: [PATCH 2/9] fix: Cycle 0056 pt2: the view's message and rows change together, hidden views do no background work, reveal says why it opens nothing, fact reads run together (tasks 16, 18-22) --- extension/README.md | 4 +- extension/src/extension.ts | 2 +- extension/src/tests/llmWikiView.test.ts | 146 ++++++++++++++++-- .../src/tests/llmWikiViewReadLoop.test.ts | 137 ++++++++++++++-- .../src/tests/readLlmWikiViewFacts.test.ts | 67 ++++++++ extension/src/tests/utils/defer.ts | 17 ++ .../src/tests/utils/fakeLlmWikiEditor.ts | 17 +- extension/src/tests/utils/wikiUpdateWindow.ts | 45 +++++- .../utils/describeUnrevealableWikiFolder.ts | 30 ++++ extension/src/utils/isExistingFolder.ts | 17 ++ extension/src/utils/llmWikiView.ts | 60 +++++-- extension/src/utils/readLlmWikiViewFacts.ts | 22 ++- .../src/utils/registerLlmWikiCommands.ts | 33 +++- 13 files changed, 541 insertions(+), 56 deletions(-) create mode 100644 extension/src/tests/utils/defer.ts create mode 100644 extension/src/utils/describeUnrevealableWikiFolder.ts create mode 100644 extension/src/utils/isExistingFolder.ts diff --git a/extension/README.md b/extension/README.md index 04605f0e..8c0dcbfc 100644 --- a/extension/README.md +++ b/extension/README.md @@ -251,11 +251,11 @@ The **LLM Wiki** view in Codebook's Activity Bar shows where the generated site - **`Generating in another window`** or **`Updating in another window`** shows a run of another editor window on the same folder, with its start time. - **`Waiting for chat`** shows the reservation a stopped VS Code watch leaves, from any window: `retry after