docs(6209): coverage, guidance-ownership, shape, warnings tests and shared fixtures
CI & Build / Python lint (push) Successful in 2s
CI & Build / Plugin hooks (push) Successful in 12s
CI & Build / TypeScript typecheck (push) Successful in 52s
CI & Build / integration (push) Successful in 1m12s
CI & Build / Python tests (push) Successful in 1m56s
CI & Build / Build & push image (push) Successful in 13s
CI & Build / Python lint (push) Successful in 2s
CI & Build / Plugin hooks (push) Successful in 12s
CI & Build / TypeScript typecheck (push) Successful in 52s
CI & Build / integration (push) Successful in 1m12s
CI & Build / Python tests (push) Successful in 1m56s
CI & Build / Build & push image (push) Successful in 13s
test_pattern_coverage, test_guidance_ownership, test_integration_shape_classify, test_instruction_surfaces_agree, test_retrieval_warnings, helpers.py and conftest.py state the property each test or fixture holds. The issue and milestone numbers, consolidation dates and one-install measurements that recorded how each was found are dropped; fixture dates and ids stay. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,29 +1,11 @@
|
||||
"""What the instruction surfaces must say that one owner per topic cannot enforce.
|
||||
|
||||
WHY THIS FILE IS SMALLER THAN IT WAS
|
||||
|
||||
Until milestone 410 this file pinned REDUNDANCY: every session-start surface —
|
||||
the MCP `_INSTRUCTIONS`, the plugin's static context, the `using-scribe` skill —
|
||||
had to restate how a rule reaches a session, what an empty session means, the
|
||||
Systems reflex and the snippet-recording triggers. That was the design #2494
|
||||
chose after #2497 (two surfaces disagreeing about who loads the rules) and
|
||||
#2198 (every hook silently inert): say it everywhere, so no single failure
|
||||
loses it.
|
||||
|
||||
Decision #4027 replaced that with ownership, and tests/test_guidance_ownership.py
|
||||
now enforces it: every topic stated in full by exactly one owner, with a
|
||||
one-line pointer in the server's index. The tests that required every surface
|
||||
to repeat itself were retired there, because they enforced the very duplication
|
||||
that drifted (#4022). What they protected is still protected:
|
||||
- "state how to ask for a rule" / "say an empty session is not an empty
|
||||
rulebook" → the rules topic: owned by using-scribe, indexed in
|
||||
`_INSTRUCTIONS` with both phrases;
|
||||
- the Systems reflex and the snippet-recording triggers → their topics'
|
||||
markers, required on their owners;
|
||||
- "never name the SessionStart push without stating the ask" (#2497's exact
|
||||
shape) → retired outright. Since milestone 394 the push carries no rules,
|
||||
so naming it can no longer imply rules were handled, and requiring every
|
||||
surface that mentions it to restate the ask would force a copy.
|
||||
tests/test_guidance_ownership.py enforces who states each topic: every topic
|
||||
stated in full by exactly one owner, with a one-line pointer in the server's
|
||||
index. How to ask for a rule and what an empty session means are the rules
|
||||
topic, owned by using-scribe and indexed in `_INSTRUCTIONS`; the Systems
|
||||
reflex and the snippet-recording triggers are their topics' markers, required
|
||||
on their owners.
|
||||
|
||||
WHAT STAYS HERE
|
||||
|
||||
@@ -46,7 +28,7 @@ def _all_surfaces() -> list[tuple[str, str]]:
|
||||
what the hook does is not the same act as telling an agent it need not pull.
|
||||
The boundary is "does a session read this", which is skills (loaded by
|
||||
description match, and each reference file a skill links is read on its
|
||||
own, so it is its own surface — #4398), the hook-injected static context, and the MCP server's
|
||||
own, so it is its own surface), the hook-injected static context, and the MCP server's
|
||||
own instructions.
|
||||
"""
|
||||
found = [(str(p.relative_to(ROOT)), p.read_text())
|
||||
@@ -68,10 +50,9 @@ def _instructions_text() -> str:
|
||||
|
||||
|
||||
# Claude Code injects only the first ~2,048 characters of an MCP server's
|
||||
# instructions and silently cuts the rest mid-word (#2562: observed live —
|
||||
# the previous 20k-char version delivered ~10% of itself, and none of the
|
||||
# Systems tagging guidance ever reached a session). The budget is set below
|
||||
# the cap, not at it: the field runs ~600–1,600 characters (spike #4389), and
|
||||
# instructions and silently cuts the rest mid-word, so guidance past the cap
|
||||
# never reaches a session. The budget is set below the cap, not at it: the
|
||||
# field runs ~600–1,600 characters, and
|
||||
# a block pressed against 2,048 is being used for depth that belongs in a
|
||||
# skill.
|
||||
INSTRUCTIONS_BUDGET = 1600
|
||||
@@ -81,18 +62,17 @@ def test_instructions_fit_the_fold():
|
||||
text = _instructions_text()
|
||||
assert len(text) <= INSTRUCTIONS_BUDGET, (
|
||||
f"_INSTRUCTIONS is {len(text)} chars; Claude Code injects only ~2,048 "
|
||||
f"and silently cuts the rest (#2562). This block is an INDEX — state "
|
||||
f"the topic in full on its owner (a skill or the tool's docstring, "
|
||||
f"decision #4027) and give it at most a line here; see the comment "
|
||||
f"and silently cuts the rest. This block is an INDEX — state "
|
||||
f"the topic in full on its owner (a skill or the tool's docstring) "
|
||||
f"and give it at most a line here; see the comment "
|
||||
f"above _INSTRUCTIONS."
|
||||
)
|
||||
|
||||
|
||||
# ── force: a surface that says rules bind must say what does not ────────
|
||||
#
|
||||
# Added with the preference kind (milestone 399). Before it, "rules bind" was
|
||||
# the whole truth and every surface said so flatly. It is now half of one, and
|
||||
# the half that is missing is the dangerous half to omit: a session reading
|
||||
# With a preference kind beside rules, "rules bind" is half of the truth, and
|
||||
# the missing half is the dangerous half to omit: a session reading
|
||||
# only "rules bind" and then receiving a preference has been told, by the most
|
||||
# authoritative surface it has, to treat it as binding.
|
||||
#
|
||||
@@ -107,7 +87,7 @@ def test_instructions_fit_the_fold():
|
||||
# PINNED ON THE CLAIM, NOT THE WORD "bind". A bare substring also matches
|
||||
# `bind_repo`, `list_repo_bindings` and the DNS-rebinding comment in
|
||||
# server.py — so it would one day fail a skill that mentions repo binding and
|
||||
# has nothing to do with force, which is rule 167's named failure: a guard
|
||||
# has nothing to do with force — a guard
|
||||
# raising a false alarm about the very thing it protects. These phrases are
|
||||
# the ones that actually assert bindingness to a reader.
|
||||
BINDING_CLAIMS = (
|
||||
@@ -144,7 +124,7 @@ def test_a_surface_claiming_rules_bind_also_names_what_does_not():
|
||||
# whole corpus; a session that meets a third line shape with no name for it
|
||||
# falls back on the nearest one it has, which is the binding one.
|
||||
#
|
||||
# The currency half is the claim #3896 was written around: a preference is the
|
||||
# The currency half is the central claim: a preference is the
|
||||
# one record a session updates ITSELF, without asking. Stated only in the
|
||||
# skill, it reaches a session that loaded the skill — which is exactly the
|
||||
# session least likely to need telling. In the index it reaches everyone.
|
||||
@@ -168,12 +148,12 @@ def test_the_index_names_all_three_strengths():
|
||||
f"client receives, and a record kind it does not name is one the session "
|
||||
f"has to guess the force of — which it does by reaching for the kind it "
|
||||
f"does know. Keep it to a clause; the full statement lives on "
|
||||
f"using-scribe (decision #4027)."
|
||||
f"using-scribe."
|
||||
)
|
||||
|
||||
|
||||
def test_the_strength_guard_can_fail():
|
||||
"""Rule 167. The guard has to be able to bite, and it bites on omission —
|
||||
"""The guard has to be able to bite, and it bites on omission —
|
||||
the failure that actually happens, when a kind is added to the product and
|
||||
the index is left describing the corpus that came before it."""
|
||||
text = "rules bind; preferences guide and you keep them current."
|
||||
@@ -182,14 +162,13 @@ def test_the_strength_guard_can_fail():
|
||||
assert missing == ["that lessons inform"]
|
||||
|
||||
|
||||
# ── Reporting back (milestone 409 step 3) ──────────────────────────────
|
||||
# ── Reporting back ─────────────────────────────────────────────────────
|
||||
#
|
||||
# The reporting-back skill carries the shapes, but a skill only helps if it
|
||||
# fires. The reflex that sends a session to it is stated in using-scribe, and
|
||||
# the in-band cue on update_task (`placement`, `report_back`) is the half that
|
||||
# fires on its own in every client. The server's index carried a REPORT line
|
||||
# until #4389: reporting is a mid-work stance, not a session-start practice. The
|
||||
# static context was a second plugin-side copy until milestone 410.
|
||||
# fires on its own in every client. The server's index carries no REPORT line:
|
||||
# reporting is a mid-work stance, not a session-start practice.
|
||||
|
||||
REPORT_REFLEX = "report back in a shape the operator can read"
|
||||
REPORT_SURFACES = (
|
||||
@@ -211,8 +190,8 @@ def test_the_reporting_reflex_is_stated_in_using_scribe():
|
||||
|
||||
|
||||
def test_the_reporting_reflex_takes_placement_from_the_record():
|
||||
"""The failure milestone 409 began from: a placement reconstructed from
|
||||
memory reads exactly like a real one when it is wrong."""
|
||||
"""A placement reconstructed from memory reads exactly like a real one
|
||||
when it is wrong."""
|
||||
for path in REPORT_SURFACES:
|
||||
text = " ".join(path.read_text().split())
|
||||
assert "`placement`" in text, f"{path.relative_to(ROOT)} no longer points at the placement block"
|
||||
|
||||
Reference in New Issue
Block a user