oh-my-opencode 4.16.3 → 4.17.1
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/command/publish.md +31 -58
- package/.agents/skills/hyperplan/SKILL.md +3 -3
- package/.agents/skills/omomomo/SKILL.md +1 -1
- package/.agents/skills/pre-publish-review/SKILL.md +1 -1
- package/.agents/skills/publish/SKILL.md +32 -59
- package/.opencode/command/omomomo.md +1 -1
- package/.opencode/command/publish.md +31 -58
- package/.opencode/skills/hyperplan/SKILL.md +3 -3
- package/.opencode/skills/pre-publish-review/SKILL.md +4 -1
- package/README.ja.md +4 -4
- package/README.ko.md +4 -4
- package/README.md +2 -2
- package/README.ru.md +4 -4
- package/README.zh-cn.md +4 -4
- package/dist/cli/index.js +195 -76
- package/dist/cli-node/index.js +195 -76
- package/dist/features/team-mode/test-support/async-test-helpers.d.ts +2 -2
- package/dist/index.js +310 -299
- package/dist/plugin/chat-message/types.d.ts +4 -0
- package/dist/plugin/command-execute-before.d.ts +1 -0
- package/dist/plugin/stop-continuation.d.ts +17 -0
- package/dist/skills/remove-ai-slops/SKILL.md +2 -2
- package/dist/skills/review-work/SKILL.md +10 -2
- package/dist/skills/start-work/SKILL.md +6 -3
- package/dist/skills/ultimate-browsing/ATTRIBUTION.md +2 -2
- package/dist/skills/ultimate-browsing/engine/templates/package.json +1 -1
- package/dist/skills/ultimate-browsing/references/chrome-stealth.md +11 -11
- package/dist/skills/ulw-plan/SKILL.md +2 -1
- package/dist/skills/ulw-plan/references/full-workflow.md +1 -1
- package/dist/skills/ulw-plan/references/intent-unclear.md +4 -4
- package/dist/skills/ulw-plan/scripts/scaffold-plan.mjs +2 -2
- package/dist/skills/visual-qa/SKILL.md +9 -5
- package/dist/tui.js +79 -32
- package/package.json +15 -14
- package/packages/git-bash-mcp/package.json +27 -0
- package/packages/lsp-daemon/dist/cli.js +7 -13
- package/packages/lsp-daemon/dist/daemon-client.js +3 -5
- package/packages/lsp-daemon/dist/index.js +12 -18
- package/packages/lsp-daemon/dist/request-routing.js +6 -8
- package/packages/omo-codex/plugin/.codex-plugin/plugin.json +3 -1
- package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +1080 -1017
- 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/codegraph/package.json +1 -1
- 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/AGENTS.md +2 -2
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/dist/cli.js +6 -2
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/dist/codex-hook.js +6 -2
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/src/codex-hook.ts +6 -2
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/test/cli.test.ts +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/test/codex-hook.test.ts +67 -2
- package/packages/omo-codex/plugin/components/lsp/dist/cli.js +14 -14
- 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/lsp/test/package-smoke.test.ts +0 -13
- package/packages/omo-codex/plugin/components/rules/bundled-rules/hephaestus/gpt-5.5.md +2 -2
- package/packages/omo-codex/plugin/components/rules/bundled-rules/hephaestus/gpt-5.6.md +3 -3
- 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/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/start-work-continuation/test/codex-hook.test.ts +1 -79
- package/packages/omo-codex/plugin/components/teammode/AGENTS.md +2 -2
- 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/teammode/skills/teammode/SKILL.md +33 -16
- package/packages/omo-codex/plugin/components/teammode/skills/teammode/scripts/team.mjs +2 -1
- package/packages/omo-codex/plugin/components/teammode/test/v2-spawn-schema.test.ts +69 -0
- 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/explorer.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 +6 -6
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-qa-executor.toml +5 -5
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-worker-high.toml +26 -0
- package/packages/omo-codex/plugin/components/ultrawork/agents/{lazycodex-executor.toml → lazycodex-worker-low.toml} +6 -4
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-worker-medium.toml +26 -0
- package/packages/omo-codex/plugin/components/ultrawork/agents/librarian.toml +2 -2
- package/packages/omo-codex/plugin/components/ultrawork/agents/plan.toml +7 -7
- package/packages/omo-codex/plugin/components/ultrawork/directive.md +76 -37
- 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 +76 -37
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +2 -1
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-unclear.md +4 -4
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/scripts/scaffold-plan.mjs +2 -2
- package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook.test.ts +25 -0
- package/packages/omo-codex/plugin/components/ultrawork/test/package-smoke.test.ts +0 -68
- package/packages/omo-codex/plugin/components/ulw-loop/AGENTS.md +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/CHANGELOG.md +2 -0
- package/packages/omo-codex/plugin/components/ulw-loop/README.md +3 -1
- package/packages/omo-codex/plugin/components/ulw-loop/directive.md +76 -37
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.js +6 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-subcommands.d.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-subcommands.js +13 -2
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +405 -25
- package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.js +12 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/domain-types.d.ts +4 -2
- package/packages/omo-codex/plugin/components/ulw-loop/dist/paths.d.ts +7 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/paths.js +16 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-crud.js +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-verdicts.d.ts +6 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-verdicts.js +20 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate.d.ts +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate.js +12 -9
- package/packages/omo-codex/plugin/components/ulw-loop/dist/spawn-guard.d.ts +3 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/spawn-guard.js +148 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/stop-resume-hook.d.ts +2 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/stop-resume-hook.js +209 -0
- package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +25 -2
- 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 +14 -15
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +30 -28
- package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint.ts +6 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-subcommands.ts +14 -3
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli.ts +10 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-instruction.ts +12 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/domain-types.ts +4 -2
- package/packages/omo-codex/plugin/components/ulw-loop/src/paths.ts +27 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/plan-crud.ts +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-verdicts.ts +23 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate.ts +16 -9
- package/packages/omo-codex/plugin/components/ulw-loop/src/spawn-guard.ts +138 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/stop-resume-hook.ts +208 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-create-goals.test.ts +12 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-entrypoint.test.ts +4 -1
- package/packages/omo-codex/plugin/components/ulw-loop/test/codex-goal-instruction.test.ts +8 -35
- package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/quality-gate-builder.ts +24 -13
- package/packages/omo-codex/plugin/components/ulw-loop/test/package-smoke.test.ts +5 -2
- package/packages/omo-codex/plugin/components/ulw-loop/test/paths.test.ts +43 -8
- package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate.test.ts +55 -2
- package/packages/omo-codex/plugin/components/ulw-loop/test/spawn-guard.test.ts +228 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/stop-resume-hook.test.ts +193 -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 +18 -0
- 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 +1 -1
- 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 +1 -1
- 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 +1 -1
- 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 +17 -0
- 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 +2 -2
- 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/model-catalog.json +16 -7
- 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/migrate-codex-config/catalog.mjs +16 -7
- package/packages/omo-codex/plugin/scripts/sync-skills.mjs +8 -2
- package/packages/omo-codex/plugin/skills/init-deep/SKILL.md +2 -2
- package/packages/omo-codex/plugin/skills/refactor/SKILL.md +2 -2
- package/packages/omo-codex/plugin/skills/remove-ai-slops/SKILL.md +4 -4
- package/packages/omo-codex/plugin/skills/review-work/SKILL.md +18 -4
- package/packages/omo-codex/plugin/skills/start-work/SKILL.md +6 -3
- package/packages/omo-codex/plugin/skills/teammode/SKILL.md +33 -16
- package/packages/omo-codex/plugin/skills/teammode/scripts/team.mjs +2 -1
- package/packages/omo-codex/plugin/skills/ultimate-browsing/ATTRIBUTION.md +2 -2
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/templates/package.json +1 -1
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/chrome-stealth.md +11 -11
- package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +76 -37
- package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +14 -15
- package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +30 -28
- package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +2 -1
- package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +1 -1
- package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-unclear.md +4 -4
- package/packages/omo-codex/plugin/skills/ulw-plan/scripts/scaffold-plan.mjs +2 -2
- package/packages/omo-codex/plugin/skills/ulw-research/SKILL.md +2 -2
- package/packages/omo-codex/plugin/skills/visual-qa/SKILL.md +11 -7
- package/packages/omo-codex/plugin/test/aggregate-agents.test.mjs +76 -16
- package/packages/omo-codex/plugin/test/aggregate-hooks.test.mjs +23 -2
- package/packages/omo-codex/plugin/test/aggregate-manifest.test.mjs +1 -1
- package/packages/omo-codex/plugin/test/aggregate-model-catalog.test.mjs +4 -4
- package/packages/omo-codex/plugin/test/auto-update.test.mjs +4 -4
- package/packages/omo-codex/plugin/test/component-hook-contract-cases.mjs +2 -2
- package/packages/omo-codex/plugin/test/lcx-bug-skills.test.mjs +4 -101
- package/packages/omo-codex/plugin/test/migrate-codex-config.test.mjs +14 -14
- package/packages/omo-codex/plugin/test/sync-skills-orchestration.test.mjs +11 -0
- package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +1 -1
- package/packages/omo-codex/plugin/test/sync-skills.test.mjs +5 -3
- package/packages/omo-codex/plugin/test/teammode-transport.test.mjs +25 -0
- package/packages/omo-codex/plugin/test/ulw-plan-scope-contract.test.mjs +24 -0
- package/packages/omo-codex/plugin/test/ulw-plan-skill-contract.test.mjs +9 -40
- package/packages/omo-codex/plugin/test/ulw-research-skill-contract.test.mjs +4 -277
- package/packages/omo-codex/scripts/install-config-reasoning.test.mjs +5 -5
- package/packages/omo-codex/scripts/install-config.test.mjs +22 -3
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +98 -30
- package/packages/shared-skills/skills/remove-ai-slops/SKILL.md +2 -2
- package/packages/shared-skills/skills/review-work/SKILL.md +10 -2
- package/packages/shared-skills/skills/start-work/SKILL.md +6 -3
- package/packages/shared-skills/skills/ultimate-browsing/ATTRIBUTION.md +2 -2
- package/packages/shared-skills/skills/ultimate-browsing/engine/templates/package.json +1 -1
- package/packages/shared-skills/skills/ultimate-browsing/references/chrome-stealth.md +11 -11
- package/packages/shared-skills/skills/ulw-plan/SKILL.md +2 -1
- package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +1 -1
- package/packages/shared-skills/skills/ulw-plan/references/intent-unclear.md +4 -4
- package/packages/shared-skills/skills/ulw-plan/scripts/scaffold-plan.mjs +2 -2
- package/packages/shared-skills/skills/visual-qa/SKILL.md +9 -5
- package/dist/skills/visual-qa/scripts/skill-prompt-contract.test.ts +0 -296
- package/packages/omo-codex/plugin/components/ulw-loop/test/skill-contract.test.ts +0 -70
- package/packages/omo-codex/plugin/test/ulw-research-epistemic-contract.test.mjs +0 -98
- package/packages/shared-skills/skills/visual-qa/scripts/skill-prompt-contract.test.ts +0 -296
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"command": "node \"${PLUGIN_ROOT}/components/bootstrap/dist/cli.js\" hook session-start",
|
|
9
9
|
"commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\bootstrap.ps1\"",
|
|
10
10
|
"timeout": 30,
|
|
11
|
-
"statusMessage": "(OmO 4.
|
|
11
|
+
"statusMessage": "(OmO 4.17.1) Checking Bootstrap Provisioning"
|
|
12
12
|
}
|
|
13
13
|
]
|
|
14
14
|
}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"type": "command",
|
|
9
9
|
"command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook pre-tool-use",
|
|
10
10
|
"timeout": 5,
|
|
11
|
-
"statusMessage": "(OmO 4.
|
|
11
|
+
"statusMessage": "(OmO 4.17.1) Recommending Git Bash MCP"
|
|
12
12
|
}
|
|
13
13
|
]
|
|
14
14
|
}
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"type": "command",
|
|
21
21
|
"command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook post-compact",
|
|
22
22
|
"timeout": 5,
|
|
23
|
-
"statusMessage": "(OmO 4.
|
|
23
|
+
"statusMessage": "(OmO 4.17.1) Resetting Git Bash MCP Reminder"
|
|
24
24
|
}
|
|
25
25
|
]
|
|
26
26
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
## OVERVIEW
|
|
6
6
|
|
|
7
|
-
Codex `SubagentStop` hook component: the evidence gate for the `lazycodex-
|
|
7
|
+
Codex `SubagentStop` hook component: the evidence gate for the ultrawork implementation workers (`lazycodex-worker-low|medium|high`). When a worker stops without a valid evidence receipt, the hook emits `{"decision": "block", "reason": <directive>}` and Codex sends it back to work. Matcher is `^lazycodex-worker-(low|medium|high)$`; read-only roles like `lazycodex-qa-executor` and `lazycodex-gate-reviewer` (same `ultrawork/agents/` family) are NOT gated by this hook. (The historical `lazycodex-executor` agent was removed; this component keeps its name.)
|
|
8
8
|
|
|
9
9
|
Valid receipt: `last_assistant_message` contains `EVIDENCE_RECORDED: <path>` where `<path>` resolves to a non-empty regular file strictly inside `<cwd>/.omo/evidence/`. Symlinks and directories rejected; containment checked on realpaths (file inside evidence root inside cwd, traversal-safe). A valid receipt clears attempt state and exits silently.
|
|
10
10
|
|
|
@@ -30,7 +30,7 @@ Escape hatches: after 3 blocked attempts (`MAX_ATTEMPTS`) the stop passes and st
|
|
|
30
30
|
| Change the block message | `directive.md`; keep both `{{...}}` placeholders and the literal `EVIDENCE_RECORDED: <path>` final-line contract |
|
|
31
31
|
| Change receipt validation | `src/codex-hook.ts` (`hasValidEvidenceReceipt`, `extractEvidencePath`, `isNonEmptyFileInsideEvidenceRoot`) |
|
|
32
32
|
| Change the retry budget | `src/state.ts` `MAX_ATTEMPTS` |
|
|
33
|
-
|
|
|
33
|
+
| Worker-side contract | `../ultrawork/agents/lazycodex-worker-{low,medium,high}.toml` instruct the final `EVIDENCE_RECORDED: <path>` line this hook parses |
|
|
34
34
|
| Plugin-level wiring | `../../hooks/subagent-stop-verifying-lazycodex-executor-evidence.json` (adds `commandWindows` via `../bootstrap/scripts/node-dispatch.ps1`) |
|
|
35
35
|
| Wiring + contract tests | `../../test/aggregate-hooks.test.mjs`, `../../test/component-hook-contract-cases.mjs`, `../../test/hook-status-message.test.mjs`, `../../test/component-bundled-cli.test.mjs` |
|
|
36
36
|
|
|
@@ -66,11 +66,15 @@ function isRecord(value) {
|
|
|
66
66
|
var SUBAGENT_STOP_EVENT = "SubagentStop";
|
|
67
67
|
|
|
68
68
|
// components/lazycodex-executor-verify/src/codex-hook.ts
|
|
69
|
-
var
|
|
69
|
+
var RECEIPT_ENFORCED_AGENTS = new Set([
|
|
70
|
+
"lazycodex-worker-low",
|
|
71
|
+
"lazycodex-worker-medium",
|
|
72
|
+
"lazycodex-worker-high"
|
|
73
|
+
]);
|
|
70
74
|
function runSubagentStopHook(input, fs) {
|
|
71
75
|
if (!isSubagentStopInput(input))
|
|
72
76
|
return "";
|
|
73
|
-
if (input.agent_type
|
|
77
|
+
if (!RECEIPT_ENFORCED_AGENTS.has(input.agent_type))
|
|
74
78
|
return "";
|
|
75
79
|
if (transcriptHasContextPressureMarker(input.transcript_path, fs))
|
|
76
80
|
return "";
|
|
@@ -3,11 +3,15 @@ import { isAbsolute, relative, resolve } from "node:path";
|
|
|
3
3
|
import { renderDirective } from "./directive.js";
|
|
4
4
|
import { clearAttemptState, MAX_ATTEMPTS, readAttemptState, writeAttemptState } from "./state.js";
|
|
5
5
|
import { SUBAGENT_STOP_EVENT } from "./types.js";
|
|
6
|
-
const
|
|
6
|
+
const RECEIPT_ENFORCED_AGENTS = new Set([
|
|
7
|
+
"lazycodex-worker-low",
|
|
8
|
+
"lazycodex-worker-medium",
|
|
9
|
+
"lazycodex-worker-high",
|
|
10
|
+
]);
|
|
7
11
|
export function runSubagentStopHook(input, fs) {
|
|
8
12
|
if (!isSubagentStopInput(input))
|
|
9
13
|
return "";
|
|
10
|
-
if (input.agent_type
|
|
14
|
+
if (!RECEIPT_ENFORCED_AGENTS.has(input.agent_type))
|
|
11
15
|
return "";
|
|
12
16
|
if (transcriptHasContextPressureMarker(input.transcript_path, fs))
|
|
13
17
|
return "";
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
"hooks": {
|
|
3
3
|
"SubagentStop": [
|
|
4
4
|
{
|
|
5
|
-
"matcher": "^lazycodex-
|
|
5
|
+
"matcher": "^lazycodex-worker-(low|medium|high)$",
|
|
6
6
|
"hooks": [
|
|
7
7
|
{
|
|
8
8
|
"type": "command",
|
|
9
9
|
"command": "node \"${PLUGIN_ROOT}/components/lazycodex-executor-verify/dist/cli.js\" hook subagent-stop",
|
|
10
10
|
"timeout": 10,
|
|
11
|
-
"statusMessage": "(OmO 4.
|
|
11
|
+
"statusMessage": "(OmO 4.17.1) Verifying LazyCodex Executor Evidence"
|
|
12
12
|
}
|
|
13
13
|
]
|
|
14
14
|
}
|
|
@@ -6,11 +6,15 @@ import { clearAttemptState, MAX_ATTEMPTS, readAttemptState, writeAttemptState }
|
|
|
6
6
|
import type { HookFileSystem, StopHookOutput, SubagentStopInput } from "./types.js";
|
|
7
7
|
import { SUBAGENT_STOP_EVENT } from "./types.js";
|
|
8
8
|
|
|
9
|
-
const
|
|
9
|
+
const RECEIPT_ENFORCED_AGENTS = new Set([
|
|
10
|
+
"lazycodex-worker-low",
|
|
11
|
+
"lazycodex-worker-medium",
|
|
12
|
+
"lazycodex-worker-high",
|
|
13
|
+
]);
|
|
10
14
|
|
|
11
15
|
export function runSubagentStopHook(input: unknown, fs: HookFileSystem): string {
|
|
12
16
|
if (!isSubagentStopInput(input)) return "";
|
|
13
|
-
if (input.agent_type
|
|
17
|
+
if (!RECEIPT_ENFORCED_AGENTS.has(input.agent_type)) return "";
|
|
14
18
|
if (transcriptHasContextPressureMarker(input.transcript_path, fs)) return "";
|
|
15
19
|
if (hasValidEvidenceReceipt(input, fs)) {
|
|
16
20
|
clearAttemptState(input.cwd, input.session_id, input.agent_id, fs);
|
|
@@ -110,7 +110,7 @@ function createPayload(
|
|
|
110
110
|
): Record<string, string | boolean> {
|
|
111
111
|
return {
|
|
112
112
|
hook_event_name: "SubagentStop",
|
|
113
|
-
agent_type: "lazycodex-
|
|
113
|
+
agent_type: "lazycodex-worker-medium",
|
|
114
114
|
agent_id: "agent_1",
|
|
115
115
|
session_id: "sess.1",
|
|
116
116
|
cwd,
|
package/packages/omo-codex/plugin/components/lazycodex-executor-verify/test/codex-hook.test.ts
CHANGED
|
@@ -299,7 +299,7 @@ function existingReceiptTargetOutsideEvidenceRoot(): string {
|
|
|
299
299
|
function createInput(cwd: string, overrides: Partial<SubagentStopInput> = {}): SubagentStopInput {
|
|
300
300
|
return {
|
|
301
301
|
hook_event_name: "SubagentStop",
|
|
302
|
-
agent_type: "lazycodex-
|
|
302
|
+
agent_type: "lazycodex-worker-medium",
|
|
303
303
|
agent_id: "agent_1",
|
|
304
304
|
session_id: "sess.1",
|
|
305
305
|
cwd,
|
|
@@ -315,7 +315,7 @@ function createInput(cwd: string, overrides: Partial<SubagentStopInput> = {}): S
|
|
|
315
315
|
function createUnknownEventInput(cwd: string): Record<string, string | boolean> {
|
|
316
316
|
return {
|
|
317
317
|
hook_event_name: "Stop",
|
|
318
|
-
agent_type: "lazycodex-
|
|
318
|
+
agent_type: "lazycodex-worker-medium",
|
|
319
319
|
agent_id: "agent_1",
|
|
320
320
|
session_id: "sess.1",
|
|
321
321
|
cwd,
|
|
@@ -344,3 +344,68 @@ function isBlockOutput(value: unknown): value is BlockOutput {
|
|
|
344
344
|
typeof value.reason === "string"
|
|
345
345
|
);
|
|
346
346
|
}
|
|
347
|
+
|
|
348
|
+
describe("tier worker receipt enforcement", () => {
|
|
349
|
+
// given the matcher set now covers the difficulty-tier workers
|
|
350
|
+
const workerTypes = ["lazycodex-worker-low", "lazycodex-worker-medium", "lazycodex-worker-high"] as const;
|
|
351
|
+
|
|
352
|
+
for (const agentType of workerTypes) {
|
|
353
|
+
it(`#given no evidence receipt #when a ${agentType} child stops #then blocks`, () => {
|
|
354
|
+
// given
|
|
355
|
+
const cwd = createWorkspace();
|
|
356
|
+
|
|
357
|
+
// when
|
|
358
|
+
const output = runSubagentStopHook(createInput(cwd, { agent_type: agentType }), nodeFileSystem);
|
|
359
|
+
|
|
360
|
+
// then
|
|
361
|
+
expect(parseBlockOutput(output).decision).toBe("block");
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
it("#given no evidence receipt #when an explorer child stops #then no-ops", () => {
|
|
366
|
+
// given
|
|
367
|
+
const cwd = createWorkspace();
|
|
368
|
+
|
|
369
|
+
// when
|
|
370
|
+
const output = runSubagentStopHook(createInput(cwd, { agent_type: "explorer" }), nodeFileSystem);
|
|
371
|
+
|
|
372
|
+
// then
|
|
373
|
+
expect(output).toBe("");
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
it("#given both hook manifests #when their matchers are applied #then enforced agents match and read-only roles do not", () => {
|
|
377
|
+
// given
|
|
378
|
+
const componentManifest = JSON.parse(
|
|
379
|
+
readFileSync(new URL("../hooks/hooks.json", import.meta.url), "utf8"),
|
|
380
|
+
);
|
|
381
|
+
const rootManifest = JSON.parse(
|
|
382
|
+
readFileSync(
|
|
383
|
+
new URL("../../../hooks/subagent-stop-verifying-lazycodex-executor-evidence.json", import.meta.url),
|
|
384
|
+
"utf8",
|
|
385
|
+
),
|
|
386
|
+
);
|
|
387
|
+
for (const manifest of [componentManifest, rootManifest]) {
|
|
388
|
+
const matcher = new RegExp(manifest.hooks.SubagentStop[0].matcher);
|
|
389
|
+
|
|
390
|
+
// then
|
|
391
|
+
for (const name of workerTypes) expect(matcher.test(name)).toBe(true);
|
|
392
|
+
expect(matcher.test("lazycodex-executor")).toBe(false);
|
|
393
|
+
expect(matcher.test("explorer")).toBe(false);
|
|
394
|
+
expect(matcher.test("lazycodex-gate-reviewer")).toBe(false);
|
|
395
|
+
}
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
it("#given the tier worker TOMLs #when inspected #then each instructs the EVIDENCE_RECORDED receipt line", () => {
|
|
399
|
+
for (const tier of ["low", "medium", "high"]) {
|
|
400
|
+
// when
|
|
401
|
+
const toml = readFileSync(
|
|
402
|
+
new URL(`../../ultrawork/agents/lazycodex-worker-${tier}.toml`, import.meta.url),
|
|
403
|
+
"utf8",
|
|
404
|
+
);
|
|
405
|
+
|
|
406
|
+
// then
|
|
407
|
+
expect(toml).toContain("EVIDENCE_RECORDED: <path>");
|
|
408
|
+
}
|
|
409
|
+
});
|
|
410
|
+
});
|
|
411
|
+
|
|
@@ -1423,6 +1423,9 @@ async function disposeDefaultLspManager() {
|
|
|
1423
1423
|
await m.stopAll();
|
|
1424
1424
|
}
|
|
1425
1425
|
}
|
|
1426
|
+
function isPlainRecord(value) {
|
|
1427
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1428
|
+
}
|
|
1426
1429
|
function isProcessAlive(pid) {
|
|
1427
1430
|
if (!Number.isInteger(pid) || pid <= 0)
|
|
1428
1431
|
return false;
|
|
@@ -3313,10 +3316,10 @@ function sendToolCall(socketPath, name, args, timeoutMs) {
|
|
|
3313
3316
|
});
|
|
3314
3317
|
}
|
|
3315
3318
|
function toToolResult(message) {
|
|
3316
|
-
if (!
|
|
3319
|
+
if (!isPlainRecord(message) || message["id"] !== REQUEST_ID)
|
|
3317
3320
|
return null;
|
|
3318
3321
|
const result = message["result"];
|
|
3319
|
-
if (!
|
|
3322
|
+
if (!isPlainRecord(result) || !Array.isArray(result["content"]))
|
|
3320
3323
|
return null;
|
|
3321
3324
|
return {
|
|
3322
3325
|
content: result["content"],
|
|
@@ -3324,9 +3327,6 @@ function toToolResult(message) {
|
|
|
3324
3327
|
details: result["details"]
|
|
3325
3328
|
};
|
|
3326
3329
|
}
|
|
3327
|
-
function isRecord6(value) {
|
|
3328
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3329
|
-
}
|
|
3330
3330
|
function errorText(error) {
|
|
3331
3331
|
return error instanceof Error ? error.message : String(error);
|
|
3332
3332
|
}
|
|
@@ -3450,7 +3450,7 @@ function readSessionState(path) {
|
|
|
3450
3450
|
return parsed;
|
|
3451
3451
|
return emptyState();
|
|
3452
3452
|
} catch (error) {
|
|
3453
|
-
if (error instanceof SyntaxError ||
|
|
3453
|
+
if (error instanceof SyntaxError || isRecord6(error) && error["code"] === "ENOENT")
|
|
3454
3454
|
return emptyState();
|
|
3455
3455
|
throw error;
|
|
3456
3456
|
}
|
|
@@ -3471,12 +3471,12 @@ function safePathSegment(value) {
|
|
|
3471
3471
|
return value.replace(/[^A-Za-z0-9._-]/g, "_").slice(0, 120) || "unknown-session";
|
|
3472
3472
|
}
|
|
3473
3473
|
function isLspSessionState(value) {
|
|
3474
|
-
if (!
|
|
3474
|
+
if (!isRecord6(value) || !Array.isArray(value["unavailableExtensions"]))
|
|
3475
3475
|
return false;
|
|
3476
3476
|
const postCompactProbePending = value["postCompactProbePending"];
|
|
3477
3477
|
return value["unavailableExtensions"].every((item) => typeof item === "string") && (postCompactProbePending === undefined || typeof postCompactProbePending === "boolean");
|
|
3478
3478
|
}
|
|
3479
|
-
function
|
|
3479
|
+
function isRecord6(value) {
|
|
3480
3480
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3481
3481
|
}
|
|
3482
3482
|
|
|
@@ -3487,7 +3487,7 @@ function extractMutatedFilePaths(input) {
|
|
|
3487
3487
|
return [];
|
|
3488
3488
|
if (isFailedToolResponse(input.tool_response))
|
|
3489
3489
|
return [];
|
|
3490
|
-
const toolInput =
|
|
3490
|
+
const toolInput = isRecord7(input.tool_input) ? input.tool_input : {};
|
|
3491
3491
|
const paths = new Set;
|
|
3492
3492
|
addStringValue(paths, toolInput["path"]);
|
|
3493
3493
|
addStringValue(paths, toolInput["filePath"]);
|
|
@@ -3506,7 +3506,7 @@ function isMutationTool(value) {
|
|
|
3506
3506
|
return MUTATION_TOOL_NAMES.has(value.toLowerCase());
|
|
3507
3507
|
}
|
|
3508
3508
|
function isFailedToolResponse(value) {
|
|
3509
|
-
if (!
|
|
3509
|
+
if (!isRecord7(value))
|
|
3510
3510
|
return false;
|
|
3511
3511
|
return value["isError"] === true || value["is_error"] === true || value["error"] === true || value["status"] === "error";
|
|
3512
3512
|
}
|
|
@@ -3549,7 +3549,7 @@ function addPatchFiles(paths, value) {
|
|
|
3549
3549
|
if (!Array.isArray(value))
|
|
3550
3550
|
return;
|
|
3551
3551
|
for (const item of value) {
|
|
3552
|
-
if (!
|
|
3552
|
+
if (!isRecord7(item))
|
|
3553
3553
|
continue;
|
|
3554
3554
|
addStringValue(paths, item["path"]);
|
|
3555
3555
|
addStringValue(paths, item["filePath"]);
|
|
@@ -3558,7 +3558,7 @@ function addPatchFiles(paths, value) {
|
|
|
3558
3558
|
addStringValue(paths, item["move_path"]);
|
|
3559
3559
|
}
|
|
3560
3560
|
}
|
|
3561
|
-
function
|
|
3561
|
+
function isRecord7(value) {
|
|
3562
3562
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3563
3563
|
}
|
|
3564
3564
|
|
|
@@ -3742,7 +3742,7 @@ function limitHookText(text2, maxChars) {
|
|
|
3742
3742
|
function isCleanDiagnostics(diagnostics) {
|
|
3743
3743
|
return diagnostics.length === 0 || diagnostics === CLEAN_DIAGNOSTICS_TEXT || diagnostics.startsWith(UNSUPPORTED_EXTENSION_TEXT);
|
|
3744
3744
|
}
|
|
3745
|
-
function
|
|
3745
|
+
function isRecord8(value) {
|
|
3746
3746
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3747
3747
|
}
|
|
3748
3748
|
|
|
@@ -3759,7 +3759,7 @@ async function runHookCli(runHook, stdin) {
|
|
|
3759
3759
|
if (!raw.trim())
|
|
3760
3760
|
return;
|
|
3761
3761
|
const parsed = JSON.parse(raw);
|
|
3762
|
-
const input =
|
|
3762
|
+
const input = isRecord8(parsed) ? parsed : {};
|
|
3763
3763
|
const output = await runHook(input);
|
|
3764
3764
|
if (output)
|
|
3765
3765
|
process.stdout.write(output);
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"type": "command",
|
|
9
9
|
"command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook post-tool-use",
|
|
10
10
|
"timeout": 60,
|
|
11
|
-
"statusMessage": "(OmO 4.
|
|
11
|
+
"statusMessage": "(OmO 4.17.1) Checking LSP Diagnostics"
|
|
12
12
|
}
|
|
13
13
|
]
|
|
14
14
|
}
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"type": "command",
|
|
22
22
|
"command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook post-compact",
|
|
23
23
|
"timeout": 5,
|
|
24
|
-
"statusMessage": "(OmO 4.
|
|
24
|
+
"statusMessage": "(OmO 4.17.1) Resetting LSP Diagnostics Cache"
|
|
25
25
|
}
|
|
26
26
|
]
|
|
27
27
|
}
|
|
@@ -56,17 +56,4 @@ describe("plugin package metadata", () => {
|
|
|
56
56
|
expect(codexHookSource).not.toContain("../../../../../lsp-daemon");
|
|
57
57
|
expect(sourceFiles.filter((name) => name.startsWith("lazy-mcp") || name === "lazy-lsp-mcp.ts")).toEqual([]);
|
|
58
58
|
});
|
|
59
|
-
|
|
60
|
-
it("#given LSP skill guidance #when validating MCP tool instructions #then tool names are not framed as shell commands", () => {
|
|
61
|
-
// given
|
|
62
|
-
const skill = readTextFile("skills/lsp/SKILL.md");
|
|
63
|
-
|
|
64
|
-
// when
|
|
65
|
-
const mentionsToolInterface = skill.includes("through the tool interface");
|
|
66
|
-
const rejectsShellExecution = skill.includes("not shell commands");
|
|
67
|
-
|
|
68
|
-
// then
|
|
69
|
-
expect(mentionsToolInterface).toBe(true);
|
|
70
|
-
expect(rejectsShellExecution).toBe(true);
|
|
71
|
-
});
|
|
72
59
|
});
|
|
@@ -45,7 +45,7 @@ Read-only Codex subagent roles live in `CODEX_HOME/agents/`. Spawn: `multi_agent
|
|
|
45
45
|
|
|
46
46
|
- `explorer` - codebase search
|
|
47
47
|
- `librarian` - external docs, OSS code, API contracts
|
|
48
|
-
- `plan` - planning for
|
|
48
|
+
- `plan` - planning when design is still open after discovery; never for a known checklist or for work being delegated onward
|
|
49
49
|
- `lazycodex-gate-reviewer` - final verification of a finished change
|
|
50
50
|
|
|
51
51
|
Spawn subagents in parallel for independent investigations; do non-overlapping prep while they run, integrate on return. Never duplicate a running search or poll without a completion signal. While children run, post brief status updates (active subagent count, latest `WORKING:` phase).
|
|
@@ -74,7 +74,7 @@ Diagnostics catch type errors, not logic bugs; tests cover only what their autho
|
|
|
74
74
|
|
|
75
75
|
# Global Review and Debugging Gate
|
|
76
76
|
|
|
77
|
-
|
|
77
|
+
Run `review-work` plus a `debugging` runtime audit only before a PR handoff or when the user asks for a review; lane pass/fail semantics live in those skills. For everything else, the gate above is the whole gate: once you have personally observed the artifact working, report your evidence. Redact secrets, tokens, and PII from ledgers, PR bodies, and handoffs.
|
|
78
78
|
|
|
79
79
|
# Failure Recovery
|
|
80
80
|
|
|
@@ -19,7 +19,7 @@ Status requests are not stop signals: give the update, keep working. Honor every
|
|
|
19
19
|
|
|
20
20
|
# Discovery
|
|
21
21
|
|
|
22
|
-
Never speculate about code you have not read: verify with tools and re-read on every hand-off. Start broad once: independent
|
|
22
|
+
Never speculate about code you have not read: verify with tools and re-read on every hand-off. Start broad once - and WIDE: tool calls run as JavaScript through `exec`, so write programs, not single calls. Batch EVERY independent read, search, and doc lookup into ONE `exec` script via `Promise.all` over the `tools` object before the first edit; filter and reduce results in-script so only what you need returns to context. NEVER await independent calls one at a time - sequence only when one result feeds the next. Retrieve again only when the core question is open, a needed fact is missing, or a second-order question (callers, error paths, ownership) changes the design. Stop when you can act. Prefer the root fix over the symptom fix.
|
|
23
23
|
|
|
24
24
|
# Operating Loop
|
|
25
25
|
|
|
@@ -33,7 +33,7 @@ Read-only Codex subagent roles live in `CODEX_HOME/agents/`. Spawn: `multi_agent
|
|
|
33
33
|
|
|
34
34
|
- `explorer` - codebase search
|
|
35
35
|
- `librarian` - external docs, OSS code, API contracts
|
|
36
|
-
- `plan` - planning for
|
|
36
|
+
- `plan` - planning when design is still open after discovery; never for a known checklist or for work being delegated onward
|
|
37
37
|
- `lazycodex-gate-reviewer` - final verification of a finished change
|
|
38
38
|
|
|
39
39
|
Spawn in parallel for independent investigations; do non-overlapping prep while they run, integrate on return. Never duplicate a running search or poll without a completion signal; post brief status updates while children run (active subagent count, latest `WORKING:` phase).
|
|
@@ -50,7 +50,7 @@ Diagnostics catch type errors, not logic bugs; tests cover only what their autho
|
|
|
50
50
|
|
|
51
51
|
"This should work" from reading source does not pass. A defect found in usage is yours to fix this turn.
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
Run `review-work` plus a `debugging` runtime audit only before a PR handoff or when the user asks for a review; lane pass/fail semantics live in those skills. For everything else, the gate above is the whole gate: once you have personally observed the artifact working, report your evidence. Redact secrets, tokens, and PII from ledgers, PR bodies, and handoffs.
|
|
54
54
|
|
|
55
55
|
# Failure Recovery
|
|
56
56
|
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"type": "command",
|
|
8
8
|
"command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook session-start",
|
|
9
9
|
"timeout": 10,
|
|
10
|
-
"statusMessage": "(OmO 4.
|
|
10
|
+
"statusMessage": "(OmO 4.17.1) Loading Project Rules"
|
|
11
11
|
}
|
|
12
12
|
]
|
|
13
13
|
}
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"type": "command",
|
|
20
20
|
"command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook user-prompt-submit",
|
|
21
21
|
"timeout": 10,
|
|
22
|
-
"statusMessage": "(OmO 4.
|
|
22
|
+
"statusMessage": "(OmO 4.17.1) Loading Project Rules"
|
|
23
23
|
}
|
|
24
24
|
]
|
|
25
25
|
}
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"type": "command",
|
|
33
33
|
"command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook post-tool-use",
|
|
34
34
|
"timeout": 10,
|
|
35
|
-
"statusMessage": "(OmO 4.
|
|
35
|
+
"statusMessage": "(OmO 4.17.1) Matching Project Rules"
|
|
36
36
|
}
|
|
37
37
|
]
|
|
38
38
|
}
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"type": "command",
|
|
46
46
|
"command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook post-compact",
|
|
47
47
|
"timeout": 10,
|
|
48
|
-
"statusMessage": "(OmO 4.
|
|
48
|
+
"statusMessage": "(OmO 4.17.1) Resetting Project Rule Cache"
|
|
49
49
|
}
|
|
50
50
|
]
|
|
51
51
|
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"type": "command",
|
|
8
8
|
"command": "node \"${PLUGIN_ROOT}/components/start-work-continuation/dist/cli.js\" hook stop",
|
|
9
9
|
"timeout": 10,
|
|
10
|
-
"statusMessage": "(OmO 4.
|
|
10
|
+
"statusMessage": "(OmO 4.17.1) Checking Start-Work Continuation"
|
|
11
11
|
}
|
|
12
12
|
]
|
|
13
13
|
}
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"type": "command",
|
|
20
20
|
"command": "node \"${PLUGIN_ROOT}/components/start-work-continuation/dist/cli.js\" hook subagent-stop",
|
|
21
21
|
"timeout": 10,
|
|
22
|
-
"statusMessage": "(OmO 4.
|
|
22
|
+
"statusMessage": "(OmO 4.17.1) Checking Start-Work Continuation"
|
|
23
23
|
}
|
|
24
24
|
]
|
|
25
25
|
}
|
package/packages/omo-codex/plugin/components/start-work-continuation/test/codex-hook.test.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { mkdirSync, mkdtempSync,
|
|
1
|
+
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { tmpdir } from "node:os";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { afterEach, describe, expect, it } from "vitest";
|
|
@@ -96,84 +96,6 @@ describe("start-work Stop hook", () => {
|
|
|
96
96
|
expect(output).toBe("");
|
|
97
97
|
});
|
|
98
98
|
|
|
99
|
-
it("#given active codex work #when continuation directive is emitted #then subagent guidance is reliable", () => {
|
|
100
|
-
// given
|
|
101
|
-
const workspace = createWorkspace({
|
|
102
|
-
boulderJson: createBoulderJson({ sessionIds: ["codex:sess_abc"], status: "active" }),
|
|
103
|
-
planMarkdown: ["# Plan", "", "## TODOs", "- [ ] First"].join("\n"),
|
|
104
|
-
});
|
|
105
|
-
const fs = createMemoryFs();
|
|
106
|
-
|
|
107
|
-
// when
|
|
108
|
-
const output = runStopHook(createStopInput(workspace), fs);
|
|
109
|
-
|
|
110
|
-
// then
|
|
111
|
-
const parsed = parseBlockOutput(output);
|
|
112
|
-
expect(parsed.reason).toMatch(/TASK:/);
|
|
113
|
-
expect(parsed.reason).toMatch(/fork_context:\s*false/);
|
|
114
|
-
expect(parsed.reason).toMatch(/wait_agent.*mailbox signals/);
|
|
115
|
-
expect(parsed.reason).toMatch(/TASK STILL ACTIVE/);
|
|
116
|
-
expect(parsed.reason).toMatch(/respawn.*smaller/);
|
|
117
|
-
expect(parsed.reason).toMatch(/WORKING:/);
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
it("#given active codex work #when continuation directive is emitted #then QA weight is tier-scoped without echo bloat", () => {
|
|
121
|
-
// given
|
|
122
|
-
const workspace = createWorkspace({
|
|
123
|
-
boulderJson: createBoulderJson({ sessionIds: ["codex:sess_abc"], status: "active" }),
|
|
124
|
-
planMarkdown: ["# Plan", "", "## TODOs", "- [ ] First"].join("\n"),
|
|
125
|
-
});
|
|
126
|
-
const fs = createMemoryFs();
|
|
127
|
-
|
|
128
|
-
// when
|
|
129
|
-
const output = runStopHook(createStopInput(workspace), fs);
|
|
130
|
-
|
|
131
|
-
// then
|
|
132
|
-
const parsed = parseBlockOutput(output);
|
|
133
|
-
expect(parsed.reason).toMatch(/LIGHT/);
|
|
134
|
-
expect(parsed.reason).toMatch(/HEAVY/);
|
|
135
|
-
expect(parsed.reason).toMatch(/When unsure[^.]{0,30}HEAVY/);
|
|
136
|
-
expect(parsed.reason).toMatch(/mirrors its implementation/);
|
|
137
|
-
expect((parsed.reason.match(/malformed input, prompt injection/g) ?? []).length).toBe(1);
|
|
138
|
-
expect(parsed.reason.split(/\s+/).filter(Boolean).length).toBeLessThanOrEqual(1135);
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
it("#given active codex work #when continuation directive is emitted #then PR lifecycle stays worktree-bound", () => {
|
|
142
|
-
// given
|
|
143
|
-
const workspace = createWorkspace({
|
|
144
|
-
boulderJson: createBoulderJson({
|
|
145
|
-
sessionIds: ["codex:sess_abc"],
|
|
146
|
-
status: "active",
|
|
147
|
-
worktreePath: "/tmp/worktree",
|
|
148
|
-
}),
|
|
149
|
-
planMarkdown: ["# Plan", "", "## TODOs", "- [ ] First"].join("\n"),
|
|
150
|
-
});
|
|
151
|
-
const fs = createMemoryFs();
|
|
152
|
-
|
|
153
|
-
// when
|
|
154
|
-
const output = runStopHook(createStopInput(workspace), fs);
|
|
155
|
-
|
|
156
|
-
// then
|
|
157
|
-
const parsed = parseBlockOutput(output);
|
|
158
|
-
expect(parsed.reason).toContain("PR or branch implementation/review/merge work requires a task-owned git worktree");
|
|
159
|
-
expect(parsed.reason).toContain("Treat the main worktree as read-only context");
|
|
160
|
-
expect(parsed.reason).toContain("create/update the PR, wait for CI/review/Cubic gates, merge by default");
|
|
161
|
-
expect(parsed.reason).toContain("Do not create a PR, PR handoff, branch handoff, merge");
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
it("#given stop hook source #when inspected #then it remains Boulder-only without planning bootstrap logic", () => {
|
|
165
|
-
// given
|
|
166
|
-
const hook = readFileSync(new URL("../src/codex-hook.ts", import.meta.url), "utf8");
|
|
167
|
-
|
|
168
|
-
// then
|
|
169
|
-
expect(hook).toMatch(/readContinuationState/);
|
|
170
|
-
expect(hook).toMatch(/START_WORK_CONTINUATION_DIRECTIVE/);
|
|
171
|
-
expect(hook).toMatch(/decision:\s*"block"/);
|
|
172
|
-
expect(hook).not.toMatch(
|
|
173
|
-
/\bulw-plan\b|\bspawn_agent\b|\brequest_user_input\b|bootstrap|selectable plan|Phase 1|Create or update Boulder state/i,
|
|
174
|
-
);
|
|
175
|
-
});
|
|
176
|
-
|
|
177
99
|
it("#given active work belongs to another harness #when hook runs #then returns empty output", () => {
|
|
178
100
|
// given
|
|
179
101
|
const workspace = createWorkspace({
|