Back to Yourule

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

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"
        }
      ]
    }
  ]
}
FieldMeaning
bundleFormat 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).
packThe set id. Lowercase, stable, never reused for a different set.
versionSemantic version of the set. See section 4.
rules[].id / numRule id (stable within the set) and its display number.
rules[].title / plainThe rule in plain English. The statement a human reads.
rules[].fileThe rule's markdown file inside the zip export.
rules[].checksOne 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.

TypeFieldsSemantics
regex-findpattern, flags, message, fixFails the rule when the pattern matches the text. Evidence names the matched words.
line-lengthmax, message, fixFails when any line is longer than max characters.
heading-first-h1message, fixFails unless the document has exactly one H1 and it is the first heading.
heading-ordermessage, fixFails when a heading jumps more than one level deeper than the heading before it.
conditional-missingif_pattern, unless_pattern, flags, message, fixFails when if_pattern matches and unless_pattern does not. Flag only, never auto-change, where the pack says so.
table-headersmessage, fixFails when a markdown table row is not followed by a header separator row.
extractlabel, pattern, flags, message, fixCollects 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

5. How another app loads a set

  1. Fetch /packs/<pack>/pack.json from yourule.29court.com, or read the set file from the user's account through the platform files API.
  2. Build one runner per rule from its checks, using section 3 semantics.
  3. Show the active set name and version on screen while the judges run. Swap is visible state, not a download errand.
  4. Run the text. Each rule returns clean, needs work with evidence, flagged (extract), or not run (no derivable judge, labeled as such).
  5. Stacking is allowed: several sets can be active at once, and verdicts group by set.
  6. 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.