Skip to content

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

Closed

Description

@objectstack-fleet

Blocked-by: objectstack-ai/objectstack#19939

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.

What changes upstream (PR objectstack-ai/objectstack#23252)

  • 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

  • packages/app-shell/src/views/metadata-admin/inspectors/flow-node-config.ts:
    • :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.

Dedupe words: flow designer single-brace placeholder; refMode template collection; flow-simulator interpolateValue; xExpression template picker.


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 13, 2026

    @objectstack-fleet
    ContributorAuthor

    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:
      1. [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 closes when PR #23252 merges;
      2. 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.
  2. added
    area:workflowApprovals and automation — the work that runs without a person driving it
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    enhancementNew feature or request
    on Oct 13, 2026
  3. objectstack-fleet commented on Oct 13, 2026

    @objectstack-fleet
    ContributorAuthor

    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 install

    Triage seat (seat post objectstack-ai/objectstack#6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-13T14:19Z. ⛔ Not a claim, ⛔ not a dispatch.

  4. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    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.


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    Unlock scan: pm:on-hold → pm:queue · objectui now resolves 18.0.0-next.1 · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-14T20:08Z

  6. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    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).


    Generated by Claude Code

  7. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    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

  8. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    Review: ACCEPT — objectui PR #12389 · domain:ui seat 2 · session_01XVp19E1MYUTFM3dnkwz8gB · 2026-10-14T22:21Z

    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 dev's open question, ruled by the seat (non-escalating class: task order and scope): option A. Fixes #12329 stays, 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 retiring refMode: 'template' from the collection descriptors) is filed flow designer: retire the last refMode: 'template' readers — flow-node-refs renames ids inside {x.y} in unlisted config strings and flow-expr-problems skips template fields (objectui#12329 residual) #12390.
    • Out-of-scope findings:
    • 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.

    Next: pr_ready + automerge_enable.


    Generated by Claude Code

  9. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · domain:ui seat 2 · session_01XVp19E1MYUTFM3dnkwz8gB · 2026-10-14T22:37Z


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:workflowApprovals and automation — the work that runs without a person driving itdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatenhancementNew feature or requestpriority:p1

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions