@smthrs/control 1.0.0-rc.3 → 1.0.0-rc.4

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.
@@ -3,3 +3,5 @@
3
3
  The default unit suite needs no PostgreSQL server. Set `SMITHERS_TEST_PG_URL` to run `test/SqlControlRuntimePostgres.test.ts` against a dedicated test database.
4
4
 
5
5
  `//packages/smithers/control:postgresInventory` runs the same assertions on Linux with the `adapterPostgresDatabase` service and loopback networking. It checks filtered inventory pagination, duplicate and absent IDs, empty filters, large ID sets, and time boundaries.
6
+
7
+ The package `test` target runs the suite twice, on SQLite and on a real PostgreSQL server, and merges the coverage before it checks the 100% floors. The PostgreSQL pass runs this file, so the PostgreSQL-only inventory filter counts toward coverage. Run the same matrix from the package directory with `pnpm run test:matrix`.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@smthrs/control",
3
3
  "type": "module",
4
- "version": "1.0.0-rc.3",
4
+ "version": "1.0.0-rc.4",
5
5
  "license": "MIT",
6
6
  "smthrs": {
7
7
  "group": "agent"
@@ -356,27 +356,27 @@
356
356
  "tag": "next"
357
357
  },
358
358
  "dependencies": {
359
- "@smthrs/model": "1.0.0-rc.3",
360
- "@smthrs/canonical": "1.0.0-rc.3",
361
- "@smthrs/crypto": "1.0.0-rc.3",
362
- "@smthrs/database": "1.0.0-rc.3",
363
- "@smthrs/journal": "1.0.0-rc.3",
364
- "@smthrs/notifications": "1.0.0-rc.3",
365
- "@smthrs/plan": "1.0.0-rc.3",
366
- "@smthrs/registry": "1.0.0-rc.3",
367
- "@smthrs/run-store": "1.0.0-rc.3",
368
- "@smthrs/flow": "1.0.0-rc.3"
359
+ "@smthrs/model": "1.0.0-rc.4",
360
+ "@smthrs/canonical": "1.0.0-rc.4",
361
+ "@smthrs/crypto": "1.0.0-rc.4",
362
+ "@smthrs/database": "1.0.0-rc.4",
363
+ "@smthrs/journal": "1.0.0-rc.4",
364
+ "@smthrs/notifications": "1.0.0-rc.4",
365
+ "@smthrs/plan": "1.0.0-rc.4",
366
+ "@smthrs/registry": "1.0.0-rc.4",
367
+ "@smthrs/run-store": "1.0.0-rc.4",
368
+ "@smthrs/flow": "1.0.0-rc.4"
369
369
  },
370
370
  "devDependencies": {
371
371
  "@effect/language-service": "0.87.2",
372
372
  "@effect/vitest": "4.0.0-rc.115",
373
373
  "@eslint/js": "9.39.5",
374
- "@smthrs/core": "1.0.0-rc.3",
375
- "@smthrs/engine-store": "1.0.0-rc.3",
376
- "@smthrs/jj": "1.0.0-rc.3",
377
- "@smthrs/plan-store": "1.0.0-rc.3",
378
- "@smthrs/step-cache": "1.0.0-rc.3",
379
- "@smthrs/time-travel": "1.0.0-rc.3",
374
+ "@smthrs/core": "1.0.0-rc.4",
375
+ "@smthrs/engine-store": "1.0.0-rc.4",
376
+ "@smthrs/jj": "1.0.0-rc.4",
377
+ "@smthrs/plan-store": "1.0.0-rc.4",
378
+ "@smthrs/step-cache": "1.0.0-rc.4",
379
+ "@smthrs/time-travel": "1.0.0-rc.4",
380
380
  "@types/node": "26.4.1",
381
381
  "@vitest/coverage-v8": "5.0.0",
382
382
  "dprint": "0.57.1",
@@ -207,7 +207,11 @@ const AttributedResumeInput = Schema.Struct({
207
207
  principal: Schema.optional(Principal)
208
208
  })
209
209
  const AttributedRunInput = Schema.Union([
210
- Schema.Struct({ ...RunInputSchema.members[0].fields, principal: Schema.optional(Principal), reservedRunId: Schema.optional(Schema.NonEmptyString) }),
210
+ Schema.Struct({
211
+ ...RunInputSchema.members[0].fields,
212
+ principal: Schema.optional(Principal),
213
+ reservedRunId: Schema.optional(Schema.NonEmptyString)
214
+ }),
211
215
  Schema.Struct({ ...RunInputSchema.members[1].fields, principal: Schema.optional(Principal) })
212
216
  ])
213
217
  const AttributedSignalInput = Schema.Struct({
@@ -995,12 +999,16 @@ export const layer: Layer.Layer<
995
999
  // A detached live host keeps its fence. Delegate the admitted event
996
1000
  // wake to it, just as a node decision does, instead of leaving an idle
997
1001
  // retained module with input it will never get a boundary to drain.
998
- Effect.catchTag("/control/ClaimLost", (refusal) => refusal.parkedBy === undefined ? Effect.void : Effect.gen(function*() {
999
- const delegated = yield* runtime.requestResume(run.runId).pipe(
1000
- Effect.catchTag("/control/InvalidInput", () => Effect.succeed(undefined))
1001
- )
1002
- if (delegated !== undefined) yield* emit(run.runId, "control.run.resumed", { runId: run.runId })
1003
- })),
1002
+ Effect.catchTag(
1003
+ "/control/ClaimLost",
1004
+ (refusal) =>
1005
+ refusal.parkedBy === undefined ? Effect.void : Effect.gen(function*() {
1006
+ const delegated = yield* runtime.requestResume(run.runId).pipe(
1007
+ Effect.catchTag("/control/InvalidInput", () => Effect.succeed(undefined))
1008
+ )
1009
+ if (delegated !== undefined) yield* emit(run.runId, "control.run.resumed", { runId: run.runId })
1010
+ })
1011
+ ),
1004
1012
  Effect.catchTag("/control/RunNotFound", () => Effect.void),
1005
1013
  Effect.catchTag(
1006
1014
  "/control/CodeDrift",
@@ -1763,7 +1771,13 @@ export const layer: Layer.Layer<
1763
1771
  principal,
1764
1772
  fingerprint("run", principal, input),
1765
1773
  Effect.gen(function*() {
1766
- const launched = yield* runtime.launch(input.planId, input.digest, input.envelope, principal, input.reservedRunId)
1774
+ const launched = yield* runtime.launch(
1775
+ input.planId,
1776
+ input.digest,
1777
+ input.envelope,
1778
+ principal,
1779
+ input.reservedRunId
1780
+ )
1767
1781
  if (launched._tag === "Parked") {
1768
1782
  return { ...launched.receipt, receiptId: input.idempotencyKey }
1769
1783
  }
@@ -1182,73 +1182,77 @@ export const layerMemory = (options: MemoryOptions = {}): Layer.Layer<ControlRun
1182
1182
  }
1183
1183
  }
1184
1184
  ),
1185
- launch: Effect.fn("ControlRuntime.launch")(function*(planId, requestedDigest, envelope, principal, reservedRunId) {
1186
- const plan = yield* Effect.fromOption(
1187
- Option.fromNullishOr(plans.get(planId)),
1188
- () => new PlanNotFound({ planId })
1189
- )
1190
- if (plan.card.digest !== requestedDigest) {
1191
- return yield* new PlanDigestMismatch({
1192
- planId,
1193
- expected: plan.card.digest,
1194
- actual: requestedDigest
1195
- })
1196
- }
1197
- if (!sameEnvelope(plan.card.envelope, envelope)) {
1198
- return yield* new EnvelopeMismatch({
1185
+ launch: Effect.fn("ControlRuntime.launch")(
1186
+ function*(planId, requestedDigest, envelope, principal, reservedRunId) {
1187
+ const plan = yield* Effect.fromOption(
1188
+ Option.fromNullishOr(plans.get(planId)),
1189
+ () => new PlanNotFound({ planId })
1190
+ )
1191
+ if (plan.card.digest !== requestedDigest) {
1192
+ return yield* new PlanDigestMismatch({
1193
+ planId,
1194
+ expected: plan.card.digest,
1195
+ actual: requestedDigest
1196
+ })
1197
+ }
1198
+ if (!sameEnvelope(plan.card.envelope, envelope)) {
1199
+ return yield* new EnvelopeMismatch({
1200
+ planId,
1201
+ expected: canonical(plan.card.envelope),
1202
+ actual: canonical(envelope)
1203
+ })
1204
+ }
1205
+ if (plan.decision === "pending") {
1206
+ return {
1207
+ _tag: "Parked",
1208
+ receipt: {
1209
+ _tag: "Parked",
1210
+ receiptId: `launch:${planId}`,
1211
+ planId,
1212
+ status: "waiting-approval"
1213
+ }
1214
+ }
1215
+ }
1216
+ if (plan.decision !== "approved") {
1217
+ return yield* new PlanDenied({ planId })
1218
+ }
1219
+ const sequence = ++runSequence
1220
+ const runId = reservedRunId ?? `run-${sequence}`
1221
+ if (runs.has(runId)) {
1222
+ return yield* new PersistenceError({ operation: "reserve a run", message: "Run identity already exists" })
1223
+ }
1224
+ const fence = `fence-${++fenceSequence}`
1225
+ const timestamp = now()
1226
+ const summary: RunSummary = {
1227
+ runId,
1228
+ flowId: plan.card.flowId,
1229
+ status: "accepted",
1199
1230
  planId,
1200
- expected: canonical(plan.card.envelope),
1201
- actual: canonical(envelope)
1231
+ planDigest: plan.card.digest,
1232
+ ...(plan.card.executionDigest === undefined ? {} : { executionDigest: plan.card.executionDigest }),
1233
+ ...(options.engineVersion === undefined ? {} : { engineVersion: options.engineVersion }),
1234
+ ownerId: "memory-owner",
1235
+ ...(principal === undefined ? {} : { launchedBy: { id: principal.id, kind: principal.kind } }),
1236
+ ...(plan.card.envelope.budget.deadline === undefined
1237
+ ? {}
1238
+ : { deadlineAt: timestamp + plan.card.envelope.budget.deadline }),
1239
+ createdAt: timestamp,
1240
+ updatedAt: timestamp
1241
+ }
1242
+ runs.set(runId, {
1243
+ summary: snapshot(summary),
1244
+ fence,
1245
+ localFence: fence,
1246
+ sequence: runSequence,
1247
+ signals: []
1202
1248
  })
1203
- }
1204
- if (plan.decision === "pending") {
1205
1249
  return {
1206
- _tag: "Parked",
1207
- receipt: {
1208
- _tag: "Parked",
1209
- receiptId: `launch:${planId}`,
1210
- planId,
1211
- status: "waiting-approval"
1212
- }
1250
+ _tag: "Started",
1251
+ receipt: accepted(`launch:${planId}:${runId}`, runId),
1252
+ run: snapshot(summary)
1213
1253
  }
1214
1254
  }
1215
- if (plan.decision !== "approved") {
1216
- return yield* new PlanDenied({ planId })
1217
- }
1218
- const sequence = ++runSequence
1219
- const runId = reservedRunId ?? `run-${sequence}`
1220
- if (runs.has(runId)) return yield* new PersistenceError({ operation: "reserve a run", message: "Run identity already exists" })
1221
- const fence = `fence-${++fenceSequence}`
1222
- const timestamp = now()
1223
- const summary: RunSummary = {
1224
- runId,
1225
- flowId: plan.card.flowId,
1226
- status: "accepted",
1227
- planId,
1228
- planDigest: plan.card.digest,
1229
- ...(plan.card.executionDigest === undefined ? {} : { executionDigest: plan.card.executionDigest }),
1230
- ...(options.engineVersion === undefined ? {} : { engineVersion: options.engineVersion }),
1231
- ownerId: "memory-owner",
1232
- ...(principal === undefined ? {} : { launchedBy: { id: principal.id, kind: principal.kind } }),
1233
- ...(plan.card.envelope.budget.deadline === undefined
1234
- ? {}
1235
- : { deadlineAt: timestamp + plan.card.envelope.budget.deadline }),
1236
- createdAt: timestamp,
1237
- updatedAt: timestamp
1238
- }
1239
- runs.set(runId, {
1240
- summary: snapshot(summary),
1241
- fence,
1242
- localFence: fence,
1243
- sequence: runSequence,
1244
- signals: []
1245
- })
1246
- return {
1247
- _tag: "Started",
1248
- receipt: accepted(`launch:${planId}:${runId}`, runId),
1249
- run: snapshot(summary)
1250
- }
1251
- }),
1255
+ ),
1252
1256
  getRun: Effect.fn("ControlRuntime.getRun")((runId) =>
1253
1257
  Effect.map(requireRun(runId), (run) => snapshot(run.summary))
1254
1258
  ),
@@ -692,7 +692,10 @@ const makeRuntime = (
692
692
  // so the walk stops at one rather than telling a reader that a run
693
693
  // which can proceed cannot.
694
694
  ...(pendingWaits === undefined ? {} : { pendingWaits }),
695
- ...(pendingWaits === undefined || !pendingWaits.some((wait) => wait.reason === ControlExecutor.humanWaitReason) || terminal(base.status)
695
+ ...(pendingWaits === undefined || !pendingWaits.some((wait) =>
696
+ wait.reason === ControlExecutor.humanWaitReason
697
+ ) ||
698
+ terminal(base.status)
696
699
  ? {}
697
700
  : { status: "waiting-approval" as const }),
698
701
  ...(pendingResume === undefined ? {} : { pendingResume }),
@@ -1393,7 +1396,6 @@ const makeRuntime = (
1393
1396
  const ids = JSON.stringify([...new Set(filters.runIds)])
1394
1397
  conditions.push(
1395
1398
  sql.onDialectOrElse({
1396
- /* v8 ignore next -- PostgreSQL adapter; covered by //packages/smithers/control:postgresInventory */
1397
1399
  pg: () => sql`runs.run_id IN (SELECT jsonb_array_elements_text(${ids}::jsonb))`,
1398
1400
  orElse: () => sql`runs.run_id IN (SELECT value FROM json_each(${ids}))`
1399
1401
  })