agent-lyceum 0.4.14 → 0.5.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/schema.d.ts CHANGED
@@ -9,51 +9,29 @@ export declare const RUNTIME_EFFORTS: Record<Runtime, readonly Effort[]>;
9
9
  /** Guess the runtime from a model name: Claude aliases/IDs -> claude-code, GPT/o-series/codex names -> codex. */
10
10
  export declare function inferRuntime(model: string | undefined): Runtime | undefined;
11
11
  export declare const AgentPartial: z.ZodObject<{
12
- runtime: z.ZodOptional<z.ZodEnum<["claude-code", "codex"]>>;
12
+ runtime: z.ZodOptional<z.ZodEnum<{
13
+ "claude-code": "claude-code";
14
+ codex: "codex";
15
+ }>>;
13
16
  model: z.ZodOptional<z.ZodString>;
14
- effort: z.ZodOptional<z.ZodEnum<["minimal", "low", "medium", "high", "xhigh", "max"]>>;
17
+ effort: z.ZodOptional<z.ZodEnum<{
18
+ high: "high";
19
+ low: "low";
20
+ max: "max";
21
+ medium: "medium";
22
+ minimal: "minimal";
23
+ xhigh: "xhigh";
24
+ }>>;
15
25
  agent_md: z.ZodOptional<z.ZodString>;
16
26
  memory: z.ZodOptional<z.ZodObject<{
17
27
  global: z.ZodOptional<z.ZodString>;
18
28
  project: z.ZodOptional<z.ZodString>;
19
- }, "strict", z.ZodTypeAny, {
20
- global?: string | undefined;
21
- project?: string | undefined;
22
- }, {
23
- global?: string | undefined;
24
- project?: string | undefined;
25
- }>>;
29
+ }, z.core.$strict>>;
26
30
  resume: z.ZodOptional<z.ZodBoolean>;
27
- can_message: z.ZodOptional<z.ZodUnion<[z.ZodLiteral<"all">, z.ZodArray<z.ZodString, "many">]>>;
31
+ can_message: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"all">, z.ZodArray<z.ZodString>]>>;
28
32
  can_edit_agent_md: z.ZodOptional<z.ZodBoolean>;
29
- owns: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
30
- }, "strict", z.ZodTypeAny, {
31
- runtime?: "claude-code" | "codex" | undefined;
32
- model?: string | undefined;
33
- effort?: "minimal" | "low" | "medium" | "high" | "xhigh" | "max" | undefined;
34
- agent_md?: string | undefined;
35
- memory?: {
36
- global?: string | undefined;
37
- project?: string | undefined;
38
- } | undefined;
39
- resume?: boolean | undefined;
40
- can_message?: string[] | "all" | undefined;
41
- can_edit_agent_md?: boolean | undefined;
42
- owns?: string[] | undefined;
43
- }, {
44
- runtime?: "claude-code" | "codex" | undefined;
45
- model?: string | undefined;
46
- effort?: "minimal" | "low" | "medium" | "high" | "xhigh" | "max" | undefined;
47
- agent_md?: string | undefined;
48
- memory?: {
49
- global?: string | undefined;
50
- project?: string | undefined;
51
- } | undefined;
52
- resume?: boolean | undefined;
53
- can_message?: string[] | "all" | undefined;
54
- can_edit_agent_md?: boolean | undefined;
55
- owns?: string[] | undefined;
56
- }>;
33
+ owns: z.ZodOptional<z.ZodArray<z.ZodString>>;
34
+ }, z.core.$strict>;
57
35
  export type AgentPartialT = z.infer<typeof AgentPartial>;
58
36
  export declare const DispatcherPartial: z.ZodObject<{
59
37
  max_rounds: z.ZodOptional<z.ZodNumber>;
@@ -61,232 +39,82 @@ export declare const DispatcherPartial: z.ZodObject<{
61
39
  wake_timeout_sec: z.ZodOptional<z.ZodNumber>;
62
40
  retry: z.ZodOptional<z.ZodNumber>;
63
41
  strict: z.ZodOptional<z.ZodBoolean>;
64
- workspace_mode: z.ZodOptional<z.ZodEnum<["auto", "shared", "worktree"]>>;
65
- }, "strict", z.ZodTypeAny, {
66
- strict?: boolean | undefined;
67
- max_rounds?: number | undefined;
68
- max_parallel?: number | undefined;
69
- wake_timeout_sec?: number | undefined;
70
- retry?: number | undefined;
71
- workspace_mode?: "shared" | "auto" | "worktree" | undefined;
72
- }, {
73
- strict?: boolean | undefined;
74
- max_rounds?: number | undefined;
75
- max_parallel?: number | undefined;
76
- wake_timeout_sec?: number | undefined;
77
- retry?: number | undefined;
78
- workspace_mode?: "shared" | "auto" | "worktree" | undefined;
79
- }>;
42
+ workspace_mode: z.ZodOptional<z.ZodEnum<{
43
+ auto: "auto";
44
+ shared: "shared";
45
+ worktree: "worktree";
46
+ }>>;
47
+ log_max_bytes: z.ZodOptional<z.ZodNumber>;
48
+ }, z.core.$strict>;
80
49
  export declare const GlobalConfig: z.ZodObject<{
81
50
  agents: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
82
- runtime: z.ZodOptional<z.ZodEnum<["claude-code", "codex"]>>;
51
+ runtime: z.ZodOptional<z.ZodEnum<{
52
+ "claude-code": "claude-code";
53
+ codex: "codex";
54
+ }>>;
83
55
  model: z.ZodOptional<z.ZodString>;
84
- effort: z.ZodOptional<z.ZodEnum<["minimal", "low", "medium", "high", "xhigh", "max"]>>;
56
+ effort: z.ZodOptional<z.ZodEnum<{
57
+ high: "high";
58
+ low: "low";
59
+ max: "max";
60
+ medium: "medium";
61
+ minimal: "minimal";
62
+ xhigh: "xhigh";
63
+ }>>;
85
64
  agent_md: z.ZodOptional<z.ZodString>;
86
65
  memory: z.ZodOptional<z.ZodObject<{
87
66
  global: z.ZodOptional<z.ZodString>;
88
67
  project: z.ZodOptional<z.ZodString>;
89
- }, "strict", z.ZodTypeAny, {
90
- global?: string | undefined;
91
- project?: string | undefined;
92
- }, {
93
- global?: string | undefined;
94
- project?: string | undefined;
95
- }>>;
68
+ }, z.core.$strict>>;
96
69
  resume: z.ZodOptional<z.ZodBoolean>;
97
- can_message: z.ZodOptional<z.ZodUnion<[z.ZodLiteral<"all">, z.ZodArray<z.ZodString, "many">]>>;
70
+ can_message: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"all">, z.ZodArray<z.ZodString>]>>;
98
71
  can_edit_agent_md: z.ZodOptional<z.ZodBoolean>;
99
- owns: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
100
- }, "strict", z.ZodTypeAny, {
101
- runtime?: "claude-code" | "codex" | undefined;
102
- model?: string | undefined;
103
- effort?: "minimal" | "low" | "medium" | "high" | "xhigh" | "max" | undefined;
104
- agent_md?: string | undefined;
105
- memory?: {
106
- global?: string | undefined;
107
- project?: string | undefined;
108
- } | undefined;
109
- resume?: boolean | undefined;
110
- can_message?: string[] | "all" | undefined;
111
- can_edit_agent_md?: boolean | undefined;
112
- owns?: string[] | undefined;
113
- }, {
114
- runtime?: "claude-code" | "codex" | undefined;
115
- model?: string | undefined;
116
- effort?: "minimal" | "low" | "medium" | "high" | "xhigh" | "max" | undefined;
117
- agent_md?: string | undefined;
118
- memory?: {
119
- global?: string | undefined;
120
- project?: string | undefined;
121
- } | undefined;
122
- resume?: boolean | undefined;
123
- can_message?: string[] | "all" | undefined;
124
- can_edit_agent_md?: boolean | undefined;
125
- owns?: string[] | undefined;
126
- }>>>;
127
- }, "strict", z.ZodTypeAny, {
128
- agents: Record<string, {
129
- runtime?: "claude-code" | "codex" | undefined;
130
- model?: string | undefined;
131
- effort?: "minimal" | "low" | "medium" | "high" | "xhigh" | "max" | undefined;
132
- agent_md?: string | undefined;
133
- memory?: {
134
- global?: string | undefined;
135
- project?: string | undefined;
136
- } | undefined;
137
- resume?: boolean | undefined;
138
- can_message?: string[] | "all" | undefined;
139
- can_edit_agent_md?: boolean | undefined;
140
- owns?: string[] | undefined;
141
- }>;
142
- }, {
143
- agents?: Record<string, {
144
- runtime?: "claude-code" | "codex" | undefined;
145
- model?: string | undefined;
146
- effort?: "minimal" | "low" | "medium" | "high" | "xhigh" | "max" | undefined;
147
- agent_md?: string | undefined;
148
- memory?: {
149
- global?: string | undefined;
150
- project?: string | undefined;
151
- } | undefined;
152
- resume?: boolean | undefined;
153
- can_message?: string[] | "all" | undefined;
154
- can_edit_agent_md?: boolean | undefined;
155
- owns?: string[] | undefined;
156
- }> | undefined;
157
- }>;
72
+ owns: z.ZodOptional<z.ZodArray<z.ZodString>>;
73
+ }, z.core.$strict>>>;
74
+ }, z.core.$strict>;
158
75
  export declare const ProjectConfig: z.ZodObject<{
159
76
  dir: z.ZodString;
160
77
  team: z.ZodObject<{
161
78
  lead: z.ZodString;
162
- }, "strict", z.ZodTypeAny, {
163
- lead: string;
164
- }, {
165
- lead: string;
166
- }>;
79
+ }, z.core.$strict>;
167
80
  dispatcher: z.ZodDefault<z.ZodObject<{
168
81
  max_rounds: z.ZodOptional<z.ZodNumber>;
169
82
  max_parallel: z.ZodOptional<z.ZodNumber>;
170
83
  wake_timeout_sec: z.ZodOptional<z.ZodNumber>;
171
84
  retry: z.ZodOptional<z.ZodNumber>;
172
85
  strict: z.ZodOptional<z.ZodBoolean>;
173
- workspace_mode: z.ZodOptional<z.ZodEnum<["auto", "shared", "worktree"]>>;
174
- }, "strict", z.ZodTypeAny, {
175
- strict?: boolean | undefined;
176
- max_rounds?: number | undefined;
177
- max_parallel?: number | undefined;
178
- wake_timeout_sec?: number | undefined;
179
- retry?: number | undefined;
180
- workspace_mode?: "shared" | "auto" | "worktree" | undefined;
181
- }, {
182
- strict?: boolean | undefined;
183
- max_rounds?: number | undefined;
184
- max_parallel?: number | undefined;
185
- wake_timeout_sec?: number | undefined;
186
- retry?: number | undefined;
187
- workspace_mode?: "shared" | "auto" | "worktree" | undefined;
188
- }>>;
86
+ workspace_mode: z.ZodOptional<z.ZodEnum<{
87
+ auto: "auto";
88
+ shared: "shared";
89
+ worktree: "worktree";
90
+ }>>;
91
+ log_max_bytes: z.ZodOptional<z.ZodNumber>;
92
+ }, z.core.$strict>>;
189
93
  agents: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
190
- runtime: z.ZodOptional<z.ZodEnum<["claude-code", "codex"]>>;
94
+ runtime: z.ZodOptional<z.ZodEnum<{
95
+ "claude-code": "claude-code";
96
+ codex: "codex";
97
+ }>>;
191
98
  model: z.ZodOptional<z.ZodString>;
192
- effort: z.ZodOptional<z.ZodEnum<["minimal", "low", "medium", "high", "xhigh", "max"]>>;
99
+ effort: z.ZodOptional<z.ZodEnum<{
100
+ high: "high";
101
+ low: "low";
102
+ max: "max";
103
+ medium: "medium";
104
+ minimal: "minimal";
105
+ xhigh: "xhigh";
106
+ }>>;
193
107
  agent_md: z.ZodOptional<z.ZodString>;
194
108
  memory: z.ZodOptional<z.ZodObject<{
195
109
  global: z.ZodOptional<z.ZodString>;
196
110
  project: z.ZodOptional<z.ZodString>;
197
- }, "strict", z.ZodTypeAny, {
198
- global?: string | undefined;
199
- project?: string | undefined;
200
- }, {
201
- global?: string | undefined;
202
- project?: string | undefined;
203
- }>>;
111
+ }, z.core.$strict>>;
204
112
  resume: z.ZodOptional<z.ZodBoolean>;
205
- can_message: z.ZodOptional<z.ZodUnion<[z.ZodLiteral<"all">, z.ZodArray<z.ZodString, "many">]>>;
113
+ can_message: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"all">, z.ZodArray<z.ZodString>]>>;
206
114
  can_edit_agent_md: z.ZodOptional<z.ZodBoolean>;
207
- owns: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
208
- }, "strict", z.ZodTypeAny, {
209
- runtime?: "claude-code" | "codex" | undefined;
210
- model?: string | undefined;
211
- effort?: "minimal" | "low" | "medium" | "high" | "xhigh" | "max" | undefined;
212
- agent_md?: string | undefined;
213
- memory?: {
214
- global?: string | undefined;
215
- project?: string | undefined;
216
- } | undefined;
217
- resume?: boolean | undefined;
218
- can_message?: string[] | "all" | undefined;
219
- can_edit_agent_md?: boolean | undefined;
220
- owns?: string[] | undefined;
221
- }, {
222
- runtime?: "claude-code" | "codex" | undefined;
223
- model?: string | undefined;
224
- effort?: "minimal" | "low" | "medium" | "high" | "xhigh" | "max" | undefined;
225
- agent_md?: string | undefined;
226
- memory?: {
227
- global?: string | undefined;
228
- project?: string | undefined;
229
- } | undefined;
230
- resume?: boolean | undefined;
231
- can_message?: string[] | "all" | undefined;
232
- can_edit_agent_md?: boolean | undefined;
233
- owns?: string[] | undefined;
234
- }>>>;
235
- }, "strict", z.ZodTypeAny, {
236
- agents: Record<string, {
237
- runtime?: "claude-code" | "codex" | undefined;
238
- model?: string | undefined;
239
- effort?: "minimal" | "low" | "medium" | "high" | "xhigh" | "max" | undefined;
240
- agent_md?: string | undefined;
241
- memory?: {
242
- global?: string | undefined;
243
- project?: string | undefined;
244
- } | undefined;
245
- resume?: boolean | undefined;
246
- can_message?: string[] | "all" | undefined;
247
- can_edit_agent_md?: boolean | undefined;
248
- owns?: string[] | undefined;
249
- }>;
250
- dir: string;
251
- team: {
252
- lead: string;
253
- };
254
- dispatcher: {
255
- strict?: boolean | undefined;
256
- max_rounds?: number | undefined;
257
- max_parallel?: number | undefined;
258
- wake_timeout_sec?: number | undefined;
259
- retry?: number | undefined;
260
- workspace_mode?: "shared" | "auto" | "worktree" | undefined;
261
- };
262
- }, {
263
- dir: string;
264
- team: {
265
- lead: string;
266
- };
267
- agents?: Record<string, {
268
- runtime?: "claude-code" | "codex" | undefined;
269
- model?: string | undefined;
270
- effort?: "minimal" | "low" | "medium" | "high" | "xhigh" | "max" | undefined;
271
- agent_md?: string | undefined;
272
- memory?: {
273
- global?: string | undefined;
274
- project?: string | undefined;
275
- } | undefined;
276
- resume?: boolean | undefined;
277
- can_message?: string[] | "all" | undefined;
278
- can_edit_agent_md?: boolean | undefined;
279
- owns?: string[] | undefined;
280
- }> | undefined;
281
- dispatcher?: {
282
- strict?: boolean | undefined;
283
- max_rounds?: number | undefined;
284
- max_parallel?: number | undefined;
285
- wake_timeout_sec?: number | undefined;
286
- retry?: number | undefined;
287
- workspace_mode?: "shared" | "auto" | "worktree" | undefined;
288
- } | undefined;
289
- }>;
115
+ owns: z.ZodOptional<z.ZodArray<z.ZodString>>;
116
+ }, z.core.$strict>>>;
117
+ }, z.core.$strict>;
290
118
  export interface DispatcherSettings {
291
119
  max_rounds: number;
292
120
  max_parallel: number;
@@ -295,6 +123,8 @@ export interface DispatcherSettings {
295
123
  strict: boolean;
296
124
  /** "auto": a git worktree per non-lead agent when agents can run in parallel, otherwise one shared checkout. */
297
125
  workspace_mode: "auto" | "shared" | "worktree";
126
+ /** log.jsonl is rotated to log.1.jsonl past this size; 0 = never. */
127
+ log_max_bytes: number;
298
128
  }
299
129
  export declare const DISPATCHER_DEFAULTS: DispatcherSettings;
300
130
  /** How a run turned out, independent of why it stopped (`EndReason`). Only "completed" means success. */
package/dist/schema.js CHANGED
@@ -45,11 +45,12 @@ export const DispatcherPartial = z
45
45
  retry: z.number().int().min(0).optional(),
46
46
  strict: z.boolean().optional(),
47
47
  workspace_mode: z.enum(["auto", "shared", "worktree"]).optional(),
48
+ log_max_bytes: z.number().int().min(0).optional(),
48
49
  })
49
50
  .strict();
50
51
  export const GlobalConfig = z
51
52
  .object({
52
- agents: z.record(AgentPartial).default({}),
53
+ agents: z.record(z.string(), AgentPartial).default({}),
53
54
  })
54
55
  .strict();
55
56
  export const ProjectConfig = z
@@ -57,7 +58,7 @@ export const ProjectConfig = z
57
58
  dir: z.string(),
58
59
  team: z.object({ lead: z.string() }).strict(),
59
60
  dispatcher: DispatcherPartial.default({}),
60
- agents: z.record(AgentPartial).default({}),
61
+ agents: z.record(z.string(), AgentPartial).default({}),
61
62
  })
62
63
  .strict();
63
64
  export const DISPATCHER_DEFAULTS = {
@@ -67,6 +68,7 @@ export const DISPATCHER_DEFAULTS = {
67
68
  retry: 1,
68
69
  strict: false,
69
70
  workspace_mode: "auto",
71
+ log_max_bytes: 8 * 1024 * 1024,
70
72
  };
71
73
  /** How a run turned out, independent of why it stopped (`EndReason`). Only "completed" means success. */
72
74
  export const RUN_OUTCOMES = ["completed", "partial", "blocked", "failed", "cancelled"];
package/dist/status.js CHANGED
@@ -137,7 +137,7 @@ function stepsLine(steps, c, finished = false) {
137
137
  function queueOf(project) {
138
138
  const rows = Object.values(project.agents)
139
139
  .map((a) => ({ agent: a.name, msg: listUnread(project, a.name)[0] }))
140
- .filter((r) => !!r.msg);
140
+ .flatMap((r) => (r.msg ? [{ agent: r.agent, msg: r.msg }] : []));
141
141
  rows.sort((x, y) => {
142
142
  if ((x.agent === project.lead) !== (y.agent === project.lead))
143
143
  return x.agent === project.lead ? -1 : 1;
@@ -251,13 +251,16 @@ function summaryBlock(run, now, c) {
251
251
  lines.push(`${L("進度:")}${steps ?? `無清單;已用 ${s.rounds}/${s.max_rounds} 輪(lead 可在信中加入 "## Steps" 清單)`}`);
252
252
  const active = Object.entries(s.active ?? {});
253
253
  if (active.length) {
254
- active.forEach(([agent, a], i) => lines.push(`${i === 0 ? L("現在:") : " "}${c.cyan(agent)} ${live ? c.green(`工作中 ${since(a.since, now)}`) : c.yellow("曾在工作(已中斷)")},處理 ${handlingText(a.handling)}`));
254
+ for (const [i, [agent, a]] of active.entries()) {
255
+ lines.push(`${i === 0 ? L("現在:") : " "}${c.cyan(agent)} ${live ? c.green(`工作中 ${since(a.since, now)}`) : c.yellow("曾在工作(已中斷)")},處理 ${handlingText(a.handling)}`);
256
+ }
255
257
  }
256
258
  else
257
259
  lines.push(`${L("現在:")}${c.dim(`閒置${s.end_reason ? `(執行已結束:${s.end_reason})` : live ? "" : "(執行未在運作)"}`)}`);
258
260
  const queue = s.queue;
259
261
  if (queue.length) {
260
- queue.slice(0, 3).forEach((q, i) => lines.push(`${i === 0 ? L("下一個:") : " "}${c.cyan(q.agent)} ← ${mailText(q)}`));
262
+ for (const [i, q] of queue.slice(0, 3).entries())
263
+ lines.push(`${i === 0 ? L("下一個:") : " "}${c.cyan(q.agent)} ← ${mailText(q)}`);
261
264
  if (queue.length > 3)
262
265
  lines.push(c.dim(` … 還有 ${queue.length - 3} 筆`));
263
266
  }
@@ -343,7 +346,8 @@ export function formatTaskListReport(report, color = false) {
343
346
  const head = `${c.bold("專案:")}${report.project.name} ${c.dim(`(共 ${runs.length} 個任務)`)}`;
344
347
  if (!runs.length)
345
348
  return `${head}\n\n無執行紀錄。`;
346
- const rows = [["ID", "狀態", "輪次", "目前步驟", "任務"]];
349
+ const header = ["ID", "狀態", "輪次", "目前步驟", "任務"];
350
+ const rows = [header];
347
351
  for (const s of runs) {
348
352
  rows.push([
349
353
  s.run_id,
@@ -353,11 +357,11 @@ export function formatTaskListReport(report, color = false) {
353
357
  clip(taskText(s), 60),
354
358
  ]);
355
359
  }
356
- const w = rows[0].map((_, i) => Math.max(...rows.map((r) => cols(r[i]))));
360
+ const w = header.map((_, i) => Math.max(...rows.map((r) => cols(r[i] ?? ""))));
357
361
  const line = (r, ri) => r
358
362
  .map((t, i) => {
359
- const p = i === r.length - 1 ? t : padCols(t, w[i]);
360
- return ri === 0 ? c.bold(p) : i === 1 ? stateColor(c, t) + " ".repeat(Math.max(0, w[i] - cols(t))) : p;
363
+ const p = i === r.length - 1 ? t : padCols(t, w[i] ?? 0);
364
+ return ri === 0 ? c.bold(p) : i === 1 ? stateColor(c, t) + " ".repeat(Math.max(0, (w[i] ?? 0) - cols(t))) : p;
361
365
  })
362
366
  .join(" ")
363
367
  .trimEnd();
@@ -371,23 +375,25 @@ export function formatStatus(base, now = Date.now(), color = false) {
371
375
  export function formatStatusReport(report, now = Date.now(), color = false) {
372
376
  const c = paint(color);
373
377
  const run = report.run;
374
- const rows = [["成員", "執行環境", "未讀", "上次喚醒"]];
378
+ const header = ["成員", "執行環境", "未讀", "上次喚醒"];
379
+ const rows = [header];
375
380
  for (const a of report.agents) {
376
381
  const lw = a.last_wake;
377
382
  rows.push([a.name + (a.lead ? " (lead)" : ""), a.runtime ?? "?", String(a.unread), lw ? `${lw.ok ? "成功" : "失敗"} ${lw.at}` : "-"]);
378
383
  }
379
- const w = rows[0].map((_, i) => Math.max(...rows.map((r) => cols(r[i]))));
384
+ const w = header.map((_, i) => Math.max(...rows.map((r) => cols(r[i] ?? ""))));
380
385
  // Pad on the plain text first so ANSI codes never skew the column widths.
381
386
  const cell = (r, ri, i) => {
382
- const t = i === r.length - 1 ? r[i] : padCols(r[i], w[i]); // no trailing padding, as in plain output
387
+ const text = r[i] ?? "";
388
+ const t = i === r.length - 1 ? text : padCols(text, w[i] ?? 0); // no trailing padding, as in plain output
383
389
  if (ri === 0)
384
390
  return c.bold(t);
385
391
  if (i === 0)
386
- return r[0].endsWith("(lead)") ? c.cyan(t) : t;
392
+ return text.endsWith("(lead)") ? c.cyan(t) : t;
387
393
  if (i === 2)
388
- return r[2] === "0" ? c.dim(t) : c.yellow(t);
394
+ return text === "0" ? c.dim(t) : c.yellow(t);
389
395
  if (i === 3)
390
- return r[3].startsWith("失敗") ? c.red(t) : r[3].startsWith("成功") ? c.green(t) : c.dim(t);
396
+ return text.startsWith("失敗") ? c.red(t) : text.startsWith("成功") ? c.green(t) : c.dim(t);
391
397
  return t;
392
398
  };
393
399
  const table = rows.map((r, ri) => r.map((_, i) => cell(r, ri, i)).join(" ").trimEnd());
package/dist/validate.js CHANGED
@@ -3,6 +3,7 @@ import { enforcementFor, memoryDirs, ownsDirs } from "./policy.js";
3
3
  import { isInside } from "./paths.js";
4
4
  import { inferRuntime, RUNTIME_EFFORTS } from "./schema.js";
5
5
  import { isGitRepo, resolveWorkspaceMode } from "./worktree.js";
6
+ import { must } from "./assert.js";
6
7
  export function validateProject(project) {
7
8
  const issues = [];
8
9
  const err = (message) => issues.push({ level: "error", message });
@@ -45,8 +46,8 @@ export function validateProject(project) {
45
46
  mem.push({ agent: a.name, dir: d });
46
47
  for (let i = 0; i < mem.length; i++) {
47
48
  for (let j = i + 1; j < mem.length; j++) {
48
- const x = mem[i];
49
- const y = mem[j];
49
+ const x = must(mem[i], "memory dir");
50
+ const y = must(mem[j], "memory dir");
50
51
  if (x.agent === y.agent && x.dir !== y.dir)
51
52
  continue;
52
53
  if (isInside(x.dir, y.dir) || isInside(y.dir, x.dir)) {
@@ -63,10 +64,12 @@ export function validateProject(project) {
63
64
  }
64
65
  for (let i = 0; i < withOwns.length; i++) {
65
66
  for (let j = i + 1; j < withOwns.length; j++) {
66
- for (const x of ownsDirs(project, withOwns[i])) {
67
- for (const y of ownsDirs(project, withOwns[j])) {
67
+ const ai = must(withOwns[i], "agent");
68
+ const aj = must(withOwns[j], "agent");
69
+ for (const x of ownsDirs(project, ai)) {
70
+ for (const y of ownsDirs(project, aj)) {
68
71
  if (isInside(x, y) || isInside(y, x)) {
69
- err(`"owns" overlap: ${withOwns[i].name} (${x}) vs ${withOwns[j].name} (${y})`);
72
+ err(`"owns" overlap: ${ai.name} (${x}) vs ${aj.name} (${y})`);
70
73
  }
71
74
  }
72
75
  }
@@ -99,11 +102,12 @@ export function validateProject(project) {
99
102
  return { issues, enforcement, ok: !issues.some((i) => i.level === "error") };
100
103
  }
101
104
  export function formatEnforcement(list) {
102
- const rows = [["agent", "runtime", "memory", "AGENT.md", "others' ctx", "repo CLAUDE/AGENTS", "owns"]];
105
+ const header = ["agent", "runtime", "memory", "AGENT.md", "others' ctx", "repo CLAUDE/AGENTS", "owns"];
106
+ const rows = [header];
103
107
  for (const e of list)
104
108
  rows.push([e.agent, e.runtime, e.memory, e.agentMd, e.otherContext, e.repoInstructions, e.owns]);
105
- const w = rows[0].map((_, i) => Math.max(...rows.map((r) => r[i].length)));
106
- const lines = rows.map((r) => r.map((c, i) => c.padEnd(w[i])).join(" ").trimEnd());
109
+ const w = header.map((_, i) => Math.max(...rows.map((r) => (r[i] ?? "").length)));
110
+ const lines = rows.map((r) => r.map((c, i) => c.padEnd(w[i] ?? 0)).join(" ").trimEnd());
107
111
  lines.splice(1, 0, w.map((n) => "-".repeat(n)).join(" "));
108
112
  const extra = [];
109
113
  for (const e of list) {
package/dist/worktree.js CHANGED
@@ -45,7 +45,7 @@ export function dirtyPaths(dir) {
45
45
  const parts = out.split("\0").filter(Boolean);
46
46
  const paths = [];
47
47
  for (let i = 0; i < parts.length; i++) {
48
- const entry = parts[i];
48
+ const entry = parts[i] ?? "";
49
49
  paths.push(entry.slice(3));
50
50
  if (entry[0] === "R" || entry[0] === "C")
51
51
  i++; // a rename lists its old name next
@@ -162,7 +162,7 @@ export function removeAgentWorkspace(project, runId, agent) {
162
162
  export function globMatch(glob, file) {
163
163
  let re = "";
164
164
  for (let i = 0; i < glob.length; i++) {
165
- const c = glob[i];
165
+ const c = glob.charAt(i);
166
166
  if (c === "*" && glob[i + 1] === "*") {
167
167
  if (glob[i + 2] === "/") {
168
168
  re += "(?:.*/)?";
@@ -210,10 +210,10 @@ export function collectAgentChanges(workspace, owns) {
210
210
  const parts = raw.split("\0").filter(Boolean);
211
211
  const files = [];
212
212
  for (let i = 0; i + 1 < parts.length; i += 2) {
213
- const m = /^:(\d+) (\d+) \w+ \w+ (\w)$/.exec(parts[i]);
213
+ const m = /^:(\d+) (\d+) \w+ \w+ (\w)$/.exec(parts[i] ?? "");
214
214
  if (!m)
215
215
  continue;
216
- files.push({ path: parts[i + 1], status: m[3], mode: m[2] });
216
+ files.push({ path: parts[i + 1] ?? "", status: m[3], mode: m[2] ?? "" });
217
217
  }
218
218
  const rel = path.relative(workspace.root, workspace.dir).split(path.sep).join("/");
219
219
  const violations = [];
@@ -365,8 +365,9 @@ export function inspectWorkspace(project, runId, agent) {
365
365
  const raw = execFileSync("git", ["diff", "--raw", "-z", "--no-renames", "--no-abbrev", ws.base, head], { cwd: root, encoding: "utf8", maxBuffer: 256 * 1024 * 1024 });
366
366
  const parts = raw.split("\0").filter(Boolean);
367
367
  for (let i = 1; i < parts.length; i += 2) {
368
- if (workingBlob(top, parts[i]) !== blobAt(top, head, parts[i]))
369
- work.unintegrated.push(parts[i]);
368
+ const file = parts[i] ?? "";
369
+ if (workingBlob(top, file) !== blobAt(top, head, file))
370
+ work.unintegrated.push(file);
370
371
  }
371
372
  }
372
373
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-lyceum",
3
- "version": "0.4.14",
3
+ "version": "0.5.0",
4
4
  "description": "Config + dispatcher for teams of Claude Code / Codex agents with scoped context and file-based mailboxes",
5
5
  "keywords": [
6
6
  "ai",
@@ -38,21 +38,27 @@
38
38
  "scripts": {
39
39
  "dev": "tsx src/cli.ts",
40
40
  "build": "tsc -p tsconfig.json",
41
- "typecheck": "tsc -p tsconfig.json --noEmit",
41
+ "typecheck": "tsc -p tsconfig.json --noEmit && npm run typecheck:plugin",
42
42
  "test": "vitest run",
43
43
  "prepare": "npm run build",
44
44
  "prepublishOnly": "npm run typecheck && npm test && npm run build",
45
- "release": "bash scripts/release.sh"
45
+ "release": "bash scripts/release.sh",
46
+ "typecheck:plugin": "tsc -p plugins/status-monitor/tsconfig.ci.json",
47
+ "check:pack": "node scripts/check-pack.mjs",
48
+ "lint": "biome lint",
49
+ "check:docs": "node scripts/check-docs.mjs"
46
50
  },
47
51
  "dependencies": {
48
- "commander": "^12.1.0",
52
+ "commander": "^14.0.3",
49
53
  "yaml": "^2.5.0",
50
- "zod": "^3.23.8"
54
+ "zod": "^4.6.5"
51
55
  },
52
56
  "devDependencies": {
53
- "@types/node": "^22.0.0",
57
+ "@biomejs/biome": "^2.5.15",
58
+ "@types/node": "^20.19.43",
54
59
  "tsx": "^4.19.0",
55
- "typescript": "^5.6.0",
56
- "vitest": "^2.1.0"
60
+ "typescript": "^7.0.2",
61
+ "vite": "^7.3.7",
62
+ "vitest": "^4.1.11"
57
63
  }
58
64
  }