## Storage


## store.FeedbackStore


Persistent store for collected feedback over the native mining engine.


Usage

``` python
store.FeedbackStore(db)
```


Composes cc-transcript's `~cc_transcript.mining.FeedbackStore`, configured by `STEER_SCHEMA`: the `feedback_events` table (extended with the `origin_path` provenance and `quarantined_reason` columns), the `triage` verdict table (the engine's verdict tier pinned to cc-steer's column names), the `refinement` table, and the `accepted_steering` and `refined_pairs` views. Verdicts and refinements key on the content-derived dedup key, so they survive a database rebuild; the enrich stage's code evidence lives in cc-transcript's shared `corrections` ledger, keyed by the steering anchor.


#### Example

``` python
>>> async with await FeedbackStore.open(FeedbackStore.default_path()) as store:
...     await store.record_file_scan(str(path), mtime, candidates)
```


#### Methods

| Name | Description |
|----|----|
| [candidates()](#cc_steer.store.FeedbackStore.candidates) | Returns one row per event with its latest judge verdict and refine summary. |
| [close()](#cc_steer.store.FeedbackStore.close) | Closes the underlying connection; a second close is a no-op. |
| [dedup_keys()](#cc_steer.store.FeedbackStore.dedup_keys) | Returns every stored event's dedup key. |
| [default_path()](#cc_steer.store.FeedbackStore.default_path) | Returns the default database path, `~/.cc-steer/feedback.db`. |
| [embeddings()](#cc_steer.store.FeedbackStore.embeddings) | Returns every stored exemplar embedding for `model`, oldest first. |
| [events()](#cc_steer.store.FeedbackStore.events) | Returns every feedback event, newest first, with the columns needed to render it. |
| [execute()](#cc_steer.store.FeedbackStore.execute) | Runs one parameterized write statement, returning the modified-row count. |
| [executemany()](#cc_steer.store.FeedbackStore.executemany) | Runs `statement` once per parameter set, returning the total modified-row count. |
| [file_mtimes()](#cc_steer.store.FeedbackStore.file_mtimes) | Returns the recorded `path` to `mtime` map for incremental scans. |
| [gate_sample_family_mismatch_keys()](#cc_steer.store.FeedbackStore.gate_sample_family_mismatch_keys) | Returns parents whose stored gate family contradicts the latest judge verdict. |
| [gate_sample_stats()](#cc_steer.store.FeedbackStore.gate_sample_stats) | Returns gate sample counts keyed by kind. |
| [gate_samples()](#cc_steer.store.FeedbackStore.gate_samples) | Returns gate samples, oldest first, optionally restricted to one kind. |
| [judged()](#cc_steer.store.FeedbackStore.judged) | Returns non-quarantined events carrying a verdict for one role and prompt version. |
| [lineage()](#cc_steer.store.FeedbackStore.lineage) | Returns one event with all its triage verdicts and latest refined pairs. |
| [mark_sessions_sampled()](#cc_steer.store.FeedbackStore.mark_sessions_sampled) | Records that `session_ids` were parsed for random negatives, dropped-only included. |
| [negative_sessions()](#cc_steer.store.FeedbackStore.negative_sessions) | Returns the sessions already parsed for random negatives. |
| [open()](#cc_steer.store.FeedbackStore.open) | Opens (creating if needed) the feedback database at `path`. |
| [open_readonly()](#cc_steer.store.FeedbackStore.open_readonly) | Opens an existing feedback database without schema or data writes. |
| [pairs()](#cc_steer.store.FeedbackStore.pairs) | Returns every row of the `refined_pairs` view, the pipeline's deliverable. |
| [prune_gate_samples()](#cc_steer.store.FeedbackStore.prune_gate_samples) | Scans and classifies over an unlocked read, then deletes in a short transaction. |
| [quarantined_keys()](#cc_steer.store.FeedbackStore.quarantined_keys) | Returns the dedup keys excluded from pipeline and dataset reads. |
| [rebuild_context()](#cc_steer.store.FeedbackStore.rebuild_context) | Persists rebuilt contexts and quarantine reasons in one transaction. |
| [recent()](#cc_steer.store.FeedbackStore.recent) | Returns the most recent feedback events, newest first. |
| [record_embeddings()](#cc_steer.store.FeedbackStore.record_embeddings) | Upserts exemplar embeddings as `(dedup_key, model, text_digest, dim, vector)` rows. |
| [record_file_scan()](#cc_steer.store.FeedbackStore.record_file_scan) | Records a scanned file and its candidates in one transaction. |
| [record_gate_samples()](#cc_steer.store.FeedbackStore.record_gate_samples) | Records gate training samples idempotently, keyed by `sample_key`. |
| [record_refinement()](#cc_steer.store.FeedbackStore.record_refinement) | Records one event's atomic refined pairs in a single transaction. |
| [record_verdict()](#cc_steer.store.FeedbackStore.record_verdict) | Records one verdict, idempotently, keyed by `(dedup_key, role, prompt_version)`. |
| [repair_gate_samples()](#cc_steer.store.FeedbackStore.repair_gate_samples) | Reads, plans, and applies one gate-family reconciliation transactionally. |
| [sql()](#cc_steer.store.FeedbackStore.sql) | Runs one parameterized statement, returning rows as dicts. |
| [stats()](#cc_steer.store.FeedbackStore.stats) | Returns ingestion counts by source kind and the scanned-file count. |
| [triage_stats()](#cc_steer.store.FeedbackStore.triage_stats) | Returns triage coverage and acceptance at `prompt_version`. |
| [unenriched()](#cc_steer.store.FeedbackStore.unenriched) | Returns refined pairs whose steering anchor carries no shared-ledger correction. |
| [unjudged()](#cc_steer.store.FeedbackStore.unjudged) | Returns non-quarantined events lacking a verdict for one role and prompt version. |
| [unrefined()](#cc_steer.store.FeedbackStore.unrefined) | Returns accepted steering events lacking a refinement at `(prompt_version, model)`. |


##### candidates()


Returns one row per event with its latest judge verdict and refine summary.


Usage

``` python
candidates()
```


Powers the dashboard's candidate view across every pipeline status -- refined, accepted-but-unrefined, judge-rejected noise, and unjudged. The verdict and refine columns are `NULL` for events that have not reached that stage.


##### Returns


`list[dict[str, object]]`  
One dict per event: the event columns plus the latest judge verdict

(`category`, `is_steering`, `confidence`, `judge_version`,

`judge_model`, `what_claude_did`), the latest auditor side

(`auditor_is_steering`), the judge `flipped` flag, and the refine

summary (`pair_count`, `refine_version`, `refine_model`).


##### close()


Closes the underlying connection; a second close is a no-op.


Usage

``` python
close()
```


##### dedup_keys()


Returns every stored event's dedup key.


Usage

``` python
dedup_keys()
```


##### default_path()


Returns the default database path, `~/.cc-steer/feedback.db`.


Usage

``` python
default_path()
```


##### embeddings()


Returns every stored exemplar embedding for `model`, oldest first.


Usage

``` python
embeddings(*, model)
```


##### events()


Returns every feedback event, newest first, with the columns needed to render it.


Usage

``` python
events(*, source_kind=None)
```


##### execute()


Runs one parameterized write statement, returning the modified-row count.


Usage

``` python
execute(statement, params=())
```


##### executemany()


Runs `statement` once per parameter set, returning the total modified-row count.


Usage

``` python
executemany(statement, seq)
```


##### file_mtimes()


Returns the recorded `path` to `mtime` map for incremental scans.


Usage

``` python
file_mtimes()
```


##### gate_sample_family_mismatch_keys()


Returns parents whose stored gate family contradicts the latest judge verdict.


Usage

``` python
gate_sample_family_mismatch_keys()
```


##### gate_sample_stats()


Returns gate sample counts keyed by kind.


Usage

``` python
gate_sample_stats()
```


##### gate_samples()


Returns gate samples, oldest first, optionally restricted to one kind.


Usage

``` python
gate_samples(*, kind=None)
```


##### judged()


Returns non-quarantined events carrying a verdict for one role and prompt version.


Usage

``` python
judged(*, role, prompt_version)
```


##### lineage()


Returns one event with all its triage verdicts and latest refined pairs.


Usage

``` python
lineage(dedup_key)
```


Reads `feedback_events`, `triage`, and `latest_refinement` directly -- the deliverable views drop the auditor, the older judge versions, and the payload the lineage needs.


##### Parameters


`dedup_key: str`  
The event's content-derived key.


##### Returns


`dict[str, object]`  
The event columns plus `verdicts` (every judge and auditor row, oldest

first) and [pairs](storage.md#cc_steer.store.FeedbackStore.pairs) (the latest refinement generation, by `pair_index`),

or `{}` when no event carries the key.


##### mark_sessions_sampled()


Records that `session_ids` were parsed for random negatives, dropped-only included.


Usage

``` python
mark_sessions_sampled(session_ids)
```


##### negative_sessions()


Returns the sessions already parsed for random negatives.


Usage

``` python
negative_sessions()
```


Doneness is completion, not survival: a session whose every empty-anchor sample was dropped at insert carries no `random_negative` row, so the `sampled_session` marker is unioned in to stop it re-parsing every pass.


##### open()


Opens (creating if needed) the feedback database at `path`.


Usage

``` python
open(path)
```


##### open_readonly()


Opens an existing feedback database without schema or data writes.


Usage

``` python
open_readonly(path)
```


##### pairs()


Returns every row of the `refined_pairs` view, the pipeline's deliverable.


Usage

``` python
pairs()
```


##### prune_gate_samples()


Scans and classifies over an unlocked read, then deletes in a short transaction.


Usage

``` python
prune_gate_samples(query, classify, *, dry_run)
```


Classification renders every stored window, so it runs *outside* the write transaction -- holding `BEGIN IMMEDIATE` across that O(table) work would starve the pipeline's 2s busy timeout. The reported counts therefore come from the scan snapshot; the delete transaction asserts its own changed-row count against the planned key count and raises on a mismatch, so a row added or removed between scan and delete is a loud retry rather than a silent miscount. `dry_run` deletes nothing.


##### quarantined_keys()


Returns the dedup keys excluded from pipeline and dataset reads.


Usage

``` python
quarantined_keys()
```


##### rebuild_context()


Persists rebuilt contexts and quarantine reasons in one transaction.


Usage

``` python
rebuild_context(rebuilt, quarantined, *, dry_run=False)
```


##### recent()


Returns the most recent feedback events, newest first.


Usage

``` python
recent(*, source_kind=None, limit=20)
```


##### record_embeddings()


Upserts exemplar embeddings as `(dedup_key, model, text_digest, dim, vector)` rows.


Usage

``` python
record_embeddings(rows)
```


##### record_file_scan()


Records a scanned file and its candidates in one transaction.


Usage

``` python
record_file_scan(path, mtime, candidates)
```


The platform store's ingestion, plus the scanned path lands in each row's `origin_path` -- a display hint only (the dashboard's project labels); transcript resolution always goes through discovery by session UUID. A candidate whose rendered context carries no substantive content is quarantined in the same transaction, so an empty capture never reaches judging, acceptance, or the frozen eval.


##### Parameters


`path: str`  
The scanned file's path.

`mtime: float`  
The file's modification time at scan.

`candidates: Sequence[FeedbackCandidate]`  
The candidates extracted from the file.


##### Returns


`int`  
The number of newly inserted feedback events.


##### record_gate_samples()


Records gate training samples idempotently, keyed by `sample_key`.


Usage

``` python
record_gate_samples(samples)
```


The single insert choke point drops any sample whose window renders no substantive gate content -- a rewound-past-content positive or an empty-anchor negative is not valid model input and never reaches the table (mirrors accrual's empty-context quarantine at its own insert seam).


##### Parameters


`samples: Sequence[GateSample]`  
The samples to persist; re-inserting an existing key is a no-op.


##### Returns


`int`  
The number of newly inserted samples.


##### record_refinement()


Records one event's atomic refined pairs in a single transaction.


Usage

``` python
record_refinement(key, refinement, *, prompt_version, model)
```


Keyed by `(dedup_key, prompt_version, model, pair_index)` so re-running over a fully refined corpus is a no-op and every pair of one event commits together.


##### Parameters


`key: DedupKey`  
The refined event's dedup key.

`refinement: Refinement`  
The atomic pairs to persist.

`prompt_version: int`  
The refine prompt version that produced them.

`model: str`  
The resolved model name that produced them.


##### record_verdict()


Records one verdict, idempotently, keyed by `(dedup_key, role, prompt_version)`.


Usage

``` python
record_verdict(key, verdict, *, role, prompt_version, model, fidelity)
```


##### repair_gate_samples()


Reads, plans, and applies one gate-family reconciliation transactionally.


Usage

``` python
repair_gate_samples(query, planner)
```


##### sql()


Runs one parameterized statement, returning rows as dicts.


Usage

``` python
sql(statement, params=())
```


##### stats()


Returns ingestion counts by source kind and the scanned-file count.


Usage

``` python
stats()
```


##### triage_stats()


Returns triage coverage and acceptance at `prompt_version`.


Usage

``` python
triage_stats(*, prompt_version)
```


##### unenriched()


Returns refined pairs whose steering anchor carries no shared-ledger correction.


Usage

``` python
unenriched(log, *, limit=None)
```


A pair settles once its `(session_id, event_uuid)` anchor has a row in the shared `corrections` ledger -- the single source of truth for "done". Since the extractor is idempotent per anchor, every pair sharing one anchor settles together the moment any of them writes its row. Pairs come from the latest refine generation only, so a refine re-run resurfaces its new pairs here automatically. Anchors that legitimately yield no correction (expired, editless, or no faulted edit) never settle, but resolving them costs no LLM call.


##### Parameters


`log: CorrectionLog`  
The shared correction ledger to check each anchor against.

`limit: int | None = None`  
When set, the maximum number of rows to return.


##### Returns


`list[dict[str, object]]`  
One dict per unenriched pair with the columns the extractor and anchor

resolution need, oldest event first.


##### unjudged()


Returns non-quarantined events lacking a verdict for one role and prompt version.


Usage

``` python
unjudged(
    *,
    role,
    prompt_version,
    limit=None,
    refresh_summary=False,
    probe_hydration=True
)
```


##### unrefined()


Returns accepted steering events lacking a refinement at `(prompt_version, model)`.


Usage

``` python
unrefined(*, prompt_version, model, limit=None)
```


Surfaces the columns the refine prompt needs -- [dedup_key](detection.md#cc_steer.models.dedup_key), `source_kind`, `text`, `context_json`, `payload_json`, and the judge's `what_claude_did` hint -- oldest first.


##### Parameters


`prompt_version: int`  
The refine prompt version the refinement must carry.

`model: str`  
The resolved model name the refinement must carry.

`limit: int | None = None`  
When set, the maximum number of rows to return.


##### Returns


`list[dict[str, object]]`  
One dict per accepted, unrefined event.
