Restack learning routing onto current #569 tip (#570) - #745
Merged
Merged
Conversation
…ure it Concrete basis for the discussion in #565, deliberately not wired into any skill. The design decisions worth arguing about are which artefacts require what, and that should be settled before anything enforces it. The problem: context carries no freshness marker. A calendar read from four hours ago and one from a minute ago sit side by side with identical authority, which is how a long session ends up using yesterday's date, an unchecked inbox, and a stale task list while sounding entirely current. Three pieces. **A per-vault declaration** (System/knowledge-half-life.yaml, shipped as seed so user tuning is never overwritten). Volatility is personal: one person's pipeline moves weekly, another's task list hourly, so a fixed table ships wrong for most people. Sources that do not decay are declared `never`, because a user's decisions and corrections are superseded rather than aged out. **Observations recorded mechanically.** A PostToolUse hook stamps a source the moment a tool that reads it is called. This is the part that matters: an assistant that cannot notice its context has gone stale is exactly the one that will forget to record when it last looked, so self-reporting would inherit the original defect. The ledger reflects what happened, not what was believed. **An artefact contract**, which is the half that can honestly be enforced. An assistant cannot audit its own memory for staleness, but "a daily plan requires a calendar read newer than its half-life" is checkable from outside. On this vault, run against yesterday's daily plan, it returns exactly the failure that occurred: email STALE at 240 minutes, week_priorities NOT OBSERVED. Distinctions the module refuses to collapse, each of which has already caused a real failure somewhere in this codebase: a missing config is UNAVAILABLE rather than everything-is-fresh; a typo in a half-life fails loudly rather than silently becoming fresh-forever; an unknown source gets the cautious answer; and "stale" reads differently from "never observed" because they call for different responses. 18 tests. All twelve quality gates pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Co-authored-by: davekilleen <davekilleen@users.noreply.github.com>
Raised on review. The single meetings entry conflated two things with opposite decay: whether new captures exist, which goes stale within the hour, and what was said in a meeting, which does not go stale at all. A finalised transcript is a record, superseded by a later meeting rather than aged out, so it belongs with decisions and corrections in the never category. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: davekilleen <davekilleen@users.noreply.github.com>
Offered against #503, to @joshm-simril's design and @davekilleen's spec. The routing table is Josh's, kept as data rather than code so it can be edited without touching this module, which was one of his own open questions. Deliberately does NOT apply anything. Dex must never silently rewrite its own instructions, so the edit has to be shown and confirmed before it lands, and confirmation belongs in the skill that can hold a conversation. Everything here is analysis and bookkeeping. The split is the point: clustering and destination-proposal are mechanical and testable, while deciding whether a proposed edit is right is judgement. Mixing them would bury an unreviewable decision inside something that looks like a helper. Four pieces, matching the spec on #503: - Parse entries from Session_Learnings with enough location to rewrite one status without disturbing its neighbours. - Cluster by proposed destination rather than by wording, because two entries belonging in the same file are worth reviewing together even when they read differently. Josh's observation was that eight related entries became one rule, not eight edits. - Trigger on volume OR age. Age matters independently: a single correction left for a fortnight is a worse signal than ten from this morning, and a count-only trigger never fires on a slow, steady leak. - Record an outcome as implemented (date and destination) or dropped (date and reason), so a falling count means something was installed rather than something ageing out of view. An invented third status is refused. 14 tests, including that two entries in one file can never have their statuses crossed. All twelve quality gates pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
What this pull request touches
Gates that will judge this change
Based on 12 changed files. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Linked Issue
What Changed
048febde→97c7f1f1) onto Restack knowledge half-life onto current main (#569) #744 headf35e24df1cb30d593c601a5afc2c7c7ea5e5f8e6main(Capture corrections when they happen, not at the end of the day #568) or restacked in Restack knowledge half-life onto current main (#569) #744 (Proposal: declare how long an observation stays trustworthy, and measure it #569)Old fork head:
048febdefea55a067199f3cc4d7e60848d27f1de(chrisjackson-coding:learning-routing)New same-origin head:
97c7f1f1f6cc93fb17cb839869ceef441ff05b32Stacked on: #744 (
f35e24df) which itself sits onmain#568(8cf7dd84)The original fork PR (#570) is DIRTY and cannot be force-pushed (workflow-file restriction on the
chrisjackson-codingfork). This same-origin branch is the MERGEABLE restack, same pattern as #744 / #743 / #742.Test Plan
core/tests/test_learning_routing.py(14 tests, carried forward from Starter for the learning routing step from #503: parse, cluster, propose, record #570)pytest core/tests/test_learning_routing.py→ 14 passedpytest core/tests/test_freshness.py→ 18 passedpytest core/tests/test_mcp_session_lifecycle.py→ 10 passed (includingtest_parent_death_reaps_the_process_pairon first run; no wait hardening)Ralph Wiggum Loop
Quality Gates
Risk & Rollback
Docs Impact
Notes
main