How to use it, by role
One tool, but what you have in hand and what you want out decide the path through it. Five readers, five paths. Start from the one closest to you.
| You are | What you have | What you want | Read |
|---|---|---|---|
| implementing a public rule (a statute, a published policy, a tariff) | the article, or the policy PDF | code that does what the article says, and that notices the amendment | 1. Implementing an existing public rule |
| implementing a rule of your own that already exists: an internal policy, your service's terms or tariff, a spreadsheet, and perhaps an implementation that runs today | the policy document, the spreadsheet, the running code | code that does what the document says and answers like the current implementation | 2. Implementing an existing rule of your own |
| designing a new rule (a new public rule, an internal rule, the terms of an online shop or a service) | the conditions, in prose or in your head | a table with no gap and no contradiction, and the pages that people read to check it or that get published | 3. Designing a new rule |
| implementing from a finished rule | a .rule that passes check |
code in your own language that answers exactly like the table | 4. Implementing from a new rule |
holding an API's or a message's contract (a .proto, OpenAPI, a JSON Schema) and wanting it kept in line with the business rule |
the contract's file and the rule's table | a CI run that says so whenever the contract and the rule move apart | 5. Holding an API contract to the rule |
The middle step is the same on every path: nothing comes out of a table that does not pass rulec check (What it proves). Every command below is one of these:
Every step below is one of three kinds: something to hand to an agent, something rulec does, or something a person decides. Transcribing an article or a policy into a table, drafting from a spreadsheet, the one line of an adapter around legacy code, wiring the generated code in: all of that an agent can do. Proving there is no gap and no overlap, pinning a source, holding the table to a legacy implementation or to past records, checking that twelve languages agree: rulec does that, mechanically. What stays with a person is deciding the conditions, checking the table, ruling on which side of a mismatch is wrong, and rereading a source after an amendment or a replacement. Under each heading below is who does that step.
1. Implementing an existing public rule
You have a statute or a published policy and want code that does exactly what it says. The lead role here is the source: which row came from which article, held to a copy of the text, so that an amendment is noticed.
1-1. Transcribe, citing the article
Who: the agent
An agent or a person transcribes; what matters is that every table or row ends with @source article, so that where it came from stays with it. For a statute, source names the law's id and the date the text is read as of. The word after law says which database: none for e-Gov, the Japanese government's statute database, and ecfr for the US federal regulations — source osha = law ecfr "29 CFR 1910" asof 2026-01-01, cited as @osha "§1910.157".
source stamp_act = law "342AC0000000023" asof 2026-04-01
source measures_act = law "332AC0000000026" asof 2026-04-01
define reduced : bool = made <= 2027-03-31 @measures_act 第91条
table base @stamp_act 別表第一
policy unique
| stated | amount | -> tax : money[JPY] |
unstated | false | - | 200JPY |
r3 | true | >=10_000JPY <=100_000JPY | 200JPY |
The whole notation is in Write a rule. A supplementary provision is cited as @stamp_act 附則第3条, an amending law's as @stamp_act 附則(令和七年三月三一日法律第一三号)第3条.
1-2. Fetch the copy and pin it
Who: the agent
check never reads the network. The article's copy lives beside the rule, and its digest is written into the rule. Two commands:
$ rulec source fetch rules/stamp_duty.rule
measures_act: fetched 第91条 (sha256:85faf53f6f6e8196)
$ rulec source pin rules/stamp_duty.rule
measures_act: pinned 1 fragments
pin writes one line under the source: 第91条 sha256:85faf53f6f6e8196. The copies go to sources/law/<law id>@<date>/; commit them.
1-3. Check
Who: rulec. The agent fixes the table until it passes
When the article's side changes, check stops there. A copy that differs is E038, naming the definitions to reread:
$ rulec check rules/stamp_duty.rule
error[E038]: Fragment `第91条` of source `measures_act` has changed
--> rules/stamp_duty.rule:7 source measures_act
|
7 | 第91条 sha256:85faf53f6f6e8196
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pinned: sha256:85faf53f6f6e8196
|
The copy now: sha256:625713b9504d23dc
Definitions to reread: definition reduced, table reduced_rate
A missing pin is E037, a missing copy E039; rulec explain E038 explains any of them.
1-4. Show it to a person
Who: a person, who compares the article with the table. rulec renders the page
Comparing the article with the table is a person's job. rulec doc renders the page, quoting the cited article from the copy.
Under the table's heading, the page reads:
Source: measures_act 第91条 (law 332AC0000000026, as of 2026-04-01; in force from 2026-04-01, as amended by Act No. 12 of 2026)
> 第九十一条
> 平成二十六年四月一日から令和九年三月三十一日までの間に作成される…
The reader compares the rows with that quotation and nothing else. How to read the page is in Showing it to people.
1-5. Generate and hold the code to the table
Who: the agent. rulec checks that the twelve languages agree
$ rulec gen rules/stamp_duty.rule --out generated/
$ rulec test generated/
ok japan_stamp_duty_split (Python) 296 vectors
ok japan_stamp_duty_split (SQL) 296 vectors
…
The header of every generated file names the article, its date and its digest, so a reader of the code can tell which text it was made from:
Where an implementation already runs, hold the table to it before anything is replaced, as in 2-3.
1-6. Notice the amendment
Who: rulec, weekly in CI. A person rereads the article and decides
Statutes get amended. check is held to the copy, so this is the one way to learn of an amendment; put it in a weekly CI job.
$ rulec source outdated rules/pension_premium.rule
厚生年金保険法: the amendment enforced on 2027-09-01 changes 第20条; the version in force from that day needs a reread rule
add `source 厚生年金保険法_20270901 = law "329AC0000000115" asof 2027-09-01` and transcribe the rows in force from that day from it
第20条: - 六〇五、〇〇〇円以上
第20条: + 六〇五、〇〇〇円以上六三五、〇〇〇円未満
第20条: + 第三二級
第20条: + 六五〇、〇〇〇円
…
What changes, from when, and the source line to add. The day an amendment takes effect is written as a row condition on a date column (月分 >=2027-09-01), with the old rows and the new rows in the same table; a gap or an overlap between them stops check.
Take the date as an input, and the amendment folds in
An amendment usually says "applies to documents made on or after the day it comes into force; earlier ones follow the old rule". The switch is not the day you run the code but the day the document was made, the wage paid, the month insured. Take that date as an input and write it into the row conditions, and the versions need no separate files.
Putting it in CI is on the install page. outdated exits 1 when something changes, so its output can become an issue as it is.
2. Implementing an existing rule of your own
An internal policy, the terms or the tariff of your own service, a spreadsheet someone keeps, code that already runs. The rule is not public, but it is decided and in force, and you want code that does the same. The lead role here is the comparison: unlike a statute, the document cannot be fetched again, so it is pinned whole by its digest; and where an implementation or past records exist, the table is held to them and every mismatch comes back by row.
2-1. Start from what you have
Who: the agent. A person confirms every line marked guess
A spreadsheet becomes a first draft. Every guess is marked, so only the marked places need a look.
rule parcel_fee v1
description "A draft that rulec import made from tariff.xlsx (sheet Base). Every line marked guess is for a person to confirm"
enum dest_values = domestic | canada | overseas # guess: the values seen in this column, as an enum; add what is missing, and rename the aliases
enum weight_values = <=2000g(v1) | >2000g(v2) # guess: the values seen in this column, as an enum; add what is missing, and rename the aliases
inputs
dest : dest_values
weight : weight_values
outputs
fee : money[USD] round down(1USD) # guess: the rounding's direction and grid come from the source; if it has none, write down that this is a placeholder
…
A policy document is transcribed as in 1-1. If all there is is the running code, hand that code to an agent to transcribe, and hold the table to the code in 2-3. The running code is not touched.
2-2. Pin the document as a file
Who: the agent. rulec notices a replaced document
It cannot be fetched again, so the document itself sits beside the rule and its digest, whole, goes into the rule. It is cited as @terms, or — to say which table of the document was transcribed — as @terms table1, the first table of the document in document order (表1 is the same name in Japanese).
source terms = file "shipping-terms.md"
table base_rate @terms table1
policy unique
| dest | weight | -> base : money[USD, incl_tax] |
| north_america | <=10lb | 8USD |
| north_america | >10lb | 14USD |
| not: north_america | <=10lb | 26USD |
| not: north_america | >10lb | 42USD |
Citing a table makes rulec source fetch take that table out of the document and write it beside it. A sheet is a table in a workbook (.xlsx), a w:tbl in a Word file (.docx), and what it looks like in Markdown and CSV. A PDF or a scan cannot be read here: hand an extractor (docling and the like) to --via, or cite the document whole as @terms.
$ rulec source fetch rules/shipping_fee.rule
terms: took out table1 (3 rows by 3 columns, sha256:c846fef7727dd6e0)
$ rulec source pin rules/shipping_fee.rule
terms: pinned sha256:d1156fa90a72194c
terms: pinned 1 fragments
From here on, an amount in the table has to be a value the copy shows, which is what catches a mistyped digit.
When the document is replaced, check stops with E038 and names the tables that cite it; whether the file changed is known on the spot, from its digest. With a url "…" on it, rulec source outdated asks where it came from, and says whether a cited table moved or only something this rule does not transcribe.
$ rulec check rules/shipping_fee.rule
error[E038]: The copy of source `terms` has changed
--> rules/shipping_fee.rule:6 source terms
|
6 | source terms = file "shipping-terms.md" sha256:a4b42e3e6c346e56
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pinned: sha256:a4b42e3e6c346e56
|
The copy now: sha256:a4b1a4052a111009
Definitions to reread: table base_rate, table surcharge
Reread the document; if what was transcribed still holds, rewrite the line as follows to pin the new copy.
A mistyped digit looks like this. 14USD written as 11USD sits on the rounding grid, leaves no gap and overlaps nothing: every other check stays green and these two are what fail.
$ rulec check rules/shipping_fee.rule
error[E116]: The amount of row 4 is not in the copy it cites
--> rules/shipping_fee.rule:24 table base_rate row 2
|
24 | | north_america | >10lb | 11USD |
| ^^^^^ not in the copy: 11USD
|
The copy cited: terms table1
An amount is not rewritten as it is transcribed, so either it was mistyped or it came from somewhere else. …
warning[W120]: The copy of table1 states values no row uses
Stated in the copy, used by no row: 14USD
The two name both halves of the same slip. W120 also catches a row that was never transcribed — the completeness check cannot, because the inputs of a dropped row fall into one of the rows that remain.
The page for people quotes the copy under the table's heading — "Source: terms table1 (shipping-terms.md, sha256:d1156fa90a72194c)", then the table itself — and adds one line to what was verified: Every amount in this table is a value the copy it cites (terms table1) shows (E116). The source table above, the rule's table below, and that line between them.
2-3. Hold it to the code that runs today
Who: the agent, for the adapter's one line and verify. A person rules on each mismatch
Where an implementation already runs, hold the table to it before anything is replaced. The legacy code is wrapped in an adapter of about twenty lines, and the cases built from the table's boundaries go through both. rulec prints the adapter's template; the one line to write is the call into the legacy code. The legacy code itself is not touched. The rule here and in 2-4 is the corpus's parcel tariff, parcel_rate.rule (pounds, inches, USD).
# rulec adapter template (rule parcel_rate).
# It only exchanges JSON Lines over stdin/stdout. Call the legacy implementation from here.
import json, sys
sys.stdin.readline() # handshake
print(json.dumps({"ok": True, "impl": "legacy@REPLACE_ME"}), flush=True)
for line in sys.stdin:
line = line.strip()
if not line:
continue
req = json.loads(line)
d = req["in"] # inputs: weight, girth, dest, signature
# Call the legacy implementation here.
got = 0 # TODO: legacy.compute(d)
print(json.dumps({"id": req["id"], "out": {"fee": got}}, ensure_ascii=False), flush=True)
$ rulec verify rules/parcel_rate.rule --adapter python3 adapter.py
Compared 96 / matched 93 (96.875%)
Counterpart: legacy@2024-03
Affected 3 (3.125%) amount +6
table size_of row 2 / table base_rate row 7 / table fuel_rate row 2 / table signature_fee row 1 3 records difference +2 uniform total +6
Example: dest=overseas, girth=23, signature=true, weight=1 → rule fee=47 / legacy fee=45
Mismatches come grouped by the rows that matched. Here only the row for small parcels going overseas disagrees. Whether that is a defect in the legacy code, a transcription error in the table or a rounding convention is decided from the row and its example; a mismatch is not automatically anyone's bug.
2-4. Hold it to past records
Who: the agent. A person rules on each mismatch
Without running code, but with records of past cases (the inputs and the values that came out), the rule is applied to the records. Records are one JSON object per line; their shape is checked first, then they are replayed.
$ rulec fixtures lint records.jsonl rules/parcel_rate.rule
records.jsonl: 96 records (96 observed, 0 filled)
No format problems.
$ rulec replay rules/parcel_rate.rule --fixtures records.jsonl --terse
Compared 96 / matched 93 (96.875%)
Counterpart: records.jsonl
Affected 3 (3.125%) amount +6
table size_of row 2 / table base_rate row 7 / table fuel_rate row 2 / table signature_fee row 1 3 records difference +2 uniform total +6
Both comparisons are described on Compare and replay.
2-5. Check and generate
Who: a person checks, the agent generates
The person who checks it gets the page rulec doc renders, with the document quoted under each table's heading, as in 1-4. Generating and holding the twelve languages to the table is 4. Implementing from a new rule.
3. Designing a new rule
Shipping fees, coupon conditions, whether a return is accepted, an internal criterion, a new public rule: something still being decided that you want to settle as a table. The lead role here is the check: every gap and every contradiction comes back with a concrete input that shows it, so what you forgot to decide is visible before you decide.
3-1. Write the table first
Who: a person decides the conditions. The agent or the person writes the table
Conditions as columns, the answer as the last column. "Canada and the US, eight dollars up to ten pounds" becomes one row.
rule shipping_fee v1
description "Standard delivery fee"
enum zone = domestic | canada | overseas
group north_america = domestic, canada
inputs
dest : zone
weight : mass[lb] range >=1lb <=70lb
outputs
fee : money[USD, incl_tax] round up(1USD)
table base
policy unique
| dest | weight | -> fee : money[USD, incl_tax] |
| north_america | <=10lb | 8USD |
| north_america | >10lb | 14USD |
| not: north_america | <=10lb | 26USD |
| not: north_america | >10lb | 42USD |
If the rule already lives in a spreadsheet, a first draft can be made from it. Every guess is marked, so only the marked places need a look.
Whether your rule fits a table at all is settled first on Does your rule fit.
3-2. Check it
Who: rulec. A person answers each witness
A gap comes back with the input that falls through it, and the shape of the row to add. Only the amount is a person's to decide.
error[E101]: Completeness gap: some input matches no row
--> rules/tariff.rule:14 table decision
|
14 | table decision # source: tariff.csv (guess: replace with the document's name and date)
| ^^^^^^^^ the input space is not fully covered
|
An input that matches no row: dest = overseas, size = S60
hint: add a row that matches this input.
The shape of the row to add: `| overseas | S60 | 8USD |`. Its output values are copied from the first row to give a shape that parses; they are not the right amounts.
A contradiction stops with an input both rows match:
error[E105]: Overlapping rows: the same input matches row 4 and row 9
--> rules/tariff.rule:25 table decision
Both rows match: dest = canada, size = S60
Fix until it passes. What you fix is the table, never code. The seven checks are on What it proves.
3-3. Write the examples
Who: the person who decided the answers. The agent may write them into the file
The answers you decided go into examples, and every check runs them. The "for instance" of a spec becomes a test that does not go away.
3-4. Render the pages for people and for customers
Who: rulec (rulec doc). The people who check the rule and the customer read
From the same table, one page per reader. For the people who check the rule, the facts the table does not show: what was verified, which row hides which, which rounding is provisional. For the customer, no aliases and no diagnostic codes, and instead the answer on both sides of every threshold.
$ rulec doc rules/shipping_fee.rule > shipping_fee.md
$ rulec doc rules/shipping_fee.rule --audience customer > shipping_fee_article.md
3-5. Know the impact of a revision before it ships
Who: rulec (rulec diff). A person decides whether it ships
When a rule is revised, what it does can be known first — in two ways, and the first needs nothing but the two versions.
With no records, rulec diff answers which inputs get a different answer, as a region in
the rule's own columns, plus the claim that there are none outside it.
$ rulec diff parcel_rate.rule parcel_rate_new.rule
rule parcel_rate v3 → v4
210 cells, of which 210 are inputs that can occur: 194 same, 16 differ, 0 unsettled, 0 unrealized
signature = false and dest = north_america and weight >=11lb <=70lb and girth >=23in <=60in
fee: 19 → 20
rows: table size_of row 2, table base_rate row 3, table fuel_rate row 1, table signature_fee row 2
example: dest=domestic, girth=23, signature=false, weight=11
signature = true and dest = north_america and weight >=11lb <=70lb and girth >=23in <=60in
fee: 23 → 24
rows: table size_of row 2, table base_rate row 3, table fuel_rate row 1, table signature_fee row 1
example: dest=domestic, girth=23, signature=true, weight=11
outside this region the two versions answer alike.
The revision raised the fuel rate for north_america from 5% to 6%, and yet weight and
girth are in there: the fee is rounded up to the dollar, and on every other row the
new surcharge comes to the same dollar as the old one, so the rise is rounded away. That
comes out of the whole rule, not out of the row that changed.
With past records (one JSON object per line), both versions are applied to the same records and the answer is how many of yours move, by name.
$ rulec fixtures lint records.jsonl rules/parcel_rate.rule
records.jsonl: 96 records (96 observed, 0 filled)
No format problems.
$ rulec diff parcel_rate.rule parcel_rate_new.rule --fixtures records.jsonl --terse
Compared 96 / matched 86 (89.583%)
Counterpart: parcel_rate.rule → parcel_rate_new.rule
Affected 10 (10.417%) amount +10
table size_of row 2 / table base_rate row 3 / table fuel_rate row 1 / table signature_fee row 1 10 records difference +1 uniform total +10
Run the first before the second: it says what can move, and the second says how many of your records land there. --format json names every record that moved, by its line and tag. Where an implementation already runs, 2-3 holds the table to it before anything is replaced. All of it is on Compare and replay.
4. Implementing from a new rule
You have a .rule that passes check and want it inside your app or your batch, in your language. The lead role here is the generated code; what you write is the caller.
4-1. Generate
Who: the agent
Under generated/, one directory per language. Python, TypeScript, JavaScript, Rust, Ruby, PHP, Go, Swift and Java get a function; SQL gets one query over a relation of inputs and the same query as a PostgreSQL function; Wasm gets one module; NumPy gets the rule as data and one fixed evaluator. No runtime, no dependency.
4-2. Read how to call it
Who: the agent
You do not read the generated code to call it; the inventory says how.
$ rulec api rules/shipping_fee.rule | jq -r .python.signature
def shipping_fee(dest: Prefecture, weight: Gram, total: YenInclTax, member: MemberKind) -> YenInclTax:
$ rulec api rules/shipping_fee.rule | jq -r .go.signature
func ShippingFee(in Input) (YenInclTax, error)
Values are integers in the declared unit (1999 for 1,999 g, a rate as a number of steps) and enum members are spelled as the inventory spells them. The entry checks ranges and enums, so a value outside the declaration is refused rather than computed in silence. The details are on Generate and call.
4-3. Hold every language to the table
Who: rulec (rulec test)
Every generated language is run over the cases built from the table's boundaries and compared with the reference evaluator, byte for byte.
$ rulec test generated/
ok shipping_fee (Python) 68 vectors
ok shipping_fee (TypeScript) 68 vectors
ok shipping_fee (Go) 68 vectors
ok shipping_fee (SQL) 68 vectors
ok shipping_fee (Wasm) 68 vectors
…
A toolchain that is not installed is skipped, and the skip is reported.
4-4. Wire it in
Who: the agent
Pick the shape the destination takes.
| Destination | What to use | Where to read |
|---|---|---|
| your application's code | the generated function | Generate and call |
| a recalculation in the database, a closing batch | the SQL query, one statement over the input relation | SQL is a query, and the same query as a function |
| an HTTP endpoint with no server of your own | the same query as a PostgreSQL function, behind PostgREST or Supabase | SQL is a query, and the same query as a function |
| a browser, or any host at all | the Wasm module | Wasm |
| a place where an agent has to decide | the generated MCP server, the rule as one tool | The rule as a tool for an agent |
| a form or an API entry | the JSON Schema from rulec schema |
The input checked from the same table |
Generated code is never edited. What you want changed is in the table, and a change to the table changes every language at once.
4-5. Keep it in step when the table changes
Who: CI (rulec gen --check)
Commit the generated code and regenerate in CI with --check. A table that changed while its generated code did not stops the build there.
The whole job is on the install page, with the two lines that post the impact of a revision to a pull request.
5. Holding an API contract to the rule
The shape of an API's request or of a message, and the values allowed in it, are usually set
by a contract: a .proto with Protovalidate's annotations, OpenAPI, a JSON Schema. The
business rule also says which values it takes. The two are written by different people in
different files, and when they drift apart nobody notices.
When a contract changes, a tool like buf breaking checks that the change is compatible on
the wire. Whether the business decisions it feeds still hold is left out, and by design:
buf breaking does not read custom options such as Protovalidate's rules, and adding a value
to a request enum is not a breaking change to it or to oasdiff. We have found no tool that
checks it. rulec checks that, from the rule's side. The lead role here is the contract, and nothing has to be
generated.
Between a request and the rule's answer there are three joints:
| Joint | What is checked | When | By |
|---|---|---|---|
| request and contract | that the request passes the contract's validation | at run time, at the service's door | Protovalidate, the OpenAPI validator |
| contract and the rule's inputs | that every path exists, that the enums' value sets agree, and that every value the contract lets through is one the inputs take | in CI | rulec check |
| the rule's inputs and the table's rows | that the rows cover the declared inputs exactly once | in CI | rulec check |
rulec takes the last two. The first stays with the validation already in place.
5-1. Bind the inputs to the contract
Who: the agent
Each input says with from where in the contract it comes from, and shape names the
contract.
shape shipment = proto "contracts/shipment.proto" shop.v1.CreateShipmentRequest
inputs
dest : region from shipment.destination.region
fragile : bool from any shipment.parcels where handling = HANDLING_FRAGILE
parcels : number range >=1 <=20 from count shipment.parcels
When the contract holds an enum, import proto "<file>" <Enum> -> <enum of this rule>
(import jsonschema for a JSON Schema) ties the rule's enum to the contract's set of values.
How to write both is in Write a rule, under Imports and under Inputs taken from
the caller's object, and two worked rules with their contracts beside them are in
Examples.
5-2. Hold them together
Who: rulec (rulec check)
Every rulec check reads the contract's file and holds it to the rule. What it finds:
| Mismatch | Code |
|---|---|
| a field the rule names is not in the contract (renamed, removed) | E121 |
| the type the rule takes does not fit the contract's | E120 |
| the contract's enum and the rule's hold different values | E032 |
a value that came through the contract has no row and no default |
E033 |
| a value the contract lets through is one the rule's input refuses | E122 |
| a row is reached only by values the contract never lets through | W123 |
a constraint between two inputs is one the contract does not keep |
E123 |
| a row is reached only by a combination the contract never lets through | W124 |
The one met most is E122. A contract that puts no cap on an order's lines, for example:
$ rulec check rules/order_shipping.rule
error[E122]: The contract lets `order.lines` hold 51, which the rule refuses
--> rules/order_shipping.rule:13
|
13 | lines : number range >=1 <=50 from count order.lines
| ^^^^^^^^^^^^^^^^^^^^^^ the contract lets through 1 or more; lines takes >=1 <=50
|
A value that passes the contract's validation is still refused at the door of the generated code: an API answers the request with an error, and a Kafka consumer stops or sends the message to the DLQ.
hint: if that value cannot occur, narrow the contract with "minItems": 1, "maxItems": 50. If it can, widen the rule's range and decide what it answers for that many. Which of the two is a person's decision.
An order of 51 lines passes the contract's validation and is refused by the rule: an API
answers it with an error, and even where no generated code runs, the rule has no answer for
that many. fix.text is the keyword to add to the contract, here "minItems": 1,
"maxItems": 50.
5-3. Decide which side to change
Who: a person
A mismatch can be the contract's error or the rule's. If an order of 51 lines really cannot come, narrow the contract; if it can, widen the rule's range and decide what it answers for that many. rulec offers both; which one is for the people who own the contract and the rule.
5-4. Stop on every change
Who: CI (rulec check)
With the contract's file where the rule can see it, putting rulec check in CI is all there
is to it. A change to the contract and a change to the rule are held together by the same
job.
--diff-base reports only what is new on the branch. A contract kept in another repository
is fetched beside the rules before the run.
5-5. Decide whether to generate
Who: a person
No generated code has appeared in any of this. The service's implementation can stay as it
is, and the rule can be kept only to check the contract. To hold the implementation to the
table as well, rulec verify in 2-3 does that.
To generate, rulec gen also writes a function that takes the request in the contract's
shape (Generate and call).
The same holds for the contract of a message on a queue such as Kafka. A message that passes the contract's validation and is refused by the rule stops the consumer or goes to the DLQ; CI finds it before any message is sent.
Where next
Write a rule (.rule) What it proves Generate and call Compare and replay