Skip to content

lifecycle.mdx's internal health-report sketch does not match PluginHealthReport #11787

Description

@os-steve

Found while implementing #11760 (PR #11789). Out of that card's scope — its ruling is relocate the sketch, do not rewrite it — so it is filed rather than fixed.

What was measured

#11760 moved the per-subsystem health sketch out from under the ### Health Status Response heading and into ### Custom Health Checks, the section that documents the internal health-monitor model. Writing an honest lead-in for it required checking what PluginHealthMonitor actually produces, and the sketch does not match.

The sketch (now at content/docs/protocol/kernel/lifecycle.mdx, under ### Custom Health Checks):

{
"status": "healthy",
"uptime": 3600,
"version": "2.0.0",
"timestamp": "2024-01-15T11:00:00.000Z",
"checks": {
"database": { "status": "healthy", "latency_ms": 5, ... },
"redis": { "status": "healthy", "latency_ms": 2 }
}
}

The real type, PluginHealthReport (packages/spec/src/kernel/plugin-lifecycle-advanced.zod.ts:90-126), constructed at packages/core/src/health-monitor.ts:185-193:

constreport: PluginHealthReport={status: this.healthStatus.get(pluginName)||'unknown',timestamp: newDate().toISOString(),
message,metrics: {uptime: Date.now()-startTime},checks: checks.length>0 ? checks : undefined,};
aspectsketchPluginHealthReport
scopeone aggregate documentper-pluginhealthReports is a Map<string, PluginHealthReport>
checkskeyed object of subsystemsarray of { name, status, message?, data? }
check status"healthy"enum "passed" | "failed" | "warning""healthy" is not a member
uptimetop-level, reads as secondsunder metrics, milliseconds (Date.now() - startTime, and the schema's .describe() says ms)
version"2.0.0"no such field in the schema

So the sketch matches neither an HTTP body (that was #11760, now fixed) nor the internal type it sits next to. #11760's lead-in says so explicitly and names the real type, which stops a reader coding against it, but the sketch itself is still a shape nothing produces.

Why it was not folded into #11760

The triage ruling on #11760 was explicit that B is relocate, not remove, and it also ring-fenced the "version": "2.0.0" literal from being touched (it belongs to an unexposed model with no producer to be stale against, so changing it would be a pattern-match rather than a measurement). Rewriting the sketch's body would cross both of those lines on the strength of a measurement the ruling had not seen. Hence a separate card.

Suggested direction

Not obvious; two readings, and the version question rides along with the choice.

  • A — replace the sketch with a real PluginHealthReport. The doc then shows a shape the code actually builds. version disappears (the schema has no such field), and uptime moves under metrics in ms. Costs the per-subsystem database/redis illustration, which the Callout above already flags as not what the model covers ("plugins, not driver connections").
  • B — drop the sketch and describe the model in prose, pointing at PluginHealthReport for the shape. Smallest surface, no shape to drift. Loses the worked example.

A looks right if the page wants a worked example at all, since it is the only option that leaves a shape backed by a producer. But the underlying question — whether content/docs/protocol/kernel/ should carry a worked example of an internal, unexposed model — is the same judgement call #11760 raised, so it is worth answering once here.

Not asserting more than was checked

Only the sketch and PluginHealthReport were compared. PluginHealthCheckParsed (the plugin-declared healthChecks config in the TypeScript example just above the sketch) was not audited against its schema, and no other page was examined.


Generated by Claude Code


Generated by Claude Code

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions