Summary
The monitor-tick tick-history watch array uses inconsistent free-form keys for the same recurring concern across ticks, fragmenting /daily-summary aggregation. This is the same #3753 watch-token-spread class already filed for the warnings field (#3882) and the actions field (#3928) — but the watch field itself was never canonicalized, and no open issue covers it.
Scope-diff vs siblings: #3882 = warnings field; #3928 = actions field (missing commented verb); #3923 = daily-summary consumer side. This issue = the watch field emit side. Together the three fields (warnings/actions/watch) are the full free-form tick-history surface; watch is the last one uncovered.
Evidence (24h digest, 2026-08-27T15:05Z, deployed sha 0ac84d4, node OFFLINE/HOLD)
Aggregating watch keys across the last 23 ticks, several single concerns each appear under 2–4 distinct keys:
- node-down:
node_down ×13, node_down_h ×4, node_offline ×1 (3 spellings)
- deploy-hold/quarantine:
deploy-blocked ×12, deploy_hold ×6, deploy_blocked ×1, deploy_gate ×1, quarantine ×16 (fragmented)
- CI History-Publish failure:
ci_history_publish_fail ×13, ci_history_publish ×2, ci_known_fail ×1, ci_known ×1, ci ×5 (4+ spellings)
- outage duration:
outage_h ×18, downtime_h ×1 (2 spellings)
During the current 5-day #3905 outage, this directly undermines the daily-summary's ability to surface the ongoing outage as a single clean signal — the exact failure mode #3753 proved can hide a multi-day structural condition.
Root cause
SKILL.md's Tick-history-capture section documents watch as free-form key=value with only illustrative examples (pruning_gap=2451, frag_pct=18, disk_pct=72, wipe=session-dir). For qualitative recurring concerns (node down, deploy hold, known-CI-fail, outage age) there is no canonical key enumeration, so each tick's agent invents its own spelling. The helper monitor-tick-artifacts.py splits watch (_split_csv) but does not pin its keys to any vocabulary (unlike warnings/actions, which map to metric-alarms.toml's closed vocab — though #3882 shows even those fragment on the emit side).
Proposed fix
Codify a canonical key vocabulary for the recurring qualitative watch concerns (e.g. node_down, deploy_hold, outage_h, ci_known_fail, quarantine) in metric-alarms.toml (or a dedicated watch_vocab table), document it in the SKILL.md tick-history template, and — mirroring #3882's approach — pin the emit side. Measurement-style keys (disk_free_gb=, frag_pct=, startup_peak_mb=) stay free-form value-carrying but with canonical key names. /daily-summary needs no change (it aggregates whatever stable key appears; fixing the emit side suffices, exactly as in #3753/#3882).
Scope / tier
Self-reflection Tier 2 — touches the tick-history data contract consumed by /daily-summary (cross-skill), so filed rather than inline-edited. Non-urgent: aggregation fragmentation; consensus unaffected. Related to #3882 (warnings), #3928 (actions), #3923 (daily-summary consumer), #3753 (originating class).
Summary
The
monitor-ticktick-historywatcharray uses inconsistent free-form keys for the same recurring concern across ticks, fragmenting/daily-summaryaggregation. This is the same #3753 watch-token-spread class already filed for thewarningsfield (#3882) and theactionsfield (#3928) — but thewatchfield itself was never canonicalized, and no open issue covers it.Scope-diff vs siblings: #3882 =
warningsfield; #3928 =actionsfield (missingcommentedverb); #3923 = daily-summary consumer side. This issue = thewatchfield emit side. Together the three fields (warnings/actions/watch) are the full free-form tick-history surface;watchis the last one uncovered.Evidence (24h digest, 2026-08-27T15:05Z, deployed sha 0ac84d4, node OFFLINE/HOLD)
Aggregating
watchkeys across the last 23 ticks, several single concerns each appear under 2–4 distinct keys:node_down×13,node_down_h×4,node_offline×1 (3 spellings)deploy-blocked×12,deploy_hold×6,deploy_blocked×1,deploy_gate×1,quarantine×16 (fragmented)ci_history_publish_fail×13,ci_history_publish×2,ci_known_fail×1,ci_known×1,ci×5 (4+ spellings)outage_h×18,downtime_h×1 (2 spellings)During the current 5-day #3905 outage, this directly undermines the daily-summary's ability to surface the ongoing outage as a single clean signal — the exact failure mode #3753 proved can hide a multi-day structural condition.
Root cause
SKILL.md's Tick-history-capture section documentswatchas free-formkey=valuewith only illustrative examples (pruning_gap=2451,frag_pct=18,disk_pct=72,wipe=session-dir). For qualitative recurring concerns (node down, deploy hold, known-CI-fail, outage age) there is no canonical key enumeration, so each tick's agent invents its own spelling. The helpermonitor-tick-artifacts.pysplitswatch(_split_csv) but does not pin its keys to any vocabulary (unlikewarnings/actions, which map to metric-alarms.toml's closed vocab — though #3882 shows even those fragment on the emit side).Proposed fix
Codify a canonical key vocabulary for the recurring qualitative
watchconcerns (e.g.node_down,deploy_hold,outage_h,ci_known_fail,quarantine) inmetric-alarms.toml(or a dedicatedwatch_vocabtable), document it in the SKILL.md tick-history template, and — mirroring #3882's approach — pin the emit side. Measurement-style keys (disk_free_gb=,frag_pct=,startup_peak_mb=) stay free-form value-carrying but with canonical key names./daily-summaryneeds no change (it aggregates whatever stable key appears; fixing the emit side suffices, exactly as in #3753/#3882).Scope / tier
Self-reflection Tier 2 — touches the tick-history data contract consumed by
/daily-summary(cross-skill), so filed rather than inline-edited. Non-urgent: aggregation fragmentation; consensus unaffected. Related to #3882 (warnings), #3928 (actions), #3923 (daily-summary consumer), #3753 (originating class).