<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: arxo</title>
    <description>The latest articles on DEV Community by arxo (@arxo).</description>
    <link>https://dev.to/arxo</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3755433%2Fabc4ff8f-88f5-4b02-8570-6efd051d433e.png</url>
      <title>DEV Community: arxo</title>
      <link>https://dev.to/arxo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/arxo"/>
    <language>en</language>
    <item>
      <title>The Statute Says $24,175. The IRS Published $24,150.</title>
      <dc:creator>arxo</dc:creator>
      <pubDate>Thu, 22 Oct 2026 19:11:13 +0000</pubDate>
      <link>https://dev.to/arxo/the-statute-says-24175-the-irs-published-24150-53ln</link>
      <guid>https://dev.to/arxo/the-statute-says-24175-the-irs-published-24150-53ln</guid>
      <description>&lt;p&gt;&lt;em&gt;Title 26, executed. Part 1 of a series: the Internal Revenue Code read as a program, and what it produces compared with what is published. &lt;a href="https://blog.arxo.io/adoption-credit-two-lists/" rel="noopener noreferrer"&gt;Part 2&lt;/a&gt; applies the 2025 tax law's amendments to the Code.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We rebuilt all 295 amounts published in section 4 of Rev. Proc. 2025-32, the IRS table of figures for 2026, from the text of the Internal Revenue Code and the price index the Code names, stating each convention the text leaves open. 216 of them match the published figures numerically, 213 without qualification. Two cannot result from the statute's own rounding rule, whatever index value is used. 57 raise the question of which year's index the law specifies. The 2027 amounts are computed from the same text and sealed by hash before the IRS publishes them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two numbers
&lt;/h2&gt;

&lt;p&gt;The head-of-household standard deduction for 2026 is published as $24,150. The base amount in the statute is $23,625. The difference is $525.&lt;/p&gt;

&lt;p&gt;The statute, §63(c)(7)(B)(ii) of the Code as amended by P.L. 119-21, says how the base is to be increased: by "an amount equal to— (I) such dollar amount, multiplied by (II) the cost-of-living adjustment" for the year, and then: "If any increase under this clause is not a multiple of $50, such increase shall be rounded to the next lowest multiple of $50."&lt;/p&gt;

&lt;p&gt;An increase of $525 is not a multiple of $50. No value of the price index turns the base into $24,150 by that rule, because the rule rounds the increase, and every increase it produces is a multiple of $50. That is the whole of the first finding, and it needs no index data to check. What the index data add is the figure the rule does produce: $24,175.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we compared, and on what
&lt;/h2&gt;

&lt;p&gt;Rev. Proc. 2025-32 sets out 63 items of inflation-adjusted figures for 2026, for Code provisions "as in effect on October 9, 2025", in its own words. We took the date literally: the official 2024 edition of Title 26 from govinfo, with P.L. 119-21 (the One Big Beautiful Bill Act, OBBBA) applied. The later 2025 public laws were checked and do not touch the indexing provisions.&lt;/p&gt;

&lt;p&gt;Each of the 295 published amounts in section 4 of the revenue procedure received an indexing record: base amount, base year, year of the adjustment, rounding rule, and the quoted statutory text that says so. The cost-of-living adjustment follows §1(f)(3)–(7): the ratio of two twelve-month averages of the Chained Consumer Price Index for All Urban Consumers (C-CPI-U), each ending on August 31. The index values are those the Bureau of Labor Statistics had published when it first released the August 2025 figure, on September 11, 2025, because §1(f)(6)(A) says so. The arithmetic is decimal, at 50 digits. A few conventions the statute leaves unstated, such as how the maximum earned income credit is rounded, were inferred from the published figures and labelled as inferred.&lt;/p&gt;

&lt;p&gt;The document we compared with is the version posted on October 17, 2025, which replaced an October 9 version at the same address. The repository holds both.&lt;/p&gt;

&lt;h2&gt;
  
  
  The computation in full
&lt;/h2&gt;

&lt;p&gt;The two twelve-month averages of the C-CPI-U, as available on September 11, 2025, are 177.113750 for the period ending August 2025 and 173.015833 for the period ending August 2024. Their ratio is 1.0236852; the statute directs that 2024 be the base year, so the cost-of-living adjustment for 2026 is 0.0236852.&lt;/p&gt;

&lt;p&gt;Increase: 23,625 × 0.0236852 = 559.56. Rounded to the next lowest multiple of $50: 550. Amount: 23,625 + 550 = &lt;strong&gt;$24,175&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The published $24,150 is consistent with a different convention: multiply the base, 23,625 × 1.0236852 = 24,184.56, and round the whole amount down to a multiple of $50. The two conventions agree for most amounts in the table. They disagree here.&lt;/p&gt;

&lt;p&gt;Head-of-household standard deduction for 2026. Base $23,625 multiplied by 1.0236852 gives $24,184.56. The statute rounds the increase of $559.56 down to $550, so the amount is $24,175. The published figure, $24,150, is consistent with rounding the whole amount of $24,184.56 down to a multiple of $50. The published increase, $525, is not a multiple of $50.&lt;/p&gt;

&lt;p&gt;The single deduction from the same clause, base $15,750, is $16,100 under both conventions, and the joint deduction, $32,200, is twice that. Only the head-of-household increase falls on the other side of a $50 step.&lt;/p&gt;

&lt;p&gt;The same pattern appears in §6334(d)(4), the amount of wages exempt from levy for each dependent. §6334(d)(4)(C) increases a base of $4,150 by the adjustment from 2017 and says: "If any increase determined under the preceding sentence is not a multiple of $100, such increase shall be rounded to the next lowest multiple of $100." For 2026 the increase is 1,167.12, rounded down to 1,100: &lt;strong&gt;$5,250&lt;/strong&gt;. Published: $5,300, which is 4,150 + 1,150, and 1,150 is not a multiple of $100. Rounding the whole amount, 5,317.12, down to $100 gives 5,300. For 2025 the same two conventions gave $5,150 under the text and $5,100 as published in Rev. Proc. 2024-40. The convention is stable; the sign of the difference changes from year to year. The qualified disability trust deduction in §642(b)(2)(C) borrows the §6334 rule and shows the same $5,300.&lt;/p&gt;

&lt;p&gt;The scale is small: $25 of deduction for a head of household, a few dollars of tax; $50 a year per dependent in the levy tables, about a dollar a week for a person whose wages are under levy. The point is the method, and whether the published figures can be verified from the statute.&lt;/p&gt;

&lt;h2&gt;
  
  
  Findings by kind
&lt;/h2&gt;

&lt;p&gt;Every amount that did not match falls into one of the kinds below. The row-by-row table, with the reconstructed figure, the rule and a note for each of the 295 rows, is in the repository.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Where&lt;/th&gt;
&lt;th&gt;What&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;Check&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;§63(c)(7)(B)(ii), item 4.14(1)&lt;/td&gt;
&lt;td&gt;Head-of-household deduction: statute $24,175, published $24,150&lt;/td&gt;
&lt;td&gt;Published figure cannot result from the statute's increase-rounding rule; consistent with rounding the whole amount&lt;/td&gt;
&lt;td&gt;Rev. Proc. 2025-32 §4.14(1); 26 U.S.C. §63(c)(7)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;§6334(d)(4)(C), items 4.50 and 4.35&lt;/td&gt;
&lt;td&gt;Per-dependent levy amount and qualified disability trust deduction: statute $5,250, published $5,300 (2025: $5,150 and $5,100)&lt;/td&gt;
&lt;td&gt;Same&lt;/td&gt;
&lt;td&gt;Rev. Proc. 2025-32 §4.50, §4.35; 26 U.S.C. §6334(d)(4)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;§213(d)(10)(B), §7702B(d)(5), items 4.27 and 4.62&lt;/td&gt;
&lt;td&gt;Long-term care premium limits and per diem. Read literally, the clause mixes two index scales (the medical component of the C-CPI-U against the medical component of the CPI-U for August 1996, scaled by the all-items ratio). The published figures match a link through the medical component itself; two of them ($930, $430) also match whole-amount rounding where the text rounds the increase ($935, $435)&lt;/td&gt;
&lt;td&gt;Question of basis. The clause directs the Secretary to prescribe an adjustment after consultation with HHS; we have not located a published act defining the adjustment applied&lt;/td&gt;
&lt;td&gt;26 U.S.C. §213(d)(10)(B)(ii)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;§§6651(j), 6652(c)(7), 6695(h), 6698(e), 6699(e), 6721(f), 6722(f), 6726(d), items 4.52–4.59&lt;/td&gt;
&lt;td&gt;Penalties for returns and statements due in 2027. The statute indexes "for the calendar year" of the filing; all 75 published rows are consistent with the 2026 adjustment. Under the filing-year reading, computed with the eleven-month mean that omits October 2025, 57 rows would differ ($555 rather than $535 for the §6651(a) minimum)&lt;/td&gt;
&lt;td&gt;Question of reading; the filing-year figures depend on index data published after the revenue procedure&lt;/td&gt;
&lt;td&gt;26 U.S.C. §6651(j); Rev. Proc. 2025-32 §4.52–4.59&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;§1(j)(3)(B), item 4.01, Table 5&lt;/td&gt;
&lt;td&gt;Estates and trusts: one amount both ends the 10% bracket (base year 2016) and starts the 24% bracket (base year 2017). Published $3,300 uses 2016; 2017 gives $3,250, and three tax amounts follow&lt;/td&gt;
&lt;td&gt;Text ambiguous; the published figures take one reading&lt;/td&gt;
&lt;td&gt;26 U.S.C. §1(j)(3)(B)(i) as amended by P.L. 119-21 §70101(b)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;§45R(d)(3)(B), §512(d)(2), §513(h)(2)(C), §6039F(d)&lt;/td&gt;
&lt;td&gt;$34,057.75 published as $34,100; $211.58 as $212; $13.878 as $13.90; $20,573.24 as $20,573&lt;/td&gt;
&lt;td&gt;Published figures are rounded; the statute states no rounding rule for these amounts&lt;/td&gt;
&lt;td&gt;the cited sections&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;§59(j), item 4.11&lt;/td&gt;
&lt;td&gt;$9,750 published for the kiddie-tax AMT exemption cap; §55(d)(4)(A)(iii) says §59(j) "shall not apply", and P.L. 119-21 made that permanent&lt;/td&gt;
&lt;td&gt;Computed correctly, for a provision that does not apply; also published in Rev. Proc. 2024-40&lt;/td&gt;
&lt;td&gt;26 U.S.C. §55(d)(4)(A)(iii)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;§642(b)(2)(C)(iii)(II); §877(a)(2)&lt;/td&gt;
&lt;td&gt;A cross-reference to "the $4,150 amount in subparagraph (A)" where the amount sits in clause (iii)(I); a substitution of "2003" for "1992" in a subparagraph that has not contained "1992" since 2017 ($211,000 as intended and published; $161,000 read literally)&lt;/td&gt;
&lt;td&gt;Drafting issues in the Code; no effect on the published figures&lt;/td&gt;
&lt;td&gt;26 U.S.C. §642(b)(2)(C), §877(a)(2)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;§4611, item 4.45&lt;/td&gt;
&lt;td&gt;$0.27 per barrel published; the Oil Spill Liability Trust Fund rate expired after December 31, 2025, leaving $0.18&lt;/td&gt;
&lt;td&gt;Already corrected by Announcement 2026-2; our computation gives $0.18&lt;/td&gt;
&lt;td&gt;Announcement 2026-2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Five amounts in four items changed between the October 9 and October 17, 2025 versions&lt;/td&gt;
&lt;td&gt;EIC completed phaseout (joint, three or more children) $70,224 → $70,244; tax at the 24% bracket (married filing separately) $17,996 → $17,966; head-of-household 24% ceiling $201,775 → $201,750; low-income housing credit ceiling $3.05 / $3,530,000 → $3.416 / $3,953,600&lt;/td&gt;
&lt;td&gt;Already corrected; our computation equals the October 17 value in each case&lt;/td&gt;
&lt;td&gt;both PDFs in the repository, with hashes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The last two rows are the control that matters most. The IRS has itself corrected six of these amounts: five, in four items, between the two versions of its document, and the oil spill rate by a later announcement. The reconstruction from the text produces the corrected value every time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the date of the index matters
&lt;/h2&gt;

&lt;p&gt;§1(f)(6)(A) fixes which values of the index count: "the latest values so published as of the date on which such Bureau publishes the initial value of the Chained Consumer Price Index for All Urban Consumers for the month of August for the preceding calendar year." The C-CPI-U is published first as a preliminary value and revised afterwards, so the values available on September 11, 2025 are not the values on the BLS site today.&lt;/p&gt;

&lt;p&gt;Of the 213 unqualified matches, 53 hold only on the September 11, 2025 values. On the revised values they would differ: the joint-return boundary between the 12% and 22% brackets would be $100,850 rather than the published $100,800; the 35%/37% boundary $769,100 rather than $768,700; the head-of-household 24%/32% boundary $201,850 rather than $201,750. A recomputation with fresh index data gives different figures and settles nothing. The index values have to be the ones the statute names, as of the date the statute names.&lt;/p&gt;

&lt;h2&gt;
  
  
  What open-source models do
&lt;/h2&gt;

&lt;p&gt;Tax-Calculator and PolicyEngine-US, two widely used open-source models of the US individual income tax, both hold $24,150 for the 2026 head-of-household deduction, taken from Rev. Proc. 2025-32. We asked each project to document its convention. The Tax-Calculator maintainer answered the same day (&lt;a href="https://github.com/PSLmodels/Tax-Calculator/issues/3191" rel="noopener noreferrer"&gt;issue #3191&lt;/a&gt;, October 21, 2026): the new revenue procedure supplies the indexed values each November, they are checked against the IRS forms early the following year, and the model stays consistent with other US income tax simulation models. The PolicyEngine-US issue (&lt;a href="https://github.com/PolicyEngine/policyengine-us/issues/10348" rel="noopener noreferrer"&gt;#10348&lt;/a&gt;) is open.&lt;/p&gt;

&lt;p&gt;Following the published figures is a reasonable choice for a model that reproduces what the IRS administers. It also means the check compares one IRS document with another: the forms take their figures from the revenue procedure, so a difference between the statute and the published figure cannot appear there. A check against the statutory text is a separate step. This is that step.&lt;/p&gt;

&lt;h2&gt;
  
  
  2027, before the IRS
&lt;/h2&gt;

&lt;p&gt;The August 2026 value of the C-CPI-U was first published on September 11, 2026. With it we computed all 307 amounts: the 295 rows above and 12 amounts whose base P.L. 119-21 set or reset, among them the $15,000,000 estate tax basic exclusion amount and the information-reporting threshold of §6041(a). One input is missing, as explained below, so every 2027 figure is stated with its treatment of that month.&lt;/p&gt;

&lt;p&gt;The result is a file, &lt;code&gt;forecast-2027.json&lt;/code&gt;, whose SHA-256 (beginning &lt;code&gt;07119073d7e96fad&lt;/code&gt;; the full value is in &lt;code&gt;PIN.sha256&lt;/code&gt;) was recorded on October 21, 2026 at 11:53 UTC; the file was published the same day in the repository and submitted to OpenTimestamps. Before publishing we checked that no general 2027 revenue procedure had appeared on irs.gov; as of October 22, 2026, none had.&lt;/p&gt;

&lt;p&gt;Every 2027 figure carries a condition, because of one missing number. BLS could not collect October 2025 prices during the lapse in appropriations, published no all-items C-CPI-U for that month, and has stated that "the October 2025 final C-CPI-U index will not be published." The statute's twelve-month average for 2027 runs from September 2025 to August 2026, and §1(f) does not say what to do when a month is missing. We computed four treatments: a mean of the eleven published months, geometric and linear interpolation of October, and carrying September forward. 163 of the 307 amounts depend on the choice. The joint-return 12%/22% boundary, for instance, is $104,050 with the eleven-month mean and $103,900 with linear interpolation. 67 amounts are the same under both readings and all four treatments we modelled; the single standard deduction, $16,600, and the joint deduction, $33,200, are among them.&lt;/p&gt;

&lt;p&gt;The head-of-household deduction for 2027 is the most informative figure in the table. With the eleven-month mean, the statute's rule, the increase rounded down to $50, gives &lt;strong&gt;$24,925&lt;/strong&gt;; rounding the whole amount down to $50 gives &lt;strong&gt;$24,950&lt;/strong&gt;, or $24,900 with October interpolated. Whichever figure the IRS prints will show which rounding it applied: because the base ends in 625, the statute's rule always produces an amount ending in 25 or 75, and whole-amount rounding always produces a multiple of $50. The per-dependent levy amount separates the two rules as well: $5,450 under the text, $5,400 if the whole amount is rounded down to $100.&lt;/p&gt;

&lt;p&gt;The penalty rows cannot be computed in advance under the filing-year reading, because the index for 2028 does not exist yet; the 2027 table shows them under the prior-year convention the published figures have followed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check it yourself in five minutes
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open &lt;a href="https://www.irs.gov/pub/irs-drop/rp-25-32.pdf" rel="noopener noreferrer"&gt;Rev. Proc. 2025-32&lt;/a&gt;, section 4.14(1). Heads of households: $24,150.&lt;/li&gt;
&lt;li&gt;Open &lt;a href="https://uscode.house.gov/view.xhtml?req=granuleid:USC-prelim-title26-section63&amp;amp;num=0&amp;amp;edition=prelim" rel="noopener noreferrer"&gt;26 U.S.C. §63&lt;/a&gt; (or the &lt;a href="https://www.law.cornell.edu/uscode/text/26/63" rel="noopener noreferrer"&gt;Cornell LII copy&lt;/a&gt;), subsection (c)(7)(B)(ii). The base is $23,625; the last sentence rounds the increase to the next lowest multiple of $50.&lt;/li&gt;
&lt;li&gt;24,150 − 23,625 = 525. Divide by 50.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That takes two minutes and no index data. For the rest: the two twelve-month averages above, one division, one multiplication, one rounding. For &lt;a href="https://uscode.house.gov/view.xhtml?req=granuleid:USC-prelim-title26-section6334&amp;amp;num=0&amp;amp;edition=prelim" rel="noopener noreferrer"&gt;§6334(d)(4)&lt;/a&gt;: 5,300 − 4,150 = 1,150; divide by 100.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/arxohq/arxo-irs-inflation-adjustments" rel="noopener noreferrer"&gt;repository&lt;/a&gt; holds the statute texts with their hashes, both versions of the revenue procedure, the index series as of the dates used, one indexing record per row quoting its rule, the scripts, and the SHA-256 of every result. Reproduction needs Python and nothing else.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we do not claim, and whom we told
&lt;/h2&gt;

&lt;p&gt;This is not legal advice, and nothing here is a recommendation to amend a return or to depart from published IRS instructions. We do not say the IRS erred: the published figures are consistent with a stable convention, and a convention may rest on a basis we have not found. We say that two amounts cannot be produced by the rounding rule as the statute words it, that one adjustment rests on a basis we could not locate in published guidance, and that one phrase, "for the calendar year", admits a reading the published figures do not follow. These are statements about text and arithmetic, and each can be checked from the citations.&lt;/p&gt;

&lt;p&gt;On October 21, 2026 we sent these findings, with the repository, to the staff of the Joint Committee on Taxation, the Senate Finance Committee, the Government Accountability Office, the Taxpayer Advocate Service, the Treasury Inspector General for Tax Administration, the Department of Health and Human Services, the AICPA Tax Section and the National Association of Enrolled Agents, to the maintainers of Tax-Calculator, PolicyEngine-US and TAXSIM, and to the tax press. When the 2027 revenue procedure appears, the row-by-row comparison goes into the same repository. Corrections to &lt;a href="mailto:hi@arxo.io"&gt;hi@arxo.io&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why we did this
&lt;/h2&gt;

&lt;p&gt;At Arxo Law we build executable models of legal texts, and the Internal Revenue Code is one of them. An executable Code needs its indexed amounts built from the statute's own rule and the index values the statute names, not copied from a table; building them is the only way to know when table and text part ways. This year they part at $25 for heads of household and $50 per dependent for people under levy, and at a question about which year's index the penalty provisions mean. Next year the question is how a missing month is treated. The test does not change: a published figure should be derivable from the text, and where it is not, the question goes to the text or to the publication.&lt;/p&gt;

&lt;p&gt;Rifat Jumagulov, founder, Arxo Law&lt;/p&gt;

&lt;h3&gt;
  
  
  Sources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Reproduction package: &lt;a href="https://github.com/arxohq/arxo-irs-inflation-adjustments" rel="noopener noreferrer"&gt;github.com/arxohq/arxo-irs-inflation-adjustments&lt;/a&gt;: &lt;a href="https://github.com/arxohq/arxo-irs-inflation-adjustments/blob/main/FINDINGS.md" rel="noopener noreferrer"&gt;FINDINGS.md&lt;/a&gt;, &lt;a href="https://github.com/arxohq/arxo-irs-inflation-adjustments/blob/main/2026-recompute/TABLE.md" rel="noopener noreferrer"&gt;2026 table&lt;/a&gt;, &lt;a href="https://github.com/arxohq/arxo-irs-inflation-adjustments/blob/main/2027-forecast/FORECAST.md" rel="noopener noreferrer"&gt;2027 forecast&lt;/a&gt;, &lt;code&gt;forecast-2027.json&lt;/code&gt;, &lt;code&gt;PIN.sha256&lt;/code&gt;, &lt;code&gt;SHA256SUMS&lt;/code&gt;, &lt;code&gt;sources/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;IRS: &lt;a href="https://www.irs.gov/pub/irs-drop/rp-25-32.pdf" rel="noopener noreferrer"&gt;Rev. Proc. 2025-32&lt;/a&gt; (I.R.B. 2025-45), &lt;a href="https://www.irs.gov/pub/irs-drop/rp-24-40.pdf" rel="noopener noreferrer"&gt;Rev. Proc. 2024-40&lt;/a&gt;, &lt;a href="https://www.irs.gov/pub/irs-drop/a-26-02.pdf" rel="noopener noreferrer"&gt;Announcement 2026-2&lt;/a&gt;, &lt;a href="https://www.irs.gov/pub/irs-pdf/p1494.pdf" rel="noopener noreferrer"&gt;Publication 1494&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Code: &lt;a href="https://uscode.house.gov/view.xhtml?req=granuleid:USC-prelim-title26-section1&amp;amp;num=0&amp;amp;edition=prelim" rel="noopener noreferrer"&gt;26 U.S.C. §1&lt;/a&gt;, &lt;a href="https://uscode.house.gov/view.xhtml?req=granuleid:USC-prelim-title26-section63&amp;amp;num=0&amp;amp;edition=prelim" rel="noopener noreferrer"&gt;§63&lt;/a&gt;, &lt;a href="https://uscode.house.gov/view.xhtml?req=granuleid:USC-prelim-title26-section6334&amp;amp;num=0&amp;amp;edition=prelim" rel="noopener noreferrer"&gt;§6334&lt;/a&gt;; &lt;a href="https://www.govinfo.gov/app/details/USCODE-2024-title26/USCODE-2024-title26-subtitleA-chap1-subchapB-partI-sec63" rel="noopener noreferrer"&gt;USCODE-2024-title26&lt;/a&gt; and &lt;a href="https://www.govinfo.gov/app/details/PLAW-119publ21" rel="noopener noreferrer"&gt;P.L. 119-21&lt;/a&gt; on govinfo.&lt;/li&gt;
&lt;li&gt;BLS: &lt;a href="https://www.bls.gov/cpi/additional-resources/handling-missing-2025-ce-data.htm" rel="noopener noreferrer"&gt;Handling of missing 2025 data&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Earlier on this blog: &lt;a href="https://blog.arxo.io/the-law-has-unit-tests/" rel="noopener noreferrer"&gt;The Law Has Unit Tests&lt;/a&gt;, &lt;a href="https://blog.arxo.io/law-as-function-law-as-data/" rel="noopener noreferrer"&gt;Law as Function, Law as Data&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://blog.arxo.io/the-statute-says-24175/" rel="noopener noreferrer"&gt;blog.arxo.io&lt;/a&gt; on October 22, 2026.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>testing</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Same Brakes, Twice the Speed</title>
      <dc:creator>arxo</dc:creator>
      <pubDate>Sun, 11 Oct 2026 19:09:11 +0000</pubDate>
      <link>https://dev.to/arxo/same-brakes-twice-the-speed-44na</link>
      <guid>https://dev.to/arxo/same-brakes-twice-the-speed-44na</guid>
      <description>&lt;p&gt;&lt;em&gt;Science, Worked Out — from Arxo. Episode 01.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A 1,500 kg car brakes hard from 14 m/s, about 50 km/h, and stops in 14 metres. Same car, same brakes, twice the speed: 28 m/s, about 100 km/h. How far does it travel before it stops?&lt;/p&gt;

&lt;p&gt;Make a guess before you read on.&lt;/p&gt;

&lt;p&gt;If you said 28 metres, you doubled the distance along with the speed. The worked answer is 56 metres. Twice the speed takes twice the time to stop and four times the distance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two quantities, two answers
&lt;/h2&gt;

&lt;p&gt;The same motion has both a momentum and a kinetic energy. Momentum is mass times velocity: p = mv. Kinetic energy is half the mass times the speed squared: K = ½mv². Double the speed, and they part ways.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Car of 1,500 kg&lt;/th&gt;
&lt;th&gt;at 14 m/s&lt;/th&gt;
&lt;th&gt;at 28 m/s&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Momentum, p = mv&lt;/td&gt;
&lt;td&gt;21,000 kg·m/s&lt;/td&gt;
&lt;td&gt;42,000 kg·m/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kinetic energy, K = ½mv²&lt;/td&gt;
&lt;td&gt;147,000 J&lt;/td&gt;
&lt;td&gt;588,000 J&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Momentum doubles. Energy quadruples, because the speed enters it twice.&lt;/p&gt;

&lt;p&gt;Momentum tells us about the stopping time. Kinetic energy tells us about the braking distance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Momentum sets the time, energy sets the distance
&lt;/h2&gt;

&lt;p&gt;Assume a constant net braking force of 10,500 newtons, opposite to the motion. For a 1,500 kg car, that force gives an acceleration of −7 m/s²: the car loses 7 m/s of speed every second.&lt;/p&gt;

&lt;p&gt;A constant force removes momentum at a steady rate: every second takes away the same amount. Twice the momentum under the same force takes twice the time. To check this, we picked a moment for each start by dividing the starting speed by 7 m/s², which gives 2 s for 14 m/s and 4 s for 28 m/s. Then we asked Arxo for the car's speed at that moment. Both times the answer is exactly 0 m/s.&lt;/p&gt;

&lt;p&gt;A constant force also removes energy at a steady rate per metre: every metre takes away the same amount. Four times the energy under the same force takes four times the distance. Asked how far the car travels by those moments, Arxo answers 14 m for the slower start and 56 m for the faster one.&lt;/p&gt;

&lt;p&gt;The run checks itself in one more place. Using the 14 metres from the motion calculation, Arxo computes the work done by the braking force: −147,000 J. That is the car's whole kinetic energy at 14 m/s, with a minus sign because the brakes take it away. Over 56 metres the work is −588,000 J, again the negative of the starting energy. Work and energy come from different rules applied to different facts, and they match exactly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo7zia2328zb8636ra9ay.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo7zia2328zb8636ra9ay.png" alt="Same brakes, different stops. Each bar is the braking distance under a constant braking force of 10,500 N." width="799" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Now change the mass
&lt;/h2&gt;

&lt;p&gt;Keep the speed at 14 m/s and the braking force at 10,500 N, and double the mass to 3,000 kg. The same brakes now have twice as much to stop.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Same brakes, 14 m/s&lt;/th&gt;
&lt;th&gt;1,500 kg&lt;/th&gt;
&lt;th&gt;3,000 kg&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Acceleration&lt;/td&gt;
&lt;td&gt;−7 m/s²&lt;/td&gt;
&lt;td&gt;−3.5 m/s²&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Momentum&lt;/td&gt;
&lt;td&gt;21,000 kg·m/s&lt;/td&gt;
&lt;td&gt;42,000 kg·m/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kinetic energy&lt;/td&gt;
&lt;td&gt;147,000 J&lt;/td&gt;
&lt;td&gt;294,000 J&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Moment we asked about (our choice)&lt;/td&gt;
&lt;td&gt;2 s&lt;/td&gt;
&lt;td&gt;4 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Speed at that moment&lt;/td&gt;
&lt;td&gt;0 m/s&lt;/td&gt;
&lt;td&gt;0 m/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Braking distance&lt;/td&gt;
&lt;td&gt;14 m&lt;/td&gt;
&lt;td&gt;28 m&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Doubling the mass doubles both the momentum and the energy, so the time and the distance double together. Doubling the speed doubles the momentum but quadruples the energy. Of the two inputs, only the speed appears squared.&lt;/p&gt;

&lt;p&gt;The comparison holds as long as the braking force stays the same. There is another common idealisation: a grip-limited stop with a constant friction coefficient. In that model the available braking force grows in proportion to the mass, the acceleration stays the same, and the mass drops out of the braking distance. That is a different model of the stop, and it answers a different question.&lt;/p&gt;

&lt;h2&gt;
  
  
  The same square in the Highway Code
&lt;/h2&gt;

&lt;p&gt;The UK Highway Code publishes a table of typical stopping distances, which it describes as "a general guide". Its braking distances at 20 and 40 mph show the same pattern: 6 m and 24 m, twice the speed and four times the distance.&lt;/p&gt;

&lt;p&gt;The table adds a second part, the thinking distance: how far the car travels before the driver starts to brake. That part is 6 m at 20 mph and 12 m at 40 mph. With the same reaction time, doubling the speed doubles the thinking distance. Together, the two parts grow from 12 m to 36 m.&lt;/p&gt;

&lt;p&gt;Source: &lt;a href="https://www.gov.uk/guidance/the-highway-code/general-rules-techniques-and-advice-for-all-drivers-and-riders-103-to-158" rel="noopener noreferrer"&gt;The Highway Code, rule 126&lt;/a&gt;, and its &lt;a href="https://assets.publishing.service.gov.uk/media/65f97642aa9b760011fbda4e/the-highway-code-stopping-distances.pdf" rel="noopener noreferrer"&gt;typical stopping distances table (PDF)&lt;/a&gt;, accessed 11 October 2026. Contains public sector information licensed under the Open Government Licence v3.0.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it yourself
&lt;/h2&gt;

&lt;p&gt;Pick a mass and a speed, guess the braking distance, then reveal the worked answer. The page shows the rule behind each value and the result hash that identifies its run.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.arxo.io/posts/same-brakes-twice-the-speed/try/index.html" rel="noopener noreferrer"&gt;Try it yourself: same brakes, five speeds, two masses&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What was computed, what was chosen, what was assumed
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Computed by Arxo.&lt;/strong&gt; The accelerations, momenta and kinetic energies, the speed at each moment we asked about, the braking distances and the work of the brakes. Arxo applied six rules to stated inputs: p = mv, K = ½mv², a = F/m, v = v₀ + at, x = v₀t + ½at² and W = Fd. Each answer comes with its derivation and a result hash, which changes when any input or rule changes. When all the questions were run again on 11 October 2026, every hash came out identical.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chosen by us.&lt;/strong&gt; The masses, the starting speeds, the braking force and the moments 2 s and 4 s. The km/h figures are our rounding.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Assumed.&lt;/strong&gt; One constant net braking force, measured in the frame of the road, on a straight level road at everyday speeds. The model covers the car up to the moment it first stops, and it leaves out reaction time, air resistance, the rotation of the wheels, tyre grip and brake fade.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Published.&lt;/strong&gt; The Highway Code figures are quoted from its official table, as a comparison with published guidance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The facts, the questions, all 52 answers and the full derivation of each one are available &lt;a href="https://blog.arxo.io/posts/same-brakes-twice-the-speed/run/index.html" rel="noopener noreferrer"&gt;as files&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Worked out with Arxo. Models formalize; Arxo executes and proves.&lt;/p&gt;

&lt;p&gt;Originally published on &lt;a href="https://blog.arxo.io/same-brakes-twice-the-speed/" rel="noopener noreferrer"&gt;Arxo Writings&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>science</category>
    </item>
    <item>
      <title>Why the Payment Deadline Falls on November 10: From Written Rule to Verifiable Answer</title>
      <dc:creator>arxo</dc:creator>
      <pubDate>Sun, 11 Oct 2026 19:05:04 +0000</pubDate>
      <link>https://dev.to/arxo/why-the-payment-deadline-falls-on-november-10-from-written-rule-to-verifiable-answer-kfg</link>
      <guid>https://dev.to/arxo/why-the-payment-deadline-falls-on-november-10-from-written-rule-to-verifiable-answer-kfg</guid>
      <description>&lt;p&gt;Imagine a hypothetical insurance claim in Kazakhstan. The insurer receives the required documents on October 19, 2026, and, in the facts of the example, makes the payment on November 10. When does the payment deadline expire? Count fifteen weekdays without checking public holidays and you get November 9. In the Arxo calculation recorded on October 11 for this case, the deadline is &lt;strong&gt;November 10&lt;/strong&gt;. The difference is a single day off: Monday, October 26.&lt;/p&gt;

&lt;p&gt;This small difference shows what lies between a written rule and an answer about a particular case. You need the relevant version of the text, the facts, a way to count working days, and a way to see which rule produced the result. Arxo executes a formal model of the rules and connects its conclusion to the source. A person first expresses the conditions in the model and checks them against the text; simply feeding a statute to a computer does not perform that work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with the text and its version
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://adilet.zan.kz/rus/docs/Z030000446_" rel="noopener noreferrer"&gt;Article 26(1) of Kazakhstan’s law on compulsory motor liability insurance&lt;/a&gt; (in Russian) says that the insurer makes the payment within fifteen working days of receiving the documents specified in Article 25. This hypothetical case uses the portal’s state dated July 23, 2026. Its fifteen-day provision was checked again through the official API on October 11. The date attached to a source matters because a rule can change. An answer must be read against the version selected for the case and the date at which it is applied.&lt;/p&gt;

&lt;p&gt;“Fifteen working days” takes more than adding fifteen to the date on a calendar. We need to know which days count as working days in 2026. &lt;a href="https://www.gov.kz/article/16887" rel="noopener noreferrer"&gt;Kazakhstan’s official 2026 working calendar&lt;/a&gt; (in Russian) identifies October 25 as Republic Day. It falls on a Sunday, so the day off moves to Monday, October 26. That Monday is skipped in the calculation. Leave it out of the holiday information and the count ends a day earlier, on November 9.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://adilet.zan.kz/rus/docs/Z2600000352" rel="noopener noreferrer"&gt;Law No. 352-VIII&lt;/a&gt; also changes Article 25 from October 21, 2026: bank details become required and payment is made by bank transfer. It does not change the fifteen-day period in Article 26. Our example takes receipt of the required documents on October 19 as a given fact; it does not assess whether a real submission is complete or which payment method was used.&lt;/p&gt;

&lt;p&gt;The law and the calendar play different roles. The law supplies the length of the deadline; the calendar identifies the working days. To check the answer, a person compares the legal text, the selected calendar, and the model’s counting rule. The calculation record names the applied rules. The accompanying source files connect those rules to the relevant fragment of the act; the calendar is a separate input to the computation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Add the facts of one case
&lt;/h2&gt;

&lt;p&gt;The example supplies two dates: documents received on October 19 and payment made on November 10, 2026. Its author entered them as case facts. Arxo did not extract them from an insurance form. The system is then asked a narrow question: is November 10 established as the day the payment period expires? That question ties the answer to a specified event, date, and set of rules.&lt;/p&gt;

&lt;p&gt;The example’s counting policy starts on the day &lt;em&gt;after&lt;/em&gt; the documents arrive. Its calendar uses a five-day week, with Saturday and Sunday off. The first counted days are October 20, 21, 22, and 23. October 26 is skipped because of the transferred day off. The count continues through October 27–30 and the working days in November. Its fifteenth working day is November 10. The diagram shows what each input contributes.&lt;/p&gt;

&lt;p&gt;Why not look up the holiday on a phone and stop there? A calendar can identify a day off, but it does not tell you which deadline Article 26 sets or which event begins the count. The law does not list every working day in October and November 2026. The case facts give the receipt date, but they do not contain a ready-made deadline. The answer appears when these pieces are joined by an explicit counting rule.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F89mrre6bc6adzaz4638g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F89mrre6bc6adzaz4638g.png" alt="How a fixed legal text, a working calendar, and case facts lead to the November 10 deadline" width="800" height="378"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There is a useful distinction here. “Documents received on October 19” is an input. “Deadline expires on November 10” is a derived result. If the latter were quietly entered as another fact, the calculation would tell us little: it would only repeat a date someone had already supplied.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read what stands behind the date
&lt;/h2&gt;

&lt;p&gt;For this hypothetical case, the saved Arxo result establishes November 10 as the expiry date. It names the general payment-deadline rule and the rule applying fifteen working days. Their source annotations identify the Article 26 fragment in the accompanying model files. We can ask both “What date did it produce?” and “Which rule and source led to it?”&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.arxo.io/posts/from-rule-to-answer/run/index.html" rel="noopener noreferrer"&gt;Open the recorded calculation&lt;/a&gt; to inspect both answers and download the inputs, results and replay instructions. The October 11 replay returned the same result hashes for the deadline and lateness questions. The record uses the same five-day calendar described here.&lt;/p&gt;

&lt;p&gt;That path also helps a person inspect the model. Compare its steps with the article and the official calendar. Omit the transferred day off and the date changes. Change the day the documents were received and the count changes. Select another version of the law and its applicability has to be checked again. Reproducibility means the same computation can be examined on the same inputs; whether the model faithfully expresses the source remains a substantive human check.&lt;/p&gt;

&lt;p&gt;The example poses another question: was the November 10 payment late? The saved answer &lt;strong&gt;does not establish lateness&lt;/strong&gt;, and it does not establish the opposite either. On that separate question, the model derives neither conclusion. A reader can see that the payment date given in the case matches the computed deadline, while still reporting the system’s answer precisely. “Not established” is not the same as “proved false.”&lt;/p&gt;

&lt;p&gt;An answer like this can be read as a route. Look at the case facts and the date of the question, then at the result. Follow the named rules to their conditions and source annotations; separately inspect the calendar used for counting. A reviewer can then identify exactly where they agree with the model or where they need to challenge it.&lt;/p&gt;

&lt;p&gt;That is how this written rule becomes a specific answer. The fixed legal text sets the period, the calendar resolves working days for the chosen year, the hypothetical case supplies its facts, and the model connects them. In the saved calculation, the result is November 10, 2026—a date whose reasoning can be retraced step by step.&lt;/p&gt;

&lt;p&gt;Originally published on &lt;a href="https://blog.arxo.io/from-rule-to-answer/" rel="noopener noreferrer"&gt;Arxo Writings&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>programming</category>
    </item>
    <item>
      <title>One Accident, Several Laws, One Answer</title>
      <dc:creator>arxo</dc:creator>
      <pubDate>Wed, 07 Oct 2026 19:14:36 +0000</pubDate>
      <link>https://dev.to/arxo/one-accident-several-laws-one-answer-5h95</link>
      <guid>https://dev.to/arxo/one-accident-several-laws-one-answer-5h95</guid>
      <description>&lt;p&gt;&lt;em&gt;An insurer pays 730,000 tenge. The payment is twelve days late. Following the rules from the insurance statute to the Civil Code produces another 4,020 tenge—and a record of how that amount was reached.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The money has arrived. Has the insurer finished paying?&lt;/p&gt;

&lt;p&gt;In this fictional motor-insurance case, the insurer receives the required documents on 22 July 2026 and pays 730,000 tenge on 24 August. Arxo computes the payment deadline as 12 August. Payment was late; under the stated calculation inputs, the late-payment penalty is 4,020 tenge.&lt;/p&gt;

&lt;p&gt;Each part of that answer comes from somewhere different. The insurance statute supplies the payment period and the obligation to pay a penalty. The Civil Code supplies the rule for that penalty. A National Bank rate and an official calendar supply dated values. The case supplies the payment events and an explicit assumption needed for the arithmetic.&lt;/p&gt;

&lt;p&gt;A single bank transfer has led us across several sources. The useful result is an answer whose steps can be inspected together.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with events
&lt;/h2&gt;

&lt;p&gt;The example belongs to a collection of five fictional cases about Kazakhstan’s compulsory motor third-party liability insurance, known as OGPO VTS. The main case is deliberately small:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Input&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Required documents received&lt;/td&gt;
&lt;td&gt;22 July 2026&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Insurance payment amount&lt;/td&gt;
&lt;td&gt;730,000 KZT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Actual payment date&lt;/td&gt;
&lt;td&gt;24 August 2026&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Annual-to-daily rate divisor&lt;/td&gt;
&lt;td&gt;365, explicitly supplied&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Calendar&lt;/td&gt;
&lt;td&gt;The recorded official 2026 calendar&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The 730,000-tenge insurance payment is an input in this example. The calculation begins after that amount has been established. It does not reconstruct repair costs from photographs or decide the disputed facts of the accident.&lt;/p&gt;

&lt;p&gt;There is no input labelled “the insurer paid late.” That is one of the questions the rules must answer.&lt;/p&gt;

&lt;p&gt;This distinction matters when building a legal application. If a person supplies the conclusion and the software merely repeats it, the central reasoning remains outside the computation. Here, the case supplies two events: receipt of documents and payment. The model must connect them through the applicable deadline.&lt;/p&gt;

&lt;h2&gt;
  
  
  A deadline has dependencies
&lt;/h2&gt;

&lt;p&gt;Article 26(1) of the &lt;a href="https://adilet.zan.kz/rus/docs/Z030000446_" rel="noopener noreferrer"&gt;motor-insurance statute&lt;/a&gt; provides the general period used in this case: fifteen working days from receipt of the documents specified in Article 25.&lt;/p&gt;

&lt;p&gt;For documents received on Wednesday, 22 July, the recorded calendar and counting policy place the deadline on Wednesday, 12 August. The payment on 24 August comes after it. The late-payment period runs from 13 through 24 August, twelve calendar days.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgigh0om787wl1qlekkb5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgigh0om787wl1qlekkb5.png" alt="Documents received on 22 July; fifteen working days lead to a deadline of 12 August; payment on 24 August is twelve calendar days late." width="799" height="311"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The two intervals use different clocks. Working days establish when payment falls due. Calendar days measure this period of delay. A calculation that treats both intervals as the same kind of duration can get the amount wrong even when its multiplication is correct.&lt;/p&gt;

&lt;p&gt;The calendar is therefore part of the case’s supporting data. Someone checking the deadline needs the calendar used for the calculation, alongside the date and the rule.&lt;/p&gt;

&lt;h2&gt;
  
  
  The insurance law sends us to the Civil Code
&lt;/h2&gt;

&lt;p&gt;Article 26(4) imposes a penalty for late payment and refers to Article 353 of the &lt;a href="https://adilet.zan.kz/rus/docs/K940001000_" rel="noopener noreferrer"&gt;Civil Code&lt;/a&gt; for its procedure and amount. The payment-day calculation used here takes the National Bank base rate applicable on the day the obligation is performed.&lt;/p&gt;

&lt;p&gt;In the recorded case, that annual rate is 16.75%. With the explicitly supplied divisor of 365, the arithmetic is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;730,000 KZT × 12 days × 0.1675 ÷ 365 = 4,020 KZT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The amount is exact for these inputs. The case also establishes that the obligation to pay the late-payment penalty is active.&lt;/p&gt;

&lt;p&gt;The saved analysis below compares this case with payment on the deadline itself. Both have the same deadline, 12 August; payment on 24 August establishes lateness. Open the analysis to inspect the 4,020-tenge result and the penalty obligation. The interface is available in English; the case questions are in Russian.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://lens.arxo.io/a/b_832ea4dca63da6e90fb61b9c16b61decf8a97a635f41905748061a901fa43646?lang=en" rel="noopener noreferrer"&gt;Payment on the deadline and payment twelve days later&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The implementation preserves the division of responsibility between sources. The insurance rule creates the obligation; the Civil Code provides the referenced basis; dated rate data supplies a value; an accrual calculation applies it. The connection between those parts does not introduce another legal rule of its own.&lt;/p&gt;

&lt;p&gt;That is what makes the cross-reference useful to software. A reader can follow it. An executable model can carry a result across it while retaining its origin.&lt;/p&gt;

&lt;h2&gt;
  
  
  Remove one assumption
&lt;/h2&gt;

&lt;p&gt;The divisor of 365 deserves its own line in the input table. Article 353’s payment-day rate provision does not specify the annual-to-daily conversion convention. This model requires that convention to be supplied explicitly.&lt;/p&gt;

&lt;p&gt;Remove the divisor from the same case. The payment is still late: the dates and calendar are unchanged. But the model no longer derives a penalty amount.&lt;/p&gt;

&lt;p&gt;That outcome keeps two questions separate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Was payment late? Established.&lt;/li&gt;
&lt;li&gt;What penalty amount follows from these inputs? No amount derived.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A zero in the second field would erase that distinction. So would silently inserting a familiar financial convention. The saved explanation identifies the amount rule as unestablished; it does not itself trace the missing divisor through every intermediate calculation. The paired cases show exactly which input was removed.&lt;/p&gt;

&lt;p&gt;Now make a different change: supply both 24 and 26 August as the single payment date for the same claim. Those assertions conflict with the field’s uniqueness requirement. The evaluation is marked &lt;code&gt;NON_EXECUTABLE&lt;/code&gt;. Any amount retained in its diagnostic output must be read with that status; it is not an accepted answer to the conflicting case.&lt;/p&gt;

&lt;h2&gt;
  
  
  Move the case across a holiday
&lt;/h2&gt;

&lt;p&gt;Another case in the collection moves receipt of documents to 19 October 2026 and payment to 10 November. In the recorded calendar, Republic Day falls on Sunday, 25 October, with the day off transferred to Monday, 26 October.&lt;/p&gt;

&lt;p&gt;The deadline is 10 November. The alternative date, 9 November, is not established; payment on 10 November does not establish lateness. The saved analysis also contains the missing-divisor and conflicting-date variants.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://lens.arxo.io/a/b_c591f670223f98bf6eade6e1ccf0e9986367912d22bf07f3f199e4ab419dec3a?lang=en" rel="noopener noreferrer"&gt;A transferred holiday, a missing divisor, and conflicting payment dates&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These are small changes to one case, but they exercise different parts of the reasoning: date calculation, sufficiency of inputs, and consistency of assertions. A single “valid” checkbox would lose information the reader needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  The rest of the accident has its own sources
&lt;/h2&gt;

&lt;p&gt;The deadline-and-penalty example sits within a wider motor-insurance model. Following a case from policy purchase to a dispute brings further sources into view:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Question&lt;/th&gt;
&lt;th&gt;Where the model looks&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;What premium applies?&lt;/td&gt;
&lt;td&gt;The insurance statute, bonus-malus rules and annual adjustment coefficients&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;How is vehicle damage assessed?&lt;/td&gt;
&lt;td&gt;The vehicle-damage assessment rules&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What payment limits apply?&lt;/td&gt;
&lt;td&gt;The insurance statute and the relevant budget index&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Was payment late, and what penalty follows?&lt;/td&gt;
&lt;td&gt;The insurance statute, calendar, Civil Code and dated rate data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Can the claimant use a guarantee mechanism?&lt;/td&gt;
&lt;td&gt;The Insurance Payments Guarantee Fund legislation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Can the dispute go to the insurance ombudsman?&lt;/td&gt;
&lt;td&gt;The insurance legislation governing that procedure&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These are branches with their own conditions. A dispute does not, by itself, establish eligibility for every procedure. A change in the insurer’s status calls for a fresh check of the guarantee conditions. The five cases shown here exercise the payment deadline and penalty branch.&lt;/p&gt;

&lt;p&gt;A software package can connect provisions from several acts, while one act can contribute to several stages. Regulations, annual tables and calendars matter alongside statutes. Each rule and value retains its source as the case moves between them.&lt;/p&gt;

&lt;h2&gt;
  
  
  What one answer contains
&lt;/h2&gt;

&lt;p&gt;For the main case, a useful answer keeps four results together: the deadline is 12 August; payment on 24 August was late; the stated inputs yield a 4,020-tenge penalty; the penalty obligation is active. It also preserves the facts, rules and assumptions behind those results.&lt;/p&gt;

&lt;p&gt;The displayed analyses are saved evaluations. In a local check on 23 September 2026, all sixteen case-and-question evaluations in the captured collection matched their saved command-line evaluation documents byte for byte when run through the local WebAssembly engine. That checks reproduction on those fixed inputs; the legal interpretation and the evidence for the case remain separately reviewable.&lt;/p&gt;

&lt;p&gt;Arxo executes the canon. Models formalize; Arxo executes and proves. In this example, the practical payoff is that a reviewer can follow the path from two payment events through a deadline and a statutory cross-reference to an additional obligation.&lt;/p&gt;

&lt;p&gt;The bank transfer answers whether money arrived. The connected rules answer what that payment leaves owing.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published on the &lt;a href="https://blog.arxo.io/one-accident-several-laws/" rel="noopener noreferrer"&gt;Arxo blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>dsl</category>
      <category>architecture</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Law as Function, Law as Data: What Catala and Arxo Compute When They Read the Same Regulation</title>
      <dc:creator>arxo</dc:creator>
      <pubDate>Tue, 06 Oct 2026 18:32:33 +0000</pubDate>
      <link>https://dev.to/arxo/law-as-function-law-as-data-what-catala-and-arxo-compute-when-they-read-the-same-regulation-1ae7</link>
      <guid>https://dev.to/arxo/law-as-function-law-as-data-what-catala-and-arxo-compute-when-they-read-the-same-regulation-1ae7</guid>
      <description>&lt;p&gt;Two independent formalizations of the same regulation, written in two different languages, agreed on every one of 65 reference cases and 240 randomly generated ones. That result is the starting point of this article, not its conclusion. Where two systems built on different foundations agree, the interesting question is what each of them computes beyond the point where the agreement ends.&lt;/p&gt;

&lt;p&gt;Catala, developed at Inria, applies programming-language theory to computational law. Its default-calculus-to-lambda-calculus compilation step is mechanized in the F* proof assistant, and its compiler targets OCaml, Python, C and Java. Legal fidelity still depends on review of the formalization alongside the source text.&lt;/p&gt;

&lt;p&gt;Arxo Law is built on a different premise. In Catala, a statute becomes a function: inputs go in, a value comes out, and the verified compilation step preserves the formal specification. In Arxo, a statute becomes data: a package of norms with byte-pinned sources, deontic positions, priorities, interpretations and editions, which an engine executes to produce a proof graph rather than a value. Both premises are principled. They answer different questions, and this article uses one shared regulation to show where each question begins.&lt;/p&gt;

&lt;h2&gt;
  
  
  The parity experiment
&lt;/h2&gt;

&lt;p&gt;The material is a Kazakh regulation: the Rules for Determining the Amount of Damage Caused to a Vehicle (Resolution No. 14 of the Board of the National Bank of the Republic of Kazakhstan, 28 January 2016). It is a compact by-law with the shape that formal methods handle best: thresholds, percentages, deadlines counted in working days, and a small set of conditions on inspections and documents.&lt;/p&gt;

&lt;p&gt;The computational part of the Rules was implemented twice, independently, from the official text:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;in Catala 1.2.0, as six scopes covering total loss, part cost, choice of appraisers, admissibility of inspection, deadlines, and the final amount;&lt;/li&gt;
&lt;li&gt;in Arxo Law, as a package whose 67 rules cover the same points plus duties, provenance and edition metadata outside the computational comparison.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Expected outcomes for 65 reference cases were established by hand from the text and the 2026 official calendar, with a written justification for each. The same 65 cases were then run through Catala and through both Arxo evaluators (the Rust engine and the Python reference implementation), and a property-based run generated 240 further random cases across two seeds, checked against a Python oracle written directly from the text.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Check (9 September 2026)&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;65 reference cases, Catala against expectations&lt;/td&gt;
&lt;td&gt;65 of 65&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;65 reference cases, both Arxo evaluators&lt;/td&gt;
&lt;td&gt;all pass, results byte-identical between evaluators&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;240 random cases, oracle vs Catala&lt;/td&gt;
&lt;td&gt;240 of 240&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;240 random cases, oracle vs Arxo engine&lt;/td&gt;
&lt;td&gt;240 of 240&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;20 targeted mutations of the Arxo model&lt;/td&gt;
&lt;td&gt;20 of 20 killed by the test suite&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq73051l29ijtqhg7mjgl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq73051l29ijtqhg7mjgl.png" alt="The parity experiment: one pinned regulation, formalized independently in Catala 1.2.0 as six scopes and in Arxo Law as 67 rules; 65 reference cases and 240 random cases run through both; Catala 65 of 65 and 240 of 240, Arxo 65 of 65 and 240 of 240 with two evaluators byte-identical; 20 of 20 mutations caught." width="799" height="408"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The single known semantic difference between the two languages was isolated on purpose. Catala stores money to the cent and rounds a money-times-decimal product; Arxo keeps money exact and rounds only where the text says so. The comparison was therefore fixed at whole tenge, which is also what the regulation itself requires of the final amount.&lt;/p&gt;

&lt;p&gt;A second, smaller data point comes from France. Arxo's formalization of the rental-sector housing benefit (APL) was checked against the ten test cases published in Catala's own examples repository. All ten matched to the cent, and the intermediate quantities were verified in separate scenarios (13 September 2026).&lt;/p&gt;

&lt;p&gt;The conclusion of both experiments is the same. For the tested cases, both formalizations reproduce the expected computational outcomes. This does not establish equivalence for every possible input. Everything that follows is about what lies beyond the algorithm. The vehicle-damage experiment is public: both models, the 65 reference cases, the runners and the recorded results are at &lt;a href="https://github.com/arxohq/arxo-catala-parity" rel="noopener noreferrer"&gt;github.com/arxohq/arxo-catala-parity&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Axis 1: a value versus a certificate
&lt;/h2&gt;

&lt;p&gt;The clearest architectural difference is what a single call returns.&lt;/p&gt;

&lt;p&gt;A Catala scope returns a value: a number, a boolean, an optional. This is a natural product for microsimulation, where a rules engine runs over millions of households. The Catala interpreter computed one total-loss case in about 16 microseconds in our measurement, and the compiled backends, which we did not benchmark, are designed to be faster still.&lt;/p&gt;

&lt;p&gt;An Arxo call returns an evaluation document: a manifest of inputs, the results, a proof graph with every rule application and every fact it rested on, the deontic positions in force, any registered conflicts, the issues raised, and content hashes that make the whole document reproducible. On a trivial vector this document is about three kilobytes, and those bytes are what the two Arxo evaluators compare against each other. One such call cost about 0.4 milliseconds in the Rust engine and about 2.5 milliseconds in the Python reference implementation, on the same machine and the same regulation.&lt;/p&gt;

&lt;p&gt;The measurements compare different outputs and different execution paths; they are not a controlled benchmark of the languages. Arxo spends its time on fact storage, a fixed-point computation over the rules, canonical serialization and hashing, because the product is a certificate of how the answer was reached. In this profile of the Rust engine, string comparison, map lookups and allocation account for most of the cost, and the solver itself for under one percent.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu4kkbv6oltj1mv9c1fxs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu4kkbv6oltj1mv9c1fxs.png" alt="What a call returns: in Catala, inputs go through a scope and come out as a value, about 16 microseconds per call in the interpreter; in Arxo, inputs go through the engine and come out as an evaluation document with manifest, results, proof graph, positions, conflicts, issues and content hashes, about 0.4 milliseconds per call in the Rust engine." width="800" height="388"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Measurement conditions: Apple Silicon, macOS 24.6, warm runs, 9 September 2026. Catala: the &lt;code&gt;Gibel&lt;/code&gt; scope called 10,000 times inside one process, the cost of a single-call run subtracted. Arxo: the engine's test runner over the parity scenarios, the cost of a one-test run subtracted. Process start and model loading were about 40 ms for Catala and about 10 ms for the Rust engine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Axis 2: default calculus versus four-valued support
&lt;/h2&gt;

&lt;p&gt;Catala's core is the prioritized default calculus. Each variable is defined once by a base rule and a tree of exceptions with a static priority order. If exactly one exception applies, it wins; if none applies, the base rule holds; if two exceptions of equal priority apply, the program raises a conflict error and produces no value. The world is closed: a variable has exactly one value or the computation fails.&lt;/p&gt;

&lt;p&gt;Arxo's core is a four-valued support relation with defeasible rules that preserve ambiguity. A query can be established (&lt;code&gt;TRUE_ONLY&lt;/code&gt;), refuted (&lt;code&gt;FALSE_ONLY&lt;/code&gt;), supported on both sides (&lt;code&gt;BOTH&lt;/code&gt;), or unsupported (&lt;code&gt;NEITHER&lt;/code&gt;). Silence is not negation: a fact that was never asserted does not make the opposite true.&lt;/p&gt;

&lt;p&gt;For a lawyer these two models answer differently in two common situations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A fact is missing.&lt;/strong&gt; In the Catala model we wrote, a missing input is either an omitted optional that flows through as absence, or a boolean that defaults to false. In Arxo, the query is &lt;code&gt;NEITHER&lt;/code&gt;, and the evaluation document says which premise was not established. Missing evidence and established negation are distinct statuses, and the mutation suite includes a test that breaks if they are ever conflated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Two norms compete.&lt;/strong&gt; In Catala, a conflict is an error at run time, which is the correct behaviour for a system that must always produce a payment amount. In Arxo, the conflict is preserved in the answer as &lt;code&gt;BOTH&lt;/code&gt;, with both derivations in the proof graph. That is how a formalization records a genuine defect in the text or a gap in the conflict-of-laws rules instead of silently picking a side. The Lean mechanization of the semantics proves this as a theorem: when two defeasible derivations rest on incomparable grounds, both survive.&lt;/p&gt;

&lt;p&gt;Neither choice is a limitation of the other. Catala's closed world is what makes a mass-payment engine trustworthy. Arxo's open world is what makes a single disputed case explainable.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5cxnyedtxq8znxy6e2ls.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5cxnyedtxq8znxy6e2ls.png" alt="Conflicts and silence: Catala's default tree gives a value when one exception applies, the base rule or nothing when none applies, and a conflict error when two apply, with an omitted input read as absent or false by field; Arxo's four statuses are established, refuted, both sides supported, and nothing concludes it, with competing norms preserved as BOTH and silence distinct from negation." width="800" height="394"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Axis 3: what lies outside our computational model
&lt;/h2&gt;

&lt;p&gt;The vehicle-damage Rules contain more than a computation. They impose ten duties and one liberty on insurers, appraisers and victims: to inspect within a deadline, to deliver a report, to allow a second inspection, to choose an appraiser. They also delegate one quantity, depreciation, to an external methodology that the Rules do not contain, and they count deadlines in working days against the official state calendar.&lt;/p&gt;

&lt;p&gt;These parts of the regulation did not enter the Catala comparison, because we scoped that model to computational outcomes. They are first-class in Arxo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Deontic positions.&lt;/strong&gt; Duty, liberty, power and immunity are declarations with a lifecycle: a duty arises, is performed, is breached or lapses inside a window. As of 9 September 2026, &lt;code&gt;power&lt;/code&gt; appeared in 189 corpus files and &lt;code&gt;immunity&lt;/code&gt; in 54; &lt;code&gt;priority&lt;/code&gt;, the declared resolution of conflicts by rank and specialty, in 321; &lt;code&gt;interpretation&lt;/code&gt;, competing readings of one text, in 127; &lt;code&gt;presumption&lt;/code&gt; in 127 and &lt;code&gt;fiction&lt;/code&gt; in 16.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The calendar as pinned data.&lt;/strong&gt; Working days are computed against a byte-pinned snapshot of the official 2026 calendar with its holiday transfers, carried into the evaluation document by hash. A case dated outside the snapshot's coverage is reported as out of calendar range rather than guessed. In the Catala program we wrote, working days were derived by folding over a list of dates supplied as input, which is entirely adequate for a fixed year and is not the same thing as a verifiable reference to the state calendar.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Editions in time.&lt;/strong&gt; A query is evaluated on the date of the event against the edition of each norm in force on that date. The regulation's own amendment history is part of the package, and an answer states which edition it applied.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quantities with units.&lt;/strong&gt; A mileage in the wrong unit is a type error, not a silent conversion. In our Catala model the unit lives in the field name.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Catala's authors chose a function model deliberately, and the choice has paid off in exactly the domain it was made for. Tax and benefit calculation needs a value; it rarely needs to know which party is currently in breach of which duty. Private-law disputes, regulatory compliance and procedural law need the second thing at least as often as the first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Axis 4: two kinds of trust
&lt;/h2&gt;

&lt;p&gt;Both systems make a verification claim. The claims are about different links in the chain.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Catala trusts the compiler.&lt;/strong&gt; The law text and its formalization live in one literate file, and the crucial translation from the default calculus to a lambda calculus with exceptions is mechanized in F*, with type preservation and a simulation result. This proof covers the specified core translation; it is not an end-to-end proof of every compiler backend or of the legal interpretation. What the annotation says about the law is a matter for legal review of the literate file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Arxo trusts the text and checks the proof.&lt;/strong&gt; Provenance is part of the language: every source, edition and publication carries a content hash, and the compiler rejects any quoted fragment that is not an exact substring of the pinned official publication. The evaluation document then carries a proof graph, and an independent checker written in Lean 4 (21 modules, 91 theorems and lemmas, no &lt;code&gt;sorry&lt;/code&gt;, toolchain 4.33.0, counted 19 September 2026) verifies that certificate against the least model of the monotone fragment of the semantics. The checker does not compare the two Arxo evaluators with each other; it checks each one's output against the specification. Its first run over the corpus found a dangling-reference defect that both evaluators shared and that byte-for-byte comparison could never have surfaced.&lt;/p&gt;

&lt;p&gt;Compiler correctness and certificate checking are complementary. One verifies a translation step from the formal specification; the other checks a certificate against the covered semantics. Neither proves that a formalization captures every legal meaning of the source. A mature discipline of computational law will want both.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff1p2q5gllnttgb8b9wg7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff1p2q5gllnttgb8b9wg7.png" alt="Two kinds of trust: Catala's chain runs from a literate file through a compiler whose default-calculus-to-lambda-calculus step is proven in F-star to OCaml, Python, C and Java code; Arxo's chain runs from an official publication pinned by hash through a package whose quoted fragments must be substrings, to an evaluation document with a proof graph that a Lean 4 checker verifies against the least model." width="800" height="390"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Discussion: a taxonomy, not a ranking
&lt;/h2&gt;

&lt;p&gt;The parity experiment suggests a simple way to place the two systems.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Question&lt;/th&gt;
&lt;th&gt;Catala&lt;/th&gt;
&lt;th&gt;Arxo Law&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;What is a norm?&lt;/td&gt;
&lt;td&gt;A function from inputs to a value&lt;/td&gt;
&lt;td&gt;A datum: text, provenance, rules, positions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What does a call return?&lt;/td&gt;
&lt;td&gt;A value&lt;/td&gt;
&lt;td&gt;An evaluation document with proof and hashes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;How are conflicts handled?&lt;/td&gt;
&lt;td&gt;Error at run time&lt;/td&gt;
&lt;td&gt;Preserved as &lt;code&gt;BOTH&lt;/code&gt; in the answer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What does silence mean in these models?&lt;/td&gt;
&lt;td&gt;Absence or false, by field&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;NEITHER&lt;/code&gt;, distinct from negation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Where is trust anchored?&lt;/td&gt;
&lt;td&gt;Verified core compilation step (F*)&lt;/td&gt;
&lt;td&gt;Pinned sources and certificate checking for the monotone fragment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best fit&lt;/td&gt;
&lt;td&gt;Mass calculation of tax and benefits&lt;/td&gt;
&lt;td&gt;Individual cases, compliance, disputes, procedure&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The two paradigms also meet in the middle. Arxo's code-generation backends print the purely computational slice of a package into a standalone TypeScript, Python or Go module that runs without the rules engine, returning answer and status without the proof (40 of 43 executed conformance vectors matched on 14 September 2026, with no divergence across the three targets; the remaining vectors were refused by the plan with a named reason). That slice is, in effect, the part of a package that Catala would also express, and it is a natural interchange point between the two worlds: computable cores could travel from one language to the other, while deontics, editions and proof stay where they are modelled.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The tested computational slice agrees: 65 reference cases and 240 random cases produced the expected outcomes in both formalizations. The 20 mutation checks apply to the Arxo model only.&lt;/p&gt;

&lt;p&gt;The practical design choice is what a caller needs beyond that result: a value, or an evaluation document that also records provenance, editions, duties and competing derivations. The experiment makes that choice concrete without establishing that either language is universally better.&lt;/p&gt;

&lt;p&gt;To inspect or reproduce the comparison, start with the &lt;a href="https://github.com/arxohq/arxo-catala-parity" rel="noopener noreferrer"&gt;public parity repository&lt;/a&gt;: it contains both models, the reference cases, runners and recorded results.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Merigoux, Chataing and Protzenko, &lt;a href="https://arxiv.org/abs/2103.03198" rel="noopener noreferrer"&gt;Catala: A Programming Language for the Law&lt;/a&gt;, ICFP 2021.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/CatalaLang/catala" rel="noopener noreferrer"&gt;Catala source and releases&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/arxohq/arxo-catala-parity" rel="noopener noreferrer"&gt;Arxo–Catala parity experiment&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://blog.arxo.io/what-is-rules-as-code/" rel="noopener noreferrer"&gt;What Is Rules as Code?&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Originally published on the &lt;a href="https://blog.arxo.io/law-as-function-law-as-data/" rel="noopener noreferrer"&gt;Arxo blog&lt;/a&gt;. Measurements and implementation counts above are dated snapshots, not claims about later releases.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>dsl</category>
      <category>architecture</category>
      <category>opensource</category>
    </item>
    <item>
      <title>What Is Rules as Code, With a Runnable Example</title>
      <dc:creator>arxo</dc:creator>
      <pubDate>Mon, 05 Oct 2026 19:20:02 +0000</pubDate>
      <link>https://dev.to/arxo/what-is-rules-as-code-with-a-runnable-example-286f</link>
      <guid>https://dev.to/arxo/what-is-rules-as-code-with-a-runnable-example-286f</guid>
      <description>&lt;h3&gt;
  
  
  Rules as Code publishes a rule in a form a machine can execute, next to the text a person reads. Here is the definition, where the idea comes from, and a limitation period you can compute yourself.
&lt;/h3&gt;

&lt;p&gt;Rules as Code is the practice of writing a rule — a statute, a regulation, an internal policy — in a form a computer can execute, alongside the natural-language text, so that both are drafted, tested and kept in step together. The same idea travels under other names: Law as Code, Legislation as Code, machine-consumable legislation, computational law. The goal is not to automate judgment. It is to make the logic of a rule explicit, so it can be tested before it applies to anyone and reproduced after it has.&lt;/p&gt;

&lt;p&gt;A runnable rule looks like this: facts go in, a question is asked, and the answer comes back with the article it rests on. Below is one such rule, a limitation period from an international instrument, with the facts, the questions and the answers, and links to run it with your own dates.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the term comes from
&lt;/h2&gt;

&lt;p&gt;In 2018 New Zealand's Service Innovation Lab ran a three-week discovery with Inland Revenue, the Ministry of Business, Innovation and Employment and the Parliamentary Counsel Office, testing the approach on two existing pieces of legislation. Its report, &lt;a href="https://www.digital.govt.nz/dmsdocument/95-better-rules-for-government-discovery-report" rel="noopener noreferrer"&gt;Better Rules for Government&lt;/a&gt;, gave the movement its name.&lt;/p&gt;

&lt;p&gt;In October 2020 the OECD's Observatory of Public Sector Innovation published &lt;a href="https://oecd-opsi.org/publications/cracking-the-code/" rel="noopener noreferrer"&gt;Cracking the Code: Rulemaking for humans and machines&lt;/a&gt;, which proposed that some government rules exist in a machine-consumable version alongside the natural-language one, and set out what that asks of drafters, lawyers and engineers.&lt;/p&gt;

&lt;p&gt;Several tools carry the idea. &lt;a href="https://openfisca.org/en/about/" rel="noopener noreferrer"&gt;OpenFisca&lt;/a&gt;, developed in France since 2011 and released as free software, models tax and benefit rules and is used to simulate the effect of new law on households and the budget. &lt;a href="https://arxiv.org/abs/2103.03198" rel="noopener noreferrer"&gt;Catala&lt;/a&gt;, from Inria and presented at ICFP 2021, is a programming language whose code follows the structure of the statute it implements; while encoding French family benefits its authors found a bug in the official implementation. &lt;a href="https://github.com/Lexpedite/blawx" rel="noopener noreferrer"&gt;Blawx&lt;/a&gt;, by Jason Morris, is a web-based tool for encoding and testing rules with answer set programming. In Germany, the federal agency SPRIND runs &lt;a href="https://www.sprind.org/en/actions/strategic-projects/law-as-code" rel="noopener noreferrer"&gt;Law as Code&lt;/a&gt; as a strategic project aimed at official, machine-readable publication of legal norms.&lt;/p&gt;

&lt;p&gt;Most of this work targets tax and benefits: who is eligible, and for how much. Contract law, time limits and procedure appear less often. The example below is a time limit.&lt;/p&gt;

&lt;h2&gt;
  
  
  A runnable example: when does a limitation period expire?
&lt;/h2&gt;

&lt;p&gt;Article 10.2 of the &lt;a href="https://www.unidroit.org/instruments/commercial-contracts/unidroit-principles-2016/" rel="noopener noreferrer"&gt;UNIDROIT Principles of International Commercial Contracts&lt;/a&gt; (2016 edition) sets two periods. The general limitation period is three years, beginning on the day after the day the obligee knows or ought to know the facts that let it exercise its right. The maximum period is ten years, beginning on the day after the day the right can be exercised.&lt;/p&gt;

&lt;p&gt;Take a case. The obligee learned the facts on 10 March 2020. The right could be exercised from 15 January 2019. Here is the test that sits in the package modelling chapter 10, trimmed to the facts that matter; the full file also names the parties and the contract:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test "PICCL-01-GENERAL-AND-MAXIMUM-PERIODS" {
    given {
        context {
            deadline_policy PICC_LIMITATION;
            legal_time @2026-09-17;
            timezone "UTC";
        }
        assert "a2": obligee_knew_facts_on(entity_ref("urn:case:piccl:right-1"), @2020-03-10) { origin case_input; }
        assert "a3": right_exercisable_from(entity_ref("urn:case:piccl:right-1"), @2019-01-15) { origin case_input; }
        assert "a4": general_period(entity_ref("urn:case:piccl:right-1"), 3 calendar_year) { origin case_input; }
        assert "a5": maximum_period(entity_ref("urn:case:piccl:right-1"), 10 calendar_year) { origin case_input; }
    }
    evaluate truth(general_period_expires_on(entity_ref("urn:case:piccl:right-1"), @2023-03-11));
    expect truth_status == TRUE_ONLY;
    expect any_applied(GeneralPeriodOfThreeYears);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the case and ask four questions:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Question&lt;/th&gt;
&lt;th&gt;Answer&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Is the exercise of this right subject to limitation at all?&lt;/td&gt;
&lt;td&gt;Established&lt;/td&gt;
&lt;td&gt;Article 10.1(1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Does the general period expire on 11 March 2023?&lt;/td&gt;
&lt;td&gt;Established&lt;/td&gt;
&lt;td&gt;Article 10.2(1): three years beginning on the day after 10 March 2020&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Does it expire on 10 March 2023?&lt;/td&gt;
&lt;td&gt;Not established&lt;/td&gt;
&lt;td&gt;No rule makes that day the last one&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Does the maximum period expire on 16 January 2029?&lt;/td&gt;
&lt;td&gt;Established&lt;/td&gt;
&lt;td&gt;Article 10.2(2): ten years beginning on the day after 15 January 2019&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The third row is the one to read twice. "Not established" is not "false". The text says the count begins on the day after, so the model says so, and a question about the 10th finds no rule that concludes it. A reader who expected the 10th learns the difference from the model, not from a footnote.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuf7vsoy2ndjjoa1931q7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuf7vsoy2ndjjoa1931q7.png" alt="Article 10.2 as two timelines: the general period runs three years from 11 March 2020, the day after the obligee knew, and expires on 11 March 2023; a question about 10 March 2023 is not established. The maximum period runs ten years from 16 January 2019 and expires on 16 January 2029." width="800" height="394"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now the second case: the period has expired, and the obligor has said nothing about it.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Question&lt;/th&gt;
&lt;th&gt;Answer&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Is the right extinguished?&lt;/td&gt;
&lt;td&gt;Established: it is not&lt;/td&gt;
&lt;td&gt;Article 10.9(1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Is its exercise barred?&lt;/td&gt;
&lt;td&gt;Not established&lt;/td&gt;
&lt;td&gt;Article 10.9(2): the obligor never asserted the expiry&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;May the obligee still set off?&lt;/td&gt;
&lt;td&gt;Established&lt;/td&gt;
&lt;td&gt;Article 10.10: until the expiry is asserted&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Two answers that only look contradictory. The right survives, and its exercise is not barred either, because the bar needs an assertion that has not happened. Article 10.10 reads the same silence from the other side.&lt;/p&gt;

&lt;p&gt;There is a third kind of answer. Where the Principles say "could not reasonably" or "fundamentally", the model does not decide. It returns a request for the tribunal's finding, with the article that calls for it. That is what the text asks for, and the answer says so in the same place it would otherwise give a result.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd8cmh82q622cggigqv4p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd8cmh82q622cggigqv4p.png" alt="Three kinds of answer from one evaluation: established, with the article that applied; not established, because no rule concludes it; and a request for the finding the text calls for, addressed to the tribunal or the arbiter." width="799" height="362"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Run it yourself.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://picc.law.arxo.io/case-player/limitation/" rel="noopener noreferrer"&gt;Change one fact and watch the answer&lt;/a&gt;: the two cases above, article by article.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://picc.law.arxo.io/date-calculator/limitation/" rel="noopener noreferrer"&gt;Bring your own dates&lt;/a&gt;: articles 10.2 and 10.4 computed in your browser, including acknowledgement, proceedings and impediments.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://picc.law.arxo.io/verify/" rel="noopener noreferrer"&gt;Verify an answer someone sent you&lt;/a&gt;: a saved calculation is run again in your browser, from the same bytes.&lt;/li&gt;
&lt;li&gt;Connect an agent: &lt;code&gt;claude mcp add --transport http picc https://mcp.arxo.io/mcp/picc&lt;/code&gt;, or &lt;code&gt;npx -y @arxo/mcp-picc&lt;/code&gt; for a local server.&lt;/li&gt;
&lt;li&gt;Read the source: &lt;a href="https://github.com/arxohq/arxo-unidroit-picc" rel="noopener noreferrer"&gt;github.com/arxohq/arxo-unidroit-picc&lt;/a&gt;, all 210 articles in seven packages.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What an executable rule carries
&lt;/h2&gt;

&lt;p&gt;Five things travel with every answer above, and they are what makes a rule executable rather than merely encoded.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The text is pinned.&lt;/strong&gt; Each article an answer cites is a fragment of the published text, fixed by a hash of its content. The model is written from that text and points back into it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time is a parameter.&lt;/strong&gt; Every question carries a date. The edition in force on that date answers, and a question asked of the 2024 text and of the 2026 text can get different results with the same facts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Silence and judgment are answers.&lt;/strong&gt; "Not established" means no rule concludes it. "For the tribunal" comes back as a typed request, naming the article that requires the finding.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The answer reproduces.&lt;/strong&gt; An answer document holds the request, the chain of reasoning down to the articles, and the hashes of the model and the result. The verify page above runs it again and either matches or shows where it does not.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The rule has tests.&lt;/strong&gt; On 21 September 2026 the corpus of executable canons held 21,948 scenario files like the one above. They are written in one language and fail the way a broken unit test fails. &lt;a href="https://dev.to/arxo/the-law-has-unit-tests-34nc"&gt;The Law Has Unit Tests&lt;/a&gt; walks through one.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The same mechanics beyond the law
&lt;/h2&gt;

&lt;p&gt;A statute, a standard, a rulebook and a textbook share one shape: an authoritative text with an edition and a provenance, applied to facts. Law came first because it is the most demanding case, not because the mechanics stop there.&lt;/p&gt;

&lt;p&gt;Take the &lt;a href="https://handbook.fide.com/chapter/E012023" rel="noopener noreferrer"&gt;FIDE Laws of Chess&lt;/a&gt;, in force since 1 January 2023. Article 7.5.5 says that after a player's first completed illegal move the arbiter gives two minutes to the opponent, and that a second completed illegal move by the same player loses the game, unless the position is such that the opponent cannot checkmate by any possible series of legal moves, in which case the game is drawn.&lt;/p&gt;

&lt;p&gt;Here is the case as the arbiter would record it: White has completed two illegal moves, and the record is complete on whether Black can still mate.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;case SecondIllegal {
    assert "player": fide.laws.chess::player_of(entity_ref("urn:example:chess:game"), entity_ref("urn:example:chess:white")) { origin case_input; }
    assert "complete-mate-facts": fide.laws.chess::checked_player(entity_ref("urn:example:chess:white")) { origin case_input; }
    assert "illegal-count": fide.laws.chess::completed_illegal_move_count(entity_ref("urn:example:chess:white"), 2) { origin case_input; }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Case&lt;/th&gt;
&lt;th&gt;Question&lt;/th&gt;
&lt;th&gt;Answer&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Two illegal moves, mate still possible&lt;/td&gt;
&lt;td&gt;Is the game lost by White?&lt;/td&gt;
&lt;td&gt;Established, by the rule on the second illegal move&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Two illegal moves, no possible mate&lt;/td&gt;
&lt;td&gt;Is the game lost by White?&lt;/td&gt;
&lt;td&gt;Not established&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Two illegal moves, no possible mate&lt;/td&gt;
&lt;td&gt;Is the game drawn?&lt;/td&gt;
&lt;td&gt;Established&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A piece touched, no finding on intent&lt;/td&gt;
&lt;td&gt;Must White move it?&lt;/td&gt;
&lt;td&gt;A request to the arbiter: Article 4 turns on the intention, and the record does not state it&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The board, the legality of a move and the possibility of mate are facts of the record. Arxo does not play chess. It applies the Laws to what the arbiter wrote down, and it names the arbiter where the Laws do.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu24jgucxz1cp0x764pl2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu24jgucxz1cp0x764pl2.png" alt="Article 7.5.5 as a decision path over the arbiter's record: one completed illegal move gives Black two minutes; two illegal moves lose the game if Black can still mate and draw it if not; a touch whose intention is not in the record comes back as a request to the arbiter." width="799" height="383"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Laws of Chess sit in the same corpus as the Principles and are served at the same public endpoint, &lt;code&gt;https://mcp.arxo.io/mcp&lt;/code&gt;. Next to them: the IFAB Laws of the Game, with the goalkeeper's time limit across two editions; three HTTP RFCs and what happens to a Content-Length header; the CSS cascade from W3C, and which declaration wins. Each is modelled from its pinned text in the same language, and each answers with the section it rests on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Questions people ask
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Is Rules as Code the same as Law as Code?&lt;/strong&gt; The same idea under two names. Rules as Code comes from the public-sector community around the New Zealand and OECD work and covers policy and regulation as well as statute. Law as Code is the name used in Germany and in much of the academic literature. Computational law is the broader academic term.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does it replace lawyers or courts?&lt;/strong&gt; No. It computes what follows from the text on the facts supplied. Where the text calls for an assessment, "reasonable", "fundamental", "intended", the answer is a request for that assessment, addressed to the tribunal or the arbiter, with the article that requires it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What tools exist?&lt;/strong&gt; OpenFisca for tax and benefit simulation; Catala, a language whose code follows the structure of the statute; Blawx, a visual tool over answer set programming; and Arxo, where the text is pinned by content, the edition is chosen by date, the answer reproduces by hash, and an AI agent can connect over MCP.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I use it from Claude, Cursor or Claude Code?&lt;/strong&gt; Yes. One command adds the Principles as a server: &lt;code&gt;claude mcp add --transport http picc https://mcp.arxo.io/mcp/picc&lt;/code&gt;. The &lt;a href="https://www.arxo.io/mcp/" rel="noopener noreferrer"&gt;MCP page&lt;/a&gt; lists the other endpoints and what an agent can ask.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://blog.arxo.io/what-is-rules-as-code/" rel="noopener noreferrer"&gt;Arxo Writings&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>opensource</category>
      <category>dsl</category>
      <category>testing</category>
    </item>
    <item>
      <title>The Law Has Unit Tests</title>
      <dc:creator>arxo</dc:creator>
      <pubDate>Mon, 05 Oct 2026 19:13:34 +0000</pubDate>
      <link>https://dev.to/arxo/the-law-has-unit-tests-34nc</link>
      <guid>https://dev.to/arxo/the-law-has-unit-tests-34nc</guid>
      <description>&lt;h3&gt;
  
  
  A test of a statute looks like a test of code, with three differences: silence is a passing result, a test can expect a question instead of an answer, and every test carries a date.
&lt;/h3&gt;

&lt;p&gt;Here is a test. If you have ever written one for software, you have read this file before:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Law 12.2, 2024/25 edition: the goalkeeper held the ball for nine seconds.
// Date of law 1 September 2024: the 2024/25 book applies.
test "ifab-01-gk-nine-seconds-2024-25" {
    given {
        context { legal_time @2024-09-01; timezone "UTC"; }
        assert "a0": goalkeeper_within_own_penalty_area(match, i1) { origin case_input; }
        assert "a1": goalkeeper_control_seconds(match, i1, 9.0) { origin case_input; }
    }
    evaluate truth(indirect_free_kick_offence(match, i1));
    expect truth_status == TRUE_ONLY;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Given, when, then. Two facts from the match report, one question to the Laws of the Game, one expected answer. The file sits in the &lt;code&gt;tests/&lt;/code&gt; folder of the package that models the IFAB Laws of the Game, next to the rules it exercises. Run it, and Arxo executes the model of Law 12 against these facts and compares the answer with the expectation.&lt;/p&gt;

&lt;p&gt;This is not a metaphor. On 21 September 2026 the corpus of executable canons holds 21,948 such scenario files: contract law, civil codes, insurance statutes, the UN Charter, chess and football, the CSS cascade. They are written in one language, they run under one engine, and they fail the same way a broken unit test fails.&lt;/p&gt;

&lt;p&gt;The interesting part is where a test of a law stops behaving like a test of code.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Silence is a passing result
&lt;/h2&gt;

&lt;p&gt;In software, a function that returns nothing has a bug. In law, a norm that says nothing about your facts is the correct outcome, and a test has to be able to expect it.&lt;/p&gt;

&lt;p&gt;The Declaration by United Nations of 1 January 1942 binds each signatory to employ its full resources against the Axis members "with which such government is at war". The Soviet Union signed. It was at war with Germany and not at war with Japan. Does the Declaration oblige the USSR against Japan?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test "un-test-pair-not-at-war" {
    given {
        context { legal_time @1942-01-01; timezone "Europe/London"; }
        assert "un-war-de2": at_war(UnionOfSovietSocialistRepublics, Germany) { origin case_input; }
    }
    evaluate truth(employs_full_resources_against(UnionOfSovietSocialistRepublics, Japan));
    expect truth_status == NEITHER;
    expect evaluation_status == COMPUTED;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The expected answer is &lt;code&gt;NEITHER&lt;/code&gt;: the proposition is neither established nor refuted. The computation finished (&lt;code&gt;COMPUTED&lt;/code&gt;), nothing went wrong, and the Declaration is simply silent for this pair. The model does not turn missing facts into "false", because the world of a case is open: nobody asserted that the USSR was at war with Japan, and nobody asserted that it was not.&lt;/p&gt;

&lt;p&gt;The same expectation appears in commercial law. Under the UNIDROIT Principles, a non-performance is fundamental if it was intentional, unless the non-performing party would suffer disproportionate loss. A scenario with an intentional breach and a disproportionate loss expects &lt;code&gt;NEITHER&lt;/code&gt; for "fundamental non-performance": the intention does not carry the day, and no other ground was pleaded.&lt;/p&gt;

&lt;p&gt;A test framework that only knows &lt;code&gt;true&lt;/code&gt; and &lt;code&gt;false&lt;/code&gt; cannot express this. The test language for canons has to, or half of the law becomes untestable.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. A test can expect a question
&lt;/h2&gt;

&lt;p&gt;Some elements of a norm are not facts. "Deliberately played the ball", "disproportionate loss", "obvious goal-scoring opportunity": the text hands these to a person with authority to decide. A model that guessed them would be wrong by design. So the model asks, and a test can expect the asking.&lt;/p&gt;

&lt;p&gt;Law 11 of football: a player in an offside position receives the ball from an opponent. Whether the opponent &lt;em&gt;deliberately&lt;/em&gt; played it, or the ball merely rebounded, is the referee's judgement. Without that judgement the question "offside offence?" has no answer yet, and the test says so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test "ifab-07-offside-rebound-requires-judgment" {
    given {
        context { legal_time @2026-09-01; timezone "UTC"; }
        assert "a0": part_in_opponents_half(match, i3, p1) { origin case_input; }
        assert "a2": part_nearer_goal_line_than_second_last_opponent(match, i3, p1) { origin case_input; }
        assert "a4": ball_came_from_opponent(match, i3) { origin case_input; }
        assert "a5": played_or_touched_the_ball(match, i3, p1) { origin case_input; }
    }
    evaluate truth(offside_offence(match, i3, p1));
    expect evaluation_status == REQUIRES_JUDGMENT;
    expect judgment_request(opponent_deliberately_played_the_ball, MatchReferee);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The expectation is precise: the evaluation stops with the status "requires judgement", and the open question is &lt;em&gt;this&lt;/em&gt; predicate, addressed to &lt;em&gt;this&lt;/em&gt; organ, the match referee. Not "the model was unsure". The next scenario in the same folder adds the referee's answer, marked &lt;code&gt;origin adjudicated&lt;/code&gt; rather than &lt;code&gt;origin case_input&lt;/code&gt;, and expects a definite result with zero open questions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5b0e15srm6srbxwr5ppw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5b0e15srm6srbxwr5ppw.png" alt="The judgement channel: without the referee's answer the test expects a named question to the match referee; with it, a definite answer and no open questions." width="799" height="362"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The same channel runs through the commercial canons. In the UNIDROIT scenario on fundamental non-performance by deprivation, the expected status is &lt;code&gt;TRUE_ONLY&lt;/code&gt; for the fundamental character &lt;em&gt;and&lt;/em&gt; &lt;code&gt;REQUIRES_JUDGMENT&lt;/code&gt;, because the question of disproportionate loss under Article 7.3.1(2)(e) has not been put to the tribunal. Two expectations on one answer, and both must hold.&lt;/p&gt;

&lt;p&gt;Civil codes use it too. In the Code civil case below, the harmful act, the damage and the causal link are on file: liability under article 1240 comes back as a question for the judge, because it needs a finding of fault, while prescription on the same facts is established, because it needs only dates.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://lens.arxo.io/a/b_e249e8e4f3addd78ae9cec3793fc84453e2b698b10d885db86a64d0172c59bda?lang=en" rel="noopener noreferrer"&gt;La faute reste au juge&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Every test carries a date
&lt;/h2&gt;

&lt;p&gt;The file at the top of this article expects an indirect free kick. Its neighbour holds the same two facts and expects a corner kick:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// The same incident on 1 September 2026: the 2026/27 book applies.
test "ifab-02-gk-nine-seconds-2026-27" {
    given {
        context { legal_time @2026-09-01; timezone "UTC"; }
        assert "a0": goalkeeper_within_own_penalty_area(match, i1) { origin case_input; }
        assert "a1": goalkeeper_control_seconds(match, i1, 9.0) { origin case_input; }
    }
    evaluate truth(restart_awarded(match, i1, corner_kick));
    expect truth_status == TRUE_ONLY;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing in the package was edited between the two tests. Both rules live in the model, each pinned to the edition of the Laws that contains it, each edition with its window of force:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@source(LOTG_2425_LAW_12)
rule GoalkeeperSixSecondsIndirectFreeKick(m, i, secs) strict {
    when goalkeeper_within_own_penalty_area(m, i)
        and goalkeeper_control_seconds(m, i, secs)
        and (secs &amp;gt; 6.0);
    then indirect_free_kick_offence(m, i);
}

@source(LOTG_2526_LAW_12, LOTG_2627_LAW_12)
rule GoalkeeperEightSecondsCornerKick(m, i, secs) strict {
    when goalkeeper_within_own_penalty_area(m, i)
        and goalkeeper_control_seconds(m, i, secs)
        and (secs &amp;gt; 8.0);
    then restart_awarded(m, i, corner_kick);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ft855vsrfah5gt98br888.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ft855vsrfah5gt98br888.png" alt="Same two facts, two dates of law: each date falls into a different edition window and selects a different rule." width="800" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The date of law in the test selects the edition; the edition selects the rule. Of the 21,948 scenarios in the corpus, 19,358 name a date of law explicitly. A test without a date would be a test of "the law in general", and there is no such thing.&lt;/p&gt;




&lt;h2&gt;
  
  
  Tests are written from the text, not from the model
&lt;/h2&gt;

&lt;p&gt;A unit test that was generated from the implementation tests nothing: it will agree with whatever the code does. The same trap exists for law, and it is easier to fall into, because the model is often the first precise reading of the text anyone has produced.&lt;/p&gt;

&lt;p&gt;So the rule for canons is the rule for good test suites: the expectation comes from the source, and it is frozen. A change in the model has to &lt;em&gt;break&lt;/em&gt; scenarios; it never rewrites them. When a scenario and the model disagree, the text is opened, the reading is settled, and the losing side is fixed.&lt;/p&gt;

&lt;p&gt;An example of what the text can hide. Article 19(4) of the Kazakh compulsory motor insurance law adds a coefficient of 0.8 "for other towns and settlements in the regions listed in paragraph 3". The table in paragraph 3 lists regions, and it also lists Almaty, Astana and Shymkent, which are cities of republican significance, not regions. A scenario written from the text for "Almaty, other settlement" expects the coefficient &lt;em&gt;not&lt;/em&gt; to apply. A scenario written from the table would expect the opposite. Three independent readers of the text agreed with the first expectation, and that is the one the package holds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Continuous integration for a bill
&lt;/h2&gt;

&lt;p&gt;Once a statute has a test suite, the question every engineer asks becomes available to a legislator: what does this change break?&lt;/p&gt;

&lt;p&gt;Arxo answers it with an impact report. Take the current model of an act and the model of the draft amendment, run every scenario and every declared goal against both, and compare:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;which norms changed in meaning, counted on the structure of the rules rather than on their wording, so that a reworded label with the same logic is reported as no change;&lt;/li&gt;
&lt;li&gt;which scenarios changed their outcome, with the answer before and after;&lt;/li&gt;
&lt;li&gt;which goals the act declares still hold, and which one held before the amendment and fails after it;&lt;/li&gt;
&lt;li&gt;which of the amended norms are executed by no scenario at all.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb9on4amtnafqh8l8c63u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb9on4amtnafqh8l8c63u.png" alt="Impact report: the scenario bank and the declared goals run against the current model and the draft; changed outcomes, broken goals and amended norms no scenario executes are listed." width="800" height="425"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That last line is the one a legislator will not get from a reading. The report names it plainly: for those norms, "outcome unchanged" is an absence of observation, not a conclusion. The test suite of a statute has coverage, and the coverage has holes, and the holes are listed.&lt;/p&gt;

&lt;p&gt;The same report runs on the axis of time instead of the axis of drafts: two dates of law, one act, and the scenarios show what the passage of an edition changed for the cases people actually brought.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to look
&lt;/h2&gt;

&lt;p&gt;The UNIDROIT Principles of International Commercial Contracts are published as executable packages at &lt;a href="https://github.com/arxohq/arxo-unidroit-picc" rel="noopener noreferrer"&gt;github.com/arxohq/arxo-unidroit-picc&lt;/a&gt;. Each package carries its &lt;code&gt;tests/&lt;/code&gt; folder; the scenarios on fundamental non-performance quoted above are in the &lt;a href="https://github.com/arxohq/arxo-unidroit-picc/blob/main/packages/unidroit.picc_non_performance/tests/03-termination.lawtest" rel="noopener noreferrer"&gt;termination file of the non-performance package&lt;/a&gt;. Open one, read the facts, and if you believe the Principles answer differently, send the counterexample as an issue in the same repository. That is how a scenario enters the suite.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://blog.arxo.io/the-law-has-unit-tests/" rel="noopener noreferrer"&gt;Arxo Writings&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>testing</category>
      <category>programming</category>
      <category>dsl</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
