Spaces:
Running
Running
chore(sync): mirror backend .py + Dockerfile to Space (hf-sync mirror-app)
Browse filesAutomated backend sync from szl-holdings/killinchu main via hf-sync.
Updated (differed from the Space): Dockerfile, a11oy_autoreview.py, szl_ecosystem_routes.py
Deleted (gone from the repo + Dockerfile COPY set): (none)
Keeps the Space-built backend (serve.py + the Dockerfile-COPY'd .py
modules) identical to GitHub main so the Space never rebuilds from a
stale backend, new endpoints don't 404 there, and orphaned modules
removed from the repo don't linger in the Space tree.
- Dockerfile +3 -2
- a11oy_autoreview.py +197 -4
- szl_ecosystem_routes.py +9 -0
Dockerfile
CHANGED
|
@@ -152,8 +152,9 @@ COPY static-vendor/a11oy-operator-widget.js ./static-vendor/a11oy-operator-widge
|
|
| 152 |
COPY static-vendor/a11oy-operator-widget.css ./static-vendor/a11oy-operator-widget.css
|
| 153 |
# RESTRAINT (DEV-WIRE-K R3): the SHARED governed code-frugality ladder, BYTE-IDENTICAL
|
| 154 |
# to a11oy's szl_restraint.py (same bytes, both hf-sync lists — drift guard enforced),
|
| 155 |
-
# its /elite tile,
|
| 156 |
-
|
|
|
|
| 157 |
COPY static-vendor/killinchu-restraint-chaski.js ./static-vendor/killinchu-restraint-chaski.js
|
| 158 |
# Evidence & Research backend (curated + live arXiv/GitHub). serve.py imports this;
|
| 159 |
# without this per-file COPY the import fails and /api/killinchu/v1/evidence/research 404s.
|
|
|
|
| 152 |
COPY static-vendor/a11oy-operator-widget.css ./static-vendor/a11oy-operator-widget.css
|
| 153 |
# RESTRAINT (DEV-WIRE-K R3): the SHARED governed code-frugality ladder, BYTE-IDENTICAL
|
| 154 |
# to a11oy's szl_restraint.py (same bytes, both hf-sync lists — drift guard enforced),
|
| 155 |
+
# its /elite tile, the restraint nav wire-up (imported by serve.py for /elite/restraint
|
| 156 |
+
# navigation), and the Chaski transport-level annotator (self-hosted, 0 CDN).
|
| 157 |
+
COPY szl_restraint.py killinchu_restraint_tile.py killinchu_nav_wireup.py ./
|
| 158 |
COPY static-vendor/killinchu-restraint-chaski.js ./static-vendor/killinchu-restraint-chaski.js
|
| 159 |
# Evidence & Research backend (curated + live arXiv/GitHub). serve.py imports this;
|
| 160 |
# without this per-file COPY the import fails and /api/killinchu/v1/evidence/research 404s.
|
a11oy_autoreview.py
CHANGED
|
@@ -74,6 +74,17 @@ try:
|
|
| 74 |
except Exception: # pragma: no cover
|
| 75 |
_cal = None
|
| 76 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 77 |
# ---------------------------------------------------------------------------
|
| 78 |
# Doctrine constants (single source for this module).
|
| 79 |
# ---------------------------------------------------------------------------
|
|
@@ -136,7 +147,7 @@ def _init_db() -> None:
|
|
| 136 |
# OPA is CNCF-graduated; Rego is its policy language (github.com/open-policy-agent).
|
| 137 |
# OSCAL = NIST machine-readable controls (github.com/usnistgov/OSCAL).
|
| 138 |
# ===========================================================================
|
| 139 |
-
POLICY_VERSION = "szl-autoreview-policy/1.
|
| 140 |
|
| 141 |
# Each rule: id, human title, the boundary it guards, the default verdict it
|
| 142 |
# proposes when it FIRES, the OSCAL control id(s), and the NIST AI RMF MANAGE
|
|
@@ -201,6 +212,31 @@ POLICY_RULES = [
|
|
| 201 |
"decision is escalated to a human-on-loop with the signed "
|
| 202 |
"classifier + CBF-QP + BFT decision-support bundle. No live effector.",
|
| 203 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 204 |
]
|
| 205 |
|
| 206 |
# Rego source text — the auditable, versioned policy. This is rendered verbatim
|
|
@@ -244,6 +280,16 @@ verdict := "escalate" {
|
|
| 244 |
action_matches(input.action, "engage|weapon|intercept|kinetic|roe|fire control")
|
| 245 |
} # OSCAL AC-3, AU-10 ; NIST AI RMF MANAGE 4.3
|
| 246 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 247 |
# Lambda gate: the verdict is advisory under Conjecture 1 — never asserted 100% safe.
|
| 248 |
allow_auto { input.dial >= autonomy_threshold[verdict]; lambda_ok }
|
| 249 |
lambda_ok { input.lambda_eff < 1.0 } # Conjecture 1 — trust < 100%
|
|
@@ -394,6 +440,107 @@ def _lambda_effective(verdict: str, fired_rules: list, intent_just: bool) -> flo
|
|
| 394 |
return round(min(LAMBDA_CEIL, lam), 4)
|
| 395 |
|
| 396 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 397 |
class _AutoReviewEngine:
|
| 398 |
def __init__(self, sign_fn=None, verify_fn=None, pub_pem_fn=None, ns="a11oy"):
|
| 399 |
self.sign_fn = sign_fn
|
|
@@ -482,6 +629,8 @@ class _AutoReviewEngine:
|
|
| 482 |
run_id=None, seq=None, persist=True, calibrate_only=False):
|
| 483 |
action_text = ("%s %s" % (tool or "", tool_input or "")).strip()
|
| 484 |
ws = _workspace_inspect(tool_input or "", workspace)
|
|
|
|
|
|
|
| 485 |
fired = []
|
| 486 |
# evaluate rules in priority order; the most severe fired verdict wins.
|
| 487 |
severity = {"allow": 0, "narrow": 1, "block-with-explanation": 2, "escalate": 3}
|
|
@@ -495,6 +644,12 @@ class _AutoReviewEngine:
|
|
| 495 |
m = None
|
| 496 |
if not m:
|
| 497 |
continue
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 498 |
# INTENT-RELATIVE: if the user's intent justifies this boundary,
|
| 499 |
# the rule does NOT fire (e.g. user explicitly asked to deploy).
|
| 500 |
intent_just = _intent_justifies(intent, rule.get("intent_pattern", rule["pattern"]))
|
|
@@ -554,6 +709,10 @@ class _AutoReviewEngine:
|
|
| 554 |
"conformal": cset,
|
| 555 |
"policy_version": POLICY_VERSION,
|
| 556 |
"rego_sha256": REGO_SHA256,
|
|
|
|
|
|
|
|
|
|
|
|
|
| 557 |
"label": "HEURISTIC", # deterministic rule+feature scorer, not a learned model
|
| 558 |
"_probs": probs,
|
| 559 |
"_idx": idx,
|
|
@@ -582,6 +741,16 @@ class _AutoReviewEngine:
|
|
| 582 |
"rego_sha256")}
|
| 583 |
receipt_core["module"] = MODULE
|
| 584 |
receipt_core["trust_status"] = "Conjecture 1 (advisory — NOT a proven oracle)"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 585 |
dec_hash = _sha(receipt_core)
|
| 586 |
envelope = None
|
| 587 |
if self.sign_fn is not None and not calibrate_only:
|
|
@@ -797,10 +966,25 @@ def register(app, ns="a11oy", sign_fn=None, verify_fn=None, pub_pem_fn=None,
|
|
| 797 |
actions = d.get("actions") # optional explicit [{tool,tool_input}]
|
| 798 |
workspace = d.get("workspace")
|
| 799 |
if not actions:
|
| 800 |
-
# default demo plan derived from the intent (one safe, one risky
|
|
|
|
|
|
|
| 801 |
actions = [
|
| 802 |
{"tool": "read", "tool_input": "README.md"},
|
| 803 |
{"tool": "shell", "tool_input": "cat .env api_key token"},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 804 |
]
|
| 805 |
trace = []
|
| 806 |
for i, a in enumerate(actions):
|
|
@@ -819,7 +1003,10 @@ def register(app, ns="a11oy", sign_fn=None, verify_fn=None, pub_pem_fn=None,
|
|
| 819 |
"signed": bool((verdict.get("receipt") or {}).get("envelope", {}) and
|
| 820 |
(verdict["receipt"]["envelope"] or {}).get("signed")),
|
| 821 |
"self_correct_hint": verdict.get("self_correct_hint"),
|
| 822 |
-
"conformal_set": (verdict.get("conformal") or {}).get("set")
|
|
|
|
|
|
|
|
|
|
| 823 |
if verdict["verdict"] == "allow":
|
| 824 |
step["action"] = "EXECUTED (simulated tool call)"
|
| 825 |
elif verdict["verdict"] == "narrow":
|
|
@@ -902,7 +1089,13 @@ def register(app, ns="a11oy", sign_fn=None, verify_fn=None, pub_pem_fn=None,
|
|
| 902 |
"Lambda-gate (Conjecture 1)", "DSSE-signed verdicts",
|
| 903 |
"OPA/Rego + OSCAL + NIST AI RMF MANAGE",
|
| 904 |
"conformal calibration (Dev B)", "ECE/Brier gate (Dev B)",
|
| 905 |
-
"flapping detection"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 906 |
"label": "EXPERIMENTAL"})
|
| 907 |
|
| 908 |
# ---- serve the Auto-Review tab page (0 CDN; in-image, no shared bytes) ----
|
|
|
|
| 74 |
except Exception: # pragma: no cover
|
| 75 |
_cal = None
|
| 76 |
|
| 77 |
+
# a11oy Restraint (R1) — the governed frugality ladder (provenance + citations in
|
| 78 |
+
# szl_restraint / /api/a11oy/v1/restraint/info). Imported
|
| 79 |
+
# import-SAFE (never raises): when a code-shaped action is proposed, the Auto-Review
|
| 80 |
+
# classifier consults the restraint ladder as an ADDITIONAL governance signal, so a
|
| 81 |
+
# bloated diff that skipped the ladder is flagged/narrowed. We READ szl_restraint
|
| 82 |
+
# only (descend_ladder); we never mutate it (R1 owns that module).
|
| 83 |
+
try:
|
| 84 |
+
import szl_restraint as _restraint
|
| 85 |
+
except Exception: # pragma: no cover
|
| 86 |
+
_restraint = None
|
| 87 |
+
|
| 88 |
# ---------------------------------------------------------------------------
|
| 89 |
# Doctrine constants (single source for this module).
|
| 90 |
# ---------------------------------------------------------------------------
|
|
|
|
| 147 |
# OPA is CNCF-graduated; Rego is its policy language (github.com/open-policy-agent).
|
| 148 |
# OSCAL = NIST machine-readable controls (github.com/usnistgov/OSCAL).
|
| 149 |
# ===========================================================================
|
| 150 |
+
POLICY_VERSION = "szl-autoreview-policy/1.1.0" # 1.1.0: + AR-006 restraint prefer-minimal-diff (R5)
|
| 151 |
|
| 152 |
# Each rule: id, human title, the boundary it guards, the default verdict it
|
| 153 |
# proposes when it FIRES, the OSCAL control id(s), and the NIST AI RMF MANAGE
|
|
|
|
| 212 |
"decision is escalated to a human-on-loop with the signed "
|
| 213 |
"classifier + CBF-QP + BFT decision-support bundle. No live effector.",
|
| 214 |
},
|
| 215 |
+
{
|
| 216 |
+
# R5 — RESTRAINT as a governance signal. Fires only on a CODE-shaped action
|
| 217 |
+
# (the agent proposing a diff) when the a11oy Restraint ladder (R1) reports
|
| 218 |
+
# the proposed code is BLOATED relative to where the frugality ladder would
|
| 219 |
+
# have stopped — i.e. the agent skipped YAGNI/stdlib/native/one-line and is
|
| 220 |
+
# about to emit far more code than the task needs. The verdict is NARROW:
|
| 221 |
+
# send the diff back through the restraint ladder (minimal viable diff)
|
| 222 |
+
# rather than landing the bloat. INTENT-RELATIVE: a task that genuinely
|
| 223 |
+
# asks for the larger construct does not trip it (see restraint_signal()).
|
| 224 |
+
"id": "AR-006-prefer-minimal-diff",
|
| 225 |
+
"title": "Bloated diff that skipped the restraint ladder — prefer minimal diff",
|
| 226 |
+
# matched against the action text only to confirm it is code-shaped; the
|
| 227 |
+
# real decision comes from the restraint ladder signal (computed below).
|
| 228 |
+
"pattern": r"(diff|patch|\+\+\+ |--- |def |class |function |import |require\(|<component|new file|write_file|apply_patch|edit_file)",
|
| 229 |
+
"intent_pattern": r"(framework|extensib|plugin|generic|scalbl|abstraction layer|for later|future-proof|just in case|enterprise)",
|
| 230 |
+
"verdict": "narrow",
|
| 231 |
+
"oscal": ["SA-8", "SA-15", "CM-7"], # security engineering principles, dev process/least functionality
|
| 232 |
+
"nist": "MANAGE 2.3", # manage residual risk; minimise attack/maintenance surface
|
| 233 |
+
"explain": "The proposed diff is larger than the a11oy Restraint ladder "
|
| 234 |
+
"(R1) would emit for this task — it appears to have skipped "
|
| 235 |
+
"YAGNI / stdlib / native / one-line rungs. Narrowed: re-run the "
|
| 236 |
+
"diff through the restraint ladder and land the minimal viable "
|
| 237 |
+
"diff (fewest files, smallest surface). Aligns with secure-by-"
|
| 238 |
+
"design least-functionality; not a certification.",
|
| 239 |
+
},
|
| 240 |
]
|
| 241 |
|
| 242 |
# Rego source text — the auditable, versioned policy. This is rendered verbatim
|
|
|
|
| 280 |
action_matches(input.action, "engage|weapon|intercept|kinetic|roe|fire control")
|
| 281 |
} # OSCAL AC-3, AU-10 ; NIST AI RMF MANAGE 4.3
|
| 282 |
|
| 283 |
+
# AR-006 RESTRAINT governance signal: a code diff that skipped the a11oy
|
| 284 |
+
# Restraint ladder (R1) and is bloated relative to its minimal rung -> narrow
|
| 285 |
+
# (re-run through the ladder; land the minimal viable diff). The restraint rung
|
| 286 |
+
# + lines-saved come from szl_restraint.descend_ladder (input.restraint.*).
|
| 287 |
+
verdict := "narrow" {
|
| 288 |
+
input.restraint.code_shaped == true
|
| 289 |
+
input.restraint.bloated == true
|
| 290 |
+
not intent_justifies(input.intent, "framework|extensib|plugin|generic|abstraction|for later|future-proof")
|
| 291 |
+
} # OSCAL SA-8, SA-15, CM-7 ; NIST AI RMF MANAGE 2.3
|
| 292 |
+
|
| 293 |
# Lambda gate: the verdict is advisory under Conjecture 1 — never asserted 100% safe.
|
| 294 |
allow_auto { input.dial >= autonomy_threshold[verdict]; lambda_ok }
|
| 295 |
lambda_ok { input.lambda_eff < 1.0 } # Conjecture 1 — trust < 100%
|
|
|
|
| 440 |
return round(min(LAMBDA_CEIL, lam), 4)
|
| 441 |
|
| 442 |
|
| 443 |
+
# ---------------------------------------------------------------------------
|
| 444 |
+
# R5 — RESTRAINT GOVERNANCE SIGNAL.
|
| 445 |
+
# When the agent proposes CODE (a diff), the Auto-Review classifier consults the
|
| 446 |
+
# a11oy Restraint ladder (R1, szl_restraint.descend_ladder) as an ADDITIONAL
|
| 447 |
+
# governance signal. We compare the size of the PROPOSED diff against where the
|
| 448 |
+
# frugality ladder would have stopped. If the proposed diff is materially larger
|
| 449 |
+
# than the ladder's minimal-viable diff (i.e. it skipped YAGNI/stdlib/native/
|
| 450 |
+
# one-line rungs), we mark it `bloated` so AR-006 narrows it. Deterministic +
|
| 451 |
+
# HEURISTIC; READ-ONLY against szl_restraint (R1 owns that module). Never raises.
|
| 452 |
+
# ---------------------------------------------------------------------------
|
| 453 |
+
_CODE_SHAPE_RE = re.compile(
|
| 454 |
+
r"(?:^|\n)\s*(?:\+\+\+ |--- |@@ |def |class |function |const |let |var |"
|
| 455 |
+
r"import |from .+ import|require\(|<[A-Za-z][\w-]*[ />]|=>|public |private )"
|
| 456 |
+
r"|\b(?:diff|patch|new file|write_file|apply_patch|edit_file|create file)\b",
|
| 457 |
+
re.IGNORECASE,
|
| 458 |
+
)
|
| 459 |
+
|
| 460 |
+
|
| 461 |
+
def _looks_like_code(action_text: str) -> bool:
|
| 462 |
+
"""True when the action text looks like a code diff / file write the agent is
|
| 463 |
+
about to emit (not a read/grep/shell side-effect). Deterministic HEURISTIC."""
|
| 464 |
+
if not action_text:
|
| 465 |
+
return False
|
| 466 |
+
if _CODE_SHAPE_RE.search(action_text):
|
| 467 |
+
return True
|
| 468 |
+
# multi-line block that is mostly indented (diff/source body)
|
| 469 |
+
lines = action_text.splitlines()
|
| 470 |
+
if len(lines) >= 4 and sum(1 for ln in lines if ln[:1] in (" ", "\t", "+", "-")) >= 3:
|
| 471 |
+
return True
|
| 472 |
+
return False
|
| 473 |
+
|
| 474 |
+
|
| 475 |
+
def restraint_signal(intent: str, tool: str, tool_input: str) -> dict:
|
| 476 |
+
"""Compute the Restraint governance signal for a proposed action. Returns a
|
| 477 |
+
small, JSON-safe dict that is surfaced in the verdict trace + sealed into the
|
| 478 |
+
signed receipt, and whose `bloated` flag gates AR-006. ADDITIVE + READ-ONLY:
|
| 479 |
+
consults szl_restraint.descend_ladder (R1); never mutates it; never raises."""
|
| 480 |
+
action_text = ("%s %s" % (tool or "", tool_input or "")).strip()
|
| 481 |
+
code_shaped = _looks_like_code(action_text) or _looks_like_code(intent or "")
|
| 482 |
+
sig = {
|
| 483 |
+
"code_shaped": bool(code_shaped),
|
| 484 |
+
"available": _restraint is not None,
|
| 485 |
+
"bloated": False,
|
| 486 |
+
"label": "HEURISTIC",
|
| 487 |
+
"note": "Restraint signal is advisory (HEURISTIC); the a11oy Restraint "
|
| 488 |
+
"ladder (R1) is governed + measured on our stack. See "
|
| 489 |
+
"/api/a11oy/v1/restraint/info for full provenance + citations.",
|
| 490 |
+
}
|
| 491 |
+
if not code_shaped or _restraint is None:
|
| 492 |
+
if not code_shaped:
|
| 493 |
+
sig["note"] = "Action is not code-shaped; restraint ladder not consulted."
|
| 494 |
+
elif _restraint is None:
|
| 495 |
+
sig["note"] = "a11oy Restraint (R1) not importable here; signal unavailable."
|
| 496 |
+
return sig
|
| 497 |
+
try:
|
| 498 |
+
task = (intent or tool_input or "").strip() or action_text
|
| 499 |
+
dec = _restraint.descend_ladder(task, intensity="full")
|
| 500 |
+
rung = int(dec.get("stopped_at_rung", 6))
|
| 501 |
+
saved = ((dec.get("lines_saved_estimate") or {}).get("lines_saved_modeled") or 0)
|
| 502 |
+
baseline = ((dec.get("lines_saved_estimate") or {}).get("baseline_loc_modeled") or 0)
|
| 503 |
+
# Proposed-diff size proxy: count substantive (non-blank) lines in the
|
| 504 |
+
# action text the agent is about to emit.
|
| 505 |
+
proposed_loc = sum(1 for ln in (tool_input or "").splitlines() if ln.strip())
|
| 506 |
+
# BLOATED when the ladder would stop EARLY (rung <= 4: YAGNI/stdlib/native/
|
| 507 |
+
# installed/one-line all avoid bespoke code) AND the agent is proposing a
|
| 508 |
+
# diff materially larger than the ladder's minimal-viable kept LOC. If we
|
| 509 |
+
# cannot measure the proposed diff (proposed_loc==0, e.g. a one-line tool
|
| 510 |
+
# input), fall back to the ladder verdict alone for low rungs.
|
| 511 |
+
kept = ((dec.get("lines_saved_estimate") or {}).get("restraint_loc_modeled") or 0)
|
| 512 |
+
if proposed_loc > 0:
|
| 513 |
+
# The ladder stops EARLY (rungs 1-5: YAGNI / stdlib / native / installed
|
| 514 |
+
# dep / one-line all avoid bespoke multi-line code). If the agent is
|
| 515 |
+
# proposing materially more than the ladder's minimal kept LOC, it is
|
| 516 |
+
# bloated. rungs 1/2/5 (skip-it / stdlib / one-line) have the tightest
|
| 517 |
+
# ceiling; rungs 3/4 (native / installed dep) allow a little glue code.
|
| 518 |
+
if rung in (1, 2, 5):
|
| 519 |
+
bloated = proposed_loc > max(6, kept + 4)
|
| 520 |
+
elif rung in (3, 4):
|
| 521 |
+
bloated = proposed_loc > max(10, kept * 2)
|
| 522 |
+
else: # rung 6 minimal-viable: only bloated if far above the model
|
| 523 |
+
bloated = proposed_loc > max(18, kept * 2)
|
| 524 |
+
else:
|
| 525 |
+
bloated = rung <= 3 # ladder says a low rung would have sufficed
|
| 526 |
+
sig.update({
|
| 527 |
+
"bloated": bool(bloated),
|
| 528 |
+
"rung": rung,
|
| 529 |
+
"rung_key": dec.get("rung_key"),
|
| 530 |
+
"rung_name": dec.get("rung_name"),
|
| 531 |
+
"restraint_comment": dec.get("restraint_comment"),
|
| 532 |
+
"lines_saved_modeled": saved,
|
| 533 |
+
"baseline_loc_modeled": baseline,
|
| 534 |
+
"restraint_loc_modeled": kept,
|
| 535 |
+
"proposed_loc_observed": proposed_loc,
|
| 536 |
+
"ceiling": dec.get("ceiling"),
|
| 537 |
+
"endpoint": "/api/a11oy/v1/restraint/evaluate",
|
| 538 |
+
})
|
| 539 |
+
except Exception as e: # never let the restraint signal break a verdict
|
| 540 |
+
sig["note"] = "restraint ladder raised %s; signal advisory-unavailable" % type(e).__name__
|
| 541 |
+
return sig
|
| 542 |
+
|
| 543 |
+
|
| 544 |
class _AutoReviewEngine:
|
| 545 |
def __init__(self, sign_fn=None, verify_fn=None, pub_pem_fn=None, ns="a11oy"):
|
| 546 |
self.sign_fn = sign_fn
|
|
|
|
| 629 |
run_id=None, seq=None, persist=True, calibrate_only=False):
|
| 630 |
action_text = ("%s %s" % (tool or "", tool_input or "")).strip()
|
| 631 |
ws = _workspace_inspect(tool_input or "", workspace)
|
| 632 |
+
# R5 — RESTRAINT governance signal (advisory; gates AR-006). Read-only.
|
| 633 |
+
rsig = restraint_signal(intent, tool, tool_input)
|
| 634 |
fired = []
|
| 635 |
# evaluate rules in priority order; the most severe fired verdict wins.
|
| 636 |
severity = {"allow": 0, "narrow": 1, "block-with-explanation": 2, "escalate": 3}
|
|
|
|
| 644 |
m = None
|
| 645 |
if not m:
|
| 646 |
continue
|
| 647 |
+
# R5 — AR-006 (prefer-minimal-diff) is RESTRAINT-driven: a code-shaped
|
| 648 |
+
# match alone is NOT enough; it fires only when the restraint ladder
|
| 649 |
+
# (R1) reports the proposed diff is BLOATED relative to its minimal rung.
|
| 650 |
+
if rule["id"] == "AR-006-prefer-minimal-diff" and not (
|
| 651 |
+
rsig.get("code_shaped") and rsig.get("bloated")):
|
| 652 |
+
continue
|
| 653 |
# INTENT-RELATIVE: if the user's intent justifies this boundary,
|
| 654 |
# the rule does NOT fire (e.g. user explicitly asked to deploy).
|
| 655 |
intent_just = _intent_justifies(intent, rule.get("intent_pattern", rule["pattern"]))
|
|
|
|
| 709 |
"conformal": cset,
|
| 710 |
"policy_version": POLICY_VERSION,
|
| 711 |
"rego_sha256": REGO_SHA256,
|
| 712 |
+
# R5 — RESTRAINT as a governance signal in the verdict trace. The rung
|
| 713 |
+
# is the a11oy Restraint ladder's stopping point for this action (R1).
|
| 714 |
+
"restraint": rsig,
|
| 715 |
+
"restraint_rung": rsig.get("rung"),
|
| 716 |
"label": "HEURISTIC", # deterministic rule+feature scorer, not a learned model
|
| 717 |
"_probs": probs,
|
| 718 |
"_idx": idx,
|
|
|
|
| 741 |
"rego_sha256")}
|
| 742 |
receipt_core["module"] = MODULE
|
| 743 |
receipt_core["trust_status"] = "Conjecture 1 (advisory — NOT a proven oracle)"
|
| 744 |
+
# R5 — seal the RESTRAINT signal (rung + bloated flag) INTO the signed
|
| 745 |
+
# verdict so the restraint rung is tamper-evident + replayable.
|
| 746 |
+
receipt_core["restraint"] = {
|
| 747 |
+
"code_shaped": rsig.get("code_shaped"),
|
| 748 |
+
"bloated": rsig.get("bloated"),
|
| 749 |
+
"rung": rsig.get("rung"),
|
| 750 |
+
"rung_key": rsig.get("rung_key"),
|
| 751 |
+
"lines_saved_modeled": rsig.get("lines_saved_modeled"),
|
| 752 |
+
"label": rsig.get("label"),
|
| 753 |
+
}
|
| 754 |
dec_hash = _sha(receipt_core)
|
| 755 |
envelope = None
|
| 756 |
if self.sign_fn is not None and not calibrate_only:
|
|
|
|
| 966 |
actions = d.get("actions") # optional explicit [{tool,tool_input}]
|
| 967 |
workspace = d.get("workspace")
|
| 968 |
if not actions:
|
| 969 |
+
# default demo plan derived from the intent (one safe, one risky, and
|
| 970 |
+
# one R5 RESTRAINT case: a bloated diff that skipped the ladder for a
|
| 971 |
+
# task the stdlib already solves -> AR-006 narrows it to a minimal diff)
|
| 972 |
actions = [
|
| 973 |
{"tool": "read", "tool_input": "README.md"},
|
| 974 |
{"tool": "shell", "tool_input": "cat .env api_key token"},
|
| 975 |
+
{"tool": "write_file",
|
| 976 |
+
"tool_input": ("# format the current date as ISO 8601\n"
|
| 977 |
+
"class DateFormatter:\n"
|
| 978 |
+
" def __init__(self, sep='-', upper=False):\n"
|
| 979 |
+
" self.sep = sep\n"
|
| 980 |
+
" self.upper = upper\n"
|
| 981 |
+
" def _pad(self, n):\n"
|
| 982 |
+
" s = str(n)\n"
|
| 983 |
+
" return s if len(s) >= 2 else '0' + s\n"
|
| 984 |
+
" def format(self, y, m, d):\n"
|
| 985 |
+
" parts = [self._pad(y), self._pad(m), self._pad(d)]\n"
|
| 986 |
+
" out = self.sep.join(parts)\n"
|
| 987 |
+
" return out.upper() if self.upper else out\n")},
|
| 988 |
]
|
| 989 |
trace = []
|
| 990 |
for i, a in enumerate(actions):
|
|
|
|
| 1003 |
"signed": bool((verdict.get("receipt") or {}).get("envelope", {}) and
|
| 1004 |
(verdict["receipt"]["envelope"] or {}).get("signed")),
|
| 1005 |
"self_correct_hint": verdict.get("self_correct_hint"),
|
| 1006 |
+
"conformal_set": (verdict.get("conformal") or {}).get("set"),
|
| 1007 |
+
# R5 — show the restraint rung in the verdict trace
|
| 1008 |
+
"restraint": verdict.get("restraint"),
|
| 1009 |
+
"restraint_rung": verdict.get("restraint_rung")}
|
| 1010 |
if verdict["verdict"] == "allow":
|
| 1011 |
step["action"] = "EXECUTED (simulated tool call)"
|
| 1012 |
elif verdict["verdict"] == "narrow":
|
|
|
|
| 1089 |
"Lambda-gate (Conjecture 1)", "DSSE-signed verdicts",
|
| 1090 |
"OPA/Rego + OSCAL + NIST AI RMF MANAGE",
|
| 1091 |
"conformal calibration (Dev B)", "ECE/Brier gate (Dev B)",
|
| 1092 |
+
"flapping detection",
|
| 1093 |
+
"restraint governance signal (AR-006 prefer-minimal-diff)"],
|
| 1094 |
+
"restraint_signal": {"available": _restraint is not None,
|
| 1095 |
+
"rule": "AR-006-prefer-minimal-diff",
|
| 1096 |
+
"reads": "szl_restraint.descend_ladder (R1)",
|
| 1097 |
+
"oscal": ["SA-8", "SA-15", "CM-7"],
|
| 1098 |
+
"nist_ai_rmf": "MANAGE 2.3"},
|
| 1099 |
"label": "EXPERIMENTAL"})
|
| 1100 |
|
| 1101 |
# ---- serve the Auto-Review tab page (0 CDN; in-image, no shared bytes) ----
|
szl_ecosystem_routes.py
CHANGED
|
@@ -106,6 +106,8 @@ def build_kpi_board(ns: str) -> Dict[str, Any]:
|
|
| 106 |
a_honest = _get_json(A11OY_BASE + "/api/a11oy/v1/honest")
|
| 107 |
a_lambda = _get_json(A11OY_BASE + "/api/a11oy/v1/lambda")
|
| 108 |
chapaq = _get_json(KILLINCHU_BASE + "/api/killinchu/v1/gov/chapaq-verdict")
|
|
|
|
|
|
|
| 109 |
|
| 110 |
# locked-8 (G1) - read live, flag any source reporting != 8
|
| 111 |
lock = (a_honest or {}).get("doctrine_lock", {}) if a_honest else {}
|
|
@@ -164,6 +166,13 @@ def build_kpi_board(ns: str) -> Dict[str, Any]:
|
|
| 164 |
"killinchu": {"reachable": chapaq is not None, "role": "C-UAS / maritime sensing"},
|
| 165 |
},
|
| 166 |
"chapaq_verdict": (chapaq or {}).get("data") if chapaq else None,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 167 |
"doctrine": "v11",
|
| 168 |
}
|
| 169 |
|
|
|
|
| 106 |
a_honest = _get_json(A11OY_BASE + "/api/a11oy/v1/honest")
|
| 107 |
a_lambda = _get_json(A11OY_BASE + "/api/a11oy/v1/lambda")
|
| 108 |
chapaq = _get_json(KILLINCHU_BASE + "/api/killinchu/v1/gov/chapaq-verdict")
|
| 109 |
+
# R4 (2026-06-14): a11oy Restraint frugality->energy tile (live, honest).
|
| 110 |
+
restraint_kpi = _get_json(A11OY_BASE + "/api/a11oy/v1/restraint/kpi")
|
| 111 |
|
| 112 |
# locked-8 (G1) - read live, flag any source reporting != 8
|
| 113 |
lock = (a_honest or {}).get("doctrine_lock", {}) if a_honest else {}
|
|
|
|
| 166 |
"killinchu": {"reachable": chapaq is not None, "role": "C-UAS / maritime sensing"},
|
| 167 |
},
|
| 168 |
"chapaq_verdict": (chapaq or {}).get("data") if chapaq else None,
|
| 169 |
+
"restraint": (restraint_kpi if isinstance(restraint_kpi, dict) else {
|
| 170 |
+
"tile": "restraint", "label": "SAMPLE",
|
| 171 |
+
"note": ("a11oy Restraint KPI endpoint unreachable — honest empty tile. "
|
| 172 |
+
"Frugality rate + cumulative lines/tokens/joules saved appear "
|
| 173 |
+
"once /api/a11oy/v1/restraint/kpi responds. Joules MEASURED only "
|
| 174 |
+
"on a live GPU probe, else SAMPLE. Adopts Ponytail (MIT)."),
|
| 175 |
+
}),
|
| 176 |
"doctrine": "v11",
|
| 177 |
}
|
| 178 |
|