@moretea-labs/forge 1.5.0-rc.1 → 1.5.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 +9 -11
- package/CHANGELOG.md +27 -1
- package/CLAUDE.md +8 -10
- package/DESIGN.md +278 -0
- package/README.md +70 -90
- package/README.zh-CN.md +52 -55
- package/SKILL.md +8 -11
- package/THIRD_PARTY_NOTICES.md +9 -3
- package/assets/branding/README.md +4 -2
- package/assets/hooks/lib/workflow-state.sh +19 -18
- package/assets/hooks/post-edit-guard.sh +6 -75
- package/assets/hooks/prompt-guard.sh +24 -12
- package/assets/hooks/session-start-context.sh +17 -17
- package/assets/hooks/stop-orchestrator.sh +2 -2
- package/assets/partials/04-project-structure.partial.md +6 -6
- package/assets/partials/05-workflow.partial.md +6 -6
- package/assets/partials/07-footer.partial.md +1 -1
- package/assets/partials/08-orchestration.partial.md +2 -2
- package/assets/partials-agents/02-operating-mode.partial.md +5 -5
- package/assets/partials-agents/03-orchestration.partial.md +3 -3
- package/assets/partials-agents/04-task-protocol.partial.md +3 -3
- package/assets/partials-agents/08-deep-docs.partial.md +1 -1
- package/assets/reference-configs/agentic-development-flow.md +49 -86
- package/assets/reference-configs/external-tooling.md +21 -61
- package/assets/reference-configs/handoff-protocol.md +25 -20
- package/assets/reference-configs/harness-overview.md +8 -8
- package/assets/skill-version.json +2 -2
- package/assets/templates/helpers/archive-workflow.sh +0 -1
- package/assets/templates/helpers/capture-plan.sh +3 -3
- package/assets/templates/helpers/check-task-workflow.sh +2 -2
- package/assets/templates/helpers/codex-handoff-resume.sh +5 -5
- package/assets/templates/helpers/ensure-task-workflow.sh +37 -35
- package/assets/templates/helpers/new-plan.sh +1 -1
- package/assets/templates/helpers/plan-to-todo.sh +2 -2
- package/assets/templates/helpers/prepare-codex-handoff.sh +2 -2
- package/assets/templates/helpers/prepare-handoff.sh +9 -9
- package/assets/templates/helpers/refresh-current-status.sh +2 -2
- package/assets/templates/helpers/ship-worktrees.sh +1 -1
- package/assets/templates/helpers/sprint-backlog.sh +1 -1
- package/assets/templates/helpers/verify-sprint.sh +7 -7
- package/assets/templates/helpers/workstream-sync.sh +1 -1
- package/assets/templates/plan.template.md +1 -1
- package/assets/workflow-contract.v1.json +6 -3
- package/docs/architecture/current/README.md +10 -9
- package/docs/architecture/current/approved-target-architecture.zh-CN.md +2 -2
- package/docs/architecture/current/architecture-invariants.md +2 -2
- package/docs/architecture/current/automation-and-schedule-engine.md +15 -15
- package/docs/architecture/current/codegraph-context-provider.md +2 -2
- package/docs/architecture/current/control-plane-authority-inventory.md +12 -0
- package/docs/architecture/current/dispatch-and-agent-strategy.md +11 -11
- package/docs/architecture/current/entity-model.md +0 -27
- package/docs/architecture/current/failure-recovery.md +0 -24
- package/docs/architecture/current/governance.md +1 -1
- package/docs/architecture/current/implementation-status.md +1 -1
- package/docs/architecture/current/legacy-governance.md +58 -0
- package/docs/architecture/current/multi-repository-execution.md +1 -1
- package/docs/architecture/current/peer-supercontroller-runtime.md +1 -1
- package/docs/architecture/current/personal-assistant-plugin-baseline.md +4 -5
- package/docs/architecture/current/scheduler-and-resource-claims.md +0 -10
- package/docs/architecture/current/target-requirements-traceability.md +2 -2
- package/docs/architecture/current/thin-harness-governance-policy.md +1 -1
- package/docs/architecture/current/thin-harness-v1.md +9 -11
- package/docs/architecture/domains/runtime-harness.md +1 -1
- package/docs/forge-autonomous-goal-loop.md +3 -1
- package/docs/forge-chatgpt-mcp-setup.md +67 -176
- package/docs/images/forge-banner-cn.svg +26 -1
- package/docs/images/forge-banner.svg +26 -1
- package/docs/operations/features.md +1 -1
- package/docs/operations/homebrew.md +3 -3
- package/docs/operations/mcp-tool-exposure.md +5 -5
- package/docs/operations/platform-support.md +45 -37
- package/docs/operations/platform-support.zh-CN.md +40 -38
- package/docs/operations/releasing.md +3 -3
- package/docs/operations/releasing.zh-CN.md +3 -3
- package/docs/operations/troubleshooting.md +11 -6
- package/docs/operations/troubleshooting.zh-CN.md +11 -6
- package/docs/public-usage-guide.md +28 -21
- package/docs/public-usage-guide.zh-CN.md +28 -21
- package/docs/tutorials/01-install-and-start.md +58 -35
- package/docs/tutorials/01-install-and-start.zh-CN.md +58 -35
- package/docs/tutorials/02-connect-chatgpt.md +118 -46
- package/docs/tutorials/02-connect-chatgpt.zh-CN.md +119 -45
- package/docs/wiki/Architecture.md +1 -1
- package/docs/wiki/Installation.md +2 -2
- package/docs/wiki/Quick-Start.md +1 -1
- package/docs/wiki/Work-Lifecycle.md +1 -1
- package/install.ps1 +4 -5
- package/install.sh +4 -6
- package/package.json +15 -5
- package/scripts/archive-workflow.sh +0 -1
- package/scripts/benchmark-thin-harness-mcp-e2e.ts +27 -14
- package/scripts/build-controller-ui.ts +28 -0
- package/scripts/capture-plan.sh +4 -4
- package/scripts/check-agent-tooling.sh +12 -1
- package/scripts/check-platform-support.mjs +2 -2
- package/scripts/check-public-docs.sh +16 -5
- package/scripts/check-release-readiness.sh +5 -11
- package/scripts/check-runtime-architecture.mjs +14 -22
- package/scripts/check-tarball-install-smoke.sh +3 -2
- package/scripts/check-task-workflow.sh +2 -2
- package/scripts/codex-handoff-resume.sh +5 -5
- package/scripts/create-project-dirs.sh +3 -3
- package/scripts/ensure-task-workflow.sh +45 -35
- package/scripts/init-project.sh +4 -4
- package/scripts/install-desktop-operator-registration.ts +2 -2
- package/scripts/lib/project-init-lib.sh +46 -44
- package/scripts/migrate-project-template.sh +7 -4
- package/scripts/new-plan.sh +1 -1
- package/scripts/plan-to-todo.sh +2 -2
- package/scripts/prepare-codex-handoff.sh +2 -2
- package/scripts/prepare-handoff.sh +9 -9
- package/scripts/refresh-current-status.sh +2 -2
- package/scripts/setup-plugins.sh +3 -3
- package/scripts/ship-worktrees.sh +1 -1
- package/scripts/sprint-backlog.sh +5 -5
- package/scripts/sync-codex-installed-copies.sh +2 -3
- package/scripts/verify-sprint.sh +7 -7
- package/scripts/workstream-sync.sh +1 -1
- package/src/cli/chatgpt-browser/bridge-extension.ts +1 -1
- package/src/cli/chatgpt-browser/bridge-provider.ts +29 -0
- package/src/cli/chatgpt-browser/file-policy.ts +3 -1
- package/src/cli/commands/chatgpt.ts +51 -0
- package/src/cli/commands/doctor.ts +1 -1
- package/src/cli/commands/init-hook.ts +213 -70
- package/src/cli/commands/init.ts +5 -6
- package/src/cli/commands/mcp.ts +31 -5
- package/src/cli/commands/runtime.ts +61 -8
- package/src/cli/commands/setup-profile.ts +472 -0
- package/src/cli/controller/check-runner.ts +20 -3
- package/src/cli/controller/codex-continuation.ts +4 -7
- package/src/cli/controller/context-pack.ts +118 -14
- package/src/cli/controller/operational-plan.ts +4 -4
- package/src/cli/controller/task-ledger.ts +10 -10
- package/src/cli/controller/work-mode.ts +6 -13
- package/src/cli/index.ts +14 -35
- package/src/cli/local-bridge/connector-freshness.ts +1 -1
- package/src/cli/local-bridge/console-assets.ts +17 -0
- package/src/cli/local-bridge/console-automations.ts +160 -0
- package/src/cli/local-bridge/dashboard.ts +8 -1303
- package/src/cli/local-bridge/facade-api.ts +16 -7
- package/src/cli/local-bridge/frontend/src/App.tsx +10 -0
- package/src/cli/local-bridge/frontend/src/components/Button.tsx +1 -0
- package/src/cli/local-bridge/frontend/src/components/DetailPane.tsx +3 -0
- package/src/cli/local-bridge/frontend/src/components/SearchField.tsx +1 -0
- package/src/cli/local-bridge/frontend/src/components/SectionHeader.tsx +1 -0
- package/src/cli/local-bridge/frontend/src/components/Segmented.tsx +1 -0
- package/src/cli/local-bridge/frontend/src/components/StatusText.tsx +3 -0
- package/src/cli/local-bridge/frontend/src/design/icons.tsx +11 -0
- package/src/cli/local-bridge/frontend/src/design/tokens.css +8 -0
- package/src/cli/local-bridge/frontend/src/features/automations/AutomationsView.tsx +3 -0
- package/src/cli/local-bridge/frontend/src/features/capabilities/CapabilitiesView.tsx +4 -0
- package/src/cli/local-bridge/frontend/src/features/overview/OverviewView.tsx +3 -0
- package/src/cli/local-bridge/frontend/src/features/repositories/RepositoriesView.tsx +2 -0
- package/src/cli/local-bridge/frontend/src/features/settings/SettingsView.tsx +2 -0
- package/src/cli/local-bridge/frontend/src/features/system/SystemView.tsx +2 -0
- package/src/cli/local-bridge/frontend/src/features/work/WorkView.tsx +3 -0
- package/src/cli/local-bridge/frontend/src/lib/api.ts +23 -0
- package/src/cli/local-bridge/frontend/src/lib/format.ts +4 -0
- package/src/cli/local-bridge/frontend/src/lib/routes.ts +7 -0
- package/src/cli/local-bridge/frontend/src/main.tsx +1 -0
- package/src/cli/local-bridge/frontend/src/shell/AppShell.tsx +1 -0
- package/src/cli/local-bridge/frontend/src/shell/CommandBar.tsx +2 -0
- package/src/cli/local-bridge/frontend/src/shell/Sidebar.tsx +3 -0
- package/src/cli/local-bridge/frontend/src/styles.css +12 -0
- package/src/cli/local-bridge/frontend/src/types.ts +14 -0
- package/src/cli/local-bridge/frontend/src/vite-env.d.ts +1 -0
- package/src/cli/local-bridge/frontend/vite.config.ts +27 -0
- package/src/cli/local-bridge/server.ts +45 -0
- package/src/cli/local-bridge/ui-dist/app.css +1 -0
- package/src/cli/local-bridge/ui-dist/app.js +11094 -0
- package/src/cli/mcp/auth.ts +2 -0
- package/src/cli/mcp/instructions.ts +3 -3
- package/src/cli/mcp/legacy-tool-service.ts +27 -23
- package/src/cli/mcp/multi-repository.ts +2 -0
- package/src/cli/mcp/policy.ts +7 -5
- package/src/cli/mcp/repository-tools.ts +53 -14
- package/src/cli/mcp/server.ts +5 -10
- package/src/cli/mcp/setup.ts +220 -276
- package/src/cli/mcp/tool-capability-cache.ts +1 -1
- package/src/cli/mcp/toolset-names.ts +1 -1
- package/src/cli/mcp/toolset.ts +0 -1
- package/src/cli/mcp/transports/http.ts +51 -4
- package/src/cli/repositories/branch-name-policy.ts +0 -7
- package/src/cli/repositories/controller-home.ts +110 -3
- package/src/cli/repositories/safe-patch.ts +1 -1
- package/src/cli/repositories/selected-path-actions.ts +26 -24
- package/src/core/adoption/gitignore-plan.ts +2 -3
- package/src/core/adoption/plan.ts +4 -1
- package/src/runtime/control-plane/execution/edit-validation-coordinator.ts +556 -0
- package/src/runtime/control-plane/execution/work-handle-store.ts +128 -1
- package/src/runtime/control-plane/execution/work-validation-reconciler.ts +277 -0
- package/src/runtime/control-plane/execution/work-verification-snapshot.ts +169 -0
- package/src/runtime/control-plane/facade/capability-registry.ts +0 -10
- package/src/runtime/control-plane/facade/handoff-inbox-store.ts +44 -25
- package/src/runtime/control-plane/facade/suggested-actions.ts +7 -1
- package/src/runtime/control-plane/facade/types.ts +0 -1
- package/src/runtime/control-plane/global-scheduler/scheduler.ts +30 -8
- package/src/runtime/control-plane/launcher/chatgpt-work-binding-store.ts +114 -0
- package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +175 -0
- package/src/runtime/control-plane/launcher/launch-reservation-store.ts +161 -0
- package/src/runtime/control-plane/launcher/provider-mcp-bootstrap.ts +64 -0
- package/src/runtime/control-plane/launcher/thin-launcher.ts +117 -24
- package/src/runtime/control-plane/routing/route-policy.ts +14 -14
- package/src/runtime/control-plane/runtime-cleanup.ts +0 -1
- package/src/runtime/evidence/event-ledger.ts +1 -1
- package/src/runtime/{workflow/campaigns/workspace.ts → execution/managed-workspace.ts} +41 -43
- package/src/runtime/execution/process-runtime/check-facade.ts +6 -0
- package/src/runtime/execution/process-runtime/check-result.ts +45 -0
- package/src/runtime/execution/process-runtime/check-runner-sidecar.ts +42 -16
- package/src/runtime/execution/process-runtime/command-facade.ts +4 -2
- package/src/runtime/execution/process-runtime/gc.ts +1 -1
- package/src/runtime/execution/process-runtime/index.ts +3 -0
- package/src/runtime/execution/process-runtime/interactive-admission.ts +14 -5
- package/src/runtime/execution/process-runtime/persisted-check.ts +285 -0
- package/src/runtime/execution/process-runtime/resource-claims.ts +30 -0
- package/src/runtime/execution/process-runtime/runtime.ts +18 -1
- package/src/runtime/execution/process-runtime/store.ts +1 -19
- package/src/runtime/execution/process-runtime/types.ts +4 -0
- package/src/runtime/execution/thin-harness/execution-router.ts +0 -1
- package/src/runtime/execution/thin-harness/fast-executor.ts +1 -1
- package/src/runtime/execution/thin-harness/lightweight-lanes.ts +1 -2
- package/src/runtime/execution/thin-harness/types.ts +0 -1
- package/src/runtime/execution/workers/executor.ts +1 -1
- package/src/runtime/gateway/mcp/execution-tools.ts +1 -1
- package/src/runtime/gateway/mcp/persisted-check-process.ts +3 -255
- package/src/runtime/gateway/mcp/process-tools.ts +16 -3
- package/src/runtime/gateway/mcp/resource-policy.ts +0 -9
- package/src/runtime/gateway/mcp/router.ts +117 -182
- package/src/runtime/gateway/mcp/runtime-tools.ts +331 -409
- package/src/runtime/gateway/mcp/work-validation-reconciler.ts +1 -219
- package/src/runtime/plugins/browser-adapter.ts +5 -0
- package/src/runtime/plugins/desktop-operator-registration.ts +1 -1
- package/src/runtime/plugins/store.ts +14 -6
- package/src/runtime/plugins/types.ts +1 -1
- package/src/runtime/projections/materialized-view.ts +1 -23
- package/src/runtime/recovery/maintenance-executor.ts +9 -0
- package/src/runtime/resources/ownership.ts +0 -1
- package/src/runtime/root/gateway-adapter.ts +2 -0
- package/src/runtime/root/mcp-transport.ts +10 -2
- package/src/runtime/root/package-connector-service.ts +136 -0
- package/src/runtime/root/package-runtime-release.ts +161 -0
- package/src/runtime/root/package-runtime-service.ts +185 -0
- package/src/runtime/root/release-materialize.ts +19 -0
- package/src/runtime/root/runtime.ts +2 -1
- package/src/runtime/root/scheduler.ts +5 -0
- package/src/runtime/root/service.ts +18 -5
- package/src/runtime/standalone-recovery/core.ts +65 -16
- package/src/runtime/workflow/findings/store.ts +145 -106
- package/src/runtime/workflow/findings/types.ts +22 -0
- package/src/runtime/workflow/schedules/engine.ts +132 -2
- package/src/runtime/workflow/schedules/pending-activation.ts +139 -0
- package/src/runtime/workflow/schedules/work-continuation.ts +218 -0
- package/docs/CHANGELOG.md +0 -978
- package/docs/README.zh-CN.md +0 -58
- package/scripts/smoke-chatgpt-supervised-automation.ts +0 -208
- package/src/cli/commands/controller.ts +0 -680
- package/src/runtime/workflow/campaigns/cleanup.ts +0 -263
- package/src/runtime/workflow/campaigns/engine.ts +0 -112
- package/src/runtime/workflow/campaigns/normalize.ts +0 -100
- package/src/runtime/workflow/campaigns/review.ts +0 -315
- package/src/runtime/workflow/campaigns/store.ts +0 -526
- package/src/runtime/workflow/campaigns/supervisor.ts +0 -112
- package/src/runtime/workflow/campaigns/types.ts +0 -290
- /package/src/runtime/{workflow/campaigns → execution}/workspace-agent.ts +0 -0
|
@@ -42,8 +42,10 @@ export interface RepositoryCommandProcessInput {
|
|
|
42
42
|
timeoutMs?: number;
|
|
43
43
|
interactiveWaitMs?: number;
|
|
44
44
|
maxOutputBytes?: number;
|
|
45
|
-
/** Force durable workflow
|
|
45
|
+
/** Force an explicit external/durable workflow boundary. */
|
|
46
46
|
forceDurable?: boolean;
|
|
47
|
+
/** Return a Process handle immediately without changing execution architecture. */
|
|
48
|
+
returnHandleImmediately?: boolean;
|
|
47
49
|
requestId?: string;
|
|
48
50
|
workId?: string;
|
|
49
51
|
commandId?: string;
|
|
@@ -297,7 +299,7 @@ export async function executeRepositoryCommandViaProcessRuntime(
|
|
|
297
299
|
correlationId: input.workId,
|
|
298
300
|
},
|
|
299
301
|
signal: input.signal,
|
|
300
|
-
returnHandleImmediately: input.
|
|
302
|
+
returnHandleImmediately: input.returnHandleImmediately === true,
|
|
301
303
|
});
|
|
302
304
|
|
|
303
305
|
const route: RepositoryCommandRoute = handle.completed ? 'process_direct' : 'process_managed';
|
|
@@ -134,7 +134,7 @@ export function gcTerminalProcesses(options: ProcessGcOptions): ProcessGcResult
|
|
|
134
134
|
for (const victim of victims) {
|
|
135
135
|
if (safeUnlink(victim.path)) removedRecords += 1;
|
|
136
136
|
if (options.deleteLogs !== false) {
|
|
137
|
-
for (const suffix of ['.stdout.log', '.stderr.log', '.exit.json']) {
|
|
137
|
+
for (const suffix of ['.stdout.log', '.stderr.log', '.exit.json', '.exit.json.started.json']) {
|
|
138
138
|
if (safeUnlink(join(logs, `${victim.processId}${suffix}`))) removedLogs += 1;
|
|
139
139
|
}
|
|
140
140
|
}
|
|
@@ -4,11 +4,20 @@ const SHORT_COMMANDS = new Set([
|
|
|
4
4
|
'true', 'false', 'echo', 'printf', 'pwd', 'basename', 'dirname', 'test', '[', 'which',
|
|
5
5
|
]);
|
|
6
6
|
|
|
7
|
+
// ChatGPT reaches Process Runtime through a remote MCP hop. Returning a handle
|
|
8
|
+
// immediately for a process that finishes a few milliseconds later forces an
|
|
9
|
+
// additional caller round trip that is much more expensive than a small local
|
|
10
|
+
// completion grace. Keep this far below the retired 800ms-2s waits: genuinely
|
|
11
|
+
// long commands still become managed almost immediately.
|
|
12
|
+
const DEFAULT_COMPLETION_GRACE_MS = 100;
|
|
13
|
+
|
|
7
14
|
/**
|
|
8
15
|
* Admission is deliberately category-based rather than a second scheduler.
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
16
|
+
* Predictable primitives retain the larger short-command window. Other
|
|
17
|
+
* synchronous commands receive only a tiny completion grace so near-immediate
|
|
18
|
+
* processes can finish in the originating MCP call instead of forcing a second
|
|
19
|
+
* remote process_wait round trip. Explicit async/zero-wait callers still return
|
|
20
|
+
* handles immediately.
|
|
12
21
|
*/
|
|
13
22
|
export function durationAwareInteractiveWaitMs(
|
|
14
23
|
command: string | readonly string[],
|
|
@@ -17,7 +26,7 @@ export function durationAwareInteractiveWaitMs(
|
|
|
17
26
|
): number {
|
|
18
27
|
if (requestedWaitMs !== undefined) return Math.max(0, Math.trunc(requestedWaitMs));
|
|
19
28
|
const normalized = normalizeRepositoryCommand(command);
|
|
20
|
-
if (normalized.kind !== 'argv') return
|
|
29
|
+
if (normalized.kind !== 'argv') return DEFAULT_COMPLETION_GRACE_MS;
|
|
21
30
|
const executable = normalized.executable?.split(/[\\/]/).at(-1)?.toLowerCase();
|
|
22
|
-
return executable && SHORT_COMMANDS.has(executable) ? shortCommandWaitMs :
|
|
31
|
+
return executable && SHORT_COMMANDS.has(executable) ? shortCommandWaitMs : DEFAULT_COMPLETION_GRACE_MS;
|
|
23
32
|
}
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import { createHash } from 'crypto';
|
|
2
|
+
import { existsSync } from 'fs';
|
|
3
|
+
import { dirname, resolve } from 'path';
|
|
4
|
+
import {
|
|
5
|
+
controllerCheckExecutionIdentity,
|
|
6
|
+
listControllerChecks,
|
|
7
|
+
snapshotControllerCheck,
|
|
8
|
+
} from '../../../cli/controller/check-runner';
|
|
9
|
+
import {
|
|
10
|
+
currentCliRuntimeTarget,
|
|
11
|
+
resolveCliChildInvocation,
|
|
12
|
+
type CliChildInvocation,
|
|
13
|
+
type CliChildInvocationOptions,
|
|
14
|
+
type CliRuntimeTarget,
|
|
15
|
+
} from '../../../cli/runtime-invocation';
|
|
16
|
+
import { readRuntimeGeneration, resolveControllerRuntimeSourceRoot } from '../../control-plane/runtime-generation';
|
|
17
|
+
import { cleanupWorkVerificationSnapshot, materializeWorkVerificationSnapshot } from '../../control-plane/execution/work-verification-snapshot';
|
|
18
|
+
import {
|
|
19
|
+
checkRequiresDurableWorkflow,
|
|
20
|
+
processCheckSemanticScopeKey,
|
|
21
|
+
type CheckExecutionMode,
|
|
22
|
+
type RunCheckFacadeInput,
|
|
23
|
+
type RunCheckFacadeResult,
|
|
24
|
+
} from './check-facade';
|
|
25
|
+
import { claimsForCheck, toProcessClaims } from './resource-claims';
|
|
26
|
+
import { spawnManagedProcess } from './runtime';
|
|
27
|
+
import { allocatePersistedCheckResultReceiptPath } from './check-result';
|
|
28
|
+
import { durationAwareInteractiveWaitMs } from './interactive-admission';
|
|
29
|
+
const PERSISTED_CHECK_SOURCE_ENTRY = 'src/runtime/execution/process-runtime/check-runner-sidecar.ts';
|
|
30
|
+
|
|
31
|
+
export function resolvePersistedCheckCliInvocation(
|
|
32
|
+
cliEntry: string,
|
|
33
|
+
args: string[],
|
|
34
|
+
options: CliChildInvocationOptions = {},
|
|
35
|
+
): CliChildInvocation {
|
|
36
|
+
return resolveCliChildInvocation(cliEntry, args, options);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function resolveRuntimeCliTarget(controllerHome?: string): CliRuntimeTarget {
|
|
40
|
+
const moduleSourceRoot = resolve(import.meta.dir, '..', '..', '..', '..');
|
|
41
|
+
const sourceEntry = resolve(moduleSourceRoot, 'src', 'cli', 'index.ts');
|
|
42
|
+
const source = resolveControllerRuntimeSourceRoot({
|
|
43
|
+
explicitRoot: existsSync(sourceEntry) ? moduleSourceRoot : undefined,
|
|
44
|
+
});
|
|
45
|
+
const sourceMode = Boolean(source.root && existsSync(resolve(source.root, 'src', 'cli', 'index.ts')));
|
|
46
|
+
const runtimeEnv = { ...process.env };
|
|
47
|
+
if (sourceMode) {
|
|
48
|
+
delete runtimeEnv.FORGE_RUNTIME_EXECUTION;
|
|
49
|
+
delete runtimeEnv.FORGE_RUNTIME_CLI_ENTRY;
|
|
50
|
+
}
|
|
51
|
+
const generation = controllerHome ? readRuntimeGeneration(controllerHome) : undefined;
|
|
52
|
+
return currentCliRuntimeTarget({
|
|
53
|
+
env: runtimeEnv,
|
|
54
|
+
argv: sourceMode ? [] : process.argv,
|
|
55
|
+
moduleUrl: sourceMode ? undefined : import.meta.url,
|
|
56
|
+
sourceRoot: source.root,
|
|
57
|
+
cwd: source.root ?? moduleSourceRoot,
|
|
58
|
+
sourceRevision: generation?.source.releaseRevision
|
|
59
|
+
?? generation?.source.commit
|
|
60
|
+
?? process.env.FORGE_ACTIVE_RUNTIME_REVISION,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function resolveRuntimeCliEntry(controllerHome?: string): string {
|
|
65
|
+
return resolveRuntimeCliTarget(controllerHome).entry;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function persistedCheckSemanticScopeKey(
|
|
69
|
+
input: Pick<RunCheckFacadeInput, 'workId' | 'verificationBinding' | 'checkoutId'>,
|
|
70
|
+
reuseScope: 'repository' | 'checkout',
|
|
71
|
+
): string {
|
|
72
|
+
return processCheckSemanticScopeKey(input, reuseScope);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function resolvePersistedCheckRuntimeExecutable(
|
|
76
|
+
cliTarget: CliRuntimeTarget,
|
|
77
|
+
runtimeExecutable = process.execPath,
|
|
78
|
+
entryExists: (path: string) => boolean = existsSync,
|
|
79
|
+
): string {
|
|
80
|
+
if (cliTarget.runtimeKind !== 'compiled_bun_release') return runtimeExecutable;
|
|
81
|
+
const checkRunner = resolve(dirname(runtimeExecutable), 'forge-check-runner');
|
|
82
|
+
if (!entryExists(checkRunner)) {
|
|
83
|
+
throw new Error(`PERSISTED_CHECK_RUNNER_MISSING: ${checkRunner}`);
|
|
84
|
+
}
|
|
85
|
+
return checkRunner;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function resolvePersistedCheckProcessInvocation(
|
|
89
|
+
cliTarget: CliRuntimeTarget,
|
|
90
|
+
args: string[],
|
|
91
|
+
options: { runtimeExecutable?: string; entryExists?: (path: string) => boolean } = {},
|
|
92
|
+
): CliChildInvocation {
|
|
93
|
+
const runtimeExecutable = options.runtimeExecutable ?? process.execPath;
|
|
94
|
+
const executable = resolvePersistedCheckRuntimeExecutable(cliTarget, runtimeExecutable, options.entryExists ?? existsSync);
|
|
95
|
+
if (cliTarget.runtimeKind === 'compiled_bun_release') {
|
|
96
|
+
return { executable, args };
|
|
97
|
+
}
|
|
98
|
+
const sourceEntry = resolve(cliTarget.cwd, PERSISTED_CHECK_SOURCE_ENTRY);
|
|
99
|
+
if (!(options.entryExists ?? existsSync)(sourceEntry)) {
|
|
100
|
+
throw new Error(`PERSISTED_CHECK_SOURCE_RUNNER_MISSING: ${sourceEntry}`);
|
|
101
|
+
}
|
|
102
|
+
return resolvePersistedCheckCliInvocation(sourceEntry, args, {
|
|
103
|
+
runtimeExecutable: executable,
|
|
104
|
+
runtimeKind: cliTarget.runtimeKind,
|
|
105
|
+
sourceRevision: cliTarget.sourceRevision,
|
|
106
|
+
immutable: false,
|
|
107
|
+
...(cliTarget.runtimeKind === 'package_launcher' ? { launcherEntry: cliTarget.entry } : {}),
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Run a registered check through Process Runtime while keeping check-runner
|
|
113
|
+
* evidence authoritative. The managed OS process invokes the same immutable
|
|
114
|
+
* forge CLI bundle with a hidden internal subcommand; that subcommand
|
|
115
|
+
* executes runControllerCheck, writes the Artifact atomically, mirrors bounded
|
|
116
|
+
* stdout/stderr, and exits with the exact check status.
|
|
117
|
+
*/
|
|
118
|
+
export async function runPersistedCheckViaProcessRuntime(
|
|
119
|
+
input: RunCheckFacadeInput,
|
|
120
|
+
): Promise<RunCheckFacadeResult> {
|
|
121
|
+
const emptyEffects = {
|
|
122
|
+
executionJobCount: 0,
|
|
123
|
+
localJobCount: 0,
|
|
124
|
+
workerSpawnCount: 0,
|
|
125
|
+
projectionUpdateCount: 0,
|
|
126
|
+
};
|
|
127
|
+
const verificationSnapshot = input.verificationSnapshot
|
|
128
|
+
? materializeWorkVerificationSnapshot({
|
|
129
|
+
controllerHome: input.controllerHome,
|
|
130
|
+
repoId: input.repoId,
|
|
131
|
+
sourceRoot: input.repoRoot,
|
|
132
|
+
scope: input.verificationSnapshot,
|
|
133
|
+
})
|
|
134
|
+
: undefined;
|
|
135
|
+
const executionRoot = verificationSnapshot?.root ?? input.repoRoot;
|
|
136
|
+
const cleanupVerificationSnapshot = () => {
|
|
137
|
+
if (verificationSnapshot) cleanupWorkVerificationSnapshot(verificationSnapshot.root);
|
|
138
|
+
};
|
|
139
|
+
const check = listControllerChecks(executionRoot).find((entry) => entry.id === input.checkId);
|
|
140
|
+
if (!check) {
|
|
141
|
+
cleanupVerificationSnapshot();
|
|
142
|
+
return {
|
|
143
|
+
mode: 'durable',
|
|
144
|
+
checkId: input.checkId,
|
|
145
|
+
durable: {
|
|
146
|
+
reason: 'check_not_found_or_requires_registry_lookup',
|
|
147
|
+
suggestedOperation: 'list_checks then run_check with a known check_id',
|
|
148
|
+
},
|
|
149
|
+
durableSideEffects: emptyEffects,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
if (input.forceDurable || checkRequiresDurableWorkflow(input.checkId, check)) {
|
|
153
|
+
cleanupVerificationSnapshot();
|
|
154
|
+
return {
|
|
155
|
+
mode: 'durable',
|
|
156
|
+
checkId: input.checkId,
|
|
157
|
+
check,
|
|
158
|
+
durable: {
|
|
159
|
+
reason: 'multi_phase_or_release_check_requires_durable_workflow',
|
|
160
|
+
suggestedOperation: 'Claim the related WorkContract and run this check through an external Controller.',
|
|
161
|
+
},
|
|
162
|
+
durableSideEffects: emptyEffects,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const interactiveWaitMs = durationAwareInteractiveWaitMs(check.command, input.interactiveWaitMs);
|
|
167
|
+
const leaseWaitMs = input.leaseWaitMs;
|
|
168
|
+
const timeoutMs = Math.min(
|
|
169
|
+
check.timeoutMs,
|
|
170
|
+
typeof input.timeoutMs === 'number' && Number.isFinite(input.timeoutMs)
|
|
171
|
+
? Math.max(1_000, Math.trunc(input.timeoutMs))
|
|
172
|
+
: check.timeoutMs,
|
|
173
|
+
);
|
|
174
|
+
if (!input.executionIdentity) {
|
|
175
|
+
throw new Error('EXECUTION_IDENTITY_REQUIRED: persisted run_check requires an immutable executionIdentity');
|
|
176
|
+
}
|
|
177
|
+
const executionIdentity = input.executionIdentity;
|
|
178
|
+
if (executionIdentity.repositoryId !== input.repoId) {
|
|
179
|
+
throw new Error(
|
|
180
|
+
`EXECUTION_IDENTITY_MISMATCH: check repo ${input.repoId} differs from identity ${executionIdentity.repositoryId}`,
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
if (input.checkoutId?.trim() && executionIdentity.checkoutId !== input.checkoutId.trim()) {
|
|
184
|
+
throw new Error(
|
|
185
|
+
`CHECKOUT_ROUTE_MISMATCH: check checkout ${input.checkoutId} differs from identity ${executionIdentity.checkoutId}`,
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
const claims = claimsForCheck(
|
|
189
|
+
input.checkId,
|
|
190
|
+
check.command,
|
|
191
|
+
executionIdentity.repositoryId,
|
|
192
|
+
executionIdentity.checkoutId,
|
|
193
|
+
check.effects,
|
|
194
|
+
);
|
|
195
|
+
const checkSnapshot = snapshotControllerCheck(executionRoot, input.checkId);
|
|
196
|
+
const checkFingerprint = createHash('sha256')
|
|
197
|
+
.update(JSON.stringify(checkSnapshot))
|
|
198
|
+
.digest('hex');
|
|
199
|
+
const semanticCheck = controllerCheckExecutionIdentity(
|
|
200
|
+
executionRoot,
|
|
201
|
+
input.checkId,
|
|
202
|
+
timeoutMs,
|
|
203
|
+
checkSnapshot,
|
|
204
|
+
);
|
|
205
|
+
const processCheckExecution = {
|
|
206
|
+
schemaVersion: 1 as const,
|
|
207
|
+
checkId: semanticCheck.checkId,
|
|
208
|
+
cacheKey: semanticCheck.cacheKey,
|
|
209
|
+
revision: semanticCheck.revision,
|
|
210
|
+
definitionDigest: semanticCheck.definitionDigest,
|
|
211
|
+
environmentFingerprint: semanticCheck.environmentFingerprint,
|
|
212
|
+
timeoutMs: semanticCheck.timeoutMs,
|
|
213
|
+
reuseScope: semanticCheck.reuseScope,
|
|
214
|
+
scopeKey: persistedCheckSemanticScopeKey(input, semanticCheck.reuseScope),
|
|
215
|
+
};
|
|
216
|
+
const cliTarget = resolveRuntimeCliTarget(input.controllerHome);
|
|
217
|
+
const checkResultReceiptPath = allocatePersistedCheckResultReceiptPath(input.controllerHome, input.repoId);
|
|
218
|
+
const checkArgs = [
|
|
219
|
+
'--repo',
|
|
220
|
+
executionRoot,
|
|
221
|
+
'--check-id',
|
|
222
|
+
input.checkId,
|
|
223
|
+
'--timeout-ms',
|
|
224
|
+
String(timeoutMs),
|
|
225
|
+
'--expected-check-fingerprint',
|
|
226
|
+
checkFingerprint,
|
|
227
|
+
'--result-receipt',
|
|
228
|
+
checkResultReceiptPath,
|
|
229
|
+
...(verificationSnapshot ? ['--cleanup-root', verificationSnapshot.root] : []),
|
|
230
|
+
];
|
|
231
|
+
const invocation = resolvePersistedCheckProcessInvocation(cliTarget, checkArgs);
|
|
232
|
+
let handle;
|
|
233
|
+
try {
|
|
234
|
+
handle = await spawnManagedProcess({
|
|
235
|
+
controllerHome: input.controllerHome,
|
|
236
|
+
repoId: executionIdentity.repositoryId,
|
|
237
|
+
checkoutId: executionIdentity.checkoutId,
|
|
238
|
+
executionIdentity,
|
|
239
|
+
workId: input.workId,
|
|
240
|
+
commandId: input.commandId,
|
|
241
|
+
command: {
|
|
242
|
+
kind: 'argv',
|
|
243
|
+
executable: invocation.executable,
|
|
244
|
+
args: invocation.args,
|
|
245
|
+
cwd: executionIdentity.canonicalRoot,
|
|
246
|
+
},
|
|
247
|
+
interactiveWaitMs,
|
|
248
|
+
leaseWaitMs,
|
|
249
|
+
timeoutMs: timeoutMs + 5_000,
|
|
250
|
+
resourceClaims: toProcessClaims(claims),
|
|
251
|
+
checkExecution: processCheckExecution,
|
|
252
|
+
origin: {
|
|
253
|
+
surface: 'check',
|
|
254
|
+
toolName: 'run_check',
|
|
255
|
+
checkId: input.checkId,
|
|
256
|
+
requestId: input.requestId,
|
|
257
|
+
correlationId: input.workId,
|
|
258
|
+
executionSessionId: input.verificationBinding?.executionSessionId,
|
|
259
|
+
editSessionId: input.verificationBinding?.editSessionId,
|
|
260
|
+
editRevision: input.verificationBinding?.editRevision,
|
|
261
|
+
issueId: input.verificationBinding?.issueId,
|
|
262
|
+
taskId: input.verificationBinding?.taskId,
|
|
263
|
+
checkResultReceiptPath,
|
|
264
|
+
workVerificationSnapshot: Boolean(verificationSnapshot),
|
|
265
|
+
},
|
|
266
|
+
signal: input.signal,
|
|
267
|
+
});
|
|
268
|
+
} catch (error) {
|
|
269
|
+
cleanupVerificationSnapshot();
|
|
270
|
+
throw error;
|
|
271
|
+
}
|
|
272
|
+
if (verificationSnapshot && (handle.deduplicated === true || handle.semanticDeduplicated === true)) {
|
|
273
|
+
cleanupVerificationSnapshot();
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
const mode: CheckExecutionMode = handle.completed ? 'direct' : 'managed';
|
|
277
|
+
return {
|
|
278
|
+
mode,
|
|
279
|
+
checkId: input.checkId,
|
|
280
|
+
check,
|
|
281
|
+
process: handle,
|
|
282
|
+
ok: handle.completed ? handle.ok : undefined,
|
|
283
|
+
durableSideEffects: handle.durableSideEffects,
|
|
284
|
+
};
|
|
285
|
+
}
|
|
@@ -130,6 +130,33 @@ function browserAppleScriptHeredocClaims(script: string): ResourceClaimSpec[] |
|
|
|
130
130
|
return [claimHostService(`osascript:${uniqueTargets[0]}`, 'write')];
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
+
function iosSimulatorTestCommandClaims(
|
|
134
|
+
command: string | readonly string[],
|
|
135
|
+
repoId: string,
|
|
136
|
+
checkoutId?: string,
|
|
137
|
+
): ResourceClaimSpec[] | undefined {
|
|
138
|
+
const canonical = normalizeRepositoryCommand(command);
|
|
139
|
+
const isTestAction = (text: string): boolean => /(?:^|\s)(?:test|test-without-building)(?:\s|$)/i.test(text);
|
|
140
|
+
let matches = false;
|
|
141
|
+
if (canonical.kind === 'argv') {
|
|
142
|
+
const program = (canonical.executable ?? '').split(/[\\/]/).at(-1)?.toLowerCase();
|
|
143
|
+
if (program === 'xcodebuild') matches = (canonical.args ?? []).some((arg) => /^(?:test|test-without-building)$/i.test(arg));
|
|
144
|
+
if (!matches) {
|
|
145
|
+
const wrapped = fixedShellWrapperCommand([canonical.executable ?? '', ...(canonical.args ?? [])]);
|
|
146
|
+
matches = Boolean(wrapped && /\bxcodebuild\b/i.test(wrapped) && isTestAction(wrapped));
|
|
147
|
+
}
|
|
148
|
+
} else {
|
|
149
|
+
const shell = canonical.shellCommand ?? '';
|
|
150
|
+
matches = /\bxcodebuild\b/i.test(shell) && isTestAction(shell);
|
|
151
|
+
}
|
|
152
|
+
if (!matches) return undefined;
|
|
153
|
+
return normalizeClaims([
|
|
154
|
+
claimWorkspaceRead(checkoutId),
|
|
155
|
+
claimBuildCacheWrite(repoId),
|
|
156
|
+
claimHostService('ios-simulator-test', 'write'),
|
|
157
|
+
]);
|
|
158
|
+
}
|
|
159
|
+
|
|
133
160
|
function hostOnlyCommandClaims(command: string | readonly string[]): ResourceClaimSpec[] | undefined {
|
|
134
161
|
const canonical = normalizeRepositoryCommand(command);
|
|
135
162
|
if (canonical.kind === 'shell') {
|
|
@@ -208,6 +235,7 @@ function claimsForDeclaredCheckEffects(
|
|
|
208
235
|
if (effects.git === 'refs') claims.push(claimGitRefs(repoId));
|
|
209
236
|
if (effects.git === 'write') claims.push(claimWorkspaceWrite(checkoutId), claimGitIndex(checkoutId), claimGitRefs(repoId));
|
|
210
237
|
if (effects.network) claims.push(claimNetwork(repoId, effects.network));
|
|
238
|
+
for (const service of effects.hostServices ?? []) claims.push(claimHostService(service, 'write'));
|
|
211
239
|
|
|
212
240
|
return normalizeClaims(claims, { readOnly: claims.every((claim) => claim.mode === 'read') });
|
|
213
241
|
}
|
|
@@ -323,6 +351,8 @@ export function claimsForRepositoryCommand(
|
|
|
323
351
|
const classification = classifyRepositoryCommand(command, defaultBranch);
|
|
324
352
|
const canonical = normalizeRepositoryCommand(command);
|
|
325
353
|
const focused = isFocusedCheckCommand(command);
|
|
354
|
+
const iosSimulatorClaims = iosSimulatorTestCommandClaims(command, repoId, checkoutId);
|
|
355
|
+
if (iosSimulatorClaims) return iosSimulatorClaims;
|
|
326
356
|
const hostClaims = hostOnlyCommandClaims(command);
|
|
327
357
|
if (hostClaims) return hostClaims;
|
|
328
358
|
|
|
@@ -121,6 +121,21 @@ function safeProcessText(value: string): string {
|
|
|
121
121
|
return redactSensitiveText(value).text;
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
+
function cleanupTerminalRunnerReceipts(record: ManagedProcessRecord): void {
|
|
125
|
+
if (!isManagedProcessTerminal(record) || record.terminalWritten !== true || record.leasesReleased !== true) return;
|
|
126
|
+
const exitReceiptPath = record.exitReceiptPath
|
|
127
|
+
?? receiptPathFor(record.controllerHome, record.repoId, record.processId);
|
|
128
|
+
for (const path of [exitReceiptPath, `${exitReceiptPath}.started.json`]) {
|
|
129
|
+
if (!path || !existsSync(path)) continue;
|
|
130
|
+
try {
|
|
131
|
+
rmSync(path, { force: true });
|
|
132
|
+
} catch {
|
|
133
|
+
// Best-effort only. The durable terminal record is authoritative and
|
|
134
|
+
// fallback Process GC reconciles stale runner artifacts later.
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
124
139
|
function sanitizeTerminalProcessArtifacts(record: ManagedProcessRecord): ManagedProcessRecord {
|
|
125
140
|
if (!isManagedProcessTerminal(record)) return record;
|
|
126
141
|
let filesExamined = 0;
|
|
@@ -555,7 +570,9 @@ export function completeProcessFromEvidence(
|
|
|
555
570
|
// already-terminal races (second caller still needs to clear leases once).
|
|
556
571
|
const afterTerminal = completion.record ?? getProcessRecord(controllerHome, repoId, processId);
|
|
557
572
|
if (afterTerminal && (completion.ok || completion.reason === 'already_terminal' || afterTerminal.terminalWritten === true)) {
|
|
558
|
-
|
|
573
|
+
const released = releaseProcessLeasesOnce(controllerHome, repoId, processId) ?? afterTerminal;
|
|
574
|
+
cleanupTerminalRunnerReceipts(released);
|
|
575
|
+
return released;
|
|
559
576
|
}
|
|
560
577
|
return afterTerminal;
|
|
561
578
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Durable Managed Process records under controller-home repositories.
|
|
3
3
|
* Layout: repositories/<repoId>/processes/<processId>.json
|
|
4
|
-
*
|
|
4
|
+
* Recovery membership authority: SQLite process_recovery_index/v2.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { createHash } from 'crypto';
|
|
@@ -87,10 +87,6 @@ function checkExecutionBindingPath(controllerHome: string, repoId: string, scope
|
|
|
87
87
|
return join(checkExecutionBindingsRoot(controllerHome, repoId), `${checkExecutionBindingKey(repoId, scopeKey, cacheKey)}.json`);
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
function indexPath(controllerHome: string, repoId: string): string {
|
|
91
|
-
return join(processesRoot(controllerHome, repoId), 'active-index.json');
|
|
92
|
-
}
|
|
93
|
-
|
|
94
90
|
interface ProcessRecoveryIndex {
|
|
95
91
|
schemaVersion: 2;
|
|
96
92
|
updatedAt: string;
|
|
@@ -118,18 +114,6 @@ function processRecoveryMembership(record: ManagedProcessRecord): { active: bool
|
|
|
118
114
|
};
|
|
119
115
|
}
|
|
120
116
|
|
|
121
|
-
function projectRecoveryIndex(controllerHome: string, repoId: string, index: ProcessRecoveryIndex): void {
|
|
122
|
-
// Compatibility/readability projection only. SQLite is authoritative; the
|
|
123
|
-
// projection is never read by Process Runtime after v2 migration.
|
|
124
|
-
atomicWrite(indexPath(controllerHome, repoId), {
|
|
125
|
-
schemaVersion: 2,
|
|
126
|
-
source: 'sqlite_projection',
|
|
127
|
-
updatedAt: index.updatedAt,
|
|
128
|
-
processIds: index.activeProcessIds,
|
|
129
|
-
pendingLeaseReleaseIds: index.pendingLeaseReleaseIds,
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
|
|
133
117
|
function readRecoveryIndex(controllerHome: string, repoId: string): ProcessRecoveryIndex | undefined {
|
|
134
118
|
return readOrImportControlPlaneRecord<ProcessRecoveryIndex>(controllerHome, {
|
|
135
119
|
namespace: PROCESS_RECOVERY_INDEX_NAMESPACE,
|
|
@@ -163,7 +147,6 @@ function replaceRecoveryIndex(
|
|
|
163
147
|
pendingLeaseReleaseIds: normalizedProcessIds(pendingLeaseReleaseIds),
|
|
164
148
|
}),
|
|
165
149
|
}).value;
|
|
166
|
-
projectRecoveryIndex(controllerHome, repoId, value);
|
|
167
150
|
return value;
|
|
168
151
|
}
|
|
169
152
|
|
|
@@ -224,7 +207,6 @@ function updateRecoveryIndexMembership(
|
|
|
224
207
|
};
|
|
225
208
|
},
|
|
226
209
|
}).value;
|
|
227
|
-
projectRecoveryIndex(controllerHome, repoId, value);
|
|
228
210
|
return value;
|
|
229
211
|
}
|
|
230
212
|
|
|
@@ -248,6 +248,10 @@ export interface ManagedProcessRecord {
|
|
|
248
248
|
/** Optional durable task identity consuming the same receipt. */
|
|
249
249
|
issueId?: string;
|
|
250
250
|
taskId?: string;
|
|
251
|
+
/** Internal structured result written by the persisted Check sidecar. */
|
|
252
|
+
checkResultReceiptPath?: string;
|
|
253
|
+
/** True when this Check executed in a Work-owned verification snapshot. */
|
|
254
|
+
workVerificationSnapshot?: boolean;
|
|
251
255
|
};
|
|
252
256
|
error?: { code: string; message: string };
|
|
253
257
|
/** Sidecar exit receipt path written by wrapper (survives controller restart). */
|
|
@@ -675,7 +675,6 @@ function durableSuggestion(operation: string): string {
|
|
|
675
675
|
if (operation.includes('patch')) return 'repository_safe_patch_apply with apply_mode=async or Durable Work';
|
|
676
676
|
if (operation.includes('command')) return 'repository_command_execute through Durable Work / Local Job';
|
|
677
677
|
if (operation.includes('agent') || operation === 'quick_agent_session') return 'quick_agent_session / dispatch_task';
|
|
678
|
-
if (operation.includes('campaign')) return 'Campaign (opt-in long orchestration only)';
|
|
679
678
|
return 'Durable Work (ExecutionJob path)';
|
|
680
679
|
}
|
|
681
680
|
|
|
@@ -419,7 +419,7 @@ function ownershipOptionsFor(
|
|
|
419
419
|
}
|
|
420
420
|
|
|
421
421
|
/**
|
|
422
|
-
* Execute one Fast Path operation without ExecutionJob / Local Job / Worker
|
|
422
|
+
* Execute one Fast Path operation without ExecutionJob / Local Job / Worker.
|
|
423
423
|
*/
|
|
424
424
|
export async function executeFast(
|
|
425
425
|
ctx: FastExecutorContext,
|
|
@@ -157,7 +157,7 @@ function digest(value: unknown): string {
|
|
|
157
157
|
}
|
|
158
158
|
|
|
159
159
|
/**
|
|
160
|
-
* Lightweight concurrent lanes without
|
|
160
|
+
* Lightweight concurrent lanes without Issue/worktree.
|
|
161
161
|
* Read lanes use async Fast primitives. Proposal lanes only validate conflicts (no Agent analysis).
|
|
162
162
|
*/
|
|
163
163
|
export async function executeLightweightLanes(
|
|
@@ -429,7 +429,6 @@ export async function executeLightweightLanes(
|
|
|
429
429
|
latency,
|
|
430
430
|
appliedByIntegrator: false,
|
|
431
431
|
createdIssue: false,
|
|
432
|
-
createdCampaign: false,
|
|
433
432
|
createdWorktree: false,
|
|
434
433
|
concurrent,
|
|
435
434
|
};
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
import { markOperationDelegated } from '../jobs/receipt-store';
|
|
23
23
|
import { assertAutomatedOperationAllowed } from '../../control-plane/governance/external-effects';
|
|
24
24
|
import { recordCandidateFinding, updateCandidateFinding } from '../../workflow/findings/store';
|
|
25
|
-
import { triggerWorkspaceAgent } from '
|
|
25
|
+
import { triggerWorkspaceAgent } from '../workspace-agent';
|
|
26
26
|
import { executeAssistantPluginAction } from '../../plugins/store';
|
|
27
27
|
import { CONTROLLER_SCOPE_REPO_ID, controllerSystemRoot, repositoryControllerRoot } from '../../../cli/repositories/controller-home';
|
|
28
28
|
import { writeExecutionArtifact } from '../../evidence/artifact-store';
|
|
@@ -18,7 +18,7 @@ import { repositoryGitCommit, repositoryGitDeleteBranch, repositoryGitFinishWork
|
|
|
18
18
|
import { previewRepositoryCommandExecution } from '../../../cli/repositories/command-executor';
|
|
19
19
|
import { classifyRepositoryCommand } from '../../../cli/repositories/command-classifier';
|
|
20
20
|
import { globMatches } from '../../../cli/mcp/paths';
|
|
21
|
-
import { ensureManagedWorkspace } from '../../
|
|
21
|
+
import { ensureManagedWorkspace } from '../../execution/managed-workspace';
|
|
22
22
|
import { listControllerChecks } from '../../../cli/controller/check-runner';
|
|
23
23
|
import { readRepositoryAccessPolicy } from '../../control-plane/governance/access-policy';
|
|
24
24
|
import { appendWorkEvidence, createWorkContract, getWorkContract, recordWorkCompletionReceipt, updateWorkContract, appendVerificationRecord } from '../../control-plane/facade/work-contract-store';
|