Repository navigation
fix(spec): author-facing describes and refusals drop service-interface names, ruling dates and foreign example ids - #22125
Conversation
…rface names, ruling dates or foreign example ids Studio renders spec describes as form help (/meta/types schema + form) and the notify node's Template help from the service-automation descriptor; refusals are read at the save and install doors. The rationale those strings carried (II18nService/IEmailService names, "maintainer ruling <date>", "ruled <date>") moves into the code comments beside them; MANIFEST_ID_EXAMPLES becomes com.acme.crm / org.example.help-desk, and the package-id refusal leads with a product-words headline and names the key as a locator after it. WIP: generated artifacts not yet regenerated. Claude-Session: https://claude.ai/code/session_01RPo7FUd6bSnAfkWMAKi848 Co-authored-by: Claude <noreply@anthropic.com>
…itBehavior describe for a governed change The top-level `submitBehavior` describe is projected into skills/objectstack-ui/references/react-blocks.md by gen:react-blocks, a governed surface, so its ruling date stays in this wording sweep and the deferral is recorded beside it. Claude-Session: https://claude.ai/code/session_01RPo7FUd6bSnAfkWMAKi848 Co-authored-by: Claude <noreply@anthropic.com>
…the email-template Identity help `pnpm i18n:extract` output; the zh-CN / ja-JP / es-ES values were re-translated by hand in the first commit of this branch. Claude-Session: https://claude.ai/code/session_01RPo7FUd6bSnAfkWMAKi848 Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 3 package(s): 33 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 — 139 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 7bd05e7d0dd0bccd68fc6e9c13c1e1a6c7637d9d && git checkout 7bd05e7d0dd0bccd68fc6e9c13c1e1a6c7637d9d
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 54ace18c669a776c7e849708039c7876ac534cee 0262046319a13c871d5427ac8cc4181ce54a3c5e && git checkout -B drift-repro 54ace18c669a776c7e849708039c7876ac534cee && git merge --no-ff 0262046319a13c871d5427ac8cc4181ce54a3c5e
node scripts/docs-audit/affected-docs.mjs --json 54ace18c669a776c7e849708039c7876ac534cee
|
…thor-strings-internal-refs
…rence left behind "(one dialog, not two —)" read as a truncated sentence in Studio's action inspector; the ruling it once cited stays in the docblock above the key. Pinned on the authoring-shape JSON Schema Studio renders: no dash left dangling before a close paren, no ruling date, no service interface, no tracker id. Claude-Session: https://claude.ai/code/session_01RPo7FUd6bSnAfkWMAKi848 Co-authored-by: Claude <noreply@anthropic.com>
gen:schema && gen:docs after merging origin/main (54ace18): the only delta is the action description row. Main's regenerated docs reproduce byte-for-byte from the merged sources. Claude-Session: https://claude.ai/code/session_01RPo7FUd6bSnAfkWMAKi848 Co-authored-by: Claude <noreply@anthropic.com>
Contract reviewServed-tier: Read-only review of PR #22125 against Check-runs on the head. First read at 2026-10-07T23:31:32Z: 46 runs, 45 completed (38 success, 7 skipped), 1 ① Derived judgmentsAccept-set: unchanged, and the PR says so correctly. Every edit is to a
Refusal ② Semver level
Clause-②: no — correct. No parse accepts or refuses anything it did not before, so neither ③ Boundary flagsDev flags and open questions, each with its answer:
Escalated to the seat (none blocks this verdict):
Implemented-by: VERDICT: PASS Generated by Claude Code |
Part of #22093
Clause-②: no
Wording only: no schema, key, type, export or error-code change. Patch changeset for
@objectstack/spec,@objectstack/service-automationand@objectstack/platform-objects. objectui#11785 is the Studio half (splitting an author message from the detail); this PR changes the server-side strings only. The card keeps two named remainders, listed under "Remainder of the card and its route" below.What changed
Form help and refusals that an author reads no longer carry service-interface names (
IXxxService.method()), ruling dates ("maintainer ruling DATE", "ruled DATE") or another product's example ids. The rationale they carried moves into the code comment beside each string. Each describe and refusal still states the rule, why it exists and the repair.How "author-facing" was measured (instrument and radius)
Studio reaches these strings through five routes. I measured each one at
a543e244f:/meta/typesschema: everyDEFAULT_METADATA_TYPE_REGISTRYtype, derived asmetadata-protocolderives it (z.toJSONSchema,unrepresentable: 'any', with theio: 'input'retry)descriptionin all 27 type schemas/meta/typesform: all 17METADATA_FORM_REGISTRYlayoutsdescription/helpText/label/placeholder/hintManifestSchemaclient-side (objectuipackage-schema.ts)descriptionconfigSchemafromGET /api/v1/automation/actionsconfigSchema(13 files)packages/spec/src(1284 files, 80190 string parts, comments excluded)The class patterns were: interface
\bI[A-Z]\w*(Service\|Driver\|Engine\|…)\b; ruling\bruling\b\|\bruled\b\|\b20\d\d-\d\d-\d\d\b; foreignsteedos\|superset\|salesforce\|apache\|airtable\|….Positive control: both strings the filer measured are found.
service-automation/src/builtin/notify-node.ts:203, as both an interface hit and a ruling hit. The spec copy is found by R5 atio-node-config.zod.ts:250.com.steedos.crmis found by R5 atmanifest.zod.ts:283.R1 to R3 found neither string (needle count 0). So the Studio-rendered Template help is produced by the service-automation descriptor, not by the spec describe. That is why the producer side is changed too.
After the change, R1 to R3 hold no interface, ruling or foreign-id hit. The one exception is the "Airtable parity" wording (see Acceptance notes). The needles
II18nService,IEmailService,com.steedos.crmandmaintainer rulingcount 0. The R5 hit count drops by 22.Every string changed
Lines are at
a543e244f. Before is the internal reference that was removed; After is what replaced it. No changed string carried a tracker number, so no tracker number moved.services/service-automation/src/builtin/notify-node.ts:203, notifyconfigSchema.properties.template.descriptiontemplate:in the descriptorspec/src/automation/io-node-config.zod.ts:250,NotifyConfigSchema.templatedescribetemplate(it already named both; one sentence added)spec/src/kernel/manifest.zod.ts:283,MANIFEST_ID_EXAMPLESPOST /api/v1/packages)'com.steedos.crm', 'org.apache.superset''com.acme.crm', 'org.example.help-desk'manifest.zod.ts:305,manifestIdRefusalmanifest.id. Expected reverse-domain notation ('com.steedos.crm', 'org.apache.superset') — …"manifest.id) is written in reverse-domain notation, like 'com.acme.crm' or 'org.example.help-desk' — …", with the rule and suggestion arm unchangedmanifestIdRefusalmanifest.zod.ts:360-361,@exampleonidcom.steedos.crm,org.apache.supersetcom.acme.crm,org.example.help-deskspec/src/data/field.zod.ts:1142,requireddescriberequiredfield.zod.ts:1170,multipledescriberadioby the narrower 2026-08-22 ruling … (maintainer ruling 2026-08-18)"radioincluded, is REFUSED at parse …"multiple(new Declarability paragraph)spec/src/ui/view.zod.ts:1175/:1221,GROUPING_FIELD_RULINGin the padded grouping-field refusalview.zod.ts:3444, form-view fieldvisibleWhendescribeview.zod.ts:3655, sectioncollapsibledescribeview.zod.ts:3663, sectioncollapseddescribecollapsed: truealone is a correct way to say "collapsed by default""view.zod.ts:3715, form-view sectionvisibleWhendescribeview.zod.ts:3959,SUBMIT_REDIRECT_RULINGin sevensubmitBehavior.urlrefusals (:3988,:3993,:4003,:4010,:4018,:4029,:4039)view.zod.ts:4097/:4123,FORM_VIEW_FEATURES_RULINGin thefeatures.*predicate refusalview.zod.ts:4444, redirect-armurldescribecheckSubmitRedirectUrlcommentspec/src/ui/page.zod.ts:941(kind) and:990(source) describeskind(new) andsource(already)spec/src/system/email-template.form.ts:19, Identity section help. Its three translated values inplatform-objects/src/apps/translations/{zh-CN,ja-JP,es-ES}.metadata-forms.generated.ts:2183are hand-written, andenis regenerated bypnpm i18n:extractdescription:spec/src/data/filter.zod.ts:475, null ordering comparand refusalfilter.zod.ts:564,{ $field }in a list position refusalfilter.zod.ts:589, null list member refusalfilter.zod.ts:801, blank$betweenbound refusalspec/src/ui/action.zod.ts:985, actiondescriptiondescribe (added in patch round 1)io: 'input') derivation; the action Description help objectui#11785 measureddescription(already cites the ruling; one sentence added)The regenerated
content/docs/references/**files follow from rows 2, 6, 7, 9 to 12, 15, 16 and 22.Remainder of the card and its route
This PR delivers the card minus two named rows. It is therefore
Part of #22093, and the card stays open for both.submitBehaviorrow.view.zod.ts:4478, the top-levelsubmitBehaviordescribe, keeps "(ruled 2026-08-11)".gen:react-blocksprojects this describe intoskills/objectstack-ui/references/react-blocks.md, which is a governed Tier H surface, so changing it here would make this whole sweep a Tier H landing. Measured: the regenerated skill file differs in exactly that one row.react-blocks.mdrow and its reference-docs row, landed on the maintainer's approval.sys_emailfield help namingIEmailService.send.packages/platform-objects,en.objects.generated.ts:2500and:2508. The source is in thesys_emailobject definitions.*.objects.generated.tsbundles, so folding it here would put two PRs on those bundles at once.Pins
Refusal
codeis asserted with the sentence:manifest.test.tsassertsinvalid_format.view-form-features-root.test.tsassertscustom.Negative pins on what the author reads. No interface name, ruling date or foreign id appears in:
io-node-config.test.tsnotify-node.test.ts, on the Studio-served descriptor textmanifest.test.ts. Its headline sentence carries nomanifest.id, the key is still named as a locator, and there is no steedos/superset/apache.filter.test.tsview-form-features-root.test.tsview-submit-redirect-url.test.tsPatch round 1:
action-description.test.ts. It derivesActionSchemathe way/meta/typesserves it (io: 'input') and asserts three things about thedescriptionhelp:Pins that changed direction. These earlier pins asserted that the date was present:
view-submit-redirect-url.test.ts, 7 assertions: "cites the ruling so the refusal is traceable"view-form-features-root.test.ts:68filter.test.ts:644io-node-config.test.ts:347and its2026-09-01pinThey are now negative pins.
filter.test.ts:661used the date as its discriminator between two messages. It now discriminates on the blank-bound headline.No whole-prose pin was added.
Where the ruling dates in refusals come from (lineage)
This PR reverses no ruling.
Tests and gates
Patch round 1, on the merged head
026204631.54ace18c6withbash scripts/pm/os-regen-merge.sh.75cec8cd1, parents34bf72933and54ace18c6. There were no conflicts.flow-edge-unresolved-or-repeated-refused,sys-presence-organization-column-retiredandsys-job-organization-column-retired.pnpm --filter @objectstack/spec buildpassed.gen:schemaandgen:docspassed.service-automation^...closure build (spec excluded) passed.pnpm --filter @objectstack/spec exec vitest run --maxWorkers=2over 26 targeted files (round 0's 25 plusaction-description.test.ts): 26 files, 2475 tests passed. This is a declared narrowing; CITest Coreruns the full suite.notify-node.test.ts, 16 passed.src/apps/translations/*.test.ts, 24 files, 430 passed.@objectstack/spectypecheckpassed.pnpm --filter @objectstack/spec check:generatedreports all 15 generated artifacts up to date (react-blocks and api-surface included).action.zod.tswent back to the54ace18c6bytes; landing confirmed bygrep -c= 1.action-description.test.tswent red: "carries no residue of a stripped reference".34bf72933):a543e244fbytes.notify-node.test.ts. Every red is a pin this PR added or flipped.pnpm exec eslint --no-inline-config --format jsonover the 20 changed lintable files at026204631: 20 files, 0 errors, 0 warnings.eslint.config.mjsmatches**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}minusNEVER_LINTED.parserOptions.project, see its note near line 328), so this diff cannot move the verdict on any file it does not touch.node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackat026204631derived 113 families (30 paths against merge base54ace18c6).check:skill-examples,check:dual-build-cjs-loads,check:i18nandcheck:type-check-debt. In round 0 each exited 3 (PREREQUISITE NOT MET).check:type-check-debt's re-measure is a 45-task workspace build and is not run outside the verify lock.--ranreconciliation: 113 accounted, 109 run, 4 NOT MEASURED (claimed), 0 unrun.Acceptance notes
stack.zod.ts:458-459(IJobService,IEmailService.sendTemplate):defineStackcollection describes. R1 to R3 do not serve them, and they are not refusals.data-engine.zod.ts:165,190(IDataEngine.find())hook.zod.ts:1269(IScopedContext)query.zod.ts:429driver.zod.ts:287-388refusals (IDataDriver)automation-api.zod.ts:452execution-context.zod.ts:441("the 2026-09-03 ruling"):preserveAuditis server-constructed and never authored.plugin-rest-api.zod.ts:138("ruling record, 2026-09-01"): a tombstone onRestApiEndpointSchema. Its own comment records that nothing parses that schema outside its unit tests, so no door reaches it.component.zod.ts:365("Since the console release of 2026-08-21 (c86185eb5)"): a release date and a commit sha, not a ruling.action.zod.ts:1139and:2157page.zod.ts:93view-grouping-query.ts:433context.zod.ts:50protocol.zod.ts:1681endpoint-publish-gate.ts:368,416error-code-ledger.zod.tsnotespage.zod.ts:911,page.form.ts:113,view.form.ts:164, plusview.zod.ts:1706,page.zod.ts:647andcomponent.zod.ts:1766. It is a design note naming a competitor, not an example id.export.zod.ts:292andobject.zod.ts:1528are comparisons, not ids.src/migrations/**, about 1,240 dated or "ruling" hits: upgrade-guide records, not a form or a door.manifest.zod.ts:546, TSDoc@exampleondependencies(@steedos/plugin-auth): TSDoc only.packages/core/src/artifact-packages.ts:114cites that exact example, so changing it moves a comment in core.sys_emailfield help namingIEmailService.sendis the second named remainder; see "Remainder of the card and its route".9990f9e(grep forII18nService,IEmailService,steedos.crm,Invalid package id).Generated by Claude Code