Repository navigation
Fifth Rule 3 population (function declarations) widened, censused ids stripped, and the gate states its own scan boundary; hot-reload refusal ids stripped - #13298
Conversation
…le 3's sink pass, and the gate states its own scan boundary The fifth widening (#13156's A half, adjudicated 2026-08-29): a plain `function` DECLARATION is transparent to the climb exactly when its NAME is consumed from a recognised customer-facing position — the same narrow clause as the fourth population, one declaration form over, never an unconditional crawl of function bodies. Its literals get their own `functionDeclared` bucket with its own blindness floor, so the declaration clause rotting cannot hide behind the arrow members. The C half (shared with the family member card): the gate's output now prints Rule 3's scan boundary — the root, the not-scanned siblings with the deferral pointer, and the recognised sink-shape list — derived from the constants the scan reads, pinned derived-vs-derived in --self-test. At this commit the widened gate is deliberately RED on the real tree (reproduce-first): 4 violations — 2 functionDeclared, 2 message via the new closure into declarations. The strip is the next commit. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KX8wnyjStaZcuMyAMNsy3N
… refusal prose, re-pin the twins The strip half of the fifth-population adjudication (2026-08-29, Class-1), under the keep-the-ADR-id charter: 17 ids across 8 spec sources — the 15 the broad declaration census finds on current origin/main (materially fewer than the relayed 47/51/14, measured before today's main moved) plus the 2 hoisted ruling consts the widened sink closure newly reaches (SUBMIT_REDIRECT_RULING, FORM_VIEW_FEATURES_RULING). ADR ids, protocol versions, error codes and ruling dates stay; ids that were the whole parenthetical take the parenthetical with them; load-bearing internal references move to adjacent comments. Twins re-pinned red-then-green, never weakened: 42 assertions across 7 spec test files red before this commit, 607/607 green after, each re-pin a customer-resolvable anchor from the NEW text plus negative id pins at the two ruling-const doors. The objectql and service-analytics twins flagged by the id sweep pin sources OUTSIDE the scanned root and are deliberately untouched (evidence for the cross-package revival census). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KX8wnyjStaZcuMyAMNsy3N
…fusal messages, re-pin the twins The member half of the 2026-08-29 family adjudication: the ruled strip is the plugin-registration refusal's tracker id (the id the #13151-verified twins at hot-reload.test.ts:259,302,310 pin); the sibling id in the same refusal table's watchPatterns entry and in the startWatching() removal notice is stripped in the same stroke under the bounded same-class extension — same defect family, same keep-the-ADR-id remedy, same file, same twin suite, declared in the PR body. ADR-0049, the spec/core versions and the scheduleReload migration call stay as the customer-resolvable anchors. Twins red-then-green, never weakened: 8 assertions red before this commit (10/18 passing), 18/18 after; each id pin re-pinned to a content anchor from the NEW text plus negative id pins at all three doors — mirroring the negative pin the spec-side parse door has carried since its own strip. Repo-wide section-7 sweep for the stripped id set: the only other test literal is an expect failure-label, not a content pin. Root extension of the doc-authoring gate's Rule 3 is deliberately NOT part of this change (deferred by the adjudication; the gate's new boundary output is what keeps that deferral visible). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KX8wnyjStaZcuMyAMNsy3N
…p's callee filter missed Found by RUNNING the full mention set rather than trusting the sweep's expect-callee filter: both pins spell the id check inside a .some() predicate, so the nearest enclosing call is w.includes, not expect. Same re-pin discipline — anchored on the warning's own prescription words (COMPOSE_KEY_DISPOSITIONS / 'cannot be composed'), red-then-green (2 red in the consumer batch, 35/35 green after), never weakened. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KX8wnyjStaZcuMyAMNsy3N
📓 Docs Drift CheckThis PR changes 2 package(s): ⛔ 1 release-owned page(s) name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 132 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin fba5b6576265dfa3f8be5d7977d274929aaa9803 && git checkout fba5b6576265dfa3f8be5d7977d274929aaa9803
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 74049254d47bd0edd2a2fcd732dcc01c91504f10 afb72654e8e8a76fba283d60fd1c4e1700eb3cfa && git checkout -B drift-repro 74049254d47bd0edd2a2fcd732dcc01c91504f10 && git merge --no-ff afb72654e8e8a76fba283d60fd1c4e1700eb3cfa
node scripts/docs-audit/affected-docs.mjs --json 74049254d47bd0edd2a2fcd732dcc01c91504f10
|
…e names, ruling dates and foreign example ids (objectstack-ai#22125) Part of objectstack-ai#22093 Clause-②: no Wording only: no schema, key, type, export or error-code change. Patch changeset for `@objectstack/spec`, `@objectstack/service-automation` and `@objectstack/platform-objects`. objectui#11785 is the Studio half (splitting an author message from the detail); this PR changes the server-side strings only. The card keeps two named remainders, listed under "Remainder of the card and its route" below. ## What changed Form help and refusals that an author reads no longer carry service-interface names (`IXxxService.method()`), ruling dates ("maintainer ruling DATE", "ruled DATE") or another product's example ids. The rationale they carried moves into the code comment beside each string. Each describe and refusal still states the rule, why it exists and the repair. ## How "author-facing" was measured (instrument and radius) Studio reaches these strings through five routes. I measured each one at `a543e244f`: | Route | What Studio renders | Instrument | | :--- | :--- | :--- | | R1 | `/meta/types` `schema`: every `DEFAULT_METADATA_TYPE_REGISTRY` type, derived as `metadata-protocol` derives it (`z.toJSONSchema`, `unrepresentable: 'any'`, with the `io: 'input'` retry) | Every `description` in all 27 type schemas | | R2 | `/meta/types` `form`: all 17 `METADATA_FORM_REGISTRY` layouts | Every `description` / `helpText` / `label` / `placeholder` / `hint` | | R3 | The package dialog, which derives its form from `ManifestSchema` client-side (objectui `package-schema.ts`) | Every `description` | | R4 | The flow inspector, which reads node `configSchema` from `GET /api/v1/automation/actions` | An AST string scan of every file that declares a `configSchema` (13 files) | | R5 | Refusals read at a door | An AST scan of every string literal in `packages/spec/src` (1284 files, 80190 string parts, comments excluded) | The class patterns were: interface `\bI[A-Z]\w*(Service\|Driver\|Engine\|…)\b`; ruling `\bruling\b\|\bruled\b\|\b20\d\d-\d\d-\d\d\b`; foreign `steedos\|superset\|salesforce\|apache\|airtable\|…`. **Positive control: both strings the filer measured are found.** - The notify Template help is found by R4 at `service-automation/src/builtin/notify-node.ts:203`, as both an interface hit and a ruling hit. The spec copy is found by R5 at `io-node-config.zod.ts:250`. - `com.steedos.crm` is found by R5 at `manifest.zod.ts:283`. R1 to R3 found neither string (needle count 0). So the Studio-rendered Template help is produced by the service-automation descriptor, not by the spec describe. That is why the producer side is changed too. **After the change**, R1 to R3 hold no interface, ruling or foreign-id hit. The one exception is the "Airtable parity" wording (see Acceptance notes). The needles `II18nService`, `IEmailService`, `com.steedos.crm` and `maintainer ruling` count 0. The R5 hit count drops by 22. ## Every string changed Lines are at `a543e244f`. Before is the internal reference that was removed; After is what replaced it. No changed string carried a tracker number, so no tracker number moved. | # | Where | Reach | Before | After | Rationale now lives in | | :-- | :--- | :--- | :--- | :--- | :--- | | 1 | `services/service-automation/src/builtin/notify-node.ts:203`, notify `configSchema.properties.template.description` | R4: Studio notify Template help (filer-measured) | "else the deployment default (II18nService.getDefaultLocale()) … (maintainer ruling 2026-09-01). A producer-set payload.locale is not consulted." | "else the deployment default locale … The node's payload.locale is not consulted." | Comment above `template:` in the descriptor | | 2 | `spec/src/automation/io-node-config.zod.ts:250`, `NotifyConfigSchema.template` describe | Reference docs and published JSON Schema; the contract row 1 mirrors | Same as row 1, with backticks | Same as row 1 | TSDoc above `template` (it already named both; one sentence added) | | 3 | `spec/src/kernel/manifest.zod.ts:283`, `MANIFEST_ID_EXAMPLES` | R5: every package-id refusal (filer-measured on `POST /api/v1/packages`) | `'com.steedos.crm', 'org.apache.superset'` | `'com.acme.crm', 'org.example.help-desk'` | Doc comment on the constant | | 4 | `manifest.zod.ts:305`, `manifestIdRefusal` | R5: same doors | "Invalid package id 'VALUE' on `manifest.id`. Expected reverse-domain notation ('com.steedos.crm', 'org.apache.superset') — …" | "Invalid package id 'VALUE'. A package id (`manifest.id`) is written in reverse-domain notation, like 'com.acme.crm' or 'org.example.help-desk' — …", with the rule and suggestion arm unchanged | TSDoc on `manifestIdRefusal` | | 5 | `manifest.zod.ts:360-361`, `@example` on `id` | TSDoc; held equal to row 3 | `com.steedos.crm`, `org.apache.superset` | `com.acme.crm`, `org.example.help-desk` | (none) | | 6 | `spec/src/data/field.zod.ts:1142`, `required` describe | R1: object, field | "(maintainer ruling 2026-08-18)" | Removed | TSDoc above `required` | | 7 | `field.zod.ts:1170`, `multiple` describe | R1: object, field | "(maintainer ruling 2026-09-13), and on `radio` by the narrower 2026-08-22 ruling … (maintainer ruling 2026-08-18)" | "on any other type, `radio` included, is REFUSED at parse …" | TSDoc above `multiple` (new Declarability paragraph) | | 8 | `spec/src/ui/view.zod.ts:1175` / `:1221`, `GROUPING_FIELD_RULING` in the padded grouping-field refusal | R5: view save | "… (ruled 2026-09-10.)" | Removed, constant deleted | Comment where the constant was | | 9 | `view.zod.ts:3444`, form-view field `visibleWhen` describe | R1: view | "refused at parse (ruled 2026-08-27):" | "refused at parse:" | TSDoc above | | 10 | `view.zod.ts:3655`, section `collapsible` describe | R1: view | "(ruled 2026-09-18)" | Removed | The collapse-pair TSDoc (already records the ruling) | | 11 | `view.zod.ts:3663`, section `collapsed` describe | R1: view | "(ruled 2026-09-18; refusing the combination at the declaration, and warning on it, were both rejected — nobody can depend on a section that cannot be opened)" | ", so writing `collapsed: true` alone is a correct way to say \"collapsed by default\"" | The collapse-pair TSDoc (already records the rejected letters) | | 12 | `view.zod.ts:3715`, form-view section `visibleWhen` describe | R1: view | "(ruled 2026-08-27)" | Removed | TSDoc above | | 13 | `view.zod.ts:3959`, `SUBMIT_REDIRECT_RULING` in seven `submitBehavior.url` refusals (`:3988`, `:3993`, `:4003`, `:4010`, `:4018`, `:4029`, `:4039`) | R5: form-view save | "(ruled 2026-08-11)" | Removed, constant deleted | Comment where the constant was | | 14 | `view.zod.ts:4097` / `:4123`, `FORM_VIEW_FEATURES_RULING` in the `features.*` predicate refusal | R5: form-view save | "scope root (ruled 2026-08-27)." | "scope root." | Comment where the constant was | | 15 | `view.zod.ts:4444`, redirect-arm `url` describe | R1: view | "…successful submit. Ruled 2026-08-11: (1) …" | "…successful submit. (1) …" | The `checkSubmitRedirectUrl` comment | | 16 | `spec/src/ui/page.zod.ts:941` (`kind`) and `:990` (`source`) describes | R1: page | "(ADR-0065; ADR-0080 amendment 2026-06-30)" | "(ADR-0065; ADR-0080)" | TSDoc above `kind` (new) and `source` (already) | | 17 | `spec/src/system/email-template.form.ts:19`, Identity section help. Its three translated values in `platform-objects/src/apps/translations/{zh-CN,ja-JP,es-ES}.metadata-forms.generated.ts:2183` are hand-written, and `en` is regenerated by `pnpm i18n:extract` | R2: email_template form | "Template identifier resolved by IEmailService.sendTemplate({ template: name, locale, ... })." | "Senders address this template by its name; the locale selects which language version of it is sent." | Comment above `description:` | | 18 | `spec/src/data/filter.zod.ts:475`, null ordering comparand refusal | R5: filter validation | "Ruled 2026-09-01: a null ordering comparand is refused at the validation entrance." | Sentence removed | Builder TSDoc | | 19 | `filter.zod.ts:564`, `{ $field }` in a list position refusal | R5 | "Ruled 2026-08-11: declared = enforced (ADR-0049)." | Sentence removed | Comment inside the builder | | 20 | `filter.zod.ts:589`, null list member refusal | R5 | "Ruled 2026-08-31: a null list member is refused at the validation entrance." | Sentence removed | Builder TSDoc | | 21 | `filter.zod.ts:801`, blank `$between` bound refusal | R5 | "Ruled 2026-09-17: a blank $between bound is refused at the validation entrance." | Sentence removed | Builder TSDoc | | 22 | `spec/src/ui/action.zod.ts:985`, action `description` describe (added in patch round 1) | R1: action, in the authoring (`io: 'input'`) derivation; the action Description help objectui#11785 measured | "(one dialog, not two —)": the dash an earlier strip of the cited ruling left dangling | "(one dialog, not two)" | Docblock above `description` (already cites the ruling; one sentence added) | The regenerated `content/docs/references/**` files follow from rows 2, 6, 7, 9 to 12, 15, 16 and 22. ## Remainder of the card and its route This PR delivers the card minus two named rows. It is therefore `Part of objectstack-ai#22093`, and the card stays open for both. 1. **The governed `submitBehavior` row.** - What: `view.zod.ts:4478`, the top-level `submitBehavior` describe, keeps "(ruled 2026-08-11)". - Why it is not here: `gen:react-blocks` projects this describe into `skills/objectstack-ui/references/react-blocks.md`, which is a governed Tier H surface, so changing it here would make this whole sweep a Tier H landing. Measured: the regenerated skill file differs in exactly that one row. - Route: a separate Tier H draft PR carrying the one describe edit, the regenerated `react-blocks.md` row and its reference-docs row, landed on the maintainer's approval. - A comment beside the describe records the deferral. 2. **The `sys_email` field help naming `IEmailService.send`.** - What: `packages/platform-objects`, `en.objects.generated.ts:2500` and `:2508`. The source is in the `sys_email` object definitions. - Why it is not here: open PR objectstack-ai#22087 regenerates the same four `*.objects.generated.ts` bundles, so folding it here would put two PRs on those bundles at once. - Route: the same class of edit, made after that PR lands. ## Pins - **Refusal `code` is asserted with the sentence:** - `manifest.test.ts` asserts `invalid_format`. - `view-form-features-root.test.ts` asserts `custom`. - **Negative pins on what the author reads.** No interface name, ruling date or foreign id appears in: - `io-node-config.test.ts` - `notify-node.test.ts`, on the Studio-served descriptor text - `manifest.test.ts`. Its headline sentence carries no `manifest.id`, the key is still named as a locator, and there is no steedos/superset/apache. - `filter.test.ts` - `view-form-features-root.test.ts` - `view-submit-redirect-url.test.ts` - **Patch round 1: `action-description.test.ts`.** It derives `ActionSchema` the way `/meta/types` serves it (`io: 'input'`) and asserts three things about the `description` help: - it is present; - no dash is left dangling before a close paren; - it has no ruling date, service interface or tracker id. - **Pins that changed direction.** These earlier pins asserted that the date was present: - `view-submit-redirect-url.test.ts`, 7 assertions: "cites the ruling so the refusal is traceable" - `view-form-features-root.test.ts:68` - `filter.test.ts:644` - `io-node-config.test.ts:347` and its `2026-09-01` pin They are now negative pins. `filter.test.ts:661` used the date as its discriminator between two messages. It now discriminates on the blank-bound headline. - No whole-prose pin was added. ## Where the ruling dates in refusals come from (lineage) This PR reverses no ruling. - The 2026-08-29 adjudication carried out objectstack-ai#12522's charter (comment 5425845726): strip tracker ids, and keep ADR ids and migration commands. That charter does not mention ruling dates. - "ADR ids, protocol versions, error codes and ruling dates stay" is PR objectstack-ai#13298's own commit note (fd289be), not ruled text. The code comments that grew from it, saying the date is "what a refused author can act on", are rewritten here. - Triage 6041940817 on this card directs that "rationale (interface names, dates, tracker ids) moves into code comments". This PR follows that direction for describes and refusals alike, and the seat confirmed it in patch round 1. ADR ids stay. ## Tests and gates **Patch round 1, on the merged head `026204631`.** - **Merge:** origin/main was merged at `54ace18c6` with `bash scripts/pm/os-regen-merge.sh`. - Merge commit `75cec8cd1`, parents `34bf72933` and `54ace18c6`. There were no conflicts. - Step 2 kept the branch's bytes of the 7 reference-docs files main had not moved. - The regeneration ran only after the merge commit (never in MERGE state). It reproduced main's side byte for byte; the only regenerated delta is the action row, in 3 docs files. - Main's landed migration entries are still present on the merged head. Three were checked by name: `flow-edge-unresolved-or-repeated-refused`, `sys-presence-organization-column-retired` and `sys-job-organization-column-retired`. - The delta against main is exactly this branch's 30 paths. - **Builds and regeneration, all under the verify lock:** - `pnpm --filter @objectstack/spec build` passed. - `gen:schema` and `gen:docs` passed. - The `service-automation^...` closure build (spec excluded) passed. - **spec tests:** `pnpm --filter @objectstack/spec exec vitest run --maxWorkers=2` over 26 targeted files (round 0's 25 plus `action-description.test.ts`): **26 files, 2475 tests passed.** This is a declared narrowing; CI `Test Core` runs the full suite. - **service-automation:** `notify-node.test.ts`, **16 passed.** - **platform-objects:** `src/apps/translations/*.test.ts`, **24 files, 430 passed.** - **Typecheck:** `@objectstack/spec` `typecheck` passed. - **Generated artifacts:** `pnpm --filter @objectstack/spec check:generated` reports **all 15 generated artifacts up to date** (react-blocks and api-surface included). - **Reverse verification, patch round 1 (one-off):** - `action.zod.ts` went back to the `54ace18c6` bytes; landing confirmed by `grep -c` = 1. - **1 of 16 tests in `action-description.test.ts` went red:** "carries no residue of a stripped reference". - The file was restored from HEAD, hash-identical to its HEAD blob, and the suite was green again (16 of 16). - **Reverse verification, round 0 (at `34bf72933`):** - The 5 touched sources went back to the `a543e244f` bytes. - **39 of 347 spec tests went red across all 5 changed spec test files, and 1 of 16 in `notify-node.test.ts`.** Every red is a pin this PR added or flipped. - Restored byte-identical to HEAD. - **Lint:** `pnpm exec eslint --no-inline-config --format json` over the 20 changed lintable files at `026204631`: **20 files, 0 errors, 0 warnings.** - Population: `eslint.config.mjs` matches `**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}` minus `NEVER_LINTED`. - Invariance: the config never enables type-aware linting (no `parserOptions.project`, see its note near line 328), so this diff cannot move the verdict on any file it does not touch. - **Gates:** `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` at `026204631` derived 113 families (30 paths against merge base `54ace18c6`). - **109 run, all exit 0**, each exit code captured before any pipe. - **4 NOT MEASURED, recorded as reasoned claims and read from CI on the landing head:** `check:skill-examples`, `check:dual-build-cjs-loads`, `check:i18n` and `check:type-check-debt`. In round 0 each exited 3 (PREREQUISITE NOT MET). `check:type-check-debt`'s re-measure is a 45-task workspace build and is not run outside the verify lock. - `--ran` reconciliation: **113 accounted, 109 run, 4 NOT MEASURED (claimed), 0 unrun.** ## Acceptance notes - **Measured but not changed, as outside the three classes or outside reach:** - `stack.zod.ts:458-459` (`IJobService`, `IEmailService.sendTemplate`): `defineStack` collection describes. R1 to R3 do not serve them, and they are not refusals. - Strings whose reader is a plugin, driver or API developer, for whom the interface is the contract they implement or call. None is in R1 to R3: - `data-engine.zod.ts:165,190` (`IDataEngine.find()`) - `hook.zod.ts:1269` (`IScopedContext`) - `query.zod.ts:429` - the `driver.zod.ts:287-388` refusals (`IDataDriver`) - `automation-api.zod.ts:452` - `execution-context.zod.ts:441` ("the 2026-09-03 ruling"): `preserveAudit` is server-constructed and never authored. - `plugin-rest-api.zod.ts:138` ("ruling record, 2026-09-01"): a tombstone on `RestApiEndpointSchema`. Its own comment records that nothing parses that schema outside its unit tests, so no door reaches it. - `component.zod.ts:365` ("Since the console release of 2026-08-21 (`c86185eb5`)"): a release date and a commit sha, not a ruling. - Undated ruling words. These carry no date and no "maintainer ruling", so they fall outside the class as the seat scoped it: - `action.zod.ts:1139` and `:2157` - `page.zod.ts:93` - `view-grouping-query.ts:433` - `context.zod.ts:50` - `protocol.zod.ts:1681` - `endpoint-publish-gate.ts:368,416` - the `error-code-ledger.zod.ts` notes - "Airtable parity" wording is the only R1 to R3 hit left: `page.zod.ts:911`, `page.form.ts:113`, `view.form.ts:164`, plus `view.zod.ts:1706`, `page.zod.ts:647` and `component.zod.ts:1766`. It is a design note naming a competitor, not an example id. - Salesforce mentions in `export.zod.ts:292` and `object.zod.ts:1528` are comparisons, not ids. - `src/migrations/**`, about 1,240 dated or "ruling" hits: upgrade-guide records, not a form or a door. - `manifest.zod.ts:546`, TSDoc `@example` on `dependencies` (`@steedos/plugin-auth`): TSDoc only. `packages/core/src/artifact-packages.ts:114` cites that exact example, so changing it moves a comment in core. - The `sys_email` field help naming `IEmailService.send` is the second named remainder; see "Remainder of the card and its route". - **objectui:** it has no copy of any changed string at `9990f9e` (grep for `II18nService`, `IEmailService`, `steedos.crm`, `Invalid package id`). --- _Generated by [Claude Code](https://claude.ai/code/session_01RPo7FUd6bSnAfkWMAKi848)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
Fixes #13156
Fixes #13179
Family PR executing the twin Class-1 adjudications of 2026-08-29 (director seat, 13:50 + the operative 14:55 pair): A + C on the chain head, strip + C, root extension deferred on the member. One branch, per-member commits, independently verifiable halves. Session: https://claude.ai/code/session_01KX8wnyjStaZcuMyAMNsy3N
Chain head — the fifth population (commits
d7e22a3d,4dd3e5e3,afb72654)A — the widening. Plain
functionDECLARATIONS join Rule 3's sink pass inscripts/check-doc-authoring.mjs, under the exact #13002/#13151 narrow clause — a declaration is transparent only when the function itself sits in a recognised customer-facing position, which for a declaration means its NAME is consumed from one (seeded or closed over bycollectTextSinkConsts, the same fixed point the hoisted const-arrow spelling rides). Never an unconditional crawl: an unconsumed declaration and one consumed only by an unrecognised call stay unswept, pinned as precision negatives in--self-test.Bucket choice + rationale (required by the adjudication): the new population gets its own
functionDeclaredbucket with its own blindness floor, not a fold intofunctionBuilt. Reasoning is #13151's per-bucket-floor principle applied one step further: the floor exists to catch exactly one clause rotting back toundefined, and the arrow/expression members (217 recognised strings on the real tree) would hold a shared floor up indefinitely while the declaration clause rotted — the precise silence this population was found by. The pre-existing options-factory clause (buildsStrictObjectOptions) is form-agnostic, already reached function declarations before this PR, and keepsfunctionBuilt; only the name-consumption clause is new. On the real tree the new floor sits at 133 recognised strings.Reproduce-first, measured: widen first, then strip. At
d7e22a3dthe widened gate is RED on the real tree: 4 violations — 2functionDeclared(listPositionFieldReferenceMessageindata/filter.zod.ts:296,normalizedMemberMessageat:1434) and 2messagevia the new closure into declarations (SUBMIT_REDIRECT_RULING,FORM_VIEW_FEATURES_RULINGinui/view.zod.ts). After the strip commit the gate is GREEN with every bucket floored (message 1037 · strictObject 3349 · tombstone 771 · describe 8524 · functionBuilt 223 · functionDeclared 133).Self-test teeth proven by two-leg ablation (mutate, confirm on disk by anchored grep counts, run, restore, prove restoration by HEAD-blob hash match; no build leg exists on this path — the gate runs from source): neutralising the recogniser entry branch fails the declaration REDs and the floor cases while the closure-pin case stays green; neutralising the declaration registration fails all three. Restoration verified: worktree blob equals HEAD blob.
Census re-derivation — a finding, not a blocker. The relayed 47 literals / 51 ids / 14 files (measured on the #13002 branch at
c0d50d612) does NOT reproduce on currentorigin/main: the broad unconditional-crawl census reads 15 literals / 15 ids / 6 files (main moved in the interim —data/field.zod.tsnow contributes zero), and the adjudicated narrow instrument reds on 4 of those plus the 2 hoisted consts above. The strip covers the full broad-census population anyway — all 15 in-declaration ids plus the 2 const-borne ids, 17 total across 8 files — because every site is same-audience refusal/warn prose and the ruled remedy is by population, not by count. After the strip the broad census reads 0/0/0.Strip discipline (#12522 keep-the-ADR-id charter): ADR ids, protocol versions, error codes (
INVALID_FILTER / 400) and ruling dates stay; an id that was the whole parenthetical takes the parenthetical with it; genuinely internal load-bearing references moved to adjacent code comments (filter.zod.ts,view.zod.ts). No tombstone had the issue id as its only reference, so nothing needed escalation.Twins, red-then-green, never weakened: 42 assertions across 7 spec test files red against the stripped tree, 607/607 green after re-pinning — each re-pin a customer-resolvable anchor from the NEW text (ruling dates, ADR anchors, prescription sentences), plus negative id pins at the two ruling-const doors. Two predicate-style pins (
.some(w => w.includes(...))incompose-stacks-key-loss.test.ts) were caught by RUNNING the full mention set after the parse sweep's expect-callee filter missed them — re-pinned the same way (35/35 green). Theobjectqlandservice-analyticsassertions the id sweep flagged pin messages produced OUTSIDE the scanned root (objectql/src/registry.ts,service-analytics/src/comparand-shape.ts) and are deliberately untouched — they are evidence for the member card's revival census, below.C — the boundary output (lands once, serves both cards): the gate now prints its own Rule 3 scan boundary on every verdict — the root (
packages/spec/src), the explicit sibling-packages-not-scanned statement with the deferral pointer, and the recognised sink-shape list — derived from the same constants the scan reads, pinned derived-vs-derived in--self-test(root fromSPEC_SOURCE_ROOT, buckets from the seen map the floor iterates).Member #13179 — the hot-reload strip (commit
1c749681)The ruled strip: the plugin-registration refusal's tracker id — the id the #13151-verified twins at
hot-reload.test.ts:259,302,310pin — removed from both registration-door strings (RETIRED_STATE_STRATEGY_GUIDANCE, thedistributedConfigentry). Declared bounded same-class extension: the sibling id in the same refusal table'swatchPatternsentry and in thestartWatching()removal notice is stripped in the same stroke. All four bounded-fix conditions hold: same defect class (same table, same door, same audience), mechanical remedy pinned by the same-day adjudicated charter, same file already on this claim's declared surface, same twin suite with no new verification face.ADR-0049 enforce-or-remove, the spec/core versions and thescheduleReloadmigration call remain as the customer-resolvable anchors — mirroring the spec-side parse door, which was already id-free with a negative pin.Twins red-then-green: 8 assertions red (10/18 passing), 18/18 green after; every id pin re-pinned to a content anchor plus negative id pins at all three doors. Repo-wide section-7 sweep for the member's id set: the only remaining test literal is an expect failure-label, not a content pin.
Root extension is NOT in this PR — deferred by the adjudication with a codified revival condition, and not smuggled in via the C output: the boundary line states the limit instead of moving it. The revival condition, however, now measurably FIRES: the diff-derived twin sweep plus a targeted source sweep found same-audience id-bearing refusal/warn/lint prose outside
packages/spec/srcwell past the adjudicated threshold (about eleven candidate sites, e.g.objectql/src/registry.ts:1036,objectql/src/having-filter.ts:186,service-analytics/src/comparand-shape.ts:598,lint/src/validate-react-page-props.ts:434,metadata-protocol/src/protocol.ts:19879). Filed for triage as the instrument card the adjudication prescribed — #13297 (which remains open; it is out of scope here). #13179 is not affected: its own strip stands regardless of how triage grades the wider census.Verification (all at
afb72654, the pushed head)node scripts/pm/dispatch-gates.mjs(no paths; provenance line names this repo atafb72654): 51/53 green, pluscheck:type-check-debtgreen after the full 70-package build (30 ledger entries re-measured, none above recorded) andcheck:nul-bytesgreen. The two non-green results are the gates' own designed NOT MEASURED refusals, not reds:check-test-completeness.mjs(exit 3 — wants a savedturbo run testlog; instructs recording NOT MEASURED locally) andpm/check-half-states.mjs(exit 3 — the container's GitHub token is the proxy placeholder; no reading). CI measures both.check:doc-authoringgreen including--self-test(the edited gate's own suite; no external test file names it — verified by repo grep).hot-reload.test.ts18/18; objectql targeted 208/208 (including the untouched out-of-rootregistrytwin); lint targeted 76/76; service-analytics targeted 126/126.@objectstack/spec typecheckgreen (check:test-typecheck: OK, test layer compiles; debt ledger unchanged).needs:contract-review; the review chain owns enqueue.Generated by Claude Code
Generated by Claude Code