@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
|
@@ -2,10 +2,9 @@ import { existsSync, readFileSync } from "fs";
|
|
|
2
2
|
import { dirname, join, resolve } from "path";
|
|
3
3
|
import { fileURLToPath } from "url";
|
|
4
4
|
import { configureBrainRoot, defaultBrainRootChoice, expandHomePath } from "./brain-root";
|
|
5
|
-
import { syncCrossReviewSkills } from "./init";
|
|
6
5
|
import { runInstall, type InstallTargetSpec } from "./install";
|
|
7
|
-
import { configureCodegraph } from "../tools/codegraph";
|
|
8
6
|
import { runProcess as runBoundedProcess } from "../../effects/process-runner";
|
|
7
|
+
import { runSetupProcess as runProcess, withProcessEnv, type SetupExecutionStep } from './setup-execution';
|
|
9
8
|
|
|
10
9
|
export interface GlobalRuntimeOptions {
|
|
11
10
|
sourceRoot?: string;
|
|
@@ -14,22 +13,11 @@ export interface GlobalRuntimeOptions {
|
|
|
14
13
|
target?: InstallTargetSpec;
|
|
15
14
|
installCli?: boolean;
|
|
16
15
|
installSpec?: string;
|
|
17
|
-
syncSkill?: boolean;
|
|
18
16
|
hostAdapters?: boolean;
|
|
19
|
-
externalSkills?: boolean;
|
|
20
|
-
codegraph?: boolean;
|
|
21
17
|
brainRoot?: string;
|
|
22
|
-
platform?: NodeJS.Platform;
|
|
23
18
|
}
|
|
24
19
|
|
|
25
|
-
export
|
|
26
|
-
step: string;
|
|
27
|
-
status: "ok" | "skipped" | "failed";
|
|
28
|
-
command?: string[];
|
|
29
|
-
detail?: string;
|
|
30
|
-
stdout?: string;
|
|
31
|
-
stderr?: string;
|
|
32
|
-
}
|
|
20
|
+
export type GlobalRuntimeStep = SetupExecutionStep;
|
|
33
21
|
|
|
34
22
|
export interface GlobalRuntimeResult {
|
|
35
23
|
exitCode: number;
|
|
@@ -40,25 +28,11 @@ export interface GlobalRuntimeResult {
|
|
|
40
28
|
}
|
|
41
29
|
|
|
42
30
|
const SCRIPT_DIR = dirname(fileURLToPath(import.meta.url));
|
|
43
|
-
const CODEGRAPH_PACKAGE = "@colbymchenry/codegraph";
|
|
44
|
-
const WAZA_SKILLS = ["think", "hunt", "check", "health"] as const;
|
|
45
31
|
|
|
46
32
|
function defaultSourceRoot(): string {
|
|
47
33
|
return join(SCRIPT_DIR, "..", "..", "..");
|
|
48
34
|
}
|
|
49
35
|
|
|
50
|
-
function runProcess(command: string, args: string[], cwd: string, env?: NodeJS.ProcessEnv): GlobalRuntimeStep {
|
|
51
|
-
const result = runBoundedProcess(command, args, { cwd, env });
|
|
52
|
-
|
|
53
|
-
return {
|
|
54
|
-
step: "",
|
|
55
|
-
status: result.ok ? "ok" : "failed",
|
|
56
|
-
command: [...result.command],
|
|
57
|
-
stdout: result.stdout,
|
|
58
|
-
stderr: result.stderr || result.error,
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
|
|
62
36
|
function withStepName(step: GlobalRuntimeStep, name: string, detail?: string): GlobalRuntimeStep {
|
|
63
37
|
return { ...step, step: name, detail: detail ?? step.detail };
|
|
64
38
|
}
|
|
@@ -69,42 +43,6 @@ function renderStep(step: GlobalRuntimeStep): string[] {
|
|
|
69
43
|
return lines;
|
|
70
44
|
}
|
|
71
45
|
|
|
72
|
-
function withProcessEnv<T>(env: NodeJS.ProcessEnv | undefined, fn: () => T): T {
|
|
73
|
-
if (!env) return fn();
|
|
74
|
-
const previous = new Map<string, string | undefined>();
|
|
75
|
-
for (const [key, value] of Object.entries(env)) {
|
|
76
|
-
previous.set(key, process.env[key]);
|
|
77
|
-
if (value === undefined) delete process.env[key];
|
|
78
|
-
else process.env[key] = value;
|
|
79
|
-
}
|
|
80
|
-
try {
|
|
81
|
-
return fn();
|
|
82
|
-
} finally {
|
|
83
|
-
for (const [key, value] of previous) {
|
|
84
|
-
if (value === undefined) delete process.env[key];
|
|
85
|
-
else process.env[key] = value;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
function hostAgents(target: InstallTargetSpec): string[] {
|
|
91
|
-
if (target === "codex") return ["codex"];
|
|
92
|
-
if (target === "claude") return ["claude-code"];
|
|
93
|
-
return ["claude-code", "codex"];
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
function isNpxCacheSource(sourceRoot: string): boolean {
|
|
97
|
-
return /[\\/]_npx[\\/]/.test(sourceRoot);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
function commandEnv(sourceRoot: string, env?: NodeJS.ProcessEnv): NodeJS.ProcessEnv | undefined {
|
|
101
|
-
const next = { ...(env ?? {}) };
|
|
102
|
-
if (isNpxCacheSource(sourceRoot) && next.AGENTIC_DEV_LINK_INSTALLED_COPIES === undefined) {
|
|
103
|
-
next.AGENTIC_DEV_LINK_INSTALLED_COPIES = "0";
|
|
104
|
-
}
|
|
105
|
-
return Object.keys(next).length > 0 ? next : env;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
46
|
function packageVersion(sourceRoot: string): string | null {
|
|
109
47
|
try {
|
|
110
48
|
const pkg = JSON.parse(readFileSync(join(sourceRoot, "package.json"), "utf-8"));
|
|
@@ -136,28 +74,6 @@ function installCli(sourceRoot: string, cwd: string, env?: NodeJS.ProcessEnv, in
|
|
|
136
74
|
);
|
|
137
75
|
}
|
|
138
76
|
|
|
139
|
-
function syncRuntimeSkill(sourceRoot: string, env?: NodeJS.ProcessEnv, platform: NodeJS.Platform = process.platform): GlobalRuntimeStep {
|
|
140
|
-
const script = join(sourceRoot, "scripts", "sync-codex-installed-copies.sh");
|
|
141
|
-
if (!existsSync(script)) {
|
|
142
|
-
return {
|
|
143
|
-
step: "sync forge skill runtime",
|
|
144
|
-
status: "skipped",
|
|
145
|
-
detail: `script not found: ${script}`,
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
if (platform === "win32") {
|
|
149
|
-
return {
|
|
150
|
-
step: "sync forge skill runtime",
|
|
151
|
-
status: "skipped",
|
|
152
|
-
detail: "native Windows skips the Bash-owned skill sync; use WSL2 for the complete shell workflow",
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
return withStepName(
|
|
156
|
-
runProcess("bash", [script], sourceRoot, env),
|
|
157
|
-
"sync forge skill runtime",
|
|
158
|
-
);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
77
|
function installHostAdapters(target: InstallTargetSpec, env?: NodeJS.ProcessEnv): GlobalRuntimeStep {
|
|
162
78
|
const installed = withProcessEnv(env, () => runInstall({ target, location: "global" }));
|
|
163
79
|
return {
|
|
@@ -167,50 +83,6 @@ function installHostAdapters(target: InstallTargetSpec, env?: NodeJS.ProcessEnv)
|
|
|
167
83
|
};
|
|
168
84
|
}
|
|
169
85
|
|
|
170
|
-
function installWazaSkills(sourceRoot: string, target: InstallTargetSpec, env?: NodeJS.ProcessEnv): GlobalRuntimeStep {
|
|
171
|
-
const agents = hostAgents(target);
|
|
172
|
-
const step = runProcess(
|
|
173
|
-
"npx",
|
|
174
|
-
[
|
|
175
|
-
"-y",
|
|
176
|
-
"skills",
|
|
177
|
-
"add",
|
|
178
|
-
"tw93/Waza",
|
|
179
|
-
"-g",
|
|
180
|
-
"-a",
|
|
181
|
-
...agents,
|
|
182
|
-
"-s",
|
|
183
|
-
...WAZA_SKILLS,
|
|
184
|
-
"-y",
|
|
185
|
-
],
|
|
186
|
-
sourceRoot,
|
|
187
|
-
env,
|
|
188
|
-
);
|
|
189
|
-
return withStepName(step, "configure Waza skills", `target=${target}`);
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
function installMermaidSkill(sourceRoot: string, target: InstallTargetSpec, env?: NodeJS.ProcessEnv): GlobalRuntimeStep {
|
|
193
|
-
const agents = hostAgents(target);
|
|
194
|
-
const step = runProcess(
|
|
195
|
-
"npx",
|
|
196
|
-
[
|
|
197
|
-
"-y",
|
|
198
|
-
"skills",
|
|
199
|
-
"add",
|
|
200
|
-
"BfdCampos/dotfiles",
|
|
201
|
-
"-g",
|
|
202
|
-
"-a",
|
|
203
|
-
...agents,
|
|
204
|
-
"-s",
|
|
205
|
-
"mermaid",
|
|
206
|
-
"-y",
|
|
207
|
-
],
|
|
208
|
-
sourceRoot,
|
|
209
|
-
env,
|
|
210
|
-
);
|
|
211
|
-
return withStepName(step, "configure Mermaid skill", `target=${target}`);
|
|
212
|
-
}
|
|
213
|
-
|
|
214
86
|
function configureBrain(root: string | undefined, env?: NodeJS.ProcessEnv): GlobalRuntimeStep {
|
|
215
87
|
try {
|
|
216
88
|
const selected = root
|
|
@@ -231,86 +103,21 @@ function configureBrain(root: string | undefined, env?: NodeJS.ProcessEnv): Glob
|
|
|
231
103
|
}
|
|
232
104
|
}
|
|
233
105
|
|
|
234
|
-
function ensureCodegraphCli(cwd: string, env?: NodeJS.ProcessEnv): GlobalRuntimeStep {
|
|
235
|
-
const check = runProcess("codegraph", ["--version"], cwd, env);
|
|
236
|
-
if (check.status === "ok") return withStepName(check, "ensure CodeGraph CLI", "present");
|
|
237
|
-
const install = commandAvailable("bun", cwd, env)
|
|
238
|
-
? runProcess("bun", ["add", "-g", CODEGRAPH_PACKAGE], cwd, env)
|
|
239
|
-
: runProcess("npm", ["install", "-g", CODEGRAPH_PACKAGE, "--omit=optional", "--no-audit", "--no-fund"], cwd, env);
|
|
240
|
-
if (install.status !== "ok") return withStepName(install, "ensure CodeGraph CLI", CODEGRAPH_PACKAGE);
|
|
241
|
-
const recheck = runProcess("codegraph", ["--version"], cwd, env);
|
|
242
|
-
if (recheck.status === "ok") return withStepName(recheck, "ensure CodeGraph CLI", "installed");
|
|
243
|
-
return {
|
|
244
|
-
...recheck,
|
|
245
|
-
step: "ensure CodeGraph CLI",
|
|
246
|
-
status: "failed",
|
|
247
|
-
detail: `${CODEGRAPH_PACKAGE} installed, but codegraph is not on PATH`,
|
|
248
|
-
};
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
function configureCodegraphMcp(cwd: string, target: InstallTargetSpec, env?: NodeJS.ProcessEnv): GlobalRuntimeStep {
|
|
252
|
-
try {
|
|
253
|
-
const result = configureCodegraph({ repoRoot: cwd, target, location: "global", env });
|
|
254
|
-
return {
|
|
255
|
-
step: "configure CodeGraph MCP",
|
|
256
|
-
status: result.actions.some((entry) => entry.status === "failed") ? "failed" : "ok",
|
|
257
|
-
detail: result.actions.map((entry) => `${entry.action}:${entry.status}`).join(", "),
|
|
258
|
-
};
|
|
259
|
-
} catch (error) {
|
|
260
|
-
return {
|
|
261
|
-
step: "configure CodeGraph MCP",
|
|
262
|
-
status: "failed",
|
|
263
|
-
stderr: String((error as Error).message ?? error),
|
|
264
|
-
};
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
|
|
268
106
|
export function runGlobalRuntimeSetup(opts: GlobalRuntimeOptions = {}): GlobalRuntimeResult {
|
|
269
107
|
const sourceRoot = opts.sourceRoot ?? defaultSourceRoot();
|
|
270
108
|
const cwd = opts.cwd ?? process.cwd();
|
|
271
109
|
const target = opts.target ?? "both";
|
|
272
|
-
const env =
|
|
273
|
-
const platform = opts.platform ?? process.platform;
|
|
110
|
+
const env = opts.env;
|
|
274
111
|
const steps: GlobalRuntimeStep[] = [];
|
|
275
112
|
|
|
276
113
|
if (opts.installCli !== false) steps.push(installCli(sourceRoot, cwd, env, opts.installSpec));
|
|
277
114
|
else steps.push({ step: "install forge CLI", status: "skipped", detail: "disabled" });
|
|
278
115
|
|
|
279
|
-
if (opts.syncSkill !== false) steps.push(syncRuntimeSkill(sourceRoot, env, platform));
|
|
280
|
-
else steps.push({ step: "sync forge skill runtime", status: "skipped", detail: "disabled" });
|
|
281
|
-
|
|
282
116
|
if (opts.hostAdapters !== false) steps.push(installHostAdapters(target, env));
|
|
283
117
|
else steps.push({ step: "install host adapters", status: "skipped", detail: "disabled" });
|
|
284
118
|
|
|
285
|
-
if (opts.externalSkills !== false) {
|
|
286
|
-
steps.push(installWazaSkills(sourceRoot, target, env));
|
|
287
|
-
steps.push(installMermaidSkill(sourceRoot, target, env));
|
|
288
|
-
steps.push(...syncCrossReviewSkills(sourceRoot, target, env));
|
|
289
|
-
} else {
|
|
290
|
-
steps.push({ step: "configure Waza skills", status: "skipped", detail: "disabled" });
|
|
291
|
-
steps.push({ step: "configure Mermaid skill", status: "skipped", detail: "disabled" });
|
|
292
|
-
steps.push({ step: "cross-review skills", status: "skipped", detail: "disabled" });
|
|
293
|
-
}
|
|
294
|
-
|
|
295
119
|
steps.push(configureBrain(opts.brainRoot, env));
|
|
296
120
|
|
|
297
|
-
if (platform === "win32" && opts.codegraph !== false) {
|
|
298
|
-
steps.push({
|
|
299
|
-
step: "ensure CodeGraph CLI",
|
|
300
|
-
status: "skipped",
|
|
301
|
-
detail: "native Windows automatic CodeGraph setup is not release-validated; use WSL2 or configure it manually",
|
|
302
|
-
});
|
|
303
|
-
steps.push({ step: "configure CodeGraph MCP", status: "skipped", detail: "native Windows default" });
|
|
304
|
-
} else if (opts.codegraph !== false) {
|
|
305
|
-
const ensure = ensureCodegraphCli(cwd, env);
|
|
306
|
-
steps.push(ensure);
|
|
307
|
-
if (ensure.status === "ok") steps.push(configureCodegraphMcp(cwd, target, env));
|
|
308
|
-
else steps.push({ step: "configure CodeGraph MCP", status: "skipped", detail: "CodeGraph CLI install failed" });
|
|
309
|
-
} else {
|
|
310
|
-
steps.push({ step: "ensure CodeGraph CLI", status: "skipped", detail: "disabled" });
|
|
311
|
-
steps.push({ step: "configure CodeGraph MCP", status: "skipped", detail: "disabled" });
|
|
312
|
-
}
|
|
313
|
-
|
|
314
121
|
const lines = steps.flatMap(renderStep);
|
|
315
122
|
const failed = steps.some((step) => step.status === "failed");
|
|
316
123
|
return {
|
|
@@ -15,6 +15,7 @@ import { dirname, join, resolve } from 'path';
|
|
|
15
15
|
import { fileURLToPath } from 'url';
|
|
16
16
|
import { Command } from 'commander';
|
|
17
17
|
import { runDoctor, type CheckStatus, type DoctorReport } from './doctor';
|
|
18
|
+
import { withProcessEnv } from './setup-execution';
|
|
18
19
|
import { runStatus, type StatusReport } from './status';
|
|
19
20
|
import { runMcpSetupChatgpt } from '../../../adapters/mcp/setup';
|
|
20
21
|
import { resolveControllerHome } from '../repositories/controller-home';
|
|
@@ -124,24 +125,6 @@ const UPDATE_CHECK_ENV = 'FORGE_CHECK_UPDATES';
|
|
|
124
125
|
const GLOBAL_RULES_BEGIN = '<!-- BEGIN: forge global-working-rules -->';
|
|
125
126
|
const VALID_TARGETS: readonly InitHookTarget[] = ['none', 'codex', 'claude', 'both'];
|
|
126
127
|
|
|
127
|
-
function withProcessEnv<T>(env: NodeJS.ProcessEnv | undefined, fn: () => T): T {
|
|
128
|
-
if (!env) return fn();
|
|
129
|
-
const previous = new Map<string, string | undefined>();
|
|
130
|
-
for (const [key, value] of Object.entries(env)) {
|
|
131
|
-
previous.set(key, process.env[key]);
|
|
132
|
-
if (value === undefined) delete process.env[key];
|
|
133
|
-
else process.env[key] = value;
|
|
134
|
-
}
|
|
135
|
-
try {
|
|
136
|
-
return fn();
|
|
137
|
-
} finally {
|
|
138
|
-
for (const [key, value] of previous) {
|
|
139
|
-
if (value === undefined) delete process.env[key];
|
|
140
|
-
else process.env[key] = value;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
128
|
function selectedTargets(target: InitHookTarget): Array<'codex' | 'claude'> {
|
|
146
129
|
if (target === 'none') return [];
|
|
147
130
|
if (target === 'both') return ['codex', 'claude'];
|
|
@@ -248,12 +231,12 @@ function parseActionCommand(detail: string): string | undefined {
|
|
|
248
231
|
function doctorEntryRelevant(id: string, target: InitHookTarget): boolean {
|
|
249
232
|
if (id === 'cli-on-path' || id === 'cli-version' || id === 'cli-update' || id === 'security-config') return true;
|
|
250
233
|
if (target === 'none') return false;
|
|
251
|
-
if (id === 'repo-hook-scripts'
|
|
234
|
+
if (id === 'repo-hook-scripts') return true;
|
|
252
235
|
if (target === 'codex' || target === 'both') {
|
|
253
|
-
if (id === 'codex-adapter' || id === 'codex-trust-state'
|
|
236
|
+
if (id === 'codex-adapter' || id === 'codex-trust-state') return true;
|
|
254
237
|
}
|
|
255
238
|
if (target === 'claude' || target === 'both') {
|
|
256
|
-
if (id === 'claude-adapter'
|
|
239
|
+
if (id === 'claude-adapter') return true;
|
|
257
240
|
}
|
|
258
241
|
return false;
|
|
259
242
|
}
|
|
@@ -296,7 +279,7 @@ function doctorChecks(
|
|
|
296
279
|
verification: 'forge security scan --json',
|
|
297
280
|
});
|
|
298
281
|
} else if (
|
|
299
|
-
|
|
282
|
+
entry.id === 'repo-hook-scripts' &&
|
|
300
283
|
(entry.status === 'warn' || entry.status === 'fail')
|
|
301
284
|
) {
|
|
302
285
|
const command = parseActionCommand(entry.detail);
|
|
@@ -454,7 +437,7 @@ function commandForToolGap(toolName: string, tool: ToolingTool, target: InitHook
|
|
|
454
437
|
return normalizeToolCommand(tool.install_command, target);
|
|
455
438
|
}
|
|
456
439
|
if (toolName === 'codex_automation_profile') {
|
|
457
|
-
return 'forge install --target codex --no-cli --no-hooks
|
|
440
|
+
return 'forge install --target codex --no-cli --no-hooks';
|
|
458
441
|
}
|
|
459
442
|
return normalizeToolCommand(
|
|
460
443
|
tool.sync_command ?? tool.ensure_command ?? tool.mcp_install_command ?? tool.install_command ?? tool.upgrade_command,
|
package/src/cli/commands/init.ts
CHANGED
|
@@ -10,12 +10,10 @@ import { createInterface } from "readline/promises";
|
|
|
10
10
|
import { stdin, stdout } from "process";
|
|
11
11
|
import { homedir } from "os";
|
|
12
12
|
import {
|
|
13
|
-
cpSync,
|
|
14
13
|
existsSync,
|
|
15
14
|
mkdirSync,
|
|
16
15
|
readFileSync,
|
|
17
16
|
realpathSync,
|
|
18
|
-
rmSync,
|
|
19
17
|
writeFileSync,
|
|
20
18
|
} from "fs";
|
|
21
19
|
import { dirname, join, resolve } from "path";
|
|
@@ -28,12 +26,11 @@ import {
|
|
|
28
26
|
expandHomePath,
|
|
29
27
|
type BrainRootChoice,
|
|
30
28
|
} from "./brain-root";
|
|
31
|
-
import { configureCodegraph, ensureCodegraph } from "../tools/codegraph";
|
|
32
29
|
import { runProcess as runBoundedProcess } from "../../effects/process-runner";
|
|
30
|
+
import { runSetupProcess as runProcess, withProcessEnv, type SetupExecutionStep } from './setup-execution';
|
|
33
31
|
|
|
34
32
|
const SCRIPT_DIR = dirname(fileURLToPath(import.meta.url));
|
|
35
33
|
const REPO_ROOT = resolve(SCRIPT_DIR, "..", "..", "..");
|
|
36
|
-
const WAZA_SKILLS = ["think", "hunt", "check", "health"];
|
|
37
34
|
const GBRAIN_INSTALL_ARGS = ["install", "-g", "github:garrytan/gbrain"] as const;
|
|
38
35
|
const GLOBAL_RULES_BEGIN = "<!-- BEGIN: forge global-working-rules -->";
|
|
39
36
|
const GLOBAL_RULES_END = "<!-- END: forge global-working-rules -->";
|
|
@@ -45,30 +42,12 @@ export interface GlobalContextOptions {
|
|
|
45
42
|
reportLanguageInstruction: string;
|
|
46
43
|
}
|
|
47
44
|
|
|
48
|
-
/**
|
|
49
|
-
* Cross-review skills bundled in this package under `assets/skills/<skill>` and
|
|
50
|
-
* installed host-aware: `codex-review` (Claude host) lets a Claude session get an
|
|
51
|
-
* independent Codex review; `claude-review` (Codex host) lets a Codex session get
|
|
52
|
-
* an independent Claude review. They are self-contained (no gstack runtime), so
|
|
53
|
-
* init bootstraps them as workflow-owned runtime skills alongside Waza and
|
|
54
|
-
* Mermaid, not as an unrelated plugin marketplace stack.
|
|
55
|
-
*/
|
|
56
|
-
const CROSS_REVIEW_SKILLS: ReadonlyArray<{ skill: string; host: "claude" | "codex" }> = [
|
|
57
|
-
{ skill: "codex-review", host: "claude" },
|
|
58
|
-
{ skill: "claude-review", host: "codex" },
|
|
59
|
-
];
|
|
60
|
-
|
|
61
45
|
export interface InitCommandOptions {
|
|
62
46
|
repo?: string;
|
|
63
47
|
sourceRoot?: string;
|
|
64
48
|
apply?: boolean;
|
|
65
49
|
verify?: boolean;
|
|
66
|
-
syncSkill?: boolean;
|
|
67
50
|
hostAdapters?: boolean;
|
|
68
|
-
externalSkills?: boolean;
|
|
69
|
-
codegraph?: boolean;
|
|
70
|
-
configureCodegraphMcp?: boolean;
|
|
71
|
-
syncCodegraph?: boolean;
|
|
72
51
|
globalContext?: GlobalContextOptions;
|
|
73
52
|
brainRoot?: string;
|
|
74
53
|
brainMode?: InitBrainMode;
|
|
@@ -76,14 +55,7 @@ export interface InitCommandOptions {
|
|
|
76
55
|
env?: NodeJS.ProcessEnv;
|
|
77
56
|
}
|
|
78
57
|
|
|
79
|
-
export
|
|
80
|
-
step: string;
|
|
81
|
-
status: "ok" | "skipped" | "failed";
|
|
82
|
-
command?: string[];
|
|
83
|
-
detail?: string;
|
|
84
|
-
stdout?: string;
|
|
85
|
-
stderr?: string;
|
|
86
|
-
}
|
|
58
|
+
export type InitStep = SetupExecutionStep;
|
|
87
59
|
|
|
88
60
|
export interface InitCommandResult {
|
|
89
61
|
exitCode: number;
|
|
@@ -103,28 +75,6 @@ interface Choice<T> {
|
|
|
103
75
|
detail?: string;
|
|
104
76
|
}
|
|
105
77
|
|
|
106
|
-
function runProcess(command: string, args: string[], cwd: string, env?: NodeJS.ProcessEnv): InitStep {
|
|
107
|
-
const result = runBoundedProcess(command, args, { cwd, env });
|
|
108
|
-
|
|
109
|
-
return {
|
|
110
|
-
step: "",
|
|
111
|
-
status: result.ok ? "ok" : "failed",
|
|
112
|
-
command: [...result.command],
|
|
113
|
-
stdout: result.stdout,
|
|
114
|
-
stderr: result.stderr || result.error,
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
function isNpxCacheSource(sourceRoot: string): boolean {
|
|
119
|
-
return /[\\/]_npx[\\/]/.test(sourceRoot);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
function initCommandEnv(sourceRoot: string, env?: NodeJS.ProcessEnv): NodeJS.ProcessEnv | undefined {
|
|
123
|
-
if (!isNpxCacheSource(sourceRoot)) return env;
|
|
124
|
-
if (env?.AGENTIC_DEV_LINK_INSTALLED_COPIES !== undefined) return env;
|
|
125
|
-
return { ...(env ?? {}), AGENTIC_DEV_LINK_INSTALLED_COPIES: "0" };
|
|
126
|
-
}
|
|
127
|
-
|
|
128
78
|
function withStepName(step: InitStep, name: string, detail?: string): InitStep {
|
|
129
79
|
return { ...step, step: name, detail: detail ?? step.detail };
|
|
130
80
|
}
|
|
@@ -137,24 +87,6 @@ function renderStep(step: InitStep): string[] {
|
|
|
137
87
|
return lines;
|
|
138
88
|
}
|
|
139
89
|
|
|
140
|
-
function withProcessEnv<T>(env: NodeJS.ProcessEnv | undefined, fn: () => T): T {
|
|
141
|
-
if (!env) return fn();
|
|
142
|
-
const previous = new Map<string, string | undefined>();
|
|
143
|
-
for (const [key, value] of Object.entries(env)) {
|
|
144
|
-
previous.set(key, process.env[key]);
|
|
145
|
-
if (value === undefined) delete process.env[key];
|
|
146
|
-
else process.env[key] = value;
|
|
147
|
-
}
|
|
148
|
-
try {
|
|
149
|
-
return fn();
|
|
150
|
-
} finally {
|
|
151
|
-
for (const [key, value] of previous) {
|
|
152
|
-
if (value === undefined) delete process.env[key];
|
|
153
|
-
else process.env[key] = value;
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
90
|
function hostAgents(target: InstallTargetSpec): string[] {
|
|
159
91
|
if (target === "codex") return ["codex"];
|
|
160
92
|
if (target === "claude") return ["claude-code"];
|
|
@@ -282,111 +214,13 @@ export function writeGlobalContextFiles(
|
|
|
282
214
|
return { step: "global working rules", status: "ok", detail: changes.join(", ") };
|
|
283
215
|
}
|
|
284
216
|
|
|
285
|
-
/**
|
|
286
|
-
* Install the bundled cross-review skills, each into the host where it is useful:
|
|
287
|
-
* `codex-review` → `~/.claude/skills` (Claude calls Codex), `claude-review` →
|
|
288
|
-
* `~/.codex/skills` (Codex calls Claude). Respects `target`, is idempotent
|
|
289
|
-
* (identical SKILL.md → "already present"), and treats a missing bundled source
|
|
290
|
-
* as `skipped` (never fails init).
|
|
291
|
-
*/
|
|
292
|
-
export function syncCrossReviewSkills(
|
|
293
|
-
sourceRoot: string,
|
|
294
|
-
target: InstallTargetSpec,
|
|
295
|
-
env?: NodeJS.ProcessEnv,
|
|
296
|
-
): InitStep[] {
|
|
297
|
-
const home = homeDir(env);
|
|
298
|
-
const steps: InitStep[] = [];
|
|
299
|
-
for (const { skill, host } of CROSS_REVIEW_SKILLS) {
|
|
300
|
-
const step = `cross-review skill ${skill}`;
|
|
301
|
-
if (target !== "both" && target !== host) continue;
|
|
302
|
-
if (!home) {
|
|
303
|
-
steps.push({ step, status: "failed", detail: "HOME is required to resolve host skill roots" });
|
|
304
|
-
continue;
|
|
305
|
-
}
|
|
306
|
-
const source = join(sourceRoot, "assets", "skills", skill);
|
|
307
|
-
const srcSkill = join(source, "SKILL.md");
|
|
308
|
-
if (!existsSync(srcSkill)) {
|
|
309
|
-
steps.push({ step, status: "skipped", detail: `bundled source not found at ${source}` });
|
|
310
|
-
continue;
|
|
311
|
-
}
|
|
312
|
-
const root = join(home, host === "claude" ? ".claude" : ".codex", "skills");
|
|
313
|
-
const dest = join(root, skill);
|
|
314
|
-
const destSkill = join(dest, "SKILL.md");
|
|
315
|
-
mkdirSync(root, { recursive: true });
|
|
316
|
-
if (
|
|
317
|
-
existsSync(dest) &&
|
|
318
|
-
(samePath(source, dest) ||
|
|
319
|
-
(existsSync(destSkill) && readFileSync(destSkill, "utf-8") === readFileSync(srcSkill, "utf-8")))
|
|
320
|
-
) {
|
|
321
|
-
steps.push({ step, status: "ok", detail: "already present" });
|
|
322
|
-
continue;
|
|
323
|
-
}
|
|
324
|
-
if (existsSync(dest)) {
|
|
325
|
-
rmSync(dest, { recursive: true, force: true });
|
|
326
|
-
}
|
|
327
|
-
cpSync(source, dest, { recursive: true });
|
|
328
|
-
steps.push({ step, status: "ok", detail: `synced ${dest}` });
|
|
329
|
-
}
|
|
330
|
-
return steps;
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
function installExternalSkills(sourceRoot: string, target: InstallTargetSpec, env?: NodeJS.ProcessEnv): InitStep[] {
|
|
334
|
-
const steps: InitStep[] = [];
|
|
335
|
-
const agents = hostAgents(target);
|
|
336
|
-
const waza = runProcess(
|
|
337
|
-
"npx",
|
|
338
|
-
[
|
|
339
|
-
"-y",
|
|
340
|
-
"skills",
|
|
341
|
-
"add",
|
|
342
|
-
"tw93/Waza",
|
|
343
|
-
"-g",
|
|
344
|
-
"-a",
|
|
345
|
-
...agents,
|
|
346
|
-
"-s",
|
|
347
|
-
...WAZA_SKILLS,
|
|
348
|
-
"-y",
|
|
349
|
-
],
|
|
350
|
-
sourceRoot,
|
|
351
|
-
env,
|
|
352
|
-
);
|
|
353
|
-
steps.push(withStepName(waza, "external skills Waza", `target=${target}`));
|
|
354
|
-
const mermaid = runProcess(
|
|
355
|
-
"npx",
|
|
356
|
-
[
|
|
357
|
-
"-y",
|
|
358
|
-
"skills",
|
|
359
|
-
"add",
|
|
360
|
-
"BfdCampos/dotfiles",
|
|
361
|
-
"-g",
|
|
362
|
-
"-a",
|
|
363
|
-
...agents,
|
|
364
|
-
"-s",
|
|
365
|
-
"mermaid",
|
|
366
|
-
"-y",
|
|
367
|
-
],
|
|
368
|
-
sourceRoot,
|
|
369
|
-
env,
|
|
370
|
-
);
|
|
371
|
-
steps.push(withStepName(mermaid, "external skill mermaid", `target=${target}`));
|
|
372
|
-
steps.push(...syncCrossReviewSkills(sourceRoot, target, env));
|
|
373
|
-
return steps;
|
|
374
|
-
}
|
|
375
|
-
|
|
376
217
|
export function runInit(opts: InitCommandOptions = {}): InitCommandResult {
|
|
377
218
|
const sourceRoot = resolve(opts.sourceRoot ?? REPO_ROOT);
|
|
378
219
|
const repoRoot = resolve(opts.repo ?? process.cwd());
|
|
379
|
-
let commandEnv =
|
|
220
|
+
let commandEnv = opts.env;
|
|
380
221
|
const apply = opts.apply !== false;
|
|
381
222
|
const verify = opts.verify !== false;
|
|
382
|
-
const syncSkill = opts.syncSkill !== false;
|
|
383
223
|
const hostAdapters = opts.hostAdapters !== false;
|
|
384
|
-
const externalSkills = opts.externalSkills === true;
|
|
385
|
-
const configureCgMcp = opts.configureCodegraphMcp === true;
|
|
386
|
-
const syncCodegraph = opts.syncCodegraph === true;
|
|
387
|
-
// CodeGraph is an optional rebuildable tool cache. Ordinary adoption leaves it
|
|
388
|
-
// disabled; any explicit CodeGraph operation opts in and uses the Controller Home-backed compatibility link.
|
|
389
|
-
const codegraph = opts.codegraph === true || configureCgMcp || syncCodegraph;
|
|
390
224
|
const brainMode = opts.brainMode ?? "skip";
|
|
391
225
|
const target = opts.target ?? "both";
|
|
392
226
|
const steps: InitStep[] = [];
|
|
@@ -406,17 +240,6 @@ export function runInit(opts: InitCommandOptions = {}): InitCommandResult {
|
|
|
406
240
|
};
|
|
407
241
|
}
|
|
408
242
|
|
|
409
|
-
if (syncSkill && apply) {
|
|
410
|
-
const step = runProcess("bash", [join(sourceRoot, "scripts", "sync-codex-installed-copies.sh")], sourceRoot, commandEnv);
|
|
411
|
-
steps.push(withStepName(step, "sync forge skills", `target=${target}`));
|
|
412
|
-
} else {
|
|
413
|
-
steps.push({
|
|
414
|
-
step: "sync forge skills",
|
|
415
|
-
status: "skipped",
|
|
416
|
-
detail: syncSkill ? "dry-run" : "disabled",
|
|
417
|
-
});
|
|
418
|
-
}
|
|
419
|
-
|
|
420
243
|
if (hostAdapters && apply) {
|
|
421
244
|
const installed = withProcessEnv(commandEnv, () => runInstall({ target, location: "global" }));
|
|
422
245
|
steps.push({
|
|
@@ -463,74 +286,6 @@ export function runInit(opts: InitCommandOptions = {}): InitCommandResult {
|
|
|
463
286
|
);
|
|
464
287
|
steps.push(withStepName(migrate, apply ? "apply Forge" : "plan Forge", repoRoot));
|
|
465
288
|
|
|
466
|
-
if (externalSkills && apply && migrate.status === "ok") {
|
|
467
|
-
steps.push(...installExternalSkills(sourceRoot, target, commandEnv));
|
|
468
|
-
} else {
|
|
469
|
-
steps.push({
|
|
470
|
-
step: "external skills",
|
|
471
|
-
status: "skipped",
|
|
472
|
-
detail: !externalSkills
|
|
473
|
-
? "disabled"
|
|
474
|
-
: apply
|
|
475
|
-
? "Forge did not apply cleanly"
|
|
476
|
-
: "dry-run",
|
|
477
|
-
});
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
if (codegraph && apply) {
|
|
481
|
-
try {
|
|
482
|
-
const cg = ensureCodegraph({ repoRoot, init: true, sync: syncCodegraph, env: commandEnv, host: target });
|
|
483
|
-
const cgFailed = cg.actions.some((entry) => entry.status === "failed");
|
|
484
|
-
steps.push({
|
|
485
|
-
step: "ensure codegraph index",
|
|
486
|
-
status: cg.actions.length === 0 ? "skipped" : cgFailed ? "failed" : "ok",
|
|
487
|
-
detail:
|
|
488
|
-
cg.resolution.source === "missing"
|
|
489
|
-
? "codegraph CLI not found; skipped (install via: forge tools ensure codegraph)"
|
|
490
|
-
: cg.actions.length > 0
|
|
491
|
-
? cg.actions.map((entry) => `${entry.action}:${entry.status}`).join(", ")
|
|
492
|
-
: `index ${cg.status}`,
|
|
493
|
-
});
|
|
494
|
-
|
|
495
|
-
const mcpHosts =
|
|
496
|
-
(cg.raw as { mcp_hosts?: Record<string, { status?: string }> }).mcp_hosts ?? {};
|
|
497
|
-
const mcpConfigured =
|
|
498
|
-
cg.resolution.source !== "missing" &&
|
|
499
|
-
["codex", "claude"].every((host) => mcpHosts[host]?.status === "configured");
|
|
500
|
-
|
|
501
|
-
if (cg.resolution.source !== "missing" && !mcpConfigured) {
|
|
502
|
-
if (configureCgMcp) {
|
|
503
|
-
const conf = configureCodegraph({ repoRoot, target, location: "global", env: commandEnv });
|
|
504
|
-
steps.push({
|
|
505
|
-
step: "configure codegraph mcp",
|
|
506
|
-
status: conf.actions.some((entry) => entry.status === "failed") ? "failed" : "ok",
|
|
507
|
-
detail: conf.actions.map((entry) => `${entry.action}:${entry.status}`).join(", "),
|
|
508
|
-
});
|
|
509
|
-
} else {
|
|
510
|
-
steps.push({
|
|
511
|
-
step: "codegraph mcp",
|
|
512
|
-
status: "skipped",
|
|
513
|
-
detail:
|
|
514
|
-
"not registered; run: forge tools configure codegraph --target both --location global",
|
|
515
|
-
});
|
|
516
|
-
}
|
|
517
|
-
}
|
|
518
|
-
} catch (error) {
|
|
519
|
-
steps.push({
|
|
520
|
-
step: "ensure codegraph index",
|
|
521
|
-
status: "failed",
|
|
522
|
-
detail: "CodeGraph readiness check failed",
|
|
523
|
-
stderr: error instanceof Error ? error.message : String(error),
|
|
524
|
-
});
|
|
525
|
-
}
|
|
526
|
-
} else {
|
|
527
|
-
steps.push({
|
|
528
|
-
step: "ensure codegraph index",
|
|
529
|
-
status: "skipped",
|
|
530
|
-
detail: codegraph ? "dry-run" : "disabled",
|
|
531
|
-
});
|
|
532
|
-
}
|
|
533
|
-
|
|
534
289
|
if (brainMode !== "skip" && apply && migrate.status === "ok") {
|
|
535
290
|
const root = opts.brainRoot ?? commandEnv?.FORGE_BRAIN_ROOT;
|
|
536
291
|
if (root) {
|
|
@@ -795,7 +550,6 @@ export async function runInteractiveInit(opts: InteractiveInitOptions = {}): Pro
|
|
|
795
550
|
`reporting=${reportLanguageInstruction}`,
|
|
796
551
|
`brainRoot=${resolvedBrainChoice.root}`,
|
|
797
552
|
`brainMode=${brainMode}`,
|
|
798
|
-
"CodeGraph=required ensure --init --sync plus global MCP configure",
|
|
799
553
|
`apply=${opts.apply === false ? "false" : "true"}`,
|
|
800
554
|
`verify=${opts.verify === false ? "false" : "true"}`,
|
|
801
555
|
]));
|
|
@@ -817,9 +571,6 @@ export async function runInteractiveInit(opts: InteractiveInitOptions = {}): Pro
|
|
|
817
571
|
repo: repoRoot,
|
|
818
572
|
sourceRoot,
|
|
819
573
|
target,
|
|
820
|
-
codegraph: true,
|
|
821
|
-
configureCodegraphMcp: true,
|
|
822
|
-
syncCodegraph: true,
|
|
823
574
|
globalContext: { reportLanguageInstruction },
|
|
824
575
|
brainRoot: resolvedBrainChoice.root,
|
|
825
576
|
brainMode,
|