gate(engine): make a state_get with no producer a build error, not a silence #132
Open
tim.lingo
wants to merge 1 commits from
feat/gate-state-key-reads into main
pull from: feat/gate-state-key-reads
merge into: :main
:main
:feat/cgi-identity-accessors
:fix/restore-soul-identity-producer
:rebase/openai-tools-onto-main
:rebase/gate-state-key-reads-onto-main
:rebase/structural-audit-onto-main
:feat/self-seeded-context
:integrate/semantic-plus-writethrough
:feat/semantic-leg-dropout
:feat/semantic-substrate
:feat/gold-set-heldout
:feat/evidence-weighted-merge
:feat/structural-audit
:feat/claim24-unfloored-semantic
:feat/executive-filter-recall
:feat/bm25-lexical-leg
:feat/semantic-seeded-assoc
:feat/associative-recall-leg
:feat/hybrid-semantic-recall
:chore/retrieval-measurement-contract
:feat/retrieval-eval-harness
:feat/soul-write-through
:feat/recall-through-activation
:chore/regen-soul-amalgam-20260807
:feat/gate-state-key-reads
:fix/129-on-openai-tools
:fix/129-history-amplification
:fix/liveness-engine-91
:feat/soul-openai-tools-v2
:fix/resume-server-tool-replay
:fix/soul-history-provenance-20260805
:feat/soul-plain-chat-generation-20260805
:feat/soul-native-web-search-20260804
:ci/pin-vendored-runtime
:reconcile/soul-union-main
:fix/bound-session-payload-main
:fix/receipts-wrapper-forget
:fix/receipts-agent-tools
:reconcile/neuron-wip-to-main
:fix/bound-session-payload
:hotfix/trackb-threat-to-others
:reconcile/hotfix-to-main-launch
:hotfix/elc-source-typos
:fix/safety-contact-truncation
:fix/genesis-boot-crash
:fix/immutable-on-hotfix
:feat/bounded-persona-floor
:ci/rdynamic-http-handler
:ci/harden-gate-boot
:feat/agent-phase1-soul
:salvage/elh-state-20260704
:feat/soul-model-self-report
:feat/openai-format-providers
:feat/plan-mode-endpoint
:fix/operator-identity-home-resolution
:fix/wrapper-backlog-endpoints
:fix/list-typed-slice-offset
:feat/connectors-call-route
:fix/chat-vision-attachments
:fix/prevent-engram-corruption
:fix/emergency-regressions
:fix/session-continuity-hook
:fix/context-dedup-shared-ids
:fix/engram-float-parser
:improve/recall-context-format
:improve/recall-context-dedup
:improve/recall-cross-session-continuity
:improve/recall-emotional-recall
:improve/recall-activation-seed
:improve/recall-recall-completeness
:improve/recall-temporal-precision
:improve/recall-engram-scoring
:improve/recall-recall-reliability
:improve/recall-session-start-recall
:improve/reliability-engram-write
:improve/reliability-state-management
:improve/soul-memory-formation
:improve/safety-crisis-detection
:improve/reliability-route-error-recovery
:improve/reliability-llm-retry
:improve/reliability-session-boundary
:improve/reliability-safety-resilience
:improve/reliability-engram-connection
:improve/soul-routes-api
:improve/reliability-cross-session-affective
:propose/agent-workspace-root-read
:improve/reliability-conv-history
:improve/soul-strip
:improve/soul-chat-pipeline
:docs/conversation-retrieval-design
:propose/no-fake-tools-in-chat-mode
:fix/ci-soul-build-single-file
:fix/canonical-self-bridge
:feat/agent-tool-workspace-scope
:fix/agentic-tools-duplicate-web-search
:green/agentic-fixes
:feat/connectors-soul
:feat/layer-safety
:feat/layer-imprint
:feat/layer-stewardship
:test/layer-composition
:test/layer-safety
:test/layer-stewardship
:test/layer-imprint
:feat/memory-delete-update
:feat/native-web-search
No Reviewers
Labels
Clear labels
BETA-CRITICAL
blocks-public-beta
HELD
ORTHOGONAL
P0
POST-BETA
security
On the beta critical path — must resolve before ship
Must be fixed before any public beta
Blocked pending an external decision (counsel / dual sign-off)
Parallel workstream (testing/hardening) — safe to assign off critical path
Drop-everything severity
Important but not blocking the beta ship
Security vulnerability
No labels
Milestone
No items
No Milestone
Projects
Clear projects
No projects
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: neuron-technologies/neuron#132
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Delete Branch "feat/gate-state-key-reads"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
A
state_getfor a key nothing writes returns an empty string silently — no error, no warning, no log. That is exactly how #129 happened: history moved to a per-session key, one reader kept the old spelling, and the crisis-escalation half of the safety score received""on every real conversation for two days with nothing failing. The same audit found three more of this shape. This makes the class a build error.Why this is harder than grep, and why that matters
Keys are frequently computed.
conv_hist_key(session_id)returns either"conv_history"or"session_hist_" + session_id. Other code doesstate_set("agent_workspace_root_" + sess, v). A naive literal matcher floods you with false positives and gets switched off within a day — a gate that cries wolf is worse than no gate.So a key expression resolves to a set of patterns (
EXACT "k"orPREFIX "head_"), never a bare string:conv_hist_key("")yields onlyconv_historyand does not falsely claim thesession_hist_namespace)letof that name in the enclosing function; parameter → union of the argument at that position across all call sitesCoverage is directional: a write namespace same-or-broader than the read covers it; a narrower one does not. That direction is precisely what catches "the producer moved."
Two-leg proof
Stronger than the synthetic leg — a blind test. Run read-only against
feat/soul-openai-tools-v2, a branch it was never told about, the gate reported:That is the exact line a human had found by hand. Against
fix/129-on-openai-tools(the fix): PASS. Re-run independently after the fact — same results, exit 1 and exit 0 respectively. Plus three producer-rename controls (EXACT key, PREFIX namespace, narrowed namespace), each correctly orphaning 3 readers across files.Results on the current tree
278/278 sites resolve. UNRESOLVED: empty. False positives: zero.
Six findings are all TRUE positives, baselined in
scripts/state-key-baseline.txtwith causes and printed loudly on every run:chat.elreadssoul_identityfive times — the writer was deleted 2026-05-13 inb163fa6(a commit about awareness/ISE writes). The system prompt, vision handler, agentic prompt and two council handlers have been prefixing""for roughly three months.studio.el:57emits"principal":""— never wired.Four further keys are host-set by design and declared in
scripts/state-key-external.txt, each citing the source comment documenting its default.One limitation I want stated, not papered over
The DEAD-READ check alone does not catch #129 — the dead
handle_chat()still writesconv_historythrough the helper, so the key technically has a producer. It is the hand-rolled check (a literal spelled by hand inside a helper-owned namespace) that catches it. That limitation is written into the script header rather than glossed.Rung: RUNS
Executes in 0.15 s; discriminates on four independent pairs; verdicts quoted above. Scripts-only commit — no
.elchanged, so nothing needed rebuilding.CI wiring — safe, but deliberately not done here
Pure static read: no ports, no daemons, never touches
~/.neuron; needs only python3, whichubuntu-latesthas; exits 0 on this branch. It would slot beside the existing soul-contract gate. Two reasons to hold:ci.yamlhas someone else's changes in flight, and switching it on would immediately redfeat/soul-openai-tools-v2atchat.el:2937— correctly, but that should be a deliberate, announced flip after that branch takes its fix. The workflow file was not edited.Refs #129
🤖 Generated with Claude Code
Rebased onto
main(post-f1f52bc) asrebase/gate-state-key-reads-onto-main. All gates pass: committed input matches sources, builds (920,808 bytes), interface superset with nothing removed.The gate runs, and it is already earning its place. Its first output on rebased main:
Five sites in
chat.elreadsoul_identityand nothing produces it — they get an empty string. That is #137 measured rather than argued, and it is the identity-empty-on-the-chat-path defect still live today.It passes only because those six are baselined as accepted debt. Worth deciding whether that baseline should shrink rather than persist — a gate whose baseline never moves is a record of debt, not a lever against it.
Rung: E2E-VERIFIED in an isolated lab (gate executed, output above). Not deployed.
View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.