Skip to main content

max / makenotwork

painhours: stop the default factors self-promoting to Critical DEFAULT_FACTOR was 3, the arithmetic midpoint of 1-5, which reads as the neutral choice. It is not: with the exponents this crate ships, a 3x3 item crosses BAND_CRITICAL in week 4. Any ingest that omitted the factors therefore promoted itself to Critical within a month, before a human had judged it. GoingsOn's /dellm migration ingested 446 problems at once and 159 of them crossed the line together on day 28, which is what surfaced it. Drop the default to 2 (~10 weeks to Critical), and pin the property rather than just the number: DEFAULT_TRIAGE_WEEKS names the window the default is chosen against, and default_does_not_self_promote asserts both ends of it, that an unscored item stays out of Critical inside the window and still reaches it within a year. Anti-starvation is why the age term exists, so a default that never escalated would be its own bug. The test guards the whole tuning block, not just the constant: raising an exponent or lowering PAINHOURS_K far enough now fails here instead of quietly re-arming the fuse.
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>
Author: Max Johnson <me@maxj.phd> · 2026-08-07 21:36 UTC
Signed with PGP, not checked
Commit: e6fb77a25c837bf988c62f2a33adb5c3090fe698
Parent: 3b143af
1 file changed, +48 insertions, -1 deletion
@@ -77,7 +77,33 @@
77 77 const BAND_MEDIUM: u32 = 20;
78 78
79 79 /// Default 1-5 guesstimate for both `pain` and `scale` when unspecified.
80 - pub const DEFAULT_FACTOR: u8 = 3;
80 + ///
81 + /// **Not the midpoint, deliberately.** 3 is the arithmetic middle of 1-5 and
82 + /// reads as the neutral choice, but neutrality is a property of the curve, not
83 + /// of the number: with the exponents above, a 3x3 item crosses
84 + /// [`BAND_CRITICAL`] in **week 4**. Any ingest that omits the factors would
85 + /// therefore promote itself to Critical within a month of arriving, without a
86 + /// human ever having judged it. That is not a default, it is a fuse.
87 + ///
88 + /// 2 crosses Critical at ~10 weeks instead, which leaves room for a real triage
89 + /// pass before the score starts making claims on someone's attention. An
90 + /// undertriaged item still climbs, because anti-starvation is the point of the
91 + /// age term; it just no longer outruns the triage it is waiting for.
92 + ///
93 + /// [`default_does_not_self_promote`](tests::default_does_not_self_promote) pins
94 + /// the relationship, so changing an exponent or `PAINHOURS_K` cannot quietly
95 + /// re-arm it.
96 + pub const DEFAULT_FACTOR: u8 = 2;
97 +
98 + /// The triage window [`DEFAULT_FACTOR`] is chosen against: an item carrying only
99 + /// the defaults must not reach [`BAND_CRITICAL`] inside this many weeks.
100 + ///
101 + /// Eight weeks is two monthly audit passes, so a finding nobody has scored gets
102 + /// looked at twice before the ranking starts insisting on it.
103 + ///
104 + /// Public because it is contract, not trivia: a caller deciding whether to score
105 + /// a finding by hand is really asking how long the default buys it.
106 + pub const DEFAULT_TRIAGE_WEEKS: u32 = 8;
81 107
82 108 /// Seconds in a week, the unit age is measured in.
83 109 const SECS_PER_WEEK: f64 = 7.0 * 86_400.0;
@@ -242,6 +268,27 @@
242 268 assert!(painhours(3, 3, 4) > painhours(3, 3, 1));
243 269 }
244 270
271 + /// The invariant `DEFAULT_FACTOR` is chosen for: an unscored item must not
272 + /// climb to Critical before anyone has had a fair chance to triage it.
273 + ///
274 + /// This is the guard on the whole tuning block, not just the default. Every
275 + /// constant above feeds the crossing point, so raising an exponent or
276 + /// lowering `PAINHOURS_K` far enough will fail here, which is the intended
277 + /// warning: the escalation curve and the default have to be picked together.
278 + #[test]
279 + fn default_does_not_self_promote() {
280 + let d = DEFAULT_FACTOR;
281 + assert_ne!(
282 + band(d, d, DEFAULT_TRIAGE_WEEKS),
283 + Priority::Critical,
284 + "an item carrying only the default factors reached Critical within \
285 + {DEFAULT_TRIAGE_WEEKS} weeks, so undertriaged input promotes itself"
286 + );
287 + // And it must still climb eventually: anti-starvation is the reason the
288 + // age term exists, so a default that never escalated would be its own bug.
289 + assert_eq!(band(d, d, 52), Priority::Critical);
290 + }
291 +
245 292 #[test]
246 293 fn fresh_blocker_reads_high() {
247 294 // The calibration claim in PAINHOURS_K's docs: pain 5, scale 5, week one