Skip to content

Tags: kagan-sh/kagan

Tags

v0.4.1

Toggle v0.4.1's commit message
fix: 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.

v0.4.0

Toggle v0.4.0's commit message
feat: refine upgrade mechanism; minor tweaks; docs (#24)

v0.3.1

Toggle v0.3.1's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
fix: simplify verifyx gate (#19)

* fix: enforce all verifyx checks and check-only pre-commit

Install knip, skott, and jscpd so verifyx all runs every built-in gate, dedupe
status resolution and break git/domain layering cycles flagged by the new checks,
and make the pre-commit hook check-only so staged content is never rewritten.

* test: make git isolation structural via test preload (#20)

* test: make git hermeticity structural via preload

* test: rename hermeticity wording to git isolation

* test: wait for the merge-conflict notice instead of asserting notice order

* test: allow slow CI git spawns to deliver the merge-conflict notice

* fix: make update promotion crash-safe and trim speculative machinery (#21)

* fix: make update promotion crash-safe and trim speculative machinery

Restore interrupted promotions on launch, self-heal stale cache state, surface
local update failures in the footer, and remove unused concurrency/path checks.

* fix: harden update cleanup against unvalidated deletes and false ready

Finding 1: removeStaleMarker only deletes marker.prepared when it is a
kagan@<x.y.z> sibling of the current wrapper in the same scope cache;
a corrupted marker naming any other path now leaves that path alone.

Finding 2: removed dead restoreCurrentFromBackup / interruptedPromotion
branch (the host re-downloads latest before the plugin loads, so it can
never run), aligned R18.8 and design.md to the real contract, and closed
the prepared-dir leak in the matched-marker cleanup path.

Finding 3: prepare failure on a ready check now sets broken status and
suppresses the ready toast instead of promising a restart that applies
nothing; a failed cleanup now returns broken before the network check.

* test: skip the host-dedupe pin when the vendored source is absent

references/opencode is git-ignored, so CI checkouts never have it.

---------

* refactor: simplify update marker and cleanup machinery

* refactor: merge single-importer modules

* refactor: extract duplicated TUI blocks

* chore: drop redundant verify overrides

* ci: run check workflow on pull requests only

* refactor: inline single-use list-editor row wrapper

renderListEditorRows only forwarded its five arguments to <ListEditorRows>
and had a single caller; render it directly and drop the now-unused JSX import.

* test: make merge-dialog command tests deterministic across file order

The two "approving …" tests in test/tui/board/commands.test.ts flaked only on
CI. Root cause: bun's mock.module is process-global and persistent, and
test/tui/session/tasks.test.ts mocks src/git/runner (currentBranch -> "kagan/x")
and src/git/merge (mergeTaskBranch -> ok:true). ESM imports hoist above
mock.module, so whichever test file loads first wins; on the Linux runner
tasks.test.ts loaded first, so the merge-dialog tests saw the leaked mocks
(wrong branch, no conflict) and failed. macOS load order hid it locally.

- commands.test.ts now declares its own git/runner + git/merge mocks and drives
  the three merge-dialog tests through reset-per-test vars (currentBranchValue,
  localBranches, mergeResult), so its values win for its own tests regardless of
  which file ran first.
- tasks.test.ts's git/runner mock was incomplete (missing listLocalBranches and
  baseBranchFreshness); stub them so binding those exports elsewhere while the
  mock is active no longer throws "Export not found".
- The merge dialog's onSelect returns its handler promise so tests await the
  real work instead of racing a render/timer.

Reproduced the exact leak order locally (bun test tasks.test.ts commands.test.ts)
and via a Linux-container full-suite run; green there, commands-only, and reverse.

* fix: surface both promotion and restore errors on update rollback

promotePreparedUpdate runs in api.lifecycle.onDispose, whose thrown errors the
host logs via console.error rather than discarding. Swallowing a failed restore
therefore hid it: a lost kagan@latest wrapper logged only as a promotion
failure. Rethrow an AggregateError carrying both, and add a test covering the
double-failure path (the single-failure restore was already tested).

v0.3.0

Toggle v0.3.0's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
test: run real-git tests in isolation and guard global-state leaks (#13)

* test: run real-git tests in isolation and guard global-state leaks

* test: use the platform null device for hermetic git config isolation

v0.2.2

Toggle v0.2.2's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
fix: self-align remediation gaps (#12)

* fix: remediate self-align audit findings

Close merge TOCTOU on squash failure, extend push-guard path matching,
emit check/setup partial and skipped badges, add filterable model and
branch pickers, align R6.2 with handoff behavior, and clean up docs,
dead exports, and duplicated helpers from the triage pass.

* fix: close remaining self-align audit gaps

Align code and specs on custom scope command matching, trust packet
title/status, merge dirty-worktree guards, push-guard subshell detection,
absolute cwd rejection, prompt evidence isolation, and status schema reads.
Add R3.8/R17.11–13 requirements, docs corrections, and OptionBoundsSchema
for settings validation.

* refactor: remove trust packet export/import, keep task details view

Trust packet file I/O was misleading portable handoff without restore semantics;
the in-app View details summary is the only retained path.

* fix: abort helper sessions before deleting a board task

Deleting a task while intake was still running left the child agent writing
parts after the parent session was removed, triggering OpenCode DB errors.

* fix: address branch review gaps

* fix: wire board settings shortcut

v0.2.1

Toggle v0.2.1's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
fix: npm keyboard, Enter submit, and duplicate helper spawn (#11)

* fix: ship compiled dist, make Enter submit, dedupe intake spawn

npm keyboard (Bug 1): the host's Solid compile transform skips any path
under node_modules, so raw src/*.tsx published to npm never got compiled
and no onMount/keymap handlers ran — every hotkey was dead. Add a
per-file Babel build (scripts/build.ts) that pre-compiles src -> dist
with OpenTUI's transformSolidSource, keeping @opentui/* and solid-js as
external bare imports. Publish dist instead of src, move those runtime
libs to optional peerDependencies, and add a prepack hook so npm pack /
publish always builds first.

create-task Enter (Bug 2): most terminals send bare CR for both Enter and
Ctrl+Enter, so Ctrl+Enter could never submit. Plain Enter now submits
from every field; Ctrl+J inserts a newline in the description.

double intake (Bug 3): a duplicate plugin load in a worktree gave each
module copy its own in-memory guard, so two session.updated events could
both spawn intake. Share helperEntryClaims and sessionLocks on globalThis
and claim the spawn (intakeOutcome: "pending") inside the serialized
metadata lock before creating the child; a failed spawn clears the claim
so retries still work.

* fix: apply durable claim to validator spawn; build log to stderr

Mirror the intake dedupe onto the validator path: onEnterReview now
claims the spawn via claimHelperSpawn("validator") inside the serialized
metadata lock, and spawnValidator no longer writes validatorOutcome
itself, so a duplicate plugin load can't spawn two validators.

Route build.ts's summary log to stderr so the prepack build during
npm pack --dry-run --json doesn't corrupt the JSON package:check parses.

* fix: clear helper claim on pre-spawn errors, kitty newline, robust build

Adversarial-review follow-ups on the npm/keyboard/intake fixes:

- server.ts: widen the intake and validator try/catch to cover resolveTaskRefs,
  worktreeDiffs, and the check commands. A throw in that pre-spawn work
  previously left {role}Outcome:"pending" with no session, so every later
  event returned early and the helper never retried (permanent lockout,
  flagged by Greptile). Any pre-spawn throw now routes through
  handleHelperFailure, which clears the claim. Regression tests for both paths.

- create-task.tsx: Ctrl+J now inserts a newline in the description on Kitty
  terminals too. Kitty reports Ctrl+J as {name:"j",ctrl}, not linefeed, so the
  old fall-through did nothing there; insert via descriptionRef.newLine() for
  ctrl+j, linefeed, and shift+return.

- build.ts: compile with public babel presets instead of importing OpenTUI's
  private scripts/solid-transform.js, which could vanish on any OpenTUI upgrade.

- package.json: peer floor >=0.3.4 (matches @opencode-ai/plugin's own range);
  dev pins aligned to the host's @OpenTui 0.4.3 / solid-js 1.9.10.

* fix: support packed production plugin install

* fix: raise opentui peer floors

v0.2.0

Toggle v0.2.0's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
feat: flag when a newer Kagan release is available (#10)

OpenCode installs a plugin once and caches it forever — it never re-checks
npm, so users are never told a newer Kagan exists. Check the npm dist-tags
endpoint at most once a day (cached in api.kv across restarts), and show
`→ vX.Y.Z available` in the board footer when a newer release is out.

v0.1.3

Toggle v0.1.3's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
fix: renderer crash fix, option-parsing refactor, CI, and docs (#7)

* refactor: centralize plugin option parsing in a single schema

Replace the scattered per-field typeof/Number.isInteger option guards with one OptionsSchema in src/options.ts and a parseOptions() reader; task.ts, intake.ts, and validator.ts derive option values from it. Defaults and accept/reject behavior are unchanged. The complex commands/validatorModels readers are left as-is (they transform rather than validate).

* ci: cancel superseded check runs and add workflow linting

Add a cancel-in-progress concurrency guard to check.yml so a newer push supersedes an in-flight run, and add a path-filtered lint-workflows.yml that runs actionlint (SHA-pinned) on workflow changes.

* docs: add CONTRIBUTING guide

A short, plain-language starting point: prerequisites, local setup and dev-install, the bun run check gate, conventional-commit/PR conventions, and pointers to AGENTS.md and .specs.

* fix: route renderer, keyboard, and keymap through TuiPluginApi

The npm-installed plugin bundles its own @opentui/solid and
@opentui/keymap/solid copies, whose Solid context the host never
populates. useTerminalDimensions/useKeyboard/useBindings therefore
threw "No renderer found" / "Keymap not found" on install (the Ubuntu
crash). Route all renderer dimensions, keyboard input, and keymap
registration through the host-provided TuiPluginApi instead — the one
object identical across module copies.

- board keys: api.keymap.registerLayer(mode "base"), matching tui.tsx
- dialog keys: api.keymap.intercept via useKeyIntercept
- dimensions: useRendererDimensions over api.renderer resize events
- reactivity-guard test fails the build if a context hook reappears
- create-task: let Enter reach the description textarea as a newline
  (ctrl+enter still submits) instead of consuming it

v0.1.2

Toggle v0.1.2's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
fix: use npm trusted publishing (#3)

v0.1.1

Toggle v0.1.1's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
fix: limit check workflow push trigger (#2)