Broad domains compile from project narrative, not generalisable rules — 'python' can never clear reinforcement #33
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Observed on: 6.7.0
Observation
compile_skill(domain='python', mode='propose')found a pool of 29 candidates and produced zero rules — nothing recurred across themin_reinforcement=2threshold. The gate behaved correctly. The interesting part is what the candidates were:find_all_duplicates()returned list[l…"find_all_duplicates()and_has_negation_pair()functions from…"These aren't Python rules. They're OmniMem project history that happens to carry a
pythontag. Some are Python-adjacent facts about Valkey commands; others are narrative about what happened in a particular PR.Why this won't fix itself
The domain will never compile, and lowering
min_reinforcementis the wrong lever — it would admit the noise rather than find the signal. Two candidate readings, and it's worth deciding which:1.
pythonis too broad for this corpus. Nearly every Python memory here belongs to one project, so "the Python domain" and "OmniMem's history" are the same set. Reinforcement can't distinguish a recurring language pattern from two unrelated episodes in the same codebase. Narrower domains (valkey-search,mcp-server-design) might have enough internal repetition to clear the gate, which is roughly what the existing three compiled skills look like.2. The
breakthroughfield is written as narrative, not as a rule.record_experience()captures what happened, in past tense, tied to the specific incident. A rule needs to be a generalisable claim. "Community PR merged cleanly despite significant changes" can never become a rule no matter how often something like it recurs, because it isn't the kind of sentence a rule is. The valkey-pydropindex()memory is the counter-example that proves the point — its breakthrough field explicitly generalises ("when a fake stands in for a component with known divergent behaviour, the fake must reproduce the divergence"), and that is rule-shaped.If (2) is the main factor, the fix is upstream of the compiler: prompt for the generalisable lesson at record time, separately from the narrative of what happened. That's a schema change, so worth deciding before more experience data accumulates in the current shape.
Suggested next step
Try
compile_skill()against a narrower domain that maps to genuine cross-project work (valkey,testing) and see whether reinforcement clears there. That distinguishes reading 1 from reading 2 cheaply, without changing anything.Related
Partly addressed in 6.7.1 (
b4822f3onv6.7.x) — diagnostics only, and the design question you raise is deliberately left open.What shipped:
insufficient_reinforcementnow reportspool_concentration, and when every candidate in the pool comes from a single project it says so outright. That is the whole of reading 1, available at the point of use — you no longer have to run the experiment to discover that "thepythondomain" and "this project's history" are the same set of memories here, and that reinforcement therefore cannot distinguish a recurring language pattern from two unrelated episodes in one codebase.The note also stopped recommending that you lower
min_reinforcement, which it previously did. You're right that it's the wrong lever: when the candidates are narrative rather than generalisable claims, a lower gate admits the noise instead of finding the signal, turning a domain that correctly compiled nothing into one that compiles the wrong thing. It points atbless()and at narrower domains instead, and tells you what to look for in the held_back text — which is now readable in full (#32).What is not fixed, and why. Reading 2 — that
breakthroughis written as narrative of what happened rather than as a generalisable claim, so the fix belongs upstream atrecord_experience()— is a schema change, and this was a patch release. Your own framing is the argument for not rushing it: it's worth deciding before more experience data accumulates in the current shape, and that decision is yours rather than something to settle as a side effect of fixing six other issues.I'd suggest a fresh issue for that specifically — capturing the lesson separately from the narrative at record time — since it's a design question with a real migration behind it, not a bug. Happy to open it if you want.
Closing this one as the diagnostic work is done; reopen or link the follow-up as you prefer.
Follow-up opened as #35 for the schema half — separating the generalisable claim from the narrative at
record_experience()time, with the four decisions it needs.