@a-t-h-i/bot-lobby 0.6.46 → 0.6.48
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/THIRD_PARTY_NOTICES.md +15 -0
- package/package.json +17 -1
- package/prompts/designer.md +62 -44
- package/prompts/master.md +4 -3
- package/prompts/qa.md +12 -4
- package/prompts/reviewer.md +7 -1
- package/src/ask/tool.ts +2 -2
- package/src/execution/agent-runner.ts +3 -0
- package/src/execution/pi-runner.ts +5 -1
- package/src/knowledge/oracle-digest.ts +66 -0
- package/src/lobby/planner.ts +2 -0
- package/src/lobby/pr-review.ts +1 -0
- package/src/lobby/quickfix.ts +4 -0
- package/src/master/master.ts +4 -4
- package/src/master/research.ts +1 -0
- package/src/pi/auto-compaction.ts +47 -6
- package/src/pi/quiet.ts +3 -0
- package/src/roles/reviewer.ts +91 -13
- package/src/schemas/configuration.ts +19 -7
- package/src/schemas/findings.ts +2 -0
- package/src/webui/palette-core.ts +278 -1
- package/src/workflow/workflow.ts +3 -1
- package/webui/dist/assets/index-B5AnxwRU.css +2 -0
- package/webui/dist/assets/index-CznnCkjK.js +114 -0
- package/webui/dist/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
- package/webui/dist/build.json +48 -28
- package/webui/dist/index.html +2 -2
- package/webui/dist/assets/index-BJ1fEle9.js +0 -110
- package/webui/dist/assets/index-BdtiIB9L.css +0 -2
- package/webui/dist/assets/oracle-CkL__6uz.png +0 -0
package/src/roles/reviewer.ts
CHANGED
|
@@ -23,11 +23,34 @@ export const reviewerSpec: RoleSpec = {
|
|
|
23
23
|
|
|
24
24
|
const SEVERITIES: readonly Severity[] = ["critical", "major", "minor", "info"];
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
/** Severity words reviewers use outside the contract's four, mapped onto them. */
|
|
27
|
+
const SEVERITY_ALIASES: ReadonlyArray<[RegExp, Severity]> = [
|
|
28
|
+
[/\b(?:blocker|blocking|severe)\b/, "critical"],
|
|
29
|
+
[/\bhigh\b/, "major"],
|
|
30
|
+
[/\b(?:low|nit|nitpick|trivial|cosmetic|optional|suggestion)\b/, "minor"],
|
|
31
|
+
[/\b(?:note|fyi)\b/, "info"],
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Verdict words in the order a reviewer writes them. FAIL is the word qa.md
|
|
36
|
+
* used to ask for: it means changes are required, not that QA could not run.
|
|
37
|
+
*/
|
|
38
|
+
const VERDICT_TOKENS: ReadonlyArray<[RegExp, Verdict]> = [
|
|
39
|
+
[/\bCHANGES?[\s_-]*(?:REQUIRED|REQUESTED|NEEDED)\b|\b(?:NEEDS|REQUEST(?:ED)?)[\s_-]+CHANGES\b/, "changes_required"],
|
|
40
|
+
[/\bFAIL(?:ED|S|URE)?\b/, "changes_required"],
|
|
41
|
+
[/\bBLOCKED\b/, "blocked"],
|
|
42
|
+
[/\bPASS(?:ED|ES)?\b/, "pass"],
|
|
43
|
+
];
|
|
44
|
+
|
|
45
|
+
/** The first verdict word in the text, so `PASS — no changes required` reads as the PASS it leads with. */
|
|
46
|
+
function verdictToken(text: string): Verdict | undefined {
|
|
47
|
+
const value = text.toUpperCase();
|
|
48
|
+
let best: { at: number; verdict: Verdict } | undefined;
|
|
49
|
+
for (const [pattern, verdict] of VERDICT_TOKENS) {
|
|
50
|
+
const match = pattern.exec(value);
|
|
51
|
+
if (match && (!best || match.index < best.at)) best = { at: match.index, verdict };
|
|
52
|
+
}
|
|
53
|
+
return best?.verdict;
|
|
31
54
|
}
|
|
32
55
|
|
|
33
56
|
/** The verdict token may sit in the heading itself (`## Verdict PASS`), leaving an empty body. */
|
|
@@ -38,14 +61,35 @@ function verdictHeading(sections: Map<string, string>): string | undefined {
|
|
|
38
61
|
return undefined;
|
|
39
62
|
}
|
|
40
63
|
|
|
64
|
+
/**
|
|
65
|
+
* The reviewer's verdict, or undefined when none can be read. The contract's
|
|
66
|
+
* `## Verdict` section comes first; failing that, a line that names the
|
|
67
|
+
* verdict (`**Verdict:** PASS`, `# Verdict: PASS`) and the line after it.
|
|
68
|
+
*/
|
|
69
|
+
export function readVerdict(raw: string, sections = parseSections(raw)): Verdict | undefined {
|
|
70
|
+
const heading = verdictHeading(sections);
|
|
71
|
+
if (heading !== undefined) {
|
|
72
|
+
const body = (findSection(sections, "verdict") ?? "").split("\n").filter((line) => line.trim()).slice(0, 2).join("\n");
|
|
73
|
+
const found = verdictToken(`${heading}\n${body}`);
|
|
74
|
+
if (found) return found;
|
|
75
|
+
}
|
|
76
|
+
const lines = raw.split("\n");
|
|
77
|
+
const at = lines.findIndex((line) => /\bverdict\b/i.test(line));
|
|
78
|
+
if (at < 0) return undefined;
|
|
79
|
+
const next = lines.slice(at + 1).find((line) => line.trim()) ?? "";
|
|
80
|
+
return verdictToken(`${lines[at]}\n${next}`);
|
|
81
|
+
}
|
|
82
|
+
|
|
41
83
|
/** The severity a finding was tagged with, or undefined when it carries none. */
|
|
42
84
|
function taggedSeverity(text: string): Severity | undefined {
|
|
43
|
-
const
|
|
44
|
-
|
|
85
|
+
const tag = /^\*{0,2}\[([^\]]+)\]/.exec(text)?.[1]?.toLowerCase();
|
|
86
|
+
if (!tag) return undefined;
|
|
87
|
+
return SEVERITIES.find((candidate) => tag.includes(candidate))
|
|
88
|
+
?? SEVERITY_ALIASES.find(([pattern]) => pattern.test(tag))?.[1];
|
|
45
89
|
}
|
|
46
90
|
|
|
47
91
|
function parseFinding(text: string): ReviewFinding {
|
|
48
|
-
const match =
|
|
92
|
+
const match = /^\*{0,2}\[([^\]]+)\]\*{0,2}\s*(.*)$/.exec(text);
|
|
49
93
|
return { severity: taggedSeverity(text) ?? "info", text: (match?.[2] ?? text).trim() };
|
|
50
94
|
}
|
|
51
95
|
|
|
@@ -55,9 +99,38 @@ export const UNVERIFIED_PASS = "unverified pass: PASS without executed checks un
|
|
|
55
99
|
/** Minor and info findings never hold the gate; what the reviewer asked for is kept as follow-ups. */
|
|
56
100
|
export const MINOR_ONLY = "CHANGES_REQUIRED for minor or info findings only: passed, its asks kept as follow-ups";
|
|
57
101
|
|
|
58
|
-
/**
|
|
102
|
+
/** No verdict could be read: the review did not finish, so it is run again rather than stopping the task. */
|
|
103
|
+
export const NO_VERDICT = "no readable verdict: the review did not finish, so nothing is known yet about the work";
|
|
104
|
+
|
|
105
|
+
/** A check names a command and its result: `cmd — result`, `cmd: result`, `✅ cmd`, `cmd (40/40)` or `cmd passed`. */
|
|
106
|
+
const CHECK_RESULT = /\S\s*(?:—|–|-{1,2}|:|=>|→|->)\s*\S|[✅✓✔❌✗✘]|\(\s*\d+\s*\/\s*\d+\s*\)|\b(?:pass(?:ed|es|ing)?|fail(?:ed|s|ing)?|clean|exit(?:ed)?\s*(?:code\s*)?\d+|\d+\s+(?:tests?|passing|passed|failing|failed))\b/i;
|
|
107
|
+
|
|
108
|
+
/** A table row's cells, or undefined for a line that is not a row. */
|
|
109
|
+
function tableCells(line: string): string[] | undefined {
|
|
110
|
+
if (!/^\|.*\|$/.test(line)) return undefined;
|
|
111
|
+
return line.slice(1, -1).split("|").map((cell) => cell.trim());
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* The checks under `## Verification`: bullets, numbered items and table rows
|
|
116
|
+
* that name a command and its result. A reviewer's list style never decides
|
|
117
|
+
* whether the gate believes it ran something.
|
|
118
|
+
*/
|
|
59
119
|
function executedChecks(verification: string): string[] {
|
|
60
|
-
|
|
120
|
+
const lines = verification.split("\n").map((line) => line.trim());
|
|
121
|
+
const checks: string[] = [];
|
|
122
|
+
lines.forEach((line, index) => {
|
|
123
|
+
const cells = tableCells(line);
|
|
124
|
+
if (cells) {
|
|
125
|
+
const separator = cells.every((cell) => /^:?-{2,}:?$/.test(cell));
|
|
126
|
+
const header = tableCells(lines[index + 1] ?? "")?.every((cell) => /^:?-{2,}:?$/.test(cell));
|
|
127
|
+
if (!separator && !header && cells.filter(Boolean).length >= 2) checks.push(cells.join(" — "));
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const item = /^(?:[-*+]|\d+[.)])\s+(\S.*)$/.exec(line)?.[1];
|
|
131
|
+
if (item && CHECK_RESULT.test(item)) checks.push(item);
|
|
132
|
+
});
|
|
133
|
+
return checks;
|
|
61
134
|
}
|
|
62
135
|
|
|
63
136
|
/** Parse a reviewer's markdown into a structured verdict (never throws). */
|
|
@@ -66,11 +139,15 @@ export function parseReviewResult(domain: Domain, raw: string): ReviewResult {
|
|
|
66
139
|
const verification = findSection(sections, "verification") ?? "";
|
|
67
140
|
const requiredChanges = bullets(findSection(sections, "required changes"));
|
|
68
141
|
const entries = bullets(findSection(sections, "findings"));
|
|
69
|
-
|
|
142
|
+
const read = readVerdict(raw, sections);
|
|
143
|
+
let verdict: Verdict = read ?? "changes_required";
|
|
70
144
|
let downgraded: string | undefined;
|
|
71
145
|
let relaxed: string | undefined;
|
|
72
146
|
const checked = executedChecks(verification).length > 0;
|
|
73
|
-
if (
|
|
147
|
+
if (!read) {
|
|
148
|
+
// Never a pass, and never a stop either: an unreadable review is run again.
|
|
149
|
+
requiredChanges.push("Re-run the QA gate: the last review returned no readable verdict.");
|
|
150
|
+
} else if (verdict === "pass" && !checked) {
|
|
74
151
|
verdict = "changes_required";
|
|
75
152
|
downgraded = UNVERIFIED_PASS;
|
|
76
153
|
requiredChanges.push("Re-run the QA gate and record the checks actually executed, each as `- command — result`.");
|
|
@@ -93,6 +170,7 @@ export function parseReviewResult(domain: Domain, raw: string): ReviewResult {
|
|
|
93
170
|
pushback: parsePushback(sections),
|
|
94
171
|
...(downgraded ? { downgraded } : {}),
|
|
95
172
|
...(relaxed ? { relaxed } : {}),
|
|
173
|
+
...(read ? {} : { unread: NO_VERDICT }),
|
|
96
174
|
raw,
|
|
97
175
|
};
|
|
98
176
|
}
|
|
@@ -100,7 +178,7 @@ export function parseReviewResult(domain: Domain, raw: string): ReviewResult {
|
|
|
100
178
|
/** An unknown verdict must never be treated as acceptance (§42). */
|
|
101
179
|
export function validateReviewResult(result: ReviewResult): string[] {
|
|
102
180
|
const issues: string[] = [];
|
|
103
|
-
if (
|
|
181
|
+
if (result.unread) issues.push("missing Verdict section");
|
|
104
182
|
if (result.downgraded) issues.push(result.downgraded);
|
|
105
183
|
if (result.verdict !== "pass" && result.findings.length === 0 && result.requiredChanges.length === 0) {
|
|
106
184
|
issues.push("non-pass verdict without findings or required changes");
|
|
@@ -31,6 +31,8 @@ export interface AgentModelConfig {
|
|
|
31
31
|
mcpTools?: string[];
|
|
32
32
|
/** Time limit per run; falls back to `workflow.agentTimeoutMs`. */
|
|
33
33
|
timeoutMs?: number;
|
|
34
|
+
/** Compact this agent's context on its own as it fills (on unless false); the oracle's also updates the knowledge base. */
|
|
35
|
+
autoCompact?: boolean;
|
|
34
36
|
}
|
|
35
37
|
|
|
36
38
|
/** Scouts pick a model and a time limit only; their thinking is fixed at `SCOUT_THINKING`. */
|
|
@@ -40,6 +42,8 @@ export interface ScoutConfig {
|
|
|
40
42
|
timeoutMs: number;
|
|
41
43
|
/** Tool calls a scout may make: it is told to wrap up at 60% and refused more past this, so it reports with what it has; 0 = no limit. */
|
|
42
44
|
maxToolCalls: number;
|
|
45
|
+
/** Compact a scout's context on its own as it fills (on unless false). */
|
|
46
|
+
autoCompact?: boolean;
|
|
43
47
|
}
|
|
44
48
|
|
|
45
49
|
/** Subagent kinds with their own settings entry. */
|
|
@@ -351,7 +355,7 @@ function normalizeAgent(base: AgentModelConfig, override: Partial<AgentModelConf
|
|
|
351
355
|
const thinking = isThinkingLevel(merged.thinking) ? merged.thinking : base.thinking;
|
|
352
356
|
const timeoutMs = positive(merged.timeoutMs) ?? base.timeoutMs;
|
|
353
357
|
const mcpTools = normalizeMcpTools(merged.mcpTools);
|
|
354
|
-
return { model: merged.model, thinking, ...(mcpTools.length ? { mcpTools } : {}), ...(typeof merged.instructions === "string" ? { instructions: merged.instructions } : {}), ...(timeoutMs ? { timeoutMs } : {}) };
|
|
358
|
+
return { model: merged.model, thinking, ...(mcpTools.length ? { mcpTools } : {}), ...(typeof merged.instructions === "string" ? { instructions: merged.instructions } : {}), ...(timeoutMs ? { timeoutMs } : {}), ...(merged.autoCompact === false ? { autoCompact: false } : {}) };
|
|
355
359
|
}
|
|
356
360
|
|
|
357
361
|
/** Scouts keep a model and a time limit; any thinking value in the file is dropped. */
|
|
@@ -363,6 +367,7 @@ function normalizeScout(override: Partial<ScoutConfig> | undefined): ScoutConfig
|
|
|
363
367
|
timeoutMs: positive(override?.timeoutMs) ?? base.timeoutMs,
|
|
364
368
|
maxToolCalls: typeof override?.maxToolCalls === "number" && Number.isFinite(override.maxToolCalls) && override.maxToolCalls >= 0 ? Math.round(override.maxToolCalls) : base.maxToolCalls,
|
|
365
369
|
...(mcpTools.length ? { mcpTools } : {}),
|
|
370
|
+
...(override?.autoCompact === false ? { autoCompact: false } : {}),
|
|
366
371
|
};
|
|
367
372
|
}
|
|
368
373
|
|
|
@@ -513,6 +518,13 @@ export interface AgentProfile {
|
|
|
513
518
|
instructions?: string;
|
|
514
519
|
/** Exact native MCP tool names this profile may call; empty grants none. */
|
|
515
520
|
mcpTools?: string[];
|
|
521
|
+
/** False when its settings turn auto-compaction off. */
|
|
522
|
+
autoCompact?: boolean;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
/** `{ autoCompact: false }` when an entry turns auto-compaction off, else nothing. */
|
|
526
|
+
function compactField(entry: { autoCompact?: boolean }): { autoCompact?: false } {
|
|
527
|
+
return entry.autoCompact === false ? { autoCompact: false } : {};
|
|
516
528
|
}
|
|
517
529
|
|
|
518
530
|
/** The settings entry a domain/role run draws from. */
|
|
@@ -537,10 +549,10 @@ export function agentProfile(config: BotLobbyConfig, domain: Domain, role: Role)
|
|
|
537
549
|
const instructions = config.agents[domain].instructions;
|
|
538
550
|
const fallback = config.workflow.agentTimeoutMs;
|
|
539
551
|
if (kind === "scout") {
|
|
540
|
-
return { kind, model: modelOf(config.scout.model), thinking: SCOUT_THINKING, timeoutMs: config.scout.timeoutMs || fallback, instructions, ...(config.scout.mcpTools?.length ? { mcpTools: config.scout.mcpTools } : {}) };
|
|
552
|
+
return { kind, model: modelOf(config.scout.model), thinking: SCOUT_THINKING, timeoutMs: config.scout.timeoutMs || fallback, instructions, ...(config.scout.mcpTools?.length ? { mcpTools: config.scout.mcpTools } : {}), ...compactField(config.scout) };
|
|
541
553
|
}
|
|
542
554
|
const entry = kind === "researcher" ? config.researcher : config.agents[kind];
|
|
543
|
-
return { kind, model: modelOf(entry.model), thinking: entry.thinking, timeoutMs: entry.timeoutMs ?? fallback, instructions, ...(entry.mcpTools?.length ? { mcpTools: entry.mcpTools } : {}) };
|
|
555
|
+
return { kind, model: modelOf(entry.model), thinking: entry.thinking, timeoutMs: entry.timeoutMs ?? fallback, instructions, ...(entry.mcpTools?.length ? { mcpTools: entry.mcpTools } : {}), ...compactField(entry) };
|
|
544
556
|
}
|
|
545
557
|
|
|
546
558
|
/** The settings entry of a lobby agent (quick fix or planner). */
|
|
@@ -549,19 +561,19 @@ export function lobbyAgentConfig(config: BotLobbyConfig, kind: LobbyAgentKind):
|
|
|
549
561
|
}
|
|
550
562
|
|
|
551
563
|
/** Profile for a lobby agent run, from settings alone; `model` is undefined while unset. */
|
|
552
|
-
export function lobbyAgentProfile(config: BotLobbyConfig, kind: LobbyAgentKind): { model?: string; thinking: string; timeoutMs: number; instructions?: string; mcpTools?: string[] } {
|
|
564
|
+
export function lobbyAgentProfile(config: BotLobbyConfig, kind: LobbyAgentKind): { model?: string; thinking: string; timeoutMs: number; instructions?: string; mcpTools?: string[]; autoCompact?: boolean } {
|
|
553
565
|
const entry = lobbyAgentConfig(config, kind);
|
|
554
|
-
return { model: modelOf(entry.model), thinking: entry.thinking, timeoutMs: entry.timeoutMs ?? config.workflow.agentTimeoutMs, instructions: entry.instructions, ...(entry.mcpTools?.length ? { mcpTools: entry.mcpTools } : {}) };
|
|
566
|
+
return { model: modelOf(entry.model), thinking: entry.thinking, timeoutMs: entry.timeoutMs ?? config.workflow.agentTimeoutMs, instructions: entry.instructions, ...(entry.mcpTools?.length ? { mcpTools: entry.mcpTools } : {}), ...compactField(entry) };
|
|
555
567
|
}
|
|
556
568
|
|
|
557
569
|
/**
|
|
558
570
|
* A planning panel seat's profile: the domain's (or the researcher's) model,
|
|
559
571
|
* thinking and custom instructions, bounded by the planner's per-turn limit.
|
|
560
572
|
*/
|
|
561
|
-
export function panelMemberProfile(config: BotLobbyConfig, member: PanelMember): { model?: string; thinking: string; timeoutMs: number; instructions?: string; mcpTools?: string[] } {
|
|
573
|
+
export function panelMemberProfile(config: BotLobbyConfig, member: PanelMember): { model?: string; thinking: string; timeoutMs: number; instructions?: string; mcpTools?: string[]; autoCompact?: boolean } {
|
|
562
574
|
const entry = member === "researcher" ? config.researcher : config.agents[member];
|
|
563
575
|
const timeoutMs = config.planner.timeoutMs ?? config.workflow.agentTimeoutMs;
|
|
564
|
-
return { model: modelOf(entry.model), thinking: entry.thinking, timeoutMs, instructions: entry.instructions, ...(entry.mcpTools?.length ? { mcpTools: entry.mcpTools } : {}) };
|
|
576
|
+
return { model: modelOf(entry.model), thinking: entry.thinking, timeoutMs, instructions: entry.instructions, ...(entry.mcpTools?.length ? { mcpTools: entry.mcpTools } : {}), ...compactField(entry) };
|
|
565
577
|
}
|
|
566
578
|
|
|
567
579
|
/** Resolves the model, thinking and time limit one subagent run uses. */
|
package/src/schemas/findings.ts
CHANGED
|
@@ -89,6 +89,8 @@ export interface ReviewResult {
|
|
|
89
89
|
downgraded?: string;
|
|
90
90
|
/** Set when the engine passed a CHANGES_REQUIRED that named only minor or info findings. */
|
|
91
91
|
relaxed?: string;
|
|
92
|
+
/** Set when no verdict could be read from the review (a failed or off-contract run). */
|
|
93
|
+
unread?: string;
|
|
92
94
|
raw: string;
|
|
93
95
|
}
|
|
94
96
|
|
|
@@ -178,7 +178,8 @@ export const DEFAULT_ID = "mist"
|
|
|
178
178
|
* T3 Tools Inc., packages/shared/src/themePalettes.ts), their roles mapped onto
|
|
179
179
|
* the shadcn variables: canvas is the background, surface the card, accent the
|
|
180
180
|
* primary, accent surface the accent, error the destructive colour. Slate,
|
|
181
|
-
* Sand, Rosewood, Aurora and Midnight are original
|
|
181
|
+
* Sand, Rosewood, Aurora and Midnight, and Graphite, Lagoon, Dune, Plum, Moss and Crimson, are original
|
|
182
|
+
* complementary palettes.
|
|
182
183
|
*/
|
|
183
184
|
export const PRESETS: readonly Palette[] = [
|
|
184
185
|
{ id: DEFAULT_ID, name: "Default" },
|
|
@@ -642,6 +643,282 @@ export const PRESETS: readonly Palette[] = [
|
|
|
642
643
|
"chart-1": "#acbbed",
|
|
643
644
|
},
|
|
644
645
|
},
|
|
646
|
+
{
|
|
647
|
+
id: "graphite",
|
|
648
|
+
name: "Graphite",
|
|
649
|
+
light: {
|
|
650
|
+
"background": "oklch(0.985 0 260)",
|
|
651
|
+
"foreground": "oklch(0.25 0 260)",
|
|
652
|
+
"card": "oklch(0.997 0 260)",
|
|
653
|
+
"card-foreground": "oklch(0.25 0 260)",
|
|
654
|
+
"popover": "oklch(0.997 0 260)",
|
|
655
|
+
"popover-foreground": "oklch(0.25 0 260)",
|
|
656
|
+
"primary": "oklch(0.32 0 0)",
|
|
657
|
+
"primary-foreground": "oklch(0.99 0 0)",
|
|
658
|
+
"secondary": "oklch(0.94 0 260)",
|
|
659
|
+
"secondary-foreground": "oklch(0.25 0 260)",
|
|
660
|
+
"muted": "oklch(0.955 0 260)",
|
|
661
|
+
"muted-foreground": "oklch(0.48 0 260)",
|
|
662
|
+
"accent": "oklch(0.93 0 260)",
|
|
663
|
+
"accent-foreground": "oklch(0.25 0 260)",
|
|
664
|
+
"destructive": "oklch(0.56 0.2 25)",
|
|
665
|
+
"border": "oklch(0.9 0 260)",
|
|
666
|
+
"input": "oklch(0.85 0 260)",
|
|
667
|
+
"ring": "oklch(0.32 0 0)",
|
|
668
|
+
"chart-1": "oklch(0.32 0 0)",
|
|
669
|
+
},
|
|
670
|
+
dark: {
|
|
671
|
+
"background": "oklch(0.18 0 260)",
|
|
672
|
+
"foreground": "oklch(0.95 0 260)",
|
|
673
|
+
"card": "oklch(0.215 0 260)",
|
|
674
|
+
"card-foreground": "oklch(0.95 0 260)",
|
|
675
|
+
"popover": "oklch(0.245 0 260)",
|
|
676
|
+
"popover-foreground": "oklch(0.95 0 260)",
|
|
677
|
+
"primary": "oklch(0.92 0 0)",
|
|
678
|
+
"primary-foreground": "oklch(0.18 0 260)",
|
|
679
|
+
"secondary": "oklch(0.28 0 260)",
|
|
680
|
+
"secondary-foreground": "oklch(0.95 0 260)",
|
|
681
|
+
"muted": "oklch(0.26 0 260)",
|
|
682
|
+
"muted-foreground": "oklch(0.74 0 260)",
|
|
683
|
+
"accent": "oklch(0.32 0 260)",
|
|
684
|
+
"accent-foreground": "oklch(0.95 0 260)",
|
|
685
|
+
"destructive": "oklch(0.7 0.17 22)",
|
|
686
|
+
"border": "oklch(0.32 0 260)",
|
|
687
|
+
"input": "oklch(0.38 0 260)",
|
|
688
|
+
"ring": "oklch(0.92 0 0)",
|
|
689
|
+
"chart-1": "oklch(0.92 0 0)",
|
|
690
|
+
},
|
|
691
|
+
},
|
|
692
|
+
{
|
|
693
|
+
id: "lagoon",
|
|
694
|
+
name: "Lagoon",
|
|
695
|
+
light: {
|
|
696
|
+
"background": "oklch(0.985 0.0096 200)",
|
|
697
|
+
"foreground": "oklch(0.25 0.03 200)",
|
|
698
|
+
"card": "oklch(0.997 0.0048 200)",
|
|
699
|
+
"card-foreground": "oklch(0.25 0.03 200)",
|
|
700
|
+
"popover": "oklch(0.997 0.0048 200)",
|
|
701
|
+
"popover-foreground": "oklch(0.25 0.03 200)",
|
|
702
|
+
"primary": "oklch(0.55 0.12 200)",
|
|
703
|
+
"primary-foreground": "oklch(0.99 0 0)",
|
|
704
|
+
"secondary": "oklch(0.94 0.03 200)",
|
|
705
|
+
"secondary-foreground": "oklch(0.25 0.03 200)",
|
|
706
|
+
"muted": "oklch(0.955 0.018 200)",
|
|
707
|
+
"muted-foreground": "oklch(0.48 0.036 200)",
|
|
708
|
+
"accent": "oklch(0.93 0.048 200)",
|
|
709
|
+
"accent-foreground": "oklch(0.25 0.03 200)",
|
|
710
|
+
"destructive": "oklch(0.56 0.2 25)",
|
|
711
|
+
"border": "oklch(0.9 0.024 200)",
|
|
712
|
+
"input": "oklch(0.85 0.03 200)",
|
|
713
|
+
"ring": "oklch(0.55 0.12 200)",
|
|
714
|
+
"chart-1": "oklch(0.55 0.12 200)",
|
|
715
|
+
},
|
|
716
|
+
dark: {
|
|
717
|
+
"background": "oklch(0.18 0.024 200)",
|
|
718
|
+
"foreground": "oklch(0.95 0.0096 200)",
|
|
719
|
+
"card": "oklch(0.215 0.0264 200)",
|
|
720
|
+
"card-foreground": "oklch(0.95 0.0096 200)",
|
|
721
|
+
"popover": "oklch(0.245 0.0264 200)",
|
|
722
|
+
"popover-foreground": "oklch(0.95 0.0096 200)",
|
|
723
|
+
"primary": "oklch(0.76 0.102 200)",
|
|
724
|
+
"primary-foreground": "oklch(0.18 0.024 200)",
|
|
725
|
+
"secondary": "oklch(0.28 0.03 200)",
|
|
726
|
+
"secondary-foreground": "oklch(0.95 0.0096 200)",
|
|
727
|
+
"muted": "oklch(0.26 0.024 200)",
|
|
728
|
+
"muted-foreground": "oklch(0.74 0.0216 200)",
|
|
729
|
+
"accent": "oklch(0.32 0.048 200)",
|
|
730
|
+
"accent-foreground": "oklch(0.95 0.0096 200)",
|
|
731
|
+
"destructive": "oklch(0.7 0.17 22)",
|
|
732
|
+
"border": "oklch(0.32 0.03 200)",
|
|
733
|
+
"input": "oklch(0.38 0.03 200)",
|
|
734
|
+
"ring": "oklch(0.76 0.102 200)",
|
|
735
|
+
"chart-1": "oklch(0.76 0.102 200)",
|
|
736
|
+
},
|
|
737
|
+
},
|
|
738
|
+
{
|
|
739
|
+
id: "dune",
|
|
740
|
+
name: "Dune",
|
|
741
|
+
light: {
|
|
742
|
+
"background": "oklch(0.985 0.0096 70)",
|
|
743
|
+
"foreground": "oklch(0.25 0.03 70)",
|
|
744
|
+
"card": "oklch(0.997 0.0048 70)",
|
|
745
|
+
"card-foreground": "oklch(0.25 0.03 70)",
|
|
746
|
+
"popover": "oklch(0.997 0.0048 70)",
|
|
747
|
+
"popover-foreground": "oklch(0.25 0.03 70)",
|
|
748
|
+
"primary": "oklch(0.55 0.12 70)",
|
|
749
|
+
"primary-foreground": "oklch(0.99 0 0)",
|
|
750
|
+
"secondary": "oklch(0.94 0.03 70)",
|
|
751
|
+
"secondary-foreground": "oklch(0.25 0.03 70)",
|
|
752
|
+
"muted": "oklch(0.955 0.018 70)",
|
|
753
|
+
"muted-foreground": "oklch(0.48 0.036 70)",
|
|
754
|
+
"accent": "oklch(0.93 0.048 70)",
|
|
755
|
+
"accent-foreground": "oklch(0.25 0.03 70)",
|
|
756
|
+
"destructive": "oklch(0.56 0.2 25)",
|
|
757
|
+
"border": "oklch(0.9 0.024 70)",
|
|
758
|
+
"input": "oklch(0.85 0.03 70)",
|
|
759
|
+
"ring": "oklch(0.55 0.12 70)",
|
|
760
|
+
"chart-1": "oklch(0.55 0.12 70)",
|
|
761
|
+
},
|
|
762
|
+
dark: {
|
|
763
|
+
"background": "oklch(0.18 0.024 70)",
|
|
764
|
+
"foreground": "oklch(0.95 0.0096 70)",
|
|
765
|
+
"card": "oklch(0.215 0.0264 70)",
|
|
766
|
+
"card-foreground": "oklch(0.95 0.0096 70)",
|
|
767
|
+
"popover": "oklch(0.245 0.0264 70)",
|
|
768
|
+
"popover-foreground": "oklch(0.95 0.0096 70)",
|
|
769
|
+
"primary": "oklch(0.76 0.102 70)",
|
|
770
|
+
"primary-foreground": "oklch(0.18 0.024 70)",
|
|
771
|
+
"secondary": "oklch(0.28 0.03 70)",
|
|
772
|
+
"secondary-foreground": "oklch(0.95 0.0096 70)",
|
|
773
|
+
"muted": "oklch(0.26 0.024 70)",
|
|
774
|
+
"muted-foreground": "oklch(0.74 0.0216 70)",
|
|
775
|
+
"accent": "oklch(0.32 0.048 70)",
|
|
776
|
+
"accent-foreground": "oklch(0.95 0.0096 70)",
|
|
777
|
+
"destructive": "oklch(0.7 0.17 22)",
|
|
778
|
+
"border": "oklch(0.32 0.03 70)",
|
|
779
|
+
"input": "oklch(0.38 0.03 70)",
|
|
780
|
+
"ring": "oklch(0.76 0.102 70)",
|
|
781
|
+
"chart-1": "oklch(0.76 0.102 70)",
|
|
782
|
+
},
|
|
783
|
+
},
|
|
784
|
+
{
|
|
785
|
+
id: "plum",
|
|
786
|
+
name: "Plum",
|
|
787
|
+
light: {
|
|
788
|
+
"background": "oklch(0.985 0.0112 320)",
|
|
789
|
+
"foreground": "oklch(0.25 0.035 320)",
|
|
790
|
+
"card": "oklch(0.997 0.0056 320)",
|
|
791
|
+
"card-foreground": "oklch(0.25 0.035 320)",
|
|
792
|
+
"popover": "oklch(0.997 0.0056 320)",
|
|
793
|
+
"popover-foreground": "oklch(0.25 0.035 320)",
|
|
794
|
+
"primary": "oklch(0.55 0.14 320)",
|
|
795
|
+
"primary-foreground": "oklch(0.99 0 0)",
|
|
796
|
+
"secondary": "oklch(0.94 0.035 320)",
|
|
797
|
+
"secondary-foreground": "oklch(0.25 0.035 320)",
|
|
798
|
+
"muted": "oklch(0.955 0.021 320)",
|
|
799
|
+
"muted-foreground": "oklch(0.48 0.042 320)",
|
|
800
|
+
"accent": "oklch(0.93 0.056 320)",
|
|
801
|
+
"accent-foreground": "oklch(0.25 0.035 320)",
|
|
802
|
+
"destructive": "oklch(0.56 0.2 25)",
|
|
803
|
+
"border": "oklch(0.9 0.028 320)",
|
|
804
|
+
"input": "oklch(0.85 0.035 320)",
|
|
805
|
+
"ring": "oklch(0.55 0.14 320)",
|
|
806
|
+
"chart-1": "oklch(0.55 0.14 320)",
|
|
807
|
+
},
|
|
808
|
+
dark: {
|
|
809
|
+
"background": "oklch(0.18 0.028 320)",
|
|
810
|
+
"foreground": "oklch(0.95 0.0112 320)",
|
|
811
|
+
"card": "oklch(0.215 0.0308 320)",
|
|
812
|
+
"card-foreground": "oklch(0.95 0.0112 320)",
|
|
813
|
+
"popover": "oklch(0.245 0.0308 320)",
|
|
814
|
+
"popover-foreground": "oklch(0.95 0.0112 320)",
|
|
815
|
+
"primary": "oklch(0.76 0.119 320)",
|
|
816
|
+
"primary-foreground": "oklch(0.18 0.028 320)",
|
|
817
|
+
"secondary": "oklch(0.28 0.035 320)",
|
|
818
|
+
"secondary-foreground": "oklch(0.95 0.0112 320)",
|
|
819
|
+
"muted": "oklch(0.26 0.028 320)",
|
|
820
|
+
"muted-foreground": "oklch(0.74 0.0252 320)",
|
|
821
|
+
"accent": "oklch(0.32 0.056 320)",
|
|
822
|
+
"accent-foreground": "oklch(0.95 0.0112 320)",
|
|
823
|
+
"destructive": "oklch(0.7 0.17 22)",
|
|
824
|
+
"border": "oklch(0.32 0.035 320)",
|
|
825
|
+
"input": "oklch(0.38 0.035 320)",
|
|
826
|
+
"ring": "oklch(0.76 0.119 320)",
|
|
827
|
+
"chart-1": "oklch(0.76 0.119 320)",
|
|
828
|
+
},
|
|
829
|
+
},
|
|
830
|
+
{
|
|
831
|
+
id: "moss",
|
|
832
|
+
name: "Moss",
|
|
833
|
+
light: {
|
|
834
|
+
"background": "oklch(0.985 0.0088 135)",
|
|
835
|
+
"foreground": "oklch(0.25 0.0275 135)",
|
|
836
|
+
"card": "oklch(0.997 0.0044 135)",
|
|
837
|
+
"card-foreground": "oklch(0.25 0.0275 135)",
|
|
838
|
+
"popover": "oklch(0.997 0.0044 135)",
|
|
839
|
+
"popover-foreground": "oklch(0.25 0.0275 135)",
|
|
840
|
+
"primary": "oklch(0.55 0.11 135)",
|
|
841
|
+
"primary-foreground": "oklch(0.99 0 0)",
|
|
842
|
+
"secondary": "oklch(0.94 0.0275 135)",
|
|
843
|
+
"secondary-foreground": "oklch(0.25 0.0275 135)",
|
|
844
|
+
"muted": "oklch(0.955 0.0165 135)",
|
|
845
|
+
"muted-foreground": "oklch(0.48 0.033 135)",
|
|
846
|
+
"accent": "oklch(0.93 0.044 135)",
|
|
847
|
+
"accent-foreground": "oklch(0.25 0.0275 135)",
|
|
848
|
+
"destructive": "oklch(0.56 0.2 25)",
|
|
849
|
+
"border": "oklch(0.9 0.022 135)",
|
|
850
|
+
"input": "oklch(0.85 0.0275 135)",
|
|
851
|
+
"ring": "oklch(0.55 0.11 135)",
|
|
852
|
+
"chart-1": "oklch(0.55 0.11 135)",
|
|
853
|
+
},
|
|
854
|
+
dark: {
|
|
855
|
+
"background": "oklch(0.18 0.022 135)",
|
|
856
|
+
"foreground": "oklch(0.95 0.0088 135)",
|
|
857
|
+
"card": "oklch(0.215 0.0242 135)",
|
|
858
|
+
"card-foreground": "oklch(0.95 0.0088 135)",
|
|
859
|
+
"popover": "oklch(0.245 0.0242 135)",
|
|
860
|
+
"popover-foreground": "oklch(0.95 0.0088 135)",
|
|
861
|
+
"primary": "oklch(0.76 0.0935 135)",
|
|
862
|
+
"primary-foreground": "oklch(0.18 0.022 135)",
|
|
863
|
+
"secondary": "oklch(0.28 0.0275 135)",
|
|
864
|
+
"secondary-foreground": "oklch(0.95 0.0088 135)",
|
|
865
|
+
"muted": "oklch(0.26 0.022 135)",
|
|
866
|
+
"muted-foreground": "oklch(0.74 0.0198 135)",
|
|
867
|
+
"accent": "oklch(0.32 0.044 135)",
|
|
868
|
+
"accent-foreground": "oklch(0.95 0.0088 135)",
|
|
869
|
+
"destructive": "oklch(0.7 0.17 22)",
|
|
870
|
+
"border": "oklch(0.32 0.0275 135)",
|
|
871
|
+
"input": "oklch(0.38 0.0275 135)",
|
|
872
|
+
"ring": "oklch(0.76 0.0935 135)",
|
|
873
|
+
"chart-1": "oklch(0.76 0.0935 135)",
|
|
874
|
+
},
|
|
875
|
+
},
|
|
876
|
+
{
|
|
877
|
+
id: "crimson",
|
|
878
|
+
name: "Crimson",
|
|
879
|
+
light: {
|
|
880
|
+
"background": "oklch(0.985 0.0136 20)",
|
|
881
|
+
"foreground": "oklch(0.25 0.0425 20)",
|
|
882
|
+
"card": "oklch(0.997 0.0068 20)",
|
|
883
|
+
"card-foreground": "oklch(0.25 0.0425 20)",
|
|
884
|
+
"popover": "oklch(0.997 0.0068 20)",
|
|
885
|
+
"popover-foreground": "oklch(0.25 0.0425 20)",
|
|
886
|
+
"primary": "oklch(0.55 0.17 20)",
|
|
887
|
+
"primary-foreground": "oklch(0.99 0 0)",
|
|
888
|
+
"secondary": "oklch(0.94 0.0425 20)",
|
|
889
|
+
"secondary-foreground": "oklch(0.25 0.0425 20)",
|
|
890
|
+
"muted": "oklch(0.955 0.0255 20)",
|
|
891
|
+
"muted-foreground": "oklch(0.48 0.051 20)",
|
|
892
|
+
"accent": "oklch(0.93 0.068 20)",
|
|
893
|
+
"accent-foreground": "oklch(0.25 0.0425 20)",
|
|
894
|
+
"destructive": "oklch(0.56 0.2 25)",
|
|
895
|
+
"border": "oklch(0.9 0.034 20)",
|
|
896
|
+
"input": "oklch(0.85 0.0425 20)",
|
|
897
|
+
"ring": "oklch(0.55 0.17 20)",
|
|
898
|
+
"chart-1": "oklch(0.55 0.17 20)",
|
|
899
|
+
},
|
|
900
|
+
dark: {
|
|
901
|
+
"background": "oklch(0.18 0.034 20)",
|
|
902
|
+
"foreground": "oklch(0.95 0.0136 20)",
|
|
903
|
+
"card": "oklch(0.215 0.0374 20)",
|
|
904
|
+
"card-foreground": "oklch(0.95 0.0136 20)",
|
|
905
|
+
"popover": "oklch(0.245 0.0374 20)",
|
|
906
|
+
"popover-foreground": "oklch(0.95 0.0136 20)",
|
|
907
|
+
"primary": "oklch(0.76 0.1445 20)",
|
|
908
|
+
"primary-foreground": "oklch(0.18 0.034 20)",
|
|
909
|
+
"secondary": "oklch(0.28 0.0425 20)",
|
|
910
|
+
"secondary-foreground": "oklch(0.95 0.0136 20)",
|
|
911
|
+
"muted": "oklch(0.26 0.034 20)",
|
|
912
|
+
"muted-foreground": "oklch(0.74 0.0306 20)",
|
|
913
|
+
"accent": "oklch(0.32 0.068 20)",
|
|
914
|
+
"accent-foreground": "oklch(0.95 0.0136 20)",
|
|
915
|
+
"destructive": "oklch(0.7 0.17 22)",
|
|
916
|
+
"border": "oklch(0.32 0.0425 20)",
|
|
917
|
+
"input": "oklch(0.38 0.0425 20)",
|
|
918
|
+
"ring": "oklch(0.76 0.1445 20)",
|
|
919
|
+
"chart-1": "oklch(0.76 0.1445 20)",
|
|
920
|
+
},
|
|
921
|
+
},
|
|
645
922
|
]
|
|
646
923
|
|
|
647
924
|
/** Colours for a preview swatch, per mode: the default's own values by hand, the rest from the theme. */
|
package/src/workflow/workflow.ts
CHANGED
|
@@ -1289,7 +1289,9 @@ function qaReport(header: string, result: ReviewResult, decision: LoopDecision,
|
|
|
1289
1289
|
: decision === "waived"
|
|
1290
1290
|
? "The user accepted the work as it is, without a QA pass. Call action=complete now with a short summary that names what QA still asked for."
|
|
1291
1291
|
: decision === "iterate"
|
|
1292
|
-
?
|
|
1292
|
+
? result.unread
|
|
1293
|
+
? "QA returned no readable verdict, so nothing is known about the work yet: re-run action=qa; there is nothing to fix first."
|
|
1294
|
+
: "The QA gate did not pass: delegate the required changes to the owning domain, then re-run action=qa."
|
|
1293
1295
|
: "The review limit is reached and the user did not accept the work: mark the task blocked and tell the user what QA still asks for. They can accept it with /bot-lobby accept.",
|
|
1294
1296
|
result.pushback ? pushbackLine(result.pushback, "qa") : "",
|
|
1295
1297
|
issues.length > 0 ? `Issues: ${issues.join("; ")}` : "",
|