@boxxy/model 0.1.2 → 0.1.3

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
  type BrandOf<K extends keyof typeof brandSchemas> = z.output<(typeof brandSchemas)[K]>;
6
7
  export type Instant = BrandOf<'instant'>;
7
8
  export type Minutes = number;
@@ -20,10 +21,11 @@ export interface PullRequestRef {
20
21
  readonly number: number;
21
22
  }
22
23
  export type ItemKindName = BrandOf<'itemKindName'>;
23
- export type LinkTypeName = BrandOf<'linkTypeName'>;
24
+ export type RelationTypeName = BrandOf<'relationTypeName'>;
24
25
  export type PhaseName = BrandOf<'phaseName'>;
25
26
  export type PipelineName = BrandOf<'pipelineName'>;
26
27
  export type PoolName = BrandOf<'poolName'>;
28
+ export type LimitName = BrandOf<'limitName'>;
27
29
  export type RecipeName = BrandOf<'recipeName'>;
28
30
  export type WorkerKindName = BrandOf<'workerKindName'>;
29
31
  export type SourceName = BrandOf<'sourceName'>;
@@ -32,6 +34,7 @@ export type LeverKind = `${string}.${string}`;
32
34
  export type RecipeHash = BrandOf<'recipeHash'>;
33
35
  export type SnapshotHash = BrandOf<'snapshotHash'>;
34
36
  export type RulesVersion = BrandOf<'rulesVersion'>;
37
+ export type OutcomeName = BrandOf<'outcomeName'>;
35
38
  export interface ConceptPin {
36
39
  readonly ref: `${string}@${number}`;
37
40
  readonly sourceHash: ContentHash;
@@ -49,12 +52,22 @@ export type Actor = {
49
52
  readonly attempt: AttemptId;
50
53
  };
51
54
  export type ActorRef = 'boxxy:owner:local' | `boxxy:runner:${string}` | `boxxy:attempt:${string}` | `boxxy:hook:${string}`;
52
- export type EvidenceKind = 'pr' | 'commit' | 'test' | 'ci-run' | 'live-check';
55
+ export interface CallerIdentity {
56
+ readonly issuer: string;
57
+ readonly subject: string;
58
+ }
59
+ export type EvidenceKind = 'pull_request' | 'commit' | 'test' | 'ci-run' | 'live-check';
53
60
  export interface Criterion {
54
61
  readonly id: CriterionId;
55
62
  readonly text: string;
56
63
  readonly evidence: readonly FactId[];
57
64
  }
65
+ export type DesignMode = 'agent' | 'attended';
66
+ export type SessionMode = 'agent' | 'attended';
67
+ export type Product = 'claude_code' | 'codex';
68
+ export interface ItemFields {
69
+ readonly designMode?: DesignMode;
70
+ }
58
71
  export interface ItemRow {
59
72
  readonly id: ItemId;
60
73
  readonly kind: ItemKindName;
@@ -62,14 +75,31 @@ export interface ItemRow {
62
75
  readonly title: string;
63
76
  readonly outcome: string;
64
77
  readonly acceptance: readonly Criterion[];
78
+ readonly fields: ItemFields;
79
+ readonly labels: readonly string[];
65
80
  readonly foundInAttempt: AttemptId | null;
66
81
  readonly filedBy: ActorRef;
67
82
  readonly filedAt: Instant;
68
83
  readonly closedAt: Instant | null;
69
84
  readonly closeReason: string | null;
85
+ readonly keptSession: KeptSession | null;
86
+ }
87
+ export interface KeptSession {
88
+ readonly atcSession: AtcSessionId;
89
+ readonly target: string;
90
+ readonly attempt: AttemptId;
91
+ readonly keptAt: Instant;
92
+ readonly caller: CallerIdentity | null;
93
+ }
94
+ export interface NoteRow {
95
+ readonly item: ItemId;
96
+ readonly seq: number;
97
+ readonly text: string;
98
+ readonly by: ActorRef;
99
+ readonly at: Instant;
70
100
  }
71
101
  export type ItemState = 'idea' | 'ready' | 'running' | 'blocked' | 'waiting' | 'done' | 'archived';
72
- export type WaitingReason = 'PR open' | 'no PR linked' | 'attempts used up';
102
+ export type WaitingReason = 'pull request open' | 'no pull request linked' | 'pull request closed unmerged' | HoldReason;
73
103
  export type DerivedState = {
74
104
  readonly state: Exclude<ItemState, 'waiting'>;
75
105
  } | {
@@ -78,32 +108,12 @@ export type DerivedState = {
78
108
  };
79
109
  export interface ItemView extends ItemRow {
80
110
  readonly derived: DerivedState;
111
+ readonly position: Position;
81
112
  }
82
- export interface ItemRows {
83
- readonly links: readonly LinkRow[];
84
- readonly blockerStates: ReadonlyMap<ItemId, ItemState>;
85
- readonly levers: readonly LeverRow[];
86
- readonly attempts: readonly AttemptRow[];
87
- readonly liveLease: LeaseRow | null;
88
- readonly pullRequests: readonly PullRequestRow[];
89
- readonly maxAttempts: number;
90
- }
91
- export interface ItemSetRows {
92
- readonly items: readonly ItemRow[];
93
- readonly links: readonly LinkRow[];
94
- readonly levers: readonly LeverRow[];
95
- readonly attempts: readonly AttemptRow[];
96
- readonly liveLeases: readonly LeaseRow[];
97
- readonly pullRequests: readonly PullRequestRow[];
98
- }
99
- export type MaxAttemptsByKind = ReadonlyMap<ItemKindName, ReadonlyMap<PhaseName, number>>;
100
- export interface ItemWithLevers extends ItemView {
101
- readonly levers: readonly LeverRow[];
102
- }
103
- export interface LinkRow {
113
+ export interface RelationRow {
104
114
  readonly source: ItemId;
105
115
  readonly target: ItemId;
106
- readonly type: LinkTypeName;
116
+ readonly type: RelationTypeName;
107
117
  readonly addedBy: ActorRef;
108
118
  readonly addedAt: Instant;
109
119
  readonly removedAt: Instant | null;
@@ -115,13 +125,17 @@ export interface LeverRow {
115
125
  readonly until: Instant | null;
116
126
  readonly expiresAt: Instant | null;
117
127
  readonly reason: string | null;
128
+ readonly phase: PhaseName | null;
118
129
  readonly actor: ActorRef;
119
130
  readonly at: Instant;
120
131
  }
121
- export type AttemptState = 'starting' | 'running' | 'reconciling' | 'succeeded' | 'failed';
122
- export type LiveAttemptState = Extract<AttemptState, 'starting' | 'running' | 'reconciling'>;
123
- export type KnownFailure = 'spawn-refused' | 'session-lost' | 'spawn-lost' | 'closeout-missing';
124
- export type ForcedFailure = Extract<KnownFailure, 'spawn-refused' | 'session-lost' | 'spawn-lost'>;
132
+ export type AttemptState = 'starting' | 'running' | 'reconciling' | 'sleeping' | 'waking' | 'closing' | 'succeeded' | 'failed';
133
+ export type LiveAttemptState = Exclude<AttemptState, 'succeeded' | 'failed'>;
134
+ export type ClosingCause = 'closed-out' | 'timed-out' | 'item-closed' | 'stalled' | 'skill-missing' | 'turn-ended' | 'usage-limit';
135
+ export type ForcedFailure = 'spawn-refused' | 'no-capacity' | 'spawn-lost' | 'session-lost' | 'resume-lost' | 'timed-out' | 'item-closed' | 'skill-missing' | 'stalled' | 'usage-limit';
136
+ export type KnownFailure = ForcedFailure | 'closeout-missing' | 'closeout-unsettleable';
137
+ export type EngineOutcome = 'lost' | 'unsettleable';
138
+ export type FieldValues = Readonly<Record<string, readonly string[]>>;
125
139
  export interface AttemptRow {
126
140
  readonly id: AttemptId;
127
141
  readonly item: ItemId;
@@ -131,23 +145,42 @@ export interface AttemptRow {
131
145
  readonly recipeHash: RecipeHash;
132
146
  readonly rulesVersion: RulesVersion;
133
147
  readonly pool: PoolName;
134
- readonly slot: number;
135
- readonly slotGen: number;
136
148
  readonly leaseGen: number;
137
149
  readonly spawnRequest: JsonValue;
138
150
  readonly spawnRequestHash: ContentHash;
139
151
  readonly state: AttemptState;
140
152
  readonly failure: string | null;
141
153
  readonly atcSession: AtcSessionId | null;
142
- readonly closeOut: BuildCloseOut | null;
154
+ readonly caller: CallerIdentity | null;
143
155
  readonly claimedAt: Instant;
144
156
  readonly startedAt: Instant | null;
145
157
  readonly endedAt: Instant | null;
158
+ readonly fields: FieldValues;
159
+ readonly mode: SessionMode;
160
+ readonly round: number;
161
+ readonly input: JsonValue;
162
+ readonly holdGen: number;
163
+ readonly closeOut: CloseOut | null;
164
+ readonly closeOutHash: ContentHash | null;
165
+ readonly closeOutFact: FactId | null;
166
+ readonly closing: ClosingCause | null;
167
+ readonly closingAt: Instant | null;
168
+ readonly suspendRequestedAt: Instant | null;
169
+ readonly sleptAt: Instant | null;
170
+ readonly wakeRequestedAt: Instant | null;
171
+ readonly wokenAt: Instant | null;
172
+ readonly outcome: OutcomeName | EngineOutcome | null;
173
+ readonly returnedOutcome: string | null;
174
+ readonly strayedAt: Instant | null;
175
+ readonly sessionStoppedAt: Instant | null;
176
+ readonly sessionForgottenAt: Instant | null;
146
177
  }
147
178
  export interface AttemptSessionRow {
148
179
  readonly attempt: AttemptId;
149
180
  readonly agentSession: AgentSessionId;
150
181
  readonly atcSession: AtcSessionId;
182
+ readonly product: Product;
183
+ readonly source: 'worker' | 'hook';
151
184
  readonly seenAt: Instant;
152
185
  }
153
186
  export interface LeaseRow {
@@ -158,27 +191,35 @@ export interface LeaseRow {
158
191
  readonly takenAt: Instant;
159
192
  readonly releasedAt: Instant | null;
160
193
  }
161
- export interface PoolSlotRow {
162
- readonly pool: PoolName;
163
- readonly slot: number;
164
- readonly holder: AttemptId | null;
165
- readonly gen: number;
166
- readonly retired: boolean;
194
+ export interface LimitSeatRow {
195
+ readonly limit: LimitName;
196
+ readonly attempt: AttemptId;
197
+ readonly holdGen: number;
198
+ readonly overCap: boolean;
199
+ readonly takenAt: Instant;
200
+ readonly releasedAt: Instant | null;
167
201
  }
168
202
  export interface ObservationBoundary {
169
203
  readonly storeVersion: number;
170
204
  readonly pepysOffsets: Readonly<Record<StreamName, number>>;
171
205
  }
206
+ export interface LimitCount {
207
+ readonly limit: LimitName;
208
+ readonly held: number;
209
+ readonly max: number;
210
+ }
172
211
  export interface DecisionRow {
173
212
  readonly id: DecisionId;
174
213
  readonly attempt: AttemptId;
175
214
  readonly item: ItemId;
215
+ readonly kind: 'start' | 'wake';
176
216
  readonly pool: PoolName;
177
217
  readonly rulesVersion: RulesVersion;
178
218
  readonly snapshotHash: SnapshotHash;
179
219
  readonly storeVersion: number;
180
220
  readonly pepysOffsets: ObservationBoundary['pepysOffsets'];
181
221
  readonly faults: readonly FaultRecord[];
222
+ readonly limits: readonly LimitCount[];
182
223
  readonly at: Instant;
183
224
  }
184
225
  export interface FaultRecord {
@@ -201,6 +242,8 @@ export interface PullRequestRow {
201
242
  readonly repo: RepoName;
202
243
  readonly number: number;
203
244
  readonly attempt: AttemptId;
245
+ readonly githubId: number;
246
+ readonly url: string;
204
247
  readonly state: 'open' | 'closed' | 'merged';
205
248
  readonly mergedAt: Instant | null;
206
249
  readonly mergeCommit: CommitSha | null;
@@ -211,6 +254,14 @@ export interface RunnerRow {
211
254
  readonly heartbeatAt: Instant;
212
255
  readonly paused: boolean;
213
256
  }
257
+ export interface NoticeRow {
258
+ readonly id: number;
259
+ readonly item: ItemId;
260
+ readonly reason: HoldReason;
261
+ readonly at: Instant;
262
+ readonly tries: number;
263
+ readonly sentAt: Instant | null;
264
+ }
214
265
  export type Effort = 'low' | 'medium' | 'high' | 'xhigh' | 'max';
215
266
  export interface Recipe {
216
267
  readonly agent: string;
@@ -218,15 +269,14 @@ export interface Recipe {
218
269
  readonly effort: Effort;
219
270
  readonly prompt: string;
220
271
  readonly source: SourceName;
272
+ readonly skills: readonly string[];
221
273
  }
222
274
  export interface RecipeMaterial {
223
275
  readonly name: RecipeName;
224
276
  readonly recipe: Recipe;
225
277
  readonly promptHash: ContentHash;
226
- readonly pluginFolderHash: ContentHash;
227
278
  readonly rulesVersion: RulesVersion;
228
279
  }
229
- export type LoadedRecipe = Omit<RecipeMaterial, 'pluginFolderHash'>;
230
280
  export interface ResolvedRecipe extends RecipeMaterial {
231
281
  readonly hash: RecipeHash;
232
282
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@boxxy/model",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "The types that boxxy's packages share",
5
5
  "homepage": "https://github.com/zgeoff/boxxy/tree/main/libs/model#readme",
6
6
  "bugs": "https://github.com/zgeoff/boxxy/issues",
@@ -31,11 +31,21 @@
31
31
  "typecheck": "tsrs --noEmit"
32
32
  },
33
33
  "dependencies": {
34
- "@boxxy/content-hash": "0.1.0",
35
- "@faker-js/faker": "10.6.0",
34
+ "@boxxy/content-hash": "0.1.3",
36
35
  "tiny-invariant": "1.3.3",
37
36
  "zod": "4.6.7"
38
37
  },
38
+ "devDependencies": {
39
+ "@faker-js/faker": "10.6.0"
40
+ },
41
+ "peerDependencies": {
42
+ "@faker-js/faker": "10.6.0"
43
+ },
44
+ "peerDependenciesMeta": {
45
+ "@faker-js/faker": {
46
+ "optional": true
47
+ }
48
+ },
39
49
  "engines": {
40
50
  "bun": ">=1.3",
41
51
  "node": ">=24"
@@ -1,7 +1,8 @@
1
1
  import { z } from 'zod';
2
- import { brandSchemas } from './brand-schemas.ts';
2
+ import { brandSchemas } from '../rows/brand-schemas.ts';
3
3
  import { frictionSchema } from './friction-schema.ts';
4
- import type { BuildCloseOut } from './types/facts.ts';
4
+ import { openItemSchema } from './open-item-schema.ts';
5
+ import type { BuildCloseOut } from './types.ts';
5
6
 
6
7
  const reasonSchema = z.string().min(1);
7
8
  const builtSchema = z.object({ kind: z.literal('built') });
@@ -13,16 +14,10 @@ const citedEvidenceSchema = z.object({
13
14
  evidence: brandSchemas.factId,
14
15
  });
15
16
 
16
- const openItemSchema = z.object({
17
- kind: z.literal('core.issue'),
18
- title: z.string().min(1),
19
- body: z.string(),
20
- });
21
-
22
- export const buildCloseOutSchema: z.ZodType<BuildCloseOut> = z.object({
17
+ export const buildCloseOutSchema = z.strictObject({
23
18
  result: z.discriminatedUnion('kind', [builtSchema, blockedSchema, abandonedSchema]),
24
19
  criteria: z.array(citedEvidenceSchema),
25
20
  openItems: z.array(openItemSchema),
26
21
  friction: z.array(frictionSchema),
27
22
  frictionDropped: z.number().int().nonnegative(),
28
- });
23
+ }) satisfies z.ZodType<BuildCloseOut>;
@@ -0,0 +1,42 @@
1
+ import { z } from 'zod';
2
+ import { brandSchemas } from '../rows/brand-schemas.ts';
3
+ import type { CloseOutAnswer, CloseOutProblem } from './types.ts';
4
+
5
+ const closeOutProblemSchema: z.ZodType<CloseOutProblem> = z.discriminatedUnion('kind', [
6
+ z.object({ kind: z.literal('schema'), path: z.string(), message: z.string() }),
7
+ z.object({ kind: z.literal('unknown-criterion'), criterion: brandSchemas.criterionId }),
8
+ z.object({ kind: z.literal('foreign-evidence'), evidence: brandSchemas.factId }),
9
+ z.object({
10
+ kind: z.literal('built-without-evidence'),
11
+ criteria: z.array(brandSchemas.criterionId),
12
+ }),
13
+ z.object({ kind: z.literal('no-acceptance') }),
14
+ z.object({ kind: z.literal('unknown-item'), item: z.string() }),
15
+ z.object({ kind: z.literal('unknown-kind'), itemKind: z.string() }),
16
+ z.object({
17
+ kind: z.literal('refused-relation'),
18
+ type: z.string(),
19
+ target: z.string(),
20
+ reason: z.enum(['unknown-type', 'self']),
21
+ }),
22
+ z.object({ kind: z.literal('phase-rule'), message: z.string() }),
23
+ z.object({
24
+ kind: z.literal('too-large'),
25
+ bytes: z.number().int().nonnegative(),
26
+ max: z.number().int().nonnegative(),
27
+ }),
28
+ ]);
29
+
30
+ export const closeOutAnswerSchema: z.ZodType<CloseOutAnswer> = z.discriminatedUnion('kind', [
31
+ z.object({
32
+ kind: z.literal('recorded'),
33
+ attempt: brandSchemas.attemptId,
34
+ factId: brandSchemas.factId,
35
+ repeat: z.boolean(),
36
+ }),
37
+ z.object({ kind: z.literal('rejected'), problems: z.array(closeOutProblemSchema) }),
38
+ z.object({
39
+ kind: z.literal('refused'),
40
+ reason: z.enum(['no-attempt', 'already-closed-out', 'not-current']),
41
+ }),
42
+ ]);
@@ -0,0 +1,13 @@
1
+ import { z } from 'zod';
2
+ import { buildCloseOutSchema } from './build-close-out-schema.ts';
3
+ import { designCloseOutSchema } from './design-close-out-schema.ts';
4
+ import { reviewCloseOutSchema } from './review-close-out-schema.ts';
5
+ import { triageCloseOutSchema } from './triage-close-out-schema.ts';
6
+ import type { CloseOut } from './types.ts';
7
+
8
+ export const closeOutSchema: z.ZodType<CloseOut> = z.union([
9
+ reviewCloseOutSchema,
10
+ triageCloseOutSchema,
11
+ buildCloseOutSchema,
12
+ designCloseOutSchema,
13
+ ]);
@@ -0,0 +1,20 @@
1
+ import { z } from 'zod';
2
+ import { frictionSchema } from './friction-schema.ts';
3
+ import type { DesignCloseOut } from './types.ts';
4
+
5
+ const reasonSchema = z.string().min(1);
6
+
7
+ const designRefSchema = z.object({
8
+ summary: z.string().min(1),
9
+ location: z.string().min(1).nullable(),
10
+ });
11
+
12
+ const designedSchema = z.object({ kind: z.literal('designed'), design: designRefSchema });
13
+ const blockedSchema = z.object({ kind: z.literal('blocked'), reason: reasonSchema });
14
+ const abandonedSchema = z.object({ kind: z.literal('abandoned'), reason: reasonSchema });
15
+
16
+ export const designCloseOutSchema = z.strictObject({
17
+ result: z.discriminatedUnion('kind', [designedSchema, blockedSchema, abandonedSchema]),
18
+ friction: z.array(frictionSchema),
19
+ frictionDropped: z.number().int().nonnegative(),
20
+ }) satisfies z.ZodType<DesignCloseOut>;
@@ -0,0 +1,11 @@
1
+ import { z } from 'zod';
2
+ import type { Friction } from './types.ts';
3
+
4
+ // A plain object, so that the fact schema of `boxxy.proposal.recorded` can extend it.
5
+ export const frictionSchema = z.object({
6
+ target: z.object({
7
+ kind: z.enum(['skill', 'rule', 'lint', 'agents-md', 'tool']),
8
+ name: z.string().min(1),
9
+ }),
10
+ change: z.string().min(1),
11
+ }) satisfies z.ZodType<Friction>;
@@ -0,0 +1,8 @@
1
+ import { z } from 'zod';
2
+ import type { OpenItem } from './types.ts';
3
+
4
+ export const openItemSchema: z.ZodType<OpenItem> = z.object({
5
+ kind: z.literal('core.issue'),
6
+ title: z.string().min(1),
7
+ body: z.string(),
8
+ });
@@ -0,0 +1,38 @@
1
+ import { z } from 'zod';
2
+ import { brandSchemas } from '../rows/brand-schemas.ts';
3
+ import { frictionSchema } from './friction-schema.ts';
4
+ import type { ReviewCloseOut } from './types.ts';
5
+
6
+ const countSchema = z.number().int().nonnegative();
7
+
8
+ const findingSchema = z.object({
9
+ title: z.string().min(1),
10
+ body: z.string(),
11
+ path: z.string().min(1).exactOptional(),
12
+ line: z.number().int().positive().exactOptional(),
13
+ });
14
+
15
+ const passedSchema = z.object({ kind: z.literal('passed') });
16
+
17
+ const changesRequestedSchema = z.object({
18
+ kind: z.literal('changes-requested'),
19
+ findings: z.array(findingSchema),
20
+ });
21
+
22
+ const noslopSummarySchema = z.object({
23
+ version: z.number().int().positive(),
24
+ reviewID: z.string().min(1),
25
+ head: brandSchemas.commitSha,
26
+ counts: z.object({ findings: countSchema, failedCalls: countSchema, fixChecks: countSchema }),
27
+ reportBytes: countSchema,
28
+ report: z.json().nullable(),
29
+ });
30
+
31
+ // The stored form. The parser of the review phase reads noslop's whole result and builds the
32
+ // summary, so this schema never sees the raw result.
33
+ export const reviewCloseOutSchema = z.strictObject({
34
+ verdict: z.discriminatedUnion('kind', [passedSchema, changesRequestedSchema]),
35
+ noslop: noslopSummarySchema,
36
+ friction: z.array(frictionSchema),
37
+ frictionDropped: countSchema,
38
+ }) satisfies z.ZodType<ReviewCloseOut>;
@@ -0,0 +1,29 @@
1
+ import { z } from 'zod';
2
+ import { brandSchemas } from '../rows/brand-schemas.ts';
3
+ import { frictionSchema } from './friction-schema.ts';
4
+ import type { TriageCloseOut } from './types.ts';
5
+
6
+ const acceptedSchema = z.object({ kind: z.literal('accepted') });
7
+ const duplicateSchema = z.object({ kind: z.literal('duplicate'), of: brandSchemas.itemId });
8
+ const declinedSchema = z.object({ kind: z.literal('declined'), reason: z.string().min(1) });
9
+ const designModeSchema = z.enum(['agent', 'attended']);
10
+ const criterionTextSchema = z.object({ text: z.string().min(1) });
11
+
12
+ const setSchema = z.strictObject({
13
+ kind: brandSchemas.itemKindName.exactOptional(),
14
+ designMode: designModeSchema.exactOptional(),
15
+ acceptance: z.array(criterionTextSchema).exactOptional(),
16
+ });
17
+
18
+ const relationDraftSchema = z.object({
19
+ type: brandSchemas.relationTypeName,
20
+ target: brandSchemas.itemId,
21
+ });
22
+
23
+ export const triageCloseOutSchema = z.strictObject({
24
+ result: z.discriminatedUnion('kind', [acceptedSchema, duplicateSchema, declinedSchema]),
25
+ set: setSchema.exactOptional(),
26
+ relations: z.array(relationDraftSchema),
27
+ friction: z.array(frictionSchema),
28
+ frictionDropped: z.number().int().nonnegative(),
29
+ }) satisfies z.ZodType<TriageCloseOut>;