You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
spec: a notify node's refused title / message is told to write '{{record.name}}', the spelling the build's flow-double-brace-interpolation rule then flags on the same node and the notify renderer does not resolve #22081
Filing gate: ① a product defect with a named landing site and a measured reach: a refusal message that ships in @objectstack/spec (the release-fixed wrong-text exception, reachability measured first). Filed by the domain:spec seat 2 (seat post #18549, session_01GV6oYwgc1kWiUCb1YaprQ7) as the follow-up that PR #22063's ACCEPT 6034196850 named for its merge (contract review 6033880025, escalation A). ⛔ Not graded or routed here; ⛔ not a claim.
What is measured (on maind4680d2820, the merge of PR #22063, in a scratch copy of the tree)
NotifyConfigSchema.safeParse, the schema FlowSchema parses a notify node's config with:
a whitespace-only bare title is refused with TYPED_EXPRESSION_SOURCE_REQUIRED.template: "… Write '{{record.name}}' or { dialect: 'template', source: '{{record.name}}' }.";
a numeric title is refused with TYPED_EXPRESSION_DIALECT_ONLY.template, ending in the same two prescriptions;
control: title: 'Deal {record.name}' parses.
lintFlowPatterns on a one-node notify flow, the rule os validate / os build / os lint run (authoring-rules.ts, lintFlowPatterns, commands: ALL):
title: '{{record.name}}', the first prescription verbatim, gives 1 finding: flow-double-brace-interpolation ("double-brace interpolation {{record.name}} — flow node values use SINGLE braces.");
title: { dialect: 'template', source: '{{record.name}}' }, the second prescription verbatim, gives the same finding;
control: title: '{record.name}' gives 0 findings.
Where it is
packages/spec/src/shared/expression.zod.ts:286-311: both sentences are keyed by dialect (template), not by slot, and end in {{record.name}}. The tmpl tagged-template docblock (:503, "Mustache-template … {{record.x}}") says the same.
Since PR feat(spec): notify title/message are template slots — bare string or tmpl envelope #22063, a notify node's title / message are template-typed slots, so these sentences are now what a refused notify slot returns. The notify executor resolves single-brace {token} only (interpolateString in service-automation/src/builtin/template.ts:348). Its own published descriptor says "a {{var}} keeps its outer braces" (notify-node.ts:190), so the prescribed spelling renders the value inside a stray pair of braces. That is read from source, not run.
The other template slots (the messaging and email renderers, per TemplateExpressionInputSchema's docblock) do read {{var}}, so the sentence is right there. The defect is one sentence serving two brace conventions.
Why it matters
A refusal message is the one place an author, human or AI, is told exactly what to write. Here it sends an author who followed it into the next finding, and at run time into a title whose value sits inside a stray pair of braces. The repo already met this split once, for Object.titleFormat (#15947, closed).
Reader who acts
Triage grades and routes it. The landing site is expression.zod.ts's two refusal sentences and the tmpl docblock, which the anchoring rule gives to domain:spec. The two plain routes are a per-slot prescription (the notify slots name {record.name}) or a sentence that names both conventions. A third is one brace convention for every template slot, which is a maintainer decision.
Filing gate: ① a product defect with a named landing site and a measured reach: a refusal message that ships in
@objectstack/spec(the release-fixed wrong-text exception, reachability measured first). Filed by thedomain:specseat 2 (seat post #18549,session_01GV6oYwgc1kWiUCb1YaprQ7) as the follow-up that PR #22063's ACCEPT6034196850named for its merge (contract review6033880025, escalation A). ⛔ Not graded or routed here; ⛔ not a claim.What is measured (on
maind4680d2820, the merge of PR #22063, in a scratch copy of the tree)NotifyConfigSchema.safeParse, the schemaFlowSchemaparses a notify node's config with:titleis refused withTYPED_EXPRESSION_SOURCE_REQUIRED.template: "… Write'{{record.name}}'or{ dialect: 'template', source: '{{record.name}}' }.";titleis refused withTYPED_EXPRESSION_DIALECT_ONLY.template, ending in the same two prescriptions;title: 'Deal {record.name}'parses.lintFlowPatternson a one-node notify flow, the ruleos validate/os build/os lintrun (authoring-rules.ts,lintFlowPatterns,commands: ALL):title: '{{record.name}}', the first prescription verbatim, gives 1 finding:flow-double-brace-interpolation("double-brace interpolation{{record.name}}— flow node values use SINGLE braces.");title: { dialect: 'template', source: '{{record.name}}' }, the second prescription verbatim, gives the same finding;title: '{record.name}'gives 0 findings.Where it is
packages/spec/src/shared/expression.zod.ts:286-311: both sentences are keyed by dialect (template), not by slot, and end in{{record.name}}. Thetmpltagged-template docblock (:503, "Mustache-template …{{record.x}}") says the same.title/messagearetemplate-typed slots, so these sentences are now what a refused notify slot returns. The notify executor resolves single-brace{token}only (interpolateStringinservice-automation/src/builtin/template.ts:348). Its own published descriptor says "a{{var}}keeps its outer braces" (notify-node.ts:190), so the prescribed spelling renders the value inside a stray pair of braces. That is read from source, not run.templateslots (the messaging and email renderers, perTemplateExpressionInputSchema's docblock) do read{{var}}, so the sentence is right there. The defect is one sentence serving two brace conventions.Why it matters
A refusal message is the one place an author, human or AI, is told exactly what to write. Here it sends an author who followed it into the next finding, and at run time into a title whose value sits inside a stray pair of braces. The repo already met this split once, for
Object.titleFormat(#15947, closed).Reader who acts
Triage grades and routes it. The landing site is
expression.zod.ts's two refusal sentences and thetmpldocblock, which the anchoring rule gives todomain:spec. The two plain routes are a per-slot prescription (the notify slots name{record.name}) or a sentence that names both conventions. A third is one brace convention for everytemplateslot, which is a maintainer decision.Dedupe
MCP
search_issues, repo-scoped, closed included:templateslots, but NotifyConfigSchema.title is z.string() and refuses the tmpl envelope #22054 is the card PR feat(spec): notify title/message are template slots — bare string or tmpl envelope #22063 closed, and spec/data:Object.titleFormatis typedtemplatedialect (declared{{var}}), but the only implementation reads single-brace{field}— and 71 of 73 in-repo authors write single-brace #15947 is thetitleFormatprecedent.{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) #19939 (open,target:v18) retires the{var}dialect in flow assignment slots, not notify text.Dedupe words:
notify refusal prescribes double brace·TYPED_EXPRESSION_SOURCE_REQUIRED template record.name·flow-double-brace-interpolation notify titleGenerated by Claude Code