[Bug] Control tokens leaked to user output in agentic task notifications

Open 💬 0 comments Opened Jul 7, 2026 by ben-at-felicis

Bug Description
claude code seemed to leak internal control tokens like <task-notification> raw into user-visible space: Monitor(Waiting for Plan agent seam-verification results)
Monitor started · task b8u09ryal · timeout 600s

Thought for 10s

The Plan agent is still reading the codebase — I'll finalize and present the plan as soon as it reports back.

system[SYSTEM NOTIFICATION - NOT USER INPUT]
This is an automated background-task event, NOT a message from the user.
Do NOT interpret this as user acknowledgement, confirmation, or response to any pending question.

<task-notification>
<task-id>aeddb425e7a993fff</task-id>
<tool-use-id>toolu_01Y3thpuc9tNyKkbLLSGXhbP</tool-use-id>
<output-file>/private/tmp/claude-501/-Users-benmathes-coding-felicis-exoskeleton-exo1/8a2c0439-0ebf-464a-a744-7d62ae7ef802/tasks/aeddb425e7a993fff.output</output-file>
<status>completed</status>
<summary>Agent "Draft implementation plan + verify seams" finished</summary>
<note>A task-notification fires each time this agent stops with no live background children of its own. The user can send it another message and resume it, so the same task-id may notify more than once.</note>
<result>Plan complete. The full implementation plan is above. Key summary:

Implementation Plan Summary

Feature: Weekly OSS Traction Sourcing email digest — headless two-phase skill run (web-isolated Phase 1, MCP-only Phase 2), rendered to branded HTML email + WeasyPrint PDF attachment, sent to EmailConfig subscribers via cron.

Verified seams (all file:line references confirmed by reading):

  1. run_anthropic_project() (anthropic_project_runner.py:257) — needs 3 new optional kwargs: allowed_tools, create_session, store_prompt_full. Subprocess stdin JSON gets allowed_tools key; _sdk_subprocess.py:236 reads it with fallback to current default. partner_email must resolve to an allowlisted Person (email_handler pattern) — use settings.DIGEST_RUNNER_EMAIL (ben@felicis.com) for the cron identity.
  2. Idempotency (send_slack_digest.py:107-133) — SystemEvent.objects.filter(event_type="oss_sourcing_digest_sent", created_at__gte=window_start).exists() guard; --force bypasses; record after successful send with payload (week key, recipients, tool_calls, duration).
  3. Email attachments — EmailAttachment NamedTuple (filename, content bytes, mimetype) added to backends/base.py Protocol; gmail.py:~また150 and ses.py MIME assembly switch from MIMEMultipart("alternative") to outer mixed wrapping the alternative part + MIMEApplication parts; memory.py records attachments for test assertions. send_email() api.py:39 gains attachments: Sequence[EmailAttachment] | None = None.
  4. Skill prompt from DB — MarkdownContext.objects.get(entity_type="skill", feature="oss_traction_sourcing") via existing get_skill_prompt() helper in core/skills/loader.py:44. Flag: seed frontmatter name: oss-traction-sourcing-test — seeding uses filename stem (oss_traction_sourcing) as feature key (seed_contexts.py:88 confirmed), frontmatter name is claude.ai-facing only. No blocker, but rename the "-test" suffix in the same PR.
  5. Namespace floor — namespaces.yaml defines: mcp_market, mcp_pipeline, mcp_portfolio, mcp_finance, mcp_lp, mcp_canonical. Portfolio-universe ("IN" bucket) check reads mcp_portfolio.portfolio_companies (verified in semantic layer YAML) — mcp_finance NOT needed. Floor = {mcp_canonical, mcp_market, mcp_pipeline, mcp_portfolio}.
  6. WeasyPrint — add weasyprint>=62 to pyproject [project.dependencies]; apt packages libpango-1.0-0 libpangoft2-1.0-0 libgdk-pixbuf-2.0-0 added to bin/setup-self-server:31 apt block; macOS dev needs brew install pango documented in README + checked in bin/setup-self-dev. Font note: Helvetica falls back to Liberation Sans on Linux — visually acceptable, add fonts-liberation to apt list.
  7. Cron — exact line format verified against crontab.production:61-66 pattern (cron-wrap + logs). New lines for 0 14 1 both files + deployment.md table row + DST comment.
  8. Tests to mirror: test_send_slack_digest.py (command-level, mocks service), test_email_backends.py (memory backend assertions), new test_oss_sourcing_digest.py integration test with unittest.mock.patch("core.services.oss_sourcing_digest.run_anthropic_project") two-call side_effect.

Risks flagged: (a) Phase 1 web run can exceed max_turns on tracker disagreement — set per-phase max_turns overrid

Environment Info

  • Platform: darwin
  • Terminal: Apple_Terminal
  • Version: 2.1.193
  • Feedback ID: c8b87286-e893-4b8a-97e1-1fc9f72440a5

Errors

[]

<img width="1492" height="1174" alt="Image" src="https://github.com/user-attachments/assets/006aa96e-bcdb-407d-880d-a0e21f5a7c34" />

View original on GitHub ↗