| name | haipipe-board-page |
| description | The PAGE contract and router of a Board: one persistent Page combines a stable Page Type with a current Page Phase. It owns the shared frame, fixed section order, section obligations, machine write boundaries, evaluation contract, and the lifecycle vocabulary DRAFT, PROBE, REVISE, CHECK. Page Type variants live under page-types/; phase contracts live under page-phases/. THREE VERBS form the callable door: CREATE scaffolds one Page, WORK ON repairs one Page, and RUN drives one Page through a bounded non-linear producer/build/judge loop with auditable receipts. RUN is deliberately not ADVANCE. Trigger: create a page, new page, working on a page, update a page, run page lifecycle, automatic page loop, audit page workflow, page contract, page grammar, page sections, Page Type, Page Phase, draft probe revise check, rewrite Opening, section evaluation, quality check, which section, base page, /haipipe-board-page. |
| metadata | {"version":"0.21.0","last_updated":"2026-08-06","summary":"One resolution table covers ALL types: filename prefix, then the HEAD route: line (moved out of the retired register marker, JL 260806), then the REQUIRED page-type: frontmatter key, then the stage and Q filenames; exactly one key matches or the page is defective."} |
/haipipe-board-page ยท the page, as a contract you can load
haipipe-board is the door you walk through to RUN a board.
This skill is the door for ONE PAGE, and the spec that page is measured against. Say create a new page on <topic>, working on <page>, or run <page>; load it with no board open and it is a pure contract.
QC1b ยง1 on the design board states the test it passes: a consumer needs these rules with no board open.
Those consumers exist today: the routing verb deciding "which page, which section", the chat drawer priming a per-page session, and the variant authors in other families.
The boundary, and it is a hard one:
Who owns what: this skill holds the spec, haipipe-board holds the machinery.
haipipe-board-page haipipe-board
โโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
what a page IS rendering it (src/page_question.py)
the section contract serving and write-back (cli/serve.py)
where a write may land the checker (cli/check.py)
the base/variant model the template file itself (ref/page-template.md)
This skill never CONTAINS the renderer, the server or the checker. It calls them, because a reader asking for one page should not have to know which script does what, and owning one page end to end is not the same as owning the machinery.
The authoritative template stays haipipe-board/ref/page-template.md; this contract cites it and must never fork it.
๐งฌ Page Types, one base
A Page's TYPE comes from one machine-readable key on the page: a filename prefix, a head route: line, or a frontmatter page-type: line.
The type decides how the Page closes, what its Content holds, and which typed records it fills through the base frame's declared extension points.
Everything else is the shared base (the model on the design board's QB4, JL 260729).
The implementation may still call this field kind; the contract term is Page Type.
Type resolution: one table for ALL types. Resolve โ to โค in order and stop at the first key that matches.
step machine-readable key Page Type contract
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ filename Skill-<n>- or Agent-<n>- Skill / Agent mirror for-skill
filename Meeting-<n>- Meeting for-meeting
filename QBv<n>- QBv venue for-venue
โก head line `route: outward` Literature evidence for-literature
head line `route: inward` Value evidence for-value
โข frontmatter `page-type: display` Display unit for-display
frontmatter `page-type: slide` Slide deck for-slide
frontmatter `page-type: design` Design brief for-design
frontmatter `page-type: section` Section unit for-section
โฃ filename S-<Family>-<unit>-<slug> Stage for-stage
โค filename Q<group><n>[<face>]-<slug> Q decision base only
EXACTLY ONE step may claim a page, or the page is defective: a page no key matches, or one carrying two keys that disagree, is fixed on the page, never in the resolver.
Step โก's key is ONE line in the page's metadata head, right after owner:/method: (JL 260806; it replaced the retired register marker): an evidence page wears a stage-shaped filename, so only the head route: line separates the two evidence routes from a plain stage page. The line is REQUIRED, and haipipe-board/ref/topic-entry-contract.md declares it.
Step โข's page-type: line is REQUIRED on those four types' pages, and it BEATS the filename.
That order settles the two real collisions: S-Display-4c wears a stage filename and is a display unit, so page-type: display resolves it at โข before โฃ can claim it; QA4 wears a Q filename and is a slide deck, so page-type: slide resolves it before โค.
Each type's contract states how it closes; the base's own type, the Q decision page, closes when every Aim is met or explicitly held, and mirror and Meeting pages are NEVER counted in a board's settled totals.
src/common.py globs four filename prefixes, Q, S, Agent and Meeting, and that glob decides only what counts as a page at all; a Skill- page starts with the letter S, so it rides the S glob.
Membership is the glob's whole job. The table above, not the glob, decides which type a page is.
Meeting-<n> is generated by cli/meetingpage.py, and its contract is haipipe-board-page-for-meeting: talk is recorded there, ruled elsewhere.
A Page Type used by one consumer family is a VARIANT of the base: it defines Content and may populate fixed extension points in Aims, States, and Stage Contract, but it never redefines, adds, removes, or reorders those frame sections.
A variant ships WHERE THE BOARD FAMILY MAINTAINS IT (JL 260803).
The ten Page Type variants maintained here live under page-types/; family-specific stage data, such as the paper door's stages/ and craft files, remains in its own family.
The earlier wording was "ships under its CONSUMER, never here", which broke when the venue variant landed because its consumer is the paper family and its maintainer is this one.
This skill owns the BASE those variants extend.
TEN Page Type variants ship under page-types/, and one of them must be loaded before you write the Page it governs:
Skill-<n> ยท Agent-<n> โ haipipe-board-page-for-skill a page that mirrors a
shipped unit and decides nothing
QBv<n> โ haipipe-board-page-for-venue a page per place a paper
is submitted to
S-<Family>-<unit> โ haipipe-board-page-for-stage a page per lifecycle stage
of one paper or application
evidence, outward route โ haipipe-board-page-for-literature an evidence page asking
what is already KNOWN
evidence, inward route โ haipipe-board-page-for-value an evidence page asking
what this project must PRODUCE
display unit โ haipipe-board-page-for-display a unit a person must ACCEPT:
figure, table, diagram
section unit โ haipipe-board-page-for-section one reader-ordered unit, bound
to its venue allocation
Meeting-<n> โ haipipe-board-page-for-meeting talk recorded here, ruled
elsewhere ยท NEVER counted
slide deck โ haipipe-board-page-for-slide one division per slide, each
embedding the deck LIVE via
?preview=N
design brief โ haipipe-board-page-for-design one division per candidate,
closes on a SELECTION record
The last seven were admitted 260805 (JL, ruled on the design board's QB6; -for-slide on the Page-for-Slide branch).
-for-section loads -for-stage the way the topic types load the topic core.
It adds the section kind, the venue contract block, and the landing surface where citation, value, and display bindings reach prose.
A section reads the venue BLUEPRINT, never the QBv catalog.
-for-meeting closed a gap this section itself used to record: Meeting-<n> pages had a generator and no contract.
Its one owned rule is that a spoken decision is not ruled until routed to the owning page.
The two evidence types resolve by the head route: line, the same key src/topic_entry_contract.py already trusts.
Their filenames look like stage-page filenames, which is why a filename cannot resolve them.
Both LOAD haipipe-board/ref/topic-entry-contract.md for the anatomy and add only their route's translation layer.
A display page is mirror-shaped but closes on human ACCEPTANCE of a render, not on a unit shipping.
That is why it does not load -for-skill.
A slide page shares that acceptance model at deck grain: one division per slide.
Each division embeds the ONE deck file live, via html-ppt's ?preview=N single-slide mode.
The same file opened bare is the presentation.
JL ruled the embed must be the html itself, and the boardform board's QA4 is the proving page (260805).
A design page is the brief itself: its Opening states audience, goal, and constraints, and each Content division carries one CANDIDATE artifact.
It closes on a SELECTION record naming the winner and each loser's disposition.
It sits UPSTREAM of -for-display: design selects the candidate, display accepts its render.
Load the matching one before writing or fixing any Page of those types.
haipipe-board-page-for-stage names the ONE stage that reads a QBv Page and the four tiers deciding what crosses from that catalog into a draft.
The first two listed types also do NOT take the create a new page steps below: they are GENERATED by haipipe-board/cli/skillpage.py new, which writes the Page from its own stub and registers it in board.md itself, so copying ref/page-template.md and registering by hand produces a Page with no managed spans that the checker then reports as broken forever.
haipipe-board-page-for-skill exists because a mirror page DECIDES NOTHING, so this skill's Opening shape, which ends in what this page decides, leaves it with no question to ask; five skill and agent pages filled that empty slot with the same rhetorical question on 260802.
๐ญ Four Page Phases, independent of Page Type
A Page persists while the authority acting on it changes.
The current phase is not another Page Type and is not inferred from the edit operation.
phase authority load
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
DRAFT define or reopen purpose, Aims, promised shape page-phases/haipipe-board-page-draft
PROBE resolve a consequential unknown across the evidence wall
page-phases/haipipe-board-page-probe
REVISE improve the current promise while purpose and Aims stay fixed
page-phases/haipipe-board-page-revise
CHECK judge one version and route its next authority page-phases/haipipe-board-page-check
Resolve one invocation in this order:
base Page contract
โ matching Page Type, when one exists
โ current Page Phase
โ family craft: the stage's declared craft files (and for probe, the family door's probe tooling), when paper or application adds artifact knowledge
The four phases form a routing grammar, not a conveyor belt.
Each may repeat, PROBE may be skipped when no consequential unknown exists, and CHECK may route to REVISE, PROBE, or DRAFT.
Returning to DRAFT because purpose or Aims changed starts a new round on the same Page.
Use the authority test when the visible operation is ambiguous:
purpose or Aims change โ DRAFT
an unanswered consequential fact moves โ PROBE
the same purpose and Aims are improved โ REVISE
a concrete version is judged โ CHECK
Adding, deleting, moving, and rewriting may be DRAFT or REVISE.
The reason for the change decides.
RUN is the router verb now that the automatic loop has a concrete contract.
It is deliberately not called ADVANCE: a Page can repeat a phase, branch, HOLD, or return to DRAFT in a new round.
The shared packet, receipt, version, role-separation, and stop rules live in ref/page-run-contract.md.
๐ The sections, in their fixed on-stage order
The sections in order: what each owes a reader, and how much a machine may write into it.
The AUTHORITY is haipipe-board/ref/board-form.md ยง4, which fixes the ON-STAGE order as five, Opening โ Diagram โ Content โ Aims โ States, with Files after them and the folds last. This skill adds no section to that list; the table below names the same run plus what a machine may write into each. ref/page-template.md carries more ## headings than this because it also seeds the optional and folded ones.
# section owes the reader phase authority
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
1 Opening the lead question + why it matters DRAFT defines ยท REVISE clarifies
2 Diagram the figure; ids in it are links DRAFT/REVISE, within Page Type rules
3 Content the substance, ### divisions DRAFT defines ยท REVISE realizes
4 Aims durable Content-linked targets DRAFT; changing intent starts a round
5 States one factual current State per Aim any phase, from inspectable evidence
6 Files action map + scoped Page context DRAFT/REVISE maintain
7 folds Discussion ยท Law ยท Lesson ยท Glossary ยท Log the phase owning the record
Each section answers ONE reader question, and the same five rows define every section's contract (JL 260801, ruled on the design board's QB4 ยง0): conveys, the reader question it answers ยท holds, the elements it must contain ยท source, how the author writes it ยท rules, what binds a write ยท omit, when it may be absent.
One reader question per section: the question it answers, and when it may be left out.
section conveys ยท the reader question omit
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
๐งญ Opening what is this page, why should I care? never
๐ผ Diagram can I see the whole subject at once? when no figure helps: delete
๐ Content what does this page actually establish? Q may ยท S never
๐ฏ Aims what should become true, and for which Content division? never
๐ States what is true now for each Aim, what waits? never
๐ Files which few files or Page fragments continue this work? allowed, advised against
๐ folds what was ruled, learned, changed, if needed each optional
A sentence answering another section's question is MISPLACED, and the protocol names its home: substance found in Opening moves to Content, Required Inputs and Venue move to Stage Contract, prose rules move to Writing Style, intended outcomes move to Aims, current facts move to States, and temporary next steps become an Aim's optional Plan.
The full five rows per section live in the design board's QB4 Content divisions; the authoritative source form stays haipipe-board/ref/page-template.md.
An Aims or States group is ### A<n> ยท <emoji> <name>, taking the NUMBER, NAME and EMOJI of the Content part it answers, so the three sections line up by eye as well as by id (JL 260802; it was C<n> until then, which made a reader translate one letter to see that A3.1 belonged under it, and C<n> still resolves). P is for a target belonging to no single part. Ordinary Files groups are a MENU of actions, taken as they apply: โ๏ธ Engines what RUNS the subject ยท ๐ Contracts what CARRIES a rule to other pages ยท ๐งช Checks what CATCHES a page breaking one ยท ๐ฅ Input files what the work READS ยท ๐ค Output files what a BUILD writes. Their names state an ACTION, never a subject, because a subject-named group rots the moment its subject leaves the page.
### ๐ Related Board Pages is the one fixed Files group. It is a selective context map between Pages, not a file dependency graph and not configuration inheritance. The fixed group name gives the checker a parser boundary; each row begins with the action-like relation that ordinary Files groups put in their heading:
### ๐ Related Board Pages ยท what this Page READS BY SCOPE
- `reads ยท PROBE` ยท [QB7 ยง3](QB-research/QB7-literature.md)
Read the evidence boundary before resolving this Page's consequential unknown.
The four relations are reads, constrained by, continues, and contrasts. The phase is DRAFT, PROBE, REVISE, CHECK, or ALL. The target is a Board-root-relative Page source. Its visible id must match that Page. Scope is page or one direct Content division such as ยง3 or ยง3.2; a division read automatically carries the target Page's identity, Opening, and matching Aims/States group so the fragment does not arrive without its promise and current state. When one packet selects several divisions from the same target Page, identity and Opening are emitted once rather than repeated per row.
Read the current Page whole first. Then run python3 <board-skill>/cli/pagecontext.py <current-page.md> --phase <PHASE> and load only the returned packet. The reader follows one hop: it never traverses Related Board Pages declared by a target Page. Cycles are therefore harmless, context stays bounded, and a phase sees only rows written for it or for ALL. check.py rejects a malformed row, a path outside the Board, a dead Page, a mismatched Page id, or a missing scope before an agent can silently work without that context.
An Aim is not a task. Write - A3.1 ยท target for a result owned by Content part 3, under the group ### A3, and P1 only for a target that genuinely crosses parts. One division may have zero, one, or many Aims. Each Aim has a testable Done when and may carry a temporary Plan; changing Plan does not change the Aim.
The section labels are deliberately both plural: Aims contains Aim records and States contains their State records. States mirrors every Aim id exactly once: โฌ not started, ๐จ being worked on now, ๐ง waiting on a person or something outside this page, โ
met with the evidence named, or โ๏ธ on ice, held on purpose. Each says its meaning by SHAPE (JL 260802); the old ๐ก ๐ โธ๏ธ still parse. This is the AIM vocabulary and NOT the page state: line, which keeps its own โ
๐ก ๐ด โธ๏ธ set and is checked apart. The section is a snapshot, so the reason for a transition belongs in Log. The strict one-to-one relationship is Aim to current State row, never Content division to Aim.
๐ช Three verbs, and this skill is the door for all three
Say any of these and this skill runs it. You never call the engine yourself.
๐ CREATE /haipipe-board-page create a new page on <topic> [on <board>]
๐ง WORK ON /haipipe-board-page working on <page> or just the path
๐ RUN /haipipe-board-page run <page> [from <phase>]
haipipe-board owns the machinery and this skill owns the contract, which is why the boundary above says this skill never renders, serves or checks: it does not CONTAIN that code. It does CALL it. A page is one unit of work, and a reader asking for one page should not have to know which script does what.
๐ create a new page on a topic
- Resolve the board folder, and the group the page belongs to. Ask ONLY if the group is genuinely ambiguous.
- Pick the id (
Q<group><n>-<slug>, or S-<Family>-<unit>-<slug> for a lifecycle stage) and copy haipipe-board/ref/page-template.md to it. Never retype the shape from memory: the template's guide sentences ARE the contract.
- Write the title so it states the page's PURPOSE, in sentence case.
- Write the Opening: the visible paragraph above the first blank line, everything else below it.
- Write Content as numbered parts, each opening with a caption, a
/diagram-ascii figure and a short intro.
- Write Aims, their States, and Files. When another Page supplies necessary context, add only the exact Related Board Pages row and scope the current phase needs.
- Register the page in the board's
board.md roster.
- Build, check, and read the RENDER. Report the page's finding count, not the fact that you finished.
๐ง working on an existing page
Scope is the one thing this verb got wrong when it was measured. On 260802 three fresh agents were each given one sentence and nothing else, and all three found this skill unaided and drove their page to zero findings. They then disagreed completely about how far to reach: one wrote to a single file, its own page; another wrote to fifteen, including four shipped SKILL.md files, four CHANGELOG.md files, six sibling pages and the shared board.md. Neither was wrong on the merits, and the wide one was fixing citations a renumbering really had broken. The skill simply never said where to stop, so steps 7 and 8 below now do.
- Read the whole target file first, including Content, Aims, States, Files and the settled folds. If Files declares Related Board Pages, resolve the current phase with
cli/pagecontext.py and read that one-hop packet before changing prose.
- Run the checker on it and work its list. Every finding names the rule it breaks and the part it is in, so nothing has to be read to know what to do.
- Fix the MECHANICAL findings first, in bulk: dead
## Files paths, a part with no figure, a figure with no caption, a group name that drifted. None needs judgment.
- Then read for what no checker reaches: the weak-English axis, whether each part still answers one question, whether the Opening's visible paragraph says anything the title did not.
- If a fix reveals a rule nobody wrote down, write it in three places: the owning page,
haipipe-board/ref/page-template.md, and this file. A repair that stops at one page will be needed again next week.
- Build, check, read the render, and report the before and after counts.
- ONE page is the deliverable. Step 5 sends you to other files on purpose, and this step bounds it: a write outside the target page is allowed only when the page CANNOT be made correct without it, and every such write is named in the report, with the reason, file by file.
- Never rewrite a sibling page's content. Repointing a citation your own renumbering broke is repair; rewriting the page that citation lands in is a second job, and it belongs to that page's own turn.
๐ run one Page lifecycle
RUN is the automatic, bounded loop. Use it when the process itself must be
exercised and audited, rather than when one known edit is enough.
- Read
ref/page-run-contract.md and assemble its raw-material packet. Resolve
the Page Type from the filename. For a new Page, CREATE and register it first,
then start at DRAFT. For an existing Page with no known next authority, start
at CHECK. Before each phase dispatch, materialize that phase's Related Board
Pages packet with cli/pagecontext.py; an invalid row or missing scope is a
named HOLD, never omitted context.
- Invoke
haipipe-board/ref/page-lifecycle.workflow.js with the packet. The
workflow dispatches a phase-scoped producer for DRAFT, PROBE, or REVISE, a
mechanical builder/version snapshot, and a fresh read-only reviewer for
CHECK.
- Follow returned routes rather than a prescribed order. Only CHECK may CLOSE.
A route to DRAFT from another phase begins a new round only when purpose or an
Aim reopened.
- Stop at CLOSE, explicit HOLD, a missing input, a version mismatch, a required
human gate,
max_steps, or max_rounds. A limit stop means the run did not
converge; it never means quality passed.
- Write the exact Workflow result to
<board>/_runs/page/<page-id>/<run-id>.json. Do not append the terminal CHECK
result to the Page, because that would mutate the approved version.
- Run
haipipe-board/cli/pageflow.py audit <receipt.json>. Report the terminal
route, checked version, traversed edges, deterministic finding count,
semantic finding count, human-gate state, and residual risk.
RUN never lets one hidden pass write, judge, fix, and approve. The producer and
judge have different actor identities, and every changed version returns
through CHECK before CLOSE.
The engine the direct verbs call, so nobody has to remember it:
python3 <toolkit>/skills/board/haipipe-board/cli/build.py <board-folder>
python3 <toolkit>/skills/board/haipipe-board/cli/check.py <board-folder> | grep '^<PAGE>'
python3 <toolkit>/skills/board/haipipe-board/cli/check.py <board-folder> --summary
watch.py rebuilds on any .md save, so step "build" is usually already done; a change to .py, .css or .js is not watched and needs the build run once.
โ๏ธ What CREATE and WORK ON write to
Load this skill and haipipe-board/ref/writing-rules.md directly before writing.
Do not copy their requirements into an assignment prompt: a copied checklist becomes a second prose authority and drifts.
For an existing page, read the entire target file before changing any section, including Content, Aims, States, Files, and settled folds.
A CHANGE IS FINISHED WHEN IT IS ON THE RENDERED PAGE, and nobody is asked for permission on the way (JL 260801: "don't wait me to say go next time, just go ahead and don't stop until the content is updated in the Page").
The unit of work is a visible page, not an edit.
Carry every change all the way through: write the source, propagate the rule to haipipe-board/ref/page-template.md and to this file so a new page inherits it, run check.py, then confirm the RENDER rather than the markdown.
Stopping mid-way to ask for a go leaves the change half-applied, which is strictly worse than either finishing or not starting: a renamed label with a dozen sentences still naming the old one, or a rule written on one page and in no template.
Verify on the artifact a reader opens, because source-is-correct is not page-is-correct: a dead watcher and a shut <details> each produced a correct file and a wrong page.
The page's own source is what keeps a rewritten Opening from promising something the rest of the page does not establish.
The title is a phrase in SENTENCE CASE that says what the page is FOR (JL 260801, ruled on the design board's QB4 ยง8). Capitalize the first word and proper nouns and nothing else; a defined term keeps its capitals. A colon may carry a short subtitle, and that is usually where the purpose lands: The page template: one grammar every page kind obeys rather than Page Template design, which mixes two cases and names only a topic. On the Index the title is the only line a reader gets before choosing, so a title naming its subject alone makes them open the page to learn what the page was for. Sentence case is a string test a checker can own; whether the title states a purpose is a judgment and belongs to the Evaluation contract below.
An Opening keeps one fixed physical shape: one real question paragraph, then one plain rationale paragraph.
THE FIRST BLANK LINE IN ## Opening IS THE SPLIT (JL 260801, ruled on QB4 ยง1). Above it is the ONE paragraph a reader sees without clicking, joined into a single block; below it is the More details drawer, behind a click. Nothing reports a blank line in the wrong place, so the failure mode is a page whose Opening renders as one bare question while its explanation sits unread. The visible paragraph is 4-5 sentences, about five lines on screen: target ~450 characters, HARD CEILING 520, measured on the RENDER. 520 is what check.py enforces (OPENING_MAX_STAGE_CHARS); ~450 is the comfortable length, not the limit. Write it in PLAIN ENGLISH for a reader whose English is weak: a shorter common word always beats a precise rare one. Its shape is the question, what the question's own words mean, why that is hard, what this page decides. NEVER open with a list that will grow: name examples and say the set grows, so a fourth member never forces an edit; the roster lives in the Content division that owns it.
EVERY FIGURE CARRIES A CAPTION LINE ABOVE IT (JL 260801, ruled on QB4 ยง2). Write **Name**: what this diagram shows. directly above the fence, one line only. A section may hold several figures, and an unlabelled one makes the reader decode it before learning what it is; the caption goes ABOVE because an explanation that arrives after the figure arrives too late.
CONTENT IS NUMBERED ALL THE WAY DOWN (JL 260801, ruled on QB4 ยง1). A division is ### 3 ยท Content, a group inside it is **3.2 ยท Group title**, and a paragraph is #### 3.2.1 ยท Its heading; an ungrouped division numbers its paragraphs #### 3.1 ยท straight through, so the depth of the number says whether a group exists. This is the same rule the board applies one level up with ยง6 against ยง6.1. Numbering is also a defect detector: it exposes a group holding exactly one paragraph, which is the floating-group-title defect, and it gives every paragraph a name a person can say in chat.
More details IS A LIST OF LABELLED PARTS, NEVER ONE BLOCK OF PROSE (JL 260801, ruled on QB4 ยง1). Each part starts with a bold label saying what it answers, then its sentences, with a blank line between parts. The two halves of an Opening have two different readers: the paragraph on stage is read straight through by someone deciding whether to stay, while More details is opened by someone who already decided and is hunting one specific thing, so they scan for a label instead of reading from the top.
A FIGURE ROW IS A LABEL AND ITS VALUE, NEVER A CLAUSE (JL 260801, ruled on QB4 ยง2). If a row could end in a period it is prose, and it belongs in the paragraph under the figure rather than inside the fence. A figure earns its fence by being scannable; a wall of clauses in a box is slower to read than the same clauses outside it.
The rationale's FIRST job is to define the words the question itself uses (JL 260801, ruled on QB4 ยง1). A sharp lead question is specific, and being specific usually means naming this board's own things, so the sharper the question the more it leans on vocabulary a cold reader does not have. Give each such term one line with a REAL EXAMPLE, never a restatement: a lifecycle-stage page carries one stage of a paper being written, such as its Results section lands where a lifecycle-stage page represents a stage does not. A restatement passes the author's own eye as an explanation, because the author already knows what the word means. Only then place the page on the board (the bearing rule), and only then argue the stake: a reader who cannot parse the question cannot be told where the page sits or why it matters. Names chosen in the question bind the rest of the page and must be used identically in Content and Law.
The rationale has no required sentence count and no required rhetorical order.
Use as many short sentences as the page needs, then stop when a cold reader can say what the page asks, why that question deserves attention, and what this page owns.
Difficulty, failure, downstream effect, and a success consequence are diagnostic prompts for missing stakes, not four slots to fill and not one sentence each.
Speak about the subject whenever possible.
This page defines ..., The hard part is ..., and It succeeds when ... are not forbidden phrases, but a writer may not use them as a reusable scaffold.
If the paragraph still fits another page after its nouns are replaced, it is generic and must be rewritten.
Move frameworks, implementation history, evidence inventories, current status, and plans to their owning sections instead of using them to pad the Opening.
Before writing back, run a local self-check:
- Compare the question and rationale with the whole target page; remove any promise the page does not support.
- Remove any sentence whose only job is filling a category such as difficulty, downstream, or success.
- Apply the noun-substitution test; wording that could introduce a sibling page is not page-specific enough.
- Preserve one sentence per source line, English only, and the no-em-dash rule.
This self-check improves the draft but never approves it.
A fresh reviewer judges the page after the writer's context is gone.
โ
Evaluation contract
Evaluation asks whether the authored page satisfies its declared requirements; it does not ask whether the reviewer personally likes the format.
The requirements stay here, in the page spec and its cited template, rather than being copied into a second evaluation skill.
The evaluator is a consumer of this contract.
Resolve applicable requirements in this order:
- The base section contract in this skill and
ref/page-template.md.
- The Page Type variant, when one exists.
- The current Page Phase contract, when the review concerns work performed under DRAFT, PROBE, REVISE, or CHECK.
- The Page's own
## Writing Style; on S Pages, also its ## Stage Contract.
- The local
### division purpose and each #### heading's immediately following (job line), when present.
A more specific source may refine a broader one but may not silently contradict it.
When two sources disagree, report a requirement conflict and stop judging that criterion until the owner resolves it.
Review four distinct axes:
| Axis | Question | Judge |
|---|
| Mechanics | Is the required structure present, ordered, addressable, and internally consistent? | check.py |
| Function | Does this section answer the reader question the contract assigns to it? | semantic reviewer |
| Evidence | Can every factual compliance claim point to visible text, a State row, or a linked artifact? | semantic reviewer |
| Readability | Can a zero-background reader understand the section without supplying a missing premise? | fresh-context reviewer |
The review units are every present ## section, every direct ### Content division, and every #### paragraph whose local job must be tested.
Use exactly four verdicts: MEETS, NEEDS WORK, N/A, and NOT VERIFIABLE.
N/A means a rule genuinely does not apply; NOT VERIFIABLE means the required evidence is unavailable and is never a pass.
When the same section changes on several pages, the batch is an additional readability unit.
Read those sections consecutively in Board order after judging them page by page.
A sentence can be clear alone and still fail in the batch when several pages reuse its opening stem, rhetorical sequence, or generic success ending.
The batch NEEDS WORK when prose is interchangeable after noun substitution or when repeated scaffolds make distinct pages sound like one form letter.
Do not repair this by demanding cosmetic synonym changes; the smallest fix is to restate each page's actual stake in its own natural order.
The report is one row per review unit:
The evaluation row: one row per reviewed unit, so a failed criterion points straight at its repair.
unit | applicable requirements + source | verdict | evidence | smallest fix
Then report requirement conflicts, mechanical findings, and one page-level verdict.
The review is read-only: it never edits prose, changes an Aim State, ticks Decision Now, or closes a page.
Execution uses existing surfaces rather than a new skill:
check.py --strict supplies the deterministic mechanical findings.
- The page's
โ
Quality Check runs the complete row-by-row rubric quickly in the current page chat.
haipipe-board-reviewer-agent runs the same contract in a fresh context after revision and adds the batch voice gate when several pages changed.
The quick check helps the author iterate; only the fresh reviewer tests whether the page stands on its own without conversation context.
There is NO ## Boundary section (JL 260731, said twice). It was added by CC on 260723 and never ruled in. What a page covers is the Opening's job; point at a neighbouring page from the prose that needs it, as a **Covered elsewhere**: part in the Opening's drawer.
The same ruling renamed three sections: ## Question -> ## Opening, ## Items to Finish -> ## Aims, ## Where we are -> ## States. src/common.py still ALIASES every old name, so a page on the old vocabulary keeps rendering correctly. Do not read that as permission. This skill claimed the removal was finished on 260731; on 260802 the board still had 26 ## Boundary sections and 45 of 55 pages on the old names, because a forgiving renderer means nobody ever sees the drift. check.py now reports every retired name as retired-section, which is the only reason this paragraph can be trusted.
One name is RESERVED inside States (JL 260731): ### Decision Now holds the decisions a machine proposes and the human must make, one - [ ] row each carrying the ask, the options, and a recommendation.
One exception is UNSETTLED and admitted: the paper board's S pages use ### Needs JL ยท tick these, which JL approved four days before this reservation, and neither ruling supersedes the other in writing; keep each board's local name until JL rules once for both (the conflict is recorded in page-types/haipipe-board-page-for-stage).
A proposal never lives only in chat: it is written there on the owning page, the human answers by ticking, and an answered row moves into the page's dated record.
The options take ONE LINE EACH, and each line says what choosing it commits you to (JL 260731: "I want the decision A, B, C, to be in a new line and explain each options, not all the options in one line").
Three labels crammed onto one line name the options and explain none, so the reader has to reconstruct the consequences before they can choose.
The recommendation is its own line, naming the letter and why it beats the others.
A Decision Now row: the shape a page uses to put one choice in front of a human.
- [ ] ๐ฃ The ask, stated as one question
One or two lines of context: what is true today, and what it costs.
A ยท the first option, and what choosing it commits you to.
B ยท the second option, and what it commits you to.
โ CC recommends B, because <the reason it beats A>.
The write anchor rule (QC1b ยง4, from a real casualty).
A machine write lands at a SECTION BOUNDARY, never at a byte offset: on 260730 a concurrent session spliced a ### block into the middle of another page's ## Opening sentence.
Appending under a named ## heading is safe; inserting by offset is how that damage reproduces at scale.
The human-decision rule (QC1b ยง5).
A verb reading a transcript can report what the transcript CLAIMS, not verify it.
So a machine may update an Aim's State only from evidence it can inspect, and may propose a human ruling as a ### Decision Now row.
Closing a row (JL 260802, amending the never-tick rule).
A machine CLOSES a ### Decision Now row once the human has answered it, and records the answer in the same write: which option, who ruled, when, and the words they used.
What it may never do is close a row nobody answered, or flip a page-level human gate.
The old rule left every answered row open, so a page showed decisions as pending that had been made hours earlier and acted on, which is the same drift the board exists to prevent.
Answered means the human said it: in chat, in a comment lane, or by ticking. A machine's own recommendation is not an answer, however confident it is.
๐ท Addressing
How a location is addressed: what each level of the board is called, and how it is written.
page QB4 #QB4
face QB4a a page whose id carries its parent's number
group #group-QB scrolls the index, opens nothing
sentence QB8's grammar haipipe-board-sentence owns everything below the section
Every id inside a fenced figure renders as a link (haipipe-board 0.53.0), so a contract that names pages is itself a map.
๐ Files
This skill's own files: what ships in the folder, and what each part is for.
haipipe-board-page/
โโโ SKILL.md this contract
โโโ CHANGELOG.md version history
โโโ ref/
โโโ page-run-contract.md
Reads haipipe-board/ref/page-template.md and ref/board-form.md ยง4 (the section mapping and requiredness) and ยง8 (on-stage order) as the authority; owns no scripts.
ref/page-run-contract.md is the shared lifecycle packet and receipt spec; executable workflow and audit machinery remain under haipipe-board.
The named next step (QC1b ยง1): live/chat.py's four hand-rolled rule strings (CHAT_RULES, FULL_RULES, BOARD_CHAT_RULES, BOARD_FULL_RULES) become this contract's consumers instead of restating it, which kills the copies, one of which has already rotted once.