@cleocode/contracts 2026.10.27 → 2026.11.1-canary.2

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.
Files changed (102) hide show
  1. package/dist/.source-stamp.json +4 -0
  2. package/dist/__tests__/acceptance-gate.test.js +15 -3
  3. package/dist/__tests__/acceptance-gate.test.js.map +1 -1
  4. package/dist/__tests__/evidence-atom-schema.test.js +3 -1
  5. package/dist/__tests__/evidence-atom-schema.test.js.map +1 -1
  6. package/dist/__tests__/memory-wire-shapes.test.js.map +1 -1
  7. package/dist/acceptance-gate-schema.d.ts +25 -0
  8. package/dist/acceptance-gate-schema.d.ts.map +1 -1
  9. package/dist/acceptance-gate-schema.js +5 -0
  10. package/dist/acceptance-gate-schema.js.map +1 -1
  11. package/dist/acceptance-gate.d.ts +8 -0
  12. package/dist/acceptance-gate.d.ts.map +1 -1
  13. package/dist/data-accessor.d.ts +7 -0
  14. package/dist/data-accessor.d.ts.map +1 -1
  15. package/dist/data-accessor.js.map +1 -1
  16. package/dist/dispatch/operations-registry.d.ts.map +1 -1
  17. package/dist/dispatch/operations-registry.js +198 -0
  18. package/dist/dispatch/operations-registry.js.map +1 -1
  19. package/dist/docs/modernize.d.ts +409 -0
  20. package/dist/docs/modernize.d.ts.map +1 -0
  21. package/dist/docs/modernize.js +129 -0
  22. package/dist/docs/modernize.js.map +1 -0
  23. package/dist/docs-taxonomy.d.ts +6 -0
  24. package/dist/docs-taxonomy.d.ts.map +1 -1
  25. package/dist/docs-taxonomy.js +38 -1
  26. package/dist/docs-taxonomy.js.map +1 -1
  27. package/dist/done-plan.d.ts +27 -2
  28. package/dist/done-plan.d.ts.map +1 -1
  29. package/dist/evidence-atom-schema.d.ts +47 -1
  30. package/dist/evidence-atom-schema.d.ts.map +1 -1
  31. package/dist/evidence-atom-schema.js +83 -0
  32. package/dist/evidence-atom-schema.js.map +1 -1
  33. package/dist/exit-codes.d.ts +41 -0
  34. package/dist/exit-codes.d.ts.map +1 -1
  35. package/dist/exit-codes.js +41 -0
  36. package/dist/exit-codes.js.map +1 -1
  37. package/dist/index.d.ts +7 -3
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js +1 -0
  40. package/dist/index.js.map +1 -1
  41. package/dist/invariants/sync-write-invariants.d.ts.map +1 -1
  42. package/dist/invariants/sync-write-invariants.js +15 -0
  43. package/dist/invariants/sync-write-invariants.js.map +1 -1
  44. package/dist/memory/search.d.ts +13 -0
  45. package/dist/memory/search.d.ts.map +1 -1
  46. package/dist/merge-close.d.ts +167 -0
  47. package/dist/merge-close.d.ts.map +1 -0
  48. package/dist/merge-close.js +16 -0
  49. package/dist/merge-close.js.map +1 -0
  50. package/dist/operations/admin.d.ts +6 -0
  51. package/dist/operations/admin.d.ts.map +1 -1
  52. package/dist/operations/docs.d.ts +174 -3
  53. package/dist/operations/docs.d.ts.map +1 -1
  54. package/dist/operations/docs.js.map +1 -1
  55. package/dist/operations/worktree.d.ts +63 -0
  56. package/dist/operations/worktree.d.ts.map +1 -1
  57. package/dist/project-context.d.ts +31 -0
  58. package/dist/project-context.d.ts.map +1 -1
  59. package/dist/release/authorization.d.ts +46 -0
  60. package/dist/release/authorization.d.ts.map +1 -0
  61. package/dist/release/authorization.js +10 -0
  62. package/dist/release/authorization.js.map +1 -0
  63. package/dist/review-verdict.d.ts +125 -0
  64. package/dist/review-verdict.d.ts.map +1 -0
  65. package/dist/review-verdict.js +14 -0
  66. package/dist/review-verdict.js.map +1 -0
  67. package/dist/session-journal.d.ts.map +1 -1
  68. package/dist/session-journal.js +7 -1
  69. package/dist/session-journal.js.map +1 -1
  70. package/dist/task-record.d.ts +6 -1
  71. package/dist/task-record.d.ts.map +1 -1
  72. package/dist/task.d.ts +130 -3
  73. package/dist/task.d.ts.map +1 -1
  74. package/package.json +2 -2
  75. package/schemas/acceptance-gate.schema.json +24 -0
  76. package/schemas/task.schema.json +24 -0
  77. package/src/__tests__/__snapshots__/operations-registry.test.ts.snap +1 -1
  78. package/src/__tests__/acceptance-gate.test.ts +16 -3
  79. package/src/__tests__/evidence-atom-schema.test.ts +3 -1
  80. package/src/__tests__/memory-wire-shapes.test.ts +2 -0
  81. package/src/acceptance-gate-schema.ts +5 -0
  82. package/src/acceptance-gate.ts +9 -0
  83. package/src/data-accessor.ts +8 -0
  84. package/src/dispatch/operations-registry.ts +207 -0
  85. package/src/docs/modernize.ts +376 -0
  86. package/src/docs-taxonomy.ts +44 -1
  87. package/src/done-plan.ts +27 -2
  88. package/src/evidence-atom-schema.ts +97 -0
  89. package/src/exit-codes.ts +41 -0
  90. package/src/index.ts +51 -0
  91. package/src/invariants/sync-write-invariants.ts +16 -0
  92. package/src/memory/search.ts +10 -0
  93. package/src/merge-close.ts +168 -0
  94. package/src/operations/admin.ts +6 -0
  95. package/src/operations/docs.ts +180 -4
  96. package/src/operations/worktree.ts +66 -0
  97. package/src/project-context.ts +33 -0
  98. package/src/release/authorization.ts +48 -0
  99. package/src/review-verdict.ts +122 -0
  100. package/src/session-journal.ts +7 -1
  101. package/src/task-record.ts +6 -1
  102. package/src/task.ts +124 -3
@@ -11,6 +11,8 @@
11
11
  * @adr ADR-013
12
12
  */
13
13
 
14
+ import type { VerificationGate } from './task.js';
15
+
14
16
  /** Detected project ecosystem. Matches the writer in `detectProjectType`. */
15
17
  export type ProjectType =
16
18
  | 'node'
@@ -78,6 +80,14 @@ export interface ProjectEvidenceContext {
78
80
  * @task T12634
79
81
  */
80
82
  ciSatisfies?: boolean;
83
+ /**
84
+ * Gates a probed `deploy:` atom satisfies (T14083). No default: unset or
85
+ * empty, a deploy atom satisfies nothing, and never `testsPassed` unless
86
+ * listed here.
87
+ *
88
+ * @task T14083
89
+ */
90
+ deploySatisfies?: VerificationGate[];
81
91
  /**
82
92
  * Which required checks attest each gate for `ci:<pr>`. Each list must be a
83
93
  * subset of the required-check list; a gate without a list refuses `ci:`.
@@ -106,6 +116,24 @@ export interface ProjectEvidenceContext {
106
116
  * refused (E_EVIDENCE_RUNTIME_PATH_PROTECTED). Default: none.
107
117
  */
108
118
  runtimePaths?: string[];
119
+ /**
120
+ * Further git repositories this project's evidence may come from (an SDK in
121
+ * a separate repository, T14078). A typed gate names one by `repo`; any
122
+ * repository not declared here is refused.
123
+ */
124
+ repositories?: EvidenceRepositoryDeclaration[];
125
+ }
126
+
127
+ /**
128
+ * A git repository outside the project that typed gates may run in (T14078).
129
+ */
130
+ export interface EvidenceRepositoryDeclaration {
131
+ /** Name a typed gate's `repo` field uses. */
132
+ name: string;
133
+ /** The checkout's root, relative to the CLEO store root or absolute. */
134
+ path: string;
135
+ /** Why the project's evidence comes from it. */
136
+ purpose: string;
109
137
  }
110
138
 
111
139
  /**
@@ -163,6 +191,11 @@ export interface ProjectContext {
163
191
  build?: {
164
192
  command?: string;
165
193
  outputDir?: string;
194
+ /**
195
+ * Globs, relative to the project root, of scripts that run heavy tools:
196
+ * `cleo run` charges them as heavy whatever their content shows (T14162).
197
+ */
198
+ heavyScripts?: string[];
166
199
  };
167
200
  directories?: {
168
201
  source?: string;
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Standing release authorization (T14141 · owner decision D11215): a grant the
3
+ * owner signs with the enrolled owner key so a non-interactive
4
+ * `cleo release cut --yes` (an agent) may tag without a typed terminal
5
+ * confirmation.
6
+ *
7
+ * @task T14141
8
+ */
9
+
10
+ /**
11
+ * What a grant covers: `canary` (`-canary.N` versions), `prerelease` (any
12
+ * `-suffix`), `stable` (no suffix), or one exact `v`-prefixed version.
13
+ */
14
+ export type ReleaseAuthorizationScope = 'canary' | 'prerelease' | 'stable' | `v${string}`;
15
+
16
+ /** One owner-signed standing release authorization. */
17
+ export interface ReleaseAuthorizationGrant {
18
+ /** Grant id (`ra-<hex>`), named in the cut audit row and the tag message. */
19
+ id: string;
20
+ /** Versions the grant covers. */
21
+ scope: ReleaseAuthorizationScope;
22
+ /** Why the owner granted it. */
23
+ reason: string;
24
+ /** ISO time the grant was issued. */
25
+ issuedAt: string;
26
+ /** ISO time it stops counting (at most 30 days after issue). */
27
+ expiresAt: string;
28
+ /** Optional cap on cuts it may allow; null = no limit (D11215). */
29
+ uses: number | null;
30
+ /** The owner decision recorded for the grant (BRAIN decision id). */
31
+ decisionId: string;
32
+ /** Revocations on record when it was issued; a shorter revocation list later means tampering. */
33
+ revocationsAtIssue: number;
34
+ /** Enrolled owner public key (hex) that signed it. */
35
+ ownerPubkey: string;
36
+ /** Ed25519 signature (hex) over the grant's fields. */
37
+ sig: string;
38
+ }
39
+
40
+ /** A grant as `cleo release authorize --list` reports it. */
41
+ export interface ReleaseAuthorizationStatus extends ReleaseAuthorizationGrant {
42
+ /** Whether it currently allows a cut, and if not why. */
43
+ state: 'active' | 'expired' | 'used-up' | 'revoked' | 'tampered';
44
+ /** Cuts it has allowed (audit rows and tags naming it). */
45
+ used: number;
46
+ /** Why it is tampered, when it is. */
47
+ why?: string;
48
+ }
@@ -0,0 +1,122 @@
1
+ /**
2
+ * Independent per-AC review of a PR (T14122, council run
3
+ * 20261028T155822Z-293ed9f0, blocking amendment 2 of D11211).
4
+ *
5
+ * A reviewer other than the task's author judges each acceptance criterion
6
+ * from the PR diff and the criterion text alone, and records a verdict under
7
+ * its own CLEO session, bound to the PR head it reviewed. The merge sweep
8
+ * (T14101) records `satisfies:` only from a `met` verdict on the merged head;
9
+ * PR text can neither create nor waive one.
10
+ *
11
+ * @task T14122
12
+ */
13
+
14
+ /** One acceptance criterion as a reviewer sees it: its alias and its text. */
15
+ export interface ReviewPacketCriterion {
16
+ /** `AC1`, `AC2`, … */
17
+ alias: string;
18
+ /** The criterion text. */
19
+ text: string;
20
+ }
21
+
22
+ /**
23
+ * What a reviewer is given for one PR and task: the diff at the PR head and
24
+ * the task's criteria. The PR title, body, comments and commit messages are
25
+ * never included, so the author's `Closes:` / `Refs:` lines and summary cannot
26
+ * reach the reviewer.
27
+ */
28
+ export interface ReviewPacket {
29
+ /** The PR. */
30
+ prNumber: number;
31
+ /** The PR head the diff was taken at (`headRefOid`). */
32
+ headSha: string;
33
+ /** The task under review. */
34
+ taskId: string;
35
+ /** The task's criteria, in ordinal order. */
36
+ acs: ReviewPacketCriterion[];
37
+ /** The PR diff at `headSha`, without the paths in `withheldPaths`. */
38
+ diff: string;
39
+ /** Changed paths left out of `diff` because they carry the author's own account (changesets). */
40
+ withheldPaths: string[];
41
+ /** sha256 of the head, the criteria and the diff: a verdict names it to prove what was reviewed. */
42
+ packetSha256: string;
43
+ }
44
+
45
+ /** The identities that authored a task: its claim holders and the session that created it. */
46
+ export interface ReviewAuthors {
47
+ /** CLEO session ids. */
48
+ sessionIds: string[];
49
+ /** Agent ids (`CLEO_AGENT_ID`, spawn handles). */
50
+ agentIds: string[];
51
+ }
52
+
53
+ /** One reviewer's verdict on one criterion of one task, for one PR head. */
54
+ export interface ReviewVerdict {
55
+ /** Verdict id (uuid). */
56
+ id: string;
57
+ /** The task. */
58
+ taskId: string;
59
+ /** The criterion alias (`AC2`). */
60
+ ac: string;
61
+ /** The criterion's stable id (`task_acceptance_criteria.id`). */
62
+ acId: string;
63
+ /** The PR. */
64
+ prNumber: number;
65
+ /** The PR head the reviewer judged (`headRefOid`), never the merge sha. */
66
+ headSha: string;
67
+ /** Whether the diff implements the criterion. */
68
+ verdict: 'met' | 'unmet';
69
+ /** Why, in the reviewer's words. */
70
+ reason: string;
71
+ /** Who reviewed: never one of `authors`. */
72
+ reviewer: { sessionId: string; agentId: string | null };
73
+ /** The task's authors when the verdict was recorded, so a reader can re-check independence. */
74
+ authors: ReviewAuthors;
75
+ /** The {@link ReviewPacket.packetSha256} the reviewer was given. */
76
+ packetSha256: string;
77
+ /**
78
+ * The id of an earlier non-author `unmet` verdict on the same head that
79
+ * this `met` answers (T14128). Without it, a later `met` cannot clear that
80
+ * `unmet`, so shopping for a friendlier reviewer stays visible.
81
+ */
82
+ answers?: string;
83
+ /** ISO-8601 time it was recorded. */
84
+ createdAt: string;
85
+ }
86
+
87
+ /** Why one criterion has no usable verdict on a head. */
88
+ export interface ReviewGap {
89
+ /** The criterion alias. */
90
+ ac: string;
91
+ /**
92
+ * `missing`: none recorded; `unmet`: the latest says unmet; `stale`: only
93
+ * older heads have one; `author`: the latest on the head came from one of
94
+ * the task's own authors (a re-check of the record-time refusal).
95
+ */
96
+ kind: 'missing' | 'unmet' | 'stale' | 'author';
97
+ /** A one-line reason, e.g. `AC2: no verdict on head abc1234 (latest is for 9f00e12)`. */
98
+ reason: string;
99
+ }
100
+
101
+ /**
102
+ * An `unmet` verdict a later `met` answered on the same head (T14137), so an
103
+ * owner can see who cleared whose finding.
104
+ */
105
+ export interface ReviewAnswer {
106
+ /** The criterion. */
107
+ ac: string;
108
+ /** The answered `unmet` verdict and its reviewer. */
109
+ unmet: { id: string; reviewer: ReviewVerdict['reviewer'] };
110
+ /** The `met` verdict that answered it and its reviewer. */
111
+ met: { id: string; reviewer: ReviewVerdict['reviewer'] };
112
+ }
113
+
114
+ /** The criteria a set of verdicts proves met on a head, and the gaps. */
115
+ export interface ReviewJudgement {
116
+ /** The head judged against. */
117
+ headSha: string;
118
+ /** Criteria whose latest verdict on `headSha` is `met`. */
119
+ met: string[];
120
+ /** Criteria without a `met` verdict on `headSha`, each with why. */
121
+ gaps: ReviewGap[];
122
+ }
@@ -112,7 +112,13 @@ export const sessionJournalEntrySchema = z.object({
112
112
  tasksCompleted: z.array(z.string()).optional(),
113
113
 
114
114
  // Doctor summary (T1262 absorbed)
115
- /** Compact result of `scanBrainNoise` run at session-end. */
115
+ /**
116
+ * Compact result of `scanBrainNoise` run at session-end.
117
+ *
118
+ * @deprecated T14120: no longer written. Session end stopped running the
119
+ * brain scan (it held `cleo session end` for ~120 s on a large store); kept
120
+ * so older journal entries still parse. Use `cleo memory doctor`.
121
+ */
116
122
  doctorSummary: sessionJournalDoctorSummarySchema.optional(),
117
123
 
118
124
  // Debrief summary
@@ -8,7 +8,7 @@
8
8
  * @epic T4654
9
9
  */
10
10
 
11
- import type { AcceptanceItem, TaskVerification } from './task.js';
11
+ import type { AcceptanceItem, TaskClaim, TaskVerification } from './task.js';
12
12
 
13
13
  /** Omitted source fields and their UTF-8 serialized sizes on partial records. */
14
14
  export interface RecordProjectionDisclosure {
@@ -119,6 +119,11 @@ export interface TaskRecord extends RecordProjectionDisclosure {
119
119
  * @task T944
120
120
  */
121
121
  severity?: string | null;
122
+ /**
123
+ * The agent work lease held on this task (T12502); absent when unclaimed.
124
+ * Surfaced so `cleo show` reads back what `cleo claim` wrote (T14165).
125
+ */
126
+ claim?: TaskClaim;
122
127
  }
123
128
 
124
129
  /**
package/src/task.ts CHANGED
@@ -209,6 +209,17 @@ export interface EvidenceValidationContext {
209
209
  * each report is still validated on its own.
210
210
  */
211
211
  testRunPaths?: readonly string[];
212
+ /**
213
+ * The task's criteria this write names with `satisfies:<task>#AC…` (T14094),
214
+ * with their `AC<n>` alias. A merged PR of another task links to this task
215
+ * only through them: each must name the files the PR changed, and none may
216
+ * have been written or edited after the PR merged (`createdAt` and
217
+ * `updatedAt`: an edit gives a criterion a new row). Both are UTC ISO-8601
218
+ * with a zone, normalised by the writer from the store's zoneless text.
219
+ */
220
+ creditedCriteria?: ReadonlyArray<
221
+ Pick<AcRow, 'id' | 'text' | 'createdAt' | 'updatedAt'> & { alias: string }
222
+ >;
212
223
  /**
213
224
  * Validate without persisting anything: `pr:`/`ci:` lookups write neither
214
225
  * the PR-result cache nor the branch-protection cache (T12671 review — the
@@ -353,9 +364,9 @@ export type EvidenceAtom =
353
364
  */
354
365
  runtimeExcluded?: string[];
355
366
  /**
356
- * Untracked files outside every directory the change touches, which the
357
- * binding did not judge as this change (T14000): another agent's work
358
- * in a shared checkout. The tree hash includes them, so `cleo complete`
367
+ * Untracked files the binding did not judge as this change (T14000,
368
+ * T14125): anything not committed or staged, such as another agent's
369
+ * work in a shared checkout. The tree hash includes them, so `cleo complete`
359
370
  * and the superseded check refuse this atom as stale once any of them
360
371
  * is tracked (committed into the change): the run never covered it.
361
372
  */
@@ -396,6 +407,13 @@ export type EvidenceAtom =
396
407
  nonCodeChange?: boolean;
397
408
  /** Untracked files set aside at bind time, as for `test-run` (T14000). */
398
409
  untrackedSetAside?: string[];
410
+ /**
411
+ * The changed paths each check reads, judged at bind time (T14089): a
412
+ * check with none is not owed (a `.mjs`-only change owes no typecheck).
413
+ * Absent on receipts bound before T14089, or when nothing was judged:
414
+ * then both checks are owed.
415
+ */
416
+ owedChecks?: { typecheck: string[]; lint: string[] };
399
417
  }
400
418
  | {
401
419
  kind: 'tool';
@@ -463,6 +481,12 @@ export type EvidenceAtom =
463
481
  untestedPackages?: string[];
464
482
  /** Changed CLEO config this result leaves to `tool:config-schema` in the same gate write (T13778). */
465
483
  configPaths?: string[];
484
+ /**
485
+ * Untracked files a scoped `tool:test`/`tool:test-affected` result did
486
+ * not judge as this change (T14125), as on a test-run atom: `cleo
487
+ * complete` refuses the result once any of them is tracked.
488
+ */
489
+ untrackedSetAside?: string[];
466
490
  /**
467
491
  * Test files that failed and then passed on their single retry
468
492
  * (T12961). The run counts as a pass; this marks it as a FLAKY pass so
@@ -734,6 +758,80 @@ export type EvidenceAtom =
734
758
  /** Where the required-check list came from (env, project context, branch protection). */
735
759
  requiredSource: string;
736
760
  }
761
+ | {
762
+ /**
763
+ * A green run of `.github/workflows/repeat-run.yml` (T14149): one test
764
+ * file run `runs` times on the default branch, every run passing. Read
765
+ * from GitHub (workflow, event, branch, latest attempt) and cross-checked
766
+ * against the run's uploaded report. `headSha` must contain the task's
767
+ * implemented commits; the test file must be one the task changed or one a
768
+ * linked criterion names. It links criteria; it does not satisfy
769
+ * `testsPassed` on its own.
770
+ *
771
+ * @task T14149
772
+ */
773
+ kind: 'ci-run';
774
+ /** GitHub Actions run id. */
775
+ runId: number;
776
+ /** Commit the run tested (the run's `head_sha` on the default branch). */
777
+ headSha: string;
778
+ /** Repo-relative test file the run repeated. */
779
+ test: string;
780
+ /** How many consecutive runs passed. */
781
+ runs: number;
782
+ /** Run attempt that was judged (the latest). */
783
+ attempt: number;
784
+ /** Workflow file of the run. */
785
+ workflow: string;
786
+ /** Task the atom was verified for. */
787
+ taskId?: string;
788
+ }
789
+ | {
790
+ /**
791
+ * Probed deployment (T14083, owner decision on option (a)): at verify
792
+ * time CLEO ran a bounded GET of `probeUrl`, it returned 2xx and named
793
+ * the deployed SHA in its body or an `X-Commit` / `X-Version` header.
794
+ * `headSha` must contain the task's implemented commits (ancestor or
795
+ * patch-equivalent); `cleo complete` re-checks only that, never the probe.
796
+ * Satisfies only the gates in `satisfiesGates`, the project's
797
+ * `evidence.deploySatisfies` at verify time.
798
+ *
799
+ * @task T14083
800
+ */
801
+ kind: 'deploy';
802
+ /** Provider name as given (`railway`, `fly`, …); recorded, not verified. */
803
+ provider: string;
804
+ /** Provider deployment id as given; recorded, not verified. */
805
+ deploymentId: string;
806
+ /** The deployed commit, resolved to its full SHA. */
807
+ headSha: string;
808
+ /** The URL that was probed. */
809
+ probeUrl: string;
810
+ /** The probe's result. */
811
+ probe: {
812
+ /** HTTP status (2xx). */
813
+ status: number;
814
+ /** ISO 8601 time the probe completed. */
815
+ probedAt: string;
816
+ /** sha256 of the (bounded) response body read. */
817
+ bodySha256: string;
818
+ /** Where the SHA was named: `x-commit`, `x-version` or `body`. */
819
+ shaSource: 'x-commit' | 'x-version' | 'body';
820
+ };
821
+ /** The gates this atom satisfies (`evidence.deploySatisfies` at verify time). */
822
+ satisfiesGates: VerificationGate[];
823
+ /**
824
+ * The provider's own word on the deployment (T14091): `verified: true`
825
+ * when its API confirmed the deployment is live and was built from
826
+ * `headSha`; `verified: false` (with why) when no adapter or credential
827
+ * let CLEO ask, and only the probe stands. Absent on atoms before T14091.
828
+ */
829
+ providerCheck?:
830
+ | { verified: true; status: string; commitSha: string; checkedAt: string }
831
+ | { verified: false; reason: string };
832
+ /** Task the atom was verified for. */
833
+ taskId?: string;
834
+ }
737
835
  | {
738
836
  /**
739
837
  * Satisfies atom — cross-task acceptance-criterion binding per
@@ -802,6 +900,29 @@ export interface GateEvidence {
802
900
  override?: boolean;
803
901
  /** Reason given for an override (`CLEO_OWNER_OVERRIDE_REASON` env). */
804
902
  overrideReason?: string;
903
+ /**
904
+ * Why a scoped run recorded after the merge stands in for this gate where
905
+ * the change alone would have needed a whole-suite run (T14163). Written by
906
+ * `cleo complete` when it accepts the stand-in, so the reason outlives the
907
+ * command's output.
908
+ */
909
+ standIn?: GateStandIn;
910
+ }
911
+
912
+ /**
913
+ * A recorded post-merge stand-in (T14163): a manifest-only workspace change
914
+ * (root `package.json` dependency fields and the pnpm lockfile) scoped by the
915
+ * lockfile importers its merge changed.
916
+ */
917
+ export interface GateStandIn {
918
+ /** The stand-in rule that applied. */
919
+ kind: 'manifest-scoped';
920
+ /** The merge commit whose lockfile diff was read. */
921
+ mergeCommit: string;
922
+ /** Lockfile importers the merge changed; `.` is the root, every package. */
923
+ importers: string[];
924
+ /** ISO 8601 time `cleo complete` recorded it. */
925
+ recordedAt: string;
805
926
  }
806
927
 
807
928
  /** Task verification state. */