docs(governance): D-104 — explicit supporter-binary path overrides (T-495)
clide resolves external supporter binaries (claude, d2, future tools) via an explicit user-scope tools: map (name → absolute path), consulted first. First run auto-detects each tool once and writes the discovered absolute paths into the map — a one-time populate, pinned thereafter, not a per-launch heuristic. Escapes the login-shell-probe brittleness (T-439 misses brew when shellenv lives only in ~/.bashrc) while staying zero- config for standard installs. User-scope only (D-93); generalizes D-58's CLIDE_PQL_BIN override. Filed T-495; gates the d2 template (T-494). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -54,3 +54,4 @@ INSERT INTO ticket_deps (blocker_record_id, blocked_record_id, created_at, updat
|
||||
INSERT INTO ticket_deps (blocker_record_id, blocked_record_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FB2ERREMEEF26KKHGNZBWW64', '06FB2AD3HPR3HXSVASVZEX8PK0', '2026-06-28 15:30:00.399', '2026-06-28 15:30:00.399', NULL, 'e0961be9550747530f530a7fd300583f', 2) ON CONFLICT(blocker_record_id, blocked_record_id) DO UPDATE SET updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_deps.updated_at OR (excluded.updated_at = ticket_deps.updated_at AND excluded.hash > ticket_deps.hash);
|
||||
INSERT INTO ticket_deps (blocker_record_id, blocked_record_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FB2ERREMEEF26KKHGNZBWW64', '06FGX26B0NAC9WRJMVB0QE6CV8', '2026-06-28 15:30:03.803', '2026-06-28 15:30:03.803', NULL, 'fa47a4a4aff706215efa3a449681d18f', 2) ON CONFLICT(blocker_record_id, blocked_record_id) DO UPDATE SET updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_deps.updated_at OR (excluded.updated_at = ticket_deps.updated_at AND excluded.hash > ticket_deps.hash);
|
||||
INSERT INTO ticket_deps (blocker_record_id, blocked_record_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FB2G2KHKT5CJYR0TK1WQGMD0', '06FB2EV29HSK6EJ5VF50R87VC4', '2026-06-28 15:30:10.567', '2026-06-28 15:30:10.567', NULL, '52cd02f3a176cd078db479ef850cbcf4', 2) ON CONFLICT(blocker_record_id, blocked_record_id) DO UPDATE SET updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_deps.updated_at OR (excluded.updated_at = ticket_deps.updated_at AND excluded.hash > ticket_deps.hash);
|
||||
INSERT INTO ticket_deps (blocker_record_id, blocked_record_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FGYPJ6FTEPP4JK3D7D01ZSMM', '06FGX26B0NAC9WRJMVB0QE6CV8', '2026-06-28 17:50:13.767', '2026-06-28 17:50:13.767', NULL, '3e0ac1d814ac13a12b68714c7320075f', 2) ON CONFLICT(blocker_record_id, blocked_record_id) DO UPDATE SET updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_deps.updated_at OR (excluded.updated_at = ticket_deps.updated_at AND excluded.hash > ticket_deps.hash);
|
||||
|
||||
@@ -8065,3 +8065,25 @@ SCHEMA DRAFTED (2026-06-28): docs/design/drawing-card-schema.md — declarative
|
||||
MODEL CLARIFICATION (user): we build clide''s OWN native Flutter CustomPaint interpreting a declarative scene-graph document. We do NOT port the HTML Canvas 2D API — ''HTML canvas'' in D-91 is only the mental model (a general drawing surface, chosen to reject Obsidian''s .canvas schema), not an API to implement. The declarative model is closer to SVG/a retained scene-graph than to canvas''s imperative 2D context.
|
||||
|
||||
RESCOPED (D-103, 2026-06-28): the primitive layer is now SVG and the SVG renderer (T-320) is the engine — so T-318 is NO LONGER a primitive renderer. T-318 = the document envelope ({template? | svg/svgPath}, card metadata), the template DISPATCH, and the clide FLUTTER OVERLAY: per-object label/description caption widgets + lightbox affordance, anchored to SVG elements via data-label / data-description / data-lightbox. Now blocked by T-320 (engine first). Schema: docs/design/drawing-card-schema.md.', NULL, '2026-06-28 15:30:33', '2026-06-28 15:30:33.771', '2026-06-28 15:30:33.771', NULL, '6298b402fc49547c7bdba1f3d5626bed', 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 ('06FGX26B0NAC9WRJMVB0QE6CV8', 'description', 'A conversation-pane drawing card (peer of the SVG card T-320) that renders a D2 diagram. SEPARATE card type from SVG, but the ONLY difference is a compile step in front: D2 source → compile to SVG → render through the SAME SVG widget (T-320). Blocked on T-320 for that reason.
|
||||
|
||||
CLI/parity (D-6): driven via the drawing-card dispatch (T-318) — ''clide draw --file pipeline.d2'' (type inferred from .d2), or template:"d2" with inline source in the drawing-card JSON. Honest userError on a d2 compile failure (bad source), mirroring image/svg validation.
|
||||
|
||||
UX: the rendered diagram LEADS; the d2 source folds into a collapsed ''view d2 source'' disclosure on the card (ClideCollapserCard pattern, T-305) so the code doesn''t dominate. Display-only per D-78.
|
||||
|
||||
Open: D2 compiler dependency — d2 is Go (there is a d2-diagram skill). Decide whether to shell out to a d2 binary (supporter-tool pattern, peer of pql) or vendor it; flag before building. Wireframe: docs/design/wireframes/conversation/d2-render-card.png.', 'A conversation-pane drawing card (peer of the SVG card T-320) that renders a D2 diagram. SEPARATE card type from SVG, but the ONLY difference is a compile step in front: D2 source → compile to SVG → render through the SAME SVG widget (T-320). Blocked on T-320 for that reason.
|
||||
|
||||
CLI/parity (D-6): driven via the drawing-card dispatch (T-318) — ''clide draw --file pipeline.d2'' (type inferred from .d2), or template:"d2" with inline source in the drawing-card JSON. Honest userError on a d2 compile failure (bad source), mirroring image/svg validation.
|
||||
|
||||
UX: the rendered diagram LEADS; the d2 source folds into a collapsed ''view d2 source'' disclosure on the card (ClideCollapserCard pattern, T-305) so the code doesn''t dominate. Display-only per D-78.
|
||||
|
||||
Open: D2 compiler dependency — d2 is Go (there is a d2-diagram skill). Decide whether to shell out to a d2 binary (supporter-tool pattern, peer of pql) or vendor it; flag before building. Wireframe: docs/design/wireframes/conversation/d2-render-card.png.
|
||||
|
||||
PATH / tool-resolution dependency (2026-06-28): the d2 compile step shells out to the ''d2'' binary, so it relies on clide resolving d2 on PATH. clide already derives a login-shell PATH for every spawned tool — T-439 (consolidated the Linux PATH fix T-347), both DONE — so this is very likely already covered. ACCEPTANCE: verify clide resolves ''d2'' via that login-shell PATH on a Homebrew/linuxbrew install (d2 lives in /home/linuxbrew/.linuxbrew/bin). WATCH: a ''$SHELL -lc'' login probe can miss brew if ''brew shellenv'' is only in ~/.bashrc (login shells source .bash_profile/.profile, not .bashrc); if so, that''s a real follow-up on T-439''s probe surfaced from here. Honest userError if d2 is unresolved, hinting how to install/locate it. (The ''command -v d2'' miss seen during design was Claude Code''s own lean sandbox PATH, not clide.)', NULL, '2026-06-28 16:18:22', '2026-06-28 16:18:22.531', '2026-06-28 16:18:22.531', NULL, 'dc5a34f7af2980ed5caac6be224670c4', 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', NULL, '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).', NULL, '2026-06-28 17:50:13', '2026-06-28 17:50:13.728', '2026-06-28 17:50:13.728', NULL, 'db0f73d19a558e556733e8b42ef7081a', 2) ON CONFLICT(hash) DO NOTHING;
|
||||
|
||||
@@ -9927,3 +9927,20 @@ SCHEMA DRAFTED (2026-06-28): docs/design/drawing-card-schema.md — declarative
|
||||
MODEL CLARIFICATION (user): we build clide''s OWN native Flutter CustomPaint interpreting a declarative scene-graph document. We do NOT port the HTML Canvas 2D API — ''HTML canvas'' in D-91 is only the mental model (a general drawing surface, chosen to reject Obsidian''s .canvas schema), not an API to implement. The declarative model is closer to SVG/a retained scene-graph than to canvas''s imperative 2D context.
|
||||
|
||||
RESCOPED (D-103, 2026-06-28): the primitive layer is now SVG and the SVG renderer (T-320) is the engine — so T-318 is NO LONGER a primitive renderer. T-318 = the document envelope ({template? | svg/svgPath}, card metadata), the template DISPATCH, and the clide FLUTTER OVERLAY: per-object label/description caption widgets + lightbox affordance, anchored to SVG elements via data-label / data-description / data-lightbox. Now blocked by T-320 (engine first). Schema: docs/design/drawing-card-schema.md.', 'backlog', 'medium', NULL, NULL, NULL, '2026-06-10 11:11:40', '2026-06-28 15:30:33.771', NULL, '98e798ae1f9749ff4d6895b5ad15cbd9', 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 ('06FGX26B0NAC9WRJMVB0QE6CV8', 'task', '06FB2EDCBYRBDSV9V1PJ1KE3CM', 'D2 diagram card — compile d2 source to SVG, reuse the SVG render widget', 'A conversation-pane drawing card (peer of the SVG card T-320) that renders a D2 diagram. SEPARATE card type from SVG, but the ONLY difference is a compile step in front: D2 source → compile to SVG → render through the SAME SVG widget (T-320). Blocked on T-320 for that reason.
|
||||
|
||||
CLI/parity (D-6): driven via the drawing-card dispatch (T-318) — ''clide draw --file pipeline.d2'' (type inferred from .d2), or template:"d2" with inline source in the drawing-card JSON. Honest userError on a d2 compile failure (bad source), mirroring image/svg validation.
|
||||
|
||||
UX: the rendered diagram LEADS; the d2 source folds into a collapsed ''view d2 source'' disclosure on the card (ClideCollapserCard pattern, T-305) so the code doesn''t dominate. Display-only per D-78.
|
||||
|
||||
Open: D2 compiler dependency — d2 is Go (there is a d2-diagram skill). Decide whether to shell out to a d2 binary (supporter-tool pattern, peer of pql) or vendor it; flag before building. Wireframe: docs/design/wireframes/conversation/d2-render-card.png.
|
||||
|
||||
PATH / tool-resolution dependency (2026-06-28): the d2 compile step shells out to the ''d2'' binary, so it relies on clide resolving d2 on PATH. clide already derives a login-shell PATH for every spawned tool — T-439 (consolidated the Linux PATH fix T-347), both DONE — so this is very likely already covered. ACCEPTANCE: verify clide resolves ''d2'' via that login-shell PATH on a Homebrew/linuxbrew install (d2 lives in /home/linuxbrew/.linuxbrew/bin). WATCH: a ''$SHELL -lc'' login probe can miss brew if ''brew shellenv'' is only in ~/.bashrc (login shells source .bash_profile/.profile, not .bashrc); if so, that''s a real follow-up on T-439''s probe surfaced from here. Honest userError if d2 is unresolved, hinting how to install/locate it. (The ''command -v d2'' miss seen during design was Claude Code''s own lean sandbox PATH, not clide.)', 'backlog', 'medium', NULL, NULL, NULL, '2026-06-28 14:01:13.733', '2026-06-28 16:18:22.531', NULL, 'db85be505664f8ca1354594bebe73063', 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', NULL, 'backlog', 'medium', NULL, NULL, 'D-104', '2026-06-28 17:50:02.366', '2026-06-28 17:50:02.366', NULL, '8643aef22705d5565006a90eead1db18', 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).', 'backlog', 'medium', NULL, NULL, 'D-104', '2026-06-28 17:50:02.366', '2026-06-28 17:50:13.728', NULL, '53f89d410f3d83567393d0baa2ae8c4f', 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