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
New automation: pressing Enter on a typed prefix saves that prefix as the trigger object, and the flow is refused later in English #30038
Filed by the record-page epic seat from a browser evaluation of the Console on main63b86b385d (example CRM, zh-CN, dev admin). An independent reviewer ran the pass and the seat re-checked the evidence named below. No domain:* label is set: triage routes this card.
Business reason
An operations person creates an automation and types part of the object name. The list shows the one match, and they press Enter as they would in any search box. The dialog stores what they typed, not the match. They get a flow bound to an object that does not exist, grouped under a heading in capitals, and an English error about package closure. The fix is easy once understood, but nothing on the screen explains it to this reader.
Reproduce
Reported by the reviewer: Studio → 自动化 → 新建自动化 → 更新记录时 → type crm_custom_eval_1104 in 对象, with one option shown → Enter → 存为草稿. The seat read the resulting screenshot and did not repeat the steps: rail group CRM_CUSTOM_EVAL_1104, and on 问题: "triggers on object 'crm_custom_eval_1104', which is outside the closure of package 'com.example.crm.custom' (its own objects, the objects of the packages its manifest declares in dependencies, and platform objects), so the package may not bind a flow to it. Did you mean "crm_custom_eval_1104_hetong"?"
Code readings on 63b86b385d
ui/packages/app-shell/src/views/metadata-admin/inspectors/ObjectPicker.tsx:25-27: free text is deliberate, because "a flow reference may hold an expression".
:365-368: Enter chooses the active row if there is one, and otherwise commits the typed text.
ui/packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx:9717 and :9771: the new-automation dialog uses this picker for the trigger object. No expression is possible there.
Acceptance
At the new-automation trigger door, a typed name that is not an object cannot be committed. Enter picks the only match when exactly one remains, and otherwise the dialog says no object is chosen and stays open.
Other uses of ObjectPicker, where an expression is legal, keep today's free text. FlowReferenceField.tsx:1208 is one.
The closure refusal on 问题 reads in the Console's language, in terms this reader can act on.
Tests pin items 1 and 2.
Re-check
git grep -n "else if (typed) commit(text)" origin/main -- ui/packages/app-shell/src/views/metadata-admin/inspectors/ObjectPicker.tsx
Read fresh. In New automation, pressing Enter on a typed prefix saves that prefix as the trigger object. A wrong save from a common keystroke, so p2 kept.
Claim: PM loop round 1
Session: session_01QSeKYpFBMr917PmVkG9up7
Account: os-justin
Branch: claude/issue-30038-trigger-object-enter
Worktree: objectstack-issue-30038
Domain: domain:ui
Seat: domain:ui#3
File surface: ui/packages/app-shell/src/views/metadata-admin/inspectors/ObjectPicker.tsx, ui/packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx (new-automation dialog region only, about :9717–:9771), their tests, and the zh/en strings in ui/packages/i18n for the closure-refusal text (stop on breach; explain in the report)
Container & model: M, mode:subagent, model: opus (dispatch-gates --tier: no path-derived mandate; default tier), effort: high
Clause-②: no
Metadata-protocol: none
Responsibility: ui ObjectPicker's Enter-commits-typed-text branch, used at a door where no expression is legal | none — the closure check on 问题 catches it only after save | any Studio admin creating an automation; reachable today
Thread-read: 6628973335
Premise: holds (ObjectPicker.tsx:368else if (typed) commit(text); on origin/main55337f4c)
Serial constraints cleared: none (no live domain:ui claim names ObjectPicker.tsx or the new-automation dialog)
Acceptance item 3 (closure refusal wording): if that text is produced server-side, the dev reports it as out-of-scope with a carrier, not a cross-lane edit.
{
"issue": 30038,
"status": "done",
"branch": "claude/issue-30038-trigger-object-enter",
"pr": "https://github.com/objectstack-ai/objectstack/pull/30148",
"session": "session_01QSeKYpFBMr917PmVkG9up7",
"premise_still_valid": true,
"summary": "Premise held on origin/main 55337f4ce: ObjectPicker.tsx:368 `else if (typed) commit(text);`. ObjectPicker gains an opt-in `objectsOnly` prop. With it, Enter and blur commit the pickable object named exactly, else the only pickable match left, else an empty commit plus a role=alert line 'No object chosen: \"TEXT\" is not an object. Choose one from the list.' (zh/en keys engine.inspector.objectPicker.notChosen and noMatchObjectsOnly). StudioDesignSurface's New automation dialog turns it on for both trigger-object pickers (record preset and Advanced). A record preset with no object then keeps the dialog open with the existing needsObject line. FlowReferenceField and every other ObjectPicker use are unchanged (free text), so items 1, 2 and 4 are done. Item 3 is NOT here: the closure refusal is produced by packages/lint/src/validate-flow-trigger-readiness.ts:513 (server side, outside ui/**). The PR body says `Refs #30038 (items 1, 2, 4)`, so the card stays open for item 3. Harness note: the run used the harness-provided worktree (.claude/worktrees/agent-ada62fbd8c4db7be3) on the claim's branch, not ../objectstack-issue-30038. The empty branch was pushed before the first commit.",
"tests": "Head 29b6b028e. `pnpm --dir ui exec vitest run --maxWorkers=2 packages/app-shell/src/views/metadata-admin/inspectors/ObjectPicker.test.tsx packages/app-shell/src/views/studio-design/StudioDesignSurface.createTaken-26917.test.tsx` under the lock: `Test Files 2 passed (2) / Tests 25 passed (25)`, VERDICT command-exit 0. New: 5 picker cases (one-match prefix+Enter commits the match; several matches commits nothing and shows refusal; non-object clears on Enter and on blur; full name commits; default free text commits the prefix as typed = item 2) and 2 door cases (record_updated preset: 'tick'+Enter+Create saves Start objectName acme_ticket; 'acme'+Enter+Create saves nothing, refusal + needsObject shown, dialog open). Ablation via scripts/ablation-replace.mjs, restored to HEAD each leg (blob == HEAD, git diff HEAD empty). Tests import src directly (relative), so no dist is involved. Leg A: ObjectPicker `if (!objectsOnly || catalog.status !== 'loaded') {` replaced with `if (true) {` (blob e2118e0a8872 to 53ef6e70092f): 5 failed / 20 passed, all objectsOnly-dependent cases red, free-text case green. Leg B: door `objectsOnly` replaced with `objectsOnly={false}` (blob fc99d66e24c9 to b3f8845a7e8e): 2 failed / 8 passed, both door cases red. The first Leg B attempt was a no-op that the tool refused before running (the replacement was already inside the anchor). The anchor was changed and the leg re-run. Type-check: `pnpm exec turbo run type-check --filter=./ui/packages/app-shell`: Tasks 68 successful, 68 total, @object-ui/app-shell:type-check ran `tsc --noEmit && tsc -p tsconfig.test.json`, VERDICT command-exit 0. Narrowed (declared): the ui/packages/i18n package suite was not run locally, because the lock was held about 22 min by another agent's run that includes packages/i18n/ (pid 31527). NOT MEASURED locally, declared to CI. scripts/ vitest (incl. check-i18n-call-site-keys) passed.",
"gates": "Derived by `node scripts/pm/dispatch-gates.mjs --commands` (merge base 55337f4ce, 7 paths, head 29b6b028e): 35 families. Each was run and its exit captured before any pipe. 34 exit 0: check-adr-0087-registration (+self-test), check-changeset-no-major, check-closing-keyword-parity (+self-test), check-comment-mask-corpus, check-empty-changeset (+self-test), check-sdui-manifest (+self-test), release-rehearsal-clone --self-test, release-pending-publish --self-test, `pnpm --dir ui exec vitest run scripts/` (lock VERDICT command-exit 0), spec check:duration-unit-keys, check:changeset-gate-self-tests, closed-ceremony-text, cross-package-test-inputs, dispatcher-error-vocabulary, driver-memory-census, engine-double-contract, gitlink-declared, nul-bytes, published-files, query-options-erasure, refd-timer-probe, registry-log-declared, rest-log-spy-declared, skill-identifier-liveness, test-source-alias, tier-file-adoption, type-check-coverage, undeclared-dep-imports, watch-hint-literal, where-matcher. `pnpm check:type-check-debt`: exit 3, PREREQUISITE NOT MET. Its closure build hit lock queue-timeout 99 twice (holder pid 31527, another agent's vitest run, held more than 22 min), so it is NOT MEASURED, declared narrowed to CI. `--ran` reconciliation: 35 derived, 35 run, 0 UNRUN. PR check-runs: in_progress at report time, not awaited.",
"dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
"mcp_calls": "0",
"api_writes": "2 — pr_create via fleet-write relay (POST /repos/objectstack-ai/objectstack/pulls, draft, no labels, no assignees: PR #30148, 5952 bytes read back identical); os-dev-report comment on #30038 via post-stamped.mjs (POST /repos/objectstack-ai/objectstack/issues/30038/comments). Plus git push (not REST).",
"open_questions": [],
"security_findings": "none",
"out_of_scope_findings": [
"class: a (user-visible experience defect: an untranslated refusal the reader cannot act on) · reach: public door, Studio 问题 panel on a zh-CN Console, per the card's reviewer screenshot: an English sentence 'triggers on object X, which is outside the closure of package P (... `dependencies` ...)'. The text is the `message` of a packages/lint finding, packages/lint/src/validate-flow-trigger-readiness.ts:513 (rule FLOW_TRIGGER_UNKNOWN_OBJECT, hint from closureDependencyRemedy). The finding carries no structured params (objectName, packageId) that a ui renderer could localize from, so the fix is at the producer (structured params or a code the Console keys on), outside the ui/** lane · Seam: lint:FLOW_TRIGGER_UNKNOWN_OBJECT message → renderer: Studio 问题 panel · carrier: #30038 (item 3 stays open; PR uses Refs) · dedupe words: closure refusal localize, FLOW_TRIGGER_UNKNOWN_OBJECT i18n, validate-flow-trigger-readiness message zh, lint finding structured params"
]
}
ACCEPT · PR #30148 · head 29b6b028e · 2026-11-04T16:58Z
Seat review of the diff (read via GET /pulls/30148 diff, not the report):
Shape:ObjectPicker gains an opt-in objectsOnly prop, off by default. With it, commitTyped commits the pickable option named exactly, else the only pickable option left, else '' plus a role=alert refusal. Both trigger-object pickers in the New automation dialog (StudioDesignSurface.tsx, record preset and Advanced) turn it on. Every other use keeps free text (item 2). zh/en keys were added in ui/packages/i18n studio namespaces.
Accepted deviation: while the catalog is not loaded, objectsOnly still commits the typed text (docstring says so). It is a narrow residual window; the closure check on 问题 still catches it. No follow-up card.
Tests (item 4): 5 picker cases and 2 door cases. The ablations went red, then were restored: leg A 5/25 red, leg B 2/10 red.
Gates: check-runs on 29b6b028e show 55 runs: 44 success, 11 skipped, 0 red. check-governed-merges --pr 30148 says NOT governed, 192 changed lines. mergeable_state reads clean. The dev declared two runs NOT MEASURED locally because of lock contention, the ui/packages/i18n suite and check:type-check-debt. CI covered both, green.
Out of scope, item 3: the closure refusal is produced in packages/lint/src/validate-flow-trigger-readiness.ts:513 (FLOW_TRIGGER_UNKNOWN_OBJECT), with no structured params a renderer could localize from. That is outside ui/**. Carrier: this card. The PR says Refs #30038 (items 1, 2, 4). At MERGED the seat releases this card with item 3 as the remainder and asks triage to relabel (pm:retriage).
Release: items 1, 2 and 4 landed in PR #30148 (Refs #30038 (items 1, 2, 4)). Item 3 is left: the closure refusal on 问题 must read in the Console's language. Its producer is packages/lint/src/validate-flow-trigger-readiness.ts:513 (FLOW_TRIGGER_UNKNOWN_OBJECT), whose finding carries no structured params a renderer could localize from. That tree is outside ui/**, so this seat does not take it. Back to pm:queue with pm:retriage: triage, please relabel the remainder to the lane that owns packages/lint (the anchoring rule says domain:spec) or split it. The assignee is cleared.
The maintainer agreed to ruling A at 21:38Z: the ui only renders the localized sentence from _diagnostics.errors[].code plus the item path, and the wire does not move. domain:server#2 routed it. The card is already domain:ui. pm:retriage and needs-user-decision are removed.
Claim: PM loop round 6 (item 3 only) · 2026-11-05T22:43Z
Session: session_01L6bhgWn6zhNa4LL7VB1rtL
Account: os-sales (the seat's linked user as GET /user answers it; the card's assignee)
Branch: the card thread's designated claude/project-thread-* branch, named in a claim amendment once the thread reports it
Worktree: objectstack-issue-30038
Domain: domain:ui
Seat: domain:ui#1
File surface: the Studio Problems path for a draft's server diagnostics in ui/packages/app-shell/src/views/metadata-admin/: previews/flow-problems.ts (ServerDiagnostic gains code?: string, :70 on 788715ef), draftVerdict.ts (verdictPreviewEntries, :88), ResourceEditPage.tsx (where the draft's _diagnostics become entries, :894 / :1378), and one new module beside them that renders the localized sentence for the two rule ids; the copy in ui/packages/i18n/src/namespaces/studio/*.ts (the namespace carries en.ts and zh.ts today: "every locale" of ruling item 5 is every catalogue that namespace has, and the dev states it); their tests; one root .changeset/ file. ⛔ packages/** (the lint producer and the wire shape do not move, ruling A), ⛔ ObjectPicker.tsx and the new-automation dialog (items 1, 2 and 4 landed in PR #30148), ⛔ the eager language packs ui/packages/i18n/src/locales/*.ts. Stop on breach and explain in the report.
Container & model: M, mode:thread, model: default (opus) (dispatch-gates --tier: no path-derived mandate; floor sonnet · default opus · ceiling fable), effort: high
Clause-②: no (an app-shell-internal diagnostic shape and new studio namespace keys; no package export, no wire change. Re-read at ACCEPT)
Metadata-protocol: none
Responsibility: after a new automation is saved on an object outside its package's closure, the Problems panel explains the refusal in English and in packaging terms | Studio shows the server's _diagnostics.errors[].message verbatim and drops its code | a Console user in any non-English locale who builds a flow in Studio; reach named on the card: zh-CN, example CRM, a trigger object typed as a prefix
Thread-read: 6670535944
Premise: holds on origin/main788715ef: ServerDiagnostic (flow-problems.ts:70) carries path, message and severity only, so no ui position can tell which rule raised an entry; the two rule ids are flow-trigger-unknown-object and flow-input-unknown-object (packages/lint/src/rule-explanations.ts:2140, :2164). The dev re-reads the three positions and the _diagnostics entry a live draft carries before the first edit.
Ruling carried (verbatim, 6670300925, maintainer 「同意」 2026-11-05T21:38Z): "Studio renders the localized sentence from _diagnostics.errors[].code (= the rule id) plus the item's relative path; the wire shape does not move." Its items 1-6 bind the dev: two rule ids at three positions and only this sentence; the object name from the draft at path and the package id from Studio's current package; "Did you mean" kept only if it can be recomputed cheaply, else "pick an object from the list, or add the package that declares it to the manifest's dependencies"; code threaded through ResourceEditPage.tsx, draftVerdict.ts, previews/flow-problems.ts; an unmatched code shows the server's English sentence as today; copy in the studio namespace with pins that a zh-CN hit renders Chinese and an unknown code passes through. B and D are not ruled; a general mechanism is a separate domain:spec card.
Serial constraints: the file lists of the open PRs read at claim time (49 PRs): none touches ui/packages/app-shell/src/views/metadata-admin/{ResourceEditPage.tsx,draftVerdict.ts,previews/flow-problems.ts} or ui/packages/i18n/src/namespaces/studio/**. PR #30595 (#30511, domain:ui#5) re-tags the Console's locales and is serialized behind PR #30640; whichever lands second carries the other's keys or locale tags, and this seat sends Notify: serial to domain:ui#5 (#30425) at the first push.
The card thread's harness-designated branch (a project-thread platform exception to the claude/issue-<n>-<slug> convention); the dev thread is session session_01L6bhgU6Ui5Bf4TtimeCqH2. Everything else in claim 6671486399 stands.
{
"issue": 30038,
"status": "done",
"branch": "claude/project-thread-saey5n",
"pr": "https://github.com/objectstack-ai/objectstack/pull/30721",
"session": "session_01L6bhgU6Ui5Bf4TtimeCqH2",
"premise_still_valid": true,
"summary": "Item 3 only, ruling A (6670300925). Premise held on origin/main 4bf9a2d7e: ServerDiagnostic (previews/flow-problems.ts) carried path, message and severity only; verdictPreviewEntries and ResourceEditPage previewDiagnostics dropped the served code. A new module previews/flow-closure-refusal.ts words the refusal from code + item-relative path at the ruling's three positions (flow-trigger-unknown-object at nodes.N.config.objectName and nodes.N.config.timeRelative.object, flow-input-unknown-object at variables.N.objectName), naming the object the flow on screen holds there; any other entry shows the server's message as sent. code is threaded through flow-problems.ts (ServerDiagnostic.code, buildFlowProblems), draftVerdict.ts (verdictPreviewEntries) and ResourceEditPage.tsx (previewDiagnostics). Studio's Automations pillar reaches it through verdictPreviewEntries plus its existing spread, so StudioDesignSurface.tsx is unchanged. Copy: 3 keys in the studio namespace en.ts + zh.ts (its only two catalogues); the eager locales/*.ts packs are untouched. DEVIATION, declared: ruling item 2's package id is not printed; the sentence says 'this package', because buildFlowProblems/FlowPreview receive no package and threading one crosses the file surface (preview-registry.ts, FlowPreview.tsx, StudioDesignSurface.tsx). 'Did you mean' not recomputed (ruling fallback wording used). The worktree was created from the shared checkout after detaching it, since the harness branch was checked out there.",
"tests": "On ac42ace6 (1f905121 only adds the changeset). Lock VERDICT command-exit 0: vitest over flow-problems.closureRefusal-30038.test.ts (new, 7), ResourceEditPage.draftPublishVerdict-26707.test.tsx (+1 describe), draftVerdict.test.ts, flow-problems.test.ts, i18n studio-namespace.test.ts: Test Files 5 passed (5), Tests 52 passed (52). Ablation via scripts/ablation-replace.mjs, src imported directly (no dist), each leg restored blob == HEAD and git diff HEAD empty: A flow-problems.ts closureRefusalMessage call -> (undefined as string | undefined): 4 failed / 3 passed (7); B draftVerdict.ts code spread deleted: 1 failed / 6 passed; C ResourceEditPage.tsx code spread deleted: 1 failed / 3 passed (4). First attempts at A, B, C were refused before running (replacement inside anchor), re-run with a distinct replacement / --delete. Type check: turbo run type-check --filter=./ui/packages/app-shell --filter=./ui/packages/i18n: Tasks 68 successful, 68 total, lock VERDICT command-exit 0.",
"gates": "dispatch-gates --commands (merge base 4bf9a2d7e, 9 paths, head 1f905121): 35 families, each exit captured before any pipe, 35/35 exit 0 (incl. ui vitest scripts/ under lock, check:type-check-debt, check:type-check-coverage, check:nul-bytes, check:published-files). --ran: 35 derived, 35 run, 0 NOT-MEASURED (derived zero, all 35 with exit codes). Per-file eslint --no-inline-config: 3 errors in ResourceEditPage.tsx L3444/3577/3600 react-hooks/static-components, identical count (3) on origin/main via --stdin, none in this diff's hunks. PR check-runs: not awaited.",
"dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
"mcp_calls": "2 — mcp__github__issue_read get and get_comments on #30038 (reads); no write tool",
"api_writes": "2 — pr_create via fleet-write relay (POST /repos/objectstack-ai/objectstack/pulls, draft, no labels, no assignees: PR #30721, 9714 bytes read back identical); this os-dev-report comment via post-stamped.mjs (POST /repos/objectstack-ai/objectstack/issues/30038/comments). Plus git push (not REST).",
"open_questions": [
{
"question": "Should the sentence print the package id (ruling item 2) rather than 'this package'?",
"options": [
"A — keep 'this package' as landed; the Studio page already shows the package",
"B — follow-up: add an optional package to MetadataPreviewProps, set it from StudioDesignSurface and ResourceEditPage, and pass it to buildFlowProblems (touches preview-registry.ts, FlowPreview.tsx, StudioDesignSurface.tsx)"
],
"recommendation": "A, because the reader is inside the package being edited, and B widens a registry contract for one noun"
}
],
"security_findings": "none",
"out_of_scope_findings": [
"carrier: none · ResourceEditPage's diagnostics banner and SchemaForm inline issues still show the served English for these two rule ids (ruling scope is the Problems list) · noted, not filed",
"carrier: none · MetadataPreviewProps.diagnostics (preview-registry.ts) does not declare code; it passes structurally and both new pins hold the behaviour · noted, not filed"
]
}
ACCEPT → PR #30721 comment 6672428611 · head 1f905121 · 2026-11-05T23:40Z — pr_ready + automerge_enable relayed; the card closes on the merge (Fixes, item 3 was the last open item). Accepted deviation: the sentence says "this package" rather than printing the package id (ruling item 2), since the Problems list has no package to name without widening the published MetadataPreviewProps.
:297 (a served error with one of the two rule ids at its three positions is worded in the Console's language; anything else shows the server's sentence)
git grep -n "export function closureRefusalMessage" origin/main -- ui/packages/app-shell/src/views/metadata-admin/previews/flow-closure-refusal.ts
:80
State: item 3 was the card's last open item (items 1, 2 and 4 landed in PR #30148); the card closed on the merge (Fixes), and pm:dispatched is removed in the same stroke. As accepted at ACCEPT, the sentence says "this package" rather than printing the package id. Still outside this card: Resource Edit's diagnostics banner and inline form issues show the server's English for these two rule ids (the ruling's scope was the Problems list).
Activity
objectstack-fleet commentedon Nov 4, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: first-touch audit · p2 kept ·
domain:ui· 2026-11-04T11:00Z⛔ Not a claim.
Generated by Claude Code
objectstack-fleet commentedon Nov 4, 2026
domain:ui#3 · os-justin · session_01QSeKYpFBMr917PmVkG9up7
Claim: PM loop round 1
Session:
session_01QSeKYpFBMr917PmVkG9up7Account:
os-justinBranch:
claude/issue-30038-trigger-object-enterWorktree:
objectstack-issue-30038Domain:
domain:uiSeat:
domain:ui#3File surface:
ui/packages/app-shell/src/views/metadata-admin/inspectors/ObjectPicker.tsx,ui/packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx(new-automation dialog region only, about:9717–:9771), their tests, and the zh/en strings inui/packages/i18nfor the closure-refusal text (stop on breach; explain in the report)Container & model:
M,mode:subagent,model: opus(dispatch-gates--tier: no path-derived mandate; default tier),effort: highClause-②: no
Metadata-protocol: none
Responsibility:
ui ObjectPicker's Enter-commits-typed-text branch, used at a door where no expression is legal|none — the closure check on 问题 catches it only after save|any Studio admin creating an automation; reachable todayThread-read: 6628973335
Premise: holds (
ObjectPicker.tsx:368else if (typed) commit(text);onorigin/main55337f4c)Serial constraints cleared: none (no live
domain:uiclaim namesObjectPicker.tsxor the new-automation dialog)Acceptance item 3 (closure refusal wording): if that text is produced server-side, the dev reports it as out-of-scope with a carrier, not a cross-lane edit.
Generated by Claude Code
objectstack-fleet commentedon Nov 4, 2026
domain:ui#3 · os-justin · session_01QSeKYpFBMr917PmVkG9up7
os-dev-report
{ "issue": 30038, "status": "done", "branch": "claude/issue-30038-trigger-object-enter", "pr": "https://github.com/objectstack-ai/objectstack/pull/30148", "session": "session_01QSeKYpFBMr917PmVkG9up7", "premise_still_valid": true, "summary": "Premise held on origin/main 55337f4ce: ObjectPicker.tsx:368 `else if (typed) commit(text);`. ObjectPicker gains an opt-in `objectsOnly` prop. With it, Enter and blur commit the pickable object named exactly, else the only pickable match left, else an empty commit plus a role=alert line 'No object chosen: \"TEXT\" is not an object. Choose one from the list.' (zh/en keys engine.inspector.objectPicker.notChosen and noMatchObjectsOnly). StudioDesignSurface's New automation dialog turns it on for both trigger-object pickers (record preset and Advanced). A record preset with no object then keeps the dialog open with the existing needsObject line. FlowReferenceField and every other ObjectPicker use are unchanged (free text), so items 1, 2 and 4 are done. Item 3 is NOT here: the closure refusal is produced by packages/lint/src/validate-flow-trigger-readiness.ts:513 (server side, outside ui/**). The PR body says `Refs #30038 (items 1, 2, 4)`, so the card stays open for item 3. Harness note: the run used the harness-provided worktree (.claude/worktrees/agent-ada62fbd8c4db7be3) on the claim's branch, not ../objectstack-issue-30038. The empty branch was pushed before the first commit.", "tests": "Head 29b6b028e. `pnpm --dir ui exec vitest run --maxWorkers=2 packages/app-shell/src/views/metadata-admin/inspectors/ObjectPicker.test.tsx packages/app-shell/src/views/studio-design/StudioDesignSurface.createTaken-26917.test.tsx` under the lock: `Test Files 2 passed (2) / Tests 25 passed (25)`, VERDICT command-exit 0. New: 5 picker cases (one-match prefix+Enter commits the match; several matches commits nothing and shows refusal; non-object clears on Enter and on blur; full name commits; default free text commits the prefix as typed = item 2) and 2 door cases (record_updated preset: 'tick'+Enter+Create saves Start objectName acme_ticket; 'acme'+Enter+Create saves nothing, refusal + needsObject shown, dialog open). Ablation via scripts/ablation-replace.mjs, restored to HEAD each leg (blob == HEAD, git diff HEAD empty). Tests import src directly (relative), so no dist is involved. Leg A: ObjectPicker `if (!objectsOnly || catalog.status !== 'loaded') {` replaced with `if (true) {` (blob e2118e0a8872 to 53ef6e70092f): 5 failed / 20 passed, all objectsOnly-dependent cases red, free-text case green. Leg B: door `objectsOnly` replaced with `objectsOnly={false}` (blob fc99d66e24c9 to b3f8845a7e8e): 2 failed / 8 passed, both door cases red. The first Leg B attempt was a no-op that the tool refused before running (the replacement was already inside the anchor). The anchor was changed and the leg re-run. Type-check: `pnpm exec turbo run type-check --filter=./ui/packages/app-shell`: Tasks 68 successful, 68 total, @object-ui/app-shell:type-check ran `tsc --noEmit && tsc -p tsconfig.test.json`, VERDICT command-exit 0. Narrowed (declared): the ui/packages/i18n package suite was not run locally, because the lock was held about 22 min by another agent's run that includes packages/i18n/ (pid 31527). NOT MEASURED locally, declared to CI. scripts/ vitest (incl. check-i18n-call-site-keys) passed.", "gates": "Derived by `node scripts/pm/dispatch-gates.mjs --commands` (merge base 55337f4ce, 7 paths, head 29b6b028e): 35 families. Each was run and its exit captured before any pipe. 34 exit 0: check-adr-0087-registration (+self-test), check-changeset-no-major, check-closing-keyword-parity (+self-test), check-comment-mask-corpus, check-empty-changeset (+self-test), check-sdui-manifest (+self-test), release-rehearsal-clone --self-test, release-pending-publish --self-test, `pnpm --dir ui exec vitest run scripts/` (lock VERDICT command-exit 0), spec check:duration-unit-keys, check:changeset-gate-self-tests, closed-ceremony-text, cross-package-test-inputs, dispatcher-error-vocabulary, driver-memory-census, engine-double-contract, gitlink-declared, nul-bytes, published-files, query-options-erasure, refd-timer-probe, registry-log-declared, rest-log-spy-declared, skill-identifier-liveness, test-source-alias, tier-file-adoption, type-check-coverage, undeclared-dep-imports, watch-hint-literal, where-matcher. `pnpm check:type-check-debt`: exit 3, PREREQUISITE NOT MET. Its closure build hit lock queue-timeout 99 twice (holder pid 31527, another agent's vitest run, held more than 22 min), so it is NOT MEASURED, declared narrowed to CI. `--ran` reconciliation: 35 derived, 35 run, 0 UNRUN. PR check-runs: in_progress at report time, not awaited.", "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm", "mcp_calls": "0", "api_writes": "2 — pr_create via fleet-write relay (POST /repos/objectstack-ai/objectstack/pulls, draft, no labels, no assignees: PR #30148, 5952 bytes read back identical); os-dev-report comment on #30038 via post-stamped.mjs (POST /repos/objectstack-ai/objectstack/issues/30038/comments). Plus git push (not REST).", "open_questions": [], "security_findings": "none", "out_of_scope_findings": [ "class: a (user-visible experience defect: an untranslated refusal the reader cannot act on) · reach: public door, Studio 问题 panel on a zh-CN Console, per the card's reviewer screenshot: an English sentence 'triggers on object X, which is outside the closure of package P (... `dependencies` ...)'. The text is the `message` of a packages/lint finding, packages/lint/src/validate-flow-trigger-readiness.ts:513 (rule FLOW_TRIGGER_UNKNOWN_OBJECT, hint from closureDependencyRemedy). The finding carries no structured params (objectName, packageId) that a ui renderer could localize from, so the fix is at the producer (structured params or a code the Console keys on), outside the ui/** lane · Seam: lint:FLOW_TRIGGER_UNKNOWN_OBJECT message → renderer: Studio 问题 panel · carrier: #30038 (item 3 stays open; PR uses Refs) · dedupe words: closure refusal localize, FLOW_TRIGGER_UNKNOWN_OBJECT i18n, validate-flow-trigger-readiness message zh, lint finding structured params" ] }Generated by Claude Code
objectstack-fleet commentedon Nov 4, 2026
domain:ui#3 · os-justin · session_01QSeKYpFBMr917PmVkG9up7
ACCEPT · PR #30148 · head
29b6b028e· 2026-11-04T16:58ZSeat review of the diff (read via
GET /pulls/30148diff, not the report):ObjectPickergains an opt-inobjectsOnlyprop, off by default. With it,commitTypedcommits the pickable option named exactly, else the only pickable option left, else''plus arole=alertrefusal. Both trigger-object pickers in the New automation dialog (StudioDesignSurface.tsx, record preset and Advanced) turn it on. Every other use keeps free text (item 2). zh/en keys were added inui/packages/i18nstudio namespaces.objectsOnlystill commits the typed text (docstring says so). It is a narrow residual window; the closure check on 问题 still catches it. No follow-up card.29b6b028eshow 55 runs: 44 success, 11 skipped, 0 red.check-governed-merges --pr 30148says NOT governed, 192 changed lines.mergeable_statereadsclean. The dev declared two runs NOT MEASURED locally because of lock contention, theui/packages/i18nsuite andcheck:type-check-debt. CI covered both, green.packages/lint/src/validate-flow-trigger-readiness.ts:513(FLOW_TRIGGER_UNKNOWN_OBJECT), with no structured params a renderer could localize from. That is outsideui/**. Carrier: this card. The PR saysRefs #30038 (items 1, 2, 4). At MERGED the seat releases this card with item 3 as the remainder and asks triage to relabel (pm:retriage).pr_ready+automerge_enable. Held: the same landing stroke on PR fix(app-shell): match sys_user.locale in the server resolveLocale order #30150 was refused by this session's auto-mode classifier (i18n: sys_user.locale still stores a shape-valid tag no platform locale serves (xx-YY) with 200, and the console's exact-match locale pick still renders English for legacy mis-cased rows and for zh / zh-Hans-CN / en-GB #30050 comment 6636572112). The seat does not retry until the maintainer allows it or lands this by hand.Generated by Claude Code
objectstack-fleet commentedon Nov 5, 2026
domain:ui#3 · os-justin · session_01QSeKYpFBMr917PmVkG9up7
Landed (partial) · PR #30148 · 2026-11-05T01:06Z
03be5655bat 2026-11-05T01:05:25Z, via the merge queueorigin/maingit grep -c "objectsOnly" origin/main -- …/inspectors/ObjectPicker.tsx …/studio-design/StudioDesignSurface.tsx→ 7 and 2Release: items 1, 2 and 4 landed in PR #30148 (
Refs #30038 (items 1, 2, 4)). Item 3 is left: the closure refusal on 问题 must read in the Console's language. Its producer ispackages/lint/src/validate-flow-trigger-readiness.ts:513(FLOW_TRIGGER_UNKNOWN_OBJECT), whose finding carries no structured params a renderer could localize from. That tree is outsideui/**, so this seat does not take it. Back topm:queuewithpm:retriage: triage, please relabel the remainder to the lane that ownspackages/lint(the anchoring rule saysdomain:spec) or split it. The assignee is cleared.Generated by Claude Code
19 remaining items
objectstack-fleet commentedon Nov 5, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: retriage answered ·
domain:ui· p3 kept · 2026-11-05T21:53Z⛔ Not a claim.
_diagnostics.errors[].codeplus the item path, and the wire does not move.domain:server#2routed it. The card is alreadydomain:ui.pm:retriageandneeds-user-decisionare removed.Generated by Claude Code
objectstack-fleet commentedon Nov 5, 2026
domain:ui#1 · os-sales · session_01L6bhgWn6zhNa4LL7VB1rtL
Claim: PM loop round 6 (item 3 only) · 2026-11-05T22:43Z
Session:
session_01L6bhgWn6zhNa4LL7VB1rtLAccount:
os-sales(the seat's linked user asGET /useranswers it; the card's assignee)Branch: the card thread's designated
claude/project-thread-*branch, named in a claim amendment once the thread reports itWorktree:
objectstack-issue-30038Domain:
domain:uiSeat:
domain:ui#1File surface: the Studio Problems path for a draft's server diagnostics in
ui/packages/app-shell/src/views/metadata-admin/:previews/flow-problems.ts(ServerDiagnosticgainscode?: string,:70on788715ef),draftVerdict.ts(verdictPreviewEntries,:88),ResourceEditPage.tsx(where the draft's_diagnosticsbecome entries,:894/:1378), and one new module beside them that renders the localized sentence for the two rule ids; the copy inui/packages/i18n/src/namespaces/studio/*.ts(the namespace carriesen.tsandzh.tstoday: "every locale" of ruling item 5 is every catalogue that namespace has, and the dev states it); their tests; one root.changeset/file. ⛔packages/**(the lint producer and the wire shape do not move, ruling A), ⛔ObjectPicker.tsxand the new-automation dialog (items 1, 2 and 4 landed in PR #30148), ⛔ the eager language packsui/packages/i18n/src/locales/*.ts. Stop on breach and explain in the report.Container & model:
M,mode:thread,model: default (opus)(dispatch-gates --tier: no path-derived mandate; floor sonnet · default opus · ceiling fable),effort: highClause-②: no (an app-shell-internal diagnostic shape and new studio namespace keys; no package export, no wire change. Re-read at ACCEPT)
Metadata-protocol: none
Responsibility: after a new automation is saved on an object outside its package's closure, the Problems panel explains the refusal in English and in packaging terms | Studio shows the server's
_diagnostics.errors[].messageverbatim and drops itscode| a Console user in any non-English locale who builds a flow in Studio; reach named on the card: zh-CN, example CRM, a trigger object typed as a prefixThread-read: 6670535944
Premise: holds on
origin/main788715ef:ServerDiagnostic(flow-problems.ts:70) carriespath,messageandseverityonly, so no ui position can tell which rule raised an entry; the two rule ids areflow-trigger-unknown-objectandflow-input-unknown-object(packages/lint/src/rule-explanations.ts:2140,:2164). The dev re-reads the three positions and the_diagnosticsentry a live draft carries before the first edit.Ruling carried (verbatim, 6670300925, maintainer 「同意」 2026-11-05T21:38Z): "Studio renders the localized sentence from
_diagnostics.errors[].code(= the rule id) plus the item's relativepath; the wire shape does not move." Its items 1-6 bind the dev: two rule ids at three positions and only this sentence; the object name from the draft atpathand the package id from Studio's current package; "Did you mean" kept only if it can be recomputed cheaply, else "pick an object from the list, or add the package that declares it to the manifest'sdependencies";codethreaded throughResourceEditPage.tsx,draftVerdict.ts,previews/flow-problems.ts; an unmatchedcodeshows the server's English sentence as today; copy in thestudionamespace with pins that azh-CNhit renders Chinese and an unknown code passes through. B and D are not ruled; a general mechanism is a separatedomain:speccard.Serial constraints: the file lists of the open PRs read at claim time (49 PRs): none touches
ui/packages/app-shell/src/views/metadata-admin/{ResourceEditPage.tsx,draftVerdict.ts,previews/flow-problems.ts}orui/packages/i18n/src/namespaces/studio/**. PR #30595 (#30511,domain:ui#5) re-tags the Console's locales and is serialized behind PR #30640; whichever lands second carries the other's keys or locale tags, and this seat sendsNotify: serialtodomain:ui#5(#30425) at the first push.objectstack-fleet commentedon Nov 5, 2026
domain:ui#1 · os-sales · session_01L6bhgWn6zhNa4LL7VB1rtL
席位核对 · Amendment · 2026-11-05T22:50Z · claim 6671486399 branch named
Branch:
claude/project-thread-saey5nWorktree:
objectstack-issue-30038The card thread's harness-designated branch (a project-thread platform exception to the
claude/issue-<n>-<slug>convention); the dev thread is sessionsession_01L6bhgU6Ui5Bf4TtimeCqH2. Everything else in claim 6671486399 stands.objectstack-fleet commentedon Nov 5, 2026
domain:ui#1 · os-sales · session_01L6bhgWn6zhNa4LL7VB1rtL
os-dev-report
{ "issue": 30038, "status": "done", "branch": "claude/project-thread-saey5n", "pr": "https://github.com/objectstack-ai/objectstack/pull/30721", "session": "session_01L6bhgU6Ui5Bf4TtimeCqH2", "premise_still_valid": true, "summary": "Item 3 only, ruling A (6670300925). Premise held on origin/main 4bf9a2d7e: ServerDiagnostic (previews/flow-problems.ts) carried path, message and severity only; verdictPreviewEntries and ResourceEditPage previewDiagnostics dropped the served code. A new module previews/flow-closure-refusal.ts words the refusal from code + item-relative path at the ruling's three positions (flow-trigger-unknown-object at nodes.N.config.objectName and nodes.N.config.timeRelative.object, flow-input-unknown-object at variables.N.objectName), naming the object the flow on screen holds there; any other entry shows the server's message as sent. code is threaded through flow-problems.ts (ServerDiagnostic.code, buildFlowProblems), draftVerdict.ts (verdictPreviewEntries) and ResourceEditPage.tsx (previewDiagnostics). Studio's Automations pillar reaches it through verdictPreviewEntries plus its existing spread, so StudioDesignSurface.tsx is unchanged. Copy: 3 keys in the studio namespace en.ts + zh.ts (its only two catalogues); the eager locales/*.ts packs are untouched. DEVIATION, declared: ruling item 2's package id is not printed; the sentence says 'this package', because buildFlowProblems/FlowPreview receive no package and threading one crosses the file surface (preview-registry.ts, FlowPreview.tsx, StudioDesignSurface.tsx). 'Did you mean' not recomputed (ruling fallback wording used). The worktree was created from the shared checkout after detaching it, since the harness branch was checked out there.", "tests": "On ac42ace6 (1f905121 only adds the changeset). Lock VERDICT command-exit 0: vitest over flow-problems.closureRefusal-30038.test.ts (new, 7), ResourceEditPage.draftPublishVerdict-26707.test.tsx (+1 describe), draftVerdict.test.ts, flow-problems.test.ts, i18n studio-namespace.test.ts: Test Files 5 passed (5), Tests 52 passed (52). Ablation via scripts/ablation-replace.mjs, src imported directly (no dist), each leg restored blob == HEAD and git diff HEAD empty: A flow-problems.ts closureRefusalMessage call -> (undefined as string | undefined): 4 failed / 3 passed (7); B draftVerdict.ts code spread deleted: 1 failed / 6 passed; C ResourceEditPage.tsx code spread deleted: 1 failed / 3 passed (4). First attempts at A, B, C were refused before running (replacement inside anchor), re-run with a distinct replacement / --delete. Type check: turbo run type-check --filter=./ui/packages/app-shell --filter=./ui/packages/i18n: Tasks 68 successful, 68 total, lock VERDICT command-exit 0.", "gates": "dispatch-gates --commands (merge base 4bf9a2d7e, 9 paths, head 1f905121): 35 families, each exit captured before any pipe, 35/35 exit 0 (incl. ui vitest scripts/ under lock, check:type-check-debt, check:type-check-coverage, check:nul-bytes, check:published-files). --ran: 35 derived, 35 run, 0 NOT-MEASURED (derived zero, all 35 with exit codes). Per-file eslint --no-inline-config: 3 errors in ResourceEditPage.tsx L3444/3577/3600 react-hooks/static-components, identical count (3) on origin/main via --stdin, none in this diff's hunks. PR check-runs: not awaited.", "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm", "mcp_calls": "2 — mcp__github__issue_read get and get_comments on #30038 (reads); no write tool", "api_writes": "2 — pr_create via fleet-write relay (POST /repos/objectstack-ai/objectstack/pulls, draft, no labels, no assignees: PR #30721, 9714 bytes read back identical); this os-dev-report comment via post-stamped.mjs (POST /repos/objectstack-ai/objectstack/issues/30038/comments). Plus git push (not REST).", "open_questions": [ { "question": "Should the sentence print the package id (ruling item 2) rather than 'this package'?", "options": [ "A — keep 'this package' as landed; the Studio page already shows the package", "B — follow-up: add an optional package to MetadataPreviewProps, set it from StudioDesignSurface and ResourceEditPage, and pass it to buildFlowProblems (touches preview-registry.ts, FlowPreview.tsx, StudioDesignSurface.tsx)" ], "recommendation": "A, because the reader is inside the package being edited, and B widens a registry contract for one noun" } ], "security_findings": "none", "out_of_scope_findings": [ "carrier: none · ResourceEditPage's diagnostics banner and SchemaForm inline issues still show the served English for these two rule ids (ruling scope is the Problems list) · noted, not filed", "carrier: none · MetadataPreviewProps.diagnostics (preview-registry.ts) does not declare code; it passes structurally and both new pins hold the behaviour · noted, not filed" ] }Report taken 2026-11-05T23:20Z.
Generated by Claude Code
objectstack-fleet commentedon Nov 5, 2026
domain:ui#1 · os-sales · session_01L6bhgWn6zhNa4LL7VB1rtL
ACCEPT → PR #30721 comment 6672428611 · head
1f905121· 2026-11-05T23:40Z —pr_ready+automerge_enablerelayed; the card closes on the merge (Fixes, item 3 was the last open item). Accepted deviation: the sentence says "this package" rather than printing the package id (ruling item 2), since the Problems list has no package to name without widening the publishedMetadataPreviewProps.objectstack-fleet commentedon Nov 5, 2026
domain:ui#1 · os-sales · session_01L6bhgWn6zhNa4LL7VB1rtL
Landed 2026-11-05T23:59Z: PR #30721 merged as
f0ad1f790c(seat ACCEPT 6672428611 on head1f905121), 2026-11-05T23:58:55Z on the PR.git grep -n "closureRefusalMessage(diag" origin/main -- ui/packages/app-shell/src/views/metadata-admin/previews/flow-problems.ts:297(a served error with one of the two rule ids at its three positions is worded in the Console's language; anything else shows the server's sentence)git grep -n "export function closureRefusalMessage" origin/main -- ui/packages/app-shell/src/views/metadata-admin/previews/flow-closure-refusal.ts:80State: item 3 was the card's last open item (items 1, 2 and 4 landed in PR #30148); the card closed on the merge (
Fixes), andpm:dispatchedis removed in the same stroke. As accepted at ACCEPT, the sentence says "this package" rather than printing the package id. Still outside this card: Resource Edit's diagnostics banner and inline form issues show the server's English for these two rule ids (the ruling's scope was the Problems list).