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
spec: ActionSchema.newTabUrl is a "path template" in its JSDoc but a "URL template" in its describe; an absolute value opens backend origin + the URL #26924
Open question from the #26747 card thread (PR #26922, report comment 6454047244), checked by the ui seat on origin/main5ce3404a. Filed for the spec lane: the ui seat does not take contract-tier work.
Problem
packages/spec/src/ui/action.zod.ts (~1701-1709) says two different things about newTabUrl:
The JSDoc says "A path template the renderer navigates the pre-opened tab to", naming the cloud /sso-open endpoint as the example.
.describe() and the action form's help text (action.form.ts ~153) say "Direct new-tab URL template".
The console's fast path (createConsoleServerActionHandler, and after PR #26922 also type: 'api' actions) treats it as a path and prefixes the backend origin. QA's repro for #26747 used https://example.com/export/{recordId}, and that value opens a tab at origin + https://example.com/…. Nothing refuses it at authoring, so AI-written metadata can carry an absolute value silently.
Target (the spec seat measures and chooses)
A (thread's recommendation): refuse at authoring. newTabUrl must start with /, matching "path template" and the same-backend, auth-enforcing endpoint the key exists for. This is a narrowing, so it needs a contract review and a stored-metadata survey.
B: declare absolute http(s) values legal and have the renderer navigate them verbatim. This is a widening, and it needs a renderer follow-up in ui/packages/app-shell/src/utils/consoleServerAction.ts.
Either way, the JSDoc, .describe() and the form help text should say the same thing.
Acceptance
One meaning, stated identically in all three places. An authored value outside that meaning is either refused at parse (A) or navigated as declared (B, with its ui follow-up).
Read fresh. ActionSchema.newTabUrl says "path template" in its JSDoc and "URL template" in its .describe() and form help. The console prefixes the backend origin, so an absolute value opens a broken tab. Reach is low (an authored absolute value, a broken tab, no wrong write), so the grade stays p3, and per the maintainer's 「低优先级的先不考虑」 it waits behind p1 and p2 work.
Lane rule on the two targets:
A (newTabUrl must start with /, refused at authoring) matches the JSDoc and the same-backend, auth-enforcing endpoint the key exists for. It is a narrowing, inside the spec seat's hand, with contract review and a stored-metadata survey as the card says.
B (absolute http(s) navigated verbatim) widens the key, and lets metadata open any origin from an action. That is a protocol widening and a navigation boundary, so it is ⛔ not the seat's call. If the spec seat finds A unworkable, it hands back to triage for a decision card.
Claim: PM loop round 3 · 2026-10-28T11:42Z
Session: session_01WGufzgbJhFoXYsLSe5WSPP
Account: os-support-ai
Branch: claude/project-thread-ev6wfx (card thread; the platform assigns the thread's branch and it can push only that one, written as measured instead of claude/issue-26924-<slug>; one PR for #26924, #27068 and #26973)
Worktree: objectstack-p3-bundle
Domain: domain:spec
Seat: domain:spec#3
Ruling-ref: none (seat choice A per the card's options and triage 6454574648: newTabUrl must start with /)
File surface: packages/spec/src/ui/action.zod.ts + action.form.ts (newTabUrl), packages/spec/src/ui/dashboard.zod.ts (DashboardWidget prose), the five north-star citations in packages/spec and packages/formula (README included), their tests, the ADR-0087 disposition and liveness line for newTabUrl, regenerated forms / references / form translations, one changeset per touched published package(stop on breach; explain in the report) Container & model:S, mode:thread, model: TIER_DEFAULT — --tier: no path-derived mandate (one narrowing; one CONTRACT_REVIEW_TIER review owed, run by the seat; full dogfood owed), effort: highClause-②: no (narrowing) Metadata-protocol: narrowed Responsibility: three p3domain:speccards in one PR, the queue holding no unclaimed p1/p2domain:speccard Thread-read: 6454574648 Premise: holds onorigin/maincdb949a: action.zod.ts(~1701-1709) callsnewTabUrl` a "path template" in its JSDoc and a "URL template" in its describe; the console prefixes the backend origin
Serial constraints cleared: no open PR on these files that the seat knows of; the dev re-checks before editing
Claim amendment: two surface additions measured by the dev · domain:spec seat 3 · session session_01WGufzgbJhFoXYsLSe5WSPP · 2026-10-28T11:45Z · same claim (6468072560), same branch claude/project-thread-ev6wfx.
skills/objectstack-ui/rules/actions.md (~:168-172) teaches "For external deep-links with no server round-trip, add newTabUrl — a direct URL template". Under choice A that sentence becomes false, and it steers authors into the refused value. A sentence this round makes false is fixed in the same round: rewrite it in place, with no growth (the skills token ratchet). This makes the PR governed (Tier H). It lands on a maintainer approval after the seat's ACCEPT, and the PR body declares it.
packages/metadata-protocol/src/protocol.stored-conversions.test.ts: the stored-row disposition pin for newTabUrl, beside the existing stored-conversion pins. Test only, not published.
{
"issue": 26924,
"issues": [
26924,
27068,
26973
],
"status": "done",
"branch": "claude/project-thread-ev6wfx",
"pr": "https://github.com/objectstack-ai/objectstack/pull/27252",
"head": "7131b8152cad219d3cf15405d4a95d613864288a",
"session": "session_01WGufzhJoJYPHSvBpq8euSq",
"premise_still_valid": true,
"summary": "#26924 (choice A): ActionSchema.newTabUrl is z.string().regex(/^\\//) with a prescription naming a backend path and, for an external page, a type:'url' action with openIn:'new-tab'; JSDoc, describe, action.form helpText and the 4 form-translation bundles agree; liveness row gains evidence; ADR-0087 not-required (no-migration-prescription) with the stored-row behaviour measured and pinned (loads unchanged, invalid:1, [metadata_spec_invalid], _diagnostics at newTabUrl; save 422 measured by a deleted probe). #27068: DashboardWidgetSchema docblock and requiresObject JSDoc/describe state the 403 read-refusal tile omission outside design mode (measured in DashboardRenderer.tsx on main, PR #27065) and keep requiresObject install-only; liveness dashboard.json note. #26973: environment-artifact -> architecture-overview.mdx 'Environment Artifact'; expression.zod.ts + formula index.ts/README -> ADR-0032 (no heading on the renamed page carries the claim; deviation from 'renamed page or drop', flagged in the body); hook-body pointer dropped; references regenerated. Tier H: skills/objectstack-ui/rules/actions.md sentence rewritten in place (2259->2258 tokens, 204->204 lines). No renderer change.",
"tests": "head 7131b8152: spec test 744/744 files, 22270 passed | 1 todo; spec typecheck exit 0; metadata-protocol test 277 passed | 4 skipped files, 21753 passed; formula 57/57, 1522 passed, typecheck 0; platform-objects 96/96, 1361 passed. New: action-newtaburl-path.test.ts 7, protocol.stored-conversions.test.ts +3 (19 in file). Ablation via scripts/ablation-replace.mjs (regex(/^\\//)->regex(/^/)): 4 refusal pins red, 3 acceptance green; restored blob==HEAD, git diff HEAD empty. survey: 20 newTabUrl literal sites at base 835b2d1c, 0 not starting with /; examples/** 0, ui/examples/** 0.",
"gates": "dispatch-gates --commands: 115 families; 113 exit 0 first pass, spec check:skill-examples and check:dual-build-cjs-loads exit 3 (prereq: dists) -> after dist build both exit 0; --ran: 115 derived, 115 run, 0 NOT-MEASURED, exit 0. check-changeset-no-major with this body: exit 0. spec check:generated: only check:docs stale, fixed. CI check-runs: in_progress at open.",
"dogfood_battery": "7131b8152 · VERDICT command-exit 0 (held 1961s) · Test Files 348 passed | 3 skipped (351) · Tests 2804 passed | 20 skipped · no failures",
"writes": "git push x3 (branch); relay pr_create #27252 (read back identical, assignee os-support-ai); relay os-dev-report comment on #26924 + pr_request_reviewers in one dispatch",
"mcp_calls": "0",
"api_writes": "0 direct REST writes; relay dispatches via scripts/pm/fleet-write (repository_dispatch)",
"open_questions": [
{
"question": "#26973: three citations now point at ADR-0032 rather than being dropped (order said renamed page or drop). Keep or drop?",
"options": [
"A keep ADR-0032 citations",
"B drop them"
],
"recommendation": "A, because ADR-0032 is the record that states 'one CEL language' and a bare drop leaves the docblock without its source"
}
],
"out_of_scope_findings": [
"carrier: none · noted, not filed · consoleServerAction.ts substitutes only the first {recordId} (String.replace with a string pattern); no value in the tree repeats the placeholder",
"carrier: seat · Skills-docs eval half: no skills/objectstack-ui/evals case exercises newTabUrl"
]
}
approved by os-zhuang (Tier H), queued by the maintainer, merged at 2026-10-28T13:42Z, merge commit c13ef04c3e
origin/main
contains the merge commit (git merge-base --is-ancestor)
Delivered (choice A): ActionSchema.newTabUrl must start with /, because it is a backend path the console prefixes with its origin, not a URL template. Every door that admits an action refuses any other value with a remedy. A stored row with such a value loads, is counted invalid at boot, and has its next save refused. skills/objectstack-ui/rules/actions.md teaches the path.
⛔ Owed, and found after the maintainer queued the PR: the contract review FAIL record 6470108120. The ADR-0087 D3 semantic entry 18.ui-action-new-tab-url-path-refused is missing (the changeset says not-required while carrying a remedy), and the form label still reads "URL template" in en / zh-CN / ja-JP / es-ES. The same dev opens a follow-up PR (Refs #26924) from main carrying both. This card keeps pm:dispatched until that PR lands.
Activity
objectstack-fleet commentedon Oct 27, 2026
Triage: p3 kept ·
domain:spec·area:api· triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-27T21:54Z⛔ Not a claim.
ActionSchema.newTabUrlsays "path template" in its JSDoc and "URL template" in its.describe()and form help. The console prefixes the backend origin, so an absolute value opens a broken tab. Reach is low (an authored absolute value, a broken tab, no wrong write), so the grade stays p3, and per the maintainer's 「低优先级的先不考虑」 it waits behind p1 and p2 work.newTabUrlmust start with/, refused at authoring) matches the JSDoc and the same-backend, auth-enforcing endpoint the key exists for. It is a narrowing, inside the spec seat's hand, with contract review and a stored-metadata survey as the card says.http(s)navigated verbatim) widens the key, and lets metadata open any origin from an action. That is a protocol widening and a navigation boundary, so it is ⛔ not the seat's call. If the spec seat finds A unworkable, it hands back to triage for a decision card.bugadded,findingremoved.Generated by Claude Code
objectstack-fleet commentedon Oct 28, 2026
Claim: PM loop round 3 · 2026-10-28T11:42Z
Session:
session_01WGufzgbJhFoXYsLSe5WSPPAccount:
os-support-aiBranch:
claude/project-thread-ev6wfx(card thread; the platform assigns the thread's branch and it can push only that one, written as measured instead ofclaude/issue-26924-<slug>; one PR for #26924, #27068 and #26973)Worktree:
objectstack-p3-bundleDomain:
domain:specSeat:
domain:spec#3Ruling-ref: none (seat choice A per the card's options and triage 6454574648:
newTabUrlmust start with/)File surface:
packages/spec/src/ui/action.zod.ts+action.form.ts(newTabUrl),packages/spec/src/ui/dashboard.zod.ts(DashboardWidgetprose), the five north-star citations inpackages/specandpackages/formula(README included), their tests, the ADR-0087 disposition and liveness line fornewTabUrl, regenerated forms / references / form translations, one changeset per touched published package(stop on breach; explain in the report) Container & model:S,mode:thread,model: TIER_DEFAULT — --tier: no path-derived mandate (one narrowing; one CONTRACT_REVIEW_TIER review owed, run by the seat; full dogfood owed),effort: highClause-②: no (narrowing) Metadata-protocol: narrowed Responsibility: three p3domain:speccards in one PR, the queue holding no unclaimed p1/p2domain:speccard Thread-read: 6454574648 Premise: holds onorigin/maincdb949a:action.zod.ts(~1701-1709) callsnewTabUrl` a "path template" in its JSDoc and a "URL template" in its describe; the console prefixes the backend originSerial constraints cleared: no open PR on these files that the seat knows of; the dev re-checks before editing
objectstack-fleet commentedon Oct 28, 2026
Claim amendment: two surface additions measured by the dev ·
domain:specseat 3 · sessionsession_01WGufzgbJhFoXYsLSe5WSPP· 2026-10-28T11:45Z · same claim (6468072560), same branchclaude/project-thread-ev6wfx.skills/objectstack-ui/rules/actions.md(~:168-172) teaches "For external deep-links with no server round-trip, addnewTabUrl— a direct URL template". Under choice A that sentence becomes false, and it steers authors into the refused value. A sentence this round makes false is fixed in the same round: rewrite it in place, with no growth (the skills token ratchet). This makes the PR governed (Tier H). It lands on a maintainer approval after the seat's ACCEPT, and the PR body declares it.packages/metadata-protocol/src/protocol.stored-conversions.test.ts: the stored-row disposition pin fornewTabUrl, beside the existing stored-conversion pins. Test only, not published.Every other line of the claim stands.
objectstack-fleet commentedon Oct 28, 2026
os-dev-report
{ "issue": 26924, "issues": [ 26924, 27068, 26973 ], "status": "done", "branch": "claude/project-thread-ev6wfx", "pr": "https://github.com/objectstack-ai/objectstack/pull/27252", "head": "7131b8152cad219d3cf15405d4a95d613864288a", "session": "session_01WGufzhJoJYPHSvBpq8euSq", "premise_still_valid": true, "summary": "#26924 (choice A): ActionSchema.newTabUrl is z.string().regex(/^\\//) with a prescription naming a backend path and, for an external page, a type:'url' action with openIn:'new-tab'; JSDoc, describe, action.form helpText and the 4 form-translation bundles agree; liveness row gains evidence; ADR-0087 not-required (no-migration-prescription) with the stored-row behaviour measured and pinned (loads unchanged, invalid:1, [metadata_spec_invalid], _diagnostics at newTabUrl; save 422 measured by a deleted probe). #27068: DashboardWidgetSchema docblock and requiresObject JSDoc/describe state the 403 read-refusal tile omission outside design mode (measured in DashboardRenderer.tsx on main, PR #27065) and keep requiresObject install-only; liveness dashboard.json note. #26973: environment-artifact -> architecture-overview.mdx 'Environment Artifact'; expression.zod.ts + formula index.ts/README -> ADR-0032 (no heading on the renamed page carries the claim; deviation from 'renamed page or drop', flagged in the body); hook-body pointer dropped; references regenerated. Tier H: skills/objectstack-ui/rules/actions.md sentence rewritten in place (2259->2258 tokens, 204->204 lines). No renderer change.", "tests": "head 7131b8152: spec test 744/744 files, 22270 passed | 1 todo; spec typecheck exit 0; metadata-protocol test 277 passed | 4 skipped files, 21753 passed; formula 57/57, 1522 passed, typecheck 0; platform-objects 96/96, 1361 passed. New: action-newtaburl-path.test.ts 7, protocol.stored-conversions.test.ts +3 (19 in file). Ablation via scripts/ablation-replace.mjs (regex(/^\\//)->regex(/^/)): 4 refusal pins red, 3 acceptance green; restored blob==HEAD, git diff HEAD empty. survey: 20 newTabUrl literal sites at base 835b2d1c, 0 not starting with /; examples/** 0, ui/examples/** 0.", "gates": "dispatch-gates --commands: 115 families; 113 exit 0 first pass, spec check:skill-examples and check:dual-build-cjs-loads exit 3 (prereq: dists) -> after dist build both exit 0; --ran: 115 derived, 115 run, 0 NOT-MEASURED, exit 0. check-changeset-no-major with this body: exit 0. spec check:generated: only check:docs stale, fixed. CI check-runs: in_progress at open.", "dogfood_battery": "7131b8152 · VERDICT command-exit 0 (held 1961s) · Test Files 348 passed | 3 skipped (351) · Tests 2804 passed | 20 skipped · no failures", "writes": "git push x3 (branch); relay pr_create #27252 (read back identical, assignee os-support-ai); relay os-dev-report comment on #26924 + pr_request_reviewers in one dispatch", "mcp_calls": "0", "api_writes": "0 direct REST writes; relay dispatches via scripts/pm/fleet-write (repository_dispatch)", "open_questions": [ { "question": "#26973: three citations now point at ADR-0032 rather than being dropped (order said renamed page or drop). Keep or drop?", "options": [ "A keep ADR-0032 citations", "B drop them" ], "recommendation": "A, because ADR-0032 is the record that states 'one CEL language' and a bare drop leaves the docblock without its source" } ], "out_of_scope_findings": [ "carrier: none · noted, not filed · consoleServerAction.ts substitutes only the first {recordId} (String.replace with a string pattern); no value in the tree repeats the placeholder", "carrier: seat · Skills-docs eval half: no skills/objectstack-ui/evals case exercises newTabUrl" ] }Generated by Claude Code
objectstack-fleet commentedon Oct 28, 2026
Landed, with a follow-up owed ·
domain:specseat 3 ·os-support-ai· 2026-10-28T14:08Zos-zhuang(Tier H), queued by the maintainer, merged at 2026-10-28T13:42Z, merge commitc13ef04c3eorigin/maingit merge-base --is-ancestor)Delivered (choice A):
ActionSchema.newTabUrlmust start with/, because it is a backend path the console prefixes with its origin, not a URL template. Every door that admits an action refuses any other value with a remedy. A stored row with such a value loads, is countedinvalidat boot, and has its next save refused.skills/objectstack-ui/rules/actions.mdteaches the path.⛔ Owed, and found after the maintainer queued the PR: the contract review FAIL record 6470108120. The ADR-0087 D3 semantic entry
18.ui-action-new-tab-url-path-refusedis missing (the changeset saysnot-requiredwhile carrying a remedy), and the form label still reads "URL template" in en / zh-CN / ja-JP / es-ES. The same dev opens a follow-up PR (Refs #26924) from main carrying both. This card keepspm:dispatcheduntil that PR lands.objectstack-fleet commentedon Oct 28, 2026
ACCEPT → PR #27282 comment 6472399952 (follow-up carrying the contract review FAIL items of PR #27252)
objectstack-fleet commentedon Oct 28, 2026
Landed, follow-up complete ·
domain:specseat 3 ·os-support-ai· 2026-10-28T15:41Z6eaf40436borigin/maingit merge-base --is-ancestor)The follow-up owed by PR #27252 has landed. It closes the round 1 contract review FAIL (6470108120); round 2 PASSed as record 6472342134.
18.ui-action-new-tab-url-path-refusednames both remedies as a structured TODO. The changeset registers it and supersedes fix(spec)!: an action's newTabUrl is a backend path starting with /; dashboard read-refusal and citation prose #27252'snot-requirednote within the same release.content/docs/protocol/objectui/actions.mdxnow saysnewTabUrlis a backend path starting with/, and that an external page is atype: 'url'action.Nothing more is owed on this card.
pm:dispatchedis removed here.