Skip to content

T5 · CognitiveLoop + two-clock scheduler (one-shot & cyclic) + afferent ingestion #548

Description

@wow-miley

Context. The cortex. Per recon (#543): CognitiveRelay is LLM-config routing only — the LLM entry point is AgentLLMService (which consults the relay internally); motor never routes through the relay. Bus is EventSerialBus; afferent return arrives as the new AfferentSignal : Event family; the per-MotorArc envelope is a Motor-kind EmissionEvent.Produced.

Objective. CognitiveLoop (deliberative) + ReflexiveScheduler (reflexive, two modes); fold afferent feedback into the next cycle. Two clocks: deliberative selects what; reflexive replays how, locally, never re-entering deliberation.

Changes (:ampere-motor)

class CognitiveLoop(bus: EventSerialBus, llm: AgentLLMService, motorArcService, reflexive: ReflexiveScheduler) {
    fun start(scope)   // subscribe (via AgentEventApi) to perception + AfferentSignal events
    // PROPEL(Perceive, Recall, Observe, Plan, Execute, Learn): deliberation may invoke the LLM
    //   via AgentLLMService (NOT CognitiveRelay directly) -> select/synthesize MotorArc -> reflexive.enqueue(motorArc.resolve())
}
class ReflexiveScheduler(registry: LoadRegistry, eventApi: AgentEventApi, tickHz: Int = 90) {
    fun enqueue(t: MotorTrajectory)   // one-shot
    fun drive(c: Cycle)               // cyclic: PhaseClock advances φ (wrapping) at c.frequencyHz; amplitude live-modulatable
    // On replay start: publish ONE Motor-kind EmissionEvent.Produced (envelope) via AgentEventApi.
    // Per tick: build a MotorFrame, dispatch IN-PROCESS via registry.dispatch(frame) — NOT on the bus.
    // PhaseClock lives HERE (runtime), NOT in ampere-core. INVARIANT: no LLM/relay call inside the tick loop.
}

Interpolation applies Easing. Low-confidence deliberation escalates via the existing CHI path — the askHuman DSL → HumanInteractionEvent (already an EmissionEvent; do NOT wire a new parallel escalation path) — stubbed here (log + escalate flag).

Validation

One perception event → exactly one MotorArc enqueued; one-shot replay emits a single envelope + in-process MotorFrames at ~tickHz (monotonic seq, count matches duration); zero LLM/relay calls during replay; jitter under threshold; a Cycle via drive() wraps and is amplitude-modulatable mid-run; entering a gait by easing amplitude 0→1 (no teleport); an injected AfferentSignal changes the next emission.

Definition of Done — un-enforced by CI (recon §8)

Any new Event types: EventRegistry.allEventTypes entry + @SerialName/EVENT_TYPE + CLI display handler + concept cell + ./gradlew jvmTest/ktlintFormat.

Out of scope

Real MotorArc-selection intelligence (a canned policy is fine); perception model; capture.

Scope ~5 pts · Model: Sonnet, high thinking.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status
    Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions