@moretea-labs/forge 1.7.0 → 1.7.1
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/AGENTS.md +2 -0
- package/CHANGELOG.md +13 -0
- package/CLAUDE.md +2 -0
- package/THIRD_PARTY_NOTICES.md +1 -1
- package/agents/openai.yaml +1 -1
- package/assets/partials-agents/02-operating-mode.partial.md +2 -0
- package/assets/plugin-registry.v1.json +3 -3
- package/assets/skill-version.json +2 -2
- package/assets/templates/helpers/check-architecture-sync.sh +17 -0
- package/assets/templates/helpers/inspect-project-state.ts +8 -6
- package/assets/templates/helpers/migrate-workflow-docs.ts +9 -7
- package/assets/templates/helpers/workflow-contract.ts +5 -1
- package/docs/architecture/CURRENT.md +12 -4
- package/docs/forge-plugin-management.md +1 -1
- package/docs/operations/controller-performance-and-502.md +19 -0
- package/docs/operations/homebrew.md +2 -2
- package/package.json +5 -2
- package/scripts/architecture-event.ts +2 -820
- package/scripts/architecture-queue.sh +2 -645
- package/scripts/archive-architecture-request.sh +2 -242
- package/scripts/archive-workflow.sh +1 -291
- package/scripts/benchmark-work-efficiency.ts +0 -0
- package/scripts/capability-config.ts +2 -392
- package/scripts/capability-resolver.ts +2 -503
- package/scripts/capture-plan.sh +1 -332
- package/scripts/check-agent-tooling.sh +2 -1531
- package/scripts/check-architecture-sync.sh +2 -302
- package/scripts/check-brain-manifest.sh +2 -253
- package/scripts/check-context-files.sh +2 -47
- package/scripts/check-deploy-sql-order.sh +2 -115
- package/scripts/check-runtime-architecture.mjs +243 -16
- package/scripts/check-skill-version.ts +3 -191
- package/scripts/check-source-duplication.mjs +61 -0
- package/scripts/check-stable-baseline.ts +0 -0
- package/scripts/check-task-sync.sh +2 -63
- package/scripts/check-task-workflow.sh +2 -1000
- package/scripts/codex-handoff-resume.sh +2 -267
- package/scripts/context-contract-sync.sh +2 -514
- package/scripts/contract-run.ts +2 -463
- package/scripts/contract-worktree.sh +1 -702
- package/scripts/ensure-task-workflow.sh +1 -1192
- package/scripts/inspect-project-state.ts +4 -279
- package/scripts/lib/project-init-lib.sh +7 -2
- package/scripts/lib/run-forge-helper.sh +19 -0
- package/scripts/lib/run-forge-helper.ts +26 -0
- package/scripts/migrate-project-template.sh +1 -33
- package/scripts/migrate-workflow-docs.ts +4 -412
- package/scripts/new-plan.sh +1 -180
- package/scripts/new-spec.sh +1 -47
- package/scripts/new-sprint.sh +1 -46
- package/scripts/plan-to-todo.sh +1 -771
- package/scripts/prepare-codex-handoff.sh +2 -201
- package/scripts/prepare-handoff.sh +1 -78
- package/scripts/refresh-current-status.sh +2 -467
- package/scripts/run-governed-gate.ts +3 -0
- package/scripts/select-agent-context-blocks.sh +2 -64
- package/scripts/ship-worktrees.sh +1 -531
- package/scripts/sprint-backlog.sh +1 -834
- package/scripts/stage-runtime-release.ts +2 -1
- package/scripts/summarize-failures.sh +2 -123
- package/scripts/switch-plan.sh +1 -150
- package/scripts/sync-brain-docs.sh +2 -379
- package/scripts/sync-generated-authority.mjs +175 -0
- package/scripts/verify-contract.sh +2 -593
- package/scripts/verify-sprint.sh +1 -500
- package/scripts/workflow-contract.ts +4 -201
- package/scripts/workstream-sync.sh +2 -261
- package/src/cli/agent-jobs/executor-health.ts +1 -1
- package/src/cli/commands/plugin.ts +12 -3
- package/src/cli/controller/check-runner.ts +7 -2
- package/src/cli/controller/context-pack.ts +46 -21
- package/src/cli/github/contracts.ts +16 -0
- package/src/cli/github/github.ts +2 -16
- package/src/cli/github/session.ts +2 -1
- package/src/cli/local-bridge/facade-api.ts +37 -47
- package/src/cli/local-bridge/server.ts +2 -2
- package/src/cli/mcp/legacy-tool-service.ts +10 -33
- package/src/cli/mcp/post-finalize-work-attribution.ts +150 -0
- package/src/cli/mcp/repository-tools.ts +85 -89
- package/src/cli/mcp/server.ts +57 -13
- package/src/cli/mcp/tool-contract.ts +14 -0
- package/src/cli/mcp/toolset.ts +2 -2
- package/src/cli/mcp/transports/http.ts +23 -0
- package/src/cli/repositories/command-classifier.ts +2 -2
- package/src/cli/repositories/command-executor.ts +24 -6
- package/src/cli/repositories/repository-snapshot.ts +5 -2
- package/src/cli/repositories/structured-git.ts +57 -3
- package/src/cli/repository/inspector.ts +11 -3
- package/src/runtime/context/generic-lsp-provider.ts +1 -1
- package/src/runtime/context/semantic-navigation-contract.ts +61 -0
- package/src/runtime/context/semantic-navigation.ts +9 -61
- package/src/runtime/control-plane/execution/direct-edit-work-completion.ts +18 -25
- package/src/runtime/control-plane/execution/repository-work-attribution.ts +106 -0
- package/src/runtime/control-plane/execution/retained-work-resume.ts +203 -0
- package/src/runtime/control-plane/execution/work-completion-authority.ts +58 -0
- package/src/runtime/control-plane/execution/work-evidence-policy.ts +200 -0
- package/src/runtime/control-plane/execution/work-execution-support.ts +386 -0
- package/src/runtime/control-plane/execution/work-finalization-service.ts +1913 -0
- package/src/runtime/control-plane/execution/work-handle-authority.ts +96 -0
- package/src/runtime/control-plane/execution/work-handle-store.ts +1 -1
- package/src/runtime/control-plane/execution/work-operation-service.ts +468 -0
- package/src/runtime/control-plane/execution/work-path-scope.ts +37 -0
- package/src/runtime/control-plane/execution/work-preparation-service.ts +479 -0
- package/src/runtime/control-plane/execution/work-process-evidence.ts +129 -0
- package/src/runtime/control-plane/execution/work-task-receipt.ts +4 -43
- package/src/runtime/control-plane/execution/work-terminal-cleanup.ts +13 -3
- package/src/runtime/control-plane/execution/work-verification-context.ts +56 -0
- package/src/runtime/control-plane/execution/work-verification-service.ts +388 -0
- package/src/runtime/control-plane/execution/work-verification-snapshot.ts +5 -1
- package/src/runtime/control-plane/facade/controller-round-relay.ts +164 -37
- package/src/runtime/control-plane/facade/controller-session-store.ts +183 -24
- package/src/runtime/control-plane/facade/goal-workloop-access.ts +15 -1
- package/src/runtime/control-plane/facade/goal-workloop.ts +329 -148
- package/src/runtime/control-plane/facade/index.ts +2 -0
- package/src/runtime/control-plane/facade/plan-contract-store.ts +90 -22
- package/src/runtime/control-plane/facade/repository-work-admission.ts +147 -0
- package/src/runtime/control-plane/facade/requirement-authority.ts +83 -0
- package/src/runtime/control-plane/facade/types.ts +68 -5
- package/src/runtime/control-plane/facade/work-contract-store.ts +3 -209
- package/src/runtime/control-plane/facade/work-state-machine.ts +250 -0
- package/src/runtime/control-plane/global-scheduler/maintenance.ts +14 -7
- package/src/runtime/control-plane/global-scheduler/scheduler.ts +5 -1
- package/src/runtime/control-plane/launcher/chatgpt-work-binding-store.ts +13 -0
- package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +15 -6
- package/src/runtime/control-plane/launcher/launch-reservation-store.ts +54 -5
- package/src/runtime/control-plane/launcher/thin-launcher.ts +56 -7
- package/src/runtime/control-plane/persistence/requirement-store.ts +0 -12
- package/src/runtime/control-plane/repo-actor/registry.ts +4 -2
- package/src/runtime/control-plane/routing/route-policy.ts +18 -6
- package/src/runtime/control-plane/routing/workspace-admission.ts +70 -0
- package/src/runtime/evidence/process-check-execution.ts +18 -0
- package/src/runtime/execution/jobs/child-reference.ts +6 -2
- package/src/runtime/execution/process-runtime/check-result.ts +53 -18
- package/src/runtime/execution/process-runtime/check-runner-sidecar.ts +7 -1
- package/src/runtime/execution/process-runtime/command-facade.ts +39 -17
- package/src/runtime/execution/process-runtime/lightweight-managed.ts +20 -3
- package/src/runtime/execution/process-runtime/persisted-check.ts +4 -1
- package/src/runtime/execution/process-runtime/runtime.ts +10 -0
- package/src/runtime/execution/process-runtime/types.ts +2 -12
- package/src/runtime/execution/work-activity.ts +21 -0
- package/src/runtime/execution/workers/executor.ts +18 -13
- package/src/runtime/gateway/mcp/execution-tools.ts +35 -2930
- package/src/runtime/gateway/mcp/legacy-ios-tool-adapter.ts +61 -0
- package/src/runtime/gateway/mcp/router.ts +2 -2
- package/src/runtime/gateway/mcp/runtime-tool-definitions.ts +21 -2
- package/src/runtime/gateway/mcp/runtime-tools.ts +805 -1009
- package/src/runtime/plugins/app-store-connect-adapter.ts +93 -28
- package/src/runtime/plugins/browser-adapter.ts +256 -1083
- package/src/runtime/plugins/browser-handoff-host.ts +2 -25
- package/src/runtime/plugins/browser-handoff.ts +18 -3
- package/src/runtime/plugins/browser-macos-bridge.ts +121 -16
- package/src/runtime/plugins/browser-manifest-surface.ts +603 -0
- package/src/runtime/plugins/browser-native-session-service.ts +222 -0
- package/src/runtime/plugins/browser-runtime-contract.ts +2 -0
- package/src/runtime/plugins/browser-runtime.ts +10 -0
- package/src/runtime/plugins/browser-session-store.ts +121 -0
- package/src/runtime/plugins/browser-session-types.ts +98 -0
- package/src/runtime/plugins/desktop-operator-registration.ts +4 -4
- package/src/runtime/plugins/external-adapter.ts +92 -58
- package/src/runtime/plugins/macos-capability-broker.ts +0 -8
- package/src/runtime/plugins/store.ts +66 -9
- package/src/runtime/plugins/types.ts +3 -1
- package/src/runtime/recovery/maintenance-executor.ts +61 -25
- package/src/runtime/root/package-connector-service.ts +46 -4
- package/src/runtime/root/package-runtime-release.ts +1 -1
- package/src/runtime/root/package-runtime-service.ts +33 -2
- package/src/runtime/root/release-manifest.ts +137 -16
- package/src/runtime/root/release-materialize.ts +109 -35
- package/src/runtime/root/types.ts +10 -0
- package/src/runtime/standalone-recovery/core.ts +425 -194
- package/src/runtime/standalone-recovery/entry.ts +1 -1
- package/src/runtime/standalone-recovery/installer.ts +1 -1
- package/src/runtime/workflow/schedules/engine.ts +113 -87
- package/src/runtime/workflow/schedules/settlement.ts +26 -23
- package/src/runtime/workflow/schedules/store.ts +79 -10
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
import type { RepositoryRecord } from '../../../cli/repositories/types';
|
|
12
12
|
import { repositoryGitStatus } from '../../../cli/repositories/structured-git';
|
|
13
|
-
import { classifyRepositoryCommand, fixedShellWrapperCommand } from '../../../cli/repositories/command-classifier';
|
|
13
|
+
import { classifyRepositoryCommand, fixedShellWrapperCommand, shellSegments, shellWordsPreservingQuotes } from '../../../cli/repositories/command-classifier';
|
|
14
14
|
import {
|
|
15
15
|
executeRepositoryCommandAsync,
|
|
16
16
|
executeRepositoryReadOnlyCommandDirect,
|
|
@@ -237,29 +237,40 @@ function repositoryCommandRecoveryLifecycle(command: string | readonly string[])
|
|
|
237
237
|
return wrapped ? recoveryLifecycleFromShell(wrapped) : undefined;
|
|
238
238
|
}
|
|
239
239
|
|
|
240
|
-
function
|
|
241
|
-
const
|
|
242
|
-
if (
|
|
243
|
-
|
|
244
|
-
}
|
|
245
|
-
const executable = commandBasename(normalized.executable ?? '');
|
|
246
|
-
const args = [...(normalized.args ?? [])];
|
|
247
|
-
if (executable !== 'git') {
|
|
248
|
-
const wrapped = fixedShellWrapperCommand(normalized.value as string[]);
|
|
249
|
-
return wrapped ? /(?:^|[;&|]\s*)\s*git\s+commit\b/i.test(wrapped) : false;
|
|
250
|
-
}
|
|
240
|
+
function gitCommitWordsRequireExplicitPathScope(words: readonly string[]): boolean | undefined {
|
|
241
|
+
const executable = commandBasename(words[0] ?? '');
|
|
242
|
+
if (executable !== 'git') return undefined;
|
|
243
|
+
const args = words.slice(1);
|
|
251
244
|
let index = 0;
|
|
252
245
|
while (index < args.length && args[index]?.startsWith('-')) {
|
|
253
246
|
const option = args[index]!;
|
|
254
247
|
if (['-c', '-C', '--git-dir', '--work-tree', '--namespace'].includes(option)) index += 2;
|
|
248
|
+
else if (['--git-dir=', '--work-tree=', '--namespace='].some((prefix) => option.startsWith(prefix))) index += 1;
|
|
255
249
|
else index += 1;
|
|
256
250
|
}
|
|
257
|
-
if (args[index]?.toLowerCase() !== 'commit') return
|
|
251
|
+
if (args[index]?.toLowerCase() !== 'commit') return undefined;
|
|
258
252
|
const commitArgs = args.slice(index + 1);
|
|
259
253
|
const pathSeparator = commitArgs.indexOf('--');
|
|
260
|
-
const hasExplicitOnly = commitArgs.includes('--only') || commitArgs.includes('-o');
|
|
261
254
|
const paths = pathSeparator >= 0 ? commitArgs.slice(pathSeparator + 1).filter(Boolean) : [];
|
|
262
|
-
|
|
255
|
+
const widensScope = commitArgs.some((arg) => ['-a', '--all', '-i', '--include', '--interactive', '-p', '--patch'].includes(arg));
|
|
256
|
+
return paths.length === 0 || widensScope;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function rawGitCommitRequiresExplicitPathScope(command: string | readonly string[]): boolean {
|
|
260
|
+
const normalized = normalizeRepositoryCommand(command);
|
|
261
|
+
if (normalized.kind === 'argv') {
|
|
262
|
+
const direct = gitCommitWordsRequireExplicitPathScope([
|
|
263
|
+
normalized.executable ?? '',
|
|
264
|
+
...(normalized.args ?? []),
|
|
265
|
+
]);
|
|
266
|
+
if (direct !== undefined) return direct;
|
|
267
|
+
const wrapped = fixedShellWrapperCommand(normalized.value as string[]);
|
|
268
|
+
if (!wrapped) return false;
|
|
269
|
+
return shellSegments(wrapped)
|
|
270
|
+
.some((segment) => gitCommitWordsRequireExplicitPathScope(shellWordsPreservingQuotes(segment)) === true);
|
|
271
|
+
}
|
|
272
|
+
return shellSegments(normalized.shellCommand ?? '')
|
|
273
|
+
.some((segment) => gitCommitWordsRequireExplicitPathScope(shellWordsPreservingQuotes(segment)) === true);
|
|
263
274
|
}
|
|
264
275
|
|
|
265
276
|
function toProcessCommand(command: string | readonly string[], cwd: string): ProcessCommandSpec {
|
|
@@ -286,6 +297,7 @@ export function classifyRepositoryCommandRoute(
|
|
|
286
297
|
command: string | readonly string[],
|
|
287
298
|
options: {
|
|
288
299
|
forceDurable?: boolean;
|
|
300
|
+
workId?: string;
|
|
289
301
|
defaultBranch?: string;
|
|
290
302
|
timeoutMs?: number;
|
|
291
303
|
} = {},
|
|
@@ -300,6 +312,12 @@ export function classifyRepositoryCommandRoute(
|
|
|
300
312
|
return { route: 'durable', reason: 'force_durable_or_async' };
|
|
301
313
|
}
|
|
302
314
|
const classification = classifyRepositoryCommand(command, options.defaultBranch);
|
|
315
|
+
// Work-bound effects must survive Controller/Runtime rotation with one durable
|
|
316
|
+
// Process identity. Read-only observations can remain ephemeral because they
|
|
317
|
+
// have no ambiguous side effect to reconcile after a restart.
|
|
318
|
+
if (options.workId?.trim() && classification.risk !== 'readonly') {
|
|
319
|
+
return { route: 'process_managed', reason: 'work_attributed_effectful_durable' };
|
|
320
|
+
}
|
|
303
321
|
const text = Array.isArray(command) ? command.join(' ') : String(command);
|
|
304
322
|
// Classification chooses scheduling/receipt granularity only; it does not
|
|
305
323
|
// decide whether a scoped repository command is allowed to run. Known remote
|
|
@@ -354,8 +372,7 @@ export async function executeRepositoryCommandViaProcessRuntime(
|
|
|
354
372
|
assertRepositoryCommandNoPluginExecutionBypass(input.command);
|
|
355
373
|
const decision = classifyRepositoryCommandRoute(input.command, {
|
|
356
374
|
forceDurable: input.forceDurable,
|
|
357
|
-
|
|
358
|
-
// execution lane of an otherwise ordinary local repository command.
|
|
375
|
+
workId: input.workId,
|
|
359
376
|
defaultBranch: input.repository.defaultBranch,
|
|
360
377
|
timeoutMs: input.timeoutMs,
|
|
361
378
|
});
|
|
@@ -454,6 +471,11 @@ export async function executeRepositoryCommandViaProcessRuntime(
|
|
|
454
471
|
deferStart: deferLongPreparation,
|
|
455
472
|
reuseActiveEquivalent: deferLongPreparation,
|
|
456
473
|
onCompleted: (result) => {
|
|
474
|
+
// A terminal child exit is sufficient to close the Process, but not to
|
|
475
|
+
// advance Work mutation authority when post-execution repository
|
|
476
|
+
// evidence is unavailable. Finalization must keep failing closed until
|
|
477
|
+
// a later authoritative repository inspection proves the new HEAD.
|
|
478
|
+
if (result.evidenceError) return;
|
|
457
479
|
settleWorkHandleExpectedHeadAfterRepositoryCommand({
|
|
458
480
|
controllerHome: input.controllerHome,
|
|
459
481
|
repository: input.repository,
|
|
@@ -52,6 +52,8 @@ interface LightweightExecutionResult {
|
|
|
52
52
|
cancelled?: boolean;
|
|
53
53
|
stdout?: string;
|
|
54
54
|
stderr?: string;
|
|
55
|
+
/** Child execution completed, but repository mutation evidence could not be proven. */
|
|
56
|
+
evidenceError?: { code: string; message: string };
|
|
55
57
|
}
|
|
56
58
|
|
|
57
59
|
interface LightweightExitObservation {
|
|
@@ -714,16 +716,31 @@ export async function startLightweightRepositoryCommand(
|
|
|
714
716
|
timedOut: result.timedOut,
|
|
715
717
|
cancelled: result.cancelled,
|
|
716
718
|
};
|
|
717
|
-
|
|
719
|
+
// Child exit is the authoritative Process terminal boundary. Repository
|
|
720
|
+
// post-processing may continue, but it must never keep this Process
|
|
721
|
+
// logically running or make process_get/process_wait lose the exit fact.
|
|
722
|
+
entry.result = result;
|
|
723
|
+
entry.finishedAtMs = Date.now();
|
|
724
|
+
input.execution.signal?.removeEventListener('abort', onCallerAbort);
|
|
725
|
+
persistTerminalReceipt(input.controllerHome, entry);
|
|
718
726
|
},
|
|
719
727
|
},
|
|
720
728
|
).then((result) => {
|
|
729
|
+
// Enriched execution evidence may replace the compact child-exit result in
|
|
730
|
+
// memory. The already-persisted terminal Process identity remains stable.
|
|
731
|
+
// Work lifecycle settlement belongs here, after repository evidence has
|
|
732
|
+
// either been proven or explicitly marked unavailable.
|
|
721
733
|
entry.result = result;
|
|
722
|
-
entry.finishedAtMs = Date.now();
|
|
723
|
-
input.execution.signal?.removeEventListener('abort', onCallerAbort);
|
|
724
734
|
input.onCompleted?.(result);
|
|
725
735
|
persistTerminalReceipt(input.controllerHome, entry);
|
|
726
736
|
return result;
|
|
737
|
+
}).catch((error) => {
|
|
738
|
+
// Once child exit has been observed, later bookkeeping failure cannot revoke
|
|
739
|
+
// the terminal Process fact or trigger command replay. Expected snapshot
|
|
740
|
+
// degradation is represented by RepositoryCommandExecution.evidenceError;
|
|
741
|
+
// this catch is the final fail-safe for any later post-processing exception.
|
|
742
|
+
if (entry.exitObservation && entry.result) return entry.result;
|
|
743
|
+
throw error;
|
|
727
744
|
});
|
|
728
745
|
entry.promise = input.deferStart
|
|
729
746
|
? new Promise<LightweightExecutionResult>((resolve, reject) => {
|
|
@@ -276,7 +276,10 @@ export async function runPersistedCheckViaProcessRuntime(
|
|
|
276
276
|
checkFingerprint,
|
|
277
277
|
'--result-receipt',
|
|
278
278
|
checkResultReceiptPath,
|
|
279
|
-
...(verificationSnapshot ? [
|
|
279
|
+
...(verificationSnapshot ? [
|
|
280
|
+
'--isolated-controller-home', verificationSnapshot.isolatedControllerHome,
|
|
281
|
+
'--cleanup-root', verificationSnapshot.root,
|
|
282
|
+
] : []),
|
|
280
283
|
];
|
|
281
284
|
const invocation = resolvePersistedCheckProcessInvocation(cliTarget, checkArgs);
|
|
282
285
|
let handle;
|
|
@@ -694,6 +694,16 @@ export function resolveProcessRunnerEntryPath(
|
|
|
694
694
|
const configured = env.FORGE_PROCESS_RUNNER_ENTRY?.trim();
|
|
695
695
|
if (configured && existsSync(configured)) return configured;
|
|
696
696
|
|
|
697
|
+
// macOS launchd runs the immutable Runtime through a stable mirrored
|
|
698
|
+
// executable path for TCC identity. In that mode process.execPath is not a
|
|
699
|
+
// sibling of the active release sidecars, so use the release authority path
|
|
700
|
+
// exported by the launch contract before any executable/source fallback.
|
|
701
|
+
const releaseRoot = env.FORGE_RELEASE_PATH?.trim();
|
|
702
|
+
if (releaseRoot) {
|
|
703
|
+
const releaseRunner = join(releaseRoot, 'process-runner.js');
|
|
704
|
+
if (existsSync(releaseRunner)) return releaseRunner;
|
|
705
|
+
}
|
|
706
|
+
|
|
697
707
|
// Compiled daemon/Gateway entrypoints and process-runner.js are siblings in
|
|
698
708
|
// every immutable release. Prefer that closed release surface before looking
|
|
699
709
|
// at source paths recorded only for diagnostics and development fallback.
|
|
@@ -140,18 +140,8 @@ export interface ProcessRequestBinding {
|
|
|
140
140
|
createdAt: string;
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
schemaVersion: 1;
|
|
146
|
-
checkId: string;
|
|
147
|
-
cacheKey: string;
|
|
148
|
-
revision: string;
|
|
149
|
-
definitionDigest: string;
|
|
150
|
-
environmentFingerprint: string;
|
|
151
|
-
timeoutMs: number;
|
|
152
|
-
reuseScope: 'repository' | 'checkout';
|
|
153
|
-
scopeKey: string;
|
|
154
|
-
}
|
|
143
|
+
export type { ProcessCheckExecutionIdentity } from '../../evidence/process-check-execution';
|
|
144
|
+
import type { ProcessCheckExecutionIdentity } from '../../evidence/process-check-execution';
|
|
155
145
|
|
|
156
146
|
/** Persistent semantic Check binding to one physical Process record. */
|
|
157
147
|
export interface ProcessCheckExecutionBinding {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { listActiveExecutionJobs } from './jobs/store';
|
|
2
|
+
import type { ExecutionJob } from './jobs/types';
|
|
3
|
+
import { listRecoverableProcessRecords } from './process-runtime/store';
|
|
4
|
+
import { isManagedProcessActive } from './process-runtime/types';
|
|
5
|
+
|
|
6
|
+
export function executionJobBelongsToWork(job: ExecutionJob, workId: string): boolean {
|
|
7
|
+
if (job.resourceClaims.some((claim) => claim.workId === workId)) return true;
|
|
8
|
+
const payload = job.payload as Record<string, unknown>;
|
|
9
|
+
const args = payload.arguments && typeof payload.arguments === 'object' && !Array.isArray(payload.arguments)
|
|
10
|
+
? payload.arguments as Record<string, unknown>
|
|
11
|
+
: undefined;
|
|
12
|
+
return [payload.workId, payload.work_id, args?.workId, args?.work_id].some((value) => value === workId);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function workHasActiveExecution(controllerHome: string, repoId: string, workId: string): boolean {
|
|
16
|
+
const activeProcess = listRecoverableProcessRecords(controllerHome, repoId)
|
|
17
|
+
.some((record) => record.workId === workId && isManagedProcessActive(record));
|
|
18
|
+
if (activeProcess) return true;
|
|
19
|
+
return listActiveExecutionJobs(controllerHome, repoId)
|
|
20
|
+
.some((job) => executionJobBelongsToWork(job, workId));
|
|
21
|
+
}
|
|
@@ -28,6 +28,8 @@ import { writeExecutionArtifact } from '../../evidence/artifact-store';
|
|
|
28
28
|
import { existsSync } from 'fs';
|
|
29
29
|
import { isAbsolute, relative, resolve, sep } from 'path';
|
|
30
30
|
import { isAssistantPluginError } from '../../plugins/errors';
|
|
31
|
+
import { executeWork, validateWork } from '../../control-plane/execution/work-operation-service';
|
|
32
|
+
import { finalizeWork } from '../../control-plane/execution/work-finalization-service';
|
|
31
33
|
|
|
32
34
|
|
|
33
35
|
function childReferenceFromLocalJob(
|
|
@@ -524,23 +526,26 @@ export async function executeExecutionJob(controllerHome: string, job: Execution
|
|
|
524
526
|
toolset: job.payload.toolset === 'core' || job.payload.toolset === 'full' ? job.payload.toolset : 'advanced',
|
|
525
527
|
toolsetLocked: true,
|
|
526
528
|
};
|
|
527
|
-
//
|
|
528
|
-
//
|
|
529
|
-
// creation while preserving the existing Work validation/authorization path.
|
|
529
|
+
// Durable Work mutations execute through control-plane application services.
|
|
530
|
+
// The Worker must never import MCP transport to obtain Work semantics.
|
|
530
531
|
const durableWorkOperation = job.payload.operation === 'work_execute'
|
|
531
532
|
|| job.payload.operation === 'work_validate'
|
|
532
533
|
|| job.payload.operation === 'work_finalize';
|
|
533
|
-
// Load the Work implementation only for Work Jobs. A static import here
|
|
534
|
-
// creates an initialization cycle through repository command and Local Bridge
|
|
535
|
-
// modules, changing unrelated execution behavior.
|
|
536
534
|
const toolArguments = { ...(job.payload.arguments ?? {}) };
|
|
537
|
-
const
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
535
|
+
const workArguments = {
|
|
536
|
+
...toolArguments,
|
|
537
|
+
__from_durable_worker: true,
|
|
538
|
+
__execution_job_id: job.jobId,
|
|
539
|
+
};
|
|
540
|
+
const executionRecord = job.payload.operation === 'work_execute'
|
|
541
|
+
? await executeWork(runtimeContext, workArguments)
|
|
542
|
+
: job.payload.operation === 'work_validate'
|
|
543
|
+
? await validateWork(runtimeContext, workArguments)
|
|
544
|
+
: job.payload.operation === 'work_finalize'
|
|
545
|
+
? await finalizeWork(runtimeContext, workArguments)
|
|
546
|
+
: undefined;
|
|
547
|
+
const executionResult: CallToolResult | undefined = durableWorkOperation && executionRecord
|
|
548
|
+
? { structuredContent: executionRecord, content: [] }
|
|
544
549
|
: undefined;
|
|
545
550
|
const runtimeResult = executionResult ?? (policy.profile === 'controller'
|
|
546
551
|
? await callRuntimeTool(runtimeContext, job.payload.operation, toolArguments)
|