oh-my-opencode 4.19.4 → 5.0.0-beta.10
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/publish.md +44 -16
- package/.agents/skills/publish/SKILL.md +44 -16
- package/.agents/skills/work-with-pr/SKILL.md +37 -23
- package/.opencode/command/publish.md +44 -16
- package/.opencode/skills/work-with-pr/SKILL.md +37 -23
- package/README.ja.md +1 -1
- package/README.ko.md +1 -1
- package/README.md +18 -6
- package/README.ru.md +1 -1
- package/README.zh-cn.md +1 -1
- package/bin/oh-my-opencode.js +14 -1
- package/bin/oh-my-opencode.test.ts +21 -0
- package/dist/agents/atlas/agent.d.ts +0 -1
- package/dist/agents/sisyphus/grok-4.d.ts +20 -0
- package/dist/agents/sisyphus/index.d.ts +2 -0
- package/dist/agents/sisyphus-agent-config.d.ts +6 -0
- package/dist/agents/sisyphus-agent-factory.d.ts +1 -1
- package/dist/agents/sisyphus-runtime-prompt-reconciler.d.ts +15 -4
- package/dist/agents/types.d.ts +2 -2
- package/dist/cli/index.js +1888 -807
- package/dist/cli/run/on-complete-hook.d.ts +2 -0
- package/dist/cli-node/index.js +1888 -807
- package/dist/config/schema/agent-overrides.d.ts +528 -0
- package/dist/config/schema/oh-my-opencode-config.d.ts +495 -0
- package/dist/features/monitor/batcher.d.ts +3 -1
- package/dist/features/monitor/manager-internals.d.ts +1 -0
- package/dist/features/monitor/output-injector-types.d.ts +2 -0
- package/dist/features/monitor/output-injector.d.ts +6 -0
- package/dist/hooks/atlas/final-wave-approval-gate.test-support.d.ts +50 -0
- package/dist/hooks/atlas/system-reminder-templates.d.ts +0 -1
- package/dist/hooks/todo-continuation-enforcer/types.d.ts +1 -0
- package/dist/hooks/todo-continuation-enforcer/unrecoverable-request-error.d.ts +9 -0
- package/dist/hooks/tool-pair-validator/hook.test-support.d.ts +29 -0
- package/dist/hooks/tool-pair-validator/tool-part-ids.d.ts +14 -5
- package/dist/hooks/tool-pair-validator/tool-result-repair.d.ts +4 -3
- package/dist/hooks/tool-pair-validator/types.d.ts +5 -22
- package/dist/index.js +3139 -2232
- package/dist/mcp/lsp.d.ts +1 -0
- package/dist/oh-my-opencode.schema.json +1466 -131
- package/dist/shared/normalize-sdk-response.d.ts +1 -0
- package/dist/shared/shell-env.d.ts +1 -1
- package/dist/shared/tmux/constants.d.ts +1 -1
- package/dist/skills/ast-grep/SOURCE +1 -1
- package/dist/skills/ast-grep/install.ps1 +2 -2
- package/dist/skills/ast-grep/install.sh +1 -1
- package/dist/skills/ast-grep/references/install.md +2 -2
- package/dist/skills/ast-grep/tests/smoke.sh +1 -1
- package/dist/skills/coding-agent-sessions/SKILL.md +3 -2
- package/dist/skills/coding-agent-sessions/references/all-platforms.md +1 -1
- package/dist/skills/coding-agent-sessions/references/senpi.md +4 -4
- package/dist/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +1 -1
- package/dist/skills/frontend/SKILL.md +10 -7
- package/dist/skills/frontend/references/design/_INDEX.md +1 -0
- package/dist/skills/frontend/references/design/stylegallery.md +80 -0
- package/dist/skills/start-work/SKILL.md +54 -9
- package/dist/skills/ultimate-browsing/ATTRIBUTION.md +37 -10
- package/dist/skills/ultimate-browsing/SKILL.md +2 -2
- package/dist/skills/ultimate-browsing/engine/AGENTS.md +179 -0
- package/dist/skills/ultimate-browsing/engine/__main__.py +8 -1
- package/dist/skills/ultimate-browsing/engine/bias_check.py +11 -0
- package/dist/skills/ultimate-browsing/engine/fetch_chain.py +90 -52
- package/dist/skills/ultimate-browsing/engine/result_schema.py +10 -1
- package/dist/skills/ultimate-browsing/engine/surrogate.py +214 -0
- package/dist/skills/ultimate-browsing/engine/surrogates.yaml +60 -0
- package/dist/skills/ultimate-browsing/engine/templates/package.json +1 -1
- package/dist/skills/ultimate-browsing/engine/tests/fixtures/amp_redirect_stub.html +7 -0
- package/dist/skills/ultimate-browsing/engine/tests/fixtures/search_interstitial.html +19 -0
- package/dist/skills/ultimate-browsing/engine/tests/fixtures/wayback_available.json +1 -0
- package/dist/skills/ultimate-browsing/engine/tests/fixtures/wayback_snapshot.html +1128 -0
- package/dist/skills/ultimate-browsing/engine/tests/test_surrogate.py +252 -0
- package/dist/skills/ultimate-browsing/engine/tests/test_surrogate_validators.py +78 -0
- package/dist/skills/ultimate-browsing/engine/validators.py +46 -0
- package/dist/skills/ultimate-browsing/engine/waf_detector.py +1 -1
- package/dist/skills/ultimate-browsing/engine/waf_profiles.yaml +10 -5
- package/dist/skills/ultimate-browsing/references/agent-reach/social.md +1 -1
- package/dist/skills/ultimate-browsing/references/chrome-stealth.md +13 -11
- package/dist/skills/ultimate-browsing/references/insane-search/README.md +4 -4
- package/dist/skills/ultimate-browsing/references/insane-search/cache-archive.md +51 -50
- package/dist/skills/ultimate-browsing/references/insane-search/fallback.md +1 -1
- package/dist/skills/ultimate-browsing/references/insane-search/jina.md +8 -2
- package/dist/skills/ultimate-browsing/references/insane-search/naver.md +1 -1
- package/dist/skills/ultimate-browsing/references/insane-search/twitter.md +3 -3
- package/dist/skills/ulw-plan/SKILL.md +3 -3
- package/dist/skills/ulw-plan/references/full-workflow.md +30 -6
- package/dist/skills/ulw-plan/references/intent-clear.md +2 -1
- package/dist/skills/ulw-plan/references/intent-unclear.md +3 -3
- package/dist/skills/ulw-plan/scripts/scaffold-plan.mjs +1 -1
- package/dist/skills/ulw-research/SKILL.md +15 -10
- package/dist/tui.js +477 -36
- package/docs/reference/web-terminal-visual-qa.md +1 -1
- package/package.json +34 -24
- package/packages/lsp-core/src/lsp/client-diagnostics-concurrency.integration.test.ts +44 -0
- package/packages/lsp-core/src/lsp/client-diagnostics-freshness.integration.test.ts +0 -28
- package/packages/lsp-core/src/lsp/client-wrapper.test.ts +60 -7
- package/packages/lsp-core/src/lsp/client-wrapper.ts +69 -16
- package/packages/lsp-core/src/lsp/connection.ts +1 -1
- package/packages/lsp-core/src/lsp/workspace-edit-adversarial.test.ts +20 -1
- package/packages/lsp-core/src/tools/diagnostics.ts +3 -3
- package/packages/lsp-core/src/tools/navigation.ts +4 -2
- package/packages/lsp-core/src/tools/rename.ts +4 -2
- package/packages/lsp-core/src/tools/symbols.ts +1 -1
- package/packages/lsp-daemon/dist/cli.js +108 -40
- package/packages/lsp-daemon/dist/client.js +123 -55
- package/packages/lsp-daemon/dist/ensure-daemon.d.ts +1 -0
- package/packages/lsp-daemon/dist/ensure-daemon.js +18 -5
- package/packages/lsp-daemon/dist/index.js +111 -43
- package/packages/lsp-tools-mcp/dist/cli.js +77 -23
- package/packages/lsp-tools-mcp/dist/lsp/manager.js +1 -1
- package/packages/lsp-tools-mcp/dist/mcp.js +77 -23
- package/packages/lsp-tools-mcp/dist/tools.js +77 -23
- package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +268 -92
- 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 +7 -7
- package/packages/omo-codex/plugin/components/bootstrap/src/worker.ts +3 -0
- package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +220 -10
- package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +220 -10
- 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/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/test/codex-hook.test.ts +3 -17
- package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +3 -3
- package/packages/omo-codex/plugin/components/lsp/dist/cli.js +135 -67
- 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/hooks/hooks.json +4 -4
- package/packages/omo-codex/plugin/components/rules/package.json +1 -1
- package/packages/omo-codex/plugin/components/rules/test/bundled-rules-priority.test.ts +11 -16
- package/packages/omo-codex/plugin/components/rules/test/bundled-rules.test.ts +16 -23
- package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-budget.test.ts +9 -7
- package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-context.test.ts +0 -6
- package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-dedup.test.ts +6 -4
- package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-directive.test.ts +12 -9
- package/packages/omo-codex/plugin/components/rules/test/codex-hook.test.ts +28 -37
- package/packages/omo-codex/plugin/components/rules/test/formatter.test.ts +37 -69
- package/packages/omo-codex/plugin/components/rules/test/hook-output.test.ts +2 -3
- package/packages/omo-codex/plugin/components/rules/test/windows-git-bash-bundled-rule.test.ts +1 -15
- package/packages/omo-codex/plugin/components/start-work-continuation/AGENTS.md +4 -2
- package/packages/omo-codex/plugin/components/start-work-continuation/README.md +5 -1
- package/packages/omo-codex/plugin/components/start-work-continuation/directive.md +2 -1
- package/packages/omo-codex/plugin/components/start-work-continuation/dist/cli.js +18 -0
- 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/src/codex-hook.ts +21 -0
- package/packages/omo-codex/plugin/components/start-work-continuation/test/cli.test.ts +0 -3
- package/packages/omo-codex/plugin/components/start-work-continuation/test/codex-hook.test.ts +107 -16
- 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/test/thread-title-hook.test.ts +3 -9
- package/packages/omo-codex/plugin/components/telemetry/dist/cli.js +24 -12
- package/packages/omo-codex/plugin/components/telemetry/dist/posthog.js +24 -12
- 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/CHANGELOG.md +2 -0
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-code-reviewer.toml +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-gate-reviewer.toml +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-qa-executor.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-low.toml +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-worker-medium.toml +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/agents/plan.toml +2 -2
- package/packages/omo-codex/plugin/components/ultrawork/directive.md +9 -2
- 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 +9 -2
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +3 -3
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +30 -6
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-clear.md +2 -1
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-unclear.md +3 -3
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/scripts/scaffold-plan.mjs +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook.test.ts +0 -136
- package/packages/omo-codex/plugin/components/ultrawork/test/skill-pointer.test.ts +0 -2
- 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 +11 -11
- package/packages/omo-codex/plugin/components/ulw-loop/directive.md +9 -2
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-reconciliation.js +1 -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 +9 -9
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-steering.js +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +66 -66
- package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.js +4 -4
- package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-hook.js +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-crud.js +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.js +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/steering.js +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/stop-resume-hook.js +2 -2
- 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 +5 -4
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/define-goal.md +108 -0
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +23 -25
- package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-reconciliation.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-output.ts +9 -9
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-steering.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-instruction.ts +4 -4
- package/packages/omo-codex/plugin/components/ulw-loop/src/codex-hook.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/plan-crud.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/plan-io.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/steering.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/stop-resume-hook.ts +2 -2
- package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-continuation.test.ts +0 -1
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-commands.test.ts +2 -2
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-entrypoint.test.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-helpers.test.ts +2 -2
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-steering-kind-guidance.test.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/test/codex-goal-instruction.test.ts +2 -2
- package/packages/omo-codex/plugin/components/ulw-loop/test/codex-hook.test.ts +2 -5
- package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/quality-gate-builder.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/test/package-smoke.test.ts +7 -40
- package/packages/omo-codex/plugin/components/ulw-loop/test/plan-io.test.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-roles.test.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/test/steering.test.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/test/stop-resume-hook.test.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/test/ultrawork-directive.test.ts +4 -5
- 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 +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 +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 +20 -20
- package/packages/omo-codex/plugin/package.json +1 -1
- package/packages/omo-codex/plugin/scripts/sync-skills.mjs +4 -4
- package/packages/omo-codex/plugin/skills/ast-grep/SOURCE +1 -1
- package/packages/omo-codex/plugin/skills/ast-grep/install.ps1 +2 -2
- package/packages/omo-codex/plugin/skills/ast-grep/install.sh +1 -1
- package/packages/omo-codex/plugin/skills/ast-grep/references/install.md +2 -2
- package/packages/omo-codex/plugin/skills/ast-grep/tests/smoke.sh +1 -1
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/SKILL.md +3 -2
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/all-platforms.md +1 -1
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/senpi.md +4 -4
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +1 -1
- package/packages/omo-codex/plugin/skills/frontend/SKILL.md +10 -7
- package/packages/omo-codex/plugin/skills/frontend/references/design/_INDEX.md +1 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/stylegallery.md +80 -0
- package/packages/omo-codex/plugin/skills/start-work/SKILL.md +54 -9
- package/packages/omo-codex/plugin/skills/ultimate-browsing/ATTRIBUTION.md +37 -10
- package/packages/omo-codex/plugin/skills/ultimate-browsing/SKILL.md +2 -2
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/AGENTS.md +179 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/__main__.py +8 -1
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/bias_check.py +11 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/fetch_chain.py +90 -52
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/result_schema.py +10 -1
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/surrogate.py +214 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/surrogates.yaml +60 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/templates/package.json +1 -1
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/fixtures/amp_redirect_stub.html +7 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/fixtures/search_interstitial.html +19 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/fixtures/wayback_available.json +1 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/fixtures/wayback_snapshot.html +1128 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/test_surrogate.py +252 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/test_surrogate_validators.py +78 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/validators.py +46 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/waf_detector.py +1 -1
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/waf_profiles.yaml +10 -5
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/agent-reach/social.md +1 -1
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/chrome-stealth.md +13 -11
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/README.md +4 -4
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/cache-archive.md +51 -50
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/fallback.md +1 -1
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/jina.md +8 -2
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/naver.md +1 -1
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/twitter.md +3 -3
- package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +9 -2
- package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +5 -4
- package/packages/omo-codex/plugin/skills/ulw-loop/references/define-goal.md +108 -0
- package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +23 -25
- package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +3 -3
- package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +30 -6
- package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-clear.md +2 -1
- package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-unclear.md +3 -3
- package/packages/omo-codex/plugin/skills/ulw-plan/scripts/scaffold-plan.mjs +1 -1
- package/packages/omo-codex/plugin/skills/ulw-research/SKILL.md +15 -10
- package/packages/omo-codex/plugin/test/aggregate-agents.test.mjs +19 -173
- package/packages/omo-codex/plugin/test/aggregate-hooks.test.mjs +4 -24
- package/packages/omo-codex/plugin/test/aggregate-plugin-fixture.mjs +175 -13
- package/packages/omo-codex/plugin/test/aggregate.test.mjs +78 -2
- package/packages/omo-codex/plugin/test/auto-update-release-notes.test.mjs +19 -33
- package/packages/omo-codex/plugin/test/bootstrap-binlinks.test.mjs +12 -12
- package/packages/omo-codex/plugin/test/bootstrap-orchestration.test.mjs +36 -4
- package/packages/omo-codex/plugin/test/lcx-contribute-bug-fix-template.test.mjs +21 -27
- package/packages/omo-codex/plugin/test/scaffold-plan.test.mjs +0 -36
- package/packages/omo-codex/plugin/test/sync-skills-codex-compatibility.test.mjs +101 -0
- package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +4 -4
- package/packages/omo-codex/plugin/test/sync-skills.test.mjs +1 -119
- package/packages/omo-codex/plugin/test/teammode-archive-ambiguity.test.mjs +0 -40
- package/packages/omo-codex/plugin/test/teammode-communication.test.mjs +6 -62
- package/packages/omo-codex/plugin/test/teammode-thread-links.test.mjs +3 -36
- package/packages/omo-codex/plugin/test/teammode-transport.test.mjs +0 -44
- package/packages/omo-codex/plugin/test/teammode-worktree.test.mjs +2 -6
- package/packages/omo-codex/plugin/test/ultrawork-skill-pointer.test.mjs +0 -3
- package/packages/omo-codex/plugin/test/ulw-plan-review-state-contract.test.mjs +0 -3
- package/packages/omo-codex/scripts/install-bin-links.test.mjs +56 -2
- package/packages/omo-codex/scripts/install-delegated-command.test.mjs +6 -6
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +170 -78
- package/packages/omo-codex/scripts/install-lazycodex-version-stamp.test.mjs +7 -2
- package/packages/omo-codex/scripts/install-local-entrypoint.test.mjs +4 -4
- package/packages/omo-codex/scripts/install-local.test.mjs +5 -2
- package/packages/shared-skills/index.mjs +19 -1
- package/packages/shared-skills/skills/ast-grep/SOURCE +1 -1
- package/packages/shared-skills/skills/ast-grep/install.ps1 +2 -2
- package/packages/shared-skills/skills/ast-grep/install.sh +1 -1
- package/packages/shared-skills/skills/ast-grep/references/install.md +2 -2
- package/packages/shared-skills/skills/ast-grep/tests/smoke.sh +1 -1
- package/packages/shared-skills/skills/coding-agent-sessions/SKILL.md +3 -2
- package/packages/shared-skills/skills/coding-agent-sessions/references/all-platforms.md +1 -1
- package/packages/shared-skills/skills/coding-agent-sessions/references/senpi.md +4 -4
- package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +1 -1
- package/packages/shared-skills/skills/frontend/SKILL.md +10 -7
- package/packages/shared-skills/skills/frontend/references/design/_INDEX.md +1 -0
- package/packages/shared-skills/skills/frontend/references/design/stylegallery.md +80 -0
- package/packages/shared-skills/skills/start-work/SKILL.md +54 -9
- package/packages/shared-skills/skills/ultimate-browsing/ATTRIBUTION.md +37 -10
- package/packages/shared-skills/skills/ultimate-browsing/SKILL.md +2 -2
- package/packages/shared-skills/skills/ultimate-browsing/engine/AGENTS.md +179 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/__main__.py +8 -1
- package/packages/shared-skills/skills/ultimate-browsing/engine/bias_check.py +11 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/fetch_chain.py +90 -52
- package/packages/shared-skills/skills/ultimate-browsing/engine/result_schema.py +10 -1
- package/packages/shared-skills/skills/ultimate-browsing/engine/surrogate.py +214 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/surrogates.yaml +60 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/templates/package.json +1 -1
- package/packages/shared-skills/skills/ultimate-browsing/engine/tests/fixtures/amp_redirect_stub.html +7 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/tests/fixtures/search_interstitial.html +19 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/tests/fixtures/wayback_available.json +1 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/tests/fixtures/wayback_snapshot.html +1128 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/tests/test_surrogate.py +252 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/tests/test_surrogate_validators.py +78 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/validators.py +46 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/waf_detector.py +1 -1
- package/packages/shared-skills/skills/ultimate-browsing/engine/waf_profiles.yaml +10 -5
- package/packages/shared-skills/skills/ultimate-browsing/references/agent-reach/social.md +1 -1
- package/packages/shared-skills/skills/ultimate-browsing/references/chrome-stealth.md +13 -11
- package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/README.md +4 -4
- package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/cache-archive.md +51 -50
- package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/fallback.md +1 -1
- package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/jina.md +8 -2
- package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/naver.md +1 -1
- package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/twitter.md +3 -3
- package/packages/shared-skills/skills/ulw-plan/SKILL.md +3 -3
- package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +30 -6
- package/packages/shared-skills/skills/ulw-plan/references/intent-clear.md +2 -1
- package/packages/shared-skills/skills/ulw-plan/references/intent-unclear.md +3 -3
- package/packages/shared-skills/skills/ulw-plan/scripts/scaffold-plan.mjs +1 -1
- package/packages/shared-skills/skills/ulw-research/SKILL.md +15 -10
- package/postinstall.mjs +6 -0
- package/dist/tools/call-omo-agent/background-agent-executor.d.ts +0 -5
- package/packages/omo-codex/plugin/test/aggregate-skills.test.mjs +0 -92
- package/packages/omo-codex/plugin/test/sync-skills-orchestration.test.mjs +0 -314
- package/packages/omo-codex/plugin/test/ulw-plan-scope-contract.test.mjs +0 -24
|
@@ -40,8 +40,12 @@ const DISABLED_BUNDLED_ENV = {
|
|
|
40
40
|
CODEX_RULES_DISABLE_BUNDLED: "1",
|
|
41
41
|
};
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
// Runtime sentinel: the rules hook emits and re-greps this marker when
|
|
44
|
+
// deduplicating injected rules against the transcript (transcript-rule-filter.ts).
|
|
45
|
+
const INSTRUCTIONS_FROM = "Instructions from: ";
|
|
46
|
+
|
|
47
|
+
const BUNDLED_BODY = "BUNDLED_PERSONA_SENTINEL";
|
|
48
|
+
const SHARED_BODY = "SHARED_RULE_SENTINEL";
|
|
45
49
|
|
|
46
50
|
const tempDirectories: string[] = [];
|
|
47
51
|
let originalPluginRoot: string | undefined;
|
|
@@ -130,10 +134,6 @@ function userPromptSubmitInput(root: string): Parameters<typeof runUserPromptSub
|
|
|
130
134
|
};
|
|
131
135
|
}
|
|
132
136
|
|
|
133
|
-
function occurrenceCount(value: string, search: string): number {
|
|
134
|
-
return value.split(search).length - 1;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
137
|
describe("plugin bundled rules", () => {
|
|
138
138
|
it("#given PLUGIN_ROOT with bundled markdown #when finding candidates #then plugin-bundled source is cached", () => {
|
|
139
139
|
// given
|
|
@@ -162,11 +162,8 @@ describe("plugin bundled rules", () => {
|
|
|
162
162
|
|
|
163
163
|
// then
|
|
164
164
|
expect(output).toContain('"hookEventName":"SessionStart"');
|
|
165
|
-
expect(output).toContain(
|
|
165
|
+
expect(output).toContain(`${INSTRUCTIONS_FROM}${bundledRulePath}`);
|
|
166
166
|
expect(output).toContain(BUNDLED_BODY);
|
|
167
|
-
expect(output).toContain("## Project Instructions");
|
|
168
|
-
expect(output).not.toContain("must read project rules:");
|
|
169
|
-
expect(output).not.toContain(`- [hephaestus.md]{${bundledRulePath}}`);
|
|
170
167
|
});
|
|
171
168
|
|
|
172
169
|
it("#given same project and bundled body #when SessionStart runs #then project rule file wins", async () => {
|
|
@@ -180,8 +177,7 @@ describe("plugin bundled rules", () => {
|
|
|
180
177
|
});
|
|
181
178
|
|
|
182
179
|
// then
|
|
183
|
-
expect(
|
|
184
|
-
expect(output).toContain(`Instructions from: ${projectRulePath}`);
|
|
180
|
+
expect(output).toContain(`${INSTRUCTIONS_FROM}${projectRulePath}`);
|
|
185
181
|
expect(output).toContain(SHARED_BODY);
|
|
186
182
|
expect(output).not.toContain(bundledRulePath);
|
|
187
183
|
});
|
|
@@ -207,7 +203,7 @@ describe("plugin bundled rules", () => {
|
|
|
207
203
|
pluginDataRoot: pluginData,
|
|
208
204
|
env: BUNDLED_ONLY_ENV,
|
|
209
205
|
});
|
|
210
|
-
expect(firstOutput).toContain(
|
|
206
|
+
expect(firstOutput).toContain(`${INSTRUCTIONS_FROM}${bundledRulePath}`);
|
|
211
207
|
expect(firstOutput).toContain(BUNDLED_BODY);
|
|
212
208
|
|
|
213
209
|
// when
|
|
@@ -219,9 +215,8 @@ describe("plugin bundled rules", () => {
|
|
|
219
215
|
|
|
220
216
|
// then
|
|
221
217
|
expect(compactOutput).toBe("");
|
|
222
|
-
expect(output).toContain(
|
|
218
|
+
expect(output).toContain(`${INSTRUCTIONS_FROM}${bundledRulePath}`);
|
|
223
219
|
expect(output).toContain(BUNDLED_BODY);
|
|
224
|
-
expect(output).not.toContain("[Truncated. Full:");
|
|
225
220
|
});
|
|
226
221
|
|
|
227
222
|
it("#given bundled Hephaestus rule body exceeds per-rule cap #when SessionStart runs #then static context expands the body within result budget", async () => {
|
|
@@ -232,7 +227,7 @@ describe("plugin bundled rules", () => {
|
|
|
232
227
|
tempDirectories.push(root, pluginRoot, pluginData);
|
|
233
228
|
writeFileSync(join(root, "package.json"), JSON.stringify({ name: "fixture" }));
|
|
234
229
|
mkdirSync(join(pluginRoot, "bundled-rules"), { recursive: true });
|
|
235
|
-
const oversizedBody = "
|
|
230
|
+
const oversizedBody = "BUNDLED_OVERSIZE_SENTINEL_".repeat(500);
|
|
236
231
|
expect(oversizedBody.length).toBeGreaterThan(12000);
|
|
237
232
|
const tailMarker = "BUNDLED_TAIL_SENTINEL_LANDS_IN_FULL";
|
|
238
233
|
const bundledRulePath = join(pluginRoot, "bundled-rules", "hephaestus.md");
|
|
@@ -247,10 +242,9 @@ describe("plugin bundled rules", () => {
|
|
|
247
242
|
});
|
|
248
243
|
|
|
249
244
|
// then
|
|
250
|
-
expect(output).toContain(
|
|
251
|
-
expect(output).toContain("
|
|
245
|
+
expect(output).toContain(`${INSTRUCTIONS_FROM}${bundledRulePath}`);
|
|
246
|
+
expect(output).toContain("BUNDLED_OVERSIZE_SENTINEL_");
|
|
252
247
|
expect(output).toContain(tailMarker);
|
|
253
|
-
expect(output).not.toContain("[Truncated. Full:");
|
|
254
248
|
});
|
|
255
249
|
|
|
256
250
|
it("#given project rule body exceeds per-rule cap #when SessionStart runs #then static context injects a truncated body", async () => {
|
|
@@ -262,7 +256,7 @@ describe("plugin bundled rules", () => {
|
|
|
262
256
|
writeFileSync(join(root, "package.json"), JSON.stringify({ name: "fixture" }));
|
|
263
257
|
mkdirSync(join(root, ".omo", "rules"), { recursive: true });
|
|
264
258
|
mkdirSync(join(pluginRoot, "bundled-rules"), { recursive: true });
|
|
265
|
-
const oversizedBody = "
|
|
259
|
+
const oversizedBody = "PROJECT_OVERSIZE_SENTINEL_".repeat(500);
|
|
266
260
|
expect(oversizedBody.length).toBeGreaterThan(12000);
|
|
267
261
|
const tailMarker = "PROJECT_TAIL_SENTINEL_SHOULD_NOT_LAND";
|
|
268
262
|
const projectRulePath = join(root, ".omo", "rules", "oversized.md");
|
|
@@ -277,9 +271,8 @@ describe("plugin bundled rules", () => {
|
|
|
277
271
|
});
|
|
278
272
|
|
|
279
273
|
// then
|
|
280
|
-
expect(output).toContain(
|
|
281
|
-
expect(output).toContain("
|
|
282
|
-
expect(output).toContain("[Truncated. Full:");
|
|
274
|
+
expect(output).toContain(`${INSTRUCTIONS_FROM}${projectRulePath}`);
|
|
275
|
+
expect(output).toContain("PROJECT_OVERSIZE_SENTINEL_");
|
|
283
276
|
expect(output).not.toContain(tailMarker);
|
|
284
277
|
});
|
|
285
278
|
});
|
package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-budget.test.ts
CHANGED
|
@@ -18,6 +18,10 @@ const PROJECT_RULES_ENV = {
|
|
|
18
18
|
CODEX_RULES_MAX_RULE_CHARS: "30000",
|
|
19
19
|
};
|
|
20
20
|
|
|
21
|
+
// Runtime sentinel: the rules hook emits and re-greps this marker when
|
|
22
|
+
// deduplicating injected rules against the transcript (transcript-rule-filter.ts).
|
|
23
|
+
const INSTRUCTIONS_FROM = "Instructions from: ";
|
|
24
|
+
|
|
21
25
|
afterEach(() => {
|
|
22
26
|
for (const directory of tempDirectories.splice(0)) {
|
|
23
27
|
rmSync(directory, { recursive: true, force: true });
|
|
@@ -46,15 +50,13 @@ describe("codex rules post-compaction context budget", () => {
|
|
|
46
50
|
});
|
|
47
51
|
|
|
48
52
|
// then
|
|
49
|
-
expect(firstContext).toContain(
|
|
50
|
-
expect(firstContext).toContain("
|
|
51
|
-
expect(firstContext).toContain("
|
|
53
|
+
expect(firstContext).toContain(`${INSTRUCTIONS_FROM}${path.join(root, "CONTEXT.md")}`);
|
|
54
|
+
expect(firstContext).toContain("CTX_OVERSIZE_SENTINEL");
|
|
55
|
+
expect(firstContext).not.toContain("CTX_TAIL_SENTINEL");
|
|
52
56
|
expect(firstContext.length).toBeLessThan(31_000);
|
|
53
57
|
const recoveryContext = readAdditionalContext(output);
|
|
54
|
-
expect(recoveryContext).toContain("MUST READ");
|
|
55
|
-
expect(recoveryContext).toContain("NO EXCUSES");
|
|
56
58
|
expect(recoveryContext).toContain(path.join(root, "CONTEXT.md"));
|
|
57
|
-
expect(recoveryContext).not.toContain("
|
|
59
|
+
expect(recoveryContext).not.toContain("CTX_OVERSIZE_SENTINEL");
|
|
58
60
|
expect(recoveryContext.length).toBeLessThan(2_000);
|
|
59
61
|
});
|
|
60
62
|
});
|
|
@@ -66,7 +68,7 @@ function makeOversizedProject(): { root: string; pluginData: string } {
|
|
|
66
68
|
writeFileSync(path.join(root, "package.json"), JSON.stringify({ name: "fixture" }));
|
|
67
69
|
writeFileSync(path.join(root, "AGENTS.md"), "Project AGENTS.md should stay Codex-native.");
|
|
68
70
|
writeFileSync(path.join(root, "CLAUDE.md"), "Project CLAUDE.md should stay outside rules hook context.");
|
|
69
|
-
writeFileSync(path.join(root, "CONTEXT.md"), `
|
|
71
|
+
writeFileSync(path.join(root, "CONTEXT.md"), `CTX_OVERSIZE_SENTINEL\n${"A".repeat(30_000)}\nCTX_TAIL_SENTINEL`);
|
|
70
72
|
mkdirSync(path.join(root, ".omo", "rules"), { recursive: true });
|
|
71
73
|
writeFileSync(
|
|
72
74
|
path.join(root, ".omo", "rules", "typescript.md"),
|
package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-context.test.ts
CHANGED
|
@@ -38,7 +38,6 @@ describe("codex rules compacted context recovery", () => {
|
|
|
38
38
|
// then
|
|
39
39
|
const postCompactContext = readAdditionalContext(output);
|
|
40
40
|
expect(postCompactContext.length).toBeLessThan(2_000);
|
|
41
|
-
expect(postCompactContext).toContain("MUST READ");
|
|
42
41
|
expect(postCompactContext).toContain("CONTEXT.md");
|
|
43
42
|
expect(postCompactContext).not.toContain("Project rule");
|
|
44
43
|
});
|
|
@@ -65,7 +64,6 @@ describe("codex rules compacted context recovery", () => {
|
|
|
65
64
|
// then
|
|
66
65
|
const firstContext = readOptionalAdditionalContext(firstOutput);
|
|
67
66
|
expect(firstContext.length).toBeLessThan(1_000);
|
|
68
|
-
expect(firstContext).toContain("MUST READ");
|
|
69
67
|
expect(firstContext).toContain("CONTEXT.md");
|
|
70
68
|
expect(secondOutput).toBe("");
|
|
71
69
|
});
|
|
@@ -88,7 +86,6 @@ describe("codex rules compacted context recovery", () => {
|
|
|
88
86
|
// then
|
|
89
87
|
const context = readOptionalAdditionalContext(output);
|
|
90
88
|
expect(context.length).toBeLessThan(1_000);
|
|
91
|
-
expect(context).toContain("MUST READ");
|
|
92
89
|
expect(context).toContain("CONTEXT.md");
|
|
93
90
|
});
|
|
94
91
|
|
|
@@ -106,7 +103,6 @@ describe("codex rules compacted context recovery", () => {
|
|
|
106
103
|
// then
|
|
107
104
|
const context = readOptionalAdditionalContext(output);
|
|
108
105
|
expect(context.length).toBeLessThan(1_000);
|
|
109
|
-
expect(context).toContain("MUST READ");
|
|
110
106
|
expect(context).toContain("CONTEXT.md");
|
|
111
107
|
});
|
|
112
108
|
|
|
@@ -128,7 +124,6 @@ describe("codex rules compacted context recovery", () => {
|
|
|
128
124
|
// then
|
|
129
125
|
const context = readOptionalAdditionalContext(output);
|
|
130
126
|
expect(context.length).toBeLessThan(1_000);
|
|
131
|
-
expect(context).toContain("MUST READ");
|
|
132
127
|
expect(context).toContain("CONTEXT.md");
|
|
133
128
|
});
|
|
134
129
|
|
|
@@ -157,7 +152,6 @@ describe("codex rules compacted context recovery", () => {
|
|
|
157
152
|
const contexts = outputs.map(readOptionalAdditionalContext);
|
|
158
153
|
expect(contexts.filter((context) => context.length > 0)).toHaveLength(1);
|
|
159
154
|
expect(contexts.join("").length).toBeLessThan(1_000);
|
|
160
|
-
expect(contexts.join("")).toContain("MUST READ");
|
|
161
155
|
expect(contexts.join("")).toContain("CONTEXT.md");
|
|
162
156
|
});
|
|
163
157
|
});
|
package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-dedup.test.ts
CHANGED
|
@@ -18,6 +18,10 @@ const PROJECT_ONLY_ENV = {
|
|
|
18
18
|
CODEX_RULES_ENABLED_SOURCES: "CONTEXT.md,.omo/rules",
|
|
19
19
|
};
|
|
20
20
|
|
|
21
|
+
// Runtime sentinel: the rules hook emits and re-greps this marker when
|
|
22
|
+
// deduplicating injected rules against the transcript (transcript-rule-filter.ts).
|
|
23
|
+
const INSTRUCTIONS_FROM = "Instructions from: ";
|
|
24
|
+
|
|
21
25
|
afterEach(() => {
|
|
22
26
|
for (const directory of tempDirectories.splice(0)) {
|
|
23
27
|
rmSync(directory, { recursive: true, force: true });
|
|
@@ -114,9 +118,8 @@ describe("codex rules PostCompact deduplication", () => {
|
|
|
114
118
|
|
|
115
119
|
// then
|
|
116
120
|
const context = readAdditionalContext(output);
|
|
117
|
-
expect(context).toContain("MUST READ");
|
|
118
121
|
expect(context).toContain("CONTEXT.md");
|
|
119
|
-
expect(context).not.toContain(
|
|
122
|
+
expect(context).not.toContain(INSTRUCTIONS_FROM);
|
|
120
123
|
});
|
|
121
124
|
|
|
122
125
|
it("#given startup static context dropped by compaction #when compact SessionStart runs after PostCompact #then it emits a mandatory read directive without rule bodies", async () => {
|
|
@@ -140,9 +143,8 @@ describe("codex rules PostCompact deduplication", () => {
|
|
|
140
143
|
|
|
141
144
|
// then
|
|
142
145
|
const context = readAdditionalContext(output);
|
|
143
|
-
expect(context).toContain("MUST READ");
|
|
144
146
|
expect(context).toContain("CONTEXT.md");
|
|
145
|
-
expect(context).not.toContain(
|
|
147
|
+
expect(context).not.toContain(INSTRUCTIONS_FROM);
|
|
146
148
|
});
|
|
147
149
|
});
|
|
148
150
|
|
package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-directive.test.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
1
|
+
import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { tmpdir } from "node:os";
|
|
3
3
|
import path from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { parseRule } from "@oh-my-opencode/rules-engine/engine";
|
|
4
6
|
import { afterEach, describe, expect, it } from "vitest";
|
|
5
|
-
|
|
6
7
|
import {
|
|
7
8
|
type CodexPostCompactInput,
|
|
8
9
|
type CodexPostToolUseInput,
|
|
@@ -20,6 +21,10 @@ const PROJECT_ONLY_ENV = {
|
|
|
20
21
|
};
|
|
21
22
|
const SESSION_ID = "session-post-compact-directive";
|
|
22
23
|
|
|
24
|
+
// Runtime sentinel: the rules hook emits and re-greps this marker when
|
|
25
|
+
// deduplicating injected rules against the transcript (transcript-rule-filter.ts).
|
|
26
|
+
const INSTRUCTIONS_FROM = "Instructions from: ";
|
|
27
|
+
|
|
23
28
|
afterEach(() => {
|
|
24
29
|
for (const directory of tempDirectories.splice(0)) {
|
|
25
30
|
rmSync(directory, { recursive: true, force: true });
|
|
@@ -48,10 +53,8 @@ describe("codex rules post-compaction read directive", () => {
|
|
|
48
53
|
});
|
|
49
54
|
|
|
50
55
|
// then
|
|
51
|
-
expect(dynamicOutput).toContain("
|
|
56
|
+
expect(dynamicOutput).toContain("TS_RULE_SENTINEL");
|
|
52
57
|
const context = readAdditionalContext(output);
|
|
53
|
-
expect(context).toContain("MUST READ");
|
|
54
|
-
expect(context).toContain("NO EXCUSES");
|
|
55
58
|
expect(context).toContain("CONTEXT.md");
|
|
56
59
|
expect(context).toContain(".omo/rules/typescript.md");
|
|
57
60
|
expect(context).not.toContain("A".repeat(50));
|
|
@@ -125,9 +128,9 @@ describe("codex rules post-compaction read directive", () => {
|
|
|
125
128
|
|
|
126
129
|
// then
|
|
127
130
|
const context = readAdditionalContext(output);
|
|
128
|
-
|
|
129
|
-
expect(context).
|
|
130
|
-
expect(context).toContain(
|
|
131
|
+
const bundledRulePath = fileURLToPath(new URL("../bundled-rules/hephaestus/gpt-5.5.md", import.meta.url));
|
|
132
|
+
expect(context).toContain(`${INSTRUCTIONS_FROM}${bundledRulePath}`);
|
|
133
|
+
expect(context).toContain(parseRule(readFileSync(bundledRulePath, "utf8")).body.trim());
|
|
131
134
|
expect(context).toContain("CONTEXT.md");
|
|
132
135
|
});
|
|
133
136
|
});
|
|
@@ -141,7 +144,7 @@ function makeProject(): { root: string; pluginData: string } {
|
|
|
141
144
|
mkdirSync(path.join(root, ".omo", "rules"), { recursive: true });
|
|
142
145
|
writeFileSync(
|
|
143
146
|
path.join(root, ".omo", "rules", "typescript.md"),
|
|
144
|
-
["---", 'globs: "**/*.ts"', "---", "", `
|
|
147
|
+
["---", 'globs: "**/*.ts"', "---", "", `TS_RULE_SENTINEL\n${"B".repeat(2_000)}`].join("\n"),
|
|
145
148
|
);
|
|
146
149
|
mkdirSync(path.join(root, "src"), { recursive: true });
|
|
147
150
|
writeFileSync(path.join(root, "src", "app.ts"), "export const app = 1;\n");
|
|
@@ -77,6 +77,10 @@ const DYNAMIC_BUNDLED_ONLY_ENV = {
|
|
|
77
77
|
PLUGIN_ROOT: COMPONENT_ROOT,
|
|
78
78
|
};
|
|
79
79
|
|
|
80
|
+
// Runtime sentinel: the rules hook emits and re-greps this marker when
|
|
81
|
+
// deduplicating injected rules against the transcript (transcript-rule-filter.ts).
|
|
82
|
+
const INSTRUCTIONS_FROM = "Instructions from: ";
|
|
83
|
+
|
|
80
84
|
afterEach(() => {
|
|
81
85
|
for (const directory of tempDirectories.splice(0)) {
|
|
82
86
|
rmSync(directory, { recursive: true, force: true });
|
|
@@ -88,20 +92,13 @@ function makeTempProject(): { root: string; pluginData: string } {
|
|
|
88
92
|
const pluginData = mkdtempSync(path.join(tmpdir(), "codex-rules-data-"));
|
|
89
93
|
tempDirectories.push(root, pluginData);
|
|
90
94
|
writeFileSync(path.join(root, "package.json"), JSON.stringify({ name: "fixture" }));
|
|
91
|
-
writeFileSync(path.join(root, "AGENTS.md"), "
|
|
92
|
-
writeFileSync(path.join(root, "CLAUDE.md"), "
|
|
93
|
-
writeFileSync(path.join(root, "CONTEXT.md"), "
|
|
95
|
+
writeFileSync(path.join(root, "AGENTS.md"), "AGENTS_MD_SENTINEL");
|
|
96
|
+
writeFileSync(path.join(root, "CLAUDE.md"), "CLAUDE_MD_SENTINEL");
|
|
97
|
+
writeFileSync(path.join(root, "CONTEXT.md"), "CTX_RULE_SENTINEL");
|
|
94
98
|
mkdirSync(path.join(root, ".omo", "rules"), { recursive: true });
|
|
95
99
|
writeFileSync(
|
|
96
100
|
path.join(root, ".omo", "rules", "typescript.md"),
|
|
97
|
-
[
|
|
98
|
-
"---",
|
|
99
|
-
"description: TypeScript",
|
|
100
|
-
'globs: ["**/*.ts", "**/*.tsx"]',
|
|
101
|
-
"---",
|
|
102
|
-
"",
|
|
103
|
-
"Prefer strict TypeScript for all source files.",
|
|
104
|
-
].join("\n"),
|
|
101
|
+
["---", "description: TypeScript", 'globs: ["**/*.ts", "**/*.tsx"]', "---", "", "TS_RULE_SENTINEL"].join("\n"),
|
|
105
102
|
);
|
|
106
103
|
mkdirSync(path.join(root, "src"), { recursive: true });
|
|
107
104
|
writeFileSync(path.join(root, "src", "app.ts"), "export const app = true;\n");
|
|
@@ -224,11 +221,10 @@ describe("codex rules hooks", () => {
|
|
|
224
221
|
// then
|
|
225
222
|
const parsed = parseHookOutput(output);
|
|
226
223
|
expect(parsed.hookSpecificOutput?.hookEventName).toBe("SessionStart");
|
|
227
|
-
expect(parsed.hookSpecificOutput?.additionalContext).toContain("## Project Instructions");
|
|
228
224
|
expect(parsed.hookSpecificOutput?.additionalContext).toContain(
|
|
229
|
-
|
|
225
|
+
`${INSTRUCTIONS_FROM}${path.join(root, "CONTEXT.md")}`,
|
|
230
226
|
);
|
|
231
|
-
expect(parsed.hookSpecificOutput?.additionalContext).toContain("
|
|
227
|
+
expect(parsed.hookSpecificOutput?.additionalContext).toContain("CTX_RULE_SENTINEL");
|
|
232
228
|
});
|
|
233
229
|
|
|
234
230
|
it("#given default auto sources #when SessionStart runs #then native Codex AGENTS.md is not duplicated", async () => {
|
|
@@ -242,11 +238,11 @@ describe("codex rules hooks", () => {
|
|
|
242
238
|
|
|
243
239
|
// then
|
|
244
240
|
const parsed = parseHookOutput(output);
|
|
245
|
-
expect(parsed.hookSpecificOutput?.additionalContext).toContain(
|
|
246
|
-
|
|
247
|
-
expect(parsed.hookSpecificOutput?.additionalContext).not.toContain(
|
|
248
|
-
"Project CLAUDE.md should stay outside rules hook context.",
|
|
241
|
+
expect(parsed.hookSpecificOutput?.additionalContext).toContain(
|
|
242
|
+
`${INSTRUCTIONS_FROM}${path.join(root, "CONTEXT.md")}`,
|
|
249
243
|
);
|
|
244
|
+
expect(parsed.hookSpecificOutput?.additionalContext).not.toContain("AGENTS_MD_SENTINEL");
|
|
245
|
+
expect(parsed.hookSpecificOutput?.additionalContext).not.toContain("CLAUDE_MD_SENTINEL");
|
|
250
246
|
});
|
|
251
247
|
|
|
252
248
|
it("#given project AGENTS.md #when SessionStart runs #then rules hook leaves AGENTS.md to Codex native handling", async () => {
|
|
@@ -320,9 +316,8 @@ describe("codex rules hooks", () => {
|
|
|
320
316
|
// then
|
|
321
317
|
expect(resumeOutput).toBe("");
|
|
322
318
|
const clearContext = parseHookOutput(clearOutput).hookSpecificOutput?.additionalContext ?? "";
|
|
323
|
-
expect(clearContext).toContain(
|
|
324
|
-
expect(clearContext).toContain(
|
|
325
|
-
expect(clearContext).toContain("Always wear safety goggles");
|
|
319
|
+
expect(clearContext).toContain(`${INSTRUCTIONS_FROM}${path.join(root, "CONTEXT.md")}`);
|
|
320
|
+
expect(clearContext).toContain("CTX_RULE_SENTINEL");
|
|
326
321
|
});
|
|
327
322
|
|
|
328
323
|
it("#given static context remains in transcript but cache is missing #when SessionStart runs #then it emits no duplicate context", async () => {
|
|
@@ -363,10 +358,8 @@ describe("codex rules hooks", () => {
|
|
|
363
358
|
// regression line: prior versions emitted "src\\app.ts" on Windows.
|
|
364
359
|
const parsed = parseHookOutput(output);
|
|
365
360
|
expect(parsed.hookSpecificOutput?.hookEventName).toBe("PostToolUse");
|
|
366
|
-
expect(parsed.hookSpecificOutput?.additionalContext).toContain(
|
|
367
|
-
|
|
368
|
-
);
|
|
369
|
-
expect(parsed.hookSpecificOutput?.additionalContext).toContain("Prefer strict TypeScript");
|
|
361
|
+
expect(parsed.hookSpecificOutput?.additionalContext).toContain("src/app.ts");
|
|
362
|
+
expect(parsed.hookSpecificOutput?.additionalContext).toContain("TS_RULE_SENTINEL");
|
|
370
363
|
expect(parsed.hookSpecificOutput?.additionalContext ?? "").not.toContain("src\\app.ts");
|
|
371
364
|
expect(output).not.toContain("updatedMCPToolOutput");
|
|
372
365
|
expect(output).not.toContain("suppressOutput");
|
|
@@ -396,9 +389,9 @@ describe("codex rules hooks", () => {
|
|
|
396
389
|
const parsed = parseHookOutput(output);
|
|
397
390
|
const additionalContext = parsed.hookSpecificOutput?.additionalContext ?? "";
|
|
398
391
|
expect(parsed.hookSpecificOutput?.hookEventName).toBe("PostToolUse");
|
|
399
|
-
expect(additionalContext).toContain("
|
|
392
|
+
expect(additionalContext).toContain("src/app.ts");
|
|
400
393
|
expect(additionalContext).not.toContain("src\\app.ts");
|
|
401
|
-
expect(occurrenceCount(additionalContext, "
|
|
394
|
+
expect(occurrenceCount(additionalContext, "TS_RULE_SENTINEL")).toBe(1);
|
|
402
395
|
});
|
|
403
396
|
|
|
404
397
|
it("#given dynamic context already injected #when PostToolUse repeats #then emits no duplicate context", async () => {
|
|
@@ -437,10 +430,10 @@ describe("codex rules hooks", () => {
|
|
|
437
430
|
// then
|
|
438
431
|
const firstContext = parseHookOutput(firstOutput).hookSpecificOutput?.additionalContext ?? "";
|
|
439
432
|
const secondContext = parseHookOutput(secondOutput).hookSpecificOutput?.additionalContext ?? "";
|
|
440
|
-
expect(firstContext).toContain("
|
|
441
|
-
expect(firstContext).not.toContain("
|
|
442
|
-
expect(secondContext).toContain("
|
|
443
|
-
expect(secondContext).not.toContain("
|
|
433
|
+
expect(firstContext).toContain("bundled-rules/hephaestus/gpt-5.5.md");
|
|
434
|
+
expect(firstContext).not.toContain("bundled-rules/hephaestus/gpt-5.6.md");
|
|
435
|
+
expect(secondContext).toContain("bundled-rules/hephaestus/gpt-5.6.md");
|
|
436
|
+
expect(secondContext).not.toContain("bundled-rules/hephaestus/gpt-5.5.md");
|
|
444
437
|
});
|
|
445
438
|
|
|
446
439
|
it("#given default auto sources #when excluded AGENTS.md changes #then PostToolUse fingerprint stays stable", async () => {
|
|
@@ -496,7 +489,7 @@ describe("codex rules hooks", () => {
|
|
|
496
489
|
);
|
|
497
490
|
|
|
498
491
|
// then
|
|
499
|
-
expect(parseHookOutput(output).hookSpecificOutput?.additionalContext).toContain("
|
|
492
|
+
expect(parseHookOutput(output).hookSpecificOutput?.additionalContext).toContain("TS_RULE_SENTINEL");
|
|
500
493
|
});
|
|
501
494
|
|
|
502
495
|
it("#given cached dynamic target #when rule frontmatter changes #then PostToolUse rechecks the target", async () => {
|
|
@@ -505,15 +498,13 @@ describe("codex rules hooks", () => {
|
|
|
505
498
|
const filePath = path.join(root, "src", "app.ts");
|
|
506
499
|
const input = postToolUseInput(root, filePath);
|
|
507
500
|
await runPostToolUseHook(input, { pluginDataRoot: pluginData, env: RULES_ONLY_ENV });
|
|
508
|
-
writeTypeScriptRule(root, '"**/*.ts"', "
|
|
501
|
+
writeTypeScriptRule(root, '"**/*.ts"', "TS_RULE_V2_SENTINEL");
|
|
509
502
|
|
|
510
503
|
// when
|
|
511
504
|
const output = await runPostToolUseHook(input, { pluginDataRoot: pluginData, env: RULES_ONLY_ENV });
|
|
512
505
|
|
|
513
506
|
// then
|
|
514
|
-
expect(parseHookOutput(output).hookSpecificOutput?.additionalContext).toContain(
|
|
515
|
-
"Prefer readonly TypeScript after rule edits.",
|
|
516
|
-
);
|
|
507
|
+
expect(parseHookOutput(output).hookSpecificOutput?.additionalContext).toContain("TS_RULE_V2_SENTINEL");
|
|
517
508
|
});
|
|
518
509
|
|
|
519
510
|
it("#given cached dynamic context #when PostCompact runs #then PostToolUse emits no duplicate dynamic context", async () => {
|
|
@@ -633,7 +624,7 @@ describe("codex rules hooks", () => {
|
|
|
633
624
|
});
|
|
634
625
|
|
|
635
626
|
// then
|
|
636
|
-
expect(parseHookOutput(output).hookSpecificOutput?.additionalContext).toContain("
|
|
627
|
+
expect(parseHookOutput(output).hookSpecificOutput?.additionalContext).toContain("TS_RULE_SENTINEL");
|
|
637
628
|
});
|
|
638
629
|
|
|
639
630
|
it("#given static-only mode #when PostToolUse runs #then emits no dynamic context", async () => {
|
|
@@ -8,13 +8,18 @@ const FORMAT_OPTIONS = {
|
|
|
8
8
|
maxResultChars: 10_000,
|
|
9
9
|
};
|
|
10
10
|
|
|
11
|
+
// Runtime sentinel: the rules hook emits and re-greps this marker when
|
|
12
|
+
// deduplicating injected rules against the transcript (transcript-rule-filter.ts).
|
|
13
|
+
const INSTRUCTIONS_FROM = "Instructions from: ";
|
|
14
|
+
|
|
11
15
|
describe("rules formatter hook context", () => {
|
|
12
16
|
it("#given multiline dynamic rules #when formatting PostToolUse context #then labels and bodies render on separate lines", () => {
|
|
13
17
|
// given
|
|
18
|
+
const body = "DYN_BODY_SENTINEL_LINE_1\n\nDYN_BODY_SENTINEL_LINE_2";
|
|
14
19
|
const rule = loadedRule({
|
|
15
20
|
path: "/repo/packages/CONTEXT.md",
|
|
16
21
|
relativePath: "packages/CONTEXT.md",
|
|
17
|
-
body
|
|
22
|
+
body,
|
|
18
23
|
});
|
|
19
24
|
|
|
20
25
|
// when
|
|
@@ -25,124 +30,86 @@ describe("rules formatter hook context", () => {
|
|
|
25
30
|
);
|
|
26
31
|
|
|
27
32
|
// then
|
|
28
|
-
expect(block).
|
|
29
|
-
|
|
30
|
-
"Additional project instructions matched for packages/omo-codex/plugin/components/ulw-loop/src/paths.ts:",
|
|
31
|
-
"",
|
|
32
|
-
"Instructions from: /repo/packages/CONTEXT.md",
|
|
33
|
-
"",
|
|
34
|
-
"# packages",
|
|
35
|
-
"",
|
|
36
|
-
"## OVERVIEW",
|
|
37
|
-
"23 sibling packages.",
|
|
38
|
-
"",
|
|
39
|
-
"## CONVENTIONS",
|
|
40
|
-
"Use npm.",
|
|
41
|
-
].join("\n"),
|
|
42
|
-
);
|
|
33
|
+
expect(block).toContain(`${INSTRUCTIONS_FROM}/repo/packages/CONTEXT.md\n\n${body}`);
|
|
34
|
+
expect(occurrenceCount(block, INSTRUCTIONS_FROM)).toBe(1);
|
|
43
35
|
});
|
|
44
36
|
|
|
45
37
|
it("#given static rules #when formatting SessionStart context #then it injects rule bodies inline", () => {
|
|
46
38
|
// given
|
|
39
|
+
const body = "STATIC_BODY_SENTINEL";
|
|
47
40
|
const rule = loadedRule({
|
|
48
41
|
path: "/repo/CONTEXT.md",
|
|
49
42
|
relativePath: "CONTEXT.md",
|
|
50
|
-
body
|
|
43
|
+
body,
|
|
51
44
|
});
|
|
52
45
|
|
|
53
46
|
// when
|
|
54
47
|
const block = formatStaticBlock([rule], FORMAT_OPTIONS);
|
|
55
48
|
|
|
56
49
|
// then
|
|
57
|
-
expect(block).
|
|
58
|
-
[
|
|
59
|
-
"## Project Instructions",
|
|
60
|
-
"",
|
|
61
|
-
"Instructions from: /repo/CONTEXT.md",
|
|
62
|
-
"",
|
|
63
|
-
"Keep generated hook context readable.",
|
|
64
|
-
].join("\n"),
|
|
65
|
-
);
|
|
50
|
+
expect(block).toContain(`${INSTRUCTIONS_FROM}/repo/CONTEXT.md\n\n${body}`);
|
|
66
51
|
});
|
|
67
52
|
|
|
68
53
|
it("#given CRLF and bare CR rule bodies #when formatting context #then it normalizes line endings", () => {
|
|
69
54
|
// given
|
|
70
55
|
const rule = loadedRule({
|
|
71
|
-
body: "
|
|
56
|
+
body: "A1\r\n B2\rC3",
|
|
72
57
|
});
|
|
73
58
|
|
|
74
59
|
// when
|
|
75
60
|
const block = formatDynamicBlock([rule], "src/app.ts", FORMAT_OPTIONS);
|
|
76
61
|
|
|
77
62
|
// then
|
|
78
|
-
expect(block).toContain("
|
|
63
|
+
expect(block).toContain("A1\n B2\nC3");
|
|
79
64
|
expect(block).not.toContain("\r");
|
|
80
65
|
});
|
|
81
66
|
|
|
82
67
|
it("#given duplicate static rules with different line endings #when formatting context #then it injects one copy", () => {
|
|
83
68
|
// given
|
|
69
|
+
const sharedBody = "SHARED_L1\r\nSHARED_L2";
|
|
70
|
+
const normalizedSharedBody = "SHARED_L1\nSHARED_L2";
|
|
84
71
|
const lfRule = loadedRule({
|
|
85
72
|
path: "/repo/CONTEXT.md",
|
|
86
73
|
relativePath: "CONTEXT.md",
|
|
87
|
-
body:
|
|
74
|
+
body: normalizedSharedBody,
|
|
88
75
|
});
|
|
89
76
|
const crlfRule = loadedRule({
|
|
90
77
|
path: "/repo/packages/CONTEXT.md",
|
|
91
78
|
relativePath: "packages/CONTEXT.md",
|
|
92
|
-
body:
|
|
79
|
+
body: sharedBody,
|
|
93
80
|
});
|
|
94
81
|
|
|
95
82
|
// when
|
|
96
83
|
const block = formatStaticBlock([lfRule, crlfRule], FORMAT_OPTIONS);
|
|
97
84
|
|
|
98
85
|
// then
|
|
99
|
-
expect(occurrenceCount(block,
|
|
100
|
-
expect(occurrenceCount(block,
|
|
86
|
+
expect(occurrenceCount(block, `${INSTRUCTIONS_FROM}/repo/CONTEXT.md`)).toBe(1);
|
|
87
|
+
expect(occurrenceCount(block, normalizedSharedBody)).toBe(1);
|
|
101
88
|
expect(block).not.toContain("/repo/packages/CONTEXT.md");
|
|
102
89
|
});
|
|
103
90
|
|
|
104
91
|
it("#given a Hephaestus static rule #when formatting SessionStart context #then it injects its body before other rule bodies", () => {
|
|
105
92
|
// given
|
|
106
93
|
const rules = [
|
|
107
|
-
loadedRule({ path: "/repo/alpha.md", relativePath: "alpha.md", body: "
|
|
94
|
+
loadedRule({ path: "/repo/alpha.md", relativePath: "alpha.md", body: "ALPHA_BODY_SENTINEL" }),
|
|
108
95
|
loadedRule({
|
|
109
96
|
path: "/repo/bundled-rules/hephaestus.md",
|
|
110
97
|
relativePath: "bundled-rules/hephaestus.md",
|
|
111
|
-
body: "
|
|
98
|
+
body: "HEPHAESTUS_BODY_SENTINEL",
|
|
112
99
|
}),
|
|
113
|
-
loadedRule({ path: "/repo/beta.md", relativePath: "beta.md", body: "
|
|
100
|
+
loadedRule({ path: "/repo/beta.md", relativePath: "beta.md", body: "BETA_BODY_SENTINEL" }),
|
|
114
101
|
];
|
|
115
102
|
|
|
116
103
|
// when
|
|
117
104
|
const block = formatStaticBlock(rules, FORMAT_OPTIONS);
|
|
118
105
|
|
|
119
106
|
// then
|
|
120
|
-
expect(block).toContain(
|
|
121
|
-
expect(block).toContain("
|
|
122
|
-
expect(block).toContain("
|
|
123
|
-
expect(block).toContain("
|
|
124
|
-
expect(block.indexOf("
|
|
125
|
-
expect(block.indexOf("
|
|
126
|
-
expect(block).not.toContain("must read project rules:");
|
|
127
|
-
expect(block).not.toContain("- [hephaestus.md]");
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
it("#given only a Hephaestus static rule #when formatting SessionStart context #then it emits no project rule link section", () => {
|
|
131
|
-
// given
|
|
132
|
-
const rule = loadedRule({
|
|
133
|
-
path: "/repo/bundled-rules/hephaestus.md",
|
|
134
|
-
relativePath: "bundled-rules/hephaestus.md",
|
|
135
|
-
body: "Hephaestus guidance.",
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
// when
|
|
139
|
-
const block = formatStaticBlock([rule], FORMAT_OPTIONS);
|
|
140
|
-
|
|
141
|
-
// then
|
|
142
|
-
expect(block).toContain("Instructions from: /repo/bundled-rules/hephaestus.md");
|
|
143
|
-
expect(block).toContain("Hephaestus guidance.");
|
|
144
|
-
expect(block).not.toContain("- [hephaestus.md]");
|
|
145
|
-
expect(block).not.toContain("must read project rules:");
|
|
107
|
+
expect(block).toContain(`${INSTRUCTIONS_FROM}/repo/bundled-rules/hephaestus.md`);
|
|
108
|
+
expect(block).toContain("HEPHAESTUS_BODY_SENTINEL");
|
|
109
|
+
expect(block).toContain("ALPHA_BODY_SENTINEL");
|
|
110
|
+
expect(block).toContain("BETA_BODY_SENTINEL");
|
|
111
|
+
expect(block.indexOf("HEPHAESTUS_BODY_SENTINEL")).toBeLessThan(block.indexOf("ALPHA_BODY_SENTINEL"));
|
|
112
|
+
expect(block.indexOf("ALPHA_BODY_SENTINEL")).toBeLessThan(block.indexOf("BETA_BODY_SENTINEL"));
|
|
146
113
|
});
|
|
147
114
|
|
|
148
115
|
it("#given an oversized Hephaestus static rule #when formatting under a tight result budget #then its body is never truncated", () => {
|
|
@@ -162,7 +129,6 @@ describe("rules formatter hook context", () => {
|
|
|
162
129
|
|
|
163
130
|
// then
|
|
164
131
|
expect(block).toContain(tailMarker);
|
|
165
|
-
expect(block).not.toContain("[Truncated. Full:");
|
|
166
132
|
});
|
|
167
133
|
|
|
168
134
|
it("#given multiple oversized rules #when formatting under a tight result budget #then every rule receives a fair truncated share with a read-full guide", () => {
|
|
@@ -180,13 +146,15 @@ describe("rules formatter hook context", () => {
|
|
|
180
146
|
});
|
|
181
147
|
|
|
182
148
|
// then
|
|
183
|
-
expect(block).toContain(
|
|
184
|
-
expect(block).toContain(
|
|
185
|
-
expect(block).toContain(
|
|
186
|
-
expect(block).toContain("
|
|
187
|
-
expect(block).toContain("
|
|
188
|
-
expect(block).toContain("
|
|
189
|
-
expect(
|
|
149
|
+
expect(block).toContain(`${INSTRUCTIONS_FROM}/repo/alpha.md`);
|
|
150
|
+
expect(block).toContain(`${INSTRUCTIONS_FROM}/repo/beta.md`);
|
|
151
|
+
expect(block).toContain(`${INSTRUCTIONS_FROM}/repo/gamma.md`);
|
|
152
|
+
expect(block).toContain("alpha-");
|
|
153
|
+
expect(block).toContain("beta-");
|
|
154
|
+
expect(block).toContain("gamma-");
|
|
155
|
+
expect(block).not.toContain("A".repeat(400));
|
|
156
|
+
expect(block).not.toContain("B".repeat(400));
|
|
157
|
+
expect(block).not.toContain("C".repeat(400));
|
|
190
158
|
});
|
|
191
159
|
|
|
192
160
|
it("#given no matching rules #when formatting hook context #then it emits no context", () => {
|