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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git-worktree.d.ts","sourceRoot":"","sources":["../../src/team/git-worktree.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"git-worktree.d.ts","sourceRoot":"","sources":["../../src/team/git-worktree.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,111 +2,375 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Git worktree manager for team worker isolation.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
* {repoRoot}/.omcp/
|
|
7
|
-
* Branch naming: omc-team/{teamName}/{workerName}
|
|
5
|
+
* Native team worktrees live at:
|
|
6
|
+
* {repoRoot}/.omcp/team/{team}/worktrees/{worker}
|
|
7
|
+
* Branch naming (branch mode): omc-team/{teamName}/{workerName}
|
|
8
|
+
*
|
|
9
|
+
* The public create/remove helpers are kept for legacy callers, but the
|
|
10
|
+
* implementation is conservative: compatible clean worktrees are reused,
|
|
11
|
+
* dirty team worktrees are preserved, and cleanup never force-removes dirty
|
|
12
|
+
* worker changes.
|
|
8
13
|
*/
|
|
9
|
-
import { existsSync, readFileSync, rmSync } from 'node:fs';
|
|
10
|
-
import { join } from 'node:path';
|
|
14
|
+
import { existsSync, readFileSync, readdirSync, rmSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
15
|
+
import { join, resolve } from 'node:path';
|
|
11
16
|
import { execFileSync } from 'node:child_process';
|
|
12
17
|
import { atomicWriteJson, ensureDirWithMode, validateResolvedPath } from './fs-utils.js';
|
|
13
18
|
import { sanitizeName } from './tmux-session.js';
|
|
14
19
|
import { withFileLockSync } from '../lib/file-lock.js';
|
|
15
|
-
/** Get worktree path for a worker */
|
|
16
|
-
function getWorktreePath(repoRoot, teamName, workerName) {
|
|
17
|
-
return join(repoRoot, '.omcp', '
|
|
20
|
+
/** Get canonical native team worktree path for a worker. */
|
|
21
|
+
export function getWorktreePath(repoRoot, teamName, workerName) {
|
|
22
|
+
return join(repoRoot, '.omcp', 'team', sanitizeName(teamName), 'worktrees', sanitizeName(workerName));
|
|
18
23
|
}
|
|
19
|
-
/** Get branch name for a worker */
|
|
20
|
-
function getBranchName(teamName, workerName) {
|
|
24
|
+
/** Get branch name for a worker. */
|
|
25
|
+
export function getBranchName(teamName, workerName) {
|
|
21
26
|
return `omc-team/${sanitizeName(teamName)}/${sanitizeName(workerName)}`;
|
|
22
27
|
}
|
|
23
|
-
function
|
|
28
|
+
function git(repoRoot, args, cwd = repoRoot) {
|
|
29
|
+
return execFileSync('git', args, { cwd, encoding: 'utf-8', stdio: 'pipe' }).trim();
|
|
30
|
+
}
|
|
31
|
+
function isInsideGitRepo(repoRoot) {
|
|
24
32
|
try {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
33
|
+
git(repoRoot, ['rev-parse', '--show-toplevel']);
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function assertCleanLeaderWorktree(repoRoot) {
|
|
41
|
+
const status = git(repoRoot, ['status', '--porcelain'])
|
|
42
|
+
.split('\n')
|
|
43
|
+
.filter(line => line.trim() !== '' && !/^\?\? \.omcp?(?:\/|$)/.test(line))
|
|
44
|
+
.join('\n')
|
|
45
|
+
.trim();
|
|
46
|
+
if (status.length > 0) {
|
|
47
|
+
const error = new Error('leader_worktree_dirty: commit, stash, or clean changes before enabling team worktree mode');
|
|
48
|
+
error.code = 'leader_worktree_dirty';
|
|
49
|
+
throw error;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
function getRegisteredWorktreeBranch(repoRoot, wtPath) {
|
|
53
|
+
try {
|
|
54
|
+
const output = git(repoRoot, ['worktree', 'list', '--porcelain']);
|
|
55
|
+
const resolvedWtPath = resolve(wtPath);
|
|
56
|
+
let currentMatches = false;
|
|
31
57
|
for (const line of output.split('\n')) {
|
|
32
|
-
if (
|
|
58
|
+
if (line.startsWith('worktree ')) {
|
|
59
|
+
currentMatches = resolve(line.slice('worktree '.length).trim()) === resolvedWtPath;
|
|
33
60
|
continue;
|
|
34
|
-
if (line.slice('worktree '.length).trim() === resolvedWtPath) {
|
|
35
|
-
return true;
|
|
36
61
|
}
|
|
62
|
+
if (!currentMatches)
|
|
63
|
+
continue;
|
|
64
|
+
if (line.startsWith('branch '))
|
|
65
|
+
return line.slice('branch '.length).trim().replace(/^refs\/heads\//, '');
|
|
66
|
+
if (line === 'detached')
|
|
67
|
+
return 'HEAD';
|
|
37
68
|
}
|
|
38
69
|
}
|
|
39
70
|
catch {
|
|
40
71
|
// Best-effort check only.
|
|
41
72
|
}
|
|
42
|
-
return
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
function isRegisteredWorktreePath(repoRoot, wtPath) {
|
|
76
|
+
try {
|
|
77
|
+
const output = git(repoRoot, ['worktree', 'list', '--porcelain']);
|
|
78
|
+
const resolvedWtPath = resolve(wtPath);
|
|
79
|
+
return output.split('\n').some(line => (line.startsWith('worktree ') && resolve(line.slice('worktree '.length).trim()) === resolvedWtPath));
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
43
84
|
}
|
|
44
|
-
|
|
85
|
+
function isDetached(wtPath) {
|
|
86
|
+
try {
|
|
87
|
+
const branch = execFileSync('git', ['branch', '--show-current'], { cwd: wtPath, encoding: 'utf-8', stdio: 'pipe' }).trim();
|
|
88
|
+
return branch.length === 0;
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
function isWorktreeDirty(wtPath) {
|
|
95
|
+
return isWorktreeDirtyExcept(wtPath).dirty;
|
|
96
|
+
}
|
|
97
|
+
function normalizeStatusPath(rawPath) {
|
|
98
|
+
const trimmed = rawPath.trim();
|
|
99
|
+
if (trimmed.startsWith('\"') && trimmed.endsWith('\"')) {
|
|
100
|
+
try {
|
|
101
|
+
return JSON.parse(trimmed);
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
return trimmed.slice(1, -1);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return trimmed;
|
|
108
|
+
}
|
|
109
|
+
function statusEntryPath(line) {
|
|
110
|
+
const payload = line.slice(3);
|
|
111
|
+
const renameSeparator = ' -> ';
|
|
112
|
+
const renameIndex = payload.indexOf(renameSeparator);
|
|
113
|
+
return normalizeStatusPath(renameIndex >= 0 ? payload.slice(renameIndex + renameSeparator.length) : payload);
|
|
114
|
+
}
|
|
115
|
+
function isWorktreeDirtyExcept(wtPath, ignoredRootPaths = []) {
|
|
116
|
+
try {
|
|
117
|
+
const ignored = new Set(ignoredRootPaths);
|
|
118
|
+
const entries = execFileSync('git', ['status', '--porcelain'], { cwd: wtPath, encoding: 'utf-8', stdio: 'pipe' })
|
|
119
|
+
.split('\n')
|
|
120
|
+
.filter(line => line.trim().length > 0);
|
|
121
|
+
const relevantEntries = entries.filter(line => !ignored.has(statusEntryPath(line)));
|
|
122
|
+
return { dirty: relevantEntries.length > 0, entries: relevantEntries };
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
return { dirty: true, entries: ['git_status_failed'] };
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
/** Get worktree metadata path. */
|
|
45
129
|
function getMetadataPath(repoRoot, teamName) {
|
|
130
|
+
return join(repoRoot, '.omcp', 'state', 'team', sanitizeName(teamName), 'worktrees.json');
|
|
131
|
+
}
|
|
132
|
+
function getLegacyMetadataPath(repoRoot, teamName) {
|
|
46
133
|
return join(repoRoot, '.omcp', 'state', 'team-bridge', sanitizeName(teamName), 'worktrees.json');
|
|
47
134
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
135
|
+
function getWorkerStateDir(repoRoot, teamName, workerName) {
|
|
136
|
+
return join(repoRoot, '.omcp', 'state', 'team', sanitizeName(teamName), 'workers', sanitizeName(workerName));
|
|
137
|
+
}
|
|
138
|
+
function getRootAgentsBackupPath(repoRoot, teamName, workerName) {
|
|
139
|
+
return join(getWorkerStateDir(repoRoot, teamName, workerName), 'worktree-root-agents.json');
|
|
140
|
+
}
|
|
141
|
+
function readRootAgentsBackup(repoRoot, teamName, workerName) {
|
|
142
|
+
const backupPath = getRootAgentsBackupPath(repoRoot, teamName, workerName);
|
|
143
|
+
if (!existsSync(backupPath))
|
|
144
|
+
return null;
|
|
53
145
|
try {
|
|
54
|
-
return JSON.parse(readFileSync(
|
|
146
|
+
return JSON.parse(readFileSync(backupPath, 'utf-8'));
|
|
55
147
|
}
|
|
56
148
|
catch (err) {
|
|
57
|
-
// Log corruption instead of silently returning empty (which would lose all entries)
|
|
58
149
|
const msg = err instanceof Error ? err.message : String(err);
|
|
59
|
-
process.stderr.write(`[omc] warning:
|
|
150
|
+
process.stderr.write(`[omc] warning: worktree root AGENTS backup parse error: ${msg}\n`);
|
|
151
|
+
const error = new Error(`worktree_root_agents_backup_unreadable:${backupPath}:${msg}`);
|
|
152
|
+
error.code = 'worktree_root_agents_backup_unreadable';
|
|
153
|
+
throw error;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Install the generated worker overlay into the root of a native worker worktree.
|
|
158
|
+
* Existing root AGENTS.md content is backed up under leader-owned state so cleanup
|
|
159
|
+
* can safely restore it. Reinstalling preserves the first original backup instead
|
|
160
|
+
* of treating an older managed overlay as user content.
|
|
161
|
+
*/
|
|
162
|
+
export function installWorktreeRootAgents(teamName, workerName, repoRoot, worktreePath, overlayContent) {
|
|
163
|
+
validateResolvedPath(worktreePath, repoRoot);
|
|
164
|
+
const agentsPath = join(worktreePath, 'AGENTS.md');
|
|
165
|
+
validateResolvedPath(agentsPath, repoRoot);
|
|
166
|
+
const backupPath = getRootAgentsBackupPath(repoRoot, teamName, workerName);
|
|
167
|
+
validateResolvedPath(backupPath, repoRoot);
|
|
168
|
+
ensureDirWithMode(getWorkerStateDir(repoRoot, teamName, workerName));
|
|
169
|
+
const previous = readRootAgentsBackup(repoRoot, teamName, workerName);
|
|
170
|
+
const currentContent = existsSync(agentsPath) ? readFileSync(agentsPath, 'utf-8') : undefined;
|
|
171
|
+
if (previous && currentContent !== undefined && currentContent !== previous.installedContent) {
|
|
172
|
+
const error = new Error(`agents_dirty: preserving modified worktree root AGENTS.md at ${agentsPath}`);
|
|
173
|
+
error.code = 'agents_dirty';
|
|
174
|
+
throw error;
|
|
175
|
+
}
|
|
176
|
+
const backup = previous
|
|
177
|
+
? { ...previous, worktreePath, installedContent: overlayContent, installedAt: new Date().toISOString() }
|
|
178
|
+
: {
|
|
179
|
+
worktreePath,
|
|
180
|
+
hadOriginal: currentContent !== undefined,
|
|
181
|
+
...(currentContent !== undefined ? { originalContent: currentContent } : {}),
|
|
182
|
+
installedContent: overlayContent,
|
|
183
|
+
installedAt: new Date().toISOString(),
|
|
184
|
+
};
|
|
185
|
+
atomicWriteJson(backupPath, backup);
|
|
186
|
+
writeFileSync(agentsPath, overlayContent, 'utf-8');
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Restore or remove a managed worktree-root AGENTS.md when it is still unchanged.
|
|
190
|
+
* If a worker edited AGENTS.md, leave it and report agents_dirty so cleanup can
|
|
191
|
+
* preserve the worktree instead of overwriting user changes.
|
|
192
|
+
*/
|
|
193
|
+
export function restoreWorktreeRootAgents(teamName, workerName, repoRoot, worktreePath) {
|
|
194
|
+
const backupPath = getRootAgentsBackupPath(repoRoot, teamName, workerName);
|
|
195
|
+
validateResolvedPath(backupPath, repoRoot);
|
|
196
|
+
const backup = readRootAgentsBackup(repoRoot, teamName, workerName);
|
|
197
|
+
if (!backup)
|
|
198
|
+
return { restored: false, reason: 'no_backup' };
|
|
199
|
+
const resolvedWorktreePath = worktreePath ?? backup.worktreePath;
|
|
200
|
+
validateResolvedPath(resolvedWorktreePath, repoRoot);
|
|
201
|
+
if (!existsSync(resolvedWorktreePath)) {
|
|
202
|
+
try {
|
|
203
|
+
unlinkSync(backupPath);
|
|
204
|
+
}
|
|
205
|
+
catch { /* backup already gone */ }
|
|
206
|
+
return { restored: false, reason: 'worktree_missing' };
|
|
207
|
+
}
|
|
208
|
+
const agentsPath = join(resolvedWorktreePath, 'AGENTS.md');
|
|
209
|
+
validateResolvedPath(agentsPath, repoRoot);
|
|
210
|
+
const currentContent = existsSync(agentsPath) ? readFileSync(agentsPath, 'utf-8') : undefined;
|
|
211
|
+
const isPartialInstallOriginal = backup.hadOriginal && currentContent === (backup.originalContent ?? '');
|
|
212
|
+
if (currentContent !== undefined && currentContent !== backup.installedContent && !isPartialInstallOriginal) {
|
|
213
|
+
return { restored: false, reason: 'agents_dirty' };
|
|
214
|
+
}
|
|
215
|
+
if (backup.hadOriginal) {
|
|
216
|
+
writeFileSync(agentsPath, backup.originalContent ?? '', 'utf-8');
|
|
217
|
+
}
|
|
218
|
+
else if (existsSync(agentsPath)) {
|
|
219
|
+
unlinkSync(agentsPath);
|
|
220
|
+
}
|
|
221
|
+
try {
|
|
222
|
+
unlinkSync(backupPath);
|
|
223
|
+
}
|
|
224
|
+
catch { /* backup already gone */ }
|
|
225
|
+
return { restored: true };
|
|
226
|
+
}
|
|
227
|
+
/** Read worktree metadata, including legacy metadata for cleanup compatibility. */
|
|
228
|
+
function readMetadataResult(repoRoot, teamName) {
|
|
229
|
+
const paths = [getMetadataPath(repoRoot, teamName), getLegacyMetadataPath(repoRoot, teamName)];
|
|
230
|
+
const byWorker = new Map();
|
|
231
|
+
const issues = [];
|
|
232
|
+
for (const metaPath of paths) {
|
|
233
|
+
if (!existsSync(metaPath))
|
|
234
|
+
continue;
|
|
235
|
+
try {
|
|
236
|
+
const entries = JSON.parse(readFileSync(metaPath, 'utf-8'));
|
|
237
|
+
for (const entry of entries)
|
|
238
|
+
byWorker.set(entry.workerName, entry);
|
|
239
|
+
}
|
|
240
|
+
catch (err) {
|
|
241
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
242
|
+
issues.push({ path: metaPath, message });
|
|
243
|
+
process.stderr.write(`[omc] warning: worktrees.json parse error at ${metaPath}: ${message}
|
|
244
|
+
`);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
return { entries: [...byWorker.values()], issues };
|
|
248
|
+
}
|
|
249
|
+
function readMetadata(repoRoot, teamName) {
|
|
250
|
+
return readMetadataResult(repoRoot, teamName).entries;
|
|
251
|
+
}
|
|
252
|
+
function listRootAgentsBackupIssues(repoRoot, teamName, entries) {
|
|
253
|
+
const workersDir = join(repoRoot, '.omcp', 'state', 'team', sanitizeName(teamName), 'workers');
|
|
254
|
+
if (!existsSync(workersDir))
|
|
60
255
|
return [];
|
|
256
|
+
const knownWorkers = new Set(entries.map((entry) => sanitizeName(entry.workerName)));
|
|
257
|
+
const issues = [];
|
|
258
|
+
for (const workerName of readdirSync(workersDir)) {
|
|
259
|
+
const backupPath = join(workersDir, workerName, 'worktree-root-agents.json');
|
|
260
|
+
if (!existsSync(backupPath))
|
|
261
|
+
continue;
|
|
262
|
+
try {
|
|
263
|
+
JSON.parse(readFileSync(backupPath, 'utf-8'));
|
|
264
|
+
}
|
|
265
|
+
catch (error) {
|
|
266
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
267
|
+
issues.push({ path: backupPath, message: `worktree_root_agents_backup_unreadable:${workerName}:${message}` });
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
if (!knownWorkers.has(sanitizeName(workerName))) {
|
|
271
|
+
issues.push({
|
|
272
|
+
path: backupPath,
|
|
273
|
+
message: `orphaned_worktree_root_agents_backup:${workerName}`,
|
|
274
|
+
});
|
|
275
|
+
}
|
|
61
276
|
}
|
|
277
|
+
return issues;
|
|
62
278
|
}
|
|
63
|
-
/** Write worktree metadata */
|
|
279
|
+
/** Write native worktree metadata. */
|
|
64
280
|
function writeMetadata(repoRoot, teamName, entries) {
|
|
65
281
|
const metaPath = getMetadataPath(repoRoot, teamName);
|
|
66
282
|
validateResolvedPath(metaPath, repoRoot);
|
|
67
|
-
|
|
68
|
-
ensureDirWithMode(dir);
|
|
283
|
+
ensureDirWithMode(join(repoRoot, '.omcp', 'state', 'team', sanitizeName(teamName)));
|
|
69
284
|
atomicWriteJson(metaPath, entries);
|
|
70
285
|
}
|
|
286
|
+
function recordMetadata(repoRoot, teamName, info) {
|
|
287
|
+
const metaLockPath = getMetadataPath(repoRoot, teamName) + '.lock';
|
|
288
|
+
withFileLockSync(metaLockPath, () => {
|
|
289
|
+
const existing = readMetadata(repoRoot, teamName).filter(entry => entry.workerName !== info.workerName);
|
|
290
|
+
writeMetadata(repoRoot, teamName, [...existing, info]);
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
function forgetMetadataUnlocked(repoRoot, teamName, workerName) {
|
|
294
|
+
const existing = readMetadata(repoRoot, teamName).filter(entry => entry.workerName !== workerName);
|
|
295
|
+
writeMetadata(repoRoot, teamName, existing);
|
|
296
|
+
}
|
|
297
|
+
function assertCompatibleExistingWorktree(repoRoot, wtPath, expectedBranch, mode) {
|
|
298
|
+
const registeredBranch = getRegisteredWorktreeBranch(repoRoot, wtPath);
|
|
299
|
+
if (!registeredBranch) {
|
|
300
|
+
const error = new Error(`worktree_path_mismatch: existing path is not a registered git worktree: ${wtPath}`);
|
|
301
|
+
error.code = 'worktree_path_mismatch';
|
|
302
|
+
throw error;
|
|
303
|
+
}
|
|
304
|
+
if (isWorktreeDirty(wtPath)) {
|
|
305
|
+
const error = new Error(`worktree_dirty: preserving dirty worker worktree at ${wtPath}`);
|
|
306
|
+
error.code = 'worktree_dirty';
|
|
307
|
+
throw error;
|
|
308
|
+
}
|
|
309
|
+
if (mode === 'named' && registeredBranch !== expectedBranch) {
|
|
310
|
+
const error = new Error(`worktree_mismatch: expected branch ${expectedBranch} at ${wtPath}, found ${registeredBranch}`);
|
|
311
|
+
error.code = 'worktree_mismatch';
|
|
312
|
+
throw error;
|
|
313
|
+
}
|
|
314
|
+
if (mode === 'detached' && registeredBranch !== 'HEAD') {
|
|
315
|
+
const error = new Error(`worktree_mismatch: expected detached worktree at ${wtPath}, found ${registeredBranch}`);
|
|
316
|
+
error.code = 'worktree_mismatch';
|
|
317
|
+
throw error;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
export function normalizeTeamWorktreeMode(value) {
|
|
321
|
+
if (typeof value !== 'string')
|
|
322
|
+
return 'disabled';
|
|
323
|
+
const normalized = value.trim().toLowerCase();
|
|
324
|
+
if (['1', 'true', 'yes', 'on', 'enabled', 'detached'].includes(normalized))
|
|
325
|
+
return 'detached';
|
|
326
|
+
if (['branch', 'named', 'named-branch'].includes(normalized))
|
|
327
|
+
return 'named';
|
|
328
|
+
return 'disabled';
|
|
329
|
+
}
|
|
71
330
|
/**
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
331
|
+
* Ensure a worker worktree exists according to the selected opt-in mode.
|
|
332
|
+
* Disabled mode is a no-op. Existing clean compatible worktrees are reused;
|
|
333
|
+
* dirty or mismatched existing worktrees throw without deleting files.
|
|
75
334
|
*/
|
|
76
|
-
export function
|
|
335
|
+
export function ensureWorkerWorktree(teamName, workerName, repoRoot, options = {}) {
|
|
336
|
+
const mode = options.mode ?? 'disabled';
|
|
337
|
+
if (mode === 'disabled')
|
|
338
|
+
return null;
|
|
339
|
+
if (!isInsideGitRepo(repoRoot)) {
|
|
340
|
+
throw new Error(`not_a_git_repository: ${repoRoot}`);
|
|
341
|
+
}
|
|
342
|
+
if (options.requireCleanLeader !== false) {
|
|
343
|
+
assertCleanLeaderWorktree(repoRoot);
|
|
344
|
+
}
|
|
77
345
|
const wtPath = getWorktreePath(repoRoot, teamName, workerName);
|
|
78
|
-
const branch = getBranchName(teamName, workerName);
|
|
346
|
+
const branch = mode === 'named' ? getBranchName(teamName, workerName) : 'HEAD';
|
|
79
347
|
validateResolvedPath(wtPath, repoRoot);
|
|
80
|
-
// Prune stale worktrees first
|
|
81
348
|
try {
|
|
82
349
|
execFileSync('git', ['worktree', 'prune'], { cwd: repoRoot, stdio: 'pipe' });
|
|
83
350
|
}
|
|
84
351
|
catch { /* ignore */ }
|
|
85
|
-
// Remove stale worktree if it exists
|
|
86
352
|
if (existsSync(wtPath)) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
353
|
+
assertCompatibleExistingWorktree(repoRoot, wtPath, branch, mode);
|
|
354
|
+
const info = {
|
|
355
|
+
path: wtPath,
|
|
356
|
+
branch,
|
|
357
|
+
workerName,
|
|
358
|
+
teamName,
|
|
359
|
+
createdAt: new Date().toISOString(),
|
|
360
|
+
repoRoot,
|
|
361
|
+
mode,
|
|
362
|
+
detached: isDetached(wtPath),
|
|
363
|
+
created: false,
|
|
364
|
+
reused: true,
|
|
365
|
+
};
|
|
366
|
+
recordMetadata(repoRoot, teamName, info);
|
|
367
|
+
return info;
|
|
101
368
|
}
|
|
102
|
-
|
|
103
|
-
// Create worktree directory
|
|
104
|
-
const wtDir = join(repoRoot, '.omcp', 'worktrees', sanitizeName(teamName));
|
|
369
|
+
const wtDir = join(repoRoot, '.omcp', 'team', sanitizeName(teamName), 'worktrees');
|
|
105
370
|
ensureDirWithMode(wtDir);
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
args.push(baseBranch);
|
|
371
|
+
const args = mode === 'named'
|
|
372
|
+
? ['worktree', 'add', '-b', branch, wtPath, options.baseRef ?? 'HEAD']
|
|
373
|
+
: ['worktree', 'add', '--detach', wtPath, options.baseRef ?? 'HEAD'];
|
|
110
374
|
execFileSync('git', args, { cwd: repoRoot, stdio: 'pipe' });
|
|
111
375
|
const info = {
|
|
112
376
|
path: wtPath,
|
|
@@ -114,62 +378,154 @@ export function createWorkerWorktree(teamName, workerName, repoRoot, baseBranch)
|
|
|
114
378
|
workerName,
|
|
115
379
|
teamName,
|
|
116
380
|
createdAt: new Date().toISOString(),
|
|
381
|
+
repoRoot,
|
|
382
|
+
mode,
|
|
383
|
+
detached: mode === 'detached',
|
|
384
|
+
created: true,
|
|
385
|
+
reused: false,
|
|
117
386
|
};
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
387
|
+
recordMetadata(repoRoot, teamName, info);
|
|
388
|
+
return info;
|
|
389
|
+
}
|
|
390
|
+
/** Legacy creation helper: create or reuse a named-branch worker worktree. */
|
|
391
|
+
export function createWorkerWorktree(teamName, workerName, repoRoot, baseBranch) {
|
|
392
|
+
const info = ensureWorkerWorktree(teamName, workerName, repoRoot, {
|
|
393
|
+
mode: 'named',
|
|
394
|
+
baseRef: baseBranch,
|
|
395
|
+
requireCleanLeader: false,
|
|
125
396
|
});
|
|
397
|
+
if (!info)
|
|
398
|
+
throw new Error('worktree creation unexpectedly disabled');
|
|
126
399
|
return info;
|
|
127
400
|
}
|
|
128
401
|
/**
|
|
129
|
-
*
|
|
402
|
+
* Dry-run validation for worker worktree removal. This does not restore/remove
|
|
403
|
+
* managed root AGENTS.md and does not delete backup state.
|
|
130
404
|
*/
|
|
131
|
-
export function
|
|
132
|
-
const wtPath = getWorktreePath(repoRoot, teamName, workerName);
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
405
|
+
export function checkWorkerWorktreeRemovalSafety(teamName, workerName, repoRoot, worktreePath) {
|
|
406
|
+
const wtPath = worktreePath ?? getWorktreePath(repoRoot, teamName, workerName);
|
|
407
|
+
const backup = readRootAgentsBackup(repoRoot, teamName, workerName);
|
|
408
|
+
if (!existsSync(wtPath))
|
|
409
|
+
return;
|
|
410
|
+
let ignoreRootAgents = false;
|
|
411
|
+
if (backup) {
|
|
412
|
+
const agentsPath = join(wtPath, 'AGENTS.md');
|
|
413
|
+
validateResolvedPath(agentsPath, repoRoot);
|
|
414
|
+
const currentContent = existsSync(agentsPath) ? readFileSync(agentsPath, 'utf-8') : undefined;
|
|
415
|
+
const isPartialInstallOriginal = backup.hadOriginal && currentContent === (backup.originalContent ?? '');
|
|
416
|
+
if (currentContent !== undefined && currentContent !== backup.installedContent && !isPartialInstallOriginal) {
|
|
417
|
+
const error = new Error(`agents_dirty: preserving modified worktree root AGENTS.md at ${agentsPath}`);
|
|
418
|
+
error.code = 'agents_dirty';
|
|
419
|
+
throw error;
|
|
420
|
+
}
|
|
421
|
+
ignoreRootAgents = true;
|
|
137
422
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
423
|
+
const dirtyCheck = isWorktreeDirtyExcept(wtPath, ignoreRootAgents ? ['AGENTS.md'] : []);
|
|
424
|
+
if (dirtyCheck.dirty) {
|
|
425
|
+
const error = new Error(`worktree_dirty: preserving dirty worker worktree at ${wtPath}`);
|
|
426
|
+
error.code = 'worktree_dirty';
|
|
427
|
+
throw error;
|
|
142
428
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* Prepare a worker worktree for later removal without deleting the worktree.
|
|
432
|
+
*
|
|
433
|
+
* This is transactional with respect to managed root AGENTS.md overlays: it first
|
|
434
|
+
* validates the overlay is restorable and that no non-overlay files are dirty.
|
|
435
|
+
* Only after that dry-run succeeds does it restore/remove AGENTS.md and delete
|
|
436
|
+
* the backup. If any other dirty file exists, the worker pane/config can remain
|
|
437
|
+
* intact with the managed overlay and backup still available for a later retry.
|
|
438
|
+
*/
|
|
439
|
+
export function prepareWorkerWorktreeForRemoval(teamName, workerName, repoRoot, worktreePath) {
|
|
440
|
+
const wtPath = worktreePath ?? getWorktreePath(repoRoot, teamName, workerName);
|
|
441
|
+
checkWorkerWorktreeRemovalSafety(teamName, workerName, repoRoot, wtPath);
|
|
442
|
+
const agentsRestore = restoreWorktreeRootAgents(teamName, workerName, repoRoot, wtPath);
|
|
443
|
+
if (agentsRestore.reason === 'agents_dirty') {
|
|
444
|
+
const error = new Error(`agents_dirty: preserving modified worktree root AGENTS.md at ${join(wtPath, 'AGENTS.md')}`);
|
|
445
|
+
error.code = 'agents_dirty';
|
|
446
|
+
throw error;
|
|
147
447
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
448
|
+
}
|
|
449
|
+
/** Remove a worker's worktree and branch, preserving dirty worktrees. */
|
|
450
|
+
export function removeWorkerWorktree(teamName, workerName, repoRoot) {
|
|
451
|
+
const wtPath = getWorktreePath(repoRoot, teamName, workerName);
|
|
452
|
+
const branch = getBranchName(teamName, workerName);
|
|
453
|
+
const metaLockPath = `${getMetadataPath(repoRoot, teamName)}.lock`;
|
|
151
454
|
withFileLockSync(metaLockPath, () => {
|
|
152
|
-
|
|
153
|
-
const
|
|
154
|
-
|
|
455
|
+
prepareWorkerWorktreeForRemoval(teamName, workerName, repoRoot, wtPath);
|
|
456
|
+
const wasRegisteredWorktree = isRegisteredWorktreePath(repoRoot, wtPath);
|
|
457
|
+
try {
|
|
458
|
+
execFileSync('git', ['worktree', 'remove', wtPath], { cwd: repoRoot, stdio: 'pipe' });
|
|
459
|
+
}
|
|
460
|
+
catch (err) {
|
|
461
|
+
if (wasRegisteredWorktree) {
|
|
462
|
+
const detail = err instanceof Error && err.message ? `: ${err.message}` : '';
|
|
463
|
+
const error = new Error(`worktree_remove_failed: preserving metadata for registered worker worktree at ${wtPath}${detail}`);
|
|
464
|
+
error.code = 'worktree_remove_failed';
|
|
465
|
+
throw error;
|
|
466
|
+
}
|
|
467
|
+
// Unregistered/absent stale paths are best-effort cleanup only.
|
|
468
|
+
}
|
|
469
|
+
try {
|
|
470
|
+
execFileSync('git', ['worktree', 'prune'], { cwd: repoRoot, stdio: 'pipe' });
|
|
471
|
+
}
|
|
472
|
+
catch { /* ignore */ }
|
|
473
|
+
try {
|
|
474
|
+
execFileSync('git', ['branch', '-D', branch], { cwd: repoRoot, stdio: 'pipe' });
|
|
475
|
+
}
|
|
476
|
+
catch { /* branch may not exist */ }
|
|
477
|
+
// If a stale plain directory remains and it is not a registered worktree, remove it.
|
|
478
|
+
if (existsSync(wtPath) && !isRegisteredWorktreePath(repoRoot, wtPath)) {
|
|
479
|
+
rmSync(wtPath, { recursive: true, force: true });
|
|
480
|
+
}
|
|
481
|
+
forgetMetadataUnlocked(repoRoot, teamName, workerName);
|
|
155
482
|
});
|
|
156
483
|
}
|
|
157
|
-
/**
|
|
158
|
-
* List all worktrees for a team.
|
|
159
|
-
*/
|
|
484
|
+
/** List all worktrees for a team. */
|
|
160
485
|
export function listTeamWorktrees(teamName, repoRoot) {
|
|
161
486
|
return readMetadata(repoRoot, teamName);
|
|
162
487
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
488
|
+
export function inspectTeamWorktreeCleanupSafety(teamName, repoRoot) {
|
|
489
|
+
const metadata = readMetadataResult(repoRoot, teamName);
|
|
490
|
+
const entries = metadata.entries;
|
|
491
|
+
const backupIssues = listRootAgentsBackupIssues(repoRoot, teamName, entries);
|
|
492
|
+
return {
|
|
493
|
+
hasEvidence: entries.length > 0 || metadata.issues.length > 0 || backupIssues.length > 0,
|
|
494
|
+
entries,
|
|
495
|
+
blockers: [
|
|
496
|
+
...metadata.issues.map((issue, index) => ({
|
|
497
|
+
workerName: `metadata-${index + 1}`,
|
|
498
|
+
path: issue.path,
|
|
499
|
+
reason: `worktree_metadata_unreadable:${issue.message}`,
|
|
500
|
+
})),
|
|
501
|
+
...backupIssues.map((issue, index) => ({
|
|
502
|
+
workerName: `agents-backup-${index + 1}`,
|
|
503
|
+
path: issue.path,
|
|
504
|
+
reason: issue.message,
|
|
505
|
+
})),
|
|
506
|
+
],
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
/** Remove all clean worktrees for a team, preserving dirty worktrees. */
|
|
166
510
|
export function cleanupTeamWorktrees(teamName, repoRoot) {
|
|
167
|
-
const
|
|
511
|
+
const safety = inspectTeamWorktreeCleanupSafety(teamName, repoRoot);
|
|
512
|
+
const entries = safety.entries;
|
|
513
|
+
const removed = [];
|
|
514
|
+
const preserved = [...safety.blockers];
|
|
515
|
+
if (preserved.length > 0) {
|
|
516
|
+
return { removed, preserved };
|
|
517
|
+
}
|
|
168
518
|
for (const entry of entries) {
|
|
169
519
|
try {
|
|
170
520
|
removeWorkerWorktree(teamName, entry.workerName, repoRoot);
|
|
521
|
+
removed.push(entry.workerName);
|
|
522
|
+
}
|
|
523
|
+
catch (err) {
|
|
524
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
525
|
+
preserved.push({ workerName: entry.workerName, path: entry.path, reason });
|
|
526
|
+
process.stderr.write(`[omc] warning: preserved worktree ${entry.path}: ${reason}\n`);
|
|
171
527
|
}
|
|
172
|
-
catch { /* best effort */ }
|
|
173
528
|
}
|
|
529
|
+
return { removed, preserved };
|
|
174
530
|
}
|
|
175
531
|
//# sourceMappingURL=git-worktree.js.map
|