Operator directive: creating Systems is the agent's call, not an approval
flow — "propose to the operator, create each confirmed one" made the
operator a permission gate. The bootstrap ask now says create_system 3-6
directly, in-session, and the consistency that approval was covering moves
to a standard cross-project vocabulary (CI & Release, Auth & Access, Data
Model & Storage, API Surface, UI & Design, Import & Export, Background
Jobs, Observability): use the standard name verbatim where the area fits,
mint freely beyond it, the duplicate gate guards sprawl. create_system and
enter_project docstrings carry the same contract.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The generic zero-state systems_hint never converts: identical on every
record, maximal in scope, asked at wrap-up time — Minstrel reached 282
records with zero Systems while vocabularied projects grew organically.
What converts is the project's own evidence at the moment of action.
bootstrap_systems_ask (mcp/tools/systems.py) fires only in a project
with >=20 records and no Systems: it names the record count and recent
titles, and asks for a concrete deliverable — propose 3-6 Systems,
confirm with the operator, create_system the set. Self-retiring: the
first System ends it everywhere. Wired at both moments the task named:
untagged_systems_hint escalates to it at write time, and enter_project
carries it as systems_bootstrap at arrival (attached only when it
applies). Young projects keep the mild question; populated vocabularies
never pay the count query.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Runs 3562/3565: _fake_system never sets .id so the dup-gate assertion
compared a MagicMock to 7; and a shared to_dict return_value dict let
the tagged create's mutation leak into the orphan create's response.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Scribe issue #2570, from the operator's challenge: the invariant is
"always be asking whether what you're touching is a System's territory
and whether the work is filed there" — not a nudge in one corner. The
prior shape failed it twice: the hint fired only on creates (with a
special-cased zero-Systems branch), and get_task/get_note returned
records WITHOUT their Systems, so the read-side reflex had nothing to
fire on (same per-kind asymmetry as #2481).
- attach_systems(): single helper used by get/create/update for tasks,
notes, and snippets, plus add_task_log. Tagged records always show
`systems`; an untagged project record carries the `systems_hint`
question instead. Neither field attaches empty (#2483). Hint is
owner-only; everything fail-open (#2109).
- untagged_systems_hint unified to ONE question — the vocabulary
listing varies, the question doesn't; the zero-Systems branch stops
being special text.
- Docstrings state the uniform contract; floor prose now names the
read-side reflex (systems visible -> list_system_records the pile).
- Plugin 0.1.27 -> 0.1.28.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
First real-world test of the #2562 fixes (Scribe issue #2569): a Forge
session ran a whole-codebase audit and created zero Systems — endorsed
by the shipped guidance, whose "no particular area takes none" clause
read as an exemption for exactly the record type that enumerates the
subsystem vocabulary. And the systems_hint was silent for a zero-Systems
project, the one state nothing else nudges out of.
- systems_hint gains a zero-Systems branch: prompt the FIRST
create_system instead of going quiet.
- create_system is duplicate-gated like the other creates (normalized
name, archived included, fail-open) — liberal creation becomes safe by
construction, so the guidance can stop preaching restraint.
- Prose inverted on every surface (hint text, create_system docstring,
floor bullet, using-scribe step 7): audits/sweeps take several tags
and mint the Systems they name; the gate is the guardrail against
sprawl, not holding back; only a record genuinely about no particular
area goes untagged.
- Plugin 0.1.26 -> 0.1.27.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude Code injects only the first ~2,048 chars of an MCP server's
instructions and silently cuts the rest mid-word (#2562, observed live):
_INSTRUCTIONS was 20,002 chars, so ~90% — including all Systems tagging
guidance — never reached any session. Rearchitect delivery around what
each surface actually delivers:
- _INSTRUCTIONS becomes a 1,997-char purpose-sorted map, with a header
comment stating the budget and where detail belongs instead.
- Tool docstrings keep the per-tool HOW (audit: nearly all displaced
topics were already duplicated there); backfill the four gaps —
enter_project session scoping + project bootstrap, create_rule
entity-vs-rule test, create_design_system not-a-rulebook,
create_system two-records test.
- The plugin static context (the delivery floor) gains the
tag-to-Systems reflex and a surfaces-layering statement; plugin
0.1.25 -> 0.1.26 so the executing cache refreshes (#2209).
- create_task / create_note / create_snippet return a systems_hint when
a record is created untagged in a project that has Systems — in-band
at the exact write it applies to, fail-open like the dedup gate.
- Guards: _INSTRUCTIONS length budget, floor-states-the-reflex, and a
displaced-topics sweep asserting every cut topic still lives on a
delivered surface.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Second slice of Issues + Systems (spec #825).
New mcp/tools/systems.py: create_system, list_systems, get_system (records
split into issues/tasks/notes), update_system (incl. archive via status),
list_system_records (kind/open_only filters), delete_system. Registered in
register_all; read tools (get_system, list_systems, list_system_records) added
to the read-only-key allowlist (write tools default-deny).
create_task/update_task: kind now accepts 'issue'; new system_ids (set-semantics
associations) and arose_from_id (provenance, 0=unchanged/-1=clear) args.
create_note/update_note: new system_ids arg (notes associate with systems too).
services/notes.create_note: arose_from_id passthrough (update_note already
handles it via setattr).
Tests: MCP system tools + create_task issue-wiring (kind/provenance/systems),
service layer mocked.
Refs plan 825 (S2).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>