Skip to content

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

Description

@objectstack-fleet

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 main d4680d2820, 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.

Dedupe

MCP search_issues, repo-scoped, closed included:

Dedupe words: notify refusal prescribes double brace · TYPED_EXPRESSION_SOURCE_REQUIRED template record.name · flow-double-brace-interpolation notify title


Generated by Claude Code

Activity

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 itbugSomething isn't workingdomain:specpriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions