| name | haipipe-board-page-for-skill |
| description | The VARIANT contract for a Board's numbered Skill and Agent mirror Pages. It loads haipipe-board-page for the base frame and adds only what a mirror Page needs: an Opening that introduces a unit instead of asking a rhetorical question, the derived-versus-authored split across three managed spans, state as a health judgment rather than a version, Aims as the unit's own open work, and Content as the unit's generated bytes. Use when writing or fixing a Skill or Agent Page, when its Opening reads like every other one, when a new unit ships and needs a Page, or when a retired unit's Page must be archived. Trigger: skill page, agent page, Skill-0, Agent-1, mirror page, skillpage, skill page Opening, working on a skill page, /haipipe-board-page-for-skill. |
| metadata | {"version":"0.4.2","last_updated":"2026-08-04","summary":"Now lives under page-types/ and composes its mirror-page structure with the current Page Phase."} |
/haipipe-board-page-for-skill ยท a skill page is not a decision page
LOAD haipipe-board-page FIRST. It owns the base: the sections and their fixed order, the five rows that define each one, the title rule, the numbering, and the evaluation contract.
This file adds only what a skill page needs and a decision page does not.
It never repeats a base rule, because a copied rule is the thing that goes a night out of date while the contract moves.
After resolving this Page Type, load the current contract from page-phases/; generated spans constrain the phase write surface but do not replace the phase authority test.
The two kinds this variant covers: both mirror something that ships elsewhere.
kind filename mirrors closes when
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Skill Skill-<n>-<slug>.md one skill FOLDER ยท SKILL.md the unit ships
Agent Agent-<n>-<slug>.md one agent FILE ยท <name>.md the unit ships
NEITHER is ever counted in the board's settled total
<n> orders the roster and never carries the version, because a filename that changed every release would break every link to the page.
A skill is LOADED into a context and an agent is DISPATCHED into a fresh one (JL 260731), which is why they are two kinds and not one.
๐ The whole page, in one picture
Every rule in this file lands in one of these slots. Read this figure first; the sections below only say WHY.
# haipipe-board-page ยท v0.11.1 โ ๐ค title ยท the version is DERIVED
state: ๐ก in flux ยท door test passed โ ๐ง HEALTH + the evidence for it
owner: JL โ ๐ง who rules on this unit
method: three managed spans syncโฆ โ ๐ง one line, how the page is kept
## Opening โ ๐ง YOURS. the three slots:
โถ what is it, what FOR ONE visible paragraph, then a
โท when, vs ONE NAMED sibling BLANK LINE, then More details
โธ where it stands, with evidence as **Label**: prose parts
๐ซ the lead sentence never ends in ?
## Writing Style โ ๐ง OPTIONAL, delete if unused
## Diagram
<!-- skill:tree:start โฆ --> โ ๐ค the folder, one purpose line
**What `x` ships**: โฆ ```tree``` per file ยท caption is generated
<!-- โฆ:end --> an AGENT's tree is EMPTY: kept
**How `x` is used**: โฆ โ ๐ง YOURS. caption, then ONE figure
```text WORKFLOW โฆ ``` drawing how the unit is used
## Content
<!-- skill:body:start โฆ --> โ ๐ค the unit's SKILL.md, its own
โฆ the whole file โฆ bytes. NEVER write in here.
<!-- โฆ:end -->
## Aims โ ๐ง the UNIT's open work
- [ ] ๐ง <what it still owes> checkboxes, no A<n> ids
<why, indented>
## States โ ๐ง dated records, newest first
<one plain paragraph: where it stands>
- 260802 CC ยท ๐ <title>
<what happened, indented>
## Files โ โ OMITTED. the tree above already
lists every file it ships
## Log
260802 2100 ยท <what changed by hand> โ ๐ง your lines go ON TOP
<!-- skill:log:start โฆ --> โ ๐ค the unit's CHANGELOG, converted
<!-- โฆ:end --> into dated Log lines
(the markers above are shortened on purpose: a literal one inside this figure reaches every mirror page's Content span, and on 260803 that fed sync a fake marker and cost one page its Aims, States and Log.)
๐ค = skillpage.py writes it and sync rewrites it. Touching it is pointless: the next sync erases you.
๐ง = a person writes it and no script may touch it. This is the half that makes the page worth more than an ls.
๐ช What makes a skill page different
A Q page asks a question and closes when its Aims are met. An S page closes when its human gate passes.
A skill page decides nothing. Its subject exists on disk before the board mentions it, ships to other people, carries its own version and its own changelog, and closes only when the unit ships.
Three consequences, and every rule below comes from one of them:
1 it has no question โ its Opening INTRODUCES; it does not ask
2 its Content is not ours โ the unit's own bytes, in a managed span
3 it has a HEALTH โ state: is a judgment about the unit, not a version
๐งญ The Opening a skill page owes (the rule this skill was opened for)
The failure, measured 260802. Five skill and agent pages on 01-boardform-260722 had Openings in one shape:
line 1 Does `<name>` <verb> one <noun> for <consumers>?
line 2 <what it owns>
line 3 The hard part is <X> without <Y>.
line 4 <consumers> depend on <Z>.
line 5 It is healthy when <W>.
Read alone each is clear. Read consecutively they are one letter with the nouns swapped, which is the failure haipipe-board-reviewer-agent 0.4.0 exists to catch and which JL caught first by eye.
The base could not have prevented it, and that is why this file exists.
The base already carries the noun-substitution test, so the rule was on the books and five writers broke it anyway.
The cause is upstream of the test: the base's Opening shape is the question, what its words mean, why that is hard, what this page decides, and a skill page decides nothing.
A writer obliged to produce a question about a unit that decides nothing can only manufacture a rhetorical one, and "Does X do X well?" has exactly one answer, "that is what it is for", which carries no information.
Give five writers the same impossible slot and they will fill it the same way. The slot was the defect, not the writers.
What replaces it. The visible paragraph answers three questions, in this order, in plain words for a reader who has never heard of the unit:
โถ WHAT IS IT, and what is it FOR
one line. A reader who stops here should be able to say what it does.
โท WHEN DO I REACH FOR IT, rather than its sibling
name the sibling you would otherwise pick, and the line between them.
A boundary stated against a real neighbour is checkable; "it owns X" is not.
โธ WHERE DOES IT STAND
the one thing to know before trusting it: what is unproven, unbuilt,
unruled, or moving fast. Never "it is healthy when ...", which describes
a hypothetical unit rather than this one.
Keep the base's physical shape unchanged: one visible paragraph, the FIRST BLANK LINE is the split, More details below it as labelled parts.
Four things a roster Opening may never do:
๐ซ THE LEAD SENTENCE NEVER ENDS IN `?` mechanical, so nobody has to judge
"rhetorical". check.py enforces it
as `skillpage-opening-is-a-question`
๐ซ paraphrase the unit's own description: Content already carries those bytes;
a paraphrase is a lossy second copy
๐ซ use the own ยท hard-part ยท depend ยท four slots produce four filler
healthy scaffold sentences and one form letter
๐ซ claim health the page cannot show โธ names evidence or says it is missing
โถโทโธ is CONTENT, not a template. The three slots say what the paragraph must ANSWER; they do not fix the order of your sentences or hand you an opening move. This matters because the base forbids a reusable scaffold, and a rule that names three slots is one keystroke away from becoming the next form letter.
The first batch written to this contract already showed the pull: 7 of 8 put a second-person pick-me line second ("Load it when...", "Reach for it when...", "Dispatch it rather than..."), and 6 of 8 closed by confessing what has not happened yet. It survived review only because each slot carried a DIFFERENT checkable fact: 155 releases, 15-1-2 files, a one-day-old merge, never dispatched, three writers died on a limit. Answer all three; do not reach for the same sentence shape to do it.
The checker agrees with this contract, and did not always. Until 260802 check.py warned opening-lead-not-a-question on every page whose lead was not a question, with no page-kind exemption, so the seven pages that obeyed THIS contract each carried a warning telling them to put the question back. A writer working the checker's list would have regressed all seven. The exemption shipped the same day the first reviewer dispatch found it. If you meet a checker rule that contradicts something here, that is a defect in one of them and not a thing to work around silently.
The test, and it is not the author's to pass. Read the changed Openings CONSECUTIVELY in board order, not one at a time. A page that is clear alone still fails if its Opening would introduce its sibling after a noun swap. Dispatch haipipe-board-reviewer-agent; the writer's own read cannot see this, because the writer knows which unit they meant.
โ๏ธ Derived and authored: the split a machine enforces
haipipe-board/cli/skillpage.py owns three spans and nothing else. Everything outside them is a person's.
DERIVED ยท skillpage.py sync rewrites, hash-checked
## Diagram <!-- haipipe:skill:tree:โฆ --> the folder tree, one purpose line per file
## Content <!-- haipipe:skill:body:โฆ --> the unit's SKILL.md, its own bytes
## Log <!-- haipipe:skill:log:โฆ --> its CHANGELOG, converted to Log lines
the title's `ยท v<version>` so the index row shows it unmaintained
AUTHORED ยท a script that rewrites one of these is a defect
## Opening ยท the WORKFLOW fence in Diagram ยท ## Aims ยท ## States
ยท the page's own hand-written ## Log lines ยท state: ยท owner: ยท method:
sync replaces only the marked spans; check REPORTS a stale hash instead of rewriting, so drift is visible rather than possible.
A green check means less than it looks. digest() hashes the frontmatter's derived facts only, by its own docstring, "so prose edits never look like drift". โ
means the metadata is current, NOT that the page's copy of the SKILL.md still matches it. Byte equality needs a regenerate-and-diff by hand.
python3 <board-skill>/cli/skillpage.py new <board> <unit> --group "<GROUP>" --stamp "YYMMDD HHMM"
python3 <board-skill>/cli/skillpage.py sync <board> [<page>|--all]
python3 <board-skill>/cli/skillpage.py check <board>
An AGENT is one file, so its tree span renders EMPTY rather than being omitted: sync replaces spans it can find, and a missing one reports forever as an older page needing repair.
The WORKFLOW fence carries the whole picture on an agent page, because there is no tree to carry it.
๐ A skill page is GENERATED, never copied from the template
Do not follow the base's create a new page steps for these two kinds. The base tells you to copy ref/page-template.md and then register the page in board.md yourself. Both are wrong here, and following them literally produces a hand-typed page with no managed spans, which skillpage.py check then reports as no managed block forever.
python3 <board-skill>/cli/skillpage.py new <board> <skill-or-agent-path> \
--group <GROUP-KEY> --stamp "YYMMDD HHMM"
The <n> in Skill-<n> is the PAGE NUMBER, not the unit. new takes max(existing) + 1, and an archived page in _archive/ does not count, so a retired Skill-1 leaves its number spent rather than free. The base writes this slot as Skill-<unit>-<slug>, where "unit" means the shipped thing everywhere else in this family; read it as the ordinal here.
Which base sections a skill page carries
๐งญ Opening REQUIRED ยท authored ยท the three slots above
โ๏ธ Writing Style optional ยท newer pages carry it, older ones do not
๐ผ Diagram REQUIRED ยท derived tree + ONE authored WORKFLOW fence
๐ Content REQUIRED ยท derived ยท the unit's own bytes, never authored
๐ฏ Aims REQUIRED ยท authored ยท the UNIT's open work
๐ States REQUIRED ยท authored
๐ Files OMITTED, and that is correct here: the derived Diagram tree
already lists every file the unit ships, so a Files section
would be a second, staler copy of it
๐ folds Log is derived-plus-authored; the rest optional
The base marks Files "allowed, advised against"; for this kind it is simply omitted, and no skill page carries one.
๐ Shipping it is not the last step: REGISTER it
A new skill folder is invisible to every agent until it is linked into the skill roster. The variant this file describes shipped on 260802 and was NOT linked, so Skill(haipipe-board-page-for-skill) failed for a whole day while the folder sat on disk. A blind door test found it: the agent concluded the skill did not exist and fell back to the base contract, which is exactly the failure this variant was written to prevent.
cd Tools && ./install.sh --global
ln -s <repo>/Tools/plugins/haipipe-toolkit/skills/<family>/<unit> ~/.claude/skills/<unit>
A session already running keeps its old roster, so the link helps the NEXT session and every agent dispatched after it, not the one that shipped the skill.
๐ฉบ state: is health, and only a person writes it
The page state: line keeps the base's four values, and on a skill page it answers one question: is this unit stable, in flux, in question, or parked?
A version cannot answer it: a unit at 0.1.0 may be finished and one at 0.9.4 mid-rewrite. So new seeds ๐ด OPEN and a person changes it. The version rides the TITLE, never state: and never the filename, so a machine number and a human judgment never compete for one line.
The readable note after the emoji must carry the evidence, not a mood:
โ
๐ก in flux ยท ~60 releases in 11 days, 3 open defects
โ
๐ก in question ยท existence unruled since 260729
โ
๐ก in flux ยท consumers declared, none measured
๐ซ ๐ก in flux โ says nothing a reader can check
๐ซ ๐ก in flux ยท v0.9.0 โ that is the title's job
๐ด OPEN on a unit that ships is almost always a page nobody finished, not a real judgment.
๐ฏ Aims and States on a skill page
A skill page's Aims are the unit's own open work, not the page's. The page is finished the moment it describes the unit truthfully; the unit is not.
Three sources fill them, and the third is the one people miss:
โ what the unit itself still owes unbuilt verbs, unwritten contracts
โก what is unproven about it shipped but never run, never measured
โข a defect another page ROUTED here because this unit ships the file
โข is correct routing, not passing the buck: the page that finds a defect is rarely the page that ships the file, and a finding parked on the finder's page is a finding nobody owns. Name the page it came from.
The FORM here overrides the base, and that override is claimed on purpose. The base wants - A<n>.<m> ยท target ids with a testable Done when and one State row mirroring every Aim id exactly once, and writing-rules.md forbids a checkbox on a canonical Aim. A skill page does none of that:
โ
ON A SKILL PAGE Aims - [ ] / - [x] <emoji> <the unit's open work>
indented explanation ยท no A<n> id ยท no Done when
States dated records, NOT one row per Aim
- YYMMDD WHO ยท <emoji> <title>
WHY the base's Aim ids key to CONTENT DIVISIONS, and this page's Content is
the unit's own bytes in a managed span. There are no divisions of OURS to
key to, so an A<n> id would point at somebody else's headings.
An Aim here is a to-do about the UNIT, and a checkbox is honest about that.
Flagged by the first independent reviewer, which correctly refused to judge the Aim-to-State map on eight pages because three contracts disagreed and none claimed the override.
Never leave Page generated <date>. Nothing ruled yet. on a page whose unit ships. That is the generator's stub, and it is a claim that nobody has looked, which stops being true the moment somebody has.
๐ When a unit retires
git mv the page into _archive/, remove its line from board.md ## Pages, and add BOTH its id and its old Q-Skill-<name> alias to ## Links pointing at the archived path, so every existing citation still resolves. Then grep the board for prose that still names the unit as live: a Log line recording what was true when written STAYS, and a sentence in live prose claiming it still ships is now false.
Proven on haipipe-board-index, retired 260802: the page went to _archive/, its id still resolved, and the sweep found eight live-prose sentences on four other pages plus one dead citation on a sibling board.
The template. template.md, beside this file. ONE template serves every page of this type: two pages of it differ in what they say, never in what shape they are, so nothing has to be resolved before writing one. Copy it, fill every <slot>, and delete each RULE comment as you satisfy it.
๐ Files
page-types/haipipe-board-page-for-skill/
โโโ SKILL.md this variant contract
โโโ CHANGELOG.md version history
Owns no scripts. The generator is haipipe-board/cli/skillpage.py; the base frame is haipipe-board-page; the writing standard is haipipe-board/ref/writing-rules.md; the roster's design record is the board's QC3a (how a folder becomes a page) and QC1b (which units exist at all).