Harness spec 1.1.0: one plan, prototypes and the library shared; the CLI implements it

The spec: plan_write and plan_update (new, shared, offered in every mode) and
plan_submit (now shared) keep one structured plan — findings, objectives,
phases of tasks — in place of the todo list, which lives on as a former name
of plan_write. The shared system text is one text for both projects, with
variables for what differs; the mode texts, a prototypes block and a library
block are shared. acp.md: the client hands the device what only it knows
(context, library, prototypes), the plan travels as a structure (plan_state),
library calls carry the chat's scope, and a client may rewind a session.
loop.json says its numbers as numbers. Four conformance areas: plan,
prototype, library_scope, toolcall_index.

The CLI: the plan is kept per session in the store and drawn above the prompt
and on the approval card; the prompt is assembled from the spec's texts with
their variables filled; the link reads the instance's instructions,
personalization, knowledge scope and prototype offer, sends the plan as a
structure and answers rewind; library calls to the instance carry the session
as scope; a prototype written in the terminal is saved as a file and named in
the transcript; a tool-call fragment without an index continues the last call;
the default theme is Moria; dead exports and Hermes leftovers removed.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
HomerandClaude Fable 5.1 committed 2026-10-18 04:02:12 +02:00
1 parent 6e70ff46d0
commit 837f38c744
96 files changed
+3259 -527

No files matched your search

+14 -1
View File
@@ -1,6 +1,6 @@
// The names harness spec v1 changed (shared with LLeMbas): question → ask_user, plan_exit →
// plan_submit, websearch/webfetch → web_search/web_fetch, notes → notes_search/note_view/
// note_manage, bash's workdir → cwd, the mode unrestricted → auto. Whatever was written under an
// note_manage, bash's workdir → cwd, the mode unrestricted → auto; and 1.1.0's todo → plan_write. Whatever was written under an
// old name — a stored session, a config file, an agent file, a prompt override — keeps working.
import { afterEach, expect, test } from "bun:test"
import { mkdirSync, mkdtempSync, writeFileSync } from "node:fs"
@@ -35,6 +35,19 @@ test("a call under a former name runs the tool it now is, with its arguments", (
expect(canonicalToolNames(["read", "webfetch", "notes"])).toEqual(["read", "web_fetch", "notes_search", "note_view", "note_manage"])
})
test("a todo call is a plan_write of one phase called Work, its statuses translated", () => {
const r = resolveCall("todo", { todos: [{ content: "Read the code", status: "completed" }, { content: "Fix it", status: "in_progress" }, "Test it", { content: "Old idea", status: "cancelled" }] })
expect(r.name).toBe("plan_write")
expect(r.raw).toEqual({
title: "Work",
phases: [{ title: "Work", status: "active", tasks: [{ text: "Read the code", status: "done" }, { text: "Fix it", status: "doing" }, { text: "Test it", status: "todo" }, { text: "Old idea", status: "dropped" }] }],
})
// Nothing in progress: the phase is pending. An empty list is an empty plan, which the tool refuses.
expect((resolveCall("todo", { todos: ["a"] }).raw as { phases: { status: string }[] }).phases[0]!.status).toBe("pending")
expect(resolveCall("todo", { todos: [] }).raw).toEqual({ title: "Work", phases: [] })
expect(canonicalToolNames(["todo", "read"])).toEqual(["plan_write", "read"])
})
test("the mode unrestricted is auto, wherever a mode is written", () => {
expect(asMode("unrestricted")).toBe("auto")
expect(asMode(" auto ")).toBe("auto")