Skip to content
docs
Arxo ↗

Shared computation as a dependency

For LLMs6 sections

The archive’s overdue fee counts by tiers: the first two thousand tenge of the base in full, everything above at half. The archive did not invent the progressive scale: income tax, duties, and tariffs count the same way. Whoever rewrites it in each act repeats the same computation with different mistakes. Hence the tree holds shared applied computations in the shared-computation tree: five packages of the calc.* family — tiers, quotas, obligations, accruals, allocation — with no jurisdiction, no source, and no [metadata]. The scale is applied by calc.tiers; its real consumer in the corpus is the Tax Code of Kazakhstan, three scales of article 363.

The boundary between the computer and the act runs along law, and it is this page’s point: the computer receives conditions explicitly and returns the calculation; norms, rates, tier bounds, calendar, and rounding stay with the subject package. calc.tiers knows not one number of the conditions.

Arxo Law
language "law.core" version "0.2";
package tutorial.archive version "0.15.0";
namespace "urn:law:tutorial:archive";
import tutorial.city version "0.1.0";
import calc.tiers version "0.1.0";
entity Person;
relation billing_year(p: Person, year: Integer) kind empirical { key(p); }
relation days_overdue(p: Person, days: Integer) kind empirical { key(p); }
relation late_fee_base(p: Person, base: Money) kind institutional { key(p); }
relation late_fee(p: Person, amount: Money) kind institutional { key(p); }
const LATE_FEE_CAP: Money = 5000 KZT;

The base from a foreign act, the scale from the computer

Section titled “The base from a foreign act, the scale from the computer”

The archive computes the fee base itself: overdue days multiply the city’s daily charge, read from the foreign act as on the last page:

Arxo Law
rule LateFeeBase strict {
label ru-KZ unofficial "База платы за просрочку: дни просрочки по дневной плате города на год счёта";
for p: Person;
for d: Integer;
for y: Integer;
for unit: Money;
when days_overdue(p, d) and billing_year(p, y) and tutorial.city::late_fee_unit(y, unit);
then late_fee_base(p, d * unit);
}

The label reads: “Overdue-fee base: overdue days at the city daily charge for the billing year”.

calc.tiers opens its API with relations: for input it takes the scale, its mode and rounding, tiers with bounds and rates, and a “apply the scale to the base” request; for output it gives the total, the base split across tiers, and each tier’s contribution. The archive declares the scale and tiers as constants — individuals of the computer’s types:

Arxo Law
const LateFeeScale: calc.tiers::Scale = entity_ref("urn:law:tutorial:archive#LateFeeScale") {
label ru-KZ unofficial "шкала платы за просрочку";
};
const LateFeeFullTier: calc.tiers::Tier = entity_ref("urn:law:tutorial:archive#LateFeeFullTier") {
label ru-KZ unofficial "ступень полного размера: база до 2 000 тенге";
};
const LateFeeHalfTier: calc.tiers::Tier = entity_ref("urn:law:tutorial:archive#LateFeeHalfTier") {
label ru-KZ unofficial "ступень половинного размера: база свыше 2 000 тенге";
};
const LATE_FEE_FULL_UPTO: Money = 2000 KZT;

The labels read: “overdue-fee scale”; “full-size tier: base up to 2,000 tenge”; “half-size tier: base above 2,000 tenge”.

The archive writes each condition as an ordinary rule with a head in a foreign pub relation. That is what the computer/act boundary looks like in code: rules set the Graduated mode (each tier’s rate applies to its own part of the base), the scale floor, the stage and policy of rounding, two tiers with bounds and rates.

Arxo Law
rule LateFeeScaleMode strict {
for p: Person;
for base: Money;
when late_fee_base(p, base);
then calc.tiers::scale_mode(LateFeeScale, calc.tiers::Graduated);
}
rule LateFeeScaleFloor strict {
for p: Person;
for base: Money;
when late_fee_base(p, base);
then calc.tiers::scale_floor(LateFeeScale, 0 KZT);
}
rule LateFeeScaleRoundingStage strict {
for p: Person;
for base: Money;
when late_fee_base(p, base);
then calc.tiers::scale_rounding_stage(LateFeeScale, calc.tiers::TotalOnly);
}
rule LateFeeScaleRoundingPolicy strict {
for p: Person;
for base: Money;
when late_fee_base(p, base);
then calc.tiers::scale_rounding_policy(LateFeeScale, 0, "HALF_UP");
}
rule LateFeeFullTierOf strict {
for p: Person;
for base: Money;
when late_fee_base(p, base);
then calc.tiers::tier_of(LateFeeFullTier, LateFeeScale);
}
rule LateFeeFullTierFrom strict {
for p: Person;
for base: Money;
when late_fee_base(p, base);
then calc.tiers::tier_from(LateFeeFullTier, 0 KZT);
}
rule LateFeeFullTierBoundKind strict {
for p: Person;
for base: Money;
when late_fee_base(p, base);
then calc.tiers::tier_bound_kind(LateFeeFullTier, calc.tiers::Bounded);
}
rule LateFeeFullTierUpto strict {
for p: Person;
for base: Money;
when late_fee_base(p, base);
then calc.tiers::tier_upto(LateFeeFullTier, LATE_FEE_FULL_UPTO);
}
rule LateFeeFullTierRate strict {
for p: Person;
for base: Money;
when late_fee_base(p, base);
then calc.tiers::tier_rate(LateFeeFullTier, 1 / 1);
}
rule LateFeeHalfTierOf strict {
for p: Person;
for base: Money;
when late_fee_base(p, base);
then calc.tiers::tier_of(LateFeeHalfTier, LateFeeScale);
}
rule LateFeeHalfTierFrom strict {
for p: Person;
for base: Money;
when late_fee_base(p, base);
then calc.tiers::tier_from(LateFeeHalfTier, LATE_FEE_FULL_UPTO);
}
rule LateFeeHalfTierBoundKind strict {
for p: Person;
for base: Money;
when late_fee_base(p, base);
then calc.tiers::tier_bound_kind(LateFeeHalfTier, calc.tiers::OpenTop);
}
rule LateFeeHalfTierRate strict {
for p: Person;
for base: Money;
when late_fee_base(p, base);
then calc.tiers::tier_rate(LateFeeHalfTier, 1 / 2);
}

Thirteen rules for one scale is many, and deliberately so: each condition is named, bound to a premise, and visible in the proof graph as the archive’s rule rather than hiding in call parameters. Rates are written as exact Rational fractions; a tier’s lower bound is included, the upper not; the last tier is open at the top.

Arxo Law
rule LateFeeScaleApplied strict {
label ru-KZ unofficial "Шкала применяется к базе платы за просрочку";
for p: Person;
for base: Money;
when late_fee_base(p, base);
then calc.tiers::scale_applied_to(LateFeeScale, base);
}
rule LateFee strict {
label ru-KZ unofficial "Плата за просрочку: итог шкалы, но не более потолка";
for p: Person;
for base: Money;
for total: Money;
when late_fee_base(p, base) and calc.tiers::scale_total(LateFeeScale, base, total);
then late_fee(p, min(total, LATE_FEE_CAP));
}

The labels read: “The scale applies to the overdue-fee base” and “Overdue fee: the scale total, capped”.

Overdue daysBaseScale totallate_fee
3600600600 KZT
153,0002,000 + 5002500 KZT
6012,0002,000 + 5,0005000 KZT — the cap

The test from this page, byte for byte; the world is the page plus the pinned bytes of tutorial.city and calc.tiers:

Arxo Law
test "три дня просрочки — 600, вся база в первой ступени" {
given {
context {
decision_time @2026-04-20T09:00:00+05:00;
knowledge_time @2026-04-20T09:00:00+05:00;
legal_time @2026-04-20;
timezone "Asia/Almaty";
}
assert billing_year(entity_ref("urn:tutorial:ivanova"), 2026) {
id "assert-year";
origin case_input;
}
assert days_overdue(entity_ref("urn:tutorial:ivanova"), 3) {
id "assert-days";
origin case_input;
}
}
evaluate truth(late_fee(entity_ref("urn:tutorial:ivanova"), 600 KZT));
expect truth_status == TRUE_ONLY;
expect evaluation_status == COMPUTED;
}

The test name reads: “Three days overdue — 600, the whole base in the first tier.”

The test asks only the archive’s own heads: the .lawtest runner does not allow qualified references in a query, so the scale total is read through late_fee, not through calc.tiers::scale_total. In the practicum package the cap does not arrive as a constant: an A3 parameter sets it by date of law, told on the next page.

calc.tiers does not know whether the scale applies to the case, which edition is in force, or whether the total is collectible. It silently chooses neither rounding, nor floor, nor rates: fail to name the rounding policy at TotalOnly and the scale proves unfit, scale_wellformed is not derived, and the defect gets a name in scale_defect. All five catalogue packages are arranged so: before extracting a new computation, find its place by the computation catalogue — package, expansion, template, core, or data — and read the family passport (calc.tiers is P05).

The shared-computation tree is held separately: corpus scanners do not see it. When the computer gains a consumer in the corpus, it is registered by hand — with a regression family and ratchets — and the Tax Code walked this path first.

A head the computer lacks. Replace scale_total in LateFee’s body with scale_sum:

Output
error LDC-E1105: calc.tiers::scale_sum: символ не экспортирован пакетом
(§24: межпакетные ссылки — только на `pub`-декларации; экспортировано: …)

The diagnostic reads: ‘symbol not exported by the package (cross-package references only to pub declarations; exported: …)’.

A missing enum member — calc.tiers::Progressive instead of Graduated — is the same refusal: the computer’s export is closed by a list, and a typo in someone else’s name does not pass silently. Both refusals belong to the language under the practicum context.

The fee cap changes by year: those are data, not a norm, and they belong in an A3 sidecar next to the package — parameters and tables.

Documentation for Arxo. Writings — blog.arxo.io.

Anonymous visit counts on stats.arxo.io, no cookies.