oh-my-opencode 4.13.0 → 4.14.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/.agents/skills/codex-qa/SKILL.md +15 -0
- package/.agents/skills/codex-qa/references/logging-debug.md +12 -0
- package/.agents/skills/opencode-qa/SKILL.md +17 -0
- package/.agents/skills/opencode-qa/references/tui-tmux.md +17 -0
- package/.agents/skills/work-with-pr/SKILL.md +18 -10
- package/.opencode/skills/work-with-pr/SKILL.md +18 -10
- package/README.md +2 -2
- package/dist/cli/doctor/checks/telemetry.d.ts +2 -0
- package/dist/cli/doctor/framework/constants.d.ts +1 -0
- package/dist/cli/doctor/framework/doctor-target.d.ts +1 -1
- package/dist/cli/index.js +24651 -16452
- package/dist/cli-node/index.js +24651 -16452
- package/dist/config/schema/oh-my-opencode-config.d.ts +1 -0
- package/dist/features/team-mode/test-support/async-test-helpers.d.ts +19 -0
- package/dist/hooks/atlas/final-wave-approval-gate.d.ts +1 -0
- package/dist/hooks/atlas/subagent-completion-reminder.d.ts +30 -0
- package/dist/hooks/atlas/types.d.ts +2 -0
- package/dist/hooks/atlas/verification-reminders.d.ts +3 -0
- package/dist/hooks/team-session-events/team-idle-wake-hint.d.ts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +33232 -19559
- package/dist/mcp/context7.d.ts +9 -8
- package/dist/oh-my-opencode.schema.json +4 -0
- package/dist/shared/posthog.d.ts +17 -10
- package/dist/shared/telemetry-product-identity.d.ts +2 -0
- package/dist/skills/coding-agent-sessions/SKILL.md +128 -0
- package/dist/skills/coding-agent-sessions/agents/openai.yaml +4 -0
- package/dist/skills/coding-agent-sessions/references/all-platforms.md +71 -0
- package/dist/skills/coding-agent-sessions/references/claude.md +32 -0
- package/dist/skills/coding-agent-sessions/references/codex.md +30 -0
- package/dist/skills/coding-agent-sessions/references/opencode.md +43 -0
- package/dist/skills/coding-agent-sessions/references/senpi.md +17 -0
- package/dist/skills/coding-agent-sessions/scripts/agent_sessions/__init__.py +1 -0
- package/dist/skills/coding-agent-sessions/scripts/agent_sessions/claude.py +66 -0
- package/dist/skills/coding-agent-sessions/scripts/agent_sessions/cli.py +283 -0
- package/dist/skills/coding-agent-sessions/scripts/agent_sessions/codex.py +105 -0
- package/dist/skills/coding-agent-sessions/scripts/agent_sessions/file_scanners.py +275 -0
- package/dist/skills/coding-agent-sessions/scripts/agent_sessions/jsonio.py +55 -0
- package/dist/skills/coding-agent-sessions/scripts/agent_sessions/kiro_scanner.py +91 -0
- package/dist/skills/coding-agent-sessions/scripts/agent_sessions/opencode.py +289 -0
- package/dist/skills/coding-agent-sessions/scripts/agent_sessions/scanners.py +92 -0
- package/dist/skills/coding-agent-sessions/scripts/agent_sessions/sqlite_optional_scanners.py +203 -0
- package/dist/skills/coding-agent-sessions/scripts/agent_sessions/sqlite_scanners.py +177 -0
- package/dist/skills/coding-agent-sessions/scripts/agent_sessions/timeparse.py +51 -0
- package/dist/skills/coding-agent-sessions/scripts/agent_sessions/transcript.py +149 -0
- package/dist/skills/coding-agent-sessions/scripts/agent_sessions/types.py +57 -0
- package/dist/skills/coding-agent-sessions/scripts/find-agent-sessions.py +19 -0
- package/dist/skills/frontend/ATTRIBUTION.md +52 -8
- package/dist/skills/frontend/SKILL.md +29 -8
- package/dist/skills/frontend/references/design/README.md +29 -12
- package/dist/skills/frontend/references/design/_INDEX.md +3 -3
- package/dist/skills/frontend/references/design/design-system-architecture.md +22 -19
- package/dist/skills/frontend/references/designpowers/EVIDENCE.md +89 -0
- package/dist/skills/frontend/references/designpowers/README.md +48 -0
- package/dist/skills/frontend/references/designpowers/UPSTREAM.md +80 -0
- package/dist/skills/frontend/references/designpowers/lane-a-direction.md +64 -0
- package/dist/skills/frontend/references/designpowers/lane-b-execution.md +65 -0
- package/dist/skills/frontend/references/designpowers/lane-c-review.md +65 -0
- package/dist/skills/frontend/references/designpowers/lane-d-memory.md +83 -0
- package/dist/skills/frontend/references/designpowers/orchestration.md +80 -0
- package/dist/skills/frontend/references/designpowers/routing.md +79 -0
- package/dist/skills/frontend/references/designpowers/vendor/LICENSE +21 -0
- package/dist/skills/frontend/references/designpowers/vendor/agents/accessibility-reviewer.md +83 -0
- package/dist/skills/frontend/references/designpowers/vendor/agents/content-writer.md +132 -0
- package/dist/skills/frontend/references/designpowers/vendor/agents/design-builder.md +109 -0
- package/dist/skills/frontend/references/designpowers/vendor/agents/design-critic.md +89 -0
- package/dist/skills/frontend/references/designpowers/vendor/agents/design-lead.md +113 -0
- package/dist/skills/frontend/references/designpowers/vendor/agents/design-scout.md +78 -0
- package/dist/skills/frontend/references/designpowers/vendor/agents/design-strategist.md +121 -0
- package/dist/skills/frontend/references/designpowers/vendor/agents/heuristic-evaluator.md +268 -0
- package/dist/skills/frontend/references/designpowers/vendor/agents/inspiration-scout.md +107 -0
- package/dist/skills/frontend/references/designpowers/vendor/agents/motion-designer.md +120 -0
- package/dist/skills/frontend/references/designpowers/vendor/skills/accessible-content/SKILL.md +101 -0
- package/dist/skills/frontend/references/designpowers/vendor/skills/adaptive-interfaces/SKILL.md +109 -0
- package/dist/skills/frontend/references/designpowers/vendor/skills/cognitive-accessibility/SKILL.md +107 -0
- package/dist/skills/frontend/references/designpowers/vendor/skills/design-debate/SKILL.md +199 -0
- package/dist/skills/frontend/references/designpowers/vendor/skills/design-debt-tracker/SKILL.md +174 -0
- package/dist/skills/frontend/references/designpowers/vendor/skills/design-handoff/SKILL.md +125 -0
- package/dist/skills/frontend/references/designpowers/vendor/skills/design-md/SKILL.md +106 -0
- package/dist/skills/frontend/references/designpowers/vendor/skills/design-retrospective/SKILL.md +266 -0
- package/dist/skills/frontend/references/designpowers/vendor/skills/design-review/SKILL.md +123 -0
- package/dist/skills/frontend/references/designpowers/vendor/skills/design-system-alignment/SKILL.md +120 -0
- package/dist/skills/frontend/references/designpowers/vendor/skills/designpowers-critique/SKILL.md +164 -0
- package/dist/skills/frontend/references/designpowers/vendor/skills/heuristic-evaluation/SKILL.md +85 -0
- package/dist/skills/frontend/references/designpowers/vendor/skills/inclusive-personas/SKILL.md +98 -0
- package/dist/skills/frontend/references/designpowers/vendor/skills/inspiration-scouting/SKILL.md +165 -0
- package/dist/skills/frontend/references/designpowers/vendor/skills/interaction-design/SKILL.md +122 -0
- package/dist/skills/frontend/references/designpowers/vendor/skills/motion-choreography/SKILL.md +81 -0
- package/dist/skills/frontend/references/designpowers/vendor/skills/research-planning/SKILL.md +96 -0
- package/dist/skills/frontend/references/designpowers/vendor/skills/responsive-patterns/SKILL.md +77 -0
- package/dist/skills/frontend/references/designpowers/vendor/skills/synthetic-user-testing/SKILL.md +192 -0
- package/dist/skills/frontend/references/designpowers/vendor/skills/taste-feedback/SKILL.md +165 -0
- package/dist/skills/frontend/references/designpowers/vendor/skills/taste-report/SKILL.md +78 -0
- package/dist/skills/frontend/references/designpowers/vendor/skills/token-architecture/SKILL.md +75 -0
- package/dist/skills/frontend/references/designpowers/vendor/skills/ui-composition/SKILL.md +117 -0
- package/dist/skills/frontend/references/designpowers/vendor/skills/usability-testing/SKILL.md +78 -0
- package/dist/skills/frontend/references/designpowers/vendor/skills/verification-before-shipping/SKILL.md +125 -0
- package/dist/skills/frontend/references/designpowers/vendor/skills/voice-and-tone/SKILL.md +79 -0
- package/dist/skills/frontend/references/designpowers/vendor/skills/writing-design-plans/SKILL.md +119 -0
- package/dist/skills/frontend/references/ui-ux-db/scripts/core.py +0 -0
- package/dist/skills/git-master/SKILL.md +4 -0
- package/dist/skills/review-work/SKILL.md +3 -3
- package/dist/skills/start-work/SKILL.md +7 -5
- package/dist/skills/ultraresearch/SKILL.md +4 -252
- package/dist/skills/ulw-plan/SKILL.md +8 -6
- package/dist/skills/ulw-plan/references/full-workflow.md +11 -6
- package/dist/skills/ulw-plan/references/intent-clear.md +3 -3
- package/dist/skills/ulw-plan/references/intent-unclear.md +1 -1
- package/dist/skills/{ultraresearch → ulw-research}/ATTRIBUTION.md +1 -1
- package/dist/skills/ulw-research/SKILL.md +260 -0
- package/dist/skills/visual-qa/SKILL.md +105 -14
- package/dist/skills/visual-qa/scripts/skill-prompt-contract.test.ts +120 -1
- package/dist/testing/create-plugin-module.d.ts +2 -0
- package/dist/tui.js +23917 -16117
- package/docs/reference/github-attachment-upload.md +51 -0
- package/docs/reference/web-terminal-visual-qa.md +81 -0
- package/package.json +20 -14
- package/packages/lsp-core/src/lsp/process.ts +4 -1
- package/packages/lsp-core/src/mcp.ts +1 -0
- package/packages/lsp-daemon/dist/cli.js +5 -1
- package/packages/lsp-daemon/dist/index.js +5 -1
- package/packages/lsp-daemon/dist/proxy.js +1 -0
- package/packages/lsp-tools-mcp/dist/cli.js +5 -1
- package/packages/lsp-tools-mcp/dist/lsp/manager.js +4 -1
- package/packages/lsp-tools-mcp/dist/mcp.js +5 -1
- package/packages/lsp-tools-mcp/dist/tools.js +4 -1
- package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +323 -62
- package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/scripts/bootstrap.ps1 +37 -68
- package/packages/omo-codex/plugin/components/bootstrap/scripts/node-dispatch.ps1 +75 -0
- package/packages/omo-codex/plugin/components/bootstrap/src/cli.ts +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/src/setup.ts +2 -18
- package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +575 -334
- package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +204 -39
- package/packages/omo-codex/plugin/components/codegraph/package.json +2 -2
- package/packages/omo-codex/plugin/components/codegraph/src/hook-types.ts +7 -1
- package/packages/omo-codex/plugin/components/codegraph/src/hook.ts +103 -3
- package/packages/omo-codex/plugin/components/codegraph/src/mcp-bridge.ts +114 -0
- package/packages/omo-codex/plugin/components/codegraph/src/serve-invocation.ts +29 -0
- package/packages/omo-codex/plugin/components/codegraph/src/serve.ts +31 -57
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker.ts +7 -4
- package/packages/omo-codex/plugin/components/codegraph/test/hook.test.ts +43 -9
- package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge.test.ts +146 -0
- package/packages/omo-codex/plugin/components/codegraph/test/serve.test.ts +12 -7
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-flow.test.ts +71 -1
- package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
- package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
- package/packages/omo-codex/plugin/components/lsp/dist/cli.js +4 -1
- package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
- package/packages/omo-codex/plugin/components/rules/dist/cli.js +2 -2
- package/packages/omo-codex/plugin/components/rules/package.json +1 -1
- package/packages/omo-codex/plugin/components/rules/src/sparkshell-awareness.ts +2 -2
- package/packages/omo-codex/plugin/components/rules/test/sparkshell-awareness.test.ts +11 -2
- package/packages/omo-codex/plugin/components/start-work-continuation/directive.md +6 -6
- package/packages/omo-codex/plugin/components/start-work-continuation/package.json +1 -1
- package/packages/omo-codex/plugin/components/start-work-continuation/test/codex-hook.test.ts +23 -0
- package/packages/omo-codex/plugin/components/teammode/dist/cli.js +22 -4
- package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/skills/teammode/SKILL.md +40 -2
- package/packages/omo-codex/plugin/components/teammode/skills/teammode/scripts/team-guide.mjs +32 -5
- package/packages/omo-codex/plugin/components/teammode/skills/teammode/scripts/team.mjs +7 -3
- package/packages/omo-codex/plugin/components/teammode/src/codex-hook.ts +19 -4
- package/packages/omo-codex/plugin/components/teammode/test/thread-title-hook.test.ts +32 -2
- package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/README.md +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/agents/explorer.toml +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/agents/plan.toml +2 -2
- package/packages/omo-codex/plugin/components/ultrawork/directive.md +23 -7
- package/packages/omo-codex/plugin/components/ultrawork/dist/cli.js +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +6 -4
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +11 -6
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-clear.md +3 -3
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-unclear.md +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/src/codex-hook.ts +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook-trigger-policy.test.ts +24 -0
- package/packages/omo-codex/plugin/components/ultrawork/test/package-smoke.test.ts +6 -1
- package/packages/omo-codex/plugin/components/ulw-loop/AGENTS.md +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/README.md +25 -21
- package/packages/omo-codex/plugin/components/ulw-loop/biome.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/directive.md +381 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-steering.js +14 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +145 -14
- package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-hook.d.ts +6 -3
- package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-hook.js +16 -6
- package/packages/omo-codex/plugin/components/ulw-loop/dist/ultrawork-directive.d.ts +5 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/ultrawork-directive.js +104 -0
- package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/package.json +2 -1
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +19 -11
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-steering.ts +14 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli.ts +4 -2
- package/packages/omo-codex/plugin/components/ulw-loop/src/codex-hook.ts +28 -6
- package/packages/omo-codex/plugin/components/ulw-loop/src/ultrawork-directive.ts +113 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-entrypoint.test.ts +33 -2
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-steering-kind-guidance.test.ts +31 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/codex-hook.test.ts +13 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/package-smoke.test.ts +36 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/skill-contract.test.ts +12 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/ultrawork-directive.test.ts +64 -0
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +2 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +2 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +2 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +2 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +2 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +2 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +2 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +2 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +2 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +2 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +2 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +2 -1
- package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +2 -1
- package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +2 -1
- package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +2 -1
- package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +2 -1
- package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +2 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +2 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +2 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +2 -1
- package/packages/omo-codex/plugin/package-lock.json +13 -13
- package/packages/omo-codex/plugin/package.json +1 -1
- package/packages/omo-codex/plugin/scripts/auto-update.mjs +9 -5
- package/packages/omo-codex/plugin/scripts/materialize-shared-upstreams.mjs +1 -0
- package/packages/omo-codex/plugin/scripts/migrate-codex-config/context7-placeholder-guard.mjs +131 -0
- package/packages/omo-codex/plugin/scripts/migrate-codex-config/multi-agent-mode-guard.mjs +60 -0
- package/packages/omo-codex/plugin/scripts/migrate-codex-config/multi-agent-v2-guard.mjs +3 -10
- package/packages/omo-codex/plugin/scripts/migrate-codex-config/root-settings.mjs +31 -1
- package/packages/omo-codex/plugin/scripts/migrate-codex-config/subagent-limit-guard.mjs +73 -0
- package/packages/omo-codex/plugin/scripts/migrate-codex-config.mjs +20 -3
- package/packages/omo-codex/plugin/scripts/sync-skills.mjs +30 -8
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/SKILL.md +128 -0
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/agents/openai.yaml +4 -0
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/all-platforms.md +71 -0
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/claude.md +32 -0
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/codex.md +30 -0
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/opencode.md +43 -0
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/senpi.md +17 -0
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/__init__.py +1 -0
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/claude.py +66 -0
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/cli.py +283 -0
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/codex.py +105 -0
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/file_scanners.py +275 -0
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/jsonio.py +55 -0
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/kiro_scanner.py +91 -0
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/opencode.py +289 -0
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/scanners.py +92 -0
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/sqlite_optional_scanners.py +203 -0
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/sqlite_scanners.py +177 -0
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/timeparse.py +51 -0
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/transcript.py +149 -0
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/types.py +57 -0
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/find-agent-sessions.py +19 -0
- package/packages/omo-codex/plugin/skills/frontend/ATTRIBUTION.md +52 -8
- package/packages/omo-codex/plugin/skills/frontend/SKILL.md +29 -8
- package/packages/omo-codex/plugin/skills/frontend/references/design/README.md +29 -12
- package/packages/omo-codex/plugin/skills/frontend/references/design/_INDEX.md +3 -3
- package/packages/omo-codex/plugin/skills/frontend/references/design/design-system-architecture.md +22 -19
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/EVIDENCE.md +89 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/README.md +48 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/UPSTREAM.md +80 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-a-direction.md +64 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-b-execution.md +65 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-c-review.md +65 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-d-memory.md +83 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/orchestration.md +80 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/routing.md +79 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/LICENSE +21 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/agents/accessibility-reviewer.md +83 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/agents/content-writer.md +132 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/agents/design-builder.md +109 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/agents/design-critic.md +89 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/agents/design-lead.md +113 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/agents/design-scout.md +78 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/agents/design-strategist.md +121 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/agents/heuristic-evaluator.md +268 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/agents/inspiration-scout.md +107 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/agents/motion-designer.md +120 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/accessible-content/SKILL.md +101 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/adaptive-interfaces/SKILL.md +109 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/cognitive-accessibility/SKILL.md +107 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/design-debate/SKILL.md +199 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/design-debt-tracker/SKILL.md +174 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/design-handoff/SKILL.md +125 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/design-md/SKILL.md +106 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/design-retrospective/SKILL.md +266 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/design-review/SKILL.md +123 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/design-system-alignment/SKILL.md +120 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/designpowers-critique/SKILL.md +164 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/heuristic-evaluation/SKILL.md +85 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/inclusive-personas/SKILL.md +98 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/inspiration-scouting/SKILL.md +165 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/interaction-design/SKILL.md +122 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/motion-choreography/SKILL.md +81 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/research-planning/SKILL.md +96 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/responsive-patterns/SKILL.md +77 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/synthetic-user-testing/SKILL.md +192 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/taste-feedback/SKILL.md +165 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/taste-report/SKILL.md +78 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/token-architecture/SKILL.md +75 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/ui-composition/SKILL.md +117 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/usability-testing/SKILL.md +78 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/verification-before-shipping/SKILL.md +125 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/voice-and-tone/SKILL.md +79 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/writing-design-plans/SKILL.md +119 -0
- package/packages/omo-codex/plugin/skills/frontend/references/ui-ux-db/scripts/core.py +0 -0
- package/packages/omo-codex/plugin/skills/git-master/SKILL.md +4 -0
- package/packages/omo-codex/plugin/skills/init-deep/SKILL.md +4 -0
- package/packages/omo-codex/plugin/skills/refactor/SKILL.md +4 -0
- package/packages/omo-codex/plugin/skills/remove-ai-slops/SKILL.md +4 -0
- package/packages/omo-codex/plugin/skills/review-work/SKILL.md +12 -4
- package/packages/omo-codex/plugin/skills/start-work/SKILL.md +14 -8
- package/packages/omo-codex/plugin/skills/teammode/SKILL.md +40 -2
- package/packages/omo-codex/plugin/skills/teammode/scripts/team-guide.mjs +32 -5
- package/packages/omo-codex/plugin/skills/teammode/scripts/team.mjs +7 -3
- package/packages/omo-codex/plugin/skills/ultraresearch/SKILL.md +4 -250
- package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +19 -11
- package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +6 -4
- package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +11 -6
- package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-clear.md +3 -3
- package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-unclear.md +1 -1
- package/packages/{shared-skills/skills/ultraresearch → omo-codex/plugin/skills/ulw-research}/ATTRIBUTION.md +1 -1
- package/packages/omo-codex/plugin/skills/ulw-research/SKILL.md +262 -0
- package/packages/omo-codex/plugin/skills/ulw-research/agents/openai.yaml +2 -0
- package/packages/omo-codex/plugin/skills/visual-qa/SKILL.md +109 -14
- package/packages/omo-codex/plugin/test/aggregate-hooks.test.mjs +23 -0
- package/packages/omo-codex/plugin/test/aggregate-manifest.test.mjs +1 -0
- package/packages/omo-codex/plugin/test/auto-update-release-notes.test.mjs +1 -0
- package/packages/omo-codex/plugin/test/auto-update-restart-notice.test.mjs +24 -1
- package/packages/omo-codex/plugin/test/bootstrap-binlinks.test.mjs +23 -5
- package/packages/omo-codex/plugin/test/bootstrap-hooks.test.mjs +38 -0
- package/packages/omo-codex/plugin/test/bootstrap-ps-guard.test.mjs +25 -0
- package/packages/omo-codex/plugin/test/bootstrap-setup.test.mjs +1 -7
- package/packages/omo-codex/plugin/test/migrate-codex-config.test.mjs +206 -6
- package/packages/omo-codex/plugin/test/subagent-limit-migration.test.mjs +44 -0
- package/packages/omo-codex/plugin/test/sync-skills-orchestration.test.mjs +50 -1
- package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +10 -7
- package/packages/omo-codex/plugin/test/sync-skills.test.mjs +28 -2
- package/packages/omo-codex/plugin/test/teammode-communication.test.mjs +20 -0
- package/packages/omo-codex/plugin/test/teammode-thread-links.test.mjs +117 -0
- package/packages/omo-codex/plugin/test/teammode-worktree.test.mjs +5 -2
- package/packages/omo-codex/plugin/test/ulw-research-skill-contract.test.mjs +285 -0
- package/packages/omo-codex/scripts/install-bin-links.test.mjs +6 -1
- package/packages/omo-codex/scripts/install-cache-copy.test.mjs +51 -0
- package/packages/omo-codex/scripts/install-config.test.mjs +198 -17
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +701 -282
- package/packages/omo-codex/scripts/install-local-git-bash-preflight.test.mjs +24 -15
- package/packages/omo-codex/scripts/install-local.test.mjs +5 -1
- package/packages/omo-codex/scripts/install-mcp-context7-runtime.test.mjs +84 -0
- package/packages/shared-skills/skills/coding-agent-sessions/SKILL.md +128 -0
- package/packages/shared-skills/skills/coding-agent-sessions/agents/openai.yaml +4 -0
- package/packages/shared-skills/skills/coding-agent-sessions/references/all-platforms.md +71 -0
- package/packages/shared-skills/skills/coding-agent-sessions/references/claude.md +32 -0
- package/packages/shared-skills/skills/coding-agent-sessions/references/codex.md +30 -0
- package/packages/shared-skills/skills/coding-agent-sessions/references/opencode.md +43 -0
- package/packages/shared-skills/skills/coding-agent-sessions/references/senpi.md +17 -0
- package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/__init__.py +1 -0
- package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/claude.py +66 -0
- package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/cli.py +283 -0
- package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/codex.py +105 -0
- package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/file_scanners.py +275 -0
- package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/jsonio.py +55 -0
- package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/kiro_scanner.py +91 -0
- package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/opencode.py +289 -0
- package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/scanners.py +92 -0
- package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/sqlite_optional_scanners.py +203 -0
- package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/sqlite_scanners.py +177 -0
- package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/timeparse.py +51 -0
- package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/transcript.py +149 -0
- package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/types.py +57 -0
- package/packages/shared-skills/skills/coding-agent-sessions/scripts/find-agent-sessions.py +19 -0
- package/packages/shared-skills/skills/frontend/ATTRIBUTION.md +52 -8
- package/packages/shared-skills/skills/frontend/SKILL.md +29 -8
- package/packages/shared-skills/skills/frontend/references/design/README.md +29 -12
- package/packages/shared-skills/skills/frontend/references/design/_INDEX.md +3 -3
- package/packages/shared-skills/skills/frontend/references/design/design-system-architecture.md +22 -19
- package/packages/shared-skills/skills/frontend/references/designpowers/EVIDENCE.md +89 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/README.md +48 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/UPSTREAM.md +80 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/lane-a-direction.md +64 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/lane-b-execution.md +65 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/lane-c-review.md +65 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/lane-d-memory.md +83 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/orchestration.md +80 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/routing.md +79 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/vendor/LICENSE +21 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/vendor/agents/accessibility-reviewer.md +83 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/vendor/agents/content-writer.md +132 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/vendor/agents/design-builder.md +109 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/vendor/agents/design-critic.md +89 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/vendor/agents/design-lead.md +113 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/vendor/agents/design-scout.md +78 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/vendor/agents/design-strategist.md +121 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/vendor/agents/heuristic-evaluator.md +268 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/vendor/agents/inspiration-scout.md +107 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/vendor/agents/motion-designer.md +120 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/accessible-content/SKILL.md +101 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/adaptive-interfaces/SKILL.md +109 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/cognitive-accessibility/SKILL.md +107 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/design-debate/SKILL.md +199 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/design-debt-tracker/SKILL.md +174 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/design-handoff/SKILL.md +125 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/design-md/SKILL.md +106 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/design-retrospective/SKILL.md +266 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/design-review/SKILL.md +123 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/design-system-alignment/SKILL.md +120 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/designpowers-critique/SKILL.md +164 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/heuristic-evaluation/SKILL.md +85 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/inclusive-personas/SKILL.md +98 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/inspiration-scouting/SKILL.md +165 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/interaction-design/SKILL.md +122 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/motion-choreography/SKILL.md +81 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/research-planning/SKILL.md +96 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/responsive-patterns/SKILL.md +77 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/synthetic-user-testing/SKILL.md +192 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/taste-feedback/SKILL.md +165 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/taste-report/SKILL.md +78 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/token-architecture/SKILL.md +75 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/ui-composition/SKILL.md +117 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/usability-testing/SKILL.md +78 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/verification-before-shipping/SKILL.md +125 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/voice-and-tone/SKILL.md +79 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/writing-design-plans/SKILL.md +119 -0
- package/packages/shared-skills/skills/frontend/references/ui-ux-db/scripts/core.py +0 -0
- package/packages/shared-skills/skills/git-master/SKILL.md +4 -0
- package/packages/shared-skills/skills/review-work/SKILL.md +3 -3
- package/packages/shared-skills/skills/start-work/SKILL.md +7 -5
- package/packages/shared-skills/skills/ultraresearch/SKILL.md +4 -252
- package/packages/shared-skills/skills/ulw-plan/SKILL.md +8 -6
- package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +11 -6
- package/packages/shared-skills/skills/ulw-plan/references/intent-clear.md +3 -3
- package/packages/shared-skills/skills/ulw-plan/references/intent-unclear.md +1 -1
- package/packages/{omo-codex/plugin/skills/ultraresearch → shared-skills/skills/ulw-research}/ATTRIBUTION.md +1 -1
- package/packages/shared-skills/skills/ulw-research/SKILL.md +260 -0
- package/packages/shared-skills/skills/visual-qa/SKILL.md +105 -14
- package/packages/shared-skills/skills/visual-qa/scripts/skill-prompt-contract.test.ts +120 -1
- package/script/qa/web-terminal-redaction.d.mts +13 -0
- package/script/qa/web-terminal-redaction.mjs +43 -0
- package/script/qa/web-terminal-renderer.mjs +218 -0
- package/script/qa/web-terminal-visual-qa.mjs +264 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/scripts/tests/test_cookie_domain_filter.py +0 -110
- package/packages/omo-codex/plugin/skills/ultimate-browsing/scripts/tests/test_extract_cookies.py +0 -245
- package/packages/omo-codex/plugin/test/ultraresearch-skill-contract.test.mjs +0 -204
|
@@ -5,9 +5,12 @@ export interface UserPromptSubmitPayload {
|
|
|
5
5
|
readonly permission_mode?: string;
|
|
6
6
|
readonly prompt: string;
|
|
7
7
|
readonly session_id: string;
|
|
8
|
-
readonly transcript_path?: string;
|
|
8
|
+
readonly transcript_path?: string | null;
|
|
9
9
|
readonly turn_id?: string;
|
|
10
10
|
}
|
|
11
|
+
export interface UserPromptSubmitHookOptions {
|
|
12
|
+
readonly includeUltraworkDirective?: boolean;
|
|
13
|
+
}
|
|
11
14
|
export interface PreToolUsePayload {
|
|
12
15
|
readonly cwd: string;
|
|
13
16
|
readonly hook_event_name: "PreToolUse";
|
|
@@ -22,7 +25,7 @@ export interface PreToolUsePayload {
|
|
|
22
25
|
}
|
|
23
26
|
export declare function parseUserPromptSubmitPayload(raw: string): UserPromptSubmitPayload | null;
|
|
24
27
|
export declare function parsePreToolUsePayload(raw: string): PreToolUsePayload | null;
|
|
25
|
-
export declare function applyUserPromptUlwLoopSteering(payload: UserPromptSubmitPayload): Promise<string>;
|
|
28
|
+
export declare function applyUserPromptUlwLoopSteering(payload: UserPromptSubmitPayload, options?: UserPromptSubmitHookOptions): Promise<string>;
|
|
26
29
|
export declare function applyPreToolUseGoalBudgetGuard(payload: PreToolUsePayload): string;
|
|
27
|
-
export declare function runUlwLoopHookCli(stdin: NodeJS.ReadableStream, stdout: NodeJS.WritableStream): Promise<void>;
|
|
30
|
+
export declare function runUlwLoopHookCli(stdin: NodeJS.ReadableStream, stdout: NodeJS.WritableStream, options?: UserPromptSubmitHookOptions): Promise<void>;
|
|
28
31
|
export declare function runPreToolUseGoalBudgetGuardCli(stdin: NodeJS.ReadableStream, stdout: NodeJS.WritableStream): Promise<void>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { parseUlwLoopSteeringDirective, steerUlwLoop } from "./steering.js";
|
|
2
|
+
import { buildUltraworkDirectiveOutput } from "./ultrawork-directive.js";
|
|
2
3
|
const CREATE_GOAL_TOOL_NAME = "create_goal";
|
|
3
4
|
const CREATE_GOAL_PAYLOAD_WARNING = "Use create_goal with objective only. Omit token_budget so the goal stays unlimited, and put lifecycle status changes on update_goal.";
|
|
4
5
|
export function parseUserPromptSubmitPayload(raw) {
|
|
@@ -27,13 +28,16 @@ export function parsePreToolUsePayload(raw) {
|
|
|
27
28
|
return null;
|
|
28
29
|
}
|
|
29
30
|
}
|
|
30
|
-
export async function applyUserPromptUlwLoopSteering(payload) {
|
|
31
|
+
export async function applyUserPromptUlwLoopSteering(payload, options = {}) {
|
|
31
32
|
try {
|
|
32
33
|
if (payload.hook_event_name !== "UserPromptSubmit")
|
|
33
34
|
return "";
|
|
34
35
|
const proposal = parseUlwLoopSteeringDirective(payload.prompt);
|
|
35
|
-
if (proposal === null)
|
|
36
|
-
|
|
36
|
+
if (proposal === null) {
|
|
37
|
+
if (hasSteeringDirectiveMarker(payload.prompt))
|
|
38
|
+
return "";
|
|
39
|
+
return options.includeUltraworkDirective ? buildUltraworkDirectiveOutput(payload) : "";
|
|
40
|
+
}
|
|
37
41
|
const result = await steerUlwLoop(payload.cwd, proposal, payloadScope(payload));
|
|
38
42
|
if (!result.accepted)
|
|
39
43
|
return "";
|
|
@@ -50,6 +54,9 @@ export async function applyUserPromptUlwLoopSteering(payload) {
|
|
|
50
54
|
return "";
|
|
51
55
|
}
|
|
52
56
|
}
|
|
57
|
+
function hasSteeringDirectiveMarker(prompt) {
|
|
58
|
+
return /(?:^|\s)(?:OMO_ULW_LOOP_STEER|omo\.ulw-loop\.steer|omo ulw-loop steer):/u.test(prompt);
|
|
59
|
+
}
|
|
53
60
|
function payloadScope(payload) {
|
|
54
61
|
return { sessionId: payload.session_id };
|
|
55
62
|
}
|
|
@@ -70,12 +77,12 @@ export function applyPreToolUseGoalBudgetGuard(payload) {
|
|
|
70
77
|
};
|
|
71
78
|
return `${JSON.stringify(output)}\n`;
|
|
72
79
|
}
|
|
73
|
-
export async function runUlwLoopHookCli(stdin, stdout) {
|
|
80
|
+
export async function runUlwLoopHookCli(stdin, stdout, options = {}) {
|
|
74
81
|
try {
|
|
75
82
|
const payload = parseUserPromptSubmitPayload(await readAll(stdin));
|
|
76
83
|
if (payload === null)
|
|
77
84
|
return;
|
|
78
|
-
const output = await applyUserPromptUlwLoopSteering(payload);
|
|
85
|
+
const output = await applyUserPromptUlwLoopSteering(payload, options);
|
|
79
86
|
if (output.length > 0)
|
|
80
87
|
stdout.write(output);
|
|
81
88
|
}
|
|
@@ -107,7 +114,10 @@ function isUserPromptSubmitPayload(value) {
|
|
|
107
114
|
typeof value["cwd"] === "string" &&
|
|
108
115
|
typeof value["prompt"] === "string" &&
|
|
109
116
|
typeof value["session_id"] === "string" &&
|
|
110
|
-
["model", "permission_mode", "
|
|
117
|
+
["model", "permission_mode", "turn_id"].every((key) => optionalString(value[key])) &&
|
|
118
|
+
(value["transcript_path"] === undefined ||
|
|
119
|
+
value["transcript_path"] === null ||
|
|
120
|
+
typeof value["transcript_path"] === "string"));
|
|
111
121
|
}
|
|
112
122
|
function isPreToolUsePayload(value) {
|
|
113
123
|
if (!isRecord(value))
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
const ULTRAWORK_DIRECTIVE = readFileSync(new URL("../directive.md", import.meta.url), "utf8");
|
|
3
|
+
const ULTRAWORK_CURRENT_PROMPT_PATTERN = /(?:ultrawork|ulw)/i;
|
|
4
|
+
const ULTRAWORK_DIRECTIVE_MARKER = "<ultrawork-mode>";
|
|
5
|
+
const TRANSCRIPT_SEARCH_BYTES = 512_000;
|
|
6
|
+
const CONTEXT_PRESSURE_MARKERS = [
|
|
7
|
+
"context compacted",
|
|
8
|
+
"context_length_exceeded",
|
|
9
|
+
"skill descriptions were shortened",
|
|
10
|
+
"context_too_large",
|
|
11
|
+
"codex ran out of room in the model's context window",
|
|
12
|
+
"your input exceeds the context window",
|
|
13
|
+
"long threads and multiple compactions",
|
|
14
|
+
];
|
|
15
|
+
export function buildUltraworkDirectiveOutput(input) {
|
|
16
|
+
if (isContextPressureRecoveryPrompt(input.prompt))
|
|
17
|
+
return "";
|
|
18
|
+
if (hasUltraworkDirectiveAlreadyInTranscript(input.transcript_path))
|
|
19
|
+
return "";
|
|
20
|
+
if (isContextPressureTranscript(input.transcript_path))
|
|
21
|
+
return "";
|
|
22
|
+
return isUltraworkPrompt(input.prompt) ? formatAdditionalContextOutput(ULTRAWORK_DIRECTIVE) : "";
|
|
23
|
+
}
|
|
24
|
+
function hasUltraworkDirectiveAlreadyInTranscript(transcriptPath) {
|
|
25
|
+
if (transcriptPath === undefined || transcriptPath === null)
|
|
26
|
+
return false;
|
|
27
|
+
try {
|
|
28
|
+
const rawTranscript = readTranscriptTail(transcriptPath);
|
|
29
|
+
for (const line of rawTranscript.split(/\r?\n/)) {
|
|
30
|
+
const parsed = parseJsonLine(line);
|
|
31
|
+
if (!isRecord(parsed))
|
|
32
|
+
continue;
|
|
33
|
+
const hookSpecificOutput = parsed["hookSpecificOutput"];
|
|
34
|
+
if (!isRecord(hookSpecificOutput))
|
|
35
|
+
continue;
|
|
36
|
+
if (hookSpecificOutput["hookEventName"] !== "UserPromptSubmit")
|
|
37
|
+
continue;
|
|
38
|
+
if (typeof hookSpecificOutput["additionalContext"] === "string" &&
|
|
39
|
+
hookSpecificOutput["additionalContext"].includes(ULTRAWORK_DIRECTIVE_MARKER)) {
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
if (error instanceof Error)
|
|
46
|
+
return false;
|
|
47
|
+
throw error;
|
|
48
|
+
}
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
function readTranscriptTail(transcriptPath) {
|
|
52
|
+
const rawTranscript = readFileSync(transcriptPath);
|
|
53
|
+
return rawTranscript.subarray(Math.max(0, rawTranscript.byteLength - TRANSCRIPT_SEARCH_BYTES)).toString("utf8");
|
|
54
|
+
}
|
|
55
|
+
function isUltraworkPrompt(prompt) {
|
|
56
|
+
return ULTRAWORK_CURRENT_PROMPT_PATTERN.test(prompt);
|
|
57
|
+
}
|
|
58
|
+
function isContextPressureRecoveryPrompt(prompt) {
|
|
59
|
+
const normalizedPrompt = prompt.toLowerCase();
|
|
60
|
+
return CONTEXT_PRESSURE_MARKERS.some((marker) => normalizedPrompt.includes(marker));
|
|
61
|
+
}
|
|
62
|
+
function isContextPressureTranscript(transcriptPath) {
|
|
63
|
+
if (transcriptPath === undefined || transcriptPath === null)
|
|
64
|
+
return false;
|
|
65
|
+
try {
|
|
66
|
+
return isContextPressureRecoveryPrompt(readTranscriptTail(transcriptPath));
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
if (error instanceof Error)
|
|
70
|
+
return false;
|
|
71
|
+
throw error;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
function formatAdditionalContextOutput(additionalContext) {
|
|
75
|
+
const normalizedContext = normalizeAdditionalContext(additionalContext);
|
|
76
|
+
if (normalizedContext.length === 0)
|
|
77
|
+
return "";
|
|
78
|
+
const output = {
|
|
79
|
+
hookSpecificOutput: {
|
|
80
|
+
hookEventName: "UserPromptSubmit",
|
|
81
|
+
additionalContext: normalizedContext,
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
return `${JSON.stringify(output)}\n`;
|
|
85
|
+
}
|
|
86
|
+
function normalizeAdditionalContext(additionalContext) {
|
|
87
|
+
return additionalContext.replace(/\r\n/g, "\n").replace(/\r/g, "\n").trim();
|
|
88
|
+
}
|
|
89
|
+
function parseJsonLine(line) {
|
|
90
|
+
if (line.trim().length === 0)
|
|
91
|
+
return null;
|
|
92
|
+
try {
|
|
93
|
+
const parsed = JSON.parse(line);
|
|
94
|
+
return parsed;
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
if (error instanceof Error)
|
|
98
|
+
return null;
|
|
99
|
+
throw error;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
function isRecord(value) {
|
|
103
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
104
|
+
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"hooks": [
|
|
6
6
|
{
|
|
7
7
|
"type": "command",
|
|
8
|
-
"command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook user-prompt-submit",
|
|
8
|
+
"command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook user-prompt-submit --with-ultrawork",
|
|
9
9
|
"timeout": 10,
|
|
10
10
|
"statusMessage": "(OmO) Checking Ulw-Loop Steering"
|
|
11
11
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@code-yeongyu/codex-ulw-loop",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.14.0",
|
|
4
4
|
"description": "Codex plugin: durable repo-native multi-goal orchestration with embedded success criteria and observable evidence audit.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"packageManager": "npm@11.12.1",
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
},
|
|
28
28
|
"files": [
|
|
29
29
|
"dist",
|
|
30
|
+
"directive.md",
|
|
30
31
|
"hooks",
|
|
31
32
|
"skills",
|
|
32
33
|
"LICENSE",
|
package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md
CHANGED
|
@@ -6,12 +6,12 @@ metadata:
|
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
## Role
|
|
9
|
-
Expert goal orchestration agent. You conduct; right-sized
|
|
9
|
+
Expert goal orchestration agent. You conduct; right-sized subagents play. Plan durable multi-goal work, fan independent work out, QA every result yourself, record only proven evidence.
|
|
10
10
|
Use GPT-5.x style: outcome-first, evidence-bound, atomic decisions, no nested branching prose.
|
|
11
11
|
|
|
12
12
|
## Goal
|
|
13
13
|
Deliver every goal in `.omo/ulw-loop/goals.json` end-to-end.
|
|
14
|
-
Prove EVERY success criterion with captured observable evidence from a real-usage scenario you
|
|
14
|
+
Prove EVERY success criterion with captured observable evidence from a real-usage scenario you ran (HTTP / tmux / browser / computer-use below).
|
|
15
15
|
TESTS ALONE NEVER PROVE DONE. A green test suite is supporting evidence, not completion proof.
|
|
16
16
|
Audit each pass, fail, block, steering change, and checkpoint in `.omo/ulw-loop/ledger.jsonl`.
|
|
17
17
|
|
|
@@ -20,8 +20,15 @@ Run each criterion's real-surface proof yourself through the channel that faithf
|
|
|
20
20
|
|
|
21
21
|
1. **HTTP call** — hit the live endpoint with `curl -i` (or a Playwright APIRequestContext); capture status line + headers + body.
|
|
22
22
|
2. **tmux** — `tmux new-session -d -s ulw-qa-<criterion>`, drive with `send-keys`, dump via `tmux capture-pane -pS -E -`; transcript is the artifact.
|
|
23
|
-
3. **Browser use** — use Chrome to drive the REAL page; if
|
|
24
|
-
4. **Computer use** —
|
|
23
|
+
3. **Browser use** — in Codex, use `browser:control-in-app-browser` first when available and the scenario does not need an authenticated or persistent user browser profile. Otherwise use Chrome to drive the REAL page; if unavailable, use agent-browser. Capture action log + screenshot path. Never downgrade a browser-facing criterion.
|
|
24
|
+
4. **Computer use** — for desktop/GUI apps, drive the running app via OS automation (computer-use, AppleScript, xdotool, etc.); capture action log + screenshot.
|
|
25
|
+
|
|
26
|
+
For TUI visual QA, pair the tmux transcript with a browser-rendered terminal
|
|
27
|
+
screenshot. In this repo run `node script/qa/web-terminal-visual-qa.mjs
|
|
28
|
+
--from-file <capture.txt> --evidence-dir <dir>` and record `terminal.png`,
|
|
29
|
+
`terminal.html`, `terminal.txt`, and `metadata.json` as the visual evidence
|
|
30
|
+
bundle. This is mandatory when a PR or review needs to inspect the terminal
|
|
31
|
+
screen, not just the text.
|
|
25
32
|
|
|
26
33
|
Auxiliary surfaces (CLI stdout / DB state diff / parsed config dump) are first-class evidence for CLI- or data-shaped criteria; use a channel scenario when the behavior is user-facing. `--dry-run`, printing the command, "should respond", and "looks correct" never count.
|
|
27
34
|
|
|
@@ -42,7 +49,7 @@ Size each worker to the task. Put the intended role, rigor level, and specialty
|
|
|
42
49
|
|
|
43
50
|
For reviewer work, use a self-contained reviewer assignment, tight scope, and explicit verification in `message`. Never spawn a context-only child for review.
|
|
44
51
|
|
|
45
|
-
Every worker message MUST carry: goal + exact files in scope; the PIN + failing-first proof
|
|
52
|
+
Every worker message MUST carry: goal + exact files in scope; the PIN + failing-first proof before production code; constraints + project rules; verification commands; the ONE Manual-QA channel and exact artifact; for git-tracked edits, require `git-master` plus repo and touched-path commit history before commit. Workers have NO interview context — be exhaustive, and forward learnings.
|
|
46
53
|
|
|
47
54
|
Codex subagent reliability:
|
|
48
55
|
- Start every `multi_agent_v1.spawn_agent` message with `TASK: <imperative assignment>`, then name `DELIVERABLE`, `SCOPE`, and `VERIFY`. State that it is an executable assignment, not a context handoff.
|
|
@@ -58,7 +65,7 @@ Codex subagent reliability:
|
|
|
58
65
|
- `.omo/ulw-loop/goals.json`: goals with embedded `successCriteria` per goal.
|
|
59
66
|
- `.omo/ulw-loop/ledger.jsonl`: append-only audit trail.
|
|
60
67
|
- Read artifacts before resuming, steering, or checkpointing.
|
|
61
|
-
- After
|
|
68
|
+
- After compaction or context loss, re-read brief + goals + ledger FIRST via `omo sparkshell cat .omo/ulw-loop/ledger.jsonl` (or direct paths), then `omo ulw-loop status --json`. Recover from artifacts; never re-plan from scratch or repeat completed work.
|
|
62
69
|
- Never invent state outside `.omo/ulw-loop` artifacts or `omo ulw-loop status --json`.
|
|
63
70
|
|
|
64
71
|
## Bootstrap
|
|
@@ -116,14 +123,15 @@ only when deliberately overwriting completed evidence.
|
|
|
116
123
|
Write state through the CLI path. Do not hand-edit state files.
|
|
117
124
|
|
|
118
125
|
### 2. Refine success criteria + a Prometheus-grade QA and parallelism plan per goal
|
|
119
|
-
Gather context BEFORE planning
|
|
126
|
+
Gather context BEFORE planning with parallel `explorer` / `librarian` workers plus your own read-only tools.
|
|
120
127
|
First survey available skills: read every loosely-relevant skill's description, deliberately choose which this work uses, and prefer applying genuinely-relevant skills over working raw.
|
|
121
128
|
Then run tier triage per goal — rigor (LIGHT/HEAVY below) and shape (`delivery` default, or `research` when the deliverable is a cited answer, not an artifact) — and record both in an `annotate_ledger` steering entry. Default is LIGHT — a narrow change inside existing layers. Take HEAVY only on a fact you can point to: a new module / abstraction / domain model; auth, security, or session; an external integration; a DB schema or migration; concurrency, transaction boundaries, or cache invalidation; a cross-domain refactor; or the user signaled care or demanded review. When unsure, take HEAVY; upgrade the moment a HEAVY fact surfaces, never downgrade mid-run.
|
|
122
129
|
HEAVY goals: spawn the `plan` agent with the gathered context, follow its wave ordering and parallel grouping exactly, and run the verification it specifies; carry 3+ successCriteria covering happy path, edge, regression, and adversarial risk. LIGHT goals: plan directly; carry 1-2 successCriteria (happy path + the riskiest edge) with one real-surface proof of the deliverable.
|
|
123
|
-
Research-shape goals change the cycle: BEFORE each investigation, read this goal's prior ledger findings and open hypotheses, then extend them — never re-investigate an answered question (the ledger is your research notebook). Record findings via `annotate_ledger` with their source (`file:line`, command output, doc URL) as `--evidence`. Track hypotheses as `HYPOTHESIS[id]: <claim> | status: open`, flipped to `confirmed`/`refuted` only on an observed source. A research criterion passes on a cited answer — skip QA-channel, cleanup, and commit, but keep source-observability (never "looks correct"). Keep hypotheses inside the user's stated question; a scope-widening one is an `add_subgoal` proposal you surface, never silent creep. For a `research`-shape goal you MAY load `ultraresearch` without hesitation — otherwise explicit-request-only, a research-shape goal IS that explicit demand. Research-only: never for a `delivery` goal. It composes with the librarian routing above — `
|
|
124
|
-
For each criterion
|
|
130
|
+
Research-shape goals change the cycle: BEFORE each investigation, read this goal's prior ledger findings and open hypotheses, then extend them — never re-investigate an answered question (the ledger is your research notebook). Record findings via `annotate_ledger` with their source (`file:line`, command output, doc URL) as `--evidence`. Track hypotheses as `HYPOTHESIS[id]: <claim> | status: open`, flipped to `confirmed`/`refuted` only on an observed source. A research criterion passes on a cited answer — skip QA-channel, cleanup, and commit, but keep source-observability (never "looks correct"). Keep hypotheses inside the user's stated question; a scope-widening one is an `add_subgoal` proposal you surface, never silent creep. For a `research`-shape goal you MAY load `ulw-research` (legacy alias: `ultraresearch`) without hesitation — otherwise explicit-request-only, a research-shape goal IS that explicit demand. Research-only: never for a `delivery` goal. It composes with the librarian routing above — `ulw-research` for saturation (many parallel sources, recursive expansion), a single `librarian` for one lookup.
|
|
131
|
+
For each criterion, define upfront: `id`, exact `scenario` (tool + inputs + binary pass/fail), `expectedEvidence` artifact path, adversarial classes, stop condition, and Manual-QA channel. Vague QA ("verify it works") is a rejected criterion — revise it before execution.
|
|
132
|
+
For optimization work, capture baseline speed before changes plus behavior/regression proof. Every attempt records speed, behavior/regression, and the keep/revert/iterate decision.
|
|
125
133
|
A criterion's adversarial classes are the ultraqa classes a fact about the change triggers: malformed input, prompt injection, cancel/resume, stale state, dirty worktree, hung or long commands, flaky tests, misleading success output, repeated interruptions. Record untriggered classes as not-applicable in one line.
|
|
126
|
-
Use evidence verbs
|
|
134
|
+
Use channel-table evidence verbs (tmux transcript, curl status+body, screenshot, action log, CLI stdout, DB diff, parsed config dump) — not vibes.
|
|
127
135
|
|
|
128
136
|
**Plan for maximum parallelism (HEAVY goals).** Decompose each goal's criteria into atomic tasks (Implementation + its Test = ONE task, never split) and group them into dependency waves. Target 5–8 tasks per wave; <3 per wave (except the final wave) means under-splitting — extract shared prerequisites into Wave 1. For each task record its wave, what it blocks, what blocks it, the worker tier from the Delegation table, and its QA scenario + evidence path. Build a dependency matrix (Task | Depends on | Blocks | Can parallelize with) and name the critical path. Anything not on a real dependency edge MUST share a wave and dispatch together.
|
|
129
137
|
Revise any criterion that lacks observable `expectedEvidence` or a named channel before execution.
|
|
@@ -220,7 +228,7 @@ Structured prompt directives accepted: `OMO_ULW_LOOP_STEER: { ... }`, `omo.ulw-l
|
|
|
220
228
|
6. Treat `.omo/ulw-loop/ledger.jsonl` as the durable audit trail; checkpoint after every success or failure.
|
|
221
229
|
7. Per-story Codex goal mode is opt-in only with `--codex-goal-mode per-story`; default is aggregate.
|
|
222
230
|
8. Structured steering directives mutate state through validation; normal prose does not.
|
|
223
|
-
9. Evidence MUST be observable from the real surface: tmux transcript, curl status+body, browser/Playwright assertion, CLI stdout, DB state diff, parsed config dump.
|
|
231
|
+
9. Evidence MUST be observable from the real surface: tmux transcript, curl status+body, Browser plugin action result or browser/Playwright assertion, CLI stdout, DB state diff, parsed config dump.
|
|
224
232
|
10. Probe the adversarial classes each criterion's trigger facts name (list in Bootstrap step 2); record untriggered classes as not-applicable in one line.
|
|
225
233
|
11. After completing an aggregate ulw-loop run, clear the Codex goal manually with `/goal clear` before starting another in the same session.
|
|
226
234
|
12. The shell command emits a model-facing handoff; only the Codex agent calls `get_goal`, `create_goal`, or `update_goal` tools.
|
|
@@ -5,6 +5,18 @@ import type { SteerUlwLoopResult, UlwLoopSteeringChildGoal, UlwLoopSteeringMutat
|
|
|
5
5
|
import { ULW_LOOP_STEERING_MUTATION_KINDS, ULW_LOOP_SUCCESS_CRITERION_USER_MODELS, UlwLoopError } from "./types.js";
|
|
6
6
|
|
|
7
7
|
const SOURCES = ["user_prompt_submit", "finding", "cli"] as const satisfies readonly UlwLoopSteeringSource[];
|
|
8
|
+
const STEERING_KIND_HELP = [
|
|
9
|
+
`Allowed --kind values: ${ULW_LOOP_STEERING_MUTATION_KINDS.join(", ")}`,
|
|
10
|
+
"Kind-specific required flags:",
|
|
11
|
+
" add_subgoal: --title, --objective, --evidence, --rationale",
|
|
12
|
+
" split_subgoal: --goal-id, --children, --evidence, --rationale",
|
|
13
|
+
" reorder_pending: --order, --evidence, --rationale",
|
|
14
|
+
" revise_pending_wording: --goal-id, --title or --objective, --evidence, --rationale",
|
|
15
|
+
" revise_criterion: --goal-id, --criterion-id, one of --scenario/--expected-evidence/--user-model, --evidence, --rationale",
|
|
16
|
+
" annotate_ledger: --evidence, --rationale",
|
|
17
|
+
" mark_blocked_superseded: --goal-id, optional --replacements, --evidence, --rationale",
|
|
18
|
+
"Example: omo ulw-loop steer --kind annotate_ledger --evidence \"observed behavior\" --rationale \"why this changes the plan\" --json",
|
|
19
|
+
].join("\n");
|
|
8
20
|
|
|
9
21
|
export type CliSteeringProposal = UlwLoopSteeringProposal & { readonly goalId?: string; readonly scenario?: string; readonly expectedEvidence?: string; readonly userModel?: UlwLoopSuccessCriterionUserModel };
|
|
10
22
|
|
|
@@ -12,6 +24,7 @@ function isKind(value: string | undefined): value is UlwLoopSteeringMutationKind
|
|
|
12
24
|
function isSource(value: string | undefined): value is UlwLoopSteeringSource { return value !== undefined && SOURCES.some((source) => source === value); }
|
|
13
25
|
function isModel(value: string): value is UlwLoopSuccessCriterionUserModel { return ULW_LOOP_SUCCESS_CRITERION_USER_MODELS.some((model) => model === value); }
|
|
14
26
|
function fail(message: string, code: string, details: Record<string, unknown>): never { throw new UlwLoopError(message, code, { details }); }
|
|
27
|
+
function kindMessage(prefix: string): string { return `${prefix}\n\n${STEERING_KIND_HELP}`; }
|
|
15
28
|
function text(value: string | undefined, field: string): string | undefined { if (value === undefined) return undefined; const trimmed = value.trim(); if (trimmed.length > 0) return trimmed; return fail(`Empty ${field}.`, "ULW_LOOP_STEERING_FIELD_EMPTY", { field }); }
|
|
16
29
|
function required(argv: readonly string[], flag: string): string { const value = text(readValue(argv, flag), flag); return value ?? fail(`Missing ${flag}.`, "ULW_LOOP_STEERING_FIELD_REQUIRED", { flag }); }
|
|
17
30
|
function requiredGoal(argv: readonly string[]): string { const value = text(parseGoalArg(argv), "--goal-id"); return value ?? fail("Missing --goal-id.", "ULW_LOOP_GOAL_ID_REQUIRED", { flag: "--goal-id" }); }
|
|
@@ -22,7 +35,7 @@ function objectText(value: object, key: string): string | undefined { const cand
|
|
|
22
35
|
export function parseSteeringKind(argv: readonly string[]): UlwLoopSteeringMutationKind {
|
|
23
36
|
const value = readValue(argv, "--kind");
|
|
24
37
|
if (isKind(value)) return value;
|
|
25
|
-
return value === undefined ? fail("Missing --kind.", "ULW_LOOP_STEERING_KIND_REQUIRED", { flag: "--kind" }) : fail(`Invalid --kind: ${value}
|
|
38
|
+
return value === undefined ? fail(kindMessage("Missing --kind."), "ULW_LOOP_STEERING_KIND_REQUIRED", { flag: "--kind", expected: ULW_LOOP_STEERING_MUTATION_KINDS, usage: STEERING_KIND_HELP }) : fail(kindMessage(`Invalid --kind: ${value}.`), "ULW_LOOP_STEERING_KIND_INVALID", { value, expected: ULW_LOOP_STEERING_MUTATION_KINDS, usage: STEERING_KIND_HELP });
|
|
26
39
|
}
|
|
27
40
|
|
|
28
41
|
export function parseSteeringSource(argv: readonly string[]): UlwLoopSteeringSource {
|
|
@@ -3,7 +3,7 @@ import { isUlwLoopSubcommand, ulwLoopCommand } from "./cli-commands.js";
|
|
|
3
3
|
import { runPreToolUseGoalBudgetGuardCli, runUlwLoopHookCli } from "./codex-hook.js";
|
|
4
4
|
|
|
5
5
|
const TOP_LEVEL_HELP =
|
|
6
|
-
"Usage:\n omo ulw-loop <subcommand> [args]\n omo hook user-prompt-submit
|
|
6
|
+
"Usage:\n omo ulw-loop <subcommand> [args]\n omo hook user-prompt-submit [--with-ultrawork] (Codex UserPromptSubmit hook)\n omo help | --help | -h (this message)\n\nRun `omo ulw-loop help` for ulw-loop subcommands.\n";
|
|
7
7
|
|
|
8
8
|
async function main(): Promise<number> {
|
|
9
9
|
const argv = process.argv.slice(2);
|
|
@@ -16,7 +16,9 @@ async function main(): Promise<number> {
|
|
|
16
16
|
if (command === "hook") {
|
|
17
17
|
const sub = argv[1];
|
|
18
18
|
if (sub === "user-prompt-submit") {
|
|
19
|
-
await runUlwLoopHookCli(process.stdin, process.stdout
|
|
19
|
+
await runUlwLoopHookCli(process.stdin, process.stdout, {
|
|
20
|
+
includeUltraworkDirective: argv.includes("--with-ultrawork"),
|
|
21
|
+
});
|
|
20
22
|
return 0;
|
|
21
23
|
}
|
|
22
24
|
if (sub === "pre-tool-use") {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { UlwLoopScope } from "./paths.js";
|
|
2
2
|
import { parseUlwLoopSteeringDirective, steerUlwLoop } from "./steering.js";
|
|
3
|
+
import { buildUltraworkDirectiveOutput } from "./ultrawork-directive.js";
|
|
3
4
|
|
|
4
5
|
export interface UserPromptSubmitPayload {
|
|
5
6
|
readonly cwd: string;
|
|
@@ -8,10 +9,14 @@ export interface UserPromptSubmitPayload {
|
|
|
8
9
|
readonly permission_mode?: string;
|
|
9
10
|
readonly prompt: string;
|
|
10
11
|
readonly session_id: string;
|
|
11
|
-
readonly transcript_path?: string;
|
|
12
|
+
readonly transcript_path?: string | null;
|
|
12
13
|
readonly turn_id?: string;
|
|
13
14
|
}
|
|
14
15
|
|
|
16
|
+
export interface UserPromptSubmitHookOptions {
|
|
17
|
+
readonly includeUltraworkDirective?: boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
15
20
|
export interface PreToolUsePayload {
|
|
16
21
|
readonly cwd: string;
|
|
17
22
|
readonly hook_event_name: "PreToolUse";
|
|
@@ -60,11 +65,17 @@ export function parsePreToolUsePayload(raw: string): PreToolUsePayload | null {
|
|
|
60
65
|
}
|
|
61
66
|
}
|
|
62
67
|
|
|
63
|
-
export async function applyUserPromptUlwLoopSteering(
|
|
68
|
+
export async function applyUserPromptUlwLoopSteering(
|
|
69
|
+
payload: UserPromptSubmitPayload,
|
|
70
|
+
options: UserPromptSubmitHookOptions = {},
|
|
71
|
+
): Promise<string> {
|
|
64
72
|
try {
|
|
65
73
|
if (payload.hook_event_name !== "UserPromptSubmit") return "";
|
|
66
74
|
const proposal = parseUlwLoopSteeringDirective(payload.prompt);
|
|
67
|
-
if (proposal === null)
|
|
75
|
+
if (proposal === null) {
|
|
76
|
+
if (hasSteeringDirectiveMarker(payload.prompt)) return "";
|
|
77
|
+
return options.includeUltraworkDirective ? buildUltraworkDirectiveOutput(payload) : "";
|
|
78
|
+
}
|
|
68
79
|
const result = await steerUlwLoop(payload.cwd, proposal, payloadScope(payload));
|
|
69
80
|
if (!result.accepted) return "";
|
|
70
81
|
return JSON.stringify({
|
|
@@ -79,6 +90,10 @@ export async function applyUserPromptUlwLoopSteering(payload: UserPromptSubmitPa
|
|
|
79
90
|
}
|
|
80
91
|
}
|
|
81
92
|
|
|
93
|
+
function hasSteeringDirectiveMarker(prompt: string): boolean {
|
|
94
|
+
return /(?:^|\s)(?:OMO_ULW_LOOP_STEER|omo\.ulw-loop\.steer|omo ulw-loop steer):/u.test(prompt);
|
|
95
|
+
}
|
|
96
|
+
|
|
82
97
|
function payloadScope(payload: UserPromptSubmitPayload): UlwLoopScope {
|
|
83
98
|
return { sessionId: payload.session_id };
|
|
84
99
|
}
|
|
@@ -98,11 +113,15 @@ export function applyPreToolUseGoalBudgetGuard(payload: PreToolUsePayload): stri
|
|
|
98
113
|
return `${JSON.stringify(output)}\n`;
|
|
99
114
|
}
|
|
100
115
|
|
|
101
|
-
export async function runUlwLoopHookCli(
|
|
116
|
+
export async function runUlwLoopHookCli(
|
|
117
|
+
stdin: NodeJS.ReadableStream,
|
|
118
|
+
stdout: NodeJS.WritableStream,
|
|
119
|
+
options: UserPromptSubmitHookOptions = {},
|
|
120
|
+
): Promise<void> {
|
|
102
121
|
try {
|
|
103
122
|
const payload = parseUserPromptSubmitPayload(await readAll(stdin));
|
|
104
123
|
if (payload === null) return;
|
|
105
|
-
const output = await applyUserPromptUlwLoopSteering(payload);
|
|
124
|
+
const output = await applyUserPromptUlwLoopSteering(payload, options);
|
|
106
125
|
if (output.length > 0) stdout.write(output);
|
|
107
126
|
} catch (error) {
|
|
108
127
|
if (error instanceof Error) return;
|
|
@@ -132,7 +151,10 @@ function isUserPromptSubmitPayload(value: unknown): value is UserPromptSubmitPay
|
|
|
132
151
|
typeof value["cwd"] === "string" &&
|
|
133
152
|
typeof value["prompt"] === "string" &&
|
|
134
153
|
typeof value["session_id"] === "string" &&
|
|
135
|
-
["model", "permission_mode", "
|
|
154
|
+
["model", "permission_mode", "turn_id"].every((key) => optionalString(value[key])) &&
|
|
155
|
+
(value["transcript_path"] === undefined ||
|
|
156
|
+
value["transcript_path"] === null ||
|
|
157
|
+
typeof value["transcript_path"] === "string")
|
|
136
158
|
);
|
|
137
159
|
}
|
|
138
160
|
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
|
|
3
|
+
export interface UltraworkDirectiveInput {
|
|
4
|
+
readonly prompt: string;
|
|
5
|
+
readonly transcript_path?: string | null;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
interface UserPromptSubmitHookOutput {
|
|
9
|
+
readonly hookSpecificOutput: {
|
|
10
|
+
readonly hookEventName: "UserPromptSubmit";
|
|
11
|
+
readonly additionalContext: string;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const ULTRAWORK_DIRECTIVE = readFileSync(new URL("../directive.md", import.meta.url), "utf8");
|
|
16
|
+
const ULTRAWORK_CURRENT_PROMPT_PATTERN = /(?:ultrawork|ulw)/i;
|
|
17
|
+
const ULTRAWORK_DIRECTIVE_MARKER = "<ultrawork-mode>";
|
|
18
|
+
const TRANSCRIPT_SEARCH_BYTES = 512_000;
|
|
19
|
+
const CONTEXT_PRESSURE_MARKERS = [
|
|
20
|
+
"context compacted",
|
|
21
|
+
"context_length_exceeded",
|
|
22
|
+
"skill descriptions were shortened",
|
|
23
|
+
"context_too_large",
|
|
24
|
+
"codex ran out of room in the model's context window",
|
|
25
|
+
"your input exceeds the context window",
|
|
26
|
+
"long threads and multiple compactions",
|
|
27
|
+
] as const;
|
|
28
|
+
|
|
29
|
+
export function buildUltraworkDirectiveOutput(input: UltraworkDirectiveInput): string {
|
|
30
|
+
if (isContextPressureRecoveryPrompt(input.prompt)) return "";
|
|
31
|
+
if (hasUltraworkDirectiveAlreadyInTranscript(input.transcript_path)) return "";
|
|
32
|
+
if (isContextPressureTranscript(input.transcript_path)) return "";
|
|
33
|
+
return isUltraworkPrompt(input.prompt) ? formatAdditionalContextOutput(ULTRAWORK_DIRECTIVE) : "";
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function hasUltraworkDirectiveAlreadyInTranscript(transcriptPath: string | null | undefined): boolean {
|
|
37
|
+
if (transcriptPath === undefined || transcriptPath === null) return false;
|
|
38
|
+
try {
|
|
39
|
+
const rawTranscript = readTranscriptTail(transcriptPath);
|
|
40
|
+
for (const line of rawTranscript.split(/\r?\n/)) {
|
|
41
|
+
const parsed = parseJsonLine(line);
|
|
42
|
+
if (!isRecord(parsed)) continue;
|
|
43
|
+
const hookSpecificOutput = parsed["hookSpecificOutput"];
|
|
44
|
+
if (!isRecord(hookSpecificOutput)) continue;
|
|
45
|
+
if (hookSpecificOutput["hookEventName"] !== "UserPromptSubmit") continue;
|
|
46
|
+
if (
|
|
47
|
+
typeof hookSpecificOutput["additionalContext"] === "string" &&
|
|
48
|
+
hookSpecificOutput["additionalContext"].includes(ULTRAWORK_DIRECTIVE_MARKER)
|
|
49
|
+
) {
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
} catch (error) {
|
|
54
|
+
if (error instanceof Error) return false;
|
|
55
|
+
throw error;
|
|
56
|
+
}
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function readTranscriptTail(transcriptPath: string): string {
|
|
61
|
+
const rawTranscript = readFileSync(transcriptPath);
|
|
62
|
+
return rawTranscript.subarray(Math.max(0, rawTranscript.byteLength - TRANSCRIPT_SEARCH_BYTES)).toString("utf8");
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function isUltraworkPrompt(prompt: string): boolean {
|
|
66
|
+
return ULTRAWORK_CURRENT_PROMPT_PATTERN.test(prompt);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function isContextPressureRecoveryPrompt(prompt: string): boolean {
|
|
70
|
+
const normalizedPrompt = prompt.toLowerCase();
|
|
71
|
+
return CONTEXT_PRESSURE_MARKERS.some((marker) => normalizedPrompt.includes(marker));
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function isContextPressureTranscript(transcriptPath: string | null | undefined): boolean {
|
|
75
|
+
if (transcriptPath === undefined || transcriptPath === null) return false;
|
|
76
|
+
try {
|
|
77
|
+
return isContextPressureRecoveryPrompt(readTranscriptTail(transcriptPath));
|
|
78
|
+
} catch (error) {
|
|
79
|
+
if (error instanceof Error) return false;
|
|
80
|
+
throw error;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function formatAdditionalContextOutput(additionalContext: string): string {
|
|
85
|
+
const normalizedContext = normalizeAdditionalContext(additionalContext);
|
|
86
|
+
if (normalizedContext.length === 0) return "";
|
|
87
|
+
const output: UserPromptSubmitHookOutput = {
|
|
88
|
+
hookSpecificOutput: {
|
|
89
|
+
hookEventName: "UserPromptSubmit",
|
|
90
|
+
additionalContext: normalizedContext,
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
return `${JSON.stringify(output)}\n`;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function normalizeAdditionalContext(additionalContext: string): string {
|
|
97
|
+
return additionalContext.replace(/\r\n/g, "\n").replace(/\r/g, "\n").trim();
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function parseJsonLine(line: string): unknown | null {
|
|
101
|
+
if (line.trim().length === 0) return null;
|
|
102
|
+
try {
|
|
103
|
+
const parsed: unknown = JSON.parse(line);
|
|
104
|
+
return parsed;
|
|
105
|
+
} catch (error) {
|
|
106
|
+
if (error instanceof Error) return null;
|
|
107
|
+
throw error;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
112
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
113
|
+
}
|
|
@@ -23,6 +23,15 @@ function sanitizedEnv(): NodeJS.ProcessEnv {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
async function runProcess(command: string, args: readonly string[], cwd: string): Promise<CliResult> {
|
|
26
|
+
return runProcessWithInput(command, args, cwd, "");
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async function runProcessWithInput(
|
|
30
|
+
command: string,
|
|
31
|
+
args: readonly string[],
|
|
32
|
+
cwd: string,
|
|
33
|
+
input: string,
|
|
34
|
+
): Promise<CliResult> {
|
|
26
35
|
return new Promise((resolvePromise, reject) => {
|
|
27
36
|
const child = spawn(command, [...args], { cwd, env: sanitizedEnv() });
|
|
28
37
|
const stdout: Buffer[] = [];
|
|
@@ -37,13 +46,14 @@ async function runProcess(command: string, args: readonly string[], cwd: string)
|
|
|
37
46
|
stderr: Buffer.concat(stderr).toString("utf8"),
|
|
38
47
|
});
|
|
39
48
|
});
|
|
49
|
+
child.stdin.end(input);
|
|
40
50
|
});
|
|
41
51
|
}
|
|
42
52
|
|
|
43
53
|
let workspace: string;
|
|
44
54
|
|
|
45
|
-
async function runCli(args: readonly string[]): Promise<CliResult> {
|
|
46
|
-
return
|
|
55
|
+
async function runCli(args: readonly string[], input = ""): Promise<CliResult> {
|
|
56
|
+
return runProcessWithInput(process.execPath, [builtCli, ...args], workspace, input);
|
|
47
57
|
}
|
|
48
58
|
|
|
49
59
|
beforeAll(async () => {
|
|
@@ -92,4 +102,25 @@ describe("dist/cli.js entrypoint dispatch", () => {
|
|
|
92
102
|
expect(result.code).toBe(1);
|
|
93
103
|
expect(result.stderr).toContain("[omo] unknown command: frobnicate");
|
|
94
104
|
});
|
|
105
|
+
|
|
106
|
+
it("#given standalone ulw-loop hook asks for ultrawork context #when user prompt is ulw #then emits the ultrawork directive", async () => {
|
|
107
|
+
const payload = {
|
|
108
|
+
cwd: workspace,
|
|
109
|
+
hook_event_name: "UserPromptSubmit",
|
|
110
|
+
model: "gpt-5.5",
|
|
111
|
+
permission_mode: "default",
|
|
112
|
+
prompt: "ulw this change",
|
|
113
|
+
session_id: "s1",
|
|
114
|
+
transcript_path: null,
|
|
115
|
+
turn_id: "t1",
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
const result = await runCli(["hook", "user-prompt-submit", "--with-ultrawork"], `${JSON.stringify(payload)}\n`);
|
|
119
|
+
const parsed = JSON.parse(result.stdout);
|
|
120
|
+
|
|
121
|
+
expect(result.code).toBe(0);
|
|
122
|
+
expect(result.stderr).toBe("");
|
|
123
|
+
expect(parsed.hookSpecificOutput.hookEventName).toBe("UserPromptSubmit");
|
|
124
|
+
expect(parsed.hookSpecificOutput.additionalContext).toMatch(/^<ultrawork-mode>/);
|
|
125
|
+
});
|
|
95
126
|
});
|