oh-my-copilot 4.13.2 → 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 +1 -1
- package/bridge/cli.cjs +2522 -949
- package/bridge/mcp-server.cjs +97 -9
- package/bridge/runtime-cli.cjs +1256 -133
- package/bridge/team.js +1241 -65
- package/dist/__tests__/auto-slash-aliases.test.js +91 -0
- package/dist/__tests__/auto-slash-aliases.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-rate-limits-priority.test.js +26 -0
- package/dist/__tests__/hud/render-rate-limits-priority.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__/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__/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 +56 -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/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 +14 -2
- 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 +23 -1
- package/dist/cli/team.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/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/detector.js +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 +10 -9
- package/dist/hooks/persistent-mode/index.js.map +1 -1
- package/dist/hooks/persistent-mode/stop-hook-blocking.test.js +64 -9
- 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 +67 -0
- package/dist/hooks/session-end/index.js.map +1 -1
- package/dist/hooks/skill-bridge.cjs +6 -5
- 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__/git-status.test.js +18 -0
- package/dist/hud/__tests__/git-status.test.js.map +1 -1
- 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/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/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/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/render.d.ts.map +1 -1
- package/dist/hud/render.js +11 -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/types.d.ts +26 -0
- package/dist/hud/types.d.ts.map +1 -1
- package/dist/hud/types.js +58 -0
- package/dist/hud/types.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.map +1 -1
- package/dist/installer/index.js +19 -7
- 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/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__/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__/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 +9 -1
- package/dist/team/__tests__/runtime-cli.test.js.map +1 -1
- package/dist/team/__tests__/runtime-v2.dispatch.test.js +150 -1
- package/dist/team/__tests__/runtime-v2.dispatch.test.js.map +1 -1
- 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__/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-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/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/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/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 +7 -1
- package/dist/team/runtime-v2.d.ts.map +1 -1
- package/dist/team/runtime-v2.js +185 -8
- package/dist/team/runtime-v2.js.map +1 -1
- package/dist/team/worker-bootstrap.d.ts +4 -0
- package/dist/team/worker-bootstrap.d.ts.map +1 -1
- package/dist/team/worker-bootstrap.js +10 -1
- package/dist/team/worker-bootstrap.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/docs/GETTING-STARTED.md +415 -0
- package/docs/MIGRATION.md +66 -66
- package/docs/REFERENCE.md +21 -4
- package/docs/company-context-interface.md +5 -16
- package/docs/copilot-instructions.md +1 -1
- package/package.json +1 -1
- package/scripts/lib/hud-cache-wrapper.sh +122 -0
- package/scripts/plugin-setup.mjs +10 -1
- package/scripts/post-tool-verifier.mjs +118 -5
- package/scripts/pre-tool-enforcer.mjs +54 -6
- package/scripts/session-start.mjs +171 -3
- 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/pre-tool-use.mjs +144 -45
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { OrchestratorHandle } from '../../merge-orchestrator.js';
|
|
2
|
+
export interface WorkerFixture {
|
|
3
|
+
name: string;
|
|
4
|
+
worktreePath: string;
|
|
5
|
+
branch: string;
|
|
6
|
+
}
|
|
7
|
+
export interface GitFixture {
|
|
8
|
+
/** Root of the (non-bare) git repository. */
|
|
9
|
+
repoRoot: string;
|
|
10
|
+
/** Leader branch name — never main/master. */
|
|
11
|
+
leaderBranch: string;
|
|
12
|
+
/** Team name used for orchestrator config. */
|
|
13
|
+
teamName: string;
|
|
14
|
+
/** Array of worker descriptors. */
|
|
15
|
+
workers: WorkerFixture[];
|
|
16
|
+
/**
|
|
17
|
+
* Commit a file in a worker worktree.
|
|
18
|
+
* Returns the resulting commit SHA.
|
|
19
|
+
*/
|
|
20
|
+
commitFile(workerName: string, relPath: string, content: string): Promise<string>;
|
|
21
|
+
/**
|
|
22
|
+
* Read the HEAD SHA of any branch in the repo.
|
|
23
|
+
*/
|
|
24
|
+
getBranchSha(branch: string): string;
|
|
25
|
+
/**
|
|
26
|
+
* Create a gitdir-aware rebase-merge marker for a real git worktree.
|
|
27
|
+
* Returns the marker path.
|
|
28
|
+
*/
|
|
29
|
+
createRebaseState(workerName: string): string;
|
|
30
|
+
/**
|
|
31
|
+
* Simulate a runtime restart: stops the orchestrator handle (if any was attached
|
|
32
|
+
* via attachHandle) without cleanup. Optionally creates an orphan rebase-merge
|
|
33
|
+
* dir inside the specified worker worktree's real gitdir.
|
|
34
|
+
*/
|
|
35
|
+
simulateRuntimeRestart(orphanWorkerName?: string): Promise<void>;
|
|
36
|
+
/** Attach an orchestrator handle so simulateRuntimeRestart can stop it. */
|
|
37
|
+
attachHandle(handle: OrchestratorHandle): void;
|
|
38
|
+
/**
|
|
39
|
+
* Remove all temporary directories.
|
|
40
|
+
* Call this in afterEach.
|
|
41
|
+
*/
|
|
42
|
+
cleanup(): Promise<void>;
|
|
43
|
+
}
|
|
44
|
+
export interface CreateGitFixtureOpts {
|
|
45
|
+
workerCount: number;
|
|
46
|
+
leaderBranchName?: string;
|
|
47
|
+
teamName?: string;
|
|
48
|
+
keepLeaderBranchCheckedOut?: boolean;
|
|
49
|
+
}
|
|
50
|
+
export declare function createGitFixture(opts: CreateGitFixtureOpts): Promise<GitFixture>;
|
|
51
|
+
export interface WaitForEventOpts {
|
|
52
|
+
/** Path to orchestrator-events.jsonl */
|
|
53
|
+
eventLogPath: string;
|
|
54
|
+
/** Event type to look for */
|
|
55
|
+
eventType: string;
|
|
56
|
+
/** Minimum count of matching events required */
|
|
57
|
+
count?: number;
|
|
58
|
+
/** Total timeout in ms */
|
|
59
|
+
timeoutMs?: number;
|
|
60
|
+
/** Optional worker name filter */
|
|
61
|
+
worker?: string;
|
|
62
|
+
}
|
|
63
|
+
export declare function waitForEventInLog(opts: WaitForEventOpts): Promise<void>;
|
|
64
|
+
/** Read all events from the orchestrator event log. */
|
|
65
|
+
export declare function readEventLog(eventLogPath: string): Array<{
|
|
66
|
+
type: string;
|
|
67
|
+
worker?: string;
|
|
68
|
+
[k: string]: unknown;
|
|
69
|
+
}>;
|
|
70
|
+
/** Build the event log path for a team. */
|
|
71
|
+
export declare function orchestratorEventLogPath(repoRoot: string, teamName: string): string;
|
|
72
|
+
//# sourceMappingURL=git-fixture.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-fixture.d.ts","sourceRoot":"","sources":["../../../../src/team/__tests__/helpers/git-fixture.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAEtE,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,UAAU;IACzB,6CAA6C;IAC7C,QAAQ,EAAE,MAAM,CAAC;IACjB,8CAA8C;IAC9C,YAAY,EAAE,MAAM,CAAC;IACrB,8CAA8C;IAC9C,QAAQ,EAAE,MAAM,CAAC;IACjB,mCAAmC;IACnC,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB;;;OAGG;IACH,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAClF;;OAEG;IACH,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IACrC;;;OAGG;IACH,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9C;;;;OAIG;IACH,sBAAsB,CAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE,2EAA2E;IAC3E,YAAY,CAAC,MAAM,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAC/C;;;OAGG;IACH,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAoBD,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0BAA0B,CAAC,EAAE,OAAO,CAAC;CACtC;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,UAAU,CAAC,CA8JtF;AAMD,MAAM,WAAW,gBAAgB;IAC/B,wCAAwC;IACxC,YAAY,EAAE,MAAM,CAAC;IACrB,6BAA6B;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,gDAAgD;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0BAA0B;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kCAAkC;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiD7E;AAED,uDAAuD;AACvD,wBAAgB,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,CAAC,CAiBjH;AAED,2CAA2C;AAC3C,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEnF"}
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
// src/team/__tests__/helpers/git-fixture.ts
|
|
2
|
+
//
|
|
3
|
+
// Ephemeral bare-repo + N worker worktrees for integration tests.
|
|
4
|
+
// Uses real git via execFileSync. Each test gets its own fixture.
|
|
5
|
+
//
|
|
6
|
+
// Design notes:
|
|
7
|
+
// - The "repo root" is a regular (non-bare) git repo at tmpDir/repo/
|
|
8
|
+
// - Worker worktrees live at tmpDir/worktrees/{workerName}/
|
|
9
|
+
// - Worker branches are omc-team/{teamName}/{workerName} (matching getBranchName)
|
|
10
|
+
// - Leader branch must NOT be main/master (M3 hardening) — defaults to 'omc-team-test-leader'
|
|
11
|
+
// - State dir (.omcp/...) is created inside the repo root so orchestrator paths resolve
|
|
12
|
+
// - simulateRuntimeRestart does NOT clean up the repo; it only kills the orchestrator
|
|
13
|
+
// handle (if set externally) and can optionally create an orphan rebase-merge dir.
|
|
14
|
+
import { execFileSync } from 'node:child_process';
|
|
15
|
+
import { mkdtempSync, mkdirSync, writeFileSync, readFileSync, existsSync } from 'node:fs';
|
|
16
|
+
import { tmpdir } from 'node:os';
|
|
17
|
+
import { join } from 'node:path';
|
|
18
|
+
function git(cwd, args) {
|
|
19
|
+
return execFileSync('git', args, {
|
|
20
|
+
cwd,
|
|
21
|
+
encoding: 'utf-8',
|
|
22
|
+
stdio: 'pipe',
|
|
23
|
+
env: {
|
|
24
|
+
...process.env,
|
|
25
|
+
// Disable GPG signing in tests
|
|
26
|
+
GIT_COMMITTER_NAME: 'Test User',
|
|
27
|
+
GIT_COMMITTER_EMAIL: 'test@example.com',
|
|
28
|
+
GIT_AUTHOR_NAME: 'Test User',
|
|
29
|
+
GIT_AUTHOR_EMAIL: 'test@example.com',
|
|
30
|
+
GIT_CONFIG_GLOBAL: '/dev/null',
|
|
31
|
+
GIT_CONFIG_SYSTEM: '/dev/null',
|
|
32
|
+
},
|
|
33
|
+
}).trim();
|
|
34
|
+
}
|
|
35
|
+
export async function createGitFixture(opts) {
|
|
36
|
+
const { workerCount, leaderBranchName = 'omc-team-test-leader', teamName = 'test-team', keepLeaderBranchCheckedOut = false, } = opts;
|
|
37
|
+
// Guard: never allow main/master as leader branch (M3)
|
|
38
|
+
const normalized = leaderBranchName.toLowerCase();
|
|
39
|
+
if (normalized === 'main' || normalized === 'master') {
|
|
40
|
+
throw new Error(`git-fixture: leaderBranchName must not be main/master (M3 hardening)`);
|
|
41
|
+
}
|
|
42
|
+
// Create temp directory structure
|
|
43
|
+
const tmpBase = mkdtempSync(join(tmpdir(), 'omc-test-'));
|
|
44
|
+
const repoRoot = join(tmpBase, 'repo');
|
|
45
|
+
mkdirSync(repoRoot, { recursive: true });
|
|
46
|
+
// Init repo
|
|
47
|
+
git(repoRoot, ['init', '-b', leaderBranchName]);
|
|
48
|
+
git(repoRoot, ['config', 'user.email', 'test@example.com']);
|
|
49
|
+
git(repoRoot, ['config', 'user.name', 'Test User']);
|
|
50
|
+
git(repoRoot, ['config', 'commit.gpgsign', 'false']);
|
|
51
|
+
git(repoRoot, ['config', 'merge.conflictstyle', 'diff3']);
|
|
52
|
+
// Create an initial commit on the leader branch so it exists
|
|
53
|
+
const readmePath = join(repoRoot, 'README.md');
|
|
54
|
+
writeFileSync(readmePath, '# test repo\n', 'utf-8');
|
|
55
|
+
git(repoRoot, ['add', 'README.md']);
|
|
56
|
+
git(repoRoot, ['commit', '-m', 'chore: initial commit']);
|
|
57
|
+
if (!keepLeaderBranchCheckedOut) {
|
|
58
|
+
// Most integration tests do not need the leader branch checked out.
|
|
59
|
+
git(repoRoot, ['checkout', '--detach']);
|
|
60
|
+
}
|
|
61
|
+
// Create worker worktrees
|
|
62
|
+
const workersDir = join(repoRoot, '.omcp', 'team', teamName, 'worktrees');
|
|
63
|
+
mkdirSync(workersDir, { recursive: true });
|
|
64
|
+
const workers = [];
|
|
65
|
+
for (let i = 0; i < workerCount; i++) {
|
|
66
|
+
const workerName = `worker-${i + 1}`;
|
|
67
|
+
const branch = `omc-team/${teamName}/${workerName}`;
|
|
68
|
+
const wtPath = join(workersDir, workerName);
|
|
69
|
+
// Create a new branch and worktree
|
|
70
|
+
git(repoRoot, ['worktree', 'add', '-b', branch, wtPath, leaderBranchName]);
|
|
71
|
+
git(wtPath, ['config', 'user.email', 'test@example.com']);
|
|
72
|
+
git(wtPath, ['config', 'user.name', 'Test User']);
|
|
73
|
+
git(wtPath, ['config', 'commit.gpgsign', 'false']);
|
|
74
|
+
workers.push({ name: workerName, worktreePath: wtPath, branch });
|
|
75
|
+
}
|
|
76
|
+
// Write worktrees.json metadata (needed by listTeamWorktrees / recoverFromRestart)
|
|
77
|
+
const worktreesMetaDir = join(repoRoot, '.omcp', 'state', 'team', teamName);
|
|
78
|
+
mkdirSync(worktreesMetaDir, { recursive: true });
|
|
79
|
+
const worktreesMeta = workers.map((w) => ({
|
|
80
|
+
path: w.worktreePath,
|
|
81
|
+
branch: w.branch,
|
|
82
|
+
workerName: w.name,
|
|
83
|
+
teamName,
|
|
84
|
+
createdAt: new Date().toISOString(),
|
|
85
|
+
repoRoot,
|
|
86
|
+
}));
|
|
87
|
+
writeFileSync(join(worktreesMetaDir, 'worktrees.json'), JSON.stringify(worktreesMeta), 'utf-8');
|
|
88
|
+
let attachedHandle = null;
|
|
89
|
+
return {
|
|
90
|
+
repoRoot,
|
|
91
|
+
leaderBranch: leaderBranchName,
|
|
92
|
+
teamName,
|
|
93
|
+
workers,
|
|
94
|
+
async commitFile(workerName, relPath, content) {
|
|
95
|
+
const worker = workers.find((w) => w.name === workerName);
|
|
96
|
+
if (!worker)
|
|
97
|
+
throw new Error(`No worker named ${workerName}`);
|
|
98
|
+
const filePath = join(worker.worktreePath, relPath);
|
|
99
|
+
mkdirSync(join(worker.worktreePath, relPath.includes('/') ? relPath.split('/').slice(0, -1).join('/') : '.'), { recursive: true });
|
|
100
|
+
writeFileSync(filePath, content, 'utf-8');
|
|
101
|
+
git(worker.worktreePath, ['add', relPath]);
|
|
102
|
+
git(worker.worktreePath, ['commit', '-m', `test: update ${relPath}`]);
|
|
103
|
+
return git(worker.worktreePath, ['rev-parse', 'HEAD']);
|
|
104
|
+
},
|
|
105
|
+
getBranchSha(branch) {
|
|
106
|
+
return git(repoRoot, ['rev-parse', `refs/heads/${branch}`]);
|
|
107
|
+
},
|
|
108
|
+
createRebaseState(workerName) {
|
|
109
|
+
const worker = workers.find((w) => w.name === workerName);
|
|
110
|
+
if (!worker)
|
|
111
|
+
throw new Error(`No worker named ${workerName}`);
|
|
112
|
+
const rebaseMergeDir = git(worker.worktreePath, ['rev-parse', '--git-path', 'rebase-merge']);
|
|
113
|
+
mkdirSync(rebaseMergeDir, { recursive: true });
|
|
114
|
+
writeFileSync(join(rebaseMergeDir, 'head-name'), `refs/heads/${worker.branch}\n`, 'utf-8');
|
|
115
|
+
writeFileSync(join(rebaseMergeDir, 'onto'), 'deadbeef\n', 'utf-8');
|
|
116
|
+
return rebaseMergeDir;
|
|
117
|
+
},
|
|
118
|
+
attachHandle(handle) {
|
|
119
|
+
attachedHandle = handle;
|
|
120
|
+
},
|
|
121
|
+
async simulateRuntimeRestart(orphanWorkerName) {
|
|
122
|
+
// Stop orchestrator without cleanup (simulating crash/restart)
|
|
123
|
+
if (attachedHandle) {
|
|
124
|
+
try {
|
|
125
|
+
await attachedHandle.drainAndStop();
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
// Ignore errors — we're simulating a crash
|
|
129
|
+
}
|
|
130
|
+
attachedHandle = null;
|
|
131
|
+
}
|
|
132
|
+
// Create orphan rebase state in the specified worker worktree's real
|
|
133
|
+
// gitdir. Real git worktrees have a `.git` FILE that points at the
|
|
134
|
+
// main repository metadata; `git rev-parse --git-path rebase-merge` is
|
|
135
|
+
// the gitdir-aware way to locate the marker path.
|
|
136
|
+
if (orphanWorkerName) {
|
|
137
|
+
const worker = workers.find((w) => w.name === orphanWorkerName);
|
|
138
|
+
if (!worker)
|
|
139
|
+
throw new Error(`No worker named ${orphanWorkerName}`);
|
|
140
|
+
const rebaseMergeDir = git(worker.worktreePath, ['rev-parse', '--git-path', 'rebase-merge']);
|
|
141
|
+
mkdirSync(rebaseMergeDir, { recursive: true });
|
|
142
|
+
writeFileSync(join(rebaseMergeDir, 'head-name'), `refs/heads/${worker.branch}\n`, 'utf-8');
|
|
143
|
+
writeFileSync(join(rebaseMergeDir, 'onto'), 'deadbeef\n', 'utf-8');
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
async cleanup() {
|
|
147
|
+
// Detach all worktrees first (best-effort)
|
|
148
|
+
try {
|
|
149
|
+
for (const w of workers) {
|
|
150
|
+
try {
|
|
151
|
+
git(repoRoot, ['worktree', 'remove', '--force', w.worktreePath]);
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
// ignore
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
// Remove merger worktree if it exists
|
|
158
|
+
const mergerPath = join(repoRoot, '.omcp', 'team', teamName, 'merger');
|
|
159
|
+
if (existsSync(mergerPath)) {
|
|
160
|
+
try {
|
|
161
|
+
git(repoRoot, ['worktree', 'remove', '--force', mergerPath]);
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
// ignore
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
// ignore cleanup errors
|
|
170
|
+
}
|
|
171
|
+
// Use rm -rf via shell to avoid Node's multi-step recursive walk racing
|
|
172
|
+
// with concurrent git object writes (ENOTEMPTY race under vitest threads).
|
|
173
|
+
execFileSync('rm', ['-rf', tmpBase], { stdio: 'pipe' });
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
export async function waitForEventInLog(opts) {
|
|
178
|
+
const { eventLogPath, eventType, count = 1, timeoutMs = 10000, worker } = opts;
|
|
179
|
+
await new Promise((r) => setTimeout(r, 250));
|
|
180
|
+
const deadline = Date.now() + timeoutMs;
|
|
181
|
+
while (Date.now() < deadline) {
|
|
182
|
+
if (existsSync(eventLogPath)) {
|
|
183
|
+
try {
|
|
184
|
+
const raw = readFileSync(eventLogPath, 'utf-8');
|
|
185
|
+
if (raw.includes(eventType) && (worker === undefined || raw.includes(worker))) {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
const lines = raw
|
|
189
|
+
.split('\n')
|
|
190
|
+
.filter((l) => l.trim().length > 0);
|
|
191
|
+
const events = lines.map((l) => {
|
|
192
|
+
try {
|
|
193
|
+
return JSON.parse(l);
|
|
194
|
+
}
|
|
195
|
+
catch {
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
}).filter(Boolean);
|
|
199
|
+
const matching = events.filter((e) => e.type === eventType && (worker === undefined || e.worker === worker));
|
|
200
|
+
if (matching.length >= count)
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
// file being written — retry
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
await new Promise((r) => setTimeout(r, 50));
|
|
208
|
+
}
|
|
209
|
+
// Provide helpful diagnostic on timeout
|
|
210
|
+
let found = 0;
|
|
211
|
+
if (existsSync(eventLogPath)) {
|
|
212
|
+
try {
|
|
213
|
+
const lines = readFileSync(eventLogPath, 'utf-8')
|
|
214
|
+
.split('\n')
|
|
215
|
+
.filter((l) => l.trim().length > 0);
|
|
216
|
+
found = lines.filter((l) => l.includes(`"${eventType}"`)).length;
|
|
217
|
+
}
|
|
218
|
+
catch {
|
|
219
|
+
// ignore
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
throw new Error(`waitForEventInLog: timed out after ${timeoutMs}ms waiting for ${count}x "${eventType}"` +
|
|
223
|
+
(worker ? ` (worker=${worker})` : '') +
|
|
224
|
+
`. Found ${found}.`);
|
|
225
|
+
}
|
|
226
|
+
/** Read all events from the orchestrator event log. */
|
|
227
|
+
export function readEventLog(eventLogPath) {
|
|
228
|
+
if (!existsSync(eventLogPath))
|
|
229
|
+
return [];
|
|
230
|
+
try {
|
|
231
|
+
return readFileSync(eventLogPath, 'utf-8')
|
|
232
|
+
.split('\n')
|
|
233
|
+
.filter((l) => l.trim().length > 0)
|
|
234
|
+
.map((l) => {
|
|
235
|
+
try {
|
|
236
|
+
return JSON.parse(l);
|
|
237
|
+
}
|
|
238
|
+
catch {
|
|
239
|
+
return null;
|
|
240
|
+
}
|
|
241
|
+
})
|
|
242
|
+
.filter(Boolean);
|
|
243
|
+
}
|
|
244
|
+
catch {
|
|
245
|
+
return [];
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
/** Build the event log path for a team. */
|
|
249
|
+
export function orchestratorEventLogPath(repoRoot, teamName) {
|
|
250
|
+
return join(repoRoot, '.omcp', 'state', 'team', teamName, 'orchestrator-events.jsonl');
|
|
251
|
+
}
|
|
252
|
+
//# sourceMappingURL=git-fixture.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-fixture.js","sourceRoot":"","sources":["../../../../src/team/__tests__/helpers/git-fixture.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"leader-inbox.test.d.ts","sourceRoot":"","sources":["../../../src/team/__tests__/leader-inbox.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import { mkdirSync, readFileSync, rmSync, existsSync, realpathSync } from 'fs';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { tmpdir } from 'os';
|
|
5
|
+
import { leaderInboxPath, ensureLeaderInbox, appendToLeaderInbox, extendLeaderBootstrapPrompt, } from '../leader-inbox.js';
|
|
6
|
+
const TEST_CWD = join(tmpdir(), `omc-test-leader-inbox-${process.pid}`);
|
|
7
|
+
const TEST_TEAM = 'my-team';
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
mkdirSync(TEST_CWD, { recursive: true });
|
|
10
|
+
});
|
|
11
|
+
afterEach(() => {
|
|
12
|
+
rmSync(TEST_CWD, { recursive: true, force: true });
|
|
13
|
+
});
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
// leaderInboxPath — pure, path correctness, sanitization
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
describe('leaderInboxPath', () => {
|
|
18
|
+
it('returns correct path under cwd', () => {
|
|
19
|
+
const p = leaderInboxPath(TEST_TEAM, TEST_CWD);
|
|
20
|
+
expect(p).toBe(join(TEST_CWD, '.omcp/state/team/my-team/leader/inbox.md'));
|
|
21
|
+
});
|
|
22
|
+
it('sanitizes team name (strips special chars)', () => {
|
|
23
|
+
// sanitizeName strips non-alphanumeric/dash/underscore chars
|
|
24
|
+
const p = leaderInboxPath('my team!', TEST_CWD);
|
|
25
|
+
expect(p).not.toContain('!');
|
|
26
|
+
expect(p).not.toContain(' ');
|
|
27
|
+
expect(p).toContain(join('leader', 'inbox.md'));
|
|
28
|
+
});
|
|
29
|
+
it('prevents traversal via team name: dots and slashes stripped', () => {
|
|
30
|
+
// sanitizeName turns '../../../etc' into 'etc', so path stays under cwd
|
|
31
|
+
const p = leaderInboxPath('../../../etc', TEST_CWD);
|
|
32
|
+
expect(p).not.toContain('..');
|
|
33
|
+
expect(p.startsWith(TEST_CWD)).toBe(true);
|
|
34
|
+
});
|
|
35
|
+
it('is pure: same input → same output', () => {
|
|
36
|
+
expect(leaderInboxPath(TEST_TEAM, TEST_CWD)).toBe(leaderInboxPath(TEST_TEAM, TEST_CWD));
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
// ensureLeaderInbox
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
describe('ensureLeaderInbox', () => {
|
|
43
|
+
it('creates the leader directory', async () => {
|
|
44
|
+
await ensureLeaderInbox(TEST_TEAM, TEST_CWD);
|
|
45
|
+
const dir = join(TEST_CWD, '.omcp/state/team/my-team/leader');
|
|
46
|
+
expect(existsSync(dir)).toBe(true);
|
|
47
|
+
});
|
|
48
|
+
it('creates inbox.md with header content', async () => {
|
|
49
|
+
const path = await ensureLeaderInbox(TEST_TEAM, TEST_CWD);
|
|
50
|
+
expect(existsSync(path)).toBe(true);
|
|
51
|
+
const content = readFileSync(path, 'utf-8');
|
|
52
|
+
expect(content).toContain('# Leader Inbox');
|
|
53
|
+
});
|
|
54
|
+
it('returns the absolute path to inbox.md', async () => {
|
|
55
|
+
const path = await ensureLeaderInbox(TEST_TEAM, TEST_CWD);
|
|
56
|
+
expect(path).toBe(leaderInboxPath(TEST_TEAM, TEST_CWD));
|
|
57
|
+
});
|
|
58
|
+
it('is idempotent: calling twice does not throw or overwrite content', async () => {
|
|
59
|
+
const path = await ensureLeaderInbox(TEST_TEAM, TEST_CWD);
|
|
60
|
+
// Append something to verify it isn't overwritten
|
|
61
|
+
const { appendFileSync } = await import('fs');
|
|
62
|
+
appendFileSync(path, '\n\n---\nextra content', 'utf-8');
|
|
63
|
+
// Call again — should not overwrite
|
|
64
|
+
await ensureLeaderInbox(TEST_TEAM, TEST_CWD);
|
|
65
|
+
const content = readFileSync(path, 'utf-8');
|
|
66
|
+
expect(content).toContain('extra content');
|
|
67
|
+
});
|
|
68
|
+
it('path is within cwd (no traversal)', async () => {
|
|
69
|
+
const path = await ensureLeaderInbox(TEST_TEAM, TEST_CWD);
|
|
70
|
+
const realCwd = realpathSync(TEST_CWD);
|
|
71
|
+
expect(path.startsWith(realCwd) || path.startsWith(TEST_CWD)).toBe(true);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
// ---------------------------------------------------------------------------
|
|
75
|
+
// appendToLeaderInbox
|
|
76
|
+
// ---------------------------------------------------------------------------
|
|
77
|
+
describe('appendToLeaderInbox', () => {
|
|
78
|
+
it('appends message with \\n\\n---\\n separator', async () => {
|
|
79
|
+
await appendToLeaderInbox(TEST_TEAM, 'hello leader', TEST_CWD);
|
|
80
|
+
const path = leaderInboxPath(TEST_TEAM, TEST_CWD);
|
|
81
|
+
const content = readFileSync(path, 'utf-8');
|
|
82
|
+
expect(content).toBe('\n\n---\nhello leader');
|
|
83
|
+
});
|
|
84
|
+
it('uses same delimiter as worker-bootstrap appendToInbox', async () => {
|
|
85
|
+
// The delimiter is exactly `\n\n---\n` — verify character-for-character
|
|
86
|
+
await appendToLeaderInbox(TEST_TEAM, 'msg', TEST_CWD);
|
|
87
|
+
const path = leaderInboxPath(TEST_TEAM, TEST_CWD);
|
|
88
|
+
const content = readFileSync(path, 'utf-8');
|
|
89
|
+
expect(content.startsWith('\n\n---\n')).toBe(true);
|
|
90
|
+
});
|
|
91
|
+
it('appends multiple messages sequentially', async () => {
|
|
92
|
+
await appendToLeaderInbox(TEST_TEAM, 'first', TEST_CWD);
|
|
93
|
+
await appendToLeaderInbox(TEST_TEAM, 'second', TEST_CWD);
|
|
94
|
+
const path = leaderInboxPath(TEST_TEAM, TEST_CWD);
|
|
95
|
+
const content = readFileSync(path, 'utf-8');
|
|
96
|
+
expect(content).toContain('first');
|
|
97
|
+
expect(content).toContain('second');
|
|
98
|
+
// Two separators
|
|
99
|
+
const separatorCount = (content.match(/\n\n---\n/g) ?? []).length;
|
|
100
|
+
expect(separatorCount).toBe(2);
|
|
101
|
+
});
|
|
102
|
+
it('creates parent directories if missing', async () => {
|
|
103
|
+
// Fresh cwd with no pre-existing dirs
|
|
104
|
+
const freshCwd = join(tmpdir(), `omc-test-leader-inbox-fresh-${process.pid}`);
|
|
105
|
+
try {
|
|
106
|
+
mkdirSync(freshCwd, { recursive: true });
|
|
107
|
+
await appendToLeaderInbox('newteam', 'msg', freshCwd);
|
|
108
|
+
const path = leaderInboxPath('newteam', freshCwd);
|
|
109
|
+
expect(existsSync(path)).toBe(true);
|
|
110
|
+
}
|
|
111
|
+
finally {
|
|
112
|
+
rmSync(freshCwd, { recursive: true, force: true });
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
// ---------------------------------------------------------------------------
|
|
117
|
+
// extendLeaderBootstrapPrompt
|
|
118
|
+
// ---------------------------------------------------------------------------
|
|
119
|
+
describe('extendLeaderBootstrapPrompt', () => {
|
|
120
|
+
it('contains the canonical leader inbox path', () => {
|
|
121
|
+
const prompt = extendLeaderBootstrapPrompt(TEST_TEAM);
|
|
122
|
+
expect(prompt).toContain('.omcp/state/team/my-team/leader/inbox.md');
|
|
123
|
+
});
|
|
124
|
+
it('contains "check this file" instruction', () => {
|
|
125
|
+
const prompt = extendLeaderBootstrapPrompt(TEST_TEAM);
|
|
126
|
+
expect(prompt.toLowerCase()).toContain('check this file');
|
|
127
|
+
});
|
|
128
|
+
it('is pure: same input → same output', () => {
|
|
129
|
+
expect(extendLeaderBootstrapPrompt(TEST_TEAM)).toBe(extendLeaderBootstrapPrompt(TEST_TEAM));
|
|
130
|
+
});
|
|
131
|
+
it('sanitizes team name in the path', () => {
|
|
132
|
+
const prompt = extendLeaderBootstrapPrompt('my team!');
|
|
133
|
+
// The prompt sentence contains spaces (natural language), but the embedded
|
|
134
|
+
// team-name segment of the path must not contain '!' or spaces.
|
|
135
|
+
expect(prompt).not.toContain('!');
|
|
136
|
+
// Extract the path segment from the prompt and verify no spaces in it
|
|
137
|
+
const pathMatch = prompt.match(/\.omcp\/state\/team\/([^/]+)\/leader\/inbox\.md/);
|
|
138
|
+
expect(pathMatch).not.toBeNull();
|
|
139
|
+
expect(pathMatch[1]).not.toContain('!');
|
|
140
|
+
expect(pathMatch[1]).not.toContain(' ');
|
|
141
|
+
});
|
|
142
|
+
it('path in prompt matches leaderInboxPath relative segment', () => {
|
|
143
|
+
const prompt = extendLeaderBootstrapPrompt(TEST_TEAM);
|
|
144
|
+
const fullPath = leaderInboxPath(TEST_TEAM, TEST_CWD);
|
|
145
|
+
// The prompt uses relative path; fullPath has cwd prefix
|
|
146
|
+
const relSegmentNative = join('.omcp', 'state', 'team', 'my-team', 'leader', 'inbox.md');
|
|
147
|
+
const relSegmentPosix = `.omcp/state/team/my-team/leader/inbox.md`;
|
|
148
|
+
expect(fullPath).toContain(relSegmentNative);
|
|
149
|
+
expect(prompt).toContain(relSegmentPosix);
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
//# sourceMappingURL=leader-inbox.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"leader-inbox.test.js","sourceRoot":"","sources":["../../../src/team/__tests__/leader-inbox.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge-orchestrator.test.d.ts","sourceRoot":"","sources":["../../../src/team/__tests__/merge-orchestrator.test.ts"],"names":[],"mappings":""}
|