The packs contract
Yourule owns the rule set format for 29Court. This page is the contract: the pack schema, the check types a loader must run, the versioning rules, and how another app (Value, Word, or any future app) loads a set and runs it. If a surface disagrees with this page, this page wins and the surface gets fixed.
1. Where sets live
- The catalog index is at
GET /packs/on yourule.29court.com. It lists each pack with its name, version, rule count, apack_jsonURL, azipURL, and this contract URL. - Each pack serves one machine-readable file:
GET /packs/<pack>/pack.json. - The same pack serves a zip with one markdown file per rule at
GET /packs/<pack>.zip. The zip is the human export. The pack.json is the loader format. - A saved user set lives in the owner's 29Court account as one platform file named
ruleset-<slug>.mdholding the same JSON shape described below, preceded by one header comment line. One file is the whole set, so a platform grant on the file shares the whole set.
2. Pack schema (pack.json)
{
"bundle": "docrules",
"pack": "tidy",
"version": "1.0.0",
"generated": "2026-10-10T05:56:52Z",
"source": "https://yourule.29court.com/packs/tidy",
"rules": [
{
"id": "t03",
"num": "03",
"title": "No em-dashes",
"plain": "Use commas, colons, parentheses, or shorter sentences.",
"file": "rules/t03-no-em-dashes.md",
"checks": [
{
"type": "regex-find",
"pattern": "\\u2014",
"flags": "g",
"message": "Em-dash found",
"fix": "Replace with a comma, colon, parentheses, or split the sentence"
}
]
}
]
}
| Field | Meaning |
|---|---|
bundle | Format family. Catalog packs use docrules. A user set saved by Yourule carries the same rule shape under its own object (name, slug, version, baseSets, customRules). |
pack | The set id. Lowercase, stable, never reused for a different set. |
version | Semantic version of the set. See section 4. |
rules[].id / num | Rule id (stable within the set) and its display number. |
rules[].title / plain | The rule in plain English. The statement a human reads. |
rules[].file | The rule's markdown file inside the zip export. |
rules[].checks | One or more typed checks. A rule runs when at least one of its checks runs. A rule with no check a loader can run must be labeled as having no derivable judge, never silently skipped. |
3. Check types
A loader implements these types exactly. An unknown type is reported as not run, never guessed at.
| Type | Fields | Semantics |
|---|---|---|
regex-find | pattern, flags, message, fix | Fails the rule when the pattern matches the text. Evidence names the matched words. |
line-length | max, message, fix | Fails when any line is longer than max characters. |
heading-first-h1 | message, fix | Fails unless the document has exactly one H1 and it is the first heading. |
heading-order | message, fix | Fails when a heading jumps more than one level deeper than the heading before it. |
conditional-missing | if_pattern, unless_pattern, flags, message, fix | Fails when if_pattern matches and unless_pattern does not. Flag only, never auto-change, where the pack says so. |
table-headers | message, fix | Fails when a markdown table row is not followed by a header separator row. |
extract | label, pattern, flags, message, fix | Collects matching lines as findings (for example action items). Reported as flagged, with the first match quoted. |
Canon judges in Yourule itself are the same idea in code form: each canon rule maps to a deterministic check in the page, and judges 04 and 12 are labeled deterministic first-pass judges, because a pattern check is a first pass, not a reading.
4. Versioning rules
- Versions are semantic:
major.minor.patch. - Any edit to a set mints a new version. Nothing edits a version in place. In an account file, an edit is a new platform file version and the version string inside the set rises with it.
- Old versions stay runnable. A loader that holds a set at an older version keeps running that version until the owner picks the newer one.
- Every verdict records the set name and version that produced it, plus a fingerprint of the graded text, so a verdict can be re-run against the exact set version that made it.
- A rule removed from a set stays in the old versions. Removal is a new version, not an erasure.
5. How another app loads a set
- Fetch
/packs/<pack>/pack.jsonfrom yourule.29court.com, or read the set file from the user's account through the platform files API. - Build one runner per rule from its checks, using section 3 semantics.
- Show the active set name and version on screen while the judges run. Swap is visible state, not a download errand.
- Run the text. Each rule returns clean, needs work with evidence, flagged (extract), or not run (no derivable judge, labeled as such).
- Stacking is allowed: several sets can be active at once, and verdicts group by set.
- Record name and version on every verdict you save.
Value loads canon and pack sets by this contract for its reads. Word and future apps load the same way. No app invents its own rule format.
6. The canon as a set
The canon twelve are the default set (id canon, version 1.0.0). Their statements, breaks-it and follows-it examples live in /rules.js on this host, and their zip export carries the same manifest shape as the packs: bundle, pack, version, and a rules list with id, num, title, and file.