diff --git a/README.md b/README.md index 7e0dcde4d..5672dadda 100644 --- a/README.md +++ b/README.md @@ -144,7 +144,7 @@ OMC exposes two different surfaces: | Feature | Terminal CLI | In-session skill | Notes | | ---------------------------------------------- | --------------------------------------------- | ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | | Setup | `omc setup` | `/omc-setup` | Both are real entrypoints. | -| Ask providers | `omc ask codex "review this patch"` | `/ask codex "review this patch"` | Both route through the same advisor flow. Providers: `claude`, `codex`, `gemini`, `antigravity`, `grok`, `cursor`. | +| Ask providers | `omc ask codex "review this patch"` | `/ask codex "review this patch"` | Both route through the same advisor flow. Providers: `claude`, `codex`, `gemini`, `antigravity`, `grok`, `cursor`, `muse`. | | Team orchestration | `omc team 2:codex "review auth flow"` | `/team 3:executor "fix all TypeScript errors"` | Both exist, but they are different runtimes: `omc team` launches tmux CLI workers; `/team` runs the in-session native team workflow. | | Pre-flight danger scan | `omc lookout scan --brief "..." [--json] [--strict]` | — | Advisory only: scans the task briefing and workspace before an unattended run and reports danger findings (findings/severity contract). Exit codes: 0 for successful non-strict scans (and strict scans without high-risk signals), 1 `--strict` with high-risk signals, 2 usage/scan error. | | Autopilot / Ralph / Execute / Deep Interview | — | `/autopilot ...`, `/ralph ...`, `/execute ...`, `/deep-interview ...` | These are in-session skills. There is no `omc autopilot` / `omc ralph` / `omc execute` CLI subcommand in this repo. | @@ -427,6 +427,7 @@ omc ask gemini --prompt "propose UI polish ideas" omc ask antigravity --prompt "propose UI polish ideas" omc ask grok --prompt "cross-check this code review" omc ask cursor --prompt "apply this implementation plan" +omc ask muse --agent-prompt critic --prompt "review this plan" omc ask claude --agent-prompt executor --prompt "draft implementation steps" # Inside a Claude Code / OMC session @@ -434,6 +435,7 @@ omc ask claude --agent-prompt executor --prompt "draft implementation steps" /ask codex "identify architecture risks" /ask antigravity "propose UI polish ideas" /ask cursor "apply this implementation plan" +/ask muse --agent-prompt critic "review this plan" ``` Canonical env vars: diff --git a/src/__tests__/keyword-detector-script.test.ts b/src/__tests__/keyword-detector-script.test.ts index 09012bf7c..42e3c2ced 100644 --- a/src/__tests__/keyword-detector-script.test.ts +++ b/src/__tests__/keyword-detector-script.test.ts @@ -496,19 +496,27 @@ describe('keyword-detector.mjs mode-message dispatch', () => { } }); - it.each(['/ask muse', '/oh-my-claudecode:ask muse'])('does not activate modes from a delegated %s payload', (command) => { - const tempDir = mkdtempSync(join(tmpdir(), 'keyword-detector-ask-muse-')); - try { - const sessionId = 'ask-muse-session'; - const output = runKeywordDetector(`${command} ralplan ralph ultrawork autopilot review`, tempDir, sessionId); - expect(output.continue).toBe(true); - expect(output.suppressOutput).toBe(true); - expect(output.hookSpecificOutput).toBeUndefined(); - for (const mode of ['ralplan', 'ralph', 'ultrawork', 'autopilot']) { - expect(existsSync(join(tempDir, '.omc', 'state', 'sessions', sessionId, `${mode}-state.json`))).toBe(false); + it.each([ + '/ask muse', + '/oh-my-claudecode:ask muse', + '/ask antigravity', + '/ask agy', + '/ask cursor', + ])('does not activate modes from a delegated %s payload in both detector copies', (command) => { + for (const detectorPath of [SCRIPT_PATH, TEMPLATE_PATH]) { + const tempDir = mkdtempSync(join(tmpdir(), 'keyword-detector-ask-provider-')); + try { + const sessionId = 'ask-provider-session'; + const output = runKeywordDetector(`${command} ralplan ralph ultrawork autopilot review`, tempDir, sessionId, {}, detectorPath); + expect(output.continue).toBe(true); + expect(output.suppressOutput).toBe(true); + expect(output.hookSpecificOutput).toBeUndefined(); + for (const mode of ['ralplan', 'ralph', 'ultrawork', 'autopilot']) { + expect(existsSync(join(tempDir, '.omc', 'state', 'sessions', sessionId, `${mode}-state.json`))).toBe(false); + } + } finally { + rmSync(tempDir, { recursive: true, force: true }); } - } finally { - rmSync(tempDir, { recursive: true, force: true }); } }); diff --git a/templates/hooks/keyword-detector.mjs b/templates/hooks/keyword-detector.mjs index f52f42c44..ce15a82f7 100644 --- a/templates/hooks/keyword-detector.mjs +++ b/templates/hooks/keyword-detector.mjs @@ -145,7 +145,7 @@ function extractPrompt(input) { } function isExplicitAskSlashInvocation(prompt) { - return /^\s*\/(?:oh-my-claudecode:)?ask\s+(?:claude|codex|gemini|grok)\b/i.test(prompt); + return /^\s*\/(?:oh-my-claudecode:)?ask\s+(?:claude|codex|gemini|antigravity|agy|grok|cursor|muse)\b/i.test(prompt); } function isRetiredSlashInvocation(prompt) {