Skill v1.0.0
currentAutomated scan100/100version: "1.0.0" name: hora description: Implement an application from its spec. Decides where a project stands and runs the five skills that do the work — spec, setup, plan, build, accept — one feature at a time, each to acceptance before the next starts. Runs at the root of the hora repository. Started or restarted only by an explicit /hora invocation.
hora
The orchestrator. Decide where this project stands, run the skill that comes next, and own every git operation on the way.
/hora does no implementation of its own. Five skills do the work:
| Skill | Does | Runs | |
|---|---|---|---|
| `/hora-spec` | writes the version's spec, in conversation — stage 0 reads what already exists, then its own seven stages | once per version, until stage 7 passes | |
| `/hora-setup` | creates the repositories the spec declares, fills in the project's values, reads the real tree | once per version, idempotent | |
| `/hora-plan` | fixes the version, verifies the spec in conversation, writes the feature list | once per version, re-entered every run | |
| `/hora-build` | takes one feature through the eighteen checkpoints | once per feature | |
| `/hora-accept` | runs the full unit suites every time, and the acceptance review at the invocation's reach | at each feature's checkpoint 18 (scoped), and once as a whole-version sweep (full) |
An emergency fix is not one of the five. /hora-hotfix takes one defect to main on its own, gives up the acceptance review, and records what it gave up as a debt. /hora reports that debt; /hora-plan turns it back into work (../hora-hotfix/SKILL.md).
Replacing a running system starts before the five, and `/hora` never starts it. /hora-replace describes the old system from its code in several passes and proposes a scope, and a person places what it wrote in annex/ and request/ before /hora-spec runs (../hora-replace/SKILL.md).
Read references/structure.md before anything else — the repository layout, where a per-repository command runs, and the three invariants all come from there. references/commits.md holds every git rule.
The shape of a run
/hora-spec ─> /hora-setup ─> /hora-plan ──┬─> /hora-build #A ─> /hora-accept ─┐├─> /hora-build #B ─> /hora-accept ─┤└─> /hora-build #C ─> /hora-accept ─┴─> sweep ─> merge
One feature goes all the way to acceptance before the next one starts. Backend, then frontend, then acceptance — per feature, not per layer. Building every backend task, then every frontend task, then testing, means the first time anyone finds out whether a feature works is after all of them are written.
Re-entrancy is the center. A single session does not run to the end. Each run decides where it is and continues from there. Nothing is ever redone because a session ended — every checkpoint's checkbox is written the moment it passes.
Serial down to the checkpoint. No feature ever runs alongside another, and no checkpoint alongside another checkpoint.
`/hora-fast` is the other scheduler. It builds several features at once, each in its own git worktree, on the same feature files this one writes. A person chooses it by invoking it instead of /hora (../hora-fast/SKILL.md).
Inside a checkpoint, its units do run together. Five of the eighteen divide into units whose files are exclusive — a table, a module, an operation, a component, a screen — and each gets an implementer of its own. The checkpoint stays one gate with one exit condition (../hora-build/SKILL.md, "Step 5 — splitting a checkpoint into units").
Whether hora can start at all
The procedures `/hora` orders are not in this repository, and /hora never puts them in place itself. They arrive as skills of their own, alongside these, and this is the one thing to confirm before deciding anything else.
Is there at least one skill under .claude/skills/ whose name carries anhoc- / hor- / hof- / hos- prefix?if not → stop. Report that the implementationskills are not equipped, and ask forthem to be equipped before rerunningIs /hora-setup under .claude/skills/ too?if not → stop. Report that code setup is notequipped, and ask for it beforererunning
`/hora-setup` is asked for here because it is not in this package either. What it does is one stack from beginning to end — which repositories exist, what fills them, what to read once they arrived — so it is written by the boilerplate that knows that stack, and equipped from there. /hora orders it like the rest, and a project whose boilerplate has not put it in place cannot get past step 2.
Nothing here checks the hora skills themselves. /hora is one of them, so a session that reached this line has already proved they are equipped. What cannot be known from the inside is the other package's state, and that is the whole of what this section asks.
A partial set is not a failure. Which of them a repository equips is its own decision, and a checkpoint that finds nothing covering its work says so and carries on (references/structure.md, "How the match is made"). Only the empty case stops, because there nothing is covered at all.
How they are equipped is not this file's business. Say what is missing, not what command to run — the route differs by repository, and naming one of them here would be wrong wherever the other is used.
Deciding where you are
With that settled, do this every time — a fresh start and a restart alike.
0. git fetch origin --prune, for the hora repository and every declared rowthat already exists. Then check for a hotfix that landed on main(references/commits.md, "Keeping release/<version> current"), and read.hora/hotfix/ for any record whose debt: still reads open.Then git -C <row> worktree list, for every declared row: a worktree under.worktrees/ is a feature /hora-fast has in flight. Stop, and say to drainit through /hora-fast (../hora-fast/SKILL.md, "Switching between the twoschedulers")1. Does the target version have a spec at all — a specs/<version>/spec.md withcontent in it? if not → /hora-spec.A version with no spec declares nolayout, so /hora-setup has nothingto read and /hora-plan nothing toverify2. Are all declared repositories present, per the current spec's layout?if any is missing → /hora-setup3. Always run /hora-plan. It fixes the version, and reconciles the featurelist against specs/ on every re-entry4. Does .hora/questions/<version>/open.md still hold an unresolvedblocking: yes? if so → stop, unless the runmay go on past it (step 4,after this list). Report whatto fix5. Does .hora/tasks/<version>/_plan.md still hold an unfinished feature — anentry with a [ ] box that the ## Acceptance sweep entry does not alreadyclose? if so → /hora-build, on thefirst one that is ready6. No [ ] entry remains that the ## Acceptance sweep entry does not close, and_sweep.md's newest block does not read reach: full with a passing verdict,a version-criteria: line accounting for every criterion the versiondeclared, and a tips: line every declared row's release/<version> stillpoints at → /hora-accept, whole-version6a. It does, and entries that sweep closes still stand [ ]→ /hora-plan again, to set themand their checkpoint 18 offthat block (../hora-plan/SKILL.md, "collapses to onesweep")7. _sweep.md's newest block reads reach: full with a passing verdict, aversion-criteria: line accounting for every criterion the versiondeclared, and a tips: line every declared row's release/<version> stillpoints at, and every entry in _plan.md is [x]→ merge (references/commits.md,"Merge order into main";references/done-criteria.md,"When a version is done",conditions 1 and 3)
Step 0 is also what catches `release/<version>` up with a `hotfix/*`. /hora has no scheduler: this fetch and the one right after every merge into release/<version> are the only two occasions it gets to notice one landed on main.
An open hotfix debt is reported here, never acted on here. Step 3's /hora-plan is what turns it back into work (../hora-hotfix/SKILL.md, "Paying the debt back").
Step 4 stops only where `Whether the run may go on past an open blocking question` (`../hora-plan/SKILL.md`) says no. The decision lives in /hora-plan, beside the question file it reads, so /hora and /hora-plan never answer it differently.
`/hora` does not ask before running this check, or before acting on an ordinary result. It stops and asks once the check turns up something it cannot resolve on its own.
Step 1 is not "write the spec for them". /hora-spec writes nothing without somebody reading it first, and a run that reaches step 1 with nobody there to answer stops there.
Step 3 runs even when the feature list already exists. A spec keeps moving while implementation is under way. Only once /hora-plan's reconciliation shows no difference does a version move on.
Step 5 reads only the entries that carry a checkbox, so a listed feature is never a candidate. A feature listed under Baseline: inventoried sits under _plan.md's ## Not accepted with no box at all, so it is neither done nor unfinished. A version whose every remaining feature is listed passes step 5 and is swept at step 6 (references/spec-format.md, "baseline"). Paying the debt is a later version's ordinary work, scheduled by a person.
Step 5 also passes over an entry whose checkpoint 18 the `## Acceptance` sweep entry covers. Its [ ] means the sweep will close this, not hand this to `/hora-build` (../hora-plan/SKILL.md, "collapses to one sweep"; ../hora-build/SKILL.md, "Where to start").
Steps 6 and 7 read the newest block's own `reach:`, never whether `_sweep.md` exists. That sweep may be invoked before every feature is done, and every run appends a block, so the file's presence says only that it ran at least once. A sweep invoked at the eighth of twenty gates writes a truthful reach: scoped.
They read `version-criteria:` beside `reach:`, for the same reason one level up. reach: full says the run reached every feature acceptance could reach; the version's own criteria reach no feature's gate at all (references/spec-format.md, "15. Version acceptance criteria").
They read `tips:` because a pass describes the code it drove. Step 0's hotfix catch-up, a retake or an update/ merge after the sweep moves a tip, and the pass no longer covers what would merge (../hora-accept/SKILL.md, "Recording the result").
Keyed that way the two steps leave no gap. Whatever fails step 7's test — no record, reach: scoped, a failed verdict, a short version-criteria: line, a stale or missing tips: line — satisfies step 6's predicate, so the run goes back to /hora-accept.
Step 6a exists because the run that earns a collapsed version's checkboxes must also set them. /hora-accept records and never writes _plan.md; /hora-build never opens those entries, which is the collapse; so /hora-plan is the writer, off the sweep's own record. Left to the next invocation's step 3, the merge happens first — and a released version's plan is never rewritten (../hora-plan/SKILL.md, "Resolve the diffs first").
Step 7 tests condition 1 as well, and not condition 3 alone. A passing sweep says the work was accepted; the checkboxes say the record caught up.
Report the decision in one line before starting work — for example, "continuing 1.0.0. 4 of 11 features done, building #payroll from checkpoint 6".
What /hora owns, and what it never does
Every git operation happens in the main session — whether /hora runs it directly or a skill it invoked does (/hora-setup initializing a row, /hora-build cutting a feature branch). No agent any skill starts ever touches git.
| Who does it | ||
|---|---|---|
| git, in every repository | the main session — /hora and the skills it runs. Never an agent | |
writing .hora/ | the skill whose work it records (/hora-plan the plan, /hora-build the checkpoints, /hora-accept the acceptance records) | |
writing specs/ | `/hora-spec`, one approved section at a time, and `/hora-plan`, one approved edit at a time. Nobody else (references/structure.md, invariant 1) | |
| writing code and tests | the agents /hora-build starts |
Manual verification is not one of the phases. A human does it whenever they want, in the backend row, with the commands /hora-setup recorded in .hora/tree/<repository>.md. What is required is the local end-to-end environment checkpoint 17 builds: whenever a run drives a browser, /hora-accept stops without it. A gate run that skips the live review is the one run that neither requires the stack nor brings it up, and its record says so (../hora-accept/SKILL.md, "What is in scope").
Where the procedures live
`/hora` holds the order. It holds no procedure and no pass/fail criterion. How to write a resolver, a migration, a component or a test — and what an acceptance review looks at — all live in the @openreachtech/hora-skills-ort-* packages, equipped under this repository's own .claude/skills/.
Never write one of those procedures into a hora skill (references/structure.md, "The division of labor").
The closing report
The outer `git status` shows nothing from inside the nested repositories. Run it at the root and only updates to .hora/ are visible, so commits get forgotten.
Check and report `git status` for the hora repository and for every declared repository. The number of repositories differs per project, so walk the declaration.
git status --short --branchgit -C <project name>-<declared row> status --short --branch # for every row
`--branch` matters now, not just `--short`. Every repository is expected to be on release/<version>; one sitting on anything else is worth surfacing.
What the report includes:
the target version, and which skill the run reachedhow many features are done, how many are left, and which checkpoint thecurrent one stopped atevery open question — its Q<n> id, its category, its blocking value, one lineof what it is, and a link to the file it is in (references/structure.md,"Citing a question in a report"). Never a bare countthe last acceptance verdict, and what it sent backevery feature this version listed rather than accepted — by id, never a count,and with what rests on each oneevery open hotfix debt — its <hotfix-id>, the features it touched, and a linkto its record. Never a bare countgit status for every repository, including the branch (state it explicitly ifanything is uncommitted, or if a branch is not release/<version>)what the next run of /hora will start from
Write it in the language of whoever ran it, always (references/structure.md).
Every question is named and linked, whatever its blocking value (references/structure.md, "Citing a question in a report"). "Two questions remain" is not a report.
When it stopped with a blocking: yes outstanding, put what the human has to do first — which section to add what to, and the link, at the top.
Every `eslint-exception` question gets its own line, by name, with its link — never counted among the ordinary questions.
Every feature the version listed rather than accepted is named by id too, and never counted. Name each one, and name what rests on it: a dependent records Rests on: #x (not accepted) in its own feature file (../hora-plan/SKILL.md, "One file per feature").
This report is where such a debt is most easily lost. The verdict and the findings are what everybody reads, and a closing report that ends at "passed" is the sentence somebody remembers a month later (../hora-accept/SKILL.md, "Recording the result").
When a version cannot proceed, lay out the choices
A version with unfinished features blocks the next one from starting. State the ways out.
1.0.0 has 3 unfinished features. 1.1.0 exists under specs/, but versions runserially, so it cannot start yet.Remaining: #payroll #bonus #year-endbuild it → just run /hora againdrop it → mark the section kicked: yes in specs/1.0.0/spec.mddefer it → kicked: yes in 1.0.0, kicked: no on the specs/1.1.0/ sidesplit it → cut the release at the last accepted feature: kicked: yeson everything past the cut, the rest handed to the nextversion through /hora-spec(/hora-spec-horizon, "Splitting a version under way")
A listed feature is never one of the remaining ones, and it is never offered these ways out. It is running code nobody has specified yet, and the way out is a later version writing its two blocks (references/spec-format.md, "baseline").
`/hora` only lays out the choices; it does not decide.
References
| File | Content | |
|---|---|---|
references/structure.md | read first. The layout, where a command runs, the invariants, the division of labor, the language rule, what lives in .hora/ | |
references/commits.md | branches, commit granularity, merging, hotfix catch-up, merge order into main | |
references/done-criteria.md | what "done" means for a checkpoint, a feature, a version and a session | |
references/asking.md | how anything is put to a person — a check, a proposal or a question, and the question tool | |
references/spec-format.md | the authority on the format of specs/<version>/spec.md | |
references/levers.md | every lever, and which file owns its rules | |
specs/skeleton/spec.md | the blank spec. Headings and table headers only. Not a version | |
../hora-spec/SKILL.md | the author — how a version's spec gets written | |
../hora-spec/references/stages.md | stage 0, then the seven stages, and each one's exit condition | |
../hora-spec/references/investigation.md | what stage 0 reads, and the line between a fact and an intent | |
../hora-spec/references/principles.md | the thinking a spec is written with | |
/hora-setup, as the project's boilerplate ships it | code setup | |
../hora-plan/SKILL.md | the planner | |
../hora-build/SKILL.md | one feature through the checkpoints | |
../hora-build/references/checkpoints.md | the eighteen checkpoints themselves | |
../hora-accept/SKILL.md | acceptance | |
../hora-hotfix/SKILL.md | one urgent defect to main, the six gates it runs, and the debt that pays for the acceptance it skipped | |
../hora-replace/SKILL.md | describing a running system from its code, checking the description, and proposing a scope, before /hora-spec |
When a human asks how to write a spec, run `/hora-spec`. specs/1.0.0/spec.md ships empty, and that skill reads whatever already exists at stage 0, copies the skeleton, asks its way through seven stages, and writes each section once it has been approved.
On a project that already holds working code, stage 0 is the difference between a spec somebody dictates and one they correct.
Point them at references/spec-format.md and specs/skeleton/spec.md when what they want is the format itself, or when they would rather write it by hand (cp specs/skeleton/spec.md specs/1.0.0/spec.md). Both routes produce the same document.