@hypercarrier/pi-team-durable 0.0.0-stage → 0.1.0-rc.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.
Files changed (48) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +209 -2
  3. package/dist/authority/anchor.d.ts +10 -0
  4. package/dist/authority/anchor.js +19 -0
  5. package/dist/authority/card-types.d.ts +152 -0
  6. package/dist/authority/card-types.js +123 -0
  7. package/dist/authority/contracts.d.ts +19 -0
  8. package/dist/authority/contracts.js +45 -0
  9. package/dist/authority/delivery.d.ts +60 -0
  10. package/dist/authority/delivery.js +158 -0
  11. package/dist/authority/graph-card.d.ts +4 -0
  12. package/dist/authority/graph-card.js +39 -0
  13. package/dist/authority/graph-control.d.ts +299 -0
  14. package/dist/authority/graph-control.js +1009 -0
  15. package/dist/authority/incremental-graph-control.d.ts +156 -0
  16. package/dist/authority/incremental-graph-control.js +1051 -0
  17. package/dist/authority/index.d.ts +15 -0
  18. package/dist/authority/index.js +15 -0
  19. package/dist/authority/interrupt.d.ts +11 -0
  20. package/dist/authority/interrupt.js +26 -0
  21. package/dist/authority/limits.d.ts +7 -0
  22. package/dist/authority/limits.js +7 -0
  23. package/dist/authority/notifier.d.ts +32 -0
  24. package/dist/authority/notifier.js +89 -0
  25. package/dist/authority/observation-store.d.ts +104 -0
  26. package/dist/authority/observation-store.js +226 -0
  27. package/dist/authority/observation.d.ts +13 -0
  28. package/dist/authority/observation.js +143 -0
  29. package/dist/authority/panel.d.ts +121 -0
  30. package/dist/authority/panel.js +44 -0
  31. package/dist/authority/projection.d.ts +5 -0
  32. package/dist/authority/projection.js +15 -0
  33. package/dist/authority/rc7-contract.json +9390 -0
  34. package/dist/authority/runtime.d.ts +106 -0
  35. package/dist/authority/runtime.js +115 -0
  36. package/dist/authority/state.d.ts +165 -0
  37. package/dist/authority/state.js +28 -0
  38. package/dist/authority/store.d.ts +144 -0
  39. package/dist/authority/store.js +675 -0
  40. package/dist/authority/sync.d.ts +13 -0
  41. package/dist/authority/sync.js +78 -0
  42. package/dist/authority/task-version-ref.d.ts +3 -0
  43. package/dist/authority/task-version-ref.js +5 -0
  44. package/dist/authority/tools.d.ts +105 -0
  45. package/dist/authority/tools.js +302 -0
  46. package/dist/testing.d.ts +11 -0
  47. package/dist/testing.js +10 -0
  48. package/package.json +63 -4
@@ -0,0 +1,106 @@
1
+ import type { Context } from '@earendil-works/chord/context';
2
+ import { type Harness, type Extension } from '@earendil-works/pi-durable';
3
+ import { type CoreApi, type CoreOptions } from './tools.ts';
4
+ import type { AbortRun } from './interrupt.ts';
5
+ import { type ObservationPortResolver } from './observation.ts';
6
+ import { type StopIntent } from './state.ts';
7
+ export interface StopPlan {
8
+ id: string;
9
+ conversations?: string[];
10
+ tasks?: string[];
11
+ }
12
+ export type StopOutcome = {
13
+ status: 'settled';
14
+ tasks: Record<string, string>;
15
+ } | {
16
+ status: 'failed';
17
+ tasks: Record<string, string>;
18
+ error: string;
19
+ };
20
+ export declare const stopPlan: (id: string, intent: StopIntent) => StopPlan;
21
+ export declare function pendingStops(harness: Harness, context: Context): Promise<StopPlan[]>;
22
+ export declare function confirmStop(harness: Harness, id: string, outcome: StopOutcome, context: Context, now?: () => number): Promise<void>;
23
+ /** Called by NodePlugin.closing after its own lead Close intent is stored. */
24
+ export declare function closing(harness: Harness, conversationId: string, context: Context): Promise<StopPlan[]>;
25
+ export interface RuntimeOptions extends Pick<CoreOptions, 'modelRoles' | 'defaultModelRole' | 'catalog' | 'goalMaxLength' | 'resolveModelRole'> {
26
+ observationPort: ObservationPortResolver;
27
+ abortRun: AbortRun;
28
+ stop: (api: CoreApi, plans: StopPlan[], context: Context) => Promise<StopOutcome[]>;
29
+ }
30
+ export declare function createTeamRuntime(options: RuntimeOptions): {
31
+ core: {
32
+ lead: {
33
+ label: string;
34
+ name: string;
35
+ description: string;
36
+ parameters: import("typebox").TSchema;
37
+ constrainedSampling?: false | import("@earendil-works/pi-ai").ConstrainedSamplingConfig;
38
+ replay?: "safe" | "unsafe";
39
+ executionMode?: import("@earendil-works/pi-durable").ToolExecutionMode;
40
+ prepareArguments?(args: unknown): unknown;
41
+ structuredOutputSchema?: import("typebox").TSchema;
42
+ callers?: readonly ("model" | "tools")[];
43
+ deferred?: true;
44
+ outputLimits?: {
45
+ readonly maxBytes?: number;
46
+ readonly maxLines?: number;
47
+ readonly retain?: "head" | "tail";
48
+ };
49
+ execute(args: unknown, api: import("@earendil-works/pi-durable").ToolExecutionApi<import("@earendil-works/chord").JsonValue>, context: Context): Promise<import("@earendil-works/pi-durable").ToolExecutionResult<import("@earendil-works/chord").JsonValue>>;
50
+ }[];
51
+ worker: {
52
+ label: string;
53
+ name: string;
54
+ description: string;
55
+ parameters: import("typebox").TSchema;
56
+ constrainedSampling?: false | import("@earendil-works/pi-ai").ConstrainedSamplingConfig;
57
+ replay?: "safe" | "unsafe";
58
+ executionMode?: import("@earendil-works/pi-durable").ToolExecutionMode;
59
+ prepareArguments?(args: unknown): unknown;
60
+ structuredOutputSchema?: import("typebox").TSchema;
61
+ callers?: readonly ("model" | "tools")[];
62
+ deferred?: true;
63
+ outputLimits?: {
64
+ readonly maxBytes?: number;
65
+ readonly maxLines?: number;
66
+ readonly retain?: "head" | "tail";
67
+ };
68
+ execute(args: unknown, api: import("@earendil-works/pi-durable").ToolExecutionApi<import("@earendil-works/chord").JsonValue>, context: Context): Promise<import("@earendil-works/pi-durable").ToolExecutionResult<import("@earendil-works/chord").JsonValue>>;
69
+ }[];
70
+ execute: (name: import("./contracts.ts").ToolName, role: import("./contracts.ts").Role, input: unknown, api: CoreApi, context: Context) => Promise<import("./state.ts").Result>;
71
+ contract: import("./contracts.ts").Contract;
72
+ };
73
+ lead: Extension<import("@earendil-works/pi-durable").ToolRegistration<import("typebox").TSchema, import("@earendil-works/chord").JsonValue>>;
74
+ worker: Extension<import("@earendil-works/pi-durable").ToolRegistration<import("typebox").TSchema, import("@earendil-works/chord").JsonValue>>;
75
+ mechanics: Extension<import("@earendil-works/pi-durable").ToolRegistration<import("typebox").TSchema, import("@earendil-works/chord").JsonValue>>;
76
+ observation: Extension<import("@earendil-works/pi-durable").ToolRegistration<import("typebox").TSchema, import("@earendil-works/chord").JsonValue>>;
77
+ extensions: Extension<import("@earendil-works/pi-durable").ToolRegistration<import("typebox").TSchema, import("@earendil-works/chord").JsonValue>>[];
78
+ tasks: {
79
+ WorkerAnchor: import("@earendil-works/pi-durable").Task<null, {
80
+ phase: "hold";
81
+ }, null, object>;
82
+ Deliver: import("@earendil-works/pi-durable").Task<import("./delivery.ts").DeliveryInput, {
83
+ phase: "interrupt";
84
+ } | {
85
+ phase: "submit";
86
+ } | {
87
+ phase: "settle";
88
+ submissionId: import("@earendil-works/pi-durable").SubmissionId;
89
+ }, null, object>;
90
+ Notify: import("@earendil-works/pi-durable").Task<{
91
+ epoch: string;
92
+ }, {
93
+ phase: "tick";
94
+ ordinal: number;
95
+ due?: number;
96
+ } | {
97
+ phase: "submit";
98
+ pageId: string;
99
+ ordinal: number;
100
+ } | {
101
+ phase: "settle";
102
+ pageId: string;
103
+ ordinal: number;
104
+ }, null, object>;
105
+ };
106
+ };
@@ -0,0 +1,115 @@
1
+ import { configure } from '@earendil-works/pi-durable';
2
+ import { catalogOf, createAuthorityTools } from "./tools.js";
3
+ import { createAnchoredConversation, WorkerAnchor } from "./anchor.js";
4
+ import { createDeliver, scheduleDeliveries } from "./delivery.js";
5
+ import { createNotifier } from "./notifier.js";
6
+ import { openObservations, startObservationEpoch, observationExtension } from "./observation.js";
7
+ import { sync } from "./sync.js";
8
+ import { event } from "./state.js";
9
+ import { openAuthority as open, flushAuthority, allObligations, setObligationState } from "./store.js";
10
+ export const stopPlan = (id, intent) => ({ id, conversations: intent.conversations.map(String), tasks: intent.tasks.map(String) });
11
+ export async function pendingStops(harness, context) {
12
+ return harness.commit(async (tx) => Object.entries((await open(tx)).team.stops).filter(([, i]) => !i.confirmed).map(([id, i]) => stopPlan(id, i)), context);
13
+ }
14
+ export async function confirmStop(harness, id, outcome, context, now = Date.now) {
15
+ await harness.commit(async (tx) => {
16
+ const s = await open(tx), intent = s.team.stops[id];
17
+ if (!intent || intent.confirmed)
18
+ return;
19
+ if (outcome.status !== 'settled') {
20
+ intent.error = outcome.error;
21
+ return;
22
+ }
23
+ // Confirm the exact persisted targets, including tasks already terminal before mark.
24
+ for (const target of intent.tasks) {
25
+ const task = await tx.task(target);
26
+ if (!task || task.state.status !== 'terminal')
27
+ throw new Error('PTB stop target is not terminal');
28
+ }
29
+ if (s.team.current?.epoch !== intent.epoch)
30
+ throw new Error('PTB stop epoch changed');
31
+ const worker = intent.worker ? s.team.current.workers[intent.worker] : undefined;
32
+ if (intent.binding && (!worker || worker.generation !== intent.generation || worker.anchorId !== intent.binding.anchorId || worker.conversationId !== intent.binding.conversationId))
33
+ throw new Error('PTB stop binding changed');
34
+ intent.confirmed = true;
35
+ delete intent.error;
36
+ if (worker) {
37
+ worker.state = 'stopped';
38
+ await event(tx, s, 'team-lead', 'worker_stopped', { worker: worker.name, at: new Date(now()).toISOString() });
39
+ }
40
+ if (s.team.current.shutdownPending && Object.values(s.team.stops).filter(i => i.epoch === intent.epoch).every(i => i.confirmed)) {
41
+ s.team.current.lifecycle = 'stopped';
42
+ await event(tx, s, 'team-lead', 'team_stopped', { at: new Date(now()).toISOString() });
43
+ }
44
+ }, context);
45
+ }
46
+ async function addMechanicStops(s, shutdown) {
47
+ const team = s.team.current, obligations = await allObligations(s);
48
+ for (const intent of Object.values(s.team.stops)) {
49
+ if (intent.epoch !== team.epoch || intent.confirmed)
50
+ continue;
51
+ for (const o of obligations)
52
+ if (o.epoch === team.epoch && o.recipient === intent.worker && o.deliveryTaskId && !intent.tasks.includes(o.deliveryTaskId))
53
+ intent.tasks.push(o.deliveryTaskId);
54
+ }
55
+ if (!shutdown)
56
+ return;
57
+ const key = `${team.epoch}:shutdown-mechanics`;
58
+ const tasks = obligations.filter(o => o.epoch === team.epoch && o.deliveryTaskId).map(o => o.deliveryTaskId);
59
+ if (team.notifierId)
60
+ tasks.push(team.notifierId);
61
+ s.team.stops[key] ??= { epoch: team.epoch, tasks, conversations: [], confirmed: false };
62
+ return key;
63
+ }
64
+ /** Called by NodePlugin.closing after its own lead Close intent is stored. */
65
+ export async function closing(harness, conversationId, context) {
66
+ return harness.commit(async (tx) => {
67
+ const s = await open(tx), team = s.team.current;
68
+ if (!team || String(team.lead) !== conversationId || team.lifecycle !== 'active')
69
+ return [];
70
+ team.shutdownPending = true;
71
+ for (const w of Object.values(team.workers))
72
+ if (w.state !== 'stopped') {
73
+ const key = `${team.epoch}:stop:${w.name}:g${w.generation}`;
74
+ w.state = 'stopping';
75
+ s.team.stops[key] ??= { epoch: team.epoch, worker: w.name, generation: w.generation, binding: { conversationId: w.conversationId, anchorId: w.anchorId }, tasks: [w.anchorId], conversations: [w.conversationId], confirmed: false };
76
+ }
77
+ for (const o of await allObligations(s))
78
+ if (o.epoch === team.epoch)
79
+ await setObligationState(s, o, 'retired');
80
+ await addMechanicStops(s, true);
81
+ flushAuthority(s);
82
+ return Object.entries(s.team.stops).filter(([, i]) => i.epoch === team.epoch && !i.confirmed).map(([id, i]) => stopPlan(id, i));
83
+ }, context);
84
+ }
85
+ export function createTeamRuntime(options) {
86
+ const Notify = createNotifier(catalogOf(options));
87
+ const Deliver = createDeliver(options.abortRun);
88
+ let lead, worker;
89
+ const core = createAuthorityTools({ ...options, sync,
90
+ createWorker: async (tx, role) => {
91
+ const s = await open(tx), binding = await createAnchoredConversation(tx, s.team.current.lead);
92
+ await configure(tx, binding.conversationId, { model: role.model, ...(role.thinking ? { thinkingLevel: role.thinking } : {}), extensions: { remove: [lead], add: [worker] } });
93
+ return binding;
94
+ },
95
+ settleStops: async (stops, context, api) => stops.length ? (await options.stop(api, stops.map(s => stopPlan(s.key, s.intent)), context)).map(o => o.status === 'settled') : [],
96
+ afterCommand: async (tx, s, name, result) => {
97
+ const team = s.team.current;
98
+ if (!team || team.lifecycle !== 'active')
99
+ return;
100
+ if (name === 'team_create') {
101
+ startObservationEpoch(await openObservations(tx), team.epoch);
102
+ }
103
+ if (!team.notifierId && !team.shutdownPending)
104
+ team.notifierId = await tx.createTask(Notify, { epoch: team.epoch }, { conversationId: team.lead, ownership: { kind: 'conversation' }, background: true, abandonOnRestart: false });
105
+ await scheduleDeliveries(tx, s, Deliver);
106
+ const extra = name === 'worker_stop' || name === 'team_shutdown' ? await addMechanicStops(s, name === 'team_shutdown') : undefined;
107
+ if (extra && Array.isArray(result.stops) && !result.stops.includes(extra))
108
+ result.stops.push(extra);
109
+ }, });
110
+ lead = { name: 'ptb.lead', tools: core.lead };
111
+ worker = { name: 'ptb.worker', tools: core.worker };
112
+ const mechanics = { name: 'ptb.mechanics', tasks: [WorkerAnchor, Deliver, Notify] };
113
+ const observation = observationExtension(options.observationPort);
114
+ return { core, lead, worker, mechanics, observation, extensions: [mechanics, lead, worker, observation], tasks: { WorkerAnchor, Deliver, Notify } };
115
+ }
@@ -0,0 +1,165 @@
1
+ import { type ConversationId, type TaskId, type SubmissionId, type EntryId, type JsonObject, type Tx } from '@earendil-works/pi-durable';
2
+ import type { GraphControlSnapshot } from './graph-control.ts';
3
+ export interface Binding {
4
+ conversationId: ConversationId;
5
+ anchorId: TaskId;
6
+ }
7
+ export interface ModelRole {
8
+ name: string;
9
+ use: string;
10
+ model: {
11
+ provider: string;
12
+ modelId: string;
13
+ };
14
+ thinking?: string;
15
+ }
16
+ /** The roles a lead can select, with the role ensure_worker uses when the call names none. */
17
+ export interface ModelRoleCatalog {
18
+ modelRoles: ModelRole[];
19
+ defaultModelRole?: string;
20
+ }
21
+ export interface Worker extends Binding {
22
+ createdAt?: number;
23
+ name: string;
24
+ scope: string;
25
+ generation: number;
26
+ state: 'active' | 'stopping' | 'stopped';
27
+ role: ModelRole;
28
+ }
29
+ export interface Team {
30
+ createdAt?: number;
31
+ epoch: string;
32
+ name: string;
33
+ purpose: string;
34
+ lead: ConversationId;
35
+ lifecycle: 'active' | 'stopped';
36
+ workers: Record<string, Worker>;
37
+ shutdownPending?: boolean;
38
+ notifierId?: TaskId;
39
+ }
40
+ export interface StopIntent {
41
+ epoch: string;
42
+ worker?: string;
43
+ binding?: Binding;
44
+ generation?: number;
45
+ tasks: TaskId[];
46
+ conversations: ConversationId[];
47
+ confirmed: boolean;
48
+ error?: string;
49
+ }
50
+ export interface TeamState {
51
+ current?: Team;
52
+ history: Team[];
53
+ stops: Record<string, StopIntent>;
54
+ }
55
+ export interface GraphState {
56
+ epoch?: string;
57
+ snapshot?: GraphControlSnapshot;
58
+ history?: Record<string, GraphControlSnapshot>;
59
+ }
60
+ export interface Alert {
61
+ interrupt?: true;
62
+ id: string;
63
+ from: string;
64
+ kind: string;
65
+ text: string;
66
+ task_id?: string;
67
+ task_version?: string;
68
+ receivedAt: string;
69
+ recipients: {
70
+ name: string;
71
+ conversationId: ConversationId;
72
+ generation: number;
73
+ }[];
74
+ }
75
+ export interface Obligation {
76
+ interrupt?: true;
77
+ interruptRun?: TaskId;
78
+ interruption?: 'interrupted' | 'ended' | 'failed';
79
+ acceptedAt?: number;
80
+ submittedAt?: number;
81
+ settledAt?: number;
82
+ key: string;
83
+ epoch: string;
84
+ kind: 'task' | 'stop' | 'alert';
85
+ recipient: string;
86
+ conversationId: ConversationId;
87
+ generation: number;
88
+ taskId?: string;
89
+ version?: string;
90
+ alertId?: string;
91
+ state: 'pending' | 'retired' | 'settled';
92
+ deliveryTaskId?: TaskId;
93
+ submissionId?: SubmissionId;
94
+ outcome?: string;
95
+ }
96
+ export interface OutboxState {
97
+ alerts: Record<string, Alert>;
98
+ obligations: Record<string, Obligation>;
99
+ }
100
+ export interface Event {
101
+ seq: number;
102
+ epoch: string;
103
+ actor: string;
104
+ kind: string;
105
+ taskId?: string;
106
+ taskIds?: string[];
107
+ worker?: string;
108
+ at?: string;
109
+ text?: string;
110
+ entryId?: EntryId;
111
+ }
112
+ export type JournalRef = Event | {
113
+ seq: number;
114
+ entryId: EntryId;
115
+ };
116
+ export interface JournalState {
117
+ seq: number;
118
+ events: Event[];
119
+ reservation?: {
120
+ epoch: string;
121
+ call: string;
122
+ through: number;
123
+ };
124
+ acknowledged: number;
125
+ }
126
+ export type Result = Record<string, unknown> & {
127
+ kind: string;
128
+ };
129
+ export interface Receipt {
130
+ fingerprint: string;
131
+ result?: Result;
132
+ stops?: string[];
133
+ epoch?: string;
134
+ }
135
+ export interface ReceiptState {
136
+ calls: Record<string, Receipt>;
137
+ }
138
+ export declare const TeamDoc: import("@earendil-works/pi-durable").SessionDocToken<JsonObject>;
139
+ export declare const GraphDoc: import("@earendil-works/pi-durable").SessionDocToken<JsonObject>;
140
+ export declare const JournalDoc: import("@earendil-works/pi-durable").SessionDocToken<JsonObject>;
141
+ export declare const OutboxDoc: import("@earendil-works/pi-durable").SessionDocToken<JsonObject>;
142
+ export declare const ReceiptDoc: import("@earendil-works/pi-durable").SessionDocToken<JsonObject>;
143
+ export declare function hasLegacyFence(value: object): boolean;
144
+ /** Keep the v2 address occupied so an old reader cannot create a v1 incarnation. */
145
+ export declare function fenceLegacyDoc(value: object): void;
146
+ export interface State {
147
+ team: TeamState;
148
+ graph: GraphState;
149
+ journal: JournalState;
150
+ outbox: OutboxState;
151
+ receipts: ReceiptState;
152
+ }
153
+ /** Full historical inspection. Runtime commands use openAuthority's indexed state. */
154
+ export declare function open(tx: Tx): Promise<State>;
155
+ export declare const plain: <T>(value: T) => T;
156
+ export declare const JOURNAL_RESIDENT_LIMIT = 100;
157
+ /** History is append-only storage; the document contains a bounded recent projection. */
158
+ export declare function event(tx: Tx, s: {
159
+ team: TeamState;
160
+ journal: {
161
+ seq: number;
162
+ events: JournalRef[];
163
+ };
164
+ flush?: () => void;
165
+ }, actor: string, kind: string, extra?: Pick<Event, 'taskId' | 'taskIds' | 'worker' | 'at' | 'text'>): Promise<void>;
@@ -0,0 +1,28 @@
1
+ import { defineDoc } from '@earendil-works/pi-durable';
2
+ const doc = (kind, initial) => defineDoc({ kind, version: 2, migrate: value => value, scope: 'session', checkpointWhen: () => true, initial });
3
+ export const TeamDoc = doc('ptb.team', () => ({ history: [], stops: {} }));
4
+ export const GraphDoc = doc('ptb.graph', () => ({}));
5
+ export const JournalDoc = doc('ptb.journal', () => ({ seq: 0, events: [], acknowledged: 0 }));
6
+ export const OutboxDoc = doc('ptb.outbox', () => ({ alerts: {}, obligations: {} }));
7
+ export const ReceiptDoc = doc('ptb.receipts', () => ({ calls: {} }));
8
+ const fenceMarker = 'ptb-authority-v2';
9
+ export function hasLegacyFence(value) { return value.fence === fenceMarker; }
10
+ /** Keep the v2 address occupied so an old reader cannot create a v1 incarnation. */
11
+ export function fenceLegacyDoc(value) {
12
+ for (const key of Object.keys(value))
13
+ Reflect.deleteProperty(value, key);
14
+ Object.assign(value, { fence: fenceMarker });
15
+ }
16
+ /** Full historical inspection. Runtime commands use openAuthority's indexed state. */
17
+ export async function open(tx) {
18
+ return (await import("./store.js")).inspectAuthority(tx);
19
+ }
20
+ export const plain = (value) => JSON.parse(JSON.stringify(value));
21
+ export const JOURNAL_RESIDENT_LIMIT = 100;
22
+ /** History is append-only storage; the document contains a bounded recent projection. */
23
+ export async function event(tx, s, actor, kind, extra = {}) {
24
+ const value = { seq: ++s.journal.seq, epoch: s.team.current.epoch, actor, kind, ...extra };
25
+ const entry = await tx.appendEntry(s.team.current.lead, { kind: 'ptb.event', data: value });
26
+ s.journal.events = [...s.journal.events, { ...value, entryId: entry.id }].slice(-JOURNAL_RESIDENT_LIMIT);
27
+ s.flush?.();
28
+ }
@@ -0,0 +1,144 @@
1
+ import { type Tx, type JsonObject, type ConversationId, type TaskId } from '@earendil-works/pi-durable';
2
+ import { type GraphControlSnapshot, type GraphApplyInput, type GraphTaskTransitionInput } from './graph-control.ts';
3
+ import { type GraphMaterializedHead, type GraphMaterializedTask } from './incremental-graph-control.ts';
4
+ import type { GraphTaskCard } from './card-types.ts';
5
+ import { type TeamState, type JournalState, type JournalRef, type Event, type Alert, type Obligation, type Receipt, type State } from './state.ts';
6
+ type GraphHead = Omit<GraphMaterializedHead, 'topology' | 'projections'>;
7
+ export interface AuthorityHead {
8
+ initialized: boolean;
9
+ legacyFenced?: boolean;
10
+ epoch?: string;
11
+ graph?: GraphHead;
12
+ taskCount: number;
13
+ log?: ConversationId;
14
+ journal: Omit<JournalState, 'events'> & {
15
+ events: string;
16
+ };
17
+ pendingBuckets: Record<string, true>;
18
+ unscheduledBuckets: Record<string, true>;
19
+ obligationSequence: number;
20
+ recentObligations: string[];
21
+ recentAlerts: string[];
22
+ leadAlerts: string[];
23
+ leadAlertCount: number;
24
+ obligationTail?: string;
25
+ alertTail?: string;
26
+ callTail?: string;
27
+ attention: Record<string, 'blocked' | 'failed'>;
28
+ frontier: Record<string, {
29
+ id: string;
30
+ version: string;
31
+ generation: number;
32
+ }>;
33
+ taskObligations: Record<string, string[]>;
34
+ workerBindings: Record<string, string>;
35
+ stopRefresh?: boolean;
36
+ }
37
+ export declare const HeadDoc: import("@earendil-works/pi-durable").SessionDocToken<JsonObject>;
38
+ export declare const TaskDoc: import("@earendil-works/pi-durable").SessionDocFamilyToken<JsonObject, null>;
39
+ export declare const GraphIndexDoc: import("@earendil-works/pi-durable").SessionDocFamilyToken<JsonObject, null>;
40
+ export declare const WorkerIndexDoc: import("@earendil-works/pi-durable").SessionDocFamilyToken<JsonObject, null>;
41
+ export declare const OrdinalDoc: import("@earendil-works/pi-durable").SessionDocFamilyToken<JsonObject, null>;
42
+ export declare const OperationDoc: import("@earendil-works/pi-durable").SessionDocFamilyToken<JsonObject, null>;
43
+ export declare const ObligationDoc: import("@earendil-works/pi-durable").SessionDocFamilyToken<JsonObject, null>;
44
+ export declare const EligibilityDoc: import("@earendil-works/pi-durable").SessionDocFamilyToken<JsonObject, null>;
45
+ export declare const AlertDoc: import("@earendil-works/pi-durable").SessionDocFamilyToken<JsonObject, null>;
46
+ export declare const DirectCallDoc: import("@earendil-works/pi-durable").SessionDocFamilyToken<JsonObject, null>;
47
+ export declare const CallDoc: import("@earendil-works/pi-durable").TaskDocToken<JsonObject>;
48
+ export declare const taskAddress: (epoch: string, id: string) => string;
49
+ export interface OperatorTask {
50
+ key: string;
51
+ title: string;
52
+ goal: string;
53
+ assignee: string;
54
+ needs: string[];
55
+ version: string;
56
+ current_context: string;
57
+ attempts: {
58
+ id: string;
59
+ ordinal: number;
60
+ startedAt?: number;
61
+ endedAt?: number;
62
+ outcome?: string;
63
+ evidence?: string;
64
+ }[];
65
+ derived: string;
66
+ status: string;
67
+ derivedReason?: string;
68
+ evidence?: string;
69
+ }
70
+ export interface TaskRecord {
71
+ materialized: GraphMaterializedTask;
72
+ card: GraphTaskCard;
73
+ operator: OperatorTask;
74
+ }
75
+ interface StoredCall {
76
+ fingerprint?: string;
77
+ result?: string;
78
+ stops?: string[];
79
+ epoch?: string;
80
+ previous?: string;
81
+ }
82
+ type CurrentJournal = Omit<JournalState, 'events'> & {
83
+ events: JournalRef[];
84
+ };
85
+ interface Eligibility {
86
+ doc: JsonObject;
87
+ pending: Record<string, number>;
88
+ unscheduled: Record<string, number>;
89
+ }
90
+ export interface Authority {
91
+ tx: Tx;
92
+ team: TeamState;
93
+ head: AuthorityHead;
94
+ journal: CurrentJournal;
95
+ headDoc: JsonObject;
96
+ deferFlush: boolean;
97
+ flush: () => void;
98
+ records: Map<string, TaskRecord | undefined>;
99
+ obligations: Map<string, Obligation>;
100
+ eligibility: Map<string, Eligibility>;
101
+ newObligations: Set<string>;
102
+ calls: Map<number, {
103
+ doc: StoredCall;
104
+ native: boolean;
105
+ }>;
106
+ workerIndexes: Map<string, string[]>;
107
+ migratedHistory?: Map<string, GraphControlSnapshot>;
108
+ }
109
+ export declare function recentEvents(s: Authority, refs?: JournalRef[]): Promise<Event[]>;
110
+ export declare function flushAuthority(s: Authority): void;
111
+ export declare function openAuthority(tx: Tx): Promise<Authority>;
112
+ export declare function startEpoch(s: Authority, epoch: string): Promise<void>;
113
+ export declare function taskIds(s: Authority): Promise<string[]>;
114
+ export declare function taskRecord(s: Authority, id: string): Promise<TaskRecord | undefined>;
115
+ export declare function taskCards(s: Authority, ids?: string[]): Promise<GraphTaskCard[]>;
116
+ export declare function unfinished(s: Authority, worker?: string): Promise<string[]>;
117
+ export declare function obligation(s: Authority, key: string): Promise<Obligation | undefined>;
118
+ export declare function markScheduled(s: Authority, key: string): Promise<void>;
119
+ export declare function unscheduledObligations(s: Authority): Promise<Obligation[]>;
120
+ export declare function addObligation(s: Authority, value: Obligation): Promise<void>;
121
+ export declare function setObligationState(s: Authority, value: Obligation, state: Obligation['state']): Promise<void>;
122
+ export declare function allObligations(s: Authority): Promise<Obligation[]>;
123
+ export declare function pendingObligations(s: Authority): Promise<Obligation[]>;
124
+ export declare function alertRecord(s: Authority, id: string): Promise<Alert | undefined>;
125
+ export declare function addAlert(s: Authority, value: Alert): Promise<void>;
126
+ export declare function callReceipt(s: Authority, id: TaskId, native?: boolean): Promise<StoredCall>;
127
+ export declare function saveCall(s: Authority, id: TaskId, receipt: Receipt): Promise<void>;
128
+ export declare function hasOperation(s: Authority, operationId: string): Promise<boolean>;
129
+ export declare function graphCommand(s: Authority, command: {
130
+ kind: 'apply';
131
+ input: GraphApplyInput;
132
+ } | {
133
+ kind: 'transition';
134
+ input: GraphTaskTransitionInput;
135
+ }, now: () => number): Promise<(import("./graph-control.ts").GraphApplyResult & {
136
+ replayed: boolean;
137
+ }) | (import("./graph-control.ts").GraphTransitionResult & {
138
+ replayed: boolean;
139
+ })>;
140
+ /** History materialization for diagnostics, migration checks, and generation reconciliation. */
141
+ export declare function readGraphHistory(s: Authority, epoch?: string): Promise<GraphControlSnapshot>;
142
+ /** Legacy-shaped, full inspection for diagnostics and existing recovery tests. */
143
+ export declare function inspectAuthority(tx: Tx): Promise<State>;
144
+ export {};