@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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from 'fs';
|
|
2
2
|
import type { McpToolDefinition, CallToolResult } from '../../../packages/protocols/mcp/tool-contract';
|
|
3
3
|
import type { MultiRepositoryMcpToolContext } from '../multi-repository';
|
|
4
|
-
import {
|
|
4
|
+
import { repositoryGitWorkspaceChanges } from '../../../src/cli/repositories/structured-git';
|
|
5
5
|
import { listControllerChecks } from '../../../src/cli/controller/check-runner';
|
|
6
6
|
import { buildWorkContinuationSnapshot } from '../../../src/runtime/control-plane/facade/work-continuation';
|
|
7
7
|
import { currentControllerInstanceId, startExecutionSession, type ExecutionSessionContext } from '../../../src/runtime/control-plane/execution/session-store';
|
|
@@ -12,7 +12,7 @@ import { resumeExecutionJobAfterApproval } from '../../../src/runtime/execution/
|
|
|
12
12
|
import { recordMcpTiming, type McpTimingTrace } from '../../../src/runtime/diagnostics/mcp-timing';
|
|
13
13
|
import { compactHandle, contractFor, identityFor, makeBoundedWorkResult, principalFor, requireSession, workForSession } from '../../../src/runtime/control-plane/execution/work-execution-support';
|
|
14
14
|
import { bindSessionRepository, prepareWork } from '../../../src/runtime/control-plane/execution/work-preparation-service';
|
|
15
|
-
import {
|
|
15
|
+
import { validateWork } from '../../../src/runtime/control-plane/execution/work-operation-service';
|
|
16
16
|
|
|
17
17
|
export { selectDefaultWorkValidationChecks } from '../../../src/runtime/control-plane/execution/work-operation-service';
|
|
18
18
|
|
|
@@ -33,13 +33,9 @@ export const executionToolDefinitions: McpToolDefinition[] = [
|
|
|
33
33
|
isolation: { type: 'string', enum: ['reuse', 'new_worktree', 'auto'] }, base_ref: { type: 'string' }, needs_dependencies: { type: 'boolean' },
|
|
34
34
|
expected_previous_head: { type: 'string', description: 'Explicit prior WorkHandle HEAD required for audited successor adoption of an existing work_id.' },
|
|
35
35
|
adopt_candidate_head: { type: 'string', description: 'Explicit current successor commit to adopt after exact identity, ownership, cleanliness, and ancestry validation.' },
|
|
36
|
+
relocate_to_new_worktree: { type: 'boolean', description: 'Move this existing Work identity to its own managed worktree, with exact previous/candidate HEADs and base_ref. WorkHandle and WorkContract placement commit atomically; the source checkout is not mutated.' },
|
|
36
37
|
}, [], false),
|
|
37
38
|
definition('work_inspect', 'Collect bounded Git, WorkContract, changed-path, check, and readiness evidence through one work handle.', { session_id: sessionId, repo_id: repoId, work_id: workId, detail: { type: 'string', enum: ['summary', 'detail'] } }, ['work_id'], true),
|
|
38
|
-
definition('work_execute', 'Execute approved, repository-scoped commands against a validated work handle while preserving the existing command policy and audit path.', {
|
|
39
|
-
session_id: sessionId, controller_id: { type: 'string', description: 'Controller identity that holds the Work lease. Defaults to the authenticated principal.' }, repo_id: repoId, work_id: workId,
|
|
40
|
-
command: { anyOf: [{ type: 'string' }, { type: 'array', items: { type: 'string' }, minItems: 1 }] }, approval_token: { type: 'string' }, cwd: { type: 'string' }, timeout_ms: { type: 'number' }, max_output_bytes: { type: 'number' },
|
|
41
|
-
commands: { type: 'array', items: { type: 'object' } }, approval_request_id: { type: 'string' },
|
|
42
|
-
}, ['work_id'], false),
|
|
43
39
|
definition('work_validate', 'Run targeted checks or read-only validation commands against a work handle with full current-state validation.', {
|
|
44
40
|
session_id: sessionId, controller_id: { type: 'string', description: 'Controller identity that holds the Work lease. Defaults to the authenticated principal.' }, repo_id: repoId, work_id: workId, check_ids: { type: 'array', items: { type: 'string' } }, commands: { type: 'array', items: { type: 'object' } }, interactive_wait_ms: { type: 'number', description: 'Optional bounded attach window for checks launched by this validation call. Defaults to asynchronous behavior.' },
|
|
45
41
|
}, ['work_id'], false),
|
|
@@ -52,7 +48,6 @@ const executionToolNames = new Set(executionToolDefinitions.map((tool) => tool.n
|
|
|
52
48
|
|
|
53
49
|
/** Repository execution and validation remain Process/WorkHandle operations; semantic Work completion is separate. */
|
|
54
50
|
const DURABLE_WORK_OPERATION_NAMES = new Set([
|
|
55
|
-
'work_execute',
|
|
56
51
|
'work_validate',
|
|
57
52
|
]);
|
|
58
53
|
|
|
@@ -89,8 +84,8 @@ function inspectWork(ctx: MultiRepositoryMcpToolContext, args: Record<string, un
|
|
|
89
84
|
const validationStarted = performance.now();
|
|
90
85
|
const validated = validateWorkHandle(ctx.controllerHome, handle, identityFor(ctx, args), 'cheap', 'inspect');
|
|
91
86
|
const validationMs = performance.now() - validationStarted;
|
|
92
|
-
const
|
|
93
|
-
const
|
|
87
|
+
const candidate = repositoryGitWorkspaceChanges(validated.worktreeRepository);
|
|
88
|
+
const { status, diff } = candidate;
|
|
94
89
|
const contract = contractFor(ctx, handle);
|
|
95
90
|
const checks = contract?.checks ?? [];
|
|
96
91
|
const packageManifest = existsSync(`${validated.worktreeRepository.canonicalRoot}/package.json`)
|
|
@@ -100,7 +95,7 @@ function inspectWork(ctx: MultiRepositoryMcpToolContext, args: Record<string, un
|
|
|
100
95
|
session: { sessionId: session.sessionId, repoId: session.activeRepositoryId, checkoutId: session.activeCheckoutId },
|
|
101
96
|
work: compactHandle(handle),
|
|
102
97
|
readiness: { valid: true, warnings: validated.warnings, permissionSnapshotVersion: handle.permissionSnapshotVersion },
|
|
103
|
-
git: { status, diff: { nameOnly:
|
|
98
|
+
git: { status, diff: { ...diff, staged: { nameOnly: candidate.staged.nameOnly, stat: candidate.staged.stat, truncated: candidate.staged.truncated }, unstaged: { nameOnly: candidate.unstaged.nameOnly, stat: candidate.unstaged.stat, truncated: candidate.unstaged.truncated }, untracked: status.untracked } },
|
|
104
99
|
workContract: contract ? {
|
|
105
100
|
workId: contract.workId,
|
|
106
101
|
state: contract.semanticState,
|
|
@@ -110,7 +105,7 @@ function inspectWork(ctx: MultiRepositoryMcpToolContext, args: Record<string, un
|
|
|
110
105
|
semantics: buildWorkContinuationSnapshot(contract).semantics,
|
|
111
106
|
} : undefined,
|
|
112
107
|
continuation: contract ? buildWorkContinuationSnapshot(contract) : undefined,
|
|
113
|
-
paths: { changed:
|
|
108
|
+
paths: { changed: candidate.changedPaths },
|
|
114
109
|
checks: checks.map((checkId) => ({ checkId, registered: listControllerChecks(validated.worktreeRepository.canonicalRoot).some((check) => check.id === checkId) })),
|
|
115
110
|
package: packageManifest ? { name: packageManifest.name, scripts: packageManifest.scripts } : undefined,
|
|
116
111
|
};
|
|
@@ -131,7 +126,6 @@ export async function callExecutionTool(ctx: MultiRepositoryMcpToolContext, name
|
|
|
131
126
|
case 'session_bind_repository': return result(bindSessionRepository(ctx, args));
|
|
132
127
|
case 'work_prepare': return result(prepareWork(ctx, args));
|
|
133
128
|
case 'work_inspect': return result(inspectWork(ctx, args));
|
|
134
|
-
case 'work_execute': return result(await executeWork(ctx, args));
|
|
135
129
|
case 'work_validate': return result(await validateWork(ctx, args));
|
|
136
130
|
case 'approval_resolve': {
|
|
137
131
|
const session = requireSession(ctx, args);
|
|
@@ -141,15 +141,15 @@ export async function callPluginAdapter(
|
|
|
141
141
|
switch (name) {
|
|
142
142
|
case 'list_plugins': {
|
|
143
143
|
const controllerPlugins = listControllerPluginManifests(ctx.controllerHome, {
|
|
144
|
-
|
|
144
|
+
preferStored: true,
|
|
145
145
|
}).map(summarizePlugin);
|
|
146
146
|
let repositoryPlugins: ReturnType<typeof summarizePlugin>[] = [];
|
|
147
147
|
let repositoryId: string | undefined;
|
|
148
|
-
if (explicitRepositoryContextRequested(args)) {
|
|
148
|
+
if (explicitRepositoryContextRequested(args) || typeof ctx.repoId === 'string' && ctx.repoId.trim()) {
|
|
149
149
|
const repository = selected(ctx, args);
|
|
150
150
|
repositoryId = repository.repoId;
|
|
151
151
|
repositoryPlugins = listAssistantPluginManifests(ctx.controllerHome, repository, {
|
|
152
|
-
|
|
152
|
+
preferStored: true,
|
|
153
153
|
}).map(summarizePlugin);
|
|
154
154
|
}
|
|
155
155
|
return result({
|
|
@@ -316,6 +316,19 @@ export async function callPluginAdapter(
|
|
|
316
316
|
}
|
|
317
317
|
|
|
318
318
|
const submitted = application.submitted;
|
|
319
|
+
if (submitted.receipt.status === 'failed' && submitted.receipt.effectOutcome !== 'outcome_unknown') {
|
|
320
|
+
return result({
|
|
321
|
+
accepted: true,
|
|
322
|
+
deduplicated: submitted.deduplicated,
|
|
323
|
+
scope: pluginScopeLabel(scope),
|
|
324
|
+
plugin: summarizePluginActionReceipt(submitted.manifest),
|
|
325
|
+
action: { actionId: submitted.action.actionId },
|
|
326
|
+
requestId: submitted.receipt.requestId,
|
|
327
|
+
receiptId: submitted.receipt.receiptId,
|
|
328
|
+
effectOutcome: submitted.receipt.effectOutcome ?? 'failed',
|
|
329
|
+
error: submitted.receipt.error ?? { code: 'PLUGIN_ACTION_FAILED', message: 'Plugin action failed.' },
|
|
330
|
+
}, true);
|
|
331
|
+
}
|
|
319
332
|
const compactResult = compactSubmittedPluginActionResult(submitted.result);
|
|
320
333
|
const value = {
|
|
321
334
|
accepted: true,
|
|
@@ -53,27 +53,10 @@ const repoIdProp = {
|
|
|
53
53
|
};
|
|
54
54
|
const processIdProp = {
|
|
55
55
|
type: 'string',
|
|
56
|
-
description: '
|
|
56
|
+
description: 'Process id returned by execute_command or run_check.',
|
|
57
57
|
};
|
|
58
58
|
|
|
59
59
|
export const processToolDefinitions: McpToolDefinition[] = [
|
|
60
|
-
definition(
|
|
61
|
-
'process_exec',
|
|
62
|
-
'Execute one command on the Forge instance itself: cwd is an execution argument and no repository, checkout, or Work is required. Requires an explicit broad `process:exec` canonical Grant for this ForgeInstance; Forge does not parse the command to prove path safety. Returns a process handle; attach with process_get/process_wait/process_logs/process_cancel using the handle only.',
|
|
63
|
-
{
|
|
64
|
-
command: { type: 'array', items: { type: 'string' }, maxItems: 512, description: 'Typed argv command; command[0] is the executable. Mutually exclusive with shell_command.' },
|
|
65
|
-
shell_command: { type: 'string', maxLength: 32_000, description: 'Explicit broad shell form. Mutually exclusive with command. Never parsed for path safety.' },
|
|
66
|
-
cwd: { type: 'string', description: 'Optional absolute working directory. With work_id and no cwd, Forge uses that Work handle\'s exact workspace/worktree as a convenience default; this never grants permission and explicit authorized cwd may be elsewhere.' },
|
|
67
|
-
timeout_ms: { type: 'number' },
|
|
68
|
-
interactive_wait_ms: { type: 'number' },
|
|
69
|
-
max_output_bytes: { type: 'number' },
|
|
70
|
-
request_id: { type: 'string', description: 'Stable invocation id. A retry with the same id attaches to the existing process instead of re-executing.' },
|
|
71
|
-
work_id: { type: 'string', description: 'Optional Work provenance; Work is never required to run a host command.' },
|
|
72
|
-
},
|
|
73
|
-
[],
|
|
74
|
-
false,
|
|
75
|
-
true,
|
|
76
|
-
),
|
|
77
60
|
definition(
|
|
78
61
|
'run_check',
|
|
79
62
|
'Run one focused repository check, or launch one resource-compatible check wave, through Process Runtime. Use check_id for the existing single-check behavior or check_ids for a batch; do not send both. Batch mode validates the existing check-scheduling resource model and starts every check in one compatible wave concurrently without waiting for completion or creating a second scheduler. Cross-wave, invalid, release, and multi-phase batches fail closed. Long ordinary checks return managed handles; attach only at a real dependency boundary.',
|
|
@@ -304,7 +287,6 @@ export async function callProcessTool(
|
|
|
304
287
|
name: string,
|
|
305
288
|
args: Record<string, unknown>,
|
|
306
289
|
): Promise<CallToolResult | undefined> {
|
|
307
|
-
if (name === 'process_exec') return callProcessExecTool(ctx, args);
|
|
308
290
|
// run_check shares this module's public schema, but its execution authority is
|
|
309
291
|
// the Gateway check facade in router.ts. Only attachment/lifecycle operations
|
|
310
292
|
// consume an existing process_id here.
|
|
@@ -383,7 +365,7 @@ export async function callProcessTool(
|
|
|
383
365
|
}
|
|
384
366
|
|
|
385
367
|
/**
|
|
386
|
-
*
|
|
368
|
+
* Host target of the single execute_command entry: canonical process:exec Grant.
|
|
387
369
|
*
|
|
388
370
|
* Repo-less by construction: the Forge instance is the target and `cwd` is an
|
|
389
371
|
* execution argument. Authorization is one explicit canonical `process:exec`
|
|
@@ -406,7 +388,7 @@ function workDefaultCommandCwd(ctx: MultiRepositoryMcpToolContext, workId: strin
|
|
|
406
388
|
return workspace || undefined;
|
|
407
389
|
}
|
|
408
390
|
|
|
409
|
-
async function
|
|
391
|
+
export async function executeAuthorizedHostCommand(
|
|
410
392
|
ctx: MultiRepositoryMcpToolContext,
|
|
411
393
|
args: Record<string, unknown>,
|
|
412
394
|
): Promise<CallToolResult> {
|
|
@@ -48,7 +48,6 @@ function result(value: Record<string, unknown>, isError = false): CallToolResult
|
|
|
48
48
|
|
|
49
49
|
export function getMcpToolDefinition(ctx: MultiRepositoryMcpToolContext, name: string): McpToolDefinition | undefined {
|
|
50
50
|
const currentDefinitions = [...runtimeToolDefinitions, ...executionToolDefinitions, ...processToolDefinitions, ...repositoryToolDefinitions];
|
|
51
|
-
if (ctx.toolset !== 'full') return currentDefinitions.find((tool) => tool.name === name);
|
|
52
51
|
return [...currentDefinitions, ...buildMultiRepositoryToolDefinitions(ctx)].find((tool) => tool.name === name);
|
|
53
52
|
}
|
|
54
53
|
|
|
@@ -212,11 +211,11 @@ export async function routeDurableMcpCall(
|
|
|
212
211
|
}, true);
|
|
213
212
|
}
|
|
214
213
|
|
|
215
|
-
//
|
|
214
|
+
// execute_command has its own durable boundary: non-destructive
|
|
216
215
|
// remote writes run through the durable Process Runtime, while destructive or
|
|
217
216
|
// explicitly delegated commands are refused by the repository facade itself.
|
|
218
217
|
// Do not intercept that tool with the retired ExecutionJob gate here.
|
|
219
|
-
if (classification.path === 'durable' && executionJobCreationRetired() && name !== '
|
|
218
|
+
if (classification.path === 'durable' && executionJobCreationRetired() && name !== 'execute_command') {
|
|
220
219
|
return result({
|
|
221
220
|
accepted: false,
|
|
222
221
|
mode: 'external_controller_required',
|
|
@@ -227,8 +226,7 @@ export async function routeDurableMcpCall(
|
|
|
227
226
|
...(classification.decision ? { decision: classification.decision } : {}),
|
|
228
227
|
},
|
|
229
228
|
rejectCode: 'EXECUTION_JOB_RETIRED',
|
|
230
|
-
message: 'This operation
|
|
231
|
-
suggestedOperation: 'Create or resume semantic Work only when durable context is useful, then use the direct Process/domain capability or rh_work.launcher_start.',
|
|
229
|
+
message: 'This operation needs external Controller or authorized domain capability; Forge does not create Work/Plans or prescribe a workflow to fulfill it.',
|
|
232
230
|
});
|
|
233
231
|
}
|
|
234
232
|
|
|
@@ -7,7 +7,7 @@ import { classifyRepositoryCommandRoute } from '../../../src/runtime/execution/p
|
|
|
7
7
|
import { isProcessIsolatedReadDiagnostic } from '../../../src/runtime/diagnostics/process-facade';
|
|
8
8
|
|
|
9
9
|
/** Pure deterministic MCP Gateway placement policy. No execution or lifecycle mutation belongs here. */
|
|
10
|
-
const DIRECT_REPOSITORY_TOOLS = new Set(['repository_list', 'repository_get', 'repository_workbench'
|
|
10
|
+
const DIRECT_REPOSITORY_TOOLS = new Set(['repository_list', 'repository_get', 'repository_workbench']);
|
|
11
11
|
const DIRECT_CONTROL_WRITE_TOOLS = new Set([
|
|
12
12
|
'runtime_maintenance_apply',
|
|
13
13
|
// Protected credential preparation and physical input own their authorization boundary.
|
|
@@ -21,7 +21,7 @@ const DIRECT_CONTROL_WRITE_TOOLS = new Set([
|
|
|
21
21
|
]);
|
|
22
22
|
|
|
23
23
|
const THIN_ROUTED_TOOLS = new Set([
|
|
24
|
-
'
|
|
24
|
+
'execute_command',
|
|
25
25
|
'repository_safe_patch_apply',
|
|
26
26
|
'repository_safe_patch_plan',
|
|
27
27
|
'capability_execute',
|
|
@@ -128,8 +128,8 @@ const GATEWAY_ROUTE_BEHAVIOR_PROBES: ReadonlyArray<{
|
|
|
128
128
|
}> = [
|
|
129
129
|
{ id: 'hot-read', operation: 'controller_ready', args: {} },
|
|
130
130
|
{ id: 'isolated-read-diagnostic', operation: 'workflow_watchdog_report', args: {} },
|
|
131
|
-
{ id: 'readonly-command', operation: '
|
|
132
|
-
{ id: 'managed-local-command', operation: '
|
|
131
|
+
{ id: 'readonly-command', operation: 'execute_command', args: { command: ['git', 'status', '--short'] } },
|
|
132
|
+
{ id: 'managed-local-command', operation: 'execute_command', args: { command: ['bun', 'run', 'check:type'], timeout_ms: 120_000 } },
|
|
133
133
|
{ id: 'focused-check', operation: 'run_check', args: { check_id: 'package:check:type' } },
|
|
134
134
|
{ id: 'release-check', operation: 'run_check', args: { check_id: 'package:check:release' } },
|
|
135
135
|
{ id: 'interactive-write', operation: 'repository_safe_patch_apply', args: { operations: [] } },
|
|
@@ -311,7 +311,7 @@ export function classifyGatewayExecutionPath(
|
|
|
311
311
|
};
|
|
312
312
|
}
|
|
313
313
|
const selfManagedProcessAsync = (
|
|
314
|
-
name === '
|
|
314
|
+
name === 'execute_command'
|
|
315
315
|
|| name === 'run_check'
|
|
316
316
|
|| name === 'verify_edit_session'
|
|
317
317
|
) && (
|
|
@@ -394,11 +394,18 @@ export function classifyGatewayExecutionPath(
|
|
|
394
394
|
};
|
|
395
395
|
}
|
|
396
396
|
|
|
397
|
-
//
|
|
398
|
-
//
|
|
399
|
-
//
|
|
400
|
-
|
|
401
|
-
|
|
397
|
+
// Host commands are already placed explicitly by the model and authorized
|
|
398
|
+
// by the ForgeInstance process:exec Grant. Never route them through a
|
|
399
|
+
// repository classifier or infer a Work/Plan from the shell command.
|
|
400
|
+
if (name === 'execute_command' && args.scope === 'host') {
|
|
401
|
+
return { path: 'fast', reasons: ['explicit_host_process_runtime'] };
|
|
402
|
+
}
|
|
403
|
+
if (name === 'execute_command' && args.dry_run === true) {
|
|
404
|
+
return { path: 'direct', reasons: ['explicit_command_preview_only'] };
|
|
405
|
+
}
|
|
406
|
+
// Repository commands use the existing Process Runtime classifier only for
|
|
407
|
+
// process handling and mechanical write protection.
|
|
408
|
+
if (name === 'execute_command') {
|
|
402
409
|
const command = args.command;
|
|
403
410
|
if (!(typeof command === 'string' || Array.isArray(command))) {
|
|
404
411
|
return { path: 'reject', reasons: ['repository_command_missing'] };
|
|
@@ -2,7 +2,7 @@ import { existsSync } from 'fs';
|
|
|
2
2
|
import { collectRuntimePerformanceDiagnostics, inferLocalControllerProcess } from '../../../src/runtime/diagnostics/performance';
|
|
3
3
|
import type { McpToolDefinition, CallToolResult } from '../../../packages/protocols/mcp/tool-contract';
|
|
4
4
|
import type { MultiRepositoryMcpToolContext } from '../multi-repository';
|
|
5
|
-
import {
|
|
5
|
+
import { controllerExposureSnapshot, controllerToolSurfaceStatus } from '../toolset';
|
|
6
6
|
import { boundedPluginArtifactImageContent, jsonPreview, result, resultWithPluginArtifactImages } from './result-adapter';
|
|
7
7
|
import { expectedRevision, repositoryRootForRepoId, selected, stringList } from './shared-adapter';
|
|
8
8
|
import { callStatusInboxAdapter, GIT_IDENTITY_SAMPLE_TTL_MS, summarizeInvalidActiveWorkCandidate, summarizeWorkListItem } from './status-inbox-adapter';
|
|
@@ -43,11 +43,12 @@ export const runtimeToolDefinitions: McpToolDefinition[] = [
|
|
|
43
43
|
detail_level: { type: 'string', enum: ['summary', 'detail'] },
|
|
44
44
|
limit: { type: 'number' },
|
|
45
45
|
}),
|
|
46
|
-
definition('rh_context', '
|
|
46
|
+
definition('rh_context', 'Read-only semantic repository retrieval and advisory context, including source snippets, paths, symbols, relationships and optional project knowledge. The model chooses when to retrieve context, when to use terminal search through execute_command, and whether the retrieved evidence is sufficient. This tool does not authorize execution or impose a required workflow.', {
|
|
47
47
|
repo_id: repoId,
|
|
48
48
|
checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple worktrees.' },
|
|
49
|
-
operation: { type: 'string', enum: ['list', 'get', 'search'], description: 'Defaults to get.
|
|
49
|
+
operation: { type: 'string', enum: ['list', 'get', 'search'], description: 'Defaults to get. Search returns semantic source candidates when the model selects this retrieval capability.' },
|
|
50
50
|
query: { type: 'string', description: 'Code/content intent for operation=search. For operation=list, a natural-language capability intent such as "configure Xcode provisioning" returns ranked read-only capability candidates while execution remains on the capability\'s typed executor. Frozen-schema clients may append @tsnav or @swiftnav references|definition|implementations <repo-path>:<line>:<column> for compiler/LSP-backed semantic navigation.' },
|
|
51
|
+
search_terms: { type: 'array', maxItems: 8, items: { type: 'string', maxLength: 160 }, description: 'Optional model-selected literal code-search terms, ordered by likely relevance. Preserve query as the original user intent; for non-English or descriptive questions about source written in another language, infer repository-language identifiers/phrases (such as the relevant function name, file symbol, or operation keyword) and supply them here. Forge uses bounded lexical ripgrep matching, not automatic translation or semantic embeddings. Refine terms or known_paths when initial candidates are insufficient.' },
|
|
51
52
|
include_learning_recall: { type: 'boolean', description: 'Defaults to true for semantic task/capability queries. Set false for routine progressive source follow-ups or micro-steps when the already recalled working set is still valid. This is a model-owned attention/cadence choice, not a Forge semantic trigger.' },
|
|
52
53
|
knowledge_query: { type: 'string', description: 'Optional explicit read-only Cognitive audit query. Ordinary code/capability intent queries already receive a bounded relevant-learning recall; use this field for deliberate memory inspection. May be used without code query. Use "*" or omit text with filters to list learned advisory memory in scopes reachable from this repo/Work.' },
|
|
53
54
|
knowledge_memory_id: { type: 'string', description: 'Optional exact Cognitive memory id for inspection.' },
|
|
@@ -63,7 +64,7 @@ export const runtimeToolDefinitions: McpToolDefinition[] = [
|
|
|
63
64
|
exclude_globs: { type: 'array', items: { type: 'string' } },
|
|
64
65
|
retrieval_mode: { type: 'string', enum: ['implementation', 'plan', 'debug', 'review'], description: 'Defaults to implementation. Implementation returns current raw impact evidence for ChatGPT to judge; plan/debug/review intentionally widen evidence.' },
|
|
65
66
|
impact_domains: { type: 'array', items: { type: 'string', enum: [...CONTROLLER_CONTEXT_IMPACT_DOMAINS] }, description: 'Optional GPT-selected cross-cutting evidence dimensions. Forge expands these mechanically in the same retrieval call; it never treats them as proof of semantic completeness.' },
|
|
66
|
-
structural_context: { type: 'string', enum: ['off', 'auto', 'required'], description: 'Optional override. Defaults to
|
|
67
|
+
structural_context: { type: 'string', enum: ['off', 'auto', 'required'], description: 'Optional override. Defaults to off for all modes; explicitly opt in only for structural investigations.' },
|
|
67
68
|
semantic_navigation: {
|
|
68
69
|
type: 'array',
|
|
69
70
|
maxItems: 8,
|
|
@@ -292,13 +293,13 @@ export const runtimeToolDefinitions: McpToolDefinition[] = [
|
|
|
292
293
|
min_age_minutes: { type: 'number' },
|
|
293
294
|
max_candidates: { type: 'number' },
|
|
294
295
|
}, ['action_id'], false),
|
|
295
|
-
definition('runtime_maintenance_status', 'Read the self-contained runtime maintenance plan without
|
|
296
|
+
definition('runtime_maintenance_status', 'Read the self-contained runtime maintenance plan without invoking execute_command or creating Local Job tickets.', {
|
|
296
297
|
repo_id: repoId,
|
|
297
298
|
min_age_minutes: { type: 'number' },
|
|
298
299
|
max_candidates: { type: 'number' },
|
|
299
300
|
cancel_pending_approvals: { type: 'boolean' },
|
|
300
301
|
}),
|
|
301
|
-
definition('runtime_maintenance_apply', 'Apply one bounded runtime maintenance action without
|
|
302
|
+
definition('runtime_maintenance_apply', 'Apply one bounded runtime maintenance action without invoking execute_command or creating Local Job tickets.', {
|
|
302
303
|
repo_id: repoId,
|
|
303
304
|
action_id: { type: 'string', enum: ['local_jobs_reconcile', 'quarantine_unreadable_local_jobs', 'runtime_storage_finalize_relocation', 'rebuild_projection', 'full_maintenance_pass'] },
|
|
304
305
|
confirm_maintenance: { type: 'boolean' },
|
|
@@ -355,7 +356,7 @@ export const runtimeToolDefinitions: McpToolDefinition[] = [
|
|
|
355
356
|
max_candidates: { type: 'number' },
|
|
356
357
|
confirm_repair: { type: 'boolean' },
|
|
357
358
|
}, ['confirm_repair'], false),
|
|
358
|
-
definition('list_plugins', 'List
|
|
359
|
+
definition('list_plugins', 'List controller plugins and the selected repository plugins. When repo_id is omitted, the current repository context is included automatically; with multiple repositories, provide repo_id. Uses registered manifest snapshots with last-observed capability health; action execution independently validates provider identity and readiness.', {
|
|
359
360
|
repo_id: repoId,
|
|
360
361
|
}),
|
|
361
362
|
definition('get_plugin', 'Read one repository or controller-scoped plugin manifest including action schemas and policy requirements.', {
|
|
@@ -453,8 +454,11 @@ export const runtimeToolDefinitions: McpToolDefinition[] = [
|
|
|
453
454
|
recent_safe_error: { type: 'string' },
|
|
454
455
|
model: { type: 'string' },
|
|
455
456
|
}),
|
|
456
|
-
definition('supervisor_task', 'Start, list, inspect, revise, recover, stop, or prove standalone Workflow Supervisor autonomous tasks. Supervisor task/effect state is the continuation authority; Requirement, Plan, and Work are
|
|
457
|
-
repo_id: { ...repoId, description: 'Optional repository provenance for start/proof; never Work authority.' },
|
|
457
|
+
definition('supervisor_task', 'Start, list, inspect, revise, recover, stop, or prove standalone Workflow Supervisor autonomous tasks. Supervisor task/effect state is the continuation authority; Requirement, Plan, and Work are not created by this tool. A standalone task may bind to one existing Work or Requirement for semantic DONE proof; omitting both keeps the unbound standalone contract.', {
|
|
458
|
+
repo_id: { ...repoId, description: 'Optional repository provenance for start/proof; a repository scope must be available with work_id or requirement_id. Repository identity alone is never Work authority.' },
|
|
459
|
+
work_id: { type: 'string', minLength: 1, maxLength: 256, description: 'For start, bind the task to this exact Work; for revise, one-way bind an existing unbound task using expected_completion_contract_sha256.' },
|
|
460
|
+
requirement_id: { type: 'string', minLength: 1, maxLength: 256, description: 'For start, bind the task to this exact Requirement; for revise, one-way bind an existing unbound task using expected_completion_contract_sha256. Mutually exclusive with work_id.' },
|
|
461
|
+
expected_completion_contract_sha256: { type: 'string', description: 'For revise with work_id or requirement_id, CAS fingerprint returned by supervisor_task get as completionContractSha256.' },
|
|
458
462
|
operation: { type: 'string', enum: ['start', 'list', 'get', 'revise', 'recover', 'stop', 'proof'] },
|
|
459
463
|
task_id: { type: 'string' },
|
|
460
464
|
objective: { type: 'string', description: 'Outcome objective for start/revise; revise never changes task or conversation identity.' },
|
|
@@ -463,7 +467,8 @@ export const runtimeToolDefinitions: McpToolDefinition[] = [
|
|
|
463
467
|
source_effect_id: { type: 'string', description: 'Optional exact source effect for operator recovery fencing.' },
|
|
464
468
|
supersede_unknown: { type: 'boolean', description: 'For recover only: explicitly retire one outcome-unknown effect instead of replaying it.' },
|
|
465
469
|
authorized_by: { type: 'string', description: 'Optional operator identity recorded by canonical recovery authority.' },
|
|
466
|
-
active_only: { type: 'boolean', description: 'For list, defaults true; exclude terminal tasks.' },
|
|
470
|
+
active_only: { type: 'boolean', description: 'For list, defaults true; exclude terminal tasks. Set false for legacy all-task listing.' },
|
|
471
|
+
terminal_only: { type: 'boolean', description: 'For list, return only canonically terminal DONE/NEEDS_USER/STOPPED task history with exact task and terminal status; does not archive ChatGPT conversations.' },
|
|
467
472
|
request_id: { type: 'string', description: 'Stable idempotency identity for start/revise/recover.' },
|
|
468
473
|
active_release_id: { type: 'string', description: 'Active Runtime release expected in proof dispatch evidence.' },
|
|
469
474
|
not_before: { type: 'string', description: 'ISO-8601 lower bound for proof completions.' },
|
|
@@ -22,7 +22,6 @@ export {
|
|
|
22
22
|
runtimeToolDefinitions,
|
|
23
23
|
} from './runtime-tool-definitions';
|
|
24
24
|
import { callWorkAdapter, runFacadeRepair } from './work-adapter';
|
|
25
|
-
import { automationMetadata, persistAutomationReceipt } from './automation-receipt-adapter';
|
|
26
25
|
|
|
27
26
|
async function callRuntimeToolUnchecked(ctx: MultiRepositoryMcpToolContext, name: string, args: Record<string, unknown>): Promise<CallToolResult | undefined> {
|
|
28
27
|
try {
|
|
@@ -68,10 +67,7 @@ async function callRuntimeToolUnchecked(ctx: MultiRepositoryMcpToolContext, name
|
|
|
68
67
|
}
|
|
69
68
|
|
|
70
69
|
export async function callRuntimeTool(ctx: MultiRepositoryMcpToolContext, name: string, args: Record<string, unknown>): Promise<CallToolResult | undefined> {
|
|
71
|
-
|
|
72
|
-
const outcome = await callRuntimeToolUnchecked(ctx, name, args);
|
|
73
|
-
await persistAutomationReceipt(ctx, name, metadata, outcome);
|
|
74
|
-
return outcome;
|
|
70
|
+
return callRuntimeToolUnchecked(ctx, name, args);
|
|
75
71
|
}
|
|
76
72
|
|
|
77
73
|
export { runtimeIdentitySnapshot, dispatchedChatgptRelayAuthorizesStaleControllerRecovery, sessionlessFacadeControllerAuthorityMatches } from './controller-authority-adapter';
|
|
@@ -3,6 +3,7 @@ import type { MultiRepositoryMcpToolContext } from '../multi-repository';
|
|
|
3
3
|
import { applyScheduleDedupe, buildScheduleDedupeReport, deleteSchedule } from '../../../packages/kernel/scheduler/api/index';
|
|
4
4
|
import { buildFacadeResult } from '../../../src/runtime/control-plane/facade/facade-result';
|
|
5
5
|
import { buildWorkContinuationSnapshot } from '../../../src/runtime/control-plane/facade/work-continuation';
|
|
6
|
+
import { bindWorkflowSupervisorScheduledWakeForWork } from '../../../src/runtime/root/workflow-supervisor-composition';
|
|
6
7
|
import {
|
|
7
8
|
createWorkContinuationSchedule,
|
|
8
9
|
getWorkContinuationSchedule,
|
|
@@ -34,6 +35,34 @@ const RH_WORK_SCHEDULE_OPERATIONS = new Set<RhWorkScheduleOperation>([
|
|
|
34
35
|
'schedule_trigger',
|
|
35
36
|
]);
|
|
36
37
|
|
|
38
|
+
async function bindSupervisorWakeForSchedule(
|
|
39
|
+
ctx: MultiRepositoryMcpToolContext,
|
|
40
|
+
repoId: string,
|
|
41
|
+
schedule: { scheduleId: string; action: { operation: string; arguments?: Record<string, unknown> } },
|
|
42
|
+
): Promise<{ status: 'bound' | 'not_enrolled' | 'binding_deferred'; taskId?: string } | undefined> {
|
|
43
|
+
if (schedule.action.operation !== 'controller_progression' || schedule.action.arguments?.controller_type !== 'chatgpt') {
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
const workId = typeof schedule.action.arguments.work_id === 'string' ? schedule.action.arguments.work_id.trim() : '';
|
|
47
|
+
if (!workId) throw new Error('SCHEDULE_SUPERVISOR_WAKE_WORK_ID_REQUIRED');
|
|
48
|
+
try {
|
|
49
|
+
return await bindWorkflowSupervisorScheduledWakeForWork(
|
|
50
|
+
{ controllerHome: ctx.controllerHome, repoId },
|
|
51
|
+
workId,
|
|
52
|
+
schedule.scheduleId,
|
|
53
|
+
);
|
|
54
|
+
} catch (error) {
|
|
55
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
56
|
+
let pauseFailure = '';
|
|
57
|
+
try {
|
|
58
|
+
pauseWorkContinuationSchedule(ctx.controllerHome, repoId, schedule.scheduleId, `Supervisor scheduled-wake binding failed: ${reason}`);
|
|
59
|
+
} catch (pauseError) {
|
|
60
|
+
pauseFailure = `; schedule pause also failed: ${pauseError instanceof Error ? pauseError.message : String(pauseError)}`;
|
|
61
|
+
}
|
|
62
|
+
throw new Error(`SCHEDULE_SUPERVISOR_WAKE_BINDING_FAILED:${reason}${pauseFailure}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
37
66
|
export function isRhWorkScheduleOperation(operation: string): operation is RhWorkScheduleOperation {
|
|
38
67
|
return RH_WORK_SCHEDULE_OPERATIONS.has(operation as RhWorkScheduleOperation);
|
|
39
68
|
}
|
|
@@ -105,6 +134,7 @@ export async function callRhWorkScheduleAdapter(
|
|
|
105
134
|
backoffMaxMinutes: typeof args.backoff_max_minutes === 'number' ? args.backoff_max_minutes : undefined,
|
|
106
135
|
stopConditions: Array.isArray(args.stop_conditions) ? args.stop_conditions.map(String) : undefined,
|
|
107
136
|
});
|
|
137
|
+
const supervisorWakeBinding = await bindSupervisorWakeForSchedule(ctx, repository.repoId, created.schedule);
|
|
108
138
|
return result(buildFacadeResult({
|
|
109
139
|
summary: created.work
|
|
110
140
|
? `Work schedule ${created.schedule.scheduleId} is configured for Work ${created.work.workId}.`
|
|
@@ -112,6 +142,7 @@ export async function callRhWorkScheduleAdapter(
|
|
|
112
142
|
data: {
|
|
113
143
|
schedule: created.schedule,
|
|
114
144
|
...(created.work ? { work: buildWorkContinuationSnapshot(created.work) } : {}),
|
|
145
|
+
...(supervisorWakeBinding ? { supervisorWakeBinding } : {}),
|
|
115
146
|
},
|
|
116
147
|
}) as unknown as Record<string, unknown>);
|
|
117
148
|
}
|
|
@@ -134,7 +165,11 @@ export async function callRhWorkScheduleAdapter(
|
|
|
134
165
|
}
|
|
135
166
|
if (operation === 'schedule_resume') {
|
|
136
167
|
const saved = resumeWorkContinuationSchedule(ctx.controllerHome, repository.repoId, scheduleId);
|
|
137
|
-
|
|
168
|
+
const supervisorWakeBinding = await bindSupervisorWakeForSchedule(ctx, repository.repoId, saved);
|
|
169
|
+
return result(buildFacadeResult({
|
|
170
|
+
summary: `Schedule ${scheduleId} is resumed.`,
|
|
171
|
+
data: { schedule: saved, ...(supervisorWakeBinding ? { supervisorWakeBinding } : {}) },
|
|
172
|
+
}) as unknown as Record<string, unknown>);
|
|
138
173
|
}
|
|
139
174
|
if (operation === 'schedule_delete') {
|
|
140
175
|
const schedule = getWorkContinuationSchedule(ctx.controllerHome, repository.repoId, scheduleId).schedule;
|
|
@@ -2,7 +2,7 @@ import { existsSync } from "fs";
|
|
|
2
2
|
import { join } from "path";
|
|
3
3
|
import { runProcess } from '../../../src/effects/process-runner';
|
|
4
4
|
import type { MultiRepositoryMcpToolContext } from "../multi-repository";
|
|
5
|
-
import {
|
|
5
|
+
import { controllerExposureSnapshot, controllerToolSurfaceStatus } from "../toolset";
|
|
6
6
|
import { result } from "./result-adapter";
|
|
7
7
|
import { selected, selectedOptional } from "./shared-adapter";
|
|
8
8
|
import { SEMANTIC_SCOPE_KEY } from "../../../src/cli/repositories/controller-home";
|
|
@@ -16,7 +16,8 @@ import { cachedGitIdentity, gitSnapshot } from "../../../src/cli/repository/insp
|
|
|
16
16
|
import { buildRuntimeMaintenanceStatus } from "../../../src/runtime/recovery";
|
|
17
17
|
import { allowedFacadeOperations, buildFacadeResult, listCapabilityDescriptors, summarizeCapabilityGroups, listHandoffAttentionItems, normalizeCheckIds, buildWorkContinuationSnapshot, listPlanContracts, summarizePlanContract, runHandoffInboxApplication, type FacadeTool } from "../../../src/runtime/control-plane/facade";
|
|
18
18
|
import { buildJobOperationDigest } from '../../../src/runtime/control-plane/facade/operation-digest';
|
|
19
|
-
import { readActiveWorkCandidates, type InvalidActiveWorkCandidate } from "../../../packages/kernel/work/api/index";
|
|
19
|
+
import { getWorkContract, readActiveWorkCandidates, semanticWorkState, type InvalidActiveWorkCandidate } from "../../../packages/kernel/work/api/index";
|
|
20
|
+
import { listWorkHandles } from '../../../src/runtime/control-plane/execution/work-handle-store';
|
|
20
21
|
import { observeRuntimeStatus } from "../../../src/runtime/root/status";
|
|
21
22
|
import { getControllerSession } from "../../../packages/kernel/controller/api/index";
|
|
22
23
|
import { listActiveOccurrences, listSchedules, scheduleOwnsWork } from "../../../packages/kernel/scheduler/api/index";
|
|
@@ -447,6 +448,7 @@ export async function callStatusInboxAdapter(
|
|
|
447
448
|
detailTimingMark = now;
|
|
448
449
|
};
|
|
449
450
|
const readiness = await controllerReadinessEvidence(ctx, repository);
|
|
451
|
+
const runtimeObservation = observeRuntimeStatus(ctx.controllerHome);
|
|
450
452
|
markDetailPhase('readiness');
|
|
451
453
|
const liveGit = gitSnapshot(repository.canonicalRoot);
|
|
452
454
|
markDetailPhase('git');
|
|
@@ -455,7 +457,7 @@ export async function callStatusInboxAdapter(
|
|
|
455
457
|
const runtimeSource = runtimeSourceSnapshotStatus(readiness.daemon.source, ctx.runtimeSourceRoot);
|
|
456
458
|
const sourceSnapshotStale = runtimeSource.restartRequired;
|
|
457
459
|
const exposure = controllerExposureSnapshot(ctx);
|
|
458
|
-
const localRegisteredToolNames =
|
|
460
|
+
const localRegisteredToolNames = [...exposure.actualToolNames].sort();
|
|
459
461
|
markDetailPhase('tool_surface');
|
|
460
462
|
const toolSurfaceReady = exposure.ready && exposure.missingToolNames.length === 0;
|
|
461
463
|
// Ordinary interactive execution depends on the execution axis only.
|
|
@@ -582,7 +584,7 @@ export async function callStatusInboxAdapter(
|
|
|
582
584
|
)],
|
|
583
585
|
diagnostics: {
|
|
584
586
|
runtime: {
|
|
585
|
-
ready:
|
|
587
|
+
ready: runtimeObservation.ready,
|
|
586
588
|
},
|
|
587
589
|
toolSurface: {
|
|
588
590
|
ready: toolSurfaceReady,
|
|
@@ -644,6 +646,39 @@ export async function callStatusInboxAdapter(
|
|
|
644
646
|
const pendingHandoffCount = pendingHandoffAttention.length;
|
|
645
647
|
const activeWorkProjection = readActiveWorkCandidates({ ...store, limit: 200 });
|
|
646
648
|
const activeContracts = activeWorkProjection.contracts;
|
|
649
|
+
// Reuse the exact WorkHandle and semantic Work authorities consulted by
|
|
650
|
+
// delivery. This is a read-only diagnosis, never a delivery admission gate.
|
|
651
|
+
const receivingOwners = detailLevel === 'detail'
|
|
652
|
+
? listWorkHandles(ctx.controllerHome, repository.repoId)
|
|
653
|
+
.filter((handle) => {
|
|
654
|
+
if (handle.checkoutId !== repository.activeCheckoutId
|
|
655
|
+
|| handle.branch !== liveGit.branch
|
|
656
|
+
|| handle.state === 'cleaned' || handle.state === 'failed') return false;
|
|
657
|
+
const contract = getWorkContract(store, handle.workContractId ?? handle.workId);
|
|
658
|
+
return Boolean(contract && semanticWorkState(contract) === 'open');
|
|
659
|
+
})
|
|
660
|
+
.sort((left, right) => left.workId.localeCompare(right.workId))
|
|
661
|
+
: [];
|
|
662
|
+
const headDriftedOwners = receivingOwners.filter((handle) =>
|
|
663
|
+
Boolean(handle.expectedHead && handle.expectedHead !== liveGit.head));
|
|
664
|
+
const repositoryDeliveryBlockers = [
|
|
665
|
+
...(receivingOwners.length > 1 ? ['WORK_CANONICAL_MUTATION_OWNERSHIP_AMBIGUOUS']
|
|
666
|
+
: receivingOwners.length ? ['WORK_DELIVERY_TARGET_WORK_ACTIVE'] : []),
|
|
667
|
+
...(headDriftedOwners.length ? ['WORK_HANDLE_HEAD_CHANGED'] : []),
|
|
668
|
+
...(liveGit.dirty ? ['WORK_DELIVERY_TARGET_DIRTY'] : []),
|
|
669
|
+
];
|
|
670
|
+
const repositoryDeliveryNextSafeAction =
|
|
671
|
+
receivingOwners.length > 1
|
|
672
|
+
? 'Multiple open WorkHandles claim this checkout. Resolve canonical ownership before any Git mutation; do not guess or bypass a writer.'
|
|
673
|
+
: headDriftedOwners.length && liveGit.dirty
|
|
674
|
+
? 'Owning Work: review the uncommitted paths against successor commits, converge its edits, then use explicit work_prepare successor adoption only if ancestry and path disjointness are proven.'
|
|
675
|
+
: headDriftedOwners.length
|
|
676
|
+
? 'Owning Work: verify exact HEAD ancestry and use work_prepare with expected_previous_head/adopt_candidate_head; never silently rebase or reset.'
|
|
677
|
+
: liveGit.dirty
|
|
678
|
+
? 'Owning writer: review and verify the existing dirty paths, then commit through its authorized Work before integrating another candidate; never auto-stash or reset.'
|
|
679
|
+
: receivingOwners.length
|
|
680
|
+
? 'The receiving Work owns this checkout. Integrate reviewed source commits using its own authorized Git path, then reconcile each source Work through canonical deliver_work.'
|
|
681
|
+
: 'For a validated source Work, use canonical repository.git.deliver_work; this read-only projection does not check live mutation leases or grant integration authority.';
|
|
647
682
|
markDetailPhase('work_state');
|
|
648
683
|
const activePrimaryWork = activeContracts.filter((contract) => (contract.lifecycleRole ?? 'primary') === 'primary');
|
|
649
684
|
const activeExecutionChildren = activeContracts.filter((contract) => contract.lifecycleRole === 'execution_child');
|
|
@@ -743,6 +778,25 @@ export async function callStatusInboxAdapter(
|
|
|
743
778
|
primaryWorkActivityCounts,
|
|
744
779
|
primaryWorkActivities,
|
|
745
780
|
activeContractCount: activeContracts.length,
|
|
781
|
+
...(detailLevel === 'detail' ? { repositoryDelivery: {
|
|
782
|
+
observation: 'work_handle_and_git_snapshot' as const,
|
|
783
|
+
diagnosticOnly: true,
|
|
784
|
+
checkoutId: repository.activeCheckoutId,
|
|
785
|
+
branch: liveGit.branch,
|
|
786
|
+
head: liveGit.head,
|
|
787
|
+
dirty: liveGit.dirty,
|
|
788
|
+
ownerCount: receivingOwners.length,
|
|
789
|
+
ownersTruncated: receivingOwners.length > 5,
|
|
790
|
+
owners: receivingOwners.slice(0, 5).map((handle) => ({
|
|
791
|
+
workId: handle.workId,
|
|
792
|
+
state: handle.state,
|
|
793
|
+
expectedHead: handle.expectedHead ?? null,
|
|
794
|
+
headDrift: Boolean(handle.expectedHead && handle.expectedHead !== liveGit.head),
|
|
795
|
+
})),
|
|
796
|
+
blockers: repositoryDeliveryBlockers,
|
|
797
|
+
nextSafeAction: repositoryDeliveryNextSafeAction,
|
|
798
|
+
limitations: 'Live leases, source validation, conflict preview and target CAS remain canonical delivery-time checks.',
|
|
799
|
+
} } : {}),
|
|
746
800
|
invalidActiveContractCount: activeWorkProjection.invalid.length,
|
|
747
801
|
invalidActiveContracts: activeWorkProjection.invalid.slice(0, 10).map(summarizeInvalidActiveWorkCandidate),
|
|
748
802
|
// Summary keeps the stable facade surface only; detail expands to the full registered schema.
|
|
@@ -10,9 +10,10 @@ import {
|
|
|
10
10
|
navigateTypeScriptSymbol,
|
|
11
11
|
type TypeScriptNavigationRequest,
|
|
12
12
|
} from '../../../src/runtime/context/typescript-navigation';
|
|
13
|
-
import
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
import {
|
|
14
|
+
isIncidentalSemanticDependencyProbe,
|
|
15
|
+
type SemanticNavigationOutcome,
|
|
16
|
+
type SemanticNavigationReadPolicy,
|
|
16
17
|
} from '../../../src/runtime/context/semantic-navigation-contract';
|
|
17
18
|
|
|
18
19
|
interface Envelope {
|
|
@@ -83,6 +84,7 @@ export function runTypeScriptNavigationSidecar(
|
|
|
83
84
|
try {
|
|
84
85
|
for (const request of envelope.requests) {
|
|
85
86
|
let policyDeniedReads = 0;
|
|
87
|
+
let materialPolicyDeniedReads = 0;
|
|
86
88
|
const policyDeniedReadSamples = new Set<string>();
|
|
87
89
|
try {
|
|
88
90
|
const result = navigateTypeScriptSymbol(repoRoot, request, {
|
|
@@ -92,6 +94,7 @@ export function runTypeScriptNavigationSidecar(
|
|
|
92
94
|
const decision = resolveMcpPath(repoRoot, relativePath, policy, 'read');
|
|
93
95
|
if (decision.ok) return true;
|
|
94
96
|
policyDeniedReads += 1;
|
|
97
|
+
if (!isIncidentalSemanticDependencyProbe(relativePath)) materialPolicyDeniedReads += 1;
|
|
95
98
|
if (policyDeniedReadSamples.size < 20) policyDeniedReadSamples.add(relativePath);
|
|
96
99
|
return false;
|
|
97
100
|
},
|
|
@@ -105,6 +108,7 @@ export function runTypeScriptNavigationSidecar(
|
|
|
105
108
|
target: result.target,
|
|
106
109
|
locations: result.locations,
|
|
107
110
|
policyDeniedReads,
|
|
111
|
+
materialPolicyDeniedReads,
|
|
108
112
|
...(policyDeniedReadSamples.size > 0 ? {
|
|
109
113
|
details: { policyDeniedReadSamples: [...policyDeniedReadSamples] },
|
|
110
114
|
} : {}),
|