oh-my-opencode 4.19.0 → 4.19.2
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/command/omomomo.md +1 -1
- package/.agents/skills/omomomo/SKILL.md +1 -1
- package/.opencode/command/omomomo.md +1 -1
- package/README.ja.md +6 -6
- package/README.ko.md +6 -6
- package/README.md +6 -6
- package/README.ru.md +6 -6
- package/README.zh-cn.md +6 -6
- package/dist/agents/atlas/agent.d.ts +5 -3
- package/dist/agents/explore.d.ts +4 -2
- package/dist/agents/gpt-prompt-identity.d.ts +3 -0
- package/dist/agents/hephaestus/agent.d.ts +4 -2
- package/dist/agents/librarian.d.ts +4 -2
- package/dist/agents/metis.d.ts +4 -2
- package/dist/agents/momus.d.ts +3 -2
- package/dist/agents/multimodal-looker.d.ts +4 -2
- package/dist/agents/oracle.d.ts +4 -2
- package/dist/agents/sisyphus/claude-opus-5.d.ts +33 -0
- package/dist/agents/sisyphus/gpt-5-5.d.ts +1 -1
- package/dist/agents/sisyphus/gpt-task-system-guide.d.ts +1 -0
- package/dist/agents/sisyphus/index.d.ts +2 -0
- package/dist/agents/sisyphus-agent-factory.d.ts +5 -2
- package/dist/agents/sisyphus-junior/agent.d.ts +4 -1
- package/dist/agents/sisyphus-junior/gpt-5-5.d.ts +2 -2
- package/dist/agents/types.d.ts +2 -2
- package/dist/cli/index.js +23577 -19269
- package/dist/cli-node/index.js +23577 -19269
- package/dist/config/schema/agent-names.d.ts +26 -26
- package/dist/config/schema/agent-overrides.d.ts +400 -400
- package/dist/config/schema/browser-automation.d.ts +2 -2
- package/dist/config/schema/categories.d.ts +36 -36
- package/dist/config/schema/codegraph.d.ts +2 -0
- package/dist/config/schema/commands.d.ts +2 -2
- package/dist/config/schema/dynamic-context-pruning.d.ts +1 -1
- package/dist/config/schema/experimental.d.ts +1 -1
- package/dist/config/schema/fallback-models.d.ts +25 -25
- package/dist/config/schema/hooks.d.ts +43 -43
- package/dist/config/schema/internal/permission.d.ts +9 -9
- package/dist/config/schema/keyword-detector.d.ts +6 -6
- package/dist/config/schema/oh-my-opencode-config.d.ts +404 -402
- package/dist/config/schema/tmux.d.ts +6 -6
- package/dist/create-hooks.d.ts +35 -35
- package/dist/features/background-agent/spawner/tmux-callback-invoker.d.ts +11 -0
- package/dist/features/builtin-commands/templates/start-work.d.ts +1 -1
- package/dist/features/claude-tasks/types.d.ts +4 -4
- package/dist/features/team-mode/team-runtime/shutdown-helpers.d.ts +1 -1
- package/dist/features/team-mode/team-runtime/shutdown-test-fixtures.d.ts +4 -4
- package/dist/features/team-mode/tools/lifecycle-test-fixture.d.ts +42 -42
- package/dist/features/tmux-subagent/environment-eligibility.d.ts +2 -0
- package/dist/features/tmux-subagent/index.d.ts +1 -0
- package/dist/features/tmux-subagent/tracked-session-state.d.ts +1 -0
- package/dist/features/tui-sidebar/snapshot-schema.d.ts +6 -6
- package/dist/help/schema/acp.d.ts +3 -3
- package/dist/help/schema/doctor.d.ts +4 -4
- package/dist/help/schema/status.d.ts +3 -3
- package/dist/hooks/codegraph-bootstrap/hook.d.ts +3 -2
- package/dist/hooks/goal/types.d.ts +5 -5
- package/dist/hooks/non-interactive-env/constants.d.ts +4 -1
- package/dist/hooks/sisyphus-junior-notepad/constants.d.ts +1 -1
- package/dist/hooks/start-work/notepad-scaffold.d.ts +10 -0
- package/dist/hooks/start-work/parse-user-request.d.ts +2 -0
- package/dist/hooks/start-work/worktree-block.d.ts +5 -0
- package/dist/index.js +27370 -21301
- package/dist/mcp/types.d.ts +3 -3
- package/dist/oh-my-opencode.schema.json +11 -0
- package/dist/plugin/chat-message/loop-commands.d.ts +1 -0
- package/dist/plugin/command-execute-before.d.ts +3 -3
- package/dist/plugin/hooks/create-core-hooks.d.ts +25 -25
- package/dist/shared/omo-process-sweep.d.ts +18 -0
- package/dist/shared/tmux/tmux-utils/environment.d.ts +1 -1
- package/dist/shared/tmux/tmux-utils.d.ts +1 -1
- package/dist/shared/typescript-native-source-parser.d.ts +7 -0
- package/dist/skills/coding-agent-sessions/SKILL.md +5 -2
- package/dist/skills/coding-agent-sessions/references/all-platforms.md +3 -1
- package/dist/skills/coding-agent-sessions/references/senpi.md +15 -5
- package/dist/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +46 -0
- package/dist/skills/coding-agent-sessions/scripts/agent_sessions/scanners.py +19 -10
- package/dist/skills/debugging/SKILL.md +2 -1
- package/dist/skills/debugging/references/methodology/03-flaky-triage.md +47 -0
- package/dist/skills/programming/SKILL.md +11 -1
- package/dist/skills/programming/references/logging.md +6 -1
- package/dist/skills/programming/scripts/typescript/check-no-excuse-rules.test.ts +87 -0
- package/dist/skills/programming/scripts/typescript/check-no-excuse-rules.ts +75 -11
- package/dist/skills/start-work/SKILL.md +12 -2
- package/dist/skills/ulw-plan/SKILL.md +21 -2
- package/dist/skills/ulw-plan/references/full-workflow.md +12 -1
- package/dist/skills/ulw-plan/references/intent-clear.md +1 -1
- package/dist/testing/create-plugin-module.d.ts +1 -0
- package/dist/tools/task/types.d.ts +10 -10
- package/dist/tui.js +23442 -19182
- package/package.json +14 -14
- package/packages/git-bash-mcp/dist/cli.js +54 -8
- package/packages/lsp-core/src/lsp/client-diagnostics-freshness.integration.test.ts +62 -2
- package/packages/lsp-core/src/lsp/client.ts +14 -1
- package/packages/lsp-core/src/lsp/fixtures/diagnostics-freshness-contract-probe.ts +2 -2
- package/packages/lsp-core/src/mcp.ts +9 -0
- package/packages/lsp-daemon/dist/cli.js +319 -51
- package/packages/lsp-daemon/dist/client.js +136 -48
- package/packages/lsp-daemon/dist/daemon-client.d.ts +0 -10
- package/packages/lsp-daemon/dist/daemon-client.js +4 -34
- package/packages/lsp-daemon/dist/daemon-failure-result.d.ts +3 -0
- package/packages/lsp-daemon/dist/daemon-failure-result.js +38 -0
- package/packages/lsp-daemon/dist/daemon-request-error.d.ts +14 -0
- package/packages/lsp-daemon/dist/daemon-request-error.js +26 -0
- package/packages/lsp-daemon/dist/daemon-server.js +5 -1
- package/packages/lsp-daemon/dist/index.js +137 -48
- package/packages/lsp-daemon/dist/proxy.d.ts +2 -0
- package/packages/lsp-daemon/dist/proxy.js +1 -0
- package/packages/lsp-daemon/dist/version-reap.d.ts +26 -0
- package/packages/lsp-daemon/dist/version-reap.js +182 -0
- package/packages/lsp-tools-mcp/dist/cli.js +61 -10
- package/packages/lsp-tools-mcp/dist/lsp/manager.js +6 -1
- package/packages/lsp-tools-mcp/dist/mcp.js +61 -10
- package/packages/lsp-tools-mcp/dist/tools.js +6 -1
- package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +72 -12
- package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/src/setup.ts +22 -2
- package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +779 -385
- package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +302 -173
- package/packages/omo-codex/plugin/components/codegraph/package.json +2 -2
- package/packages/omo-codex/plugin/components/codegraph/src/hook-types.ts +3 -1
- package/packages/omo-codex/plugin/components/codegraph/src/hook.ts +23 -42
- package/packages/omo-codex/plugin/components/codegraph/src/mcp-bridge.ts +98 -32
- package/packages/omo-codex/plugin/components/codegraph/src/mcp-unavailable.ts +5 -0
- package/packages/omo-codex/plugin/components/codegraph/src/serve.ts +17 -9
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker.ts +18 -25
- package/packages/omo-codex/plugin/components/codegraph/src/sweep-cli.ts +1 -0
- package/packages/omo-codex/plugin/components/codegraph/test/hook-exclusion.test.ts +5 -0
- package/packages/omo-codex/plugin/components/codegraph/test/hook-store-upgrade.test.ts +176 -0
- package/packages/omo-codex/plugin/components/codegraph/test/hook.test.ts +6 -1
- package/packages/omo-codex/plugin/components/codegraph/test/mcp-bridge-fixtures.ts +31 -2
- package/packages/omo-codex/plugin/components/codegraph/test/package-runtime.test.ts +1 -1
- package/packages/omo-codex/plugin/components/codegraph/test/provisioned-node-guard.test.ts +6 -0
- package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge-lifecycle.test.ts +65 -1
- package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge.test.ts +3 -7
- package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-facade.test.ts +2 -1
- package/packages/omo-codex/plugin/components/codegraph/test/serve-provision.test.ts +57 -3
- package/packages/omo-codex/plugin/components/codegraph/test/serve-unavailable.test.ts +42 -0
- package/packages/omo-codex/plugin/components/codegraph/test/serve.test.ts +122 -10
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-node-support.test.ts +2 -2
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-flow.test.ts +101 -64
- package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
- package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
- package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +3 -3
- package/packages/omo-codex/plugin/components/lsp/dist/cli.js +80 -40
- package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
- package/packages/omo-codex/plugin/components/rules/dist/cli.js +11 -0
- package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
- package/packages/omo-codex/plugin/components/rules/package.json +1 -1
- package/packages/omo-codex/plugin/components/rules/src/post-compact-budget.ts +11 -0
- package/packages/omo-codex/plugin/components/rules/test/post-compact-budget.test.ts +60 -0
- package/packages/omo-codex/plugin/components/start-work-continuation/directive.md +1 -1
- package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/start-work-continuation/package.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
- package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-clone-fidelity-reviewer.toml +2 -2
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-code-reviewer.toml +2 -2
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-gate-reviewer.toml +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-worker-high.toml +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-worker-medium.toml +2 -2
- package/packages/omo-codex/plugin/components/ultrawork/agents/plan.toml +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/directive.md +12 -7
- package/packages/omo-codex/plugin/components/ultrawork/dist/cli.js +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/skills/ultrawork/SKILL.md +12 -7
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +21 -2
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +12 -1
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-clear.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 +42 -0
- package/packages/omo-codex/plugin/components/ulw-loop/README.md +6 -4
- package/packages/omo-codex/plugin/components/ulw-loop/directive.md +12 -7
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-continuation.d.ts +21 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-continuation.js +64 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.js +15 -2
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-arg-parser.js +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-commands.js +2 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.d.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.js +3 -3
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-steering.d.ts +3 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-steering.js +85 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-subcommands.d.ts +0 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-subcommands.js +13 -33
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +998 -593
- package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.js +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/constants.d.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/constants.js +2 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/domain-types.d.ts +6 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/goal-status.d.ts +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/goal-status.js +3 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-crud.d.ts +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-crud.js +4 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.d.ts +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.js +10 -2
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-verdicts.js +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-batch.d.ts +15 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-batch.js +84 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-mutations.d.ts +5 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-mutations.js +81 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/steering.js +7 -59
- package/packages/omo-codex/plugin/components/ulw-loop/dist/stop-resume-hook.js +12 -4
- package/packages/omo-codex/plugin/components/ulw-loop/dist/validation-batch.d.ts +9 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/validation-batch.js +122 -0
- package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
- package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/SKILL.md +2 -1
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +8 -6
- package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-continuation.ts +84 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint.ts +13 -2
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-arg-parser.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-commands.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-output.ts +3 -3
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-steering.ts +49 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-subcommands.ts +13 -45
- package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-instruction.ts +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/constants.ts +2 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/domain-types.ts +7 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/goal-status.ts +4 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/plan-crud.ts +4 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/plan-io.ts +20 -2
- package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-verdicts.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/steering-batch.ts +125 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/steering-mutations.ts +59 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/steering.ts +6 -58
- package/packages/omo-codex/plugin/components/ulw-loop/src/stop-resume-hook.ts +12 -4
- package/packages/omo-codex/plugin/components/ulw-loop/src/validation-batch.ts +122 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-continuation.test.ts +76 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-checkpoint-continuation.test.ts +111 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-steering-batch.test.ts +67 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-validation-batch.test.ts +57 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/paths.test.ts +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/steering-batch.test.ts +152 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/stop-resume-hook.test.ts +29 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/validation-batch-checkpoint.test.ts +147 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/validation-batch.test.ts +73 -0
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +2 -2
- package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +2 -2
- package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +2 -2
- package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +1 -1
- package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
- package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +1 -1
- package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
- package/packages/omo-codex/plugin/package-lock.json +41 -41
- package/packages/omo-codex/plugin/package.json +1 -1
- package/packages/omo-codex/plugin/shared/test/config-loader.test.ts +44 -0
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/SKILL.md +5 -2
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/all-platforms.md +3 -1
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/senpi.md +15 -5
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +46 -0
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/scanners.py +19 -10
- package/packages/omo-codex/plugin/skills/debugging/SKILL.md +2 -1
- package/packages/omo-codex/plugin/skills/debugging/references/methodology/03-flaky-triage.md +47 -0
- package/packages/omo-codex/plugin/skills/programming/SKILL.md +11 -1
- package/packages/omo-codex/plugin/skills/programming/references/logging.md +6 -1
- package/packages/omo-codex/plugin/skills/programming/scripts/typescript/check-no-excuse-rules.ts +75 -11
- package/packages/omo-codex/plugin/skills/start-work/SKILL.md +12 -2
- package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +12 -7
- package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +2 -1
- package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +8 -6
- package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +21 -2
- package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +12 -1
- package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-clear.md +1 -1
- package/packages/omo-codex/plugin/test/aggregate-agents.test.mjs +9 -9
- package/packages/omo-codex/plugin/test/aggregate-hooks.test.mjs +26 -0
- package/packages/omo-codex/plugin/test/bootstrap-setup.test.mjs +41 -0
- package/packages/omo-codex/plugin/test/sync-skills-orchestration.test.mjs +22 -0
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +49 -5
- package/packages/omo-codex/scripts/install-marketplace-cache.test.mjs +4 -1
- package/packages/shared-skills/skills/coding-agent-sessions/SKILL.md +5 -2
- package/packages/shared-skills/skills/coding-agent-sessions/references/all-platforms.md +3 -1
- package/packages/shared-skills/skills/coding-agent-sessions/references/senpi.md +15 -5
- package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +46 -0
- package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/scanners.py +19 -10
- package/packages/shared-skills/skills/debugging/SKILL.md +2 -1
- package/packages/shared-skills/skills/debugging/references/methodology/03-flaky-triage.md +47 -0
- package/packages/shared-skills/skills/programming/SKILL.md +11 -1
- package/packages/shared-skills/skills/programming/references/logging.md +6 -1
- package/packages/shared-skills/skills/programming/scripts/typescript/check-no-excuse-rules.test.ts +87 -0
- package/packages/shared-skills/skills/programming/scripts/typescript/check-no-excuse-rules.ts +75 -11
- package/packages/shared-skills/skills/start-work/SKILL.md +12 -2
- package/packages/shared-skills/skills/ulw-plan/SKILL.md +21 -2
- package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +12 -1
- package/packages/shared-skills/skills/ulw-plan/references/intent-clear.md +1 -1
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { checkpointUlwLoop } from "./checkpoint.js";
|
|
2
|
+
import { hasFlag, parseCodexGoalJson, readValue } from "./cli-arg-parser.js";
|
|
3
|
+
import { blockedDecisionHandoff, printJson } from "./cli-output.js";
|
|
4
|
+
import { buildCodexGoalInstruction } from "./codex-goal-instruction.js";
|
|
5
|
+
import { startNextUlwLoop, summarizeUlwLoopPlan } from "./plan-crud.js";
|
|
6
|
+
import { UlwLoopError } from "./types.js";
|
|
7
|
+
export async function checkpointAndContinue(repoRoot, args, scope) {
|
|
8
|
+
const result = await checkpointUlwLoop(repoRoot, args, scope);
|
|
9
|
+
if (args.status !== "complete" || result.aggregateCompletion !== undefined || !args.advance)
|
|
10
|
+
return result;
|
|
11
|
+
const next = await startNextUlwLoop(repoRoot, {}, scope);
|
|
12
|
+
if ("done" in next)
|
|
13
|
+
return { ...result, plan: next.plan, next: doneNext(next.plan) };
|
|
14
|
+
const instruction = buildCodexGoalInstruction({ plan: next.plan, goal: next.goal });
|
|
15
|
+
return { ...result, plan: next.plan, next: { resumed: next.resumed, goal: next.goal, instruction } };
|
|
16
|
+
}
|
|
17
|
+
export async function checkpoint(repoRoot, argv, json, scope) {
|
|
18
|
+
const goalId = required(argv, "--goal-id");
|
|
19
|
+
const statusValue = checkpointStatus(required(argv, "--status"));
|
|
20
|
+
const evidence = required(argv, "--evidence");
|
|
21
|
+
const codexGoalJson = await parseCodexGoalJson(statusValue === "complete" ? required(argv, "--codex-goal-json") : readValue(argv, "--codex-goal-json"));
|
|
22
|
+
if (statusValue === "complete" && codexGoalJson === undefined) {
|
|
23
|
+
throw new UlwLoopError("Missing --codex-goal-json.", "ULW_LOOP_CODEX_GOAL_JSON_REQUIRED");
|
|
24
|
+
}
|
|
25
|
+
const qualityGateJson = readValue(argv, "--quality-gate-json");
|
|
26
|
+
const args = {
|
|
27
|
+
goalId,
|
|
28
|
+
status: statusValue,
|
|
29
|
+
evidence,
|
|
30
|
+
advance: !hasFlag(argv, "--no-advance"),
|
|
31
|
+
...(codexGoalJson === undefined ? {} : { codexGoalJson }),
|
|
32
|
+
...(qualityGateJson === undefined ? {} : { qualityGateJson }),
|
|
33
|
+
};
|
|
34
|
+
const result = await checkpointAndContinue(repoRoot, args, scope);
|
|
35
|
+
if (json)
|
|
36
|
+
printJson({ ok: true, ...result, summary: summarizeUlwLoopPlan(result.plan) });
|
|
37
|
+
else
|
|
38
|
+
printCheckpointText(result);
|
|
39
|
+
return 0;
|
|
40
|
+
}
|
|
41
|
+
function printCheckpointText(result) {
|
|
42
|
+
process.stdout.write(`ulw-loop checkpoint: ${result.goal.id} -> ${result.goal.status}\n`);
|
|
43
|
+
if (result.next === undefined)
|
|
44
|
+
return;
|
|
45
|
+
if ("instruction" in result.next)
|
|
46
|
+
process.stdout.write(`${result.next.instruction.text}\n`);
|
|
47
|
+
else
|
|
48
|
+
process.stdout.write(`${result.next.handoff || "ulw-loop: all goals complete"}\n`);
|
|
49
|
+
}
|
|
50
|
+
function doneNext(plan) {
|
|
51
|
+
const handoff = blockedDecisionHandoff(plan);
|
|
52
|
+
return { done: true, blocked: handoff.length > 0, handoff };
|
|
53
|
+
}
|
|
54
|
+
function required(argv, flag) {
|
|
55
|
+
const value = readValue(argv, flag)?.trim();
|
|
56
|
+
if (value)
|
|
57
|
+
return value;
|
|
58
|
+
throw new UlwLoopError(`Missing ${flag}.`, "ULW_LOOP_ARGUMENT_MISSING", { details: { flag } });
|
|
59
|
+
}
|
|
60
|
+
function checkpointStatus(value) {
|
|
61
|
+
if (value === "complete" || value === "failed" || value === "blocked")
|
|
62
|
+
return value;
|
|
63
|
+
throw new UlwLoopError("Missing or invalid --status; expected complete, failed, or blocked.", "ULW_LOOP_STATUS_INVALID", { details: { status: value } });
|
|
64
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
// biome-ignore-all format: checkpoint stays under the pure LOC ceiling.
|
|
2
2
|
import { existsSync, statSync } from "node:fs";
|
|
3
3
|
import { readFile } from "node:fs/promises";
|
|
4
4
|
import { resolve } from "node:path";
|
|
@@ -6,9 +6,11 @@ import { buildTaskScopedAggregateReconciliationHint, canReconcileActiveFinalTask
|
|
|
6
6
|
import { formatCodexGoalReconciliation, readCodexGoalSnapshotInput, reconcileCodexGoalSnapshot, } from "./codex-goal-snapshot.js";
|
|
7
7
|
import { requireAllCriteriaPass, requireAllPlanCriteriaPass, requireEssentialCriteriaPass } from "./evidence.js";
|
|
8
8
|
import { codexGoalMode, compatibleCodexObjectives, expectedCodexObjective, isFinalRunCompletionCandidate, } from "./goal-status.js";
|
|
9
|
+
import { ulwLoopAttemptEvidenceDir } from "./paths.js";
|
|
9
10
|
import { appendLedger, readUlwLoopPlan, withUlwLoopMutationLock, writePlan } from "./plan-io.js";
|
|
10
11
|
import { classifyExternalAuthorizationBlocker, clearGoalBlockerFields, sameBlockerOccurrences, validateQualityGate, } from "./quality-gate.js";
|
|
11
12
|
import { iso, UlwLoopError } from "./types.js";
|
|
13
|
+
import { batchClosedBy, requireAllValidationBatchesClosed, requireBatchFinalReady, requireBatchGate } from "./validation-batch.js";
|
|
12
14
|
const QUALITY_GATE_FS = { existsSync, statSync };
|
|
13
15
|
function ulwLoopFail(message, code) {
|
|
14
16
|
throw new UlwLoopError(message, code);
|
|
@@ -112,9 +114,11 @@ export async function checkpointUlwLoop(repoRoot, args, scope) {
|
|
|
112
114
|
if (args.status === "complete") {
|
|
113
115
|
const aggregate = codexGoalMode(plan) === "aggregate";
|
|
114
116
|
const final = isFinalRunCompletionCandidate(plan, goal);
|
|
117
|
+
const closesBatch = batchClosedBy(plan, goal.id) !== undefined;
|
|
115
118
|
if (final) {
|
|
116
119
|
requireAllCriteriaPass(goal);
|
|
117
120
|
requireAllPlanCriteriaPass(plan);
|
|
121
|
+
requireAllValidationBatchesClosed(plan, goal.id);
|
|
118
122
|
}
|
|
119
123
|
else if (aggregate)
|
|
120
124
|
requireEssentialCriteriaPass(goal);
|
|
@@ -144,9 +148,13 @@ export async function checkpointUlwLoop(repoRoot, args, scope) {
|
|
|
144
148
|
if (!taskScoped)
|
|
145
149
|
throw new UlwLoopError(`${formatCodexGoalReconciliation(reconciliation)}${aggregate && snapshot?.status === "complete" && objective !== undefined ? buildTaskScopedAggregateReconciliationHint(goal, final) : ""}`, "ulw_loop_codex_snapshot_mismatch");
|
|
146
150
|
}
|
|
151
|
+
if (closesBatch)
|
|
152
|
+
requireBatchFinalReady(plan, goal);
|
|
153
|
+
if (closesBatch && args.qualityGateJson === undefined)
|
|
154
|
+
throw new UlwLoopError("Validation batch final checkpoint requires --quality-gate-json.", "ULW_LOOP_VALIDATION_BATCH_GATE_REQUIRED");
|
|
147
155
|
if (final)
|
|
148
156
|
aggregateCompletion = makeAggregateCompletion(now, evidence, codexGoal);
|
|
149
|
-
if (final || aggregateCompletion !== undefined)
|
|
157
|
+
if (final || aggregateCompletion !== undefined || closesBatch) {
|
|
150
158
|
qualityGate = validateQualityGate(await readJsonInput(args.qualityGateJson, repoRoot), {
|
|
151
159
|
repoRoot,
|
|
152
160
|
fs: QUALITY_GATE_FS,
|
|
@@ -154,6 +162,8 @@ export async function checkpointUlwLoop(repoRoot, args, scope) {
|
|
|
154
162
|
? { currentAttemptDir: ulwLoopAttemptEvidenceDir(goal.id, goal.attempt, scope) }
|
|
155
163
|
: {}),
|
|
156
164
|
});
|
|
165
|
+
requireBatchGate(plan, goal, qualityGate);
|
|
166
|
+
}
|
|
157
167
|
goal.status = "complete";
|
|
158
168
|
goal.completedAt = now;
|
|
159
169
|
goal.evidence = evidence;
|
|
@@ -172,6 +182,9 @@ export async function checkpointUlwLoop(repoRoot, args, scope) {
|
|
|
172
182
|
await writePlan(repoRoot, plan, scope);
|
|
173
183
|
const ledgerEntry = buildLedger(now, args, goal, qualityGate, codexGoal, aggregateCompletion);
|
|
174
184
|
await appendLedger(repoRoot, ledgerEntry, scope);
|
|
185
|
+
const closedBatch = args.status === "complete" ? batchClosedBy(plan, goal.id) : undefined;
|
|
186
|
+
if (closedBatch !== undefined)
|
|
187
|
+
await appendLedger(repoRoot, { at: now, kind: "batch_closed", goalId: goal.id, message: closedBatch.batchId }, scope);
|
|
175
188
|
return aggregateCompletion === undefined
|
|
176
189
|
? { plan, goal, ledgerEntry }
|
|
177
190
|
: { plan, goal, ledgerEntry, aggregateCompletion };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// biome-ignore-all format: keep this module under the mandated pure LOC budget.
|
|
2
2
|
import { readFile } from "node:fs/promises";
|
|
3
3
|
import { UlwLoopError } from "./types.js";
|
|
4
|
-
const VALUE_FLAGS = new Set("--brief --brief-file --session-id --codex-goal-mode --goal --goal-id --criterion-id --status --evidence --notes --codex-goal-json --quality-gate-json --kind --rationale --title --objective --target-goal-id --source --after-json --directive-json --directive-file --idempotency-key".split(" "));
|
|
4
|
+
const VALUE_FLAGS = new Set("--brief --brief-file --session-id --codex-goal-mode --validation-batch-json --goal --goal-id --criterion-id --status --evidence --notes --codex-goal-json --quality-gate-json --kind --rationale --title --objective --target-goal-id --source --after-json --directive-json --directive-file --idempotency-key --proposals-json".split(" "));
|
|
5
5
|
const SUBCOMMANDS = new Set("create-goals status complete-goals criteria record-evidence checkpoint steer add-goal record-review-blockers".split(" "));
|
|
6
6
|
export function hasFlag(argv, flag) { return argv.includes(flag); }
|
|
7
7
|
export function readValue(argv, flag) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { checkpoint } from "./checkpoint-continuation.js";
|
|
1
2
|
import { hasFlag, readValue } from "./cli-arg-parser.js";
|
|
2
3
|
import { printJsonError, ULW_LOOP_HELP } from "./cli-output.js";
|
|
3
|
-
import { addGoal, captureEvidence,
|
|
4
|
+
import { addGoal, captureEvidence, completeGoals, createGoals, criteria, reviewBlockers, status, steer, } from "./cli-subcommands.js";
|
|
4
5
|
import { resolveUlwLoopSessionIdFromEnv } from "./paths.js";
|
|
5
6
|
import { UlwLoopError } from "./types.js";
|
|
6
7
|
export const ULW_LOOP_SUBCOMMANDS = [
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { UlwLoopCodexGoalMode, UlwLoopPlan } from "./types.js";
|
|
2
|
-
export declare const ULW_LOOP_HELP = "Usage:\n omo ulw-loop create-goals --brief \"...\" [--brief-file <path>] [--from-stdin] [--codex-goal-mode aggregate|per_story] [--force] [--json]\n omo ulw-loop status [--json]\n omo ulw-loop complete-goals [--retry-failed] [--json]\n omo ulw-loop criteria --goal-id <id> [--json]\n omo ulw-loop record-evidence --goal-id <id> --criterion-id <id> --status pass|fail|blocked --evidence \"...\" [--notes \"...\"] [--json]\n omo ulw-loop checkpoint --goal-id <id> --status complete|failed|blocked --evidence \"...\" --codex-goal-json <...> [--quality-gate-json <...>] [--json]\n omo ulw-loop steer --kind <kind> ... --evidence \"...\" --rationale \"...\" [--json]\n omo ulw-loop add-goal --title \"...\" --objective \"...\" [--json]\n omo ulw-loop record-review-blockers --goal-id <id> --title \"...\" --objective \"...\" --evidence \"...\" --codex-goal-json <...> [--json]\n\nAll subcommands accept [--session-id <id>] to isolate state under .omo/ulw-loop/<id>/; without it, Codex session env is used when present.";
|
|
2
|
+
export declare const ULW_LOOP_HELP = "Usage:\n omo ulw-loop create-goals --brief \"...\" [--brief-file <path>] [--from-stdin] [--codex-goal-mode aggregate|per_story] [--validation-batch-json <json-or-path>] [--force] [--json]\n omo ulw-loop status [--json]\n omo ulw-loop complete-goals [--retry-failed] [--json]\n omo ulw-loop criteria --goal-id <id> [--json]\n omo ulw-loop record-evidence --goal-id <id> --criterion-id <id> --status pass|fail|blocked --evidence \"...\" [--notes \"...\"] [--json]\n omo ulw-loop checkpoint --goal-id <id> --status complete|failed|blocked --evidence \"...\" --codex-goal-json <...> [--quality-gate-json <...>] [--no-advance] [--json]\n omo ulw-loop steer --kind <kind> ... --evidence \"...\" --rationale \"...\" [--proposals-json <json-or-path>] [--json]\n omo ulw-loop add-goal --title \"...\" --objective \"...\" [--json]\n omo ulw-loop record-review-blockers --goal-id <id> --title \"...\" --objective \"...\" --evidence \"...\" --codex-goal-json <...> [--json]\n\nAll subcommands accept [--session-id <id>] to isolate state under .omo/ulw-loop/<id>/; without it, Codex session env is used when present.";
|
|
3
3
|
export declare function printJson(value: unknown): void;
|
|
4
4
|
export declare function printJsonError(error: unknown): void;
|
|
5
5
|
export declare function printStatus(plan: UlwLoopPlan): void;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { UlwLoopError } from "./types.js";
|
|
2
2
|
export const ULW_LOOP_HELP = `Usage:
|
|
3
|
-
omo ulw-loop create-goals --brief "..." [--brief-file <path>] [--from-stdin] [--codex-goal-mode aggregate|per_story] [--force] [--json]
|
|
3
|
+
omo ulw-loop create-goals --brief "..." [--brief-file <path>] [--from-stdin] [--codex-goal-mode aggregate|per_story] [--validation-batch-json <json-or-path>] [--force] [--json]
|
|
4
4
|
omo ulw-loop status [--json]
|
|
5
5
|
omo ulw-loop complete-goals [--retry-failed] [--json]
|
|
6
6
|
omo ulw-loop criteria --goal-id <id> [--json]
|
|
7
7
|
omo ulw-loop record-evidence --goal-id <id> --criterion-id <id> --status pass|fail|blocked --evidence "..." [--notes "..."] [--json]
|
|
8
|
-
omo ulw-loop checkpoint --goal-id <id> --status complete|failed|blocked --evidence "..." --codex-goal-json <...> [--quality-gate-json <...>] [--json]
|
|
9
|
-
omo ulw-loop steer --kind <kind> ... --evidence "..." --rationale "..." [--json]
|
|
8
|
+
omo ulw-loop checkpoint --goal-id <id> --status complete|failed|blocked --evidence "..." --codex-goal-json <...> [--quality-gate-json <...>] [--no-advance] [--json]
|
|
9
|
+
omo ulw-loop steer --kind <kind> ... --evidence "..." --rationale "..." [--proposals-json <json-or-path>] [--json]
|
|
10
10
|
omo ulw-loop add-goal --title "..." --objective "..." [--json]
|
|
11
11
|
omo ulw-loop record-review-blockers --goal-id <id> --title "..." --objective "..." --evidence "..." --codex-goal-json <...> [--json]
|
|
12
12
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { SteerUlwLoopBatchResult } from "./steering-batch.js";
|
|
1
2
|
import type { SteerUlwLoopResult, UlwLoopSteeringMutationKind, UlwLoopSteeringProposal, UlwLoopSteeringSource, UlwLoopSuccessCriterionUserModel } from "./types.js";
|
|
2
3
|
export type CliSteeringProposal = UlwLoopSteeringProposal & {
|
|
3
4
|
readonly goalId?: string;
|
|
@@ -9,4 +10,6 @@ export declare function parseSteeringKind(argv: readonly string[]): UlwLoopSteer
|
|
|
9
10
|
export declare function parseSteeringSource(argv: readonly string[]): UlwLoopSteeringSource;
|
|
10
11
|
export declare function parseSteeringProposal(argv: readonly string[]): Promise<CliSteeringProposal>;
|
|
11
12
|
export declare function normalizeSteeringProposal(proposal: CliSteeringProposal): CliSteeringProposal;
|
|
13
|
+
export declare function parseSteeringProposals(argv: readonly string[]): Promise<readonly CliSteeringProposal[]>;
|
|
12
14
|
export declare function printSteerResult(result: SteerUlwLoopResult, json: boolean): void;
|
|
15
|
+
export declare function printSteerBatchResult(result: SteerUlwLoopBatchResult, json: boolean): void;
|
|
@@ -28,6 +28,16 @@ function requiredGoal(argv) { const value = text(parseGoalArg(argv), "--goal-id"
|
|
|
28
28
|
function readObject(value, key) { return Object.entries(value).find(([name]) => name === key)?.[1]; }
|
|
29
29
|
function isPlain(value) { return typeof value === "object" && value !== null && !Array.isArray(value); }
|
|
30
30
|
function objectText(value, key) { const candidate = readObject(value, key); return typeof candidate === "string" ? candidate : undefined; }
|
|
31
|
+
function objectStrings(value, key) { const candidate = readObject(value, key); return Array.isArray(candidate) && candidate.every((item) => typeof item === "string") ? candidate : undefined; }
|
|
32
|
+
function objectChildren(value, key) { const candidate = readObject(value, key); if (!Array.isArray(candidate))
|
|
33
|
+
return undefined; const parsed = []; for (const item of candidate) {
|
|
34
|
+
const next = child(item);
|
|
35
|
+
if (next === null)
|
|
36
|
+
return fail(`${key} entries require title/objective.`, "ULW_LOOP_STEERING_CHILD_INVALID", { key });
|
|
37
|
+
parsed.push(next);
|
|
38
|
+
} return parsed; }
|
|
39
|
+
function isProposalKind(value) { return typeof value === "string" && ULW_LOOP_STEERING_MUTATION_KINDS.some((kind) => kind === value); }
|
|
40
|
+
function isProposalSource(value) { return typeof value === "string" && SOURCES.some((source) => source === value); }
|
|
31
41
|
export function parseSteeringKind(argv) {
|
|
32
42
|
const value = readValue(argv, "--kind");
|
|
33
43
|
if (isKind(value))
|
|
@@ -144,6 +154,71 @@ export function normalizeSteeringProposal(proposal) {
|
|
|
144
154
|
const pendingOrder = normalizedStrings(proposal.pendingOrder, "pendingOrder");
|
|
145
155
|
return { kind: proposal.kind, source: proposal.source, evidence, rationale, ...(goalId === undefined ? {} : { goalId }), ...(targetGoalId === undefined ? {} : { targetGoalId }), ...(targetGoalIds === undefined ? {} : { targetGoalIds }), ...(criterionId === undefined ? {} : { criterionId }), ...(title === undefined ? {} : { title }), ...(objective === undefined ? {} : { objective }), ...(childGoals === undefined ? {} : { childGoals }), ...(revisedTitle === undefined ? {} : { revisedTitle }), ...(revisedObjective === undefined ? {} : { revisedObjective }), ...(pendingOrder === undefined ? {} : { pendingOrder }), ...(blockedReason === undefined ? {} : { blockedReason }), ...(proposal.after === undefined ? {} : { after: proposal.after }), ...(directiveText === undefined ? {} : { directiveText }), ...(promptSignature === undefined ? {} : { promptSignature }), ...(idempotencyKey === undefined ? {} : { idempotencyKey }), ...(proposal.now === undefined ? {} : { now: proposal.now }), ...(scenario === undefined ? {} : { scenario }), ...(expectedEvidence === undefined ? {} : { expectedEvidence }), ...(proposal.userModel === undefined ? {} : { userModel: proposal.userModel }) };
|
|
146
156
|
}
|
|
157
|
+
export async function parseSteeringProposals(argv) {
|
|
158
|
+
const input = text(readValue(argv, "--proposals-json"), "--proposals-json");
|
|
159
|
+
if (input === undefined)
|
|
160
|
+
return [await parseSteeringProposal(argv)];
|
|
161
|
+
if (readValue(argv, "--kind") !== undefined)
|
|
162
|
+
return fail("--kind and --proposals-json are mutually exclusive.", "ULW_LOOP_STEERING_BATCH_CONFLICT", { flags: ["--kind", "--proposals-json"] });
|
|
163
|
+
const raw = await readJsonInput(input);
|
|
164
|
+
if (!Array.isArray(raw) || raw.length === 0)
|
|
165
|
+
return fail("--proposals-json must be a non-empty JSON array.", "ULW_LOOP_STEERING_BATCH_ARRAY_REQUIRED", { flag: "--proposals-json" });
|
|
166
|
+
const proposals = [];
|
|
167
|
+
for (const item of raw)
|
|
168
|
+
proposals.push(normalizeSteeringProposal(proposalFromObject(item)));
|
|
169
|
+
return proposals;
|
|
170
|
+
}
|
|
171
|
+
function proposalFromObject(value) {
|
|
172
|
+
if (!isPlain(value))
|
|
173
|
+
return fail("--proposals-json entries must be objects.", "ULW_LOOP_STEERING_BATCH_ITEM_INVALID", { flag: "--proposals-json" });
|
|
174
|
+
const kind = readObject(value, "kind");
|
|
175
|
+
const source = readObject(value, "source") ?? "cli";
|
|
176
|
+
if (!isProposalKind(kind))
|
|
177
|
+
return fail(`Invalid batch steering kind: ${String(kind)}.`, "ULW_LOOP_STEERING_KIND_INVALID", { value: kind });
|
|
178
|
+
if (!isProposalSource(source))
|
|
179
|
+
return fail(`Invalid batch steering source: ${String(source)}.`, "ULW_LOOP_STEERING_SOURCE_INVALID", { value: source });
|
|
180
|
+
let proposal = { kind, source, evidence: objectText(value, "evidence") ?? "", rationale: objectText(value, "rationale") ?? "" };
|
|
181
|
+
const goalId = objectText(value, "goalId");
|
|
182
|
+
const targetGoalId = objectText(value, "targetGoalId");
|
|
183
|
+
const criterionId = objectText(value, "criterionId");
|
|
184
|
+
const title = objectText(value, "title");
|
|
185
|
+
const objective = objectText(value, "objective");
|
|
186
|
+
const revisedTitle = objectText(value, "revisedTitle");
|
|
187
|
+
const revisedObjective = objectText(value, "revisedObjective");
|
|
188
|
+
const scenario = objectText(value, "scenario");
|
|
189
|
+
const expectedEvidence = objectText(value, "expectedEvidence");
|
|
190
|
+
const idempotencyKey = objectText(value, "idempotencyKey");
|
|
191
|
+
const targetGoalIds = objectStrings(value, "targetGoalIds");
|
|
192
|
+
const pendingOrder = objectStrings(value, "pendingOrder");
|
|
193
|
+
const childGoals = objectChildren(value, "childGoals");
|
|
194
|
+
if (goalId !== undefined)
|
|
195
|
+
proposal = { ...proposal, goalId };
|
|
196
|
+
if (targetGoalId !== undefined)
|
|
197
|
+
proposal = { ...proposal, targetGoalId };
|
|
198
|
+
if (criterionId !== undefined)
|
|
199
|
+
proposal = { ...proposal, criterionId };
|
|
200
|
+
if (title !== undefined)
|
|
201
|
+
proposal = { ...proposal, title };
|
|
202
|
+
if (objective !== undefined)
|
|
203
|
+
proposal = { ...proposal, objective };
|
|
204
|
+
if (revisedTitle !== undefined)
|
|
205
|
+
proposal = { ...proposal, revisedTitle };
|
|
206
|
+
if (revisedObjective !== undefined)
|
|
207
|
+
proposal = { ...proposal, revisedObjective };
|
|
208
|
+
if (scenario !== undefined)
|
|
209
|
+
proposal = { ...proposal, scenario };
|
|
210
|
+
if (expectedEvidence !== undefined)
|
|
211
|
+
proposal = { ...proposal, expectedEvidence };
|
|
212
|
+
if (idempotencyKey !== undefined)
|
|
213
|
+
proposal = { ...proposal, idempotencyKey };
|
|
214
|
+
if (targetGoalIds !== undefined)
|
|
215
|
+
proposal = { ...proposal, targetGoalIds };
|
|
216
|
+
if (pendingOrder !== undefined)
|
|
217
|
+
proposal = { ...proposal, pendingOrder };
|
|
218
|
+
if (childGoals !== undefined)
|
|
219
|
+
proposal = { ...proposal, childGoals };
|
|
220
|
+
return proposal;
|
|
221
|
+
}
|
|
147
222
|
export function printSteerResult(result, json) {
|
|
148
223
|
if (json) {
|
|
149
224
|
printJson({ ok: result.accepted, accepted: result.accepted, rejectedReasons: result.rejectedReasons, deduped: result.deduped, audit: result.audit, plan: result.plan });
|
|
@@ -157,3 +232,13 @@ export function printSteerResult(result, json) {
|
|
|
157
232
|
process.stdout.write(`idempotency-key: ${result.audit.idempotencyKey}\n`);
|
|
158
233
|
printStatus(result.plan);
|
|
159
234
|
}
|
|
235
|
+
export function printSteerBatchResult(result, json) {
|
|
236
|
+
if (json) {
|
|
237
|
+
printJson({ ok: result.accepted, accepted: result.accepted, rejectedReasons: result.rejectedReasons, results: result.results, plan: result.plan });
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
process.stdout.write(`ulw-loop steer batch: ${result.accepted ? "accepted" : "rejected"} ${result.results.length} proposal(s)\n`);
|
|
241
|
+
if (result.rejectedReasons.length > 0)
|
|
242
|
+
process.stdout.write(`rejected: ${result.rejectedReasons.join("; ")}\n`);
|
|
243
|
+
printStatus(result.plan);
|
|
244
|
+
}
|
|
@@ -2,7 +2,6 @@ import { type UlwLoopScope } from "./paths.js";
|
|
|
2
2
|
export declare function createGoals(repoRoot: string, argv: readonly string[], json: boolean, scope?: UlwLoopScope): Promise<number>;
|
|
3
3
|
export declare function status(repoRoot: string, json: boolean, scope?: UlwLoopScope): Promise<number>;
|
|
4
4
|
export declare function completeGoals(repoRoot: string, argv: readonly string[], json: boolean, scope?: UlwLoopScope): Promise<number>;
|
|
5
|
-
export declare function checkpoint(repoRoot: string, argv: readonly string[], json: boolean, scope?: UlwLoopScope): Promise<number>;
|
|
6
5
|
export declare function steer(repoRoot: string, argv: readonly string[], json: boolean, scope?: UlwLoopScope): Promise<number>;
|
|
7
6
|
export declare function addGoal(repoRoot: string, argv: readonly string[], json: boolean, scope?: UlwLoopScope): Promise<number>;
|
|
8
7
|
export declare function criteria(repoRoot: string, argv: readonly string[], json: boolean, scope?: UlwLoopScope): Promise<number>;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
|
-
import { checkpointUlwLoop } from "./checkpoint.js";
|
|
3
2
|
import { hasFlag, parseCodexGoalJson, parseRecordEvidenceArgs, positionalText, readStdin, readValue, } from "./cli-arg-parser.js";
|
|
4
3
|
import { blockedDecisionHandoff, normalizeCodexGoalMode, printJson, printStatus } from "./cli-output.js";
|
|
5
|
-
import {
|
|
4
|
+
import { parseSteeringProposals, printSteerBatchResult, printSteerResult } from "./cli-steering.js";
|
|
6
5
|
import { buildCodexGoalInstruction } from "./codex-goal-instruction.js";
|
|
7
6
|
import { recordEvidence } from "./evidence.js";
|
|
8
7
|
import { isEssentialCriterion } from "./goal-status.js";
|
|
@@ -11,6 +10,7 @@ import { addUlwLoopGoal, createUlwLoopPlan, startNextUlwLoop, summarizeUlwLoopPl
|
|
|
11
10
|
import { readUlwLoopPlan } from "./plan-io.js";
|
|
12
11
|
import { recordFinalReviewBlockers } from "./review-blockers.js";
|
|
13
12
|
import { steerUlwLoop } from "./steering.js";
|
|
13
|
+
import { steerUlwLoopBatch } from "./steering-batch.js";
|
|
14
14
|
import { UlwLoopError } from "./types.js";
|
|
15
15
|
export async function createGoals(repoRoot, argv, json, scope) {
|
|
16
16
|
const briefFile = readValue(argv, "--brief-file");
|
|
@@ -21,10 +21,12 @@ export async function createGoals(repoRoot, argv, json, scope) {
|
|
|
21
21
|
if (!brief.trim()) {
|
|
22
22
|
throw new UlwLoopError("Missing brief text. Pass --brief, --brief-file, --from-stdin, or positional text.", "ULW_LOOP_BRIEF_REQUIRED");
|
|
23
23
|
}
|
|
24
|
+
const validationBatchesJson = readValue(argv, "--validation-batch-json");
|
|
24
25
|
const plan = await createUlwLoopPlan(repoRoot, {
|
|
25
26
|
brief,
|
|
26
27
|
codexGoalMode: normalizeCodexGoalMode(readValue(argv, "--codex-goal-mode")),
|
|
27
28
|
force: hasFlag(argv, "--force"),
|
|
29
|
+
...(validationBatchesJson === undefined ? {} : { validationBatchesJson }),
|
|
28
30
|
}, scope);
|
|
29
31
|
if (json)
|
|
30
32
|
printJson({ ok: true, plan, summary: summarizeUlwLoopPlan(plan) });
|
|
@@ -76,33 +78,16 @@ export async function completeGoals(repoRoot, argv, json, scope) {
|
|
|
76
78
|
process.stdout.write(`${instruction.text}\n`);
|
|
77
79
|
return 0;
|
|
78
80
|
}
|
|
79
|
-
export async function checkpoint(repoRoot, argv, json, scope) {
|
|
80
|
-
const goalId = required(argv, "--goal-id");
|
|
81
|
-
const statusValue = checkpointStatus(required(argv, "--status"));
|
|
82
|
-
const evidence = required(argv, "--evidence");
|
|
83
|
-
const codexGoalJson = await parseCodexGoalJson(statusValue === "complete" ? required(argv, "--codex-goal-json") : readValue(argv, "--codex-goal-json"));
|
|
84
|
-
if (statusValue === "complete" && codexGoalJson === undefined) {
|
|
85
|
-
throw new UlwLoopError("Missing --codex-goal-json.", "ULW_LOOP_CODEX_GOAL_JSON_REQUIRED");
|
|
86
|
-
}
|
|
87
|
-
const qualityGateJson = readValue(argv, "--quality-gate-json");
|
|
88
|
-
const args = {
|
|
89
|
-
goalId,
|
|
90
|
-
status: statusValue,
|
|
91
|
-
evidence,
|
|
92
|
-
...(codexGoalJson === undefined ? {} : { codexGoalJson }),
|
|
93
|
-
...(qualityGateJson === undefined ? {} : { qualityGateJson }),
|
|
94
|
-
};
|
|
95
|
-
const result = await checkpointUlwLoop(repoRoot, args, scope);
|
|
96
|
-
if (json)
|
|
97
|
-
printJson({ ok: true, ...result, summary: summarizeUlwLoopPlan(result.plan) });
|
|
98
|
-
else
|
|
99
|
-
process.stdout.write(`ulw-loop checkpoint: ${result.goal.id} -> ${result.goal.status}\n`);
|
|
100
|
-
return 0;
|
|
101
|
-
}
|
|
102
81
|
export async function steer(repoRoot, argv, json, scope) {
|
|
103
|
-
const
|
|
104
|
-
const
|
|
105
|
-
|
|
82
|
+
const proposals = await parseSteeringProposals(argv);
|
|
83
|
+
const single = proposals[0];
|
|
84
|
+
if (single !== undefined && proposals.length === 1 && readValue(argv, "--proposals-json") === undefined) {
|
|
85
|
+
const result = await steerUlwLoop(repoRoot, single, scope);
|
|
86
|
+
printSteerResult(result, json);
|
|
87
|
+
return result.accepted ? 0 : 1;
|
|
88
|
+
}
|
|
89
|
+
const result = await steerUlwLoopBatch(repoRoot, proposals, scope);
|
|
90
|
+
printSteerBatchResult(result, json);
|
|
106
91
|
return result.accepted ? 0 : 1;
|
|
107
92
|
}
|
|
108
93
|
export async function addGoal(repoRoot, argv, json, scope) {
|
|
@@ -171,11 +156,6 @@ function required(argv, flag) {
|
|
|
171
156
|
return value;
|
|
172
157
|
throw new UlwLoopError(`Missing ${flag}.`, "ULW_LOOP_ARGUMENT_MISSING", { details: { flag } });
|
|
173
158
|
}
|
|
174
|
-
function checkpointStatus(value) {
|
|
175
|
-
if (value === "complete" || value === "failed" || value === "blocked")
|
|
176
|
-
return value;
|
|
177
|
-
throw new UlwLoopError("Missing or invalid --status; expected complete, failed, or blocked.", "ULW_LOOP_STATUS_INVALID", { details: { status: value } });
|
|
178
|
-
}
|
|
179
159
|
function findGoal(plan, goalId) {
|
|
180
160
|
const goal = plan.goals.find((candidate) => candidate.id === goalId);
|
|
181
161
|
if (goal !== undefined)
|