@moretea-labs/forge 1.5.0-rc.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 +120 -0
- package/CHANGELOG.md +36 -0
- package/CLAUDE.md +120 -0
- package/CODE_OF_CONDUCT.md +23 -0
- package/CONTRIBUTING.md +77 -0
- package/LICENSE +22 -0
- package/NOTICE +9 -0
- package/README.en.md +5 -0
- package/README.es.md +12 -0
- package/README.fr.md +12 -0
- package/README.ja.md +12 -0
- package/README.md +132 -0
- package/README.zh-CN.md +84 -0
- package/SECURITY.md +50 -0
- package/SKILL.md +431 -0
- package/SUPPORT.md +31 -0
- package/THIRD_PARTY_NOTICES.md +18 -0
- package/agents/openai.yaml +4 -0
- package/assets/AGENTS.md +68 -0
- package/assets/CLAUDE.md +68 -0
- package/assets/branding/README.md +10 -0
- package/assets/branding/forge-controller-flow.mmd +8 -0
- package/assets/hooks/AGENTS.md +75 -0
- package/assets/hooks/CLAUDE.md +75 -0
- package/assets/hooks/anti-simplification.sh +12 -0
- package/assets/hooks/changelog-guard.sh +80 -0
- package/assets/hooks/codex.hooks.template.json +60 -0
- package/assets/hooks/first-principles-guard.sh +72 -0
- package/assets/hooks/hook-input.sh +618 -0
- package/assets/hooks/lib/session-state.sh +106 -0
- package/assets/hooks/lib/workflow-state.sh +1730 -0
- package/assets/hooks/post-bash.sh +215 -0
- package/assets/hooks/post-edit-guard.sh +256 -0
- package/assets/hooks/post-tool-observer.sh +99 -0
- package/assets/hooks/pre-edit-guard.sh +240 -0
- package/assets/hooks/prompt-guard.sh +1077 -0
- package/assets/hooks/run-hook.sh +67 -0
- package/assets/hooks/security-sentinel.sh +115 -0
- package/assets/hooks/session-start-context.sh +593 -0
- package/assets/hooks/settings.template.json +60 -0
- package/assets/hooks/stop-orchestrator.sh +171 -0
- package/assets/hooks/subagent-return-channel-guard.sh +107 -0
- package/assets/hooks/worktree-guard.sh +39 -0
- package/assets/initializer-question-pack.v1.json +132 -0
- package/assets/initializer-question-pack.v1.schema.json +46 -0
- package/assets/initializer-question-pack.v2.json +174 -0
- package/assets/initializer-question-pack.v3.json +206 -0
- package/assets/initializer-question-pack.v3.schema.json +92 -0
- package/assets/initializer-question-pack.v4.json +557 -0
- package/assets/initializer-question-pack.v4.schema.json +169 -0
- package/assets/partials/01-header.partial.md +10 -0
- package/assets/partials/02-iron-rules.partial.md +30 -0
- package/assets/partials/03-philosophy.partial.md +32 -0
- package/assets/partials/04-project-structure.partial.md +56 -0
- package/assets/partials/05-workflow.partial.md +79 -0
- package/assets/partials/06-cloudflare.partial.md +20 -0
- package/assets/partials/07-footer.partial.md +38 -0
- package/assets/partials/08-orchestration.partial.md +49 -0
- package/assets/partials/09-compact-instructions.partial.md +11 -0
- package/assets/partials/_assembly-order.md +40 -0
- package/assets/partials-agents/01-header.partial.md +8 -0
- package/assets/partials-agents/02-operating-mode.partial.md +44 -0
- package/assets/partials-agents/03-orchestration.partial.md +45 -0
- package/assets/partials-agents/04-task-protocol.partial.md +69 -0
- package/assets/partials-agents/05-coding-constraints.partial.md +20 -0
- package/assets/partials-agents/06-quality-safety.partial.md +23 -0
- package/assets/partials-agents/07-cloudflare.partial.md +9 -0
- package/assets/partials-agents/08-deep-docs.partial.md +32 -0
- package/assets/plan-map.json +301 -0
- package/assets/plugin-registry.v1.json +8 -0
- package/assets/project-structures/ai-native-collaborative-editor.txt +25 -0
- package/assets/project-structures/ai-native-product-copilot.txt +21 -0
- package/assets/project-structures/ai-native-runtime-console.txt +25 -0
- package/assets/project-structures/ai-native-sidecar-kernel.txt +19 -0
- package/assets/project-structures/astro-ssr.txt +25 -0
- package/assets/project-structures/expo-nativewind.txt +52 -0
- package/assets/project-structures/monorepo.txt +63 -0
- package/assets/project-structures/remix.txt +50 -0
- package/assets/project-structures/tanstack-start-workers.txt +51 -0
- package/assets/project-structures/vite-tanstack.txt +58 -0
- package/assets/reference-configs/AGENTS.md +13 -0
- package/assets/reference-configs/CLAUDE.md +13 -0
- package/assets/reference-configs/agentic-development-flow.md +94 -0
- package/assets/reference-configs/ai-workflows.md +14 -0
- package/assets/reference-configs/changelog-versioning.md +13 -0
- package/assets/reference-configs/coding-standards.md +14 -0
- package/assets/reference-configs/development-protocol.md +21 -0
- package/assets/reference-configs/document-generation.md +38 -0
- package/assets/reference-configs/evaluator-rubric.md +19 -0
- package/assets/reference-configs/external-tooling.md +374 -0
- package/assets/reference-configs/git-strategy.md +14 -0
- package/assets/reference-configs/global-working-rules.md +64 -0
- package/assets/reference-configs/handoff-protocol.md +38 -0
- package/assets/reference-configs/harness-overview.md +124 -0
- package/assets/reference-configs/heartbeat-triage.md +57 -0
- package/assets/reference-configs/hook-operations.md +96 -0
- package/assets/reference-configs/release-deploy.md +40 -0
- package/assets/reference-configs/spa-day-protocol.md +14 -0
- package/assets/reference-configs/sprint-contracts.md +89 -0
- package/assets/reference-configs/workflow-orchestration.md +14 -0
- package/assets/skill-hooks.json +41 -0
- package/assets/skill-version.json +189 -0
- package/assets/skills/claude-review/SKILL.md +231 -0
- package/assets/skills/codex-review/SKILL.md +103 -0
- package/assets/templates/AGENTS.md +13 -0
- package/assets/templates/CLAUDE.md +13 -0
- package/assets/templates/architecture.template.md +80 -0
- package/assets/templates/brief.template.md +38 -0
- package/assets/templates/contract.template.md +104 -0
- package/assets/templates/decisions.template.md +85 -0
- package/assets/templates/factor-factory/factor-backtest-report.template.md +36 -0
- package/assets/templates/factor-factory/factor-hypothesis.template.md +30 -0
- package/assets/templates/factor-factory/factor-registry.template.json +5 -0
- package/assets/templates/gitignore.template +53 -0
- package/assets/templates/guides/metro-esm-gotchas.template.md +46 -0
- package/assets/templates/helpers/architecture-event.ts +822 -0
- package/assets/templates/helpers/architecture-queue.sh +647 -0
- package/assets/templates/helpers/archive-architecture-request.sh +244 -0
- package/assets/templates/helpers/archive-workflow.sh +295 -0
- package/assets/templates/helpers/capability-config.ts +394 -0
- package/assets/templates/helpers/capability-resolver.ts +505 -0
- package/assets/templates/helpers/capture-plan.sh +335 -0
- package/assets/templates/helpers/check-agent-tooling.sh +1533 -0
- package/assets/templates/helpers/check-architecture-sync.sh +287 -0
- package/assets/templates/helpers/check-brain-manifest.sh +255 -0
- package/assets/templates/helpers/check-context-files.sh +49 -0
- package/assets/templates/helpers/check-deploy-sql-order.sh +117 -0
- package/assets/templates/helpers/check-skill-version.ts +193 -0
- package/assets/templates/helpers/check-task-sync.sh +65 -0
- package/assets/templates/helpers/check-task-workflow.sh +1002 -0
- package/assets/templates/helpers/codex-handoff-resume.sh +269 -0
- package/assets/templates/helpers/context-contract-sync.sh +516 -0
- package/assets/templates/helpers/contract-run.ts +465 -0
- package/assets/templates/helpers/contract-worktree.sh +725 -0
- package/assets/templates/helpers/ensure-task-workflow.sh +1218 -0
- package/assets/templates/helpers/harness-trace-grade.sh +150 -0
- package/assets/templates/helpers/heartbeat-triage.sh +361 -0
- package/assets/templates/helpers/inspect-project-state.ts +280 -0
- package/assets/templates/helpers/maintenance-triage.sh +167 -0
- package/assets/templates/helpers/migrate-project-template.sh +54 -0
- package/assets/templates/helpers/migrate-workflow-docs.ts +413 -0
- package/assets/templates/helpers/new-plan.sh +183 -0
- package/assets/templates/helpers/new-spec.sh +50 -0
- package/assets/templates/helpers/new-sprint.sh +49 -0
- package/assets/templates/helpers/plan-to-todo.sh +799 -0
- package/assets/templates/helpers/prepare-codex-handoff.sh +203 -0
- package/assets/templates/helpers/prepare-handoff.sh +81 -0
- package/assets/templates/helpers/refresh-current-status.sh +469 -0
- package/assets/templates/helpers/select-agent-context-blocks.sh +66 -0
- package/assets/templates/helpers/ship-worktrees.sh +561 -0
- package/assets/templates/helpers/sprint-backlog.sh +837 -0
- package/assets/templates/helpers/summarize-failures.sh +125 -0
- package/assets/templates/helpers/switch-plan.sh +153 -0
- package/assets/templates/helpers/sync-brain-docs.sh +381 -0
- package/assets/templates/helpers/verify-contract.sh +705 -0
- package/assets/templates/helpers/verify-sprint.sh +680 -0
- package/assets/templates/helpers/workflow-contract.ts +202 -0
- package/assets/templates/helpers/workstream-sync.sh +263 -0
- package/assets/templates/implementation-notes.template.md +37 -0
- package/assets/templates/packages.template.md +45 -0
- package/assets/templates/plan.template.md +77 -0
- package/assets/templates/prd.template.md +165 -0
- package/assets/templates/research.template.md +25 -0
- package/assets/templates/review.template.md +78 -0
- package/assets/templates/spec.template.md +31 -0
- package/assets/templates/sprint.template.md +69 -0
- package/assets/templates/tech-stack.template.md +57 -0
- package/assets/versions.json +77 -0
- package/assets/workflow-contract.v1.json +671 -0
- package/bin/forge-desktop-helper.mjs +204 -0
- package/bin/forge-hook.mjs +32 -0
- package/bin/forge-runtime-service.mjs +34 -0
- package/bin/forge-runtime.mjs +30 -0
- package/bin/forge.mjs +32 -0
- package/docs/CHANGELOG.md +978 -0
- package/docs/README.md +72 -0
- package/docs/README.zh-CN.md +58 -0
- package/docs/architecture/chatgpt-handoff-facade.md +393 -0
- package/docs/architecture/current/README.md +158 -0
- package/docs/architecture/current/approved-target-architecture.zh-CN.md +1501 -0
- package/docs/architecture/current/architecture-invariants.md +331 -0
- package/docs/architecture/current/automation-and-schedule-engine.md +453 -0
- package/docs/architecture/current/codegraph-context-provider.md +226 -0
- package/docs/architecture/current/control-plane-authority-inventory.md +82 -0
- package/docs/architecture/current/controller-repository-decoupling.md +148 -0
- package/docs/architecture/current/dispatch-and-agent-strategy.md +354 -0
- package/docs/architecture/current/entity-model.md +619 -0
- package/docs/architecture/current/external-plugin-governance.md +396 -0
- package/docs/architecture/current/failure-recovery.md +471 -0
- package/docs/architecture/current/governance.md +213 -0
- package/docs/architecture/current/human-interaction-plane.md +87 -0
- package/docs/architecture/current/implementation-status.md +128 -0
- package/docs/architecture/current/job-and-run-lifecycle.md +413 -0
- package/docs/architecture/current/local-workspace-target-grants.md +70 -0
- package/docs/architecture/current/migration-roadmap.md +105 -0
- package/docs/architecture/current/multi-repository-execution.md +371 -0
- package/docs/architecture/current/operations-runbook.md +45 -0
- package/docs/architecture/current/peer-supercontroller-runtime.md +32 -0
- package/docs/architecture/current/personal-assistant-plugin-baseline.md +207 -0
- package/docs/architecture/current/repository-access-modes.md +102 -0
- package/docs/architecture/current/route-policy.md +15 -0
- package/docs/architecture/current/route-session-concurrency.md +85 -0
- package/docs/architecture/current/runtime-architecture-simplification.md +214 -0
- package/docs/architecture/current/runtime-directory-map.md +49 -0
- package/docs/architecture/current/runtime-health-and-resource-lifecycle.md +85 -0
- package/docs/architecture/current/scheduler-and-resource-claims.md +432 -0
- package/docs/architecture/current/session-aware-execution-and-authorization.md +77 -0
- package/docs/architecture/current/system-overview.md +144 -0
- package/docs/architecture/current/target-requirements-traceability.md +202 -0
- package/docs/architecture/current/thin-harness-governance-policy.md +32 -0
- package/docs/architecture/current/thin-harness-v1.md +313 -0
- package/docs/architecture/current/verification-and-release-gates.md +391 -0
- package/docs/architecture/decisions/20260801-controller-home-sqlite-state.md +100 -0
- package/docs/architecture/decisions/20260803-canonical-skill-surface.md +40 -0
- package/docs/architecture/decisions/20260803-release-identity-binding-and-exit-policy.md +53 -0
- package/docs/architecture/diagrams/.gitkeep +1 -0
- package/docs/architecture/diagrams/agentic-dev-plugin-architecture.html +186 -0
- package/docs/architecture/domains/.gitkeep +0 -0
- package/docs/architecture/domains/public-surface.md +30 -0
- package/docs/architecture/domains/runtime-harness.md +33 -0
- package/docs/architecture/domains/verification.md +33 -0
- package/docs/architecture/domains/workflow-engine.md +30 -0
- package/docs/architecture/global-hook-runtime.md +162 -0
- package/docs/architecture/history.md +38 -0
- package/docs/architecture/index.md +114 -0
- package/docs/architecture/ios-semantic-automation-provider-v2.md +166 -0
- package/docs/architecture/modules/.gitkeep +0 -0
- package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +24 -0
- package/docs/architecture/requests/.gitkeep +1 -0
- package/docs/architecture/requests/archive/2026/20260528-154740-ai-hooks-ai-hooks-hook-input-sh.md +59 -0
- package/docs/architecture/requests/archive/2026/20260528-154816-assets-hooks-assets-hooks-hook-input-sh.md +59 -0
- package/docs/architecture/requests/archive/2026/20260528-161851-ai-harness-workflow-contract-json-ai-harness-workflow-contract-json.md +59 -0
- package/docs/architecture/requests/archive/2026/20260528-161853-scripts-check-task-workflow-sh-scripts-check-task-workflow-sh.md +59 -0
- package/docs/architecture/requests/archive/2026/20260528-161911-assets-workflow-contract-v1-json-assets-workflow-contract-v1-json.md +59 -0
- package/docs/architecture/requests/archive/2026/20260528-222416-ai-hooks-ai-hooks-hook-input-sh.md +59 -0
- package/docs/architecture/requests/archive/2026/20260528-222444-ai-hooks-ai-hooks-pre-edit-guard-sh.md +59 -0
- package/docs/architecture/requests/archive/2026/20260528-222457-ai-hooks-ai-hooks-pre-edit-guard-sh.md +59 -0
- package/docs/architecture/requests/archive/2026/20260528-222648-ai-hooks-ai-hooks-pre-edit-guard-sh.md +59 -0
- package/docs/architecture/requests/archive/2026/20260528-222705-ai-hooks-ai-hooks-worktree-guard-sh.md +59 -0
- package/docs/architecture/requests/archive/2026/20260528-222726-ai-hooks-ai-hooks-prompt-guard-sh.md +59 -0
- package/docs/architecture/requests/archive/2026/20260528-222727-ai-hooks-ai-hooks-prompt-guard-sh.md +59 -0
- package/docs/architecture/requests/archive/2026/20260528-224736-ai-hooks-ai-hooks-hook-input-sh.md +59 -0
- package/docs/architecture/requests/archive/2026/20260528-233259-ai-hooks-ai-hooks-prompt-guard-sh.md +59 -0
- package/docs/architecture/requests/archive/2026/20260528-233335-assets-hooks-assets-hooks-prompt-guard-sh.md +59 -0
- package/docs/architecture/requests/archive/2026/20260528-233456-ai-hooks-ai-hooks-prompt-guard-sh.md +59 -0
- package/docs/architecture/requests/archive/2026/20260528-233457-assets-hooks-assets-hooks-prompt-guard-sh.md +59 -0
- package/docs/architecture/requests/archive/2026/20260528-233637-ai-hooks-ai-hooks-prompt-guard-sh.md +59 -0
- package/docs/architecture/requests/archive/2026/20260528-233638-assets-hooks-assets-hooks-prompt-guard-sh.md +59 -0
- package/docs/architecture/requests/archive/2026/20260529-000322-root-package-json.md +59 -0
- package/docs/architecture/requests/archive/2026/20260529-004238-ai-hooks-ai-hooks-lib-workflow-state-sh.md +59 -0
- package/docs/architecture/requests/archive/2026/20260529-020654-ai-harness-policy-json-ai-harness-policy-json.md +63 -0
- package/docs/architecture/requests/archive/2026/20260529-094236-ai-hooks-ai-hooks-prompt-guard-sh.md +60 -0
- package/docs/architecture/requests/archive/2026/20260529-094323-assets-hooks-assets-hooks-prompt-guard-sh.md +60 -0
- package/docs/architecture/requests/archive/2026/20260529-094331-ai-hooks-ai-hooks-prompt-guard-sh.md +60 -0
- package/docs/architecture/requests/archive/2026/20260529-094339-assets-hooks-assets-hooks-prompt-guard-sh.md +60 -0
- package/docs/architecture/requests/archive/2026/20260529-094430-assets-hooks-assets-hooks-session-start-context-sh.md +60 -0
- package/docs/architecture/requests/archive/2026/20260529-094446-ai-hooks-ai-hooks-session-start-context-sh.md +60 -0
- package/docs/architecture/requests/archive/2026/20260613-002040-runtime-harness-hook-adapters.md +68 -0
- package/docs/architecture/requests/archive/2026/root.md +68 -0
- package/docs/architecture/requests/archive/2026/runtime-harness-hook-adapters.md +76 -0
- package/docs/architecture/requests/archive/2026/verification-evals-checks.md +68 -0
- package/docs/architecture/requests/archive/2026/workflow-engine-contract-assets.md +69 -0
- package/docs/architecture/reviews/2026-07-11-access-surface-review.md +99 -0
- package/docs/architecture/snapshots/.gitkeep +1 -0
- package/docs/forge-autonomous-goal-loop.md +7 -0
- package/docs/forge-chatgpt-browser-engine.md +11 -0
- package/docs/forge-chatgpt-mcp-setup.md +239 -0
- package/docs/forge-chatgpt-supervised-automation.md +11 -0
- package/docs/forge-github-issue-launcher.md +7 -0
- package/docs/forge-plugin-management.md +95 -0
- package/docs/forge-provider-configuration.md +7 -0
- package/docs/forge-runtime-self-healing-loop.md +7 -0
- package/docs/images/forge-banner-cn.svg +1 -0
- package/docs/images/forge-banner.svg +1 -0
- package/docs/images/forge-controller-flow.svg +1 -0
- package/docs/images/image.png +0 -0
- package/docs/images/repo-harness-gptpro-cn.png +0 -0
- package/docs/images/repo-harness-gptpro.png +0 -0
- package/docs/images/repo-harness-hook-carrot.png +0 -0
- package/docs/operations/chatgpt-personal-assistant-runtime.md +83 -0
- package/docs/operations/checkout-route-integrity.md +22 -0
- package/docs/operations/controller-browser-plugin.md +299 -0
- package/docs/operations/controller-desktop-plugin.md +112 -0
- package/docs/operations/controller-performance-and-502.md +126 -0
- package/docs/operations/controller-reliability-runbook.md +134 -0
- package/docs/operations/environment-hardening.md +50 -0
- package/docs/operations/features.md +45 -0
- package/docs/operations/features.zh-CN.md +45 -0
- package/docs/operations/github-repository.md +60 -0
- package/docs/operations/gmail-assistant-routines.md +186 -0
- package/docs/operations/homebrew.md +26 -0
- package/docs/operations/local-system-assistant.md +46 -0
- package/docs/operations/local-system-assistant.zh-CN.md +46 -0
- package/docs/operations/mcp-tool-exposure.md +58 -0
- package/docs/operations/mobile-intents-shortcuts.md +117 -0
- package/docs/operations/open-source-release-hygiene.md +31 -0
- package/docs/operations/personal-assistant-operator-guide.md +61 -0
- package/docs/operations/platform-support.md +62 -0
- package/docs/operations/platform-support.zh-CN.md +61 -0
- package/docs/operations/provider-configuration.md +31 -0
- package/docs/operations/releasing.md +86 -0
- package/docs/operations/releasing.zh-CN.md +86 -0
- package/docs/operations/route-session-concurrency-baseline.json +893 -0
- package/docs/operations/route-session-concurrency-baseline.md +94 -0
- package/docs/operations/runtime-performance-diagnostics.md +14 -0
- package/docs/operations/sqlite-control-plane-recovery.md +65 -0
- package/docs/operations/standalone-disaster-recovery.md +136 -0
- package/docs/operations/troubleshooting.md +72 -0
- package/docs/operations/troubleshooting.zh-CN.md +70 -0
- package/docs/public-usage-guide.md +33 -0
- package/docs/public-usage-guide.zh-CN.md +33 -0
- package/docs/tutorials/01-install-and-start.md +93 -0
- package/docs/tutorials/01-install-and-start.zh-CN.md +93 -0
- package/docs/tutorials/02-connect-chatgpt.md +82 -0
- package/docs/tutorials/02-connect-chatgpt.zh-CN.md +80 -0
- package/docs/tutorials/03-first-repository-task.md +57 -0
- package/docs/tutorials/03-first-repository-task.zh-CN.md +57 -0
- package/docs/tutorials/README.md +13 -0
- package/docs/tutorials/README.zh-CN.md +13 -0
- package/docs/wiki/Architecture.md +85 -0
- package/docs/wiki/Core-Concepts.md +27 -0
- package/docs/wiki/Home.md +36 -0
- package/docs/wiki/Implementation.md +172 -0
- package/docs/wiki/Installation.md +50 -0
- package/docs/wiki/Integrations.md +29 -0
- package/docs/wiki/Operations.md +26 -0
- package/docs/wiki/Quick-Start.md +46 -0
- package/docs/wiki/Releases-and-Upgrades.md +34 -0
- package/docs/wiki/Runtime-Architecture.md +50 -0
- package/docs/wiki/Security-Model.md +31 -0
- package/docs/wiki/Troubleshooting.md +38 -0
- package/docs/wiki/Work-Lifecycle.md +31 -0
- package/docs/wiki/_Sidebar.md +21 -0
- package/install.ps1 +48 -0
- package/install.sh +66 -0
- package/package.json +156 -0
- package/scripts/activate-source-baseline.ts +335 -0
- package/scripts/architecture-event.ts +822 -0
- package/scripts/architecture-queue.sh +647 -0
- package/scripts/archive-architecture-request.sh +244 -0
- package/scripts/archive-workflow.sh +295 -0
- package/scripts/assemble-template.ts +1172 -0
- package/scripts/benchmark-controller-hotpath.ts +212 -0
- package/scripts/benchmark-controller-round2.ts +139 -0
- package/scripts/benchmark-ios-agent-device.ts +514 -0
- package/scripts/benchmark-route-session-concurrency.ts +714 -0
- package/scripts/benchmark-thin-harness-gateway-ab.ts +632 -0
- package/scripts/benchmark-thin-harness-mcp-e2e.ts +479 -0
- package/scripts/benchmark-thin-harness.ts +251 -0
- package/scripts/bootstrap-runtime-maintenance-recovery.sh +183 -0
- package/scripts/canary-global-hook.sh +263 -0
- package/scripts/capability-config.ts +394 -0
- package/scripts/capability-resolver.ts +505 -0
- package/scripts/capture-plan.sh +335 -0
- package/scripts/check-agent-tooling.sh +1549 -0
- package/scripts/check-architecture-sync.sh +373 -0
- package/scripts/check-brain-manifest.sh +255 -0
- package/scripts/check-ci.sh +16 -0
- package/scripts/check-context-files.sh +49 -0
- package/scripts/check-deploy-sql-order.sh +117 -0
- package/scripts/check-mcp-compatibility.ts +93 -0
- package/scripts/check-npm-release.sh +32 -0
- package/scripts/check-open-source-tracked-surface.sh +146 -0
- package/scripts/check-package-identity.mjs +117 -0
- package/scripts/check-platform-support.mjs +79 -0
- package/scripts/check-public-docs.sh +105 -0
- package/scripts/check-public-release-surface.sh +19 -0
- package/scripts/check-release-published.sh +57 -0
- package/scripts/check-release-readiness.sh +43 -0
- package/scripts/check-release-version.mjs +74 -0
- package/scripts/check-runtime-architecture.mjs +593 -0
- package/scripts/check-runtime-env.mjs +89 -0
- package/scripts/check-skill-version.ts +193 -0
- package/scripts/check-tarball-install-smoke.sh +66 -0
- package/scripts/check-task-sync.sh +65 -0
- package/scripts/check-task-workflow.sh +1002 -0
- package/scripts/check-third-party-notices.mjs +36 -0
- package/scripts/codex-handoff-resume.sh +269 -0
- package/scripts/complete-control-plane-cutover.ts +126 -0
- package/scripts/context-contract-sync.sh +516 -0
- package/scripts/contract-run.ts +465 -0
- package/scripts/contract-worktree.sh +725 -0
- package/scripts/controller-ngrok-rotation.sh +678 -0
- package/scripts/create-project-dirs.sh +282 -0
- package/scripts/ensure-codegraph.sh +16 -0
- package/scripts/ensure-task-workflow.sh +1218 -0
- package/scripts/export-requirement-portfolio.ts +28 -0
- package/scripts/factor-lab-check.sh +73 -0
- package/scripts/factor-lab-new.sh +96 -0
- package/scripts/factor-lab-promote.sh +86 -0
- package/scripts/factor-lab-reject.sh +68 -0
- package/scripts/harness-trace-grade.sh +150 -0
- package/scripts/heartbeat-triage.sh +361 -0
- package/scripts/hook-dispatch-diet-report.ts +234 -0
- package/scripts/hook-shim.sh +93 -0
- package/scripts/init-project.sh +505 -0
- package/scripts/initializer-question-pack.ts +200 -0
- package/scripts/inspect-project-state.ts +280 -0
- package/scripts/install-desktop-operator-registration.ts +45 -0
- package/scripts/install-standalone-recovery.ts +74 -0
- package/scripts/lib/AGENTS.md +13 -0
- package/scripts/lib/CLAUDE.md +13 -0
- package/scripts/lib/controller-home-env.sh +69 -0
- package/scripts/lib/project-init-lib.sh +2759 -0
- package/scripts/load-standalone-recovery.sh +17 -0
- package/scripts/loop-engine-cutover-gate.ts +324 -0
- package/scripts/maintenance-triage.sh +167 -0
- package/scripts/migrate-project-template.sh +1189 -0
- package/scripts/migrate-requirement-portfolio.ts +86 -0
- package/scripts/migrate-workflow-docs.ts +413 -0
- package/scripts/new-plan.sh +183 -0
- package/scripts/new-spec.sh +50 -0
- package/scripts/new-sprint.sh +49 -0
- package/scripts/open-source-audit-allowlist.txt +46 -0
- package/scripts/package-source-archive.sh +147 -0
- package/scripts/plan-to-todo.sh +799 -0
- package/scripts/prepare-codex-handoff.sh +203 -0
- package/scripts/prepare-handoff.sh +81 -0
- package/scripts/public-release-files.txt +39 -0
- package/scripts/public-release.ts +174 -0
- package/scripts/publish-release-tarball.sh +27 -0
- package/scripts/refresh-current-status.sh +469 -0
- package/scripts/refresh-ios-physical-runtime.ts +196 -0
- package/scripts/repair-executable-modes.ts +8 -0
- package/scripts/rollout-all-registered-repos.sh +7 -0
- package/scripts/route-nl-vs-ts-eval.ts +679 -0
- package/scripts/run-bun-test-file.ts +182 -0
- package/scripts/run-governed-gate.ts +140 -0
- package/scripts/run-mobile-monitor-bridge.ts +71 -0
- package/scripts/run-skill-evals.ts +1022 -0
- package/scripts/run-skill-hook.ts +244 -0
- package/scripts/run-supervised-command.ts +24 -0
- package/scripts/run-tests-portable.sh +20 -0
- package/scripts/select-agent-context-blocks.sh +66 -0
- package/scripts/setup-plugins.sh +43 -0
- package/scripts/ship-worktrees.sh +561 -0
- package/scripts/smoke-browser-cdp-bridge.ts +93 -0
- package/scripts/smoke-chatgpt-supervised-automation.ts +208 -0
- package/scripts/smoke-ios-physical-device.ts +114 -0
- package/scripts/smoke-mcp-http-runtime.ts +216 -0
- package/scripts/smoke-mcp-tool-surface.ts +117 -0
- package/scripts/smoke-runtime-recovery.ts +220 -0
- package/scripts/smoke-schedule-engine.ts +283 -0
- package/scripts/sprint-backlog.sh +837 -0
- package/scripts/stage-runtime-release.ts +38 -0
- package/scripts/summarize-failures.sh +125 -0
- package/scripts/switch-plan.sh +153 -0
- package/scripts/sync-brain-docs.sh +381 -0
- package/scripts/sync-codex-installed-copies.sh +183 -0
- package/scripts/test-governance.ts +75 -0
- package/scripts/verify-contract.sh +705 -0
- package/scripts/verify-forge-runtime.sh +31 -0
- package/scripts/verify-sprint.sh +680 -0
- package/scripts/windows-paths.d.mts +7 -0
- package/scripts/windows-paths.mjs +28 -0
- package/scripts/workflow-contract.ts +206 -0
- package/scripts/workstream-sync.sh +263 -0
- package/src/cli/agent-jobs/executable-resolver.ts +289 -0
- package/src/cli/agent-jobs/executor-health.ts +252 -0
- package/src/cli/agent-jobs/integration.ts +963 -0
- package/src/cli/agent-jobs/job-manager.ts +2030 -0
- package/src/cli/agent-jobs/types.ts +219 -0
- package/src/cli/agent-jobs/worker-lifecycle.ts +288 -0
- package/src/cli/chatgpt-browser/bind-server.ts +504 -0
- package/src/cli/chatgpt-browser/binding.ts +140 -0
- package/src/cli/chatgpt-browser/bridge-extension.ts +221 -0
- package/src/cli/chatgpt-browser/bridge-provider.ts +268 -0
- package/src/cli/chatgpt-browser/engine.ts +569 -0
- package/src/cli/chatgpt-browser/file-policy.ts +158 -0
- package/src/cli/chatgpt-browser/native-provider.ts +553 -0
- package/src/cli/chatgpt-browser/oracle-provider.ts +437 -0
- package/src/cli/chatgpt-browser/prompt-assembler.ts +29 -0
- package/src/cli/chatgpt-browser/session-store.ts +301 -0
- package/src/cli/chatgpt-browser/types.ts +172 -0
- package/src/cli/commands/adopt-plan.ts +186 -0
- package/src/cli/commands/brain-root.ts +132 -0
- package/src/cli/commands/brain.ts +609 -0
- package/src/cli/commands/capability-context.ts +613 -0
- package/src/cli/commands/chatgpt.ts +424 -0
- package/src/cli/commands/controller.ts +680 -0
- package/src/cli/commands/docs.ts +103 -0
- package/src/cli/commands/doctor.ts +476 -0
- package/src/cli/commands/global-runtime.ts +323 -0
- package/src/cli/commands/hook.ts +34 -0
- package/src/cli/commands/init-hook.ts +870 -0
- package/src/cli/commands/init.ts +829 -0
- package/src/cli/commands/install.ts +86 -0
- package/src/cli/commands/mcp.ts +315 -0
- package/src/cli/commands/migrate.ts +154 -0
- package/src/cli/commands/plugin.ts +74 -0
- package/src/cli/commands/prompt-guard-decision.ts +238 -0
- package/src/cli/commands/recovery.ts +667 -0
- package/src/cli/commands/repository.ts +224 -0
- package/src/cli/commands/run.ts +23 -0
- package/src/cli/commands/runtime.ts +191 -0
- package/src/cli/commands/security.ts +440 -0
- package/src/cli/commands/status.ts +137 -0
- package/src/cli/commands/tools.ts +167 -0
- package/src/cli/controller/check-runner.ts +1022 -0
- package/src/cli/controller/codex-continuation.ts +153 -0
- package/src/cli/controller/completion-backlog.ts +380 -0
- package/src/cli/controller/completion-orchestrator.ts +1807 -0
- package/src/cli/controller/completion-target.ts +96 -0
- package/src/cli/controller/composite-operations.ts +196 -0
- package/src/cli/controller/composite-result.ts +130 -0
- package/src/cli/controller/context-pack.ts +652 -0
- package/src/cli/controller/execution-completion.ts +175 -0
- package/src/cli/controller/execution-policy.ts +392 -0
- package/src/cli/controller/governance.ts +594 -0
- package/src/cli/controller/issue-store.ts +1421 -0
- package/src/cli/controller/launch-agents.ts +410 -0
- package/src/cli/controller/legacy-issue-cutover.ts +415 -0
- package/src/cli/controller/lifecycle-authority.ts +16 -0
- package/src/cli/controller/migrated-issue-decision.ts +237 -0
- package/src/cli/controller/operational-plan.ts +226 -0
- package/src/cli/controller/postcondition.ts +134 -0
- package/src/cli/controller/progress.ts +656 -0
- package/src/cli/controller/project-state.ts +147 -0
- package/src/cli/controller/requirement-portfolio-export.ts +146 -0
- package/src/cli/controller/requirement-portfolio-migration.ts +613 -0
- package/src/cli/controller/run-evidence.ts +43 -0
- package/src/cli/controller/runtime-config.ts +92 -0
- package/src/cli/controller/stuck-state-migration.ts +396 -0
- package/src/cli/controller/task-ledger.ts +632 -0
- package/src/cli/controller/task-status-resolver.ts +403 -0
- package/src/cli/controller/types.ts +273 -0
- package/src/cli/controller/work-mode.ts +186 -0
- package/src/cli/controller/worklog.ts +201 -0
- package/src/cli/diagnostic-entry.ts +39 -0
- package/src/cli/editing/edit-session.ts +1606 -0
- package/src/cli/editing/executable-modes.ts +70 -0
- package/src/cli/github/github.ts +274 -0
- package/src/cli/github/plugin.ts +345 -0
- package/src/cli/github/session.ts +104 -0
- package/src/cli/hook/prompt-guard-decision.ts +238 -0
- package/src/cli/hook/prompt-intents.ts +534 -0
- package/src/cli/hook/route-registry.ts +107 -0
- package/src/cli/hook/runtime.ts +303 -0
- package/src/cli/hook/state-snapshot.ts +388 -0
- package/src/cli/hook-entry.ts +51 -0
- package/src/cli/index.ts +574 -0
- package/src/cli/installer/managed-entries.ts +78 -0
- package/src/cli/installer/shared.ts +65 -0
- package/src/cli/installer/targets/claude.ts +136 -0
- package/src/cli/installer/targets/codex.ts +174 -0
- package/src/cli/installer/targets/registry.ts +28 -0
- package/src/cli/installer/types.ts +72 -0
- package/src/cli/local-bridge/connector-freshness.ts +529 -0
- package/src/cli/local-bridge/console-view-models.ts +324 -0
- package/src/cli/local-bridge/dashboard.ts +1312 -0
- package/src/cli/local-bridge/facade-api.ts +1877 -0
- package/src/cli/local-bridge/job-store.ts +1451 -0
- package/src/cli/local-bridge/mobile-intents.ts +344 -0
- package/src/cli/local-bridge/mobile-monitor.ts +209 -0
- package/src/cli/local-bridge/server.ts +3183 -0
- package/src/cli/local-bridge/types.ts +176 -0
- package/src/cli/mcp/access-mode.ts +132 -0
- package/src/cli/mcp/access-tools.ts +387 -0
- package/src/cli/mcp/audit.ts +32 -0
- package/src/cli/mcp/auth.ts +402 -0
- package/src/cli/mcp/instructions.ts +33 -0
- package/src/cli/mcp/legacy-context.ts +16 -0
- package/src/cli/mcp/legacy-tool-service.ts +5516 -0
- package/src/cli/mcp/multi-repository.ts +423 -0
- package/src/cli/mcp/oauth.ts +226 -0
- package/src/cli/mcp/paths.ts +134 -0
- package/src/cli/mcp/policy.ts +230 -0
- package/src/cli/mcp/proxy-env.ts +62 -0
- package/src/cli/mcp/readiness-projection.ts +24 -0
- package/src/cli/mcp/redaction.ts +21 -0
- package/src/cli/mcp/repo.ts +24 -0
- package/src/cli/mcp/repository-tools.ts +1295 -0
- package/src/cli/mcp/server.ts +341 -0
- package/src/cli/mcp/setup.ts +793 -0
- package/src/cli/mcp/tool-capability-cache.ts +87 -0
- package/src/cli/mcp/tools.ts +9 -0
- package/src/cli/mcp/toolset-names.ts +70 -0
- package/src/cli/mcp/toolset-selection.ts +41 -0
- package/src/cli/mcp/toolset.ts +300 -0
- package/src/cli/mcp/transports/AGENTS.md +39 -0
- package/src/cli/mcp/transports/CLAUDE.md +39 -0
- package/src/cli/mcp/transports/http.ts +1234 -0
- package/src/cli/mcp/transports/session-registry.ts +428 -0
- package/src/cli/mcp/transports/stdio.ts +8 -0
- package/src/cli/mcp/types.ts +41 -0
- package/src/cli/mcp/umbrella-tools.ts +117 -0
- package/src/cli/repo-adoption/reclaim-runtime.ts +681 -0
- package/src/cli/repositories/branch-name-policy.ts +57 -0
- package/src/cli/repositories/command-classifier.ts +600 -0
- package/src/cli/repositories/command-executor.ts +1066 -0
- package/src/cli/repositories/command-normalization.ts +53 -0
- package/src/cli/repositories/command-scope.ts +264 -0
- package/src/cli/repositories/controller-home.ts +88 -0
- package/src/cli/repositories/entity-migration.ts +199 -0
- package/src/cli/repositories/ephemeral-workspace.ts +62 -0
- package/src/cli/repositories/git-command-executor.ts +301 -0
- package/src/cli/repositories/goal-registry.ts +239 -0
- package/src/cli/repositories/identity.ts +64 -0
- package/src/cli/repositories/local-project-onboarding.ts +539 -0
- package/src/cli/repositories/locks.ts +262 -0
- package/src/cli/repositories/registry.ts +1057 -0
- package/src/cli/repositories/runtime-storage.ts +411 -0
- package/src/cli/repositories/safe-patch.ts +421 -0
- package/src/cli/repositories/selected-path-actions.ts +341 -0
- package/src/cli/repositories/structured-git.ts +257 -0
- package/src/cli/repositories/types.ts +155 -0
- package/src/cli/repositories/umbrella.ts +134 -0
- package/src/cli/repositories/workbench.ts +140 -0
- package/src/cli/repositories/worktree-storage.ts +137 -0
- package/src/cli/repository/inspector.ts +637 -0
- package/src/cli/repository/session-cache.ts +453 -0
- package/src/cli/runtime/helper-runner.ts +172 -0
- package/src/cli/runtime-invocation.ts +318 -0
- package/src/cli/tools/codegraph.ts +676 -0
- package/src/cli/v81-entry.ts +29 -0
- package/src/core/adoption/gitignore-plan.ts +127 -0
- package/src/core/adoption/helper-wrapper-plan.ts +159 -0
- package/src/core/adoption/manifest-templates.ts +60 -0
- package/src/core/adoption/modes.ts +7 -0
- package/src/core/adoption/operations.ts +126 -0
- package/src/core/adoption/plan.ts +149 -0
- package/src/core/adoption/render.ts +70 -0
- package/src/core/adoption/rollback.ts +62 -0
- package/src/core/adoption/summary.ts +43 -0
- package/src/core/adoption/workflow-contract-asset.ts +14 -0
- package/src/core/adoption/workflow-contract-plan.ts +31 -0
- package/src/effects/fs-transaction.ts +540 -0
- package/src/effects/git-executable.ts +59 -0
- package/src/effects/managed-block.ts +86 -0
- package/src/effects/path-safety.ts +47 -0
- package/src/effects/process-runner.ts +192 -0
- package/src/runtime/assistant/action-proposals.ts +279 -0
- package/src/runtime/assistant/intent.ts +395 -0
- package/src/runtime/assistant/model-provider.ts +460 -0
- package/src/runtime/assistant/openapi.ts +223 -0
- package/src/runtime/assistant/policy.ts +89 -0
- package/src/runtime/assistant/readiness.ts +258 -0
- package/src/runtime/assistant/routine-runtime.ts +477 -0
- package/src/runtime/assistant/schedule-binding.ts +171 -0
- package/src/runtime/assistant/standing-grants.ts +375 -0
- package/src/runtime/assistant/store.ts +243 -0
- package/src/runtime/assistant/types.ts +135 -0
- package/src/runtime/context/codegraph-read-provider.ts +347 -0
- package/src/runtime/context/codegraph-sidecar.cjs +207 -0
- package/src/runtime/control-plane/dispatch-priority.ts +67 -0
- package/src/runtime/control-plane/execution/direct-edit-work-completion.ts +151 -0
- package/src/runtime/control-plane/execution/execution-identity.ts +456 -0
- package/src/runtime/control-plane/execution/session-store.ts +175 -0
- package/src/runtime/control-plane/execution/validation.ts +117 -0
- package/src/runtime/control-plane/execution/verification-evidence.ts +191 -0
- package/src/runtime/control-plane/execution/work-handle-store.ts +225 -0
- package/src/runtime/control-plane/execution/work-prepare-request-store.ts +159 -0
- package/src/runtime/control-plane/execution/work-task-receipt.ts +445 -0
- package/src/runtime/control-plane/execution/work-terminal-cleanup.ts +821 -0
- package/src/runtime/control-plane/facade/capability-registry.ts +279 -0
- package/src/runtime/control-plane/facade/check-normalization.ts +233 -0
- package/src/runtime/control-plane/facade/codex-delegation.ts +196 -0
- package/src/runtime/control-plane/facade/controller-session-store.ts +199 -0
- package/src/runtime/control-plane/facade/facade-result.ts +41 -0
- package/src/runtime/control-plane/facade/goal-workloop-access.ts +177 -0
- package/src/runtime/control-plane/facade/goal-workloop.ts +1216 -0
- package/src/runtime/control-plane/facade/handoff-inbox-store.ts +221 -0
- package/src/runtime/control-plane/facade/index.ts +16 -0
- package/src/runtime/control-plane/facade/operation-digest.ts +528 -0
- package/src/runtime/control-plane/facade/plan-contract-store.ts +403 -0
- package/src/runtime/control-plane/facade/policy-gate.ts +149 -0
- package/src/runtime/control-plane/facade/requirement-board.ts +280 -0
- package/src/runtime/control-plane/facade/self-healing-loop.ts +555 -0
- package/src/runtime/control-plane/facade/suggested-actions.ts +108 -0
- package/src/runtime/control-plane/facade/types.ts +729 -0
- package/src/runtime/control-plane/facade/work-admission-policy.ts +93 -0
- package/src/runtime/control-plane/facade/work-continuation.ts +104 -0
- package/src/runtime/control-plane/facade/work-contract-store.ts +1118 -0
- package/src/runtime/control-plane/facade/work-task-projection.ts +66 -0
- package/src/runtime/control-plane/global-scheduler/reconciliation.ts +365 -0
- package/src/runtime/control-plane/global-scheduler/scheduler.ts +920 -0
- package/src/runtime/control-plane/global-scheduler/wake-signal.ts +89 -0
- package/src/runtime/control-plane/goal-loop/config-facade.ts +700 -0
- package/src/runtime/control-plane/goal-loop/config-store.ts +570 -0
- package/src/runtime/control-plane/goal-loop/config-types.ts +213 -0
- package/src/runtime/control-plane/goal-loop/executor-router.ts +109 -0
- package/src/runtime/control-plane/goal-loop/failure-taxonomy.ts +149 -0
- package/src/runtime/control-plane/goal-loop/goal-contract-store.ts +304 -0
- package/src/runtime/control-plane/goal-loop/goal-loop-engine.ts +1001 -0
- package/src/runtime/control-plane/goal-loop/handoff-packet.ts +160 -0
- package/src/runtime/control-plane/goal-loop/index.ts +13 -0
- package/src/runtime/control-plane/goal-loop/local-tools.ts +290 -0
- package/src/runtime/control-plane/goal-loop/policy-gates.ts +203 -0
- package/src/runtime/control-plane/goal-loop/provider-dispatch.ts +93 -0
- package/src/runtime/control-plane/goal-loop/provider-registry.ts +545 -0
- package/src/runtime/control-plane/goal-loop/types.ts +378 -0
- package/src/runtime/control-plane/governance/access-policy.ts +147 -0
- package/src/runtime/control-plane/governance/authorization.ts +195 -0
- package/src/runtime/control-plane/governance/external-effects.ts +43 -0
- package/src/runtime/control-plane/launcher/thin-launcher.ts +97 -0
- package/src/runtime/control-plane/persistence/metadata-payload-policy.ts +53 -0
- package/src/runtime/control-plane/persistence/requirement-store.ts +241 -0
- package/src/runtime/control-plane/persistence/sqlite-store.ts +539 -0
- package/src/runtime/control-plane/release-retention.ts +447 -0
- package/src/runtime/control-plane/repo-actor/actor.ts +181 -0
- package/src/runtime/control-plane/repo-actor/registry.ts +20 -0
- package/src/runtime/control-plane/routing/index.ts +1 -0
- package/src/runtime/control-plane/routing/route-policy.ts +379 -0
- package/src/runtime/control-plane/runtime-cleanup.ts +727 -0
- package/src/runtime/control-plane/runtime-generation.ts +509 -0
- package/src/runtime/control-plane/runtime-pid-ownership.ts +11 -0
- package/src/runtime/control-plane/runtime-status-client.ts +90 -0
- package/src/runtime/control-plane/startup-recovery.ts +198 -0
- package/src/runtime/diagnostics/connectivity-observability.ts +475 -0
- package/src/runtime/diagnostics/mcp-timing.ts +64 -0
- package/src/runtime/diagnostics/performance.ts +379 -0
- package/src/runtime/diagnostics/process-facade.ts +350 -0
- package/src/runtime/diagnostics/read-only-tool.ts +226 -0
- package/src/runtime/evidence/artifact-store.ts +154 -0
- package/src/runtime/evidence/event-ledger.ts +80 -0
- package/src/runtime/evidence/evidence-store.ts +68 -0
- package/src/runtime/evidence/process-check-receipt.ts +43 -0
- package/src/runtime/evidence/result-store.ts +209 -0
- package/src/runtime/evidence/sensitive-output.ts +353 -0
- package/src/runtime/execution/jobs/child-reference.ts +124 -0
- package/src/runtime/execution/jobs/legacy-adapter.ts +22 -0
- package/src/runtime/execution/jobs/receipt-recovery.ts +119 -0
- package/src/runtime/execution/jobs/receipt-store.ts +243 -0
- package/src/runtime/execution/jobs/store.ts +737 -0
- package/src/runtime/execution/jobs/timeouts.ts +109 -0
- package/src/runtime/execution/jobs/types.ts +230 -0
- package/src/runtime/execution/jobs/wait.ts +45 -0
- package/src/runtime/execution/process-runtime/canary.ts +26 -0
- package/src/runtime/execution/process-runtime/check-facade.ts +272 -0
- package/src/runtime/execution/process-runtime/check-receipt.ts +185 -0
- package/src/runtime/execution/process-runtime/check-runner-sidecar.ts +60 -0
- package/src/runtime/execution/process-runtime/command-facade.ts +321 -0
- package/src/runtime/execution/process-runtime/gc.ts +171 -0
- package/src/runtime/execution/process-runtime/index.ts +9 -0
- package/src/runtime/execution/process-runtime/interactive-admission.ts +23 -0
- package/src/runtime/execution/process-runtime/process-runner-entry.ts +466 -0
- package/src/runtime/execution/process-runtime/resource-claims.ts +440 -0
- package/src/runtime/execution/process-runtime/runtime.ts +1816 -0
- package/src/runtime/execution/process-runtime/store.ts +687 -0
- package/src/runtime/execution/process-runtime/types.ts +352 -0
- package/src/runtime/execution/thin-harness/async-process.ts +181 -0
- package/src/runtime/execution/thin-harness/batch-executor.ts +671 -0
- package/src/runtime/execution/thin-harness/execution-router.ts +700 -0
- package/src/runtime/execution/thin-harness/fast-executor.ts +1263 -0
- package/src/runtime/execution/thin-harness/fast-receipt.ts +235 -0
- package/src/runtime/execution/thin-harness/fingerprint-worker.ts +191 -0
- package/src/runtime/execution/thin-harness/index.ts +13 -0
- package/src/runtime/execution/thin-harness/latency-trace.ts +107 -0
- package/src/runtime/execution/thin-harness/lightweight-lanes.ts +745 -0
- package/src/runtime/execution/thin-harness/mutation-gate.ts +578 -0
- package/src/runtime/execution/thin-harness/proposal-store.ts +409 -0
- package/src/runtime/execution/thin-harness/request-ledger.ts +595 -0
- package/src/runtime/execution/thin-harness/search-worker.ts +114 -0
- package/src/runtime/execution/thin-harness/types.ts +313 -0
- package/src/runtime/execution/thin-harness/workspace-savepoint.ts +333 -0
- package/src/runtime/execution/workers/executor.ts +687 -0
- package/src/runtime/execution/workers/ownership.ts +94 -0
- package/src/runtime/execution/workers/worker-entry.ts +277 -0
- package/src/runtime/gateway/mcp/execution-tools.ts +2009 -0
- package/src/runtime/gateway/mcp/persisted-check-process.ts +255 -0
- package/src/runtime/gateway/mcp/process-tools.ts +230 -0
- package/src/runtime/gateway/mcp/resource-policy.ts +195 -0
- package/src/runtime/gateway/mcp/router.ts +1088 -0
- package/src/runtime/gateway/mcp/runtime-tools.ts +5994 -0
- package/src/runtime/gateway/mcp/work-validation-reconciler.ts +219 -0
- package/src/runtime/health/evaluator.ts +474 -0
- package/src/runtime/health/index.ts +2 -0
- package/src/runtime/health/operational-view.ts +198 -0
- package/src/runtime/maintenance/cleanup.ts +419 -0
- package/src/runtime/model-clients/deepseek-adapter.ts +312 -0
- package/src/runtime/model-clients/index.ts +2 -0
- package/src/runtime/model-clients/types.ts +101 -0
- package/src/runtime/observability/gateway-contention-metrics.ts +129 -0
- package/src/runtime/observability/route-session-benchmark.ts +110 -0
- package/src/runtime/personal-assistant/gmail-triage-manager.ts +231 -0
- package/src/runtime/personal-assistant/reporting-runtime.ts +344 -0
- package/src/runtime/personal-assistant/triage-runtime.ts +748 -0
- package/src/runtime/plugins/app-store-connect-adapter.ts +868 -0
- package/src/runtime/plugins/browser-adapter.ts +2812 -0
- package/src/runtime/plugins/browser-automation-service.ts +46 -0
- package/src/runtime/plugins/browser-handoff-host.ts +304 -0
- package/src/runtime/plugins/browser-handoff.ts +371 -0
- package/src/runtime/plugins/browser-macos-bridge.ts +865 -0
- package/src/runtime/plugins/browser-node-bridge-host.ts +64 -0
- package/src/runtime/plugins/browser-node-bridge.ts +249 -0
- package/src/runtime/plugins/desktop-adapter.ts +374 -0
- package/src/runtime/plugins/desktop-operator-registration.ts +418 -0
- package/src/runtime/plugins/errors.ts +39 -0
- package/src/runtime/plugins/execution-origin.ts +26 -0
- package/src/runtime/plugins/external-adapter.ts +322 -0
- package/src/runtime/plugins/external-registration.ts +308 -0
- package/src/runtime/plugins/external-unix-socket-probe.cjs +79 -0
- package/src/runtime/plugins/external-unix-socket.ts +238 -0
- package/src/runtime/plugins/first-party-registry.ts +37 -0
- package/src/runtime/plugins/github-adapter.ts +266 -0
- package/src/runtime/plugins/gmail-adapter.ts +729 -0
- package/src/runtime/plugins/google-calendar-adapter.ts +468 -0
- package/src/runtime/plugins/google-shared.ts +578 -0
- package/src/runtime/plugins/google-tasks-adapter.ts +535 -0
- package/src/runtime/plugins/interaction-session.ts +252 -0
- package/src/runtime/plugins/ios/agent-device-capabilities.ts +258 -0
- package/src/runtime/plugins/ios/agent-device-failures.ts +95 -0
- package/src/runtime/plugins/ios/agent-device-provider.ts +63 -0
- package/src/runtime/plugins/ios/agent-device-typed-provider.ts +268 -0
- package/src/runtime/plugins/ios/app-adapters.ts +122 -0
- package/src/runtime/plugins/ios-adapter.ts +509 -0
- package/src/runtime/plugins/ios-agent-device.ts +2311 -0
- package/src/runtime/plugins/ios-physical-device.ts +955 -0
- package/src/runtime/plugins/local-system-adapter.ts +1016 -0
- package/src/runtime/plugins/macos-capability-broker.ts +73 -0
- package/src/runtime/plugins/managed-process-adapter.ts +366 -0
- package/src/runtime/plugins/resend-adapter.ts +506 -0
- package/src/runtime/plugins/store.ts +1025 -0
- package/src/runtime/plugins/types.ts +138 -0
- package/src/runtime/projections/controller-context.ts +596 -0
- package/src/runtime/projections/git-status-sampler.ts +84 -0
- package/src/runtime/projections/invalidation.ts +250 -0
- package/src/runtime/projections/materialized-view.ts +694 -0
- package/src/runtime/recovery/actions.ts +158 -0
- package/src/runtime/recovery/audit.ts +38 -0
- package/src/runtime/recovery/classifier.ts +163 -0
- package/src/runtime/recovery/index.ts +9 -0
- package/src/runtime/recovery/local-jobs-repair.ts +393 -0
- package/src/runtime/recovery/maintenance-executor.ts +822 -0
- package/src/runtime/recovery/patch-handoff.ts +50 -0
- package/src/runtime/recovery/probe.ts +308 -0
- package/src/runtime/recovery/store.ts +35 -0
- package/src/runtime/recovery/types.ts +175 -0
- package/src/runtime/release/identity.ts +101 -0
- package/src/runtime/release/release-gate.ts +137 -0
- package/src/runtime/resources/claims/conflicts.ts +205 -0
- package/src/runtime/resources/index.ts +1 -0
- package/src/runtime/resources/leases/store.ts +539 -0
- package/src/runtime/resources/leases/types.ts +50 -0
- package/src/runtime/resources/ownership.ts +72 -0
- package/src/runtime/root/controller-services.ts +42 -0
- package/src/runtime/root/entry.ts +70 -0
- package/src/runtime/root/gateway-adapter.ts +46 -0
- package/src/runtime/root/local-bridge.ts +72 -0
- package/src/runtime/root/mcp-transport.ts +198 -0
- package/src/runtime/root/ownership.ts +94 -0
- package/src/runtime/root/readiness.ts +69 -0
- package/src/runtime/root/release-manifest.ts +147 -0
- package/src/runtime/root/release-materialize.ts +509 -0
- package/src/runtime/root/release-store.ts +236 -0
- package/src/runtime/root/runtime.ts +318 -0
- package/src/runtime/root/scheduler.ts +58 -0
- package/src/runtime/root/service-runner-entry.ts +20 -0
- package/src/runtime/root/service-runner.ts +69 -0
- package/src/runtime/root/service.ts +291 -0
- package/src/runtime/root/status.ts +127 -0
- package/src/runtime/root/types.ts +112 -0
- package/src/runtime/root/write-fence.ts +309 -0
- package/src/runtime/safe-tooling/browser-safe.ts +133 -0
- package/src/runtime/safe-tooling/external-filesystem.ts +304 -0
- package/src/runtime/safe-tooling/google-credential-store.ts +95 -0
- package/src/runtime/safe-tooling/google-oauth-broker.ts +286 -0
- package/src/runtime/safe-tooling/index.ts +11 -0
- package/src/runtime/safe-tooling/ios-development.ts +1039 -0
- package/src/runtime/safe-tooling/job-summary.ts +361 -0
- package/src/runtime/safe-tooling/plugin-summary.ts +53 -0
- package/src/runtime/safe-tooling/resend-oauth.ts +387 -0
- package/src/runtime/safe-tooling/review-artifacts.ts +133 -0
- package/src/runtime/safe-tooling/types.ts +103 -0
- package/src/runtime/safe-tooling/workspace-auth.ts +116 -0
- package/src/runtime/shared/bounded-child-supervisor.ts +235 -0
- package/src/runtime/shared/idempotent-retry.ts +128 -0
- package/src/runtime/shared/json-files.ts +43 -0
- package/src/runtime/shared/local-bridge-surface.ts +231 -0
- package/src/runtime/shared/managed-env.ts +154 -0
- package/src/runtime/shared/node-ts-loader.mjs +50 -0
- package/src/runtime/shared/process-environment.ts +97 -0
- package/src/runtime/shared/process-identity.ts +72 -0
- package/src/runtime/shared/process-tree.ts +227 -0
- package/src/runtime/shared/response-budget.ts +246 -0
- package/src/runtime/standalone-recovery/core.ts +2275 -0
- package/src/runtime/standalone-recovery/entry.ts +686 -0
- package/src/runtime/standalone-recovery/http-transport.ts +317 -0
- package/src/runtime/standalone-recovery/installer.ts +747 -0
- package/src/runtime/standalone-recovery/release.ts +241 -0
- package/src/runtime/watchdog/workflow-watchdog.ts +118 -0
- package/src/runtime/workflow/campaigns/cleanup.ts +263 -0
- package/src/runtime/workflow/campaigns/engine.ts +112 -0
- package/src/runtime/workflow/campaigns/normalize.ts +100 -0
- package/src/runtime/workflow/campaigns/review.ts +315 -0
- package/src/runtime/workflow/campaigns/store.ts +526 -0
- package/src/runtime/workflow/campaigns/supervisor.ts +112 -0
- package/src/runtime/workflow/campaigns/types.ts +290 -0
- package/src/runtime/workflow/campaigns/workspace-agent.ts +155 -0
- package/src/runtime/workflow/campaigns/workspace.ts +200 -0
- package/src/runtime/workflow/findings/store.ts +165 -0
- package/src/runtime/workflow/findings/types.ts +36 -0
- package/src/runtime/workflow/portfolio/engine.ts +20 -0
- package/src/runtime/workflow/portfolio/store.ts +185 -0
- package/src/runtime/workflow/portfolio/types.ts +29 -0
- package/src/runtime/workflow/schedules/engine.ts +620 -0
- package/src/runtime/workflow/schedules/settlement.ts +144 -0
- package/src/runtime/workflow/schedules/store.ts +417 -0
- package/src/runtime/workflow/schedules/types.ts +124 -0
- package/src/runtime/workspace-targets/index.ts +24 -0
- package/src/runtime/workspace-targets/target-grant.ts +721 -0
- package/src/testing/test-governance.ts +626 -0
- package/src/version.ts +21 -0
|
@@ -0,0 +1,2759 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Shared install helpers for forge scaffolding scripts.
|
|
3
|
+
|
|
4
|
+
PI_RUNTIME_BLOCK_BEGIN="# BEGIN: claude-runtime-temp (managed by forge)"
|
|
5
|
+
PI_RUNTIME_BLOCK_END="# END: claude-runtime-temp"
|
|
6
|
+
PI_DEFAULT_GITIGNORE_CONTENT=$(cat <<'EOF_GITIGNORE'
|
|
7
|
+
# Dependencies
|
|
8
|
+
node_modules/
|
|
9
|
+
|
|
10
|
+
# Build artifacts
|
|
11
|
+
artifacts/
|
|
12
|
+
coverage/
|
|
13
|
+
*.tar.gz
|
|
14
|
+
*.tgz
|
|
15
|
+
|
|
16
|
+
# External references
|
|
17
|
+
_ref/
|
|
18
|
+
.codegraph/
|
|
19
|
+
|
|
20
|
+
# Local operations state
|
|
21
|
+
_ops/
|
|
22
|
+
|
|
23
|
+
# Environment
|
|
24
|
+
.env
|
|
25
|
+
.env.*
|
|
26
|
+
!.env.example
|
|
27
|
+
|
|
28
|
+
# OS metadata
|
|
29
|
+
.DS_Store
|
|
30
|
+
EOF_GITIGNORE
|
|
31
|
+
)
|
|
32
|
+
PI_DEFAULT_RUNTIME_ENTRIES=$(cat <<'EOF_RUNTIME'
|
|
33
|
+
.claude/settings.local.json
|
|
34
|
+
.claude/.atomic_pending
|
|
35
|
+
.claude/.session-id
|
|
36
|
+
.claude/.trace.jsonl
|
|
37
|
+
.claude/.session-handoff.md
|
|
38
|
+
.claude/.task-state.json
|
|
39
|
+
.claude/.task-handoff.md
|
|
40
|
+
.claude/.codegraph-state/
|
|
41
|
+
.claude/*.tmp
|
|
42
|
+
.claude/*.bak
|
|
43
|
+
.claude/*.bak.*
|
|
44
|
+
.claude/*.backup-*
|
|
45
|
+
tasks/.current.md.tmp.*
|
|
46
|
+
.ai/harness/checks/latest.json
|
|
47
|
+
.ai/harness/checks/post-bash-latest.json
|
|
48
|
+
.ai/harness/events.jsonl
|
|
49
|
+
.ai/harness/archive/
|
|
50
|
+
.ai/harness/failures/latest.jsonl
|
|
51
|
+
.ai/harness/handoff/current.md
|
|
52
|
+
.ai/harness/handoff/resume.md
|
|
53
|
+
.ai/harness/capability-context/
|
|
54
|
+
.ai/harness/security/*
|
|
55
|
+
!.ai/harness/security/.gitkeep
|
|
56
|
+
.ai/harness/planning/*
|
|
57
|
+
!.ai/harness/planning/.gitkeep
|
|
58
|
+
.ai/harness/architecture/events.jsonl
|
|
59
|
+
.ai/harness/active-plan
|
|
60
|
+
.ai/harness/active-worktree
|
|
61
|
+
.ai/harness/sprint/
|
|
62
|
+
.ai/harness/worktrees/
|
|
63
|
+
.ai/harness/runs/
|
|
64
|
+
.ai/harness/chatgpt/browser-lock.json
|
|
65
|
+
.ai/harness/chatgpt/bridge-extension/
|
|
66
|
+
.ai/harness/chatgpt/tmp/
|
|
67
|
+
.ai/harness/chatgpt/sessions/
|
|
68
|
+
.ai/harness/triage/*
|
|
69
|
+
!.ai/harness/triage/.gitkeep
|
|
70
|
+
.forge/chatgpt-browser.local.json
|
|
71
|
+
.forge/chatgpt-browser.tokens.json
|
|
72
|
+
.forge/interactions/
|
|
73
|
+
.codex/*
|
|
74
|
+
.claude/.active-plan
|
|
75
|
+
.claude/.plan-state/
|
|
76
|
+
EOF_RUNTIME
|
|
77
|
+
)
|
|
78
|
+
PI_EXTERNAL_TOOLING_HOSTS_DEFAULT=$(cat <<'EOF_EXTERNAL_TOOLING_HOSTS'
|
|
79
|
+
[
|
|
80
|
+
"claude-code",
|
|
81
|
+
"codex"
|
|
82
|
+
]
|
|
83
|
+
EOF_EXTERNAL_TOOLING_HOSTS
|
|
84
|
+
)
|
|
85
|
+
PI_TEMPLATE_RESEARCH=$(cat <<'EOF_TEMPLATE_RESEARCH'
|
|
86
|
+
# {{PROJECT_NAME}} — Research Notes
|
|
87
|
+
|
|
88
|
+
> **Last Updated**: {{DATE}}
|
|
89
|
+
> **Scope**: (what area of the codebase was researched)
|
|
90
|
+
> **Usage**: Store deep codebase findings and hidden contracts here, not in chat-only summaries.
|
|
91
|
+
|
|
92
|
+
## Codebase Map
|
|
93
|
+
| File | Purpose | Key Exports |
|
|
94
|
+
|------|---------|-------------|
|
|
95
|
+
|
|
96
|
+
## Architecture Observations
|
|
97
|
+
### Patterns & Conventions
|
|
98
|
+
### Implicit Contracts
|
|
99
|
+
### Edge Cases & Intricacies
|
|
100
|
+
|
|
101
|
+
## Technical Debt / Risks
|
|
102
|
+
|
|
103
|
+
## Research Conclusions
|
|
104
|
+
### What to Preserve
|
|
105
|
+
### What to Change
|
|
106
|
+
### Open Questions
|
|
107
|
+
EOF_TEMPLATE_RESEARCH
|
|
108
|
+
)
|
|
109
|
+
PI_TEMPLATE_SPEC=$(cat <<'EOF_TEMPLATE_SPEC'
|
|
110
|
+
# Product Spec: {{PROJECT_NAME}}
|
|
111
|
+
|
|
112
|
+
> **Status**: Draft
|
|
113
|
+
> **Last Updated**: {{TIMESTAMP}}
|
|
114
|
+
> **Owner**: Planner
|
|
115
|
+
|
|
116
|
+
## Product Outcome
|
|
117
|
+
|
|
118
|
+
Describe the stable user or operator outcome this repo should deliver.
|
|
119
|
+
|
|
120
|
+
## Success Criteria
|
|
121
|
+
|
|
122
|
+
- Primary workflow:
|
|
123
|
+
- Quality bar:
|
|
124
|
+
- Out of scope:
|
|
125
|
+
|
|
126
|
+
## Constraints
|
|
127
|
+
|
|
128
|
+
- Technical:
|
|
129
|
+
- Compliance:
|
|
130
|
+
- Delivery:
|
|
131
|
+
|
|
132
|
+
## Acceptance Scenarios
|
|
133
|
+
|
|
134
|
+
- Given
|
|
135
|
+
When
|
|
136
|
+
Then
|
|
137
|
+
|
|
138
|
+
## Open Questions
|
|
139
|
+
|
|
140
|
+
- ...
|
|
141
|
+
EOF_TEMPLATE_SPEC
|
|
142
|
+
)
|
|
143
|
+
PI_TEMPLATE_PLAN=$(cat <<'EOF_TEMPLATE_PLAN'
|
|
144
|
+
# Plan: {{TITLE}}
|
|
145
|
+
|
|
146
|
+
> **Status**: Draft
|
|
147
|
+
> **Created**: {{TIMESTAMP}}
|
|
148
|
+
> **Slug**: {{SLUG}}
|
|
149
|
+
> **Spec**: `docs/spec.md`
|
|
150
|
+
> **Research**: See `docs/researches/`
|
|
151
|
+
> **Task Contract**: `tasks/contracts/{{ARTIFACT_STEM}}.contract.md`
|
|
152
|
+
> **Task Review**: `tasks/reviews/{{ARTIFACT_STEM}}.review.md`
|
|
153
|
+
> **Implementation Notes**: `tasks/notes/{{ARTIFACT_STEM}}.notes.md`
|
|
154
|
+
|
|
155
|
+
## Agentic Routing
|
|
156
|
+
- Selected route:
|
|
157
|
+
- Routing reason:
|
|
158
|
+
- Due diligence:
|
|
159
|
+
- P1 map:
|
|
160
|
+
- P2 trace:
|
|
161
|
+
- P3 decision rationale:
|
|
162
|
+
|
|
163
|
+
## Workflow Inventory
|
|
164
|
+
Complete this inventory before implementation. If any line is unknown, keep the plan in Draft and fill it before projection.
|
|
165
|
+
|
|
166
|
+
- Active plan: `{{PLAN_FILE}}`
|
|
167
|
+
- Sprint contract: `tasks/contracts/{{ARTIFACT_STEM}}.contract.md`
|
|
168
|
+
- Sprint review: `tasks/reviews/{{ARTIFACT_STEM}}.review.md`
|
|
169
|
+
- Implementation notes: `tasks/notes/{{ARTIFACT_STEM}}.notes.md`
|
|
170
|
+
- Deferred-goal ledger: `tasks/todos.md`
|
|
171
|
+
- Current checks: `.ai/harness/checks/latest.json`
|
|
172
|
+
- Run snapshots: `.ai/harness/runs/`
|
|
173
|
+
- Scope authority: `tasks/contracts/{{ARTIFACT_STEM}}.contract.md` `allowed_paths`
|
|
174
|
+
- Concurrency rule: `.ai/harness/active-plan` selects the active plan for this worktree when present; `.ai/harness/active-worktree` records the owning worktree; `.claude/.active-plan` is a legacy fallback during transition. If another worktree already owns active work, open or switch to the matching worktree instead of serializing unrelated plans.
|
|
175
|
+
- Execution isolation: approved contract-level work projects through `.ai/harness/scripts/plan-to-todo.sh --plan {{PLAN_FILE}}` and may start `.ai/harness/scripts/contract-worktree.sh start --plan {{PLAN_FILE}}`.
|
|
176
|
+
|
|
177
|
+
## Approach
|
|
178
|
+
### Strategy
|
|
179
|
+
### Trade-offs
|
|
180
|
+
| Option | Pros | Cons | Decision |
|
|
181
|
+
|--------|------|------|----------|
|
|
182
|
+
|
|
183
|
+
## Detailed Design
|
|
184
|
+
### File Changes
|
|
185
|
+
| File | Action | Description |
|
|
186
|
+
|------|--------|-------------|
|
|
187
|
+
|
|
188
|
+
### Code Snippets
|
|
189
|
+
### Data Flow
|
|
190
|
+
|
|
191
|
+
## Risk Assessment
|
|
192
|
+
| Risk | Likelihood | Impact | Mitigation |
|
|
193
|
+
|------|------------|--------|------------|
|
|
194
|
+
|
|
195
|
+
## Task Contracts
|
|
196
|
+
- Contract file: `tasks/contracts/{{ARTIFACT_STEM}}.contract.md`
|
|
197
|
+
- Review file: `tasks/reviews/{{ARTIFACT_STEM}}.review.md`
|
|
198
|
+
- Implementation notes file: `tasks/notes/{{ARTIFACT_STEM}}.notes.md`
|
|
199
|
+
- Template: `.claude/templates/contract.template.md`
|
|
200
|
+
- Verification command: `bash .ai/harness/scripts/verify-contract.sh --contract tasks/contracts/{{ARTIFACT_STEM}}.contract.md --strict`
|
|
201
|
+
- Active plan rule: `.ai/harness/active-plan` is authoritative for this worktree when present; `.ai/harness/active-worktree` records the owning worktree; `.claude/.active-plan` is a legacy fallback during transition. Do not infer active execution from the latest non-archived plan.
|
|
202
|
+
|
|
203
|
+
## Handoff
|
|
204
|
+
|
|
205
|
+
- Checks file: `.ai/harness/checks/latest.json`
|
|
206
|
+
- Session handoff: `.ai/harness/handoff/current.md`
|
|
207
|
+
|
|
208
|
+
## Evidence Contract
|
|
209
|
+
|
|
210
|
+
- **State/progress path**:
|
|
211
|
+
- **Verification evidence**:
|
|
212
|
+
- **Evaluator rubric**:
|
|
213
|
+
- **Stop condition**:
|
|
214
|
+
- **Rollback surface**:
|
|
215
|
+
|
|
216
|
+
## Annotations
|
|
217
|
+
<!-- [NOTE]: prefixed inline. Claude processes all and revises. -->
|
|
218
|
+
|
|
219
|
+
## Task Breakdown
|
|
220
|
+
- [ ] ...
|
|
221
|
+
EOF_TEMPLATE_PLAN
|
|
222
|
+
)
|
|
223
|
+
PI_TEMPLATE_CONTRACT=$(cat <<'EOF_TEMPLATE_CONTRACT'
|
|
224
|
+
# Task Contract: {{TASK_SLUG}}
|
|
225
|
+
|
|
226
|
+
> **Status**: Pending
|
|
227
|
+
> **Plan**: {{PLAN_FILE}}
|
|
228
|
+
> **Task Profile**: {{TASK_PROFILE}}
|
|
229
|
+
> **Owner**: {{OWNER}}
|
|
230
|
+
> **Capability ID**: {{CAPABILITY_ID}}
|
|
231
|
+
> **Last Updated**: {{TIMESTAMP}}
|
|
232
|
+
> **Review File**: `{{REVIEW_FILE}}`
|
|
233
|
+
> **Notes File**: `{{NOTES_FILE}}`
|
|
234
|
+
|
|
235
|
+
## Goal
|
|
236
|
+
|
|
237
|
+
Describe the exact outcome this task must deliver.
|
|
238
|
+
|
|
239
|
+
## Scope
|
|
240
|
+
|
|
241
|
+
- In scope:
|
|
242
|
+
- Out of scope:
|
|
243
|
+
|
|
244
|
+
## Workflow Inventory
|
|
245
|
+
|
|
246
|
+
- Source plan: `{{PLAN_FILE}}`
|
|
247
|
+
- Deferred-goal ledger: `tasks/todos.md`
|
|
248
|
+
- Review file: `{{REVIEW_FILE}}`
|
|
249
|
+
- Notes file: `{{NOTES_FILE}}`
|
|
250
|
+
- Checks file: `.ai/harness/checks/latest.json`
|
|
251
|
+
- Run snapshots: `.ai/harness/runs/`
|
|
252
|
+
- Scope gate: edit only paths listed under `allowed_paths`; update this contract before widening scope.
|
|
253
|
+
- Completion gate: `scripts/verify-sprint.sh` must see this contract pass, the review recommend pass, and `## External Acceptance Advice` pass or record a manual override.
|
|
254
|
+
|
|
255
|
+
## Allowed Paths
|
|
256
|
+
|
|
257
|
+
```yaml
|
|
258
|
+
allowed_paths:
|
|
259
|
+
- plans/
|
|
260
|
+
- tasks/todos.md
|
|
261
|
+
- {{CONTRACT_FILE}}
|
|
262
|
+
- {{REVIEW_FILE}}
|
|
263
|
+
- {{NOTES_FILE}}
|
|
264
|
+
- .ai/context/capabilities.json
|
|
265
|
+
- src/
|
|
266
|
+
- tests/
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
## Delegation Contract
|
|
270
|
+
|
|
271
|
+
```yaml
|
|
272
|
+
delegation:
|
|
273
|
+
budget:
|
|
274
|
+
tokens: null
|
|
275
|
+
tool_calls: null
|
|
276
|
+
wall_time_minutes: null
|
|
277
|
+
permission_scope:
|
|
278
|
+
mode: inherit_allowed_paths
|
|
279
|
+
writable_paths: []
|
|
280
|
+
network: inherited
|
|
281
|
+
roles:
|
|
282
|
+
parent:
|
|
283
|
+
mode: narrate_and_gatekeep
|
|
284
|
+
purpose: approval_checkpoint_owner
|
|
285
|
+
explorer:
|
|
286
|
+
mode: read_only
|
|
287
|
+
purpose: codebase_research
|
|
288
|
+
worker:
|
|
289
|
+
mode: edit_within_allowed_paths
|
|
290
|
+
purpose: implementation
|
|
291
|
+
verifier:
|
|
292
|
+
mode: read_only
|
|
293
|
+
purpose: exit_criteria_review
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
## Exit Criteria (Machine Verifiable)
|
|
297
|
+
|
|
298
|
+
```yaml
|
|
299
|
+
exit_criteria:
|
|
300
|
+
files_exist:
|
|
301
|
+
- src/modules/{{TASK_SLUG}}/index.ts
|
|
302
|
+
- {{NOTES_FILE}}
|
|
303
|
+
tests_pass:
|
|
304
|
+
- path: tests/unit/{{TASK_SLUG}}.test.ts
|
|
305
|
+
commands_succeed:
|
|
306
|
+
- bun run typecheck
|
|
307
|
+
files_contain:
|
|
308
|
+
- path: src/modules/{{TASK_SLUG}}/index.ts
|
|
309
|
+
pattern: "export"
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
## Acceptance Notes (Human Review)
|
|
313
|
+
|
|
314
|
+
- Functional behavior:
|
|
315
|
+
- Edge cases:
|
|
316
|
+
- Regression risks:
|
|
317
|
+
|
|
318
|
+
## Rollback Point
|
|
319
|
+
|
|
320
|
+
- Commit / checkpoint:
|
|
321
|
+
- Revert strategy:
|
|
322
|
+
EOF_TEMPLATE_CONTRACT
|
|
323
|
+
)
|
|
324
|
+
PI_TEMPLATE_REVIEW=$(cat <<'EOF_TEMPLATE_REVIEW'
|
|
325
|
+
# Task Review: {{TASK_SLUG}}
|
|
326
|
+
|
|
327
|
+
> **Status**: Pending
|
|
328
|
+
> **Plan**: {{PLAN_FILE}}
|
|
329
|
+
> **Contract**: {{CONTRACT_FILE}}
|
|
330
|
+
> **Notes File**: {{NOTES_FILE}}
|
|
331
|
+
> **Checks File**: {{CHECKS_FILE}}
|
|
332
|
+
> **Last Updated**: {{TIMESTAMP}}
|
|
333
|
+
> **Recommendation**: fail
|
|
334
|
+
|
|
335
|
+
## Human Review Card
|
|
336
|
+
|
|
337
|
+
- Verdict: pending
|
|
338
|
+
- Change type: code-change | docs-only | ledger-closeout | migration | eval-only | delegated-run
|
|
339
|
+
- Intended files changed:
|
|
340
|
+
- Actual files changed:
|
|
341
|
+
- Commands passed:
|
|
342
|
+
- External acceptance: unavailable
|
|
343
|
+
- Residual risks:
|
|
344
|
+
- Reviewer action required: inspect diff and card
|
|
345
|
+
- Rollback:
|
|
346
|
+
|
|
347
|
+
## Verification Evidence
|
|
348
|
+
|
|
349
|
+
- Waza /check run:
|
|
350
|
+
- Commands run:
|
|
351
|
+
- Manual checks:
|
|
352
|
+
- Supporting artifacts:
|
|
353
|
+
|
|
354
|
+
## External Acceptance Advice
|
|
355
|
+
|
|
356
|
+
> **External Acceptance**: unavailable
|
|
357
|
+
> **External Reviewer**:
|
|
358
|
+
> **External Source**:
|
|
359
|
+
> **External Started**:
|
|
360
|
+
> **External Completed**:
|
|
361
|
+
|
|
362
|
+
- P1 blockers:
|
|
363
|
+
- P2 advisories:
|
|
364
|
+
- Acceptance checklist:
|
|
365
|
+
|
|
366
|
+
## Behavior Diff Notes
|
|
367
|
+
|
|
368
|
+
- ...
|
|
369
|
+
|
|
370
|
+
## Residual Risks / Follow-ups
|
|
371
|
+
|
|
372
|
+
- ...
|
|
373
|
+
|
|
374
|
+
## Scorecard
|
|
375
|
+
|
|
376
|
+
| Dimension | Score | Notes |
|
|
377
|
+
|-----------|-------|-------|
|
|
378
|
+
| Functionality | 0/10 | |
|
|
379
|
+
| Product depth | 0/10 | |
|
|
380
|
+
| Design quality | 0/10 | |
|
|
381
|
+
| Code quality | 0/10 | |
|
|
382
|
+
|
|
383
|
+
## Failing Items
|
|
384
|
+
|
|
385
|
+
- ...
|
|
386
|
+
|
|
387
|
+
## Retest Steps
|
|
388
|
+
|
|
389
|
+
- Re-run:
|
|
390
|
+
- Re-check:
|
|
391
|
+
|
|
392
|
+
## Summary
|
|
393
|
+
|
|
394
|
+
- ...
|
|
395
|
+
EOF_TEMPLATE_REVIEW
|
|
396
|
+
)
|
|
397
|
+
PI_TEMPLATE_IMPLEMENTATION_NOTES=$(cat <<'EOF_TEMPLATE_IMPLEMENTATION_NOTES'
|
|
398
|
+
# Implementation Notes: {{TASK_SLUG}}
|
|
399
|
+
|
|
400
|
+
> **Status**: Active
|
|
401
|
+
> **Plan**: {{PLAN_FILE}}
|
|
402
|
+
> **Contract**: {{CONTRACT_FILE}}
|
|
403
|
+
> **Review**: {{REVIEW_FILE}}
|
|
404
|
+
> **Last Updated**: {{TIMESTAMP}}
|
|
405
|
+
> **Lifecycle**: notes
|
|
406
|
+
|
|
407
|
+
## Design Decisions
|
|
408
|
+
|
|
409
|
+
- ...
|
|
410
|
+
|
|
411
|
+
## Deviations From Plan Or Spec
|
|
412
|
+
|
|
413
|
+
- None recorded.
|
|
414
|
+
|
|
415
|
+
## Tradeoffs Considered
|
|
416
|
+
|
|
417
|
+
| Option | Decision | Reason |
|
|
418
|
+
|--------|----------|--------|
|
|
419
|
+
| ... | ... | ... |
|
|
420
|
+
|
|
421
|
+
## Open Questions
|
|
422
|
+
|
|
423
|
+
- None.
|
|
424
|
+
|
|
425
|
+
## Evidence Links
|
|
426
|
+
|
|
427
|
+
- Checks: `.ai/harness/checks/latest.json`
|
|
428
|
+
- Run snapshots: `.ai/harness/runs/`
|
|
429
|
+
|
|
430
|
+
## Promotion Candidates
|
|
431
|
+
|
|
432
|
+
- Promote to `tasks/lessons.md` only after a repeated correction or failure pattern.
|
|
433
|
+
- Promote to `docs/researches/` only when it is durable repo knowledge with evidence.
|
|
434
|
+
- Promote to harness asset files only after verification across more than one task or fixture.
|
|
435
|
+
EOF_TEMPLATE_IMPLEMENTATION_NOTES
|
|
436
|
+
)
|
|
437
|
+
PI_CONTEXT_PROFILE_DEFAULT="stable-root-progressive-subdir"
|
|
438
|
+
PI_RECOVERY_PROFILE_DEFAULT="hybrid"
|
|
439
|
+
PI_STATE_PROFILE_DEFAULT="file-backed"
|
|
440
|
+
PI_ORCHESTRATION_PROFILE_DEFAULT="shared-long-running-harness"
|
|
441
|
+
PI_EVALUATION_PROFILE_DEFAULT="browser-qa"
|
|
442
|
+
PI_HANDOFF_PROFILE_DEFAULT="artifact-aware"
|
|
443
|
+
PI_DOCUMENTATION_PROFILE_DEFAULT="minimal-agentic"
|
|
444
|
+
PI_DEFAULT_LSP_PROFILE="typescript-lsp"
|
|
445
|
+
PI_MINIMAL_REFERENCE_CONFIGS="harness-overview.md agentic-development-flow.md external-tooling.md sprint-contracts.md heartbeat-triage.md handoff-protocol.md document-generation.md global-working-rules.md"
|
|
446
|
+
PI_FULL_REFERENCE_CONFIGS="agentic-development-flow.md ai-workflows.md changelog-versioning.md coding-standards.md development-protocol.md document-generation.md evaluator-rubric.md external-tooling.md git-strategy.md global-working-rules.md heartbeat-triage.md handoff-protocol.md harness-overview.md hook-operations.md release-deploy.md spa-day-protocol.md sprint-contracts.md workflow-orchestration.md"
|
|
447
|
+
PI_REFERENCE_CONFIG_STUB_MARKER="<!-- forge: reference-config-stub v1 -->"
|
|
448
|
+
|
|
449
|
+
pi_write_file_if_apply() {
|
|
450
|
+
local mode="${1:-apply}"
|
|
451
|
+
local path="$2"
|
|
452
|
+
local content="$3"
|
|
453
|
+
|
|
454
|
+
if [[ "$mode" != "apply" ]]; then
|
|
455
|
+
echo "[dry-run] write $path"
|
|
456
|
+
return 0
|
|
457
|
+
fi
|
|
458
|
+
|
|
459
|
+
mkdir -p "$(dirname "$path")"
|
|
460
|
+
printf '%s\n' "$content" > "$path"
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
pi_copy_file_if_apply() {
|
|
464
|
+
local mode="${1:-apply}"
|
|
465
|
+
local src="$2"
|
|
466
|
+
local dest="$3"
|
|
467
|
+
local src_abs=""
|
|
468
|
+
local dest_abs=""
|
|
469
|
+
|
|
470
|
+
if [[ "$mode" != "apply" ]]; then
|
|
471
|
+
echo "[dry-run] cp \"$src\" \"$dest\""
|
|
472
|
+
return 0
|
|
473
|
+
fi
|
|
474
|
+
|
|
475
|
+
mkdir -p "$(dirname "$dest")"
|
|
476
|
+
src_abs="$(cd "$(dirname "$src")" && pwd)/$(basename "$src")"
|
|
477
|
+
dest_abs="$(cd "$(dirname "$dest")" && pwd)/$(basename "$dest")"
|
|
478
|
+
|
|
479
|
+
if [[ "$src_abs" == "$dest_abs" ]]; then
|
|
480
|
+
return 0
|
|
481
|
+
fi
|
|
482
|
+
|
|
483
|
+
cp "$src" "$dest"
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
pi_install_hook_adapters() {
|
|
487
|
+
local repo="$1"
|
|
488
|
+
local _hooks_dir="$2"
|
|
489
|
+
local mode="${3:-apply}"
|
|
490
|
+
|
|
491
|
+
pi_retire_project_hook_adapter "$mode" "$repo/.claude/settings.json"
|
|
492
|
+
pi_retire_project_hook_adapter "$mode" "$repo/.claude/settings.local.json"
|
|
493
|
+
pi_retire_project_hook_adapter "$mode" "$repo/.codex/hooks.json"
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
pi_retire_project_hook_adapter() {
|
|
497
|
+
local mode="${1:-apply}"
|
|
498
|
+
local file_path="$2"
|
|
499
|
+
|
|
500
|
+
if [[ ! -f "$file_path" ]]; then
|
|
501
|
+
return 0
|
|
502
|
+
fi
|
|
503
|
+
|
|
504
|
+
if [[ "$mode" != "apply" ]]; then
|
|
505
|
+
echo "[dry-run] retire project hook adapter $file_path"
|
|
506
|
+
return 0
|
|
507
|
+
fi
|
|
508
|
+
|
|
509
|
+
if ! command -v node >/dev/null 2>&1; then
|
|
510
|
+
echo "[project-init] Skipping project hook adapter retirement for $file_path because node is unavailable" >&2
|
|
511
|
+
return 0
|
|
512
|
+
fi
|
|
513
|
+
|
|
514
|
+
node - "$file_path" <<'NODE_EOF'
|
|
515
|
+
const fs = require("fs");
|
|
516
|
+
const path = process.argv[2];
|
|
517
|
+
|
|
518
|
+
function writeJson(file, value) {
|
|
519
|
+
fs.writeFileSync(file, `${JSON.stringify(value, null, 2)}\n`);
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
let data;
|
|
523
|
+
try {
|
|
524
|
+
const raw = fs.readFileSync(path, "utf8");
|
|
525
|
+
data = raw.trim() ? JSON.parse(raw) : {};
|
|
526
|
+
} catch (err) {
|
|
527
|
+
console.error(`[project-init] Skipping invalid JSON while retiring project hook adapter: ${path}`);
|
|
528
|
+
process.exit(0);
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
if (!Object.prototype.hasOwnProperty.call(data, "hooks")) {
|
|
532
|
+
if (Object.keys(data).length === 0) fs.rmSync(path, { force: true });
|
|
533
|
+
process.exit(0);
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
const backup = `${path}.forge-migrate-backup`;
|
|
537
|
+
if (!fs.existsSync(backup)) fs.copyFileSync(path, backup);
|
|
538
|
+
delete data.hooks;
|
|
539
|
+
|
|
540
|
+
if (Object.keys(data).length === 0) {
|
|
541
|
+
fs.rmSync(path, { force: true });
|
|
542
|
+
} else {
|
|
543
|
+
writeJson(path, data);
|
|
544
|
+
}
|
|
545
|
+
NODE_EOF
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
pi_print_codex_hook_trust_notice() {
|
|
549
|
+
echo "Host hook adapters are user-level: run forge install --target both --location global, then trust ~/.codex/hooks.json in Codex Settings."
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
pi_repo_pins_hook_source() {
|
|
553
|
+
local repo="$1"
|
|
554
|
+
local policy_file="$repo/.ai/harness/policy.json"
|
|
555
|
+
|
|
556
|
+
if [[ "${FORGE_HOOK_SOURCE:-}" == "repo" ]]; then
|
|
557
|
+
return 0
|
|
558
|
+
fi
|
|
559
|
+
|
|
560
|
+
[[ -f "$policy_file" ]] || return 1
|
|
561
|
+
grep -Eq '"hook_source"[[:space:]]*:[[:space:]]*"repo"' "$policy_file"
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
pi_repo_pins_helper_source() {
|
|
565
|
+
local repo="$1"
|
|
566
|
+
local policy_file="$repo/.ai/harness/policy.json"
|
|
567
|
+
|
|
568
|
+
if [[ "${FORGE_HELPER_SOURCE:-}" == "repo" ]]; then
|
|
569
|
+
return 0
|
|
570
|
+
fi
|
|
571
|
+
|
|
572
|
+
[[ -f "$policy_file" ]] || return 1
|
|
573
|
+
grep -Eq '"helper_source"[[:space:]]*:[[:space:]]*"repo"' "$policy_file"
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
pi_write_hook_runtime_readme() {
|
|
577
|
+
local hooks_dir="$1"
|
|
578
|
+
local mode="${2:-apply}"
|
|
579
|
+
local readme="$hooks_dir/README.md"
|
|
580
|
+
|
|
581
|
+
if [[ "$mode" != "apply" ]]; then
|
|
582
|
+
echo "[dry-run] write $readme"
|
|
583
|
+
return 0
|
|
584
|
+
fi
|
|
585
|
+
|
|
586
|
+
mkdir -p "$hooks_dir"
|
|
587
|
+
cat > "$readme" <<'EOF_HOOK_README'
|
|
588
|
+
# Repo-Local Hook Fallback
|
|
589
|
+
|
|
590
|
+
This repo does not pin `"hook_source": "repo"`, so active hook execution is
|
|
591
|
+
user-level and central-first:
|
|
592
|
+
|
|
593
|
+
`~/.codex/hooks.json` / `~/.claude/settings.json` -> `forge-hook` ->
|
|
594
|
+
packaged hooks from the installed forge runtime.
|
|
595
|
+
|
|
596
|
+
The files under `.ai/hooks/lib/` are kept only for repo workflow helper scripts
|
|
597
|
+
that source shared shell utilities. Full hook runtime scripts are not vendored
|
|
598
|
+
here by default because stale copies can be mistaken for the active hook path.
|
|
599
|
+
|
|
600
|
+
Set `"hook_source": "repo"` in `.ai/harness/policy.json` only for self-hosted
|
|
601
|
+
hook development or an explicitly reviewed repo-local hook override.
|
|
602
|
+
EOF_HOOK_README
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
pi_prune_repo_local_hook_runtime() {
|
|
606
|
+
local hooks_dir="$1"
|
|
607
|
+
local mode="${2:-apply}"
|
|
608
|
+
|
|
609
|
+
if [[ ! -d "$hooks_dir" ]]; then
|
|
610
|
+
return 0
|
|
611
|
+
fi
|
|
612
|
+
|
|
613
|
+
if [[ "$mode" != "apply" ]]; then
|
|
614
|
+
echo "[dry-run] remove repo-local hook entry scripts from $hooks_dir unless hook_source is repo"
|
|
615
|
+
return 0
|
|
616
|
+
fi
|
|
617
|
+
|
|
618
|
+
find "$hooks_dir" -mindepth 1 -maxdepth 1 -type f \
|
|
619
|
+
\( -name '*.sh' \
|
|
620
|
+
-o -name 'AGENTS.md' \
|
|
621
|
+
-o -name 'CLAUDE.md' \
|
|
622
|
+
-o -name 'settings.template.json' \
|
|
623
|
+
-o -name 'codex.hooks.template.json' \
|
|
624
|
+
-o -name '.version' \) \
|
|
625
|
+
-delete
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
pi_install_hook_assets() {
|
|
629
|
+
local target_dir="$1"
|
|
630
|
+
local hooks_assets_dir="$2"
|
|
631
|
+
local mode="${3:-apply}"
|
|
632
|
+
local hooks_dir="$target_dir/.ai/hooks"
|
|
633
|
+
|
|
634
|
+
if [[ ! -d "$hooks_assets_dir" ]]; then
|
|
635
|
+
echo "[project-init] Warning: hook assets not found at $hooks_assets_dir" >&2
|
|
636
|
+
echo "[project-init] User-level host adapters dispatch through forge-hook packaged hooks." >&2
|
|
637
|
+
return 0
|
|
638
|
+
fi
|
|
639
|
+
|
|
640
|
+
if [[ "$mode" != "apply" ]]; then
|
|
641
|
+
echo "[dry-run] mkdir -p \"$hooks_dir\""
|
|
642
|
+
else
|
|
643
|
+
mkdir -p "$hooks_dir"
|
|
644
|
+
fi
|
|
645
|
+
|
|
646
|
+
if pi_repo_pins_hook_source "$target_dir"; then
|
|
647
|
+
while IFS= read -r hook; do
|
|
648
|
+
local rel_path rel_dir dest_dir hook_name
|
|
649
|
+
rel_path="${hook#"$hooks_assets_dir"/}"
|
|
650
|
+
rel_dir="$(dirname "$rel_path")"
|
|
651
|
+
if [[ "$rel_dir" == "." ]]; then
|
|
652
|
+
dest_dir="$hooks_dir"
|
|
653
|
+
else
|
|
654
|
+
dest_dir="$hooks_dir/$rel_dir"
|
|
655
|
+
fi
|
|
656
|
+
hook_name="$(basename "$hook")"
|
|
657
|
+
if [[ "$mode" != "apply" ]]; then
|
|
658
|
+
echo "[dry-run] mkdir -p \"$dest_dir\""
|
|
659
|
+
echo "[dry-run] cp \"$hook\" \"$dest_dir/$hook_name\""
|
|
660
|
+
continue
|
|
661
|
+
fi
|
|
662
|
+
mkdir -p "$dest_dir"
|
|
663
|
+
cp "$hook" "$dest_dir/$hook_name"
|
|
664
|
+
chmod +x "$dest_dir/$hook_name" 2>/dev/null || true
|
|
665
|
+
done < <(find "$hooks_assets_dir" -type f -name '*.sh' | sort)
|
|
666
|
+
return 0
|
|
667
|
+
fi
|
|
668
|
+
|
|
669
|
+
pi_prune_repo_local_hook_runtime "$hooks_dir" "$mode"
|
|
670
|
+
|
|
671
|
+
if [[ "$mode" != "apply" ]]; then
|
|
672
|
+
echo "[dry-run] mkdir -p \"$hooks_dir/lib\""
|
|
673
|
+
else
|
|
674
|
+
mkdir -p "$hooks_dir/lib"
|
|
675
|
+
fi
|
|
676
|
+
|
|
677
|
+
if [[ -d "$hooks_assets_dir/lib" ]]; then
|
|
678
|
+
while IFS= read -r hook_lib; do
|
|
679
|
+
local lib_name
|
|
680
|
+
lib_name="$(basename "$hook_lib")"
|
|
681
|
+
if [[ "$mode" != "apply" ]]; then
|
|
682
|
+
echo "[dry-run] cp \"$hook_lib\" \"$hooks_dir/lib/$lib_name\""
|
|
683
|
+
continue
|
|
684
|
+
fi
|
|
685
|
+
cp "$hook_lib" "$hooks_dir/lib/$lib_name"
|
|
686
|
+
chmod +x "$hooks_dir/lib/$lib_name" 2>/dev/null || true
|
|
687
|
+
done < <(find "$hooks_assets_dir/lib" -maxdepth 1 -type f -name '*.sh' | sort)
|
|
688
|
+
fi
|
|
689
|
+
|
|
690
|
+
pi_write_hook_runtime_readme "$hooks_dir" "$mode"
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
pi_ensure_executable_if_apply() {
|
|
694
|
+
local mode="${1:-apply}"
|
|
695
|
+
shift || true
|
|
696
|
+
|
|
697
|
+
if [[ "$mode" != "apply" || "$#" -eq 0 ]]; then
|
|
698
|
+
return 0
|
|
699
|
+
fi
|
|
700
|
+
|
|
701
|
+
local candidate first_line
|
|
702
|
+
for candidate in "$@"; do
|
|
703
|
+
[[ -f "$candidate" ]] || continue
|
|
704
|
+
case "$candidate" in
|
|
705
|
+
*.sh)
|
|
706
|
+
chmod +x "$candidate" 2>/dev/null || true
|
|
707
|
+
;;
|
|
708
|
+
*.ts)
|
|
709
|
+
first_line="$(head -n 1 "$candidate" 2>/dev/null || true)"
|
|
710
|
+
if [[ "$first_line" == '#!'* ]]; then
|
|
711
|
+
chmod +x "$candidate" 2>/dev/null || true
|
|
712
|
+
fi
|
|
713
|
+
;;
|
|
714
|
+
esac
|
|
715
|
+
done
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
pi_default_runtime_block() {
|
|
719
|
+
local extra_entries="${1:-}"
|
|
720
|
+
local runtime_entries="$PI_DEFAULT_RUNTIME_ENTRIES"
|
|
721
|
+
|
|
722
|
+
if [[ -n "$extra_entries" ]]; then
|
|
723
|
+
runtime_entries="${runtime_entries}"$'\n'"${extra_entries}"
|
|
724
|
+
fi
|
|
725
|
+
|
|
726
|
+
printf '%s\n%s\n%s\n' "$PI_RUNTIME_BLOCK_BEGIN" "$runtime_entries" "$PI_RUNTIME_BLOCK_END"
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
pi_helper_wrapper_paths() {
|
|
730
|
+
local workflow_contract="$1"
|
|
731
|
+
local helper_names
|
|
732
|
+
local helper_name
|
|
733
|
+
|
|
734
|
+
helper_names="$(pi_workflow_contract_query_lines "$workflow_contract" "helpers.scripts" | xargs)"
|
|
735
|
+
for helper_name in $helper_names; do
|
|
736
|
+
printf 'scripts/%s\n' "$helper_name"
|
|
737
|
+
done
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
pi_helper_wrapper_gitignore_entries() {
|
|
741
|
+
local workflow_contract="$1"
|
|
742
|
+
local paths
|
|
743
|
+
|
|
744
|
+
paths="$(pi_helper_wrapper_paths "$workflow_contract")"
|
|
745
|
+
[[ -n "$paths" ]] || return 0
|
|
746
|
+
|
|
747
|
+
printf '%s\n' "# forge generated helper wrappers"
|
|
748
|
+
printf '%s\n' "$paths"
|
|
749
|
+
printf '%s\n' "scripts/forge/"
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
pi_is_runtime_block_begin() {
|
|
753
|
+
local line="$1"
|
|
754
|
+
[[ "$line" == "$PI_RUNTIME_BLOCK_BEGIN" ]]
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
pi_has_runtime_block() {
|
|
758
|
+
local file_path="$1"
|
|
759
|
+
grep -Fq "$PI_RUNTIME_BLOCK_BEGIN" "$file_path"
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
pi_ensure_gitignore_block() {
|
|
763
|
+
local file_path="$1"
|
|
764
|
+
local prelude="${2:-}"
|
|
765
|
+
local extra_entries="${3:-}"
|
|
766
|
+
local mode="${4:-apply}"
|
|
767
|
+
local block
|
|
768
|
+
|
|
769
|
+
block="$(pi_default_runtime_block "$extra_entries")"
|
|
770
|
+
|
|
771
|
+
if [[ "$mode" != "apply" ]]; then
|
|
772
|
+
echo "[dry-run] ensure managed runtime block in $file_path"
|
|
773
|
+
return 0
|
|
774
|
+
fi
|
|
775
|
+
|
|
776
|
+
mkdir -p "$(dirname "$file_path")"
|
|
777
|
+
if [[ ! -f "$file_path" ]]; then
|
|
778
|
+
if [[ -n "$prelude" ]]; then
|
|
779
|
+
printf '%s\n' "$prelude" > "$file_path"
|
|
780
|
+
else
|
|
781
|
+
touch "$file_path"
|
|
782
|
+
fi
|
|
783
|
+
fi
|
|
784
|
+
|
|
785
|
+
if ! pi_has_runtime_block "$file_path"; then
|
|
786
|
+
printf '\n%s\n' "$block" >> "$file_path"
|
|
787
|
+
return 0
|
|
788
|
+
fi
|
|
789
|
+
|
|
790
|
+
local tmp_file
|
|
791
|
+
local block_written=0
|
|
792
|
+
tmp_file="$(mktemp)"
|
|
793
|
+
|
|
794
|
+
while IFS= read -r line || [[ -n "$line" ]]; do
|
|
795
|
+
if pi_is_runtime_block_begin "$line"; then
|
|
796
|
+
if [[ "$block_written" -eq 0 ]]; then
|
|
797
|
+
printf '%s\n' "$block" >> "$tmp_file"
|
|
798
|
+
block_written=1
|
|
799
|
+
fi
|
|
800
|
+
|
|
801
|
+
while IFS= read -r inner_line || [[ -n "$inner_line" ]]; do
|
|
802
|
+
if [[ "$inner_line" == "$PI_RUNTIME_BLOCK_END" ]]; then
|
|
803
|
+
break
|
|
804
|
+
fi
|
|
805
|
+
done
|
|
806
|
+
continue
|
|
807
|
+
fi
|
|
808
|
+
|
|
809
|
+
printf '%s\n' "$line" >> "$tmp_file"
|
|
810
|
+
done < "$file_path"
|
|
811
|
+
|
|
812
|
+
mv "$tmp_file" "$file_path"
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
pi_resolve_json_runtime() {
|
|
816
|
+
if command -v node >/dev/null 2>&1; then
|
|
817
|
+
printf 'node'
|
|
818
|
+
return 0
|
|
819
|
+
fi
|
|
820
|
+
|
|
821
|
+
if command -v bun >/dev/null 2>&1; then
|
|
822
|
+
printf 'bun'
|
|
823
|
+
return 0
|
|
824
|
+
fi
|
|
825
|
+
|
|
826
|
+
if command -v python3 >/dev/null 2>&1; then
|
|
827
|
+
printf 'python3'
|
|
828
|
+
return 0
|
|
829
|
+
fi
|
|
830
|
+
|
|
831
|
+
return 1
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
pi_workflow_contract_query_lines() {
|
|
835
|
+
local contract_file="$1"
|
|
836
|
+
local selector="$2"
|
|
837
|
+
local runtime
|
|
838
|
+
|
|
839
|
+
if [[ ! -f "$contract_file" ]]; then
|
|
840
|
+
return 1
|
|
841
|
+
fi
|
|
842
|
+
|
|
843
|
+
runtime="$(pi_resolve_json_runtime || true)"
|
|
844
|
+
if [[ -z "$runtime" ]]; then
|
|
845
|
+
echo "[warn] no runtime available to read workflow contract: $contract_file" >&2
|
|
846
|
+
return 1
|
|
847
|
+
fi
|
|
848
|
+
|
|
849
|
+
case "$runtime" in
|
|
850
|
+
python3)
|
|
851
|
+
"$runtime" - "$contract_file" "$selector" <<'PY_EOF'
|
|
852
|
+
import json
|
|
853
|
+
import sys
|
|
854
|
+
|
|
855
|
+
path, selector = sys.argv[1], sys.argv[2]
|
|
856
|
+
value = json.load(open(path, "r", encoding="utf-8"))
|
|
857
|
+
for part in selector.split("."):
|
|
858
|
+
value = value.get(part) if isinstance(value, dict) else None
|
|
859
|
+
if isinstance(value, list):
|
|
860
|
+
for item in value:
|
|
861
|
+
print(item)
|
|
862
|
+
elif value is not None:
|
|
863
|
+
print(value)
|
|
864
|
+
PY_EOF
|
|
865
|
+
;;
|
|
866
|
+
*)
|
|
867
|
+
"$runtime" -e '
|
|
868
|
+
const fs = require("fs");
|
|
869
|
+
const [, filePath, selector] = process.argv;
|
|
870
|
+
const parts = selector.split(".");
|
|
871
|
+
let value = JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
872
|
+
for (const part of parts) {
|
|
873
|
+
value = value && typeof value === "object" ? value[part] : undefined;
|
|
874
|
+
}
|
|
875
|
+
if (Array.isArray(value)) {
|
|
876
|
+
for (const item of value) {
|
|
877
|
+
console.log(item);
|
|
878
|
+
}
|
|
879
|
+
} else if (value !== undefined && value !== null) {
|
|
880
|
+
console.log(value);
|
|
881
|
+
}
|
|
882
|
+
' "$contract_file" "$selector"
|
|
883
|
+
;;
|
|
884
|
+
esac
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
pi_workflow_contract_upgrade_action_paths() {
|
|
888
|
+
local contract_file="$1"
|
|
889
|
+
local action_filter="${2:-remove}"
|
|
890
|
+
local ownership_filter="${3:-known_generated}"
|
|
891
|
+
local runtime
|
|
892
|
+
|
|
893
|
+
if [[ ! -f "$contract_file" ]]; then
|
|
894
|
+
return 1
|
|
895
|
+
fi
|
|
896
|
+
|
|
897
|
+
runtime="$(pi_resolve_json_runtime || true)"
|
|
898
|
+
if [[ -z "$runtime" ]]; then
|
|
899
|
+
echo "[warn] no runtime available to read workflow contract: $contract_file" >&2
|
|
900
|
+
return 1
|
|
901
|
+
fi
|
|
902
|
+
|
|
903
|
+
case "$runtime" in
|
|
904
|
+
python3)
|
|
905
|
+
"$runtime" - "$contract_file" "$action_filter" "$ownership_filter" <<'PY_EOF'
|
|
906
|
+
import json
|
|
907
|
+
import sys
|
|
908
|
+
|
|
909
|
+
path, action_filter, ownership_filter = sys.argv[1], sys.argv[2], sys.argv[3]
|
|
910
|
+
contract = json.load(open(path, "r", encoding="utf-8"))
|
|
911
|
+
for action in contract.get("migrations", {}).get("upgrade", {}).get("actions", []):
|
|
912
|
+
if action.get("action") != action_filter:
|
|
913
|
+
continue
|
|
914
|
+
if ownership_filter and action.get("ownership") != ownership_filter:
|
|
915
|
+
continue
|
|
916
|
+
for rel_path in action.get("paths", []):
|
|
917
|
+
print(rel_path)
|
|
918
|
+
PY_EOF
|
|
919
|
+
;;
|
|
920
|
+
*)
|
|
921
|
+
"$runtime" -e '
|
|
922
|
+
const fs = require("fs");
|
|
923
|
+
const [, filePath, actionFilter, ownershipFilter] = process.argv;
|
|
924
|
+
const contract = JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
925
|
+
const actions = contract.migrations?.upgrade?.actions ?? [];
|
|
926
|
+
for (const action of actions) {
|
|
927
|
+
if (action.action !== actionFilter) continue;
|
|
928
|
+
if (ownershipFilter && action.ownership !== ownershipFilter) continue;
|
|
929
|
+
for (const relPath of action.paths ?? []) {
|
|
930
|
+
console.log(relPath);
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
' "$contract_file" "$action_filter" "$ownership_filter"
|
|
934
|
+
;;
|
|
935
|
+
esac
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
pi_workflow_contract_upgrade_action_entries() {
|
|
939
|
+
local contract_file="$1"
|
|
940
|
+
local action_filter="${2:-remove}"
|
|
941
|
+
local ownership_filter="${3:-known_generated}"
|
|
942
|
+
local runtime
|
|
943
|
+
|
|
944
|
+
if [[ ! -f "$contract_file" ]]; then
|
|
945
|
+
return 1
|
|
946
|
+
fi
|
|
947
|
+
|
|
948
|
+
runtime="$(pi_resolve_json_runtime || true)"
|
|
949
|
+
if [[ -z "$runtime" ]]; then
|
|
950
|
+
echo "[warn] no runtime available to read workflow contract: $contract_file" >&2
|
|
951
|
+
return 1
|
|
952
|
+
fi
|
|
953
|
+
|
|
954
|
+
case "$runtime" in
|
|
955
|
+
python3)
|
|
956
|
+
"$runtime" - "$contract_file" "$action_filter" "$ownership_filter" <<'PY_EOF'
|
|
957
|
+
import json
|
|
958
|
+
import sys
|
|
959
|
+
|
|
960
|
+
path, action_filter, ownership_filter = sys.argv[1], sys.argv[2], sys.argv[3]
|
|
961
|
+
contract = json.load(open(path, "r", encoding="utf-8"))
|
|
962
|
+
for action in contract.get("migrations", {}).get("upgrade", {}).get("actions", []):
|
|
963
|
+
if action.get("action") != action_filter:
|
|
964
|
+
continue
|
|
965
|
+
if ownership_filter and action.get("ownership") != ownership_filter:
|
|
966
|
+
continue
|
|
967
|
+
cleanup_mode = action.get("cleanupMode", "always")
|
|
968
|
+
for rel_path in action.get("paths", []):
|
|
969
|
+
print(f"{cleanup_mode}\t{rel_path}")
|
|
970
|
+
PY_EOF
|
|
971
|
+
;;
|
|
972
|
+
*)
|
|
973
|
+
"$runtime" -e '
|
|
974
|
+
const fs = require("fs");
|
|
975
|
+
const [, filePath, actionFilter, ownershipFilter] = process.argv;
|
|
976
|
+
const contract = JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
977
|
+
const actions = contract.migrations?.upgrade?.actions ?? [];
|
|
978
|
+
for (const action of actions) {
|
|
979
|
+
if (action.action !== actionFilter) continue;
|
|
980
|
+
if (ownershipFilter && action.ownership !== ownershipFilter) continue;
|
|
981
|
+
const cleanupMode = action.cleanupMode ?? "always";
|
|
982
|
+
for (const relPath of action.paths ?? []) {
|
|
983
|
+
console.log(`${cleanupMode}\t${relPath}`);
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
' "$contract_file" "$action_filter" "$ownership_filter"
|
|
987
|
+
;;
|
|
988
|
+
esac
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
pi_install_workflow_contract() {
|
|
992
|
+
local target_dir="$1"
|
|
993
|
+
local contract_asset="$2"
|
|
994
|
+
local mode="${3:-apply}"
|
|
995
|
+
local output_path="$target_dir/.ai/harness/workflow-contract.json"
|
|
996
|
+
|
|
997
|
+
if [[ "$mode" != "apply" ]]; then
|
|
998
|
+
echo "[dry-run] install workflow contract into $output_path"
|
|
999
|
+
return 0
|
|
1000
|
+
fi
|
|
1001
|
+
|
|
1002
|
+
mkdir -p "$(dirname "$output_path")"
|
|
1003
|
+
cp "$contract_asset" "$output_path"
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
pi_install_templates() {
|
|
1007
|
+
local target_dir="$1"
|
|
1008
|
+
local templates_dir="$2"
|
|
1009
|
+
local mode="${3:-apply}"
|
|
1010
|
+
local output_dir="$target_dir/.claude/templates"
|
|
1011
|
+
|
|
1012
|
+
if [[ "$mode" != "apply" ]]; then
|
|
1013
|
+
echo "[dry-run] install templates into $output_dir"
|
|
1014
|
+
return 0
|
|
1015
|
+
fi
|
|
1016
|
+
|
|
1017
|
+
mkdir -p "$output_dir"
|
|
1018
|
+
|
|
1019
|
+
if [[ -f "$templates_dir/research.template.md" ]]; then
|
|
1020
|
+
cp "$templates_dir/research.template.md" "$output_dir/research.template.md"
|
|
1021
|
+
else
|
|
1022
|
+
printf '%s\n' "$PI_TEMPLATE_RESEARCH" > "$output_dir/research.template.md"
|
|
1023
|
+
fi
|
|
1024
|
+
|
|
1025
|
+
if [[ -f "$templates_dir/spec.template.md" ]]; then
|
|
1026
|
+
cp "$templates_dir/spec.template.md" "$output_dir/spec.template.md"
|
|
1027
|
+
else
|
|
1028
|
+
printf '%s\n' "$PI_TEMPLATE_SPEC" > "$output_dir/spec.template.md"
|
|
1029
|
+
fi
|
|
1030
|
+
|
|
1031
|
+
if [[ -f "$templates_dir/plan.template.md" ]]; then
|
|
1032
|
+
cp "$templates_dir/plan.template.md" "$output_dir/plan.template.md"
|
|
1033
|
+
else
|
|
1034
|
+
printf '%s\n' "$PI_TEMPLATE_PLAN" > "$output_dir/plan.template.md"
|
|
1035
|
+
fi
|
|
1036
|
+
|
|
1037
|
+
if [[ -f "$templates_dir/contract.template.md" ]]; then
|
|
1038
|
+
cp "$templates_dir/contract.template.md" "$output_dir/contract.template.md"
|
|
1039
|
+
else
|
|
1040
|
+
printf '%s\n' "$PI_TEMPLATE_CONTRACT" > "$output_dir/contract.template.md"
|
|
1041
|
+
fi
|
|
1042
|
+
|
|
1043
|
+
if [[ -f "$templates_dir/review.template.md" ]]; then
|
|
1044
|
+
cp "$templates_dir/review.template.md" "$output_dir/review.template.md"
|
|
1045
|
+
else
|
|
1046
|
+
printf '%s\n' "$PI_TEMPLATE_REVIEW" > "$output_dir/review.template.md"
|
|
1047
|
+
fi
|
|
1048
|
+
|
|
1049
|
+
if [[ -f "$templates_dir/implementation-notes.template.md" ]]; then
|
|
1050
|
+
cp "$templates_dir/implementation-notes.template.md" "$output_dir/implementation-notes.template.md"
|
|
1051
|
+
else
|
|
1052
|
+
printf '%s\n' "$PI_TEMPLATE_IMPLEMENTATION_NOTES" > "$output_dir/implementation-notes.template.md"
|
|
1053
|
+
fi
|
|
1054
|
+
|
|
1055
|
+
# Sprint template ships when available; sprint-backlog.sh also carries an
|
|
1056
|
+
# inline fallback, so older asset dirs degrade gracefully.
|
|
1057
|
+
if [[ -f "$templates_dir/sprint.template.md" ]]; then
|
|
1058
|
+
cp "$templates_dir/sprint.template.md" "$output_dir/sprint.template.md"
|
|
1059
|
+
fi
|
|
1060
|
+
|
|
1061
|
+
if [[ -f "$templates_dir/prd.template.md" ]]; then
|
|
1062
|
+
cp "$templates_dir/prd.template.md" "$output_dir/prd.template.md"
|
|
1063
|
+
fi
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
pi_install_helpers() {
|
|
1067
|
+
local target_dir="$1"
|
|
1068
|
+
local helpers_dir="$2"
|
|
1069
|
+
local mode="${3:-apply}"
|
|
1070
|
+
local helper_names="${4:-new-spec.sh new-sprint.sh new-plan.sh capture-plan.sh plan-to-todo.sh contract-run.ts contract-worktree.sh ship-worktrees.sh archive-workflow.sh refresh-current-status.sh prepare-handoff.sh verify-contract.sh summarize-failures.sh verify-sprint.sh harness-trace-grade.sh sprint-backlog.sh check-task-sync.sh check-deploy-sql-order.sh check-architecture-sync.sh check-agent-tooling.sh check-context-files.sh check-brain-manifest.sh sync-brain-docs.sh check-skill-version.ts select-agent-context-blocks.sh ensure-task-workflow.sh check-task-workflow.sh maintenance-triage.sh heartbeat-triage.sh switch-plan.sh workflow-contract.ts inspect-project-state.ts migrate-workflow-docs.ts migrate-project-template.sh capability-resolver.ts architecture-event.ts capability-config.ts architecture-queue.sh archive-architecture-request.sh context-contract-sync.sh workstream-sync.sh prepare-codex-handoff.sh codex-handoff-resume.sh}"
|
|
1071
|
+
local scripts_dir="$target_dir/scripts"
|
|
1072
|
+
local runtime_dir="$target_dir/.ai/harness/scripts"
|
|
1073
|
+
local helper_name
|
|
1074
|
+
local source_repo_target=0
|
|
1075
|
+
|
|
1076
|
+
if [[ -d "$target_dir/assets/templates/helpers" && -d "$helpers_dir" ]]; then
|
|
1077
|
+
local target_helpers_abs helpers_abs
|
|
1078
|
+
target_helpers_abs="$(cd "$target_dir/assets/templates/helpers" && pwd)"
|
|
1079
|
+
helpers_abs="$(cd "$helpers_dir" && pwd)"
|
|
1080
|
+
if [[ "$target_helpers_abs" == "$helpers_abs" ]]; then
|
|
1081
|
+
source_repo_target=1
|
|
1082
|
+
fi
|
|
1083
|
+
fi
|
|
1084
|
+
|
|
1085
|
+
if [[ "$mode" != "apply" ]]; then
|
|
1086
|
+
if [[ "$source_repo_target" -eq 1 || "$(pi_repo_pins_helper_source "$target_dir" && printf yes || true)" == "yes" ]]; then
|
|
1087
|
+
echo "[dry-run] install source helpers into $scripts_dir"
|
|
1088
|
+
else
|
|
1089
|
+
echo "[dry-run] install helper compatibility wrappers in $scripts_dir; package runtime dispatches through forge run"
|
|
1090
|
+
fi
|
|
1091
|
+
return 0
|
|
1092
|
+
fi
|
|
1093
|
+
|
|
1094
|
+
mkdir -p "$scripts_dir"
|
|
1095
|
+
mkdir -p "$runtime_dir"
|
|
1096
|
+
|
|
1097
|
+
if [[ -d "$helpers_dir" ]]; then
|
|
1098
|
+
for helper_name in $helper_names; do
|
|
1099
|
+
if [[ -f "$helpers_dir/$helper_name" ]]; then
|
|
1100
|
+
if [[ "$helper_name" == "migrate-project-template.sh" ]]; then
|
|
1101
|
+
local target_abs=""
|
|
1102
|
+
local skill_abs=""
|
|
1103
|
+
target_abs="$(cd "$target_dir" && pwd)"
|
|
1104
|
+
if [[ -n "${SKILL_ROOT:-}" ]]; then
|
|
1105
|
+
skill_abs="$(cd "$SKILL_ROOT" && pwd)"
|
|
1106
|
+
else
|
|
1107
|
+
skill_abs="$(cd "$helpers_dir/../.." && pwd)"
|
|
1108
|
+
fi
|
|
1109
|
+
if [[ "$target_abs" == "$skill_abs" ]]; then
|
|
1110
|
+
continue
|
|
1111
|
+
fi
|
|
1112
|
+
fi
|
|
1113
|
+
if [[ "$source_repo_target" -eq 1 ]]; then
|
|
1114
|
+
cp "$helpers_dir/$helper_name" "$scripts_dir/$helper_name"
|
|
1115
|
+
elif pi_repo_pins_helper_source "$target_dir"; then
|
|
1116
|
+
cp "$helpers_dir/$helper_name" "$runtime_dir/$helper_name"
|
|
1117
|
+
pi_normalize_installed_helper "$runtime_dir/$helper_name"
|
|
1118
|
+
if ! pi_preserve_existing_app_script "$scripts_dir/$helper_name" "$helpers_dir/$helper_name"; then
|
|
1119
|
+
pi_write_helper_wrapper "$scripts_dir/$helper_name" "$helper_name"
|
|
1120
|
+
fi
|
|
1121
|
+
else
|
|
1122
|
+
if ! pi_preserve_existing_app_script "$scripts_dir/$helper_name" "$helpers_dir/$helper_name"; then
|
|
1123
|
+
pi_write_helper_wrapper "$scripts_dir/$helper_name" "$helper_name"
|
|
1124
|
+
else
|
|
1125
|
+
mkdir -p "$scripts_dir/forge"
|
|
1126
|
+
pi_write_helper_wrapper "$scripts_dir/forge/$helper_name" "$helper_name"
|
|
1127
|
+
fi
|
|
1128
|
+
fi
|
|
1129
|
+
fi
|
|
1130
|
+
done
|
|
1131
|
+
pi_ensure_executable_if_apply "$mode" "$runtime_dir"/*.sh "$runtime_dir"/*.ts "$scripts_dir"/*.sh "$scripts_dir"/*.ts "$scripts_dir/forge"/*.sh "$scripts_dir/forge"/*.ts
|
|
1132
|
+
return 0
|
|
1133
|
+
fi
|
|
1134
|
+
|
|
1135
|
+
for helper_name in $helper_names; do
|
|
1136
|
+
pi_write_helper_wrapper "$scripts_dir/$helper_name" "$helper_name"
|
|
1137
|
+
done
|
|
1138
|
+
pi_ensure_executable_if_apply "$mode" "$scripts_dir"/*.sh "$scripts_dir"/*.ts
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
pi_preserve_existing_app_script() {
|
|
1142
|
+
local output_file="$1"
|
|
1143
|
+
local source_file="$2"
|
|
1144
|
+
|
|
1145
|
+
[[ -f "$output_file" ]] || return 1
|
|
1146
|
+
|
|
1147
|
+
if cmp -s "$output_file" "$source_file"; then
|
|
1148
|
+
return 1
|
|
1149
|
+
fi
|
|
1150
|
+
|
|
1151
|
+
if grep -Eiq '(forge|claude-runtime-temp|Task Contract|Task Review|Deferred Goal Ledger|Workflow Contract|ContractWorktree|SprintBacklog|ArchitectureSync|ArchitectureDrift|BrainSync|CurrentStatus|\.ai/harness|\.claude/templates|tasks/contracts|tasks/reviews)' "$output_file"; then
|
|
1152
|
+
return 1
|
|
1153
|
+
fi
|
|
1154
|
+
|
|
1155
|
+
return 0
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1158
|
+
pi_write_helper_wrapper() {
|
|
1159
|
+
local output_file="$1"
|
|
1160
|
+
local helper_name="$2"
|
|
1161
|
+
|
|
1162
|
+
case "$helper_name" in
|
|
1163
|
+
*.ts)
|
|
1164
|
+
cat > "$output_file" <<EOF_WRAPPER_TS
|
|
1165
|
+
#!/usr/bin/env bun
|
|
1166
|
+
import { spawnSync } from "node:child_process";
|
|
1167
|
+
import { existsSync } from "node:fs";
|
|
1168
|
+
import { join } from "node:path";
|
|
1169
|
+
|
|
1170
|
+
const sourceRoot =
|
|
1171
|
+
process.env.FORGE_SOURCE_ROOT ||
|
|
1172
|
+
process.env.AGENTIC_DEV_ROOT ||
|
|
1173
|
+
process.env.AGENTIC_DEV_SKILL_ROOT;
|
|
1174
|
+
const command = sourceRoot && existsSync(join(sourceRoot, "src", "cli", "index.ts"))
|
|
1175
|
+
? ["bun", join(sourceRoot, "src", "cli", "index.ts"), "run", "$(basename "$helper_name" .ts)"]
|
|
1176
|
+
: ["forge", "run", "$(basename "$helper_name" .ts)"];
|
|
1177
|
+
|
|
1178
|
+
const result = spawnSync(command[0], [...command.slice(1), ...process.argv.slice(2)], {
|
|
1179
|
+
cwd: process.cwd(),
|
|
1180
|
+
env: process.env,
|
|
1181
|
+
stdio: "inherit",
|
|
1182
|
+
});
|
|
1183
|
+
|
|
1184
|
+
if (result.error) {
|
|
1185
|
+
console.error(\`Missing forge CLI for helper $(basename "$helper_name" .ts): \${result.error.message}\`);
|
|
1186
|
+
process.exit(1);
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
process.exit(result.status ?? 1);
|
|
1190
|
+
EOF_WRAPPER_TS
|
|
1191
|
+
;;
|
|
1192
|
+
*)
|
|
1193
|
+
local helper_id="${helper_name%.*}"
|
|
1194
|
+
cat > "$output_file" <<EOF_WRAPPER_SH
|
|
1195
|
+
#!/bin/bash
|
|
1196
|
+
set -euo pipefail
|
|
1197
|
+
|
|
1198
|
+
SOURCE_ROOT="\${FORGE_SOURCE_ROOT:-\${AGENTIC_DEV_ROOT:-\${AGENTIC_DEV_SKILL_ROOT:-}}}"
|
|
1199
|
+
|
|
1200
|
+
if [[ -n "\$SOURCE_ROOT" && -f "\$SOURCE_ROOT/src/cli/index.ts" ]]; then
|
|
1201
|
+
if command -v bun >/dev/null 2>&1; then
|
|
1202
|
+
exec bun "\$SOURCE_ROOT/src/cli/index.ts" run $helper_id "\$@"
|
|
1203
|
+
fi
|
|
1204
|
+
fi
|
|
1205
|
+
|
|
1206
|
+
if command -v forge >/dev/null 2>&1; then
|
|
1207
|
+
exec forge run $helper_id "\$@"
|
|
1208
|
+
fi
|
|
1209
|
+
|
|
1210
|
+
echo "Missing forge CLI for helper $helper_id" >&2
|
|
1211
|
+
exit 1
|
|
1212
|
+
EOF_WRAPPER_SH
|
|
1213
|
+
;;
|
|
1214
|
+
esac
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
pi_normalize_installed_helper() {
|
|
1218
|
+
local helper_file="$1"
|
|
1219
|
+
[[ -f "$helper_file" ]] || return 0
|
|
1220
|
+
|
|
1221
|
+
if [[ "$helper_file" == *.sh ]]; then
|
|
1222
|
+
perl -0pi -e '
|
|
1223
|
+
s#([A-Z_][A-Z0-9_]*)="\$\(cd "\$SCRIPT_DIR/\.\." && pwd\)"#${1}="\$(cd "\$SCRIPT_DIR/../../.." && pwd)"#g;
|
|
1224
|
+
s#if ([A-Z_][A-Z0-9_]*)="\$\(git -C "\$SCRIPT_DIR/\.\." rev-parse --show-toplevel 2>/dev/null\)"; then#if ${1}="\$(git -C "\$SCRIPT_DIR/../../.." rev-parse --show-toplevel 2>/dev/null)"; then#g;
|
|
1225
|
+
s#cd "\$SCRIPT_DIR/\.\."#if [[ "\$SCRIPT_DIR" == */.ai/harness/scripts ]]; then\n cd "\$SCRIPT_DIR/../../.."\nelse\n cd "\$SCRIPT_DIR/.."\nfi#g;
|
|
1226
|
+
s#git -C "\$SCRIPT_DIR/\.\."#git -C "\$SCRIPT_DIR/../../.."#g;
|
|
1227
|
+
s#\./scripts/#.ai/harness/scripts/#g;
|
|
1228
|
+
s#(\$[A-Za-z_][A-Za-z0-9_]*|\$\{[A-Za-z_][A-Za-z0-9_]*\})/scripts/#$1/.ai/harness/scripts/#g;
|
|
1229
|
+
s#(?<![A-Za-z0-9_./-])scripts/#.ai/harness/scripts/#g;
|
|
1230
|
+
' "$helper_file"
|
|
1231
|
+
elif [[ "$helper_file" == *.ts ]]; then
|
|
1232
|
+
perl -0pi -e '
|
|
1233
|
+
s#join\(SCRIPT_DIR, "\.\."\)#join(SCRIPT_DIR, "..", "..", "..")#g;
|
|
1234
|
+
s#join\(__dirname, "\.\."\)#join(__dirname, "..", "..", "..")#g;
|
|
1235
|
+
s#\./scripts/#.ai/harness/scripts/#g;
|
|
1236
|
+
s#(\$[A-Za-z_][A-Za-z0-9_]*|\$\{[A-Za-z_][A-Za-z0-9_]*\})/scripts/#$1/.ai/harness/scripts/#g;
|
|
1237
|
+
s#(?<![A-Za-z0-9_./-])scripts/#.ai/harness/scripts/#g;
|
|
1238
|
+
' "$helper_file"
|
|
1239
|
+
fi
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
pi_env_value() {
|
|
1243
|
+
local name="$1"
|
|
1244
|
+
local default_value="${2:-}"
|
|
1245
|
+
local value
|
|
1246
|
+
|
|
1247
|
+
value="${!name-}"
|
|
1248
|
+
if [[ -n "$value" ]]; then
|
|
1249
|
+
printf '%s' "$value"
|
|
1250
|
+
return 0
|
|
1251
|
+
fi
|
|
1252
|
+
|
|
1253
|
+
printf '%s' "$default_value"
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1256
|
+
pi_plan_type() {
|
|
1257
|
+
local default_value="${1:-}"
|
|
1258
|
+
pi_env_value "FORGE_PLAN_TYPE" "$default_value"
|
|
1259
|
+
}
|
|
1260
|
+
|
|
1261
|
+
pi_context_profile() {
|
|
1262
|
+
pi_env_value "FORGE_CONTEXT_PROFILE" "$PI_CONTEXT_PROFILE_DEFAULT"
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1265
|
+
pi_recovery_profile() {
|
|
1266
|
+
pi_env_value "FORGE_RECOVERY_PROFILE" "$PI_RECOVERY_PROFILE_DEFAULT"
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
pi_state_profile() {
|
|
1270
|
+
pi_env_value "FORGE_STATE_PROFILE" "$PI_STATE_PROFILE_DEFAULT"
|
|
1271
|
+
}
|
|
1272
|
+
|
|
1273
|
+
pi_orchestration_profile() {
|
|
1274
|
+
pi_env_value "FORGE_ORCHESTRATION_PROFILE" "$PI_ORCHESTRATION_PROFILE_DEFAULT"
|
|
1275
|
+
}
|
|
1276
|
+
|
|
1277
|
+
pi_evaluation_profile() {
|
|
1278
|
+
pi_env_value "FORGE_EVALUATION_PROFILE" "$PI_EVALUATION_PROFILE_DEFAULT"
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
pi_handoff_profile() {
|
|
1282
|
+
pi_env_value "FORGE_HANDOFF_PROFILE" "$PI_HANDOFF_PROFILE_DEFAULT"
|
|
1283
|
+
}
|
|
1284
|
+
|
|
1285
|
+
pi_documentation_profile() {
|
|
1286
|
+
pi_env_value "FORGE_DOCUMENTATION_PROFILE" "$PI_DOCUMENTATION_PROFILE_DEFAULT"
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1289
|
+
pi_lsp_profile() {
|
|
1290
|
+
pi_env_value "FORGE_LSP_PROFILE" "$PI_DEFAULT_LSP_PROFILE"
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1293
|
+
pi_should_generate_full_docs() {
|
|
1294
|
+
case "$(pi_documentation_profile)" in
|
|
1295
|
+
full|full-docs|legacy-full)
|
|
1296
|
+
return 0
|
|
1297
|
+
;;
|
|
1298
|
+
*)
|
|
1299
|
+
return 1
|
|
1300
|
+
;;
|
|
1301
|
+
esac
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1304
|
+
pi_external_tooling_hosts_json() {
|
|
1305
|
+
pi_env_value "FORGE_EXTERNAL_TOOLING_HOSTS_JSON" "$PI_EXTERNAL_TOOLING_HOSTS_DEFAULT"
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1308
|
+
pi_external_tooling_gbrain_mcp() {
|
|
1309
|
+
pi_env_value "FORGE_EXTERNAL_TOOLING_GBRAIN_MCP" "candidate-disabled"
|
|
1310
|
+
}
|
|
1311
|
+
|
|
1312
|
+
pi_external_tooling_defaults_summary() {
|
|
1313
|
+
cat <<'EOF_EXTERNAL_TOOLING_DEFAULTS'
|
|
1314
|
+
- Policy defaults: routing complex->gstack, simple->waza, knowledge->gbrain
|
|
1315
|
+
- Hosts: claude-code, codex
|
|
1316
|
+
- Mode: agent-readiness-required
|
|
1317
|
+
- Detection: init-migrate
|
|
1318
|
+
- Waza: Codex-first, managed skills think/hunt/check/health, stage upstream in ~/.agents/skills, sync verified copies into ~/.codex/skills
|
|
1319
|
+
- Codex automation profile: required health/check/mermaid from ~/.codex/skills; do not vendor skill bodies
|
|
1320
|
+
- gbrain MCP: candidate-disabled
|
|
1321
|
+
- CodeGraph: required agent code-navigation readiness tool, target-aware MCP configure by explicit user command or authorized agent action, per-repo ignored .codegraph/ index; generated repos do not add it as a package dependency unless local policy opts in
|
|
1322
|
+
- Auto-actions: never install, upgrade, serve, sync, or enable MCP automatically
|
|
1323
|
+
EOF_EXTERNAL_TOOLING_DEFAULTS
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
pi_resolve_external_tooling_detector() {
|
|
1327
|
+
local repo_dir="$1"
|
|
1328
|
+
local fallback_script="${2:-}"
|
|
1329
|
+
local repo_detector="$repo_dir/.ai/harness/scripts/check-agent-tooling.sh"
|
|
1330
|
+
local legacy_repo_detector="$repo_dir/scripts/check-agent-tooling.sh"
|
|
1331
|
+
|
|
1332
|
+
if [[ -n "$fallback_script" && -f "$fallback_script" ]]; then
|
|
1333
|
+
printf '%s' "$fallback_script"
|
|
1334
|
+
return 0
|
|
1335
|
+
fi
|
|
1336
|
+
|
|
1337
|
+
if [[ -f "$repo_detector" ]]; then
|
|
1338
|
+
printf '%s' "$repo_detector"
|
|
1339
|
+
return 0
|
|
1340
|
+
fi
|
|
1341
|
+
|
|
1342
|
+
if [[ -f "$legacy_repo_detector" ]]; then
|
|
1343
|
+
printf '%s' "$legacy_repo_detector"
|
|
1344
|
+
return 0
|
|
1345
|
+
fi
|
|
1346
|
+
|
|
1347
|
+
return 1
|
|
1348
|
+
}
|
|
1349
|
+
|
|
1350
|
+
pi_print_external_tooling_report() {
|
|
1351
|
+
local repo_dir="$1"
|
|
1352
|
+
local mode="${2:-apply}"
|
|
1353
|
+
local fallback_script="${3:-}"
|
|
1354
|
+
local detector
|
|
1355
|
+
local output
|
|
1356
|
+
|
|
1357
|
+
echo "--- External Tooling ---"
|
|
1358
|
+
pi_external_tooling_defaults_summary
|
|
1359
|
+
|
|
1360
|
+
detector="$(pi_resolve_external_tooling_detector "$repo_dir" "$fallback_script" || true)"
|
|
1361
|
+
if [[ -z "$detector" ]]; then
|
|
1362
|
+
echo "- Advisory detector: unavailable"
|
|
1363
|
+
return 0
|
|
1364
|
+
fi
|
|
1365
|
+
|
|
1366
|
+
local detector_args=(--host both)
|
|
1367
|
+
local check_tooling_updates="${FORGE_CHECK_TOOLING_UPDATES:-${AGENTIC_DEV_CHECK_TOOLING_UPDATES:-0}}"
|
|
1368
|
+
if [[ "$check_tooling_updates" == "1" ]]; then
|
|
1369
|
+
detector_args+=(--check-updates)
|
|
1370
|
+
fi
|
|
1371
|
+
|
|
1372
|
+
if output="$(cd "$repo_dir" && bash "$detector" "${detector_args[@]}" 2>&1)"; then
|
|
1373
|
+
if [[ "$mode" == "apply" ]]; then
|
|
1374
|
+
echo "- Advisory report:"
|
|
1375
|
+
else
|
|
1376
|
+
echo "- Advisory report (dry-run snapshot):"
|
|
1377
|
+
fi
|
|
1378
|
+
printf '%s\n' "$output" | sed 's/^/ /'
|
|
1379
|
+
return 0
|
|
1380
|
+
fi
|
|
1381
|
+
|
|
1382
|
+
echo "- Advisory report: detector failed (non-fatal)"
|
|
1383
|
+
printf '%s\n' "$output" | sed 's/^/ /'
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1386
|
+
pi_reference_config_names() {
|
|
1387
|
+
local ref_assets_dir="$1"
|
|
1388
|
+
local name
|
|
1389
|
+
|
|
1390
|
+
if pi_should_generate_full_docs; then
|
|
1391
|
+
find "$ref_assets_dir" -maxdepth 1 -type f -name '*.md' \
|
|
1392
|
+
! -name 'AGENTS.md' \
|
|
1393
|
+
! -name 'CLAUDE.md' \
|
|
1394
|
+
-print 2>/dev/null | sort | while IFS= read -r ref_file; do
|
|
1395
|
+
basename "$ref_file"
|
|
1396
|
+
done
|
|
1397
|
+
return 0
|
|
1398
|
+
fi
|
|
1399
|
+
|
|
1400
|
+
for name in $PI_MINIMAL_REFERENCE_CONFIGS; do
|
|
1401
|
+
[[ -f "$ref_assets_dir/$name" ]] || continue
|
|
1402
|
+
printf '%s\n' "$name"
|
|
1403
|
+
done
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1406
|
+
pi_install_reference_configs() {
|
|
1407
|
+
local target_dir="$1"
|
|
1408
|
+
local ref_assets_dir="$2"
|
|
1409
|
+
local mode="${3:-apply}"
|
|
1410
|
+
local ref_dir="$target_dir/docs/reference-configs"
|
|
1411
|
+
local name
|
|
1412
|
+
local source_repo_target=0
|
|
1413
|
+
|
|
1414
|
+
if [[ "$mode" != "apply" ]]; then
|
|
1415
|
+
echo "[dry-run] install $(pi_documentation_profile) reference config stubs into $ref_dir"
|
|
1416
|
+
return 0
|
|
1417
|
+
fi
|
|
1418
|
+
|
|
1419
|
+
mkdir -p "$ref_dir"
|
|
1420
|
+
if [[ ! -d "$ref_assets_dir" ]]; then
|
|
1421
|
+
return 0
|
|
1422
|
+
fi
|
|
1423
|
+
|
|
1424
|
+
if [[ -d "$target_dir/assets/reference-configs" ]]; then
|
|
1425
|
+
local target_refs_abs refs_abs
|
|
1426
|
+
target_refs_abs="$(cd "$target_dir/assets/reference-configs" && pwd)"
|
|
1427
|
+
refs_abs="$(cd "$ref_assets_dir" && pwd)"
|
|
1428
|
+
if [[ "$target_refs_abs" == "$refs_abs" ]]; then
|
|
1429
|
+
source_repo_target=1
|
|
1430
|
+
fi
|
|
1431
|
+
fi
|
|
1432
|
+
|
|
1433
|
+
while IFS= read -r name; do
|
|
1434
|
+
[[ -n "$name" ]] || continue
|
|
1435
|
+
if [[ "$source_repo_target" -eq 1 ]]; then
|
|
1436
|
+
cp "$ref_assets_dir/$name" "$ref_dir/$name"
|
|
1437
|
+
continue
|
|
1438
|
+
fi
|
|
1439
|
+
|
|
1440
|
+
if pi_should_preserve_reference_config "$ref_dir/$name" "$ref_assets_dir/$name"; then
|
|
1441
|
+
echo "[forge] preserved user-authored reference config: docs/reference-configs/$name"
|
|
1442
|
+
continue
|
|
1443
|
+
fi
|
|
1444
|
+
|
|
1445
|
+
pi_write_reference_config_stub "$ref_dir/$name" "$name" "$ref_assets_dir"
|
|
1446
|
+
done < <(pi_reference_config_names "$ref_assets_dir")
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1449
|
+
pi_reference_config_doc_id() {
|
|
1450
|
+
local name="$1"
|
|
1451
|
+
printf '%s\n' "${name%.md}"
|
|
1452
|
+
}
|
|
1453
|
+
|
|
1454
|
+
pi_forge_version_for_refs() {
|
|
1455
|
+
local ref_assets_dir="$1"
|
|
1456
|
+
local root_dir
|
|
1457
|
+
root_dir="$(cd "$ref_assets_dir/../.." 2>/dev/null && pwd || true)"
|
|
1458
|
+
if [[ -z "$root_dir" ]]; then
|
|
1459
|
+
printf '%s\n' "unknown"
|
|
1460
|
+
return 0
|
|
1461
|
+
fi
|
|
1462
|
+
local version_file="$root_dir/assets/skill-version.json"
|
|
1463
|
+
|
|
1464
|
+
if [[ -f "$version_file" ]]; then
|
|
1465
|
+
sed -n 's/^[[:space:]]*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' "$version_file" | head -n 1
|
|
1466
|
+
return 0
|
|
1467
|
+
fi
|
|
1468
|
+
|
|
1469
|
+
printf '%s\n' "unknown"
|
|
1470
|
+
}
|
|
1471
|
+
|
|
1472
|
+
pi_should_preserve_reference_config() {
|
|
1473
|
+
local target_file="$1"
|
|
1474
|
+
local asset_file="$2"
|
|
1475
|
+
|
|
1476
|
+
[[ -f "$target_file" ]] || return 1
|
|
1477
|
+
if [[ -f "$asset_file" ]] && cmp -s "$target_file" "$asset_file"; then
|
|
1478
|
+
return 1
|
|
1479
|
+
fi
|
|
1480
|
+
if grep -Fq "$PI_REFERENCE_CONFIG_STUB_MARKER" "$target_file"; then
|
|
1481
|
+
return 1
|
|
1482
|
+
fi
|
|
1483
|
+
local target_heading asset_heading
|
|
1484
|
+
target_heading="$(pi_reference_config_first_heading "$target_file")"
|
|
1485
|
+
asset_heading="$(pi_reference_config_first_heading "$asset_file")"
|
|
1486
|
+
if [[ -n "$asset_heading" && "$target_heading" == "$asset_heading" ]]; then
|
|
1487
|
+
return 1
|
|
1488
|
+
fi
|
|
1489
|
+
|
|
1490
|
+
return 0
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1493
|
+
pi_reference_config_first_heading() {
|
|
1494
|
+
local file="$1"
|
|
1495
|
+
[[ -f "$file" ]] || return 0
|
|
1496
|
+
sed -n 's/^# //p' "$file" | head -n 1
|
|
1497
|
+
}
|
|
1498
|
+
|
|
1499
|
+
pi_write_reference_config_stub() {
|
|
1500
|
+
local output_file="$1"
|
|
1501
|
+
local name="$2"
|
|
1502
|
+
local ref_assets_dir="$3"
|
|
1503
|
+
local doc_id
|
|
1504
|
+
local version
|
|
1505
|
+
|
|
1506
|
+
doc_id="$(pi_reference_config_doc_id "$name")"
|
|
1507
|
+
version="$(pi_forge_version_for_refs "$ref_assets_dir")"
|
|
1508
|
+
|
|
1509
|
+
cat > "$output_file" <<EOF_REFERENCE_STUB
|
|
1510
|
+
$PI_REFERENCE_CONFIG_STUB_MARKER
|
|
1511
|
+
# forge Reference: $doc_id
|
|
1512
|
+
|
|
1513
|
+
> **Runtime Docs**: user-level forge reference
|
|
1514
|
+
> **Doc ID**: $doc_id
|
|
1515
|
+
> **Version**: $version
|
|
1516
|
+
> **Source Command**: \`forge docs path $doc_id\`
|
|
1517
|
+
|
|
1518
|
+
This repo keeps workflow facts and runtime artifacts locally under \`.ai/\`.
|
|
1519
|
+
The full generic runtime guide is supplied by the installed forge
|
|
1520
|
+
package/user-level runtime so each repository does not need to refresh a full
|
|
1521
|
+
copy of shared documentation.
|
|
1522
|
+
|
|
1523
|
+
Use:
|
|
1524
|
+
|
|
1525
|
+
\`\`\`bash
|
|
1526
|
+
forge docs path $doc_id
|
|
1527
|
+
forge docs show $doc_id
|
|
1528
|
+
\`\`\`
|
|
1529
|
+
EOF_REFERENCE_STUB
|
|
1530
|
+
}
|
|
1531
|
+
|
|
1532
|
+
pi_policy_reference_config_names() {
|
|
1533
|
+
if pi_should_generate_full_docs; then
|
|
1534
|
+
printf '%s\n' $PI_FULL_REFERENCE_CONFIGS
|
|
1535
|
+
return 0
|
|
1536
|
+
fi
|
|
1537
|
+
|
|
1538
|
+
printf '%s\n' $PI_MINIMAL_REFERENCE_CONFIGS
|
|
1539
|
+
}
|
|
1540
|
+
|
|
1541
|
+
pi_json_string_array_from_lines() {
|
|
1542
|
+
local first=1
|
|
1543
|
+
local item
|
|
1544
|
+
|
|
1545
|
+
while IFS= read -r item; do
|
|
1546
|
+
[[ -n "$item" ]] || continue
|
|
1547
|
+
if [[ "$first" -eq 0 ]]; then
|
|
1548
|
+
printf ', '
|
|
1549
|
+
fi
|
|
1550
|
+
first=0
|
|
1551
|
+
printf '"%s"' "$item"
|
|
1552
|
+
done
|
|
1553
|
+
}
|
|
1554
|
+
|
|
1555
|
+
pi_context_block_config_file() {
|
|
1556
|
+
local target_dir="$1"
|
|
1557
|
+
pi_env_value "FORGE_CONTEXT_BLOCKS_FILE" "$target_dir/.ai/context/agent-context-blocks.txt"
|
|
1558
|
+
}
|
|
1559
|
+
|
|
1560
|
+
pi_capability_registry_file() {
|
|
1561
|
+
local target_dir="$1"
|
|
1562
|
+
printf '%s' "$target_dir/.ai/context/capabilities.json"
|
|
1563
|
+
}
|
|
1564
|
+
|
|
1565
|
+
pi_safe_token() {
|
|
1566
|
+
local value="$1"
|
|
1567
|
+
value="$(printf '%s' "$value" | tr '[:upper:]' '[:lower:]')"
|
|
1568
|
+
value="$(printf '%s' "$value" | sed -E 's/[^a-z0-9]+/-/g; s/^-+//; s/-+$//; s/-{2,}/-/g')"
|
|
1569
|
+
printf '%s' "${value:-capability}"
|
|
1570
|
+
}
|
|
1571
|
+
|
|
1572
|
+
pi_legacy_context_block_candidates() {
|
|
1573
|
+
local target_dir="$1"
|
|
1574
|
+
local config_file
|
|
1575
|
+
|
|
1576
|
+
local env_blocks
|
|
1577
|
+
env_blocks="$(pi_env_value "FORGE_CONTEXT_BLOCKS")"
|
|
1578
|
+
if [[ -n "$env_blocks" ]]; then
|
|
1579
|
+
printf '%s\n' "$env_blocks" | tr ',:' '\n'
|
|
1580
|
+
return 0
|
|
1581
|
+
fi
|
|
1582
|
+
|
|
1583
|
+
config_file="$(pi_context_block_config_file "$target_dir")"
|
|
1584
|
+
if [[ -f "$config_file" ]]; then
|
|
1585
|
+
sed -e 's/#.*$//' -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' "$config_file" | sed '/^$/d'
|
|
1586
|
+
return 0
|
|
1587
|
+
fi
|
|
1588
|
+
|
|
1589
|
+
find "$target_dir" \
|
|
1590
|
+
\( \
|
|
1591
|
+
-name .git -o -name node_modules -o -name vendor -o -name .ai -o -name .claude \
|
|
1592
|
+
-o -name _ref -o -name _ops -o -name .worktrees -o -name .cache \
|
|
1593
|
+
-o -name .venv -o -name venv -o -name dist -o -name build -o -name coverage \
|
|
1594
|
+
-o -name .next -o -name .turbo -o -path '*/go/pkg/mod' -o -path '*/Library' \
|
|
1595
|
+
\) -prune -o \
|
|
1596
|
+
\( -type f \( -name 'CLAUDE.md' -o -name 'AGENTS.md' \) \) -print 2>/dev/null | while IFS= read -r context_file; do
|
|
1597
|
+
local context_dir
|
|
1598
|
+
local rel_dir
|
|
1599
|
+
context_dir="$(dirname "$context_file")"
|
|
1600
|
+
rel_dir="${context_dir#$target_dir/}"
|
|
1601
|
+
[[ "$rel_dir" == "$context_dir" || "$rel_dir" == "." ]] && continue
|
|
1602
|
+
printf '%s\n' "$rel_dir"
|
|
1603
|
+
done
|
|
1604
|
+
}
|
|
1605
|
+
|
|
1606
|
+
pi_context_block_candidates() {
|
|
1607
|
+
local target_dir="$1"
|
|
1608
|
+
local registry_file
|
|
1609
|
+
local selector
|
|
1610
|
+
|
|
1611
|
+
registry_file="$(pi_capability_registry_file "$target_dir")"
|
|
1612
|
+
if [[ -f "$registry_file" ]]; then
|
|
1613
|
+
if command -v bun >/dev/null 2>&1 && [[ -f "$target_dir/.ai/harness/scripts/capability-resolver.ts" ]]; then
|
|
1614
|
+
(cd "$target_dir" && bun .ai/harness/scripts/capability-resolver.ts list --format prefixes 2>/dev/null || true)
|
|
1615
|
+
return 0
|
|
1616
|
+
fi
|
|
1617
|
+
|
|
1618
|
+
if command -v node >/dev/null 2>&1; then
|
|
1619
|
+
node - "$registry_file" <<'JS_EOF'
|
|
1620
|
+
const fs = require("fs");
|
|
1621
|
+
const registry = JSON.parse(fs.readFileSync(process.argv[2], "utf8"));
|
|
1622
|
+
for (const capability of registry.capabilities || []) {
|
|
1623
|
+
for (const prefix of capability.prefixes || []) console.log(prefix);
|
|
1624
|
+
}
|
|
1625
|
+
JS_EOF
|
|
1626
|
+
return 0
|
|
1627
|
+
fi
|
|
1628
|
+
fi
|
|
1629
|
+
|
|
1630
|
+
selector="$(pi_env_value "FORGE_CONTEXT_BLOCK_SELECTOR")"
|
|
1631
|
+
if [[ -n "$selector" && -x "$selector" ]]; then
|
|
1632
|
+
(cd "$target_dir" && "$selector" "$target_dir")
|
|
1633
|
+
return 0
|
|
1634
|
+
fi
|
|
1635
|
+
|
|
1636
|
+
pi_legacy_context_block_candidates "$target_dir"
|
|
1637
|
+
}
|
|
1638
|
+
|
|
1639
|
+
pi_legacy_context_block_dirs() {
|
|
1640
|
+
local target_dir="$1"
|
|
1641
|
+
local raw_path
|
|
1642
|
+
local rel_path
|
|
1643
|
+
|
|
1644
|
+
pi_legacy_context_block_candidates "$target_dir" | while IFS= read -r raw_path; do
|
|
1645
|
+
rel_path="$(printf '%s' "$raw_path" | sed -e 's/#.*$//' -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
|
|
1646
|
+
rel_path="${rel_path#./}"
|
|
1647
|
+
rel_path="${rel_path%/}"
|
|
1648
|
+
[[ -z "$rel_path" || "$rel_path" == "." ]] && continue
|
|
1649
|
+
case "$rel_path" in
|
|
1650
|
+
/*|../*|*/../*|*\"*)
|
|
1651
|
+
continue
|
|
1652
|
+
;;
|
|
1653
|
+
esac
|
|
1654
|
+
[[ -d "$target_dir/$rel_path" ]] || continue
|
|
1655
|
+
printf '%s\n' "$rel_path"
|
|
1656
|
+
done | sort -u
|
|
1657
|
+
}
|
|
1658
|
+
|
|
1659
|
+
pi_context_block_dirs() {
|
|
1660
|
+
local target_dir="$1"
|
|
1661
|
+
local raw_path
|
|
1662
|
+
local rel_path
|
|
1663
|
+
|
|
1664
|
+
pi_context_block_candidates "$target_dir" | while IFS= read -r raw_path; do
|
|
1665
|
+
rel_path="$(printf '%s' "$raw_path" | sed -e 's/#.*$//' -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
|
|
1666
|
+
rel_path="${rel_path#./}"
|
|
1667
|
+
rel_path="${rel_path%/}"
|
|
1668
|
+
[[ -z "$rel_path" || "$rel_path" == "." ]] && continue
|
|
1669
|
+
case "$rel_path" in
|
|
1670
|
+
/*|../*|*/../*|*\"*)
|
|
1671
|
+
continue
|
|
1672
|
+
;;
|
|
1673
|
+
esac
|
|
1674
|
+
[[ -d "$target_dir/$rel_path" ]] || continue
|
|
1675
|
+
printf '%s\n' "$rel_path"
|
|
1676
|
+
done | sort -u
|
|
1677
|
+
}
|
|
1678
|
+
|
|
1679
|
+
pi_write_capability_registry() {
|
|
1680
|
+
local target_dir="$1"
|
|
1681
|
+
local mode="${2:-apply}"
|
|
1682
|
+
local output_file
|
|
1683
|
+
local rel_dir
|
|
1684
|
+
local first=1
|
|
1685
|
+
|
|
1686
|
+
output_file="$(pi_capability_registry_file "$target_dir")"
|
|
1687
|
+
|
|
1688
|
+
if [[ "$mode" != "apply" ]]; then
|
|
1689
|
+
echo "[dry-run] write $output_file"
|
|
1690
|
+
return 0
|
|
1691
|
+
fi
|
|
1692
|
+
|
|
1693
|
+
if [[ -f "$output_file" ]]; then
|
|
1694
|
+
return 0
|
|
1695
|
+
fi
|
|
1696
|
+
|
|
1697
|
+
mkdir -p "$(dirname "$output_file")"
|
|
1698
|
+
{
|
|
1699
|
+
printf '{\n "version": 1,\n "capabilities": [\n'
|
|
1700
|
+
while IFS= read -r rel_dir; do
|
|
1701
|
+
[[ -n "$rel_dir" ]] || continue
|
|
1702
|
+
local domain
|
|
1703
|
+
local name
|
|
1704
|
+
local id
|
|
1705
|
+
local parts_count
|
|
1706
|
+
local last_part
|
|
1707
|
+
|
|
1708
|
+
parts_count="$(awk -F'/' '{print NF}' <<< "$rel_dir")"
|
|
1709
|
+
last_part="${rel_dir##*/}"
|
|
1710
|
+
if [[ "$parts_count" -ge 2 ]]; then
|
|
1711
|
+
domain="$(pi_safe_token "$(cut -d/ -f1-2 <<< "$rel_dir" | tr '/' '-')")"
|
|
1712
|
+
else
|
|
1713
|
+
domain="$(pi_safe_token "$rel_dir")"
|
|
1714
|
+
fi
|
|
1715
|
+
if [[ "$parts_count" -gt 2 ]]; then
|
|
1716
|
+
name="$(pi_safe_token "$last_part")"
|
|
1717
|
+
id="${domain}-${name}"
|
|
1718
|
+
else
|
|
1719
|
+
name="$(pi_safe_token "$last_part")"
|
|
1720
|
+
id="$domain"
|
|
1721
|
+
fi
|
|
1722
|
+
|
|
1723
|
+
if [[ "$first" -eq 0 ]]; then
|
|
1724
|
+
printf ',\n'
|
|
1725
|
+
fi
|
|
1726
|
+
first=0
|
|
1727
|
+
cat <<EOF_CAPABILITY
|
|
1728
|
+
{
|
|
1729
|
+
"id": "$id",
|
|
1730
|
+
"domain": "$domain",
|
|
1731
|
+
"name": "$name",
|
|
1732
|
+
"prefixes": ["$rel_dir"],
|
|
1733
|
+
"contract_files": {
|
|
1734
|
+
"agents": "$rel_dir/AGENTS.md",
|
|
1735
|
+
"claude": "$rel_dir/CLAUDE.md"
|
|
1736
|
+
},
|
|
1737
|
+
"architecture_module": "docs/architecture/modules/$domain/$name.md",
|
|
1738
|
+
"workstream_dir": "tasks/workstreams/$domain/$name",
|
|
1739
|
+
"lsp_profile": "$(pi_lsp_profile)",
|
|
1740
|
+
"verification_hints": ["record local commands here before implementation"]
|
|
1741
|
+
}
|
|
1742
|
+
EOF_CAPABILITY
|
|
1743
|
+
done < <(pi_legacy_context_block_dirs "$target_dir")
|
|
1744
|
+
printf '\n ]\n}\n'
|
|
1745
|
+
} > "$output_file"
|
|
1746
|
+
}
|
|
1747
|
+
|
|
1748
|
+
pi_should_generate_directory_context() {
|
|
1749
|
+
local target_dir="$1"
|
|
1750
|
+
[[ -n "$(pi_context_block_dirs "$target_dir" | head -n 1)" ]]
|
|
1751
|
+
}
|
|
1752
|
+
|
|
1753
|
+
pi_context_map_discoverable_entries() {
|
|
1754
|
+
local target_dir="$1"
|
|
1755
|
+
local first_entry=1
|
|
1756
|
+
local rel_dir
|
|
1757
|
+
local file_name
|
|
1758
|
+
local target_agent
|
|
1759
|
+
local registry_file
|
|
1760
|
+
local capability_entries
|
|
1761
|
+
|
|
1762
|
+
registry_file="$(pi_capability_registry_file "$target_dir")"
|
|
1763
|
+
if [[ -f "$registry_file" ]] && command -v node >/dev/null 2>&1; then
|
|
1764
|
+
capability_entries="$(node - "$registry_file" <<'JS_EOF'
|
|
1765
|
+
const fs = require("fs");
|
|
1766
|
+
const registry = JSON.parse(fs.readFileSync(process.argv[2], "utf8"));
|
|
1767
|
+
const entries = [];
|
|
1768
|
+
for (const capability of registry.capabilities || []) {
|
|
1769
|
+
const prefix = (capability.prefixes || [])[0];
|
|
1770
|
+
if (!prefix || !capability.contract_files) continue;
|
|
1771
|
+
for (const [fileName, targetAgent] of [["CLAUDE.md", "claude"], ["AGENTS.md", "codex"]]) {
|
|
1772
|
+
const path = fileName === "CLAUDE.md" ? capability.contract_files.claude : capability.contract_files.agents;
|
|
1773
|
+
entries.push({
|
|
1774
|
+
path,
|
|
1775
|
+
priority: "high",
|
|
1776
|
+
char_budget: 1000,
|
|
1777
|
+
purpose: "capability-contract",
|
|
1778
|
+
capability_id: capability.id,
|
|
1779
|
+
functional_block: prefix,
|
|
1780
|
+
matched_prefix: prefix,
|
|
1781
|
+
architecture_domain: capability.domain,
|
|
1782
|
+
architecture_capability: capability.name,
|
|
1783
|
+
target_agent: targetAgent,
|
|
1784
|
+
lsp_profile: capability.lsp_profile || "typescript-lsp",
|
|
1785
|
+
doc_scope: "capability-contract",
|
|
1786
|
+
verification_hint: (capability.verification_hints || [])[0] || "record local commands here before implementation"
|
|
1787
|
+
});
|
|
1788
|
+
}
|
|
1789
|
+
}
|
|
1790
|
+
process.stdout.write(entries.map((entry) => JSON.stringify(entry, null, 6).replace(/^/gm, " ")).join(",\n"));
|
|
1791
|
+
JS_EOF
|
|
1792
|
+
)"
|
|
1793
|
+
if [[ -n "$capability_entries" ]]; then
|
|
1794
|
+
printf '%s,\n' "$capability_entries"
|
|
1795
|
+
fi
|
|
1796
|
+
cat <<'EOF_CONTEXT_ENTRY'
|
|
1797
|
+
{
|
|
1798
|
+
"path": "docs/reference-configs/*.md",
|
|
1799
|
+
"priority": "low",
|
|
1800
|
+
"char_budget": 900,
|
|
1801
|
+
"purpose": "deep-doc"
|
|
1802
|
+
},
|
|
1803
|
+
{
|
|
1804
|
+
"path": "tasks/workstreams/**/*.md",
|
|
1805
|
+
"priority": "high",
|
|
1806
|
+
"char_budget": 1200,
|
|
1807
|
+
"purpose": "capability-workstream"
|
|
1808
|
+
}
|
|
1809
|
+
EOF_CONTEXT_ENTRY
|
|
1810
|
+
return 0
|
|
1811
|
+
fi
|
|
1812
|
+
|
|
1813
|
+
while IFS= read -r rel_dir; do
|
|
1814
|
+
[[ -n "$rel_dir" ]] || continue
|
|
1815
|
+
for file_name in CLAUDE.md AGENTS.md; do
|
|
1816
|
+
if [[ "$first_entry" -eq 0 ]]; then
|
|
1817
|
+
printf ',\n'
|
|
1818
|
+
fi
|
|
1819
|
+
first_entry=0
|
|
1820
|
+
target_agent="codex"
|
|
1821
|
+
[[ "$file_name" == "CLAUDE.md" ]] && target_agent="claude"
|
|
1822
|
+
cat <<EOF_CONTEXT_ENTRY
|
|
1823
|
+
{
|
|
1824
|
+
"path": "$rel_dir/$file_name",
|
|
1825
|
+
"priority": "high",
|
|
1826
|
+
"char_budget": 1000,
|
|
1827
|
+
"purpose": "capability-contract",
|
|
1828
|
+
"functional_block": "$rel_dir",
|
|
1829
|
+
"target_agent": "$target_agent",
|
|
1830
|
+
"lsp_profile": "$(pi_lsp_profile)",
|
|
1831
|
+
"doc_scope": "capability-contract",
|
|
1832
|
+
"verification_hint": "record local commands here before implementation"
|
|
1833
|
+
}
|
|
1834
|
+
EOF_CONTEXT_ENTRY
|
|
1835
|
+
done
|
|
1836
|
+
done < <(pi_context_block_dirs "$target_dir")
|
|
1837
|
+
|
|
1838
|
+
if [[ "$first_entry" -eq 0 ]]; then
|
|
1839
|
+
printf ',\n'
|
|
1840
|
+
fi
|
|
1841
|
+
|
|
1842
|
+
cat <<'EOF_CONTEXT_ENTRY'
|
|
1843
|
+
{
|
|
1844
|
+
"path": "docs/reference-configs/*.md",
|
|
1845
|
+
"priority": "low",
|
|
1846
|
+
"char_budget": 900,
|
|
1847
|
+
"purpose": "deep-doc"
|
|
1848
|
+
},
|
|
1849
|
+
{
|
|
1850
|
+
"path": "tasks/workstreams/**/*.md",
|
|
1851
|
+
"priority": "high",
|
|
1852
|
+
"char_budget": 1200,
|
|
1853
|
+
"purpose": "capability-workstream"
|
|
1854
|
+
}
|
|
1855
|
+
EOF_CONTEXT_ENTRY
|
|
1856
|
+
}
|
|
1857
|
+
|
|
1858
|
+
pi_write_harness_policy() {
|
|
1859
|
+
local target_dir="$1"
|
|
1860
|
+
local mode="${2:-apply}"
|
|
1861
|
+
local output_file="$target_dir/.ai/harness/policy.json"
|
|
1862
|
+
local default_file
|
|
1863
|
+
local merged_file
|
|
1864
|
+
|
|
1865
|
+
if [[ "$mode" != "apply" ]]; then
|
|
1866
|
+
echo "[dry-run] write $output_file"
|
|
1867
|
+
return 0
|
|
1868
|
+
fi
|
|
1869
|
+
|
|
1870
|
+
mkdir -p "$(dirname "$output_file")"
|
|
1871
|
+
default_file="$(mktemp)"
|
|
1872
|
+
merged_file="$(mktemp)"
|
|
1873
|
+
cat > "$default_file" <<EOF_POLICY
|
|
1874
|
+
{
|
|
1875
|
+
"version": 1,
|
|
1876
|
+
"active_plan": {
|
|
1877
|
+
"marker_file": ".ai/harness/active-plan",
|
|
1878
|
+
"legacy_marker_file": ".claude/.active-plan",
|
|
1879
|
+
"directory": "plans",
|
|
1880
|
+
"archive_directory": "plans/archive",
|
|
1881
|
+
"glob": "plan-*.md",
|
|
1882
|
+
"active_worktree_marker_file": ".ai/harness/active-worktree",
|
|
1883
|
+
"source_of_truth": "per-worktree explicit marker with active-worktree owner; legacy Claude marker fallback only"
|
|
1884
|
+
},
|
|
1885
|
+
"tasks": {
|
|
1886
|
+
"todo_file": "tasks/todos.md",
|
|
1887
|
+
"current_status_file": "tasks/current.md",
|
|
1888
|
+
"lessons_file": "tasks/lessons.md",
|
|
1889
|
+
"research_dir": "docs/researches",
|
|
1890
|
+
"workstreams_dir": "tasks/workstreams",
|
|
1891
|
+
"contracts_dir": "tasks/contracts",
|
|
1892
|
+
"reviews_dir": "tasks/reviews",
|
|
1893
|
+
"notes_dir": "tasks/notes"
|
|
1894
|
+
},
|
|
1895
|
+
"prds": {
|
|
1896
|
+
"dir": "plans/prds",
|
|
1897
|
+
"template_file": ".claude/templates/prd.template.md",
|
|
1898
|
+
"statuses": ["Draft", "Approved", "Superseded"],
|
|
1899
|
+
"rule": "PRDs live in plans/prds as the upper planning layer. They decompose docs/spec.md intent into product direction, acceptance scenarios, module behavior, data model, performance targets, and developer handoff. Sprints reference PRDs through Source PRD and decompose them into ordered execution backlogs."
|
|
1900
|
+
},
|
|
1901
|
+
"sprints": {
|
|
1902
|
+
"dir": "plans/sprints",
|
|
1903
|
+
"active_marker_file": ".ai/harness/sprint/active-sprint",
|
|
1904
|
+
"template_file": ".claude/templates/sprint.template.md",
|
|
1905
|
+
"helper_script": "scripts/sprint-backlog.sh",
|
|
1906
|
+
"statuses": ["Draft", "Approved", "Executing", "Done", "Archived"],
|
|
1907
|
+
"rule": "PRDs live in plans/prds as the upper planning layer. Sprints live in plans/sprints as long-task execution backlogs; each sprint row is expanded with Waza \$think into a detailed plans/plan-*.md before the plan -> contract -> worktree flow; tasks/todos.md stays the deferred-goal ledger"
|
|
1908
|
+
},
|
|
1909
|
+
"reference_material": {
|
|
1910
|
+
"dir": "_ref",
|
|
1911
|
+
"mode": "external-ignored",
|
|
1912
|
+
"commit_policy": "never commit _ref contents",
|
|
1913
|
+
"rule": "use _ref as an occasional ignored external reference checkout cache for upstream/source comparison only; refresh from external sources instead of editing as product code; when it influences a decision, cite the source repo plus commit/tag and path in tasks/notes/ or docs/researches/"
|
|
1914
|
+
},
|
|
1915
|
+
"operations": {
|
|
1916
|
+
"dir": "deploy",
|
|
1917
|
+
"private_dir": "_ops",
|
|
1918
|
+
"tracked": ["deploy/README.md", "deploy/scripts/", "deploy/submissions/", "deploy/runbooks/", "deploy/release-checklists/", "deploy/sql/", "deploy/*.md", "deploy/env/.env.example"],
|
|
1919
|
+
"ignored": ["_ops/"],
|
|
1920
|
+
"rule": "commit deployment runbooks, submission materials, release checklists, helper scripts, ordered SQL files, and env examples under deploy/; keep deploy SQL in deploy/sql/ with 4-digit ascending prefixes; keep keys, tokens, real env values, provider state, artifacts, logs, and scratch files in ignored _ops/ only"
|
|
1921
|
+
},
|
|
1922
|
+
"context": {
|
|
1923
|
+
"profile": "$(pi_context_profile)",
|
|
1924
|
+
"map_file": ".ai/context/context-map.json",
|
|
1925
|
+
"capability_registry_file": ".ai/context/capabilities.json",
|
|
1926
|
+
"capability_resolver": "scripts/capability-resolver.ts",
|
|
1927
|
+
"capability_config": "scripts/capability-config.ts",
|
|
1928
|
+
"capability_match_rule": "longest-prefix; same-length ambiguity fails",
|
|
1929
|
+
"functional_block_selector": {
|
|
1930
|
+
"script": "scripts/select-agent-context-blocks.sh",
|
|
1931
|
+
"config_file": ".ai/context/agent-context-blocks.txt",
|
|
1932
|
+
"env": "FORGE_CONTEXT_BLOCKS",
|
|
1933
|
+
"rule": "compatibility selector; capability registry is the source of truth"
|
|
1934
|
+
}
|
|
1935
|
+
},
|
|
1936
|
+
"harness": {
|
|
1937
|
+
"policy_file": ".ai/harness/policy.json",
|
|
1938
|
+
"checks_file": ".ai/harness/checks/latest.json",
|
|
1939
|
+
"handoff_file": ".ai/harness/handoff/current.md",
|
|
1940
|
+
"failure_log_file": ".ai/harness/failures/latest.jsonl",
|
|
1941
|
+
"events_file": ".ai/harness/events.jsonl",
|
|
1942
|
+
"architecture_events_file": ".ai/harness/architecture/events.jsonl",
|
|
1943
|
+
"runs_dir": ".ai/harness/runs",
|
|
1944
|
+
"helper_runtime_dir": ".ai/harness/scripts",
|
|
1945
|
+
"helper_compat_dir": "scripts",
|
|
1946
|
+
"helper_source": "package",
|
|
1947
|
+
"helper_package_dir": "assets/templates/helpers"
|
|
1948
|
+
},
|
|
1949
|
+
"architecture": {
|
|
1950
|
+
"index_file": "docs/architecture/index.md",
|
|
1951
|
+
"requests_dir": "docs/architecture/requests",
|
|
1952
|
+
"snapshots_dir": "docs/architecture/snapshots",
|
|
1953
|
+
"diagrams_dir": "docs/architecture/diagrams",
|
|
1954
|
+
"domains_dir": "docs/architecture/domains",
|
|
1955
|
+
"modules_dir": "docs/architecture/modules",
|
|
1956
|
+
"diagram_skill": "mermaid",
|
|
1957
|
+
"diagram_skill_source": "~/.codex/skills/mermaid",
|
|
1958
|
+
"vendoring_policy": "do-not-vendor-diagram-skill-assets",
|
|
1959
|
+
"freshness_gate": "advisory",
|
|
1960
|
+
"gate_min_severity": "medium",
|
|
1961
|
+
"pending_card_scope": "capability",
|
|
1962
|
+
"pending_block_begin": "<!-- BEGIN ARCHITECTURE PENDING REQUESTS -->",
|
|
1963
|
+
"pending_block_end": "<!-- END ARCHITECTURE PENDING REQUESTS -->",
|
|
1964
|
+
"queue_script": ".ai/harness/scripts/architecture-queue.sh",
|
|
1965
|
+
"contract_block_begin": "<!-- BEGIN ARCHITECTURE CONTRACT -->",
|
|
1966
|
+
"contract_block_end": "<!-- END ARCHITECTURE CONTRACT -->",
|
|
1967
|
+
"rule": "hooks record architecture queue cards and sync controlled local context blocks; agents author semantic snapshots and diagrams"
|
|
1968
|
+
},
|
|
1969
|
+
"workstreams": {
|
|
1970
|
+
"dir": "tasks/workstreams",
|
|
1971
|
+
"scope": "capability",
|
|
1972
|
+
"projection": "local-contract-active-pointer-and-current-slice",
|
|
1973
|
+
"todo_projection": "tasks/todos.md",
|
|
1974
|
+
"rule": "durable multi-session progress lives under tasks/workstreams/<domain>/<capability>; current plan execution lives in the plan Task Breakdown; tasks/todos.md records deferred goals only"
|
|
1975
|
+
},
|
|
1976
|
+
"information_lifecycle": {
|
|
1977
|
+
"notes": {
|
|
1978
|
+
"dir": "tasks/notes",
|
|
1979
|
+
"purpose": "task-local implementation decisions, deviations, tradeoffs, and open questions",
|
|
1980
|
+
"promotion": "archive on workflow close; promote only repeated or durable findings"
|
|
1981
|
+
},
|
|
1982
|
+
"evidence": {
|
|
1983
|
+
"latest": ".ai/harness/checks/latest.json",
|
|
1984
|
+
"snapshots_dir": ".ai/harness/runs",
|
|
1985
|
+
"purpose": "raw verification records used to audit notes, reviews, and future promotion"
|
|
1986
|
+
},
|
|
1987
|
+
"assets": {
|
|
1988
|
+
"sources": [".ai/harness/policy.json", ".ai/harness/workflow-contract.json", ".ai/hooks/", "scripts/", "docs/reference-configs/"],
|
|
1989
|
+
"promotion_rule": "only promote patterns after verified reuse across tasks or fixtures"
|
|
1990
|
+
},
|
|
1991
|
+
"memory": {
|
|
1992
|
+
"sources": ["docs/researches/", "tasks/lessons.md", "gbrain"],
|
|
1993
|
+
"rule": "memory is advisory; current repo state and evidence override summaries"
|
|
1994
|
+
},
|
|
1995
|
+
"external_knowledge": {
|
|
1996
|
+
"default_brain_path": "brain/<project>/*",
|
|
1997
|
+
"project_path": "brain/<project>/*",
|
|
1998
|
+
"manifest_file": ".ai/harness/brain-manifest.json",
|
|
1999
|
+
"drift_check": "scripts/check-brain-manifest.sh",
|
|
2000
|
+
"sync_script": "scripts/sync-brain-docs.sh",
|
|
2001
|
+
"hook_trigger": "PostToolUse Edit|Write for manifest entries with sync.direction=repo-to-brain",
|
|
2002
|
+
"rule": "external knowledge stores long-lived explanations, runbooks, and patterns only; repo-local contracts, hooks, scripts, checks, and evidence remain authoritative",
|
|
2003
|
+
"sync_rule": "only explicitly opted-in repo-to-brain manifest entries may be written to the default brain vault; pointer-only externalized stubs remain check-only"
|
|
2004
|
+
}
|
|
2005
|
+
},
|
|
2006
|
+
"handoff_resume": {
|
|
2007
|
+
"resume_packet_file": ".ai/harness/handoff/resume.md",
|
|
2008
|
+
"global_handoff_dir": "~/.codex/handoffs",
|
|
2009
|
+
"auto_start_new_session": false
|
|
2010
|
+
},
|
|
2011
|
+
"plan_capture": {
|
|
2012
|
+
"script": "scripts/capture-plan.sh",
|
|
2013
|
+
"sources": ["codex-plan-mode", "waza-think", "forge-plan", "forge-sprint"],
|
|
2014
|
+
"rule": "Codex Plan mode and Waza think planning should capture decision-complete plans into plans/plan-*.md; implementation approval then projects the active approved plan through scripts/plan-to-todo.sh; sprint backlog rows are long-task waypoints and should be expanded with \$think before capture/execution"
|
|
2015
|
+
},
|
|
2016
|
+
"planning": {
|
|
2017
|
+
"pending_orchestration_file": ".ai/harness/planning/pending.json",
|
|
2018
|
+
"source_of_truth": "transient host planning bridge only; plans/ and .ai/harness/active-plan remain authoritative"
|
|
2019
|
+
},
|
|
2020
|
+
"guards": {
|
|
2021
|
+
"edit_plan_gate": "advice",
|
|
2022
|
+
"edit_plan_gate_modes": ["enforce", "advice", "off"],
|
|
2023
|
+
"rule": "pre-edit-guard advises when implementation lacks an active plan; execution remains available unless a real safety boundary blocks it"
|
|
2024
|
+
},
|
|
2025
|
+
"sidecar_research": {
|
|
2026
|
+
"default": true,
|
|
2027
|
+
"output_dir": "docs/researches",
|
|
2028
|
+
"preferred_runners": ["subagent", "codex exec --json", "main-thread trace"],
|
|
2029
|
+
"spawn_decision": "main agent decides from task breadth, context impact, raw-log volume, and callable runner availability; do not ask the user for spawn confirmation",
|
|
2030
|
+
"fallback_runner": "main-thread trace",
|
|
2031
|
+
"main_thread_policy": "if spawning is not worthwhile or no sidecar runner is callable, perform bounded research in the main thread; consume conclusions and evidence paths, not raw logs"
|
|
2032
|
+
},
|
|
2033
|
+
"documentation": {
|
|
2034
|
+
"profile": "$(pi_documentation_profile)",
|
|
2035
|
+
"reference_source": "user-level-runtime-docs",
|
|
2036
|
+
"reference_stub_marker": "$PI_REFERENCE_CONFIG_STUB_MARKER",
|
|
2037
|
+
"reference_resolver": "forge docs path <doc-id>",
|
|
2038
|
+
"required": ["docs/spec.md", "docs/architecture/index.md"],
|
|
2039
|
+
"on_demand": ["docs/brief.md", "docs/tech-stack.md", "docs/decisions.md", "docs/architecture.md", "docs/packages.md"],
|
|
2040
|
+
"reference_configs": [$(pi_policy_reference_config_names | pi_json_string_array_from_lines)],
|
|
2041
|
+
"rule": "create optional docs only when the agent has concrete repo evidence or the user asks; docs/reference-configs contains repo-local pointer stubs while full generic runtime docs live in the user-level/package forge install"
|
|
2042
|
+
},
|
|
2043
|
+
"lsp_profiles": {
|
|
2044
|
+
"default": "$(pi_lsp_profile)",
|
|
2045
|
+
"selection": "functional-block-first",
|
|
2046
|
+
"rule": "use block-level LSP/tooling hints before broad repo assumptions"
|
|
2047
|
+
},
|
|
2048
|
+
"worktree_strategy": {
|
|
2049
|
+
"auto_on_conflict": true,
|
|
2050
|
+
"auto_for_contract_tasks": true,
|
|
2051
|
+
"branch_prefix": "codex/",
|
|
2052
|
+
"base_branch": "main",
|
|
2053
|
+
"worktree_dir_template": "../{{repo}}-wt-{{slug}}",
|
|
2054
|
+
"start_script": "scripts/contract-worktree.sh start --plan <plan-file>",
|
|
2055
|
+
"finish_script": "scripts/contract-worktree.sh finish",
|
|
2056
|
+
"cleanup_script": "scripts/contract-worktree.sh cleanup --slug <slug>",
|
|
2057
|
+
"conflict_signals": [
|
|
2058
|
+
"dirty_worktree_overlaps_task_files",
|
|
2059
|
+
"current_branch_not_suitable_for_task",
|
|
2060
|
+
"existing_changes_unrelated_but_would_block_review",
|
|
2061
|
+
"task_requires_clean_validation_surface"
|
|
2062
|
+
],
|
|
2063
|
+
"validation_route": "waza:check",
|
|
2064
|
+
"merge_back": {
|
|
2065
|
+
"target": "main",
|
|
2066
|
+
"requires_clean_check": true,
|
|
2067
|
+
"preserve_unrelated_changes": true
|
|
2068
|
+
}
|
|
2069
|
+
},
|
|
2070
|
+
"upgrade": {
|
|
2071
|
+
"strategy_version": 1,
|
|
2072
|
+
"supported_legacy_versions": ["pre-tasks-first", "tasks-first-without-contract-manifest", "current-v1"],
|
|
2073
|
+
"action_classes": {
|
|
2074
|
+
"preserve": "keep user-authored hooks, ignored reference material, private operations state, secrets, and local env files unchanged",
|
|
2075
|
+
"archive": "move user-authored legacy workflow documents or checklists into archive/research surfaces before refresh",
|
|
2076
|
+
"reconfigure": "merge managed config defaults without overwriting explicit repo overrides",
|
|
2077
|
+
"remove": "delete only workflow-contract actions marked ownership=known_generated"
|
|
2078
|
+
},
|
|
2079
|
+
"cleanup": {
|
|
2080
|
+
"source": ".ai/harness/workflow-contract.json#migrations.upgrade.actions",
|
|
2081
|
+
"remove_only_ownership": "known_generated",
|
|
2082
|
+
"unknown_files": "preserve-or-archive",
|
|
2083
|
+
"custom_hooks": "preserve",
|
|
2084
|
+
"ignored_reference_material": "preserve",
|
|
2085
|
+
"local_operations_state": "preserve",
|
|
2086
|
+
"local_secrets": "preserve"
|
|
2087
|
+
},
|
|
2088
|
+
"reporting": {
|
|
2089
|
+
"inspector_field": "upgrade_plan",
|
|
2090
|
+
"dry_run_required": true
|
|
2091
|
+
}
|
|
2092
|
+
},
|
|
2093
|
+
"profiles": {
|
|
2094
|
+
"orchestration": "$(pi_orchestration_profile)",
|
|
2095
|
+
"evaluation": "$(pi_evaluation_profile)",
|
|
2096
|
+
"handoff": "$(pi_handoff_profile)",
|
|
2097
|
+
"recovery": "$(pi_recovery_profile)",
|
|
2098
|
+
"state": "$(pi_state_profile)"
|
|
2099
|
+
},
|
|
2100
|
+
"external_tooling": {
|
|
2101
|
+
"routing": {
|
|
2102
|
+
"complex": "gstack",
|
|
2103
|
+
"simple": "waza",
|
|
2104
|
+
"knowledge": "gbrain"
|
|
2105
|
+
},
|
|
2106
|
+
"hosts": $(pi_external_tooling_hosts_json),
|
|
2107
|
+
"mode": "agent-readiness-required",
|
|
2108
|
+
"detection": "init-migrate",
|
|
2109
|
+
"readiness_gate": "forge run check-agent-tooling --host codex --strict-readiness",
|
|
2110
|
+
"waza": {
|
|
2111
|
+
"source_repo": "tw93/Waza",
|
|
2112
|
+
"source_url": "https://github.com/tw93/Waza.git",
|
|
2113
|
+
"managed_skills": ["think", "hunt", "check", "health"],
|
|
2114
|
+
"primary_host": "codex",
|
|
2115
|
+
"codex_primary_path": "~/.codex/skills",
|
|
2116
|
+
"staging_cache_path": "~/.agents/skills",
|
|
2117
|
+
"sync_mode": "stage-upstream-then-copy-to-codex",
|
|
2118
|
+
"host_drift_policy": "report-per-host-version-staging-and-upstream-drift"
|
|
2119
|
+
},
|
|
2120
|
+
"codex_automation_profile": {
|
|
2121
|
+
"required_skills": ["health", "check", "mermaid"],
|
|
2122
|
+
"optional_skills": [],
|
|
2123
|
+
"mode": "codex-runtime-reference",
|
|
2124
|
+
"source": "~/.codex/skills",
|
|
2125
|
+
"routes": {
|
|
2126
|
+
"workflow_health": "waza:health",
|
|
2127
|
+
"review_gate": "waza:check",
|
|
2128
|
+
"architecture_diagram": "mermaid"
|
|
2129
|
+
},
|
|
2130
|
+
"vendoring_policy": "do-not-vendor-skill-body"
|
|
2131
|
+
},
|
|
2132
|
+
"diagram_design": {
|
|
2133
|
+
"skill_name": "mermaid",
|
|
2134
|
+
"primary_host": "codex",
|
|
2135
|
+
"codex_primary_path": "~/.codex/skills/mermaid",
|
|
2136
|
+
"sync_mode": "external-installed-skill",
|
|
2137
|
+
"vendoring_policy": "do-not-vendor"
|
|
2138
|
+
},
|
|
2139
|
+
"gbrain": {
|
|
2140
|
+
"mcp": "$(pi_external_tooling_gbrain_mcp)"
|
|
2141
|
+
},
|
|
2142
|
+
"codegraph": {
|
|
2143
|
+
"package": "@colbymchenry/codegraph",
|
|
2144
|
+
"primary_host": "both",
|
|
2145
|
+
"install_mode": "target-aware-mcp",
|
|
2146
|
+
"codex_config_path": "~/.codex/config.toml",
|
|
2147
|
+
"claude_config_path": "~/.claude.json",
|
|
2148
|
+
"index_dir": ".codegraph",
|
|
2149
|
+
"readiness": "required-for-agent-code-navigation",
|
|
2150
|
+
"hook_policy": "do-not-block-hooks",
|
|
2151
|
+
"install_command": "bun add -g @colbymchenry/codegraph && forge tools configure codegraph --target codex --location global",
|
|
2152
|
+
"project_init_command": "codegraph init -i .",
|
|
2153
|
+
"sync_command": "codegraph sync .",
|
|
2154
|
+
"vendoring_policy": "do-not-add-package-dependency"
|
|
2155
|
+
}
|
|
2156
|
+
},
|
|
2157
|
+
"agentic_development": {
|
|
2158
|
+
"routing": {
|
|
2159
|
+
"product_discovery": "gstack:office-hours",
|
|
2160
|
+
"complex_engineering_plan": "gstack:plan-eng-review",
|
|
2161
|
+
"design_plan": "gstack:plan-design-review",
|
|
2162
|
+
"small_or_medium_plan": "waza:think",
|
|
2163
|
+
"bug_or_regression": "waza:hunt",
|
|
2164
|
+
"post_implementation_review": "waza:check"
|
|
2165
|
+
},
|
|
2166
|
+
"due_diligence": {
|
|
2167
|
+
"levels": ["P1_GLOBAL_ARCHITECTURE", "P2_DATA_FLOW_TRACE", "P3_DESIGN_DECISION"],
|
|
2168
|
+
"explicit_report_required_for": ["plan-eng-review", "hunt", "risky_refactor", "deployment", "auth_payment_data", "shared_contract"]
|
|
2169
|
+
}
|
|
2170
|
+
},
|
|
2171
|
+
"enforcement": {
|
|
2172
|
+
"worktree_guard": "warn-by-default",
|
|
2173
|
+
"verification_gate": "contract-and-review",
|
|
2174
|
+
"completion_requires_checks": true
|
|
2175
|
+
}
|
|
2176
|
+
}
|
|
2177
|
+
EOF_POLICY
|
|
2178
|
+
|
|
2179
|
+
if [[ -f "$output_file" ]]; then
|
|
2180
|
+
if ! pi_merge_json_defaults "$default_file" "$output_file" "$merged_file"; then
|
|
2181
|
+
cp "$default_file" "$merged_file"
|
|
2182
|
+
fi
|
|
2183
|
+
elif ! pi_merge_json_defaults "$default_file" "$default_file" "$merged_file"; then
|
|
2184
|
+
cp "$default_file" "$merged_file"
|
|
2185
|
+
else
|
|
2186
|
+
:
|
|
2187
|
+
fi
|
|
2188
|
+
|
|
2189
|
+
mv "$merged_file" "$output_file"
|
|
2190
|
+
rm -f "$default_file"
|
|
2191
|
+
}
|
|
2192
|
+
|
|
2193
|
+
pi_write_brain_manifest() {
|
|
2194
|
+
local target_dir="$1"
|
|
2195
|
+
local mode="${2:-apply}"
|
|
2196
|
+
local output_file="$target_dir/.ai/harness/brain-manifest.json"
|
|
2197
|
+
local project_name
|
|
2198
|
+
|
|
2199
|
+
if [[ "$mode" != "apply" ]]; then
|
|
2200
|
+
echo "[dry-run] write $output_file if missing"
|
|
2201
|
+
return 0
|
|
2202
|
+
fi
|
|
2203
|
+
|
|
2204
|
+
if [[ -f "$output_file" ]]; then
|
|
2205
|
+
return 0
|
|
2206
|
+
fi
|
|
2207
|
+
|
|
2208
|
+
project_name="$(basename "$target_dir")"
|
|
2209
|
+
mkdir -p "$(dirname "$output_file")"
|
|
2210
|
+
cat > "$output_file" <<EOF_BRAIN_MANIFEST
|
|
2211
|
+
{
|
|
2212
|
+
"version": 1,
|
|
2213
|
+
"project": "${project_name}",
|
|
2214
|
+
"mode": "repo-contract-external-knowledge",
|
|
2215
|
+
"default_brain_path": "brain/<project>/*",
|
|
2216
|
+
"rules": [
|
|
2217
|
+
"repo-local contracts, hooks, scripts, checks, and evidence remain authoritative",
|
|
2218
|
+
"default brain stores long-lived explanations, runbooks, decisions, references, and patterns",
|
|
2219
|
+
"hook runtime may sync explicitly opted-in repo-to-brain entries only; it must not query gbrain, MCP, or unregistered default brain paths"
|
|
2220
|
+
],
|
|
2221
|
+
"entries": []
|
|
2222
|
+
}
|
|
2223
|
+
EOF_BRAIN_MANIFEST
|
|
2224
|
+
}
|
|
2225
|
+
|
|
2226
|
+
pi_write_context_map() {
|
|
2227
|
+
local target_dir="$1"
|
|
2228
|
+
local mode="${2:-apply}"
|
|
2229
|
+
local output_file="$target_dir/.ai/context/context-map.json"
|
|
2230
|
+
local discoverable_entries
|
|
2231
|
+
|
|
2232
|
+
discoverable_entries="$(pi_context_map_discoverable_entries "$target_dir")"
|
|
2233
|
+
|
|
2234
|
+
if [[ "$mode" != "apply" ]]; then
|
|
2235
|
+
echo "[dry-run] write $output_file"
|
|
2236
|
+
return 0
|
|
2237
|
+
fi
|
|
2238
|
+
|
|
2239
|
+
mkdir -p "$(dirname "$output_file")"
|
|
2240
|
+
cat > "$output_file" <<EOF_CONTEXT
|
|
2241
|
+
{
|
|
2242
|
+
"version": 1,
|
|
2243
|
+
"profile": "$(pi_context_profile)",
|
|
2244
|
+
"functional_block_selector": {
|
|
2245
|
+
"script": "scripts/select-agent-context-blocks.sh",
|
|
2246
|
+
"config_file": ".ai/context/agent-context-blocks.txt",
|
|
2247
|
+
"env": "FORGE_CONTEXT_BLOCKS",
|
|
2248
|
+
"rule": "compatibility selector; capability registry is the source of truth"
|
|
2249
|
+
},
|
|
2250
|
+
"lsp_profiles": {
|
|
2251
|
+
"default": "$(pi_lsp_profile)",
|
|
2252
|
+
"selection": "functional-block-first"
|
|
2253
|
+
},
|
|
2254
|
+
"root_context_files": [
|
|
2255
|
+
"CLAUDE.md",
|
|
2256
|
+
"AGENTS.md",
|
|
2257
|
+
"docs/spec.md",
|
|
2258
|
+
"tasks/current.md",
|
|
2259
|
+
"tasks/todos.md",
|
|
2260
|
+
"tasks/lessons.md",
|
|
2261
|
+
".ai/context/capabilities.json",
|
|
2262
|
+
".ai/harness/policy.json"
|
|
2263
|
+
],
|
|
2264
|
+
"discoverable_contexts": [
|
|
2265
|
+
${discoverable_entries}
|
|
2266
|
+
],
|
|
2267
|
+
"budgets": {
|
|
2268
|
+
"root_total_chars": 12000,
|
|
2269
|
+
"per_discoverable_file_chars": 1200
|
|
2270
|
+
}
|
|
2271
|
+
}
|
|
2272
|
+
EOF_CONTEXT
|
|
2273
|
+
}
|
|
2274
|
+
|
|
2275
|
+
pi_root_context_content() {
|
|
2276
|
+
cat <<'EOF_ROOT_CONTEXT'
|
|
2277
|
+
# Repo Agent Context
|
|
2278
|
+
|
|
2279
|
+
This is the root routing contract for Claude Code and Codex.
|
|
2280
|
+
|
|
2281
|
+
## Root Workflow Contract
|
|
2282
|
+
|
|
2283
|
+
- Keep sibling `CLAUDE.md` and `AGENTS.md` files aligned. Claude Code consumes `CLAUDE.md`; Codex consumes `AGENTS.md`.
|
|
2284
|
+
- Treat `docs/spec.md` as stable product truth, `tasks/current.md` as a derived status snapshot, and `tasks/todos.md` as the deferred-goal ledger; current execution stays in the active plan's `## Task Breakdown`.
|
|
2285
|
+
- Treat `docs/researches/`, `tasks/lessons.md`, and `.ai/harness/policy.json` as durable workflow context.
|
|
2286
|
+
- Use `.ai/context/context-map.json` and `.ai/context/capabilities.json` to discover functional-block contracts.
|
|
2287
|
+
- Do not infer local `CLAUDE.md` or `AGENTS.md` files from broad physical layouts such as `apps/*`, `packages/*`, or `services/*`.
|
|
2288
|
+
- Put capability-specific ownership, entrypoints, and verification commands in explicitly selected functional-block contracts.
|
|
2289
|
+
- Keep root context concise; route deep implementation detail into plans, task notes, research, workstreams, or architecture docs.
|
|
2290
|
+
- Treat `_ref/` as ignored external reference material and `_ops/` as ignored local operations state.
|
|
2291
|
+
- Prefer repo-local workflow artifacts over tool-specific chat memory.
|
|
2292
|
+
EOF_ROOT_CONTEXT
|
|
2293
|
+
}
|
|
2294
|
+
|
|
2295
|
+
pi_install_root_context_files() {
|
|
2296
|
+
local target_dir="$1"
|
|
2297
|
+
local mode="${2:-apply}"
|
|
2298
|
+
|
|
2299
|
+
if [[ "$mode" != "apply" ]]; then
|
|
2300
|
+
echo "[dry-run] install root CLAUDE.md/AGENTS.md files in $target_dir"
|
|
2301
|
+
return 0
|
|
2302
|
+
fi
|
|
2303
|
+
|
|
2304
|
+
if [[ -f "$target_dir/AGENTS.md" && ! -f "$target_dir/CLAUDE.md" ]]; then
|
|
2305
|
+
cp "$target_dir/AGENTS.md" "$target_dir/CLAUDE.md"
|
|
2306
|
+
return 0
|
|
2307
|
+
fi
|
|
2308
|
+
|
|
2309
|
+
if [[ -f "$target_dir/CLAUDE.md" && ! -f "$target_dir/AGENTS.md" ]]; then
|
|
2310
|
+
cp "$target_dir/CLAUDE.md" "$target_dir/AGENTS.md"
|
|
2311
|
+
return 0
|
|
2312
|
+
fi
|
|
2313
|
+
|
|
2314
|
+
if [[ ! -f "$target_dir/CLAUDE.md" ]]; then
|
|
2315
|
+
pi_root_context_content > "$target_dir/CLAUDE.md"
|
|
2316
|
+
fi
|
|
2317
|
+
|
|
2318
|
+
if [[ ! -f "$target_dir/AGENTS.md" ]]; then
|
|
2319
|
+
pi_root_context_content > "$target_dir/AGENTS.md"
|
|
2320
|
+
fi
|
|
2321
|
+
}
|
|
2322
|
+
|
|
2323
|
+
pi_install_directory_context_files() {
|
|
2324
|
+
local target_dir="$1"
|
|
2325
|
+
local mode="${2:-apply}"
|
|
2326
|
+
local directory_agents_content
|
|
2327
|
+
local selected_dirs
|
|
2328
|
+
local rel_dir
|
|
2329
|
+
local module_dir
|
|
2330
|
+
|
|
2331
|
+
selected_dirs="$(pi_context_block_dirs "$target_dir")"
|
|
2332
|
+
if [[ -z "$selected_dirs" ]]; then
|
|
2333
|
+
return 0
|
|
2334
|
+
fi
|
|
2335
|
+
|
|
2336
|
+
if [[ "$mode" != "apply" ]]; then
|
|
2337
|
+
echo "[dry-run] install selected CLAUDE.md/AGENTS.md files in $target_dir"
|
|
2338
|
+
return 0
|
|
2339
|
+
fi
|
|
2340
|
+
|
|
2341
|
+
directory_agents_content=$(cat <<'EOF_DIRECTORY_AGENTS'
|
|
2342
|
+
# Functional Block Agent Context
|
|
2343
|
+
|
|
2344
|
+
Keep this file focused on the local contract for this primary functional block.
|
|
2345
|
+
|
|
2346
|
+
## Local Context Contract
|
|
2347
|
+
|
|
2348
|
+
- Describe only the ownership, boundaries, stable entrypoints, and local verification commands for this functional block.
|
|
2349
|
+
- Keep sibling `CLAUDE.md` and `AGENTS.md` files aligned. Claude Code consumes `CLAUDE.md`; Codex consumes `AGENTS.md`.
|
|
2350
|
+
- Record the local LSP/tooling profile here when it differs from the repo default.
|
|
2351
|
+
- Route deep implementation detail into nearby docs instead of inflating root agent context files.
|
|
2352
|
+
- Treat `.ai/context/context-map.json` as the index of discoverable context files.
|
|
2353
|
+
- Do not keep pushing context files deeper by default; add lower-level files only for a separately owned functional block with its own commands and invariants.
|
|
2354
|
+
- Prefer repo-local workflow artifacts over tool-specific chat memory.
|
|
2355
|
+
EOF_DIRECTORY_AGENTS
|
|
2356
|
+
)
|
|
2357
|
+
|
|
2358
|
+
while IFS= read -r rel_dir; do
|
|
2359
|
+
[[ -n "$rel_dir" ]] || continue
|
|
2360
|
+
module_dir="$target_dir/$rel_dir"
|
|
2361
|
+
if [[ ! -d "$module_dir" ]]; then
|
|
2362
|
+
continue
|
|
2363
|
+
fi
|
|
2364
|
+
if [[ ! -w "$module_dir" ]]; then
|
|
2365
|
+
echo "[migrate] skipped context mirror in unwritable directory: $rel_dir" >&2
|
|
2366
|
+
continue
|
|
2367
|
+
fi
|
|
2368
|
+
if [[ -f "$module_dir/AGENTS.md" && ! -f "$module_dir/CLAUDE.md" ]]; then
|
|
2369
|
+
cp "$module_dir/AGENTS.md" "$module_dir/CLAUDE.md" || {
|
|
2370
|
+
echo "[migrate] skipped context mirror AGENTS.md -> CLAUDE.md in $rel_dir" >&2
|
|
2371
|
+
continue
|
|
2372
|
+
}
|
|
2373
|
+
elif [[ -f "$module_dir/CLAUDE.md" && ! -f "$module_dir/AGENTS.md" ]]; then
|
|
2374
|
+
cp "$module_dir/CLAUDE.md" "$module_dir/AGENTS.md" || {
|
|
2375
|
+
echo "[migrate] skipped context mirror CLAUDE.md -> AGENTS.md in $rel_dir" >&2
|
|
2376
|
+
continue
|
|
2377
|
+
}
|
|
2378
|
+
else
|
|
2379
|
+
if [[ ! -f "$module_dir/CLAUDE.md" ]]; then
|
|
2380
|
+
printf '%s\n' "$directory_agents_content" > "$module_dir/CLAUDE.md"
|
|
2381
|
+
fi
|
|
2382
|
+
if [[ ! -f "$module_dir/AGENTS.md" ]]; then
|
|
2383
|
+
printf '%s\n' "$directory_agents_content" > "$module_dir/AGENTS.md"
|
|
2384
|
+
fi
|
|
2385
|
+
fi
|
|
2386
|
+
done <<< "$selected_dirs"
|
|
2387
|
+
}
|
|
2388
|
+
|
|
2389
|
+
pi_ensure_harness_state_surface() {
|
|
2390
|
+
local target_dir="$1"
|
|
2391
|
+
local mode="${2:-apply}"
|
|
2392
|
+
|
|
2393
|
+
if [[ "$mode" != "apply" ]]; then
|
|
2394
|
+
echo "[dry-run] ensure harness policy/context/events/runs/worktrees/local-jobs/controller/triage/planning in $target_dir"
|
|
2395
|
+
return 0
|
|
2396
|
+
fi
|
|
2397
|
+
|
|
2398
|
+
mkdir -p \
|
|
2399
|
+
"$target_dir/tasks/notes" \
|
|
2400
|
+
"$target_dir/tasks/workstreams" \
|
|
2401
|
+
"$target_dir/.ai/context" \
|
|
2402
|
+
"$target_dir/.ai/harness/checks" \
|
|
2403
|
+
"$target_dir/.ai/harness/handoff" \
|
|
2404
|
+
"$target_dir/.ai/harness/scripts" \
|
|
2405
|
+
"$target_dir/.ai/harness/failures" \
|
|
2406
|
+
"$target_dir/.ai/harness/security" \
|
|
2407
|
+
"$target_dir/.ai/harness/planning" \
|
|
2408
|
+
"$target_dir/.ai/harness/architecture" \
|
|
2409
|
+
"$target_dir/.ai/harness/worktrees" \
|
|
2410
|
+
"$target_dir/.ai/harness/controller" \
|
|
2411
|
+
"$target_dir/.ai/harness/local-jobs" \
|
|
2412
|
+
"$target_dir/.ai/harness/triage" \
|
|
2413
|
+
"$target_dir/docs/researches" \
|
|
2414
|
+
"$target_dir/docs/architecture/domains" \
|
|
2415
|
+
"$target_dir/docs/architecture/modules" \
|
|
2416
|
+
"$target_dir/docs/architecture/requests" \
|
|
2417
|
+
"$target_dir/docs/architecture/snapshots" \
|
|
2418
|
+
"$target_dir/docs/architecture/diagrams" \
|
|
2419
|
+
"$target_dir/.ai/harness/runs"
|
|
2420
|
+
|
|
2421
|
+
[[ -f "$target_dir/.ai/harness/checks/latest.json" ]] || printf "{}\n" > "$target_dir/.ai/harness/checks/latest.json"
|
|
2422
|
+
[[ -f "$target_dir/.ai/harness/handoff/current.md" ]] || printf "# Harness Handoff\n\n> **Reason**: bootstrap\n" > "$target_dir/.ai/harness/handoff/current.md"
|
|
2423
|
+
[[ -f "$target_dir/.ai/harness/handoff/resume.md" ]] || printf "# Codex Resume Packet\n\n> **Reason**: bootstrap\n" > "$target_dir/.ai/harness/handoff/resume.md"
|
|
2424
|
+
[[ -f "$target_dir/.ai/context/capability-source-map.json" ]] || printf '{\n "version": 1,\n "capabilities": {}\n}\n' > "$target_dir/.ai/context/capability-source-map.json"
|
|
2425
|
+
[[ -f "$target_dir/.ai/harness/events.jsonl" ]] || : > "$target_dir/.ai/harness/events.jsonl"
|
|
2426
|
+
[[ -f "$target_dir/.ai/harness/architecture/events.jsonl" ]] || : > "$target_dir/.ai/harness/architecture/events.jsonl"
|
|
2427
|
+
[[ -f "$target_dir/.ai/harness/architecture/.gitkeep" ]] || : > "$target_dir/.ai/harness/architecture/.gitkeep"
|
|
2428
|
+
[[ -f "$target_dir/.ai/harness/failures/latest.jsonl" ]] || : > "$target_dir/.ai/harness/failures/latest.jsonl"
|
|
2429
|
+
[[ -f "$target_dir/.ai/harness/security/.gitkeep" ]] || : > "$target_dir/.ai/harness/security/.gitkeep"
|
|
2430
|
+
[[ -f "$target_dir/.ai/harness/scripts/.gitkeep" ]] || : > "$target_dir/.ai/harness/scripts/.gitkeep"
|
|
2431
|
+
[[ -f "$target_dir/.ai/harness/planning/.gitkeep" ]] || : > "$target_dir/.ai/harness/planning/.gitkeep"
|
|
2432
|
+
[[ -f "$target_dir/.ai/harness/worktrees/.gitkeep" ]] || : > "$target_dir/.ai/harness/worktrees/.gitkeep"
|
|
2433
|
+
[[ -f "$target_dir/.ai/harness/runs/.gitkeep" ]] || : > "$target_dir/.ai/harness/runs/.gitkeep"
|
|
2434
|
+
[[ -f "$target_dir/.ai/harness/triage/.gitkeep" ]] || : > "$target_dir/.ai/harness/triage/.gitkeep"
|
|
2435
|
+
[[ -f "$target_dir/tasks/workstreams/.gitkeep" ]] || : > "$target_dir/tasks/workstreams/.gitkeep"
|
|
2436
|
+
if [[ ! -f "$target_dir/docs/researches/README.md" ]]; then
|
|
2437
|
+
cat > "$target_dir/docs/researches/README.md" <<'RESEARCH_README_EOF'
|
|
2438
|
+
# Research Reports
|
|
2439
|
+
|
|
2440
|
+
Durable research reports live in this directory as topic-scoped Markdown files.
|
|
2441
|
+
|
|
2442
|
+
Use `YYYYMMDD-topic.md` names when chronology matters, or `<topic>.md` for
|
|
2443
|
+
stable subject reports. Keep task-local implementation decisions in
|
|
2444
|
+
`tasks/notes/`, and keep repeated correction-derived rules in `tasks/lessons.md`.
|
|
2445
|
+
RESEARCH_README_EOF
|
|
2446
|
+
fi
|
|
2447
|
+
if [[ ! -f "$target_dir/tasks/current.md" ]]; then
|
|
2448
|
+
cat > "$target_dir/tasks/current.md" <<'CURRENT_STATUS_EOF'
|
|
2449
|
+
# Current Status Snapshot
|
|
2450
|
+
|
|
2451
|
+
<!-- generated-by: forge refresh-current-status v1 -->
|
|
2452
|
+
<!-- updated_at: bootstrap -->
|
|
2453
|
+
<!-- stale_after: 24h -->
|
|
2454
|
+
|
|
2455
|
+
> **Status**: Idle
|
|
2456
|
+
> **Updated At**: bootstrap
|
|
2457
|
+
> **Source Branch**: main
|
|
2458
|
+
> **Source Commit**: bootstrap
|
|
2459
|
+
> **Target Branch**: main
|
|
2460
|
+
> **Stale After**: 24h
|
|
2461
|
+
> **Reason**: bootstrap
|
|
2462
|
+
> **Derived From**: active-plan, active-sprint, workstreams, handoff, checks, git status
|
|
2463
|
+
|
|
2464
|
+
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.
|
|
2465
|
+
CURRENT_STATUS_EOF
|
|
2466
|
+
fi
|
|
2467
|
+
[[ -f "$target_dir/docs/architecture/domains/.gitkeep" ]] || : > "$target_dir/docs/architecture/domains/.gitkeep"
|
|
2468
|
+
[[ -f "$target_dir/docs/architecture/modules/.gitkeep" ]] || : > "$target_dir/docs/architecture/modules/.gitkeep"
|
|
2469
|
+
[[ -f "$target_dir/docs/architecture/requests/.gitkeep" ]] || : > "$target_dir/docs/architecture/requests/.gitkeep"
|
|
2470
|
+
[[ -f "$target_dir/docs/architecture/snapshots/.gitkeep" ]] || : > "$target_dir/docs/architecture/snapshots/.gitkeep"
|
|
2471
|
+
[[ -f "$target_dir/docs/architecture/diagrams/.gitkeep" ]] || : > "$target_dir/docs/architecture/diagrams/.gitkeep"
|
|
2472
|
+
if [[ ! -f "$target_dir/docs/architecture/index.md" ]]; then
|
|
2473
|
+
cat > "$target_dir/docs/architecture/index.md" <<'ARCHITECTURE_INDEX_EOF'
|
|
2474
|
+
# Architecture Index
|
|
2475
|
+
|
|
2476
|
+
> Umbrella architecture ledger for current boundaries, drift requests, snapshots, and diagrams.
|
|
2477
|
+
|
|
2478
|
+
## Current Snapshot
|
|
2479
|
+
|
|
2480
|
+
- Latest snapshot: (none yet)
|
|
2481
|
+
- Semantic diagram source: (none yet)
|
|
2482
|
+
- Latest human diagram: (none yet)
|
|
2483
|
+
|
|
2484
|
+
## Architecture Drift Flow
|
|
2485
|
+
|
|
2486
|
+
- `.ai/harness/scripts/architecture-queue.sh` records architecture-sensitive edits as requests.
|
|
2487
|
+
- `.ai/harness/scripts/archive-architecture-request.sh` archives handled requests after an agent records the resolution status and linked artifacts.
|
|
2488
|
+
- `.ai/harness/scripts/context-contract-sync.sh` keeps only the controlled architecture block in functional-block `AGENTS.md` and `CLAUDE.md` files aligned.
|
|
2489
|
+
- `.ai/harness/scripts/workstream-sync.sh` keeps durable multi-session progress under `tasks/workstreams/<domain>/<capability>/` and projects only pointers into local contracts.
|
|
2490
|
+
- Semantic architecture diagrams live as Mermaid fenced blocks in the relevant module or snapshot Markdown.
|
|
2491
|
+
- Human-readable architecture diagrams are optional `mermaid` HTML files in `docs/architecture/diagrams/` and should link back to the Markdown semantic source.
|
|
2492
|
+
|
|
2493
|
+
## Pending Requests
|
|
2494
|
+
|
|
2495
|
+
<!-- BEGIN ARCHITECTURE PENDING REQUESTS -->
|
|
2496
|
+
- (none)
|
|
2497
|
+
<!-- END ARCHITECTURE PENDING REQUESTS -->
|
|
2498
|
+
|
|
2499
|
+
ARCHITECTURE_INDEX_EOF
|
|
2500
|
+
fi
|
|
2501
|
+
|
|
2502
|
+
pi_write_capability_registry "$target_dir" "$mode"
|
|
2503
|
+
pi_write_harness_policy "$target_dir" "$mode"
|
|
2504
|
+
pi_write_brain_manifest "$target_dir" "$mode"
|
|
2505
|
+
pi_write_context_map "$target_dir" "$mode"
|
|
2506
|
+
pi_install_root_context_files "$target_dir" "$mode"
|
|
2507
|
+
pi_install_directory_context_files "$target_dir" "$mode"
|
|
2508
|
+
}
|
|
2509
|
+
|
|
2510
|
+
pi_resolve_js_runtime() {
|
|
2511
|
+
if command -v node >/dev/null 2>&1; then
|
|
2512
|
+
printf 'node'
|
|
2513
|
+
return 0
|
|
2514
|
+
fi
|
|
2515
|
+
|
|
2516
|
+
if command -v bun >/dev/null 2>&1; then
|
|
2517
|
+
printf 'bun'
|
|
2518
|
+
return 0
|
|
2519
|
+
fi
|
|
2520
|
+
|
|
2521
|
+
if [[ -x "${HOME}/.bun/bin/bun" ]]; then
|
|
2522
|
+
printf '%s' "${HOME}/.bun/bin/bun"
|
|
2523
|
+
return 0
|
|
2524
|
+
fi
|
|
2525
|
+
|
|
2526
|
+
return 1
|
|
2527
|
+
}
|
|
2528
|
+
|
|
2529
|
+
pi_merge_json_defaults() {
|
|
2530
|
+
local defaults_file="$1"
|
|
2531
|
+
local current_file="$2"
|
|
2532
|
+
local output_file="$3"
|
|
2533
|
+
local js_runtime
|
|
2534
|
+
|
|
2535
|
+
js_runtime="$(pi_resolve_js_runtime || true)"
|
|
2536
|
+
if [[ -n "$js_runtime" ]]; then
|
|
2537
|
+
"$js_runtime" -e '
|
|
2538
|
+
const fs = require("fs");
|
|
2539
|
+
const [defaultsPath, currentPath, outputPath] = process.argv.slice(1);
|
|
2540
|
+
|
|
2541
|
+
function isPlainObject(value) {
|
|
2542
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
2543
|
+
}
|
|
2544
|
+
|
|
2545
|
+
const unionArrayPaths = new Set(["documentation.reference_configs"]);
|
|
2546
|
+
|
|
2547
|
+
function mergeDefaults(defaultsValue, currentValue, path = []) {
|
|
2548
|
+
if (Array.isArray(defaultsValue)) {
|
|
2549
|
+
const keyPath = path.join(".");
|
|
2550
|
+
if (Array.isArray(currentValue) && unionArrayPaths.has(keyPath)) {
|
|
2551
|
+
const result = [...currentValue];
|
|
2552
|
+
for (const item of defaultsValue) {
|
|
2553
|
+
if (!result.includes(item)) result.push(item);
|
|
2554
|
+
}
|
|
2555
|
+
return result;
|
|
2556
|
+
}
|
|
2557
|
+
return Array.isArray(currentValue) ? currentValue : defaultsValue;
|
|
2558
|
+
}
|
|
2559
|
+
|
|
2560
|
+
if (isPlainObject(defaultsValue)) {
|
|
2561
|
+
const result = { ...defaultsValue };
|
|
2562
|
+
if (isPlainObject(currentValue)) {
|
|
2563
|
+
for (const [key, value] of Object.entries(currentValue)) {
|
|
2564
|
+
result[key] = Object.prototype.hasOwnProperty.call(defaultsValue, key)
|
|
2565
|
+
? mergeDefaults(defaultsValue[key], value, [...path, key])
|
|
2566
|
+
: value;
|
|
2567
|
+
}
|
|
2568
|
+
}
|
|
2569
|
+
return result;
|
|
2570
|
+
}
|
|
2571
|
+
|
|
2572
|
+
return currentValue === undefined ? defaultsValue : currentValue;
|
|
2573
|
+
}
|
|
2574
|
+
|
|
2575
|
+
const defaultsJson = JSON.parse(fs.readFileSync(defaultsPath, "utf8"));
|
|
2576
|
+
let currentJson = {};
|
|
2577
|
+
try {
|
|
2578
|
+
currentJson = JSON.parse(fs.readFileSync(currentPath, "utf8"));
|
|
2579
|
+
} catch (_error) {
|
|
2580
|
+
currentJson = {};
|
|
2581
|
+
}
|
|
2582
|
+
|
|
2583
|
+
const merged = mergeDefaults(defaultsJson, currentJson);
|
|
2584
|
+
fs.writeFileSync(outputPath, JSON.stringify(merged, null, 2) + "\n");
|
|
2585
|
+
' "$defaults_file" "$current_file" "$output_file"
|
|
2586
|
+
return $?
|
|
2587
|
+
fi
|
|
2588
|
+
|
|
2589
|
+
if command -v python3 >/dev/null 2>&1; then
|
|
2590
|
+
python3 - "$defaults_file" "$current_file" "$output_file" <<'PY_EOF'
|
|
2591
|
+
import json
|
|
2592
|
+
import sys
|
|
2593
|
+
|
|
2594
|
+
defaults_path, current_path, output_path = sys.argv[1:]
|
|
2595
|
+
|
|
2596
|
+
UNION_ARRAY_PATHS = {("documentation", "reference_configs")}
|
|
2597
|
+
|
|
2598
|
+
def merge_defaults(defaults_value, current_value, path=()):
|
|
2599
|
+
if isinstance(defaults_value, list):
|
|
2600
|
+
if isinstance(current_value, list) and path in UNION_ARRAY_PATHS:
|
|
2601
|
+
result = list(current_value)
|
|
2602
|
+
for item in defaults_value:
|
|
2603
|
+
if item not in result:
|
|
2604
|
+
result.append(item)
|
|
2605
|
+
return result
|
|
2606
|
+
return current_value if isinstance(current_value, list) else defaults_value
|
|
2607
|
+
if isinstance(defaults_value, dict):
|
|
2608
|
+
result = dict(defaults_value)
|
|
2609
|
+
if isinstance(current_value, dict):
|
|
2610
|
+
for key, value in current_value.items():
|
|
2611
|
+
result[key] = merge_defaults(defaults_value[key], value, path + (key,)) if key in defaults_value else value
|
|
2612
|
+
return result
|
|
2613
|
+
return defaults_value if current_value is None else current_value
|
|
2614
|
+
|
|
2615
|
+
with open(defaults_path, "r", encoding="utf-8") as handle:
|
|
2616
|
+
defaults_json = json.load(handle)
|
|
2617
|
+
|
|
2618
|
+
try:
|
|
2619
|
+
with open(current_path, "r", encoding="utf-8") as handle:
|
|
2620
|
+
current_json = json.load(handle)
|
|
2621
|
+
except Exception:
|
|
2622
|
+
current_json = {}
|
|
2623
|
+
|
|
2624
|
+
merged = merge_defaults(defaults_json, current_json)
|
|
2625
|
+
with open(output_path, "w", encoding="utf-8") as handle:
|
|
2626
|
+
json.dump(merged, handle, indent=2)
|
|
2627
|
+
handle.write("\n")
|
|
2628
|
+
PY_EOF
|
|
2629
|
+
return $?
|
|
2630
|
+
fi
|
|
2631
|
+
|
|
2632
|
+
return 1
|
|
2633
|
+
}
|
|
2634
|
+
|
|
2635
|
+
pi_ensure_task_sync() {
|
|
2636
|
+
local target_dir="$1"
|
|
2637
|
+
local create_if_missing="${2:-0}"
|
|
2638
|
+
local mode="${3:-apply}"
|
|
2639
|
+
local package_file="$target_dir/package.json"
|
|
2640
|
+
local js_runtime
|
|
2641
|
+
local project_name
|
|
2642
|
+
|
|
2643
|
+
if [[ ! -f "$package_file" && "$create_if_missing" != "1" ]]; then
|
|
2644
|
+
if [[ "$mode" != "apply" ]]; then
|
|
2645
|
+
echo "[dry-run] package.json missing; skip task workflow script injection"
|
|
2646
|
+
fi
|
|
2647
|
+
return 0
|
|
2648
|
+
fi
|
|
2649
|
+
|
|
2650
|
+
if [[ "$mode" != "apply" ]]; then
|
|
2651
|
+
echo "[dry-run] inject task workflow scripts into $package_file"
|
|
2652
|
+
return 0
|
|
2653
|
+
fi
|
|
2654
|
+
|
|
2655
|
+
if [[ ! -f "$package_file" ]]; then
|
|
2656
|
+
project_name="$(basename "$target_dir" | tr '[:upper:]' '[:lower:]' | tr -cs 'a-z0-9-' '-')"
|
|
2657
|
+
project_name="${project_name:-project}"
|
|
2658
|
+
cat > "$package_file" <<EOF_PACKAGE
|
|
2659
|
+
{
|
|
2660
|
+
"name": "$project_name",
|
|
2661
|
+
"private": true,
|
|
2662
|
+
"scripts": {
|
|
2663
|
+
"check:brain-manifest": "forge run check-brain-manifest",
|
|
2664
|
+
"check:context-files": "forge run check-context-files",
|
|
2665
|
+
"check:deploy-sql": "forge run check-deploy-sql-order",
|
|
2666
|
+
"check:architecture-sync": "forge run check-architecture-sync",
|
|
2667
|
+
"check:task": "bash scripts/check-task-workflow.sh --strict",
|
|
2668
|
+
"check:task-sync": "forge run check-task-sync",
|
|
2669
|
+
"check:task-workflow": "forge run check-task-workflow --strict",
|
|
2670
|
+
"sync:brain-docs": "forge run sync-brain-docs --all"
|
|
2671
|
+
}
|
|
2672
|
+
}
|
|
2673
|
+
EOF_PACKAGE
|
|
2674
|
+
return 0
|
|
2675
|
+
fi
|
|
2676
|
+
|
|
2677
|
+
js_runtime="$(pi_resolve_js_runtime || true)"
|
|
2678
|
+
if [[ -z "$js_runtime" ]]; then
|
|
2679
|
+
echo "[warn] no JavaScript runtime found; unable to inject task workflow scripts into $package_file" >&2
|
|
2680
|
+
return 0
|
|
2681
|
+
fi
|
|
2682
|
+
|
|
2683
|
+
"$js_runtime" -e '
|
|
2684
|
+
const fs = require("fs");
|
|
2685
|
+
const file = process.argv[1];
|
|
2686
|
+
const pkg = JSON.parse(fs.readFileSync(file, "utf8"));
|
|
2687
|
+
pkg.private ??= true;
|
|
2688
|
+
pkg.scripts ??= {};
|
|
2689
|
+
pkg.scripts["check:brain-manifest"] = "forge run check-brain-manifest";
|
|
2690
|
+
pkg.scripts["check:context-files"] = "forge run check-context-files";
|
|
2691
|
+
pkg.scripts["check:deploy-sql"] = "forge run check-deploy-sql-order";
|
|
2692
|
+
pkg.scripts["check:architecture-sync"] = "forge run check-architecture-sync";
|
|
2693
|
+
pkg.scripts["check:task"] = "bash scripts/check-task-workflow.sh --strict";
|
|
2694
|
+
pkg.scripts["check:task-sync"] = "forge run check-task-sync";
|
|
2695
|
+
pkg.scripts["check:task-workflow"] = "forge run check-task-workflow --strict";
|
|
2696
|
+
pkg.scripts["sync:brain-docs"] = "forge run sync-brain-docs --all";
|
|
2697
|
+
fs.writeFileSync(file, JSON.stringify(pkg, null, 2) + "\n");
|
|
2698
|
+
' "$package_file"
|
|
2699
|
+
}
|
|
2700
|
+
|
|
2701
|
+
pi_factor_factory_gitignore_entries() {
|
|
2702
|
+
printf '%s\n' ".claude/.factor-cache/"
|
|
2703
|
+
}
|
|
2704
|
+
|
|
2705
|
+
pi_should_enable_factor_factory() {
|
|
2706
|
+
local plan_type="${1:-$(pi_plan_type)}"
|
|
2707
|
+
local explicit
|
|
2708
|
+
explicit="$(pi_env_value "FORGE_FACTOR_FACTORY" "0")"
|
|
2709
|
+
|
|
2710
|
+
case "$explicit" in
|
|
2711
|
+
1|true|TRUE|yes|YES) return 0 ;;
|
|
2712
|
+
esac
|
|
2713
|
+
|
|
2714
|
+
[[ "$plan_type" == "G" ]]
|
|
2715
|
+
}
|
|
2716
|
+
|
|
2717
|
+
pi_install_factor_factory() {
|
|
2718
|
+
local target_dir="$1"
|
|
2719
|
+
local factor_assets_dir="$2"
|
|
2720
|
+
local scripts_source_dir="$3"
|
|
2721
|
+
local mode="${4:-apply}"
|
|
2722
|
+
local scripts_dir="$target_dir/.ai/harness/scripts"
|
|
2723
|
+
local factors_dir="$target_dir/tasks/factors"
|
|
2724
|
+
local cache_dir="$target_dir/.claude/.factor-cache/candidates"
|
|
2725
|
+
local registry_template="$factor_assets_dir/factor-registry.template.json"
|
|
2726
|
+
local hypothesis_template="$factor_assets_dir/factor-hypothesis.template.md"
|
|
2727
|
+
local report_template="$factor_assets_dir/factor-backtest-report.template.md"
|
|
2728
|
+
|
|
2729
|
+
if [[ "$mode" != "apply" ]]; then
|
|
2730
|
+
echo "[dry-run] install factor factory assets into $target_dir"
|
|
2731
|
+
return 0
|
|
2732
|
+
fi
|
|
2733
|
+
|
|
2734
|
+
mkdir -p "$factors_dir/promoted" "$cache_dir" "$scripts_dir"
|
|
2735
|
+
|
|
2736
|
+
if [[ -f "$registry_template" ]]; then
|
|
2737
|
+
cp "$registry_template" "$factors_dir/registry.json"
|
|
2738
|
+
fi
|
|
2739
|
+
|
|
2740
|
+
if [[ -f "$hypothesis_template" ]]; then
|
|
2741
|
+
mkdir -p "$target_dir/.claude/factor-factory"
|
|
2742
|
+
cp "$hypothesis_template" "$target_dir/.claude/factor-factory/hypothesis.template.md"
|
|
2743
|
+
fi
|
|
2744
|
+
|
|
2745
|
+
if [[ -f "$report_template" ]]; then
|
|
2746
|
+
mkdir -p "$target_dir/.claude/factor-factory"
|
|
2747
|
+
cp "$report_template" "$target_dir/.claude/factor-factory/backtest-report.template.md"
|
|
2748
|
+
fi
|
|
2749
|
+
|
|
2750
|
+
local factor_script
|
|
2751
|
+
for factor_script in factor-lab-new.sh factor-lab-promote.sh factor-lab-reject.sh factor-lab-check.sh; do
|
|
2752
|
+
if [[ -f "$scripts_source_dir/$factor_script" ]]; then
|
|
2753
|
+
cp "$scripts_source_dir/$factor_script" "$scripts_dir/$factor_script"
|
|
2754
|
+
pi_normalize_installed_helper "$scripts_dir/$factor_script"
|
|
2755
|
+
fi
|
|
2756
|
+
done
|
|
2757
|
+
|
|
2758
|
+
pi_ensure_executable_if_apply "$mode" "$scripts_dir"/factor-lab-*.sh
|
|
2759
|
+
}
|