Repository navigation
Commit 288611e
fix(spec): os migrate meta guidance for the rest-*, analytics-*, view-*, package-*, object-*, sharing-*, audit-*, flow-* and http-* migration entries states each lesson in words, not tracker numbers (stage 6) (#20536)
Part of #20233
Stage 6: the rest-, analytics-, view-, package-, object-, sharing-,
audit-, flow- and http- families.
Clause-②: no
**Stage 6 of a staged card.** The card stays open for later stages; this
PR carries no closing keyword. Text only: no entry id, `from` / `to`,
conversion or matching logic moves, and the chain rewrites exactly what
it rewrote before. One `surface` moves, under ruling A of the stage-1
ACCEPT (`5858839916`): it carried two tracker numbers.
## What this does
`os migrate meta` prints every ADR-0087 semantic entry it crosses as one
block: `⚠ [protocol N] SURFACE → REPLACEMENT`, then `why:` (the entry's
`reason`) and `verify:` (its `acceptanceCriteria`). AGENTS.md's
runtime-string rule applies to all of it: 「Runtime strings — refusal
prose, prescriptions, anything an author is shown — carry no tracker
number (`pnpm check:doc-authoring`): the lesson goes into the text.」
Form **D** of ruling C+D on card `19123` (`5749154545`) sets the shape:
the lesson in words, and no number, dead or alive; a cross-repo number
is still a tracker number.
This stage covers the nine families `rest-`, `analytics-`, `view-`,
`package-`, `object-`, `sharing-`, `audit-`, `flow-` and `http-`: **122
sites → 0** in the three prose fields and **2 → 0** in `surface`, across
33 entry files. It also takes the two carry-overs the stage-5 record
(`5880299859`) named:
- `18.api-error-retry-after-unit-in-key`: the clause on the ~16
runtime-emitted measurements and `ApiError.retryAfter` now dates the
ruling that decided it — "its 2026-09-05 population ruling" — instead of
reading under ruling B's 2026-09-02 date alone.
- `18.inline-grid-column-currency-scale-refused`: the two ruling-record
ids and the batch / item numbers are replaced by the rulings' dates and
options, the same rewrite stage 5 gave its `field-` sibling.
Each site now says what the cited ruling, measurement or fix decided.
ADR ids stay, and so does `Prime Directive #10` in
`18.package-manifest-version-grammar-enforced` (a rule in AGENTS.md, as
stages 2–5 kept `#10` / `#12`). `registry.ts`, `spec-changes.json` and
`docs/protocol-upgrade-guide.md` are regenerated from the entries
(`gen:migration-registry`, `gen:spec-changes`, `gen:upgrade-guide`),
never hand-edited. The pin now holds twenty-seven families.
## Census — tracker ids in the author-shown fields
**Instrument.** The stage-4 / stage-5 TypeScript-AST census, the same
script: for each entry object literal under
`packages/spec/src/migrations/entries/**` it evaluates `replacement`,
`reason`, `acceptanceCriteria` and (separately) `surface`, joining
string literals with `+`, and counts `#` followed by 4 or 5 digits at a
word boundary. On base `fb386074` it reads the whole tree at **461**
sites / 5 `surface` / 50 short, which is the stage-5 record's
after-count. Unevaluable fields: 0. 313 semantic entries.
**Controls, same run.**
- **Lit:** `17.aggregation-node-distinct-retired.ts` reads 7 sites
(replacement 1, reason 6), before and after.
- **Dark (comment lines):** 832 `//` / docblock lines in entry files
carry a tracker id, and none is counted; 832 before and after. Comment
lines are the sibling card's surface (the one that owns every comment
and docblock line), and this PR touches none (proved below).
**Base `fb386074`:** `rest-` 6 entries, **17** sites (0 / 17 / 0);
`view-` 10, **15** (0 / 13 / 2); `analytics-` 6, **14** (2 / 12 / 0);
`audit-` 2, **14** (2 / 12 / 0); `sharing-` 2, **14** (1 / 13 / 0);
`http-` 2, **13** (0 / 13 / 0); `object-` 7, **13** (1 / 11 / 1);
`flow-` 6, **11** (0 / 11 / 0) plus **2** in `surface`; `package-` 6,
**11** (0 / 10 / 1). **122** sites (6 / 112 / 4) in 31 of the 47
entries; 91 distinct ids read (82 in this repository, 8 in objectui, 1
`hotcrm#`), plus five ruling-record comment ids. Short numbers in the
nine families: 9 (one kept, the Prime Directive).
**After this PR:** all nine families **0**, `surface` 0; the seventeen
earlier families still 0; whole tree **461 → 339**, `surface` **5 → 3**,
short **50 → 40** (the two `inline-` batch numbers included). The PM's
rough line count (about 133 sites, about 30 files) is a wider line
instrument; the AST reading is 122 in 31 files.
| entry | sites (replacement / reason / acceptanceCriteria) | surface |
short numbers | record ids |
|---|---|---|---|---|
| `17.analytics-query-request-envelope-retired` | 1 (0 / 1 / 0) | | | |
| `17.audit-log-action-enum-retired` | 4 (0 / 4 / 0) | | | |
| `17.audit-log-action-restore-retired` | 10 (2 / 8 / 0) | | | |
| `17.flow-retry-max-retries-required` | 1 (0 / 1 / 0) | | | |
| `17.http-request-errors-total-retired` | 7 (0 / 7 / 0) | | | |
| `17.http-server-runtime-vocabulary-retired` | 6 (0 / 6 / 0) | | | |
| `17.package-uninstall-explicit-all-tenants` | 3 (0 / 2 / 1) | | 1 | |
| `17.rest-server-openapi31-block-removed` | 2 (0 / 2 / 0) | | | |
| `17.sharing-execution-context-retired` | 11 (1 / 10 / 0) | | | |
| `17.sharing-rule-recipient-reconcile` | 3 (0 / 3 / 0) | | | |
| `17.view-filter-rule-value-shaped-by-operator` | 4 (0 / 3 / 1) | | | |
| `17.view-management-protocol-retired` | 3 (0 / 2 / 1) | | | |
| `18.analytics-authorable-unknown-keys-refused` | 3 (0 / 3 / 0) | | | |
| `18.analytics-date-range-array-two-bounds-required` | 7 (2 / 5 / 0) |
| 1 | |
| `18.analytics-time-dimension-date-range-vocabulary-closed` | 3 (0 / 3
/ 0) | | 1 | |
| `18.api-error-retry-after-unit-in-key` | 0 | | | |
| `18.flow-decision-branch-expression-absent-refused` | 1 (0 / 1 / 0) |
| | |
| `18.flow-decision-edge-branching-first-match` | 1 (0 / 1 / 0) | | | |
| `18.flow-edge-condition-evaluated-slot-source-required` | 4 (0 / 4 /
0) | 2 | | 1 |
| `18.flow-predicate-slot-blank-string-refused` | 4 (0 / 4 / 0) | | | 1
|
| `18.inline-grid-column-currency-scale-refused` | 0 | | 2 | 2 |
| `18.object-block-sort-item-array` | 3 (0 / 3 / 0) | | 1 | |
| `18.object-grid-data-view-data-converged` | 4 (0 / 3 / 1) | | | |
| `18.object-grid-default-filters-rule-array` | 2 (0 / 2 / 0) | | | |
| `18.object-index-unknown-keys-refused` | 4 (1 / 3 / 0) | | | |
| `18.package-api-contracts-unmounted-entries-retired` | 3 (0 / 3 / 0) |
| 1 | |
| `18.package-install-request-unknown-keys-refused` | 0 | | 1 | 1 |
| `18.package-rollback-response-retired` | 5 (0 / 5 / 0) | | | |
| `18.rest-api-endpoint-handler-status-retired` | 7 (0 / 7 / 0) | | 1 |
|
| `18.rest-api-plugin-durations-unit-in-key` | 3 (0 / 3 / 0) | | 1 | |
| `18.rest-server-config-dead-keys-retired` | 5 (0 / 5 / 0) | | | |
| `18.view-filter-rule-absent-value-refused` | 2 (0 / 2 / 0) | | | |
| `18.view-filter-rule-scalar-operator-array-refused` | 4 (0 / 4 / 0) |
| | |
| `18.view-overlay-options-bag-judged` | 0 | | | |
| `18.view-pagination-page-size-default-50` | 2 (0 / 2 / 0) | | | |
| **total, 35 entries** | **122 (6 / 112 / 4)** | **2** | **10 (0
kept)** | **5** |
The fourteen entries of these families that carried no number are
untouched: `analytics-cube-public-default-visible-enforced`,
`analytics-query-request-format-retired`,
`flow-node-config-required-keys-refused`,
`object-grid-default-sort-retired`, `object-kanban-quick-add-retired`,
`object-tenancy-organization-field-retired`,
`package-manifest-version-grammar-enforced` (its one short number is the
kept Prime Directive), `package-version-row-semver-2-0-0`,
`rest-api-config-dead-keys-retired`,
`rest-api-documentation-version-retired` (the new entry from the landed
`rest-` change: its prose was read and is clean),
`view-filter-rule-operator-input-canonical`,
`view-item-owner-hidden-retired`, `view-overlay-judged-by-viewkind-arm`,
`view-overlay-owner-hidden-retired`. Four of the 35 changed entries
carried no four- or five-digit id: `view-overlay-options-bag-judged` (a
provenance-only acknowledgement quote),
`package-install-request-unknown-keys-refused` (a batch number and a
ruling-record id) and the two carry-overs.
## Text only — proved by a base-vs-head AST comparison
For every entry file this PR changes, both versions (`fb386074` and the
head) are parsed and compared: every import declaration; every property
other than the three prose fields, by evaluated value (so `id`, `from` /
`to` and any matcher); every comment token in the file; and the code
skeleton, token by token with each run of joined string literals
collapsed to one. `surface` is allowed to differ only where the base
value carried a tracker id and the head value carries none. **35 files
compared, 0 with a non-prose change**; one note, the ruling-A `surface`
of `18.flow-edge-condition-evaluated-slot-source-required`. The
instrument is shown able to fail first: on an in-memory copy it reports
DETECTED for a mutated `id`, a mutated comment, a mutated `surface`
whose base carried no tracker id, a mutated code token and a mutated
import, and stays dark on a prose-only mutation. So none of the sibling
card's comment lines moved, and no entry's identity or matching moved.
`registry.ts`, compared the same way: comment tokens, imports and code
skeleton identical; all 1,572 non-prose properties identical by value
(container literals compared through their children); exactly the 35
changed ids differ; and all 313 head registry entries equal the head
entry files on `surface` / `replacement` / `reason` /
`acceptanceCriteria`.
## Every citation read, and what the text now says
Each cited id was read with a single-card REST read (body plus the
ruling, measurement or landing comments), resolved against the
repository its sentence names: 82 in this repository and 8 in
`objectstack-ai/objectui` (one bare id resolves there: the sort ruling's
consumer change `8758` is "objectui PR" in its sentence). The five
ruling-record comment ids were read by id. `hotcrm#1555` answers 403 to
this session and is rewritten from what `main` records. Ids are in code
spans so this body posts no cross-references. **8 of this repository's
ids answer 404** on the issues endpoint and again on the pulls endpoint
(`6206`, `6239`, `6511`, `6523`, `10004`, `14369`, `14691`, `17124`;
control `6209` answers 200); their sentences are rewritten from what
`main` records, listed in Acceptance notes.
**`rest-` (14 ids)**
| cited | what it decided (read) | how the text now carries it |
|---|---|---|
| `3197` | An audit: several event / subscription / connector webhook
enums are schema-only, declared with no runtime consumer. | "the
declared-but-unconsumed shape an earlier audit found in the connector
webhook and event enums one layer up" |
| `4579` | This retirement's own card (`openApi31` declared, never
enforced). | trailing id dropped; "(the `openApi31` precedent)" |
| `13823` | Maintainer, 2026-09-01: remove `handlerStatus` with a
tombstone; enforce excluded; the class direction recorded for two
sibling cards. | "maintainer ruling of 2026-09-01 on this key: remove it
with a tombstone; enforce excluded"; trailing id dropped |
| `5384` | `ApiEndpointSchema` was still an open object after `api`
became a registered metadata type; closed strictly. | "the same endpoint
vocabulary whose ApiEndpointSchema had already been closed strictly once
`api` became a registered metadata type" |
| `13808` (PR) | A factual sweep of the automation skill; one corrected
sentence taught `handlerStatus` as working machinery. | "this finding
came out of correcting that skill sentence, in a factual sweep of the
automation skill" |
| `3950` (PR) | The precedent that an exported value schema with no
consumer reads as a capability, so it leaves with its key. | "an
exported value schema with no consumer reads as a capability, so it
leaves with its key" |
| `13612`, `13613` | The unbound branded identifier schemas;
`EventNameSchema`'s binding schemas with no runtime consumer. | "two
sibling ADR-0049 findings (the unbound branded identifier schemas and
the event-name schema no runtime reads; not ruled by it)" |
| `14478`, `15677` | Maintainer ruling B on duration units (2026-09-02),
its population widened 2026-09-05; the `api/` stack of that ruling. |
the stage-3 wording, naming both dates; trailing ids dropped |
| `14369` | **404** — see Acceptance notes. | "The liveness census that
enrolled the four `RestServerConfig` sub-objects" |
| `11984` | `normalizeConfig` cast the four sub-objects instead of
parsing them; it parses them since. | "(which parses them, rather than
casting them, since an earlier fix)" |
| `14796` | A closed-set sweep of the cloud repository for the 15 dead
keys: zero hits. | "A closed-set sweep of the cloud repository at
9b6abe0f2fd5: zero hits" |
| `14691` | **404** — this retirement's own card. | trailing id dropped
|
**`analytics-` (10 ids)**
| cited | what it decided (read) | how the text now carries it |
|---|---|---|
| `3891` | The degraded analytics shim (the fallback serving
`/analytics/query` with no analytics service installed) dropped the
caller's identity and the contract's `where` filter at its door. | "the
retired degraded analytics shim (the fallback that answered
/analytics/query when no analytics service was installed, and dropped
the caller's identity and its `where` filter at the door)" |
| `4001` | The unknown-key strictness campaign: silent stripping of
undeclared keys ends as the default, schema family by schema family. |
"The unknown-key strictness campaign (the sweep that ended silent
stripping of undeclared keys as the default, one schema family at a
time), its data/ batch" |
| `3878` | One URL, two request bodies (the shim's envelope vs the bare
query); the envelope dialect was retired. | "strict since the degraded
shim's envelope dialect was retired (one URL, one request body)" |
| `10414` | `MetricSchema.filters` was authorable with zero consumers;
removed. | "removed later in this major, because nothing ever read it:
`metric-filters-removed`" |
| `17598` | Maintainer ruling A, 2026-09-12, re-affirmed 2026-09-13: the
array arm refuses anything but exactly two string bounds. | "Maintainer
ruling A of 2026-09-12, re-affirmed 2026-09-13, which tightened the
array arm to exactly two string bounds" |
| `16322` | The driver half of the closed preset vocabulary; its
migration table is the vocabulary entry's, unchanged (single day as the
same date twice). | "the shipped migration table for the closed preset
vocabulary"; "in a driver change of their own" |
| `17593` (PR) | All four analytics faces read the array arm through one
rule and refuse the rest with the ADR-0112 envelope. | "since the fix
that made them read the array arm one way"; "The fix that followed made
all four faces refuse it"; "Since that fix" |
| `17124` | **404** — see Acceptance notes. | "a measurement of one
authored document on each face found what that bought" |
| `16041` | Maintainer, 2026-09-06, option A (contract first): the
string arm closes to the declared preset vocabulary. | "Maintainer
ruling of 2026-09-06 on the analytics date-range string (option A —
contract first)" |
| `4614` | The preset list, once three copies (spec, objectui, docs),
became one source of truth. | "since the dashboard date filter's three
copies of the list were folded into it" |
**`view-` (10 ids)**
| cited | what it decided (read) | how the text now carries it |
|---|---|---|
| `5869`, `6209` (PR) | A scalar comparand on `in` / `not_in` answered
500; now a named 400 INVALID_FILTER. | "An earlier fix closed the
RUNTIME half"; the trailing `(5869)` in `acceptanceCriteria` dropped |
| `5685` | The ordering operators' comparand was widened to the strings
the platform itself produces (a schema stricter than the runtime was the
wrong side). | "an earlier fix already settled the opposite error (the
ordering operators' comparand widened to the strings the platform itself
produces)" |
| `5948` | The issue asking what `GET /ui/view/:object/:type` answers,
and its 2026-08-07 ruling, both read `GetViewResponseSchema`. | "The
issue asking what `GET /ui/view/:object/:type` answers AND its
2026-08-07 maintainer ruling"; "the shapes that ruling meant" |
| `6239` | **404** — this removal's own change (recorded in the client
and spec CHANGELOGs). | trailing id dropped |
| `19751`, `19514` | The absent-value and scalar-array findings (this
and its sibling entry's own cards). | leading ids dropped |
| `6227` | `ViewFilterRuleSchema.value` shaped by its operator (the
`view-filter-rule-value-shaped-by-operator` entry). | "since the value
was first shaped by its operator"; "from then until this change" |
| `objectui#9050` | Maintainer ruling C′, 2026-09-20: the protocol is
the only refusal set; render time never throws on a protocol-valid
document. | "the maintainer's ruling C-prime of 2026-09-20 on objectui's
render-time filter converter — the protocol is the only refusal set, so
a document it accepts never throws at render time"; the lesson quote
「the differences are the protocol's to close」 kept verbatim |
| `objectui#9853` | Maintainer, 2026-09-24: the display default page
size is 50, declared once in the protocol; objectui reads the spec
default and never hardcodes it. | "the maintainer's ruling of 2026-09-24
set the platform display page size to 50, declared once in the
protocol"; "(an earlier ruling on the grid's page size, which the
page-size ruling restated)" |
| (no id) `view-overlay-options-bag-judged` | Maintainer, 2026-09-24
(objectui's overlay-options card), option A: judge each `options.KIND`
at the door. | 「其他同意」 replaced by "the maintainer's ruling of
2026-09-24" |
**`package-` (8 ids and one ruling record)**
| cited | what it decided (read) | how the text now carries it |
|---|---|---|
| `7705`, `7780` | Uninstall left orphaned rows (repaired); measured
there: an org-less uninstall deleted every organization's rows. |
"measured at 5 of 5 deleted, including a foreign org's, while
uninstall's orphaned-row defect was being repaired"; "exactly as the
orphaned-row repair left it" |
| `#12` (short) | Not a tracker id: `rest-requireauth-default-flip`
lived in protocol 12. | "(protocol 12)", the spelling four sibling
entries use |
| `19116` | Maintainer, 2026-09-23, option A: retire the three
contract-map entries naming paths nothing mounts. | "Maintainer ruling
of 2026-09-23 (option A: retire the three contract-map entries that name
paths nothing mounts)" |
| `18604` | The measurement on one `HttpDispatcher` over a real
`SchemaRegistry`. | the measurement was already in the sentence; the id
is dropped |
| `18058` | `installPackage` rebound onto the serving `POST
/api/v1/packages`. | "rebound by an earlier fix onto the serving POST
/api/v1/packages" |
| `5856869656` (record) | Maintainer, 2026-09-27, option A: the wrapped
install form refuses an unknown top-level key by name. | "the
maintainer's ruling of 2026-09-27, option A: the wrapped form refuses an
unknown top-level key by name" |
| `12038` | Maintainer, 2026-08-27, sub-question 3A: retire the false
rollback declaration first, then author the true one. | "Maintainer
ruling of 2026-08-27 on the client SDK's unbound response contracts,
sub-question 3A: retire this false declaration first, then author the
true one"; "the ruling's own survey" |
| `11925` | Typed the SDK's un-annotated return values, keeping
compile-time guards against a wrong-contract substitution. | "the change
that typed the SDK's un-annotated return values left a compile-time
guard"; "that negative guard" |
| `3877` | Response bodies are never checked against the schemas that
declare them. | "the hazard of response bodies never checked against the
schemas that declare them, realised in the opposite direction" |
**`object-` (11 ids)**
| cited | what it decided (read) | how the text now carries it |
|---|---|---|
| `objectui#8221` | Maintainer, 2026-09-07, option B: the legacy string
`sort` clause retired, one spelling (the array); its fourth item routes
the `ComponentPropsMap` pull-back here. | "the maintainer's ruling of
2026-09-07 (option B) retired the legacy string `sort` clause"; "One
item of that ruling"; the item's quote kept verbatim |
| `8758` (objectui PR) | The consumer half: the string arm dropped from
`convertSortToQueryParams`. | "the objectui change that drops the string
arm from `convertSortToQueryParams`" |
| `7751` | Maintainer, 2026-08-12, direction A: the `object-*` block
family's props schemas enter `ComponentPropsMap`. | "a read-point record
from the change that brought the `object-*` blocks into
`ComponentPropsMap` (the maintainer's ruling of 2026-08-12)" |
| `objectui#6207` | Found by objectui's declared-arm parity gate: two
spec authorities disagreed on `data`'s kind. Ruled 2026-08-25, option A.
| "(contract-vs-contract, found by objectui's declared-arm parity
gate)"; "The maintainer's ruling of 2026-08-25 (option A)"; "closes the
objectui finding that the two authorities disagreed" |
| `objectui#5090` | The grid's registry declaration of `data` was
aligned to `ViewData`. | "the authority objectui aligned the grid's
registry declaration to" |
| `objectui#4648` | Its deprecated-alias carve-out: object-grid's
deprecated spellings (`staticData` among them) are not published as
authoring surface. | "the deprecated `staticData` shortcut that
objectui's deprecated-alias carve-out already refuses to publish as
authoring surface" |
| `19514`, `objectui#9050` | As in `view-`. | as in `view-` |
| `objectui#4772` | The console's index fallback editor converged onto
`IndexSchema`, dropping `where`. | "removed when objectui converged that
editor onto `IndexSchema`"; "objectui then converged that editor" |
| `4001` | As in `analytics-`. | "The unknown-key strictness campaign
held this site open" (its internal batch and site numbers dropped) |
| `5114` | The console's filter save answered 422: a strict schema
refused a key the console itself writes. | "a measured risk, the kind
that had already made a console save answer 422 (a strict schema
refusing a key the console itself writes)" |
**`sharing-` (11 ids)**
| cited | what it decided (read) | how the text now carries it |
|---|---|---|
| `6206` | **404** — see Acceptance notes. | "completing the
maintainer's ruling of 2026-08-07 on the share-link context (enforcement
adjudicates on the WHOLE envelope, never a per-site subset)" |
| `6430`, `6511` | The share-link enforcement path moved onto the full
context under that ruling (`6511` answers 404). | "the share-link twin,
which that same ruling moved onto the whole context" |
| `6523`, `7068` (PR) | The sharing, approval and report contracts
converged onto the full envelope (`6523` answers 404). | "the envelope
the sharing, approval and report contracts have declared since they
converged onto it"; "One change converged the contracts" |
| `7140` (PR), `7206` (PR), `7070` | The four implementations
re-annotated (sharing and audit, then approvals and reports); the split
that deferred the type's deletion. | "two more re-annotated the four
implementations (sharing and audit, then approvals and reports)"; "the
deletion that split had deferred" |
| `7218` | This retirement's own card. | trailing ids dropped |
| `1878` | The metadata property liveness audit: security properties
parsed but never enforced. | "The change came out of the metadata
property liveness audit, which found security properties parsed but
never enforced" |
| `6350` | The stock reconciliation of the v17 train's breaking
changesets, which backfilled this entry. | "registered late, by the
stock reconciliation that compared the breaking changesets already on
the v17 release train against this ledger" |
**`audit-` (8 ids)**
| cited | what it decided (read) | how the text now carries it |
|---|---|---|
| `7675` | Maintainer, 2026-08-12: two halves — build the cheap writers,
retire the enum values with no feature; principle recorded 「空 widget +
永远查不到东西的过滤器是可见产品缺陷;审计面宁窄勿谎」 (kept verbatim, it is the lesson). |
"Maintainer ruling 2026-08-12 on the audit log's writerless actions";
"that ruling's own survey" |
| `8144`, `8145` | The `login` / `logout` writers on the auth session
hooks; `config_change` from the settings service. | "(`login` / `logout`
on the auth session hooks, `config_change` from the settings service)" |
| `8147`, `8315` | The two retirements' own cards. | trailing ids
dropped; "(triage 2026-08-13)" kept |
| `1883`, `3146` | The undelete / purge permission lifecycle and the
soft-delete recycle bin: both open, held, not declined. | "(an undelete
/ purge permission lifecycle and a soft-delete recycle bin, neither
built yet)"; "both held open, not declined" |
| `8011` | A credential-storage audit had to re-measure two "hashed at
rest" comments; resolved by making the declaration cite its mechanism. |
"(the shape a credential-storage audit had to settle by re-measuring two
"hashed at rest" comments)" |
**`flow-` (11 ids and two ruling records)**
| cited | what it decided (read) | how the text now carries it |
|---|---|---|
| `4247` | `maxRetries` had two defaults (schema 0, engine 3). | the
measurement was already in the sentence; the id is dropped |
| `19961` | This refusal's own card. | leading id dropped |
| `hotcrm#1555` | **403** — see Acceptance notes. | "a CRM application's
lead-conversion flow rendered a refusal screen AND ran the conversion in
one execution" |
| `17322`, `17495` (in `surface`) | The node slot rebound to the edge
door's rule at `registerFlow`, then at `objectstack validate`. | "The
node slot joined this entry with the two later changes that rebound
AutomationEngine.registerFlow and objectstack validate to the edge
door's own rule" |
| `15807`, `15430`, `15662` | The evaluated-slot rule: an `ast`-only
envelope no engine can evaluate refused; a non-string node predicate
refused at registration rather than answered a silent `false`; carried
to the edge. | "The evaluated-slot rule, carried to the edge condition —
the line that first refused an `ast`-only envelope no engine can
evaluate, and refused a non-string node predicate at registration
instead of letting the evaluator answer it a silent `false`" |
| `5550509137` (record) | 2026-09-05: an `ast`-only envelope driven
through `AutomationEngine.evaluateCondition` answers `false`. |
"(measured on 2026-09-05 by driving an `ast`-only envelope through
`AutomationEngine.evaluateCondition` directly)" |
| `17493`, `5651023407` (record) | Maintainer ruling A, 2026-09-13: the
two sibling predicate slots refuse a blank string at authoring. |
"Maintainer ruling A of 2026-09-13: the two sibling predicate slots
refuse a blank string at authoring" |
| `15572` | Its pin had held the blank admission correct because parser
and evaluator agreed. | "An earlier fix had pinned that admission as
correct" |
| `17322`, `15811` | The structural `config.condition` and every
evaluated `source` refuse a blank. | "after the structural
`config.condition` and a blank evaluated `source`" |
**`http-` (11 ids)**
| cited | what it decided (read) | how the text now carries it |
|---|---|---|
| `9650`, `9835`, `9834`, `10004` | The request counter, then the
latency histogram, moved to the transport through the response-observing
hook (`10004` answers 404). | "(the request counter, then the latency
histogram, both through the response-observing hook the transport was
given)" |
| `5122`, `3977` | The origin cards of the two named sibling entries. |
named by those entries' ids, which the sentence already carried |
| `9834`, `5295` | This retirement's own cards. | trailing ids dropped |
| `4938` | The CONFIG half of `system/http-server.zod.ts` removed. |
"The first removed the CONFIG half"; "the config half's removal in this
very file" |
| `4834`, `4988`, `5055` | The dynamic plugin-loading family, the `ui/`
interaction configs, the widget / i18n shapes — each removed by route 3.
| "the earlier removals of the dynamic plugin-loading family, the `ui/`
interaction configs and the widget / i18n shapes" |
**Beyond the four- and five-digit regex.** Nine decision-batch numbers
(`#27`, `#43`, `#57`, `#77`, `#117`, `#215`, `#217`, `#218`, `#227`),
their item numbers, the campaign's internal batch and site numbers,
`batch adjudication batch 4`, 「五问一批」 and "C′ item 1" were dropped; each
sentence now carries the ruling's date and content. The provenance-only
acknowledgements 「同意」 (×2), 「其他同意」 (×2), 「217 同意」, 「其他接受」 and 「9853
默认页大小改为50」 (the ruling's content, 50, is stated in words; the quote
itself carried a tracker number) were replaced by the ruling's date and
content. The lesson-bearing quotes are kept verbatim: 「the differences
are the protocol's to close」 (×2), the sort ruling's fourth item, 「every
other operator takes a scalar」, 「lowers to a deep-equality comparand」,
「`persistViewPatch` 只存 patch,不存 merged base」 and the audit ruling's
原则记录.
## Pin — widened, not weakened
`packages/cli/test/migrate-meta-engine-guidance.test.ts`:
`COVERED_PREFIXES` 17 → **27** (`rest-`, `analytics-`, `view-`,
`package-`, `object-`, `sharing-`, `audit-`, `flow-`, `http-`, and
`inline-` for the carry-over entry, the `inline-` family's only entry,
now tracker-free); `package-` selects no `packages-` entry. `REWRITTEN`
113 → **147**: the 34 ids this stage rewrote for the first time (the 33
nine-family entries plus `inline-grid-column-currency-scale-refused`;
`api-error-retry-after-unit-in-key` was already listed). The header
comment names the new families; the three `it` blocks and every `expect`
are textually unchanged.
**Ablation, from committed HEAD `472ee29b82`, one lock turn**
(`scripts/ablation-replace.mjs` wrap mode, a restore trap by absolute
path with a blob check, `scripts/ablation-dist-preflight.mjs`):
`registry.ts`, `http-server-runtime-vocabulary-retired`'s `reason`,
anchor `behind it, vocabulary second. ADR-0049.` → `behind it,
vocabulary second. ADR-0049, #5295.` (anchor 1 → 0, replacement 0 → 1,
blob `06c06741` → `702e7370`). Mutate leg: spec build exit 0; the marker
in 4 `dist` files; the pin **RED**, 1 failed | 2 passed:
`http-server-runtime-vocabulary-retired: the printed guidance cites a
tracker id: expected '#5295' to be undefined`. Restore proven by the
tool (blob == HEAD `06c06741`, `git diff HEAD` empty). Restore leg: spec
build exit 0; the marker absent from all 224 `dist` files with the tree
clean; the pin **GREEN**, 3 passed; whole tree 0 dirty paths.
No other test pins a removed number: on `main`, the tests naming any of
the 35 entry ids (`sys-audit-log-retired-actions`,
`plugin-rest-api.handler-status-retirement`,
`rest-api-config-dead-keys-retirement`,
`inline-grid-column-currency-scale-refused`,
`component-object-grid-default-filters.pin`,
`view-overlay-owner-hidden-retirement`, and two that name them in
passing) assert ids, surfaces and prescriptions this PR does not move,
not the prose it rewrites.
## Generated artifacts
- `registry.ts`: 313 semantic, 232 retired-key, 206 retired-def; exactly
the 35 ids differ (see the AST comparison above).
- `spec-changes.json` and `docs/protocol-upgrade-guide.md`: only the
protocol-17 entries appear in them, as the generators project; every
changed line is a fragment of a changed entry's field.
-
`.changeset/20233-rest-analytics-view-package-object-sharing-audit-flow-http-migration-guidance-tracker-free.md`:
`'@objectstack/spec': patch`, `Clause-②: no`.
## Verification (head `472ee29b82`)
Every heavy run through `scripts/pm/os-verify-lock.sh`, each exit code
written to disk before it was read.
- **Build:** `turbo run build --concurrency=2
--filter='@objectstack/cli^...'` → Tasks: 58 successful, 58 total
(VERDICT command-exit 0); plus the 10 packages outside that closure for
the dual-build gate → Tasks: 68 successful, 68 total.
- **Pin + neighbour:** `pnpm --filter @objectstack/cli exec vitest run
--project integration --maxWorkers=2
test/migrate-meta-engine-guidance.test.ts
test/migrate-meta-default-range.test.ts` → Test Files 2 passed (2),
Tests 10 passed | 1 skipped (the default-range file's own `skipIf`).
- **CLI unit (the tests that read the registry or
`spec-changes.json`):** `spec-release-changes`, `meta.stored-flags`,
`doctor-deprecation-hint-commands`, `vitest-tiers-partition` → Test
Files 4 passed (4), Tests 48 passed (48).
- **Spec:** `--project local` → Test Files 573 passed (573), Tests 16835
passed | 1 todo; `--project repo` → Test Files 39 passed (39), Tests 701
passed (701); `src/migrations/migrations.test.ts` alone → Tests 150
passed (150).
- **Typecheck:** `pnpm --filter @objectstack/spec typecheck` exit 0
(test layer 53 files / 251 errors held); `pnpm --filter @objectstack/cli
typecheck` exit 0 (3 files / 28 errors held).
- **Gates:** `node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` derives 89 families over this diff; all 89
run, all exit 0; `--ran` → "89 derived, 89 run, 0 NOT-MEASURED, 0
UNRUN". Among them: `check:doc-authoring` ("16759 customer-facing
string(s) across 1172 spec sources clean"), `check:generated` ("All 15
generated artifacts are up to date"), `check:migration-registry`
("registry.ts is current (313 semantic, 232 retired-key, 206
retired-def)"), `check:spec-changes`, `check:upgrade-guide`,
`check:issue-citations` ("no issue citations added"),
`check:org-identifier`, `check:nul-bytes`, `check:api-surface`,
`check:authorable-surface`, `check:dual-build-cjs-loads` (104 require
entry points across 66 packages load), `check:type-check-debt`,
`check:adr-0087-registration`, `check:changeset-no-major`,
`check:empty-changeset`.
- **Lint, a proven narrowing:** `eslint --no-inline-config --format
json` over the 37 changed `.ts` files → 37 files, 0 errors, 0 warnings,
no file-ignored notice. Population read from `eslint.config.mjs`
(`**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}` minus `NEVER_LINTED`);
invariance: the config enables no type-aware linting (no
`parserOptions.project`, no typed rules), so this diff cannot move any
untouched file's verdict. The full `pnpm lint` is CI's.
- **Mergeability:** `origin/main` is `1378ec7c`, three commits past the
base, none touching the migration ledger or its projections; a
driver-free bare-clone `merge-tree --write-tree` of the head against it
exits 0 with no conflicted path. `registry.ts` is shared with open PRs
`20504`, `20460` and `20458`, ordinary concurrency; no open PR touches
any of the 35 entry files or the pin.
## Acceptance notes
**404 and 403 ids, rewritten from what `main` records.**
- `6206` (the share-link ruling of 2026-08-07):
`packages/core/src/security/assemble-execution-context.ts` (the
share-link copies omitted `accessible_org_ids`; both surfaces converted
to pass the whole envelope) and
`packages/plugins/plugin-approvals/CHANGELOG.md` ("applying the ...
ruling — enforcement adjudicates on the whole envelope, never a per-site
subset").
- `6523` / `6511`: the same CHANGELOG ("converged 36 contract signatures
onto the complete `resolveAuthzContext` envelope"); `6430` (200) names
the share-link half.
- `6239`: `packages/client/CHANGELOG.md` records it as this removal
itself (retire `ViewProtocol`'s five viewId-addressed methods); dropped.
- `8758` as a bare id: its sentence names objectui, and `objectui#8758`
answers 200 (the string `sort` clause retired).
- `10004`: `packages/observability/src/semconv.ts` and the observability
CHANGELOG pair it with `9834` as the histogram's move to the transport
seam.
- `14369`: `docs/qa/platform-checklist/areas/api-backend.json` ("the
liveness census that found the block read by nothing") and the `14640`
changeset (it enrolled four of the five sub-objects). `14691`: the same
file records it as this retirement; dropped.
- `17124`: `.changeset/17124-daterange-array-arm-arity.md` records the
measurement (one authored document, four faces, three readings).
- `hotcrm#1555` (403 cross-repo):
`.changeset/15429-decision-edge-branching-first-match.md` records the
case and the node (`lead_conversion.decision_duplicate`).
**Observations, not filed.**
- Carrier: this card's later stages · 339 prose-field sites, 40 short
numbers and 3 `surface` sites remain in the other families (the largest:
`actor-` 13, `hot-` 12, `external-` 11, `query-` 11, `delete-` 10,
`stack-` 10); `stack-` and `turso-` have entries in open PRs. The pin
file keeps its stage-1 name while holding twenty-seven families.
- Carrier: the sibling card for comment and docblock lines · 832 comment
lines in entry files still cite tracker ids (unchanged), including the
header comments of `18.view-pagination-page-size-default-50.ts`,
`18.view-overlay-options-bag-judged.ts`,
`18.flow-decision-edge-branching-first-match.ts` (`hotcrm#1555`) and
`18.analytics-authorable-unknown-keys-refused.ts`.
Implemented-by: `claude/issue-20233-migrate-meta-tracker-free-stage-6` ·
`domain:spec` seat 4 dispatch, session
`session_01ARcDurZ5j34RdqsGgc4jgH`.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01ARcDurZ5j34RdqsGgc4jgH)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 05077d4 commit 288611e
40 files changed
Lines changed: 498 additions & 310 deletions
File tree
- .changeset
- docs
- packages
- cli/test
- spec
- src/migrations
- entries/semantic
Lines changed: 36 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
8 | | - | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
9 | 11 | | |
10 | 12 | | |
11 | 13 | | |
| |||
78 | 80 | | |
79 | 81 | | |
80 | 82 | | |
| 83 | + | |
| 84 | + | |
81 | 85 | | |
82 | 86 | | |
83 | 87 | | |
| |||
91 | 95 | | |
92 | 96 | | |
93 | 97 | | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
94 | 102 | | |
95 | 103 | | |
96 | 104 | | |
97 | 105 | | |
| 106 | + | |
| 107 | + | |
98 | 108 | | |
99 | 109 | | |
100 | 110 | | |
| |||
148 | 158 | | |
149 | 159 | | |
150 | 160 | | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
151 | 166 | | |
152 | 167 | | |
153 | 168 | | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
154 | 172 | | |
155 | 173 | | |
156 | 174 | | |
| |||
165 | 183 | | |
166 | 184 | | |
167 | 185 | | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
168 | 194 | | |
169 | 195 | | |
170 | 196 | | |
| |||
175 | 201 | | |
176 | 202 | | |
177 | 203 | | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
178 | 210 | | |
179 | 211 | | |
180 | 212 | | |
| |||
199 | 231 | | |
200 | 232 | | |
201 | 233 | | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
202 | 240 | | |
203 | 241 | | |
204 | 242 | | |
| |||
0 commit comments