Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
365 commits
Select commit Hold shift + click to select a range
5260ed9
fix(app): correct worktree project header titles
matej21 Jun 29, 2026
69d018f
fix(daemon): reconnect after local daemon restart
matej21 Jun 29, 2026
3f194e8
feat(web): improve project overview
matej21 Jun 29, 2026
e1e034e
fix(cli): call local daemon over socket
matej21 Jun 29, 2026
2171975
fix(lint): clear CI clippy warnings
matej21 Jun 30, 2026
40022ec
fix(workspace): preserve hidden projects after daemon migration
matej21 Jun 30, 2026
fa3ab6a
fix(app): focus new daemon split terminals
matej21 Jun 30, 2026
bd4002b
fix(git): carry default_branch over the wire (hide redundant base label)
matej21 Jun 30, 2026
1729d72
feat(soft-close): unify grace-period close across daemon + headless l…
jonasnobile Jul 1, 2026
2e9e792
refactor(daemon): extract shared remote snapshot + service handlers
jonasnobile Jul 1, 2026
422d8fb
refactor(config): unify settings/theme handlers over a ConfigBackend …
jonasnobile Jul 1, 2026
8336648
fix(clippy): drop redundant closures around config handlers
jonasnobile Jul 1, 2026
033986f
fix(theme): use neutral footer colors for REMOTE/Pair
jonasnobile Jul 2, 2026
30754d2
feat(toast): redesign toasts to notification style
jonasnobile Jul 2, 2026
fa1613e
fix(daemon): trust local socket connections
matej21 Jul 1, 2026
efeae1c
fix(daemon): wait for local health before connecting
matej21 Jul 1, 2026
dd0bc60
fix(workspace): avoid restoring stale extra windows
matej21 Jul 1, 2026
2631b84
fix(remote): keep resize ownership with input owner
matej21 Jul 1, 2026
b3b8165
fix(daemon): skip tokens for local sockets
matej21 Jul 1, 2026
78ca642
fix(remote): keep resize authority process-global
matej21 Jul 1, 2026
08e81e7
fix(remote): release resize ownership on disconnect
matej21 Jul 2, 2026
aa0406e
feat(remote): add status popover
matej21 Jul 2, 2026
97b2d25
fix(daemon): refresh git status after branch switch
matej21 Jul 2, 2026
a2610fa
feat(terminal): open new terminals in the focused terminal's cwd
jonasnobile Jul 2, 2026
217bb90
fix(terminal): answer terminal queries only on the daemon, not the cl…
jonasnobile Jul 2, 2026
92bad84
fix(lint): clear workspace clippy warnings to green CI
jonasnobile Jul 2, 2026
ea1ccd4
fix(toast): render countdown as bottom line
matej21 Jul 2, 2026
fb297e3
fix(remote): make resize ownership follow real user input only
matej21 Jul 2, 2026
c749b6f
feat(remote): client-aware graceful daemon shutdown endpoint
matej21 Jul 2, 2026
c41234c
fix(app): graceful daemon shutdown at quit + self-heal local connection
matej21 Jul 2, 2026
5f2b2bb
fix(terminal): never GC non-dtach sockets from the runtime dir
matej21 Jul 2, 2026
4d19fc2
fix(remote): clean up socket and lock on headless hard-exit shutdown
matej21 Jul 2, 2026
ab461f8
fix(app): recovery escalation for alive-but-unreachable local daemon
matej21 Jul 2, 2026
d96fe2a
feat(remote): show system stats in status popover
matej21 Jul 2, 2026
e3af196
feat(tui): add remote client proof of concept
matej21 Jul 2, 2026
be292d6
fix(toast): ignore Codex MainThread terminal title
matej21 Jul 2, 2026
9b89919
fix(lint): satisfy new clippy warnings
matej21 Jul 7, 2026
13f1c31
refactor(daemon): deduplicate action test helpers
matej21 Jul 7, 2026
e2b9f64
refactor(remote): deduplicate daemon listen address policy
matej21 Jul 7, 2026
4ec4a19
refactor(remote): share terminal transport messages
matej21 Jul 7, 2026
500de16
refactor(actions): deduplicate terminal lookup handling
matej21 Jul 7, 2026
eb57a04
refactor(workspace): centralize data mutation notification
matej21 Jul 7, 2026
9601e52
refactor(mobile): deduplicate action dispatch wrappers
matej21 Jul 7, 2026
b565dc9
refactor(transport): share layout terminal id collection
matej21 Jul 7, 2026
ac846ed
refactor(git): deduplicate remote provider actions
matej21 Jul 7, 2026
77be2b8
refactor(actions): deduplicate project existence guards
matej21 Jul 7, 2026
40ffc30
refactor(core): centralize process liveness checks
matej21 Jul 7, 2026
059ddac
docs: add duplicate detection skill
matej21 Jul 7, 2026
7a875a9
fix(git): refresh visible projects immediately
matej21 Jul 7, 2026
b0ac67c
fix(claude): show scoped usage limits
matej21 Jul 7, 2026
5794bf3
fix(lint): collapse nested if in git watcher
matej21 Jul 7, 2026
6e1fd2a
fix(git): ignore stale PR and origin head state
matej21 Jul 7, 2026
b655d26
fix(git): refresh visible projects without opening a terminal
matej21 Jul 7, 2026
0f79740
docs: reframe okena --headless as standard single-binary daemon
matej21 Jul 7, 2026
02929a3
fix(daemon): make startup ownership atomic
matej21 Jul 10, 2026
a07e38e
fix(daemon): flush state before shutdown
matej21 Jul 10, 2026
c932046
fix(app): only kill owned daemon during recovery
matej21 Jul 10, 2026
9b0e7f8
fix(daemon): hand off UI-owned lifecycle
matej21 Jul 10, 2026
2acfab5
fix(remote): make terminal resync lossless
matej21 Jul 10, 2026
0a57525
fix(remote): deliver terminal input without loss
matej21 Jul 10, 2026
5c957c8
fix(remote): preserve UI action ordering
matej21 Jul 10, 2026
d4437e1
fix(layout): separate shell and zoom ownership
matej21 Jul 10, 2026
facd7b1
fix(mobile): keep presentation state client-owned
matej21 Jul 10, 2026
9db4e57
fix(web): keep active tabs client-owned
matej21 Jul 10, 2026
922c7b3
fix(settings): make daemon the configuration authority
matej21 Jul 10, 2026
a55a4c1
fix(security): require TLS off loopback
matej21 Jul 10, 2026
821a3cd
fix(auth): serialize token persistence across processes
matej21 Jul 10, 2026
209b791
fix(daemon): run every headless host on daemon core
matej21 Jul 10, 2026
d14626d
fix(app): persist client presentation across restarts
matej21 Jul 10, 2026
8259116
chore(audit): codify client-owned window state
matej21 Jul 10, 2026
b92a6df
fix(daemon): restart through graceful shutdown
matej21 Jul 10, 2026
652ab2b
docs(architecture): align daemon ownership comments
matej21 Jul 10, 2026
9356954
fix(remote): use pinned TLS client for remote actions
matej21 Jul 11, 2026
4d20dc6
fix(layout): reconcile presentation by terminal identity
matej21 Jul 13, 2026
8d815dd
fix(app): keep project orientation window-local
matej21 Jul 13, 2026
62e6019
fix(remote): preserve presentation across reconnects
matej21 Jul 13, 2026
8810f00
fix(remote): record activity without sharing client focus
matej21 Jul 13, 2026
b956e12
fix(layout): align project column resize with pointer
matej21 Jul 13, 2026
32c50d0
feat(codex): show available usage resets
matej21 Jul 13, 2026
60e1464
fix(app): keep window layout authoritative
matej21 Jul 13, 2026
7b0ed37
fix(git): align commit graph row content
matej21 Jul 13, 2026
124b623
fix(remote): avoid polling completed websocket task
matej21 Jul 13, 2026
9f0f8bb
fix(app): restore secondary windows on startup
matej21 Jul 13, 2026
9992921
fix(git): constrain commit graph row typography
matej21 Jul 13, 2026
69d9d48
fix(app): restore extra windows after event loop starts
matej21 Jul 13, 2026
fd33eb5
fix(remote): unify action transport across clients
matej21 Jul 14, 2026
ffbd633
fix(remote): route worktree and hook actions through daemon
matej21 Jul 14, 2026
8ad5e93
fix(remote): respect daemon filesystem locality
matej21 Jul 14, 2026
44e5601
fix(remote): surface daemon action failures
matej21 Jul 14, 2026
f973f65
fix(remote): make file views daemon-authoritative
matej21 Jul 14, 2026
9fb6cea
fix(remote): unify daemon transport configuration
matej21 Jul 14, 2026
9df34c1
fix(remote): make session views daemon-authoritative
matej21 Jul 14, 2026
b126a1c
fix(files): surface rename failures
matej21 Jul 14, 2026
8edeaef
chore(remote): clean up upload dispatch
matej21 Jul 14, 2026
ac53869
chore(remote): clean up session dispatch
matej21 Jul 14, 2026
ef8aa93
fix(app): stop quit-time window closes from wiping the multi-window l…
matej21 Jul 15, 2026
d37e6b9
test(scripts): add multi-window quit/restore E2E harness
matej21 Jul 15, 2026
a476ad3
feat(ui): make file tree sidebars resizable
matej21 Jul 15, 2026
9d14e9a
feat(ui): distinguish typescript test files
matej21 Jul 15, 2026
9d0d869
fix(ui): end sidebar resize on mouse release
matej21 Jul 15, 2026
6338282
docs: credit Codex in authorship note
matej21 Jul 15, 2026
3ec9ed1
fix(files): recover from deleted directories
matej21 Jul 15, 2026
d269387
fix(hooks): fire worktree_removed on the headless removal path
neumie Jul 14, 2026
e3343e5
fix(hooks): surface daemon hook history to thin clients
neumie Jul 14, 2026
31f73d4
fix(hooks): fire on_project_open for restored projects at daemon boot
neumie Jul 14, 2026
d234c8a
fix(daemon): self-terminate UI-owned daemon when its last client leaves
neumie Jul 14, 2026
758e951
fix(daemon): reconnect to a surviving daemon instead of "already runn…
neumie Jul 14, 2026
0b3bc98
fix(remote): subscribe hook-terminal PTYs so their output streams to …
neumie Jul 14, 2026
467306b
fix(worktree): seed an initial terminal when the parent project has n…
neumie Jul 14, 2026
5a5bed7
fix(app): auto-open the hook panel when a project mirrors in with hooks
neumie Jul 15, 2026
e9dd83d
perf(daemon): run worktree git off the command-loop thread
neumie Jul 15, 2026
a60eb9a
perf(daemon): run worktree removal git off the command-loop thread
neumie Jul 15, 2026
d1e1d8a
perf(daemon): run the deferred worktree-close removal off the reactor
neumie Jul 15, 2026
30eec6e
perf(worktree): create from local ref, freshen to remote tip in backg…
neumie Jul 15, 2026
b585cad
perf(daemon): run the merge-close pipeline off the reactor
neumie Jul 15, 2026
a983152
feat(worktree): show "Closing…" state during before_remove hook
neumie Jul 15, 2026
59b91e2
fix(sidebar): repaint on workspace notify so "Closing…" (and lifecycl…
neumie Jul 15, 2026
3e974b3
fix(daemon): decouple autosave debounce from state_version so removal…
neumie Jul 15, 2026
c35c91c
fix(daemon): optimistic worktree removal so the row closes instantly
neumie Jul 15, 2026
bd7df60
fix(daemon): optimistic removal for the other two worktree-close paths
neumie Jul 15, 2026
c221e47
feat(daemon): optimistic worktree create — instant "Setting up worktr…
neumie Jul 15, 2026
d199ebb
fix: focus terminals from external actions
neumie Jul 15, 2026
52d1bee
fix(daemon): actually spawn worktree terminals in optimistic create (…
neumie Jul 16, 2026
d53e92f
fix(daemon): clean up the partial checkout when worktree create fails
neumie Jul 16, 2026
923edd7
fix: harden optimistic worktree lifecycle, hook semantics, and state …
neumie Jul 16, 2026
3cdc810
fix(daemon): heal the closing state when a hook-gated close is rejected
neumie Jul 16, 2026
c052fda
fix: guard generic DeleteProject against mid-create rows + guard regr…
neumie Jul 16, 2026
842ddae
fix(hooks): preserve daemon-owned lifecycle state
matej21 Jul 17, 2026
26e9619
fix(worktree): finalize checkout before lifecycle hooks
matej21 Jul 17, 2026
8fbef76
fix(daemon): reap only verified ui-owned processes
matej21 Jul 17, 2026
872e1de
fix(app): honor terminal focus window targets
matej21 Jul 17, 2026
13577dc
fix(daemon): keep worktree close authoritative
matej21 Jul 17, 2026
154feff
fix(hooks): refresh reused daemon history ids
matej21 Jul 17, 2026
e08bc81
test(daemon): cover worktree close integration paths
matej21 Jul 17, 2026
da603f0
Merge pull request #162 from contember/fix/headless-hooks
matej21 Jul 17, 2026
8a18be6
feat(updater): add local rebuild and restart mode
matej21 Jul 17, 2026
e0533fa
perf(git): refresh status on HEAD changes
matej21 Jul 17, 2026
80014fa
fix(updater): separate local rebuild and restart
matej21 Jul 17, 2026
c4e09a2
fix(git): prevent stale branch status after checkout
matej21 Jul 17, 2026
f85de52
fix(files): stabilize markdown preview scrollbar
matej21 Jul 17, 2026
aeef2e8
feat(mobile): improve terminal input and LAN TLS
matej21 Jul 17, 2026
78f5f48
fix(layout): preserve pane weights when closing splits
matej21 Jul 21, 2026
d928be3
fix(worktree): show closing state instead of "Starting terminal…"
neumie Jul 21, 2026
e4358d6
fix(daemon): restore instance-lock recovery from a wedged daemon
neumie Jul 21, 2026
113469c
fix(core): stop counting unreaped processes as running
neumie Jul 21, 2026
e3034c8
fix(daemon): harden lock recovery handoff
matej21 Jul 21, 2026
18493ee
chore: format Rust workspace
matej21 Jul 22, 2026
130784c
fix(hooks): preserve daemon lifecycle ownership
matej21 Jul 22, 2026
8553db2
fix(hooks): close restore and teardown lifecycle gaps
matej21 Jul 22, 2026
e52d771
fix(headless): harden async lifecycle ownership
matej21 Jul 22, 2026
772144b
fix(terminal): fence PTY generations and teardown
matej21 Jul 22, 2026
ec24f6e
fix(headless): harden worktree and hook ownership
matej21 Jul 22, 2026
699df18
fix(services): fence stale lifecycle callbacks
matej21 Jul 22, 2026
dd24759
fix(headless): preserve session and autosave ownership
matej21 Jul 22, 2026
a30f419
fix(hooks): finalize pending removal PTYs
matej21 Jul 22, 2026
eb66972
fix(services): preserve runtime ownership across reloads
matej21 Jul 22, 2026
5519df8
fix(headless): guard restore and worktree ownership
matej21 Jul 22, 2026
4d0d37c
fix(app): order final window layout save
matej21 Jul 22, 2026
312ad67
fix(services): close restore lifecycle leaks
matej21 Jul 22, 2026
9be45a1
fix(headless): reject blocked restore conflicts early
matej21 Jul 22, 2026
9c1cea1
fix(worktree): enforce physical root ownership
matej21 Jul 22, 2026
5b2d6d6
fix(headless): load workspace data off reactor
matej21 Jul 22, 2026
f71312b
fix(services): fence observer reconciliation
matej21 Jul 22, 2026
6e04f87
fix(worktree): verify physical checkout provenance
matej21 Jul 22, 2026
e9db5d8
fix(windows): preserve terminal lifecycle routes
matej21 Jul 22, 2026
84fe229
fix(worktree): guard destructive checkout removal
matej21 Jul 22, 2026
1abdcd5
fix(worktree): preserve registration across directory rename
matej21 Jul 22, 2026
a6889c7
fix(workspace): resolve stale cleanup shell routes
matej21 Jul 22, 2026
730a6e9
fix(windows): isolate hook launch environment
matej21 Jul 22, 2026
a7f7f92
fix(workspace): use configured shell for session loads
matej21 Jul 22, 2026
d25925d
fix(headless): route session cleanup through configured shell
matej21 Jul 22, 2026
9c27f49
fix(services): move reconciliation off reactor
matej21 Jul 22, 2026
bb5bb9b
fix(services): rearm recovery writeback ownership
matej21 Jul 22, 2026
77f7472
refactor(headless): prepare live backend migration
matej21 Jul 22, 2026
662678f
fix(headless): fence backend migration observers
matej21 Jul 22, 2026
acd04d7
refactor(headless): snapshot backend migration ownership
matej21 Jul 22, 2026
021202f
fix(headless): migrate live terminal backend settings
matej21 Jul 22, 2026
48eaf88
fix(services): preserve stopped intent during backend migration
matej21 Jul 22, 2026
a0640cd
fix(terminal): fence backend route reconfiguration
matej21 Jul 22, 2026
3fb6000
fix(headless): prepare service reloads off reactor
matej21 Jul 22, 2026
22809f3
fix(headless): complete backend migration before shutdown
matej21 Jul 22, 2026
79e601d
fix(headless): materialize session replacements off reactor
matej21 Jul 22, 2026
65640bf
fix(services): preserve manual stop over crash restart
matej21 Jul 22, 2026
f169ca5
fix(hooks): cancel intentional terminal teardown
matej21 Jul 22, 2026
ddf291a
fix(windows): preserve discovered worktree visibility
matej21 Jul 22, 2026
11256fa
fix(workspace): translate projects after directory rename
matej21 Jul 22, 2026
df87158
fix(headless): move direct worktree removal off reactor
matej21 Jul 22, 2026
3c9de4c
fix(services): preserve pending launches across reloads
matej21 Jul 22, 2026
238ce42
fix(services): suspend reconciliation during project lifecycle
matej21 Jul 22, 2026
a97ae78
fix(services): preserve reload writeback ownership
matej21 Jul 22, 2026
0ba46cd
fix(headless): publish committed backend settings
matej21 Jul 22, 2026
0bd5b5a
fix(services): serialize Docker mutations
matej21 Jul 22, 2026
937e02e
fix(services): preserve intent after removal failure
matej21 Jul 22, 2026
865c343
fix(services): keep Docker status polling convergent
matej21 Jul 22, 2026
5367dab
fix(worktree): preserve all changes before removal
matej21 Jul 22, 2026
7192bf7
fix(services): apply configured launch environment
matej21 Jul 22, 2026
cdf29a1
fix(services): retry Docker service discovery
matej21 Jul 22, 2026
a165212
fix(services): treat clean exits as stopped
matej21 Jul 22, 2026
eabaebf
fix(services): prefer Okena definitions on reload
matej21 Jul 22, 2026
b42e367
fix(worktree): track monorepo checkout roots
matej21 Jul 22, 2026
2784877
fix(workspace): block unsafe main repository rename
matej21 Jul 22, 2026
203eb47
fix(search): reject stale content results
matej21 Jul 22, 2026
4dca827
fix(services): own pending manual restarts
matej21 Jul 22, 2026
6533e96
fix(headless): detach content searches from reactor
matej21 Jul 22, 2026
6fd20a0
fix(headless): quiesce runtimes before direct worktree removal
matej21 Jul 22, 2026
cc2ab91
fix(headless): quiesce runtimes before directory rename
matej21 Jul 22, 2026
bf4cae2
fix(headless): make runtime quiesce recovery explicit
matej21 Jul 22, 2026
b7c453a
fix(transport): extend content search timeout
matej21 Jul 22, 2026
df6fe3e
fix(search): enforce parallel result limits
matej21 Jul 22, 2026
c55e2fd
fix(search): report invalid search patterns
matej21 Jul 22, 2026
0f04baf
fix(headless): release state before terminal teardown
matej21 Jul 22, 2026
e573efe
fix(search): cancel detached remote requests
matej21 Jul 22, 2026
b0fc7f3
fix(services): bound Docker mutation execution
matej21 Jul 22, 2026
9687bc5
fix(services): serialize Compose project mutations
matej21 Jul 22, 2026
88cb344
fix(services): add Compose removal safety preflights
matej21 Jul 22, 2026
c8adb7d
fix(workspace): fence multi-project runtime moves
matej21 Jul 22, 2026
a55be3c
refactor(headless): prepare terminal recovery batches
matej21 Jul 22, 2026
dc0d542
fix(headless): recover directory runtimes atomically
matej21 Jul 22, 2026
28bb5e5
fix(search): post cancellable actions to canonical route
matej21 Jul 22, 2026
1b199f7
fix(headless): adopt recovered service rename ownership
matej21 Jul 22, 2026
cc2a50d
fix(services): fence Docker polls across mutations
matej21 Jul 22, 2026
6bd31b0
fix(search): bound daemon result payloads
matej21 Jul 22, 2026
42175e3
fix(process): terminate collected process trees
matej21 Jul 22, 2026
31657f3
fix(services): offload blocking reactor work
matej21 Jul 22, 2026
70d9623
fix(transport): extend destructive action timeouts
matej21 Jul 22, 2026
88863f7
fix(services): avoid generation overflow panics
matej21 Jul 23, 2026
da69a7d
fix(ci): satisfy strict workspace clippy checks
matej21 Jul 23, 2026
ee5e140
fix(logging): give headless/ui-owned its own log file
neumie Jul 23, 2026
cbeffa2
fix(terminal): avoid blocking teardown on stuck reader
neumie Jul 23, 2026
f0bb33b
fix(daemon): recover vanished worktree close hooks
neumie Jul 23, 2026
302d0c1
fix(worktree): reconcile close teardown recovery
neumie Jul 23, 2026
92623b9
fix(teardown): bound reaping and verify session exits
neumie Jul 23, 2026
9918357
fix(teardown): retain indeterminate child reaping
neumie Jul 23, 2026
7854350
fix(terminal): reap orphaned persistent sessions
neumie Jul 23, 2026
5c41192
perf(terminal): replace pane polling with activity events
neumie Jul 23, 2026
79ced68
fix(terminal): treat Linux zombies as terminated
neumie Jul 23, 2026
aaf1054
test(core): wait for profile socket shutdown
neumie Jul 23, 2026
0c89ca4
fix(ci): move log rotation tests after runtime items
neumie Jul 24, 2026
a45b7be
Merge pull request #167 from contember/fix/worktree-close-recovery
matej21 Jul 24, 2026
a3bfc5f
fix(terminal): verify liveness after a failed session kill
matej21 Jul 24, 2026
5974f24
fix(terminal): keep reaper handoff and teardown count in lockstep
matej21 Jul 24, 2026
27b498d
fix(terminal): scope teardown verification to the terminals being del…
matej21 Jul 24, 2026
2cf2c5c
perf(gui): coalesce terminal activity repaints
neumie Jul 27, 2026
b309fd2
perf(daemon): tier git polling by project relevance
neumie Jul 27, 2026
01e7f2a
fix(gui): keep non-key windows live
neumie Jul 28, 2026
f931311
fix(gui): present initial terminal output immediately
neumie Jul 29, 2026
b9de707
fix(gui): prioritize output following terminal input
neumie Jul 29, 2026
aa9f4e8
test(terminal): add input latency probe
matej21 Jul 29, 2026
94e895a
fix(git): follow rendered file tree navigation order
matej21 Jul 30, 2026
f41f45e
refactor(files): unify file tree rendering and navigation
matej21 Jul 31, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
114 changes: 114 additions & 0 deletions .claude/skills/duplicate-detection/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
---
name: duplicate-detection
description: Detect duplicated code and choose safe deduplication targets in Rust or general codebases. Use when the user asks to find code clones, dedupe a PR or branch, run duplicate-code tools, reduce repeated logic, identify dangerous duplication that may drift, or continue incremental refactors driven by duplicate-detection reports.
---

# Duplicate Detection

Use this skill to turn clone reports into small, safe refactors. Prefer removing duplication that can cause behavior drift over reducing a metric for its own sake.

## Workflow

1. Establish scope.
- Inspect the current branch, worktree state, language mix, and test commands.
- For PR work, determine the correct merge base before judging whether duplication is new.
- Check whether CI already runs linting such as `cargo clippy`; clippy is useful but is not a duplicate-code detector.

2. Generate duplicate reports.
- Use at least one structural or token-based detector.
- Exclude generated output, vendored dependencies, build artifacts, lockfiles, snapshots, and large fixtures unless the user explicitly wants them included.
- Save reports under `/tmp` or another disposable path; do not commit report output unless asked.

3. Triage the reports before editing.
- Prioritize logic that can drift: policy checks, wire protocol construction, persistence, filesystem/process/network behavior, lifecycle transitions, cache invalidation, notifications, and cross-entrypoint behavior.
- Treat tests as lower priority unless duplicated setup hides product behavior, makes assertions diverge, or blocks future maintenance.
- Ignore harmless symmetry when abstraction would obscure intent: simple DTO conversions, repeated enum arms, tiny wrappers, trivial UI layout, or generated-looking glue.

4. Refactor in small slices.
- Extract the smallest shared helper that matches an existing module boundary.
- Preserve public APIs, FFI boundaries, serialized formats, and observable error text unless the user asked to change them.
- Avoid macro layers, broad architecture moves, or generic frameworks unless the payoff is obvious; ask first when unsure.
- Commit each coherent refactor separately when the user asks for incremental commits.

5. Verify and report.
- Run targeted tests or checks for touched code; run broader checks when shared behavior moved.
- Re-run the duplicate detector after meaningful refactors and report before/after counts.
- Explain which duplicate classes remain and why they are lower priority.

## Rust Commands

Use `cargo-dupes` for Rust-focused clone reports when available:

```bash
cargo dupes --path . \
--exclude target \
--exclude node_modules \
--exclude-tests \
--min-lines 8 \
--min-nodes 20 \
--threshold 0.85 \
--format json report > /tmp/duplicate-detection-cargo-dupes.json
```

If it is missing and installing tools is acceptable in the environment:

```bash
cargo install cargo-dupes --locked
```

`cargo-dupes` may emit multiple JSON values. Read the first report object with `jq -s`:

```bash
jq -s '.[0] | {
exact_groups: .exact_duplicate_groups,
exact_lines: .exact_duplicate_lines,
near_groups: .near_duplicate_groups,
near_lines: .near_duplicate_lines
}' /tmp/duplicate-detection-cargo-dupes.json
```

Run normal Rust quality gates for changed behavior:

```bash
cargo test
cargo clippy --all-targets --all-features -- -D warnings
```

Adjust those commands to match the repo's documented CI.

## General Commands

Use `jscpd` for broad token/text clone detection across mixed-language repos:

```bash
npx --yes jscpd@5 . \
--min-lines 8 \
--min-tokens 80 \
--ignore "**/target/**,**/.git/**,**/node_modules/**,**/dist/**,**/build/**,**/coverage/**,**/Cargo.lock,**/package-lock.json,**/pnpm-lock.yaml,**/yarn.lock" \
--reporters json,silent \
--output /tmp/duplicate-detection-jscpd
```

When the repo is mostly Rust, add `--format rust` to reduce noise. For mixed repos, let `jscpd` auto-detect formats or pass a comma-separated format list.

Summarize the JSON report:

```bash
jq '.statistics.total | {
clones: .clones,
duplicated_lines: .duplicatedLines,
duplicated_percentage: .percentage
}' /tmp/duplicate-detection-jscpd/jscpd-report.json
```

## Review Heuristics

Ask these questions for each candidate:

- Would a future change likely need to update both places?
- Is one copy already subtly different in a way that looks accidental?
- Does the duplication cross a boundary where behavior should stay aligned, such as local versus remote, daemon versus client, or API versus UI?
- Can the shared helper be named after a real domain concept rather than after the duplicated syntax?
- Will the refactor reduce branching and tests, or just hide two readable blocks behind indirection?

Proceed when the answers point to drift risk and the extraction is local. Leave the duplication alone when a shared abstraction would be more fragile than the repeated code.
16 changes: 15 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,14 @@ jobs:
- name: Clippy
run: cargo clippy --workspace --all-targets -- -D warnings

- name: Daemon/client split gates
run: |
scripts/audit-daemon-client-gaps.sh
if cargo tree -p okena-daemon --edges no-dev | grep -E 'gpui|gpui-component'; then
echo "okena-daemon must stay GPUI-free"
exit 1
fi

- name: Run tests
run: cargo test

Expand Down Expand Up @@ -163,14 +171,18 @@ jobs:
run: cd web && bun install --frozen-lockfile && bun run build

- name: Build
run: cargo build --release --target ${{ matrix.target }}
run: cargo build --release --target ${{ matrix.target }} -p okena -p okena-daemon

- name: Prepare artifact (Linux)
if: runner.os == 'Linux'
run: |
mkdir -p dist/icons
cp target/${{ matrix.target }}/release/okena dist/
chmod +x dist/okena
# Ship the GPUI-free daemon sibling so the app runs the real daemon
# binary instead of falling back to `okena --headless`.
cp target/${{ matrix.target }}/release/okena-daemon dist/
chmod +x dist/okena-daemon
# Bundle icons for Linux installation
cp assets/app-icon-16.png assets/app-icon-32.png assets/app-icon-48.png \
assets/app-icon-64.png assets/app-icon-128.png assets/app-icon-256.png \
Expand All @@ -188,6 +200,8 @@ jobs:
run: |
mkdir dist
copy target\${{ matrix.target }}\release\okena.exe dist\
rem Ship the GPUI-free daemon sibling (see Linux step).
copy target\${{ matrix.target }}\release\okena-daemon.exe dist\

- name: Upload artifact
uses: actions/upload-artifact@v4
Expand Down
Loading
Loading