@boxxy/model 0.1.1 → 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 (222) 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/facts/outbox-fact-schema.d.ts +3 -0
  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 -16
  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/rows/row-schemas.d.ts +5 -0
  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 +2 -0
  73. package/dist/test-utils/build-mock-fact-id.d.ts +2 -0
  74. package/dist/test-utils/build-mock-frame-item.d.ts +2 -0
  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 +2 -0
  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} +94 -36
  95. package/dist/utils/format-key-path.d.ts +1 -0
  96. package/dist/utils/to-json-value.d.ts +2 -0
  97. package/package.json +14 -3
  98. package/src/{build-close-out-schema.ts → closeouts/build-close-out-schema.ts} +5 -10
  99. package/src/closeouts/close-out-answer-schema.ts +42 -0
  100. package/src/closeouts/close-out-schema.ts +13 -0
  101. package/src/closeouts/design-close-out-schema.ts +20 -0
  102. package/src/closeouts/friction-schema.ts +11 -0
  103. package/src/closeouts/open-item-schema.ts +8 -0
  104. package/src/closeouts/review-close-out-schema.ts +38 -0
  105. package/src/closeouts/triage-close-out-schema.ts +29 -0
  106. package/src/closeouts/types.ts +230 -0
  107. package/src/dispatch/build-applied-change.ts +57 -0
  108. package/src/dispatch/collect-seat-sync.ts +86 -0
  109. package/src/dispatch/pick-seat-take.ts +39 -0
  110. package/src/dispatch/types.ts +14 -0
  111. package/src/facts/outbox-fact-schema.ts +22 -0
  112. package/src/facts/parse-new-fact.ts +16 -0
  113. package/src/facts/types.ts +235 -0
  114. package/src/facts/work-fact-schemas.ts +201 -0
  115. package/src/index.ts +147 -41
  116. package/src/items/build-item-views.ts +146 -0
  117. package/src/items/collect-retries.ts +12 -0
  118. package/src/items/collect-settled.ts +20 -0
  119. package/src/items/derive-item-state.ts +95 -0
  120. package/src/{live-levers.ts → items/live-levers.ts} +1 -1
  121. package/src/items/types.ts +26 -0
  122. package/src/pipeline/advance.ts +78 -0
  123. package/src/pipeline/constants.ts +12 -0
  124. package/src/pipeline/count-trailing.ts +16 -0
  125. package/src/pipeline/find-position.ts +74 -0
  126. package/src/pipeline/find-step.ts +6 -0
  127. package/src/pipeline/merge-by-time.ts +33 -0
  128. package/src/pipeline/position-schema.ts +27 -0
  129. package/src/pipeline/types.ts +47 -0
  130. package/src/{define-admission.ts → planning/define-admission.ts} +2 -2
  131. package/src/{define-gate.ts → planning/define-gate.ts} +2 -2
  132. package/src/{define-signal.ts → planning/define-signal.ts} +2 -2
  133. package/src/planning/is-filter-match.ts +10 -0
  134. package/src/planning/limit-fill-schema.ts +12 -0
  135. package/src/{signal-key.ts → planning/signal-key.ts} +1 -1
  136. package/src/planning/types.ts +216 -0
  137. package/src/ports/types.ts +412 -0
  138. package/src/reports/constants.ts +6 -0
  139. package/src/reports/cost-to-land-schema.ts +47 -0
  140. package/src/reports/outbox-status.ts +22 -0
  141. package/src/reports/stage-time-schema.ts +21 -0
  142. package/src/reports/types.ts +7 -0
  143. package/src/rows/actor-ref-schema.ts +17 -0
  144. package/src/rows/attempt-row-schema.ts +69 -0
  145. package/src/rows/attempt-session-row-schema.ts +12 -0
  146. package/src/{brand-schemas.ts → rows/brand-schemas.ts} +5 -2
  147. package/src/rows/caller-identity-schema.ts +7 -0
  148. package/src/rows/criterion-schema.ts +9 -0
  149. package/src/rows/decision-row-schema.ts +34 -0
  150. package/src/rows/evidence-row-schema.ts +13 -0
  151. package/src/rows/item-row-schema.ts +32 -0
  152. package/src/rows/item-view-schema.ts +31 -0
  153. package/src/rows/lease-row-schema.ts +12 -0
  154. package/src/rows/lever-row-schema.ts +17 -0
  155. package/src/rows/limit-schema.ts +12 -0
  156. package/src/rows/limit-seat-row-schema.ts +12 -0
  157. package/src/rows/note-row-schema.ts +12 -0
  158. package/src/rows/notice-row-schema.ts +17 -0
  159. package/src/rows/pull-request-row-schema.ts +15 -0
  160. package/src/rows/relation-row-schema.ts +13 -0
  161. package/src/rows/row-schemas.ts +30 -0
  162. package/src/rows/runner-row-schema.ts +9 -0
  163. package/src/rows/spawn-request-schema.ts +15 -0
  164. package/src/rules/define-phase.ts +12 -0
  165. package/src/rules/load-rejection-schema.ts +51 -0
  166. package/src/rules/types.ts +291 -0
  167. package/src/test-utils/build-mock-cost-to-land.ts +31 -0
  168. package/src/test-utils/build-mock-evidence-row.ts +17 -0
  169. package/src/test-utils/build-mock-fact-id.ts +7 -0
  170. package/src/test-utils/build-mock-frame-item.ts +14 -0
  171. package/src/test-utils/build-mock-frame.ts +13 -0
  172. package/src/test-utils/build-mock-item-rules.ts +17 -0
  173. package/src/test-utils/build-mock-lease-row.ts +2 -2
  174. package/src/test-utils/build-mock-outbox-fact.ts +22 -0
  175. package/src/test-utils/build-mock-phase-kind.ts +29 -0
  176. package/src/test-utils/build-mock-pipeline.ts +52 -0
  177. package/src/test-utils/{build-mock-link-row.ts → build-mock-relation-row.ts} +4 -4
  178. package/src/test-utils/build-mock-settled.ts +18 -0
  179. package/src/test-utils/build-mock-snapshot.ts +13 -0
  180. package/src/test-utils/{build-mock-attempt-row.ts → build-mock-v1-attempt-row.ts} +28 -9
  181. package/src/test-utils/{build-mock-item-row.ts → build-mock-v1-item-row.ts} +7 -3
  182. package/src/test-utils/build-mock-v1-item-view.ts +29 -0
  183. package/src/test-utils/{build-mock-lever-row.ts → build-mock-v1-lever-row.ts} +5 -3
  184. package/src/test-utils/build-mock-v1-pull-request-row.ts +26 -0
  185. package/src/test-utils/build-mock-work-fact.ts +179 -0
  186. package/src/test-utils/create-fake-notifier.ts +54 -0
  187. package/src/test-utils/create-fake-pepys-reader.ts +73 -0
  188. package/src/test-utils/fact-sink-contract.ts +103 -0
  189. package/src/test-utils/pepys-reader-contract.ts +117 -0
  190. package/src/{types/core.ts → types.ts} +184 -48
  191. package/src/utils/format-key-path.ts +19 -0
  192. package/src/utils/to-json-value.ts +25 -0
  193. package/dist/build-close-out-schema.d.ts +0 -3
  194. package/dist/define-admission.d.ts +0 -3
  195. package/dist/define-gate.d.ts +0 -3
  196. package/dist/define-signal.d.ts +0 -3
  197. package/dist/derive-item-state.d.ts +0 -2
  198. package/dist/fact-schemas.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-lever-row.d.ts +0 -2
  204. package/dist/test-utils/build-mock-link-row.d.ts +0 -2
  205. package/dist/test-utils/build-mock-pull-request-row.d.ts +0 -2
  206. package/dist/types/dispatch.d.ts +0 -82
  207. package/dist/types/facts.d.ts +0 -154
  208. package/dist/types/planning.d.ts +0 -94
  209. package/dist/types/ports.d.ts +0 -218
  210. package/dist/types/registries.d.ts +0 -150
  211. package/src/derive-item-state.ts +0 -76
  212. package/src/fact-schemas.ts +0 -138
  213. package/src/friction-schema.ts +0 -10
  214. package/src/test-utils/build-mock-item-rows.ts +0 -14
  215. package/src/test-utils/build-mock-pull-request-row.ts +0 -16
  216. package/src/types/dispatch.ts +0 -95
  217. package/src/types/facts.ts +0 -166
  218. package/src/types/planning.ts +0 -136
  219. package/src/types/ports.ts +0 -262
  220. package/src/types/registries.ts +0 -185
  221. /package/dist/test-utils/{seed-faker.d.ts → pin-faker-seed.d.ts} +0 -0
  222. /package/src/test-utils/{seed-faker.ts → pin-faker-seed.ts} +0 -0
@@ -0,0 +1,19 @@
1
+ export function formatKeyPath(segments: readonly PropertyKey[]): string {
2
+ return segments.map((segment, index) => formatSegment(segment, index === 0)).join('');
3
+ }
4
+
5
+ const plainKeyPattern = /^[A-Za-z_][\w-]*$/u;
6
+
7
+ function formatSegment(segment: PropertyKey, isFirst: boolean): string {
8
+ if (typeof segment === 'number') {
9
+ return `[${segment}]`;
10
+ }
11
+
12
+ const key = String(segment);
13
+
14
+ if (!plainKeyPattern.test(key)) {
15
+ return `[${JSON.stringify(key)}]`;
16
+ }
17
+
18
+ return isFirst ? key : `.${key}`;
19
+ }
@@ -0,0 +1,25 @@
1
+ import type { JsonValue } from '@boxxy/content-hash';
2
+ import invariant from 'tiny-invariant';
3
+
4
+ export function toJSONValue(value: unknown): JsonValue {
5
+ if (
6
+ value === null ||
7
+ typeof value === 'boolean' ||
8
+ typeof value === 'number' ||
9
+ typeof value === 'string'
10
+ ) {
11
+ return value;
12
+ }
13
+
14
+ if (Array.isArray(value)) {
15
+ return value.map((entry: unknown) => toJSONValue(entry));
16
+ }
17
+
18
+ invariant(typeof value === 'object', `a ${typeof value} has no JSON form`);
19
+
20
+ return Object.fromEntries(
21
+ Object.entries(value)
22
+ .filter(([, entry]: [string, unknown]) => entry !== undefined)
23
+ .map(([key, entry]: [string, unknown]) => [key, toJSONValue(entry)]),
24
+ );
25
+ }
@@ -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,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,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 { 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
- }
@@ -1,154 +0,0 @@
1
- import type { JsonValue } from '@boxxy/content-hash';
2
- import type { ActorRef, AgentSessionId, AtcSessionId, CommitSha, Criterion, CriterionId, DecisionRow, EvidenceKind, FactId, Instant, ItemId, ItemRow, LeverRow, LinkTypeName, PhaseName, PoolName, RecipeHash, RepoName, RulesVersion, RunnerId } from './core.ts';
3
- export interface BuildCloseOut {
4
- readonly result: {
5
- readonly kind: 'built';
6
- } | {
7
- readonly kind: 'blocked';
8
- readonly reason: string;
9
- } | {
10
- readonly kind: 'abandoned';
11
- readonly reason: string;
12
- };
13
- readonly criteria: readonly {
14
- readonly criterion: CriterionId;
15
- readonly evidence: FactId;
16
- }[];
17
- readonly openItems: readonly OpenItem[];
18
- readonly friction: readonly Friction[];
19
- readonly frictionDropped: number;
20
- }
21
- export interface OpenItem {
22
- readonly kind: 'core.issue';
23
- readonly title: string;
24
- readonly body: string;
25
- }
26
- export type FrictionTargetKind = 'skill' | 'rule' | 'lint' | 'agents-md' | 'tool';
27
- export interface Friction {
28
- readonly target: {
29
- readonly kind: FrictionTargetKind;
30
- readonly name: string;
31
- };
32
- readonly change: string;
33
- }
34
- export type EntityRef = `boxxy:item:${string}` | `boxxy:link:${string}:${string}:${string}` | `boxxy:attempt:${string}` | `boxxy:decision:${string}` | `boxxy:runner:${string}`;
35
- export interface FactEnvelope<M extends object = SliceOneFacts, T extends keyof M & string = keyof M & string> {
36
- readonly id: FactId;
37
- readonly type: T;
38
- readonly v: 1;
39
- readonly api: 'boxxy/1';
40
- readonly entity: EntityRef;
41
- readonly actor: ActorRef;
42
- readonly at: Instant;
43
- readonly payload: M[T] & {
44
- readonly storeVersion: number;
45
- };
46
- }
47
- export interface NewFact<T extends keyof M & string, M extends object = SliceOneFacts> {
48
- readonly id: FactId;
49
- readonly type: T;
50
- readonly entity: EntityRef;
51
- readonly actor: ActorRef;
52
- readonly payload: M[T];
53
- }
54
- export interface OutboxFact {
55
- readonly seq: number;
56
- readonly factId: FactId;
57
- readonly type: string;
58
- readonly entity: EntityRef;
59
- readonly actor: ActorRef;
60
- readonly at: Instant;
61
- readonly payload: JsonValue;
62
- readonly sentAt: Instant | null;
63
- }
64
- export type FactType = keyof SliceOneFacts;
65
- export interface LinkPayload {
66
- readonly source: ItemId;
67
- readonly target: ItemId;
68
- readonly type: LinkTypeName;
69
- }
70
- export interface SliceOneFacts {
71
- 'boxxy.item.filed': ItemRow;
72
- 'boxxy.item.edited': {
73
- readonly title?: string;
74
- readonly outcome?: string;
75
- readonly acceptance?: readonly Criterion[];
76
- };
77
- 'boxxy.item.closed': {
78
- readonly reason: string;
79
- };
80
- 'boxxy.link.added': LinkPayload;
81
- 'boxxy.link.removed': LinkPayload;
82
- 'boxxy.lever.recorded': LeverRow;
83
- 'boxxy.attempt.claimed': {
84
- readonly item: ItemId;
85
- readonly phase: PhaseName;
86
- readonly number: number;
87
- readonly pool: PoolName;
88
- readonly slot: number;
89
- readonly gen: number;
90
- readonly recipeHash: RecipeHash;
91
- readonly rulesVersion: RulesVersion;
92
- };
93
- 'boxxy.decision.recorded': DecisionRow;
94
- 'boxxy.attempt.started': {
95
- readonly atcSession: AtcSessionId;
96
- };
97
- 'boxxy.attempt.reconciling': {
98
- readonly reason: string;
99
- };
100
- 'boxxy.attempt.reconciled': {
101
- readonly atcSession: AtcSessionId;
102
- };
103
- 'boxxy.attempt.session_bound': {
104
- readonly atcSession: AtcSessionId;
105
- readonly agentSession: AgentSessionId;
106
- readonly seenAt: Instant;
107
- };
108
- 'boxxy.attempt.closed_out': {
109
- readonly closeOut: BuildCloseOut;
110
- };
111
- 'boxxy.attempt.settled': {
112
- readonly state: 'succeeded' | 'failed';
113
- readonly failure: string | null;
114
- readonly endedAt: Instant;
115
- readonly criteria: readonly {
116
- readonly criterion: CriterionId;
117
- readonly evidence: readonly FactId[];
118
- }[];
119
- readonly matched: readonly ItemId[];
120
- readonly frictionDropped: number;
121
- };
122
- 'boxxy.evidence.recorded': {
123
- readonly kind: EvidenceKind;
124
- readonly ref: string;
125
- readonly observed: string | null;
126
- };
127
- 'boxxy.evidence.pr_linked': {
128
- readonly repo: RepoName;
129
- readonly number: number;
130
- readonly url: string;
131
- };
132
- 'boxxy.evidence.commit_linked': {
133
- readonly repo: RepoName;
134
- readonly sha: CommitSha;
135
- readonly pr: number;
136
- };
137
- 'boxxy.pr.merged': {
138
- readonly repo: RepoName;
139
- readonly number: number;
140
- readonly mergedAt: Instant;
141
- readonly mergeCommit: CommitSha;
142
- };
143
- 'boxxy.pr.closed': {
144
- readonly repo: RepoName;
145
- readonly number: number;
146
- };
147
- 'boxxy.proposal.recorded': Friction;
148
- 'boxxy.runner.paused': {
149
- readonly runner: RunnerId;
150
- };
151
- 'boxxy.runner.resumed': {
152
- readonly runner: RunnerId;
153
- };
154
- }
@@ -1,94 +0,0 @@
1
- import type { FaultRecord, Instant, ItemId, ItemView, LeverRow, LinkRow, LinkTypeName, PhaseName, PoolName } from './core.ts';
2
- import type { Schema } from './registries.ts';
3
- export type SignalName = string;
4
- export type GateName = string;
5
- export type WaiverName = string;
6
- export type AdmissionName = string;
7
- export type ViewName = string;
8
- export type SignalKey = `${SignalName}#${string}`;
9
- export interface Snapshot {
10
- storeVersion: number;
11
- items: ItemView[];
12
- links: LinkRow[];
13
- levers: LeverRow[];
14
- freeSlots: Record<PoolName, number>;
15
- }
16
- export interface FrameItem extends ItemView {
17
- readonly phase: PhaseName;
18
- }
19
- export interface Frame {
20
- candidates: FrameItem[];
21
- fields: Map<ItemId, Readonly<Record<string, readonly string[]>>>;
22
- values: Map<SignalKey, Map<ItemId, number>>;
23
- holds: Map<ItemId, Hold[]>;
24
- lifted: Map<ItemId, Lift[]>;
25
- faults: Fault[];
26
- }
27
- export type FrameValues = ReadonlyMap<SignalKey, ReadonlyMap<ItemId, number>>;
28
- export interface Hold {
29
- readonly gate: GateName;
30
- readonly reason: string;
31
- readonly until?: Instant;
32
- }
33
- export interface Lift {
34
- readonly waiver: WaiverName;
35
- readonly gate: GateName;
36
- readonly reason: string;
37
- }
38
- export type Fault = FaultRecord;
39
- export interface Decision {
40
- picks: Pick[];
41
- }
42
- export interface Pick {
43
- item: ItemId;
44
- phase: PhaseName;
45
- pool: PoolName;
46
- }
47
- export interface Pool {
48
- readonly name: PoolName;
49
- readonly slots: number;
50
- readonly takes: Readonly<Record<string, readonly string[]>>;
51
- readonly order: readonly SignalKey[];
52
- }
53
- export interface PlanContext {
54
- now: Instant;
55
- levers: LeverRow[];
56
- links: LinkRow[];
57
- values: FrameValues;
58
- }
59
- export interface Signal<P> {
60
- name: SignalName;
61
- params: Schema<P>;
62
- value: (item: FrameItem, ctx: PlanContext, params: P) => number | null;
63
- combine?: (left: number, right: number) => number;
64
- }
65
- export interface Gate<P> {
66
- name: GateName;
67
- liftable: boolean;
68
- params: Schema<P>;
69
- hold: (item: FrameItem, ctx: PlanContext, params: P) => Hold | null;
70
- }
71
- export interface Waiver {
72
- name: WaiverName;
73
- lifts: GateName;
74
- lift: (item: FrameItem, hold: Hold, ctx: PlanContext) => Lift | null;
75
- }
76
- export interface Admission<P> {
77
- name: AdmissionName;
78
- params: Schema<P>;
79
- admit: (item: FrameItem, ctx: PlanContext, params: P) => AdmissionGrant | null;
80
- }
81
- export interface AdmissionGrant {
82
- readonly admission: AdmissionName;
83
- readonly pools: readonly PoolName[] | 'any';
84
- readonly reason: string;
85
- }
86
- export interface View<I = unknown, O = unknown> {
87
- name: ViewName;
88
- render: (frame: Frame, input: I) => O;
89
- }
90
- export interface PropagationLine {
91
- readonly value: SignalName;
92
- readonly over: LinkTypeName;
93
- readonly toward: 'source' | 'target';
94
- }
@@ -1,218 +0,0 @@
1
- import type { JsonValue } from '@boxxy/content-hash';
2
- import type { AgentSessionId, AtcSessionId, AttemptId, AttemptRow, AttemptSessionRow, CommitSha, DecisionRow, Effort, EvidenceRow, FactId, Instant, ItemId, ItemRow, ItemState, ItemView, ItemWithLevers, LeaseRow, LeverRow, LinkRow, MaxAttemptsByKind, PhaseName, PoolName, PoolSlotRow, PullRequestRef, PullRequestRow, RepoName, RunnerId, RunnerRow } from './core.ts';
3
- import type { FactType, NewFact, OutboxFact } from './facts.ts';
4
- import type { Snapshot } from './planning.ts';
5
- export interface ClaimStore {
6
- exclusive: <T>(work: (tx: StoreTx) => Promise<T>) => Promise<T>;
7
- read: <T>(work: (tx: StoreReader) => Promise<T>) => Promise<T>;
8
- }
9
- export interface StoreReader {
10
- readSnapshot: (now: Instant, maxAttemptsByKind: MaxAttemptsByKind) => Promise<Snapshot>;
11
- readItem: (id: ItemId, now: Instant, maxAttemptsByKind: MaxAttemptsByKind) => Promise<ItemView | null>;
12
- readItemDetail: (id: ItemId, now: Instant, maxAttemptsByKind: MaxAttemptsByKind) => Promise<ItemDetailRows | null>;
13
- listItems: (filter: ItemFilter, now: Instant, maxAttemptsByKind: MaxAttemptsByKind) => Promise<ItemWithLevers[]>;
14
- listOpenIssues: (repo: RepoName, now: Instant, maxAttemptsByKind: MaxAttemptsByKind) => Promise<ItemView[]>;
15
- readLastLeaseGen: (item: ItemId, phase: PhaseName) => Promise<number>;
16
- readAttempt: (id: AttemptId) => Promise<AttemptRow | null>;
17
- listEvidence: (attempt: AttemptId) => Promise<EvidenceRow[]>;
18
- listLiveAttempts: () => Promise<AttemptRow[]>;
19
- listSucceededAttemptsWithoutPr: () => Promise<AttemptRow[]>;
20
- findAttemptBySession: (session: AtcSessionId) => Promise<AttemptRow | null>;
21
- findAttemptByAgentSession: (session: AgentSessionId) => Promise<AttemptId | null>;
22
- listWatchedPullRequests: () => Promise<PullRequestRow[]>;
23
- listPoolSlots: () => Promise<PoolSlotRow[]>;
24
- readUnsentFacts: (limit: number) => Promise<OutboxFact[]>;
25
- readOutboxLag: () => Promise<{
26
- readonly unsent: number;
27
- readonly oldestUnsentAt: Instant | null;
28
- }>;
29
- readRunner: (id: RunnerId) => Promise<RunnerRow | null>;
30
- }
31
- export interface ItemDetailRows {
32
- readonly item: ItemWithLevers;
33
- readonly attempts: readonly AttemptRow[];
34
- readonly links: readonly LinkRow[];
35
- readonly evidence: readonly EvidenceRow[];
36
- readonly pullRequests: readonly PullRequestRow[];
37
- }
38
- export interface StoreTx extends StoreReader {
39
- applyChange: (change: StoreChange) => Promise<ApplyResult>;
40
- markFactsSent: (ids: FactId[], at: Instant) => Promise<void>;
41
- writeHeartbeat: (runner: RunnerId, at: Instant) => Promise<void>;
42
- syncPoolSlots: (pools: readonly {
43
- readonly name: PoolName;
44
- readonly slots: number;
45
- }[]) => Promise<void>;
46
- markPullRequestChecked: (ref: PullRequestRef, at: Instant) => Promise<void>;
47
- }
48
- export interface StoreChange {
49
- at: Instant;
50
- under?: {
51
- item: ItemId;
52
- phase: PhaseName;
53
- gen: number;
54
- slot?: {
55
- pool: PoolName;
56
- slot: number;
57
- gen: number;
58
- };
59
- };
60
- writes: RowWrite[];
61
- facts: AnyNewFact[];
62
- }
63
- export type ApplyResult = {
64
- kind: 'applied';
65
- slot: {
66
- pool: PoolName;
67
- slot: number;
68
- gen: number;
69
- } | null;
70
- } | {
71
- kind: 'stale-generation';
72
- } | {
73
- kind: 'lease-held';
74
- } | {
75
- kind: 'no-free-slot';
76
- } | {
77
- kind: 'guard-mismatch';
78
- table: TableName;
79
- key: JsonValue;
80
- };
81
- export interface ItemFilter {
82
- readonly state?: ItemState;
83
- readonly repo?: RepoName;
84
- }
85
- export interface Tables {
86
- items: ItemRow;
87
- links: LinkRow;
88
- levers: LeverRow;
89
- attempts: AttemptRow;
90
- attempt_sessions: AttemptSessionRow;
91
- leases: LeaseRow;
92
- pool_slots: PoolSlotRow;
93
- decisions: DecisionRow;
94
- evidence: EvidenceRow;
95
- pull_requests: PullRequestRow;
96
- runners: RunnerRow;
97
- }
98
- export type TableName = keyof Tables;
99
- export type RowWrite = {
100
- [T in TableName]: {
101
- readonly op: 'insert';
102
- readonly table: T;
103
- readonly row: Tables[T];
104
- };
105
- }[TableName] | {
106
- [T in TableName]: {
107
- readonly op: 'update';
108
- readonly table: T;
109
- readonly key: Partial<Tables[T]>;
110
- readonly expect: Partial<Tables[T]>;
111
- readonly set: Partial<Tables[T]>;
112
- };
113
- }[TableName] | {
114
- readonly op: 'take-slot';
115
- readonly pool: PoolName;
116
- readonly holder: AttemptId;
117
- } | {
118
- readonly op: 'release-slot';
119
- readonly pool: PoolName;
120
- readonly slot: number;
121
- readonly holder: AttemptId;
122
- };
123
- export type AnyNewFact = {
124
- [T in FactType]: NewFact<T>;
125
- }[FactType];
126
- export interface WorkerKind {
127
- start: (request: SpawnRequest) => Promise<StartOutcome>;
128
- reconcile: (attempt: AttemptRow) => Promise<SessionReading>;
129
- }
130
- export type StartOutcome = {
131
- kind: 'started';
132
- atcSession: AtcSessionId;
133
- agentSession: AgentSessionId | null;
134
- } | {
135
- kind: 'refused';
136
- reason: string;
137
- } | {
138
- kind: 'unknown';
139
- reason: string;
140
- };
141
- export type SessionReading = {
142
- kind: 'running';
143
- atcSession: AtcSessionId;
144
- agentSession: AgentSessionId | null;
145
- } | {
146
- kind: 'ended';
147
- atcSession: AtcSessionId;
148
- agentSession: AgentSessionId | null;
149
- } | {
150
- kind: 'absent';
151
- };
152
- export interface SpawnRequest {
153
- readonly cwd: string;
154
- readonly prompt: string;
155
- readonly agent: string;
156
- readonly model: string;
157
- readonly effort: Effort;
158
- readonly pluginDirs: readonly string[];
159
- readonly name: `boxxy/${string}`;
160
- readonly idempotencyKey: AttemptId;
161
- }
162
- export interface SessionFault {
163
- readonly kind: 'fault';
164
- readonly fault: 'agent-session-owned';
165
- readonly agentSession: AgentSessionId;
166
- readonly attempt: AttemptId;
167
- readonly holder: AttemptId;
168
- }
169
- export interface FactSink {
170
- append: (facts: OutboxFact[]) => Promise<'accepted' | {
171
- kind: 'unknown';
172
- reason: string;
173
- } | {
174
- kind: 'rejected';
175
- error: string;
176
- }>;
177
- }
178
- export interface CostToLandRow {
179
- readonly item: ItemId;
180
- readonly title: string;
181
- readonly repo: RepoName;
182
- readonly landedAt: Instant;
183
- readonly model: string;
184
- readonly attempts: number;
185
- readonly requests: number;
186
- readonly inputTokens: number;
187
- readonly outputTokens: number;
188
- readonly cacheReadTokens: number;
189
- readonly cacheCreationTokens: number;
190
- readonly totalInputTokens: number;
191
- readonly costUsd: number;
192
- }
193
- export interface CostToLandInput {
194
- readonly repo?: string;
195
- readonly landedFrom?: string;
196
- readonly landedTo?: string;
197
- }
198
- export interface CostReader {
199
- costToLand: (input: CostToLandInput) => Promise<CostToLandRow[]>;
200
- }
201
- export interface Forge {
202
- readPullRequest: (ref: PullRequestRef) => Promise<PullRequestReading | 'not-found'>;
203
- listOpenPullRequests: (repo: RepoName) => Promise<PullRequestRef[]>;
204
- }
205
- export interface PullRequestReading {
206
- url: string;
207
- state: 'open' | 'closed' | 'merged';
208
- mergedAt: Instant | null;
209
- mergeCommit: CommitSha | null;
210
- commits: {
211
- sha: CommitSha;
212
- message: string;
213
- }[];
214
- }
215
- export interface Clock {
216
- now: () => Instant;
217
- }
218
- export type NewId = () => string;