omp packages

@tinoy/pi-canon0.7.0

Durable system-prompt rules for pi: an on-disk canon store, its tools, and the /canon commands.

GitHub Actions Published 17 days ago MIT ~1.5K downloads/mo

Untested on omp

This is a pi package. No one has reported whether it works on omp yet. If you try it, add your result below.

Did it work for you?

Result

One report per person. A new report replaces your old one.

Reports 0

No reports yet.

Readme

[!WARNING] Do not install anything here yet.

This is a fast-moving prototype: the interfaces change without notice, and nothing here is stable. Every package in this project is headed for a stable 1.0, but that is still some way off. Install one only if you intend to follow the code and expect breakage.

@tinoy/pi-canon

Durable system-prompt rules ("canon") for pi. Rules and learned facts are stored on disk, scoped by model (global or a model id) and audience (all, parent, foreman, subagent), and injected into every matching session's system prompt. Runtime edits reach running sessions as notices; the injected block is a session-start snapshot, so a running session's prompt never changes mid-session.

pi install npm:@tinoy/pi-canon

What it does

  • Store — ~/.pi/agent/canon/canon.json: {entries: [{id, text, model, audience, category?}], categories: [{id, title}]}. Written atomically; a missing or corrupt store reads as empty, and a field the shape no longer defines is dropped when the store is read.
  • Upgrading a store written by an earlier version — an entry's retired reason and a category's retired description are dropped when the store is read, so nothing prints them, and they are absent from the file at the next write. A session that only lists, renders or receives notices never writes, so the file keeps them until something changes it.
  • Tools — canon_add, canon_remove, canon_edit, canon_category.
  • Commands — /canon (list, add, remove, edit, category management). With no argument it prints exactly the block this session receives; list prints the same thing, and a scope argument (an audience word or a model id) prints the block that scope receives instead.
  • Injection — the block is appended at before_agent_start and re-normalized on every provider request, so a run started by an injected message carries the same bytes as an interactive prompt.
  • Category headings — a category sub-heading inside a scope group prints the store id after the word category (#### Behavioural Preferences [category 1cg5lr]), which is the same id a canon_add refusal lists; the word keeps it from reading as an entry handle, which the block renders as [1i15c2]. Uncategorized entries carry no id, and a scope group holding a single category stays flat with no sub-heading.
  • Peer notices — entry changes are published over the ipc transport's bus (namespace canon); receivers match the entry scope against their own model and audience. A matching notice steers into a run that is already in flight, landing at the next tool boundary, and queues for the next turn when the session is idle, so it never wakes anything.
  • Tail sections — another extension contributes prompt text through the canon:section event; its ids are published on canon:sections.

Exports

index.ts is the package entry, and it is also the module API:

Export What it is
default the pi extension factory — the hooks, the four tools and the command
setTailSection(id, text) contribute a tail section, replaced per id
registeredSectionIds() the ids currently registered

The tail-section registry stays here because it owns this package's event contract: the canon:section / canon:sections names, the canon hook-log source, and the section cap. setTailSection / registeredSectionIds are exported for this package's own use and are never re-exported elsewhere; another extension reaches the registry through the canon:section event, because an exported function is unreachable across the loader's module isolation.

The system-prompt seam

The seam canon composes the tail through — canonicalSystemPrompt(systemPrompt, block), systemPromptSlot(payload) and the append separator PROMPT_APPEND_SEP — is NOT exported from this package. It lives in @tinoy/pi-ext-lib (src/system-prompt.ts), together with the rule that makes it shared: before_agent_start fires only from the interactive prompt() path, so an appended block has to be re-normalized on every provider request for the request prefix to stay byte-identical. Canon imports it from there, and so does any other extension that appends to the system prompt — import @tinoy/pi-ext-lib, not this package. What stays here is the policy: the block's content, its scope rules, and what happens when the payload carries no rewritable slot.

Dependencies

pi supplies these, so they are declared as peer dependencies with * and are not bundled: @earendil-works/pi-ai, @earendil-works/pi-coding-agent, typebox. @tinoy/pi-ext-lib is a plain dependency; the prompt seam above is imported from it, not re-exported by this package.

Licence

MIT — see the repository LICENSE.