oh-my-codex 0.7.5 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.de.md +314 -0
- package/README.es.md +295 -17
- package/README.fr.md +314 -0
- package/README.it.md +314 -0
- package/README.ja.md +296 -18
- package/README.ko.md +295 -17
- package/README.md +68 -3
- package/README.pt.md +295 -17
- package/README.ru.md +295 -17
- package/README.tr.md +314 -0
- package/README.vi.md +296 -18
- package/README.zh.md +292 -17
- package/dist/catalog/__tests__/generator.test.js +2 -0
- package/dist/catalog/__tests__/generator.test.js.map +1 -1
- package/dist/catalog/__tests__/schema.test.js +7 -0
- package/dist/catalog/__tests__/schema.test.js.map +1 -1
- package/dist/cli/__tests__/ask.test.d.ts +2 -0
- package/dist/cli/__tests__/ask.test.d.ts.map +1 -0
- package/dist/cli/__tests__/ask.test.js +236 -0
- package/dist/cli/__tests__/ask.test.js.map +1 -0
- package/dist/cli/__tests__/doctor-warning-copy.test.d.ts +2 -0
- package/dist/cli/__tests__/doctor-warning-copy.test.d.ts.map +1 -0
- package/dist/cli/__tests__/doctor-warning-copy.test.js +45 -0
- package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -0
- package/dist/cli/__tests__/index.test.js +43 -1
- package/dist/cli/__tests__/index.test.js.map +1 -1
- package/dist/cli/__tests__/ralph-prd-deep-interview.test.d.ts +2 -0
- package/dist/cli/__tests__/ralph-prd-deep-interview.test.d.ts.map +1 -0
- package/dist/cli/__tests__/ralph-prd-deep-interview.test.js +15 -0
- package/dist/cli/__tests__/ralph-prd-deep-interview.test.js.map +1 -0
- package/dist/cli/__tests__/ralph.test.d.ts +2 -0
- package/dist/cli/__tests__/ralph.test.d.ts.map +1 -0
- package/dist/cli/__tests__/ralph.test.js +40 -0
- package/dist/cli/__tests__/ralph.test.js.map +1 -0
- package/dist/cli/__tests__/setup-scope.test.js +2 -0
- package/dist/cli/__tests__/setup-scope.test.js.map +1 -1
- package/dist/cli/__tests__/team-decompose.test.d.ts +2 -0
- package/dist/cli/__tests__/team-decompose.test.d.ts.map +1 -0
- package/dist/cli/__tests__/team-decompose.test.js +67 -0
- package/dist/cli/__tests__/team-decompose.test.js.map +1 -0
- package/dist/cli/__tests__/version.test.d.ts +2 -0
- package/dist/cli/__tests__/version.test.d.ts.map +1 -0
- package/dist/cli/__tests__/version.test.js +21 -0
- package/dist/cli/__tests__/version.test.js.map +1 -0
- package/dist/cli/ask.d.ts +13 -0
- package/dist/cli/ask.d.ts.map +1 -0
- package/dist/cli/ask.js +174 -0
- package/dist/cli/ask.js.map +1 -0
- package/dist/cli/constants.d.ts +10 -0
- package/dist/cli/constants.d.ts.map +1 -0
- package/dist/cli/constants.js +10 -0
- package/dist/cli/constants.js.map +1 -0
- package/dist/cli/doctor.js +16 -5
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/index.d.ts +7 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +117 -43
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/ralph.d.ts +4 -0
- package/dist/cli/ralph.d.ts.map +1 -1
- package/dist/cli/ralph.js +89 -13
- package/dist/cli/ralph.js.map +1 -1
- package/dist/cli/setup.js +1 -1
- package/dist/cli/setup.js.map +1 -1
- package/dist/cli/team.d.ts +18 -0
- package/dist/cli/team.d.ts.map +1 -1
- package/dist/cli/team.js +108 -16
- package/dist/cli/team.js.map +1 -1
- package/dist/config/generator.d.ts.map +1 -1
- package/dist/config/generator.js +8 -0
- package/dist/config/generator.js.map +1 -1
- package/dist/hooks/__tests__/deep-interview-contract.test.d.ts +2 -0
- package/dist/hooks/__tests__/deep-interview-contract.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/deep-interview-contract.test.js +55 -0
- package/dist/hooks/__tests__/deep-interview-contract.test.js.map +1 -0
- package/dist/hooks/__tests__/emulator.test.js +6 -0
- package/dist/hooks/__tests__/emulator.test.js.map +1 -1
- package/dist/hooks/__tests__/keyword-detector.test.js +44 -22
- package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-session-scope.test.js +59 -0
- package/dist/hooks/__tests__/notify-hook-session-scope.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js +88 -0
- package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js +199 -0
- package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-visual-verdict.test.d.ts +11 -0
- package/dist/hooks/__tests__/notify-hook-visual-verdict.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/notify-hook-visual-verdict.test.js +266 -0
- package/dist/hooks/__tests__/notify-hook-visual-verdict.test.js.map +1 -0
- package/dist/hooks/__tests__/openclaw-setup-contract.test.d.ts +2 -0
- package/dist/hooks/__tests__/openclaw-setup-contract.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/openclaw-setup-contract.test.js +51 -0
- package/dist/hooks/__tests__/openclaw-setup-contract.test.js.map +1 -0
- package/dist/hooks/__tests__/pre-context-gate-skills.test.d.ts +2 -0
- package/dist/hooks/__tests__/pre-context-gate-skills.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/pre-context-gate-skills.test.js +34 -0
- package/dist/hooks/__tests__/pre-context-gate-skills.test.js.map +1 -0
- package/dist/hooks/__tests__/tmux-hook-engine.test.js +36 -1
- package/dist/hooks/__tests__/tmux-hook-engine.test.js.map +1 -1
- package/dist/hooks/__tests__/visual-verdict-loop.test.d.ts +2 -0
- package/dist/hooks/__tests__/visual-verdict-loop.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/visual-verdict-loop.test.js +35 -0
- package/dist/hooks/__tests__/visual-verdict-loop.test.js.map +1 -0
- package/dist/hooks/agents-overlay.d.ts.map +1 -1
- package/dist/hooks/agents-overlay.js +18 -16
- package/dist/hooks/agents-overlay.js.map +1 -1
- package/dist/hooks/codebase-map.d.ts.map +1 -1
- package/dist/hooks/codebase-map.js +6 -2
- package/dist/hooks/codebase-map.js.map +1 -1
- package/dist/hooks/emulator.d.ts.map +1 -1
- package/dist/hooks/emulator.js +2 -0
- package/dist/hooks/emulator.js.map +1 -1
- package/dist/hooks/extensibility/sdk.d.ts.map +1 -1
- package/dist/hooks/extensibility/sdk.js +2 -1
- package/dist/hooks/extensibility/sdk.js.map +1 -1
- package/dist/hooks/keyword-registry.d.ts.map +1 -1
- package/dist/hooks/keyword-registry.js +6 -0
- package/dist/hooks/keyword-registry.js.map +1 -1
- package/dist/hud/index.d.ts.map +1 -1
- package/dist/hud/index.js +2 -24
- package/dist/hud/index.js.map +1 -1
- package/dist/mcp/__tests__/team-server-cleanup.test.d.ts +2 -0
- package/dist/mcp/__tests__/team-server-cleanup.test.d.ts.map +1 -0
- package/dist/mcp/__tests__/team-server-cleanup.test.js +219 -0
- package/dist/mcp/__tests__/team-server-cleanup.test.js.map +1 -0
- package/dist/mcp/bootstrap.d.ts +1 -1
- package/dist/mcp/bootstrap.d.ts.map +1 -1
- package/dist/mcp/bootstrap.js +1 -0
- package/dist/mcp/bootstrap.js.map +1 -1
- package/dist/mcp/code-intel-server.d.ts.map +1 -1
- package/dist/mcp/code-intel-server.js +18 -8
- package/dist/mcp/code-intel-server.js.map +1 -1
- package/dist/mcp/memory-server.js +72 -11
- package/dist/mcp/memory-server.js.map +1 -1
- package/dist/mcp/state-paths.d.ts.map +1 -1
- package/dist/mcp/state-paths.js +4 -1
- package/dist/mcp/state-paths.js.map +1 -1
- package/dist/mcp/state-server.d.ts.map +1 -1
- package/dist/mcp/state-server.js +18 -5
- package/dist/mcp/state-server.js.map +1 -1
- package/dist/mcp/team-server.d.ts +24 -0
- package/dist/mcp/team-server.d.ts.map +1 -0
- package/dist/mcp/team-server.js +425 -0
- package/dist/mcp/team-server.js.map +1 -0
- package/dist/mcp/trace-server.d.ts.map +1 -1
- package/dist/mcp/trace-server.js +8 -3
- package/dist/mcp/trace-server.js.map +1 -1
- package/dist/notifications/__tests__/verbosity.test.js +35 -0
- package/dist/notifications/__tests__/verbosity.test.js.map +1 -1
- package/dist/notifications/config.d.ts.map +1 -1
- package/dist/notifications/config.js +12 -3
- package/dist/notifications/config.js.map +1 -1
- package/dist/notifications/dispatcher.d.ts.map +1 -1
- package/dist/notifications/dispatcher.js +4 -4
- package/dist/notifications/dispatcher.js.map +1 -1
- package/dist/notifications/reply-listener.d.ts.map +1 -1
- package/dist/notifications/reply-listener.js +6 -2
- package/dist/notifications/reply-listener.js.map +1 -1
- package/dist/notifications/session-registry.d.ts.map +1 -1
- package/dist/notifications/session-registry.js +2 -2
- package/dist/notifications/session-registry.js.map +1 -1
- package/dist/notifications/tmux.d.ts.map +1 -1
- package/dist/notifications/tmux.js +13 -4
- package/dist/notifications/tmux.js.map +1 -1
- package/dist/notifications/types.d.ts +4 -0
- package/dist/notifications/types.d.ts.map +1 -1
- package/dist/openclaw/__tests__/index.test.js +40 -0
- package/dist/openclaw/__tests__/index.test.js.map +1 -1
- package/dist/openclaw/dispatcher.d.ts.map +1 -1
- package/dist/openclaw/dispatcher.js +5 -2
- package/dist/openclaw/dispatcher.js.map +1 -1
- package/dist/openclaw/index.d.ts.map +1 -1
- package/dist/openclaw/index.js +1 -0
- package/dist/openclaw/index.js.map +1 -1
- package/dist/openclaw/types.d.ts +2 -0
- package/dist/openclaw/types.d.ts.map +1 -1
- package/dist/ralph/__tests__/persistence.test.js +28 -1
- package/dist/ralph/__tests__/persistence.test.js.map +1 -1
- package/dist/ralph/persistence.d.ts +21 -0
- package/dist/ralph/persistence.d.ts.map +1 -1
- package/dist/ralph/persistence.js +85 -2
- package/dist/ralph/persistence.js.map +1 -1
- package/dist/state/paths.d.ts +3 -0
- package/dist/state/paths.d.ts.map +1 -0
- package/dist/state/paths.js +2 -0
- package/dist/state/paths.js.map +1 -0
- package/dist/team/__tests__/idle-nudge.test.d.ts +2 -0
- package/dist/team/__tests__/idle-nudge.test.d.ts.map +1 -0
- package/dist/team/__tests__/idle-nudge.test.js +225 -0
- package/dist/team/__tests__/idle-nudge.test.js.map +1 -0
- package/dist/team/__tests__/role-router.test.d.ts +2 -0
- package/dist/team/__tests__/role-router.test.d.ts.map +1 -0
- package/dist/team/__tests__/role-router.test.js +204 -0
- package/dist/team/__tests__/role-router.test.js.map +1 -0
- package/dist/team/__tests__/runtime-cli.test.d.ts +2 -0
- package/dist/team/__tests__/runtime-cli.test.d.ts.map +1 -0
- package/dist/team/__tests__/runtime-cli.test.js +72 -0
- package/dist/team/__tests__/runtime-cli.test.js.map +1 -0
- package/dist/team/__tests__/runtime.test.js +195 -9
- package/dist/team/__tests__/runtime.test.js.map +1 -1
- package/dist/team/__tests__/scaling.test.js +132 -2
- package/dist/team/__tests__/scaling.test.js.map +1 -1
- package/dist/team/__tests__/state-root.test.d.ts +2 -0
- package/dist/team/__tests__/state-root.test.d.ts.map +1 -0
- package/dist/team/__tests__/state-root.test.js +9 -0
- package/dist/team/__tests__/state-root.test.js.map +1 -0
- package/dist/team/__tests__/state.test.js +52 -17
- package/dist/team/__tests__/state.test.js.map +1 -1
- package/dist/team/__tests__/team-ops-contract.test.d.ts +2 -0
- package/dist/team/__tests__/team-ops-contract.test.d.ts.map +1 -0
- package/dist/team/__tests__/team-ops-contract.test.js +90 -0
- package/dist/team/__tests__/team-ops-contract.test.js.map +1 -0
- package/dist/team/__tests__/tmux-session.test.js +94 -7
- package/dist/team/__tests__/tmux-session.test.js.map +1 -1
- package/dist/team/__tests__/worker-bootstrap.test.js +59 -0
- package/dist/team/__tests__/worker-bootstrap.test.js.map +1 -1
- package/dist/team/__tests__/worktree.test.js +81 -2
- package/dist/team/__tests__/worktree.test.js.map +1 -1
- package/dist/team/idle-nudge.d.ts +53 -0
- package/dist/team/idle-nudge.d.ts.map +1 -0
- package/dist/team/idle-nudge.js +140 -0
- package/dist/team/idle-nudge.js.map +1 -0
- package/dist/team/mcp-comm.d.ts +1 -1
- package/dist/team/mcp-comm.d.ts.map +1 -1
- package/dist/team/mcp-comm.js +6 -2
- package/dist/team/mcp-comm.js.map +1 -1
- package/dist/team/orchestrator.d.ts +1 -10
- package/dist/team/orchestrator.d.ts.map +1 -1
- package/dist/team/orchestrator.js +8 -0
- package/dist/team/orchestrator.js.map +1 -1
- package/dist/team/role-router.d.ts +32 -0
- package/dist/team/role-router.d.ts.map +1 -0
- package/dist/team/role-router.js +137 -0
- package/dist/team/role-router.js.map +1 -0
- package/dist/team/runtime-cli.d.ts +18 -0
- package/dist/team/runtime-cli.d.ts.map +1 -0
- package/dist/team/runtime-cli.js +244 -0
- package/dist/team/runtime-cli.js.map +1 -0
- package/dist/team/runtime.d.ts +6 -1
- package/dist/team/runtime.d.ts.map +1 -1
- package/dist/team/runtime.js +148 -60
- package/dist/team/runtime.js.map +1 -1
- package/dist/team/scaling.d.ts +1 -0
- package/dist/team/scaling.d.ts.map +1 -1
- package/dist/team/scaling.js +74 -32
- package/dist/team/scaling.js.map +1 -1
- package/dist/team/state/approvals.d.ts +25 -0
- package/dist/team/state/approvals.d.ts.map +1 -0
- package/dist/team/state/approvals.js +31 -0
- package/dist/team/state/approvals.js.map +1 -0
- package/dist/team/state/config.d.ts +2 -0
- package/dist/team/state/config.d.ts.map +1 -0
- package/dist/team/state/config.js +2 -0
- package/dist/team/state/config.js.map +1 -0
- package/dist/team/state/dispatch-lock.d.ts +3 -0
- package/dist/team/state/dispatch-lock.d.ts.map +1 -0
- package/dist/team/state/dispatch-lock.js +81 -0
- package/dist/team/state/dispatch-lock.js.map +1 -0
- package/dist/team/state/dispatch.d.ts +61 -0
- package/dist/team/state/dispatch.d.ts.map +1 -0
- package/dist/team/state/dispatch.js +158 -0
- package/dist/team/state/dispatch.js.map +1 -0
- package/dist/team/state/events.d.ts +2 -0
- package/dist/team/state/events.d.ts.map +1 -0
- package/dist/team/state/events.js +2 -0
- package/dist/team/state/events.js.map +1 -0
- package/dist/team/state/index.d.ts +11 -0
- package/dist/team/state/index.d.ts.map +1 -0
- package/dist/team/state/index.js +11 -0
- package/dist/team/state/index.js.map +1 -0
- package/dist/team/state/io.d.ts +2 -0
- package/dist/team/state/io.d.ts.map +1 -0
- package/dist/team/state/io.js +2 -0
- package/dist/team/state/io.js.map +1 -0
- package/dist/team/state/locks.d.ts +16 -0
- package/dist/team/state/locks.d.ts.map +1 -0
- package/dist/team/state/locks.js +201 -0
- package/dist/team/state/locks.js.map +1 -0
- package/dist/team/state/mailbox.d.ts +39 -0
- package/dist/team/state/mailbox.d.ts.map +1 -0
- package/dist/team/state/mailbox.js +58 -0
- package/dist/team/state/mailbox.js.map +1 -0
- package/dist/team/state/monitor.d.ts +96 -0
- package/dist/team/state/monitor.d.ts.map +1 -0
- package/dist/team/state/monitor.js +163 -0
- package/dist/team/state/monitor.js.map +1 -0
- package/dist/team/state/shutdown.d.ts +2 -0
- package/dist/team/state/shutdown.d.ts.map +1 -0
- package/dist/team/state/shutdown.js +2 -0
- package/dist/team/state/shutdown.js.map +1 -0
- package/dist/team/state/summary.d.ts +2 -0
- package/dist/team/state/summary.d.ts.map +1 -0
- package/dist/team/state/summary.js +2 -0
- package/dist/team/state/summary.js.map +1 -0
- package/dist/team/state/tasks.d.ts +49 -0
- package/dist/team/state/tasks.d.ts.map +1 -0
- package/dist/team/state/tasks.js +182 -0
- package/dist/team/state/tasks.js.map +1 -0
- package/dist/team/state/types.d.ts +281 -0
- package/dist/team/state/types.d.ts.map +1 -0
- package/dist/team/state/types.js +3 -0
- package/dist/team/state/types.js.map +1 -0
- package/dist/team/state/workers.d.ts +2 -0
- package/dist/team/state/workers.d.ts.map +1 -0
- package/dist/team/state/workers.js +2 -0
- package/dist/team/state/workers.js.map +1 -0
- package/dist/team/state-root.d.ts +5 -0
- package/dist/team/state-root.d.ts.map +1 -0
- package/dist/team/state-root.js +8 -0
- package/dist/team/state-root.js.map +1 -0
- package/dist/team/state.d.ts +6 -2
- package/dist/team/state.d.ts.map +1 -1
- package/dist/team/state.js +200 -881
- package/dist/team/state.js.map +1 -1
- package/dist/team/tmux-session.d.ts +42 -2
- package/dist/team/tmux-session.d.ts.map +1 -1
- package/dist/team/tmux-session.js +229 -74
- package/dist/team/tmux-session.js.map +1 -1
- package/dist/team/worker-bootstrap.d.ts +2 -0
- package/dist/team/worker-bootstrap.d.ts.map +1 -1
- package/dist/team/worker-bootstrap.js +47 -20
- package/dist/team/worker-bootstrap.js.map +1 -1
- package/dist/team/worktree.d.ts +5 -1
- package/dist/team/worktree.d.ts.map +1 -1
- package/dist/team/worktree.js +71 -17
- package/dist/team/worktree.js.map +1 -1
- package/dist/utils/safe-json.d.ts +3 -0
- package/dist/utils/safe-json.d.ts.map +1 -0
- package/dist/utils/safe-json.js +19 -0
- package/dist/utils/safe-json.js.map +1 -0
- package/dist/utils/sleep.d.ts +3 -0
- package/dist/utils/sleep.d.ts.map +1 -0
- package/dist/utils/sleep.js +15 -0
- package/dist/utils/sleep.js.map +1 -0
- package/dist/visual/__tests__/verdict.test.d.ts +2 -0
- package/dist/visual/__tests__/verdict.test.d.ts.map +1 -0
- package/dist/visual/__tests__/verdict.test.js +81 -0
- package/dist/visual/__tests__/verdict.test.js.map +1 -0
- package/dist/visual/constants.d.ts +4 -0
- package/dist/visual/constants.d.ts.map +1 -0
- package/dist/visual/constants.js +3 -0
- package/dist/visual/constants.js.map +1 -0
- package/dist/visual/verdict.d.ts +17 -0
- package/dist/visual/verdict.d.ts.map +1 -0
- package/dist/visual/verdict.js +61 -0
- package/dist/visual/verdict.js.map +1 -0
- package/package.json +10 -3
- package/scripts/ask-claude.sh +17 -0
- package/scripts/ask-gemini.sh +14 -0
- package/scripts/fixtures/ask-advisor-stub.js +12 -0
- package/scripts/notify-hook/log.js +5 -0
- package/scripts/notify-hook/team-dispatch.js +56 -1
- package/scripts/notify-hook/tmux-injection.js +45 -4
- package/scripts/notify-hook/visual-verdict.js +158 -0
- package/scripts/notify-hook.js +27 -0
- package/scripts/run-provider-advisor.js +179 -0
- package/scripts/tmux-hook-engine.js +24 -0
- package/skills/ask-claude/SKILL.md +61 -0
- package/skills/ask-gemini/SKILL.md +61 -0
- package/skills/autopilot/SKILL.md +34 -4
- package/skills/configure-notifications/SKILL.md +1 -1
- package/skills/configure-openclaw/SKILL.md +154 -157
- package/skills/deep-interview/SKILL.md +247 -0
- package/skills/doctor/SKILL.md +1 -1
- package/skills/help/SKILL.md +3 -3
- package/skills/ralph/SKILL.md +42 -11
- package/skills/ralplan/SKILL.md +17 -0
- package/skills/skill/SKILL.md +32 -32
- package/skills/team/SKILL.md +60 -0
- package/skills/visual-verdict/SKILL.md +76 -0
- package/skills/web-clone/SKILL.md +366 -0
- package/skills/worker/SKILL.md +5 -4
- package/templates/AGENTS.md +9 -0
- package/templates/catalog-manifest.json +39 -2
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Visual verdict extraction and persistence.
|
|
3
|
+
*
|
|
4
|
+
* Parses PASS / FAIL / INCOMPLETE verdicts from verifier agent output
|
|
5
|
+
* and persists them to stateDir/verdicts/latest-verdict.json.
|
|
6
|
+
*
|
|
7
|
+
* All failures are logged with structured context (issue #421) rather
|
|
8
|
+
* than silently swallowed.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { writeFile, mkdir } from 'fs/promises';
|
|
12
|
+
import { join } from 'path';
|
|
13
|
+
import { logNotifyHookEvent } from './log.js';
|
|
14
|
+
import { safeString } from './utils.js';
|
|
15
|
+
|
|
16
|
+
/** Structured patterns that reliably indicate a verification verdict. */
|
|
17
|
+
const VERDICT_PATTERNS = [
|
|
18
|
+
/\*\*Status\*\*:\s*(PASS|FAIL|INCOMPLETE)/i,
|
|
19
|
+
/\bVerdict:\s*(PASS|FAIL|INCOMPLETE)\b/i,
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Heuristic: output contains verdict-like markers but no structured match.
|
|
24
|
+
* Used to emit a debug-level log for candidate parse failures.
|
|
25
|
+
*/
|
|
26
|
+
const VERDICT_CANDIDATE_RE = /(?:\*\*Status\*\*\s*:|Verdict\s*:)/i;
|
|
27
|
+
|
|
28
|
+
function extractJsonCandidates(rawMessage) {
|
|
29
|
+
const message = safeString(rawMessage).trim();
|
|
30
|
+
if (!message) return [];
|
|
31
|
+
|
|
32
|
+
const candidates = [message];
|
|
33
|
+
const fencePattern = /```(?:json)?\s*([\s\S]*?)```/gi;
|
|
34
|
+
for (const match of message.matchAll(fencePattern)) {
|
|
35
|
+
const block = safeString(match[1]).trim();
|
|
36
|
+
if (block) candidates.push(block);
|
|
37
|
+
}
|
|
38
|
+
return candidates;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async function maybePersistRuntimeVisualFeedback({ cwd, output, sessionId }) {
|
|
42
|
+
if (!cwd || !output) return;
|
|
43
|
+
|
|
44
|
+
const candidates = extractJsonCandidates(output);
|
|
45
|
+
if (candidates.length === 0) return;
|
|
46
|
+
|
|
47
|
+
const { buildVisualLoopFeedback } = await import('../../dist/visual/verdict.js');
|
|
48
|
+
const { recordRalphVisualFeedback } = await import('../../dist/ralph/persistence.js');
|
|
49
|
+
|
|
50
|
+
for (const candidate of candidates) {
|
|
51
|
+
try {
|
|
52
|
+
const parsed = JSON.parse(candidate);
|
|
53
|
+
const feedback = buildVisualLoopFeedback(parsed);
|
|
54
|
+
await recordRalphVisualFeedback(cwd, feedback, sessionId || undefined);
|
|
55
|
+
return;
|
|
56
|
+
} catch {
|
|
57
|
+
// Try next candidate
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Attempt to extract a structured verdict from free-form text.
|
|
64
|
+
* Returns `{ verdict, raw }` on success, `null` otherwise.
|
|
65
|
+
*/
|
|
66
|
+
export function parseVisualVerdict(text) {
|
|
67
|
+
if (!text || typeof text !== 'string') return null;
|
|
68
|
+
for (const pattern of VERDICT_PATTERNS) {
|
|
69
|
+
const match = text.match(pattern);
|
|
70
|
+
if (match) {
|
|
71
|
+
return { verdict: match[1].toUpperCase(), raw: match[0] };
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Parse a visual verdict from the agent payload output and persist it.
|
|
79
|
+
*
|
|
80
|
+
* Logs structured warnings/debug events instead of silently swallowing
|
|
81
|
+
* errors (addresses issue #421):
|
|
82
|
+
* - debug: candidate markers found but no structured verdict matched
|
|
83
|
+
* - warn: verdict file write failure (with turn/session context)
|
|
84
|
+
*
|
|
85
|
+
* Module import failure is handled by the caller in notify-hook.js.
|
|
86
|
+
*/
|
|
87
|
+
export async function maybePersistVisualVerdict({ cwd, payload, stateDir, logsDir, sessionId, turnId }) {
|
|
88
|
+
const output = safeString(
|
|
89
|
+
payload?.['last-assistant-message'] || payload?.last_assistant_message || '',
|
|
90
|
+
);
|
|
91
|
+
if (!output) return;
|
|
92
|
+
|
|
93
|
+
// Runtime visual feedback (JSON/fenced JSON) for ralph-progress persistence.
|
|
94
|
+
// Non-fatal and observable via warn-level structured logging.
|
|
95
|
+
try {
|
|
96
|
+
await maybePersistRuntimeVisualFeedback({ cwd, output, sessionId });
|
|
97
|
+
} catch (err) {
|
|
98
|
+
await logNotifyHookEvent(logsDir, {
|
|
99
|
+
timestamp: new Date().toISOString(),
|
|
100
|
+
level: 'warn',
|
|
101
|
+
type: 'visual_runtime_feedback_persist_failure',
|
|
102
|
+
error: err?.message || String(err),
|
|
103
|
+
session_id: sessionId,
|
|
104
|
+
turn_id: turnId,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const parsed = parseVisualVerdict(output);
|
|
109
|
+
|
|
110
|
+
if (!parsed) {
|
|
111
|
+
// Debug level: verdict-like markers present but no structured match
|
|
112
|
+
if (VERDICT_CANDIDATE_RE.test(output)) {
|
|
113
|
+
await logNotifyHookEvent(logsDir, {
|
|
114
|
+
timestamp: new Date().toISOString(),
|
|
115
|
+
level: 'debug',
|
|
116
|
+
type: 'visual_verdict_parse_no_match',
|
|
117
|
+
session_id: sessionId,
|
|
118
|
+
turn_id: turnId,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Persist the extracted verdict
|
|
125
|
+
try {
|
|
126
|
+
const verdictDir = join(stateDir, 'verdicts');
|
|
127
|
+
await mkdir(verdictDir, { recursive: true });
|
|
128
|
+
|
|
129
|
+
const entry = {
|
|
130
|
+
timestamp: new Date().toISOString(),
|
|
131
|
+
verdict: parsed.verdict,
|
|
132
|
+
raw_match: parsed.raw,
|
|
133
|
+
session_id: sessionId,
|
|
134
|
+
turn_id: turnId,
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
await writeFile(
|
|
138
|
+
join(verdictDir, 'latest-verdict.json'),
|
|
139
|
+
JSON.stringify(entry, null, 2),
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
await logNotifyHookEvent(logsDir, {
|
|
143
|
+
...entry,
|
|
144
|
+
level: 'info',
|
|
145
|
+
type: 'visual_verdict_persisted',
|
|
146
|
+
});
|
|
147
|
+
} catch (err) {
|
|
148
|
+
// Warn level: persistence write failure with turn/session context
|
|
149
|
+
await logNotifyHookEvent(logsDir, {
|
|
150
|
+
timestamp: new Date().toISOString(),
|
|
151
|
+
level: 'warn',
|
|
152
|
+
type: 'visual_verdict_write_failure',
|
|
153
|
+
error: err?.message || String(err),
|
|
154
|
+
session_id: sessionId,
|
|
155
|
+
turn_id: turnId,
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
}
|
package/scripts/notify-hook.js
CHANGED
|
@@ -404,6 +404,33 @@ async function main() {
|
|
|
404
404
|
// Non-critical
|
|
405
405
|
}
|
|
406
406
|
|
|
407
|
+
// 10.5. Visual verdict persistence (non-fatal, observable – issue #421)
|
|
408
|
+
if (!isTeamWorker) {
|
|
409
|
+
try {
|
|
410
|
+
const { maybePersistVisualVerdict } = await import('./notify-hook/visual-verdict.js');
|
|
411
|
+
await maybePersistVisualVerdict({
|
|
412
|
+
cwd,
|
|
413
|
+
payload,
|
|
414
|
+
stateDir,
|
|
415
|
+
logsDir,
|
|
416
|
+
sessionId: payloadSessionId,
|
|
417
|
+
turnId: safeString(payload['turn-id'] || payload.turn_id || ''),
|
|
418
|
+
});
|
|
419
|
+
} catch (err) {
|
|
420
|
+
// Structured warning for module import failure (issue #421)
|
|
421
|
+
const warnEntry = JSON.stringify({
|
|
422
|
+
timestamp: new Date().toISOString(),
|
|
423
|
+
level: 'warn',
|
|
424
|
+
type: 'visual_verdict_import_failure',
|
|
425
|
+
error: err?.message || String(err),
|
|
426
|
+
session_id: payloadSessionId,
|
|
427
|
+
turn_id: safeString(payload['turn-id'] || payload.turn_id || ''),
|
|
428
|
+
});
|
|
429
|
+
const warnFile = join(logsDir, `notify-hook-${new Date().toISOString().split('T')[0]}.jsonl`);
|
|
430
|
+
await appendFile(warnFile, warnEntry + '\n').catch(() => {});
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
407
434
|
// 10. Code simplifier: delegate recently modified files for simplification.
|
|
408
435
|
// Opt-in via ~/.omx/config.json: { "codeSimplifier": { "enabled": true } }
|
|
409
436
|
if (!isTeamWorker) {
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { mkdir, writeFile } from 'fs/promises';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import process from 'process';
|
|
5
|
+
import { spawnSync } from 'child_process';
|
|
6
|
+
|
|
7
|
+
const PROVIDER_BINARIES = {
|
|
8
|
+
claude: 'claude',
|
|
9
|
+
gemini: 'gemini',
|
|
10
|
+
};
|
|
11
|
+
const ASK_ORIGINAL_TASK_ENV = 'OMX_ASK_ORIGINAL_TASK';
|
|
12
|
+
|
|
13
|
+
function usage() {
|
|
14
|
+
console.error('Usage: omx ask <claude|gemini> "<prompt>"');
|
|
15
|
+
console.error('Legacy direct usage: node scripts/run-provider-advisor.js <claude|gemini> <prompt...>');
|
|
16
|
+
console.error(' or: node scripts/run-provider-advisor.js claude --print "<prompt>"');
|
|
17
|
+
console.error(' or: node scripts/run-provider-advisor.js gemini --prompt "<prompt>"');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function slugify(value) {
|
|
21
|
+
return value
|
|
22
|
+
.toLowerCase()
|
|
23
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
24
|
+
.replace(/^-+|-+$/g, '')
|
|
25
|
+
.slice(0, 60) || 'task';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function timestampToken(date = new Date()) {
|
|
29
|
+
return date.toISOString().replace(/[:.]/g, '-');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function parseArgs(argv) {
|
|
33
|
+
const [providerRaw, ...rest] = argv;
|
|
34
|
+
const provider = (providerRaw || '').toLowerCase();
|
|
35
|
+
|
|
36
|
+
if (!provider || !(provider in PROVIDER_BINARIES)) {
|
|
37
|
+
usage();
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (rest.length === 0) {
|
|
42
|
+
usage();
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (rest[0] === '-p' || rest[0] === '--print' || rest[0] === '--prompt') {
|
|
47
|
+
const prompt = rest.slice(1).join(' ').trim();
|
|
48
|
+
if (!prompt) {
|
|
49
|
+
usage();
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
return { provider, prompt };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return { provider, prompt: rest.join(' ').trim() };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function ensureBinary(binary) {
|
|
59
|
+
const probe = spawnSync(binary, ['--version'], {
|
|
60
|
+
stdio: 'ignore',
|
|
61
|
+
encoding: 'utf8',
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
if (probe.error && probe.error.code === 'ENOENT') {
|
|
65
|
+
const verify = `${binary} --version`;
|
|
66
|
+
console.error(`[ask-${binary}] Missing required local CLI binary: ${binary}`);
|
|
67
|
+
console.error(`[ask-${binary}] Install/configure ${binary} CLI, then verify with: ${verify}`);
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function buildSummary(exitCode, output) {
|
|
73
|
+
if (exitCode === 0) {
|
|
74
|
+
return 'Provider completed successfully. Review the raw output for details.';
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const firstLine = output
|
|
78
|
+
.split('\n')
|
|
79
|
+
.map((line) => line.trim())
|
|
80
|
+
.find(Boolean);
|
|
81
|
+
|
|
82
|
+
return firstLine
|
|
83
|
+
? `Provider command failed (exit ${exitCode}): ${firstLine}`
|
|
84
|
+
: `Provider command failed with exit code ${exitCode}.`;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function buildActionItems(exitCode) {
|
|
88
|
+
if (exitCode === 0) {
|
|
89
|
+
return ['Review the response and extract decisions you want to apply.', 'Capture follow-up implementation tasks if needed.'];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return ['Inspect the raw output error details.', 'Fix CLI/auth/environment issues and rerun the command.'];
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async function writeArtifact({ provider, originalTask, finalPrompt, rawOutput, exitCode }) {
|
|
96
|
+
const root = process.cwd();
|
|
97
|
+
const artifactDir = join(root, '.omx', 'artifacts');
|
|
98
|
+
const slug = slugify(originalTask);
|
|
99
|
+
const timestamp = timestampToken();
|
|
100
|
+
const artifactPath = join(artifactDir, `${provider}-${slug}-${timestamp}.md`);
|
|
101
|
+
|
|
102
|
+
const summary = buildSummary(exitCode, rawOutput);
|
|
103
|
+
const actionItems = buildActionItems(exitCode);
|
|
104
|
+
|
|
105
|
+
const body = [
|
|
106
|
+
`# ${provider} advisor artifact`,
|
|
107
|
+
'',
|
|
108
|
+
`- Provider: ${provider}`,
|
|
109
|
+
`- Exit code: ${exitCode}`,
|
|
110
|
+
`- Created at: ${new Date().toISOString()}`,
|
|
111
|
+
'',
|
|
112
|
+
'## Original task',
|
|
113
|
+
'',
|
|
114
|
+
originalTask,
|
|
115
|
+
'',
|
|
116
|
+
'## Final prompt',
|
|
117
|
+
'',
|
|
118
|
+
finalPrompt,
|
|
119
|
+
'',
|
|
120
|
+
'## Raw output',
|
|
121
|
+
'',
|
|
122
|
+
'```text',
|
|
123
|
+
rawOutput || '(no output)',
|
|
124
|
+
'```',
|
|
125
|
+
'',
|
|
126
|
+
'## Concise summary',
|
|
127
|
+
'',
|
|
128
|
+
summary,
|
|
129
|
+
'',
|
|
130
|
+
'## Action items',
|
|
131
|
+
'',
|
|
132
|
+
...actionItems.map((item) => `- ${item}`),
|
|
133
|
+
'',
|
|
134
|
+
].join('\n');
|
|
135
|
+
|
|
136
|
+
await mkdir(artifactDir, { recursive: true });
|
|
137
|
+
await writeFile(artifactPath, body, 'utf8');
|
|
138
|
+
return artifactPath;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
async function main() {
|
|
142
|
+
const { provider, prompt } = parseArgs(process.argv.slice(2));
|
|
143
|
+
const binary = PROVIDER_BINARIES[provider];
|
|
144
|
+
|
|
145
|
+
ensureBinary(binary);
|
|
146
|
+
|
|
147
|
+
const run = spawnSync(binary, ['-p', prompt], {
|
|
148
|
+
encoding: 'utf8',
|
|
149
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
const stdout = run.stdout || '';
|
|
153
|
+
const stderr = run.stderr || '';
|
|
154
|
+
const rawOutput = [stdout, stderr].filter(Boolean).join(stdout && stderr ? '\n\n' : '');
|
|
155
|
+
const exitCode = typeof run.status === 'number' ? run.status : 1;
|
|
156
|
+
|
|
157
|
+
const artifactPath = await writeArtifact({
|
|
158
|
+
provider,
|
|
159
|
+
originalTask: process.env[ASK_ORIGINAL_TASK_ENV] ?? prompt,
|
|
160
|
+
finalPrompt: prompt,
|
|
161
|
+
rawOutput,
|
|
162
|
+
exitCode,
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
console.log(artifactPath);
|
|
166
|
+
|
|
167
|
+
if (run.error) {
|
|
168
|
+
console.error(`[ask-${provider}] ${run.error.message}`);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (exitCode !== 0) {
|
|
172
|
+
process.exit(exitCode);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
main().catch((error) => {
|
|
177
|
+
console.error(`[run-provider-advisor] ${error instanceof Error ? error.message : String(error)}`);
|
|
178
|
+
process.exit(1);
|
|
179
|
+
});
|
|
@@ -154,6 +154,30 @@ export function buildPaneInModeArgv(paneTarget) {
|
|
|
154
154
|
return ['display-message', '-p', '-t', paneTarget, '#{pane_in_mode}'];
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
+
/**
|
|
158
|
+
* Returns the tmux argv to query the current foreground command of a pane.
|
|
159
|
+
* Used to detect when the agent process has exited and the pane has returned
|
|
160
|
+
* to a shell (zsh, bash, fish, etc.).
|
|
161
|
+
*/
|
|
162
|
+
export function buildPaneCurrentCommandArgv(paneTarget) {
|
|
163
|
+
return ['display-message', '-p', '-t', paneTarget, '#{pane_current_command}'];
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const SHELL_COMMANDS = new Set(['zsh', 'bash', 'fish', 'sh', 'dash', 'ksh', 'csh', 'tcsh', 'login']);
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Returns true when the pane's foreground process is an interactive shell,
|
|
170
|
+
* meaning the agent has exited and injection would land on a bare prompt.
|
|
171
|
+
*/
|
|
172
|
+
export function isPaneRunningShell(paneCurrentCommand) {
|
|
173
|
+
if (typeof paneCurrentCommand !== 'string') return false;
|
|
174
|
+
const cmd = paneCurrentCommand.trim().toLowerCase();
|
|
175
|
+
if (cmd === '') return false;
|
|
176
|
+
// Handle paths like /bin/zsh -> zsh, and flags like -zsh -> zsh
|
|
177
|
+
const base = cmd.split('/').pop().replace(/^-/, '');
|
|
178
|
+
return SHELL_COMMANDS.has(base);
|
|
179
|
+
}
|
|
180
|
+
|
|
157
181
|
export function buildCapturePaneArgv(paneTarget, tailLines = 80) {
|
|
158
182
|
return ['capture-pane', '-t', paneTarget, '-p', '-S', `-${tailLines}`];
|
|
159
183
|
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ask-claude
|
|
3
|
+
description: Ask Claude via local CLI and capture a reusable artifact
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Ask Claude (Local CLI)
|
|
7
|
+
|
|
8
|
+
Use the locally installed Claude CLI as a direct external advisor for focused questions, reviews, or second opinions.
|
|
9
|
+
|
|
10
|
+
## Usage
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
/ask-claude <question or task>
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Routing
|
|
17
|
+
|
|
18
|
+
### Preferred: Local CLI execution
|
|
19
|
+
Run Claude through the canonical OMX CLI command path (no MCP routing):
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
omx ask claude "{{ARGUMENTS}}"
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Exact non-interactive Claude CLI command from `claude --help`:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
claude -p "{{ARGUMENTS}}"
|
|
29
|
+
# equivalent: claude --print "{{ARGUMENTS}}"
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
If needed, adapt to the user's installed Claude CLI variant while keeping local execution as the default path.
|
|
33
|
+
|
|
34
|
+
Legacy compatibility entrypoints (`./scripts/ask-claude.sh`, `npm run ask:claude -- ...`) are transitional wrappers.
|
|
35
|
+
|
|
36
|
+
### Missing binary behavior
|
|
37
|
+
If `claude` is not found, do **not** switch to MCP.
|
|
38
|
+
Instead:
|
|
39
|
+
1. Explain that local Claude CLI is required for this skill.
|
|
40
|
+
2. Ask the user to install/configure Claude CLI.
|
|
41
|
+
3. Provide a quick verification command:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
claude --version
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Artifact requirement
|
|
48
|
+
After local execution, save a markdown artifact to:
|
|
49
|
+
|
|
50
|
+
```text
|
|
51
|
+
.omx/artifacts/claude-<slug>-<timestamp>.md
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Minimum artifact sections:
|
|
55
|
+
1. Original user task
|
|
56
|
+
2. Final prompt sent to Claude CLI
|
|
57
|
+
3. Claude output (raw)
|
|
58
|
+
4. Concise summary
|
|
59
|
+
5. Action items / next steps
|
|
60
|
+
|
|
61
|
+
Task: {{ARGUMENTS}}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ask-gemini
|
|
3
|
+
description: Ask Gemini via local CLI and capture a reusable artifact
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Ask Gemini (Local CLI)
|
|
7
|
+
|
|
8
|
+
Use the locally installed Gemini CLI as a direct external advisor for brainstorming, design feedback, and second opinions.
|
|
9
|
+
|
|
10
|
+
## Usage
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
/ask-gemini <question or task>
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Routing
|
|
17
|
+
|
|
18
|
+
### Preferred: Local CLI execution
|
|
19
|
+
Run Gemini through the canonical OMX CLI command path (no MCP routing):
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
omx ask gemini "{{ARGUMENTS}}"
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Exact non-interactive Gemini CLI command from `gemini --help`:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
gemini -p "{{ARGUMENTS}}"
|
|
29
|
+
# equivalent: gemini --prompt "{{ARGUMENTS}}"
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
If needed, adapt to the user's installed Gemini CLI variant while keeping local execution as the default path.
|
|
33
|
+
|
|
34
|
+
Legacy compatibility entrypoints (`./scripts/ask-gemini.sh`, `npm run ask:gemini -- ...`) are transitional wrappers.
|
|
35
|
+
|
|
36
|
+
### Missing binary behavior
|
|
37
|
+
If `gemini` is not found, do **not** switch to MCP.
|
|
38
|
+
Instead:
|
|
39
|
+
1. Explain that local Gemini CLI is required for this skill.
|
|
40
|
+
2. Ask the user to install/configure Gemini CLI.
|
|
41
|
+
3. Provide a quick verification command:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
gemini --version
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Artifact requirement
|
|
48
|
+
After local execution, save a markdown artifact to:
|
|
49
|
+
|
|
50
|
+
```text
|
|
51
|
+
.omx/artifacts/gemini-<slug>-<timestamp>.md
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Minimum artifact sections:
|
|
55
|
+
1. Original user task
|
|
56
|
+
2. Final prompt sent to Gemini CLI
|
|
57
|
+
3. Gemini output (raw)
|
|
58
|
+
4. Concise summary
|
|
59
|
+
5. Action items / next steps
|
|
60
|
+
|
|
61
|
+
Task: {{ARGUMENTS}}
|
|
@@ -32,10 +32,28 @@ Most non-trivial software tasks require coordinated phases: understanding requir
|
|
|
32
32
|
- QA cycles repeat up to 5 times; if the same error persists 3 times, stop and report the fundamental issue
|
|
33
33
|
- Validation requires approval from all reviewers; rejected items get fixed and re-validated
|
|
34
34
|
- Cancel with `/cancel` at any time; progress is preserved for resume
|
|
35
|
+
- If a deep-interview spec exists, use it as high-clarity phase input instead of re-expanding from scratch
|
|
36
|
+
- If input is too vague for reliable expansion, offer/trigger `$deep-interview` first
|
|
37
|
+
- Do not enter expansion/planning/execution-heavy phases until pre-context grounding exists; if fast execution is forced, proceed only with explicit risk notes
|
|
35
38
|
</Execution_Policy>
|
|
36
39
|
|
|
37
40
|
<Steps>
|
|
41
|
+
0. **Pre-context Intake (required before Phase 0 starts)**:
|
|
42
|
+
- Derive a task slug from the request.
|
|
43
|
+
- Load the latest relevant snapshot from `.omx/context/{slug}-*.md` when available.
|
|
44
|
+
- If no snapshot exists, create `.omx/context/{slug}-{timestamp}.md` (UTC `YYYYMMDDTHHMMSSZ`) with:
|
|
45
|
+
- Task statement
|
|
46
|
+
- Desired outcome
|
|
47
|
+
- Known facts/evidence
|
|
48
|
+
- Constraints
|
|
49
|
+
- Unknowns/open questions
|
|
50
|
+
- Likely codebase touchpoints
|
|
51
|
+
- If ambiguity remains high, run `explore` first for brownfield facts, then run `$deep-interview --quick <task>` before proceeding.
|
|
52
|
+
- Carry the snapshot path into autopilot artifacts/state so all phases share grounded context.
|
|
53
|
+
|
|
38
54
|
1. **Phase 0 - Expansion**: Turn the user's idea into a detailed spec
|
|
55
|
+
- If `.omx/specs/deep-interview-*.md` exists for this task: reuse it and skip redundant expansion work
|
|
56
|
+
- If prompt is highly vague: route to `$deep-interview` for Socratic ambiguity-gated clarification
|
|
39
57
|
- Analyst (Opus): Extract requirements
|
|
40
58
|
- Architect (Opus): Create technical specification
|
|
41
59
|
- Output: `.omx/plans/autopilot-spec.md`
|
|
@@ -84,7 +102,7 @@ Most non-trivial software tasks require coordinated phases: understanding requir
|
|
|
84
102
|
Use `omx_state` MCP tools for autopilot lifecycle state.
|
|
85
103
|
|
|
86
104
|
- **On start**:
|
|
87
|
-
`state_write({mode: "autopilot", active: true, current_phase: "expansion", started_at: "<now>"})`
|
|
105
|
+
`state_write({mode: "autopilot", active: true, current_phase: "expansion", started_at: "<now>", state: {context_snapshot_path: "<snapshot-path>"}})`
|
|
88
106
|
- **On phase transitions**:
|
|
89
107
|
`state_write({mode: "autopilot", current_phase: "planning"})`
|
|
90
108
|
`state_write({mode: "autopilot", current_phase: "execution"})`
|
|
@@ -121,7 +139,7 @@ Why bad: This is an exploration/brainstorming request. Respond conversationally
|
|
|
121
139
|
- Stop and report when the same QA error persists across 3 cycles (fundamental issue requiring human input)
|
|
122
140
|
- Stop and report when validation keeps failing after 3 re-validation rounds
|
|
123
141
|
- Stop when the user says "stop", "cancel", or "abort"
|
|
124
|
-
- If requirements were too vague and expansion produces an unclear spec, pause and
|
|
142
|
+
- If requirements were too vague and expansion produces an unclear spec, pause and redirect to `$deep-interview` before proceeding
|
|
125
143
|
</Escalation_And_Stop_Conditions>
|
|
126
144
|
|
|
127
145
|
<Final_Checklist>
|
|
@@ -139,7 +157,7 @@ Why bad: This is an exploration/brainstorming request. Respond conversationally
|
|
|
139
157
|
Optional settings in `~/.codex/config.toml`:
|
|
140
158
|
|
|
141
159
|
```toml
|
|
142
|
-
[
|
|
160
|
+
[omx.autopilot]
|
|
143
161
|
maxIterations = 10
|
|
144
162
|
maxQaCycles = 5
|
|
145
163
|
maxValidationRounds = 3
|
|
@@ -153,6 +171,18 @@ skipValidation = false
|
|
|
153
171
|
|
|
154
172
|
If autopilot was cancelled or failed, run `/autopilot` again to resume from where it stopped.
|
|
155
173
|
|
|
174
|
+
## Recommended Clarity Pipeline
|
|
175
|
+
|
|
176
|
+
For ambiguous requests, prefer:
|
|
177
|
+
|
|
178
|
+
```
|
|
179
|
+
deep-interview -> ralplan -> autopilot
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
- `deep-interview`: ambiguity-gated Socratic requirements
|
|
183
|
+
- `ralplan`: consensus planning (planner/architect/critic)
|
|
184
|
+
- `autopilot`: execution + QA + validation
|
|
185
|
+
|
|
156
186
|
## Best Practices for Input
|
|
157
187
|
|
|
158
188
|
1. Be specific about the domain -- "bookstore" not "store"
|
|
@@ -172,7 +202,7 @@ RALPLAN (consensus planning) -> team-exec (Codex CLI workers) -> ralph-verify (a
|
|
|
172
202
|
Pipeline configuration options:
|
|
173
203
|
|
|
174
204
|
```toml
|
|
175
|
-
[
|
|
205
|
+
[omx.autopilot.pipeline]
|
|
176
206
|
maxRalphIterations = 10 # Ralph verification iteration ceiling
|
|
177
207
|
workerCount = 2 # Number of Codex CLI team workers
|
|
178
208
|
agentType = "executor" # Agent type for team workers
|
|
@@ -89,7 +89,7 @@ Then use AskUserQuestion:
|
|
|
89
89
|
1. **Discord** - Webhook or bot notifications to Discord channels
|
|
90
90
|
2. **Telegram** - Bot notifications to personal or group chats
|
|
91
91
|
3. **Slack** - Incoming webhook notifications to Slack channels
|
|
92
|
-
4. **OpenClaw** - Self-hosted
|
|
92
|
+
4. **OpenClaw** - Self-hosted gateway (`notifications.openclaw.gateways + hooks`) with /hooks/agent delivery verification
|
|
93
93
|
5. **Cross-cutting settings** - Verbosity, idle cooldown, profiles, reply listener
|
|
94
94
|
6. **Disable all notifications** - Turn off all notification dispatching
|
|
95
95
|
|