oh-my-copilot 4.13.1 → 4.13.21
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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +3 -3
- package/bridge/cli.cjs +4709 -1961
- package/bridge/mcp-server.cjs +112 -11
- package/bridge/runtime-cli.cjs +4917 -2645
- package/bridge/team-bridge.cjs +6 -4
- package/bridge/team-mcp.cjs +19607 -0
- package/bridge/team.js +4895 -2215
- package/dist/__tests__/auto-slash-aliases.test.js +91 -0
- package/dist/__tests__/auto-slash-aliases.test.js.map +1 -1
- package/dist/__tests__/hooks/learner/bridge.test.js +25 -0
- package/dist/__tests__/hooks/learner/bridge.test.js.map +1 -1
- package/dist/__tests__/hooks/learner/parser.test.js +30 -0
- package/dist/__tests__/hooks/learner/parser.test.js.map +1 -1
- package/dist/__tests__/hud/extra-usage.test.js +42 -0
- package/dist/__tests__/hud/extra-usage.test.js.map +1 -1
- package/dist/__tests__/hud/labels.test.d.ts +2 -0
- package/dist/__tests__/hud/labels.test.d.ts.map +1 -0
- package/dist/__tests__/hud/labels.test.js +158 -0
- package/dist/__tests__/hud/labels.test.js.map +1 -0
- package/dist/__tests__/hud/render-enterprise.test.d.ts +5 -0
- package/dist/__tests__/hud/render-enterprise.test.d.ts.map +1 -0
- package/dist/__tests__/hud/render-enterprise.test.js +232 -0
- package/dist/__tests__/hud/render-enterprise.test.js.map +1 -0
- package/dist/__tests__/hud/render-rate-limits-priority.test.js +185 -0
- package/dist/__tests__/hud/render-rate-limits-priority.test.js.map +1 -1
- package/dist/__tests__/hud/stdin-session-scope.test.d.ts +2 -0
- package/dist/__tests__/hud/stdin-session-scope.test.d.ts.map +1 -0
- package/dist/__tests__/hud/stdin-session-scope.test.js +169 -0
- package/dist/__tests__/hud/stdin-session-scope.test.js.map +1 -0
- package/dist/__tests__/hud/usage-api.test.js +111 -1
- package/dist/__tests__/hud/usage-api.test.js.map +1 -1
- package/dist/__tests__/hud-marketplace-resolution.test.js +34 -0
- package/dist/__tests__/hud-marketplace-resolution.test.js.map +1 -1
- package/dist/__tests__/installer-hud-skip.test.js +6 -0
- package/dist/__tests__/installer-hud-skip.test.js.map +1 -1
- package/dist/__tests__/installer-omc-reference.test.js +1 -1
- package/dist/__tests__/installer-omc-reference.test.js.map +1 -1
- package/dist/__tests__/keyword-detector-echo-guard.test.d.ts +2 -0
- package/dist/__tests__/keyword-detector-echo-guard.test.d.ts.map +1 -0
- package/dist/__tests__/keyword-detector-echo-guard.test.js +218 -0
- package/dist/__tests__/keyword-detector-echo-guard.test.js.map +1 -0
- package/dist/__tests__/mnemosyne/detector.test.js +2 -0
- package/dist/__tests__/mnemosyne/detector.test.js.map +1 -1
- package/dist/__tests__/notepad.test.js +2 -2
- package/dist/__tests__/notepad.test.js.map +1 -1
- package/dist/__tests__/pre-tool-enforcer.test.js +84 -1
- package/dist/__tests__/pre-tool-enforcer.test.js.map +1 -1
- package/dist/__tests__/preemptive-compaction-hook.test.js +63 -0
- package/dist/__tests__/preemptive-compaction-hook.test.js.map +1 -1
- package/dist/__tests__/ralph-prd-mandatory.test.js +11 -1
- package/dist/__tests__/ralph-prd-mandatory.test.js.map +1 -1
- package/dist/__tests__/ralph-prd.test.js +40 -2
- package/dist/__tests__/ralph-prd.test.js.map +1 -1
- package/dist/__tests__/skills.test.js +363 -4
- package/dist/__tests__/skills.test.js.map +1 -1
- package/dist/__tests__/state-root-resolution.test.js +120 -6
- package/dist/__tests__/state-root-resolution.test.js.map +1 -1
- package/dist/autoresearch/__tests__/runtime.test.js +225 -28
- package/dist/autoresearch/__tests__/runtime.test.js.map +1 -1
- package/dist/autoresearch/runtime.d.ts.map +1 -1
- package/dist/autoresearch/runtime.js +9 -5
- package/dist/autoresearch/runtime.js.map +1 -1
- package/dist/cli/__tests__/team-status-worktree.test.d.ts +2 -0
- package/dist/cli/__tests__/team-status-worktree.test.d.ts.map +1 -0
- package/dist/cli/__tests__/team-status-worktree.test.js +96 -0
- package/dist/cli/__tests__/team-status-worktree.test.js.map +1 -0
- package/dist/cli/__tests__/team.test.js +164 -0
- package/dist/cli/__tests__/team.test.js.map +1 -1
- package/dist/cli/autoresearch.d.ts +1 -1
- package/dist/cli/autoresearch.d.ts.map +1 -1
- package/dist/cli/autoresearch.js +4 -4
- package/dist/cli/commands/team.d.ts +1 -0
- package/dist/cli/commands/team.d.ts.map +1 -1
- package/dist/cli/commands/team.js +15 -3
- package/dist/cli/commands/team.js.map +1 -1
- package/dist/cli/index.js +3 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/team.d.ts +6 -0
- package/dist/cli/team.d.ts.map +1 -1
- package/dist/cli/team.js +126 -5
- package/dist/cli/team.js.map +1 -1
- package/dist/cli/utils/formatting.d.ts +0 -10
- package/dist/cli/utils/formatting.d.ts.map +1 -1
- package/dist/cli/utils/formatting.js +0 -52
- package/dist/cli/utils/formatting.js.map +1 -1
- package/dist/config/__tests__/loader.test.js.map +1 -1
- package/dist/features/boulder-state/constants.d.ts +1 -1
- package/dist/features/boulder-state/constants.d.ts.map +1 -1
- package/dist/features/builtin-skills/skills.d.ts.map +1 -1
- package/dist/features/builtin-skills/skills.js +11 -3
- package/dist/features/builtin-skills/skills.js.map +1 -1
- package/dist/features/builtin-skills/types.d.ts +7 -0
- package/dist/features/builtin-skills/types.d.ts.map +1 -1
- package/dist/features/delegation-enforcer.d.ts +2 -0
- package/dist/features/delegation-enforcer.d.ts.map +1 -1
- package/dist/features/delegation-enforcer.js +10 -0
- package/dist/features/delegation-enforcer.js.map +1 -1
- package/dist/features/magic-keywords.d.ts.map +1 -1
- package/dist/features/magic-keywords.js +30 -1
- package/dist/features/magic-keywords.js.map +1 -1
- package/dist/features/rate-limit-wait/tmux-detector.d.ts +4 -4
- package/dist/features/rate-limit-wait/tmux-detector.js +9 -9
- package/dist/features/rate-limit-wait/tmux-detector.js.map +1 -1
- package/dist/hooks/__tests__/bridge-routing.test.js +156 -0
- package/dist/hooks/__tests__/bridge-routing.test.js.map +1 -1
- package/dist/hooks/auto-slash-command/constants.d.ts.map +1 -1
- package/dist/hooks/auto-slash-command/constants.js +1 -0
- package/dist/hooks/auto-slash-command/constants.js.map +1 -1
- package/dist/hooks/auto-slash-command/executor.d.ts.map +1 -1
- package/dist/hooks/auto-slash-command/executor.js +29 -0
- package/dist/hooks/auto-slash-command/executor.js.map +1 -1
- package/dist/hooks/bridge.d.ts.map +1 -1
- package/dist/hooks/bridge.js +184 -1
- package/dist/hooks/bridge.js.map +1 -1
- package/dist/hooks/learner/bridge.d.ts.map +1 -1
- package/dist/hooks/learner/bridge.js +4 -109
- package/dist/hooks/learner/bridge.js.map +1 -1
- package/dist/hooks/learner/detector.js +1 -1
- package/dist/hooks/learner/parser.d.ts +9 -0
- package/dist/hooks/learner/parser.d.ts.map +1 -1
- package/dist/hooks/learner/parser.js +18 -5
- package/dist/hooks/learner/parser.js.map +1 -1
- package/dist/hooks/learner/types.d.ts +6 -0
- package/dist/hooks/learner/types.d.ts.map +1 -1
- package/dist/hooks/mode-registry/__tests__/session-isolation.test.js +16 -0
- package/dist/hooks/mode-registry/__tests__/session-isolation.test.js.map +1 -1
- package/dist/hooks/notepad/index.d.ts +4 -1
- package/dist/hooks/notepad/index.d.ts.map +1 -1
- package/dist/hooks/notepad/index.js +7 -4
- package/dist/hooks/notepad/index.js.map +1 -1
- package/dist/hooks/persistent-mode/__tests__/ralph-verification-flow.test.js +70 -3
- package/dist/hooks/persistent-mode/__tests__/ralph-verification-flow.test.js.map +1 -1
- package/dist/hooks/persistent-mode/index.d.ts.map +1 -1
- package/dist/hooks/persistent-mode/index.js +17 -13
- package/dist/hooks/persistent-mode/index.js.map +1 -1
- package/dist/hooks/persistent-mode/stop-hook-blocking.test.js +175 -3
- package/dist/hooks/persistent-mode/stop-hook-blocking.test.js.map +1 -1
- package/dist/hooks/project-memory/__tests__/integration.test.js +117 -3
- package/dist/hooks/project-memory/__tests__/integration.test.js.map +1 -1
- package/dist/hooks/project-memory/__tests__/storage.test.js +11 -11
- package/dist/hooks/project-memory/__tests__/storage.test.js.map +1 -1
- package/dist/hooks/project-memory/index.d.ts.map +1 -1
- package/dist/hooks/project-memory/index.js +24 -12
- package/dist/hooks/project-memory/index.js.map +1 -1
- package/dist/hooks/ralph/index.d.ts +1 -1
- package/dist/hooks/ralph/index.d.ts.map +1 -1
- package/dist/hooks/ralph/index.js +1 -1
- package/dist/hooks/ralph/index.js.map +1 -1
- package/dist/hooks/ralph/loop.d.ts +6 -6
- package/dist/hooks/ralph/loop.d.ts.map +1 -1
- package/dist/hooks/ralph/loop.js +18 -18
- package/dist/hooks/ralph/loop.js.map +1 -1
- package/dist/hooks/ralph/prd.d.ts +23 -12
- package/dist/hooks/ralph/prd.d.ts.map +1 -1
- package/dist/hooks/ralph/prd.js +88 -42
- package/dist/hooks/ralph/prd.js.map +1 -1
- package/dist/hooks/session-end/__tests__/mode-state-cleanup.test.js +20 -0
- package/dist/hooks/session-end/__tests__/mode-state-cleanup.test.js.map +1 -1
- package/dist/hooks/session-end/index.d.ts +9 -0
- package/dist/hooks/session-end/index.d.ts.map +1 -1
- package/dist/hooks/session-end/index.js +110 -0
- package/dist/hooks/session-end/index.js.map +1 -1
- package/dist/hooks/skill-bridge.cjs +114 -92
- package/dist/hooks/skill-state/index.d.ts.map +1 -1
- package/dist/hooks/skill-state/index.js +1 -0
- package/dist/hooks/skill-state/index.js.map +1 -1
- package/dist/hud/__tests__/enterprise-cost.test.d.ts +5 -0
- package/dist/hud/__tests__/enterprise-cost.test.d.ts.map +1 -0
- package/dist/hud/__tests__/enterprise-cost.test.js +151 -0
- package/dist/hud/__tests__/enterprise-cost.test.js.map +1 -0
- package/dist/hud/__tests__/git-status.test.js +18 -0
- package/dist/hud/__tests__/git-status.test.js.map +1 -1
- package/dist/hud/__tests__/usage-api-enterprise.test.d.ts +5 -0
- package/dist/hud/__tests__/usage-api-enterprise.test.d.ts.map +1 -0
- package/dist/hud/__tests__/usage-api-enterprise.test.js +249 -0
- package/dist/hud/__tests__/usage-api-enterprise.test.js.map +1 -0
- package/dist/hud/elements/background.d.ts +3 -3
- package/dist/hud/elements/background.d.ts.map +1 -1
- package/dist/hud/elements/background.js +5 -4
- package/dist/hud/elements/background.js.map +1 -1
- package/dist/hud/elements/call-counts.d.ts +2 -2
- package/dist/hud/elements/call-counts.d.ts.map +1 -1
- package/dist/hud/elements/call-counts.js +7 -6
- package/dist/hud/elements/call-counts.js.map +1 -1
- package/dist/hud/elements/context.d.ts +3 -3
- package/dist/hud/elements/context.d.ts.map +1 -1
- package/dist/hud/elements/context.js +5 -4
- package/dist/hud/elements/context.js.map +1 -1
- package/dist/hud/elements/enterprise-cost.d.ts +16 -0
- package/dist/hud/elements/enterprise-cost.d.ts.map +1 -0
- package/dist/hud/elements/enterprise-cost.js +63 -0
- package/dist/hud/elements/enterprise-cost.js.map +1 -0
- package/dist/hud/elements/git.d.ts +2 -1
- package/dist/hud/elements/git.d.ts.map +1 -1
- package/dist/hud/elements/git.js +7 -6
- package/dist/hud/elements/git.js.map +1 -1
- package/dist/hud/elements/permission.d.ts.map +1 -1
- package/dist/hud/elements/permission.js +2 -5
- package/dist/hud/elements/permission.js.map +1 -1
- package/dist/hud/elements/ralph.d.ts +2 -2
- package/dist/hud/elements/ralph.d.ts.map +1 -1
- package/dist/hud/elements/ralph.js +3 -2
- package/dist/hud/elements/ralph.js.map +1 -1
- package/dist/hud/elements/session.d.ts.map +1 -1
- package/dist/hud/elements/session.js +5 -9
- package/dist/hud/elements/session.js.map +1 -1
- package/dist/hud/elements/thinking.d.ts +2 -2
- package/dist/hud/elements/thinking.d.ts.map +1 -1
- package/dist/hud/elements/thinking.js +3 -2
- package/dist/hud/elements/thinking.js.map +1 -1
- package/dist/hud/elements/token-usage.d.ts +2 -2
- package/dist/hud/elements/token-usage.d.ts.map +1 -1
- package/dist/hud/elements/token-usage.js +3 -2
- package/dist/hud/elements/token-usage.js.map +1 -1
- package/dist/hud/index.d.ts.map +1 -1
- package/dist/hud/index.js +5 -1
- package/dist/hud/index.js.map +1 -1
- package/dist/hud/render.d.ts.map +1 -1
- package/dist/hud/render.js +43 -10
- package/dist/hud/render.js.map +1 -1
- package/dist/hud/state.d.ts.map +1 -1
- package/dist/hud/state.js +18 -1
- package/dist/hud/state.js.map +1 -1
- package/dist/hud/stdin.d.ts.map +1 -1
- package/dist/hud/stdin.js +49 -5
- package/dist/hud/stdin.js.map +1 -1
- package/dist/hud/types.d.ts +42 -0
- package/dist/hud/types.d.ts.map +1 -1
- package/dist/hud/types.js +59 -1
- package/dist/hud/types.js.map +1 -1
- package/dist/hud/usage-api.d.ts +19 -1
- package/dist/hud/usage-api.d.ts.map +1 -1
- package/dist/hud/usage-api.js +101 -18
- package/dist/hud/usage-api.js.map +1 -1
- package/dist/installer/__tests__/hud-cache-wrapper.test.d.ts +2 -0
- package/dist/installer/__tests__/hud-cache-wrapper.test.d.ts.map +1 -0
- package/dist/installer/__tests__/hud-cache-wrapper.test.js +235 -0
- package/dist/installer/__tests__/hud-cache-wrapper.test.js.map +1 -0
- package/dist/installer/__tests__/standalone-hook-reconcile.test.js +2 -0
- package/dist/installer/__tests__/standalone-hook-reconcile.test.js.map +1 -1
- package/dist/installer/index.d.ts +1 -0
- package/dist/installer/index.d.ts.map +1 -1
- package/dist/installer/index.js +83 -31
- package/dist/installer/index.js.map +1 -1
- package/dist/lib/__tests__/worktree-paths.test.js +162 -39
- package/dist/lib/__tests__/worktree-paths.test.js.map +1 -1
- package/dist/lib/worktree-paths.d.ts +87 -9
- package/dist/lib/worktree-paths.d.ts.map +1 -1
- package/dist/lib/worktree-paths.js +209 -27
- package/dist/lib/worktree-paths.js.map +1 -1
- package/dist/mcp/__tests__/team-server-artifact-convergence.test.js +156 -4
- package/dist/mcp/__tests__/team-server-artifact-convergence.test.js.map +1 -1
- package/dist/mcp/omc-tools-server.d.ts +11 -17
- package/dist/mcp/omc-tools-server.d.ts.map +1 -1
- package/dist/mcp/omc-tools-server.js +22 -32
- package/dist/mcp/omc-tools-server.js.map +1 -1
- package/dist/mcp/team-job-convergence.d.ts +9 -2
- package/dist/mcp/team-job-convergence.d.ts.map +1 -1
- package/dist/mcp/team-job-convergence.js +35 -14
- package/dist/mcp/team-job-convergence.js.map +1 -1
- package/dist/mcp/team-server.d.ts.map +1 -1
- package/dist/mcp/team-server.js +93 -13
- package/dist/mcp/team-server.js.map +1 -1
- package/dist/ralphthon/prd.d.ts.map +1 -1
- package/dist/ralphthon/prd.js +13 -17
- package/dist/ralphthon/prd.js.map +1 -1
- package/dist/shared/types.d.ts +2 -0
- package/dist/shared/types.d.ts.map +1 -1
- package/dist/team/__tests__/api-interop.cleanup.test.d.ts +2 -0
- package/dist/team/__tests__/api-interop.cleanup.test.d.ts.map +1 -0
- package/dist/team/__tests__/api-interop.cleanup.test.js +234 -0
- package/dist/team/__tests__/api-interop.cleanup.test.js.map +1 -0
- package/dist/team/__tests__/api-interop.dispatch.test.js +2 -1
- package/dist/team/__tests__/api-interop.dispatch.test.js.map +1 -1
- package/dist/team/__tests__/auto-merge-restart.test.d.ts +2 -0
- package/dist/team/__tests__/auto-merge-restart.test.d.ts.map +1 -0
- package/dist/team/__tests__/auto-merge-restart.test.js +128 -0
- package/dist/team/__tests__/auto-merge-restart.test.js.map +1 -0
- package/dist/team/__tests__/auto-merge.perf.test.d.ts +2 -0
- package/dist/team/__tests__/auto-merge.perf.test.d.ts.map +1 -0
- package/dist/team/__tests__/auto-merge.perf.test.js +85 -0
- package/dist/team/__tests__/auto-merge.perf.test.js.map +1 -0
- package/dist/team/__tests__/conflict-mailbox.test.d.ts +2 -0
- package/dist/team/__tests__/conflict-mailbox.test.d.ts.map +1 -0
- package/dist/team/__tests__/conflict-mailbox.test.js +238 -0
- package/dist/team/__tests__/conflict-mailbox.test.js.map +1 -0
- package/dist/team/__tests__/git-worktree.test.js +164 -3
- package/dist/team/__tests__/git-worktree.test.js.map +1 -1
- package/dist/team/__tests__/helpers/git-fixture.d.ts +72 -0
- package/dist/team/__tests__/helpers/git-fixture.d.ts.map +1 -0
- package/dist/team/__tests__/helpers/git-fixture.js +252 -0
- package/dist/team/__tests__/helpers/git-fixture.js.map +1 -0
- package/dist/team/__tests__/leader-inbox.test.d.ts +2 -0
- package/dist/team/__tests__/leader-inbox.test.d.ts.map +1 -0
- package/dist/team/__tests__/leader-inbox.test.js +152 -0
- package/dist/team/__tests__/leader-inbox.test.js.map +1 -0
- package/dist/team/__tests__/merge-orchestrator.test.d.ts +2 -0
- package/dist/team/__tests__/merge-orchestrator.test.d.ts.map +1 -0
- package/dist/team/__tests__/merge-orchestrator.test.js +779 -0
- package/dist/team/__tests__/merge-orchestrator.test.js.map +1 -0
- package/dist/team/__tests__/model-contract.test.js +35 -21
- package/dist/team/__tests__/model-contract.test.js.map +1 -1
- package/dist/team/__tests__/rebase-smoke.test.d.ts +2 -0
- package/dist/team/__tests__/rebase-smoke.test.d.ts.map +1 -0
- package/dist/team/__tests__/rebase-smoke.test.js +272 -0
- package/dist/team/__tests__/rebase-smoke.test.js.map +1 -0
- package/dist/team/__tests__/runtime-cli.test.js +11 -3
- package/dist/team/__tests__/runtime-cli.test.js.map +1 -1
- package/dist/team/__tests__/runtime-prompt-mode.test.js +14 -16
- package/dist/team/__tests__/runtime-prompt-mode.test.js.map +1 -1
- package/dist/team/__tests__/runtime-v2-role-routing.test.js +7 -1
- package/dist/team/__tests__/runtime-v2-role-routing.test.js.map +1 -1
- package/dist/team/__tests__/runtime-v2.dispatch.test.js +293 -15
- package/dist/team/__tests__/runtime-v2.dispatch.test.js.map +1 -1
- package/dist/team/__tests__/runtime-v2.monitor.test.d.ts +2 -0
- package/dist/team/__tests__/runtime-v2.monitor.test.d.ts.map +1 -0
- package/dist/team/__tests__/runtime-v2.monitor.test.js +219 -0
- package/dist/team/__tests__/runtime-v2.monitor.test.js.map +1 -0
- package/dist/team/__tests__/runtime-v2.shutdown.test.d.ts +2 -0
- package/dist/team/__tests__/runtime-v2.shutdown.test.d.ts.map +1 -0
- package/dist/team/__tests__/runtime-v2.shutdown.test.js +292 -0
- package/dist/team/__tests__/runtime-v2.shutdown.test.js.map +1 -0
- package/dist/team/__tests__/scaling-launch-config.test.js +203 -3
- package/dist/team/__tests__/scaling-launch-config.test.js.map +1 -1
- package/dist/team/__tests__/team-summary-worktree.test.d.ts +2 -0
- package/dist/team/__tests__/team-summary-worktree.test.d.ts.map +1 -0
- package/dist/team/__tests__/team-summary-worktree.test.js +85 -0
- package/dist/team/__tests__/team-summary-worktree.test.js.map +1 -0
- package/dist/team/__tests__/teardown-invariant.test.d.ts +2 -0
- package/dist/team/__tests__/teardown-invariant.test.d.ts.map +1 -0
- package/dist/team/__tests__/teardown-invariant.test.js +176 -0
- package/dist/team/__tests__/teardown-invariant.test.js.map +1 -0
- package/dist/team/__tests__/tmux-session-liveness.test.d.ts +2 -0
- package/dist/team/__tests__/tmux-session-liveness.test.d.ts.map +1 -0
- package/dist/team/__tests__/tmux-session-liveness.test.js +37 -0
- package/dist/team/__tests__/tmux-session-liveness.test.js.map +1 -0
- package/dist/team/__tests__/worker-bootstrap.test.js +47 -1
- package/dist/team/__tests__/worker-bootstrap.test.js.map +1 -1
- package/dist/team/__tests__/worker-commit-cadence.test.d.ts +2 -0
- package/dist/team/__tests__/worker-commit-cadence.test.d.ts.map +1 -0
- package/dist/team/__tests__/worker-commit-cadence.test.js +315 -0
- package/dist/team/__tests__/worker-commit-cadence.test.js.map +1 -0
- package/dist/team/__tests__/worktree-contract-fields.test.d.ts +2 -0
- package/dist/team/__tests__/worktree-contract-fields.test.d.ts.map +1 -0
- package/dist/team/__tests__/worktree-contract-fields.test.js +157 -0
- package/dist/team/__tests__/worktree-contract-fields.test.js.map +1 -0
- package/dist/team/__tests__/worktree-runtime-e2e.test.d.ts +2 -0
- package/dist/team/__tests__/worktree-runtime-e2e.test.d.ts.map +1 -0
- package/dist/team/__tests__/worktree-runtime-e2e.test.js +182 -0
- package/dist/team/__tests__/worktree-runtime-e2e.test.js.map +1 -0
- package/dist/team/api-interop.d.ts +2 -1
- package/dist/team/api-interop.d.ts.map +1 -1
- package/dist/team/api-interop.js +121 -14
- package/dist/team/api-interop.js.map +1 -1
- package/dist/team/capabilities.d.ts.map +1 -1
- package/dist/team/capabilities.js +2 -0
- package/dist/team/capabilities.js.map +1 -1
- package/dist/team/cli-worker-contract.d.ts +7 -6
- package/dist/team/cli-worker-contract.d.ts.map +1 -1
- package/dist/team/cli-worker-contract.js +7 -6
- package/dist/team/cli-worker-contract.js.map +1 -1
- package/dist/team/conflict-mailbox.d.ts +49 -0
- package/dist/team/conflict-mailbox.d.ts.map +1 -0
- package/dist/team/conflict-mailbox.js +98 -0
- package/dist/team/conflict-mailbox.js.map +1 -0
- package/dist/team/events.d.ts +3 -0
- package/dist/team/events.d.ts.map +1 -1
- package/dist/team/events.js +2 -1
- package/dist/team/events.js.map +1 -1
- package/dist/team/git-worktree.d.ts +78 -10
- package/dist/team/git-worktree.d.ts.map +1 -1
- package/dist/team/git-worktree.js +453 -97
- package/dist/team/git-worktree.js.map +1 -1
- package/dist/team/governance.d.ts +3 -2
- package/dist/team/governance.d.ts.map +1 -1
- package/dist/team/governance.js.map +1 -1
- package/dist/team/leader-inbox.d.ts +28 -0
- package/dist/team/leader-inbox.d.ts.map +1 -0
- package/dist/team/leader-inbox.js +68 -0
- package/dist/team/leader-inbox.js.map +1 -0
- package/dist/team/merge-coordinator.d.ts +6 -0
- package/dist/team/merge-coordinator.d.ts.map +1 -1
- package/dist/team/merge-coordinator.js +6 -2
- package/dist/team/merge-coordinator.js.map +1 -1
- package/dist/team/merge-orchestrator.d.ts +41 -0
- package/dist/team/merge-orchestrator.d.ts.map +1 -0
- package/dist/team/merge-orchestrator.js +736 -0
- package/dist/team/merge-orchestrator.js.map +1 -0
- package/dist/team/model-contract.d.ts +18 -2
- package/dist/team/model-contract.d.ts.map +1 -1
- package/dist/team/model-contract.js +55 -28
- package/dist/team/model-contract.js.map +1 -1
- package/dist/team/monitor.d.ts.map +1 -1
- package/dist/team/monitor.js +47 -3
- package/dist/team/monitor.js.map +1 -1
- package/dist/team/runtime-cli.d.ts +1 -0
- package/dist/team/runtime-cli.d.ts.map +1 -1
- package/dist/team/runtime-cli.js +15 -2
- package/dist/team/runtime-cli.js.map +1 -1
- package/dist/team/runtime-flags.d.ts +5 -0
- package/dist/team/runtime-flags.d.ts.map +1 -0
- package/dist/team/runtime-flags.js +12 -0
- package/dist/team/runtime-flags.js.map +1 -0
- package/dist/team/runtime-v2.d.ts +16 -1
- package/dist/team/runtime-v2.d.ts.map +1 -1
- package/dist/team/runtime-v2.js +531 -127
- package/dist/team/runtime-v2.js.map +1 -1
- package/dist/team/runtime.d.ts.map +1 -1
- package/dist/team/runtime.js +4 -1
- package/dist/team/runtime.js.map +1 -1
- package/dist/team/scaling.d.ts.map +1 -1
- package/dist/team/scaling.js +110 -13
- package/dist/team/scaling.js.map +1 -1
- package/dist/team/state/tasks.d.ts.map +1 -1
- package/dist/team/state/tasks.js +1 -0
- package/dist/team/state/tasks.js.map +1 -1
- package/dist/team/team-ops.d.ts.map +1 -1
- package/dist/team/team-ops.js +112 -16
- package/dist/team/team-ops.js.map +1 -1
- package/dist/team/tmux-session.d.ts +17 -29
- package/dist/team/tmux-session.d.ts.map +1 -1
- package/dist/team/tmux-session.js +117 -108
- package/dist/team/tmux-session.js.map +1 -1
- package/dist/team/types.d.ts +31 -17
- package/dist/team/types.d.ts.map +1 -1
- package/dist/team/types.js.map +1 -1
- package/dist/team/worker-bootstrap.d.ts +11 -0
- package/dist/team/worker-bootstrap.d.ts.map +1 -1
- package/dist/team/worker-bootstrap.js +37 -14
- package/dist/team/worker-bootstrap.js.map +1 -1
- package/dist/team/worker-canonicalization.d.ts.map +1 -1
- package/dist/team/worker-canonicalization.js +2 -0
- package/dist/team/worker-canonicalization.js.map +1 -1
- package/dist/team/worker-commit-cadence.d.ts +70 -0
- package/dist/team/worker-commit-cadence.d.ts.map +1 -0
- package/dist/team/worker-commit-cadence.js +271 -0
- package/dist/team/worker-commit-cadence.js.map +1 -0
- package/dist/tools/__tests__/memory-tools.test.js +4 -4
- package/dist/tools/__tests__/memory-tools.test.js.map +1 -1
- package/dist/tools/__tests__/state-tools.test.js +13 -1
- package/dist/tools/__tests__/state-tools.test.js.map +1 -1
- package/dist/utils/frontmatter.d.ts.map +1 -1
- package/dist/utils/frontmatter.js +1 -16
- package/dist/utils/frontmatter.js.map +1 -1
- package/dist/utils/resolve-node.d.ts.map +1 -1
- package/dist/utils/resolve-node.js +22 -28
- package/dist/utils/resolve-node.js.map +1 -1
- package/docs/GETTING-STARTED.md +415 -0
- package/docs/MIGRATION.md +1003 -0
- package/docs/REFERENCE.md +21 -4
- package/docs/TEAM-WORKTREE-MODE.md +86 -0
- package/docs/company-context-interface.md +5 -16
- package/docs/copilot-instructions.md +1 -1
- package/package.json +1 -1
- package/scripts/keyword-detector.mjs +168 -20
- package/scripts/lib/hud-cache-wrapper.sh +122 -0
- package/scripts/persistent-mode.cjs +28 -2
- package/scripts/persistent-mode.mjs +28 -2
- package/scripts/plugin-setup.mjs +10 -1
- package/scripts/post-tool-verifier.mjs +153 -3
- package/scripts/pre-tool-enforcer.mjs +54 -6
- package/scripts/session-start.mjs +194 -2
- package/skills/AGENTS.md +22 -91
- package/skills/ai-slop-cleaner/SKILL.md +118 -120
- package/skills/ask/SKILL.md +6 -8
- package/skills/autopilot/SKILL.md +1 -28
- package/skills/autoresearch/SKILL.md +5 -5
- package/skills/cancel/SKILL.md +13 -13
- package/skills/cccg/SKILL.md +1 -0
- package/skills/configure-notifications/SKILL.md +80 -215
- package/skills/debug/SKILL.md +3 -2
- package/skills/deep-dive/SKILL.md +20 -9
- package/skills/deep-interview/SKILL.md +32 -4
- package/skills/deepinit/SKILL.md +1 -0
- package/skills/external-context/SKILL.md +2 -1
- package/skills/hud/SKILL.md +22 -52
- package/skills/learner/SKILL.md +90 -57
- package/skills/mcp-setup/SKILL.md +45 -60
- package/skills/omc-doctor/SKILL.md +1 -1
- package/skills/omc-reference/SKILL.md +6 -6
- package/skills/omc-setup/SKILL.md +30 -74
- package/skills/omc-setup/phases/01-install-claude-md.md +97 -0
- package/skills/omc-setup/phases/02-configure.md +25 -40
- package/skills/omc-setup/phases/03-integrations.md +100 -69
- package/skills/omc-setup/phases/04-welcome.md +102 -44
- package/skills/omc-teams/SKILL.md +63 -26
- package/skills/plan/SKILL.md +11 -9
- package/skills/ralph/SKILL.md +42 -41
- package/skills/ralplan/SKILL.md +3 -10
- package/skills/release/SKILL.md +168 -57
- package/skills/remember/SKILL.md +2 -1
- package/skills/sciomc/SKILL.md +12 -11
- package/skills/self-improve/SKILL.md +4 -4
- package/skills/setup/SKILL.md +1 -0
- package/skills/skill/SKILL.md +21 -20
- package/skills/skillify/SKILL.md +34 -3
- package/skills/team/SKILL.md +62 -44
- package/skills/ultraqa/SKILL.md +1 -2
- package/skills/ultrawork/SKILL.md +28 -21
- package/skills/verify/SKILL.md +2 -1
- package/skills/writer-memory/SKILL.md +2 -1
- package/templates/hooks/keyword-detector.mjs +129 -11
- package/templates/hooks/persistent-mode.mjs +28 -2
- package/templates/hooks/pre-tool-use.mjs +144 -45
- package/templates/hooks/session-start.mjs +25 -1
package/docs/REFERENCE.md
CHANGED
|
@@ -12,7 +12,7 @@ Complete reference for oh-my-copilot. For quick start, see the main [README.md](
|
|
|
12
12
|
- [CLI Commands: ask/team/session](#cli-commands-askteamsession)
|
|
13
13
|
- [Legacy MCP Team Runtime Tools (Deprecated)](#legacy-mcp-team-runtime-tools-deprecated)
|
|
14
14
|
- [Agents (29 Total)](#agents-29-total)
|
|
15
|
-
- [Skills (
|
|
15
|
+
- [Skills (36 Total)](#skills-36-total)
|
|
16
16
|
- [Slash Commands](#slash-commands)
|
|
17
17
|
- [Hooks System](#hooks-system)
|
|
18
18
|
- [Magic Keywords](#magic-keywords)
|
|
@@ -520,9 +520,9 @@ Always use `oh-my-copilot:` prefix when calling via Task tool.
|
|
|
520
520
|
|
|
521
521
|
---
|
|
522
522
|
|
|
523
|
-
## Skills (
|
|
523
|
+
## Skills (36 Total)
|
|
524
524
|
|
|
525
|
-
Includes **34 canonical skills +
|
|
525
|
+
Includes **34 canonical skills + 2 deprecated aliases** (`learner`, `psm`). Runtime truth comes from the builtin skill loader scanning `skills/*/SKILL.md` and expanding aliases declared in frontmatter.
|
|
526
526
|
|
|
527
527
|
| Skill | Description | Manual Command |
|
|
528
528
|
| ------------------------- | ---------------------------------------------------------------- | ------------------------------------------- |
|
|
@@ -900,12 +900,29 @@ Configure HUD elements in `~/.claude/settings.json`:
|
|
|
900
900
|
| `autopilot` | Show autopilot status | `true` |
|
|
901
901
|
| `showTokens` | Show transcript-derived token usage (`tok:i1.2k/o340`, plus `r...` reasoning and `s...` session total when reliable) | `false` |
|
|
902
902
|
|
|
903
|
-
Additional `omcHud` layout options (top-level):
|
|
903
|
+
Additional `omcHud` layout and label options (top-level):
|
|
904
904
|
|
|
905
905
|
| Option | Description | Default |
|
|
906
906
|
| ---------- | --------------------------------------------------------------------------------- | ---------- |
|
|
907
907
|
| `maxWidth` | Maximum HUD line width (terminal columns) | unset |
|
|
908
908
|
| `wrapMode` | `truncate` (ellipsis) or `wrap` (break at `\|` boundaries) when `maxWidth` is set | `truncate` |
|
|
909
|
+
| `locale` | HUD label preset. Supported values: `en`, `zh-CN` | `en` |
|
|
910
|
+
| `labels` | Per-label HUD text overrides; supported keys only | unset |
|
|
911
|
+
|
|
912
|
+
`locale` and `labels` affect only HUD labels. English remains the default, unsupported locale values and unknown label keys are ignored, and explicit `labels` override the locale preset. Supported label keys are `context`, `tokens`, `tool`, `agent`, `skill`, `ralph`, `background`, `thinking`, `staged`, `modified`, `untracked`, `ahead`, and `behind`.
|
|
913
|
+
|
|
914
|
+
Example:
|
|
915
|
+
|
|
916
|
+
```json
|
|
917
|
+
{
|
|
918
|
+
"omcHud": {
|
|
919
|
+
"locale": "zh-CN",
|
|
920
|
+
"labels": {
|
|
921
|
+
"context": "CTX"
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
```
|
|
909
926
|
|
|
910
927
|
Available presets: `minimal`, `focused`, `full`, `dense`, `analytics`, `opencode`
|
|
911
928
|
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# Native Team Worktree Mode
|
|
2
|
+
|
|
3
|
+
Native team worktree mode is the opt-in rollout path for running `omc team` workers in dedicated git worktrees while keeping one leader-owned team-specific coordination root. It is intended for runtime-v2 team sessions and is designed to make worker edits isolated without fragmenting task, mailbox, status, or manifest state.
|
|
4
|
+
|
|
5
|
+
## Availability
|
|
6
|
+
|
|
7
|
+
- The rollout is **opt-in / config-gated** for the first slice. Do not assume worktree mode is the default behavior.
|
|
8
|
+
- The target runtime is `runtime-v2`. Legacy `runtime.ts` remains limited to read/status and cleanup compatibility unless a later plan explicitly expands it.
|
|
9
|
+
- No new dependency is required; lifecycle operations use git worktrees plus the existing team CLI/API surfaces.
|
|
10
|
+
|
|
11
|
+
## Workspace contract
|
|
12
|
+
|
|
13
|
+
When worktree mode is active, OMC uses this stable layout:
|
|
14
|
+
|
|
15
|
+
| Field | Contract |
|
|
16
|
+
| --- | --- |
|
|
17
|
+
| Worktree root | `<repo>/.omc/team/<team-name>/worktrees/<worker-name>` |
|
|
18
|
+
| Team-specific coordination root | `<repo>/.omc/state/team/<team-name>` in the leader workspace |
|
|
19
|
+
| Worker cwd | The worker's `worktree_path` |
|
|
20
|
+
| Worker coordination | `OMC_TEAM_STATE_ROOT` points back to the team-specific leader-owned coordination root |
|
|
21
|
+
| Worker instructions | Worktree-root `AGENTS.md` is installed with backup/restore safeguards |
|
|
22
|
+
|
|
23
|
+
Workers must keep using `omc team api ...` lifecycle and mailbox operations against the team-specific coordination root. They must not create or mutate a separate local `.omc/state` inside their worker worktree when `OMC_TEAM_STATE_ROOT` is available; for worktree-backed workers it should point at `<repo>/.omc/state/team/<team-name>`.
|
|
24
|
+
|
|
25
|
+
## Persisted fields
|
|
26
|
+
|
|
27
|
+
Config, manifest, worker identity, and status surfaces should expose the same locked field set so resume/status/bootstrap paths can reason about worker location without inference:
|
|
28
|
+
|
|
29
|
+
- `workspace_mode`
|
|
30
|
+
- `worktree_mode`
|
|
31
|
+
- `team_state_root`
|
|
32
|
+
- `working_dir`
|
|
33
|
+
- `worktree_repo_root`
|
|
34
|
+
- `worktree_path`
|
|
35
|
+
- `worktree_branch`
|
|
36
|
+
- `worktree_detached`
|
|
37
|
+
- `worktree_created`
|
|
38
|
+
|
|
39
|
+
`workspace_mode` should be `worktree` for worktree-backed sessions and `single` for the existing shared-workspace behavior. `team_state_root` means the team-specific coordination root (`<repo>/.omc/state/team/<team-name>`); if a future feature needs the broader `.omc/state` base, use a separately named field such as `state_base_root`.
|
|
40
|
+
|
|
41
|
+
## Safety rules
|
|
42
|
+
|
|
43
|
+
- OMC must check the leader workspace before provisioning worktrees. If the leader repo is dirty, startup should refuse worktree provisioning rather than copying an unsafe base state.
|
|
44
|
+
- Existing compatible clean worker worktrees may be reused.
|
|
45
|
+
- Dirty worker worktrees must be preserved and surfaced as warnings/events. Cleanup must not force-remove dirty worker edits.
|
|
46
|
+
- Branch/path mismatches should fail instead of reusing the wrong workspace.
|
|
47
|
+
- Rollback may remove newly created clean worktrees and runtime-created branches when safe; reused worktrees are preserved.
|
|
48
|
+
- `orphan-cleanup` is a destructive escape hatch that may delete worktree recovery metadata and root `AGENTS.md` backups. When that evidence exists, callers must pass `acknowledge_lost_worktree_recovery: true` only after manually preserving or intentionally discarding the affected worker worktrees/backups.
|
|
49
|
+
|
|
50
|
+
## CLI and status expectations
|
|
51
|
+
|
|
52
|
+
`omc team status <team-name> --json` should make the workspace contract observable. JSON consumers should be able to find `workspace_mode`, `worktree_mode`, `team_state_root`, and each worker's worktree metadata without reading private files directly.
|
|
53
|
+
|
|
54
|
+
Human status output should also surface the mode and worktree path/branch details enough for users to understand where worker changes live and whether cleanup preserved a dirty worktree.
|
|
55
|
+
|
|
56
|
+
## Verification checklist for changes
|
|
57
|
+
|
|
58
|
+
Use the source PRD/test-spec checklist when modifying this area. At minimum, changes should cover:
|
|
59
|
+
|
|
60
|
+
1. Worktree planning disabled/no-op and active path modes.
|
|
61
|
+
2. Fresh, reused, dirty, and mismatched worktree lifecycle cases.
|
|
62
|
+
3. Runtime-v2 startup/spawn state: worker cwd, env, config, manifest, and identity all agree.
|
|
63
|
+
4. Bootstrap prompts and trigger paths use `$OMC_TEAM_STATE_ROOT` for worktree-backed workers.
|
|
64
|
+
5. Scale-up workers inherit the same team-specific coordination root and worktree instruction strategy.
|
|
65
|
+
6. Shutdown/cleanup removes safe clean worktrees, preserves dirty ones, and reports warnings.
|
|
66
|
+
7. CLI help/status tests cover the opt-in rollout and locked status field set.
|
|
67
|
+
|
|
68
|
+
Recommended focused commands:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
npm test -- --run src/team/__tests__/git-worktree.test.ts
|
|
72
|
+
npm test -- --run src/team/__tests__/worker-bootstrap.test.ts
|
|
73
|
+
npm test -- --run src/team/__tests__/runtime-v2.dispatch.test.ts
|
|
74
|
+
npm test -- --run src/team/__tests__/runtime-v2.shutdown.test.ts
|
|
75
|
+
npm test -- --run src/team/__tests__/api-interop.dispatch.test.ts
|
|
76
|
+
npm test -- --run src/team/__tests__/api-interop.cwd-resolution.test.ts
|
|
77
|
+
npm test -- --run src/team/__tests__/scaling-launch-config.test.ts
|
|
78
|
+
npm test -- --run src/cli/__tests__/team-runtime-boundary.test.ts
|
|
79
|
+
npm run build
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Review notes
|
|
83
|
+
|
|
84
|
+
- Keep the first slice narrow: runtime-v2 startup/spawn/dispatch/scale-up/resume/status/shutdown/cleanup plus legacy read/cleanup compatibility.
|
|
85
|
+
- Do not reduce scope by omitting status visibility, dirty-worktree preservation, or team-specific coordination-root behavior; those are part of the locked contract.
|
|
86
|
+
- Prefer explicit persisted fields over reconstructing worktree state from paths or branch names.
|
|
@@ -2,12 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
OMC supports a narrow, prompt-level contract for vendor-owned company context.
|
|
4
4
|
|
|
5
|
-
This contract is aimed at a specific failure mode from upstream issue #2692:
|
|
6
|
-
purely prompt-directive company-context guidance is still missed in practice
|
|
7
|
-
roughly 5% of the time. Making the lookup an explicit configured tool call
|
|
8
|
-
materially reduces that miss mode at the spec layer without changing OMC
|
|
9
|
-
runtime behavior.
|
|
10
|
-
|
|
11
5
|
This is **not** a runtime enforcement feature. It gives OMC workflows:
|
|
12
6
|
|
|
13
7
|
- a consistent tool shape,
|
|
@@ -52,8 +46,8 @@ OMC skill clauses should treat the returned markdown the same way `deep-dive` tr
|
|
|
52
46
|
|
|
53
47
|
Configure the contract in the standard OMC config surface:
|
|
54
48
|
|
|
55
|
-
- Project: `.
|
|
56
|
-
- User: `~/.config/
|
|
49
|
+
- Project: `.claude/omc.jsonc`
|
|
50
|
+
- User: `~/.config/claude-omc/config.jsonc`
|
|
57
51
|
|
|
58
52
|
Project config overrides user config.
|
|
59
53
|
|
|
@@ -98,23 +92,18 @@ Each skill should build a `query` that summarizes the current task, current stag
|
|
|
98
92
|
|
|
99
93
|
The company-context server itself is still registered through the normal MCP surfaces:
|
|
100
94
|
|
|
101
|
-
-
|
|
95
|
+
- Claude MCP configuration / `claude mcp add ...`
|
|
102
96
|
- the unified MCP registry that OMC syncs to Codex
|
|
103
97
|
|
|
104
98
|
This contract does not change how MCP servers are registered.
|
|
105
99
|
|
|
106
100
|
For a tiny runnable reference implementation, see:
|
|
107
101
|
|
|
108
|
-
- [`examples/vendor-mcp-server/README.md`](
|
|
102
|
+
- [`examples/vendor-mcp-server/README.md`](/mnt/offloading/Workspace/oh-my-claudecode.omx-worktrees/issue-2692-company-context-mcp-interface/examples/vendor-mcp-server/README.md)
|
|
109
103
|
|
|
110
104
|
## Residual Risk
|
|
111
105
|
|
|
112
|
-
This interface
|
|
113
|
-
the company-context lookup explicit, but it still operates at the skill-prompt
|
|
114
|
-
layer. The documented MUST-call clauses should meaningfully reduce that miss
|
|
115
|
-
rate, yet they do **not** guarantee a 0% miss rate or mathematically perfect
|
|
116
|
-
invocation. If you need deterministic invocation, that would require a separate
|
|
117
|
-
runtime enforcement design.
|
|
106
|
+
This interface makes the contract explicit and lowers prompt drift, but it still operates at the skill-prompt layer. If you need guaranteed invocation, that would require a separate runtime enforcement design.
|
|
118
107
|
|
|
119
108
|
## Non-Goals
|
|
120
109
|
|
package/package.json
CHANGED
|
@@ -28,6 +28,7 @@ import { join, dirname } from 'path';
|
|
|
28
28
|
import { homedir } from 'os';
|
|
29
29
|
import { fileURLToPath } from 'url';
|
|
30
30
|
import { getClaudeConfigDir } from './lib/config-dir.mjs';
|
|
31
|
+
import { atomicWriteFileSync } from './lib/atomic-write.mjs';
|
|
31
32
|
import { readStdin } from './lib/stdin.mjs';
|
|
32
33
|
|
|
33
34
|
// Resolve OMC package root: PLUGIN_ROOT (plugin system) or derive from this script's location
|
|
@@ -359,6 +360,119 @@ const QUESTION_FOLLOWUP_PATTERNS = [
|
|
|
359
360
|
/\b(?:how\s+many|how\s+much|why|what\s+happened|what\s+went\s+wrong|token\s+budget|cost|pricing)\b/i,
|
|
360
361
|
/(?:왜|얼마|몇\s*번|몇번|토큰|가격|비용|질문)/u,
|
|
361
362
|
];
|
|
363
|
+
|
|
364
|
+
// Patterns that identify system-generated echoes (hook outputs) which can be
|
|
365
|
+
// pasted back into the prompt verbatim. If a mode keyword only appears inside
|
|
366
|
+
// such an echo block we MUST NOT re-activate the mode: otherwise a user who
|
|
367
|
+
// copies a "[RALPH LOOP - ITERATION N] ..." block into a new session to debug
|
|
368
|
+
// it will unintentionally re-trigger ralph, and the pasted text ends up as
|
|
369
|
+
// the new state.prompt — producing a recursive self-reinforcing loop.
|
|
370
|
+
// Continuation lines that hook output typically emits DIRECTLY after a
|
|
371
|
+
// recognized block header. They must be stripped only in that context —
|
|
372
|
+
// never standalone — because a user might legitimately start a prompt with
|
|
373
|
+
// "Task: …" or similar (Codex automated review P1/P2 on #2795).
|
|
374
|
+
const ECHO_CONTINUATION = '(?:\\r?\\n[ \\t]*(?:Task:\\s|When FULLY complete \\(after Architect verification\\)|run\\s+\\/oh-my-(?:claudecode|codex|copilot):cancel).*)*';
|
|
375
|
+
|
|
376
|
+
// NOTE: each pattern is a SINGLE LOGICAL BLOCK: the block header line +
|
|
377
|
+
// zero-or-more continuation lines that hooks emit right after it. The whole
|
|
378
|
+
// match is stripped together. Both `i` (case-insensitive against the
|
|
379
|
+
// lower-cased cleanPrompt upstream) and `m` (so `^`/`$` match line
|
|
380
|
+
// boundaries) are required.
|
|
381
|
+
function buildEchoBlockRegex(headerBody) {
|
|
382
|
+
return new RegExp(`^[ \\t]*${headerBody}.*${ECHO_CONTINUATION}$`, 'gim');
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
const SYSTEM_ECHO_BLOCK_PATTERNS = [
|
|
386
|
+
// persistent-mode.mjs block headers
|
|
387
|
+
buildEchoBlockRegex('\\[RALPH LOOP\\s*-\\s*ITERATION[^\\]\\n]*\\]'),
|
|
388
|
+
buildEchoBlockRegex('\\[RALPH LOOP\\s*-\\s*(?:HARD LIMIT|EXTENDED)\\]'),
|
|
389
|
+
buildEchoBlockRegex('\\[TEAM\\s*-\\s*Phase:[^\\]\\n]*\\]'),
|
|
390
|
+
buildEchoBlockRegex('\\[AUTOPILOT[^\\]\\n]*\\]'),
|
|
391
|
+
buildEchoBlockRegex('\\[ULTRAPILOT[^\\]\\n]*\\]'),
|
|
392
|
+
buildEchoBlockRegex('\\[ULTRAWORK[^\\]\\n]*\\]'),
|
|
393
|
+
buildEchoBlockRegex('\\[ULTRAQA[^\\]\\n]*\\]'),
|
|
394
|
+
buildEchoBlockRegex('\\[PIPELINE[^\\]\\n]*\\]'),
|
|
395
|
+
buildEchoBlockRegex('\\[SWARM[^\\]\\n]*\\]'),
|
|
396
|
+
buildEchoBlockRegex('\\[TOOL ERROR[^\\]\\n]*\\]'),
|
|
397
|
+
// keyword-detector.mjs block headers
|
|
398
|
+
buildEchoBlockRegex('\\[MAGIC KEYWORD:[^\\]\\n]*\\]'),
|
|
399
|
+
buildEchoBlockRegex('\\[MAGIC KEYWORDS DETECTED:[^\\]\\n]*\\]'),
|
|
400
|
+
// Stop-hook wrapping by the Claude Code harness
|
|
401
|
+
buildEchoBlockRegex('Stop hook (?:blocking error|feedback|stopped continuation)'),
|
|
402
|
+
buildEchoBlockRegex('PreToolUse:[^\\n]*hook additional context:'),
|
|
403
|
+
buildEchoBlockRegex('PostToolUse:[^\\n]*hook additional context:'),
|
|
404
|
+
];
|
|
405
|
+
|
|
406
|
+
// Signature lines indicating the text is predominantly a system echo. Even
|
|
407
|
+
// when the block patterns above fail to delimit cleanly (e.g. truncation),
|
|
408
|
+
// presence of these sentinels should make us treat the prompt as an echo.
|
|
409
|
+
// All patterns use `i` because hasActionableKeyword sees a lowercased prompt.
|
|
410
|
+
const SYSTEM_ECHO_SIGNATURES = [
|
|
411
|
+
/\bWhen FULLY complete \(after Architect verification\)\b/i,
|
|
412
|
+
/\brun\s+\/oh-my-(?:claudecode|codex|copilot):cancel\b/i,
|
|
413
|
+
/\[RALPH LOOP\s*-\s*ITERATION\b/i,
|
|
414
|
+
];
|
|
415
|
+
|
|
416
|
+
const MAX_STATE_PROMPT_LEN = 500;
|
|
417
|
+
|
|
418
|
+
function stripSystemEchoes(text) {
|
|
419
|
+
if (typeof text !== 'string' || text.length === 0) return '';
|
|
420
|
+
let cleaned = text;
|
|
421
|
+
for (const pattern of SYSTEM_ECHO_BLOCK_PATTERNS) {
|
|
422
|
+
cleaned = cleaned.replace(pattern, ' ');
|
|
423
|
+
}
|
|
424
|
+
return cleaned;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
function looksLikeSystemEcho(text) {
|
|
428
|
+
if (typeof text !== 'string' || text.length === 0) return false;
|
|
429
|
+
if (SYSTEM_ECHO_SIGNATURES.some((pattern) => pattern.test(text))) return true;
|
|
430
|
+
// Also treat the presence of ANY echo block pattern as an echo, so that
|
|
431
|
+
// mode-specific paste blocks (AUTOPILOT, ULTRAWORK, TEAM, etc.) are
|
|
432
|
+
// recognized without needing a dedicated signature line.
|
|
433
|
+
for (const pattern of SYSTEM_ECHO_BLOCK_PATTERNS) {
|
|
434
|
+
const probe = new RegExp(pattern.source, pattern.flags.replace('g', ''));
|
|
435
|
+
if (probe.test(text)) return true;
|
|
436
|
+
}
|
|
437
|
+
return false;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* Sanitize a prompt before persisting it to a *-state.json file.
|
|
442
|
+
* Returning the raw prompt risks storing large system echoes or pasted
|
|
443
|
+
* hook output, which persistent-mode.mjs would then blast back into the
|
|
444
|
+
* next Stop-hook block reason on every iteration.
|
|
445
|
+
*
|
|
446
|
+
* Strategy:
|
|
447
|
+
* 1. Strip echoes first. If non-empty content remains AND that remainder no
|
|
448
|
+
* longer looks like an echo, keep it (preserves the real user request in
|
|
449
|
+
* an "echo + blank line + real request" paste).
|
|
450
|
+
* 2. Otherwise, if the raw prompt looks like a pure echo, substitute the
|
|
451
|
+
* placeholder sentinel.
|
|
452
|
+
* 3. Finally, hard-truncate to MAX_STATE_PROMPT_LEN chars.
|
|
453
|
+
*/
|
|
454
|
+
function sanitizePromptForState(prompt) {
|
|
455
|
+
if (typeof prompt !== 'string') return '';
|
|
456
|
+
const trimmed = prompt.trim();
|
|
457
|
+
if (!trimmed) return '';
|
|
458
|
+
|
|
459
|
+
const stripped = stripSystemEchoes(trimmed).trim();
|
|
460
|
+
if (stripped.length > 0 && !looksLikeSystemEcho(stripped)) {
|
|
461
|
+
return stripped.length > MAX_STATE_PROMPT_LEN
|
|
462
|
+
? `${stripped.slice(0, MAX_STATE_PROMPT_LEN - 3)}...`
|
|
463
|
+
: stripped;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
if (looksLikeSystemEcho(trimmed)) {
|
|
467
|
+
return '(prompt omitted: pasted system echo)';
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
// Fallback (stripping left nothing but original isn't recognizably an echo)
|
|
471
|
+
const base = stripped.length > 0 ? stripped : trimmed;
|
|
472
|
+
return base.length > MAX_STATE_PROMPT_LEN
|
|
473
|
+
? `${base.slice(0, MAX_STATE_PROMPT_LEN - 3)}...`
|
|
474
|
+
: base;
|
|
475
|
+
}
|
|
362
476
|
const MODE_REFERENCE_PATTERN =
|
|
363
477
|
/\b(?:ralph|autopilot|auto[\s-]?pilot|ultrawork|ulw|ralplan|ultrathink|deepsearch|deep[\s-]?analyze|deepanalyze|deep[\s-]interview|ouroboros|ccg|claude-codex-gemini|deerflow)\b/gi;
|
|
364
478
|
|
|
@@ -473,15 +587,25 @@ function isInformationalKeywordContext(text, position, keywordLength, keywordTex
|
|
|
473
587
|
}
|
|
474
588
|
|
|
475
589
|
function hasActionableKeyword(text, pattern) {
|
|
590
|
+
// Strip system-generated echo blocks (persistent-mode/keyword-detector
|
|
591
|
+
// outputs, Stop-hook wrappers) BEFORE searching for keywords. Otherwise
|
|
592
|
+
// pasting a previous "[RALPH LOOP - ITERATION N] ..." block into a prompt
|
|
593
|
+
// would re-activate ralph mode and the echo itself would be saved as
|
|
594
|
+
// state.prompt, which persistent-mode.mjs then blasts back on every
|
|
595
|
+
// iteration — a self-reinforcing loop that is hard to cancel.
|
|
596
|
+
const searchText = looksLikeSystemEcho(text)
|
|
597
|
+
? stripSystemEchoes(text)
|
|
598
|
+
: text;
|
|
599
|
+
|
|
476
600
|
const flags = pattern.flags.includes('g') ? pattern.flags : `${pattern.flags}g`;
|
|
477
601
|
const globalPattern = new RegExp(pattern.source, flags);
|
|
478
602
|
|
|
479
|
-
for (const match of
|
|
603
|
+
for (const match of searchText.matchAll(globalPattern)) {
|
|
480
604
|
if (match.index === undefined) {
|
|
481
605
|
continue;
|
|
482
606
|
}
|
|
483
607
|
|
|
484
|
-
if (isInformationalKeywordContext(
|
|
608
|
+
if (isInformationalKeywordContext(searchText, match.index, match[0].length, match[0])) {
|
|
485
609
|
continue;
|
|
486
610
|
}
|
|
487
611
|
|
|
@@ -508,19 +632,26 @@ function hasExplicitInvocationContext(text, position, keywordLength, keywordText
|
|
|
508
632
|
}
|
|
509
633
|
|
|
510
634
|
function hasActionableRalplanKeyword(text, pattern) {
|
|
635
|
+
// Same echo guard as hasActionableKeyword.
|
|
636
|
+
const searchText = looksLikeSystemEcho(text)
|
|
637
|
+
? stripSystemEchoes(text)
|
|
638
|
+
: text;
|
|
639
|
+
|
|
511
640
|
const flags = pattern.flags.includes('g') ? pattern.flags : `${pattern.flags}g`;
|
|
512
641
|
const globalPattern = new RegExp(pattern.source, flags);
|
|
513
642
|
|
|
514
|
-
for (const match of
|
|
643
|
+
for (const match of searchText.matchAll(globalPattern)) {
|
|
515
644
|
if (match.index === undefined) {
|
|
516
645
|
continue;
|
|
517
646
|
}
|
|
518
647
|
|
|
519
|
-
|
|
648
|
+
// match.index is relative to searchText — use searchText for all
|
|
649
|
+
// downstream context lookups to keep indices aligned.
|
|
650
|
+
if (isInformationalKeywordContext(searchText, match.index, match[0].length, match[0])) {
|
|
520
651
|
continue;
|
|
521
652
|
}
|
|
522
653
|
|
|
523
|
-
if (!hasExplicitInvocationContext(
|
|
654
|
+
if (!hasExplicitInvocationContext(searchText, match.index, match[0].length, match[0])) {
|
|
524
655
|
continue;
|
|
525
656
|
}
|
|
526
657
|
|
|
@@ -532,6 +663,10 @@ function hasActionableRalplanKeyword(text, pattern) {
|
|
|
532
663
|
|
|
533
664
|
// Create state file for a mode
|
|
534
665
|
function activateState(directory, prompt, stateName, sessionId) {
|
|
666
|
+
const now = new Date().toISOString();
|
|
667
|
+
// Sanitize prompt BEFORE writing to state: prevents pasted system echoes
|
|
668
|
+
// and oversized blobs from being persisted and re-emitted by Stop hook.
|
|
669
|
+
const safePrompt = sanitizePromptForState(prompt);
|
|
535
670
|
let state;
|
|
536
671
|
|
|
537
672
|
if (stateName === 'ralph') {
|
|
@@ -540,45 +675,51 @@ function activateState(directory, prompt, stateName, sessionId) {
|
|
|
540
675
|
active: true,
|
|
541
676
|
iteration: 1,
|
|
542
677
|
max_iterations: 100,
|
|
543
|
-
started_at:
|
|
544
|
-
prompt:
|
|
678
|
+
started_at: now,
|
|
679
|
+
prompt: safePrompt,
|
|
545
680
|
session_id: sessionId || undefined,
|
|
546
681
|
project_path: directory,
|
|
547
682
|
linked_ultrawork: true,
|
|
548
683
|
awaiting_confirmation: true,
|
|
549
|
-
|
|
684
|
+
awaiting_confirmation_set_at: now,
|
|
685
|
+
last_checked_at: now
|
|
550
686
|
};
|
|
551
687
|
} else if (stateName === 'ralplan') {
|
|
552
688
|
// Ralplan needs active + session_id for stop-hook enforcement
|
|
553
689
|
state = {
|
|
554
690
|
active: true,
|
|
555
|
-
started_at:
|
|
691
|
+
started_at: now,
|
|
556
692
|
session_id: sessionId || undefined,
|
|
557
693
|
project_path: directory,
|
|
558
694
|
awaiting_confirmation: true,
|
|
559
|
-
|
|
695
|
+
awaiting_confirmation_set_at: now,
|
|
696
|
+
last_checked_at: now
|
|
560
697
|
};
|
|
561
698
|
} else {
|
|
562
699
|
// Generic state for ultrawork, autopilot, etc.
|
|
563
700
|
state = {
|
|
564
701
|
active: true,
|
|
565
|
-
started_at:
|
|
566
|
-
original_prompt:
|
|
702
|
+
started_at: now,
|
|
703
|
+
original_prompt: safePrompt,
|
|
567
704
|
session_id: sessionId || undefined,
|
|
568
705
|
project_path: directory,
|
|
569
706
|
reinforcement_count: 0,
|
|
570
707
|
awaiting_confirmation: true,
|
|
571
|
-
|
|
708
|
+
awaiting_confirmation_set_at: now,
|
|
709
|
+
last_checked_at: now
|
|
572
710
|
};
|
|
573
711
|
}
|
|
574
712
|
|
|
575
|
-
// Write to session-scoped path if sessionId available
|
|
713
|
+
// Write to session-scoped path if sessionId available. Use atomic writes
|
|
714
|
+
// so that concurrent hook processes cannot expose half-written JSON to
|
|
715
|
+
// persistent-mode.mjs's readJsonFile (which would otherwise return null
|
|
716
|
+
// and temporarily drop mode enforcement).
|
|
576
717
|
if (sessionId && /^[a-zA-Z0-9][a-zA-Z0-9_-]{0,255}$/.test(sessionId)) {
|
|
577
718
|
const sessionDir = join(directory, '.omcp', 'state', 'sessions', sessionId);
|
|
578
719
|
if (!existsSync(sessionDir)) {
|
|
579
720
|
try { mkdirSync(sessionDir, { recursive: true }); } catch {}
|
|
580
721
|
}
|
|
581
|
-
try {
|
|
722
|
+
try { atomicWriteFileSync(join(sessionDir, `${stateName}-state.json`), JSON.stringify(state, null, 2)); } catch {}
|
|
582
723
|
return;
|
|
583
724
|
}
|
|
584
725
|
|
|
@@ -587,7 +728,7 @@ function activateState(directory, prompt, stateName, sessionId) {
|
|
|
587
728
|
if (!existsSync(localDir)) {
|
|
588
729
|
try { mkdirSync(localDir, { recursive: true }); } catch {}
|
|
589
730
|
}
|
|
590
|
-
try {
|
|
731
|
+
try { atomicWriteFileSync(join(localDir, `${stateName}-state.json`), JSON.stringify(state, null, 2)); } catch {}
|
|
591
732
|
}
|
|
592
733
|
|
|
593
734
|
function activateRalplanStartupState(directory, prompt, sessionId) {
|
|
@@ -596,7 +737,7 @@ function activateRalplanStartupState(directory, prompt, sessionId) {
|
|
|
596
737
|
active: true,
|
|
597
738
|
started_at: now,
|
|
598
739
|
current_phase: 'ralplan',
|
|
599
|
-
original_prompt: prompt,
|
|
740
|
+
original_prompt: sanitizePromptForState(prompt),
|
|
600
741
|
session_id: sessionId || undefined,
|
|
601
742
|
project_path: directory,
|
|
602
743
|
awaiting_confirmation: true,
|
|
@@ -609,7 +750,7 @@ function activateRalplanStartupState(directory, prompt, sessionId) {
|
|
|
609
750
|
if (!existsSync(sessionDir)) {
|
|
610
751
|
try { mkdirSync(sessionDir, { recursive: true }); } catch {}
|
|
611
752
|
}
|
|
612
|
-
try {
|
|
753
|
+
try { atomicWriteFileSync(join(sessionDir, 'ralplan-state.json'), JSON.stringify(state, null, 2)); } catch {}
|
|
613
754
|
return;
|
|
614
755
|
}
|
|
615
756
|
|
|
@@ -617,7 +758,7 @@ function activateRalplanStartupState(directory, prompt, sessionId) {
|
|
|
617
758
|
if (!existsSync(localDir)) {
|
|
618
759
|
try { mkdirSync(localDir, { recursive: true }); } catch {}
|
|
619
760
|
}
|
|
620
|
-
try {
|
|
761
|
+
try { atomicWriteFileSync(join(localDir, 'ralplan-state.json'), JSON.stringify(state, null, 2)); } catch {}
|
|
621
762
|
}
|
|
622
763
|
|
|
623
764
|
/**
|
|
@@ -858,7 +999,14 @@ async function main() {
|
|
|
858
999
|
return;
|
|
859
1000
|
}
|
|
860
1001
|
|
|
861
|
-
|
|
1002
|
+
// Strip pasted system-echo blocks BEFORE any mode-keyword dispatch runs.
|
|
1003
|
+
// This covers both the hasActionableKeyword() call sites AND alternative
|
|
1004
|
+
// matchers (e.g. isAntiSlopCleanupRequest) that bypass it. The helper
|
|
1005
|
+
// inside hasActionableKeyword also strips defensively, which stays as
|
|
1006
|
+
// belt-and-suspenders.
|
|
1007
|
+
const cleanPrompt = stripSystemEchoes(
|
|
1008
|
+
sanitizeForKeywordDetection(prompt).toLowerCase(),
|
|
1009
|
+
);
|
|
862
1010
|
|
|
863
1011
|
// Collect all matching keywords
|
|
864
1012
|
const matches = [];
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# OMC HUD cached statusLine launcher.
|
|
3
|
+
#
|
|
4
|
+
# Claude Code invokes statusLine commands for every render. Starting Node and
|
|
5
|
+
# importing the HUD bundle each time can take hundreds of milliseconds, which
|
|
6
|
+
# makes the first frame blank/flickery. This POSIX wrapper keeps the statusLine
|
|
7
|
+
# protocol unchanged (stdin JSON in, one line out) while making the hot path a
|
|
8
|
+
# shell read + cat of the last rendered line. A single background Node refresh
|
|
9
|
+
# updates the session-scoped cache for the next frame.
|
|
10
|
+
|
|
11
|
+
case "$0" in
|
|
12
|
+
*/*) SCRIPT_DIR=${0%/*} ;;
|
|
13
|
+
*) SCRIPT_DIR=. ;;
|
|
14
|
+
esac
|
|
15
|
+
SCRIPT_DIR=$(cd "$SCRIPT_DIR" 2>/dev/null && pwd -P) || SCRIPT_DIR=.
|
|
16
|
+
CONFIG_DIR=${COPILOT_CONFIG_DIR:-$(cd "$SCRIPT_DIR/.." 2>/dev/null && pwd -P)}
|
|
17
|
+
CACHE_DIR=${OMC_HUD_CACHE_DIR:-"$CONFIG_DIR/hud/cache"}
|
|
18
|
+
HUD_SCRIPT=${1:-"$SCRIPT_DIR/omcp-hud.mjs"}
|
|
19
|
+
INPUT_TMP="$CACHE_DIR/stdin.$$.tmp"
|
|
20
|
+
|
|
21
|
+
mkdir -p "$CACHE_DIR" 2>/dev/null || {
|
|
22
|
+
printf '[OMC] Starting...\n'
|
|
23
|
+
exit 0
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
# Capture Claude's current statusLine stdin first so rendered output can be
|
|
27
|
+
# scoped per session/worktree instead of leaking across concurrent sessions.
|
|
28
|
+
cat > "$INPUT_TMP" 2>/dev/null || :
|
|
29
|
+
|
|
30
|
+
extract_json_string() {
|
|
31
|
+
key=$1
|
|
32
|
+
sed -n "s/.*\"$key\"[[:space:]]*:[[:space:]]*\"\([^\"]*\)\".*/\1/p" "$INPUT_TMP" 2>/dev/null | head -1
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
SESSION_KEY=$(extract_json_string session_id)
|
|
36
|
+
if [ -z "$SESSION_KEY" ] && [ -n "${CLAUDE_SESSION_ID:-}" ]; then
|
|
37
|
+
SESSION_KEY=$CLAUDE_SESSION_ID
|
|
38
|
+
fi
|
|
39
|
+
if [ -z "$SESSION_KEY" ] && [ -n "${CLAUDECODE_SESSION_ID:-}" ]; then
|
|
40
|
+
SESSION_KEY=$CLAUDECODE_SESSION_ID
|
|
41
|
+
fi
|
|
42
|
+
TRANSCRIPT_PATH=$(extract_json_string transcript_path)
|
|
43
|
+
if [ -z "$SESSION_KEY" ] && [ -n "$TRANSCRIPT_PATH" ]; then
|
|
44
|
+
SESSION_KEY=$(printf '%s\n' "$TRANSCRIPT_PATH" | sed -n 's/.*\([0-9a-fA-F][0-9a-fA-F-]\{35\}\).*/\1/p' | head -1)
|
|
45
|
+
if [ -z "$SESSION_KEY" ]; then
|
|
46
|
+
SESSION_KEY=$(printf '%s\n' "$TRANSCRIPT_PATH" | cksum 2>/dev/null | awk '{print "transcript-" $1}')
|
|
47
|
+
fi
|
|
48
|
+
fi
|
|
49
|
+
if [ -z "$SESSION_KEY" ]; then
|
|
50
|
+
CWD_VALUE=$(extract_json_string cwd)
|
|
51
|
+
if [ -n "$CWD_VALUE" ]; then
|
|
52
|
+
SESSION_KEY=$(printf '%s\n' "$CWD_VALUE" | cksum 2>/dev/null | awk '{print "cwd-" $1}')
|
|
53
|
+
fi
|
|
54
|
+
fi
|
|
55
|
+
if [ -z "$SESSION_KEY" ]; then
|
|
56
|
+
SESSION_KEY=default
|
|
57
|
+
fi
|
|
58
|
+
SESSION_KEY=$(printf '%s' "$SESSION_KEY" | sed 's/[^A-Za-z0-9_.-]/_/g')
|
|
59
|
+
|
|
60
|
+
INPUT_FILE="$CACHE_DIR/stdin.$SESSION_KEY.json"
|
|
61
|
+
OUTPUT_FILE="$CACHE_DIR/statusline.$SESSION_KEY.txt"
|
|
62
|
+
LOCK_DIR="$CACHE_DIR/render.$SESSION_KEY.lock"
|
|
63
|
+
NODE_STDOUT_TMP="$CACHE_DIR/statusline.$SESSION_KEY.$$.tmp"
|
|
64
|
+
NODE_STDERR_TMP="$CACHE_DIR/statusline.$SESSION_KEY.$$.err"
|
|
65
|
+
|
|
66
|
+
if [ -s "$INPUT_TMP" ]; then
|
|
67
|
+
mv "$INPUT_TMP" "$INPUT_FILE" 2>/dev/null || cp "$INPUT_TMP" "$INPUT_FILE" 2>/dev/null || :
|
|
68
|
+
fi
|
|
69
|
+
rm -f "$INPUT_TMP" 2>/dev/null || :
|
|
70
|
+
|
|
71
|
+
# Hot path: return immediately from the last successful render for this session.
|
|
72
|
+
if [ -s "$OUTPUT_FILE" ]; then
|
|
73
|
+
cat "$OUTPUT_FILE" 2>/dev/null || printf '[OMC] Starting...\n'
|
|
74
|
+
else
|
|
75
|
+
printf '[OMC] Starting...\n'
|
|
76
|
+
fi
|
|
77
|
+
|
|
78
|
+
# Avoid spawning a Node renderer on every statusLine render. mkdir is atomic.
|
|
79
|
+
if ! mkdir "$LOCK_DIR" 2>/dev/null; then
|
|
80
|
+
# Recover from stale locks left by crashes.
|
|
81
|
+
if [ -d "$LOCK_DIR" ]; then
|
|
82
|
+
now=$(date +%s 2>/dev/null || printf '0')
|
|
83
|
+
lock_mtime=$( (stat -c %Y "$LOCK_DIR" 2>/dev/null || stat -f %m "$LOCK_DIR" 2>/dev/null) | head -1 )
|
|
84
|
+
if [ -n "$lock_mtime" ] && [ "$now" -gt 0 ] && [ $((now - lock_mtime)) -gt 10 ]; then
|
|
85
|
+
rm -rf "$LOCK_DIR" 2>/dev/null || :
|
|
86
|
+
mkdir "$LOCK_DIR" 2>/dev/null || exit 0
|
|
87
|
+
else
|
|
88
|
+
exit 0
|
|
89
|
+
fi
|
|
90
|
+
else
|
|
91
|
+
exit 0
|
|
92
|
+
fi
|
|
93
|
+
fi
|
|
94
|
+
|
|
95
|
+
refresh_cache() {
|
|
96
|
+
if [ ! -s "$INPUT_FILE" ]; then
|
|
97
|
+
rm -rf "$LOCK_DIR" 2>/dev/null || :
|
|
98
|
+
return
|
|
99
|
+
fi
|
|
100
|
+
|
|
101
|
+
if [ -x "$SCRIPT_DIR/find-node.sh" ]; then
|
|
102
|
+
sh "$SCRIPT_DIR/find-node.sh" "$HUD_SCRIPT" < "$INPUT_FILE" > "$NODE_STDOUT_TMP" 2> "$NODE_STDERR_TMP"
|
|
103
|
+
else
|
|
104
|
+
node "$HUD_SCRIPT" < "$INPUT_FILE" > "$NODE_STDOUT_TMP" 2> "$NODE_STDERR_TMP"
|
|
105
|
+
fi
|
|
106
|
+
|
|
107
|
+
# Keep the last good line if rendering fails or returns empty output.
|
|
108
|
+
if [ -s "$NODE_STDOUT_TMP" ]; then
|
|
109
|
+
mv "$NODE_STDOUT_TMP" "$OUTPUT_FILE" 2>/dev/null || cp "$NODE_STDOUT_TMP" "$OUTPUT_FILE" 2>/dev/null || :
|
|
110
|
+
fi
|
|
111
|
+
|
|
112
|
+
rm -f "$NODE_STDOUT_TMP" "$NODE_STDERR_TMP" 2>/dev/null || :
|
|
113
|
+
rm -rf "$LOCK_DIR" 2>/dev/null || :
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if [ "${OMC_HUD_SYNC_REFRESH:-0}" = "1" ]; then
|
|
117
|
+
refresh_cache
|
|
118
|
+
else
|
|
119
|
+
( refresh_cache ) >/dev/null 2>&1 &
|
|
120
|
+
fi
|
|
121
|
+
|
|
122
|
+
exit 0
|