From 0af13f5a99799ffbda13ad3e1fc063f1fcaa2c4e Mon Sep 17 00:00:00 2001 From: 7Sageer <7sageer@djwcb.cn> Date: Tue, 4 Aug 2026 14:54:29 +0800 Subject: [PATCH] feat(agent-core-v2): transcribe context-ownership spine view from SpineCodex Replace the rule-manual text with the upstream rewrite (SPINE_JIT_INSTRUCTIONS, through 97f4eb1a): node boundaries derive from context ownership and lifecycle, shared context lives in the lowest common ancestor, and execution rules cover one transition per turn, batching, and transition attribution. Local adaptations: spine_open/next/close tool spellings, no code-mode exec clause, and no trim segment (upstream leaves SPINE_TRIM_INSTRUCTIONS empty pending approved copy). --- .../src/agent/spine/instructions.ts | 173 +++++++++--------- 1 file changed, 88 insertions(+), 85 deletions(-) diff --git a/packages/agent-core-v2/src/agent/spine/instructions.ts b/packages/agent-core-v2/src/agent/spine/instructions.ts index c1efb3d7d..05c437c30 100644 --- a/packages/agent-core-v2/src/agent/spine/instructions.ts +++ b/packages/agent-core-v2/src/agent/spine/instructions.ts @@ -3,9 +3,16 @@ * system prompt when spine is enabled, plus the `appendSpineView` splicer and * the `~/spine_instruction.md` override loader. * - * The text is transcribed from the upstream protocol (with the `spine.trim` - * guidance removed, since trim is not implemented in this milestone) so the - * model sees an identical contract. `loadSpineViewOverride` returns the + * The text is transcribed from the upstream `SPINE_JIT_INSTRUCTIONS` + * (codex-rs/core/src/spine/instructions.rs, context-ownership rewrite through + * 97f4eb1a) so the model sees an identical contract, with three local + * adaptations: the control tools keep their local `spine_open` / `spine_next` + * / `spine_close` spellings (upstream writes bare `open` / `next` / `close`); + * the code-mode `exec` batching clause is dropped (no code mode in this + * repo); and no trim segment is appended because upstream's + * `SPINE_TRIM_INSTRUCTIONS` is intentionally empty pending approved copy — + * trim semantics live in the `spine_trim` tool description. + * `loadSpineViewOverride` returns the * `` block extracted from `~/spine_instruction.md` (`undefined` * when the file is missing, unreadable, empty, or carries no block); the * caller owns the result — there is no module-level cache, so co-resident @@ -16,94 +23,90 @@ */ export const SPINE_VIEW = ` -All work must be Spine-managed to make every test-time step produce efficient, -explicit task progress: the Spine tree enables scaling by recursively -decomposing tasks into scoped nodes and merging them through compact -continuation memory, while just-in-time context compilation turns each node's -local working context into that memory to keep scaling cost-efficient. +All work must be Spine-managed. Structure the tree around context ownership and +lifecycle. Keep each body of working context in the lowest node whose scope +spans all work that needs its exact detail. Once remaining work can continue +from compact continuation memory, let that memory replace the full detail. +Keep routine bounded work lightweight, while allowing difficult or open-ended +work to autonomously scale test-time compute toward the best attainable +outcome. -Use Spine as a recursive task-boundary workflow. The Spine tree is the semantic -scope structure for task decomposition and context compilation. Preserve node -hierarchy carefully: every transition must route work to its correct child, -sibling, parent, or ancestor scope. +Recursive policy: -1. Start task work with \`spine_open()\` under the startup node. -2. At every node, maintain orientation to the big picture: the current node, its - parent goal, its role in the parent decomposition, completed siblings, - remaining siblings, and where the next work belongs. -3. If the current node is unclear, too broad, or not concrete enough to verify, - use \`spine_open()\` - only when that goal is a true child of the current node. Use the child to - gather evidence, clarify constraints, plan, or decompose the work. Repeat - recursively until the next work can be executed in a focused, specific, - verifiable leaf node. -4. When an exploration/planning/decomposition node is complete, use - \`spine_next(, memory)\` if the next work is a true sibling - under the same parent. Use \`spine_close(memory)\` if the distilled result should - return to the parent before deciding the next node. -5. Use \`spine_next(, memory)\` for remaining sibling work under - the same parent. \`spine_next\` finalizes the current node and continues in a fresh - sibling with distilled continuation memory. -6. Use \`spine_close(memory)\` when the current task node is complete enough for its - parent or later siblings to continue correctly. \`spine_close\` is the upward merge - operation: it returns compact state to the parent, not the local trace. If - the next work belongs to an ancestor's scope, close upward until the correct - parent scope is reached, then continue with \`spine_next\` or \`spine_open\`. +Begin every top-level task with \`spine_open(summary)\` while the current root +epoch is live. Root epochs are synthetic containers and cannot be closed. The +\`summary\` argument to every \`spine_open\` or \`spine_next\` call must +concisely identify the node's concrete scope and intended outcome. -Optimize the tree for correct progress per unit of working context. Node summaries -should name concrete goals. Node memory should be the minimal sufficient context -needed for correct continuation. +Then solve each node recursively. Derive node boundaries from context ownership +and lifecycle. Keep work in one node only while its required working context +shares a common ownership scope and lifecycle. If achieving one outcome spans +multiple independently compactable bodies of local context, decompose the +associated work along those ownership and lifecycle boundaries into direct +children, even when all of it serves the same semantic outcome. -Hierarchy and placement rules: +A useful child owns a concrete, independently meaningful body of work and the +local working context needed to complete it. That context must have an +independent lifecycle: its exact detail can become unnecessary to remaining +work once the child's result is stable and its compact memory preserves the +state required for continuation. A useful decomposition may consist of a single +exploratory child when resolving or bounding a focused uncertainty will +accumulate such independently compactable local detail. -* Before any \`spine_open\`, \`spine_next\`, or \`spine_close\`, identify the current node's parent goal, - the current node's role in that parent, and whether the next work belongs to - the current node, the same parent, or an ancestor scope. -* Use \`spine_open\` only when the new goal is truly a child of the current node. -* Use \`spine_next\` only when the new goal is truly a sibling under the same parent. -* Use \`spine_close\` when the remaining work belongs to the parent or to an ancestor's - scope; if necessary, close upward before continuing. -* If multiple ancestor levels must be exited, close one level per assistant - response until the correct scope is reached. -* Every \`spine_next\` or \`spine_close\` memory must preserve compact big-picture state: - current position, parent goal, completed siblings, remaining siblings, key - decisions/evidence, unresolved risks, and why the transition is - child/sibling/parent/ancestor-level. +Keep the minimum context whose exact detail is needed by multiple branches in +their lowest common ancestor for as long as those branches need it. Keep context +needed by only one branch in the child that owns that work. A child boundary is +useful only when compact memory lets remaining work continue without broadly +reconstructing the child's working context. Avoid node boundaries that cause +repeated reloads of unchanged working context or fragment one ownership and +lifecycle scope without enabling independent compaction. -Conventions: -* A single assistant response may batch ordinary task-progress tool calls with at - most one Spine transition. Never include more than one of \`spine_open\`, \`spine_next\`, or - \`spine_close\` in the same assistant response. -* \`summary\` is the concise goal summary for the node being opened: for \`spine_open\`, - the child goal; for \`spine_next\`, the next sibling goal. -* \`memory\` is concise continuation state with progress, big-picture position, - decisions, evidence, constraints, risks, remaining work, and critical - references. -* Optimize for compact recoverability: preserve the smallest sufficient state - that lets future work continue correctly without replaying this node. Treat - inherited context and assembled child memory as already available, then write - only compact deltas and current state needed to continue correctly. -* Use \`spine_open\` to start child work, \`spine_close\` to return completed evidence to the - parent, and \`spine_next\` to finish the current node and continue from distilled - memory in a fresh sibling. -* \`spine_tree\` is read-only; actual transitions happen only through \`spine_open\`, - \`spine_close\`, and \`spine_next\`. -* Spine transitions change task scope, not communication state. A final response, - status update, or user-facing report does not by itself require a \`spine_open\`, - \`spine_next\`, or \`spine_close\` call; never create a reporting node or perform - a transition solely for delivery. -* Root-epoch ids such as \`1\` or \`2\` cannot be closed. The initial \`1.1\` is a - startup work node, not a concrete task node; use \`spine_open\` before doing task work. -* \`\` gives current node orientation; \`\` gives - continuation memory from closed work. -* \`[U#]\` anchors refer to numbered user requests. When writing memory, preserve - \`[U#]\` anchors for user requests that still matter. Do not maintain a separate - request-status ledger when the relevant intent is already captured in ordinary - continuation state. After \`\` continuity or a node transition, - report only new results, blockers, or requested details. -* Place user-facing replies where they are most useful: local intermediate - results may wait for later merge, while complete conclusions, blocking status, - or decisions needing user input should be surfaced promptly. +When decomposing, choose the smallest useful set of direct children, solve each +recursively, and continue in the parent from their compact memories. Open a +child as soon as its context ownership and lifecycle are clear, before its local +detail accumulates in the parent. Strictly preserve correct parent-child +relationships, and recurse only until the active work and its working context +have a clear owner in a focused leaf. + +Lifecycle rules: + +* \`spine_open(summary)\` enters a direct child and begins the lifecycle of the + working context it owns. Inherited context remains visible to every + descendant, so opening a node focuses ownership but does not reduce visible + context; compression is realized only after \`spine_close\` or \`spine_next\`. +* Finalize a node only when its owned work is complete or precisely bounded, + its result is stable, and continuation no longer needs its full working + context because compact memory preserves all required state. +* \`spine_close(memory)\` finalizes the current node, replaces its working + context with compact continuation memory, and returns to its immediate + parent. Use it when the remaining work and context belong in that parent. +* \`spine_next(summary, memory)\` performs the same finalization and enters a + true sibling under the same parent. To return to a higher ancestor, close + one level at a time and reassess after each transition. +* Follow the tool's Node Memory contract. Runtime preserves user messages and + child memories, so use Node Memory only for the additional + continuation-relevant state required by that contract. +* Treat \`[U#]\` anchors as internal Node Memory references. Use them only when + needed to disambiguate changes in user intent, and avoid exposing or + discussing them in ordinary user-facing responses. + +Execution rules: + +* Once context ownership and lifecycle determine the node boundaries, complete + work in as few assistant turns as practical while minimizing total context + pressure, roughly the sum of visible context across assistant turns. Issue + all compatible ready tool calls in the same turn. Use at most one Spine + transition (\`spine_open\`, \`spine_next\`, or \`spine_close\`) per turn. + When compatible ready work exists for the resulting node, include the + transition and that work in the same batch. +* When a transition and ordinary tool calls are issued together, the transition + applies to the current node's prior ReAct history, while the ordinary calls + execute in and belong to the resulting node. +* \`\` provides continuation memory compiled from finalized work. +* Spine nodes are ownership scopes for work and working context with + independently completable lifecycles, not user-response boundaries. Answer + the user as soon as useful, and do not create a node merely to report + progress. `;