@mstar-harness/engine 3.9.3 → 3.10.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.
@@ -1,4 +1,5 @@
1
- import type { GateResult, ValidationResult } from "./core.js";
1
+ import { type GateResult, type ValidationResult } from "./core.js";
2
+ import { type SnapshotCoordination } from "./coordination-write.js";
2
3
  import { type IntegrationMergeLease } from "./lease.js";
3
4
  import { type PlanRow } from "./status.js";
4
5
  /** Snapshot file name inside `workflows/<id>/` ( — writer contract). */
@@ -9,6 +10,58 @@ export declare const WORKFLOW_LIFECYCLE_STATUSES: readonly ["running", "paused",
9
10
  export declare const WORKFLOW_TERMINAL_STATUSES: readonly ["completed", "failed", "stopped"];
10
11
  /** Lifecycle type enum ( — id reuses the orchestration id). */
11
12
  export declare const WORKFLOW_LIFECYCLE_TYPES: readonly ["plan", "iteration"];
13
+ /**
14
+ * Delivery kinds declared at registration (mstar-artifacts/references/plan-workflow-lifecycle-contract.md
15
+ * §1). The declared kind is recorded at registration and never inferred
16
+ * retroactively; `development` carries the full PR/merge delivery lifecycle,
17
+ * `verification/report-only` follows the explicit completion policy recorded
18
+ * alongside it.
19
+ */
20
+ export declare const WORKFLOW_DELIVERY_KINDS: readonly ["development", "verification/report-only"];
21
+ export type WorkflowDeliveryKind = (typeof WORKFLOW_DELIVERY_KINDS)[number];
22
+ /**
23
+ * Compound disposition outcomes (contract §4c): `created` / `updated` /
24
+ * reasoned `skipped`. The disposition is recorded on the workflow before the
25
+ * PR head is finalized, so the delivery evidence names the compound outcome
26
+ * it was taken from.
27
+ */
28
+ export declare const WORKFLOW_COMPOUND_OUTCOMES: readonly ["created", "updated", "skipped"];
29
+ export type WorkflowCompoundOutcome = (typeof WORKFLOW_COMPOUND_OUTCOMES)[number];
30
+ /**
31
+ * Delivery evidence recorded on the snapshot (contract §3 lifecycle stages,
32
+ * §4c/§4d/§4f, seam S3). Each member is recorded by its owner at its own
33
+ * stage through the authorized write seam (`recordWorkflowDelivery`), and the
34
+ * close consultation reads the block for the DECLARED delivery kind — never
35
+ * inferring a kind from which members happen to be present (§1):
36
+ *
37
+ * - `compound` — compound disposition (§4c), recorded before the PR head is
38
+ * finalized; `skipped` carries the mandatory reason;
39
+ * - `pr` — PR identity recorded at submission (§4d): repo/head/target. A
40
+ * local commit or a pre-existing unrelated PR does not satisfy it;
41
+ * - `merge` — the PM's verified-merge record (§4f): the provider evidence
42
+ * they checked. The engine NEVER verifies the remote merge itself;
43
+ * - `completion` — the fulfilment record of the `completion_policy` recorded
44
+ * at registration (§1) for `verification/report-only` workflows.
45
+ */
46
+ export type WorkflowDeliveryEvidence = {
47
+ compound?: {
48
+ outcome: WorkflowCompoundOutcome;
49
+ reason?: string;
50
+ };
51
+ pr?: {
52
+ repo: string;
53
+ head: string;
54
+ target: string;
55
+ };
56
+ merge?: {
57
+ provider: string;
58
+ evidence: string;
59
+ };
60
+ completion?: {
61
+ policy: string;
62
+ evidence: string;
63
+ };
64
+ };
12
65
  export type WorkflowLifecycleStatus = (typeof WORKFLOW_LIFECYCLE_STATUSES)[number];
13
66
  export type WorkflowLifecycleType = (typeof WORKFLOW_LIFECYCLE_TYPES)[number];
14
67
  /**
@@ -23,7 +76,20 @@ export type WorkflowExecutionPolicy = {
23
76
  };
24
77
  /** Iteration branch anchors ( — from root metadata anchors). */
25
78
  export type WorkflowBranchAnchors = {
79
+ /**
80
+ * Protected base anchor: the branch the lifecycle starts from (iteration
81
+ * `iteration_base_branch`). Cleanup Rule 2 never deletes it and L1 uses it
82
+ * as the explicit main-worktree residency fallback — it is NEVER a
83
+ * feature/working branch (`registerPlanWorkflow` records the plan's
84
+ * delivery branch under `source`).
85
+ */
26
86
  base?: string;
87
+ /**
88
+ * Source branch of a standalone `type: plan` delivery, recorded at
89
+ * registration (`--branch-source`). Semantically a delivery branch, not a
90
+ * protected base anchor: cleanup/L1 consumers keep reading `base`.
91
+ */
92
+ source?: string;
27
93
  integration?: string;
28
94
  target?: string;
29
95
  };
@@ -63,7 +129,38 @@ export type WorkflowSnapshot = {
63
129
  integration_worktree_path?: string;
64
130
  legacy_metadata?: Record<string, unknown>;
65
131
  compass_ref?: string;
132
+ /**
133
+ * Snapshot-level coordination block ( — scoped plan-PM coordination).
134
+ * Present only on a coordinated lifecycle: it carries the workflow's
135
+ * coordinator binding (session id + canonical envelope path). The block
136
+ * is validated strictly (`validateSnapshotCoordination`) and may only be
137
+ * changed by the locked coordination writer.
138
+ */
139
+ coordination?: SnapshotCoordination;
140
+ /**
141
+ * Delivery kind declared at registration (mstar-artifacts/references/plan-workflow-lifecycle-contract.md
142
+ * §1). Recorded by the registration producer; never inferred from runtime
143
+ * behavior or from the presence/absence of other fields.
144
+ */
145
+ delivery_kind?: WorkflowDeliveryKind;
146
+ /** Project register id recorded at registration (contract §3 register row). */
147
+ project?: string;
148
+ /**
149
+ * Explicit completion policy for `verification/report-only` workflows,
150
+ * recorded at registration (contract §1): names the evidence that completes
151
+ * the workflow (e.g. acceptance artifacts or the report location).
152
+ */
153
+ completion_policy?: string;
154
+ /**
155
+ * Delivery evidence collected over the lifecycle (contract §3/§4c/§4d/§4f,
156
+ * seam S3). Optional at the schema level — it is populated stage by stage
157
+ * through `recordWorkflowDelivery` and consulted by the close path (and the
158
+ * read-only phase-6 gate) for the declared `delivery_kind`.
159
+ */
160
+ delivery?: WorkflowDeliveryEvidence;
66
161
  };
162
+ /** Stable JSON for change detection (sorted keys, recursive). */
163
+ export declare function stableJson(value: unknown): string;
67
164
  /**
68
165
  * Validate a v3 workflow snapshot document ( — final schema):
69
166
  * enum/type/id checks, `schema_version: 1`, required timestamps, `plans[]`
@@ -114,8 +211,34 @@ export declare class WorkflowSnapshotValidationError extends Error {
114
211
  }
115
212
  export declare function readWorkflowSnapshot(dir: string): WorkflowSnapshotRead;
116
213
  /**
117
- * Write a workflow snapshot as a whole-rewrite of `dir/snapshot.json` under
118
- * `withStatusWriteLock(snapshotPath)` ( the `.status-write.lockdir`
214
+ * Writer contract (spec §C4). `expectedVersion` is the CAS token — the exact
215
+ * on-disk artifact version (`sha256:<64 hex>`), or `"absent"` for
216
+ * create-only. `createOnly` is the locked `absent` shorthand used by the
217
+ * scaffold/migrate/audit writers: an existing document (even an empty or
218
+ * malformed one) is never silently replaced.
219
+ *
220
+ * Omitting `expectedVersion` means create-only, NOT "replace whatever is
221
+ * there": there is no missing-version compatibility fallback, so an existing
222
+ * snapshot still refuses with `coordination.expected-version-required`.
223
+ *
224
+ * The delta allowed here is `phase` + `updated_at` and nothing else — a
225
+ * coordinator persists its phase projection through this writer without ever
226
+ * gaining a backdoor to row owners, leases, lifecycle scalars or branch
227
+ * anchors. Lifecycle terminal changes belong to `closeWorkflow` (spec §C4).
228
+ */
229
+ export type WriteWorkflowSnapshotOptions = {
230
+ expectedVersion?: string;
231
+ createOnly?: boolean;
232
+ /**
233
+ * Canonical coordinator session envelope path (spec §C4). Required when the
234
+ * stored snapshot is coordinated: only the snapshot's own bound coordinator
235
+ * may pass, and the `coordination` block itself is never part of the delta.
236
+ */
237
+ sessionPath?: string;
238
+ };
239
+ /**
240
+ * Write a workflow snapshot as a field-scoped update of `dir/snapshot.json`
241
+ * under `withStatusWriteLock(snapshotPath)` ( — the `.status-write.lockdir`
119
242
  * lands inside `workflows/<id>/`, dirname of the snapshot; no harness-root
120
243
  * pollution). The snapshot is validated first — an invalid snapshot throws
121
244
  * and nothing is written. `dir` is created recursively. The durable write
@@ -128,14 +251,262 @@ export declare function readWorkflowSnapshot(dir: string): WorkflowSnapshotRead;
128
251
  * whose target root differs from the active store's root MUST
129
252
  * `setArtifactStore(createFsStore(root))` first.
130
253
  */
131
- export declare function writeWorkflowSnapshot(snapshot: WorkflowSnapshot, dir: string): Promise<void>;
254
+ export declare function writeWorkflowSnapshot(snapshot: WorkflowSnapshot, dir: string, opts?: WriteWorkflowSnapshotOptions): Promise<void>;
132
255
  /** Terminal enum predicate only; callers validate document shape separately. */
133
256
  export declare function isTerminalSnapshot(doc: WorkflowSnapshot): boolean;
257
+ /** Delivery-registration inputs every producer declares (contract §1/§4a). */
258
+ export type DeliveryRegistrationEvidence = {
259
+ branchSource?: string;
260
+ branchTarget?: string;
261
+ completionPolicy?: string;
262
+ };
263
+ /**
264
+ * Per-kind registration-evidence coherence (contract §1) — the ONE rule shared
265
+ * by every producer that declares a delivery kind at registration time:
266
+ * `registerPlanWorkflow` (the normal-entry producer), `promoteAuditPlans`
267
+ * (audit promotion) and `migrateHarnessTree` (v1 lift), plus the one-time
268
+ * `declareWorkflowDeliveryKind` backfill for active kind-less snapshots.
269
+ * Lockstep here is the point: a `development` workflow declares BOTH delivery
270
+ * anchors and a `verification/report-only` workflow declares the completion
271
+ * policy that completes it — missing fields are incomplete registration, never
272
+ * an exemption, and a producer that drifted would otherwise mint an
273
+ * unclosable lifecycle. `what` prefixes the refusal (the caller's own name).
274
+ */
275
+ export declare function assertDeliveryRegistrationCoherence(kind: WorkflowDeliveryKind, evidence: DeliveryRegistrationEvidence, what: string): void;
276
+ /**
277
+ * Delivery-kind evidence consultation (seam S3 — contract §4g + §6 S3): the
278
+ * ONE implementation behind both the read-only Phase-6 gate
279
+ * (`evaluatePostMergeClose`) and the close write path (`closeWorkflow`), so
280
+ * the gate's verdict and the close's refusal can never drift apart. Pure,
281
+ * read-only, no writes; the input snapshot is consumed as read.
282
+ *
283
+ * Only `type: plan` lifecycles consult (an iteration declares no delivery
284
+ * kind — §1); WHEN the consultation runs is the caller's rule, and both
285
+ * callers scope it to a delivered lifecycle: `closeWorkflow` consults the
286
+ * running snapshot it is about to complete, and the Phase-6 gate consults a
287
+ * `completed` terminal snapshot. A `failed`/`stopped` close is therefore never
288
+ * demanded delivery evidence (§5). The DECLARED kind decides the required
289
+ * evidence; nothing is inferred from which fields happen to be present, and a
290
+ * missing field is incomplete registration, never an exemption (§1):
291
+ *
292
+ * - no registered `delivery_kind` → `PHASE6_DELIVERY_KIND_UNREGISTERED` (a
293
+ * legacy terminal snapshot cannot be backfilled: the register producer is
294
+ * create-only and preserves the terminal bytes);
295
+ * - `development` → the registered `branch.source`/`branch.target` plus the
296
+ * collected `delivery` evidence: compound disposition (§4c), PR identity
297
+ * (§4d) and the PM's verified-merge record (§4f — the engine never verifies
298
+ * the remote merge itself);
299
+ * - `verification/report-only` → the recorded `completion_policy` plus its
300
+ * fulfilment record, which must name that same policy (§1).
301
+ *
302
+ * Everything missing is named in one refusal (`PHASE6_DELIVERY_EVIDENCE_INCOMPLETE`)
303
+ * whose fix hint points at the authorized recording seam.
304
+ */
305
+ export declare function consultDeliveryEvidence(snapshot: WorkflowSnapshot): ValidationResult[];
134
306
  export type CloseWorkflowOptions = {
135
307
  endedAt: string;
308
+ /**
309
+ * Canonical coordinator session envelope path (spec §C4). Required when the
310
+ * stored snapshot is coordinated: the close writes the snapshot, so only the
311
+ * snapshot's own bound coordinator may pass. A missing/mismatched envelope
312
+ * refuses the close with `coordination.session-mismatch` before anything is
313
+ * written. Non-coordinated snapshots ignore it; an already-terminal snapshot
314
+ * is returned unchanged (no write, no authorization needed).
315
+ */
316
+ sessionPath?: string;
136
317
  };
137
318
  /**
138
319
  * Complete the latest snapshot under its write lock. Never releases leases.
139
- * A valid terminal snapshot is returned unchanged, including failed/stopped.
320
+ * A valid terminal snapshot is returned unchanged, including failed/stopped
321
+ * (idempotent preservation — nothing is rewritten, not even the timestamp).
322
+ * A coordinated snapshot is closed only by its own bound coordinator
323
+ * (spec §C4) — the same envelope seam as `writeWorkflowSnapshot` — so a plan
324
+ * actor or a bare CLI call can never complete a lifecycle it does not own.
325
+ *
326
+ * Before the terminal write the close consults the registered delivery
327
+ * kind's evidence through `consultDeliveryEvidence` — the SAME pure function
328
+ * the read-only Phase-6 gate runs (contract §4g/§6 S3), so the gate's verdict
329
+ * and this refusal can never disagree. An incomplete delivery (a
330
+ * `development` workflow without its compound disposition / PR identity /
331
+ * verified-merge record, a `verification/report-only` workflow without the
332
+ * fulfilment of its recorded completion policy) throws with every missing
333
+ * item named and ZERO writes: the snapshot stays `running` and the root entry
334
+ * stays registered, so the workflow remains resumable. The local close never
335
+ * verifies a remote merge (§4f keeps that as the PM's separate check) and
336
+ * never releases leases.
140
337
  */
141
338
  export declare function closeWorkflow(workflowId: string, dir: string, opts: CloseWorkflowOptions): Promise<WorkflowSnapshot>;
339
+ export type RecordWorkflowDeliveryOptions = {
340
+ /**
341
+ * Partial delivery-evidence patch: only the named members are merged into
342
+ * the stored block, so the compound disposition, the PR identity and the
343
+ * merge record can be recorded at their own lifecycle stages without
344
+ * rewriting each other. At least one member is required.
345
+ */
346
+ evidence: WorkflowDeliveryEvidence;
347
+ /**
348
+ * Canonical coordinator session envelope path (spec §C4) — the same
349
+ * authority seam `closeWorkflow` uses: a coordinated snapshot is written
350
+ * only by its own bound coordinator. Non-coordinated snapshots have no
351
+ * coordinator to bind and ignore it.
352
+ */
353
+ sessionPath?: string;
354
+ /** Recording timestamp (YYYY-MM-DD or RFC3339). Default: now. */
355
+ at?: string;
356
+ };
357
+ export type RecordWorkflowDeliveryResult = {
358
+ snapshot: WorkflowSnapshot;
359
+ /** `false` when the recorded evidence already matched disk — nothing was written. */
360
+ written: boolean;
361
+ };
362
+ /**
363
+ * Record (or extend) the delivery evidence on a `type: plan` workflow's
364
+ * snapshot, under the snapshot write lock: the close path's consultation is
365
+ * only as good as the evidence recorded here, so this is the seam that makes
366
+ * a `development` close possible at all.
367
+ *
368
+ * Refusals (before any write):
369
+ * - a terminal snapshot: delivery evidence is collected BEFORE the close, and
370
+ * a terminal lifecycle is never amended (§5 — no rewriting a closed
371
+ * lifecycle);
372
+ * - a lifecycle other than `type: plan`, or one without a registered
373
+ * `delivery_kind`: the evidence belongs to the declared kind (§1);
374
+ * - evidence the declared kind does not use (e.g. a completion record on a
375
+ * `development` workflow) — the declared kind is authoritative;
376
+ * - a rewrite of the recorded PR identity (§4d records it once at submission:
377
+ * an identical re-record is idempotent, a different pair is refused);
378
+ * - an empty patch or a malformed member: nothing is silently dropped.
379
+ *
380
+ * Idempotent and re-entrant: re-recording the exact stored evidence performs
381
+ * NO write and returns the snapshot as read (the timestamp is untouched), so
382
+ * a retried recording never produces a spurious revision. The write itself
383
+ * routes through the same protected-writer path as the close (the store's
384
+ * locked put inside the snapshot lock).
385
+ */
386
+ export declare function recordWorkflowDelivery(workflowId: string, dir: string, opts: RecordWorkflowDeliveryOptions): Promise<RecordWorkflowDeliveryResult>;
387
+ export type DeclareWorkflowDeliveryKindOptions = {
388
+ /** The declared kind (contract §1). Required — never inferred. */
389
+ deliveryKind: WorkflowDeliveryKind;
390
+ /** Delivery source branch, recorded as `branch.source`. Required for `development`. */
391
+ branchSource?: string;
392
+ /** Delivery target branch, recorded as `branch.target`. Required for `development`. */
393
+ branchTarget?: string;
394
+ /** Completion policy naming the evidence that completes the workflow. Required for `verification/report-only`. */
395
+ completionPolicy?: string;
396
+ /**
397
+ * Canonical coordinator session envelope path (spec §C4) — the same
398
+ * authority seam `closeWorkflow` and `recordWorkflowDelivery` use: a
399
+ * coordinated snapshot is written only by its own bound coordinator. An
400
+ * uncoordinated snapshot has no coordinator binding to authenticate (the
401
+ * historical audit-promotion / migrate population is exactly that), so it
402
+ * keeps the harness-owner stance the close already applies.
403
+ */
404
+ sessionPath?: string;
405
+ /** Declaration timestamp (YYYY-MM-DD or RFC3339). Default: now. */
406
+ at?: string;
407
+ };
408
+ /**
409
+ * Declare the delivery kind (and its per-kind registration evidence) of an
410
+ * ACTIVE `type: plan` snapshot whose producer declared none — the one-time
411
+ * upgrade seam for the historical population (contract §1/§4a). ONE-TIME by
412
+ * construction: the kind is registration evidence that is never inferred
413
+ * retroactively (§1), so a second declaration is refused even with the same
414
+ * value, and a terminal snapshot is refused outright (§5 — a closed lifecycle
415
+ * is never amended; the legacy terminal dead end keeps its documented
416
+ * owner-amendment path).
417
+ *
418
+ * The declaration carries the kind's own evidence through the shared
419
+ * `assertDeliveryRegistrationCoherence` rule, so it cannot mint an unclosable
420
+ * lifecycle (a `development` kind needs its delivery anchors, a
421
+ * `verification/report-only` kind its completion policy). A supplied delivery
422
+ * anchor either FILLS the missing one or restates the value the snapshot
423
+ * already registers; a contradicting value is refused, so the declaration can
424
+ * never re-point a lifecycle at another delivery. The write lands in the
425
+ * snapshot lock through the same protected writer as the close.
426
+ */
427
+ export declare function declareWorkflowDeliveryKind(workflowId: string, dir: string, opts: DeclareWorkflowDeliveryKindOptions): Promise<WorkflowSnapshot>;
428
+ /** Options for `registerPlanWorkflow`. `harnessDir` is required — the
429
+ * snapshot and `status.json` live under the harness root. */
430
+ export type RegisterPlanWorkflowOptions = {
431
+ /** Absolute harness dir that contains `status.json` + `workflows/`. Required. */
432
+ harnessDir: string;
433
+ /** The owned plan (contract §2: one independently owned plan per workflow on the new normal route). */
434
+ plan: {
435
+ id: string;
436
+ title: string;
437
+ file: string;
438
+ };
439
+ /** Delivery kind declared at registration (contract §1). Required — never inferred. */
440
+ deliveryKind: WorkflowDeliveryKind;
441
+ /** Project register id recorded on the snapshot (contract §3 register row). */
442
+ project?: string;
443
+ /** Source branch of the delivery, recorded as `branch.source`. Required together with `branchTarget` for `development`. */
444
+ branchSource?: string;
445
+ /** Target branch. Required together with `branchSource` for `development`. */
446
+ branchTarget?: string;
447
+ /**
448
+ * Completion policy for `verification/report-only` workflows (contract §1):
449
+ * names the evidence that completes the workflow. Required for that kind.
450
+ */
451
+ completionPolicy?: string;
452
+ /**
453
+ * Pre-existing coordinator binding recorded at registration. Optional —
454
+ * binding a NEW coordinator session stays on the authorized `bind` seam
455
+ * (`coordination.ts`); this only records an already-held binding.
456
+ */
457
+ coordinator?: {
458
+ session_id: string;
459
+ session_file: string;
460
+ };
461
+ /** Registration timestamp (YYYY-MM-DD or RFC3339). Default: now. */
462
+ startedAt?: string;
463
+ };
464
+ export type RegisterPlanWorkflowResult = {
465
+ workflowId: string;
466
+ snapshotPath: string;
467
+ /**
468
+ * True when this call completed a registration whose snapshot already
469
+ * existed (crash between snapshot creation and root registration): the
470
+ * existing snapshot bytes — identity, timestamps, ownership — were kept
471
+ * and only the root entry was written (contract §4b recovery).
472
+ */
473
+ recovered: boolean;
474
+ };
475
+ /**
476
+ * Register a standalone plan workflow (seam S1 — the generic normal-entry
477
+ * producer). Builds the create-only `type: plan` snapshot (workflow id, the
478
+ * owned plan as its single Todo row, project, delivery kind, source/target
479
+ * branches, optional coordinator) and the root `workflows[]` entry, then
480
+ * writes BOTH under one atomic section of the root `withStatusWriteLock`
481
+ * — the same serialization point `registerWorkflow` uses — mirroring
482
+ * `promoteAuditPlans`'s primitive sequence: create-only
483
+ * `writeWorkflowSnapshot` (its snapshot-dir lock nests inside the root lock,
484
+ * root → snapshot is the documented acquisition order) →
485
+ * `registerWorkflowEntryLocked`, with rollback that removes ONLY the exact
486
+ * snapshot version this call created (plus the now-empty workflow dir), so a
487
+ * failed register write is never treated as partial activation success.
488
+ *
489
+ * Refusals (fail-loud, no partial activation):
490
+ * - existing id: the workflow is already registered (snapshot + root entry) —
491
+ * registration is create-only, never a re-registration;
492
+ * - unreadable root: a malformed/v1 `status.json` refuses (the created
493
+ * snapshot is rolled back first);
494
+ * - missing required fields: id/plan/delivery-kind shape per the existing
495
+ * snapshot validators; `development` additionally requires source+target
496
+ * branches (contract §1 — a development workflow with missing branch
497
+ * fields is incomplete registration, not an exempt workflow) and
498
+ * `verification/report-only` requires the completion policy.
499
+ *
500
+ * Crash/retry recovery (contract §4b): a crash between snapshot creation and
501
+ * root registration leaves the snapshot orphaned (no root entry = no
502
+ * activation). Re-running this producer with the same registration identity
503
+ * completes the registration against the EXISTING snapshot bytes — identity,
504
+ * timestamps and ownership are preserved, never rewritten. An existing
505
+ * snapshot with a DIFFERENT registration identity refuses (it belongs to
506
+ * another registration).
507
+ *
508
+ * The caller must pin the artifact store to the harness root first
509
+ * (`setArtifactStore(createFsStore(harnessDir))`) when the active store's
510
+ * root could differ — the routed writers fail loud on a path mismatch.
511
+ */
512
+ export declare function registerPlanWorkflow(workflowId: string, options: RegisterPlanWorkflowOptions): Promise<RegisterPlanWorkflowResult>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mstar-harness/engine",
3
- "version": "3.9.3",
3
+ "version": "3.10.0",
4
4
  "description": "Morning Star Harness Workflow Engine — deterministic workflow enforcement library (path, status, lease, dispatch, sdd, iteration, lint gates).",
5
5
  "license": "MIT",
6
6
  "repository": {