@@ -227,14 +227,24 @@ describe('configSchema ↔ expression-ledger reconciliation (#4027)', () => {
227227 * contract does not back would refuse a legal omission (an absent
228228 * `visibleWhen` shows the field); a requirement the ledger misses is the
229229 * #19961 shape again — declared required, admitted absent at every door.
230+ *
231+ * Reconciled over the `predicate` role, the one role the flag acts on: the
232+ * resolver emits an absent value only for a required PREDICATE slot. The
233+ * channels require two `flow-template` slots too (`loop.collection`,
234+ * `map.collection`), and no door refuses their absence — their executors
235+ * parse their own config — so the flag stays off there, and the second
236+ * assertion pins that it is never set on another role.
230237 */
231- it ( 'the ledger marks `required` exactly the slots the declaring channel requires (#19961)' , ( ) => {
232- const declared = declaredEverywhere ( ) ;
238+ it ( 'the ledger marks `required` exactly the predicate slots the declaring channel requires (#19961)' , ( ) => {
239+ const declared = declaredEverywhere ( ) . filter ( ( d ) => d . role === 'predicate' ) ;
233240 const requiredByChannel = declared . filter ( ( d ) => d . required ) . map ( key ) . sort ( ) ;
234- const requiredByLedger = FLOW_NODE_EXPRESSION_PATHS . filter ( ( e ) => e . required ) . map ( key ) . sort ( ) ;
241+ const requiredByLedger = FLOW_NODE_EXPRESSION_PATHS . filter ( ( e ) => e . role === 'predicate' && e . required ) . map ( key ) . sort ( ) ;
235242 expect ( requiredByLedger , 'ledger `required` flags disagree with the declaring channel' ) . toEqual ( requiredByChannel ) ;
236- // Non-vacuous: the one required slot there is today is derived, not assumed.
243+ expect ( FLOW_NODE_EXPRESSION_PATHS . filter ( ( e ) => e . role !== 'predicate' && e . required ) . map ( key ) , '`required` acts on the predicate role only' ) . toEqual ( [ ] ) ;
244+ // Non-vacuous: the one required predicate slot there is today is derived,
245+ // not assumed — and the optional one (`visibleWhen`) is derived as optional.
237246 expect ( requiredByChannel ) . toEqual ( [ 'decision.conditions[].expression (predicate)' ] ) ;
247+ expect ( declared . filter ( ( d ) => ! d . required ) . map ( key ) ) . toEqual ( [ 'screen.fields[].visibleWhen (predicate)' ] ) ;
238248 } ) ;
239249
240250 it ( 'decision.conditions[].expression is covered — the #4439 hole' , ( ) => {
0 commit comments