Relationships
#3510 typed-secrets 1.1: commit the cel-js 7.6.1 probe harness as pinned behavior tests
Opened by zack · 10/15/2026· Shipped 10/15/2026
Outcome
The cel-js behavior probes written during the typed-secrets plan review are committed as tests under src/infrastructure/cel/, pinning the behavior of @marcbachmann/cel-js 7.6.1 that the plan's design depends on (design doc Section 4.2). The plan's dependency facts become evidence CI reruns instead of claims from a review session, and a future cel-js upgrade that changes any of them fails a test instead of silently changing semantics.
Why now
The plan's header says Phase 1 must commit reproducible tests and that the document is not a passing attestation; Section 4.4 says uncommitted probe claims do not satisfy the dependency gate. The probes exist only in a session scratchpad today. Phases 1.2 to 1.4 (the opaque Secret type, lowering, the evaluation frame, tracked async loading) extend the same harness, so it lands first.
Scope
Convert the eleven probe scripts (helpers.ts, probe1_types, probe2_operators, probe3_async, probe3b_async_reject, probe4_hetero, probe5_macros, probe6_errors, probe7_reuse, probe8_unicode_regex, probe9_typecheck, probe10_followups) from result-printing scripts into Deno.test files with assertions. They run cel-js directly and touch no swamp code. Each test name starts with the library version so the file reads as a pin of observed behavior, not a statement of desired behavior. Findings every test must assert:
- Custom types: runtime type is exact constructor identity; a subclass is unsupported_type; a plain object of the same shape is a map; names need at least two characters; fields: {} makes field access throw no_such_key and has() return false, but comprehension macros still iterate own enumerable properties, and private fields yield an empty range.
- Operators: signature syntax for custom overloads; != is derived from == and registering both throws; Secret == string is mirrored, Secret + string is not; a custom binary overload marks the operator maybe-async.
- Async equality: a Promise-returning == handler is awaited for s == t, but s != t, list equality, map equality and membership consume the handler's return synchronously and produce wrong results; a rejecting handler leaks an unhandled rejection. The rejection test must install an unhandledrejection listener and leave no pending ops for the test sanitizers.
- Mixed-type comparison with no matching overload falls back to identity with zero handler calls; static typing via registerVariable gives a check-time no_such_overload.
- Errors: error || true is true for every error class; exists and all absorb per-element errors; map, filter and exists_one always throw; there is no fatal error class; ParseError, EvaluationError and TypeError share an unexported base.
- Reuse: a parsed program is reusable; 25 concurrent async evaluations of one program show no interference; registering on an environment after parse mutates the shared registry.
- size(string) counts code points; substring and indexOf use UTF-16 units; matches is a bare RegExp with no flags and no timeout.
- The static checker always runs; a dotted function name cannot be declared; a registered receiver type plus a bound variable works.
Add license headers with deno run license-headers. Keep the tests in-process with no subprocesses, sockets or env mutation.
Out of scope
- The Secret type, the vault namespace receiver, AST lowering, the evaluation frame and fake async loading. Those are typed-secrets 1.2 to 1.4.
- The Section 4.4 conformance matrix and the Phase 1 gate decision (1.5).
- Any cel-js upgrade. 8.0.0 was checked and is byte-identical in registry.js and overloads.js; it changes nothing above.
Acceptance
- Every bullet in design doc Section 4.2 has a named test.
- The suite passes against the pinned 7.6.1 and runs under deno run test with no sanitizer failures.
- verify-build, verify-reviews and verify-skills pass at the reviewed commit.
References
- Design doc Sections 4.2 and 4.4 and Phase 1, landed by swamp-club#3509.
- cel-js source at the pinned release: https://github.com/marcbachmann/cel-js/tree/v7.6.1
Shipped
Click a lifecycle step above to view its details.
Sign in to post a ripple.