The previous commits in this branch inadvertently dropped the prominent
ROADMAP-refactor-in-progress warning from AGENTS.md. That change is
unrelated to fixing the team_send_message ambiguous delivery loss and
should not ride along with this PR.
This commit restores the banner verbatim from the dev branch tip.
Reduce the ralph loop continuation prompt from ~15 lines to ~3 lines:
- Keep system directive prefix for proper identification
- Keep the essential 'output <promise>DONE</promise>' instruction
- Keep the original task prompt (needed context)
- Remove verbose boilerplate about reviewing progress and not stopping
When both default_mode.ultrawork and default_mode.ralph_loop are true,
the ralph loop handles ultrawork behavior via its continuation mechanism
(prepends 'ultrawork' to each iteration prompt). Injecting the ultrawork
system prompt on top would be redundant — the continuation prompt
re-triggers keyword detection, which defeats the purpose of invisible
system prompt injection.
The ultrawork flag still controls loop behavior (500 max iterations +
Oracle verification gate) via chat-message.ts startLoop({ ultrawork }).
When default_mode.ultrawork is enabled, inject the ultrawork behavioral
instructions into the system prompt (experimental.chat.system.transform)
instead of prepending them to the user's visible chat message.
- system-transform.ts: No-op handler now injects ultrawork message into
output.system[] when defaultMode.ultrawork is active. Checks for existing
<ultrawork-mode> tag to avoid re-injection after compaction.
- keyword-detector/hook.ts: Removes the visible text injection
(output.parts[].text prepend) for default_mode.ultrawork path. Only
shows the toast as the user-facing indicator.
- plugin-interface.ts: Wires getUltraworkMessage from keyword-detector
into createSystemTransformHandler.
Result: Ultrawork mode activates silently via system prompt — the chat
stays clean, and only a toast shows 'Ultrawork Mode Active'.
Add new `default_mode` config section with two boolean fields:
- `ultrawork`: Auto-inject ultrawork mode prompt on main session start
without requiring the "ultrawork"/"ulw" keyword. Wired through the
keyword-detector hook — injects once per session, respects existing
guards (non-OMO agents, planner agents, subagent sessions).
- `ralph_loop`: Auto-start ralph loop on first main session message
without requiring /ralph-loop or /ulw-loop commands. When ultrawork
is also enabled, the loop starts in ultrawork mode.
Usage:
```jsonc
{
"default_mode": {
"ultrawork": true, // Always get ultrawork prompt on start
"ralph_loop": true // Auto-start ralph loop
}
}
```
Files: 7 modified/added, ~65 LOC added.
Also fix CI test isolation: run each test file in its own bun process to prevent
mock.module() leaks across files that were introduced by upstream commit 6acca09b.
Grok model IDs (e.g. `grok-4.3`, `grok-3-mini`) were missing from `HEURISTIC_MODEL_FAMILY_REGISTRY`, so `resolveCompatibleModelSettings` returned an "unknown family" result for them.
The `chat.params` hook treats unknown families as "no reasoning support" and deletes `output.options.reasoningEffort` before the request leaves the plugin, so users routing Grok via OpenAI-compatible endpoints never saw their reasoning effort forwarded — even with `forceReasoning: true`.
Add a `grok` family entry that includes any model ID containing "grok", exposes `low | medium | high` variants, and sets `reasoningEfforts` so the heuristic surfaces the same capability flag used by the `chat.params` hook. Extend the family table-driven test in `model-settings-compatibility.test.ts` to cover `grok-4.3`.
Two blockers from the maintainer's Oracle review on PR #4121:
Blocker 1 — load_skills=null should still throw, omitted should default
The previous PR collapsed both `loadSkills === undefined` and
`loadSkills === null` into a silent default of `[]`. The closing
rationale of PR #1663 (which reverted PR #1493) and the maintainer's
review both call out the importance of preserving the distinct
"omitted -> default, explicit invalid -> throw" contract. `null`
strongly signals "I tried to pass something and it was wrong";
silently coercing it hides bugs upstream.
Restored the split: `undefined` -> default `[]` + log,
`null` -> throw with the historical error string.
Blocker 2 — task_id continuation test rewritten, not deleted
The original PR removed the `task_id without run_in_background ->
throws` test entirely. The behavior IS preserved (default false ->
`isExplicitSyncRun` true -> `executeSyncContinuation`), but with the
test gone the new contract was unprotected.
Added a regression test that asserts the new contract: when
`task_id` is present and `run_in_background` is omitted,
`tool.execute` must route through sync continuation without throwing
the legacy required-parameter error. Mocks include `session.abort`
because the sync poller calls it during shutdown.
Also flipped the existing `load_skills=null` regression test from
"normalizes to []" back to "throws with the legacy error string" to
match the restored contract.
Tests:
- bun test src/tools/delegate-task/tools.test.ts -> 132/132 pass
- bun test src/tools/delegate-task/ -> 406/406 pass
- bun run typecheck -> clean
Sisyphus and other delegators occasionally invoke the task() tool without
an explicit run_in_background or load_skills argument. The runtime
validators in tool-argument-preparation.ts threw a hard Error in that
case, which short-circuited tool.execute() entirely. Because OpenCode's
tool.execute.after hook only runs on returned results, the
delegate-task-retry hook never had a chance to attach corrective
guidance — so the model saw a raw failure and either burned several
retries or fell back to a synchronous Explore call, silently losing
parallel execution.
Behavior change:
- run_in_background omitted -> defaults to false (sync delegation), with
a log entry for observability.
- load_skills omitted or null -> normalized to [] with a log entry on
the explicit-null path.
- The Zod schema entries are now .optional() and their .describe()
strings declare the defaults honestly; the markdown tool description
was updated to match (no more 'REQUIRED' lie).
The orthogonal validation 'Must provide either category or
subagent_type.' is unchanged and still surfaces as a returned error.
Tests:
- The five throw-on-missing tests in tools.test.ts are rewritten to
assert the new default-and-proceed contract.
- The 'no category, no subagent_type' test now asserts the
missing-target error remains intact.
Refs the workaround the reporter validated in the original issue body;
matches the design from PR #2375 which was previously reverted by
566031f4.
Add a `Docs` badge next to `Ask DeepWiki` in each README so users can
discover the hosted documentation site directly from the project front
page. Same line added to README.md, README.ko.md, README.ja.md, and
README.zh-cn.md so the language switcher stays visually consistent.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Add src/locales/ with en baseline and zh overrides (Partial<Record> fallback)
- Add src/shared/i18n.ts with initI18n/t/setLocale/getLocale (LANG env auto-detect)
- Add I18nConfigSchema with locale field to plugin config
- Internationalize 13 hardcoded strings in task-toast-manager
- Add 18 unit tests for i18n module
- Pin manager tests to en locale for determinism
When all plugin hooks are removed (user disables/uninstalls plugins),
hooksConfigs becomes an empty array. The previous guard
(hooksConfigs.length > 0) skipped setPluginHooksConfigs(), leaving
stale plugin hooks active in pendingPluginHooksConfigs. Now we always
call setPluginHooksConfigs() so empty configs properly clear the
pending state and invalidate the cache.
Previously, loadPluginHooksConfigs() loaded plugin hooks from marketplace
plugins (hookify, superpowers, zzcommon, zzfe, etc.) into
pluginComponents.hooksConfigs, but config-handler.ts never consumed them.
This meant plugin hooks were discovered but never merged into the runtime
hooks dispatch system.
Changes:
- Extend ClaudeHookEvent and ClaudeHooksConfig to support all 12 event
types (PostToolUseFailure, PermissionRequest, Notification,
SubagentStart, SubagentStop, SessionStart, SessionEnd) in addition to
the existing 5
- Add ALL_HOOK_EVENT_TYPES constant as single source of truth for event
type iteration
- Add mergePluginHooksConfigs() to unwrap plugin HooksConfig (with hooks
wrapper) into flat ClaudeHooksConfig, filtering out unsupported
prompt/agent hook types
- Add setPluginHooksConfigs() to store pending plugin configs and
invalidate the config cache
- Create applyHookConfig() handler following existing applyXxxConfig
pattern, wired into config-handler after loadPluginComponents()
- Extend DisabledHooksConfig and mergeDisabledHooks for all 12 events
Closes#4179