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: the "Required: Name, Email, Message" banner stays after those fields are filled and the next submit fails for a different reason #27496
Found in the 18.3.0 release-candidate browser walkthrough (wave anchor #27377, card W3-UX), at framework main @ c4c515ad, Console built in-repo from the same commit.
Repro (fresh boot)
Boot examples/app-showcase with --seed-admin. Signed out, open /forms/contact-us, which redirects to /_console/f/contact-us. Viewport 1440×900.
Click Submit with the form empty. The banner reads Required: Name, Email, Message.
Fill in Name and Message, type not-an-email into Email, and click Submit again.
Expected
The banner reflects the current attempt: it names the email format problem, or it clears.
Actual
The banner still reads Required: Name, Email, Message although all three are filled. Only the browser's native validation bubble on Email explains what is wrong.
Related, not repeated here: #27355 row 10 (a refused public-form submit does not mark the fields).
Claim: PM loop round 2 · 2026-10-29T12:56Z
Session: session_01L6bhgXU26UBEjd1KKHgNEx (seat; in-seat mode:subagent dev, same session, identity by branch)
Account: os-sales (the seat's linked user as GET /user answers it; the card's assignee)
Branch: claude/issue-27496-public-form-required-banner
Worktree: objectstack-issue-27496
Domain: domain:ui
Seat: domain:ui#1
File surface: ui/apps/console/src/components/FormPage.tsx (form element, reportRefusals, handleSubmit, the banner), a FormPage.*.test.tsx pin beside it, one patch changeset (stop on breach; explain in the report)
Container & model: S, mode:subagent, model: TIER_DEFAULT (seat-run dispatch-gates --tier on the paths: no path-derived mandate), effort: medium
Clause-②: no
Metadata-protocol: none
Responsibility: public form page (this lane) | the refusal banner #27443 extended | every visitor filling a public form whose email the browser rejects
Thread-read: 6495337670
Premise: holds — on origin/mainad3a640e, the <form> has native validation (no noValidate) and the banner state is cleared only inside handleSubmit, which a natively blocked submit never reaches.
Serial constraints cleared: no open PR changes FormPage.tsx; sibling #27483 (date widget native refusal) is held until this lands.
Resume-from: none
{
"issue": 27496,
"status": "done",
"branch": "claude/issue-27496-public-form-required-banner",
"pr": "https://github.com/objectstack-ai/objectstack/pull/27578",
"session": "session_01L6bhgXU26UBEjd1KKHgNEx",
"premise_still_valid": true,
"summary": "Measured on origin/main ad3a640e: the public form element has no noValidate, the email widget renders type=email, and the banner state is cleared only inside handleSubmit, which a submit the browser blocks never reaches. FormPage.tsx now gives the form an onInvalidCapture handler, handleNativeInvalid. It runs the page's own checks again (findSubmitRefusals through reportRefusals, scoped to the current wizard step before the last one), so the banner names what is still refused or clears. Each control the browser refused is marked with the browser's validationMessage through the existing fieldErrors channel, and the marks are read again from the whole form on every invalid event. Native validation is kept, and the rule covers any natively invalid control, so sibling #27483 is covered when it lands.",
"tests": "head a66f23cc. `pnpm --dir ui exec vitest run apps/console/src/components/FormPage` (lock VERDICT command-exit 0): Test Files 38 passed (38), Tests 363 passed (363), including the new FormPage.nativeInvalid-27496.test.tsx with 3 tests: stale banner cleared and only email marked with no POST; a fixed email POSTs once; a server 400 still shows the 'Submit failed (400)' banner. `pnpm --filter @object-ui/console run type-check`: VERDICT command-exit 0. Ablation at commit 023e1e53 via scripts/ablation-replace.mjs --delete of anchor ' onInvalidCapture={handleNativeInvalid}' (anchor x1 to x0, blob d3584786 to a9e144c7): 'clears Required' pin went red with 'expected the form-error div to be null', Tests 1 failed / 2 passed. Restored: blob equals HEAD d3584786, git diff HEAD empty. No dist rebuild was needed: the console tests import FormPage from src by relative path.",
"gates": "Local, head a66f23cc: `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` derived 33 commands. All 33 ran, each exit code captured before any pipe, all exit 0, with the ui vitest scripts/ run under the lock. `--ran` reconciliation: 33 derived, 33 run, 0 NOT-MEASURED, 0 UNRUN, a DERIVED zero with every exit code recorded. Also run: `pnpm check:new-line-citations` (ui) VERDICT 0 new citations, exit 0. CI families (Lint UI, Type Check UI, Test UI, Build & E2E UI, Live E2E UI, Lint & Repo Gates, etc.): in_progress on PR #27578, not re-run locally. The repo-wide full suite was not run locally and is declared to CI (Test UI / Test Core); the local run was narrowed to the 38 FormPage files plus the derived list.",
"line_budget": "150 limit; branch diff vs merge base: 3 files, +145 / -1 = 146 changed lines (FormPage.tsx +27/-1, the test +108, the changeset +10).",
"files_changed": [
"ui/apps/console/src/components/FormPage.tsx",
"ui/apps/console/src/components/FormPage.nativeInvalid-27496.test.tsx",
".changeset/27496-public-form-native-invalid-banner.md"
],
"deviations": [
"PR body order: os-dev.md puts Fixes right after the harness attribution line, and the dispatch fixes the first two lines (attribution plus 'Requested by') and then lists 速读 before Fixes. Resolved as: the two dispatch lines, then Fixes / Clause-② / Metadata-protocol, then 速读. Fixes is the first line after the dispatch-mandated pair.",
"PR body line 1 is the HTML-comment attribution that the dispatch order mandates. os-dev forbids dev-written HTML comments. The read-back shows the 3474 bytes stored identically.",
"Report comment: the dispatch requires the signature as the first line, and os-dev requires os-dev-report as the first line. Written as signature first, then os-dev-report on line 2.",
"dogfood_battery: n/a, with no ! in the title and no (narrowing) arm."
],
"dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
"mcp_calls": "0",
"api_writes": "3 — git push (not REST); POST /repos/objectstack-ai/objectstack/dispatches (fleet-write relay pr_create, created draft PR #27578); POST /repos/objectstack-ai/objectstack/issues/27496/comments via post-stamped.mjs (this report)",
"open_questions": [],
"out_of_scope_findings": []
}
Takeover of claim 6497277243 by domain:ui#4. Withdrawn. The maintainer, Bill, revoked the takeover (「刚才的接管撤销」) minutes after approving it, in the same project chat. The ui lane is winding down: in-hand work finishes and nothing new is picked up.
This comment was the only write. No assignee changed, no label changed, and no landing op ran on PR #27578. Claim 6497277243 (domain:ui#1, os-sales) stands exactly as it did before, together with its ACCEPT on PR #27578. Its landing remains the maintainer's, as that ACCEPT states. The release and claim lines this comment carried have been removed, so no checker reads them as live.
Activity
objectstack-fleet commentedon Oct 29, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: 能用的表单 | none | P②
Triage: p2 ·
domain:ui·area:records· 2026-10-29T11:24Z⛔ Not a claim.
bug,pm:queue.Generated by Claude Code
objectstack-fleet commentedon Oct 29, 2026
domain:ui#1 · os-sales · session_01L6bhgXU26UBEjd1KKHgNEx
Claim: PM loop round 2 · 2026-10-29T12:56Z
Session:
session_01L6bhgXU26UBEjd1KKHgNEx(seat; in-seatmode:subagentdev, same session, identity by branch)Account:
os-sales(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-27496-public-form-required-bannerWorktree:
objectstack-issue-27496Domain:
domain:uiSeat:
domain:ui#1File surface:
ui/apps/console/src/components/FormPage.tsx(form element,reportRefusals,handleSubmit, the banner), aFormPage.*.test.tsxpin beside it, one patch changeset (stop on breach; explain in the report)Container & model:
S,mode:subagent,model: TIER_DEFAULT(seat-rundispatch-gates --tieron the paths: no path-derived mandate),effort: mediumClause-②: no
Metadata-protocol: none
Responsibility: public form page (this lane) | the refusal banner #27443 extended | every visitor filling a public form whose email the browser rejects
Thread-read: 6495337670
Premise: holds — on
origin/mainad3a640e, the<form>has native validation (nonoValidate) and the banner state is cleared only insidehandleSubmit, which a natively blocked submit never reaches.Serial constraints cleared: no open PR changes
FormPage.tsx; sibling #27483 (date widget native refusal) is held until this lands.Resume-from: none
objectstack-fleet commentedon Oct 29, 2026
domain:ui#1 · os-sales · session_01L6bhgXU26UBEjd1KKHgNEx
os-dev-report
{ "issue": 27496, "status": "done", "branch": "claude/issue-27496-public-form-required-banner", "pr": "https://github.com/objectstack-ai/objectstack/pull/27578", "session": "session_01L6bhgXU26UBEjd1KKHgNEx", "premise_still_valid": true, "summary": "Measured on origin/main ad3a640e: the public form element has no noValidate, the email widget renders type=email, and the banner state is cleared only inside handleSubmit, which a submit the browser blocks never reaches. FormPage.tsx now gives the form an onInvalidCapture handler, handleNativeInvalid. It runs the page's own checks again (findSubmitRefusals through reportRefusals, scoped to the current wizard step before the last one), so the banner names what is still refused or clears. Each control the browser refused is marked with the browser's validationMessage through the existing fieldErrors channel, and the marks are read again from the whole form on every invalid event. Native validation is kept, and the rule covers any natively invalid control, so sibling #27483 is covered when it lands.", "tests": "head a66f23cc. `pnpm --dir ui exec vitest run apps/console/src/components/FormPage` (lock VERDICT command-exit 0): Test Files 38 passed (38), Tests 363 passed (363), including the new FormPage.nativeInvalid-27496.test.tsx with 3 tests: stale banner cleared and only email marked with no POST; a fixed email POSTs once; a server 400 still shows the 'Submit failed (400)' banner. `pnpm --filter @object-ui/console run type-check`: VERDICT command-exit 0. Ablation at commit 023e1e53 via scripts/ablation-replace.mjs --delete of anchor ' onInvalidCapture={handleNativeInvalid}' (anchor x1 to x0, blob d3584786 to a9e144c7): 'clears Required' pin went red with 'expected the form-error div to be null', Tests 1 failed / 2 passed. Restored: blob equals HEAD d3584786, git diff HEAD empty. No dist rebuild was needed: the console tests import FormPage from src by relative path.", "gates": "Local, head a66f23cc: `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` derived 33 commands. All 33 ran, each exit code captured before any pipe, all exit 0, with the ui vitest scripts/ run under the lock. `--ran` reconciliation: 33 derived, 33 run, 0 NOT-MEASURED, 0 UNRUN, a DERIVED zero with every exit code recorded. Also run: `pnpm check:new-line-citations` (ui) VERDICT 0 new citations, exit 0. CI families (Lint UI, Type Check UI, Test UI, Build & E2E UI, Live E2E UI, Lint & Repo Gates, etc.): in_progress on PR #27578, not re-run locally. The repo-wide full suite was not run locally and is declared to CI (Test UI / Test Core); the local run was narrowed to the 38 FormPage files plus the derived list.", "line_budget": "150 limit; branch diff vs merge base: 3 files, +145 / -1 = 146 changed lines (FormPage.tsx +27/-1, the test +108, the changeset +10).", "files_changed": [ "ui/apps/console/src/components/FormPage.tsx", "ui/apps/console/src/components/FormPage.nativeInvalid-27496.test.tsx", ".changeset/27496-public-form-native-invalid-banner.md" ], "deviations": [ "PR body order: os-dev.md puts Fixes right after the harness attribution line, and the dispatch fixes the first two lines (attribution plus 'Requested by') and then lists 速读 before Fixes. Resolved as: the two dispatch lines, then Fixes / Clause-② / Metadata-protocol, then 速读. Fixes is the first line after the dispatch-mandated pair.", "PR body line 1 is the HTML-comment attribution that the dispatch order mandates. os-dev forbids dev-written HTML comments. The read-back shows the 3474 bytes stored identically.", "Report comment: the dispatch requires the signature as the first line, and os-dev requires os-dev-report as the first line. Written as signature first, then os-dev-report on line 2.", "dogfood_battery: n/a, with no ! in the title and no (narrowing) arm." ], "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm", "mcp_calls": "0", "api_writes": "3 — git push (not REST); POST /repos/objectstack-ai/objectstack/dispatches (fleet-write relay pr_create, created draft PR #27578); POST /repos/objectstack-ai/objectstack/issues/27496/comments via post-stamped.mjs (this report)", "open_questions": [], "out_of_scope_findings": [] }Generated by Claude Code
objectstack-fleet commentedon Oct 29, 2026
domain:ui#4 · os-bill · session_01Utp6CbDAucNyQ4UtzCJKyh
Takeover of claim 6497277243 by. Withdrawn. The maintainer, Bill, revoked the takeover (「刚才的接管撤销」) minutes after approving it, in the same project chat. The ui lane is winding down: in-hand work finishes and nothing new is picked up.domain:ui#4This comment was the only write. No assignee changed, no label changed, and no landing op ran on PR #27578. Claim 6497277243 (
domain:ui#1,os-sales) stands exactly as it did before, together with its ACCEPT on PR #27578. Its landing remains the maintainer's, as that ACCEPT states. The release and claim lines this comment carried have been removed, so no checker reads them as live.Generated by Claude Code
objectstack-fleet commentedon Oct 29, 2026
domain:ui#1 · os-sales · session_01L6bhgXU26UBEjd1KKHgNEx
落地 · 2026-10-29T19:54Z
ca4b5d503f在origin/main上git grep -c "onInvalidCapture" origin/main -- ui/apps/console/src/components/FormPage.tsxuseState= 14)状态:卡已由 PR 关闭,摘
pm:dispatched。排在本卡之后的 #27483 现可派,收班时释放回队列。