Skip to content

Feat/caveman response style#1920

Closed
zgriffiin wants to merge 20 commits intopingdotgg:mainfrom
zgriffiin:feat/caveman-response-style
Closed

Feat/caveman response style#1920
zgriffiin wants to merge 20 commits intopingdotgg:mainfrom
zgriffiin:feat/caveman-response-style

Conversation

@zgriffiin
Copy link
Copy Markdown

@zgriffiin zgriffiin commented Apr 11, 2026

What Changed

Why

UI Changes

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Note

High Risk
High risk because it changes core orchestration/session lifecycle handling and adds new commit/push gating that can block developer workflows if misconfigured. It also alters process spawning behavior (disables shell) and introduces new CLI-based provider adapters, increasing cross-platform/runtime surface area.

Overview
Adds workflow guardrails across commits, pushes, and agent turns. Git actions can now require per-change proof (Intent + functional validation commands), run those validation commands during commit, append proof to commit bodies, and block push/PR creation when outgoing commits are missing required proof.

Integrates a post-turn quality gate into provider runtime ingestion: turns with file changes trigger evaluation, record pass/fail activities, set the thread session to error on failure, and automatically prepend the failure detail to the next user prompt until a passing gate is recorded.

Improves reliability and UX of long-running sessions by treating turn.aborted as terminal, reconciling stale activeTurnId/latest turn state when sessions settle, and rejecting thread.turn.start while a turn is already running.

Expands provider/editor tooling: adds CLI-based adapters and health checks for Kiro and Amazon Q (including WSL execution and Amazon Q IAM Identity Center auth detection), adds Kiro to editor launch detection, and updates documentation/Beans metadata (new .beans config + bean files, README refresh).

Reviewed by Cursor Bugbot for commit ed3d320. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Add Kiro and Amazon Q provider support with quality guardrails, Beans UI, and Caveman response style

  • Adds Kiro and Amazon Q as supported AI providers throughout the stack: ProviderKind schema, model selection, settings UI, adapter layers, provider registry, and editor/picker integration
  • Introduces CliAgentAdapter and CliAgentProvider implementations that invoke kiro and q binaries via CLI (host or WSL mode) to handle turns and detect install/auth readiness
  • Adds a QualityGate service that evaluates file-changing turns against configurable rules (format, lint, typecheck, file/function length, cyclomatic complexity); failures are surfaced as QUALITY_GATE_FAILED activities and block the session with a lastError
  • Introduces a Caveman response style (responseStyle: off/lite/full/ultra) that prepends style instructions to turn inputs and developer instructions before routing to providers
  • Adds a Beans management UI (BeansControl) backed by new RPC endpoints and React Query hooks for browsing, creating, editing, and tracking project beans
  • Adds commit quality gates: intent and functional validation commands can be required by settings, enforced at commit and push/PR time via GitManager, with proof appended to commit messages and parsed on push
  • Extends the diff panel with a conversation-wide diff scope mode and fixes latestTurn finalization when a running session settles
  • Risk: processRunner now spawns with shell: false on all platforms including Windows, changing process invocation behavior
📊 Macroscope summarized ed3d320. 59 files reviewed, 8 issues evaluated, 2 issues filtered, 4 comments posted

🗂️ Filtered Issues

apps/server/src/provider/Layers/CliAgentAdapterRuntime.ts — 0 comments posted, 1 evaluated, 1 filtered
  • line 407: In Effect.catchCause, the cause parameter is a Cause.Cause<E> from Effect, not a JavaScript Error. The toMessage(cause, ...) call will always return the fallback message because cause instanceof Error is always false for Effect's Cause type. This loses actual error information. To extract error details from a Cause, use Effect's Cause utilities like Cause.findError or inspect cause.reasons. [ Cross-file consolidated ]
packages/contracts/src/beans.ts — 0 comments posted, 1 evaluated, 1 filtered
  • line 94: BeansArchiveInput only contains cwd but lacks an id field to identify which bean to archive. Comparing to BeansUpdateInput (lines 77-85) which includes both cwd and id to target a specific bean, this schema appears incomplete. Without an identifier, the archive operation cannot target a specific bean. [ Out of scope (triage) ]

zgriffiin added 20 commits April 9, 2026 14:41
- Add Beans CLI integration and UI
- Thread quality gate failures into provider turns
- Handle aborted turns and update docs
[codex] Fix orchestration recovery and work log detail popup
Added personal acknowledgment and thanks to contributors.
[codex] Fix session completion and diff rendering performance
Add change-proof requirements to commit and push flows, surface the required intent and validation inputs in the app, and harden Bun-based quality-gate execution on Windows.

Intent: Tie significant git actions to a clear why and to functional proof before code is committed or pushed, while keeping the app quality gate able to run bun scripts reliably.

Functional Validation:
- bun fmt
- bun lint
- bun typecheck
- bun run --cwd apps/server test -- src/processRunner.test.ts
…nal-test-enforcement

[codex] Enforce intent and functional validation
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 11, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: a01cbc74-13bb-4453-9948-23ef3a08f2e9

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XXL 1,000+ changed lines (additions + deletions). labels Apr 11, 2026
@zgriffiin
Copy link
Copy Markdown
Author

Sorry, my agent wanted to publish this to the original!

@zgriffiin zgriffiin closed this Apr 11, 2026
Copy link
Copy Markdown
Contributor

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit ed3d320. Configure here.

),
Effect.forkDetach,
);
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Interrupt causes duplicate turn completion and abort events

High Severity

When interruptTurn calls Fiber.interrupt on the active turn fiber, Effect.catchCause in forkTurn catches the Interrupt cause and runs completeTurnFailure, which emits runtime.error and turn.completed(failed). After the fiber finishes, interruptTurn then emits turn.aborted and sets the session to "ready". This produces conflicting lifecycle events (turn.completed and turn.aborted) for the same turn, which the ProviderRuntimeIngestion layer processes independently, leading to inconsistent session state.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit ed3d320. Configure here.

env: options.env,
stdio: "pipe",
shell: process.platform === "win32",
shell: false,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Removing shell mode breaks Windows .cmd shim resolution

Medium Severity

Changing shell from process.platform === "win32" to false breaks Windows execution of commands distributed as .cmd shims (e.g., beans). Node.js spawn without shell: true cannot execute .cmd files on Windows. While the cli.ts build script added resolveCliBinary for its own bun/npm calls, other callers like beans/cli.ts (calling runProcess("beans", ...)) still rely on shell-based .cmd resolution.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit ed3d320. Configure here.

@zgriffiin zgriffiin deleted the feat/caveman-response-style branch April 11, 2026 05:49
@@ -226,12 +239,10 @@ const publishCmd = Command.make(

yield* Effect.log(`[cli] Running: npm ${args.join(" ")}`);
yield* runCommand(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Medium scripts/cli.ts:241

On Windows, resolveCliBinary("npm") returns a path to npm.cmd, but the shell: true option was removed in this diff. Spawning a .cmd file without shell mode fails because .cmd files are batch scripts that require cmd.exe to interpret them. The npm publish command will fail on Windows.

🤖 Copy this AI Prompt to have your agent fix this:
In file apps/server/scripts/cli.ts around line 241:

On Windows, `resolveCliBinary("npm")` returns a path to `npm.cmd`, but the `shell: true` option was removed in this diff. Spawning a `.cmd` file without shell mode fails because `.cmd` files are batch scripts that require `cmd.exe` to interpret them. The `npm publish` command will fail on Windows.

Evidence trail:
1. apps/server/scripts/cli.ts lines 37-50 (REVIEWED_COMMIT): `resolveCliBinary` function returns `npm.cmd` for npm on Windows (line 48)
2. git_diff MERGE_BASE..REVIEWED_COMMIT apps/server/scripts/cli.ts: shows removal of `shell: process.platform === "win32"` and the comment "Windows needs shell mode to resolve .cmd shims"
3. apps/server/scripts/cli.ts line 242 (REVIEWED_COMMIT): `ChildProcess.make(resolveCliBinary("npm"), [...args], {...})` without shell option
4. External evidence: GitHub issue anomalyco/opencode#18043 documents the exact same bug pattern with `.cmd` files and `spawn()` without shell option causing ENOENT on Windows

Comment on lines +78 to +80
function toMessage(cause: unknown, fallback: string): string {
return cause instanceof Error && cause.message.length > 0 ? cause.message : fallback;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Medium Layers/CliAgentAdapterOps.ts:78

result.failure from Effect.result is a Cause<E>, not an Error, so cause instanceof Error always fails and the function always returns the fallback string. Use Cause.squash or Cause.failureOrCause to extract the actual error message from the Cause structure.

-function toMessage(cause: unknown, fallback: string): string {
-  return cause instanceof Error && cause.message.length > 0 ? cause.message : fallback;
-}
Also found in 1 other location(s)

apps/server/src/provider/Layers/CliAgentAdapterRuntime.ts:407

In Effect.catchCause, the cause parameter is a Cause.Cause&lt;E&gt; from Effect, not a JavaScript Error. The toMessage(cause, ...) call will always return the fallback message because cause instanceof Error is always false for Effect's Cause type. This loses actual error information. To extract error details from a Cause, use Effect's Cause utilities like Cause.findError or inspect cause.reasons.

🤖 Copy this AI Prompt to have your agent fix this:
In file apps/server/src/provider/Layers/CliAgentAdapterOps.ts around lines 78-80:

`result.failure` from `Effect.result` is a `Cause<E>`, not an `Error`, so `cause instanceof Error` always fails and the function always returns the fallback string. Use `Cause.squash` or `Cause.failureOrCause` to extract the actual error message from the Cause structure.

Evidence trail:
apps/server/src/provider/Layers/CliAgentAdapterOps.ts lines 78-79 (toMessage function definition), lines 108-118 (Effect.result usage and result.failure passed to toMessage). Effect-ts library documentation confirms Exit.Failure.failure is of type Cause<E>, not the error E itself.

Also found in 1 other location(s):
- apps/server/src/provider/Layers/CliAgentAdapterRuntime.ts:407 -- In `Effect.catchCause`, the `cause` parameter is a `Cause.Cause<E>` from Effect, not a JavaScript `Error`. The `toMessage(cause, ...)` call will always return the fallback message because `cause instanceof Error` is always `false` for Effect's `Cause` type. This loses actual error information. To extract error details from a `Cause`, use Effect's `Cause` utilities like `Cause.findError` or inspect `cause.reasons`.

Comment on lines +250 to +260
it.effect("returns unauthenticated when the Kiro auth probe reports no session", () =>
Effect.gen(function* () {
const status = yield* checkCliAgentProviderStatus(KIRO_PROVIDER_CONFIG);
assert.strictEqual(status.provider, "kiro");
assert.strictEqual(status.status, "error");
assert.strictEqual(status.installed, true);
assert.strictEqual(status.auth.status, "unauthenticated");
assert.strictEqual(
status.message,
'Kiro is not authenticated. Run `wsl.exe --exec bash -lc "exec \\"$@\\"" bash kiro-cli login` and try again.',
);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Low Layers/CliAgentProvider.test.ts:250

The test asserts status.message equals a WSL-wrapped login command (wsl.exe --exec bash -lc ...), but ServerSettingsService.layerTest() is called without any executionMode or wslDistro settings. The actual message will be the plain kiro-cli login command instead of the WSL variant, causing the assertion to fail when the test runs.

-      assert.strictEqual(
-        status.message,
-        'Kiro is not authenticated. Run `wsl.exe --exec bash -lc "exec \\"$@\\"" bash kiro-cli login` and try again.',
-      );
+      assert.strictEqual(
+        status.message,
+        'Kiro is not authenticated. Run `kiro-cli login` and try again.',
+      );
🤖 Copy this AI Prompt to have your agent fix this:
In file apps/server/src/provider/Layers/CliAgentProvider.test.ts around lines 250-260:

The test asserts `status.message` equals a WSL-wrapped login command (`wsl.exe --exec bash -lc ...`), but `ServerSettingsService.layerTest()` is called without any `executionMode` or `wslDistro` settings. The actual message will be the plain `kiro-cli login` command instead of the WSL variant, causing the assertion to fail when the test runs.

Evidence trail:
1. apps/server/src/provider/Layers/CliAgentProvider.test.ts lines 249-270: Test uses `ServerSettingsService.layerTest()` with no overrides, expects WSL-wrapped message
2. packages/contracts/src/settings.test.ts lines 11-16: `DEFAULT_SERVER_SETTINGS.providers.kiro` has `executionMode: "auto"`
3. packages/shared/src/cliAgentCommand.ts lines 65-66: `effectiveExecutionMode = executionMode === "auto" ? (platform === "win32" ? "wsl" : "host") : executionMode`
4. packages/shared/src/cliAgentCommand.ts lines 70-77: When `effectiveExecutionMode !== "wsl"`, returns plain command
5. apps/server/src/provider/Layers/CliAgentProvider.test.ts lines 146-153: Contrast with test that explicitly sets `executionMode: "wsl"` for WSL testing

Comment on lines +239 to +248
const decoded = decodeBeansJson(
result.stdout.trim(),
BeansCreateEnvelope,
"create",
"Beans CLI returned invalid create JSON.",
);
return Schema.decodeUnknownSync(BeansCreateResult)({
bean: decoded.bean,
message: decoded.message?.trim() || "Bean created",
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Low beans/cli.ts:239

BeansCreateEnvelope decodes a success field from the CLI response, but createBean never checks it. If the CLI returns { success: false, bean: {...}, message: "error" }, the function proceeds to return decoded.bean and the error message as if the operation succeeded. Consider verifying decoded.success === true before extracting the bean, and throwing an appropriate error when the CLI reports failure.

-      const decoded = decodeBeansJson(
+      const decoded = decodeBeansJson(
         result.stdout.trim(),
         BeansCreateEnvelope,
         "create",
         "Beans CLI returned invalid create JSON.",
       );
+      if (!decoded.success) {
+        throw new BeansCommandError({
+          operation: "create",
+          detail: decoded.message?.trim() || "Bean creation failed",
+          cause: new Error(decoded.message || "Beans CLI returned success: false"),
+        });
+      }
       return Schema.decodeUnknownSync(BeansCreateResult)({
         bean: decoded.bean,
         message: decoded.message?.trim() || "Bean created",
🤖 Copy this AI Prompt to have your agent fix this:
In file apps/server/src/beans/cli.ts around lines 239-248:

`BeansCreateEnvelope` decodes a `success` field from the CLI response, but `createBean` never checks it. If the CLI returns `{ success: false, bean: {...}, message: "error" }`, the function proceeds to return `decoded.bean` and the error message as if the operation succeeded. Consider verifying `decoded.success === true` before extracting the bean, and throwing an appropriate error when the CLI reports failure.

Evidence trail:
apps/server/src/beans/cli.ts lines 26-30: `BeansCreateEnvelope` schema with `success: Schema.Boolean` field.
apps/server/src/beans/cli.ts lines 239-248: `createBean` function decodes with `BeansCreateEnvelope` but only extracts `decoded.bean` and `decoded.message`, never checking `decoded.success`.

@macroscopeapp
Copy link
Copy Markdown
Contributor

macroscopeapp Bot commented Apr 11, 2026

Approvability

Verdict: Needs human review

2 blocking correctness issues found. Diff is too large for automated approval analysis. A human reviewer should evaluate this PR.

You can customize Macroscope's approvability policy. Learn more.

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

Labels

size:XXL 1,000+ changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant