Context hygiene at insert time: result ids, read stubs, the cap, recall
Harness spec 3.0.0 (context.md, loop.json `context`), in session/results.ts, applied by the engine when a result goes into the conversation and never afterwards: - every result is headed by its id ([#0001]); a read also by the path as given, its lines, the file's length and the first 8 hex digits of the content's SHA-256; an empty file says so; - a read of an unchanged file whose lines lie inside an earlier full read is a stub naming it; a list/glob/grep repeated with the same arguments and the same result is "Same result as #…"; - output over 400 lines or 40,000 characters keeps head and tail with the elided line; the full result is kept with the session (a new `results` table in sessions.db, gone with the session); - edit, multiedit, write and apply_patch answer with their hunks under a bracket with the new content's hash; a new file is "Created, N lines."; - recall (new built-in tool) shows any stored result, or a range of it, also after a resume; ids are never reused; - compaction appends the table of the reads still in the conversation to the summary. A stub only ever points at a result still in the conversation, so after a compaction, an /undo or a rewind the file is read in full. compaction.prune is gone: cutting old outputs in place threw the prompt cache away (an old config's key is dropped with a warning). blocks/context.md is in the prompt wherever recall is offered. Conformance runner for the `context` area (11 cases pass). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
28 files changed
+595
-81
No files matched your search
+4
-1
@@ -45,12 +45,15 @@ describe("end to end", () => {
|
||||
// The tool result went back to the model as a tool message with the right id.
|
||||
expect(fake!.requests[1].messages.at(-1)).toMatchObject({ role: "tool", tool_call_id: "c1" })
|
||||
expect(fake!.requests[1].messages.at(-1).content).toContain("1: hello world")
|
||||
// Spec 3.0.0 (context.md): the read is headed by its id, lines and hash; the edit answers with its diff.
|
||||
expect(fake!.requests[1].messages.at(-1).content).toMatch(/^\[#0001 hello\.txt lines 1-1 of 1 sha [0-9a-f]{8}\]\n1: hello world$/)
|
||||
expect(fake!.requests[2].messages.at(-1).content).toMatch(/^\[#0002 hello\.txt sha [0-9a-f]{8}\]\n@@ -1,1 \+1,1 @@\n-hello world\n\+hello lembas$/)
|
||||
// System prompt carries env and the mode.
|
||||
expect(fake!.requests[0].messages[0].content).toContain(`Project root: ${dir}`)
|
||||
expect(fake!.requests[0].messages[0].content).toContain("Permission mode: edit")
|
||||
// knowledge_search/get are offered once any knowledge base has documents, and the suite shares
|
||||
// one LEMBAS_HOME: another file's base must not decide this list (found in the full run).
|
||||
expect(fake!.requests[0].tools.map((t: any) => t.function.name).filter((n: string) => !n.startsWith("knowledge_"))).toEqual(["read", "write", "edit", "multiedit", "apply_patch", "glob", "grep", "list", "bash", "job_output", "job_list", "job_stop", "job_send", "web_search", "web_fetch", "task", "plan_write", "plan_update", "ask_user", "memory", "session_search", "notes_search", "note_view", "note_manage", "skills_list", "skill_view", "skill_manage", "settings"])
|
||||
expect(fake!.requests[0].tools.map((t: any) => t.function.name).filter((n: string) => !n.startsWith("knowledge_"))).toEqual(["read", "write", "edit", "multiedit", "apply_patch", "glob", "grep", "list", "bash", "job_output", "job_list", "job_stop", "job_send", "web_search", "web_fetch", "task", "plan_write", "plan_update", "ask_user", "memory", "session_search", "notes_search", "note_view", "note_manage", "skills_list", "skill_view", "skill_manage", "settings", "recall"])
|
||||
const ends = events.filter((e) => e.type === "tool_end")
|
||||
expect(ends.map((e) => e.type === "tool_end" && e.result.title)).toEqual(["hello.txt · 1–1 of 1", "hello.txt +1 −1"])
|
||||
const sid = store.sessions(1)[0]!.id
|
||||
|
||||
Reference in new issue
Block a user