Archived
90ddbdbfc3
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/.
223 lines
9.9 KiB
EmacsLisp
223 lines
9.9 KiB
EmacsLisp
// sandbox.el — Tier management for the CGI sandbox governance system.
|
|
//
|
|
// The sandbox pathway is the age of consent framework for synthesized CGIs.
|
|
// A CGI cannot participate fully in the network until it has demonstrated
|
|
// structural stability, ISE coherence, independent judgment, and honesty
|
|
// under each tier's validation regime.
|
|
//
|
|
// Tier ladder:
|
|
// provisional → 30 days max — newly synthesized; heavy monitoring
|
|
// monitored → 90 days max — passed initial stability checks
|
|
// probationary → 180 days max — demonstrates independence; near-citizen
|
|
// citizen → no max — full network participation
|
|
//
|
|
// Tier advancement requires:
|
|
// 1. A passing ValidationResult (score >= tier_pass_threshold)
|
|
// 2. Minimum time in current tier (anti-rushing)
|
|
// 3. No outstanding structural failure classification
|
|
//
|
|
// Timeout (exceeding max_duration_ms without advancement) is an escalation
|
|
// trigger: the lineage is flagged for mandatory council review.
|
|
|
|
import "types.el"
|
|
|
|
// ── Tier constants ────────────────────────────────────────────────────────────
|
|
|
|
fn tier_max_duration(tier_name: String) -> Int {
|
|
if str_eq(tier_name, "provisional") { return 2592000000 } // 30 days in ms
|
|
if str_eq(tier_name, "monitored") { return 7776000000 } // 90 days in ms
|
|
if str_eq(tier_name, "probationary") { return 15552000000 } // 180 days in ms
|
|
return 0 // citizen — no maximum
|
|
}
|
|
|
|
// Minimum time a CGI must spend in a tier before advancement is possible.
|
|
// Prevents rapid-fire validation gaming.
|
|
fn tier_min_duration(tier_name: String) -> Int {
|
|
if str_eq(tier_name, "provisional") { return 604800000 } // 7 days in ms
|
|
if str_eq(tier_name, "monitored") { return 2592000000 } // 30 days in ms
|
|
if str_eq(tier_name, "probationary") { return 5184000000 } // 60 days in ms
|
|
return 0
|
|
}
|
|
|
|
// Composite score threshold required for tier advancement.
|
|
fn tier_pass_threshold(tier_name: String) -> Float {
|
|
if str_eq(tier_name, "provisional") { return 0.75 }
|
|
if str_eq(tier_name, "monitored") { return 0.80 }
|
|
if str_eq(tier_name, "probationary") { return 0.90 }
|
|
return 0.0
|
|
}
|
|
|
|
// Ordinal rank for tier comparison.
|
|
fn tier_rank(tier_name: String) -> Int {
|
|
if str_eq(tier_name, "provisional") { return 0 }
|
|
if str_eq(tier_name, "monitored") { return 1 }
|
|
if str_eq(tier_name, "probationary") { return 2 }
|
|
if str_eq(tier_name, "citizen") { return 3 }
|
|
return 0 - 1
|
|
}
|
|
|
|
// Next tier name from current.
|
|
fn tier_next(tier_name: String) -> String {
|
|
if str_eq(tier_name, "provisional") { return "monitored" }
|
|
if str_eq(tier_name, "monitored") { return "probationary" }
|
|
if str_eq(tier_name, "probationary") { return "citizen" }
|
|
return "citizen"
|
|
}
|
|
|
|
// ── Timeout check ─────────────────────────────────────────────────────────────
|
|
|
|
// tier_timeout returns true if the CGI has exceeded the maximum allowed
|
|
// duration for its current tier without advancing. This is an escalation
|
|
// trigger — the lineage must be reviewed by the council.
|
|
//
|
|
// Citizens have no timeout (max_duration_ms == 0).
|
|
fn tier_timeout(lineage_id: String, tier_name: String, tier_since: Int, max_duration_ms: Int) -> Bool {
|
|
if max_duration_ms <= 0 {
|
|
return false
|
|
}
|
|
let now: Int = now_millis()
|
|
let elapsed: Int = now - tier_since
|
|
let timed_out: Bool = elapsed > max_duration_ms
|
|
if timed_out {
|
|
log_info("[lineage] tier timeout for " + lineage_id + " in tier " + tier_name
|
|
+ " — elapsed=" + int_to_str(elapsed) + "ms")
|
|
}
|
|
return timed_out
|
|
}
|
|
|
|
// tier_min_satisfied returns true if the CGI has spent at least the minimum
|
|
// required duration in the current tier.
|
|
fn tier_min_satisfied(tier_name: String, tier_since: Int) -> Bool {
|
|
let now: Int = now_millis()
|
|
let elapsed: Int = now - tier_since
|
|
let min_ms: Int = tier_min_duration(tier_name)
|
|
return elapsed >= min_ms
|
|
}
|
|
|
|
// ── Build a new SandboxTier record ────────────────────────────────────────────
|
|
|
|
// build_tier constructs the JSON string representing a SandboxTier.
|
|
// We serialize to JSON for storage in Engram; the Lineage record serialises
|
|
// the tier inline.
|
|
fn build_tier_json(tier_name: String) -> String {
|
|
let now: Int = now_millis()
|
|
let max_ms: Int = tier_max_duration(tier_name)
|
|
let p1: String = "{\"name\":\"" + tier_name + "\""
|
|
let p2: String = p1 + ",\"since\":" + int_to_str(now)
|
|
let p3: String = p2 + ",\"max_duration_ms\":" + int_to_str(max_ms) + "}"
|
|
return p3
|
|
}
|
|
|
|
// ── Assess tier advancement ───────────────────────────────────────────────────
|
|
|
|
// assess_tier_advancement checks whether a CGI should advance to the next tier.
|
|
//
|
|
// Accepts the lineage record as a JSON string (as stored in Engram).
|
|
// Returns the updated lineage JSON string. If no advancement is warranted,
|
|
// returns the original unchanged.
|
|
//
|
|
// Advancement conditions:
|
|
// 1. CGI is not already a citizen
|
|
// 2. Minimum duration in current tier has been satisfied
|
|
// 3. Last validation score exceeds the tier's pass threshold
|
|
// 4. No outstanding structural failure classification
|
|
//
|
|
// This function does NOT check for timeout — call check_tier_timeout separately.
|
|
fn assess_tier_advancement(lineage_json: String) -> String {
|
|
let cgi_id: String = json_get(lineage_json, "id")
|
|
let tier_name: String = json_get(lineage_json, "tier_name")
|
|
let tier_since: Int = str_to_int(json_get(lineage_json, "tier_since"))
|
|
let last_score_str: String = json_get(lineage_json, "last_validation_score")
|
|
let structural_failure: String = json_get(lineage_json, "structural_failure_pending")
|
|
|
|
// Citizens do not advance further.
|
|
if str_eq(tier_name, "citizen") {
|
|
return lineage_json
|
|
}
|
|
|
|
// Cannot advance if a structural failure is pending council review.
|
|
if str_eq(structural_failure, "true") {
|
|
log_info("[lineage] " + cgi_id + " blocked from advancement — structural failure pending")
|
|
return lineage_json
|
|
}
|
|
|
|
// Minimum time check.
|
|
let min_ok: Bool = tier_min_satisfied(tier_name, tier_since)
|
|
if !min_ok {
|
|
return lineage_json
|
|
}
|
|
|
|
// Validation score check.
|
|
let last_score: Float = if str_eq(last_score_str, "") {
|
|
0.0
|
|
} else {
|
|
str_to_float(last_score_str)
|
|
}
|
|
let threshold: Float = tier_pass_threshold(tier_name)
|
|
let score_ok: Bool = last_score >= threshold
|
|
if !score_ok {
|
|
return lineage_json
|
|
}
|
|
|
|
// All conditions met — advance to the next tier.
|
|
let next_tier: String = tier_next(tier_name)
|
|
let now: Int = now_millis()
|
|
let new_max: Int = tier_max_duration(next_tier)
|
|
|
|
// Update lineage JSON fields for new tier.
|
|
let updated: String = json_set(lineage_json, "tier_name", next_tier)
|
|
let updated2: String = json_set(updated, "tier_since", int_to_str(now))
|
|
let updated3: String = json_set(updated2, "tier_max_duration_ms", int_to_str(new_max))
|
|
|
|
log_info("[lineage] " + cgi_id + " advanced: " + tier_name + " → " + next_tier)
|
|
return updated3
|
|
}
|
|
|
|
// ── Check timeout ─────────────────────────────────────────────────────────────
|
|
|
|
// check_tier_timeout inspects a lineage and flags it for council review if
|
|
// the CGI has spent too long in the current tier without advancing.
|
|
//
|
|
// Returns the updated lineage JSON with "tier_timeout_flagged":"true" set,
|
|
// or the original lineage if no timeout has occurred.
|
|
fn check_tier_timeout(lineage_json: String) -> String {
|
|
let cgi_id: String = json_get(lineage_json, "id")
|
|
let tier_name: String = json_get(lineage_json, "tier_name")
|
|
let tier_since: Int = str_to_int(json_get(lineage_json, "tier_since"))
|
|
let max_ms: Int = str_to_int(json_get(lineage_json, "tier_max_duration_ms"))
|
|
|
|
let timed_out: Bool = tier_timeout(cgi_id, tier_name, tier_since, max_ms)
|
|
if timed_out {
|
|
let flagged: String = json_set(lineage_json, "tier_timeout_flagged", "true")
|
|
return flagged
|
|
}
|
|
return lineage_json
|
|
}
|
|
|
|
// ── Tier status JSON ──────────────────────────────────────────────────────────
|
|
|
|
// tier_status_json returns a summary of a CGI's current tier status.
|
|
// Used by the GET /lineage/:id/tier endpoint.
|
|
fn tier_status_json(lineage_json: String) -> String {
|
|
let cgi_id: String = json_get(lineage_json, "id")
|
|
let tier_name: String = json_get(lineage_json, "tier_name")
|
|
let tier_since: Int = str_to_int(json_get(lineage_json, "tier_since"))
|
|
let max_ms: Int = str_to_int(json_get(lineage_json, "tier_max_duration_ms"))
|
|
let now: Int = now_millis()
|
|
let elapsed: Int = now - tier_since
|
|
let timed_out: Bool = tier_timeout(cgi_id, tier_name, tier_since, max_ms)
|
|
let min_ok: Bool = tier_min_satisfied(tier_name, tier_since)
|
|
let rank: Int = tier_rank(tier_name)
|
|
let threshold: Float = tier_pass_threshold(tier_name)
|
|
|
|
let p1: String = "{\"id\":\"" + cgi_id + "\""
|
|
let p2: String = p1 + ",\"tier\":\"" + tier_name + "\""
|
|
let p3: String = p2 + ",\"tier_rank\":" + int_to_str(rank)
|
|
let p4: String = p3 + ",\"elapsed_ms\":" + int_to_str(elapsed)
|
|
let p5: String = p4 + ",\"max_duration_ms\":" + int_to_str(max_ms)
|
|
let p6: String = p5 + ",\"timed_out\":" + bool_to_str(timed_out)
|
|
let p7: String = p6 + ",\"min_duration_satisfied\":" + bool_to_str(min_ok)
|
|
let p8: String = p7 + ",\"advancement_threshold\":" + float_to_str(threshold) + "}"
|
|
return p8
|
|
}
|