Skip to content

fix: npm keyboard, Enter submit, and duplicate helper spawn - #11

Merged
aorumbayev merged 5 commits into
mainfrom
fix/npm-keyboard-intake-and-ctrlenter
Jul 9, 2026
Merged

fix: npm keyboard, Enter submit, and duplicate helper spawn#11
aorumbayev merged 5 commits into
mainfrom
fix/npm-keyboard-intake-and-ctrlenter

Conversation

@aorumbayev

Copy link
Copy Markdown
Member

Summary

Three independent bugs surfaced when kagan is installed from npm (vs. the local dev snapshot), plus their fixes:

  • Dead keyboard on npm installs. OpenCode's Solid compile transform skips any path under node_modules, so publishing raw src/*.tsx meant the plugin's components were never Solid-compiled — no onMount ran, so no key handlers registered. Now we pre-compile srcdist per-file with OpenTUI's own transformSolidSource (scripts/build.ts), keeping @opentui/* and solid-js as external bare imports the host provides. Publish dist instead of src, move those runtime libs to optional peerDependencies, and add a prepack hook so npm pack/publish always builds first.
  • Ctrl+Enter never created a task. Most terminals send bare CR for both Enter and Ctrl+Enter, so the modifier never arrives. Plain Enter now submits the create-task dialog from every field; Ctrl+J inserts a newline in the description.
  • Two intake/validator agents spawned per task (Ubuntu). A duplicate plugin load in a task worktree gave each module copy its own in-memory guard, so concurrent session.updated events could both spawn a helper. Share helperEntryClaims and sessionLocks on globalThis, and claim the spawn ({role}Outcome: "pending") inside the serialized metadata lock before creating the child. A failed spawn clears the claim so retries still work. Applied to both the intake and validator paths.

Test plan

  • bun run check — prettier, oxlint, tsc, 641 tests pass, build, package:check
  • dist/ is Solid-compiled (no raw JSX; @opentui/*/solid-js external), no bundled host deps in the packed tarball
  • Manual runtime smoke test: npm pack → install under node_modules/@kagan-sh/kagan with host peers → open the board and confirm arrows/Tab/Enter work
  • Create a task: Enter submits from the description; Ctrl+J inserts a newline
  • New task on Ubuntu: exactly one intake agent spawns

Notes / follow-ups

  • scripts/build.ts imports OpenTUI's non-exported scripts/solid-transform.js — works today, brittle across OpenTUI upgrades.
  • Dev pins are @opentui 0.4.2 while the peer floor is >=0.4.3; AGENTS.md may still say "never pre-transform" — doc/version follow-ups.

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.
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.
@greptile-apps

greptile-apps Bot commented Jul 9, 2026

Copy link
Copy Markdown

Greptile Summary

This PR fixes npm packaging, create-task keyboard input, and duplicate helper spawning. The main changes are:

  • Publishes precompiled dist entrypoints instead of raw src files.
  • Adds build and package checks for Solid compilation and host peer dependencies.
  • Changes the create-task dialog so Enter submits and Ctrl+J inserts a newline.
  • Shares helper spawn locks and claims across duplicate plugin module loads.

Confidence Score: 4/5

This change is close, but the npm peer range can produce a broken supported install.

The helper-spawn and keyboard changes are covered by focused tests. The packaging change has one current runtime contract issue: the compiled output relies on OpenTUI runtime-plugin support while package.json accepts older peers.

package.json

T-Rex T-Rex Logs

What T-Rex did

  • T-Rex ran the requested verification, but its local artifact references were not uploaded.
  • Post-run verification showed a successful build and package-check with exit code 0.
  • The focused create-task keyboard test file passed completely, with 11 passes and 0 failures.
  • The npm-pack inspection confirmed a successful pack and tarball contents limited to dist JS/package files, with the tarball artifact generated.
  • OpenCode host availability log documents a blocker for the full compatible host smoke due to host version availability.

View all artifacts

T-Rex Ran code and verified through T-Rex

Important Files Changed

Filename Overview
package.json Switches published entrypoints to prebuilt dist and peers OpenTUI/Solid; peer floors are too low for the new precompiled runtime-plugin output.
scripts/build.ts Adds per-file Babel/Solid build to dist with OpenTUI/Solid host runtime import rewrites.
scripts/package-check.ts Expands package validation to build dist, check compiled Solid output, install with host peers, and ensure host deps are not bundled.
src/create-task.tsx Changes create-task keyboard behavior so Enter submits and Ctrl+J/linefeed/Shift+Return insert description newlines.
src/server.ts Shares in-memory helper entry claims across module copies and claims helper spawns inside serialized metadata updates.
src/session-api.ts Moves session locks to globalThis and adds atomic helper-spawn claiming via patchKaganWhen.

Fix All in Claude Code Fix All in Codex

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
package.json:69-72
**Raise peer floors**
The published package now ships precompiled `dist` output that rewrites OpenTUI/Solid imports through the runtime-plugin module IDs, but these peer ranges still allow hosts with `@opentui/*@0.3.4`. The runtime-plugin exports and JSX runtime support used by the compiled output are a `0.4.x` API surface, so npm can install this plugin into a supported peer set that then fails to load at runtime; set the OpenTUI peer floors to the version you build and package-check against.

Reviews (2): Last reviewed commit: "fix: support packed production plugin in..." | Re-trigger Greptile

Comment thread src/server.ts Outdated
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.
@socket-security

socket-security Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updated@​opentui/​keymap@​0.4.2 ⏵ 0.4.37810010097 -1100
Updated@​opentui/​core@​0.4.2 ⏵ 0.4.385 -1310092 +198100
Updatedsolid-js@​1.9.13 ⏵ 1.9.1010010010095 +1100
Updated@​opentui/​solid@​0.4.2 ⏵ 0.4.397100100 +197 -1100

View full report

@aorumbayev

Copy link
Copy Markdown
Member Author

@greptileai

Comment thread package.json Outdated
Comment on lines +69 to +72
"@opentui/core": ">=0.3.4",
"@opentui/keymap": ">=0.3.4",
"@opentui/solid": ">=0.3.4",
"solid-js": ">=1.9.10"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Raise peer floors
The published package now ships precompiled dist output that rewrites OpenTUI/Solid imports through the runtime-plugin module IDs, but these peer ranges still allow hosts with @opentui/*@0.3.4. The runtime-plugin exports and JSX runtime support used by the compiled output are a 0.4.x API surface, so npm can install this plugin into a supported peer set that then fails to load at runtime; set the OpenTUI peer floors to the version you build and package-check against.

T-Rex Ran code and verified through T-Rex

Prompt To Fix With AI
This is a comment left during a code review.
Path: package.json
Line: 69-72

Comment:
**Raise peer floors**
The published package now ships precompiled `dist` output that rewrites OpenTUI/Solid imports through the runtime-plugin module IDs, but these peer ranges still allow hosts with `@opentui/*@0.3.4`. The runtime-plugin exports and JSX runtime support used by the compiled output are a `0.4.x` API surface, so npm can install this plugin into a supported peer set that then fails to load at runtime; set the OpenTUI peer floors to the version you build and package-check against.

How can I resolve this? If you propose a fix, please make it concise.

Fix in Claude Code Fix in Codex

@aorumbayev
aorumbayev merged commit 2cf62cf into main Jul 9, 2026
3 checks passed
@aorumbayev
aorumbayev deleted the fix/npm-keyboard-intake-and-ctrlenter branch July 9, 2026 08:26
@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown

🎉 This PR is included in version 0.2.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant