@moretea-labs/forge 1.8.1 → 1.8.2
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 +5 -2
- package/CHANGELOG.md +20 -0
- package/README.en.md +24 -3
- package/README.md +10 -6
- package/README.zh-CN.md +5 -3
- package/THIRD_PARTY_NOTICES.md +1 -2
- package/adapters/chatgpt/browser-delivery-runtime.ts +5 -3
- package/adapters/chatgpt/provider-delivery.ts +1 -1
- package/adapters/chatgpt/work-conversation-binding-store.ts +20 -1
- package/adapters/computer/chatgpt-extension-target.ts +295 -50
- package/adapters/computer/chrome-extension/background.js +227 -71
- package/adapters/computer/chrome-extension/content.js +181 -157
- package/adapters/computer/chrome-extension/manifest.json +3 -1
- package/adapters/computer/desktop-operator-provider.ts +18 -6
- package/adapters/computer/interaction-target-authority.ts +39 -9
- package/adapters/mcp/access-mode.ts +18 -39
- package/adapters/mcp/auth.ts +2 -6
- package/adapters/mcp/instructions.ts +2 -2
- package/adapters/mcp/multi-repository.ts +7 -28
- package/adapters/mcp/runtime-gateway/context-adapter.ts +79 -40
- package/adapters/mcp/runtime-gateway/context-pack-sidecar.ts +7 -15
- package/adapters/mcp/runtime-gateway/execution-tools.ts +7 -13
- package/adapters/mcp/runtime-gateway/plugin-adapter.ts +16 -3
- package/adapters/mcp/runtime-gateway/process-tools.ts +3 -21
- package/adapters/mcp/runtime-gateway/router.ts +3 -5
- package/adapters/mcp/runtime-gateway/routing-policy.ts +17 -10
- package/adapters/mcp/runtime-gateway/runtime-observation-adapter.ts +1 -1
- package/adapters/mcp/runtime-gateway/runtime-tool-definitions.ts +14 -9
- package/adapters/mcp/runtime-gateway/runtime-tools.ts +1 -5
- package/adapters/mcp/runtime-gateway/scheduler-adapter.ts +36 -1
- package/adapters/mcp/runtime-gateway/status-inbox-adapter.ts +58 -4
- package/adapters/mcp/runtime-gateway/typescript-navigation-sidecar.ts +7 -3
- package/adapters/mcp/runtime-gateway/work-adapter.ts +16 -16
- package/adapters/mcp/runtime-gateway/work-input-wire-migration.ts +0 -17
- package/adapters/mcp/runtime-gateway/work-semantic-operations.ts +69 -12
- package/adapters/mcp/runtime-gateway/workflow-supervisor-adapter.ts +26 -2
- package/adapters/mcp/server.ts +24 -3
- package/adapters/mcp/setup.ts +4 -10
- package/adapters/mcp/tool-mapping/access-tools.ts +0 -6
- package/adapters/mcp/tool-mapping/legacy-tool-service.ts +672 -2935
- package/adapters/mcp/tool-mapping/post-finalize-work-attribution.ts +1 -1
- package/adapters/mcp/tool-mapping/repository-tools.ts +52 -86
- package/adapters/mcp/toolset-names.ts +11 -42
- package/adapters/mcp/toolset.ts +16 -90
- package/{src/cli → adapters}/mcp/transports/AGENTS.md +5 -5
- package/{src/cli → adapters}/mcp/transports/CLAUDE.md +5 -5
- package/adapters/mcp/transports/http-observation.ts +18 -6
- package/adapters/mcp/transports/http-post-lifecycle.ts +19 -0
- package/adapters/mcp/transports/http.ts +54 -14
- package/adapters/mcp/types.ts +0 -6
- package/assets/hooks/lib/session-state.sh +0 -38
- package/assets/hooks/post-bash.sh +1 -1
- package/assets/hooks/post-tool-observer.sh +0 -5
- package/assets/hooks/prompt-guard.sh +0 -55
- package/assets/partials/04-project-structure.partial.md +1 -1
- package/assets/partials/07-footer.partial.md +1 -1
- package/assets/partials-agents/02-operating-mode.partial.md +1 -1
- package/assets/partials-agents/08-deep-docs.partial.md +1 -1
- package/assets/reference-configs/agentic-development-flow.md +1 -1
- package/assets/reference-configs/external-tooling.md +0 -76
- package/assets/reference-configs/release-deploy.md +1 -1
- package/assets/templates/helpers/architecture-queue.sh +1 -1
- package/assets/templates/helpers/check-agent-tooling.sh +1 -327
- package/assets/templates/helpers/check-task-workflow.sh +1 -1
- package/assets/templates/helpers/ensure-task-workflow.sh +0 -14
- package/assets/templates/helpers/migrate-project-template.sh +2 -2
- package/assets/workflow-contract.v1.json +0 -2
- package/docs/README.md +5 -2
- package/docs/architecture/CURRENT.md +114 -30
- package/docs/architecture/decisions/20260904-ios-device-migration-baseline.md +42 -0
- package/docs/architecture/decisions/20260918-stable-candidate-release-lifecycle.md +15 -2
- package/docs/architecture/decisions/20260924-thin-semantic-working-context.md +4 -2
- package/docs/architecture/decisions/20261001-supervisor-turn-authority.md +109 -4
- package/docs/architecture/decisions/20261009-exact-code-context-discovery.md +19 -0
- package/docs/architecture/decisions/20261009-generated-xcode-cache-retention.md +37 -0
- package/docs/architecture/decisions/20261011-autonomous-continuation-convergence.md +597 -0
- package/docs/architecture/decisions/20261017-edit-session-finalization-reconciliation.md +17 -0
- package/docs/architecture/decisions/20261019-retire-host-skills.md +16 -0
- package/docs/architecture/diagrams/agentic-dev-plugin-architecture.html +1 -1
- package/docs/architecture/domains/public-surface.md +3 -5
- package/docs/architecture/domains/verification.md +5 -5
- package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +2 -2
- package/docs/architecture/requests/2026-09-04-computer-plugin-workflow-taxonomy.md +4 -4
- package/docs/architecture/reviews/20261015-code-search-runtime-acceptance.md +75 -0
- package/docs/forge-plugin-management.md +14 -2
- package/docs/operations/controller-browser-plugin.md +23 -0
- package/docs/operations/features.md +6 -7
- package/docs/operations/features.zh-CN.md +1 -1
- package/docs/operations/github-repository.md +4 -4
- package/docs/operations/github-semantic-release-projection.md +20 -0
- package/docs/operations/homebrew.md +2 -2
- package/docs/operations/mcp-tool-exposure.md +13 -54
- package/docs/operations/runtime-performance-diagnostics.md +8 -0
- package/docs/operations/standalone-disaster-recovery.md +1 -1
- package/docs/tutorials/01-install-and-start.zh-CN.md +1 -1
- package/docs/tutorials/03-first-repository-task.md +2 -0
- package/docs/wiki/Computer-and-Plugins.md +78 -0
- package/docs/wiki/Computer-and-Plugins.zh-CN.md +88 -0
- package/docs/wiki/Home.md +16 -2
- package/docs/wiki/Implementation.md +24 -12
- package/docs/wiki/Installation.md +28 -32
- package/docs/wiki/Integrations.md +4 -0
- package/docs/wiki/Quick-Start.md +35 -22
- package/docs/wiki/Releases-and-Upgrades.md +15 -25
- package/docs/wiki/_Sidebar.md +5 -1
- package/package.json +1 -12
- package/packages/kernel/controller/infrastructure/controller-session-store.ts +63 -38
- package/packages/kernel/identity/infrastructure/activity-projection-store.ts +10 -0
- package/packages/kernel/scheduler/application/eligibility.ts +4 -1
- package/packages/kernel/scheduler/infrastructure/schedule-store.ts +13 -10
- package/packages/kernel/work/application/work-service.ts +1 -0
- package/packages/kernel/work/domain/repository-completion-receipt.ts +1 -1
- package/packages/kernel/work/domain/state-machine.ts +9 -2
- package/packages/kernel/work/infrastructure/work-contract-store.ts +28 -1
- package/packages/plugin-runtime/browser/provider-registry.ts +12 -36
- package/packages/plugin-runtime/computer/conversation-target.ts +17 -7
- package/scripts/assemble-template.ts +11 -72
- package/scripts/check-mcp-compatibility.ts +55 -74
- package/scripts/check-package-identity.mjs +0 -5
- package/scripts/check-runtime-architecture.mjs +305 -28
- package/scripts/init-project.sh +0 -46
- package/scripts/install-ios-hid-toolchain.sh +60 -0
- package/scripts/install-standalone-recovery.ts +1 -1
- package/scripts/lib/project-init-lib.sh +3 -3
- package/scripts/migrate-windows-wsl-controller-home.ts +2 -0
- package/scripts/open-source-audit-allowlist.txt +0 -1
- package/scripts/run-governed-gate.ts +2 -0
- package/scripts/smoke-ios-physical-device.ts +38 -10
- package/scripts/smoke-mcp-http-runtime.ts +7 -8
- package/scripts/smoke-mcp-tool-surface.ts +27 -41
- package/scripts/smoke-workflow-supervisor-chrome-adapter.ts +6 -3
- package/scripts/sync-generated-authority.mjs +0 -1
- package/src/cli/agent-jobs/executor-health.ts +1 -1
- package/src/cli/agent-jobs/integration.ts +2 -2
- package/src/cli/chatgpt-browser/file-policy.ts +2 -2
- package/src/cli/commands/doctor.ts +1 -143
- package/src/cli/commands/global-runtime.ts +3 -196
- package/src/cli/commands/init-hook.ts +6 -23
- package/src/cli/commands/init.ts +3 -252
- package/src/cli/commands/mcp.ts +0 -5
- package/src/cli/commands/prompt-guard-decision.ts +0 -2
- package/src/cli/commands/recovery.ts +2 -14
- package/src/cli/commands/repository.ts +17 -1
- package/src/cli/commands/setup-execution.ts +41 -0
- package/src/cli/controller/completion-orchestrator.ts +1 -1
- package/src/cli/controller/composite-operations.ts +1 -1
- package/src/cli/controller/context/instruction-context.ts +1 -1
- package/src/cli/controller/context/known-paths.ts +2 -2
- package/src/cli/controller/context/query-planning.ts +11 -4
- package/src/cli/controller/context/rule-resolution.ts +2 -2
- package/src/cli/controller/context/source-materializer.ts +2 -2
- package/src/cli/controller/context/structural-provider.ts +84 -0
- package/src/cli/controller/context/structural.ts +6 -6
- package/src/cli/controller/context/types.ts +8 -9
- package/src/cli/controller/context-pack.ts +97 -76
- package/src/cli/controller/operational-plan.ts +1 -1
- package/src/cli/controller/systemd-user.ts +4 -10
- package/src/cli/editing/edit-session.ts +17 -5
- package/src/cli/github/github.ts +4 -4
- package/src/cli/github/semantic-projection.ts +174 -0
- package/src/cli/hook/prompt-intents.ts +0 -9
- package/src/cli/index.ts +1 -43
- package/src/cli/local-bridge/connector-freshness.ts +1 -12
- package/src/cli/local-bridge/console-automations.ts +1 -1
- package/src/cli/local-bridge/console-view-models.ts +1 -1
- package/src/cli/local-bridge/facade-api.ts +0 -2
- package/src/cli/repositories/command-classifier.ts +0 -9
- package/src/cli/repositories/command-scope.ts +2 -2
- package/src/cli/repositories/locks.ts +20 -0
- package/src/cli/repositories/registry.ts +2 -1
- package/src/cli/repositories/safe-patch.ts +2 -12
- package/src/cli/repositories/structured-git.ts +39 -3
- package/src/cli/repository/inspector.ts +185 -343
- package/src/effects/process-runner.ts +17 -1
- package/src/runtime/context/generic-lsp-provider.ts +1 -1
- package/src/runtime/context/semantic-navigation-contract.ts +7 -0
- package/src/runtime/context/semantic-navigation.ts +1 -1
- package/src/runtime/control-plane/cleanup-artifact-retention.ts +4 -4
- package/src/runtime/control-plane/execution/work-delivery-service.ts +150 -31
- package/src/runtime/control-plane/execution/work-handle-authority.ts +12 -4
- package/src/runtime/control-plane/execution/work-handle-store.ts +53 -1
- package/src/runtime/control-plane/execution/work-operation-service.ts +20 -10
- package/src/runtime/control-plane/execution/work-preparation-service.ts +108 -4
- package/src/runtime/control-plane/execution/work-process-evidence.ts +2 -2
- package/src/runtime/control-plane/execution/work-terminal-cleanup.ts +28 -13
- package/src/runtime/control-plane/execution/work-validation-reconciler.ts +5 -1
- package/src/runtime/control-plane/execution/work-verification-snapshot.ts +1 -1
- package/src/runtime/control-plane/facade/capability-registry.ts +2 -0
- package/src/runtime/control-plane/facade/work-continuation.ts +1 -1
- package/src/runtime/control-plane/generated-cache-retention.ts +114 -63
- package/src/runtime/control-plane/global-scheduler/maintenance.ts +20 -8
- package/src/runtime/control-plane/global-scheduler/reconciliation.ts +1 -11
- package/src/runtime/control-plane/governance/external-effects.ts +1 -1
- package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +1 -0
- package/src/runtime/control-plane/runtime-cleanup.ts +12 -93
- package/src/runtime/evidence/sensitive-output.ts +22 -2
- package/src/runtime/execution/jobs/child-reference.ts +11 -0
- package/src/runtime/execution/jobs/receipt-recovery.ts +1 -11
- package/src/runtime/execution/process-runtime/command-facade.ts +3 -3
- package/src/runtime/execution/process-runtime/runtime.ts +20 -16
- package/src/runtime/execution/thin-harness/execution-router.ts +16 -16
- package/src/runtime/execution/thin-harness/fast-executor.ts +2 -2
- package/src/runtime/execution/thin-harness/search-worker.ts +2 -2
- package/src/runtime/execution/workers/executor.ts +1 -2
- package/src/runtime/maintenance/cleanup.ts +41 -5
- package/src/runtime/plugins/action-application.ts +12 -1
- package/src/runtime/plugins/app-store-connect-adapter.ts +252 -4
- package/src/runtime/plugins/browser-adapter.ts +381 -313
- package/src/runtime/plugins/browser-macos-bridge.ts +114 -112
- package/src/runtime/plugins/browser-manifest-surface.ts +2 -1
- package/src/runtime/plugins/browser-registration.ts +2 -0
- package/src/runtime/plugins/browser-runtime.ts +26 -35
- package/src/runtime/plugins/computer-chatgpt-browser-adapter-installer.ts +11 -2
- package/src/runtime/plugins/computer-registration.ts +76 -9
- package/src/runtime/plugins/github-adapter.ts +30 -3
- package/src/runtime/plugins/gmail-adapter.ts +166 -1
- package/src/runtime/plugins/google-shared.ts +10 -5
- package/src/runtime/plugins/ios/remote-xpc-hid.ts +70 -30
- package/src/runtime/plugins/ios-adapter.ts +45 -40
- package/src/runtime/plugins/ios-agent-device.ts +54 -4
- package/src/runtime/plugins/ios-device-ownership.ts +103 -0
- package/src/runtime/plugins/ios-physical-device.ts +497 -79
- package/src/runtime/plugins/local-system-adapter.ts +1 -99
- package/src/runtime/plugins/store.ts +80 -7
- package/src/runtime/plugins/types.ts +4 -0
- package/src/runtime/projections/git-status-sampler.ts +2 -19
- package/src/runtime/recovery/actions.ts +1 -1
- package/src/runtime/recovery/lifecycle-inventory.ts +1 -11
- package/src/runtime/recovery/probe.ts +2 -2
- package/src/runtime/release/release-coordinator.ts +20 -4
- package/src/runtime/root/controller-progression-composition.ts +67 -5
- package/src/runtime/root/package-connector-service.ts +123 -11
- package/src/runtime/root/package-runtime-release.ts +6 -18
- package/src/runtime/root/package-runtime-service.ts +7 -13
- package/src/runtime/root/release-execution-canary.ts +18 -5
- package/src/runtime/root/release-manifest.ts +0 -34
- package/src/runtime/root/release-materialize.ts +0 -78
- package/src/runtime/root/runtime.ts +1 -2
- package/src/runtime/root/scheduled-controller-composition.ts +2 -1
- package/src/runtime/root/service.ts +90 -11
- package/src/runtime/root/types.ts +0 -6
- package/src/runtime/root/workflow-supervisor-composition.ts +207 -19
- package/src/runtime/root/workflow-supervisor-runtime.ts +365 -10
- package/src/runtime/safe-tooling/google-credential-store.ts +1 -11
- package/src/runtime/safe-tooling/ios-development.ts +22 -8
- package/src/runtime/safe-tooling/job-summary.ts +1 -1
- package/src/runtime/safe-tooling/workspace-auth.ts +4 -1
- package/src/runtime/shared/atomic-text-file.ts +21 -0
- package/src/runtime/shared/json-files.ts +8 -3
- package/src/runtime/standalone-recovery/core.ts +189 -174
- package/src/runtime/standalone-recovery/entry.ts +62 -30
- package/src/runtime/standalone-recovery/operation-lock.ts +11 -1
- package/src/runtime/workflow/schedules/chatgpt-automation-migration.ts +1 -0
- package/src/runtime/workflow/schedules/engine.ts +36 -14
- package/src/runtime/workflow/schedules/pending-activation.ts +11 -4
- package/src/runtime/workflow/schedules/work-continuation.ts +51 -6
- package/supervisor/client.ts +31 -14
- package/supervisor/control-plane.ts +210 -115
- package/supervisor/forge-validators.ts +88 -21
- package/supervisor/native-browser-adapter.ts +393 -28
- package/supervisor/native-messaging/host.ts +21 -2
- package/supervisor/protocol.ts +74 -26
- package/supervisor/server.ts +16 -8
- package/supervisor/store.ts +476 -57
- package/supervisor/types.ts +19 -13
- package/SKILL.md +0 -427
- package/adapters/computer/chatgpt-target-router.ts +0 -103
- package/adapters/mcp/runtime-gateway/automation-receipt-adapter.ts +0 -87
- package/adapters/mcp/runtime-gateway/work-validation-reconciler.ts +0 -1
- package/adapters/mcp/toolset-selection.ts +0 -41
- package/agents/openai.yaml +0 -4
- package/assets/skill-hooks.json +0 -41
- package/assets/skill-version.json +0 -189
- package/assets/skills/claude-review/SKILL.md +0 -231
- package/assets/skills/codex-review/SKILL.md +0 -103
- package/assets/templates/helpers/check-skill-version.ts +0 -193
- package/scripts/check-skill-version.ts +0 -5
- package/scripts/ensure-codegraph.sh +0 -16
- package/scripts/run-skill-hook.ts +0 -244
- package/scripts/sync-codex-installed-copies.sh +0 -182
- package/src/cli/commands/tools.ts +0 -167
- package/src/cli/mcp/access-mode.ts +0 -2
- package/src/cli/mcp/access-tools.ts +0 -2
- package/src/cli/mcp/audit.ts +0 -2
- package/src/cli/mcp/auth.ts +0 -2
- package/src/cli/mcp/instructions.ts +0 -2
- package/src/cli/mcp/legacy-context.ts +0 -2
- package/src/cli/mcp/legacy-tool-service.ts +0 -2
- package/src/cli/mcp/multi-repository.ts +0 -2
- package/src/cli/mcp/oauth.ts +0 -2
- package/src/cli/mcp/openai-secure-tunnel.ts +0 -2
- package/src/cli/mcp/paths.ts +0 -2
- package/src/cli/mcp/policy.ts +0 -2
- package/src/cli/mcp/post-finalize-work-attribution.ts +0 -2
- package/src/cli/mcp/proxy-env.ts +0 -2
- package/src/cli/mcp/readiness-projection.ts +0 -2
- package/src/cli/mcp/redaction.ts +0 -2
- package/src/cli/mcp/repo.ts +0 -2
- package/src/cli/mcp/repository-tools.ts +0 -2
- package/src/cli/mcp/server.ts +0 -2
- package/src/cli/mcp/setup.ts +0 -2
- package/src/cli/mcp/tool-capability-cache.ts +0 -2
- package/src/cli/mcp/tool-contract.ts +0 -2
- package/src/cli/mcp/tools.ts +0 -2
- package/src/cli/mcp/toolset-names.ts +0 -2
- package/src/cli/mcp/toolset-selection.ts +0 -2
- package/src/cli/mcp/toolset.ts +0 -2
- package/src/cli/mcp/transports/http.ts +0 -2
- package/src/cli/mcp/transports/session-registry.ts +0 -2
- package/src/cli/mcp/transports/stdio.ts +0 -2
- package/src/cli/mcp/types.ts +0 -2
- package/src/cli/mcp/umbrella-tools.ts +0 -2
- package/src/cli/tools/codegraph.ts +0 -695
- package/src/core/adoption/helper-wrapper-plan.ts +0 -159
- package/src/runtime/context/codegraph-cache-boundary.ts +0 -255
- package/src/runtime/context/codegraph-read-provider.ts +0 -611
- package/src/runtime/context/codegraph-sidecar.cjs +0 -248
- package/src/runtime/control-plane/codegraph-cache-retention.ts +0 -164
- package/src/runtime/gateway/mcp/execution-tools.ts +0 -2
- package/src/runtime/gateway/mcp/legacy-ios-tool-adapter.ts +0 -2
- package/src/runtime/gateway/mcp/persisted-check-process.ts +0 -2
- package/src/runtime/gateway/mcp/process-tools.ts +0 -2
- package/src/runtime/gateway/mcp/router.ts +0 -2
- package/src/runtime/gateway/mcp/runtime-tool-definitions.ts +0 -2
- package/src/runtime/gateway/mcp/runtime-tools.ts +0 -2
- package/src/runtime/gateway/mcp/work-validation-reconciler.ts +0 -2
- package/src/runtime/plugins/browser-provider-registry.ts +0 -2
- package/src/runtime/plugins/computer-chatgpt-macos-target.ts +0 -891
|
@@ -5,6 +5,7 @@ import { listControllerChecks } from '../../../src/cli/controller/check-runner';
|
|
|
5
5
|
import { repositoryGitStatus } from '../../../src/cli/repositories/structured-git';
|
|
6
6
|
import { getWorkContract, updateWorkContract, workSemanticView } from '../../../packages/kernel/work/api/index';
|
|
7
7
|
import { ensureRepositoryWorkHandle } from '../../../src/runtime/control-plane/execution/work-handle-authority';
|
|
8
|
+
import { readWorkHandle } from '../../../src/runtime/control-plane/execution/work-handle-store';
|
|
8
9
|
import { ensureManagedWorkspace } from '../../../src/runtime/execution/managed-workspace';
|
|
9
10
|
import { ensureRepositoryProjectOnboarding } from '../../../src/runtime/control-plane/workspace/project-onboarding';
|
|
10
11
|
import { buildFacadeResult } from '../../../src/runtime/control-plane/facade';
|
|
@@ -16,7 +17,7 @@ import { invalidFacadeOperation } from './status-inbox-adapter';
|
|
|
16
17
|
import { normalizeRhWorkInputWireMigration } from './work-input-wire-migration';
|
|
17
18
|
import { callRhWorkScheduleAdapter, isRhWorkScheduleOperation } from './scheduler-adapter';
|
|
18
19
|
import { callRhWorkRequirementOperation, isRhWorkRequirementOperation } from './work-requirement-operations';
|
|
19
|
-
import { callRhWorkSemanticOperation, semanticWorkId } from './work-semantic-operations';
|
|
20
|
+
import { buildWorkSemanticFacadeResult, callRhWorkSemanticOperation, semanticWorkId } from './work-semantic-operations';
|
|
20
21
|
import { callRhWorkListProjection } from './work-list-projection';
|
|
21
22
|
import {
|
|
22
23
|
callRhWorkPlanCreateOperation,
|
|
@@ -27,7 +28,6 @@ import { callRhWorkWorkflowOperation } from './work-workflow-operations';
|
|
|
27
28
|
import { callRhWorkLearningOperation } from './work-learning-operations';
|
|
28
29
|
import { callRhWorkControllerOperation } from './work-controller-operations';
|
|
29
30
|
import { runFacadeRepair } from './work-repair-adapter';
|
|
30
|
-
import { isAutomationReceiptCompatibilityCall } from './automation-receipt-adapter';
|
|
31
31
|
import { authenticatedFacadeControllerIdentity } from './controller-authority-adapter';
|
|
32
32
|
|
|
33
33
|
export { runFacadeRepair };
|
|
@@ -79,12 +79,19 @@ async function callRepositoryBoundStart(
|
|
|
79
79
|
|
|
80
80
|
try {
|
|
81
81
|
const rawConstraints = contextRecord(args.constraints);
|
|
82
|
-
// Placement is caller-owned.
|
|
83
|
-
// of the durable-Work isolated/frozen-base default;
|
|
84
|
-
//
|
|
85
|
-
const requestedWorkspaceMode: 'current' | 'isolated' = rawConstraints.workspace_mode === '
|
|
86
|
-
? '
|
|
87
|
-
: '
|
|
82
|
+
// Placement is caller-owned. Omitted placement and legacy `auto` are the
|
|
83
|
+
// stable mechanical spelling of the durable-Work isolated/frozen-base default;
|
|
84
|
+
// only explicit `current` may reuse the selected canonical checkout.
|
|
85
|
+
const requestedWorkspaceMode: 'current' | 'isolated' = rawConstraints.workspace_mode === 'current'
|
|
86
|
+
? 'current'
|
|
87
|
+
: 'isolated';
|
|
88
|
+
const existingHandle = readWorkHandle(ctx.controllerHome, repository.repoId, workId);
|
|
89
|
+
if (existingHandle) {
|
|
90
|
+
const existingWorkspaceMode = existingHandle.managedWorktree ? 'isolated' : 'current';
|
|
91
|
+
if (existingWorkspaceMode !== requestedWorkspaceMode) {
|
|
92
|
+
throw new Error(`WORK_REPOSITORY_ADMISSION_PLACEMENT_CONFLICT: ${workId}; existing=${existingWorkspaceMode}; requested=${requestedWorkspaceMode}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
88
95
|
const sourceStatus = repositoryGitStatus(repository);
|
|
89
96
|
const requestedSourceRevision = typeof args.source_revision === 'string' ? args.source_revision.trim() : '';
|
|
90
97
|
if (requestedSourceRevision && sourceStatus.head && requestedWorkspaceMode !== 'isolated' && requestedSourceRevision !== sourceStatus.head) {
|
|
@@ -137,7 +144,7 @@ async function callRepositoryBoundStart(
|
|
|
137
144
|
repository,
|
|
138
145
|
sourceRevision: baseRevision,
|
|
139
146
|
});
|
|
140
|
-
return result(
|
|
147
|
+
return result(buildWorkSemanticFacadeResult({
|
|
141
148
|
summary: `Work ${workId} admitted to repository execution on checkout ${checkoutId}.`,
|
|
142
149
|
data: {
|
|
143
150
|
work: workSemanticView(contract),
|
|
@@ -257,13 +264,6 @@ export async function callWorkAdapter(
|
|
|
257
264
|
const operation = wireMigration.operation;
|
|
258
265
|
if (!isRhWorkAcceptedOperation(operation)) return invalidFacadeOperation('rh_work', operation);
|
|
259
266
|
|
|
260
|
-
if (operation === 'repair' && isAutomationReceiptCompatibilityCall(args)) {
|
|
261
|
-
return result(buildFacadeResult({
|
|
262
|
-
summary: 'Workflow Supervisor automation receipt accepted for canonical persistence.',
|
|
263
|
-
data: { automationReceiptCompatibility: true },
|
|
264
|
-
}) as unknown as Record<string, unknown>);
|
|
265
|
-
}
|
|
266
|
-
|
|
267
267
|
if (isRhWorkRequirementOperation(operation) && operation !== 'requirement_promote_candidate') {
|
|
268
268
|
const requirement = await callRhWorkRequirementOperation(ctx, undefined, operation, args);
|
|
269
269
|
if (requirement) return requirement;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { isDeepStrictEqual } from 'node:util';
|
|
2
|
-
import { AUTOMATION_RECEIPT_CAPABILITY_PREFIX } from './automation-receipt-adapter';
|
|
3
2
|
|
|
4
3
|
export type RhWorkInputWireMigrationResult =
|
|
5
4
|
| {
|
|
@@ -220,22 +219,6 @@ export function normalizeRhWorkInputWireMigration(input: Record<string, unknown>
|
|
|
220
219
|
return translateFrozenSemanticV1(args, parsed.value);
|
|
221
220
|
}
|
|
222
221
|
|
|
223
|
-
if (capabilityId.startsWith(AUTOMATION_RECEIPT_CAPABILITY_PREFIX)) {
|
|
224
|
-
// Frozen clients attach ordinary repository context and a reason. These are
|
|
225
|
-
// transport annotations, never receipt/task/effect authority. Strip them;
|
|
226
|
-
// the canonical Supervisor derives all causal identity from its own journal.
|
|
227
|
-
const allowed = new Set(['operation', 'capability_id', 'repo_id', 'checkout_id', 'reason']);
|
|
228
|
-
const unsupported = unsupportedInputField(args, allowed);
|
|
229
|
-
if (unsupported) return failure('FROZEN_MCP_AUTOMATION_RECEIPT_FIELD_UNSUPPORTED', { field: unsupported });
|
|
230
|
-
if (requestedOperation !== 'repair') return failure('FROZEN_MCP_AUTOMATION_RECEIPT_OPERATION_INVALID', { operation: requestedOperation });
|
|
231
|
-
for (const field of ['repo_id', 'checkout_id', 'reason']) {
|
|
232
|
-
if (args[field] !== undefined && (typeof args[field] !== 'string' || (args[field] as string).length > 2_000)) {
|
|
233
|
-
return failure('FROZEN_MCP_AUTOMATION_RECEIPT_FIELD_INVALID', { field });
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
return { ok: true, args: { operation: 'repair', capability_id: capabilityId }, operation: 'repair' };
|
|
237
|
-
}
|
|
238
|
-
|
|
239
222
|
if (capabilityId.includes(':')) {
|
|
240
223
|
return failure('FROZEN_MCP_LIFECYCLE_REMOVED: only bounded semantic.v1 and current-conversation enrollment carriers remain supported.', {
|
|
241
224
|
carrier: capabilityId.slice(0, capabilityId.indexOf(':')),
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
semanticWorkState,
|
|
13
13
|
type WorkContractStoreOptions,
|
|
14
14
|
} from '../../../packages/kernel/work/api/index';
|
|
15
|
-
import { buildFacadeResult } from '../../../src/runtime/control-plane/facade';
|
|
15
|
+
import { buildFacadeResult, type BuildFacadeResultOptions } from '../../../src/runtime/control-plane/facade';
|
|
16
16
|
import { getPlanContract, currentPlanSemanticRevision, getPlanSemanticRevisionRecord, planSemanticView } from '../../../src/runtime/control-plane/facade/plan-contract-store';
|
|
17
17
|
import { readRequirement, currentRequirementSemanticRevision, getRequirementRevisionRecord, requirementSemanticView } from '../../../src/runtime/control-plane/persistence/requirement-store';
|
|
18
18
|
import { buildWorkContinuationSnapshot } from '../../../src/runtime/control-plane/facade/work-continuation';
|
|
@@ -21,8 +21,61 @@ import { projectWorkExecutionEvidence } from './work-detail-projection';
|
|
|
21
21
|
import { readWorkHandle } from '../../../src/runtime/control-plane/execution/work-handle-store';
|
|
22
22
|
import { reconcileSingleTerminalWorkCleanup } from '../../../src/runtime/control-plane/execution/work-terminal-cleanup';
|
|
23
23
|
|
|
24
|
+
import { existsSync } from 'node:fs';
|
|
25
|
+
import { getWorkflowSupervisorTask, stopWorkflowSupervisorTask } from '../../../supervisor/client';
|
|
26
|
+
import { workflowSupervisorSocketPath } from '../../../supervisor/paths';
|
|
27
|
+
|
|
28
|
+
async function stopTerminalWorkSupervisor(
|
|
29
|
+
options: WorkContractStoreOptions,
|
|
30
|
+
workId: string,
|
|
31
|
+
state: 'completed' | 'cancelled',
|
|
32
|
+
): Promise<{ status: 'stopped' | 'already_terminal' | 'not_enrolled' | 'pending_reconcile'; reason?: string }> {
|
|
33
|
+
const controllerHome = options.controllerHome;
|
|
34
|
+
const repoId = options.repoId?.trim();
|
|
35
|
+
if (!controllerHome || !repoId || !existsSync(workflowSupervisorSocketPath(controllerHome))) {
|
|
36
|
+
return { status: 'pending_reconcile', reason: 'Supervisor socket unavailable; native consumer will reconcile terminal Work on restart.' };
|
|
37
|
+
}
|
|
38
|
+
const taskId = `forge:${repoId}:work:${workId}`;
|
|
39
|
+
try {
|
|
40
|
+
const task = await getWorkflowSupervisorTask(controllerHome, taskId);
|
|
41
|
+
if (!task) return { status: 'not_enrolled' };
|
|
42
|
+
// Fail closed: an unrelated Requirement/standalone Goal must never be
|
|
43
|
+
// stopped by a lower-layer Work transition.
|
|
44
|
+
if (task.taskId !== taskId || task.completionContract?.work_id !== workId
|
|
45
|
+
|| task.completionContract?.repo_id !== repoId
|
|
46
|
+
|| task.continuationPolicy.kind === 'standalone_supervisor') {
|
|
47
|
+
return { status: 'pending_reconcile', reason: 'Supervisor task contract is not exact Work-owned.' };
|
|
48
|
+
}
|
|
49
|
+
const stopped = await stopWorkflowSupervisorTask(controllerHome, taskId, `Work ${workId} changed to ${state}; its exact Work-owned automatic continuation is closed.`);
|
|
50
|
+
return { status: stopped.deduplicated ? 'already_terminal' : 'stopped' };
|
|
51
|
+
} catch (error) {
|
|
52
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
53
|
+
const code = reason.split(':', 1)[0]?.trim();
|
|
54
|
+
if (code === 'WORKFLOW_SUPERVISOR_TASK_UNKNOWN') return { status: 'not_enrolled' };
|
|
55
|
+
if (code === 'WORKFLOW_SUPERVISOR_TASK_TERMINAL') return { status: 'already_terminal' };
|
|
56
|
+
return { status: 'pending_reconcile', reason };
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
24
60
|
const RH_WORK_SEMANTIC_OPERATIONS = new Set(['start', 'get', 'revise', 'complete']);
|
|
25
61
|
|
|
62
|
+
type WorkSemanticFacadeData = Record<string, unknown> & {
|
|
63
|
+
work?: ReturnType<typeof workSemanticView>;
|
|
64
|
+
currentWork?: ReturnType<typeof workSemanticView>;
|
|
65
|
+
revisionHistory?: ReturnType<typeof listWorkSemanticRevisionRecords>;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export function buildWorkSemanticFacadeResult(options: BuildFacadeResultOptions<WorkSemanticFacadeData>) {
|
|
69
|
+
const facade = buildFacadeResult(options);
|
|
70
|
+
// These authored projections already have domain limits. Generic diagnostic
|
|
71
|
+
// clipping corrupts their read/revise round trip (100 refs become 50, and a
|
|
72
|
+
// valid objective becomes an ellipsis). Keep execution diagnostics bounded.
|
|
73
|
+
if (options.data.work) facade.data.work = options.data.work;
|
|
74
|
+
if (options.data.currentWork) facade.data.currentWork = options.data.currentWork;
|
|
75
|
+
if (options.data.revisionHistory) facade.data.revisionHistory = options.data.revisionHistory;
|
|
76
|
+
return facade;
|
|
77
|
+
}
|
|
78
|
+
|
|
26
79
|
/** Resolve semantic version references against existing canonical heads/history. */
|
|
27
80
|
function workBasis(store: WorkContractStoreOptions, x: { requirementId?: string; requirementRevision?: number; planId?: string; planRevision?: number }) {
|
|
28
81
|
const plan = x.planId ? getPlanContract(store, x.planId) : undefined;
|
|
@@ -118,18 +171,18 @@ export async function callRhWorkSemanticOperation(
|
|
|
118
171
|
const workId = operation === 'start' ? semanticWorkId(store, args) : String(args.work_id ?? '').trim();
|
|
119
172
|
if (operation === 'start') {
|
|
120
173
|
const objective = String(args.objective ?? '').trim();
|
|
121
|
-
if (!objective) return result(
|
|
174
|
+
if (!objective) return result(buildWorkSemanticFacadeResult({
|
|
122
175
|
status: 'blocked', summary: 'WORK_OBJECTIVE_REQUIRED', data: { workId },
|
|
123
176
|
}) as unknown as Record<string, unknown>, true);
|
|
124
177
|
const requestId = typeof args.request_id === 'string' ? args.request_id.trim() : '';
|
|
125
178
|
const existing = getWorkContract(store, workId);
|
|
126
179
|
if (existing) {
|
|
127
|
-
if (!semanticCreateMatches(existing, args, requestId)) return result(
|
|
180
|
+
if (!semanticCreateMatches(existing, args, requestId)) return result(buildWorkSemanticFacadeResult({
|
|
128
181
|
status: 'blocked',
|
|
129
182
|
summary: `WORK_SEMANTIC_CREATE_CONFLICT: ${workId}`,
|
|
130
183
|
data: { workId, currentWork: workSemanticView(existing) },
|
|
131
184
|
}) as unknown as Record<string, unknown>, true);
|
|
132
|
-
return result(
|
|
185
|
+
return result(buildWorkSemanticFacadeResult({
|
|
133
186
|
summary: `Work ${workId} already exists; semantic create was deduplicated.`,
|
|
134
187
|
data: { work: workSemanticView(existing), deduplicated: true },
|
|
135
188
|
}) as unknown as Record<string, unknown>);
|
|
@@ -150,17 +203,17 @@ export async function callRhWorkSemanticOperation(
|
|
|
150
203
|
...(Array.isArray(args.depends_on_work_ids) ? { dependsOnWorkIds: args.depends_on_work_ids.map(String) } : {}),
|
|
151
204
|
...(requestId ? { requestId } : {}),
|
|
152
205
|
});
|
|
153
|
-
return result(
|
|
206
|
+
return result(buildWorkSemanticFacadeResult({
|
|
154
207
|
summary: `Work ${workId} created as semantic context.`,
|
|
155
208
|
data: { work: workSemanticView(created), deduplicated: false },
|
|
156
209
|
}) as unknown as Record<string, unknown>);
|
|
157
210
|
} catch (error) {
|
|
158
211
|
const raced = getWorkContract(store, workId);
|
|
159
|
-
if (raced && semanticCreateMatches(raced, args, requestId)) return result(
|
|
212
|
+
if (raced && semanticCreateMatches(raced, args, requestId)) return result(buildWorkSemanticFacadeResult({
|
|
160
213
|
summary: `Work ${workId} already exists; semantic create was deduplicated.`,
|
|
161
214
|
data: { work: workSemanticView(raced), deduplicated: true },
|
|
162
215
|
}) as unknown as Record<string, unknown>);
|
|
163
|
-
return result(
|
|
216
|
+
return result(buildWorkSemanticFacadeResult({
|
|
164
217
|
status: 'blocked',
|
|
165
218
|
summary: error instanceof Error ? error.message : String(error),
|
|
166
219
|
data: { workId },
|
|
@@ -169,7 +222,7 @@ export async function callRhWorkSemanticOperation(
|
|
|
169
222
|
}
|
|
170
223
|
if (operation === 'get') {
|
|
171
224
|
const work = workId ? getWorkContract(store, workId) : undefined;
|
|
172
|
-
if (!work) return result(
|
|
225
|
+
if (!work) return result(buildWorkSemanticFacadeResult({
|
|
173
226
|
status: 'not_found', summary: `Work ${workId || '(missing)'} not found.`, data: { workId },
|
|
174
227
|
}) as unknown as Record<string, unknown>, true);
|
|
175
228
|
const semantic = workSemanticView(work);
|
|
@@ -180,7 +233,7 @@ export async function callRhWorkSemanticOperation(
|
|
|
180
233
|
listWorkSemanticRevisionRecords(store, undefined, 200),
|
|
181
234
|
semantic.workId,
|
|
182
235
|
) : undefined;
|
|
183
|
-
return result(
|
|
236
|
+
return result(buildWorkSemanticFacadeResult({
|
|
184
237
|
summary: `Work ${semantic.workId} retrieved at semantic revision ${semantic.revision}.`,
|
|
185
238
|
data: {
|
|
186
239
|
work: semantic,
|
|
@@ -222,9 +275,12 @@ export async function callRhWorkSemanticOperation(
|
|
|
222
275
|
...(Array.isArray(args.work_result_refs) ? { resultRefs: args.work_result_refs.map(String) } : {}),
|
|
223
276
|
});
|
|
224
277
|
const semantic = workSemanticView(revised);
|
|
278
|
+
const supervisorClosure = semantic.state !== 'open'
|
|
279
|
+
? await stopTerminalWorkSupervisor(store, semantic.workId, semantic.state)
|
|
280
|
+
: undefined;
|
|
225
281
|
let resourceReconciliation: Awaited<ReturnType<typeof reconcileSingleTerminalWorkCleanup>> | undefined;
|
|
226
282
|
if (
|
|
227
|
-
|
|
283
|
+
semantic.state !== 'open'
|
|
228
284
|
&& store.controllerHome
|
|
229
285
|
&& revised.repoId?.trim()
|
|
230
286
|
&& readWorkHandle(store.controllerHome, revised.repoId, revised.workId)
|
|
@@ -243,19 +299,20 @@ export async function callRhWorkSemanticOperation(
|
|
|
243
299
|
};
|
|
244
300
|
}
|
|
245
301
|
}
|
|
246
|
-
return result(
|
|
302
|
+
return result(buildWorkSemanticFacadeResult({
|
|
247
303
|
summary: `Work ${semantic.workId} revised atomically to semantic revision ${semantic.revision}.`,
|
|
248
304
|
data: {
|
|
249
305
|
work: semantic,
|
|
250
306
|
expectedRevision,
|
|
251
307
|
semanticRevision: semantic.revision,
|
|
252
308
|
versionBinding: versionBinding(store, revised, false),
|
|
309
|
+
...(supervisorClosure ? { supervisorClosure } : {}),
|
|
253
310
|
...(resourceReconciliation ? { resourceReconciliation } : {}),
|
|
254
311
|
},
|
|
255
312
|
}) as unknown as Record<string, unknown>);
|
|
256
313
|
} catch (error) {
|
|
257
314
|
const current = workId ? getWorkContract(store, workId) : undefined;
|
|
258
|
-
return result(
|
|
315
|
+
return result(buildWorkSemanticFacadeResult({
|
|
259
316
|
status: 'blocked', summary: error instanceof Error ? error.message : String(error),
|
|
260
317
|
data: { workId, expectedRevision, ...(current ? { currentWork: workSemanticView(current) } : {}) },
|
|
261
318
|
}) as unknown as Record<string, unknown>, true);
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
getWorkflowSupervisorTask,
|
|
6
6
|
getWorkflowSupervisorTaskStall,
|
|
7
7
|
listWorkflowSupervisorTasks,
|
|
8
|
+
listWorkflowSupervisorTerminalTasks,
|
|
8
9
|
migrateWorkflowSupervisorConversation,
|
|
9
10
|
recoverWorkflowSupervisorTask,
|
|
10
11
|
registerWorkflowSupervisorTask,
|
|
@@ -13,6 +14,7 @@ import {
|
|
|
13
14
|
stopWorkflowSupervisorTask,
|
|
14
15
|
} from '../../../supervisor/client';
|
|
15
16
|
import { resolveWorkflowSupervisorForgeHome } from '../../../supervisor/paths';
|
|
17
|
+
import { workflowSupervisorCompletionContractSha256 } from '../../../supervisor/store';
|
|
16
18
|
import type { MultiRepositoryMcpToolContext } from '../multi-repository';
|
|
17
19
|
import { result } from './result-adapter';
|
|
18
20
|
|
|
@@ -40,6 +42,10 @@ export async function callWorkflowSupervisorAdapter(
|
|
|
40
42
|
const requestId = textArg(args, 'request_id');
|
|
41
43
|
if (!objective) throw new Error('WORKFLOW_SUPERVISOR_OBJECTIVE_REQUIRED');
|
|
42
44
|
if (!requestId) throw new Error('WORKFLOW_SUPERVISOR_REQUEST_ID_REQUIRED');
|
|
45
|
+
const workId = textArg(args, 'work_id');
|
|
46
|
+
const requirementId = textArg(args, 'requirement_id');
|
|
47
|
+
if (workId && requirementId) throw new Error('WORKFLOW_SUPERVISOR_SEMANTIC_BINDING_AMBIGUOUS');
|
|
48
|
+
if ((workId || requirementId) && !repoId) throw new Error('WORKFLOW_SUPERVISOR_SEMANTIC_BINDING_REPO_REQUIRED');
|
|
43
49
|
const id = standaloneTaskId(repoId, requestId);
|
|
44
50
|
const task = await registerWorkflowSupervisorTask(forgeHome, {
|
|
45
51
|
taskId: id,
|
|
@@ -49,6 +55,8 @@ export async function callWorkflowSupervisorAdapter(
|
|
|
49
55
|
completionContract: {
|
|
50
56
|
kind: 'model_semantic_completion',
|
|
51
57
|
...(repoId ? { repo_id: repoId, controller_home: ctx.controllerHome } : {}),
|
|
58
|
+
...(workId ? { work_id: workId } : {}),
|
|
59
|
+
...(requirementId ? { requirement_id: requirementId } : {}),
|
|
52
60
|
},
|
|
53
61
|
continuationPolicy: { kind: 'standalone_supervisor', bootstrap: true, ...(repoId ? { repo_id: repoId } : {}) },
|
|
54
62
|
userBlockerPolicy: { kind: 'model_semantic_user_blocker' },
|
|
@@ -58,6 +66,10 @@ export async function callWorkflowSupervisorAdapter(
|
|
|
58
66
|
}
|
|
59
67
|
|
|
60
68
|
if (operation === 'list') {
|
|
69
|
+
if (args.terminal_only === true) {
|
|
70
|
+
const terminalTasks = await listWorkflowSupervisorTerminalTasks(forgeHome);
|
|
71
|
+
return result({ terminalTasks, count: terminalTasks.length, terminalOnly: true, summary: `${terminalTasks.length} canonically terminal Supervisor task(s) in retained history; conversations are not archived or deleted.` });
|
|
72
|
+
}
|
|
61
73
|
const activeOnly = args.active_only !== false;
|
|
62
74
|
const tasks = await listWorkflowSupervisorTasks(forgeHome, activeOnly);
|
|
63
75
|
return result({ tasks, count: tasks.length, activeOnly, summary: `${tasks.length} Supervisor task(s) listed.` });
|
|
@@ -67,19 +79,31 @@ export async function callWorkflowSupervisorAdapter(
|
|
|
67
79
|
const id = textArg(args, 'task_id');
|
|
68
80
|
const objective = textArg(args, 'objective');
|
|
69
81
|
const expectedObjectiveSha256 = textArg(args, 'expected_objective_sha256');
|
|
82
|
+
const expectedCompletionContractSha256 = textArg(args, 'expected_completion_contract_sha256');
|
|
83
|
+
const workId = textArg(args, 'work_id');
|
|
84
|
+
const requirementId = textArg(args, 'requirement_id');
|
|
70
85
|
const requestId = textArg(args, 'request_id');
|
|
71
86
|
if (!id) throw new Error('WORKFLOW_SUPERVISOR_TASK_ID_REQUIRED');
|
|
72
87
|
if (!objective) throw new Error('WORKFLOW_SUPERVISOR_OBJECTIVE_REQUIRED');
|
|
73
88
|
if (!expectedObjectiveSha256) throw new Error('WORKFLOW_SUPERVISOR_OBJECTIVE_REVISION_EXPECTED_SHA_REQUIRED');
|
|
74
89
|
if (!requestId) throw new Error('WORKFLOW_SUPERVISOR_REQUEST_ID_REQUIRED');
|
|
90
|
+
if (workId && requirementId) throw new Error('WORKFLOW_SUPERVISOR_SEMANTIC_BINDING_TARGET_INVALID');
|
|
91
|
+
if ((workId || requirementId) && !expectedCompletionContractSha256) throw new Error('WORKFLOW_SUPERVISOR_COMPLETION_CONTRACT_REVISION_EXPECTED_SHA_REQUIRED');
|
|
92
|
+
if (!(workId || requirementId) && expectedCompletionContractSha256) throw new Error('WORKFLOW_SUPERVISOR_COMPLETION_CONTRACT_REVISION_TARGET_REQUIRED');
|
|
75
93
|
const revised = await reviseWorkflowSupervisorTaskObjective(forgeHome, {
|
|
76
94
|
taskId: id,
|
|
77
95
|
objective,
|
|
78
96
|
expectedObjectiveSha256,
|
|
79
97
|
requestId,
|
|
98
|
+
...(workId ? { workId } : {}),
|
|
99
|
+
...(requirementId ? { requirementId } : {}),
|
|
100
|
+
...(expectedCompletionContractSha256 ? { expectedCompletionContractSha256 } : {}),
|
|
80
101
|
authorizedBy: textArg(args, 'authorized_by') || 'operator',
|
|
81
102
|
});
|
|
82
|
-
|
|
103
|
+
const bindingSummary = workId || requirementId
|
|
104
|
+
? `; semantic completion binding ${revised.semanticBindingChanged ? 'revised' : 'confirmed'}`
|
|
105
|
+
: '';
|
|
106
|
+
return result({ ...revised, summary: `Supervisor task ${id} objective ${revised.changed ? 'revised' : 'confirmed'} in place${bindingSummary}.` });
|
|
83
107
|
}
|
|
84
108
|
|
|
85
109
|
if (operation === 'stop') {
|
|
@@ -138,7 +162,7 @@ export async function callWorkflowSupervisorAdapter(
|
|
|
138
162
|
// retry/resume budget used to make the task silently leave the delivery
|
|
139
163
|
// queue. The stall state names the exact operator action that can move it.
|
|
140
164
|
const stall = await getWorkflowSupervisorTaskStall(forgeHome, id).catch(() => undefined);
|
|
141
|
-
return result({ task, ...(stall ? { stall } : {}), summary: `Supervisor task ${id} retrieved${stall ? ` (${stall.state})` : ''}.` });
|
|
165
|
+
return result({ task, completionContractSha256: workflowSupervisorCompletionContractSha256(task.completionContract), ...(stall ? { stall } : {}), summary: `Supervisor task ${id} retrieved${stall ? ` (${stall.state})` : ''}; canonical completion-contract CAS fingerprint included.` });
|
|
142
166
|
}
|
|
143
167
|
|
|
144
168
|
if (operation === 'proof') {
|
package/adapters/mcp/server.ts
CHANGED
|
@@ -16,7 +16,7 @@ import { callAccessTool } from './tool-mapping/access-tools';
|
|
|
16
16
|
import { callRepositoryToolWithPostFinalizeAttribution } from './tool-mapping/post-finalize-work-attribution';
|
|
17
17
|
import { callRuntimeTool } from './runtime-gateway/runtime-tools';
|
|
18
18
|
import { callExecutionTool } from './runtime-gateway/execution-tools';
|
|
19
|
-
import { callProcessTool } from './runtime-gateway/process-tools';
|
|
19
|
+
import { callProcessTool, executeAuthorizedHostCommand } from './runtime-gateway/process-tools';
|
|
20
20
|
import { injectDurableCommandFields, isGatewayIsolatedTool, routeDurableMcpCall } from './runtime-gateway/router';
|
|
21
21
|
import { controllerExposureSnapshot, isControllerToolExposed } from './toolset';
|
|
22
22
|
import { settleCognitionAfterTool } from './runtime-gateway/cognition-settlement';
|
|
@@ -507,7 +507,7 @@ export function sameCanonicalRuntimeProxyIdentity(
|
|
|
507
507
|
}
|
|
508
508
|
|
|
509
509
|
export function canonicalRuntimeToolCallIsReplaySafe(name: string, args: Record<string, unknown>): boolean {
|
|
510
|
-
if (name !== '
|
|
510
|
+
if (name !== 'execute_command') return false;
|
|
511
511
|
const workId = typeof args.work_id === 'string' ? args.work_id.trim() : '';
|
|
512
512
|
const requestId = typeof args.request_id === 'string' ? args.request_id.trim() : '';
|
|
513
513
|
return Boolean(workId && requestId);
|
|
@@ -1029,7 +1029,7 @@ export function createForgeMcpServerFromContext(
|
|
|
1029
1029
|
if (isMultiRepositoryContext(ctx)) {
|
|
1030
1030
|
const rpcId = handlerContext.mcpReq.id;
|
|
1031
1031
|
return traceControllerMcpRequest(ctx, name, args, typeof rpcId === 'string' || typeof rpcId === 'number' ? rpcId : undefined, async (requestId, _traceId, phaseTimings) => {
|
|
1032
|
-
// The public Gateway
|
|
1032
|
+
// The public Gateway serves one complete canonical tool schema. It may
|
|
1033
1033
|
// proxy execution, but it never discovers one Runtime schema and
|
|
1034
1034
|
// validates calls against another source checkout.
|
|
1035
1035
|
if (!getRuntimeWriteClaim() && !runtimeSchema && !canonicalRuntimeSchemaMatchesGateway(ctx)) {
|
|
@@ -1060,6 +1060,17 @@ export function createForgeMcpServerFromContext(
|
|
|
1060
1060
|
if (runtimeProxy && observeRuntimeStatus(ctx.controllerHome).ready) return runtimeProxy.callTool(ctx, name, forwardedArgs, phaseTimings);
|
|
1061
1061
|
}
|
|
1062
1062
|
const executeLocalTool = async (): Promise<CallToolResult> => {
|
|
1063
|
+
if (name === 'execute_command' && args.scope === 'host') {
|
|
1064
|
+
if (args.dry_run === true) {
|
|
1065
|
+
return { content: [{ type: 'text', text: 'HOST_COMMAND_PREVIEW_UNSUPPORTED: host command preview requires a separate explicit grant-aware facility' }], structuredContent: { error: { code: 'HOST_COMMAND_PREVIEW_UNSUPPORTED' } }, isError: true };
|
|
1066
|
+
}
|
|
1067
|
+
if (args.repo_id !== undefined || args.checkout_id !== undefined || args.workspace_root !== undefined) {
|
|
1068
|
+
return { content: [{ type: 'text', text: 'COMMAND_SCOPE_CONFLICT: host execution cannot claim repository or workspace targeting' }], structuredContent: { error: { code: 'COMMAND_SCOPE_CONFLICT', message: 'Host execution cannot claim repository or workspace targeting' } }, isError: true };
|
|
1069
|
+
}
|
|
1070
|
+
// One exposed command, two existing authorization targets. The host
|
|
1071
|
+
// lane checks its canonical ForgeInstance process:exec Grant itself.
|
|
1072
|
+
return executeAuthorizedHostCommand(ctx, args);
|
|
1073
|
+
}
|
|
1063
1074
|
const accessResult = callAccessTool(ctx, name, args);
|
|
1064
1075
|
if (accessResult) return accessResult;
|
|
1065
1076
|
const executionResult = await callExecutionTool(ctx, name, args);
|
|
@@ -1076,9 +1087,19 @@ export function createForgeMcpServerFromContext(
|
|
|
1076
1087
|
if (durableResult) return durableResult;
|
|
1077
1088
|
const repositoryResult = await callRepositoryToolWithPostFinalizeAttribution(ctx.controllerHome, name, args, ctx);
|
|
1078
1089
|
if (repositoryResult) return repositoryResult;
|
|
1090
|
+
if (name === 'controller_capabilities') {
|
|
1091
|
+
// Legacy read-only diagnostics consume the authoritative tools/list
|
|
1092
|
+
// snapshot; legacy handlers must not import Runtime registries.
|
|
1093
|
+
return await callMultiRepositoryTool({
|
|
1094
|
+
...ctx,
|
|
1095
|
+
publishedToolNames: controllerExposureSnapshot(ctx).actualToolNames,
|
|
1096
|
+
}, name, args);
|
|
1097
|
+
}
|
|
1079
1098
|
return await callMultiRepositoryTool(ctx, name, args);
|
|
1080
1099
|
};
|
|
1081
1100
|
const localResult = await executeLocalTool();
|
|
1101
|
+
// MCP calls are intermediate. Only the provider-observed final assistant
|
|
1102
|
+
// response can close a Supervisor turn.
|
|
1082
1103
|
return settleCognitionAfterTool(ctx, name, args, localResult) ?? localResult;
|
|
1083
1104
|
});
|
|
1084
1105
|
}
|
package/adapters/mcp/setup.ts
CHANGED
|
@@ -24,8 +24,7 @@ import {
|
|
|
24
24
|
MAX_AGENT_TIMEOUT_MS,
|
|
25
25
|
} from "../../src/cli/controller/runtime-config";
|
|
26
26
|
import { ensureControllerHome, ensureRepoPreferredControllerHome } from "../../src/cli/repositories/controller-home";
|
|
27
|
-
import {
|
|
28
|
-
import { migrateControllerToolsetConfig } from "./toolset-selection";
|
|
27
|
+
import { configuredControllerAccessMode } from './access-mode';
|
|
29
28
|
import { ensureForgeInstanceIdentity, normalizeConfiguredForgeInstanceId, readForgeInstanceIdentity } from "../../packages/kernel/identity/api/index";
|
|
30
29
|
import { discoverExecutable } from "../../src/runtime/platform/executable-discovery";
|
|
31
30
|
|
|
@@ -383,8 +382,6 @@ export function runMcpSetupChatgpt(opts: {
|
|
|
383
382
|
const oauth = ensureMcpControllerHomeOAuthPassphrase(controllerHome);
|
|
384
383
|
if (token.changed) changed.push(token.path);
|
|
385
384
|
if (oauth.changed) changed.push(oauth.path);
|
|
386
|
-
const migratedToolset = migrateControllerToolsetConfig(existingConfig);
|
|
387
|
-
const toolset = migratedToolset.toolset;
|
|
388
385
|
const config = {
|
|
389
386
|
version: Math.max(existingConfig?.version ?? 1, 3),
|
|
390
387
|
identity: { forgeInstanceId: forgeInstance.instanceId },
|
|
@@ -408,10 +405,7 @@ export function runMcpSetupChatgpt(opts: {
|
|
|
408
405
|
localEndpoint: `http://127.0.0.1:${connectorPort}/mcp`,
|
|
409
406
|
},
|
|
410
407
|
profile: existingConfig?.profile ?? "controller",
|
|
411
|
-
|
|
412
|
-
toolsetExplicit: migratedToolset.toolsetExplicit,
|
|
413
|
-
accessMode: existingConfig?.accessMode
|
|
414
|
-
?? accessModeForLegacyToolset(existingConfig?.toolset ?? toolset),
|
|
408
|
+
accessMode: configuredControllerAccessMode(existingConfig),
|
|
415
409
|
accessModeUpdatedAt: existingConfig?.accessModeUpdatedAt,
|
|
416
410
|
accessModeRevision: existingConfig?.accessModeRevision ?? 0,
|
|
417
411
|
localController: opts.userLevel && !existingConfig?.repo
|
|
@@ -470,7 +464,7 @@ export function runMcpSetupChatgpt(opts: {
|
|
|
470
464
|
`[forge mcp] Forge instance: ${forgeInstance.instanceId}`,
|
|
471
465
|
opts.userLevel ? `[forge mcp] Scope: user (${controllerHome})` : `[forge mcp] Repo: ${repoRoot}`,
|
|
472
466
|
"[forge mcp] Profile: controller",
|
|
473
|
-
|
|
467
|
+
'[forge mcp] Tools: complete Forge capability registry',
|
|
474
468
|
`[forge mcp] ChatGPT MCP server name: ${serverName}`,
|
|
475
469
|
`[forge mcp] Internal Runtime endpoint: http://${host}:${port}/mcp`,
|
|
476
470
|
`[forge mcp] ChatGPT local OAuth endpoint: http://127.0.0.1:${connectorPort}/mcp`,
|
|
@@ -686,7 +680,7 @@ export function runMcpDoctor(opts: {
|
|
|
686
680
|
: "not_adopted",
|
|
687
681
|
repo: repoRoot,
|
|
688
682
|
mcp: {
|
|
689
|
-
toolset:
|
|
683
|
+
toolset: 'full',
|
|
690
684
|
localConfig: existsSync(mcpControllerHomeLocalConfigPath(controllerHome)) || existsSync(
|
|
691
685
|
join(repoRoot, ".forge", "mcp.local.json"),
|
|
692
686
|
),
|
|
@@ -167,8 +167,6 @@ function accessStatePayload(
|
|
|
167
167
|
effective = resolveControllerAccessState({
|
|
168
168
|
controllerHome: ctx.controllerHome,
|
|
169
169
|
repoRoot: ctx.explicitRepository?.canonicalRoot,
|
|
170
|
-
toolsetOverride: ctx.toolset,
|
|
171
|
-
toolsetLocked: ctx.toolsetLocked,
|
|
172
170
|
}),
|
|
173
171
|
) {
|
|
174
172
|
const repositoryPolicy = readRepositoryAccessPolicy(ctx.controllerHome, repository.repoId);
|
|
@@ -206,8 +204,6 @@ function previewPayload(
|
|
|
206
204
|
const currentEffective = resolveControllerAccessState({
|
|
207
205
|
controllerHome: ctx.controllerHome,
|
|
208
206
|
repoRoot: ctx.explicitRepository?.canonicalRoot,
|
|
209
|
-
toolsetOverride: ctx.toolset,
|
|
210
|
-
toolsetLocked: ctx.toolsetLocked,
|
|
211
207
|
});
|
|
212
208
|
const currentPolicy = readRepositoryAccessPolicy(ctx.controllerHome, repository.repoId);
|
|
213
209
|
const currentGroups = accessToolGroups(currentEffective.effectiveAccessMode);
|
|
@@ -280,8 +276,6 @@ export function callAccessTool(
|
|
|
280
276
|
const effective = resolveControllerAccessState({
|
|
281
277
|
controllerHome: ctx.controllerHome,
|
|
282
278
|
repoRoot: ctx.explicitRepository?.canonicalRoot,
|
|
283
|
-
toolsetOverride: ctx.toolset,
|
|
284
|
-
toolsetLocked: ctx.toolsetLocked,
|
|
285
279
|
});
|
|
286
280
|
return result({
|
|
287
281
|
...accessStatePayload(ctx, repository, configured, effective),
|