diff --git a/README.md b/README.md index e6ab4db2..c798a3ba 100644 --- a/README.md +++ b/README.md @@ -314,7 +314,7 @@ milestone. | **Every Ubuntu LTS validated** — 22.04, 24.04 and 26.04 all at 79/79, each with a replay twin that reproduces it | ✅ | | Telegram approval interface | 📋 roadmap | -**1,845 Rust tests and 72 frontend tests** form the current deterministic +**1,846 Rust tests and 72 frontend tests** form the current deterministic release baseline. ## Configure your LLM diff --git a/crates/sysknife-brain/src/planner.rs b/crates/sysknife-brain/src/planner.rs index 65a96e9d..e7d90f7a 100644 --- a/crates/sysknife-brain/src/planner.rs +++ b/crates/sysknife-brain/src/planner.rs @@ -754,6 +754,10 @@ impl LlmPlanner { /// HTTP client cannot be initialised (rare; only fails if the TLS /// subsystem is unavailable). /// + /// Safety-fence rejection logging is enabled by default and writes to + /// [`SafetyAuditLog::default_path`]. Use [`Self::new`] for a planner + /// without runtime defaults. + /// /// Rate limiting is **enabled by default** at [`DEFAULT_MAX_RPM`] requests /// per minute. Override with the `SYSKNIFE_MAX_RPM` environment variable. /// Call `with_rate_limiter` after this to replace the default limiter, or @@ -859,9 +863,13 @@ impl LlmPlanner { None => provider, }; - let mut planner = Self::new(provider, state_client, config.max_turns); + let mut planner = Self::new(provider, state_client, config.max_turns) + .with_audit_log(SafetyAuditLog::new(SafetyAuditLog::default_path())); + // `from_config` is the production construction path used by the CLI, + // MCP server, and shell. Attach the default safety log here so every + // runtime planner records fence rejections; direct `new` remains + // opt-in for callers such as tests and embedded consumers. planner.prefs_path = Some(sysknife_core::config::prefs_path()); - if replaying { // No rate limiter under replay. It exists to bound spend and load on a // provider, and a replay reaches neither: every answer comes off disk. @@ -1516,6 +1524,18 @@ mod tests { .expect("ollama defaults need no credentials") } + /// The integration test exercises the rejection path and reads the JSONL; + /// this test pins that the production constructor actually attaches the + /// log without mutating process-global path configuration. + #[test] + fn configured_planner_attaches_audit_log() { + let planner = ollama_planner(); + assert!( + planner.audit_log.is_some(), + "from_config must attach the safety audit log" + ); + } + #[test] fn into_authorized_replaces_every_step_risk() { let step = |name: &str, risk| { diff --git a/docs/distro-support.md b/docs/distro-support.md index 415d35bf..223e4f21 100644 --- a/docs/distro-support.md +++ b/docs/distro-support.md @@ -82,7 +82,7 @@ family and the atomic story family are implemented and covered by the workspace suite. What is missing is a way to put the helpers somewhere the daemon's own grants already point. -The deterministic workspace baseline is 1,845 Rust tests plus 72 frontend +The deterministic workspace baseline is 1,846 Rust tests plus 72 frontend tests. Those tests verify action construction, policy, approval, storage, and UI behavior, but they do not replace a real distribution VM run. diff --git a/docs/introduction.md b/docs/introduction.md index f26a54d7..337f584a 100644 --- a/docs/introduction.md +++ b/docs/introduction.md @@ -141,7 +141,7 @@ flow. ## Status -190 typed actions · 1,845 Rust tests + 72 frontend tests · MIT +190 typed actions · 1,846 Rust tests + 72 frontend tests · MIT SysKnife is the reference implementation of the [LACS specification](https://github.com/lacs-project/specification) — a diff --git a/tests/evidence/workspace-tests.json b/tests/evidence/workspace-tests.json index 5f66b8d5..cc092b4f 100644 --- a/tests/evidence/workspace-tests.json +++ b/tests/evidence/workspace-tests.json @@ -4,6 +4,6 @@ "tests": "cargo nextest run --workspace --locked" }, "frontend_tests": 72, - "tests": 1845, + "tests": 1846, "version": 2 }