fix(preflight): classify blocked replay evidence - #3905
Conversation
Problem: blank and whitespace-only raw_sessions.parse_error values were omitted from the source distribution and eligibility counts.\n\nWhat changed: count every non-NULL parse_error value in the production preflight projection and update the route assertion to cover empty and whitespace text.\n\nCompatibility/migration: no schema or storage mutation; the preflight remains read-only.\n\nCo-Authored-By: Claude <noreply@anthropic.com>
Problem: the replay preflight failed whenever any candidate existed, even when every candidate was blocked by authority or resource conditions.\n\nWhat changed: compare executable candidates with blocked candidates and exercise both outcomes through build_preflight_ledger.\n\nCompatibility/migration: no schema or storage mutation; blocked replay work remains visible as a warning.\n\nCo-Authored-By: Claude <noreply@anthropic.com>
📝 WalkthroughWalkthroughThe change updates parse-error classification across storage and preflight reporting. It also changes replay backlog status to use executable authority-component counts and exposes that count in ledger output. Unit tests cover empty, whitespace-only, mixed, and blocked cases. ChangesFailure and replay accounting
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4c7556527f
ℹ️ 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".
| candidate_count = _count(payload.get("candidate_count")) | ||
| blocked_count = _count(payload.get("blocked_candidate_count")) | ||
| state = "fail" if candidate_count else "warn" if blocked_count else "pass" | ||
| state = "fail" if candidate_count > blocked_count else "warn" if blocked_count else "pass" |
There was a problem hiding this comment.
Derive executable replay candidates from the same population
When executable and blocked work coexist, this comparison can mark the preflight non-blocking even though replayable work remains. raw_materialization_replay_backlog() defines candidate_count from candidates.raw_ids, but its blocked_candidate_count also includes adoption-deferred and byte-authority-pending rows that were explicitly excluded from raw_ids (polylogue/storage/repair.py:4007-4032,4770-4796), as well as expanded non-candidate component members. For example, one executable candidate plus one unrelated pending row produces 1 > 1 == false, so this check warns and build_preflight_ledger() reports ok=true; expose or calculate an executable count from the candidate set instead of comparing unrelated aggregates.
AGENTS.md reference: AGENTS.md:L477-L482
Useful? React with 👍 / 👎.
| {"_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-31T22:35:43Z","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-31T22:35:43Z","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-31T22:35:43Z","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-agbgr","title":"preflight: classify blocked replay and all raw parse-error evidence","description":"The reindex preflight ledger must distinguish executable replay candidates from blocked candidates and must count every non-null raw parse-error marker, including empty and whitespace values, so readiness cannot be falsely green.","acceptance_criteria":"1. Replay preflight fails only when executable candidates outnumber blocked candidates; a fully blocked population remains a visible warning.\\n2. Every non-null raw_sessions.parse_error value is represented in source distribution and actionable eligibility counts.\\n3. Focused preflight ledger tests cover both replay orderings and blank/whitespace parse-error values.\\n4. devtools verify --quick passes.\\n5. The ledger remains read-only and does not authorize live replay or migration.","notes":"Unique WIP lane completed on feature/fix/preflight-predicate-corrections. This is a preflight correctness change only; live source remediation remains separately gated.","status":"open","priority":1,"issue_type":"bug","owner":"ezo.dev@gmail.com","created_at":"2026-08-09T22:52:03Z","created_by":"Sinity","updated_at":"2026-08-09T22:52:03Z","dependency_count":0,"dependent_count":0,"comment_count":0} |
There was a problem hiding this comment.
Bind the carrier to the existing preflight child
The structured carrier marks this newly created standalone Bead as satisfied, but the repository already contains the still-open polylogue-reindex-preflight-authorization.1 record at .beads/issues.jsonl:177 with the same two predicate corrections and a parent-child link to the reindex authorization campaign. Creating an unlinked duplicate lets the carrier validate a satisfied scope while the campaign-owned task remains undispositioned and open; bind the PR to the existing child, or explicitly link/supersede and disposition both records.
AGENTS.md reference: AGENTS.md:L288-L299
Useful? React with 👍 / 👎.
| CASE WHEN r.parse_error IS NOT NULL | ||
| OR LOWER(COALESCE(r.validation_status, '')) = 'failed' | ||
| THEN 1 ELSE 0 END AS failure, |
There was a problem hiding this comment.
Align the lifecycle check with non-null parse errors
For an empty or whitespace-only parse_error, this changed predicate now reports a parse failure and actionable source debt, while the raw_failure_lifecycle check included in the same ledger still selects only parse_error IS NOT NULL AND TRIM(parse_error) != '' (polylogue/storage/raw_failure_lifecycle.py:122-142) and therefore reports zero failures and a healthy lifecycle. The exact report can consequently present two contradictory failure universes, and downstream lifecycle consumers continue treating the newly recognized evidence as clean; define the non-null failure semantics in the shared lifecycle authority and consume it here rather than changing only this projection.
AGENTS.md reference: AGENTS.md:L37-L40
Useful? React with 👍 / 👎.
| @@ -1,3 +1,4 @@ | |||
| {"_type":"issue","id":"polylogue-r4jiu","title":"verification: complete source-index coverage ground-truth integration","description":"The parser-census readiness guard is now fail-closed, but source-index coverage still needs its own ground-truth universe wired through the verification registry. Complete the residual from polylogue-in24n without allowing the census ledger to define the population being audited.","acceptance_criteria":"1. The source-index coverage universe is derived from raw logical heads in source.db, not from the census ledger under audit.\\n2. Every raw logical head absent from the index is either indexed or has an explicit typed parse failure, unsupported/non-session disposition, quarantine blocker, or other accepted terminal state.\\n3. A red mutation that removes a raw head from the derived census while leaving source.db unchanged makes the check fail.\\n4. Focused registry tests and devtools verify --quick pass.","notes":"Residual successor created while publishing the parser-census readiness guard. The guard is merged only as a partial prerequisite; do not close this successor until the verification oracle itself uses the raw logical-head universe and its anti-vacuity mutation is green.","status":"open","priority":0,"issue_type":"bug","owner":"ezo.dev@gmail.com","created_at":"2026-08-09T22:42:50Z","created_by":"Sinity","updated_at":"2026-08-09T22:42:50Z","dependencies":[{"issue_id":"polylogue-r4jiu","depends_on_id":"polylogue-in24n","type":"discovered-from","created_at":"2026-08-09T22:42:58Z","created_by":"Sinity","metadata":"{}"}],"dependency_count":0,"dependent_count":0,"comment_count":0} | |||
There was a problem hiding this comment.
Remove tracker mutations outside the declared carrier scope
This head also adds polylogue-r4jiu here and polylogue-8iuna at line 174, concerning source-index coverage and a daemon recovery probe respectively; neither is linked to or listed alongside the carrier's sole assigned Bead, polylogue-agbgr. Because the carrier's canonical Beads digest covers only assigned IDs, these unrelated P0/P1 tracker mutations can change without invalidating the published scope or receiving any disposition or evidence, so keep them on their owning lanes or add their actual scope and dispositions to the carrier.
AGENTS.md reference: AGENTS.md:L381-L389
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fd992631fd
ℹ️ 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".
| # numbers can therefore hide one executable row behind one unrelated | ||
| # blocked row. Any executable candidate is a hard preflight failure; | ||
| # blocked-only work remains a visible warning. | ||
| state = "fail" if candidate_count else "warn" if blocked_count else "pass" |
There was a problem hiding this comment.
Warn when every replay component is resource-blocked
When all replay candidates belong to an oversized authority component, raw_materialization_replay_backlog() still reports a positive candidate_count while counting those same rows in blocked_candidate_count and reporting zero executable_authority_component_count; this predicate therefore marks a blocked-only backlog as fail, makes the overall ledger ok=false, and contradicts the carrier's warning-only blocked-population acceptance criterion. Fresh evidence in this repaired predicate is that it treats every raw candidate as executable despite the backlog already exposing the executable-component count; gate failure on that executable population instead.
AGENTS.md reference: AGENTS.md:L477-L482
Useful? React with 👍 / 👎.
| parse_failures = int( | ||
| conn.execute( | ||
| "SELECT COUNT(*) FROM raw_sessions WHERE parse_error IS NOT NULL AND TRIM(parse_error) != ''" | ||
| ).fetchone()[0] | ||
| or 0 | ||
| conn.execute("SELECT COUNT(*) FROM raw_sessions WHERE parse_error IS NOT NULL").fetchone()[0] or 0 | ||
| ) |
There was a problem hiding this comment.
Apply non-null parse-error semantics to the usage projection
For a raw row whose parse_error is empty or whitespace-only, this new lifecycle authority reports a parse failure and can block status/rebuild checks, but _source_raw_stats() still requires TRIM(parse_error) != '' and then includes the same row in acquired_not_materialized_count (polylogue/storage/usage.py:1198-1204,1251). Consequently polylogue analyze usage can report zero parse errors and describe the row as having no parse error while daemon status and this lifecycle report a failure; update that product projection to consume the same non-null failure universe.
AGENTS.md reference: AGENTS.md:L37-L40
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
devtools/preflight_ledger.py (1)
368-386: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winDo not pass when raw replay candidates lack a classification.
Line 373 returns
passwhencandidate_count > 0,executable_authority_component_count == 0, andblocked_candidate_count == 0. This violates the stated contract that only no candidates produce a pass. Mark this state asunknownand block preflight until the backlog supplies an executable or blocked classification. Add a regression case with_replay_backlog(1, 0, 0).Proposed fix
- state = "fail" if executable_component_count else "warn" if blocked_count else "pass" + state = ( + "fail" + if executable_component_count + else "warn" + if blocked_count + else "unknown" + if candidate_count + else "pass" + )🤖 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 `@devtools/preflight_ledger.py` around lines 368 - 386, Update the state selection in the replay preflight status logic to return “unknown” when candidate_count is positive but both executable_authority_component_count and blocked_candidate_count are zero, preserving “fail” and “warn” for their existing classifications and “pass” only when no candidates exist. Ensure this unknown state blocks preflight, and add a regression case covering _replay_backlog(1, 0, 0).
🤖 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.
Outside diff comments:
In `@devtools/preflight_ledger.py`:
- Around line 368-386: Update the state selection in the replay preflight status
logic to return “unknown” when candidate_count is positive but both
executable_authority_component_count and blocked_candidate_count are zero,
preserving “fail” and “warn” for their existing classifications and “pass” only
when no candidates exist. Ensure this unknown state blocks preflight, and add a
regression case covering _replay_backlog(1, 0, 0).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: a7c9f3d4-56d6-40d4-beff-641df48d2254
📒 Files selected for processing (5)
devtools/preflight_ledger.pypolylogue/storage/raw_failure_lifecycle.pypolylogue/storage/usage.pytests/unit/devtools/test_preflight_ledger.pytests/unit/storage/test_origin_usage_report.py
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 67ae58ea5b
ℹ️ 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".
| # includes authority/resource debt. The backlog already computes the | ||
| # executable authority-component population, so use that typed relation | ||
| # to distinguish executable work from blocked-only work. | ||
| state = "fail" if executable_component_count else "warn" if blocked_count else "pass" |
There was a problem hiding this comment.
Reconcile the gate with the carried acceptance criterion
Fresh evidence in this repaired head is that a mixed backlog such as candidate_count=2, blocked_candidate_count=5, and a positive executable-component count now fails here, while the carrier’s sole assigned Bead, polylogue-reindex-preflight-authorization.1, still requires failure only when candidate_count > blocked_count; nevertheless, the carrier marks that whole Bead satisfied with no successor. The executable-component predicate is the safer implementation after the prior review repairs, but the canonical Bead criterion must be updated or explicitly dispositioned before the structured carrier can truthfully claim satisfaction.
AGENTS.md reference: AGENTS.md:L477-L482
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d9138a73b8
ℹ️ 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".
| # executable authority-component population, so use that typed relation | ||
| # to distinguish executable work from blocked-only work. | ||
| state = ( | ||
| "fail" if executable_component_count else "warn" if blocked_count else "unknown" if candidate_count else "pass" |
There was a problem hiding this comment.
Reconcile the fail-closed state with the carried criterion
Fresh evidence in this head is the new candidate_count=1, blocked_candidate_count=0, executable_authority_component_count=0 branch, which returns unknown, while the canonical acceptance criterion for polylogue-reindex-preflight-authorization.1 still explicitly requires fail whenever candidate_count > blocked_count. Although both states make the ledger non-OK, the structured carrier cannot truthfully mark the whole Bead satisfied while its required state and the newly added regression test disagree; update the criterion/disposition or implement the carried state contract.
AGENTS.md reference: AGENTS.md:L480-L482
Useful? React with 👍 / 👎.
| "SELECT COUNT(*) FROM raw_sessions WHERE parse_error IS NOT NULL AND TRIM(parse_error) != ''" | ||
| ).fetchone()[0] | ||
| or 0 | ||
| conn.execute("SELECT COUNT(*) FROM raw_sessions WHERE parse_error IS NOT NULL").fetchone()[0] or 0 |
There was a problem hiding this comment.
Accept every recognized failure in terminal disposition
When a durable raw has an empty or whitespace-only parse_error and lacks typed lifecycle evidence, this broadened predicate now classifies it as unexplained and blocks bulk rebuild, but _validate_candidate() in polylogue/maintenance/raw_failure_disposition_apply.py:126-127 still requires TRIM(r.parse_error) != ''. The supported terminal-disposition actuator therefore rejects exactly these newly recognized failures, leaving operators unable to classify them without changing durable state through some other route; align the actuator with the non-null failure authority.
AGENTS.md reference: AGENTS.md:L37-L40
Useful? React with 👍 / 👎.
| # executable authority-component population, so use that typed relation | ||
| # to distinguish executable work from blocked-only work. | ||
| state = ( | ||
| "fail" if executable_component_count else "warn" if blocked_count else "unknown" if candidate_count else "pass" |
There was a problem hiding this comment.
Check unclassified candidates before blocked debt
When an unclassified replay candidate coexists with any unrelated adoption-deferred or byte-authority-pending row, this ordering returns warn before examining candidate_count; for example, candidate_count=1, blocked_candidate_count=1, and executable_authority_component_count=0 makes the overall ledger ok=true. Because blocked_candidate_count explicitly includes debt outside the candidate component population (polylogue/storage/repair.py:4770), its presence does not prove the candidate was classified as blocked, so the new fail-closed repair still fails open for mixed evidence; test component classification/conservation before selecting the warning state.
Useful? React with 👍 / 👎.
| r.validation_status, r.acquired_at_ms | ||
| FROM raw_sessions AS r | ||
| WHERE (r.parse_error IS NOT NULL AND TRIM(r.parse_error) != '') | ||
| WHERE r.parse_error IS NOT NULL |
There was a problem hiding this comment.
Include non-null failures in daemon status evidence
When a raw has an empty or whitespace-only parse_error, parsed_at_ms IS NULL, and no validation failure, this broadened CTE now includes it in the lifecycle's parse-failure and unexplained counts, but _archive_raw_failure_info() still applies TRIM(parse_error) != '' in both its quarantine count and sample query (polylogue/daemon/status.py:943,982). The public status payload therefore reports a blocked lifecycle and a nonzero parse-failure count while claiming zero quarantined rows and omitting the responsible raw from raw_failure_samples, making the new blocker opaque to operators; adapt those status queries to the same non-null universe.
AGENTS.md reference: AGENTS.md:L37-L40
Useful? React with 👍 / 👎.
Summary
Correct reindex preflight classification for blocked replay candidates and non-null raw parse-error evidence.
Problem
The preflight ledger treated any replay candidate as executable even when all candidates were blocked, and it discarded empty or whitespace parse-error markers. Both behaviors distorted the source-remediation readiness decision.
Solution
raw_sessions.parse_errorvalue in source distribution and eligibility projections.Verification
devtools test tests/unit/devtools/test_preflight_ledger.py: 7 passed.devtools test tests/unit/daemon/test_raw_failure_sample.py -k lifecycle: 12 passed.devtools verify --quickat the exact headfd992631f: all 24 steps passed.