01826421c4
Will waived diff review -> build it for real. Add engram_boundary_beat() to the runtime (afferent counter++ + engram_chrono_tick + engram_strengthen(self-anchor) + dharma_emit) and two act-stats counters (aff_boundary_ops, dharma_emits). codegen cg_fn injects ONE engram_boundary_beat(op) at the entry of every @manager/@accessor fn (fn_has_decorator, so it fires under @route @manager too) — a decorated op self-reports with ZERO hand-written instrumentation. Rebuilt elc self-host + the cognition engram in the worktree; ran it as the clone daemon on :8900. Proof (/api/boundary-proof, @manager, empty body, 5x): aff_boundary_ops 0->5, dharma_emits 0->5, self activation_count 1510->1513, chrono stamp advanced. Brought in feat/cognitive-architecture engram runtime+server for the build. strengthen = activation bump (not content/edge write) -> identity protection intact. Live :8742 untouched; no push, no cutover.
217 lines
15 KiB
C
217 lines
15 KiB
C
/* engram_cognition.h — THE ONE OPERATION.
|
||
*
|
||
* The buildable form of the "cognition is one operation" theory (design doc
|
||
* engram/spec/cognitive-architecture.design.md; memory bdc8a488 / d582a766).
|
||
*
|
||
* Cognition is ONE operation — think — a directed traversal-READ of the geometry
|
||
* from an anchor, steered by a learned STANCE, whose output is a GRADIENT (a
|
||
* direction + spread over the geometry), never a point. The named faculties
|
||
* (reason / induce / abduce / analogy / relate / plan / ground) are human LABELS
|
||
* on regions of think's steering space: each faculty == { think + a named stance }.
|
||
* Collapse-to-a-point happens only at EXPRESSION (a separate faculty), never in think.
|
||
*
|
||
* NAMING (Will's directive): the surface verbs name the cognitive ACT being
|
||
* performed (think / reason / induce / ground / verify), not the internal function
|
||
* shape. The single frozen primitive underneath every faculty is engram_think,
|
||
* which composes over engram_reason_point_fit + the §5 geo-algebra. Those never
|
||
* learn. Only the STANCE learns.
|
||
*
|
||
* "Stance" is the theory's steering PRIOR, deliberately named distinctly: in this
|
||
* codebase the token "prior" already means previous-VERSION (supersession). A
|
||
* Stance is a learnable bias/disposition over the geometry — which axes matter,
|
||
* which way pays off, plus a calibrated track record — attached to a faculty-label
|
||
* and a region, and grounded-for-whom.
|
||
*
|
||
* PURE + (mostly) READ-ONLY, stdlib + libm only. think() and the warp are pure
|
||
* over their inputs. Persistence (Stance <-> StoreNode, grounded-by edges) is the
|
||
* only part that touches the store, and it is additive / supersede / tombstone —
|
||
* never mutate-in-place, never delete. It NEVER touches the live daemon: all
|
||
* offline against a scratch store, per the design's rails.
|
||
*/
|
||
#ifndef ENGRAM_COGNITION_H
|
||
#define ENGRAM_COGNITION_H
|
||
|
||
#include <stdint.h>
|
||
#include <stddef.h>
|
||
#include "engram_geometry.h"
|
||
#include "engram_reason.h"
|
||
#include "engram_store.h"
|
||
|
||
/* Max principal axes a stance warps (matches GeoParams.top_axes default budget). */
|
||
#define COG_MAX_AXES 32
|
||
|
||
/* ═══════════════════════════════════════════════════════════════════════════
|
||
* §1 GeoGradient — the OUTPUT of think. A direction + spread over the geometry,
|
||
* plus the calibrated confidence and the read it was computed against. NOT a point.
|
||
* A spiked gradient (spread→0) = "exact" (deduction); a spread gradient = "fuzzy"
|
||
* (prediction). The gradient is ALSO the next steering direction (closed-loop flow).
|
||
* ═══════════════════════════════════════════════════════════════════════════ */
|
||
typedef struct {
|
||
int dim;
|
||
float* direction; /* unit steering vector in the anchor's frame (owned) */
|
||
double spread; /* 0 = spiked/exact ... large = diffuse/fuzzy */
|
||
double confidence; /* calibrated, from the stance's track record (reliab.) */
|
||
double magnitude; /* THIS read's own membership/fit estimate ∈(0,1].
|
||
* The scalar an expression faculty would SAMPLE; kept
|
||
* on the gradient but never used AS a decision by think.*/
|
||
const char* anchor_id; /* borrowed: the vantage this was read from */
|
||
int n_support; /* neighborhood members that shaped the read */
|
||
const char* stance_id; /* borrowed: which stance steered this (provenance) */
|
||
} GeoGradient;
|
||
|
||
void engram_gradient_free(GeoGradient* g);
|
||
|
||
/* ═══════════════════════════════════════════════════════════════════════════
|
||
* §2 Stance — the learnable steering prior, as a first-class object. In memory
|
||
* here; persisted as a StoreNode (node_type "Stance") via cog_stance_*serialize.
|
||
*
|
||
* warp: axis_gain[] per-principal-axis multiplier on extents (which axes
|
||
* matter — gain>1 WIDENS an axis so it penalizes less);
|
||
* bias_dir[] a steering-direction seed in the region's frame;
|
||
* scalars faculty constants this stance overrides (ext_floor, etc).
|
||
* calibration: the track record — the ONLY thing the loop (§4) updates
|
||
* besides warp: n_trials, a Brier accumulator, reliability
|
||
* (→ GeoGradient.confidence), and an EMA error.
|
||
* keystone: if set, the correspondence-loop MUST NEVER write warp or
|
||
* calibration — read-mostly (self / values). §6 metastability.
|
||
* ═══════════════════════════════════════════════════════════════════════════ */
|
||
typedef struct {
|
||
char* id; /* stance node id (owned) */
|
||
char* faculty; /* the act this stance serves: "induce"|"relate"|... */
|
||
char* anchor_region; /* node/neighborhood id this stance is attached to */
|
||
char* for_whom; /* observer id — grounding is relational (NULL=global) */
|
||
int keystone; /* 1 = read-mostly, loop never writes it (§6) */
|
||
|
||
int dim; /* embedding dim of the region */
|
||
int n_axes; /* how many axis_gain entries are live (<= COG_MAX_AXES)*/
|
||
double axis_gain[COG_MAX_AXES]; /* per-axis extent multipliers (init 1.0) */
|
||
float* bias_dir; /* dim floats, steering seed (owned; NULL = none) */
|
||
double ext_floor; /* faculty scalar: the extent floor (init 1.0) */
|
||
double drop_frac; /* faculty scalar (causal): confound drop (init 0.5) */
|
||
double assoc_floor; /* faculty scalar (causal): assoc floor (init 0.2) */
|
||
|
||
/* calibration / track record */
|
||
int64_t n_trials;
|
||
double brier_sum; /* Σ (p − y)² */
|
||
double reliability; /* calibrated ∈[0,1] → GeoGradient.confidence */
|
||
double ema_error; /* EMA of per-trial error */
|
||
double last_error;
|
||
} CogStance;
|
||
|
||
/* Initialize a neutral stance (all gains 1.0, default scalars, reliability 0.5).
|
||
* dim/n_axes taken from the region descriptor. faculty/id/for_whom are copied. */
|
||
int cog_stance_init(CogStance* s, const char* id, const char* faculty,
|
||
const char* anchor_region, const char* for_whom,
|
||
const GeoDescriptor* region);
|
||
void cog_stance_free(CogStance* s);
|
||
|
||
/* A stance set to today's hard-coded constants == behavioral parity with the
|
||
* pre-stance operators (axis_gain all 1.0, ext_floor default, drop_frac 0.5,
|
||
* assoc_floor 0.2). This is the FROZEN CONTROL used by the validation. */
|
||
void cog_stance_set_frozen_defaults(CogStance* s);
|
||
|
||
/* ── Serialization: Stance <-> StoreNode (compact line schema "STNC1", mirroring
|
||
* the reify "GEO1" precedent). Additive; the node's importance field caches the
|
||
* reliability readout. Round-trips exactly (reboot-prove). ──────────────────── */
|
||
char* cog_stance_to_metadata(const CogStance* s); /* owned string */
|
||
int cog_stance_to_node(const CogStance* s, StoreNode* out);/* fills a StoreNode */
|
||
int cog_stance_from_node(const StoreNode* n, CogStance* out);/* parse STNC1 */
|
||
|
||
#define COG_STANCE_NODE_TYPE "Stance"
|
||
#define COG_STANCE_META_MAGIC "STNC1"
|
||
|
||
/* ═══════════════════════════════════════════════════════════════════════════
|
||
* §1.2 think — the ONE operation. Frozen procedure over three steps:
|
||
* 1. re-origin on the anchor point (the vantage; the manifold is the read
|
||
* neighborhood, passed as `region`);
|
||
* 2. fit the anchor under the stance's WARP (engram_reason_point_fit with the
|
||
* axis extents multiplied by axis_gain and ext_floor substituted);
|
||
* 3. emit a GRADIENT: direction = the warped steepest-descent that reduces the
|
||
* fit distance (the "which way pays off" seed + bias_dir), spread from the
|
||
* fit distance, confidence from the stance's reliability, magnitude = the
|
||
* read's membership estimate. NO point-collapse — that is expression.
|
||
*
|
||
* `region` — the read neighborhood (built by vantage_read / geometry descriptor).
|
||
* `anchor` — the point to read FROM (dim floats). NULL = region centroid (self).
|
||
* `stance` — the steering prior. NULL = neutral (frozen defaults) => parity.
|
||
* Returns 0 and fills `out` (engram_gradient_free), <0 on error.
|
||
* ═══════════════════════════════════════════════════════════════════════════ */
|
||
int engram_think(const GeoDescriptor* region, const float* anchor,
|
||
const CogStance* stance, GeoGradient* out);
|
||
|
||
/* The warped fit itself (step 2), exposed for the loop + verifier reuse. Identical
|
||
* to engram_reason_point_fit when stance==NULL or all gains==1 && ext_floor default. */
|
||
int cog_warped_fit(const GeoDescriptor* region, const float* x,
|
||
const CogStance* stance, GeoFit* out);
|
||
|
||
/* EXPRESSION — the ONLY place a gradient collapses to a point. Samples the gradient
|
||
* off the anchor along its steering direction, scaled by (1 − spread) so a spiked
|
||
* (confident) gradient lands a definite point and a diffuse one barely moves.
|
||
* This is deliberately a SEPARATE faculty from think (§1.2, M5). */
|
||
int engram_express(const GeoGradient* g, const float* anchor, float* out_point);
|
||
|
||
/* ═══════════════════════════════════════════════════════════════════════════
|
||
* §5 HOLD vs GROUND vs ASSERT. Holding is unconditional (the store gates nothing).
|
||
* Grounding is a RELATION — a "grounded-by" edge, probabilistic, grounded-for-whom.
|
||
* The honesty floor is checked only at ASSERTION.
|
||
* ═══════════════════════════════════════════════════════════════════════════ */
|
||
#define COG_GROUNDED_BY_RELATION "grounded-by"
|
||
#define COG_SALIENT_TO_RELATION "salient-to"
|
||
|
||
/* Write a grounded-by edge (additive). weight = grounding ∈(0,1] from the verifier;
|
||
* for_whom recorded in edge metadata (grounding is relational). Never a node flag. */
|
||
int cog_ground_edge(EngramPagedStore* s, const char* claim_id,
|
||
const char* evidence_id, double grounding, const char* for_whom);
|
||
|
||
/* Write/refresh a salient-to edge: salience is RELATIONAL (grounded-for-whom),
|
||
* carried on the edge to the observer — not baked into the node scalar (§2.1). */
|
||
int cog_salient_edge(EngramPagedStore* s, const char* node_id,
|
||
const char* observer_id, double salience);
|
||
|
||
/* The honesty floor — a QUERY at assertion time, NOT a schema constraint. Reads the
|
||
* claim's stored grounded-by edges (for the given observer) and returns:
|
||
* 1 = may assert (best grounding >= floor),
|
||
* 0 = REFUSE assertion (holds unconditionally; only asserting is gated),
|
||
* <0 = error. The content remains held either way. */
|
||
int cog_assert_gate(EngramPagedStore* s, const char* claim_id,
|
||
const char* for_whom, double floor);
|
||
|
||
/* ═══════════════════════════════════════════════════════════════════════════
|
||
* §4 THE REFLEXIVE CORRESPONDENCE-LOOP — the learning engine. think scores its
|
||
* OWN gradient against outcome, refines the stance on the error, and (optionally)
|
||
* writes the (gradient, outcome, error) back as self-describing geometry. This is
|
||
* the dormant verifier turned INWARD.
|
||
*
|
||
* grade(1) SELF-CONSISTENCY (no external world-labels): the outcome is what the
|
||
* geometry itself says — the membership determined by the region's SIGNAL subspace
|
||
* (the axes reality actually weights). The stance's cheap warped read is graded
|
||
* against that geometric truth; error refines the warp so the read corresponds.
|
||
* ═══════════════════════════════════════════════════════════════════════════ */
|
||
typedef struct {
|
||
double correspondence; /* ∈[0,1]: 1 − |p − y| for this trial */
|
||
double error; /* 1 − correspondence */
|
||
double brier; /* running mean (p − y)² across the stance's trials */
|
||
double reliability; /* the stance's current calibrated reliability */
|
||
int wrote_keystone; /* 1 iff a keystone update was BLOCKED (safety audit) */
|
||
} CogBeatResult;
|
||
|
||
/* One correspondence beat for ONE trial:
|
||
* think(region, anchor, stance) -> gradient (a PREDICTION, ungrounded)
|
||
* outcome y := grade-1 self-consistency target (in [0,1])
|
||
* error = |magnitude − y|; refine stance.warp + calibration on the error
|
||
* (bounded step; NEVER writes a keystone stance)
|
||
* `learn`==0 grades WITHOUT updating (the frozen-control path). `max_step` bounds
|
||
* the per-beat warp change (metastability; §6). Returns 0 / <0. */
|
||
int engram_correspondence_beat(const GeoDescriptor* region, const float* anchor,
|
||
double outcome_y, CogStance* stance,
|
||
int learn, double max_step, CogBeatResult* out);
|
||
|
||
/* ═══════════════════════════════════════════════════════════════════════════
|
||
* §6 METASTABILITY. Keystones (self/values) are read-mostly: the loop reads but
|
||
* never writes them. Mark by stance flag or by a keystone-id set the loop consults.
|
||
* ═══════════════════════════════════════════════════════════════════════════ */
|
||
typedef struct { const char** ids; int n; } CogKeystoneSet;
|
||
int cog_is_keystone(const CogKeystoneSet* ks, const CogStance* s);
|
||
|
||
#endif /* ENGRAM_COGNITION_H */
|