Files
Jarvis/packages/AgentCore/Sources
james.maesandClaude Opus 4.7 23b4ca7712 feat(round-4): agent system prompt knows when subsystems are degraded
Slice 3 of Round 4 — the Toby-the-dog fix. With Slice 1 the probes
report severity and with Slice 2 banners route by severity, but the
critical behavioral change is here: the agent's system prompt itself
must carry the degradation truth so the model can't confidently lie
about features that don't work.

The Toby case in detail: user said "remember my dog Toby is a golden
retriever". The Ollama probe correctly reported missing nomic-embed-text
(degraded). The memory extractor tried to embed Toby, the embed call
failed, no row was inserted in `facts`. But the agent's system prompt
said "you are Jarvis with memory" and the model answered "Got it —
Toby." A lie, dressed up as competence.

Implementation:

- `AgentOrchestrator` gains a private `var degradationSummary: String?`
  + a public `setDegradationSummary(_:)` actor-isolated setter. Mutable
  because installAgent runs BEFORE runBootHealth in the boot order;
  the orchestrator is constructed with `nil` and AppDelegate pushes
  the summary in post-construction. Re-probes from the Status panel
  update the value mid-session.
- `runTurn` prepends the summary BEFORE `composedSystem` (which already
  includes the UntrustedWrapper nonce + locked self-aware preamble),
  so the warning lands at the very top of the system message — outranks
  the preamble, outranks presence/memory enrichment.
- `AppDelegate.runBootHealth` now calls
  `orchestrator.setDegradationSummary(buildDegradationSummary(snapshot:))`
  after every probe sweep. The builder produces text like:

    CRITICAL — SUBSYSTEMS DEGRADED:
    - memory: failed (vec0 missing) — DO NOT promise to use memory
    - ollama: degraded — missing models: nomic-embed-text
    Be honest. Do not claim to use tools that are unavailable. Do not
    pretend memory works if it doesn't.

  When every subsystem is `.ok`, the function returns `nil` and the
  orchestrator's behavior is identical to pre-Round-4.

- Cache-hints invariant preserved: the locked preamble is ~700 chars,
  the worst-case degradation summary is <500 chars; sum stays well
  under the 4096-char Anthropic cache-eligibility boundary so adding
  the summary doesn't unintentionally flip `cache_control` emission.
  CacheHintsEligibilityTests/preambleDoesNotEnableCacheUnintentionally
  remains green.

4 new tests in AgentOrchestratorDegradationPreambleTests (all pass):
  * DP1: initial summary threaded into first turn's system message
  * DP2: nil summary leaves prompt unchanged (no "CRITICAL" / "DO NOT")
  * DP3: setDegradationSummary updates the next turn's prompt
  * DP4: setting summary back to nil clears it from the next turn

Boundary gates 18/18 green. `swift test --package-path packages/AgentCore`
runs 242/240 (4 new minus 2 pre-existing unrelated failures from
qwen2.5-coder model-ID literal drift, present before Round 4).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-11 15:47:58 -05:00
..