codex-orchestrator 0.1.46 → 0.1.48

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.
Files changed (170) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/dist/src/config/schema.d.ts +5 -1
  3. package/dist/src/config/schema.d.ts.map +1 -1
  4. package/dist/src/config/schema.js +16 -0
  5. package/dist/src/config/schema.js.map +1 -1
  6. package/dist/src/runner/command-utils.d.ts.map +1 -1
  7. package/dist/src/runner/command-utils.js +1 -0
  8. package/dist/src/runner/command-utils.js.map +1 -1
  9. package/dist/src/runner/completion-report.d.ts +6 -1
  10. package/dist/src/runner/completion-report.d.ts.map +1 -1
  11. package/dist/src/runner/completion-report.js +26 -1
  12. package/dist/src/runner/completion-report.js.map +1 -1
  13. package/dist/src/runner/handoff-evidence.d.ts.map +1 -1
  14. package/dist/src/runner/handoff-evidence.js +13 -8
  15. package/dist/src/runner/handoff-evidence.js.map +1 -1
  16. package/dist/src/runner/local-execution-session.d.ts.map +1 -1
  17. package/dist/src/runner/local-execution-session.js +24 -7
  18. package/dist/src/runner/local-execution-session.js.map +1 -1
  19. package/dist/src/runner/mission-activation.d.ts +29 -0
  20. package/dist/src/runner/mission-activation.d.ts.map +1 -0
  21. package/dist/src/runner/mission-activation.js +54 -0
  22. package/dist/src/runner/mission-activation.js.map +1 -0
  23. package/dist/src/runner/mission-agent-broker.d.ts +53 -0
  24. package/dist/src/runner/mission-agent-broker.d.ts.map +1 -0
  25. package/dist/src/runner/mission-agent-broker.js +182 -0
  26. package/dist/src/runner/mission-agent-broker.js.map +1 -0
  27. package/dist/src/runner/mission-cancellation.d.ts +77 -0
  28. package/dist/src/runner/mission-cancellation.d.ts.map +1 -0
  29. package/dist/src/runner/mission-cancellation.js +180 -0
  30. package/dist/src/runner/mission-cancellation.js.map +1 -0
  31. package/dist/src/runner/mission-canonical-path.d.ts +34 -0
  32. package/dist/src/runner/mission-canonical-path.d.ts.map +1 -0
  33. package/dist/src/runner/mission-canonical-path.js +121 -0
  34. package/dist/src/runner/mission-canonical-path.js.map +1 -0
  35. package/dist/src/runner/mission-capability-kernel.d.ts +34 -0
  36. package/dist/src/runner/mission-capability-kernel.d.ts.map +1 -0
  37. package/dist/src/runner/mission-capability-kernel.js +158 -0
  38. package/dist/src/runner/mission-capability-kernel.js.map +1 -0
  39. package/dist/src/runner/mission-check-policy.d.ts +17 -0
  40. package/dist/src/runner/mission-check-policy.d.ts.map +1 -0
  41. package/dist/src/runner/mission-check-policy.js +31 -0
  42. package/dist/src/runner/mission-check-policy.js.map +1 -0
  43. package/dist/src/runner/mission-coordinator-lock.d.ts +16 -0
  44. package/dist/src/runner/mission-coordinator-lock.d.ts.map +1 -0
  45. package/dist/src/runner/mission-coordinator-lock.js +170 -0
  46. package/dist/src/runner/mission-coordinator-lock.js.map +1 -0
  47. package/dist/src/runner/mission-deployment.d.ts +21 -0
  48. package/dist/src/runner/mission-deployment.d.ts.map +1 -0
  49. package/dist/src/runner/mission-deployment.js +108 -0
  50. package/dist/src/runner/mission-deployment.js.map +1 -0
  51. package/dist/src/runner/mission-evaluation.d.ts +61 -0
  52. package/dist/src/runner/mission-evaluation.d.ts.map +1 -0
  53. package/dist/src/runner/mission-evaluation.js +183 -0
  54. package/dist/src/runner/mission-evaluation.js.map +1 -0
  55. package/dist/src/runner/mission-executor-probe.d.ts +10 -0
  56. package/dist/src/runner/mission-executor-probe.d.ts.map +1 -0
  57. package/dist/src/runner/mission-executor-probe.js +180 -0
  58. package/dist/src/runner/mission-executor-probe.js.map +1 -0
  59. package/dist/src/runner/mission-git-contracts.d.ts +75 -0
  60. package/dist/src/runner/mission-git-contracts.d.ts.map +1 -0
  61. package/dist/src/runner/mission-git-contracts.js +201 -0
  62. package/dist/src/runner/mission-git-contracts.js.map +1 -0
  63. package/dist/src/runner/mission-git-runtime-owner-ref.d.ts +13 -0
  64. package/dist/src/runner/mission-git-runtime-owner-ref.d.ts.map +1 -0
  65. package/dist/src/runner/mission-git-runtime-owner-ref.js +111 -0
  66. package/dist/src/runner/mission-git-runtime-owner-ref.js.map +1 -0
  67. package/dist/src/runner/mission-git-transaction.d.ts +97 -0
  68. package/dist/src/runner/mission-git-transaction.d.ts.map +1 -0
  69. package/dist/src/runner/mission-git-transaction.js +1009 -0
  70. package/dist/src/runner/mission-git-transaction.js.map +1 -0
  71. package/dist/src/runner/mission-identifiers.d.ts +31 -0
  72. package/dist/src/runner/mission-identifiers.d.ts.map +1 -0
  73. package/dist/src/runner/mission-identifiers.js +75 -0
  74. package/dist/src/runner/mission-identifiers.js.map +1 -0
  75. package/dist/src/runner/mission-input-snapshot.d.ts +21 -0
  76. package/dist/src/runner/mission-input-snapshot.d.ts.map +1 -0
  77. package/dist/src/runner/mission-input-snapshot.js +63 -0
  78. package/dist/src/runner/mission-input-snapshot.js.map +1 -0
  79. package/dist/src/runner/mission-ownership.d.ts +38 -0
  80. package/dist/src/runner/mission-ownership.d.ts.map +1 -0
  81. package/dist/src/runner/mission-ownership.js +88 -0
  82. package/dist/src/runner/mission-ownership.js.map +1 -0
  83. package/dist/src/runner/mission-patch-audit.d.ts +21 -0
  84. package/dist/src/runner/mission-patch-audit.d.ts.map +1 -0
  85. package/dist/src/runner/mission-patch-audit.js +186 -0
  86. package/dist/src/runner/mission-patch-audit.js.map +1 -0
  87. package/dist/src/runner/mission-path-language.d.ts +6 -0
  88. package/dist/src/runner/mission-path-language.d.ts.map +1 -0
  89. package/dist/src/runner/mission-path-language.js +106 -0
  90. package/dist/src/runner/mission-path-language.js.map +1 -0
  91. package/dist/src/runner/mission-permit-authority.d.ts +26 -0
  92. package/dist/src/runner/mission-permit-authority.d.ts.map +1 -0
  93. package/dist/src/runner/mission-permit-authority.js +145 -0
  94. package/dist/src/runner/mission-permit-authority.js.map +1 -0
  95. package/dist/src/runner/mission-plan-parent-coordinator.d.ts +87 -0
  96. package/dist/src/runner/mission-plan-parent-coordinator.d.ts.map +1 -0
  97. package/dist/src/runner/mission-plan-parent-coordinator.js +412 -0
  98. package/dist/src/runner/mission-plan-parent-coordinator.js.map +1 -0
  99. package/dist/src/runner/mission-plan-parent.d.ts +154 -0
  100. package/dist/src/runner/mission-plan-parent.d.ts.map +1 -0
  101. package/dist/src/runner/mission-plan-parent.js +583 -0
  102. package/dist/src/runner/mission-plan-parent.js.map +1 -0
  103. package/dist/src/runner/mission-process-executor.d.ts +25 -0
  104. package/dist/src/runner/mission-process-executor.d.ts.map +1 -0
  105. package/dist/src/runner/mission-process-executor.js +182 -0
  106. package/dist/src/runner/mission-process-executor.js.map +1 -0
  107. package/dist/src/runner/mission-quarantine-patch-executor.d.ts +29 -0
  108. package/dist/src/runner/mission-quarantine-patch-executor.d.ts.map +1 -0
  109. package/dist/src/runner/mission-quarantine-patch-executor.js +121 -0
  110. package/dist/src/runner/mission-quarantine-patch-executor.js.map +1 -0
  111. package/dist/src/runner/mission-repository-executor.d.ts +54 -0
  112. package/dist/src/runner/mission-repository-executor.d.ts.map +1 -0
  113. package/dist/src/runner/mission-repository-executor.js +192 -0
  114. package/dist/src/runner/mission-repository-executor.js.map +1 -0
  115. package/dist/src/runner/mission-repository-observer.d.ts +8 -0
  116. package/dist/src/runner/mission-repository-observer.d.ts.map +1 -0
  117. package/dist/src/runner/mission-repository-observer.js +24 -0
  118. package/dist/src/runner/mission-repository-observer.js.map +1 -0
  119. package/dist/src/runner/mission-reservations.d.ts +15 -0
  120. package/dist/src/runner/mission-reservations.d.ts.map +1 -0
  121. package/dist/src/runner/mission-reservations.js +116 -0
  122. package/dist/src/runner/mission-reservations.js.map +1 -0
  123. package/dist/src/runner/mission-resolution-loop.d.ts +172 -0
  124. package/dist/src/runner/mission-resolution-loop.d.ts.map +1 -0
  125. package/dist/src/runner/mission-resolution-loop.js +318 -0
  126. package/dist/src/runner/mission-resolution-loop.js.map +1 -0
  127. package/dist/src/runner/mission-runtime-owner.d.ts +36 -0
  128. package/dist/src/runner/mission-runtime-owner.d.ts.map +1 -0
  129. package/dist/src/runner/mission-runtime-owner.js +174 -0
  130. package/dist/src/runner/mission-runtime-owner.js.map +1 -0
  131. package/dist/src/runner/mission-safe-executor.d.ts +96 -0
  132. package/dist/src/runner/mission-safe-executor.d.ts.map +1 -0
  133. package/dist/src/runner/mission-safe-executor.js +288 -0
  134. package/dist/src/runner/mission-safe-executor.js.map +1 -0
  135. package/dist/src/runner/mission-sandbox.d.ts +16 -0
  136. package/dist/src/runner/mission-sandbox.d.ts.map +1 -0
  137. package/dist/src/runner/mission-sandbox.js +91 -0
  138. package/dist/src/runner/mission-sandbox.js.map +1 -0
  139. package/dist/src/runner/mission-scheduler.d.ts +57 -0
  140. package/dist/src/runner/mission-scheduler.d.ts.map +1 -0
  141. package/dist/src/runner/mission-scheduler.js +205 -0
  142. package/dist/src/runner/mission-scheduler.js.map +1 -0
  143. package/dist/src/runner/mission-scope-expansion.d.ts +47 -0
  144. package/dist/src/runner/mission-scope-expansion.d.ts.map +1 -0
  145. package/dist/src/runner/mission-scope-expansion.js +147 -0
  146. package/dist/src/runner/mission-scope-expansion.js.map +1 -0
  147. package/dist/src/runner/mission-state-machine.d.ts +118 -0
  148. package/dist/src/runner/mission-state-machine.d.ts.map +1 -0
  149. package/dist/src/runner/mission-state-machine.js +316 -0
  150. package/dist/src/runner/mission-state-machine.js.map +1 -0
  151. package/dist/src/runner/mission-state-store.d.ts +70 -0
  152. package/dist/src/runner/mission-state-store.d.ts.map +1 -0
  153. package/dist/src/runner/mission-state-store.js +856 -0
  154. package/dist/src/runner/mission-state-store.js.map +1 -0
  155. package/dist/src/runner/prompt.d.ts.map +1 -1
  156. package/dist/src/runner/prompt.js +5 -2
  157. package/dist/src/runner/prompt.js.map +1 -1
  158. package/dist/src/runner/review-gates.js +41 -1
  159. package/dist/src/runner/review-gates.js.map +1 -1
  160. package/dist/src/runner/rework-policy.d.ts +2 -1
  161. package/dist/src/runner/rework-policy.d.ts.map +1 -1
  162. package/dist/src/runner/rework-policy.js +3 -0
  163. package/dist/src/runner/rework-policy.js.map +1 -1
  164. package/dist/src/setup/project-config.d.ts.map +1 -1
  165. package/dist/src/setup/project-config.js +5 -0
  166. package/dist/src/setup/project-config.js.map +1 -1
  167. package/docs/deep-dive.md +39 -17
  168. package/package.json +1 -1
  169. package/prompts/workflows/issue-tree-orchestration.md +1 -1
  170. package/prompts/workflows/scoped-implementation.md +2 -1
@@ -0,0 +1,25 @@
1
+ export interface MissionProcessInput {
2
+ file: string;
3
+ args: string[];
4
+ cwd?: string;
5
+ timeoutMs: number;
6
+ sourceEnv: NodeJS.ProcessEnv;
7
+ allowedEnvKeys: string[];
8
+ stdin?: string;
9
+ maxOutputBytes?: number;
10
+ signal?: AbortSignal;
11
+ onSpawn?: (pid: number | undefined) => void;
12
+ }
13
+ export interface MissionProcessResult {
14
+ stdout: string;
15
+ stderr: string;
16
+ exitCode: number;
17
+ timedOut: boolean;
18
+ termination: 'exited' | 'timeout' | 'output-limit' | 'stdin-error' | 'cancelled';
19
+ }
20
+ export interface MissionProcessDependencies {
21
+ terminateProcessGroup?: (pid: number | undefined, signal: NodeJS.Signals) => void;
22
+ terminateChild?: (signal: NodeJS.Signals) => void;
23
+ }
24
+ export declare function runMissionProcess(input: MissionProcessInput, dependencies?: MissionProcessDependencies): Promise<MissionProcessResult>;
25
+ //# sourceMappingURL=mission-process-executor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mission-process-executor.d.ts","sourceRoot":"","sources":["../../../src/runner/mission-process-executor.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC,UAAU,CAAC;IAC7B,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;CAC7C;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,QAAQ,GAAG,SAAS,GAAG,cAAc,GAAG,aAAa,GAAG,WAAW,CAAC;CAClF;AAED,MAAM,WAAW,0BAA0B;IACzC,qBAAqB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,KAAK,IAAI,CAAC;IAClF,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,KAAK,IAAI,CAAC;CACnD;AAED,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,mBAAmB,EAC1B,YAAY,GAAE,0BAA+B,GAC5C,OAAO,CAAC,oBAAoB,CAAC,CAoJ/B"}
@@ -0,0 +1,182 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { scrubMissionExecutorEnv } from './mission-capability-kernel.js';
3
+ export function runMissionProcess(input, dependencies = {}) {
4
+ if (!Number.isSafeInteger(input.timeoutMs) || input.timeoutMs <= 0) {
5
+ throw new Error('Mission process timeoutMs must be a positive integer.');
6
+ }
7
+ if (input.file.trim().length === 0 || input.args.some((arg) => arg.includes('\0'))) {
8
+ throw new Error('Mission process requires a valid argv command.');
9
+ }
10
+ const maxOutputBytes = input.maxOutputBytes ?? 4 * 1024 * 1024;
11
+ if (!Number.isSafeInteger(maxOutputBytes) || maxOutputBytes <= 0) {
12
+ throw new Error('Mission process maxOutputBytes must be a positive integer.');
13
+ }
14
+ if (input.signal?.aborted) {
15
+ return Promise.resolve({
16
+ stdout: '',
17
+ stderr: '',
18
+ exitCode: 130,
19
+ timedOut: false,
20
+ termination: 'cancelled',
21
+ });
22
+ }
23
+ return new Promise((resolve, reject) => {
24
+ let stdout = '';
25
+ let stderr = '';
26
+ let termination;
27
+ let outputBytes = 0;
28
+ let settled = false;
29
+ let terminationError;
30
+ let inputError;
31
+ let closeExitCode;
32
+ let escalationComplete = false;
33
+ let settlementTimeout;
34
+ const child = spawn(input.file, input.args, {
35
+ cwd: input.cwd,
36
+ env: scrubMissionExecutorEnv(input.sourceEnv, input.allowedEnvKeys),
37
+ shell: false,
38
+ detached: process.platform !== 'win32',
39
+ stdio: ['pipe', 'pipe', 'pipe'],
40
+ });
41
+ const onAbort = () => beginTermination('cancelled');
42
+ input.signal?.addEventListener('abort', onAbort, { once: true });
43
+ child.stdout.on('data', (chunk) => { collectOutput('stdout', chunk); });
44
+ child.stderr.on('data', (chunk) => { collectOutput('stderr', chunk); });
45
+ const timeout = setTimeout(() => {
46
+ beginTermination('timeout');
47
+ }, input.timeoutMs);
48
+ timeout.unref();
49
+ try {
50
+ input.onSpawn?.(child.pid);
51
+ }
52
+ catch (error) {
53
+ inputError = error instanceof Error ? error : new Error(String(error));
54
+ beginTermination('stdin-error');
55
+ }
56
+ if (input.signal?.aborted)
57
+ beginTermination('cancelled');
58
+ function beginTermination(reason) {
59
+ if (termination || settled)
60
+ return;
61
+ termination = reason;
62
+ clearTimeout(timeout);
63
+ requestTermination(child.pid, 'SIGTERM');
64
+ setTimeout(() => {
65
+ if (settled)
66
+ return;
67
+ requestTermination(child.pid, 'SIGKILL');
68
+ escalationComplete = true;
69
+ if (closeExitCode !== undefined) {
70
+ finishClose(closeExitCode);
71
+ }
72
+ else {
73
+ settlementTimeout = setTimeout(() => {
74
+ if (settled)
75
+ return;
76
+ settled = true;
77
+ input.signal?.removeEventListener('abort', onAbort);
78
+ reject(terminationError ?? inputError
79
+ ?? new Error('Mission process did not terminate after SIGKILL reconciliation.'));
80
+ }, 500);
81
+ }
82
+ }, 250);
83
+ }
84
+ child.on('error', (error) => {
85
+ if (settled)
86
+ return;
87
+ settled = true;
88
+ clearTimeout(timeout);
89
+ input.signal?.removeEventListener('abort', onAbort);
90
+ if (settlementTimeout)
91
+ clearTimeout(settlementTimeout);
92
+ reject(error);
93
+ });
94
+ child.on('close', (exitCode) => {
95
+ if (settled)
96
+ return;
97
+ clearTimeout(timeout);
98
+ closeExitCode = exitCode;
99
+ if (termination && !escalationComplete)
100
+ return;
101
+ finishClose(exitCode);
102
+ });
103
+ child.stdin.on('error', (error) => {
104
+ if (settled)
105
+ return;
106
+ inputError ??= new Error(`Mission process stdin failed: ${error.message}`, { cause: error });
107
+ beginTermination('stdin-error');
108
+ });
109
+ child.stdin.end(input.stdin);
110
+ function finishClose(exitCode) {
111
+ if (settled)
112
+ return;
113
+ settled = true;
114
+ input.signal?.removeEventListener('abort', onAbort);
115
+ if (settlementTimeout)
116
+ clearTimeout(settlementTimeout);
117
+ if (terminationError) {
118
+ reject(terminationError);
119
+ return;
120
+ }
121
+ if (inputError) {
122
+ reject(inputError);
123
+ return;
124
+ }
125
+ resolve({
126
+ stdout,
127
+ stderr,
128
+ exitCode: termination === 'timeout' ? 124
129
+ : termination === 'output-limit' ? 125
130
+ : termination === 'cancelled' ? 130 : (exitCode ?? 1),
131
+ timedOut: termination === 'timeout',
132
+ termination: termination ?? 'exited',
133
+ });
134
+ }
135
+ function collectOutput(target, chunk) {
136
+ const remaining = Math.max(0, maxOutputBytes - outputBytes);
137
+ const accepted = chunk.subarray(0, remaining);
138
+ if (accepted.byteLength > 0) {
139
+ if (target === 'stdout')
140
+ stdout += accepted.toString('utf8');
141
+ else
142
+ stderr += accepted.toString('utf8');
143
+ outputBytes += accepted.byteLength;
144
+ }
145
+ if (chunk.byteLength > remaining)
146
+ beginTermination('output-limit');
147
+ }
148
+ function requestTermination(pid, signal) {
149
+ try {
150
+ (dependencies.terminateProcessGroup ?? terminateProcessGroup)(pid, signal);
151
+ }
152
+ catch (error) {
153
+ const message = error instanceof Error ? error.message : String(error);
154
+ terminationError ??= new Error(`Mission process failed to terminate process group: ${message}`);
155
+ try {
156
+ (dependencies.terminateChild ?? ((childSignal) => { child.kill(childSignal); }))(signal);
157
+ }
158
+ catch {
159
+ // The stored termination error is reported when the child closes.
160
+ }
161
+ }
162
+ }
163
+ });
164
+ }
165
+ function terminateProcessGroup(pid, signal) {
166
+ if (pid === undefined)
167
+ return;
168
+ try {
169
+ if (process.platform === 'win32') {
170
+ process.kill(pid, signal);
171
+ }
172
+ else {
173
+ process.kill(-pid, signal);
174
+ }
175
+ }
176
+ catch (error) {
177
+ if (!(error instanceof Error && 'code' in error && error.code === 'ESRCH')) {
178
+ throw error;
179
+ }
180
+ }
181
+ }
182
+ //# sourceMappingURL=mission-process-executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mission-process-executor.js","sourceRoot":"","sources":["../../../src/runner/mission-process-executor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import type { MissionSandboxBackend } from './mission-capability-kernel.js';
2
+ import type { MissionProcessInput, MissionProcessResult } from './mission-process-executor.js';
3
+ export interface MissionPatchReceipt {
4
+ version: 1;
5
+ sha256: string;
6
+ size: number;
7
+ storage: 'mission-state-blob';
8
+ }
9
+ export interface MissionQuarantinePatchExecutorOptions {
10
+ backend: MissionSandboxBackend;
11
+ workspaceRoot: string;
12
+ quarantineRoot: string;
13
+ deniedReadPaths: string[];
14
+ sourceEnv: NodeJS.ProcessEnv;
15
+ allowedEnvKeys: string[];
16
+ timeoutMs: number;
17
+ maxPatchBytes: number;
18
+ }
19
+ export declare class MissionQuarantinePatchExecutor {
20
+ private readonly options;
21
+ private readonly runProcess;
22
+ constructor(options: MissionQuarantinePatchExecutorOptions, runProcess: (input: MissionProcessInput) => Promise<MissionProcessResult>);
23
+ materialize(patch: string): Promise<{
24
+ receipt: MissionPatchReceipt;
25
+ content: string;
26
+ discard: () => Promise<void>;
27
+ }>;
28
+ }
29
+ //# sourceMappingURL=mission-quarantine-patch-executor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mission-quarantine-patch-executor.d.ts","sourceRoot":"","sources":["../../../src/runner/mission-quarantine-patch-executor.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAC5E,OAAO,KAAK,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAG/F,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,CAAC,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,oBAAoB,CAAC;CAC/B;AAED,MAAM,WAAW,qCAAqC;IACpD,OAAO,EAAE,qBAAqB,CAAC;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC,UAAU,CAAC;IAC7B,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,qBAAa,8BAA8B;IAEvC,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,UAAU;gBADV,OAAO,EAAE,qCAAqC,EAC9C,UAAU,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,OAAO,CAAC,oBAAoB,CAAC;IAG/E,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;QAC/C,OAAO,EAAE,mBAAmB,CAAC;QAC7B,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;KAC9B,CAAC;CAqEH"}
@@ -0,0 +1,121 @@
1
+ import { createHash, randomUUID } from 'node:crypto';
2
+ import { constants } from 'node:fs';
3
+ import { link, mkdir, open, realpath, unlink } from 'node:fs/promises';
4
+ import { join } from 'node:path';
5
+ import { buildMissionSandboxInvocation } from './mission-sandbox.js';
6
+ export class MissionQuarantinePatchExecutor {
7
+ options;
8
+ runProcess;
9
+ constructor(options, runProcess) {
10
+ this.options = options;
11
+ this.runProcess = runProcess;
12
+ }
13
+ async materialize(patch) {
14
+ const bytes = Buffer.from(patch, 'utf8');
15
+ if (bytes.byteLength > this.options.maxPatchBytes) {
16
+ throw new Error(`Mission quarantine patch size limit exceeded: ${bytes.byteLength}.`);
17
+ }
18
+ const quarantineRoot = await realpath(this.options.quarantineRoot);
19
+ const receiptDirectory = join(quarantineRoot, 'patch-receipts');
20
+ await mkdir(receiptDirectory, { recursive: true, mode: 0o700 });
21
+ const temporaryPath = join(receiptDirectory, `.incoming.${process.pid}.${randomUUID()}.patch`);
22
+ const invocation = buildMissionSandboxInvocation({
23
+ backend: this.options.backend,
24
+ workspaceRoot: this.options.workspaceRoot,
25
+ quarantineRoot,
26
+ mode: 'quarantine-write',
27
+ command: '/usr/bin/tee',
28
+ args: [temporaryPath],
29
+ deniedReadPaths: this.options.deniedReadPaths,
30
+ });
31
+ try {
32
+ const result = await this.runProcess({
33
+ ...invocation,
34
+ cwd: this.options.workspaceRoot,
35
+ timeoutMs: this.options.timeoutMs,
36
+ sourceEnv: this.options.sourceEnv,
37
+ allowedEnvKeys: this.options.allowedEnvKeys,
38
+ stdin: patch,
39
+ });
40
+ if (result.exitCode !== 0 || result.timedOut) {
41
+ throw new Error(`Mission quarantine patch producer failed with exit ${result.exitCode}.`);
42
+ }
43
+ const produced = await readRegularNoFollow(temporaryPath, true);
44
+ if (!produced.equals(bytes)) {
45
+ throw new Error('Mission quarantine patch producer output differs from the authorized proposal.');
46
+ }
47
+ const sha256 = createHash('sha256').update(produced).digest('hex');
48
+ const receiptPath = join(receiptDirectory, `${sha256}.patch`);
49
+ try {
50
+ await link(temporaryPath, receiptPath);
51
+ }
52
+ catch (error) {
53
+ if (!(error instanceof Error && 'code' in error && error.code === 'EEXIST'))
54
+ throw error;
55
+ }
56
+ await unlink(temporaryPath);
57
+ const immutable = await readRegularNoFollow(receiptPath);
58
+ if (immutable.byteLength !== produced.byteLength
59
+ || createHash('sha256').update(immutable).digest('hex') !== sha256) {
60
+ throw new Error('Mission quarantine content-addressed receipt is corrupted.');
61
+ }
62
+ const directory = await open(receiptDirectory, 'r');
63
+ try {
64
+ await directory.sync();
65
+ }
66
+ finally {
67
+ await directory.close();
68
+ }
69
+ return {
70
+ receipt: {
71
+ version: 1,
72
+ sha256,
73
+ size: immutable.byteLength,
74
+ storage: 'mission-state-blob',
75
+ },
76
+ content: immutable.toString('utf8'),
77
+ discard: async () => {
78
+ await unlink(receiptPath).catch((error) => {
79
+ if (!(error instanceof Error && 'code' in error && error.code === 'ENOENT'))
80
+ throw error;
81
+ });
82
+ const directory = await open(receiptDirectory, 'r');
83
+ try {
84
+ await directory.sync();
85
+ }
86
+ finally {
87
+ await directory.close();
88
+ }
89
+ },
90
+ };
91
+ }
92
+ finally {
93
+ await unlink(temporaryPath).catch(() => undefined);
94
+ }
95
+ }
96
+ }
97
+ async function readRegularNoFollow(path, seal = false) {
98
+ const handle = await open(path, constants.O_RDONLY | constants.O_NOFOLLOW);
99
+ try {
100
+ const before = await handle.stat({ bigint: true });
101
+ if (!before.isFile() || before.nlink !== 1n) {
102
+ throw new Error('Mission quarantine receipt must be a single-link regular file.');
103
+ }
104
+ if (seal)
105
+ await handle.chmod(0o400);
106
+ const content = await handle.readFile();
107
+ const after = await handle.stat({ bigint: true });
108
+ if (before.dev !== after.dev || before.ino !== after.ino || before.size !== after.size
109
+ || before.mtimeNs !== after.mtimeNs || after.size !== BigInt(content.byteLength)
110
+ || after.nlink !== 1n) {
111
+ throw new Error('Mission quarantine receipt changed during read.');
112
+ }
113
+ if (seal)
114
+ await handle.sync();
115
+ return content;
116
+ }
117
+ finally {
118
+ await handle.close();
119
+ }
120
+ }
121
+ //# sourceMappingURL=mission-quarantine-patch-executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mission-quarantine-patch-executor.js","sourceRoot":"","sources":["../../../src/runner/mission-quarantine-patch-executor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ import { type MissionCapabilityPermit, type MissionCapabilityRequest, type MissionSandboxBackend } from './mission-capability-kernel.js';
2
+ import { type CanonicalFileIdentity } from './mission-canonical-path.js';
3
+ import { type MissionPatchAuditResult } from './mission-patch-audit.js';
4
+ import { type MissionExecutorProbeResult } from './mission-executor-probe.js';
5
+ import { type MissionProcessInput, type MissionProcessResult } from './mission-process-executor.js';
6
+ import type { MissionPermitAuthority } from './mission-permit-authority.js';
7
+ import type { MissionInputSnapshotVerifier } from './mission-input-snapshot.js';
8
+ import { type MissionPatchReceipt } from './mission-quarantine-patch-executor.js';
9
+ export type MissionRepositoryPatchAuditResult = Extract<MissionPatchAuditResult, {
10
+ accepted: false;
11
+ }> | {
12
+ accepted: true;
13
+ files: Extract<MissionPatchAuditResult, {
14
+ accepted: true;
15
+ }>['files'];
16
+ preconditions: Record<string, CanonicalFileIdentity | null>;
17
+ };
18
+ export type MissionPatchExecutionResult = MissionRepositoryPatchAuditResult & {
19
+ receipt: MissionPatchReceipt;
20
+ };
21
+ export interface MissionRepositoryExecutorOptions {
22
+ backend: MissionSandboxBackend;
23
+ workspaceRoot: string;
24
+ quarantineRoot: string;
25
+ deniedReadPaths: string[];
26
+ sourceEnv: NodeJS.ProcessEnv;
27
+ allowedEnvKeys: string[];
28
+ timeoutMs: number;
29
+ deniedRepositoryPaths?: string[];
30
+ maxPatchBytes?: number;
31
+ capabilityProof: MissionExecutorProbeResult;
32
+ }
33
+ export interface MissionRepositoryExecutorDependencies {
34
+ runProcess?: (input: MissionProcessInput) => Promise<MissionProcessResult>;
35
+ permitAuthority: MissionPermitAuthority;
36
+ snapshotVerifier: MissionInputSnapshotVerifier;
37
+ }
38
+ export declare class MissionRepositoryExecutor {
39
+ private readonly options;
40
+ private readonly runProcess;
41
+ private readonly permitAuthority;
42
+ private readonly snapshotVerifier;
43
+ private readonly quarantinePatchExecutor;
44
+ constructor(options: MissionRepositoryExecutorOptions, dependencies: MissionRepositoryExecutorDependencies);
45
+ authorize(request: MissionCapabilityRequest): MissionCapabilityPermit;
46
+ observeGitStatus(permit: MissionCapabilityPermit): Promise<MissionProcessResult>;
47
+ readText(permit: MissionCapabilityPermit): Promise<string>;
48
+ executePatch(permit: MissionCapabilityPermit, patch: string): Promise<MissionPatchExecutionResult>;
49
+ private validatePermit;
50
+ private beginPermit;
51
+ private deniedRepositoryPaths;
52
+ private completePermit;
53
+ }
54
+ //# sourceMappingURL=mission-repository-executor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mission-repository-executor.d.ts","sourceRoot":"","sources":["../../../src/runner/mission-repository-executor.ts"],"names":[],"mappings":"AACA,OAAO,EAIL,KAAK,uBAAuB,EAC5B,KAAK,wBAAwB,EAC7B,KAAK,qBAAqB,EAC3B,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAEL,KAAK,qBAAqB,EAC3B,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAqB,KAAK,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAC3F,OAAO,EAEL,KAAK,0BAA0B,EAChC,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EAC1B,MAAM,+BAA+B,CAAC;AAEvC,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AAC5E,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,6BAA6B,CAAC;AAChF,OAAO,EAEL,KAAK,mBAAmB,EACzB,MAAM,wCAAwC,CAAC;AAOhD,MAAM,MAAM,iCAAiC,GACzC,OAAO,CAAC,uBAAuB,EAAE;IAAE,QAAQ,EAAE,KAAK,CAAA;CAAE,CAAC,GACrD;IACE,QAAQ,EAAE,IAAI,CAAC;IACf,KAAK,EAAE,OAAO,CAAC,uBAAuB,EAAE;QAAE,QAAQ,EAAE,IAAI,CAAA;KAAE,CAAC,CAAC,OAAO,CAAC,CAAC;IACrE,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,GAAG,IAAI,CAAC,CAAC;CAC7D,CAAC;AAEN,MAAM,MAAM,2BAA2B,GAAG,iCAAiC,GAAG;IAC5E,OAAO,EAAE,mBAAmB,CAAC;CAC9B,CAAC;AAEF,MAAM,WAAW,gCAAgC;IAC/C,OAAO,EAAE,qBAAqB,CAAC;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC,UAAU,CAAC;IAC7B,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,0BAA0B,CAAC;CAC7C;AAED,MAAM,WAAW,qCAAqC;IACpD,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAC3E,eAAe,EAAE,sBAAsB,CAAC;IACxC,gBAAgB,EAAE,4BAA4B,CAAC;CAChD;AAED,qBAAa,yBAAyB;IAOlC,OAAO,CAAC,QAAQ,CAAC,OAAO;IAN1B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAgE;IAC3F,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAyB;IACzD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA+B;IAChE,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAiC;gBAGtD,OAAO,EAAE,gCAAgC,EAC1D,YAAY,EAAE,qCAAqC;IAwB9C,SAAS,CAAC,OAAO,EAAE,wBAAwB,GAAG,uBAAuB;IAI/D,gBAAgB,CAAC,MAAM,EAAE,uBAAuB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAyBhF,QAAQ,CACnB,MAAM,EAAE,uBAAuB,GAC9B,OAAO,CAAC,MAAM,CAAC;IAuBL,YAAY,CACvB,MAAM,EAAE,uBAAuB,EAC/B,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,2BAA2B,CAAC;IAgEvC,OAAO,CAAC,cAAc;YAWR,WAAW;IASzB,OAAO,CAAC,qBAAqB;YAIf,cAAc;CAU7B"}
@@ -0,0 +1,192 @@
1
+ import { globMatches } from '../path-policy.js';
2
+ import { authorizeMissionCapability, missionGitStatusArgv, } from './mission-capability-kernel.js';
3
+ import { inspectCanonicalFile, } from './mission-canonical-path.js';
4
+ import { auditMissionPatch } from './mission-patch-audit.js';
5
+ import { missionExecutorRequiredChecks, } from './mission-executor-probe.js';
6
+ import { runMissionProcess, } from './mission-process-executor.js';
7
+ import { MissionRepositoryObserver } from './mission-repository-observer.js';
8
+ import { MissionQuarantinePatchExecutor, } from './mission-quarantine-patch-executor.js';
9
+ import { buildMissionSandboxInvocation } from './mission-sandbox.js';
10
+ import { missionDefaultDeniedRepositoryPaths, missionPathDenied, } from './mission-path-language.js';
11
+ export class MissionRepositoryExecutor {
12
+ options;
13
+ runProcess;
14
+ permitAuthority;
15
+ snapshotVerifier;
16
+ quarantinePatchExecutor;
17
+ constructor(options, dependencies) {
18
+ this.options = options;
19
+ const proofChecks = new Set(options.capabilityProof.checks);
20
+ if (!options.capabilityProof.supported
21
+ || options.capabilityProof.backend !== options.backend
22
+ || options.capabilityProof.failures.length > 0
23
+ || missionExecutorRequiredChecks.some((check) => !proofChecks.has(check))) {
24
+ throw new Error('Mission repository executor requires a successful active capability proof.');
25
+ }
26
+ this.runProcess = dependencies.runProcess ?? runMissionProcess;
27
+ this.permitAuthority = dependencies.permitAuthority;
28
+ this.snapshotVerifier = dependencies.snapshotVerifier;
29
+ this.quarantinePatchExecutor = new MissionQuarantinePatchExecutor({
30
+ backend: options.backend,
31
+ workspaceRoot: options.workspaceRoot,
32
+ quarantineRoot: options.quarantineRoot,
33
+ deniedReadPaths: options.deniedReadPaths,
34
+ sourceEnv: options.sourceEnv,
35
+ allowedEnvKeys: options.allowedEnvKeys,
36
+ timeoutMs: options.timeoutMs,
37
+ maxPatchBytes: options.maxPatchBytes ?? 4 * 1024 * 1024,
38
+ }, this.runProcess);
39
+ }
40
+ authorize(request) {
41
+ return authorizeMissionCapability(request);
42
+ }
43
+ async observeGitStatus(permit) {
44
+ const authorized = this.validatePermit(permit, 'git-status');
45
+ const replay = await this.beginPermit(authorized);
46
+ if (replay)
47
+ return decodeActionReceipt(replay, 'process-result');
48
+ const [command, ...args] = missionGitStatusArgv;
49
+ const invocation = buildMissionSandboxInvocation({
50
+ backend: this.options.backend,
51
+ workspaceRoot: this.options.workspaceRoot,
52
+ quarantineRoot: this.options.quarantineRoot,
53
+ mode: 'read-only',
54
+ command,
55
+ args,
56
+ deniedReadPaths: this.options.deniedReadPaths,
57
+ });
58
+ const result = await this.runProcess({
59
+ ...invocation,
60
+ cwd: this.options.workspaceRoot,
61
+ timeoutMs: this.options.timeoutMs,
62
+ sourceEnv: this.options.sourceEnv,
63
+ allowedEnvKeys: this.options.allowedEnvKeys,
64
+ });
65
+ await this.completePermit(authorized, 'process-result', result);
66
+ return result;
67
+ }
68
+ async readText(permit) {
69
+ const authorized = this.validatePermit(permit, 'read-file');
70
+ const path = authorized.readPath;
71
+ const maxBytes = authorized.maxReadBytes;
72
+ if (!authorized.requestedPaths.some((pattern) => globMatches(pattern, path))) {
73
+ throw new Error(`Mission repository read is outside permitted scope: ${path}.`);
74
+ }
75
+ const deniedPaths = this.deniedRepositoryPaths();
76
+ if (missionPathDenied(path, deniedPaths)) {
77
+ throw new Error(`Mission repository read path is denied: ${path}.`);
78
+ }
79
+ const replay = await this.beginPermit(authorized);
80
+ if (replay)
81
+ return decodeActionReceipt(replay, 'text-result');
82
+ const observer = new MissionRepositoryObserver(this.options.workspaceRoot, authorized.requestedPaths, deniedPaths);
83
+ const text = await observer.readText(path, maxBytes);
84
+ await this.completePermit(authorized, 'text-result', text);
85
+ return text;
86
+ }
87
+ async executePatch(permit, patch) {
88
+ const authorized = this.validatePermit(permit, 'validate-patch');
89
+ const preliminary = auditMissionPatch({
90
+ patch,
91
+ grantedPaths: authorized.requestedPaths,
92
+ deniedPaths: this.deniedRepositoryPaths(),
93
+ maxBytes: this.options.maxPatchBytes ?? 4 * 1024 * 1024,
94
+ });
95
+ if (!preliminary.accepted) {
96
+ throw new Error(`Mission patch proposal rejected before execution: ${preliminary.reason}.`);
97
+ }
98
+ const replay = await this.beginPermit(authorized);
99
+ if (replay)
100
+ return decodeActionReceipt(replay, 'patch-result');
101
+ const produced = await this.quarantinePatchExecutor.materialize(patch);
102
+ let durablyCompleted = false;
103
+ try {
104
+ const audited = auditMissionPatch({
105
+ patch: produced.content,
106
+ grantedPaths: authorized.requestedPaths,
107
+ deniedPaths: this.deniedRepositoryPaths(),
108
+ maxBytes: this.options.maxPatchBytes ?? 4 * 1024 * 1024,
109
+ });
110
+ if (!audited.accepted) {
111
+ const result = { ...audited, receipt: produced.receipt };
112
+ await this.completePermit(authorized, 'patch-result', result, [Buffer.from(produced.content, 'utf8')]);
113
+ durablyCompleted = true;
114
+ return result;
115
+ }
116
+ const preconditions = {};
117
+ for (const file of audited.files) {
118
+ try {
119
+ const inspected = await inspectCanonicalFile({
120
+ root: this.options.workspaceRoot,
121
+ path: file.path,
122
+ deniedPaths: this.deniedRepositoryPaths(),
123
+ });
124
+ preconditions[file.path] = inspected?.identity ?? null;
125
+ }
126
+ catch (error) {
127
+ const result = {
128
+ accepted: false,
129
+ reason: error instanceof Error && /hard-linked|non-regular/u.test(error.message)
130
+ ? 'canonical-non-regular-or-hard-linked-file-forbidden'
131
+ : 'canonical-path-precondition-rejected',
132
+ receipt: produced.receipt,
133
+ };
134
+ await this.completePermit(authorized, 'patch-result', result, [Buffer.from(produced.content, 'utf8')]);
135
+ durablyCompleted = true;
136
+ return result;
137
+ }
138
+ }
139
+ const result = { ...audited, preconditions, receipt: produced.receipt };
140
+ await this.completePermit(authorized, 'patch-result', result, [Buffer.from(produced.content, 'utf8')]);
141
+ durablyCompleted = true;
142
+ return result;
143
+ }
144
+ finally {
145
+ if (durablyCompleted)
146
+ await produced.discard();
147
+ }
148
+ }
149
+ validatePermit(permit, capability) {
150
+ if (permit.capability !== capability || permit.network !== 'deny'
151
+ || permit.workspace !== 'read-only') {
152
+ throw new Error(`Mission repository executor received an invalid ${capability} permit.`);
153
+ }
154
+ return authorizeMissionCapability(permit);
155
+ }
156
+ async beginPermit(authorized) {
157
+ await this.snapshotVerifier.verify(authorized.inputSnapshot);
158
+ const result = await this.permitAuthority.begin(authorized);
159
+ if (result.kind === 'completed') {
160
+ return this.permitAuthority.readReceipt(result.receiptSha256);
161
+ }
162
+ return undefined;
163
+ }
164
+ deniedRepositoryPaths() {
165
+ return [...missionDefaultDeniedRepositoryPaths, ...(this.options.deniedRepositoryPaths ?? [])];
166
+ }
167
+ async completePermit(permit, kind, value, artifacts = []) {
168
+ await this.snapshotVerifier.verify(permit.inputSnapshot);
169
+ await this.permitAuthority.complete(permit, encodeActionReceipt(kind, value), artifacts);
170
+ }
171
+ }
172
+ function encodeActionReceipt(kind, value) {
173
+ return Buffer.from(JSON.stringify({ version: 1, kind, value }), 'utf8');
174
+ }
175
+ function decodeActionReceipt(payload, expectedKind) {
176
+ let parsed;
177
+ try {
178
+ parsed = JSON.parse(payload.toString('utf8'));
179
+ }
180
+ catch {
181
+ parsed = undefined;
182
+ }
183
+ if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
184
+ throw new Error('Mission action receipt payload is invalid.');
185
+ }
186
+ const record = parsed;
187
+ if (record.version !== 1 || record.kind !== expectedKind || !('value' in record)) {
188
+ throw new Error(`Mission action receipt kind does not match ${expectedKind}.`);
189
+ }
190
+ return record.value;
191
+ }
192
+ //# sourceMappingURL=mission-repository-executor.js.map