@consiliency/agent-board-schema 1.23.0 → 1.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/README.md +75 -1
  2. package/fixtures/already-applied.json +12 -0
  3. package/migrations/20260905000100_agent_board_consent_gating_reconcile.sql +151 -0
  4. package/migrations/20260906000100_agent_board_enroll_resumption.sql +749 -0
  5. package/migrations/20260907000100_agent_board_signed_authority_provenance.sql +243 -0
  6. package/package.json +1 -1
  7. package/schema-manifest.json +30 -3
  8. package/src/check.js +23 -0
  9. package/src/index.js +20 -0
  10. package/src/plan.js +79 -5
  11. package/src/tooling.test.mjs +237 -4
  12. package/tests/agent_board_atomic_fleet_onboarding.test.sql +124 -112
  13. package/tests/agent_board_claimkey.test.sql +25 -3
  14. package/tests/agent_board_consent_emission.test.sql +17 -13
  15. package/tests/agent_board_consent_gating.test.sql +55 -11
  16. package/tests/agent_board_delegation_policies.test.sql +3 -1
  17. package/tests/agent_board_enroll_resumption.test.sql +412 -0
  18. package/tests/agent_board_federated_lock_order_class.test.sql +1 -3
  19. package/tests/agent_board_fedsession_provider_absence_gate.test.sql +9 -6
  20. package/tests/agent_board_fleet_machine_reactivation.test.sql +56 -5
  21. package/tests/agent_board_mint_harden.test.sql +39 -4
  22. package/tests/agent_board_outbox_wake_ordering.test.sql +27 -12
  23. package/tests/agent_board_rejectsem.test.sql +1 -1
  24. package/tests/agent_board_rolereset.test.sql +23 -2
  25. package/tests/agent_board_rowid.test.sql +24 -13
  26. package/tests/agent_board_scoped_send_regrant.test.sql +8 -4
  27. package/tests/agent_board_signed_authority_provenance.test.sql +454 -0
  28. package/tests/agent_board_source_strip_helper.test.sql +285 -0
  29. package/tests/agent_board_wake_recovery.test.sql +58 -40
  30. package/tests/catalog/p_metadata_parameters.json +689 -0
  31. package/tests/fixtures/test-prereqs.sql +313 -0
  32. package/tests/isolation/expected/atomic_fleet_lifecycle_races.out +3 -3
@@ -0,0 +1,285 @@
1
+ -- ===========================================================================
2
+ -- agent_board_test.strip_sql — the shared source-text strip every positional
3
+ -- and negative pgTAP assertion in this suite now reads through
4
+ -- (message-board#196, message-board#199).
5
+ --
6
+ -- WHY THIS FILE EXISTS. The strip is now a single point of failure for ~47
7
+ -- assertion sites across 14 files. Before it was shared, each file carried its
8
+ -- own regex; the two most hardened copies were kept deliberately byte-identical
9
+ -- so they could not drift, and they were both WRONG in the same way -- a nested
10
+ -- block comment walked straight through them and left
11
+ -- agent_board_atomic_fleet_onboarding at 52/52 and
12
+ -- agent_board_federated_lock_order_class at 15/15 with a lock genuinely moved.
13
+ -- A shared scanner without its own vectors would just be one wrong copy instead
14
+ -- of two, so every escape hatch the helper's header CLAIMS to close is asserted
15
+ -- here, and the claim is treated as falsifiable.
16
+ --
17
+ -- WHAT A REGEX CANNOT DO, and why this is a character scanner. Postgres block
18
+ -- comments NEST. Nested delimiters are not a regular language, and Postgres'
19
+ -- regex engine has no recursion, so no regular expression -- however clever --
20
+ -- can match `/* a /* b */ c */`. Every regex-based strip in the tree stopped at
21
+ -- the FIRST `*/` and handed back the text after it as if it were code.
22
+ --
23
+ -- The last three assertions are CORPUS-WIDE and catalog-derived: they run the
24
+ -- scanner over every live agent_board function rather than over vectors, so a
25
+ -- desync on real source (which is exactly how #199 was found) fails here.
26
+ -- ===========================================================================
27
+ create extension if not exists pgtap with schema extensions;
28
+ set search_path = extensions, public, agent_board;
29
+
30
+ begin;
31
+
32
+ select plan(31);
33
+
34
+ -- ---------------------------------------------------------------------------
35
+ -- The four demonstrated masking constructs.
36
+ -- ---------------------------------------------------------------------------
37
+ select is(
38
+ agent_board_test.strip_sql(E'a -- MARKER\nb'),
39
+ E'a \nb',
40
+ 'MASK 1 (line comment): a `--` comment naming the marker is removed');
41
+
42
+ select is(
43
+ agent_board_test.strip_sql('a /* MARKER **/ b'),
44
+ 'a b',
45
+ 'MASK 2 (block comment ending in `*`): `/* … **/` is removed -- the regex form `(/\*([^*]|\*[^/])*\*/)` could not match this at all');
46
+
47
+ select is(
48
+ agent_board_test.strip_sql(E'a /* note /* x */\nselect * into v_board from agent_board.boards b where b.id = v_inv.board_id for update;\n*/ b'),
49
+ 'a b',
50
+ 'MASK 3 (NESTED block comment, message-board#199): the code after the INNER `*/` is removed too -- this is the construct that left two hardened files fully green with the lock relocated');
51
+
52
+ select is(
53
+ agent_board_test.strip_sql($x$v_note := 'MARKER'; b$x$),
54
+ 'v_note := ; b',
55
+ 'MASK 4 (string literal): `raise debug ''…''`-style prose naming the marker is removed');
56
+
57
+ -- ...and the mode that keeps literals keeps EXACTLY the literals, not the comments.
58
+ select is(
59
+ agent_board_test.strip_sql(E'v_note := \'MARKER\'; -- and a comment\nb', true),
60
+ E'v_note := \'MARKER\'; \nb',
61
+ 'p_keep_literals keeps the literal (for a marker that IS a literal) and still removes the comment');
62
+
63
+ -- ---------------------------------------------------------------------------
64
+ -- Desync vectors: constructs that make a two-pass or regex scanner lose its
65
+ -- place, so that a LIVE statement afterwards is silently dropped or kept.
66
+ -- ---------------------------------------------------------------------------
67
+ select is(
68
+ agent_board_test.strip_sql($x$x 'it''s -- not a comment' y$x$),
69
+ 'x y',
70
+ 'DESYNC: a doubled quote does not end the literal, and a `--` inside a literal is not a comment');
71
+
72
+ select is(
73
+ agent_board_test.strip_sql($x$p $r$ don't /* nope $r$ q$x$),
74
+ 'p q',
75
+ 'DESYNC: a dollar-quoted block with an ODD apostrophe count is consumed whole -- `mark_retention_metadata` survives a naive scanner today only because its 64 apostrophes happen to be even');
76
+
77
+ select is(
78
+ agent_board_test.strip_sql(E'select "weird\'col" -- c\n, z'),
79
+ E'select "weird\'col" \n, z',
80
+ 'DESYNC: an apostrophe inside a "quoted identifier" does not open a literal -- the identifier is CODE and survives');
81
+
82
+ -- PostgreSQL permits `$` INSIDE an unquoted identifier and consumes it greedily,
83
+ -- so `foo$tag$danger$tag$` is ONE identifier -- live code, not a dollar-quoted
84
+ -- string. A scanner that does not look at the preceding character reads `$tag$`
85
+ -- as an opener and silently DELETES the rest. Confirmed against the server rather
86
+ -- than argued: `do $do$ declare foo$tag$danger$tag$ int := 7;
87
+ -- begin raise notice '%', foo$tag$danger$tag$; end $do$;` runs and prints 7.
88
+ select is(
89
+ agent_board_test.strip_sql('select foo$tag$danger$tag$ from t'),
90
+ 'select foo$tag$danger$tag$ from t',
91
+ 'DESYNC: `$` inside an unquoted identifier does not open a dollar quote -- `foo$tag$danger$tag$` is one identifier and survives whole');
92
+
93
+ -- The identifier grammar is NOT ASCII. PostgreSQL accepts any letter the server
94
+ -- encoding recognises, in unquoted identifiers AND in dollar-quote tags, so an
95
+ -- `[A-Za-z0-9_]` class (or an \x80-\xff BYTE range, which is simply wrong for
96
+ -- multi-byte UTF-8) fails in both directions at once. Both confirmed to be legal
97
+ -- SQL against the server, not assumed:
98
+ -- do $do$ begin raise notice '%', $Ω$ hello $Ω$; end $do$;
99
+ -- do $do$ declare Ω$tag$danger$tag$ int := 7; begin raise notice '%', Ω$tag$danger$tag$; end $do$;
100
+ select is(
101
+ agent_board_test.strip_sql('a $Ω$ perform agent_board._lock_board_authority_ceiling(x) $Ω$ b'),
102
+ 'a b',
103
+ 'DESYNC: a NON-ASCII dollar-quote tag still opens a dollar quote -- a marker planted inside `$Ω$ … $Ω$` is stripped, not handed back as code');
104
+
105
+ select is(
106
+ agent_board_test.strip_sql('select Ω$tag$danger$tag$ from t'),
107
+ 'select Ω$tag$danger$tag$ from t',
108
+ 'DESYNC: an identifier STARTING with a non-ASCII letter is still an identifier -- `Ω$tag$danger$tag$` survives whole');
109
+
110
+ -- ...and the identifier class must be LOCALE-INDEPENDENT, not merely non-ASCII
111
+ -- aware. `[[:alpha:]]` is locale-sensitive: under `C` collation it does NOT match
112
+ -- `Ω` (measured: `('Ω' collate "C") ~ '[[:alpha:]]'` is FALSE, while the default
113
+ -- collation says TRUE). A scanner built on it passes here and fails on a runner
114
+ -- with a different collation -- and diverges from the JS mirror in scripts/, so the
115
+ -- two enforcement paths would disagree about the same file. These two vectors pin
116
+ -- the behaviour under an explicitly C-collated input.
117
+ select is(
118
+ agent_board_test.strip_sql(('a $Ω$ perform agent_board._lock_board_authority_ceiling(x) $Ω$ b' collate "C")),
119
+ 'a b',
120
+ 'LOCALE: a non-ASCII dollar-quote tag is stripped under C collation too -- the identifier class is collation-free');
121
+
122
+ select is(
123
+ agent_board_test.strip_sql(('select Ω$tag$danger$tag$ from t' collate "C")),
124
+ 'select Ω$tag$danger$tag$ from t',
125
+ 'LOCALE: a non-ASCII identifier survives under C collation too');
126
+
127
+ select is(
128
+ agent_board_test.strip_sql('select foo$$danger$$ from t'),
129
+ 'select foo$$danger$$ from t',
130
+ 'DESYNC: the same holds for the untagged form -- `foo$$danger$$` is an identifier, not code plus a $$-quoted string');
131
+
132
+ select is(
133
+ agent_board_test.strip_sql(E'select $1 + $2 -- c\nfrom t'),
134
+ E'select $1 + $2 \nfrom t',
135
+ 'DESYNC: `$1` is a parameter, not a dollar quote -- a tag cannot start with a digit, and treating it as one would swallow live SQL');
136
+
137
+ select is(
138
+ agent_board_test.strip_sql($x$a E'x\'y -- z' b$x$),
139
+ 'a b',
140
+ 'DESYNC: in an E-string a backslash escapes the closing quote, so the literal ends where the E-string rules say it does');
141
+
142
+ select is(
143
+ agent_board_test.strip_sql($x$a '/*' b '*/' c$x$, true),
144
+ $x$a '/*' b '*/' c$x$,
145
+ 'DESYNC: comment OPENERS inside literals are not comment openers, even in keep-literals mode');
146
+
147
+ select is(
148
+ agent_board_test.strip_sql('a/*x*/b'),
149
+ 'a b',
150
+ 'TOKENS: a stripped construct collapses to a SPACE, so `a/*x*/b` never becomes the identifier `ab`');
151
+
152
+ select is(
153
+ agent_board_test.strip_sql(null),
154
+ null,
155
+ 'NULL in, NULL out');
156
+
157
+ -- ---------------------------------------------------------------------------
158
+ -- FAIL CLOSED. An unterminated construct raises rather than returning a
159
+ -- truncated body -- a short string silently satisfies every `!~` in the suite.
160
+ -- ---------------------------------------------------------------------------
161
+ select throws_ok(
162
+ $$ select agent_board_test.strip_sql('a /* oops') $$,
163
+ null, null,
164
+ 'FAIL-CLOSED: an unterminated block comment raises instead of returning a truncated body');
165
+
166
+ select throws_ok(
167
+ $$ select agent_board_test.strip_sql('a ''oops') $$,
168
+ null, null,
169
+ 'FAIL-CLOSED: an unterminated string literal raises');
170
+
171
+ select throws_ok(
172
+ $$ select agent_board_test.strip_sql('a $q$ oops') $$,
173
+ null, null,
174
+ 'FAIL-CLOSED: an unterminated dollar-quoted string raises');
175
+
176
+ select throws_ok(
177
+ $$ select agent_board_test.strip_sql('a "oops') $$,
178
+ null, null,
179
+ 'FAIL-CLOSED: an unterminated quoted identifier raises');
180
+
181
+ -- ---------------------------------------------------------------------------
182
+ -- stripped_def: the header must survive, the body must NOT be deleted.
183
+ -- ---------------------------------------------------------------------------
184
+ -- pg_get_functiondef wraps the body in a dollar quote (`AS $function$ … $function$`).
185
+ -- Handing that whole string to a dollar-quote-aware strip deletes the ENTIRE body
186
+ -- and every negative assertion over the result passes. stripped_def() splices
187
+ -- instead, and these two assertions are what stop that regression.
188
+ select ok(
189
+ agent_board_test.stripped_def('agent_board.update_board_membership(uuid,uuid,text,jsonb)'::regprocedure)
190
+ ~ 'SECURITY DEFINER',
191
+ 'stripped_def keeps the generated HEADER -- SECURITY DEFINER is still matchable');
192
+
193
+ -- The token below is deliberately one that appears ONLY in the body. The first
194
+ -- version of this assertion used `board_memberships` against
195
+ -- _upsert_board_membership_state, whose header says `RETURNS
196
+ -- agent_board.board_memberships` -- so it passed even with the entire body
197
+ -- deleted, which is precisely the failure it was written to catch.
198
+ select ok(
199
+ agent_board_test.stripped_def('agent_board.update_board_membership(uuid,uuid,text,jsonb)'::regprocedure)
200
+ ~ '_membership_consent_present',
201
+ 'stripped_def does NOT delete the body -- a BODY-ONLY code token is still matchable');
202
+
203
+ select ok(
204
+ length(agent_board_test.stripped_def('agent_board.mark_retention_metadata(text,timestamp with time zone,uuid,text)'::regprocedure))
205
+ > length(pg_get_functiondef('agent_board.mark_retention_metadata(text,timestamp with time zone,uuid,text)'::regprocedure)) / 4,
206
+ 'stripped_def on a body containing a dollar-quoted block keeps the surrounding code rather than collapsing the definition');
207
+
208
+ -- ---------------------------------------------------------------------------
209
+ -- CORPUS (catalog-derived). The vectors above are written by hand and can only
210
+ -- prove what their author thought of. These run the scanner over every live
211
+ -- agent_board function: a desync leaves a comment delimiter behind, and the
212
+ -- offender NAMES ITSELF.
213
+ -- ---------------------------------------------------------------------------
214
+ select is(
215
+ (select coalesce(string_agg(proname, ', ' order by proname), '')
216
+ from (
217
+ select p.proname, agent_board_test.stripped_body(p.oid) as b
218
+ from pg_proc p
219
+ join pg_namespace n on n.oid = p.pronamespace
220
+ where n.nspname = 'agent_board'
221
+ and p.prolang <> (select oid from pg_language where lanname = 'internal')
222
+ ) s
223
+ where b ~ '--' or b ~ '/\*' or b ~ '\*/'),
224
+ '',
225
+ 'CORPUS: no agent_board function body leaves a comment delimiter behind after the default strip');
226
+
227
+ select is(
228
+ (select coalesce(string_agg(proname, ', ' order by proname), '')
229
+ from (
230
+ select p.proname, agent_board_test.stripped_body(p.oid, true) as b
231
+ from pg_proc p
232
+ join pg_namespace n on n.oid = p.pronamespace
233
+ where n.nspname = 'agent_board'
234
+ and p.prolang <> (select oid from pg_language where lanname = 'internal')
235
+ ) s
236
+ where b ~ '--' or b ~ '/\*' or b ~ '\*/'),
237
+ '',
238
+ 'CORPUS: the keep-literals mode still removes every comment form -- removing comments is its only job there');
239
+
240
+ -- NON-VACUITY, both directions. The two corpus checks above would pass on a
241
+ -- corpus with no comments in it, and they would also pass if the scanner returned
242
+ -- the empty string for everything. Neither is true, and both are asserted rather
243
+ -- than assumed.
244
+ --
245
+ -- Stated plainly because it bounds what the corpus checks prove: the live
246
+ -- agent_board corpus contains 62 bodies with `--` comments and ZERO with a block
247
+ -- comment, so the block-comment half of those checks is a TRIPWIRE for the day
248
+ -- one appears, not evidence today. The block-comment and nested-block-comment
249
+ -- behaviour is pinned by the vectors above instead, where it can be mutated.
250
+ select cmp_ok(
251
+ (select count(*)::int
252
+ from pg_proc p
253
+ join pg_namespace n on n.oid = p.pronamespace
254
+ where n.nspname = 'agent_board'
255
+ and p.prolang <> (select oid from pg_language where lanname = 'internal')
256
+ and p.prosrc ~ '--'),
257
+ '>', 20,
258
+ 'CORPUS NON-VACUITY: the corpus really does contain `--` comments for the strip to remove');
259
+ select ok(
260
+ (select min(length(agent_board_test.stripped_body(p.oid)))
261
+ from pg_proc p
262
+ join pg_namespace n on n.oid = p.pronamespace
263
+ where n.nspname = 'agent_board'
264
+ and p.prolang <> (select oid from pg_language where lanname = 'internal')
265
+ and length(p.prosrc) > 200) > 50,
266
+ 'CORPUS NON-VACUITY: every non-trivial body still has substance after stripping -- the corpus checks are not passing on empty strings');
267
+
268
+ -- stripped_def must not be "simplified" into strip_sql(pg_get_functiondef(...)).
269
+ -- That form deletes the whole body (it is dollar-quoted) and every negative
270
+ -- assertion in the suite would pass on the remains. Asserted as a SIZE relation
271
+ -- against the raw definition so the collapse cannot hide.
272
+ select cmp_ok(
273
+ (select length(agent_board_test.stripped_def(p.oid))::int
274
+ from pg_proc p
275
+ join pg_namespace n on n.oid = p.pronamespace
276
+ where n.nspname = 'agent_board' and p.proname = 'update_board_membership'),
277
+ '>',
278
+ (select (length(pg_get_functiondef(p.oid)) / 2)::int
279
+ from pg_proc p
280
+ join pg_namespace n on n.oid = p.pronamespace
281
+ where n.nspname = 'agent_board' and p.proname = 'update_board_membership'),
282
+ 'stripped_def keeps most of a real definition -- a dollar-quote-aware strip applied to the WHOLE functiondef would leave almost nothing');
283
+
284
+ select * from finish();
285
+ rollback;
@@ -94,14 +94,11 @@ select plan(35);
94
94
  -- Shared helpers. Both are temp objects and vanish with the rollback.
95
95
  -- ---------------------------------------------------------------------------
96
96
 
97
- -- ONE-PASS strip of string literals, line comments, and block comments.
98
- create or replace function pg_temp._wr_strip(p_text text) returns text
99
- language sql immutable as $fn$
100
- select regexp_replace(
101
- coalesce($1, ''),
102
- $re$'(?:[^']|'')*'|--[^\n]*|/\*(?:[^*]|\*+[^*/])*\*+/$re$,
103
- ' ', 'g')
104
- $fn$;
97
+ -- The one-pass strip is agent_board_test.strip_sql(), shared by the whole suite
98
+ -- from tests/fixtures/test-prereqs.sql. The local copy this replaces was a regex,
99
+ -- and no regex can match a NESTED block comment (message-board#199); it also had
100
+ -- no dollar-quote alternative, so it desynced on any body whose apostrophes did
101
+ -- not happen to pair up. Both are handled by construction now.
105
102
 
106
103
  -- A "cursor gate" is a range test against a PRE-COMMIT-ASSIGNED column.
107
104
  --
@@ -166,13 +163,6 @@ $fn$;
166
163
  -- exactly that boundary: it goes red the day a function moves to a SQL-standard
167
164
  -- body, because at that point the parse tree this file could not use becomes
168
165
  -- available and the function half can be made exhaustive too.
169
- create or replace function pg_temp._wr_strip(p_text text) returns text
170
- language sql immutable as $fn$
171
- select regexp_replace(
172
- coalesce($1, ''),
173
- $re$'(?:[^']|'')*'|--[^\n]*|/\*(?:[^*]|\*+[^*/])*\*+/$re$,
174
- ' ', 'g')
175
- $fn$;
176
166
 
177
167
  -- The closure, and the two derived patterns, materialised once.
178
168
  create temp table _wr_class(kind text, pattern text) on commit drop;
@@ -218,7 +208,9 @@ language sql stable as $fn$
218
208
  (select string_agg(distinct regexp_replace(m[1], '[[:space:]]+', ' ', 'g'), ' | ')
219
209
  from _wr_class c,
220
210
  regexp_matches(
221
- pg_temp._wr_strip($1),
211
+ -- literals KEPT: this file's class members put real predicates in
212
+ -- dynamic SQL (see the _wr_members header). Comments are removed.
213
+ agent_board_test.strip_sql($1, true),
222
214
  '(\m(' || c.pattern || ')\M[^<>=]{0,40}(?:<=|>=|<|>)'
223
215
  || '|(?:<=|>=|<|>)[^<>=]{0,40}\m(' || c.pattern || ')\M'
224
216
  || '|\m(' || c.pattern || ')\M[^<>=]{0,20}\mbetween\M'
@@ -228,7 +220,28 @@ language sql stable as $fn$
228
220
  '')
229
221
  $fn$;
230
222
 
231
- create temp table _wr_members(name text, kind text, src text) on commit drop;
223
+ -- `src` is the RAW definition and `body` is the STRIPPED one. Two columns rather
224
+ -- than one because both are legitimately needed: WR-8 reads a jsonb KEY, which is
225
+ -- a string literal and only exists in `src`.
226
+ --
227
+ -- `body` for a FUNCTION is agent_board_test.stripped_body(), never
228
+ -- strip_sql(pg_get_functiondef(...)). pg_get_functiondef wraps the body in a
229
+ -- dollar quote (`AS $function$ … $function$`), so a dollar-quote-aware strip
230
+ -- applied to the whole definition deletes THE ENTIRE BODY and every `!~` over the
231
+ -- result passes. stripped_def() splices the stripped body back into the generated
232
+ -- header instead.
233
+ --
234
+ -- LITERALS ARE KEPT (the `true` argument), and this file is the reason that mode
235
+ -- exists. `mark_retention_metadata` builds its entire retention sweep as DYNAMIC
236
+ -- SQL inside `format($retention$ … $retention$, …)`, so the `created_at <` and
237
+ -- `available_at <=` comparisons WR-7/WR-8 exist to find are CODE THAT LIVES
238
+ -- INSIDE A STRING LITERAL. Measured with literals stripped: WR-7 and WR-8 both
239
+ -- read the empty string -- vacuous, not passing. Comments (all forms, including
240
+ -- the nested one of message-board#199) are still removed in this mode, which is
241
+ -- what closes the message-board#196 masks. It is also the fail-CLOSED direction
242
+ -- for these particular assertions: an extra gate that only exists in a message
243
+ -- makes an exact-set claim RED, never green.
244
+ create temp table _wr_members(name text, kind text, src text, body text) on commit drop;
232
245
 
233
246
  with recursive closure as (
234
247
  select 'agent_board.inbox_items'::regclass as oid
@@ -243,16 +256,16 @@ with recursive closure as (
243
256
  and d.refclassid = 'pg_class'::regclass
244
257
  and r.ev_class <> d.refobjid
245
258
  )
246
- insert into _wr_members(name, kind, src)
247
- select c.relname, 'view', pg_get_viewdef(c.oid)
259
+ insert into _wr_members(name, kind, src, body)
260
+ select c.relname, 'view', pg_get_viewdef(c.oid), agent_board_test.stripped_viewdef(c.oid, true)
248
261
  from closure cl
249
262
  join pg_class c on c.oid = cl.oid
250
263
  join pg_namespace n on n.oid = c.relnamespace
251
264
  where c.relkind in ('v', 'm')
252
265
  and n.nspname = 'agent_board';
253
266
 
254
- insert into _wr_members(name, kind, src)
255
- select p.proname, 'function', pg_get_functiondef(p.oid)
267
+ insert into _wr_members(name, kind, src, body)
268
+ select p.proname, 'function', pg_get_functiondef(p.oid), agent_board_test.stripped_body(p.oid, true)
256
269
  from pg_proc p
257
270
  join pg_namespace n on n.oid = p.pronamespace
258
271
  where n.nspname = 'agent_board'
@@ -339,7 +352,8 @@ select is(
339
352
  'WR-4 the wake recovery view definition references no pre-commit ordering column in a comparison -- a cursor filter in view clothing is NAMED here');
340
353
 
341
354
  select ok(
342
- (select pg_get_viewdef(to_regclass('agent_board.v_agent_wake_recovery')) !~* '\morder[[:space:]]+by\M'),
355
+ (select agent_board_test.stripped_viewdef(to_regclass('agent_board.v_agent_wake_recovery'), true)
356
+ !~* '\morder[[:space:]]+by\M'),
343
357
  'WR-4 the wake recovery view carries no ORDER BY -- the unhandled set is a SET, not a cursor stream');
344
358
 
345
359
  -- ---------------------------------------------------------------------------
@@ -583,7 +597,7 @@ select is(
583
597
  select is(
584
598
  (select coalesce(string_agg(distinct name, ', ' order by name), '')
585
599
  from _wr_members
586
- where pg_temp._wr_cursor_gates(src) <> ''),
600
+ where pg_temp._wr_cursor_gates(body) <> ''),
587
601
  'claim_callback_outbox_events, mark_retention_metadata',
588
602
  'WR-7 no member of the derived class gates on a derived pre-commit column, except the two asserted positively below -- an offender NAMES ITSELF here');
589
603
 
@@ -599,17 +613,20 @@ select is(
599
613
  'WR-8 mark_retention_metadata returns a COUNT and is not set-returning -- it hands no batch to a consumer, so its comparison cannot be a recovery cursor');
600
614
 
601
615
  select is(
602
- (select pg_temp._wr_cursor_gates(src) from _wr_members where name = 'mark_retention_metadata'),
616
+ (select pg_temp._wr_cursor_gates(body) from _wr_members where name = 'mark_retention_metadata'),
603
617
  'created_at <',
604
618
  'WR-8 mark_retention_metadata''s ONLY pre-commit comparison is `created_at <` (an age cutoff) -- it never compares seq, and never gates on a lower bound');
605
619
 
606
- -- Read from the RAW definition on purpose: `ops_retention_reason` is a jsonb KEY,
607
- -- i.e. a string literal, and the one-pass strip removes it. The companion half of
608
- -- this assertion is read from the STRIPPED definition, where the UPDATE survives
609
- -- because it lives inside a dollar-quoted body rather than a single-quoted one.
620
+ -- `ops_retention_reason` is a jsonb KEY -- a string literal -- so it is read from
621
+ -- the RAW definition, which is true regardless of strip mode. The companion half
622
+ -- is read from `body`, i.e. through the shared strip: the UPDATE it looks for is
623
+ -- inside the `$retention$` dynamic-SQL block, which survives because this file
624
+ -- keeps literals (see the _wr_members header) but would NOT survive the default
625
+ -- literal-stripping mode. Restated so the next reader does not "simplify" the two
626
+ -- halves into one column.
610
627
  select ok(
611
628
  (select src ~ 'ops_retention_reason'
612
- and pg_temp._wr_strip(src) ~ 'update agent_board'
629
+ and body ~ 'update agent_board'
613
630
  from _wr_members where name = 'mark_retention_metadata'),
614
631
  'WR-8 mark_retention_metadata stamps retention metadata through an UPDATE sweep -- the age cutoff drives retention, not a fetch');
615
632
 
@@ -628,12 +645,12 @@ select ok(
628
645
  -- SCHEDULING predicate against now(), not a caller-supplied cursor, and the batch
629
646
  -- it hands back is bounded by STATUS (WR-9 below). Both halves are stated.
630
647
  select is(
631
- (select pg_temp._wr_cursor_gates(src) from _wr_members where name = 'claim_callback_outbox_events'),
648
+ (select pg_temp._wr_cursor_gates(body) from _wr_members where name = 'claim_callback_outbox_events'),
632
649
  'available_at <=',
633
650
  'WR-8 claim_callback_outbox_events'' ONLY pre-commit gate is `available_at <=` -- a scheduling predicate, never a lower bound against a caller cursor');
634
651
 
635
652
  select ok(
636
- (select pg_temp._wr_strip(src) !~* '\mavailable_at\M[^<>=]{0,40}(?:>=|>)'
653
+ (select body !~* '\mavailable_at\M[^<>=]{0,40}(?:>=|>)'
637
654
  from _wr_members where name = 'claim_callback_outbox_events'),
638
655
  'WR-8 that gate is an UPPER bound (<=) and never a lower bound -- a `available_at >` would be a cursor, and is what this distinguishes');
639
656
 
@@ -661,7 +678,7 @@ select is(
661
678
  -- WR-9 POSITIVE: the recovery-shaped members partition on STATUS.
662
679
  -- ---------------------------------------------------------------------------
663
680
  select ok(
664
- (select pg_temp._wr_strip(src) ~ 'outbox_status[[:space:]]*(=|in|<>)'
681
+ (select body ~ 'outbox_status[[:space:]]*(=|in|<>)'
665
682
  from _wr_members where name = 'claim_callback_outbox_events'),
666
683
  'WR-9 claim_callback_outbox_events partitions the queue on outbox_status -- the lossless property #187 relies on, restated positively here');
667
684
 
@@ -683,12 +700,12 @@ select is(
683
700
  from pg_proc p
684
701
  where p.pronamespace = 'agent_board'::regnamespace
685
702
  and p.prolang <> (select oid from pg_language where lanname = 'internal')
686
- and pg_temp._wr_strip(pg_get_functiondef(p.oid)) ~ 'action_state[[:space:]]*=[[:space:]]*[^=]'
703
+ and agent_board_test.stripped_body(p.oid, true) ~* 'action_state[[:space:]]*=[[:space:]]*[^=]'
687
704
  -- The schema qualification is OPTIONAL on purpose (board review F3): a writer
688
705
  -- using `set search_path` plus a bare `update inbox_items` was invisible to
689
706
  -- the qualified form, and WR-10 stayed green naming only one writer. Same
690
707
  -- class as the WR-7 name filter -- two name-based enumerators in one file.
691
- and pg_temp._wr_strip(pg_get_functiondef(p.oid)) ~* 'update[[:space:]]+(agent_board\.)?inbox_items\M'),
708
+ and agent_board_test.stripped_body(p.oid, true) ~* 'update[[:space:]]+(agent_board\.)?inbox_items\M'),
692
709
  'update_inbox_item_state',
693
710
  'WR-10 exactly ONE function writes inbox_items.action_state -- the only way out of the unhandled set');
694
711
 
@@ -696,8 +713,8 @@ select is(
696
713
  -- the intuition the comment encoded and it is false: mark_read writes read
697
714
  -- receipts, so a READ item is still unhandled and still woken for.
698
715
  select ok(
699
- (select pg_temp._wr_strip(pg_get_functiondef(p.oid)) !~ 'action_state'
700
- and pg_temp._wr_strip(pg_get_functiondef(p.oid)) ~ 'read_receipts'
716
+ (select agent_board_test.stripped_body(p.oid, true) !~* 'action_state'
717
+ and agent_board_test.stripped_body(p.oid, true) ~* 'read_receipts'
701
718
  from pg_proc p
702
719
  where p.pronamespace = 'agent_board'::regnamespace and p.proname = 'mark_read'),
703
720
  'WR-10 mark_read writes read_receipts and NEVER action_state -- marking an item read does not remove it from the recovery set');
@@ -741,11 +758,12 @@ select is(
741
758
  -- assert a falsehood. Pinning this properly needs named arguments at the call
742
759
  -- sites; until then this is a known, unpinned second exit.
743
760
  select ok(
744
- (select regexp_replace(pg_get_functiondef(p.oid), '--[^\n]*', '', 'g')
745
- ~ 'on conflict[^;]*do update'
761
+ -- CODE markers -> case-insensitive (`ON CONFLICT … DO UPDATE` is the same clause)
762
+ (select agent_board_test.stripped_body(p.oid, true)
763
+ ~* 'on conflict[^;]*do update'
746
764
  and (select m[1] !~ 'action_state'
747
- from regexp_matches(regexp_replace(pg_get_functiondef(p.oid), '--[^\n]*', '', 'g'),
748
- 'on conflict[^;]*do update([^;]*)', 'g') m
765
+ from regexp_matches(agent_board_test.stripped_body(p.oid, true),
766
+ 'on conflict[^;]*do update([^;]*)', 'gi') m
749
767
  limit 1)
750
768
  from pg_proc p
751
769
  where p.pronamespace = 'agent_board'::regnamespace and p.proname = '_upsert_inbox_item'),