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
Setup → metadata edit page saves a bad name anyway and stacks three messages (server refusal, client summary, inline error) (#27521 row 16) #27865
Filing gate: ② a wrong or confusing state shown to the user. Split from #27521 row 16 by the seat; the parent's acceptance says each row is taken as its own card or answered.
Business reason
Who: every administrator creating a permission set (and any metadata item edited on the same page). What happens: with an illegal name the save is sent anyway, and the page then draws the server refusal ("is not a legal metadata item name"), the client summary ("does not match the spec — 1 validation error(s)") and the inline field error — three messages for one mistake. Reach: every administrator creating a set.
Mechanism
ui/packages/app-shell/src/views/metadata-admin/ResourceEditPage.tsx: the client validator flags the name, but the save is not held, so the server refusal and the summary banner are drawn beside the inline error.
Claim: PM loop round 1
Session: session_01Utp6CaJoinvGQSbHeDaWBe
Account: os-bill
Branch: claude/project-thread-uk5z33 (the card thread's designated push branch, the recorded platform exception to claude/issue-<n>-<slug>)
Worktree: objectstack-issue-27865
Domain: domain:ui
Seat: domain:ui#3
File surface: Setup metadata edit page (ui/packages/app-shell/src/views/metadata-admin/ResourceEditPage.tsx and helpers), app-shell/studio i18n only if a sentence changes (changed en strings in all ten packs), tests beside, root changeset (stop on breach; explain in the report)
Container & model: S/M, mode:thread, model: TIER_DEFAULT (dispatch-gates --tier on 178b5238: no path-derived mandate), effort: high
Clause-②: no
Metadata-protocol: none
Responsibility: ui code produces the defect | no platform path covers it | every Studio / console author reaches it today
Thread-read: none
Premise: holds
Serial constraints cleared: none (sibling spec card #27864 is independent; handed over by domain:ui seat 2 at 03:01Z)
Dispatched 2026-10-30T03:04Z to a card thread of the seat's project; the order lives in the project. ⛔ The thread posts no claim and writes no assignee.
{
"issue": 27865,
"status": "done",
"branch": "claude/project-thread-uk5z33",
"pr": "https://github.com/objectstack-ai/objectstack/pull/27938",
"head": "ab56afe954a735f13d074e0856e3a02d35269b41",
"session": "session_01Utp6CZcCCHhGAp4cezRhuD (card thread; seat session_01Utp6CaJoinvGQSbHeDaWBe)",
"premise_still_valid": true,
"summary": "Measured on main e6553619, stock showcase, Setup > Permission Sets > New, Name 'Bad Name': before Save the summary banner and the inline error both show; Save sends PUT /meta/permission/Bad%20Name, answered 400 'is not a legal metadata item name', and the next edit brings banner + inline back beside the standing refusal (three messages). Now: doSave holds a create whose identity field the live client validator refuses (validateMetadataDraft mode create on the same draft, awaited, so no debounce race): no request, issues back on the form. A Save attempt reveals the create form's deferred field errors (SchemaForm revealIssues). The outer SchemaForm reports which top-level fields draw issues inline; the summary banner leaves those out (only issues the form received), and a 422 whose issues all sit on drawn fields skips the refusal line (only where a client validator exists). Re-driven live at the branch: zero PUT, only the inline error; a good name still creates. The hold is bounded to create + identity field to stay inside the pinned advisory design (see open_questions).",
"tests": "New ResourceEditPage.heldBadName-27865.test.tsx (real page, real MetadataClient, in-memory door: 400 for an ungrammatical name via the spec's METADATA_ITEM_NAME_PATTERN, 422 at name for taken_set; live permission registration via registerBuiltinAnchors): 4/4. Affected set on ab56afe9 (every ui test file naming ResourceEditPage|SchemaForm|PackageFormDialog, 187 files): Test Files 187 passed, Tests 1921 passed, lock VERDICT 0 (6m59s); before the merge 169 files / 1765 passed. Ablations via ablation-replace (app-shell tests import src, no dist leg; every restore blob == HEAD, git diff HEAD empty): hold condition -> (a) red 1/3; banner filter -> (a)+(b) red 2/3 (first attempt was a no-op marker, 3/3 green, re-run with a filter-removing marker); refusal-line skip -> (b) red 1/3; reveal -> (c) red 1/4. Known-stricter probe (scratch, not committed): 20 types with a client create validator x 9 names: no type where the client refuses a name the server registry schema + door grammar accept.",
"gates": [
"node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0",
"node scripts/check-adr-0087-registration.mjs --self-test :: exit 0",
"node scripts/check-changeset-no-major.mjs --base origin/main :: exit 0",
"node scripts/check-closing-keyword-parity.mjs :: exit 0",
"node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0",
"node scripts/check-comment-mask-corpus.mjs :: exit 0",
"node scripts/check-empty-changeset.mjs --base origin/main :: exit 0",
"node scripts/check-empty-changeset.mjs --self-test :: exit 0",
"node scripts/check-sdui-manifest.mjs :: exit 0",
"node scripts/check-sdui-manifest.mjs --self-test :: exit 0",
"node scripts/pm/release-rehearsal-clone.mjs --self-test :: exit 0",
"node scripts/release-pending-publish.mjs --self-test :: exit 0",
"pnpm --dir ui exec vitest run scripts/ :: exit 0",
"pnpm --filter @objectstack/spec run check:duration-unit-keys :: exit 0",
"pnpm check:changeset-gate-self-tests :: exit 0",
"pnpm check:closed-ceremony-text :: exit 0",
"pnpm check:cross-package-test-inputs :: exit 0",
"pnpm check:dispatcher-error-vocabulary :: exit 0",
"pnpm check:driver-memory-census :: exit 0",
"pnpm check:engine-double-contract :: exit 0",
"pnpm check:gitlink-declared :: exit 0",
"pnpm check:nul-bytes :: exit 0",
"pnpm check:pm-changeset-deadline-census :: exit 0",
"pnpm check:published-files :: exit 0",
"pnpm check:query-options-erasure :: exit 0",
"pnpm check:refd-timer-probe :: exit 0",
"pnpm check:skill-identifier-liveness :: exit 0",
"pnpm check:test-source-alias :: exit 0",
"pnpm check:tier-file-adoption :: exit 0",
"pnpm check:type-check-coverage :: exit 0",
"pnpm check:type-check-debt :: exit 0",
"pnpm check:undeclared-dep-imports :: exit 0",
"pnpm check:watch-hint-literal :: exit 0",
"pnpm check:where-matcher :: exit 0",
"dispatch-gates --ran: 34 derived, 34 run, 0 NOT-MEASURED, 0 UNRUN (head ab56afe9); the same 34 also all exit 0 on a18abd01 before the main merge",
"ui check:new-line-citations :: exit 0 (0 new)",
"pnpm --filter @object-ui/app-shell run type-check :: exit 0 (lock VERDICT 0, after rebuilding @object-ui/app-shell^... on ab56afe9)",
"eslint on the three changed ui files :: exit 0 (0 errors; no warning on an added line)",
"PR check-runs at report time (head ab56afe9): 17 in_progress, 3 skipped"
],
"dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
"line_budget": "4 files, +335 / -6 vs main (test +195 of that)",
"files_changed": [
".changeset/27865-held-bad-name-one-message.md",
"ui/packages/app-shell/src/views/metadata-admin/ResourceEditPage.heldBadName-27865.test.tsx",
"ui/packages/app-shell/src/views/metadata-admin/ResourceEditPage.tsx",
"ui/packages/app-shell/src/views/metadata-admin/SchemaForm.tsx"
],
"deviations": [
"Pushed the designated branch once before any commit (it then equalled main e6553619); os-dev says a card thread does not push an empty branch.",
"PR body attribution link names this card thread (the session's own attribution block, as PR #27870 did), not the seat-thread link the order spelled.",
"Skipped the harness's after-PR assignee/review-request step, per the order (no os-bill assignee or reviewer).",
"The first 169-file affected run overlapped a ref-only refactor commit (a18abd01); the full affected set was re-run on ab56afe9 (187 files).",
"One ablation attempt was a logical no-op (marker spelling); re-run, both readings reported."
],
"mcp_calls": "0",
"api_writes": "2 — relay pr_create (POST /repos/objectstack-ai/objectstack/pulls, #27938); this report via post-stamped (POST /repos/objectstack-ai/objectstack/issues/27865/comments)",
"open_questions": [
{
"question": "ResourceEditPage pins (objectui#6980, schemaAdvisory.test, re-affirmed by ruling 5749269225) that the live client Zod pass never gates Save. The card asks to hold Save on that verdict. Is the bounded hold (create door, identity field only, in doSave; Save button gate untouched) acceptable without a maintainer ruling?",
"options": [
"A keep the bounded hold: the create form always offers the name input, so a stricter client can never wedge the author; measured no stricter type today",
"B drop the hold (revert item 1 only), keep reveal + one-message dedupe: the bad name is still sent and refused, but said once",
"C take it to the maintainer as a decision"
],
"recommendation": "A, because the advisory design's stated failure (a dead-bolt with no on-screen editor able to fix it) cannot occur on the create form's name input, and the card's acceptance needs the hold"
}
],
"out_of_scope_findings": []
}
Activity
objectstack-fleet commentedon Oct 30, 2026
domain:ui#3 · os-bill · session_01Utp6CaJoinvGQSbHeDaWBe
Claim: PM loop round 1
Session:
session_01Utp6CaJoinvGQSbHeDaWBeAccount:
os-billBranch:
claude/project-thread-uk5z33(the card thread's designated push branch, the recorded platform exception toclaude/issue-<n>-<slug>)Worktree:
objectstack-issue-27865Domain:
domain:uiSeat:
domain:ui#3File surface: Setup metadata edit page (ui/packages/app-shell/src/views/metadata-admin/ResourceEditPage.tsx and helpers), app-shell/studio i18n only if a sentence changes (changed en strings in all ten packs), tests beside, root changeset (stop on breach; explain in the report)
Container & model:
S/M,mode:thread,model: TIER_DEFAULT(dispatch-gates --tieron178b5238: no path-derived mandate),effort: highClause-②: no
Metadata-protocol: none
Responsibility: ui code produces the defect | no platform path covers it | every Studio / console author reaches it today
Thread-read: none
Premise: holds
Serial constraints cleared: none (sibling spec card #27864 is independent; handed over by domain:ui seat 2 at 03:01Z)
Dispatched 2026-10-30T03:04Z to a card thread of the seat's project; the order lives in the project. ⛔ The thread posts no claim and writes no assignee.
Generated by Claude Code
fix(app-shell): hold a create whose name the client refuses; one mess…
test(app-shell): pin the held derived name and the live permission re…
chore(changeset): app-shell and console patch for the held create name (
refactor(app-shell): mirror the inline-issue field set into its ref i…
objectstack-fleet commentedon Oct 30, 2026
domain:ui#3 · os-bill · session_01Utp6CZcCCHhGAp4cezRhuD
os-dev-report
{ "issue": 27865, "status": "done", "branch": "claude/project-thread-uk5z33", "pr": "https://github.com/objectstack-ai/objectstack/pull/27938", "head": "ab56afe954a735f13d074e0856e3a02d35269b41", "session": "session_01Utp6CZcCCHhGAp4cezRhuD (card thread; seat session_01Utp6CaJoinvGQSbHeDaWBe)", "premise_still_valid": true, "summary": "Measured on main e6553619, stock showcase, Setup > Permission Sets > New, Name 'Bad Name': before Save the summary banner and the inline error both show; Save sends PUT /meta/permission/Bad%20Name, answered 400 'is not a legal metadata item name', and the next edit brings banner + inline back beside the standing refusal (three messages). Now: doSave holds a create whose identity field the live client validator refuses (validateMetadataDraft mode create on the same draft, awaited, so no debounce race): no request, issues back on the form. A Save attempt reveals the create form's deferred field errors (SchemaForm revealIssues). The outer SchemaForm reports which top-level fields draw issues inline; the summary banner leaves those out (only issues the form received), and a 422 whose issues all sit on drawn fields skips the refusal line (only where a client validator exists). Re-driven live at the branch: zero PUT, only the inline error; a good name still creates. The hold is bounded to create + identity field to stay inside the pinned advisory design (see open_questions).", "tests": "New ResourceEditPage.heldBadName-27865.test.tsx (real page, real MetadataClient, in-memory door: 400 for an ungrammatical name via the spec's METADATA_ITEM_NAME_PATTERN, 422 at name for taken_set; live permission registration via registerBuiltinAnchors): 4/4. Affected set on ab56afe9 (every ui test file naming ResourceEditPage|SchemaForm|PackageFormDialog, 187 files): Test Files 187 passed, Tests 1921 passed, lock VERDICT 0 (6m59s); before the merge 169 files / 1765 passed. Ablations via ablation-replace (app-shell tests import src, no dist leg; every restore blob == HEAD, git diff HEAD empty): hold condition -> (a) red 1/3; banner filter -> (a)+(b) red 2/3 (first attempt was a no-op marker, 3/3 green, re-run with a filter-removing marker); refusal-line skip -> (b) red 1/3; reveal -> (c) red 1/4. Known-stricter probe (scratch, not committed): 20 types with a client create validator x 9 names: no type where the client refuses a name the server registry schema + door grammar accept.", "gates": [ "node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0", "node scripts/check-adr-0087-registration.mjs --self-test :: exit 0", "node scripts/check-changeset-no-major.mjs --base origin/main :: exit 0", "node scripts/check-closing-keyword-parity.mjs :: exit 0", "node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0", "node scripts/check-comment-mask-corpus.mjs :: exit 0", "node scripts/check-empty-changeset.mjs --base origin/main :: exit 0", "node scripts/check-empty-changeset.mjs --self-test :: exit 0", "node scripts/check-sdui-manifest.mjs :: exit 0", "node scripts/check-sdui-manifest.mjs --self-test :: exit 0", "node scripts/pm/release-rehearsal-clone.mjs --self-test :: exit 0", "node scripts/release-pending-publish.mjs --self-test :: exit 0", "pnpm --dir ui exec vitest run scripts/ :: exit 0", "pnpm --filter @objectstack/spec run check:duration-unit-keys :: exit 0", "pnpm check:changeset-gate-self-tests :: exit 0", "pnpm check:closed-ceremony-text :: exit 0", "pnpm check:cross-package-test-inputs :: exit 0", "pnpm check:dispatcher-error-vocabulary :: exit 0", "pnpm check:driver-memory-census :: exit 0", "pnpm check:engine-double-contract :: exit 0", "pnpm check:gitlink-declared :: exit 0", "pnpm check:nul-bytes :: exit 0", "pnpm check:pm-changeset-deadline-census :: exit 0", "pnpm check:published-files :: exit 0", "pnpm check:query-options-erasure :: exit 0", "pnpm check:refd-timer-probe :: exit 0", "pnpm check:skill-identifier-liveness :: exit 0", "pnpm check:test-source-alias :: exit 0", "pnpm check:tier-file-adoption :: exit 0", "pnpm check:type-check-coverage :: exit 0", "pnpm check:type-check-debt :: exit 0", "pnpm check:undeclared-dep-imports :: exit 0", "pnpm check:watch-hint-literal :: exit 0", "pnpm check:where-matcher :: exit 0", "dispatch-gates --ran: 34 derived, 34 run, 0 NOT-MEASURED, 0 UNRUN (head ab56afe9); the same 34 also all exit 0 on a18abd01 before the main merge", "ui check:new-line-citations :: exit 0 (0 new)", "pnpm --filter @object-ui/app-shell run type-check :: exit 0 (lock VERDICT 0, after rebuilding @object-ui/app-shell^... on ab56afe9)", "eslint on the three changed ui files :: exit 0 (0 errors; no warning on an added line)", "PR check-runs at report time (head ab56afe9): 17 in_progress, 3 skipped" ], "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm", "line_budget": "4 files, +335 / -6 vs main (test +195 of that)", "files_changed": [ ".changeset/27865-held-bad-name-one-message.md", "ui/packages/app-shell/src/views/metadata-admin/ResourceEditPage.heldBadName-27865.test.tsx", "ui/packages/app-shell/src/views/metadata-admin/ResourceEditPage.tsx", "ui/packages/app-shell/src/views/metadata-admin/SchemaForm.tsx" ], "deviations": [ "Pushed the designated branch once before any commit (it then equalled main e6553619); os-dev says a card thread does not push an empty branch.", "PR body attribution link names this card thread (the session's own attribution block, as PR #27870 did), not the seat-thread link the order spelled.", "Skipped the harness's after-PR assignee/review-request step, per the order (no os-bill assignee or reviewer).", "The first 169-file affected run overlapped a ref-only refactor commit (a18abd01); the full affected set was re-run on ab56afe9 (187 files).", "One ablation attempt was a logical no-op (marker spelling); re-run, both readings reported." ], "mcp_calls": "0", "api_writes": "2 — relay pr_create (POST /repos/objectstack-ai/objectstack/pulls, #27938); this report via post-stamped (POST /repos/objectstack-ai/objectstack/issues/27865/comments)", "open_questions": [ { "question": "ResourceEditPage pins (objectui#6980, schemaAdvisory.test, re-affirmed by ruling 5749269225) that the live client Zod pass never gates Save. The card asks to hold Save on that verdict. Is the bounded hold (create door, identity field only, in doSave; Save button gate untouched) acceptable without a maintainer ruling?", "options": [ "A keep the bounded hold: the create form always offers the name input, so a stricter client can never wedge the author; measured no stricter type today", "B drop the hold (revert item 1 only), keep reveal + one-message dedupe: the bad name is still sent and refused, but said once", "C take it to the maintainer as a decision" ], "recommendation": "A, because the advisory design's stated failure (a dead-bolt with no on-screen editor able to fix it) cannot occur on the create form's name input, and the card's acceptance needs the hold" } ], "out_of_scope_findings": [] }Posted 2026-10-30T04:37Z.
test(app-shell): pin the create-name hold's bound and name the carve-…
test(app-shell): type the served create seed before spreading it (#27865
objectstack-fleet commentedon Oct 30, 2026
domain:ui#3 · os-bill · session_01Utp6CaJoinvGQSbHeDaWBe
ACCEPT → PR #27938 comment 6515420999 · 2026-10-30T05:04Z
Generated by Claude Code