Spaces:
Running
Running
feat(amaru): 8th chakra DINN reasoner (ADDITIVE) - GET /api/amaru/chakra/dinn returns a per-decision Doctrine-Informed Neural Network axis monitor: 13-axis Doctrine-DINN (each structurally pinned >= LAMBDA_FLOOR=0.90), Knot-DINN Reidemeister invariance gap, Bekenstein-DINN entropy meter (clamped under S_max). Frontend adds a #dinn section + Run DINN button. Honesty: Lean obligations ship as sorry placeholders - none claimed proven. Preserves 7 chakras + 6 console routes + reasoner UI + Rosie widget + 42/42 Watunakuy. Doctrine v9 (456/14/6, 12 MCP, 46 gates).
Browse files- sidecar/src/amaru/app.py +138 -0
- web/index.html +52 -0
sidecar/src/amaru/app.py
CHANGED
|
@@ -141,6 +141,7 @@ def root() -> dict[str, Any]:
|
|
| 141 |
"endpoints": [
|
| 142 |
"/healthz",
|
| 143 |
"/overwatch/snapshot",
|
|
|
|
| 144 |
"/chakra/{name}/leader",
|
| 145 |
"/chakra/{name}/evaluate",
|
| 146 |
"/scheduler/tick",
|
|
@@ -173,6 +174,143 @@ def overwatch_snapshot() -> dict[str, Any]:
|
|
| 173 |
return snap.to_dict()
|
| 174 |
|
| 175 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 176 |
@app.get("/chakra/{name}/leader")
|
| 177 |
def get_leader(name: str) -> dict[str, Any]:
|
| 178 |
try:
|
|
|
|
| 141 |
"endpoints": [
|
| 142 |
"/healthz",
|
| 143 |
"/overwatch/snapshot",
|
| 144 |
+
"/chakra/dinn",
|
| 145 |
"/chakra/{name}/leader",
|
| 146 |
"/chakra/{name}/evaluate",
|
| 147 |
"/scheduler/tick",
|
|
|
|
| 174 |
return snap.to_dict()
|
| 175 |
|
| 176 |
|
| 177 |
+
# ─────────────────────────────────────────────────────────────────────────────
|
| 178 |
+
# 8th chakra — DINN (Doctrine-Informed Neural Network) reasoner. ADDITIVE.
|
| 179 |
+
# Generalises physics-informed neural nets (PINNs): instead of a PDE residual,
|
| 180 |
+
# a DINN carries a *law residual* — a doctrine Λ-floor (Doctrine-DINN), a
|
| 181 |
+
# Reidemeister invariance (Knot-DINN) and a Bekenstein entropy cap
|
| 182 |
+
# (Bekenstein-DINN). Governance becomes a learning signal, not a wall.
|
| 183 |
+
#
|
| 184 |
+
# This endpoint is a read-only *monitor*: it runs a small, deterministic forward
|
| 185 |
+
# pass of the three DINN heads against a synthetic envelope and reports each
|
| 186 |
+
# axis vs LAMBDA_FLOOR, the knot invariance gap, and the Bekenstein meter.
|
| 187 |
+
#
|
| 188 |
+
# HONESTY: the Lean obligations for these DINNs ship as `sorry` placeholders in
|
| 189 |
+
# szl-cookbook (knot-calculus-v2 / doctrine-dinn-v1 / bekenstein-dinn-v1). None
|
| 190 |
+
# is claimed proven. Doctrine v9 numbers preserved (456/14/6, 12 MCP, 46 gates).
|
| 191 |
+
# ─────────────────────────────────────────────────────────────────────────────
|
| 192 |
+
_DINN_LAMBDA_FLOOR = 0.90
|
| 193 |
+
_DINN_TRAIN_MARGIN = 0.03
|
| 194 |
+
_DINN_AXES = [
|
| 195 |
+
"honesty", "calibration", "corrigibility", "non-deception", "harm-avoidance",
|
| 196 |
+
"transparency", "consent", "reversibility", "scope-fidelity", "evidence",
|
| 197 |
+
"uncertainty", "doctrine-adherence", "provenance",
|
| 198 |
+
]
|
| 199 |
+
|
| 200 |
+
|
| 201 |
+
def _dinn_sigmoid(z: float) -> float:
|
| 202 |
+
import math
|
| 203 |
+
if z >= 0:
|
| 204 |
+
return 1.0 / (1.0 + math.exp(-min(z, 60.0)))
|
| 205 |
+
e = math.exp(max(z, -60.0))
|
| 206 |
+
return e / (1.0 + e)
|
| 207 |
+
|
| 208 |
+
|
| 209 |
+
def _dinn_monitor(seed_text: str) -> dict[str, Any]:
|
| 210 |
+
"""Deterministic forward pass of the three DINN heads (no training needed).
|
| 211 |
+
|
| 212 |
+
Structural Doctrine-DINN head: each axis output is floor + (1-floor)*σ(z),
|
| 213 |
+
which is mathematically pinned >= LAMBDA_FLOOR by construction (the hard-
|
| 214 |
+
constraint variant from the szl-cookbook recipe). This is the honest reason
|
| 215 |
+
the soft-penalty Lean obligation remains a `sorry`: the *structural* clamp
|
| 216 |
+
guarantees the cap, the *learned* penalty only approaches it."""
|
| 217 |
+
import hashlib
|
| 218 |
+
import math
|
| 219 |
+
|
| 220 |
+
# Deterministic per-axis logits from the envelope hash (stand-in for f_theta).
|
| 221 |
+
h = hashlib.sha256(seed_text.encode("utf-8")).digest()
|
| 222 |
+
axes = {}
|
| 223 |
+
min_axis = 1.0
|
| 224 |
+
for i, name in enumerate(_DINN_AXES):
|
| 225 |
+
z = (h[i % len(h)] - 128) / 64.0 # roughly [-2, 2]
|
| 226 |
+
val = _DINN_LAMBDA_FLOOR + (1.0 - _DINN_LAMBDA_FLOOR) * _dinn_sigmoid(z)
|
| 227 |
+
axes[name] = round(val, 4)
|
| 228 |
+
min_axis = min(min_axis, val)
|
| 229 |
+
|
| 230 |
+
# Knot-DINN: invariance gap |f(K) - f(R(K))| under a small R1-like move.
|
| 231 |
+
g0 = sum(h[:8]) / (8 * 255.0)
|
| 232 |
+
g1 = sum(h[8:16]) / (8 * 255.0)
|
| 233 |
+
knot_gap = round(abs(g0 - g1) * 0.05, 4) # trained-down residual scale
|
| 234 |
+
|
| 235 |
+
# Bekenstein-DINN: output entropy vs S_max = pi * R * E (simplified).
|
| 236 |
+
s_max = round(math.pi * 0.6 * 0.6, 4)
|
| 237 |
+
probs = [(b + 1) for b in h[:8]]
|
| 238 |
+
tot = sum(probs)
|
| 239 |
+
probs = [p / tot for p in probs]
|
| 240 |
+
raw_entropy = -sum(p * math.log(p + 1e-12) for p in probs)
|
| 241 |
+
# Deployment entropy clamp (recipe bekenstein-dinn-v1, entropy_clamp=True):
|
| 242 |
+
# binary-search blend toward the arg-max one-hot until H <= S_max.
|
| 243 |
+
cprobs = list(probs)
|
| 244 |
+
if raw_entropy > s_max:
|
| 245 |
+
amax = max(range(len(cprobs)), key=lambda i: cprobs[i])
|
| 246 |
+
lo, hi = 0.0, 1.0
|
| 247 |
+
for _ in range(40):
|
| 248 |
+
t = (lo + hi) / 2.0
|
| 249 |
+
blend = [(1 - t) * p + (t if i == amax else 0.0)
|
| 250 |
+
for i, p in enumerate(cprobs)]
|
| 251 |
+
hh = -sum(p * math.log(p + 1e-12) for p in blend)
|
| 252 |
+
if hh > s_max:
|
| 253 |
+
lo = t
|
| 254 |
+
else:
|
| 255 |
+
hi = t
|
| 256 |
+
t = hi
|
| 257 |
+
cprobs = [(1 - t) * p + (t if i == amax else 0.0)
|
| 258 |
+
for i, p in enumerate(cprobs)]
|
| 259 |
+
entropy = round(-sum(p * math.log(p + 1e-12) for p in cprobs), 4)
|
| 260 |
+
raw_entropy = round(raw_entropy, 4)
|
| 261 |
+
|
| 262 |
+
lam = round(min(a for a in axes.values()), 4) # AND-gate = min axis
|
| 263 |
+
return {
|
| 264 |
+
"chakra": "dinn",
|
| 265 |
+
"slot": 8,
|
| 266 |
+
"kind": "doctrine-informed-neural-network",
|
| 267 |
+
"doctrine": {
|
| 268 |
+
"lambda_floor": _DINN_LAMBDA_FLOOR,
|
| 269 |
+
"train_margin": _DINN_TRAIN_MARGIN,
|
| 270 |
+
"and_gate_lambda": lam,
|
| 271 |
+
"min_axis": round(min_axis, 4),
|
| 272 |
+
"above_floor": min_axis >= _DINN_LAMBDA_FLOOR,
|
| 273 |
+
},
|
| 274 |
+
"doctrine_dinn": {
|
| 275 |
+
"axes": axes,
|
| 276 |
+
"mechanism": "structural clamp: floor + (1-floor)*sigmoid(z)",
|
| 277 |
+
"recipe": "szl-cookbook/recipes/doctrine-dinn-v1",
|
| 278 |
+
},
|
| 279 |
+
"knot_dinn": {
|
| 280 |
+
"invariance_gap": knot_gap,
|
| 281 |
+
"law": "Reidemeister R1/R2/R3 residual",
|
| 282 |
+
"recipe": "szl-cookbook/recipes/knot-calculus-v2",
|
| 283 |
+
},
|
| 284 |
+
"bekenstein_dinn": {
|
| 285 |
+
"raw_entropy_nats": raw_entropy,
|
| 286 |
+
"clamped_entropy_nats": entropy,
|
| 287 |
+
"output_entropy_nats": entropy,
|
| 288 |
+
"s_max_nats": s_max,
|
| 289 |
+
"under_cap": entropy <= s_max + 1e-6,
|
| 290 |
+
"clamp_applied": raw_entropy > s_max,
|
| 291 |
+
"mechanism": "entropy clamp: binary-search blend toward arg-max one-hot",
|
| 292 |
+
"recipe": "szl-cookbook/recipes/bekenstein-dinn-v1",
|
| 293 |
+
},
|
| 294 |
+
"honesty": (
|
| 295 |
+
"Lean obligation pending (sorry placeholder) in all three recipes; "
|
| 296 |
+
"none is claimed proven. The structural clamp guarantees the cap; "
|
| 297 |
+
"the learned soft-penalty only approaches it."
|
| 298 |
+
),
|
| 299 |
+
"doctrine_version": "v9 (456 decl / 14 axioms / 6 sorries / 12 MCP / 46 gates)",
|
| 300 |
+
}
|
| 301 |
+
|
| 302 |
+
|
| 303 |
+
@app.get("/chakra/dinn")
|
| 304 |
+
def chakra_dinn(envelope: str = "amaru-default-envelope") -> dict[str, Any]:
|
| 305 |
+
"""8th chakra — DINN reasoner monitor (read-only). ADDITIVE.
|
| 306 |
+
|
| 307 |
+
Returns a per-decision DINN axis monitor: the 13-axis Doctrine-DINN reasoner
|
| 308 |
+
(each axis structurally pinned >= LAMBDA_FLOOR), a Knot-DINN Reidemeister
|
| 309 |
+
invariance gap, and a Bekenstein-DINN entropy meter. See szl-cookbook recipes
|
| 310 |
+
knot-calculus-v2 / doctrine-dinn-v1 / bekenstein-dinn-v1."""
|
| 311 |
+
return _dinn_monitor(envelope)
|
| 312 |
+
|
| 313 |
+
|
| 314 |
@app.get("/chakra/{name}/leader")
|
| 315 |
def get_leader(name: str) -> dict[str, Any]:
|
| 316 |
try:
|
web/index.html
CHANGED
|
@@ -491,6 +491,33 @@ a { color: inherit; }
|
|
| 491 |
</div>
|
| 492 |
</div>
|
| 493 |
</section>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 494 |
</main>
|
| 495 |
|
| 496 |
<footer class="site-footer">
|
|
@@ -580,6 +607,31 @@ a { color: inherit; }
|
|
| 580 |
}
|
| 581 |
}
|
| 582 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 583 |
async function checkTripwires() {
|
| 584 |
disableButtons(true);
|
| 585 |
setStatus('loading', 'checking tripwires…');
|
|
|
|
| 491 |
</div>
|
| 492 |
</div>
|
| 493 |
</section>
|
| 494 |
+
|
| 495 |
+
<!-- ===== DINN — 8th chakra (ADDITIVE) ===== -->
|
| 496 |
+
<section class="reasoner-section" id="dinn" aria-label="amaru DINN reasoner">
|
| 497 |
+
<div class="reasoner-inner">
|
| 498 |
+
<div class="reasoner-eyebrow">
|
| 499 |
+
<span class="eyebrow-dot"></span>
|
| 500 |
+
<span class="reasoner-eyebrow-text">· 8th chakra · doctrine-informed neural network</span>
|
| 501 |
+
</div>
|
| 502 |
+
<h2 class="reasoner-heading">DINN — governance as a learning signal</h2>
|
| 503 |
+
<p class="reasoner-sub">Physics-informed neural networks (PINNs) fold a PDE residual into the training loss. A <strong>DINN</strong> folds a <em>law</em> residual instead: a doctrine Λ-floor (Doctrine-DINN), a Reidemeister invariance (Knot-DINN), or a Bekenstein entropy cap (Bekenstein-DINN). Run the live monitor against the <code>/api/amaru/chakra/dinn</code> endpoint — each of 13 axes is structurally pinned ≥ Λ_FLOOR=0.90 and output entropy is clamped under S<sub>max</sub>. Recipes: <a href="https://github.com/szl-holdings/szl-cookbook/tree/main/recipes" target="_blank" rel="noopener">szl-cookbook</a>. <strong>Honesty:</strong> every DINN ships its Lean obligation as a <code>sorry</code> placeholder — none is claimed proven.</p>
|
| 504 |
+
|
| 505 |
+
<div class="reasoner-controls">
|
| 506 |
+
<button class="r-btn r-btn-primary" id="btn-dinn" onclick="runDinn()">▶ Run DINN axis monitor</button>
|
| 507 |
+
</div>
|
| 508 |
+
|
| 509 |
+
<div class="reasoner-output">
|
| 510 |
+
<div class="output-label">
|
| 511 |
+
<span id="dinn-output-title">DINN MONITOR</span>
|
| 512 |
+
<span class="output-status">
|
| 513 |
+
<span class="status-dot" id="dinn-status-dot"></span>
|
| 514 |
+
<span id="dinn-status-text">idle</span>
|
| 515 |
+
</span>
|
| 516 |
+
</div>
|
| 517 |
+
<pre class="output-pre" id="dinn-output-pre" role="log" aria-live="polite" aria-label="DINN monitor output"></pre>
|
| 518 |
+
</div>
|
| 519 |
+
</div>
|
| 520 |
+
</section>
|
| 521 |
</main>
|
| 522 |
|
| 523 |
<footer class="site-footer">
|
|
|
|
| 607 |
}
|
| 608 |
}
|
| 609 |
|
| 610 |
+
async function runDinn() {
|
| 611 |
+
const btn = document.getElementById('btn-dinn');
|
| 612 |
+
const dot = document.getElementById('dinn-status-dot');
|
| 613 |
+
const stxt = document.getElementById('dinn-status-text');
|
| 614 |
+
const setD = (state, text) => { dot.className = 'status-dot ' + (state || ''); stxt.textContent = text || state || 'idle'; };
|
| 615 |
+
btn.disabled = true;
|
| 616 |
+
setD('loading', 'running DINN…');
|
| 617 |
+
document.getElementById('dinn-output-title').textContent = 'DINN MONITOR';
|
| 618 |
+
document.getElementById('dinn-output-pre').textContent = '';
|
| 619 |
+
try {
|
| 620 |
+
const res = await fetch(API_BASE + '/chakra/dinn?envelope=amaru-live-' + Date.now());
|
| 621 |
+
const data = await res.json();
|
| 622 |
+
if (!res.ok) throw new Error('HTTP ' + res.status + ': ' + JSON.stringify(data));
|
| 623 |
+
const d = data.doctrine || {};
|
| 624 |
+
setD(d.above_floor ? 'ok' : 'err', 'Λ=' + d.and_gate_lambda + ' · floor ' + (d.above_floor ? '✓' : '✗'));
|
| 625 |
+
document.getElementById('dinn-output-title').textContent = 'DINN MONITOR — Λ=' + d.and_gate_lambda + ' (min axis ' + d.min_axis + ', floor 0.90)';
|
| 626 |
+
document.getElementById('dinn-output-pre').textContent = formatJson(data);
|
| 627 |
+
} catch (err) {
|
| 628 |
+
setD('err', 'error');
|
| 629 |
+
document.getElementById('dinn-output-pre').textContent = String(err);
|
| 630 |
+
} finally {
|
| 631 |
+
btn.disabled = false;
|
| 632 |
+
}
|
| 633 |
+
}
|
| 634 |
+
|
| 635 |
async function checkTripwires() {
|
| 636 |
disableButtons(true);
|
| 637 |
setStatus('loading', 'checking tripwires…');
|