@event4u/agent-config 9.1.0 → 9.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +38 -234
  3. package/README.md +1 -1
  4. package/dist/agent-src/commands/fix/route.md +49 -0
  5. package/dist/agent-src/commands/fix.md +4 -2
  6. package/dist/agent-src/commands/implement-ticket.md +2 -0
  7. package/dist/agent-src/commands/review/changes.md +22 -0
  8. package/dist/agent-src/commands/tdd/green.md +32 -0
  9. package/dist/agent-src/commands/tdd/red.md +33 -0
  10. package/dist/agent-src/commands/tdd/refactor.md +31 -0
  11. package/dist/agent-src/commands/tdd.md +50 -0
  12. package/dist/agent-src/contexts/communication/rules-auto/guidelines-mechanics.md +1 -0
  13. package/dist/agent-src/contexts/execution/subagent-modes-detail.md +41 -6
  14. package/dist/agent-src/contexts/execution/subagent-spawn-contract.md +81 -2
  15. package/dist/agent-src/contexts/execution/verify-budget.md +15 -0
  16. package/dist/agent-src/rules/architecture.md +7 -0
  17. package/dist/agent-src/rules/cross-source-consistency.md +92 -0
  18. package/dist/agent-src/rules/delegation-policy.md +1 -1
  19. package/dist/agent-src/skills/estimate-ticket/SKILL.md +2 -0
  20. package/dist/agent-src/skills/fe-design/SKILL.md +1 -0
  21. package/dist/agent-src/skills/feature-planning/SKILL.md +1 -1
  22. package/dist/agent-src/skills/judge-code-quality/SKILL.md +1 -0
  23. package/dist/agent-src/skills/persona-improvement/SKILL.md +81 -0
  24. package/dist/agent-src/skills/po-discovery/SKILL.md +2 -0
  25. package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +10 -0
  26. package/dist/agent-src/skills/refine-ticket/SKILL.md +7 -0
  27. package/dist/agent-src/skills/roadmap-writing/SKILL.md +14 -0
  28. package/dist/agent-src/skills/subagent-orchestration/SKILL.md +38 -28
  29. package/dist/agent-src/skills/subagent-orchestration/evals/evals.json +18 -0
  30. package/dist/agent-src/skills/subagent-orchestration/prompts/README.md +3 -2
  31. package/dist/agent-src/skills/subagent-orchestration/prompts/adversarial-verification-council.md +79 -0
  32. package/dist/agent-src/skills/subagent-orchestration/schemas/adversarial-findings.json +56 -0
  33. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  34. package/dist/discovery/deprecation-report.md +1 -1
  35. package/dist/discovery/discovery-manifest.json +205 -29
  36. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  37. package/dist/discovery/discovery-manifest.summary.md +5 -5
  38. package/dist/discovery/orphan-report.md +1 -1
  39. package/dist/discovery/packs.json +19 -11
  40. package/dist/discovery/trust-report.md +4 -4
  41. package/dist/discovery/workspaces.json +16 -8
  42. package/dist/install/install.mjs +9 -0
  43. package/dist/mcp/registry-manifest.json +3 -3
  44. package/dist/router.json +1 -1
  45. package/dist/server/schemas/settings.js +5 -0
  46. package/dist/server/schemas/settings.js.map +1 -1
  47. package/docs/CLAIMS.md +10 -3
  48. package/docs/architecture.md +4 -4
  49. package/docs/archive/CHANGELOG-pre-9.2.0.md +276 -0
  50. package/docs/benchmark.md +24 -0
  51. package/docs/command-flows.md +9 -3
  52. package/docs/contracts/command-clusters.md +2 -1
  53. package/docs/decisions/ADR-122-adversarial-verification-council.md +136 -0
  54. package/docs/decisions/INDEX.md +1 -0
  55. package/docs/design/adversarial-council-eval.md +106 -0
  56. package/docs/development.md +10 -1
  57. package/docs/featured-skills.md +2 -2
  58. package/docs/getting-started-by-role.md +1 -1
  59. package/docs/getting-started.md +1 -1
  60. package/docs/governance-advantage.md +1 -1
  61. package/docs/guidelines/agent-infra/cross-source-consistency-mechanics.md +109 -0
  62. package/docs/guidelines/component-oriented-and-oop-development.md +181 -0
  63. package/docs/proof.md +7 -7
  64. package/package.json +3 -2
  65. package/src/config/agent-settings.template.yml +42 -0
  66. package/src/scripts/_lib/adversarial_council_gate.test.ts +112 -0
  67. package/src/scripts/_lib/adversarial_council_gate.ts +98 -0
  68. package/src/scripts/_lib/adversarial_reconcile.test.ts +197 -0
  69. package/src/scripts/_lib/adversarial_reconcile.ts +187 -0
  70. package/src/scripts/_lib/verify_budget.ts +4 -1
  71. package/src/scripts/ai_council/prompts.ts +7 -0
  72. package/src/scripts/hook_manifest.yaml +17 -6
  73. package/src/scripts/install-hooks.sh +32 -17
  74. package/src/scripts/pr_url_reminder_hook.ts +177 -0
  75. package/src/scripts/schemas/agent-settings.schema.json +11 -0
  76. package/src/server/schemas/settings.ts +9 -0
@@ -145,6 +145,17 @@ concerns:
145
145
  script: src/scripts/team_review_gate_hook.ts
146
146
  args: []
147
147
  fail_closed: false
148
+ # Reply-shape backstop for the direct-answers rule (reply-close): a PR
149
+ # created THIS turn must end the reply as the literal last raw URL. This
150
+ # PostToolUse hook fires right after a PR *create* (gh pr create, or a
151
+ # github create-pull-request tool) that produced a `…/pull/<n>` URL, and
152
+ # WARNS in context (exit 2) so the reminder lands before the reply closes.
153
+ # Never blocks; unconditional (reinforces an always-on rule, fires only on
154
+ # the rare create event, so no settings gate). fail_closed: false.
155
+ pr-url-reminder:
156
+ script: src/scripts/pr_url_reminder_hook.ts
157
+ args: []
158
+ fail_closed: false
148
159
 
149
160
  platforms:
150
161
  augment:
@@ -152,7 +163,7 @@ platforms:
152
163
  session_end: [chat-history]
153
164
  stop: [chat-history, hot-context, verify-before-complete]
154
165
  pre_tool_use: [block-no-verify, rtk-wrap, design-slop]
155
- post_tool_use: [chat-history, roadmap-progress, context-hygiene, verify-before-complete, minimal-safe-diff, injection-scan]
166
+ post_tool_use: [chat-history, roadmap-progress, context-hygiene, verify-before-complete, minimal-safe-diff, injection-scan, pr-url-reminder]
156
167
 
157
168
  claude:
158
169
  session_start: [chat-history, hot-context, first-run-gate, onboarding-gate, verify-before-complete, minimal-safe-diff, profile-staleness, wrapper-freshness, surface-probe]
@@ -160,7 +171,7 @@ platforms:
160
171
  stop: [chat-history, hot-context, verify-before-complete, team-review-gate]
161
172
  user_prompt_submit: [chat-history, verify-before-complete, minimal-safe-diff]
162
173
  pre_tool_use: [block-no-verify, rtk-wrap, design-slop]
163
- post_tool_use: [chat-history, roadmap-progress, context-hygiene, verify-before-complete, minimal-safe-diff, injection-scan]
174
+ post_tool_use: [chat-history, roadmap-progress, context-hygiene, verify-before-complete, minimal-safe-diff, injection-scan, pr-url-reminder]
164
175
 
165
176
  # Cowork — the Claude desktop app's local-agent-mode runtime, built
166
177
  # on top of the Claude Code CLI. Same lifecycle vocabulary, same
@@ -182,7 +193,7 @@ platforms:
182
193
  stop: [chat-history, hot-context, verify-before-complete]
183
194
  user_prompt_submit: [chat-history, verify-before-complete, minimal-safe-diff]
184
195
  pre_tool_use: [block-no-verify, rtk-wrap, design-slop]
185
- post_tool_use: [chat-history, roadmap-progress, context-hygiene, verify-before-complete, minimal-safe-diff, injection-scan]
196
+ post_tool_use: [chat-history, roadmap-progress, context-hygiene, verify-before-complete, minimal-safe-diff, injection-scan, pr-url-reminder]
186
197
 
187
198
  # Phase 7.5 — Cursor. `.cursor/hooks.json` (project) is read by the
188
199
  # IDE and CLI; `~/.cursor/hooks.json` (user) is opt-in via
@@ -196,7 +207,7 @@ platforms:
196
207
  session_end: [chat-history]
197
208
  stop: [chat-history, hot-context, verify-before-complete]
198
209
  user_prompt_submit: [chat-history, verify-before-complete, minimal-safe-diff]
199
- post_tool_use: [chat-history, roadmap-progress, context-hygiene, verify-before-complete, minimal-safe-diff, injection-scan]
210
+ post_tool_use: [chat-history, roadmap-progress, context-hygiene, verify-before-complete, minimal-safe-diff, injection-scan, pr-url-reminder]
200
211
 
201
212
  # Phase 7.6 — Cline. Hooks live under `.clinerules/hooks/<HookName>`
202
213
  # (project, no file extension, must be executable per Cline docs) or
@@ -211,7 +222,7 @@ platforms:
211
222
  session_end: [chat-history]
212
223
  stop: [chat-history, hot-context, verify-before-complete]
213
224
  user_prompt_submit: [chat-history, verify-before-complete, minimal-safe-diff]
214
- post_tool_use: [chat-history, roadmap-progress, context-hygiene, verify-before-complete, minimal-safe-diff, injection-scan]
225
+ post_tool_use: [chat-history, roadmap-progress, context-hygiene, verify-before-complete, minimal-safe-diff, injection-scan, pr-url-reminder]
215
226
 
216
227
  # Phase 7.7 — Windsurf (Cascade). Hooks live at `.windsurf/hooks.json`
217
228
  # (project) or `~/.codeium/windsurf/hooks.json` (user). Cascade has
@@ -245,7 +256,7 @@ platforms:
245
256
  session_end: [chat-history]
246
257
  stop: [chat-history, hot-context, verify-before-complete]
247
258
  user_prompt_submit: [chat-history, verify-before-complete, minimal-safe-diff]
248
- post_tool_use: [chat-history, roadmap-progress, context-hygiene, verify-before-complete, minimal-safe-diff, injection-scan]
259
+ post_tool_use: [chat-history, roadmap-progress, context-hygiene, verify-before-complete, minimal-safe-diff, injection-scan, pr-url-reminder]
249
260
 
250
261
  # Phase 7.9 — Copilot has no hook surface. Concerns route through
251
262
  # rule-only fallback; the dispatcher silently no-ops on --platform copilot.
@@ -8,32 +8,47 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
8
8
  # This installer lives at src/scripts/install-hooks.sh, so the repo root
9
9
  # (which owns .git/) is two levels up.
10
10
  PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
11
- HOOKS_DIR="$PROJECT_ROOT/.git/hooks"
11
+ # Resolve the SHARED hooks dir via git so this also works from a linked worktree
12
+ # (where $PROJECT_ROOT/.git is a file, not a dir, and a literal .git/hooks path
13
+ # would break under `set -e`). --git-common-dir points at the main .git even from
14
+ # a worktree; fall back to the literal path only outside a git repo.
15
+ if COMMON_GIT_DIR="$(git -C "$PROJECT_ROOT" rev-parse --git-common-dir 2>/dev/null)"; then
16
+ case "$COMMON_GIT_DIR" in /*) : ;; *) COMMON_GIT_DIR="$PROJECT_ROOT/$COMMON_GIT_DIR" ;; esac
17
+ HOOKS_DIR="$COMMON_GIT_DIR/hooks"
18
+ else
19
+ HOOKS_DIR="$PROJECT_ROOT/.git/hooks"
20
+ fi
12
21
 
13
22
  mkdir -p "$HOOKS_DIR"
14
23
 
15
24
  cat > "$HOOKS_DIR/pre-push" << 'EOF'
16
25
  #!/usr/bin/env bash
17
- # Pre-push hook: verify dist/agent-src/ is in sync with .agent-src.uncondensed/
18
- # and that the canonical command count matches README + getting-started docs.
26
+ # Pre-push hook: mirror the CI "Sync + Generate Tools Consistency" gate LOCALLY
27
+ # so derived-output drift is caught BEFORE push, not in remote CI.
19
28
  #
20
- # The command-count gate exists because three consecutive PRs landed
21
- # post-CI count-drift fixes (e.g. f2fb0026 "bump command count
22
- # 101→103"). Catching the drift pre-push stops it from flooding remote
23
- # CI. Runtime ~0.1s.
29
+ # History: the remote "Consistency" check failed in a large share of PRs because
30
+ # the old hook only verified dist sync + the COMMAND count — it missed
31
+ # guideline/skill/rule count drift and the generate-tools / router / corpus
32
+ # outputs (e.g. a new guideline bumping the count in README + docs/architecture).
33
+ # `task consistency` is the EXACT CI mirror (sync-check + sync-check-hashes +
34
+ # sync + generate-tools + compile-router + compile-corpus + `git diff --quiet`),
35
+ # so any derived-output drift blocks the push here. Runtime ~15-40s (it
36
+ # regenerates the tool trees) — cheaper than a red CI run and a fixup re-push.
24
37
 
25
38
  fail=0
26
39
 
27
- echo "🔍 Checking dist/agent-src/ sync..."
28
- if ! ./scripts-run src/scripts/condense --check; then
29
- echo "❌ dist/agent-src/ is out of sync. Run 'task sync' and condense changed .md files, then commit."
30
- fail=1
31
- fi
32
-
33
- echo "🔍 Checking command count messaging..."
34
- if ! ./scripts-run src/scripts/check_command_count_messaging; then
35
- echo "❌ Command-count drift in README / AGENTS.md / getting-started. Run 'task counts-update', stage the changes, then re-commit."
36
- fail=1
40
+ if ! command -v task >/dev/null 2>&1; then
41
+ echo "⚠️ 'task' (go-task) not found — cannot run the consistency gate locally."
42
+ echo " Install it (https://taskfile.dev) so pre-push can mirror the CI check;"
43
+ echo " skipping the consistency check for this push."
44
+ else
45
+ echo "🔍 Consistency — mirroring the CI 'Sync + Generate Tools Consistency' gate..."
46
+ if ! task consistency; then
47
+ echo "❌ Derived outputs drifted (counts / dist / generated tool trees / router / corpus)."
48
+ echo " 'task consistency' just regenerated them into your working tree —"
49
+ echo " review + 'git add' the changes (or run 'task consistency-fix'), commit, then re-push."
50
+ fail=1
51
+ fi
37
52
  fi
38
53
 
39
54
  echo "🔍 Checking for leftover conflict markers / unmerged paths..."
@@ -0,0 +1,177 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * PostToolUse PR-URL reminder — reply-shape backstop for `direct-answers`.
4
+ *
5
+ * The `direct-answers` rule (reply-close) requires: a PR created THIS turn puts
6
+ * its raw URL as the **literal last line** of the reply. That is a behavioural
7
+ * rule with no deterministic backstop, so it can be silently missed — the URL
8
+ * ends up inline mid-reply instead of last. This hook fires right after a
9
+ * PR-creating tool call, extracts the created PR URL from the tool output, and
10
+ * WARNS in context (exit 2) so the reminder lands exactly when the PR is born,
11
+ * before the reply closes.
12
+ *
13
+ * Fires ONLY on an actual PR *create*:
14
+ * - a shell command matching `gh pr create`, OR
15
+ * - a GitHub tool whose name means "create a pull request"
16
+ * (e.g. create_pull_request / createPullRequest / pulls.create),
17
+ * AND only when the tool output actually contains a `…/pull/<n>` URL — so a
18
+ * failed / dry-run create (no URL) does not nag, and `gh pr view/checks/list/
19
+ * comment` (which also print PR URLs) never fire it.
20
+ *
21
+ * Warn only — never blocks (fail_closed: false). Unconditional: it reinforces
22
+ * an always-on rule and only fires on the rare PR-create event, so it carries
23
+ * no settings gate (mirrors verify-before-complete / roadmap-progress).
24
+ *
25
+ * Exit codes (dispatcher contract): 0 allow · 2 warn (+ `{decision,reason}`
26
+ * JSON on stdout).
27
+ */
28
+ import fs from "node:fs";
29
+ import path from "node:path";
30
+ import { fileURLToPath, pathToFileURL } from "node:url";
31
+
32
+ const EXIT_ALLOW = 0;
33
+ const EXIT_WARN = 2;
34
+
35
+ type JsonValue = string | number | boolean | null | JsonValue[] | { [k: string]: JsonValue };
36
+ type JsonObject = { [k: string]: JsonValue };
37
+
38
+ // Tool names across platforms whose command field carries a shell command
39
+ // (kept in lock-step with verify_before_complete_hook.COMMAND_TOOLS).
40
+ const COMMAND_TOOLS: ReadonlySet<string> = new Set([
41
+ "launch-process",
42
+ "launch_process",
43
+ "Bash",
44
+ "BashTool",
45
+ "run-process",
46
+ "runProcess",
47
+ "shell",
48
+ "execute_shell",
49
+ "RunShellCommand",
50
+ ]);
51
+
52
+ // A shell command that CREATES a pull request. Anchored on a shell separator so
53
+ // it matches inside a chained command (`git push && gh pr create …`) but not a
54
+ // substring of another word. `gh pr view/checks/list/comment` do not match.
55
+ const _GH_PR_CREATE = /(?:^|[\s;&|`(])gh\s+pr\s+create\b/i;
56
+
57
+ // A non-shell tool whose NAME means "create a pull request" (github-api / MCP).
58
+ const _CREATE_PR_TOOL = /(?:create[_-]?pull_?request|createpullrequest|pulls[._-]create|create_pr\b)/i;
59
+
60
+ // A GitHub pull-request URL as printed by `gh pr create` / returned as html_url.
61
+ const _PR_URL = /https?:\/\/github\.com\/[^\s"'`<>]+\/pull\/\d+/i;
62
+
63
+ function _isObject(v: unknown): v is JsonObject {
64
+ return typeof v === "object" && v !== null && !Array.isArray(v);
65
+ }
66
+
67
+ /** Return [tool_name, command_text] from a tool-event payload. */
68
+ function _extractCommand(payload: JsonObject): [string | null, string | null] {
69
+ const toolRaw = payload["tool_name"] ?? payload["toolName"] ?? payload["tool"];
70
+ const tool = typeof toolRaw === "string" ? toolRaw : null;
71
+ if (!(tool !== null && COMMAND_TOOLS.has(tool))) {
72
+ return [tool, null];
73
+ }
74
+ const ti = payload["tool_input"];
75
+ if (_isObject(ti)) {
76
+ for (const key of ["command", "cmd", "shell_command"]) {
77
+ const v = ti[key];
78
+ if (typeof v === "string" && v) {
79
+ return [tool, v];
80
+ }
81
+ }
82
+ }
83
+ for (const key of ["command", "cmd"]) {
84
+ const v = payload[key];
85
+ if (typeof v === "string" && v) {
86
+ return [tool, v];
87
+ }
88
+ }
89
+ return [tool, null];
90
+ }
91
+
92
+ /** Best-effort extraction of the tool-output text from the envelope. */
93
+ function _toolOutput(envelope: JsonObject): string {
94
+ for (const key of ["tool_response", "tool_result", "toolResponse", "output", "result", "stdout"]) {
95
+ const v = envelope[key];
96
+ if (typeof v === "string") {
97
+ return v;
98
+ }
99
+ if (_isObject(v) || Array.isArray(v)) {
100
+ return JSON.stringify(v);
101
+ }
102
+ }
103
+ return JSON.stringify(envelope);
104
+ }
105
+
106
+ /** True when this tool event created a pull request. */
107
+ function _isPrCreate(tool: string | null, command: string | null): boolean {
108
+ if (command !== null && _GH_PR_CREATE.test(command)) {
109
+ return true;
110
+ }
111
+ return tool !== null && _CREATE_PR_TOOL.test(tool);
112
+ }
113
+
114
+ export function main(): number {
115
+ let envelope: JsonValue;
116
+ try {
117
+ const raw = _readStdin();
118
+ envelope = raw.trim() ? (JSON.parse(raw) as JsonValue) : {};
119
+ } catch {
120
+ return EXIT_ALLOW; // never block on a malformed envelope
121
+ }
122
+ if (!_isObject(envelope)) {
123
+ return EXIT_ALLOW;
124
+ }
125
+
126
+ const [tool, command] = _extractCommand(envelope);
127
+ if (!_isPrCreate(tool, command)) {
128
+ return EXIT_ALLOW;
129
+ }
130
+
131
+ const match = _PR_URL.exec(_toolOutput(envelope));
132
+ if (match === null) {
133
+ return EXIT_ALLOW; // create attempted but no URL produced (failed / dry-run) — do not nag
134
+ }
135
+ const url = match[0];
136
+
137
+ // `reason` (≤ 200 chars) goes to stderr; `additional_context` is what
138
+ // surfaces back to the model on platforms that support it — so the
139
+ // actionable instruction lives there (a stderr-only reason would not
140
+ // change the reply that this hook exists to shape).
141
+ const reason = `PR created this turn (${url}) — end your reply with this raw URL as the literal last line (direct-answers/reply-close).`;
142
+ const additional_context =
143
+ `You created a pull request this turn: ${url}\n\n` +
144
+ `Per the direct-answers rule (reply-close): a PR created this turn must appear ` +
145
+ `as the raw URL on the LITERAL LAST LINE of your reply — not inline mid-message. ` +
146
+ `Before ending the turn, make your final line exactly:\n${url}\n` +
147
+ `If it already is, no action needed.`;
148
+ process.stdout.write(`${JSON.stringify({ decision: "warn", reason, additional_context })}\n`);
149
+ return EXIT_WARN;
150
+ }
151
+
152
+ function _readStdin(): string {
153
+ return fs.readFileSync(0, "utf-8");
154
+ }
155
+
156
+ function _isCliEntry(): boolean {
157
+ if (process.argv[1] === undefined) {
158
+ return false;
159
+ }
160
+ const argvUrl = pathToFileURL(path.resolve(process.argv[1])).href;
161
+ if (import.meta.url === argvUrl) {
162
+ return true;
163
+ }
164
+ // Symlinked invocation (installed projection, or macOS /var → /private/var
165
+ // temp dirs) makes the raw URLs differ; compare realpaths so the guard fires.
166
+ try {
167
+ const here = fs.realpathSync(fileURLToPath(import.meta.url));
168
+ const argv = fs.realpathSync(path.resolve(process.argv[1]));
169
+ return here === argv;
170
+ } catch {
171
+ return false;
172
+ }
173
+ }
174
+
175
+ if (_isCliEntry()) {
176
+ process.exit(main());
177
+ }
@@ -84,6 +84,17 @@
84
84
  }
85
85
  }
86
86
  },
87
+ "consistency": {
88
+ "type": "object",
89
+ "additionalProperties": true,
90
+ "properties": {
91
+ "cross_source": {
92
+ "type": "string",
93
+ "enum": ["on", "auto", "off"],
94
+ "description": "Consumed by the cross-source-consistency rule. When the agent works from multiple sources (ticket text, an attached image/mockup, the spec, the codebase) it checks them against each other and asks before proceeding on a discrepancy. on (default) = surface every real cross-source contradiction / silent-scope-expansion as one question; auto = surface only high-confidence contradictions, state low-confidence as an assumption; off = no cross-source checking."
95
+ }
96
+ }
97
+ },
87
98
  "code_style": {
88
99
  "type": "object",
89
100
  "additionalProperties": true,
@@ -26,6 +26,7 @@ const qualityCadence = z.enum(['end_of_roadmap', 'per_phase', 'per_step']);
26
26
  const regenCadence = z.enum(['per_step', 'every_5_steps', 'phase_boundary']);
27
27
  const worktreeMode = z.enum(['off', 'on', 'ask']);
28
28
  const fidelityMode = z.enum(['strict', 'structural', 'hard-floor']);
29
+ const crossSourceMode = z.enum(['on', 'auto', 'off']);
29
30
  const richSkillsMode = z.enum(['on', 'ask', 'off']);
30
31
  const replyMethod = z.enum(['replies_endpoint', 'create_review_comment', 'auto']);
31
32
  const confidenceBand = z.enum(['off', 'low', 'medium', 'high']);
@@ -203,6 +204,11 @@ export const settingsSchema = z.object({
203
204
  'How strictly the agent must follow a user-provided prototype / mockup / design system (consumed by the design-fidelity rule). strict = build 1:1, every visible deviation needs confirmation; structural = structure locked, silent gaps fillable with a stated assumption; hard-floor = any deviation is never autonomous.',
204
205
  ),
205
206
  }).default({ fidelity_mode: 'strict' }),
207
+ consistency: z.object({
208
+ cross_source: crossSourceMode.default('on').describe(
209
+ 'Consumed by the cross-source-consistency rule. When the agent works from multiple sources (ticket text, an attached image/mockup, the spec, the codebase) it checks them against each other and asks before proceeding on a discrepancy — instead of silently guessing. on (default) = surface every real cross-source contradiction / silent-scope-expansion as one question; auto = surface only high-confidence contradictions, state low-confidence as an assumption; off = no cross-source checking.',
210
+ ),
211
+ }).default({ cross_source: 'on' }),
206
212
  tokens: z.object({
207
213
  rich_skills: richSkillsMode.default('on').describe(
208
214
  'Whether skills marked token_budget_class: rich may load in full (exempt from telegraph-speak + thin-projector trimming), consumed by the token-budget-discipline rule. on = allowed (default); off = fall back to standard condensed behavior; ask = surface an estimated token delta (tokens, not dollars) and ask once per session before loading.',
@@ -282,6 +288,9 @@ export const settingsSchema = z.object({
282
288
  max_parallel: z.number().int().min(1).default(3).describe(
283
289
  'Hard cap on subagents running in parallel during /do-in-parallel, /do-competitively, and /judge runs. Raise for faster fan-out, lower if you hit rate limits or want lower token spend.',
284
290
  ),
291
+ adversarial_council: z.enum(['off', 'ask', 'on']).default('off').describe(
292
+ 'Opt-in adversarial-verification-council mode (subagent-orchestration Mode 9, ADR-122). off (default) = never runs; ask = offer it on an explicit high-risk change; on = auto-run on high-risk changes. Advisory only — a panel of distinct-model skeptics red-teams a real change for defect FINDING coverage and NEVER auto-gates it (Hard Floor). Stays default-off until the adversarial-council-finding-coverage claim is backed.',
293
+ ),
285
294
  }),
286
295
  worktrees: z.object({
287
296
  mode: worktreeMode.default('ask').describe(