Metadata-Version: 2.4
Name: posterior-memory-harness
Version: 0.9.0
Summary: Model-agnostic probabilistic relation memory middleware for LLM agents
Author: sudoun
License: MIT
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=1.24
Dynamic: license-file

# Posterior Memory Harness

A model- and framework-neutral memory middleware for agents that preserves
uncertain local observations and reconciles them with global relation
constraints before each model call.

This package is a reusable implementation of the central mechanism studied in
the PosteriorGlue experiments. It is not another vector database and it does
not replace semantic retrieval. Use it beside a conventional memory system
when several observations describe related checkpoints, entities, plans, tool
states, or world states and their composition law matters.

## Why this memory is different

Most agent memory pipelines commit early:

1. an extractor emits one label or one summary;
2. the label is stored as fact;
3. retrieval ranks snippets independently;
4. contradictions are left for the LLM to notice.

This harness instead stores the complete local posterior
\(q_{uv}(r\mid x)\), its local class prior \(\mu_{uv}(r)\), time validity,
provenance, evidence-family fallback, and explicit source lineage. At query
time it builds the
factor

\[
\ell_{uv}(r)\propto q_{uv}(r\mid x)/\mu_{uv}(r)
\]

and infers globally compatible node states under a registered finite relation
law. The output is a small structured memory capsule containing ranked beliefs,
conflicts, and the exact observation IDs used.

The distinction is useful when:

- the locally correct state often remains in the top two or three candidates;
- cycles or redundant observations can resolve local ambiguity;
- relation order is meaningful;
- stale information and corrections must support as-of queries;
- compaction or repeated retrieval could otherwise count one source twice.

## What is included

- In-memory and persistent SQLite stores.
- Versioned SQLite schema adoption with an append-only migration history.
- Append-only observations with validity windows and timed revocation.
- Explicit local-prior correction.
- Cross-family evidence-lineage deduplication; only the latest active
  representative of one underlying source event counts.
- A non-blocking prior-only capsule when a new Agent has no observations yet.
- Seed-based bounded subgraph discovery, so callers need not know every related
  memory node in advance.
- Matched-budget `recent`, `coverage`, and `cycle_aware` retrieval policies.
- Structural retrieval diagnostics including connected components, cycle rank,
  covered-node fraction, and informative cycle-factor mass.
- A registry for custom finite relation laws.
- Built-in cyclic groups and the noncommutative \(S_3\) law.
- Exhaustive exact inference for small graphs.
- Deterministic beam inference for larger graphs.
- A dual-width beam stability diagnostic with MAP, marginal-TV, and entropy
  checks; the wider run supplies the returned approximation.
- Durable delayed-label calibration and prediction-drift monitoring, with
  hash-locked reference windows and pre-specified guards.
- Atomic observation/prediction commits and append-only outcome corrections.
- Restart-safe monitor replay, knowledge-time `as_of` reports, and journal
  integrity verification.
- A compact target-specific `memory_decision` projection for models that cannot
  reliably locate one action inside the full audit capsule.
- Node priors, tag/namespace isolation, trust tempering, and hard-top-1 control.
- A framework-neutral before-model/after-event middleware.
- A versioned, strict JSON input contract and a SQLite-backed command-line
  interface.
- Structured capsules with no free-form instruction field.

## Install

From this directory:

```powershell
python -m pip install .
```

For development:

```powershell
python -m pip install -e .
python -m unittest discover -s tests -v
```

The only runtime dependency is NumPy. Python 3.10 or newer is required.

The release has four independent version axes:

| Contract | Current version |
|---|---:|
| Python package | 0.9.0 |
| SQLite schema | 3 |
| observation/query/outcome JSON input | 2 (legacy 1 accepted) |
| calibration-monitor report | 2 |

The JSON schemas are included both in the source tree and in the installed
package under `posterior_memory_harness/schemas/`.

Release bundles are built from an explicit allowlist, use one safe top-level
directory, include a per-file SHA-256 manifest, and exclude local models,
databases, caches, and prior build outputs:

```powershell
python tools/build_release.py `
  --wheel dist/posterior_memory_harness-0.9.0-py3-none-any.whl
```

## Minimal Python integration

```python
from posterior_memory_harness import (
    MemoryMiddleware,
    PosteriorMemoryHarness,
    SQLiteMemoryStore,
    cyclic_law,
)
from posterior_memory_harness.middleware import StructuredObservationEncoder

harness = PosteriorMemoryHarness(SQLiteMemoryStore("agent_memory.sqlite"))
harness.register_relation("task-phase", cyclic_law(4))
middleware = MemoryMiddleware(harness, StructuredObservationEncoder())

harness.observe_payload({
    "schema_version": 2,
    "observation_id": "tracker:7",
    "namespace": "run-42",
    "relation_type": "task-phase",
    "source": "start",
    "target": "after-build",
    "posterior": {"0": 0.02, "1": 0.92, "2": 0.04, "3": 0.02},
    "prior": {"0": 0.25, "1": 0.25, "2": 0.25, "3": 0.25},
    "evidence_family": "raw-tool-call:7",
    "source_event_id": "tool-event:7",
    "lineage_root_id": "tool-event:7",
    "derived_from": [],
    "encoder_revision": "verified-tool-parser:v1",
    "calibration_revision": "tool-deterministic:v1",
    "observed_at": 100.0,
    "valid_from": 100.0,
    "provenance": {"tool": "build-tracker", "event": "7"},
    "tags": ["project-x"],
})

request = middleware.before_model(
    {"messages": [{"role": "user", "content": "What should I do next?"}]},
    {
        "schema_version": 2,
        "namespace": "run-42",
        "relation_type": "task-phase",
        "seeds": ["start"],
        "root": "start",
        "as_of": 101.0,
        "tags": ["project-x"],
        "max_hops": 2,
        "max_nodes": 16,
        "max_observations": 32,
        "retrieval_policy": "cycle_aware",
    },
)

# Pass request to any model/framework. It now contains `memory_capsule`.
```

A runnable version is in
[`examples/generic_agent_loop.py`](examples/generic_agent_loop.py).

## Explicit and discovered queries

An explicit query supplies `"nodes"` and is useful for locked evaluations or
when the surrounding application already owns the graph. A discovered query
supplies `"seeds"` instead:

```json
{
  "schema_version": 2,
  "namespace": "agent-run-42",
  "relation_type": "task-phase",
  "seeds": ["current-checkpoint"],
  "root": "current-checkpoint",
  "as_of": 101,
  "max_hops": 2,
  "max_nodes": 32,
  "max_observations": 512,
  "retrieval_policy": "cycle_aware"
}
```

The store discovers only active, tag-matching, independent observations
reachable within `max_hops`. It first keeps the latest active observation in
each explicit lineage root (falling back to `source_event_id`, then
`evidence_family`) and then applies deterministic node and observation
budgets. `coverage` preserves an information-ranked rooted spanning forest;
`cycle_aware` fills the remaining matched budget with informative
cycle-closing factors. SQLite performs reachability with a recursive CTE after
time, tag, revocation, and lineage filtering.

Every capsule includes retrieval metadata:

```json
{
  "retrieval": {
    "mode": "neighborhood",
    "seed_nodes": ["current-checkpoint"],
    "hops_explored": 2,
    "node_limit_hit": false,
    "observation_limit_hit": false,
    "truncated": false,
    "policy": "cycle_aware",
    "selected_observation_count": 5,
    "independent_lineage_count": 5,
    "connected_components": 1,
    "cycle_rank": 2,
    "covered_node_fraction": 1.0,
    "factor_information_score": 0.60,
    "cycle_information_score": 0.23
  }
}
```

The two information scores are deterministic selection diagnostics derived
from posterior-versus-prior Jensen--Shannon change, ambiguity, and trust. They
are not proper predictive scores and must not be compared across unrelated
relation laws.

Approximate queries also include an inference diagnostic. By default the
harness compares beam widths \(B\) and \(2B\), returns the wider result, and
reports MAP agreement, maximum node-marginal total variation, and maximum
entropy change:

```json
{
  "inference_diagnostics": {
    "mode": "dual-width-beam",
    "stable": true,
    "base_beam_size": 1024,
    "comparison_beam_size": 2048,
    "map_agreement": true,
    "max_marginal_tv": 0.004,
    "max_entropy_delta": 0.009,
    "marginal_tv_tolerance": 0.02,
    "entropy_tolerance": 0.05
  }
}
```

This is a budget-sensitivity diagnostic, not a proof of distance to the exact
posterior. A false result should trigger a wider beam, a smaller retrieved
subgraph, or exact inference where feasible.

The two modes are mutually exclusive. Supplying both `nodes` and `seeds`, or
neither, is rejected.

## Agent lifecycle contract

The integration surface deliberately uses plain mappings:

| Lifecycle point | Harness operation | Purpose |
|---|---|---|
| after tool | `after_tool` / `after_event` | store calibrated tool evidence |
| after model | `after_model` | store extractor output when appropriate |
| before model | `before_model` | attach a reconciled memory capsule |
| compaction | `on_compaction` | store derived summaries as non-independent |
| memory-evidence correction | `revoke` plus a new observation | preserve evidence history |

An observation encoder is an adapter boundary. It may be a calibrated
classifier, an LLM structured-output extractor, or a verified tool parser.
The harness never assumes a particular LLM vendor, chat message format, agent
loop, or vector store.

Compaction outputs must use `"independent_evidence": false` unless they contain
new independent evidence. Otherwise the summary and its source observations
would be counted twice.

This lifecycle row concerns correcting stored memory evidence. Correcting a
delayed calibration label instead uses `correct_outcome(...)`, which appends a
superseding outcome event without revoking the observation.

## Relation semantics

For node states \(z_u,z_v\), an edge observation describes
\(r_{uv}=z_u^{-1}z_v\). Register a law whose labels have a closed,
associative composition table, identity, and inverses:

```python
from posterior_memory_harness import FiniteRelationLaw

law = FiniteRelationLaw.from_dict({
    "name": "my-law",
    "labels": ["..."],
    "table": [[...]],
    "inverse": [...],
    "identity": 0,
})
harness.register_relation("my-relation", law)
```

The constructor exhaustively validates the finite law. Noncommutative laws are
supported; reversing the multiplication order is not treated as equivalent.

One node in each query is fixed to the identity as a gauge root. The returned
beliefs are therefore relative to that root, not absolute real-world claims.

## CLI

The CLI accepts observation and query JSON matching
[`schemas/observation.schema.json`](schemas/observation.schema.json) and
[`schemas/query.schema.json`](schemas/query.schema.json):

```powershell
posterior-memory --db memory.sqlite --relation-type task-phase `
  --law cyclic:4 observe examples/observation.json

posterior-memory --db memory.sqlite --relation-type task-phase `
  --law cyclic:4 query examples/query.json

posterior-memory --db memory.sqlite revoke tracker:7 --at 120

posterior-memory --db memory.sqlite --relation-type task-phase `
  --law cyclic:4 decision examples/query.json --focus-node after-build

posterior-memory --db memory.sqlite --relation-type task-phase `
  --law cyclic:4 outcome examples/outcome.json

posterior-memory --db memory.sqlite health --namespace agent-run-42

posterior-memory --db memory.sqlite verify
```

Use `--law s3` for the built-in noncommutative law or pass a finite-law JSON
file. `observe`, `query`, `decision`, and `outcome` require a law;
`health`, `verify`, and `revoke` do not. If a JSON payload already contains
`relation_type`, it must match the CLI value—the CLI never silently overwrites
a conflicting relation.

`query` and `decision` do not create a durable relation-law registration. They
accept an empty database for a prior-only answer, but fail closed if matching
observations exist without a previously bound database-global law. Normal
`observe` and Python `register_relation(...)` paths perform that binding.

An outcome file follows
[`schemas/outcome.schema.json`](schemas/outcome.schema.json):

```json
{
  "schema_version": 2,
  "observation_id": "tracker:7",
  "true_relation": "1",
  "outcome_event_id": "verified:tracker:7:v1",
  "labeled_at": 120.0
}
```

To correct a verified label, append a second event instead of editing the
first:

```json
{
  "schema_version": 2,
  "observation_id": "tracker:7",
  "true_relation": "2",
  "outcome_event_id": "verified:tracker:7:v2",
  "labeled_at": 120.0,
  "correction_reason": "human adjudication"
}
```

To use non-default monitor guards, provide them on the first `observe` for a
new run:

```powershell
posterior-memory --db memory.sqlite --monitor-run production-v1 `
  --monitor-config examples/monitor_config.json --relation-type task-phase `
  --law cyclic:4 observe examples/observation.json
```

Later commands use `--monitor-run production-v1` and reload the locked config
from SQLite. `health` fails if the requested run does not yet exist; it never
creates or silently configures a monitor. Stable observation/outcome event IDs
should be derived from the source event so crash retries are detectable.

CLI exit codes are stable and machine-readable:

| Code | Meaning |
|---:|---|
| 0 | success |
| 1 | unexpected internal failure |
| 2 | invalid input or payload |
| 3 | incompatible schema or failed integrity verification |
| 4 | durable state/idempotency conflict |

## Strict adapter input contract

Agent adapters are untrusted JSON boundaries. Payloads are validated before
any coercion or storage. Add `"schema_version": 2` to use lineage and
structure-aware retrieval fields. Version 1 remains accepted for backwards
compatibility and defaults to recency retrieval; omitted versions are
interpreted as version 1. Unknown future versions are rejected.

Unknown fields, string booleans, boolean probabilities, non-finite numbers,
duplicate identifiers, oversized relation supports, out-of-query node priors,
and non-JSON provenance are rejected. Hard resource limits cover identifier
length, tag count, provenance bytes/depth, query nodes, hops, and observation
budgets. `evidence_family` remains mandatory. A v2 adapter should additionally
set `lineage_root_id` from the original source event whenever the same evidence
can appear through different parsers, model echoes, or summaries.

See [`STRICT_INPUT_BEAM_STABILITY_ZH.md`](STRICT_INPUT_BEAM_STABILITY_ZH.md)
for the exact limits and stability semantics.

## Calibration and drift monitoring

The monitor evaluates the local posterior interface without changing stored
evidence or refitting online. With `SQLiteMemoryStore`, its configuration,
prediction snapshots, label order, relation-law fingerprint, and outcome
events are durable:

```python
from posterior_memory_harness import (
    CalibrationDriftMonitor,
    MonitorConfig,
    PosteriorMemoryHarness,
    SQLiteMemoryStore,
    cyclic_law,
)

monitor = CalibrationDriftMonitor(MonitorConfig(
    reference_size=200,
    current_size=100,
    min_current_size=30,
    run_id="production-v1",
))
harness = PosteriorMemoryHarness(
    SQLiteMemoryStore("agent_memory.sqlite"),
    monitor=monitor,
).register_relation("task-phase", cyclic_law(4))

# The monitor must be bound before this independent observation is stored.
harness.observe_payload({
    "schema_version": 2,
    "observation_id": "tracker:7",
    "namespace": "run-42",
    "relation_type": "task-phase",
    "source": "start",
    "target": "after-build",
    "posterior": [0.02, 0.92, 0.04, 0.02],
    "prior": [0.25, 0.25, 0.25, 0.25],
    "evidence_family": "raw-tool-call:7",
    "source_event_id": "tool-event:7",
    "lineage_root_id": "tool-event:7",
    "observed_at": 100.0,
})

# After the environment, a verified tool, or a human supplies delayed truth:
harness.record_outcome(
    "tracker:7",
    "1",
    outcome_event_id="verified:tracker:7:v1",
)
health = harness.calibration_report(namespace="run-42")

# A correction is a new immutable event; it never overwrites v1.
harness.correct_outcome(
    "tracker:7",
    "2",
    reason="human adjudication",
    outcome_event_id="verified:tracker:7:v2",
)
```

Reports are segmented by relation law and observation source family. They
contain accuracy, NLL, Brier, ECE, top-2 coverage, confidence, entropy,
reference/current deltas, prediction-marginal Jensen--Shannon divergence, and
machine-readable alerts. Insufficiently labeled windows are reported as
`insufficient_data`, never `healthy`.

For durable runs, `MonitorConfig` is canonicalized and SHA-256 locked by
`run_id`; reopening the same run with changed thresholds fails closed.
`as_of` reports include only predictions and outcome/correction events already
known by that cutoff. The monitor never applies an automatic calibration
update and its report is not inserted into model prompts. Thresholds should be
frozen before an audit.
See
[`CALIBRATION_DRIFT_MONITOR_ZH.md`](CALIBRATION_DRIFT_MONITOR_ZH.md).

## Target-specific decision projection

The full capsule is the audit record, but small language models may fail to
locate one target belief inside it. Project a focus node without recomputing or
re-ranking the posterior:

```python
request = middleware.before_model(
    {"messages": messages},
    memory_query,
    focus_node="checkpoint_4",
    alternatives=2,
)
```

The attached `memory_capsule` is then a compact `memory_decision` with
`highest_probability_state`, probability, alternatives, evidence/conflict
counts, and inference stability. It retains an empty instruction channel.

## SQLite schema lifecycle

Every SQLite database records `PRAGMA user_version` and an append-only
`memory_schema_migrations` history. Explicitly migrate it without loading a
relation law:

```powershell
posterior-memory-schema --db memory.sqlite migrate
```

Check an existing database without migrating or creating it:

```powershell
posterior-memory-schema --db memory.sqlite check
```

Schema v2 introduced five locked registry/journal tables: database-global
`relation_laws`,
`monitor_runs`, per-run `monitor_laws`, `monitor_predictions`, and
`monitor_outcomes`. Those five tables and `memory_schema_migrations` are
protected by database triggers against update/delete; root and
superseding-event uniqueness prevents correction forks. Changing `run_id`
cannot bypass the database-global relation-law binding. Before legacy
adoption, migration verifies every required observation column and the
`observation_id` primary key. Existing rows and additional application columns
are preserved. A malformed legacy table fails without destructive
reconstruction, and a database created by a newer package version is refused
rather than silently downgraded. Schema v3 adds nullable source/lineage and
encoder/calibration revision columns plus a validated `derived_from_json`
array. Old rows retain `evidence_family` as their lineage fallback; their
posterior payloads are not rewritten.

Migration uses an immediate transaction and is idempotent under concurrent
initialization. The subsequent WAL-mode transition uses bounded
`SQLITE_BUSY`/`SQLITE_LOCKED` retry with a fresh connection and verifies that
SQLite actually selected WAL; this closes the separate cross-process lock
window after migration commits. For monitored observations, the observation
and its exact posterior snapshot commit in one transaction, so a crash cannot
expose half a monitor record. Observation inserts name every column explicitly,
so a compatible additive application column with a default does not shift
stored values. `posterior-memory ... verify` performs `quick_check`,
foreign-key, schema, journal-shape, and payload-hash checks without repairing
the file. See
[`SQLITE_SCHEMA_MIGRATION_ZH.md`](SQLITE_SCHEMA_MIGRATION_ZH.md).

When a legacy database already contains observations, the first law binding
fully decodes every matching row and checks that its posterior/prior support
length matches the proposed labels. Equal support size cannot reveal
historical composition semantics, so that first binding remains an operator
attestation and should be made from the original deployment configuration.

## Safety and accounting rules

- Memory data is emitted as typed evidence, never as executable instructions.
- Raw provenance is stored for audit but is not copied into the model capsule.
- Namespace and tags are enforced before the observation budget is applied.
- Neighborhood discovery applies time, tag, revocation, and independence
  filters before graph traversal.
- Queries can be evaluated at historical `as_of` times.
- Historical queries never retrieve observations from their future.
- Revocation is timed and does not erase the prior record.
- Verified outcomes are append-only; corrections explicitly supersede an
  earlier event and retain both records.
- Durable monitor thresholds, label order, and relation law are hash-locked.
- Historical monitor reports are cut off by knowledge time, so a later
  correction cannot leak into an earlier audit snapshot.
- Prior correction prevents a classifier's training prior from being counted
  again as observation likelihood.
- Lineage-root deduplication prevents different parser families, model echoes,
  summaries, or retries from multiplying one source event. Legacy rows fall
  back to evidence-family deduplication.
- Every `derived_from` parent must already exist in the same namespace and
  relation type. An independent echo must also retain its parent's lineage root
  and relation endpoints, making the ancestry acyclic by append order.
- Compaction middleware forcibly marks summaries as derived evidence even if
  an encoder incorrectly labels them independent.
- A registered relation type cannot silently change its composition law.
- Existing SQLite observations cannot be queried under an unbound or
  support-size-incompatible relation law.
- Approximate outputs explicitly report the beam backend and
  `"approximate": true`, plus a dual-width stability diagnostic by default.

This does not make untrusted memory harmless by itself. The surrounding agent
must still authorize tools, isolate tenants, validate extractor schemas, and
keep retrieved evidence separate from system/developer instructions.

## Evidence from the controlled harness experiment

The accompanying controlled \(S_3\) checkpoint-graph experiment used 20 seeds
and 200 episodes per seed. With mean local top-1 accuracy of 64.76%, full
posterior reconciliation improved cycle-rich node accuracy from 65.59% to
94.45%, a paired gain of 28.86 percentage points with a 95% bootstrap interval
of [27.89, 29.84]. Episode success rose from 34.28% to 88.33%.

The controls matter:

- wrong composition order: 66.53%;
- posterior-to-episode shuffle: 17.13%;
- oracle local factors: 100%;
- cycle-free accuracy gain: only 0.94 percentage points, although NLL and
  Brier still improved.

This supports a narrow conclusion: the mechanism can recover locally retained
probability mass when correct redundant constraints are present. It is not yet
evidence that every LLM agent will improve. The runnable experiment, per-seed
outputs, bootstrap tables, and provenance are bundled under
[`benchmark/controlled_experiment/`](benchmark/controlled_experiment/).

The matched-budget structural retrieval audit then holds the observation count
at five in every condition. On 20 seeds and 200 episodes per seed,
`cycle_aware` retrieval reached 96.27% node accuracy, compared with 81.57% for
coverage-only and 16.34% for recent-only selection in an intentionally
adversarial recency-clutter design. Its paired accuracy interval versus
recency was [78.77, 81.10] percentage points, and exact cross-family lineage
echoes produced marginal TV 0. Recent-only selection actually had a larger raw
multigraph cycle rank (4 versus 2) but zero cycle-information score and only
50% node coverage. Thus cycle count alone is not used as a quality claim.
This is a controlled selector stress test, not an open-domain claim. Frozen
outputs and hashes are under
[`benchmark/structural_retrieval/`](benchmark/structural_retrieval/).

A separate frozen local-LLM audit found that a full capsule was not directly
usable by Qwen2.5-0.5B-Instruct (15.0% accuracy; 15.0% capsule adherence).
After a development-only interface diagnosis, a target-specific decision
projection was frozen and evaluated on new seeds. Full-posterior memory reached
97.5% answer accuracy versus 70.0% for hard-top-1 memory, a paired gain of
27.5 percentage points with a 95% bootstrap interval of [12.5, 42.5].
Raw-context accuracy was 10.0%. Both the failed v1 and passing fresh v2 outputs
are retained under
[`benchmark/llm_agent_audit/`](benchmark/llm_agent_audit/). See
[`LLM_AGENT_AUDIT_ZH.md`](LLM_AGENT_AUDIT_ZH.md) for scope and provenance.

## Limits

- The current runtime implements finite group-like relation laws, not arbitrary
  natural-language facts or continuous state spaces.
- Local posterior fidelity and calibration remain the caller's responsibility.
- Exact inference is exponential in the number of free nodes; `auto` switches
  to beam inference above the configured budget.
- Beam marginals are conditional on retained assignments and are approximate.
  Dual-width stability is a sensitivity check, not an exact-error certificate.
- SQLite monitor state is durable and incrementally synchronized across
  long-lived workers; the in-memory store remains process-local.
- `max_tracked` is a hard, database-enforced run capacity. Roll over to a new
  hash-locked `run_id` instead of silently changing a full reference period.
- Outcome-before-observation is rejected atomically and must be retried after
  the monitored observation exists.
- Explicit `lineage_root_id` values must identify the underlying source event
  correctly. If omitted, the fallback source-event/evidence-family key remains
  a caller responsibility.
- Neighborhood discovery starts from exact node IDs. Semantic/vector retrieval
  can supply seeds, but is intentionally outside this package.
- This is complementary to semantic retrieval, episodic summaries, and durable
  fact databases; it is not a drop-in replacement for them.
- The real-model audit uses one small local model and a controlled synthetic
  relation task; generalization to frontier models and open-domain agents is
  untested.

## Repository layout

```text
src/posterior_memory_harness/
  models.py       observation, query, and capsule contracts
  validation.py   strict versioned JSON adapter boundary
  store.py        in-memory and SQLite persistence
  sqlite_schema.py version checks, migration history, and legacy adoption
  laws.py         finite relation laws and registry
  inference.py    prior-corrected exact/beam inference
  retrieval.py    lineage deduplication and matched-budget graph selection
  monitoring.py   delayed-label calibration and drift guards
  projection.py   compact target-specific decision capsules
  harness.py      high-level API
  middleware.py   framework-neutral lifecycle hooks
  cli.py          JSON command-line adapter
  schemas/        schemas bundled as installed package data
schemas/          observation, query, and delayed-outcome JSON schemas
examples/         minimal integration
tests/            unit, persistence, and end-to-end regressions
benchmark/        runnable controlled experiment and frozen results
tools/            deterministic allowlisted release builder
```

The production dogfood findings and fixes are recorded in
[`DOGFOOD_AUDIT_ZH.md`](DOGFOOD_AUDIT_ZH.md). A fixed-command example that
actually invokes test/compile tools and feeds their lifecycle events through
the middleware is available at
[`examples/tool_using_agent_dogfood.py`](examples/tool_using_agent_dogfood.py).
The rationale and validation for automatic neighborhood retrieval are in
[`IMPROVEMENT_TARGET_ZH.md`](IMPROVEMENT_TARGET_ZH.md).
The v0.9 matched-budget audit is documented in
[`benchmark/structural_retrieval/README.md`](benchmark/structural_retrieval/README.md).
