Repository navigation
fix(lint): one-line fix lines for the slice-19 rule ids (two flow wrong-syntax ids, capability, liveness ledger, two page-field ids, list-view mode); os explain carries what they explained - #23918
Conversation
Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XK9otrEUnkWkwJQAnVeTk6
…explain Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XK9otrEUnkWkwJQAnVeTk6
Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XK9otrEUnkWkwJQAnVeTk6
…9-five-file-hints
📓 Docs Drift CheckThis PR changes 1 package(s): 3 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 1 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 4 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 16438192e6e6fdd5e710c462013c382bb2da3897 && git checkout 16438192e6e6fdd5e710c462013c382bb2da3897
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin d5666be8769a18c5c8d7695b3ac9100af2394620 bb6c6032d6073e645b9247c0625f2951c4e6ce6b && git checkout -B drift-repro d5666be8769a18c5c8d7695b3ac9100af2394620 && git merge --no-ff bb6c6032d6073e645b9247c0625f2951c4e6ce6b
node scripts/docs-audit/affected-docs.mjs --json d5666be8769a18c5c8d7695b3ac9100af2394620
|
Review: ACCEPT · #22161 slice 19 · PR #23918 @
|
Part of #22161
Clause-②: no
Slice 19 of the card: the over-long
fix:lines, continued in slices 11–17's shape, for the ids slice 16's report (6140250582) lists invalidate-capability-references.ts,lint-liveness-properties.ts,validate-page-field-bindings.tsandvalidate-list-view-mode.ts, pluslint-flow-patterns.ts's two wrong-syntax ids now that #19939 has finished. Each finding'shint(the CLI'sfix:line, the runtime advisory'shint) of these 7 rule ids is now one remedy line of at most 200 characters, and what the lines used to explain is each id'sRULE_EXPLANATIONSentry behindos explain RULE_ID. The card stays open: the last section lists what is left.Claim:
6213957180(the newestClaim:naming this branch; the only later-or-concurrent claim,6213942673, names slice 18's branch; verified before the first edit). No file of slice 18 (data-model-rules.ts) is touched.What changes
One remedy line per finding. Every hint the lint suite fires, before → after (count of distinct hints · length range). Measured with the push-preload census (an
Array.prototype.pushpreload over the whole lint suite, plus anArray.prototype.mapleg for findings built with.map()), at the base6db53acd6and at this branch:flow-double-brace-interpolationlint-flow-patterns.tsflowwrite, 2xx advisoryflow-bare-dollar-referencelint-flow-patterns.tsflowwrite, 2xx advisoryliveness-ledger-unreadablelint-liveness-properties.tscapability-reference-unknownvalidate-capability-references.tspage-section-count-not-multi-valuevalidate-page-field-bindings.tspagewritelist-view-filters-in-views-modevalidate-list-view-mode.tspage-field-unknownvalidate-page-field-bindings.tspagewriteMeasured and not changed:
liveness-planned-property(slice 16 listed it at 230) is 3 · 1–88 today. No shipped ledger row carries anauthorHint, so its line is the verdict's default. The file's over-200 id isliveness-ledger-unreadable, which the push census cannot see (its findings come from a.map()); the map leg measured it, so it is converted instead. Stated as a deviation from the claim's per-file count.Counts that fall are lists and judge sentences that no longer make each hint distinct. The flow counts also include cases this slice added (a reference list too long for one line, in each slot kind).
The flow ids keep the judge's spelling, and only where it evaluates. Before this change, both flow hints spliced the spec value-slot or text-slot judge's whole remedy into the line: guards, the run user's null, callee and client sentences, literal-position and legacy-shape paragraphs, the list of text slots. After:
directSpellingAt, matching the judge's two direct openings,Write `{x}` as ENVELOPEand the text-with-holes concatenation). FROM (681)A value slot reads a CEL value envelope, … $source.id names $source, which is not one of the flow engine's own $ variables, … Write {source.id} as { dialect: 'cel', source: 'source.id' }. CEL refuses an absent variable or key … (the guarded form writes null).TO (116)A value slot stores a bare `$` reference as written: write `{source.id}` as { dialect: 'cel', source: 'source.id' }.assignments: [{ variable, value }]shape, a$Userpath that never resolved), the judge's remedy opens differently. The line names no envelope and points atos explain, so it never prescribes an envelope that would be stored as data. For a double brace it deliberately does not point at the build's own value-slot refusal. That refusal reads the outer braces as literal text, so its spelling is'{' + record.title + '}', not the hole the author meant; a test pins this as the control.{{ }}hole for each reference the engine binds. For any other$root, the remedy every refusal of one ends with: compute the value into a variable with anassignmentnode and write{{ v }}.{var}nor{{ }}resolves there. Write the value itself.". Where they are refused, and the list of text slots, moved to the entries.withinHintBudget,HINT_BUDGET = 200).Lists are no longer echoed (slices 11, 12, 14, 16 and 17's rule).
page-field-unknownno longer appendsObject fields: …; it names the nearest declared field with the package's one "Did you mean" helper (suggestName).os explaincarries the rest. Six ids gain an entry, so theirrule:line now carries the pointer:flow-double-brace-interpolation,flow-bare-dollar-reference,liveness-ledger-unreadable,page-field-unknown,page-section-count-not-multi-valueandlist-view-filters-in-views-mode.capability-reference-unknown's entry gains one sentence: a capability another installed package declares needs no change. The two flow entries share five paragraphs (the text slots, the literals, the CEL caveats, the filter operand, the no-envelope positions), written once. Every id already had a rule-id constant on the root barrel, so no published name is added andClause-②: noholds.Nothing else moves. Every
message, rule id, severity andpathis unchanged, and so is what each rule accepts or refuses. The rule-file hunks arehintexpressions, comments, the new hint helpers and constants inlint-flow-patterns.ts, and thesuggestNameimport.File surface: the claim's
The five rule files, their tests,
rule-explanations.ts(entries for these ids only, inserted beside the capability entry and away from slice 18's data-model entries), and.changeset/22161-s19-five-file-fix-lines.md. Pin sweep, repo-wide (git grepof each id, its constant and every distinctive old phrase, docs and examples included): onlypackages/lint/srctests pin these hints, so nopackages/cliorpackages/metadata-protocolrider was needed. Every flipped flow pin keeps its structural half: each envelope the line prescribes, put back in the slot, still passes the value-slot judge, the build door, the flow contract and this rule with 0 refusals. What left the line is asserted absent there and present in the entry.The runtime wire
lintFlowPatternsisCLI_AND_RUNTIMEwithruntimeTypes: ['flow']. Measured at the door withrunRuntimeAuthoringRules(a scratch probe of 12 writes, base rule sources vs branch), all 2xxadvisories[].hint, FROM → TO:flow-bare-dollar-reference: a value-slot$source.id681 → 116,$User.Id681 → 121,$User.Email742 → 198, a nested literal 1231 → 198, a legacy assignment 1030 → 198; a text-slot$User.Id767 → 144,$error.message114 → 83;flow-double-brace-interpolation: a value-slot{{ }}746 → 116, a notify literal 297 → 137, a value no slot reads 362 → 158.validateCapabilityReferencesandvalidateListViewModeareCLI_ONLY. Apagewrite runs 4 rules and neither page id fires there (0 findings, base and branch).lintLivenessPropertiesruns onemail_template,mappinganddatasourcewrites, butliveness-ledger-unreadablefires only when@objectstack/specships without a ledger file; not probed. No 422 changes.Verification (all at the merge head
bb6c6032dunless noted; heavy runs viaos-verify-lock.sh, verdict lines read)6db53acd6140 files / 6776 passed | 5 skipped; branchb8c9c4ac1140 / 6788 passed | 5 skipped; merge head 140 / 6794 passed. VERDICT 0 each.check-dts-emitted) +typecheck(tsc +check:test-typecheckOK, 2 files / 6 errors / 2 pinned): VERDICT 0 atb8c9c4ac1and at the merge head.--project unit), branchb8c9c4ac1: 302 files / 4498 passed, VERDICT 0.@objectstack/metadata-protocolwhole suite, branchb8c9c4ac1: 242 passed | 3 skipped files, 20598 passed | 19 skipped, VERDICT 0.@objectstack/specrepo project (--project repo, which readspackages/lint/srcas a text corpus), branchb8c9c4ac1: 63 files / 1070 passed, VERDICT 0.objectstack validate(built CLI), branchb8c9c4ac1, on app-crm / app-todo / app-showcase / app-multi-package: exit 0 each,rule:lines 9 / 7 / 68 / 3; none of the 7 ids fires on the apps.b8c9c4ac1,scripts/ablation-replace.mjsunder the lock, a shell trap restoringHEADby absolute path; the lint suite imports source, so there is no dist leg):HINT_BUDGET = 200→2000(anchor x1 → x0, replacement x0 → x1, bloba2a5a375ea3f→8e143fdfd2cd). Predicted before the run: exactly the two bound cases red. Observed:lint-flow-patterns.test.ts2 failed | 227 passed, exactly those two. Restored blob == HEAD,git diff HEADempty, status clean.node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack(no paths), 62 families, run one by one with each exit code captured before any pipe;--ranreconciliation in the report.Acceptance notes
main(6db53acd6) says 33 ids over 200 = 3 repo-gate (lint-startup-registry-verdict.ts) + 24 in the files slice 2 fenced (PR fix(lint): one-line verdicts for the widget, dataset, security-posture and visibility rules;os explain RULE_IDcarries their reasoning #22448) + 6 author-time outside the fence. Slice 16's ledger counted only the last group (13 then, 6 after slice 17), so the two counts were each right about a different population.os explainentry describes each such position, but cannot carry a per-string spelling. For a double brace there, the build's own refusal is no substitute (it keeps the braces as text, pinned above).Remaining for this card (census at the merge head, 26 over 200, by file)
data-model-rules.ts(3 measured):unique/legacy-organization-composite578,unique/unscoped-declared-index380,unique/double-declaration279. This is slice 18's file; slice 17 recorded 3 more of its ids as NOT MEASURED by the census.lint-startup-registry-verdict.ts(3, repo gate, not author-time):startup-open-vocabulary-verdict972,startup-verdict-assertive-wording972,startup-source-unparseable254.lint-flow-patterns.ts(12):flow-loop-body-uncontained800,flow-multi-write-unfiltered695,flow-try-catch-without-catch594,flow-decision-inclusive-overlap437,flow-approval-revise-target-not-service-owned412,flow-time-relative-antipattern397,flow-date-equality-filter379,flow-runas-unscoped372,flow-decision-mode-invalid295,flow-decision-unconditional-branch286,flow-error-label-not-fault239,flow-branch-label-unmatched224;validate-flow-template-paths.ts(2):flow-template-field-unprovisioned362,flow-template-lookup-traversal316;validate-page-field-bindings.ts(2):page-field-unprovisioned362,page-section-group-unknown279;validate-component-props.ts(1):component-props-invalid258;validate-filter-tokens.ts(1):filter-token-unknown259;validate-form-layout.ts(1):form-section-group-unknown275;validate-print-page-blocks.ts(1):print-page-block-unprintable362.content/docs/ui/react-pages.mdxtranscript carry from slice 15's landing record6136999237.🤖 Generated with Claude Code
https://claude.ai/code/session_01XK9otrEUnkWkwJQAnVeTk6
Generated by Claude Code