|
|
|
@@ -2449,3 +2449,34 @@ Fix: make taps that land outside the actual image bounds dismiss — e.g. add an
|
|
|
|
|
|
|
|
|
|
Acceptance: single click on the dimmed area surrounding the image closes the lightbox; clicking/dragging/zooming the image does not; Esc and the x still close.', 'done', 'low', NULL, NULL, NULL, '2026-06-10 09:37:31', '2026-06-10 13:15:15', NULL, '2c16b97db9098d73e122bfbaba2b74eb', 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 ('06FB37JZSFZKWPK9PDFYJY2YC0', 'task', '06FB0TNQM5TWC00GW0P3X02HZW', 'Deny & simplify note: don''t narrate the reformulation, just retry simpler', 'The T-311 ''Deny & simplify'' note prompts Claude to retry in a simpler form, but Claude tends to narrate the change (''right, splitting that command'', etc.) instead of silently retrying. Add a clause to the preformatted note (lib/builtin/claude/src/prompt_card.dart _kDenySimplifyNote) telling Claude NOT to narrate or re-explain the changes it makes — just proceed as it was, only simpler. Target: a quiet simpler retry, no commentary. Surfaced live while the button was tested against git commands.', 'done', 'low', NULL, NULL, NULL, '2026-06-10 13:00:06', '2026-06-10 13:18:57', NULL, 'd63c15b0903f860a85dd1b437e96c388', 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 ('06FB0TNQM7F2TBJJV1F2KP7XR8', 'task', '06FB0TNQM5TWC00GW0P3X02HZW', 'Clickable file references in Claude conversation open in editor', 'Make file-path references rendered in the Claude conversation pane clickable: clicking a path opens that file in the editor.
|
|
|
|
|
|
|
|
|
|
**Behavior**
|
|
|
|
|
- Detect references to files in the workspace as the conversation markdown is rendered — bare paths (`lib/app.dart`), `file:line` forms (`lib/app.dart:42`, clickable per CLAUDE.md), and likely inline-code spans / markdown links pointing at repo paths.
|
|
|
|
|
- Resolve against the workspace root (CLIDE_WORKSPACE / git repo root). Only linkify paths that exist in the repo to avoid false positives on prose.
|
|
|
|
|
- On click, open in the editor — same path as `clide editor open <path>` — and jump to the line when a `:line` suffix is present.
|
|
|
|
|
|
|
|
|
|
**Notes / constraints**
|
|
|
|
|
- Markdown rendering is clide-owned custom CustomPaint/widgets (not a package), so detection + hit-testing lands in the conversation/markdown render path.
|
|
|
|
|
- Honors User/Claude parity (D-6): the click maps to the existing `clide editor open` verb.
|
|
|
|
|
- Open questions to settle during design: how aggressive path detection should be (existence check vs. heuristic), handling of non-existent / external paths, and visual affordance (underline/hover) for a linkified ref.', 'ready', 'medium', NULL, NULL, NULL, '2026-06-09 20:02:41', '2026-06-10 13:24:15', NULL, '75c7f89b46b83a29e547f7efe3314826', 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 ('06FB3DHCTP001YCHFP39XER0ZM', 'epic', NULL, 'SSH-remote workspaces', 'Run clide locally but open and work in a git repo that lives on a remote machine over SSH. All shell actions (git, pql, the claude process, terminal panes, file I/O) execute remotely; only inherently-local things (clipboard / image paste) stay local and bridge their bytes across. Resolves Q-23. The user''s original ''pql binary local, db+repo remote'' hypothesis is not viable (pql reads its .pql/ index off the filesystem, git needs .git/ local, inotify does not cross sshfs) — so the cut is: execution is remote, UI + clipboard stay local, bridged by SSH. Load-bearing tension: execution must be remote, but the user does not want to install clide components on the remote or manage versions there — the footprint model is deferred to a Phase-0 spike. Locked: auth reuses system ssh + ~/.ssh/config for v1 (Windows is a known gap); v1 scope is full backend remote (files, git, pql, terminal, native Claude pane). Plan: ~/.claude/plans/can-we-plan-an-sleepy-gem.md', 'backlog', 'high', NULL, NULL, NULL, '2026-06-10 13:26:06', '2026-06-10 13:26:06', NULL, '28d37835a16accafb3eab563ad4003e3', 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 ('06FB3DJZDDZ00BSA04B660RS7M', 'story', '06FB3DHCTP001YCHFP39XER0ZM', 'Phase 0 — governance spike: pick remote-execution footprint model (resolve Q-23)', 'GATE for the whole epic — nothing else starts until this lands. Turn Q-23 into D-records and pick the footprint model with evidence. Decide between: (1) No-install ssh-exec (zero remote footprint) — stock ssh: ssh -tt PTYs for terminal/Claude, multiplexed ControlMaster command channels for git/pql/file ops; nothing clide-specific on the remote; watching degrades to polling; no stateful remote process. (2) Auto-pushed self-managed agent (VS Code Remote model) — clide auto-deploys + version-checks one self-contained binary on connect (a headless UI-less deployment of the existing subsystem library: lib/src/daemon, git, pql, files, pty, ipc/server.dart — hosting the same DaemonDispatcher + IpcServer); gains native inotify watching + stateful backend. MUST answer the user''s agent-model sub-questions: is it a proxy/backend? cleanup/GC on disconnect/version-bump/repo-removal? placement (per-repo .clide/agent vs per-host ~/.clide/agent vs shared — per-host shared likely)? multi-client sharing (two local clides / two users — share one agent or one each? IpcServer is already multi-connection, D-72)? version skew (version encoded in binary name, e.g. clide-agent-<ver>, so versions coexist)? Also measure ControlMaster per-command latency for the ssh-exec model. Also decide the remote-tool contract: what must exist remotely (git/pql/claude/shell), whether pql is hard-required or degrades, and how a preflight surfaces what is missing. Include the D-56 reconciliation: ''single process'' is scoped per-host-per-workspace; a headless remote deployment of the subsystem library does not violate the no-second-local-process rule. Artifacts: Q-23 -> Resolved; new D-records for footprint model + D-56 framing, ssh:// URI scheme, remote auth (system ssh, v1, Windows deferred), remote-tool contract, session identity keyed on (host, repo) amending D-41/D-77.', 'backlog', 'high', NULL, NULL, NULL, '2026-06-10 13:26:19', '2026-06-10 13:26:19', NULL, '2ab1c13b28a4bd6a78b9e7aad88ab438', 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 ('06FB3DKQQJ583944DG8561VQ3G', 'story', '06FB3DHCTP001YCHFP39XER0ZM', 'Phase 1 — backend transport seam (DaemonTransport, prove locally)', 'Model-independent backbone. Make the local app talk to its backend through a DaemonTransport abstraction with ZERO behavior change, so a remote transport can slot in later. New lib/src/ipc/transport.dart: DaemonTransport interface + LocalTransport (wraps today''s unix-socket connect). DaemonClient takes a transport instead of a hard-coded socket path; its reconnect loop generalizes to ''re-establish via transport''. lib/main.dart: swapIpcServer (~:119) becomes swapBackend — local binds the in-process IpcServer as today; seam ready for a remote branch. Wire protocol unchanged — JSON-lines IpcRequest/IpcResponse/IpcEvent (envelope.dart) already serialize over IPC; event stream, tail --events, events --since cursor-pull ride the same stream untouched. Verify: make test-core (IPC) + testmode skill — local path behaves identically through the seam, no regression. Depends on Phase 0 (T-330).', 'backlog', 'high', NULL, NULL, NULL, '2026-06-10 13:26:25', '2026-06-10 13:26:25', NULL, '8aa11d9791af3d5653cf33260ed7b1ae', 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 ('06FB3DMF20SYFDT6WX2RFBQXKW', 'story', '06FB3DHCTP001YCHFP39XER0ZM', 'Phase 2 — remote workspace identity + ssh:// open scheme', 'Model-independent backbone. clide can represent and open an ssh:// workspace end-to-end (actual remote calls land on the execution layer from the fork phase). URI: ssh://[user@]host[:port]/abs/remote/path, resolving host aliases via ~/.ssh/config. lib/kernel/src/project.dart: RecentProject gains host/port/user (absent = local; back-compatible toJson/fromJson), bool get isRemote, remote display form in relativePath/timeAgo (e.g. buildbox:~/repo); introduce a WorkspaceRef { String? host; String path; } value type and migrate _current/current off bare Directory (Directory(remotePath) is meaningless locally) — local callers read .path; resolveProject (~:204) branches: local runs git rev-parse as today, remote resolves the toplevel via the execution layer. lib/main.dart: swapBackend remote branch wires DaemonClient to the remote transport (no local server bound for remote workspaces). Connection lifecycle: connect -> resolve auth -> establish transport -> preflight remote tools -> ProjectOpened. On SSH drop, DaemonClient reconnect re-attaches; events --since cursor-pull (server.dart ~:339) is the re-sync primitive (gap:true -> UI full refresh). Verify: unit tests on RecentProject/WorkspaceRef JSON round-trips (local + remote); open ssh://localhost/... loopback workspace and confirm resolveProject returns the remote toplevel. Depends on Phase 1 (transport seam).', 'backlog', 'high', NULL, NULL, NULL, '2026-06-10 13:26:31', '2026-06-10 13:26:31', NULL, 'a75b65a2775abc2852b81c2f1a078847', 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 ('06FB3DN94MBCTYJW17ZCYVSXE0', 'story', '06FB3DHCTP001YCHFP39XER0ZM', 'Phase 3 — Claude remoting (stdio control channel)', 'Model-independent backbone. Native Claude pane works against a remote workspace. claude is spawned where the repo is (remote), workingDirectory = remote repo; its --resume transcripts live on the remote under ~/.claude/... — correct and automatic. New long-lived IPC verb claude.control.attach (modeled on the tail --events long-lived connection, server.dart ~:302) relays the stdio control protocol both directions, so canUseTool / AskUserQuestion prompts render natively locally and answers return over the tunnel (D-77/D-78). lib/builtin/claude/src/session_naming.dart: re-key the session seed on (host, repo) so the same path on two hosts (or local) is two sessions (D-41/D-77 amendment from Phase 0). lib/builtin/claude/src/agent_bootstrap.dart: CLIDE_SOCK/CLIDE_WORKSPACE/PATH describe the remote socket + workspace (computed remote-side). Verify: drive a Claude turn against the loopback-remote workspace; confirm a permission prompt renders natively and the answer flows back; confirm --resume re-attaches the remote transcript. Depends on Phase 2 + the execution-layer fork.', 'backlog', 'high', NULL, NULL, NULL, '2026-06-10 13:26:38', '2026-06-10 13:26:38', NULL, 'b961853eda518a7508558d5c8d85fc87', 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 ('06FB3DNQZKV20F7YG5PJH8V8SM', 'story', '06FB3DHCTP001YCHFP39XER0ZM', 'Phase 4 — image-paste local->remote bridge', 'Model-independent backbone. Paste an image from the local clipboard, reference it from remote Claude. Clipboard read stays local (clipboard_paste.dart, clide/clipboard MethodChannel) — clipboard is inherently local. New IPC verb files.put (write bytes remote-side) in lib/src/daemon/files_commands.dart — the only local->remote byte push. After writing the local temp image, push bytes to a remote scratch dir and rewrite ComposerAttachment.path to the remote path before building the @<path> token, so remote claude resolves it. New minor D-record: scratch-dir location (<repo>/.clide/pasted vs remote cache), tying into ignore discipline (D-4; .clide/ is already ignore-handled). Verify: paste a screenshot locally, confirm bytes land remotely and remote Claude reads the @path. Depends on Phase 2 + execution-layer fork.', 'backlog', 'medium', NULL, NULL, NULL, '2026-06-10 13:26:42', '2026-06-10 13:26:42', NULL, '85987f1719a16078b095a9d9ba8c8e14', 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 ('06FB3DP48FS33CQGRDF7EB9GT0', 'story', '06FB3DHCTP001YCHFP39XER0ZM', 'Phase 5 — UI: remote connect, switcher, status indicator', 'Model-independent backbone. First-class remote affordances. lib/builtin/welcome/src/welcome_view.dart: ''Connect to remote...'' beside ''Open folder...''; remote recents render with a host badge. lib/app.dart: project switcher accepts remote refs (open() branches on isRemote); the existing daemon-indicator slot (~:1172) becomes the connection indicator (connected / reconnecting / offline). registerStatusCommand (main.dart ~:245): surface host in clide status. Verify: make test (analyze + format + unit + widget + golden) for the UI; manual: connect indicator reflects drop/reconnect. Depends on Phase 2 (open scheme). UI dresses a working backend, so land last.', 'backlog', 'medium', NULL, NULL, NULL, '2026-06-10 13:26:45', '2026-06-10 13:26:45', NULL, '65c981fa45c4cb52fbe7df59d8046c78', 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 ('06FB3DQEMTDHF8SV27AKAB8JHW', 'story', '06FB3DHCTP001YCHFP39XER0ZM', 'Fork — execution layer (expand after Phase-0 spike decides footprint)', 'PLACEHOLDER — exact tickets crystallize after the Phase-0 spike (T-330) picks the footprint model. Both designs below so the choice is a swap, not a redesign. IF auto-pushed agent: execution layer is mostly transport + provisioning — subsystems (GitClient, PqlClient, FilesService, SearchService, NativePty) run UNCHANGED inside the remote agent; buildDispatcher (main.dart ~:176) split into UI-coupled vs headless-safe registrations; new bin/clide_agent.dart hosts the headless set + an IpcServer; RemoteTransport = SSH-tunneled agent socket (stdio bridge); watching is native inotify in the agent (watcher.dart unchanged); plus a provisioning module lib/src/remote/ (push, version-name, launch, GC). IF no-install ssh-exec: introduce a RemoteExecutionContext that each subsystem uses instead of bare Process.run/File/Directory — ssh -tt for PTYs, multiplexed ControlMaster command channels for git/pql/file ops, and a polling watcher (debounced git-status/mtime, or inotifywait if present) emitting the same FileChange events so the UI is unaware; heavier subsystem surface, zero remote footprint. Either way: pql runs where its .pql/ index lives (remote), git runs where .git/ lives (remote), clide still only wraps pql (D-3 preserved). Blocks Phases 3 and 4. Depends on Phase 0 (T-330) and Phase 1 (T-331).', 'backlog', 'high', NULL, NULL, NULL, '2026-06-10 13:26:56', '2026-06-10 13:26:56', NULL, 'f5c3f4f28b4b4b6c4301ad0400182aee', 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 ('06FB3DWCJSGZH9WYDNFWZBAYYR', 'bug', '06FB0TNQM5TWC00GW0P3X02HZW', 'ExitPlanMode does not exit plan mode in the conversation panel', 'Observed live: Claude used the ExitPlanMode tool (approved the plan / left plan mode), but the clide conversation panel did not reflect the exit — it still appears to be in plan mode afterward.
|
|
|
|
|
|
|
|
|
|
Expected: once ExitPlanMode is accepted, the pane leaves plan mode — the permission-mode indicator (claude_status / permission_mode_control) flips off ''plan'', and the composer / status reflect the new mode.
|
|
|
|
|
|
|
|
|
|
Where to look:
|
|
|
|
|
- How the stream-json session handles the ExitPlanMode tool/control event (stream_json_session.dart) and whether it updates the tracked permission mode (claude_status.dart permissionMode).
|
|
|
|
|
- The permission-mode control + status badge wiring (permission_mode_control.dart, claude_pane.dart) — does an ExitPlanMode resolution feed back into the mode the way Ctrl/Cmd+M and the picker do?
|
|
|
|
|
- Whether ExitPlanMode arrives as a permission prompt (ToolPromptCard) and, if approved, actually transitions the session out of plan mode rather than just resolving the tool.
|
|
|
|
|
|
|
|
|
|
Repro: enter plan mode, let Claude present a plan via ExitPlanMode, accept it — the pane stays showing plan mode.
|
|
|
|
|
|
|
|
|
|
Acceptance: accepting ExitPlanMode leaves plan mode in the conversation panel (mode indicator + behavior update), matching what the underlying session does.', 'backlog', 'medium', NULL, NULL, NULL, '2026-06-10 13:27:36', '2026-06-10 13:27:36', NULL, 'e4644bb33acffeb4ac1cdd2ab7dd0942', 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);
|
|
|
|
|