@boxxy/model 0.1.2 → 0.1.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.
Files changed (234) hide show
  1. package/README.md +8 -6
  2. package/dist/closeouts/build-close-out-schema.d.ts +31 -0
  3. package/dist/closeouts/close-out-answer-schema.d.ts +3 -0
  4. package/dist/closeouts/close-out-schema.d.ts +3 -0
  5. package/dist/closeouts/design-close-out-schema.d.ts +30 -0
  6. package/dist/closeouts/friction-schema.d.ts +14 -0
  7. package/dist/closeouts/open-item-schema.d.ts +3 -0
  8. package/dist/closeouts/review-close-out-schema.d.ts +40 -0
  9. package/dist/closeouts/triage-close-out-schema.d.ts +40 -0
  10. package/dist/closeouts/types.d.ts +221 -0
  11. package/dist/dispatch/build-applied-change.d.ts +6 -0
  12. package/dist/dispatch/collect-seat-sync.d.ts +14 -0
  13. package/dist/dispatch/pick-seat-take.d.ts +10 -0
  14. package/dist/dispatch/types.d.ts +11 -0
  15. package/dist/{outbox-fact-schema.d.ts → facts/outbox-fact-schema.d.ts} +1 -1
  16. package/dist/facts/parse-new-fact.d.ts +2 -0
  17. package/dist/facts/types.d.ts +191 -0
  18. package/dist/facts/work-fact-schemas.d.ts +293 -0
  19. package/dist/index.d.ts +64 -23
  20. package/dist/items/build-item-views.d.ts +4 -0
  21. package/dist/items/collect-retries.d.ts +3 -0
  22. package/dist/items/collect-settled.d.ts +3 -0
  23. package/dist/items/derive-item-state.d.ts +17 -0
  24. package/dist/{live-levers.d.ts → items/live-levers.d.ts} +1 -1
  25. package/dist/items/types.d.ts +12 -0
  26. package/dist/pipeline/advance.d.ts +10 -0
  27. package/dist/pipeline/constants.d.ts +2 -0
  28. package/dist/pipeline/count-trailing.d.ts +1 -0
  29. package/dist/pipeline/find-position.d.ts +9 -0
  30. package/dist/pipeline/find-step.d.ts +3 -0
  31. package/dist/pipeline/merge-by-time.d.ts +9 -0
  32. package/dist/pipeline/position-schema.d.ts +3 -0
  33. package/dist/pipeline/types.d.ts +28 -0
  34. package/dist/planning/define-admission.d.ts +3 -0
  35. package/dist/planning/define-gate.d.ts +3 -0
  36. package/dist/planning/define-signal.d.ts +3 -0
  37. package/dist/planning/is-filter-match.d.ts +3 -0
  38. package/dist/planning/limit-fill-schema.d.ts +3 -0
  39. package/dist/{signal-key.d.ts → planning/signal-key.d.ts} +1 -1
  40. package/dist/planning/types.d.ts +155 -0
  41. package/dist/ports/types.d.ts +289 -0
  42. package/dist/reports/constants.d.ts +3 -0
  43. package/dist/reports/cost-to-land-schema.d.ts +29 -0
  44. package/dist/reports/outbox-status.d.ts +16 -0
  45. package/dist/reports/stage-time-schema.d.ts +25 -0
  46. package/dist/reports/types.d.ts +5 -0
  47. package/dist/rows/actor-ref-schema.d.ts +2 -0
  48. package/dist/rows/attempt-row-schema.d.ts +3 -0
  49. package/dist/rows/attempt-session-row-schema.d.ts +3 -0
  50. package/dist/{brand-schemas.d.ts → rows/brand-schemas.d.ts} +5 -2
  51. package/dist/rows/caller-identity-schema.d.ts +3 -0
  52. package/dist/rows/criterion-schema.d.ts +3 -0
  53. package/dist/rows/decision-row-schema.d.ts +34 -0
  54. package/dist/rows/evidence-row-schema.d.ts +3 -0
  55. package/dist/rows/item-row-schema.d.ts +28 -0
  56. package/dist/rows/item-view-schema.d.ts +3 -0
  57. package/dist/rows/lease-row-schema.d.ts +3 -0
  58. package/dist/rows/lever-row-schema.d.ts +12 -0
  59. package/dist/rows/limit-schema.d.ts +3 -0
  60. package/dist/rows/limit-seat-row-schema.d.ts +3 -0
  61. package/dist/rows/note-row-schema.d.ts +3 -0
  62. package/dist/rows/notice-row-schema.d.ts +3 -0
  63. package/dist/rows/pull-request-row-schema.d.ts +3 -0
  64. package/dist/rows/relation-row-schema.d.ts +3 -0
  65. package/dist/{row-schemas.d.ts → rows/row-schemas.d.ts} +2 -2
  66. package/dist/rows/runner-row-schema.d.ts +3 -0
  67. package/dist/rows/spawn-request-schema.d.ts +3 -0
  68. package/dist/rules/define-phase.d.ts +3 -0
  69. package/dist/rules/load-rejection-schema.d.ts +3 -0
  70. package/dist/rules/types.d.ts +244 -0
  71. package/dist/test-utils/build-mock-cost-to-land.d.ts +2 -0
  72. package/dist/test-utils/build-mock-evidence-row.d.ts +1 -1
  73. package/dist/test-utils/build-mock-fact-id.d.ts +1 -1
  74. package/dist/test-utils/build-mock-frame-item.d.ts +1 -1
  75. package/dist/test-utils/build-mock-frame.d.ts +2 -0
  76. package/dist/test-utils/build-mock-item-rules.d.ts +2 -0
  77. package/dist/test-utils/build-mock-lease-row.d.ts +1 -1
  78. package/dist/test-utils/build-mock-outbox-fact.d.ts +2 -0
  79. package/dist/test-utils/build-mock-phase-kind.d.ts +7 -0
  80. package/dist/test-utils/build-mock-pipeline.d.ts +7 -0
  81. package/dist/test-utils/build-mock-relation-row.d.ts +2 -0
  82. package/dist/test-utils/build-mock-settled.d.ts +9 -0
  83. package/dist/test-utils/build-mock-snapshot.d.ts +1 -1
  84. package/dist/test-utils/build-mock-v1-attempt-row.d.ts +2 -0
  85. package/dist/test-utils/build-mock-v1-item-row.d.ts +2 -0
  86. package/dist/test-utils/build-mock-v1-item-view.d.ts +2 -0
  87. package/dist/test-utils/build-mock-v1-lever-row.d.ts +2 -0
  88. package/dist/test-utils/build-mock-v1-pull-request-row.d.ts +2 -0
  89. package/dist/test-utils/build-mock-work-fact.d.ts +12 -0
  90. package/dist/test-utils/create-fake-notifier.d.ts +9 -0
  91. package/dist/test-utils/create-fake-pepys-reader.d.ts +13 -0
  92. package/dist/test-utils/fact-sink-contract.d.ts +14 -0
  93. package/dist/test-utils/pepys-reader-contract.d.ts +17 -0
  94. package/dist/{types/core.d.ts → types.d.ts} +93 -43
  95. package/package.json +13 -3
  96. package/src/{build-close-out-schema.ts → closeouts/build-close-out-schema.ts} +5 -10
  97. package/src/closeouts/close-out-answer-schema.ts +42 -0
  98. package/src/closeouts/close-out-schema.ts +13 -0
  99. package/src/closeouts/design-close-out-schema.ts +20 -0
  100. package/src/closeouts/friction-schema.ts +11 -0
  101. package/src/closeouts/open-item-schema.ts +8 -0
  102. package/src/closeouts/review-close-out-schema.ts +38 -0
  103. package/src/closeouts/triage-close-out-schema.ts +29 -0
  104. package/src/closeouts/types.ts +230 -0
  105. package/src/dispatch/build-applied-change.ts +57 -0
  106. package/src/dispatch/collect-seat-sync.ts +86 -0
  107. package/src/dispatch/pick-seat-take.ts +39 -0
  108. package/src/dispatch/types.ts +14 -0
  109. package/src/facts/outbox-fact-schema.ts +22 -0
  110. package/src/facts/parse-new-fact.ts +16 -0
  111. package/src/facts/types.ts +235 -0
  112. package/src/facts/work-fact-schemas.ts +201 -0
  113. package/src/index.ts +147 -55
  114. package/src/items/build-item-views.ts +146 -0
  115. package/src/items/collect-retries.ts +12 -0
  116. package/src/items/collect-settled.ts +20 -0
  117. package/src/items/derive-item-state.ts +95 -0
  118. package/src/{live-levers.ts → items/live-levers.ts} +1 -1
  119. package/src/items/types.ts +26 -0
  120. package/src/pipeline/advance.ts +78 -0
  121. package/src/pipeline/constants.ts +12 -0
  122. package/src/pipeline/count-trailing.ts +16 -0
  123. package/src/pipeline/find-position.ts +74 -0
  124. package/src/pipeline/find-step.ts +6 -0
  125. package/src/pipeline/merge-by-time.ts +33 -0
  126. package/src/pipeline/position-schema.ts +27 -0
  127. package/src/pipeline/types.ts +47 -0
  128. package/src/{define-admission.ts → planning/define-admission.ts} +2 -2
  129. package/src/{define-gate.ts → planning/define-gate.ts} +2 -2
  130. package/src/{define-signal.ts → planning/define-signal.ts} +2 -2
  131. package/src/planning/is-filter-match.ts +10 -0
  132. package/src/planning/limit-fill-schema.ts +12 -0
  133. package/src/{signal-key.ts → planning/signal-key.ts} +1 -1
  134. package/src/planning/types.ts +216 -0
  135. package/src/ports/types.ts +412 -0
  136. package/src/reports/constants.ts +6 -0
  137. package/src/reports/cost-to-land-schema.ts +47 -0
  138. package/src/reports/outbox-status.ts +22 -0
  139. package/src/reports/stage-time-schema.ts +21 -0
  140. package/src/reports/types.ts +7 -0
  141. package/src/rows/actor-ref-schema.ts +17 -0
  142. package/src/rows/attempt-row-schema.ts +69 -0
  143. package/src/rows/attempt-session-row-schema.ts +12 -0
  144. package/src/{brand-schemas.ts → rows/brand-schemas.ts} +5 -2
  145. package/src/rows/caller-identity-schema.ts +7 -0
  146. package/src/rows/criterion-schema.ts +9 -0
  147. package/src/rows/decision-row-schema.ts +34 -0
  148. package/src/rows/evidence-row-schema.ts +13 -0
  149. package/src/rows/item-row-schema.ts +32 -0
  150. package/src/rows/item-view-schema.ts +31 -0
  151. package/src/rows/lease-row-schema.ts +12 -0
  152. package/src/rows/lever-row-schema.ts +17 -0
  153. package/src/rows/limit-schema.ts +12 -0
  154. package/src/rows/limit-seat-row-schema.ts +12 -0
  155. package/src/rows/note-row-schema.ts +12 -0
  156. package/src/rows/notice-row-schema.ts +17 -0
  157. package/src/rows/pull-request-row-schema.ts +15 -0
  158. package/src/rows/relation-row-schema.ts +13 -0
  159. package/src/rows/row-schemas.ts +30 -0
  160. package/src/rows/runner-row-schema.ts +9 -0
  161. package/src/rows/spawn-request-schema.ts +15 -0
  162. package/src/rules/define-phase.ts +12 -0
  163. package/src/rules/load-rejection-schema.ts +51 -0
  164. package/src/rules/types.ts +291 -0
  165. package/src/test-utils/build-mock-cost-to-land.ts +31 -0
  166. package/src/test-utils/build-mock-evidence-row.ts +2 -2
  167. package/src/test-utils/build-mock-fact-id.ts +3 -3
  168. package/src/test-utils/build-mock-frame-item.ts +10 -5
  169. package/src/test-utils/build-mock-frame.ts +13 -0
  170. package/src/test-utils/build-mock-item-rules.ts +17 -0
  171. package/src/test-utils/build-mock-lease-row.ts +2 -2
  172. package/src/test-utils/build-mock-outbox-fact.ts +22 -0
  173. package/src/test-utils/build-mock-phase-kind.ts +29 -0
  174. package/src/test-utils/build-mock-pipeline.ts +52 -0
  175. package/src/test-utils/{build-mock-link-row.ts → build-mock-relation-row.ts} +4 -4
  176. package/src/test-utils/build-mock-settled.ts +18 -0
  177. package/src/test-utils/build-mock-snapshot.ts +10 -2
  178. package/src/test-utils/{build-mock-attempt-row.ts → build-mock-v1-attempt-row.ts} +28 -9
  179. package/src/test-utils/{build-mock-item-row.ts → build-mock-v1-item-row.ts} +7 -3
  180. package/src/test-utils/build-mock-v1-item-view.ts +29 -0
  181. package/src/test-utils/{build-mock-lever-row.ts → build-mock-v1-lever-row.ts} +5 -3
  182. package/src/test-utils/build-mock-v1-pull-request-row.ts +26 -0
  183. package/src/test-utils/build-mock-work-fact.ts +179 -0
  184. package/src/test-utils/create-fake-notifier.ts +54 -0
  185. package/src/test-utils/create-fake-pepys-reader.ts +73 -0
  186. package/src/test-utils/fact-sink-contract.ts +103 -0
  187. package/src/test-utils/pepys-reader-contract.ts +117 -0
  188. package/src/{types/core.ts → types.ts} +183 -59
  189. package/dist/actor-ref-schema.d.ts +0 -2
  190. package/dist/build-applied-change.d.ts +0 -13
  191. package/dist/build-close-out-schema.d.ts +0 -3
  192. package/dist/build-item-views.d.ts +0 -2
  193. package/dist/define-admission.d.ts +0 -3
  194. package/dist/define-gate.d.ts +0 -3
  195. package/dist/define-signal.d.ts +0 -3
  196. package/dist/derive-item-state.d.ts +0 -2
  197. package/dist/fact-schemas.d.ts +0 -5
  198. package/dist/find-slot-take.d.ts +0 -5
  199. package/dist/friction-schema.d.ts +0 -3
  200. package/dist/test-utils/build-mock-attempt-row.d.ts +0 -2
  201. package/dist/test-utils/build-mock-item-row.d.ts +0 -2
  202. package/dist/test-utils/build-mock-item-rows.d.ts +0 -2
  203. package/dist/test-utils/build-mock-item-view.d.ts +0 -2
  204. package/dist/test-utils/build-mock-lever-row.d.ts +0 -2
  205. package/dist/test-utils/build-mock-link-row.d.ts +0 -2
  206. package/dist/test-utils/build-mock-pull-request-row.d.ts +0 -2
  207. package/dist/types/dispatch.d.ts +0 -82
  208. package/dist/types/facts.d.ts +0 -154
  209. package/dist/types/planning.d.ts +0 -94
  210. package/dist/types/ports.d.ts +0 -218
  211. package/dist/types/registries.d.ts +0 -150
  212. package/src/actor-ref-schema.ts +0 -9
  213. package/src/build-applied-change.ts +0 -71
  214. package/src/build-item-views.ts +0 -128
  215. package/src/derive-item-state.ts +0 -76
  216. package/src/fact-schemas.ts +0 -132
  217. package/src/find-slot-take.ts +0 -12
  218. package/src/friction-schema.ts +0 -10
  219. package/src/outbox-fact-schema.ts +0 -25
  220. package/src/row-schemas.ts +0 -89
  221. package/src/test-utils/build-mock-item-rows.ts +0 -14
  222. package/src/test-utils/build-mock-item-view.ts +0 -8
  223. package/src/test-utils/build-mock-pull-request-row.ts +0 -16
  224. package/src/types/dispatch.ts +0 -95
  225. package/src/types/facts.ts +0 -166
  226. package/src/types/planning.ts +0 -136
  227. package/src/types/ports.ts +0 -262
  228. package/src/types/registries.ts +0 -185
  229. /package/dist/test-utils/{seed-faker.d.ts → pin-faker-seed.d.ts} +0 -0
  230. /package/dist/{format-key-path.d.ts → utils/format-key-path.d.ts} +0 -0
  231. /package/dist/{to-json-value.d.ts → utils/to-json-value.d.ts} +0 -0
  232. /package/src/test-utils/{seed-faker.ts → pin-faker-seed.ts} +0 -0
  233. /package/src/{format-key-path.ts → utils/format-key-path.ts} +0 -0
  234. /package/src/{to-json-value.ts → utils/to-json-value.ts} +0 -0
@@ -1,7 +1,8 @@
1
1
  import type { ContentHash, JsonValue } from '@boxxy/content-hash';
2
2
  import type { z } from 'zod';
3
- import type { brandSchemas } from '../brand-schemas.ts';
4
- import type { BuildCloseOut } from './facts.ts';
3
+ import type { CloseOut } from './closeouts/types.ts';
4
+ import type { HoldReason, Position } from './pipeline/types.ts';
5
+ import type { brandSchemas } from './rows/brand-schemas.ts';
5
6
 
6
7
  type BrandOf<K extends keyof typeof brandSchemas> = z.output<(typeof brandSchemas)[K]>;
7
8
 
@@ -15,6 +16,8 @@ export type AttemptId = BrandOf<'attemptId'>;
15
16
 
16
17
  export type DecisionId = BrandOf<'decisionId'>;
17
18
 
19
+ // A bare UUID version 7. The outbox row's fact ID, an evidence ID that a close-out cites, and
20
+ // each ID in `settled.criteria[].evidence` all have this one brand.
18
21
  export type FactId = BrandOf<'factId'>;
19
22
 
20
23
  export type RunnerId = BrandOf<'runnerId'>;
@@ -36,7 +39,7 @@ export interface PullRequestRef {
36
39
 
37
40
  export type ItemKindName = BrandOf<'itemKindName'>;
38
41
 
39
- export type LinkTypeName = BrandOf<'linkTypeName'>;
42
+ export type RelationTypeName = BrandOf<'relationTypeName'>;
40
43
 
41
44
  export type PhaseName = BrandOf<'phaseName'>;
42
45
 
@@ -44,6 +47,8 @@ export type PipelineName = BrandOf<'pipelineName'>;
44
47
 
45
48
  export type PoolName = BrandOf<'poolName'>;
46
49
 
50
+ export type LimitName = BrandOf<'limitName'>;
51
+
47
52
  export type RecipeName = BrandOf<'recipeName'>;
48
53
 
49
54
  export type WorkerKindName = BrandOf<'workerKindName'>;
@@ -60,6 +65,9 @@ export type SnapshotHash = BrandOf<'snapshotHash'>;
60
65
 
61
66
  export type RulesVersion = BrandOf<'rulesVersion'>;
62
67
 
68
+ // A name from a phase kind's `outcomes` list.
69
+ export type OutcomeName = BrandOf<'outcomeName'>;
70
+
63
71
  export interface ConceptPin {
64
72
  readonly ref: `${string}@${number}`;
65
73
  readonly sourceHash: ContentHash;
@@ -77,7 +85,14 @@ export type ActorRef =
77
85
  | `boxxy:attempt:${string}`
78
86
  | `boxxy:hook:${string}`;
79
87
 
80
- export type EvidenceKind = 'pr' | 'commit' | 'test' | 'ci-run' | 'live-check';
88
+ // A proven caller: who runs an attempt's session, or who sent a request. The core compares two
89
+ // of these for equality, on both fields, and reads nothing else from them.
90
+ export interface CallerIdentity {
91
+ readonly issuer: string;
92
+ readonly subject: string;
93
+ }
94
+
95
+ export type EvidenceKind = 'pull_request' | 'commit' | 'test' | 'ci-run' | 'live-check';
81
96
 
82
97
  export interface Criterion {
83
98
  readonly id: CriterionId;
@@ -85,6 +100,20 @@ export interface Criterion {
85
100
  readonly evidence: readonly FactId[];
86
101
  }
87
102
 
103
+ export type DesignMode = 'agent' | 'attended';
104
+
105
+ // How dispatch reads an attempt's session. Only design gives 'attended' in v1.
106
+ export type SessionMode = 'agent' | 'attended';
107
+
108
+ // v1 writes `claude_code` only. The second value keeps the telemetry tables' other product.
109
+ export type Product = 'claude_code' | 'codex';
110
+
111
+ // The fields of an item that a filter reads. The one v1 field is the design mode, and an item
112
+ // that sets none runs in agent mode.
113
+ export interface ItemFields {
114
+ readonly designMode?: DesignMode;
115
+ }
116
+
88
117
  export interface ItemRow {
89
118
  readonly id: ItemId;
90
119
  readonly kind: ItemKindName;
@@ -92,16 +121,48 @@ export interface ItemRow {
92
121
  readonly title: string;
93
122
  readonly outcome: string;
94
123
  readonly acceptance: readonly Criterion[];
124
+ readonly fields: ItemFields;
125
+
126
+ // free short strings: `item.file` sets them, and `item.edit` replaces the whole list
127
+ readonly labels: readonly string[];
95
128
  readonly foundInAttempt: AttemptId | null;
96
129
  readonly filedBy: ActorRef;
97
130
  readonly filedAt: Instant;
98
131
  readonly closedAt: Instant | null;
99
132
  readonly closeReason: string | null;
133
+
134
+ // state of the item between two attempts, which no fact carries
135
+ readonly keptSession: KeptSession | null;
136
+ }
137
+
138
+ export interface KeptSession {
139
+ readonly atcSession: AtcSessionId;
140
+
141
+ // the worker target the session runs on, as `SpawnRequest.target` has it
142
+ readonly target: string;
143
+ readonly attempt: AttemptId;
144
+ readonly keptAt: Instant;
145
+ readonly caller: CallerIdentity | null;
146
+ }
147
+
148
+ // Append-only: no procedure edits or removes a note.
149
+ export interface NoteRow {
150
+ readonly item: ItemId;
151
+
152
+ // 1, 2, 3… per item
153
+ readonly seq: number;
154
+ readonly text: string;
155
+ readonly by: ActorRef;
156
+ readonly at: Instant;
100
157
  }
101
158
 
102
159
  export type ItemState = 'idea' | 'ready' | 'running' | 'blocked' | 'waiting' | 'done' | 'archived';
103
160
 
104
- export type WaitingReason = 'PR open' | 'no PR linked' | 'attempts used up';
161
+ export type WaitingReason =
162
+ | 'pull request open'
163
+ | 'no pull request linked'
164
+ | 'pull request closed unmerged'
165
+ | HoldReason;
105
166
 
106
167
  export type DerivedState =
107
168
  | { readonly state: Exclude<ItemState, 'waiting'> }
@@ -109,43 +170,13 @@ export type DerivedState =
109
170
 
110
171
  export interface ItemView extends ItemRow {
111
172
  readonly derived: DerivedState;
173
+ readonly position: Position;
112
174
  }
113
175
 
114
- export interface ItemRows {
115
- // live links whose target is the item
116
- readonly links: readonly LinkRow[];
117
- readonly blockerStates: ReadonlyMap<ItemId, ItemState>;
118
- readonly levers: readonly LeverRow[];
119
- readonly attempts: readonly AttemptRow[];
120
- readonly liveLease: LeaseRow | null;
121
- readonly pullRequests: readonly PullRequestRow[];
122
-
123
- // the kind's `maxAttempts` for the item's current phase
124
- readonly maxAttempts: number;
125
- }
126
-
127
- // the rows a store reads to derive the state of a set of items, with each blocking source item
128
- export interface ItemSetRows {
129
- readonly items: readonly ItemRow[];
130
-
131
- // live links only
132
- readonly links: readonly LinkRow[];
133
- readonly levers: readonly LeverRow[];
134
- readonly attempts: readonly AttemptRow[];
135
- readonly liveLeases: readonly LeaseRow[];
136
- readonly pullRequests: readonly PullRequestRow[];
137
- }
138
-
139
- export type MaxAttemptsByKind = ReadonlyMap<ItemKindName, ReadonlyMap<PhaseName, number>>;
140
-
141
- export interface ItemWithLevers extends ItemView {
142
- readonly levers: readonly LeverRow[];
143
- }
144
-
145
- export interface LinkRow {
176
+ export interface RelationRow {
146
177
  readonly source: ItemId;
147
178
  readonly target: ItemId;
148
- readonly type: LinkTypeName;
179
+ readonly type: RelationTypeName;
149
180
  readonly addedBy: ActorRef;
150
181
  readonly addedAt: Instant;
151
182
  readonly removedAt: Instant | null;
@@ -158,17 +189,53 @@ export interface LeverRow {
158
189
  readonly until: Instant | null;
159
190
  readonly expiresAt: Instant | null;
160
191
  readonly reason: string | null;
192
+
193
+ // only `item.retry --phase` sets it
194
+ readonly phase: PhaseName | null;
161
195
  readonly actor: ActorRef;
162
196
  readonly at: Instant;
163
197
  }
164
198
 
165
- export type AttemptState = 'starting' | 'running' | 'reconciling' | 'succeeded' | 'failed';
166
-
167
- export type LiveAttemptState = Extract<AttemptState, 'starting' | 'running' | 'reconciling'>;
168
-
169
- export type KnownFailure = 'spawn-refused' | 'session-lost' | 'spawn-lost' | 'closeout-missing';
170
-
171
- export type ForcedFailure = Extract<KnownFailure, 'spawn-refused' | 'session-lost' | 'spawn-lost'>;
199
+ export type AttemptState =
200
+ | 'starting'
201
+ | 'running'
202
+ | 'reconciling'
203
+ | 'sleeping'
204
+ | 'waking'
205
+ | 'closing'
206
+ | 'succeeded'
207
+ | 'failed';
208
+
209
+ export type LiveAttemptState = Exclude<AttemptState, 'succeeded' | 'failed'>;
210
+
211
+ export type ClosingCause =
212
+ | 'closed-out'
213
+ | 'timed-out'
214
+ | 'item-closed'
215
+ | 'stalled'
216
+ | 'skill-missing'
217
+ | 'turn-ended'
218
+ | 'usage-limit';
219
+
220
+ export type ForcedFailure =
221
+ | 'spawn-refused'
222
+ | 'no-capacity'
223
+ | 'spawn-lost'
224
+ | 'session-lost'
225
+ | 'resume-lost'
226
+ | 'timed-out'
227
+ | 'item-closed'
228
+ | 'skill-missing'
229
+ | 'stalled'
230
+ | 'usage-limit';
231
+
232
+ export type KnownFailure = ForcedFailure | 'closeout-missing' | 'closeout-unsettleable';
233
+
234
+ // The engine's own outcomes. No phase kind may list either name.
235
+ export type EngineOutcome = 'lost' | 'unsettleable';
236
+
237
+ // each field holds a list of values, never one string
238
+ export type FieldValues = Readonly<Record<string, readonly string[]>>;
172
239
 
173
240
  export interface AttemptRow {
174
241
  readonly id: AttemptId;
@@ -179,24 +246,53 @@ export interface AttemptRow {
179
246
  readonly recipeHash: RecipeHash;
180
247
  readonly rulesVersion: RulesVersion;
181
248
  readonly pool: PoolName;
182
- readonly slot: number;
183
- readonly slotGen: number;
184
249
  readonly leaseGen: number;
185
250
  readonly spawnRequest: JsonValue;
186
251
  readonly spawnRequestHash: ContentHash;
187
252
  readonly state: AttemptState;
188
253
  readonly failure: string | null;
189
254
  readonly atcSession: AtcSessionId | null;
190
- readonly closeOut: BuildCloseOut | null;
255
+
256
+ // null: the worker gave no caller, and every session and hook call for the attempt is refused
257
+ readonly caller: CallerIdentity | null;
191
258
  readonly claimedAt: Instant;
192
259
  readonly startedAt: Instant | null;
193
260
  readonly endedAt: Instant | null;
261
+
262
+ // what `decide` saw; a wake and a rules reload match limits against these
263
+ readonly fields: FieldValues;
264
+ readonly mode: SessionMode;
265
+ readonly round: number;
266
+ readonly input: JsonValue;
267
+
268
+ // 1 at the claim, one higher on each wake; every held seat carries it
269
+ readonly holdGen: number;
270
+
271
+ // the first valid close-out, never replaced
272
+ readonly closeOut: CloseOut | null;
273
+ readonly closeOutHash: ContentHash | null;
274
+ readonly closeOutFact: FactId | null;
275
+ readonly closing: ClosingCause | null;
276
+ readonly closingAt: Instant | null;
277
+ readonly suspendRequestedAt: Instant | null;
278
+ readonly sleptAt: Instant | null;
279
+ readonly wakeRequestedAt: Instant | null;
280
+ readonly wokenAt: Instant | null;
281
+ readonly outcome: OutcomeName | EngineOutcome | null;
282
+
283
+ // what the phase code returned, for an attempt settled as `closeout-unsettleable`
284
+ readonly returnedOutcome: string | null;
285
+ readonly strayedAt: Instant | null;
286
+ readonly sessionStoppedAt: Instant | null;
287
+ readonly sessionForgottenAt: Instant | null;
194
288
  }
195
289
 
196
290
  export interface AttemptSessionRow {
197
291
  readonly attempt: AttemptId;
198
292
  readonly agentSession: AgentSessionId;
199
293
  readonly atcSession: AtcSessionId;
294
+ readonly product: Product;
295
+ readonly source: 'worker' | 'hook';
200
296
  readonly seenAt: Instant;
201
297
  }
202
298
 
@@ -209,12 +305,16 @@ export interface LeaseRow {
209
305
  readonly releasedAt: Instant | null;
210
306
  }
211
307
 
212
- export interface PoolSlotRow {
213
- readonly pool: PoolName;
214
- readonly slot: number;
215
- readonly holder: AttemptId | null;
216
- readonly gen: number;
217
- readonly retired: boolean;
308
+ // A limit's count is its rows with no `releasedAt`.
309
+ export interface LimitSeatRow {
310
+ readonly limit: LimitName;
311
+ readonly attempt: AttemptId;
312
+ readonly holdGen: number;
313
+
314
+ // taken past the limit's `max`, by a wake over the cap
315
+ readonly overCap: boolean;
316
+ readonly takenAt: Instant;
317
+ readonly releasedAt: Instant | null;
218
318
  }
219
319
 
220
320
  export interface ObservationBoundary {
@@ -222,21 +322,32 @@ export interface ObservationBoundary {
222
322
  readonly pepysOffsets: Readonly<Record<StreamName, number>>;
223
323
  }
224
324
 
325
+ // A limit's count and `max` at the moment of a pick.
326
+ export interface LimitCount {
327
+ readonly limit: LimitName;
328
+ readonly held: number;
329
+ readonly max: number;
330
+ }
331
+
225
332
  export interface DecisionRow {
226
333
  readonly id: DecisionId;
227
334
  readonly attempt: AttemptId;
228
335
  readonly item: ItemId;
336
+ readonly kind: 'start' | 'wake';
229
337
  readonly pool: PoolName;
230
338
  readonly rulesVersion: RulesVersion;
231
339
  readonly snapshotHash: SnapshotHash;
232
340
  readonly storeVersion: number;
233
341
  readonly pepysOffsets: ObservationBoundary['pepysOffsets'];
234
342
  readonly faults: readonly FaultRecord[];
343
+
344
+ // each limit that counts the pick, with its count before the seat was taken
345
+ readonly limits: readonly LimitCount[];
235
346
  readonly at: Instant;
236
347
  }
237
348
 
238
349
  export interface FaultRecord {
239
- // the signal, gate, waiver or filter field name, or `propagation:<signal>:<link>`
350
+ // the signal, gate, waiver or filter field name, or `propagation:<signal>:<relation>`
240
351
  readonly plugin: string;
241
352
  readonly kind: 'signal' | 'gate' | 'waiver' | 'admission' | 'propagation' | 'filter-field';
242
353
  readonly item: ItemId | null;
@@ -259,6 +370,10 @@ export interface PullRequestRow {
259
370
  readonly repo: RepoName;
260
371
  readonly number: number;
261
372
  readonly attempt: AttemptId;
373
+
374
+ // GitHub's own `id` of the pull request, which pepys builds its entity ID from
375
+ readonly githubId: number;
376
+ readonly url: string;
262
377
  readonly state: 'open' | 'closed' | 'merged';
263
378
  readonly mergedAt: Instant | null;
264
379
  readonly mergeCommit: CommitSha | null;
@@ -271,6 +386,16 @@ export interface RunnerRow {
271
386
  readonly paused: boolean;
272
387
  }
273
388
 
389
+ // A hold notice for the `Notifier` port. The tick tries it again until `tries` reaches 5.
390
+ export interface NoticeRow {
391
+ readonly id: number;
392
+ readonly item: ItemId;
393
+ readonly reason: HoldReason;
394
+ readonly at: Instant;
395
+ readonly tries: number;
396
+ readonly sentAt: Instant | null;
397
+ }
398
+
274
399
  export type Effort = 'low' | 'medium' | 'high' | 'xhigh' | 'max';
275
400
 
276
401
  export interface Recipe {
@@ -281,19 +406,18 @@ export interface Recipe {
281
406
  // the prompt template's path in the rules checkout
282
407
  readonly prompt: string;
283
408
  readonly source: SourceName;
409
+
410
+ // the skills the phase needs; the recipe hash covers the list and the rules' pin
411
+ readonly skills: readonly string[];
284
412
  }
285
413
 
286
414
  export interface RecipeMaterial {
287
415
  readonly name: RecipeName;
288
416
  readonly recipe: Recipe;
289
417
  readonly promptHash: ContentHash;
290
- readonly pluginFolderHash: ContentHash;
291
418
  readonly rulesVersion: RulesVersion;
292
419
  }
293
420
 
294
- // the loader can't see the plugin folder, so claimNext adds its hash
295
- export type LoadedRecipe = Omit<RecipeMaterial, 'pluginFolderHash'>;
296
-
297
421
  export interface ResolvedRecipe extends RecipeMaterial {
298
422
  readonly hash: RecipeHash;
299
423
  }
@@ -1,2 +0,0 @@
1
- import { z } from 'zod';
2
- export declare const actorRefSchema: z.ZodUnion<readonly [z.ZodLiteral<"boxxy:owner:local">, z.ZodTemplateLiteral<`boxxy:runner:${string & z.$brand<"RunnerId">}`>, z.ZodTemplateLiteral<`boxxy:attempt:${string & z.$brand<"AttemptId">}`>, z.ZodTemplateLiteral<`boxxy:hook:${string & z.$brand<"AttemptId">}`>]>;
@@ -1,13 +0,0 @@
1
- import type { AttemptId, PoolName } from './types/core.ts';
2
- import type { StoreChange } from './types/ports.ts';
3
- export interface TakenSlot {
4
- readonly holder: AttemptId;
5
- readonly pool: PoolName;
6
- readonly slot: number;
7
- readonly gen: number;
8
- }
9
- export interface ChangeAssignments {
10
- readonly taken: TakenSlot | null;
11
- readonly lastLeverSeq: number;
12
- }
13
- export declare function buildAppliedChange(change: StoreChange, assignments: ChangeAssignments): Pick<StoreChange, 'writes' | 'facts'>;
@@ -1,3 +0,0 @@
1
- import { z } from 'zod';
2
- import type { BuildCloseOut } from './types/facts.ts';
3
- export declare const buildCloseOutSchema: z.ZodType<BuildCloseOut>;
@@ -1,2 +0,0 @@
1
- import type { Instant, ItemSetRows, ItemWithLevers, MaxAttemptsByKind } from './types/core.ts';
2
- export declare function buildItemViews(rows: ItemSetRows, now: Instant, maxAttemptsByKind: MaxAttemptsByKind): ItemWithLevers[];
@@ -1,3 +0,0 @@
1
- import type { Admission } from './types/planning.ts';
2
- import type { Registered } from './types/registries.ts';
3
- export declare function defineAdmission<P>(admission: Admission<P>): Registered<'admission'>;
@@ -1,3 +0,0 @@
1
- import type { Gate } from './types/planning.ts';
2
- import type { Registered } from './types/registries.ts';
3
- export declare function defineGate<P>(gate: Gate<P>): Registered<'gate'>;
@@ -1,3 +0,0 @@
1
- import type { Signal } from './types/planning.ts';
2
- import type { Registered } from './types/registries.ts';
3
- export declare function defineSignal<P>(signal: Signal<P>): Registered<'signal'>;
@@ -1,2 +0,0 @@
1
- import type { DerivedState, ItemRow, ItemRows } from './types/core.ts';
2
- export declare function deriveItemState(item: ItemRow, rows: ItemRows): DerivedState;
@@ -1,5 +0,0 @@
1
- import { z } from 'zod';
2
- import type { FactType, SliceOneFacts } from './types/facts.ts';
3
- export declare const factSchemas: {
4
- readonly [T in FactType]: z.ZodType<SliceOneFacts[T]>;
5
- };
@@ -1,5 +0,0 @@
1
- import type { RowWrite } from './types/ports.ts';
2
- export type SlotTake = Extract<RowWrite, {
3
- op: 'take-slot';
4
- }>;
5
- export declare function findSlotTake(writes: readonly RowWrite[]): SlotTake | null;
@@ -1,3 +0,0 @@
1
- import { z } from 'zod';
2
- import type { Friction } from './types/facts.ts';
3
- export declare const frictionSchema: z.ZodType<Friction>;
@@ -1,2 +0,0 @@
1
- import type { AttemptRow } from '../types/core.ts';
2
- export declare function buildMockAttemptRow(overrides?: Partial<AttemptRow>): AttemptRow;
@@ -1,2 +0,0 @@
1
- import type { ItemRow } from '../types/core.ts';
2
- export declare function buildMockItemRow(overrides?: Partial<ItemRow>): ItemRow;
@@ -1,2 +0,0 @@
1
- import type { ItemRows } from '../types/core.ts';
2
- export declare function buildMockItemRows(overrides?: Partial<ItemRows>): ItemRows;
@@ -1,2 +0,0 @@
1
- import type { ItemView } from '../types/core.ts';
2
- export declare function buildMockItemView(overrides?: Partial<ItemView>): ItemView;
@@ -1,2 +0,0 @@
1
- import type { LeverRow } from '../types/core.ts';
2
- export declare function buildMockLeverRow(overrides?: Partial<LeverRow>): LeverRow;
@@ -1,2 +0,0 @@
1
- import type { LinkRow } from '../types/core.ts';
2
- export declare function buildMockLinkRow(overrides?: Partial<LinkRow>): LinkRow;
@@ -1,2 +0,0 @@
1
- import type { PullRequestRow } from '../types/core.ts';
2
- export declare function buildMockPullRequestRow(overrides?: Partial<PullRequestRow>): PullRequestRow;
@@ -1,82 +0,0 @@
1
- import type { ContentHash } from '@boxxy/content-hash';
2
- import type { AttemptId, AttemptRow, CriterionId, EvidenceRow, FactId, ForcedFailure, Instant, ItemView, KnownFailure, LiveAttemptState, Minutes, RecipeName, RepoName } from './core.ts';
3
- import type { Friction, OpenItem } from './facts.ts';
4
- import type { SessionReading, SpawnRequest } from './ports.ts';
5
- export interface SpawnContext {
6
- readonly repoPaths: ReadonlyMap<RepoName, string>;
7
- readonly pluginFolder: {
8
- readonly path: string;
9
- readonly hash: ContentHash;
10
- };
11
- readonly promptTemplates: ReadonlyMap<RecipeName, string>;
12
- }
13
- export interface Claim {
14
- readonly attempt: AttemptRow;
15
- readonly spawn: SpawnRequest;
16
- }
17
- export type ReconcileAction = {
18
- readonly kind: 'move-to-running';
19
- readonly fact: 'boxxy.attempt.started' | 'boxxy.attempt.reconciled';
20
- } | {
21
- readonly kind: 'bind-session';
22
- } | {
23
- readonly kind: 'settle';
24
- } | {
25
- readonly kind: 'fail';
26
- readonly failure: Extract<KnownFailure, 'session-lost'>;
27
- } | {
28
- readonly kind: 'respawn';
29
- readonly giveUpAfter: Minutes;
30
- readonly then: Extract<KnownFailure, 'spawn-lost'>;
31
- };
32
- export type ReconcileTable = Readonly<Record<SessionReading['kind'], Readonly<Record<LiveAttemptState, ReconcileAction>>>>;
33
- export interface Settlement {
34
- readonly state: 'succeeded' | 'failed';
35
- readonly failure: string | null;
36
- readonly openItems: readonly OpenItem[];
37
- readonly criteria: readonly {
38
- readonly criterion: CriterionId;
39
- readonly evidence: readonly FactId[];
40
- }[];
41
- readonly friction: readonly Friction[];
42
- readonly frictionDropped: number;
43
- }
44
- export interface SettleRule<Out = unknown> {
45
- settle: (input: SettleInput<Out>) => Settlement;
46
- }
47
- export interface SettleInput<Out> {
48
- readonly attempt: AttemptRow;
49
- readonly item: ItemView;
50
- readonly closeOut: CloseOutParse<Out> | null;
51
- readonly forced: ForcedFailure | null;
52
- readonly now: Instant;
53
- }
54
- export interface CloseOutContext {
55
- readonly item: ItemView;
56
- readonly attempt: AttemptId;
57
- readonly evidence: readonly EvidenceRow[];
58
- }
59
- export type CloseOutProblem = {
60
- readonly kind: 'schema';
61
- readonly path: string;
62
- readonly message: string;
63
- } | {
64
- readonly kind: 'unknown-criterion';
65
- readonly criterion: CriterionId;
66
- } | {
67
- readonly kind: 'foreign-evidence';
68
- readonly evidence: FactId;
69
- } | {
70
- readonly kind: 'built-without-evidence';
71
- readonly criteria: readonly CriterionId[];
72
- };
73
- export type CloseOutParse<Out> = {
74
- readonly kind: 'valid';
75
- readonly closeOut: Out;
76
- } | {
77
- readonly kind: 'invalid';
78
- readonly problems: readonly CloseOutProblem[];
79
- };
80
- export interface CloseOutParser<Out> {
81
- parse: (raw: unknown, ctx: CloseOutContext) => CloseOutParse<Out>;
82
- }