decision-system S4: levers and os-me-route in predict #1246
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#1246
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
A prediction does not record where its answer can come from or how much a wrong ruling costs. Thus no caller can set the confidence that a row needs. The design names four objects for these labels:
AnswerSource,WrongCostAssessor,WrongCost, andRequiredBand(docs/decision-system/levers.md, levers 1 to 3). None of them exists. This ticket is the first of three S4 tickets. S4b adds the evidence-loop objects. S4c adds the parser fields and theos-me-routeCLI.Approach
The model-backed objects use the
DecisionModelport that exists today, not the sketch inlevers.md. The port has one shape:Client#ask(question, rules)takes oneDecisionModel::Question.new(text:, options:)and returnsDecisionModel::Answer.new(choice:). The answer has no probability. Thus:AnswerSource#classify(row)asks one question. Its options are%w[rule precedent facts experiment taste], in this order. Its text holds the row text and the five criterion sentences fromlevers.md, lever 1. It returnsAnswerSource::Result.new(source: <choice as a symbol>).Resulthas noprobabilityfield.WrongCostAssessor#assess(row)asks three questions, in this order:hard_to_undo,compounds,stays_hidden. Each question has the options%w[yes no]. Its text holds the row text and the instruction sentence for that key fromlevers.md, lever 2. The choiceyesgivestrue. The choicenogivesfalse. There is no threshold.The lever tables give these values:
max_rungnovel?ruleprecedentfactsexperimenttasteWrongCost#levelRequiredBand#for:lownil:medium:high:highRowis the input of the model-backed levers. It holds the row text only. O-9 is settled: the levers live in os-me, and os-sdlc calls theos-me-routeCLI (S4c). The ADR challenge rejected an ADR.Required work:
Row, a value that holds the row text — check: presentData.define(:text)inplugins/os-me/lib/os_me/row.rbAnswerSourcewithMAX_RUNGandResult— check: presentMAX_RUNG = { rule: 1, precedent: 1, facts: 2, experiment: 3, taste: 0 }inplugins/os-me/lib/os_me/answer_source.rbWrongCostwithyes_countandlevel— check: presentLEVELS = { 0 => :low, 1 => :medium, 2 => :high, 3 => :high }inplugins/os-me/lib/os_me/wrong_cost.rbWrongCostAssessorthat asks the three yes/no questions — check: presentclass WrongCostAssessorinplugins/os-me/lib/os_me/wrong_cost_assessor.rbRequiredBand— check: presentBY_LEVEL = { low: nil, medium: 70, high: 85 }inplugins/os-me/lib/os_me/required_band.rbAcceptance criteria
rule,precedent,facts,experiment, andtastein turn, whenAnswerSource#classifyruns once for each answer, then the results havesource:rule,:precedent,:facts,:experiment,:taste;max_rung1, 1, 2, 3, 0; andnovel?false, false, false, false, true.Move Gate::StepOutcome to OsSdlc::StepOutcome., whenAnswerSource#classifyruns, then the adapter gets one question with the options["rule", "precedent", "facts", "experiment", "taste"], and the question text includes the row text and the sentenceJared ruled the same kind of case in an earlier session.yes,no,yesin turn, whenWrongCostAssessor#assessruns, then it returnsWrongCost.new(hard_to_undo: true, compounds: false, stays_hidden: true).Delete the OsSdlc::Error root., whenWrongCostAssessor#assessruns, then the adapter gets three questions, each with the options["yes", "no"]. Each question text includes the row text. The first question text includesdeletes code or policy. The second includessets a pattern. The third includesNo test, lint cop, or later gate.WrongCost.new(hard_to_undo: false, compounds: false, stays_hidden: false), whenlevelruns, then it returns:low, andyes_countreturns 0.WrongCostwith exactly onetruefield (three cases), whenlevelruns, then each returns:medium.WrongCost.new(hard_to_undo: true, compounds: true, stays_hidden: false)andWrongCost.new(hard_to_undo: true, compounds: true, stays_hidden: true), whenlevelruns, then both return:high.:low,:medium, and:high, whenRequiredBand#forruns, then it returnsnil, 70, and 85.no,yes,no(the S22 worked example inlevers.md), whenWrongCostAssessor#assessruns andRequiredBand#forreads the result, then the level is:mediumand the band is 70.OsMe::DecisionModel::UnreadableAnswer, whenWrongCostAssessor#assessruns, then the error reaches the caller.Owner sketch
Non-goals
ConfidenceBand.claimed,EvidenceLadder,StopRule,StakeReducer,CostModel(S4b).os-me-routeCLI (S4c).AnswerSource::Result. TheDecisionModelport gives none.DecisionModelport.Origin
DESIGN(docs/decision-system/levers.md).VERDICT: CREATE (user-approved; backlog search only)
jared referenced this issue2026-10-23 15:17:26 +00:00
Work started on branch ticket-1246 (/os-sdlc:implement, S4a).
Resolution
Done: S4a built: Row, AnswerSource (+Result), WrongCost, WrongCostAssessor, RequiredBand on the current DecisionModel port; implementation 127 complete.
Evidence: Branch ticket-1246, Runner commit; suite and lint gates green; contract audit pass after one refactor round; 10 acceptance criteria covered in answer_source_test.rb and wrong_cost_test.rb.
Follow-ups: S4b #1262 and S4c #1263 continue S4. A lens proposal on A3 (prefix-sharing assessor under a ticket-pinned name) goes through the lens challenge. S8 #1250 swaps the DecisionModel port to the decision-model gem, which changes AnswerSource and WrongCostAssessor asks.