docs(6209): rulebooks, pull telemetry, lesson usage, duplicate arm, cited status, trigger shape
CI & Build / Python lint (push) Successful in 2s
CI & Build / Plugin hooks (push) Successful in 14s
CI & Build / TypeScript typecheck (push) Successful in 54s
CI & Build / integration (push) Successful in 1m3s
CI & Build / Python tests (push) Successful in 1m55s
CI & Build / Build & push image (push) Successful in 13s
CI & Build / Python lint (push) Successful in 2s
CI & Build / Plugin hooks (push) Successful in 14s
CI & Build / TypeScript typecheck (push) Successful in 54s
CI & Build / integration (push) Successful in 1m3s
CI & Build / Python tests (push) Successful in 1m55s
CI & Build / Build & push image (push) Successful in 13s
Six more test files state their pinned properties without the issue and milestone history: the pull-telemetry guard explains enumerating kinds instead of listing two getter incidents, cited-record status explains why a hint's id needs its status instead of recounting one misreported step, and the trigger-shape guard keeps its reasoning about why prose heuristics fail while dropping the dated corpus audit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,19 +1,17 @@
|
||||
"""Every rule-write surface SHOWS what a trigger looks like (#3855).
|
||||
"""Every rule-write surface SHOWS what a trigger looks like.
|
||||
|
||||
WHY THIS EXISTS
|
||||
|
||||
`when_to_apply` is not documentation. `rule_document()` uses it twice — as
|
||||
the embedded title's second half and again above the body — so it dominates
|
||||
the vector, and a rule whose trigger names a CATEGORY rather than a moment
|
||||
collapses toward its title and never arrives. Measured in #3835 across 113
|
||||
rules, then again in #3855 on eight preferences.
|
||||
collapses toward its title and never arrives.
|
||||
|
||||
The corpus damage traced to an uneven contract rather than to careless
|
||||
authors. `create_rule` had carried the full argument since 2026-08-27, and
|
||||
the two preferences written that day got good triggers; the six written
|
||||
before it — "during hard debugging", "when reading any request from the
|
||||
operator" — got categories. The guidance worked wherever it existed. It
|
||||
simply did not exist on either `update_*` surface, which is where every
|
||||
Bad triggers come from an uneven contract rather than from careless authors.
|
||||
Triggers written where the guidance exists name a moment; triggers written
|
||||
without it — "during hard debugging", "when reading any request from the
|
||||
operator" — name categories. The guidance has to exist on the `update_*`
|
||||
surfaces too, which is where every
|
||||
RETROFITTED trigger is written, and retrofitting is most of the work: a
|
||||
trigger that already reads fine as English is the one nobody rewrites.
|
||||
|
||||
@@ -21,9 +19,8 @@ WHAT THIS PINS
|
||||
|
||||
Two properties, neither of them wording:
|
||||
|
||||
1. A tool accepting `when_to_apply` mentions it. Exactly what
|
||||
`update_preference` failed before #3855 — the parameter existed and
|
||||
the docstring never said so.
|
||||
1. A tool accepting `when_to_apply` mentions it — a parameter the
|
||||
docstring never names is one nobody fills well.
|
||||
2. It carries a worked CONTRAST: one `RETRIEVES:` example and one
|
||||
`COLLAPSES:` example, quoted, and different from each other.
|
||||
|
||||
@@ -31,23 +28,21 @@ WHY A CONVENTION RATHER THAN A PROSE HEURISTIC
|
||||
|
||||
The second property guards the softer regression — guidance kept but
|
||||
abstracted back to "name the moment in session vocabulary", which is advice
|
||||
about being concrete that is not itself concrete, and is the shape that was
|
||||
already on file while the corpus filled with categories.
|
||||
about being concrete that is not itself concrete.
|
||||
|
||||
Two attempts to detect that in free prose were written and discarded, and
|
||||
the reason is worth keeping because it generalises:
|
||||
Two ways to detect that in free prose fail, and the reason generalises:
|
||||
|
||||
- Counting quoted multi-word phrases anywhere in the docstring measured
|
||||
ambient quotation, not demonstrated triggers. It PASSED the abstracted
|
||||
ambient quotation, not demonstrated triggers. It PASSES the abstracted
|
||||
version by scoring unrelated prose, and text with an odd number of
|
||||
quote characters produced matches spanning the gap BETWEEN two
|
||||
unrelated phrases.
|
||||
- Scoping that count to a window after each "trigger"/"when_to_apply"
|
||||
mention then FAILED `create_preference` in its correct state, because
|
||||
mention FAILS `create_preference` in its correct state, because
|
||||
its examples sit further from the first mention than any defensible
|
||||
window reaches.
|
||||
|
||||
Both were proxies trying to infer demonstration from prose. The fix was to
|
||||
Both are proxies trying to infer demonstration from prose. The answer is to
|
||||
stop inferring: a two-line labelled contrast is unambiguous to parse, free
|
||||
in its wording, and a better teaching form than the sentences it replaced —
|
||||
`RETRIEVES:`/`COLLAPSES:` names the mechanism, so the label does work for
|
||||
@@ -56,7 +51,7 @@ measured, changing the shape of the thing is cheaper than a cleverer
|
||||
measurement.
|
||||
|
||||
What it still cannot do is judge whether a GOOD example is good. It catches
|
||||
what actually happened: a write surface shipping with the contrast absent,
|
||||
the likely failure: a write surface shipping with the contrast absent,
|
||||
half-present, or tidied back into abstract advice.
|
||||
|
||||
THE SURFACE LIST IS DERIVED, NEVER HAND-KEPT. It comes from what
|
||||
@@ -64,7 +59,7 @@ THE SURFACE LIST IS DERIVED, NEVER HAND-KEPT. It comes from what
|
||||
taking `when_to_apply`, so a rule-write tool added later is in scope on the
|
||||
day it is added. A hand-kept list has to be remembered by the person least
|
||||
likely to know it exists — the argument `RANKED_SOURCES` makes in
|
||||
services/rule_usage.py, and the reason #3855 happened at all.
|
||||
services/rule_usage.py.
|
||||
"""
|
||||
import inspect
|
||||
import re
|
||||
@@ -111,8 +106,8 @@ def _trigger_writers() -> list[str]:
|
||||
if "when_to_apply" in inspect.signature(fn).parameters
|
||||
]
|
||||
# An empty list would make every case below vacuous and the guard would
|
||||
# pass by having nothing to check — absence read as non-existence, the
|
||||
# #3720 shape. Fail loudly instead.
|
||||
# pass by having nothing to check — absence read as non-existence. Fail
|
||||
# loudly instead.
|
||||
assert names, "no rule-write surface takes when_to_apply; the guard is blind"
|
||||
return sorted(names)
|
||||
|
||||
@@ -123,10 +118,9 @@ def test_a_trigger_writing_surface_documents_the_field(name):
|
||||
doc = _doc(_MODULE, name)
|
||||
assert "when_to_apply" in doc, (
|
||||
f"{name} accepts when_to_apply but never mentions it in its "
|
||||
"docstring. The tool docstring is the agent-facing contract "
|
||||
"(rule 119), and a trigger written against no contract is the #3855 "
|
||||
"defect: six preferences named a category instead of a moment, and "
|
||||
"a category is not a thing any session ever types."
|
||||
"docstring. The tool docstring is the agent-facing contract, and a "
|
||||
"trigger written against no contract names a category instead of a "
|
||||
"moment — and a category is not a thing any session ever types."
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user