Clear three platform lint rule families (31 of 90 warnings), and report the rest with named reasons - #1605
Merged
Conversation
…-target-unknown) Clears rule `translation-target-unknown` — 4 warnings, one per locale. `crm_case` declares no `sla_overview` section anywhere: not as a `fieldGroups[].key` (the SLA group's key is `sla`), not as a named form-view section (`case.view.ts` names `case` and `how_can_we_help`), and not as a named `record:details` section (`case_detail.page.ts` names `info` / `status` / `description`). The four `_sections.sla_overview` entries therefore translated nothing — the heading they were written for no longer exists. The comment above each entry claimed the key was a form section name on `case.view.ts`; it is not, and grepping `src/` finds `sla_overview` only in these four files. Deleting the entries is the fix the rule prescribes: the alternative it suggests (`sla`) is already present and already translated, as the fieldGroup key. No user-visible change: an entry keyed to nothing rendered nowhere. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DuzfS5chho38Yx1jxx9DEj
…ithout-binding)
Clears rule `view/layout-without-binding` — 1 warning.
`listViews.account_map` declared `type: 'map'` and no `map` block, so it was
bound to nothing: the renderer falls back to literal default field names, and
the view renders empty while authoring reports success. The rule's prescribed
spelling is `map: { locationField: '<location_field>' }` (or an explicit
latitude/longitude pair).
`crm_account.office_location` is the object's `Field.location(...)` and the one
field on it that carries coordinates, so it is the binding. `billing_address`
is an `address` field — a postal shape, not a coordinate one — and stays a
column. `titleField: 'name'` labels the marker with the same field the view's
own `columns` lead with.
User-visible: the map view can now plot its markers.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DuzfS5chho38Yx1jxx9DEj
…-colspan-discouraged)
Clears rule `absolute-colspan-discouraged` — 26 warnings across 11 view files.
A form's column count is DERIVED per surface (mobile 1 / modal 2 / page 3-4),
so an absolute `colSpan` only lines up at the one width the author imagined and
is clamped everywhere else. The rule's prescribed primitive is the relative
`span: 'full'` (whole row at any column count), or omitting the key for auto
width — both declared by `@objectstack/spec@17.3.0`'s form-field schema
(`span: 'auto' | 'full'`) and both read by the published form renderer, which
resolves `span: 'full'` to the full grid and treats `colSpan` as the legacy
arm it clamps.
Every converted site sits in a `columns: 2` section, so the two intents map
cleanly and neither is guessed at:
- `colSpan: 2` (24 sites) — "span both columns", i.e. the whole row at this
density. Becomes `span: 'full'`, which is that same intent stated
independently of the surface: still a whole row when the page renders 4
columns, where `colSpan: 2` was only half of one.
- `colSpan: 1` (2 sites, `salutation` / `first_name` on the lead form) — one
cell, which is exactly what the section's own `columns: 2` already says.
The key is dropped rather than translated: `span: 'auto'` is the default,
and materializing a default rewrites "the author said nothing" into "the
author asked for the default".
Also updates the showcase docblock in `lead.view.ts`, which advertised
`colSpan` to readers as a field-level control; this file is what other authors
copy from.
User-visible: fields that span a row now do so at every surface width, instead
of only where the derived column count happens to be 2.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DuzfS5chho38Yx1jxx9DEj
Real frontmatter, not the empty declaration: two of the three families change what a user sees (the account map can plot; row-spanning form fields span at every surface width). The third is invisible by construction — a translation entry keyed to a section that does not exist rendered nowhere. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DuzfS5chho38Yx1jxx9DEj
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
os-steve
marked this pull request as ready for review
September 5, 2026 23:03
This was referenced Sep 5, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1596
objectstack lint: 90 warnings to 59, one commit per rule id, exit 0 andpnpm verifygreen. No rule is suppressed, whitelisted or locally re-severitied, and no warning is bought by bending metadata around a rule.scripts/wow1-live-schema.shis not deleted — the premise that nothing names it is false.Both dispatched premises, measured
1. "90 warnings / 12 suggestions" — HOLDS. That figure came from the director seat's census on #1579 and nobody had re-run it (no
node_modulesin the checkout). Fresh install on this branch's base81a79ee: 90 warnings, 12 suggestions, unchanged. The commit plan survives.2. "
scripts/wow1-live-schema.shis wired to nothing" — FALSE. Not deleted; stopped and reported, as instructed. The card's narrow claim is true — nopackage.jsonscript and no workflow names it — butgit grep wow1across the whole repo finds six published documentation pages that tell a reader to run it, in three locales:content/docs/ai-copilot/live-schema.mdx./scripts/wow1-live-schema.shcontent/docs/ai-copilot/live-schema.zh-Hans.mdx·.zh-Hant.mdxcontent/docs/whats-new.mdxHOTCRM_TOKEN=... ./scripts/wow1-live-schema.shcontent/docs/whats-new.zh-Hans.mdx·.zh-Hant.mdxPlus
.changeset/header-position-prose-integers.md, whose prose asserts "the one.sh(scripts/wow1-live-schema.sh)". Deleting the file would leave six shipped pages instructing readers to run something that does not exist. Removing it is a docs decision, not a cleanup rider — it needs its own card.What is fixed
translation-target-unknown— 4 warnings._sections.sla_overviewwas translated in all four locales and named nothing oncrm_case: not afieldGroups[].key(the SLA group's key issla), not a named form-view section (case.view.tsnamescaseandhow_can_we_help), not a namedrecord:detailssection (case_detail.page.tsnamesinfo/status/description). The rule's suggested alternative,sla, is already present and already translated as the fieldGroup key, so the fix is deletion, not renaming. Greppingsrc/findssla_overviewonly in those four files. Not user-visible: an entry keyed to nothing rendered nowhere.view/layout-without-binding— 1 warning.account_mapdeclaredtype: 'map'with nomapblock, so it was bound to nothing: the renderer falls back to literal default field names, and the view draws no marker while authoring reports success. Now bindslocationField: 'office_location'—crm_account's oneField.location(...), and the only coordinate-carrying field on it;billing_addressis anaddress, a postal shape, so it stays a column — withtitleField: 'name'to match the view's own leading column. User-visible: the map can plot.absolute-colspan-discouraged— 26 warnings, 11 files. A form's column count is derived per surface (mobile 1 / modal 2 / page 3-4), so an absolutecolSpanonly lines up at the one width its author imagined. Every converted site sits in acolumns: 2section, so neither intent is guessed at:colSpan: 2sites — "span both columns", i.e. the whole row — becomespan: 'full', the same intent stated independently of the surface. At a 4-column page these were previously half a row.colSpan: 1sites (salutation,first_nameon the lead form) lose the key rather than gainingspan: 'auto'. That is already the default, and materializing a default rewrites "the author said nothing" into "the author asked for the default".span: 'auto' | 'full'is declared by the pinned@objectstack/spec@17.3.0form-field schema and read by the published form renderer (resolveColSpanresolves'full'to the full grid and treatscolSpanas the legacy arm it clamps) — checked against the published artifact, not the source tree. The showcase docblock inlead.view.ts, which advertisedcolSpanto readers as a field-level control, is updated too: this file is what other authors copy from.What is NOT fixed, and why
component-props-invalid— 16 warnings. Refused: the fix would delete every header button from four record pages.The rule is right about the contract.
PageHeaderProps.actionsisz.array(z.string())("Action IDs to show in header") and these four pages author wholeActionDefobjects. But the fix depends on a renderer that is not published:page:headerthe id-resolution path, and objectui#7182 rules that ids are the contract (maintainer, 2026-09-02, option C).npm view @object-ui/components version= 17.6.0; objectuimainHEAD's changelog head is also 17.6.0, and both changesets are still pending, unconsumed in its.changeset/.⇒ Merged, not released — the same trap as
--stricton #1581, and exactly the unlock predicate hotcrm#1279 already warns about ("a read of the published artefact"). On the renderer this repo's console runs, an id-authored array resolves nothing: Convert Lead, Generate Quote, Escalate Case and the activity trio would vanish, with no other entry point on a custom record page. Left in place; #1279 updated with the measurement and the now-narrowed unlock predicate. The fourKNOWN_UNCONFORMINGlines intest/metadata-references.test.tsare untouched.component-props-unknown-key— 1 warning. Owned by #1216.sales_home_page/ai_briefingauthorsproperties.description, whichpage:carddoes not declare, so the paragraph renders nowhere. The fix is to move the copy into anelement:textchild — but the copy is pinned in place by the #1002 persona guard, which readsproperties.description, asserts it is a string, and encodes a maintainer ruling. Relocating it means rewriting a ruling-backed guard intest/**, which is #1216's job and outside this card's file surface.flow-loop-body-uncontained— 42 warnings. Stopped on file surface; filed as #1604 with the fix already measured.Ten scheduled sweeps abort on their first failing record. The fix is real, entirely inside
src/flows/**, and was written and verified on this branch before being reverted: 42 to 0, lint exit 0, typecheck exit 0, token ratchet clean with 155 tokens of headroom (the literal 22-times spelling does not fit — its re-indentation alone putbusiness semantics~1,327 tokens over a ceiling that only moves on a maintainer ruling; aguarded()helper that leaves each body's indentation untouched does fit).try_catchregion execution and the bare-assignmenthandler were both checked against the pinned 17.3.0 engine, not the platform source.It is not in this PR because landing it reds 14 assertions across 8 files under
test/**— hand-rolled flow-graph walkers that descendconfig.body.nodesand stop, plus one that builds a live-engine fixture by mutatingloop.config.body.edges. This card's file surface is "whateverobjectstack lintnames", which never names a test file, and those same 8 files are what epic step 3 (#1582 to #1587) is queued to rework, eachBlocked-by#1581. #1604 carries the full plan, the helper, the token measurements and the walker inventory so none of it is rediscovered.Suggestions
12, unchanged and not addressed (the card reports them by count):
approval-approvers-may-resolve-empty4,rollup/missing-summary2,relationship/line-items-inline-edit2,relationship/line-item-should-be-master-detail2,object/missing-name-field2.No upstream findings filed
Every one of the 59 remaining warnings is correct about this metadata. None is a rule that is wrong here, so there is nothing to file in
objectstack-ai/objectstack; the blockers are a pending objectui release, a ruling-backed local guard, and a file-surface boundary. Filing a platform card for any of them would be noise.Verification
Base re-measured at
81a79eeafter a fresh install. Changeset carries real frontmatter ('hotcrm': patch), not the empty declaration: two of the three families change what a user sees.🤖 Generated with Claude Code
https://claude.ai/code/session_01DuzfS5chho38Yx1jxx9DEj
Generated by Claude Code