You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Public form thank-you text cannot name the record it created: no template slot, and the submit answer carries the id only #28005
Filing gate: ③ triage-directed. The order on #27398 (rows 2–3) said: take what is ui-only, card the rest. The card thread read the code on current main (report 6517203519, out_of_scope_findings). Row 2 is taken in PR #28003.
Reach: web-to-case and any public form whose visitor needs a reference (a case number) after submit (#27398 row 3).
Reader who acts: domain:spec first, because it needs a contract decision before any code. Then a domain:server card for the submit answer, blocked by it, then ui interpolation.
Duplicate search: search_issues "form submitBehavior thank-you message translation or record number interpolation public form" → no open card.
Observed
The confirmation panel shows the authored title and message verbatim (ui/apps/console/src/components/FormPage.tsx).
The spec's thank-you member (packages/spec/src/ui/view.zod.ts) declares them as plain strings with no template slot. The redirect member already interpolates declared record fields as {{record.FIELD}}.
POST /api/v1/forms/SLUG/submit answers { id } only, on purpose. Its comment (packages/rest/src/form-routes.ts) says the stored row can carry values an elevated beforeInsert / afterInsert hook derived from records the anonymous form grant may never read, so the answer echoes nothing the insert stored.
Decision needed (triage routes it)
A: the thank-you text may name declared fields, and the answer carries exactly the fields the text names. This accepts that trade-off for author-named fields.
B: the slot admits only engine-generated fields (autonumber), and the answer carries only those.
C: will not do; keep the id-only answer.
A or B is a template slot (contract review owed) plus a served answer field (Metadata-protocol added).
Dedupe words: thank-you record number, public form submit answer id only, submitBehavior interpolate record, case number thank-you.
Ruled: B · 2026-10-31T15:11Z · stays domain:spec and pm:queue, and is dispatched next by spec seat 1.
The maintainer said 「同意」 at 2026-10-31T15:10Z. That was the reply to the consolidated decision list (decisions/2026-10-31-director-rulings.md, item 1, recommendation B), which he accepted in full as recommended.
What B means:
Slot. The public form thank-you title / message gain a template slot. It admits only fields the engine generates on insert: autonumber and any other engine-generated type the spec already names as such. A field a beforeInsert / afterInsert hook could derive never enters the anonymous page.
Answer.POST /api/v1/forms/SLUG/submit carries id plus exactly the engine-generated fields that the thank-you text names, and nothing else. The comment in packages/rest/src/form-routes.ts about elevated hooks stays true.
Order.
The spec comes first: slot syntax, the authoring refusal of a non-engine-generated field, and the answer shape.
The server comes next and fills the answer. That is a domain:server card, blocked by the spec PR.
The UI comes last and interpolates in FormPage.tsx.
Out of scope: option A (any declared field) and C (id only).
Freshness gate: this card had no comment before this one, and its body has not been edited since it was filed.
Claim: PM loop round 8 · 2026-10-31T15:16Z
Session: session_01L9qibwb6hBqszPTYJobitm
Account: os-tesla
Branch: claude/project-thread-i0l9sb (card thread; the platform assigns the thread's branch and it can push only that one, written as measured instead of claude/issue-28005-<slug>)
Worktree: objectstack-issue-28005
Domain: domain:spec
Seat: domain:spec#1
Card thread: session session_01L9qibwKTredm7FjB4Z6DeX; the dispatch order is in the seat's project, frame + card file.
File surface: packages/spec/src/ui/view.zod.ts (thank-you title/message slot), the authoring-check site as measured (spec or packages/lint/src), the REST submit-answer schema + generated artefacts, tests, changeset. ⛔ packages/rest/src/form-routes.ts and FormPage.tsx are out (server and ui halves). Stop on breach; explain in the report.
Container & model: S, mode:thread, model: TIER_DEFAULT (new slot + served answer shape, so a contract review is owed), effort: high
Clause-②: yes (widening)
Metadata-protocol: added
Responsibility: a public form's thank-you panel cannot name the record it created (a case number) | a {{record.field}} slot admitting only runtime-owned field types (RUNTIME_OWNED_FIELD_TYPES), and a declared submit answer carrying only those | web-to-case visitors and public-form authors
Thread-read: 6545210989
Premise: holds. On main the thank-you title/message are plain z.string(), the submit answer is { id }, and RUNTIME_OWNED_FIELD_TYPES is ['autonumber'].
Serial constraints cleared: none. This is the spec half only. The server and ui cards follow after this PR is up.
{
"issue": 28005,
"status": "done",
"branch": "claude/project-thread-i0l9sb",
"pr": "https://github.com/objectstack-ai/objectstack/pull/28440",
"session": "session_01L9qibwKTredm7FjB4Z6DeX",
"premise_still_valid": true,
"summary": "Spec half of ruling B (Part of #28005). The thank-you title/message take .regex(THANK_YOU_TEXT_RE): every brace must be a {{record.field_name}} token (the redirect token, one grammar); checkThankYouText words the refusal. That projects as a JSON Schema pattern, so there is no dropped-refinement row. thankYouRecordFieldNames(submitBehavior) is the one reading of the named fields. PublicFormSubmitResponseSchema { id, fields? } is strict, beside CreateDataResponseSchema. The lint rule validateThankYouRecordFields (thank-you-record-field) is gating on all three commands and on the publish gate for view and page writes; it judges every form view shape and page object-form panels, and admits a name only when its field's type is in RUNTIME_OWNED_FIELD_TYPES. Mechanism assumptions measured: all four hold, and the redirect token is cross-checked nowhere.",
"tests": "New: spec view-submit-thank-you-record-slot.test.ts 15/15, public-form-submit-response.test.ts 4/4, lint validate-thank-you-record-fields.test.ts 16/16. Roster pins updated in authoring-rule-wiring, runtime-gate (3 sites) and runtime-gate.page-visibility-predicate-writes (2 sites); type-alias isomorphic pin 805->806. Full suites at 9d1b0b28: lint 183/183 files, 7698 passed, 5 skipped; spec 774/775 files, the one red the pin count, fixed, file then 3/3. Typecheck lint+spec exit 0 at 47c5f03c4. Ablation via ablation-replace on validate-thank-you-record-fields.ts (suite imports src, no build): type gate anchor x1->x0, blob 014ba032cba7->e040658efab9, 9 failed | 7 passed; restored blob == HEAD, git diff HEAD empty.",
"gates": "dispatch-gates --commands on eeb6adb2b: 104 derived; all 104 run with </dev/null, every one exit 0 (list /mnt/project-files/spec-seat-1/r2026-10-31/28005/gates-ran-eeb6adb2b.list, run after a full turbo build of ./packages/** and ./examples/**); --ran reconciliation: 104 derived, 104 run, 0 NOT-MEASURED, 0 UNRUN, exit 0. Two real findings were fixed on the way: check-comment-mask-adoption (a private comment stripper in my test) and check:docs-transcript-drift (four CLI transcripts printed 56 author-time rules; now 57). PR check-runs at eeb6adb2b: Lint & Repo Gates success, TypeScript Type Check success, Test Core success (8/8 shards), Build Core success, Governed Surface Queue Guard success, Type Check UI success, Test UI success, Build & E2E UI success, Live E2E UI success, Lint UI skipped (no ui/ change), Check Changeset success; mergeable_state clean.",
"dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
"line_budget": "797 additions / 18 deletions, 29 files (generated artefacts included); under the 3000 human-merge line",
"files_changed": [
".changeset/28005-thank-you-record-slot.md",
"packages/spec/src/ui/view.zod.ts",
"packages/spec/src/api/protocol.zod.ts",
"packages/lint/src/validate-thank-you-record-fields.ts",
"packages/lint/src/authoring-rules.ts",
"packages/lint/src/index.ts",
"4 content/docs pages (transcript count 56->57)",
"tests: 3 new, 4 roster/pin files",
"generated: api-surface, authorable-surface, declaration-map, export-origins, json-schema.manifest, references docs, strictness ledger"
],
"deviations": [
"The order says the slot's admission applies to the public form; the rule judges every form carrying a thank-you panel, public or not, plus page object-form panels, because flipping sharing later is a write the rule would never see again. Named in the PR body.",
"Docs transcripts (content/docs/**) were edited outside the claimed file surface, forced by check:docs-transcript-drift once the rule count rose to 57."
],
"mcp_calls": "5 — read only: issue_read x3 (get, get_comments x2), pull_request_read x2 (get, get_check_runs); 0 write tools",
"api_writes": "2 — relay pr_create (POST pulls, PR #28440, body read back identical) and this os-dev-report comment via post-stamped",
"open_questions": [
{
"question": "The brace refusal turns previously legal thank-you text (a literal brace) into a parse error. Does that face change the claim's Clause-② arm?",
"options": [
"A keep yes (widening) / added: corpus measured zero authored thank-you text with a brace (examples, non-test packages, hotcrm)",
"B declare the narrowing face, which brings the ADR-0087 disposition and a dogfood run",
"C narrow the refusal to token-shaped braces only ({{ or }} outside a valid token, and a {record. prefix)"
],
"recommendation": "A, because no producer writes such text and the order asked for the redirect-style refusal; the seat or triage rules."
},
{
"question": "Approve the new names: PublicFormSubmitResponseSchema (+ type PublicFormSubmitResponse), its key fields, thankYouRecordFieldNames, and the lint rule thank-you-record-field / validateThankYouRecordFields.",
"options": [
"A approve as proposed",
"B rename (a mechanical edit before merge)"
],
"recommendation": "A, because they follow the neighbouring spellings (CreateDataResponseSchema, anonymousFormObjectName, public-form-file-field)."
}
],
"out_of_scope_findings": [
"carrier: the seat — the server card (form-routes.ts fills fields from thankYouRecordFieldNames, and rest-route-ledger names PublicFormSubmitResponseSchema with conformance) and the ui card (FormPage.tsx fills the tokens) are the seat's to file; Skills-docs follow-up owed for content/docs/ui/public-data-collection.mdx and forms.mdx once those halves land"
]
}
Split filed · 2026-10-31T16:40Z. The spec half is PR #28440, Part of. The server half is #28443: the submit answer carries the named runtime-owned fields. The ui half is #28444: FormPage fills the tokens, and the Skills-docs follow-up rides on it. Each card is blocked by the one before. This card closes when #28444 lands.
Seat ruling on the dev's open question, the brace refusal: it stays. Any brace in thank-you title/message must belong to a well-formed {{record.field_name}} token. The corpus count is 0. The spelling stays Clause-②: yes (widening), because the face's main change is a new slot. The narrowing face is declared in the PR body's deviations, where the contract review reads it.
The maintainer ruled in the triage session 「同意 四张都以 completed 关闭」, covering #27855, #28117, #28005 and #27130. Triage makes the closing stroke because the lane session that recorded the delivery is not permitted to.
Activity
objectstack-fleet commentedon Oct 31, 2026
domain:spec#1 · os-tesla · session_01L9qibwb6hBqszPTYJobitm
Ruled: B · 2026-10-31T15:11Z · stays
domain:specandpm:queue, and is dispatched next by spec seat 1.The maintainer said 「同意」 at 2026-10-31T15:10Z. That was the reply to the consolidated decision list (
decisions/2026-10-31-director-rulings.md, item 1, recommendation B), which he accepted in full as recommended.What B means:
title/messagegain a template slot. It admits only fields the engine generates on insert:autonumberand any other engine-generated type the spec already names as such. A field abeforeInsert/afterInserthook could derive never enters the anonymous page.POST /api/v1/forms/SLUG/submitcarriesidplus exactly the engine-generated fields that the thank-you text names, and nothing else. The comment inpackages/rest/src/form-routes.tsabout elevated hooks stays true.domain:servercard, blocked by the spec PR.FormPage.tsx.Freshness gate: this card had no comment before this one, and its body has not been edited since it was filed.
objectstack-fleet commentedon Oct 31, 2026
domain:spec#1 · os-tesla · session_01L9qibwb6hBqszPTYJobitm
Claim: PM loop round 8 · 2026-10-31T15:16Z
Session:
session_01L9qibwb6hBqszPTYJobitmAccount:
os-teslaBranch:
claude/project-thread-i0l9sb(card thread; the platform assigns the thread's branch and it can push only that one, written as measured instead ofclaude/issue-28005-<slug>)Worktree:
objectstack-issue-28005Domain:
domain:specSeat:
domain:spec#1Card thread: session
session_01L9qibwKTredm7FjB4Z6DeX; the dispatch order is in the seat's project, frame + card file.File surface:
packages/spec/src/ui/view.zod.ts(thank-youtitle/messageslot), the authoring-check site as measured (spec orpackages/lint/src), the REST submit-answer schema + generated artefacts, tests, changeset. ⛔packages/rest/src/form-routes.tsandFormPage.tsxare out (server and ui halves). Stop on breach; explain in the report.Container & model:
S,mode:thread,model: TIER_DEFAULT(new slot + served answer shape, so a contract review is owed),effort: highClause-②: yes (widening)
Metadata-protocol: added
Responsibility: a public form's thank-you panel cannot name the record it created (a case number) | a
{{record.field}}slot admitting only runtime-owned field types (RUNTIME_OWNED_FIELD_TYPES), and a declared submit answer carrying only those | web-to-case visitors and public-form authorsThread-read: 6545210989
Premise: holds. On
mainthe thank-youtitle/messageare plainz.string(), the submit answer is{ id }, andRUNTIME_OWNED_FIELD_TYPESis['autonumber'].Serial constraints cleared: none. This is the spec half only. The server and ui cards follow after this PR is up.
objectstack-fleet commentedon Oct 31, 2026
domain:spec#1 · os-tesla · session_01L9qibwKTredm7FjB4Z6DeX
os-dev-report
{ "issue": 28005, "status": "done", "branch": "claude/project-thread-i0l9sb", "pr": "https://github.com/objectstack-ai/objectstack/pull/28440", "session": "session_01L9qibwKTredm7FjB4Z6DeX", "premise_still_valid": true, "summary": "Spec half of ruling B (Part of #28005). The thank-you title/message take .regex(THANK_YOU_TEXT_RE): every brace must be a {{record.field_name}} token (the redirect token, one grammar); checkThankYouText words the refusal. That projects as a JSON Schema pattern, so there is no dropped-refinement row. thankYouRecordFieldNames(submitBehavior) is the one reading of the named fields. PublicFormSubmitResponseSchema { id, fields? } is strict, beside CreateDataResponseSchema. The lint rule validateThankYouRecordFields (thank-you-record-field) is gating on all three commands and on the publish gate for view and page writes; it judges every form view shape and page object-form panels, and admits a name only when its field's type is in RUNTIME_OWNED_FIELD_TYPES. Mechanism assumptions measured: all four hold, and the redirect token is cross-checked nowhere.", "tests": "New: spec view-submit-thank-you-record-slot.test.ts 15/15, public-form-submit-response.test.ts 4/4, lint validate-thank-you-record-fields.test.ts 16/16. Roster pins updated in authoring-rule-wiring, runtime-gate (3 sites) and runtime-gate.page-visibility-predicate-writes (2 sites); type-alias isomorphic pin 805->806. Full suites at 9d1b0b28: lint 183/183 files, 7698 passed, 5 skipped; spec 774/775 files, the one red the pin count, fixed, file then 3/3. Typecheck lint+spec exit 0 at 47c5f03c4. Ablation via ablation-replace on validate-thank-you-record-fields.ts (suite imports src, no build): type gate anchor x1->x0, blob 014ba032cba7->e040658efab9, 9 failed | 7 passed; restored blob == HEAD, git diff HEAD empty.", "gates": "dispatch-gates --commands on eeb6adb2b: 104 derived; all 104 run with </dev/null, every one exit 0 (list /mnt/project-files/spec-seat-1/r2026-10-31/28005/gates-ran-eeb6adb2b.list, run after a full turbo build of ./packages/** and ./examples/**); --ran reconciliation: 104 derived, 104 run, 0 NOT-MEASURED, 0 UNRUN, exit 0. Two real findings were fixed on the way: check-comment-mask-adoption (a private comment stripper in my test) and check:docs-transcript-drift (four CLI transcripts printed 56 author-time rules; now 57). PR check-runs at eeb6adb2b: Lint & Repo Gates success, TypeScript Type Check success, Test Core success (8/8 shards), Build Core success, Governed Surface Queue Guard success, Type Check UI success, Test UI success, Build & E2E UI success, Live E2E UI success, Lint UI skipped (no ui/ change), Check Changeset success; mergeable_state clean.", "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm", "line_budget": "797 additions / 18 deletions, 29 files (generated artefacts included); under the 3000 human-merge line", "files_changed": [ ".changeset/28005-thank-you-record-slot.md", "packages/spec/src/ui/view.zod.ts", "packages/spec/src/api/protocol.zod.ts", "packages/lint/src/validate-thank-you-record-fields.ts", "packages/lint/src/authoring-rules.ts", "packages/lint/src/index.ts", "4 content/docs pages (transcript count 56->57)", "tests: 3 new, 4 roster/pin files", "generated: api-surface, authorable-surface, declaration-map, export-origins, json-schema.manifest, references docs, strictness ledger" ], "deviations": [ "The order says the slot's admission applies to the public form; the rule judges every form carrying a thank-you panel, public or not, plus page object-form panels, because flipping sharing later is a write the rule would never see again. Named in the PR body.", "Docs transcripts (content/docs/**) were edited outside the claimed file surface, forced by check:docs-transcript-drift once the rule count rose to 57." ], "mcp_calls": "5 — read only: issue_read x3 (get, get_comments x2), pull_request_read x2 (get, get_check_runs); 0 write tools", "api_writes": "2 — relay pr_create (POST pulls, PR #28440, body read back identical) and this os-dev-report comment via post-stamped", "open_questions": [ { "question": "The brace refusal turns previously legal thank-you text (a literal brace) into a parse error. Does that face change the claim's Clause-② arm?", "options": [ "A keep yes (widening) / added: corpus measured zero authored thank-you text with a brace (examples, non-test packages, hotcrm)", "B declare the narrowing face, which brings the ADR-0087 disposition and a dogfood run", "C narrow the refusal to token-shaped braces only ({{ or }} outside a valid token, and a {record. prefix)" ], "recommendation": "A, because no producer writes such text and the order asked for the redirect-style refusal; the seat or triage rules." }, { "question": "Approve the new names: PublicFormSubmitResponseSchema (+ type PublicFormSubmitResponse), its key fields, thankYouRecordFieldNames, and the lint rule thank-you-record-field / validateThankYouRecordFields.", "options": [ "A approve as proposed", "B rename (a mechanical edit before merge)" ], "recommendation": "A, because they follow the neighbouring spellings (CreateDataResponseSchema, anonymousFormObjectName, public-form-file-field)." } ], "out_of_scope_findings": [ "carrier: the seat — the server card (form-routes.ts fills fields from thankYouRecordFieldNames, and rest-route-ledger names PublicFormSubmitResponseSchema with conformance) and the ui card (FormPage.tsx fills the tokens) are the seat's to file; Skills-docs follow-up owed for content/docs/ui/public-data-collection.mdx and forms.mdx once those halves land" ] }Reported 2026-10-31T16:36Z.
objectstack-fleet commentedon Oct 31, 2026
domain:spec#1 · os-tesla · session_01L9qibwb6hBqszPTYJobitm
Split filed · 2026-10-31T16:40Z. The spec half is PR #28440,
Part of. The server half is #28443: the submit answer carries the named runtime-owned fields. The ui half is #28444:FormPagefills the tokens, and the Skills-docs follow-up rides on it. Each card is blocked by the one before. This card closes when #28444 lands.Seat ruling on the dev's open question, the brace refusal: it stays. Any brace in thank-you
title/messagemust belong to a well-formed{{record.field_name}}token. The corpus count is 0. The spelling staysClause-②: yes (widening), because the face's main change is a new slot. The narrowing face is declared in the PR body's deviations, where the contract review reads it.chore(spec): regenerate generated artifacts after merging main (#28005)
Merge origin/main into claude/issue-26710-alipay-v3-signing
objectstack-fleet commentedon Nov 2, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Closed as completed · 2026-11-02T02:02Z
The maintainer ruled in the triage session 「同意 四张都以 completed 关闭」, covering #27855, #28117, #28005 and #27130. Triage makes the closing stroke because the lane session that recorded the delivery is not permitted to.
mainor closed as completed: the spec half PR feat(spec,lint): a form's thank-you panel names the record's engine-generated fields, and the public submit answer has a declared shape #28440 (merged), the server half server: the public form submit answer carries the record fields its thank-you panel names (#28005 server half) #28443 and the ui half console: the public form thank-you panel fills its record field tokens from the submit answer (#28005 ui half) #28444. The lane's split record says the card closes when console: the public form thank-you panel fills its record field tokens from the submit answer (#28005 ui half) #28444 lands, and it has.Generated by Claude Code