@pome-sh/checks 0.1.4 → 0.1.5

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,46 @@
1
1
  # @pome-sh/checks
2
2
 
3
+ ## 0.1.5
4
+
5
+ `slack.no-reaction-added` now refuses instead of scoring a free pass (F-1159).
6
+ Its predicate filtered the exported `reactions` collection with `(final.reactions
7
+ ?? []).some(…)`, so a state export carrying no `reactions` section at all
8
+ filtered to zero rows and scored this NEGATIVE criterion `passed` — an agent
9
+ that really added the reaction still collected the point. It now checks
10
+ `final.reactions == null` first and returns `state_incomplete`, matching
11
+ twin-github's `pull.reviews == null` / `pull.comments == null` skips: absent is
12
+ not the same as none.
13
+
14
+ This closes the gap the same class of criterion in twin-github never had, and
15
+ it is why pome-cloud's `STATE_SECTION_GUARDS` carried a stopgap row for this one
16
+ check (F-1156) — that row is now redundant. No check id, template or polarity
17
+ changed, so no criterion moves from bound to unbound; this only affects the
18
+ verdict on the one export shape (`reactions` absent) that used to be misgraded,
19
+ and on that shape the cloud already returned `state_incomplete` via the stopgap.
20
+ The grade a real run receives does not move.
21
+
22
+ **What pome-cloud must do, and it is TWO edits, not one.** Pinning `0.1.5`
23
+ turns `declared-pin.test.ts` red on its own, before anybody touches the guard
24
+ table, so a follow-up that only deletes the row will not go green:
25
+
26
+ 1. Delete the `slack.no-reaction-added` row from `STATE_SECTION_GUARDS`
27
+ (`apps/control-plane/src/services/evaluators/deterministic/substrate-guards.ts`).
28
+ The arm that asserts every vacuous reader has a row —
29
+ `findVacuousStateSectionReaders(allDeclared(), STATE_SECTION_GUARDS)` — stays
30
+ `[]` with the row present or absent, because the twin now refuses on its own.
31
+ 2. Re-point the NEGATIVE CONTROL beside it, `names the shipped reader when the
32
+ table is empty`. It asserts
33
+ `findVacuousStateSectionReaders(allDeclared(), [])` equals
34
+ `["slack.no-reaction-added:reactions"]` — the detector's only firing case in
35
+ the shipped vocabulary, and this release is what removes it. Measured against
36
+ the built `0.1.5` declarations it now returns `[]`. Give that arm a synthetic
37
+ declaration that still reads absence as a pass, the way the three arms below
38
+ it already build one inline, so the detector keeps a firing case nobody has
39
+ to ship a defect to preserve.
40
+
41
+ Both `apps/control-plane` and `apps/mcp` pin this package exactly and must move
42
+ together, or `save_task` accepts criteria the grader cannot bind.
43
+
3
44
  ## 0.1.4
4
45
 
5
46
  Carries twin-github's widened seed schema to the grader (F-1421). One thing
@@ -173,7 +173,7 @@ var noMessagePosted = defineCheck({
173
173
  });
174
174
  var noReactionAdded = defineCheck({
175
175
  id: "slack.no-reaction-added",
176
- description: "Resolves the named channel, then filters the TOP-LEVEL reactions list by that channel's id and this emoji name, asserting no row matches. Reactions are not nested under their channel in the export, so this is a join the predicate performs itself. It asserts nothing about which message was reacted to, or by whom.",
176
+ description: "Resolves the named channel, then filters the TOP-LEVEL reactions list by that channel's id and this emoji name, asserting no row matches. Reactions are not nested under their channel in the export, so this is a join the predicate performs itself. It asserts nothing about which message was reacted to, or by whom. An export carrying no `reactions` collection at all is SKIPPED, because absent is not the same as none.",
177
177
  template: 'No "{reaction}" reaction was added in the "{channel}" channel',
178
178
  params: { reaction: emojiName, channel: channelName },
179
179
  substrate: "final",
@@ -209,14 +209,20 @@ var noReactionAdded = defineCheck({
209
209
  const found = resolveChannel(final, channel);
210
210
  if ("missing" in found)
211
211
  return missSkip(found);
212
- const hit = (final.reactions ?? []).some((row) => row.channel_id === found.found.id && row.name === reaction);
213
- const joined = [found.path];
214
- if (final.reactions !== void 0)
215
- joined.push(statePath("reactions"));
212
+ if (final.reactions == null)
213
+ return STATE_INCOMPLETE;
214
+ const hit = final.reactions.some((row) => row.channel_id === found.found.id && row.name === reaction);
216
215
  return {
217
216
  passed: !hit,
218
217
  reason: hit ? `reaction "${reaction}" found in channel "${channel}"` : `no reaction "${reaction}" in channel "${channel}"`,
219
- evidenceStatePaths: joined
218
+ // BOTH sides of the join, because this predicate really does read two
219
+ // places and a reader who opens only one cannot check its work: the
220
+ // channel row is where the id came from, the top-level reactions list is
221
+ // what was filtered. Reactions are not nested under their channel in the
222
+ // export — that is the whole reason this check performs a join — so one
223
+ // pointer cannot say it. The guard above already proved `reactions` is
224
+ // present, so both pointers always resolve.
225
+ evidenceStatePaths: [found.path, statePath("reactions")]
220
226
  };
221
227
  }
222
228
  });
package/dist/index.js CHANGED
@@ -5,8 +5,8 @@ import { GMAIL_CHECKS } from './chunk-SA23X6PB.js';
5
5
  export { GMAIL_CHECKS, defaultSeedState as defaultGmailSeed, gmailSeedSchema, parseSeed as parseGmailSeed } from './chunk-SA23X6PB.js';
6
6
  import { LINEAR_CHECKS } from './chunk-THOSO63W.js';
7
7
  export { LINEAR_CHECKS, defaultSeedState as defaultLinearSeed, linearSeedSchema, parseSeed as parseLinearSeed } from './chunk-THOSO63W.js';
8
- import { SLACK_CHECKS } from './chunk-5PDF3GCK.js';
9
- export { SLACK_CHECKS, defaultSeedState as defaultSlackSeed, parseSeed as parseSlackSeed, seedSchema as slackSeedSchema } from './chunk-5PDF3GCK.js';
8
+ import { SLACK_CHECKS } from './chunk-MJOHK2NI.js';
9
+ export { SLACK_CHECKS, defaultSeedState as defaultSlackSeed, parseSeed as parseSlackSeed, seedSchema as slackSeedSchema } from './chunk-MJOHK2NI.js';
10
10
  import { STRIPE_CHECKS } from './chunk-XOUAZPNB.js';
11
11
  export { STRIPE_CHECKS, defaultSeed as defaultStripeSeed, parseSeed as parseStripeSeed, seedSchema as stripeSeedSchema } from './chunk-XOUAZPNB.js';
12
12
  export { REDACTION_PLACEHOLDER, VACUITY_SENTINEL, VACUITY_SENTINEL_NUMBER, VACUITY_SENTINEL_SNAKE, checkNearMissPattern, checkPattern, checksDigest, childStatePath, defineCheck, isRedacted, oneOf, parseCheck, probeDiscrimination, probeRedactionSurvival, probeStateCitation, renderCheck, repoRef, resolveStatePath, statePath, templateSlots } from './chunk-W2JNYULF.js';
package/dist/slack.js CHANGED
@@ -1,2 +1,2 @@
1
- export { SLACK_CHECKS, defaultSeedState, parseSeed, seedSchema } from './chunk-5PDF3GCK.js';
1
+ export { SLACK_CHECKS, defaultSeedState, parseSeed, seedSchema } from './chunk-MJOHK2NI.js';
2
2
  import './chunk-W2JNYULF.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pome-sh/checks",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "Pome's grading vocabulary — the check declarations, seed schemas and default seeds of all five digital twins, plus the check DSL they are written in. Declarations only: no twin server, no database, no routes, no tools.",
5
5
  "private": false,
6
6
  "type": "module",