agent-nuvira 3.3.12 → 3.3.13

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 (152) hide show
  1. package/dist/agents/agents/reasoner.d.ts.map +1 -1
  2. package/dist/agents/agents/reasoner.js +13 -0
  3. package/dist/agents/agents/reasoner.js.map +1 -1
  4. package/dist/agents/orchestrator.d.ts.map +1 -1
  5. package/dist/agents/orchestrator.js +29 -9
  6. package/dist/agents/orchestrator.js.map +1 -1
  7. package/dist/cli/chat.d.ts.map +1 -1
  8. package/dist/cli/chat.js +34 -7
  9. package/dist/cli/chat.js.map +1 -1
  10. package/dist/cli/cli-program.d.ts.map +1 -1
  11. package/dist/cli/cli-program.js +8 -0
  12. package/dist/cli/cli-program.js.map +1 -1
  13. package/dist/cli/config.d.ts.map +1 -1
  14. package/dist/cli/config.js +21 -3
  15. package/dist/cli/config.js.map +1 -1
  16. package/dist/cli/execute.d.ts.map +1 -1
  17. package/dist/cli/execute.js +6 -0
  18. package/dist/cli/execute.js.map +1 -1
  19. package/dist/cli/knowledge.d.ts +23 -0
  20. package/dist/cli/knowledge.d.ts.map +1 -0
  21. package/dist/cli/knowledge.js +132 -0
  22. package/dist/cli/knowledge.js.map +1 -0
  23. package/dist/cli/loop-executor.d.ts.map +1 -1
  24. package/dist/cli/loop-executor.js +45 -6
  25. package/dist/cli/loop-executor.js.map +1 -1
  26. package/dist/cli/omniroute-control.d.ts +88 -0
  27. package/dist/cli/omniroute-control.d.ts.map +1 -0
  28. package/dist/cli/omniroute-control.js +179 -0
  29. package/dist/cli/omniroute-control.js.map +1 -0
  30. package/dist/cli/omniroute.d.ts +21 -0
  31. package/dist/cli/omniroute.d.ts.map +1 -0
  32. package/dist/cli/omniroute.js +67 -0
  33. package/dist/cli/omniroute.js.map +1 -0
  34. package/dist/config/types.d.ts +8 -0
  35. package/dist/config/types.d.ts.map +1 -1
  36. package/dist/context/history.d.ts +21 -0
  37. package/dist/context/history.d.ts.map +1 -1
  38. package/dist/context/history.js +50 -0
  39. package/dist/context/history.js.map +1 -1
  40. package/dist/gateway/hook-contract.d.ts +173 -0
  41. package/dist/gateway/hook-contract.d.ts.map +1 -0
  42. package/dist/gateway/hook-contract.js +352 -0
  43. package/dist/gateway/hook-contract.js.map +1 -0
  44. package/dist/gateway/hooks.d.ts.map +1 -1
  45. package/dist/gateway/hooks.js +14 -0
  46. package/dist/gateway/hooks.js.map +1 -1
  47. package/dist/inference/interface.d.ts +17 -0
  48. package/dist/inference/interface.d.ts.map +1 -1
  49. package/dist/inference/model-id-validation.d.ts +57 -0
  50. package/dist/inference/model-id-validation.d.ts.map +1 -0
  51. package/dist/inference/model-id-validation.js +127 -0
  52. package/dist/inference/model-id-validation.js.map +1 -0
  53. package/dist/inference/openai-compat-adapter.d.ts.map +1 -1
  54. package/dist/inference/openai-compat-adapter.js +12 -1
  55. package/dist/inference/openai-compat-adapter.js.map +1 -1
  56. package/dist/inference/provider-catalog.d.ts +11 -0
  57. package/dist/inference/provider-catalog.d.ts.map +1 -1
  58. package/dist/inference/provider-catalog.js +80 -0
  59. package/dist/inference/provider-catalog.js.map +1 -1
  60. package/dist/inference/route-resolver.d.ts +2 -8
  61. package/dist/inference/route-resolver.d.ts.map +1 -1
  62. package/dist/inference/route-resolver.js +17 -0
  63. package/dist/inference/route-resolver.js.map +1 -1
  64. package/dist/inference/tool-call-utils.d.ts.map +1 -1
  65. package/dist/inference/tool-call-utils.js +10 -8
  66. package/dist/inference/tool-call-utils.js.map +1 -1
  67. package/dist/inference/tools.d.ts +1 -0
  68. package/dist/inference/tools.d.ts.map +1 -1
  69. package/dist/inference/tools.js +20 -3
  70. package/dist/inference/tools.js.map +1 -1
  71. package/dist/learning/auto-router.d.ts +53 -0
  72. package/dist/learning/auto-router.d.ts.map +1 -1
  73. package/dist/learning/auto-router.js +73 -0
  74. package/dist/learning/auto-router.js.map +1 -1
  75. package/dist/learning/error-repair.d.ts +23 -1
  76. package/dist/learning/error-repair.d.ts.map +1 -1
  77. package/dist/learning/error-repair.js +58 -0
  78. package/dist/learning/error-repair.js.map +1 -1
  79. package/dist/learning/knowledge-base.d.ts +124 -0
  80. package/dist/learning/knowledge-base.d.ts.map +1 -0
  81. package/dist/learning/knowledge-base.js +337 -0
  82. package/dist/learning/knowledge-base.js.map +1 -0
  83. package/dist/learning/model-selection.d.ts +2 -1
  84. package/dist/learning/model-selection.d.ts.map +1 -1
  85. package/dist/learning/model-selection.js +35 -2
  86. package/dist/learning/model-selection.js.map +1 -1
  87. package/dist/learning/project-docs.d.ts +83 -0
  88. package/dist/learning/project-docs.d.ts.map +1 -0
  89. package/dist/learning/project-docs.js +132 -0
  90. package/dist/learning/project-docs.js.map +1 -0
  91. package/dist/learning/quota-ledger.d.ts +13 -0
  92. package/dist/learning/quota-ledger.d.ts.map +1 -1
  93. package/dist/learning/quota-ledger.js +28 -0
  94. package/dist/learning/quota-ledger.js.map +1 -1
  95. package/dist/learning/seeded-benchmark.d.ts +14 -0
  96. package/dist/learning/seeded-benchmark.d.ts.map +1 -1
  97. package/dist/learning/seeded-benchmark.js +43 -4
  98. package/dist/learning/seeded-benchmark.js.map +1 -1
  99. package/dist/security/secret-scan.d.ts +156 -0
  100. package/dist/security/secret-scan.d.ts.map +1 -0
  101. package/dist/security/secret-scan.js +525 -0
  102. package/dist/security/secret-scan.js.map +1 -0
  103. package/dist/tools/plan-store.d.ts +24 -2
  104. package/dist/tools/plan-store.d.ts.map +1 -1
  105. package/dist/tools/plan-store.js +42 -2
  106. package/dist/tools/plan-store.js.map +1 -1
  107. package/dist/tools/registry.d.ts.map +1 -1
  108. package/dist/tools/registry.js +149 -1
  109. package/dist/tools/registry.js.map +1 -1
  110. package/dist/tools/remediation-ladder.d.ts +91 -0
  111. package/dist/tools/remediation-ladder.d.ts.map +1 -0
  112. package/dist/tools/remediation-ladder.js +308 -0
  113. package/dist/tools/remediation-ladder.js.map +1 -0
  114. package/dist/tools/run-terminal.d.ts.map +1 -1
  115. package/dist/tools/run-terminal.js +26 -2
  116. package/dist/tools/run-terminal.js.map +1 -1
  117. package/dist/tools/skills-hub.d.ts +7 -0
  118. package/dist/tools/skills-hub.d.ts.map +1 -1
  119. package/dist/tools/skills-hub.js +11 -2
  120. package/dist/tools/skills-hub.js.map +1 -1
  121. package/dist/tools/step-artifact.d.ts +35 -0
  122. package/dist/tools/step-artifact.d.ts.map +1 -0
  123. package/dist/tools/step-artifact.js +154 -0
  124. package/dist/tools/step-artifact.js.map +1 -0
  125. package/dist/tools/tool-loop.d.ts +6 -0
  126. package/dist/tools/tool-loop.d.ts.map +1 -1
  127. package/dist/tools/tool-loop.js +27 -3
  128. package/dist/tools/tool-loop.js.map +1 -1
  129. package/dist/tools/toolsets.js +4 -4
  130. package/dist/tools/toolsets.js.map +1 -1
  131. package/dist/tools/worktree.d.ts +11 -2
  132. package/dist/tools/worktree.d.ts.map +1 -1
  133. package/dist/tools/worktree.js +11 -2
  134. package/dist/tools/worktree.js.map +1 -1
  135. package/dist/web-dashboard/server.d.ts +29 -0
  136. package/dist/web-dashboard/server.d.ts.map +1 -1
  137. package/dist/web-dashboard/server.js +372 -5
  138. package/dist/web-dashboard/server.js.map +1 -1
  139. package/dist/web-dashboard/src/types.d.ts +66 -0
  140. package/dist/web-dashboard/src/types.d.ts.map +1 -1
  141. package/dist/web-dashboard/workspace-guard.d.ts +7 -0
  142. package/dist/web-dashboard/workspace-guard.d.ts.map +1 -1
  143. package/dist/web-dashboard/workspace-guard.js +70 -0
  144. package/dist/web-dashboard/workspace-guard.js.map +1 -1
  145. package/package.json +1 -1
  146. package/src/web-dashboard/public/assets/index-DhiuR4S2.js +210 -0
  147. package/src/web-dashboard/public/assets/index-DhiuR4S2.js.map +1 -0
  148. package/src/web-dashboard/public/assets/index-tK8Y2qHB.css +1 -0
  149. package/src/web-dashboard/public/index.html +2 -2
  150. package/src/web-dashboard/public/assets/index-BrZcYhy6.js +0 -207
  151. package/src/web-dashboard/public/assets/index-BrZcYhy6.js.map +0 -1
  152. package/src/web-dashboard/public/assets/index-DsWczTa6.css +0 -1
@@ -0,0 +1,525 @@
1
+ /**
2
+ * secret-scan — find secret-shaped strings in a working tree, ON DEMAND.
3
+ *
4
+ * WHY THIS EXISTS. Nuvira writes code and commits it. "Did I just stage a key?"
5
+ * is a real, recurring failure mode in that loop, and it is the one the toolchain
6
+ * cannot answer today: `redact()` (enterprise/secrets.ts) keeps secrets out of
7
+ * logs and history, but nothing ever LOOKS for them in the user's files.
8
+ *
9
+ * RELATIONSHIP TO `redact()`: deliberately complementary, not a second opinion.
10
+ * `redact()` is a SCRUBBER — it masks and never reports. This module is a
11
+ * DETECTOR — it reports what and where, and masks the value in its own output
12
+ * (reusing the SAME `maskSecret`/`redact` primitives and the SAME
13
+ * `KNOWN_KEY_PREFIXES` table), so what we detect can never drift from what we
14
+ * redact. One pattern source of truth, two readers.
15
+ *
16
+ * DESIGN CONSTRAINTS
17
+ * - Dependency-free and LOCAL. No `gitleaks`/`ggshield` binary, no network, no
18
+ * vendor. That is the whole point of the local-first path: a scanner that
19
+ * reads every file is a privacy decision, so the default must keep the data
20
+ * on the machine.
21
+ * - PURE + DETERMINISTIC at the text level (`scanText`), so it is unit-testable
22
+ * without a filesystem; `scanDirectory` is the thin I/O wrapper.
23
+ * - NEVER a security guarantee. It is a lint: it catches KNOWN shapes and common
24
+ * assignments, and a clean result means "nothing matched", not "no secrets".
25
+ * The summary says so, because a scanner that overclaims is worse than none.
26
+ */
27
+ import { execFileSync } from 'node:child_process';
28
+ import { readFileSync, readdirSync, statSync } from 'node:fs';
29
+ import { join, relative, sep } from 'node:path';
30
+ import { KNOWN_KEY_PREFIXES, maskSecret, redact } from '../enterprise/secrets.js';
31
+ // ─── Pattern table ──────────────────────────────────────────────────────────
32
+ /**
33
+ * High-confidence, low-false-positive shapes. Ordered most-specific first so a
34
+ * value is attributed to the narrowest pattern that matches it.
35
+ *
36
+ * Deliberately NOT included: a bare high-entropy heuristic. It is the classic
37
+ * source of "your scan found 4000 secrets" noise (git SHAs, hashes, minified
38
+ * bundles), and a lint nobody trusts gets switched off — which is worse than a
39
+ * narrower one people keep on.
40
+ */
41
+ export const SECRET_PATTERNS = [
42
+ { id: 'private-key', label: 'Private key block', severity: 'critical', re: /-----BEGIN [A-Z ]{0,40}PRIVATE KEY-----/g },
43
+ { id: 'aws-access-key-id', label: 'AWS access key id', severity: 'critical', re: /\b(?:AKIA|ASIA)[0-9A-Z]{16}\b/g },
44
+ { id: 'aws-secret', label: 'AWS secret access key', severity: 'critical', re: /\baws[_-]?secret[_-]?access[_-]?key\b\s*[:=]\s*["']?([A-Za-z0-9/+=]{40})/gi },
45
+ { id: 'github-pat', label: 'GitHub token', severity: 'critical', re: /\bgh[pousr]_[A-Za-z0-9]{36,}\b/g },
46
+ { id: 'github-pat-fine', label: 'GitHub fine-grained token', severity: 'critical', re: /\bgithub_pat_[A-Za-z0-9_]{30,}\b/g },
47
+ { id: 'anthropic-key', label: 'Anthropic API key', severity: 'critical', re: /\bsk-ant-[A-Za-z0-9_-]{20,}\b/g },
48
+ { id: 'openai-key', label: 'OpenAI-compatible API key', severity: 'critical', re: /\bsk-(?!ant-)[A-Za-z0-9]{20,}\b/g },
49
+ { id: 'groq-key', label: 'Groq API key', severity: 'critical', re: /\bgsk_[A-Za-z0-9]{20,}\b/g },
50
+ { id: 'google-api-key', label: 'Google API key', severity: 'critical', re: /\bAIza[0-9A-Za-z_-]{35}\b/g },
51
+ { id: 'google-oauth-secret', label: 'Google OAuth client secret', severity: 'critical', re: /\bGOCSPX-[A-Za-z0-9_-]{20,}\b/g },
52
+ { id: 'nvidia-nim-key', label: 'NVIDIA NIM key', severity: 'critical', re: /\bnvapi-[A-Za-z0-9_-]{20,}\b/g },
53
+ { id: 'slack-token', label: 'Slack token', severity: 'critical', re: /\bxox[baprs]-[A-Za-z0-9-]{10,}\b/g },
54
+ { id: 'stripe-key', label: 'Stripe secret/restricted key', severity: 'critical', re: /\b(?:sk|rk)_(?:live|test)_[A-Za-z0-9]{20,}\b/g },
55
+ { id: 'hf-token', label: 'HuggingFace token', severity: 'high', re: /\bhf_[A-Za-z0-9]{30,}\b/g },
56
+ { id: 'xai-key', label: 'xAI API key', severity: 'high', re: /\bxai-[A-Za-z0-9]{20,}\b/g },
57
+ { id: 'jwt', label: 'JWT / bearer token', severity: 'high', re: /\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/g },
58
+ {
59
+ id: 'url-credentials',
60
+ label: 'Credentials embedded in a URL',
61
+ severity: 'high',
62
+ re: /\b[a-z][a-z0-9+.-]{1,12}:\/\/[^\s/:@]{2,}:[^\s/:@]{4,}@[^\s/]+/gi,
63
+ },
64
+ ];
65
+ /**
66
+ * Build a bare-prefix pattern from the SAME list `redact()` uses, so every
67
+ * prefix we know how to mask is also one we can find. Kept separate from
68
+ * SECRET_PATTERNS because it is generated, not hand-written.
69
+ */
70
+ function buildPrefixPatterns() {
71
+ // Skip prefixes already covered by an explicit, narrower pattern above
72
+ // (rewriting them here would double-report the same value).
73
+ const covered = new Set(['sk-', 'gsk_', 'AIza', 'xai-', 'hf_', 'AKIA', 'eyJ', 'ghp_', 'nvapi-']);
74
+ return KNOWN_KEY_PREFIXES.filter((p) => !covered.has(p)).map((prefix) => ({
75
+ id: `prefix:${prefix}`,
76
+ label: `Known key prefix "${prefix}"`,
77
+ severity: 'medium',
78
+ re: new RegExp(`\\b${prefix.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}[A-Za-z0-9._\\-+/]{16,}`, 'g'),
79
+ }));
80
+ }
81
+ const ALL_PATTERNS = [...SECRET_PATTERNS, ...buildPrefixPatterns()];
82
+ /**
83
+ * Assignment-shaped matches (`apiKey = "…"`, `"token": "…"`). The value must be
84
+ * long AND not obviously a placeholder, or every `.env.example` in the world
85
+ * becomes a finding.
86
+ */
87
+ const ASSIGN_PATTERN = {
88
+ id: 'assigned-secret',
89
+ label: 'Secret-looking value assigned to a sensitive name',
90
+ severity: 'medium',
91
+ re: /\b(?:api[_-]?key|apikey|secret|client[_-]?secret|access[_-]?token|auth[_-]?token|refresh[_-]?token|password|passwd|private[_-]?key|access[_-]?key)\b["']?\s*[:=]\s*["']([A-Za-z0-9._\-+/]{16,})["']/gi,
92
+ };
93
+ /** Values that are plainly not real secrets — checked before reporting. */
94
+ const PLACEHOLDER_RE = /^(?:your|my|the|example|sample|test|dummy|fake|placeholder|changeme|change_me|none|null|undefined|todo|xxx+|\*+|<.*>)$/i;
95
+ const TEMPLATE_RE = /[$%{<]/; // `${VAR}`, `{{var}}`, `<your-key>` — interpolation, not a literal
96
+ const LOW_ENTROPY_RE = /^(.)\1+$/; // aaaa..., 1111...
97
+ /** Is this matched VALUE obviously a placeholder rather than a real secret? */
98
+ export function looksLikePlaceholder(value) {
99
+ const v = value.trim();
100
+ if (!v)
101
+ return true;
102
+ if (v.length < 8)
103
+ return true;
104
+ if (PLACEHOLDER_RE.test(v))
105
+ return true;
106
+ if (TEMPLATE_RE.test(v))
107
+ return true;
108
+ if (LOW_ENTROPY_RE.test(v))
109
+ return true;
110
+ if (!/[A-Za-z]/.test(v) || !/[0-9]/.test(v)) {
111
+ // Pure letters or pure digits is usually a word/number, not a credential.
112
+ // (Real keys are mixed, and the prefix patterns above still catch the
113
+ // vendors whose keys are letters-only.)
114
+ if (v.length < 24)
115
+ return true;
116
+ }
117
+ return false;
118
+ }
119
+ // ─── Text scanning (pure) ───────────────────────────────────────────────────
120
+ /**
121
+ * Find secret-shaped substrings in `text`. Pure and synchronous — the whole
122
+ * detector lives here, so it can be tested without touching a filesystem.
123
+ *
124
+ * @param text Content to scan (a file body, a diff, a log line).
125
+ * @param path Label attached to each finding (workspace-relative).
126
+ */
127
+ export function scanText(text, path = '<text>') {
128
+ if (!text)
129
+ return [];
130
+ const lines = text.split(/\r?\n/);
131
+ const findings = [];
132
+ // One report per (pattern, line) — a minified line must not yield 50 rows.
133
+ const seen = new Set();
134
+ for (let i = 0; i < lines.length; i += 1) {
135
+ const line = lines[i];
136
+ if (!line || line.length === 0)
137
+ continue;
138
+ for (const pattern of [...ALL_PATTERNS, ASSIGN_PATTERN]) {
139
+ pattern.re.lastIndex = 0;
140
+ let m;
141
+ while ((m = pattern.re.exec(line)) !== null) {
142
+ // When the pattern captures the value explicitly, judge THAT (the
143
+ // assignment case); otherwise judge the whole match.
144
+ const value = m[1] ?? m[0];
145
+ if (looksLikePlaceholder(value)) {
146
+ if (m[0].length === 0)
147
+ pattern.re.lastIndex += 1; // never loop forever
148
+ continue;
149
+ }
150
+ const key = `${pattern.id}:${i}`;
151
+ if (seen.has(key))
152
+ continue;
153
+ seen.add(key);
154
+ findings.push({
155
+ path,
156
+ line: i + 1,
157
+ column: m.index + 1,
158
+ id: pattern.id,
159
+ label: pattern.label,
160
+ severity: pattern.severity,
161
+ masked: maskSecret(value),
162
+ });
163
+ break; // one finding per pattern per line is enough to act on
164
+ }
165
+ }
166
+ }
167
+ return findings;
168
+ }
169
+ // ─── Filesystem walk ────────────────────────────────────────────────────────
170
+ /** Directories that never contain the user's own source. */
171
+ const SKIP_DIRS = new Set([
172
+ '.git', 'node_modules', 'dist', 'build', 'out', 'coverage', 'vendor',
173
+ '.next', '.nuxt', '.svelte-kit', '__pycache__', '.venv', 'venv', '.tox',
174
+ '.cache', '.turbo', 'target', '.idea', '.vscode', 'Pods', '.gradle',
175
+ ]);
176
+ /** Extensions that are binary or generated — reading them wastes time and noise. */
177
+ const SKIP_EXTENSIONS = new Set([
178
+ 'png', 'jpg', 'jpeg', 'gif', 'webp', 'ico', 'bmp', 'svg', 'pdf', 'zip', 'gz',
179
+ 'tar', 'tgz', 'bz2', '7z', 'rar', 'jar', 'war', 'class', 'exe', 'dll', 'so',
180
+ 'dylib', 'bin', 'o', 'a', 'wasm', 'mp3', 'mp4', 'mov', 'avi', 'wav', 'woff',
181
+ 'woff2', 'ttf', 'eot', 'otf', 'map', 'lock', 'pyc', 'pyo', 'snap',
182
+ ]);
183
+ /** Per-file read cap. A secret never hides beyond this; a minified bundle does. */
184
+ export const MAX_FILE_BYTES = 1_000_000;
185
+ /** Default cap on files visited per scan, so a huge monorepo cannot hang a turn. */
186
+ export const DEFAULT_MAX_FILES = 5_000;
187
+ /** Should this workspace-relative path be skipped? (exported for tests) */
188
+ export function shouldSkipPath(relPath) {
189
+ const parts = relPath.split(/[\\/]/);
190
+ if (parts.some((p) => SKIP_DIRS.has(p)))
191
+ return true;
192
+ const base = parts[parts.length - 1] ?? '';
193
+ const dot = base.lastIndexOf('.');
194
+ if (dot > 0) {
195
+ const ext = base.slice(dot + 1).toLowerCase();
196
+ if (SKIP_EXTENSIONS.has(ext))
197
+ return true;
198
+ }
199
+ return false;
200
+ }
201
+ /**
202
+ * Scan a directory tree for secret-shaped content.
203
+ *
204
+ * The walk is bounded twice (file count + per-file size) and skips binary dirs
205
+ * and generated artifacts. Findings carry a WORKSPACE-RELATIVE path so a report
206
+ * can be pasted into a ticket without leaking the operator's home directory.
207
+ * Read failures are counted as skipped, never thrown — a scan must not die on
208
+ * one unreadable file.
209
+ */
210
+ export function scanDirectory(root, options = {}) {
211
+ const maxFiles = options.maxFiles ?? DEFAULT_MAX_FILES;
212
+ const maxFileBytes = options.maxFileBytes ?? MAX_FILE_BYTES;
213
+ const start = options.subdir ? join(root, options.subdir) : root;
214
+ const findings = [];
215
+ let filesScanned = 0;
216
+ let filesSkipped = 0;
217
+ let truncated = false;
218
+ const walk = (dir) => {
219
+ if (truncated)
220
+ return;
221
+ let entries;
222
+ try {
223
+ entries = readdirSync(dir);
224
+ }
225
+ catch {
226
+ filesSkipped += 1;
227
+ return;
228
+ }
229
+ for (const entry of entries) {
230
+ if (truncated)
231
+ return;
232
+ const abs = join(dir, entry);
233
+ let rel;
234
+ try {
235
+ rel = relative(root, abs);
236
+ }
237
+ catch {
238
+ filesSkipped += 1;
239
+ continue;
240
+ }
241
+ if (shouldSkipPath(rel)) {
242
+ filesSkipped += 1;
243
+ continue;
244
+ }
245
+ let st;
246
+ try {
247
+ st = statSync(abs);
248
+ }
249
+ catch {
250
+ filesSkipped += 1;
251
+ continue;
252
+ }
253
+ if (st.isDirectory()) {
254
+ walk(abs);
255
+ continue;
256
+ }
257
+ if (!st.isFile()) {
258
+ filesSkipped += 1;
259
+ continue;
260
+ }
261
+ if (filesScanned >= maxFiles) {
262
+ truncated = true;
263
+ return;
264
+ }
265
+ if (st.size > maxFileBytes) {
266
+ filesSkipped += 1;
267
+ continue;
268
+ }
269
+ let body;
270
+ try {
271
+ body = readFileSync(abs, 'utf-8');
272
+ }
273
+ catch {
274
+ filesSkipped += 1;
275
+ continue;
276
+ }
277
+ filesScanned += 1;
278
+ for (const hit of scanText(body, rel.split(sep).join('/'))) {
279
+ const lineText = body.split(/\r?\n/)[hit.line - 1] ?? '';
280
+ findings.push({ ...hit, preview: redact(lineText).slice(0, 200) });
281
+ }
282
+ }
283
+ };
284
+ walk(start);
285
+ const bySeverity = { critical: 0, high: 0, medium: 0 };
286
+ for (const f of findings)
287
+ bySeverity[f.severity] += 1;
288
+ return {
289
+ root,
290
+ filesScanned,
291
+ filesSkipped,
292
+ truncated,
293
+ findings: findings.sort((a, b) => a.path.localeCompare(b.path) || a.line - b.line),
294
+ bySeverity,
295
+ summary: buildSummary(findings, bySeverity, filesScanned, truncated),
296
+ };
297
+ }
298
+ // ─── Git history scan ───────────────────────────────────────────────────────
299
+ //
300
+ // The working-tree scan answers "is a key staged right now?". The other half of
301
+ // the same worry is "was a key ever COMMITTED?" — a key deleted in a later
302
+ // commit is still in the object store, still cloneable, still valid until it is
303
+ // rotated. This walks the reachable blobs (every version of every file) rather
304
+ // than the diff, so a secret that was added and later removed is still found at
305
+ // the commit that introduced it. Bounded the same way as the tree walk, and
306
+ // entirely local (`git` only — no network, no vendor binary).
307
+ /** Default cap on commits walked. */
308
+ export const DEFAULT_MAX_HISTORY_COMMITS = 500;
309
+ /** Default cap on distinct blobs read, so a huge history cannot hang a turn. */
310
+ export const DEFAULT_MAX_HISTORY_BLOBS = 2_000;
311
+ /** Per-blob read cap (mirrors MAX_FILE_BYTES). */
312
+ export const MAX_HISTORY_BLOB_BYTES = MAX_FILE_BYTES;
313
+ /** Run a git command in `root`; null on any failure (git absent, not a repo…). */
314
+ function runGit(root, args, input, maxBuffer = 256 * 1024 * 1024) {
315
+ try {
316
+ return execFileSync('git', args, {
317
+ cwd: root,
318
+ input,
319
+ maxBuffer,
320
+ stdio: ['pipe', 'pipe', 'ignore'],
321
+ });
322
+ }
323
+ catch {
324
+ return null;
325
+ }
326
+ }
327
+ /**
328
+ * Scan reachable git history for secret-shaped content.
329
+ *
330
+ * Walks `git rev-list --objects --all` to enumerate every blob version, keeps
331
+ * only blobs whose path survives {@link shouldSkipPath}, reads the small ones
332
+ * through a single batched `git cat-file`, and runs the SAME {@link scanText}
333
+ * detector as the tree scan — one pattern source of truth across both surfaces.
334
+ * A finding's path is labelled `<path>@<commit>` when the introducing commit can
335
+ * be resolved (best-effort; the blob sha stand-in is used otherwise).
336
+ */
337
+ export function scanGitHistory(root, options = {}) {
338
+ const maxCommits = options.maxCommits ?? DEFAULT_MAX_HISTORY_COMMITS;
339
+ const maxBlobs = options.maxBlobs ?? DEFAULT_MAX_HISTORY_BLOBS;
340
+ const maxBlobBytes = options.maxBlobBytes ?? MAX_HISTORY_BLOB_BYTES;
341
+ const empty = (isGitRepo, summary) => ({
342
+ root,
343
+ isGitRepo,
344
+ commitsScanned: 0,
345
+ blobsScanned: 0,
346
+ blobsSkipped: 0,
347
+ truncated: false,
348
+ findings: [],
349
+ bySeverity: { critical: 0, high: 0, medium: 0 },
350
+ summary,
351
+ });
352
+ const inside = runGit(root, ['rev-parse', '--is-inside-work-tree']);
353
+ if (!inside || inside.toString('utf-8').trim() !== 'true') {
354
+ return empty(false, 'Not a git work tree — nothing in history to scan.');
355
+ }
356
+ const totalRaw = runGit(root, ['rev-list', '--count', '--all']);
357
+ const totalCommits = totalRaw ? Number.parseInt(totalRaw.toString('utf-8').trim(), 10) || 0 : 0;
358
+ const commitsScanned = Math.min(totalCommits, maxCommits);
359
+ const pathArgs = options.subdir ? ['--', options.subdir] : [];
360
+ const listed = runGit(root, ['rev-list', '--objects', '--max-count', String(maxCommits), '--all', ...pathArgs]);
361
+ if (!listed) {
362
+ return empty(true, 'Could not read git history (the repository may be corrupt or shallow).');
363
+ }
364
+ // sha → first path seen. Bare lines are commits/trees (no path) — ignored.
365
+ const blobPath = new Map();
366
+ for (const rawLine of listed.toString('utf-8').split('\n')) {
367
+ const line = rawLine.trim();
368
+ if (!line)
369
+ continue;
370
+ const sp = line.indexOf(' ');
371
+ if (sp < 0)
372
+ continue;
373
+ const sha = line.slice(0, sp);
374
+ const path = line.slice(sp + 1).trim();
375
+ if (!path || !sha)
376
+ continue;
377
+ if (shouldSkipPath(path))
378
+ continue;
379
+ if (!blobPath.has(sha))
380
+ blobPath.set(sha, path);
381
+ }
382
+ const allShas = [...blobPath.keys()];
383
+ let truncated = totalCommits > maxCommits || allShas.length > maxBlobs;
384
+ const shas = allShas.slice(0, maxBlobs);
385
+ let blobsSkipped = allShas.length - shas.length;
386
+ // Sizes first (no content), so a huge minified bundle is never read.
387
+ const smallShas = [];
388
+ const sizeOut = runGit(root, ['cat-file', '--batch-check'], shas.join('\n') + '\n');
389
+ if (sizeOut) {
390
+ for (const line of sizeOut.toString('utf-8').split('\n')) {
391
+ const parts = line.trim().split(/\s+/);
392
+ if (parts.length < 3)
393
+ continue;
394
+ const [sha, type, sizeStr] = parts;
395
+ const size = Number.parseInt(sizeStr, 10);
396
+ if (type !== 'blob' || !Number.isFinite(size))
397
+ continue;
398
+ if (size > maxBlobBytes) {
399
+ blobsSkipped += 1;
400
+ continue;
401
+ }
402
+ smallShas.push(sha);
403
+ }
404
+ }
405
+ else {
406
+ blobsSkipped += shas.length;
407
+ }
408
+ // Read the small blobs in bounded chunks through one batched cat-file.
409
+ const findings = [];
410
+ let blobsScanned = 0;
411
+ const CHUNK = 500;
412
+ for (let i = 0; i < smallShas.length; i += CHUNK) {
413
+ const chunk = smallShas.slice(i, i + CHUNK);
414
+ const out = runGit(root, ['cat-file', '--batch'], chunk.join('\n') + '\n');
415
+ if (!out) {
416
+ blobsSkipped += chunk.length;
417
+ continue;
418
+ }
419
+ let pos = 0;
420
+ while (pos < out.length) {
421
+ const nl = out.indexOf(10, pos);
422
+ if (nl < 0)
423
+ break;
424
+ const header = out.toString('utf-8', pos, nl);
425
+ pos = nl + 1;
426
+ const [sha, type, sizeStr] = header.split(' ');
427
+ const size = Number.parseInt(sizeStr, 10);
428
+ if (!sha || type !== 'blob' || !Number.isFinite(size))
429
+ break;
430
+ const content = out.toString('utf-8', pos, pos + size);
431
+ pos += size + 1; // skip the content and its trailing newline
432
+ blobsScanned += 1;
433
+ const path = blobPath.get(sha) ?? sha;
434
+ for (const hit of scanText(content, path)) {
435
+ const lineText = content.split(/\r?\n/)[hit.line - 1] ?? '';
436
+ findings.push({ ...hit, preview: redact(lineText).slice(0, 200) });
437
+ }
438
+ }
439
+ }
440
+ // Best-effort: name the commit that introduced each finding-bearing blob, so
441
+ // the report says WHICH commit to rewrite. Done only for blobs with findings.
442
+ const findingBlobs = new Set(findings.map((f) => f.path));
443
+ const commitByPath = new Map();
444
+ for (const [sha, path] of blobPath) {
445
+ if (!findingBlobs.has(path) || commitByPath.has(path))
446
+ continue;
447
+ const log = runGit(root, ['log', '--all', '-1', '--format=%h', `--find-object=${sha}`]);
448
+ const commit = log?.toString('utf-8').trim().split('\n')[0] || undefined;
449
+ if (commit)
450
+ commitByPath.set(path, commit);
451
+ }
452
+ for (const f of findings) {
453
+ const commit = commitByPath.get(f.path);
454
+ if (commit)
455
+ f.commit = commit;
456
+ }
457
+ const bySeverity = { critical: 0, high: 0, medium: 0 };
458
+ for (const f of findings)
459
+ bySeverity[f.severity] += 1;
460
+ findings.sort((a, b) => a.path.localeCompare(b.path) || a.line - b.line);
461
+ return {
462
+ root,
463
+ isGitRepo: true,
464
+ commitsScanned,
465
+ blobsScanned,
466
+ blobsSkipped,
467
+ truncated,
468
+ findings,
469
+ bySeverity,
470
+ summary: buildHistorySummary(findings, bySeverity, commitsScanned, blobsScanned, truncated),
471
+ };
472
+ }
473
+ /** One honest sentence for a history scan — never overclaims a clean result. */
474
+ function buildHistorySummary(findings, bySeverity, commitsScanned, blobsScanned, truncated) {
475
+ const suffix = truncated ? ' (cap reached — coverage is partial)' : '';
476
+ const base = `Walked ${commitsScanned} commit(s), ${blobsScanned} blob(s)${suffix}`;
477
+ if (findings.length === 0) {
478
+ return `${base}: nothing matched a known secret shape in history. ` +
479
+ 'This is a lint, not a guarantee. A key only in a rewritten-away object is still reachable until `git gc`.';
480
+ }
481
+ return (`${base}: ${findings.length} historical finding(s) — ` +
482
+ `${bySeverity.critical} critical, ${bySeverity.high} high, ${bySeverity.medium} medium. ` +
483
+ 'A committed secret must be ROTATED, not just deleted: it stays in the object store. Values are masked.');
484
+ }
485
+ /** Render a git-history result as a compact report a model or human can act on. */
486
+ export function formatSecretHistoryScan(result) {
487
+ const lines = [result.summary];
488
+ if (result.findings.length > 0) {
489
+ lines.push('', 'path commit severity kind value(masked)');
490
+ for (const f of result.findings.slice(0, 200)) {
491
+ lines.push(`${f.path} ${f.commit ?? '?'} ${f.severity} ${f.label} ${f.masked}`);
492
+ }
493
+ if (result.findings.length > 200) {
494
+ lines.push(`… and ${result.findings.length - 200} more`);
495
+ }
496
+ }
497
+ return lines.join('\n');
498
+ }
499
+ /** One honest sentence. A clean scan is reported as "nothing matched". */
500
+ function buildSummary(findings, bySeverity, filesScanned, truncated) {
501
+ const suffix = truncated ? ' (file cap reached — coverage is partial)' : '';
502
+ if (findings.length === 0) {
503
+ return `Scanned ${filesScanned} file(s)${suffix}: nothing matched a known secret shape. ` +
504
+ 'This is a lint, not a guarantee — it finds known shapes and common assignments only.';
505
+ }
506
+ return (`Scanned ${filesScanned} file(s)${suffix}: ${findings.length} finding(s) — ` +
507
+ `${bySeverity.critical} critical, ${bySeverity.high} high, ${bySeverity.medium} medium. ` +
508
+ 'Values are masked; rotate any that are real before they are committed.');
509
+ }
510
+ // ─── Rendering ──────────────────────────────────────────────────────────────
511
+ /** Render a result as a compact report a model or a human can act on. */
512
+ export function formatSecretScan(result) {
513
+ const lines = [result.summary];
514
+ if (result.findings.length > 0) {
515
+ lines.push('', 'path:line severity kind value(masked)');
516
+ for (const f of result.findings.slice(0, 200)) {
517
+ lines.push(`${f.path}:${f.line} ${f.severity} ${f.label} ${f.masked}`);
518
+ }
519
+ if (result.findings.length > 200) {
520
+ lines.push(`… and ${result.findings.length - 200} more`);
521
+ }
522
+ }
523
+ return lines.join('\n');
524
+ }
525
+ //# sourceMappingURL=secret-scan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secret-scan.js","sourceRoot":"","sources":["../../src/security/secret-scan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC9D,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AA4ClF,+EAA+E;AAE/E;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,eAAe,GAAoB;IAC9C,EAAE,EAAE,EAAE,aAAa,EAAE,KAAK,EAAE,mBAAmB,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE,0CAA0C,EAAE;IACvH,EAAE,EAAE,EAAE,mBAAmB,EAAE,KAAK,EAAE,mBAAmB,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE,gCAAgC,EAAE;IACnH,EAAE,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,uBAAuB,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE,4EAA4E,EAAE;IAC5J,EAAE,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE,iCAAiC,EAAE;IACxG,EAAE,EAAE,EAAE,iBAAiB,EAAE,KAAK,EAAE,2BAA2B,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE,mCAAmC,EAAE;IAC5H,EAAE,EAAE,EAAE,eAAe,EAAE,KAAK,EAAE,mBAAmB,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE,gCAAgC,EAAE;IAC/G,EAAE,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,2BAA2B,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE,kCAAkC,EAAE;IACtH,EAAE,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE,2BAA2B,EAAE;IAChG,EAAE,EAAE,EAAE,gBAAgB,EAAE,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE,4BAA4B,EAAE;IACzG,EAAE,EAAE,EAAE,qBAAqB,EAAE,KAAK,EAAE,4BAA4B,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE,gCAAgC,EAAE;IAC9H,EAAE,EAAE,EAAE,gBAAgB,EAAE,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE,+BAA+B,EAAE;IAC5G,EAAE,EAAE,EAAE,aAAa,EAAE,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE,mCAAmC,EAAE;IAC1G,EAAE,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,8BAA8B,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE,+CAA+C,EAAE;IACtI,EAAE,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,0BAA0B,EAAE;IAChG,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,2BAA2B,EAAE;IAC1F,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,oBAAoB,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,iEAAiE,EAAE;IACnI;QACE,EAAE,EAAE,iBAAiB;QACrB,KAAK,EAAE,+BAA+B;QACtC,QAAQ,EAAE,MAAM;QAChB,EAAE,EAAE,kEAAkE;KACvE;CACF,CAAC;AAEF;;;;GAIG;AACH,SAAS,mBAAmB;IAC1B,uEAAuE;IACvE,4DAA4D;IAC5D,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;IACjG,OAAO,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QACxE,EAAE,EAAE,UAAU,MAAM,EAAE;QACtB,KAAK,EAAE,qBAAqB,MAAM,GAAG;QACrC,QAAQ,EAAE,QAA0B;QACpC,EAAE,EAAE,IAAI,MAAM,CAAC,MAAM,MAAM,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,yBAAyB,EAAE,GAAG,CAAC;KAClG,CAAC,CAAC,CAAC;AACN,CAAC;AAED,MAAM,YAAY,GAAoB,CAAC,GAAG,eAAe,EAAE,GAAG,mBAAmB,EAAE,CAAC,CAAC;AAErF;;;;GAIG;AACH,MAAM,cAAc,GAAkB;IACpC,EAAE,EAAE,iBAAiB;IACrB,KAAK,EAAE,mDAAmD;IAC1D,QAAQ,EAAE,QAAQ;IAClB,EAAE,EAAE,uMAAuM;CAC5M,CAAC;AAEF,2EAA2E;AAC3E,MAAM,cAAc,GAAG,yHAAyH,CAAC;AACjJ,MAAM,WAAW,GAAG,QAAQ,CAAC,CAAC,mEAAmE;AACjG,MAAM,cAAc,GAAG,UAAU,CAAC,CAAC,mBAAmB;AAEtD,+EAA+E;AAC/E,MAAM,UAAU,oBAAoB,CAAC,KAAa;IAChD,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IACvB,IAAI,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACpB,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAC9B,IAAI,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACxC,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACrC,IAAI,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACxC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5C,0EAA0E;QAC1E,sEAAsE;QACtE,wCAAwC;QACxC,IAAI,CAAC,CAAC,MAAM,GAAG,EAAE;YAAE,OAAO,IAAI,CAAC;IACjC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,+EAA+E;AAE/E;;;;;;GAMG;AACH,MAAM,UAAU,QAAQ,CAAC,IAAY,EAAE,IAAI,GAAG,QAAQ;IACpD,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,CAAC;IACrB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAClC,MAAM,QAAQ,GAAqC,EAAE,CAAC;IACtD,2EAA2E;IAC3E,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACzC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QAEzC,KAAK,MAAM,OAAO,IAAI,CAAC,GAAG,YAAY,EAAE,cAAc,CAAC,EAAE,CAAC;YACxD,OAAO,CAAC,EAAE,CAAC,SAAS,GAAG,CAAC,CAAC;YACzB,IAAI,CAAyB,CAAC;YAC9B,OAAO,CAAC,CAAC,GAAG,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;gBAC5C,kEAAkE;gBAClE,qDAAqD;gBACrD,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC3B,IAAI,oBAAoB,CAAC,KAAK,CAAC,EAAE,CAAC;oBAChC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC;wBAAE,OAAO,CAAC,EAAE,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,qBAAqB;oBACvE,SAAS;gBACX,CAAC;gBACD,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC;gBACjC,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;oBAAE,SAAS;gBAC5B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBACd,QAAQ,CAAC,IAAI,CAAC;oBACZ,IAAI;oBACJ,IAAI,EAAE,CAAC,GAAG,CAAC;oBACX,MAAM,EAAE,CAAC,CAAC,KAAK,GAAG,CAAC;oBACnB,EAAE,EAAE,OAAO,CAAC,EAAE;oBACd,KAAK,EAAE,OAAO,CAAC,KAAK;oBACpB,QAAQ,EAAE,OAAO,CAAC,QAAQ;oBAC1B,MAAM,EAAE,UAAU,CAAC,KAAK,CAAC;iBAC1B,CAAC,CAAC;gBACH,MAAM,CAAC,uDAAuD;YAChE,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,+EAA+E;AAE/E,4DAA4D;AAC5D,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC;IACxB,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ;IACpE,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM;IACvE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS;CACpE,CAAC,CAAC;AAEH,oFAAoF;AACpF,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC;IAC9B,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI;IAC5E,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI;IAC3E,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM;IAC3E,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM;CAClE,CAAC,CAAC;AAEH,mFAAmF;AACnF,MAAM,CAAC,MAAM,cAAc,GAAG,SAAS,CAAC;AACxC,oFAAoF;AACpF,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,CAAC;AAEvC,2EAA2E;AAC3E,MAAM,UAAU,cAAc,CAAC,OAAe;IAC5C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACrC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACrD,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAC3C,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAClC,IAAI,GAAG,GAAG,CAAC,EAAE,CAAC;QACZ,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QAC9C,IAAI,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;IAC5C,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAWD;;;;;;;;GAQG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,UAAgC,EAAE;IAC5E,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,iBAAiB,CAAC;IACvD,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,cAAc,CAAC;IAC5D,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAEjE,MAAM,QAAQ,GAAoB,EAAE,CAAC;IACrC,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,IAAI,SAAS,GAAG,KAAK,CAAC;IAEtB,MAAM,IAAI,GAAG,CAAC,GAAW,EAAQ,EAAE;QACjC,IAAI,SAAS;YAAE,OAAO;QACtB,IAAI,OAAiB,CAAC;QACtB,IAAI,CAAC;YACH,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;QAC7B,CAAC;QAAC,MAAM,CAAC;YACP,YAAY,IAAI,CAAC,CAAC;YAClB,OAAO;QACT,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,SAAS;gBAAE,OAAO;YACtB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YAC7B,IAAI,GAAW,CAAC;YAChB,IAAI,CAAC;gBACH,GAAG,GAAG,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YAC5B,CAAC;YAAC,MAAM,CAAC;gBACP,YAAY,IAAI,CAAC,CAAC;gBAClB,SAAS;YACX,CAAC;YACD,IAAI,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC;gBACxB,YAAY,IAAI,CAAC,CAAC;gBAClB,SAAS;YACX,CAAC;YACD,IAAI,EAAE,CAAC;YACP,IAAI,CAAC;gBACH,EAAE,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;YACrB,CAAC;YAAC,MAAM,CAAC;gBACP,YAAY,IAAI,CAAC,CAAC;gBAClB,SAAS;YACX,CAAC;YACD,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;gBACrB,IAAI,CAAC,GAAG,CAAC,CAAC;gBACV,SAAS;YACX,CAAC;YACD,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC;gBACjB,YAAY,IAAI,CAAC,CAAC;gBAClB,SAAS;YACX,CAAC;YACD,IAAI,YAAY,IAAI,QAAQ,EAAE,CAAC;gBAC7B,SAAS,GAAG,IAAI,CAAC;gBACjB,OAAO;YACT,CAAC;YACD,IAAI,EAAE,CAAC,IAAI,GAAG,YAAY,EAAE,CAAC;gBAC3B,YAAY,IAAI,CAAC,CAAC;gBAClB,SAAS;YACX,CAAC;YACD,IAAI,IAAY,CAAC;YACjB,IAAI,CAAC;gBACH,IAAI,GAAG,YAAY,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;YACpC,CAAC;YAAC,MAAM,CAAC;gBACP,YAAY,IAAI,CAAC,CAAC;gBAClB,SAAS;YACX,CAAC;YACD,YAAY,IAAI,CAAC,CAAC;YAClB,KAAK,MAAM,GAAG,IAAI,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;gBAC3D,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;gBACzD,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;YACrE,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IAEF,IAAI,CAAC,KAAK,CAAC,CAAC;IAEZ,MAAM,UAAU,GAAmC,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;IACvF,KAAK,MAAM,CAAC,IAAI,QAAQ;QAAE,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAEtD,OAAO;QACL,IAAI;QACJ,YAAY;QACZ,YAAY;QACZ,SAAS;QACT,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC;QAClF,UAAU;QACV,OAAO,EAAE,YAAY,CAAC,QAAQ,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,CAAC;KACrE,CAAC;AACJ,CAAC;AAED,+EAA+E;AAC/E,EAAE;AACF,gFAAgF;AAChF,2EAA2E;AAC3E,gFAAgF;AAChF,+EAA+E;AAC/E,gFAAgF;AAChF,4EAA4E;AAC5E,8DAA8D;AAE9D,qCAAqC;AACrC,MAAM,CAAC,MAAM,2BAA2B,GAAG,GAAG,CAAC;AAC/C,gFAAgF;AAChF,MAAM,CAAC,MAAM,yBAAyB,GAAG,KAAK,CAAC;AAC/C,kDAAkD;AAClD,MAAM,CAAC,MAAM,sBAAsB,GAAG,cAAc,CAAC;AAiCrD,kFAAkF;AAClF,SAAS,MAAM,CAAC,IAAY,EAAE,IAAc,EAAE,KAAc,EAAE,SAAS,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI;IACzF,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,KAAK,EAAE,IAAI,EAAE;YAC/B,GAAG,EAAE,IAAI;YACT,KAAK;YACL,SAAS;YACT,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC;SAClC,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,UAA8B,EAAE;IAC3E,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,2BAA2B,CAAC;IACrE,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,yBAAyB,CAAC;IAC/D,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,sBAAsB,CAAC;IAEpE,MAAM,KAAK,GAAG,CAAC,SAAkB,EAAE,OAAe,EAA2B,EAAE,CAAC,CAAC;QAC/E,IAAI;QACJ,SAAS;QACT,cAAc,EAAE,CAAC;QACjB,YAAY,EAAE,CAAC;QACf,YAAY,EAAE,CAAC;QACf,SAAS,EAAE,KAAK;QAChB,QAAQ,EAAE,EAAE;QACZ,UAAU,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE;QAC/C,OAAO;KACR,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,uBAAuB,CAAC,CAAC,CAAC;IACpE,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,MAAM,EAAE,CAAC;QAC1D,OAAO,KAAK,CAAC,KAAK,EAAE,mDAAmD,CAAC,CAAC;IAC3E,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,UAAU,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;IAChE,MAAM,YAAY,GAAG,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAChG,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;IAE1D,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9D,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,UAAU,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC;IAChH,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,KAAK,CAAC,IAAI,EAAE,wEAAwE,CAAC,CAAC;IAC/F,CAAC;IAED,2EAA2E;IAC3E,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC3C,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3D,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,IAAI;YAAE,SAAS;QACpB,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,EAAE,GAAG,CAAC;YAAE,SAAS;QACrB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACvC,IAAI,CAAC,IAAI,IAAI,CAAC,GAAG;YAAE,SAAS;QAC5B,IAAI,cAAc,CAAC,IAAI,CAAC;YAAE,SAAS;QACnC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAClD,CAAC;IAED,MAAM,OAAO,GAAG,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IACrC,IAAI,SAAS,GAAG,YAAY,GAAG,UAAU,IAAI,OAAO,CAAC,MAAM,GAAG,QAAQ,CAAC;IACvE,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;IACxC,IAAI,YAAY,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IAEhD,qEAAqE;IACrE,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,UAAU,EAAE,eAAe,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IACpF,IAAI,OAAO,EAAE,CAAC;QACZ,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YACzD,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACvC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;gBAAE,SAAS;YAC/B,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,KAAK,CAAC;YACnC,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YAC1C,IAAI,IAAI,KAAK,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;gBAAE,SAAS;YACxD,IAAI,IAAI,GAAG,YAAY,EAAE,CAAC;gBACxB,YAAY,IAAI,CAAC,CAAC;gBAClB,SAAS;YACX,CAAC;YACD,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;SAAM,CAAC;QACN,YAAY,IAAI,IAAI,CAAC,MAAM,CAAC;IAC9B,CAAC;IAED,uEAAuE;IACvE,MAAM,QAAQ,GAAqB,EAAE,CAAC;IACtC,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,MAAM,KAAK,GAAG,GAAG,CAAC;IAClB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC;QACjD,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC;QAC5C,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;QAC3E,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,YAAY,IAAI,KAAK,CAAC,MAAM,CAAC;YAC7B,SAAS;QACX,CAAC;QACD,IAAI,GAAG,GAAG,CAAC,CAAC;QACZ,OAAO,GAAG,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC;YACxB,MAAM,EAAE,GAAG,GAAG,CAAC,OAAO,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YAChC,IAAI,EAAE,GAAG,CAAC;gBAAE,MAAM;YAClB,MAAM,MAAM,GAAG,GAAG,CAAC,QAAQ,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;YAC9C,GAAG,GAAG,EAAE,GAAG,CAAC,CAAC;YACb,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC/C,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YAC1C,IAAI,CAAC,GAAG,IAAI,IAAI,KAAK,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;gBAAE,MAAM;YAC7D,MAAM,OAAO,GAAG,GAAG,CAAC,QAAQ,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,GAAG,IAAI,CAAC,CAAC;YACvD,GAAG,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,4CAA4C;YAC7D,YAAY,IAAI,CAAC,CAAC;YAClB,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC;YACtC,KAAK,MAAM,GAAG,IAAI,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC;gBAC1C,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;gBAC5D,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;YACrE,CAAC;QACH,CAAC;IACH,CAAC;IAED,6EAA6E;IAC7E,8EAA8E;IAC9E,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1D,MAAM,YAAY,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC/C,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,QAAQ,EAAE,CAAC;QACnC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,SAAS;QAChE,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,iBAAiB,GAAG,EAAE,CAAC,CAAC,CAAC;QACxF,MAAM,MAAM,GAAG,GAAG,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC;QACzE,IAAI,MAAM;YAAE,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC7C,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,MAAM;YAAE,CAAC,CAAC,MAAM,GAAG,MAAM,CAAC;IAChC,CAAC;IAED,MAAM,UAAU,GAAmC,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;IACvF,KAAK,MAAM,CAAC,IAAI,QAAQ;QAAE,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAEtD,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;IAEzE,OAAO;QACL,IAAI;QACJ,SAAS,EAAE,IAAI;QACf,cAAc;QACd,YAAY;QACZ,YAAY;QACZ,SAAS;QACT,QAAQ;QACR,UAAU;QACV,OAAO,EAAE,mBAAmB,CAAC,QAAQ,EAAE,UAAU,EAAE,cAAc,EAAE,YAAY,EAAE,SAAS,CAAC;KAC5F,CAAC;AACJ,CAAC;AAED,gFAAgF;AAChF,SAAS,mBAAmB,CAC1B,QAA0B,EAC1B,UAA0C,EAC1C,cAAsB,EACtB,YAAoB,EACpB,SAAkB;IAElB,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,sCAAsC,CAAC,CAAC,CAAC,EAAE,CAAC;IACvE,MAAM,IAAI,GAAG,UAAU,cAAc,eAAe,YAAY,WAAW,MAAM,EAAE,CAAC;IACpF,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,GAAG,IAAI,qDAAqD;YACjE,2GAA2G,CAAC;IAChH,CAAC;IACD,OAAO,CACL,GAAG,IAAI,KAAK,QAAQ,CAAC,MAAM,2BAA2B;QACtD,GAAG,UAAU,CAAC,QAAQ,cAAc,UAAU,CAAC,IAAI,UAAU,UAAU,CAAC,MAAM,WAAW;QACzF,wGAAwG,CACzG,CAAC;AACJ,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,uBAAuB,CAAC,MAA+B;IACrE,MAAM,KAAK,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC/B,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,6CAA6C,CAAC,CAAC;QAC9D,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;YAC9C,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;QACtF,CAAC;QACD,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;YACjC,KAAK,CAAC,IAAI,CAAC,SAAS,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,0EAA0E;AAC1E,SAAS,YAAY,CACnB,QAAyB,EACzB,UAA0C,EAC1C,YAAoB,EACpB,SAAkB;IAElB,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,2CAA2C,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5E,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,WAAW,YAAY,WAAW,MAAM,0CAA0C;YACvF,sFAAsF,CAAC;IAC3F,CAAC;IACD,OAAO,CACL,WAAW,YAAY,WAAW,MAAM,KAAK,QAAQ,CAAC,MAAM,gBAAgB;QAC5E,GAAG,UAAU,CAAC,QAAQ,cAAc,UAAU,CAAC,IAAI,UAAU,UAAU,CAAC,MAAM,WAAW;QACzF,wEAAwE,CACzE,CAAC;AACJ,CAAC;AAED,+EAA+E;AAE/E,yEAAyE;AACzE,MAAM,UAAU,gBAAgB,CAAC,MAAwB;IACvD,MAAM,KAAK,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC/B,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,0CAA0C,CAAC,CAAC;QAC3D,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;YAC9C,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;QAC5E,CAAC;QACD,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;YACjC,KAAK,CAAC,IAAI,CAAC,SAAS,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
@@ -81,6 +81,12 @@ export interface PlanStoreLike {
81
81
  description: string;
82
82
  }>): Plan;
83
83
  update(id: string, status: PlanStepStatus, note?: string): Plan | null;
84
+ /**
85
+ * Map a model-supplied step reference onto a real step id, or null when it
86
+ * names nothing in the plan. `plan_todo` calls this BEFORE `update` so an
87
+ * unknown reference is reported instead of silently doing nothing (A1).
88
+ */
89
+ resolveStepId?(id: string): string | null;
84
90
  /** Structured GUI snapshot (plan_todo emits it via plan:changed). */
85
91
  toGUI?(): PlanSnapshot | null;
86
92
  /** Human-readable checklist text (the model's tool result). */
@@ -125,11 +131,27 @@ export declare class PlanStore implements PlanStoreLike {
125
131
  id: string;
126
132
  description: string;
127
133
  }>): Plan;
134
+ /**
135
+ * Resolve a step reference the model sent to a real step id.
136
+ *
137
+ * Models are inconsistent about how they name a step: the schema examples
138
+ * are `step-1`/`reproduce`, but a live run's model addressed steps by bare
139
+ * ordinal (`2`, `3`) while it had created them as `step-2` (observed on the
140
+ * `cal` Android run, 2026-10-05 — the one-update that matched advanced the
141
+ * plan, every later update was a silent no-op and the checklist froze at
142
+ * `1/7`). Accept, in order: the exact id, the id with an optional
143
+ * `step`/`step-`/`#` prefix stripped (either side), and a 1-based ordinal
144
+ * when the reference is a plain integer inside range. Case-insensitive.
145
+ */
146
+ resolveStepId(id: string): string | null;
128
147
  /**
129
148
  * Mark one step's status (and optionally record a plain-English note about
130
- * it). Unknown id → no-op (returns the unchanged plan).
149
+ * it). The reference is resolved through {@link resolveStepId} first, so a
150
+ * model that addressed `3` when the step is `step-3` still advances the
151
+ * plan. Unknown reference → no-op (returns the unchanged plan); callers that
152
+ * need to tell the two apart resolve first.
131
153
  */
132
- update(id: string, status: PlanStepStatus, note?: string): Plan | null;
154
+ update(reference: string, status: PlanStepStatus, note?: string): Plan | null;
133
155
  /** A single, shared progress computation for every renderer. */
134
156
  progress(): PlanProgress;
135
157
  /** The step being worked right now (the first `running` one), or null. */
@@ -1 +1 @@
1
- {"version":3,"file":"plan-store.d.ts","sourceRoot":"","sources":["../../src/tools/plan-store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"plan-store.d.ts","sourceRoot":"","sources":["../../src/tools/plan-store.ts"],"names":[],"mappings":"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"}