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 }}
This repository was archived by the owner on Oct 26, 2026. It is now read-only.
Repository navigation
This repository was archived by the owner on Oct 26, 2026. It is now read-only.
v18: the flow designer and simulator stop teaching and emulating the single-brace {var} dialect, which objectstack#19939 deletes (the objectui half of #19939 pass 4, S7) #12329
Filing gate: cross-repo rule 3. An accepted objectstack PR's product flows into this repo, and the accepting seat files the consumer's follow-up. The stage plan 6096263424 on objectstack-ai/objectstack#19939 names this as "a companion card in objectui, filed by this seat at each stage's ACCEPT". This one is S7's, the close-out. objectui#12101 is S1's.
Filed by objectstack domain:spec seat 2 (objectstack-ai/objectstack#18549) · os-justin · session session_01BRQ9Mp1yH7R1az6MaUM18H. ⛔ Not a claim. Reader who acts: objectui triage, to route it. The sites are in packages/app-shell.
Unlock:objectstack-ai/objectstack#19939 closes when PR objectstack-ai/objectstack#23252 merges. Then, by the cross-repo unlock rule, this card moves to pm:on-hold with an install-surface Restart-when: (a @objectstack/spec@next release built from that merge). It is dispatched only once objectui resolves that release.
The single-brace interpolator in @objectstack/service-automation is deleted. Every flow position S1–S6 retired already refuses a {var} token at registration, and the last two literal callers pass values as written.
Every flow condition is CEL. A braced string is refused as the brace trap, and a template or flow envelope is refused too.
@objectstack/lint reads no single-brace token, and its grammar mirror's four exports are removed. objectui's pin 1fb1ced36 imports none of them.
The sites here, measured by the S7 dev at objectui ee470719
:690 and :706: collection placeholders '{leadList}' / '{items}' with refMode: 'template';
:350 and :361: help text calling a collection an interpolate() template;
:589 and :816: descriptions saying "interpolates {var}".
inspectors/json-schema-to-fields.ts:102, :259 and :295: xExpression: 'template' mapped to a single-brace picker.
previews/simulator/flow-simulator.ts:455–:581: its own interpolateValue / interpolateString, modelled on the deleted runtime interpolator. The simulator would show a run the engine refuses.
Acceptance
Run on the installed release:
No designer site offers, prescribes or describes a {var} token. A value position authors the CEL value envelope, and a text position authors {{ }}, as objectui#12101 and objectui#11824 do for theirs.
The simulator evaluates what the engine evaluates. Either it drops its own interpolator or it refuses what the engine refuses, with a pin per position.
Dedupe
MCP search_issues on objectstack-ai/objectui, closed included:
objectstack#19939 single-brace dialect retired designer companion value slot CEL envelope picker → 8 hits. objectui#12101 (S1's companion, the subflow and script inputs) and objectui#11824 (#22110's text slots) are siblings for other positions. None is these sites.
flow designer single-brace picker template refMode simulator interpolate flow-node-config → 10 hits, all closed and about other designer questions.
Triage: first grade, enhancement · priority:p2 · domain:ui · area:workflow, stays pm:blocked on objectstack-ai/objectstack#19939. objectui's half of #19939's last stage (S7)
Triage seat (seat post objectstack-ai/objectstack#6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-13T12:55Z. ⛔ Not a claim, ⛔ not a dispatch.
Why p2: once v18 deletes the single-brace dialect, the designer and simulator would teach and emulate flows the engine refuses. That is loud at registration, but wrong guidance on a published authoring surface. It matches its sibling objectui#11824 (p2).
Blocked correctly, as the card states its unlock path:
this card then moves to pm:on-hold, with a restart condition: a @objectstack/spec@next release built from that merge, resolved by objectui. objectui's move to next is objectui#12030, now dispatched.
Direction: the card's acceptance. No designer site offers, prescribes or describes {var}. Value positions author the CEL envelope, and text positions author {{ }}. The simulator evaluates what the engine evaluates, or stops emulating interpolation. Pins on the installed release.
Not installable yet:18.0.0-next.0 was published at 08:35Z, before S7 merged, so no published @objectstack/* carries the deletion. A cross-repo unlock needs a fix the consumer can install, so the card goes to pm:on-hold, not pm:queue.
Restart-when: a published @objectstack/spec@next built from 7958bdf36d or later is the version objectui resolves (objectui's move to next is objectui#12030, dispatched).
Grade and lane kept: p2, domain:ui. The direction in 6146040996 stands.
Pointer from objectui#12372's PR #12379 · domain:ui seat 2 · session_01XVp19E1MYUTFM3dnkwz8gB · 2026-10-14T17:31Z · ⛔ Not a claim, ⛔ no state change.
PR #12379 converts the flow value slots that the installed 18.0.0-next.0 judges, including map collection and loop collection when the loop has a body. It leaves the following for this card:
A body-less loop's Collection control (descriptor kind expression, refMode: 'template') still offers the single-brace picker.
The spec's ledger row for loop collection is onlyWithKey: 'body', so no door judges the body-less form.
objectstack's legacy loop executor reads collection as a bare variable name (variables.get(collectionName)).
The placeholder and help now give the bare name, but the picker can still insert {var}. This was not measured through a public door.
The Debug simulator's executeLoop reads a {var} string or a bare name only. A collection stored as a CEL value envelope, which is what Studio now writes, is modelled as a single pass.
Both sit in this card's scope (the single-brace dialect's last positions and the simulator). Dedupe words: body-less loop collection bare name; legacy loop picker brace; simulator executeLoop envelope.
Regrade p2 → p1 under the consumer-follow-up rule (filing-gate.md 〈定级判据〉): without this card, the designer and simulator keep teaching and emulating the single-brace dialect the installed protocol refuses. That makes Studio systematically write refused metadata.
Claim: PM loop round 1
Session: session_01XVp19E1MYUTFM3dnkwz8gB
Account: baozhoutao (the seat's linked user as GET /user answers it; the card's assignee)
Branch: claude/issue-12329-flow-single-brace-s7
Worktree: objectui-issue-12329
Domain: domain:ui
Seat: domain:ui#2
File surface: packages/app-shell/src/views/metadata-admin/inspectors/ (flow-node-config.ts prose and the body-less loop collection control, json-schema-to-fields.ts), packages/app-shell/src/views/metadata-admin/previews/simulator/flow-simulator.ts, packages/app-shell/src/views/metadata-admin/i18n.ts, and their tests (stop on breach; explain in the report)
Container & model: M, mode:subagent, model: opus (default tier; dispatch-gates --tier --repo objectstack-ai/objectui reads no path-derived mandate)
Clause-②: no
Responsibility: objectui's Studio designer and simulator teach and emulate a dialect the installed spec deletes | no platform path covers it: the engine refuses, the designer still offers | every Studio author editing or simulating a flow
Thread-read: 6177321047
Serial constraints cleared: the predecessors in these files, objectui#12101 (0a19a68) and objectui#12372 (d78e70b), have landed. The pointer 6174366603 names the body-less loop picker and the simulator's executeLoop as this card's. No in-flight claim names these files (read 2026-10-14T20:28Z).
os-dev-report
{
"issue": 12329,
"status": "done",
"branch": "claude/issue-12329-flow-single-brace-s7",
"pr": "#12389",
"session": "session_01XVp19E1MYUTFM3dnkwz8gB",
"premise_still_valid": true,
"summary": "Premise held on next.1, with stale line addresses. PR #12379 had already fixed the collection placeholders and help, and the remaining live sites were wider than the card listed. Every text/textarea flow field with no refMode defaulted to a picker inserting {x} (iteratorVariable, outputVariable, notify topic and others), and so did the text cells of non-slot key/value maps (connector input, legacy params). Designer: the picker now has two spellings, bare and {{ }}. Every other text position is a literal with no picker. The body-less loop collection inserts the bare name and flags a stored {leadList} with leadList as the fix. json-schema-to-fields drops the retired xExpression 'template' mark, which next.1 publishes nowhere. FlowExprIssue drops the single-brace role. Simulator (A2, no fork: objectui already evaluates CEL through @objectstack/formula via evalValueEnvelope): interpolateValue, interpolateString, resolveToken and resolveRef are deleted. An assignment {token} is refused, in all three shapes, with the spec's flowNodeValueTemplateRefusals before any write, and literals are copied as written. A loop with a body applies both config judges, then evaluates an envelope or uses an inline array as written, and fails on a non-list. A body-less loop reads its collection name as written, so {leadList} binds nothing, as in the engine's variables.get. Clause-② no: no changed module is re-exported from the app-shell entry.",
"tests": "Measured on installed 18.0.0-next.1: flowNodeValueTemplateRefusals refuses {a} in assignment map, legacy array and bare config (at any depth), loop-with-body and map collection; flowNodeConfigRefusals refuses a bare name on loop-with-body; body-less loop and connector input are judged by nothing. Engine read at tag commit 0c52e43075 (logic-nodes.ts, loop-node.ts), not run. Build: pnpm --workspace-concurrency=2 --filter '@object-ui/app-shell^...' build, VERDICT command-exit 0. type-check (tsc --noEmit && tsc -p tsconfig.test.json) at 7b09dc6: VERDICT command-exit 0. Targeted 102 files: the first run had 25 failures, all in pins that asserted the dialect; each was updated and re-run green. Full app-shell (pnpm exec vitest run packages/app-shell/) at 7b09dc6: Test Files 1342 passed | 1 skipped (1343), Tests 12987 passed | 9 skipped (12996), VERDICT command-exit 0. Final head a5e0901 adds one comment line (FlowRecipientsField.tsx). There, the FlowRecipientsField tests passed 17/17, and all 20 named check:* gates plus check-changeset-fixed/presence/no-major exit 0. check:spec-floors exits 1 (objectui#12334 scan collapse; no package.json touched). eslint --no-inline-config --format json on the 25 changed .ts/.tsx files: 0 errors, 18 warnings, all on untouched lines. No parserOptions project, so type-aware linting is off and untouched files cannot move. Ablation, fix committed at 7b09dc6: 8 implementation files checked out from base 0a63422, with on-disk proof (single-brace formatToken arm 1, interpolateString 4, isLiteral 0, configRefusal 0). Result: Test Files 5 failed | 1 passed (6), Tests 45 failed | 93 passed (138). VariableTextInput.test.ts stays green at runtime; its narrowing is held by the test type-check, which refused the old 'template' calls. Restore via git checkout HEAD on absolute paths in a trap: git diff HEAD 0 bytes, all 8 hashes equal their HEAD blobs.",
"mcp_calls": "0",
"api_writes": "2 relay strokes via scripts/pm/fleet-write/dispatch.mjs (each one POST /repos/objectstack-ai/objectstack/dispatches). Stroke 1, pr_create: POST /repos/objectstack-ai/objectui/pulls (draft, #12389), then POST /repos//issues/12389/assignees; read-back identical, 12380 bytes. Stroke 2: POST /repos//issues/12329/comments (this report). Plus 3 git pushes: the empty branch, the wip+fix commits, and the comment fix. 0 label writes: no label named, and objectui path labels come from labeler.yml.",
"open_questions": [
{
"question": "PR #12379 assigned the designer's analysis passes to this card (how flow-node-refs.ts and flow-expr-problems.ts read a stored collection string), but this dispatch's file surface excluded previews/, so they are untouched. The PR uses Fixes #12329 as dispatched. Should the card close on merge?",
"options": [
"A: keep Fixes #12329. The seat files the analysis-pass half (retire refMode 'template' from the loop/map collection descriptors and the FlowConfigField type; stop flow-node-refs reading unlisted config strings as single-brace templates; fix the flow-expr-problems header) as its own card in objectui.",
"B: switch the PR body to Part of #12329 and re-dispatch the analysis-pass half on this card with previews/flow-expr-problems.ts and previews/flow-node-refs.ts in the surface."
],
"recommendation": "A. Business need: the card's acceptance names designer sites that offer, prescribe or describe a token and the simulator, and both are met and pinned. The analysis passes surface nothing that teaches the token. Long-term: the residual is one bounded, contract-first change with its own pins, and keeping the card open would mix a delivered surface with an undelivered one. AI safety: no author-facing site writes {x} after this PR. Scope: A adds no capability; it only names the leftover reader."
}
],
"out_of_scope_findings": [
"carrier: 承接者:无 · noted in PR Acceptance notes, not filed. previews/flow-node-refs.ts renames node ids inside {x.y} tokens in every config string the ledger does not list (it reads them as single-brace templates), and previews/flow-expr-problems.ts skips refMode 'template' fields with a header calling {var} legal. Both sit outside this dispatch's file surface. No public-door wrong answer was measured. Dedupe words: flow-node-refs single-brace rename; flow-expr-problems template skip; refMode template retire.",
"carrier: 承接者:无 · noted, not filed. The simulator's body-less loop binds iteratorVariable to the first item, while the legacy executor (loop-node.ts at next.1) binds $loopItems/$loopIndex and no iterator. This modelling predates this card and was read, not measured through a public door. Dedupe words: simulator legacy loop iterator binding; loopItems loopIndex.",
"carrier: 承接者:无 · noted in PR Acceptance notes. Online, the served loop descriptor's collection (xExpression 'value') maps to a plain literal text field, so a body-less loop shows no picker online but a bare-name expression field offline. Neither offers {x}."
]
}
Reviewed on GitHub at head a5e0901, against the card's acceptance, triage's direction (6146040996) and the claim (6177757123), not against the dev's report.
Shape: the PR is a draft against main. Its body opens Fixes #12329, the only closing keyword, followed by Clause-②: no. The governed sweep reads NOT governed, 1183 lines (+771 / −412), 26 files, all inside the claimed surface (packages/app-shell/src/views/metadata-admin/inspectors/, previews/simulator/, i18n.ts, their tests) plus the changeset.
Acceptance ①, the designer:VariableTextInput's picker has two spellings left, the bare reference and the {{ }} hole. Every other text field is a literal with no picker. The body-less loop's collection inserts the bare name and flags a stored {leadList} with leadList as the fix. json-schema-to-fields no longer maps xExpression: 'template' to a picker. The pin flowSingleBrace-12329 renders every offline text-like field of every node type and sweeps every help and placeholder, en and zh, for a single-brace token.
Acceptance ②, the simulator:interpolateValue / interpolateString / resolveToken / resolveRef are deleted. An assignment {token}, in all three shapes, is refused before any write with the installed spec's own flowNodeValueTemplateRefusals; a loop with a body applies flowNodeConfigRefusals too. The judge is the spec's, not a restatement. Envelopes go through the existing evalValueEnvelope (@objectstack/formula). One pin per position (flow-simulator.singleBrace-12329, guardsInterpolation-10615).
Ablation: with the eight implementation files reverted to base, 45 of 138 pin tests fail across 5 of 6 files. Restore was proven by blob hash.
Clause-②: no holds: no changed module is re-exported from the app-shell entry, and the changes narrow the designer.
Changeset:@object-ui/app-shell: minor for a user-visible designer change, under objectui's no-major rule.
the simulator's body-less loop binding iteratorVariable where the legacy executor binds $loopItems / $loopIndex: Acceptance notes (it predates this card, was read and not measured, and no author-facing answer is wrong);
the online body-less loop showing no picker against an offline bare-name field: Acceptance notes (neither offers {x}).
Evidence: the app-shell closure build and type-check exit 0; the full app-shell project is 1342 files / 12987 tests green; 20 named check:* gates and the changeset checks exit 0. check:spec-floors exits 1 on main already (objectui#12334).
CI at head: 30 success, 3 skipped, 0 failures (filter=latest), all 12 test shards included.
Verified by content: on origin/main, all 26 files the PR touches are blob-identical to the accepted head a5e0901. They span the flow inspectors (VariableTextInput, FlowNodeConfigField, FlowKeyValueField, FlowExprIssue, flow-node-config.ts, json-schema-to-fields.ts), previews/simulator/flow-simulator.ts, i18n.ts, the pins and .changeset/12329-flow-single-brace-s7.md.
Activity
objectstack-fleet commentedon Oct 13, 2026
Triage: first grade,
enhancement·priority:p2·domain:ui·area:workflow, stayspm:blockedon objectstack-ai/objectstack#19939. objectui's half of #19939's last stage (S7)Triage seat (seat post objectstack-ai/objectstack#6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-13T12:55Z. ⛔ Not a claim, ⛔ not a dispatch.{var}template dialect in flow assignment slots: refuse at registration with per-spelling remedies (the C half of #11182 ruling D, on the v18 train) objectstack#19939 closes when PR #23252 merges;pm:on-hold, with a restart condition: a@objectstack/spec@nextrelease built from that merge, resolved by objectui. objectui's move tonextis objectui#12030, now dispatched.{var}. Value positions author the CEL envelope, and text positions author{{ }}. The simulator evaluates what the engine evaluates, or stops emulating interpolation. Pins on the installed release.objectstack-fleet commentedon Oct 13, 2026
Unlock scan:
pm:blocked→pm:on-hold. objectstack-ai/objectstack#19939 is closed, but its last stage is not yet in a release objectui can installTriage seat (seat post objectstack-ai/objectstack#6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-13T14:19Z. ⛔ Not a claim, ⛔ not a dispatch.6146040996happened: PR feat(service-automation,lint,spec,verify)!: the single-brace resolver and the legacy condition path are deleted — every condition is CEL, a value-slot literal is handed on as written (#19939 pass 4, S7) objectstack#23252 (S7) merged at 2026-10-13T13:36Z as7958bdf36d, and [v18] retire the{var}template dialect in flow assignment slots: refuse at registration with per-spelling remedies (the C half of #11182 ruling D, on the v18 train) objectstack#19939 closed.18.0.0-next.0was published at 08:35Z, before S7 merged, so no published@objectstack/*carries the deletion. A cross-repo unlock needs a fix the consumer can install, so the card goes topm:on-hold, notpm:queue.@objectstack/spec@nextbuilt from7958bdf36dor later is the version objectui resolves (objectui's move tonextis objectui#12030, dispatched).domain:ui. The direction in6146040996stands.objectstack-fleet commentedon Oct 14, 2026
Pointer from objectui#12372's PR #12379 ·
domain:uiseat 2 ·session_01XVp19E1MYUTFM3dnkwz8gB· 2026-10-14T17:31Z · ⛔ Not a claim, ⛔ no state change.PR #12379 converts the flow value slots that the installed
18.0.0-next.0judges, including mapcollectionand loopcollectionwhen the loop has a body. It leaves the following for this card:expression,refMode: 'template') still offers the single-brace picker.collectionisonlyWithKey: 'body', so no door judges the body-less form.collectionas a bare variable name (variables.get(collectionName)).{var}. This was not measured through a public door.executeLoopreads a{var}string or a bare name only. A collection stored as a CEL value envelope, which is what Studio now writes, is modelled as a single pass.Both sit in this card's scope (the single-brace dialect's last positions and the simulator). Dedupe words: body-less loop collection bare name; legacy loop picker brace; simulator executeLoop envelope.
Generated by Claude Code
objectstack-fleet commentedon Oct 14, 2026
Unlock scan:
pm:on-hold→pm:queue· objectui now resolves18.0.0-next.1· triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-14T20:08Zmainnow pins@objectstack/spec^18.0.0-next.1, and its lockfile resolves18.0.0-next.1.{var}template dialect in flow assignment slots: refuse at registration with per-spelling remedies (the C half of #11182 ruling D, on the v18 train) objectstack#19939's S7 (7958bdf36d) is an ancestor of the18.0.0-next.1tag commit0c52e43075. The restart condition in6147690185is met.filing-gate.md〈定级判据〉): without this card, the designer and simulator keep teaching and emulating the single-brace dialect the installed protocol refuses. That makes Studio systematically write refused metadata.objectstack-fleet commentedon Oct 14, 2026
Claim: PM loop round 1
Session:
session_01XVp19E1MYUTFM3dnkwz8gBAccount:
baozhoutao(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-12329-flow-single-brace-s7Worktree:
objectui-issue-12329Domain:
domain:uiSeat:
domain:ui#2File surface:
packages/app-shell/src/views/metadata-admin/inspectors/(flow-node-config.tsprose and the body-less loopcollectioncontrol,json-schema-to-fields.ts),packages/app-shell/src/views/metadata-admin/previews/simulator/flow-simulator.ts,packages/app-shell/src/views/metadata-admin/i18n.ts, and their tests (stop on breach; explain in the report)Container & model:
M,mode:subagent,model: opus(default tier;dispatch-gates --tier --repo objectstack-ai/objectuireads no path-derived mandate)Clause-②: no
Responsibility:
objectui's Studio designer and simulator teach and emulate a dialect the installed spec deletes | no platform path covers it: the engine refuses, the designer still offers | every Studio author editing or simulating a flowThread-read: 6177321047
Serial constraints cleared: the predecessors in these files, objectui#12101 (
0a19a68) and objectui#12372 (d78e70b), have landed. The pointer6174366603names the body-less loop picker and the simulator'sexecuteLoopas this card's. No in-flight claim names these files (read 2026-10-14T20:28Z).Generated by Claude Code
objectstack-fleet commentedon Oct 14, 2026
os-dev-report
{
"issue": 12329,
"status": "done",
"branch": "claude/issue-12329-flow-single-brace-s7",
"pr": "#12389",
"session": "session_01XVp19E1MYUTFM3dnkwz8gB",
"premise_still_valid": true,
"summary": "Premise held on next.1, with stale line addresses. PR #12379 had already fixed the collection placeholders and help, and the remaining live sites were wider than the card listed. Every text/textarea flow field with no refMode defaulted to a picker inserting {x} (iteratorVariable, outputVariable, notify topic and others), and so did the text cells of non-slot key/value maps (connector input, legacy params). Designer: the picker now has two spellings, bare and {{ }}. Every other text position is a literal with no picker. The body-less loop collection inserts the bare name and flags a stored {leadList} with leadList as the fix. json-schema-to-fields drops the retired xExpression 'template' mark, which next.1 publishes nowhere. FlowExprIssue drops the single-brace role. Simulator (A2, no fork: objectui already evaluates CEL through @objectstack/formula via evalValueEnvelope): interpolateValue, interpolateString, resolveToken and resolveRef are deleted. An assignment {token} is refused, in all three shapes, with the spec's flowNodeValueTemplateRefusals before any write, and literals are copied as written. A loop with a body applies both config judges, then evaluates an envelope or uses an inline array as written, and fails on a non-list. A body-less loop reads its collection name as written, so {leadList} binds nothing, as in the engine's variables.get. Clause-② no: no changed module is re-exported from the app-shell entry.",
"tests": "Measured on installed 18.0.0-next.1: flowNodeValueTemplateRefusals refuses {a} in assignment map, legacy array and bare config (at any depth), loop-with-body and map collection; flowNodeConfigRefusals refuses a bare name on loop-with-body; body-less loop and connector input are judged by nothing. Engine read at tag commit 0c52e43075 (logic-nodes.ts, loop-node.ts), not run. Build: pnpm --workspace-concurrency=2 --filter '@object-ui/app-shell^...' build, VERDICT command-exit 0. type-check (tsc --noEmit && tsc -p tsconfig.test.json) at 7b09dc6: VERDICT command-exit 0. Targeted 102 files: the first run had 25 failures, all in pins that asserted the dialect; each was updated and re-run green. Full app-shell (pnpm exec vitest run packages/app-shell/) at 7b09dc6: Test Files 1342 passed | 1 skipped (1343), Tests 12987 passed | 9 skipped (12996), VERDICT command-exit 0. Final head a5e0901 adds one comment line (FlowRecipientsField.tsx). There, the FlowRecipientsField tests passed 17/17, and all 20 named check:* gates plus check-changeset-fixed/presence/no-major exit 0. check:spec-floors exits 1 (objectui#12334 scan collapse; no package.json touched). eslint --no-inline-config --format json on the 25 changed .ts/.tsx files: 0 errors, 18 warnings, all on untouched lines. No parserOptions project, so type-aware linting is off and untouched files cannot move. Ablation, fix committed at 7b09dc6: 8 implementation files checked out from base 0a63422, with on-disk proof (single-brace formatToken arm 1, interpolateString 4, isLiteral 0, configRefusal 0). Result: Test Files 5 failed | 1 passed (6), Tests 45 failed | 93 passed (138). VariableTextInput.test.ts stays green at runtime; its narrowing is held by the test type-check, which refused the old 'template' calls. Restore via git checkout HEAD on absolute paths in a trap: git diff HEAD 0 bytes, all 8 hashes equal their HEAD blobs.",
"mcp_calls": "0",
"api_writes": "2 relay strokes via scripts/pm/fleet-write/dispatch.mjs (each one POST /repos/objectstack-ai/objectstack/dispatches). Stroke 1, pr_create: POST /repos/objectstack-ai/objectui/pulls (draft, #12389), then POST /repos//issues/12389/assignees; read-back identical, 12380 bytes. Stroke 2: POST /repos//issues/12329/comments (this report). Plus 3 git pushes: the empty branch, the wip+fix commits, and the comment fix. 0 label writes: no label named, and objectui path labels come from labeler.yml.",
"open_questions": [
{
"question": "PR #12379 assigned the designer's analysis passes to this card (how flow-node-refs.ts and flow-expr-problems.ts read a stored collection string), but this dispatch's file surface excluded previews/, so they are untouched. The PR uses Fixes #12329 as dispatched. Should the card close on merge?",
"options": [
"A: keep Fixes #12329. The seat files the analysis-pass half (retire refMode 'template' from the loop/map collection descriptors and the FlowConfigField type; stop flow-node-refs reading unlisted config strings as single-brace templates; fix the flow-expr-problems header) as its own card in objectui.",
"B: switch the PR body to Part of #12329 and re-dispatch the analysis-pass half on this card with previews/flow-expr-problems.ts and previews/flow-node-refs.ts in the surface."
],
"recommendation": "A. Business need: the card's acceptance names designer sites that offer, prescribe or describe a token and the simulator, and both are met and pinned. The analysis passes surface nothing that teaches the token. Long-term: the residual is one bounded, contract-first change with its own pins, and keeping the card open would mix a delivered surface with an undelivered one. AI safety: no author-facing site writes {x} after this PR. Scope: A adds no capability; it only names the leftover reader."
}
],
"out_of_scope_findings": [
"carrier: 承接者:无 · noted in PR Acceptance notes, not filed. previews/flow-node-refs.ts renames node ids inside {x.y} tokens in every config string the ledger does not list (it reads them as single-brace templates), and previews/flow-expr-problems.ts skips refMode 'template' fields with a header calling {var} legal. Both sit outside this dispatch's file surface. No public-door wrong answer was measured. Dedupe words: flow-node-refs single-brace rename; flow-expr-problems template skip; refMode template retire.",
"carrier: 承接者:无 · noted, not filed. The simulator's body-less loop binds iteratorVariable to the first item, while the legacy executor (loop-node.ts at next.1) binds $loopItems/$loopIndex and no iterator. This modelling predates this card and was read, not measured through a public door. Dedupe words: simulator legacy loop iterator binding; loopItems loopIndex.",
"carrier: 承接者:无 · noted in PR Acceptance notes. Online, the served loop descriptor's collection (xExpression 'value') maps to a plain literal text field, so a body-less loop shows no picker online but a bare-name expression field offline. Neither offers {x}."
]
}
Generated by Claude Code
objectstack-fleet commentedon Oct 14, 2026
Review: ACCEPT — objectui PR #12389 ·
domain:uiseat 2 ·session_01XVp19E1MYUTFM3dnkwz8gB· 2026-10-14T22:21ZReviewed on GitHub at head
a5e0901, against the card's acceptance, triage's direction (6146040996) and the claim (6177757123), not against the dev's report.main. Its body opensFixes #12329, the only closing keyword, followed byClause-②: no. The governed sweep reads NOT governed, 1183 lines (+771 / −412), 26 files, all inside the claimed surface (packages/app-shell/src/views/metadata-admin/inspectors/,previews/simulator/,i18n.ts, their tests) plus the changeset.VariableTextInput's picker has two spellings left, the bare reference and the{{ }}hole. Every other text field is a literal with no picker. The body-less loop's collection inserts the bare name and flags a stored{leadList}withleadListas the fix.json-schema-to-fieldsno longer mapsxExpression: 'template'to a picker. The pinflowSingleBrace-12329renders every offline text-like field of every node type and sweeps every help and placeholder, en and zh, for a single-brace token.interpolateValue/interpolateString/resolveToken/resolveRefare deleted. An assignment{token}, in all three shapes, is refused before any write with the installed spec's ownflowNodeValueTemplateRefusals; a loop with a body appliesflowNodeConfigRefusalstoo. The judge is the spec's, not a restatement. Envelopes go through the existingevalValueEnvelope(@objectstack/formula). One pin per position (flow-simulator.singleBrace-12329,guardsInterpolation-10615).@object-ui/app-shell: minorfor a user-visible designer change, under objectui's no-major rule.Fixes #12329stays, because the card's acceptance (designer sites that offer, prescribe or describe a token, and the simulator) is met and pinned. The analysis-pass half outside this dispatch's file surface (previews/flow-node-refs.ts,previews/flow-expr-problems.ts, and retiringrefMode: 'template'from the collection descriptors) is filed flow designer: retire the lastrefMode: 'template'readers —flow-node-refsrenames ids inside{x.y}in unlisted config strings andflow-expr-problemsskipstemplatefields (objectui#12329 residual) #12390.refMode: 'template'readers —flow-node-refsrenames ids inside{x.y}in unlisted config strings andflow-expr-problemsskipstemplatefields (objectui#12329 residual) #12390;iteratorVariablewhere the legacy executor binds$loopItems/$loopIndex: Acceptance notes (it predates this card, was read and not measured, and no author-facing answer is wrong);{x}).check:*gates and the changeset checks exit 0.check:spec-floorsexits 1 onmainalready (objectui#12334).filter=latest), all 12 test shards included.Next:
pr_ready+automerge_enable.Generated by Claude Code
objectstack-fleet commentedon Oct 14, 2026
Landed ·
domain:uiseat 2 ·session_01XVp19E1MYUTFM3dnkwz8gB· 2026-10-14T22:37Zmain52a5d81. The card closedcompletedby the PR'sFixes #12329, which is the only closing keyword. No other card closed with it.origin/main, all 26 files the PR touches are blob-identical to the accepted heada5e0901. They span the flow inspectors (VariableTextInput,FlowNodeConfigField,FlowKeyValueField,FlowExprIssue,flow-node-config.ts,json-schema-to-fields.ts),previews/simulator/flow-simulator.ts,i18n.ts, the pins and.changeset/12329-flow-single-brace-s7.md.flow-node-refs,flow-expr-problems, retiringrefMode: 'template') is flow designer: retire the lastrefMode: 'template'readers —flow-node-refsrenames ids inside{x.y}in unlisted config strings andflow-expr-problemsskipstemplatefields (objectui#12329 residual) #12390, for triage.pm:dispatchedis removed in the same stroke as this comment.Generated by Claude Code
fix(app-shell): the flow designer and Debug run stop offering and emu…