workflow-fix: sweep park predicate misses mid-note parks
Highlight text on any card (body, plan, or an event) to anchor a comment, or leave a whole-task comment here. Mention @claude to summon a reply.
No comments yet.
Overview / Motivation
Auto-filed by /daily 2026-07-11 from its own problem sweep (emitting agent: /daily orchestrator; the Step C enumerator missed a genuinely parked candidate tonight).
Goal
Broaden sweep_parked_wf_candidates.py _row_is_parked to match a park declaration anywhere in the note (e.g. Routing: parked / a parked + recursion-guard mention mid-note), not only a leading parked or routed: parked.
Workflow gap
- Bug observed:
_row_is_parkedmisses genuinely parked candidates whose note prefixes the park declaration with other prose — #1271's Guard-1 candidate note (2026-07-11T18:39:16Z) starts with a root-sync recovery record and ends withRouting: parked — running under workflow_fix_target recursion guard ..., matching neither_PARKED_LEAD_RE.matchnor the literalrouted: parked, so the 2026-07-11 Step C sweep silently skipped it (it was recovered only because the /daily transcript miner independently surfaced it). - Why it is a workflow gap: the sweep is the recursion-guard escape valve's only routing path; a parked candidate it cannot see is a dropped bug, violating the "never silently lost" contract in
.claude/rules/workflow-fix-on-bug.md§ Recursion guard. - Confidence (emitter): high
- verified-at-filing:
grep -n "parked" scripts/sweep_parked_wf_candidates.py→_PARKED_LEAD_RE = re.compile(r"\s*parked\b", re.IGNORECASE)(line 104, used via.match) +_PARKED_ROUTED_RE = re.compile(r"routed:\s*parked\b", ...)(line 105) are the only two accept paths in_row_is_parked(lines 195–201); #1271's note verified to match neither (2026-07-12).
Proposed change (candidate diff sketch — refine in planning)
_PARKED_ROUTED_RE = re.compile(r"routed:\s*parked\b", re.IGNORECASE)
+ _PARKED_MIDNOTE_RE = re.compile(r"(?i)\brouting:\s*parked\b|\bparked\b[^\n]{0,120}recursion guard")
def _row_is_parked(row):
- if _PARKED_LEAD_RE.match(note) or _PARKED_ROUTED_RE.search(note): return True
+ if _PARKED_LEAD_RE.match(note) or _PARKED_ROUTED_RE.search(note) or _PARKED_MIDNOTE_RE.search(note): return True
Plus a red fixture reproducing the #1271 note shape (record-prose prefix + trailing Routing: parked). Keep the suppression logic (routed-record matching) unchanged.
Scope / surfaces
- Primary target:
scripts/sweep_parked_wf_candidates.py - Tests: the sweep's existing test file (add the #1271-shape fixture red-green).
Constraints / invariants
- Workflow-surface only; ruff passes; the sweep stays read-only.
- This session runs under
EPM_WORKFLOW_FIX_SESSION=1and carries aworkflow_fix_target:Provenance line — it MUST NOT auto-route any of its own subagents' workflow-fix candidates (recursion guard).
Provenance
- workflow_fix_target: scripts/sweep_parked_wf_candidates.py
- fingerprint: ae7b7d49ff93
Origin: /daily 2026-07-11 problem sweep — the Step C run at 2026-07-12T06:32Z returned 6 candidates and omitted #1271's formal Guard-1 candidate (epm:workflow-fix-candidate v1, 2026-07-11T18:39:16Z), which a transcript miner independently surfaced the same night.