@hunsu/core 0.1.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.
@@ -0,0 +1,1263 @@
1
+ import { createHash } from "node:crypto";
2
+ import { gzipSync, gunzipSync } from "node:zlib";
3
+ import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
4
+ import { dirname, join } from "node:path";
5
+ import {
6
+ createDefaultHarness,
7
+ decodeArtifactActionDefinitionArray,
8
+ harnessEntityFromSnapshot,
9
+ err,
10
+ ok,
11
+ rootHarnessSnapshot,
12
+ tryProjectBoard,
13
+ tryApplyCommand,
14
+ validateHarnessEntity,
15
+ validateDomainEvent,
16
+ type Result
17
+ } from "@hunsu/protocol";
18
+ import type { AgentConversationRef, ArtifactActionDefinition, BoardProjection, Command, Destination, DomainEvent, ExecutorEntity, ExecutorId, GuardrailConfig, Harness, HubPackageLock, HunsuOrigin, MoveId, MoveRecord, NodeId, ExecutionPlan, PathId, MemberPath, PositiveInteger, ResourceEntity, WorktreeRef } from "@hunsu/protocol";
19
+ import { GitError } from "./errors.ts";
20
+ import { ensureGitRepository, git } from "./git.ts";
21
+ import { parseCommitSha, parseRuntimeChecksum } from "./primitives.ts";
22
+ import type { CommitSha, RuntimeChecksum } from "./primitives.ts";
23
+
24
+ export const HUNSU_COMPLETED_DESTINATIONS_PATH = ".hunsu/completed-destinations.hunsu";
25
+ export const HUNSU_DESTINATIONS_PATH = ".hunsu/destinations.hunsu";
26
+ export const HUNSU_HARNESS_PATH = ".hunsu/harness.hunsu";
27
+ export const HUNSU_EXECUTORS_PATH = ".hunsu/executors.hunsu";
28
+ export const HUNSU_RESOURCES_PATH = ".hunsu/resources.hunsu";
29
+ export const HUNSU_ARTIFACT_ACTIONS_PATH = ".hunsu/artifact-actions.hunsu";
30
+ export const HUNSU_CURRENT_EXECUTION_PATH = ".hunsu/current-execution.hunsu";
31
+ export const HUNSU_PREVIOUS_EXECUTION_PATH = ".hunsu/previous-execution.hunsu";
32
+ export const HUNSU_HUNSU_DRAFT_PATH = ".hunsu/hunsu-draft.hunsu";
33
+ export const HUNSU_RUNTIME_PATHS = [HUNSU_COMPLETED_DESTINATIONS_PATH, HUNSU_DESTINATIONS_PATH, HUNSU_HARNESS_PATH, HUNSU_EXECUTORS_PATH, HUNSU_RESOURCES_PATH, HUNSU_ARTIFACT_ACTIONS_PATH] as const;
34
+ export const HUNSU_LEGACY_STATE_PATH = ".hunsu/state.hunsu";
35
+ export const HUNSU_RUNTIME_ENCODING = "gzip+base64url";
36
+ export const HUNSU_DRAFT_RUNTIME_FILE_NAMES = ["destinations.json", "harness.json", "executors.json", "resources.json", "artifact-actions.json"] as const;
37
+ export const HUNSU_SELF_COMMIT_REF: MoveCommitRef = { type: "self" };
38
+ export const HUNSU_SELF_COMMIT_SENTINEL = "__HUNSU_SELF_COMMIT__";
39
+ const HUNSU_RUNTIME_HEADER = "HUNSU_RUNTIME_FILE_V1";
40
+ const LEGACY_STATE_HEADER = "HUNSU_STATE_V1";
41
+ const DOMAIN_EVENT_REF_PREFIX = "refs/hunsu/events";
42
+ const DOMAIN_EVENT_REF_FORMAT = "%(refname)\t%(objectname)\t%(objecttype)";
43
+ const DOMAIN_EVENT_REF_SEPARATOR = "\t";
44
+
45
+ export type DomainStore = {
46
+ root: string;
47
+ eventRefs: DomainEventRef[];
48
+ events: DomainEvent[];
49
+ board: BoardProjection;
50
+ runtimePaths: typeof HUNSU_RUNTIME_PATHS;
51
+ runtime: HunsuRuntimeState;
52
+ source: "worktree-runtime" | "reachable-runtime" | "legacy-state" | "legacy-refs" | "empty";
53
+ checksum: RuntimeChecksum;
54
+ commit?: CommitSha;
55
+ };
56
+
57
+ export type DomainEventRef = {
58
+ ref: string;
59
+ object: string;
60
+ objectType: string;
61
+ ordinal: number;
62
+ };
63
+
64
+ export type DomainStoreError = {
65
+ type: "DomainStoreError";
66
+ message: string;
67
+ };
68
+
69
+ export type CompletedDestinationEntry = {
70
+ destinationId: string;
71
+ title: string;
72
+ completedAt?: string;
73
+ resultCommit: CommitSha | typeof HUNSU_SELF_COMMIT_SENTINEL | MoveCommitRef;
74
+ moveId: MoveId;
75
+ harnessId?: string;
76
+ digest: {
77
+ summary: string;
78
+ evidence: string[];
79
+ changedPaths?: string[];
80
+ checks?: Array<{ command: string; status: "passed" | "failed"; summary?: string }>;
81
+ risks?: string[];
82
+ transcriptDigest?: string;
83
+ };
84
+ };
85
+
86
+ export type HunsuCompletedDestinationsFile = {
87
+ schema: "hunsu.completed-destinations.v1";
88
+ order: "oldest-first-tail-append";
89
+ entries: CompletedDestinationEntry[];
90
+ };
91
+
92
+ export type HunsuPendingDestinationsFile = {
93
+ schema: "hunsu.destinations.v1";
94
+ order: "queue-head-is-current";
95
+ destinations: Destination[];
96
+ compatibility: {
97
+ events: DomainEvent[];
98
+ updatedAt?: string;
99
+ };
100
+ };
101
+
102
+ export type HunsuHarnessFile = {
103
+ schema: "hunsu.harness.v1";
104
+ origins?: HunsuOrigin[];
105
+ harness: {
106
+ name: string;
107
+ rootTeamId: ExecutorId;
108
+ guardrails?: GuardrailConfig[];
109
+ lock?: HubPackageLock;
110
+ };
111
+ };
112
+
113
+ export type HunsuExecutorsFile = {
114
+ schema: "hunsu.executors.v1";
115
+ executors: ExecutorEntity[];
116
+ };
117
+
118
+ export type HunsuResourcesFile = {
119
+ schema: "hunsu.resources.v1";
120
+ resources: ResourceEntity[];
121
+ bindings: Array<{
122
+ destinationId: string;
123
+ executorPackageBindings?: BoardProjection["nodes"][number]["executorPackageBindings"];
124
+ resourcePackageBindings?: BoardProjection["nodes"][number]["resourcePackageBindings"];
125
+ }>;
126
+ };
127
+
128
+ export type HunsuArtifactActionsFile = {
129
+ schema: "hunsu.artifact-actions.v1";
130
+ order: "display-order";
131
+ actions: ArtifactActionDefinition[];
132
+ };
133
+
134
+ export type HunsuRuntimeEventLog = {
135
+ events: DomainEvent[];
136
+ updatedAt?: string;
137
+ };
138
+
139
+ export type HunsuCurrentExecutionFile = {
140
+ schema: "hunsu.current-execution.v1";
141
+ execution: ExecutionPlan;
142
+ updatedAt?: string;
143
+ };
144
+
145
+ export type MoveCommitRef =
146
+ | { type: "self" }
147
+ | { type: "external"; commit: CommitSha };
148
+
149
+ export type RouteNodeLifecycle = "Waiting" | "Executing" | "Completed" | "Failed";
150
+
151
+ export type PreviousExecutionAgentSessionRef = {
152
+ sessionId: string;
153
+ ownerKind: "TeamPlan" | "ExecutionPlan" | "MoveFinalizer";
154
+ providerThreadId?: string;
155
+ providerTurnId?: string;
156
+ state: "waiting" | "starting" | "executing" | "interactWait" | "completed" | "failed";
157
+ startedAt?: string;
158
+ completedAt?: string;
159
+ error?: string;
160
+ };
161
+
162
+ export type PlanNodeExecutionRecord = {
163
+ nodeType: "PlanNode";
164
+ lifecycle: Extract<RouteNodeLifecycle, "Completed" | "Failed">;
165
+ session?: PreviousExecutionAgentSessionRef;
166
+ completedAt?: string;
167
+ error?: string;
168
+ };
169
+
170
+ export type PathNodeExecutionRecord = {
171
+ nodeType: "PathNode";
172
+ pathId: PathId;
173
+ executorId: string;
174
+ goal: string;
175
+ requires: MemberPath["requires"];
176
+ lifecycle: RouteNodeLifecycle;
177
+ session?: PreviousExecutionAgentSessionRef;
178
+ commit?: CommitSha;
179
+ parentCommit?: CommitSha;
180
+ treeChanged?: boolean;
181
+ startedAt?: string;
182
+ completedAt?: string;
183
+ error?: string;
184
+ };
185
+
186
+ export type RouteNodeExecutionRecord = PlanNodeExecutionRecord | PathNodeExecutionRecord;
187
+
188
+ export type HunsuPreviousExecutionFile = {
189
+ schema: "hunsu.previous-execution.v1";
190
+ sourceMoveCommit: CommitSha;
191
+ targetMoveId: MoveId;
192
+ executeId: string;
193
+ runId: string;
194
+ lineId: string;
195
+ sourceNodeId?: NodeId;
196
+ sourceMoveId?: MoveId;
197
+ targetMoveOrdinal?: PositiveInteger;
198
+ selectedDestinationIds: string[];
199
+ worktree?: WorktreeRef;
200
+ conversationRef?: AgentConversationRef;
201
+ plan: PlanNodeExecutionRecord;
202
+ paths: PathNodeExecutionRecord[];
203
+ pathCommits: Record<string, CommitSha>;
204
+ terminalPathId?: PathId;
205
+ terminalPathCommit?: CommitSha;
206
+ finalizerSession?: PreviousExecutionAgentSessionRef;
207
+ moveFinalizerCommit?: MoveCommitRef;
208
+ moveFinalizerMessage?: string;
209
+ startedAt?: string;
210
+ completedAt?: string;
211
+ };
212
+
213
+ export type PreviousExecutionState =
214
+ | { type: "none" }
215
+ | { type: "present"; value: HunsuPreviousExecutionFile };
216
+
217
+ export type CurrentExecutionState =
218
+ | { type: "none" }
219
+ | { type: "present"; value: HunsuCurrentExecutionFile };
220
+
221
+ export type HunsuRuntimeState = {
222
+ completed: HunsuCompletedDestinationsFile;
223
+ destinations: HunsuPendingDestinationsFile;
224
+ harness: HunsuHarnessFile;
225
+ executors: HunsuExecutorsFile;
226
+ resources: HunsuResourcesFile;
227
+ artifactActions: HunsuArtifactActionsFile;
228
+ currentExecution: CurrentExecutionState;
229
+ previousExecution: PreviousExecutionState;
230
+ eventLog: HunsuRuntimeEventLog;
231
+ };
232
+
233
+ export type HunsuDraftRuntimeFileName = (typeof HUNSU_DRAFT_RUNTIME_FILE_NAMES)[number];
234
+
235
+ export type HunsuDraftRuntimeBundle = Pick<HunsuRuntimeState, "destinations" | "harness" | "executors" | "resources" | "artifactActions">;
236
+
237
+ export type HunsuDraftRuntimeValidation = {
238
+ previous: HunsuDraftRuntimeBundle;
239
+ request: HunsuDraftRuntimeBundle;
240
+ requestRuntime: HunsuRuntimeState;
241
+ };
242
+
243
+ export type EncodedHunsuRuntimeFile = {
244
+ text: string;
245
+ checksum: RuntimeChecksum;
246
+ };
247
+
248
+ type DecodedRuntimeFile<T> = {
249
+ value: T;
250
+ checksum: RuntimeChecksum;
251
+ };
252
+
253
+ type LegacyRuntimeState = {
254
+ version: 1;
255
+ events: DomainEvent[];
256
+ updatedAt?: string;
257
+ };
258
+
259
+ export function loadDomainStore(cwd = process.cwd()): DomainStore {
260
+ const root = ensureGitRepository(cwd);
261
+ const worktreeRuntime = readHunsuRuntimeStateFromWorktree(root);
262
+ const reachableRuntime = readLatestReachableHunsuRuntimeState(root);
263
+ if (worktreeRuntime && (!reachableRuntime || runtimeEventCount(worktreeRuntime.runtime) >= runtimeEventCount(reachableRuntime.runtime))) {
264
+ return domainStoreFromRuntime(root, worktreeRuntime.runtime, "worktree-runtime", [], worktreeRuntime.checksum);
265
+ }
266
+ if (reachableRuntime) {
267
+ return domainStoreFromRuntime(root, reachableRuntime.runtime, "reachable-runtime", [], reachableRuntime.checksum, reachableRuntime.commit);
268
+ }
269
+ const legacyState = readLegacyHunsuRuntimeStateFromWorktree(root) ?? readLegacyHunsuRuntimeStateAtRef(root, "HEAD");
270
+ if (legacyState) {
271
+ const runtime = runtimeFromEvents(legacyState.state.events, undefined, legacyState.state.events);
272
+ return domainStoreFromRuntime(root, runtime, "legacy-state", [], checksumRuntimeState(runtime));
273
+ }
274
+ const eventRefs = readDomainEventRefs(root);
275
+ if (eventRefs.length > 0) {
276
+ const events = eventRefs.map(ref => unwrapDomainStoreResult(readDomainEventObject(root, ref)));
277
+ const runtime = runtimeFromEvents(events, undefined, events);
278
+ return domainStoreFromRuntime(root, runtime, "legacy-refs", eventRefs, checksumRuntimeState(runtime));
279
+ }
280
+ const runtime = runtimeFromEvents([]);
281
+ return domainStoreFromRuntime(root, runtime, "empty", [], checksumRuntimeState(runtime));
282
+ }
283
+
284
+ export function initializeDomainStore(cwd = process.cwd(), options: { commitMessage?: string } = {}): DomainStore {
285
+ const root = ensureGitRepository(cwd);
286
+ const store = loadDomainStore(root);
287
+ if (store.source === "worktree-runtime") {
288
+ return store;
289
+ }
290
+ writeHunsuRuntimeState(root, store.runtime);
291
+ commitRuntimeStateIfRequested(root, options.commitMessage);
292
+ return {
293
+ ...store,
294
+ source: "worktree-runtime"
295
+ };
296
+ }
297
+
298
+ export function dryRunCommand(command: Command, cwd = process.cwd()): { store: DomainStore; acceptedEvents: DomainEvent[]; board: BoardProjection } {
299
+ return dryRunCommands([command], cwd);
300
+ }
301
+
302
+ export function dryRunCommands(commands: Command[], cwd = process.cwd()): { store: DomainStore; acceptedEvents: DomainEvent[]; board: BoardProjection } {
303
+ const store = loadDomainStore(cwd);
304
+ const nextEvents = commands.reduce((events, command) => {
305
+ const result = tryApplyCommand(events, command);
306
+ if (!result.ok) {
307
+ throw new Error(result.error.message);
308
+ }
309
+ return result.value;
310
+ }, store.events);
311
+ const acceptedEvents = nextEvents.slice(store.events.length);
312
+ return { store, acceptedEvents, board: projectDomainEvents(nextEvents, "dry-run commands") };
313
+ }
314
+
315
+ export function writeCommand(command: Command, options: { cwd?: string; commitMessage?: string; previousExecution?: PreviousExecutionState; selfCommitMoveIds?: string[] } = {}): { acceptedEvents: DomainEvent[]; board: BoardProjection } {
316
+ return writeCommands([command], options);
317
+ }
318
+
319
+ export function writeCommands(commands: Command[], options: { cwd?: string; commitMessage?: string; previousExecution?: PreviousExecutionState; selfCommitMoveIds?: string[] } = {}): { acceptedEvents: DomainEvent[]; board: BoardProjection } {
320
+ const cwd = options.cwd ?? process.cwd();
321
+ const { store, acceptedEvents, board } = dryRunCommands(commands, cwd);
322
+ if (acceptedEvents.length > 0) {
323
+ const nextRuntime = runtimeFromEvents([...store.events, ...acceptedEvents], store.runtime, acceptedEvents, options.previousExecution);
324
+ writeHunsuRuntimeState(store.root, nextRuntime, { selfCommitMoveIds: options.selfCommitMoveIds });
325
+ commitRuntimeStateIfRequested(store.root, options.commitMessage);
326
+ }
327
+ return { acceptedEvents, board };
328
+ }
329
+
330
+ export function encodeHunsuRuntimeFile(value: unknown): EncodedHunsuRuntimeFile {
331
+ const json = `${JSON.stringify(value)}\n`;
332
+ const checksum = parseRuntimeChecksum(sha256(json));
333
+ const payload = gzipSync(Buffer.from(json, "utf8")).toString("base64url");
334
+ return {
335
+ checksum,
336
+ text: `${HUNSU_RUNTIME_HEADER}\nencoding: ${HUNSU_RUNTIME_ENCODING}\nchecksum: sha256:${checksum}\n\n${payload}\n`
337
+ };
338
+ }
339
+
340
+ export function decodeHunsuRuntimeFileText<T = unknown>(text: string, source: string): Result<T, DomainStoreError> {
341
+ const decoded = decodeRuntimeEnvelope(text, source, HUNSU_RUNTIME_HEADER);
342
+ if (!decoded.ok) {
343
+ return decoded;
344
+ }
345
+ return ok(decoded.value.value as T);
346
+ }
347
+
348
+ export function decodeRuntimeBundleToDraftFiles(runtime: HunsuRuntimeState): Record<HunsuDraftRuntimeFileName, unknown> {
349
+ const bundle = hunsuDraftRuntimeBundleFromRuntime(runtime);
350
+ return {
351
+ "destinations.json": bundle.destinations,
352
+ "harness.json": bundle.harness,
353
+ "executors.json": bundle.executors,
354
+ "resources.json": bundle.resources,
355
+ "artifact-actions.json": bundle.artifactActions
356
+ };
357
+ }
358
+
359
+ export function hunsuDraftRuntimeBundleFromRuntime(runtime: HunsuRuntimeState): HunsuDraftRuntimeBundle {
360
+ return {
361
+ destinations: cloneJson(runtime.destinations) as HunsuPendingDestinationsFile,
362
+ harness: cloneJson(runtime.harness) as HunsuHarnessFile,
363
+ executors: cloneJson(runtime.executors) as HunsuExecutorsFile,
364
+ resources: cloneJson(runtime.resources) as HunsuResourcesFile,
365
+ artifactActions: cloneJson(runtime.artifactActions) as HunsuArtifactActionsFile
366
+ };
367
+ }
368
+
369
+ export function readDraftRuntimeBundle(cwd: string, dir: string): Result<HunsuDraftRuntimeBundle, DomainStoreError> {
370
+ const root = ensureGitRepository(cwd);
371
+ const destinations = readDraftRuntimeJson(root, dir, "destinations.json");
372
+ if (!destinations.ok) return destinations;
373
+ const harness = readDraftRuntimeJson(root, dir, "harness.json");
374
+ if (!harness.ok) return harness;
375
+ const executors = readDraftRuntimeJson(root, dir, "executors.json");
376
+ if (!executors.ok) return executors;
377
+ const resources = readDraftRuntimeJson(root, dir, "resources.json");
378
+ if (!resources.ok) return resources;
379
+ const artifactActions = readDraftRuntimeJson(root, dir, "artifact-actions.json");
380
+ if (!artifactActions.ok) return artifactActions;
381
+ return ok({
382
+ destinations: destinations.value as HunsuPendingDestinationsFile,
383
+ harness: harness.value as HunsuHarnessFile,
384
+ executors: executors.value as HunsuExecutorsFile,
385
+ resources: resources.value as HunsuResourcesFile,
386
+ artifactActions: artifactActions.value as HunsuArtifactActionsFile
387
+ });
388
+ }
389
+
390
+ export function validateDraftRuntimeBundle(
391
+ previous: HunsuDraftRuntimeBundle,
392
+ request: HunsuDraftRuntimeBundle,
393
+ sourceRuntime: HunsuRuntimeState
394
+ ): Result<HunsuDraftRuntimeValidation, DomainStoreError> {
395
+ const sourceBundle = hunsuDraftRuntimeBundleFromRuntime(sourceRuntime);
396
+ if (stableJson(previous) !== stableJson(sourceBundle)) {
397
+ return domainStoreError(".hunsu-prev no longer matches the source runtime bundle");
398
+ }
399
+ if (stableJson(request.destinations.compatibility) !== stableJson(sourceRuntime.destinations.compatibility)) {
400
+ return domainStoreError(".hunsu-request/destinations.json compatibility is Local-owned and must not be edited");
401
+ }
402
+ try {
403
+ const requestRuntime = validateRuntimeState({
404
+ completed: sourceRuntime.completed,
405
+ destinations: request.destinations,
406
+ harness: request.harness,
407
+ executors: request.executors,
408
+ resources: request.resources,
409
+ artifactActions: request.artifactActions,
410
+ currentExecution: sourceRuntime.currentExecution,
411
+ previousExecution: sourceRuntime.previousExecution,
412
+ eventLog: sourceRuntime.eventLog
413
+ }, "draft request runtime");
414
+ return ok({
415
+ previous: hunsuDraftRuntimeBundleFromRuntime(sourceRuntime),
416
+ request: hunsuDraftRuntimeBundleFromRuntime(requestRuntime),
417
+ requestRuntime
418
+ });
419
+ } catch (error) {
420
+ return domainStoreError(error instanceof Error ? error.message : String(error));
421
+ }
422
+ }
423
+
424
+ export function encodeDraftRuntimeBundleToHunsuFiles(
425
+ request: HunsuDraftRuntimeBundle
426
+ ): Record<typeof HUNSU_DESTINATIONS_PATH | typeof HUNSU_HARNESS_PATH | typeof HUNSU_EXECUTORS_PATH | typeof HUNSU_RESOURCES_PATH | typeof HUNSU_ARTIFACT_ACTIONS_PATH, EncodedHunsuRuntimeFile> {
427
+ return {
428
+ [HUNSU_DESTINATIONS_PATH]: encodeHunsuRuntimeFile(request.destinations),
429
+ [HUNSU_HARNESS_PATH]: encodeHunsuRuntimeFile(request.harness),
430
+ [HUNSU_EXECUTORS_PATH]: encodeHunsuRuntimeFile(request.executors),
431
+ [HUNSU_RESOURCES_PATH]: encodeHunsuRuntimeFile(request.resources),
432
+ [HUNSU_ARTIFACT_ACTIONS_PATH]: encodeHunsuRuntimeFile(request.artifactActions)
433
+ };
434
+ }
435
+
436
+ export function readHunsuRuntimeStateFromWorktree(cwd = process.cwd()): { runtime: HunsuRuntimeState; checksum: RuntimeChecksum } | undefined {
437
+ const root = ensureGitRepository(cwd);
438
+ if (!HUNSU_RUNTIME_PATHS.every(path => existsSync(join(root, path)))) {
439
+ return undefined;
440
+ }
441
+ return readHunsuRuntimeStateFromSource(path => readFileSync(join(root, path), "utf8"), "worktree", currentHeadCommit(root));
442
+ }
443
+
444
+ export function readHunsuRuntimeStateAtRef(cwd = process.cwd(), ref = "HEAD"): { runtime: HunsuRuntimeState; checksum: RuntimeChecksum } | undefined {
445
+ const root = ensureGitRepository(cwd);
446
+ try {
447
+ const commit = parseCommitSha(git(["rev-parse", "--verify", `${ref}^{commit}`], { cwd: root }).trim());
448
+ return readHunsuRuntimeStateFromSource(path => git(["show", `${commit}:${path}`], { cwd: root }), commit, commit);
449
+ } catch (error) {
450
+ if (error instanceof GitError) {
451
+ return undefined;
452
+ }
453
+ throw error;
454
+ }
455
+ }
456
+
457
+ export function readReachableHunsuRuntimeStates(cwd = process.cwd()): Array<{ commit: CommitSha; runtime: HunsuRuntimeState; checksum: RuntimeChecksum }> {
458
+ const root = ensureGitRepository(cwd);
459
+ let commits: string[];
460
+ try {
461
+ commits = git(["rev-list", "--date-order", "--all", "--", HUNSU_DESTINATIONS_PATH], { cwd: root })
462
+ .trim()
463
+ .split(/\r?\n/)
464
+ .filter(Boolean);
465
+ } catch (error) {
466
+ if (error instanceof GitError) {
467
+ return [];
468
+ }
469
+ throw error;
470
+ }
471
+ return commits.flatMap(commit => {
472
+ const commitSha = parseCommitSha(commit);
473
+ const state = readHunsuRuntimeStateAtRef(root, commitSha);
474
+ return state ? [{ commit: commitSha, ...state }] : [];
475
+ });
476
+ }
477
+
478
+ export function readPreviousExecutionChain(cwd = process.cwd(), ref?: string): Array<{ commit: CommitSha; execution: HunsuPreviousExecutionFile }> {
479
+ const root = ensureGitRepository(cwd);
480
+ const visited = new Set<string>();
481
+ const chain: Array<{ commit: CommitSha; execution: HunsuPreviousExecutionFile }> = [];
482
+ let nextRef: string | undefined = ref ?? readLatestReachableHunsuRuntimeState(root)?.commit ?? "HEAD";
483
+ while (nextRef) {
484
+ let commit: CommitSha;
485
+ try {
486
+ commit = parseCommitSha(git(["rev-parse", "--verify", `${nextRef}^{commit}`], { cwd: root }).trim());
487
+ } catch (error) {
488
+ if (error instanceof GitError) {
489
+ break;
490
+ }
491
+ throw error;
492
+ }
493
+ if (visited.has(commit)) {
494
+ break;
495
+ }
496
+ visited.add(commit);
497
+ const state = readHunsuRuntimeStateAtRef(root, commit);
498
+ if (!state || state.runtime.previousExecution.type !== "present") {
499
+ break;
500
+ }
501
+ chain.push({ commit, execution: state.runtime.previousExecution.value });
502
+ nextRef = state.runtime.previousExecution.value.sourceMoveCommit;
503
+ }
504
+ return chain;
505
+ }
506
+
507
+ export function hasHunsuRuntimeState(cwd = process.cwd()): boolean {
508
+ const root = ensureGitRepository(cwd);
509
+ return readHunsuRuntimeStateFromWorktree(root) !== undefined || readLatestReachableHunsuRuntimeState(root) !== undefined;
510
+ }
511
+
512
+ export function readDomainEventRefs(cwd = process.cwd()): DomainEventRef[] {
513
+ const root = ensureGitRepository(cwd);
514
+ const output = git(["for-each-ref", `--format=${DOMAIN_EVENT_REF_FORMAT}`, DOMAIN_EVENT_REF_PREFIX], { cwd: root }).trim();
515
+ if (!output) {
516
+ return [];
517
+ }
518
+ return output
519
+ .split(/\r?\n/)
520
+ .map(parseDomainEventRef)
521
+ .filter(ref => ref.objectType === "blob")
522
+ .sort((left, right) => left.ordinal - right.ordinal || left.ref.localeCompare(right.ref));
523
+ }
524
+
525
+ export function readDomainEventObject(cwd: string, ref: Pick<DomainEventRef, "object" | "ref">): Result<DomainEvent, DomainStoreError> {
526
+ const root = ensureGitRepository(cwd);
527
+ const text = git(["cat-file", "-p", ref.object], { cwd: root });
528
+ return decodeDomainEventText(text, ref.ref);
529
+ }
530
+
531
+ export function decodeDomainEventText(text: string, ref: string): Result<DomainEvent, DomainStoreError> {
532
+ const trimmed = text.trim();
533
+ if (!trimmed) {
534
+ return domainStoreError(`Empty Hunsu domain event object: ${ref}`);
535
+ }
536
+ let parsed: unknown;
537
+ try {
538
+ parsed = JSON.parse(trimmed);
539
+ } catch (error) {
540
+ return domainStoreError(`Invalid Hunsu domain event JSON in ${ref}: ${error instanceof Error ? error.message : String(error)}`);
541
+ }
542
+ const validation = validateDomainEvent(parsed);
543
+ if (!validation.ok) {
544
+ return domainStoreError(`Invalid Hunsu domain event object in ${ref}: ${validation.error.message}`);
545
+ }
546
+ return ok(validation.value);
547
+ }
548
+
549
+ function runtimeFromEvents(
550
+ events: DomainEvent[],
551
+ previous?: HunsuRuntimeState,
552
+ acceptedEvents: DomainEvent[] = [],
553
+ previousExecutionOverride?: PreviousExecutionState
554
+ ): HunsuRuntimeState {
555
+ const board = projectDomainEvents(events, "runtime events");
556
+ const eventLog = {
557
+ events,
558
+ updatedAt: acceptedEvents.length > 0 ? new Date().toISOString() : previous?.eventLog.updatedAt
559
+ };
560
+ return {
561
+ completed: completedDestinationsFromEvents(board, previous?.completed, previous ? acceptedEvents : events),
562
+ destinations: {
563
+ schema: "hunsu.destinations.v1",
564
+ order: "queue-head-is-current",
565
+ destinations: pendingQueueFromBoard(board),
566
+ compatibility: {
567
+ events: eventLog.events,
568
+ updatedAt: eventLog.updatedAt
569
+ }
570
+ },
571
+ ...harnessExecutorsResourcesFilesFromBoard(board, previous),
572
+ artifactActions: artifactActionsFileFromBoard(board),
573
+ currentExecution: currentExecutionFromEvents(previous?.currentExecution, acceptedEvents),
574
+ previousExecution: previousExecutionFromEvents(previous?.previousExecution, acceptedEvents, previousExecutionOverride),
575
+ eventLog
576
+ };
577
+ }
578
+
579
+ function currentExecutionFromEvents(
580
+ previous: CurrentExecutionState | undefined,
581
+ acceptedEvents: DomainEvent[]
582
+ ): CurrentExecutionState {
583
+ if (acceptedEvents.some(event => event.type === "HunsuRecorded" || event.type === "LineForkedByHunsu" || event.type === "MoveRecorded")) {
584
+ return { type: "none" };
585
+ }
586
+ return previous ?? { type: "none" };
587
+ }
588
+
589
+ function previousExecutionFromEvents(
590
+ previous: PreviousExecutionState | undefined,
591
+ acceptedEvents: DomainEvent[],
592
+ override: PreviousExecutionState | undefined
593
+ ): PreviousExecutionState {
594
+ if (override) {
595
+ return override;
596
+ }
597
+ if (acceptedEvents.some(event => event.type === "HunsuRecorded" || event.type === "LineForkedByHunsu")) {
598
+ return { type: "none" };
599
+ }
600
+ if (acceptedEvents.some(event => event.type === "MoveRecorded")) {
601
+ return { type: "none" };
602
+ }
603
+ return previous ?? { type: "none" };
604
+ }
605
+
606
+ function completedDestinationsFromEvents(
607
+ board: BoardProjection,
608
+ previous: HunsuCompletedDestinationsFile | undefined,
609
+ acceptedEvents: DomainEvent[]
610
+ ): HunsuCompletedDestinationsFile {
611
+ const entries = previous ? [...previous.entries] : [];
612
+ for (const event of acceptedEvents) {
613
+ if (event.type !== "MoveRecorded" || event.move.outcome !== "arrived") {
614
+ continue;
615
+ }
616
+ for (const destinationId of event.move.reachedDestinationIds) {
617
+ if (entries.some(entry => entry.moveId === event.move.id && entry.destinationId === destinationId)) {
618
+ continue;
619
+ }
620
+ entries.push(completedEntryForMove(board, event.move, destinationId));
621
+ }
622
+ }
623
+ return {
624
+ schema: "hunsu.completed-destinations.v1",
625
+ order: "oldest-first-tail-append",
626
+ entries
627
+ };
628
+ }
629
+
630
+ function completedEntryForMove(board: BoardProjection, move: MoveRecord, destinationId: string): CompletedDestinationEntry {
631
+ const destination = move.snapshot?.destinations.find(candidate => candidate.id === destinationId)
632
+ ?? board.destinations.find(candidate => candidate.id === destinationId);
633
+ return {
634
+ destinationId,
635
+ title: destination?.title ?? destinationId,
636
+ completedAt: move.recordedAt,
637
+ resultCommit: runtimeCommitRef(move.commit),
638
+ moveId: move.id,
639
+ harnessId: "default",
640
+ digest: {
641
+ summary: move.summary,
642
+ evidence: [...move.evidence],
643
+ risks: move.risks ? [...move.risks] : undefined
644
+ }
645
+ };
646
+ }
647
+
648
+ function pendingQueueFromBoard(board: BoardProjection): Destination[] {
649
+ return board.destinations
650
+ .filter(destination => destination.status !== "reached" && destination.status !== "canceled" && destination.status !== "superseded")
651
+ .sort((left, right) => (right.priority ?? 0) - (left.priority ?? 0) || left.id.localeCompare(right.id));
652
+ }
653
+
654
+ function harnessExecutorsResourcesFilesFromBoard(board: BoardProjection, previous: HunsuRuntimeState | undefined): Pick<HunsuRuntimeState, "harness" | "executors" | "resources"> {
655
+ const activeLine = board.lines.findLast(line => line.status === "active") ?? board.lines.at(-1);
656
+ const activeNode = activeLine ? board.nodes.find(node => node.id === activeLine.currentNodeId) : undefined;
657
+ const harnessGraph = activeNode?.harnessGraph
658
+ ?? (previous ? runtimeHarnessGraph(previous) : harnessEntityFromSnapshot(createDefaultHarness()));
659
+ return {
660
+ harness: {
661
+ schema: "hunsu.harness.v1",
662
+ origins: board.origins.map(origin => ({ ...origin })),
663
+ harness: {
664
+ name: "Default Harness",
665
+ rootTeamId: harnessGraph.rootTeamId,
666
+ guardrails: harnessGraph.guardrails.map(guardrail => ({ ...guardrail })),
667
+ lock: activeNode?.harnessLock ? { ...activeNode.harnessLock } : previous?.harness.harness.lock
668
+ }
669
+ },
670
+ executors: {
671
+ schema: "hunsu.executors.v1",
672
+ executors: cloneJson(harnessGraph.executors) as ExecutorEntity[]
673
+ },
674
+ resources: {
675
+ schema: "hunsu.resources.v1",
676
+ resources: cloneJson(harnessGraph.resources) as ResourceEntity[],
677
+ bindings: board.destinations.map(destination => {
678
+ const previousBinding = previous?.resources.bindings.find(binding => binding.destinationId === destination.id);
679
+ return {
680
+ destinationId: destination.id,
681
+ executorPackageBindings: activeNode?.executorPackageBindings?.map(binding => ({ executorId: binding.executorId, lock: { ...binding.lock } })) ?? previousBinding?.executorPackageBindings,
682
+ resourcePackageBindings: activeNode?.resourcePackageBindings?.map(binding => ({ name: binding.name, lock: { ...binding.lock } })) ?? previousBinding?.resourcePackageBindings
683
+ };
684
+ })
685
+ }
686
+ };
687
+ }
688
+
689
+ function artifactActionsFileFromBoard(board: BoardProjection): HunsuArtifactActionsFile {
690
+ return {
691
+ schema: "hunsu.artifact-actions.v1",
692
+ order: "display-order",
693
+ actions: board.artifactActions
694
+ .map(cloneArtifactAction)
695
+ .sort((left, right) => left.displayOrder - right.displayOrder || String(left.id).localeCompare(String(right.id)))
696
+ };
697
+ }
698
+
699
+ function cloneArtifactAction(action: ArtifactActionDefinition): ArtifactActionDefinition {
700
+ return {
701
+ ...action,
702
+ env: action.env ? Object.fromEntries(Object.entries(action.env).map(([key, value]) => [key, { ...value }])) : undefined,
703
+ runner: { ...action.runner },
704
+ aliases: action.aliases ? Object.fromEntries(Object.entries(action.aliases).map(([key, value]) => [key, { ...value }])) : undefined,
705
+ evidence: action.evidence ? { ...action.evidence, paths: action.evidence.paths?.slice() } : undefined
706
+ };
707
+ }
708
+
709
+ function readHunsuRuntimeStateFromSource(read: (path: string) => string, label: string, selfCommit?: CommitSha): { runtime: HunsuRuntimeState; checksum: RuntimeChecksum } | undefined {
710
+ const completed = decodeRequiredRuntimeFile<HunsuCompletedDestinationsFile>(read, HUNSU_COMPLETED_DESTINATIONS_PATH, label);
711
+ const destinations = decodeRequiredRuntimeFile<HunsuPendingDestinationsFile>(read, HUNSU_DESTINATIONS_PATH, label);
712
+ const harness = decodeRequiredRuntimeFile<HunsuHarnessFile>(read, HUNSU_HARNESS_PATH, label);
713
+ const executors = decodeRequiredRuntimeFile<HunsuExecutorsFile>(read, HUNSU_EXECUTORS_PATH, label);
714
+ const resources = decodeRequiredRuntimeFile<HunsuResourcesFile>(read, HUNSU_RESOURCES_PATH, label);
715
+ const artifactActions = decodeRequiredRuntimeFile<HunsuArtifactActionsFile>(read, HUNSU_ARTIFACT_ACTIONS_PATH, label);
716
+ if (!completed || !destinations || !harness || !executors || !resources || !artifactActions) {
717
+ return undefined;
718
+ }
719
+ const currentExecution = decodeOptionalRuntimeFile<HunsuCurrentExecutionFile>(read, HUNSU_CURRENT_EXECUTION_PATH, label);
720
+ const previousExecution = decodeOptionalRuntimeFile<HunsuPreviousExecutionFile>(read, HUNSU_PREVIOUS_EXECUTION_PATH, label);
721
+ const runtime = validateRuntimeState({
722
+ completed: completed.value,
723
+ destinations: destinations.value,
724
+ harness: harness.value,
725
+ executors: executors.value,
726
+ resources: resources.value,
727
+ artifactActions: artifactActions.value,
728
+ currentExecution: currentExecution ? { type: "present", value: currentExecution.value } : { type: "none" },
729
+ previousExecution: previousExecution ? { type: "present", value: previousExecution.value } : { type: "none" }
730
+ }, label, selfCommit);
731
+ return {
732
+ runtime,
733
+ checksum: parseRuntimeChecksum(sha256([completed.checksum, destinations.checksum, harness.checksum, executors.checksum, resources.checksum, artifactActions.checksum, currentExecution?.checksum ?? "none", previousExecution?.checksum ?? "none"].join("\n")))
734
+ };
735
+ }
736
+
737
+ function decodeRequiredRuntimeFile<T>(read: (path: string) => string, path: string, label: string): DecodedRuntimeFile<T> | undefined {
738
+ try {
739
+ const decoded = decodeRuntimeEnvelope(read(path), `${label}:${path}`, HUNSU_RUNTIME_HEADER);
740
+ return decoded.ok ? { value: decoded.value.value as T, checksum: decoded.value.checksum } : unwrapDomainStoreResult(decoded);
741
+ } catch (error) {
742
+ if (error instanceof GitError) {
743
+ return undefined;
744
+ }
745
+ throw error;
746
+ }
747
+ }
748
+
749
+ function decodeOptionalRuntimeFile<T>(read: (path: string) => string, path: string, label: string): DecodedRuntimeFile<T> | undefined {
750
+ try {
751
+ const decoded = decodeRuntimeEnvelope(read(path), `${label}:${path}`, HUNSU_RUNTIME_HEADER);
752
+ return decoded.ok ? { value: decoded.value.value as T, checksum: decoded.value.checksum } : unwrapDomainStoreResult(decoded);
753
+ } catch (error) {
754
+ if (error instanceof GitError || isMissingFileError(error)) {
755
+ return undefined;
756
+ }
757
+ throw error;
758
+ }
759
+ }
760
+
761
+ function validateRuntimeState(runtime: Omit<HunsuRuntimeState, "eventLog"> & { eventLog?: HunsuRuntimeEventLog }, source: string, selfCommit?: CommitSha): HunsuRuntimeState {
762
+ if (runtime.completed.schema !== "hunsu.completed-destinations.v1" || runtime.completed.order !== "oldest-first-tail-append" || !Array.isArray(runtime.completed.entries)) {
763
+ throw new Error(`Invalid completed Destinations runtime file in ${source}`);
764
+ }
765
+ if (runtime.destinations.schema !== "hunsu.destinations.v1" || runtime.destinations.order !== "queue-head-is-current" || !Array.isArray(runtime.destinations.destinations)) {
766
+ throw new Error(`Invalid pending Destinations runtime file in ${source}`);
767
+ }
768
+ if (!runtime.destinations.compatibility || !Array.isArray(runtime.destinations.compatibility.events)) {
769
+ throw new Error(`Invalid pending Destinations compatibility data in ${source}`);
770
+ }
771
+ const events: DomainEvent[] = [];
772
+ for (const [index, event] of runtime.destinations.compatibility.events.entries()) {
773
+ const validation = validateDomainEvent(resolveRuntimeEventSelfCommit(event, selfCommit));
774
+ if (!validation.ok) {
775
+ throw new Error(`Invalid Hunsu runtime event ${index} in ${source}: ${validation.error.message}`);
776
+ }
777
+ events.push(validation.value);
778
+ }
779
+ const eventLog = {
780
+ events,
781
+ updatedAt: typeof runtime.destinations.compatibility.updatedAt === "string"
782
+ ? runtime.destinations.compatibility.updatedAt
783
+ : runtime.eventLog?.updatedAt
784
+ };
785
+ if (runtime.harness.schema !== "hunsu.harness.v1" || !runtime.harness.harness || typeof runtime.harness.harness.name !== "string") {
786
+ throw new Error(`Invalid Harness runtime file in ${source}`);
787
+ }
788
+ if (Object.prototype.hasOwnProperty.call(runtime.harness.harness, "executors")) {
789
+ throw new Error(`Invalid Harness runtime file in ${source}: Executor definitions are stored in executors.json`);
790
+ }
791
+ if (Object.prototype.hasOwnProperty.call(runtime.harness.harness, "members")) {
792
+ throw new Error(`Invalid Harness runtime file in ${source}: members is stored in executors.json, not harness.json`);
793
+ }
794
+ if (Object.prototype.hasOwnProperty.call(runtime.harness.harness, "plan")) {
795
+ throw new Error(`Invalid Harness runtime file in ${source}: root Team planner is stored in executors.json, not harness.json`);
796
+ }
797
+ if (typeof runtime.harness.harness.rootTeamId !== "string" || !runtime.harness.harness.rootTeamId.trim()) {
798
+ throw new Error(`Invalid Harness runtime file in ${source}: rootTeamId must reference the locked root Team`);
799
+ }
800
+ if (runtime.executors.schema !== "hunsu.executors.v1" || !Array.isArray(runtime.executors.executors)) {
801
+ throw new Error(`Invalid Executors runtime file in ${source}`);
802
+ }
803
+ if (runtime.resources.schema !== "hunsu.resources.v1" || !Array.isArray(runtime.resources.resources) || !Array.isArray(runtime.resources.bindings)) {
804
+ throw new Error(`Invalid Resources runtime file in ${source}`);
805
+ }
806
+ const artifactActions = validateArtifactActionsRuntimeFile(runtime.artifactActions, source);
807
+ const graph = runtimeHarnessGraph({
808
+ ...runtime,
809
+ artifactActions
810
+ }, source);
811
+ rootHarnessSnapshot(graph);
812
+ const currentExecution = validateCurrentExecutionState(runtime.currentExecution, source);
813
+ const previousExecution = validatePreviousExecutionState(runtime.previousExecution, source, selfCommit);
814
+ return {
815
+ completed: runtime.completed,
816
+ destinations: {
817
+ ...runtime.destinations,
818
+ compatibility: { ...runtime.destinations.compatibility, events }
819
+ },
820
+ harness: {
821
+ ...runtime.harness,
822
+ harness: {
823
+ name: runtime.harness.harness.name,
824
+ rootTeamId: graph.rootTeamId,
825
+ guardrails: graph.guardrails.map(guardrail => ({ ...guardrail })),
826
+ lock: runtime.harness.harness.lock
827
+ }
828
+ },
829
+ executors: {
830
+ ...runtime.executors,
831
+ executors: graph.executors
832
+ },
833
+ resources: {
834
+ ...runtime.resources,
835
+ resources: graph.resources
836
+ },
837
+ artifactActions,
838
+ currentExecution,
839
+ previousExecution,
840
+ eventLog
841
+ };
842
+ }
843
+
844
+ function runtimeHarnessGraph(runtime: Pick<HunsuRuntimeState, "harness" | "executors" | "resources" | "artifactActions">, source = "runtime"): Harness {
845
+ const graph = validateHarnessEntity({
846
+ rootTeamId: runtime.harness.harness.rootTeamId,
847
+ executors: runtime.executors.executors,
848
+ resources: runtime.resources.resources,
849
+ guardrails: runtime.harness.harness.guardrails ?? [],
850
+ artifactActions: runtime.artifactActions.actions
851
+ }, `${source} Harness graph`);
852
+ if (!graph.ok) {
853
+ throw new Error(`Invalid Harness runtime graph in ${source}: ${graph.error.message}`);
854
+ }
855
+ return graph.value;
856
+ }
857
+
858
+ function validateArtifactActionsRuntimeFile(value: HunsuArtifactActionsFile, source: string): HunsuArtifactActionsFile {
859
+ if (value.schema !== "hunsu.artifact-actions.v1" || value.order !== "display-order" || !Array.isArray(value.actions)) {
860
+ throw new Error(`Invalid Artifact Actions runtime file in ${source}`);
861
+ }
862
+ const actions = decodeArtifactActionDefinitionArray(value.actions, "artifactActions.actions");
863
+ if (!actions.ok) {
864
+ throw new Error(`Invalid Artifact Actions runtime file in ${source}: ${actions.error.message}`);
865
+ }
866
+ return { ...value, actions: actions.value };
867
+ }
868
+
869
+ function validateCurrentExecutionState(value: CurrentExecutionState | undefined, source: string): CurrentExecutionState {
870
+ if (!value || value.type === "none") {
871
+ return { type: "none" };
872
+ }
873
+ if (value.type !== "present" || !value.value || value.value.schema !== "hunsu.current-execution.v1") {
874
+ throw new Error(`Invalid current execution runtime file in ${source}`);
875
+ }
876
+ if (!value.value.execution || typeof value.value.execution !== "object") {
877
+ throw new Error(`Invalid current execution payload in ${source}`);
878
+ }
879
+ return value;
880
+ }
881
+
882
+ function validatePreviousExecutionState(value: PreviousExecutionState | undefined, source: string, selfCommit?: CommitSha): PreviousExecutionState {
883
+ if (!value || value.type === "none") {
884
+ return { type: "none" };
885
+ }
886
+ if (value.type !== "present" || !value.value || value.value.schema !== "hunsu.previous-execution.v1") {
887
+ throw new Error(`Invalid previous execution runtime file in ${source}`);
888
+ }
889
+ if (!value.value.sourceMoveCommit || !value.value.targetMoveId || !value.value.executeId || !value.value.runId || !value.value.lineId) {
890
+ throw new Error(`Invalid previous execution identity in ${source}`);
891
+ }
892
+ if (!value.value.plan || value.value.plan.nodeType !== "PlanNode") {
893
+ throw new Error(`Invalid previous execution PlanNode in ${source}`);
894
+ }
895
+ if (!Array.isArray(value.value.paths)) {
896
+ throw new Error(`Invalid previous execution PathNode list in ${source}`);
897
+ }
898
+ const moveFinalizerCommit = value.value.moveFinalizerCommit;
899
+ if (isSelfMoveCommitRef(moveFinalizerCommit)) {
900
+ if (!selfCommit) {
901
+ throw new Error(`Cannot resolve previous execution self commit in ${source}`);
902
+ }
903
+ return { type: "present", value: { ...value.value, moveFinalizerCommit: { type: "external", commit: selfCommit } } };
904
+ }
905
+ return value;
906
+ }
907
+
908
+ function resolveRuntimeEventSelfCommit(event: DomainEvent, selfCommit: CommitSha | undefined): unknown {
909
+ if (event.type !== "MoveRecorded") {
910
+ return event;
911
+ }
912
+ const commit = (event.move as { commit?: unknown }).commit;
913
+ if (isSelfMoveCommitRef(commit)) {
914
+ if (!selfCommit) {
915
+ throw new Error("Cannot resolve self MOVE commit without containing commit");
916
+ }
917
+ return { ...event, move: { ...event.move, commit: selfCommit } };
918
+ }
919
+ if (commit === HUNSU_SELF_COMMIT_SENTINEL) {
920
+ if (!selfCommit) {
921
+ throw new Error("Cannot resolve self MOVE commit without containing commit");
922
+ }
923
+ return { ...event, move: { ...event.move, commit: selfCommit } };
924
+ }
925
+ return event;
926
+ }
927
+
928
+ function isSelfMoveCommitRef(value: unknown): value is Extract<MoveCommitRef, { type: "self" }> {
929
+ return Boolean(value && typeof value === "object" && (value as { type?: unknown }).type === "self");
930
+ }
931
+
932
+ function runtimeCommitRef(value: unknown): CompletedDestinationEntry["resultCommit"] {
933
+ if (isSelfMoveCommitRef(value)) {
934
+ return HUNSU_SELF_COMMIT_REF;
935
+ }
936
+ if (value === HUNSU_SELF_COMMIT_SENTINEL) {
937
+ return HUNSU_SELF_COMMIT_SENTINEL;
938
+ }
939
+ return parseCommitSha(String(value));
940
+ }
941
+
942
+ function writeHunsuRuntimeState(cwd: string, runtime: HunsuRuntimeState, options: { selfCommitMoveIds?: string[] } = {}): void {
943
+ const root = ensureGitRepository(cwd);
944
+ writeRuntimeFile(root, HUNSU_COMPLETED_DESTINATIONS_PATH, runtime.completed);
945
+ writeRuntimeFile(root, HUNSU_DESTINATIONS_PATH, destinationsForEncoding(runtime, options.selfCommitMoveIds ?? []));
946
+ writeRuntimeFile(root, HUNSU_HARNESS_PATH, runtime.harness);
947
+ writeRuntimeFile(root, HUNSU_EXECUTORS_PATH, runtime.executors);
948
+ writeRuntimeFile(root, HUNSU_RESOURCES_PATH, runtime.resources);
949
+ writeRuntimeFile(root, HUNSU_ARTIFACT_ACTIONS_PATH, runtime.artifactActions);
950
+ writeCurrentExecutionRuntimeFile(root, runtime.currentExecution);
951
+ writePreviousExecutionRuntimeFile(root, runtime.previousExecution, options.selfCommitMoveIds ?? []);
952
+ }
953
+
954
+ function writeRuntimeFile(root: string, path: string, value: unknown): void {
955
+ const file = join(root, path);
956
+ mkdirSync(dirname(file), { recursive: true });
957
+ writeFileSync(file, encodeHunsuRuntimeFile(value).text, "utf8");
958
+ }
959
+
960
+ function writeCurrentExecutionRuntimeFile(root: string, state: CurrentExecutionState): void {
961
+ const file = join(root, HUNSU_CURRENT_EXECUTION_PATH);
962
+ if (state.type === "none") {
963
+ if (existsSync(file)) {
964
+ rmSync(file, { force: true });
965
+ }
966
+ return;
967
+ }
968
+ writeRuntimeFile(root, HUNSU_CURRENT_EXECUTION_PATH, state.value);
969
+ }
970
+
971
+ function writePreviousExecutionRuntimeFile(root: string, state: PreviousExecutionState, selfCommitMoveIds: string[]): void {
972
+ const file = join(root, HUNSU_PREVIOUS_EXECUTION_PATH);
973
+ if (state.type === "none") {
974
+ if (existsSync(file)) {
975
+ rmSync(file, { force: true });
976
+ }
977
+ return;
978
+ }
979
+ const value = previousExecutionForEncoding(state.value, selfCommitMoveIds);
980
+ writeRuntimeFile(root, HUNSU_PREVIOUS_EXECUTION_PATH, value);
981
+ }
982
+
983
+ function destinationsForEncoding(runtime: HunsuRuntimeState, selfCommitMoveIds: string[]): HunsuPendingDestinationsFile {
984
+ return {
985
+ ...runtime.destinations,
986
+ compatibility: {
987
+ events: runtime.eventLog.events.map(event => eventForEncoding(event, selfCommitMoveIds)),
988
+ updatedAt: runtime.eventLog.updatedAt
989
+ }
990
+ };
991
+ }
992
+
993
+ function eventForEncoding(event: DomainEvent, selfCommitMoveIds: string[]): DomainEvent {
994
+ if (event.type !== "MoveRecorded" || !selfCommitMoveIds.includes(String(event.move.id))) {
995
+ return event;
996
+ }
997
+ return { ...event, move: { ...event.move, commit: HUNSU_SELF_COMMIT_REF } as unknown as MoveRecord };
998
+ }
999
+
1000
+ function previousExecutionForEncoding(value: HunsuPreviousExecutionFile, selfCommitMoveIds: string[]): HunsuPreviousExecutionFile {
1001
+ if (!value.moveFinalizerCommit || value.moveFinalizerCommit.type !== "external" || !selfCommitMoveIds.includes(value.targetMoveId)) {
1002
+ return value;
1003
+ }
1004
+ return { ...value, moveFinalizerCommit: HUNSU_SELF_COMMIT_REF };
1005
+ }
1006
+
1007
+ function commitRuntimeStateIfRequested(cwd: string, commitMessage: string | undefined): void {
1008
+ if (!commitMessage) {
1009
+ return;
1010
+ }
1011
+ const paths = stageableRuntimePaths(cwd);
1012
+ if (paths.length === 0) {
1013
+ return;
1014
+ }
1015
+ git(["add", "--all", "--", ...paths], { cwd });
1016
+ const status = git(["status", "--porcelain=v1", "--", ...paths], { cwd }).trim();
1017
+ if (!status) {
1018
+ return;
1019
+ }
1020
+ git(["commit", "--only", "-m", commitMessage, "--", ...paths], { cwd });
1021
+ }
1022
+
1023
+ function stageableRuntimePaths(cwd: string): string[] {
1024
+ return [...HUNSU_RUNTIME_PATHS, HUNSU_CURRENT_EXECUTION_PATH, HUNSU_PREVIOUS_EXECUTION_PATH].filter(path => existsSync(join(cwd, path)) || isTrackedPath(cwd, path));
1025
+ }
1026
+
1027
+ function isTrackedPath(cwd: string, path: string): boolean {
1028
+ try {
1029
+ git(["ls-files", "--error-unmatch", path], { cwd });
1030
+ return true;
1031
+ } catch (error) {
1032
+ if (error instanceof GitError) {
1033
+ return false;
1034
+ }
1035
+ throw error;
1036
+ }
1037
+ }
1038
+
1039
+ function domainStoreFromRuntime(
1040
+ root: string,
1041
+ runtime: HunsuRuntimeState,
1042
+ source: DomainStore["source"],
1043
+ eventRefs: DomainEventRef[],
1044
+ checksum: RuntimeChecksum,
1045
+ commit?: CommitSha
1046
+ ): DomainStore {
1047
+ const events = [...runtime.eventLog.events];
1048
+ return {
1049
+ root,
1050
+ eventRefs,
1051
+ events,
1052
+ board: projectDomainEvents(events, source),
1053
+ runtimePaths: HUNSU_RUNTIME_PATHS,
1054
+ runtime,
1055
+ source,
1056
+ checksum,
1057
+ commit
1058
+ };
1059
+ }
1060
+
1061
+ function projectDomainEvents(events: DomainEvent[], source: string): BoardProjection {
1062
+ const projected = tryProjectBoard(events);
1063
+ if (!projected.ok) {
1064
+ throw new Error(`Invalid Hunsu domain event stream in ${source}: ${projected.error.message}`);
1065
+ }
1066
+ return projected.value;
1067
+ }
1068
+
1069
+ function readLatestReachableHunsuRuntimeState(cwd: string): { commit: CommitSha; runtime: HunsuRuntimeState; checksum: RuntimeChecksum } | undefined {
1070
+ return readReachableHunsuRuntimeStates(cwd)
1071
+ .sort((left, right) => runtimeEventCount(right.runtime) - runtimeEventCount(left.runtime))
1072
+ .at(0);
1073
+ }
1074
+
1075
+ function runtimeEventCount(runtime: HunsuRuntimeState): number {
1076
+ return runtime.eventLog.events.length;
1077
+ }
1078
+
1079
+ function checksumRuntimeState(runtime: HunsuRuntimeState): RuntimeChecksum {
1080
+ return parseRuntimeChecksum(sha256([
1081
+ encodeHunsuRuntimeFile(runtime.completed).checksum,
1082
+ encodeHunsuRuntimeFile(destinationsForEncoding(runtime, [])).checksum,
1083
+ encodeHunsuRuntimeFile(runtime.harness).checksum,
1084
+ encodeHunsuRuntimeFile(runtime.executors).checksum,
1085
+ encodeHunsuRuntimeFile(runtime.resources).checksum,
1086
+ encodeHunsuRuntimeFile(runtime.artifactActions).checksum,
1087
+ runtime.currentExecution.type === "present" ? encodeHunsuRuntimeFile(runtime.currentExecution.value).checksum : "none",
1088
+ runtime.previousExecution.type === "present" ? encodeHunsuRuntimeFile(runtime.previousExecution.value).checksum : "none"
1089
+ ].join("\n")));
1090
+ }
1091
+
1092
+ function decodeRuntimeEnvelope(text: string, source: string, expectedHeader: string): Result<{ value: unknown; checksum: RuntimeChecksum }, DomainStoreError> {
1093
+ const normalized = text.replace(/\r\n/g, "\n");
1094
+ const separator = normalized.indexOf("\n\n");
1095
+ if (separator === -1) {
1096
+ return domainStoreError(`Invalid Hunsu runtime envelope in ${source}`);
1097
+ }
1098
+ const header = normalized.slice(0, separator).split("\n");
1099
+ const payload = normalized.slice(separator + 2).trim();
1100
+ if (header[0] !== expectedHeader) {
1101
+ return domainStoreError(`Invalid Hunsu runtime header in ${source}`);
1102
+ }
1103
+ const metadata = new Map(header.slice(1).map(line => {
1104
+ const index = line.indexOf(":");
1105
+ return index === -1 ? [line.trim(), ""] : [line.slice(0, index).trim(), line.slice(index + 1).trim()];
1106
+ }));
1107
+ if (metadata.get("encoding") !== HUNSU_RUNTIME_ENCODING) {
1108
+ return domainStoreError(`Unsupported Hunsu runtime encoding in ${source}: ${metadata.get("encoding") ?? "missing"}`);
1109
+ }
1110
+ const expectedChecksum = metadata.get("checksum")?.replace(/^sha256:/, "");
1111
+ if (!expectedChecksum) {
1112
+ return domainStoreError(`Missing Hunsu runtime checksum in ${source}`);
1113
+ }
1114
+ let json: string;
1115
+ try {
1116
+ json = gunzipSync(Buffer.from(payload, "base64url")).toString("utf8");
1117
+ } catch (error) {
1118
+ return domainStoreError(`Invalid Hunsu runtime payload in ${source}: ${error instanceof Error ? error.message : String(error)}`);
1119
+ }
1120
+ const actualChecksum = sha256(json);
1121
+ if (actualChecksum !== expectedChecksum) {
1122
+ return domainStoreError(`Hunsu runtime checksum mismatch in ${source}`);
1123
+ }
1124
+ try {
1125
+ return ok({ value: JSON.parse(json), checksum: parseRuntimeChecksum(actualChecksum) });
1126
+ } catch (error) {
1127
+ return domainStoreError(`Invalid Hunsu runtime JSON in ${source}: ${error instanceof Error ? error.message : String(error)}`);
1128
+ }
1129
+ }
1130
+
1131
+ function readLegacyHunsuRuntimeStateFromWorktree(cwd: string): { state: LegacyRuntimeState; checksum: RuntimeChecksum } | undefined {
1132
+ const root = ensureGitRepository(cwd);
1133
+ const path = join(root, HUNSU_LEGACY_STATE_PATH);
1134
+ if (!existsSync(path)) {
1135
+ return undefined;
1136
+ }
1137
+ const state = unwrapDomainStoreResult(decodeLegacyHunsuRuntimeStateText(readFileSync(path, "utf8"), path));
1138
+ return { state, checksum: checksumLegacyRuntimeState(state) };
1139
+ }
1140
+
1141
+ function readLegacyHunsuRuntimeStateAtRef(cwd: string, ref: string): { state: LegacyRuntimeState; checksum: RuntimeChecksum } | undefined {
1142
+ const root = ensureGitRepository(cwd);
1143
+ try {
1144
+ const text = git(["show", `${ref}:${HUNSU_LEGACY_STATE_PATH}`], { cwd: root });
1145
+ const state = unwrapDomainStoreResult(decodeLegacyHunsuRuntimeStateText(text, `${ref}:${HUNSU_LEGACY_STATE_PATH}`));
1146
+ return { state, checksum: checksumLegacyRuntimeState(state) };
1147
+ } catch (error) {
1148
+ if (error instanceof GitError) {
1149
+ return undefined;
1150
+ }
1151
+ throw error;
1152
+ }
1153
+ }
1154
+
1155
+ function decodeLegacyHunsuRuntimeStateText(text: string, source: string): Result<LegacyRuntimeState, DomainStoreError> {
1156
+ const decoded = decodeRuntimeEnvelope(text, source, LEGACY_STATE_HEADER);
1157
+ if (!decoded.ok) {
1158
+ return decoded;
1159
+ }
1160
+ const value = decoded.value.value;
1161
+ if (!value || typeof value !== "object") {
1162
+ return domainStoreError(`Invalid legacy Hunsu runtime state JSON in ${source}: expected object`);
1163
+ }
1164
+ const record = value as { version?: unknown; events?: unknown; updatedAt?: unknown };
1165
+ if (record.version !== 1 || !Array.isArray(record.events)) {
1166
+ return domainStoreError(`Invalid legacy Hunsu runtime state in ${source}`);
1167
+ }
1168
+ const events: DomainEvent[] = [];
1169
+ for (const [index, event] of record.events.entries()) {
1170
+ const validation = validateDomainEvent(event);
1171
+ if (!validation.ok) {
1172
+ return domainStoreError(`Invalid legacy Hunsu runtime state event ${index} in ${source}: ${validation.error.message}`);
1173
+ }
1174
+ events.push(validation.value);
1175
+ }
1176
+ return ok({
1177
+ version: 1,
1178
+ events,
1179
+ ...(typeof record.updatedAt === "string" ? { updatedAt: record.updatedAt } : {})
1180
+ });
1181
+ }
1182
+
1183
+ function checksumLegacyRuntimeState(state: LegacyRuntimeState): RuntimeChecksum {
1184
+ return parseRuntimeChecksum(sha256(`${JSON.stringify(state)}\n`));
1185
+ }
1186
+
1187
+ function domainStoreError(message: string): Result<never, DomainStoreError> {
1188
+ return err({ type: "DomainStoreError", message });
1189
+ }
1190
+
1191
+ function readDraftRuntimeJson(root: string, dir: string, fileName: HunsuDraftRuntimeFileName): Result<unknown, DomainStoreError> {
1192
+ const path = join(root, dir, fileName);
1193
+ try {
1194
+ return ok(JSON.parse(readFileSync(path, "utf8")) as unknown);
1195
+ } catch (error) {
1196
+ return domainStoreError(`Cannot read ${dir}/${fileName}: ${error instanceof Error ? error.message : String(error)}`);
1197
+ }
1198
+ }
1199
+
1200
+ function cloneJson<T>(value: T): T {
1201
+ return JSON.parse(JSON.stringify(value)) as T;
1202
+ }
1203
+
1204
+ function stableJson(value: unknown): string {
1205
+ return JSON.stringify(sortJson(value));
1206
+ }
1207
+
1208
+ function sortJson(value: unknown): unknown {
1209
+ if (Array.isArray(value)) {
1210
+ return value.map(sortJson);
1211
+ }
1212
+ if (value && typeof value === "object") {
1213
+ return Object.fromEntries(Object.entries(value as Record<string, unknown>)
1214
+ .sort(([left], [right]) => left.localeCompare(right))
1215
+ .map(([key, entry]) => [key, sortJson(entry)]));
1216
+ }
1217
+ return value;
1218
+ }
1219
+
1220
+ function unwrapDomainStoreResult<T>(result: Result<T, DomainStoreError>): T {
1221
+ if (result.ok) {
1222
+ return result.value;
1223
+ }
1224
+ throw new Error(result.error.message);
1225
+ }
1226
+
1227
+ function currentHeadCommit(cwd: string): CommitSha | undefined {
1228
+ try {
1229
+ return parseCommitSha(git(["rev-parse", "--verify", "HEAD^{commit}"], { cwd }).trim());
1230
+ } catch (error) {
1231
+ if (error instanceof GitError) {
1232
+ return undefined;
1233
+ }
1234
+ throw error;
1235
+ }
1236
+ }
1237
+
1238
+ function isMissingFileError(error: unknown): boolean {
1239
+ if (!(error instanceof Error)) {
1240
+ return false;
1241
+ }
1242
+ return "code" in error && (error as { code?: unknown }).code === "ENOENT";
1243
+ }
1244
+
1245
+ function sha256(text: string): string {
1246
+ return createHash("sha256").update(text).digest("hex");
1247
+ }
1248
+
1249
+ function parseDomainEventRef(line: string): DomainEventRef {
1250
+ const [ref, object, objectType] = line.split(DOMAIN_EVENT_REF_SEPARATOR);
1251
+ return {
1252
+ ref,
1253
+ object,
1254
+ objectType,
1255
+ ordinal: parseDomainEventOrdinal(ref)
1256
+ };
1257
+ }
1258
+
1259
+ function parseDomainEventOrdinal(ref: string): number {
1260
+ const leaf = ref.slice(ref.lastIndexOf("/") + 1);
1261
+ const match = leaf.match(/^E(\d+)(?:-|$)/);
1262
+ return match ? Number.parseInt(match[1], 10) : Number.MAX_SAFE_INTEGER;
1263
+ }