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
|
@@ -1,20 +1,27 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
|
+
import { execFile } from "node:child_process";
|
|
2
3
|
import { lstat, mkdir, mkdtemp, readdir, readFile, readlink, rm, stat, writeFile } from "node:fs/promises";
|
|
3
4
|
import { tmpdir } from "node:os";
|
|
4
|
-
import { join, sep } from "node:path";
|
|
5
|
+
import { dirname, join, sep } from "node:path";
|
|
5
6
|
import test from "node:test";
|
|
7
|
+
import { promisify } from "node:util";
|
|
6
8
|
|
|
7
9
|
const CLI_URL = new URL("../components/bootstrap/dist/cli.js", import.meta.url);
|
|
8
10
|
const { runBootstrapWorker, runWorkerSetup } = await import(CLI_URL.href);
|
|
9
11
|
|
|
10
12
|
const MARKETPLACE_SOURCE_LINE = 'source = "https://github.com/code-yeongyu/lazycodex.git"';
|
|
11
13
|
const COMPONENT_BIN_NAME = "omo-toolbox";
|
|
14
|
+
const execFileAsync = promisify(execFile);
|
|
12
15
|
const OMO_CLI_DEGRADED_ENTRY = {
|
|
13
16
|
component: "omo-cli",
|
|
14
17
|
hint: "use npx lazycodex-ai for the omo CLI",
|
|
15
18
|
reason: "marketplace payload has no dist/cli",
|
|
16
19
|
};
|
|
17
20
|
|
|
21
|
+
function escapeRegExp(value) {
|
|
22
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
23
|
+
}
|
|
24
|
+
|
|
18
25
|
async function withBinLinkFixture(run) {
|
|
19
26
|
const root = await mkdtemp(join(tmpdir(), "omo-bootstrap-binlinks-"));
|
|
20
27
|
try {
|
|
@@ -79,6 +86,8 @@ async function writeVersionedRoot(root, version, { withRuntimeCli = false } = {}
|
|
|
79
86
|
if (withRuntimeCli) {
|
|
80
87
|
await mkdir(join(pluginRoot, "dist", "cli"), { recursive: true });
|
|
81
88
|
await writeFile(join(pluginRoot, "dist", "cli", "index.js"), "console.log('omo');\n");
|
|
89
|
+
await mkdir(join(pluginRoot, "dist", "cli-node"), { recursive: true });
|
|
90
|
+
await writeFile(join(pluginRoot, "dist", "cli-node", "index.js"), "console.log('omo node runtime');\n");
|
|
82
91
|
}
|
|
83
92
|
return pluginRoot;
|
|
84
93
|
}
|
|
@@ -196,14 +205,18 @@ test("#given platform win32 #when the worker setup links bins #then component bi
|
|
|
196
205
|
assert.deepEqual(outcome.degraded, []);
|
|
197
206
|
const shim = await readFile(join(fixture.binDir, `${COMPONENT_BIN_NAME}.cmd`), "utf8");
|
|
198
207
|
assert.match(shim, /@echo off/);
|
|
199
|
-
|
|
208
|
+
const componentEntrypoint = join(pluginRoot, "components", "toolbox", "dist", "cli.js");
|
|
209
|
+
assert.match(shim, /NODE_REPL_NODE_PATH/);
|
|
210
|
+
assert.match(shim, /"%OMO_NODE_BINARY%"/);
|
|
211
|
+
assert.match(shim, new RegExp(`"${escapeRegExp(componentEntrypoint)}" %\\*`));
|
|
212
|
+
assert.doesNotMatch(shim, new RegExp(`node "${escapeRegExp(componentEntrypoint)}" %\\*`));
|
|
200
213
|
const wrapper = await readFile(join(fixture.binDir, "omo.cmd"), "utf8");
|
|
201
214
|
assert.ok(wrapper.includes(join(pluginRoot, "dist", "cli", "index.js")));
|
|
202
215
|
await assert.rejects(() => lstat(join(fixture.binDir, COMPONENT_BIN_NAME)), "win32 must not leave posix symlinks behind");
|
|
203
216
|
});
|
|
204
217
|
});
|
|
205
218
|
|
|
206
|
-
test("#given a
|
|
219
|
+
test("#given a legacy payload without root CLI dist #when the worker setup runs #then it records degraded omo-cli and leaves no broken link", async () => {
|
|
207
220
|
await withBinLinkFixture(async (fixture) => {
|
|
208
221
|
const pluginRoot = await writeVersionedRoot(fixture.root, "1.0.0");
|
|
209
222
|
|
|
@@ -234,14 +247,19 @@ test("#given a payload shipping dist/cli #when the worker setup runs with no bin
|
|
|
234
247
|
assert.deepEqual(outcome.degraded, []);
|
|
235
248
|
const defaultBinDir = join(fixture.codexHome, "bin");
|
|
236
249
|
const wrapperName = process.platform === "win32" ? "omo.cmd" : "omo";
|
|
237
|
-
const
|
|
250
|
+
const wrapperPath = join(defaultBinDir, wrapperName);
|
|
251
|
+
const wrapper = await readFile(wrapperPath, "utf8");
|
|
238
252
|
assert.ok(wrapper.includes(join(pluginRoot, "dist", "cli", "index.js")));
|
|
239
253
|
if (process.platform !== "win32") {
|
|
240
|
-
assert.ok((await stat(
|
|
254
|
+
assert.ok((await stat(wrapperPath)).mode & 0o111, "the posix omo wrapper must be executable");
|
|
241
255
|
assert.equal(
|
|
242
256
|
await readlink(join(defaultBinDir, COMPONENT_BIN_NAME)),
|
|
243
257
|
join(pluginRoot, "components", "toolbox", "dist", "cli.js"),
|
|
244
258
|
);
|
|
259
|
+
const result = await execFileAsync(wrapperPath, ["--version"], {
|
|
260
|
+
env: { ...process.env, OMO_RUNTIME: "node", PATH: `${dirname(process.execPath)}:/usr/bin:/bin` },
|
|
261
|
+
});
|
|
262
|
+
assert.match(result.stdout, /omo node runtime/);
|
|
245
263
|
} else {
|
|
246
264
|
const shim = await readFile(join(defaultBinDir, `${COMPONENT_BIN_NAME}.cmd`), "utf8");
|
|
247
265
|
assert.ok(shim.includes(join(pluginRoot, "components", "toolbox", "dist", "cli.js")));
|
|
@@ -16,6 +16,8 @@ const SKIPPED_DIRECTORY_NAMES = new Set([".git", "node_modules"]);
|
|
|
16
16
|
const EXPECTED_BOOTSTRAP_COMMAND = 'node "${PLUGIN_ROOT}/components/bootstrap/dist/cli.js" hook session-start';
|
|
17
17
|
const EXPECTED_BOOTSTRAP_COMMAND_WINDOWS =
|
|
18
18
|
'powershell -NoProfile -ExecutionPolicy Bypass -File "${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\bootstrap.ps1"';
|
|
19
|
+
const EXPECTED_NODE_DISPATCH_PREFIX =
|
|
20
|
+
'powershell -NoProfile -ExecutionPolicy Bypass -File "${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1"';
|
|
19
21
|
|
|
20
22
|
async function pathExists(absolutePath) {
|
|
21
23
|
try {
|
|
@@ -127,6 +129,23 @@ test("#given aggregate and component hook manifests #when command targets are re
|
|
|
127
129
|
assert.deepEqual(missing, []);
|
|
128
130
|
});
|
|
129
131
|
|
|
132
|
+
test("#given aggregate hook manifests #when command handlers are inspected #then each has a Windows dispatcher", async () => {
|
|
133
|
+
// given
|
|
134
|
+
const aggregateHooks = await readAggregateHookManifests();
|
|
135
|
+
|
|
136
|
+
// when
|
|
137
|
+
const missing = [];
|
|
138
|
+
for (const manifest of aggregateHooks) {
|
|
139
|
+
for (const { handler } of collectCommandHooks(manifest.hooks, manifest.source)) {
|
|
140
|
+
if (typeof handler.commandWindows === "string" && handler.commandWindows.length > 0) continue;
|
|
141
|
+
missing.push(`${manifest.source}: ${handler.command}`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// then
|
|
146
|
+
assert.deepEqual(missing, [], `Aggregate hook commands need commandWindows dispatchers:\n${missing.join("\n")}`);
|
|
147
|
+
});
|
|
148
|
+
|
|
130
149
|
test("#given the bootstrap component #when its SessionStart registration is inspected #then aggregate and component entries declare both platform commands", async () => {
|
|
131
150
|
// given
|
|
132
151
|
const aggregateHooks = (await readAggregateHookManifests()).find(({ source }) =>
|
|
@@ -156,6 +175,25 @@ test("#given the bootstrap component #when its SessionStart registration is insp
|
|
|
156
175
|
}
|
|
157
176
|
});
|
|
158
177
|
|
|
178
|
+
test("#given non-bootstrap aggregate hook manifests #when commandWindows entries are read #then they launch the managed Node dispatcher", async () => {
|
|
179
|
+
// given
|
|
180
|
+
const aggregateHooks = await readAggregateHookManifests();
|
|
181
|
+
|
|
182
|
+
// when
|
|
183
|
+
const offenders = [];
|
|
184
|
+
for (const manifest of aggregateHooks) {
|
|
185
|
+
for (const { handler } of collectCommandHooks(manifest.hooks, manifest.source)) {
|
|
186
|
+
if (handler.command === EXPECTED_BOOTSTRAP_COMMAND) continue;
|
|
187
|
+
if (typeof handler.commandWindows !== "string" || !handler.commandWindows.startsWith(EXPECTED_NODE_DISPATCH_PREFIX)) {
|
|
188
|
+
offenders.push(`${manifest.source}: ${handler.commandWindows ?? "<missing>"}`);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// then
|
|
194
|
+
assert.deepEqual(offenders, [], `Non-bootstrap aggregate hooks must use node-dispatch.ps1 on Windows:\n${offenders.join("\n")}`);
|
|
195
|
+
});
|
|
196
|
+
|
|
159
197
|
test("#given the built bootstrap bundle #when its module references are inspected #then it depends on Node built-ins only", async () => {
|
|
160
198
|
// given
|
|
161
199
|
const bundlePath = join(root, "components", "bootstrap", "dist", "cli.js");
|
|
@@ -68,6 +68,31 @@ test("#given bootstrap.ps1 #when environment writes are scanned #then no Machine
|
|
|
68
68
|
assert.deepEqual(offenders, [], "bootstrap.ps1 must only touch User-scope environment values (Machine scope needs elevation)");
|
|
69
69
|
});
|
|
70
70
|
|
|
71
|
+
test("#given bootstrap.ps1 #when dependency discovery misses #then it never invokes winget or mutates user PATH", async () => {
|
|
72
|
+
// given
|
|
73
|
+
const content = await readBootstrapScript();
|
|
74
|
+
|
|
75
|
+
// then
|
|
76
|
+
assert.doesNotMatch(content, /&\s*winget\s+install/i, "bootstrap.ps1 must not install system dependencies with winget");
|
|
77
|
+
assert.doesNotMatch(
|
|
78
|
+
content,
|
|
79
|
+
/SetEnvironmentVariable\("Path"/,
|
|
80
|
+
"bootstrap.ps1 must not mutate the user PATH when Codex Desktop misses PATH entries",
|
|
81
|
+
);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test("#given bootstrap.ps1 #when resolving Node #then Codex NODE_REPL_NODE_PATH is checked before PATH", async () => {
|
|
85
|
+
// given
|
|
86
|
+
const content = await readBootstrapScript();
|
|
87
|
+
|
|
88
|
+
// then
|
|
89
|
+
assert.match(content, /NODE_REPL_NODE_PATH/, "bootstrap.ps1 must know how to read the Codex bundled Node setting");
|
|
90
|
+
assert(
|
|
91
|
+
content.indexOf("NODE_REPL_NODE_PATH") < content.indexOf("Get-Command node"),
|
|
92
|
+
"bootstrap.ps1 must prefer Codex bundled Node config before probing PATH",
|
|
93
|
+
);
|
|
94
|
+
});
|
|
95
|
+
|
|
71
96
|
test("#given bootstrap.ps1 #when execution policy mutations are scanned #then Set-ExecutionPolicy is never invoked", async () => {
|
|
72
97
|
// given
|
|
73
98
|
const content = await readBootstrapScript();
|
|
@@ -205,21 +205,15 @@ test("#given an unwritable config.toml #when the worker setup runs #then it degr
|
|
|
205
205
|
});
|
|
206
206
|
});
|
|
207
207
|
|
|
208
|
-
test("#given win32 without Git Bash
|
|
208
|
+
test("#given win32 without Git Bash #when the worker setup runs #then it degrades instead of throwing and disables the git_bash MCP", async () => {
|
|
209
209
|
await withSetupFixture(async (fixture) => {
|
|
210
|
-
const commands = [];
|
|
211
210
|
const outcome = await runWorkerSetup(
|
|
212
211
|
setupOptions(fixture, {
|
|
213
|
-
env: { OMO_CODEX_SKIP_GIT_BASH_AUTO_INSTALL: "1" },
|
|
214
212
|
platform: "win32",
|
|
215
213
|
resolveGitBash: () => ({ checkedPaths: [], found: false, installHint: "install git bash" }),
|
|
216
|
-
runCommand: async (command, args) => {
|
|
217
|
-
commands.push([command, ...args]);
|
|
218
|
-
},
|
|
219
214
|
}),
|
|
220
215
|
);
|
|
221
216
|
|
|
222
|
-
assert.deepEqual(commands, []);
|
|
223
217
|
const gitBashEntries = outcome.degraded.filter((entry) => entry.component === "git-bash");
|
|
224
218
|
assert.equal(gitBashEntries.length, 1);
|
|
225
219
|
const config = await readConfig(fixture);
|
|
@@ -1,12 +1,41 @@
|
|
|
1
|
+
// allow: SIZE_OK - migration scenarios share one temp Codex-home harness across legacy TOML shapes; this release only adds config cases and future additions should split by migration family.
|
|
2
|
+
|
|
1
3
|
import assert from "node:assert/strict";
|
|
4
|
+
import { spawnSync } from "node:child_process";
|
|
2
5
|
import { mkdir, mkdtemp, readFile, rm, symlink, writeFile } from "node:fs/promises";
|
|
3
6
|
import { tmpdir } from "node:os";
|
|
4
7
|
import { dirname, join } from "node:path";
|
|
5
8
|
import test from "node:test";
|
|
6
9
|
|
|
10
|
+
import { removeUnsupportedRootMultiAgentMode } from "../scripts/migrate-codex-config/multi-agent-mode-guard.mjs";
|
|
7
11
|
import { forceDisableMultiAgentV2 } from "../scripts/migrate-codex-config/multi-agent-v2-guard.mjs";
|
|
8
12
|
import { ensureCodexReasoningConfig, migrateCodexConfig } from "../scripts/migrate-codex-config.mjs";
|
|
9
13
|
|
|
14
|
+
function parseTomlWithPython(config) {
|
|
15
|
+
const python = resolvePython();
|
|
16
|
+
const result = spawnSync(
|
|
17
|
+
python,
|
|
18
|
+
[
|
|
19
|
+
"-c",
|
|
20
|
+
[
|
|
21
|
+
"import json, sys, tomllib",
|
|
22
|
+
"print(json.dumps(tomllib.loads(sys.stdin.read())))",
|
|
23
|
+
].join("; "),
|
|
24
|
+
],
|
|
25
|
+
{ encoding: "utf8", input: config },
|
|
26
|
+
);
|
|
27
|
+
assert.equal(result.status, 0, result.stderr);
|
|
28
|
+
return JSON.parse(result.stdout);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function resolvePython() {
|
|
32
|
+
for (const command of ["python3", "python"]) {
|
|
33
|
+
const result = spawnSync(command, ["-c", "import tomllib"], { encoding: "utf8" });
|
|
34
|
+
if (result.status === 0) return command;
|
|
35
|
+
}
|
|
36
|
+
assert.fail("Python with tomllib is required for TOML parse assertions");
|
|
37
|
+
}
|
|
38
|
+
|
|
10
39
|
test("#given stale root reasoning config #when ensuring config #then replaces stale values without duplicate keys", () => {
|
|
11
40
|
const result = ensureCodexReasoningConfig(
|
|
12
41
|
[
|
|
@@ -181,7 +210,7 @@ test("#given model catalog is malformed and stale config #when migrating #then f
|
|
|
181
210
|
assert.match(content, /model_context_window = 400000/);
|
|
182
211
|
});
|
|
183
212
|
|
|
184
|
-
test("#given user-customized Codex model config #when migrating #then user values are preserved", async () => {
|
|
213
|
+
test("#given user-customized Codex model config #when migrating #then user values are preserved without root multi-agent mode", async () => {
|
|
185
214
|
const root = await mkdtemp(join(tmpdir(), "lazycodex-config-custom-"));
|
|
186
215
|
const codexHome = join(root, "codex-home");
|
|
187
216
|
await mkdir(codexHome, { recursive: true });
|
|
@@ -205,11 +234,16 @@ test("#given user-customized Codex model config #when migrating #then user value
|
|
|
205
234
|
});
|
|
206
235
|
|
|
207
236
|
const content = await readFile(join(codexHome, "config.toml"), "utf8");
|
|
208
|
-
assert.deepEqual(result.changed, []);
|
|
237
|
+
assert.deepEqual(result.changed, [join(codexHome, "config.toml")]);
|
|
238
|
+
assert.deepEqual(result.modeChanged, []);
|
|
209
239
|
assert.match(content, /model = "gpt-5\.4"/);
|
|
210
240
|
assert.match(content, /model_context_window = 123456/);
|
|
211
241
|
assert.match(content, /model_reasoning_effort = "medium"/);
|
|
212
242
|
assert.match(content, /plan_mode_reasoning_effort = "medium"/);
|
|
243
|
+
assert.doesNotMatch(content, /^\s*multi_agent_mode\s*=/m);
|
|
244
|
+
assert.match(content, /\[agents\][\s\S]*?max_threads = 1000/);
|
|
245
|
+
assert.match(content, /\[features\.multi_agent_v2\][\s\S]*?enabled = false/);
|
|
246
|
+
assert.match(content, /max_concurrent_threads_per_session = 1000/);
|
|
213
247
|
});
|
|
214
248
|
|
|
215
249
|
test("#given managed config state is malformed #when migrating #then migration ignores stale state safely", async () => {
|
|
@@ -328,6 +362,7 @@ test("#given config already matches current catalog #when catalog version advanc
|
|
|
328
362
|
"model_context_window = 400000",
|
|
329
363
|
'model_reasoning_effort = "high"',
|
|
330
364
|
'plan_mode_reasoning_effort = "xhigh"',
|
|
365
|
+
'multi_agent_mode = "proactive"',
|
|
331
366
|
"",
|
|
332
367
|
"[features.multi_agent_v2]",
|
|
333
368
|
"enabled = false",
|
|
@@ -363,9 +398,88 @@ test("#given config already matches current catalog #when catalog version advanc
|
|
|
363
398
|
});
|
|
364
399
|
|
|
365
400
|
const state = JSON.parse(await readFile(statePath, "utf8"));
|
|
366
|
-
assert.deepEqual(result.changed, []);
|
|
401
|
+
assert.deepEqual(result.changed, [configPath]);
|
|
402
|
+
assert.deepEqual(result.modeChanged, [configPath]);
|
|
367
403
|
assert.equal(state.files[configPath].managed, true);
|
|
368
404
|
assert.equal(state.files[configPath].catalogVersion, "test.role-only");
|
|
405
|
+
const content = await readFile(configPath, "utf8");
|
|
406
|
+
assert.doesNotMatch(content, /^\s*multi_agent_mode\s*=/m);
|
|
407
|
+
assert.match(content, /\[agents\][\s\S]*?max_threads = 1000/);
|
|
408
|
+
assert.match(content, /max_concurrent_threads_per_session = 1000/);
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
test("#given stale Context7 placeholder MCP config #when migrating #then removes it and keeps plugin policy", async () => {
|
|
412
|
+
const root = await mkdtemp(join(tmpdir(), "lazycodex-context7-placeholder-cleanup-"));
|
|
413
|
+
const codexHome = join(root, "codex-home");
|
|
414
|
+
const configPath = join(codexHome, "config.toml");
|
|
415
|
+
await mkdir(codexHome, { recursive: true });
|
|
416
|
+
await writeFile(
|
|
417
|
+
configPath,
|
|
418
|
+
[
|
|
419
|
+
'model = "gpt-5.5"',
|
|
420
|
+
"model_context_window = 400000",
|
|
421
|
+
'model_reasoning_effort = "high"',
|
|
422
|
+
'plan_mode_reasoning_effort = "xhigh"',
|
|
423
|
+
"",
|
|
424
|
+
"[mcp_servers.context7] # stale npx package from old docs",
|
|
425
|
+
'command = "npx"',
|
|
426
|
+
'args = ["-y", "@upstash/context7-mcp", "--api-key", "YOUR_API_KEY"]',
|
|
427
|
+
"startup_timeout_sec = 20",
|
|
428
|
+
"",
|
|
429
|
+
'[plugins."omo@sisyphuslabs".mcp_servers.context7]',
|
|
430
|
+
"enabled = true",
|
|
431
|
+
"",
|
|
432
|
+
].join("\n"),
|
|
433
|
+
);
|
|
434
|
+
|
|
435
|
+
const result = await migrateCodexConfig({
|
|
436
|
+
env: { CODEX_HOME: codexHome, LAZYCODEX_MODEL_CATALOG_STATE_PATH: join(root, "model-state.json") },
|
|
437
|
+
cwd: root,
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
const content = await readFile(configPath, "utf8");
|
|
441
|
+
assert.deepEqual(result.changed, [configPath]);
|
|
442
|
+
assert.doesNotMatch(content, /\[mcp_servers\.context7\]/);
|
|
443
|
+
assert.doesNotMatch(content, /@upstash\/context7-mcp/);
|
|
444
|
+
assert.doesNotMatch(content, /YOUR_API_KEY/);
|
|
445
|
+
assert.match(content, /\[plugins\."omo@sisyphuslabs"\.mcp_servers\.context7\][\s\S]*?enabled = true/);
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
test("#given real Context7 API key and placeholder comment #when migrating #then preserves user server settings", async () => {
|
|
449
|
+
const root = await mkdtemp(join(tmpdir(), "lazycodex-context7-real-key-"));
|
|
450
|
+
const codexHome = join(root, "codex-home");
|
|
451
|
+
const configPath = join(codexHome, "config.toml");
|
|
452
|
+
await mkdir(codexHome, { recursive: true });
|
|
453
|
+
await writeFile(
|
|
454
|
+
configPath,
|
|
455
|
+
[
|
|
456
|
+
'model = "gpt-5.5"',
|
|
457
|
+
"model_context_window = 400000",
|
|
458
|
+
'model_reasoning_effort = "high"',
|
|
459
|
+
'plan_mode_reasoning_effort = "xhigh"',
|
|
460
|
+
"",
|
|
461
|
+
"[mcp_servers.context7]",
|
|
462
|
+
'command = "npx"',
|
|
463
|
+
'args = ["-y", "@upstash/context7-mcp", "--api-key", "ctx7sk_live_example"] # replace YOUR_API_KEY in docs only',
|
|
464
|
+
"startup_timeout_sec = 20",
|
|
465
|
+
"",
|
|
466
|
+
'[plugins."omo@sisyphuslabs".mcp_servers.context7]',
|
|
467
|
+
"enabled = true",
|
|
468
|
+
"",
|
|
469
|
+
].join("\n"),
|
|
470
|
+
);
|
|
471
|
+
|
|
472
|
+
const result = await migrateCodexConfig({
|
|
473
|
+
env: { CODEX_HOME: codexHome, LAZYCODEX_MODEL_CATALOG_STATE_PATH: join(root, "model-state.json") },
|
|
474
|
+
cwd: root,
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
const content = await readFile(configPath, "utf8");
|
|
478
|
+
assert.deepEqual(result.changed, [configPath]);
|
|
479
|
+
assert.match(content, /\[mcp_servers\.context7\]/);
|
|
480
|
+
assert.match(content, /ctx7sk_live_example/);
|
|
481
|
+
assert.match(content, /replace YOUR_API_KEY in docs only/);
|
|
482
|
+
assert.match(content, /\[plugins\."omo@sisyphuslabs"\.mcp_servers\.context7\][\s\S]*?enabled = true/);
|
|
369
483
|
});
|
|
370
484
|
|
|
371
485
|
test("#given multi_agent_v2 enabled #when forcing disable #then flips the flag to false", () => {
|
|
@@ -470,18 +584,23 @@ test("#given an annotated managed section #when forcing disable runs again #then
|
|
|
470
584
|
assert.match(rerun, /enabled = false/);
|
|
471
585
|
});
|
|
472
586
|
|
|
473
|
-
test("#given [features] boolean shorthand multi_agent_v2 = false #when forcing disable #then
|
|
587
|
+
test("#given [features] boolean shorthand multi_agent_v2 = false #when forcing disable #then rewrites to the non-conflicting disabled table", () => {
|
|
474
588
|
const config = [
|
|
475
589
|
'model = "gpt-5.5"',
|
|
476
590
|
"",
|
|
477
591
|
"[features]",
|
|
478
592
|
"multi_agent_v2 = false",
|
|
593
|
+
"plugins = true",
|
|
479
594
|
"",
|
|
480
595
|
].join("\n");
|
|
481
596
|
|
|
482
597
|
const result = forceDisableMultiAgentV2(config);
|
|
598
|
+
const parsed = parseTomlWithPython(result);
|
|
483
599
|
|
|
484
|
-
assert.
|
|
600
|
+
assert.doesNotMatch(result, /^\s*multi_agent_v2\s*=/m);
|
|
601
|
+
assert.equal((result.match(/\[features\.multi_agent_v2\]/g) ?? []).length, 1);
|
|
602
|
+
assert.equal(parsed.features.plugins, true);
|
|
603
|
+
assert.equal(parsed.features.multi_agent_v2.enabled, false);
|
|
485
604
|
});
|
|
486
605
|
|
|
487
606
|
test("#given multi_agent_v2 already disabled #when forcing disable #then returns config unchanged", () => {
|
|
@@ -520,8 +639,87 @@ test("#given global config without multi_agent_v2 section #when full migration r
|
|
|
520
639
|
});
|
|
521
640
|
|
|
522
641
|
assert.deepEqual(result.changed, [configPath]);
|
|
642
|
+
assert.deepEqual(result.modeChanged, []);
|
|
523
643
|
const content = await readFile(configPath, "utf8");
|
|
524
|
-
assert.match(content, /\[features\.multi_agent_v2\]\
|
|
644
|
+
assert.match(content, /\[features\.multi_agent_v2\][\s\S]*?enabled = false/);
|
|
645
|
+
assert.match(content, /max_concurrent_threads_per_session = 1000/);
|
|
646
|
+
assert.match(content, /\[agents\][\s\S]*?max_threads = 1000/);
|
|
647
|
+
assert.doesNotMatch(content, /^\s*multi_agent_mode\s*=/m);
|
|
648
|
+
});
|
|
649
|
+
|
|
650
|
+
test("#given global config starts with inline-comment features table #when full migration runs #then managed root settings stay at TOML root", async () => {
|
|
651
|
+
const root = await mkdtemp(join(tmpdir(), "lazycodex-root-settings-inline-features-"));
|
|
652
|
+
const codexHome = join(root, "codex-home");
|
|
653
|
+
await mkdir(codexHome, { recursive: true });
|
|
654
|
+
const configPath = join(codexHome, "config.toml");
|
|
655
|
+
await writeFile(
|
|
656
|
+
configPath,
|
|
657
|
+
[
|
|
658
|
+
"[features] # keep comment",
|
|
659
|
+
"plugins = true",
|
|
660
|
+
"",
|
|
661
|
+
].join("\n"),
|
|
662
|
+
);
|
|
663
|
+
|
|
664
|
+
const result = await migrateCodexConfig({
|
|
665
|
+
env: { CODEX_HOME: codexHome, LAZYCODEX_MODEL_CATALOG_STATE_PATH: join(root, "model-state.json") },
|
|
666
|
+
cwd: root,
|
|
667
|
+
});
|
|
668
|
+
|
|
669
|
+
assert.deepEqual(result.changed, [configPath]);
|
|
670
|
+
const content = await readFile(configPath, "utf8");
|
|
671
|
+
const parsed = parseTomlWithPython(content);
|
|
672
|
+
assert.equal("multi_agent_mode" in parsed, false);
|
|
673
|
+
assert.equal(parsed.model, "gpt-5.5");
|
|
674
|
+
assert.equal(parsed.model_context_window, 400000);
|
|
675
|
+
assert.equal(parsed.model_reasoning_effort, "high");
|
|
676
|
+
assert.equal(parsed.plan_mode_reasoning_effort, "xhigh");
|
|
677
|
+
assert.equal(parsed.features.plugins, true);
|
|
678
|
+
assert.equal("multi_agent_mode" in parsed.features, false);
|
|
679
|
+
assert.equal("model" in parsed.features, false);
|
|
680
|
+
assert.equal("model_context_window" in parsed.features, false);
|
|
681
|
+
assert.match(content, /^model = "gpt-5\.5"\nmodel_context_window = 400000/m);
|
|
682
|
+
assert.doesNotMatch(content, /^\s*multi_agent_mode\s*=/m);
|
|
683
|
+
assert.match(content, /\[features\] # keep comment\nplugins = true/);
|
|
684
|
+
});
|
|
685
|
+
|
|
686
|
+
test("#given queue multi-agent mode #when removing unsupported root key #then deletes root setting", () => {
|
|
687
|
+
const config = ['multi_agent_mode = "queue"', "", "[features]", "multi_agent = true", ""].join("\n");
|
|
688
|
+
|
|
689
|
+
const result = removeUnsupportedRootMultiAgentMode(config);
|
|
690
|
+
|
|
691
|
+
assert.doesNotMatch(result, /^\s*multi_agent_mode\s*=/m);
|
|
692
|
+
assert.doesNotMatch(result, /multi_agent_mode = "queue"/);
|
|
693
|
+
assert.match(result, /\[features\]/);
|
|
694
|
+
});
|
|
695
|
+
|
|
696
|
+
test("#given proactive multi-agent mode #when removing unsupported root key #then deletes root setting", () => {
|
|
697
|
+
const config = ['multi_agent_mode = "proactive" # user already opted in', "", "[features]", "multi_agent = true", ""].join("\n");
|
|
698
|
+
|
|
699
|
+
const result = removeUnsupportedRootMultiAgentMode(config);
|
|
700
|
+
|
|
701
|
+
assert.doesNotMatch(result, /^\s*multi_agent_mode\s*=/m);
|
|
702
|
+
assert.match(result, /\[features\]/);
|
|
703
|
+
});
|
|
704
|
+
|
|
705
|
+
test("#given inline-comment features table #when removing unsupported root key #then config stays unchanged", () => {
|
|
706
|
+
const config = ["[features] # keep comment", "multi_agent = true", ""].join("\n");
|
|
707
|
+
|
|
708
|
+
const result = removeUnsupportedRootMultiAgentMode(config);
|
|
709
|
+
const parsed = parseTomlWithPython(result);
|
|
710
|
+
|
|
711
|
+
assert.equal(result, config);
|
|
712
|
+
assert.equal("multi_agent_mode" in parsed, false);
|
|
713
|
+
assert.equal(parsed.features.multi_agent, true);
|
|
714
|
+
});
|
|
715
|
+
|
|
716
|
+
test("#given indented root proactive mode #when removing unsupported root key #then no root setting remains", () => {
|
|
717
|
+
const config = [' multi_agent_mode = "proactive" # user already opted in', "", "[features] # keep comment", "multi_agent = true", ""].join("\n");
|
|
718
|
+
|
|
719
|
+
const result = removeUnsupportedRootMultiAgentMode(config);
|
|
720
|
+
|
|
721
|
+
assert.equal(result.match(/multi_agent_mode\s*=/g)?.length ?? 0, 0);
|
|
722
|
+
assert.match(result, /^\[features\] # keep comment$/m);
|
|
525
723
|
});
|
|
526
724
|
|
|
527
725
|
test("#given global config with forced multi_agent_v2 #when full migration runs #then disables it on disk", async () => {
|
|
@@ -551,6 +749,8 @@ test("#given global config with forced multi_agent_v2 #when full migration runs
|
|
|
551
749
|
const content = await readFile(configPath, "utf8");
|
|
552
750
|
assert.match(content, /enabled = false/);
|
|
553
751
|
assert.doesNotMatch(content, /enabled = true/);
|
|
752
|
+
assert.match(content, /max_concurrent_threads_per_session = 1000/);
|
|
753
|
+
assert.match(content, /\[agents\][\s\S]*?max_threads = 1000/);
|
|
554
754
|
});
|
|
555
755
|
|
|
556
756
|
test("#given enabled = true with an inline comment #when forcing disable #then flips to false and preserves the comment", () => {
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { mkdtemp, readFile, writeFile } from "node:fs/promises";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import test from "node:test";
|
|
6
|
+
|
|
7
|
+
import { migrateConfigFile } from "../scripts/migrate-codex-config.mjs";
|
|
8
|
+
|
|
9
|
+
test("#given SessionStart config migration sees a low subagent cap #when migrating #then raises it to 1000", async () => {
|
|
10
|
+
const root = await mkdtemp(join(tmpdir(), "lazycodex-subagent-limit-migration-"));
|
|
11
|
+
const configPath = join(root, "config.toml");
|
|
12
|
+
await writeFile(
|
|
13
|
+
configPath,
|
|
14
|
+
[
|
|
15
|
+
'model = "gpt-5.4"',
|
|
16
|
+
"model_context_window = 123456",
|
|
17
|
+
'model_reasoning_effort = "medium"',
|
|
18
|
+
'plan_mode_reasoning_effort = "medium"',
|
|
19
|
+
"",
|
|
20
|
+
"[agents]",
|
|
21
|
+
"max_threads = 6",
|
|
22
|
+
"max_depth = 4",
|
|
23
|
+
"",
|
|
24
|
+
"[agents.explorer]",
|
|
25
|
+
'config_file = "./agents/explorer.toml"',
|
|
26
|
+
"",
|
|
27
|
+
"[features.multi_agent_v2]",
|
|
28
|
+
"enabled = false",
|
|
29
|
+
"max_concurrent_threads_per_session = 6",
|
|
30
|
+
"",
|
|
31
|
+
].join("\n"),
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
const result = await migrateConfigFile(configPath);
|
|
35
|
+
|
|
36
|
+
const content = await readFile(configPath, "utf8");
|
|
37
|
+
assert.equal(result.changed, true);
|
|
38
|
+
assert.match(content, /\[agents\][\s\S]*?max_threads = 1000/);
|
|
39
|
+
assert.match(content, /max_depth = 4/);
|
|
40
|
+
assert.match(content, /\[agents\.explorer\]\nconfig_file = "\.\/agents\/explorer\.toml"/);
|
|
41
|
+
assert.match(content, /\[features\.multi_agent_v2\][\s\S]*?enabled = false/);
|
|
42
|
+
assert.match(content, /max_concurrent_threads_per_session = 1000/);
|
|
43
|
+
assert.doesNotMatch(content, /^max_threads\s*=\s*6$/m);
|
|
44
|
+
});
|
|
@@ -20,10 +20,19 @@ async function readSkill(skillName) {
|
|
|
20
20
|
return readFile(join(root, "skills", skillName, "SKILL.md"), "utf8");
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
async function readSharedSkill(skillName) {
|
|
24
|
+
return readFile(join(root, "../../shared-skills/skills", skillName, "SKILL.md"), "utf8");
|
|
25
|
+
}
|
|
26
|
+
|
|
23
27
|
function patternFromParts(parts, flags) {
|
|
24
28
|
return new RegExp(parts.join(""), flags);
|
|
25
29
|
}
|
|
26
30
|
|
|
31
|
+
const multiAgentV2RoleGuidance =
|
|
32
|
+
"On `multi_agent_v2` sessions the same `agent_type` applies (the OMO installer exposes it) with `fork_turns` instead of `fork_context`.";
|
|
33
|
+
const loadSkillsGuidance =
|
|
34
|
+
"When translating `load_skills=[...]`, include the requested skill names in the spawned agent's `message`.";
|
|
35
|
+
|
|
27
36
|
test("#given synced aggregate Codex skills #when they contain OpenCode orchestration examples #then Codex tool compatibility guidance is injected", async () => {
|
|
28
37
|
// given
|
|
29
38
|
const opencodeOnlyToolPattern = /\b(?:call_omo_agent|background_output|team_[a-z_]+|task)\s*\(/;
|
|
@@ -41,6 +50,8 @@ test("#given synced aggregate Codex skills #when they contain OpenCode orchestra
|
|
|
41
50
|
compatibilityIndex < content.search(opencodeOnlyToolPattern),
|
|
42
51
|
`${skillName} must explain Codex tool translation before OpenCode-only examples`,
|
|
43
52
|
);
|
|
53
|
+
assert.ok(content.includes(multiAgentV2RoleGuidance), `${skillName} missing multi_agent_v2 role guidance`);
|
|
54
|
+
assert.ok(content.includes(loadSkillsGuidance), `${skillName} missing load_skills guidance`);
|
|
44
55
|
}
|
|
45
56
|
});
|
|
46
57
|
|
|
@@ -77,7 +88,7 @@ task(category="quick", prompt="verify")
|
|
|
77
88
|
assert.ok(compatibilityIndex < firstToolIndex);
|
|
78
89
|
assert.equal(adapted.match(/## Codex Harness Tool Compatibility/g)?.length, 1);
|
|
79
90
|
assert.doesNotMatch(adapted, /Older variant guidance/);
|
|
80
|
-
assert.doesNotMatch(adapted, /
|
|
91
|
+
assert.doesNotMatch(adapted, /name the skills inside the spawned agent's `message`/);
|
|
81
92
|
assert.match(adapted, /\n---\n\n## Next Section/);
|
|
82
93
|
});
|
|
83
94
|
|
|
@@ -141,6 +152,25 @@ call_omo_agent(subagent_type="explore", prompt="inspect")
|
|
|
141
152
|
assert.doesNotMatch(adapted, /Obsolete generated compatibility prose/);
|
|
142
153
|
});
|
|
143
154
|
|
|
155
|
+
test("#given generated Codex compatibility guidance #when adapting a skill #then multi-agent role and load_skills guidance are both present", () => {
|
|
156
|
+
// given
|
|
157
|
+
const content = `---
|
|
158
|
+
name: example
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
# Example Skill
|
|
162
|
+
|
|
163
|
+
task(subagent_type="oracle", load_skills=["debugging"], prompt="verify")
|
|
164
|
+
`;
|
|
165
|
+
|
|
166
|
+
// when
|
|
167
|
+
const adapted = insertCodexCompatibilityGuidance(content);
|
|
168
|
+
|
|
169
|
+
// then
|
|
170
|
+
assert.ok(adapted.includes(multiAgentV2RoleGuidance));
|
|
171
|
+
assert.ok(adapted.includes(loadSkillsGuidance));
|
|
172
|
+
});
|
|
173
|
+
|
|
144
174
|
test("#given generated guidance before a template export #when adapting a skill #then the export wrapper is preserved", () => {
|
|
145
175
|
// given
|
|
146
176
|
const content = `---
|
|
@@ -214,3 +244,22 @@ test("#given review-work skill #when some lanes do not finish #then aggregate re
|
|
|
214
244
|
assert.match(content, /Do not spin in repeated/);
|
|
215
245
|
assert.match(content, /Do not use `multi_agent_v1\.send_input` as an interrupt/);
|
|
216
246
|
});
|
|
247
|
+
|
|
248
|
+
test("#given PR and review skills #when synced for Codex #then worktree lifecycle is mandatory", async () => {
|
|
249
|
+
const startWork = await readSkill("start-work");
|
|
250
|
+
const reviewWork = await readSkill("review-work");
|
|
251
|
+
const sharedStartWork = await readSharedSkill("start-work");
|
|
252
|
+
|
|
253
|
+
assert.match(startWork, /PR creation, PR handoff, branch handoff, or merge/);
|
|
254
|
+
assert.match(startWork, /Finish the PR\/branch lifecycle from its task-owned worktree/);
|
|
255
|
+
assert.match(startWork, /merge by default unless explicitly opted out/);
|
|
256
|
+
assert.match(startWork, /No PR\/branch implementation or review in the main worktree/);
|
|
257
|
+
|
|
258
|
+
assert.match(sharedStartWork, /required for PR\/branch work/);
|
|
259
|
+
assert.match(sharedStartWork, /No PR\/branch implementation, review, or merge in the main worktree/);
|
|
260
|
+
assert.doesNotMatch(sharedStartWork, /If worktree mode was used/);
|
|
261
|
+
assert.doesNotMatch(sharedStartWork, /merge or hand off exactly as requested/);
|
|
262
|
+
|
|
263
|
+
assert.match(reviewWork, /dedicated review worktree attached to that branch/);
|
|
264
|
+
assert.match(reviewWork, /Never\s+checkout, test, or edit the review branch in the main worktree/);
|
|
265
|
+
});
|