Skip to content

aktagon/RulesAsCode-Finland

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

RulesAsCode-Finland

Finnish social security law is public. The systems that execute it should be too.

This project encodes section 6 of the Unemployment Security Act (Työttömyysturvalaki 1290/2002 §6) as executable logic using s(CASP). The rules determine whether a person is classified as an entrepreneur (yrittäjä) — a classification that affects unemployment benefit eligibility.

The system produces Finnish-language justification trees that explain why a decision was made. Not just the answer. The reasoning.

matti on yrittäjä, because
   matti on yrityksen osaomistaja, because
      ex_oy on osakeyhtiö, and
      matti työskentelee johtavassa asemassa yrityksessä ex_oy, because
         ex_oy on osakeyhtiö, and
         matti on ex_oy:n toimitusjohtaja
      matti:n tosiasiallinen omistusosuus yrityksessä ex_oy on 20%, because
         matti omistaa 20% ex_oy:n osakepääomasta tai äänimäärästä
      20% on vähintään 15%

Every rule traces to a specific paragraph of the statute.

Why s(CASP)

s(CASP) reasons under the open-world assumption. Unstated facts are unknown, not false. This is how law works — a person not in the database is not "not an entrepreneur." Their status is unknown.

Closed-world systems (SQL, Python, conventional rule engines) get this wrong. They treat missing data as negation. s(CASP) treats it as absence of evidence, which is a fundamentally different thing.

The justification tree is not a side effect. It is the product.

Quick Start

docker build -t rules-as-code .

Run the example query (Matti, CEO of a limited company, 20% ownership):

docker run --rm --entrypoint scasp rules-as-code \
    --tree --human src/entrepreneur.pl facts/example.pl

Run all 18 tests:

make test

What Is Encoded

All of section 6:

  • §6(1) — YEL and MYEL pension coverage as entrepreneur grounds
  • §6(2) items 1-4 — Part-owner conditions with ownership thresholds (15%, 30%, 50%) for limited companies and other entities
  • §6(3) — Direct and indirect ownership through intermediate entities, including equivalent control
  • §6(4) — Leadership position definition (CEO, board member, equivalent) scoped to company type. Family member definition (spouse, lineal relatives in same household)

Symmetric relations (spouse, same household, lineal relative) are enforced — facts can be asserted in either direction. Family share aggregation across multiple members is handled via pre-computation at the data boundary.

Test Scenarios

ID Scenario Expected
T01 YEL-covered person entrepreneur
T02 MYEL-covered person entrepreneur
T03 CEO of ltd, 20% ownership entrepreneur (item 1)
T04 CEO of ltd, 10% + spouse 25% = 35% entrepreneur (item 2)
T05 Worker in ltd, 50% ownership entrepreneur (item 3)
T06 Worker in ltd, 20% + spouse 35% = 55% entrepreneur (item 3)
T07 Equivalent leadership in non-ltd, 15% entrepreneur (item 4)
T08 Equivalent leadership in non-ltd, family 30% entrepreneur (item 4)
T09 Indirect ownership via holding company entrepreneur (item 1)
T09b Equivalent control over holding company entrepreneur
T10 Worker in ltd, 14% (below 15% threshold) not entrepreneur
T11 Board member of ltd, family combined 29% (below 30%) not entrepreneur
T12 Worker in ltd, no ownership, no YEL/MYEL not entrepreneur
T13 Person holds 20% but does not work in company not entrepreneur
T14 Sibling holds 20% (not a family member under §6) not entrepreneur
T15 Lineal relative not in same household not entrepreneur
T16 CEO, spouse 12% + parent 10% = multi-member aggregation entrepreneur (item 2)
T04b Same as T04, spouse fact asserted in reverse direction entrepreneur (symmetry)

Project Structure

src/entrepreneur.pl     §6 rules + Finnish #pred directives
test/t01-t16.pl         Per-scenario test files
facts/example.pl        Example fact base with query
Dockerfile              SWI-Prolog stable + s(CASP)
Makefile                build, run, query, test

Ambiguity Findings

Encoding law as formal logic exposes where the statute resists computation. Section 6 has 14 such points across 5 types:

Type Count Example
Undefined term 6 "Equivalent control" — no computable definition in §6
Aggregation gap 2 Family shares must be summed; s(CASP) cannot aggregate natively
Implicit bound 2 Indirect ownership depth not specified by statute
Symmetry assumption 3 Resolved — spouse/household/relative now enforce symmetry
Scope leak 1 Resolved — CEO/board scoped to limited companies

Four were resolved in code. The rest are inherent to the statute.

Beyond §6

The method is not specific to this statute or to Finnish law. Open-world logic, every clause traced to source, and justification in the regulated party's language apply to any rule-dense domain: clinical guidelines, tax codes, MDR/IVDR requirements, internal compliance policies.

References

License

EUPL-1.2

Built by Aktagon Ltd.

About

Finnish law encoded as executable logic with s(CASP) — Unemployment Security Act §6 entrepreneur definition with open-world reasoning and Finnish-language justification trees

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors