Repository navigation
fix(lint): the approval and flow advisories a flow save returns carry a user sentence in every platform locale - #33120
Conversation
…val catalog Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibymXZPShrjayTXHyCg
Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibymXZPShrjayTXHyCg
…l catalogs Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibymXZPShrjayTXHyCg
… the gate Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibymXZPShrjayTXHyCg
Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibymXZPShrjayTXHyCg
…odule top Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibymXZPShrjayTXHyCg
Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibymXZPShrjayTXHyCg
📓 Docs Drift CheckThis PR changes 1 package(s): 1 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
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 a3630a392db9c5ad0da0ce5f6835869d7f337175 && git checkout a3630a392db9c5ad0da0ce5f6835869d7f337175
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 5c005e0e42e207b073843b255248877b84442342 08d77c00f8eb3ca183bd4007ebd5e063029aba86 && git checkout -B drift-repro 5c005e0e42e207b073843b255248877b84442342 && git merge --no-ff 08d77c00f8eb3ca183bd4007ebd5e063029aba86
node scripts/docs-audit/affected-docs.mjs --json 5c005e0e42e207b073843b255248877b84442342
|
Keeps both catalog lines in finding-user-text.ts: the automation catalogs from this branch and the dashboard binding catalogs from main. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibymXZPShrjayTXHyCg
|
domain:spec#2 · os-tesla · session_01L9qibvfX5bawZKtfa6u7j9 维护者速读
席位意见:可以落地。 席位核对ACCEPT · seat
|
Requested by Tesla · project thread
Fixes #32836
Clause-②: no
Metadata-protocol: none
维护者速读
userTextParams字段,不改变哪些写入被拒、哪些通过;回滚即撤销本 PR。os validate --json/os build --json的 warnings 里会多出userTextParams键。validate-approval-approvers.user-text.ts(8 条审批提示,最贴近用户),再看finding-user-text.test.ts里按真实流程经保存门渲染的用例。pnpm --filter @objectstack/lint exec vitest run src/finding-user-text.test.ts,102 个用例全绿,每条都从真实流程经运行时保存门取出并逐语言渲染。What changes
Nineteen advisory rule ids that the save door returns on a flow write now carry
userTextParamsand a user sentence in all elevenPLATFORM_LOCALE_TAGS. Each rule file gets a*.user-text.tscatalog beside it, and the six catalogs merge intoFINDING_USER_TEXT_CATALOGthroughmergeUserTextCatalogs, the way #32655 landedvalidate-security-posture.user-text.ts.validate-approval-approvers.tsAPPROVAL_APPROVERS_USER_TEXTapproval-approver-type-unknown,approval-expression-invalid(itsinfoarm only),approval-approver-not-membership-tier,approval-approver-type-deprecated,approval-approver-type-unsupported,approval-approvers-may-resolve-empty,approval-expression-no-empty-policy,approval-escalation-reassign-no-targetvalidate-flow-trigger-readiness.tsFLOW_TRIGGER_READINESS_USER_TEXTflow-trigger-unknown-object,flow-input-unknown-object(advisory arm, no package closure),flow-input-object-less,flow-input-record-read-as-list,flow-draft-status-ambiguousvalidate-flow-template-paths.tsFLOW_TEMPLATE_PATHS_USER_TEXTflow-template-unknown-field,flow-template-lookup-traversal,flow-template-field-unprovisionedvalidate-flow-node-writes.tsFLOW_NODE_WRITES_USER_TEXTflow-node-write-unprovisioned-anchorvalidate-readonly-flow-writes.tsREADONLY_FLOW_WRITES_USER_TEXTflow-update-readonly-when-fieldlint-flow-credential-literals.tsFLOW_CREDENTIAL_LITERALS_USER_TEXTflow-credential-literaluserTextParams(flow, node, object, field, input names, plus small arm keys such asslate,locked,trigger,root,position). Rule ids,messageandhintare unchanged.approval-expression-invalid's error arm,flow-trigger-unknown-object/flow-input-unknown-objectunder a package closure) carry no params, so they render no user sentence.flow-credential-literal's sentence names where the credential sits (header, query parameter or input name) and never its value.authoring-rules.ts: thelintFlowCredentialLiteralsadapter keepsuserTextParamswhen it re-maps its findings (one spread, approved by the seat's surface amendment 6855561105), so the publish gate's advisory carries them.32836-advisory-user-text.md,@objectstack/lintpatch.Tests
finding-user-text.test.tsgains a shared harness and 25 cases from real flows:FINDING_USER_TEXT_CATALOG;undefined, no unfilled${, every shown name present, and no locale falling back to the English sentence; arms that differ (group vs manager slate, locked vs not, record vs schedule trigger, trigger vs variable root, header vs query vs input) render apart;runRuntimeAuthoringRules({ type: 'flow' }), checks the advisory's params, parses it underRuntimeAuthoringIssueSchemaand comparesuserMessageto the zh-Hans sentence;ヘッダー「Authorization」).validate-approval-approvers.unsupported-type.test.tsadds the same pins forapproval-approver-type-unsupportedunder its mocked binding table, including a gate advisory parsed for a ko-KR request.Acceptance notes
Re-measure. The card's table lists 27 ids; a static scan of the listed files finds 29 (action-body-writes 4, not 3; flow-trigger-readiness 5, not 4). Through the save door, 19 reach a user, all on flow writes. This PR writes catalogs and pins for those 19 only, as the seat ruled (it supersedes the amendment's "cover all 29" clause), and writes no dead catalog. Under #32835's Done-when alternative, the 10 ids that never reach the door:
runtimeTypes, so they default toflow, but a flow write's snapshot carries no hooks or actions. Measured through the gate:rulesRun1 for a hook write, 1 for an action write, 14 for an object-with-action write, and none of these advisories.hook-body-source-unparseable,hook-body-write-unprovisioned-anchor,hook-body-write-unknown-fieldaction-body-source-unparseable,action-record-write-discarded,action-body-write-unprovisioned-anchor,action-body-write-unknown-fieldhook-api-update-readonly-when-field,action-api-update-readonly-when-fieldemail-template-hole-grammar's warning arm (rung ④, a platform-prefixed option object) runs only whenliveUniverseis false; the registry setsliveUniverse: ctx.runtimeWriteType !== undefined, so at the door the same hole is an error.approval-approver-type-unsupportedhas no live trigger today (no binding isunsupportedsincequeuelanded), so its sentence is pinned only under the mocked binding table, as its existing message pin is.Agent-written sentences for the native-review round. Every non-English sentence in this PR is agent-written: 19 ids × 10 locales (zh-Hans, zh-Hant, es, ar, fr, pt-BR, ru, de, ja, ko), in the six
*.user-text.tsfiles above. Terms followui/packages/i18n(flow 流程 / 流程 / flujo / التدفق / flux / fluxo / поток / Flow / フロー / 플로우; field 字段 / 欄位 / … / 項目 / 필드; object 对象 / 物件 / … / オブジェクト / 개체). Theapproval-approvers-may-resolve-emptyandflow-draft-status-ambiguoussentences carry the most domain wording and are the best first read.Metadata-protocol.
none, following #32835's stated reading for its sub-cards. #32790 declaredadded/yesbecause it added a spec field (userMessage); this PR adds no spec field.Ruling grep (
ruling|Ruling-ref|maintainer|⛔across the surface, read before editing): approval approvers 14 (manager kept out of the expandable routes; never name an empty-slate outcome or default; tracker ids stay out of strings), flow trigger readiness 9 (#9612 ruling, #29425 ruling A, #7215 maintainer-ruled, ruling G), readonly flow writes 6 (the 2026-09-03 ruling: never say "INSERT is exempt"), flow template paths 1, credential literals 2 (never the value; no url-path promise),finding-user-text.ts2, flow node writes 0. The sentences keep every one of them; none is reversed.Serial. #32837 also adds one line to
finding-user-text.ts; whichever lands second merges main once and keeps both catalogs.Ablations (both red, both restored to HEAD and verified clean):
authoring-rules.tsspread: 4 credential gate tests red;userTextParams: { flow: flowName },at the draft-status push site: 2 tests red.Verification
Head
8b347e57, merged withorigin/mainat7c36f524.pnpm --filter @objectstack/lint exec vitest run: 202 files, 8692 tests passed (after the merge with main).pnpm --filter @objectstack/lint typecheckandtsc --noEmit: exit 0.node scripts/check-cli-command-ids.mjs: exit 0.@objectstack/metadata-protocol: 337 files passed, 7 skipped; 22799 tests passed, 36 skipped.@objectstack/objectql: 595 files, 12789 tests passed.@objectstack/cli(the 4 test files naming these rule ids, incl.flow-credential-literal-doors.e2e.test.tsandauthoring-rule-command-parity.test.ts): 63 tests passed.examples/app-showcasetest/author-time-advisories.test.ts: 2 tests passed.dispatch-gates.mjs --ranreconciles 63 derived, 63 run, 0 NOT-MEASURED, 0 UNRUN; the derivation at the merged head is identical.Gate readings that were not exit 0 on the first sweep
check:test-source-aliasexit 1:validate-approval-approvers.unsupported-type.test.tsloaded@objectstack/spec/systemand@objectstack/spec/apiinside a clocked body. Fixed in af4e1c7 (module-top imports); rerun exit 0.check-plugin-teardown-shape --self-testexit 3: shallow clone could not reach the pinned fixture commit; after fetching it, exit 0.check:docs-transcript-driftexit 1 andcheck:dts-closureexit 1: ran while a closure build was rewritingspec/dist; rerun exit 0.check:dual-build-cjs-loadsexit 3 andcheck:lean-entry-closureexit 3: prerequisite (no dist); afterpnpm build, exit 0.check:type-check-debtexit 124: my 600s per-gate timeout; rerun without it, exit 0.Generated by Claude Code