@volter/supercode-orchestrator 0.4.79 → 0.4.81
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/board/ztrack.mjs +5 -3
- package/ontology.d.ts +225 -0
- package/package.json +1 -1
package/board/ztrack.mjs
CHANGED
|
@@ -140,13 +140,15 @@ class ZtrackBoard {
|
|
|
140
140
|
const status = old.stage ?? task.status;
|
|
141
141
|
const mapped = source.mapping[status];
|
|
142
142
|
if (!mapped) throw new Error(`migration needs an explicit mapping for ${status} (${task.id})`);
|
|
143
|
-
|
|
143
|
+
let stage = typeof mapped === 'string' ? mapped : mapped.status;
|
|
144
|
+
if (mapped.preserve_completed && task.completed_at) stage = 'done';
|
|
144
145
|
const parents = this.mem.prepare('SELECT parent_id FROM task_links WHERE child_id = ?').all(task.id).map((p) => ({ id: p.parent_id, kind: 'card' }));
|
|
145
146
|
const last = this.mem.prepare("SELECT kind, payload FROM task_events WHERE task_id = ? AND kind IN ('blocked','unblocked') ORDER BY id DESC LIMIT 1").get(task.id);
|
|
146
147
|
const wait = last?.kind === 'blocked' ? json(last.payload, {})?.waiting_on : null;
|
|
147
148
|
if (wait) parents.push({ id: wait, kind: 'message' });
|
|
148
149
|
this.insert('supercode_cards', { ...old, task_id: task.id, stage, archived: Number(Boolean(mapped.archived) || stage === 'cancelled'), blocked_by: JSON.stringify(parents),
|
|
149
|
-
|
|
150
|
+
every: mapped.every ?? old.every ?? null, next_run_at: mapped.every ? now() : old.next_run_at,
|
|
151
|
+
paused: mapped.paused ? JSON.stringify({ by: actorOf() ?? 'migration', reason: `migrated ${status}: ${json(last?.payload, {})?.reason ?? 'held by previous workflow'}` }) : null });
|
|
150
152
|
this.mem.prepare('UPDATE tasks SET status = ? WHERE id = ?').run(stage, task.id);
|
|
151
153
|
if (task.current_run_id && ['done','cancelled'].includes(stage)) {
|
|
152
154
|
this.mem.prepare("UPDATE task_runs SET ended_at = COALESCE(ended_at, ?), status = 'reclaimed', outcome = COALESCE(outcome, 'reclaimed') WHERE id = ?").run(now(), task.current_run_id);
|
|
@@ -186,7 +188,7 @@ class ZtrackBoard {
|
|
|
186
188
|
this.taskKeys.set(tid, `${id}:${task.id}`);
|
|
187
189
|
const body = task.metadata?.body ?? '';
|
|
188
190
|
const taskCard = { ...task.metadata?.card, id: tid, title: `${task.id} ${task.text}`, body,
|
|
189
|
-
status: task.status === 'passed' ? 'done' : (task.metadata?.status
|
|
191
|
+
status: task.status === 'passed' ? (task.metadata?.status === 'cancelled' ? 'cancelled' : 'done') : (['done','cancelled'].includes(task.metadata?.status) ? 'todo' : task.metadata?.status ?? 'todo'),
|
|
190
192
|
metadata: task.metadata?.properties ?? {}, assignee: task.metadata?.assignee ?? card.assignee,
|
|
191
193
|
machine: task.metadata?.machine ?? card.machine, acceptanceCriteria: [],
|
|
192
194
|
acceptance: task.lines ?? [], relations: (task.blockedBy ?? []).map((b) => ({ type: 'blocked-by', issueId: b.ac ? `${nativeId(b.issue)}:${b.ac}` : nativeId(b.issue) })) };
|
package/ontology.d.ts
CHANGED
|
@@ -20,6 +20,17 @@ export type AccessPolicy =
|
|
|
20
20
|
/** Anyone. */
|
|
21
21
|
| 'open';
|
|
22
22
|
|
|
23
|
+
/**
|
|
24
|
+
* One step a transition, an entry or an exit takes: a primitive the engine provides, named, with its arguments
|
|
25
|
+
* (`notify: {roles: [creator], template: …}`). Written as a one-key map.
|
|
26
|
+
*/
|
|
27
|
+
export interface Action {
|
|
28
|
+
/** The primitive (`assign`, `count`, `reset`, `notify`, `comment`, `send_to_actor`, `close_session`, …). */
|
|
29
|
+
name: string;
|
|
30
|
+
/** Its arguments, as written. */
|
|
31
|
+
args: unknown;
|
|
32
|
+
}
|
|
33
|
+
|
|
23
34
|
/** What one artifact reached on the way in or out. */
|
|
24
35
|
export interface ArtifactFidelity {
|
|
25
36
|
/** Path relative to the home the codec read or wrote. */
|
|
@@ -90,6 +101,45 @@ export interface ChannelConfig {
|
|
|
90
101
|
extra?: Record<string, unknown>;
|
|
91
102
|
}
|
|
92
103
|
|
|
104
|
+
/** A transition taken once a duration has passed in the status (XState's `after`, ASL's `Wait`). */
|
|
105
|
+
export interface Delayed {
|
|
106
|
+
/** How long, in seconds (an expression). */
|
|
107
|
+
after: Expr;
|
|
108
|
+
/** Source statuses; empty applies from every status. */
|
|
109
|
+
from?: string[];
|
|
110
|
+
/**
|
|
111
|
+
* Who may send the event: role names (the workflow's `roles`, and the engine's `platform` and `manager`).
|
|
112
|
+
* Empty: anyone who may write the card.
|
|
113
|
+
*/
|
|
114
|
+
by?: string[];
|
|
115
|
+
/** The transition is taken only when this holds (Jira's condition); the first one that holds is taken. */
|
|
116
|
+
guard?: Expr | null;
|
|
117
|
+
/** Must hold, else the event is refused with the message (Jira's validator). */
|
|
118
|
+
validate?: Validation[];
|
|
119
|
+
/** The status the card moves to: a status name, or `{{expr}}`; none stays where it is (runs the actions only). */
|
|
120
|
+
target?: string | null;
|
|
121
|
+
/** What happens, in order, after the move (Jira's post functions). */
|
|
122
|
+
actions?: Action[];
|
|
123
|
+
/** What a person reads about it (the event's door text, the log). */
|
|
124
|
+
description?: string | null;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/** The dispatcher: when it runs, what it may start, in what order, under which caps. */
|
|
128
|
+
export interface Dispatch {
|
|
129
|
+
/** Whether the served home dispatches its boards (an expression; Hermes's `dispatch_in_gateway`). */
|
|
130
|
+
serve?: Expr | null;
|
|
131
|
+
/** Seconds between ticks. */
|
|
132
|
+
tick: Expr;
|
|
133
|
+
/** The event the dispatcher sends a card it starts (to cards whose status has a transition for it). */
|
|
134
|
+
start: string;
|
|
135
|
+
/** Which cards it may start this tick. */
|
|
136
|
+
eligible?: Expr | null;
|
|
137
|
+
/** The order it starts them in: sort keys, `-` before one for descending. */
|
|
138
|
+
order?: Expr[];
|
|
139
|
+
/** The caps. */
|
|
140
|
+
limits?: Limit[];
|
|
141
|
+
}
|
|
142
|
+
|
|
93
143
|
/** Why a binding ended (`docs/ORCHESTRATOR-IR.md` §2.5). */
|
|
94
144
|
export type EndReason =
|
|
95
145
|
/** Idle expiry. */
|
|
@@ -112,6 +162,13 @@ export type EnvValue =
|
|
|
112
162
|
/** A secret, named and never held. */
|
|
113
163
|
| SecretRef;
|
|
114
164
|
|
|
165
|
+
/**
|
|
166
|
+
* An expression over the card, its relations, the event and `params` (a small CEL-like language: literals,
|
|
167
|
+
* `card.*`, `event.*`, `params.*`, comparisons, `&&`/`||`/`!`, `in`, and the engine's functions such as
|
|
168
|
+
* `parents.all(p, …)`). Written as a string; a bare number, boolean or null is the literal it spells.
|
|
169
|
+
*/
|
|
170
|
+
export type Expr = string;
|
|
171
|
+
|
|
115
172
|
/**
|
|
116
173
|
* How faithfully a reconstruction reproduces its source.
|
|
117
174
|
*
|
|
@@ -241,6 +298,20 @@ export interface JobOrigin {
|
|
|
241
298
|
thread_id?: string | null;
|
|
242
299
|
}
|
|
243
300
|
|
|
301
|
+
/** A cap on what the dispatcher starts: cards counted per group, at most `max` in each. */
|
|
302
|
+
export interface Limit {
|
|
303
|
+
/** What the cap is about, for its message. */
|
|
304
|
+
description?: string | null;
|
|
305
|
+
/** The group a card falls in (GitHub's `concurrency.group`): `'home'`, `card.board`, `card.assignee`, … */
|
|
306
|
+
group: Expr;
|
|
307
|
+
/** Which cards count against it. */
|
|
308
|
+
counts: Expr;
|
|
309
|
+
/** The cap; a cap that evaluates to nothing caps nothing. */
|
|
310
|
+
max: Expr;
|
|
311
|
+
/** Slots held back for the cards this matches while any waits (Hermes's review reservation). */
|
|
312
|
+
reserve?: Reserve | null;
|
|
313
|
+
}
|
|
314
|
+
|
|
244
315
|
/** One delivery obligation. */
|
|
245
316
|
export interface Obligation {
|
|
246
317
|
/** The id. */
|
|
@@ -300,6 +371,8 @@ export interface Orchestration {
|
|
|
300
371
|
root: string;
|
|
301
372
|
/** `default` is the root folder; the rest are `profiles/<name>/`. */
|
|
302
373
|
profiles: Record<string, Profile>;
|
|
374
|
+
/** O — how the home's boards are worked (`workflow.yaml` at the root; Hermes's dispatcher when there is none). */
|
|
375
|
+
workflow?: Workflow;
|
|
303
376
|
}
|
|
304
377
|
|
|
305
378
|
/** What is delivered. */
|
|
@@ -414,6 +487,14 @@ export interface Repeat {
|
|
|
414
487
|
completed?: number;
|
|
415
488
|
}
|
|
416
489
|
|
|
490
|
+
/** Slots of a limit held for some cards. */
|
|
491
|
+
export interface Reserve {
|
|
492
|
+
/** The cards the slots are held for. */
|
|
493
|
+
for: Expr;
|
|
494
|
+
/** How many. */
|
|
495
|
+
slots: Expr;
|
|
496
|
+
}
|
|
497
|
+
|
|
417
498
|
/** Unmodeled source fields, keyed by the source's own field name. */
|
|
418
499
|
export type Residue = Record<string, unknown>;
|
|
419
500
|
|
|
@@ -441,6 +522,49 @@ export interface RouteMatch {
|
|
|
441
522
|
thread_id?: string | null;
|
|
442
523
|
}
|
|
443
524
|
|
|
525
|
+
/** What runs while a card is in a status: an actor of a role's lane in a named session slot of the card. */
|
|
526
|
+
export interface Run {
|
|
527
|
+
/** The role whose lane (the profile it names) runs it. */
|
|
528
|
+
role: string;
|
|
529
|
+
/**
|
|
530
|
+
* The card's session slot it runs in: a live session in the slot is kept, a lost one resumed, an empty slot
|
|
531
|
+
* started fresh. Different slots are different sessions (a reviewer never works in the implementer's).
|
|
532
|
+
*/
|
|
533
|
+
session: string;
|
|
534
|
+
/**
|
|
535
|
+
* What the actor is told when it starts: a template over the card (`{{card.id}}`, `{{context}}`) and
|
|
536
|
+
* `{{doors}}`, the events the actor may send in this status, generated from its transitions.
|
|
537
|
+
*/
|
|
538
|
+
prompt?: string;
|
|
539
|
+
/** Prompt file relative to the orchestration home. */
|
|
540
|
+
prompt_file?: string | null;
|
|
541
|
+
/** Skills the actor's session is given. */
|
|
542
|
+
skills?: string[];
|
|
543
|
+
/**
|
|
544
|
+
* Limits on the run, each an expression in seconds or a count (`runtime`, `heartbeat`, …); the engine emits
|
|
545
|
+
* an event when one passes (`timed_out`, `stale`, …).
|
|
546
|
+
*/
|
|
547
|
+
limits?: Record<string, Expr>;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
/** The independently supervised run machine. Its events never become card notices. */
|
|
551
|
+
export interface RunMachine {
|
|
552
|
+
/** Run specification selected for a card with an Every interval. */
|
|
553
|
+
recurring_role?: string | null;
|
|
554
|
+
/** Shared supervision limits, overridden by individual role specifications. */
|
|
555
|
+
limits?: Record<string, Expr>;
|
|
556
|
+
/** Named run specifications, selected by a card status or a recurring role. */
|
|
557
|
+
roles?: Record<string, Run>;
|
|
558
|
+
/** Run states and their entry, exit and event rules. */
|
|
559
|
+
states?: Record<string, Status>;
|
|
560
|
+
/** Initial run state. */
|
|
561
|
+
initial?: string;
|
|
562
|
+
/** Supervision shared by all run states. */
|
|
563
|
+
on?: Record<string, Transition[]>;
|
|
564
|
+
/** A run outcome emits this card verb (the sole link between machines). */
|
|
565
|
+
outcomes?: Record<string, Transition[]>;
|
|
566
|
+
}
|
|
567
|
+
|
|
444
568
|
/** When a job fires. */
|
|
445
569
|
export type Schedule =
|
|
446
570
|
/** Once, at an instant. */
|
|
@@ -457,6 +581,39 @@ export type SecretRef =
|
|
|
457
581
|
/** A key in the home's own `.env` file. */
|
|
458
582
|
| { dotenv: string };
|
|
459
583
|
|
|
584
|
+
/** One status a card can be in. */
|
|
585
|
+
export interface Status {
|
|
586
|
+
/**
|
|
587
|
+
* What `kanban.db`'s `tasks.status` holds for a card here, so Hermes reads the board (Hermes's own nine
|
|
588
|
+
* statuses store as themselves); the exact name rides beside it where it differs.
|
|
589
|
+
*/
|
|
590
|
+
stored_as?: string | null;
|
|
591
|
+
/** What a person reads about it. */
|
|
592
|
+
description?: string | null;
|
|
593
|
+
/** What runs while a card is here. */
|
|
594
|
+
run?: Run | null;
|
|
595
|
+
/** A specification in the run machine's roles, without repeating supervision. */
|
|
596
|
+
run_role?: string | null;
|
|
597
|
+
/** Status used when a failed or blocked run is later resumed. */
|
|
598
|
+
resume_as?: string | null;
|
|
599
|
+
/** Done on entering (after the move's own actions). */
|
|
600
|
+
entry?: Action[];
|
|
601
|
+
/** Done on leaving (before the move's own actions): e.g. `close_session: reviewer`. */
|
|
602
|
+
exit?: Action[];
|
|
603
|
+
/** Events and their transitions, the first whose guard holds taken. */
|
|
604
|
+
on?: Record<string, Transition[]>;
|
|
605
|
+
/** Transitions taken as soon as their guard holds (XState's `always`). */
|
|
606
|
+
always?: Transition[];
|
|
607
|
+
/** Transitions taken after a time in the status. */
|
|
608
|
+
after?: Delayed[];
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
/** Ordered lowering rule for Hermes's fixed dispatcher. */
|
|
612
|
+
export interface StorageRule {
|
|
613
|
+
guard: Expr;
|
|
614
|
+
status: string;
|
|
615
|
+
}
|
|
616
|
+
|
|
460
617
|
/**
|
|
461
618
|
* ORCH-3: the conversation identity on a surface. Full tuple on a channel;
|
|
462
619
|
* degenerate (all `None`) on a terminal.
|
|
@@ -490,6 +647,27 @@ export type Target =
|
|
|
490
647
|
/** A named surface, as `hermes send --to` spells one. */
|
|
491
648
|
| { platform: string; chat_id?: string | null; thread_id?: string | null; kind: 'explicit' };
|
|
492
649
|
|
|
650
|
+
/** A move from the card's status on an event (or on none: `always`, `after`). */
|
|
651
|
+
export interface Transition {
|
|
652
|
+
/** Source statuses; empty applies from every status. */
|
|
653
|
+
from?: string[];
|
|
654
|
+
/**
|
|
655
|
+
* Who may send the event: role names (the workflow's `roles`, and the engine's `platform` and `manager`).
|
|
656
|
+
* Empty: anyone who may write the card.
|
|
657
|
+
*/
|
|
658
|
+
by?: string[];
|
|
659
|
+
/** The transition is taken only when this holds (Jira's condition); the first one that holds is taken. */
|
|
660
|
+
guard?: Expr | null;
|
|
661
|
+
/** Must hold, else the event is refused with the message (Jira's validator). */
|
|
662
|
+
validate?: Validation[];
|
|
663
|
+
/** The status the card moves to: a status name, or `{{expr}}`; none stays where it is (runs the actions only). */
|
|
664
|
+
target?: string | null;
|
|
665
|
+
/** What happens, in order, after the move (Jira's post functions). */
|
|
666
|
+
actions?: Action[];
|
|
667
|
+
/** What a person reads about it (the event's door text, the log). */
|
|
668
|
+
description?: string | null;
|
|
669
|
+
}
|
|
670
|
+
|
|
493
671
|
/** ORCH-3: why a session exists (the trigger noun; `docs/HERMES-IDEAL-SUPPORT-DESIGN.md` §3). */
|
|
494
672
|
export type Trigger =
|
|
495
673
|
/** A person started it on a terminal, IDE, or chat surface. */
|
|
@@ -511,6 +689,14 @@ export type Trigger =
|
|
|
511
689
|
/** The source does not say. */
|
|
512
690
|
| 'unknown';
|
|
513
691
|
|
|
692
|
+
/** A validator: the expression must hold, else the event is refused with the message. */
|
|
693
|
+
export interface Validation {
|
|
694
|
+
/** What must hold. */
|
|
695
|
+
expr: Expr;
|
|
696
|
+
/** The refusal. */
|
|
697
|
+
message: string;
|
|
698
|
+
}
|
|
699
|
+
|
|
514
700
|
/** One subscription: the route is `/webhooks/<name>`. */
|
|
515
701
|
export interface WebhookSubscription {
|
|
516
702
|
/** The name. */
|
|
@@ -585,3 +771,42 @@ export type WorkerSurface =
|
|
|
585
771
|
* when it cannot be resumed.
|
|
586
772
|
*/
|
|
587
773
|
| 'pane';
|
|
774
|
+
|
|
775
|
+
/** A board's workflow. */
|
|
776
|
+
export interface Workflow {
|
|
777
|
+
/** The run machine; absent for legacy homes during migration. */
|
|
778
|
+
run?: RunMachine | null;
|
|
779
|
+
/** Card verbs declared once, with source statuses on each transition. */
|
|
780
|
+
verbs?: Record<string, Transition[]>;
|
|
781
|
+
/** Derived card conditions, such as ready. */
|
|
782
|
+
derived?: Record<string, Expr>;
|
|
783
|
+
/** Relation policies, interpreted by the engine's relation primitives. */
|
|
784
|
+
relations?: Record<string, unknown>;
|
|
785
|
+
/** Flag policies, interpreted by the engine's flag primitives. */
|
|
786
|
+
flags?: Record<string, unknown>;
|
|
787
|
+
/** Ordered Hermes projection and its explicitly accepted losses. */
|
|
788
|
+
stored_as?: StorageRule[];
|
|
789
|
+
losses?: string[];
|
|
790
|
+
/** What a person reads about it. */
|
|
791
|
+
description?: string | null;
|
|
792
|
+
/**
|
|
793
|
+
* Named values the expressions read (`params.failure_limit`); a home's config.yaml `kanban:` keys override
|
|
794
|
+
* them by name, so Hermes's settings are this workflow's parameters.
|
|
795
|
+
*/
|
|
796
|
+
params?: Record<string, unknown>;
|
|
797
|
+
/** Who acts on a card, each an expression naming a profile (`implementer: card.assignee`) or a person. */
|
|
798
|
+
roles?: Record<string, Expr>;
|
|
799
|
+
/** Where a new card starts: the first transition whose guard holds. */
|
|
800
|
+
initial: Transition[];
|
|
801
|
+
/** Every status, by name. */
|
|
802
|
+
statuses: Record<string, Status>;
|
|
803
|
+
/** Events that apply in every status (a status's own `on` for the same event is tried first). */
|
|
804
|
+
on?: Record<string, Transition[]>;
|
|
805
|
+
/** The dispatcher. */
|
|
806
|
+
dispatch: Dispatch;
|
|
807
|
+
/**
|
|
808
|
+
* Who is told what: for each audience (`creator`, `worker`, `dependency`, `chat`: who a card's subscriptions
|
|
809
|
+
* are), the event kinds it hears and the template each is told in. A kind not named is not sent.
|
|
810
|
+
*/
|
|
811
|
+
notify?: Record<string, Record<string, string>>;
|
|
812
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volter/supercode-orchestrator",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.81",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "The orchestrator runtime over the Volter Harness ontology: one typed operational model whose folder is its serialization, read and written through the harness orchestration doors (docs/ORCHESTRATOR-IR.md)",
|
|
6
6
|
"exports": {
|