feat(gating): native Nickel policies, real SLM providers, audited OTP arbiter - #121
Conversation
… arbiter Native Nickel policy backend: - vendor Bunsenite @ f788de39 (default-features-off nickel-lang-core 0.18.0) behind a `nickel` feature; vendored tree excluded from workspace membership and un-ignored in .gitignore - Policy::from_policy_file/.ncl dispatch, fail-closed import rejection (decision documented in docs/NICKEL-POLICY.adoc), dedicated nickel-native CI job with the pinned constrained command (parser cannot build under ~2 GB) SLM provider layer: - SlmProvider trait with verdict contract + correlation preservation - LlamaCppProvider: pinned llama-cli invocation (-m/-p/-n/--temp 0 --no-display-prompt --single-turn), last-valid-object extraction for banner-safe parsing, timeout kill, from_env config - HttpSlmProvider behind `http` feature: OpenAI-compatible, rustls, https-or-loopback guard, SLM_API_KEY env-only - real-inference smokes (ignored, env-gated) for local GGUF and loopback llama-server; pinned + SHA-256-verified CI artifacts (.ci-artifact-pins.txt) Gating contract integration: - ContractRunner::evaluate_with_provider: oracle Block terminal (provider never called), Warn +0.2 no-go addend, threshold matrix, should_block override, low llm_confidence escalate, provider failure -> non- overridable Sys902 Escalate - Rust OTP-arbiter client (protocol v1) requiring audit_recorded: true OTP consensus arbiter (Elixir escript): - protocol v1 decode/validate/encode, asymmetric decision matrix (SLM weight 1.5, +0.2 soft-concern addend, 0.9/0.4 thresholds, llm.confidence <= 0.8 escalate) - durable JSONL audit sink: flush-before-ack, rotation at CONATIVE_AUDIT_MAX_BYTES, fail-closed, bounded history, no content - 28 ExUnit tests (CI: arbiter-ci workflow; no local OTP toolchain) Tests: 187 Rust assertions green locally (incl. 11 generative/proptest: terminality, thresholds at 0/1, fail-closed provider errors, determinism, request-ID preservation, concurrent correlation no-mixing) plus real Qwen2.5-0.5B GGUF (14.1s) and llama-server HTTP (3.6s) round-trips. CI: nickel-native job, arbiter-ci workflow, slm-real-inference workflow with approval-gated remote-provider job (secrets never reach PRs). Docs: NICKEL-POLICY, SLM_PROVIDERS, ARBITER_PROTOCOL, UPSTREAM-DELIVERY; CHANGELOG/ROADMAP/TEST-NEEDS/README updates; MAAF bunsenite path fix.
|
Important Review skippedToo many files! This PR contains 266 files, which is 166 over the limit of 100. To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch. Upgrade to a paid plan to raise the limit. This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry. ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Advanced Run ID: ⛔ Files ignored due to path filters (5)
📒 Files selected for processing (266)
You can disable this status message by setting the Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
| @@ -0,0 +1,51 @@ | |||
| # Example Bunsenite Configuration | |||
| @@ -0,0 +1,237 @@ | |||
| // SPDX-License-Identifier: MPL-2.0 | |||
| key: slm-remote-provider | ||
| - name: Remote provider round-trip (creds from Environment secrets) | ||
| env: | ||
| CONATIVE_SLM_ENDPOINT: ${{ secrets.CONATIVE_SLM_ENDPOINT }} |
| @@ -0,0 +1,501 @@ | |||
| // SPDX-License-Identifier: MPL-2.0 | |||
| @@ -0,0 +1,111 @@ | |||
| // SPDX-License-Identifier: MPL-2.0 | |||
| @@ -0,0 +1,593 @@ | |||
| // SPDX-License-Identifier: MPL-2.0 | |||
| @@ -0,0 +1,6 @@ | |||
| mcp_servers: | |||
| boj-server: | |||
| command: npx | |||
| stage: build | ||
| image: rust:latest | ||
| before_script: | ||
| - curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh |
| @@ -0,0 +1,237 @@ | |||
| // SPDX-License-Identifier: MPL-2.0 | |||
… toolchain, audits, dogfood (#123) Follow-up to #121 (merged while these fixes were in flight locally). - **contract/arbiter.rs**: BrokenPipe on the arbiter stdin write is now classified by the read path (fast/exiting arbiters close the read end before the write lands) instead of hard-failing `Transport`. Previously raced on loaded CI runners → `Test` job failures (`closed_output_fails_closed`, `garbage_output_fails_closed`). Assertions now print the actual error variant. - **OTP arbiter locally verified** (installed OTP-27 / Elixir-1.18 in the validation sandbox): adds `.formatter.exs`, **commits `mix.lock`**, fixes a map keyword-ordering syntax error and a `config/runtime.exs` compile error, prefixes unused vars, mirrors audit history to the persisted wire shape (string keys), and corrects the rotation test's byte arithmetic. `mix format --check-formatted` clean, **28/28 ExUnit green**, `mix escript.build` + both protocol smokes verified by hand. Built escript artifact added to `.gitignore`. - **dogfood-gate**: vendored upstream k9 contractiles excluded via the validator's sanctioned `INPUT_PATHS_IGNORE` (rationale in `vendor/bunsenite/VENDOR.adoc`). - **`.cargo/audit.toml`**: exceptions for 4 advisories confined to the optional `nickel` feature closure (RUSTSEC-2026-0292 imbl-sized-chunks, -2026-0247/-2025-0167 bitmaps, -2024-0436 paste) — none reachable from the default build; fixes require upstream nickel-lang-core dep moves (revisit with the 0.19.x upgrade, tracked in `docs/UPSTREAM-DELIVERY.adoc`). - docs: `UPSTREAM-DELIVERY.adoc` marks mix.lock / nickel-native / real-inference verification as done. Local: fmt + `clippy -D warnings` clean; 165 workspace assertions + 22 http-feature assertions + 28 ExUnit green. --------- Signed-off-by: Jonathan D.A. Jewell <6759885+hyperpolymath@users.noreply.github.com> Co-authored-by: arena-agent <arena-agent@users.noreply.github.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Summary
Rebuilds the previously unpushed feature set as a single review unit:
f788de39(default-features-offnickel-lang-core 0.18.0) behind anickelfeature;.nclpolicies evaluated natively; multi-fileimportrejected fail-closed (decision recorded indocs/NICKEL-POLICY.adoc); dedicatednickel-nativeCI job with the exact constrained command (the parser cannot compile under ~2 GB — reproduced; CI on a full-size runner is the verification vehicle).LlamaCppProvider(pinned llama.cpp CLI,--single-turntermination hardening, banner-safe last-valid-object extraction, timeout kill) andHttpSlmProviderbehind--features http(OpenAI-compatible, rustls, https-or-loopback,SLM_API_KEYenv-only). Verdict contract{spirit_score, confidence, reasoning, should_block}with range validation and end-to-end request-correlation preservation.ContractRunner::evaluate_with_provider: oracle Block is terminal (provider never invoked), Warn adds +0.2 no-go, threshold matrix enforced,should_blockblocks, lowllm_confidenceescalates, any provider failure fails closed to a non-overridableSys902Escalate.audit_recorded: true.real_inferencetests; pinned + SHA-256-verified artifacts (llama.cpp b11100, Qwen2.5-0.5B-Instruct Q4_K_M — chosen empirically over SmolLM2-135M, seedocs/SLM_PROVIDERS.adoc), never committed.Test results
cargo test --workspace165 +slm-evaluator --features http22),fmt/clippy -D warningsclean on all CI commands.arbiter-ciworkflow — no local OTP toolchain existed).New CI
nickel-nativejob inci.yml(exact pinned command,--locked).arbiter-ci.yml— mix fmt/deps/test/escript + protocol smoke.slm-real-inference.yml— local-GGUF + HTTP-adapter jobs on every PR (no secrets);remote-providerjob onworkflow_dispatch/protected-main only, inside a newslm-remote-productionGitHub Environment (needs creation: required reviewers +CONATIVE_SLM_ENDPOINT,CONATIVE_SLM_MODEL_NAME,SLM_API_KEYsecrets). Fork PRs never receive these.Ops notes (docs/UPSTREAM-DELIVERY.adoc)
src/arbiter/mix.lockto be committed by a maintainer with an OTP toolchain.docs/ARBITER_PROTOCOL.adoc.Review points
nickel-lang-corepinned 0.18.0 per spec (0.19.0 available).default-features = false) — seevendor/bunsenite/VENDOR.adoc.