@knpkv/herdr-work 0.2.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 knpkv
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,7 @@
1
+ # @knpkv/herdr-work
2
+
3
+ Durable fleet work checkpoints and the Rly departure-board projection used by the Herdr control surface.
4
+
5
+ Each `WorkGoalCheckpoint` stores a complete, Schema-decoded goal state at its exact durable timestamp. `projectWorkSnapshots` selects the latest recorded checkpoint at now, 24 hours, 7 days, and 30 days. A goal does not appear before its creation checkpoint, and missing history is never synthesized.
6
+
7
+ `WorkStore` persists events in SQLite. Recording the exact same checkpoint again is an idempotent replay; reusing an event ID or goal timestamp with changed content returns `WorkCheckpointConflictError`. `makeWorkService` is the small runtime interface for recording checkpoints and reading all four snapshots. `WorkBoard` renders the projection and links only through the persisted `AgentConnectTarget`.
@@ -0,0 +1,23 @@
1
+ import { Schema } from "effect";
2
+ declare const WorkProjectionError_base: Schema.Class<WorkProjectionError, Schema.TaggedStruct<"WorkProjectionError", {
3
+ readonly cause: Schema.Defect;
4
+ readonly detail: Schema.String;
5
+ readonly reason: Schema.Literals<readonly ["malformed", "duplicate_event", "ambiguous_checkpoint", "inconsistent_history", "capacity_exceeded"]>;
6
+ }>, import("effect/Cause").YieldableError>;
7
+ export declare class WorkProjectionError extends WorkProjectionError_base {
8
+ }
9
+ declare const WorkStoreError_base: Schema.Class<WorkStoreError, Schema.TaggedStruct<"WorkStoreError", {
10
+ readonly cause: Schema.Defect;
11
+ readonly operation: Schema.String;
12
+ }>, import("effect/Cause").YieldableError>;
13
+ export declare class WorkStoreError extends WorkStoreError_base {
14
+ }
15
+ declare const WorkCheckpointConflictError_base: Schema.Class<WorkCheckpointConflictError, Schema.TaggedStruct<"WorkCheckpointConflictError", {
16
+ readonly eventId: Schema.String;
17
+ readonly goalId: Schema.String;
18
+ readonly occurredAt: Schema.Number;
19
+ }>, import("effect/Cause").YieldableError>;
20
+ export declare class WorkCheckpointConflictError extends WorkCheckpointConflictError_base {
21
+ }
22
+ export {};
23
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;;;;;;AAE/B,qBAAa,mBAAoB,SAAQ,wBAaxC;CAAG;;;;;AAEJ,qBAAa,cAAe,SAAQ,mBAGnC;CAAG;;;;;;AAEJ,qBAAa,2BAA4B,SAAQ,gCAOhD;CAAG"}
package/dist/errors.js ADDED
@@ -0,0 +1,22 @@
1
+ import { Schema } from "effect";
2
+ export class WorkProjectionError extends Schema.TaggedError()("WorkProjectionError", {
3
+ cause: Schema.Defect(),
4
+ detail: Schema.String,
5
+ reason: Schema.Literals([
6
+ "malformed",
7
+ "duplicate_event",
8
+ "ambiguous_checkpoint",
9
+ "inconsistent_history",
10
+ "capacity_exceeded"
11
+ ])
12
+ }) {
13
+ }
14
+ export class WorkStoreError extends Schema.TaggedError()("WorkStoreError", { cause: Schema.Defect(), operation: Schema.String }) {
15
+ }
16
+ export class WorkCheckpointConflictError extends Schema.TaggedError()("WorkCheckpointConflictError", {
17
+ eventId: Schema.String,
18
+ goalId: Schema.String,
19
+ occurredAt: Schema.Number
20
+ }) {
21
+ }
22
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE/B,MAAM,OAAO,mBAAoB,SAAQ,MAAM,CAAC,WAAW,EAAuB,CAChF,qBAAqB,EACrB;IACE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE;IACtB,MAAM,EAAE,MAAM,CAAC,MAAM;IACrB,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC;QACtB,WAAW;QACX,iBAAiB;QACjB,sBAAsB;QACtB,sBAAsB;QACtB,mBAAmB;KACpB,CAAC;CACH,CACF;CAAG;AAEJ,MAAM,OAAO,cAAe,SAAQ,MAAM,CAAC,WAAW,EAAkB,CACtE,gBAAgB,EAChB,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,CACrD;CAAG;AAEJ,MAAM,OAAO,2BAA4B,SAAQ,MAAM,CAAC,WAAW,EAA+B,CAChG,6BAA6B,EAC7B;IACE,OAAO,EAAE,MAAM,CAAC,MAAM;IACtB,MAAM,EAAE,MAAM,CAAC,MAAM;IACrB,UAAU,EAAE,MAAM,CAAC,MAAM;CAC1B,CACF;CAAG"}
@@ -0,0 +1,7 @@
1
+ export * from "./errors.js";
2
+ export * from "./model.js";
3
+ export * from "./projection.js";
4
+ export * from "./service.js";
5
+ export * from "./store.js";
6
+ export * from "./view.js";
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA;AAC1B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,cAAc,CAAA;AAC5B,cAAc,YAAY,CAAA;AAC1B,cAAc,WAAW,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
1
+ export * from "./errors.js";
2
+ export * from "./model.js";
3
+ export * from "./projection.js";
4
+ export * from "./service.js";
5
+ export * from "./store.js";
6
+ export * from "./view.js";
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA;AAC1B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,cAAc,CAAA;AAC5B,cAAc,YAAY,CAAA;AAC1B,cAAc,WAAW,CAAA"}
@@ -0,0 +1,294 @@
1
+ import { Schema } from "effect";
2
+ export declare const workHistoryMaxEvents = 16384;
3
+ export declare const workSnapshotMaxGoals = 1024;
4
+ export declare const WorkGoalId: Schema.String;
5
+ export type WorkGoalId = typeof WorkGoalId.Type;
6
+ export declare const WorkState: Schema.Literals<readonly ["planned", "working", "blocked", "review", "deployed", "completed"]>;
7
+ export type WorkState = typeof WorkState.Type;
8
+ export declare const DeliveryStage: Schema.Literals<readonly ["local", "review", "pull_request", "merged", "deployed"]>;
9
+ export type DeliveryStage = typeof DeliveryStage.Type;
10
+ export declare const WorkOwner: Schema.Struct<{
11
+ readonly id: Schema.String;
12
+ readonly name: Schema.String;
13
+ }>;
14
+ export interface WorkOwner extends Schema.Schema.Type<typeof WorkOwner> {
15
+ }
16
+ export declare const WorkRepository: Schema.Struct<{
17
+ readonly repository: Schema.String;
18
+ readonly branch: Schema.String;
19
+ }>;
20
+ export interface WorkRepository extends Schema.Schema.Type<typeof WorkRepository> {
21
+ }
22
+ export declare const WorkSpend: Schema.Struct<{
23
+ readonly currency: Schema.String;
24
+ readonly minorUnits: Schema.Number;
25
+ }>;
26
+ export interface WorkSpend extends Schema.Schema.Type<typeof WorkSpend> {
27
+ }
28
+ export declare const WorkBlocker: Schema.Struct<{
29
+ readonly summary: Schema.String;
30
+ readonly since: Schema.Number;
31
+ }>;
32
+ export interface WorkBlocker extends Schema.Schema.Type<typeof WorkBlocker> {
33
+ }
34
+ export declare const WorkGoal: Schema.Struct<{
35
+ readonly id: Schema.String;
36
+ readonly title: Schema.String;
37
+ readonly summary: Schema.String;
38
+ readonly detail: Schema.String;
39
+ readonly state: Schema.Literals<readonly ["planned", "working", "blocked", "review", "deployed", "completed"]>;
40
+ readonly owner: Schema.Struct<{
41
+ readonly id: Schema.String;
42
+ readonly name: Schema.String;
43
+ }>;
44
+ readonly repository: Schema.Struct<{
45
+ readonly repository: Schema.String;
46
+ readonly branch: Schema.String;
47
+ }>;
48
+ readonly spend: Schema.NullOr<Schema.Struct<{
49
+ readonly currency: Schema.String;
50
+ readonly minorUnits: Schema.Number;
51
+ }>>;
52
+ readonly delivery: Schema.Literals<readonly ["local", "review", "pull_request", "merged", "deployed"]>;
53
+ readonly blocker: Schema.NullOr<Schema.Struct<{
54
+ readonly summary: Schema.String;
55
+ readonly since: Schema.Number;
56
+ }>>;
57
+ readonly connectTarget: Schema.NullOr<Schema.Struct<{
58
+ readonly host: Schema.String;
59
+ readonly agentId: Schema.String;
60
+ readonly url: Schema.String;
61
+ }>>;
62
+ readonly createdAt: Schema.Number;
63
+ readonly updatedAt: Schema.Number;
64
+ }>;
65
+ export interface WorkGoal extends Schema.Schema.Type<typeof WorkGoal> {
66
+ }
67
+ export declare const WorkGoalCheckpoint: Schema.Struct<{
68
+ readonly version: Schema.Literal<"herdr.work.event.v1">;
69
+ readonly eventId: Schema.String;
70
+ readonly occurredAt: Schema.Number;
71
+ readonly goal: Schema.Struct<{
72
+ readonly id: Schema.String;
73
+ readonly title: Schema.String;
74
+ readonly summary: Schema.String;
75
+ readonly detail: Schema.String;
76
+ readonly state: Schema.Literals<readonly ["planned", "working", "blocked", "review", "deployed", "completed"]>;
77
+ readonly owner: Schema.Struct<{
78
+ readonly id: Schema.String;
79
+ readonly name: Schema.String;
80
+ }>;
81
+ readonly repository: Schema.Struct<{
82
+ readonly repository: Schema.String;
83
+ readonly branch: Schema.String;
84
+ }>;
85
+ readonly spend: Schema.NullOr<Schema.Struct<{
86
+ readonly currency: Schema.String;
87
+ readonly minorUnits: Schema.Number;
88
+ }>>;
89
+ readonly delivery: Schema.Literals<readonly ["local", "review", "pull_request", "merged", "deployed"]>;
90
+ readonly blocker: Schema.NullOr<Schema.Struct<{
91
+ readonly summary: Schema.String;
92
+ readonly since: Schema.Number;
93
+ }>>;
94
+ readonly connectTarget: Schema.NullOr<Schema.Struct<{
95
+ readonly host: Schema.String;
96
+ readonly agentId: Schema.String;
97
+ readonly url: Schema.String;
98
+ }>>;
99
+ readonly createdAt: Schema.Number;
100
+ readonly updatedAt: Schema.Number;
101
+ }>;
102
+ }>;
103
+ export interface WorkGoalCheckpoint extends Schema.Schema.Type<typeof WorkGoalCheckpoint> {
104
+ }
105
+ export declare const WorkSnapshotWindow: Schema.Literals<readonly ["now", "day", "week", "month"]>;
106
+ export type WorkSnapshotWindow = typeof WorkSnapshotWindow.Type;
107
+ export declare const WorkSnapshot: Schema.Struct<{
108
+ readonly window: Schema.Literals<readonly ["now", "day", "week", "month"]>;
109
+ readonly observedAt: Schema.Number;
110
+ readonly asOf: Schema.Number;
111
+ readonly goals: Schema.$Array<Schema.Struct<{
112
+ readonly id: Schema.String;
113
+ readonly title: Schema.String;
114
+ readonly summary: Schema.String;
115
+ readonly detail: Schema.String;
116
+ readonly state: Schema.Literals<readonly ["planned", "working", "blocked", "review", "deployed", "completed"]>;
117
+ readonly owner: Schema.Struct<{
118
+ readonly id: Schema.String;
119
+ readonly name: Schema.String;
120
+ }>;
121
+ readonly repository: Schema.Struct<{
122
+ readonly repository: Schema.String;
123
+ readonly branch: Schema.String;
124
+ }>;
125
+ readonly spend: Schema.NullOr<Schema.Struct<{
126
+ readonly currency: Schema.String;
127
+ readonly minorUnits: Schema.Number;
128
+ }>>;
129
+ readonly delivery: Schema.Literals<readonly ["local", "review", "pull_request", "merged", "deployed"]>;
130
+ readonly blocker: Schema.NullOr<Schema.Struct<{
131
+ readonly summary: Schema.String;
132
+ readonly since: Schema.Number;
133
+ }>>;
134
+ readonly connectTarget: Schema.NullOr<Schema.Struct<{
135
+ readonly host: Schema.String;
136
+ readonly agentId: Schema.String;
137
+ readonly url: Schema.String;
138
+ }>>;
139
+ readonly createdAt: Schema.Number;
140
+ readonly updatedAt: Schema.Number;
141
+ }>>;
142
+ }>;
143
+ export interface WorkSnapshot extends Schema.Schema.Type<typeof WorkSnapshot> {
144
+ }
145
+ export declare const WorkSnapshots: Schema.Struct<{
146
+ readonly observedAt: Schema.Number;
147
+ readonly now: Schema.Struct<{
148
+ readonly window: Schema.Literals<readonly ["now", "day", "week", "month"]>;
149
+ readonly observedAt: Schema.Number;
150
+ readonly asOf: Schema.Number;
151
+ readonly goals: Schema.$Array<Schema.Struct<{
152
+ readonly id: Schema.String;
153
+ readonly title: Schema.String;
154
+ readonly summary: Schema.String;
155
+ readonly detail: Schema.String;
156
+ readonly state: Schema.Literals<readonly ["planned", "working", "blocked", "review", "deployed", "completed"]>;
157
+ readonly owner: Schema.Struct<{
158
+ readonly id: Schema.String;
159
+ readonly name: Schema.String;
160
+ }>;
161
+ readonly repository: Schema.Struct<{
162
+ readonly repository: Schema.String;
163
+ readonly branch: Schema.String;
164
+ }>;
165
+ readonly spend: Schema.NullOr<Schema.Struct<{
166
+ readonly currency: Schema.String;
167
+ readonly minorUnits: Schema.Number;
168
+ }>>;
169
+ readonly delivery: Schema.Literals<readonly ["local", "review", "pull_request", "merged", "deployed"]>;
170
+ readonly blocker: Schema.NullOr<Schema.Struct<{
171
+ readonly summary: Schema.String;
172
+ readonly since: Schema.Number;
173
+ }>>;
174
+ readonly connectTarget: Schema.NullOr<Schema.Struct<{
175
+ readonly host: Schema.String;
176
+ readonly agentId: Schema.String;
177
+ readonly url: Schema.String;
178
+ }>>;
179
+ readonly createdAt: Schema.Number;
180
+ readonly updatedAt: Schema.Number;
181
+ }>>;
182
+ }>;
183
+ readonly day: Schema.Struct<{
184
+ readonly window: Schema.Literals<readonly ["now", "day", "week", "month"]>;
185
+ readonly observedAt: Schema.Number;
186
+ readonly asOf: Schema.Number;
187
+ readonly goals: Schema.$Array<Schema.Struct<{
188
+ readonly id: Schema.String;
189
+ readonly title: Schema.String;
190
+ readonly summary: Schema.String;
191
+ readonly detail: Schema.String;
192
+ readonly state: Schema.Literals<readonly ["planned", "working", "blocked", "review", "deployed", "completed"]>;
193
+ readonly owner: Schema.Struct<{
194
+ readonly id: Schema.String;
195
+ readonly name: Schema.String;
196
+ }>;
197
+ readonly repository: Schema.Struct<{
198
+ readonly repository: Schema.String;
199
+ readonly branch: Schema.String;
200
+ }>;
201
+ readonly spend: Schema.NullOr<Schema.Struct<{
202
+ readonly currency: Schema.String;
203
+ readonly minorUnits: Schema.Number;
204
+ }>>;
205
+ readonly delivery: Schema.Literals<readonly ["local", "review", "pull_request", "merged", "deployed"]>;
206
+ readonly blocker: Schema.NullOr<Schema.Struct<{
207
+ readonly summary: Schema.String;
208
+ readonly since: Schema.Number;
209
+ }>>;
210
+ readonly connectTarget: Schema.NullOr<Schema.Struct<{
211
+ readonly host: Schema.String;
212
+ readonly agentId: Schema.String;
213
+ readonly url: Schema.String;
214
+ }>>;
215
+ readonly createdAt: Schema.Number;
216
+ readonly updatedAt: Schema.Number;
217
+ }>>;
218
+ }>;
219
+ readonly week: Schema.Struct<{
220
+ readonly window: Schema.Literals<readonly ["now", "day", "week", "month"]>;
221
+ readonly observedAt: Schema.Number;
222
+ readonly asOf: Schema.Number;
223
+ readonly goals: Schema.$Array<Schema.Struct<{
224
+ readonly id: Schema.String;
225
+ readonly title: Schema.String;
226
+ readonly summary: Schema.String;
227
+ readonly detail: Schema.String;
228
+ readonly state: Schema.Literals<readonly ["planned", "working", "blocked", "review", "deployed", "completed"]>;
229
+ readonly owner: Schema.Struct<{
230
+ readonly id: Schema.String;
231
+ readonly name: Schema.String;
232
+ }>;
233
+ readonly repository: Schema.Struct<{
234
+ readonly repository: Schema.String;
235
+ readonly branch: Schema.String;
236
+ }>;
237
+ readonly spend: Schema.NullOr<Schema.Struct<{
238
+ readonly currency: Schema.String;
239
+ readonly minorUnits: Schema.Number;
240
+ }>>;
241
+ readonly delivery: Schema.Literals<readonly ["local", "review", "pull_request", "merged", "deployed"]>;
242
+ readonly blocker: Schema.NullOr<Schema.Struct<{
243
+ readonly summary: Schema.String;
244
+ readonly since: Schema.Number;
245
+ }>>;
246
+ readonly connectTarget: Schema.NullOr<Schema.Struct<{
247
+ readonly host: Schema.String;
248
+ readonly agentId: Schema.String;
249
+ readonly url: Schema.String;
250
+ }>>;
251
+ readonly createdAt: Schema.Number;
252
+ readonly updatedAt: Schema.Number;
253
+ }>>;
254
+ }>;
255
+ readonly month: Schema.Struct<{
256
+ readonly window: Schema.Literals<readonly ["now", "day", "week", "month"]>;
257
+ readonly observedAt: Schema.Number;
258
+ readonly asOf: Schema.Number;
259
+ readonly goals: Schema.$Array<Schema.Struct<{
260
+ readonly id: Schema.String;
261
+ readonly title: Schema.String;
262
+ readonly summary: Schema.String;
263
+ readonly detail: Schema.String;
264
+ readonly state: Schema.Literals<readonly ["planned", "working", "blocked", "review", "deployed", "completed"]>;
265
+ readonly owner: Schema.Struct<{
266
+ readonly id: Schema.String;
267
+ readonly name: Schema.String;
268
+ }>;
269
+ readonly repository: Schema.Struct<{
270
+ readonly repository: Schema.String;
271
+ readonly branch: Schema.String;
272
+ }>;
273
+ readonly spend: Schema.NullOr<Schema.Struct<{
274
+ readonly currency: Schema.String;
275
+ readonly minorUnits: Schema.Number;
276
+ }>>;
277
+ readonly delivery: Schema.Literals<readonly ["local", "review", "pull_request", "merged", "deployed"]>;
278
+ readonly blocker: Schema.NullOr<Schema.Struct<{
279
+ readonly summary: Schema.String;
280
+ readonly since: Schema.Number;
281
+ }>>;
282
+ readonly connectTarget: Schema.NullOr<Schema.Struct<{
283
+ readonly host: Schema.String;
284
+ readonly agentId: Schema.String;
285
+ readonly url: Schema.String;
286
+ }>>;
287
+ readonly createdAt: Schema.Number;
288
+ readonly updatedAt: Schema.Number;
289
+ }>>;
290
+ }>;
291
+ }>;
292
+ export interface WorkSnapshots extends Schema.Schema.Type<typeof WorkSnapshots> {
293
+ }
294
+ //# sourceMappingURL=model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAS/B,eAAO,MAAM,oBAAoB,QAAS,CAAA;AAC1C,eAAO,MAAM,oBAAoB,OAAQ,CAAA;AAEzC,eAAO,MAAM,UAAU,eAAa,CAAA;AACpC,MAAM,MAAM,UAAU,GAAG,OAAO,UAAU,CAAC,IAAI,CAAA;AAE/C,eAAO,MAAM,SAAS,gGAAwF,CAAA;AAC9G,MAAM,MAAM,SAAS,GAAG,OAAO,SAAS,CAAC,IAAI,CAAA;AAE7C,eAAO,MAAM,aAAa,qFAA6E,CAAA;AACvG,MAAM,MAAM,aAAa,GAAG,OAAO,aAAa,CAAC,IAAI,CAAA;AAErD,eAAO,MAAM,SAAS;;;EAAgD,CAAA;AACtE,MAAM,WAAW,SAAU,SAAQ,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,SAAS,CAAC;CAAG;AAE1E,eAAO,MAAM,cAAc;;;EAGzB,CAAA;AACF,MAAM,WAAW,cAAe,SAAQ,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,cAAc,CAAC;CAAG;AAEpF,eAAO,MAAM,SAAS;;;EAGpB,CAAA;AACF,MAAM,WAAW,SAAU,SAAQ,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,SAAS,CAAC;CAAG;AAE1E,eAAO,MAAM,WAAW;;;EAGtB,CAAA;AACF,MAAM,WAAW,WAAY,SAAQ,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,WAAW,CAAC;CAAG;AAE9E,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmBpB,CAAA;AACD,MAAM,WAAW,QAAS,SAAQ,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,QAAQ,CAAC;CAAG;AAExE,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAU9B,CAAA;AACD,MAAM,WAAW,kBAAmB,SAAQ,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,kBAAkB,CAAC;CAAG;AAE5F,eAAO,MAAM,kBAAkB,2DAAmD,CAAA;AAClF,MAAM,MAAM,kBAAkB,GAAG,OAAO,kBAAkB,CAAC,IAAI,CAAA;AAE/D,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAKvB,CAAA;AACF,MAAM,WAAW,YAAa,SAAQ,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,YAAY,CAAC;CAAG;AAEhF,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAMxB,CAAA;AACF,MAAM,WAAW,aAAc,SAAQ,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,aAAa,CAAC;CAAG"}
package/dist/model.js ADDED
@@ -0,0 +1,59 @@
1
+ import { AgentConnectTarget } from "@knpkv/herdr-fleet/model";
2
+ import { Schema } from "effect";
3
+ const Identifier = Schema.String.check(Schema.isNonEmpty(), Schema.isMaxLength(256));
4
+ const Text = Schema.String.check(Schema.isNonEmpty(), Schema.isMaxLength(4_096), Schema.isPattern(/^[^\p{Cc}]+$/u));
5
+ const Timestamp = Schema.Number.check(Schema.isInt(), Schema.isBetween({ minimum: 0, maximum: 8_640_000_000_000_000 }));
6
+ export const workHistoryMaxEvents = 16_384;
7
+ export const workSnapshotMaxGoals = 1_024;
8
+ export const WorkGoalId = Identifier;
9
+ export const WorkState = Schema.Literals(["planned", "working", "blocked", "review", "deployed", "completed"]);
10
+ export const DeliveryStage = Schema.Literals(["local", "review", "pull_request", "merged", "deployed"]);
11
+ export const WorkOwner = Schema.Struct({ id: Identifier, name: Text });
12
+ export const WorkRepository = Schema.Struct({
13
+ repository: Text,
14
+ branch: Text
15
+ });
16
+ export const WorkSpend = Schema.Struct({
17
+ currency: Schema.String.check(Schema.isPattern(/^[A-Z]{3}$/)),
18
+ minorUnits: Schema.Number.check(Schema.isInt(), Schema.isBetween({ minimum: 0, maximum: Number.MAX_SAFE_INTEGER }))
19
+ });
20
+ export const WorkBlocker = Schema.Struct({
21
+ summary: Text,
22
+ since: Timestamp
23
+ });
24
+ export const WorkGoal = Schema.Struct({
25
+ id: WorkGoalId,
26
+ title: Text,
27
+ summary: Text,
28
+ detail: Text,
29
+ state: WorkState,
30
+ owner: WorkOwner,
31
+ repository: WorkRepository,
32
+ spend: Schema.NullOr(WorkSpend),
33
+ delivery: DeliveryStage,
34
+ blocker: Schema.NullOr(WorkBlocker),
35
+ connectTarget: Schema.NullOr(AgentConnectTarget),
36
+ createdAt: Timestamp,
37
+ updatedAt: Timestamp
38
+ }).check(Schema.makeFilter((goal) => goal.updatedAt >= goal.createdAt && ((goal.state === "blocked") === (goal.blocker !== null)), { expected: "ordered goal timestamps and blocker present exactly for blocked state" }));
39
+ export const WorkGoalCheckpoint = Schema.Struct({
40
+ version: Schema.Literal("herdr.work.event.v1"),
41
+ eventId: Identifier,
42
+ occurredAt: Timestamp,
43
+ goal: WorkGoal
44
+ }).check(Schema.makeFilter((event) => event.occurredAt === event.goal.updatedAt, { expected: "checkpoint occurrence equal to the durable goal update timestamp" }));
45
+ export const WorkSnapshotWindow = Schema.Literals(["now", "day", "week", "month"]);
46
+ export const WorkSnapshot = Schema.Struct({
47
+ window: WorkSnapshotWindow,
48
+ observedAt: Timestamp,
49
+ asOf: Timestamp,
50
+ goals: Schema.Array(WorkGoal).check(Schema.isMaxLength(workSnapshotMaxGoals))
51
+ });
52
+ export const WorkSnapshots = Schema.Struct({
53
+ observedAt: Timestamp,
54
+ now: WorkSnapshot,
55
+ day: WorkSnapshot,
56
+ week: WorkSnapshot,
57
+ month: WorkSnapshot
58
+ });
59
+ //# sourceMappingURL=model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.js","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,151 @@
1
+ import { Effect } from "effect";
2
+ import { WorkProjectionError } from "./errors.js";
3
+ import { WorkGoalCheckpoint } from "./model.js";
4
+ export declare const projectWorkSnapshots: (input: readonly WorkGoalCheckpoint[], observedAt: number) => Effect.Effect<{
5
+ readonly observedAt: number;
6
+ readonly now: {
7
+ readonly window: "day" | "month" | "now" | "week";
8
+ readonly observedAt: number;
9
+ readonly asOf: number;
10
+ readonly goals: readonly {
11
+ readonly id: string;
12
+ readonly title: string;
13
+ readonly summary: string;
14
+ readonly detail: string;
15
+ readonly state: "blocked" | "completed" | "deployed" | "planned" | "review" | "working";
16
+ readonly owner: {
17
+ readonly id: string;
18
+ readonly name: string;
19
+ };
20
+ readonly repository: {
21
+ readonly repository: string;
22
+ readonly branch: string;
23
+ };
24
+ readonly spend: {
25
+ readonly currency: string;
26
+ readonly minorUnits: number;
27
+ } | null;
28
+ readonly delivery: "deployed" | "local" | "merged" | "pull_request" | "review";
29
+ readonly blocker: {
30
+ readonly summary: string;
31
+ readonly since: number;
32
+ } | null;
33
+ readonly connectTarget: {
34
+ readonly host: string;
35
+ readonly agentId: string;
36
+ readonly url: string;
37
+ } | null;
38
+ readonly createdAt: number;
39
+ readonly updatedAt: number;
40
+ }[];
41
+ };
42
+ readonly day: {
43
+ readonly window: "day" | "month" | "now" | "week";
44
+ readonly observedAt: number;
45
+ readonly asOf: number;
46
+ readonly goals: readonly {
47
+ readonly id: string;
48
+ readonly title: string;
49
+ readonly summary: string;
50
+ readonly detail: string;
51
+ readonly state: "blocked" | "completed" | "deployed" | "planned" | "review" | "working";
52
+ readonly owner: {
53
+ readonly id: string;
54
+ readonly name: string;
55
+ };
56
+ readonly repository: {
57
+ readonly repository: string;
58
+ readonly branch: string;
59
+ };
60
+ readonly spend: {
61
+ readonly currency: string;
62
+ readonly minorUnits: number;
63
+ } | null;
64
+ readonly delivery: "deployed" | "local" | "merged" | "pull_request" | "review";
65
+ readonly blocker: {
66
+ readonly summary: string;
67
+ readonly since: number;
68
+ } | null;
69
+ readonly connectTarget: {
70
+ readonly host: string;
71
+ readonly agentId: string;
72
+ readonly url: string;
73
+ } | null;
74
+ readonly createdAt: number;
75
+ readonly updatedAt: number;
76
+ }[];
77
+ };
78
+ readonly week: {
79
+ readonly window: "day" | "month" | "now" | "week";
80
+ readonly observedAt: number;
81
+ readonly asOf: number;
82
+ readonly goals: readonly {
83
+ readonly id: string;
84
+ readonly title: string;
85
+ readonly summary: string;
86
+ readonly detail: string;
87
+ readonly state: "blocked" | "completed" | "deployed" | "planned" | "review" | "working";
88
+ readonly owner: {
89
+ readonly id: string;
90
+ readonly name: string;
91
+ };
92
+ readonly repository: {
93
+ readonly repository: string;
94
+ readonly branch: string;
95
+ };
96
+ readonly spend: {
97
+ readonly currency: string;
98
+ readonly minorUnits: number;
99
+ } | null;
100
+ readonly delivery: "deployed" | "local" | "merged" | "pull_request" | "review";
101
+ readonly blocker: {
102
+ readonly summary: string;
103
+ readonly since: number;
104
+ } | null;
105
+ readonly connectTarget: {
106
+ readonly host: string;
107
+ readonly agentId: string;
108
+ readonly url: string;
109
+ } | null;
110
+ readonly createdAt: number;
111
+ readonly updatedAt: number;
112
+ }[];
113
+ };
114
+ readonly month: {
115
+ readonly window: "day" | "month" | "now" | "week";
116
+ readonly observedAt: number;
117
+ readonly asOf: number;
118
+ readonly goals: readonly {
119
+ readonly id: string;
120
+ readonly title: string;
121
+ readonly summary: string;
122
+ readonly detail: string;
123
+ readonly state: "blocked" | "completed" | "deployed" | "planned" | "review" | "working";
124
+ readonly owner: {
125
+ readonly id: string;
126
+ readonly name: string;
127
+ };
128
+ readonly repository: {
129
+ readonly repository: string;
130
+ readonly branch: string;
131
+ };
132
+ readonly spend: {
133
+ readonly currency: string;
134
+ readonly minorUnits: number;
135
+ } | null;
136
+ readonly delivery: "deployed" | "local" | "merged" | "pull_request" | "review";
137
+ readonly blocker: {
138
+ readonly summary: string;
139
+ readonly since: number;
140
+ } | null;
141
+ readonly connectTarget: {
142
+ readonly host: string;
143
+ readonly agentId: string;
144
+ readonly url: string;
145
+ } | null;
146
+ readonly createdAt: number;
147
+ readonly updatedAt: number;
148
+ }[];
149
+ };
150
+ }, WorkProjectionError, never>;
151
+ //# sourceMappingURL=projection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projection.d.ts","sourceRoot":"","sources":["../src/projection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAU,MAAM,QAAQ,CAAA;AACvC,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AACjD,OAAO,EAEL,kBAAkB,EAKnB,MAAM,YAAY,CAAA;AAkFnB,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8BAiB/B,CAAA"}