Board UX fixes, intake dialog polish, and over-engineering cleanup - #25
Conversation
Replace the logic/TUI two-tier split with src at MI 52 first and test/ support files at MI 40 second so the fast verify path scores all source before slower test fixtures. Co-authored-by: Cursor <cursoragent@cursor.com>
Score non-TUI logic at MI 52 and the TUI surface at 50, then fold artificial verifyx micro-splits back into cohesive modules so the gate matches the architecture instead of forcing file fragmentation. Co-authored-by: Cursor <cursoragent@cursor.com>
Replace host DialogSelect/Prompt/Confirm for the intake chain so assumptions, questions, and mode rationale are readable as markdown, with short actions beside the body (answer step stays full-width stacked). Co-authored-by: Cursor <cursoragent@cursor.com>
Hand-edited opencode.json often keeps a trailing comma; strict JSON parse made plugin:install:prod fail with an opaque SyntaxError. Co-authored-by: Cursor <cursoragent@cursor.com>
Keep selectedColumn synced with the highlighted card, auto-select on refresh, blur leftover host focus on open, and cycle root tasks with Tab/Shift+Tab. Co-authored-by: Cursor <cursoragent@cursor.com>
Approve/Reject were ambiguous when a clarifying question was on screen; Accept assumption / Override with answer name the object of the choice. Co-authored-by: Cursor <cursoragent@cursor.com>
- delete CreateTaskDependencies bag and createUpdateController's optional check/confirm/runCommand/now; tests mock modules instead - dedupe patch.ts lock/read/merge/update skeleton into withKaganUpdate - delete shellGitRunner; server uses bunGitRunner (now a const, not a factory) - board passes store instead of drilling cap/sendBackStopThreshold/checkCommand - inline buildEditorContext/listEditorSignals/listEditorDialogControls into hook - drop dead code: setupCommand field, unused checkCommand hook prop, test:ci script, HOST_DIALOG_WIDTH size param, oxfmt pass in install-plugin - fold eligible predicate into spawnHelper; store parses options once - delete update-launch.test.ts (re-implemented wiring) and duplicate gateBadges mode tests; simplify git-shell fixture (preload already isolates) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Greptile SummaryThis PR streamlines the board and server code while polishing several TUI workflows. The main changes are:
Confidence Score: 4/5The changed config parsing path can silently alter quoted values and needs a fix before merging. Trailing-comma recovery operates on raw text rather than JSON tokens. A recoverable config can be parsed and saved with modified string data. scripts/install-plugin.ts
What T-Rex did
|
| Filename | Overview |
|---|---|
| scripts/install-plugin.ts | Adds trailing-comma recovery, but the raw replacement can alter commas inside quoted values. |
| src/git/runner.ts | Replaces the shell-backed git runner with a shared Bun runner and updates callers to use its value form. |
| src/server/session/patch.ts | Consolidates serialized metadata updates while preserving fresh-read and merge behavior. |
| src/server/helpers/spawn.ts | Consolidates helper eligibility and switches review git operations to the shared Bun runner. |
| src/tui/board/store/selection.ts | Adds wrapped root-card navigation while retaining child-aware row selection. |
| src/tui/dialogs/task-details-view.tsx | Keeps the task summary pinned and moves long detail sections into a bounded scroll area. |
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 1
scripts/install-plugin.ts:30
**Fallback Rewrites Quoted Values**
When an invalid config has both a trailing comma and a quoted value containing `, }` or `, ]`, this raw-text replacement removes the comma inside the string as well. The second parse can then succeed and the installer writes back silently changed configuration data; trailing commas need to be removed with a string-aware scanner or JSONC parser.
Reviews (1): Last reviewed commit: "refactor: remove test-only DI seams and ..." | Re-trigger Greptile
| } catch { | ||
| // hand-edited OpenCode configs often keep a trailing comma | ||
| try { | ||
| return JSON.parse(text.replace(/,\s*([}\]])/g, "$1")) as Record<string, unknown> |
There was a problem hiding this comment.
Fallback Rewrites Quoted Values
When an invalid config has both a trailing comma and a quoted value containing , } or , ], this raw-text replacement removes the comma inside the string as well. The second parse can then succeed and the installer writes back silently changed configuration data; trailing commas need to be removed with a string-aware scanner or JSONC parser.
Context Used: AGENTS.md (source)
Artifacts
Repro: executable harness invoking the actual installer reset path with a disposable config home
- Contains supporting evidence from the run (text/x-shellscript; charset=utf-8).
Repro: input config containing both the quoted comma sequence and actual trailing comma
- Contains supporting evidence from the run (application/json; charset=utf-8).
Repro: successful execution trace showing the original and silently modified quoted values
- Keeps the command output available without making the summary code-heavy.
Ran code and verified through T-Rex
Prompt To Fix With AI
This is a comment left during a code review.
Path: scripts/install-plugin.ts
Line: 30
Comment:
**Fallback Rewrites Quoted Values**
When an invalid config has both a trailing comma and a quoted value containing `, }` or `, ]`, this raw-text replacement removes the comma inside the string as well. The second parse can then succeed and the installer writes back silently changed configuration data; trailing commas need to be removed with a string-aware scanner or JSONC parser.
**Context Used:** AGENTS.md ([source](https://app.greptile.com/kagan/github/kagan-sh/kagan/-/custom-context?memory=88a14340-9a15-4297-925d-3656d144ad2a))
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
Fixed in 7a0669d — replaced the raw regex with a string-aware scanner that tracks quote/escape state, so , } / , ] inside quoted values are left untouched; only structural trailing commas are stripped.
Raw regex fallback also removed ", }" / ", ]" sequences inside quoted config values, silently rewriting them on the reparse-and-write path. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* refactor: gate src complexity before test support files Replace the logic/TUI two-tier split with src at MI 52 first and test/ support files at MI 40 second so the fast verify path scores all source before slower test fixtures. * refactor: restore logic/TUI complexity tiers and cohesive layout Score non-TUI logic at MI 52 and the TUI surface at 50, then fold artificial verifyx micro-splits back into cohesive modules so the gate matches the architecture instead of forcing file fragmentation. * feat: render intake gates with markdown two-column dialogs Replace host DialogSelect/Prompt/Confirm for the intake chain so assumptions, questions, and mode rationale are readable as markdown, with short actions beside the body (answer step stays full-width stacked). * fix: tolerate trailing commas in OpenCode plugin config Hand-edited opencode.json often keeps a trailing comma; strict JSON parse made plugin:install:prod fail with an opaque SyntaxError. * fix: make board keyboard selection reliable and add Tab cycling Keep selectedColumn synced with the highlighted card, auto-select on refresh, blur leftover host focus on open, and cycle root tasks with Tab/Shift+Tab. Co-authored-by: Cursor <cursoragent@cursor.com> * fix: clarify intake decision action labels Approve/Reject were ambiguous when a clarifying question was on screen; Accept assumption / Override with answer name the object of the choice. * feat: lead Review menu with approve * fix: scroll task details overflow * refactor: remove test-only DI seams and dead flexibility - delete CreateTaskDependencies bag and createUpdateController's optional check/confirm/runCommand/now; tests mock modules instead - dedupe patch.ts lock/read/merge/update skeleton into withKaganUpdate - delete shellGitRunner; server uses bunGitRunner (now a const, not a factory) - board passes store instead of drilling cap/sendBackStopThreshold/checkCommand - inline buildEditorContext/listEditorSignals/listEditorDialogControls into hook - drop dead code: setupCommand field, unused checkCommand hook prop, test:ci script, HOST_DIALOG_WIDTH size param, oxfmt pass in install-plugin - fold eligible predicate into spawnHelper; store parses options once - delete update-launch.test.ts (re-implemented wiring) and duplicate gateBadges mode tests; simplify git-shell fixture (preload already isolates) * fix: strip trailing commas with string-aware scanner Raw regex fallback also removed ", }" / ", ]" sequences inside quoted config values, silently rewriting them on the reparse-and-write path.
* Board UX fixes, intake dialog polish (#25) * refactor: gate src complexity before test support files Replace the logic/TUI two-tier split with src at MI 52 first and test/ support files at MI 40 second so the fast verify path scores all source before slower test fixtures. * refactor: restore logic/TUI complexity tiers and cohesive layout Score non-TUI logic at MI 52 and the TUI surface at 50, then fold artificial verifyx micro-splits back into cohesive modules so the gate matches the architecture instead of forcing file fragmentation. * feat: render intake gates with markdown two-column dialogs Replace host DialogSelect/Prompt/Confirm for the intake chain so assumptions, questions, and mode rationale are readable as markdown, with short actions beside the body (answer step stays full-width stacked). * fix: tolerate trailing commas in OpenCode plugin config Hand-edited opencode.json often keeps a trailing comma; strict JSON parse made plugin:install:prod fail with an opaque SyntaxError. * fix: make board keyboard selection reliable and add Tab cycling Keep selectedColumn synced with the highlighted card, auto-select on refresh, blur leftover host focus on open, and cycle root tasks with Tab/Shift+Tab. Co-authored-by: Cursor <cursoragent@cursor.com> * fix: clarify intake decision action labels Approve/Reject were ambiguous when a clarifying question was on screen; Accept assumption / Override with answer name the object of the choice. * feat: lead Review menu with approve * fix: scroll task details overflow * refactor: remove test-only DI seams and dead flexibility - delete CreateTaskDependencies bag and createUpdateController's optional check/confirm/runCommand/now; tests mock modules instead - dedupe patch.ts lock/read/merge/update skeleton into withKaganUpdate - delete shellGitRunner; server uses bunGitRunner (now a const, not a factory) - board passes store instead of drilling cap/sendBackStopThreshold/checkCommand - inline buildEditorContext/listEditorSignals/listEditorDialogControls into hook - drop dead code: setupCommand field, unused checkCommand hook prop, test:ci script, HOST_DIALOG_WIDTH size param, oxfmt pass in install-plugin - fold eligible predicate into spawnHelper; store parses options once - delete update-launch.test.ts (re-implemented wiring) and duplicate gateBadges mode tests; simplify git-shell fixture (preload already isolates) * fix: strip trailing commas with string-aware scanner Raw regex fallback also removed ", }" / ", ]" sequences inside quoted config values, silently rewriting them on the reparse-and-write path. * build(deps-dev): bump @types/bun from 1.3.13 to 1.3.14 Bumps [@types/bun](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/bun) from 1.3.13 to 1.3.14. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/bun) --- updated-dependencies: - dependency-name: "@types/bun" dependency-version: 1.3.14 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: Al <7698600+aorumbayev@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* Board UX fixes, intake dialog polish (#25) * refactor: gate src complexity before test support files Replace the logic/TUI two-tier split with src at MI 52 first and test/ support files at MI 40 second so the fast verify path scores all source before slower test fixtures. * refactor: restore logic/TUI complexity tiers and cohesive layout Score non-TUI logic at MI 52 and the TUI surface at 50, then fold artificial verifyx micro-splits back into cohesive modules so the gate matches the architecture instead of forcing file fragmentation. * feat: render intake gates with markdown two-column dialogs Replace host DialogSelect/Prompt/Confirm for the intake chain so assumptions, questions, and mode rationale are readable as markdown, with short actions beside the body (answer step stays full-width stacked). * fix: tolerate trailing commas in OpenCode plugin config Hand-edited opencode.json often keeps a trailing comma; strict JSON parse made plugin:install:prod fail with an opaque SyntaxError. * fix: make board keyboard selection reliable and add Tab cycling Keep selectedColumn synced with the highlighted card, auto-select on refresh, blur leftover host focus on open, and cycle root tasks with Tab/Shift+Tab. Co-authored-by: Cursor <cursoragent@cursor.com> * fix: clarify intake decision action labels Approve/Reject were ambiguous when a clarifying question was on screen; Accept assumption / Override with answer name the object of the choice. * feat: lead Review menu with approve * fix: scroll task details overflow * refactor: remove test-only DI seams and dead flexibility - delete CreateTaskDependencies bag and createUpdateController's optional check/confirm/runCommand/now; tests mock modules instead - dedupe patch.ts lock/read/merge/update skeleton into withKaganUpdate - delete shellGitRunner; server uses bunGitRunner (now a const, not a factory) - board passes store instead of drilling cap/sendBackStopThreshold/checkCommand - inline buildEditorContext/listEditorSignals/listEditorDialogControls into hook - drop dead code: setupCommand field, unused checkCommand hook prop, test:ci script, HOST_DIALOG_WIDTH size param, oxfmt pass in install-plugin - fold eligible predicate into spawnHelper; store parses options once - delete update-launch.test.ts (re-implemented wiring) and duplicate gateBadges mode tests; simplify git-shell fixture (preload already isolates) * fix: strip trailing commas with string-aware scanner Raw regex fallback also removed ", }" / ", ]" sequences inside quoted config values, silently rewriting them on the reparse-and-write path. * build(deps): bump zod from 4.1.8 to 4.4.3 Bumps [zod](https://github.com/colinhacks/zod) from 4.1.8 to 4.4.3. - [Release notes](https://github.com/colinhacks/zod/releases) - [Commits](colinhacks/zod@v4.1.8...v4.4.3) --- updated-dependencies: - dependency-name: zod dependency-version: 4.4.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: Al <7698600+aorumbayev@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* Board UX fixes, intake dialog polish (#25) * refactor: gate src complexity before test support files Replace the logic/TUI two-tier split with src at MI 52 first and test/ support files at MI 40 second so the fast verify path scores all source before slower test fixtures. * refactor: restore logic/TUI complexity tiers and cohesive layout Score non-TUI logic at MI 52 and the TUI surface at 50, then fold artificial verifyx micro-splits back into cohesive modules so the gate matches the architecture instead of forcing file fragmentation. * feat: render intake gates with markdown two-column dialogs Replace host DialogSelect/Prompt/Confirm for the intake chain so assumptions, questions, and mode rationale are readable as markdown, with short actions beside the body (answer step stays full-width stacked). * fix: tolerate trailing commas in OpenCode plugin config Hand-edited opencode.json often keeps a trailing comma; strict JSON parse made plugin:install:prod fail with an opaque SyntaxError. * fix: make board keyboard selection reliable and add Tab cycling Keep selectedColumn synced with the highlighted card, auto-select on refresh, blur leftover host focus on open, and cycle root tasks with Tab/Shift+Tab. Co-authored-by: Cursor <cursoragent@cursor.com> * fix: clarify intake decision action labels Approve/Reject were ambiguous when a clarifying question was on screen; Accept assumption / Override with answer name the object of the choice. * feat: lead Review menu with approve * fix: scroll task details overflow * refactor: remove test-only DI seams and dead flexibility - delete CreateTaskDependencies bag and createUpdateController's optional check/confirm/runCommand/now; tests mock modules instead - dedupe patch.ts lock/read/merge/update skeleton into withKaganUpdate - delete shellGitRunner; server uses bunGitRunner (now a const, not a factory) - board passes store instead of drilling cap/sendBackStopThreshold/checkCommand - inline buildEditorContext/listEditorSignals/listEditorDialogControls into hook - drop dead code: setupCommand field, unused checkCommand hook prop, test:ci script, HOST_DIALOG_WIDTH size param, oxfmt pass in install-plugin - fold eligible predicate into spawnHelper; store parses options once - delete update-launch.test.ts (re-implemented wiring) and duplicate gateBadges mode tests; simplify git-shell fixture (preload already isolates) * fix: strip trailing commas with string-aware scanner Raw regex fallback also removed ", }" / ", ]" sequences inside quoted config values, silently rewriting them on the reparse-and-write path. * build(deps-dev): bump solid-js from 1.9.10 to 1.9.14 Bumps [solid-js](https://github.com/solidjs/solid) from 1.9.10 to 1.9.14. - [Release notes](https://github.com/solidjs/solid/releases) - [Changelog](https://github.com/solidjs/solid/blob/main/CHANGELOG.md) - [Commits](https://github.com/solidjs/solid/commits) --- updated-dependencies: - dependency-name: solid-js dependency-version: 1.9.14 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: Al <7698600+aorumbayev@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Summary
Nine commits: board/intake UX fixes, complexity-gate restructuring, and a whole-codebase over-engineering cleanup (−299 net lines in the final commit, none touching user-visible behavior).
UX and fixes
Verification infrastructure
Over-engineering cleanup (audit-driven)
CreateTaskDependenciesbag,createUpdateControlleroptional deps); tests mock modules insteadpatch.tslock/read/merge/update skeleton into one private helper, public API unchangedshellGitRunner; server usesbunGitRunner(now a const)cap/sendBackStopThreshold/checkCommandthrough four component layerssetupCommandfield, unused hook prop,test:ciscript, dead dialog width sizes, oxfmt pass in install scriptupdate-launch.test.ts(re-implemented wiring locally), byte-identical duplicategateBadgesmode testsTesting
bun run checkclean (verifyx gates + package check against OpenCode 1.17.20 and 1.17.13)🤖 Generated with Claude Code