Skip to content

LOU-U13, LOU-U16: bind flow placeholders as values; flow and adapter types match the runtime - #48

Merged
LinuxDevil merged 4 commits into
mainfrom
lou-u13-u16-flow-bindings-and-types
Oct 1, 2026
Merged

LinuxDevil merged 4 commits into
mainfrom
lou-u13-u16-flow-bindings-and-types

Conversation

@LinuxDevil

Copy link
Copy Markdown
Owner

What

  • LOU-U13: flow {{var}} placeholders are bound as values, not pasted into the expression text.
  • LOU-U16: EditorStep covers every node kind FlowExecutor runs; FileSystemAdapter accepts the real node:fs. Both README casts are gone.

Why

  • U13: a value like x' === 'x' || 'a inside '{{input}}' === 'admin' could rewrite a condition's logic (no code execution, but still injection).
  • U16: README snippets needed as unknown as casts for the flow example and for fs.

How verified

  • npx tsc --noEmit: clean. npm run lint: 0 errors (440 warnings, none new in touched code).
  • Builds (root and create-loushy-agent): success.
  • npm run test:coverage: 95 files passed, 1175 tests passed, 3 skipped, thresholds met.
  • npm run fallow: exit 0 ("0 above threshold").
  • npm run docs:verify-snippets: "all 32 snippet(s) type-check against src/; 5 also run cleanly".
  • npm run test:types: 10 passed, no type errors.
  • Agent Forge: typecheck and typecheck:server clean; npx vitest run 108 passed; npm run test:server 105 passed.
  • Merged origin/main (376959f, LOU-Y2) before the final run.

Notes for reviewer

  • evaluateSafeExpression(expr, scope, { bindPlaceholders: true }). Bare {{x}} is a value token; inside a literal it interpolates String(value) (missing/null become '', like before). A bare missing variable yields no token, so {{x}} >= 90 is still a syntax error (false) and {{x}} alone is undefined, matching the old text substitution. Bare string values are now string literals rather than re-parsed identifiers. Inherited properties (e.g. {{toString}}) are no longer read.
  • llmCall prompts, tool arguments and throw messages still use plain text interpolation (not expressions).
  • Types: oneOf, forEach and evaluator exist in editor shape (branches/inputFlow/subFlow) and executor shape (options/items/expression), so the union has two members per type. convertToFlowDefinition maps executor-shaped nodes to the unknownAgent placeholder instead of throwing. FileSystemAdapter encodings narrowed to 'utf8', which hand-written adapters with string still satisfy.
  • test:types was vacuous: tsconfig.json excludes *.test-d.ts and vitest's typecheck reported no errors even for an obvious type error. Added tsconfig.test-d.json and run tsc -p on it first in test:types. I confirmed the new node:fs test fails against the old adapter type.

🤖 Generated with Claude Code

LinuxDevil and others added 4 commits October 1, 2026 09:26
…types match the runtime

U13: FlowExecutor no longer pastes {{var}} text into condition/evaluator
expressions. evaluateSafeExpression takes { bindPlaceholders: true }: a bare
{{x}} becomes the variable's value token, and {{x}} inside a string literal
is interpolated into that literal's value after tokenizing, so quotes,
backslashes and operators in a value are data. Missing/null variables behave
as before ('' in a literal, nothing when bare).

U16: EditorStep is now a union covering every node kind the executor handles
(llmCall, toolCall, setVariable, return, end, throw, and the options/items/
expression shapes of oneOf/forEach/evaluator); editor shapes are unchanged.
FileSystemAdapter takes the 'utf8' encoding StorageService passes, so
node:fs is assignable without a cast. Add tsconfig.test-d.json and run it in
test:types (test-d files were excluded from tsc, so type tests were vacuous).
README casts removed.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@LinuxDevil
LinuxDevil merged commit 6f2dc67 into main Oct 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant