Commit fb29f62
Fixes #18076
Clause-②: no — the landing surface is prose inside one already-compiled
`packages/spec/CHANGELOG.md` entry plus an erratum line. No schema key,
no accepted-set change, no new exported symbol, no new key on a
published payload, and no path under `packages/**/src/**` moves.
`skip-changeset`: no package publishes anything from this change.
## The ruling this PR implements
Director seat, decision batch #119 item 1, 2026-09-12T04:15Z,
maintainer's own word `1A·2A·3A·4D·5A`: 「同意」, implemented once already
by `ef47459474` (#17896). This card applies the same remedy shape to a
second falsified instance:
> **A: correct the two published CHANGELOG entries in the repository,
with a post-release erratum note.** … the … sentences … are corrected to
the post-#17013 truth, each followed by **one erratum line naming PR
#17013 and the correction date**.
>
> **Before editing**, run the release tooling's dry-run (`changeset
version` on a scratch branch) and record that a manual edit inside an
already-compiled section **survives** … **if it does not survive, stop
and report**.
>
> `skip-changeset`: no package publishes anything from this change.
## Step 2 first — the survival gate, run before any edit
On a local scratch branch off `484484041a`
(`scratch/issue-18076-survival-gate`), discarded afterward:
| reading | value |
|:--|:--|
| marker inserted into the already-compiled `## 17.4.0` "Keys
deliberately left alone" paragraph | `SURVIVALGATEMARKER18076XQ7` |
| marker count before `changeset version` | **1** |
| dark control (`ZZQV18076NOPE`, invented at read time) before | **0** |
| `pnpm changeset version` | exit 0, "All files have been updated" |
| marker count **after** `changeset version` | **1** — the manual edit
**survives** |
| where the marker ended up | line 2869 → line 7316 — pushed down,
content intact |
| dark control after | **0** — unchanged, confirming the grep
methodology (not a broken instrument reading a false zero) |
| lit control — did the tool actually rewrite the files? | yes: a new
`## 17.5.0` section is prepended, `packages/spec/package.json` moves
`17.4.0` → `17.5.0`, and 452 of 453 pending `.changeset/*.md` files are
consumed |
| restore | `git checkout -f` back to the real branch; `diff <(git show
origin/main:packages/spec/CHANGELOG.md) packages/spec/CHANGELOG.md` →
**identical**; scratch branch deleted |
⇒ `changeset version` prepends a new section and never rewrites an
already-compiled one. Re-measured on this tree rather than inherited
from `ef47459474`'s reading, per the ruling's explicit instruction.
## What changed, and why each corrected claim is true of today's tree
`packages/spec/CHANGELOG.md`, inside the already-released `## 17.4.0`
entry (commit `e9fcd6b`, "Keys deliberately left alone"), said:
> `ServiceLevelObjective.errorBudget`'s burn-rate `window` and the
OpenTelemetry exporter `timeout` name no unit anywhere in their prose,
so both are outside the gate's population entirely. Pin tests assert
each of these, so a later sweep cannot read this card as "every
duration-shaped number on these files".
All three claims are false, verified on this tree independently of the
card:
- **Half 1** — `packages/spec/src/system/metrics.zod.ts:368-375`
(`SLO_BURN_RATE_WINDOW_RETIRED`):
`ServiceLevelObjective.errorBudget.burnRateWindows[].window` was renamed
to `durationSeconds` in `@objectstack/spec` 17 (#17783), tombstoned with
`retiredKey()` at `metrics.zod.ts:402`/`:498`. The pin that held the
bare spelling is now `metrics.test.ts:612`, `it('REFUSES the burn-rate
\`window\` with a rename naming \`durationSeconds\`', …)`.
- **Half 2** — `packages/spec/src/system/tracing.zod.ts:546-550`:
`OpenTelemetryCompatibility.exporter.timeout` was renamed to `timeoutMs`
(#17785), tombstoned with `retiredKey()`; its `batch.exportTimeout`
sibling moved to `exportTimeoutMs` the same way (`:586`/`:601`). The pin
is now `tracing.test.ts:594-611`, `it.each([['exporter.timeout',
'timeoutMs'], …])('REFUSES the retired \`%s\` with the rename in the
message', …)`.
The corrected paragraph quotes the falsified sentence, states the truth
with both PR numbers and both new key names, and closes with one erratum
line naming this PR and the correction date, matching `ef47459474`'s
shape.
**The paragraph's other four claims were checked and are still true**
(not touched, per the ruling's scope boundary):
- `FailoverConfig.dns.ttl` — still bare, `disaster-recovery.zod.ts:148`,
under the same `externalVocabulary` exemption comment.
- `CacheAvalanchePrevention.lockout.lockTimeoutMs` — still milliseconds,
`cache.zod.ts:162`.
- `MetricExportConfig.batch.size` — still a bare record count,
`metrics.zod.ts:702`.
- `QueueConfig.rateLimit.max` — still a bare task count,
`worker.zod.ts:~276`.
## The erratum line's PR number — how it went in, and the fix for a
review finding
`#18077` (the PR number for this correction) is not knowable before the
PR exists, so the first pushed commit (`bfc744c98c`) carried a
placeholder, `#PRPLACEHOLDER18076`, in the erratum line's parenthetical,
meaning to fill it in once the PR was open. **That fill-in commit
(`ac68eff364`) was made locally but not pushed before the round's first
status check ran against `bfc744c98c`, so a reviewer correctly caught a
shipped placeholder.** It is now pushed; **HEAD is `ac68eff364`**,
verified directly against the remote rather than assumed:
```
$ git show origin/claude/issue-18076-changelog-duration-keys-erratum:packages/spec/CHANGELOG.md | grep -c PRPLACEHOLDER
0
$ git show origin/claude/issue-18076-changelog-duration-keys-erratum:packages/spec/CHANGELOG.md | grep -n 'Corrected after publication, #18077'
7331: population as of `@objectstack/spec` 17. (Corrected after publication,
```
**Placeholder sweep of the whole diff, with controls** (`git diff
origin/main..HEAD -- packages/spec/CHANGELOG.md`, 35 lines):
- Pattern
`PLACEHOLDER|\bTODO\b|\bTBD\b|\bXXX\b|\bFIXME\b|<[A-Z_]+>|\{\{.*\}\}`
(case-insensitive) over the diff: **0 matches**.
- Lit control, drawn a different way: appended a synthetic
`PRPLACEHOLDER99999` line to the same scanned text and re-ran the
identical pattern — **1 match**, confirming the regex class actually
fires and the 0 above is a real zero, not a typo'd pattern reading a
false clean.
- Positive control: `18077` appears **exactly once** in the diff — the
one erratum reference, present and correctly substituted.
## Verification
`node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` derived **54** local gate families for this
diff (all matched via broad `packages/**` / `packages/spec` globs — this
path carries no gate of its own). Ran all 54 **twice** — once on
`bfc744c98c`, again on the final `ac68eff364` after the placeholder fix
landed — both times reconciled with `--ran` against the recorded exit
codes, same result both runs:
```
Run reconciliation — 54 derived, 50 run, 4 NOT-MEASURED, 0 UNRUN.
✓ dispatch-gates --ran: 54 derived famil(ies) accounted for — 50 run, 4 NOT-MEASURED (4 DERIVED from a recorded exit 3).
```
- **50/50 that ran, passed** (`pnpm check:nul-bytes`,
`check:release-notes`, `check:release-page-status`,
`check:release-section-coverage[--strict]`,
`check:changeset-gate-self-tests`, `check:doc-authoring`,
`check:page-declaration-shape`, `check:published-files`,
`check:slot-lookup`, `check:test-source-alias`,
`check:type-source-resolution`, and 39 more — full list in this branch's
derivation).
- **4 NOT-MEASURED, exit 3 (`PREREQUISITE NOT MET`), declared rather
than swallowed**: `check:dts-closure`, `check:dual-build-cjs-loads`,
`check:lean-entry-closure`, `check:sourcemap-no-sources-content` — each
refuses on a missing `dist/` in this fresh worktree ("Run `pnpm build`
first … this is NOT a pass: nothing was measured"). These are whole-repo
build-completeness gates unrelated to this diff's content (no code, no
export, no `dist` path moves); running a ~80-package `pnpm build` to
satisfy them is disproportionate to a one-line CHANGELOG correction, and
CI builds fresh before running them.
- No changeset added; `check:changeset-gate-self-tests` (the gate's own
self-test) is green. `skip-changeset` now shows as an applied label on
this PR (not applied by this session — labels were left untouched per
this card's operating constraints).
- `pnpm check:nul-bytes` and a direct `grep -naP
'[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]'` both clean on the diff.
- `node scripts/check-commit-card-trailers.mjs --range
origin/main..HEAD`: clean on both commits — no card-relation trailer,
model-free trailer pair.
No `packages/spec` test/typecheck run beyond the above: this diff
touches no code, no export and no public surface byte, so per this
repo's verification-scope convention there is nothing for `pnpm --filter
@objectstack/spec test`/`typecheck` to newly exercise.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_015c5G6TmpMKgnusmTpD7Ntt
---
_Generated by [Claude
Code](https://claude.ai/code/session_015c5G6TmpMKgnusmTpD7Ntt)_
---------
Co-authored-by: Claude <noreply@anthropic.com>
1 parent 4844840 commit fb29f62
1 file changed
Lines changed: 19 additions & 5 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2862 | 2862 | | |
2863 | 2863 | | |
2864 | 2864 | | |
2865 | | - | |
2866 | | - | |
2867 | | - | |
2868 | | - | |
2869 | | - | |
| 2865 | + | |
| 2866 | + | |
| 2867 | + | |
| 2868 | + | |
| 2869 | + | |
| 2870 | + | |
| 2871 | + | |
| 2872 | + | |
| 2873 | + | |
| 2874 | + | |
| 2875 | + | |
| 2876 | + | |
| 2877 | + | |
| 2878 | + | |
| 2879 | + | |
| 2880 | + | |
| 2881 | + | |
| 2882 | + | |
| 2883 | + | |
2870 | 2884 | | |
2871 | 2885 | | |
2872 | 2886 | | |
| |||
0 commit comments