fix(calendar): surface degraded get_calendar_events sentinel so web fallback fires#2833
Conversation
…llback fires The riksdag-regering MCP get_calendar_events tool returns a "successful" empty events:[] result with an error/rawHtml sentinel when upstream data.riksdagen.se/kalender/ serves HTML. The client read this as a legitimate zero-event window, masking the outage and suppressing the web-scraper fallback. Add isDegradedKalenderSentinel detection in both calendar clients (throw CalendarMcpError 'html' so orchestrator falls back), plus regression tests and agentic guidance steering agents to the resilient scripts/calendar-fetch.ts CLI / data/runtime/calendar-status.json. Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
🏷️ Automatic Labeling SummaryThis PR has been automatically labeled based on the files changed and PR metadata. Applied Labels: documentation,testing,refactor,size-m Label Categories
For more information, see |
🔍 Lighthouse Performance Audit
📥 Download full Lighthouse report Budget Compliance: Performance budgets enforced via |
|
@copilot analyse TypeScript & JavaScript Testing / Build Test (Vite) (pull_request) and improve code quality and test coverage |
…xpand test coverage
- Refactored scripts/mcp-client/methods/calendar.ts to import and use the
shared isDegradedKalenderSentinel() from fetch-calendar/mcp/errors.ts
instead of duplicating the detection logic inline.
- Added 9 new test cases across 3 test files:
- errors.test.ts: both fields present, rawHtml-only, empty object,
additional non-string type variants
- client.test.ts: malformed JSON content, rawHtml in responseText,
error message propagation, rawHtml-only sentinel
- calendar.test.ts: rawHtml-only sentinel, error message verification
Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
The CI failure was a runner timeout/shutdown during the I've made the following improvements in commit Code quality:
Test coverage (50 → 59 tests, all passing):
|
🔍 Lighthouse Performance Audit
📥 Download full Lighthouse report Budget Compliance: Performance budgets enforced via |
There was a problem hiding this comment.
Pull request overview
This PR fixes calendar outage handling so degraded get_calendar_events MCP responses are surfaced as failures instead of being interpreted as legitimate empty calendars, allowing fallback/error reporting paths to behave honestly.
Changes:
- Adds degraded calendar sentinel detection for
error/rawHtmlMCP payloads. - Wires detection into both the resilient calendar fetcher and generic MCP calendar method.
- Updates prompt/template guidance and adds regression tests for sentinel handling and fallback behavior.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
scripts/fetch-calendar/mcp/errors.ts |
Adds isDegradedKalenderSentinel() detector. |
scripts/fetch-calendar/mcp/client.ts |
Throws CalendarMcpError('html') for degraded sentinel payloads. |
scripts/fetch-calendar.ts |
Re-exports the new detector. |
scripts/mcp-client/methods/calendar.ts |
Makes generic MCP calendar calls throw on degraded sentinel results. |
tests/fetch-calendar/mcp/errors.test.ts |
Covers sentinel detection positives and negatives. |
tests/fetch-calendar/mcp/client.test.ts |
Covers content-wrapped/direct sentinel handling and error propagation. |
tests/fetch-calendar/orchestrator-integration.test.ts |
Verifies sentinel-triggered web fallback. |
tests/mcp-client/methods/calendar.test.ts |
Covers generic MCP client sentinel failures. |
analysis/templates/session-baseline.md |
Documents resilient calendar sourcing guidance. |
.github/prompts/02-mcp-access.md |
Instructs workflows to use the resilient CLI/prewarm artifact instead of raw calendar tool output. |
Analysis of the last 5 agentic-workflow PRs (#2819, #2821, #2822, #2823, #2824) for degraded datasources surfaced a client masking bug: when
data.riksdagen.se/kalender/serves an HTML error page, the riksdag-regering MCPget_calendar_eventstool returns a successful result wrapping a sentinel{count:0, events:[], error, rawHtml}. The clients read the emptyevents:[]as a legitimate zero-event window, soscripts/calendar-fetch.tsreported a falsestatus:ok, path:mcp-primaryand the web-scraper fallback never fired — masking the outage as a real zero-sitting week.Client code
scripts/fetch-calendar/mcp/errors.ts— newisDegradedKalenderSentinel()detector; triggers only on a non-emptyerrorstring orrawHtml, so a clean{count:0, events:[]}stays a valid empty window.scripts/fetch-calendar/mcp/client.ts— detect the sentinel in both the content-wrapped and direct-result paths and throwCalendarMcpError(..., 'html', rawHtml);orchestrator.tsalready breaks the retry loop onkind:'html'and falls straight to the public-page scraper.scripts/mcp-client/methods/calendar.ts— mirror the detection (throw instead of returning[]).scripts/fetch-calendar.ts— re-export the new detector.With the fix, the CLI now reports
status:error, path:noneduring the outage instead of a fabricated zero-event success.Agentic config / prompts / instructions
analysis/templates/session-baseline.md— added a 📅 Calendar sourcing degraded-source guard and pointed the 3 inlineget_calendar_eventsreferences at the resilientdata/runtime/calendar-status.json/scripts/calendar-fetch.ts..github/prompts/02-mcp-access.md— added a data-sourcing rule: fetch the calendar via the resilient CLI / pre-warm artifact (never the raw tool); record[DATA GAP: calendar source degraded]when both paths fail.Tests
tests/fetch-calendar/mcp/errors.test.ts,tests/fetch-calendar/mcp/client.test.ts(content + direct sentinel →kind:'html'),tests/fetch-calendar/orchestrator-integration.test.ts(sentinel → web-fallback), andtests/mcp-client/methods/calendar.test.ts(sentinel → throws).Out of scope (documented)
The public fallback page moved from
/sv/kalendarium/(now 404) to a Next.js/sv/aktuellt/kalendersida/serving data in__NEXT_DATA__; repointing the HTML scraper needs a parser rewrite plus markup fixtures. The now-honeststatus:error/path:noneensures the degradation is no longer silently masked in the meantime.IMF (no change)
The other degraded source flagged in the manifests is already mitigated by the 3-tier WEO pipeline and
data/imf-context.jsondegraded/unavailablehandling.