feat: initial text-deontic-extract v0.1.0 (text.deontic_extract@0.1.0)

Regex-based extraction of atomic deontic statements (Pflicht,
Verbot, Erlaubnis) from German legal text. Reuse-lens: contracts,
ISO standards, internal policies. Vorbild: Mercatus QuantGov /
RegData.

Pattern coverage in v0.1.0:

  - OBLIGATION:  muss, hat zu, ist verpflichtet, ist anzuzeigen,
                 aufzuzeichnen, muss eingehalten/geführt/...
  - PROHIBITION: darf nicht, dürfen nicht, ist untersagt, verboten
  - PERMISSION:  kann, können, darf

Each emitted Duty carries a confidence ∈ [0, 1]. Pattern hits
default to 0.85; ambiguous structures (bare "kann") drop to 0.70.
Anything below 0.6 is the surrounding flow's signal to re-run
through llm.chat for human-readable refinement and feed the result
to system.approval@^0 — that keeps deterministic extraction
separate from non-deterministic LLM judgment.

Pure in-WASM (regex), zero filesystem, zero network.

Reserved for next versions:

  - 0.2: EN / FR locale variants
  - 0.3: addressee + frequency + authority detection (Phase 1
         relies on flow-side LLM enrichment for those fields)

Signed-off-by: flemming-it <sf@flemming.it>
This commit is contained in:
flemming-it 2026-06-18 11:24:58 +02:00
commit 7dcdf7679f
6 changed files with 769 additions and 0 deletions

40
Cargo.toml Normal file
View file

@ -0,0 +1,40 @@
[package]
name = "text_deontic_extract"
version = "0.1.0"
edition = "2024"
authors = ["Dr. Stefan Flemming <chain@flemming.ai>"]
license = "Apache-2.0"
publish = false
description = "F∆I module — extract atomic deontic statements (Pflicht/Verbot/Erlaubnis) from normalised legal text"
repository = "https://git.flemming.ws/chain-modules/text-deontic-extract"
rust-version = "1.85"
[lib]
crate-type = ["cdylib", "rlib"]
[dependencies]
chain-module-sdk = { git = "https://git.flemming.ai/fai/chain-module-sdk-rust.git", branch = "main" }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
regex = "1"
[dev-dependencies]
serde_json = "1"
[profile.release]
opt-level = "s"
lto = true
codegen-units = 1
strip = "symbols"
[lints.rust]
unsafe_op_in_unsafe_fn = "warn"
[lints.clippy]
unwrap_used = "deny"
expect_used = "deny"
panic = "deny"
print_stdout = "deny"
print_stderr = "deny"
[workspace]