Found while writing the scheduled-jobs guide (#10211). Comment-only drift in a contract file — no runtime behaviour is wrong, but the comment is the authority a handler author reads before deciding whether reporting degraded does anything.
The stale text
packages/spec/src/contracts/job-service.ts, in the JobHandler docblock:
The reporting channel is deliberately opt-in on both ends. Consuming it — mapping degraded onto a sys_job_run.status distinct from success — is #5548's half and is not yet wired: the shipped adapters currently discard the resolved value, which is precisely why doing so is safe.
What the tree actually does now
All three shipped adapters map a resolved { outcome: 'degraded' }, and the persistence half landed too:
packages/services/service-job/src/cron-job-adapter.ts — if (outcome && outcome.outcome === 'degraded') { execution.status = 'degraded'; execution.error = outcome.reason; }packages/services/service-job/src/interval-job-adapter.ts — same mappingpackages/services/service-job/src/db-job-adapter.ts — settles the run as degraded, writes the reason to error / last_error, and leaves failure_count flatsys_job_run.status and sys_job.last_status both carry degraded in their enforced select vocabularies (packages/platform-objects/src/audit/sys-job-run.object.ts, sys-job.object.ts), each with a [#7072] comment saying it must stay in step with JobExecutionStatus
So the sentence is inverted twice over: the value is no longer discarded, and "which is precisely why doing so is safe" now argues for a safety that rests on a fact that has changed.
Why it is worth a card rather than a silent fix
The same docblock is the reason a handler author would decide not to bother returning { outcome: 'degraded' } — it currently tells them nothing will read it. JobExecutionStatus in system/job.zod.ts already documents the wired behaviour correctly, so the two halves of the spec disagree with each other.
Scope is one docblock in packages/spec/src/contracts/job-service.ts; the #5548/#6617 framing above it stays, only the "not yet wired" paragraph needs re-measuring against the adapters.
Filed unassigned from the #10211 docs card, which is barred from touching packages/spec/**. The new content/docs/automation/jobs.mdx documents the measured behaviour (degraded is recorded, never retried, leaves failure_count flat), not the docblock's claim.
Found while writing the scheduled-jobs guide (#10211). Comment-only drift in a contract file — no runtime behaviour is wrong, but the comment is the authority a handler author reads before deciding whether reporting
degradeddoes anything.The stale text
packages/spec/src/contracts/job-service.ts, in theJobHandlerdocblock:What the tree actually does now
All three shipped adapters map a resolved
{ outcome: 'degraded' }, and the persistence half landed too:packages/services/service-job/src/cron-job-adapter.ts—if (outcome && outcome.outcome === 'degraded') { execution.status = 'degraded'; execution.error = outcome.reason; }packages/services/service-job/src/interval-job-adapter.ts— same mappingpackages/services/service-job/src/db-job-adapter.ts— settles the run asdegraded, writes the reason toerror/last_error, and leavesfailure_countflatsys_job_run.statusandsys_job.last_statusboth carrydegradedin their enforced select vocabularies (packages/platform-objects/src/audit/sys-job-run.object.ts,sys-job.object.ts), each with a[#7072]comment saying it must stay in step withJobExecutionStatusSo the sentence is inverted twice over: the value is no longer discarded, and "which is precisely why doing so is safe" now argues for a safety that rests on a fact that has changed.
Why it is worth a card rather than a silent fix
The same docblock is the reason a handler author would decide not to bother returning
{ outcome: 'degraded' }— it currently tells them nothing will read it.JobExecutionStatusinsystem/job.zod.tsalready documents the wired behaviour correctly, so the two halves of the spec disagree with each other.Scope is one docblock in
packages/spec/src/contracts/job-service.ts; the#5548/#6617framing above it stays, only the "not yet wired" paragraph needs re-measuring against the adapters.Filed unassigned from the #10211 docs card, which is barred from touching
packages/spec/**. The newcontent/docs/automation/jobs.mdxdocuments the measured behaviour (degraded is recorded, never retried, leavesfailure_countflat), not the docblock's claim.