@ultimat3/cli 30.4.0 → 30.5.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ultimat3/cli",
3
- "version": "30.4.0",
3
+ "version": "30.5.0",
4
4
  "description": "The `x` binary: new, dev, build, verify, generate, db, mcp, doctor, deploy",
5
5
  "keywords": [
6
6
  "ultimate",
@@ -53,33 +53,33 @@
53
53
  },
54
54
  "dependencies": {
55
55
  "@babel/core": "^8.0.7",
56
- "@ultimat3/action": "30.4.0",
57
- "@ultimat3/admin": "30.4.0",
58
- "@ultimat3/ai": "30.4.0",
59
- "@ultimat3/auth": "30.4.0",
60
- "@ultimat3/cache": "30.4.0",
61
- "@ultimat3/core": "30.4.0",
62
- "@ultimat3/db": "30.4.0",
63
- "@ultimat3/entity": "30.4.0",
64
- "@ultimat3/flags": "30.4.0",
65
- "@ultimat3/http": "30.4.0",
66
- "@ultimat3/i18n": "30.4.0",
67
- "@ultimat3/jobs": "30.4.0",
68
- "@ultimat3/mail": "30.4.0",
69
- "@ultimat3/manifest": "30.4.0",
70
- "@ultimat3/mcp": "30.4.0",
71
- "@ultimat3/money": "30.4.0",
72
- "@ultimat3/notify": "30.4.0",
73
- "@ultimat3/policy": "30.4.0",
74
- "@ultimat3/pwa": "30.4.0",
75
- "@ultimat3/query": "30.4.0",
76
- "@ultimat3/realtime": "30.4.0",
77
- "@ultimat3/render": "30.4.0",
78
- "@ultimat3/schema": "30.4.0",
79
- "@ultimat3/seo": "30.4.0",
80
- "@ultimat3/storage": "30.4.0",
81
- "@ultimat3/testing": "30.4.0",
82
- "@ultimat3/time": "30.4.0",
56
+ "@ultimat3/action": "30.5.0",
57
+ "@ultimat3/admin": "30.5.0",
58
+ "@ultimat3/ai": "30.5.0",
59
+ "@ultimat3/auth": "30.5.0",
60
+ "@ultimat3/cache": "30.5.0",
61
+ "@ultimat3/core": "30.5.0",
62
+ "@ultimat3/db": "30.5.0",
63
+ "@ultimat3/entity": "30.5.0",
64
+ "@ultimat3/flags": "30.5.0",
65
+ "@ultimat3/http": "30.5.0",
66
+ "@ultimat3/i18n": "30.5.0",
67
+ "@ultimat3/jobs": "30.5.0",
68
+ "@ultimat3/mail": "30.5.0",
69
+ "@ultimat3/manifest": "30.5.0",
70
+ "@ultimat3/mcp": "30.5.0",
71
+ "@ultimat3/money": "30.5.0",
72
+ "@ultimat3/notify": "30.5.0",
73
+ "@ultimat3/policy": "30.5.0",
74
+ "@ultimat3/pwa": "30.5.0",
75
+ "@ultimat3/query": "30.5.0",
76
+ "@ultimat3/realtime": "30.5.0",
77
+ "@ultimat3/render": "30.5.0",
78
+ "@ultimat3/schema": "30.5.0",
79
+ "@ultimat3/seo": "30.5.0",
80
+ "@ultimat3/storage": "30.5.0",
81
+ "@ultimat3/testing": "30.5.0",
82
+ "@ultimat3/time": "30.5.0",
83
83
  "babel-preset-solid": "^1.9.16"
84
84
  }
85
85
  }
@@ -12,7 +12,7 @@ import {
12
12
  renderFixShellArg,
13
13
  } from '@ultimat3/core';
14
14
  import type { ExerciseRecord } from '@ultimat3/testing';
15
- import { planSweepFindings, tenantProofFindings } from '@ultimat3/testing';
15
+ import { crashEffectPlace, planSweepFindings, tenantProofFindings } from '@ultimat3/testing';
16
16
  import type { Finding } from './output';
17
17
  import { renderTable } from './table';
18
18
 
@@ -44,6 +44,20 @@ export const exerciseCounts = (records: readonly ExerciseRecord[]): ExerciseCoun
44
44
  };
45
45
  };
46
46
 
47
+ /**
48
+ * A 5xx's own words — the cause testing recorded (credential values already masked there) and the
49
+ * fields a validation failure names. The statement is inside the cause, so it is not said twice.
50
+ */
51
+ const defectOf = (record: ExerciseRecord): string => {
52
+ const defect = record.defect;
53
+ if (defect === undefined) return '';
54
+ const fields =
55
+ defect.fields === undefined
56
+ ? ''
57
+ : ` at ${defect.fields.map((field) => renderCauseValue(field)).join(', ')}`;
58
+ return ` — cause: ${renderCauseValue(defect.cause)}${fields}`;
59
+ };
60
+
47
61
  /**
48
62
  * `X_CONTRACT_EXERCISE_UNREACHED`, `@ultimat3/action`'s code for the same silence one level up: a
49
63
  * primitive no run got to as an allowed actor. The fix is the override the pass printed, or the
@@ -56,7 +70,7 @@ const unreachedFinding = (record: ExerciseRecord): Finding => {
56
70
  const why = record.reason === undefined ? '' : ` (${renderCauseValue(record.reason)})`;
57
71
  return {
58
72
  code: 'X_CONTRACT_EXERCISE_UNREACHED',
59
- cause: `${record.kind} ${renderCauseValue(record.name)} never reached its handler as an allowed actor in the exercise pass${stopped}${why}`,
73
+ cause: `${record.kind} ${renderCauseValue(record.name)} never reached its handler as an allowed actor in the exercise pass${stopped}${why}${defectOf(record)}`,
60
74
  fix:
61
75
  record.fix ??
62
76
  `defineExercise({ ${override} }) # paste the entry into ${EXERCISE_FILE}, or { off: '<why>' }; then: x exercise ${name} --json`,
@@ -75,27 +89,29 @@ const crashFindingsOf = (record: ExerciseRecord): readonly CrashFinding[] =>
75
89
 
76
90
  /**
77
91
  * `X_JOB_CRASH_DIVERGED`, testing's code: a reached job, killed at a step boundary, made an effect
78
- * more often than a clean run — it sits outside every `step.run`, so a retry makes it again. One
79
- * finding per effect and the step it follows, every boundary that showed it named in the cause.
92
+ * a different number of times than a clean run. Where it ran — outside every `step.run`, or inside
93
+ * one whose body re-runs — is testing's `crashEffectPlace`, the phrase its error uses too. One
94
+ * finding per effect and place, every boundary that showed it named in the cause.
80
95
  */
81
96
  const crashFindings = (record: ExerciseRecord): readonly Finding[] => {
82
97
  const groups = new Map<string, CrashFinding[]>();
83
98
  for (const one of crashFindingsOf(record)) {
84
- const key = `${one.effect}\u0000${one.after ?? ''}`;
99
+ const key = `${one.effect}\u0000${one.after ?? ''}\u0000${one.inside ?? ''}`;
85
100
  groups.set(key, [...(groups.get(key) ?? []), one]);
86
101
  }
87
102
  const job = renderFixShellArg(record.name, '<job>');
88
103
  return [...groups.values()].map((group): Finding => {
89
104
  const [first] = group as [CrashFinding, ...CrashFinding[]];
90
- const where =
91
- first.after === undefined
92
- ? 'before the first step'
93
- : `after step ${JSON.stringify(first.after)}`;
105
+ const { place, remedy } = crashEffectPlace(first);
106
+ const how =
107
+ first.killed > first.clean
108
+ ? 'the retry after a crash makes it again'
109
+ : 'the crash skipped it';
94
110
  const at = group.map((one) => JSON.stringify(one.boundary)).join(', ');
95
111
  return {
96
112
  code: 'X_JOB_CRASH_DIVERGED',
97
- cause: `job ${renderCauseValue(record.name)} killed at ${at} made ${renderCauseValue(first.effect)} ${first.killed}× against ${first.clean}× in a clean run: it runs outside every step, ${where}, so the retry after a crash makes it again`,
98
- fix: `x exercise ${job} --json # in job(${renderFixLiteral(record.name, '<job>')}): wrap the ${renderFixLiteral(first.effect, '<effect>')} made ${where} in step.run('<name>', async () => …)`,
113
+ cause: `job ${renderCauseValue(record.name)} killed at ${at} made ${renderCauseValue(first.effect)} ${first.killed}× against ${first.clean}× in a clean run: ${place}, so ${how}`,
114
+ fix: `x exercise ${job} --json # in job(${renderFixLiteral(record.name, '<job>')}), for ${renderFixLiteral(first.effect, '<effect>')}: ${remedy}`,
99
115
  docs: ERROR_DOCS_URL,
100
116
  at: `${record.kind} ${record.name}`,
101
117
  };
package/wiki/Testing.md CHANGED
@@ -92,6 +92,7 @@ Any test that can pass twice and fail the third time is worse than no test — i
92
92
  | **Frozen clock** | time starts at a fixed instant. `clock.advance('3d')` moves it, and it also drives `step.sleep` and cron in tests |
93
93
  | **Seeded RNG** | `Math.random`, `crypto.randomUUID`, and Bun's RNG are seeded per test file from its path — reproducible, distinct across files |
94
94
  | **Sealed network** | a `fetch`, a `new WebSocket(…)` or a `Bun.connect(…)` to anywhere not explicitly mocked or allowed **fails the test** with `X_TEST_NETWORK_SEALED`, naming the URL and the fix — the three dials share one gate, so the allow-list and `offline()` apply to all of them — `offline()` refuses a loopback dial too (`X_TEST_NETWORK_OFFLINE`). A dial that goes around those three globals (a `node:net` socket, `Bun.udpSocket`) is not sealed |
95
+ | **Sealed names** | `Bun.dns.lookup`, `dns.lookup` and `dns.promises.lookup` ask the same gate: a host a `mockFetch` route names resolves to `MOCKED_HOST_ADDRESS` (`11.11.11.11`, public, so an SSRF screen such as `screenDial` passes it and the dial it pins still meets the mock by its `Host`); this machine, an address literal and an `allowHost` name resolve for real; offline refuses every name (`X_TEST_NETWORK_OFFLINE`); any other name is `X_TEST_NETWORK_SEALED`. A RegExp route names a host it matches at the origin or spells in its source. Not covered: `lookup` bound by a named ESM import (`import { lookup } from 'node:dns'`) before the seal, and `dns.resolve*` |
95
96
  | **Fixed timezone + locale** | `UTC` and `en-US` unless a test declares otherwise; a tz-dependent bug fails deterministically |
96
97
  | **Ordered concurrency** | job workers in tests run deterministically; `runJobs()` drains the queue synchronously |
97
98
  | **Per-test reset** | before EVERY test, not every file, the preload puts the jobs event bus back (`installPerTestReset()`): an answer one test published never resumes the next test's waiting run, with or without `runJobs`. A test that never loaded `@ultimat3/jobs` pays nothing. `As of 2026-10` |
@@ -1001,7 +1002,7 @@ shape, same unreached code. `As of 2026-11`.
1001
1002
  | Overrides | `apps/web/exercise.ts`: `export const exercise = defineExercise({ publishPost: { actor, input }, sendInvoice: { off: '<why>' } })`. Each value is `.contract({ exercise })`'s option. An unknown name is `X_DECLARATION_UNKNOWN`; a blank `off` is `X_CONTRACT_EXERCISE_UNDECLARED` |
1002
1003
  | A handler that calls a vendor | `defineExercise({ … }, { setup: () => { mockFetch('https://api.vendor.test/*', handler); } })` — or `setup: () => cassette(import.meta.dir, 'exercise')`. Runs once in the exercise process, after the seal and before the first row; what it returns is disposed after the pass. A call a setup route answers is reached, not refused. `allowHost` in it is `X_EXERCISE_SETUP_UNSEALED` |
1003
1004
  | Rows a generated value cannot satisfy | a cross-column `c.satisfies(…)` reads `X_SEED_GRAPH_UNSATISFIED`: `defineExercise({ … }, { factories: { bosses: defineFactory(bosses, { defaults: (i) => ({ … }) }) } })`, keyed by entity name, the graph's keys kept. A column that follows from a key or reference the graph picked: `derive: (row) => ({ scopeKey: … })` beside `build`/`reset`, reading `row.ownerOrgId`. A partial unique whose columns the factory builds is the database's to judge. An unknown name is `X_DECLARATION_UNKNOWN` |
1004
- | Report | `.x/exercise.json` and `--json`: `{ seed, counts, records[] }`, each record `{ kind, name, outcome, code?, reason?, statements, effects, ms, override?, fix?, tenant?, crash? }` — `fix` where no override reaches it. The fields before `tenant` are A's call. The human table's `tenant` and `crash` columns are the verdicts, `-` where none ran |
1005
+ | Report | `.x/exercise.json` and `--json`: `{ seed, counts, records[] }`, each record `{ kind, name, outcome, code?, reason?, defect?, statements, effects, ms, override?, fix?, tenant?, crash? }` — `fix` where no override reaches it; `defect` on a 5xx: `{ cause, statement?, fields? }`, the error's own cause (a value the input held under a credential key or a `.sensitive()` field masked `[redacted]`), the SQL a database refusal names and the paths a validation failure names, all carried into the `X_CONTRACT_EXERCISE_UNREACHED` finding. The fields before `tenant` are A's call. The human table's `tenant` and `crash` columns are the verdicts, `-` where none ran |
1005
1006
  | Gate | the `exercise` step, after `job`, runs `x exercise --json` as a child and is red on its findings: `X_CONTRACT_EXERCISE_UNREACHED`, `X_TENANT_LEAK`, `X_TENANT_WRITE_CROSSED`, `X_JOB_CRASH_DIVERGED`, and — on a whole pass, not `x exercise <name>` — `X_ENTITY_TENANT_UNDECLARED`. `unreached` is never sampled or skipped: it is a finding whose `fix:` is the entry to paste |
1006
1007
 
1007
1008
  ```bash
@@ -1063,7 +1064,7 @@ actor, after the tenant proof. Source: `packages/testing/src/exercise-crash.ts`,
1063
1064
 
1064
1065
  | `crash.verdict` | When | Red |
1065
1066
  |---|---|---|
1066
- | `diverged` | an effect made more often by a killed run: `findings[]` of `{ boundary, mode, effect, clean, killed, after? }` | yes: `X_JOB_CRASH_DIVERGED`, one per effect and the step it follows, every boundary named |
1067
+ | `diverged` | an effect made more often by a killed run: `findings[]` of `{ boundary, mode, effect, clean, killed, after?, inside? }` — `inside` the step whose body made it (`@ultimat3/jobs`' `currentStep()`), `after` the last step completed before it. An effect inside a step that did not complete, made FEWER times by a kill that spent one of its attempts, is not a divergence | yes: `X_JOB_CRASH_DIVERGED`, one per effect and place, every boundary named. Inside a step the fix keys its call on `${jobId}:<step>`; outside every step it wraps it in `step.run` |
1067
1068
  | `held` | otherwise; `boundaries` and `reruns` (lost answers — at-least-once, never red) counted | no |
1068
1069
  | `unproven` | the proof itself threw: `reason` | no |
1069
1070