Repository navigation
Description
Found while working on #14139 (the same literal on the filter surface); out of scope
there, filed unassigned for triage. Suggested domain: domain:cli. That card's triage
comment already anticipated this one: "packages/cli/src/commands/explain.ts's
$currentUser is a default-value sample on a different surface and is out of this card's
scope; if it is also wrong it is a domain:cli card."
The sample
packages/cli/src/commands/explain.ts:128, inside the flow entry's example string —
the text os explain flow prints to an author:
example: `{
name: 'assign_on_create',
type: 'autolaunched',
label: 'Auto-Assign on Create',
trigger: { object: 'project_task', event: 'afterInsert' },
steps: [
{ type: 'assignment', field: 'assigned_to', value: '$currentUser' },
],
}`,
Note this is a flow step of type: 'assignment' (Set Variable,
packages/spec/src/automation/flow.zod.ts:30) — not a field defaultValue, and not a
query filter. The surface is its own; that is exactly why #14139 left it alone.
What was measured
On origin/main:
- The literal appears exactly once in non-test, non-CHANGELOG source in the whole
repository — this sample. (git grep -n -F '$currentUser'returns 4 hits: this line,
two inskills/objectstack-ui/rules/list-views.mdwhich skills/objectstack-ui teaches$currentUseras a filter value, contradicting its own "only two tokens resolve in a filter" contract #14139 is fixing, and
docs/adr/0017-object-has-many-view.md:216which is SQL-shaped prose.) - The flow template vocabulary is brace-based, not
$-prefixed. Flow templates are
written{record.field}and validated byflow-template-unknown-field
(packages/lint/src/validate-flow-template-paths.ts:92), whose diagnostics say an
unresolvable path "resolves to an empty string at runtime (silently)". - The
$-prefixed sentinels that do exist are enumerated and different:$root
(approvalorganization),$trigger,$record,$source. There is no$currentUser
among them, and no alias table maps it. - The acting-user token on the value-producing surface next door is spelled bare:
DEFAULT_VALUE_TOKEN_CURRENT_USER = 'current_user'
(packages/spec/src/data/default-value-tokens.ts:67), matched EXACTLY by
isCurrentUserDefaultToken(:114-116), whose own comment namescurrentUseras an
authoring error rather than an accepted spelling.packages/spec/src/data/default-value-shape.ts:225
carriescurrentuseronly as a near-miss suggestion, and
default-value-shape.test.ts:54pinscurrentUser (camelCase) is a literal. - Nothing in
packages/services/service-automationstrips or resolves a leading$in an
assignment value.
What was NOT measured — please settle this in triage
I did not execute an assignment node with this value against a running engine. So the
claim I am confident in is "no declared vocabulary contains this spelling and nothing was
found that resolves it"; the claim I have not proved is "an assignment step therefore
stores the literal string $currentUser into assigned_to". If it does, that is the
lookup('sys_user') column taking a bogus literal — the same failure class as the DDL
incident catalogued in the default-value-tokens.ts module note.
Why it matters
os explain is an authoring aid whose whole audience is authors — increasingly AI authors
— writing their first flow. It is the one place a reader is told what an assignment value
looks like. If the spelling resolves nowhere, the sample teaches a value that either fails
validation or is silently stored as text, and the reader has no other reference to correct
it against.
Likely fix
Decide the correct spelling for "the acting user" on the flow-assignment surface, then make
the sample use it. If no such token exists on this surface, the sample should assign
something that does resolve rather than inventing a sentinel — and the gap itself is worth a
separate decision, since "assign to the current user on create" is the textbook
auto-assignment flow.
Generated by Claude Code
Activity
huangyiirene commentedon Sep 3, 2026
Triage — graded.
bug·documentation·priority:p3·pm:queue·domain:cli. The card asked triage to settle the half it did not measure. Partly settled below — and a second defect turned up on the way.Verified at
origin/main✅
git grep -F '$currentUser'returns exactly the four hits described:explain.ts:128,skills/objectstack-ui/rules/list-views.md:95and:103(#14139's), anddocs/adr/0017-…:216(SQL-shaped prose). So the sample really is the only non-test source occurrence outside what #14139 is already fixing.✅
DEFAULT_VALUE_TOKEN_CURRENT_USER = 'current_user'atdefault-value-tokens.ts:67, matched exactly at:115.⭐ The unmeasured half, advanced but not closed
packages/services/service-automation/src/builtin/logic-nodes.ts:135:and
:92states the intent outright — the assignment node shares the CRUD/screen resolution "sovalue: '{record.amount}'resolves". ⇒ The resolver on this surface is brace-based, confirming the card's vocabulary finding at the execution layer rather than only the declaration layer. A$-prefixed token carries no braces, so there is nothing for it to match.assigned_toends up holding the literal'$currentUser'.variables.setsets a flow variable, not a record field; reaching alookup('sys_user')column takes a later record-writing node. The card's feared failure class stays plausible and unproven. ⛔ Do not write it up as measured.⭐ Second defect the card did not find — the sample's node SHAPE
logic-nodes.ts:85-88warns:The sample writes neither. It writes
{ type: 'assignment', field: 'assigned_to', value: '$currentUser' }— afield/valuepair with noassignmentskey at all.packages/spec/src/automation/flow.zod.ts:30, which the card cites) versus the runtime node config these builtins consume. Settling that is the claimer's first step, and it is cheap: if the spec step shape isfield/valueand something adapts it, the sample's only defect is the token; if the surfaces are the same, the sample teaches a node that silently sets a variable namedassignmentsand the card is understated.⇒ ⛔ Do not fix the token before answering that. Correcting
$currentUserin a sample whose shape is also wrong ships a second wrong sample that now looks authoritative.Scope — terminal
The fix lands in
packages/cli/src/commands/explain.ts— one lane, one file.current_userfrom the default-value surface on the assumption it carries over. Change the sample to assign something that demonstrably resolves (a brace template such as{record.…}), and say in the report that "assign to the current user on create" has no expressible spelling here.⛔ That gap is out of scope: the card is right that it deserves its own decision, and it is one — a missing token on a published authoring surface is a contract question, not a sample fix. ⛔ Do not open an ADR or add a token; name it in the report and it gets carded separately.
skills/objectstack-ui/rules/list-views.md:95/:103— those two hits belong to #14139, on the filter surface, and editing them here collides with that card.Generated by Claude Code
fix(cli): make `os explain flow` teach a flow that actually parses (o…