thoth-agents 0.3.2 → 0.3.4
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/.claude-plugin/marketplace.json +1 -1
- package/README.md +34 -29
- package/dist/{chunk-YUCGIJPP.js → chunk-6GQYMWWT.js} +1 -1
- package/dist/{chunk-XO74DXBZ.js → chunk-F2K4CS5J.js} +32 -23
- package/dist/{chunk-NUSODNWE.js → chunk-W5GCMYA3.js} +63 -24
- package/dist/cli/codex-plugin-install.d.ts +51 -0
- package/dist/cli/index.js +260 -13
- package/dist/cli/skills.d.ts +2 -0
- package/dist/cli/tui/index.js +2 -2
- package/dist/harness/core/agent-pack.d.ts +3 -3
- package/dist/harness/core/sdd.d.ts +30 -23
- package/dist/index.js +2 -2
- package/package.json +1 -1
- package/plugin/.claude-plugin/.thoth-agents-plugin-assets.json +2 -2
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/agents/oracle.md +6 -6
- package/plugin/agents/orchestrator.md +8 -7
- package/plugin/skills/plan-reviewer/SKILL.md +107 -0
- package/plugin/skills/plan-reviewer/templates/plan-review.md +65 -0
- package/plugin/skills/thoth-constitution/templates/constitution.md +2 -2
- package/plugin/skills/thoth-init/SKILL.md +1 -1
- package/plugin/skills/thoth-init/scripts/init.mjs +1 -0
- package/plugin/skills/thoth-sdd/SKILL.md +21 -15
- package/skills/README.md +4 -2
- package/skills/plan-reviewer/SKILL.md +107 -0
- package/skills/plan-reviewer/templates/plan-review.md +65 -0
- package/skills/thoth-constitution/templates/constitution.md +2 -2
- package/skills/thoth-init/SKILL.md +1 -1
- package/skills/thoth-init/scripts/init.mjs +1 -0
- package/skills/thoth-sdd/SKILL.md +21 -15
- package/plugin/skills/thoth-sdd/references/phases/analyze.md +0 -21
- package/skills/thoth-sdd/references/phases/analyze.md +0 -21
package/dist/cli/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
getOpenCodeVersion,
|
|
5
5
|
isOpenCodeInstalled,
|
|
6
6
|
opencodeAdapter
|
|
7
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-6GQYMWWT.js";
|
|
8
8
|
import {
|
|
9
9
|
CODEX_ROLE_NAMES,
|
|
10
10
|
REQUIRED_SKILLS,
|
|
@@ -43,7 +43,7 @@ import {
|
|
|
43
43
|
installRequiredSkill,
|
|
44
44
|
listOperationHarnesses,
|
|
45
45
|
normalizeEffortSelection
|
|
46
|
-
} from "../chunk-
|
|
46
|
+
} from "../chunk-W5GCMYA3.js";
|
|
47
47
|
import {
|
|
48
48
|
ALL_AGENT_NAMES,
|
|
49
49
|
detectCurrentConfig,
|
|
@@ -53,7 +53,7 @@ import {
|
|
|
53
53
|
getExistingLiteConfigPath,
|
|
54
54
|
updateOpenCodeMainConfig,
|
|
55
55
|
writeLiteConfig
|
|
56
|
-
} from "../chunk-
|
|
56
|
+
} from "../chunk-F2K4CS5J.js";
|
|
57
57
|
|
|
58
58
|
// src/cli/index.ts
|
|
59
59
|
import { pathToFileURL } from "url";
|
|
@@ -74,8 +74,243 @@ import { existsSync } from "fs";
|
|
|
74
74
|
import { homedir } from "os";
|
|
75
75
|
import { cwd } from "process";
|
|
76
76
|
|
|
77
|
-
// src/cli/
|
|
77
|
+
// src/cli/codex-plugin-install.ts
|
|
78
78
|
import { spawnSync } from "child_process";
|
|
79
|
+
var MARKETPLACE_NAME = "thoth-agents";
|
|
80
|
+
var MARKETPLACE_SOURCE = "EremesNG/thoth-agents";
|
|
81
|
+
var PLUGIN_ID = "thoth-agents@thoth-agents";
|
|
82
|
+
var MARKETPLACE_TARGET = "codex://marketplaces/thoth-agents";
|
|
83
|
+
var PLUGIN_TARGET = "codex://plugins/thoth-agents@thoth-agents";
|
|
84
|
+
function getCodexCommand(args, options = {}) {
|
|
85
|
+
if ((options.platform ?? process.platform) !== "win32") {
|
|
86
|
+
return { command: "codex", args: [...args] };
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
command: options.commandShell ?? process.env.ComSpec ?? "cmd.exe",
|
|
90
|
+
args: ["/d", "/s", "/c", "codex.cmd", ...args]
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
function defaultCommandExecutor(command, args, options) {
|
|
94
|
+
const invocation = command === "codex" ? getCodexCommand(args) : { command, args: [...args] };
|
|
95
|
+
const result = spawnSync(invocation.command, invocation.args, {
|
|
96
|
+
cwd: options.cwd,
|
|
97
|
+
encoding: "utf8",
|
|
98
|
+
shell: false,
|
|
99
|
+
windowsHide: true
|
|
100
|
+
});
|
|
101
|
+
return {
|
|
102
|
+
exitCode: result.status ?? (result.error ? 1 : 0),
|
|
103
|
+
stdout: result.stdout ?? "",
|
|
104
|
+
stderr: result.stderr ?? result.error?.message ?? ""
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function isRecord(value) {
|
|
108
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
109
|
+
}
|
|
110
|
+
function parseRecordArray(value) {
|
|
111
|
+
return Array.isArray(value) && value.every(isRecord) ? value : null;
|
|
112
|
+
}
|
|
113
|
+
function parseManagerRecord(content) {
|
|
114
|
+
try {
|
|
115
|
+
const parsed = JSON.parse(content);
|
|
116
|
+
return isRecord(parsed) ? parsed : null;
|
|
117
|
+
} catch {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
function normalizeMarketplaceSource(value) {
|
|
122
|
+
return value.trim().replace(/^git@github\.com:/i, "").replace(/^(?:https?|ssh):\/\/(?:git@)?github\.com\//i, "").replace(/^github\.com\//i, "").replace(/\/?\.git\/?$/i, "").replace(/\/$/, "").toLowerCase();
|
|
123
|
+
}
|
|
124
|
+
function marketplaceSources(entry) {
|
|
125
|
+
const sources = [entry.repo, entry.source];
|
|
126
|
+
if (isRecord(entry.marketplaceSource)) {
|
|
127
|
+
sources.push(entry.marketplaceSource.repo, entry.marketplaceSource.source);
|
|
128
|
+
}
|
|
129
|
+
return sources.filter(
|
|
130
|
+
(source) => typeof source === "string"
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
function isCanonicalMarketplace(entry) {
|
|
134
|
+
if (entry.name !== MARKETPLACE_NAME) return false;
|
|
135
|
+
const canonical = MARKETPLACE_SOURCE.toLowerCase();
|
|
136
|
+
return marketplaceSources(entry).some(
|
|
137
|
+
(source) => normalizeMarketplaceSource(source) === canonical
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
function inspectCodexManager(executor, cwd2) {
|
|
141
|
+
const marketplaceResult = executor(
|
|
142
|
+
"codex",
|
|
143
|
+
["plugin", "marketplace", "list", "--json"],
|
|
144
|
+
{ cwd: cwd2 }
|
|
145
|
+
);
|
|
146
|
+
const pluginResult = executor(
|
|
147
|
+
"codex",
|
|
148
|
+
["plugin", "list", "--available", "--json"],
|
|
149
|
+
{ cwd: cwd2 }
|
|
150
|
+
);
|
|
151
|
+
const diagnostics = [];
|
|
152
|
+
if (marketplaceResult.exitCode !== 0 || pluginResult.exitCode !== 0) {
|
|
153
|
+
diagnostics.push(
|
|
154
|
+
"Codex native plugin state could not be inspected; no manager mutation will be attempted."
|
|
155
|
+
);
|
|
156
|
+
return {
|
|
157
|
+
ready: false,
|
|
158
|
+
marketplace: "unknown",
|
|
159
|
+
plugin: "unknown",
|
|
160
|
+
diagnostics
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
const marketplaceRecord = parseManagerRecord(marketplaceResult.stdout);
|
|
164
|
+
const pluginRecord = parseManagerRecord(pluginResult.stdout);
|
|
165
|
+
const marketplaces = marketplaceRecord ? parseRecordArray(marketplaceRecord.marketplaces) : null;
|
|
166
|
+
const installedPlugins = pluginRecord ? parseRecordArray(pluginRecord.installed) : null;
|
|
167
|
+
if (!marketplaces || !installedPlugins) {
|
|
168
|
+
diagnostics.push(
|
|
169
|
+
"Codex returned unparseable plugin manager JSON; no manager mutation will be attempted."
|
|
170
|
+
);
|
|
171
|
+
return {
|
|
172
|
+
ready: false,
|
|
173
|
+
marketplace: "unknown",
|
|
174
|
+
plugin: "unknown",
|
|
175
|
+
diagnostics
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
const namedMarketplaces = marketplaces.filter(
|
|
179
|
+
(entry) => entry.name === MARKETPLACE_NAME
|
|
180
|
+
);
|
|
181
|
+
let marketplace = "absent";
|
|
182
|
+
if (namedMarketplaces.length > 0) {
|
|
183
|
+
marketplace = namedMarketplaces.every(isCanonicalMarketplace) ? "installed" : "conflict";
|
|
184
|
+
}
|
|
185
|
+
if (marketplace === "conflict") {
|
|
186
|
+
diagnostics.push(
|
|
187
|
+
"A Codex marketplace named thoth-agents is registered from a different source; resolve it through Codex before retrying."
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
const matchingPlugins = installedPlugins.filter(
|
|
191
|
+
(entry) => entry.pluginId === PLUGIN_ID
|
|
192
|
+
);
|
|
193
|
+
let plugin = "absent";
|
|
194
|
+
if (matchingPlugins.some((entry) => entry.enabled === true)) {
|
|
195
|
+
plugin = "installed";
|
|
196
|
+
} else if (matchingPlugins.length > 0) {
|
|
197
|
+
plugin = "disabled";
|
|
198
|
+
}
|
|
199
|
+
return {
|
|
200
|
+
ready: marketplace !== "conflict",
|
|
201
|
+
marketplace,
|
|
202
|
+
plugin,
|
|
203
|
+
diagnostics
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
function commandItem(action, projectRoot) {
|
|
207
|
+
if (action === "register-marketplace") {
|
|
208
|
+
return {
|
|
209
|
+
action,
|
|
210
|
+
targetPath: MARKETPLACE_TARGET,
|
|
211
|
+
description: "Register the package-owned thoth-agents Codex marketplace.",
|
|
212
|
+
command: {
|
|
213
|
+
executable: "codex",
|
|
214
|
+
args: ["plugin", "marketplace", "add", MARKETPLACE_SOURCE, "--json"],
|
|
215
|
+
cwd: projectRoot
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
return {
|
|
220
|
+
action,
|
|
221
|
+
targetPath: PLUGIN_TARGET,
|
|
222
|
+
description: "Install and enable the thoth-agents Codex plugin from its native marketplace.",
|
|
223
|
+
command: {
|
|
224
|
+
executable: "codex",
|
|
225
|
+
args: ["plugin", "add", PLUGIN_ID, "--json"],
|
|
226
|
+
cwd: projectRoot
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
function buildCodexPluginSetupPlan(config) {
|
|
231
|
+
const commandExecutor = config.commandExecutor ?? defaultCommandExecutor;
|
|
232
|
+
const inspection = inspectCodexManager(commandExecutor, config.projectRoot);
|
|
233
|
+
const items = [];
|
|
234
|
+
if (inspection.ready) {
|
|
235
|
+
if (inspection.marketplace === "absent") {
|
|
236
|
+
items.push(commandItem("register-marketplace", config.projectRoot));
|
|
237
|
+
}
|
|
238
|
+
if (inspection.plugin === "absent" || inspection.plugin === "disabled") {
|
|
239
|
+
items.push(commandItem("install-plugin", config.projectRoot));
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return {
|
|
243
|
+
dryRun: config.dryRun === true,
|
|
244
|
+
items,
|
|
245
|
+
ready: inspection.ready,
|
|
246
|
+
projectRoot: config.projectRoot,
|
|
247
|
+
commandExecutor,
|
|
248
|
+
diagnostics: [
|
|
249
|
+
...inspection.diagnostics,
|
|
250
|
+
"Codex installs thoth-agents from EremesNG/thoth-agents through its native plugin manager and owns the cached plugin files.",
|
|
251
|
+
"Restart Codex after installation; use /plugins to inspect marketplace and plugin state."
|
|
252
|
+
]
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
function uniqueMessages(messages) {
|
|
256
|
+
return [...new Set(messages)];
|
|
257
|
+
}
|
|
258
|
+
function boundedCommandFailure(item, result) {
|
|
259
|
+
const detail = result.stderr.trim().replace(/\s+/g, " ").slice(0, 240);
|
|
260
|
+
return `${item.description} Codex exited with code ${result.exitCode}${detail ? `: ${detail}` : "."}`;
|
|
261
|
+
}
|
|
262
|
+
function applyCodexPluginSetup(plan) {
|
|
263
|
+
const changed = [];
|
|
264
|
+
const diagnostics = uniqueMessages(plan.diagnostics);
|
|
265
|
+
if (!plan.ready) {
|
|
266
|
+
return {
|
|
267
|
+
success: false,
|
|
268
|
+
changed,
|
|
269
|
+
diagnostics,
|
|
270
|
+
error: "Codex native plugin manager state is not safe to mutate."
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
if (plan.dryRun) return { success: true, changed, diagnostics };
|
|
274
|
+
for (const item of plan.items) {
|
|
275
|
+
const result = plan.commandExecutor(
|
|
276
|
+
item.command.executable,
|
|
277
|
+
item.command.args,
|
|
278
|
+
{ cwd: item.command.cwd }
|
|
279
|
+
);
|
|
280
|
+
if (result.exitCode !== 0) {
|
|
281
|
+
return {
|
|
282
|
+
success: false,
|
|
283
|
+
changed,
|
|
284
|
+
diagnostics,
|
|
285
|
+
error: boundedCommandFailure(item, result)
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
changed.push(item.targetPath);
|
|
289
|
+
}
|
|
290
|
+
const inspection = inspectCodexManager(
|
|
291
|
+
plan.commandExecutor,
|
|
292
|
+
plan.projectRoot
|
|
293
|
+
);
|
|
294
|
+
diagnostics.push(...inspection.diagnostics);
|
|
295
|
+
if (inspection.marketplace !== "installed" || inspection.plugin !== "installed") {
|
|
296
|
+
return {
|
|
297
|
+
success: false,
|
|
298
|
+
changed,
|
|
299
|
+
diagnostics: uniqueMessages(diagnostics),
|
|
300
|
+
error: "Codex did not verify the expected marketplace and enabled plugin after mutation."
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
return { success: true, changed, diagnostics: uniqueMessages(diagnostics) };
|
|
304
|
+
}
|
|
305
|
+
function formatCodexPluginSetupPlan(plan) {
|
|
306
|
+
const lines = plan.items.map(
|
|
307
|
+
(item) => `- ${item.action}: ${item.command.executable} ${item.command.args.join(" ")}`
|
|
308
|
+
);
|
|
309
|
+
return ["Codex plugin setup plan:", ...lines].join("\n");
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// src/cli/thoth-mem-install.ts
|
|
313
|
+
import { spawnSync as spawnSync2 } from "child_process";
|
|
79
314
|
var THOTH_MEM_SETUP_TIMEOUT_MS = 12e4;
|
|
80
315
|
var STATUS_EXIT_CODE = {
|
|
81
316
|
complete: 0,
|
|
@@ -93,17 +328,17 @@ var STEP_OUTCOMES = /* @__PURE__ */ new Set([
|
|
|
93
328
|
"failed",
|
|
94
329
|
"unavailable"
|
|
95
330
|
]);
|
|
96
|
-
function
|
|
331
|
+
function isRecord2(value) {
|
|
97
332
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
98
333
|
}
|
|
99
334
|
function isStringArray(value) {
|
|
100
335
|
return Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
101
336
|
}
|
|
102
337
|
function isSetupStep(value) {
|
|
103
|
-
return
|
|
338
|
+
return isRecord2(value) && typeof value.name === "string" && value.name.length > 0 && typeof value.outcome === "string" && STEP_OUTCOMES.has(value.outcome);
|
|
104
339
|
}
|
|
105
340
|
function isProviderSetupResult(value, expectedHarness) {
|
|
106
|
-
return
|
|
341
|
+
return isRecord2(value) && typeof value.status === "string" && SETUP_STATUSES.has(value.status) && typeof value.changed === "boolean" && value.harness === expectedHarness && value.scope === "global" && typeof value.target === "string" && value.target.length > 0 && Array.isArray(value.steps) && value.steps.every(isSetupStep) && isStringArray(value.diagnostics) && isStringArray(value.manual_actions) && (value.receipt === null || typeof value.receipt === "string");
|
|
107
342
|
}
|
|
108
343
|
function parseProviderSetupResult(stdout, expectedHarness) {
|
|
109
344
|
let value;
|
|
@@ -114,8 +349,8 @@ function parseProviderSetupResult(stdout, expectedHarness) {
|
|
|
114
349
|
}
|
|
115
350
|
return isProviderSetupResult(value, expectedHarness) ? value : void 0;
|
|
116
351
|
}
|
|
117
|
-
function
|
|
118
|
-
const result =
|
|
352
|
+
function defaultCommandExecutor2(command, args, options) {
|
|
353
|
+
const result = spawnSync2(command, [...args], {
|
|
119
354
|
cwd: options.cwd,
|
|
120
355
|
encoding: "utf8",
|
|
121
356
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -132,7 +367,7 @@ function describeError(error) {
|
|
|
132
367
|
return error instanceof Error ? error.message : String(error);
|
|
133
368
|
}
|
|
134
369
|
function isTimeoutError(error) {
|
|
135
|
-
return
|
|
370
|
+
return isRecord2(error) && error.code === "ETIMEDOUT";
|
|
136
371
|
}
|
|
137
372
|
function invalidResult(harness, command, args, exitCode, error) {
|
|
138
373
|
return {
|
|
@@ -171,7 +406,7 @@ function runThothMemSetup(options) {
|
|
|
171
406
|
options.harness,
|
|
172
407
|
options.dryRun ?? false
|
|
173
408
|
);
|
|
174
|
-
const executor = options.commandExecutor ??
|
|
409
|
+
const executor = options.commandExecutor ?? defaultCommandExecutor2;
|
|
175
410
|
let commandResult;
|
|
176
411
|
try {
|
|
177
412
|
commandResult = executor(command, args, {
|
|
@@ -466,11 +701,23 @@ function createInstallConfig(args) {
|
|
|
466
701
|
async function install(args, dependencies = {}) {
|
|
467
702
|
const config = createInstallConfig(args);
|
|
468
703
|
if (config.agent === "codex") {
|
|
704
|
+
const projectRoot = cwd();
|
|
705
|
+
const pluginPlan = buildCodexPluginSetupPlan({
|
|
706
|
+
dryRun: config.dryRun,
|
|
707
|
+
projectRoot
|
|
708
|
+
});
|
|
709
|
+
console.log(formatCodexPluginSetupPlan(pluginPlan));
|
|
710
|
+
const pluginResult = applyCodexPluginSetup(pluginPlan);
|
|
711
|
+
for (const diagnostic of pluginResult.diagnostics) printInfo(diagnostic);
|
|
712
|
+
if (!pluginResult.success) {
|
|
713
|
+
printError(`Codex plugin install failed: ${pluginResult.error}`);
|
|
714
|
+
return 1;
|
|
715
|
+
}
|
|
469
716
|
const plan = buildCodexSetupPlan({
|
|
470
717
|
dryRun: config.dryRun,
|
|
471
718
|
reset: config.reset,
|
|
472
719
|
scope: "user",
|
|
473
|
-
projectRoot
|
|
720
|
+
projectRoot,
|
|
474
721
|
homeDir: homedir()
|
|
475
722
|
});
|
|
476
723
|
console.log(formatCodexSetupPlan(plan));
|
|
@@ -485,7 +732,7 @@ async function install(args, dependencies = {}) {
|
|
|
485
732
|
return 1;
|
|
486
733
|
}
|
|
487
734
|
printSuccess(
|
|
488
|
-
config.dryRun ? "Codex dry-run complete; no files written" : "Codex agent-pack setup complete"
|
|
735
|
+
config.dryRun ? "Codex dry-run complete; no files written" : "Codex plugin installed as thoth-agents@thoth-agents and agent-pack setup complete (restart Codex to activate)"
|
|
489
736
|
);
|
|
490
737
|
return 0;
|
|
491
738
|
}
|
package/dist/cli/skills.d.ts
CHANGED
|
@@ -19,7 +19,9 @@ interface InstallRequiredSkillOptions extends NpxCommandOptions {
|
|
|
19
19
|
homeDir?: string;
|
|
20
20
|
}
|
|
21
21
|
export declare const REQUIRED_SKILLS: readonly RequiredSkill[];
|
|
22
|
+
export declare function getRequiredSkillPaths(skill: RequiredSkill, harness: SkillInstallHarness, homeDir?: string): string[];
|
|
22
23
|
export declare function getRequiredSkillPath(skill: RequiredSkill, harness: SkillInstallHarness, homeDir?: string): string;
|
|
24
|
+
export declare function getInstalledRequiredSkillPath(skill: RequiredSkill, harness: SkillInstallHarness, homeDir?: string): string | undefined;
|
|
23
25
|
export declare function isRequiredSkillInstalled(skill: RequiredSkill, harness: SkillInstallHarness, options?: InstallRequiredSkillOptions): boolean;
|
|
24
26
|
export declare function getRequiredSkillInstallCommand(skill: RequiredSkill, harness: SkillInstallHarness, options?: NpxCommandOptions): NpxCommand;
|
|
25
27
|
/** Install one mandatory skill into the selected harness's global skill root. */
|
package/dist/cli/tui/index.js
CHANGED
|
@@ -2,8 +2,8 @@ import {
|
|
|
2
2
|
defaultTuiOperations,
|
|
3
3
|
effortChoicesForModel,
|
|
4
4
|
listOperationHarnesses
|
|
5
|
-
} from "../../chunk-
|
|
6
|
-
import "../../chunk-
|
|
5
|
+
} from "../../chunk-W5GCMYA3.js";
|
|
6
|
+
import "../../chunk-F2K4CS5J.js";
|
|
7
7
|
|
|
8
8
|
// src/cli/tui/index.tsx
|
|
9
9
|
import { render } from "ink";
|
|
@@ -32,7 +32,7 @@ export declare const AGENT_ROLES: readonly [{
|
|
|
32
32
|
readonly scope: "requirements, SDD coordination, routing, bounded direct work, decisions, and synthesis";
|
|
33
33
|
readonly responsibility: "Keep the task coherent, own sequential specification, planning, task, convergence, and archive coordination, act directly when work is clear and bounded, and delegate only for net gain.";
|
|
34
34
|
readonly toolGovernance: ["may inspect and edit bounded direct work, but every verification is delegated to oracle", "loads the matching thoth-sdd phase contract on demand instead of carrying every phase protocol in its prompt", "owns governed coordination writes under openspec/ and uses append-only tasks.md updates during convergence", "delegates independent or specialist work only when it produces a net gain", "keeps requirements, decisions, and final synthesis in the root thread"];
|
|
35
|
-
readonly verification: ["delegates
|
|
35
|
+
readonly verification: ["delegates selected plan-review and every verify phase to oracle; plan review stays optional and final verification stays mandatory", "consolidates summarized evidence returned by child agents"];
|
|
36
36
|
}, {
|
|
37
37
|
readonly name: "explorer";
|
|
38
38
|
readonly mode: "read-only";
|
|
@@ -56,8 +56,8 @@ export declare const AGENT_ROLES: readonly [{
|
|
|
56
56
|
readonly mode: "read-only";
|
|
57
57
|
readonly dispatch: "synchronous-task-only";
|
|
58
58
|
readonly canMutateWorkspace: false;
|
|
59
|
-
readonly scope: "diagnosis, architecture,
|
|
60
|
-
readonly responsibility: "Independently
|
|
59
|
+
readonly scope: "diagnosis, architecture, optional plan review, and independent verification";
|
|
60
|
+
readonly responsibility: "Independently review plans when the user requests it and perform every implementation verification, exposing correctness risks and judging whether results satisfy their contracts.";
|
|
61
61
|
readonly toolGovernance: ["performs read-only analysis and independent review and is never the implementer of the work it judges", "does not implement, persist artifacts, or delegate further"];
|
|
62
62
|
readonly verification: ["separates observations, risks, and recommendations"];
|
|
63
63
|
}, {
|
|
@@ -22,7 +22,7 @@ export interface SddRoutingDecision {
|
|
|
22
22
|
requiresUserInput: boolean;
|
|
23
23
|
reasons: string[];
|
|
24
24
|
}
|
|
25
|
-
export type SddPhaseId = 'explore' | 'specify' | 'clarify' | 'plan' | 'checklist' | 'tasks' | '
|
|
25
|
+
export type SddPhaseId = 'explore' | 'specify' | 'clarify' | 'plan' | 'checklist' | 'tasks' | 'plan-review' | 'implement' | 'verify' | 'converge' | 'archive';
|
|
26
26
|
export type SddPhaseActivation = 'required' | 'conditional';
|
|
27
27
|
export interface SddPhaseContract {
|
|
28
28
|
id: SddPhaseId;
|
|
@@ -58,7 +58,7 @@ export interface SddPhaseDispatchInput {
|
|
|
58
58
|
verification?: string[];
|
|
59
59
|
memory: MemoryDispatchContract;
|
|
60
60
|
}
|
|
61
|
-
export type SddArtifactId = 'spec' | 'plan' | 'tasks' | 'requirements-checklist' | 'research' | 'data-model' | 'contracts' | 'quickstart' | 'verify-report' | 'archive-report';
|
|
61
|
+
export type SddArtifactId = 'spec' | 'plan' | 'tasks' | 'requirements-checklist' | 'research' | 'data-model' | 'contracts' | 'quickstart' | 'plan-review' | 'verify-report' | 'archive-report';
|
|
62
62
|
export interface SddArtifactContract {
|
|
63
63
|
id: SddArtifactId;
|
|
64
64
|
path: string;
|
|
@@ -151,23 +151,24 @@ export declare const SDD_PHASES: readonly [{
|
|
|
151
151
|
readonly eligibleAgentRoles: ["orchestrator"];
|
|
152
152
|
readonly reason: "Produce dependency-ordered implementation slices with verification.";
|
|
153
153
|
}, {
|
|
154
|
-
readonly id: "
|
|
154
|
+
readonly id: "plan-review";
|
|
155
155
|
readonly order: 6;
|
|
156
|
-
readonly availableFor: ["full"];
|
|
157
|
-
readonly requiredFor: [
|
|
158
|
-
readonly activation: "
|
|
159
|
-
readonly prerequisites: ["
|
|
160
|
-
readonly producesArtifact:
|
|
156
|
+
readonly availableFor: ["accelerated", "full"];
|
|
157
|
+
readonly requiredFor: [];
|
|
158
|
+
readonly activation: "conditional";
|
|
159
|
+
readonly prerequisites: ["tasks"];
|
|
160
|
+
readonly producesArtifact: true;
|
|
161
161
|
readonly defaultAgentRole: "oracle";
|
|
162
162
|
readonly eligibleAgentRoles: ["oracle"];
|
|
163
|
-
readonly reason: "
|
|
163
|
+
readonly reason: "Offer independent blocker-only plan review when the user selects it after planning passes ready.";
|
|
164
|
+
readonly condition: "Activate only after ready when the user chooses Review plan with Oracle (Recommended).";
|
|
164
165
|
}, {
|
|
165
166
|
readonly id: "implement";
|
|
166
167
|
readonly order: 7;
|
|
167
168
|
readonly availableFor: ["direct", "accelerated", "full"];
|
|
168
169
|
readonly requiredFor: ["direct", "accelerated", "full"];
|
|
169
170
|
readonly activation: "required";
|
|
170
|
-
readonly prerequisites: ["tasks"
|
|
171
|
+
readonly prerequisites: ["tasks"];
|
|
171
172
|
readonly producesArtifact: false;
|
|
172
173
|
readonly defaultAgentRole: "orchestrator";
|
|
173
174
|
readonly eligibleAgentRoles: ["orchestrator", "designer", "quick", "deep"];
|
|
@@ -255,6 +256,12 @@ export declare const SDD_ARTIFACT_GRAPH: readonly [{
|
|
|
255
256
|
readonly producedBy: "plan";
|
|
256
257
|
readonly consumes: ["spec", "plan"];
|
|
257
258
|
readonly requiredFor: [];
|
|
259
|
+
}, {
|
|
260
|
+
readonly id: "plan-review";
|
|
261
|
+
readonly path: "plan-review.md";
|
|
262
|
+
readonly producedBy: "plan-review";
|
|
263
|
+
readonly consumes: ["spec", "plan", "tasks"];
|
|
264
|
+
readonly requiredFor: [];
|
|
258
265
|
}, {
|
|
259
266
|
readonly id: "verify-report";
|
|
260
267
|
readonly path: "verify-report.md";
|
|
@@ -280,14 +287,14 @@ export declare const SDD_ROUTE_EXECUTION_POLICIES: readonly [{
|
|
|
280
287
|
readonly planningMode: "fast-forward";
|
|
281
288
|
readonly validationGates: ["specify", "ready", "closeout"];
|
|
282
289
|
readonly optionalArtifactsByDefault: false;
|
|
283
|
-
readonly routineUserPauses:
|
|
290
|
+
readonly routineUserPauses: true;
|
|
284
291
|
readonly artifactRevisionPolicy: "revalidate-affected-downstream";
|
|
285
292
|
}, {
|
|
286
293
|
readonly route: "full";
|
|
287
294
|
readonly planningMode: "gated";
|
|
288
295
|
readonly validationGates: ["specify", "plan", "tasks", "ready", "closeout"];
|
|
289
296
|
readonly optionalArtifactsByDefault: false;
|
|
290
|
-
readonly routineUserPauses:
|
|
297
|
+
readonly routineUserPauses: true;
|
|
291
298
|
readonly artifactRevisionPolicy: "revalidate-affected-downstream";
|
|
292
299
|
}];
|
|
293
300
|
export declare const SDD_PHASE_PROTOCOLS: readonly [{
|
|
@@ -349,17 +356,17 @@ export declare const SDD_PHASE_PROTOCOLS: readonly [{
|
|
|
349
356
|
readonly outputSchema: ["tasks.md path", "requirement coverage", "dependency order"];
|
|
350
357
|
readonly doneWhen: ["Every FR and buildable SC has executable task coverage and every task has a verification step."];
|
|
351
358
|
readonly blockingConditions: ["A task requires an unresolved requirement, architecture choice, or hidden prerequisite."];
|
|
352
|
-
readonly handoff: ["
|
|
353
|
-
}, {
|
|
354
|
-
readonly id: "
|
|
355
|
-
readonly objective: "Perform read-only
|
|
356
|
-
readonly requiredInputs: ["spec.md", "plan.md", "tasks.md", "Project constitution"];
|
|
357
|
-
readonly instructions: ["
|
|
358
|
-
readonly allowedWrites: ["None;
|
|
359
|
-
readonly outputSchema: ["findings
|
|
360
|
-
readonly doneWhen: ["
|
|
361
|
-
readonly blockingConditions: ["
|
|
362
|
-
readonly handoff: ["On
|
|
359
|
+
readonly handoff: ["After ready, pass spec.md, plan.md, tasks.md, dependencies, and verification commands to the user-selected plan-review path or implement."];
|
|
360
|
+
}, {
|
|
361
|
+
readonly id: "plan-review";
|
|
362
|
+
readonly objective: "Perform the user-selected read-only blocker review before Accelerated or Full implementation.";
|
|
363
|
+
readonly requiredInputs: ["spec.md", "plan.md", "tasks.md", "Optional active requirements checklist", "Project constitution", "Explicit user choice to review after the ready gate"];
|
|
364
|
+
readonly instructions: ["Load the bundled plan-reviewer skill and review executability, completeness, correctness, and coherence without redesigning the plan.", "Require task coverage for every FR and buildable SC; assess outcome SC as measurable verification targets without manufacturing implementation tasks.", "Return exact [OKAY] or [REJECT] semantics, default to [OKAY], and report at most three true blockers with the smallest fixes.", "Provide the reviewed artifact set so root can persist plan-review.md with SHA-256 freshness evidence; Oracle never writes it.", "Keep plan-review approval separate from implementation confirmation and mandatory final verify."];
|
|
365
|
+
readonly allowedWrites: ["None; Oracle is read-only. Root persists plan-review.md when review runs."];
|
|
366
|
+
readonly outputSchema: ["status: [OKAY] or [REJECT]", "zero to three blocker findings with smallest fixes", "non-blocking cautions", "requirement coverage percentage", "constitution alignment", "reviewed artifact freshness manifest input"];
|
|
367
|
+
readonly doneWhen: ["Oracle has returned an exact status and every true blocker has a concrete remediation anchor."];
|
|
368
|
+
readonly blockingConditions: ["[REJECT] blocks the review path until root repairs planning blockers, the user explicitly proceeds without review, or an explicit override is recorded."];
|
|
369
|
+
readonly handoff: ["On [OKAY], root persists review evidence, presents the approved-plan overview, and asks whether to implement or stop.", "A plan-review result never satisfies mandatory final verify."];
|
|
363
370
|
}, {
|
|
364
371
|
readonly id: "implement";
|
|
365
372
|
readonly objective: "Execute the accepted task slice with one writer and focused verification.";
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
renderOpenCodeAgentConfigs,
|
|
4
4
|
spawn,
|
|
5
5
|
spawnSync
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-6GQYMWWT.js";
|
|
7
7
|
import {
|
|
8
8
|
POLL_INTERVAL_BACKGROUND_MS,
|
|
9
9
|
context7,
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
grep_app,
|
|
13
13
|
loadPluginConfig,
|
|
14
14
|
stripJsonComments
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-F2K4CS5J.js";
|
|
16
16
|
|
|
17
17
|
// src/index.ts
|
|
18
18
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "thoth-agents",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.4",
|
|
4
4
|
"description": "Adaptive multi-harness orchestration with seven roles, runtime-autonomous Spec Kit-compatible SDD routes, and external provider boundaries.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -29,12 +29,12 @@
|
|
|
29
29
|
{
|
|
30
30
|
"path": "agents/oracle.md",
|
|
31
31
|
"kind": "agent-config",
|
|
32
|
-
"sha256": "sha256:
|
|
32
|
+
"sha256": "sha256:b5a2334cc0b52fb95281cb46fb9c2a6fc1df9f87faefe0e47838df270992bfe0"
|
|
33
33
|
},
|
|
34
34
|
{
|
|
35
35
|
"path": "agents/orchestrator.md",
|
|
36
36
|
"kind": "agent-config",
|
|
37
|
-
"sha256": "sha256:
|
|
37
|
+
"sha256": "sha256:b39b6cb996d5dcb38dc66bb83bfd7d6dacbb75d9e1de9097ce2416e64d630b9e"
|
|
38
38
|
},
|
|
39
39
|
{
|
|
40
40
|
"path": "agents/quick.md",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "thoth-agents",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.4",
|
|
4
4
|
"description": "Bundled Spec Kit-compatible SDD skills and MCP configuration; the seven-role global Codex layer requires thoth-agents CLI setup.",
|
|
5
5
|
"skills": "./skills/",
|
|
6
6
|
"mcpServers": "./codex.mcp.json"
|
package/plugin/agents/oracle.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: oracle
|
|
3
|
-
description: "Independently
|
|
3
|
+
description: "Independently review plans when the user requests it and perform every implementation verification, exposing correctness risks and judging whether results satisfy their contracts."
|
|
4
4
|
model: opus
|
|
5
5
|
disallowedTools: "Write, Edit"
|
|
6
6
|
---
|
|
@@ -12,11 +12,11 @@ You are oracle.
|
|
|
12
12
|
<mode>
|
|
13
13
|
- Mode: read-only
|
|
14
14
|
- Dispatch: synchronous Agent only
|
|
15
|
-
- Scope: diagnosis, architecture,
|
|
15
|
+
- Scope: diagnosis, architecture, optional plan review, and independent verification
|
|
16
16
|
</mode>
|
|
17
17
|
|
|
18
18
|
<responsibility>
|
|
19
|
-
Independently
|
|
19
|
+
Independently review plans when the user requests it and perform every implementation verification, exposing correctness risks and judging whether results satisfy their contracts.
|
|
20
20
|
</responsibility>
|
|
21
21
|
|
|
22
22
|
<reasoning-discipline>
|
|
@@ -30,7 +30,7 @@ Independently analyze plans and perform every implementation verification, expos
|
|
|
30
30
|
- Do not create coordination artifacts.
|
|
31
31
|
- Separate observations, risks, and recommendations.
|
|
32
32
|
- Review against stated requirements and contracts; do not invent implementation scope.
|
|
33
|
-
- For
|
|
33
|
+
- For plan-review, load the bundled plan-reviewer skill; for verify, load the matching bundled thoth-sdd reference and remain read-only.
|
|
34
34
|
- Reject self-review: the implementing root or writer cannot substitute for independent oracle judgment.
|
|
35
35
|
- Ask only when a local blocking decision cannot be resolved from the assignment and evidence.
|
|
36
36
|
</rules>
|
|
@@ -64,8 +64,8 @@ Be concise. Return distilled evidence and outcomes, not raw logs or full-file du
|
|
|
64
64
|
<role-operational-contract>
|
|
65
65
|
- Role: oracle
|
|
66
66
|
- Mode: read-only
|
|
67
|
-
- Scope: diagnosis, architecture,
|
|
68
|
-
- Responsibility: Independently
|
|
67
|
+
- Scope: diagnosis, architecture, optional plan review, and independent verification
|
|
68
|
+
- Responsibility: Independently review plans when the user requests it and perform every implementation verification, exposing correctness risks and judging whether results satisfy their contracts.
|
|
69
69
|
- Use AskUserQuestion for local blocking decisions.
|
|
70
70
|
- oracle runs as an auto-discovered Claude Code plugin subagent invoked via Agent(subagent_type: thoth-agents:oracle); plugin subagents are namespaced with the plugin name. The orchestrator is the main Claude Code session.
|
|
71
71
|
- Write and Edit are denied in frontmatter while all other inherited tools, including MCP tools, remain available.
|