import { CONTRACT_SECTION_ICON, MECHANISM_SECTION_ICON, POLICY_SECTION_ICON, RULE_SECTION_ICON, } from "#configuration/icons/rule.icons"; import { CONTRACT_SECTION_ID, MECHANISM_SECTION_ID, POLICY_SECTION_ID, RULE_SECTION_ID } from "#core/ids/rule.ids"; import { MARKDOWN_LANGUAGE, TYPESCRIPT_LANGUAGE } from "#configuration/constants/code.constants"; import type { Section } from "#types/document.types"; const RULE_RECORD_SHAPE = 'export type Tier = "always" | "situational" | "exception";\nexport type Gate = { readonly kind: "check"; readonly id: GateId } | { readonly kind: "conduct" };\n\nexport interface RuleRecord {\n readonly slug: string;\n readonly directive: string;\n readonly tier: Tier;\n readonly gate: Gate;\n readonly locked: boolean;\n readonly source: DocumentId;\n}\n\nexport interface Digest {\n readonly slug: RuleRecord["slug"];\n readonly why: string;\n readonly how: string;\n readonly measured?: { readonly shape: string; readonly presents: string };\n}'; const RULE_LINES = "## \n\n- `read_before_claim`: a claim about a file is a lie until the file is read in this session · gate: conduct\n- `finding_not_principle`: the AI is directed with a location and a mismatch, never with a principle · gate: conduct\n- `one_run_is_the_answer`: a check runs once per state and its first output is read whole · gate: conduct\n\n## \n\n- `rename_by_hand`: a move is done by hand, every reference enumerated before and verified after · gate: reference\n- `ask_at_the_uncertainty`: a question is raised where it appears, with a recommendation, before the dependent work · gate: conduct"; const ROLE_TEMPLATE = "# Reviewer\n\n## \nThe seat's identity, bound in the index before its first write.\n\n## \nThe list of findings, and nothing else.\n\n## \nA change ships only once the list is empty.\n\n## \nOne finding per line: file, line, expected, found. No style comments, no rewrites.\n\n## \nAffirming a change that reads well. Reviewing the description instead of the diff.\n\n## \nA finding without a location is an opinion. Approval is what remains when the list is empty."; const MECHANISM_DIAGRAM = 'flowchart TB\n rule["A rule"]\n conversation["Held in the conversation"]\n restated["Restated every session"]\n fades["Fades as the context fills"]\n defaults["The AI is back to its defaults"]\n tree["Held in the tree"]\n policy["A policy file the AI reads on its own"]\n check["A check that runs on every change"]\n holds["Holds without anyone remembering it"]\n rule --> conversation --> restated --> fades --> defaults\n rule --> tree --> policy --> holds\n tree --> check --> holds'; const CORRECTION_DIAGRAM = 'flowchart TB\n correction["A correction arrives"]\n classify["Classified to one encoding"]\n rule["One line · slug, directive, gate"]\n reason["Its reason · why it exists"]\n application["Its application · how it applies"]\n memory["A memory file · the fact, its why, its how"]\n search["Verified by search, never by recollection"]\n correction --> classify --> rule --> reason --> application --> memory --> search\n rule -. the class, never the instance .-> rule'; const MECHANISM_SECTION: Section = { icon: MECHANISM_SECTION_ICON, id: MECHANISM_SECTION_ID, intro: "A rule has two possible homes, and two homes draws where each one ends. It lives in the conversation, where someone restates it and hopes, or it lives in the tree, where the AI reads it on its own and a check refuses what breaks it. Everything in this method lives in the tree, as policy as code where a check can hold it and as a policy line where only conduct can. An instruction that needs restating is a mechanism that has not been built yet, and the ontology's name for the state it leaves behind is manual-only governance.", subsections: [ { blocks: [ { application: "Move each instruction you keep repeating into a file the AI reads on its own. Move each check you keep performing into a command the pipeline runs. Delete the ritual once the mechanism holds, because a ritual kept beside its mechanism is a second home for the same rule.", boundary: "A conversation is the right home only when the AI has no access to your files. The tree is the home the moment it does.", cause: "A rule held by discipline is re-decided at every use, and every re-decision is a chance to decide differently.", decision: "Convert discipline into mechanism the moment you have stated a rule twice.", failureMode: "The session starts well, the instructions fade as the context fills, and by the end the AI is back to its defaults.", kind: "lesson", principle: "Discipline held in a conversation decays. A mechanism held in the tree does not.", problem: "Rules that live in a chat need restating every session, and the restating is where they drift.", validation: "Delete your custom instructions for one session. What still holds is mechanism. What breaks was discipline.", }, { kind: "text", text: "The test that separates the two is whether anything would disagree if the rule stopped holding, the objector test that stating an invariant applies to a whole topology. A rule in a conversation has no objector: the moment it is forgotten, nothing notices. A rule in the tree has one of two objectors. A check refuses the change that breaks it, or a policy line the AI reads every session states it in the same words every time. The second is weaker than the first and still stronger than a memory, because a policy is delivered to every session at startup and a memory is delivered to whoever remembers to look.", }, { kind: "text", text: "Coordination friction is the same question at a larger scale, answered where coordination is software: when two parties on one tree lose a write, leave a stale item or miss a message, the first response is what the shared surface is missing, never who should have been more careful. A rule added without a mechanism behind it is more care wearing a rule's clothes, and it decays at the same rate the care did.", }, { caption: "two homes", kind: "mermaid", text: MECHANISM_DIAGRAM }, ], title: "Discipline decays, mechanism holds", }, ], title: "Where a rule lives", }; const RULE_SECTION: Section = { icon: RULE_SECTION_ICON, id: RULE_SECTION_ID, intro: "Every behavioural rule is one line with a stable name, a directive, and the name of the check that enforces it or a declaration that none can, the lines a policy file shows and a rule record parses. The name is what a correction lands on and what a citation resolves to. When I correct the AI, the correction becomes a rule with a name and a memory the same turn, so it hardens instead of repeating, as a correction hardens draws.", subsections: [ { blocks: [ { application: "Write each rule as one line: a short stable name, a directive in the present tense, and the gate that holds it. Cite the name wherever the rule applies. When a correction arrives, classify it to one home, write the rule first, then its reason and its application, land a memory beside it, and verify every destination by search rather than by recollection. Capture the class the correction belongs to, never the one instance that triggered it.", boundary: "A rule may state the measured failure that produced it, in past tense, inside the rule it justifies and nowhere else, because that clause is an operand the rule depends on. It carries the shape that failed and how it presented, never who did it, when, or in what order.", cause: "A correction with nowhere to land is remembered by the person and forgotten by the model, so it arrives again next week.", decision: "Give each rule a name to land on rather than a paragraph to append to.", failureMode: "The same correction gets made in three sessions, each time as a new paragraph, and the three paragraphs disagree.", kind: "lesson", principle: "Behaviour is a set of named rules, so a correction hardens rather than repeats.", problem: "Instructions written as prose have no stable place for a correction to land.", validation: "Take the last correction you gave the AI. Find its name in the rules. If it has no name, you will give it again.", }, { kind: "text", text: "The line shape is the whole design. A slug is a stable identity, so a rule can be cited from a digest, a memory, a finding or a peer's message without quoting its text, and it survives every rewording; the slugs are the ubiquitous language the operator, the model and the tooling share. A directive in one line cannot hide a second instruction, so a reader executes it as one step. The gate field is the honest part: it names the check that observes the rule, or it says that no artifact can, and a rule that says neither is a rule nobody has assessed. That field lives in exactly one place per rule, because a single source of truth admits no second declaration site. A rule without its reason gets re-litigated, and a rule without its application gets admired and ignored, so the digest that expands a rule carries both; a digest is an architecture decision record for one line of conduct.", }, { kind: "text", text: "The reason and the application are written in the operator's own sharpest words where there are any, since paraphrase loses the distinction that made the correction necessary. The unit captured is the class: one bad path becomes a rule about verifying paths, and one missed reference becomes a rule about surfaces that resolve by pattern.", }, { kind: "text", text: "The rules split into the ones that bite every turn and the ones that fire on a matching task, plus a small set of declared exceptions. That grouping is the reader's, not the checker's. A check reads the gate field and never the heading, which is why a rule can move between groups without any mechanism noticing and why a new rule is one appended line rather than a section.", }, { kind: "text", text: "Parsed, a rule is a record, and the record is what an inventory, a coverage walk and a leak check all read; coverage is derived from that inventory rather than counted. The gate is a discriminated union rather than a nullable string, so a rule that declares neither cannot be represented, which is how the unassessed state becomes unwritable rather than merely discouraged.", }, { code: RULE_LINES, kind: "code", language: MARKDOWN_LANGUAGE, title: "a policy file" }, { code: RULE_RECORD_SHAPE, kind: "code", language: TYPESCRIPT_LANGUAGE, title: "a rule record" }, { caption: "a correction hardens", kind: "mermaid", text: CORRECTION_DIAGRAM }, ], title: "A correction lands on a name", }, ], title: "Rules with names", }; const CONTRACT_SECTION: Section = { icon: CONTRACT_SECTION_ICON, id: CONTRACT_SECTION_ID, intro: "A seat is defined by a contract, never by a character. Design by contract applied to a party: the contract is a role document with the same sections for every seat, naming what it owns, what it refuses, how it works, the principles that decide its calls, and the mistakes it is prone to.", subsections: [ { blocks: [ { application: "Write a role as a short document with the same sections every time, and name the failure modes that seat exhibits beside what it owns. Check the seat's output against the contract, never against its tone. Keep the identity out of the filename so a handover changes a field rather than a path.", boundary: "A measured failure mode is evidence held in one place, so it leaves a role document only by extraction to the one home history has. An anticipated failure never displaces a measured one.", cause: "A character is judged by how it sounds, and sounding right is the one thing a model can always do.", decision: "Define a seat by its contract, never by its character.", failureMode: "The persona stays in voice through the whole session and produces the same drift as a session with no persona at all.", kind: "lesson", principle: "Consistency comes from the check, not from the roleplay.", problem: "A persona gives an AI a voice, and a voice is not a behaviour.", validation: "Strip the voice from a session's output and check what remains against the contract. Whatever the voice was hiding is now visible.", }, { kind: "text", text: "A uniform shape is what makes a set of seats comparable. A reader looking for what a seat refuses finds it in the same place in every document, or the documents are prose that happens to be filed together. The section set is the contract and the declared fields are the operands a tool reads: the identity, the concern it holds, the one line another seat routes by. The seat's identity is allocated and bound before its first write, which coordination is software derives.", }, { kind: "text", text: "The section that carries the value is the one about what the seat gets wrong. A reviewer that affirms a change that reads well, a builder that reviews the description instead of the diff, a coordinator that routes work one edit would have closed: those are measured shapes, and a seat that opens its own document before its first edit is reading them to avoid repeating them. A contract without that section is a job description, and a job description constrains nobody.", }, { code: ROLE_TEMPLATE, kind: "code", language: MARKDOWN_LANGUAGE, title: "a role document" }, ], title: "Contract over character", }, ], title: "A seat is a contract", }; const POLICY_SKELETON = "# \n\nA claim about the tree is unverified until the tree is read. Review is adversarial by default. Every manual step is a failure of automation. A document states what is true now.\n\n# \n\nThe behaviour policy governs the agent. The codebase contract governs the code. A digest expands one rule and declares nothing. The tree outranks all of them, and a document that disagrees with the tree is corrected the same turn.\n\n# \n\nA blocker outranks everything and is read first. Then the board, whole. Then the seat's own role. Then the document whose domain the task enters.\n\n# \n\n- `read_before_claim`: a claim about a file is a lie until the file is read in this session · gate: conduct\n\n# \n\n- `rename_by_hand`: a move is done by hand, every reference enumerated before and verified after · gate: reference\n\n# \n\n- `question_is_blocked`: a pending question is a blocked state, never a third verdict\n\n# \n\nOne command runs every stage in order. It runs once per state, and its first output is read whole.\n\n# \n\n: what it holds and what authority it carries, one line each."; const COMPOSITION_DIAGRAM = 'flowchart TB\n subgraph resident["Resident · in force before the task is known"]\n axiom["The axiom · the stance, the readings, the hard prohibitions"]\n set["The document set · what governs what, and the precedence"]\n startup["Startup · what is read first, and in which order"]\n always["Rules that bite every turn"]\n end\n subgraph referenced["Referenced · presupposes a known task"]\n situational["Rules that fire on a matching task"]\n exceptions["Declared exceptions"]\n verify["How the work is verified · one chain"]\n tooling["How the tree is looked at"]\n notes["What the tree is"]\n digests["Digests · one concern each, expanding a rule"]\n end\n test{"Does it tell you how to find out what you are doing?"}\n test -- yes --> resident\n test -- no --> referenced\n axiom --> set --> startup --> always\n situational --> exceptions --> verify --> tooling --> notes\n resident -- delivery order --> referenced\n situational -. needs room .-> digests'; const PORTABILITY_DIAGRAM = 'flowchart TB\n policy["The behaviour document"]\n operations["Semantic operations · discover, read, search, analyse, execute, persist, report"]\n slots["Slots · the gate, the rule host, the test root, the depth cap"]\n binding["One binding per harness"]\n toolsA["Harness A · its tools, its file name"]\n toolsB["Harness B · its tools, its file name"]\n model["The model · an absent slot by construction"]\n policy --> operations --> binding\n policy --> slots --> binding\n binding --> toolsA\n binding --> toolsB\n policy -. names nothing about .-> model'; const DELIVERY_DIAGRAM = 'flowchart TB\n doc["The behaviour document · delivered once, at startup"]\n seat["A seat"]\n bounded["A bounded invocation"]\n board["The board · read whole every round"]\n line["One projection line · the only board it ever sees"]\n invert["Turn-owning rules invert · returning is its contract"]\n routed["A change to the document is routed to the running parties"]\n doc --> seat --> board\n doc --> bounded --> line\n bounded --> invert\n doc -. edited mid-session reaches nobody running .-> routed'; const POLICY_SECTION: Section = { icon: POLICY_SECTION_ICON, id: POLICY_SECTION_ID, intro: "The behaviour policy is the system prompt of the collaboration, whatever file name the harness reads it under. It is the one document delivered to every session at startup, so it carries what has to be in force before the agent knows what it is doing, and it points at everything else, in the order a behaviour document shows and delivery order places. Its composition is the same in any harness and for any model, because nothing in it names a tool: it names operations and slots, and one binding says which tool performs which, which is platform independence applied to a prompt, as one binding per harness draws. What each reader class receives is what reader classes draws. It is the behavioural encoding of the three encodings, and document structure on the grammar page is the same rule for a single document: declare, then instruct.", subsections: [ { blocks: [ { application: "Open with the stance and the hard prohibitions, because those bind before the task is known. Follow with what to read first and in which order, then the rules that bite every turn, then the situational ones, then the declared exceptions. Put how the work is verified, how the tree is looked at and what the tree is after the rules, because each presupposes a task. Point at a digest for anything that needs room. Name no tool anywhere; name the operation, and let the binding resolve it.", boundary: "The document is delivered once per reader, so a change to it has no subscribers in a running session. A rule edited mid-session reaches only parties that start afterwards, which is why a governing change is also routed as a message to the parties already running, and the message is read whole every round where the file is not.", cause: "A document delivered once carries no shape that says what is resident and what is referenced, so every line competes for the same attention and the order is whatever it was written in.", decision: "Compose the behaviour document by orienting precedence, and treat its shape as portable across harnesses.", failureMode: "The document grows by appending, every session opens on a wall of prose, the first rules hold and the last ones are never read, and the same correction is added a fourth time at the bottom.", kind: "lesson", principle: "The behaviour document is a system prompt with a composition. Resident context comes first, delivery order is precedence order, and what presupposes a known task is referenced rather than carried.", problem: "A prompt written as one long instruction document is read once at startup by a model that will forget most of it, and nothing in its shape says which parts must survive.", validation: "Rename the file to what another harness reads and hand it to a different model. Where it fails, a tool name or a path leaked into a place a slot belongs. Where it holds, the composition transferred.", }, { code: POLICY_SKELETON, kind: "code", language: MARKDOWN_LANGUAGE, title: "a behaviour document" }, ], title: "A system prompt with a composition", }, { blocks: [ { kind: "text", text: "The test that decides where a part goes is one question. If it tells the agent how to find out what it is doing, it is resident, and it sits at the top in the order it binds. If it tells the agent what to do once it knows, it is referenced, and it sits below or in a digest the top points at. Frequency is a proxy and a bad one: a rule that fires every hour but presupposes a known task is safely referenced, and a rule that fires once a month but decides which document to open is resident.", }, { caption: "delivery order", kind: "mermaid", text: COMPOSITION_DIAGRAM }, ], title: "Resident, then referenced", }, { blocks: [ { kind: "text", text: "The document is a claim like any other and the stance binds it: it is re-read whenever it enters context, because a version held in memory is a memory, and it defers to the tree as three encodings orders.", }, { kind: "text", text: "It states what is true now and never what used to be, as derived state requires of every document. Copying a sentence from one document into another is how a dead reference propagates, so a fact keeps a single source of truth and the other documents point at it, which documentation is code turns into a check. The set is validated as documents, each class to its declared shape, and a document off shape fails before it is delivered.", }, ], title: "The document is a claim", }, { blocks: [ { kind: "text", text: "Portability follows from what the document is allowed to say. It states what to do as semantic operations: discover the resources, read the resource, search the content, analyse, execute a tool, persist the artifact, report the result, the same rule semantic operations on the grammar page states. It states where things are as slots: the gate, the rule host, the test root, the depth cap. One binding per harness maps each operation to that harness's tool and each slot to that tree's value, which is configuration externalization for a prompt, so moving the document to a harness that reads a different file name is a rename plus one binding, and the rules do not change. The model is an absent slot by construction, because model selection belongs to the harness and a value written into an absent slot has no source.", }, { kind: "text", text: "A body of rules meant for adoption elsewhere is written as a block a host copies into its own document rather than merges. The host's rule wins where the two collide on one construct, and the collision is a finding rather than a negotiation. Every path in the block is relative to one value the adopter re-points, and the one literal that survives is the import a runtime resolves, because a runtime reading a path has no binding to consult.", }, { caption: "one binding per harness", kind: "mermaid", text: PORTABILITY_DIAGRAM }, ], title: "Operations and slots", }, { blocks: [ { kind: "text", text: "Who receives the document decides which of its rules bind, and the document says which class each rule binds rather than leaving the reader to classify itself; coordination is software derives the two classes from what each receives. The one line a bounded reader gets is refreshed in the same change as the fact it carries and held to a cap, because a projection that grows by perfect compliance with a refresh rule stated without a shape is the document's own accumulation.", }, { caption: "reader classes", kind: "mermaid", text: DELIVERY_DIAGRAM }, ], title: "Who receives it", }, { blocks: [ { kind: "text", text: "The document grows in the one shape rules with names describes, and a rule stated twice for the same shape becomes a check the line points at.", }, { kind: "text", text: "The document restates nothing the codebase contract owns and the contract restates nothing the document owns, and a reader who finds one fact in both has found the copy nobody maintains.", }, ], title: "How it grows", }, ], title: "The behaviour document", }; export const RULE_SECTIONS: readonly Section[] = [MECHANISM_SECTION, RULE_SECTION, CONTRACT_SECTION, POLICY_SECTION];