Skip to content

feat: wire Claude Workflow gap readiness + ship real D1 receipts demo - #3438

Merged
Sinity merged 6 commits into
masterfrom
feature/cleanup/dead-coverage-and-session-refs
Jul 31, 2026
Merged

feat: wire Claude Workflow gap readiness + ship real D1 receipts demo#3438
Sinity merged 6 commits into
masterfrom
feature/cleanup/dead-coverage-and-session-refs

Conversation

@Sinity

@Sinity Sinity commented Jul 31, 2026

Copy link
Copy Markdown
Owner

Summary

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

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 (Sinity/polylogue#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

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.

Sinity added 5 commits July 31, 2026 10:06
Problem: assembly_claude_code.py:discover_sidecars computed
orchestration_artifacts/orchestration_coverage/orchestration_parse_gaps
(ClaudeOrchestrationCoverage) on every Claude Code ingest pass. Grepped the
whole tree: nothing reads these SidecarData keys except the struct's own
definition site and unit tests that assert against the struct directly.
enrich_session only ever consumes session_index/history_paste_index from the
returned dict. The genuinely running Claude Workflow gap tracker
(insights/claude_workflow_materializer.py, wired into
daemon/convergence_stages.py's claude_workflow stage) re-parses artifacts
independently from source.db's raw_artifacts and never consults this
SidecarData at all, so it fully supersedes this branch.

Solution: delete inventory_claude_orchestration_artifacts +
ClaudeOrchestrationCoverage and the discover_sidecars block that built the
three dead SidecarData fields. Keep parse_claude_orchestration_artifact,
ClaudeOrchestrationArtifact, ClaudeOrchestrationFact (production dependencies
of the materializer). Update the two touched test files accordingly.

Ref polylogue-uh9l

Verification: devtools test tests/unit/sources/test_assembly_claude_code_history.py tests/unit/sources/test_parsers_claude_code_artifacts.py -> 42 passed
Problem: the claude_workflow convergence stage (daemon/convergence_stages.py)
computes a fresh gap count from claude_workflow_materializer every daemon
pass but only logged it -- "claude-workflow: materialized runs=... gaps=%d" --
and discarded the summary otherwise. No readiness/repair surface consulted
it, so `polylogue doctor` could report healthy while Claude Workflow
materialization gaps existed (bd polylogue-uh9l, corrected closure of
polylogue-z9gh.6's AC2/AC5).

Solution: persist each materialization summary into ops.db's existing
generic daemon_stage_events table (no schema change --
record_daemon_stage_event already exists and is used by other stages) via a
new stage="claude_workflow" event carrying gap_count/gaps plus the run/call/
attempt counts. Add claude_workflow_materialization_status() in
storage/archive_readiness.py to read the latest event, and register a new
"claude_workflow_materialization" ReadinessCheck in run_archive_readiness()
(readiness/__init__.py) -- the function polylogue doctor already calls via
get_readiness()/CheckCommandResult, so no renderer changes were needed.

Verification exercises the real callers, not the materializer struct in
isolation: tests/integration/test_claude_workflow_admission.py's new test
calls make_claude_workflow_stage(...).execute() (the exact function the
daemon invokes every convergence pass) against the wf_54d4fb2e-841 fixture,
then reads the result back through get_readiness() (what `polylogue doctor`
calls). Corrupting one retained metadata sidecar makes the readiness check
flip OK->WARNING with the specific gap text surfaced in check.details --
proving the corruption-produces-a-visible-gap path (AC3) reaches the
readiness surface end-to-end, not just the materializer's own summary.

Ref polylogue-uh9l

Verification:
- devtools test tests/integration/test_claude_workflow_admission.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 -> 117 passed
- mypy --strict on touched files -> Success: no issues found in 7 source files
- devtools render all --check -> OK
Problem: polylogue-212.7's AC literally asked for "one existing demo (D1
receipts) re-emitted through the runner" but shipped only a trivial stub
fixture, filing polylogue-xyel to build the real thing. polylogue-xyel's
framing also carried a stale "session_refs has no consumer" premise from
before this repo's own 2026-07-31 investigation trail (polylogue-cijx.1):
PR #3425 wired typed session_refs pull_request evidence into
build_correlation_result, and PR #3431 fixed a pre-existing NameError in
the GitHub-enrichment path that made the default `read --view correlation
--github-api` invocation crash on every session carrying a ref.

Re-verified against current master (this branch's HEAD) before building:
session_refs is a live, wired consumer -- confirmed both by grep (only
insights/session_commit.py and insights/correlation_view.py consume it) and
by a direct run against /realm/db/polylogue (read-only) showing
`read --view correlation` resolving a real typed PR ref with
source=typed_session_ref and a disagreements entry naming the numbers the
regex heuristic path found that typed evidence doesn't corroborate. So the
consumer-wiring half of xyel's original framing is not the remaining work;
the bead's own AC (build and register a real D1 receipts packet) is.

Solution: .agent/demos/d1-receipts/ -- a real Demo Packet v2 (all 9
PACKET_FILENAMES) picking a real merged, agent-authored PR
(#3282) and resolving it to its authoring/dispatch session
structurally through session_refs (not regex/time-window), then checking 4
individually falsifiable sentences from the PR body against that session's
own recorded blocks:

- 3 of 4 claims are structurally supported (gh pr create body/URL match,
  devtools verify --quick per-step exit codes from the tool_result JSON,
  the rebuild_index.py test+commit pair).
- The 4th (a 7-file `devtools test` invocation named in the PR's own
  Verification section) is explicitly scored not_supported: that exact
  string only appears inside the gh-pr-create --body text itself, never as
  an executed command in this session -- a real, structurally-confirmed
  gap the packet surfaces rather than assumes away.
- A genuine methodological finding surfaced along the way: the resolved
  session is a merge-conductor (53 Bash + 3 Read tool_use blocks, 0
  Edit/Write) that orchestrates `git`/`gh`/`devtools` across several worker
  worktrees rather than the direct file-editing session -- documented in
  report.md's Counterexamples/Limits, not hidden.

Registered in .agent/demos/registry.json (mode=private, since it reads the
live archive + live GitHub history, not the public seed corpus).

Honest scope disposition: this ships the live-archive operator variant only.
212's own two-variant design (public seed-corpus + live-archive operator)
is not fully satisfied here -- session_refs pull_request rows are a
provider-native Claude Code capability the deterministic seed fixture
doesn't currently populate, so the public D1 variant remains unbuilt;
named explicitly as remaining scope in report.md's Limits section rather
than silently claimed done.

Ref polylogue-xyel

Verification:
- devtools lab policy demo-packet-registry -> "demo packet registry: all 4 entries conform"
- devtools test tests/unit/devtools/test_demo_packet.py tests/unit/demo/test_tour_packet_contract.py -> 32 passed
- devtools render all --check -> OK (no drift)
mypy --strict (via dmypy, which devtools verify --quick's mypy step
prefers when warm) flagged three call sites in the new readiness test
indexing a dict[str, object] and passing the object-typed result straight
to int()/iteration -- caught by the full verify gate, not the earlier
narrower `mypy polylogue` spot-check which excludes tests/.

Add _status_gap_count/_status_gaps helpers that isinstance-narrow before
use, matching the same pattern readiness/__init__.py's
_claude_workflow_materialization_check already uses for the same payload
shape.

Verification: dmypy run -- --no-error-summary -> clean; devtools test
tests/integration/test_claude_workflow_admission.py -> 2 passed.
polylogue-uh9l: closed -- Claude Workflow coverage/gap tracking now has
exactly one live computation, wired into a readiness surface with focused
tests (see the two feat commits on this branch).

polylogue-xyel: closed (--force over open blocker polylogue-cijx.1, whose
own notes say the specific concern it raised for this bead is resolved and
its remaining scope is unrelated -- see the close reason for the full
disposition) -- real D1 receipts demo packet built and registered.

polylogue-nt5f: filed as the named remainder -- the public seed-corpus D1
variant, which xyel's live-archive-only packet does not build.

Verification: devtools lab policy bead-graph -> exit 0 (dup_labels=0,
inversions=0, malformed_wave=0; missing_ac=144 is pre-existing repo-wide
noise, not introduced by this delta -- nt5f itself carries acceptance
criteria).
@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

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

Next review available in: 29 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: 92ae0e97-b6e7-45cf-98ab-7faffc55a05b

📥 Commits

Reviewing files that changed from the base of the PR and between 056c91e and 8a7b4d9.

📒 Files selected for processing (1)
  • polylogue/sources/parsers/claude/__init__.py
📝 Walkthrough

Walkthrough

The change adds a private D1 receipts demo and registers its evidence packet. It removes Claude orchestration coverage inventory, persists Claude Workflow materialization results, exposes them in archive readiness checks, adds related tests, and updates audit issue records.

Changes

D1 receipts demo

Layer / File(s) Summary
Receipt packet and verification contract
.agent/demos/d1-receipts/PROMPT.md, .agent/demos/d1-receipts/packet.json, .agent/demos/d1-receipts/finding.yaml, .agent/demos/d1-receipts/NON-CLAIMS.md
Defines PR-to-session correlation, claim verification, evidence controls, metadata, reproduction details, and scope limitations.
Receipt evidence and report
.agent/demos/d1-receipts/queries.ndjson, .agent/demos/d1-receipts/evidence.ndjson, .agent/demos/d1-receipts/checks.json, .agent/demos/d1-receipts/report.md
Adds structured queries, evidence records, check results, and the rendered verification report.
Demo registry wiring
.agent/demos/registry.json
Registers the private d1-receipts demo and its required primitives.

Claude Workflow materialization readiness

Layer / File(s) Summary
Remove orchestration coverage inventory
polylogue/sources/assembly.py, polylogue/sources/assembly_claude_code.py, polylogue/sources/parsers/claude/*, tests/unit/sources/*
Removes orchestration artifact inventory, coverage data, parse-gap reporting, and related test assertions while retaining native parser facts.
Persist workflow materialization status
polylogue/daemon/convergence_stages.py, polylogue/storage/archive_readiness.py
Records bounded Claude Workflow materialization counts and gaps in ops.db, then reads the latest stage event with normalized metadata.
Expose and validate readiness status
polylogue/readiness/__init__.py, tests/integration/test_claude_workflow_admission.py, tests/unit/storage/test_archive_readiness.py
Adds skip, warning, and success readiness checks and tests missing databases, persisted events, and missing-sidecar gaps.

Audit issue records

Layer / File(s) Summary
Record audit findings and dispositions
.beads/issues.jsonl
Adds audit findings and records closure notes, measured impacts, implemented follow-ups, and deferred work.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Convergence as Claude Workflow convergence
  participant OpsDB as ops.db
  participant Readiness as Archive readiness
  Convergence->>OpsDB: record materialization status and bounded gaps
  Readiness->>OpsDB: read latest claude_workflow stage event
  OpsDB-->>Readiness: return normalized status and timestamp
  Readiness-->>Readiness: emit SKIP, WARNING, or OK check
Loading

Possibly related PRs

  • Sinity/polylogue#2842: Adds a related evidence-receipt demo on a different implementation surface.
  • Sinity/polylogue#2912: Also changes polylogue/daemon/convergence_stages.py and uses the shared table_exists helper.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 53.85% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely identifies both primary changes: Claude Workflow readiness wiring and the D1 receipts demo.
Description check ✅ Passed The description covers the required summary, problem, solution, and verification details, with follow-up work also documented.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
⚔️ Resolve merge conflicts 💡
  • Resolve merge conflict in branch feature/cleanup/dead-coverage-and-session-refs
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/cleanup/dead-coverage-and-session-refs

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.

@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: 056c91e8c2

ℹ️ 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".

summary.attempt_count,
len(summary.gaps),
)
_record_claude_workflow_stage_event(archive_root(), summary)

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 Record receipts from every materialization path

The receipt is written only from ConvergenceStage.execute, but both configured ingest (pipeline/services/parsing_workflow.py:279-285) and direct archive ingest (pipeline/services/archive_ingest.py:333-342) materialize Claude Workflow graphs first. When convergence subsequently checks the same archive, claude_workflow_materialization_needed() returns false, so execute() and this recording call are skipped; consequently a normally ingested archive reports claude_workflow_materialization as SKIP and never surfaces its actual gaps. Persist the summary from the production materialization paths (or a shared wrapper) rather than only from convergence execution.

AGENTS.md reference: AGENTS.md:L139-L148

Useful? React with 👍 / 👎.

summary.attempt_count,
len(summary.gaps),
)
_record_claude_workflow_stage_event(archive_root(), summary)

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 Invalidate the receipt when rematerialization fails

When an archive has a previous clean receipt and a later source change causes materialize_claude_workflow_archive() to fail, execution reaches the catch block without recording anything, leaving the old clean row as the latest event. _claude_workflow_materialization_check() then continues to report OK even though the current graph is stale and convergence is failing. Record a failed/stale status for the attempted snapshot, or validate the receipt against current materialization freshness before treating it as healthy.

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai 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.

Actionable comments posted: 10

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.agent/demos/d1-receipts/PROMPT.md:
- Line 57: Update the sentence in PROMPT.md so the phrase before “inconvenience”
uses the article “an” rather than “a,” preserving the rest of the wording.
- Around line 21-26: Update the Markdown around the fenced SQL block in the
“Resolve PR → session structurally” section by adding a blank line immediately
before the opening fence and immediately after the closing fence, preserving the
SQL content and surrounding instructions.

In @.agent/demos/d1-receipts/report.md:
- Around line 46-48: Add reproducible receipt coverage for claims 1 and 3 in the
report: define committed queries and Reproduce commands that retrieve claim 1’s
gh pr create tool_use/tool_result blocks and claim 3’s test and follow-up git
commit blocks, and add the commit-block citation to evidence.ndjson alongside
the existing test citations. Re-run those commands and retain the supported
statuses only when they reproduce the stated results.

In @.beads/issues.jsonl:
- Line 504: Remove the duplicate issue record for polylogue-9dtr and retain
polylogue-bsi7 as the canonical issue. Mark the removed record as closed with a
duplicate resolution, preserving the canonical issue’s details and acceptance
criteria.
- Line 1091: Remove the stale polylogue-cijx.1 dependency from the issue’s
dependencies, or change its type from blocks to a non-blocking relation, and
update dependency_count to match so graph consumers no longer report
polylogue-xyel as blocked.
- Line 506: Align the issue’s remediation scope with its deletion predicate:
either add workflow_journal rows and their count to the described query and
acceptance criteria, or update the title and acceptance criteria to consistently
state 233 rows. Keep the artifact kinds, counts, and remediation language
consistent throughout the issue.
- Line 79: Resolve the issue record rather than changing implementation: mark
polylogue-8zzs as a duplicate/closed because PR `#3429` reportedly removed the
coverage_pct fallback. If retaining it as open, add specific post-PR `#3429`
regression evidence, including the introducing commit and a reproducible command
or snapshot showing the fallback returned.
- Line 100: The issue is closed even though acceptance criterion 3 remains
unperformed. Reopen polylogue-lzh8, or create and link an explicitly open
follow-up preserving the required index reset, operator scheduling, and
verification that all 172 contaminated rows are gone; update the issue metadata
accordingly without treating the remediation as complete.
- Line 1: Make the acceptance criteria internally consistent: in
.beads/issues.jsonl lines 1-1, require a regression test for _exact_estimate
only when provider-reported exact cost is retained, otherwise require removing
_exact_estimate and its tests; in .beads/issues.jsonl lines 82-82, remove the
requirement that origin_reported implies cost_usd is non-null, and instead
rename the state or define a separate invariant for cost presence.

In `@polylogue/daemon/convergence_stages.py`:
- Around line 361-384: Update _record_claude_workflow_stage_event to type
summary as ClaudeWorkflowMaterializationSummary, importing that type under
TYPE_CHECKING to preserve the existing lazy runtime import pattern. Replace the
getattr calls with direct access to run_count, call_count, attempt_count,
linked_session_count, unresolved_call_count, and gaps, while keeping the payload
and gap-limit behavior unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: b076d39b-831d-43d1-99d3-c3a8a896f62c

📥 Commits

Reviewing files that changed from the base of the PR and between ad069ae and 056c91e.

⛔ Files ignored due to path filters (1)
  • .agent/demos/d1-receipts/run.log is excluded by !**/*.log
📒 Files selected for processing (21)
  • .agent/demos/d1-receipts/NON-CLAIMS.md
  • .agent/demos/d1-receipts/PROMPT.md
  • .agent/demos/d1-receipts/checks.json
  • .agent/demos/d1-receipts/evidence.ndjson
  • .agent/demos/d1-receipts/finding.yaml
  • .agent/demos/d1-receipts/packet.json
  • .agent/demos/d1-receipts/queries.ndjson
  • .agent/demos/d1-receipts/report.md
  • .agent/demos/registry.json
  • .beads/issues.jsonl
  • polylogue/daemon/convergence_stages.py
  • polylogue/readiness/__init__.py
  • polylogue/sources/assembly.py
  • polylogue/sources/assembly_claude_code.py
  • polylogue/sources/parsers/claude/__init__.py
  • polylogue/sources/parsers/claude/orchestration.py
  • polylogue/storage/archive_readiness.py
  • tests/integration/test_claude_workflow_admission.py
  • 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
💤 Files with no reviewable changes (2)
  • tests/unit/sources/test_assembly_claude_code_history.py
  • polylogue/sources/assembly.py

Comment on lines +21 to +26
1. Resolve PR → session structurally:
```sql
SELECT session_id, repo, ref_number, url
FROM session_refs
WHERE kind = 'pull_request' AND repo = 'Sinity/polylogue' AND ref_number = 3282;
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add blank lines around the fenced SQL block.

Markdownlint reports MD031 for this fence. Add a blank line before and after the fence.

Proposed fix
 1. Resolve PR → session structurally:
+
    ```sql
    SELECT session_id, repo, ref_number, url
    FROM session_refs
    WHERE kind = 'pull_request' AND repo = 'Sinity/polylogue' AND ref_number = 3282;
    ```
+
    Cross-check the same resolution through the CLI's own read surface:
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
1. Resolve PR → session structurally:
```sql
SELECT session_id, repo, ref_number, url
FROM session_refs
WHERE kind = 'pull_request' AND repo = 'Sinity/polylogue' AND ref_number = 3282;
```
1. Resolve PR → session structurally:
🧰 Tools
🪛 markdownlint-cli2 (0.23.1)

[warning] 22-22: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 26-26: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.agent/demos/d1-receipts/PROMPT.md around lines 21 - 26, Update the Markdown
around the fenced SQL block in the “Resolve PR → session structurally” section
by adding a blank line immediately before the opening fence and immediately
after the closing fence, preserving the SQL content and surrounding
instructions.

Source: Linters/SAST tools

orchestrates `git`, `gh pr create`, and `devtools test`/`devtools verify`
invocations across those worktrees and stitches the result into one PR.

This is itself a real, useful finding, not a inconvenience to hide: the PR

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Fix the article before “inconvenience.”

Use “an inconvenience” because inconvenience starts with a vowel sound.

Proposed fix
-This is itself a real, useful finding, not a inconvenience to hide:
+This is itself a real, useful finding, not an inconvenience to hide:
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
This is itself a real, useful finding, not a inconvenience to hide: the PR
This is itself a real, useful finding, not an inconvenience to hide: the PR
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.agent/demos/d1-receipts/PROMPT.md at line 57, Update the sentence in
PROMPT.md so the phrase before “inconvenience” uses the article “an” rather than
“a,” preserving the rest of the wording.

Comment on lines +46 to +48
| 1 | This session authored/opened the PR | `tool_use` block runs `gh pr create --title "perf(storage): defer FTS repair off the live-ingest write path" --body "..."` with body text byte-identical to the live-fetched PR body; `tool_result` returns `https://github.com/Sinity/polylogue/pull/3282` | **supported** |
| 2 | "`devtools verify --quick` -- pass (ruff format/check, mypy, render all, topology/layering/...)" | `tool_use` runs `timeout 180 devtools verify --quick`; `tool_result` is a structured run-JSON with every step's `exit` field `0` (17 steps enumerated, `total_duration_s: 32.99`, top-level `exit_code: 0`) | **supported** (structural -- the exit codes, not a trusted "pass" word) |
| 3 | "`rebuild_index` bulk FTS materialization checkpoints progress (base for #3281, rebased here after that merge)" | `tool_use` runs `devtools test tests/unit/maintenance/test_rebuild_index_bulk_build.py` (+4 more files) in `/realm/worktrees/polylogue-membership-head-provenance`; `tool_result` pytest summary: `123 passed in 8.05s`; a following `git commit` in the same worktree stages exactly `polylogue/maintenance/rebuild_index.py` -- the one file this line's claim is about, matching the PR's own file diff (`polylogue/maintenance/rebuild_index.py 1 1`) | **supported** |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Add reproducible receipts for claims 1 and 3.

The committed queries and Reproduce commands do not retrieve the gh pr create input/result used for claim 1. They also do not retrieve the test and follow-up git commit blocks used for claim 3. In addition, evidence.ndjson cites the claim 3 test blocks but not the commit block stated here.

The packet therefore cannot re-run all three supported decisions from its committed evidence. Add the missing block citations, query definitions, and reproduction commands. Then retain the supported statuses only after those commands reproduce the stated results.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.agent/demos/d1-receipts/report.md around lines 46 - 48, Add reproducible
receipt coverage for claims 1 and 3 in the report: define committed queries and
Reproduce commands that retrieve claim 1’s gh pr create tool_use/tool_result
blocks and claim 3’s test and follow-up git commit blocks, and add the
commit-block citation to evidence.ndjson alongside the existing test citations.
Re-run those commands and retain the supported statuses only when they reproduce
the stated results.

Comment thread .beads/issues.jsonl Outdated
@@ -1,3 +1,4 @@
{"_type":"issue","id":"polylogue-gt1z","title":"Cost contract tests assert hand-built payloads for a dead provider-reported-cost path","description":"FALSE-GREEN AUDIT 2026-07-31 (finding F1+F2). Two test suites claim to verify that a provider-reported cost total is preserved verbatim. Neither calls any estimator.\n\nEVIDENCE (all grep-verified at 229c2739):\n- tests/unit/cost/test_contract_suite.py:109 defines a TEST-LOCAL _exact_estimate() that\n builds a CostEstimatePayload from literals (total_usd=1.25, provider_reported_usd=1.25,\n api_equivalent_usd=1.25, catalog_priced_usd=0.002).\n- :167 test_basis_fields_are_independent and :186 test_provider_reported_usd_preserved_exactly\n assert that this hand-built object has the fields it was just assigned.\n- tests/unit/insights/test_cost_basis_split.py:46-71 repeats the same shape independently.\n\nTHE PRODUCTION PATH IS DEAD:\n- polylogue/archive/semantic/pricing.py:628 defines _exact_estimate(). rg over polylogue/\n shows ZERO production callers. The only occurrences outside this definition are the\n test-local helper of the same name.\n- Its only would-be caller, _session_level_estimate() at pricing.py:793, is a stub:\n def _session_level_estimate(session): del session; return None\n- estimate_session_cost() (:808) calls it and only uses the result if status == 'exact',\n which can therefore never happen.\n- The provenance literal 'archive_session_reported_cost' that BOTH tests assert on appears\n nowhere in polylogue/ -- only in those two test files. No production path can emit it.\n\nWHY THIS IS P0 RATHER THAN A WEAK TEST: it is not that the assertions are weak, it is that\nthey document and 'verify' a cost-accounting behaviour the running system does not have.\nA reader (or agent) consulting these tests concludes provider-reported cost preservation is\nimplemented and covered. Given this repo's history of cost-accounting inflation defects\n(Codex 7.69x double-count; subscription-vs-API-equivalent confusion), a phantom-verified\ncost feature is exactly the wrong thing to have in the suite.\n\nAC:\n- Decide and record whether provider-reported exact cost is a real product requirement.\n- If yes: wire _exact_estimate into _session_level_estimate, and rewrite both tests to call\n estimate_session_cost() on a real Session so the assertion exercises production.\n- If no: delete _exact_estimate, the stub, and both tests -- do not leave the tests asserting\n a shape nothing produces (surgical renewal).\n- Either way a test must exist that fails when _exact_estimate's body is broken.\n- Audit the rest of tests/unit/cost/ for other hand-built-payload assertions.","status":"open","priority":0,"issue_type":"bug","owner":"ezo.dev@gmail.com","created_at":"2026-07-31T08:19:23Z","created_by":"Sinity","updated_at":"2026-07-31T08:19:23Z","dependency_count":0,"dependent_count":0,"comment_count":0}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Make each acceptance criterion consistent with its stated disposition.

Both records define completion conditions that cannot be satisfied under one of their own supported resolutions.

  • .beads/issues.jsonl#L1-L1: Require a regression test for _exact_estimate only if provider-reported exact cost remains a product requirement. If the chosen resolution deletes _exact_estimate, require deletion of its tests instead.
  • .beads/issues.jsonl#L82-L82: Do not require origin_reported => cost_usd IS NOT NULL while the issue evidence states that origin_reported represents token provenance without a provider-reported cost. Rename the state or define a separate cost-presence invariant.
📍 Affects 1 file
  • .beads/issues.jsonl#L1-L1 (this comment)
  • .beads/issues.jsonl#L82-L82
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.beads/issues.jsonl at line 1, Make the acceptance criteria internally
consistent: in .beads/issues.jsonl lines 1-1, require a regression test for
_exact_estimate only when provider-reported exact cost is retained, otherwise
require removing _exact_estimate and its tests; in .beads/issues.jsonl lines
82-82, remove the requirement that origin_reported implies cost_usd is non-null,
and instead rename the state or define a separate invariant for cost presence.

Comment thread .beads/issues.jsonl Outdated
@@ -75,8 +76,28 @@
{"_type":"issue","id":"polylogue-tf2.1","title":"Rerun forensics on current archive; price origin_reported providers","description":"Rerun scripts/agent_forensics.py against the current archive (v23+); price origin_reported providers via the vendored LiteLLM catalog (match last path segment); all-provider headline or explicitly-labeled per-provenance figures that cannot be misread; record deltas vs 06-27; verify chart SVGs render. Cache-inclusion must be disambiguated (Codex input INCLUDES cached ~96%; see bd memories). Also blocked on logical-session token attribution — the headline must not be double-counted.","notes":"Correction to close_reason monetary values: stored/provider-priced subset was $239,453.14; catalog API-equivalent was $318,650.88; origin_reported catalog estimate was $79,197.74. The original close_reason text lost dollar-prefixed digits due shell expansion, not measurement drift.","status":"closed","priority":0,"issue_type":"task","assignee":"Sinity","owner":"ezo.dev@gmail.com","created_at":"2026-07-03T04:31:33Z","created_by":"Sinity","updated_at":"2026-07-03T09:59:13Z","started_at":"2026-07-03T09:28:10Z","closed_at":"2026-07-03T09:59:02Z","close_reason":"Completed with blocker caveat preserved: scripts/agent_forensics.py now prices origin_reported rows through the shared vendored LiteLLM pricing catalog while preserving stored provenance; report separates stored/provider-priced cost from catalog API-equivalent estimates and carries logical-session/cache caveats instead of claiming final billing reconciliation. Regenerated current artifact at .agent/demos/agent-forensics against /home/sinity/.local/share/polylogue schema v23: 16,498 physical sessions, 4,142,175 messages, 356.5B tokens, ,453.14 stored/provider-priced subset, ,650.88 catalog API-equivalent, and ,197.74 origin_reported catalog estimate. SVG parse check passed for 9 charts; devtools test tests/unit/scripts/test_agent_forensics.py passed; devtools verify --quick passed run 20260703T095718Z-quick-753466-96559776; devloop-review clean. Remaining final-reconciliation blocker stays open as polylogue-4ts.2.","labels":["area:usage","campaign"],"dependencies":[{"issue_id":"polylogue-tf2.1","depends_on_id":"polylogue-4ts.2","type":"blocks","created_at":"2026-07-03T06:32:45Z","created_by":"Sinity","metadata":"{}"},{"issue_id":"polylogue-tf2.1","depends_on_id":"polylogue-sru.7","type":"blocks","created_at":"2026-07-03T06:31:33Z","created_by":"Sinity","metadata":"{}"},{"issue_id":"polylogue-tf2.1","depends_on_id":"polylogue-tf2","type":"parent-child","created_at":"2026-07-03T06:31:33Z","created_by":"Sinity","metadata":"{}"}],"dependency_count":2,"dependent_count":2,"comment_count":0}
{"_type":"issue","id":"polylogue-tf2","title":"Campaign: agent-forensics regeneration + all-provider repricing","description":"Regenerate the agent-forensics packet on the current archive with an honest all-provider headline. The 2026-06-27 report (546.6B tokens, $89,368 API-list equivalent, 216x cache amplification) is the most stranger-legible artifact on any shelf, but its numbers are pre-dedup stale and the headline prices only the priced-provenance subset (Claude Code cost_usd rows); Codex/ChatGPT/Gemini are origin_reported token counts with no dollar value (operator estimate ~$150K all-provider). Sequenced after claim-vs-evidence per operator direction 2026-07-02.","design":"Current slice design: turn the existing agent-forensics/cost headline into a product-backed all-provider repricing artifact. First inspect devtools/scripts and polylogue analyze surfaces for agent_forensics/cost code. Use active archive usage headline (detail=headline) for authoritative physical_session and logical_session_model_high_water token totals. Keep priced-provenance dollars and origin-reported token estimates separate: do not multiply every token by one blended price without a labeled lane. Add or reuse a shared pricing/projection helper so the demo artifact is regenerated from Polylogue product code, not ad hoc SQL. Acceptance for this slice: the generated agent-forensics artifact names archive root/schema, includes physical vs logical token grain, separates priced subset from origin-reported estimate lanes, gives reproduction commands, and has focused tests for any new repricing helper/surface.","acceptance_criteria":"Terminal state: regenerated forensics packet on the current archive with an honest all-provider headline (priced subset AND origin-reported estimate lanes separated), agent_forensics.py folded into polylogue analyze (tf2.2), artifact on the demo shelf with reproduction commands, cold-reader gate passed. Epic closes only when that artifact is recorded.","status":"closed","priority":0,"issue_type":"epic","assignee":"Sinity","owner":"ezo.dev@gmail.com","created_at":"2026-07-03T04:31:32Z","created_by":"Sinity","updated_at":"2026-07-03T19:06:44Z","started_at":"2026-07-03T18:47:23Z","closed_at":"2026-07-03T19:06:44Z","close_reason":"Completed: provider usage headline now exposes product-backed pricing lanes in polylogue analyze usage --detail headline, separating stored/provider-priced cost from catalog API-equivalent estimates for origin_reported rows. Regenerated the current .agent/demos/agent-forensics artifact against /home/sinity/.local/share/polylogue schema v23: physical-session tokens 395,320,980,423; logical high-water tokens 288,741,229,728; stored/provider-priced USD 243,392.189328; catalog API-equivalent USD 337,565.031618; priced lane 13,889 rows / 12,331 sessions / 12,650 matched rows; origin_reported lane 2,308 rows / 2,270 sessions / 2,302 matched rows. Verification: live polylogue --plain analyze usage --detail headline --format json --limit 0 wrote /realm/tmp/polylogue-usage-headline-pricing-current.json; devtools test tests/unit/storage/test_provider_usage_report.py tests/unit/cli/test_diagnostics.py passed 23 tests; devtools verify --quick passed run 20260703T190553Z-quick-2226137-d91d4e8f; devtools workspace demo-shelf --json reported ok. Non-claim preserved: this is not final billing reconciliation and physical/logical token grains stay explicitly separated.","labels":["area:usage","campaign","size:M","spine"],"dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"polylogue-sru","title":"Campaign: claim-vs-evidence report to finding-grade","description":"Terminal state: an externally publishable finding ('how often do coding agents proceed past failed tool calls, by model/tool') with stated sample frame, calibrated markers, benign/consequential split, seeded stranger-runnable reproduction, and a passed cold-reader gate. Slice closure is NOT campaign closure; this epic stays top-of-frame until its terminal state is recorded.\\n\\nState as of 2026-07-03 after calibrated active-archive regeneration: archive root /home/sinity/.local/share/polylogue, index schema v23, 41,886 structured failures total, 5,000 origin-stratified failures inspected (3,746 claude-code-session, 1,247 codex-session, 7 claude-ai-export), 100 unpaired structured failures. Marker vocabulary was tightened to avoid broad issue/fix/block/gitignored false positives. Immediate next-turn totals: acknowledged=420, silent_proceed=1,205, ambiguous=3,375 (2,624 wordless tool continuations; 751 prose without marker). Lower-bound silent rate is 24.1%; among classified immediate next turns, silent rate is 74.2%. Next-3 sensitivity window, stopping before the next user message, finds 302 acknowledgments that appear only after the next turn; window3 silent lower bound is 37.0%. Calibration: 50 hand-labeled immediate-next-turn rows, acknowledged-marker precision=1.0, recall=0.8421052631578947, invalid rows=0. Artifact: .agent/demos/claim-vs-evidence/claim-vs-evidence.report.json.","notes":"2026-07-03 update: methodology package is now cold-read gated. .agent/demos/claim-vs-evidence contains aggregate live evidence, public-summary.json, PUBLIC_REPRODUCTION.md, COLD_READER_GATE.md, and COLD_READ_RESULT.md. Seeded reproduction is meaningful, not empty: 4 structured failures, 2 acknowledged follow-ups, 2 silent-proceed follow-ups, 0 unpaired. Cold-reader subagent PASS recovered claim/non-claim, sample frame, rates, calibration, caveats, and reproduction commands from the artifact directory only. Remaining campaign child: polylogue-sru.1 productizes action-unit outcome/followup_class capability.","status":"closed","priority":0,"issue_type":"epic","owner":"ezo.dev@gmail.com","created_at":"2026-07-03T04:31:26Z","created_by":"Sinity","updated_at":"2026-07-03T09:28:09Z","closed_at":"2026-07-03T09:28:09Z","close_reason":"Completed: all seven campaign children are closed. The claim-vs-evidence finding now has bounded sample-frame reporting, calibrated marker precision/recall, handler-class and next-3 sensitivity splits, meaningful seeded reproduction, cold-reader PASS, and productized action-unit followup_class/followup_message_ref query capability. Current artifact lives under .agent/demos/claim-vs-evidence and was regenerated against /home/sinity/.local/share/polylogue schema v23.","labels":["area:substrate","campaign"],"dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"polylogue-8zzs","title":"CLI status fabricates 'FTS: 100.0% indexed' from readiness boolean when coverage_pct is null","description":"Surface-coherence audit 2026-07-31 — the live 'ops status says FTS 100% while query path says incomplete' incident, CLI-render site. polylogue/cli/commands/status.py:1273-1276: `pct = _safe_float(fts.get(\"coverage_pct\"), default=100.0 if fts.get(\"messages_ready\") else 0.0)` then prints `FTS: [green]100.0% indexed`. Live evidence: `polylogue ops status --json --full` has fts_readiness.coverage_pct=null, message_indexed_count=null, message_indexable_count=null, coverage_exact=false, surfaces.messages_fts source_rows=1 indexed_rows=1 (index.db fts_freshness_state row: detail='bounded global messages_fts repair completed; exact counts skipped') — yet the human status line asserts the precise measured-looking claim \"FTS: 100.0% indexed\" fabricated from the messages_ready boolean. Same snapshot: component_readiness.search.counts all None, search.collection.state=stale. Sibling of polylogue-oitx (daemon/fts_status.py fabricated coverage class — filed by the 2026-07-31 silent-degradation audit); this bead covers the CLI presentation layer: when coverage_pct is null/not measured, render 'structurally ready (coverage not measured)' or similar — never a fabricated percentage.\n","status":"open","priority":1,"issue_type":"task","owner":"ezo.dev@gmail.com","created_at":"2026-07-31T08:40:26Z","created_by":"Sinity","updated_at":"2026-07-31T08:40:26Z","labels":["cli","surface-coherence"],"dependency_count":0,"dependent_count":0,"comment_count":0}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Do not reopen a fixed FTS presentation defect without regression evidence.

Line 101 states that PR #3429 removed this exact coverage_pct fallback and changed unmeasured output to coverage unknown. This new open issue asserts the pre-fix implementation without identifying a post-fix regression.

Close this as a duplicate, or add the commit and reproduction that proves the fallback returned after PR #3429.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.beads/issues.jsonl at line 79, Resolve the issue record rather than
changing implementation: mark polylogue-8zzs as a duplicate/closed because PR
`#3429` reportedly removed the coverage_pct fallback. If retaining it as open, add
specific post-PR `#3429` regression evidence, including the introducing commit and
a reproducible command or snapshot showing the fallback returned.

Comment thread .beads/issues.jsonl Outdated
{"_type":"issue","id":"polylogue-zqph","title":"Repair pass for existing empty-session phantom rows (polylogue-9ykn dataset cleanup)","description":"Follow-up to polylogue-9ykn: the ingest-time classifier fix (looks_like_record_entry / looks_like_code\ntype-only overmatch, and unifying the live-ingest classify_artifact gate with the\nrevision_backfill.py replay/rebuild gate) stops NEW phantom sessions of the\nconversation_relationships.jsonl / problems_index.jsonl / graph-edge-index shape from being\ncreated going forward, on both the live daemon path and any polylogue ops reset --index rebuild.\n\nIt deliberately does NOT delete or touch any of the existing ~5,257 empty-session rows already in\nthe live archive (per explicit operator scoping: dataset repair is a separate, carefully-scoped\nconcern). This bead tracks that repair pass.\n\nWhat the repair needs to do, precisely (do not blanket-delete via repair_empty_sessions /\n`polylogue check --cleanup` -- see polylogue-ne6k, which found that predicate cannot distinguish\na legitimately-empty session, e.g. the 832 the 2026-07-22 hook-inflation postmortem chose to\nretain, from corruption debris):\n\n1. Re-run classification (the now-fixed classify_artifact / looks_like_record_entry /\n looks_like_code) against each existing empty session's ORIGINAL raw_sessions source_path +\n raw bytes to determine: would this record be admitted as a session under the current\n classifier, or refused?\n2. For rows the current classifier would refuse (the conversation_relationships.jsonl-shaped\n phantoms, and any other now-caught non-conversational content): these are safe candidates for\n targeted reclassification/removal from index.db (rebuildable tier) -- NOT source.db (durable\n raw evidence must be retained per the repo's schema regime).\n3. For rows the current classifier would still admit (genuinely-empty-but-valid sessions, e.g. a\n real Claude Code/Codex session that has zero turns so far, or the 832 retained browser-capture\n stubs): leave untouched.\n4. Needs explicit operator sign-off before running against the live archive (per CLAUDE.md's\n destructive-operation and schema-regime discipline) -- this bead should NOT be closed by an\n agent unilaterally running the repair.\n\nEvidence base: polylogue-9ykn's own measurement (5,255 zero-message sessions, 22.6% of the\n23,296-session archive at measurement time; 5,193 claude-code-session, 46 claude-ai-export, 17\ncodex-session) plus polylogue-gvgi's single dominant phantom (conversation_relationships.jsonl,\n96,748 empty messages, ~95% of the archive's zero-block messages -- tracked/repaired separately\nper gvgi's own AC, coordinate rather than duplicate).","status":"open","priority":1,"issue_type":"task","owner":"ezo.dev@gmail.com","created_at":"2026-07-31T06:27:42Z","created_by":"Sinity","updated_at":"2026-07-31T06:27:42Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"polylogue-lzh8","title":"Declare SEMANTIC_REPARSE index bump for Claude Workflow artifact classification (PR #3088)","description":"Investigation 2026-07-31 (worktree agent-a7335b82eed35c7cf), triggered by\noperator report that Claude Code Workflow artifacts appear BOTH normalized\nAND independently ingested raw as empty sessions.\n\nFINDING: the classification code is already correct. polylogue/archive/\nartifact_taxonomy/runtime.py:classify_artifact_path consults OriginSpec's\nartifact_rules (polylogue/sources/origin_specs.py, added by 1e0246d77 / PR\n#3088, \"admit Claude Workflow artifacts through OriginSpec\", 2026-07-18) and\ncorrectly returns parse_as_session=False for workflow_run_snapshot,\nworkflow_journal, agent_sidecar_meta, and adopt_manifest artifact kinds.\nVerified directly against the live paths (python3 -c\n\"classify_artifact_path(...)\") -- current code classifies them correctly.\n\nBut 1e0246d77 changed session/fact classification semantics for an already-\nrunning archive WITHOUT declaring an INDEX_SCHEMA_VERSION bump in\npolylogue/storage/sqlite/lifecycle.py (checked: no lifecycle.py/index.py\nchange in that commit, and no v33-v47 IndexDeltaDeclaration references\npolylogue-2qx.2 or the Workflow admission PR). Per docs/architecture (\"Schema\nregimes\"), only a declared SEMANTIC_REPARSE delta routes an index.db through\n`polylogue ops reset --index \u0026\u0026 polylogued run`; a semantic parser change\nwith no declared bump leaves already-materialized wrong-classification rows\nuntouched forever, because the daemon's fast-forward convergence has no\nsignal that anything changed.\n\nMEASURED LIVE IMPACT (index.db read-only query, 2026-07-31):\n zero-message claude-code-session rows total: 5,193\n of these, joined to a source_path under a `workflows/` artifact family: 172\n agent_sidecar_meta (subagents/workflows/*/agent-*.meta.json): 164\n workflow_run_snapshot (workflows/wf_*.json): 7\n other (workflow_journal / adopt_manifest): 1\n acquired_at_ms range for these 172: 2026-07-14 10:52 UTC .. 2026-07-26\n 19:18 UTC -- i.e. ALL acquired while the deployed daemon build predated\n the fix. The sinnix flake's polylogue input only advanced to a revision\n containing 1e0246d77 on 2026-07-29 (flake.lock lastModified\n 1785367887 = 2026-07-29 23:31 UTC; `git merge-base --is-ancestor` confirms\n 1e0246d77 is an ancestor of the pinned rev 5e23e6a). So this is deploy-lag\n contamination the fix code cannot self-heal without a reparse trigger, not\n a currently-active defect in the shipped classification logic.\n\nSeparately, polylogue-omsw's tool-result-sidecar and file-history-snapshot\npopulations are a DIFFERENT, still-open acquisition-scope gap (not covered\nby this bead) -- do not conflate the two when scoping remediation.\n\nDO NOT execute the reset live from this investigation; this bead exists to\nmake the repair describable and consented rather than silent. Per this\nrepo's ops.db/index.db durability rules, `polylogue ops reset --index` is a\ndisposable-tier rebuild, not durable-data loss, but it is still a\nconsequential live-daemon action (extended downtime rebuilding ~20K\nsessions) that needs explicit operator scheduling, not an agent-triggered\nversion bump buried in an unrelated PR.\n","acceptance_criteria":"1. polylogue/storage/sqlite/lifecycle.py gets a new IndexDeltaDeclaration bumping INDEX_SCHEMA_VERSION with classes=(SEMANTIC_REPARSE,), whose comment names 1e0246d77/#3088 as the retroactive semantic change being captured and cites the measured live-impact counts. 2. The bump lands in a PR whose body explicitly tells the operator a 'polylogue ops reset --index \u0026\u0026 polylogued run' is now required, so it is scheduled deliberately (not silently triggered by routine deploy). 3. After the rebuild, the 172+ contaminated sessions reclassify to their correct non-session disposition (verified by re-running the same index.db query this bead's evidence used and confirming zero remain). 4. devtools lab policy schema-versioning stays green.","status":"open","priority":1,"issue_type":"bug","owner":"ezo.dev@gmail.com","created_at":"2026-07-31T05:59:40Z","created_by":"Sinity","updated_at":"2026-07-31T05:59:40Z","dependencies":[{"issue_id":"polylogue-lzh8","depends_on_id":"polylogue-2qx.2","type":"related","created_at":"2026-07-31T07:59:51Z","created_by":"Sinity","metadata":"{}"},{"issue_id":"polylogue-lzh8","depends_on_id":"polylogue-9ykn","type":"related","created_at":"2026-07-31T07:59:50Z","created_by":"Sinity","metadata":"{}"},{"issue_id":"polylogue-lzh8","depends_on_id":"polylogue-omsw","type":"related","created_at":"2026-07-31T07:59:50Z","created_by":"Sinity","metadata":"{}"}],"dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"polylogue-lzh8","title":"Declare SEMANTIC_REPARSE index bump for Claude Workflow artifact classification (PR #3088)","description":"Investigation 2026-07-31 (worktree agent-a7335b82eed35c7cf), triggered by\noperator report that Claude Code Workflow artifacts appear BOTH normalized\nAND independently ingested raw as empty sessions.\n\nFINDING: the classification code is already correct. polylogue/archive/\nartifact_taxonomy/runtime.py:classify_artifact_path consults OriginSpec's\nartifact_rules (polylogue/sources/origin_specs.py, added by 1e0246d77 / PR\n#3088, \"admit Claude Workflow artifacts through OriginSpec\", 2026-07-18) and\ncorrectly returns parse_as_session=False for workflow_run_snapshot,\nworkflow_journal, agent_sidecar_meta, and adopt_manifest artifact kinds.\nVerified directly against the live paths (python3 -c\n\"classify_artifact_path(...)\") -- current code classifies them correctly.\n\nBut 1e0246d77 changed session/fact classification semantics for an already-\nrunning archive WITHOUT declaring an INDEX_SCHEMA_VERSION bump in\npolylogue/storage/sqlite/lifecycle.py (checked: no lifecycle.py/index.py\nchange in that commit, and no v33-v47 IndexDeltaDeclaration references\npolylogue-2qx.2 or the Workflow admission PR). Per docs/architecture (\"Schema\nregimes\"), only a declared SEMANTIC_REPARSE delta routes an index.db through\n`polylogue ops reset --index \u0026\u0026 polylogued run`; a semantic parser change\nwith no declared bump leaves already-materialized wrong-classification rows\nuntouched forever, because the daemon's fast-forward convergence has no\nsignal that anything changed.\n\nMEASURED LIVE IMPACT (index.db read-only query, 2026-07-31):\n zero-message claude-code-session rows total: 5,193\n of these, joined to a source_path under a `workflows/` artifact family: 172\n agent_sidecar_meta (subagents/workflows/*/agent-*.meta.json): 164\n workflow_run_snapshot (workflows/wf_*.json): 7\n other (workflow_journal / adopt_manifest): 1\n acquired_at_ms range for these 172: 2026-07-14 10:52 UTC .. 2026-07-26\n 19:18 UTC -- i.e. ALL acquired while the deployed daemon build predated\n the fix. The sinnix flake's polylogue input only advanced to a revision\n containing 1e0246d77 on 2026-07-29 (flake.lock lastModified\n 1785367887 = 2026-07-29 23:31 UTC; `git merge-base --is-ancestor` confirms\n 1e0246d77 is an ancestor of the pinned rev 5e23e6a). So this is deploy-lag\n contamination the fix code cannot self-heal without a reparse trigger, not\n a currently-active defect in the shipped classification logic.\n\nSeparately, polylogue-omsw's tool-result-sidecar and file-history-snapshot\npopulations are a DIFFERENT, still-open acquisition-scope gap (not covered\nby this bead) -- do not conflate the two when scoping remediation.\n\nDO NOT execute the reset live from this investigation; this bead exists to\nmake the repair describable and consented rather than silent. Per this\nrepo's ops.db/index.db durability rules, `polylogue ops reset --index` is a\ndisposable-tier rebuild, not durable-data loss, but it is still a\nconsequential live-daemon action (extended downtime rebuilding ~20K\nsessions) that needs explicit operator scheduling, not an agent-triggered\nversion bump buried in an unrelated PR.\n","acceptance_criteria":"1. polylogue/storage/sqlite/lifecycle.py gets a new IndexDeltaDeclaration bumping INDEX_SCHEMA_VERSION with classes=(SEMANTIC_REPARSE,), whose comment names 1e0246d77/#3088 as the retroactive semantic change being captured and cites the measured live-impact counts. 2. The bump lands in a PR whose body explicitly tells the operator a 'polylogue ops reset --index \u0026\u0026 polylogued run' is now required, so it is scheduled deliberately (not silently triggered by routine deploy). 3. After the rebuild, the 172+ contaminated sessions reclassify to their correct non-session disposition (verified by re-running the same index.db query this bead's evidence used and confirming zero remain). 4. devtools lab policy schema-versioning stays green.","status":"closed","priority":1,"issue_type":"bug","assignee":"Sinity","owner":"ezo.dev@gmail.com","created_at":"2026-07-31T05:59:40Z","created_by":"Sinity","updated_at":"2026-07-31T08:18:10Z","started_at":"2026-07-31T07:51:22Z","closed_at":"2026-07-31T08:18:10Z","close_reason":"Declared the missing v48 SEMANTIC_REPARSE IndexDeltaDeclaration for #3088/1e0246d77 (storage/sqlite/lifecycle.py + INDEX_SCHEMA_VERSION bump in archive_tiers/index.py), citing the measured live-impact counts (172 zero-message sessions: 164 agent_sidecar_meta + 7 workflow_run_snapshot + 1 other). AC1-2 satisfied (declaration lands, PR body states the operator command required). AC3 (172 rows reclassify to zero) is explicitly deferred -- NOT executed per this bead's own DO-NOT-EXECUTE instruction; the operator must run 'polylogue ops reset --index \u0026\u0026 polylogued run' deliberately. AC4 (devtools lab policy schema-versioning stays green) verified. Also investigated why the lint didn't catch PR #3088's original undeclared bump: it only checks declaration-table completeness against the CURRENT INDEX_SCHEMA_VERSION constant, never inspects classification source files, so it structurally cannot detect a missing bump, only an undeclared existing one. Filed polylogue-qs4b to design a real fix (content-fingerprint of classification tables) rather than rushing one in; explained in PR body.","dependencies":[{"issue_id":"polylogue-lzh8","depends_on_id":"polylogue-2qx.2","type":"related","created_at":"2026-07-31T07:59:51Z","created_by":"Sinity","metadata":"{}"},{"issue_id":"polylogue-lzh8","depends_on_id":"polylogue-9ykn","type":"related","created_at":"2026-07-31T07:59:50Z","created_by":"Sinity","metadata":"{}"},{"issue_id":"polylogue-lzh8","depends_on_id":"polylogue-omsw","type":"related","created_at":"2026-07-31T07:59:50Z","created_by":"Sinity","metadata":"{}"}],"dependency_count":0,"dependent_count":0,"comment_count":0}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Keep the unperformed live remediation as open tracked work.

The close reason explicitly defers acceptance criterion 3. The required rebuild and verification that the 172 contaminated rows are gone has not occurred. A closed status can cause planning tools to treat that remediation as complete.

Reopen this issue, or move acceptance criterion 3 into an explicitly linked open follow-up with the same count query and operator-action requirement.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.beads/issues.jsonl at line 100, The issue is closed even though acceptance
criterion 3 remains unperformed. Reopen polylogue-lzh8, or create and link an
explicitly open follow-up preserving the required index reset, operator
scheduling, and verification that all 172 contaminated rows are gone; update the
issue metadata accordingly without treating the remediation as complete.

Comment thread .beads/issues.jsonl Outdated
{"_type":"issue","id":"polylogue-pfdf","title":"Attachment backlog: 7,376 of 9,289 attachments (79%) still acquisition_status='unfetched'","description":"Forensics 2026-07-31. attachments: 1,913 acquired vs 7,376 unfetched. The #2469 fix (real _acquire_attachment_blob) stores true blobs going forward; the historical backlog was never backfilled and is static. Sources may still have the bytes (exports re-acquired regularly).\nRepro: SELECT acquisition_status, count(*) FROM attachments GROUP BY 1;\nAC: backfill pass over unfetched attachments where the source payload still contains the bytes; unrecoverable ones marked distinctly from 'unfetched'.","status":"open","priority":2,"issue_type":"task","owner":"ezo.dev@gmail.com","created_at":"2026-07-31T08:22:13Z","created_by":"Sinity","updated_at":"2026-07-31T08:22:13Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"polylogue-bsi7","title":"test_web_reader agent-coordination test is order-dependent: passes alone, fails in a wide selection","description":"FALSE-GREEN AUDIT 2026-07-31 (finding F6). MEASURED.\n\ntests/unit/daemon/test_web_reader.py TestReaderSearchState::test_agent_coordination_endpoint_uses_shared_payload\nfails with KeyError 'root' at test_web_reader.py:894 when run as part of a 31-file selection,\nand PASSES when run alone.\n\n isolated: pytest tests/unit/daemon/test_web_reader.py -k agent_coordination\n -\u003e 3 passed, 174 deselected in 4.50s\n in a 31-file selection (all tests/unit files referencing MaterialOrigin)\n -\u003e FAILED with KeyError 'root'; reproduced 5 consecutive times\n\nThis is cross-test state leakage, not a flake: deterministic in both directions.\n\nWHY IT MATTERS: the default gate is devtools verify with pytest-testmon affected-selection,\nwhich rarely runs this file together with that set, so the pollution is invisible to the\nnormal pre-merge gate. It surfaces only in a broad run.\n\nHOW IT WAS FOUND: it produced a FALSE RED in my own mutation harness. v1 ran pytest with -x\nand read the exit code; this pre-existing failure tripped -x on every run, so all five planted\nmutations looked caught when the runs proved nothing. The harness auditing for false greens\ngenerated a false red.\n\nSTANDING RULE: a mutation-testing or bisect harness must difference against a measured\nbaseline set of failing node ids. An exit code is not evidence, and -x makes any pre-existing\nfailure masquerade as the signal.\n\nAC:\n- Identify the polluting module/fixture (bisect the 31-file selection).\n- Fix the leak at its source, not by reordering or by adding a fixture-reset to the victim.\n- Check whether the 'root' key comes from module-global or process-global state another test\n mutates.\n- Record whether other order-dependent failures exist in a broad run.","status":"open","priority":2,"issue_type":"bug","owner":"ezo.dev@gmail.com","created_at":"2026-07-31T08:21:55Z","created_by":"Sinity","updated_at":"2026-07-31T08:21:55Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"polylogue-vid0","title":"1,413 unresolved subagent links; 58 of 85 distinct targets already acquired as raws but never parsed","description":"Forensics 2026-07-31. session_links: 9,333 total, 1,426 unresolved (1,413 subagent: 1,275 claude-code + 138 codex; 12 hermes branch; 1 continuation). The 1,413 subagent rows point at 85 distinct dst_native_ids; 58 of those exist in raw_sessions (acquired but never parsed into sessions) — recoverable by parsing; 27 are absent from capture entirely.\nRepro: SELECT count(*), count(DISTINCT dst_native_id) FROM session_links WHERE resolved_dst_session_id IS NULL AND link_type='subagent';\nAC: the 58 recoverable targets parse and resolve; the 27 unrecoverable are classified (deleted-before-capture vs still-pending) and the census documented.","status":"open","priority":2,"issue_type":"task","owner":"ezo.dev@gmail.com","created_at":"2026-07-31T08:21:46Z","created_by":"Sinity","updated_at":"2026-07-31T08:21:46Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"polylogue-9dtr","title":"test_web_reader agent-coordination test is order-dependent: passes alone, fails in a wide selection","description":"FALSE-GREEN AUDIT 2026-07-31 (finding F6). MEASURED.\n\ntests/unit/daemon/test_web_reader.py::TestReaderSearchState::test_agent_coordination_endpoint_uses_shared_payload\nfails with KeyError: 'root' at test_web_reader.py:894 when run as part of a 31-file selection,\nand PASSES when run alone.\n\n isolated: pytest tests/unit/daemon/test_web_reader.py -k agent_coordination\n -\u003e 3 passed, 174 deselected in 4.50s\n in a 31-file selection (all tests/unit files referencing MaterialOrigin)\n -\u003e FAILED ... KeyError: 'root'\n reproduced 5 consecutive times\n\nThis is cross-test state leakage, not a flake: it is deterministic in both directions.\n\nWHY IT MATTERS BEYOND THE ONE TEST: the default gate is 'devtools verify' with pytest-testmon\naffected-selection, which rarely runs this file together with that set, so the pollution is\ninvisible to the normal pre-merge gate. It surfaces only in a broad run.\n\nHOW IT WAS FOUND (worth recording): it produced a FALSE RED in my own mutation harness. v1 ran\npytest with -x and read the exit code; this pre-existing failure tripped -x on every run, so\nall five planted mutations looked 'caught' when the runs proved nothing. The harness auditing\nfor false greens generated a false red.\n\nSTANDING RULE that came out of it: a mutation-testing or bisect harness must difference against\na measured baseline set of failing node ids. An exit code is not evidence, and -x makes any\npre-existing failure masquerade as the signal.\n\nAC:\n- Identify the polluting module/fixture (bisect the 31-file selection).\n- Fix the leak at its source rather than by reordering or by adding a fixture-reset to the\n victim test.\n- Consider whether the 'root' key is being consumed from module-global or process-global state\n that another test mutates.\n- Record whether other order-dependent failures exist in a broad run (devtools verify --all is\n ~3min/12725 tests per project memory, so a full-order check is affordable).","status":"open","priority":2,"issue_type":"bug","owner":"ezo.dev@gmail.com","created_at":"2026-07-31T08:21:15Z","created_by":"Sinity","updated_at":"2026-07-31T08:21:15Z","dependency_count":0,"dependent_count":0,"comment_count":0}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Remove the duplicate test-leak issue.

This record duplicates polylogue-bsi7 at line 502. Both records name the same test, the same KeyError: 'root', the same 31-file reproduction, and the same acceptance criteria.

Keep one canonical issue and close the other as a duplicate.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.beads/issues.jsonl at line 504, Remove the duplicate issue record for
polylogue-9dtr and retain polylogue-bsi7 as the canonical issue. Mark the
removed record as closed with a duplicate resolution, preserving the canonical
issue’s details and acceptance criteria.

Comment thread .beads/issues.jsonl Outdated
{"_type":"issue","id":"polylogue-vid0","title":"1,413 unresolved subagent links; 58 of 85 distinct targets already acquired as raws but never parsed","description":"Forensics 2026-07-31. session_links: 9,333 total, 1,426 unresolved (1,413 subagent: 1,275 claude-code + 138 codex; 12 hermes branch; 1 continuation). The 1,413 subagent rows point at 85 distinct dst_native_ids; 58 of those exist in raw_sessions (acquired but never parsed into sessions) — recoverable by parsing; 27 are absent from capture entirely.\nRepro: SELECT count(*), count(DISTINCT dst_native_id) FROM session_links WHERE resolved_dst_session_id IS NULL AND link_type='subagent';\nAC: the 58 recoverable targets parse and resolve; the 27 unrecoverable are classified (deleted-before-capture vs still-pending) and the census documented.","status":"open","priority":2,"issue_type":"task","owner":"ezo.dev@gmail.com","created_at":"2026-07-31T08:21:46Z","created_by":"Sinity","updated_at":"2026-07-31T08:21:46Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"polylogue-9dtr","title":"test_web_reader agent-coordination test is order-dependent: passes alone, fails in a wide selection","description":"FALSE-GREEN AUDIT 2026-07-31 (finding F6). MEASURED.\n\ntests/unit/daemon/test_web_reader.py::TestReaderSearchState::test_agent_coordination_endpoint_uses_shared_payload\nfails with KeyError: 'root' at test_web_reader.py:894 when run as part of a 31-file selection,\nand PASSES when run alone.\n\n isolated: pytest tests/unit/daemon/test_web_reader.py -k agent_coordination\n -\u003e 3 passed, 174 deselected in 4.50s\n in a 31-file selection (all tests/unit files referencing MaterialOrigin)\n -\u003e FAILED ... KeyError: 'root'\n reproduced 5 consecutive times\n\nThis is cross-test state leakage, not a flake: it is deterministic in both directions.\n\nWHY IT MATTERS BEYOND THE ONE TEST: the default gate is 'devtools verify' with pytest-testmon\naffected-selection, which rarely runs this file together with that set, so the pollution is\ninvisible to the normal pre-merge gate. It surfaces only in a broad run.\n\nHOW IT WAS FOUND (worth recording): it produced a FALSE RED in my own mutation harness. v1 ran\npytest with -x and read the exit code; this pre-existing failure tripped -x on every run, so\nall five planted mutations looked 'caught' when the runs proved nothing. The harness auditing\nfor false greens generated a false red.\n\nSTANDING RULE that came out of it: a mutation-testing or bisect harness must difference against\na measured baseline set of failing node ids. An exit code is not evidence, and -x makes any\npre-existing failure masquerade as the signal.\n\nAC:\n- Identify the polluting module/fixture (bisect the 31-file selection).\n- Fix the leak at its source rather than by reordering or by adding a fixture-reset to the\n victim test.\n- Consider whether the 'root' key is being consumed from module-global or process-global state\n that another test mutates.\n- Record whether other order-dependent failures exist in a broad run (devtools verify --all is\n ~3min/12725 tests per project memory, so a full-order check is affordable).","status":"open","priority":2,"issue_type":"bug","owner":"ezo.dev@gmail.com","created_at":"2026-07-31T08:21:15Z","created_by":"Sinity","updated_at":"2026-07-31T08:21:15Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"polylogue-3a61","title":"Tautological assertions: three tests that cannot fail","description":"FALSE-GREEN AUDIT 2026-07-31 (findings F7, F8, F9). Read-verified, not mutation-checked.\n\n1) tests/unit/core/test_json.py:169 test_loads_malformed_json_never_silent\n Docstring: 'loads either raises or returns a non-None value; it never silently returns None\n for a non-null JSON input.'\n Body:\n try:\n result = core_json.loads(text)\n _ = result # No assertion needed - successful parse is fine\n except Exception:\n pass # Expected for malformed input\n There is NO assertion. The exact regression the docstring names -- loads() silently\n returning None -- passes. Note the contrast with the test immediately above it (:163),\n which uses pytest.raises and carries an explicit 'Anti-vacuity:' docstring, so the concept\n was understood in this very file.\n FIX: assert result is not None (the docstring's actual claim), keeping the documented\n carve-out that literal JSON 'null' legitimately returns None.\n\n2) tests/unit/core/test_filters_props.py:505 test_provider_filter_exclusion_disjoint\n Docstring: 'Provider inclusion and exclusion should be mutually exclusive.'\n Body computes result = included - excluded over two plain Python sets built from the\n Hypothesis inputs, then asserts members of the difference are not in excluded. That is a\n property of set.__sub__. No SessionFilter, no archive code, nothing from polylogue is\n invoked -- in a module whose subject is production filter properties.\n FIX: build a SessionFilter with those origins/exclusions and assert on .list() output, or\n delete the test.\n\n3) tests/unit/core/test_filters_props.py:791, :804, :816\n test_exclude_provider_and_exclude_tag / test_provider_with_exclude_tag /\n test_multiple_exclude_providers\n These DO call real SessionFilter(...).exclude_origin(...).list(), but every assertion sits\n inside 'for conv in result:' with no cardinality guard. Currently non-vacuous (the\n filter_repo_advanced fixture leaves 1-2 rows), so they are not silently passing today --\n but a regression that made the filter return [] (the total-failure mode) keeps all three\n green.\n FIX: add assert len(result) \u003e= 1 before each loop.\n\nCONTEXT -- suite-wide AST sweep over 12,513 test functions (upper bounds on CANDIDATES, not\ndefect counts; manual sampling found only ~15-20% of each bucket genuine, because this\ncodebase legitimately delegates assertions to shared helpers such as _assert_structured_error):\n 186 functions with zero bare-assert statements\n 137 with only weak asserts (is not None / isinstance / len\u003e=0)\n 238 with all asserts inside a possibly-empty loop \u003c- bucket (3) above\n 63 mock-assert only\n 17 with a swallowing try/except \u003c- bucket (1) above\n\nAC: the three tests above assert something that can fail; the loop-only cluster gets\ncardinality guards; consider whether a cardinality-guard convention belongs in TESTING.md.","status":"open","priority":2,"issue_type":"bug","owner":"ezo.dev@gmail.com","created_at":"2026-07-31T08:20:49Z","created_by":"Sinity","updated_at":"2026-07-31T08:20:49Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"polylogue-zn1k","title":"234 stale workflow-artifact sessions (coordinator_session_stream 226 + workflow_run_snapshot 7 + journal counted separately) never reparsed after classification fix","description":"Forensics 2026-07-31. The previously known '172 workflow-artifact sessions' is actually 233 empty sessions today: 226 with artifact_kind=coordinator_session_stream + 7 workflow_run_snapshot (wf_*.json). Producers stopped (max acquired 2026-07-19 / 07-26 respectively; 455 newer coordinator raws stay correctly unparsed), but the classification fix shipped without a SEMANTIC_REPARSE / cleanup so the materialized empties persist.\nRepro: ATTACH source.db; SELECT count(*) FROM sessions s JOIN src.raw_artifacts a ON a.raw_id=s.raw_id WHERE s.message_count=0 AND a.artifact_kind IN ('coordinator_session_stream','workflow_run_snapshot');\nAC: these session rows removed or reparsed under current classification; policy lint that a reclassification shipping without reparse/purge of already-materialized rows fails.","status":"open","priority":2,"issue_type":"chore","owner":"ezo.dev@gmail.com","created_at":"2026-07-31T08:19:27Z","created_by":"Sinity","updated_at":"2026-07-31T08:19:27Z","dependency_count":0,"dependent_count":0,"comment_count":0}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Make the remediation count match the deletion predicate.

The title claims 234 rows, but the described query selects only 226 + 7 = 233 rows. It does not include workflow_journal, although the title says that journal rows are counted separately.

Either include the journal artifact kind and its count in the predicate, or change the title and acceptance criteria to 233 rows.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.beads/issues.jsonl at line 506, Align the issue’s remediation scope with
its deletion predicate: either add workflow_journal rows and their count to the
described query and acceptance criteria, or update the title and acceptance
criteria to consistently state 233 rows. Keep the artifact kinds, counts, and
remediation language consistent throughout the issue.

Comment thread .beads/issues.jsonl Outdated
@@ -1024,7 +1088,7 @@
{"_type":"issue","id":"polylogue-f3kd","title":"Model delegation chains, retries, and evidence-backed parent follow-up","description":"After the canonical delegation-attempt relation and ObjectRefs land, add richer sequence semantics: retries, corrections, redelegations, escalation, and bounded parent follow-up observations. The prior target_kind and provider-fixture scope moves to the foundational ObjectRef bead. The prior lexical-overlap PARENT-USE heuristic is rejected: text overlap is not evidence that a child result was used.","design":"Build relations over stable delegation refs and transcript order. Parent follow-up is a typed observation with evidence categories such as explicit citation, quote, structured result reference, synthesis judgment, ignored, or unknown. Only structural refs or accepted annotations can support utility/used claims; lexical similarity may be exposed as a low-tier candidate signal but never promoted automatically. Include provider-native retry/redelegation and auto-compaction exclusion fixtures.","acceptance_criteria":"Fixtures cover retry, correction, redelegation, escalation, ignored result, explicit structured use, ambiguous follow-up, and auto-compaction exclusion. Every follow-up category carries an evidence tier and refs; unknown is excluded from use/utility denominators. Removing the lexical similarity signal does not erase structurally supported observations. Sequence rows and cards resolve through stable delegation refs.","notes":"Priority calibration 2026-07-15: P2 to P3. This is an important downstream integration, richer semantic layer, or adoption step whose prerequisites and core contracts must land first. It stays explicitly tracked at its existing horizon; P3 marks sequencing, not reduced ambition.","status":"open","priority":3,"issue_type":"task","owner":"ezo.dev@gmail.com","created_at":"2026-07-09T04:19:02Z","created_by":"Sinity","updated_at":"2026-07-15T20:07:29Z","labels":["area:analytics","area:delegations","area:lineage","delivery:I-analytics-experiments","horizon:frontier"],"dependencies":[{"issue_id":"polylogue-f3kd","depends_on_id":"polylogue-1vpm","type":"parent-child","created_at":"2026-07-15T01:19:27Z","created_by":"Sinity","metadata":"{}"},{"issue_id":"polylogue-f3kd","depends_on_id":"polylogue-1vpm.1","type":"discovered-from","created_at":"2026-07-09T06:19:02Z","created_by":"Sinity","metadata":"{}"},{"issue_id":"polylogue-f3kd","depends_on_id":"polylogue-lph4","type":"blocks","created_at":"2026-07-10T10:10:39Z","created_by":"Sinity","metadata":"{}"},{"issue_id":"polylogue-f3kd","depends_on_id":"polylogue-y964","type":"blocks","created_at":"2026-07-10T10:10:38Z","created_by":"Sinity","metadata":"{}"}],"dependency_count":2,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"polylogue-57bg","title":"Extend cfk uplift re-run to n=12-20 using the production pack-generation pipeline","description":"polylogue-cfks n=5 pilot (directional positive, 4/5 pairs favor handoff-pack, mean 30.2/40 vs 22.8/40) used hand-written context summaries as the \"pack\" arm input, not the actual production pack-generation pipeline (qt3s fast regeneration + yps freshness metadata), and drew all 5 checkpoints from one sessions own consecutive devloop history rather than genuinely independent subjects. Both are real limitations the n=5 report documents explicitly. A publishable uplift claim needs n=12-20 per the original protocol.","design":"Use the actual production pack-generation command (compose_context_preamble / devtools workspace read-package or whatever the qt3-shipped fast-regeneration path is) to generate each pack arms input, verifying yps freshness metadata (generated_at ~= consumption time, freshness state fresh, zero successor warnings) before dispatching that arm -- this directly tests the root-cause fix the original jxe campaign attributed its negative result to (packet staleness), which the n=5 pilot did not test. Draw subjects from genuinely independent devloop sessions/checkpoints (not all from one continuous session) to avoid the correlated-subject-and-rater limitation the n=5 report flags. Reuse the n=5 pilots mechanism otherwise: isolated Agent-tool subagents per arm, ground truth written before dispatch, blinded judge subagents, cold-reader gate on the final artifact. Commit under a NEW .agent/demos/uplift-two-arm/ run (retire the n=5 current/ to a dated subfolder per the shelfs own \"current, not append-only\" convention).","acceptance_criteria":"n=12-20 paired runs completed using the production pack-generation pipeline with verified freshness metadata per pack; genuinely independent subjects (not one sessions consecutive checkpoints); per-pair scores + paired analysis (sign test, means) committed; cold-reader gate PASS; result recorded as the programs first potentially-publishable uplift finding (positive, negative, or still-ambiguous).","notes":"[2026-07-09] Added a required measurement per user challenge to the n=5 pilots \"synthesis effort\" framing: the n=5 pilot did not impose or measure any effort/budget difference between the raw-ref and handoff-pack arms (both got the same nominal single unbounded dispatch), so it cannot actually show whether raw-ref lost because it explored less or because synthesis quality is independent of exploration volume. This re-run must log tool-call count and token usage per arm per pair, and explicitly check whether raw-ref arms that matched or exceeded the pack arms measured effort still lost -- that is much stronger evidence for (or against) the synthesis-effort hypothesis than the current pilots untested assumption.","status":"open","priority":3,"issue_type":"task","owner":"ezo.dev@gmail.com","created_at":"2026-07-09T04:05:38Z","created_by":"Sinity","updated_at":"2026-07-09T04:50:45Z","labels":["area:analytics","area:experiments"],"dependencies":[{"issue_id":"polylogue-57bg","depends_on_id":"polylogue-cfk","type":"discovered-from","created_at":"2026-07-09T06:05:38Z","created_by":"Sinity","metadata":"{}"},{"issue_id":"polylogue-57bg","depends_on_id":"polylogue-e5b5","type":"blocks","created_at":"2026-07-09T12:31:02Z","created_by":"Sinity","metadata":"{}"},{"issue_id":"polylogue-57bg","depends_on_id":"polylogue-rxdo","type":"parent-child","created_at":"2026-07-15T19:13:27Z","created_by":"Sinity","metadata":"{}"},{"issue_id":"polylogue-57bg","depends_on_id":"polylogue-x35k","type":"blocks","created_at":"2026-07-09T12:31:03Z","created_by":"Sinity","metadata":"{}"}],"dependency_count":2,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"polylogue-vv2b","title":"Wire lineage-completeness signal into CLI/API session payloads","description":"polylogue-4ts.6 added lineage_complete/lineage_truncation_reason to ArchiveSessionEnvelope and wired it through the two MCP-facing payloads (MCPMessagesListPayload via archive_messages_payload, MCPArchiveSessionPayload.from_session) -- CodeRabbit correctly flagged (PR #2603) that two more read surfaces still silently drop it: _session_payload (polylogue/cli/archive_query.py:2198, the CLI reader payload) and _archive_session_to_session (polylogue/api/archive.py:1162, the Python API Session domain model). Also relevant: the async batch/paginated wrappers (get_messages_batch, get_messages_paginated, get_message_edge_windows in message_query_reads.py) currently discard the signal by calling plain get_messages internally rather than get_messages_with_lineage_completeness -- their callers cannot observe truncation either.","design":"Same additive pattern as the two already-wired payloads: add lineage_complete: bool = True / lineage_truncation_reason: str | None = None (or the LineageTruncationReason Literal from polylogue.storage.runtime) to whatever dict/model _session_payload and Session (api/archive.py) already return, and pass session.lineage_complete/lineage_truncation_reason through at the two construction sites. For the async batch/paginated wrappers, switch their internal get_messages(...) calls to get_messages_with_lineage_completeness(...) and thread the signal through their own return shapes (may need new tuple/dataclass wrapping, same trade-off already made for get_messages itself).","acceptance_criteria":"polylogue read (CLI) and the Python API Session model both expose lineage_complete/lineage_truncation_reason for a truncated session, proven by a fixture (dangling branch point or depth-limit case) asserting the field on the CLI JSON output and the API Session object. get_messages_batch/get_messages_paginated/get_message_edge_windows either surface the signal or explicitly document why they intentionally do not (e.g. if paginated views are inherently partial by design and completeness is a session-level, not a page-level, concern).","status":"closed","priority":3,"issue_type":"task","owner":"ezo.dev@gmail.com","created_at":"2026-07-09T03:14:24Z","created_by":"Sinity","updated_at":"2026-07-15T19:40:22Z","closed_at":"2026-07-15T19:40:22Z","close_reason":"Superseded by polylogue-4p1, whose sole read algebra and generated field-parity contract now explicitly own lineage completeness across CLI, Python, batch, and paginated readers.","labels":["area:lineage","area:mcp"],"dependencies":[{"issue_id":"polylogue-vv2b","depends_on_id":"polylogue-4ts","type":"parent-child","created_at":"2026-07-15T19:13:10Z","created_by":"Sinity","metadata":"{}"},{"issue_id":"polylogue-vv2b","depends_on_id":"polylogue-4ts.6","type":"discovered-from","created_at":"2026-07-09T05:14:24Z","created_by":"Sinity","metadata":"{}"},{"issue_id":"polylogue-vv2b","depends_on_id":"polylogue-4ts.9","type":"relates-to","created_at":"2026-07-15T06:25:54Z","created_by":"Sinity","metadata":"{}"}],"dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"polylogue-xyel","title":"Real PF-D1-receipts demo (212.2) re-emitted through demo-packet contract","description":"polylogue-212.7 built the Demo Finding Packet contract (devtools/demo_packet.py: validate_packet, lint_demo_registry, devtools lab policy demo-packet-registry) and proved it end-to-end with a deliberately trivial stub fixture (.agent/demos/_packet-contract-stub/, counts sessions in the seeded corpus). The bead AC literally asked for \"one existing demo (PF-D1 receipts) re-emitted through the runner\" -- 212.2 (PF-D1 receipts: claim-vs-evidence on a real PR) does not exist as an implemented demo yet, so 212.7 shipped the mechanism proven against a stub instead of the real thing. This bead is the follow-up: implement 212.2 for real and register it in .agent/demos/registry.json as a conforming packet, retiring (or keeping alongside, if useful as a contract-only fixture) the stub.","design":"Implement 212.2 per its own description: pick a merged agent-authored PR, resolve PR -\u003e authoring session via session_commits/session_repos, get_postmortem_bundle, render two columns (claimed PR-body sentences vs observed actions rows with exit_code/duration, drillable to the raw tool_result block). Package the output as a packet directory under .agent/demos/d1-receipts/ conforming to devtools/demo_packet.py PACKET_FILENAMES + PROVENANCE_STANZA_FIELDS + REPORT_SECTION_ORDER (reuse the stub as a structural template). Register it in .agent/demos/registry.json. Run devtools lab policy demo-packet-registry to prove it validates.","acceptance_criteria":".agent/demos/d1-receipts/ (or similar slug) exists with all 7 required packet files, a real claim-vs-evidence finding on an actual merged PR from this repo, and validates cleanly via devtools lab policy demo-packet-registry. Registered in .agent/demos/registry.json. Verify: devtools lab policy demo-packet-registry passes with the new entry included.","notes":"[2026-07-10 fable] polylogue demo receipts (PR #2662) is the deterministic contract-proof baseline this bead re-emits through the packet contract; receipts.json/summary.json shapes in the v2 escrow (polylogue-demo-receipts/) are a draft packet layout.\nVERIFICATION (group4 stale-sweep, 2026-07-31): LIVE. AC requires .agent/demos/d1-receipts/ (or similar) implementing a real PF-D1 receipts demo, registered in .agent/demos/registry.json. No such directory/entry exists on master. Bead's own dependency chain (cijx.1) confirms the underlying PR\u003c-\u003esession correlation producer (session_refs) exists but has no consumer wired on any surface, so 212.2/xyel remain explicitly un-unblocked per cijx.1's 2026-07-31 note. Evidence: git ls-tree -r origin/master --name-only -- .agent/demos/ | grep -i d1 -\u003e empty; git show origin/master:.agent/demos/registry.json | grep -i d1-receipts -\u003e empty.\nUNBLOCKED 2026-07-31 (polylogue-pbuh/cijx.1 residual pass, worktree agent-aaffe89902b670d4b): the session-\u003ePR producer+reader chain this bead depends on is now real. session_refs carries typed pull_request evidence (18,949 rows live), and PR #3425 (merged 5525446a2) wired `read --view correlation` / Polylogue.session_correlation_payload to consume it as authoritative over the old regex/time-window heuristics, with disagreements surfaced rather than silently guessed. Verified live against /realm/db/polylogue/index.db (read-only) that the CLI path resolves real typed PR refs end-to-end (also fixed a pre-existing NameError in that path's GitHub-enrichment branch that had never been exercised with real refs before this pass). Full detail: polylogue-cijx.1 and polylogue-pbuh notes, 2026-07-31.\n\nNOT closed by this alone: this bead's own AC still needs its specific deliverable (see this bead's own description) beyond \"the correlation data is now readable\" -- that implementation work was not attempted in this pass (out of its declared scope: read-surface residual verification for pbuh/cijx.1 only). Re-triage this bead's own AC against the now-working session_commit.py/correlation_view.py surface when picked up next.\n","status":"open","priority":3,"issue_type":"task","owner":"ezo.dev@gmail.com","created_at":"2026-07-09T00:12:05Z","created_by":"Sinity","updated_at":"2026-07-31T06:07:17Z","labels":["area:demos","delivery:L-external-legibility","lane:docs-demos-launch"],"dependencies":[{"issue_id":"polylogue-xyel","depends_on_id":"polylogue-212","type":"parent-child","created_at":"2026-07-15T19:13:34Z","created_by":"Sinity","metadata":"{}"},{"issue_id":"polylogue-xyel","depends_on_id":"polylogue-212.7","type":"discovered-from","created_at":"2026-07-09T02:12:05Z","created_by":"Sinity","metadata":"{}"},{"issue_id":"polylogue-xyel","depends_on_id":"polylogue-cijx.1","type":"blocks","created_at":"2026-07-29T06:51:59Z","created_by":"Sinity","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"polylogue-xyel","title":"Real PF-D1-receipts demo (212.2) re-emitted through demo-packet contract","description":"polylogue-212.7 built the Demo Finding Packet contract (devtools/demo_packet.py: validate_packet, lint_demo_registry, devtools lab policy demo-packet-registry) and proved it end-to-end with a deliberately trivial stub fixture (.agent/demos/_packet-contract-stub/, counts sessions in the seeded corpus). The bead AC literally asked for \"one existing demo (PF-D1 receipts) re-emitted through the runner\" -- 212.2 (PF-D1 receipts: claim-vs-evidence on a real PR) does not exist as an implemented demo yet, so 212.7 shipped the mechanism proven against a stub instead of the real thing. This bead is the follow-up: implement 212.2 for real and register it in .agent/demos/registry.json as a conforming packet, retiring (or keeping alongside, if useful as a contract-only fixture) the stub.","design":"Implement 212.2 per its own description: pick a merged agent-authored PR, resolve PR -\u003e authoring session via session_commits/session_repos, get_postmortem_bundle, render two columns (claimed PR-body sentences vs observed actions rows with exit_code/duration, drillable to the raw tool_result block). Package the output as a packet directory under .agent/demos/d1-receipts/ conforming to devtools/demo_packet.py PACKET_FILENAMES + PROVENANCE_STANZA_FIELDS + REPORT_SECTION_ORDER (reuse the stub as a structural template). Register it in .agent/demos/registry.json. Run devtools lab policy demo-packet-registry to prove it validates.","acceptance_criteria":".agent/demos/d1-receipts/ (or similar slug) exists with all 7 required packet files, a real claim-vs-evidence finding on an actual merged PR from this repo, and validates cleanly via devtools lab policy demo-packet-registry. Registered in .agent/demos/registry.json. Verify: devtools lab policy demo-packet-registry passes with the new entry included.","notes":"[2026-07-10 fable] polylogue demo receipts (PR #2662) is the deterministic contract-proof baseline this bead re-emits through the packet contract; receipts.json/summary.json shapes in the v2 escrow (polylogue-demo-receipts/) are a draft packet layout.\nVERIFICATION (group4 stale-sweep, 2026-07-31): LIVE. AC requires .agent/demos/d1-receipts/ (or similar) implementing a real PF-D1 receipts demo, registered in .agent/demos/registry.json. No such directory/entry exists on master. Bead's own dependency chain (cijx.1) confirms the underlying PR\u003c-\u003esession correlation producer (session_refs) exists but has no consumer wired on any surface, so 212.2/xyel remain explicitly un-unblocked per cijx.1's 2026-07-31 note. Evidence: git ls-tree -r origin/master --name-only -- .agent/demos/ | grep -i d1 -\u003e empty; git show origin/master:.agent/demos/registry.json | grep -i d1-receipts -\u003e empty.\nUNBLOCKED 2026-07-31 (polylogue-pbuh/cijx.1 residual pass, worktree agent-aaffe89902b670d4b): the session-\u003ePR producer+reader chain this bead depends on is now real. session_refs carries typed pull_request evidence (18,949 rows live), and PR #3425 (merged 5525446a2) wired `read --view correlation` / Polylogue.session_correlation_payload to consume it as authoritative over the old regex/time-window heuristics, with disagreements surfaced rather than silently guessed. Verified live against /realm/db/polylogue/index.db (read-only) that the CLI path resolves real typed PR refs end-to-end (also fixed a pre-existing NameError in that path's GitHub-enrichment branch that had never been exercised with real refs before this pass). Full detail: polylogue-cijx.1 and polylogue-pbuh notes, 2026-07-31.\n\nNOT closed by this alone: this bead's own AC still needs its specific deliverable (see this bead's own description) beyond \"the correlation data is now readable\" -- that implementation work was not attempted in this pass (out of its declared scope: read-surface residual verification for pbuh/cijx.1 only). Re-triage this bead's own AC against the now-working session_commit.py/correlation_view.py surface when picked up next.\n","status":"closed","priority":3,"issue_type":"task","owner":"ezo.dev@gmail.com","created_at":"2026-07-09T00:12:05Z","created_by":"Sinity","updated_at":"2026-07-31T09:03:24Z","closed_at":"2026-07-31T09:03:24Z","close_reason":"Re-verified the bead's original framing against current master before doing\nanything: \"session_refs has no consumer\" is FALSE today. PR #3425 wired\ntyped session_refs pull_request/issue evidence into\ninsights/session_commit.py:build_correlation_result, and PR #3431 fixed a\npre-existing NameError in insights/correlation_view.py's GitHub-enrichment\npath that had made the default `read --view correlation --github-api`\ninvocation crash on every session carrying a ref -- confirmed live (this\nsession) by running it against /realm/db/polylogue (read-only): it resolves\na typed PR ref (source=typed_session_ref) plus a disagreements entry naming\nnon-corroborated regex-heuristic matches. The bead's own dependency\npolylogue-cijx.1 documents the same finding. So the consumer-wiring half of\nthis bead's title was already satisfied by tonight's merges -- accurately\nreported here rather than re-claimed as new work.\n\nWhat remained was this bead's own literal AC: build and register a real D1\nreceipts demo (212.2), not the packet-contract stub 212.7 shipped. Built\n.agent/demos/d1-receipts/ -- 9 packet files (current PACKET_FILENAMES\ncontract; AC's \"7\" is a stale pre-v2-schema count), a real claim-vs-evidence\nfinding on an actual merged PR (Sinity/polylogue#3282), registered in\n.agent/demos/registry.json, validating cleanly via\n`devtools lab policy demo-packet-registry` (\"all 4 entries conform\").\n\nThe finding itself: resolved PR #3282 to its authoring/dispatch session\nstructurally via session_refs, then checked 4 individually falsifiable\nPR-body sentences against that session's own tool_use/tool_result blocks.\n3 of 4 are structurally supported; the 4th (a 7-file devtools test\ninvocation named in the PR's Verification section) is correctly scored\nnot_supported -- that exact string appears only inside the gh-pr-create\n--body text itself, never as an executed command in this session. Also\nsurfaced a genuine, undocumented-until-now finding: the resolved session is\na merge-conductor (53 Bash + 3 Read tool_use, 0 Edit/Write) that dispatches\nfile edits to separate worker worktrees rather than editing files directly\n-- session_refs correctly answers \"which session opened this PR\", not\n\"which session edited file X\".\n\nHonest scope disposition: only the live-archive operator variant is built\n(mode=private). 212's own two-variant design (public seed-corpus + live\noperator) is not fully satisfied -- session_refs pull_request rows are a\nprovider-native capability the deterministic seed fixture doesn't populate,\nso the public D1 variant is out of scope here. Filed polylogue-nt5f for\nthat named remainder rather than silently leaving it unstated.\n\n--force disposition: closed over the open blocker polylogue-cijx.1. cijx.1's\nown notes explicitly state the specific concern it raised for this bead's\ndependents (the session_refs producer/reader chain \"does not work\") is\nresolved, and that concluding this bead's own concrete deliverable was left\nto whoever picks it up next -- done here. cijx.1 itself remains legitimately\nopen for its own, unrelated titled AC (106 repo_ids for one polylogue\nrepository across worktrees/URL spellings); that scope has no bearing on\nthis bead's demo-packet deliverable, so the dependency edge no longer\nreflects a real blocker for this specific bead.\n\nVerification: devtools lab policy demo-packet-registry -\u003e all 4 entries\nconform. devtools test tests/unit/devtools/test_demo_packet.py\ntests/unit/demo/test_tour_packet_contract.py -\u003e 32 passed. devtools verify\n--quick -\u003e 20/20 steps green. devtools render all --check -\u003e OK. Landing on\nbranch feature/cleanup/dead-coverage-and-session-refs alongside polylogue-uh9l.","labels":["area:demos","delivery:L-external-legibility","lane:docs-demos-launch"],"dependencies":[{"issue_id":"polylogue-xyel","depends_on_id":"polylogue-212","type":"parent-child","created_at":"2026-07-15T19:13:34Z","created_by":"Sinity","metadata":"{}"},{"issue_id":"polylogue-xyel","depends_on_id":"polylogue-212.7","type":"discovered-from","created_at":"2026-07-09T02:12:05Z","created_by":"Sinity","metadata":"{}"},{"issue_id":"polylogue-xyel","depends_on_id":"polylogue-cijx.1","type":"blocks","created_at":"2026-07-29T06:51:59Z","created_by":"Sinity","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Remove the stale blocking dependency.

The close reason states that polylogue-cijx.1 no longer blocks this work, but the record still stores a blocks dependency and dependency_count: 1. Dependency graph consumers will continue to report this issue as blocked.

Delete the blocking edge or change it to a non-blocking relation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.beads/issues.jsonl at line 1091, Remove the stale polylogue-cijx.1
dependency from the issue’s dependencies, or change its type from blocks to a
non-blocking relation, and update dependency_count to match so graph consumers
no longer report polylogue-xyel as blocked.

Comment on lines +361 to +384
_CLAUDE_WORKFLOW_RECORDED_GAP_LIMIT = 20


def _record_claude_workflow_stage_event(archive_root: Path, summary: object) -> None:
"""Persist the materialization summary so a readiness surface can read it.

``materialize_claude_workflow_archive`` returns a fresh
``ClaudeWorkflowMaterializationSummary`` every convergence pass; without
this it was logged once and discarded. Recorded into the disposable
``ops.db`` tier via the existing generic ``daemon_stage_events`` table (no
schema change) so ``polylogue doctor`` / archive readiness can report the
current gap count instead of only a log line.
"""
gaps = tuple(getattr(summary, "gaps", ()))
payload: dict[str, object] = {
"run_count": getattr(summary, "run_count", 0),
"call_count": getattr(summary, "call_count", 0),
"attempt_count": getattr(summary, "attempt_count", 0),
"linked_session_count": getattr(summary, "linked_session_count", 0),
"unresolved_call_count": getattr(summary, "unresolved_call_count", 0),
"gap_count": len(gaps),
"gaps": list(gaps[:_CLAUDE_WORKFLOW_RECORDED_GAP_LIMIT]),
}
status = "gaps" if gaps else "clean"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Consider typing summary as the real materialization-summary type instead of object + getattr.

The function reads run_count, call_count, attempt_count, linked_session_count, unresolved_call_count, and gaps from summary using getattr(summary, name, default). Because summary is typed as object, a static type checker cannot catch a future field rename on ClaudeWorkflowMaterializationSummary. If a field is renamed, this function silently records zero/empty values instead of failing, and polylogue doctor's Claude Workflow gap check would then report false confidence instead of surfacing an error.

Import the real summary type under TYPE_CHECKING and use direct attribute access. This keeps the runtime lazy-import pattern used elsewhere in this file while restoring static safety for this health-reporting path.

♻️ Proposed typing fix
+from typing import TYPE_CHECKING
+
+if TYPE_CHECKING:
+    from polylogue.insights.claude_workflow_materializer import ClaudeWorkflowMaterializationSummary
+
-def _record_claude_workflow_stage_event(archive_root: Path, summary: object) -> None:
+def _record_claude_workflow_stage_event(
+    archive_root: Path, summary: "ClaudeWorkflowMaterializationSummary"
+) -> None:
     ...
-    gaps = tuple(getattr(summary, "gaps", ()))
+    gaps = tuple(summary.gaps)
     payload: dict[str, object] = {
-        "run_count": getattr(summary, "run_count", 0),
-        "call_count": getattr(summary, "call_count", 0),
-        "attempt_count": getattr(summary, "attempt_count", 0),
-        "linked_session_count": getattr(summary, "linked_session_count", 0),
-        "unresolved_call_count": getattr(summary, "unresolved_call_count", 0),
+        "run_count": summary.run_count,
+        "call_count": summary.call_count,
+        "attempt_count": summary.attempt_count,
+        "linked_session_count": summary.linked_session_count,
+        "unresolved_call_count": summary.unresolved_call_count,
         "gap_count": len(gaps),
         "gaps": list(gaps[:_CLAUDE_WORKFLOW_RECORDED_GAP_LIMIT]),
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
_CLAUDE_WORKFLOW_RECORDED_GAP_LIMIT = 20
def _record_claude_workflow_stage_event(archive_root: Path, summary: object) -> None:
"""Persist the materialization summary so a readiness surface can read it.
``materialize_claude_workflow_archive`` returns a fresh
``ClaudeWorkflowMaterializationSummary`` every convergence pass; without
this it was logged once and discarded. Recorded into the disposable
``ops.db`` tier via the existing generic ``daemon_stage_events`` table (no
schema change) so ``polylogue doctor`` / archive readiness can report the
current gap count instead of only a log line.
"""
gaps = tuple(getattr(summary, "gaps", ()))
payload: dict[str, object] = {
"run_count": getattr(summary, "run_count", 0),
"call_count": getattr(summary, "call_count", 0),
"attempt_count": getattr(summary, "attempt_count", 0),
"linked_session_count": getattr(summary, "linked_session_count", 0),
"unresolved_call_count": getattr(summary, "unresolved_call_count", 0),
"gap_count": len(gaps),
"gaps": list(gaps[:_CLAUDE_WORKFLOW_RECORDED_GAP_LIMIT]),
}
status = "gaps" if gaps else "clean"
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from polylogue.insights.claude_workflow_materializer import ClaudeWorkflowMaterializationSummary
_CLAUDE_WORKFLOW_RECORDED_GAP_LIMIT = 20
def _record_claude_workflow_stage_event(
archive_root: Path, summary: "ClaudeWorkflowMaterializationSummary"
) -> None:
"""Persist the materialization summary so a readiness surface can read it.
``materialize_claude_workflow_archive`` returns a fresh
``ClaudeWorkflowMaterializationSummary`` every convergence pass; without
this it was logged once and discarded. Recorded into the disposable
``ops.db`` tier via the existing generic ``daemon_stage_events`` table (no
schema change) so ``polylogue doctor`` / archive readiness can report the
current gap count instead of only a log line.
"""
gaps = tuple(summary.gaps)
payload: dict[str, object] = {
"run_count": summary.run_count,
"call_count": summary.call_count,
"attempt_count": summary.attempt_count,
"linked_session_count": summary.linked_session_count,
"unresolved_call_count": summary.unresolved_call_count,
"gap_count": len(gaps),
"gaps": list(gaps[:_CLAUDE_WORKFLOW_RECORDED_GAP_LIMIT]),
}
status = "gaps" if gaps else "clean"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@polylogue/daemon/convergence_stages.py` around lines 361 - 384, Update
_record_claude_workflow_stage_event to type summary as
ClaudeWorkflowMaterializationSummary, importing that type under TYPE_CHECKING to
preserve the existing lazy runtime import pattern. Replace the getattr calls
with direct access to run_count, call_count, attempt_count,
linked_session_count, unresolved_call_count, and gaps, while keeping the payload
and gap-limit behavior unchanged.

@Sinity
Sinity merged commit af5a762 into master Jul 31, 2026
1 of 3 checks passed
@Sinity
Sinity deleted the feature/cleanup/dead-coverage-and-session-refs branch July 31, 2026 09:37
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