madcop v1.3.0-rc.2 — Outcome-aware L3
Pre-release
Pre-release
v1.3.0-rc.2 closes the second half of the loop: every reflection is now stamped with outcome: success|failure at write time, and a new L3 layer re-ranks lessons accordingly before the planner sees them.
Backward-compat: rc.1 contract is bit-identical for any brain whose pages lack the outcome: field. Old skills, old tests, old chains keep working.
L1 side — outcome stamp
ReflectionMiddleware now stamps every skill page it writes with outcome: success|failure in the frontmatter and as a tag. The value is exposed on ctx.shared["reflection_outcome"] for chain observability.
L3 side — outcome-aware re-rank
New module madcop.agent.outcome ships:
boost_outcome(lessons, outcome_weight=0.4, half_life_days=60)— pure additive rerank.score += outcome_weight * (-1|0|+1) * recency_factor. Stable for ties (preserves rc.1 FTS5+recency order).OutcomePrioritizer— middleware atHOOK_PLAN_START, runs afterRetrievalMiddleware, rewritesctx.shared["prior_lessons"]in place.strategy="boost"(default) or"filter"(drops outcome:failure lessons).format_lessons_with_outcome(lessons)— renders a## Prior lessons (outcome-tagged)block with✓/✗/?glyphs per line, so the planner can weight lessons visually without a second LLM call.
Quick start
from madcop.agent import (
MiddlewareChain, QianControlMiddleware,
RetrievalMiddleware, OutcomePrioritizer,
)
chain = MiddlewareChain([
RetrievalMiddleware(db=db), # L2 — writes prior_lessons
OutcomePrioritizer(outcome_weight=0.4), # L3 — re-ranks them
QianControlMiddleware(),
])Defaults
outcome_weight = 0.4— small enough to preserve strong FTS5 hits, large enough to reorder ties.outcome_half_life_days = 60.0— 60-day-oldfailuretag carries ~50% weight; 1-year-old tag carries ~3%.strategy = "boost"(default) — additive, never destructive.
Tests
23 new tests in tests/agent/test_outcome.py. Total 901/901 passing.
Install
pip install --upgrade madcop==1.3.0rc2
Verification
- pytest: 901 passed in 4.90s
python3 -c "from madcop import __version__"->1.3.0rc2- Fresh-venv
pip install --force-reinstall madcop==1.3.0rc2-> imports L3 surface; syntheticsucc -> unk -> failE2E order PASS