@boxxy/model 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -2
- package/dist/actor-ref-schema.d.ts +2 -0
- package/dist/brand-schemas.d.ts +26 -0
- package/dist/build-applied-change.d.ts +13 -0
- package/dist/build-close-out-schema.d.ts +3 -0
- package/dist/build-item-views.d.ts +2 -0
- package/dist/define-admission.d.ts +3 -0
- package/dist/define-gate.d.ts +3 -0
- package/dist/define-signal.d.ts +3 -0
- package/dist/derive-item-state.d.ts +2 -0
- package/dist/fact-schemas.d.ts +5 -0
- package/dist/find-slot-take.d.ts +5 -0
- package/dist/format-key-path.d.ts +1 -0
- package/dist/friction-schema.d.ts +3 -0
- package/dist/index.d.ts +24 -1
- package/dist/live-levers.d.ts +2 -0
- package/dist/outbox-fact-schema.d.ts +3 -0
- package/dist/row-schemas.d.ts +5 -0
- package/dist/signal-key.d.ts +3 -0
- package/dist/test-utils/build-mock-attempt-row.d.ts +2 -0
- package/dist/test-utils/build-mock-evidence-row.d.ts +2 -0
- package/dist/test-utils/build-mock-fact-id.d.ts +2 -0
- package/dist/test-utils/build-mock-frame-item.d.ts +2 -0
- package/dist/test-utils/build-mock-item-row.d.ts +2 -0
- package/dist/test-utils/build-mock-item-rows.d.ts +2 -0
- package/dist/test-utils/build-mock-item-view.d.ts +2 -0
- package/dist/test-utils/build-mock-lease-row.d.ts +2 -0
- package/dist/test-utils/build-mock-lever-row.d.ts +2 -0
- package/dist/test-utils/build-mock-link-row.d.ts +2 -0
- package/dist/test-utils/build-mock-pull-request-row.d.ts +2 -0
- package/dist/test-utils/build-mock-snapshot.d.ts +2 -0
- package/dist/test-utils/seed-faker.d.ts +1 -0
- package/dist/to-json-value.d.ts +2 -0
- package/dist/types/core.d.ts +233 -0
- package/dist/types/dispatch.d.ts +82 -0
- package/dist/types/facts.d.ts +154 -0
- package/dist/types/planning.d.ts +94 -0
- package/dist/types/ports.d.ts +218 -0
- package/dist/types/registries.d.ts +150 -0
- package/package.json +9 -2
- package/src/actor-ref-schema.ts +9 -0
- package/src/brand-schemas.ts +46 -0
- package/src/build-applied-change.ts +71 -0
- package/src/build-close-out-schema.ts +28 -0
- package/src/build-item-views.ts +128 -0
- package/src/define-admission.ts +6 -0
- package/src/define-gate.ts +6 -0
- package/src/define-signal.ts +6 -0
- package/src/derive-item-state.ts +76 -0
- package/src/fact-schemas.ts +132 -0
- package/src/find-slot-take.ts +12 -0
- package/src/format-key-path.ts +19 -0
- package/src/friction-schema.ts +10 -0
- package/src/index.ts +196 -1
- package/src/live-levers.ts +22 -0
- package/src/outbox-fact-schema.ts +25 -0
- package/src/row-schemas.ts +89 -0
- package/src/signal-key.ts +7 -0
- package/src/test-utils/build-mock-attempt-row.ts +37 -0
- package/src/test-utils/build-mock-evidence-row.ts +17 -0
- package/src/test-utils/build-mock-fact-id.ts +7 -0
- package/src/test-utils/build-mock-frame-item.ts +9 -0
- package/src/test-utils/build-mock-item-row.ts +22 -0
- package/src/test-utils/build-mock-item-rows.ts +14 -0
- package/src/test-utils/build-mock-item-view.ts +8 -0
- package/src/test-utils/build-mock-lease-row.ts +15 -0
- package/src/test-utils/build-mock-lever-row.ts +17 -0
- package/src/test-utils/build-mock-link-row.ts +15 -0
- package/src/test-utils/build-mock-pull-request-row.ts +16 -0
- package/src/test-utils/build-mock-snapshot.ts +5 -0
- package/src/test-utils/seed-faker.ts +3 -0
- package/src/to-json-value.ts +25 -0
- package/src/types/core.ts +299 -0
- package/src/types/dispatch.ts +95 -0
- package/src/types/facts.ts +166 -0
- package/src/types/planning.ts +136 -0
- package/src/types/ports.ts +262 -0
- package/src/types/registries.ts +185 -0
- package/dist/package-name.d.ts +0 -1
- package/src/package-name.ts +0 -1
package/README.md
CHANGED
|
@@ -5,12 +5,17 @@
|
|
|
5
5
|
<a href="https://www.npmjs.com/package/@boxxy/model"><img src="https://img.shields.io/npm/v/@boxxy/model" alt="npm version"></a>
|
|
6
6
|
<a href="./LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue" alt="MIT license"></a>
|
|
7
7
|
</p>
|
|
8
|
+
|
|
9
|
+
<p>
|
|
10
|
+
<a href="../../docs/design/boxxy/README.md">Documentation</a>
|
|
11
|
+
</p>
|
|
8
12
|
</div>
|
|
9
13
|
|
|
10
14
|
The types that boxxy's packages share, with the fact catalog and its schemas.
|
|
11
15
|
|
|
12
|
-
|
|
13
|
-
|
|
16
|
+
Every boxxy package that reads or writes a store row, a fact or a port imports its types from here.
|
|
17
|
+
The package does no I/O: it takes the time as an argument, and it holds only types, zod schemas and
|
|
18
|
+
pure functions.
|
|
14
19
|
|
|
15
20
|
## Install
|
|
16
21
|
|
|
@@ -21,3 +26,23 @@ bun add @boxxy/model
|
|
|
21
26
|
```
|
|
22
27
|
|
|
23
28
|
The package runs on [Bun](https://bun.sh) 1.3 or newer.
|
|
29
|
+
|
|
30
|
+
## Features
|
|
31
|
+
|
|
32
|
+
- The branded ids and names, with a zod schema for each in `brandSchemas`.
|
|
33
|
+
- The store rows, the port interfaces, the plug-in interfaces and the loaded rules.
|
|
34
|
+
- The fact catalog, with a zod schema for each fact type's payload in `factSchemas`
|
|
35
|
+
([facts and the outbox](../../docs/design/boxxy/slice-1.md#facts-and-the-outbox)).
|
|
36
|
+
- `BuildCloseOut` and its schema, `buildCloseOutSchema`
|
|
37
|
+
([the build close-out](../../docs/design/boxxy/slice-1.md#the-build-close-out)).
|
|
38
|
+
- `deriveItemState`, which derives an item's state from its rows
|
|
39
|
+
([derived item state](../../docs/design/boxxy/slice-1.md#derived-item-state)).
|
|
40
|
+
- `liveLevers`, which drops the levers a later undo lever cancels and those past their expiry.
|
|
41
|
+
- `signalKey`, which builds a signal's key from its name and the content hash of its parameters.
|
|
42
|
+
- `defineSignal`, `defineGate` and `defineAdmission`, which register a plug-in with its parameter
|
|
43
|
+
type hidden.
|
|
44
|
+
|
|
45
|
+
## Documentation
|
|
46
|
+
|
|
47
|
+
The [boxxy design docs](../../docs/design/boxxy/README.md) describe each type, and the
|
|
48
|
+
[interface sketches](../../docs/design/boxxy/sketches/README.md) give its shape.
|
|
@@ -0,0 +1,2 @@
|
|
|
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">}`>]>;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const brandSchemas: {
|
|
3
|
+
instant: z.core.$ZodBranded<z.ZodNumber, "Instant", "out">;
|
|
4
|
+
itemId: z.core.$ZodBranded<z.ZodString, "ItemId", "out">;
|
|
5
|
+
attemptId: z.core.$ZodBranded<z.ZodString, "AttemptId", "out">;
|
|
6
|
+
decisionId: z.core.$ZodBranded<z.ZodString, "DecisionId", "out">;
|
|
7
|
+
factId: z.core.$ZodBranded<z.ZodTemplateLiteral<`manual:${string}`>, "FactId", "out">;
|
|
8
|
+
runnerId: z.core.$ZodBranded<z.ZodString, "RunnerId", "out">;
|
|
9
|
+
atcSessionId: z.core.$ZodBranded<z.ZodString, "AtcSessionId", "out">;
|
|
10
|
+
agentSessionId: z.core.$ZodBranded<z.ZodString, "AgentSessionId", "out">;
|
|
11
|
+
commitSha: z.core.$ZodBranded<z.ZodString, "CommitSha", "out">;
|
|
12
|
+
repoName: z.core.$ZodBranded<z.ZodString, "RepoName", "out">;
|
|
13
|
+
criterionId: z.core.$ZodBranded<z.ZodString, "CriterionId", "out">;
|
|
14
|
+
itemKindName: z.core.$ZodBranded<z.ZodString, "ItemKindName", "out">;
|
|
15
|
+
linkTypeName: z.core.$ZodBranded<z.ZodString, "LinkTypeName", "out">;
|
|
16
|
+
phaseName: z.core.$ZodBranded<z.ZodString, "PhaseName", "out">;
|
|
17
|
+
pipelineName: z.core.$ZodBranded<z.ZodString, "PipelineName", "out">;
|
|
18
|
+
poolName: z.core.$ZodBranded<z.ZodString, "PoolName", "out">;
|
|
19
|
+
recipeName: z.core.$ZodBranded<z.ZodString, "RecipeName", "out">;
|
|
20
|
+
workerKindName: z.core.$ZodBranded<z.ZodString, "WorkerKindName", "out">;
|
|
21
|
+
sourceName: z.core.$ZodBranded<z.ZodString, "SourceName", "out">;
|
|
22
|
+
streamName: z.core.$ZodBranded<z.ZodString, "StreamName", "out">;
|
|
23
|
+
recipeHash: z.core.$ZodBranded<z.core.$ZodBranded<z.ZodString, "ContentHash", "out">, "RecipeHash", "out">;
|
|
24
|
+
snapshotHash: z.core.$ZodBranded<z.core.$ZodBranded<z.ZodString, "ContentHash", "out">, "SnapshotHash", "out">;
|
|
25
|
+
rulesVersion: z.core.$ZodBranded<z.core.$ZodBranded<z.ZodString, "ContentHash", "out">, "RulesVersion", "out">;
|
|
26
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
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'>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function formatKeyPath(segments: readonly PropertyKey[]): string;
|
package/dist/index.d.ts
CHANGED
|
@@ -1 +1,24 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export type { ContentHash, JsonValue } from '@boxxy/content-hash';
|
|
2
|
+
export { brandSchemas } from './brand-schemas.ts';
|
|
3
|
+
export { buildAppliedChange, type ChangeAssignments, type TakenSlot, } from './build-applied-change.ts';
|
|
4
|
+
export { buildCloseOutSchema } from './build-close-out-schema.ts';
|
|
5
|
+
export { buildItemViews } from './build-item-views.ts';
|
|
6
|
+
export { defineAdmission } from './define-admission.ts';
|
|
7
|
+
export { defineGate } from './define-gate.ts';
|
|
8
|
+
export { defineSignal } from './define-signal.ts';
|
|
9
|
+
export { deriveItemState } from './derive-item-state.ts';
|
|
10
|
+
export { factSchemas } from './fact-schemas.ts';
|
|
11
|
+
export { findSlotTake, type SlotTake } from './find-slot-take.ts';
|
|
12
|
+
export { formatKeyPath } from './format-key-path.ts';
|
|
13
|
+
export { frictionSchema } from './friction-schema.ts';
|
|
14
|
+
export { liveLevers } from './live-levers.ts';
|
|
15
|
+
export { outboxFactSchema } from './outbox-fact-schema.ts';
|
|
16
|
+
export { rowSchemas } from './row-schemas.ts';
|
|
17
|
+
export { signalKey } from './signal-key.ts';
|
|
18
|
+
export { toJSONValue } from './to-json-value.ts';
|
|
19
|
+
export type { Actor, ActorRef, AgentSessionId, AtcSessionId, AttemptId, AttemptRow, AttemptSessionRow, AttemptState, CommitSha, ConceptPin, Criterion, CriterionId, DecisionId, DecisionRow, DerivedState, Effort, EvidenceKind, EvidenceRow, EvidenceSource, FactId, FaultRecord, ForcedFailure, Instant, ItemId, ItemKindName, ItemRow, ItemRows, ItemSetRows, ItemState, ItemView, ItemWithLevers, KnownFailure, LeaseRow, LeverKind, LeverRow, LinkRow, LinkTypeName, LiveAttemptState, LoadedRecipe, MaxAttemptsByKind, Minutes, ObservationBoundary, PhaseName, PipelineName, PoolName, PoolSlotRow, PullRequestRef, PullRequestRow, Recipe, RecipeHash, RecipeMaterial, RecipeName, RepoName, ResolvedRecipe, RulesVersion, RunnerId, RunnerRow, SnapshotHash, SourceName, StreamName, WaitingReason, WorkerKindName, } from './types/core.ts';
|
|
20
|
+
export type { Claim, CloseOutContext, CloseOutParse, CloseOutParser, CloseOutProblem, ReconcileAction, ReconcileTable, SettleInput, Settlement, SettleRule, SpawnContext, } from './types/dispatch.ts';
|
|
21
|
+
export type { BuildCloseOut, EntityRef, FactEnvelope, FactType, Friction, FrictionTargetKind, LinkPayload, NewFact, OpenItem, OutboxFact, SliceOneFacts, } from './types/facts.ts';
|
|
22
|
+
export type { Admission, AdmissionGrant, AdmissionName, Decision, Fault, Frame, FrameItem, FrameValues, Gate, GateName, Hold, Lift, Pick, PlanContext, Pool, PropagationLine, Signal, SignalKey, SignalName, Snapshot, View, ViewName, Waiver, WaiverName, } from './types/planning.ts';
|
|
23
|
+
export type { AnyNewFact, ApplyResult, ClaimStore, Clock, CostReader, CostToLandInput, CostToLandRow, FactSink, Forge, ItemDetailRows, ItemFilter, NewId, PullRequestReading, RowWrite, SessionFault, SessionReading, SpawnRequest, StartOutcome, StoreChange, StoreReader, StoreTx, TableName, Tables, WorkerKind, } from './types/ports.ts';
|
|
24
|
+
export type { Concept, ConceptEntry, ConceptName, FilterField, KindRules, LoadedRules, LoadRejection, LoadRejectionReason, LoadResult, ParamKindName, ParamKinds, Pipeline, PipelineStep, PlainKinds, PluginKindName, PluginRef, Registered, Registry, Resolved, RulesFile, Schema, SignalRef, } from './types/registries.ts';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import type { ContentHash, JsonValue } from '@boxxy/content-hash';
|
|
2
|
+
import type { z } from 'zod';
|
|
3
|
+
import type { brandSchemas } from '../brand-schemas.ts';
|
|
4
|
+
import type { BuildCloseOut } from './facts.ts';
|
|
5
|
+
type BrandOf<K extends keyof typeof brandSchemas> = z.output<(typeof brandSchemas)[K]>;
|
|
6
|
+
export type Instant = BrandOf<'instant'>;
|
|
7
|
+
export type Minutes = number;
|
|
8
|
+
export type ItemId = BrandOf<'itemId'>;
|
|
9
|
+
export type AttemptId = BrandOf<'attemptId'>;
|
|
10
|
+
export type DecisionId = BrandOf<'decisionId'>;
|
|
11
|
+
export type FactId = BrandOf<'factId'>;
|
|
12
|
+
export type RunnerId = BrandOf<'runnerId'>;
|
|
13
|
+
export type AtcSessionId = BrandOf<'atcSessionId'>;
|
|
14
|
+
export type AgentSessionId = BrandOf<'agentSessionId'>;
|
|
15
|
+
export type CommitSha = BrandOf<'commitSha'>;
|
|
16
|
+
export type RepoName = BrandOf<'repoName'>;
|
|
17
|
+
export type CriterionId = BrandOf<'criterionId'>;
|
|
18
|
+
export interface PullRequestRef {
|
|
19
|
+
readonly repo: RepoName;
|
|
20
|
+
readonly number: number;
|
|
21
|
+
}
|
|
22
|
+
export type ItemKindName = BrandOf<'itemKindName'>;
|
|
23
|
+
export type LinkTypeName = BrandOf<'linkTypeName'>;
|
|
24
|
+
export type PhaseName = BrandOf<'phaseName'>;
|
|
25
|
+
export type PipelineName = BrandOf<'pipelineName'>;
|
|
26
|
+
export type PoolName = BrandOf<'poolName'>;
|
|
27
|
+
export type RecipeName = BrandOf<'recipeName'>;
|
|
28
|
+
export type WorkerKindName = BrandOf<'workerKindName'>;
|
|
29
|
+
export type SourceName = BrandOf<'sourceName'>;
|
|
30
|
+
export type StreamName = BrandOf<'streamName'>;
|
|
31
|
+
export type LeverKind = `${string}.${string}`;
|
|
32
|
+
export type RecipeHash = BrandOf<'recipeHash'>;
|
|
33
|
+
export type SnapshotHash = BrandOf<'snapshotHash'>;
|
|
34
|
+
export type RulesVersion = BrandOf<'rulesVersion'>;
|
|
35
|
+
export interface ConceptPin {
|
|
36
|
+
readonly ref: `${string}@${number}`;
|
|
37
|
+
readonly sourceHash: ContentHash;
|
|
38
|
+
}
|
|
39
|
+
export type Actor = {
|
|
40
|
+
readonly kind: 'owner';
|
|
41
|
+
} | {
|
|
42
|
+
readonly kind: 'attempt';
|
|
43
|
+
readonly attempt: AttemptId;
|
|
44
|
+
} | {
|
|
45
|
+
readonly kind: 'runner';
|
|
46
|
+
readonly runner: RunnerId;
|
|
47
|
+
} | {
|
|
48
|
+
readonly kind: 'hook';
|
|
49
|
+
readonly attempt: AttemptId;
|
|
50
|
+
};
|
|
51
|
+
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';
|
|
53
|
+
export interface Criterion {
|
|
54
|
+
readonly id: CriterionId;
|
|
55
|
+
readonly text: string;
|
|
56
|
+
readonly evidence: readonly FactId[];
|
|
57
|
+
}
|
|
58
|
+
export interface ItemRow {
|
|
59
|
+
readonly id: ItemId;
|
|
60
|
+
readonly kind: ItemKindName;
|
|
61
|
+
readonly repo: RepoName;
|
|
62
|
+
readonly title: string;
|
|
63
|
+
readonly outcome: string;
|
|
64
|
+
readonly acceptance: readonly Criterion[];
|
|
65
|
+
readonly foundInAttempt: AttemptId | null;
|
|
66
|
+
readonly filedBy: ActorRef;
|
|
67
|
+
readonly filedAt: Instant;
|
|
68
|
+
readonly closedAt: Instant | null;
|
|
69
|
+
readonly closeReason: string | null;
|
|
70
|
+
}
|
|
71
|
+
export type ItemState = 'idea' | 'ready' | 'running' | 'blocked' | 'waiting' | 'done' | 'archived';
|
|
72
|
+
export type WaitingReason = 'PR open' | 'no PR linked' | 'attempts used up';
|
|
73
|
+
export type DerivedState = {
|
|
74
|
+
readonly state: Exclude<ItemState, 'waiting'>;
|
|
75
|
+
} | {
|
|
76
|
+
readonly state: 'waiting';
|
|
77
|
+
readonly reason: WaitingReason;
|
|
78
|
+
};
|
|
79
|
+
export interface ItemView extends ItemRow {
|
|
80
|
+
readonly derived: DerivedState;
|
|
81
|
+
}
|
|
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 {
|
|
104
|
+
readonly source: ItemId;
|
|
105
|
+
readonly target: ItemId;
|
|
106
|
+
readonly type: LinkTypeName;
|
|
107
|
+
readonly addedBy: ActorRef;
|
|
108
|
+
readonly addedAt: Instant;
|
|
109
|
+
readonly removedAt: Instant | null;
|
|
110
|
+
}
|
|
111
|
+
export interface LeverRow {
|
|
112
|
+
readonly seq: number;
|
|
113
|
+
readonly kind: LeverKind;
|
|
114
|
+
readonly item: ItemId;
|
|
115
|
+
readonly until: Instant | null;
|
|
116
|
+
readonly expiresAt: Instant | null;
|
|
117
|
+
readonly reason: string | null;
|
|
118
|
+
readonly actor: ActorRef;
|
|
119
|
+
readonly at: Instant;
|
|
120
|
+
}
|
|
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'>;
|
|
125
|
+
export interface AttemptRow {
|
|
126
|
+
readonly id: AttemptId;
|
|
127
|
+
readonly item: ItemId;
|
|
128
|
+
readonly phase: PhaseName;
|
|
129
|
+
readonly number: number;
|
|
130
|
+
readonly runner: RunnerId;
|
|
131
|
+
readonly recipeHash: RecipeHash;
|
|
132
|
+
readonly rulesVersion: RulesVersion;
|
|
133
|
+
readonly pool: PoolName;
|
|
134
|
+
readonly slot: number;
|
|
135
|
+
readonly slotGen: number;
|
|
136
|
+
readonly leaseGen: number;
|
|
137
|
+
readonly spawnRequest: JsonValue;
|
|
138
|
+
readonly spawnRequestHash: ContentHash;
|
|
139
|
+
readonly state: AttemptState;
|
|
140
|
+
readonly failure: string | null;
|
|
141
|
+
readonly atcSession: AtcSessionId | null;
|
|
142
|
+
readonly closeOut: BuildCloseOut | null;
|
|
143
|
+
readonly claimedAt: Instant;
|
|
144
|
+
readonly startedAt: Instant | null;
|
|
145
|
+
readonly endedAt: Instant | null;
|
|
146
|
+
}
|
|
147
|
+
export interface AttemptSessionRow {
|
|
148
|
+
readonly attempt: AttemptId;
|
|
149
|
+
readonly agentSession: AgentSessionId;
|
|
150
|
+
readonly atcSession: AtcSessionId;
|
|
151
|
+
readonly seenAt: Instant;
|
|
152
|
+
}
|
|
153
|
+
export interface LeaseRow {
|
|
154
|
+
readonly item: ItemId;
|
|
155
|
+
readonly phase: PhaseName;
|
|
156
|
+
readonly attempt: AttemptId;
|
|
157
|
+
readonly gen: number;
|
|
158
|
+
readonly takenAt: Instant;
|
|
159
|
+
readonly releasedAt: Instant | null;
|
|
160
|
+
}
|
|
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;
|
|
167
|
+
}
|
|
168
|
+
export interface ObservationBoundary {
|
|
169
|
+
readonly storeVersion: number;
|
|
170
|
+
readonly pepysOffsets: Readonly<Record<StreamName, number>>;
|
|
171
|
+
}
|
|
172
|
+
export interface DecisionRow {
|
|
173
|
+
readonly id: DecisionId;
|
|
174
|
+
readonly attempt: AttemptId;
|
|
175
|
+
readonly item: ItemId;
|
|
176
|
+
readonly pool: PoolName;
|
|
177
|
+
readonly rulesVersion: RulesVersion;
|
|
178
|
+
readonly snapshotHash: SnapshotHash;
|
|
179
|
+
readonly storeVersion: number;
|
|
180
|
+
readonly pepysOffsets: ObservationBoundary['pepysOffsets'];
|
|
181
|
+
readonly faults: readonly FaultRecord[];
|
|
182
|
+
readonly at: Instant;
|
|
183
|
+
}
|
|
184
|
+
export interface FaultRecord {
|
|
185
|
+
readonly plugin: string;
|
|
186
|
+
readonly kind: 'signal' | 'gate' | 'waiver' | 'admission' | 'propagation' | 'filter-field';
|
|
187
|
+
readonly item: ItemId | null;
|
|
188
|
+
readonly error: string;
|
|
189
|
+
}
|
|
190
|
+
export type EvidenceSource = 'hook' | 'trailer' | 'agent' | 'watch';
|
|
191
|
+
export interface EvidenceRow {
|
|
192
|
+
readonly factId: FactId;
|
|
193
|
+
readonly attempt: AttemptId;
|
|
194
|
+
readonly kind: EvidenceKind;
|
|
195
|
+
readonly ref: string;
|
|
196
|
+
readonly observed: string | null;
|
|
197
|
+
readonly source: EvidenceSource;
|
|
198
|
+
readonly at: Instant;
|
|
199
|
+
}
|
|
200
|
+
export interface PullRequestRow {
|
|
201
|
+
readonly repo: RepoName;
|
|
202
|
+
readonly number: number;
|
|
203
|
+
readonly attempt: AttemptId;
|
|
204
|
+
readonly state: 'open' | 'closed' | 'merged';
|
|
205
|
+
readonly mergedAt: Instant | null;
|
|
206
|
+
readonly mergeCommit: CommitSha | null;
|
|
207
|
+
readonly checkedAt: Instant;
|
|
208
|
+
}
|
|
209
|
+
export interface RunnerRow {
|
|
210
|
+
readonly id: RunnerId;
|
|
211
|
+
readonly heartbeatAt: Instant;
|
|
212
|
+
readonly paused: boolean;
|
|
213
|
+
}
|
|
214
|
+
export type Effort = 'low' | 'medium' | 'high' | 'xhigh' | 'max';
|
|
215
|
+
export interface Recipe {
|
|
216
|
+
readonly agent: string;
|
|
217
|
+
readonly model: string;
|
|
218
|
+
readonly effort: Effort;
|
|
219
|
+
readonly prompt: string;
|
|
220
|
+
readonly source: SourceName;
|
|
221
|
+
}
|
|
222
|
+
export interface RecipeMaterial {
|
|
223
|
+
readonly name: RecipeName;
|
|
224
|
+
readonly recipe: Recipe;
|
|
225
|
+
readonly promptHash: ContentHash;
|
|
226
|
+
readonly pluginFolderHash: ContentHash;
|
|
227
|
+
readonly rulesVersion: RulesVersion;
|
|
228
|
+
}
|
|
229
|
+
export type LoadedRecipe = Omit<RecipeMaterial, 'pluginFolderHash'>;
|
|
230
|
+
export interface ResolvedRecipe extends RecipeMaterial {
|
|
231
|
+
readonly hash: RecipeHash;
|
|
232
|
+
}
|
|
233
|
+
export {};
|
|
@@ -0,0 +1,82 @@
|
|
|
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
|
+
}
|