Procedural Memory: Compiling Fast Responses

For new readers

This page documents one component of the self-model reference implementation, a working PatLang system that models cognitive processes for study. Procedural Memory compiles repeated, trusted patterns into rules it can answer from directly — it does not "learn to like" anything or form habits in any subjective sense; it applies inductive synthesis to accumulated symbolic examples, gated by a numeric trust score.

What Procedural Memory does

Procedural Memory's required function, per the requirements specification's component table, is compiled fast-response rules, fed by (trust-gated, repeated) Short Term content and by Perception, producing a direct response candidate published to the shared queue. It uses the same inductive synthesis engine as Abstraction (Requirement 4.7), aimed at a different target: instead of building a general category, it compiles entity-to-intent rules and, once a category has already been compiled once, treats a further repeated occurrence as grounds to publish its own competing response candidate.

The fast path is a genuine competing draft, not a consultation

This is the component's most consequential design choice, stated directly in its own header comment: once an entity's intent has been compiled at least once above the trust threshold, Procedural Memory publishes a direct response candidate straight onto a Reason/Plan writer-topic — the same family of topics Action already reads across — rather than waiting to be asked. It competes for uptake exactly like a real Reason/Plan instance's own candidate would (Requirement 4.1's parallel-drafts model), so Action never needs to know about a separate "procedural candidates" topic on top of the ones it already reads. This is the "fast path": once a pattern is well established, the system does not have to wait on a fresh Reason/Plan evaluation to produce a candidate for something it has effectively already handled before.

Trust-gating compilation

Per Requirements Spec Section 5, Procedural Memory's updates from Short Term must be weighted by the interlocutor's trust score, computed via the project's distributed embedding calculus of trust (see lib/trust_calculus.patlang). Trust per interlocutor is a three-component vector — positive evidence, negative evidence, and uncertainty — rather than one scalar, because "no interaction history" and "a long history of exactly balanced good and bad outcomes" both net out near zero but call for different handling. The drift rule weights damage from negative evidence about three times as heavily as growth from positive evidence (tc_beta is 0.3 against tc_alpha's 0.1): trust is meant to build slowly and be damaged quickly. procedural_tick checks tc_score_for(interlocutor) against a fixed admission threshold of 0.15 before compiling anything — below threshold, the example is logged but rejected, never compiled.

This threshold exists specifically as a mitigation for a documented failure mode: unweighted compilation from repeated exposure is exploitable by coordinated adversarial input regardless of model sophistication, per the precedent of Microsoft's Tay (2016), cited directly in the requirements specification's Section 5.3. See the safety and ethics page for the fuller design rationale.

The bootstrap identity never fast-paths

A fully-trusted bootstrap identity (tc_bootstrap_interlocutor, starting at trust score 1 by construction) exists to let curated, pre-vetted examples establish baseline content before the system is exposed to open input (Requirements Spec Section 5.2). But the implementation's header describes a real bug this exact design choice was found to cause and had to specifically guard against: bootstrap's nine seed examples, three per category, produced six unwanted fast-path candidates on first attempt, and Action turned every one of them into real conversational output before any actual user had said anything. procedural_tick now checks interlocutor != tc_bootstrap_interlocutor() before ever calling procedural_publish_fast_path — bootstrap repetition is allowed to compile rules, but is never treated as a live conversational turn. The corresponding scenario in features/procedural_memory.feature makes this explicit: repeating a "greeting" category three times from the bootstrap identity compiles the rule (fast_response for "hi" eventually returns "greeting") but no fast-path candidate ever appears on the Reason/Plan writer-topic.

Freeze, checkpoint, and rollback

Procedural Memory exposes signals beyond the base lifecycle: freeze_compilation stops it from compiling new rules while still answering fast_response from whatever is already compiled (a direct implementation of a stated safety control — see features/procedural_memory.feature's freezing scenario, which shows a trusted percept being rejected purely because the component is frozen), and resume_compilation reverses that. checkpoint snapshots the current examples; rollback rewrites the persisted examples file and then calls component_request_stop() to restart the process, because PatLang's rule_add has no retract — a compiled rule already registered in the running process's fact store cannot be un-registered live, so rollback has to take effect via a fresh restart that replays examples from disk.

Instrumentation and lifecycle

Procedural Memory composes the same lib/component_base.patlang / lib/instrumentation.patlang pair every component in this project uses, claiming a port and announcing via component_start. Its status reply adds a compiled_rules count and reports state as "frozen" when compilation is paused, on top of the shared snapshot format.

See also

Procedural Memory reads from Short Term, the same source feeding Episodic Memory and Abstraction, and publishes competing candidates onto Reason/Plan's writer-topics. See safety and ethics for the full trust-calculus rationale and the architecture overview for how the fast path fits into the wider parallel-drafts model.