@spinejit/pi-spinejit

SpineJIT context management for Pi, backed by the portable Spine SDK.

Packages

Package details

extension

Install @spinejit/pi-spinejit from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:@spinejit/pi-spinejit
Package
@spinejit/pi-spinejit
Version
0.1.2
Published
Oct 29, 2026
Downloads
427/mo · 233/wk
Author
ghabix
License
Apache-2.0
Types
extension
Size
298.4 KB
Dependencies
2 dependencies · 2 peers
Pi manifest JSON
{
  "extensions": [
    "./dist/pi/extension.js"
  ]
}

Security note

Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.

README

Pi SpineJIT

SpineJIT context management for Pi, backed by the portable Spine SDK. Install one package; npm installs the SDK and host dependencies automatically:

pi install npm:@spinejit/pi-spinejit

Version 0.1.0 is developed and tested against Pi 1.1.0. The last state developed against Pi 0.87.1 is tagged pi-0.87-final.

Recommended Pi plugins

We also publish these Pi plugins, which work alongside this one:

Package Source Description
@spinejit/pi-background-job GhabiX/pi-background-job Background jobs and output monitors for Pi: exits and new log lines wake the agent by themselves.
@spinejit/pi-btw-cached GhabiX/pi-btw-cached /btw side questions for Pi: ask about the main session while it runs, on the same prompt-cache prefix; runs no tools, saves nothing to history.
@spinejit/pi-compact-tree GhabiX/pi-compact-tree Compact process tree for Pi's terminal UI: tool calls fold into one-line summaries and thinking into titles, with a borderless input and a one-line footer.
@spinejit/pi-timeout-policy GhabiX/pi-timeout-policy One timeout policy for Pi's foreground tools: 60s when unset, 2h at most, and timeouts for grep and find too.
pi install npm:@spinejit/pi-background-job
pi install npm:@spinejit/pi-btw-cached
pi install npm:@spinejit/pi-compact-tree
pi install npm:@spinejit/pi-timeout-policy

Migrating from @spinejit/spine-plugin

The public package is now @spinejit/pi-spinejit. Stop the current session, then replace the old installation:

pi remove npm:@spinejit/spine-plugin
pi install npm:@spinejit/pi-spinejit

Use --local on both commands for project installations, then restart Pi. Do not load both names together. Update pinned package settings and imports to the new name; all exported subpaths remain available. SDK and host names stay the same.

Spine plugin prompt configuration

Pi loads its prompt configuration from spine.toml in @spinejit/spine-sdk, the SpineConfig every host plugin shares. This file overrides the embedded spine-core prompt defaults, so updating the shared WASM artifact alone does not update Pi's configured wording.

Each extension activation reads one configuration snapshot for its tool catalog and default runtime. Tree navigation reuses it; /new and reload read the file again. A custom runtime factory remains responsible for its own configuration.

The default node body is empty. Each projected <spine_node> still includes its identity, summary, and stable status; the global JIT prompt explains those boundaries once. An explicit nonempty prompt.node remains supported. Tool descriptions retain the operation and returned-memory guidance.

Pi and SpineCodex now use the v6 recursive-call policy: each branch owns an outcome, Close returns one level, and new work begins under its direct owner. The global policy and Open/Close/Next descriptions are synchronized, with host tool names adapted. Node bodies remain empty; Spawn and parameter schemas are unchanged. The v6 Pi training and unseen-task PoC passed the exercised ownership and return cases; repeated memory and broader lifecycle coverage remain limits.

Pi SDK installation and updates

This package is the SDK-backed Pi SpineJIT extension. Its Pi manifest and package export both select dist/pi/extension.js, which is included in the package. The native Pi implementation is a separate project.

From this repository's root, build the TypeScript packages in dependency order:

npm run build -w @spinejit/spine-sdk
npm run build -w @spinejit/spine-host
npm run build -w @spinejit/pi-spinejit
pi install /absolute/path/to/spine-plugin/packages/plugin

Users install only the Pi package; npm resolves the matching SDK and host dependencies automatically:

pi install npm:@spinejit/pi-spinejit

Local directory installation and packed installation use the same compiled entry. After source changes, rebuild these packages, then /reload or restart Pi and start a new session. A spine.toml wording change needs extension reactivation, but does not require a TypeScript or WASM rebuild. Normal Pi 0.87.1 /new also reactivates extensions; a tree navigation is not a reload.

The package depends on matching SDK and host packages and Pi 1.1.0. In a local checkout, workspace dependencies must already be installed. A packed consumer must resolve those dependencies too; the plugin tarball does not bundle them. Spawn's default child invocation passes the currently loaded extension module, so the formal dist entry is also the explicit child entry.

SpineTree / SDK session modes

The same Pi configuration may load this package, navigation, and the SpineTree L1/native artifact. At session_start, the plugin synchronously queries L1 on pi.events channel spinetree:mode with { cwd, sessionId, mode? }. Only L1 owns discovery; no responder means sdk. The decision is frozen for that session. Creating a tree mid-session takes effect in a new session, not during the current run. Both extension load orders are supported.

In st mode every spine_* tool is re-registered as hidden, so neither the model nor codemode/ctx.executeTool() can reach it. SDK context, sampling, compaction, ownership claims and navigation are inactive. Work uses shell st and delegate/job workers; their branch caps are the results. In sdk mode the existing SDK tools, context projection, compaction, Spawn and navigation remain the active path. An SDK conversation is not migrated into a st conversation.

Compaction-owner conflict checking occurs at SDK session_start, after mode selection, rather than factory activation; st sessions never claim SDK ownership. A conflicting SDK compaction configuration is still invalid and must not run.

Runtime composition

extendSystemPrompt(base) composes an original host base with enabled Spine prompt sections. Pass the original base for every call, not an earlier composed result. The host text is preserved as supplied, including any literal examples of Spine tags. Pi's sampling hook receives fresh original system options and performs this composition once for the request.

Local development build

The development spine-core source is fixed by core-source.json as SpineCodex revision cb01f18b0113ada388b0ede69b36c1194513a240 plus the versioned patch provenance/spine-core-cb01f18.patch. The declaration records the full core file inventory and hashes, including prompt composition fixes and the v6 configuration. It does not claim those changes are in the upstream commit.

Build with the repository's scripts/build-node-wasm.sh, an explicitly selected shared Cargo target cache, and wasm-bindgen 0.2.127. The script produces packages/sdk/wasm/node/spine_wasm*, loaded by packages/sdk/dist/node.js. The script verifies the declared source before and after its locked Cargo build. See the repository README for source reconstruction. Build evidence is recorded in tasks/sdk_review_branch_e2e_20260928_1232/evidence/core-provenance/. No release or publication is implied by this local development build.

Provider message ordering

Spine items stay at their projected positions in the conversation. Node descriptors, memory, births and arrivals are Pi custom messages, which Pi sends to every provider as user messages in place; kept replies are assistant messages. None of them is a system message, so no provider moves them into the initial system content, and opening a node only appends to the request. A closed node shows its memory first, then the user messages, replies and arrivals it keeps, so a kept reply never reads as an answer given without the work behind it.

Sampling boundary

One Spine sampling is one Pi agent-loop model request. It begins in the context hook, after the request context is published and materialized, and ends at turn_end, which Pi emits on every path, including run failures. before_provider_request is not a sampling boundary: Pi's cache warmer replays the last request with maxTokens: 1 through that hook without a turn, while a tool call runs (cacheWarming: "streaming") or after the run settles ("idle"). Spine leaves those replays alone.

Durable message order

Pi 0.87.1 can persist context-only custom messages after a turn without calling extension message handlers. Before admitting a user or custom steering/follow-up message, the plugin admits that durable tail first. Context preparation also reconciles the tail. This preserves source order across sampling commits and recovery, including a silent custom update followed by a queued custom message. Assistant and tool-result events retain normal sampling order; they do not trigger full replay while Spawn terminal staging may still be uncommitted.