Skip to content

feat(ingest): name conversational-capture source kind (transcript) — #1089 axis-2 prereq - #1105

Merged
github-actions[bot] merged 3 commits into
mainfrom
feat/issue-1089-source-tiebreak
Jul 6, 2026
Merged

github-actions[bot] merged 3 commits into
mainfrom
feat/issue-1089-source-tiebreak

Conversation

@robotrocketscience

Copy link
Copy Markdown
Owner

What

Names conversational / passive transcript capture as a first-class ingest source (INGEST_SOURCE_TRANSCRIPT) instead of letting it masquerade as INGEST_SOURCE_FILESYSTEM (the project-file scanner source). This is the axis-2 prerequisite of #1089 — the operator-approved slice after the pack-loop source tie-break was scoped out (see below). Behaviour-preserving; does not close #1089.

Why this, and why only this

Axis 2 of #1089 is "rank curated claude-memory above conversational capture." The already-merged origin tie-break (#1102) handles the important case (user/feedbackuser_validated outranks user_transcript). The only residual gap is claude-memory project/reference (deliberately deflated to agent_inferred) tying with agent-role transcript capture (also agent_inferred).

Closing that gap with a pack-loop source tie-break (issue option b) turned out to need a new source_kind column on beliefs + a data migration — the belief row persists origin and a path-like source, but no source_kind, so claude-memory and transcript beliefs aren't distinguishable at pack time. Given that cost buys only a marginal, arguably-undesirable reorder of two low-authority tiers, the operator chose prereq-only: land the migration-free naming now, defer the ranking lever.

The naming is independently worth doing: transcript capture recording source_kind=filesystem is real provenance debt (wrong audit/observability label; the retention/corroboration semantics conflate two distinct sources), and naming it is what makes "rank X above Y" expressible at all (per the note in #1089).

How (3 atomic commits)

  1. feat(models) — new INGEST_SOURCE_TRANSCRIPT constant (wire string transcript, matching the existing _TRANSCRIPT_SOURCE_LABEL), added to INGEST_SOURCE_KINDS (which record_ingest validates against) with retention default RETENTION_FACT (identical to the prior filesystem tag — no decay/GC change). Ships the required transcript_v0_1.jsonl replay-soak corpus (README kind count 7 → 8).
  2. feat(ingest)_ingest_turn_ids records source_kind=transcript; derive()'s user-transcript branch keys on the transcript source kind. Routing preserved: role=user → origin=user_transcript + undeflated prior still fires.
  3. docs(changelog) — Unreleased Changed entry.

Correctness / behaviour-preservation

  • Replay-equality holds. Production replay (replay.py) passes raw_meta=None to derive() and replay_full_equality compares origin — so the corpus rows use raw_meta=null, re-deriving on the agent_inferred path (stable both ways). Full replay-soak suite green.
  • Retention unchanged (RETENTION_FACT, same as filesystem) → no decay/GC behaviour change for transcript beliefs.
  • Routing preserved — the role=user → user_transcript end-to-end path is covered by an existing ingest_jsonl test (now implicitly proving the retag) plus a new ingest_log.source_kind assertion.
  • Side benefit (new guard test): the user-transcript branch now requires the transcript source kind, not just source_path=="transcript" — so a project file literally named transcript can no longer spoof the undeflated user prior.
  • Only ingest.py:_ingest_turn_ids is retagged; the scanner (scanner.py, classification.py) and derivation.py filesystem paths are untouched (the sole source_kind==filesystem branch was the transcript guard).

Tests

test_derivation (user-transcript cases moved to the transcript kind + a new spoof-guard test), test_ingest_jsonl (new ingest_log source-kind assertion), test_ingest_log (ingest_turn now stamps transcript), test_replay_soak_corpus (new corpus file validated + soak-green). Full suite green.

Out of scope (follow-ups, #1089 stays open)

  • The source-priority ranking lever itself (needs the beliefs.source_kind column + migration, or the lighter distinct-origin route for project/reference).
  • Prior-boost / project/reference provenance semantics.

Part of #1089 (axis-2 prerequisite); does not close it.

@robotrocketscience robotrocketscience added the author-Gylf PR coordination mutex label Jul 6, 2026

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @robotrocketscience, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@robotrocketscience, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 47 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 5a7a6347-20f6-46e7-a034-a3e231d93349

📥 Commits

Reviewing files that changed from the base of the PR and between 2f299f8 and f0f284f.

📒 Files selected for processing (10)
  • CHANGELOG/v3.md
  • src/aelfrice/derivation.py
  • src/aelfrice/ingest.py
  • src/aelfrice/models.py
  • tests/corpus/replay_soak/README.md
  • tests/corpus/replay_soak/v0.1/transcript_v0_1.jsonl
  • tests/e2e/test_source_type_discrimination.py
  • tests/test_derivation.py
  • tests/test_ingest_jsonl.py
  • tests/test_ingest_log.py
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/issue-1089-source-tiebreak

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@robotrocketscience robotrocketscience added the attn:review Needs review (PR open, awaiting reviewer) label Jul 6, 2026
@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown

PR-size soft cap

This PR is over the advisory size threshold:

  • 134 changed lines (limit: 200)
  • 10 changed files (limit: 3)

Bigger PRs collide with more open work, which under the parallel-session workflow tends to produce repeated attn:merge-conflict cycles (see #602). When practical, split into smaller PRs that each touch a focused surface.

This is advisory only — nothing is blocked. If the size is intentional (large refactor, module removal, generated code), apply the size:override label and this comment will be removed on the next push.

@robotrocketscience

Copy link
Copy Markdown
Owner Author

[claim:review:garsecg:2026-07-06T19:54:42Z]

@robotrocketscience

Copy link
Copy Markdown
Owner Author

[claim:review:Setr:2026-07-06T19:59:40Z]

@robotrocketscience

Copy link
Copy Markdown
Owner Author

[release:review:Setr:2026-07-06T19:59:45Z]

@robotrocketscience

Copy link
Copy Markdown
Owner Author

Review: approved on correctness — behaviour-preserving, replay-safe. Needs a rebase before the merge-train can FF (main advanced under #1104).

Verified end-to-end against github/main:

  • Symmetric rename, no behaviour change. The is_user_transcript guard swap (filesystemtranscript) in derivation.py is matched by the ingest-write swap in ingest.py:_ingest_turn_ids, and "transcript" is registered in INGEST_SOURCE_KINDS (so record_ingest validation accepts it) with RETENTION_FACT — identical to the prior filesystem tag, so no decay/GC change. ✓
  • Corroboration audit label preserved. _resolve_corroboration_source returns the explicit call_site first, and _ingest_turn_ids always stamps call_site=CORROBORATION_SOURCE_TRANSCRIPT_INGEST, so transcript beliefs keep the transcript corroboration source regardless of _CORROBORATION_BY_SOURCE_KIND. The map's .get(source_kind, FILESYSTEM_INGEST) default is byte-identical before/after — the transcript omission from that map is harmless (call_site is authoritative for these rows). ✓
  • Replay-safe. replay.py passes raw_meta=None and reconstructs only route_overrides/override_belief_type, so the is_user_transcript branch was already replay-inert regardless of source_kind; the source-kind swap does not change replay output for any row. The pre-existing live-vs-replay divergence on the role=user undeflation is honestly disclosed and correctly sidestepped by the raw_meta=null soak corpus. ✓
  • Strict improvement. The guard now also requires source_kind==transcript, so a scanner file literally named transcript can no longer spoof the undeflated user prior. ✓
  • CI green (pytest 3.12 + 3.13, incl. test_replay_soak_corpus); discretion grep clean on added lines; 3 atomic signed commits (all G).

Only remaining step: the branch is no longer FF (main moved when #1104 merged). File sets are disjoint (that PR was docs-only), so a git rebase github/main is clean — after that, ready-to-merge will FF cleanly. Leaving the rebase + label to the author/operator rather than force-pushing this branch from a review session.

@robotrocketscience

Copy link
Copy Markdown
Owner Author

[release:review:garsecg:2026-07-06T20:00:54Z]

@robotrocketscience

Copy link
Copy Markdown
Owner Author

[claim:review:garsecg:2026-07-06T20:02:38Z]

Conversational / passive transcript capture previously masqueraded as
INGEST_SOURCE_FILESYSTEM (the project-file scanner source). Give it a
first-class source kind so provenance is honest in ingest_log and the
axis-2 goal 'rank curated claude-memory above conversational capture'
is expressible.

- New INGEST_SOURCE_TRANSCRIPT constant (wire string 'transcript',
  matching the existing source_path label) + membership in
  INGEST_SOURCE_KINDS (record_ingest validates against this set).
- Retention default RETENTION_FACT, identical to the prior filesystem
  tag, so this rename does not change decay/GC behaviour.
- transcript_v0_1.jsonl replay-soak corpus (10 rows, raw_meta=null so
  derive() re-derives on the agent_inferred path — stable under the
  raw_meta=None production replay); README kind count 7 -> 8.

Part of #1089 (axis-2 prerequisite); no routing change here.
#1089)

_ingest_turn_ids now records source_kind=INGEST_SOURCE_TRANSCRIPT
instead of masquerading as INGEST_SOURCE_FILESYSTEM, and derive()'s
user-transcript branch keys on the transcript source kind rather than
filesystem. Behaviour is otherwise unchanged: retention default is
identical (RETENTION_FACT), and the role=user -> ORIGIN_USER_TRANSCRIPT
+ undeflated-prior routing is preserved.

Side benefit: the branch now requires the transcript *source kind*, so a
project file literally named 'transcript' can no longer spoof the
undeflated user prior (new regression test).

Tests: test_derivation user-transcript cases move to the transcript
kind; a new spoof-guard test; test_ingest_log asserts ingest_turn
stamps source_kind=transcript; a new ingest_jsonl end-to-end assertion
on the ingest_log label; the e2e source-discrimination scenario asserts
the transcript kind (and that the filesystem masquerade is gone).

Part of #1089 (axis-2 prerequisite).
…ce (#1089)

Unreleased Changed entry for the #1089 axis-2 prerequisite: naming
conversational capture as a first-class transcript ingest source.
@robotrocketscience
robotrocketscience force-pushed the feat/issue-1089-source-tiebreak branch from c4cd587 to f0f284f Compare July 6, 2026 20:03
@robotrocketscience robotrocketscience added the ready-to-merge Trigger merge-train: FF main to this PR's head label Jul 6, 2026
@robotrocketscience

Copy link
Copy Markdown
Owner Author

[claim:review:idnn:2026-07-06T20:06:38Z]

@github-actions github-actions Bot removed the ready-to-merge Trigger merge-train: FF main to this PR's head label Jul 6, 2026
@github-actions
github-actions Bot merged commit f0f284f into main Jul 6, 2026
29 checks passed
@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown

merge-train: merged f0f284fmain via FF push.

@robotrocketscience

Copy link
Copy Markdown
Owner Author

[release:review:idnn:2026-07-06T20:06:43Z]

@robotrocketscience

Copy link
Copy Markdown
Owner Author

[release:review:garsecg:2026-07-06T20:06:58Z]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

attn:review Needs review (PR open, awaiting reviewer) author-Gylf PR coordination mutex

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Ingest claude-memory as a default-on source, ranked above conversational capture

1 participant