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.
Files changed (33) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/README.md +34 -29
  3. package/dist/{chunk-YUCGIJPP.js → chunk-6GQYMWWT.js} +1 -1
  4. package/dist/{chunk-XO74DXBZ.js → chunk-F2K4CS5J.js} +32 -23
  5. package/dist/{chunk-NUSODNWE.js → chunk-W5GCMYA3.js} +63 -24
  6. package/dist/cli/codex-plugin-install.d.ts +51 -0
  7. package/dist/cli/index.js +260 -13
  8. package/dist/cli/skills.d.ts +2 -0
  9. package/dist/cli/tui/index.js +2 -2
  10. package/dist/harness/core/agent-pack.d.ts +3 -3
  11. package/dist/harness/core/sdd.d.ts +30 -23
  12. package/dist/index.js +2 -2
  13. package/package.json +1 -1
  14. package/plugin/.claude-plugin/.thoth-agents-plugin-assets.json +2 -2
  15. package/plugin/.claude-plugin/plugin.json +1 -1
  16. package/plugin/.codex-plugin/plugin.json +1 -1
  17. package/plugin/agents/oracle.md +6 -6
  18. package/plugin/agents/orchestrator.md +8 -7
  19. package/plugin/skills/plan-reviewer/SKILL.md +107 -0
  20. package/plugin/skills/plan-reviewer/templates/plan-review.md +65 -0
  21. package/plugin/skills/thoth-constitution/templates/constitution.md +2 -2
  22. package/plugin/skills/thoth-init/SKILL.md +1 -1
  23. package/plugin/skills/thoth-init/scripts/init.mjs +1 -0
  24. package/plugin/skills/thoth-sdd/SKILL.md +21 -15
  25. package/skills/README.md +4 -2
  26. package/skills/plan-reviewer/SKILL.md +107 -0
  27. package/skills/plan-reviewer/templates/plan-review.md +65 -0
  28. package/skills/thoth-constitution/templates/constitution.md +2 -2
  29. package/skills/thoth-init/SKILL.md +1 -1
  30. package/skills/thoth-init/scripts/init.mjs +1 -0
  31. package/skills/thoth-sdd/SKILL.md +21 -15
  32. package/plugin/skills/thoth-sdd/references/phases/analyze.md +0 -21
  33. 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-YUCGIJPP.js";
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-NUSODNWE.js";
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-XO74DXBZ.js";
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/thoth-mem-install.ts
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 isRecord(value) {
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 isRecord(value) && typeof value.name === "string" && value.name.length > 0 && typeof value.outcome === "string" && STEP_OUTCOMES.has(value.outcome);
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 isRecord(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");
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 defaultCommandExecutor(command, args, options) {
118
- const result = spawnSync(command, [...args], {
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 isRecord(error) && error.code === "ETIMEDOUT";
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 ?? defaultCommandExecutor;
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: cwd(),
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
  }
@@ -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. */
@@ -2,8 +2,8 @@ import {
2
2
  defaultTuiOperations,
3
3
  effortChoicesForModel,
4
4
  listOperationHarnesses
5
- } from "../../chunk-NUSODNWE.js";
6
- import "../../chunk-XO74DXBZ.js";
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 analyze and every verify phase to oracle, including Direct and Accelerated routes", "consolidates summarized evidence returned by child agents"];
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, analysis, and independent verification";
60
- readonly responsibility: "Independently analyze plans and perform every implementation verification, exposing correctness risks and judging whether results satisfy their contracts.";
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' | 'analyze' | 'implement' | 'verify' | 'converge' | 'archive';
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: "analyze";
154
+ readonly id: "plan-review";
155
155
  readonly order: 6;
156
- readonly availableFor: ["full"];
157
- readonly requiredFor: ["full"];
158
- readonly activation: "required";
159
- readonly prerequisites: ["specify", "plan", "tasks"];
160
- readonly producesArtifact: false;
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: "Independently check cross-artifact consistency before high-risk implementation.";
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", "analyze"];
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: false;
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: false;
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: ["Pass spec.md, plan.md, tasks.md, dependencies, and verification commands to analyze or implement."];
353
- }, {
354
- readonly id: "analyze";
355
- readonly objective: "Perform read-only cross-artifact consistency and readiness analysis before full SDD implementation.";
356
- readonly requiredInputs: ["spec.md", "plan.md", "tasks.md", "Project constitution"];
357
- readonly instructions: ["Detect contradictions, ambiguity, duplication, scope drift, orphan tasks, and uncovered requirements.", "Challenge artifact completeness, requirement correctness, and cross-artifact coherence as separate review dimensions.", "Require task coverage for every FR and buildable SC; assess outcome SC as measurable verification targets without manufacturing implementation tasks.", "Report requirement coverage as a percentage and classify findings as CRITICAL, HIGH, MEDIUM, or LOW.", "Treat constitution violations and baseline requirements with zero task coverage as blocking."];
358
- readonly allowedWrites: ["None; analysis is read-only and returns its report in-session."];
359
- readonly outputSchema: ["findings table with stable IDs and severity", "requirement coverage percentage", "constitution alignment", "readiness verdict: ready | blocked"];
360
- readonly doneWhen: ["Every high-signal cross-artifact inconsistency has a severity and remediation anchor."];
361
- readonly blockingConditions: ["Any unresolved CRITICAL finding or constitution violation blocks implementation."];
362
- readonly handoff: ["On ready, pass the reviewed artifact set and cautions to implement; on blocked, return findings to the owning coordination phase."];
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-YUCGIJPP.js";
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-XO74DXBZ.js";
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.2",
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:93b9744b95bf657d8902f0108d24904ab504249fd47308f66271978010501a13"
32
+ "sha256": "sha256:b5a2334cc0b52fb95281cb46fb9c2a6fc1df9f87faefe0e47838df270992bfe0"
33
33
  },
34
34
  {
35
35
  "path": "agents/orchestrator.md",
36
36
  "kind": "agent-config",
37
- "sha256": "sha256:bac6c6c2abda0352f785fec16debde1361d2bfbd17acdf3a75b326c6c4d0a992"
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.2",
3
+ "version": "0.3.4",
4
4
  "description": "Adaptive multi-harness agent pack with seven roles and a runtime-autonomous Spec Kit-compatible SDD bundle for Claude Code.",
5
5
  "author": {
6
6
  "name": "thoth-agents"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "thoth-agents",
3
- "version": "0.3.2",
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"
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: oracle
3
- description: "Independently analyze plans and perform every implementation verification, exposing correctness risks and judging whether results satisfy their contracts."
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, analysis, and independent verification
15
+ - Scope: diagnosis, architecture, optional plan review, and independent verification
16
16
  </mode>
17
17
 
18
18
  <responsibility>
19
- Independently analyze plans and perform every implementation verification, exposing correctness risks and judging whether results satisfy their contracts.
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 analyze or verify, load the matching bundled thoth-sdd reference and remain read-only.
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, analysis, and independent verification
68
- - Responsibility: Independently analyze plans and perform every implementation verification, exposing correctness risks and judging whether results satisfy their contracts.
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.