moon_policyforge

    Typed rule evaluation, decision tables and explainable decisions

    policyforge
    cli
    moonbit
    Download zip
    Version
    0.10.0
    License
    Apache-2.0
    Last updated
    16 days ago
    Downloads
    40

    No dependencies

    #Moon PolicyForge

    CI

    Explainable rule decisions, implemented in MoonBit with a JSON CLI and reusable library API. Thirty-seven operations, four backends, 206 white-box tests, 101 CLI fixtures, two differential fuzz oracles and a 100k-fact scale check — all wired into one verification ladder (node scripts/verify.mjs).

    • Repository: https://github.com/123123213weqw/moon-policyforge
    • Package: 123123213weqw/moon_policyforge on mooncakes.io (registry versions are listed in CHANGELOG.md)
    • License: Apache-2.0
    • Release scope: 1.0.0 complete implementation of the scope defined in docs/proposal.md: the three scenarios run end to end, the acceptance checks (independent reference evaluation, 100k-fact statistical agreement, per-decision explanation chains, failure validation) are executable, and the remaining limits are listed in docs/boundaries.md.

    #Implemented

    An expression lexer and precedence parser; numeric/string/boolean literals; dotted fact paths; arithmetic and comparisons; strict boolean short circuit; exists/len/contains/lower/abs; finite arithmetic; evaluation budgets (shared by decide and evaluate); rule priority; first/all/unique decisions; conflict flags with conflicting rule IDs; per-record errors; condition traces; rule-set diff with conflict attribution; an opt-in schema-based static checker; array quantifiers (count_matches, any_match, all_match); fact projection (pick); expression AST as JSON interchange; policy bundle manifests with migration resolution and application; one-call governance lint; canonical rule-set formatting; JSON Schema draft 2020-12 export; fact validation with required paths; semantic condition conflict detection (disjointness and subsumption over range fragments); engine self-description via stats; an optimizer with semantics-preserving rewrites; precompiled rule programs; coverage analysis; dependency graphs; an explain text renderer; a coded error taxonomy (E1xxx-E4xxx); JSONL streaming; canonical expression serialization with structural metrics and round-trip verification; group-wise aggregation; schema inference; static rule-set analysis (dependencies, tautologies, shadowing, ties); single-record text decision reports; a coded error taxonomy (E1xxx-E4xxx); JSONL streaming through the CLI; three complete scenario fixtures; a 100k-fact scale validation, a 500-expression differential fuzz oracle and recorded throughput benchmarks.

    #Build and run

    Use MoonBit and Node.js 24. The core library supports JS, wasm, wasm-gc and native; the filesystem/HTTP/process CLI is JS only.

    moon update moon build --target js moon run cmd/main --target js -- examples/discount-scenario.json node _build/js/debug/build/cmd/main/main.js examples/admission-scenario.json

    Pass - to read a UTF-8 JSON request from stdin. A single request must be at most 16 MiB. The CLI prints one JSON result and exits 0 for a clean report, 2 for a completed report with findings (a top-level ok: false such as lint or compare drift, or a non-empty findings array), and 1 after printing {"error": "..."} for a rejected request; .jsonl streaming applies the same rule per line. The host runner is a separate process and does not edit the input request file.

    #Library use

    mooncakes.io currently accepts only zero-major versions (moon publish rejects anything else with "In this very early stage, the major version must be '0'"), so repository releases and registry versions are numbered separately. The registry version corresponding to each repository release is recorded in CHANGELOG.md; 0.1.0 on the registry is the initial implementation.

    moon add 123123213weqw/moon_policyforge@0.10.0

    In the consumer's moon.pkg:

    import {
    "123123213weqw/moon_policyforge" @engine,
    "moonbitlang/core/json",
    }

    fn example(request : Json) -> Json raise {
    @engine.execute(request)
    }

    execute(Json) -> Json raise is the standard JSON boundary. from_json, Value::to_json, and run(Value) -> Value raise provide a typed semantic value interface; Value::flatten (leaf values keyed by JSON Pointer), Value::pointer (lookup by JSON Pointer) and Value::canonical (canonical JSON text) help consumers work with reports, and digest(String) -> String is the SHA-256 used for digests. Object ordering is not significant; numeric values use finite Double. Public domain functions are listed in pkg.generated.mbti.

    #Static checking

    The check operation validates an expression or a rule set without evaluating it against facts:

    echo '{"operation":"check","expression":"amount > \"x\"","schema":{"amount":"number"}}' | \ node _build/js/debug/build/cmd/main/main.js -

    The optional schema maps dotted fact paths to one of boolean, number, string, null, array, object. The checker mirrors runtime semantics exactly and only reports what the evaluator would reject; fact paths absent from the schema are unknown and defer to runtime, so a schema-less check still catches structural errors. Rule checks cover duplicate IDs, missing conditions, non-boolean conditions, non-finite priorities, uncompilable compute expressions, and rules with neither output nor compute.

    #Tests

    moon test --target js moon test --target wasm moon test --target wasm-gc moon test --target native # requires a C compiler moon build --target js node scripts/check.mjs node scripts/verify.mjs # everything below in one fail-fast ladder python -B scripts/reference.py python -B scripts/scale_check.py python -B scripts/error_codes.py python -B scripts/fuzz_diff.py python -B scripts/fuzz_rules.py python -B scripts/check_docs.py node scripts/jsonl_check.mjs node scripts/smoke.mjs node scripts/bench.mjs

    There are 107 checked fixture cases in tests/cases.json, executed both in MoonBit white-box tests and through the actual Node CLI. Independent reference checks use Python's standard library or separately written algorithms; scripts/scale_check.py re-decides 100,000 deterministic facts with a plain-Python oracle and asserts per-index agreement, hit-rule attribution through the explanation chain, and a deterministic hit distribution. Fixtures are synthetic and are not presented as production adoption evidence. New to the project? Start with the tutorial. The module map lives in docs/structure.md. Releases are summarized in the changelog; validation scripts are catalogued in docs/scripts.md. Then see the operation reference, the error taxonomy, benchmarks, input and output examples and current boundaries.

    #Current boundaries

    A custom bounded expression language. No arbitrary code execution, loops, user functions or external I/O. Runtime types are always checked at evaluation. A full static type inference is not included; the opt-in check operation reports what an optional caller-supplied schema proves, and unknown fact paths defer to runtime. Every input error carries a stable E-code prefix (see docs/errors.md). All matching rule outputs are evaluated even in first mode, and first selects the highest-priority match; equal priority uses rule ID order. Unique produces conflict and null decision on multiple matches, with the conflicting IDs in conflict_ids. Facts are caller supplied. Traces can include fact values, so redact sensitive facts before storing reports.

    See source and dependency attribution. This release does not establish competition eligibility or organizer acceptance.

    #2026-10-18 follow-up

    保留公开最新版已有的决策表、冲突分析、静态检查、快照及验证能力,新增 replay_versions:同一组有唯一 ID 的事实分别执行旧、新规则,逐条报告决定、冲突、错误和命中集合的变化。区分样本等价与全局证明,报告漂移可供 CLI 门控。拒绝空规则 ID、diff 中重复身份、非整数执行预算及决策表列名注入;纠正编译决策表即证明互斥的说明。

    新回放入口接收 decide 定义,不递归执行任意操作。样本回放不证明全输入空间等价;决策表编译本身不证明行互斥,同类项目也具备求值、解释或测试能力,不能把通用能力作为独有性证明。

    Repository release: 1.1.0; installable MoonCakes module: 123123213weqw/moon_policyforge@0.10.0. Earlier repository 1.0.0 labels are retained as history; the module uses the registry-compatible zero-major sequence.

    Current source contains 316 MoonBit test declarations and 107 CLI fixtures (generated fixture tests are included in the declaration count). Run python -B scripts/followup_reference.py for independent follow-up oracles and examples/followup-20261018.json for the new scenario.

    InputError

    pub(all) suberror InputError {
    InputError(String)
    } derive(Eq)

    impl Show for InputError

    InputError::equal

    fn InputError::equal(InputError, InputError) -> Bool

    InputError::to_string

    fn InputError::to_string(self : InputError) -> String

    Expression

    pub(all) enum Expression {
    Literal(Value)
    Variable(String)
    Unary(String, Expression)
    Binary(String, Expression, Expression)
    Call(String, Array[Expression])
    }

    Value

    pub(all) enum Value {
    Null
    Bool(Bool)
    Number(Double)
    String(String)
    Array(Array[Value])
    Object(Map[String, Value])
    } derive(Eq,
    Debug
    )

    Value::canonical

    fn Value::canonical(self : Value) -> String

    Canonical JSON text: object keys in UTF-16 code unit order, no whitespace, arrays in order.

    Value::equal

    fn Value::equal(Value, Value) -> Bool

    Value::flatten

    fn Value::flatten(self : Value) -> Map[String, Value]

    Maps every leaf (a scalar or an empty container) to its JSON Pointer path. The root path is "" and keys are escaped as in RFC 6901.

    Value::not_equal

    fn Value::not_equal(x : Value, y : Value) -> Bool

    Value::pointer

    fn Value::pointer(self : Value, path : String) -> Value raise

    Returns the value at a JSON Pointer path, raising an input error when the path is malformed or absent.

    Value::stringify

    fn Value::stringify(self : Value) -> String

    Value::to_json

    fn Value::to_json(self : Value) -> Json

    Value::to_repr

    compile

    fn compile(source : String) -> Expression raise

    digest

    fn digest(text : String) -> String

    Hex SHA-256 of the UTF-8 encoding of a string; the digest used for rule-set digests and decision fingerprints.

    evaluate_expression

    fn evaluate_expression(source : String, facts : Value, budget? : Int) -> Value raise

    execute

    fn execute(request : Json) -> Json raise

    from_json

    fn from_json(value : Json) -> Value

    run

    fn run(request : Value) -> Value raise

    Powered by MoonBit

    Site sourceReport issueModulesSkillsBuild queueStatistics

    © 2026 mooncakes.io