@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
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Install the one Controller-owned physical-iPhone HID Python toolchain.
|
|
3
|
+
# Execute only with an authorized ForgeInstance host process:exec grant.
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
|
|
6
|
+
if [[ $# -ne 1 || ! -d "$1" ]]; then
|
|
7
|
+
echo "Usage: $0 <existing-controller-home>" >&2
|
|
8
|
+
exit 2
|
|
9
|
+
fi
|
|
10
|
+
if [[ "$(uname -s)" != "Darwin" ]]; then
|
|
11
|
+
echo "The CoreDevice HID toolchain requires macOS." >&2
|
|
12
|
+
exit 2
|
|
13
|
+
fi
|
|
14
|
+
|
|
15
|
+
repo_root="$(cd "$(dirname "$0")/.." && pwd -P)"
|
|
16
|
+
controller_home="$(cd "$1" && pwd -P)"
|
|
17
|
+
version="11.24.0"
|
|
18
|
+
# The provider source is the sole runtime version authority. Refuse a stale installer.
|
|
19
|
+
if ! grep -Fq "export const IOS_HID_TOOLCHAIN_VERSION = '$version';" \
|
|
20
|
+
"$repo_root/src/runtime/plugins/ios/remote-xpc-hid.ts"; then
|
|
21
|
+
echo "Installer version no longer matches the RemoteXPC provider pin." >&2
|
|
22
|
+
exit 2
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
toolchains="$controller_home/toolchains"
|
|
26
|
+
mkdir -p "$toolchains"
|
|
27
|
+
target="$toolchains/pymobiledevice3-$version"
|
|
28
|
+
lock="$toolchains/.pymobiledevice3-$version-install.lock"
|
|
29
|
+
if ! mkdir "$lock" 2>/dev/null; then
|
|
30
|
+
echo "The pinned HID toolchain is already being installed; no parallel writer." >&2
|
|
31
|
+
exit 1
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
created=false
|
|
35
|
+
completed=false
|
|
36
|
+
cleanup() {
|
|
37
|
+
if [[ "$created" == true && "$completed" != true ]]; then
|
|
38
|
+
rm -rf -- "$target"
|
|
39
|
+
fi
|
|
40
|
+
rmdir "$lock" 2>/dev/null || true
|
|
41
|
+
}
|
|
42
|
+
trap cleanup EXIT
|
|
43
|
+
|
|
44
|
+
verify() {
|
|
45
|
+
"$1" -c "from importlib.metadata import version; from pymobiledevice3.remote.remote_service_discovery import RemoteServiceDiscoveryService; from pymobiledevice3.remote.core_device.pasteboard_service import PasteboardService; from pymobiledevice3.remote.core_device.hid_service import UniversalHIDServiceService, touch_session; actual=version('pymobiledevice3'); assert actual == '$version', (actual, '$version'); print('pymobiledevice3 ' + actual + ' verified')"
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if [[ -e "$target" ]]; then
|
|
49
|
+
verify "$target/bin/python"
|
|
50
|
+
completed=true
|
|
51
|
+
exit 0
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
# A newly created target is owned by this invocation. Never alter an old toolchain.
|
|
55
|
+
created=true
|
|
56
|
+
python3 -m venv "$target"
|
|
57
|
+
"$target/bin/python" -m pip install --disable-pip-version-check --no-input "pymobiledevice3==$version"
|
|
58
|
+
verify "$target/bin/python"
|
|
59
|
+
completed=true
|
|
60
|
+
printf 'Installed Controller-owned HID toolchain: %s\n' "$target"
|
|
@@ -2,7 +2,7 @@ import { createHash } from 'crypto';
|
|
|
2
2
|
import { isAbsolute, join, resolve } from 'path';
|
|
3
3
|
import { hostname } from 'os';
|
|
4
4
|
import { systemdUserUnitName } from '../src/cli/controller/systemd-user';
|
|
5
|
-
import { openAiSecureTunnelConnectArgs } from '../
|
|
5
|
+
import { openAiSecureTunnelConnectArgs } from '../adapters/mcp/tunnels/openai-secure-tunnel';
|
|
6
6
|
import type { OpenAiSecureTunnelServiceConfig, PrimaryConnectorServiceConfig, PublicTunnelServiceConfig, RecoveryTunnelServiceConfig } from '../src/runtime/standalone-recovery/core';
|
|
7
7
|
import { installStandaloneRecovery } from '../src/runtime/standalone-recovery/installer';
|
|
8
8
|
|
|
@@ -1029,7 +1029,7 @@ pi_install_helpers() {
|
|
|
1029
1029
|
local target_dir="$1"
|
|
1030
1030
|
local helpers_dir="$2"
|
|
1031
1031
|
local mode="${3:-apply}"
|
|
1032
|
-
local helper_names="${4:-new-spec.sh new-sprint.sh new-plan.sh capture-plan.sh plan-to-todo.sh contract-run.ts contract-worktree.sh ship-worktrees.sh archive-workflow.sh refresh-current-status.sh prepare-handoff.sh verify-contract.sh summarize-failures.sh verify-sprint.sh sprint-backlog.sh check-task-sync.sh check-deploy-sql-order.sh check-architecture-sync.sh check-agent-tooling.sh check-context-files.sh check-brain-manifest.sh sync-brain-docs.sh
|
|
1032
|
+
local helper_names="${4:-new-spec.sh new-sprint.sh new-plan.sh capture-plan.sh plan-to-todo.sh contract-run.ts contract-worktree.sh ship-worktrees.sh archive-workflow.sh refresh-current-status.sh prepare-handoff.sh verify-contract.sh summarize-failures.sh verify-sprint.sh sprint-backlog.sh check-task-sync.sh check-deploy-sql-order.sh check-architecture-sync.sh check-agent-tooling.sh check-context-files.sh check-brain-manifest.sh sync-brain-docs.sh select-agent-context-blocks.sh ensure-task-workflow.sh check-task-workflow.sh switch-plan.sh workflow-contract.ts inspect-project-state.ts migrate-workflow-docs.ts migrate-project-template.sh capability-resolver.ts architecture-event.ts capability-config.ts architecture-queue.sh context-contract-sync.sh workstream-sync.sh prepare-codex-handoff.sh codex-handoff-resume.sh}"
|
|
1033
1033
|
local scripts_dir="$target_dir/scripts"
|
|
1034
1034
|
local runtime_dir="$target_dir/.ai/harness/scripts"
|
|
1035
1035
|
local helper_name
|
|
@@ -1283,7 +1283,7 @@ pi_external_tooling_defaults_summary() {
|
|
|
1283
1283
|
- Mode: optional-enhancements
|
|
1284
1284
|
- Detection: setup/readiness only
|
|
1285
1285
|
- Waza/gstack/gbrain/Mermaid: optional host enhancements; never required for Forge correctness
|
|
1286
|
-
-
|
|
1286
|
+
- Code location: ripgrep lexical source search with explicit language-service definition/reference navigation; no managed graph index
|
|
1287
1287
|
- Auto-actions: never install, upgrade, serve, sync, or enable unrelated third-party tooling automatically
|
|
1288
1288
|
EOF_EXTERNAL_TOOLING_DEFAULTS
|
|
1289
1289
|
}
|
|
@@ -1424,7 +1424,7 @@ pi_forge_version_for_refs() {
|
|
|
1424
1424
|
printf '%s\n' "unknown"
|
|
1425
1425
|
return 0
|
|
1426
1426
|
fi
|
|
1427
|
-
local version_file="$root_dir/
|
|
1427
|
+
local version_file="$root_dir/package.json"
|
|
1428
1428
|
|
|
1429
1429
|
if [[ -f "$version_file" ]]; then
|
|
1430
1430
|
sed -n 's/^[[:space:]]*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' "$version_file" | head -n 1
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
import { homedir } from 'os';
|
|
13
13
|
import { basename, dirname, join, resolve } from 'path';
|
|
14
14
|
import { spawnSync } from 'child_process';
|
|
15
|
+
import { assertRuntimeReleaseExecutionCanaries } from '../src/runtime/root/release-execution-canary';
|
|
15
16
|
import { stageRuntimeRelease } from '../src/runtime/root/release-materialize';
|
|
16
17
|
import { publishRuntimeRelease } from '../src/runtime/root/release-store';
|
|
17
18
|
|
|
@@ -254,6 +255,7 @@ try {
|
|
|
254
255
|
// the clean source checkout before any canonical unit starts.
|
|
255
256
|
preserveLegacyReleaseAuthority(destination, timestamp);
|
|
256
257
|
const stagedRelease = stageRuntimeRelease({ controllerHome: destination, sourceRoot });
|
|
258
|
+
assertRuntimeReleaseExecutionCanaries(stagedRelease.manifestPath, destination);
|
|
257
259
|
publishRuntimeRelease(destination, stagedRelease.manifestPath, `windows-wsl-controller-home-migration-${timestamp}`);
|
|
258
260
|
const release = readActiveRelease(destination);
|
|
259
261
|
atomicWrite(unitPath(units.canonicalRuntime), renderRuntimeUnit(destination, units.canonicalRuntime, release), 0o644);
|
|
@@ -17,7 +17,6 @@ tests/readme-dx.test.ts
|
|
|
17
17
|
|
|
18
18
|
# Runtime proxy bypass intentionally includes Tailscale's standardized CGNAT CIDR.
|
|
19
19
|
adapters/mcp/proxy-env.ts
|
|
20
|
-
src/cli/mcp/proxy-env.ts
|
|
21
20
|
|
|
22
21
|
# Scanner / redaction implementations intentionally embed pattern samples.
|
|
23
22
|
scripts/public-release.ts
|
|
@@ -27,6 +27,8 @@ export function stepsFor(gate: Gate): Step[] {
|
|
|
27
27
|
];
|
|
28
28
|
if (gate === 'main') return [
|
|
29
29
|
{ label: 'focused task receipt', gate: 'task' },
|
|
30
|
+
{ label: 'frozen MCP tool contract', command: 'bun', args: ['run', 'check:mcp-compatibility'], timeoutMs: 2 * 60_000 },
|
|
31
|
+
{ label: 'quality harness benchmark', command: 'bun', args: ['run', 'check:quality-harness'], timeoutMs: 2 * 60_000 },
|
|
30
32
|
{ label: 'core regression', command: 'bun', args: ['run', 'test:core'], timeoutMs: 20 * 60_000 },
|
|
31
33
|
{ label: 'runtime smoke', command: 'bun', args: ['run', 'check:smoke'], timeoutMs: 10 * 60_000 },
|
|
32
34
|
];
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { existsSync } from 'fs';
|
|
1
|
+
import { existsSync, readFileSync } from 'fs';
|
|
2
|
+
import { createHash } from 'crypto';
|
|
2
3
|
import { spawnSync } from 'child_process';
|
|
3
|
-
import {
|
|
4
|
+
import { computerPluginAdapter } from '../src/runtime/plugins/computer-registration';
|
|
4
5
|
import { resolveRepoPreferredControllerHome } from '../src/cli/repositories/controller-home';
|
|
5
6
|
|
|
6
7
|
const repoRoot = process.cwd();
|
|
@@ -29,12 +30,12 @@ const common = {
|
|
|
29
30
|
controllerHome,
|
|
30
31
|
repoId,
|
|
31
32
|
repoRoot,
|
|
32
|
-
pluginId: '
|
|
33
|
+
pluginId: 'computer',
|
|
33
34
|
origin: { surface: 'local-ui' as const, actor: 'physical-ios-live-smoke' },
|
|
34
35
|
};
|
|
35
36
|
|
|
36
37
|
async function invoke(actionId: string, args: Record<string, unknown>) {
|
|
37
|
-
return
|
|
38
|
+
return computerPluginAdapter.executeAction({
|
|
38
39
|
...common,
|
|
39
40
|
actionId,
|
|
40
41
|
args,
|
|
@@ -43,6 +44,7 @@ async function invoke(actionId: string, args: Record<string, unknown>) {
|
|
|
43
44
|
}
|
|
44
45
|
|
|
45
46
|
let interactionId: string | undefined;
|
|
47
|
+
let reusedSession = false;
|
|
46
48
|
try {
|
|
47
49
|
const listed = await invoke('physical_device_list', {});
|
|
48
50
|
const devices = Array.isArray(listed.devices) ? listed.devices as Array<Record<string, unknown>> : [];
|
|
@@ -50,6 +52,9 @@ try {
|
|
|
50
52
|
entry.identifier === deviceSelector || entry.udid === deviceSelector || entry.name === deviceSelector);
|
|
51
53
|
if (matches.length !== 1) throw new Error(`Expected exactly one physical iPhone for selector ${deviceSelector}; found ${matches.length}.`);
|
|
52
54
|
const device = matches[0]!;
|
|
55
|
+
if (device.connected !== true || device.screenshotAvailable !== true) {
|
|
56
|
+
throw new Error(`The selected iPhone ${deviceSelector} has no connected CoreDevice screenshot transport. No app inspection or activation was attempted.`);
|
|
57
|
+
}
|
|
53
58
|
const info = await invoke('physical_device_info', { device: device.identifier });
|
|
54
59
|
const apps = await invoke('physical_device_apps', { device: device.identifier, bundle_id: bundleId });
|
|
55
60
|
const installed = Array.isArray(apps.apps) ? apps.apps as Array<Record<string, unknown>> : [];
|
|
@@ -58,11 +63,15 @@ try {
|
|
|
58
63
|
const opened = await invoke('physical_device_open', {
|
|
59
64
|
device: device.identifier,
|
|
60
65
|
bundle_id: bundleId,
|
|
61
|
-
relaunch:
|
|
66
|
+
relaunch: false,
|
|
67
|
+
observe_after_open: true,
|
|
68
|
+
// This is a one-shot open/capture receipt; do not retain a HID worker.
|
|
69
|
+
prewarm_input: false,
|
|
62
70
|
});
|
|
63
71
|
const interaction = opened.interaction as Record<string, unknown> | undefined;
|
|
64
72
|
interactionId = typeof interaction?.interactionId === 'string' ? interaction.interactionId : undefined;
|
|
65
73
|
if (!interactionId) throw new Error('The physical provider did not return an interaction id.');
|
|
74
|
+
reusedSession = opened.reusedSession === true;
|
|
66
75
|
|
|
67
76
|
const screenshot = await invoke('physical_device_screenshot', {
|
|
68
77
|
interaction_id: interactionId,
|
|
@@ -71,17 +80,29 @@ try {
|
|
|
71
80
|
const artifacts = Array.isArray(screenshot.artifactCandidates)
|
|
72
81
|
? screenshot.artifactCandidates as Array<Record<string, unknown>>
|
|
73
82
|
: [];
|
|
74
|
-
const
|
|
83
|
+
const artifact = artifacts[0];
|
|
84
|
+
const path = typeof artifact?.path === 'string' ? artifact.path : '';
|
|
75
85
|
if (!path || !existsSync(path)) throw new Error('The physical provider did not create a screenshot artifact.');
|
|
86
|
+
// Bind the local evidence to this exact CoreDevice observation without
|
|
87
|
+
// claiming what App, SKU or checkout price is actually visible.
|
|
88
|
+
const observation = screenshot.observation as Record<string, unknown> | undefined;
|
|
89
|
+
const image = readFileSync(path);
|
|
90
|
+
const screenshotSha256 = createHash('sha256').update(image).digest('hex');
|
|
91
|
+
const observationId = typeof observation?.observationId === 'string' ? observation.observationId : undefined;
|
|
92
|
+
if (!observationId || artifact?.sha256 !== screenshotSha256 || artifact?.bytes !== image.length
|
|
93
|
+
|| observation?.screenshotSha256 !== screenshotSha256 || observation?.screenshotBytes !== image.length) {
|
|
94
|
+
throw new Error('The screenshot file and CoreDevice observation receipts do not match.');
|
|
95
|
+
}
|
|
76
96
|
const metadata = spawnSync('sips', ['-g', 'pixelWidth', '-g', 'pixelHeight', '-g', 'format', path], { encoding: 'utf8' }).stdout;
|
|
77
97
|
const width = metadata.match(/pixelWidth:\s*(\d+)/)?.[1];
|
|
78
98
|
const height = metadata.match(/pixelHeight:\s*(\d+)/)?.[1];
|
|
79
99
|
const format = metadata.match(/format:\s*(\S+)/)?.[1];
|
|
80
100
|
|
|
81
|
-
const closed = await invoke('physical_device_close', { interaction_id: interactionId });
|
|
101
|
+
const closed = reusedSession ? undefined : await invoke('physical_device_close', { interaction_id: interactionId });
|
|
82
102
|
interactionId = undefined;
|
|
83
103
|
const app = installed[0]!;
|
|
84
104
|
console.log(JSON.stringify({
|
|
105
|
+
verificationLevel: 'source_computer_adapter_open_and_capture_only',
|
|
85
106
|
device: {
|
|
86
107
|
name: device.name,
|
|
87
108
|
model: device.model,
|
|
@@ -97,20 +118,27 @@ try {
|
|
|
97
118
|
version: app.version,
|
|
98
119
|
},
|
|
99
120
|
launchStatus: interaction?.status,
|
|
121
|
+
reusedSession,
|
|
100
122
|
controlPlane: opened.controlPlane,
|
|
101
123
|
coreDeviceCapabilities: info.capabilities,
|
|
102
124
|
screenViewingURLAvailable: typeof info.screenViewingURL === 'string',
|
|
103
125
|
screenshot: {
|
|
104
126
|
created: true,
|
|
127
|
+
path,
|
|
128
|
+
sha256: screenshotSha256,
|
|
129
|
+
bytes: image.length,
|
|
130
|
+
observationId,
|
|
131
|
+
observedAt: observation?.observedAt,
|
|
132
|
+
semanticPriceVerified: false,
|
|
105
133
|
width: width ? Number(width) : undefined,
|
|
106
134
|
height: height ? Number(height) : undefined,
|
|
107
135
|
format,
|
|
108
136
|
},
|
|
109
|
-
closeStatus: (closed
|
|
110
|
-
deviceUnmodified: closed
|
|
137
|
+
closeStatus: (closed?.interaction as Record<string, unknown> | undefined)?.status,
|
|
138
|
+
deviceUnmodified: closed?.deviceUnmodified === true,
|
|
111
139
|
}, null, 2));
|
|
112
140
|
} finally {
|
|
113
|
-
if (interactionId) {
|
|
141
|
+
if (interactionId && !reusedSession) {
|
|
114
142
|
try { await invoke('physical_device_close', { interaction_id: interactionId }); } catch {}
|
|
115
143
|
}
|
|
116
144
|
}
|
|
@@ -6,13 +6,12 @@ import { join } from 'path';
|
|
|
6
6
|
import { registerRepository } from '../src/cli/repositories/registry';
|
|
7
7
|
import { readForgeRuntimeStatus } from '../src/runtime/control-plane/runtime-status-client';
|
|
8
8
|
import { FORGE_TOOL_SURFACE } from '../src/cli/controller/runtime-config';
|
|
9
|
-
import {
|
|
9
|
+
import { controllerExposureSnapshot } from '../adapters/mcp/toolset';
|
|
10
10
|
import { writeMcpServiceLocalConfig } from '../adapters/mcp/auth';
|
|
11
|
-
import { buildMcpToolDefinitions } from '../
|
|
12
|
-
import { runtimePolicy } from '../
|
|
13
|
-
import { resolveControllerToolsetSelection } from '../src/cli/mcp/toolset-selection';
|
|
11
|
+
import { buildMcpToolDefinitions } from '../adapters/mcp/tool-mapping/tools';
|
|
12
|
+
import { runtimePolicy } from '../adapters/mcp/multi-repository';
|
|
14
13
|
import { RUNTIME_WRITE_CLAIM_ENV } from '../src/runtime/root/write-fence';
|
|
15
|
-
import { createMcpToolContext, readCanonicalRuntimeToolSchema } from '../
|
|
14
|
+
import { createMcpToolContext, readCanonicalRuntimeToolSchema } from '../adapters/mcp/server';
|
|
16
15
|
|
|
17
16
|
const root = mkdtempSync(join(tmpdir(), 'forge-mcp-http-smoke-'));
|
|
18
17
|
const repoRoot = join(root, 'repo');
|
|
@@ -160,8 +159,8 @@ try {
|
|
|
160
159
|
enableDevRunner: true,
|
|
161
160
|
devRunnerAgents: 'codex,claude',
|
|
162
161
|
});
|
|
163
|
-
//
|
|
164
|
-
const expectedToolset =
|
|
162
|
+
// Every Controller session exposes the same complete capability registry.
|
|
163
|
+
const expectedToolset = 'full';
|
|
165
164
|
if (health.body.toolset !== expectedToolset) throw new Error(`TOOLSET_CHANGED: ${String(health.body.toolset)}`);
|
|
166
165
|
if (health.body.toolSurface !== FORGE_TOOL_SURFACE) throw new Error(`TOOL_SURFACE_CHANGED: ${String(health.body.toolSurface)}`);
|
|
167
166
|
const expectedCompatibilityToolCount = buildMcpToolDefinitions(expectedPolicy).length;
|
|
@@ -184,7 +183,7 @@ try {
|
|
|
184
183
|
devRunnerAgents: 'codex,claude',
|
|
185
184
|
});
|
|
186
185
|
const runtimeSchema = await readCanonicalRuntimeToolSchema(runtimeContext);
|
|
187
|
-
const expectedRuntimeNames = [...
|
|
186
|
+
const expectedRuntimeNames = [...controllerExposureSnapshot(runtimeContext).actualToolNames].sort();
|
|
188
187
|
if (JSON.stringify(runtimeSchema.toolNames) !== JSON.stringify(expectedRuntimeNames)) {
|
|
189
188
|
throw new Error(`RUNTIME_TOOL_SCHEMA_CHANGED: ${JSON.stringify(runtimeSchema.toolNames)}`);
|
|
190
189
|
}
|
|
@@ -3,27 +3,34 @@
|
|
|
3
3
|
* Focused smoke: local MCP tool surface + connector freshness semantics.
|
|
4
4
|
* Does not require a live ChatGPT connector session.
|
|
5
5
|
*/
|
|
6
|
-
import { getMcpPolicy } from '../
|
|
7
|
-
import { controllerExpectedToolNames } from '../src/cli/mcp/legacy-tool-service';
|
|
6
|
+
import { getMcpPolicy } from '../adapters/mcp/policy';
|
|
8
7
|
import {
|
|
9
|
-
|
|
10
|
-
DEFAULT_CONTROLLER_TOOL_NAMES,
|
|
8
|
+
PREFERRED_CONTROLLER_TOOL_NAMES,
|
|
11
9
|
PREFERRED_FACADE_TOOL_NAMES,
|
|
12
10
|
exposedControllerToolDefinitions,
|
|
13
|
-
} from '../
|
|
11
|
+
} from '../adapters/mcp/toolset';
|
|
14
12
|
import {
|
|
15
13
|
EXPECTED_FACADE_TOOLS,
|
|
16
14
|
OPTIONAL_INTERACTIVE_DEVELOPMENT_TOOLS,
|
|
17
15
|
evaluateConnectorFreshness,
|
|
18
16
|
} from '../src/cli/local-bridge/connector-freshness';
|
|
19
|
-
import type { MultiRepositoryMcpToolContext } from '../
|
|
17
|
+
import type { MultiRepositoryMcpToolContext } from '../adapters/mcp/multi-repository';
|
|
20
18
|
|
|
21
19
|
function assert(condition: unknown, message: string): asserts condition {
|
|
22
20
|
if (!condition) throw new Error(`SMOKE_FAIL: ${message}`);
|
|
23
21
|
}
|
|
24
22
|
|
|
25
23
|
const policy = getMcpPolicy('controller');
|
|
26
|
-
const
|
|
24
|
+
const fullCtx = {
|
|
25
|
+
policy,
|
|
26
|
+
toolset: 'full' as const,
|
|
27
|
+
controllerHome: process.cwd(),
|
|
28
|
+
repoRoot: process.cwd(),
|
|
29
|
+
enableChatgptBrowser: false,
|
|
30
|
+
audit: () => undefined,
|
|
31
|
+
} as unknown as MultiRepositoryMcpToolContext;
|
|
32
|
+
const fullExposed = exposedControllerToolDefinitions(fullCtx).map((tool) => tool.name);
|
|
33
|
+
const expected = fullExposed;
|
|
27
34
|
|
|
28
35
|
assert(
|
|
29
36
|
JSON.stringify([...PREFERRED_FACADE_TOOL_NAMES]) === JSON.stringify([...EXPECTED_FACADE_TOOLS]),
|
|
@@ -32,7 +39,7 @@ assert(
|
|
|
32
39
|
|
|
33
40
|
for (const name of EXPECTED_FACADE_TOOLS) {
|
|
34
41
|
assert(
|
|
35
|
-
(
|
|
42
|
+
(PREFERRED_CONTROLLER_TOOL_NAMES as readonly string[]).includes(name),
|
|
36
43
|
`default exposure missing ${name}`,
|
|
37
44
|
);
|
|
38
45
|
assert(expected.includes(name), `expectedTools missing ${name}`);
|
|
@@ -40,41 +47,21 @@ for (const name of EXPECTED_FACADE_TOOLS) {
|
|
|
40
47
|
|
|
41
48
|
for (const name of OPTIONAL_INTERACTIVE_DEVELOPMENT_TOOLS) {
|
|
42
49
|
assert(
|
|
43
|
-
(
|
|
44
|
-
`interactive tool ${name} missing from
|
|
50
|
+
(PREFERRED_CONTROLLER_TOOL_NAMES as readonly string[]).includes(name),
|
|
51
|
+
`interactive tool ${name} missing from the preferred capability list`,
|
|
45
52
|
);
|
|
46
53
|
assert(
|
|
47
|
-
(
|
|
48
|
-
`interactive tool ${name} missing from the
|
|
54
|
+
(PREFERRED_CONTROLLER_TOOL_NAMES as readonly string[]).includes(name),
|
|
55
|
+
`interactive tool ${name} missing from the preferred routing list`,
|
|
49
56
|
);
|
|
50
57
|
}
|
|
51
58
|
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
toolset: 'core' as const,
|
|
55
|
-
enableChatgptBrowser: false,
|
|
56
|
-
audit: () => undefined,
|
|
57
|
-
} as unknown as MultiRepositoryMcpToolContext;
|
|
58
|
-
const advancedCtx = { ...coreCtx, toolset: 'advanced' as const };
|
|
59
|
-
|
|
60
|
-
const coreExposed = exposedControllerToolDefinitions(coreCtx).map((tool) => tool.name);
|
|
61
|
-
const advancedExposed = exposedControllerToolDefinitions(advancedCtx).map((tool) => tool.name);
|
|
62
|
-
for (const name of EXPECTED_FACADE_TOOLS) {
|
|
63
|
-
assert(coreExposed.includes(name), `exposed core tools missing ${name}`);
|
|
64
|
-
}
|
|
65
|
-
assert(coreExposed.includes('repository_list'), 'default surface missing repository_list');
|
|
66
|
-
assert(!coreExposed.includes('repository_bootstrap_local_project'), 'default stable surface must not expose legacy bootstrap tool');
|
|
67
|
-
assert(!advancedExposed.includes('repository_bootstrap_local_project'), 'advanced stable alias must not expose legacy bootstrap tool');
|
|
68
|
-
assert(coreExposed.length === DEFAULT_CONTROLLER_TOOL_NAMES.length, `core stable tool count changed: ${coreExposed.length}`);
|
|
69
|
-
assert(advancedExposed.length === DEFAULT_CONTROLLER_TOOL_NAMES.length, `advanced stable tool count changed: ${advancedExposed.length}`);
|
|
70
|
-
assert(
|
|
71
|
-
JSON.stringify(coreExposed) === JSON.stringify(advancedExposed),
|
|
72
|
-
'Core and Advanced must remain schema-stable aliases of the same bounded tool surface',
|
|
73
|
-
);
|
|
74
|
-
for (const name of OPTIONAL_INTERACTIVE_DEVELOPMENT_TOOLS) {
|
|
75
|
-
assert(coreExposed.includes(name), `stable surface missing interactive ${name}`);
|
|
76
|
-
assert(advancedExposed.includes(name), `advanced alias missing interactive ${name}`);
|
|
59
|
+
for (const name of PREFERRED_CONTROLLER_TOOL_NAMES) {
|
|
60
|
+
assert(fullExposed.includes(name), `complete registry missing preferred capability ${name}`);
|
|
77
61
|
}
|
|
62
|
+
assert(fullExposed.includes('repository_bootstrap_local_project'), 'complete registry missing repository bootstrap');
|
|
63
|
+
assert(fullExposed.includes('git_commit_paths'), 'complete registry missing canonical Git operation');
|
|
64
|
+
assert(fullExposed.length > PREFERRED_CONTROLLER_TOOL_NAMES.length, 'complete registry must include every registered operation');
|
|
78
65
|
|
|
79
66
|
const unable = evaluateConnectorFreshness({ localToolNames: expected });
|
|
80
67
|
assert(unable.status === 'unable_to_verify_chatgpt_snapshot', `expected unable_to_verify, got ${unable.status}`);
|
|
@@ -103,11 +90,10 @@ console.log(JSON.stringify({
|
|
|
103
90
|
ok: true,
|
|
104
91
|
expectedFacadeTools: EXPECTED_FACADE_TOOLS,
|
|
105
92
|
preferredTools: PREFERRED_FACADE_TOOL_NAMES,
|
|
106
|
-
|
|
107
|
-
|
|
93
|
+
exposedToolCount: fullExposed.length,
|
|
94
|
+
preferredToolCount: PREFERRED_CONTROLLER_TOOL_NAMES.length,
|
|
108
95
|
expectedToolsHasFacade: EXPECTED_FACADE_TOOLS.every((name) => expected.includes(name)),
|
|
109
|
-
|
|
110
|
-
(ADVANCED_CONTROLLER_TOOL_NAMES as readonly string[]).includes(name)),
|
|
96
|
+
fullHasInteractive: OPTIONAL_INTERACTIVE_DEVELOPMENT_TOOLS.every((name) => fullExposed.includes(name)),
|
|
111
97
|
states: {
|
|
112
98
|
unable: unable.status,
|
|
113
99
|
missingSnap: missingSnap.status,
|
|
@@ -73,10 +73,13 @@ try {
|
|
|
73
73
|
assert.equal(browserCore.parseConversation(conversationUrl)?.conversationId, conversationId);
|
|
74
74
|
assert.equal(browserCore.parseConversation(`https://example.com/c/${conversationId}`), null);
|
|
75
75
|
const extensionManifest = JSON.parse(readFileSync(resolve('adapters/computer/chrome-extension/manifest.json'), 'utf8')) as { permissions?: string[] };
|
|
76
|
-
assert.equal(extensionManifest.permissions?.includes('storage'),
|
|
76
|
+
assert.equal(extensionManifest.permissions?.includes('storage'), true);
|
|
77
77
|
const backgroundSource = readFileSync(resolve('adapters/computer/chrome-extension/background.js'), 'utf8');
|
|
78
|
-
assert.ok(backgroundSource.includes(
|
|
79
|
-
assert.
|
|
78
|
+
assert.ok(backgroundSource.includes("chrome.storage.local.get('forgeComputerProviderInstanceId')"));
|
|
79
|
+
assert.ok(backgroundSource.includes('const instanceId = await providerInstanceId();'));
|
|
80
|
+
assert.ok(backgroundSource.includes('source: `chrome-extension:${instanceId}`'));
|
|
81
|
+
assert.equal(backgroundSource.includes('PROVIDER_INSTANCE_ID'), false);
|
|
82
|
+
assert.ok(backgroundSource.includes('chrome.storage.local.set({ forgeComputerProviderInstanceId: instanceId })'));
|
|
80
83
|
assert.ok(backgroundSource.includes("nativeRpc('computer_extension_heartbeat'"));
|
|
81
84
|
assert.ok(backgroundSource.includes('providerInstanceId: instanceId'));
|
|
82
85
|
assert.ok(backgroundSource.includes("nativeRpc('computer_extension_claim', { provider_instance_id: instanceId })"));
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { GitHubStatus } from "../github/contracts";
|
|
2
|
-
import type { McpAgentRunnerName } from "
|
|
2
|
+
import type { McpAgentRunnerName } from "../../../adapters/mcp/types";
|
|
3
3
|
import type { ControllerAgent } from "../controller/types";
|
|
4
4
|
|
|
5
5
|
export type ExecutorHealthStatus =
|
|
@@ -13,8 +13,8 @@ import {
|
|
|
13
13
|
type EditOperation,
|
|
14
14
|
type EditSession,
|
|
15
15
|
} from "../editing/edit-session";
|
|
16
|
-
import { resolveMcpPath } from "
|
|
17
|
-
import type { McpPolicy } from "
|
|
16
|
+
import { resolveMcpPath } from "../../../adapters/mcp/paths";
|
|
17
|
+
import type { McpPolicy } from "../../../adapters/mcp/types";
|
|
18
18
|
import { getAgentJob, markAgentJobClosure, markAgentJobIntegrated, markAgentJobIntegrationReview } from "./job-manager";
|
|
19
19
|
import type { AgentJobMeta, AgentJobPreservationReason } from "./types";
|
|
20
20
|
import { assertRuntimeMayWriteOrThrow, isRuntimeWriteFenceError } from "../../runtime/root/write-fence";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { createHash } from 'crypto';
|
|
2
2
|
import { existsSync, readFileSync, statSync } from 'fs';
|
|
3
3
|
import { isAbsolute, resolve } from 'path';
|
|
4
|
-
import { resolveMcpPath } from '
|
|
5
|
-
import type { McpPolicy } from '
|
|
4
|
+
import { resolveMcpPath } from '../../../adapters/mcp/paths';
|
|
5
|
+
import type { McpPolicy } from '../../../adapters/mcp/types';
|
|
6
6
|
import type { BrowserWriteOutputPolicy, PromptBundleFile } from './types';
|
|
7
7
|
|
|
8
8
|
const READ_ALLOW_GLOBS = [
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* `forge doctor` — read-only readiness diagnostics.
|
|
3
3
|
*
|
|
4
4
|
* Built-in checks: PATH resolution, CLI version, per-host install detection,
|
|
5
|
-
* Codex user-level trust state count, and
|
|
5
|
+
* Codex user-level trust state count, and current-source tool readiness.
|
|
6
6
|
* Never mutates.
|
|
7
7
|
*/
|
|
8
8
|
|
|
@@ -11,7 +11,6 @@ import * as os from 'os';
|
|
|
11
11
|
import * as path from 'path';
|
|
12
12
|
import { spawnSync } from 'child_process';
|
|
13
13
|
import { ALL_TARGETS } from '../installer/targets/registry';
|
|
14
|
-
import { checkCodegraph, type CodegraphCheckResult } from '../tools/codegraph';
|
|
15
14
|
import { CLI_VERSION } from './status';
|
|
16
15
|
import { runSecurityScan, type SecurityScanReport } from './security';
|
|
17
16
|
import { isOptIn, resolveHooksDir, resolveRepoRoot } from '../hook/runtime';
|
|
@@ -225,142 +224,6 @@ function checkCodexTrustState(): DoctorCheckResult {
|
|
|
225
224
|
}
|
|
226
225
|
}
|
|
227
226
|
|
|
228
|
-
function doctorStatusForCodegraph(status: CodegraphCheckResult['status']): CheckStatus {
|
|
229
|
-
if (status === 'present') return 'ok';
|
|
230
|
-
if (status === 'missing') return 'fail';
|
|
231
|
-
return 'warn';
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
function formatCodegraphDetail(result: CodegraphCheckResult): string {
|
|
235
|
-
const raw = result.raw as Record<string, any>;
|
|
236
|
-
const indexStatus = raw.project_index?.status ?? 'unknown';
|
|
237
|
-
const codexMcpStatus = raw.mcp_hosts?.codex?.status ?? 'unknown';
|
|
238
|
-
const claudeMcpStatus = raw.mcp_hosts?.claude?.status ?? 'unknown';
|
|
239
|
-
const bits = [
|
|
240
|
-
result.reason,
|
|
241
|
-
`source=${result.resolution.source}`,
|
|
242
|
-
`version=${result.resolution.version ?? 'unknown'}`,
|
|
243
|
-
`codex-mcp=${codexMcpStatus}`,
|
|
244
|
-
`claude-mcp=${claudeMcpStatus}`,
|
|
245
|
-
`index=${indexStatus}`,
|
|
246
|
-
];
|
|
247
|
-
if (result.resolution.globalFallbackUsed) bits.push('global-fallback=true');
|
|
248
|
-
const remediation = codegraphRemediation(result);
|
|
249
|
-
if (remediation) bits.push(`remediation=${remediation}`);
|
|
250
|
-
return bits.join('; ');
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
function codegraphRemediation(result: CodegraphCheckResult): string | null {
|
|
254
|
-
if (result.status === 'present') return null;
|
|
255
|
-
|
|
256
|
-
const raw = result.raw as Record<string, any>;
|
|
257
|
-
if (result.resolution.source === 'missing') {
|
|
258
|
-
return String(raw.install_command ?? 'bash scripts/ensure-codegraph.sh');
|
|
259
|
-
}
|
|
260
|
-
if (result.resolution.globalFallbackUsed) {
|
|
261
|
-
return String(raw.install_command ?? 'bun install');
|
|
262
|
-
}
|
|
263
|
-
if (raw.mcp_hosts?.codex?.status !== 'configured' || raw.mcp_hosts?.claude?.status !== 'configured') {
|
|
264
|
-
return String(raw.mcp_install_command ?? 'forge tools configure codegraph --target both --location global');
|
|
265
|
-
}
|
|
266
|
-
if (raw.project_index?.status === 'not-initialized') {
|
|
267
|
-
return String(raw.init_command ?? 'bash scripts/ensure-codegraph.sh --init');
|
|
268
|
-
}
|
|
269
|
-
if (raw.project_index?.status === 'stale') {
|
|
270
|
-
return String(raw.sync_command ?? 'bash scripts/ensure-codegraph.sh --sync');
|
|
271
|
-
}
|
|
272
|
-
return String(raw.ensure_command ?? raw.sync_command ?? 'bash scripts/ensure-codegraph.sh --check');
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
interface CodegraphProbe {
|
|
276
|
-
result?: CodegraphCheckResult;
|
|
277
|
-
error?: Error;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
function probeCodegraph(cwd: string): CodegraphProbe {
|
|
281
|
-
try {
|
|
282
|
-
return { result: checkCodegraph({ repoRoot: cwd, host: 'both' }) };
|
|
283
|
-
} catch (err) {
|
|
284
|
-
return { error: err as Error };
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
function checkCodegraphReadiness(probe: CodegraphProbe): DoctorCheckResult {
|
|
289
|
-
const id = 'codegraph-readiness';
|
|
290
|
-
const describe = 'CodeGraph CLI, MCP, and project index readiness';
|
|
291
|
-
if (probe.result) {
|
|
292
|
-
return {
|
|
293
|
-
id,
|
|
294
|
-
describe,
|
|
295
|
-
status: doctorStatusForCodegraph(probe.result.status),
|
|
296
|
-
detail: formatCodegraphDetail(probe.result),
|
|
297
|
-
};
|
|
298
|
-
}
|
|
299
|
-
return {
|
|
300
|
-
id,
|
|
301
|
-
describe,
|
|
302
|
-
status: 'fail',
|
|
303
|
-
detail: `error checking CodeGraph readiness: ${probe.error?.message ?? 'unknown error'}`,
|
|
304
|
-
};
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
function checkCodegraphMcpHost(probe: CodegraphProbe, host: 'codex' | 'claude'): DoctorCheckResult {
|
|
308
|
-
const id = `${host}-codegraph-mcp`;
|
|
309
|
-
const describe = `${host === 'codex' ? 'Codex' : 'Claude Code'} CodeGraph MCP config`;
|
|
310
|
-
if (!probe.result) {
|
|
311
|
-
return {
|
|
312
|
-
id,
|
|
313
|
-
describe,
|
|
314
|
-
status: 'fail',
|
|
315
|
-
detail: `error checking CodeGraph MCP config: ${probe.error?.message ?? 'unknown error'}`,
|
|
316
|
-
};
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
const raw = probe.result.raw as Record<string, any>;
|
|
320
|
-
const entry = raw.mcp_hosts?.[host];
|
|
321
|
-
if (entry?.status === 'configured') {
|
|
322
|
-
return { id, describe, status: 'ok', detail: entry.reason ?? 'configured' };
|
|
323
|
-
}
|
|
324
|
-
return {
|
|
325
|
-
id,
|
|
326
|
-
describe,
|
|
327
|
-
status: 'warn',
|
|
328
|
-
detail: `${entry?.reason ?? 'missing'}; remediation=forge tools configure codegraph --target ${host} --location global`,
|
|
329
|
-
};
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
function checkCodegraphIndex(probe: CodegraphProbe): DoctorCheckResult {
|
|
333
|
-
const id = 'codegraph-index';
|
|
334
|
-
const describe = 'CodeGraph project index';
|
|
335
|
-
if (!probe.result) {
|
|
336
|
-
return {
|
|
337
|
-
id,
|
|
338
|
-
describe,
|
|
339
|
-
status: 'fail',
|
|
340
|
-
detail: `error checking CodeGraph index: ${probe.error?.message ?? 'unknown error'}`,
|
|
341
|
-
};
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
const raw = probe.result.raw as Record<string, any>;
|
|
345
|
-
const indexStatus = raw.project_index?.status ?? 'unknown';
|
|
346
|
-
const status: CheckStatus = indexStatus === 'up-to-date'
|
|
347
|
-
? 'ok'
|
|
348
|
-
: indexStatus === 'stale' || indexStatus === 'unknown'
|
|
349
|
-
? 'warn'
|
|
350
|
-
: 'fail';
|
|
351
|
-
const remediation = indexStatus === 'not-initialized'
|
|
352
|
-
? raw.init_command
|
|
353
|
-
: indexStatus === 'stale'
|
|
354
|
-
? raw.sync_command
|
|
355
|
-
: raw.ensure_command;
|
|
356
|
-
return {
|
|
357
|
-
id,
|
|
358
|
-
describe,
|
|
359
|
-
status,
|
|
360
|
-
detail: `index=${indexStatus}${remediation ? `; remediation=${remediation}` : ''}`,
|
|
361
|
-
};
|
|
362
|
-
}
|
|
363
|
-
|
|
364
227
|
function checkSecurityConfig(report: SecurityScanReport): DoctorCheckResult {
|
|
365
228
|
const id = 'security-config';
|
|
366
229
|
const describe = 'Local hook and VS Code automatic task security scan';
|
|
@@ -451,7 +314,6 @@ function checkHookScriptDrift(cwd: string): DoctorCheckResult {
|
|
|
451
314
|
|
|
452
315
|
export function runDoctor(cwd: string = process.cwd()): DoctorReport {
|
|
453
316
|
const checks: DoctorCheckResult[] = [];
|
|
454
|
-
const codegraphProbe = probeCodegraph(cwd);
|
|
455
317
|
const securityReport = runSecurityScan({ cwd });
|
|
456
318
|
checks.push(checkPath());
|
|
457
319
|
checks.push(checkVersion());
|
|
@@ -462,10 +324,6 @@ export function runDoctor(cwd: string = process.cwd()): DoctorReport {
|
|
|
462
324
|
}
|
|
463
325
|
}
|
|
464
326
|
checks.push(checkCodexTrustState());
|
|
465
|
-
checks.push(checkCodegraphReadiness(codegraphProbe));
|
|
466
|
-
checks.push(checkCodegraphMcpHost(codegraphProbe, 'codex'));
|
|
467
|
-
checks.push(checkCodegraphMcpHost(codegraphProbe, 'claude'));
|
|
468
|
-
checks.push(checkCodegraphIndex(codegraphProbe));
|
|
469
327
|
checks.push(checkSecurityConfig(securityReport));
|
|
470
328
|
checks.push(checkHookScriptDrift(cwd));
|
|
471
329
|
checks.push(checkBootstrapLifecycle());
|