Repository navigation
Commit 23419ba
fix(lint): one-line verdicts for the nav, object-reference, capability, action-name, mapping-target, view-container and interface-page rules;
Part of #22161
Clause-②: no
Stage 2 of the card, slice 9: the 10 rule ids of ten whole
`packages/lint` source files — the three app-navigation rules, the
object field-name-list rule, the platform-prefixed object-reference
rule, the capability-reference rule, the name-bound action rule, the
import-mapping-target rule, the view-container rule and the
interface-page visualization rule. Plus a text-only correction of the
pending slice 5, 6 and 7 changesets (one clause each, below). The card
stays open for the later slices listed under "Remaining for later
slices" below.
## What changes
- **One verdict line per finding.** Each finding of the 10 ids prints a
`message` of one verdict sentence, followed by `Did you mean "…"?` where
the rule offers the nearest declared name. Every finding the rules' own
suites fire is now 199 characters or fewer; the longest of each id was
227 to 629 before. The runtime publish gate's suite (the whole
`@objectstack/metadata-protocol` suite) fires one of the 10,
`object-field-ref-unknown`, at 95 or fewer (273 before). The whole
`packages/cli` unit tier fires one arm of `view-container-shape` whose
text is unchanged; `os validate` on the four example apps fires none of
the 10, before or after.
- **Where the verdict keeps a name, it is the one the author needs to
find the defect.** The verdict no longer repeats what the finding's
`where` already names (the import mapping and its object, the interface
page). `nav-object-unservable` names the object's `enable` key and the
status the list answers; `nav-target-unresolved` keeps the "NO pages at
all" clause when `defineStack`'s own check is off;
`action-name-undefined` names where a related-list id IS defined, at
most three places, then `(and N more)`; `mapping-target-field-unknown`
keeps the `transform "lookup"` fix on the reference arm, its only fix
not on the `fix:` line.
- **`object-field-ref-unknown` prints the family's shared field-path
sentence alone** (`describeFieldPathVerdict`, unchanged, shared with
four other rules), exactly as slice 8 left `list-view-field-unknown`:
`highlightFields[1] "field_10" is not a field on object "proj_task".` A
short per-position consequence clause was measured first and dropped:
with it, the path's hop verdicts (a dotted name through a
non-relationship field) printed 206 to 232 characters on probes, and the
clause read "does not exist" on a field that exists. What a miss costs
at each position (the redaction that fails OPEN, the index the SQL sync
skips, the field `dependsOn` gates for good) is the explanation's,
written out per position.
- **The flat-list-view arm of `view-container-shape` no longer states a
false mechanism.** It said `ViewSchema` strips the keys and the entry
"parses to an EMPTY container — zero views register". The module's own
header records that as measured false since `ViewSchema` went strict,
and the registration loop refuses the shape (`isViewContainerShaped`,
422 `INVALID_METADATA`). The verdict now says the schema and the loop
refuse it, and the rule's test holds both seams (`ViewSchema.safeParse`
refuses the flat and the ViewItem entry; `isViewContainerShaped` refuses
both and takes the empty container).
- **The reasoning moves to `RULE_EXPLANATIONS`**
(`packages/lint/src/rule-explanations.ts`), 10 new entries, so `os
explain RULE_ID` prints it and the CLI's `rule:` line ends with the
pointer for these ids. No CLI source changes: `explainPointer()` and `os
explain` resolve any key the table holds
(`packages/cli/test/explain-rule-id.test.ts` iterates every key; it ran
in the unit tier below); `node bin/run.js explain nav-object-unservable`
prints the entry. The 111 entries already in the table are byte-equal
(the diff of `rule-explanations.ts` is additions only).
- **Nothing else moves.** Rule ids, severities, `path`, `hint` (the
`fix:` line) and what each rule accepts or refuses are unchanged. No
condition, branch, skip or dedupe moved, and no export was added,
removed or renamed: every hunk in the ten rule files is a `message`
expression, a comment, a verdict helper, or the removal of a value that
fed only the old message. The plumbing hunks, each message-only:
- `validate-object-field-refs.ts`: the module-private `consequence`
member of `ListPosition`, `FieldNameSlot` and `INDEX_POSITION` (and the
`judge` parameter that carried it) goes; it fed only the message, and
its text is the explanation's.
- `validate-nav-object-servability.ts`: the local `condition` and
`answer` strings go (message-only); `offendingKey` stays and is now the
one name the verdict carries.
- `validate-mapping-target-fields.ts`: `dottedReason()` becomes
`dottedVerdict()` (still a string, one sentence per arm; the
`objectName` argument it no longer reads goes), and `capitalize()`,
which fed only it, goes.
- `validate-action-name-refs.ts`: `atMostThree()` (new, module-private)
bounds the "defined only on …" list; the `consequence` defaults of
`check()` become clauses.
- No helper changed shape (string in, string out); no truth table is
involved.
- `.changeset/22161-lint-slice-9-one-line.md`: `@objectstack/lint`
`patch`, naming every door that prints the new text (below). `Clause-②:
no`, as line 2 says: every rule id these entries key already had an
exported constant on the root barrel (`index.ts` is untouched), and
slice 1's contract review (② of its record) reads `RULE_EXPLANATIONS`
entries as data in an existing export.
- **The changeset rider** (the dispatch's DELIBERATE CORRECTION, see
Acceptance notes): `.changeset/22161-lint-slice-5-one-line.md:17`,
`22161-lint-slice-6-one-line.md:19` and
`22161-lint-slice-7-one-line.md:20` each said "the scaffold check `os
init` and `os generate` run print …". Re-measured at the base
`996aa86e0a`: `validateScaffold`
(`packages/cli/src/utils/scaffold-validate.ts`) has one caller,
`commands/init.ts:1314`, and `commands/generate.ts` imports nothing from
`@objectstack/lint` and calls no authoring rule (its only stack read is
`authoringRuleUnionStack`, a fold). Each now reads "the scaffold check
`os init` runs print …". One line per file; front matter, level and
`Clause-②:` line byte-identical. All three are still pending at the base
(not consumed into a CHANGELOG).
- **The declared rider went unused:** no `packages/cli/test` or
`packages/metadata-protocol` file asserts these ids' message text (they
pin `rule`, `path` and planted rule ids), and no `content/docs` page
quotes one of these messages as printed output
(`content/docs/permissions/authorization.mdx` and `permission-sets.mdx`
describe the capability rule's behaviour, "registered nowhere", which
stays true). `examples/app-showcase/test/nav-and-detail-grants.test.ts`
asserts `navigation exposes object "showcase_cascade"`, so the new
`nav-object-ungranted` verdict keeps that opening; the test ran green on
the rebuilt dist (below), unedited.
The verdict forms, the longest of each arm the rule suites fired:
```text
navigation exposes object "crm_secret_token", but no permission set this stack declares grants read on it, so opening the entry fails permission-denied for everyone but a wildcard admin
Navigation targets object "crm_secret_token", which cannot serve a list (`objects[1].enable.apiEnabled` is false), so the server prunes the entry: its list answers 404 for every user
Navigation targets object "crm_audit_row", which cannot serve a list (`objects[2].enable.apiMethods` lacks `list`), so the server prunes the entry: its list answers 405 for every user
Navigation targets dashboard 'nope', which `dashboards` does not declare (there are NO dashboards at all, so `defineStack` skipped the entry), so the entry resolves to nothing when clicked
Navigation targets page 'typo', which `pages` does not declare, so the entry resolves to nothing when clicked
highlightFields[1] "field_10" is not a field on object "proj_task".
fields.account.lookupColumns[0] "crm_account.region" is not a field on object "crm_account". Did you mean "region"?
fields.account.lookupFilters[0].field "status.label" traverses "status", which is a `select` field on object "crm_account" and not a relationship — there is nothing to join through.
field-backed param object "sys_approval_process" has a platform prefix, but no known package registers it and this stack does not define it, so it likely resolves to nothing. Did you mean "sys_app"?
requiredPermissions names capability "clm_legal_workbnch.view", which no built-in, `defineCapability`, `systemPermissions` grant or `sys_capability` seed provides, so this gate fails closed
Bulk-action menu names action "crm_convert_leads", which no action in this stack defines, so the button does nothing when clicked. Did you mean "crm_convert_lead"?
Alert call-to-action names action "resend_verifcation_email", which no action in this stack defines, so the banner renders without its call-to-action button. Did you mean "resend_verification_email"?
Page-header actions names action "covert_lead", which no action in this stack defines, so the header draws no button for it.
Related-list actions names action "crm_merge_accounts", not an action of related object "crm_contact" (defined only on object "crm_account"), so the list draws no button for it.
Related-list actions names action "crm_lgo_call", not an action of related object "crm_contact" (defined nowhere in this stack), so the list draws no button for it. Did you mean "crm_log_call"?
Related-list actions names action "crm_sync_contact" of "crm_contact", which is placed at no location a related list draws, so the list draws no button for it.
Related-list actions names action "crm_score_contact" of "crm_contact", which declares no `locations`, so the list draws no button for it.
Target "emial" names no field of "crm_contact", so the import endpoint refuses this mapping (INVALID_FIELD) and it imports nothing. Did you mean "email"?
Target "mailing_address.stret" names no part of the address field "mailing_address", so the import endpoint refuses this mapping (INVALID_FIELD). Did you mean "street"?
Target "full_name.first" is dotted, but the text field "full_name" has no parts (only a compound field does), so the import endpoint refuses this mapping (INVALID_FIELD).
Target "account.name" cannot traverse the lookup field "account", so the import endpoint refuses this mapping (INVALID_FIELD); map the column to "account" with transform "lookup".
The compound field "mailing_address" is mapped both whole (fieldMapping[0].target) and by its part "street", so the two collide and the import endpoint refuses this mapping (INVALID_FIELD).
A ViewItem record (`viewKind`) is not a view container: `views:` carries containers only, so the stack schema, this rule and the registration loop all refuse it.
Flat list-view object is not a view container: its single-view keys sit where the container slots belong, so the stack schema and the registration loop refuse it.
'gantt' leads the whitelist, but its `startDateField + endDateField` derives from no field of "showcase_task" and no `sourceView` supplies it, so every visitor lands on its refusal screen
'kanban' is in the whitelist, but its `groupByField` derives from no field of "crm_note" and view "schedule" has no `kanban:` block, so the switcher SILENTLY drops it
```
## Shared prose: written once (the dispatch's route, measured)
| shared paragraph | ids | explanation constant (`rule-explanations.ts`)
| held to its source by |
|---|---|---|---|
| a nav entry's grant and its servability are independent conditions |
`nav-object-ungranted`, `nav-object-unservable` |
`NAV_INDEPENDENT_CONDITIONS` | one text under both ids (each rule's
test) |
The dispatch expected the three nav rules and the two object-reference
rules to share paragraphs. Measured: the nav rules walk different
containers (`nav-object-ungranted` reads each area's `navigation` only;
the other two read each area's `items` and `navigation`), and
`nav-target-unresolved`'s facts (the `defineStack` size gate, no
registry for pages) are its own, so one paragraph is shared, not a walk.
`object-reference-unknown` prints one sentence of at most 175 characters
at the base (lint suite; 188 is `os lint`'s printer row, which prefixes
`where`), so it is not converted and has no entry to share with.
The explanation module imports nothing, so each fact it writes out is
held to its source by the rule's own test: the read bits by running
`validateNavAccess` on each; the walked nav containers by firing each;
the three nav target types and collections by running the rule on each;
the object-field positions by the paths fired; the platform prefixes to
`PLATFORM_OBJECT_PREFIXES`; the four capability sources by each one
silencing the rule; the related-list drawn locations by running the rule
over every `ACTION_LOCATIONS` member; the provisioned mapping columns by
running the rule; the view-container refusals to `ViewSchema` and
`isViewContainerShaped`; and the derivation paragraph to
`OBJECTUI_DERIVATION_PREDICATES`, row by row.
## Census (taken first, before any edit, at the base `996aa86e0a`)
Method: slice 4–8's scratch preload (`NODE_OPTIONS=--import`, never
committed), which patches `Array.prototype.push` to record every
finding-shaped object (`rule` + `message`) of the 10 ids (plus
`object-reference-unknown`, the second id of
`validate-object-references.ts`, to measure it), deduped by (rule,
message) per process, with its push site. Lengths are `message` alone;
the printed line adds `where` and `: `. Rows from `os lint`'s own
printer (`commands/lint.ts:761`, which pushes `where: message`) are
named as such. Positive control in every run: `field-no-consumers` (and,
in the runtime-gate suite, `sort-field-unknown` and
`searchable-field-unknown`), recorded in every run.
- **`packages/lint` suite**, base 136 files / 6,374 tests (after the
CLI, metadata-protocol and example closure build): **all 10 ids fire**,
every one over 200 at its longest; the longest of each equals PR
#22765's figure except `capability-reference-unknown`, 227 here (219 in
slice 2's census, a longer capability name in a case added since).
`object-reference-unknown`: 21 messages, longest 175.
- **`packages/cli` unit tier**, the whole project (280 files, 4,170
tests, all loaded; `packages/cli/dist` built): fires
`view-container-shape`'s empty-container arm only (127; 150 as `os
lint`'s printer row), whose text this slice leaves unchanged, and
`object-reference-unknown` (not converted). Control recorded.
- **Runtime publish gate:** the whole `@objectstack/metadata-protocol`
suite (227 files, 224 run, 28,116 passed), which reads
`@objectstack/lint` from its built `dist/`: fires
`object-field-ref-unknown` (4 messages,
`protocol-publish-drafts-object-field-refs.test.ts` and
`protocol.runtime-authoring-gate.test.ts`, which pin rule id, path and
field name, never the text); none of the other 9. Controls recorded both
runs.
- **Example apps:** `os validate` (the built CLI) on `app-crm`,
`app-todo`, `app-showcase` and `app-multi-package`, exit 0 each, before
and after: **none of the 10 fire**; control recorded (22 messages), and
every app prints the same number of `rule:` lines before and after (9 /
7 / 70 / 3).
- **Extra, outside the dispatch's list:** three `packages/cli`
integration-tier files that name these ids
(`authoring-rule-command-parity.test.ts`,
`verify-author-time-stage.test.ts`, `union-fold-command-parity.test.ts`;
the fourth, `build-multi-package-artifact.e2e.test.ts`, is in no vitest
project and is declared to CI), which fire `view-container-shape`'s flat
arm.
- **After:** the lint `dist/` rebuilt from the slice (marker `so the
switcher SILENTLY drops it` 1 hit each in `dist/index.js`, `index.cjs`,
`runtime.js`, `runtime.cjs`; the old `visualization, but nothing
supplies its` 0 in each; `how a list page binds each visualization it
allows` 1 in `dist/rule-explanations.js`). The cli-unit, runtime-gate,
example and cli-integration after-runs read the dist built at
`5beae52dd0`; the one lint-source change after it is the text of
`action-name-undefined`'s related-list placement arm, an id none of
those four runs fires, before or after. The lint-suite after-run below
is at `f5bf79ea14`, whose lint source is the final head's.
| rule id | severity | lint suite: before (msgs · longest) → after (msgs
· range) | runtime-gate suite | cli integration (3 files) |
|---|---|---|---|---|
| `nav-object-ungranted` | warning | 3 · 353 → 3 · 177–185 | — | — |
| `nav-object-unservable` | error | 1 · 528 → 3 · 180–183 | — | — |
| `nav-target-unresolved` | warning | 6 · 426 → 7 · 109–188 | — | — |
| `object-field-ref-unknown` | error | 36 · 320 → 40 · 65–181 | 4 · 273
→ 4 · 67–95 | — |
| `object-reference-unregistered-platform` | warning | 5 · 324 → 9 ·
186–198 | — | — |
| `capability-reference-unknown` | warning | 14 · 227 → 15 · 174–189 | —
| — |
| `action-name-undefined` | error | 24 · 409 → 30 · 117–199 | — | — |
| `mapping-target-field-unknown` | error | 8 · 466 → 9 · 129–189 | — | —
|
| `view-container-shape` | error | 4 · 290 → 4 · 127–182 | — | 1 · 173 →
1 · 162 (the flat arm) |
| `page/visualization-without-binding` | error / warning | 15 · 629 → 25
· 153–187 | — | — |
The cli unit tier column is not drawn: it fires `view-container-shape`'s
empty-container arm alone (127, and 150 as two `os lint` printer rows),
before and after, with unchanged text. The example-app column is not
drawn: none of the 10 fire there, before or after.
`object-reference-unknown` (not converted): lint suite 21 · 175 before
and after.
All push sites fire before and after (`action-name-undefined` 3,
`mapping-target-field-unknown` 2, `view-container-shape` 3, every other
id 1). A higher message count after is a case this slice added (the
servability arms, the every-site object-reference probe, the dotted
object-field paths, the alert and header arms, the every-visualization
probe).
## Doors that print the new text
Read from the registry (`authoring-rules.ts`:
`validateCapabilityReferences` and `validateViewContainers` are
`commands: ALL`, CLI only; the reference-integrity suite, `commands:
ALL`, CLI and runtime, dispatches `validateObjectFieldRefs` on `['flow',
'object']`, `validateObjectReferences` on `['flow', 'dataset']`, and the
nav, action-name, mapping and page-visualization members on the default
`['flow']`), the runtime gate's split (errors → the 422 issue,
everything else → 2xx `advisories` plus the `[Protocol] authoring
advisory` log line, both after the gate's differential), and the CLI's
callers (`commands/validate.ts`, `compile.ts`, `lint.ts`, `verify.ts`
through `judgeAuthorTimeRules` on the `validate` set, and `init.ts`
through `validateScaffold` on the `build` set). Measured at the runtime
door with `runRuntimeAuthoringRules` (scratch probe): a `dataset` write
over `sys_approval_process` answers
`object-reference-unregistered-platform` in `advisories`; an `object`
write with a dangling `highlightFields` entry answers
`object-field-ref-unknown` in `errors` (and its `lookup` to
`sys_approval_process` is not judged there); a `flow` write answers none
of the 10.
| door | ids | what changes |
|---|---|---|
| `os validate`, `os build` (and `os compile`, which `os dev` runs per
compile), `os lint`, `os verify`, the scaffold check `os init` runs |
all 10 | the text-face verdict line; the `rule:` line gains the `os
explain` pointer; `os validate --json` `errors` and `os build --json`
author-time `issues` carry the new `message` |
| runtime publish gate, `object` write | `object-field-ref-unknown`
(error) | the 422 issue's `message` and the
`OS_ALLOW_UNLINTED_METADATA_WRITES` refusal log line |
| runtime publish gate, `dataset` write |
`object-reference-unregistered-platform` (warning, the dataset's base
`object`) | the 2xx `advisories` entry and the advisory log line |
| never at the runtime gate | `capability-reference-unknown`,
`view-container-shape` (CLI-only rules); the three nav ids,
`action-name-undefined`, `mapping-target-field-unknown`,
`page/visualization-without-binding` (dispatched only for a `flow`
write, whose snapshot carries no apps, pages, views or mappings of its
own) | |
| unchanged | every `hint`; every other rule id | |
Every row is named in the changeset.
## Tests
The rule suites import the rule source; the CLI, runtime-gate and
example runs read the rebuilt `@objectstack/lint` dist. Every heavy run
went through `scripts/pm/os-verify-lock.sh`; its VERDICT lines are
quoted.
- **Each rule's own suite pins the new shape**, as in slices 2–8. The
ten touched suites wrap their rule import and record every finding their
direct calls fire; the LAST case in each file holds every recorded
verdict of its id to one line of at most 200 characters, behind a
coverage control (each arm: both servability conditions; all three nav
target types with and without the empty-collection clause; every
object-field position, the retired `compactLayout` spelling and both hop
verdicts of a dotted path; all nine object-reference sites; every
action-name surface and all four related-list arms; all five mapping
arms; all four view-container arms; both severities, both remedy arms
and every visualization with a deriver). Exact pins hold one verdict per
arm; explanation pins hold, per id, that `explainRule(id)` exists and
names what the verdict stopped saying, that the shared paragraph is one
text under both ids it serves, and the source-held facts in the table
above. Every refusal assertion, rule id, severity, `path`, `where` and
hint pin is unchanged; the pins that read the old text moved to the new
verdict or to the explanation (`size > 0` and `forced view type` to the
explanation; `fails OPEN`, `stays gated for good` and `` `unique` index
is then unenforced `` to the explanation; the mapping arms' and the
related-list arms' fragments to the new sentences; the interface-page
search description to the `fix:` line, where the hint already carries
it). `validate-nav-object-servability.ts` had no test file of its own
(its one pin was the suite's "every member actually runs" case); it
gains `validate-nav-object-servability.test.ts`, which covers both
conditions, the walked containers and the four skips besides the new
shape.
- **Lint suite** at `f5bf79ea14` (the final head `79747fd0ce` adds
changeset text only): `pnpm --filter @objectstack/lint exec vitest run
--maxWorkers=2`: Test Files 137 passed (137), Tests 6,416 passed
(6,416); VERDICT command-exit 0 (base 136 / 6,374; one new file, 42 new
cases).
- **Lint build + typecheck:** `pnpm --filter @objectstack/lint build`
(VERDICT command-exit 0, `check-dts-emitted` 6/6), and the merged
closure build at `f5bf79ea14` (`turbo run build`, 62 tasks, VERDICT
command-exit 0). `pnpm --filter @objectstack/lint run typecheck` at
`f5bf79ea14`: VERDICT command-exit 0; `check:test-typecheck` OK, 2 files
/ 6 errors / 2 pinned signatures held. `tsc -p
packages/lint/tsconfig.test.json --listFiles` lists all ten touched test
files, the new one included.
- **CLI unit tier**, against the rebuilt lint dist: `pnpm --filter
@objectstack/cli exec vitest run --project unit --maxWorkers=2`: Test
Files 280 passed (280), Tests 4,170 passed (4,170), before and after;
VERDICT command-exit 0 both. It includes `test/explain-rule-id.test.ts`
(iterates every `RULE_EXPLANATIONS` key, so the 10 new ids resolve
through `os explain`, `explainPointer` and the listing). `node
bin/run.js explain nav-object-unservable` prints the entry on the dist
built at `f5bf79ea14`. The integration tier is declared to CI (no file
in it asserts these ids' text, and the diff touches no spawn entry); its
three files that name these ids ran as the census extra above: Test
Files 3 passed (3), Tests 23 passed (23), before and after.
- **Runtime gate:** the whole `@objectstack/metadata-protocol` suite,
before and after: Test Files 224 passed | 3 skipped (227), Tests 28,116
passed | 19 skipped (28,135), both runs; VERDICT command-exit 0.
- **The showcase pin on the `nav-object-ungranted` opening:** `pnpm
--filter @objectstack/example-showcase exec vitest run
test/nav-and-detail-grants.test.ts` on the final dist: Test Files 1
passed (1), Tests 4 passed (4); VERDICT command-exit 0.
- **Tracker ids:** no `#` plus digits in any printed message or
explanation (`rule-explanations.test.ts` refuses one in every
paragraph); the citations stay in `//` comments and test names.
- **Ablation** (one-shot, from the committed state `f5bf79ea14`, through
`scripts/ablation-replace.mjs` wrap mode under the verify lock, plus a
shell `trap` restoring `HEAD` by absolute path). The rule suites import
the rule source, so there is no dist leg. `nav-object-ungranted`'s
pre-slice message block was restored verbatim (the replacement read from
the base file) through the anchor of its new block: anchor x1 → x0, blob
`5358057cddb2` → `efc20da6f54e`. Predicted before the run: exactly two
cases red — the 200-character bound pin and the id's exact-text pin;
every other assertion on the id pins fragments the old text also carries
(`crm_forecast`, the path, the rule id). Observed:
`src/validate-nav-access.test.ts` Test Files 1 failed (1), Tests 2
failed | 18 passed (20); the two red cases are exactly those two (the
bound pin read 349 characters). Restored: blob `5358057cddb2` == blob at
HEAD, `git diff HEAD` empty, `git status --porcelain` empty.
- **ESLint, narrowed:** `npx eslint --no-inline-config --format json`
over the 21 changed `.ts` files at `79747fd0ce` gave 21 files in the
report, 0 errors, 0 warnings. The population is `eslint.config.mjs`'s
`files: ['**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}']` block plus the
`packages/**/*.{ts,tsx,mts,cts}` blocks, which all 21 are in (the
changesets are not a linted kind). `eslint.config.mjs` never enables
type-aware linting (no `parserOptions.project`, no typed
`@typescript-eslint` rules; the config's own note says so), so no
untouched file's verdict can move. A control-character scan of every
changed file found no match.
- **Gates:** `node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` with no paths, at the final head
`79747fd0ce` (merge base `e84aeb36ce`, after one merge of `origin/main`;
`origin/main` has since moved two commits, an ADR and the new
`packages/skills`, which touch no `packages/lint`, `packages/cli`,
`packages/metadata-protocol` or `.changeset` file), derived 62 commands,
the same set as at `51dc621510` before the merge. I ran 61 of them
sequentially at that head, each with its own log and its exit code
captured before any pipe: 60 exited 0, and `node
scripts/check-empty-changeset.mjs --base origin/main` exited 1, the
expected DELIBERATE CORRECTION reading on the three slice 5–7 changesets
(Acceptance notes). One is NOT MEASURED, as the dispatch directs: `pnpm
check:type-check-debt` (`--re-measure`, which builds every package); its
non-re-measuring half, `check:type-check-coverage`, ran and exited 0.
`--ran` over the exit-coded record: `Run reconciliation — 62 derived, 61
run, 1 NOT-MEASURED, 0 UNRUN.` The four artifact-roster families
rostered under a directory this diff touches (`check-changeset-fixed`,
`check:authz-resolver`, `check:error-code-casing`,
`check:filter-alias-parity`) also ran at the head: all exited 0. An
earlier full pass at `f5bf79ea14` (the head before the last
changeset-text commit) read the same: `check:dual-build-cjs-loads` there
first answered `PREREQUISITE NOT MET` (six packages' `dist/` absent:
`studio`, `client-react`, `embedder-openai`, `knowledge-ragflow`,
`organizations`, `service-cluster-redis`), I built exactly those six
under the lock (VERDICT command-exit 0), and it exited 0 then and at the
final head. The long ones on the shared box:
`check:query-options-erasure` 316s, `check:slot-lookup` 166s,
`check-comment-mask-corpus` 136s.
## Remaining for later slices — 10 ids in `packages/lint`, by file
PR #22765's list minus this slice's ten files and ids. The lengths are
slice 2's (PR #22448, census at `05c7c3fa3b`), not re-measured here.
- `lint-flow-credential-literals.ts` (1): `flow-credential-literal` 390
- `validate-ai-surface-affinity.ts` (1): `ai-skill-surface-mismatch` 281
- `validate-ai-tool-references.ts` (1): `ai-skill-tool-unresolved` 441
- `validate-flow-filter-tokens.ts` (1): `flow-filter-token-unknown` 278
- `validate-managed-api-methods.ts` (1):
`object/managed-api-method-unaffordable` 412
- `validate-org-axis-red-lines.ts` (1): `org-axis-cross-org-bu-grant`
365
- `validate-retired-permission-residue.ts` (1):
`permission-retired-lifecycle-residue` 235
- `validate-seed-replay-safety.ts` (1):
`seed-insert-mode-duplicates-on-replay` 222
- `validate-seed-state-machine.ts` (1):
`seed-value-outside-state-machine` 320
- `validate-semantic-roles.ts` (1): `semantic-role-field-unprovisioned`
291
The 26 ids slice 2 fenced, the 9 ids owned by `packages/cli`, and the
`action-governance.ts` boot-log lines stay as PR #22448's body lists
them, and `react-prop-deprecated` as PR #22700's notes it. This slice
touched none of them.
## Acceptance notes
- **`Check Changeset` is red on this head by design.** The three slice
5–7 edits are the `check-empty-changeset` DELIBERATE CORRECTION class
(pending notes corrected in place before the release that publishes
them); `pr-automation.yml` route 0 reds on any edit to an existing
`.changeset/*.md`. The files are not restored and `skip-changeset` is
not applied (this PR adds a changeset of its own). **Written
confirmation is requested** from the review at `CONTRACT_REVIEW_TIER`:
that the three one-clause edits are the measured correction and nothing
else (`git diff 996aa86 --
.changeset/22161-lint-slice-{5,6,7}-one-line.md`: 3 files, 3 insertions,
3 deletions, one hunk each).
- **Hints, for the card's open hint call:** none of the 10 ids' hints
points at text the verdicts cut. Each was read against the cut text: the
nav hints (grant, `enable` and declaration remedies), the object-field
prescriptions with their `Fields on …` list, the object-reference hint
(with the per-site consequence it carries), the capability hint, the
action-name hints (the related-list ones list the drawn locations), the
mapping hints (with the compound parts), the view-container wrap-it
hints and the interface-page hint (which says what the derivation looks
for) are each self-contained. Unchanged here, as every slice leaves
hints. One inverse case, kept: `mapping-target-field-unknown`'s
reference arm carries the `transform "lookup"` fix in its verdict,
because its hint does not say it.
- **`object-reference-unknown` is not converted** (175 at its longest in
the lint suite, 153 in the cli unit tier, before and after; the
dispatch's mechanism assumption: include it only if it exceeds about
200).
- **`field-no-consumers` (stage 1's id)** still prints its 341-character
verdict on `os validate` of `examples/app-showcase` (this census's
control), as PRs #22742 and #22765 recorded; untouched, a later slice's.
- **`view-container-shape`'s flat-arm `looksFlat` fingerprint** reads
`type`, `columns`, `data`, `filter`, `sort`, while the registration
loop's `isViewContainerShaped` also refuses `sections`. A container-less
entry with only `sections` set reaches this rule's empty-container arm
instead of the flat one; observation only, no wrong verdict follows
(both arms are errors with the wrap-it hint).
- **A long name can still lengthen a line.** The 200 bound holds on
every variant the suites fire; the object, field, action, page, view,
capability and mapping names in a verdict are the author's.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01S3aAf11JjbW1mSGL1EhfFj)_
---------
Co-authored-by: Claude <noreply@anthropic.com>os explain RULE_ID carries their reasoning (#22799)1 parent 14f4912 commit 23419ba
25 files changed
Lines changed: 1473 additions & 182 deletions
File tree
- .changeset
- packages/lint/src
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
14 | 14 | | |
15 | 15 | | |
16 | 16 | | |
17 | | - | |
| 17 | + | |
18 | 18 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
16 | 16 | | |
17 | 17 | | |
18 | 18 | | |
19 | | - | |
| 19 | + | |
20 | 20 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
20 | | - | |
| 20 | + | |
21 | 21 | | |
| 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 | + | |
0 commit comments