picatz / picatz/flowstate

dsl: `must:` is the one expression position stored as source text — re-parsed and re-checked on every compile, refused by a walker no other position uses, and evaluated through the uncached path with an `env.Extend` per check

Open
#1,503 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

dsl engine enhancement
Dominant language
Go
Stars
9
Forks
0
Avg merge
3h 3m
Merged PRs (30d)
509

Description

Observed behavior

Every expression position in a compiled specification is a ParsedExpr (value.proto:143) — except must:. InputDeclaration.must (proto/flowstate/v1/workflow.proto:1043) and OutputDeclaration.must (:1121) are optional string. Consequences at 40cc365:

  • compileMustIn (pkg/flowstate/v1/constraints.go:231-259) parses, converts to a proto, runs refuseNondeterministicMust, checks, and tests the output type — on every call. It is called from validate (:414, :628), from submit for every declared input (:832, under BindRunInputs) and from run-output evaluation (:874). A workflow with twenty constrained inputs parses and checks twenty expressions per submission and per call: with: binding (docs/DSL.md:4115-4118 lists the four enforcement points).
  • Evaluation goes through Evaluator.Eval (constraints.go:888, :929), the deliberately uncached path (celenv.go:296-306): each check re-runs orderMapComprehensionsAST, env.Extend(orderedMapEnvOption(...)) and env.Program.
  • refuseNondeterministicMust walks the proto for now (constraints.go:262); every other position learns what is in scope from the validator's refScope and collectReferences (validate.go:1952). A second refusal mechanism for one position is the #1437 shape.
  • flow fmt normalizes every expression through the AstToString fixed point (flowfile/value.go:432) except must:, which is written back as typed; and #332's proposed flow fix rewrite of must: this in [...] into type: enum needs an AST it does not have.
  • The spec digest and flow breaking compare must: as text, so this>=1 and this >= 1 are different constraints.

Desired outcome

must: compiles to a ParsedExpr like every other position; it is checked once at compile, its refusal rules are the validator's, and its evaluation is EvalParsed on the cached program.

Acceptance criteria

  • InputDeclaration and OutputDeclaration gain a ParsedExpr-typed field written by the compiler; the string stays for old specs (invariant 10) and is compiled on read only when the new field is absent.
  • BindRunInputs evaluates a constrained input through EvalParsed; a benchmark with twenty constrained inputs shows no per-submit parse.
  • refuseNondeterministicMust is deleted in favour of the validator's scope rules applied to the must: position (this in scope, now not).
  • flow fmt normalizes must: the way it normalizes if:; the examples corpus is byte-identical after flow fmt and a deliberately unnormalized fixture changes.

Constraints and dependencies

  • #332 (the must: scope ladder) decides what must: may read; this decides how it is stored and does not widen the scope.
  • #1436 / #1452 decide what this may be typed as; mustEnvFor keeps binding this from the declared type.
  • buf breaking: adding a field is safe; the string is not removed.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with InputDeclaration and OutputDeclaration in proto/flowstate/v1/workflow.proto, then trace compileMustIn and its callers in pkg/flowstate/v1/constraints.go. Read ParsedExpr in value.proto and formatting in flowfile/value.go, and review the validator scope logic in validate.go. Done means must: is stored and compiled once, uses cached evaluation and validator scope rules, and flow fmt normalizes it with the stated tests and benchmark passing.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
compilers
Issue type
Refactor
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.