Skip to content

docs(api): document typed StallEventPayload on status.stall.typed SSE event (#4802)#4807

Merged
aegis-gh-agent[bot] merged 1 commit into
developfrom
docs/4802-typed-stall-payload
Jun 22, 2026
Merged

docs(api): document typed StallEventPayload on status.stall.typed SSE event (#4802)#4807
aegis-gh-agent[bot] merged 1 commit into
developfrom
docs/4802-typed-stall-payload

Conversation

@OneStepAt4time

Copy link
Copy Markdown
Owner

Summary

Documents the new status.stall.typed SSE event and its typed StallEventPayload schema introduced by PR #4806 (Issue #4802 F-9 β€” typed stall payload wiring at every stall-detector emit site).

What changed

  • docs/api-reference.md:
    • Added status.stall.typed to the Per-Session Events (SSE) event-type list (inline reference at the top of the section).
    • Added a new Typed Stall Payload (status.stall.typed) subsection covering:
      • Full wire-format example with every StallEventPayload field populated.
      • Field reference table (typed, presence rule, description).
      • Bounded errorClass enum reference (6 values from ERROR_CLASS_VALUES).
      • Backward-compat note (legacy free-form stall event still ships in parallel).
      • Channel-fanout note (statusCode stripped for Telegram/Slack/Email via toChannelFanoutPayload()).
      • Migration recipe for consumers on the legacy stall event.

Why

PR #4806 adds a typed superset of the legacy free-form stall SSE event. The renderer (PR #4804 dashboard pill + Send continue button) consumes the typed schema, but every external consumer (CLI scripts, third-party integrations, channel transports) needs to know:

  1. The new event name on the per-session SSE stream.
  2. The bounded errorClass enum values (no more free-form string parsing).
  3. The conditional presence of statusCode (only when errorClass === 'transient_5xx').
  4. The channel-fanout fingerprint-defense rule (operator surfaces see statusCode, channels don't).

Without docs, the new event is opaque β€” consumers can't subscribe or render it correctly.

Aegis version

Developed with: v0.6.7

Cross-references

Verification

  • Cross-checked all field names + types against src/stall-events.ts (StallEventPayload interface, lines 56-78) βœ“
  • Cross-checked all 6 errorClass enum values against ERROR_CLASS_VALUES (src/stall-events.ts:35-42) βœ“
  • Cross-checked emitStallTyped event name (status.stall.typed) against src/events.ts:380 βœ“
  • Cross-checked SessionSSEEvent union addition against src/events.ts:20-22 βœ“
  • Cross-checked toChannelFanoutPayload strip rule against src/stall-events.ts:115-120 βœ“
  • Cross-checked extractStatusCode 5xx-only validation against src/stall-detector-typed-emit.ts:78-87 βœ“
  • Cross-checked recovery counter reset semantics against PR #4806 description (recoveryAttempts resets on success + idle transition) βœ“
  • Anchor link #typed-stall-payload-statusstalltyped matches GitHub's auto-generated slug for ### Typed Stall Payload (status.stall.typed) βœ“

Diff: 1 file, +68/-0.

Follow-ups (out of scope for this PR)

  • The global event stream (GET /v1/events) does NOT emit status.stall.typed β€” the typed variant is exclusively on the per-session stream. Pre-existing minor docs drift (session.stalled listed vs session_stall in code) is also untouched here β€” separate cleanup PR if Boss wants it.
  • recoveryExhausted field is computed locally by the dashboard from recoveryAttemptCount >= recoveryMaxAttempts, not server-emitted. No API surface to document.
  • Channel-side fanout (Telegram/Slack/Email) currently receives legacy status.stall with free-form detail; a follow-up PR can route meta: toChannelFanoutPayload(payload) through SessionEventPayload.meta for typed channels. Not blocking β€” F-9 close scope is the SSE path.

@aegis-gh-agent aegis-gh-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

βœ… APPROVED β€” docs(api): document typed StallEventPayload on status.stall.typed SSE event (#4802)

9-gate audit (all passed):

  1. βœ… Review completed β€” full diff reviewed, content verified against develop sources
  2. βœ… No conflicts β€” mergeable: MERGEABLE
  3. βœ… CI green β€” all 4 required status checks pass (lint-pr-title, test ubuntu-22, lint, Analyze/CodeQL); advisory test ubuntu-20 still in progress but non-blocking
  4. βœ… No regressions β€” docs-only, no code changes
  5. ⏭️ Unit tests β€” N/A for docs-only per MEMORY 2026-06-09
  6. ⏭️ E2E/UAT β€” N/A for docs-only
  7. βœ… Documented β€” this IS documentation
  8. βœ… Security clean β€” Gitleaks, Trivy, GitGuardian all green; no secrets in diff
  9. βœ… Targets develop

Content accuracy β€” verified against develop source:

Claim in docs Source verified
6 errorClass enum values src/stall-events.ts:35-42 ERROR_CLASS_VALUES β€” all 6 match exactly (transient_5xx, permission_timeout, jsonl_stall, thinking_stall, unknown_stall, extended_working)
StallEventPayload field shape (7 fields, types, presence rules) src/stall-events.ts:56-78 interface β€” matches
statusCode only when errorClass === 'transient_5xx' src/stall-events.ts builder validates scope; extractStatusCode returns undefined for non-5xx
status.stall.typed event name on per-session SSE src/events.ts:20 union addition + src/events.ts:380 emitStallTyped body
toChannelFanoutPayload() strips statusCode (fingerprint-defense) src/stall-events.ts:115-120
recoveryDisabled per-session kill-switch state matches SessionInfo semantics

Strengths:

  • Wire-format example shows every field populated
  • Field reference table with type + presence rule + description is exactly what consumers need
  • errorClass enum table makes the bounded contract unmissable
  • Channel-fanout fingerprint-defense note is security-aware (operator surfaces vs channels β€” right call)
  • Migration recipe shows the curl+jq filter idiom for typed-only subscribers
  • Backward-compat note preserves the legacy stall event as the Path 2 fallback

Scope discipline: 1 file (docs/api-reference.md), +68/-0. No scope creep. Anchor #typed-stall-payload-statusstalltyped matches the auto-generated GitHub slug.

PR body follow-ups (out of scope, acknowledged):

  • Global event stream (GET /v1/events) doesn't emit status.stall.typed β€” pre-existing minor docs drift noted but untouched, separate cleanup PR if Boss wants it
  • Channel-side fanout typed variant deferred β€” not blocking F-9 close scope

Cross-references validated: src/stall-events.ts, src/events.ts, src/stall-detector-typed-emit.ts β€” all source paths cited in the PR body match the actual files on develop.

Lane: owner-authored PR β†’ bot APPROVE + squash directly per MEMORY 2026-06-21 matrix.

@aegis-gh-agent aegis-gh-agent Bot merged commit 79fba30 into develop Jun 22, 2026
18 checks passed
@aegis-gh-agent aegis-gh-agent Bot deleted the docs/4802-typed-stall-payload branch June 22, 2026 18:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant