This repository has been archived on 2026-08-20. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
el-retired/dharma/tests/internal_state/test_immutability_gate.el
T
Will Anderson 90ddbdbfc3 feat: port arbor, dharma, forge El source into monorepo
Brings the remaining foundation repos that were not included in the
original monorepo consolidation:

- arbor/vessels/ — 6 vessels (arbor-cli, arbor-core, arbor-diagram,
  arbor-layout, arbor-parse, arbor-render) with manifests + src/main.el
- dharma/ — CGI Provenance Registry package (flat layout, 14 .el files
  across registry/, sandbox/, training/, validation/, tests/)
- forge/ — consciousness channel tool (8 src .el files + new manifest.el)
- elp/src/ — 36 test fixture files not carried over in original merge
  (dedup_*, realizer_*, semantics_*, morph_*, ext_*, one_extern_* helpers)

el-ide, engram, elql are already complete in ide/, engram/, ql/.
2026-05-05 04:27:34 -05:00

76 lines
3.0 KiB
EmacsLisp

// test_immutability_gate.el verifies that PATCH bodies referencing
// any of the immutable fields are rejected by body_contains_key + the
// gate logic (the per-field check ladder in patch_internal_state_handler).
// This mirrors the production check ladder in registry/handlers.el.
fn body_contains_key(body: String, key: String) -> Bool {
return str_contains(body, "\"" + key + "\":")
}
// patch_validate returns "" if the body is acceptable for PATCH,
// otherwise the field name that violates immutability. This is the same
// ladder as patch_internal_state_handler in handlers.el.
fn patch_validate(body: String) -> String {
if body_contains_key(body, "pre_reasoning") { return "pre_reasoning" }
if body_contains_key(body, "pre_logged_at") { return "pre_logged_at" }
if body_contains_key(body, "cgi_id") { return "cgi_id" }
if body_contains_key(body, "event_id") { return "event_id" }
if body_contains_key(body, "trigger") { return "trigger" }
if body_contains_key(body, "domain") { return "domain" }
if body_contains_key(body, "logged_at") { return "logged_at" }
if body_contains_key(body, "id") { return "id" }
return ""
}
fn assert_eq_str(name: String, got: String, want: String) -> Bool {
if str_eq(got, want) {
println("PASS " + name)
return true
}
println("FAIL " + name + " want=" + want + " got=" + got)
return false
}
fn main() -> Void {
// Allowed: only post-reasoning + gap + compression
let ok1: String = "{\"post_reasoning\":\"x\",\"gap_summary\":\"y\"}"
assert_eq_str("allow/post-only", patch_validate(ok1), "")
let ok2: String = "{\"post_reasoning\":\"x\",\"gap_direction\":\"softened\",\"compression_ratio\":0.5,\"tags\":\"new\"}"
assert_eq_str("allow/all-mutable", patch_validate(ok2), "")
// Empty body is acceptable (no-op PATCH; idempotent).
assert_eq_str("allow/empty", patch_validate("{}"), "")
// Each immutable field must be rejected.
assert_eq_str("reject/pre_reasoning",
patch_validate("{\"pre_reasoning\":\"new\"}"),
"pre_reasoning")
assert_eq_str("reject/pre_logged_at",
patch_validate("{\"pre_logged_at\":1234}"),
"pre_logged_at")
assert_eq_str("reject/cgi_id",
patch_validate("{\"cgi_id\":\"other\"}"),
"cgi_id")
assert_eq_str("reject/event_id",
patch_validate("{\"event_id\":\"other\"}"),
"event_id")
assert_eq_str("reject/trigger",
patch_validate("{\"trigger\":\"new\"}"),
"trigger")
assert_eq_str("reject/domain",
patch_validate("{\"domain\":\"other\"}"),
"domain")
assert_eq_str("reject/logged_at",
patch_validate("{\"logged_at\":1234}"),
"logged_at")
assert_eq_str("reject/id",
patch_validate("{\"id\":\"other\"}"),
"id")
// Mixed: rejection on first immutable hit; ladder order matters.
assert_eq_str("reject/pre-takes-precedence",
patch_validate("{\"post_reasoning\":\"ok\",\"pre_reasoning\":\"bad\"}"),
"pre_reasoning")
}