You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(spec): the protection-envelope check was hollow — it skipped 24 of 25 types (#4001) (#4519)
The invariant test added one change ago asserted two things about every
registered metadata type: that it does not REJECT the ADR-0010 envelope its
loader stamps (the hard-422 case), and that it does not silently lose it.
The reject half worked — it found `hook` and `datasource` on its first run.
The other half did not. It probed each schema with one generic body and asked
whether `_packageId` survived. A type whose required fields that body did not
supply failed for unrelated reasons, and the assertion returned early. TWENTY-
FOUR of the twenty-five types took that early return. Only `field` was ever
really checked, and the suite reported green.
That is this campaign's own subject matter — a success signal covering an
omission — reproduced inside the instrument built to detect it, one change after
the ledger recorded the identical lesson about the strictness gate's
non-recursive directory walk. A check that skips is indistinguishable from a
check that passes.
The declaration side is now STRUCTURAL: it walks the schema, unwrapping
lazy/pipe/optional/default and expanding unions, and asks whether any resolved
object shape declares the key. That needs no valid instance, so it cannot skip.
Two guards keep it honest:
- a type the walker cannot resolve is a hard FAILURE, not a pass. The walker
going quiet is exactly when this test would otherwise stop covering
something.
- the debt list carries a reverse pin that fails when an entry is fixed, so
the list cannot outlive the debt it tracks.
What it found: 8 registered types do not declare the envelope, not 1 — `action`,
`book`, `field`, `job`, `mapping`, `page`, `translation`, `validation`. Each
loses protection metadata on every round-trip today and becomes a hard 422 the
day its schema closes. `job` and `book` are closed here; 6 remain listed.
Three occurrences now of one pattern, in three different instruments: the ledger
gate's non-recursive walk, `strictObject(` not matching the site count, and this
early return. Every one was a measuring tool reporting coverage it did not have.
The ledger now states the rule it keeps re-deriving: before trusting a green
check, make it go red on something you know is there.
Verified: spec 282 files / 7141 tests, `tsc --noEmit` clean, all 8 generated
artifacts current (the only regeneration is the two envelope key tables), all
15 `check:*` gates green.
Claude-Session: https://claude.ai/code/session_01WnqGjQFQMqd5k81LYV8SCY
Co-authored-by: Claude <noreply@anthropic.com>
The protection-envelope invariant test was hollow — it silently skipped 24 of 25 registered types. Fixed, and it immediately found 8 undeclared envelopes instead of 1.
6
+
7
+
The check shipped in the previous change asserted two things about every registered metadata type: that it does not *reject* the ADR-0010 envelope its loader stamps (the hard-422 case), and that it does not *strip* it (the silent-loss case). The reject half worked — it found `hook` and `datasource` on its first run.
8
+
9
+
The strip half did not. It probed each schema with one generic body and asked whether `_packageId` survived; a type whose required fields that body did not satisfy failed for unrelated reasons and the assertion returned early. **24 of the 25 types took that early return.** Only `field` was ever actually checked, and the suite reported green.
10
+
11
+
That is the campaign's own subject matter — a success signal covering an omission — reproduced inside the instrument built to detect it, one change after the ledger recorded the same lesson about the strictness gate's non-recursive directory walk. A check that skips is indistinguishable from a check that passes.
12
+
13
+
**The declaration side is now structural.** It walks the schema — unwrapping `lazy` / `pipe` / `optional` / `default` and expanding unions — and asks whether any resolved object shape declares the key. That answer does not require constructing a valid instance, so it cannot skip. Two guards keep it honest: a type whose shape the walker cannot resolve is a hard failure (the walker going quiet is exactly when this test would otherwise stop covering something), and the debt list carries a reverse pin that fails when an entry is fixed, so the list cannot outlive the debt it tracks.
14
+
15
+
**What it found:** 8 registered types do not declare the envelope, not 1 — `action`, `book`, `field`, `job`, `mapping`, `page`, `translation`, `validation`. `job` and `book` are closed here, leaving 6 on the list. Each is protection metadata lost on every round-trip today, and a hard 422 the day its schema is closed.
Copy file name to clipboardExpand all lines: content/docs/references/system/job.mdx
+7Lines changed: 7 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -65,6 +65,13 @@ const result = CronSchedule.parse(data);
65
65
|**retryPolicy**|`{ maxRetries?: integer; backoffMs?: integer; backoffMultiplier?: number }`| optional | Retry policy: failed runs (including timeouts) are retried with exponential backoff (delay = backoffMs * backoffMultiplier^(retry-1)) up to maxRetries retries after the initial attempt (#3494). Omit for the legacy single-attempt behavior. |
66
66
|**timeout**|`integer`| optional | Per-attempt time limit in milliseconds; an over-limit run is recorded with execution status "timeout" (#3494). The in-flight handler is abandoned, not forcibly cancelled. Omit for no time limit. |
67
67
|**enabled**|`boolean`| optional | Whether the job is enabled |
0 commit comments