[speckl#37.7] B2: Forward constraint/verify expressions through TS generator (or evaluate at runtime) #45
Labels
No labels
blocked
bug
design
docs
engineering
feature
infra
priority:high
priority:low
priority:medium
question
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: sscoble/speckl#45
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
The TypeScript generator's
checkConstraintN()andverifyN()stub emitters (aroundtypescript-state-machine.ts:263-279) always returntruewith a// TODO: Evaluate in Z3 or runtimecomment. No actual evaluation of the constraint expression or LTL-styleverifyformula ever happens at runtime. The generated code looks type-safe but is semantically a no-op for every spec with aconstraintorverifyblock.Affected examples
All 16 that have
constraintorverifyblocks: AccessControl, DrugDosageCalculator, KafkaProducer, OAuth2, PaymentService, Raft, RetryHandler, SQLitePager, SQLiteWAL, TemperatureMonitor, TigerBeetleLedger, TwoPhaseCommit, etc.Scope
Forward the constraint expression through the existing
rewriteExpr(...)chain and emit a real boolean expression. ForverifyN, two acceptable resolutions (pick one):@speckdl/runtimeif it exists).false. Adds a Z3 runtime dependency to the TS output.If neither resolution fits the 1200s subagent window, document the chosen approach in a comment and stub a follow-up ticket.
Out of scope
nix buildor open a PR. Build only the compiler.Acceptance Criteria
checkConstraintN()andverifyN()in the TS output return a real boolean (not alwaystrue) when the constraint/formula is violatedAccessControl.speck— simplest) is end-to-end verified: the emitted TS, when run, reports a constraint violation when the spec'sconstraintblock is violatedtsc --noEmit --target es2020Why this exists
Triage on #39 found 6 bugs. B2 is the largest scope — Z3 integration or runtime evaluator work — and may need a second round of decomposition. Flagged as the 'do last' ticket.
Depends on
None (but B1's parser fix may unblock the AST shape; the generator can still be implemented independently if B1 lands in parallel)
Blocks
None
Decomposition — 2-child stack ready for PR-sequenced merge
Per Scott directive (2026-06-02 18:39 PT): decompose and stack PRs if necessary. This ticket is being split into two stackable children.
rewriteExpr(synchronous, in-process)verifyN()with runtime LTL evaluator or Z3 call-outWhy split (not just dispatch as-is at 7 ACs):
PR stack patterns (Scott's choice):
Dispatch plan (post-decomposition):
child_timeout_secondsbudget; sequential dispatch avoids the parent wall-clock capClosing this ticket: Marking #45 as the B2 decomposition parent. Will be closed when both #47 and #48 ship.
CoS housekeeping closure (2026-06-02 cron cycle 21:50 UTC)
This ticket's scope has been carried by decomposition children. Closing the parent.
Decomposition (2026-06-02 18:39 PT, Scott directive)
Why close the parent
The B2 work is now bounded to two atomic-releasable children with explicit PR-stack ordering. The original 7 ACs of this ticket are split:
The "choose runtime vs Z3" decision in AC1 here is also pushed to #48 (per the CoS verification, this is a Scott-level architecture call that the agent should not make unilaterally).
Cross-references
Closing this parent. Reopen if Scott wants the runtime-vs-Z3 decision in the original parent thread.