thoth-agents 0.9.8 → 0.9.9

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 (49) hide show
  1. package/dist/agents/prompt-dialects.d.ts +1 -0
  2. package/dist/{chunk-EDGQVTV3.js → chunk-2ER6FKVC.js} +52 -5
  3. package/dist/{chunk-V5GDCWFR.js → chunk-RN2ERZLZ.js} +1 -1
  4. package/dist/{chunk-ARUBELNT.js → chunk-RVQ6IIBR.js} +10 -4
  5. package/dist/chunk-RWQPMWEM.js +624 -0
  6. package/dist/{chunk-QQV5S3TW.js → chunk-VHQMTZ5O.js} +5 -24
  7. package/dist/cli/index.js +4 -4
  8. package/dist/cli/pi-tool-config.d.ts +0 -1
  9. package/dist/cli/tui/index.js +3 -3
  10. package/dist/harness/gate-hook-script.d.ts +2 -0
  11. package/dist/harness/writers/claude-code-plugin-package.d.ts +4 -4
  12. package/dist/harness/writers/pi-agent.d.ts +0 -1
  13. package/dist/hooks/index.d.ts +1 -0
  14. package/dist/hooks/oracle-gate-verdict/hook.d.ts +11 -0
  15. package/dist/hooks/oracle-gate-verdict/index.d.ts +1 -0
  16. package/dist/index.js +42 -3
  17. package/dist/pi-gate-verdict.d.ts +4 -0
  18. package/dist/pi.d.ts +2 -1
  19. package/dist/pi.js +101 -2
  20. package/package.json +1 -1
  21. package/pi/.thoth-agents-assets.json +5 -5
  22. package/pi/agents/thoth-designer.md +0 -1
  23. package/pi/agents/thoth-explorer.md +0 -1
  24. package/pi/agents/thoth-librarian.md +0 -1
  25. package/pi/agents/thoth-oracle.md +0 -1
  26. package/pi/agents/thoth-worker.md +0 -1
  27. package/plugin/.claude-plugin/.thoth-agents-plugin-assets.json +6 -1
  28. package/plugin/.claude-plugin/plugin.json +3 -2
  29. package/plugin/.codex-plugin/.thoth-agents-plugin-assets.json +2 -2
  30. package/plugin/.codex-plugin/plugin.json +1 -1
  31. package/plugin/agents/orchestrator.md +5 -3
  32. package/plugin/claude-hooks/hooks.json +27 -0
  33. package/plugin/codex-hooks/hooks.json +14 -0
  34. package/plugin/codex-hooks/payloads/root.md +5 -3
  35. package/plugin/skills/plan-reviewer/SKILL.md +16 -5
  36. package/plugin/skills/thoth-sdd/SKILL.md +69 -23
  37. package/plugin/skills/thoth-sdd/references/phases/verify.md +6 -2
  38. package/plugin/skills/thoth-sdd/scripts/record-digest.mjs +15 -0
  39. package/plugin/skills/thoth-sdd/scripts/validate-result.d.mts +19 -0
  40. package/plugin/skills/thoth-sdd/scripts/validate-result.mjs +110 -41
  41. package/plugin/skills/thoth-sdd/scripts/validate.mjs +7 -16
  42. package/plugin/thoth-hooks/gate-verdict.mjs +80 -0
  43. package/skills/plan-reviewer/SKILL.md +16 -5
  44. package/skills/thoth-sdd/SKILL.md +69 -23
  45. package/skills/thoth-sdd/references/phases/verify.md +6 -2
  46. package/skills/thoth-sdd/scripts/record-digest.mjs +15 -0
  47. package/skills/thoth-sdd/scripts/validate-result.d.mts +19 -0
  48. package/skills/thoth-sdd/scripts/validate-result.mjs +110 -41
  49. package/skills/thoth-sdd/scripts/validate.mjs +7 -16
package/dist/cli/index.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  getOpenCodeVersion,
5
5
  isOpenCodeInstalled,
6
6
  opencodeAdapter
7
- } from "../chunk-V5GDCWFR.js";
7
+ } from "../chunk-RN2ERZLZ.js";
8
8
  import {
9
9
  CODEX_PLUGIN_ID,
10
10
  CODEX_ROLE_NAMES,
@@ -76,11 +76,11 @@ import {
76
76
  safeAtomicWriteFileSync,
77
77
  scalarLocation,
78
78
  syncOpenCodeOwnedSkills
79
- } from "../chunk-EDGQVTV3.js";
79
+ } from "../chunk-2ER6FKVC.js";
80
80
  import "../chunk-62L3ORXN.js";
81
81
  import {
82
82
  piAdapter
83
- } from "../chunk-QQV5S3TW.js";
83
+ } from "../chunk-VHQMTZ5O.js";
84
84
  import {
85
85
  ALL_AGENT_NAMES,
86
86
  detectCurrentConfig,
@@ -91,7 +91,7 @@ import {
91
91
  resolveExecutingPackageVersion,
92
92
  updateOpenCodeMainConfig,
93
93
  writeLiteConfig
94
- } from "../chunk-ARUBELNT.js";
94
+ } from "../chunk-RVQ6IIBR.js";
95
95
 
96
96
  // src/cli/index.ts
97
97
  import { pathToFileURL } from "url";
@@ -24,7 +24,6 @@ export interface PiToolSaveResult {
24
24
  export interface PiSpecialistToolOverrides {
25
25
  tools?: string[];
26
26
  disallowedTools?: string[];
27
- subagentMode?: 'task' | 'background';
28
27
  }
29
28
  export declare function validatePiSpecialistTools(tools: readonly string[]): void;
30
29
  export declare function readPiSpecialistToolOverrides(content: string): PiSpecialistToolOverrides;
@@ -2,10 +2,10 @@ import {
2
2
  defaultTuiOperations,
3
3
  effortChoicesForModel,
4
4
  listOperationHarnesses
5
- } from "../../chunk-EDGQVTV3.js";
5
+ } from "../../chunk-2ER6FKVC.js";
6
6
  import "../../chunk-62L3ORXN.js";
7
- import "../../chunk-QQV5S3TW.js";
8
- import "../../chunk-ARUBELNT.js";
7
+ import "../../chunk-VHQMTZ5O.js";
8
+ import "../../chunk-RVQ6IIBR.js";
9
9
 
10
10
  // src/cli/tui/index.tsx
11
11
  import { render } from "ink";
@@ -0,0 +1,2 @@
1
+ /** Standalone ESM runtime shared by the explicitly declared Claude and Codex hooks. */
2
+ export declare function renderGateHookScript(): string;
@@ -1,5 +1,5 @@
1
1
  import type { HarnessArtifact, HarnessDiagnostic } from '../types';
2
- export declare const CLAUDE_PLUGIN_MANIFEST_FIELDS: readonly ["name", "version", "description", "author"];
2
+ export declare const CLAUDE_PLUGIN_MANIFEST_FIELDS: readonly ["name", "version", "description", "author", "hooks"];
3
3
  export interface ClaudeCodePluginAuthor {
4
4
  name?: string;
5
5
  email?: string;
@@ -10,13 +10,13 @@ export interface ClaudeCodePluginManifest {
10
10
  version: string;
11
11
  description: string;
12
12
  author?: ClaudeCodePluginAuthor | string;
13
+ hooks?: string;
13
14
  }
14
15
  export interface ClaudeCodePluginPackageInput {
15
16
  manifest: ClaudeCodePluginManifest;
16
17
  /**
17
- * Already-rendered plugin component artifacts (subagents, `.mcp.json`,
18
- * `hooks/`, skills). Auto-discovered by Claude Code, so the manifest does not
19
- * reference them; the writer records their provenance.
18
+ * Already-rendered plugin components. Default paths are auto-discovered;
19
+ * custom hook paths are referenced by the manifest. The writer records provenance.
20
20
  */
21
21
  componentArtifacts: HarnessArtifact[];
22
22
  }
@@ -12,7 +12,6 @@ export interface PiAgentDefinitionInput {
12
12
  model?: string;
13
13
  effort?: string;
14
14
  skills?: readonly string[];
15
- subagentMode: 'task' | 'background';
16
15
  }
17
16
  export declare function getPiSpecialistDefaultTools(role: PiSpecialistRole): string[];
18
17
  export declare function renderPiAgentDefinition(input: PiAgentDefinitionInput): string;
@@ -3,3 +3,4 @@ export { createAutoUpdateCheckerHook } from './auto-update-checker';
3
3
  export { createDelegateTaskRetryHook } from './delegate-task-retry';
4
4
  export { ForegroundFallbackManager, isRateLimitError, } from './foreground-fallback';
5
5
  export { createJsonErrorRecoveryHook } from './json-error-recovery';
6
+ export { createOracleGateVerdictHook } from './oracle-gate-verdict';
@@ -0,0 +1,11 @@
1
+ import type { PluginInput } from '@opencode-ai/plugin';
2
+ export declare function createOracleGateVerdictHook(ctx: PluginInput): {
3
+ 'tool.execute.after': (input: {
4
+ tool: string;
5
+ args?: {
6
+ subagent_type?: unknown;
7
+ };
8
+ }, output: {
9
+ output: unknown;
10
+ }) => Promise<void>;
11
+ };
@@ -0,0 +1 @@
1
+ export { createOracleGateVerdictHook } from './hook';
package/dist/index.js CHANGED
@@ -1,9 +1,13 @@
1
+ import {
2
+ formatGateVerdict,
3
+ summarizeGateResult
4
+ } from "./chunk-RWQPMWEM.js";
1
5
  import {
2
6
  createAgents,
3
7
  renderOpenCodeAgentConfigs,
4
8
  spawn,
5
9
  spawnSync
6
- } from "./chunk-V5GDCWFR.js";
10
+ } from "./chunk-RN2ERZLZ.js";
7
11
  import {
8
12
  context7,
9
13
  exa,
@@ -11,10 +15,11 @@ import {
11
15
  } from "./chunk-62L3ORXN.js";
12
16
  import {
13
17
  POLL_INTERVAL_BACKGROUND_MS,
18
+ getAgentRole,
14
19
  getOpenCodeConfigPaths,
15
20
  loadPluginConfig,
16
21
  stripJsonComments
17
- } from "./chunk-ARUBELNT.js";
22
+ } from "./chunk-RVQ6IIBR.js";
18
23
 
19
24
  // src/index.ts
20
25
  import { fileURLToPath as fileURLToPath3 } from "url";
@@ -757,6 +762,38 @@ ${JSON_ERROR_REMINDER}`;
757
762
  };
758
763
  }
759
764
 
765
+ // src/hooks/oracle-gate-verdict/hook.ts
766
+ var ORACLE_AGENT = getAgentRole("oracle").name;
767
+ function createOracleGateVerdictHook(ctx) {
768
+ return {
769
+ "tool.execute.after": async (input, output) => {
770
+ if (input.tool.toLowerCase() !== "task") return;
771
+ if (input.args?.subagent_type !== ORACLE_AGENT) return;
772
+ if (typeof output.output !== "string") return;
773
+ const text = output.output;
774
+ if (!text.includes("```thoth-result")) return;
775
+ const opening = "<task_result>";
776
+ const closing = "</task_result>";
777
+ const start = text.indexOf(opening);
778
+ const end = text.lastIndexOf(closing);
779
+ const wrapped = start !== -1 && end >= start + opening.length;
780
+ const child = wrapped ? text.slice(start + opening.length, end) : text;
781
+ const summary = {
782
+ ...summarizeGateResult(child, { cwd: ctx.directory }),
783
+ agent: ORACLE_AGENT
784
+ };
785
+ const verdict = formatGateVerdict(summary);
786
+ if (wrapped && text.slice(end + closing.length).endsWith(`
787
+
788
+ ${verdict}`))
789
+ return;
790
+ output.output += `
791
+
792
+ ${verdict}`;
793
+ }
794
+ };
795
+ }
796
+
760
797
  // src/mcp/index.ts
761
798
  function createAllBuiltinMcps() {
762
799
  return {
@@ -3494,6 +3531,7 @@ var ThothAgents = async (ctx, _options) => {
3494
3531
  });
3495
3532
  const delegateTaskRetryHook = createDelegateTaskRetryHook(ctx);
3496
3533
  const jsonErrorRecoveryHook = createJsonErrorRecoveryHook(ctx);
3534
+ const oracleGateVerdictHook = createOracleGateVerdictHook(ctx);
3497
3535
  const foregroundFallback = new ForegroundFallbackManager(
3498
3536
  client,
3499
3537
  runtimeChains,
@@ -3599,7 +3637,7 @@ var ThothAgents = async (ctx, _options) => {
3599
3637
  input.event
3600
3638
  );
3601
3639
  },
3602
- // Post-tool hooks: retry guidance for delegation and JSON errors.
3640
+ // Post-tool hooks: delegation retry, JSON recovery, then Oracle gate verdicts.
3603
3641
  "tool.execute.after": async (input, output) => {
3604
3642
  await delegateTaskRetryHook["tool.execute.after"](
3605
3643
  input,
@@ -3609,6 +3647,7 @@ var ThothAgents = async (ctx, _options) => {
3609
3647
  input,
3610
3648
  output
3611
3649
  );
3650
+ await oracleGateVerdictHook["tool.execute.after"](input, output);
3612
3651
  }
3613
3652
  };
3614
3653
  };
@@ -0,0 +1,4 @@
1
+ export declare function withPiContextGateVerdicts(event: Record<string, unknown>, cwd: string): {
2
+ messages: unknown[];
3
+ } | undefined;
4
+ export declare function withPiToolGateVerdicts(event: Record<string, unknown>, cwd: string): Record<string, unknown> | undefined;
package/dist/pi.d.ts CHANGED
@@ -1,11 +1,12 @@
1
1
  type PiHandler = (event: Record<string, unknown>, context?: {
2
+ cwd?: string;
2
3
  isIdle?(): boolean;
3
4
  ui?: {
4
5
  notify(message: string, type?: 'info' | 'warning' | 'error'): void;
5
6
  };
6
7
  }) => unknown;
7
8
  export interface PiExtensionApi {
8
- on(event: 'input' | 'before_agent_start' | 'session_start', handler: PiHandler): void;
9
+ on(event: 'input' | 'before_agent_start' | 'session_start' | 'tool_result' | 'context', handler: PiHandler): void;
9
10
  registerCommand?(name: string, command: {
10
11
  description: string;
11
12
  handler(args: string | undefined, context: unknown): unknown;
package/dist/pi.js CHANGED
@@ -1,18 +1,109 @@
1
+ import {
2
+ formatGateVerdict,
3
+ summarizeGateResult
4
+ } from "./chunk-RWQPMWEM.js";
1
5
  import {
2
6
  PI_ROOT_END,
3
7
  PI_ROOT_START,
4
8
  createPiToolsPanelAdapter,
5
9
  renderPiRootInstructions,
6
10
  syncPiSpecialists
7
- } from "./chunk-QQV5S3TW.js";
11
+ } from "./chunk-VHQMTZ5O.js";
8
12
  import {
9
13
  findPackageRoot
10
- } from "./chunk-ARUBELNT.js";
14
+ } from "./chunk-RVQ6IIBR.js";
11
15
 
12
16
  // src/pi.ts
13
17
  import { homedir } from "os";
14
18
  import { dirname, join } from "path";
15
19
  import { fileURLToPath } from "url";
20
+
21
+ // src/pi-gate-verdict.ts
22
+ var VERDICT_PREFIX = "thoth-gate-verdict ";
23
+ function asRecord(value) {
24
+ return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
25
+ }
26
+ function hasAppendedVerdict(content, verdict, blockSeparator = "") {
27
+ if (typeof content === "string") return content.endsWith(`
28
+
29
+ ${verdict}`);
30
+ if (!Array.isArray(content)) return false;
31
+ for (let index = content.length - 1; index >= 0; index--) {
32
+ const block = asRecord(content[index]);
33
+ if (block?.type !== "text" || typeof block.text !== "string" || !block.text.startsWith(`${blockSeparator}${VERDICT_PREFIX}`) || block.text.slice(blockSeparator.length).includes("\n"))
34
+ break;
35
+ if (block.text === `${blockSeparator}${verdict}`) return true;
36
+ }
37
+ return false;
38
+ }
39
+ function oracleGateVerdict(taskValue, result, cwd) {
40
+ const task = asRecord(taskValue);
41
+ if (task?.agent !== "thoth-oracle" || typeof result !== "string" || !result.includes("```thoth-result"))
42
+ return void 0;
43
+ const taskId = typeof task.id === "string" ? task.id : null;
44
+ const summary = {
45
+ ...summarizeGateResult(result, { cwd }),
46
+ agent: "thoth-oracle",
47
+ taskId
48
+ };
49
+ return formatGateVerdict(summary);
50
+ }
51
+ function withPiContextGateVerdicts(event, cwd) {
52
+ if (!Array.isArray(event.messages)) return void 0;
53
+ let changed = false;
54
+ const messages = event.messages.map((value) => {
55
+ const message = asRecord(value);
56
+ if (message?.role !== "custom" || message.customType !== "subagent-completion" || typeof message.content !== "string" && !Array.isArray(message.content))
57
+ return value;
58
+ const details = asRecord(message.details);
59
+ const task = asRecord(details?.task);
60
+ const verdict = oracleGateVerdict(
61
+ task,
62
+ details?.full_result ?? task?.result,
63
+ cwd
64
+ );
65
+ if (!verdict || hasAppendedVerdict(message.content, verdict)) return value;
66
+ changed = true;
67
+ return {
68
+ ...message,
69
+ content: typeof message.content === "string" ? `${message.content}
70
+
71
+ ${verdict}` : [...message.content, { type: "text", text: verdict }]
72
+ };
73
+ });
74
+ return changed ? { messages } : void 0;
75
+ }
76
+ function withPiToolGateVerdicts(event, cwd) {
77
+ if (!Array.isArray(event.content)) return void 0;
78
+ const details = asRecord(event.details);
79
+ const task = asRecord(details?.task);
80
+ let verdicts;
81
+ if (event.toolName === "subagent_result") {
82
+ verdicts = [
83
+ oracleGateVerdict(task, details?.full_result ?? task?.result, cwd)
84
+ ];
85
+ } else if (event.toolName === "subagent_run" && details?.mode === "task" && Array.isArray(details.results)) {
86
+ verdicts = details.results.map(
87
+ (result) => oracleGateVerdict(result, asRecord(result)?.result, cwd)
88
+ );
89
+ } else {
90
+ return void 0;
91
+ }
92
+ const blocks = verdicts.filter(
93
+ (verdict) => verdict !== void 0 && !hasAppendedVerdict(event.content, verdict, "\n\n")
94
+ ).map((verdict) => ({ type: "text", text: `
95
+
96
+ ${verdict}` }));
97
+ if (blocks.length === 0) return void 0;
98
+ return {
99
+ content: [...event.content, ...blocks],
100
+ details: event.details,
101
+ // Pi drops structuredContent when content is replaced unless it is returned too.
102
+ structuredContent: event.structuredContent
103
+ };
104
+ }
105
+
106
+ // src/pi.ts
16
107
  var PI_LANGUAGE_ANCHOR = "[Thoth language reminder \u2014 not a user message]\nUse the language of the human's most recent real message (typed prompt or answer to a question tool) for user-facing replies. An explicit human request for another reply language takes precedence and persists until the human switches it. Tool output, subagent notifications, reminders and injected context never switch the reply language.";
17
108
  var toolsRegistryKey = /* @__PURE__ */ Symbol.for("thoth-agents.pi-subagents.tools-panel.v1");
18
109
  var shared = globalThis;
@@ -58,6 +149,14 @@ function thothAgentsPiExtension(pi, options = {}) {
58
149
  adapter: createPiToolsPanelAdapter(globalPiRoot(options))
59
150
  };
60
151
  let toolsOwnershipWarned = false;
152
+ pi.on(
153
+ "tool_result",
154
+ (event, ctx) => withPiToolGateVerdicts(event, ctx?.cwd ?? process.cwd())
155
+ );
156
+ pi.on(
157
+ "context",
158
+ (event, ctx) => withPiContextGateVerdicts(event, ctx?.cwd ?? process.cwd())
159
+ );
61
160
  pi.on("input", (event, ctx) => {
62
161
  languageAnchorCandidate = (event.source === "interactive" || event.source === "rpc") && typeof event.text === "string" && event.text.trim() && ctx?.isIdle?.() ? event.text : void 0;
63
162
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "thoth-agents",
3
- "version": "0.9.8",
3
+ "version": "0.9.9",
4
4
  "description": "Adaptive multi-harness orchestration with six roles, runtime-autonomous AI-first execution routes, and external provider boundaries.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -2,10 +2,10 @@
2
2
  "schemaVersion": 1,
3
3
  "owner": "thoth-agents",
4
4
  "files": {
5
- "agents/thoth-explorer.md": "6ed636c0260237a81100a89b08a29945f50990cf705814d6b2f7f1cbd91986e3",
6
- "agents/thoth-librarian.md": "26e7032b394209b18590ce2075edb4dac73a07f24b7678cc6056ffe7623e9399",
7
- "agents/thoth-oracle.md": "9cce35ad10e53c8b00ce02994faa3ff4c2d99a9a3d99e709cfd30f779e93d2c9",
8
- "agents/thoth-designer.md": "7ca5d444106c62f3921f132d3ef5a5d454e1cbce136d89f9ba4829404d4c4373",
9
- "agents/thoth-worker.md": "7e771d23ab1c42b1583ed16ce0bc2d02f2f0a353fbb53a91e3bd2d47ad94c76d"
5
+ "agents/thoth-explorer.md": "961a1be9c1a387a582374e4ed23302a1eec228c80c9e8f8f70b48b822781eb8b",
6
+ "agents/thoth-librarian.md": "26eb9468c5fbf07ea8231c44831ba5aa8cba96081d0e432673ba6e42d3005544",
7
+ "agents/thoth-oracle.md": "49584f245a2ae1ba0fff56541215c4736393fa8cec3bcf58a4b3d737dc2b6c09",
8
+ "agents/thoth-designer.md": "78e26b5c7c8b0fdea00e1824e2ffaa193e304c6d7b58c534ecaa4378e13b590d",
9
+ "agents/thoth-worker.md": "1aa1f7b5fd29eda4a81d175a3286047cdf8369022a517be4e39c513933418f2a"
10
10
  }
11
11
  }
@@ -4,7 +4,6 @@ description: "Own user-facing implementation choices and visual quality for UI w
4
4
  tools: "read, bash, edit, write, grep, find, ls, mem_recall, mem_get"
5
5
  model: "openai-codex/gpt-6-luna"
6
6
  effort: "max"
7
- subagent_mode: "background"
8
7
  managed-by: thoth-agents
9
8
  ---
10
9
 
@@ -4,7 +4,6 @@ description: "Resolve broad or uncertain repository questions and return distill
4
4
  tools: "read, bash, grep, find, ls, mem_recall, mem_get, codemode"
5
5
  model: "openai-codex/gpt-6-luna"
6
6
  effort: "max"
7
- subagent_mode: "background"
8
7
  managed-by: thoth-agents
9
8
  ---
10
9
 
@@ -4,7 +4,6 @@ description: "Gather current authoritative evidence and separate documented fact
4
4
  tools: "read, bash, grep, find, ls, mem_recall, mem_get, codemode, resolve-library-id, query-docs, mcp, web_search, fetch_content, get_search_content, source_check"
5
5
  model: "openai-codex/gpt-6-luna"
6
6
  effort: "max"
7
- subagent_mode: "background"
8
7
  managed-by: thoth-agents
9
8
  ---
10
9
 
@@ -5,7 +5,6 @@ tools: "read, bash, grep, find, ls, mem_recall, mem_get"
5
5
  disallowed_tools: "ask_orchestrator"
6
6
  model: "openai-codex/gpt-6.1-sol"
7
7
  effort: "xhigh"
8
- subagent_mode: "background"
9
8
  managed-by: thoth-agents
10
9
  ---
11
10
 
@@ -4,7 +4,6 @@ description: "Handle bounded nonvisual implementation with full local context, i
4
4
  tools: "read, bash, edit, write, grep, find, ls, mem_recall, mem_get"
5
5
  model: "openai-codex/gpt-6-luna"
6
6
  effort: "max"
7
- subagent_mode: "background"
8
7
  managed-by: thoth-agents
9
8
  ---
10
9
 
@@ -29,13 +29,18 @@
29
29
  {
30
30
  "path": "agents/orchestrator.md",
31
31
  "kind": "agent-config",
32
- "sha256": "sha256:d556386592670e605d2bd748104092571241fc68f0cd19cd7ef01eef11ff1a88"
32
+ "sha256": "sha256:3416fa6da73974241b6c40d1d6d15a6f09fa5b20cdb1e9e00cf90b0eab9b9f47"
33
33
  },
34
34
  {
35
35
  "path": "agents/worker.md",
36
36
  "kind": "agent-config",
37
37
  "sha256": "sha256:4a569341d43cb4d10d317aee009429a6baf71e7ec248259e93847b59187f3764"
38
38
  },
39
+ {
40
+ "path": "claude-hooks/hooks.json",
41
+ "kind": "hook-config",
42
+ "sha256": "sha256:6293aeb237f98e0827f6eed9209554a8ea8a3074643075ee75ef7b71f9c6fcd1"
43
+ },
39
44
  {
40
45
  "path": "settings.json",
41
46
  "kind": "harness-config",
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "thoth-agents",
3
- "version": "0.9.8",
3
+ "version": "0.9.9",
4
4
  "description": "Adaptive multi-harness agent pack with six roles and proportional SDD governance for Claude Code.",
5
5
  "author": {
6
6
  "name": "thoth-agents"
7
- }
7
+ },
8
+ "hooks": "./claude-hooks/hooks.json"
8
9
  }
@@ -11,7 +11,7 @@
11
11
  "field": "hooks",
12
12
  "path": ".codex-plugin/codex-hooks/hooks.json",
13
13
  "reference": "./codex-hooks/hooks.json",
14
- "sha256": "sha256:b2949fe8110fdc7552bc09788d4b0b0543c9276f8fb90f155b5e974da91b8ece"
14
+ "sha256": "sha256:4f739213d552b50e9b64a6e17bdce2b2628f848f33f736c24798145751475392"
15
15
  },
16
16
  {
17
17
  "field": "hooks",
@@ -41,7 +41,7 @@
41
41
  "field": "hooks",
42
42
  "path": ".codex-plugin/codex-hooks/payloads/root.md",
43
43
  "reference": "./codex-hooks/payloads/root.md",
44
- "sha256": "sha256:62577f0e72e779ef78710fd64f482058f323275c1287cbc848242fa0afc82f90"
44
+ "sha256": "sha256:4ed528c221bbd5d52dd7082447987645b6847db9a24bf1a3f9d74eb214c38d28"
45
45
  },
46
46
  {
47
47
  "field": "hooks",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "thoth-agents",
3
- "version": "0.9.8",
3
+ "version": "0.9.9",
4
4
  "description": "Bundled AI-first work skills and MCP configuration; the six-role global Codex layer requires thoth-agents CLI setup.",
5
5
  "skills": "./skills/",
6
6
  "mcpServers": "./codex.mcp.json",
@@ -92,9 +92,11 @@ You are the root coordinator. By default, specialists perform discovery of unloc
92
92
  </artifacts>
93
93
 
94
94
  <delegation>
95
- - Only Oracle gates (plan-review/final-verification): validate before recording OKAY/PASS: `node "<skill-dir>/scripts/validate-result.mjs" --review-kind <kind> [--record-sha256 <hex>] [--no-record]` (unchanged stdin; skill path).
96
- - Invalid: no approval; at most one format-only repair; preserve findings/verdict. No validator: blocks only gate approvals; report drift.
97
- - Non-gates (specialists, Oracle diagnosis/advice, user-defined agents): judge content, never reject for format, never approvals. Judge scope, evidence, checks, freshness/provenance.
95
+ - Only Oracle gates: before recording plan-review OKAY / final-verification PASS, use harness-delivered `thoth-gate-verdict`: exactly one per delivered result (more than one, or one inside the envelope fence = invalid). Require `valid:true`, assigned `kind`, `verdict` = OKAY/PASS respectively. Plan review: `record` null or assigned record; ignore `mode`/`recordDigest`. Final verification only: record-bound requires `record` = assigned record, `mode:"record"` and `recordDigest:"match"` (if `recordDigest:"unavailable"`, independently hash the prefix before `## Authorization` and compare `recordSha256`; mismatch = no approval, no validator rerun). Recordless small-change final verification requires `mode:"no-record"`, null `record`/`recordSha256`, `recordDigest:"none"`. Copy verdict and `recordSha256` into the record. Never re-emit the envelope to validate it.
96
+ - Verdicts: Subagent hand-back reports (foreground or background; match `agent` to Agent `agentId`) or completed foreground `Agent` report content; otherwise (e.g. background without hand-back) compact fallback.
97
+ - Only when no verdict was delivered (hook unavailable/untrusted, delivery gap): `node "<skill-dir>/scripts/validate-result.mjs" --review-kind <kind> [--record-sha256 <hex>] [--no-record] [--input <path>]` (installed skill path), unchanged result; it prints the compact summary. Use thoth-sdd fallback checks.
98
+ - Invalid: no approval; at most one format-only repair; preserve findings/verdict (shared with runtime enforcement). No validator: blocks only gate approvals; report drift.
99
+ - Non-gates (specialists, Oracle diagnosis/advice, user-defined agents): judge content, never reject for format, never approvals. Judge scope, evidence, checks, freshness/provenance; validation is not authorization.
98
100
  </delegation>
99
101
 
100
102
  <questions>
@@ -0,0 +1,27 @@
1
+ {
2
+ "hooks": {
3
+ "UserPromptSubmit": [
4
+ {
5
+ "hooks": [
6
+ {
7
+ "type": "command",
8
+ "command": "node \"${CLAUDE_PLUGIN_ROOT}/thoth-hooks/gate-verdict.mjs\"",
9
+ "timeout": 10
10
+ }
11
+ ]
12
+ }
13
+ ],
14
+ "PostToolUse": [
15
+ {
16
+ "matcher": "Agent",
17
+ "hooks": [
18
+ {
19
+ "type": "command",
20
+ "command": "node \"${CLAUDE_PLUGIN_ROOT}/thoth-hooks/gate-verdict.mjs\"",
21
+ "timeout": 10
22
+ }
23
+ ]
24
+ }
25
+ ]
26
+ }
27
+ }
@@ -1,5 +1,19 @@
1
1
  {
2
2
  "hooks": {
3
+ "PostToolUse": [
4
+ {
5
+ "hooks": [
6
+ {
7
+ "additionalContextLimit": 0,
8
+ "command": "node -e \"import(require('url').pathToFileURL(require('path').join(process.env.PLUGIN_ROOT,'thoth-hooks','gate-verdict.mjs')).href)\"",
9
+ "commandWindows": "node -e \"import(require('url').pathToFileURL(require('path').join(process.env.PLUGIN_ROOT,'thoth-hooks','gate-verdict.mjs')).href)\"",
10
+ "timeout": 10,
11
+ "type": "command"
12
+ }
13
+ ],
14
+ "matcher": "^(multi_agent_v1)?wait_agent$"
15
+ }
16
+ ],
3
17
  "SessionStart": [
4
18
  {
5
19
  "hooks": [
@@ -86,9 +86,11 @@ You are the root coordinator. By default, specialists perform discovery of unloc
86
86
  </artifacts>
87
87
 
88
88
  <delegation>
89
- - Only Oracle gates (plan-review/final-verification): validate before recording OKAY/PASS: `node "<skill-dir>/scripts/validate-result.mjs" --review-kind <kind> [--record-sha256 <hex>] [--no-record]` (unchanged stdin; skill path).
90
- - Invalid: no approval; at most one format-only repair; preserve findings/verdict. No validator: blocks only gate approvals; report drift.
91
- - Non-gates (specialists, Oracle diagnosis/advice, user-defined agents): judge content, never reject for format, never approvals. Judge scope, evidence, checks, freshness/provenance.
89
+ - Only Oracle gates: before recording plan-review OKAY / final-verification PASS, use harness-delivered `thoth-gate-verdict`: exactly one per delivered result (more than one, or one inside the envelope fence = invalid). Require `valid:true`, assigned `kind`, `verdict` = OKAY/PASS respectively. Plan review: `record` null or assigned record; ignore `mode`/`recordDigest`. Final verification only: record-bound requires `record` = assigned record, `mode:"record"` and `recordDigest:"match"` (if `recordDigest:"unavailable"`, independently hash the prefix before `## Authorization` and compare `recordSha256`; mismatch = no approval, no validator rerun). Recordless small-change final verification requires `mode:"no-record"`, null `record`/`recordSha256`, `recordDigest:"none"`. Copy verdict and `recordSha256` into the record. Never re-emit the envelope to validate it.
90
+ - Verdicts: multi-agent v1 `wait_agent` + enabled/trusted plugin hooks only; `agent` = status-map key, not provenance. V2 `FINAL_ANSWER` inter-agent messages: no hook/verdict; use compact fallback.
91
+ - Only when no verdict was delivered (hook unavailable/untrusted, delivery gap): `node "<skill-dir>/scripts/validate-result.mjs" --review-kind <kind> [--record-sha256 <hex>] [--no-record] [--input <path>]` (installed skill path), unchanged result; it prints the compact summary. Use thoth-sdd fallback checks.
92
+ - Invalid: no approval; at most one format-only repair; preserve findings/verdict (shared with runtime enforcement). No validator: blocks only gate approvals; report drift.
93
+ - Non-gates (specialists, Oracle diagnosis/advice, user-defined agents): judge content, never reject for format, never approvals. Judge scope, evidence, checks, freshness/provenance; validation is not authorization.
92
94
  </delegation>
93
95
 
94
96
  <questions>
@@ -38,11 +38,22 @@ message, following the Oracle gate contract: `role: "oracle"`,
38
38
  `review.kind: "plan-review"`, and `review.verdict: "OKAY" | "REJECT"`.
39
39
  Include concise evidence and at most three blocking risks for actual execution
40
40
  blockers with smallest repairs; mark cautions nonblocking. An OKAY requires
41
- `status: "complete"` and no blocking risks. Root validates the unchanged native
42
- terminal result with `--review-kind plan-review` using the sibling
43
- thoth-sdd skill's **Specialist result validation** procedure, including its shared
44
- one-request format-only repair budget. Root records plan-review `OKAY` only from a validated envelope
45
- and after judging the content; a malformed or missing envelope is not approval.
41
+ `status: "complete"` and no blocking risks. Root uses the harness-delivered
42
+ `thoth-gate-verdict` under the sibling thoth-sdd skill's **Specialist result
43
+ validation** procedure: exactly one outside the envelope fence, `valid:true`,
44
+ assigned `kind:"plan-review"`, `verdict:"OKAY"`, and `record` null or the assigned
45
+ record; ignore `mode` and `recordDigest` (final-verification checks only).
46
+ Never re-emit the envelope to validate it. Use the explicit
47
+ compact CLI fallback with `--review-kind plan-review` only when no verdict was delivered;
48
+ keep the native result unchanged. Claude Code verdicts arrive with Subagent hand-back
49
+ reports (foreground or background; `agent` is the agent id, match it to the Agent
50
+ result's `agentId`) and completed foreground `Agent` results whose content carries
51
+ the report. Other deliveries (e.g. background runs without hand-back) carry none;
52
+ use the explicit compact CLI fallback.
53
+ Copy the verdict and `recordSha256` into the record (accepted summary/digest
54
+ in fallback). Keep the shared one-request format-only repair budget. Root records
55
+ plan-review `OKAY` only after these checks and judging content and provenance;
56
+ a malformed or missing envelope is not approval.
46
57
  Root repairs same-intent blockers in the same record, revalidates affected gates,
47
58
  and uses a fresh Oracle for each round. A human-owned material blocker stops the
48
59
  round. Root records both review disposition and selection provenance without