diff --git a/.codekin/reports/complexity/2026-04-08_complexity-report.md b/.codekin/reports/complexity/2026-04-08_complexity-report.md new file mode 100644 index 00000000..fde68614 --- /dev/null +++ b/.codekin/reports/complexity/2026-04-08_complexity-report.md @@ -0,0 +1,163 @@ +# Complexity Report: codekin + +**Date**: 2026-04-08T04:34:03.812Z +**Repository**: /srv/repos/codekin +**Branch**: chore/workflow-reports-2026-04-07 +**Workflow Run**: afd7ef0c-b166-4bea-b067-81dcb3f0db66 +**Session**: e504403b-a2ad-4e3c-b9e5-d42aaac40b36 + +--- + +Now I have enough information to produce the report. + +```markdown +## Summary + +**Overall Complexity Rating: Medium–High** + +The codebase is a TypeScript/React monorepo (~46,000 lines of first-party code excluding tests) with a well-structured server and a mostly clean frontend. The primary complexity hot-spot is `session-manager.ts` — a 2,174-line, 55-method class that acts as a God Object, combining session CRUD, process lifecycle, WebSocket broadcasting, approval routing, retry logic, plan-mode state, worktree management, and diff delegation. Secondary concerns are parallel tool summarization logic duplicated across modules and prompt/approval flows with 4–5 levels of branching nesting. + +| Metric | Value | +|---|---| +| Largest file (non-test) | `server/session-manager.ts` — 2,174 lines | +| Total first-party source files | ~737 | +| Most complex function | `requestToolApproval` (~140 lines, 5+ branch levels) | +| Deepest nesting observed | 5–6 levels (`leave()`, `requestToolApproval`, `sendPromptResponse`) | + +--- + +## Largest Files + +| File | Lines | Primary Responsibility | Refactor Priority | +|---|---|---|---| +| `server/session-manager.ts` | 2,174 | Session lifecycle, process management, approval routing, broadcast, worktree, context building | **High** | +| `server/claude-process.ts` | 762 | Spawning/managing a single Claude CLI subprocess | Medium | +| `server/workflow-engine.ts` | 746 | SQLite-backed workflow runs, cron scheduling | Low | +| `server/orchestrator-learning.ts` | 704 | Memory extraction, aging, skill modeling | Low | +| `server/ws-server.ts` | 621 | Express/WebSocket server entry point, startup | Medium | +| `server/orchestrator-routes.ts` | 614 | Orchestrator REST API routes | Low | +| `server/stepflow-handler.ts` | 521 | Stepflow webhook integration | Low | +| `server/workflow-loader.ts` | 505 | Loads `.md` workflow definitions | Low | +| `server/session-routes.ts` | 475 | Session REST endpoints | Low | +| `server/approval-manager.ts` | 456 | Tool auto-approval registry, pattern matching | Low | +| `src/components/InputBar.tsx` | 684 | Chat input, slash commands, skill menu, toolbar | **High** | +| `src/App.tsx` | 674 | Root app component, global state/hooks wiring | **High** | +| `src/components/ChatView.tsx` | 602 | Chat message rendering | Medium | +| `src/components/AddWorkflowModal.tsx` | 580 | Workflow creation modal | Low | +| `src/lib/ccApi.ts` | 534 | REST client functions for server API | Low | + +--- + +## Most Complex Functions + +| File:Function | Estimated Complexity | Issue Description | Refactor Suggestion | +|---|---|---|---| +| `session-manager.ts:requestToolApproval` | Very High | ~140 lines with 5-level nesting; handles AskUserQuestion, ExitPlanMode, double-gating guard, pattern construction, and 300s timeout all in one method | Split into `handleQuestionApproval()`, `handlePermissionApproval()`, and `buildPromptMessage()` helpers | +| `session-manager.ts:sendPromptResponse` | High | ~70 lines; routes through 4 approval paths with nested null-checks and fallback logic; difficult to trace which branch handles which case | Extract `routeToolApproval()` and `routeControlRequest()` sub-methods | +| `session-manager.ts:handleClaudeExit` | High | ~90 lines; mixes process cleanup, session conflict detection, restart evaluation, message building, and context injection | Separate `afterExitCleanup()` from the restart decision dispatch | +| `session-manager.ts:leave` | High | 5-level nesting (method → if-no-clients → setTimeout callback → re-check → iterate pending maps) to auto-deny prompts after grace period | Extract `autoDeniesPendingPrompts(session)` called from the timeout | +| `session-manager.ts:startClaude` | High | ~65 lines building env vars, merging allowed tools, computing `resume` flag, and wiring events; assembles too many concerns | Extract `buildProcessEnv()` and `buildClaudeOptions()` helpers | +| `claude-process.ts:handleControlRequest` | Medium-High | Branches on AskUserQuestion, AUTO_APPROVE_TOOLS, and fallback; duplicates question-parsing logic also present in `session-manager.ts:requestToolApproval` | Consolidate question-structure mapping into a shared `parseAskUserQuestions()` utility | +| `session-manager.ts:reapIdleSessions` | Medium | Two separate iteration passes over `this.sessions` (idle-stop pass, stale-prune pass) — O(2n) with duplicated source exemptions | Merge into one pass with a helper that decides action per session | +| `workflow-engine.ts:executeRun` | Medium | ~100 lines; nested try-catch-try-catch with multiple DB update paths for each status (skipped/canceled/failed) | Extract `markRunFailed()`, `markRunSkipped()`, `markRunCanceled()` helpers | +| `session-manager.ts:buildSessionContext` | Medium | History-replay accumulator with state machine logic inline; duplicates pattern from `useChatSocket.ts:applyMessageMut` | Extract a shared `replayHistory(messages)` utility used by both | +| `session-manager.ts:resolveToolApproval` | Medium | Handles three distinct tool types (AskUserQuestion, ExitPlanMode, generic permission) with branching decode + registry update | Dispatch table pattern or strategy objects per tool type | + +--- + +## Coupling & Cohesion Issues + +**1. `SessionManager` is a God Object** + +`session-manager.ts` mixes at least seven distinct concerns: session CRUD, Claude process lifecycle, WebSocket broadcast, approval/prompt routing, worktree management, session context building, and API retry scheduling. It already delegates some logic to `ApprovalManager`, `SessionNaming`, `SessionPersistence`, and `DiffManager`, but the remaining 2,174 lines still contain too many responsibilities. Any change to approval flow, restart logic, or broadcast requires editing the same file. + +*Suggested fix:* Extract a `PromptRouter` class for all approval/prompt dispatch, and a `SessionLifecycle` class for process start/stop/restart. `SessionManager` becomes a thin coordinator. + +**2. Duplicated question-structure parsing between `ClaudeProcess` and `SessionManager`** + +`claude-process.ts:handleControlRequest` (lines ~495–510) parses the `AskUserQuestion.questions` array and maps option labels/values. The same mapping logic reappears in `session-manager.ts:requestToolApproval` (lines ~1593–1604). Two different callers maintaining the same transformation is a latent inconsistency risk. + +*Suggested fix:* Extract `parseStructuredQuestions(rawQuestions)` into a shared utility in `types.ts` or a small `question-utils.ts`. + +**3. Tool-input summarization duplicated across `ClaudeProcess` and `SessionManager`** + +`claude-process.ts:summarizeToolInput` and `session-manager.ts:summarizeToolPermission` both handle `Bash`, `Read`, `Write`, and other tools with overlapping switch-case logic. They diverge in format (`$ cmd` vs `Allow Bash? \`$ cmd\``) but share the same tool-name dispatch. + +*Suggested fix:* Centralize tool input extraction into a `getToolDisplayString(toolName, toolInput)` utility; each call site adds its own prefix. + +**4. `ws-server.ts` wires business logic inline** + +`ws-server.ts` registers the orchestrator prompt listener (lines 517–540) and the workflow engine event broadcaster (lines 551–566) as inline closures. This makes startup sequencing harder to test and means the file owns behavior beyond "server wiring." + +*Suggested fix:* Move these into dedicated `OrchestratorBridge.connect()` and `WorkflowBroadcaster.connect()` methods. + +**5. `src/App.tsx` as a mega-component** + +`App.tsx` imports 12+ hooks and 15+ components, maintains ~20 pieces of state, and provides callbacks that thread through multiple child components. While content views are extracted (`OrchestratorContent`, `SessionContent`, `DocsBrowserContent`), the App component still wires together authentication, routing, diff panel, worktree toggle, queue messages, command palette, and skill menu. + +*Suggested fix:* Extract a `useAppState()` composite hook to own the wiring of smaller domain hooks, leaving `App` as a layout-only component. + +--- + +## Refactoring Candidates + +**1. Extract `PromptRouter` from `SessionManager`** +- **Location:** `server/session-manager.ts` lines 1328–1724 +- **Problem:** `sendPromptResponse`, `requestToolApproval`, `handleExitPlanModeApproval`, `resolveToolApproval`, `handleAskUserQuestion`, `sendControlResponseForRequest`, and `decodeApprovalValue` form a cohesive approval routing subsystem but live inside `SessionManager` alongside unrelated concerns. +- **Approach:** Create `server/prompt-router.ts` with a `PromptRouter` class that takes `session` + `claudeProcess` as constructor args; move all seven methods there. `SessionManager` holds a `PromptRouter` instance and delegates. +- **Effort:** Medium + +**2. Extract `SessionLifecycle` process management** +- **Location:** `server/session-manager.ts` lines 729–875, 1173–1265, 1841–1878 +- **Problem:** `startClaude`, `wireClaudeEvents`, `handleClaudeExit`, `stopClaude`, `stopClaudeAndWait`, and `waitForReady` are cohesive but tangled with broadcast and session-state mutation. +- **Approach:** Create `server/session-lifecycle.ts` owning these methods; `SessionManager` delegates and provides a broadcast callback. +- **Effort:** Medium + +**3. Consolidate tool-input summarization** +- **Location:** `server/claude-process.ts:summarizeToolInput` (line 633) and `server/session-manager.ts:summarizeToolPermission` (line 1771) +- **Problem:** Duplicated switch-case dispatch with similar logic. +- **Approach:** Extract `server/tool-summary.ts` with `summarizeToolInput(name, input): string` and `permissionPrompt(name, input): string` built on top of it. +- **Effort:** Small + +**4. Consolidate `AskUserQuestion` question-structure parsing** +- **Location:** `server/claude-process.ts` ~line 495 and `server/session-manager.ts` ~line 1593 +- **Problem:** Same `rawQuestions.map(q => ({ question, header, multiSelect, options: opts.map(...) }))` mapping in two files. +- **Approach:** Add `parseAskUserQuestions(rawInput): StructuredQuestion[]` to `server/types.ts` or a `server/question-utils.ts`; both files call it. +- **Effort:** Small + +**5. Reduce `App.tsx` complexity with `useAppState` hook** +- **Location:** `src/App.tsx` lines 1–100+ +- **Problem:** 20+ state declarations and 10+ `useCallback` / `useEffect` hooks make the component hard to read and impossible to test in isolation. +- **Approach:** Extract a `src/hooks/useAppState.ts` composing all sub-hooks (`useSettings`, `useRepos`, `useSessions`, `useRouter`, etc.) into a single return value. `App` only handles layout/JSX. +- **Effort:** Medium + +**6. Extract `InputBar` sub-components** +- **Location:** `src/components/InputBar.tsx` — 684 lines +- **Problem:** Contains 10+ sub-functions/components (dropdowns, permission picker, model picker, mobile variant, skill menu integration) inside one file; growing independently. +- **Approach:** Move `PermissionModeDropdown`, `ModelDropdown`, `MobileInputBar`, `DesktopInputBar` into a `src/components/InputBar/` folder with an index re-export. +- **Effort:** Small + +**7. Merge `reapIdleSessions` into a single pass** +- **Location:** `server/session-manager.ts:reapIdleSessions` (line 141) +- **Problem:** Two separate `for` loops over `this.sessions.values()` — one for idle-stopping, one for stale-pruning — with duplicated source-type exemption guards. +- **Approach:** Combine into one loop; compute both `isIdle` and `isStale` per session, collect actions, then execute. Reduces O(2n) to O(n) and eliminates the repeated exemption checks. +- **Effort:** Small + +**8. Replace inline listeners in `ws-server.ts` with bridge classes** +- **Location:** `server/ws-server.ts` lines 517–590 +- **Problem:** Orchestrator prompt listener and workflow event broadcaster are long inline closures that belong to the `OrchestratorMonitor` and `WorkflowEngine` subsystems, not to server startup wiring. +- **Approach:** Add `OrchestratorBridge.attach(sessions, engine)` and `WorkflowBroadcaster.attach(engine, wss)` that encapsulate these listeners; call them once after init. +- **Effort:** Small + +**9. Extract `buildSessionContext` into a shared history replay utility** +- **Location:** `server/session-manager.ts:buildSessionContext` (line 1914) and `src/hooks/useChatSocket.ts:applyMessageMut` +- **Problem:** Both implement state-machine history replay logic to reconstruct conversation context from `WsServerMessage[]`. The server version is a reduced text version; the client version is a UI version — but the structural pattern (accumulating assistant text, flushing on `result`) is the same. +- **Approach:** Document a `replayHistory(messages, reducer)` utility usable by both; or at minimum extract a shared `accumulateAssistantText(messages): string` helper for the server path. +- **Effort:** Small + +**10. Inline cron parser or replace with a library** +- **Location:** `server/workflow-engine.ts` lines 159–210 +- **Problem:** The hand-rolled 5-field cron parser (`parseCronField`, `cronMatchesDate`, `nextCronMatch`) is ~50 lines with its own edge-case surface area. The 366-day minute-by-minute search loop in `nextCronMatch` is O(526,560) per call — acceptable for low-frequency use but unexpected. +- **Approach:** Replace with the `cron-parser` npm package (already in the ecosystem, battle-tested) or at least add an early exit to `nextCronMatch` once the next match is found past a reasonable bound. +- **Effort:** Small +```Committed and pushed the complexity report to `chore/workflow-reports-2026-04-07`. \ No newline at end of file diff --git a/.codekin/reports/repo-health/2026-04-09_repo-health.md b/.codekin/reports/repo-health/2026-04-09_repo-health.md new file mode 100644 index 00000000..12af2c36 --- /dev/null +++ b/.codekin/reports/repo-health/2026-04-09_repo-health.md @@ -0,0 +1,268 @@ +# Repository Health: codekin + +**Date**: 2026-04-09T03:24:21.219Z +**Repository**: /srv/repos/codekin +**Branch**: main +**Workflow Run**: c0f2f83c-0065-4a64-8243-9a7ec8d004e0 +**Session**: 5907a5ea-3b05-4757-9832-3ad0ffaeb070 + +--- + +Good, now let me gather the remaining data in parallel.Now I have all the data needed. Let me compile the final report.Now I have everything needed. Let me write the report. + +```markdown +# Codekin Repository Health Assessment — 2026-04-09 + +## Summary + +**Overall Health: Good** + +The repository is in active, well-maintained shape. CI is green, all open work was merged yesterday (2026-04-08) across 10 PRs, no open PRs remain, and there are zero stale TODO/FIXME items. The main housekeeping needs are: (1) a cluster of dead orchestrator-related code that should be removed, (2) 9 stale remote branch refs from yesterday's merged PRs, (3) a handful of minor config inconsistencies, and (4) a small CORS default misdocumentation. + +| Category | Count / Status | +|---|---| +| Dead code items | 13 (10 functions + 1 constant + 2 type clusters) | +| Stale TODOs/FIXMEs | 0 | +| Config issues | 7 minor | +| License concerns | 0 (3 MPL-2.0 acknowledged, build-time only) | +| Doc drift items | 4 (1 medium, 3 low) | +| Stale branches | 0 truly stale; 9 merged-PR refs pending deletion | +| Stuck open PRs | 0 (no open PRs) | +| High merge-conflict risk | 0 (all branches already merged) | + +--- + +## Dead Code + +> All findings are in the `src/` or `server/` directories. No orphan files were detected — all non-entry-point source files are imported by at least one other file. + +| File | Export / Function | Type | Recommendation | +|---|---|---|---| +| `src/lib/ccApi.ts` | `getOrchestratorStatus()` | Unused export | Remove — orchestrator feature inactive | +| `src/lib/ccApi.ts` | `getOrchestratorReports()` | Unused export | Remove — orchestrator feature inactive | +| `src/lib/ccApi.ts` | `getOrchestratorChildren()` | Unused export | Remove — orchestrator feature inactive | +| `src/lib/ccApi.ts` | `spawnOrchestratorChild()` | Unused export | Remove — orchestrator feature inactive | +| `src/lib/ccApi.ts` | `queryOrchestratorMemory()` | Unused export | Remove — orchestrator feature inactive | +| `src/lib/ccApi.ts` | `getOrchestratorTrust()` | Unused export | Remove — orchestrator feature inactive | +| `src/lib/ccApi.ts` | `getOrchestratorNotifications()` | Unused export | Remove — orchestrator feature inactive | +| `src/lib/ccApi.ts` | `getOrchestratorDashboard()` | Unused export | Remove — orchestrator feature inactive | +| `server/commit-event-hooks.ts` | `installCommitHook()` | Unused export | Remove — abandoned feature, ~35 lines | +| `server/commit-event-hooks.ts` | `uninstallCommitHook()` | Unused export | Remove — abandoned feature, ~35 lines | +| `server/orchestrator-reports.ts` | `scanAllReports()` | Unused export | Remove — no callers anywhere in codebase | +| `src/lib/workflowHelpers.ts` | `DAY_PATTERNS` | Unused export | Remove — `DAY_PRESETS`/`DAY_INDIVIDUAL` used internally but this combined export is not | +| Various `src/types.ts` | Orchestrator types: `ChildSessionRequest`, `ChildStatus`, `ChildSession`, `TrustLevel`, `TrustRecord`, `MemoryCandidate`, `SkillLevel`, `DecisionRecord` | Unused type exports | Remove as a group if orchestrator feature is abandoned | + +**Pattern:** The 8 orchestrator API functions in `ccApi.ts`, the `scanAllReports` function in `orchestrator-reports.ts`, and the orchestrator type cluster in `types.ts` all form a coherent dead-code island — an incomplete or abandoned "orchestrator" feature. These should be removed as a unit. + +--- + +## TODO/FIXME Tracker + +> Scanned all `.ts`, `.tsx`, `.js`, `.mjs` files in `src/` and `server/`. Today's cutoff for "stale" is 2026-03-10 (30 days before 2026-04-09). + +| File:Line | Type | Comment | Author | Date | Stale? | +|---|---|---|---|---|---| +| `server/plan-manager.ts:8` | WORKAROUND | `deny-with-message workaround for ExitPlanMode` | alari | 2026-03-25 | No | +| `server/plan-manager.ts:22` | WORKAROUND | `On approve: hook returns deny-with-approval-message (CLI workaround for requiresUserInteraction)` | alari | 2026-03-25 | No | + +Both are intentional JSDoc annotations documenting a known Claude CLI behavioral constraint (the `ExitPlanMode` deny-with-approval-message pattern). They are not deferred work items. + +Three occurrences of the string literal `'TODO'` appear in `server/claude-process.test.ts:61,62,810` (blamed to 2026-03-08, >30 days) — these are test fixture values passed to `summarizeToolInput()`, not debt markers. + +**Summary:** + +| Type | Count | Stale | +|---|---|---| +| TODO | 0 | 0 | +| FIXME | 0 | 0 | +| HACK | 0 | 0 | +| XXX | 0 | 0 | +| WORKAROUND | 2 (intentional) | 0 | +| **Total** | **2** | **0** | + +--- + +## Config Drift + +| Config File | Setting | Current Value | Recommended Value / Action | +|---|---|---|---| +| `package.json` + `server/package.json` | TypeScript version | Frontend: `^6.0.2`, Server: `~5.9.3` | Align both to `^6.0.2` — two different versions cause inconsistent type checking | +| `tsconfig.node.json` | `target` | `ES2023` | `ES2022` — inconsistent with `tsconfig.app.json` and `server/tsconfig.json` (both `ES2022`) | +| `server/tsconfig.json` | `noUncheckedSideEffectImports` | Missing | Add `true` — present in other configs, provides consistent safety checks | +| `eslint.config.js` | Rule severity (8 rules) | `warn` | Promote to `error` over time — warnings allow CI to pass with violations | +| `eslint.config.js` | Test file config | `tseslint.configs.recommended` | Consider `strictTypeChecked` — test code currently gets less strict type checking than production code | +| `package.json` | `lint` script | `"eslint ."` | `"eslint src server vite.config.ts"` — current form may lint build outputs | +| `server/package.json` | `overrides.vite` | `"^8.0.5"` | Remove — Vite is not a direct server dependency; this override is spurious | + +**Positive findings:** `strict: true` is set in all TypeScript configs; ESLint uses modern flat config (v9+) with `strictTypeChecked` for frontend and server; Prettier config is clean. + +--- + +## License Compliance + +**Project license:** MIT + +**Summary (509 packages):** + +| License | Count | Notes | +|---|---|---| +| MIT | 441 | Permissive ✓ | +| ISC | 20 | Permissive ✓ | +| Apache-2.0 | 18 | Permissive ✓ | +| BSD-3-Clause | 9 | Permissive ✓ | +| BSD-2-Clause | 8 | Permissive ✓ | +| MPL-2.0 | 3 | Weak copyleft — see below | +| MIT-0 | 2 | Permissive ✓ | +| BlueOak-1.0.0 | 2 | Permissive ✓ | +| MPL-2.0 OR Apache-2.0 | 1 | Dual-licensed — see below | +| CC-BY-4.0 | 1 | Data only (`caniuse-lite`) ✓ | +| CC0-1.0 | 1 | Public domain (`mdn-data`) ✓ | +| MIT OR WTFPL | 1 | Permissive either way ✓ | +| 0BSD | 1 | Public domain (`tslib`) ✓ | + +**Flagged packages:** + +| Package | License | Risk | Notes | +|---|---|---|---| +| `lightningcss` + 2 platform binaries | MPL-2.0 | Low | Build-time only (TailwindCSS dep); not shipped in built artifacts | +| `dompurify` | MPL-2.0 OR Apache-2.0 | Negligible | Dual-licensed; Apache-2.0 option is fully permissive | + +Both MPL-2.0 situations are already acknowledged in `package.json`'s `licenseNotes` field. No GPL, AGPL, LGPL, SSPL, BUSL, or EPL packages detected. All 509 packages have a recognised SPDX identifier — zero unknown licenses. + +--- + +## Documentation Freshness + +### API / Protocol Docs + +The `docs/API-REFERENCE.md` and `docs/stream-json-protocol.md` were updated on 2026-04-08 (PR #300) to remove stale endpoints and fix env var names. The WebSocket message types in `src/types.ts` and the `session-lifecycle.ts` refactor (PR #308) are internal — no protocol changes required doc updates. No server-route drift detected. + +### README Drift + +The `README.md` scripts (`npm run dev`, `npm run build`, `npm test`, `npm run lint`, `npm run test:watch`) all exist in `package.json`. No drift. + +### Stale Doc Items + +| File | Line | Issue | Severity | +|---|---|---|---| +| `docs/INSTALL-DISTRIBUTION.md` | ~141 | `CORS_ORIGIN` default documented as `*`; actual default in `server/config.ts` is `http://localhost:5173` | Medium | +| `docs/SETUP.md` | ~395 | `lib/` directory described as containing "terminal theme" — no such file exists (removed with xterm.js) | Low | +| `docs/SETUP.md` | ~351 | "Updating" section includes `cd server && npm install` — server deps are now in root `package.json` | Low | +| `CLAUDE.md` | components example | `RepoSelector` listed as example component; file was removed (replaced by `RepoList.tsx`/`RepoSection.tsx`) | Very Low | + +--- + +## Draft Changelog + +> Covers commits since tag `v0.5.4` (2026-04-06) through 2026-04-09. 16 commits on `main`. + +### Refactoring +- Extract session lifecycle logic into dedicated `session-lifecycle.ts` module (#308) +- Extract `PromptRouter` from `SessionManager` into its own module (#303) + +### Fixes +- Strip `GIT_*` environment variables when spawning Claude CLI processes to prevent env leakage (#307) +- Prevent worktree restart death loops by validating CWD before restart (#305) +- Prevent broken worktree directories from causing infinite restart loops (#304) +- Preserve `claudeSessionId` on spawn failures (ENOENT) so session history is not lost (#302) +- Resolve session restart race conditions and worktree index corruption (#301) +- Prevent caller-supplied branch names from being deleted; use `show-ref` for branch detection +- Remove unused WebSocket import in `prompt-router` + +### Tests +- Add unit tests covering session restart and worktree fix scenarios (#306) + +### Documentation +- Fix stale paths, env var names, and remove non-existent API endpoints from docs (#300) + +### Chores +- Add workflow reports for 2026-04-07 (#299) +- Security, reliability, and housekeeping fixes (#298) + +--- + +## Stale Branches + +> No branches have been inactive for 30+ days. All 9 non-main remote branches received their last commit on 2026-04-08 (yesterday). However, all 9 correspond to PRs that were merged yesterday — their remote refs are now orphaned and should be deleted. + +| Branch | Last Commit | Author | PR | Merged? | Recommendation | +|---|---|---|---|---|---| +| `refactor/extract-session-lifecycle` | 2026-04-08 | alari | #308 | Yes | Delete remote ref | +| `fix/strip-git-env-vars-from-claude-spawn` | 2026-04-08 | alari | #307 | Yes | Delete remote ref | +| `test/cover-session-restart-fixes` | 2026-04-08 | alari | #306 | Yes | Delete remote ref | +| `fix/worktree-restart-resilience` | 2026-04-08 | alari | #305 | Yes | Delete remote ref | +| `fix/worktree-creation-resilience` | 2026-04-08 | alari | #304 | Yes | Delete remote ref | +| `refactor/session-manager-extract` | 2026-04-08 | alari | #303 | Yes | Delete remote ref | +| `fix/spawn-failure-preserve-session-id` | 2026-04-08 | alari | #302 | Yes | Delete remote ref | +| `fix/session-restart-race-conditions` | 2026-04-08 | alari | #301 | Yes | Delete remote ref | +| `docs/cleanup-2026-04-08` | 2026-04-08 | alari | #300 | Yes | Delete remote ref | + +--- + +## PR Hygiene + +**No open PRs.** All recent work was merged on 2026-04-08. + +**Notable closed PRs to be aware of:** + +| PR# | Title | Status | Note | +|---|---|---|---| +| #309 | fix: resolve all 24 lint errors | Closed without merging | Lint errors may still be present — verify with `npm run lint` | +| #297 | chore: add repo health report | Closed without merging | Superseded by subsequent reports | +| #296 | Chore/docs optimize 2026-04-06 | Closed without merging | Superseded | + +PR #309 is the most relevant: it was closed without merging, suggesting the 24 lint errors it addressed may remain in the codebase. This should be verified. + +--- + +## Merge Conflict Forecast + +All 9 non-main remote branches correspond to **already-merged PRs**. There are no truly active unmerged branches. The "ahead" commits visible on those branches are pre-squash branch tips that were superseded by the squash merge into main — they pose no conflict risk. + +| Branch | Ahead | Behind | Status | Risk | +|---|---|---|---|---| +| All 9 listed above | 0–5 (artifact) | 1–14 | Merged via PR | None — branch can be deleted | + +No active unmerged work is currently diverged from `main`. + +--- + +## Recommendations + +1. **Remove orphaned remote branch refs** (9 branches) — these all correspond to merged PRs from 2026-04-08 and add noise to `git branch -r`. Run `git push origin --delete ` for each, or use `git remote prune origin` after deleting via GitHub. + +2. **Delete the dead orchestrator code island** — the 8 functions in `src/lib/ccApi.ts`, `server/orchestrator-reports.ts:scanAllReports()`, and the orchestrator types in `src/types.ts` are all unreferenced. Removing them reduces the codebase by ~150–200 lines and eliminates misleading surface area. Do this as a single PR. + +3. **Verify lint status after PR #309 was closed** — PR #309 ("fix: resolve all 24 lint errors") was closed without merging. Run `npm run lint` to determine if lint errors remain in the current `main` branch. If so, open a fresh fix branch. + +4. **Fix `CORS_ORIGIN` documentation in `INSTALL-DISTRIBUTION.md`** — the documented default (`*`) differs from the actual default (`http://localhost:5173`). This is a medium-severity issue for anyone deploying from docs alone. + +5. **Remove `installCommitHook`/`uninstallCommitHook` from `server/commit-event-hooks.ts`** — these are dead code from an abandoned feature with zero callers. Can be batched into the orchestrator cleanup PR. + +6. **Align TypeScript versions** — `package.json` allows `^6.0.2` while `server/package.json` pins `~5.9.3`. Align both to `^6.0.2` (or use a workspace-level single TS install) to avoid subtle type-checking inconsistencies. + +7. **Tag a new release** — 16 commits (including 8 fixes, 2 refactors, 1 test addition) have landed on `main` since `v0.5.4` (2026-04-06). This warrants at minimum a `v0.5.5` patch tag. + +8. **Remove `workflowHelpers.ts:DAY_PATTERNS`** — unused export; can be removed in a small cleanup PR or batched with item 2. + +9. **Standardise `tsconfig.node.json` target** — change `ES2023` to `ES2022` to match the other two tsconfig files and eliminate a subtle inconsistency in the build pipeline. + +10. **Update `docs/SETUP.md`** — fix the two low-severity items: remove the stale "terminal theme" description from the `lib/` entry and remove the obsolete `cd server && npm install` step from the "Updating" section. +```Report written to `.codekin/reports/repo-health/2026-04-09_repo-health.md`. + +--- + +Here's the executive summary of findings: + +**Overall Health: Good** + +The repo is in solid shape — 10 PRs merged cleanly yesterday, zero open PRs, zero stale TODOs, clean license tree. The main action items: + +**Top priorities:** +1. **Dead orchestrator code** — 8 unused API functions in `src/lib/ccApi.ts`, `scanAllReports()` in `server/orchestrator-reports.ts`, and a cluster of orphaned types in `src/types.ts` form a coherent dead-code island (~150–200 lines). Remove as one PR. +2. **Verify lint errors** — PR #309 ("fix: resolve all 24 lint errors") was closed without merging. Run `npm run lint` to confirm whether those errors are still present. +3. **Delete 9 stale remote branch refs** — all correspond to yesterday's merged PRs; safe to prune. +4. **Fix `CORS_ORIGIN` docs** — `INSTALL-DISTRIBUTION.md` documents the default as `*` but `server/config.ts` defaults to `http://localhost:5173`. +5. **Tag `v0.5.5`** — 16 commits have landed since `v0.5.4`. + +**Minor config drift:** TypeScript version mismatch between `package.json` (`^6.0.2`) and `server/package.json` (`~5.9.3`); `tsconfig.node.json` targets `ES2023` while others target `ES2022`; spurious Vite override in `server/package.json`. \ No newline at end of file