feat(draw): d2 diagram template — compile d2 source to SVG (T-494)
The d2 drawing template compiles a diagram's source to SVG through the d2 binary (resolved via the D-104 path layer), then paints it with the same renderer the svg card uses. `clide draw --file x.d2` infers the type from the extension; `.svg` files render directly. Template handlers now return a DrawResult so a compile failure or an unresolved d2 surface as an honest userError with an install hint, not a generic "no SVG". Real d2 0.7.1 verified end to end. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -8867,3 +8867,23 @@ First run: auto-detect each tool ONCE — probe the login-shell PATH + well-know
|
||||
Storage: user-scope SettingsStore keyed by machine (D-93) — never committed. Surface in the Config tab (T-414) + flag unresolved tools in the Problems panel (echoes D-58''s soft floor). Generalizes D-58''s CLIDE_PQL_BIN override to all supporter tools. First consumer: the d2 template (T-494).
|
||||
|
||||
RESOLUTION CORE DONE (2026-06-28): functional path resolution built + wired + tested (14 dart-test cases). SupporterBinaries resolver (lib/src/env/supporter_binaries.dart): explicit override -> login-shell/process PATH -> well-known dirs INCLUDING Homebrew-on-Linux (the D-104 gap). loadSupporterBinaries: first-run auto-detect + persist (pinned, not re-probed); isStalePin flags a moved tool. Boot wiring in main.dart exposes the process-wide activeSupporterBinaries. This UNBLOCKS T-494 — the d2 template resolves d2 via activeSupporterBinaries.resolve(''d2''). REMAINING (UI follow-ons, not gating T-494): Config-tab override editor (view/edit/clear paths), a re-detect action, and Problems-panel surfacing of unresolved tools.', NULL, '2026-06-28 21:08:40', '2026-06-28 21:08:40.178', '2026-06-28 21:08:40.178', NULL, 'f155f8e589cd19c3cc52409495d24f50', 2) ON CONFLICT(hash) DO NOTHING;
|
||||
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FGYPJ6FTEPP4JK3D7D01ZSMM', 'description', 'Implement D-104. clide resolves external supporter binaries (claude, d2, future supporter tools) via an explicit user-scope ''tools:'' map (name → absolute path), consulted FIRST.
|
||||
|
||||
Resolution order: (1) explicit settings path → use it; honest error + fallback-with-warning if missing/non-exec. (2) bundled/pinned (pql D-58, git D-59). (3) login-shell PATH (T-439). (4) bare PATH.
|
||||
|
||||
First run: auto-detect each tool ONCE — probe the login-shell PATH + well-known dirs (~/.local/bin, /usr/local/bin, /opt/homebrew, /home/linuxbrew/.linuxbrew/bin) — and WRITE the discovered absolute paths into the map (pinned, not re-probed each launch). Provide a re-detect action.
|
||||
|
||||
Storage: user-scope SettingsStore keyed by machine (D-93) — never committed. Surface in the Config tab (T-414) + flag unresolved tools in the Problems panel (echoes D-58''s soft floor). Generalizes D-58''s CLIDE_PQL_BIN override to all supporter tools. First consumer: the d2 template (T-494).
|
||||
|
||||
RESOLUTION CORE DONE (2026-06-28): functional path resolution built + wired + tested (14 dart-test cases). SupporterBinaries resolver (lib/src/env/supporter_binaries.dart): explicit override -> login-shell/process PATH -> well-known dirs INCLUDING Homebrew-on-Linux (the D-104 gap). loadSupporterBinaries: first-run auto-detect + persist (pinned, not re-probed); isStalePin flags a moved tool. Boot wiring in main.dart exposes the process-wide activeSupporterBinaries. This UNBLOCKS T-494 — the d2 template resolves d2 via activeSupporterBinaries.resolve(''d2''). REMAINING (UI follow-ons, not gating T-494): Config-tab override editor (view/edit/clear paths), a re-detect action, and Problems-panel surfacing of unresolved tools.', 'Implement D-104. clide resolves external supporter binaries (claude, d2, future supporter tools) via an explicit user-scope ''tools:'' map (name → absolute path), consulted FIRST.
|
||||
|
||||
Resolution order: (1) explicit settings path → use it; honest error + fallback-with-warning if missing/non-exec. (2) bundled/pinned (pql D-58, git D-59). (3) login-shell PATH (T-439). (4) bare PATH.
|
||||
|
||||
First run: auto-detect each tool ONCE — probe the login-shell PATH + well-known dirs (~/.local/bin, /usr/local/bin, /opt/homebrew, /home/linuxbrew/.linuxbrew/bin) — and WRITE the discovered absolute paths into the map (pinned, not re-probed each launch). Provide a re-detect action.
|
||||
|
||||
Storage: user-scope SettingsStore keyed by machine (D-93) — never committed. Surface in the Config tab (T-414) + flag unresolved tools in the Problems panel (echoes D-58''s soft floor). Generalizes D-58''s CLIDE_PQL_BIN override to all supporter tools. First consumer: the d2 template (T-494).
|
||||
|
||||
RESOLUTION CORE DONE (2026-06-28): functional path resolution built + wired + tested (14 dart-test cases). SupporterBinaries resolver (lib/src/env/supporter_binaries.dart): explicit override -> login-shell/process PATH -> well-known dirs INCLUDING Homebrew-on-Linux (the D-104 gap). loadSupporterBinaries: first-run auto-detect + persist (pinned, not re-probed); isStalePin flags a moved tool. Boot wiring in main.dart exposes the process-wide activeSupporterBinaries. This UNBLOCKS T-494 — the d2 template resolves d2 via activeSupporterBinaries.resolve(''d2''). REMAINING (UI follow-ons, not gating T-494): Config-tab override editor (view/edit/clear paths), a re-detect action, and Problems-panel surfacing of unresolved tools.
|
||||
|
||||
DONE (2026-06-29): full D-104 surface landed + fast suite green. UI complete — Tools settings category (per-tool path field app.tools.<name> + Re-detect action tools.detect, live resolver rebuild on edit, en+nl catalogs) in new builtin.tools-settings; Problems panel flags a stale/broken pinned path. Storage is per-tool keys + a first-run marker. Commits dab0b319/0adccc5c/62418b40/bd4a8332/3be063d6/eac9612a/67edf732.', NULL, '2026-06-29 07:32:43', '2026-06-29 07:32:43.640', '2026-06-29 07:32:43.640', NULL, '0dfb6eeb1bcde2f386379f029fa4d0f6', 2) ON CONFLICT(hash) DO NOTHING;
|
||||
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FGYPJ6FTEPP4JK3D7D01ZSMM', 'status', 'in_progress', 'done', NULL, '2026-06-29 07:32:43', '2026-06-29 07:32:43.682', '2026-06-29 07:32:43.682', NULL, '45aeefee25353af62e4aa9f7b1f3265c', 2) ON CONFLICT(hash) DO NOTHING;
|
||||
|
||||
@@ -10656,3 +10656,25 @@ First run: auto-detect each tool ONCE — probe the login-shell PATH + well-know
|
||||
Storage: user-scope SettingsStore keyed by machine (D-93) — never committed. Surface in the Config tab (T-414) + flag unresolved tools in the Problems panel (echoes D-58''s soft floor). Generalizes D-58''s CLIDE_PQL_BIN override to all supporter tools. First consumer: the d2 template (T-494).
|
||||
|
||||
RESOLUTION CORE DONE (2026-06-28): functional path resolution built + wired + tested (14 dart-test cases). SupporterBinaries resolver (lib/src/env/supporter_binaries.dart): explicit override -> login-shell/process PATH -> well-known dirs INCLUDING Homebrew-on-Linux (the D-104 gap). loadSupporterBinaries: first-run auto-detect + persist (pinned, not re-probed); isStalePin flags a moved tool. Boot wiring in main.dart exposes the process-wide activeSupporterBinaries. This UNBLOCKS T-494 — the d2 template resolves d2 via activeSupporterBinaries.resolve(''d2''). REMAINING (UI follow-ons, not gating T-494): Config-tab override editor (view/edit/clear paths), a re-detect action, and Problems-panel surfacing of unresolved tools.', 'in_progress', 'medium', NULL, NULL, 'D-104', '2026-06-28 17:50:02.366', '2026-06-28 21:08:40.177', NULL, '7e1f7077abd788309d38a51f8a3b1348', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
|
||||
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FGYPJ6FTEPP4JK3D7D01ZSMM', 'task', NULL, 'Supporter-binary path resolution: explicit user-scope overrides + first-run auto-detect', 'Implement D-104. clide resolves external supporter binaries (claude, d2, future supporter tools) via an explicit user-scope ''tools:'' map (name → absolute path), consulted FIRST.
|
||||
|
||||
Resolution order: (1) explicit settings path → use it; honest error + fallback-with-warning if missing/non-exec. (2) bundled/pinned (pql D-58, git D-59). (3) login-shell PATH (T-439). (4) bare PATH.
|
||||
|
||||
First run: auto-detect each tool ONCE — probe the login-shell PATH + well-known dirs (~/.local/bin, /usr/local/bin, /opt/homebrew, /home/linuxbrew/.linuxbrew/bin) — and WRITE the discovered absolute paths into the map (pinned, not re-probed each launch). Provide a re-detect action.
|
||||
|
||||
Storage: user-scope SettingsStore keyed by machine (D-93) — never committed. Surface in the Config tab (T-414) + flag unresolved tools in the Problems panel (echoes D-58''s soft floor). Generalizes D-58''s CLIDE_PQL_BIN override to all supporter tools. First consumer: the d2 template (T-494).
|
||||
|
||||
RESOLUTION CORE DONE (2026-06-28): functional path resolution built + wired + tested (14 dart-test cases). SupporterBinaries resolver (lib/src/env/supporter_binaries.dart): explicit override -> login-shell/process PATH -> well-known dirs INCLUDING Homebrew-on-Linux (the D-104 gap). loadSupporterBinaries: first-run auto-detect + persist (pinned, not re-probed); isStalePin flags a moved tool. Boot wiring in main.dart exposes the process-wide activeSupporterBinaries. This UNBLOCKS T-494 — the d2 template resolves d2 via activeSupporterBinaries.resolve(''d2''). REMAINING (UI follow-ons, not gating T-494): Config-tab override editor (view/edit/clear paths), a re-detect action, and Problems-panel surfacing of unresolved tools.
|
||||
|
||||
DONE (2026-06-29): full D-104 surface landed + fast suite green. UI complete — Tools settings category (per-tool path field app.tools.<name> + Re-detect action tools.detect, live resolver rebuild on edit, en+nl catalogs) in new builtin.tools-settings; Problems panel flags a stale/broken pinned path. Storage is per-tool keys + a first-run marker. Commits dab0b319/0adccc5c/62418b40/bd4a8332/3be063d6/eac9612a/67edf732.', 'in_progress', 'medium', NULL, NULL, 'D-104', '2026-06-28 17:50:02.366', '2026-06-29 07:32:43.640', NULL, '5047cde2263e4df79fef6f4718f948fa', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
|
||||
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FGYPJ6FTEPP4JK3D7D01ZSMM', 'task', NULL, 'Supporter-binary path resolution: explicit user-scope overrides + first-run auto-detect', 'Implement D-104. clide resolves external supporter binaries (claude, d2, future supporter tools) via an explicit user-scope ''tools:'' map (name → absolute path), consulted FIRST.
|
||||
|
||||
Resolution order: (1) explicit settings path → use it; honest error + fallback-with-warning if missing/non-exec. (2) bundled/pinned (pql D-58, git D-59). (3) login-shell PATH (T-439). (4) bare PATH.
|
||||
|
||||
First run: auto-detect each tool ONCE — probe the login-shell PATH + well-known dirs (~/.local/bin, /usr/local/bin, /opt/homebrew, /home/linuxbrew/.linuxbrew/bin) — and WRITE the discovered absolute paths into the map (pinned, not re-probed each launch). Provide a re-detect action.
|
||||
|
||||
Storage: user-scope SettingsStore keyed by machine (D-93) — never committed. Surface in the Config tab (T-414) + flag unresolved tools in the Problems panel (echoes D-58''s soft floor). Generalizes D-58''s CLIDE_PQL_BIN override to all supporter tools. First consumer: the d2 template (T-494).
|
||||
|
||||
RESOLUTION CORE DONE (2026-06-28): functional path resolution built + wired + tested (14 dart-test cases). SupporterBinaries resolver (lib/src/env/supporter_binaries.dart): explicit override -> login-shell/process PATH -> well-known dirs INCLUDING Homebrew-on-Linux (the D-104 gap). loadSupporterBinaries: first-run auto-detect + persist (pinned, not re-probed); isStalePin flags a moved tool. Boot wiring in main.dart exposes the process-wide activeSupporterBinaries. This UNBLOCKS T-494 — the d2 template resolves d2 via activeSupporterBinaries.resolve(''d2''). REMAINING (UI follow-ons, not gating T-494): Config-tab override editor (view/edit/clear paths), a re-detect action, and Problems-panel surfacing of unresolved tools.
|
||||
|
||||
DONE (2026-06-29): full D-104 surface landed + fast suite green. UI complete — Tools settings category (per-tool path field app.tools.<name> + Re-detect action tools.detect, live resolver rebuild on edit, en+nl catalogs) in new builtin.tools-settings; Problems panel flags a stale/broken pinned path. Storage is per-tool keys + a first-run marker. Commits dab0b319/0adccc5c/62418b40/bd4a8332/3be063d6/eac9612a/67edf732.', 'done', 'medium', NULL, NULL, 'D-104', '2026-06-28 17:50:02.366', '2026-06-29 07:32:43.682', NULL, '70724bd4ac9c1da06f8d1c252492a4b0', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
|
||||
|
||||
Reference in New Issue
Block a user