@knpkv/herdr-work 0.7.2 → 0.9.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/dist/store.d.ts CHANGED
@@ -2,7 +2,7 @@ import { Crypto, Effect, Option, Schema } from "effect";
2
2
  import { WorkAdmissionConflictError, WorkAgentBindingAuthorityError, WorkAgentBindingConflictError, WorkCheckpointConflictError, WorkCoordinatorHandoffConflictError, WorkDecisionAuthorityConflictError, WorkDecisionHandoffConflictError, WorkDecisionRevisionConflictError, WorkGoalAbandonmentConflictError, WorkGoalAgentTargetConflictError, WorkGoalBindingRequiresAgentError, WorkGoalLaneActiveError, WorkGoalOwnerMismatchError, WorkGoalReassignmentConflictError, WorkGoalRevisionConflictError, WorkGoalTerminalError, WorkLaneClaimConflictError, WorkLaneGoalConflictError, WorkLaneOperationConflictError, WorkProjectionError, WorkPullRequestLinkError, WorkStoreError, WorkTransactionConflictError } from "./errors.js";
3
3
  import { workAgentBindingMaximumSnapshotBytes } from "./internal/agent-binding-admission.js";
4
4
  import { WorkAdmissionTarget, WorkAgentBinding, WorkAgentBindingRequest, WorkDecisionHandoff, WorkGoalAbandoned, WorkGoalCheckpoint, WorkGoalReassigned, WorkLaneClaim, WorkLaneClaimed, WorkObservationEnvelope, WorkPullRequestLink, WorkReconcileOptions, WorkRecoveryTarget } from "./model.js";
5
- import type { WorkActivity as WorkActivityType, WorkAdmissionPreflight as WorkAdmissionPreflightType, WorkAdmissionTarget as WorkAdmissionTargetType, WorkAgentBinding as WorkAgentBindingType, WorkAgentBindingRequest as WorkAgentBindingRequestType, WorkExistingGoalRecovery as WorkExistingGoalRecoveryType, WorkGoalAbandoned as WorkGoalAbandonedType, WorkGoalAbandonment as WorkGoalAbandonmentType, WorkGoalCheckpoint as WorkGoalCheckpointType, WorkGoalReassigned as WorkGoalReassignedType, WorkGoalReassignment as WorkGoalReassignmentType, WorkObservationEnvelope as WorkObservationEnvelopeType, WorkObservedAdmission as WorkObservedAdmissionType, WorkObservedFact as WorkObservedFactType, WorkObservedFailure as WorkObservedFailureType, WorkObserveReport, WorkProspectiveAdmission as WorkProspectiveAdmissionType, WorkPullRequestLink as WorkPullRequestLinkType, WorkReconcileOutcome, WorkRecoveryPreflight as WorkRecoveryPreflightType, WorkRecoveryTarget as WorkRecoveryTargetType } from "./model.js";
5
+ import type { WorkActivity as WorkActivityType, WorkAdmissionPreflight as WorkAdmissionPreflightType, WorkAdmissionTarget as WorkAdmissionTargetType, WorkAgentBinding as WorkAgentBindingType, WorkAgentBindingRequest as WorkAgentBindingRequestType, WorkExistingGoalRecovery as WorkExistingGoalRecoveryType, WorkGoalAbandoned as WorkGoalAbandonedType, WorkGoalAbandonment as WorkGoalAbandonmentType, WorkGoalCheckpoint as WorkGoalCheckpointType, WorkGoalReassigned as WorkGoalReassignedType, WorkGoalReassignment as WorkGoalReassignmentType, WorkObservationEnvelope as WorkObservationEnvelopeType, WorkObservedAdmission as WorkObservedAdmissionType, WorkObservedFact as WorkObservedFactType, WorkObservedFailure as WorkObservedFailureType, WorkObserveReport, WorkProspectiveAdmission as WorkProspectiveAdmissionType, WorkPullRequestLink as WorkPullRequestLinkType, WorkReconcileOutcome, WorkReconcilePlanStep, WorkRecoveryPreflight as WorkRecoveryPreflightType, WorkRecoveryTarget as WorkRecoveryTargetType } from "./model.js";
6
6
  import { type WorkApprovedActivity } from "./observed.js";
7
7
  type ReassignRejection = WorkGoalAgentTargetConflictError | WorkGoalBindingRequiresAgentError | WorkGoalOwnerMismatchError | WorkGoalReassignmentConflictError | WorkGoalRevisionConflictError | WorkProjectionError | WorkStoreError;
8
8
  type AbandonRejection = WorkGoalAbandonmentConflictError | WorkGoalLaneActiveError | WorkGoalOwnerMismatchError | WorkGoalRevisionConflictError | WorkGoalTerminalError | WorkProjectionError | WorkStoreError;
@@ -44,6 +44,8 @@ export interface WorkStoreService {
44
44
  * facts are ever written to goal history; everything else stays an overlay.
45
45
  */
46
46
  readonly reconcile: (options: WorkReconcileOptions) => Effect.Effect<ReadonlyArray<WorkReconcileOutcome>, WorkCheckpointConflictError | WorkProjectionError | WorkStoreError>;
47
+ /** What `reconcile` would do now, running its checks and writing nothing. */
48
+ readonly planReconcile: (options: WorkReconcileOptions) => Effect.Effect<ReadonlyArray<WorkReconcilePlanStep>, WorkCheckpointConflictError | WorkProjectionError | WorkStoreError>;
47
49
  /** Atomically reads projection history, observed facts, and the coordinator-owned logical-time boundary. */
48
50
  readonly snapshotInput: () => Effect.Effect<{
49
51
  readonly events: ReadonlyArray<WorkGoalCheckpointType>;
@@ -1055,6 +1057,11 @@ export declare class WorkStore implements WorkStoreService {
1055
1057
  * succeeds), so a writer that planned from the head cannot bury a newer
1056
1058
  * owner checkpoint.
1057
1059
  */
1060
+ /**
1061
+ * Appends one checkpoint. With `mode` `check`, every check runs in the same
1062
+ * transaction and it is rolled back instead of written: the checkpoint is
1063
+ * returned when it would have been appended.
1064
+ */
1058
1065
  private readonly appendAt;
1059
1066
  readonly appendMany: (this: WorkStore, transactionId: string, events: readonly WorkGoalCheckpoint[]) => Effect.Effect<{
1060
1067
  readonly version: "herdr.work.event.v1";
@@ -1326,6 +1333,11 @@ export declare class WorkStore implements WorkStoreService {
1326
1333
  readonly goalId: string;
1327
1334
  }[];
1328
1335
  }, WorkStoreError, never>;
1336
+ /**
1337
+ * The steps `reconcile` takes, shared by `reconcile` (`write`) and
1338
+ * `planReconcile` (`check`, which runs every check and writes nothing).
1339
+ */
1340
+ private readonly reconcileSteps;
1329
1341
  readonly reconcile: (this: WorkStore, request: WorkReconcileOptions) => Effect.Effect<({
1330
1342
  readonly _tag: "applied";
1331
1343
  readonly goalId: string;
@@ -1339,6 +1351,30 @@ export declare class WorkStore implements WorkStoreService {
1339
1351
  readonly goalId: string;
1340
1352
  readonly eventId: string;
1341
1353
  })[], WorkCheckpointConflictError | WorkProjectionError | WorkStoreError, never>;
1354
+ /**
1355
+ * What `reconcile` would do now with the same confirmations, writing
1356
+ * nothing: every check it makes before writing runs, each in a transaction
1357
+ * that is rolled back at once, with each step checked against the
1358
+ * checkpoints earlier steps planned.
1359
+ */
1360
+ readonly planReconcile: (this: WorkStore, request: WorkReconcileOptions) => Effect.Effect<({
1361
+ readonly _tag: "conflict";
1362
+ readonly goalId: string;
1363
+ readonly reason: "checkpoint" | "revision";
1364
+ } | {
1365
+ readonly _tag: "recorded";
1366
+ readonly goalId: string;
1367
+ readonly eventId: string;
1368
+ } | {
1369
+ readonly _tag: "would_apply";
1370
+ readonly goalId: string;
1371
+ readonly eventId: string;
1372
+ readonly state: "abandoned" | "completed";
1373
+ readonly subject: string;
1374
+ readonly observationId: string & import("effect/Brand").Brand<"WorkObservationId">;
1375
+ readonly goalEventId: string;
1376
+ readonly goalUpdatedAt: number;
1377
+ })[], WorkCheckpointConflictError | WorkProjectionError | WorkStoreError, never>;
1342
1378
  readonly observe: (this: WorkStore, envelopes: readonly WorkObservationEnvelope[]) => Effect.Effect<WorkObserveReport, WorkStoreError, never>;
1343
1379
  private secureFiles;
1344
1380
  close(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
package/dist/store.js CHANGED
@@ -2053,7 +2053,7 @@ export class WorkStore {
2053
2053
  {
2054
2054
  id: jobId,
2055
2055
  kind: "status",
2056
- summary: workReassignActivitySummary(decoded, jobId, decoded.approvalHash),
2056
+ summary: workReassignActivitySummary(decoded),
2057
2057
  occurredAt: at
2058
2058
  }
2059
2059
  ],
@@ -2284,7 +2284,7 @@ export class WorkStore {
2284
2284
  {
2285
2285
  id: jobId,
2286
2286
  kind: "status",
2287
- summary: workAbandonActivitySummary(decoded, jobId, decoded.approvalHash),
2287
+ summary: workAbandonActivitySummary(decoded),
2288
2288
  occurredAt: at
2289
2289
  }
2290
2290
  ],
@@ -2812,7 +2812,15 @@ export class WorkStore {
2812
2812
  * succeeds), so a writer that planned from the head cannot bury a newer
2813
2813
  * owner checkpoint.
2814
2814
  */
2815
- appendAt = Effect.fn("WorkStore.append")(function* (event, guard) {
2815
+ /**
2816
+ * Appends one checkpoint. With `mode` `check`, every check runs in the same
2817
+ * transaction and it is rolled back instead of written: the checkpoint is
2818
+ * returned when it would have been appended.
2819
+ */
2820
+ appendAt = Effect.fn("WorkStore.append")(function* (event, guard, mode = "write",
2821
+ // In a check, the checkpoints earlier steps of the same plan would have
2822
+ // written: limits are checked as if they were already stored.
2823
+ planned = []) {
2816
2824
  const decoded = yield* Schema.decodeUnknownEffect(WorkGoalCheckpoint)(event).pipe(Effect.mapError(storeError("append.decode")));
2817
2825
  // The reconciler's event and activity ids are its provenance; no other
2818
2826
  // writer may use them.
@@ -2827,11 +2835,12 @@ export class WorkStore {
2827
2835
  const decision = yield* Effect.try({
2828
2836
  try: () => {
2829
2837
  let transaction = false;
2838
+ const abort = () => this.#database.exec("ROLLBACK");
2830
2839
  try {
2831
2840
  this.#database.exec("BEGIN IMMEDIATE");
2832
2841
  transaction = true;
2833
2842
  const reject = (error) => {
2834
- this.#database.exec("ROLLBACK");
2843
+ abort();
2835
2844
  transaction = false;
2836
2845
  return { _tag: "rejected", error };
2837
2846
  };
@@ -2840,7 +2849,7 @@ export class WorkStore {
2840
2849
  WHERE event_id = ? OR (goal_id = ? AND occurred_at = ?)`)
2841
2850
  .all(decoded.eventId, decoded.goal.id, decoded.occurredAt)).map(({ record }) => Schema.decodeUnknownSync(WorkGoalCheckpoint)(JSON.parse(record)));
2842
2851
  if (collisions.length > 0 && collisions.every((existing) => Equal.equals(existing, decoded))) {
2843
- this.#database.exec("ROLLBACK");
2852
+ abort();
2844
2853
  transaction = false;
2845
2854
  return { _tag: "replayed", event: decoded };
2846
2855
  }
@@ -2868,7 +2877,7 @@ export class WorkStore {
2868
2877
  }));
2869
2878
  }
2870
2879
  const count = Schema.decodeUnknownSync(CountRow)(this.#database.prepare("SELECT COUNT(*) AS count FROM work_goal_events").get()).count;
2871
- if (count + 1 > workHistoryMaxEvents - guard.reserve) {
2880
+ if (count + planned.length + 1 > workHistoryMaxEvents - guard.reserve) {
2872
2881
  return reject(new WorkProjectionError({
2873
2882
  cause: count,
2874
2883
  detail: `the reconciler leaves ${guard.reserve} of ${workHistoryMaxEvents} checkpoints free`,
@@ -2884,14 +2893,15 @@ export class WorkStore {
2884
2893
  }));
2885
2894
  }
2886
2895
  const eventCount = Schema.decodeUnknownSync(CountRow)(this.#database.prepare("SELECT COUNT(*) AS count FROM work_goal_events").get()).count;
2887
- if (eventCount >= workHistoryMaxEvents) {
2896
+ if (eventCount + planned.length >= workHistoryMaxEvents) {
2888
2897
  return reject(new WorkProjectionError({
2889
2898
  cause: decoded,
2890
2899
  detail: `work history cannot exceed ${workHistoryMaxEvents} checkpoints`,
2891
2900
  reason: "capacity_exceeded"
2892
2901
  }));
2893
2902
  }
2894
- const history = Schema.decodeUnknownSync(StoredEventRows)(this.#database.prepare("SELECT record FROM work_goal_events").all()).map(({ record }) => Schema.decodeUnknownSync(WorkGoalCheckpoint)(JSON.parse(record)));
2903
+ const history = Schema.decodeUnknownSync(StoredEventRows)(this.#database.prepare("SELECT record FROM work_goal_events").all()).map(({ record }) => Schema.decodeUnknownSync(WorkGoalCheckpoint)(JSON.parse(record)))
2904
+ .concat(planned);
2895
2905
  const familyError = validateGoalFamilyHistory([...history, decoded]);
2896
2906
  if (familyError !== undefined)
2897
2907
  return reject(familyError);
@@ -2930,6 +2940,11 @@ export class WorkStore {
2930
2940
  }));
2931
2941
  }
2932
2942
  }
2943
+ if (mode === "check") {
2944
+ abort();
2945
+ transaction = false;
2946
+ return { _tag: "checked" };
2947
+ }
2933
2948
  const result = this.#database.prepare("INSERT INTO work_goal_events (event_id, goal_id, occurred_at, record) VALUES (?, ?, ?, ?)").run(decoded.eventId, decoded.goal.id, decoded.occurredAt, JSON.stringify(decoded));
2934
2949
  // The reconciler's own record of what it wrote: its authorship and its
2935
2950
  // once-per-goal rule come from this table, never from an id's spelling.
@@ -2942,7 +2957,7 @@ export class WorkStore {
2942
2957
  }
2943
2958
  catch (error) {
2944
2959
  if (transaction)
2945
- this.#database.exec("ROLLBACK");
2960
+ abort();
2946
2961
  throw error;
2947
2962
  }
2948
2963
  },
@@ -2952,6 +2967,8 @@ export class WorkStore {
2952
2967
  return yield* decision.error;
2953
2968
  if (decision._tag === "replayed")
2954
2969
  return decision.event;
2970
+ if (decision._tag === "checked")
2971
+ return decoded;
2955
2972
  if (decision.changes !== 1 && decision.changes !== 1n) {
2956
2973
  return yield* storeError("append.insert.count")(decision.changes);
2957
2974
  }
@@ -4041,7 +4058,11 @@ export class WorkStore {
4041
4058
  reconcilerEvents
4042
4059
  };
4043
4060
  });
4044
- reconcile = Effect.fn("WorkStore.reconcile")(function* (request) {
4061
+ /**
4062
+ * The steps `reconcile` takes, shared by `reconcile` (`write`) and
4063
+ * `planReconcile` (`check`, which runs every check and writes nothing).
4064
+ */
4065
+ reconcileSteps = Effect.fn("WorkStore.reconcileSteps")(function* (request, mode) {
4045
4066
  const options = yield* Schema.decodeUnknownEffect(WorkReconcileOptions)(request).pipe(Effect.mapError(storeError("reconcile.options")));
4046
4067
  const source = yield* this.snapshotInput();
4047
4068
  if (workHistoryMaxEvents - source.events.length < workReconcilerHeadroom) {
@@ -4063,7 +4084,13 @@ export class WorkStore {
4063
4084
  const stamped = new Map(source.reconcilerEvents.map(({ eventId, goalId }) => [goalId, eventId]));
4064
4085
  const cryptoService = this.#cryptoService;
4065
4086
  const now = yield* Clock.currentTimeMillis;
4066
- const appendAt = (checkpoint, guard) => this.appendAt(checkpoint, guard);
4087
+ // A plan holds no transaction between steps: each check rolls back at once,
4088
+ // and later steps are checked against the checkpoints earlier ones planned.
4089
+ const planned = [];
4090
+ const appendAt = (checkpoint, guard) => this.appendAt(checkpoint, guard, mode, planned).pipe(Effect.tap(() => Effect.sync(() => {
4091
+ if (mode === "check")
4092
+ planned.push(checkpoint);
4093
+ })));
4067
4094
  return yield* Effect.forEach(terminalCandidates(source.events, source.facts, source.failures, new Set(options.confirmed.map(({ observationId, subject }) => `${subject}\u0000${observationId}`))), Effect.fnUntraced(function* (candidate) {
4068
4095
  const goalId = candidate.head.goal.id;
4069
4096
  const previous = stamped.get(goalId);
@@ -4076,7 +4103,7 @@ export class WorkStore {
4076
4103
  // holds the reconciler's id, a timestamp past the bound) is left for
4077
4104
  // its owner: reported as a conflict, never failing the other goals.
4078
4105
  if (Result.isFailure(checkpoint))
4079
- return { _tag: "conflict", goalId };
4106
+ return { _tag: "conflict", goalId, reason: "checkpoint" };
4080
4107
  return yield* appendAt(checkpoint.success, {
4081
4108
  fact: { observationId: candidate.fact.observationId, subject: candidate.fact.subject },
4082
4109
  head: candidate.head,
@@ -4085,10 +4112,40 @@ export class WorkStore {
4085
4112
  _tag: "applied",
4086
4113
  eventId,
4087
4114
  goalId,
4088
- state: candidate.pullRequest.state === "merged" ? "completed" : "abandoned"
4089
- }), Effect.catchTag("WorkGoalRevisionConflictError", () => Effect.succeed({ _tag: "conflict", goalId })));
4115
+ state: candidate.pullRequest.state === "merged" ? "completed" : "abandoned",
4116
+ candidate
4117
+ }), Effect.catchTag("WorkGoalRevisionConflictError", () => Effect.succeed({ _tag: "conflict", goalId, reason: "revision" })));
4090
4118
  }));
4091
4119
  });
4120
+ reconcile = Effect.fn("WorkStore.reconcile")(function* (request) {
4121
+ const steps = yield* this.reconcileSteps(request, "write");
4122
+ return steps.map((step) => step._tag === "applied"
4123
+ ? { _tag: "applied", eventId: step.eventId, goalId: step.goalId, state: step.state }
4124
+ : step._tag === "recorded"
4125
+ ? step
4126
+ : { _tag: "conflict", goalId: step.goalId });
4127
+ });
4128
+ /**
4129
+ * What `reconcile` would do now with the same confirmations, writing
4130
+ * nothing: every check it makes before writing runs, each in a transaction
4131
+ * that is rolled back at once, with each step checked against the
4132
+ * checkpoints earlier steps planned.
4133
+ */
4134
+ planReconcile = Effect.fn("WorkStore.planReconcile")(function* (request) {
4135
+ const steps = yield* this.reconcileSteps(request, "check");
4136
+ return steps.map((step) => step._tag === "applied"
4137
+ ? {
4138
+ _tag: "would_apply",
4139
+ eventId: step.eventId,
4140
+ goalId: step.goalId,
4141
+ state: step.state,
4142
+ subject: step.candidate.fact.subject,
4143
+ observationId: step.candidate.fact.observationId,
4144
+ goalEventId: step.candidate.head.eventId,
4145
+ goalUpdatedAt: step.candidate.head.goal.updatedAt
4146
+ }
4147
+ : step);
4148
+ });
4092
4149
  observe = Effect.fn("WorkStore.observe")(function* (envelopes) {
4093
4150
  const decoded = yield* Schema.decodeUnknownEffect(Schema.Array(WorkObservationEnvelope).check(Schema.isMaxLength(workObservedFactMaxRecords)))(envelopes).pipe(Effect.mapError(storeError("observe.decode")));
4094
4151
  const cryptoService = this.#cryptoService;