oxe-cc 1.2.1 → 1.4.0
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/.cursor/commands/oxe-ask.md +2 -2
- package/.cursor/commands/oxe-capabilities.md +2 -2
- package/.cursor/commands/oxe-checkpoint.md +2 -2
- package/.cursor/commands/oxe-compact.md +2 -2
- package/.cursor/commands/oxe-dashboard.md +2 -2
- package/.cursor/commands/oxe-debug.md +2 -2
- package/.cursor/commands/oxe-discuss.md +2 -2
- package/.cursor/commands/oxe-execute.md +5 -2
- package/.cursor/commands/oxe-forensics.md +2 -2
- package/.cursor/commands/oxe-help.md +2 -2
- package/.cursor/commands/oxe-loop.md +2 -2
- package/.cursor/commands/oxe-milestone.md +2 -2
- package/.cursor/commands/oxe-next.md +2 -2
- package/.cursor/commands/oxe-obs.md +2 -2
- package/.cursor/commands/oxe-plan-agent.md +2 -2
- package/.cursor/commands/oxe-plan.md +2 -2
- package/.cursor/commands/oxe-project.md +2 -2
- package/.cursor/commands/oxe-quick.md +2 -2
- package/.cursor/commands/oxe-research.md +2 -2
- package/.cursor/commands/oxe-retro.md +2 -2
- package/.cursor/commands/oxe-review-pr.md +2 -2
- package/.cursor/commands/oxe-route.md +2 -2
- package/.cursor/commands/oxe-scan.md +2 -2
- package/.cursor/commands/oxe-security.md +2 -2
- package/.cursor/commands/oxe-session.md +2 -2
- package/.cursor/commands/oxe-ship.md +2 -2
- package/.cursor/commands/oxe-skill.md +2 -2
- package/.cursor/commands/oxe-spec.md +2 -2
- package/.cursor/commands/oxe-ui-review.md +2 -2
- package/.cursor/commands/oxe-ui-spec.md +2 -2
- package/.cursor/commands/oxe-update.md +2 -2
- package/.cursor/commands/oxe-validate-gaps.md +2 -2
- package/.cursor/commands/oxe-verify.md +5 -2
- package/.cursor/commands/oxe-workstream.md +2 -2
- package/.cursor/commands/oxe.md +2 -2
- package/.github/copilot-instructions.md +13 -13
- package/.github/prompts/oxe-ask.prompt.md +2 -2
- package/.github/prompts/oxe-capabilities.prompt.md +2 -2
- package/.github/prompts/oxe-checkpoint.prompt.md +2 -2
- package/.github/prompts/oxe-compact.prompt.md +2 -2
- package/.github/prompts/oxe-dashboard.prompt.md +2 -2
- package/.github/prompts/oxe-debug.prompt.md +2 -2
- package/.github/prompts/oxe-discuss.prompt.md +2 -2
- package/.github/prompts/oxe-execute.prompt.md +5 -2
- package/.github/prompts/oxe-forensics.prompt.md +2 -2
- package/.github/prompts/oxe-help.prompt.md +2 -2
- package/.github/prompts/oxe-loop.prompt.md +2 -2
- package/.github/prompts/oxe-milestone.prompt.md +2 -2
- package/.github/prompts/oxe-next.prompt.md +2 -2
- package/.github/prompts/oxe-obs.prompt.md +2 -2
- package/.github/prompts/oxe-plan-agent.prompt.md +2 -2
- package/.github/prompts/oxe-plan.prompt.md +2 -2
- package/.github/prompts/oxe-project.prompt.md +2 -2
- package/.github/prompts/oxe-quick.prompt.md +2 -2
- package/.github/prompts/oxe-research.prompt.md +2 -2
- package/.github/prompts/oxe-retro.prompt.md +2 -2
- package/.github/prompts/oxe-review-pr.prompt.md +2 -2
- package/.github/prompts/oxe-route.prompt.md +2 -2
- package/.github/prompts/oxe-scan.prompt.md +2 -2
- package/.github/prompts/oxe-security.prompt.md +2 -2
- package/.github/prompts/oxe-session.prompt.md +2 -2
- package/.github/prompts/oxe-ship.prompt.md +2 -2
- package/.github/prompts/oxe-skill.prompt.md +2 -2
- package/.github/prompts/oxe-spec.prompt.md +2 -2
- package/.github/prompts/oxe-ui-review.prompt.md +2 -2
- package/.github/prompts/oxe-ui-spec.prompt.md +2 -2
- package/.github/prompts/oxe-update.prompt.md +2 -2
- package/.github/prompts/oxe-validate-gaps.prompt.md +2 -2
- package/.github/prompts/oxe-verify.prompt.md +5 -2
- package/.github/prompts/oxe-workstream.prompt.md +2 -2
- package/.github/prompts/oxe.prompt.md +2 -2
- package/AGENTS.md +5 -3
- package/CHANGELOG.md +72 -10
- package/LICENSE +21 -674
- package/README.md +631 -535
- package/bin/banner.txt +6 -6
- package/bin/lib/oxe-agent-install.cjs +69 -69
- package/bin/lib/oxe-azure.cjs +1445 -1445
- package/bin/lib/oxe-context-engine.cjs +867 -867
- package/bin/lib/oxe-dashboard.cjs +76 -28
- package/bin/lib/oxe-operational.cjs +2144 -1340
- package/bin/lib/oxe-project-health.cjs +483 -1
- package/bin/lib/oxe-runtime-semantics.cjs +12 -0
- package/bin/oxe-cc.js +554 -152
- package/commands/oxe/ask.md +2 -2
- package/commands/oxe/capabilities.md +2 -2
- package/commands/oxe/checkpoint.md +2 -2
- package/commands/oxe/compact.md +2 -2
- package/commands/oxe/dashboard.md +2 -2
- package/commands/oxe/debug.md +2 -2
- package/commands/oxe/discuss.md +2 -2
- package/commands/oxe/execute.md +5 -2
- package/commands/oxe/forensics.md +2 -2
- package/commands/oxe/help.md +2 -2
- package/commands/oxe/loop.md +2 -2
- package/commands/oxe/milestone.md +2 -2
- package/commands/oxe/next.md +2 -2
- package/commands/oxe/obs.md +2 -2
- package/commands/oxe/oxe.md +2 -2
- package/commands/oxe/plan-agent.md +2 -2
- package/commands/oxe/plan.md +2 -2
- package/commands/oxe/project.md +2 -2
- package/commands/oxe/quick.md +2 -2
- package/commands/oxe/research.md +2 -2
- package/commands/oxe/retro.md +2 -2
- package/commands/oxe/review-pr.md +2 -2
- package/commands/oxe/route.md +2 -2
- package/commands/oxe/scan.md +2 -2
- package/commands/oxe/security.md +2 -2
- package/commands/oxe/session.md +2 -2
- package/commands/oxe/ship.md +2 -2
- package/commands/oxe/skill.md +2 -2
- package/commands/oxe/spec.md +2 -2
- package/commands/oxe/ui-review.md +2 -2
- package/commands/oxe/ui-spec.md +2 -2
- package/commands/oxe/update.md +2 -2
- package/commands/oxe/validate-gaps.md +2 -2
- package/commands/oxe/verify.md +5 -2
- package/commands/oxe/workstream.md +2 -2
- package/lib/runtime/delivery/branch-manager.d.ts +1 -0
- package/lib/runtime/delivery/branch-manager.js +7 -0
- package/lib/runtime/delivery/ci-checks.js +34 -1
- package/lib/runtime/delivery/delivery-records.d.ts +34 -0
- package/lib/runtime/delivery/delivery-records.js +48 -0
- package/lib/runtime/delivery/index.d.ts +1 -0
- package/lib/runtime/delivery/index.js +1 -0
- package/lib/runtime/delivery/promotion-pipeline.d.ts +26 -2
- package/lib/runtime/delivery/promotion-pipeline.js +111 -14
- package/lib/runtime/gate/gate-manager.d.ts +41 -0
- package/lib/runtime/gate/gate-manager.js +108 -1
- package/lib/runtime/index.d.ts +2 -2
- package/lib/runtime/index.js +3 -1
- package/lib/runtime/models/gate-decision.d.ts +4 -1
- package/lib/runtime/models/workspace.d.ts +3 -0
- package/lib/runtime/plugins/capability-adapter.d.ts +12 -0
- package/lib/runtime/plugins/capability-adapter.js +204 -0
- package/lib/runtime/plugins/capability-matrix.d.ts +5 -0
- package/lib/runtime/plugins/capability-matrix.js +48 -17
- package/lib/runtime/plugins/index.d.ts +1 -0
- package/lib/runtime/plugins/index.js +1 -0
- package/lib/runtime/plugins/plugin-abi.d.ts +2 -0
- package/lib/runtime/plugins/plugin-manifest.d.ts +1 -1
- package/lib/runtime/plugins/plugin-manifest.js +6 -2
- package/lib/runtime/plugins/plugin-registry.d.ts +46 -0
- package/lib/runtime/plugins/plugin-registry.js +79 -2
- package/lib/runtime/policy/policy-engine.d.ts +19 -0
- package/lib/runtime/policy/policy-engine.js +76 -4
- package/lib/runtime/projection/projection-engine.d.ts +9 -1
- package/lib/runtime/projection/projection-engine.js +73 -3
- package/lib/runtime/scheduler/multi-agent-coordinator.d.ts +43 -1
- package/lib/runtime/scheduler/multi-agent-coordinator.js +151 -39
- package/lib/runtime/scheduler/run-journal.d.ts +1 -1
- package/lib/runtime/scheduler/scheduler.d.ts +19 -1
- package/lib/runtime/scheduler/scheduler.js +258 -13
- package/lib/runtime/verification/verification-compiler.d.ts +43 -0
- package/lib/runtime/verification/verification-compiler.js +137 -0
- package/lib/runtime/verification/verification-manifest.d.ts +9 -0
- package/lib/runtime/verification/verification-manifest.js +56 -6
- package/lib/runtime/workspace/strategies/ephemeral-container.d.ts +1 -0
- package/lib/runtime/workspace/strategies/ephemeral-container.js +4 -0
- package/lib/runtime/workspace/strategies/git-worktree.d.ts +1 -0
- package/lib/runtime/workspace/strategies/git-worktree.js +2 -0
- package/lib/runtime/workspace/strategies/inplace.d.ts +1 -0
- package/lib/runtime/workspace/strategies/inplace.js +2 -0
- package/lib/runtime/workspace/workspace-manager.d.ts +2 -1
- package/lib/sdk/README.md +20 -8
- package/lib/sdk/index.cjs +33 -24
- package/lib/sdk/index.d.ts +149 -14
- package/oxe/templates/ACTIVE-RUN.template.json +32 -32
- package/oxe/templates/CAPABILITIES.template.md +7 -7
- package/oxe/templates/CAPABILITY.template.md +45 -45
- package/oxe/templates/CHECKPOINTS.template.md +7 -7
- package/oxe/templates/EXECUTION-RUNTIME.template.md +68 -68
- package/oxe/templates/HYPOTHESES.template.md +33 -33
- package/oxe/templates/LESSONS-METRICS.template.json +13 -13
- package/oxe/templates/NOTES.template.md +16 -16
- package/oxe/templates/PLAN-REVIEW.template.md +31 -31
- package/oxe/templates/SESSION.template.md +34 -34
- package/oxe/templates/SKILL.template.md +26 -26
- package/oxe/templates/STATE.md +55 -55
- package/oxe/templates/WORKFLOW_AUTHORING.md +18 -18
- package/oxe/workflows/ask.md +96 -96
- package/oxe/workflows/capabilities.md +25 -25
- package/oxe/workflows/dashboard.md +33 -33
- package/oxe/workflows/discuss.md +12 -12
- package/oxe/workflows/execute.md +14 -0
- package/oxe/workflows/help.md +352 -352
- package/oxe/workflows/next.md +22 -22
- package/oxe/workflows/oxe.md +6 -6
- package/oxe/workflows/plan-agent.md +9 -9
- package/oxe/workflows/plan.md +51 -20
- package/oxe/workflows/quick.md +10 -10
- package/oxe/workflows/references/reasoning-discovery.md +28 -28
- package/oxe/workflows/references/reasoning-execution.md +29 -29
- package/oxe/workflows/references/reasoning-planning.md +32 -32
- package/oxe/workflows/references/reasoning-review.md +29 -29
- package/oxe/workflows/references/reasoning-status.md +24 -24
- package/oxe/workflows/references/robustness-elevation.md +295 -295
- package/oxe/workflows/references/workflow-runtime-contracts.json +952 -930
- package/oxe/workflows/route.md +16 -16
- package/oxe/workflows/session.md +213 -213
- package/oxe/workflows/ship.md +142 -142
- package/oxe/workflows/skill.md +44 -44
- package/oxe/workflows/ui-review.md +36 -36
- package/oxe/workflows/verify-audit.md +73 -73
- package/oxe/workflows/verify.md +10 -0
- package/package.json +92 -92
- package/packages/runtime/package.json +16 -15
- package/packages/runtime/src/audit/audit-trail.ts +243 -243
- package/packages/runtime/src/audit/index.ts +2 -2
- package/packages/runtime/src/audit/policy-pack.ts +62 -62
- package/packages/runtime/src/compiler/graph-compiler.ts +245 -245
- package/packages/runtime/src/compiler/index.ts +1 -1
- package/packages/runtime/src/context/context-pack-builder.ts +259 -259
- package/packages/runtime/src/context/context-pack-store.ts +197 -197
- package/packages/runtime/src/context/context-profiles.ts +60 -60
- package/packages/runtime/src/context/index.ts +3 -3
- package/packages/runtime/src/decision/decision-engine.ts +174 -174
- package/packages/runtime/src/decision/decision-memo.ts +211 -211
- package/packages/runtime/src/decision/index.ts +2 -2
- package/packages/runtime/src/delivery/branch-manager.ts +91 -84
- package/packages/runtime/src/delivery/ci-checks.ts +285 -252
- package/packages/runtime/src/delivery/delivery-records.ts +75 -0
- package/packages/runtime/src/delivery/index.ts +5 -4
- package/packages/runtime/src/delivery/pr-manager.ts +112 -112
- package/packages/runtime/src/delivery/promotion-pipeline.ts +334 -180
- package/packages/runtime/src/events/bus.ts +92 -92
- package/packages/runtime/src/events/catalog.ts +29 -29
- package/packages/runtime/src/events/envelope.ts +14 -14
- package/packages/runtime/src/events/index.ts +3 -3
- package/packages/runtime/src/evidence/evidence-store.ts +130 -130
- package/packages/runtime/src/evidence/index.ts +1 -1
- package/packages/runtime/src/gate/gate-manager.ts +289 -137
- package/packages/runtime/src/gate/index.ts +1 -1
- package/packages/runtime/src/index.ts +41 -37
- package/packages/runtime/src/models/attempt.ts +19 -19
- package/packages/runtime/src/models/evidence.ts +21 -21
- package/packages/runtime/src/models/gate-decision.ts +25 -21
- package/packages/runtime/src/models/index.ts +8 -8
- package/packages/runtime/src/models/run.ts +24 -24
- package/packages/runtime/src/models/session.ts +11 -11
- package/packages/runtime/src/models/verification-result.ts +10 -10
- package/packages/runtime/src/models/work-item.ts +25 -25
- package/packages/runtime/src/models/workspace.ts +31 -28
- package/packages/runtime/src/plugins/capability-adapter.ts +206 -0
- package/packages/runtime/src/plugins/capability-matrix.ts +126 -83
- package/packages/runtime/src/plugins/index.ts +5 -4
- package/packages/runtime/src/plugins/plugin-abi.ts +97 -95
- package/packages/runtime/src/plugins/plugin-manifest.ts +118 -113
- package/packages/runtime/src/plugins/plugin-registry.ts +232 -124
- package/packages/runtime/src/policy/index.ts +1 -1
- package/packages/runtime/src/policy/policy-engine.ts +330 -244
- package/packages/runtime/src/projection/index.ts +1 -1
- package/packages/runtime/src/projection/projection-engine.ts +328 -249
- package/packages/runtime/src/reducers/debug-reducer.ts +36 -36
- package/packages/runtime/src/reducers/index.ts +2 -2
- package/packages/runtime/src/reducers/run-state-reducer.ts +269 -269
- package/packages/runtime/src/scheduler/agent-registry.ts +132 -132
- package/packages/runtime/src/scheduler/agent-roles.ts +109 -109
- package/packages/runtime/src/scheduler/index.ts +4 -4
- package/packages/runtime/src/scheduler/multi-agent-coordinator.ts +521 -333
- package/packages/runtime/src/scheduler/run-journal.ts +62 -62
- package/packages/runtime/src/scheduler/scheduler.ts +722 -441
- package/packages/runtime/src/verification/index.ts +2 -2
- package/packages/runtime/src/verification/verification-compiler.ts +436 -225
- package/packages/runtime/src/verification/verification-manifest.ts +252 -192
- package/packages/runtime/src/workspace/index.ts +5 -5
- package/packages/runtime/src/workspace/strategies/ephemeral-container.ts +126 -121
- package/packages/runtime/src/workspace/strategies/git-worktree.ts +79 -77
- package/packages/runtime/src/workspace/strategies/inplace.ts +38 -35
- package/packages/runtime/src/workspace/workspace-manager.ts +16 -15
- package/packages/runtime/tsconfig.json +17 -17
- package/vscode-extension/.vscodeignore +7 -7
- package/vscode-extension/LICENSE +21 -0
- package/vscode-extension/oxe-agents-1.0.0.vsix +0 -0
- package/vscode-extension/oxe-agents-1.4.0.vsix +0 -0
- package/vscode-extension/package.json +184 -184
- package/vscode-extension/src/extension.js +310 -310
- package/vscode-extension/src/shared/contextLoader.js +137 -137
- package/vscode-extension/src/shared/contractBuilder.js +159 -159
- package/vscode-extension/src/shared/stateReader.js +101 -101
|
@@ -1,121 +1,126 @@
|
|
|
1
|
-
import { execFileSync, spawnSync } from 'child_process';
|
|
2
|
-
import crypto from 'crypto';
|
|
3
|
-
import type { WorkspaceManager, WorkspaceRequest } from '../workspace-manager';
|
|
4
|
-
import type { WorkspaceLease, SnapshotRef } from '../../models/workspace';
|
|
5
|
-
import { GitWorktreeManager } from './git-worktree';
|
|
6
|
-
|
|
7
|
-
export interface ContainerOptions {
|
|
8
|
-
image: string;
|
|
9
|
-
mountPath: string;
|
|
10
|
-
extraEnv?: Record<string, string>;
|
|
11
|
-
/** Gracefully fall back to git_worktree if Docker is unavailable */
|
|
12
|
-
fallback?: boolean;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
function isDockerAvailable(): boolean {
|
|
16
|
-
const result = spawnSync('docker', ['version', '--format', '{{.Server.Version}}'], {
|
|
17
|
-
encoding: 'utf8',
|
|
18
|
-
timeout: 5000,
|
|
19
|
-
});
|
|
20
|
-
return result.status === 0;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export class EphemeralContainerManager implements WorkspaceManager {
|
|
24
|
-
private readonly fallbackManager: GitWorktreeManager;
|
|
25
|
-
private containerIds = new Map<string, string>();
|
|
26
|
-
private useFallback = false;
|
|
27
|
-
|
|
28
|
-
constructor(
|
|
29
|
-
private readonly projectRoot: string,
|
|
30
|
-
private readonly opts: ContainerOptions = { image: 'node:20-alpine', mountPath: '/workspace', fallback: true }
|
|
31
|
-
) {
|
|
32
|
-
this.fallbackManager = new GitWorktreeManager(projectRoot);
|
|
33
|
-
if (!isDockerAvailable()) {
|
|
34
|
-
if (opts.fallback !== false) {
|
|
35
|
-
this.useFallback = true;
|
|
36
|
-
} else {
|
|
37
|
-
throw new Error('Docker is not available and fallback is disabled');
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
get
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
'
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
this.
|
|
120
|
-
|
|
121
|
-
|
|
1
|
+
import { execFileSync, spawnSync } from 'child_process';
|
|
2
|
+
import crypto from 'crypto';
|
|
3
|
+
import type { WorkspaceManager, WorkspaceRequest } from '../workspace-manager';
|
|
4
|
+
import type { WorkspaceLease, SnapshotRef } from '../../models/workspace';
|
|
5
|
+
import { GitWorktreeManager } from './git-worktree';
|
|
6
|
+
|
|
7
|
+
export interface ContainerOptions {
|
|
8
|
+
image: string;
|
|
9
|
+
mountPath: string;
|
|
10
|
+
extraEnv?: Record<string, string>;
|
|
11
|
+
/** Gracefully fall back to git_worktree if Docker is unavailable */
|
|
12
|
+
fallback?: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function isDockerAvailable(): boolean {
|
|
16
|
+
const result = spawnSync('docker', ['version', '--format', '{{.Server.Version}}'], {
|
|
17
|
+
encoding: 'utf8',
|
|
18
|
+
timeout: 5000,
|
|
19
|
+
});
|
|
20
|
+
return result.status === 0;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export class EphemeralContainerManager implements WorkspaceManager {
|
|
24
|
+
private readonly fallbackManager: GitWorktreeManager;
|
|
25
|
+
private containerIds = new Map<string, string>();
|
|
26
|
+
private useFallback = false;
|
|
27
|
+
|
|
28
|
+
constructor(
|
|
29
|
+
private readonly projectRoot: string,
|
|
30
|
+
private readonly opts: ContainerOptions = { image: 'node:20-alpine', mountPath: '/workspace', fallback: true }
|
|
31
|
+
) {
|
|
32
|
+
this.fallbackManager = new GitWorktreeManager(projectRoot);
|
|
33
|
+
if (!isDockerAvailable()) {
|
|
34
|
+
if (opts.fallback !== false) {
|
|
35
|
+
this.useFallback = true;
|
|
36
|
+
} else {
|
|
37
|
+
throw new Error('Docker is not available and fallback is disabled');
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
get isolation_level(): 'shared' | 'isolated' {
|
|
43
|
+
return this.useFallback ? this.fallbackManager.isolation_level : 'isolated';
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
get usingFallback(): boolean { return this.useFallback; }
|
|
47
|
+
|
|
48
|
+
async allocate(req: WorkspaceRequest): Promise<WorkspaceLease> {
|
|
49
|
+
if (this.useFallback) return this.fallbackManager.allocate(req);
|
|
50
|
+
|
|
51
|
+
const wsId = `ws-container-${req.work_item_id}-a${req.attempt_number}`;
|
|
52
|
+
const envArgs = Object.entries(this.opts.extraEnv ?? {}).flatMap(([k, v]) => ['-e', `${k}=${v}`]);
|
|
53
|
+
|
|
54
|
+
const result = spawnSync('docker', [
|
|
55
|
+
'run', '-d',
|
|
56
|
+
'-v', `${this.projectRoot}:${this.opts.mountPath}`,
|
|
57
|
+
'-w', this.opts.mountPath,
|
|
58
|
+
...envArgs,
|
|
59
|
+
this.opts.image,
|
|
60
|
+
'sleep', '3600',
|
|
61
|
+
], { encoding: 'utf8' });
|
|
62
|
+
|
|
63
|
+
if (result.status !== 0) {
|
|
64
|
+
if (this.opts.fallback !== false) {
|
|
65
|
+
this.useFallback = true;
|
|
66
|
+
return this.fallbackManager.allocate(req);
|
|
67
|
+
}
|
|
68
|
+
throw new Error(`docker run failed: ${result.stderr}`);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const containerId = result.stdout.trim().slice(0, 12);
|
|
72
|
+
this.containerIds.set(wsId, containerId);
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
workspace_id: wsId,
|
|
76
|
+
strategy: 'ephemeral_container',
|
|
77
|
+
isolation_level: this.isolation_level,
|
|
78
|
+
branch: null,
|
|
79
|
+
base_commit: null,
|
|
80
|
+
root_path: `docker:${containerId}:${this.opts.mountPath}`,
|
|
81
|
+
ttl_minutes: 60,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async snapshot(id: string): Promise<SnapshotRef> {
|
|
86
|
+
if (this.useFallback) return this.fallbackManager.snapshot(id);
|
|
87
|
+
const containerId = this.containerIds.get(id);
|
|
88
|
+
if (!containerId) throw new Error(`Container for workspace ${id} not found`);
|
|
89
|
+
|
|
90
|
+
const tag = `oxe-snap-${crypto.randomBytes(4).toString('hex')}`;
|
|
91
|
+
execFileSync('docker', ['commit', containerId, tag]);
|
|
92
|
+
|
|
93
|
+
return {
|
|
94
|
+
snapshot_id: tag,
|
|
95
|
+
workspace_id: id,
|
|
96
|
+
commit: tag,
|
|
97
|
+
created_at: new Date().toISOString(),
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
async reset(id: string, snapRef: SnapshotRef): Promise<void> {
|
|
102
|
+
if (this.useFallback) return this.fallbackManager.reset(id, snapRef);
|
|
103
|
+
const containerId = this.containerIds.get(id);
|
|
104
|
+
if (!containerId) return;
|
|
105
|
+
// Stop current container and start from snapshot
|
|
106
|
+
spawnSync('docker', ['stop', containerId]);
|
|
107
|
+
spawnSync('docker', ['rm', containerId]);
|
|
108
|
+
const result = spawnSync('docker', [
|
|
109
|
+
'run', '-d',
|
|
110
|
+
'-v', `${this.projectRoot}:${this.opts.mountPath}`,
|
|
111
|
+
snapRef.commit,
|
|
112
|
+
'sleep', '3600',
|
|
113
|
+
], { encoding: 'utf8' });
|
|
114
|
+
const newId = result.stdout.trim().slice(0, 12);
|
|
115
|
+
this.containerIds.set(id, newId);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
async dispose(id: string): Promise<void> {
|
|
119
|
+
if (this.useFallback) return this.fallbackManager.dispose(id);
|
|
120
|
+
const containerId = this.containerIds.get(id);
|
|
121
|
+
if (!containerId) return;
|
|
122
|
+
spawnSync('docker', ['stop', containerId], { encoding: 'utf8' });
|
|
123
|
+
spawnSync('docker', ['rm', containerId], { encoding: 'utf8' });
|
|
124
|
+
this.containerIds.delete(id);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
@@ -1,77 +1,79 @@
|
|
|
1
|
-
import { execFileSync } from 'child_process';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import fs from 'fs';
|
|
4
|
-
import crypto from 'crypto';
|
|
5
|
-
import type { WorkspaceManager, WorkspaceRequest } from '../workspace-manager';
|
|
6
|
-
import type { WorkspaceLease, SnapshotRef } from '../../models/workspace';
|
|
7
|
-
|
|
8
|
-
export class GitWorktreeManager implements WorkspaceManager {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
1
|
+
import { execFileSync } from 'child_process';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import crypto from 'crypto';
|
|
5
|
+
import type { WorkspaceManager, WorkspaceRequest } from '../workspace-manager';
|
|
6
|
+
import type { WorkspaceLease, SnapshotRef } from '../../models/workspace';
|
|
7
|
+
|
|
8
|
+
export class GitWorktreeManager implements WorkspaceManager {
|
|
9
|
+
readonly isolation_level = 'isolated' as const;
|
|
10
|
+
private leases = new Map<string, WorkspaceLease>();
|
|
11
|
+
|
|
12
|
+
constructor(private readonly projectRoot: string) {}
|
|
13
|
+
|
|
14
|
+
async allocate(req: WorkspaceRequest): Promise<WorkspaceLease> {
|
|
15
|
+
const wsId = `ws-${req.work_item_id}-a${req.attempt_number}`;
|
|
16
|
+
const branch = `oxe/${req.work_item_id}-attempt${req.attempt_number}`;
|
|
17
|
+
const worktreePath = path.join(this.projectRoot, '.oxe', 'workspaces', wsId);
|
|
18
|
+
|
|
19
|
+
const baseCommit = this.git(['rev-parse', 'HEAD']).trim();
|
|
20
|
+
|
|
21
|
+
fs.mkdirSync(path.dirname(worktreePath), { recursive: true });
|
|
22
|
+
|
|
23
|
+
// Create worktree on a new branch starting from HEAD
|
|
24
|
+
this.git(['worktree', 'add', worktreePath, '-b', branch]);
|
|
25
|
+
|
|
26
|
+
const lease: WorkspaceLease = {
|
|
27
|
+
workspace_id: wsId,
|
|
28
|
+
strategy: 'git_worktree',
|
|
29
|
+
isolation_level: this.isolation_level,
|
|
30
|
+
branch,
|
|
31
|
+
base_commit: baseCommit,
|
|
32
|
+
root_path: worktreePath,
|
|
33
|
+
ttl_minutes: 45,
|
|
34
|
+
};
|
|
35
|
+
this.leases.set(wsId, lease);
|
|
36
|
+
return lease;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async snapshot(id: string): Promise<SnapshotRef> {
|
|
40
|
+
const lease = this.leases.get(id);
|
|
41
|
+
if (!lease || !lease.root_path) throw new Error(`Workspace ${id} not found`);
|
|
42
|
+
const commit = this.git(['rev-parse', 'HEAD'], lease.root_path).trim();
|
|
43
|
+
return {
|
|
44
|
+
snapshot_id: `snap-${crypto.randomBytes(4).toString('hex')}`,
|
|
45
|
+
workspace_id: id,
|
|
46
|
+
commit,
|
|
47
|
+
created_at: new Date().toISOString(),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async reset(id: string, snapRef: SnapshotRef): Promise<void> {
|
|
52
|
+
const lease = this.leases.get(id);
|
|
53
|
+
if (!lease) return;
|
|
54
|
+
this.git(['reset', '--hard', snapRef.commit], lease.root_path);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async dispose(id: string): Promise<void> {
|
|
58
|
+
const lease = this.leases.get(id);
|
|
59
|
+
if (!lease) return;
|
|
60
|
+
try {
|
|
61
|
+
this.git(['worktree', 'remove', lease.root_path, '--force']);
|
|
62
|
+
} catch {
|
|
63
|
+
// worktree may already be gone
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
if (lease.branch) this.git(['branch', '-D', lease.branch]);
|
|
67
|
+
} catch {
|
|
68
|
+
// branch may already be deleted
|
|
69
|
+
}
|
|
70
|
+
this.leases.delete(id);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
private git(args: string[], cwd?: string): string {
|
|
74
|
+
return execFileSync('git', args, {
|
|
75
|
+
cwd: cwd ?? this.projectRoot,
|
|
76
|
+
encoding: 'utf8',
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -1,35 +1,38 @@
|
|
|
1
|
-
import crypto from 'crypto';
|
|
2
|
-
import type { WorkspaceManager, WorkspaceRequest } from '../workspace-manager';
|
|
3
|
-
import type { WorkspaceLease, SnapshotRef } from '../../models/workspace';
|
|
4
|
-
|
|
5
|
-
export class InplaceWorkspaceManager implements WorkspaceManager {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
1
|
+
import crypto from 'crypto';
|
|
2
|
+
import type { WorkspaceManager, WorkspaceRequest } from '../workspace-manager';
|
|
3
|
+
import type { WorkspaceLease, SnapshotRef } from '../../models/workspace';
|
|
4
|
+
|
|
5
|
+
export class InplaceWorkspaceManager implements WorkspaceManager {
|
|
6
|
+
readonly isolation_level = 'shared' as const;
|
|
7
|
+
|
|
8
|
+
constructor(private readonly projectRoot: string) {}
|
|
9
|
+
|
|
10
|
+
async allocate(req: WorkspaceRequest): Promise<WorkspaceLease> {
|
|
11
|
+
return {
|
|
12
|
+
workspace_id: `ws-inplace-${req.work_item_id}-a${req.attempt_number}`,
|
|
13
|
+
strategy: 'inplace',
|
|
14
|
+
isolation_level: this.isolation_level,
|
|
15
|
+
branch: null,
|
|
16
|
+
base_commit: null,
|
|
17
|
+
root_path: this.projectRoot,
|
|
18
|
+
ttl_minutes: 60,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async snapshot(id: string): Promise<SnapshotRef> {
|
|
23
|
+
return {
|
|
24
|
+
snapshot_id: `snap-${crypto.randomBytes(4).toString('hex')}`,
|
|
25
|
+
workspace_id: id,
|
|
26
|
+
commit: 'HEAD',
|
|
27
|
+
created_at: new Date().toISOString(),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async reset(_id: string, _snapRef: SnapshotRef): Promise<void> {
|
|
32
|
+
// inplace: no filesystem isolation — reset is a no-op
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async dispose(_id: string): Promise<void> {
|
|
36
|
+
// inplace: nothing to tear down
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
import type { WorkspaceLease, SnapshotRef, WorkspaceStrategy } from '../models/workspace';
|
|
2
|
-
|
|
3
|
-
export interface WorkspaceRequest {
|
|
4
|
-
work_item_id: string;
|
|
5
|
-
attempt_number: number;
|
|
6
|
-
strategy: WorkspaceStrategy;
|
|
7
|
-
mutation_scope: string[];
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export interface WorkspaceManager {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
1
|
+
import type { WorkspaceLease, SnapshotRef, WorkspaceStrategy, WorkspaceIsolationLevel } from '../models/workspace';
|
|
2
|
+
|
|
3
|
+
export interface WorkspaceRequest {
|
|
4
|
+
work_item_id: string;
|
|
5
|
+
attempt_number: number;
|
|
6
|
+
strategy: WorkspaceStrategy;
|
|
7
|
+
mutation_scope: string[];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface WorkspaceManager {
|
|
11
|
+
readonly isolation_level: WorkspaceIsolationLevel;
|
|
12
|
+
allocate(req: WorkspaceRequest): Promise<WorkspaceLease>;
|
|
13
|
+
snapshot(id: string): Promise<SnapshotRef>;
|
|
14
|
+
reset(id: string, snapRef: SnapshotRef): Promise<void>;
|
|
15
|
+
dispose(id: string): Promise<void>;
|
|
16
|
+
}
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2020",
|
|
4
|
-
"module": "commonjs",
|
|
5
|
-
"moduleResolution": "node",
|
|
6
|
-
"strict": true,
|
|
7
|
-
"esModuleInterop": true,
|
|
8
|
-
"declaration": true,
|
|
9
|
-
"declarationMap": false,
|
|
10
|
-
"sourceMap": false,
|
|
11
|
-
"outDir": "../../lib/runtime",
|
|
12
|
-
"rootDir": "src",
|
|
13
|
-
"skipLibCheck": true
|
|
14
|
-
},
|
|
15
|
-
"include": ["src/**/*.ts"],
|
|
16
|
-
"exclude": ["tests/**", "node_modules/**", "dist-tests/**"]
|
|
17
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "commonjs",
|
|
5
|
+
"moduleResolution": "node",
|
|
6
|
+
"strict": true,
|
|
7
|
+
"esModuleInterop": true,
|
|
8
|
+
"declaration": true,
|
|
9
|
+
"declarationMap": false,
|
|
10
|
+
"sourceMap": false,
|
|
11
|
+
"outDir": "../../lib/runtime",
|
|
12
|
+
"rootDir": "src",
|
|
13
|
+
"skipLibCheck": true
|
|
14
|
+
},
|
|
15
|
+
"include": ["src/**/*.ts"],
|
|
16
|
+
"exclude": ["tests/**", "node_modules/**", "dist-tests/**"]
|
|
17
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
.vscode/**
|
|
2
|
-
.git/**
|
|
3
|
-
.gitignore
|
|
4
|
-
node_modules/**
|
|
5
|
-
**/*.map
|
|
6
|
-
**/*.test.js
|
|
7
|
-
tests/**
|
|
1
|
+
.vscode/**
|
|
2
|
+
.git/**
|
|
3
|
+
.gitignore
|
|
4
|
+
node_modules/**
|
|
5
|
+
**/*.map
|
|
6
|
+
**/*.test.js
|
|
7
|
+
tests/**
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 OXE contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
Binary file
|
|
Binary file
|