decision-system S3: calibration report #1245
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#1245
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
No report shows if a stated confidence is true. A memo that says "80%" must be right about 80% of the time. The moment log (S2) and the prediction log hold the outcomes, but no object turns them into hit rates per confidence band. Design:
docs/decision-system/learning-loops.md, "Loop 1: calibration" and theTuneSplitsketch.Approach
Points come from two sources, in one
Pointshape. The report does not join the two sources.moments.jsonl)ConfidenceBand.of_percent(stated_percent)outcomesource, else itskind(memo_reply)prediction-log.jsonl)ConfidenceBand.of_percent(confidence)hit=accept,partial=modify,miss=overridepredictionA moment with outcome
none, a moment with nostated_percent, a record with noconfidence, and a record with no verdict give no point. Hit value:accept1.0,modify0.5,override0.0. Brier usesband / 100.0as the forecast.ConfidenceBanddoes not exist yet. Add onlyLEVELS = [50, 65, 80, 90]andself.of_percent(percent) = LEVELS.select { |l| l <= percent }.max || 50; S4 adds the rest (levers.md, "ConfidenceBand").TuneSplitsplits train moments into tune and holdout by a hash of the moment id, as inlearning-loops.md:holdout?(moment_id) = Digest::SHA256.hexdigest("tune:#{moment_id}").to_i(16) % 100 < 20. It does not callOsMe::Split.Required work:
ConfidenceBand.of_percent— check: presentdef self.of_percentinplugins/os-me/lib/os_me/confidence_band.rbTuneSplit#holdout?that hashestune:plus the moment id — check: present"tune:#{moment_id}"inplugins/os-me/lib/os_me/tune_split.rbCalibrationReport,Point, and the commandos-me-eval calibration— check: presentclass CalibrationReportinplugins/os-me/lib/os_me/calibration_report.rbAcceptance criteria
ConfidenceBand.of_percentruns, then it returns 65; given 45, it returns 50; given 95, it returns 90.abc:7, whenTuneSplit#holdout?runs, then it returns the value ofDigest::SHA256.hexdigest("tune:abc:7").to_i(16) % 100 < 20.s:0tos:999, whenTuneSplit#holdout?runs on each, then between 150 and 250 of them are holdout.modify, when the report renders, then the band 65 hit rate is 0.50.acceptand one point in band 65 with outcomeoverride, when the report renders, then the Brier line reads 0.23.accept, whenos-me-eval calibrationruns, then the output has a band 65 row with hit rate 1.00 and amemo_replysource row with hit rate 1.00.partial, whenos-me-eval calibrationruns, then the output has a band 80 row with hit rate 0.50 and apredictionsource row with hit rate 0.50.noneor no stated percent, whenos-me-eval calibrationruns, then it counts none of them and printsBrier: n/a.Owner sketch
Non-goals
Per-route and per-labeler tables, ECE,
p_wrong, andhit_rate(band:, source:)for other objects (S4, S5). Lever changes (S4). Tuning (S10).Origin
TuneSplit, and the run built a session join with free band labels.DESIGN(docs/decision-system/learning-loops.md).Work started on branch ticket-1245 (os-sdlc implement pipeline). S2c extraction rerun is in progress; this run builds the S3 objects against fixtures.
Implementation 124 failed at suite-check (gate_skip): the orchestrator passed the previous agent's dispatch ID in the prompt. The green work also missed the design in learning-loops.md (band labels joined by session, TuneSplit reused the held-out split, outcome none counted as a miss). The off-design work is discarded. The body now pins the band rule, the two point sources, and TuneSplit in nine acceptance criteria. A fresh implementation follows.
Resolution
Done: ConfidenceBand.of_percent (50/65/80/90), TuneSplit#holdout? (SHA256 of tune:, 20%), Point, CalibrationReport (moments and prediction records as two point sources; too few under 20 points; modify counts half; Brier from band/100), and os-me-eval calibration. Built by implementation 125 after implementation 124 failed (orchestrator passed a stale dispatch ID; loose criteria let the build miss learning-loops.md). Body rewritten with nine acceptance criteria.
Evidence: Implementation 125 complete: 11 dispatches, 6 min 37 s; suite-check pass twice; contract audit pass after one refactor. Runner commit on ticket-1245 with 9 paths under plugins/os-me.
Follow-ups: none; the S3 data gate (three band cells with 20 or more points) runs on the real Store after the S2c extraction rerun, as orchestrator work under #1244