Mining

mining.MiningSignal

A neutral fact mined from a transcript, ready for an app to map to a candidate.

Usage

Source

mining.MiningSignal(
    kind,
    detector,
    session_id,
    event_index,
    event_uuid,
    occurred_at,
    text,
    cc_version,
    trigger_index,
    signal,
    lower_bound=None,
    evidence=dict()
)

Attributes

kind: SourceKind

The descriptive source category.

detector: str

The sub-discriminator naming the shape that produced the signal.

session_id: SessionId

The session the originating event belongs to.

event_index: int

The index of the originating event in the stream.

event_uuid: EventUuid

The originating event’s uuid.

occurred_at: datetime

When the originating event was recorded.

text: str

The mined feedback text.

cc_version: CcVersion | None

The Claude Code version recorded for the origin.

trigger_index: int | None

The nearest preceding assistant index, or None — a hint the app may use; absence never disqualifies the fact here.

signal: CandidateSignal

The de-noising confidence signal; apps re-derive as needed.

lower_bound: int | None

A context anchor, such as the plan-reentry edit index.

evidence: Mapping[str, Any]
Detector-specific metadata preserved verbatim.

mining.CandidateSignal

A confidence verdict on a mined fact, with the reasons that produced it.

Usage

Source

mining.CandidateSignal(confidence, reasons=(), durable=True)

Attributes

confidence: Confidence

The de-noising score in [0, 1].

reasons: tuple[str, …]

The short reason codes that justify the score.

durable: bool
Whether the signal should persist across re-derivation.

mining.Confidence

A de-noising score in the closed interval [0, 1]; higher is more trustworthy.

mining.Confidence=NewType("Confidence", float)

mining.NOISE_FLOOR

mining.NOISE_FLOOR=LOW

mining.MiningSpec

The full declarative mining policy the Rust executor interprets.

Usage

Source

mining.MiningSpec(
    detectors=ALL_DETECTORS,
    user_message=USER_MESSAGE_SPEC,
    calibrated=CALIBRATED_SPEC,
    provenance=ProvenanceSpec(),
    review=ReviewSpec(),
    reentry_lookback=REENTRY_LOOKBACK,
    edit_tools=(lambda: expand_tool_names(_TOOL_SETS["EDIT_TOOLS"]))(),
    plan_tools=(lambda: expand_tool_names(_TOOL_SETS["PLAN_TOOLS"]))(),
    denial_excluded_tools=(lambda: expand_tool_names(_TOOL_SETS["DENIAL_EXCLUDED_TOOLS"]))()
)

Attributes

detectors: frozenset[DetectorName]

The detector ids to run; absent detectors are skipped.

user_message: ConfidenceSpec

Scoring stages for the transcript-message detector.

calibrated: ConfidenceSpec

Calibration stages seeded per call by the denial, plan, and review detectors.

provenance: ProvenanceSpec

The provenance classification policy.

review: ReviewSpec

The review-comment detector’s format and surface policy.

reentry_lookback: int

How many events back the plan-reentry detector scans for an edit.

edit_tools: frozenset[str]

The tool names whose use anchors a plan-reentry edit.

plan_tools: frozenset[str]

The plan-submission tool names whose denials mine as plan rejections.

denial_excluded_tools: frozenset[str]
The tool names whose denials the denial detector skips.

mining.mine()

Mines every MiningSignal from already-parsed transcript events.

Usage

Source

mining.mine(events, spec)

The Rust detector pipeline runs over materialized ~cc_transcript.models.TranscriptEvent objects, so a consumer that already parsed a transcript mines it without re-reading the file, and each mined signal’s event_index addresses straight back into the same events list. Each ~cc_transcript.mining.spec.CallableReviewFormat’s Python pattern and extractor fire through a positional side-channel. The events are materialized eagerly, since the Rust backend indexes them positionally, so a malformed spec pattern raises here rather than mid-stream.

Parameters

events: Sequence[TranscriptEvent]

The parsed transcript events, in stream order.

spec: MiningSpec
The mining policy: which detectors run, with which scoring, provenance, and review-format policy.

Yields

MiningSignal
Neutral mined facts, one per recognized transcript shape, in detector order.

mining.mining_spec_to_json()

Serializes spec to the JSON contract consumed by the Rust mining executor.

Usage

Source

mining.mining_spec_to_json(spec)

mining.DENIAL_PREFIX

mining.DENIAL_PREFIX=literal_str("protocol.DENIAL_PREFIX")

mining.DENIAL_KIND_USER_REJECTED

mining.DENIAL_KIND_USER_REJECTED=literal_str("protocol.DENIAL_KIND_USER_REJECTED")

mining.DENIAL_KIND_PERMISSION_RULE

mining.DENIAL_KIND_PERMISSION_RULE=literal_str("protocol.DENIAL_KIND_PERMISSION_RULE")

mining.USER_SAID_MARKER

mining.USER_SAID_MARKER=literal_str("protocol.USER_SAID_MARKER")

mining.USER_SAID_TRAILER

mining.USER_SAID_TRAILER=literal_str("protocol.USER_SAID_TRAILER")

mining.ANSWERED_PREFIX

mining.ANSWERED_PREFIX=literal_str("protocol.ANSWERED_PREFIX")

mining.ANSWERED_TRAILER

mining.ANSWERED_TRAILER=literal_str("protocol.ANSWERED_TRAILER")

mining.SourceKind

A descriptive category for a mined feedback fact.

mining.SourceKind=NewType("SourceKind", str)

The five module constants are the common categories the fact-detectors emit; apps may define their own SourceKind values for categories the core does not name.

mining.FeedbackCandidate

A single piece of developer pushback extracted from a transcript.

Usage

Source

mining.FeedbackCandidate(
    dedup_key,
    source_kind,
    occurred_at,
    text,
    window,
    ref,
    signal,
    session_id=None,
    cc_version=None,
    payload=None
)

Attributes

dedup_key: DedupKey

The content-derived key that makes ingestion idempotent.

source_kind: SourceKind

Which detector produced the candidate.

occurred_at: datetime

When the feedback was given.

text: str

The verbatim pushback text.

window: ContextWindow

The durable context window around the feedback, captured via ~cc_transcript.context.capture_window().

ref: EventRef

The resolvable reference to the originating event.

signal: CandidateSignal

The de-noising confidence signal.

session_id: SessionId | None

The transcript session the feedback came from.

cc_version: str | None

The Claude Code version recorded for the origin.

payload: Mapping[str, Any] | None
Detector-specific metadata preserved verbatim.

mining.DedupKey

A content-derived SHA-256 key that makes feedback ingestion idempotent.

mining.DedupKey=NewType("DedupKey", str)

mining.dedup_key()

Returns the stable dedup key for parts.

Usage

Source

mining.dedup_key(*parts)

Detectors key on session, kind, and the feedback content (plus its code location for review comments) rather than the transcript entry’s uuid or the absolute file path, so the same pushback recorded under two transcript entries collapses to one row, and the database stays portable and idempotent across moves.

Parameters

parts: str = ()
The content fragments that uniquely identify a candidate.

Returns

DedupKey
The SHA-256 hex digest of the parts joined by a null byte.

mining.ReviewComment

A single inline review comment parsed from a code-review message.

Usage

Source

mining.ReviewComment(file, line_start, line_end, comment)

Attributes

file: str | None

The file the comment targets, when cited.

line_start: int | None

The first line the comment targets, when cited.

line_end: int | None

The last line the comment targets, when a range is cited.

comment: str
The comment’s text.

mining.ReviewFormat

mining.ReviewFormat=RegexReviewFormat | CallableReviewFormat

mining.FeedbackStore

Persistent store for collected feedback over the native store engine.

Usage

Source

mining.FeedbackStore(engine, schema)

Owns the one connection to feedback.db — the feedback_events ledger, the scanned-file mtime table, and the verdict tier. Recording a scanned file and inserting its candidates commit in one transaction, so a scan is atomic. Apps hold a store and compose their own writes with record_file() inside transaction().

Example

>>> async with await FeedbackStore.open(Path("feedback.db")) as store:
...     await store.record_file_scan(str(path), mtime, candidates)

Methods

Name Description
close() Closes the underlying connection; a second close is a no-op.
dedup_keys() Returns every stored event’s dedup key.
events() Returns every feedback event, newest first, with the columns needed to render it.
execute() Runs one parameterized write statement, returning the modified-row count.
executemany() Runs statement once per parameter set, returning the total modified-row count.
executescript() Runs a multi-statement script — refused while a transaction is open.
file_mtimes() Returns the recorded path to mtime map for incremental scans.
insert_candidates() INSERT OR IGNOREs candidate rows, returning the newly inserted dedup keys.
judged() Returns events joined with their (role, prompt_version) verdicts, oldest first.
last_insert_rowid() Returns the rowid of the last inserted row on this connection.
open() Opens (creating if needed) the feedback database at path.
recent() Returns the most recent feedback events, newest first.
record_file() Upserts the recorded mtime for path.
record_file_scan() Records a scanned file and its candidates in one transaction.
record_verdict() Records one verdict, idempotently, keyed by (dedup_key, role, prompt_version).
sql() Runs one parameterized statement, returning rows as dicts.
stats() Returns ingestion counts by source kind and the scanned-file count.
transaction() Yields the store inside a single committed transaction.
unjudged() Returns events lacking a verdict for (role, prompt_version), unjudged first.
close()

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

Usage

Source

close()

Any later use of the store — or of a retained engine reference — raises sqlite3.ProgrammingError, exactly like a closed sqlite3.Connection.

dedup_keys()

Returns every stored event’s dedup key.

Usage

Source

dedup_keys()
events()

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

Usage

Source

events(*, source_kind=None)
Parameters
source_kind: SourceKind | None = None
When set, restrict to this source kind.
Returns
list[dict[str, object]]

One dict per event with its id, source_kind, occurred_at,

text, payload_json, context_json, event_uuid, and

session_id.
execute()

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

Usage

Source

execute(statement, params=())
executemany()

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

Usage

Source

executemany(statement, seq)
executescript()

Runs a multi-statement script — refused while a transaction is open.

Usage

Source

executescript(script)
file_mtimes()

Returns the recorded path to mtime map for incremental scans.

Usage

Source

file_mtimes()
insert_candidates()

INSERT OR IGNOREs candidate rows, returning the newly inserted dedup keys.

Usage

Source

insert_candidates(rows, extras=None)
judged()

Returns events joined with their (role, prompt_version) verdicts, oldest first.

Usage

Source

judged(*, role, prompt_version)

The physical accepted/summary columns are aliased to the generic accepted and summary keys, whatever the schema names them.

Parameters
role: str

The verdict role to join.

prompt_version: int
The prompt version to join.
Returns
list[dict[str, object]]

One dict per verdict-bearing event: the event columns plus the

verdict’s category, accepted, confidence, summary,

rationale, and model.
last_insert_rowid()

Returns the rowid of the last inserted row on this connection.

Usage

Source

last_insert_rowid()
open()

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

Usage

Source

open(path, schema=None, *, readonly=False, busy_timeout_ms=None, extensions=())
Parameters
path: Path

The database file path; its parent is created if absent.

schema: StoreSchema | None = None

The app’s schema composition; the platform default when omitted.

readonly: bool = False

When True, open read-only after exact schema attestation.

busy_timeout_ms: int | None = None

The SQLite busy timeout; the 5000ms default when omitted.

extensions: Sequence[str] = ()
Loadable SQLite extensions required by the exact schema.
Returns
Self
The opened store.
recent()

Returns the most recent feedback events, newest first.

Usage

Source

recent(*, source_kind=None, limit=20)
Parameters
source_kind: SourceKind | None = None

When set, restrict to this source kind.

limit: int = 20
The maximum number of rows to return.
Returns
list[dict[str, object]]
One dict per event with its source_kind, occurred_at, and text.
record_file()

Upserts the recorded mtime for path.

Usage

Source

record_file(path, mtime)

Called inside transaction() by the owning task it joins that transaction; called on its own it commits immediately. A standalone call during another task’s transaction raises TransactionConflictError.

Raises
TransactionConflictError
Another task’s transaction is open.
record_file_scan()

Records a scanned file and its candidates in one transaction.

Usage

Source

record_file_scan(path, mtime, candidates)

Inserts every candidate with INSERT OR IGNORE keyed by its dedup key and upserts the file’s mtime, so re-scanning an unchanged file is a no-op.

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_verdict()

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

Usage

Source

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

model is provenance only, never part of the identity: re-recording is a no-op, except a 'full'-fidelity verdict replaces a 'summary' one at the same key (any model), carrying the new model, content, and canonical_key across. When the engine reports a row changed, the judged event’s sqlite-vec evidence is upserted (or cleared when the verdict names no canonical_key) in the same transaction.

Parameters
key: DedupKey

The judged event’s dedup key.

verdict: VerdictLike

The structured verdict to persist.

role: str

Who produced it, e.g. judge or auditor.

prompt_version: int

The prompt version that produced it.

model: str

The resolved model name that produced it, kept as provenance.

fidelity: Fidelity
Whether the judged window rendered at 'full' fidelity or from 'summary' previews.
sql()

Runs one parameterized statement, returning rows as dicts.

Usage

Source

sql(statement, params=())
stats()

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

Usage

Source

stats()
transaction()

Yields the store inside a single committed transaction.

Usage

Source

transaction()

Composes consumer writes with record_file() so they commit or roll back together. A standalone write by the same task joins this transaction; the transaction is exclusive, so opening another while one is in flight raises TransactionConflictError.

Yields
AsyncIterator[Self]
The store.
Raises
TransactionConflictError
A transaction is already open.
unjudged()

Returns events lacking a verdict for (role, prompt_version), unjudged first.

Usage

Source

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

Truly-unjudged events sort ahead of summary-refresh rows, then by event id. With refresh_summary set, events whose verdict was recorded at fidelity='summary' re-yield for a full re-judge; a summary row whose context window no longer hydrates is dropped (unless probe_hydration is False). An event filter, when configured, pages a bounded window past dead summary rows and short-circuits limit=0 to empty; the unfiltered shape loads the candidates and returns its off-by-one first row for limit=0 — the pinned observable divergence between the two shapes.

Parameters
role: str

The verdict role to check.

prompt_version: int

The prompt version the verdict must carry.

limit: int | None = None

When set, the maximum number of rows to return.

refresh_summary: bool = False

When True, also re-yield summary-fidelity rows.

probe_hydration: bool = True
When True, drop summary-refresh rows whose window no longer hydrates; when False, skip the per-row transcript probe.
Returns
list[dict[str, object]]
One dict per event with the columns needed to build its prompt.

mining.StoreSchema

One complete exact v1 feedback-store schema.

Usage

Source

mining.StoreSchema(
    identity="cc-transcript-feedback",
    ddl=DEFAULT_SCHEMA_DDL,
    event_columns=(),
    verdict_table="verdicts",
    accepted_column="accepted",
    summary_column="summary",
    event_filter=None
)

Attributes

identity: str

The product-owned identity recorded in the exact v1 marker.

ddl: str

Complete one-shot application DDL, excluding the platform marker.

event_columns: tuple[str, …]

Product column names appended to candidate insert rows.

verdict_table: str

The physical verdict table name.

accepted_column: str

The verdict table’s accept column name.

summary_column: str

The verdict table’s summary column name.

event_filter: str | None
A SQL predicate over alias e ANDed into unjudged and judged, e.g. "e.quarantined_reason IS NULL".

mining.TransactionConflictError

A write attempted while another task’s transaction holds the connection.

Usage

Source

mining.TransactionConflictError()

The store shares one SQLite connection, so a transaction is exclusive: a standalone write from a different task or thread must not silently join it (a rollback would take the bystander’s committed-looking write with it). Callers hitting this serialize their writes or retry after the open transaction finishes.

mining.Stats

A snapshot of ingestion progress.

Usage

Source

mining.Stats(total, files, by_source)

Attributes

total: int

The total feedback events ingested.

files: int

The number of scanned files recorded.

by_source: Mapping[str, int]
Event counts keyed by source kind.

mining.sample_windows()

Sample up to n triggerless context windows as steering negatives.

Usage

Source

mining.sample_windows(
    raw,
    *,
    n,
    exclude=(),
    exclusion_radius=6,
    seed=0,
    before=6,
    after=2,
    preview_chars=200
)

Each window anchors on a completed turn — the agent acted and the user’s next prompt was not a steer we know about — and folds that turn into the window’s context: trigger is None, before ends at the sampled turn and keeps at most before turns, and after is unchanged. The anchor stays the sampled turn’s first meta-bearing event, so consumers key negatives exactly like positives.

Candidates are every turn carrying at least one event with resolvable meta (the anchor), except the session’s final turn, which may still be in flight. Every candidate in the exclusion_radius turns leading up to an exclude ref’s turn is dropped; refs that no longer resolve are ignored. The draw is a Rust-native deterministic sample keyed on f"{seed}:{session_id}" — stable across processes and releases from this version on, so one seed always yields the same windows for a session.

Parameters

raw: bytes

The session’s transcript bytes to sample from.

n: int

The maximum number of windows to return.

exclude: Iterable[EventRef] = ()

Anchors of known positives to keep clear of.

exclusion_radius: int = 6

How many turns before each excluded turn to drop (the excluded turn itself included). Turns after an excluded turn stay eligible — once the user has steered, letting the agent run again is a genuine negative; only the pre-steer approach, which positive-window rewinds occupy, is label-conflicted.

seed: int = 0

The determinism seed, mixed with the session id.

before: int = 6

How many turns each window’s folded before keeps, ending at the sampled turn.

after: int = 2

How many turns after each sampled turn to capture.

preview_chars: int = 200
The per-chunk preview budget persisted on each window.

Returns

list[ContextWindow]
The sampled windows, sorted by sampled turn index.