Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .github/workflows/residual-constraint-graph-v1.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: Residual Constraint Graph V1
on:
pull_request:
branches: [agent/v121-cache-batch2]
paths:
- 'research/residual_constraint_graph/**'
- '.github/workflows/residual-constraint-graph-v1.yml'
workflow_dispatch:

jobs:
self-test:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- run: python research/residual_constraint_graph/rcg_v1.py
16 changes: 16 additions & 0 deletions research/residual_constraint_graph/RCG_SCHEMA_V1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"schema": "RCG_SCHEMA_V1",
"residual": {
"required": ["id", "world", "observation", "verifier", "status", "constraints", "provenance"],
"status": ["unresolved", "closed", "infrastructure", "superseded"],
"constraint_kinds": ["layer", "scope", "phenotype", "invariant", "causal_status", "eliminated_family", "required_property"]
},
"latent_obstruction": {
"required": ["constraint_conjunction", "covered_residuals", "minimality_witness", "closure_novelty", "predicted_operator_family", "status"],
"status": ["provisional", "intervention_supported", "ablation_supported", "transfer_supported", "refuted"]
},
"operator": {
"required": ["id", "properties", "preserved_invariants", "cost_assumptions", "closure_identity", "verification"]
},
"developmental_novelty": "An operator is novel iff it satisfies a verifier-supported constraint intersection not satisfied by any operator in the current closure-equivalence class."
}
107 changes: 107 additions & 0 deletions research/residual_constraint_graph/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# Residual Constraint Graph (RCG) v1

## Thesis

Verified failures are not primarily records to retrieve. Each residual induces constraints on admissible future representations and operators. Multiple residual views can therefore be intersected to infer the smallest latent obstruction that explains them jointly.

The developmental inference loop is:

`world -> residual -> multi-typing -> constraint closure -> latent obstruction -> missing distinction -> operator family -> verified intervention -> new residual geometry`

## Objects

### Residual
A verifier-visible discrepancy or cost whose provenance is fixed.

Each residual carries typed views rather than one flat label:

- layer: representation / identity / routing / capacity / soundness / benchmark / infrastructure / semantics
- scope: local / family / workload / benchmark / cross-domain
- phenotype: high-frequency / tiny-state / shallow / repeated / cold / collision / unsupported / expensive-materialization
- invariant: soundness-required / reuse-required / source-independence / closure-preserving / no-capacity-assumption / no-leakage
- causal status: observational / intervention-supported / ablation-supported / transfer-supported / refuted
- eliminated families: operator or representation families contradicted by verified experiments
- required properties: positive constraints induced by evidence

### Operator
A representation or transformation with an explicit capability signature:

- properties it satisfies
- invariants it preserves
- residual types it is intended to cover
- cost assumptions
- provenance of supporting evidence

### Latent obstruction
A minimal conjunction of constraints shared by a residual cluster that is not currently satisfied by any operator in closure.

A latent obstruction is an inference object, not automatically a law. It becomes verified only after a predicted operator family closes the implicated residuals and survives controls.

## Constraint closure

For a residual set `R`, collect only verifier-supported constraints. Candidate common explanations are conjunctions of those constraints.

A useful obstruction should satisfy:

1. **Coverage** — explains multiple unresolved residuals.
2. **Consistency** — violates no verified invariant.
3. **Minimality** — dropping any conjunct admits an already-refuted family or loses explanatory coverage.
4. **Novelty** — no operator in current closure satisfies the conjunction.
5. **Testability** — predicts a discriminating intervention or operator family.

## Discovery objective

Given unresolved residuals `R`, existing operator closure `K`, and verified invariants `I`, search for a candidate operator `o` maximizing

`covered_residual_mass(o) - complexity(o)`

subject to

- `o` satisfies the inferred constraint conjunction,
- `o` violates no invariant in `I`,
- `o` is outside closure-equivalence of current `K`, and
- its claimed causal effect is externally testable.

The important novelty criterion is therefore closure-relative:

> An operator is developmentally novel when it satisfies a verified constraint intersection that no current closure-equivalent operator satisfies.

Syntactic novelty alone does not count.

## Example: kernel closure identity

The following verified negatives can be represented as constraints:

- cache capacity approximately flat -> `capacity-independent`
- source-pointer identity unsound -> `semantic-identity-required`
- structural key improves but duplicates semantic work -> `duplicate-key-computation-prohibited`
- cache bypass collapses useful reuse -> `reuse-essential`
- dominant states have 0/1/2 slots -> `tiny-state`

Their intersection generates a specification approximately of the form:

`tiny-state AND canonical-semantic-identity AND reuse-compatible AND no-duplicate-key-computation AND capacity-independent AND sound`

If no current operator satisfies that conjunction, the graph exposes a representation gap before the missing representation has been explicitly named.

## Verification discipline

RCG is not allowed to turn correlation into mechanism. A proposed latent obstruction remains provisional until an intervention chain establishes:

`residual cluster -> inferred constraint -> predicted operator family -> gap closure -> ablation reopens gap -> transfer`

Negative experiments are retained when they shrink admissible operator space, even when they add no capability.

## Developmental state

The compact state to remember is not every raw failed trace. It is:

- provenance-linked residuals,
- verifier-supported type assignments,
- induced positive/negative constraints,
- closure of eliminated operator families,
- unresolved constraint intersections,
- provisional latent obstructions,
- verified operator laws.

Raw evidence remains available for audit, but control/search operates over this constraint closure.
42 changes: 42 additions & 0 deletions research/residual_constraint_graph/cases/trace_ace_v129_v131.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"case": "TRACE_ACE_V129_V131_APPLICABILITY",
"status": "unresolved",
"evidence": [
{
"residual": "V129_GLOBAL_UPTAKE_HARM",
"constraints": ["relational-operator", "globally-harmful", "applicability-sensitive", "must-be-gated"],
"evidence": "V129 uptake worsens V97 overall in both objective- and session-grouped OOF"
},
{
"residual": "V129_HARD_COLLISION_LIFT",
"constraints": ["relational-operator", "signal-present-in-ambiguity-regime", "rotation-control-separated"],
"evidence": "V129 improves label-defined hard collisions and beats within-session rotated replies in both geometries"
},
{
"residual": "HARD_COLLISION_NONDEPLOYABLE",
"constraints": ["activation-required", "label-free-at-inference", "opposite-label-test-forbidden-at-deployment"],
"evidence": "hard-collision membership requires an opposite-label same-objective row"
},
{
"residual": "V131_CROWDING_GATE_HARM",
"constraints": ["activation-required", "prediction-density-insufficient", "broad-crowding-not-ambiguity", "rotation-control-separated"],
"evidence": "label-free same-objective prediction crowding covers 71-76% and remains harmful, despite real uptake beating rotated control"
},
{
"residual": "V130_NO_BACKGROUND_REGIME",
"constraints": ["provider-marker-not-background-presence", "no-simple-background-regime"],
"evidence": "background appears in 99.3% of sessions and structural signatures are diffuse"
}
],
"constraint_intersection": [
"relational-operator-has-local-information",
"application-must-be-selective",
"activation-must-be-runtime-visible",
"prediction-density-alone-insufficient",
"activation-should-identify-representation-ambiguity-not-frequency",
"causal-control-required"
],
"latent_obstruction": "V97 lacks a deployable applicability predicate that identifies when a relational tutor-uptake correction is informative rather than destructive.",
"next_predicted_operator_family": "leakage-safe learned applicability gate over runtime-visible ambiguity/disagreement/support signals",
"falsification": "If a nested outer-fold gate trained only on inner-OOF correction benefit cannot improve V97 and beat the rotated-reply control on untouched outer folds, suppress this applicability family rather than tuning thresholds."
}
95 changes: 95 additions & 0 deletions research/residual_constraint_graph/rcg_v1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#!/usr/bin/env python3
"""Minimal executable Residual Constraint Graph v1.

The engine intentionally does not infer mechanisms from text similarity. It operates
only on explicit verified constraints supplied with provenance. It finds minimal
constraint intersections that cover multiple unresolved residuals and are not
already satisfied by an existing operator signature.
"""
from __future__ import annotations
from dataclasses import dataclass, field
from itertools import combinations
from typing import FrozenSet, Iterable


@dataclass(frozen=True)
class Residual:
name: str
constraints: FrozenSet[str]
weight: float = 1.0
verified: bool = True


@dataclass(frozen=True)
class Operator:
name: str
properties: FrozenSet[str]


@dataclass(frozen=True)
class Obstruction:
constraints: FrozenSet[str]
covered: tuple[str, ...]
mass: float
closure_satisfied: bool


def intersections(residuals: Iterable[Residual], operators: Iterable[Operator], min_cover: int = 2):
rs = [r for r in residuals if r.verified]
ops = list(operators)
out = []
for k in range(2, len(rs) + 1):
for subset in combinations(rs, k):
common = frozenset.intersection(*(r.constraints for r in subset))
if not common:
continue
covered = tuple(r.name for r in rs if common <= r.constraints)
if len(covered) < min_cover:
continue
closure = any(common <= op.properties for op in ops)
mass = sum(r.weight for r in rs if r.name in covered)
out.append(Obstruction(common, covered, mass, closure))

# Keep only non-closure-satisfied candidates, de-duplicate, then Pareto/minimality prune:
# a candidate is redundant when a strict subset of its constraints has identical coverage.
uniq = {}
for o in out:
if o.closure_satisfied:
continue
key = (o.constraints, o.covered)
if key not in uniq or o.mass > uniq[key].mass:
uniq[key] = o
vals = list(uniq.values())
pruned = []
for o in vals:
redundant = any(
p.covered == o.covered and p.constraints < o.constraints
for p in vals
)
if not redundant:
pruned.append(o)
return sorted(pruned, key=lambda o: (-o.mass, len(o.constraints), sorted(o.constraints)))


def self_test():
residuals = [
Residual('capacity_flat', frozenset({'structural','representation','capacity-independent','cache-related'})),
Residual('source_pointer_unsound', frozenset({'structural','identity','semantic-identity-required','cache-related','sound'})),
Residual('structural_key_cost', frozenset({'structural','representation','semantic-identity-required','duplicate-key-computation-prohibited','cache-related'})),
Residual('cache_bypass_bad', frozenset({'structural','reuse-essential','cache-related'})),
Residual('tiny_state_mass', frozenset({'structural','representation','tiny-state','cache-related'})),
]
operators = [
Operator('source_pointer', frozenset({'structural','cache-related','reuse-essential'})),
Operator('full_structural_key', frozenset({'structural','cache-related','semantic-identity-required','sound'})),
]
obs = intersections(residuals, operators)
assert obs
assert any('cache-related' in o.constraints and len(o.covered) >= 3 for o in obs)
print('RCG_SELF_TEST_PASS')
for o in obs[:10]:
print({'constraints': sorted(o.constraints), 'covered': o.covered, 'mass': o.mass})


if __name__ == '__main__':
self_test()
Loading