Commit Graph

1637 Commits

Author SHA1 Message Date
YeonGyu-Kim 9c19bd8c51 fix(ralph-loop): defer during fresh user prompts
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 16:05:36 +09:00
YeonGyu-Kim bcbab0555d fix(todo-continuation-enforcer): preserve countdown across compaction
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 15:59:16 +09:00
YeonGyu-Kim f898116be1 test(todo-continuation-enforcer): lock compaction countdown state
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 15:51:53 +09:00
YeonGyu-Kim f20294a702 fix(unstable-agent-babysitter): normalize reminder agent names
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 15:48:43 +09:00
YeonGyu-Kim 0ee45aa6ab fix(unstable-agent-babysitter): respect active sessions
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 15:48:43 +09:00
YeonGyu-Kim 3b54d587bf Merge pull request #4132 from code-yeongyu/fix/3446-atlas-runaway-loop
fix(atlas): stop runaway boulder continuation loops
2026-05-18 14:43:03 +09:00
YeonGyu-Kim 6dc31b2c4f fix(atlas): scope no-tool-progress counter to active plan path before stall
Oracle review on PR #4132 flagged that resetStallStateForPlanChange only
reset state when stalledContinuationReason was already set, so partial
in-progress counts from plan A could carry to plan B and abort the new
plan on its first idle.

Adds activeContinuationPlanPath to SessionState and resets the
no-tool-progress counter + awaiting state whenever the active plan path
changes, even when no stall has occurred yet. The existing stalled-plan
reset still fires when the previously stalled plan path differs from
the new one.
2026-05-18 14:34:00 +09:00
YeonGyu-Kim 428a18c748 test(prompt-gate): tighten dispatch route regressions 2026-05-18 14:22:58 +09:00
YeonGyu-Kim e1554c088e fix(ralph-loop): preserve prompt dispatch holds through activity 2026-05-18 14:22:58 +09:00
YeonGyu-Kim 66cb72b831 fix(prompt-gate): bind session messages receiver 2026-05-18 14:22:58 +09:00
YeonGyu-Kim 1a66b96bb8 docs: note Atlas stalled continuation fix
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 14:18:33 +09:00
YeonGyu-Kim d3b4c022d2 fix(atlas): stop stalled boulder continuations
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 14:17:54 +09:00
YeonGyu-Kim fff99aeb29 fix(atlas): track no-tool-progress state
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 14:17:54 +09:00
YeonGyu-Kim 0994c107d2 fix(atlas): require blocked plan checkbox edits
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 14:17:54 +09:00
YeonGyu-Kim b0f432dbe5 Merge pull request #4136 from code-yeongyu/fix/4059-blocker4-reland
fix(runtime-fallback): reland BLOCKER-4 delegated empty-history fallback (#4059)
2026-05-18 13:50:03 +09:00
YeonGyu-Kim c37725bb7f Merge pull request #4139 from code-yeongyu/fix/3450-anthropic-context-limit-revisited
fix(shared): return GA 1M context limit for Anthropic 4.6/4.7 models without cached entry
2026-05-18 13:44:56 +09:00
YeonGyu-Kim 0f8fc548f1 fix(runtime-fallback): consume delegated bootstrap retry payload
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 13:42:57 +09:00
YeonGyu-Kim 2387f1e702 Merge pull request #4134 from code-yeongyu/ulw/rule-comment-baseline-20260518
Optimize rules injector caches
2026-05-18 13:37:09 +09:00
YeonGyu-Kim 35df911919 test(hooks): update preemptive-compaction token thresholds for GA 1M context
Raise test token counts from 170K/180K to 800K/810K so compaction triggers at 78% of 1M instead of 78% of 200K, matching the actual GA context limit for 4.6 models.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 13:36:17 +09:00
YeonGyu-Kim 50ae2e110e perf(rules-injector): cache match decisions
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 13:30:23 +09:00
YeonGyu-Kim 5555dbfc67 Merge pull request #4133 from code-yeongyu/fix/3816-frozen-output-args
fix: replace direct output.args mutation with replaceToolArgs helper (fixes #3816)
2026-05-18 13:09:30 +09:00
YeonGyu-Kim b20e2c9c55 fix: refactor 5 additional aliased output.args mutations + strengthen audit test
Address Oracle review feedback: refactor 4 aliased mutations via argsObject
in plugin/tool-execute-before.ts and 1 via toolOutput in atlas/tool-execute-before.ts.
Strengthen audit test regex to catch Output.args mutations regardless of the
variable name prefix (toolOutput, argsObject aliases).

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 13:04:10 +09:00
YeonGyu-Kim 61890f0857 fix(rules-injector): bound parsed rule cache
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 12:58:41 +09:00
YeonGyu-Kim 46b965b9da fix(rules-injector): bound matcher cache
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 12:58:41 +09:00
YeonGyu-Kim 1ab1b54ce6 perf(rules-injector): cache compiled glob matchers
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 12:58:41 +09:00
YeonGyu-Kim 3a63a8b205 test(shared): add audit test forbidding direct output.args mutation + fix 9th site
Add replace-tool-args.audit.test.ts that scans src/**/*.ts for direct
output.args property assignments and Object.assign(output.args, ...) outside
the helper. Also fix the 9th mutation site discovered by the audit in
compaction-todo-preserver/hook.ts.

Add replace-tool-args.test.ts with 12 regression tests covering both mutable
and Object.freeze'd output.args scenarios for all hook patterns.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 12:46:52 +09:00
YeonGyu-Kim 13d8857415 refactor(hooks): replace direct output.args mutation with replaceToolArgs (question/webfetch/null-byte)
Replace Object.assign(output.args, truncatedArgs), output.args.url = resolution.url,
and output.args.command = ... .replace(/\x00/g, "") with replaceToolArgs() calls
in question-label-truncator, webfetch-redirect-guard, and plugin/tool-execute-before.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 12:46:52 +09:00
YeonGyu-Kim af66b8de0b refactor(hooks): replace direct output.args mutation with replaceToolArgs (env + prompt injectors)
Replace output.args.command and output.args.prompt direct assignments
with replaceToolArgs() in non-interactive-env, prometheus-md-only,
and sisyphus-junior-notepad hooks.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 12:37:45 +09:00
YeonGyu-Kim 63a3021094 test(anthropic-effort): cover pre-set effort=max clamping for constrained providers (#3563)
Add 4 regression tests covering the pre-set effort path:

- pre-set effort=max + variant=max + github-copilot Opus -> clamped to high

- pre-set effort=max + variant=high + github-copilot Opus -> clamped to high (cubic violation case from PR #3608)

- pre-set effort=max + non-constrained Opus -> max preserved (no regression)

- pre-set effort=high + github-copilot Opus -> high preserved (don't overwrite valid pre-set)

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 12:36:56 +09:00
YeonGyu-Kim 96767b5d1a fix(anthropic-effort): clamp pre-set effort=max for constrained providers regardless of variant
Move the pre-set effort handling BEFORE the message.variant !== "max" early-return so that output.options.effort="max" set via session params or model-requirements fallback chains is always clamped to "high" on constrained providers (github-copilot, Anthropic OAuth), even when message.variant is not "max".

This addresses the cubic violation from PR #3608 where the clamp block was gated behind the variant-based return.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 12:36:45 +09:00
YeonGyu-Kim f72bb3fe8f refactor(hooks): replace direct output.args mutation with replaceToolArgs (claude-code-hooks)
Replace output.args.todos = parsed and Object.assign(output.args, result.modifiedInput)
with replaceToolArgs() calls that create a shallow clone instead of
mutating the potentially-frozen args object.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 12:33:32 +09:00
YeonGyu-Kim 34e6af1ae6 docs: update AGENTS guidance 2026-05-18 11:49:56 +09:00
YeonGyu-Kim 397ed1048a fix(hooks): guard session-notification against missing ctx.$ (refs #3997) 2026-05-18 10:47:27 +09:00
ZeyuFu a8ccffdd7c style(runtime-fallback): add explicit optional chain on .replace per review
Addresses cubic-dev-ai P1 finding on #4113 (#4113 review).

The original chain `extractErrorName(error)?.toLowerCase().replace(...)`
is semantically safe — JavaScript optional chaining short-circuits the
ENTIRE access chain when the head returns null/undefined, so when
`extractErrorName` returns undefined the whole expression evaluates to
undefined without ever reaching `.replace()`. Verified empirically via
`const x = undefined; x?.toLowerCase().replace(/_/g, "")` returns
undefined with no crash.

Applying the suggested defensive `?.` before `.replace` anyway, since
it is semantically a no-op and explicit chaining at each hop is easier
for static analyzers to reason about.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 11:05:01 -04:00
ZeyuFu 2bd7946001 fix(non-interactive-env): use powershell syntax on Windows regardless of SHELL/MSYSTEM
Closes #3607.

## Root cause

On Windows, `detectCommandShellType()` fell through to `detectShellType()`
for two common environments and incorrectly returned `"unix"`:

1. **SHELL points at a Unix-shaped path** (e.g. Git Bash sets
   `SHELL=/usr/bin/bash` on a fresh Windows install).
   The `detectWindowsShellType(process.env.SHELL)` probe didn't recognize
   `bash` as a Windows shell, so the function fell through and
   `detectShellType()` returned `"unix"`.

2. **MSYSTEM is set but SHELL is not** (Git Bash leaves MSYSTEM permanently
   set system-wide even when the active shell is PowerShell).
   The fall-through path returned `"unix"` via the MSYSTEM check.

In both cases, the hook then prepended `export KEY=val;` to git commands,
which PowerShell rejects with:

  `export : 无法将"export"项识别为 cmdlet...`

OpenCode on Windows runs the bash tool through a Windows shell
(PowerShell by default, cmd as the user-overridable fallback), regardless
of MSYSTEM or a Unix-shaped SHELL set by Git Bash — so the env prefix
must use Windows-compatible syntax.

## Fix

`detectCommandShellType()` now short-circuits on `process.platform === "win32"`:

- If `SHELL` points at a recognized Windows shell (`cmd.exe`, `powershell.exe`,
  `pwsh.exe`), return that.
- If `SHELL` and `MSYSTEM` are both unset, fall back to `ComSpec` then to cmd.
- Otherwise, default to PowerShell — matching what OpenCode actually spawns.

`detectShellType()` is unchanged; other callers (including non-Windows
platforms) are unaffected.

## Test changes

Three pre-existing tests encoded the buggy behavior as expected behavior
and have been updated to assert the new PowerShell syntax with a
`(#3607)` marker and a comment explaining why a Unix-shaped SHELL on
win32 must still resolve to PowerShell. WSL is not affected because in
WSL `process.platform === "linux"`, not `"win32"`.

- `src/hooks/non-interactive-env/`: 24 tests pass / 0 fail
- `bunx tsc --noEmit`: clean

## Note on issue thread

The sisyphus-bot triage comment on #3607 framed this as a policy choice
between (A) forcing Windows env-prefix syntax and (B) resolving against
the OpenCode-configured shell. This PR implements option (A) as the
minimal surgical fix; option (B) remains a follow-up.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 10:59:29 -04:00
ZeyuFu b2f0d42394 test(runtime-fallback): tighten quota regression fixtures so new paths actually fire
Addresses cubic-dev-ai bot review on #4113 (P2): the RESOURCE_EXHAUSTED
and snake_case insufficient_quota fixtures contained quota-shaped
messages that already matched pre-existing message regexes, so the tests
passed even without the new errorName allow-list entry and the
underscore normalization respectively.

Replace both fixture messages with a generic "Request failed." so the
only path to a `quota_exceeded` classification is via the new code:

- RESOURCE_EXHAUSTED: only the new `errorName?.includes("resourceexhausted")`
  match on the normalized name can fire.
- insufficient_quota (snake_case): only the new underscore-stripping
  normalization can route the name to `insufficientquota` and match the
  existing allow-list entry.

The third new test (Google ResourceExhausted message-only) is unchanged
because its message uniquely matches only the new
`/resource.?exhausted/i` pattern and not any existing quota regex.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 10:37:40 -04:00
ZeyuFu f357ed033a fix(runtime-fallback): classify more provider quota error names
Closes #3937.

Adds three small classification gaps to `classifyErrorType` so that
quota-exhaustion errors from a wider range of providers trigger
configured fallback chains instead of looping retry attempts:

- Normalize error names by stripping `_` and `-` so snake_case /
  SCREAMING_SNAKE_CASE provider names (`insufficient_quota`,
  `RESOURCE_EXHAUSTED`, `rate_limit_exceeded`) match the existing
  alphanumeric `.includes()` checks.
- Add `resourceexhausted` to the quota error-name allow-list to cover
  Google Generative AI's gRPC code 8 / `ResourceExhausted` surface.
- Add `/resource.?exhausted/i` to the quota message-pattern list so the
  same error surface is caught when the provider only sets a generic
  error name but puts the signal in the message.

Three new regression tests in
`quota-error-classifier.regression.test.ts` cover:

- Google `RESOURCE_EXHAUSTED` (gRPC error name + quota-shaped message)
- Google `ResourceExhausted` message form without HTTP status
- OpenAI snake_case `insufficient_quota` error name

No existing tests were touched; the underscore normalization preserves
all existing `.includes()` matches by rewriting the one underscore-bearing
literal (`ai_loadapikeyerror` → `ailoadapikeyerror`) so previously
matched names still resolve.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 10:28:05 -04:00
ZeyuFu 6c54123ec1 fix(slash-commands): inject command content exactly once (#3724)
Guard command.execute.before against injecting when parts already
contain auto-slash-command tags, preventing duplication when both
chat.message and command.execute.before fire for the same slash command.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 07:07:49 -04:00
deopa0402 9758168676 test(auto-update): isolate cached version resolution
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-17 18:36:42 +09:00
deopa0402 37d9d613b6 fix(auto-update): clean stale OMO cache roots
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-17 18:35:29 +09:00
YeonGyu-Kim 6768decddb fix(session-recovery): fallback when stored unavailable-tool parts are absent
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-17 17:16:10 +09:00
YeonGyu-Kim 12bd658079 refactor(prompt-async-gate): remove deprecated dispatch wrappers
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-17 17:15:54 +09:00
YeonGyu-Kim 1bbe065c60 refactor(prompt-callers): migrate shared and cli dispatch
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-17 17:09:04 +09:00
YeonGyu-Kim 989ab7171d refactor(hooks): use unified internal prompt dispatch
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-17 17:07:35 +09:00
YeonGyu-Kim b5d24619c8 test(prompt-async-gate): pin unified internal prompt dispatch contract
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-17 16:34:05 +09:00
YeonGyu-Kim 8bc4977563 fix(slash-command): skip already tagged command output 2026-05-17 16:17:42 +09:00
YeonGyu-Kim 55312cc4b6 fix(session-recovery): preflight idle recovery fanout 2026-05-17 16:17:36 +09:00
YeonGyu-Kim a7b7ace7ed fix(prompt-gate): block prompts into pending tool turns 2026-05-17 15:42:58 +09:00
YeonGyu-Kim 6eb88a0545 fix(session-recovery): prefer valid tool use ids 2026-05-17 15:15:13 +09:00
YeonGyu-Kim f43effb842 fix(session-recovery): recover interrupted idle tool turns 2026-05-17 15:08:39 +09:00