# Agent Instructions

- Keep independent domain modules under `lib/`, mirror every domain with a same-named file under `tests/`, place cross-domain architecture checks in `tests/invariants.test.ts`, and keep `index.ts` as a minimal composition/public-export boundary.
- Keep the extension opt-in and preserve clear attribution to SKILL.state wherever the inherited explicit-state approach is described.
- Preserve Pi's native tool loop and complete inspectable session trace; project completed-run history only at user-run boundaries. Retain persistent and current-run context-bearing custom messages from other extensions, plus the complete current-run trajectory, except State Flow's own validation feedback when it is represented separately.
- Expose one canonical materialized state shape across global, CWD, and session scopes with exactly `artifacts`, `contract`, `working`, and `response`; the first three are flexible semantic objects and the fourth is the latest complete user-facing answer string where applicable.
- Key artifacts directly by their source path. Model-visible artifact entries require only a non-empty `description` plus optional forward-compatible metadata; runtime-owned freshness evidence (`sourceHash`, `compilerRevision`, `compiledAt`) belongs in the scope `meta.json` provenance registry, never in projected semantic state. Retired embedded `hash`/`compiler`/`compiled_at` fields remain readable compatibility evidence and are stripped from model projection.
- After local activation and before the next enabled inference, discover regular lowercase `*.md` files recursively beneath the configured Knowledge repository root; use canonical absolute paths, hash opaque source bytes and retain their byte counts without decoding or retaining bodies, skip symlinks, and never traverse outside that canonical root. Treat the current candidate set plus explicit removals as generic global artifact input without invoking Knowledge validators. Materialize removals deterministically as runtime-owned global transitions without rereading missing bodies or requesting model compiler output. Never reserve Knowledge document names, provide built-in Knowledge templates, or implement `save_knowledge`.
- Derive artifact freshness per available evidence: a new source always requires compilation, a matching `sourceHash` or `compilerRevision` detects its own change, malformed present evidence fails closed for the capability that depends on it, and missing evidence degrades to an unknown-but-usable artifact rather than corrupt state or a migration. Never treat `compiled_at` as a correctness signal. Plan acquisition from path/hash identity without source bodies, project stale global candidates as runtime-owned `artifact_invalidations` containing only `{path, reason}`, and publish accepted compilation semantics plus matching provenance in one durable cohort.
- Correlate successful exact-path reads with the current ordinary global invalidation plan. Require each acquired stale source to have a compact compiler output at the same path in a global transition, reject model-authored provenance fields, and record the runtime-observed source hash plus current ordinary compiler revision in the global provenance registry. Compile routing descriptions by default, never raw Markdown or a full-file summary; preserve uncertainty and reserve richer compilations for reusable operational semantics.
- Apply one materialized-first acquisition policy to every source: read only for a concrete relevant gap not covered by a sufficient compilation, an exact-source operation including edits, evidenced invalidation, contradiction/failure reconciliation, explicit request, or selection by bounded maintenance. New sessions, routine recall or activation, reassurance, and an index or description alone are not reasons to read. Changed hashes require rereading; prefer the smallest sufficient read.
- Keep artifact maintenance opt-in, low-frequency, and side-effect free until a selected source is acquired. Select only otherwise-fresh artifacts old enough for maintenance, rank missing/unparseable `compiled_at` first then oldest timestamp and path, and enforce strict per-cycle read-count and source-byte ceilings. Treat source bytes as the conservative source-token upper bound. Never let maintenance displace correctness invalidation; use explicit invalidation refresh for full rebuilds and never mutate source files.
- Load optional agent-level `state-flow.json` once per extension load/reload. Its `directory` selects the state store, `autoStart` defaults false for genuinely new sessions, and `remotePublication` selects `off`, `turn-end`, or compatibility `transition`. State Flow always owns durable memory while enabled and global semantic memory is always available; these are invariants, not configuration switches. Keep runtime configuration and provenance outside model-patchable semantic state.
- Keep runtime configuration and provenance separate from model-patchable semantic state. Persist session `config.json` for enablement/projection settings and `meta.json` for lineage, counters, branch identity, durable base, publication, migration metadata, and session-scope artifact provenance; global and CWD scopes own their artifact provenance in scope `meta.json`. Neither participates in scope overlay. New Pi checkpoints contain only a durable revision pointer, or `{disabled:true}` when no durable runtime exists on that branch. Preserve exact Git hashes for Git-backed revisions and give file-only current-cohort references an unambiguous distinct identity; file references use `file:<64 lowercase hex>`, bind the store root and complete scoped/runtime cohort, and must not pretend to provide arbitrary cold or branch history. Operationally unavailable references (including expired file cohorts, missing Git, and publication exclusion) retain selection rather than falling through to older disabled markers; malformed immutable targets remain a distinct recovery case; they are not a parallel authoritative semantic or config/meta store. Emit a disabled marker only from proven pre-runtime branch provenance; missing/invalid revisions and failed restoration do not establish that permission. Predecessor checkpoint formats are read-only migration input. Validate immutable pointer targets before acquiring the live publication basis; transient publication failures preserve the selected retry reference rather than choosing older semantic state. In Git mode, runtime `revision: "self"` resolves to the commit owning the config/meta pair, not an unrelated later repository commit. File publication uses explicit `publication: "files"` provenance and resolves the exact complete live cohort instead of claiming a Git owner. Use a distinct `meta.temporalRevision` when a runtime-only write selects older semantic scopes, so stop or lifecycle persistence does not rewind another branch's live files. Persist publication intent as unconfirmed before pushing; reconcile that exact existing commit after restart rather than embedding an impossible self-hash or inventing semantic history.
- Overlay materialized state recursively in `global → cwd → session` order. Scope-local deletion removes only that scope's key so a lower-scope value becomes visible again; scope never changes instruction authority. Route branch/run-local continuation to session, project-local reusable state and Skill artifacts to CWD, and cross-project reusable state to global.
- Reserve `state` for the runtime materialized semantic view. For each scope, current state is exactly `materialize(checkpoint.json, patches.jsonl)`: an older anchored checkpoint plus its ordered tail of at most seven materially effective semantic patches. On overflow, apply the oldest patch into the checkpoint, advance its `through` boundary, remove it, and append the new patch. Never truncate unapplied replay records or replay patches over an already-current snapshot.
- Give every accepted semantic transition one opaque identity shared by all affected scope records, with explicit active causal lineage. A branch-local position can order identities but never acts as a global counter, substitutes for identity, or merges forks. Unchanged scopes contribute no record and remain unchanged at that boundary. Adopt revision-proven inherited streams at a new session origin without rewriting their checkpoints/tails; pre-origin coordinates are not one shared clock. A restored branch adopts current proven live shared streams it does not modify at a fresh origin while preserving its selected session layer; a shared scope the accepted transition actually changes must still match its selected basis or fail closed naming that scope. Reconciliation adoption is not a fabricated semantic transition, parent link, or retry loop. True semantic no-ops and origin adoption do not advance semantic history.
- Define `state[n]` and `state.global[n]`, `state.cwd[n]`, `state.session[n]` at the same nth previous accepted transition boundary in the active lineage, never the nth local patch of each scope. Guarantee offsets zero through seven once the lineage has seven proven transitions; report earlier-than-origin history as unavailable for new/migrated lineages and reject offsets beyond seven on the hot interface. Reconstruct scopes at one target before overlaying them.
- Keep historical reads lazy through the smallest runtime/model read interface. Normal inference gets only current effective state and useful bounded compact transition context, never eight full snapshots. `patch_state` is the sole semantic mutation tool. `read_state` exposes one cached effective/global/CWD/session projection at offset 0–7, defaulting to effective/0; it returns the exact boundary with semantic state and never publishes, appends a checkpoint, or advances history. Both tools follow branch enablement and host tool restrictions; the patch barrier blocks reader siblings too. Live/cached checkpoint plus tails own the hot path; use Git for branch restoration and explicit cold inspection, not to rebuild current state on every inference.
- Store runtime state in its own directory with optional Git durability, defaulting to `state-flow/` beneath Pi's configured agent directory (`~/.pi/agent/state-flow/` normally), independently from the Knowledge Markdown source root. Use exactly these owned paths: `checkpoint.json`, `patches.jsonl`, and `meta.json` for global; `<cwd-key>/checkpoint.json`, `<cwd-key>/patches.jsonl`, and `<cwd-key>/meta.json` for CWD; `<cwd-key>/<session-key>/checkpoint.json`, `patches.jsonl`, `config.json`, and `meta.json` for session. Do not create `.state-flow`, `scopes`, or another storage/history namespace. Mirror Pi's native CWD session-directory encoding and JSONL-basename session key (deriving `<header timestamp>_<UUID>` for in-memory sessions), while retaining separately verifiable canonical identity provenance in owned state. Keep the UUID authoritative, reject unsafe segments and mismatches rather than selecting another scope, and use CWD checkpoint ownership to fail closed on Pi-name collisions.
- Migrate legacy current `state.json` losslessly into an initial anchored checkpoint with an empty tail; current snapshots are the sole semantic recovery basis, independent of the presence or validity of explanatory journals, including historical revision reads. Preserve only proven history, remove obsolete files within the successful scoped migration, and never retain two authoritative formats. Exercise migrations in temporary repositories rather than modifying the user's active Knowledge data during development.
- Read and write only regular non-symlink State Flow-owned files at those exact paths, publish each file by same-directory atomic rename, preserve arbitrary repository contents, and classify ownership exactly; never use repository-wide staging. Retain opaque source bytes for file identity and rollback, not decoded-text reconstructions. Use validated structural JSON equality for in-process semantic comparisons; reserve cryptographic hashes for compact identities that cross inference, persistence, process, or source-freshness boundaries. Serialize cooperating Git publications through a common-Git-directory publication lock; low-level file helpers require caller exclusion. Recheck prepared bases before each replacement/deletion and restore only bytes still matching the publisher's own output. Preserve detected concurrent changes and report unresolved rollback conflicts; do not claim kernel-atomic multi-file CAS against nonparticipating writers. Markdown discovery uses its independently configured source root, defaulting to `knowledge/` beneath Pi's agent directory; a storage-root override must not redirect source discovery.
- At instance initialization resolve the repository, CWD key, and session key; load each scope's anchored checkpoint and tail, materialize at the selected temporal boundary, then overlay `global → cwd → session`. Install cached view and publication basis atomically only after successful restoration/initialization; unavailable publication is an error, not a semantic no-op. Preserve the selected revision across transient restore failure so an explicit start can retry it. A genuinely new session gets an empty session layer and inherits only global/CWD values; it must never reuse another same-CWD session layer.
- Bind every loaded scope and active Pi branch/checkpoint to the corresponding State Flow Git revision. Resume and tree restoration must recover branch-correct runtime config and semantic layers from that revision without blindly importing Git `HEAD`; reading an older revision must use object-level Git reads and never reset or check out the shared repository worktree.
- Every accepted semantic change, including session-only and response-only changes, atomically updates affected checkpoint/tail pairs and temporal metadata and creates one immediate local Git commit when Git is available; each commit stages the complete non-ignored worktree delta (`git add -A` semantics, including manual deletions) before overlaying exact prepared State Flow outputs, respects `.gitignore`, keeps State Flow-owned active files under compare-and-swap protection, and synchronizes the caller-visible index to the committed tree. `remotePublication` is branch runtime policy: `turn-end` queues only the newest accepted target for asynchronous non-interactive push, `off` remains local-only, and `transition` preserves synchronous legacy behavior. Queue state is operational metadata beneath the Git common directory, not semantic history; use exact targets, destination identity, symlink-safe atomic CAS, descendant-only coalescing, cross-process worker leases, restart recovery, and truthful failure diagnostics. Remote failure never rolls back accepted state or regenerates an answer. A repository with no remote is intentionally local-only; only Git executable `ENOENT` authorizes file-only mode.
- Register `patch_state` as the sole model-authored semantic mutation protocol. It accepts optional fixed `global`, `cwd`, and `session` semantic patches plus optional `final:true`; require at least one scope or `final:true`, reject unknown fields, `final:false`, empty supplied scopes, material no-ops, and the retired `{scope, patch}` / `unchanged` grammar. Validate every supplied scope against one causal basis and publish it all-or-nothing with one identity, temporal boundary, and durable cohort. Never accept model-authored `response`.
- Treat every semantic `patch_state` as a strict inference barrier. Give it sequential execution mode, inspect Pi's synchronized current assistant message during tool preflight, require exactly one `patch_state` call in that response, and block every sibling tool call before execution. Every enabled iteration begins terminal-ineligible; only a successful call containing `final:true` latches eligibility for the next accepted `turn_end`, without stopping later reasoning, tools, or patches. If the model attempts terminal prose before eligibility, discard that transient draft and issue a hidden same-run instruction for the first two attempts; the third attempted terminal completion ends steering with one concise error while preserving committed state, enablement, and the rejected-response boundary. Failed patch calls do not consume this ephemeral three-attempt budget. A subsequent legal patch remains possible, and only a later accepted ordinary answer is reconciled.
- Reconcile `response` only from the actually accepted ordinary assistant answer at `turn_end`; it remains runtime-owned. State Flow has no terminal HTML-comment mutation protocol and does not parse generic service comments. A draft intercepted for pending turn resolution is not final, must never reach `response`, and may be followed by `patch_state` in the same unfinished run. Other extensions retain ownership of their own comments and output handling.
- Treat terminal state as a decision-relevant handoff, not narration: retain source-addressed reusable operational knowledge in `artifacts`; compile stable requirements, confirmed decisions, rejected approaches, and interface commitments into `contract`; retain observations, validation, failures, current domain state, unresolved work, interaction consequences, and exact continuation in `working`. Preserve relevant completed prerequisites and verified outcomes while removing obsolete progress narration; reconcile only information affected by the run and relevant existing commitments, not every scope or repository surface.
- Preserve active constraints, unresolved questions, consequential negative results, and the next discriminating check before compression. Distinguish observations, user requirements, assistant decisions, and hypotheses; do not promote assistant conclusions to user requirements. Retain useful source locators and validity conditions for consequential facts without mandatory per-value metadata. Keep rejection reasons and reconsideration conditions. Reconcile contradictions through evidence or user clarification instead of silently overwriting established constraints or observations; retain unresolved conflicts and decision-relevant hypotheses as uncertain. These are protocol obligations, not deterministic semantic validation gates.
- Treat `working` as last observations, not a live workspace. Revalidate volatile facts before consequential actions; after interruption or branch navigation inspect relevant external effects before repeating operations. Failed state commits and restored memory do not undo tool effects. Missing evidence proves neither success nor absence of effects: retain uncertainty and the next check. Keep revalidation targeted, without action ledgers or runtime freshness/rollback guarantees.
- Treat each successful `SKILL.md` read as CWD artifact acquisition using the finalized tool-execution arguments after mutable interception: require a non-empty compiler output in the next `patch_state` call under `cwd.artifacts[exactReadPath]` with `description`, `kind: "skill"`, and a flexible non-empty `compilation` object; hash the executed source bytes and record runtime-owned `sourceHash` plus `skill-artifact-v1` `compilerRevision` in the CWD provenance registry; reject missing, unhashable, malformed, or forged freshness data; replace the complete prior Skill artifact and its provenance entry on refresh so obsolete evidence cannot survive. `contract.compiled_skills` is retired and rejected; migrate useful legacy entries into artifacts while preserving behavior and marking fallback hashes unverified when the source is unavailable.
- Make the model audit and optimize complete state at every handoff: reorganize inefficient structure, merge fragmented facts, compress history into conclusions, and delete stale, completed, redundant, or low-value keys while preserving active commitments and evidence.
- Accept omitted semantic fields inside each supplied scope patch, but reject empty supplied scopes; when no state change is needed require explicit `{final:true}` without inventing bookkeeping. This final-only call changes only ephemeral terminal eligibility and creates no semantic transition, identity, temporal step, or Git commit. Always require an accepted non-empty answer, which runtime owns as session `response`. A changed response is a semantic transition; identical complete semantic state finalizes lifecycle without a patch, identity, or temporal step. Semantic usefulness and optimization remain protocol-owned because deterministic validation cannot prove them.
- Agent-level opt-in `logging` appends local JSONL diagnostics for rejected `patch_state` attempts and terminal drafts intercepted while turn resolution remains pending. Every rejected call retains its exact attempted arguments plus the precise error and, when available, tool identity, call id, resolution attempt, and terminal-eligibility state; successful patches are never logged. Preserve exact text blocks only where useful, reduce other blocks to structural identity, never duplicate reasoning bodies, and keep logging outside semantic state, scope metadata, checkpoints, and publication. Logging failure emits at most one warning and never changes resolution, enablement, or accepted state.
- Recursively materialize patches immediately; empty objects preserve, nested object-key `null` deletes, and `null` anywhere in semantic state including arrays is invalid. This prohibition does not apply to runtime envelopes such as an origin's null parent. Persist runtime-normalized replay patches that exactly reproduce accepted state, including complete artifact replacement; runtime-owned provenance is stored in scope `meta.json` and is not part of semantic replay.
- Do not impose project schemas, state or patch byte caps, dynamic growth pressure, observation envelopes, action authorization, action ledgers, or state-size limits.
- Rotate the turn-stable specification on every user-initiated run, while runtime-triggered turn-resolution continuation remains inside that same run. Keep user-controlled specification text at user authority: never interpolate it into the system prompt; repeat it only in synthetic user runtime context. Treat materialized state in that message as fallible assistant-produced data whose transport role does not elevate it into user instructions.
- When enabled inside an existing session, retain Pi's active context for exactly one complete bootstrap run and require its `patch_state` resolution to migrate all future-relevant context.
- Restore extension state from the active Pi session branch's checkpoint and recorded State Flow revision, not the full session entry list or current Git `HEAD`, on both startup and successful in-session tree navigation.
- Render compact status as accent `state-flow` plus dim `#<step>`. `/state-flow-status` must distinguish session config/meta from semantic temporal materialization; show the CWD and session keys, step, active temporal head and State Flow revision, available hot-history depth, per-scope artifact/tail counts, discovered global Markdown stale reasons, and pending publication; and label global, CWD, session, and effective materializations without reading or dumping source bodies beyond path/hash discovery needed for freshness diagnostics. Distinguish selected retained tail counts from active history depth; inherited tails may predate the origin. When temporal materialization is unavailable, report unknown counts/freshness and unavailable state rather than inventing empty projections.
- Explicit `/state-flow-start` creates the State Flow directory when missing and returns after locally usable runtime acceptance for normal `turn-end`/`off` policy. If Git is installed, initialize an exact-root Git repository when needed, including a populated file-only store, preserving all existing bytes and unrelated files; an ancestor repository is not a valid substitute. Skip full predecessor-format migration planning only when all exact legacy snapshot names are absent, and defer Markdown freshness discovery until before the next enabled inference. If Git is absent, use file persistence. Manual-mode startup/status/restore do not initialize Git; configured automatic start of a genuinely new session uses the same initialization as explicit start. Never create external accounts, remote repositories, credentials, or remote configuration; those remain operator-owned. Never auto-import, delete, or reset files/history in a previous Knowledge-backed store; old branch revisions require their original Git history to remain available in the selected store. `/state-flow-start` must initialize missing global, CWD, and current-session checkpoint/tail pairs plus session config/meta through compare-and-swap publication when required, enable only the current session branch, and bootstrap prior conversation when needed. Explicit start on a proven pre-runtime branch (no checkpoint or an ordinary-disabled marker) establishes an empty session origin rather than importing a later same-session layer; validate existing runtime identity, retain shared streams unchanged, and preserve later branch data in cold Git history. Ordinary new sessions remain manual unless agent-level `autoStart` is true; CWD materialization alone grants no automatic activation. Configured new sessions may initialize missing CWD state and receive distinct empty session layers while inheriting global/CWD values. Resumed and tree-selected branches restore their own config and temporal lineage, regardless of the global flag.
- `/state-flow-stop` must persist only the current session/branch's `config.enabled = false` and necessary runtime provenance, preserving all semantic checkpoints/tails and creating no semantic transition. It must retain a same-physical-session bounded passive context handoff across reload, resume, and tree restoration so disabling semantics never re-exposes pre-stop raw history. Active restart replaces passive mode but uses that bounded boundary for its one migration run; new and forked physical sessions inherit neither projection. It does not rewrite agent-level `autoStart` or change its policy for future new sessions.
- Keep the injected runtime protocol compact and normative; put rationale and extended explanation in README rather than the model prompt. Never parse or strip State Flow HTML comments; they are ordinary historical text, while foreign comment handling remains owned by other extensions.
- Do not claim strict boundedness for state, the current run trajectory, the turn specification, or the external full trace.
- Remain extension-agnostic: do not import, name, special-case, or encode policy for any other extension or transport.
- Activate State Flow model tools only while enabled on the selected branch; preserve every unrelated active tool when toggling them. Keep mutation confined to `patch_state` and historical observation read-only.
- Keep `.github/workflows/release.yml` as the sole version-tag release owner: it validates immutable tag identity, publishes through npm Trusted Publisher with provenance, verifies the public package, and only then creates the GitHub Release. Keep package, lockfile, tag, and changelog versions aligned; never add a long-lived npm token fallback.
- Run `npm run validate` after retained code changes.
