Skip to content

fix(insights): finish typed session-PR evidence + wire root: filter - #3431

Merged
Sinity merged 5 commits into
masterfrom
feature/insights/pbuh-cijx-root-filter
Jul 31, 2026
Merged

fix(insights): finish typed session-PR evidence + wire root: filter#3431
Sinity merged 5 commits into
masterfrom
feature/insights/pbuh-cijx-root-filter

Conversation

@Sinity

@Sinity Sinity commented Jul 31, 2026

Copy link
Copy Markdown
Owner

Summary

Closes the two named, still-open gaps from tonight's polylogue-pbuh and
polylogue-cijx.4 investigations: (1) verifies and finishes the read-side
wiring for typed session→PR evidence (pbuh AC4), and (2) wires the root:
session-structure filter end-to-end across the query DSL, CLI, and Python
API (cijx.4 AC4 / its follow-up polylogue-oqib).

Problem

Gap 1 (pbuh AC4). polylogue-pbuh's parser-side fix (index v46, PR #3390)
persists Claude Code's pr-link sidecar record as typed session_refs
evidence, but nothing on the CLI/insights/MCP surface read it — the four
dependent beads (212.2/xyel/kph/fs1.4) were blocked on an inference
mechanism (session_commits, 0 readers, 2,989 rows of a narrower fact)
instead of the typed evidence the provider already supplies.

Gap 2 (cijx.4 AC4 / oqib). sessions.parent_session_id and
Session.is_root are correct, and a plan-level root: bool | None field
plus .is_root() builder already existed, but root had no spec_attr,
no DSL grammar case, and no CLI flag — completely unreachable from any
query surface, so a default find mixes 66.1% root sessions with 33.9%
subagent/branch children unlabeled.

Solution

Gap 1: A sibling lane's PR #3425 (fix/insights/session-commit-typed-evidence)
had landed the actual read-side fix — build_correlation_result now
consumes session_refs/claude_bridge_session typed evidence as
authoritative, falling back to regex/time-window heuristics only where no
typed evidence exists, and surfacing disagreements. It was open but
unmerged when this pass started; triaged its 3 non-blocking CodeRabbit P2
findings (filed as follow-up polylogue-2vor) and merged it (5525446).

Verifying the now-merged surface against the live archive
(find id:<session> then read --view correlation) surfaced a second,
independent, pre-existing bug
: _enrich_with_github_api
(polylogue/insights/correlation_view.py) referenced SessionCorrelationResult
at runtime while only importing it under TYPE_CHECKING — every call with
the default github_api=True and any issue/PR ref present raised
NameError. This predates PR #3425 (present since ac84f734f); the
existing test suite only exercised github_api=False, so it was never
caught. Fixed by importing the class at runtime alongside the existing
GitHubRef import, plus a regression test.

Gap 2:

  • SessionQuerySpec.root: bool | None, wired through
    build_query_spec_from_params/query_spec_to_plan (new optional_bool
    tri-state parser in archive/query/spec.py).
  • DSL: root:true/root:false field clause (archive/query/expression.py);
    -root: negation is rejected pointing at root:false instead (the value
    already carries polarity).
  • CLI: --root/--no-root flag, added last in cli()'s signature per this
    repo's "new Click params go last" convention.
  • EXPRESSION_FIELD_REGISTRY["root"] + regenerated docs/cli-reference.md,
    docs/search.md.

Two deeper bugs found while making this reachable (neither was "just
unreachable" — both were silent no-ops even where a plan/spec did carry a
value):

  1. The CLI's actual browse/search path (cli/archive_query.py's
    _ArchiveFilterKwargsArchiveStore.list_summaries/search_summaries/
    count_sessions/count_search_sessions/search_session_ids/
    semantic_summaries/stats/stats_by) is a SQL-level filter path
    entirely separate from the SessionQueryPlan/apply_common_filters
    post-filter machinery root's field descriptor (requires_post_filter=True)
    was designed against. None of those eight ArchiveStore methods accepted
    a root kwarg. Fixed by pushing root into _session_filter_clause as
    a direct SQL predicate (sessions.parent_session_id IS [NOT] NULL
    trivially SQL-pushable, unlike continuation/sidechain which derive
    from branch_type) and threading it through all eight methods.
  2. Even the SessionQueryPlan post-filter path (Python API's
    list_summaries_archive/list_archive) was independently broken:
    ArchiveSessionSummary never carried parent_id (the SELECT never
    projected sessions.parent_session_id, _summary_from_row never read
    it), so is_root was True for every summary row regardless of actual
    parent — a root:true filter would have silently returned everything
    even once reachable. Fixed by adding parent_id to
    ArchiveSessionSummary, projecting the column in both read_summary
    and list_summaries, and threading it through _summary_to_domain.

Default-behavior decision: did not flip any surface's default.
find/Python API list()/MCP query/daemon HTTP all continue to return
every session unless root:/--root/.is_root() is given explicitly.
Flipping even the narrower "CLI find verb only" option still has real
blast radius (every existing test/saved-query/demo-script assuming
today's "everything" default needs re-auditing), and reachability is the
load-bearing wedge — polylogue find repo:polylogue root:true now
produces the named, non-fanout view AC4's proof text asks for. The
default question is left open as a deliberate, separately-reviewable
follow-up (narrowed onto polylogue-oqib).

AC disposition

polylogue-pbuh (typed session→PR evidence): AC4 satisfied. Typed
session→PR linkage is reachable from read --view correlation
(CLI/API), verified live against the real archive. AC6 (before/after
UUID-title/PR-link census) is untouched — out of this gap's declared
scope, still open.

polylogue-cijx.1 (repo-identity bead whose notes tracked the
session-commits/pr-link consumer question): the specific blocking concern
its notes raised for 212.2/xyel/kph/fs1.4 ("the producer does not work" /
"0 readers") is resolved. Its own titled AC (repo_id fragmentation) is
unrelated and was already addressed by cijx.4.

212.2 / xyel / kph / fs1.4: unblocked, not closed — each still needs
its own concrete deliverable (demo build, CI hook, CLI/report regen)
beyond "the data is now readable." Noted individually on each bead.

polylogue-cijx.4 AC4: reachability satisfied. Default-behavior
question deferred, narrowed onto polylogue-oqib (priority lowered —
remaining scope is a design decision, not plumbing).

polylogue-oqib: reachability + both deeper bugs satisfied and
fixed
. Default-behavior flip not attempted, left open and
explicitly narrowed to that one remaining decision.

Verification

  • devtools test tests/unit/cli/test_correlate_view.py — 4 passed
    (including new NameError regression test).
  • devtools test tests/unit/cli/test_query_expression.py tests/unit/core/test_query_fields.py tests/unit/cli/test_archive_query.py tests/unit/archive/test_archive_execution_filters.py tests/unit/cli/test_query_exec_laws.py tests/unit/archive/ tests/unit/storage/test_archive_tiers_archive.py tests/unit/archive/query/test_discovery.py — all green (new
    test_root_filter_partitions_top_level_and_subagent_sessions covers all
    eight ArchiveStore methods plus the parent_id/is_root wiring bug).
  • mypy --strict on every touched module — no issues.
  • devtools render all --check — sync OK.
  • devtools verify --quick — exit 0 (also ran automatically via the
    pre-push hook).
  • Manual live verification (read-only, /realm/db/polylogue/index.db):
    find id:<session> then read --view correlation --format json returns
    typed pr_refs (source=typed_session_ref) plus a disagreements list;
    find repo:polylogue --root → total 1906; find repo:polylogue --no-root
    → total 3206; 1906+3206=5112, the unfiltered total.

Not done / follow-ups

  • polylogue-2vor: 3 CodeRabbit P2 findings on PR fix(insights): prefer typed PR/session evidence over regex correlation #3425's typed-evidence
    path (PR #0 coercion, cross-repo number collision, foreign-trailer
    false-disagreement).
  • polylogue-oqib: the default-behavior decision for root: (which
    surfaces, if any, should default to top-level-only).
  • root is not wired into query_unit_session_filters (the with <units>
    projection's separate session-filter adapter), and daemon HTTP's
    _build_query_spec_params named-param allowlist has no dedicated
    ?root= query param (the existing ?query=root:true DSL path already
    covers it). continuation/sidechain/has_branches remain exactly as
    unreachable as before this PR.

Ref polylogue-pbuh, polylogue-cijx.1, polylogue-cijx.4, polylogue-oqib.

Sinity and others added 4 commits July 31, 2026 08:03
Problem: verifying polylogue-pbuh AC4 (typed session->PR evidence now
has readers, per PR #3425) by running `read --view correlation`
against a real session in the live archive raised
`NameError: name 'SessionCorrelationResult' is not defined` -- the
default github_api=True path in _enrich_with_github_api never worked.
The class was imported only under `TYPE_CHECKING` (line 11) but
constructed at runtime at the function's return statement. This bug
predates PR #3425 (present since ac84f73); the existing test suite
only exercised github_api=False, so it went uncaught.

What changed: import SessionCorrelationResult inside
_enrich_with_github_api alongside the existing runtime GitHubRef
import, and add a regression test that exercises the default
github_api=True path with a mocked `gh` failure (the common case in
CI/sandboxes without gh installed).

Verification: devtools test tests/unit/cli/test_correlate_view.py (4
passed, including the new regression test); manually confirmed against
the live archive (read-only, /realm/db/polylogue/index.db) that
`find id:<session> then read --view correlation --format json` now
returns typed pr_refs (source=typed_session_ref) and a disagreements
list instead of crashing.

Co-Authored-By: Claude <noreply@anthropic.com>
Problem: polylogue-cijx.4 decision 4 ("default result unit is the
top-level session") and its split-off follow-up polylogue-oqib found
that `sessions.parent_session_id`/`Session.is_root` are correct and a
plan-level `root: bool | None` field + `.is_root()` fluent builder
already existed, but `root` had no `spec_attr`, no query-DSL grammar
case, and no CLI flag -- completely unreachable from any query surface.

What changed:

- SessionQuerySpec gains `root: bool | None`, wired through
  `build_query_spec_from_params`/`query_spec_to_plan` (archive/query/spec.py)
  and a new `optional_bool` tri-state parser.
- DSL grammar: `root:true`/`root:false` field clause in the compact-query
  transformer (archive/query/expression.py); negation (`-root:...`) is
  rejected with a message pointing at `root:false` instead, since the
  boolean value already carries polarity.
- CLI: `--root/--no-root` flag (cli/click_option_groups.py), threaded
  through the root `cli()` signature per this repo's "new Click params
  go last" convention.
- Field metadata/discovery: `EXPRESSION_FIELD_REGISTRY["root"]`
  (archive/query/metadata.py) and the generated unknown-field diagnostic
  in archive/query/discovery.py + docs/search.md (`devtools render all`).

Deeper bug found while making this reachable: the CLI's actual browse/
search path (`polylogue/cli/archive_query.py`'s `_ArchiveFilterKwargs` ->
`ArchiveStore.list_summaries`/`search_summaries`/`count_sessions`/
`count_search_sessions`/`search_session_ids`/`semantic_summaries`/`stats`/
`stats_by`) is a SQL-level filter path entirely separate from the
`SessionQueryPlan`/`apply_common_filters` post-filter machinery `root`'s
field descriptor was designed against. None of those eight ArchiveStore
methods accepted a `root` kwarg or passed it to `_session_filter_clause`,
so wiring the DSL/CLI/spec layers alone would have produced a flag that
parses successfully but silently filters nothing. Fixed by pushing
`root` into `_session_filter_clause` as a direct SQL predicate
(`sessions.parent_session_id IS [NOT] NULL` -- trivially SQL-pushable,
unlike `continuation`/`sidechain` which derive from `branch_type`) and
threading it through all eight methods plus `_ArchiveFilterKwargs`.

Second bug found during verification: even the `SessionQueryPlan` post-
filter path (used by the Python API's `list_summaries_archive`/`list_archive`)
was silently broken -- `ArchiveSessionSummary` (storage/sqlite/archive_tiers/archive.py)
never carried `parent_id` (the SELECT never projected
`sessions.parent_session_id` and `_summary_from_row` never read it), and
`_summary_to_domain` (archive/query/archive_execution.py) never passed it
to `SessionSummary`, so `is_root` was `True` for every summary row
regardless of actual parent. Fixed by adding `parent_id` to
`ArchiveSessionSummary`, projecting `s.parent_session_id` in both
`read_summary` and `list_summaries`' SELECTs, and threading it through
`_summary_to_domain`.

DEFAULT-BEHAVIOR DECISION: did NOT flip any surface's default result set.
`find`/Python API `list()`/MCP query/daemon HTTP all continue to return
every session (root and child) unless `root:`/`--root`/`.is_root()` is
given explicitly. Justification: flipping the CLI `find` default alone
(cijx.4's suggested narrower option) still has real blast radius --
every existing test, saved query, and demo script that assumes today's
"everything" default would need re-auditing, and the operator's own
framing of AC4 treats reachability as the wedge, not an implicit
behavior change. Exposing the filter without changing the default lets
`polylogue find repo:polylogue root:true` immediately produce the named,
non-fanout view AC4's proof text asks for, without a silent behavior
change for every unfiltered caller. The default question itself is left
open as a deliberate, separately-reviewable follow-up.

Not done (explicitly out of scope, noted for follow-up): `root` is not
wired into `query_unit_session_filters` (the `with <units>` projection's
separate session-filter adapter), and daemon HTTP's `_build_query_spec_params`
named-param allowlist does not include a dedicated `?root=` query param
(the existing `?query=root:true` DSL path already covers it via
`compile_expression_into`). `continuation`/`sidechain`/`has_branches`
remain unreachable exactly as before -- this PR does not touch them.

Verification:
- devtools test tests/unit/cli/test_query_expression.py
  tests/unit/core/test_query_fields.py tests/unit/cli/test_archive_query.py
  tests/unit/archive/test_archive_execution_filters.py
  tests/unit/cli/test_query_exec_laws.py tests/unit/archive/
  tests/unit/storage/test_archive_tiers_archive.py
  tests/unit/archive/query/test_discovery.py -> all green (new
  test_root_filter_partitions_top_level_and_subagent_sessions covers all
  eight ArchiveStore methods + the parent_id/is_root wiring bug).
- mypy --strict on every touched module: no issues.
- devtools render all --check: sync OK (docs/cli-reference.md,
  docs/search.md regenerated).
- devtools verify --quick: exit 0.
- Manual live verification (read-only, /realm/db/polylogue/index.db):
  `find repo:polylogue --root --format json` -> total 1906;
  `find repo:polylogue --no-root --format json` -> total 3206;
  1906 + 3206 = 5112, the unfiltered total -- confirms the SQL pushdown
  partitions the real archive exactly, not just a fixture.

Co-Authored-By: Claude <noreply@anthropic.com>
Captures the bd note updates made while verifying polylogue-pbuh AC4
and polylogue-cijx.1 (PR #3425 merge, correlation_view.py NameError fix,
and disposition notes on the four cijx.1 dependents 212.2/xyel/kph/fs1.4).
These landed in the main checkout's .beads/issues.jsonl via the
cwd-independent bd export path (known hazard) instead of this worktree's
copy; re-synced here so the branch carries the current bead state.

Co-Authored-By: Claude <noreply@anthropic.com>
polylogue-oqib: reachability (spec_attr/DSL/CLI + the two deeper
SQL-pushdown and parent_id-wiring bugs found along the way) is done;
narrowed remaining scope to the default-behavior decision only, and
lowered priority accordingly. Re-synced from the main checkout's
.beads/issues.jsonl (same cwd-independent bd export hazard as the prior
beads commit on this branch).

Co-Authored-By: Claude <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 74ce554df0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +279 to +284
"--root/--no-root",
"root",
default=None,
help=(
"Only top-level sessions (--root) or only subagent/branch children "
"(--no-root). Unset (default) selects both, unfiltered by structure."

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Carry root through daemon query execution

When a daemon is reachable—the normal polylogued run setup—ordinary find pages take _try_emit_daemon_session_page, but _daemon_session_query_params never sends this new flag and _daemon_session_page_supported does not force a local fallback. Even root:true transported as DSL is discarded because polylogue/daemon/http.py::_archive_filter_kwargs_from_spec omits root; consequently --root, --no-root, and the DSL form return unfiltered rows on the daemon path. Thread the tri-state value through both daemon adapters or disable that fast path for root-filtered requests.

AGENTS.md reference: AGENTS.md:L193-L197

Useful? React with 👍 / 👎.

Comment on lines 305 to +308
"since_ms": since_ms,
"until_ms": until_ms,
"since_session_id": since_session_id,
"root": compiled_spec.root,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Apply root to analyze counts

For polylogue --root find ... then analyze --count (and the --no-root equivalent), the count_only branch below bypasses this shared filter_kwargs mapping and manually invokes count_search_sessions/count_sessions without root. The command therefore reports the unpartitioned total even though ordinary local list/search output applies the filter; pass root in both count calls or reuse this mapping.

AGENTS.md reference: AGENTS.md:L193-L197

Useful? React with 👍 / 👎.

Comment on lines 449 to 453
offset=spec.offset,
cursor=spec.cursor,
boolean_predicate=spec.boolean_predicate,
root=spec.root,
vector_provider=vector_provider,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Push root down before plan pagination

When a spec is executed through the Python API/MCP plan path, this activates plan.root, but archive_execution._plan_filter_kwargs still omits it even though the storage readers now accept SQL-level root. The residual filter runs only after _archive_summaries has applied the requested offset and fetched at most limit * 4, so a page whose leading rows are children can return short or empty for root:true despite matching roots later in the archive (and conversely for root:false). Add root to the plan-to-storage kwargs so partitioning occurs before pagination.

AGENTS.md reference: AGENTS.md:L227-L229

Useful? React with 👍 / 👎.

@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown

Warning

Review limit reached

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

Next review available in: 54 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: ASSERTIVE

Plan: Pro Plus

Run ID: daf1ab0a-add9-4a7b-86fb-f539203cce16

📥 Commits

Reviewing files that changed from the base of the PR and between eb5796f and 87f192a.

📒 Files selected for processing (18)
  • .beads/issues.jsonl
  • docs/cli-reference.md
  • docs/search.md
  • polylogue/archive/query/archive_execution.py
  • polylogue/archive/query/discovery.py
  • polylogue/archive/query/expression.py
  • polylogue/archive/query/fields.py
  • polylogue/archive/query/metadata.py
  • polylogue/archive/query/spec.py
  • polylogue/cli/archive_query.py
  • polylogue/cli/click_app.py
  • polylogue/cli/click_option_groups.py
  • polylogue/insights/correlation_view.py
  • polylogue/storage/sqlite/archive_tiers/archive.py
  • tests/unit/cli/test_correlate_view.py
  • tests/unit/cli/test_query_exec_laws.py
  • tests/unit/cli/test_query_expression.py
  • tests/unit/storage/test_archive_tiers_archive.py

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.

@Sinity
Sinity merged commit 7f494b8 into master Jul 31, 2026
2 checks passed
@Sinity
Sinity deleted the feature/insights/pbuh-cijx-root-filter branch July 31, 2026 07:47
Sinity added a commit that referenced this pull request Jul 31, 2026
…#3438)

## Summary

Two independent "computed and discarded" defects, both verified live
tonight per the operator's audit theme:

- **polylogue-uh9l**: Claude Workflow artifact coverage was computed on
every ingest pass by `assembly_claude_code.py:discover_sidecars` and
consumed by nothing. Deleted the dead branch and wired the
genuinely-running materializer's gap count into `polylogue doctor`'s
readiness surface instead.
- **polylogue-xyel**: re-verified against current master (not assumed
from the bead's original framing) that `session_refs` now has a live
production consumer (PR #3425/#3431, already merged) — then built the
bead's own remaining, un-satisfied AC: a real D1 "receipts" demo packet.

## Problem

**uh9l**: `polylogue-z9gh.6`'s closure claimed "readiness and repair
commands no longer report healthy solely because subagents/workflows is
classified as a known sidecar." False as written — no readiness/repair
command consulted either of the two coverage computations that existed
for Claude Workflow artifacts. One
(`ClaudeOrchestrationCoverage`/`inventory_claude_orchestration_artifacts`)
was fully dead code; the other (`claude_workflow_materializer`'s gap
tuple) ran every convergence pass but was only ever logged.

**xyel**: the bead's title/framing ("SESSION_REFS HAS NO CONSUMER")
predates this repo's own same-night investigation trail
(`polylogue-cijx.1`), which found and fixed the actual gap (a NameError
that crashed `read --view correlation`'s default GitHub-enrichment path
on every real ref). The bead's own literal AC — build and register a
real PF-D1 receipts demo, not the packet-contract stub `212.7` shipped —
remained unaddressed.

## Solution

**uh9l** (3 commits):
1. `refactor(sources)`: delete the dead
`orchestration_artifacts`/`orchestration_coverage`/`orchestration_parse_gaps`
computation from `discover_sidecars` and its supporting
`ClaudeOrchestrationCoverage`/`inventory_claude_orchestration_artifacts`
(kept
`parse_claude_orchestration_artifact`/`ClaudeOrchestrationArtifact`/`ClaudeOrchestrationFact`,
still used by the materializer).
2. `feat(readiness)`: `daemon/convergence_stages.py`'s `claude_workflow`
stage now persists each materialization summary into `ops.db`'s existing
generic `daemon_stage_events` table (no schema change).
`readiness/__init__.py` registers a new
`claude_workflow_materialization` `ReadinessCheck` that `polylogue
doctor` already surfaces via `get_readiness()`.

**xyel** (1 commit + a follow-up type fix):
3. `feat(demos)`: `.agent/demos/d1-receipts/` — resolves a real merged
PR (`#3282`) to its authoring/dispatch session
structurally via `session_refs`, then checks 4 individually falsifiable
PR-body claims against that session's own recorded blocks. 3 supported,
1 explicitly scored `not_supported` (a real, structurally-confirmed gap:
a 7-file `devtools test` invocation named in the PR body only ever
appears as prose, never as an executed command in this session). Also
surfaces a genuine finding: the resolved session is a merge-conductor (0
`Edit`/`Write` tool_use blocks), not the file-editing session.
4. `fix(tests)`: type-narrow a `dict[str, object]` read in the new
integration test that `devtools verify --quick`'s `dmypy`-backed mypy
step caught (the earlier plain `mypy polylogue` spot-check doesn't cover
`tests/`).

Beads updated in a final commit: closed `polylogue-uh9l` and
`polylogue-xyel` with full AC disposition in their close reasons; filed
`polylogue-nt5f` for the one honestly-named remainder (D1's public
seed-corpus variant isn't built — `session_refs` pull_request rows are a
provider-native capability the deterministic demo seed fixture doesn't
currently populate).

## Verification

- `devtools test tests/unit/sources/test_assembly_claude_code_history.py
tests/unit/sources/test_parsers_claude_code_artifacts.py
tests/unit/storage/test_archive_readiness.py
tests/unit/daemon/test_convergence_stages.py
tests/unit/cli/test_convergence_surface_contract.py
tests/unit/cli/test_check.py
tests/integration/test_claude_workflow_admission.py
tests/unit/devtools/test_demo_packet.py
tests/unit/demo/test_tour_packet_contract.py` → 191 passed
- `devtools lab policy demo-packet-registry` → "demo packet registry:
all 4 entries conform"
- `devtools lab policy bead-graph` → exit 0 (dup_labels=0, inversions=0,
malformed_wave=0)
- `devtools verify --quick` → 20/20 steps green (pre-push hook also ran
this clean)
- `devtools render all --check` → OK, no drift

Ref polylogue-uh9l, polylogue-xyel

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Added Claude Workflow readiness reporting that identifies missing
materialization records, unresolved gaps, and successful convergence.
* Added a verification demo documenting pull-request claims, supporting
evidence, counterexamples, limitations, and reproduction steps.
* **Bug Fixes**
* Improved archive readiness handling for missing, malformed, or
unavailable status data.
* Updated audit records with fixes, deferred work, and newly identified
reliability issues.
* **Refactor**
* Simplified Claude Code history processing by removing obsolete
orchestration artifact inventory and coverage reporting.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Sinity added a commit that referenced this pull request Jul 31, 2026
…faces (#3442)

## Summary

Three beads about polylogue evidence that is already captured and
persisted, but unreachable from any CLI/MCP/API surface. This PR wires
the genuine remainders: `file_edits`, `session_agent_policies`, and
`sessions.display_name` (the Claude Code "slug" wire field).

## Problem

- **polylogue-nua7**: `file_edits` (76,272 live rows),
`session_agent_policies` (402,879 rows), and `session_refs` (19,024
rows) each had a complete, tested read chain that terminated at
`repository/archive/sessions.py` with nothing above it. `session_refs`
was already wired by prior PRs #3425/#3431 (`read --view correlation`);
`file_edits` and `session_agent_policies` remained unreachable from any
CLI/MCP/API surface. Four helpers (`get_file_edit`,
`sync_get_file_edits_for_session`, `sync_get_session_refs`,
`sync_session_agent_policies_batch`) had zero references anywhere
outside their own `def`/`__all__` entry.
- **polylogue-cgfy**: the Claude Code `slug` wire field (1,500 sampled
occurrences) is captured into `ParsedSession.display_name` and persisted
into `sessions.display_name`, but neither `Session` nor `SessionSummary`
carried a `display_name` field at all — the value was dropped on every
read path. This is the fix for subagent rows rendering as
`<uuid-prefix>:agent-<suffix>` instead of a human name.
- **polylogue-pbuh**: AC6 asked for a live before/after census of
UUID-titled sessions and PR-link counts. Measured read-only against
`/realm/db/polylogue/index.db`.

## Solution

1. **`polylogue/api/archive.py`**: added `Polylogue.get_file_edits()` /
`get_agent_policies()`, mirroring the existing `get_session_events()`
reader pattern (returns `None` for an unknown session, an empty list for
a session with no matching rows).
2. **MCP** (`polylogue/mcp/server_cutover.py`): wired both into the
existing `get(ref, projection=...)` dispatcher as two new projection
values (`"file-edits"`, `"agent-policies"`) alongside the existing
`"events"` projection. No new tool or tool contract needed — same
six-tool `get` operation.
3. **CLI**: added `read --view file-edits` / `read --view
agent-policies`, following the existing `events`/`hooks` view pattern —
new handler module `polylogue/cli/read_views/file_edits.py`, registered
in `read_view_handlers.py`, `read_view_registry.py`, and the profile
metadata in `archive/viewport/profiles.py`. Also required adding entries
to `polylogue/surfaces/projection_spec.py`'s
`EvidenceFamily`/`READ_VIEW_PROJECTION_FAMILIES` maps — a separate
registry from the CLI handler registry that raises "unknown projection
view" if a view is missing there.
4. **Dead code**: deleted the four zero-reference helpers named in
nua7's audit, plus their now-dangling `sqlite3` imports where nothing
else used them.
5. **`display_name` reachability** (polylogue-cgfy), two independent
hydration paths:
- Async repository path (`storage/hydrators.py`): added `display_name`
to `Session`/`SessionSummary` (`archive/session/domain_models.py`) and
their runtime mixins' `display_title` property — now falls back
`user_title > title > display_name > id[:8]`.
- Sync `ArchiveStore` summary path that backs `find`/MCP `get(ref)`
default projection (`storage/sqlite/archive_tiers/archive.py`): added
`display_name` to `ArchiveSessionSummary`, selected it in
`read_summary`'s and `list_summaries`' SQL, and made it a title fallback
tier **above** the existing structural-label fallback (polylogue-cijx.4
decision 3) when no provider title exists — `display_name` is real
origin evidence (`title_source="origin"`), stronger than a derived
structural label. Wired through
`api/archive.py::_archive_summary_to_domain`.
6. **pbuh AC6 live census** (read-only against
`/realm/db/polylogue/index.db`, no code change — measurement only):
- 16,420 Claude Code sessions total; 14,717 carry
`title_source='unknown'` (raw-id/structural-label fallback before this
PR).
- 7,088 of those 16,420 sessions have a captured `display_name`; **6,585
of the 14,717 `title_source='unknown'` sessions (44.7%) now surface a
real slug-derived title** instead of a raw id or structural label — this
PR's concrete, measured improvement.
- `session_events` with `event_type='claude_pr_link'`: 19,140 rows
(unchanged by this PR — pr-link reader wiring was already resolved by
the earlier #3425/#3431 pass; see pbuh's own notes).
- `file_edits`: 76,272 rows; `session_agent_policies`: 402,879 rows;
`session_refs`: 19,024 rows (167 distinct sessions) — all now reachable
per point 1-3 above.

## AC disposition

**polylogue-nua7**: file_edits/session_agent_policies now have real CLI
(`read --view file-edits`/`agent-policies`) and MCP
(`get(projection=...)`) consumers; session_refs already had one (prior
PRs, verified unchanged). All four zero-reference helpers deleted.
Satisfied.

**polylogue-cgfy**: AC1 (per-key classification recorded in OriginSpec)
and AC4 (re-runnable committed enumeration) were already addressed by
prior passes per the bead's own notes — not re-verified in this pass,
out of this PR's declared surface. AC2's
`structuredPatch`/`originalFile`/`oldString` persistence was already
done (index v46); this PR adds the missing *read* side (file_edits
reachability, point 1-3 above) — the specific "cijx grading rises from
observed to checkpointed" wiring is a separate insights-model change
(`insights/session_commit.py`-adjacent, in this PR's avoid list) and
remains open, noted here as a genuine remainder. AC3 (slug reaches read
surfaces) is satisfied — see point 5 above, proven with a measured live
census (point 6) and end-to-end tests. AC5 (bytes/row counts per key
acquired) is partially covered by the live counts in point 6 but not a
full per-key report.

**polylogue-pbuh**: AC6 (before/after census) satisfied as a live
measurement (point 6) — this is the "after" state; no "before" baseline
exists since the parser fix landed in an earlier PR and no un-fixed
archive is available to compare against. AC1-AC5 were already resolved
in prior passes per the bead's own extensive notes; not re-verified
here, out of this PR's declared surface (parsers/claude,
assembly_claude_code.py, providers/claude_code*.py were avoided per the
task's own instructions).

## Verification

- `devtools test tests/unit/mcp/test_server_surfaces.py` — 11 passed,
including 3 new tests exercising `get(projection="file-edits")`,
`get(projection="agent-policies")`, and the default `get(ref)`
display_name fallback through the real MCP `tool_manager` entrypoint
against a real `ArchiveStore`-written session.
- `devtools test
tests/unit/cli/test_file_edits_and_agent_policies_views.py` — 2 passed,
full `CliRunner` invocation of `read --view file-edits`/`agent-policies`
against a real `ArchiveStore`-written session.
- `devtools test
tests/unit/storage/test_session_display_name_reaches_repository.py` — 2
passed, proving both `Session` and `SessionSummary` carry
`display_name`/`display_title` correctly through the real writer → async
repository chain, and that a real title still wins over the slug.
- `devtools test tests/unit/storage/test_unread_wire_batch_v46.py
tests/unit/storage/test_repository_agent_policies.py` — 13 passed (no
regression from dead-helper removal).
- `devtools test tests/unit/storage/test_title_source_queryable.py
tests/unit/storage/test_archive_tiers_write.py
tests/unit/storage/test_archive_tiers_archive.py
tests/unit/cli/test_query_exec_laws.py` — 243 passed (no regressions to
existing title/summary logic).
- `devtools test tests/unit/api/test_facade_contracts.py -k
"no_undiscovered or file_edits or agent_polic"` — 3 passed.
- Broader affected-area sweep: 28 test files that directly import the
touched domain modules
(`tests/unit/{api,archive,cli,core,insights,sources,storage,surfaces}/...`)
— 863 passed, 2 pre-existing unrelated failures
(`test_archive_tiers_api_raw_artifacts_read_source_tier`, 4 parametrized
cases of `test_filters_props.py::TestFilterDateParsing`) confirmed to
reproduce identically with this branch's changes reverted — stale
hardcoded date assertions / a clock-hygiene issue in
`archive/filter/filters.py`, untouched by this PR.
- `mypy --strict` on every touched file — no issues.
- `devtools verify --quick` — exit 0.
- `devtools render all --check` — all surfaces sync OK (regenerated
`docs/cli-reference.md`, `docs/plans/topology-target.yaml` for the new
`polylogue/cli/read_views/file_edits.py` module).

Not run: full `devtools verify --all` / whole-directory `tests/unit`
sweep (anti-pattern per repo convention — testmon wasn't seeded in this
worktree; relying on the targeted + affected-area sweeps above plus CI's
post-merge heavy `test` suite).

Ref polylogue-nua7, polylogue-cgfy, polylogue-pbuh
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant