decision-system S9: demotion and the One Thing question #1251
Labels
No labels
P0
P1
P2
P3
bug
category/code-change
category/cross-repo
category/eval-run
category/investigation
category/no-test-target
category/owner-ruling
category/prose-artifact
category/recurring-chore
category/structure
category/umbrella
crc-refactor
create
delete
enhancement
filed-by/agent
filed-by/user
frozen
lint-rule
needs-info
needs-triage
next
plugin/cc-architect
plugin/os
plugin/os-adr
plugin/os-aidd-lint
plugin/os-backlog
plugin/os-context
plugin/os-doc-hygiene
plugin/os-sdlc
plugin/os-vault
project/cc-os
ready-for-agent
ready-for-human
recurring
review
rule-proposal
update
waiting
wayfinder:grilling
wayfinder:map
wayfinder:map
wayfinder:research
wayfinder:task
wayfinder:task
wontfix
worklist/deviations
worklist/lint-rule
worklist/new-implement-build
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
jared/cc-os#1251
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?
Problem
Confirmed patterns must become lessons so agents need Jared less (D-6, #1240). Today nothing groups the train moments in the Store
moments.jsonlinto patterns, and nothing finds the patterns that are ready to become a One Thing question. S9b asks the question; it needs a list of candidates first.Approach
Required work:
OsMe::OllamaEmbedder:#embed(texts)posts{"model" => MODEL, "input" => texts}toapi/embedthrough a connection that answerspost_json(path, body)and returns theembeddingsarray.MODELisnomic-embed-text..standardbuilds it onDecision::Model::Http::Connectionathttp://localhost:11434. No vector is written to disk; each run embeds again. check: presentclass OllamaEmbedderinplugins/os-me/lib/**/*.rbOsMe::PatternClusterer: takes an embedder (any object with#embed(texts)), embeds theheadlineof each ruling moment in one call, and groups moments in one greedy pass by id order: a moment joins the first cluster whose seed vector has cosine similarity at or aboveSIMILARITY(0.85), else it starts a new cluster. A ruling moment ismemo_replywith outcomeaccept,modify, oroverride, or kindquestion_answer,correction, ordirection. check: presentclass PatternClustererinplugins/os-me/lib/**/*.rbOsMe::PatternCluster: holds the moment rows;#sessions(distinct session ids),#agreement(mean ofCalibrationReport::HITover thememo_replyoutcomes; eachquestion_answer,correction, ordirectionmoment counts 1.0, because it is Jared's own ruling),#moment_ids,#headline(the headline of the seed moment). check: presentclass PatternClusterinplugins/os-me/lib/**/*.rbOsMe::LessonCandidate:MIN_SESSIONS = 3,MIN_AGREEMENT = 0.8,#eligible?,#id(first 12 hex digits of the SHA-256 of the sorted moment ids joined by newlines),#question, and#to_hfor the log row. check: presentclass LessonCandidateinplugins/os-me/lib/**/*.rbOsMe::CandidateLogover the Store filequeue/lesson-candidates.jsonlandOsMe::CandidateRefresh:#runreads onlyMomentExtractor::TRAIN_LOG, clusters, and appends one row{id, question, moment_ids, sessions, agreement, moments, status: "open", created_at}per eligible cluster that shares no moment id with a row already in the log. check: presentclass CandidateRefreshinplugins/os-me/lib/**/*.rbos-me-eval candidatescommand: it runsCandidateRefreshon--storewithOllamaEmbedder.standardand prints the number of new rows. check: presentdesc 'candidates'inplugins/os-me/lib/os_me/cli.rbNotes: The rule sentence is the seed headline, not a model draft: the
decision-modelgem has no free-text question type (types arechoice,noul,score), and a deterministic sentence costs no model call.MomentLogstays unchanged (O-2 is not touched). Tests use a fake embedder that returns fixed vectors and a fake connection; no test calls Ollama. Fail loudly: an embedder error ends the run before any row is written. AFK defaults used: O-8 (no Ollama model pull without approval; thenomic-embed-textmodel is not on this machine, so the live command fails until Jared approves the pull).Acceptance criteria
[1, 0],[0.99, 0.1], and[0, 1], whenPatternClusterer#clusterruns, then onePatternClusterholds the first two moment ids and a second cluster holds the third.noneandover_escalationand amemo_replymoment with outcomenone, whenPatternClusterer#clusterruns, then no cluster holds them and the fake embedder receives none of their headlines.memo_replymoments from 3 sessions with outcomesaccept,accept,modify,accept,accept, when aLessonCandidateis built from it, thenagreementis 0.9 andeligible?is true.acceptmoments from 2 sessions, when aLessonCandidateis built from it, theneligible?is false.accept,accept,override,accept, when aLessonCandidateis built from it, thenagreementis 0.75 andeligible?is false.direction, onecorrection, and onequestion_answermoment from 3 sessions, when aLessonCandidateis built from it, thenagreementis 1.0 andeligible?is true.Decision: cache the index, whenLessonCandidate#questionis read, then it returnsIn 4 sessions you ruled on "Decision: cache the index". Is this a rule? (y/n).moments.jsonlholds one eligible cluster and a fake embedder, whenCandidateRefresh#runruns twice, thenqueue/lesson-candidates.jsonlholds exactly one row, with statusopen, the question, and the cluster's moment ids.CandidateRefresh#runruns, then the error reaches the caller andqueue/lesson-candidates.jsonldoes not exist.{"embeddings" => [[0.1, 0.2], [0.3, 0.4]]}, whenOllamaEmbedder#embed(["a", "b"])runs, then the connection receives pathapi/embedand body{"model" => "nomic-embed-text", "input" => ["a", "b"]}, and the result is[[0.1, 0.2], [0.3, 0.4]].Owner sketch
Scope and blocking
Blocked by: #1245
Blocked by: #1249
Design is in
docs/decision-system/learning-loops.md(loop 2: demotion). Related: #1240. S9b (the One Thing question, the session ledger, and the verdict readback) is a separate ticket blocked by this one.Non-goals: the One Thing question and the SessionStart hook (S9b); a model-drafted rule sentence; the calibration factor in
demotion_value(S9b orders by moment count); tuningSIMILARITY(S10); a stored vector index; writing a confirmed lesson to its destination.Origin
DESIGN(docs/decision-system/build-plan.md).VERDICT: CREATE (user-approved; backlog search only)
Work started on branch ticket-1251 (os-sdlc implement, AFK decision-system build, S9a).
Resolution
Done: Train ruling moments are clustered by headline embedding; clusters with 3+ sessions and 80% agreement become open lesson candidates in queue/lesson-candidates.jsonl; os-me-eval candidates runs the refresh.
Evidence: Implementation 141: 8 dispatches, 0 retries, 7 min 58 s, implementation_complete. Suite gate green. Records commit on ticket-1251.
Follow-ups: S9b is #1278 (the One Thing question and verdict readback). The live candidates command needs an embedding model; pulling nomic-embed-text waits for Jared's approval (O-8), reported to Jared in session. SIMILARITY tuning belongs to S10.