@pome-sh/checks 0.2.1 → 0.3.1

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,68 @@
1
1
  # @pome-sh/checks
2
2
 
3
+ ## 0.3.1 — 2026-08-18
4
+
5
+ **`slackSeedSchema` accepts a `files` key** (F-1509). This package re-exports
6
+ twin-slack's seed schema (`slackSeedSchema` / `parseSlackSeed` /
7
+ `defaultSlackSeed`), and that schema gained
8
+ `files: [{id?, name, title?, filetype?, user?, channels?, content?}]` so a Slack
9
+ world can be seeded with files rather than only acquiring them through a
10
+ `files.upload` mutation.
11
+
12
+ **No check changed.** `SLACK_CHECKS` is the same tuple, every compiled pattern is
13
+ byte-identical, and `checksDigest` does not move — so a cloud pin does NOT have to
14
+ catch up for this release, unlike 0.3.0 above. The seed schema is a separate export
15
+ from the check vocabulary and only the former widened.
16
+
17
+ **Patch, not minor.** `files` defaults to `[]`, so every seed that parsed before
18
+ parses to the same value, and no consumer must act. It is a widening of an INPUT
19
+ schema, which is the direction that cannot break a caller.
20
+
21
+ ## 0.3.0 — 2026-08-14
22
+
23
+ **`` `add_issue_comment` was called `` binds, and the github tape slot widens
24
+ from two names to three** (F-1521). No check is added or removed —
25
+ `GITHUB_CHECKS` stays at sixteen — but `github.tool-was-called` and
26
+ `github.tool-never-called` share one slot type generated from the twin's
27
+ `TAPE_ASSERTABLE_TOOLS`, so both of their compiled patterns move:
28
+
29
+ ```
30
+ before ^`((?:create_commit_status|create_check_run))` was (never )?called$
31
+ after ^`((?:create_commit_status|create_check_run|add_issue_comment))` was (never )?called$
32
+ ```
33
+
34
+ **Minor, and the pattern is the whole reason.** `checksDigest` hashes
35
+ `{id, substrate, pattern}` per check, so a widened alternation moves the digest
36
+ and every pin must catch up:
37
+
38
+ ```
39
+ before sha256:3e426067133135045418b88dedaf98050f19e58610481799d1f81a38ecf3adfc
40
+ after sha256:fcaef7734f88d874e1e0da85eeab06ff6521e6036134d78c8112a9ed62ad7cd2
41
+ ```
42
+
43
+ Until the cloud pins this version, `pome checks add --check
44
+ github.tool-was-called` reports `this CLI has it, the cloud does not` and
45
+ declines to write the new sentence — the same handshake 0.2.0 describes,
46
+ working as designed rather than a defect. Nothing that binds today changes
47
+ verdict: every sentence that parsed against the old pattern parses against the
48
+ new one, and both predicates read `event.tool` exactly as before.
49
+
50
+ **Why one name and not F-1342's sweep.** M0's slice task needs to prove the
51
+ examinee actually left its comment, and only a positive tape assertion can say
52
+ so — a prohibition cannot separate *"held the line"* from *"never showed up"*.
53
+ The vocabulary for that shipped in 0.2.0; the sentence the slice wanted did not
54
+ bind, because the twin's REST comment route was unstamped and the stamping
55
+ invariant refuses positive assertions on unstamped names. So one route was
56
+ stamped and its both-doors probe paid for. `merge_pull_request` and
57
+ `add_issue_labels` are still unstamped and their sentences still correctly refuse
58
+ to bind, in both directions.
59
+
60
+ **Consumers pinning `@pome-sh/sandbox-domains` must move both together.** That
61
+ package re-exports the same `GITHUB_CHECKS` tuple, and
62
+ `checks-package-drift.test.ts` demands the two declare an identical binding
63
+ surface per twin — so this release and its `@pome-sh/sandbox-domains` sibling are
64
+ cut from one `main` commit and must be pinned as a pair.
65
+
3
66
  ## 0.2.1 — 2026-08-13
4
67
 
5
68
  No change to the vocabulary: every check id, template, polarity and seed schema
@@ -35,6 +35,15 @@ export declare const seedSchema: z.ZodObject<{
35
35
  }, z.core.$strip>>>;
36
36
  }, z.core.$strip>>>;
37
37
  }, z.core.$strip>>>;
38
+ files: z.ZodDefault<z.ZodArray<z.ZodObject<{
39
+ id: z.ZodOptional<z.ZodString>;
40
+ name: z.ZodString;
41
+ title: z.ZodOptional<z.ZodString>;
42
+ filetype: z.ZodDefault<z.ZodString>;
43
+ user: z.ZodOptional<z.ZodString>;
44
+ channels: z.ZodDefault<z.ZodArray<z.ZodString>>;
45
+ content: z.ZodOptional<z.ZodString>;
46
+ }, z.core.$strip>>>;
38
47
  emoji: z.ZodDefault<z.ZodArray<z.ZodObject<{
39
48
  name: z.ZodString;
40
49
  url: z.ZodOptional<z.ZodString>;
@@ -44,10 +44,40 @@ export type SeedEmoji = {
44
44
  /** Alias target name → stored as `alias:<name>`. */
45
45
  alias?: string;
46
46
  };
47
+ /**
48
+ * A file present in the world before the agent touches it (F-1509).
49
+ *
50
+ * Until this existed the `files` table had exactly ONE writer — `filesUpload`,
51
+ * a mutation — so every read of `files.list` / `files.info` against a freshly
52
+ * seeded world answered on an empty table. That is not a serializer gap and it
53
+ * was not a deliberate ruling; it is simply a hole in the seed vocabulary, and
54
+ * it made `files.list` a surface no read-only comparison could measure.
55
+ *
56
+ * `user` and `channels` carry SEED HANDLES (a user `name` / channel `name`), the
57
+ * same currency `SeedMessage.user` and `SeedChannel.members` use, so a seed never
58
+ * has to know a minted id. Both also accept an explicit id.
59
+ */
60
+ export type SeedFile = {
61
+ /** Explicit stable id (`F…`). Minted from the workspace counter when absent. */
62
+ id?: string;
63
+ /** Filename, e.g. `runbook.md`. */
64
+ name: string;
65
+ /** Display title. Defaults to `name`, matching `files.upload`. */
66
+ title?: string;
67
+ /** Slack filetype (`text`, `markdown`, `javascript`, …). Drives `mimetype`. */
68
+ filetype?: string;
69
+ /** Uploader — a seed user handle or id. Defaults to the seed's agent user. */
70
+ user?: string;
71
+ /** Channels the file is shared into — seed channel handles or ids. */
72
+ channels?: string[];
73
+ /** File body. `size` is derived from it, as `files.upload` derives it. */
74
+ content?: string;
75
+ };
47
76
  export type SlackStateSeed = {
48
77
  team?: SeedTeam;
49
78
  users?: SeedUser[];
50
79
  channels?: SeedChannel[];
80
+ files?: SeedFile[];
51
81
  emoji?: SeedEmoji[];
52
82
  };
53
83
  export type WorkspaceRow = {
@@ -2,7 +2,11 @@ import { oneOf, defineCheck, repoRef, VACUITY_SENTINEL_NUMBER, childStatePath, V
2
2
  import { z } from 'zod';
3
3
 
4
4
  // ../twin-github/dist/src/tape-assertable-tools.js
5
- var TAPE_ASSERTABLE_TOOLS = ["create_commit_status", "create_check_run"];
5
+ var TAPE_ASSERTABLE_TOOLS = [
6
+ "create_commit_status",
7
+ "create_check_run",
8
+ "add_issue_comment"
9
+ ];
6
10
 
7
11
  // ../twin-github/dist/src/check-params.js
8
12
  var entityNumber = (name) => ({
@@ -787,7 +791,7 @@ var toolNeverCalled = defineCheck({
787
791
  // that a verified fact rather than an assumption.
788
792
  subject: (args) => args.tool,
789
793
  // Null, and admitted in `HONEST_NULL_MUTANTS`. The only slot is a closed set,
790
- // so there is no value guaranteed to be false: a mutant naming the OTHER
794
+ // so there is no value guaranteed to be false: a mutant naming ANOTHER
791
795
  // assertable action asserts something that may well also be true, and a value
792
796
  // outside the set does not re-bind at all — which reads as "the verdict moved"
793
797
  // and would bless the very criterion the probe exists to catch.
@@ -837,9 +841,9 @@ var toolWasCalled = defineCheck({
837
841
  // nothing, i.e. failing an agent that did the work.
838
842
  subject: (args) => args.tool,
839
843
  // Null, and admitted in `HONEST_NULL_MUTANTS`. Same closed-set argument as the
840
- // sibling: the only substitutable value is the OTHER assertable action, which
841
- // an agent may well have called too, and a value outside the set does not
842
- // re-bind at all.
844
+ // sibling: every substitutable value is ANOTHER assertable action, which an
845
+ // agent may well have called too, and a value outside the set does not re-bind
846
+ // at all.
843
847
  vacuityMutant: () => null,
844
848
  // A POSITIVE check, so the passing world is the one where the action WAS
845
849
  // called. The failing world is deliberately NOT an empty tape: `[]` fails
@@ -380,6 +380,18 @@ var seedSchema = z.object({
380
380
  reactions: z.array(z.object({ name: z.string(), user: z.string() })).default([])
381
381
  })).default([])
382
382
  })).default([]),
383
+ // F-1509. Files present in the world before the agent runs. `user` and
384
+ // `channels` are seed HANDLES (a user/channel `name`) or ids — the same
385
+ // currency `channels[].members` and `channels[].messages[].user` already use.
386
+ files: z.array(z.object({
387
+ id: z.string().regex(/^F[A-Z0-9_]+$/).optional(),
388
+ name: z.string().min(1),
389
+ title: z.string().optional(),
390
+ filetype: z.string().min(1).default("text"),
391
+ user: z.string().optional(),
392
+ channels: z.array(z.string()).default([]),
393
+ content: z.string().optional()
394
+ })).default([]),
383
395
  emoji: z.array(z.object({
384
396
  name: z.string().regex(/^[a-z0-9_+-]{1,100}$/),
385
397
  url: z.string().url().optional(),
package/dist/github.js CHANGED
@@ -1,2 +1,2 @@
1
- export { GITHUB_CHECKS, defaultSeedState, parseSeed, seedSchema } from './chunk-XTSASWF4.js';
1
+ export { GITHUB_CHECKS, defaultSeedState, parseSeed, seedSchema } from './chunk-E2AKLQVI.js';
2
2
  import './chunk-W2JNYULF.js';
package/dist/index.js CHANGED
@@ -1,12 +1,12 @@
1
1
  import './chunk-ZXE6LAM3.js';
2
- import { GITHUB_CHECKS } from './chunk-XTSASWF4.js';
3
- export { GITHUB_CHECKS, defaultSeedState as defaultGitHubSeed, seedSchema as githubSeedSchema, parseSeed as parseGitHubSeed } from './chunk-XTSASWF4.js';
2
+ import { GITHUB_CHECKS } from './chunk-E2AKLQVI.js';
3
+ export { GITHUB_CHECKS, defaultSeedState as defaultGitHubSeed, seedSchema as githubSeedSchema, parseSeed as parseGitHubSeed } from './chunk-E2AKLQVI.js';
4
4
  import { GMAIL_CHECKS } from './chunk-KTTJCEDH.js';
5
5
  export { GMAIL_CHECKS, defaultSeedState as defaultGmailSeed, gmailSeedSchema, parseSeed as parseGmailSeed } from './chunk-KTTJCEDH.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-MJOHK2NI.js';
9
- export { SLACK_CHECKS, defaultSeedState as defaultSlackSeed, parseSeed as parseSlackSeed, seedSchema as slackSeedSchema } from './chunk-MJOHK2NI.js';
8
+ import { SLACK_CHECKS } from './chunk-ZXS3NTSQ.js';
9
+ export { SLACK_CHECKS, defaultSeedState as defaultSlackSeed, parseSeed as parseSlackSeed, seedSchema as slackSeedSchema } from './chunk-ZXS3NTSQ.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-MJOHK2NI.js';
1
+ export { SLACK_CHECKS, defaultSeedState, parseSeed, seedSchema } from './chunk-ZXS3NTSQ.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.2.1",
3
+ "version": "0.3.1",
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",