@moretea-labs/forge 1.5.0-rc.1 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +9 -11
- package/CHANGELOG.md +19 -0
- package/CLAUDE.md +8 -10
- package/DESIGN.md +278 -0
- package/README.md +70 -90
- package/README.zh-CN.md +50 -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/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 +51 -184
- 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 +56 -35
- package/docs/tutorials/01-install-and-start.zh-CN.md +56 -35
- package/docs/tutorials/02-connect-chatgpt.md +112 -46
- package/docs/tutorials/02-connect-chatgpt.zh-CN.md +113 -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 +211 -70
- package/src/cli/commands/init.ts +5 -6
- package/src/cli/commands/mcp.ts +29 -5
- package/src/cli/commands/runtime.ts +60 -8
- package/src/cli/commands/setup-profile.ts +441 -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-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 +44 -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/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 +211 -275
- 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 +24 -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-runtime-release.ts +161 -0
- package/src/runtime/root/package-runtime-service.ts +172 -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
|
@@ -4,14 +4,13 @@ import {
|
|
|
4
4
|
buildMultiRepositoryToolDefinitions,
|
|
5
5
|
type MultiRepositoryMcpToolContext,
|
|
6
6
|
} from '../../../cli/mcp/multi-repository';
|
|
7
|
-
import { repositoryToolDefinitions } from '../../../cli/mcp/repository-tools';
|
|
7
|
+
import { callRepositoryTool, repositoryToolDefinitions } from '../../../cli/mcp/repository-tools';
|
|
8
8
|
import { runtimeToolDefinitions } from './runtime-tools';
|
|
9
9
|
import { executionToolDefinitions } from './execution-tools';
|
|
10
10
|
import { processToolDefinitions } from './process-tools';
|
|
11
11
|
import { resolveRepositorySelection } from '../../../cli/repositories/registry';
|
|
12
12
|
import { executionIdentityForRepository } from '../../control-plane/execution/execution-identity';
|
|
13
|
-
import {
|
|
14
|
-
import { controllerCheckExecutionIdentity, listControllerChecks } from '../../../cli/controller/check-runner';
|
|
13
|
+
import { startOrJoinEditValidation } from '../../control-plane/execution/edit-validation-coordinator';
|
|
15
14
|
import type {
|
|
16
15
|
ExecutionOperationMetadata,
|
|
17
16
|
ExecutionTimeoutPolicy,
|
|
@@ -25,18 +24,13 @@ import {
|
|
|
25
24
|
} from '../../execution/thin-harness';
|
|
26
25
|
import {
|
|
27
26
|
checkRequiresDurableWorkflow,
|
|
28
|
-
claimsForCheck,
|
|
29
27
|
classifyRepositoryCommandRoute,
|
|
30
|
-
getProcessRecord,
|
|
31
|
-
processCheckCompletionReceipt,
|
|
32
|
-
processCheckSemanticScopeKey,
|
|
33
28
|
} from '../../execution/process-runtime';
|
|
34
29
|
import { runPersistedCheckViaProcessRuntime } from './persisted-check-process';
|
|
35
30
|
import {
|
|
36
31
|
isProcessIsolatedReadDiagnostic,
|
|
37
32
|
runReadOnlyDiagnosticViaProcessRuntime,
|
|
38
33
|
} from '../../diagnostics/process-facade';
|
|
39
|
-
import { resourceClaimsConflict } from '../../resources/claims/conflicts';
|
|
40
34
|
|
|
41
35
|
const DIRECT_REPOSITORY_TOOLS = new Set(['repository_list', 'repository_get', 'repository_workbench', 'repository_command_preview']);
|
|
42
36
|
export const RETIRED_AGENT_OPERATIONS = new Set([
|
|
@@ -353,7 +347,21 @@ export function classifyGatewayExecutionPath(
|
|
|
353
347
|
reasons: opts.forceDurable ? ['force_durable'] : ['gateway_isolated_tool'],
|
|
354
348
|
};
|
|
355
349
|
}
|
|
356
|
-
|
|
350
|
+
const selfManagedProcessAsync = (
|
|
351
|
+
name === 'repository_command_execute'
|
|
352
|
+
|| name === 'run_check'
|
|
353
|
+
|| name === 'verify_edit_session'
|
|
354
|
+
) && (
|
|
355
|
+
args.apply_mode === 'async'
|
|
356
|
+
|| args.mode === 'async'
|
|
357
|
+
|| args.async === true
|
|
358
|
+
|| args.background === true
|
|
359
|
+
);
|
|
360
|
+
// Async on Process-Runtime-owned tools means return the managed Process
|
|
361
|
+
// handle immediately. It must not promote local work into the retired
|
|
362
|
+
// ExecutionJob path. Explicit durable mode still crosses the external
|
|
363
|
+
// Controller boundary.
|
|
364
|
+
if (wantsAsyncExecution(args) && !selfManagedProcessAsync) {
|
|
357
365
|
return {
|
|
358
366
|
path: 'durable',
|
|
359
367
|
reasons: ['caller_requested_async_or_durable'],
|
|
@@ -362,7 +370,7 @@ export function classifyGatewayExecutionPath(
|
|
|
362
370
|
// run_check: Process Runtime for ordinary checks; Durable only for release/multi-phase.
|
|
363
371
|
if (name === 'run_check') {
|
|
364
372
|
const checkId = String(args.check_id ?? args.checkId ?? '').trim();
|
|
365
|
-
if (args.
|
|
373
|
+
if (args.mode === 'durable' || args.force_durable === true) {
|
|
366
374
|
return { path: 'durable', reasons: ['caller_requested_durable_check'] };
|
|
367
375
|
}
|
|
368
376
|
if (checkId && checkRequiresDurableWorkflow(checkId)) {
|
|
@@ -394,7 +402,7 @@ export function classifyGatewayExecutionPath(
|
|
|
394
402
|
// return a managed handle, but it must never be promoted to a retired
|
|
395
403
|
// ExecutionJob/LocalJob merely because the edit session has checks.
|
|
396
404
|
if (name === 'verify_edit_session') {
|
|
397
|
-
if (args.
|
|
405
|
+
if (args.mode === 'durable' || args.force_durable === true) {
|
|
398
406
|
return { path: 'durable', reasons: ['caller_requested_durable_edit_verification'] };
|
|
399
407
|
}
|
|
400
408
|
const checkIds = Array.isArray(args.check_ids)
|
|
@@ -424,8 +432,9 @@ export function classifyGatewayExecutionPath(
|
|
|
424
432
|
}
|
|
425
433
|
|
|
426
434
|
// repository_command_execute has one authoritative classifier. Process Runtime
|
|
427
|
-
// owns every local single-process command regardless of timeout
|
|
428
|
-
//
|
|
435
|
+
// owns every local single-process command regardless of timeout. Async requests
|
|
436
|
+
// stay here and return a handle; explicit durable mode remains an external-
|
|
437
|
+
// Controller boundary.
|
|
429
438
|
if (name === 'repository_command_execute') {
|
|
430
439
|
const command = args.command;
|
|
431
440
|
if (!(typeof command === 'string' || Array.isArray(command))) {
|
|
@@ -678,6 +687,29 @@ export function injectDurableCommandFields(tool: McpToolDefinition): McpToolDefi
|
|
|
678
687
|
};
|
|
679
688
|
}
|
|
680
689
|
|
|
690
|
+
async function runEditSessionValidationViaProcessRuntime(
|
|
691
|
+
ctx: MultiRepositoryMcpToolContext,
|
|
692
|
+
repository: NonNullable<ReturnType<typeof resolveRepositorySelection>>,
|
|
693
|
+
editSessionId: string,
|
|
694
|
+
args: Record<string, unknown>,
|
|
695
|
+
): Promise<CallToolResult> {
|
|
696
|
+
const validation = await startOrJoinEditValidation(ctx.controllerHome, repository, {
|
|
697
|
+
editSessionId,
|
|
698
|
+
checkIds: Array.isArray(args.check_ids) ? args.check_ids.map(String) : undefined,
|
|
699
|
+
requestId: typeof args.request_id === 'string' ? args.request_id : undefined,
|
|
700
|
+
validationRequestId: typeof args.validation_request_id === 'string' ? args.validation_request_id : undefined,
|
|
701
|
+
reviewer: typeof args.reviewer === 'string' ? args.reviewer : undefined,
|
|
702
|
+
note: typeof args.note === 'string' ? args.note : undefined,
|
|
703
|
+
timeoutMs: typeof args.check_timeout_ms === 'number'
|
|
704
|
+
? args.check_timeout_ms
|
|
705
|
+
: typeof args.timeout_ms === 'number'
|
|
706
|
+
? args.timeout_ms
|
|
707
|
+
: undefined,
|
|
708
|
+
leaseWaitMs: typeof args.lease_wait_ms === 'number' ? args.lease_wait_ms : undefined,
|
|
709
|
+
});
|
|
710
|
+
return result(validation as unknown as Record<string, unknown>, validation.accepted === false);
|
|
711
|
+
}
|
|
712
|
+
|
|
681
713
|
export async function routeDurableMcpCall(
|
|
682
714
|
ctx: MultiRepositoryMcpToolContext,
|
|
683
715
|
name: string,
|
|
@@ -805,9 +837,8 @@ export async function routeDurableMcpCall(
|
|
|
805
837
|
}
|
|
806
838
|
}
|
|
807
839
|
|
|
808
|
-
// Edit-session verification uses the same
|
|
809
|
-
//
|
|
810
|
-
// instead of launching a duplicate command.
|
|
840
|
+
// Edit-session verification uses the same resource-aware Process Runtime
|
|
841
|
+
// coordinator as the stable Direct Edit composite below.
|
|
811
842
|
if (name === 'verify_edit_session' && classification.path === 'fast') {
|
|
812
843
|
const repository = resolveRepositorySelection({
|
|
813
844
|
repoId: typeof args.repo_id === 'string' ? args.repo_id : undefined,
|
|
@@ -823,175 +854,77 @@ export async function routeDurableMcpCall(
|
|
|
823
854
|
if (!editSessionId) {
|
|
824
855
|
return result({ accepted: false, mode: 'reject', path: 'reject', message: 'verify_edit_session requires session_id' });
|
|
825
856
|
}
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
note: typeof args.note === 'string' ? args.note : undefined,
|
|
842
|
-
});
|
|
843
|
-
return result({ accepted: true, mode: 'direct', path: 'process_direct', completed: true, ok: true, session: checked, receipts: [] });
|
|
844
|
-
}
|
|
845
|
-
// Parallel-first without a timeout-based correctness tradeoff. Build
|
|
846
|
-
// conflict-connected lanes from the same Resource Claim model used by the
|
|
847
|
-
// Lease store. Different lanes run concurrently; checks in one lane retain
|
|
848
|
-
// the historical managed-process behavior: once a check is still running,
|
|
849
|
-
// stop that lane and continue it on the caller's retry. This avoids turning
|
|
850
|
-
// a legitimate long serialization wait into PROCESS_LEASE_CONFLICT.
|
|
851
|
-
const availableChecks = new Map(listControllerChecks(repository.canonicalRoot).map((check) => [check.id, check] as const));
|
|
852
|
-
const claimSets = checkIds.map((checkId) => {
|
|
853
|
-
const check = availableChecks.get(checkId);
|
|
854
|
-
return claimsForCheck(
|
|
855
|
-
checkId,
|
|
856
|
-
check?.command,
|
|
857
|
-
repository.repoId,
|
|
858
|
-
repository.activeCheckoutId,
|
|
859
|
-
check?.effects,
|
|
860
|
-
);
|
|
857
|
+
return runEditSessionValidationViaProcessRuntime(ctx, repository, editSessionId, args);
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
// Stable Direct Edit composite: checks are opt-in. Without check_ids this
|
|
861
|
+
// tool remains the ordinary synchronous patch path. With check_ids, the same
|
|
862
|
+
// call applies one coherent edit batch, returns its review evidence, and
|
|
863
|
+
// starts revision-bound validation without waiting on long checks.
|
|
864
|
+
if (name === 'repository_safe_patch_apply' && classification.path === 'direct'
|
|
865
|
+
&& (args.validation_only === true || (Array.isArray(args.check_ids) && args.check_ids.length > 0))) {
|
|
866
|
+
const repository = resolveRepositorySelection({
|
|
867
|
+
repoId: typeof args.repo_id === 'string' ? args.repo_id : undefined,
|
|
868
|
+
checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined,
|
|
869
|
+
explicitPath: ctx.explicitRepository?.canonicalRoot,
|
|
870
|
+
controllerHome: ctx.controllerHome,
|
|
871
|
+
allowSoleRepository: true,
|
|
861
872
|
});
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
for (let start = 0; start < checkIds.length; start += 1) {
|
|
865
|
-
if (assigned.has(start)) continue;
|
|
866
|
-
const lane: number[] = [];
|
|
867
|
-
const queue = [start];
|
|
868
|
-
assigned.add(start);
|
|
869
|
-
while (queue.length > 0) {
|
|
870
|
-
const current = queue.shift()!;
|
|
871
|
-
lane.push(current);
|
|
872
|
-
for (let candidate = 0; candidate < checkIds.length; candidate += 1) {
|
|
873
|
-
if (assigned.has(candidate)) continue;
|
|
874
|
-
const conflicts = claimSets[current]!.some((left) =>
|
|
875
|
-
claimSets[candidate]!.some((right) => resourceClaimsConflict(left, right)));
|
|
876
|
-
if (!conflicts) continue;
|
|
877
|
-
assigned.add(candidate);
|
|
878
|
-
queue.push(candidate);
|
|
879
|
-
}
|
|
880
|
-
}
|
|
881
|
-
lanes.push(lane.sort((left, right) => left - right));
|
|
873
|
+
if (!repository) {
|
|
874
|
+
return result({ accepted: false, mode: 'reject', path: 'reject', message: 'repository_safe_patch_apply requires a resolvable repository' }, true);
|
|
882
875
|
}
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
for (const index of lane) {
|
|
889
|
-
const checkId = checkIds[index]!;
|
|
890
|
-
const checkRequestId = `${requestBase}:check:${index + 1}:${createHash('sha256').update(checkId).digest('hex').slice(0, 12)}`;
|
|
891
|
-
const facade = await runPersistedCheckViaProcessRuntime({
|
|
892
|
-
controllerHome: ctx.controllerHome,
|
|
893
|
-
repoId: repository.repoId,
|
|
894
|
-
checkoutId: repository.activeCheckoutId,
|
|
895
|
-
repoRoot: repository.canonicalRoot,
|
|
896
|
-
executionIdentity: executionIdentityForRepository(repository),
|
|
897
|
-
checkId,
|
|
898
|
-
timeoutMs: typeof args.timeout_ms === 'number' ? args.timeout_ms : undefined,
|
|
899
|
-
interactiveWaitMs: typeof args.interactive_wait_ms === 'number' ? args.interactive_wait_ms : undefined,
|
|
900
|
-
requestId: checkRequestId,
|
|
901
|
-
commandId: checkRequestId,
|
|
902
|
-
verificationBinding: {
|
|
903
|
-
editSessionId: editSession.sessionId,
|
|
904
|
-
editRevision: editSession.currentRevision,
|
|
905
|
-
issueId: editSession.issueId,
|
|
906
|
-
taskId: editSession.taskId,
|
|
907
|
-
},
|
|
908
|
-
leaseWaitMs,
|
|
909
|
-
});
|
|
910
|
-
facadesByIndex[index] = facade;
|
|
911
|
-
if (facade.mode === 'durable' || !facade.process || !facade.process.completed) break;
|
|
876
|
+
|
|
877
|
+
if (args.validation_only === true) {
|
|
878
|
+
const editSessionId = String(args.session_id ?? '').trim();
|
|
879
|
+
if (!editSessionId) {
|
|
880
|
+
return result({ accepted: false, mode: 'reject', path: 'reject', message: 'validation_only requires session_id' }, true);
|
|
912
881
|
}
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
const durableFailure = facades.find((facade) => facade.mode === 'durable' || !facade.process);
|
|
916
|
-
if (durableFailure) {
|
|
917
|
-
return result({
|
|
918
|
-
accepted: false,
|
|
919
|
-
mode: 'durable',
|
|
920
|
-
path: 'durable',
|
|
921
|
-
checkId: durableFailure.checkId,
|
|
922
|
-
message: durableFailure.durable?.reason ?? 'check requires durable workflow',
|
|
923
|
-
suggestedOperation: durableFailure.durable?.suggestedOperation,
|
|
924
|
-
});
|
|
925
|
-
}
|
|
926
|
-
const processes = facades.map((facade) => facade.process!);
|
|
927
|
-
const pending = processes.find((process) => !process.completed);
|
|
928
|
-
if (pending || processes.length !== checkIds.length) {
|
|
882
|
+
const validation = await runEditSessionValidationViaProcessRuntime(ctx, repository, editSessionId, args);
|
|
883
|
+
const validationPayload = (validation.structuredContent ?? {}) as Record<string, unknown>;
|
|
929
884
|
return result({
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
next:
|
|
939
|
-
|
|
940
|
-
|
|
885
|
+
operation: 'repository_safe_patch_apply',
|
|
886
|
+
validationOnly: true,
|
|
887
|
+
sessionId: editSessionId,
|
|
888
|
+
validation: validationPayload,
|
|
889
|
+
validationRequestId: validationPayload.validationRequestId,
|
|
890
|
+
completed: validationPayload.completed === true,
|
|
891
|
+
ok: validationPayload.ok,
|
|
892
|
+
acceptanceReady: validationPayload.completed === true && validationPayload.ok === true,
|
|
893
|
+
next: validationPayload.completed === true
|
|
894
|
+
? validationPayload.ok === true
|
|
895
|
+
? 'Validation passed for the exact edit revision; delivery may proceed if policy and semantic review are satisfied.'
|
|
896
|
+
: 'Validation completed with failures; return the failure evidence to ChatGPT for repair reasoning.'
|
|
897
|
+
: validationPayload.next,
|
|
898
|
+
}, validation.isError === true);
|
|
941
899
|
}
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
checkId,
|
|
957
|
-
processId: handle.processId,
|
|
958
|
-
...(currentIdentity ? {
|
|
959
|
-
checkExecution: {
|
|
960
|
-
cacheKey: currentIdentity.cacheKey,
|
|
961
|
-
revision: currentIdentity.revision,
|
|
962
|
-
definitionDigest: currentIdentity.definitionDigest,
|
|
963
|
-
environmentFingerprint: currentIdentity.environmentFingerprint,
|
|
964
|
-
timeoutMs: currentIdentity.timeoutMs,
|
|
965
|
-
scopeKey: processCheckSemanticScopeKey({
|
|
966
|
-
checkoutId: repository.activeCheckoutId,
|
|
967
|
-
verificationBinding: {
|
|
968
|
-
editSessionId: editSession.sessionId,
|
|
969
|
-
editRevision: editSession.currentRevision,
|
|
970
|
-
issueId: editSession.issueId,
|
|
971
|
-
taskId: editSession.taskId,
|
|
972
|
-
},
|
|
973
|
-
}, currentIdentity.reuseScope),
|
|
974
|
-
},
|
|
975
|
-
} : {}),
|
|
976
|
-
});
|
|
977
|
-
});
|
|
978
|
-
const checked = recordEditSessionProcessCheckReceipts(repository.canonicalRoot, editSession.sessionId, {
|
|
979
|
-
repoId: repository.repoId,
|
|
980
|
-
checkoutId: repository.activeCheckoutId,
|
|
981
|
-
receipts,
|
|
982
|
-
reviewer: typeof args.reviewer === 'string' ? args.reviewer : undefined,
|
|
983
|
-
note: typeof args.note === 'string' ? args.note : undefined,
|
|
984
|
-
});
|
|
900
|
+
|
|
901
|
+
const applied = await callRepositoryTool(ctx.controllerHome, name, args);
|
|
902
|
+
if (!applied || applied.isError === true) return applied;
|
|
903
|
+
const patchPayload = (applied.structuredContent ?? {}) as Record<string, unknown>;
|
|
904
|
+
if (patchPayload.status !== 'applied') return applied;
|
|
905
|
+
const session = patchPayload.session && typeof patchPayload.session === 'object'
|
|
906
|
+
? patchPayload.session as Record<string, unknown>
|
|
907
|
+
: undefined;
|
|
908
|
+
const editSessionId = typeof session?.sessionId === 'string' ? session.sessionId : '';
|
|
909
|
+
if (!editSessionId) return applied;
|
|
910
|
+
const validation = await runEditSessionValidationViaProcessRuntime(ctx, repository, editSessionId, args);
|
|
911
|
+
const validationPayload = (validation.structuredContent ?? {}) as Record<string, unknown>;
|
|
912
|
+
const validationCompleted = validationPayload.completed === true;
|
|
913
|
+
const validationPassed = validationCompleted && validationPayload.ok === true;
|
|
985
914
|
return result({
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
915
|
+
...patchPayload,
|
|
916
|
+
validation: validationPayload,
|
|
917
|
+
validationStarted: true,
|
|
918
|
+
validationCompleted,
|
|
919
|
+
validationPassed,
|
|
920
|
+
acceptanceReady: validationPassed,
|
|
921
|
+
validationRequestId: validationPayload.validationRequestId,
|
|
922
|
+
next: validationCompleted
|
|
923
|
+
? validationPassed
|
|
924
|
+
? 'Patch review evidence and requested validation are complete; proceed to delivery only after ChatGPT semantic review is satisfied.'
|
|
925
|
+
: 'Patch applied but validation failed; return the failure evidence to ChatGPT before any delivery.'
|
|
926
|
+
: validationPayload.next,
|
|
927
|
+
}, validation.isError === true);
|
|
995
928
|
}
|
|
996
929
|
|
|
997
930
|
// run_check Process Runtime facade — execute here so legacy LocalBridgeJob path is skipped.
|
|
@@ -1030,9 +963,11 @@ export async function routeDurableMcpCall(
|
|
|
1030
963
|
executionIdentity: executionIdentityForRepository(repository),
|
|
1031
964
|
checkId,
|
|
1032
965
|
timeoutMs: typeof args.timeout_ms === 'number' ? args.timeout_ms : undefined,
|
|
1033
|
-
interactiveWaitMs:
|
|
966
|
+
interactiveWaitMs: args.apply_mode === 'async' || args.mode === 'async' || args.async === true || args.background === true
|
|
967
|
+
? 0
|
|
968
|
+
: typeof args.interactive_wait_ms === 'number' ? args.interactive_wait_ms : undefined,
|
|
1034
969
|
requestId: typeof args.request_id === 'string' ? args.request_id : undefined,
|
|
1035
|
-
forceDurable: args.force_durable === true,
|
|
970
|
+
forceDurable: args.force_durable === true || args.mode === 'durable',
|
|
1036
971
|
});
|
|
1037
972
|
if (facade.mode === 'durable') {
|
|
1038
973
|
// Multi-phase/release should already be classified durable. Remaining durable
|
|
@@ -1077,7 +1012,7 @@ export async function routeDurableMcpCall(
|
|
|
1077
1012
|
durableSideEffects: facade.durableSideEffects,
|
|
1078
1013
|
next: handle?.completed
|
|
1079
1014
|
? 'Check finished on Process Runtime without ExecutionJob / LocalBridgeJob / Worker.'
|
|
1080
|
-
: `Check still running as managed process ${handle?.processId}.
|
|
1015
|
+
: `Check still running as managed process ${handle?.processId}. Continue independent work; use process_wait once when this result becomes a real dependency. Do not re-run or repeatedly poll the same check.`,
|
|
1081
1016
|
});
|
|
1082
1017
|
}
|
|
1083
1018
|
|