@ci-kit/roundtable 0.0.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,16 +1,230 @@
1
+ import { text } from '@ci-kit/ai';
2
+
3
+ type Sees = 'all' | 'none' | 'lead-only' | string[];
4
+ type Fallback = 'skip' | 'retry' | 'abort';
5
+ type SeatOutput = 'text' | 'json' | 'markdown';
6
+ interface SeatIdentity {
7
+ name: string;
8
+ avatar?: string;
9
+ title?: string;
10
+ background?: string;
11
+ }
12
+ interface SeatPersona {
13
+ /** Decision tendency. Kept apart from expression so verdicts stay reproducible. */
14
+ stance?: string;
15
+ personality: string[];
16
+ style?: string;
17
+ speech?: string;
18
+ values?: string;
19
+ quirks?: string;
20
+ avoid?: string;
21
+ }
22
+ interface SeatPowers {
23
+ /** Phase ids this seat attends; empty means every phase. */
24
+ phase: string[];
25
+ sees: Sees;
26
+ canPropose: boolean;
27
+ canVeto: boolean;
28
+ lead: boolean;
29
+ weight: number;
30
+ priority: number;
31
+ budget?: number;
32
+ fallback: Fallback;
33
+ output: SeatOutput;
34
+ model?: string;
35
+ temperature?: number;
36
+ maxTokens?: number;
37
+ }
38
+ interface Seat {
39
+ id: string;
40
+ role: string;
41
+ enabled: boolean;
42
+ identity: SeatIdentity;
43
+ persona: SeatPersona;
44
+ seat: SeatPowers;
45
+ /** Markdown body, used verbatim as the seat's instructions. */
46
+ body: string;
47
+ /** File the seat came from, for error messages only. */
48
+ source: string;
49
+ }
50
+
51
+ type PhaseMode = 'serial' | 'parallel';
52
+ type OnVeto = 're-propose' | 'revise' | 'abort';
53
+ interface Phase {
54
+ id: string;
55
+ /** Seats named here; empty means "derive from every seat's seat.phase". */
56
+ seats: string[];
57
+ vetoable: boolean;
58
+ requires: string[];
59
+ mode: PhaseMode;
60
+ }
61
+ interface Budget {
62
+ total?: number;
63
+ perSeat?: number;
64
+ }
65
+ interface Table {
66
+ title: string;
67
+ schedule?: string;
68
+ budget: Budget;
69
+ onVeto: OnVeto;
70
+ maxAttempts: number;
71
+ threshold: number;
72
+ phases: Phase[];
73
+ /** Phase ids given the special roles, resolved during validation. */
74
+ special: {
75
+ propose: string;
76
+ converge: string;
77
+ };
78
+ }
79
+
80
+ declare class RoundtableConfigError extends Error {
81
+ constructor(message: string);
82
+ }
83
+ interface LoadedRoundtable {
84
+ table: Table;
85
+ seats: Seat[];
86
+ /** Seats after `enabled` filtering, keyed by id. */
87
+ byId: Map<string, Seat>;
88
+ /** Phases with their participant lists resolved. */
89
+ phases: Phase[];
90
+ configDir: string;
91
+ /** Content fingerprint over table, seats and the roundtable schema. */
92
+ fingerprint: string;
93
+ }
1
94
  /**
2
- * @ci-kit/roundtable
3
- *
4
- * Placeholder package. The design is settled in `ai-docs/design-docs/roundtable/`;
5
- * the implementation has not started yet, so this module exports only the
6
- * names and types that downstream code may already reference.
95
+ * Read and validate a roundtable directory without calling any model.
7
96
  *
8
- * Do not add behaviour here before the design document is followed end to end:
9
- * seat parsing, phase scheduling, programmatic adjudication and resumable runs
10
- * are one unit, and half of them is worse than none.
97
+ * Everything a meeting needs to be well defined is checked here: unknown
98
+ * fields, missing required fields, duplicate ids, phase references and the
99
+ * table/seat membership intersection. A meeting that starts is a meeting that
100
+ * can finish.
11
101
  */
12
- declare const ROUNDTABLE_SCHEMA: 1;
13
- type RoundtableStatus = 'passed' | 'rejected' | 'aborted' | 'failed';
102
+ declare function loadRoundtable(options: {
103
+ configDir: string;
104
+ schema?: number;
105
+ }): Promise<LoadedRoundtable>;
106
+ /** Convenience for the CLI: validate and report, never call a model. */
107
+ declare function checkRoundtable(options: {
108
+ configDir: string;
109
+ env?: NodeJS.ProcessEnv;
110
+ }): Promise<LoadedRoundtable>;
111
+ /** Resolved default output directory. */
112
+ declare function defaultOutDir(cwd?: string): string;
113
+
114
+ /** One seat's turn in a phase, as seen by later seats. */
115
+ interface Statement {
116
+ seat: string;
117
+ name: string;
118
+ role: string;
119
+ phase: string;
120
+ status: StatementStatus;
121
+ content: string;
122
+ structured?: unknown;
123
+ durationMs?: number;
124
+ model?: string;
125
+ usage?: {
126
+ input: number;
127
+ output: number;
128
+ };
129
+ /** One log-safe line when the seat failed. */
130
+ error?: string;
131
+ artifacts?: ArtifactRef[];
132
+ }
133
+ type StatementStatus = 'completed' | 'skipped' | 'failed' | 'budget-exhausted' | 'invalid-veto';
134
+ interface ArtifactRef {
135
+ path: string;
136
+ bytes: number;
137
+ }
138
+
139
+ interface Vote {
140
+ seatId: string;
141
+ weight: number;
142
+ /** `undefined` when the seat failed or was skipped, so it cannot count. */
143
+ vote?: 'pass' | 'reject';
144
+ /** Set when a veto-capable seat wrote `reject` with a reason. */
145
+ veto?: boolean;
146
+ /** Whether the seat actually wrote text for its reason. */
147
+ hasReason?: boolean;
148
+ }
149
+ interface Judgement {
150
+ passed: boolean;
151
+ /** Seats whose valid veto blocked the phase. */
152
+ vetoed: string[];
153
+ /** Seats that voted reject without a valid veto. */
154
+ rejected: string[];
155
+ /** Weighted pass ratio over seats that actually voted. */
156
+ score: number;
157
+ /** Seats whose veto had no reason and was therefore ignored. */
158
+ invalidVetoes: string[];
159
+ }
160
+
161
+ type RoundtableStatus = 'running' | 'passed' | 'rejected' | 'aborted' | 'failed';
162
+ type PhaseStatus = 'completed' | 'skipped' | 'failed' | 'budget-exhausted';
163
+ interface PhaseRecord {
164
+ id: string;
165
+ status: PhaseStatus;
166
+ statements: Statement[];
167
+ judgement?: Judgement;
168
+ /** True when a completed phase had no input from its dependencies. */
169
+ pruned?: boolean;
170
+ }
171
+ interface RoundRecord {
172
+ attempt: number;
173
+ phases: PhaseRecord[];
174
+ }
175
+ interface BudgetState {
176
+ total?: number;
177
+ used: number;
178
+ perSeat: Record<string, number>;
179
+ perSeatLimit: Record<string, number | undefined>;
180
+ }
181
+ /** The AI call the engine depends on; injectable so meetings can be tested offline. */
182
+ type TextCaller = typeof text;
183
+
184
+ declare const RECORD_SCHEMA = 1;
185
+ interface RoundtableRecord {
186
+ schema: number;
187
+ title: string;
188
+ startedAt: string;
189
+ finishedAt?: string;
190
+ status: RoundtableStatus;
191
+ attempts: number;
192
+ verdict: {
193
+ passed: boolean;
194
+ vetoed: string[];
195
+ rejected: string[];
196
+ score: number;
197
+ invalidVetoes: string[];
198
+ };
199
+ rounds: RoundRecord[];
200
+ budget: {
201
+ total?: number;
202
+ used: number;
203
+ perSeat: Record<string, number>;
204
+ };
205
+ /** Files produced under artifacts/, referenced by statements. */
206
+ artifacts?: string[];
207
+ error?: string;
208
+ }
209
+ interface RunState {
210
+ schema: number;
211
+ runId: string;
212
+ /** `running` until the loop settles on a terminal status. */
213
+ status: RoundtableStatus | 'running';
214
+ attempt: number;
215
+ phaseIndex: number;
216
+ phaseId?: string;
217
+ budget: BudgetState;
218
+ fingerprint: string;
219
+ resumable: boolean;
220
+ rounds: RoundRecord[];
221
+ startedAt: string;
222
+ finishedAt?: string;
223
+ topic?: string;
224
+ context: string[];
225
+ error?: string;
226
+ }
227
+
14
228
  interface RoundtableOptions {
15
229
  /** Directory holding `table.md` and `seats/` */
16
230
  configDir: string;
@@ -21,17 +235,45 @@ interface RoundtableOptions {
21
235
  /** Where run directories are written */
22
236
  outDir?: string;
23
237
  env?: NodeJS.ProcessEnv;
238
+ /** Emit one line per statement while the meeting runs. */
239
+ onProgress?: (line: string) => void;
240
+ /** Defaults to `@ci-kit/ai`'s text(); tests pass a stub. */
241
+ callText?: TextCaller;
24
242
  }
25
243
  interface RoundtableResult {
26
244
  status: RoundtableStatus;
27
245
  recordPath: string;
246
+ /** Directory holding record.json, record.md, state.json. */
247
+ runDir: string;
248
+ record: RoundtableRecord;
249
+ /** Total AI calls consumed. */
250
+ used: number;
251
+ budgetTotal?: number;
252
+ }
253
+ /**
254
+ * Run one meeting.
255
+ *
256
+ * Business failure is reported through `status`, never thrown: a rejected
257
+ * meeting is a normal result. Only configuration and usage errors throw,
258
+ * because those mean nothing could start.
259
+ */
260
+ declare function runRoundtable(options: RoundtableOptions): Promise<RoundtableResult>;
261
+ interface ResumeOptions extends Omit<RoundtableOptions, 'outDir'> {
262
+ /** Run directory produced by a previous, interrupted execution. */
263
+ runDir: string;
28
264
  }
29
- /** Validate `table.md` and `seats/*.md` without calling a model. */
30
- declare function loadRoundtable(_options: RoundtableOptions): Promise<never>;
31
- /** Alias kept for the CLI `check` command: no paid calls, config errors only. */
32
- declare function checkRoundtable(_options: RoundtableOptions): Promise<never>;
33
- /** Run one meeting and return its verdict. Business failure is reported via `status`. */
34
- declare function runRoundtable(_options: RoundtableOptions): Promise<RoundtableResult>;
265
+ /**
266
+ * Continue an interrupted run from the phase that did not finish.
267
+ *
268
+ * Rules are fingerprinted: if a seat or the table changed, the previous
269
+ * progress described a different meeting and cannot be resumed. That mirrors
270
+ * "editing a prompt never rewrites an already-published draft".
271
+ *
272
+ * A run that already reached a terminal status is returned as-is rather than
273
+ * re-executed: repeating a finished meeting would spend money to reach the same
274
+ * answer.
275
+ */
276
+ declare function resumeRoundtable(options: ResumeOptions): Promise<RoundtableResult>;
35
277
 
36
- export { ROUNDTABLE_SCHEMA, checkRoundtable, loadRoundtable, runRoundtable };
37
- export type { RoundtableOptions, RoundtableResult, RoundtableStatus };
278
+ export { RECORD_SCHEMA as ROUNDTABLE_SCHEMA, RoundtableConfigError, checkRoundtable, defaultOutDir, loadRoundtable, resumeRoundtable, runRoundtable };
279
+ export type { ArtifactRef, BudgetState, Judgement, LoadedRoundtable, Phase, PhaseMode, PhaseRecord, ResumeOptions, RoundRecord, RoundtableOptions, RoundtableRecord, RoundtableResult, RoundtableStatus, RunState, Seat, SeatIdentity, SeatOutput, SeatPersona, SeatPowers, Statement, StatementStatus, Table, TextCaller, Vote };