@moretea-labs/forge 1.6.0 → 1.7.1
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 +4 -0
- package/CHANGELOG.md +39 -0
- package/CLAUDE.md +4 -0
- package/README.md +2 -2
- package/README.zh-CN.md +1 -1
- package/SKILL.md +2 -2
- package/THIRD_PARTY_NOTICES.md +1 -1
- package/agents/openai.yaml +1 -1
- package/assets/hooks/hook-input.sh +11 -8
- package/assets/hooks/lib/session-state.sh +10 -7
- package/assets/hooks/lib/workflow-state.sh +13 -177
- package/assets/hooks/post-tool-observer.sh +8 -2
- package/assets/hooks/prompt-guard.sh +5 -81
- package/assets/hooks/session-start-context.sh +56 -1
- package/assets/partials/05-workflow.partial.md +1 -1
- package/assets/partials-agents/02-operating-mode.partial.md +2 -0
- package/assets/partials-agents/03-orchestration.partial.md +1 -1
- package/assets/plugin-registry.v1.json +3 -3
- package/assets/reference-configs/document-generation.md +1 -1
- package/assets/reference-configs/harness-overview.md +1 -1
- package/assets/reference-configs/sprint-contracts.md +3 -3
- package/assets/skill-version.json +2 -2
- package/assets/templates/contract.template.md +2 -7
- package/assets/templates/helpers/capture-plan.sh +2 -2
- package/assets/templates/helpers/check-architecture-sync.sh +17 -0
- package/assets/templates/helpers/check-task-workflow.sh +4 -4
- package/assets/templates/helpers/contract-worktree.sh +1 -21
- package/assets/templates/helpers/ensure-task-workflow.sh +11 -36
- package/assets/templates/helpers/inspect-project-state.ts +8 -6
- package/assets/templates/helpers/migrate-project-template.sh +22 -45
- package/assets/templates/helpers/migrate-workflow-docs.ts +9 -7
- package/assets/templates/helpers/new-plan.sh +1 -1
- package/assets/templates/helpers/plan-to-todo.sh +12 -37
- package/assets/templates/helpers/ship-worktrees.sh +2 -29
- package/assets/templates/helpers/verify-contract.sh +1 -111
- package/assets/templates/helpers/verify-sprint.sh +3 -180
- package/assets/templates/helpers/workflow-contract.ts +5 -1
- package/assets/templates/plan.template.md +1 -1
- package/assets/templates/review.template.md +9 -34
- package/assets/workflow-contract.v1.json +10 -19
- package/docs/README.md +10 -10
- package/docs/architecture/CURRENT.md +178 -0
- package/docs/architecture/EVOLUTION.md +42 -0
- package/docs/architecture/current/README.md +4 -156
- package/docs/architecture/decisions/20260803-release-identity-binding-and-exit-policy.md +2 -2
- package/docs/architecture/decisions/20260823-immediate-controller-relay.md +53 -0
- package/docs/architecture/decisions/20260826-browser-runtime-v2.md +73 -0
- package/docs/architecture/history/README.md +7 -0
- package/docs/architecture/{chatgpt-handoff-facade.md → history/chatgpt-handoff-facade.md} +4 -0
- package/docs/architecture/{global-hook-runtime.md → history/global-hook-runtime.md} +7 -3
- package/docs/architecture/{ios-semantic-automation-provider-v2.md → history/ios-semantic-automation-provider-v2.md} +6 -2
- package/docs/architecture/history.md +3 -34
- package/docs/architecture/index.md +15 -98
- package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +1 -1
- package/docs/architecture/reviews/2026-08-22-semantic-harness-convergence-acceptance.md +39 -0
- package/docs/architecture/versions/1.6.md +38 -0
- package/docs/architecture/versions/1.7.md +41 -0
- package/docs/forge-chatgpt-browser-engine.md +2 -2
- package/docs/forge-chatgpt-mcp-setup.md +4 -28
- package/docs/forge-chatgpt-supervised-automation.md +3 -3
- package/docs/forge-github-issue-launcher.md +1 -1
- package/docs/forge-plugin-management.md +1 -1
- package/docs/forge-runtime-self-healing-loop.md +1 -1
- package/docs/operations/controller-browser-plugin.md +26 -6
- package/docs/operations/controller-performance-and-502.md +143 -0
- package/docs/operations/controller-reliability-runbook.md +1 -1
- package/docs/operations/features.md +2 -2
- package/docs/operations/github-repository.md +1 -1
- package/docs/operations/homebrew.md +2 -2
- package/docs/operations/mcp-tool-exposure.md +5 -3
- package/docs/wiki/Architecture.md +6 -6
- package/docs/wiki/Implementation.md +2 -2
- package/docs/wiki/Integrations.md +2 -2
- package/docs/wiki/Work-Lifecycle.md +1 -1
- package/package.json +33 -11
- package/scripts/activate-source-baseline.ts +17 -13
- package/scripts/architecture-event.ts +2 -820
- package/scripts/architecture-queue.sh +2 -645
- package/scripts/archive-architecture-request.sh +2 -242
- package/scripts/archive-workflow.sh +1 -291
- package/scripts/benchmark-background-check-overlap.ts +228 -0
- package/scripts/benchmark-mcp-host.sh +117 -0
- package/scripts/benchmark-mcp-transport.ts +170 -0
- package/scripts/benchmark-quality-harness.ts +146 -0
- package/scripts/benchmark-route-session-concurrency.ts +207 -6
- package/scripts/benchmark-thin-harness-mcp-e2e.ts +7 -1
- package/scripts/benchmark-typescript-navigation.ts +186 -0
- package/scripts/benchmark-work-efficiency.ts +334 -0
- package/scripts/capability-config.ts +2 -392
- package/scripts/capability-resolver.ts +2 -503
- package/scripts/capture-plan.sh +1 -332
- package/scripts/check-agent-tooling.sh +2 -1558
- package/scripts/check-architecture-sync.sh +2 -371
- package/scripts/check-brain-manifest.sh +2 -253
- package/scripts/check-context-files.sh +2 -47
- package/scripts/check-deploy-sql-order.sh +2 -115
- package/scripts/check-mcp-compatibility.ts +14 -0
- package/scripts/check-runtime-architecture.mjs +349 -79
- package/scripts/check-skill-version.ts +3 -191
- package/scripts/check-source-duplication.mjs +61 -0
- package/scripts/check-stable-baseline.ts +92 -0
- package/scripts/check-task-sync.sh +2 -63
- package/scripts/check-task-workflow.sh +2 -1000
- package/scripts/codex-handoff-resume.sh +2 -267
- package/scripts/context-contract-sync.sh +2 -514
- package/scripts/contract-run.ts +2 -463
- package/scripts/contract-worktree.sh +1 -722
- package/scripts/ensure-task-workflow.sh +1 -1225
- package/scripts/host-temporary-cloud-mcp-e2e.sh +265 -0
- package/scripts/inspect-project-state.ts +4 -279
- package/scripts/install-standalone-recovery.ts +24 -0
- package/scripts/lib/project-init-lib.sh +22 -46
- package/scripts/lib/run-forge-helper.sh +19 -0
- package/scripts/lib/run-forge-helper.ts +26 -0
- package/scripts/migrate-project-template.sh +1 -1189
- package/scripts/migrate-workflow-docs.ts +4 -412
- package/scripts/new-plan.sh +1 -180
- package/scripts/new-spec.sh +1 -47
- package/scripts/new-sprint.sh +1 -46
- package/scripts/plan-to-todo.sh +1 -796
- package/scripts/prepare-codex-handoff.sh +2 -201
- package/scripts/prepare-handoff.sh +1 -78
- package/scripts/refresh-current-status.sh +2 -467
- package/scripts/run-governed-gate.ts +5 -1
- package/scripts/select-agent-context-blocks.sh +2 -64
- package/scripts/ship-worktrees.sh +1 -558
- package/scripts/smoke-ios-physical-device.ts +4 -2
- package/scripts/smoke-runtime-recovery.ts +1 -35
- package/scripts/smoke-schedule-engine.ts +1 -20
- package/scripts/sprint-backlog.sh +1 -834
- package/scripts/stage-runtime-release.ts +2 -1
- package/scripts/summarize-failures.sh +2 -123
- package/scripts/switch-plan.sh +1 -150
- package/scripts/sync-brain-docs.sh +2 -379
- package/scripts/sync-generated-authority.mjs +175 -0
- package/scripts/verify-contract.sh +2 -703
- package/scripts/verify-forge-runtime.sh +0 -1
- package/scripts/verify-sprint.sh +1 -677
- package/scripts/workflow-contract.ts +4 -205
- package/scripts/workstream-sync.sh +2 -261
- package/src/cli/agent-jobs/executor-health.ts +1 -1
- package/src/cli/commands/init-hook.ts +3 -3
- package/src/cli/commands/mcp.ts +9 -5
- package/src/cli/commands/plugin.ts +12 -3
- package/src/cli/commands/recovery.ts +25 -3
- package/src/cli/commands/runtime.ts +55 -3
- package/src/cli/commands/security.ts +12 -1
- package/src/cli/commands/setup-profile.ts +31 -21
- package/src/cli/controller/check-runner.ts +113 -5
- package/src/cli/controller/composite-result.ts +1 -1
- package/src/cli/controller/context/focus.ts +51 -0
- package/src/cli/controller/context/instruction-context.ts +114 -0
- package/src/cli/controller/context/known-paths.ts +76 -0
- package/src/cli/controller/context/query-planning.ts +110 -0
- package/src/cli/controller/context/rule-resolution.ts +532 -0
- package/src/cli/controller/context/source-materializer.ts +278 -0
- package/src/cli/controller/context/structural.ts +16 -0
- package/src/cli/controller/context/types.ts +286 -0
- package/src/cli/controller/context-pack.ts +828 -487
- package/src/cli/controller/launch-agents.ts +77 -2
- package/src/cli/controller/operational-plan.ts +2 -2
- package/src/cli/controller/work-mode.ts +6 -4
- package/src/cli/editing/edit-session.ts +60 -7
- package/src/cli/github/contracts.ts +16 -0
- package/src/cli/github/github.ts +135 -16
- package/src/cli/github/session.ts +2 -1
- package/src/cli/installer/managed-entries.ts +15 -1
- package/src/cli/local-bridge/console-automations.ts +54 -78
- package/src/cli/local-bridge/console-view-models.ts +1 -35
- package/src/cli/local-bridge/facade-api.ts +37 -264
- package/src/cli/local-bridge/frontend/src/App.tsx +3 -3
- package/src/cli/local-bridge/frontend/src/features/automations/AutomationsView.tsx +23 -13
- package/src/cli/local-bridge/frontend/src/features/capabilities/CapabilitiesView.tsx +37 -4
- package/src/cli/local-bridge/frontend/src/features/overview/OverviewView.tsx +6 -4
- package/src/cli/local-bridge/frontend/src/lib/api.ts +1 -6
- package/src/cli/local-bridge/frontend/src/lib/routes.ts +1 -1
- package/src/cli/local-bridge/frontend/src/shell/Sidebar.tsx +2 -2
- package/src/cli/local-bridge/frontend/src/styles.css +1 -1
- package/src/cli/local-bridge/frontend/src/types.ts +5 -8
- package/src/cli/local-bridge/job-store.ts +1 -490
- package/src/cli/local-bridge/server.ts +2 -515
- package/src/cli/local-bridge/ui-dist/app.css +1 -1
- package/src/cli/local-bridge/ui-dist/app.js +3703 -3757
- package/src/cli/mcp/auth.ts +5 -5
- package/src/cli/mcp/instructions.ts +3 -2
- package/src/cli/mcp/legacy-tool-service.ts +10 -222
- package/src/cli/mcp/multi-repository.ts +16 -5
- package/src/cli/mcp/oauth.ts +175 -26
- package/src/cli/mcp/post-finalize-work-attribution.ts +150 -0
- package/src/cli/mcp/repository-tools.ts +282 -146
- package/src/cli/mcp/server.ts +586 -116
- package/src/cli/mcp/tool-capability-cache.ts +1 -1
- package/src/cli/mcp/tool-contract.ts +14 -0
- package/src/cli/mcp/toolset-selection.ts +1 -1
- package/src/cli/mcp/toolset.ts +44 -7
- package/src/cli/mcp/transports/http.ts +124 -14
- package/src/cli/mcp/transports/session-registry.ts +43 -5
- package/src/cli/mcp/types.ts +3 -3
- package/src/cli/repositories/command-classifier.ts +103 -21
- package/src/cli/repositories/command-executor.ts +78 -526
- package/src/cli/repositories/command-process.ts +108 -0
- package/src/cli/repositories/command-scope.ts +99 -41
- package/src/cli/repositories/controller-home.ts +7 -8
- package/src/cli/repositories/git-command-executor.ts +2 -0
- package/src/cli/repositories/locks.ts +53 -16
- package/src/cli/repositories/repository-snapshot.ts +124 -0
- package/src/cli/repositories/selected-path-actions.ts +17 -9
- package/src/cli/repositories/structured-git.ts +118 -6
- package/src/cli/repository/inspector.ts +563 -65
- package/src/cli/repository/session-cache.ts +58 -17
- package/src/cli/v81-entry.ts +1 -4
- package/src/effects/fs-transaction.ts +85 -17
- package/src/runtime/context/codegraph-read-provider.ts +233 -2
- package/src/runtime/context/codegraph-sidecar.cjs +74 -40
- package/src/runtime/context/generic-lsp-provider.ts +355 -0
- package/src/runtime/context/lsp-client.ts +283 -0
- package/src/runtime/context/semantic-navigation-contract.ts +61 -0
- package/src/runtime/context/semantic-navigation.ts +223 -0
- package/src/runtime/context/swift-navigation.ts +565 -0
- package/src/runtime/context/typescript-navigation.ts +226 -0
- package/src/runtime/control-plane/dispatch-priority.ts +28 -0
- package/src/runtime/control-plane/execution/direct-edit-work-completion.ts +48 -16
- package/src/runtime/control-plane/execution/edit-validation-coordinator.ts +86 -24
- package/src/runtime/control-plane/execution/repository-work-attribution.ts +106 -0
- package/src/runtime/control-plane/execution/retained-work-resume.ts +203 -0
- package/src/runtime/control-plane/execution/session-store.ts +18 -0
- package/src/runtime/control-plane/execution/verification-evidence.ts +58 -3
- package/src/runtime/control-plane/execution/work-completion-authority.ts +58 -0
- package/src/runtime/control-plane/execution/work-evidence-policy.ts +200 -0
- package/src/runtime/control-plane/execution/work-execution-support.ts +386 -0
- package/src/runtime/control-plane/execution/work-finalization-service.ts +1913 -0
- package/src/runtime/control-plane/execution/work-handle-authority.ts +96 -0
- package/src/runtime/control-plane/execution/work-handle-store.ts +27 -2
- package/src/runtime/control-plane/execution/work-lifecycle-audit.ts +258 -0
- package/src/runtime/control-plane/execution/work-operation-service.ts +468 -0
- package/src/runtime/control-plane/execution/work-path-scope.ts +37 -0
- package/src/runtime/control-plane/execution/work-preparation-service.ts +479 -0
- package/src/runtime/control-plane/execution/work-process-evidence.ts +129 -0
- package/src/runtime/control-plane/execution/work-remote-delivery.ts +215 -0
- package/src/runtime/control-plane/execution/work-task-receipt.ts +22 -18
- package/src/runtime/control-plane/execution/work-terminal-cleanup.ts +156 -11
- package/src/runtime/control-plane/execution/work-validation-reconciler.ts +22 -14
- package/src/runtime/control-plane/execution/work-verification-context.ts +56 -0
- package/src/runtime/control-plane/execution/work-verification-service.ts +388 -0
- package/src/runtime/control-plane/execution/work-verification-snapshot.ts +90 -9
- package/src/runtime/control-plane/facade/capability-registry.ts +129 -25
- package/src/runtime/control-plane/facade/controller-round-relay.ts +1118 -0
- package/src/runtime/control-plane/facade/controller-session-store.ts +302 -12
- package/src/runtime/control-plane/facade/goal-workloop-access.ts +17 -1
- package/src/runtime/control-plane/facade/goal-workloop.ts +928 -190
- package/src/runtime/control-plane/facade/index.ts +3 -0
- package/src/runtime/control-plane/facade/plan-contract-store.ts +275 -42
- package/src/runtime/control-plane/facade/repository-work-admission.ts +147 -0
- package/src/runtime/control-plane/facade/requirement-authority.ts +83 -0
- package/src/runtime/control-plane/facade/semantic-admission.ts +205 -0
- package/src/runtime/control-plane/facade/suggested-actions.ts +5 -1
- package/src/runtime/control-plane/facade/types.ts +90 -10
- package/src/runtime/control-plane/facade/work-contract-store.ts +157 -261
- package/src/runtime/control-plane/facade/work-state-machine.ts +250 -0
- package/src/runtime/control-plane/generated-cache-retention.ts +271 -0
- package/src/runtime/control-plane/global-scheduler/config.ts +44 -0
- package/src/runtime/control-plane/global-scheduler/dispatch-capacity.ts +80 -0
- package/src/runtime/control-plane/global-scheduler/durable-admission.ts +46 -0
- package/src/runtime/control-plane/global-scheduler/maintenance.ts +152 -0
- package/src/runtime/control-plane/global-scheduler/projection-refresh.ts +84 -0
- package/src/runtime/control-plane/global-scheduler/reconciliation.ts +3 -3
- package/src/runtime/control-plane/global-scheduler/scheduler.ts +278 -543
- package/src/runtime/control-plane/global-scheduler/source-scan.ts +59 -0
- package/src/runtime/control-plane/global-scheduler/state.ts +88 -0
- package/src/runtime/control-plane/global-scheduler/worker-attachment.ts +57 -0
- package/src/runtime/control-plane/global-scheduler/worker-exit-decision.ts +38 -0
- package/src/runtime/control-plane/global-scheduler/worker-exit-reconciler.ts +175 -0
- package/src/runtime/control-plane/global-scheduler/worker-launch.ts +111 -0
- package/src/runtime/control-plane/global-scheduler/worker-lifecycle-store.ts +64 -0
- package/src/runtime/control-plane/global-scheduler/worker-lifecycle.ts +150 -0
- package/src/runtime/control-plane/global-scheduler/worker-process.ts +119 -0
- package/src/runtime/control-plane/global-scheduler/worker-stderr.ts +60 -0
- package/src/runtime/control-plane/launcher/chatgpt-work-binding-store.ts +63 -0
- package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +365 -117
- package/src/runtime/control-plane/launcher/launch-reservation-store.ts +89 -0
- package/src/runtime/control-plane/launcher/thin-launcher.ts +244 -11
- package/src/runtime/control-plane/persistence/controller-home-migration.ts +487 -0
- package/src/runtime/control-plane/persistence/requirement-store.ts +0 -12
- package/src/runtime/control-plane/persistence/sqlite-store.ts +33 -2
- package/src/runtime/control-plane/release-retention.ts +62 -2
- package/src/runtime/control-plane/repo-actor/registry.ts +4 -2
- package/src/runtime/control-plane/routing/route-policy.ts +24 -21
- package/src/runtime/control-plane/routing/workspace-admission.ts +70 -0
- package/src/runtime/control-plane/runtime-status-client.ts +0 -2
- package/src/runtime/diagnostics/mcp-timing.ts +13 -0
- package/src/runtime/diagnostics/mcp-transport-benchmark.ts +129 -0
- package/src/runtime/diagnostics/performance.ts +24 -1
- package/src/runtime/evidence/event-ledger.ts +1 -1
- package/src/runtime/evidence/process-check-execution.ts +18 -0
- package/src/runtime/execution/jobs/child-reference.ts +6 -2
- package/src/runtime/execution/jobs/store.ts +58 -4
- package/src/runtime/execution/jobs/types.ts +1 -1
- package/src/runtime/execution/managed-workspace.ts +203 -1
- package/src/runtime/execution/process-runtime/check-facade.ts +51 -4
- package/src/runtime/execution/process-runtime/check-result.ts +88 -0
- package/src/runtime/execution/process-runtime/check-runner-sidecar.ts +7 -1
- package/src/runtime/execution/process-runtime/check-scheduling.ts +114 -0
- package/src/runtime/execution/process-runtime/command-facade.ts +367 -40
- package/src/runtime/execution/process-runtime/gc.ts +38 -6
- package/src/runtime/execution/process-runtime/lightweight-managed.ts +1201 -0
- package/src/runtime/execution/process-runtime/persisted-check.ts +51 -5
- package/src/runtime/execution/process-runtime/resource-claims.ts +10 -6
- package/src/runtime/execution/process-runtime/runtime.ts +53 -3
- package/src/runtime/execution/process-runtime/store.ts +1 -0
- package/src/runtime/execution/process-runtime/types.ts +4 -12
- package/src/runtime/execution/thin-harness/async-process.ts +12 -2
- package/src/runtime/execution/thin-harness/search-worker.ts +54 -5
- package/src/runtime/execution/work-activity.ts +21 -0
- package/src/runtime/execution/workers/executor.ts +18 -61
- package/src/runtime/gateway/mcp/execution-tools.ts +35 -1852
- package/src/runtime/gateway/mcp/legacy-ios-tool-adapter.ts +61 -0
- package/src/runtime/gateway/mcp/process-tools.ts +83 -37
- package/src/runtime/gateway/mcp/router.ts +186 -84
- package/src/runtime/gateway/mcp/runtime-tool-definitions.ts +565 -0
- package/src/runtime/gateway/mcp/runtime-tools.ts +2378 -1947
- package/src/runtime/plugins/app-store-connect-adapter.ts +216 -47
- package/src/runtime/plugins/browser-adapter.ts +2662 -829
- package/src/runtime/plugins/browser-automation-service.ts +10 -0
- package/src/runtime/plugins/browser-handoff-host.ts +2 -25
- package/src/runtime/plugins/browser-handoff.ts +110 -5
- package/src/runtime/plugins/browser-macos-bridge.ts +701 -63
- package/src/runtime/plugins/browser-manifest-surface.ts +603 -0
- package/src/runtime/plugins/browser-native-session-service.ts +222 -0
- package/src/runtime/plugins/browser-node-bridge.ts +6 -34
- package/src/runtime/plugins/browser-provider-registry.ts +109 -0
- package/src/runtime/plugins/browser-runtime-contract.ts +154 -0
- package/src/runtime/plugins/browser-runtime.ts +193 -0
- package/src/runtime/plugins/browser-session-authority.ts +332 -0
- package/src/runtime/plugins/browser-session-store.ts +121 -0
- package/src/runtime/plugins/browser-session-types.ts +98 -0
- package/src/runtime/plugins/capability-authorization-grants.ts +354 -0
- package/src/runtime/plugins/desktop-operator-registration.ts +10 -4
- package/src/runtime/plugins/external-adapter.ts +358 -3
- package/src/runtime/plugins/external-unix-socket.ts +7 -1
- package/src/runtime/plugins/first-party-registry.ts +2 -0
- package/src/runtime/plugins/github-adapter.ts +125 -0
- package/src/runtime/plugins/ios/agent-device-provider.ts +1 -1
- package/src/runtime/plugins/ios/agent-device-typed-provider.ts +52 -9
- package/src/runtime/plugins/ios/remote-xpc-hid.ts +1171 -0
- package/src/runtime/plugins/ios-adapter.ts +106 -16
- package/src/runtime/plugins/ios-agent-device.ts +234 -64
- package/src/runtime/plugins/ios-physical-device.ts +1143 -392
- package/src/runtime/plugins/lightweight-action.ts +153 -0
- package/src/runtime/plugins/local-system-adapter.ts +123 -6
- package/src/runtime/plugins/macos-capability-broker.ts +47 -9
- package/src/runtime/plugins/plugin-action-sidecar.ts +59 -0
- package/src/runtime/plugins/plugin-management-adapter.ts +49 -8
- package/src/runtime/plugins/resend-adapter.ts +1 -1
- package/src/runtime/plugins/store.ts +330 -33
- package/src/runtime/plugins/types.ts +38 -3
- package/src/runtime/plugins/xiaohongshu-publish.ts +515 -0
- package/src/runtime/projections/git-status-sampler.ts +16 -16
- package/src/runtime/projections/materialized-view.ts +28 -10
- package/src/runtime/recovery/maintenance-executor.ts +426 -25
- package/src/runtime/root/mcp-transport.ts +180 -10
- package/src/runtime/root/package-connector-service.ts +230 -10
- package/src/runtime/root/package-runtime-release.ts +143 -17
- package/src/runtime/root/package-runtime-service.ts +461 -22
- package/src/runtime/root/release-manifest.ts +144 -18
- package/src/runtime/root/release-materialize.ts +125 -32
- package/src/runtime/root/release-store.ts +48 -11
- package/src/runtime/root/runtime.ts +23 -5
- package/src/runtime/root/service.ts +100 -29
- package/src/runtime/root/types.ts +12 -0
- package/src/runtime/safe-tooling/ios-development.ts +321 -63
- package/src/runtime/shared/trusted-executable.ts +62 -0
- package/src/runtime/shared/trusted-node-executable.ts +48 -0
- package/src/runtime/standalone-recovery/core.ts +1079 -240
- package/src/runtime/standalone-recovery/entry.ts +100 -24
- package/src/runtime/standalone-recovery/installer.ts +20 -4
- package/src/runtime/standalone-recovery/service-labels.ts +2 -0
- package/src/runtime/standalone-recovery/watchdog-heartbeat.ts +160 -0
- package/src/runtime/workflow/schedules/browser-probe.ts +81 -3
- package/src/runtime/workflow/schedules/engine.ts +364 -202
- package/src/runtime/workflow/schedules/github-issue-watch.ts +158 -0
- package/src/runtime/workflow/schedules/settlement.ts +64 -17
- package/src/runtime/workflow/schedules/store.ts +209 -19
- package/src/runtime/workflow/schedules/types.ts +2 -4
- package/src/runtime/workflow/schedules/work-continuation.ts +26 -13
- package/src/testing/test-governance.ts +8 -40
- package/assets/reference-configs/heartbeat-triage.md +0 -57
- package/assets/templates/helpers/harness-trace-grade.sh +0 -150
- package/assets/templates/helpers/heartbeat-triage.sh +0 -361
- package/assets/templates/helpers/maintenance-triage.sh +0 -167
- package/docs/architecture/current/approved-target-architecture.zh-CN.md +0 -1501
- package/docs/architecture/current/architecture-invariants.md +0 -331
- package/docs/architecture/current/automation-and-schedule-engine.md +0 -459
- package/docs/architecture/current/codegraph-context-provider.md +0 -238
- package/docs/architecture/current/control-plane-authority-inventory.md +0 -94
- package/docs/architecture/current/controller-repository-decoupling.md +0 -148
- package/docs/architecture/current/dispatch-and-agent-strategy.md +0 -373
- package/docs/architecture/current/entity-model.md +0 -612
- package/docs/architecture/current/external-plugin-governance.md +0 -396
- package/docs/architecture/current/failure-recovery.md +0 -447
- package/docs/architecture/current/governance.md +0 -213
- package/docs/architecture/current/human-interaction-plane.md +0 -87
- package/docs/architecture/current/implementation-status.md +0 -128
- package/docs/architecture/current/job-and-run-lifecycle.md +0 -413
- package/docs/architecture/current/legacy-governance.md +0 -58
- package/docs/architecture/current/local-workspace-target-grants.md +0 -70
- package/docs/architecture/current/migration-roadmap.md +0 -105
- package/docs/architecture/current/multi-repository-execution.md +0 -371
- package/docs/architecture/current/operations-runbook.md +0 -45
- package/docs/architecture/current/peer-supercontroller-runtime.md +0 -32
- package/docs/architecture/current/personal-assistant-plugin-baseline.md +0 -206
- package/docs/architecture/current/repository-access-modes.md +0 -102
- package/docs/architecture/current/route-policy.md +0 -15
- package/docs/architecture/current/route-session-concurrency.md +0 -85
- package/docs/architecture/current/runtime-architecture-simplification.md +0 -214
- package/docs/architecture/current/runtime-directory-map.md +0 -49
- package/docs/architecture/current/runtime-health-and-resource-lifecycle.md +0 -85
- package/docs/architecture/current/scheduler-and-resource-claims.md +0 -422
- package/docs/architecture/current/session-aware-execution-and-authorization.md +0 -77
- package/docs/architecture/current/system-overview.md +0 -169
- package/docs/architecture/current/target-requirements-traceability.md +0 -202
- package/docs/architecture/current/thin-harness-governance-policy.md +0 -32
- package/docs/architecture/current/thin-harness-v1.md +0 -321
- package/docs/architecture/current/verification-and-release-gates.md +0 -391
- package/docs/forge-autonomous-goal-loop.md +0 -9
- package/docs/forge-provider-configuration.md +0 -7
- package/docs/operations/chatgpt-personal-assistant-runtime.md +0 -93
- package/docs/operations/gmail-assistant-routines.md +0 -186
- package/docs/operations/personal-assistant-operator-guide.md +0 -61
- package/docs/operations/provider-configuration.md +0 -31
- package/scripts/harness-trace-grade.sh +0 -150
- package/scripts/heartbeat-triage.sh +0 -361
- package/scripts/maintenance-triage.sh +0 -167
- package/src/cli/local-bridge/frontend/src/features/settings/SettingsView.tsx +0 -2
- package/src/cli/repositories/goal-registry.ts +0 -239
- package/src/runtime/assistant/action-proposals.ts +0 -279
- package/src/runtime/assistant/intent.ts +0 -395
- package/src/runtime/assistant/model-provider.ts +0 -460
- package/src/runtime/assistant/openapi.ts +0 -223
- package/src/runtime/assistant/policy.ts +0 -89
- package/src/runtime/assistant/readiness.ts +0 -258
- package/src/runtime/assistant/routine-runtime.ts +0 -477
- package/src/runtime/assistant/schedule-binding.ts +0 -171
- package/src/runtime/assistant/standing-grants.ts +0 -375
- package/src/runtime/assistant/store.ts +0 -243
- package/src/runtime/assistant/types.ts +0 -135
- package/src/runtime/control-plane/goal-loop/config-facade.ts +0 -700
- package/src/runtime/control-plane/goal-loop/config-store.ts +0 -570
- package/src/runtime/control-plane/goal-loop/config-types.ts +0 -213
- package/src/runtime/control-plane/goal-loop/executor-router.ts +0 -109
- package/src/runtime/control-plane/goal-loop/failure-taxonomy.ts +0 -149
- package/src/runtime/control-plane/goal-loop/goal-contract-store.ts +0 -304
- package/src/runtime/control-plane/goal-loop/goal-loop-engine.ts +0 -1001
- package/src/runtime/control-plane/goal-loop/handoff-packet.ts +0 -160
- package/src/runtime/control-plane/goal-loop/index.ts +0 -13
- package/src/runtime/control-plane/goal-loop/local-tools.ts +0 -290
- package/src/runtime/control-plane/goal-loop/policy-gates.ts +0 -203
- package/src/runtime/control-plane/goal-loop/provider-dispatch.ts +0 -93
- package/src/runtime/control-plane/goal-loop/provider-registry.ts +0 -545
- package/src/runtime/control-plane/goal-loop/types.ts +0 -378
- package/src/runtime/control-plane/startup-recovery.ts +0 -198
- package/src/runtime/gateway/mcp/resource-policy.ts +0 -186
- package/src/runtime/personal-assistant/gmail-triage-manager.ts +0 -231
- package/src/runtime/personal-assistant/reporting-runtime.ts +0 -344
- package/src/runtime/personal-assistant/triage-runtime.ts +0 -748
- package/src/runtime/workflow/findings/store.ts +0 -204
- package/src/runtime/workflow/findings/types.ts +0 -58
- package/src/runtime/workflow/portfolio/engine.ts +0 -20
- package/src/runtime/workflow/portfolio/store.ts +0 -185
- package/src/runtime/workflow/portfolio/types.ts +0 -29
|
@@ -1,1192 +1,4 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
-
# Migrate an existing project to the forge tasks-first harness model.
|
|
3
|
-
# - Shared hook source of truth: .ai/hooks/
|
|
4
|
-
# - User-level host adapters: ~/.claude/settings.json and ~/.codex/hooks.json
|
|
5
|
-
# - Stable product truth: docs/spec.md
|
|
6
|
-
# - Active-plan selector: .ai/harness/active-plan, with .claude/.active-plan legacy fallback
|
|
7
|
-
# - Sprint artifacts: plans/sprints/, tasks/contracts/, tasks/reviews/, .ai/context/context-map.json
|
|
8
|
-
# - Harness state: .ai/harness/checks/latest.json, .ai/harness/policy.json,
|
|
9
|
-
# .ai/harness/brain-manifest.json,
|
|
10
|
-
# .ai/harness/events.jsonl, .ai/harness/architecture/events.jsonl,
|
|
11
|
-
# .ai/harness/session/continuation.md,
|
|
12
|
-
# .ai/harness/session/resume.md,
|
|
13
|
-
# .ai/harness/failures/latest.jsonl, .ai/harness/security/.gitkeep,
|
|
14
|
-
# .ai/harness/worktrees/.gitkeep, .ai/harness/runs/.gitkeep
|
|
15
|
-
#
|
|
16
|
-
# Usage:
|
|
17
|
-
# bash scripts/migrate-project-template.sh --repo /path/to/repo --dry-run
|
|
18
|
-
# bash scripts/migrate-project-template.sh --repo /path/to/repo --apply
|
|
19
|
-
|
|
20
2
|
set -euo pipefail
|
|
21
|
-
|
|
22
3
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
23
|
-
|
|
24
|
-
PI_LIB_DIR="$SCRIPT_DIR/lib"
|
|
25
|
-
if [[ -f "$PI_LIB_DIR/project-init-lib.sh" ]]; then
|
|
26
|
-
# shellcheck source=/dev/null
|
|
27
|
-
. "$PI_LIB_DIR/project-init-lib.sh"
|
|
28
|
-
fi
|
|
29
|
-
HOOK_ASSETS_DIR="$SKILL_ROOT/assets/hooks"
|
|
30
|
-
TEMPLATE_ASSETS_DIR="$SKILL_ROOT/assets/templates"
|
|
31
|
-
HELPER_ASSETS_DIR="$TEMPLATE_ASSETS_DIR/helpers"
|
|
32
|
-
FACTOR_FACTORY_ASSETS_DIR="$TEMPLATE_ASSETS_DIR/factor-factory"
|
|
33
|
-
WORKFLOW_CONTRACT_ASSET="$SKILL_ROOT/assets/workflow-contract.v1.json"
|
|
34
|
-
JQ_BIN="${FORGE_JQ_BIN:-jq}"
|
|
35
|
-
|
|
36
|
-
MODE="dry-run"
|
|
37
|
-
TARGET_REPO=""
|
|
38
|
-
INSPECT_OUTPUT=""
|
|
39
|
-
|
|
40
|
-
usage() {
|
|
41
|
-
cat <<'USAGE_EOF'
|
|
42
|
-
Usage: migrate-project-template.sh --repo <path> [--dry-run|--apply]
|
|
43
|
-
|
|
44
|
-
Options:
|
|
45
|
-
--repo <path> Target repository path
|
|
46
|
-
--dry-run Print planned changes only (default)
|
|
47
|
-
--apply Apply changes
|
|
48
|
-
--help Show help
|
|
49
|
-
USAGE_EOF
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
log() {
|
|
53
|
-
echo "[migrate] $*"
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
has_jq() {
|
|
57
|
-
command -v "$JQ_BIN" >/dev/null 2>&1
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
run_ts_script() {
|
|
61
|
-
local script_path="$1"
|
|
62
|
-
shift
|
|
63
|
-
|
|
64
|
-
if command -v bun >/dev/null 2>&1; then
|
|
65
|
-
bun "$script_path" "$@"
|
|
66
|
-
return $?
|
|
67
|
-
fi
|
|
68
|
-
|
|
69
|
-
if command -v node >/dev/null 2>&1; then
|
|
70
|
-
node --loader "$SKILL_ROOT/src/runtime/shared/node-ts-loader.mjs" "$script_path" "$@"
|
|
71
|
-
return $?
|
|
72
|
-
fi
|
|
73
|
-
|
|
74
|
-
echo "[migrate] Missing bun/node runtime for TypeScript helper: $script_path" >&2
|
|
75
|
-
return 1
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
merge_hook_settings_json() {
|
|
79
|
-
local base_file="$1"
|
|
80
|
-
local patch_file="$2"
|
|
81
|
-
local output_file="$3"
|
|
82
|
-
|
|
83
|
-
node - "$base_file" "$patch_file" "$output_file" <<'NODE_EOF'
|
|
84
|
-
const fs = require("fs");
|
|
85
|
-
|
|
86
|
-
const [, , basePath, patchPath, outputPath] = process.argv;
|
|
87
|
-
|
|
88
|
-
function readJson(path) {
|
|
89
|
-
return JSON.parse(fs.readFileSync(path, "utf8"));
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
function clone(value) {
|
|
93
|
-
return JSON.parse(JSON.stringify(value));
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
function matcherOf(block) {
|
|
97
|
-
return block && Object.prototype.hasOwnProperty.call(block, "matcher")
|
|
98
|
-
? block.matcher ?? null
|
|
99
|
-
: null;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
function ensureHooksArray(block) {
|
|
103
|
-
if (!Array.isArray(block.hooks)) {
|
|
104
|
-
block.hooks = [];
|
|
105
|
-
}
|
|
106
|
-
return block.hooks;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
function hasCommand(block, command) {
|
|
110
|
-
return ensureHooksArray(block).some((hook) => (hook?.command ?? "") === command);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
function mergeEventBlocks(baseBlocks, patchBlocks) {
|
|
114
|
-
const result = Array.isArray(baseBlocks) ? clone(baseBlocks) : [];
|
|
115
|
-
|
|
116
|
-
for (const patchBlock of Array.isArray(patchBlocks) ? patchBlocks : []) {
|
|
117
|
-
const matcher = matcherOf(patchBlock);
|
|
118
|
-
const patchHooks = Array.isArray(patchBlock?.hooks) ? patchBlock.hooks : [];
|
|
119
|
-
|
|
120
|
-
for (const patchHook of patchHooks) {
|
|
121
|
-
const command = patchHook?.command ?? "";
|
|
122
|
-
if (!command) continue;
|
|
123
|
-
|
|
124
|
-
const existingWithCommand = result.find(
|
|
125
|
-
(block) => matcherOf(block) === matcher && hasCommand(block, command)
|
|
126
|
-
);
|
|
127
|
-
if (existingWithCommand) continue;
|
|
128
|
-
|
|
129
|
-
const targetBlock = result.find((block) => matcherOf(block) === matcher);
|
|
130
|
-
if (targetBlock) {
|
|
131
|
-
ensureHooksArray(targetBlock).push(clone(patchHook));
|
|
132
|
-
continue;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
const newBlock = matcher === null
|
|
136
|
-
? { hooks: [clone(patchHook)] }
|
|
137
|
-
: { matcher, hooks: [clone(patchHook)] };
|
|
138
|
-
result.push(newBlock);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
return result;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
const base = readJson(basePath);
|
|
146
|
-
const patch = readJson(patchPath);
|
|
147
|
-
|
|
148
|
-
const merged = {
|
|
149
|
-
...clone(base),
|
|
150
|
-
...clone(Object.fromEntries(Object.entries(patch).filter(([key]) => key !== "hooks"))),
|
|
151
|
-
};
|
|
152
|
-
|
|
153
|
-
const baseHooks = (base && typeof base.hooks === "object" && base.hooks !== null) ? clone(base.hooks) : {};
|
|
154
|
-
const patchHooks = (patch && typeof patch.hooks === "object" && patch.hooks !== null) ? patch.hooks : {};
|
|
155
|
-
|
|
156
|
-
merged.hooks = baseHooks;
|
|
157
|
-
for (const [eventName, patchBlocks] of Object.entries(patchHooks)) {
|
|
158
|
-
merged.hooks[eventName] = mergeEventBlocks(baseHooks[eventName], patchBlocks);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
fs.writeFileSync(outputPath, JSON.stringify(merged, null, 2) + "\n");
|
|
162
|
-
NODE_EOF
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
run_or_echo() {
|
|
166
|
-
if [[ "$MODE" == "apply" ]]; then
|
|
167
|
-
"$@"
|
|
168
|
-
else
|
|
169
|
-
printf '[dry-run]'
|
|
170
|
-
printf ' %q' "$@"
|
|
171
|
-
printf '\n'
|
|
172
|
-
fi
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
backup_if_exists() {
|
|
176
|
-
local path="$1"
|
|
177
|
-
if [[ -f "$path" ]]; then
|
|
178
|
-
run_or_echo cp "$path" "$path.bak.$(date +%Y%m%d%H%M%S)"
|
|
179
|
-
fi
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
remove_path_if_exists() {
|
|
183
|
-
local path="$1"
|
|
184
|
-
if [[ "$MODE" != "apply" ]]; then
|
|
185
|
-
echo "[dry-run] remove \"$path\" if it exists"
|
|
186
|
-
return 0
|
|
187
|
-
fi
|
|
188
|
-
|
|
189
|
-
if [[ -e "$path" ]]; then
|
|
190
|
-
rm -rf "$path"
|
|
191
|
-
fi
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
repo_relative_path() {
|
|
195
|
-
local repo="$1"
|
|
196
|
-
local path="$2"
|
|
197
|
-
|
|
198
|
-
if [[ "$path" == "$repo/"* ]]; then
|
|
199
|
-
printf '%s' "${path#"$repo/"}"
|
|
200
|
-
else
|
|
201
|
-
printf '%s' "$path"
|
|
202
|
-
fi
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
file_matches_any_source() {
|
|
206
|
-
local file_path="$1"
|
|
207
|
-
shift
|
|
208
|
-
local source_path
|
|
209
|
-
|
|
210
|
-
[[ -f "$file_path" ]] || return 1
|
|
211
|
-
for source_path in "$@"; do
|
|
212
|
-
[[ -f "$source_path" ]] || continue
|
|
213
|
-
if cmp -s "$file_path" "$source_path"; then
|
|
214
|
-
return 0
|
|
215
|
-
fi
|
|
216
|
-
done
|
|
217
|
-
|
|
218
|
-
return 1
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
file_has_forge_marker() {
|
|
222
|
-
local file_path="$1"
|
|
223
|
-
|
|
224
|
-
[[ -f "$file_path" ]] || return 1
|
|
225
|
-
|
|
226
|
-
grep -Eiq \
|
|
227
|
-
'(forge|claude-runtime-temp|Task Contract|Sprint Review|Deferred Goal Ledger|Workflow Contract|ContractWorktree|SprintBacklog|ArchitectureSync|ArchitectureDrift|BrainSync|CurrentStatus|\.ai/harness|\.claude/templates|tasks/contracts|tasks/reviews)' \
|
|
228
|
-
"$file_path"
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
is_self_host_source_repo() {
|
|
232
|
-
local repo="$1"
|
|
233
|
-
local repo_real
|
|
234
|
-
local source_real
|
|
235
|
-
|
|
236
|
-
repo_real="$(cd "$repo" 2>/dev/null && pwd -P || printf '%s' "$repo")"
|
|
237
|
-
source_real="$(cd "$SKILL_ROOT" 2>/dev/null && pwd -P || printf '%s' "$SKILL_ROOT")"
|
|
238
|
-
|
|
239
|
-
[[ "$repo_real" == "$source_real" ]]
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
is_generated_root_helper() {
|
|
243
|
-
local repo="$1"
|
|
244
|
-
local rel_path="$2"
|
|
245
|
-
local path="$repo/$rel_path"
|
|
246
|
-
local helper_name="${rel_path##*/}"
|
|
247
|
-
|
|
248
|
-
[[ "$rel_path" == scripts/* && -f "$path" ]] || return 1
|
|
249
|
-
|
|
250
|
-
if file_matches_any_source "$path" "$HELPER_ASSETS_DIR/$helper_name" "$SCRIPT_DIR/$helper_name"; then
|
|
251
|
-
return 0
|
|
252
|
-
fi
|
|
253
|
-
|
|
254
|
-
case "$helper_name" in
|
|
255
|
-
skill-factory-create.sh|skill-factory-check.sh|architecture-drift.sh)
|
|
256
|
-
file_has_forge_marker "$path"
|
|
257
|
-
return $?
|
|
258
|
-
;;
|
|
259
|
-
esac
|
|
260
|
-
|
|
261
|
-
file_has_forge_marker "$path"
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
remove_generated_helper_if_owned() {
|
|
265
|
-
local repo="$1"
|
|
266
|
-
local rel_path="$2"
|
|
267
|
-
local path="$repo/$rel_path"
|
|
268
|
-
local display_path
|
|
269
|
-
|
|
270
|
-
display_path="$(repo_relative_path "$repo" "$path")"
|
|
271
|
-
|
|
272
|
-
if is_self_host_source_repo "$repo"; then
|
|
273
|
-
if [[ "$MODE" != "apply" ]]; then
|
|
274
|
-
echo "[dry-run] preserve self-host source helper \"$path\""
|
|
275
|
-
else
|
|
276
|
-
log "Preserved self-host source helper: $display_path"
|
|
277
|
-
fi
|
|
278
|
-
return 0
|
|
279
|
-
fi
|
|
280
|
-
|
|
281
|
-
if [[ "$MODE" != "apply" ]]; then
|
|
282
|
-
echo "[dry-run] remove generated helper \"$path\" if forge ownership is identifiable"
|
|
283
|
-
return 0
|
|
284
|
-
fi
|
|
285
|
-
|
|
286
|
-
[[ -e "$path" ]] || return 0
|
|
287
|
-
|
|
288
|
-
if is_generated_root_helper "$repo" "$rel_path"; then
|
|
289
|
-
rm -f "$path"
|
|
290
|
-
log "Removed generated legacy root helper: $display_path"
|
|
291
|
-
else
|
|
292
|
-
log "Preserved possible app-owned script: $display_path (not identifiable as forge generated helper)"
|
|
293
|
-
fi
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
prune_removed_hook_commands() {
|
|
297
|
-
local settings_file="$1"
|
|
298
|
-
|
|
299
|
-
if [[ "$MODE" != "apply" || ! -f "$settings_file" ]]; then
|
|
300
|
-
return 0
|
|
301
|
-
fi
|
|
302
|
-
|
|
303
|
-
if ! command -v node >/dev/null 2>&1; then
|
|
304
|
-
log "Skipping removed-hook pruning for $settings_file because node is unavailable"
|
|
305
|
-
return 0
|
|
306
|
-
fi
|
|
307
|
-
|
|
308
|
-
node - "$settings_file" <<'NODE_EOF'
|
|
309
|
-
const fs = require("fs");
|
|
310
|
-
const path = process.argv[2];
|
|
311
|
-
const removedFragments = ["memory-intake.sh", "skill-factory-session-end.sh"];
|
|
312
|
-
|
|
313
|
-
const settings = JSON.parse(fs.readFileSync(path, "utf8"));
|
|
314
|
-
if (!settings.hooks || typeof settings.hooks !== "object") {
|
|
315
|
-
process.exit(0);
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
const nextHooks = {};
|
|
319
|
-
for (const [eventName, blocks] of Object.entries(settings.hooks)) {
|
|
320
|
-
const keptBlocks = (Array.isArray(blocks) ? blocks : [])
|
|
321
|
-
.map((block) => {
|
|
322
|
-
const hooks = (Array.isArray(block.hooks) ? block.hooks : []).filter((hook) => {
|
|
323
|
-
const command = hook?.command ?? "";
|
|
324
|
-
return !removedFragments.some((fragment) => command.includes(fragment));
|
|
325
|
-
});
|
|
326
|
-
return hooks.length > 0 ? { ...block, hooks } : null;
|
|
327
|
-
})
|
|
328
|
-
.filter(Boolean);
|
|
329
|
-
|
|
330
|
-
if (keptBlocks.length > 0) {
|
|
331
|
-
nextHooks[eventName] = keptBlocks;
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
settings.hooks = nextHooks;
|
|
336
|
-
fs.writeFileSync(path, JSON.stringify(settings, null, 2) + "\n");
|
|
337
|
-
NODE_EOF
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
cleanup_removed_workflow_assets() {
|
|
341
|
-
local repo="$1"
|
|
342
|
-
local cleanup_mode
|
|
343
|
-
local rel_path
|
|
344
|
-
|
|
345
|
-
while IFS=$'\t' read -r cleanup_mode rel_path; do
|
|
346
|
-
[[ -z "$rel_path" ]] && continue
|
|
347
|
-
case "$cleanup_mode" in
|
|
348
|
-
generated_helper)
|
|
349
|
-
remove_generated_helper_if_owned "$repo" "$rel_path"
|
|
350
|
-
;;
|
|
351
|
-
*)
|
|
352
|
-
remove_path_if_exists "$repo/$rel_path"
|
|
353
|
-
;;
|
|
354
|
-
esac
|
|
355
|
-
done < <(pi_workflow_contract_upgrade_action_entries "$WORKFLOW_CONTRACT_ASSET" "remove" "known_generated")
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
ensure_runtime_gitignore_block() {
|
|
359
|
-
local repo="$1"
|
|
360
|
-
local file_path="$2"
|
|
361
|
-
local extra_entries=""
|
|
362
|
-
local helper_entries=""
|
|
363
|
-
if pi_should_enable_factor_factory "$(pi_plan_type)"; then
|
|
364
|
-
extra_entries="$(pi_factor_factory_gitignore_entries)"
|
|
365
|
-
fi
|
|
366
|
-
if ! is_self_host_source_repo "$repo" && ! pi_repo_pins_helper_source "$repo"; then
|
|
367
|
-
helper_entries="$(pi_helper_wrapper_gitignore_entries "$WORKFLOW_CONTRACT_ASSET")"
|
|
368
|
-
if [[ -n "$helper_entries" ]]; then
|
|
369
|
-
if [[ -n "$extra_entries" ]]; then
|
|
370
|
-
extra_entries="${extra_entries}"$'\n'"${helper_entries}"
|
|
371
|
-
else
|
|
372
|
-
extra_entries="$helper_entries"
|
|
373
|
-
fi
|
|
374
|
-
fi
|
|
375
|
-
fi
|
|
376
|
-
pi_ensure_gitignore_block "$file_path" "" "$extra_entries" "$MODE"
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
generated_helper_wrapper_paths() {
|
|
380
|
-
local helper_name
|
|
381
|
-
while IFS= read -r helper_name; do
|
|
382
|
-
[[ -z "$helper_name" ]] && continue
|
|
383
|
-
printf '%s\n' "$helper_name"
|
|
384
|
-
printf '%s\n' "scripts/forge/${helper_name#scripts/}"
|
|
385
|
-
done < <(pi_helper_wrapper_paths "$WORKFLOW_CONTRACT_ASSET")
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
untrack_generated_helper_wrappers() {
|
|
389
|
-
local repo="$1"
|
|
390
|
-
local rel_path
|
|
391
|
-
|
|
392
|
-
if is_self_host_source_repo "$repo" || pi_repo_pins_helper_source "$repo"; then
|
|
393
|
-
return 0
|
|
394
|
-
fi
|
|
395
|
-
|
|
396
|
-
if [[ "$MODE" != "apply" ]]; then
|
|
397
|
-
echo "[dry-run] untrack forge generated helper wrappers from git index when tracked"
|
|
398
|
-
return 0
|
|
399
|
-
fi
|
|
400
|
-
|
|
401
|
-
if ! git -C "$repo" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
402
|
-
return 0
|
|
403
|
-
fi
|
|
404
|
-
|
|
405
|
-
while IFS= read -r rel_path; do
|
|
406
|
-
[[ -z "$rel_path" ]] && continue
|
|
407
|
-
if ! git -C "$repo" ls-files --error-unmatch -- "$rel_path" >/dev/null 2>&1; then
|
|
408
|
-
continue
|
|
409
|
-
fi
|
|
410
|
-
if [[ "$rel_path" == scripts/forge/* ]] || is_generated_root_helper "$repo" "$rel_path"; then
|
|
411
|
-
git -C "$repo" rm --cached --force --quiet -- "$rel_path"
|
|
412
|
-
log "Untracked generated helper wrapper: $rel_path"
|
|
413
|
-
else
|
|
414
|
-
log "Preserved tracked app-owned script: $rel_path"
|
|
415
|
-
fi
|
|
416
|
-
done < <(generated_helper_wrapper_paths)
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
migrate_active_plan_marker() {
|
|
420
|
-
local repo="$1"
|
|
421
|
-
local new_marker="$repo/.ai/harness/active-plan"
|
|
422
|
-
local legacy_marker="$repo/.claude/.active-plan"
|
|
423
|
-
local worktree_marker="$repo/.ai/harness/active-worktree"
|
|
424
|
-
local new_value=""
|
|
425
|
-
local legacy_value=""
|
|
426
|
-
|
|
427
|
-
if [[ "$MODE" != "apply" ]]; then
|
|
428
|
-
echo "[dry-run] migrate active-plan marker to .ai/harness/active-plan with .claude/.active-plan compatibility"
|
|
429
|
-
return 0
|
|
430
|
-
fi
|
|
431
|
-
|
|
432
|
-
if [[ -f "$new_marker" ]]; then
|
|
433
|
-
new_value="$(cat "$new_marker" 2>/dev/null | xargs)"
|
|
434
|
-
fi
|
|
435
|
-
if [[ -f "$legacy_marker" ]]; then
|
|
436
|
-
legacy_value="$(cat "$legacy_marker" 2>/dev/null | xargs)"
|
|
437
|
-
fi
|
|
438
|
-
|
|
439
|
-
if [[ -n "$new_value" ]]; then
|
|
440
|
-
mkdir -p "$(dirname "$legacy_marker")"
|
|
441
|
-
printf '%s' "$new_value" > "$legacy_marker"
|
|
442
|
-
mkdir -p "$(dirname "$worktree_marker")"
|
|
443
|
-
(cd "$repo" && pwd -P) > "$worktree_marker"
|
|
444
|
-
return 0
|
|
445
|
-
fi
|
|
446
|
-
|
|
447
|
-
if [[ -n "$legacy_value" ]]; then
|
|
448
|
-
mkdir -p "$(dirname "$new_marker")"
|
|
449
|
-
printf '%s' "$legacy_value" > "$new_marker"
|
|
450
|
-
(cd "$repo" && pwd -P) > "$worktree_marker"
|
|
451
|
-
fi
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
ensure_gitignore_entry() {
|
|
455
|
-
local file_path="$1"
|
|
456
|
-
local entry="$2"
|
|
457
|
-
|
|
458
|
-
if [[ "$MODE" != "apply" ]]; then
|
|
459
|
-
echo "[dry-run] ensure .gitignore entry: $entry"
|
|
460
|
-
return
|
|
461
|
-
fi
|
|
462
|
-
|
|
463
|
-
if ! grep -Fxq "$entry" "$file_path"; then
|
|
464
|
-
printf "%s\n" "$entry" >> "$file_path"
|
|
465
|
-
fi
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
install_templates() {
|
|
469
|
-
local repo="$1"
|
|
470
|
-
pi_install_templates "$repo" "$TEMPLATE_ASSETS_DIR" "$MODE"
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
install_helpers() {
|
|
474
|
-
local repo="$1"
|
|
475
|
-
if [[ -d "$HELPER_ASSETS_DIR" ]]; then
|
|
476
|
-
local helper_names
|
|
477
|
-
helper_names="$(pi_workflow_contract_query_lines "$WORKFLOW_CONTRACT_ASSET" "helpers.scripts" | xargs)"
|
|
478
|
-
pi_install_helpers "$repo" "$HELPER_ASSETS_DIR" "$MODE" "$helper_names"
|
|
479
|
-
else
|
|
480
|
-
log "Helper assets not found at $HELPER_ASSETS_DIR"
|
|
481
|
-
fi
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
install_workflow_contract() {
|
|
485
|
-
local repo="$1"
|
|
486
|
-
pi_install_workflow_contract "$repo" "$WORKFLOW_CONTRACT_ASSET" "$MODE"
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
ensure_task_sync_package_script() {
|
|
490
|
-
local repo="$1"
|
|
491
|
-
local package_file="$repo/package.json"
|
|
492
|
-
|
|
493
|
-
if [[ ! -f "$package_file" ]]; then
|
|
494
|
-
if [[ "$MODE" == "apply" ]]; then
|
|
495
|
-
log "package.json missing; skipped check:task-sync injection"
|
|
496
|
-
else
|
|
497
|
-
echo "[dry-run] package.json missing; skip task workflow script injection"
|
|
498
|
-
fi
|
|
499
|
-
return
|
|
500
|
-
fi
|
|
501
|
-
|
|
502
|
-
pi_ensure_task_sync "$repo" "0" "$MODE"
|
|
503
|
-
if [[ "$MODE" == "apply" ]]; then
|
|
504
|
-
log "Injected task workflow scripts into $package_file"
|
|
505
|
-
fi
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
migrate_legacy_sprint_prds() {
|
|
509
|
-
local repo="$1"
|
|
510
|
-
local legacy_dir="$repo/tasks/sprints"
|
|
511
|
-
local prd_dir="$repo/plans/prds"
|
|
512
|
-
local sprint_dir="$repo/plans/sprints"
|
|
513
|
-
local marker_file="$repo/.ai/harness/sprint/active-sprint"
|
|
514
|
-
local src
|
|
515
|
-
local stem
|
|
516
|
-
local legacy_rel
|
|
517
|
-
local marker_value
|
|
518
|
-
|
|
519
|
-
if [[ "$MODE" != "apply" ]]; then
|
|
520
|
-
echo "[dry-run] migrate legacy sprint files from tasks/sprints/*.sprint.md and sprint-shaped plans/prds/*.prd.md into plans/sprints/*.sprint.md"
|
|
521
|
-
return 0
|
|
522
|
-
fi
|
|
523
|
-
|
|
524
|
-
mkdir -p "$prd_dir" "$sprint_dir"
|
|
525
|
-
shopt -s nullglob
|
|
526
|
-
|
|
527
|
-
move_sprint_file() {
|
|
528
|
-
local src_file="$1"
|
|
529
|
-
local old_rel="$2"
|
|
530
|
-
local stem_name="$3"
|
|
531
|
-
local dest_file
|
|
532
|
-
local dest_rel_file
|
|
533
|
-
local n
|
|
534
|
-
|
|
535
|
-
dest_file="$sprint_dir/${stem_name}.sprint.md"
|
|
536
|
-
n=2
|
|
537
|
-
while [[ -e "$dest_file" ]]; do
|
|
538
|
-
dest_file="$sprint_dir/${stem_name}-v${n}.sprint.md"
|
|
539
|
-
n=$((n + 1))
|
|
540
|
-
done
|
|
541
|
-
|
|
542
|
-
mv "$src_file" "$dest_file"
|
|
543
|
-
|
|
544
|
-
dest_rel_file="plans/sprints/$(basename "$dest_file")"
|
|
545
|
-
if [[ -f "$marker_file" ]]; then
|
|
546
|
-
marker_value="$(tr -d '\r\n' < "$marker_file")"
|
|
547
|
-
if [[ "$marker_value" == "$old_rel" || "$marker_value" == "$src_file" ]]; then
|
|
548
|
-
printf '%s\n' "$dest_rel_file" > "$marker_file"
|
|
549
|
-
fi
|
|
550
|
-
fi
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
for src in "$legacy_dir"/*.sprint.md; do
|
|
554
|
-
stem="$(basename "$src" .sprint.md)"
|
|
555
|
-
legacy_rel="tasks/sprints/${stem}.sprint.md"
|
|
556
|
-
move_sprint_file "$src" "$legacy_rel" "$stem"
|
|
557
|
-
done
|
|
558
|
-
|
|
559
|
-
for src in "$prd_dir"/*.prd.md; do
|
|
560
|
-
if grep -Eq '^(# Sprint:|## Backlog[[:space:]]*$)' "$src"; then
|
|
561
|
-
stem="$(basename "$src" .prd.md)"
|
|
562
|
-
legacy_rel="plans/prds/${stem}.prd.md"
|
|
563
|
-
move_sprint_file "$src" "$legacy_rel" "$stem"
|
|
564
|
-
fi
|
|
565
|
-
done
|
|
566
|
-
shopt -u nullglob
|
|
567
|
-
|
|
568
|
-
rmdir "$legacy_dir" 2>/dev/null || true
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
create_task_files_if_missing() {
|
|
572
|
-
local repo="$1"
|
|
573
|
-
local project_name
|
|
574
|
-
local timestamp
|
|
575
|
-
local todo_file
|
|
576
|
-
local legacy_todo_file
|
|
577
|
-
local legacy_todo_archive
|
|
578
|
-
|
|
579
|
-
project_name="$(basename "$repo")"
|
|
580
|
-
timestamp="$(date '+%Y-%m-%d %H:%M')"
|
|
581
|
-
todo_file="$repo/tasks/todos.md"
|
|
582
|
-
legacy_todo_file="$repo/tasks/todo.md"
|
|
583
|
-
legacy_todo_archive="$repo/tasks/archive/legacy-tasks-todo.md"
|
|
584
|
-
|
|
585
|
-
if [[ "$MODE" != "apply" ]]; then
|
|
586
|
-
echo "[dry-run] ensure docs/spec.md, tasks/*, workstreams, reviews, notes, .ai/context/{capabilities.json,context-map.json}, and .ai/harness/{checks/latest.json,policy.json,brain-manifest.json,events.jsonl,architecture/events.jsonl,handoff/current.md,handoff/resume.md,failures/latest.jsonl,security/.gitkeep,worktrees/.gitkeep,runs/.gitkeep} exist with current workflow guidance"
|
|
587
|
-
return
|
|
588
|
-
fi
|
|
589
|
-
|
|
590
|
-
mkdir -p \
|
|
591
|
-
"$repo/plans" \
|
|
592
|
-
"$repo/plans/archive" \
|
|
593
|
-
"$repo/plans/prds" \
|
|
594
|
-
"$repo/plans/sprints" \
|
|
595
|
-
"$repo/tasks" \
|
|
596
|
-
"$repo/tasks/issues" \
|
|
597
|
-
"$repo/tasks/archive" \
|
|
598
|
-
"$repo/tasks/contracts" \
|
|
599
|
-
"$repo/tasks/reviews" \
|
|
600
|
-
"$repo/tasks/notes" \
|
|
601
|
-
"$repo/tasks/workstreams" \
|
|
602
|
-
"$repo/docs" \
|
|
603
|
-
"$repo/docs/architecture/domains" \
|
|
604
|
-
"$repo/docs/architecture/modules" \
|
|
605
|
-
"$repo/docs/architecture/requests" \
|
|
606
|
-
"$repo/docs/architecture/snapshots" \
|
|
607
|
-
"$repo/docs/architecture/diagrams" \
|
|
608
|
-
"$repo/.ai/context" \
|
|
609
|
-
"$repo/.ai/harness/checks" \
|
|
610
|
-
"$repo/.ai/harness/session" \
|
|
611
|
-
"$repo/.ai/harness/controller/packets" \
|
|
612
|
-
"$repo/.ai/harness/projections" \
|
|
613
|
-
"$repo/.ai/harness/transfers" \
|
|
614
|
-
"$repo/.ai/harness/failures" \
|
|
615
|
-
"$repo/.ai/harness/architecture" \
|
|
616
|
-
"$repo/.ai/harness/runs" \
|
|
617
|
-
"$repo/.ai/harness/worktrees" \
|
|
618
|
-
"$repo/.ai/harness/jobs" \
|
|
619
|
-
"$repo/.ai/harness/edit-sessions"
|
|
620
|
-
|
|
621
|
-
if [[ ! -f "$repo/docs/spec.md" ]]; then
|
|
622
|
-
if [[ -f "$repo/.claude/templates/spec.template.md" ]]; then
|
|
623
|
-
sed \
|
|
624
|
-
-e "s/{{PROJECT_NAME}}/${project_name}/g" \
|
|
625
|
-
-e "s/{{TIMESTAMP}}/${timestamp}/g" \
|
|
626
|
-
"$repo/.claude/templates/spec.template.md" > "$repo/docs/spec.md"
|
|
627
|
-
else
|
|
628
|
-
cat > "$repo/docs/spec.md" <<EOF_SPEC
|
|
629
|
-
# Product Spec: ${project_name}
|
|
630
|
-
|
|
631
|
-
> **Status**: Draft
|
|
632
|
-
> **Last Updated**: ${timestamp}
|
|
633
|
-
> **Owner**: Planner
|
|
634
|
-
EOF_SPEC
|
|
635
|
-
fi
|
|
636
|
-
fi
|
|
637
|
-
|
|
638
|
-
if [[ -f "$legacy_todo_file" ]]; then
|
|
639
|
-
mkdir -p "$repo/tasks/archive"
|
|
640
|
-
if [[ ! -f "$legacy_todo_archive" ]]; then
|
|
641
|
-
cp "$legacy_todo_file" "$legacy_todo_archive"
|
|
642
|
-
fi
|
|
643
|
-
if [[ ! -f "$todo_file" ]]; then
|
|
644
|
-
if grep -Eq '^# Deferred Goal Ledger[[:space:]]*$' "$legacy_todo_file" \
|
|
645
|
-
&& grep -Eq '^> \*\*Status\*\*:[[:space:]]*Backlog[[:space:]]*$' "$legacy_todo_file"; then
|
|
646
|
-
cp "$legacy_todo_file" "$todo_file"
|
|
647
|
-
else
|
|
648
|
-
cat > "$todo_file" <<'TODO_EOF'
|
|
649
|
-
# Deferred Goal Ledger
|
|
650
|
-
|
|
651
|
-
> **Status**: Backlog
|
|
652
|
-
> **Updated**: (migration)
|
|
653
|
-
> **Scope**: Medium/long-term goals deferred from active plan execution
|
|
654
|
-
|
|
655
|
-
Current plan tasks live in the active plan's `## Task Breakdown`.
|
|
656
|
-
Do not duplicate that execution checklist here. Record only work intentionally deferred beyond this slice, with the tradeoff and revisit trigger.
|
|
657
|
-
|
|
658
|
-
## Deferred Goals
|
|
659
|
-
|
|
660
|
-
| Goal | Why Deferred | Tradeoff | Revisit Trigger |
|
|
661
|
-
|------|--------------|----------|-----------------|
|
|
662
|
-
| Review archived legacy checklist | Legacy tasks/todo.md contained execution checklist content before migration. | Preserve user-authored task text in tasks/archive instead of guessing which items still matter. | Open the archive and promote real follow-up work into a new plan or a deferred-goal row. |
|
|
663
|
-
TODO_EOF
|
|
664
|
-
fi
|
|
665
|
-
fi
|
|
666
|
-
mv "$legacy_todo_file" "$legacy_todo_file.migrated.bak"
|
|
667
|
-
fi
|
|
668
|
-
|
|
669
|
-
if [[ ! -f "$todo_file" ]]; then
|
|
670
|
-
cat > "$todo_file" <<'TODO_EOF'
|
|
671
|
-
# Deferred Goal Ledger
|
|
672
|
-
|
|
673
|
-
> **Status**: Backlog
|
|
674
|
-
> **Updated**: (migration)
|
|
675
|
-
> **Scope**: Medium/long-term goals deferred from active plan execution
|
|
676
|
-
|
|
677
|
-
Current plan tasks live in the active plan's `## Task Breakdown`.
|
|
678
|
-
Do not duplicate that execution checklist here. Record only work intentionally deferred beyond this slice, with the tradeoff and revisit trigger.
|
|
679
|
-
|
|
680
|
-
## Deferred Goals
|
|
681
|
-
|
|
682
|
-
| Goal | Why Deferred | Tradeoff | Revisit Trigger |
|
|
683
|
-
|------|--------------|----------|-----------------|
|
|
684
|
-
| (none) | No deferred medium/long-term goal recorded yet. | Keep migrated workflow state bounded. | Add a row when a real follow-up is postponed. |
|
|
685
|
-
TODO_EOF
|
|
686
|
-
elif ! grep -Eq '^> \*\*Status\*\*:[[:space:]]*Backlog[[:space:]]*$' "$todo_file"; then
|
|
687
|
-
backup_if_exists "$todo_file"
|
|
688
|
-
cat > "$todo_file" <<'TODO_EOF'
|
|
689
|
-
# Deferred Goal Ledger
|
|
690
|
-
|
|
691
|
-
> **Status**: Backlog
|
|
692
|
-
> **Updated**: (migration)
|
|
693
|
-
> **Scope**: Medium/long-term goals deferred from active plan execution
|
|
694
|
-
|
|
695
|
-
Current plan tasks live in the active plan's `## Task Breakdown`.
|
|
696
|
-
Do not duplicate that execution checklist here. Record only work intentionally deferred beyond this slice, with the tradeoff and revisit trigger.
|
|
697
|
-
|
|
698
|
-
## Deferred Goals
|
|
699
|
-
|
|
700
|
-
| Goal | Why Deferred | Tradeoff | Revisit Trigger |
|
|
701
|
-
|------|--------------|----------|-----------------|
|
|
702
|
-
| Review archived legacy checklist | Legacy tasks/todos.md contained execution checklist content before migration. | Preserve user-authored task text in tasks/archive instead of guessing which items still matter. | Open the archive and promote real follow-up work into a new plan or a deferred-goal row. |
|
|
703
|
-
TODO_EOF
|
|
704
|
-
fi
|
|
705
|
-
|
|
706
|
-
if [[ ! -f "$repo/tasks/current.md" ]]; then
|
|
707
|
-
cat > "$repo/tasks/current.md" <<'CURRENT_STATUS_EOF'
|
|
708
|
-
# Current Status Snapshot
|
|
709
|
-
|
|
710
|
-
<!-- generated-by: forge refresh-current-status v1 -->
|
|
711
|
-
<!-- updated_at: bootstrap -->
|
|
712
|
-
<!-- stale_after: 24h -->
|
|
713
|
-
|
|
714
|
-
> **Status**: Idle
|
|
715
|
-
> **Updated At**: bootstrap
|
|
716
|
-
> **Source Branch**: main
|
|
717
|
-
> **Source Commit**: bootstrap
|
|
718
|
-
> **Target Branch**: main
|
|
719
|
-
> **Stale After**: 24h
|
|
720
|
-
> **Reason**: bootstrap
|
|
721
|
-
> **Derived From**: active-plan, workstreams, handoff, checks, git status
|
|
722
|
-
|
|
723
|
-
This file is a tracked mainline snapshot derived from repo artifacts. It is not a live lock, not a kanban board, and not an implementation gate. If it is stale, read the source artifacts below.
|
|
724
|
-
CURRENT_STATUS_EOF
|
|
725
|
-
fi
|
|
726
|
-
|
|
727
|
-
if [[ ! -f "$repo/tasks/lessons.md" ]]; then
|
|
728
|
-
cat > "$repo/tasks/lessons.md" <<'LESSONS_EOF'
|
|
729
|
-
# Lessons Learned (Self-Improvement Loop)
|
|
730
|
-
|
|
731
|
-
> Capture correction-derived prevention rules here.
|
|
732
|
-
> Promote repeated patterns into durable project rules during spa day.
|
|
733
|
-
|
|
734
|
-
## Template
|
|
735
|
-
- Date:
|
|
736
|
-
- Triggered by correction:
|
|
737
|
-
- Mistake pattern:
|
|
738
|
-
- Prevention rule:
|
|
739
|
-
- Where to apply next time:
|
|
740
|
-
LESSONS_EOF
|
|
741
|
-
fi
|
|
742
|
-
|
|
743
|
-
pi_ensure_harness_state_surface "$repo" "apply"
|
|
744
|
-
|
|
745
|
-
}
|
|
746
|
-
|
|
747
|
-
install_reference_configs() {
|
|
748
|
-
local repo="$1"
|
|
749
|
-
local ref_dir="$repo/docs/reference-configs"
|
|
750
|
-
local ref_assets_dir="$SKILL_ROOT/assets/reference-configs"
|
|
751
|
-
|
|
752
|
-
run_or_echo mkdir -p "$ref_dir"
|
|
753
|
-
|
|
754
|
-
if [[ -d "$ref_assets_dir" ]]; then
|
|
755
|
-
if [[ "$MODE" == "apply" ]]; then
|
|
756
|
-
pi_install_reference_configs "$repo" "$ref_assets_dir" "apply"
|
|
757
|
-
else
|
|
758
|
-
pi_install_reference_configs "$repo" "$ref_assets_dir" "dry-run"
|
|
759
|
-
fi
|
|
760
|
-
fi
|
|
761
|
-
}
|
|
762
|
-
|
|
763
|
-
ensure_ops_scaffold() {
|
|
764
|
-
local repo="$1"
|
|
765
|
-
local deploy_readme="$repo/deploy/README.md"
|
|
766
|
-
|
|
767
|
-
run_or_echo mkdir -p "$repo/deploy/env"
|
|
768
|
-
run_or_echo mkdir -p "$repo/deploy/scripts"
|
|
769
|
-
run_or_echo mkdir -p "$repo/deploy/submissions"
|
|
770
|
-
run_or_echo mkdir -p "$repo/deploy/runbooks"
|
|
771
|
-
run_or_echo mkdir -p "$repo/deploy/release-checklists"
|
|
772
|
-
run_or_echo mkdir -p "$repo/deploy/sql"
|
|
773
|
-
run_or_echo mkdir -p "$repo/_ops/env"
|
|
774
|
-
run_or_echo mkdir -p "$repo/_ops/secrets"
|
|
775
|
-
run_or_echo mkdir -p "$repo/_ops/artifacts"
|
|
776
|
-
run_or_echo mkdir -p "$repo/_ops/logs"
|
|
777
|
-
run_or_echo mkdir -p "$repo/_ops/state"
|
|
778
|
-
run_or_echo mkdir -p "$repo/_ops/scratch"
|
|
779
|
-
|
|
780
|
-
if [[ "$MODE" != "apply" ]]; then
|
|
781
|
-
echo "[dry-run] ensure deploy workspace README, tracked placeholders, deploy/sql, and ignored _ops private state"
|
|
782
|
-
echo "[dry-run] migrate legacy _ops runbooks/scripts/submissions/env examples into deploy/"
|
|
783
|
-
return 0
|
|
784
|
-
fi
|
|
785
|
-
|
|
786
|
-
migrate_legacy_ops_asset() {
|
|
787
|
-
local src="$1"
|
|
788
|
-
local dest="$2"
|
|
789
|
-
if [[ -e "$src" && ! -e "$dest" ]]; then
|
|
790
|
-
mv "$src" "$dest"
|
|
791
|
-
fi
|
|
792
|
-
}
|
|
793
|
-
|
|
794
|
-
migrate_legacy_ops_children() {
|
|
795
|
-
local src_dir="$1"
|
|
796
|
-
local dest_dir="$2"
|
|
797
|
-
local src
|
|
798
|
-
local base
|
|
799
|
-
[[ -d "$src_dir" ]] || return 0
|
|
800
|
-
shopt -s nullglob dotglob
|
|
801
|
-
for src in "$src_dir"/*; do
|
|
802
|
-
base="$(basename "$src")"
|
|
803
|
-
[[ "$base" == ".gitkeep" ]] && continue
|
|
804
|
-
migrate_legacy_ops_asset "$src" "$dest_dir/$base"
|
|
805
|
-
done
|
|
806
|
-
shopt -u nullglob dotglob
|
|
807
|
-
}
|
|
808
|
-
|
|
809
|
-
migrate_legacy_ops_asset "$repo/_ops/env/.env.example" "$repo/deploy/env/.env.example"
|
|
810
|
-
migrate_legacy_ops_children "$repo/_ops/scripts" "$repo/deploy/scripts"
|
|
811
|
-
migrate_legacy_ops_children "$repo/_ops/submissions" "$repo/deploy/submissions"
|
|
812
|
-
migrate_legacy_ops_children "$repo/_ops/sql" "$repo/deploy/sql"
|
|
813
|
-
|
|
814
|
-
shopt -s nullglob
|
|
815
|
-
for legacy_doc in "$repo/_ops"/*.md; do
|
|
816
|
-
legacy_base="$(basename "$legacy_doc")"
|
|
817
|
-
[[ "$legacy_base" == "README.md" ]] && continue
|
|
818
|
-
migrate_legacy_ops_asset "$legacy_doc" "$repo/deploy/$legacy_base"
|
|
819
|
-
done
|
|
820
|
-
shopt -u nullglob
|
|
821
|
-
|
|
822
|
-
shopt -s nullglob
|
|
823
|
-
for legacy_sql in "$repo/_ops"/*.sql; do
|
|
824
|
-
legacy_base="$(basename "$legacy_sql")"
|
|
825
|
-
migrate_legacy_ops_asset "$legacy_sql" "$repo/deploy/sql/$legacy_base"
|
|
826
|
-
done
|
|
827
|
-
shopt -u nullglob
|
|
828
|
-
|
|
829
|
-
touch "$repo/deploy/env/.gitkeep"
|
|
830
|
-
touch "$repo/deploy/scripts/.gitkeep"
|
|
831
|
-
touch "$repo/deploy/submissions/.gitkeep"
|
|
832
|
-
touch "$repo/deploy/runbooks/.gitkeep"
|
|
833
|
-
touch "$repo/deploy/release-checklists/.gitkeep"
|
|
834
|
-
touch "$repo/deploy/sql/.gitkeep"
|
|
835
|
-
|
|
836
|
-
if [[ ! -f "$deploy_readme" ]]; then
|
|
837
|
-
cat > "$deploy_readme" <<'DEPLOY_README_EOF'
|
|
838
|
-
# Deployment Operations
|
|
839
|
-
|
|
840
|
-
`deploy/` is a commit-ready surface for deployment and operations runbooks, submission materials, release checklists, helper scripts, and env examples.
|
|
841
|
-
|
|
842
|
-
## Track
|
|
843
|
-
|
|
844
|
-
- `deploy/scripts/` for operational scripts.
|
|
845
|
-
- `deploy/submissions/` for submission or review materials.
|
|
846
|
-
- `deploy/runbooks/` and `deploy/release-checklists/` for operational documentation.
|
|
847
|
-
- `deploy/sql/` for ordered deployment SQL files named like `0001_create_tables.sql`.
|
|
848
|
-
- `deploy/*.md` for runbooks and operating notes.
|
|
849
|
-
- `deploy/env/.env.example` for documented variable shapes only.
|
|
850
|
-
|
|
851
|
-
## Do Not Track
|
|
852
|
-
|
|
853
|
-
- `_ops/`
|
|
854
|
-
- private keys, real env files, provider state, production tokens, credential dumps, artifacts, logs, and local-only overrides
|
|
855
|
-
|
|
856
|
-
Keep external upstream checkouts and source references in `_ref/`; `_ref/` is ignored and must stay out of commits.
|
|
857
|
-
DEPLOY_README_EOF
|
|
858
|
-
fi
|
|
859
|
-
}
|
|
860
|
-
|
|
861
|
-
ensure_research_surface() {
|
|
862
|
-
local repo="$1"
|
|
863
|
-
local research_dir="$repo/docs/researches"
|
|
864
|
-
local research_readme="$research_dir/README.md"
|
|
865
|
-
local legacy_research="$repo/tasks/research.md"
|
|
866
|
-
local legacy_archive="$research_dir/legacy-research-notes.md"
|
|
867
|
-
|
|
868
|
-
if [[ "$MODE" != "apply" ]]; then
|
|
869
|
-
echo "[dry-run] ensure research reports directory at $research_dir"
|
|
870
|
-
if [[ -f "$legacy_research" ]]; then
|
|
871
|
-
echo "[dry-run] archive legacy $legacy_research into $legacy_archive and leave a tombstone"
|
|
872
|
-
fi
|
|
873
|
-
return
|
|
874
|
-
fi
|
|
875
|
-
|
|
876
|
-
mkdir -p "$research_dir"
|
|
877
|
-
|
|
878
|
-
if [[ ! -f "$research_readme" ]]; then
|
|
879
|
-
cat > "$research_readme" <<'RESEARCH_README_EOF'
|
|
880
|
-
# Research Reports
|
|
881
|
-
|
|
882
|
-
Durable research reports live in this directory as dated Markdown files.
|
|
883
|
-
|
|
884
|
-
Use `YYYYMMDD-topic.md` names for new reports. Keep task-local implementation
|
|
885
|
-
decisions in `tasks/notes/`, and keep repeated correction-derived rules in
|
|
886
|
-
`tasks/lessons.md`.
|
|
887
|
-
RESEARCH_README_EOF
|
|
888
|
-
fi
|
|
889
|
-
|
|
890
|
-
if [[ -f "$legacy_research" ]]; then
|
|
891
|
-
if [[ ! -f "$legacy_archive" ]]; then
|
|
892
|
-
cp "$legacy_research" "$legacy_archive"
|
|
893
|
-
fi
|
|
894
|
-
|
|
895
|
-
cat > "$legacy_research" <<'RESEARCH_TOMBSTONE_EOF'
|
|
896
|
-
# Research Notes Moved
|
|
897
|
-
|
|
898
|
-
> **Status**: Retired tombstone
|
|
899
|
-
> **Canonical Surface**: `docs/researches/`
|
|
900
|
-
> **Legacy Archive**: `docs/researches/legacy-research-notes.md`
|
|
901
|
-
|
|
902
|
-
Durable research reports now live under `docs/researches/*.md`. This file is
|
|
903
|
-
kept only as a transition pointer for older tooling and historical links; do
|
|
904
|
-
not add new findings here.
|
|
905
|
-
RESEARCH_TOMBSTONE_EOF
|
|
906
|
-
fi
|
|
907
|
-
}
|
|
908
|
-
|
|
909
|
-
parse_args() {
|
|
910
|
-
while [[ $# -gt 0 ]]; do
|
|
911
|
-
case "$1" in
|
|
912
|
-
--repo)
|
|
913
|
-
TARGET_REPO="${2:-}"
|
|
914
|
-
shift 2
|
|
915
|
-
;;
|
|
916
|
-
--dry-run)
|
|
917
|
-
MODE="dry-run"
|
|
918
|
-
shift
|
|
919
|
-
;;
|
|
920
|
-
--apply)
|
|
921
|
-
MODE="apply"
|
|
922
|
-
shift
|
|
923
|
-
;;
|
|
924
|
-
--help)
|
|
925
|
-
usage
|
|
926
|
-
exit 0
|
|
927
|
-
;;
|
|
928
|
-
*)
|
|
929
|
-
echo "Unknown argument: $1" >&2
|
|
930
|
-
usage
|
|
931
|
-
exit 1
|
|
932
|
-
;;
|
|
933
|
-
esac
|
|
934
|
-
done
|
|
935
|
-
}
|
|
936
|
-
|
|
937
|
-
require_repo() {
|
|
938
|
-
if [[ -z "$TARGET_REPO" ]]; then
|
|
939
|
-
echo "--repo is required" >&2
|
|
940
|
-
usage
|
|
941
|
-
exit 1
|
|
942
|
-
fi
|
|
943
|
-
|
|
944
|
-
if [[ ! -d "$TARGET_REPO" ]]; then
|
|
945
|
-
echo "Repo path does not exist: $TARGET_REPO" >&2
|
|
946
|
-
exit 1
|
|
947
|
-
fi
|
|
948
|
-
|
|
949
|
-
local target_physical
|
|
950
|
-
target_physical="$(cd "$TARGET_REPO" && pwd -P)"
|
|
951
|
-
local home_physical=""
|
|
952
|
-
if [[ -n "${HOME:-}" && -d "$HOME" ]]; then
|
|
953
|
-
home_physical="$(cd "$HOME" && pwd -P)"
|
|
954
|
-
fi
|
|
955
|
-
|
|
956
|
-
if [[ -n "$home_physical" && "$target_physical" == "$home_physical" ]]; then
|
|
957
|
-
echo "Refusing to migrate HOME as a repo target: $target_physical" >&2
|
|
958
|
-
echo "Run forge adopt --repo <git-repo> from an intended project." >&2
|
|
959
|
-
exit 2
|
|
960
|
-
fi
|
|
961
|
-
}
|
|
962
|
-
|
|
963
|
-
inspect_project_state() {
|
|
964
|
-
local repo="$1"
|
|
965
|
-
local inspector="$SCRIPT_DIR/inspect-project-state.ts"
|
|
966
|
-
|
|
967
|
-
if [[ ! -f "$inspector" ]]; then
|
|
968
|
-
log "Project-state inspector missing: $inspector"
|
|
969
|
-
return 1
|
|
970
|
-
fi
|
|
971
|
-
|
|
972
|
-
INSPECT_OUTPUT="$(run_ts_script "$inspector" --repo "$repo" --format text)"
|
|
973
|
-
printf '%s\n' "$INSPECT_OUTPUT"
|
|
974
|
-
}
|
|
975
|
-
|
|
976
|
-
migrate_hooks() {
|
|
977
|
-
local repo="$1"
|
|
978
|
-
local project_claude_dir="$repo/.claude"
|
|
979
|
-
local project_ai_hooks_dir="$repo/.ai/hooks"
|
|
980
|
-
|
|
981
|
-
run_or_echo mkdir -p "$project_claude_dir" "$project_ai_hooks_dir"
|
|
982
|
-
|
|
983
|
-
cleanup_removed_workflow_assets "$repo"
|
|
984
|
-
pi_install_hook_assets "$repo" "$HOOK_ASSETS_DIR" "$MODE"
|
|
985
|
-
pi_install_hook_adapters "$repo" "$HOOK_ASSETS_DIR" "$MODE"
|
|
986
|
-
}
|
|
987
|
-
|
|
988
|
-
migrate_docs() {
|
|
989
|
-
local repo="$1"
|
|
990
|
-
local migrator="$SCRIPT_DIR/migrate-workflow-docs.ts"
|
|
991
|
-
|
|
992
|
-
if [[ ! -f "$migrator" ]]; then
|
|
993
|
-
log "Legacy-doc migrator missing: $migrator"
|
|
994
|
-
return 1
|
|
995
|
-
fi
|
|
996
|
-
|
|
997
|
-
if [[ "$MODE" == "apply" ]]; then
|
|
998
|
-
run_ts_script "$migrator" --repo "$repo" --apply
|
|
999
|
-
else
|
|
1000
|
-
run_ts_script "$migrator" --repo "$repo" --dry-run
|
|
1001
|
-
fi
|
|
1002
|
-
}
|
|
1003
|
-
|
|
1004
|
-
migrate_workflow() {
|
|
1005
|
-
local repo="$1"
|
|
1006
|
-
|
|
1007
|
-
run_or_echo mkdir -p "$repo/plans/archive"
|
|
1008
|
-
run_or_echo mkdir -p "$repo/plans/prds"
|
|
1009
|
-
run_or_echo mkdir -p "$repo/plans/sprints"
|
|
1010
|
-
run_or_echo mkdir -p "$repo/tasks/archive"
|
|
1011
|
-
run_or_echo mkdir -p "$repo/tasks/contracts"
|
|
1012
|
-
run_or_echo mkdir -p "$repo/tasks/reviews"
|
|
1013
|
-
run_or_echo mkdir -p "$repo/tasks/notes"
|
|
1014
|
-
run_or_echo mkdir -p "$repo/tasks/workstreams"
|
|
1015
|
-
run_or_echo mkdir -p "$repo/docs/reference-configs"
|
|
1016
|
-
run_or_echo mkdir -p "$repo/.ai/harness/checks"
|
|
1017
|
-
run_or_echo mkdir -p "$repo/.ai/harness/session" "$repo/.ai/harness/controller/packets" "$repo/.ai/harness/projections" "$repo/.ai/harness/transfers"
|
|
1018
|
-
migrate_active_plan_marker "$repo"
|
|
1019
|
-
|
|
1020
|
-
install_templates "$repo"
|
|
1021
|
-
install_helpers "$repo"
|
|
1022
|
-
install_workflow_contract "$repo"
|
|
1023
|
-
if pi_should_enable_factor_factory "$(pi_plan_type)"; then
|
|
1024
|
-
pi_install_factor_factory "$repo" "$FACTOR_FACTORY_ASSETS_DIR" "$SKILL_ROOT/scripts" "$MODE"
|
|
1025
|
-
fi
|
|
1026
|
-
install_reference_configs "$repo"
|
|
1027
|
-
ensure_ops_scaffold "$repo"
|
|
1028
|
-
ensure_research_surface "$repo"
|
|
1029
|
-
migrate_legacy_sprint_prds "$repo"
|
|
1030
|
-
create_task_files_if_missing "$repo"
|
|
1031
|
-
ensure_task_sync_package_script "$repo"
|
|
1032
|
-
|
|
1033
|
-
local repo_gitignore="$repo/.gitignore"
|
|
1034
|
-
run_or_echo touch "$repo_gitignore"
|
|
1035
|
-
ensure_gitignore_entry "$repo_gitignore" "# Project-specific"
|
|
1036
|
-
ensure_gitignore_entry "$repo_gitignore" "artifacts/"
|
|
1037
|
-
ensure_gitignore_entry "$repo_gitignore" "coverage/"
|
|
1038
|
-
ensure_gitignore_entry "$repo_gitignore" "*.tar.gz"
|
|
1039
|
-
ensure_gitignore_entry "$repo_gitignore" "*.tgz"
|
|
1040
|
-
ensure_gitignore_entry "$repo_gitignore" "# External references"
|
|
1041
|
-
ensure_gitignore_entry "$repo_gitignore" "_ref/"
|
|
1042
|
-
ensure_gitignore_entry "$repo_gitignore" ".codegraph/"
|
|
1043
|
-
ensure_gitignore_entry "$repo_gitignore" "# Local operations state"
|
|
1044
|
-
ensure_gitignore_entry "$repo_gitignore" "_ops/"
|
|
1045
|
-
ensure_gitignore_entry "$repo_gitignore" "# Environment"
|
|
1046
|
-
ensure_gitignore_entry "$repo_gitignore" ".env"
|
|
1047
|
-
ensure_gitignore_entry "$repo_gitignore" ".env.*"
|
|
1048
|
-
ensure_gitignore_entry "$repo_gitignore" "!.env.example"
|
|
1049
|
-
ensure_gitignore_entry "$repo_gitignore" "# OS metadata"
|
|
1050
|
-
ensure_gitignore_entry "$repo_gitignore" ".DS_Store"
|
|
1051
|
-
ensure_runtime_gitignore_block "$repo" "$repo_gitignore"
|
|
1052
|
-
untrack_generated_helper_wrappers "$repo"
|
|
1053
|
-
|
|
1054
|
-
}
|
|
1055
|
-
|
|
1056
|
-
verify_migration_contract() {
|
|
1057
|
-
local repo="$1"
|
|
1058
|
-
local check_script="$repo/scripts/check-task-workflow.sh"
|
|
1059
|
-
local handoff_script="$repo/scripts/prepare-codex-handoff.sh"
|
|
1060
|
-
|
|
1061
|
-
if [[ "$MODE" != "apply" ]]; then
|
|
1062
|
-
echo "[dry-run] refresh Codex handoff before workflow verify"
|
|
1063
|
-
echo "[dry-run] verify migrated workflow with forge run check-task-workflow --strict"
|
|
1064
|
-
return 0
|
|
1065
|
-
fi
|
|
1066
|
-
|
|
1067
|
-
if [[ ! -f "$check_script" ]]; then
|
|
1068
|
-
log "Missing workflow check script after migration: $check_script"
|
|
1069
|
-
return 1
|
|
1070
|
-
fi
|
|
1071
|
-
|
|
1072
|
-
if [[ -f "$handoff_script" ]]; then
|
|
1073
|
-
(cd "$repo" && FORGE_SOURCE_ROOT="$SKILL_ROOT" bash "scripts/prepare-codex-handoff.sh" --reason "forge-migration-verify" >/dev/null)
|
|
1074
|
-
log "Refreshed Codex handoff before workflow verify"
|
|
1075
|
-
fi
|
|
1076
|
-
|
|
1077
|
-
(cd "$repo" && FORGE_SOURCE_ROOT="$SKILL_ROOT" bash "scripts/check-task-workflow.sh" --strict)
|
|
1078
|
-
}
|
|
1079
|
-
|
|
1080
|
-
print_report() {
|
|
1081
|
-
local repo="$1"
|
|
1082
|
-
echo
|
|
1083
|
-
echo "=== Migration Report ==="
|
|
1084
|
-
echo "Mode: $MODE"
|
|
1085
|
-
echo "Repo: $repo"
|
|
1086
|
-
if [[ -n "$INSPECT_OUTPUT" ]]; then
|
|
1087
|
-
echo "--- Inspection ---"
|
|
1088
|
-
printf '%s\n' "$INSPECT_OUTPUT"
|
|
1089
|
-
fi
|
|
1090
|
-
echo "- Project hooks synced from: $HOOK_ASSETS_DIR (repo-local fallback; lib-only unless hook_source=repo)"
|
|
1091
|
-
echo "- Host hook config target: user-level ~/.claude/settings.json and ~/.codex/hooks.json"
|
|
1092
|
-
echo "- $(pi_print_codex_hook_trust_notice)"
|
|
1093
|
-
echo "- Legacy docs/TODO.md / docs/plan.md / docs/PROGRESS.md: migrated by scripts/migrate-workflow-docs.ts"
|
|
1094
|
-
echo "- Workflow migration: docs/spec.md + plans/ + tasks/contracts + tasks/reviews + .ai/context/context-map.json + .ai/harness/*"
|
|
1095
|
-
echo "- Workflow contract manifest installed at: .ai/harness/workflow-contract.json"
|
|
1096
|
-
echo "- Helper runtime: package-dispatched through forge run with scripts/* compatibility wrappers"
|
|
1097
|
-
echo "- Upgrade/reconfigure/cleanup plan: generated from workflow contract migrations.upgrade"
|
|
1098
|
-
echo "- Existing external_tooling overrides are preserved; missing defaults are merged into .ai/harness/policy.json"
|
|
1099
|
-
echo "- Runtime temporary ignore block synced to .gitignore"
|
|
1100
|
-
pi_print_external_tooling_report "$repo" "$MODE" "$SCRIPT_DIR/check-agent-tooling.sh"
|
|
1101
|
-
}
|
|
1102
|
-
|
|
1103
|
-
run_skill_hook() {
|
|
1104
|
-
local event="$1"
|
|
1105
|
-
local hook_script="$SCRIPT_DIR/run-skill-hook.ts"
|
|
1106
|
-
|
|
1107
|
-
if command -v bun >/dev/null 2>&1 && [[ -f "$hook_script" ]]; then
|
|
1108
|
-
bun "$hook_script" "$event" --context "{\"repo\":\"$TARGET_REPO\",\"mode\":\"$MODE\"}" 2>&1 || {
|
|
1109
|
-
if [[ "$event" == pre-* ]]; then
|
|
1110
|
-
log "Pre-hook $event failed, aborting."
|
|
1111
|
-
return 1
|
|
1112
|
-
else
|
|
1113
|
-
log "Post-hook $event warning (non-fatal)."
|
|
1114
|
-
fi
|
|
1115
|
-
}
|
|
1116
|
-
fi
|
|
1117
|
-
}
|
|
1118
|
-
|
|
1119
|
-
update_version_stamp() {
|
|
1120
|
-
local repo="$1"
|
|
1121
|
-
local stamp_file="$repo/.claude/.skill-version"
|
|
1122
|
-
local skill_version_file="$SKILL_ROOT/assets/skill-version.json"
|
|
1123
|
-
local sv_version="unknown"
|
|
1124
|
-
local sv_template_version="unknown"
|
|
1125
|
-
|
|
1126
|
-
if [[ -f "$skill_version_file" ]] && command -v bun >/dev/null 2>&1; then
|
|
1127
|
-
sv_version=$(bun -e "console.log(JSON.parse(require('fs').readFileSync('$skill_version_file','utf-8')).version)")
|
|
1128
|
-
sv_template_version=$(bun -e "console.log(JSON.parse(require('fs').readFileSync('$skill_version_file','utf-8')).templateVersion)")
|
|
1129
|
-
elif [[ -f "$skill_version_file" ]] && command -v node >/dev/null 2>&1; then
|
|
1130
|
-
sv_version=$(node -e "console.log(JSON.parse(require('fs').readFileSync('$skill_version_file','utf-8')).version)")
|
|
1131
|
-
sv_template_version=$(node -e "console.log(JSON.parse(require('fs').readFileSync('$skill_version_file','utf-8')).templateVersion)")
|
|
1132
|
-
fi
|
|
1133
|
-
|
|
1134
|
-
if [[ "$MODE" == "apply" ]]; then
|
|
1135
|
-
local existing_skill_version=""
|
|
1136
|
-
local existing_template_version=""
|
|
1137
|
-
local existing_migrated_at=""
|
|
1138
|
-
local migrated_at=""
|
|
1139
|
-
|
|
1140
|
-
if [[ -f "$stamp_file" ]]; then
|
|
1141
|
-
existing_skill_version="$(awk -F= '$1 == "skill_version" { print $2 }' "$stamp_file" 2>/dev/null || true)"
|
|
1142
|
-
existing_template_version="$(awk -F= '$1 == "template_version" { print $2 }' "$stamp_file" 2>/dev/null || true)"
|
|
1143
|
-
existing_migrated_at="$(awk -F= '$1 == "migrated_at" { print $2 }' "$stamp_file" 2>/dev/null || true)"
|
|
1144
|
-
fi
|
|
1145
|
-
|
|
1146
|
-
if [[ "$existing_skill_version" == "$sv_version" && "$existing_template_version" == "$sv_template_version" && -n "$existing_migrated_at" ]]; then
|
|
1147
|
-
migrated_at="$existing_migrated_at"
|
|
1148
|
-
else
|
|
1149
|
-
migrated_at="$(date -u '+%Y-%m-%dT%H:%M:%SZ')"
|
|
1150
|
-
fi
|
|
1151
|
-
|
|
1152
|
-
mkdir -p "$(dirname "$stamp_file")"
|
|
1153
|
-
local stamp_tmp
|
|
1154
|
-
stamp_tmp="$(mktemp)"
|
|
1155
|
-
cat > "$stamp_tmp" <<STAMP_EOF
|
|
1156
|
-
skill_version=$sv_version
|
|
1157
|
-
template_version=$sv_template_version
|
|
1158
|
-
migrated_at=$migrated_at
|
|
1159
|
-
STAMP_EOF
|
|
1160
|
-
if [[ -f "$stamp_file" ]] && cmp -s "$stamp_tmp" "$stamp_file"; then
|
|
1161
|
-
rm -f "$stamp_tmp"
|
|
1162
|
-
log "Version stamp already current: $stamp_file"
|
|
1163
|
-
else
|
|
1164
|
-
mv "$stamp_tmp" "$stamp_file"
|
|
1165
|
-
log "Version stamp updated: $stamp_file"
|
|
1166
|
-
fi
|
|
1167
|
-
else
|
|
1168
|
-
echo "[dry-run] update version stamp at $stamp_file (skill=$sv_version, template=$sv_template_version)"
|
|
1169
|
-
fi
|
|
1170
|
-
}
|
|
1171
|
-
|
|
1172
|
-
main() {
|
|
1173
|
-
parse_args "$@"
|
|
1174
|
-
require_repo
|
|
1175
|
-
|
|
1176
|
-
TARGET_REPO="$(cd "$TARGET_REPO" && pwd)"
|
|
1177
|
-
log "Starting migration ($MODE) for $TARGET_REPO"
|
|
1178
|
-
|
|
1179
|
-
run_skill_hook "pre-migrate" || exit 1
|
|
1180
|
-
|
|
1181
|
-
inspect_project_state "$TARGET_REPO" || exit 1
|
|
1182
|
-
migrate_hooks "$TARGET_REPO"
|
|
1183
|
-
migrate_docs "$TARGET_REPO"
|
|
1184
|
-
migrate_workflow "$TARGET_REPO"
|
|
1185
|
-
update_version_stamp "$TARGET_REPO"
|
|
1186
|
-
verify_migration_contract "$TARGET_REPO" || exit 1
|
|
1187
|
-
print_report "$TARGET_REPO"
|
|
1188
|
-
|
|
1189
|
-
run_skill_hook "post-migrate"
|
|
1190
|
-
}
|
|
1191
|
-
|
|
1192
|
-
main "$@"
|
|
4
|
+
exec "$SCRIPT_DIR/lib/run-forge-helper.sh" "migrate-project-template.sh" "$@"
|