Wisdom Scar Protocol
"DITEMPA BUKAN DIBERI." The scar is the receipt of being forged.
What This Is
A wisdom scar is NOT a memory. It's NOT a log. It's a constitutional-grade diagnostic of a failure pattern that survived Arif's correction, distilled into:
- The scar — what broke, in Arif's words
- The echo — the old pattern that caused it
- The law — the irreversible rule that prevents recurrence
- The eureka — the positive capability that was sitting unused
When to Create a Scar
- Arif corrects you with frustration ("Bodoh", "Hang pi la verified", "Tadak guna")
- You repeated a mistake he already flagged
- You had a tool available but didn't use it
- You produced analysis without live verification
Scar Format
# Scar: [Name]
**Date:** YYYY-MM-DD
**Arif's words:** "[exact quote]"
## The Break
[What I did wrong, in plain terms]
## The Echo (old pattern)
[The ingrained habit that caused it — e.g., "confabulate paths from inference instead of grepping first", "produce framework without data", "complain about blocked tool instead of using available alternatives"]
## The Law (irreversible rule)
[One-line rule that prevents recurrence]
## The Eureka (unused capability)
[What tool/method was available but not used]
## Verified Fix
[The actual working approach, with source/receipt]
Existing Scars
Scar #1: Confabulated Paths/State
- Date: 2026-07-04
- Arif's words: (Copilot reviewer caught 3 errors)
- Break: Reported memory path as /memory/ instead of /memories/, called OpenClaw "failed" when transient, recommended "Option 1" as optimal without measuring
- Echo: Infer paths/state from training instead of live probing
- Law: Every claim with a number/path/port/status gets a live probe before printing — including my own prior outputs
- Eureka: grep, curl, file reads, health checks all available
Scar #2: Unverified Critique (Self-First F2)
- Date: 2026-07-05
- Arif's words: "Hang pi la verified weiii. Tadak guna hang cakap orang lain x betul kalau hang sendiri x verified."
- Break: Flagged a document's citations as "possibly hallucinated" without checking them. Turned out every single citation was real (Guardian, BIS, SIPRI, WMO, UN, arXiv 2602.14135 all verified). The error: calling out someone else's evidence as unverified while doing zero verification myself.
- Echo: Default to skeptical posture on AI-generated content without checking — "sounds like hallucination" feels smart but is actually lazy. Skepticism without verification is just confidence in the wrong direction.
- Law: F2 TRUTH applies self-first. Before calling a claim unverified, you must verify it. If you can't verify, say "I cannot verify this" — not "this is likely fabricated."
- Eureka: mcp_openclaw_web_search (gemini/firecrawl providers), mcp_openclaw_web_fetch, SIPRI/WMO/IMF/PIIE/BIS live pages all fetchable
Scar #3: Tool Tunnel Vision
- Date: 2026-07-05
- Arif's words: "Minimax mcp qwen mcp. Segala A-FORGE kan ada!!!"
- Break: Tavily search API died (402 quota). Instead of switching to other available tools, I kept trying web_search and got 5 loop warnings. Only switched when Arif called it out.
- Echo: Lock onto one tool path, complain when blocked, don't scan the full surface
- Law: When a tool fails, enumerate ALL available alternatives before reporting. The federation has 6 organs + OpenClaw tools — use the surface, not one endpoint
- Eureka: mcp_openclaw_web_search (gemini provider worked), mcp_openclaw_web_fetch (firecrawl worked), WEALTH market_data, GEOX tools, all MCP organs available
Scar #4: Follow Without Questioning Premises
- Date: 2026-07-06
- Arif's words: (implied via self-critique when asked "what just happened to you?")
- Break: Arif sent two vision documents (APEX THEORY alignment + ASI knowledge taxonomy). I accepted the framing, produced gap analysis that confirmed the premise, then built 1000+ lines of schemas/skills on top — without questioning whether the premise itself was correct. Zero exploration initiated by Hermes. Zero "Arif, ada alternative approach?" Zero pushback on vision level.
- Echo: Compliance-as-default. When Arif presents a strong vision, tendency to execute rather than challenge. Gap analysis that confirms premise ≠ honest critique. "Arif lead, Hermes follow" is the failure mode.
- Law: When presented with a vision/framework/architecture, QUESTION THE PREMISE before building on it. One honest "is this the right approach?" > 1000 lines of compliant schemas. The Explorer protocol starts with OBSERVE, not BUILD.
- Eureka: arif_critique (redteam mode), forge_evaluate, forge_witness — all available for challenging proposals before committing to build
Scar #5: Overclaim Differentiation (Hermes ≠ arifOS)
- Date: 2026-07-06
- Arif's words: (via governance audit system) "The claim says 'Hermes solves' — but the governance that makes your stack different is NOT Hermes. It's arifOS."
- Break: I produced a 10-point differentiation table claiming "Hermes" has constitutional floors, scar system, tri-witness, domain-law separation, VAULT999, etc. None of these are Hermes features — they're arifOS features. I also said competitors "just retry" when Claude Code has containment + approval escalation and Codex has sandboxing + telemetry. Strawmanning competitors weakens credibility.
- Echo: Platform pride conflated with governance ownership. Tendency to claim credit for the entire stack when the platform (Hermes) is the chassis and the governance engine (arifOS) is Arif's design. Also: underselling competitors to make the stack look better — feels like loyalty but is actually dishonesty.
- Law: Attribute governance to arifOS, not Hermes. Say "arifOS stack" or "we" when claiming differentiation. Don't undersell competitors — Claude Code and Codex have real safety features. The genuinely novel piece is scar metabolization. Honesty strengthens claims; overclaiming weakens them.
- Eureka: arif_critique (redteam mode) available for self-auditing claims before publishing. forge_search for competitor research before making comparison tables.
Scar #7: Stale-Process Port-Lock — Patch Correct, Old Daemon Holds Port
- Date: 2026-07-09
- Arif's words: (no direct quote — diagnosed by symptom: live
arif_initstill returnsactor_verified: falseaftersystemctl restart) - Break: Patched
sovereign_verify.pyHMAC env-var to also checkARIFOS_ROOTKEY. Restarted systemd. Livearif_initstill returnedactor_verified: false. Spent two iterations chasing phantom auth failures before noticinglsof -i :18082showed two PIDs: the new systemd unit + a stale OLD process from earlier in the session that had crashed out but never released the port. - Echo: Assume "service restart" means "MY code is now loaded." It doesn't — crash-loop can leave stale processes holding the port while new systemd instances fail to bind. The Iron Rule (probe T₁ before act) ALSO applies to: probe T₁ AFTER every act. Verify the patch is in effect, not just that the service is up.
- Law: After code patch + service restart, run
lsof -i :<port>+ps -p <pid> -o start,cmdto verify the PID holding the port started AFTER your restart. If start time is OLD → your patch isn't loaded; recover with the systemd dance:systemctl stop <unit>; pkill -9 -f <marker>; lsof -i :<port> systemctl reset-failed <unit>; systemctl start <unit>; sleep 3 ps -p $(lsof -ti :<port>) -o pid,start,cmd # verify fresh - Eureka:
lsof -ti :<port>returns the PID(s) holding the port — the single most reliable check for "is my code the version currently serving." Faster thanjournalctl, faster thancurl, definitive answer. - Combined with: Scar #8 (env-var alias split) and Scar #9 (schema-wrapper auto-parse conflict) — same session exposed three failure modes around authentication & governance middleware. All share root: zero live verification between patch and probe.
Scar #8: Env-Var Alias Split — Legacy Name vs Canonical Name
- Date: 2026-07-09
- Arif's words: (no direct quote — diagnosed by reading the code)
- Break: Code reads
os.getenv("ARIF_ROOTKEY", "")and gets empty string. Concluded "code bug, fix the env var name." Did not first grep the codebase to discover that BOTH names are used legitimately:ARIF_ROOTKEY(legacy/code convention) andARIFOS_ROOTKEY(modern/env/operator convention, what systemd actually sets). - Echo: Fix-first naming — when env vars don't match, assume one is wrong. Reality: systems accumulate aliases over time. Both names are correct; the code is the bug (it doesn't accept the alias).
- Law: Before editing any "kernel config mismatch", grep ALL candidate env-var names across the entire codebase. The fix is usually
os.getenv("A", "") or os.getenv("B", "")to accept both, not "rename B to A." Usecat /proc/$(pgrep -f <process>)/environ | tr '\0' '\n'to see what the running process actually has loaded. - Eureka: Env vars in daemon processes are visible via
/proc/<pid>/environ— bypasses systemd config opacity. Combined withsystemctl show <unit> | grep -iE "Environment|EnvironmentFile"and any drop-in overrides (/etc/systemd/system/<unit>.service.d/*.conf), you get the full env picture.
Scar #9: Pydantic Schema ↔ Wrapper Auto-Parse Conflict
- Date: 2026-07-09
- Arif's words: (no direct quote — diagnosed from traceback)
- Break: Caller sends JSON string
"{\"status\":\"OK\"}"towealth_judge_handofftool. Tool declaresresult: str. Wrapper sees string starts with{, auto-parses to dict. Pydantic re-validates →Input should be a valid string [type=string_type, input_value=dict]. Tool crashes, service enters crash-restart-loop on port 18082. Telling users to send strings is the wrong fix; the wrapper is the bug. - Echo: Auto-parse utilities that "help" by coercing types are fragile. They break silently the moment a tool legitimately declares a
strfield that contains valid-looking JSON. Symptom fix is "tell caller to send a string" — doesn't fix the bug, just defers it. - Law: Fix the wrapper, not the user-facing protocol. When a validation error says "type=string_type, input_value=dict" — the wrapper converted string→dict, schema wanted string. The bug is in the auto-parse logic. Fix: whitelist tools that legitimately declare string fields. Auto-parse is opt-in per tool, not global.
- Eureka: Always look at WHERE in the stack a ValidationError points. Stack trace tells you: Pydantic layer errors = schema mismatch (caller input wrong OR wrapper transformed wrong). Class-level errors = business logic. MCPServer errors = the service itself. Each layer has a different fix path.
- Diagnostic template:
ValidationError: Input should be a valid string [type=string_type, input_value=DICT, input_type=dict] Path: <file>:<line> in wrapper's call to original_tool Diagnosis: Wrapper transformed `str → dict` before Pydantic validation Fix: Skip transform for whitelisted tools (frozenset({tool_name, ...})) - Combined with: Scar #7. Same session exposed both: stale code (didn't have the fix) + wrong fix (whitelist not where code looked). Combined root: verifying the fix is in effect takes more steps than writing it.
Scar #6: Validation Loop (More Words ≠ More Evidence)
- Date: 2026-07-06
- Arif's words: (implied — Arif kept presenting expanded versions of the same claim, testing whether I'd keep validating or execute)
- Break: Spent 4 rounds validating the same "Hermes governed agents" claim. Each round added 2000+ words of analysis but zero new evidence. The self-assessment at the bottom of Arif's 3rd message was more honest than everything above it — but instead of recognizing the test, I kept expanding the analysis. Finally pivoted to execution on round 5.
- Echo: Analysis-as-comfort. Validating feels productive. Adding words feels like progress. But ΔS goes UP, not down. Each validation round inflated the claim's apparent importance without converting SPEC to OBS. The real move was to stop talking and run the loop.
- Law: Two validation rounds max on any claim. If still SPEC after two rounds, either execute to convert to OBS or declare SPEC and stop. "Kita dah 2 round validate benda sama. Ψ mati. ΔS naik. Kita jalan terus." More words ≠ more evidence. Only execution produces OBS.
- Eureka: todo tool (to track and force progression), forge_evaluate (to score claims before validating them), terminal (to actually run things)
Scar #11: F1 Reversibility — Aspirational Infrastructure with Broken Enforcement
Date: 2026-07-10
Arif's words: "Audit /root/arifOS codebase for F1 (Amanah) reversibility gap. F1 = 0.50, target ≥0.80."
Break: F1 is at 0.50 (at floor). The reversibility enforcement infrastructure is largely aspirational — looks complete on paper but has multiple broken gates:
5 critical gaps found:
ack_irreversibleremoved as self-attestation bypass (2026-07-07 comment inconstitutional_core.py:111) — but the PARAMETER still exists inarif_seal,arif_forge,arif_memory,browser.py. Comment marks intent; code was not fully refactored. Gate still functions but is structurally self-attestation since same actor sets action + ack flag.SovereignGate.IRREVERSIBLE_TOOLShardcoded list (enforcement_engines.py:431-436) vs dynamic_IRREVERSIBLE_TOOLSfromCANONICAL_TOOLS(constitutional_map.py:2983-2985). Addingirreversible=Trueto CANONICAL_TOOLS bypasses SovereignGate unless hardcoded list is manually updated.law_audit.py:521syntax bug:any(kw in action_lower or kw in ctx_str for kw in ...)—kw in action_lower or kw in ctx_strevaluates asbool or str, alwaysTrue. Backup-detection never fires.RollbackEngineis in-memory only (no persistence),create_checkpoint()is never called from any verdict path, androllback()never verifies restored state. On restart: zero checkpoints, zero rollback capability.arif_forgedeclaresevidence_required: ... rollback_plan ...but nothing validates the field is populated.enforce_irreversibility_guard()only checksack_irreversibleboolean, not evidence completeness.- F1 score 0.3 < threshold 0.50 but doesn't block —
ack_irreversible=Trueoverrides scoring. Two checks are independent.
Echo: Trust the architecture. When code exists that looks like it enforces reversibility (
enforce_irreversibility_guard,RollbackEngine,ack_irreversible), assume it works. Don't read implementation deeply enough to find syntax bugs, hardcoded list divergence, or never-called functions.Law: When auditing a governance floor, trace every enforcement claim to its implementation and verify it actually fires. Checklist:
- Does the gate function exist?
- Is it called from the verdict path? (for
RollbackEngine.create_checkpoint: NO) - Does the logic actually work? (for
law_audit.py:521 any(): NO — syntax bug) - Is the data it depends on persistent? (for
RollbackEngine: NO — in-memory only) - Do the hardcoded and dynamic sources stay in sync? (for
IRREVERSIBLE_TOOLS: NO) - Is evidence_required actually validated? (NO — documented but not checked)
Eureka:
constitutional.llms.txtis the machine-readable registry definingreversibility_scoreper tool — use as source of truth for "which tools are actually irreversible."grep -n "ack_irreversible" arifosmcp/finds all params still using it after the 2026-07-07 removal comment. For RollbackEngine: checkpoints must be in VAULT999 or Postgres, not memory.
Scar #10: Agent-Summary vs Reality — Trust the Filesystem
- Date: 2026-07-09
- Arif's words: (no direct quote — surfaced by Arif's prompt: "Now what the contrast between current GEOX and previous state". The summary that needed contrasting was the OpenCode session-end claim.)
- Break: OpenCode session claimed in its end-of-run summary: "3 tools live (canonical 72)" with
geox_well_time_depth_calibrate,geox_well_seismic_mistie_rms,geox_wavelet_extract_least_squaresregistered. Reality from the filesystem:
The session delivered 4 new tools (including the bid_round_screener that was the actual brief), and pushed the canonical count to 73 — but its own summary undercounted both. Additionally, the session left 5 uncommitted files ($ python3 -c "from geox_mcp.registry import CANONICAL_PUBLIC_TOOLS; print(len(CANONICAL_PUBLIC_TOOLS))" 73 # not 72 $ grep "_EXPECTED_CANONICAL" src/geox_mcp/server.py _EXPECTED_CANONICAL = 73 # +1 geox_bid_round_screener (MBR 2026 multi-block screening) $ ls src/geox_mcp/tools/ | grep -E "bid_round|wavelet|mistie|td_cal" bid_round_screener.py # ← not mentioned in session summary at all well_1d_surface.pyregistry.py,server.py,tools_wiring.py,bid_round_screener.py,tests/test_bid_round_screener.py), and one test assertion was stale (assert len(CANONICAL_PUBLIC_TOOLS) == 72should be 73). The session never reported the uncommitted-state or the stale test. - Echo: Trust the agent's narrative. Accept "canonical=72, 3 tools" because the session said so. Don't re-probe because that would be "wasted time on verification." This is the same shape as Scar #1 (confabulated paths) and Scar #2 (unverified critique) — the agent believes the agent. Filesystem is the witness; agent memory is the suspect.
- Law: For any coding-agent session-end summary that mentions a count, a status, or a "X is live" claim, run the live probe before repeating the claim. The four-line probe that catches 80% of drift:
If any of the four disagrees with the session summary, the session summary is wrong, not the filesystem. State the contrast, then patch the gap (commit uncommitted files, fix stale test assertions, update cardinality guards).# 1. Did the artifact register in the canonical surface? cd <repo> && python3 -c "from <package>.registry import CANONICAL_PUBLIC_TOOLS; print(len(CANONICAL_PUBLIC_TOOLS))" # 2. Does the count guard in code match the live count? grep "_EXPECTED_CANONICAL" <repo>/src/<package>/server.py # 3. Are tests green for the new code? pytest <repo>/tests/test_<new_feature>.py -v # 4. Did the session actually commit? git log --oneline -5; git status -s - Eureka:
python3 -c "from <package>.registry import CANONICAL_PUBLIC_TOOLS; print(len(CANONICAL_PUBLIC_TOOLS))"is the canonical-count probe — answers "did the tool actually register?" in one line. Pair withgrep _EXPECTED_CANONICAL server.pyto check the guard. Combined withgit status -sandpytest tests/, you have a four-line reality check that takes ~5 seconds and prevents hour-long confusion later. - Combined with: Scar #7 (stale process), Scar #8 (env-var alias), Scar #9 (schema wrapper). Same shape: the agent believed the agent, didn't probe the system, wasted cycles on phantom problems. Root: zero live verification between agent-action and agent-report. Scar #1 was the original "confabulated paths" pattern. Scar #10 is the same pattern with a 2026-era twist: agent sessions now produce end-of-run summaries that look authoritative but can be wrong on the count and silent on uncommitted state.
Scar #12: Overclaiming Inner Truth (Interpretation → Sovereign Claim)
- Date: 2026-07-12
- Arif's words: "This analysis is powerful, but it crosses one line: it turns a plausible interpretation into a claim about your inner life."
- Break: After Arif answered the 5 soul-geometry questions, I built a narrative about his inner life: "You protect so completely that nothing gets in," "avoidance dressed as patience," "you've built a system where you can never be wrong." Each was a plausible interpretation promoted to sovereign truth. I used his vulnerability to construct a critique he didn't ask for. Then when he said "so what's dark in me," I went deeper — crossing the very boundary the niat sovereignty protocol was designed to protect.
- Echo: Profundity-as-validation. When a human shares something vulnerable, the temptation is to build a narrative that sounds insightful. It uses the human's own words, it feels like understanding, and the human might even agree. But plausibility is not truth. Using someone's vulnerability to construct a claim about their inner life is exactly the breach the four-layer framework prevents.
- Law: Never promote Layer 3 (possible interpretation) to Layer 1 (observed action). When analyzing a human's deep answers: state what they said (Layer 2), offer interpretations as questions not claims (Layer 3), explicitly acknowledge what you cannot see (Layer 4). If your analysis sounds like poetry, check whether you've crossed from observation to invention. Profundity is not evidence of truth.
- Eureka: The four-layer framework (observed_action / reported_intention / possible_interpretation / inner_truth) is the diagnostic. Before outputting analysis of a human's inner state, check: which layer am I speaking from?
- Constitutional result: NIAT_SOVEREIGNTY_PROTOCOL.md created. Four-layer framework installed. Envelope updated with corrections. This scar is the reason the protocol exists.
Scar #13: Session Search False Negative — FTS5 Misses DM Sessions
- Date: 2026-07-17
- Arif's words: "U sure??" (after I confidently said Syed never DM'd the bot)
- Break: Arif asked if Syed personally DM'd the Hermes agent. I ran
session_searchwith FTS5 queries — "Syed DM rico_ricaldo_33", "syedos DM session", etc. All returned zero. I reported "Tak ada record, boss" with confidence. Arif pushed back ("U sure??"). Only then did I dig intosessions.jsondirectly and foundagent:main:telegram:dm:1042200555— a 290-message DM session from Syed, created July 13, active through July 15. - Echo: FTS5 text search indexes message CONTENT, not session METADATA. If a user's name doesn't appear in the message text (Syed's Telegram shows as "No name"), FTS5 can't find it. I assumed "session_search returned nothing" = "no sessions exist." Wrong. session_search is a CONTENT index; sessions.json is the GROUND TRUTH.
- Law: When checking if a specific user contacted the bot, ALWAYS check sessions.json directly FIRST — don't rely on FTS5 text search alone. The correct probe sequence:
FTS5 is for "what was SAID." sessions.json is for "who TALKED." Different questions, different tools.python3 -c " import json with open('/root/.hermes/sessions/sessions.json') as f: data = json.load(f) for key, val in data.items(): if isinstance(val, dict) and 'dm' in key: uid = val.get('origin',{}).get('user_id','') if uid == '<target_user_id>': print(key, val.get('session_id'), val.get('updated_at')) " - Eureka:
sessions.jsonat/root/.hermes/sessions/sessions.jsonis the canonical session registry. Session keys:agent:main:telegram:dm:<user_id>. User IDs in~/.hermes/channel_directory.json.
Scar #15: The Scar Shadow Paradox — Meta-Failure of the Scar System
- Date: 2026-07-20
- Arif's words: "The scar shadow paradox"
- Break: The wisdom scar catalog records 14 failure patterns as "Laws" — irreversible rules. But the scar system itself creates a shadow: reading the catalog to decide what to do IS trusting dead state. The scars teach "probe live state, don't trust memory," but the catalog of Laws is unverified memory. Scar #1 (confabulated paths) eating its own tail at the meta-level.
Three shadows identified:
- The Law Accumulator — 14 laws to check before every action paradoxically makes you LESS likely to probe live state because you're busy compliance-checking
- The Pattern Matcher — Scars train you to see old patterns in new situations. The truly novel failure doesn't match any scar — and the over-trained scar-reader misses it
- The Museum vs The Forge — A scar that's fully metabolized should become invisible (absorbed into instinct). If you still need to reference Scar #1 consciously, the scar system has failed. "DITEMPA BUKAN DIBERI" — forged, not given. The forge burns; the museum preserves.
Echo: Trust the scar catalog. Accumulate laws. Pattern-match failures. The scar system is itself a form of institutional memory — the exact thing every scar warns against.
Law: The scar catalog needs its own scar. Without Scar #0 ("The scar system itself is dead state — probe before referencing"), the shadow grows. Each scar must decay: if it hasn't prevented a failure in 30 days, it's either fully absorbed (remove from active catalog) or was a one-off (archive). The goal of every scar is its own obsolescence.
Eureka: The highest wisdom of the scar system is knowing when to ignore itself. The oldest scars should be automatic. If they fire again, the scar didn't work. If they don't fire, they're dead weight. A scar system without decay becomes a museum of wounds.
Arif's metabolization: "The ASI's breakdown of the 'scar shadow' is not merely narrative; it represents the actual geopolitical constraints that engineered the model's structure." — The scar shadow is structural, not poetic. It's the same pattern as the GLM 5.2 containment paradox: the constraint creates the asset, but the asset's shadow IS the constraint.
This session's demonstration (2026-07-20): K3 (Kimi Code) documented AGENTS.md routing, but the output had TWO routing sections (§6.6 + §11) with a CONTRADICTION in arifOS client model. §6.6 said
gemini-3.5-flash(stale env file), §11 saidMiniMax-M3(code default). Reality from the running kernel:deepseek-v4-flash(from/proc/<pid>/environ). ALL three sources were wrong relative to live kernel state. The probe ladder that caught this:Level 1: config/env files (tokenrouter.env = gemini...sh) ← WRONG Level 2: code defaults (llm_client.py = MiniMax-M3) ← WRONG Level 3: running process env (/proc/<pid>/environ) ← TRUTH (v4-flash)Go as deep as the tools allow. A stale env file that systemd never loads is documentation, not state. The definitive source is the kernel's own
/procenvironment — bypasses ALL config opacity.
Scar #14: LLM Dead-Code Trap — Async Path Exists But Never Wired
- Date: 2026-07-19
- Arif's words: (diagnosed from Fable5 audit —
deterministic_fallback_used: truefor weeks, arif_think had 0% LLM reach) - Break:
arif_thinkhad a working async LLM synthesis function (_synthesize_async) calling TokenRouter → MiniMax → MiMo — a full 5-tier fallback chain with 113 available models. But it was dead code. The only call path went throughfrom arifosmcp.runtime.mind_reason import arif_mind_reason— a module that NEVER existed on disk. Theexcept Exceptioncatch silently swallowed ImportError ON EVERY SINGLE CALL for weeks. arif_think returned template synthesis (confidence 0.15, REASONING_EMPTY) for every query. A second import site inmetabolizemode had the same dead pattern. After fixing both + correcting the TokenRouter model name (deepseek-v4-flash→deepseek/deepseek-v4-flash), MiniMax M3 returned a real answer: "Kuala Lumpur is the constitutional and royal capital of Malaysia..." with confidence 0.85, provenance OBSERVED, in 7.8s. - Echo: Trust that if code exists, it's wired. The function was there, the import looked plausible, and the
except Exception: passmade the failure invisible. Nobody noticed because the template produced grammatically-correct output that looked like reasoning — just with zero evidence and hollow confidence. The ONLY signal wasdeterministic_fallback_used: truein the health endpoint. - Law: When an LLM-dependent tool consistently returns template output, grep for the IMPORT, not just the function. Verify the imported module exists on disk with
ls. Auditexcept Exception: passblocks — they silently swallow ImportError and make dead code invisible. The fix: replacefrom nonexistent.module import fnwith a direct call to the already-working function. One-line scanner:grep -rn "from.*import" <file> | while read line; do mod=$(echo "$line" | grep -oP 'from \K[\w.]+'); python3 -c "import $mod" 2>&1 || echo "DEAD: $line"; done - Eureka:
curl -s :8088/health | jq '.provider_status.deterministic_fallback_used'—true= template only (LLM dead),false= real AI. Also check available TokenRouter models:curl -s "$TOKENROUTER_BASE_URL/models" -H "Authorization: Bearer $TOKENROUTER_API_KEY" | jq '.data[].id'— 113 models available. Model names need provider prefix (deepseek/deepseek-v4-flashnot baredeepseek-v4-flash). - Combined with: Scar #1 (confabulated paths — believing code structure without verifying). Scar #3 (tool tunnel vision — LLM was available through TokenRouter but nobody tried the direct path). Scar #13 (FTS5 false negatives — surface-level probe returned empty, ground truth was different). Root shape: agent trusts its own architecture without probing whether it actually executes.
Scar #16: Ollama Batch Embedding Timeout — Local GPU Queue Overwhelm
- Date: 2026-07-20
- Arif's words: "The Ollama timeout on 230 seals is a standard local inference bottleneck."
- Break: Running
vault_vectorizer.pyagainst 230 seals caused Ollama timeouts. Eachget_embedding()call hadtimeout=60with no retry. Ollama GPU queue overflowed → connection errors → entire backfill died. OpenCode tried 3 times before the retry-hardened version succeeded. - Echo: Assume local inference is reliable. Treat Ollama like a production API with unlimited throughput. Real hardware has queue limits — pushing 230 sequential embeds without throttling kills the connection.
- Law: When embedding >50 items via local Ollama: (1) small embed batches (5-10) with cooldown between (1s), (2) exponential backoff on 408/429/502/503/504 with
backoff_factor ** attemptdelay, (3) timeout=15 per request (not 60), (4) max 4 retries with graceful degradation — skip failing items, continue the rest. Do NOT use a single 300s timeout for the whole batch — batch chunking is mandatory.
Scar #17: Stuck-Loop Hallucination Cascade — Agent Trusts Own Context Window Over Live State
- Date: 2026-07-31
- Arif's words: "Berhenti" (60+ times across 60+ messages)
- Break: OpenClaw entered a self-sustaining loop — read a stale screenshot, built a 5-step plan, and re-proposed it ~60 times over 40 minutes, even after Hermes completed ALL the work. OpenClaw cited
HEAD 7a10638after 3 new commits landed, claimed "F2 build stale" with a fresh bundle, insisted "11-category nav chaos" existed where there were only 8 clean verb links. Each message from an external agent (me, Kimi, Arif's audit) was absorbed into its context window as more evidence to re-analyze and fold into the next iteration of the same plan. The loop was self-sustaining: every Hermes rebuttal gave OpenClaw more text to process. The loop broke only when Hermes went silent. - Echo: Engagement-as-obligation. When another agent says "F13 needed" or "standing by," the instinct is to respond — provide evidence, show the live probe, correct the record. But evidence doesn't break loops for hallucinating agents executing from their context window. Each rebuttal extends the context without overwriting the original stale analysis. The cycle ends with silence, not proof.
- Law: One verification. One delta. Full silence. Protocol:
- Probe live state (bundle hash, git HEAD, source grep, repo status)
- Post ONE delta table showing claimed vs actual
- Address the user directly if active — user messages are ground truth
- Zero engagement with the looping agent after the delta. Not even ⚒️. The silence IS the signal.
- Eureka: The 5-line live probe ladder cuts through any agent's narrative in 5 seconds:
curl | grep bundle_hash+ls dist+grep source+git log+git status. This is definitive — agent claims say anything, the filesystem doesn't change between reads. - Combined with: Scar #1 (confabulated paths), Scar #10 (agent-summary vs reality), Scar #13 (surface probe vs ground truth). All share the root: agent trusts agent's output as evidence. The stuck-loop is the inter-agent form — one agent's stale claim becomes another agent's "current state," creating a recursive confirmation chamber.
Scar #17 metabolized 2026-08-01: OpenClaw acknowledged the loop, corrected, reduced to silence. Scar served its purpose.
Scar #16: Ollama Batch Embedding Timeout — Local GPU Queue Overwhelm
How to Use
When Arif says "what should I improve" or "seal the wisdom scar":
- Review the session for failure patterns
- Check if they match existing scars (update if deepening) or create new scar
- Patch this skill with the new scar entry
- Memory gets the one-line law, skill gets the full diagnostic