fix(automation, audit): runtime strings state each decision in words instead of a tracker number (stage 4) - #21472
Conversation
…instead of a tracker number (stage 4) The service-automation refusals, prescriptions, log lines and run-object field help, and the sys_activity type help, drop their tracker numbers; where the sentence leaned on the number it now says what was decided. Claude-Session: https://claude.ai/code/session_01DiCSbmJrkzNhuEAier4VoJ Co-authored-by: Claude <noreply@anthropic.com>
…sed source text The es-ES, ja-JP and zh-CN leaves were byte copies of the English source; they were emptied and refilled by the extract config's own documented command (scripts/check-i18n-bundles.mjs --write --filter=plugin-audit), which also rewrote en and recorded the new source digests. Claude-Session: https://claude.ai/code/session_01DiCSbmJrkzNhuEAier4VoJ Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DiCSbmJrkzNhuEAier4VoJ Co-authored-by: Claude <noreply@anthropic.com>
…age 4 (service-automation, plugin-audit) Recomputed with `node scripts/check-doc-authoring.mjs --census-ledger` on the tree with origin/main merged in: 58 lines deleted, 0 added; the service-automation entries and the plugin-audit entries other than audit-writers.ts go to zero, no other row moves. Adds the stage-4 changeset. Claude-Session: https://claude.ai/code/session_01DiCSbmJrkzNhuEAier4VoJ Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DiCSbmJrkzNhuEAier4VoJ Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DiCSbmJrkzNhuEAier4VoJ Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 2 package(s): 22 hand-written doc(s) name something this change touched — list omitted above 15 rows. Re-derive on the tree named below: ⛔ 7 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails. What this run could not see
Coarse fallback — 12 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 ab498c8c92e369a84c5e9b06dd2d8c58278bdff8 && git checkout ab498c8c92e369a84c5e9b06dd2d8c58278bdff8
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin aa4632235ba571ef800b95e6bc18d00a30aa1d57 f300a255b0e20023e6f6e0e131fc5b7b261ac4d8 && git checkout -B drift-repro aa4632235ba571ef800b95e6bc18d00a30aa1d57 && git merge --no-ff f300a255b0e20023e6f6e0e131fc5b7b261ac4d8
node scripts/docs-audit/affected-docs.mjs --json aa4632235ba571ef800b95e6bc18d00a30aa1d57
|
Part of #20751
Clause-②: no
Stage 4 of the
domain:serviceslane under the maintainer's A / A ruling (5902360492): theservice-automationandplugin-auditstrings. The card stays open for the later stages, so this PR carries no closing keyword. Text only: no status, errorcode, field, route, export or control flow moves (AST skeleton reads SAME for 10 of 10 changed sources, below).What this does
The two packages' refusals, prescriptions, warnings, log lines, the
sys_automation_run/sys_flow_dispatchfield help and description, and thesys_activitytypehelp (with itses-ES,ja-JPandzh-CNleaves) sent the reader to a tracker number for the reason behind them. In form D, as stages 1 to 3 applied it, the number goes. Where the sentence already said what was decided, only the citation goes. Where it leaned on the number, it now says the decision in words.All 38 ledgered occurrences in this stage's surface (claim
5959898258), re-derived from the ledger onorigin/mainat9b7a0ef3:service-automation33 (25 pairs, 9 files),plugin-audit5 (5 pairs, 5 files:objects/sys-activity.object.tsand its fourtranslations/*.objects.generated.ts). They sit in 37 string sites. The sixthplugin-auditledger entry,audit-writers.ts(one occurrence), is in a file excluded at file level (open PR #21436) and stays for a later stage. None of the three excluded files (audit-writers.ts,stored-metadata-body-migration.ts,stored-metadata-hash-migration.test.ts) is touched.Rewritten in words
Author- and administrator-visible text first, log lines last. Line numbers are at the head.
engine.ts:196-205, thefieldValuesrefusal prescriptions oncreate_recordandupdate_recordfieldskey rather than two spellings"cfg.fields ?? cfg.fieldValuesalias in the executor; the design review declined it: correct the metadata at the source and keep a single strictconfig.fieldscontractengine.ts:210-213, the screen fieldvisibleIfrefusal prescriptionrequiredfield meant to stay hidden then blocks the screen from ever being submitted"requiredfield the author meant to hide rendered unconditionally and the screen flow could not be submitted;visibleWhenwent into the contract and is forwarded verbatimengine.ts:10272-10274, the undeclared-config-key refusalconfigSchemagot a Zod written from its executor and a two-way key-set reconciliation (CRUD, screen and map surfaced seven read-but-undeclared keys, all declared)builtin/template.ts:192, the unknown value-expression function errornullrewrite of an unknown function name became a loud, named errorsys-automation-run.object.ts:169,node_typehelprefuseGatedResumeenforces it: the gate is keyed on what the run is parked on; anapprovalpause continues only throughApprovalService, while ascreenpause stays open to its flow runnersys-automation-run.object.ts:234trigger_typeand:288trigger_record_idhelpsys-automation-run.object.ts:324,steps_jsonhelpplugin-auditobjects/sys-activity.object.ts:116-121,typehelp, and its four locale leavesplugin.ts:1680-1689, the inert-connector warningproviderare catalog descriptors (descriptor-only contract) ... An entry that names aprovideris a connector instance instead: that provider's installed executor materializes it into a live connector (ADR-0097)"enabled: falsemarks a catalog-only entry) and 2977's (ADR-0097 implemented: a provider-bound entry is materialized at boot by a generic executor). The old sentence said provider-bound instances were "tracked in" 2977, which has since landed;findInertDeclaredConnectorsalready skips provider-bound entries, which the new wording now saysplugin.ts:1143-1146, debugregisterFlowthrough an opt-in object-schema resolverplugin.ts:1184-1187, debugrunAs:'user'resolves the triggering user's positions and permission sets at run setupplugin.ts:1214-1217, debugconfig.expand, expanded engine-side as the run's own identity so the referenced object's RLS/FLS holdsCitation only (the sentence already stated the decision)
builtin/connector-nodes.ts:72(3017, "Dispatch is unavailable until its upstream recovers; the platform retries automatically." — ADR-0097 quotes "the platform retries automatically", which stays verbatim).builtin/parse-config.ts:112(4277, "config does not satisfy the X contract ... The declared contract is the node type's configSchema (the Studio form) and the X config Zod").builtin/screen-nodes.ts:336(1870, "no function named 'X' is registered. Register it viadefineStack({ functions }), or fix the name").engine.ts:181,:184,:187,:191, the bulk-intent guidance (5393, "Bulk intent ismulti: true... so the concept keeps one name from node config to driver call ... a predicate write is refused by the engine rather than silently widened"; "Translating that declaration intooptions.multion the engine call is the executor's job").engine.ts:4026(3017, "the materializer retries with backoff").engine.ts:6069,:6073(3760, 1888: "its data operations will be REFUSED ... Declare runAs:'system' ... a record-change flow fired by a system write carries no user either (ADR-0049)").engine.ts:10268(4277, "Flow 'X' rejected: N undeclared config key(s)").engine.ts:11326(4414, "The branch selection is IGNORED and every out-edge is evaluated instead ... mark the fallback edgeisDefault: true").runtime-identity.ts:113, theAUTOMATION_UNSCOPED_RUN_DATA_ACCESSrefusal (1888, 3760: "refusing a data operation ... would execute UNSCOPED ... DeclarerunAs: 'system'"; it keeps "(ADR-0049)"). Itscodeis unchanged.plugin.ts:1831,:2074,:2086,:2143(3017: "pending retry cancelled", "until a retry succeeds", "retrying with backoff, attempt N", "next retry in Nms").sys-flow-dispatch.object.ts:86(10220, "one row per claimed dispatch key ... so a re-scan, a rebuilt kernel or an operator replay never re-launches a flow for a window it already delivered").Every cited card (21: 1870, 1888, 1928, 2419, 2585, 2612, 2977, 3017, 3356, 3475, 3528, 3760, 3801, 4045, 4277, 4414, 5393, 7533, 10220, 11060, 11507) was read through REST, body and every comment, before its string was rewritten. 2419 is a pull request; its closing comment carries the decision. 11060 and 11507 answer 404 on the issue endpoint while their comment threads read normally; the rulings and dev reports in those threads carry the decisions.
Translations
es-ES,ja-JPandzh-CNsys_activity.fields.type.helpleaves were byte copies of the English source, recorded as such in each locale's*.source-hashes.generated.ts. No translated text was written by hand: the three leaf values were emptied (key kept) andnode scripts/check-i18n-bundles.mjs --write --filter=plugin-audit(the extract config's documented command,--fill=default) refilled them from the revised source, rewroteen, and recorded the three new digests. The same route the original ruling's PR took for these leaves.sys-activity.object.ts). Tracker numbers left in the package's locale bundles: 0.Ledger (
scripts/doc-authoring-prose-id.baseline.json)At dispatch no open PR held this file. While this branch was being built, PR #21462 (
domain:specstage 1 of #20749) opened and took it, so this PR waited: the branch was finished and green, and it was opened only after #21462 merged (7e7e64b1, about 40 minutes of waiting). Thenorigin/mainat7e7e64b1was merged in (no rebase), and the ledger was recomputed on that tree withnode scripts/check-doc-authoring.mjs --census-ledger(exit 0, no growth refusal) into a scratch file. The recomputed file is byte-identical to git's textual merge of the two sides. Againstmainthe diff deletes 58 lines and adds none: exactly the 14 file blocks of this stage. Every other row is unchanged (a scripted comparison: 14 keys moved, all of them this stage's, each to absent). At PR-open time no other open PR touches the file.service-automationplugin-auditaudit-writers.ts, excluded)9b7a0ef3)#21462(7e7e64b1)pnpm check:doc-authoringat the head: "sibling-package prose ids hold the baseline — 118 pinned site(s) across 39 file(s), 86309 string(s) read in 1253 parsed source(s), no growth, no burn-down unrecorded". No gate is added or loosened;scripts/check-doc-authoring.mjsis untouched.Changeset
.changeset/20751-services-strings-stage4-state-the-decision.md:patchfor@objectstack/service-automationand@objectstack/plugin-audit. Measured after building: the new sentences are in each package's built output (service-automationdist/index.jsanddist/index.cjs;plugin-auditdist/index.jsanddist/index.mjs). A TypeScript scan of every string literal and template text in the built output finds 0 tracker ids inservice-automation, and 2 inplugin-audit, both the excludedaudit-writers.tsoccurrence (once per build format). Control: the same scan reads 86 inplugin-security's built output.Text-only proof
A TypeScript-AST skeleton of each changed non-test
.tsfile, where every string literal and template text is a placeholder, a run of adjacent string operands of a+chain is one string (only its embedded expressions are kept), identifiers and numbers keep their text, and comments are never read.9b7a0ef3against the head: 10 of 10 SAME (the two merges fromorigin/maintouched neither package). Controls on scratch copies ofplugin.ts, each mutation's marker counted once on disk first: a one-identifier rename reads DIFF; a text-only change reads SAME; a re-split of one template into two concatenated pieces reads SAME.Pins
Assertions that found a message by its tracker number now find it by what it says. No
codeorstatusassertion was touched; none of these strings is a coded refusal.builtin/config-unknown-keys.test.ts:97: thevisibleIfprescription by "blocks the screen from ever being submitted" instead of the id.builtin/decision-branch-routing.test.ts:210: the unclaimed-branch warning by "The branch selection is IGNORED" instead of the id.connector-degrade-cause.test.ts:185and:274: the degrade error by "retrying with backoff, attempt 1." and the husk warning by "stays absent from the connector registry until a retry succeeds"; the three hand-built fixture messages in the same file (:376,:396,:407), which mirror the production text, drop the id too.connector-descriptor-audit.test.ts:134: the inert-connector warning by "catalog descriptors (descriptor-only contract)".degraded-register-cause.test.ts:212: the degraded-registration warning by "the materializer retries with backoff"; its fixture message (:407) drops the id.plugin-auditobjects/sys-activity-type-open-vocabulary.test.tsasserts thetypehelp by three markers (built-in,open vocabulary,ADR-0052), all kept; no edit needed.The five edited test files were run with the verbose reporter (5 files, 50 tests passed) and every re-pinned case is listed as passed.
Tests
All through
scripts/pm/os-verify-lock.sh, every verdictVERDICT command-exit 0, at the headf300a255:turbo run build --filter=./packages/* --filter=./packages/*/*(71/71).@objectstack/service-automation: 166 files, 2053 tests passed;@objectstack/plugin-audit: 38 files, 618 tests passed.typecheckfor both, includingcheck:test-typecheck: OKfor each.Gates
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands(no paths) atf300a255(24 paths vs merge base7e7e64b1, 195 changed lines): 74 commands, run one at a time from the worktree, each exit code recorded before any pipe; 74 exit 0.--ran: "74 derived famil(ies) accounted for — 74 run, 0 NOT-MEASURED (a DERIVED zero — all 74 recorded an exit code and none of them is 3)". The same 74 also ran green at1af6bed2, before the last merge.check:i18n: "OK (9 package(s) — all bundles in sync, no undeclared authoring keys)";check:i18n-stale-fill: "OK (10 bundle set(s) — no new stale fills, 0 baselined)";check-issue-citations: "no issue citations added against 7e7e64b (17 file(s) read)";check:nul-bytes: OK, 9807 files;check:type-check-debt: "none above its recorded number";check:dual-build-cjs-loads: 105 require entry points across 66 packages load;check:dts-closure: 71 built packages, 167/167;check:sourcemap-no-sources-content: 68 packages, 524 maps;check:published-files: 69 publishable packages.f300a255: the eleven declared wide-population families (check:init-service-contract,check:live-db-isolation,check:meta-type-normalized,check:optional-error-sink,check:resume-authority-declared,check:route-envelope,check:runner-env-posture,check:settings-bind-window,check:startup-registry-verdict,check:verify-stand-in,check:wildcard-fallthrough) and the artifact-roster families whose roster sits under one of this PR's directories (check-changeset-fixed,check-published-list-mirrorsand its self-test,check:authz-resolver,check:console-injection,check:error-code-casing,check:filter-alias-parity,check:published-readme-exports,check-dts-references --self-test;check:engine-double-contractandcheck:i18n-stale-fillare in the derived set). The path-scheduled CI jobs and the type-check lanes are CI's.pnpm lint(eslint . --no-inline-config, repo-wide, not narrowed) atf300a255: exit 0.origin/mainmoved by two commits after the ledger recompute (49524f69,packages/rest;aa463223,packages/specand object-grid surfaces). Neither touches the ledger,service-automationorplugin-audit; the PR's CI merge ref and the queue carry them.Acceptance notes
Noted, not filed:
packages/runtime/src/domains/automation-put-post-error-parity.test.ts(lines 57-70, assertion at line 247) andautomation-register-error-class.test.ts(lines 87-100, assertion at line 308) each rebuild the undeclared-config-key refusal in a test fake, copied fromengine.tswith both old ids, and asserttoContainof the 4277 id on their own fake's message. They stay green (the fake is self-consistent) but no longer mirror the engine's text.packages/runtimeis outside this stage's surface. Carrier: none.plugin-audit/src/audit-writers.tskeeps its one ledgered occurrence (excluded file, open PR fix(metadata-protocol)!: a metadata body's stored content hash is served and compared only in keyed form, never copied, never evaluated (#21207) #21436); it is left for a later stage.plugin-audittest files carry the 11507 id in failure-message text; test files are outside the ledger.Generated by Claude Code