@jpkme/diff-review 0.1.15 → 0.1.16

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 (127) hide show
  1. package/lib/acp-policy.mjs +10 -2
  2. package/lib/acp-policy.test.mjs +27 -0
  3. package/lib/output-name.mjs +7 -0
  4. package/lib/prompt.mjs +3 -2
  5. package/lib/prompt.test.mjs +37 -0
  6. package/lib/review-dir.mjs +14 -1
  7. package/lib/review.mjs +36 -4
  8. package/lib/review.test.mjs +35 -0
  9. package/lib/validate.mjs +10 -0
  10. package/lib/validate.test.mjs +47 -0
  11. package/package.json +1 -1
  12. package/schema.json +16 -1
  13. package/web/build/client/_app/immutable/assets/3.DB-bJJq2.css +1 -0
  14. package/web/build/client/_app/immutable/assets/3.DB-bJJq2.css.br +0 -0
  15. package/web/build/client/_app/immutable/assets/3.DB-bJJq2.css.gz +0 -0
  16. package/web/build/client/_app/immutable/assets/{storage.TlsiS-AP.css → storage.BxR6930R.css} +1 -1
  17. package/web/build/client/_app/immutable/assets/storage.BxR6930R.css.br +0 -0
  18. package/web/build/client/_app/immutable/assets/{storage.TlsiS-AP.css.gz → storage.BxR6930R.css.gz} +0 -0
  19. package/web/build/client/_app/immutable/chunks/BLMWhW3J.js +1 -0
  20. package/web/build/client/_app/immutable/chunks/BLMWhW3J.js.br +1 -0
  21. package/web/build/client/_app/immutable/chunks/BLMWhW3J.js.gz +0 -0
  22. package/web/build/client/_app/immutable/chunks/{D8WOD_eS.js → CXhIC34H.js} +1 -1
  23. package/web/build/client/_app/immutable/chunks/CXhIC34H.js.br +0 -0
  24. package/web/build/client/_app/immutable/chunks/CXhIC34H.js.gz +0 -0
  25. package/web/build/client/_app/immutable/chunks/DHO7NTh1.js +2 -0
  26. package/web/build/client/_app/immutable/chunks/DHO7NTh1.js.br +0 -0
  27. package/web/build/client/_app/immutable/chunks/DHO7NTh1.js.gz +0 -0
  28. package/web/build/client/_app/immutable/chunks/DpxY75GB.js +215 -0
  29. package/web/build/client/_app/immutable/chunks/DpxY75GB.js.br +0 -0
  30. package/web/build/client/_app/immutable/chunks/DpxY75GB.js.gz +0 -0
  31. package/web/build/client/_app/immutable/chunks/{BpVtXA-T.js → cYiFfRa3.js} +1 -1
  32. package/web/build/client/_app/immutable/chunks/cYiFfRa3.js.br +1 -0
  33. package/web/build/client/_app/immutable/chunks/cYiFfRa3.js.gz +0 -0
  34. package/web/build/client/_app/immutable/entry/{app.BjJsHui4.js → app.CCv57mvp.js} +2 -2
  35. package/web/build/client/_app/immutable/entry/app.CCv57mvp.js.br +0 -0
  36. package/web/build/client/_app/immutable/entry/app.CCv57mvp.js.gz +0 -0
  37. package/web/build/client/_app/immutable/entry/start.B012TSbW.js +1 -0
  38. package/web/build/client/_app/immutable/entry/start.B012TSbW.js.br +1 -0
  39. package/web/build/client/_app/immutable/entry/start.B012TSbW.js.gz +0 -0
  40. package/web/build/client/_app/immutable/nodes/0.slrnBioC.js +1 -0
  41. package/web/build/client/_app/immutable/nodes/0.slrnBioC.js.br +0 -0
  42. package/web/build/client/_app/immutable/nodes/0.slrnBioC.js.gz +0 -0
  43. package/web/build/client/_app/immutable/nodes/1.Bs5JdO4l.js +1 -0
  44. package/web/build/client/_app/immutable/nodes/1.Bs5JdO4l.js.br +0 -0
  45. package/web/build/client/_app/immutable/nodes/1.Bs5JdO4l.js.gz +0 -0
  46. package/web/build/client/_app/immutable/nodes/2.D5ULH3EX.js +10 -0
  47. package/web/build/client/_app/immutable/nodes/2.D5ULH3EX.js.br +0 -0
  48. package/web/build/client/_app/immutable/nodes/2.D5ULH3EX.js.gz +0 -0
  49. package/web/build/client/_app/immutable/nodes/3.hjzQQgyj.js +173 -0
  50. package/web/build/client/_app/immutable/nodes/3.hjzQQgyj.js.br +0 -0
  51. package/web/build/client/_app/immutable/nodes/3.hjzQQgyj.js.gz +0 -0
  52. package/web/build/client/_app/version.json +1 -1
  53. package/web/build/client/_app/version.json.br +0 -0
  54. package/web/build/client/_app/version.json.gz +0 -0
  55. package/web/build/handler.js +3 -3
  56. package/web/build/index.js +3 -3
  57. package/web/build/server/chunks/{0-DUStDOsr.js → 0-D7NSxn1-.js} +2 -2
  58. package/web/build/server/chunks/{0-DUStDOsr.js.map → 0-D7NSxn1-.js.map} +1 -1
  59. package/web/build/server/chunks/1-DboYz8Fw.js +7 -0
  60. package/web/build/server/chunks/{1-DUj63QTT.js.map → 1-DboYz8Fw.js.map} +1 -1
  61. package/web/build/server/chunks/2-B7LX817Q.js +7 -0
  62. package/web/build/server/chunks/2-B7LX817Q.js.map +1 -0
  63. package/web/build/server/chunks/3-DgJ_LmTL.js +7 -0
  64. package/web/build/server/chunks/{3-C7UD6rei.js.map → 3-DgJ_LmTL.js.map} +1 -1
  65. package/web/build/server/chunks/{_server.ts-4RcoUd0l.js → _server.ts-CP5cRLhW.js} +4 -4
  66. package/web/build/server/chunks/{_server.ts-4RcoUd0l.js.map → _server.ts-CP5cRLhW.js.map} +1 -1
  67. package/web/build/server/chunks/{agent-sessions-C_hlZJKN.js → agent-sessions-2XGojSJ_.js} +84 -15
  68. package/web/build/server/chunks/agent-sessions-2XGojSJ_.js.map +1 -0
  69. package/web/build/server/chunks/{git-review-Bh1w0gak.js → git-review-jZ_JJYfv.js} +36 -8
  70. package/web/build/server/chunks/git-review-jZ_JJYfv.js.map +1 -0
  71. package/web/build/server/chunks/{handler-e2lEvjVT.js → handler-B_8yUXji.js} +3 -3
  72. package/web/build/server/chunks/{handler-e2lEvjVT.js.map → handler-B_8yUXji.js.map} +1 -1
  73. package/web/build/server/chunks/{hooks.server-Um1Sknmz.js → hooks.server-rF_eBCff.js} +3 -3
  74. package/web/build/server/chunks/{hooks.server-Um1Sknmz.js.map → hooks.server-rF_eBCff.js.map} +1 -1
  75. package/web/build/server/chunks/{index.js-C3-YX8SA.js → index.js-CGw8_Q7V.js} +884 -881
  76. package/web/build/server/chunks/index.js-CGw8_Q7V.js.map +1 -0
  77. package/web/build/server/chunks/{manifest.js-CmbRPv0j.js → manifest.js-CImZFS6G.js} +9 -9
  78. package/web/build/server/chunks/{manifest.js-CmbRPv0j.js.map → manifest.js-CImZFS6G.js.map} +1 -1
  79. package/web/build/server/chunks/{remote-1g4ayag-DMiPy1mT.js → remote-1g4ayag-BMpjk8UD.js} +4 -4
  80. package/web/build/server/chunks/{remote-1g4ayag-DMiPy1mT.js.map → remote-1g4ayag-BMpjk8UD.js.map} +1 -1
  81. package/web/build/server/chunks/{remote-wh6t6j-RlIVOUe-.js → remote-wh6t6j-dYLCg8ks.js} +19 -7
  82. package/web/build/server/chunks/remote-wh6t6j-dYLCg8ks.js.map +1 -0
  83. package/web/build/server/chunks/{validate-CAQ31C7k.js → validate-Da6e71V3.js} +34 -5
  84. package/web/build/server/chunks/validate-Da6e71V3.js.map +1 -0
  85. package/web/build/client/_app/immutable/assets/3.Cw1J6YTM.css +0 -1
  86. package/web/build/client/_app/immutable/assets/3.Cw1J6YTM.css.br +0 -0
  87. package/web/build/client/_app/immutable/assets/3.Cw1J6YTM.css.gz +0 -0
  88. package/web/build/client/_app/immutable/assets/storage.TlsiS-AP.css.br +0 -0
  89. package/web/build/client/_app/immutable/chunks/BpVtXA-T.js.br +0 -2
  90. package/web/build/client/_app/immutable/chunks/BpVtXA-T.js.gz +0 -0
  91. package/web/build/client/_app/immutable/chunks/CUhrLa7d.js +0 -210
  92. package/web/build/client/_app/immutable/chunks/CUhrLa7d.js.br +0 -0
  93. package/web/build/client/_app/immutable/chunks/CUhrLa7d.js.gz +0 -0
  94. package/web/build/client/_app/immutable/chunks/D8WOD_eS.js.br +0 -0
  95. package/web/build/client/_app/immutable/chunks/D8WOD_eS.js.gz +0 -0
  96. package/web/build/client/_app/immutable/chunks/QvO6K-HK.js +0 -2
  97. package/web/build/client/_app/immutable/chunks/QvO6K-HK.js.br +0 -0
  98. package/web/build/client/_app/immutable/chunks/QvO6K-HK.js.gz +0 -0
  99. package/web/build/client/_app/immutable/chunks/lUYXRDtZ.js +0 -1
  100. package/web/build/client/_app/immutable/chunks/lUYXRDtZ.js.br +0 -0
  101. package/web/build/client/_app/immutable/chunks/lUYXRDtZ.js.gz +0 -0
  102. package/web/build/client/_app/immutable/entry/app.BjJsHui4.js.br +0 -0
  103. package/web/build/client/_app/immutable/entry/app.BjJsHui4.js.gz +0 -0
  104. package/web/build/client/_app/immutable/entry/start.D4unRHC4.js +0 -1
  105. package/web/build/client/_app/immutable/entry/start.D4unRHC4.js.br +0 -0
  106. package/web/build/client/_app/immutable/entry/start.D4unRHC4.js.gz +0 -0
  107. package/web/build/client/_app/immutable/nodes/0.Dj97JW46.js +0 -1
  108. package/web/build/client/_app/immutable/nodes/0.Dj97JW46.js.br +0 -0
  109. package/web/build/client/_app/immutable/nodes/0.Dj97JW46.js.gz +0 -0
  110. package/web/build/client/_app/immutable/nodes/1.C8JJYlWG.js +0 -1
  111. package/web/build/client/_app/immutable/nodes/1.C8JJYlWG.js.br +0 -1
  112. package/web/build/client/_app/immutable/nodes/1.C8JJYlWG.js.gz +0 -0
  113. package/web/build/client/_app/immutable/nodes/2.CDI0Ipi4.js +0 -10
  114. package/web/build/client/_app/immutable/nodes/2.CDI0Ipi4.js.br +0 -0
  115. package/web/build/client/_app/immutable/nodes/2.CDI0Ipi4.js.gz +0 -0
  116. package/web/build/client/_app/immutable/nodes/3.DVC22CDg.js +0 -171
  117. package/web/build/client/_app/immutable/nodes/3.DVC22CDg.js.br +0 -0
  118. package/web/build/client/_app/immutable/nodes/3.DVC22CDg.js.gz +0 -0
  119. package/web/build/server/chunks/1-DUj63QTT.js +0 -7
  120. package/web/build/server/chunks/2-B4PSKe5P.js +0 -7
  121. package/web/build/server/chunks/2-B4PSKe5P.js.map +0 -1
  122. package/web/build/server/chunks/3-C7UD6rei.js +0 -7
  123. package/web/build/server/chunks/agent-sessions-C_hlZJKN.js.map +0 -1
  124. package/web/build/server/chunks/git-review-Bh1w0gak.js.map +0 -1
  125. package/web/build/server/chunks/index.js-C3-YX8SA.js.map +0 -1
  126. package/web/build/server/chunks/remote-wh6t6j-RlIVOUe-.js.map +0 -1
  127. package/web/build/server/chunks/validate-CAQ31C7k.js.map +0 -1
@@ -13,8 +13,9 @@ import { checkShell } from "./acp-shell.mjs";
13
13
  import { outputRelPath } from "./output-name.mjs";
14
14
 
15
15
  /**
16
- * @typedef {"review" | "ask" | "edit"} PolicyMode
17
- * review = generar el JSON; ask = preguntas (no puede escribir nada); edit = modificar el JSON.
16
+ * @typedef {"review" | "ask" | "edit" | "fix"} PolicyMode
17
+ * review = generar el JSON; ask = preguntas (no puede escribir nada); edit = modificar el JSON;
18
+ * fix = editar código dentro del repo (no solo el JSON).
18
19
  * @typedef {{ repo: string, outputFilename: string, mode: PolicyMode }} PolicyContext
19
20
  * @typedef {{
20
21
  * kind?: string | null,
@@ -190,6 +191,13 @@ export function decidePermission(toolCall, { repo, outputFilename, mode }) {
190
191
  if (kind === "edit" || kind === "delete") {
191
192
  if (mode === "ask") return { allow: false, reason: "modo pregunta: no se edita nada" };
192
193
  if (!paths.length) return { allow: false, reason: `${kind === "delete" ? "borrado" : "edición"} sin path` };
194
+ // fix mode: puede editar cualquier archivo dentro del repo (no solo el JSON de salida como edit mode).
195
+ if (mode === "fix") {
196
+ const outside = paths.find((p) => !isInside(p, repo));
197
+ return outside
198
+ ? { allow: false, reason: `path fuera del repo: ${outside}` }
199
+ : { allow: true, reason: "escritura en el repo" };
200
+ }
193
201
  const target = resolve(repo, outputRelPath(outputFilename));
194
202
  const outside = paths.find((p) => !samePath(canonicalPath(p), canonicalPath(target)));
195
203
  return outside
@@ -87,6 +87,33 @@ test("decidePermission: escritura solo del JSON objetivo, nunca en modo pregunta
87
87
  );
88
88
  });
89
89
 
90
+ test("decidePermission: modo fix permite edit/delete dentro del repo, deniega fuera", () => {
91
+ assert.equal(decidePermission(edit(join(repo, "lib", "a.mjs")), ctx("fix")).allow, true);
92
+ assert.equal(decidePermission(edit("lib/a.mjs"), ctx("fix")).allow, true);
93
+ assert.equal(decidePermission(edit(outPath), ctx("fix")).allow, true);
94
+ const home = process.platform === "win32" ? "C:\\Users\\me\\.ssh\\id_rsa" : "/home/me/.ssh/id_rsa";
95
+ assert.equal(decidePermission(edit(home), ctx("fix")).allow, false);
96
+ assert.equal(decidePermission(edit(join(repo, "..", "otro", "x")), ctx("fix")).allow, false);
97
+ assert.equal(decidePermission({ kind: "edit", title: "Edit", rawInput: {} }, ctx("fix")).allow, false);
98
+ assert.equal(
99
+ decidePermission(
100
+ { kind: "delete", title: "Delete", rawInput: { path: join(repo, "lib", "a.mjs") }, locations: [{ path: join(repo, "lib", "a.mjs") }] },
101
+ ctx("fix")
102
+ ).allow,
103
+ true
104
+ );
105
+ assert.equal(
106
+ decidePermission(
107
+ { kind: "delete", title: "Delete", rawInput: { path: home }, locations: [{ path: home }] },
108
+ ctx("fix")
109
+ ).allow,
110
+ false
111
+ );
112
+ // ask/edit JSON sin regresiones frente a paths de código.
113
+ assert.equal(decidePermission(edit(join(repo, "lib", "a.mjs")), ctx("ask")).allow, false);
114
+ assert.equal(decidePermission(edit(join(repo, "lib", "a.mjs")), ctx("edit")).allow, false);
115
+ });
116
+
90
117
  test("decidePermission: comandos según isAllowedShell y el resto rechazado", () => {
91
118
  assert.equal(decidePermission(bash("git diff a...b"), ctx("ask")).allow, true);
92
119
  assert.equal(decidePermission(bash("rm -rf ."), ctx()).allow, false);
@@ -19,6 +19,13 @@ export function outputRelPath(filename) {
19
19
  return `${OUTPUT_DIR}/${String(filename || "").replace(/^.*[\\/]/, "")}`;
20
20
  }
21
21
 
22
+ /** Companion de handoff: mismo stem que el JSON → `.diff-review/<stem>.chat.md`. */
23
+ export function chatRelPath(filename) {
24
+ const name = String(filename || "").replace(/^.*[\\/]/, "");
25
+ const stem = name.replace(/\.json$/i, "") || "diff-rev";
26
+ return `${OUTPUT_DIR}/${stem}.chat.md`;
27
+ }
28
+
22
29
  /** Nombre legacy fijo. */
23
30
  export const OUTPUT_FILENAME_LEGACY = `${OUTPUT_PREFIX_LEGACY}.json`;
24
31
 
package/lib/prompt.mjs CHANGED
@@ -85,7 +85,8 @@ const RULES = `- Ids: themes use \`t1\`, \`t2\`, …; findings use \`f1\`, \`f2\
85
85
  - "blocking": true ONLY if the branch should not merge as-is. Use only with class "risk".
86
86
  - When several read-only lookups are independent (files, searches), batch them in the same turn if your tools allow parallel calls.
87
87
  - Write human-readable strings (intent, title, what, why, fix, notes) in Spanish. Keep enums/ids/paths/JSON keys exactly as in the schema.
88
- - Length is a soft target, not a check: aim for title ≤72 characters and what/why/fix ≤120 characters. Prefer clarity over shortening. Longer text is still valid. Do not rewrite the file only to shorten it.`;
88
+ - Length is a soft target, not a check: aim for title ≤72 characters and what/why/fix ≤120 characters. Prefer clarity over shortening. Longer text is still valid. Do not rewrite the file only to shorten it.
89
+ - If the output JSON already exists and findings have \`resolution\` ({ kind: ignored|fix|corrected, detail?: string }), preserve those fields on rewrite (coverage / edit / regenerate). Keep existing finding ids when possible; do not drop or reshuffle resolutions.`;
89
90
 
90
91
  /** @param {{ hasDiff?: boolean }} [ctx] */
91
92
  function workflowLocal(base, branch, ctx = {}) {
@@ -316,7 +317,7 @@ ${outputSchemaBlock(meta)}
316
317
 
317
318
  Include "meta" with the source/repo/branch/base above (and origin "remoteUrl" when local). "agent" and "model" are required: set "agent" to the product you are (Claude Code, Cursor, Codex, Copilot, Gemini, …) and "model" to the exact model id you are running. Do not leave placeholders or omit them; validation fails without both. "generatedAt" is optional (ISO-8601 now).
318
319
 
319
- Do NOT include diffs or a "files" array. The tool loads the companion \`.diff\` (or computes with git if missing) when opening the report. Do not invent hunks or paste patches into the JSON.
320
+ Do NOT include diffs or a "files" array. The tool loads the companion \`.diff\` (or computes with git if missing) when opening the report. Do not invent hunks or paste patches into the JSON. If you are rewriting an existing review JSON, copy through any per-finding \`resolution\` already present.
320
321
 
321
322
  ${validateSection}`;
322
323
  }
@@ -0,0 +1,37 @@
1
+ import assert from "node:assert/strict";
2
+ import { mkdtempSync, readFileSync, rmSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { after, test } from "node:test";
6
+ import { buildPrompt } from "./prompt.mjs";
7
+ import { chatRelPath } from "./output-name.mjs";
8
+ import { companionPaths, writeHandoffChat } from "./review-dir.mjs";
9
+
10
+ const tmp = mkdtempSync(join(tmpdir(), "diff-review-prompt-"));
11
+ after(() => rmSync(tmp, { recursive: true, force: true }));
12
+
13
+ test("chatRelPath uses same stem as JSON", () => {
14
+ assert.equal(
15
+ chatRelPath("diff-rev_aaaaaaaaaa_bbbbbbbbbb.json"),
16
+ ".diff-review/diff-rev_aaaaaaaaaa_bbbbbbbbbb.chat.md"
17
+ );
18
+ });
19
+
20
+ test("writeHandoffChat overwrites companion .chat.md", () => {
21
+ const filename = "diff-rev_aaaaaaaaaa_bbbbbbbbbb.json";
22
+ writeHandoffChat(tmp, filename, "# first\n");
23
+ writeHandoffChat(tmp, filename, "# second\n");
24
+ const { chat } = companionPaths(tmp, filename);
25
+ assert.equal(readFileSync(chat, "utf8"), "# second\n");
26
+ assert.equal(chatRelPath(filename), `.diff-review/${filename.replace(/\.json$/i, "")}.chat.md`);
27
+ });
28
+
29
+ test("buildPrompt tells agent to preserve finding resolution on rewrite", () => {
30
+ const text = buildPrompt(
31
+ { source: "local", repo: "/tmp/r", branch: "feat", base: "develop" },
32
+ { outputFilename: "diff-rev_aaaaaaaaaa_bbbbbbbbbb.json" }
33
+ );
34
+ assert.match(text, /preserve those fields on rewrite/i);
35
+ assert.match(text, /resolution/);
36
+ assert.match(text, /copy through any per-finding `resolution`/i);
37
+ });
@@ -27,7 +27,7 @@ export function ensureReviewDir(repoRoot) {
27
27
  return dir;
28
28
  }
29
29
 
30
- /** `diff-rev_a_b.json` → `{ json, diff, session }` dentro de `.diff-review/`. */
30
+ /** `diff-rev_a_b.json` → `{ json, diff, session, chat }` dentro de `.diff-review/`. */
31
31
  export function companionPaths(repoRoot, filename) {
32
32
  const name = basename(String(filename || ""));
33
33
  const stem = name.replace(/\.json$/i, "");
@@ -36,6 +36,8 @@ export function companionPaths(repoRoot, filename) {
36
36
  json: join(dir, name),
37
37
  diff: join(dir, `${stem}.diff`),
38
38
  session: join(dir, `${stem}.session.json`),
39
+ /** Transcript legible al cambiar de agente (se pisa en cada switch). */
40
+ chat: join(dir, `${stem}.chat.md`),
39
41
  };
40
42
  }
41
43
 
@@ -106,3 +108,14 @@ export function writeSessionRef(repoRoot, filename, ref) {
106
108
  writeFileSync(companionPaths(repoRoot, filename).session, `${JSON.stringify(full, null, 2)}\n`);
107
109
  return full;
108
110
  }
111
+
112
+ /**
113
+ * Guarda (pisa) el transcript legible de handoff junto al JSON.
114
+ * @returns {string} path absoluto del `.chat.md`
115
+ */
116
+ export function writeHandoffChat(repoRoot, filename, text) {
117
+ ensureReviewDir(repoRoot);
118
+ const { chat } = companionPaths(repoRoot, filename);
119
+ writeFileSync(chat, String(text ?? ""));
120
+ return chat;
121
+ }
package/lib/review.mjs CHANGED
@@ -2,6 +2,7 @@ import {
2
2
  BLOCK_OPS,
3
3
  FINDING_CLASSES,
4
4
  FINDING_KINDS,
5
+ FINDING_RESOLUTION_KINDS,
5
6
  FINDING_SEVERITIES,
6
7
  GROUP_KINDS,
7
8
  SKIP_REASONS,
@@ -111,6 +112,37 @@ function findingKey(finding) {
111
112
  return [finding.file, finding.line ?? "", finding.kind, finding.what].join("|");
112
113
  }
113
114
 
115
+ /** Triage UI (`ignored` | `fix` | `corrected`); se preserva al rehidratar desde disco. */
116
+ function normalizeResolution(raw) {
117
+ const kind = String(raw?.kind ?? "")
118
+ .trim()
119
+ .toLowerCase();
120
+ if (!FINDING_RESOLUTION_KINDS.includes(kind)) return undefined;
121
+ const detail = String(raw?.detail ?? "").trim();
122
+ return detail ? { kind, detail } : { kind };
123
+ }
124
+
125
+ function assignFindingIds(findings) {
126
+ const used = new Set();
127
+ for (const finding of findings) {
128
+ const id = String(finding.id || "").trim();
129
+ if (id && !used.has(id)) {
130
+ finding.id = id;
131
+ used.add(id);
132
+ } else {
133
+ finding.id = "";
134
+ }
135
+ }
136
+ let n = 1;
137
+ for (const finding of findings) {
138
+ if (finding.id) continue;
139
+ while (used.has(`f${n}`)) n += 1;
140
+ finding.id = `f${n}`;
141
+ used.add(finding.id);
142
+ n += 1;
143
+ }
144
+ }
145
+
114
146
  function normalizeFindings(raw, { blockIds, knownPaths }) {
115
147
  const seen = new Set();
116
148
  const findings = [];
@@ -123,8 +155,9 @@ function normalizeFindings(raw, { blockIds, knownPaths }) {
123
155
  const severity = oneOf(item.severity, FINDING_SEVERITIES, "med");
124
156
  const block = String(item?.block || "").trim();
125
157
  const line = Number.isFinite(Number(item?.line)) ? Number(item.line) : null;
158
+ const resolution = normalizeResolution(item?.resolution);
126
159
  const finding = {
127
- id: "",
160
+ id: String(item?.id || "").trim(),
128
161
  class: cls,
129
162
  severity,
130
163
  // Una mejora de calidad nunca frena un merge, diga lo que diga el modelo;
@@ -136,6 +169,7 @@ function normalizeFindings(raw, { blockIds, knownPaths }) {
136
169
  block: blockIds.has(block) ? block : "",
137
170
  what,
138
171
  fix: text(item.fix || item.detail, MAX.finding),
172
+ ...(resolution ? { resolution } : {}),
139
173
  };
140
174
  const key = findingKey(finding);
141
175
  if (seen.has(key)) continue;
@@ -150,9 +184,7 @@ function normalizeFindings(raw, { blockIds, knownPaths }) {
150
184
  rank[a.severity] - rank[b.severity] ||
151
185
  a.file.localeCompare(b.file),
152
186
  );
153
- findings.forEach((finding, i) => {
154
- finding.id = `f${i + 1}`;
155
- });
187
+ assignFindingIds(findings);
156
188
  return findings;
157
189
  }
158
190
 
@@ -130,6 +130,41 @@ test("buildReview deduplica hallazgos repetidos y limpia referencias colgadas",
130
130
  assert.equal(doc.findings[0].block, "");
131
131
  });
132
132
 
133
+ test("buildReview preserva resolution e ids al rehidratar triage desde disco", () => {
134
+ const withFindings = payload();
135
+ withFindings.findings = [
136
+ {
137
+ id: "f2",
138
+ class: "quality",
139
+ severity: "low",
140
+ kind: "docs",
141
+ file: "src/a.ts",
142
+ line: 3,
143
+ what: "comentario viejo",
144
+ fix: "actualizar",
145
+ resolution: { kind: "ignored" },
146
+ },
147
+ {
148
+ id: "f1",
149
+ class: "risk",
150
+ severity: "med",
151
+ kind: "bug",
152
+ file: "src/a.ts",
153
+ line: 22,
154
+ block: "b1",
155
+ what: "null sin chequear",
156
+ fix: "guardar",
157
+ resolution: { kind: "corrected", detail: "null-check en parse" },
158
+ },
159
+ ];
160
+ const doc = buildReview({ skeleton: skeleton(), payload: withFindings });
161
+ const byId = Object.fromEntries(doc.findings.map((f) => [f.id, f]));
162
+ assert.equal(doc.findings.length, 2);
163
+ assert.deepEqual(byId.f1.resolution, { kind: "corrected", detail: "null-check en parse" });
164
+ assert.deepEqual(byId.f2.resolution, { kind: "ignored" });
165
+ assert.equal(byId.f1.what, "null sin chequear");
166
+ });
167
+
133
168
  test("una respuesta JSON del modelo atraviesa decode, validación y normalización", () => {
134
169
  const answer = JSON.stringify({
135
170
  meta: { agent: "Claude Code", model: "claude-opus" },
package/lib/validate.mjs CHANGED
@@ -8,6 +8,7 @@ export const FINDING_KINDS = [
8
8
  "missing-test", "perf", "maintainability", "docs", "other",
9
9
  ];
10
10
  export const SKIP_REASONS = ["generated", "lockfile", "format", "vendored", "binary", "trivial", "ignored"];
11
+ export const FINDING_RESOLUTION_KINDS = ["ignored", "fix", "corrected"];
11
12
 
12
13
  /** Lo que tiene que devolver el modelo en un turno. El resto lo agrega el pipeline. */
13
14
  export const REVIEW_SCHEMA = {
@@ -77,6 +78,15 @@ export const REVIEW_SCHEMA = {
77
78
  block: { type: "string" },
78
79
  what: { type: "string", minLength: 1 },
79
80
  fix: { type: "string" },
81
+ resolution: {
82
+ type: "object",
83
+ required: ["kind"],
84
+ additionalProperties: true,
85
+ properties: {
86
+ kind: { type: "string", enum: FINDING_RESOLUTION_KINDS },
87
+ detail: { type: "string" },
88
+ },
89
+ },
80
90
  },
81
91
  },
82
92
  },
@@ -68,6 +68,53 @@ test("validateAgainst acepta los dos ejes de hallazgo", () => {
68
68
  assert.deepEqual(validateAgainst(REVIEW_SCHEMA, doc), []);
69
69
  });
70
70
 
71
+ test("validateAgainst acepta resolution de triage en hallazgos", () => {
72
+ const doc = valid();
73
+ doc.findings = [
74
+ {
75
+ id: "f1",
76
+ class: "risk",
77
+ severity: "high",
78
+ blocking: true,
79
+ kind: "bug",
80
+ file: "src/a.ts",
81
+ line: 4,
82
+ what: "rompe",
83
+ fix: "arreglar",
84
+ resolution: { kind: "corrected", detail: "null-check en parse" },
85
+ },
86
+ {
87
+ id: "f2",
88
+ class: "quality",
89
+ severity: "low",
90
+ blocking: false,
91
+ kind: "maintainability",
92
+ file: "src/a.ts",
93
+ line: null,
94
+ what: "duplicado",
95
+ resolution: { kind: "ignored" },
96
+ },
97
+ ];
98
+ assert.deepEqual(validateAgainst(REVIEW_SCHEMA, doc), []);
99
+ });
100
+
101
+ test("validateAgainst rechaza resolution.kind inválido", () => {
102
+ const doc = valid();
103
+ doc.findings = [
104
+ {
105
+ id: "f1",
106
+ class: "risk",
107
+ severity: "high",
108
+ blocking: true,
109
+ kind: "bug",
110
+ file: "src/a.ts",
111
+ what: "x",
112
+ resolution: { kind: "done" },
113
+ },
114
+ ];
115
+ assert.ok(validateAgainst(REVIEW_SCHEMA, doc).some((e) => e.includes("kind")));
116
+ });
117
+
71
118
  test("reviewIssues detecta un bloque que apunta a un grupo inexistente", () => {
72
119
  const doc = valid();
73
120
  doc.blocks[0].group = "g9";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jpkme/diff-review",
3
- "version": "0.1.15",
3
+ "version": "0.1.16",
4
4
  "description": "Local UI to prompt a coding agent for a branch review and browse the result.",
5
5
  "type": "module",
6
6
  "bin": {
package/schema.json CHANGED
@@ -123,7 +123,22 @@
123
123
  "line": { "type": ["integer", "null"], "description": "Línea de la post-imagen (columna derecha / @@ +N)." },
124
124
  "block": { "type": ["string", "null"], "description": "Id del bloque, o vacío/null si es transversal." },
125
125
  "what": { "type": "string" },
126
- "fix": { "type": "string", "description": "Acción concreta." }
126
+ "fix": { "type": "string", "description": "Acción concreta." },
127
+ "resolution": {
128
+ "type": "object",
129
+ "description": "Triage de la UI (Ignorar / Corregir / Corregido). Lo escribe el viewer; el agente debe preservarlo al editar el JSON.",
130
+ "required": ["kind"],
131
+ "properties": {
132
+ "kind": {
133
+ "type": "string",
134
+ "enum": ["ignored", "fix", "corrected"]
135
+ },
136
+ "detail": {
137
+ "type": "string",
138
+ "description": "Resumen de la corrección aplicada (solo con kind=corrected)."
139
+ }
140
+ }
141
+ }
127
142
  }
128
143
  }
129
144
  },
@@ -0,0 +1 @@
1
+ .resize-handle.svelte-ywcz8g{cursor:col-resize;z-index:2;touch-action:none;background:0 0;flex-shrink:0;width:6px;position:relative}.resize-handle.svelte-ywcz8g:after{content:"";background:0 0;width:2px;position:absolute;top:0;bottom:0;left:2px}.resize-handle.svelte-ywcz8g:hover:after,.resize-handle.dragging.svelte-ywcz8g:after{background:var(--accent)}.chat-shell.svelte-1nylsi{flex-shrink:0;align-self:stretch;min-width:0;min-height:0;display:flex}.chat.svelte-1nylsi{border-left:1px solid var(--border);background:var(--bg-elev);flex-direction:column;flex:1;min-width:0;min-height:0;display:flex}header.svelte-1nylsi{border-bottom:1px solid var(--border);justify-content:space-between;align-items:center;padding:10px 14px;display:flex}.title.svelte-1nylsi{align-items:center;gap:8px;min-width:0;display:flex}.title.svelte-1nylsi strong:where(.svelte-1nylsi){font-size:13.5px;font-weight:650}.title.svelte-1nylsi small:where(.svelte-1nylsi){font-family:var(--mono);color:var(--text-faint);text-overflow:ellipsis;white-space:nowrap;min-width:0;font-size:11.5px;overflow:hidden}.header-agent.svelte-1nylsi{flex:0 auto;min-width:0;max-width:min(200px,55%)}.header-agent.svelte-1nylsi .agent-select .trigger{background:0 0;border-color:#0000;min-height:28px;padding:4px 8px;font-size:13px;font-weight:650}.header-agent.svelte-1nylsi .agent-select .trigger:hover:not(:disabled){border-color:var(--border);background:var(--bg-card)}.header-agent.svelte-1nylsi .agent-select .menu{min-width:180px}.close.svelte-1nylsi{color:var(--text-dim);cursor:pointer;background:0 0;border:0;font-size:13px}.log-area.svelte-1nylsi{flex-direction:column;flex:1;gap:10px;min-height:0;padding:12px 14px;display:flex}.log.svelte-1nylsi{flex:1;min-height:0;display:flex}.log.svelte-1nylsi .log{flex:1;min-height:0}.picker.svelte-1nylsi{flex-direction:column;flex:1;gap:10px;padding:14px;display:flex}.field.svelte-1nylsi{color:var(--text-dim);flex-direction:column;gap:4px;font-size:12px;display:flex}.field.svelte-1nylsi .agent-select .trigger{padding:6px 8px;font-size:13px}.field.svelte-1nylsi small:where(.svelte-1nylsi){color:var(--text-faint)}.start.svelte-1nylsi{background:var(--btn-primary-bg);border:1px solid var(--btn-primary-border);color:var(--btn-primary-text);align-self:flex-start;padding:8px 14px;font-size:13px}.start.svelte-1nylsi:disabled{opacity:.5}.hint.svelte-1nylsi,.note.svelte-1nylsi,.err.svelte-1nylsi{color:var(--text-faint);margin:0;padding:8px 14px;font-size:12.5px}.picker.svelte-1nylsi .hint:where(.svelte-1nylsi){padding:0}.err.svelte-1nylsi{color:var(--danger)}.models-error.svelte-1nylsi{flex-wrap:wrap;align-items:baseline;gap:8px;padding-inline:0;display:flex}button.linkish.svelte-1nylsi{color:var(--accent,#3b82f6);cursor:pointer;font:inherit;background:0 0;border:none;padding:0;text-decoration:underline}.connecting.svelte-1nylsi{text-align:center;flex-direction:column;flex:1;justify-content:center;gap:6px;padding:18px 8px;display:flex}.connecting-title.svelte-1nylsi{color:var(--text);margin:0;font-size:13.5px;font-weight:650}.connecting-detail.svelte-1nylsi{font-size:12px;font-family:var(--mono);color:var(--text-dim);word-break:break-all;margin:0}.connecting-hint.svelte-1nylsi{color:var(--text-faint);margin:4px 0 0;font-size:12px}.composer.svelte-1nylsi{border-top:1px solid var(--border);flex-direction:column;gap:8px;padding:10px 14px 14px;display:flex}.composer-top.svelte-1nylsi{flex-wrap:wrap;align-items:flex-end;gap:10px;display:flex}.model-field.svelte-1nylsi{flex:0 auto;min-width:0;max-width:min(280px,48%);margin-left:auto}.mode-field.svelte-1nylsi{flex:0 auto;align-self:flex-end;min-width:0}.mode-select.svelte-1nylsi{width:100%;max-width:180px;font:inherit;color:var(--text);background:var(--bg-card);border:1px solid var(--border);cursor:pointer;border-radius:0;padding:5px 8px;font-size:12px;display:block}.mode-select.svelte-1nylsi:disabled{opacity:.5;cursor:not-allowed}.sr-only.svelte-1nylsi{clip:rect(0, 0, 0, 0);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}textarea.svelte-1nylsi{resize:vertical;min-height:60px;font:inherit;background:var(--bg-card);color:var(--text);border:1px solid var(--border);padding:8px;font-size:13px}.actions.svelte-1nylsi{align-items:center;gap:8px;display:flex}.actions-spacer.svelte-1nylsi{flex:1;min-width:0}.actions.svelte-1nylsi button:where(.svelte-1nylsi){background:var(--bg-card);border:1px solid var(--border);color:var(--text);padding:6px 12px;font-size:12.5px}.actions.svelte-1nylsi button.primary:where(.svelte-1nylsi){background:var(--btn-primary-bg);border-color:var(--btn-primary-border);color:var(--btn-primary-text)}.actions.svelte-1nylsi button:where(.svelte-1nylsi):disabled{opacity:.5}.switch-backdrop.svelte-1nylsi{z-index:80;background:#0006;position:fixed;inset:0}.switch-dialog.svelte-1nylsi{z-index:81;background:var(--bg-elev);border:1px solid var(--border);width:min(420px,100vw - 32px);padding:18px 20px;position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);box-shadow:0 16px 40px #00000047}.switch-dialog.svelte-1nylsi h2:where(.svelte-1nylsi){margin:0 0 10px;font-size:15px;font-weight:650}.switch-dialog.svelte-1nylsi p:where(.svelte-1nylsi){color:var(--text-dim);margin:0;font-size:13px;line-height:1.45}.switch-dialog.svelte-1nylsi strong:where(.svelte-1nylsi){color:var(--text);font-weight:650}.switch-actions.svelte-1nylsi{justify-content:flex-end;gap:8px;margin-top:16px;display:flex}.switch-actions.svelte-1nylsi button:where(.svelte-1nylsi){background:var(--bg-card);border:1px solid var(--border);color:var(--text);cursor:pointer;padding:7px 12px;font-size:13px}.switch-actions.svelte-1nylsi button.primary:where(.svelte-1nylsi){background:var(--btn-primary-bg);border-color:var(--btn-primary-border);color:var(--btn-primary-text)}.ask-agent.svelte-1dix5z0{border:1px solid var(--border);background:var(--bg-card);width:28px;height:28px;color:var(--text-dim);cursor:pointer;border-radius:0;flex-shrink:0;justify-content:center;align-items:center;padding:0;display:inline-flex}.ask-agent.svelte-1dix5z0:hover{border-color:var(--border-strong,var(--border));color:var(--text);background:var(--bg-elev,var(--bg-card))}.diff-wrap.svelte-13r6alg{background:var(--bg);--ln-w:calc(var(--diff-font-size,11.5px) * 3.1);--sign-w:calc(var(--diff-font-size,11.5px) * 1.05);--divider-w:5px}.collapse-bar.svelte-13r6alg{background:var(--diff-hunk-bg);border-bottom:1px solid var(--border-soft);color:var(--text-faint);flex-wrap:wrap;justify-content:space-between;align-items:center;gap:8px;padding:5px 10px;font-size:10.5px;display:flex}.link.svelte-13r6alg{color:var(--accent);background:0 0;border:0;padding:0;font-size:10.5px;text-decoration:underline}.gap-bar.svelte-13r6alg{background:var(--diff-hunk-bg);border-top:1px solid var(--border-soft);border-bottom:1px solid var(--border-soft);align-items:center;gap:10px;padding:3px 10px;display:flex}.gap-actions.svelte-13r6alg{border:1px solid var(--border);flex-shrink:0;display:flex;overflow:hidden}.gap-actions.svelte-13r6alg button:where(.svelte-13r6alg){background:var(--bg-card);font-family:var(--mono);font-size:calc(var(--diff-font-size,11.5px) * .87);color:var(--text-dim);border:0;padding:1px 8px;line-height:1.5}.gap-actions.svelte-13r6alg button:where(.svelte-13r6alg)+button:where(.svelte-13r6alg){border-left:1px solid var(--border)}.gap-actions.svelte-13r6alg button:where(.svelte-13r6alg):hover:not(:disabled){background:var(--accent-soft);color:var(--text)}.gap-actions.svelte-13r6alg button:where(.svelte-13r6alg):disabled{opacity:.4;cursor:not-allowed}.gap-info.svelte-13r6alg{font-family:var(--mono);font-size:calc(var(--diff-font-size,11.5px) * .87);color:var(--text-faint);white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.empty.svelte-13r6alg{color:var(--text-faint);margin:0;padding:12px;font-size:11.5px}.diff.svelte-13r6alg,.hunk-header.svelte-13r6alg{font-family:var(--mono)}.diff.svelte-13r6alg{max-height:55vh;font-size:var(--diff-font-size,11.5px);overflow:auto}.diff.wrap.svelte-13r6alg{overflow-x:hidden}.diff.wrap.svelte-13r6alg .row:where(.svelte-13r6alg){width:auto;min-width:0}.diff.wrap.svelte-13r6alg .code:where(.svelte-13r6alg){white-space:pre-wrap;overflow-wrap:anywhere}.hunk-header.svelte-13r6alg{background:var(--diff-hunk-bg);border-top:1px solid var(--border-soft);border-bottom:1px solid var(--border-soft);font-size:calc(var(--diff-font-size,11.5px) * .913);color:var(--text-faint);white-space:nowrap;text-overflow:ellipsis;padding:3px 10px;overflow:hidden}.row.svelte-13r6alg{grid-template-columns:var(--ln-w) var(--ln-w) var(--sign-w) auto;border-left:2px solid #0000;width:max-content;min-width:100%;display:grid}.split-grid.svelte-13r6alg{align-items:stretch;display:grid}.srow.svelte-13r6alg{display:contents}.divider.svelte-13r6alg{background:var(--border-soft);cursor:col-resize;touch-action:none}.divider.svelte-13r6alg:hover,.divider.svelte-13r6alg:active{background:var(--accent)}.split-grid.svelte-13r6alg .code:where(.svelte-13r6alg){white-space:pre-wrap;overflow-wrap:anywhere}.ln.svelte-13r6alg{text-align:right;color:var(--diff-gutter);font-size:calc(var(--diff-font-size,11.5px) * .87);-webkit-user-select:none;user-select:none;font-variant-numeric:tabular-nums;border-left:2px solid #0000;padding-right:6px;overflow:hidden}.row.svelte-13r6alg .ln:where(.svelte-13r6alg){border-left:0}.sign.svelte-13r6alg{text-align:center;-webkit-user-select:none;user-select:none;color:var(--text-faint)}.sign.add.svelte-13r6alg{color:var(--diff-add-fg)}.sign.del.svelte-13r6alg{color:var(--diff-del-fg)}.code.svelte-13r6alg{white-space:pre;padding-right:10px}.row.add.svelte-13r6alg{background:var(--diff-add-bg)}.row.add.svelte-13r6alg .sign:where(.svelte-13r6alg){color:var(--diff-add-fg)}.row.del.svelte-13r6alg{background:var(--diff-del-bg)}.row.del.svelte-13r6alg .sign:where(.svelte-13r6alg){color:var(--diff-del-fg)}.file-icon.svelte-1dshc1f{flex-shrink:0;justify-content:center;align-items:center;display:inline-flex}.file-icon.svelte-1dshc1f svg{width:100%;height:100%}.file-icon.branded.svelte-1dshc1f svg{width:78%;height:78%}.file-icon.svelte-1dshc1f:not(.branded) svg{fill:currentColor}.explore.svelte-1k3qopq{display:contents}.blocker-bar.svelte-1k3qopq{background:var(--danger-bg);border:1px solid var(--danger-border);color:var(--danger);margin:0;padding:10px 14px;font-size:13px;font-weight:600}h2.svelte-1k3qopq{letter-spacing:.07em;text-transform:uppercase;color:var(--text-faint);margin:0 0 8px;font-size:12px;font-weight:650}.intent.svelte-1k3qopq{border-bottom:1px solid var(--border);padding:0 0 16px}.intent-text.svelte-1k3qopq{color:var(--text);max-width:80ch;margin:0;font-size:14px;line-height:1.6}.note.svelte-1k3qopq{color:var(--text-faint);max-width:80ch;margin:8px 0 0;font-size:11.5px;line-height:1.5}.group.svelte-1k3qopq{flex-direction:column;gap:12px;padding:18px 0 6px;display:flex}.group-sticky.svelte-1k3qopq{z-index:4;background:var(--bg);border-bottom:1px solid var(--border-soft);flex-direction:column;gap:6px;margin:0 -20px;padding:14px 20px 12px;display:flex;position:sticky;top:-14px}.group-head.svelte-1k3qopq{flex-wrap:wrap;align-items:center;gap:10px;display:flex}.group-ask.svelte-1k3qopq{margin-left:auto}.group-head.svelte-1k3qopq .number:where(.svelte-1k3qopq){color:var(--text-faint);flex-shrink:0;font-size:12px;font-weight:700}.group-head.svelte-1k3qopq h2:where(.svelte-1k3qopq){color:var(--text);text-transform:none;letter-spacing:normal;margin:0;font-size:15px;font-weight:650;line-height:1.3}.kind-chip.svelte-1k3qopq{border:1px solid var(--border);background:var(--bg-card);flex-shrink:0;padding:2px 8px;font-size:11px;font-weight:700}.group-intent.svelte-1k3qopq{color:var(--text-dim);max-width:80ch;margin:0;font-size:12.5px;line-height:1.45}.loose.svelte-1k3qopq .kind-chip:where(.svelte-1k3qopq){color:var(--text-faint)}.file-section.svelte-1k3qopq{border-top:1px solid var(--border)}.file-head.svelte-1k3qopq{border-bottom:1px solid var(--border-soft);align-items:center;display:grid}.file-section.collapsed.svelte-1k3qopq .file-head:where(.svelte-1k3qopq){border-bottom:0}.file-head-main.svelte-1k3qopq{align-items:center;gap:8px;min-width:0;padding:6px 0;display:flex}.file-toggle.svelte-1k3qopq{text-align:left;min-width:0;color:inherit;cursor:pointer;background:0 0;border:0;flex:1;align-items:center;gap:8px;padding:4px 0;display:flex}.file-toggle.svelte-1k3qopq:hover .path:where(.svelte-1k3qopq){color:var(--accent)}.caret.svelte-1k3qopq{width:10px;color:var(--text-faint);flex-shrink:0;font-size:10px}.file-head-gutter.svelte-1k3qopq{flex-shrink:0}.file-head-explain.svelte-1k3qopq{align-items:center;padding:10px 0 10px 14px;display:flex}.path.svelte-1k3qopq{font-family:var(--mono);color:var(--text);text-overflow:ellipsis;white-space:nowrap;min-width:0;font-size:12.5px;overflow:hidden}.change-label.svelte-1k3qopq{color:var(--text-faint);flex:1;font-size:11px}.findings-control.svelte-1k3qopq{color:var(--text);background:0 0;border:0;flex-shrink:0;align-items:center;gap:6px;padding:0;display:flex}.count-badge.svelte-1k3qopq{justify-content:center;align-items:center;min-width:18px;height:18px;padding:0 4px;font-size:10.5px;font-weight:700;display:flex}.count-badge.done.svelte-1k3qopq{border:1px solid var(--fix-border);color:var(--ok)}.count-badge.open.svelte-1k3qopq{background:color-mix(in srgb, var(--finding-sev) 22%, transparent);color:var(--finding-sev)}.count-label.svelte-1k3qopq{color:var(--text-faint);font-size:11.5px}.count-label.open.svelte-1k3qopq{color:var(--text-dim)}.arrow.svelte-1k3qopq{color:var(--finding-sev,var(--accent));font-size:14px}.file-grid.svelte-1k3qopq{grid-template-columns:minmax(0,1fr) minmax(260px,320px);display:grid}.file-grid.no-explanations.svelte-1k3qopq{grid-template-columns:minmax(0,1fr)}.diff-col.svelte-1k3qopq{min-width:0}.explain-col.svelte-1k3qopq{border-left:1px solid var(--border-soft);background:var(--bg-elev);flex-direction:column;display:flex;overflow:auto}.explain-row.svelte-1k3qopq{border-bottom:1px solid var(--border-soft);padding:10px 14px}.explain-top.svelte-1k3qopq{align-items:center;gap:8px;margin-bottom:4px;display:flex}.explain-ask.svelte-1k3qopq{margin-left:auto}.lines.svelte-1k3qopq{color:var(--text-faint);font-size:10.5px;font-family:var(--mono)}.op.svelte-1k3qopq{color:var(--text-faint);text-transform:uppercase;letter-spacing:.04em;font-size:10px}.what.svelte-1k3qopq{color:var(--text);max-width:80ch;margin:0 0 3px;font-size:13px;line-height:1.4}.why.svelte-1k3qopq{color:var(--text-dim);max-width:80ch;margin:0;font-size:11.5px;line-height:1.4}.orphans.svelte-1k3qopq,.skipped.svelte-1k3qopq{border-top:1px solid var(--border-soft);padding-top:12px}.orphan-list.svelte-1k3qopq{flex-direction:column;gap:6px;display:flex}.orphan-row.svelte-1k3qopq{background:var(--bg-elev);border-left:2px solid #0000;align-items:baseline;gap:10px;padding:6px 10px;display:flex}.orphan-row.svelte-1k3qopq .badge:where(.svelte-1k3qopq){flex-shrink:0;font-size:10px;font-weight:700}.orphan-row.svelte-1k3qopq .what:where(.svelte-1k3qopq){flex:1;margin:0;font-size:12.5px}.orphan-row.svelte-1k3qopq .where:where(.svelte-1k3qopq){font-family:var(--mono);color:var(--text-faint);font-size:10.5px}.skipped-list.svelte-1k3qopq{flex-wrap:wrap;gap:6px;display:flex}.skipped-chip.svelte-1k3qopq{font-size:11px;font-family:var(--mono);color:var(--text-faint);border:1px solid var(--border);padding:4px 8px}.prompt-box.svelte-1dm34m1{border:1px solid var(--fix-border);background:var(--fix-bg);flex-direction:column;gap:10px;padding:14px 16px;display:flex}.prompt-box.publish.svelte-1dm34m1{border-color:var(--publish-border);background:var(--publish-bg)}.prompt-head.svelte-1dm34m1{justify-content:space-between;align-items:center;display:flex}.fix-title.svelte-1dm34m1{letter-spacing:.07em;text-transform:uppercase;color:var(--fix-text);margin:0;font-size:12px;font-weight:650}.publish-title.svelte-1dm34m1{letter-spacing:.07em;text-transform:uppercase;color:var(--publish-text);margin:0;font-size:12px;font-weight:650}.close.svelte-1dm34m1{color:var(--text-faint);background:0 0;border:0;padding:0;font-size:12px}.mode-toggle.svelte-1dm34m1{border:1px solid var(--border);width:fit-content;display:flex;overflow:hidden}.mode-toggle.svelte-1dm34m1 button:where(.svelte-1dm34m1){color:var(--text);background:0 0;border:0;padding:6px 12px;font-size:12px}.mode-toggle.svelte-1dm34m1 button:where(.svelte-1dm34m1)+button:where(.svelte-1dm34m1){border-left:1px solid var(--border)}.mode-toggle.svelte-1dm34m1 button.on:where(.svelte-1dm34m1){background:var(--accent-soft)}textarea.svelte-1dm34m1{resize:vertical;background:var(--bg);border:1px solid var(--border);width:100%;height:220px;font-family:var(--mono);color:var(--text);padding:12px;font-size:12px;line-height:1.5}.hint.svelte-1dm34m1{color:var(--text-faint);margin:0;font-size:11.5px}.copy.svelte-1dm34m1{background:var(--btn-primary-bg);border:1px solid var(--btn-primary-border);color:var(--btn-primary-text);padding:9px 14px;font-size:13px;font-weight:600}.detail-panel.svelte-1dm34m1{border:1px solid var(--border);background:var(--bg-card);flex-direction:column;flex:1;min-width:0;min-height:0;display:flex;overflow:hidden}.detail-head.svelte-1dm34m1{border-bottom:1px solid var(--border-soft);background:var(--bg-elev);flex-direction:column;flex-shrink:0;gap:2px;min-width:0;padding:10px 16px;display:flex}.detail-head-row.svelte-1dm34m1{justify-content:space-between;align-items:center;gap:12px;min-width:0;display:flex}.detail-head-left.svelte-1dm34m1{align-items:center;gap:8px;min-width:0;display:flex;overflow:hidden}.number.svelte-1dm34m1{color:var(--text);flex-shrink:0;font-size:12px;font-weight:700}.badge.svelte-1dm34m1{flex-shrink:0;font-size:10px;font-weight:700}.file-name.svelte-1dm34m1{color:var(--text);font-size:12px;font-weight:600;font-family:var(--mono);text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.file-dir.svelte-1dm34m1{color:var(--text-faint);font-size:11px;font-family:var(--mono);text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.head-actions.svelte-1dm34m1{flex-shrink:0;align-items:center;gap:8px;display:flex}.decision-group.svelte-1dm34m1{border:1px solid var(--border);flex-shrink:0;display:flex;overflow:hidden}.decision-group.corrected.svelte-1dm34m1{border-color:color-mix(in srgb, var(--ok) 45%, var(--border));background:var(--ok-bg)}.corrected-label.svelte-1dm34m1{color:var(--ok);padding:6px 14px;font-size:12px;font-weight:600}.decision-group.svelte-1dm34m1 button:where(.svelte-1dm34m1){color:var(--text-dim);background:0 0;border:0;padding:6px 14px;font-size:12px;font-weight:600}.decision-group.svelte-1dm34m1 button:first-child.on:where(.svelte-1dm34m1){background:var(--danger-bg);color:var(--danger)}.decision-group.svelte-1dm34m1 button:nth-child(2).on:where(.svelte-1dm34m1){background:var(--fix-bg);color:var(--ok)}.decision-group.svelte-1dm34m1 button:where(.svelte-1dm34m1)+button:where(.svelte-1dm34m1){border-left:1px solid var(--border)}.decision-group.svelte-1dm34m1 .clear:where(.svelte-1dm34m1){color:var(--text-faint);border-left:1px solid var(--border);padding:6px 10px}.fix-detail.svelte-1dm34m1{border:1px solid var(--border);background:var(--ok-bg);margin-top:4px;padding:8px 10px}.fix-detail.svelte-1dm34m1 summary:where(.svelte-1dm34m1){cursor:pointer;letter-spacing:.04em;text-transform:uppercase;color:var(--ok);-webkit-user-select:none;user-select:none;font-size:11px;font-weight:650}.fix-detail.svelte-1dm34m1 p:where(.svelte-1dm34m1){color:var(--text);white-space:pre-wrap;margin:8px 0 0;font-size:12.5px;line-height:1.45}.detail-grid.svelte-1dm34m1{flex:1;grid-template-columns:minmax(0,1fr) minmax(260px,320px);min-height:0;display:grid}.detail-grid.no-explanations.svelte-1dm34m1{grid-template-columns:minmax(0,1fr)}.diff-col.svelte-1dm34m1{flex-direction:column;min-width:0;display:flex;overflow:hidden auto}.file-path-bar.svelte-1dm34m1{border-bottom:1px solid var(--border-soft);background:var(--bg-elev);flex-shrink:0;align-items:center;gap:8px;min-width:0;padding:8px 14px;display:flex}.file-path-text.svelte-1dm34m1{font-family:var(--mono);color:var(--text-faint);text-overflow:ellipsis;white-space:nowrap;min-width:0;font-size:11px;overflow:hidden}.explain-col.svelte-1dm34m1{border-left:1px solid var(--border-soft);background:var(--bg-elev);flex-direction:column;gap:16px;padding:14px 16px;display:flex;overflow:auto}.explain-counter.svelte-1dm34m1{color:var(--text-dim);border:1px solid var(--border);background:var(--bg-card);align-self:flex-start;padding:3px 8px;font-size:10.5px;font-weight:650}.explain-col.svelte-1dm34m1 h3:where(.svelte-1dm34m1){letter-spacing:.06em;text-transform:uppercase;color:var(--text-faint);margin:0 0 4px;font-size:10.5px;font-weight:650}.explain-col.svelte-1dm34m1 .what:where(.svelte-1dm34m1){color:var(--text);margin:0;font-size:13px;line-height:1.45}.explain-col.svelte-1dm34m1 .fix:where(.svelte-1dm34m1){color:var(--text-dim);margin:0;font-size:13px;line-height:1.45}.backdrop.svelte-lfje9j{z-index:9;background:#00000059;position:fixed;inset:0}.drawer.svelte-lfje9j{background:var(--bg-card);border-left:1px solid var(--border);z-index:10;flex-direction:column;width:420px;transition:transform .2s;display:flex;position:fixed;top:0;bottom:0;right:0;transform:translate(100%)}.drawer.open.svelte-lfje9j{transform:translate(0)}.drawer-head.svelte-lfje9j{border-bottom:1px solid var(--border-soft);flex-shrink:0;justify-content:space-between;align-items:center;gap:8px;min-width:0;padding:12px 14px;display:flex}.drawer-title.svelte-lfje9j{flex:1;align-items:center;gap:8px;min-width:0;display:flex}.file-ref.svelte-lfje9j{flex-direction:column;gap:1px;min-width:0;display:flex;overflow:hidden}.name.svelte-lfje9j{color:var(--text);font-size:13px;font-weight:600;font-family:var(--mono);text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.dir.svelte-lfje9j{color:var(--text-faint);font-size:11px;font-family:var(--mono);text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.close.svelte-lfje9j{color:var(--text-faint);background:0 0;border:0;flex-shrink:0;padding:0;font-size:14px}.list.svelte-lfje9j{flex-direction:column;display:flex;overflow:auto}.item.svelte-lfje9j{border-bottom:1px solid var(--border-soft)}.item-head.svelte-lfje9j{text-align:left;background:0 0;border:0;border-left:2px solid #0000;align-items:center;gap:8px;width:100%;padding:10px 14px;display:flex}.status.svelte-lfje9j{border:1px solid #0000;flex-shrink:0;justify-content:center;align-items:center;width:14px;height:14px;font-size:10px;line-height:1;display:flex}.badge.svelte-lfje9j{flex-shrink:0;font-size:10px;font-weight:700}.what.svelte-lfje9j{color:var(--text);text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;font-size:12.5px;overflow:hidden}.chevron.svelte-lfje9j{color:var(--text-faint);flex-shrink:0;font-size:11px}.item-body.svelte-lfje9j{flex-direction:column;gap:14px;padding:0 14px 14px 20px;display:flex}.item-body.svelte-lfje9j h4:where(.svelte-lfje9j){letter-spacing:.06em;text-transform:uppercase;color:var(--text-faint);margin:0 0 4px;font-size:10px;font-weight:650}.item-body.svelte-lfje9j p:where(.svelte-lfje9j){color:var(--text);margin:0;font-size:13px;line-height:1.5}.item-body.svelte-lfje9j p.fix:where(.svelte-lfje9j){color:var(--text-dim)}.item-actions.svelte-lfje9j{flex-wrap:wrap;align-items:center;gap:8px;min-width:0;display:flex}.decision-group.svelte-lfje9j{border:1px solid var(--border);flex-shrink:0;width:fit-content;display:flex;overflow:hidden}.decision-group.corrected.svelte-lfje9j{border-color:color-mix(in srgb, var(--ok) 45%, var(--border));background:var(--ok-bg)}.corrected-label.svelte-lfje9j{color:var(--ok);padding:7px 14px;font-size:12px;font-weight:600}.decision-group.svelte-lfje9j button:where(.svelte-lfje9j){color:var(--text-dim);background:0 0;border:0;padding:7px 14px;font-size:12px;font-weight:600}.decision-group.svelte-lfje9j button:first-child.on:where(.svelte-lfje9j){background:var(--danger-bg);color:var(--danger)}.decision-group.svelte-lfje9j button:nth-child(2).on:where(.svelte-lfje9j){background:var(--fix-bg);color:var(--ok)}.decision-group.svelte-lfje9j button:where(.svelte-lfje9j)+button:where(.svelte-lfje9j){border-left:1px solid var(--border)}.decision-group.svelte-lfje9j .clear:where(.svelte-lfje9j){color:var(--text-faint);border-left:1px solid var(--border);padding:7px 10px}.fix-detail.svelte-lfje9j{border:1px solid var(--border);background:var(--ok-bg);padding:8px 10px}.fix-detail.svelte-lfje9j summary:where(.svelte-lfje9j){cursor:pointer;letter-spacing:.04em;text-transform:uppercase;color:var(--ok);-webkit-user-select:none;user-select:none;font-size:11px;font-weight:650}.fix-detail.svelte-lfje9j p:where(.svelte-lfje9j){color:var(--text);white-space:pre-wrap;margin:8px 0 0;font-size:12.5px;line-height:1.45}.footer.svelte-67e2dl{border-top:1px solid var(--border);background:var(--bg-elev);flex-shrink:0;justify-content:space-between;align-items:center;gap:12px;min-height:33px;padding:6px 16px;display:flex}.right.svelte-67e2dl{flex-wrap:wrap;justify-content:flex-end;align-items:center;gap:8px;display:flex}.reviewed.svelte-67e2dl{color:var(--text-faint);font-size:11px}.fix.svelte-67e2dl,.publish.svelte-67e2dl,.ghost.svelte-67e2dl,.purge.svelte-67e2dl{cursor:pointer;border:1px solid;padding:6px 12px;font-size:11.5px;font-weight:600}.fix.svelte-67e2dl{background:var(--fix-bg);border-color:var(--fix-border);color:var(--ok)}.publish.svelte-67e2dl{background:var(--publish-bg);border-color:var(--publish-border);color:var(--publish-text)}.ghost.svelte-67e2dl{border-color:var(--border);color:var(--text);background:0 0;font-weight:500}.ghost.svelte-67e2dl:hover{border-color:var(--accent)}.purge.svelte-67e2dl{border-color:var(--border);color:var(--danger);background:0 0;font-weight:500}.purge.svelte-67e2dl:hover{border-color:var(--danger)}.sidebar.svelte-xengl2{border-right:1px solid var(--border);background:var(--bg-elev);flex-direction:column;height:100%;min-height:0;padding:14px 0;display:flex;overflow:hidden}.sidebar.collapsed.svelte-xengl2{border-right:0}.mode-toggle.svelte-xengl2{border:1px solid var(--border);flex-shrink:0;margin:0 14px 12px;display:flex;overflow:hidden}.mode-toggle.svelte-xengl2 button:where(.svelte-xengl2){color:var(--text);background:0 0;border:0;flex:1;justify-content:center;align-items:center;gap:6px;padding:7px 8px;font-size:12px;display:flex}.mode-toggle.svelte-xengl2 button:where(.svelte-xengl2)+button:where(.svelte-xengl2){border-left:1px solid var(--border)}.mode-toggle.svelte-xengl2 button.on:where(.svelte-xengl2){background:var(--accent-soft)}.mode-label.svelte-xengl2{align-items:center;gap:6px;line-height:1;display:inline-flex}.count-badge.svelte-xengl2{font-family:var(--mono);border:1px solid color-mix(in srgb, var(--finding-sev,var(--border)) 45%, transparent);background:color-mix(in srgb, var(--finding-sev,var(--bg-card)) 18%, transparent);color:var(--finding-sev,var(--text-dim));justify-content:center;align-items:center;padding:2px 6px;font-size:10px;font-weight:700;line-height:1;display:inline-flex}.panel.svelte-xengl2{padding:0 14px 10px}.explore-panel.svelte-xengl2{flex-direction:column;flex:1;min-height:0;padding:0 0 10px;display:flex;overflow:hidden}.panel-chrome.svelte-xengl2{flex-shrink:0;padding:0 14px}.panel-scroll.svelte-xengl2{flex:1;min-height:0;padding:0 14px;overflow:hidden auto}h3.svelte-xengl2{letter-spacing:.06em;text-transform:uppercase;color:var(--text-faint);margin:0 0 8px;font-size:11.5px;font-weight:650}.index-tabs.svelte-xengl2{border-bottom:1px solid var(--border-soft);gap:12px;margin-bottom:8px;display:flex}.index-tabs.svelte-xengl2 button:where(.svelte-xengl2){letter-spacing:.06em;text-transform:uppercase;color:var(--text-faint);background:0 0;border:0;border-bottom:2px solid #0000;padding:0 0 6px;font-size:11.5px;font-weight:650}.index-tabs.svelte-xengl2 button.on:where(.svelte-xengl2){color:var(--text);border-bottom-color:var(--accent)}.files-toolbar.svelte-xengl2{justify-content:space-between;align-items:center;gap:6px;margin:-2px 0 8px;display:flex}.files-toolbar.svelte-xengl2 .tool:where(.svelte-xengl2){border:1px solid var(--border);background:var(--bg-card);width:26px;height:26px;color:var(--text-dim);justify-content:center;align-items:center;padding:0;display:inline-flex}.files-toolbar.svelte-xengl2 .tool:where(.svelte-xengl2):hover:not(:disabled){color:var(--text);border-color:var(--text-faint)}.files-toolbar.svelte-xengl2 .tool.on:where(.svelte-xengl2){background:var(--accent-soft);border-color:var(--border);color:var(--text)}.files-toolbar.svelte-xengl2 .tool:where(.svelte-xengl2):disabled{opacity:.35;cursor:default}.files-toolbar.svelte-xengl2 .tool-icon:where(.svelte-xengl2){width:14px;height:14px;display:block}.files-toolbar.svelte-xengl2 .seg:where(.svelte-xengl2){border:1px solid var(--border);display:flex;overflow:hidden}.files-toolbar.svelte-xengl2 .seg:where(.svelte-xengl2) .tool:where(.svelte-xengl2){background:0 0;border:0;border-radius:0}.files-toolbar.svelte-xengl2 .seg:where(.svelte-xengl2) .tool:where(.svelte-xengl2)+.tool:where(.svelte-xengl2){border-left:1px solid var(--border)}.files-toolbar.svelte-xengl2 .seg:where(.svelte-xengl2) .tool.on:where(.svelte-xengl2){background:var(--accent-soft)}.nav-list.svelte-xengl2{flex-direction:column;gap:2px;display:flex}.tree.svelte-xengl2{flex-direction:column;display:flex}.tree-row.svelte-xengl2{text-align:left;width:100%;color:var(--text);background:0 0;border:0;align-items:center;gap:4px;min-width:0;padding:2px 6px 2px 0;font-size:12px;display:flex;position:relative}.tree-row.svelte-xengl2:hover:not(:disabled){background:var(--bg-card)}.tree-row.dir.svelte-xengl2{color:var(--text-dim)}.tree-row.muted.svelte-xengl2{color:var(--text-faint);cursor:default}.tree-row.skipped.svelte-xengl2 .name:where(.svelte-xengl2){text-decoration:line-through;-webkit-text-decoration-color:var(--text-faint);text-decoration-color:var(--text-faint)}.tree-guides.svelte-xengl2{pointer-events:none;width:0;position:absolute;inset:0 auto 0 0}.tree-guide.svelte-xengl2{background:var(--border-soft);opacity:.9;width:1px;position:absolute;top:0;bottom:0}.tree-slot.svelte-xengl2{flex-shrink:0;justify-content:center;align-items:center;width:16px;height:16px;display:inline-flex}.caret.svelte-xengl2{color:var(--text-faint);font-size:10px;line-height:1}.mark.svelte-xengl2{width:9px;font-family:var(--mono);color:var(--text-faint);flex-shrink:0;font-size:9.5px;font-weight:700}.mark.add.svelte-xengl2{color:var(--diff-add-fg)}.mark.del.svelte-xengl2{color:var(--diff-del-fg)}.tree-row.svelte-xengl2 .name:where(.svelte-xengl2){text-overflow:ellipsis;white-space:nowrap;min-width:0;font-family:var(--mono);flex:1;font-size:11.5px;overflow:hidden}.tree-row.svelte-xengl2 .name-line:where(.svelte-xengl2){flex:1;align-items:baseline;gap:6px;min-width:0;display:flex;overflow:hidden}.tree-row.svelte-xengl2 .name-line:where(.svelte-xengl2) .name:where(.svelte-xengl2){text-overflow:ellipsis;flex:0 auto;overflow:hidden}.tree-row.svelte-xengl2 .name-line:where(.svelte-xengl2) .dir:where(.svelte-xengl2){text-overflow:ellipsis;white-space:nowrap;min-width:0;font-family:var(--mono);color:var(--text-faint);flex:1;font-size:10.5px;overflow:hidden}.tree-row.svelte-xengl2 .count:where(.svelte-xengl2),.group-link.svelte-xengl2 .count:where(.svelte-xengl2){color:var(--finding-sev,var(--danger));border:1px solid color-mix(in srgb, var(--finding-sev,var(--danger-border)) 55%, transparent);flex-shrink:0;padding:2px 5px;font-size:9.5px;font-weight:700;line-height:1}.tree-row.svelte-xengl2 .count.done:where(.svelte-xengl2),.group-link.svelte-xengl2 .count.done:where(.svelte-xengl2){color:var(--ok);border-color:var(--border)}.group-link.svelte-xengl2{min-width:0;color:var(--text);flex-direction:column;flex:1;gap:2px;padding:6px 8px 6px 0;font-size:12.5px;text-decoration:none;display:flex}.group-link.svelte-xengl2:hover{background:0 0}.group-item.svelte-xengl2{border-radius:0}.group-item.open.svelte-xengl2>.group-head-row:where(.svelte-xengl2){background:var(--bg-card)}.group-head-row.svelte-xengl2{align-items:flex-start;gap:0;display:flex}.group-head-row.svelte-xengl2:hover{background:var(--bg-card)}.group-caret.svelte-xengl2{width:20px;color:var(--text-faint);cursor:pointer;background:0 0;border:0;flex-shrink:0;justify-content:center;align-items:center;padding:8px 0 0;display:inline-flex}.group-caret.svelte-xengl2:hover{color:var(--text)}.group-files.svelte-xengl2{flex-direction:column;padding:0 0 4px 8px;display:flex}.row.svelte-xengl2{flex-wrap:wrap;align-items:center;gap:6px;display:flex}.group-link.svelte-xengl2 .number:where(.svelte-xengl2){color:var(--text-faint);flex-shrink:0;font-size:10px;font-weight:700}.kind-chip.svelte-xengl2{border:1px solid var(--border);background:var(--bg-card);flex-shrink:0;padding:1px 5px;font-size:10px;font-weight:700}.group-link.svelte-xengl2 .title:where(.svelte-xengl2){white-space:normal;overflow-wrap:anywhere;line-height:1.35;display:block}.group-link.svelte-xengl2 .row:where(.svelte-xengl2)>.count:where(.svelte-xengl2){margin-left:auto}.meta.svelte-xengl2{color:var(--text-faint);padding-left:0;font-size:11px}.group-files.svelte-xengl2 .tree-row.file.active:where(.svelte-xengl2){background:var(--accent-soft)}.findings-panel.svelte-xengl2{flex-direction:column;flex:1;min-height:0;display:flex;overflow:hidden}.findings-head.svelte-xengl2{justify-content:space-between;align-items:baseline;margin-bottom:8px;display:flex}.findings-head.svelte-xengl2 h3:where(.svelte-xengl2){margin:0}.reviewed.svelte-xengl2{color:var(--text-faint);font-size:10.5px}.progress.svelte-xengl2{background:var(--border-soft);flex-shrink:0;height:3px;margin-bottom:10px;overflow:hidden}.progress-bar.svelte-xengl2{background:var(--accent);height:100%}.findings-list.svelte-xengl2{flex-direction:column;flex:1;gap:4px;min-height:0;display:flex;overflow:hidden auto}.finding-row.svelte-xengl2{text-align:left;border:0;border-bottom:1px solid var(--border-soft);background:var(--bg-elev);border-left:2px solid #0000;flex-direction:column;width:100%;min-width:0;padding:8px 10px;display:flex}.finding-row.active.svelte-xengl2{background:var(--accent-soft)}.finding-row.svelte-xengl2 .top:where(.svelte-xengl2){flex-wrap:wrap;justify-content:space-between;align-items:center;gap:4px 6px;margin-bottom:3px;display:flex}.finding-row.svelte-xengl2 .left:where(.svelte-xengl2){flex-wrap:wrap;align-items:center;gap:4px 6px;min-width:0;display:flex}.status.svelte-xengl2{border:1px solid #0000;flex-shrink:0;justify-content:center;align-items:center;width:14px;height:14px;font-size:10px;line-height:1;display:flex}.number.svelte-xengl2{color:var(--text-faint);font-size:9.5px;font-weight:650}.badge.svelte-xengl2{font-size:9.5px;font-weight:700}.decision.svelte-xengl2{font-size:9.5px;font-weight:650}.what.svelte-xengl2{color:var(--text);overflow-wrap:anywhere;font-size:12.5px;line-height:1.35;display:block}.file-line.svelte-xengl2{color:var(--text-faint);font-size:10.5px;font-family:var(--mono);overflow-wrap:anywhere;margin-top:3px;display:block}.report-shell.svelte-1ipe5j3{flex-direction:column;flex:1;min-height:0;display:flex}.report.svelte-1ipe5j3{flex:1;min-height:0;display:grid}.content.svelte-1ipe5j3{flex-direction:column;gap:18px;min-height:0;padding:14px 20px 24px;display:flex;overflow:auto}.page.svelte-67dwv3{background:var(--bg);flex-direction:column;height:100vh;min-height:0;display:flex}.body.svelte-67dwv3{flex:1;min-height:0;display:flex}.body.svelte-67dwv3>.report-shell{flex:1;min-width:0}.ghost.on.svelte-67dwv3{background:var(--accent-soft);border-color:var(--accent)}.chrome.svelte-67dwv3{border-bottom:1px solid var(--border);background:var(--header-bg);flex-shrink:0;grid-template-columns:1fr auto 1fr;align-items:center;gap:16px;padding:12px 28px;display:grid}.chrome-left.svelte-67dwv3{justify-self:start;align-items:center;gap:12px;min-width:0;display:flex}.chrome-center.svelte-67dwv3{justify-self:center;align-items:center;gap:10px;display:flex}.chrome-right.svelte-67dwv3{justify-self:end;align-items:center;gap:10px;display:flex}.brand.svelte-67dwv3{color:var(--text);flex-shrink:0;align-items:center;gap:10px;font-size:15px;font-weight:700;text-decoration:none;display:flex}.brand-dot.svelte-67dwv3{background:linear-gradient(135deg,#6ea8fe,#c9a5ff);border-radius:50%;flex-shrink:0;width:9px;height:9px;box-shadow:0 0 12px #6ea8fe88}.chrome-divider.svelte-67dwv3{background:var(--border);flex-shrink:0;width:1px;height:18px}.breadcrumb.svelte-67dwv3{font-family:var(--mono);align-items:center;gap:6px;min-width:0;font-size:12.5px;display:flex}.crumb-branch.svelte-67dwv3{color:var(--text);text-overflow:ellipsis;white-space:nowrap;font-weight:600;overflow:hidden}.crumb-sep.svelte-67dwv3{color:var(--text-faint)}.crumb-base.svelte-67dwv3{color:var(--text-faint);white-space:nowrap}.provenance.svelte-67dwv3{min-width:0;color:var(--text-dim);align-items:center;gap:6px;font-size:12px;display:flex}.prov-agent.svelte-67dwv3{white-space:nowrap}.prov-sep.svelte-67dwv3{color:var(--text-faint)}.prov-model.svelte-67dwv3{font-family:var(--mono);text-overflow:ellipsis;white-space:nowrap;font-size:11.5px;overflow:hidden}.menu-wrap.svelte-67dwv3{flex-shrink:0;position:relative}.menu.svelte-67dwv3{z-index:40;border:1px solid var(--border);background:var(--bg-card);min-width:180px;padding:4px;position:absolute;top:calc(100% + 4px);left:0;box-shadow:0 8px 24px #0000002e}.download-menu.svelte-67dwv3{flex-direction:column;gap:0;min-width:220px;padding:4px;display:flex;left:auto;right:0}.menu-item.svelte-67dwv3{width:100%;color:var(--text);text-align:left;cursor:pointer;background:0 0;border:0;flex-direction:column;align-items:flex-start;gap:0;padding:4px 8px;font-size:12px;line-height:1.25;display:flex}.download-menu.svelte-67dwv3 button.menu-item:where(.svelte-67dwv3){box-sizing:border-box;z-index:0;height:44px;min-height:44px;color:var(--text);font:inherit;letter-spacing:normal;text-align:left;cursor:pointer;appearance:none;background:0 0;border:0;border-radius:2px;flex-direction:row;justify-content:space-between;align-items:center;gap:8px;margin:0;padding:0 10px;font-size:12px;font-weight:400;line-height:1.2;display:flex;position:relative;overflow:hidden}.download-menu.svelte-67dwv3 button.menu-item:where(.svelte-67dwv3):hover{z-index:1;background:var(--accent-soft)}.menu-item.svelte-67dwv3:hover{background:var(--accent-soft)}.menu-item.danger.svelte-67dwv3{color:var(--danger)}.menu-item.svelte-67dwv3 .fmt:where(.svelte-67dwv3){flex-shrink:0;font-weight:600;line-height:1.2}.menu-item.svelte-67dwv3 .hint:where(.svelte-67dwv3){color:var(--text-faint);font-size:10.5px;line-height:1.2}.download-menu.svelte-67dwv3 .menu-item:where(.svelte-67dwv3) .fmt:where(.svelte-67dwv3),.download-menu.svelte-67dwv3 .menu-item:where(.svelte-67dwv3) .hint:where(.svelte-67dwv3){pointer-events:none}.download-menu.svelte-67dwv3 .menu-item:where(.svelte-67dwv3) .hint:where(.svelte-67dwv3){text-align:right;white-space:nowrap;text-overflow:ellipsis;min-width:0;font-size:10px;overflow:hidden}.mode-toggle.svelte-67dwv3{border:1px solid var(--border);display:flex;overflow:hidden}.mode-toggle.svelte-67dwv3 button:where(.svelte-67dwv3){white-space:nowrap;color:var(--text);background:0 0;border:0;padding:6px 12px;font-size:12px}.mode-toggle.svelte-67dwv3 button:where(.svelte-67dwv3)+button:where(.svelte-67dwv3){border-left:1px solid var(--border)}.mode-toggle.svelte-67dwv3 button.on:where(.svelte-67dwv3){background:var(--accent-soft)}.zoom.svelte-67dwv3{align-items:center;gap:4px;display:flex}.icon-btn.svelte-67dwv3{background:var(--bg-card);border:1px solid var(--border);width:26px;height:26px;color:var(--text-dim);justify-content:center;align-items:center;padding:0;font-size:13px;display:flex}.icon-btn.svelte-67dwv3:hover{border-color:var(--accent);color:var(--text)}.icon-btn.on.svelte-67dwv3{background:var(--accent-soft);border-color:var(--accent);color:var(--text)}.icon-btn.kebab.svelte-67dwv3{background:0 0;border-color:#0000;width:24px;height:24px}.icon-btn.kebab.svelte-67dwv3:hover{border-color:var(--border);background:var(--bg-card)}.icon-btn.panel.svelte-67dwv3{font-size:15px}.icon-btn.svelte-67dwv3:disabled{opacity:.4;cursor:not-allowed}.zoom-label.svelte-67dwv3{font-family:var(--mono);color:var(--text-faint);text-align:center;width:30px;font-size:10.5px}.ghost.svelte-67dwv3{background:var(--bg-card);border:1px solid var(--border);color:var(--text);padding:7px 12px;font-size:12.5px}.agent-btn.svelte-67dwv3,.download-btn.svelte-67dwv3{align-items:center;gap:6px;display:inline-flex}.download-btn.svelte-67dwv3 .caret:where(.svelte-67dwv3){opacity:.7}.hint.svelte-67dwv3{color:var(--text-faint);padding:40px 28px;font-size:13px}
@@ -1 +1 @@
1
- .agent-icon.svelte-1o6iyhy{flex-shrink:0;justify-content:center;align-items:center;display:inline-flex}.agent-icon.svelte-1o6iyhy svg:where(.svelte-1o6iyhy){width:100%;height:100%;display:block}.agent-select.svelte-grhxa3{flex:1;width:100%;min-width:0;position:relative}.trigger.svelte-grhxa3{box-sizing:border-box;background:var(--bg-card);border:1px solid var(--border);width:100%;min-width:0;min-height:38px;color:var(--text);font:inherit;font-size:inherit;text-align:left;cursor:pointer;align-items:center;gap:8px;padding:9px 12px;display:flex}.trigger.svelte-grhxa3:hover:not(:disabled){border-color:var(--accent)}.trigger.svelte-grhxa3:disabled{opacity:.5;cursor:not-allowed}.label.svelte-grhxa3{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.label.muted.svelte-grhxa3{color:var(--text-faint)}.caret.svelte-grhxa3{opacity:.7;color:var(--text-dim);flex-shrink:0}.agent-select.open.svelte-grhxa3 .caret:where(.svelte-grhxa3){transform:rotate(180deg)}.menu.svelte-grhxa3{z-index:40;border:1px solid var(--border);background:var(--bg-card);flex-direction:column;gap:0;padding:4px;display:flex;position:absolute;top:calc(100% + 4px);left:0;right:0;box-shadow:0 8px 24px #0000002e}.option.svelte-grhxa3{width:100%;color:var(--text);font:inherit;font-size:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:2px;align-items:center;gap:8px;padding:8px 10px;display:flex}.option.svelte-grhxa3:hover,.option.selected.svelte-grhxa3{background:var(--accent-soft)}.theme-toggle.svelte-lu0t34{background:var(--bg-card);border:1px solid var(--border);width:30px;height:30px;color:var(--text-dim);flex-shrink:0;justify-content:center;align-items:center;padding:0;font-size:14px;display:flex}.theme-toggle.svelte-lu0t34:hover{border-color:var(--accent);color:var(--text)}.md.svelte-cxb0dt{color:var(--text);overflow-wrap:anywhere}.md.svelte-cxb0dt>:first-child{margin-top:0}.md.svelte-cxb0dt>:last-child{margin-bottom:0}.md.svelte-cxb0dt p,.md.svelte-cxb0dt ul,.md.svelte-cxb0dt ol,.md.svelte-cxb0dt pre,.md.svelte-cxb0dt blockquote{margin:.45em 0}.md.svelte-cxb0dt ul,.md.svelte-cxb0dt ol{padding-left:1.35em}.md.svelte-cxb0dt li{margin:.15em 0}.md.svelte-cxb0dt h1,.md.svelte-cxb0dt h2,.md.svelte-cxb0dt h3,.md.svelte-cxb0dt h4{margin:.7em 0 .35em;font-size:1em;font-weight:650;line-height:1.35}.md.svelte-cxb0dt h1{font-size:1.15em}.md.svelte-cxb0dt h2{font-size:1.08em}.md.svelte-cxb0dt a{color:var(--accent)}.md.svelte-cxb0dt code{font-family:var(--mono);background:var(--bg-card);border:1px solid var(--border-soft,var(--border));border-radius:4px;padding:.1em .35em;font-size:.92em}.md.svelte-cxb0dt pre{background:var(--bg-card);border:1px solid var(--border);border-radius:6px;padding:8px 10px;overflow-x:auto}.md.svelte-cxb0dt pre code{background:0 0;border:none;padding:0;font-size:12px;line-height:1.45}.md.svelte-cxb0dt blockquote{border-left:3px solid var(--border);color:var(--text-dim);padding-left:10px}.md.svelte-cxb0dt hr{border:none;border-top:1px solid var(--border);margin:.75em 0}.md.svelte-cxb0dt table{border-collapse:collapse;width:100%;font-size:12.5px}.md.svelte-cxb0dt th,.md.svelte-cxb0dt td{border:1px solid var(--border);text-align:left;padding:4px 8px}.md.svelte-cxb0dt th{background:var(--bg-card);font-weight:600}.perm-actions.svelte-1l4yk48{flex-wrap:wrap;gap:8px;display:flex}.perm-actions.svelte-1l4yk48 button:where(.svelte-1l4yk48){border:1px solid var(--border);background:var(--bg-elev);color:var(--text);border-radius:0;padding:5px 10px;font-size:12px}.perm-actions.svelte-1l4yk48 .allow:where(.svelte-1l4yk48),.perm-actions.svelte-1l4yk48 .allow-all:where(.svelte-1l4yk48){background:var(--ok-bg);border-color:var(--ok);color:var(--ok)}.perm-actions.svelte-1l4yk48 .deny:where(.svelte-1l4yk48),.perm-actions.svelte-1l4yk48 .deny-all:where(.svelte-1l4yk48){background:var(--danger-bg);border-color:var(--danger-border);color:var(--danger)}.log.svelte-18syxl5{flex-direction:column;gap:6px;min-height:0;font-size:13px;line-height:1.45;display:flex;overflow-y:auto}p.svelte-18syxl5{white-space:pre-wrap;overflow-wrap:anywhere;margin:0}.user.svelte-18syxl5{background:var(--accent-soft);border:1px solid var(--btn-primary-border);border-radius:0;align-self:flex-end;max-width:90%;padding:6px 10px}.tag.svelte-18syxl5{text-transform:uppercase;letter-spacing:.06em;color:var(--text-faint);font-size:10px;display:block}.message.svelte-18syxl5{color:var(--text);max-width:100%}.thought.svelte-18syxl5{color:var(--text-faint);font-size:12px}.thought.svelte-18syxl5 summary:where(.svelte-18syxl5){cursor:pointer;font-style:italic}.thought.svelte-18syxl5 p:where(.svelte-18syxl5){max-height:200px;margin-top:4px;overflow-y:auto}.tool.svelte-18syxl5{font-family:var(--mono);color:var(--text-dim);gap:6px;font-size:12px;display:flex}.tool.svelte-18syxl5 .mark:where(.svelte-18syxl5){width:12px;color:var(--ok);flex:none}.tool.failed.svelte-18syxl5 .mark:where(.svelte-18syxl5),.tool.failed.svelte-18syxl5 .title:where(.svelte-18syxl5){color:var(--danger)}.tool.svelte-18syxl5 .title:where(.svelte-18syxl5){text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.permission.svelte-18syxl5{color:var(--warn);font-size:12px}.permission.allowed.svelte-18syxl5{color:var(--ok)}.permission.pending.svelte-18syxl5{border:1px solid var(--warn);background:var(--bg-card);color:var(--text);border-radius:0;padding:8px 10px}.perm-head.svelte-18syxl5{text-transform:uppercase;letter-spacing:.05em;color:var(--warn);flex-wrap:wrap;align-items:center;gap:8px;font-size:11px;display:flex}.perm-head.svelte-18syxl5 .kind:where(.svelte-18syxl5){color:var(--text-faint);font-family:var(--mono);text-transform:none;letter-spacing:0}.perm-head.svelte-18syxl5 .counter:where(.svelte-18syxl5){font-variant-numeric:tabular-nums;color:var(--text-dim);text-transform:none;letter-spacing:0;font-family:var(--mono);margin-left:auto}.perm-head.svelte-18syxl5 .nav:where(.svelte-18syxl5){gap:2px;display:flex}.nav-btn.svelte-18syxl5{border:1px solid var(--border);background:var(--bg-elev);color:var(--text-dim);border-radius:0;padding:2px 6px;font-size:11px;line-height:1.2}.perm-subtitle.svelte-18syxl5{color:var(--text-faint);margin:4px 0 0;font-size:11.5px}.perm-title.svelte-18syxl5{font-family:var(--mono);margin:4px 0 0;font-size:12px}.perm-command.svelte-18syxl5{font-family:var(--mono);white-space:pre-wrap;overflow-wrap:anywhere;word-break:break-word;background:var(--bg-elev);border:1px solid var(--border);border-radius:0;max-width:100%;margin:6px 0 0;padding:8px 10px;font-size:11.5px;line-height:1.4}.perm-command.collapsed.svelte-18syxl5{max-height:10.5em;overflow:hidden}.perm-expand.svelte-18syxl5{color:var(--accent);cursor:pointer;background:0 0;border:none;border-radius:0;margin:4px 0 0;padding:0;font-size:11.5px;text-decoration:underline}.perm-expand.svelte-18syxl5:hover{color:var(--text)}.perm-reason.svelte-18syxl5{color:var(--text-faint);margin:2px 0 0;font-size:11.5px}.permission.pending.svelte-18syxl5 .perm-actions{margin-top:8px}.permission.svelte-18syxl5 span:where(.svelte-18syxl5){color:var(--text-faint)}.plan.svelte-18syxl5{color:var(--text-dim);margin:0;padding-left:18px;font-size:12px}.plan.svelte-18syxl5 li.done:where(.svelte-18syxl5){color:var(--text-faint);text-decoration:line-through}.review.svelte-18syxl5{border-radius:0;padding:6px 10px;font-size:12px}.review.ok.svelte-18syxl5{background:var(--ok-bg);color:var(--ok)}.review.bad.svelte-18syxl5 .retry:where(.svelte-18syxl5){border:1px solid var(--danger-border);background:var(--bg-elev);color:var(--text);cursor:pointer;border-radius:0;margin-top:8px;padding:5px 12px;font-size:12px}.review.bad.svelte-18syxl5 .retry:where(.svelte-18syxl5):hover:not(:disabled){border-color:var(--accent)}.review.bad.svelte-18syxl5 .retry:where(.svelte-18syxl5):disabled{opacity:.55;cursor:default}.review.bad.svelte-18syxl5,.error.svelte-18syxl5{background:var(--danger-bg);border:1px solid var(--danger-border);color:var(--danger);border-radius:0;padding:6px 10px;font-size:12px}.review.svelte-18syxl5 ul:where(.svelte-18syxl5){margin:4px 0 0;padding-left:16px}.note.svelte-18syxl5{color:var(--text-faint);font-size:12px}.working.svelte-18syxl5{gap:4px;padding:4px 0;display:flex}.working.svelte-18syxl5 span:where(.svelte-18syxl5){background:var(--text-faint);border-radius:50%;width:6px;height:6px;animation:1.2s ease-in-out infinite svelte-18syxl5-blink}.working.svelte-18syxl5 span:where(.svelte-18syxl5):nth-child(2){animation-delay:.2s}.working.svelte-18syxl5 span:where(.svelte-18syxl5):nth-child(3){animation-delay:.4s}@keyframes svelte-18syxl5-blink{0%,80%,to{opacity:.2}40%{opacity:1}}.trust.svelte-3jjxns{border:1px solid var(--border);background:var(--bg-card);text-align:left;cursor:pointer;-webkit-user-select:none;user-select:none;width:100%;font:inherit;border-radius:0;flex:none;align-items:center;gap:8px;padding:5px 8px;display:flex}.trust.inline.svelte-3jjxns{width:auto;max-width:100%;padding:4px 8px}.trust.on.svelte-3jjxns{border-color:color-mix(in srgb, var(--ok) 45%, var(--border));background:var(--ok-bg)}.trust.svelte-3jjxns:focus-visible{outline:2px solid var(--accent);outline-offset:2px}.switch.svelte-3jjxns{border:1px solid var(--border);background:var(--bg-elev);border-radius:999px;flex:none;width:30px;height:16px;transition:background .15s,border-color .15s;position:relative}.trust.on.svelte-3jjxns .switch:where(.svelte-3jjxns){background:var(--ok);border-color:var(--ok)}.knob.svelte-3jjxns{background:var(--text);opacity:.55;border-radius:50%;width:12px;height:12px;transition:transform .15s,background .15s,opacity .15s;position:absolute;top:1px;left:1px}.trust.on.svelte-3jjxns .knob:where(.svelte-3jjxns){background:var(--bg-card);opacity:1;transform:translate(14px)}.trust-text.svelte-3jjxns{flex-wrap:wrap;align-items:baseline;gap:4px;min-width:0;line-height:1.2;display:flex}.trust-text.svelte-3jjxns strong:where(.svelte-3jjxns){color:var(--text);font-size:12px;font-weight:600}.trust-text.svelte-3jjxns small:where(.svelte-3jjxns){color:var(--text-faint);font-size:11px}.model-select.svelte-9wkprr{flex:1;width:100%;min-width:0;position:relative}.trigger.svelte-9wkprr{box-sizing:border-box;background:var(--bg-card);border:1px solid var(--border);width:100%;min-width:0;min-height:38px;color:var(--text);font:inherit;font-size:inherit;text-align:left;cursor:pointer;align-items:center;gap:8px;padding:9px 12px;display:flex}.model-select.compact.svelte-9wkprr .trigger:where(.svelte-9wkprr){gap:6px;min-height:30px;padding:5px 10px;font-size:12px}.trigger.svelte-9wkprr:hover:not(:disabled){border-color:var(--accent)}.trigger.svelte-9wkprr:disabled{opacity:.5;cursor:not-allowed}.title.svelte-9wkprr{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.title.muted.svelte-9wkprr{color:var(--text-faint)}.badges.svelte-9wkprr{flex-wrap:wrap;flex-shrink:0;justify-content:flex-end;gap:4px;max-width:45%;display:flex}.badge.svelte-9wkprr{border:1px solid var(--border);background:var(--bg-elev,var(--bg-card));color:var(--text-dim,var(--text-faint));font-size:10px;line-height:1.35;font-family:var(--mono,ui-monospace, monospace);white-space:nowrap;border-radius:0;padding:0 5px}.hint.svelte-9wkprr{color:var(--text-faint);font-size:10px;font-family:var(--mono,ui-monospace, monospace);flex-shrink:0}.caret.svelte-9wkprr{opacity:.7;color:var(--text-dim);flex-shrink:0}.model-select.open.svelte-9wkprr .caret:where(.svelte-9wkprr){transform:rotate(180deg)}.menu.svelte-9wkprr{z-index:40;border:1px solid var(--border);background:var(--bg-card);flex-direction:column;max-height:min(360px,50vh);padding:4px;display:flex;position:absolute;inset:calc(100% + 4px) 0 auto;overflow:auto;box-shadow:0 8px 24px #0000002e}.model-select.drop-up.svelte-9wkprr .menu:where(.svelte-9wkprr){top:auto;bottom:calc(100% + 4px);box-shadow:0 -8px 24px #0000002e}.option.svelte-9wkprr{width:100%;color:var(--text);font:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:2px;align-items:center;gap:6px;padding:6px 8px;font-size:12px;display:flex}.option.svelte-9wkprr:hover,.option.selected.svelte-9wkprr{background:var(--accent-soft)}
1
+ .agent-icon.svelte-1o6iyhy{flex-shrink:0;justify-content:center;align-items:center;display:inline-flex}.agent-icon.svelte-1o6iyhy svg:where(.svelte-1o6iyhy){width:100%;height:100%;display:block}.agent-select.svelte-grhxa3{flex:1;width:100%;min-width:0;position:relative}.trigger.svelte-grhxa3{box-sizing:border-box;background:var(--bg-card);border:1px solid var(--border);width:100%;min-width:0;min-height:38px;color:var(--text);font:inherit;font-size:inherit;text-align:left;cursor:pointer;align-items:center;gap:8px;padding:9px 12px;display:flex}.trigger.svelte-grhxa3:hover:not(:disabled){border-color:var(--accent)}.trigger.svelte-grhxa3:disabled{opacity:.5;cursor:not-allowed}.label.svelte-grhxa3{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.label.muted.svelte-grhxa3{color:var(--text-faint)}.caret.svelte-grhxa3{opacity:.7;color:var(--text-dim);flex-shrink:0}.agent-select.open.svelte-grhxa3 .caret:where(.svelte-grhxa3){transform:rotate(180deg)}.menu.svelte-grhxa3{z-index:40;border:1px solid var(--border);background:var(--bg-card);flex-direction:column;gap:0;padding:4px;display:flex;position:absolute;top:calc(100% + 4px);left:0;right:0;box-shadow:0 8px 24px #0000002e}.option.svelte-grhxa3{width:100%;color:var(--text);font:inherit;font-size:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:2px;align-items:center;gap:8px;padding:8px 10px;display:flex}.option.svelte-grhxa3:hover,.option.selected.svelte-grhxa3{background:var(--accent-soft)}.theme-toggle.svelte-lu0t34{background:var(--bg-card);border:1px solid var(--border);width:30px;height:30px;color:var(--text-dim);flex-shrink:0;justify-content:center;align-items:center;padding:0;font-size:14px;display:flex}.theme-toggle.svelte-lu0t34:hover{border-color:var(--accent);color:var(--text)}.md.svelte-cxb0dt{color:var(--text);overflow-wrap:anywhere}.md.svelte-cxb0dt>:first-child{margin-top:0}.md.svelte-cxb0dt>:last-child{margin-bottom:0}.md.svelte-cxb0dt p,.md.svelte-cxb0dt ul,.md.svelte-cxb0dt ol,.md.svelte-cxb0dt pre,.md.svelte-cxb0dt blockquote{margin:.45em 0}.md.svelte-cxb0dt ul,.md.svelte-cxb0dt ol{padding-left:1.35em}.md.svelte-cxb0dt li{margin:.15em 0}.md.svelte-cxb0dt h1,.md.svelte-cxb0dt h2,.md.svelte-cxb0dt h3,.md.svelte-cxb0dt h4{margin:.7em 0 .35em;font-size:1em;font-weight:650;line-height:1.35}.md.svelte-cxb0dt h1{font-size:1.15em}.md.svelte-cxb0dt h2{font-size:1.08em}.md.svelte-cxb0dt a{color:var(--accent)}.md.svelte-cxb0dt code{font-family:var(--mono);background:var(--bg-card);border:1px solid var(--border-soft,var(--border));border-radius:4px;padding:.1em .35em;font-size:.92em}.md.svelte-cxb0dt pre{background:var(--bg-card);border:1px solid var(--border);border-radius:6px;padding:8px 10px;overflow-x:auto}.md.svelte-cxb0dt pre code{background:0 0;border:none;padding:0;font-size:12px;line-height:1.45}.md.svelte-cxb0dt blockquote{border-left:3px solid var(--border);color:var(--text-dim);padding-left:10px}.md.svelte-cxb0dt hr{border:none;border-top:1px solid var(--border);margin:.75em 0}.md.svelte-cxb0dt table{border-collapse:collapse;width:100%;font-size:12.5px}.md.svelte-cxb0dt th,.md.svelte-cxb0dt td{border:1px solid var(--border);text-align:left;padding:4px 8px}.md.svelte-cxb0dt th{background:var(--bg-card);font-weight:600}.perm-actions.svelte-1l4yk48{flex-wrap:wrap;gap:8px;display:flex}.perm-actions.svelte-1l4yk48 button:where(.svelte-1l4yk48){border:1px solid var(--border);background:var(--bg-elev);color:var(--text);border-radius:0;padding:5px 10px;font-size:12px}.perm-actions.svelte-1l4yk48 .allow:where(.svelte-1l4yk48),.perm-actions.svelte-1l4yk48 .allow-all:where(.svelte-1l4yk48){background:var(--ok-bg);border-color:var(--ok);color:var(--ok)}.perm-actions.svelte-1l4yk48 .deny:where(.svelte-1l4yk48),.perm-actions.svelte-1l4yk48 .deny-all:where(.svelte-1l4yk48){background:var(--danger-bg);border-color:var(--danger-border);color:var(--danger)}.log.svelte-18syxl5{flex-direction:column;gap:6px;min-height:0;font-size:13px;line-height:1.45;display:flex;overflow-y:auto}p.svelte-18syxl5{white-space:pre-wrap;overflow-wrap:anywhere;margin:0}.user.svelte-18syxl5{background:var(--accent-soft);border:1px solid var(--btn-primary-border);border-radius:0;align-self:flex-end;max-width:90%;padding:6px 10px}.tag.svelte-18syxl5{text-transform:uppercase;letter-spacing:.06em;color:var(--text-faint);font-size:10px;display:block}.message.svelte-18syxl5{color:var(--text);max-width:100%}.thought.svelte-18syxl5{color:var(--text-faint);font-size:12px}.thought.svelte-18syxl5 summary:where(.svelte-18syxl5){cursor:pointer;font-style:italic}.thought.svelte-18syxl5 p:where(.svelte-18syxl5){max-height:200px;margin-top:4px;overflow-y:auto}.tool.svelte-18syxl5{font-family:var(--mono);color:var(--text-dim);gap:6px;font-size:12px;display:flex}.tool.svelte-18syxl5 .mark:where(.svelte-18syxl5){width:12px;color:var(--ok);flex:none}.tool.failed.svelte-18syxl5 .mark:where(.svelte-18syxl5),.tool.failed.svelte-18syxl5 .title:where(.svelte-18syxl5){color:var(--danger)}.tool.svelte-18syxl5 .title:where(.svelte-18syxl5){text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.permission.svelte-18syxl5{color:var(--warn);font-size:12px}.permission.allowed.svelte-18syxl5{color:var(--ok)}.permission.pending.svelte-18syxl5{border:1px solid var(--warn);background:var(--bg-card);color:var(--text);border-radius:0;padding:8px 10px}.perm-head.svelte-18syxl5{text-transform:uppercase;letter-spacing:.05em;color:var(--warn);flex-wrap:wrap;align-items:center;gap:8px;font-size:11px;display:flex}.perm-head.svelte-18syxl5 .kind:where(.svelte-18syxl5){color:var(--text-faint);font-family:var(--mono);text-transform:none;letter-spacing:0}.perm-head.svelte-18syxl5 .counter:where(.svelte-18syxl5){font-variant-numeric:tabular-nums;color:var(--text-dim);text-transform:none;letter-spacing:0;font-family:var(--mono);margin-left:auto}.perm-head.svelte-18syxl5 .nav:where(.svelte-18syxl5){gap:2px;display:flex}.nav-btn.svelte-18syxl5{border:1px solid var(--border);background:var(--bg-elev);color:var(--text-dim);border-radius:0;padding:2px 6px;font-size:11px;line-height:1.2}.perm-subtitle.svelte-18syxl5{color:var(--text-faint);margin:4px 0 0;font-size:11.5px}.perm-title.svelte-18syxl5{font-family:var(--mono);margin:4px 0 0;font-size:12px}.perm-command.svelte-18syxl5{font-family:var(--mono);white-space:pre-wrap;overflow-wrap:anywhere;word-break:break-word;background:var(--bg-elev);border:1px solid var(--border);border-radius:0;max-width:100%;margin:6px 0 0;padding:8px 10px;font-size:11.5px;line-height:1.4}.perm-command.collapsed.svelte-18syxl5{max-height:10.5em;overflow:hidden}.perm-expand.svelte-18syxl5{color:var(--accent);cursor:pointer;background:0 0;border:none;border-radius:0;margin:4px 0 0;padding:0;font-size:11.5px;text-decoration:underline}.perm-expand.svelte-18syxl5:hover{color:var(--text)}.perm-reason.svelte-18syxl5{color:var(--text-faint);margin:2px 0 0;font-size:11.5px}.permission.pending.svelte-18syxl5 .perm-actions{margin-top:8px}.permission.svelte-18syxl5 span:where(.svelte-18syxl5){color:var(--text-faint)}.plan.svelte-18syxl5{color:var(--text-dim);margin:0;padding-left:18px;font-size:12px}.plan.svelte-18syxl5 li.done:where(.svelte-18syxl5){color:var(--text-faint);text-decoration:line-through}.review.svelte-18syxl5{border-radius:0;padding:6px 10px;font-size:12px}.review.ok.svelte-18syxl5{background:var(--ok-bg);color:var(--ok)}.review.bad.svelte-18syxl5 .retry:where(.svelte-18syxl5){border:1px solid var(--danger-border);background:var(--bg-elev);color:var(--text);cursor:pointer;border-radius:0;margin-top:8px;padding:5px 12px;font-size:12px}.review.bad.svelte-18syxl5 .retry:where(.svelte-18syxl5):hover:not(:disabled){border-color:var(--accent)}.review.bad.svelte-18syxl5 .retry:where(.svelte-18syxl5):disabled{opacity:.55;cursor:default}.review.bad.svelte-18syxl5,.error.svelte-18syxl5{background:var(--danger-bg);border:1px solid var(--danger-border);color:var(--danger);border-radius:0;padding:6px 10px;font-size:12px}.review.svelte-18syxl5 ul:where(.svelte-18syxl5){margin:4px 0 0;padding-left:16px}.note.svelte-18syxl5{color:var(--text-faint);font-size:12px}.working.svelte-18syxl5{gap:4px;padding:4px 0;display:flex}.working.svelte-18syxl5 span:where(.svelte-18syxl5){background:var(--text-faint);border-radius:50%;width:6px;height:6px;animation:1.2s ease-in-out infinite svelte-18syxl5-blink}.working.svelte-18syxl5 span:where(.svelte-18syxl5):nth-child(2){animation-delay:.2s}.working.svelte-18syxl5 span:where(.svelte-18syxl5):nth-child(3){animation-delay:.4s}@keyframes svelte-18syxl5-blink{0%,80%,to{opacity:.2}40%{opacity:1}}.trust.svelte-3jjxns{border:1px solid var(--border);background:var(--bg-card);text-align:left;cursor:pointer;-webkit-user-select:none;user-select:none;width:100%;font:inherit;border-radius:0;flex:none;align-items:center;gap:8px;padding:5px 8px;display:flex}.trust.inline.svelte-3jjxns{width:auto;max-width:100%;padding:4px 8px}.trust.on.svelte-3jjxns{border-color:color-mix(in srgb, var(--ok) 45%, var(--border));background:var(--ok-bg)}.trust.svelte-3jjxns:focus-visible{outline:2px solid var(--accent);outline-offset:2px}.switch.svelte-3jjxns{border:1px solid var(--border);background:var(--bg-elev);border-radius:999px;flex:none;width:30px;height:16px;transition:background .15s,border-color .15s;position:relative}.trust.on.svelte-3jjxns .switch:where(.svelte-3jjxns){background:var(--ok);border-color:var(--ok)}.knob.svelte-3jjxns{background:var(--text);opacity:.55;border-radius:50%;width:12px;height:12px;transition:transform .15s,background .15s,opacity .15s;position:absolute;top:1px;left:1px}.trust.on.svelte-3jjxns .knob:where(.svelte-3jjxns){background:var(--bg-card);opacity:1;transform:translate(14px)}.trust-text.svelte-3jjxns{flex-wrap:wrap;align-items:baseline;gap:4px;min-width:0;line-height:1.2;display:flex}.trust-text.svelte-3jjxns strong:where(.svelte-3jjxns){color:var(--text);font-size:12px;font-weight:600}.trust-text.svelte-3jjxns small:where(.svelte-3jjxns){color:var(--text-faint);font-size:11px}.model-select.svelte-9wkprr{flex:1;width:100%;min-width:0;position:relative}.trigger.svelte-9wkprr{box-sizing:border-box;background:var(--bg-card);border:1px solid var(--border);width:100%;min-width:0;min-height:38px;color:var(--text);font:inherit;font-size:inherit;text-align:left;cursor:pointer;align-items:center;gap:8px;padding:9px 12px;display:flex}.model-select.compact.svelte-9wkprr .trigger:where(.svelte-9wkprr){gap:6px;min-height:30px;padding:5px 10px;font-size:12px}.trigger.svelte-9wkprr:hover:not(:disabled){border-color:var(--accent)}.trigger.svelte-9wkprr:disabled{opacity:.5;cursor:not-allowed}.title.svelte-9wkprr{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.title.muted.svelte-9wkprr{color:var(--text-faint)}.badges.svelte-9wkprr{flex-wrap:wrap;flex-shrink:0;justify-content:flex-end;gap:4px;max-width:45%;display:flex}.badge.svelte-9wkprr{border:1px solid var(--border);background:var(--bg-elev,var(--bg-card));color:var(--text-dim,var(--text-faint));font-size:10px;line-height:1.35;font-family:var(--mono,ui-monospace, monospace);white-space:nowrap;border-radius:0;padding:0 5px}.hint.svelte-9wkprr{color:var(--text-faint);font-size:10px;font-family:var(--mono,ui-monospace, monospace);flex-shrink:0}.caret.svelte-9wkprr{opacity:.7;color:var(--text-dim);flex-shrink:0}.model-select.open.svelte-9wkprr .caret:where(.svelte-9wkprr){transform:rotate(180deg)}.menu.svelte-9wkprr{z-index:40;border:1px solid var(--border);background:var(--bg-card);flex-direction:column;max-height:min(360px,50vh);padding:4px;display:flex;position:absolute;inset:calc(100% + 4px) 0 auto;overflow:auto;box-shadow:0 8px 24px #0000002e}.model-select.compact.svelte-9wkprr .menu:where(.svelte-9wkprr){width:max-content;min-width:max(100%,280px);max-width:min(360px,90vw);left:auto;right:0}.model-select.compact.svelte-9wkprr .option:where(.svelte-9wkprr) .title:where(.svelte-9wkprr){white-space:normal;text-overflow:unset;overflow:visible}.model-select.drop-up.svelte-9wkprr .menu:where(.svelte-9wkprr){top:auto;bottom:calc(100% + 4px);box-shadow:0 -8px 24px #0000002e}.option.svelte-9wkprr{width:100%;color:var(--text);font:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:2px;align-items:center;gap:6px;padding:6px 8px;font-size:12px;display:flex}.option.svelte-9wkprr:hover,.option.selected.svelte-9wkprr{background:var(--accent-soft)}
@@ -0,0 +1 @@
1
+ import{ot as e}from"./CXhIC34H.js";typeof window<`u`&&((window.__svelte??={}).v??=new Set).add(`5`),e();
@@ -0,0 +1 @@
1
+ �3�import{ot as e}from"./CXhIC34H.js";typeof window<`u`&&((window.__svelte??={}).v??=new Set).add(`5`),e();