fix: NULL required_context_tokens handling in TUI ctx cell and metrics demand-ceiling path #96
Reference in New Issue
Block a user
Delete Branch "fix/required-context-null-guards"
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?
Two independent bugs in
required_context_tokenshandling.1. TUI
ctxcell renders literal "None"_render_decisions_table(src/tui.py:769) doesstr(r.get("required_context_tokens")),so a decision row without a context figure shows the literal string
"None"in thectxcolumn — the same defect theprofilecell was specifically written to avoid(see
.omo/notepads/tui-overhaul/issues.md, which recorded this as a one-linefollow-up but deliberately left it out of scope for that plan).
Fixed:
str(r.get("required_context_tokens") or "")— an absent value renders blank.No other cell in the same table uses the blind
str(dict.get(...))pattern on anullable column; id/kind/category/tier are non-nullable, profile is already guarded,
and the remaining cells pass through helpers.
Regression test:
test_app_decision_table_ctx_column_blank_not_none— asserts a 50000value renders
"50000"and aNonerenders"", never the literal"None".Proven non-vacuous: against old code the test fails with
AssertionError: assert 'None' == ''.2. NULL
required_context_tokensraises TypeError in demand-ceiling logicroute_decisions.required_context_tokensis a nullable column. SQLiteMAX()over anall-NULL group returns
NULL, not0— so a time window whose every row lacks atoken count produced
Nonewhere0(or a valid max) was expected, andNone > ceilingraised
TypeError. Three sites insrc/metrics.pywere affected:demand_ceiling_warnings(the MAX/comparison step):observed_max = None→ crashdemand_ceiling_warnings(the escalation p95 path):_percentilereceived a listcontaining
Nonemixed with ints →sorted()crashedcapability_demand_warnings(the MAX/comparison step): same shape as the firstSemantics: NULL is "no demand recorded for this row", not zero. All three are guarded
with presence-checks so a NULL value is excluded from comparisons — no crash, no
fabricated warning.
3 regression tests, all proven non-vacuous: each fails against old code with
TypeError: '>' not supported between instances of 'NoneType' and 'int'.Verification
/metrics+ SSE, 25s uptime): no errorssrc/tui.py(1 line),src/metrics.py(3 guard blocks),tests/test_metrics.py(125 lines, 3 tests),tests/test_tui.py(23 lines, 1 test)