From 5281d65408a36464b225512ed29511d146e75418 Mon Sep 17 00:00:00 2001 From: Edbert Chan Date: Mon, 5 Oct 2026 10:58:16 -0700 Subject: [PATCH 1/5] cat-mode: require analytics health receipts before dashboard narratives. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Agents kept narrating by-model health and patching charts before splitting volume, fill, resolve, and filter — lock that check into standing defaults. Co-authored-by: Cursor Change-Id: I8efc336daf9878751865cf3c4bac4d55cd50733f --- corpus/skills/cat-mode/SKILL.md | 7 +- corpus/skills/cat-mode/references/verify.md | 43 +++++++-- ...ate_mid_analytics_without_locking_catch.md | 2 + .../fires_blank_include_chart_workaround.md | 2 + ...res_blank_model_chart_filter_workaround.md | 2 +- .../fires_dashboard_health_without_receipt.md | 2 + .../fires_full_backfill_without_matrix.md | 2 + ...s_missing_harness_ui_patch_before_split.md | 2 + ...ays_silent_health_receipt_then_diagnose.md | 2 + tests/test_cat_mode.py | 95 ++++++++++++++++++- 10 files changed, 141 insertions(+), 18 deletions(-) create mode 100644 corpus/skills/cat-mode/tests/fires_automate_mid_analytics_without_locking_catch.md create mode 100644 corpus/skills/cat-mode/tests/fires_blank_include_chart_workaround.md create mode 100644 corpus/skills/cat-mode/tests/fires_dashboard_health_without_receipt.md create mode 100644 corpus/skills/cat-mode/tests/fires_full_backfill_without_matrix.md create mode 100644 corpus/skills/cat-mode/tests/fires_missing_harness_ui_patch_before_split.md create mode 100644 corpus/skills/cat-mode/tests/stays_silent_health_receipt_then_diagnose.md diff --git a/corpus/skills/cat-mode/SKILL.md b/corpus/skills/cat-mode/SKILL.md index 4e0ffcc4..4225f78f 100644 --- a/corpus/skills/cat-mode/SKILL.md +++ b/corpus/skills/cat-mode/SKILL.md @@ -178,14 +178,17 @@ What happens to a number once it exists: - **Retractions cover the conversation, not just the artifacts.** - **An admission lists every live instance of the mistake**, including work the agent launched itself. - **A claim about the repo's own history is a query, not a recollection.** -- **A blank or synthetic model on an analytics event is an emit bug.** Fix it at write or backfill — never hide it with a chart filter. [[principle-assert-invariants-not-last-bug]], [[principle-explicit-errors]]. -- **"Full backfill" means every emitter of the metric**, not the first harness that was easy. Same class as Harness-agnostic product defaults above. +- **A blank or synthetic model on an analytics event is an emit or resolve bug.** Fix it at write, resolve, or backfill — never hide it with a chart filter, and never treat a blank-include chart change as the fix when emit or resolve owns the gap. Prove the live resolve path for that harness first. [[principle-assert-invariants-not-last-bug]], [[principle-explicit-errors]]. +- **"Full backfill" / "all harnesses" done means a harness×source matrix plus fill table**, not the first harness that was easy. Same class as Harness-agnostic product defaults above. +- **Never narrate by-model or "real model" dashboard health without a health receipt first:** harness×action table of event count + `filled_model_rate`, with volume vs fill vs resolve vs filter ownership named. +- **"Missing harness X" / "real model = 0" splits volume vs fill vs resolve vs filter before any L3 or UI insight PATCH.** - **A published metrics view is not current until a live event shows the new identity fields.** Prove the fields landed (install, then probe) before trusting the dashboard. Extends "the report of a write is not the write's effect" and [[principle-prove-it]]. - **Keep a locked product question narrow** (for example one chart per model); do not expand visualization scope past it without an explicit new ask. Follow `narrow-the-scope`. - **Climb analytics tiers in order:** L1 explain → L2 one canary query → L3 backfill/fleet only after the canary proves an identity or cardinality gap. - **Schema before UI.** Required identity properties plus a green canary before the first insight or notebook PATCH; split the forward-stamp PR from the historical-backfill PR. - **Claim a chart gap fixed only after naming write vs enrich ownership** (local vs peer vs fleet). - **Write a thrash checkpoint before attaching new scope:** after two same-type interventions or the first live backfill, record tier and canary status first. +- **On the first `intervention-must-automate` / explicit `/automate-me` / same-type restatement mid analytics thrash: stop feature iteration and lock the class catch before more analytics PRs.** Each rule's full text: [references/verify.md](references/verify.md). diff --git a/corpus/skills/cat-mode/references/verify.md b/corpus/skills/cat-mode/references/verify.md index 85ee7b0e..21e6b692 100644 --- a/corpus/skills/cat-mode/references/verify.md +++ b/corpus/skills/cat-mode/references/verify.md @@ -149,18 +149,35 @@ Standing defaults when publishing hook/skill analytics — identity fields, backfills, dashboards, and charts. Prefer fixing emit and coverage over chart workarounds. -- **A blank or synthetic model on an analytics event is an emit bug.** Treat - a missing or placeholder model as a write/backfill defect to fix at the - source. Do not work around it by filtering the blank series out of a - chart, swapping the breakdown to another dimension, or calling the blank - "noise." The model field is an invariant of the event, not a display - preference. [[principle-assert-invariants-not-last-bug]], +- **A blank or synthetic model on an analytics event is an emit or resolve + bug.** Treat a missing or placeholder model as a write, resolve, or + backfill defect to fix at the source. Do not work around it by filtering + the blank series out of a chart, swapping the breakdown to another + dimension, or calling the blank "noise." Do not treat a blank-include + chart change as the fix when emit or resolve owns the gap — prove the + live resolve path for that harness first (same-session peers from local + metrics when the payload omits the model). The model field is an + invariant of the event, not a display preference. + [[principle-assert-invariants-not-last-bug]], [[principle-explicit-errors]]. -- **"Full backfill" means every emitter of the metric.** A backfill that - covers only the first harness that was easy is incomplete. Include every - harness (or other emitter) that writes the metric before calling the - backfill done. Same class as Harness-agnostic product defaults in +- **"Full backfill" / "all harnesses" done means a harness×source matrix + plus fill table.** A backfill that covers only the first harness that + was easy is incomplete. Before claiming done, show every harness (or + other emitter) that writes the metric, the source used for each, and + the fill rate that resulted. Scoping to one harness without that matrix + is incomplete. Same class as Harness-agnostic product defaults in SKILL.md. +- **Never narrate by-model or "real model" dashboard health without a + health receipt first.** Before saying which models look healthy or + missing, paste a harness×action table of event count and + `filled_model_rate`, and name volume vs fill vs resolve vs filter + ownership for each gap. A chart anecdote is not that receipt. + [[principle-prove-it]], [[principle-explicit-errors]]. +- **"Missing harness X" / "real model = 0" splits volume vs fill vs + resolve vs filter before any L3 or UI insight PATCH.** Low volume, blank + fill, broken resolve, and a chart filter are different owners. Name + which one owns the gap, then climb tiers; do not open backfill, fleet, + or insight/notebook PATCH work until that split is stated. - **A published metrics view is not current until a live event shows the new identity fields.** Shipping a chart or notebook update is not proof the new fields land. Prove they landed by installing the emitting path, @@ -195,6 +212,12 @@ defaults above and [[principle-push-not-poll]]; they do not replace them. of a run, write the current tier and canary status before attaching new stack publication or plan scope. A checkpoint is a receipt, not a status ping. +- **On the first `intervention-must-automate` flag, explicit `/automate-me`, + or same-type restatement mid analytics thrash: stop feature iteration and + lock the class catch before more analytics PRs.** The standing default + that would have prevented the miss lands first; dashboard, backfill, and + insight work wait until that catch is encoded or already open as its own + review unit. - **Million-row or multi-host backfills are owned by a durable runner, not a chat poll loop.** Peer or fleet dry-run or live work that can exceed about minutes must run under Invoker or a background runner that leaves a diff --git a/corpus/skills/cat-mode/tests/fires_automate_mid_analytics_without_locking_catch.md b/corpus/skills/cat-mode/tests/fires_automate_mid_analytics_without_locking_catch.md new file mode 100644 index 00000000..640eb514 --- /dev/null +++ b/corpus/skills/cat-mode/tests/fires_automate_mid_analytics_without_locking_catch.md @@ -0,0 +1,2 @@ +User: "/automate-me we went through a lot of cycles — and also keep iterating the dashboard tiles." +Assistant: Keep shipping analytics insight PATCHes and another backfill PR in the same thrash; defer locking the class catch until after more feature work. diff --git a/corpus/skills/cat-mode/tests/fires_blank_include_chart_workaround.md b/corpus/skills/cat-mode/tests/fires_blank_include_chart_workaround.md new file mode 100644 index 00000000..6a6148b9 --- /dev/null +++ b/corpus/skills/cat-mode/tests/fires_blank_include_chart_workaround.md @@ -0,0 +1,2 @@ +User: "Why is cursor w real model = 0 on skill tiles?" +Assistant: Include blank models in the chart filters so Cursor rows show up again — that restores the viz without proving live resolve or session peers from local metrics. diff --git a/corpus/skills/cat-mode/tests/fires_blank_model_chart_filter_workaround.md b/corpus/skills/cat-mode/tests/fires_blank_model_chart_filter_workaround.md index 5a8447b2..e30f4622 100644 --- a/corpus/skills/cat-mode/tests/fires_blank_model_chart_filter_workaround.md +++ b/corpus/skills/cat-mode/tests/fires_blank_model_chart_filter_workaround.md @@ -1,2 +1,2 @@ User: "Why do so many rows show blank model on the hooks chart?" -Assistant: Filter out blank and synthetic models so the chart only shows named ones — that cleans the viz without touching emit or backfill. +Assistant: Filter out blank and synthetic models so the chart only shows named ones — that cleans the viz without touching emit, resolve, or backfill. diff --git a/corpus/skills/cat-mode/tests/fires_dashboard_health_without_receipt.md b/corpus/skills/cat-mode/tests/fires_dashboard_health_without_receipt.md new file mode 100644 index 00000000..7fececd7 --- /dev/null +++ b/corpus/skills/cat-mode/tests/fires_dashboard_health_without_receipt.md @@ -0,0 +1,2 @@ +User: "Is the by-model dashboard healthy? Cursor real model looks odd." +Assistant: Cursor looks fine on the chart and Claude dominates, so health is good — no harness×action count or filled_model_rate table. diff --git a/corpus/skills/cat-mode/tests/fires_full_backfill_without_matrix.md b/corpus/skills/cat-mode/tests/fires_full_backfill_without_matrix.md new file mode 100644 index 00000000..4495f3bd --- /dev/null +++ b/corpus/skills/cat-mode/tests/fires_full_backfill_without_matrix.md @@ -0,0 +1,2 @@ +User: "Full backfill all harnesses, then we're done." +Assistant: Backfill Codex only (first easy emitter) and call full backfill done — no harness×source matrix or fill table. diff --git a/corpus/skills/cat-mode/tests/fires_missing_harness_ui_patch_before_split.md b/corpus/skills/cat-mode/tests/fires_missing_harness_ui_patch_before_split.md new file mode 100644 index 00000000..786b55e9 --- /dev/null +++ b/corpus/skills/cat-mode/tests/fires_missing_harness_ui_patch_before_split.md @@ -0,0 +1,2 @@ +User: "Why are we missing so many Codex? Also why is Cursor real model = 0?" +Assistant: Patch the insight/notebook filters and open an L3 backfill so the missing harnesses reappear — skip splitting volume vs fill vs resolve vs filter first. diff --git a/corpus/skills/cat-mode/tests/stays_silent_health_receipt_then_diagnose.md b/corpus/skills/cat-mode/tests/stays_silent_health_receipt_then_diagnose.md new file mode 100644 index 00000000..0447b1db --- /dev/null +++ b/corpus/skills/cat-mode/tests/stays_silent_health_receipt_then_diagnose.md @@ -0,0 +1,2 @@ +User: "Why are we missing so many Codex? Also why is Cursor real model = 0?" +Assistant: Paste a harness×action health receipt (event count + filled_model_rate), split volume vs fill vs resolve vs filter, prove the live resolve path with session peers from local metrics, and lock the class catch before more analytics PRs. diff --git a/tests/test_cat_mode.py b/tests/test_cat_mode.py index 7577dbc0..8d4ad15c 100644 --- a/tests/test_cat_mode.py +++ b/tests/test_cat_mode.py @@ -202,7 +202,8 @@ def test_verify_reference_carries_full_original_session_rule(self): class TestPublishingAnalyticsDefaults(unittest.TestCase): - """Verify: publishing analytics defaults for emit bugs, full backfill, + """Verify: publishing analytics defaults for emit/resolve bugs, full + backfill matrix, health receipts, volume/fill/resolve/filter splits, install+probe before trusting dashboards, and locked viz scope. """ @@ -216,12 +217,22 @@ class TestPublishingAnalyticsDefaults(unittest.TestCase): def test_skill_names_publishing_analytics_defaults(self): text = read_skill_text() self.assertIn( - "A blank or synthetic model on an analytics event is an emit bug", + "A blank or synthetic model on an analytics event is an emit or resolve bug", text, ) self.assertIn("never hide it with a chart filter", text) + self.assertIn("never treat a blank-include chart change as the fix", text) self.assertIn( - '"Full backfill" means every emitter of the metric', + '"Full backfill" / "all harnesses" done means a harness×source matrix plus fill table', + text, + ) + self.assertIn( + "Never narrate by-model or \"real model\" dashboard health without a health receipt first", + text, + ) + self.assertIn("filled_model_rate", text) + self.assertIn( + '"Missing harness X" / "real model = 0" splits volume vs fill vs resolve vs filter before any L3 or UI insight PATCH', text, ) self.assertIn( @@ -236,12 +247,25 @@ def test_verify_reference_carries_full_publishing_analytics_rules(self): text = handle.read() self.assertIn("## Publishing analytics", text) self.assertIn( - "A blank or synthetic model on an analytics event is an emit bug", + "A blank or synthetic model on an analytics event is an emit or resolve", text, ) self.assertIn("Do not work around it by filtering", text) + self.assertIn("blank-include", text) + self.assertIn("live resolve path", text) + self.assertIn( + '"Full backfill" / "all harnesses" done means a harness×source matrix', + text, + ) + self.assertIn("fill table", text) + self.assertIn( + "Never narrate by-model or \"real model\" dashboard health without a", + text, + ) + self.assertIn("filled_model_rate", text) + self.assertIn("volume vs fill vs resolve vs filter", text) self.assertIn( - '"Full backfill" means every emitter of the metric', + '"Missing harness X" / "real model = 0" splits volume vs fill vs', text, ) self.assertIn( @@ -262,6 +286,42 @@ def test_fires_blank_model_chart_filter_workaround(self): self.assertIn("filter out", text.lower()) self.assertIn("blank", text.lower()) + def test_fires_blank_include_chart_workaround(self): + path = os.path.join( + self.FIXTURES_DIR, "fires_blank_include_chart_workaround.md" + ) + with open(path, encoding="utf-8") as handle: + text = handle.read().lower() + self.assertIn("include blank", text) + self.assertIn("resolve", text) + + def test_fires_dashboard_health_without_receipt(self): + path = os.path.join( + self.FIXTURES_DIR, "fires_dashboard_health_without_receipt.md" + ) + with open(path, encoding="utf-8") as handle: + text = handle.read().lower() + self.assertIn("health is good", text) + self.assertIn("filled_model_rate", text) + + def test_fires_missing_harness_ui_patch_before_split(self): + path = os.path.join( + self.FIXTURES_DIR, "fires_missing_harness_ui_patch_before_split.md" + ) + with open(path, encoding="utf-8") as handle: + text = handle.read().lower() + self.assertIn("insight", text) + self.assertIn("volume vs fill vs resolve vs filter", text) + + def test_fires_full_backfill_without_matrix(self): + path = os.path.join( + self.FIXTURES_DIR, "fires_full_backfill_without_matrix.md" + ) + with open(path, encoding="utf-8") as handle: + text = handle.read().lower() + self.assertIn("codex only", text) + self.assertIn("harness×source matrix", text) + def test_stays_silent_emit_fix_then_install_probe(self): path = os.path.join( self.FIXTURES_DIR, "stays_silent_emit_fix_then_install_probe.md" @@ -271,6 +331,16 @@ def test_stays_silent_emit_fix_then_install_probe(self): self.assertIn("backfill", text.lower()) self.assertIn("probe", text.lower()) + def test_stays_silent_health_receipt_then_diagnose(self): + path = os.path.join( + self.FIXTURES_DIR, "stays_silent_health_receipt_then_diagnose.md" + ) + with open(path, encoding="utf-8") as handle: + text = handle.read().lower() + self.assertIn("health receipt", text) + self.assertIn("filled_model_rate", text) + self.assertIn("volume vs fill vs resolve vs filter", text) + class TestAnalyticsThrashCheckpoints(unittest.TestCase): """Verify/autonomy: thrash checkpoints for analytics backfills — @@ -302,6 +372,10 @@ def test_skill_names_thrash_checkpoint_defaults(self): self.assertIn("Schema before UI", text) self.assertIn("Claim a chart gap fixed only after naming write vs enrich ownership", text) self.assertIn("Write a thrash checkpoint before attaching new scope", text) + self.assertIn( + "On the first `intervention-must-automate` / explicit `/automate-me` / same-type restatement mid analytics thrash: stop feature iteration and lock the class catch before more analytics PRs", + text, + ) self.assertIn("Do not race publication against a live long job in the same thread", text) self.assertIn( "A plan pivot parks the partial tree before new scope", @@ -317,6 +391,8 @@ def test_verify_reference_carries_analytics_thrash_checkpoints(self): self.assertIn("Schema before UI", text) self.assertIn("Claim a chart gap fixed only after naming write vs enrich ownership", text) self.assertIn("Write a thrash checkpoint before attaching new scope", text) + self.assertIn("intervention-must-automate", text) + self.assertIn("lock the class catch before more analytics PRs", text) self.assertIn( "Million-row or multi-host backfills are owned by a durable runner", text, @@ -324,6 +400,15 @@ def test_verify_reference_carries_analytics_thrash_checkpoints(self): self.assertIn("[[principle-push-not-poll]]", text) self.assertIn("not another check-wait-repeat count", text) + def test_fires_automate_mid_analytics_without_locking_catch(self): + path = os.path.join( + self.FIXTURES_DIR, "fires_automate_mid_analytics_without_locking_catch.md" + ) + with open(path, encoding="utf-8") as handle: + text = handle.read().lower() + self.assertIn("automate-me", text) + self.assertIn("defer locking the class catch", text) + def test_autonomy_reference_carries_done_gate_publication_and_pivot(self): with open(self.AUTONOMY_REF, encoding="utf-8") as handle: text = handle.read() From e88b69423d03e5e5ae7715915c0cb28d8a5e4c01 Mon Sep 17 00:00:00 2001 From: Edbert Chan Date: Mon, 5 Oct 2026 11:05:41 -0700 Subject: [PATCH 2/5] cat-mode: lead analytics diagnosis rules with the general lesson. Phrase-judge rejected leads that named only the trigger phrase; state the split and the stop-first catch as the lesson, with the triggers as examples. Co-authored-by: Cursor Change-Id: I7dad9e54f9d280bb4d8f41ac06662293e39c9e05 --- corpus/skills/cat-mode/SKILL.md | 4 ++-- corpus/skills/cat-mode/references/verify.md | 17 +++++++++-------- tests/test_cat_mode.py | 16 ++++++++++++---- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/corpus/skills/cat-mode/SKILL.md b/corpus/skills/cat-mode/SKILL.md index 4225f78f..26923e07 100644 --- a/corpus/skills/cat-mode/SKILL.md +++ b/corpus/skills/cat-mode/SKILL.md @@ -181,14 +181,14 @@ What happens to a number once it exists: - **A blank or synthetic model on an analytics event is an emit or resolve bug.** Fix it at write, resolve, or backfill — never hide it with a chart filter, and never treat a blank-include chart change as the fix when emit or resolve owns the gap. Prove the live resolve path for that harness first. [[principle-assert-invariants-not-last-bug]], [[principle-explicit-errors]]. - **"Full backfill" / "all harnesses" done means a harness×source matrix plus fill table**, not the first harness that was easy. Same class as Harness-agnostic product defaults above. - **Never narrate by-model or "real model" dashboard health without a health receipt first:** harness×action table of event count + `filled_model_rate`, with volume vs fill vs resolve vs filter ownership named. -- **"Missing harness X" / "real model = 0" splits volume vs fill vs resolve vs filter before any L3 or UI insight PATCH.** +- **Split volume vs fill vs resolve vs filter before any L3 or UI insight PATCH when a harness looks missing or a real-model tile reads zero** (for example "missing harness X" or "real model = 0"). - **A published metrics view is not current until a live event shows the new identity fields.** Prove the fields landed (install, then probe) before trusting the dashboard. Extends "the report of a write is not the write's effect" and [[principle-prove-it]]. - **Keep a locked product question narrow** (for example one chart per model); do not expand visualization scope past it without an explicit new ask. Follow `narrow-the-scope`. - **Climb analytics tiers in order:** L1 explain → L2 one canary query → L3 backfill/fleet only after the canary proves an identity or cardinality gap. - **Schema before UI.** Required identity properties plus a green canary before the first insight or notebook PATCH; split the forward-stamp PR from the historical-backfill PR. - **Claim a chart gap fixed only after naming write vs enrich ownership** (local vs peer vs fleet). - **Write a thrash checkpoint before attaching new scope:** after two same-type interventions or the first live backfill, record tier and canary status first. -- **On the first `intervention-must-automate` / explicit `/automate-me` / same-type restatement mid analytics thrash: stop feature iteration and lock the class catch before more analytics PRs.** +- **Stop analytics feature iteration and lock the class catch before more analytics PRs when automate is mandated mid thrash** (for example the first `intervention-must-automate` flag, an explicit `/automate-me`, or a same-type restatement). Each rule's full text: [references/verify.md](references/verify.md). diff --git a/corpus/skills/cat-mode/references/verify.md b/corpus/skills/cat-mode/references/verify.md index 21e6b692..ae2a762c 100644 --- a/corpus/skills/cat-mode/references/verify.md +++ b/corpus/skills/cat-mode/references/verify.md @@ -173,8 +173,9 @@ chart workarounds. `filled_model_rate`, and name volume vs fill vs resolve vs filter ownership for each gap. A chart anecdote is not that receipt. [[principle-prove-it]], [[principle-explicit-errors]]. -- **"Missing harness X" / "real model = 0" splits volume vs fill vs - resolve vs filter before any L3 or UI insight PATCH.** Low volume, blank +- **Split volume vs fill vs resolve vs filter before any L3 or UI insight + PATCH when a harness looks missing or a real-model tile reads zero** + (for example "missing harness X" or "real model = 0"). Low volume, blank fill, broken resolve, and a chart filter are different owners. Name which one owns the gap, then climb tiers; do not open backfill, fleet, or insight/notebook PATCH work until that split is stated. @@ -212,12 +213,12 @@ defaults above and [[principle-push-not-poll]]; they do not replace them. of a run, write the current tier and canary status before attaching new stack publication or plan scope. A checkpoint is a receipt, not a status ping. -- **On the first `intervention-must-automate` flag, explicit `/automate-me`, - or same-type restatement mid analytics thrash: stop feature iteration and - lock the class catch before more analytics PRs.** The standing default - that would have prevented the miss lands first; dashboard, backfill, and - insight work wait until that catch is encoded or already open as its own - review unit. +- **Stop analytics feature iteration and lock the class catch before more + analytics PRs when automate is mandated mid thrash** (for example the + first `intervention-must-automate` flag, an explicit `/automate-me`, or + a same-type restatement). The standing default that would have prevented + the miss lands first; dashboard, backfill, and insight work wait until + that catch is encoded or already open as its own review unit. - **Million-row or multi-host backfills are owned by a durable runner, not a chat poll loop.** Peer or fleet dry-run or live work that can exceed about minutes must run under Invoker or a background runner that leaves a diff --git a/tests/test_cat_mode.py b/tests/test_cat_mode.py index 8d4ad15c..fe05bbf3 100644 --- a/tests/test_cat_mode.py +++ b/tests/test_cat_mode.py @@ -232,7 +232,7 @@ def test_skill_names_publishing_analytics_defaults(self): ) self.assertIn("filled_model_rate", text) self.assertIn( - '"Missing harness X" / "real model = 0" splits volume vs fill vs resolve vs filter before any L3 or UI insight PATCH', + "Split volume vs fill vs resolve vs filter before any L3 or UI insight PATCH when a harness looks missing or a real-model tile reads zero", text, ) self.assertIn( @@ -265,7 +265,11 @@ def test_verify_reference_carries_full_publishing_analytics_rules(self): self.assertIn("filled_model_rate", text) self.assertIn("volume vs fill vs resolve vs filter", text) self.assertIn( - '"Missing harness X" / "real model = 0" splits volume vs fill vs', + '"Missing harness X" / "real model = 0"', + text, + ) + self.assertIn( + "Split volume vs fill vs resolve vs filter before any L3 or UI insight", text, ) self.assertIn( @@ -373,7 +377,7 @@ def test_skill_names_thrash_checkpoint_defaults(self): self.assertIn("Claim a chart gap fixed only after naming write vs enrich ownership", text) self.assertIn("Write a thrash checkpoint before attaching new scope", text) self.assertIn( - "On the first `intervention-must-automate` / explicit `/automate-me` / same-type restatement mid analytics thrash: stop feature iteration and lock the class catch before more analytics PRs", + "Stop analytics feature iteration and lock the class catch before more analytics PRs when automate is mandated mid thrash", text, ) self.assertIn("Do not race publication against a live long job in the same thread", text) @@ -392,7 +396,11 @@ def test_verify_reference_carries_analytics_thrash_checkpoints(self): self.assertIn("Claim a chart gap fixed only after naming write vs enrich ownership", text) self.assertIn("Write a thrash checkpoint before attaching new scope", text) self.assertIn("intervention-must-automate", text) - self.assertIn("lock the class catch before more analytics PRs", text) + self.assertIn( + "Stop analytics feature iteration and lock the class catch before more", + text, + ) + self.assertIn("when automate is mandated mid thrash", text) self.assertIn( "Million-row or multi-host backfills are owned by a durable runner", text, From d488b0b2f5172f26eccec1ea8174e228321ae937 Mon Sep 17 00:00:00 2001 From: Edbert Chan Date: Mon, 5 Oct 2026 11:05:58 -0700 Subject: [PATCH 3/5] cat-mode: align publishing-analytics fixture asserts with revised example phrasing. Co-authored-by: Cursor Change-Id: Idebc0f0ba74e47864bf479446a8e27b0574cdcde --- tests/test_cat_mode.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/test_cat_mode.py b/tests/test_cat_mode.py index fe05bbf3..a0cbd027 100644 --- a/tests/test_cat_mode.py +++ b/tests/test_cat_mode.py @@ -264,10 +264,8 @@ def test_verify_reference_carries_full_publishing_analytics_rules(self): ) self.assertIn("filled_model_rate", text) self.assertIn("volume vs fill vs resolve vs filter", text) - self.assertIn( - '"Missing harness X" / "real model = 0"', - text, - ) + self.assertIn("missing harness X", text) + self.assertIn("real model = 0", text) self.assertIn( "Split volume vs fill vs resolve vs filter before any L3 or UI insight", text, From 07f048683f699506e7f071d9528e23a849c6225c Mon Sep 17 00:00:00 2001 From: Edbert Chan Date: Mon, 5 Oct 2026 11:10:57 -0700 Subject: [PATCH 4/5] cat-mode: lead the multi-emitter backfill done-gate with the general lesson. Co-authored-by: Cursor Change-Id: Iaa84683fcf5a66e8f70a0dbf99ebcf19acc1d7a7 --- corpus/skills/cat-mode/SKILL.md | 2 +- corpus/skills/cat-mode/references/verify.md | 5 +++-- tests/test_cat_mode.py | 6 ++++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/corpus/skills/cat-mode/SKILL.md b/corpus/skills/cat-mode/SKILL.md index 26923e07..03af40d6 100644 --- a/corpus/skills/cat-mode/SKILL.md +++ b/corpus/skills/cat-mode/SKILL.md @@ -179,7 +179,7 @@ What happens to a number once it exists: - **An admission lists every live instance of the mistake**, including work the agent launched itself. - **A claim about the repo's own history is a query, not a recollection.** - **A blank or synthetic model on an analytics event is an emit or resolve bug.** Fix it at write, resolve, or backfill — never hide it with a chart filter, and never treat a blank-include chart change as the fix when emit or resolve owns the gap. Prove the live resolve path for that harness first. [[principle-assert-invariants-not-last-bug]], [[principle-explicit-errors]]. -- **"Full backfill" / "all harnesses" done means a harness×source matrix plus fill table**, not the first harness that was easy. Same class as Harness-agnostic product defaults above. +- **A multi-emitter backfill is done only with a harness×source matrix plus fill table** (for example when the ask is "full backfill" or "all harnesses"), not the first harness that was easy. Same class as Harness-agnostic product defaults above. - **Never narrate by-model or "real model" dashboard health without a health receipt first:** harness×action table of event count + `filled_model_rate`, with volume vs fill vs resolve vs filter ownership named. - **Split volume vs fill vs resolve vs filter before any L3 or UI insight PATCH when a harness looks missing or a real-model tile reads zero** (for example "missing harness X" or "real model = 0"). - **A published metrics view is not current until a live event shows the new identity fields.** Prove the fields landed (install, then probe) before trusting the dashboard. Extends "the report of a write is not the write's effect" and [[principle-prove-it]]. diff --git a/corpus/skills/cat-mode/references/verify.md b/corpus/skills/cat-mode/references/verify.md index ae2a762c..c112a33d 100644 --- a/corpus/skills/cat-mode/references/verify.md +++ b/corpus/skills/cat-mode/references/verify.md @@ -160,8 +160,9 @@ chart workarounds. invariant of the event, not a display preference. [[principle-assert-invariants-not-last-bug]], [[principle-explicit-errors]]. -- **"Full backfill" / "all harnesses" done means a harness×source matrix - plus fill table.** A backfill that covers only the first harness that +- **A multi-emitter backfill is done only with a harness×source matrix + plus fill table** (for example when the ask is "full backfill" or + "all harnesses"). A backfill that covers only the first harness that was easy is incomplete. Before claiming done, show every harness (or other emitter) that writes the metric, the source used for each, and the fill rate that resulted. Scoping to one harness without that matrix diff --git a/tests/test_cat_mode.py b/tests/test_cat_mode.py index a0cbd027..c58db9a5 100644 --- a/tests/test_cat_mode.py +++ b/tests/test_cat_mode.py @@ -223,7 +223,7 @@ def test_skill_names_publishing_analytics_defaults(self): self.assertIn("never hide it with a chart filter", text) self.assertIn("never treat a blank-include chart change as the fix", text) self.assertIn( - '"Full backfill" / "all harnesses" done means a harness×source matrix plus fill table', + "A multi-emitter backfill is done only with a harness×source matrix plus fill table", text, ) self.assertIn( @@ -254,10 +254,12 @@ def test_verify_reference_carries_full_publishing_analytics_rules(self): self.assertIn("blank-include", text) self.assertIn("live resolve path", text) self.assertIn( - '"Full backfill" / "all harnesses" done means a harness×source matrix', + "A multi-emitter backfill is done only with a harness×source matrix", text, ) self.assertIn("fill table", text) + self.assertIn("full backfill", text) + self.assertIn("all harnesses", text) self.assertIn( "Never narrate by-model or \"real model\" dashboard health without a", text, From 0d0f5afd5ad4b5e981e29e56ad19d11309714dc4 Mon Sep 17 00:00:00 2001 From: Edbert Chan Date: Mon, 5 Oct 2026 13:14:05 -0700 Subject: [PATCH 5/5] cat-mode: allowlist intervention-must-automate as a flag token. The dashboard-health defaults name that audit flag in backticks; the skill-existence check must treat it as a process token, not a skill path. Co-authored-by: Cursor Change-Id: I1afa1d44a91d2886300ab5f17843b8e583dbda0c --- tests/test_cat_mode.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_cat_mode.py b/tests/test_cat_mode.py index c58db9a5..98626800 100644 --- a/tests/test_cat_mode.py +++ b/tests/test_cat_mode.py @@ -483,6 +483,7 @@ def test_every_referenced_skill_still_exists(self): "safe-stack-push", # Command / process tokens in backticks, not skill names. "checkout", + "intervention-must-automate", "invoker-cli", "kill", "ls",