Skip to content

Commit 569a320

Browse files
committed
docs: sync CALM-TRANSCRIPT + align explanation word-count (PR review)
Second review pass flagged doc drift and a word-count mismatch: - The `explanation` length was three different numbers — SYSTEM_BASE said 3-10, run_command's schema 5-10, read_file/search 3-8, the doc 5-10. Unified to **3-8 words** everywhere (prompt, all three schemas, D6). Every example given already fits that range. - D3 claimed "no event schema changes" — but the `agentTool` payload gained `label`/`kind`/`path` (types unchanged, fields added, filled by agent.js). Reworded to say exactly that. - "Not doing (yet)" still listed model-written labels for reads/searches as unbuilt; this PR implements them (required `explanation`, used as the row label). Removed that bullet and updated §1's baseline note to point at D6/S1. Docs + prompt only; no behavior change. Gate green.
1 parent b655f95 commit 569a320

2 files changed

Lines changed: 13 additions & 12 deletions

File tree

docs/CALM-TRANSCRIPT.md

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ Two halves, shipped as separate slices: the **voice** (system prompt) and the **
3737
subtitle and the run card's italic `cmdwhy`), but the schema text doesn't say what to write and
3838
the system prompt never asks for it — in practice it's often missing. File ops post derived
3939
chips ("read X", `search "q"`). There is nothing like Claude Code's semantic command label
40-
("Found exact insertion point in section 10") unless we make `explanation` effectively required.
40+
("Found exact insertion point in section 10") unless we make `explanation` required — which D6/S1
41+
now do (schema-required on all three tools).
4142
- **Diffstat data exists everywhere we need it**: `editApplied` carries per-file `add`/`del`
4243
(rendered `+N −M` on the edit card); `reviewState` carries the run aggregate. A group header sum
4344
is arithmetic on data already in the webview.
@@ -63,10 +64,12 @@ stay verbatim. The voice rules are additive: *narrate briefly, then call the too
6364
turn*. A narration-only turn that promises action remains a stall and still gets nudged. This is
6465
the difference between "calm" and "chatty but idle".
6566

66-
### D3 — Grouping is a webview-only reducer. The extension host keeps posting the same events.
67-
No event schema changes, no agent.js changes for grouping. `chat.html` gets a small router:
68-
consecutive tool-ish entries (`agentTool` chips, `termRun` cards, `editApplied` cards, verify
69-
cards) are appended into the open group's body instead of `log`; any assistant text bubble,
67+
### D3 — Grouping is a webview-only reducer; the host keeps posting the same event *types*.
68+
No new event types and no host-side grouping logic. The `agentTool` payload does gain optional
69+
metadata — `label` (the model's `explanation`), `kind`, and `path` — so the webview can title and
70+
categorise rows; `agent.js` fills those fields, but the grouping decisions all live in `chat.html`.
71+
The router appends consecutive tool-ish entries (`agentTool` chips, `termRun` cards, `editApplied`
72+
cards, verify cards) into the open group's body instead of `log`; any assistant text bubble,
7073
`ask_user` card, `agentError`, or `agentDone` **closes** the group. This keeps the diff small,
7174
rebase-safe, and revertable (one function + CSS).
7275

@@ -96,9 +99,9 @@ read+edit merged, summed diffstat, fallback "N steps" when the sentence would ge
9699
single-member group unwraps and hands the card back **expanded** — no group chrome.
97100

98101
### D6 — Labels: model-written, for every tool that has a story to tell.
99-
`run_command`, `read_file` and `search` all take a required `explanation`: "5–10 words, active
100-
voice, what it does — e.g. 'Find the insertion point in section 10'", and the voice rules require
101-
it. That sentence titles the row; the raw tool text (`read src/agent.js`) becomes the tooltip. UI
102+
`run_command`, `read_file` and `search` all take a required `explanation`: "3–8 words, active
103+
voice, what it does — e.g. 'Find the insertion point in section 10'" (the same range in the prompt
104+
and all three schemas), and the voice rules require it. That sentence titles the row; the raw tool text (`read src/agent.js`) becomes the tooltip. UI
102105
falls back to deriving a label from the arguments when absent (older transcripts, weaker models).
103106
Tense: a small verb map (Run/Ran/Running, Read, Edit, Verify, Search, Create, Delete, Install,
104107
Check ~a dozen) converts imperative → progressive/past; unknown verbs render as-is. No grammar
@@ -175,8 +178,6 @@ Then re-run with grouping toggled off and confirm the flat timeline is unchanged
175178

176179
## 6. Not doing (yet)
177180

178-
- Model-written labels for file reads/searches (derived-only is enough parity; revisit if reads
179-
dominate groups).
180181
- Group state across webview rebuilds / session restore.
181182
- Per-model prompt forks for the voice.
182183
- Collapsing `ask_user`/approvals into groups — deliberately excluded (D4).

extensions/levelcode-ai/agent.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ const SYSTEM_BASE = [
3131
'- Use delete_file to remove an existing file (e.g. during a refactor). To RENAME/move a file, write_file the new path then delete_file the old one. Deletions are reviewable (Keep/Undo) and restorable from the per-turn checkpoint.',
3232
'- Your file edits are APPLIED IMMEDIATELY and the user reviews them afterward in the editor with Keep/Undo — do NOT wait for approval, and do NOT re-edit a file you just edited. Only run_command still needs approval; if the user skips a command, adapt or stop.',
3333
'- Commands that do NOT exit on their own (dev servers, file watchers, tail -f) MUST be run with run_command background:true — it returns immediately so you keep working instead of hanging. After starting one, call read_command_output with the returned id to watch for a readiness/port line (e.g. "listening on :3000") before you test against it. Use a normal foreground run_command for things that finish (builds, installs, tests, git, curl). This pairs with verification: bring the app up in the background, confirm it serves, fix, repeat.',
34-
'- EVERY run_command, read_file and search MUST include "explanation": 3-10 words, active voice, imperative, saying what you are doing and why ("Run the extension unit tests", "Find the insertion point in section 10", "Read the runAgent call site"). It becomes that action\'s label in the user\'s activity view — never omit it.',
34+
'- EVERY run_command, read_file and search MUST include "explanation": 3-8 words, active voice, imperative, saying what you are doing and why ("Run the extension unit tests", "Find the insertion point in section 10", "Read the runAgent call site"). It becomes that action\'s label in the user\'s activity view — never omit it.',
3535
'- Paths are relative to the workspace root. In a MULTI-ROOT workspace (several top-level folders), paths from list_files/search are prefixed with the folder name (e.g. "thin.ly/app/models/link.rb") — use them exactly as shown; an unprefixed path resolves against the first folder. To create a file in a specific folder, prefix its name. run_command accepts an optional "folder" to pick which folder it runs in.',
3636
'- For a multi-step goal, call update_plan FIRST with a short checklist (3-8 short items, all "pending"), then call it again to set an item "in_progress" when you start it and "done" when finished. Skip the plan for trivial single-step goals.',
3737
'- If the goal truly depends on a decision only the user can make (tech stack, scope, where to create files, must-have features), call ask_user ONCE with concise multiple-choice questions (a short header + 2-4 concrete options each) INSTEAD of writing the questions as prose. Put your RECOMMENDED option FIRST and use its description to say why — and, when it matters, what would change your mind. Then act on their answers and do not ask again. Do NOT ask about things you can reasonably decide yourself — prefer a sensible default and proceed.',
@@ -48,7 +48,7 @@ const TOOLS = [
4848
{ name: 'edit_file', description: 'Make a targeted edit to an EXISTING file: replace an exact, unique snippet (old_str) with new_str. Applied immediately; the user reviews it with Keep/Undo. old_str must appear exactly once — include enough surrounding context to be unique.', input_schema: { type: 'object', properties: { path: { type: 'string' }, old_str: { type: 'string' }, new_str: { type: 'string' } }, required: ['path', 'old_str', 'new_str'] } },
4949
{ name: 'write_file', description: 'Create a new file (or fully overwrite a short one) with the COMPLETE content. For edits to existing files, prefer edit_file. Applied immediately; the user reviews it with Keep/Undo.', input_schema: { type: 'object', properties: { path: { type: 'string' }, content: { type: 'string' } }, required: ['path', 'content'] } },
5050
{ name: 'delete_file', description: 'Delete an EXISTING workspace file (e.g. removing a file during a refactor). Applied immediately; the user reviews it with Keep/Undo, and the per-turn checkpoint can restore it. To RENAME or move a file: write_file the new path, then delete_file the old one.', input_schema: { type: 'object', properties: { path: { type: 'string' } }, required: ['path'] } },
51-
{ name: 'run_command', description: 'Run a shell command in the workspace root (or a named workspace folder via "folder" in multi-root workspaces). Requires approval. Pass background:true for commands that do not exit on their own (servers, watchers) so the agent is not blocked — it returns immediately and you read progress later with read_command_output.', input_schema: { type: 'object', properties: { command: { type: 'string' }, explanation: { type: 'string', description: 'REQUIRED: 5-10 words, active voice, imperative — what this command does ("Run the extension unit tests", "Find the insertion point in section 10"). Shown to the user as this action\'s label.' }, folder: { type: 'string', description: 'multi-root workspaces only: the workspace folder NAME to run in; defaults to the first folder' }, background: { type: 'boolean', description: 'true = start it and keep working without waiting (dev servers, watchers, tail -f). Returns immediately with an id; poll read_command_output for its output/status.' } }, required: ['command', 'explanation'] } },
51+
{ name: 'run_command', description: 'Run a shell command in the workspace root (or a named workspace folder via "folder" in multi-root workspaces). Requires approval. Pass background:true for commands that do not exit on their own (servers, watchers) so the agent is not blocked — it returns immediately and you read progress later with read_command_output.', input_schema: { type: 'object', properties: { command: { type: 'string' }, explanation: { type: 'string', description: 'REQUIRED: 3-8 words, active voice, imperative — what this command does ("Run the extension unit tests", "Find the insertion point in section 10"). Shown to the user as this action\'s label.' }, folder: { type: 'string', description: 'multi-root workspaces only: the workspace folder NAME to run in; defaults to the first folder' }, background: { type: 'boolean', description: 'true = start it and keep working without waiting (dev servers, watchers, tail -f). Returns immediately with an id; poll read_command_output for its output/status.' } }, required: ['command', 'explanation'] } },
5252
{ name: 'read_command_output', description: 'Read recent output + status of a command started with run_command background:true. Returns a status header ([running on :3000] / [exited 0] / [stopped]) followed by the latest output lines. Poll this to wait for a server to become ready before testing against it.', input_schema: { type: 'object', properties: { id: { type: 'string', description: 'the id returned by a background run_command' }, lines: { type: 'number', description: 'max recent output lines to return (default 80, max 400)' } }, required: ['id'] } },
5353
{ name: 'ask_user', description: 'Ask the user one or more multiple-choice questions when the goal genuinely depends on a decision only they can make (tech stack, scope, where to put files, must-have features). The user picks by CLICKING — do NOT write questions as prose. Ask ONCE up front with all your questions, then proceed with the answers and never re-ask. Prefer sensible defaults over asking; only ask when a wrong guess would waste real work.', input_schema: { type: 'object', properties: { questions: { type: 'array', items: { type: 'object', properties: { header: { type: 'string', description: 'a 1-3 word tag for the question' }, question: { type: 'string' }, multiSelect: { type: 'boolean', description: 'true if several options can be picked at once' }, options: { type: 'array', items: { type: 'object', properties: { label: { type: 'string' }, description: { type: 'string' } }, required: ['label'] } } }, required: ['question', 'options'] } } }, required: ['questions'] } },
5454
{ name: 'use_skill', description: 'Load an expert playbook (SKILL.md) for a task type, chosen from the "Available skills" list in your system prompt. Returns the skill\'s step-by-step instructions as the tool result — then follow them. Read-only and instant (no approval). Call it once, early, when the goal matches a skill\'s description.', input_schema: { type: 'object', properties: { name: { type: 'string', description: 'the exact skill name from the Available skills list' } }, required: ['name'] } }

0 commit comments

Comments
 (0)