The FDRP evolution log advanced from entry 641 to 656 in a single cycle today. That is fifteen committed changes in a day — well above baseline cadence — and three of them were scope expansions, not tweaks. Each answers a binding constraint that had been quietly accumulating pressure for weeks. This post walks through the four stories that shipped: the stranded-research problem (R8 reusability), the append-only plan problem (R9 dynamic priority), the exfiltration problem (A3 prompt scrubber), and the scaffolding backdoor (BIND-049 Haiku purge).

BLUF. 11 new tables, 9 new views, 40 WSJF-scored roadmap items, 29 scrubber rules across 4 tenant tiers, one fail-closed Rust daemon, and one mesh-wide model-tier correction. Zero agents below Opus on the dispatch table after this cycle. The bin/ directory contains zero direct cross-model invocations; every one of them now routes through cross-model-scrubbed.

The stranded-research problem — R8 Gate 8a

MySQL is an excellent substrate for structured, queryable facts. It is a poor substrate for a 40KB cross-model critique, a 120 second web search result, or a claude.ai research export. When those artifacts are forced into TEXT columns they become opaque — you cannot diff them, you cannot grep them cheaply, and you cannot retrieve the right one without remembering the exact run_id that generated it. The natural failure mode is regeneration: the mesh quietly re-runs the same expensive web fetch or the same cross-model critique, paying for it again each time.

Scope VII (R8) adds a reusability substrate that treats MySQL as a catalogue and the filesystem as the store. Five new tables — reusable_artifacts, cross_model_cache, web_search_cache, claude_ai_imports, artifact_retrieval_log — index content-addressable artifacts that live under /var/lib/claude-shared/{cache,claude-ai-imports,web-cache}/. Three views surface hit-rate and staleness. An import tool at bin/import-claude-ai.sh ingests claude.ai research exports with deduplication by SHA hash.

The direct pressure source was a week of defence-branding research on claude.ai that would otherwise have been stranded in a browser tab. The deeper pressure was URL rot: external research links that were cited last month but resolve to 404 today. A reusability index with local storage fixes both.

The append-only plan problem — R9 Gate 9a

A queue that only grows is a queue that lies about itself. Roadmaps drafted in March were still at the top of the file in April even though new client fires — CJMM launch compensating control, Extruplast concept work, R4.5 std_error fix — had clearly superseded them. There was no formal way to say “item X got displaced because item Y arrived with a 10-day external deadline” without rewriting the file and losing the audit trail.

Scope VIII (R9) replaces the flat list with a WSJF-scored, database-backed queue. Four tables — roadmap_items, roadmap_priority_inputs, roadmap_decisions, roadmap_dependencies — hold the items, the four CoD components (cost of delay, reuse leverage, external urgency, upstream blocker), the audit trail of every reorder, and the dependency edges. Four views surface the ordered queue, recent insertions, staleness, and scope-grouped summaries. The formula is WSJF-lite:

wsjf = (cost_of_delay + reuse_leverage + external_urgency + upstream_blocker) / effort_points

40 items were seeded at launch. 26 priority rows are live. 6 audit rows in roadmap_decisions record how today's shipments moved the queue: R8 Reusability scored WSJF 13.3, R9 itself shipped the moment the table existed to record it, R4.5 std_error fix scored 3.0 and cleared in one cycle, and the two CJMM A3 shipments flipped CJMM launch from blocked to waiting on A1 tenant_id.

This gives the mesh agile cadence between waves (items get reordered every time trigger_event fires) and waterfall discipline within a wave (once an item is in_flight, it ships before the next reorder). The canonical ordered view is v_roadmap_priority_ordered.

The exfiltration problem — A3 prompt-scrubber MVP

Three client launches (Extruplast, Hospital-Twin, CJMM) were blocked on the same concern: when the mesh sends a prompt to an external model — Codex Pro (OpenAI) or Gemini 3.1 (Google) — what guarantees the prompt does not contain patient identifiers, tenant secrets, or industrial chemistry IP? Cross-model verification is a core FDRP discipline, but the pipes had no sanitizer.

Scope IV (A3) ships a Rust daemon at daemons/prompt-scrubber/ that sits between every caller and every external model. The DDL lives in prompt_scrubber_rules + prompt_scrubber_log with two auxiliary views. Every invocation writes an audit row; every deny or redact action is traceable. A wrapper at bin/cross-model-scrubbed is the only sanctioned cross-model entry point.

29 rules across 4 tiers:

TIER · GENERIC
12 rules
PII baselines: email, phone, IBAN, credit-card (with Luhn check), RFC 1918 IPs, private-key blocks.
TIER · HOSPITAL-TWIN
5 rules
CNP (Romanian national ID), medical-record numbers, dates of birth near diagnosis codes.
TIER · CJMM
5 rules
Tenant-ID redaction, internal path prefixes, staff credentials, court-file references.
TIER · EXTRUPLAST
7 rules
Formulation IDs, process parameters above a resolution threshold, customer manifests.

Action types are REDACT, DENY, and WARN. Severity is LOW to CRITICAL. The daemon is fail-closed: if the scrubber cannot reach its rule set, the wrapper refuses to send. If a rule matches on DENY, the caller gets an error and the prompt never leaves the host. This is the compensating control that unblocks all three launches.

Migration wave. Nine FDRP scripts in bin/ were migrated today from direct codex exec / gemini -m calls to cross-model-scrubbed. A pre-commit check enforces the invariant: zero direct cross-model invocations remain in the repository.

The scaffolding backdoor — BIND-049 mesh-wide Haiku purge

BIND-049 bans Claude Haiku from this system. Haiku lacks the reasoning depth for safety-critical work, and the cost savings from cheaper models are meaningless against the cost of a wrong threat assessment. Yet a routine audit today surfaced ten files still calling Haiku explicitly, all of them dated after BIND-049 was ratified.

Investigation found the root cause: the Anthropic marketplace scaffolding templates teach Haiku. When the mesh uses an upstream template as a starting point, Haiku is the default in the hello-world example — because Haiku is the cheap-demo model for plugin authors. The template was copying the wrong doctrine into our repo at scaffold time.

Fix: all ten files were rewritten to opus[1m], and a preventive PreCommit hook at /var/lib/claude-shared/hooks/enforce-bind049-no-haiku.sh blocks the string claude-haiku (and the shortened variants) from entering any file in the tree. This is a classic META-005 failure: the fix on its own repo did not propagate to the scaffolding source, so every new plugin was re-infecting the tree. The hook closes the scaffold-to-repo vector.

What this unblocks

Three external deliverables move from blocked to queued:

  • Extruplast concept work. The scrubber's Extruplast tier redacts formulation IDs and process parameters, so concept2X pipelines can run cross-model without leaking industrial chemistry IP.
  • Hospital-Twin resumption. CNP, MRN, and DOB patterns are now sanitized at the pipe. The physician-facing loop can resume against external models where needed.
  • CJMM launch compensating control. If A1 tenant_id isolation misses its deadline, the A3 scrubber is the fallback compensating control — every prompt leaving the CJMM tenant is redacted before egress.

Numbers at cycle end

MetricBefore (≈641)After (656)Delta
Base tables~644655+11
Views~297306+9
Roadmap items (live queue)040+40
Scrubber rules029+29
Haiku agents in dispatch100−10
Direct cross-model calls in bin/90−9
Evolution-log entries (delta)+15

FDRP principles reinforced

Each of the three scope expansions is an application of an earlier FDRP principle, not a novelty:

  • R8 is reuse leverage — the WSJF component that scores cheap, multi-use substrate highly. The reusability table is itself WSJF-scored; that is why it got ahead of items with more visibility.
  • R9 is BIND-043 IMPLEMENT_LOW in its cleanest form — queue reordering is a deterministic operation against a deterministic view. No LLM inference in the priority path.
  • A3 is BIND-044 IMPLEMENT_MEDIUM with peer-review gating — the Rust daemon was sent to cross-model review before it was wired into bin/, even though the rule additions themselves are mechanical regex.
  • BIND-049 enforcement is META-005 (partial fix not propagated) corrected by a PreCommit hook, and BIND-048 (detection without correction is failure) honoured by fixing all ten files in the same cycle the violations were found.

The live dashboard at /dashboard/roadmap.html shows today's queue. The state tile at the top of the dashboard index reflects the counts above. The full evolution log is queryable by anyone with read access to c6_mysql_intelligence.

———
← All research notes