feat(410): the server orients with a client-neutral index; the live context carries live state only (#4030)
CI & Build / Python lint (push) Successful in 2s
CI & Build / Plugin hooks (push) Successful in 12s
CI & Build / TypeScript typecheck (push) Successful in 53s
CI & Build / integration (push) Successful in 54s
CI & Build / Python tests (push) Successful in 1m28s
CI & Build / Build & push image (push) Successful in 27s

Step 3 of milestone 410 "One owner per piece of guidance".

_INSTRUCTIONS is rewritten as an index for every MCP client (1,597 of 2,000
chars): orient, rules, recall, record, plan, ids, reuse, UI, report. Each
line names its tool, and the block says every reflex is stated in full in
the using-scribe skill and in each tool description.
- names no client: CLAUDE.md, auto-memory and "the client injects ~2k
  chars" are gone
- gains the two reflexes it lacked: records that cite each other go through
  create_records with {{ref:N}}, and reports start from `placement`

The comment block above it now explains ownership (decision #4027) instead of
accumulating per-milestone trade history, and keeps the budget and its
reason (#2562).

build_session_context states only what the server knows about this session:
the active project and open work, its design system, an unbound-repo hint,
or that no project is bound. Removed: the "you are not holding the
operator's rules" section, the closing "Reflex: search Scribe" line, the
design-system usage sentence, and the plugin-specific header. using-scribe
owns all of that. The truncation note no longer restates the rules ask.

Tests: a pin that the live context carries no rules reflex; the cap test
drives truncation through the unbound-repo hint, since a bare session is now
one line; the budget test message describes the index.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-14 12:41:08 -04:00
co-authored by Claude Opus 5
parent 0a29252f9b
commit 76bfd92c21
4 changed files with 80 additions and 145 deletions
+10 -4
View File
@@ -114,6 +114,10 @@ async def test_build_session_context_includes_project_when_scoped():
# No design system on the project -> no design block at all. An install with
# none is the ordinary case, not a degraded one.
assert "## Design system" not in out["context"]
# Live state only (decision #4027): how to work with Scribe is the
# using-scribe skill's to say. A restated reflex here is a copy that drifts.
assert 'content_type="rule"' not in out["context"]
assert "Reflex:" not in out["context"]
@pytest.mark.asyncio
@@ -246,14 +250,16 @@ async def test_build_session_context_caps_length():
Patching the cap rather than manufacturing 9,000 characters keeps the test
about the TRUNCATION PATH — that it cuts, and that it says it cut — which
is the part a reader depends on.
is the part a reader depends on. The unbound-repo hint supplies the text:
since milestone 410 the block carries live state only, and a bare session
is a one-liner.
"""
from scribe.services import plugin_context as pc
with patch.object(pc, "_MAX_CHARS", 120):
out = await pc.build_session_context(user_id=7)
with patch.object(pc, "_MAX_CHARS", 60):
out = await pc.build_session_context(user_id=7, unbound_repo="host/owner/repo")
assert len(out["context"]) <= 120 + 60 # cap + truncation note
assert len(out["context"]) <= 60 + 20 # cap + truncation note
assert "truncated" in out["context"], (
"the block was cut without saying so — a reader cannot tell a "
"truncated context from a short one"