core/docs/analysis/afferent-field-ingest-scope-2026-06-15.md
Shay efd280d45f
feat(l10): autonomous idle frontier-contemplation — the always-on life learns on its own (#758)
* feat(l10): autonomous idle frontier-contemplation — the always-on life learns on its own

Frontier survey move #2, path (c): give the always-on idle life a stream of experience via
SYMBOLIC intake (not the afferent→field seam, which is deferred pending a commensurability
ruling — docs/analysis/afferent-field-ingest-scope-2026-06-15.md). The idle heartbeat
converges (idle_tick drains a finite backlog + saturates is-a closure, then does nothing
forever); this makes it autonomously MINE its frontier with no user turn.

Reuse-heavy (the mechanism largely existed): a gated idle pass wires ADR-0080 contemplation
into the always-on loop.

- core/config.py: contemplate_frontier_during_idle (default off → no behavior change).
- chat/runtime.py: idle_tick pass 2b — when on, runs core.contemplation.run_contemplation()
  (mines the checked-in frontier-compare reports) and persists a reviewable ContemplationRun
  to <engine_state>/contemplation_runs/idle_<substrate_hash>.json. IDEMPOTENT per frontier
  (an already-mined frontier is not re-persisted → the life converges, no churn) and MEMOIZED
  per session (the static frontier is mined once, not re-read every beat). SPECULATIVE-only
  (ADR-0080: ContemplationFinding.__post_init__ RAISES if not SPECULATIVE → wrong=0 by
  construction; never ratified here — the HITL path is untouched). IdleTickResult gains
  frontier_findings.
- chat/always_on.py: run_continuous did_work + HeartbeatRecord count frontier work, so the
  heartbeat/soak convergence (H3) stays honest.
- core/cli.py: `core always-on --contemplate-frontier` (explicit learning-daemon mode) +
  honest per-beat log ("+N findings").

Adversarial 3-lens review (wrong=0/convergence, determinism/trust-boundary, test-vacuity)
found 7; fixed the real ones: the MEDIUM torn-write (write_contemplation_run is now atomic
temp+os.replace — the indefinite-uptime daemon expects SIGKILL mid-write, and the skip-guard
would never repair a torn canonical file), the gitignore breadth (contemplation_runs/ at any
engine-state root), the 64-bit filename truncation (full substrate_hash), and the
re-mine-every-beat cost (session memoization). Deferred + documented: the shared
contemplation miner embeds absolute report paths in finding CONTENT — a portability wrinkle
that does NOT affect wrong=0/convergence/soak determinism (those key on the content-only
substrate_hash) and touches shared code + its test surface; a follow-up.

Tests (non-vacuous): 7 — off-by-default (no behavior change), mines-when-enabled,
findings-SPECULATIVE (wrong=0), converges-idempotent, heartbeat-mines-then-converges,
mines-once-per-session (memoization), atomic-no-orphan. 55 idle/contemplation/always-on +
96 invariants/contemplation + 28 smoke green; `core always-on --contemplate-frontier` mines
end-to-end. engine_state contemplation_runs are per-life runtime state (gitignored).

* fix(l10): isolate idle frontier pass + persist frontier_findings (#758)

Three review blockers on the autonomous idle frontier-contemplation pass:

1. Daemon isolation. idle_tick's pass 2b called run_contemplation /
   write_contemplation_run bare inside the always-on loop (run_continuous
   wraps idle_tick in nothing but an exit-checkpoint finally), so a malformed
   frontier report or a transient FS fault would propagate out and KILL the
   continuous life. Wrap the optional pass best-effort (the exit-checkpoint
   boundary idiom): degrade to 0 findings + RuntimeWarning, leave did_work
   untouched, let a later beat retry.

2. Durable did_work explanation. HeartbeatRecord carried frontier_findings
   but serialize_report omitted it and AlwaysOnReport had no run total, so
   lived_life.json could show did_work=true with facts=0/proposals=0 and no
   persisted cause. Persist frontier_findings per-record + total_frontier_findings.

3. Honest HITL claim. The docstring/CLI/config said findings are "reviewable
   via the HITL path", but the existing HITL queue + workbench reader scan
   <repo>/contemplation/runs while the pass writes <engine_state>/contemplation_runs/.
   Narrow the claim to "persisted reviewable artifact, not yet in the HITL
   queue" (wiring that discovery is a follow-up).

Tests: 4 new non-vacuous regressions (mining-failure degrade, write-failure
degrade, always-on loop survives frontier failure, lived_life persists
frontier_findings) — all fail against the unpatched pass. 38 L10/always-on/
workbench tests green.
2026-06-14 23:59:49 -07:00

6.4 KiB
Raw Blame History

Afferent → Field Ingest Seam — Scope & Decision Brief

Status: scope (decision-gated; field-touching, CLAUDE.md sanctioned-site implication) · Context: frontier survey move #2, after the always-on process (#747/#748/#752) + its long-horizon soak (#757) closed the idle lived-spine. This is the proposed next edge: give the always-on life a stream of experience by folding compiled afferent observations into the live cognitive field.

The gap it would close

The always-on heartbeat lives, holds closure, and resumes — but it is a continuously idling life: idle_tick drains a finite backlog + saturates deductive closure, then does no work forever (proven by the convergence gate H3 in evals/l10_always_on). There is no afferent input channel into the idle loop. Separately, the sensorium is fully built as a compiler/frame/merge substrate but is never wired to the field — ADR-0208's own pipeline arrow (ObservationFrame → … → field / recall / cognition) stops at the merge. This seam is the missing edge in listen → comprehend → … → replay.

What is confirmed (geometric feasibility)

  • Units carry a field-shaped target. CompilationUnitLike (sensorium/compiler/protocol.py:28) exposes versor: np.ndarray — a real CL(4,1) multivector — alongside versor_condition. A live ObservationFrame's units therefore expose targets in the field's algebra.
  • The sanctioned pull pattern applies directly, closure-preserving BY CONSTRUCTION. The exemplar is session/context.py::_session_anchor_pull:
    R       = word_transition_rotor(field_state.F, target)   # rotor toward target
    R_step  = rotor_power(R, α)                               # fractional, stays on Spin manifold
    pulled  = versor_apply(R_step, field_state.F)             # apply — no post-hoc unitize
    
    It explicitly replaced the rejected _slerp_toward (which broke closure and needed a forbidden post-hoc unitize_versor). An afferent pull toward unit.versor is structurally identical → preserves versor_condition < 1e-6 by construction, adds no normalization site.
  • Home: session/context.py (the already-sanctioned site that owns the field), a new opt-in observe(frame) that pulls the field toward each unit's versor by a fractional step. Default off → serving + existing behavior byte-unchanged.

The load-bearing wrinkle (the decision)

Closure-preservation is necessary but NOT sufficient. The sanctioned anchor-pull moves the field toward a session concept-attractor — a target in the cognitive semantic frame, carrying meaning ("the field anchors toward the session's concept"). An afferent unit's versor is in the same algebra (CL(4,1)) but:

Is the sensorium's CGA embedding semantically COMMENSURABLE with the cognitive field — or merely same-algebra, different meaning?

  • If commensurable: pulling the field toward unit.versor is genuine perception → cognitive state (decoding doctrine: the observation is real, the field moves toward it). The seam is clean and meaningful.
  • If not (same algebra, unrelated embedding): the pull is geometrically valid but semantically empty — the field drifts toward an arbitrary point. That is exactly the degenerate fit the field-as-standing-hand doctrine forbids ("geometrically-realizable structure only; never force a degenerate fit").

This question is unestablished in the code: the sensorium compiles units into CL(4,1) but nothing today asserts that embedding shares the cognitive field's semantic frame (they were built as disjoint tracks — CLAUDE.md: the afferent arc "is disjoint from the GSM8K serving path"). Wiring afferent → field is the first connection of the two.

Decisions for ratification (Shay reviews the design)

  1. Commensurability ruling (the crux). Is the sensorium CGA embedding intended to be commensurable with the cognitive field? Three honest paths:

    • (a) Commensurable by construction — if the modality packs project into the same concept manifold the cognition field uses, the pull is meaningful → build the seam. (Needs: evidence/assertion that the projection shares the frame, e.g. a shared concept-attractor basis, before any pull is wired.)
    • (b) Bridge required — define an explicit, falsifiable map from a unit's versor to a cognitive-field target (a grounded embedding), so the pull is toward a meant point. Larger; an ADR + a commensurability gate.
    • (c) Not yet — keep the tracks disjoint; the always-on life stays idle-converging for now; the stream-of-experience comes from a different intake (the autonomous determination-frontier — roadmap Step 5 — which feeds symbolic new questions, not afferent versors). Lower geometric risk, advances the telos via comprehension.
  2. Sanctioned-site clause. If (a)/(b): extend session/context.py's CLAUDE.md clause to cover afferent-observation pull (closure-preserving by construction AND semantic = perception→field), with the same bright-line justification. A CLAUDE.md amendment.

  3. ADR. Completing ADR-0208's arrow (ObservationFrame → field) is the first afferent→cognitive-core connection; it likely warrants an ADR (extend 0208 or new), given the tracks were deliberately disjoint.

  4. Falsifiable gate (regardless of path). Any pull that "preserves closure" is only proven if a test fails when it doesn't: a soak guard (sibling to evals/l10_always_on) asserting (i) versor_condition < 1e-6 every observed beat, (ii) the same frame sequence → byte-identical field digest (determinism), (iii) a commensurability assertion — the field moves toward the observation (dist(F, target) decreases), not arbitrarily.

Recommendation

The geometry is clean; the semantics are the gate. Recommend ruling on decision 1 first — do not wire a field pull until the commensurability question is answered, or the seam risks a closure-valid-but-meaningless fit. If commensurability isn't yet established (likely), the higher-leverage telos move is path (c): the autonomous determination-frontier intake (feed the idle heartbeat symbolic new questions it can determine + commit wrong=0 / propose HITL) — which needs no field-embedding ruling and directly converts the idle life into a learning one. The afferent→field seam then follows once the embedding frame is established.