Agent consent: the pause contract + false-receipt kill (2 fixes, stricter only) #79
Open
tim.lingo
wants to merge 3 commits from
feat/agent-phase1-soul into main
pull from: feat/agent-phase1-soul
merge into: :main
:main
: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/neuron-dev-setup
:feat/immutable-engram-deletes
:feat/agent-phase1-soul
:salvage/elh-state-20260704
:hotfix/trackb-threat-to-others
: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
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/agent-phase1-soul"
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?
Rebased clean onto the regenerated main (zero conflicts). Two consent-flow fixes, both verified E2E on the clean test brain:
1. PAUSE CONTRACT — honor require_approval. The client has sent require_approval:true on every agentic request since Phase 1c, but needs_bridge never consulted it: builtin sub-escalate tools ran server-side unasked, making the app's Ask autonomy silently inert for that class. The flag is now persisted per session (so /approve resumes keep it) and ask_all bridges every tool turn. Absent/false = byte-identical legacy behavior. Proven: the probe that executed a write unasked now returns the pause envelope with nothing on disk; full in-app circle verified (card → crash → resurrection → late approve → fence re-fires).
2. BUG-6 — approved writes must land, and say where. Two compounding defects made every pause→approve write_file report success while writing nothing: (a) the naive json_get matched "content" inside tool_input, so approved builtin writes were treated as client-executed and skipped; (b) write_file returned ok unconditionally. Builtins now always dispatch server-side; write_file verifies fs_exists and returns the resolved path. Proven: approve-path write lands byte-exact; auto-run unchanged; deny executes nothing.
Also carried: per-session workspace-root isolation (BUG-LEAK) — sessions can no longer inherit another session's root via the shared state key; re-asserted on /approve and resume. Live proof pending a local rebuild (below).
Ask: local full-source rebuild now compiles all 49 modules (your elc OOM fix works — thank you) but links one symbol short: engram_get_node_by_label (+ friends) aren't in any el_runtime.c we have locally. Where does the current runtime C live? With it we can E2E the root-isolation fix locally too.
Deeper flag: the naive json scanner is a standing landmine (BUG-6 was one instance) — a nesting-aware reader would kill the class.
🤖 Generated with Claude Code
Two compounding defects made every pause->approve write_file report success while writing NOTHING: 1. The naive json_get scanner matches "content" anywhere in the approve body — including INSIDE tool_input, which for write_file always carries a content field. The handler therefore treated every approved builtin write as already-client-executed, skipped dispatch entirely, and handed the model the file's own content as the 'tool result'. The model then narrated 'Done, created' — a false receipt with no file. Builtin tools now ALWAYS dispatch server-side; client content is only honored for non-builtin (MCP/client-executed) tools. Stricter only. 2. write_file returned {"ok":true} unconditionally — fs_write's outcome was never checked, so any failed write also reported success. The write now verifies the file landed (fs_exists) and returns the RESOLVED path in the ok payload; failures return a real error naming the destination. E2E on the test brain (boot 38): approve-path write lands byte-exact and the result carries the resolved path; auto-run writes unchanged; denied writes execute nothing. BUG-5 (approve wire lacked tool_name) had been masking this one — two stacked bugs on the same path. NOTE for review: the deeper cure is a nesting-aware json reader; this fix removes the dangerous consequence at the two spots that lie about disk. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.