forge-workflow 0.0.9 → 0.1.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/rules/{greptile-review-process.md → review-process.md} +56 -41
- package/.claude/scripts/{greptile-resolve.sh → review-resolve.sh} +13 -3
- package/.cursor/rules/permissions-guidance.mdc +2 -2
- package/.forge/hooks/check-tdd.js +3 -0
- package/.forge/hooks/forge-native-hook.js +245 -0
- package/.forge/protected-paths.yaml +157 -0
- package/AGENTS.md +151 -61
- package/CHANGELOG.md +681 -0
- package/CLAUDE.md +9 -106
- package/QUICKSTART.md +171 -0
- package/README.md +271 -363
- package/bin/forge-cmd.js +120 -9
- package/bin/forge-preflight.js +26 -5
- package/bin/forge.js +466 -489
- package/docs/INDEX.md +93 -0
- package/docs/PROJECT_DESIGN.md +685 -0
- package/docs/architecture/index.md +66 -0
- package/docs/architecture/notes/README.md +35 -0
- package/docs/architecture/subsystems/README.md +46 -0
- package/docs/{TOOLCHAIN.md → forge/TOOLCHAIN.md} +56 -47
- package/docs/forge/VALIDATION.md +82 -0
- package/docs/{AGENT_INSTALL_PROMPT.md → guides/AGENT_INSTALL_PROMPT.md} +3 -3
- package/docs/guides/BEADS_GITHUB_SYNC.md +32 -0
- package/docs/{ENHANCED_ONBOARDING.md → guides/ENHANCED_ONBOARDING.md} +16 -12
- package/docs/guides/GREPTILE_SETUP.md +46 -0
- package/docs/guides/MANUAL_REVIEW_GUIDE.md +58 -0
- package/docs/guides/MIGRATION.md +56 -0
- package/docs/guides/SETUP.md +118 -0
- package/docs/guides/SUPPORT.md +185 -0
- package/docs/guides/WORKFLOW_TEMPLATES.md +74 -0
- package/docs/guides/memory-backends.md +183 -0
- package/docs/reference/ADAPTERS.md +128 -0
- package/docs/reference/AGENT_SKILL_PARITY.md +175 -0
- package/docs/reference/COMMANDS.md +205 -0
- package/docs/reference/DECISION_DRIFT_GUARDS.md +97 -0
- package/docs/{EXAMPLES.md → reference/EXAMPLES.md} +7 -5
- package/docs/reference/FORGE_KERNEL_STORAGE_MODEL.md +135 -0
- package/docs/reference/HERMES_INTEGRATION.md +118 -0
- package/docs/reference/INSIGHTS_RECAP.md +63 -0
- package/docs/reference/INSTALL.md +164 -0
- package/docs/reference/KERNEL_TAXONOMY_VALIDATION.md +161 -0
- package/docs/reference/PROTECTED_PATH_MANIFEST.md +25 -0
- package/docs/reference/RELEASE.md +68 -0
- package/docs/reference/RESEARCH_TEMPLATE.md +292 -0
- package/docs/{ROADMAP.md → reference/ROADMAP.md} +12 -9
- package/docs/reference/SKILLS.md +35 -0
- package/docs/reference/STATUS_BOARD.md +80 -0
- package/docs/reference/TEMPLATES.md +106 -0
- package/docs/reference/TOOLCHAIN.md +658 -0
- package/docs/reference/VALIDATION.md +82 -0
- package/docs/reference/agent-permissions.md +169 -0
- package/docs/reference/beads-to-kernel-migration-ux.md +61 -0
- package/docs/reference/control-plane-guarantees.md +125 -0
- package/docs/reference/dependency-chain.md +331 -0
- package/docs/reference/forge-kernel-issue-command-contract.md +161 -0
- package/docs/reference/forge-kernel-schema.md +72 -0
- package/docs/reference/kernel-conflict-evaluators.md +27 -0
- package/docs/reference/patch-md-format.md +77 -0
- package/docs/reference/protected-state-surfaces.md +59 -0
- package/docs/reference/shepherd.md +115 -0
- package/docs/reference/superpowers-analysis.md +320 -0
- package/docs/reference/superpowers-integration-options.md +404 -0
- package/docs/reference/test-environment.md +519 -0
- package/docs/reference/upgrade-safety.md +59 -0
- package/lefthook.yml +18 -0
- package/lib/adapter-cli.js +307 -0
- package/lib/adapters/beads-issue-adapter.js +127 -0
- package/lib/adapters/beads-kernel-compat.js +1042 -0
- package/lib/adapters/greptile-review-adapter.js +141 -0
- package/lib/adapters/kernel-issue-adapter.js +101 -0
- package/lib/adapters/pr-state-adapter.js +484 -0
- package/lib/adoption-profiles.js +126 -0
- package/lib/agents/README.md +2 -6
- package/lib/agents/claude.plugin.json +3 -8
- package/lib/agents/codex.plugin.json +9 -1
- package/lib/agents/cursor.plugin.json +2 -6
- package/lib/agents/hermes.plugin.json +22 -0
- package/lib/agents-config.js +39 -1236
- package/lib/audit-evidence.js +282 -0
- package/lib/beads-setup.js +225 -28
- package/lib/beads-sync-scaffold.js +36 -107
- package/lib/codex-skills.js +51 -1
- package/lib/commands/_issue.js +744 -70
- package/lib/commands/_manifest.js +91 -0
- package/lib/commands/_registry.js +85 -34
- package/lib/commands/_resolve-command-opts.js +261 -0
- package/lib/commands/_serve-security.js +270 -0
- package/lib/commands/adapter.js +12 -0
- package/lib/commands/add.js +118 -0
- package/lib/commands/audit.js +70 -0
- package/lib/commands/blocked.js +5 -0
- package/lib/commands/board.js +64 -0
- package/lib/commands/claim.js +21 -2
- package/lib/commands/claims.js +7 -0
- package/lib/commands/clean.js +485 -75
- package/lib/commands/close.js +2 -2
- package/lib/commands/comment.js +5 -0
- package/lib/commands/control.js +148 -0
- package/lib/commands/create.js +2 -2
- package/lib/commands/dev.js +185 -7
- package/lib/commands/doc-gate.js +336 -0
- package/lib/commands/doctor.js +156 -0
- package/lib/commands/explain.js +15 -0
- package/lib/commands/export.js +237 -0
- package/lib/commands/gate.js +192 -0
- package/lib/commands/hooks.js +242 -0
- package/lib/commands/inbox.js +118 -0
- package/lib/commands/init.js +598 -0
- package/lib/commands/insights.js +79 -0
- package/lib/commands/issue.js +12 -1
- package/lib/commands/issues.js +66 -0
- package/lib/commands/lint.js +5 -0
- package/lib/commands/list.js +2 -2
- package/lib/commands/merge.js +312 -0
- package/lib/commands/migrate.js +523 -0
- package/lib/commands/new.js +12 -0
- package/lib/commands/options.js +241 -0
- package/lib/commands/orient.js +13 -0
- package/lib/commands/orphans.js +5 -0
- package/lib/commands/patch.js +67 -0
- package/lib/commands/plan.js +436 -24
- package/lib/commands/preflight.js +211 -0
- package/lib/commands/prime.js +13 -0
- package/lib/commands/push.js +69 -2
- package/lib/commands/ready.js +2 -2
- package/lib/commands/recall.js +116 -0
- package/lib/commands/recap.js +61 -0
- package/lib/commands/recommend.js +22 -2
- package/lib/commands/release.js +91 -0
- package/lib/commands/remember.js +74 -0
- package/lib/commands/role.js +99 -0
- package/lib/commands/serve.js +581 -0
- package/lib/commands/setup.js +851 -979
- package/lib/commands/shepherd.js +436 -0
- package/lib/commands/ship.js +23 -1
- package/lib/commands/show.js +2 -2
- package/lib/commands/stage.js +192 -0
- package/lib/commands/stale.js +5 -0
- package/lib/commands/status.js +329 -11
- package/lib/commands/sync.js +34 -46
- package/lib/commands/team.js +15 -2
- package/lib/commands/test.js +58 -7
- package/lib/commands/update.js +2 -2
- package/lib/commands/upgrade.js +47 -0
- package/lib/commands/validate.js +56 -25
- package/lib/commands/worktree.js +308 -128
- package/lib/config-writer.js +202 -0
- package/lib/control-plane.js +236 -0
- package/lib/core/runtime-graph.js +946 -0
- package/lib/dep-guard/keyword-ripple.js +184 -0
- package/lib/deprecated-sync-cleanup.js +362 -0
- package/lib/detect-agent.js +2 -28
- package/lib/detect-worktree.js +42 -17
- package/lib/doc-gate/declaration.js +177 -0
- package/lib/doc-gate/detect.js +289 -0
- package/lib/doc-gate/gate.js +375 -0
- package/lib/doc-gate/okf-config.js +128 -0
- package/lib/doc-gate/okf.js +429 -0
- package/lib/docs-command.js +1161 -6
- package/lib/forge-issues.js +697 -0
- package/lib/forge-lock.js +262 -0
- package/lib/gate-events.js +193 -0
- package/lib/global-flags.js +74 -0
- package/lib/greptile-match.js +7 -63
- package/lib/harness-capability-matrix.js +380 -0
- package/lib/hook-global-installer.js +347 -0
- package/lib/hook-renderer.js +451 -0
- package/lib/inbox.js +391 -0
- package/lib/insights.js +397 -0
- package/lib/issue-adapter.js +156 -0
- package/lib/issue-backend.js +145 -0
- package/lib/issue-render.js +220 -0
- package/lib/issue-sync/authority.js +100 -0
- package/lib/issue-sync/github-pull.js +184 -0
- package/lib/issue-sync/import-primitives.js +98 -0
- package/lib/issue-sync/legacy-link-bridge.js +436 -0
- package/lib/issue-sync/link-store.js +292 -0
- package/lib/issue-sync/project-github.js +123 -0
- package/lib/issue-sync/reconcile.js +195 -0
- package/lib/issue-sync/schema.js +126 -0
- package/lib/kernel/backing-issue.js +305 -0
- package/lib/kernel/broker.js +1218 -0
- package/lib/kernel/cli-broker-factory.js +130 -0
- package/lib/kernel/conflict-signal.js +82 -0
- package/lib/kernel/evaluators.js +195 -0
- package/lib/kernel/fs-class.js +495 -0
- package/lib/kernel/issue-command-contract.js +559 -0
- package/lib/kernel/issue-id-resolver.js +186 -0
- package/lib/kernel/lease-enforcer.js +158 -0
- package/lib/kernel/migrations.js +333 -0
- package/lib/kernel/planning-buckets-schema.js +109 -0
- package/lib/kernel/projection-jsonl-writer.js +450 -0
- package/lib/kernel/readiness-model.js +329 -0
- package/lib/kernel/schema.js +356 -0
- package/lib/kernel/sqlite-driver.js +2504 -0
- package/lib/kernel/taxonomy-validator.js +394 -0
- package/lib/lefthook-check.js +8 -4
- package/lib/lefthook-wiring.js +413 -0
- package/lib/mcp-config-renderer.js +288 -0
- package/lib/memory/graphiti-mcp.js +106 -0
- package/lib/memory/router.js +387 -0
- package/lib/memory/typed-api.js +102 -0
- package/lib/memory-digest.js +195 -0
- package/lib/merge-rules.js +395 -0
- package/lib/migrate-dry-run.js +466 -0
- package/lib/orientation.js +863 -0
- package/lib/package-manager-remediation.js +103 -0
- package/lib/package-root.js +381 -0
- package/lib/patch-intent.js +890 -0
- package/lib/plugin-catalog.js +3 -4
- package/lib/plugin-manager.js +0 -5
- package/lib/pr-bundle.js +186 -0
- package/lib/pr-monitor/differ.js +195 -0
- package/lib/pr-monitor/events.js +0 -0
- package/lib/pr-monitor/gather.js +124 -0
- package/lib/pr-monitor/journal.js +299 -0
- package/lib/pr-monitor/monitor.js +146 -0
- package/lib/pr-monitor/render-sticky.js +157 -0
- package/lib/pr-monitor/watch-lifecycle.js +95 -0
- package/lib/pr-monitor/watch.js +247 -0
- package/lib/pr-pull.js +1273 -0
- package/lib/pr-shepherd.js +494 -0
- package/lib/pr-state-validator.js +59 -0
- package/lib/preflight/gates.js +237 -0
- package/lib/preflight/runner.js +116 -0
- package/lib/project-discovery.js +0 -53
- package/lib/project-memory.js +166 -0
- package/lib/protected-path-manifest.js +281 -0
- package/lib/protected-state-surfaces.js +387 -0
- package/lib/release-readiness.js +2089 -0
- package/lib/reset.js +59 -45
- package/lib/review-adapter.js +68 -0
- package/lib/rules-sync.js +260 -0
- package/lib/runtime-health.js +332 -23
- package/lib/safety-config-renderer.js +268 -0
- package/lib/setup-action-log.js +1 -7
- package/lib/setup.js +27 -65
- package/lib/shell-utils.js +76 -6
- package/lib/skills-sync.js +330 -0
- package/lib/smart-status/conflicts.js +205 -0
- package/lib/smart-status/scoring.js +191 -0
- package/lib/status/beads-snapshot.js +145 -0
- package/lib/status/presenter.js +216 -0
- package/lib/status/snapshot.js +186 -0
- package/lib/sync-backend.js +202 -0
- package/lib/untrusted-content.js +52 -0
- package/lib/upgrade-safety.js +199 -0
- package/lib/workflow/enforce-stage.js +298 -47
- package/lib/workflow/stage-transition.js +115 -0
- package/lib/workflow/stages.js +30 -6
- package/lib/workflow/state-manager.js +159 -14
- package/lib/workflow/state.js +23 -1
- package/lib/workflow-profiles.js +17 -5
- package/package.json +46 -36
- package/rules/documentation.md +19 -0
- package/rules/kernel-tracking.md +26 -0
- package/rules/security.md +22 -0
- package/rules/tdd.md +20 -0
- package/rules/workflow.md +27 -0
- package/scripts/auto-backing-issue.js +47 -0
- package/scripts/beads-context.sh +165 -22
- package/scripts/beads-migrate-to-dolt.sh +7 -0
- package/scripts/beads-upgrade-smoke.sh +284 -0
- package/scripts/behavioral-judge.sh +115 -11
- package/scripts/benchmark.js +349 -63
- package/scripts/bootstrap-windows-tools.sh +78 -0
- package/scripts/branch-protection.js +2 -3
- package/scripts/check-agents.js +34 -137
- package/scripts/commitlint.js +3 -1
- package/scripts/conflict-detect.sh +3 -0
- package/scripts/dep-guard-analyze.js +52 -17
- package/scripts/dep-guard-keyword-ripple.js +29 -0
- package/scripts/dep-guard-render-review.js +86 -0
- package/scripts/dep-guard.sh +64 -232
- package/scripts/file-index.sh +3 -0
- package/scripts/forge-team/lib/claim.sh +34 -18
- package/scripts/forge-team/lib/dashboard.sh +61 -86
- package/scripts/forge-team/lib/epic.sh +99 -263
- package/scripts/forge-team/lib/hooks.sh +26 -28
- package/scripts/forge-team/lib/identity.sh +4 -4
- package/scripts/forge-team/lib/sync-github.sh +144 -47
- package/scripts/forge-team/lib/verify.sh +93 -83
- package/scripts/forge-team/lib/workload.sh +41 -65
- package/scripts/forge-team/tests/claim.test.sh +25 -19
- package/scripts/forge-team/tests/dashboard.test.sh +31 -46
- package/scripts/forge-team/tests/epic.test.sh +52 -71
- package/scripts/forge-team/tests/hooks.test.sh +38 -50
- package/scripts/forge-team/tests/identity.test.sh +3 -3
- package/scripts/forge-team/tests/integration.test.sh +44 -66
- package/scripts/forge-team/tests/sync-github.test.sh +183 -79
- package/scripts/forge-team/tests/verify.test.sh +37 -46
- package/scripts/forge-team/tests/workflow-integration.test.sh +4 -4
- package/scripts/forge-team/tests/workload.test.sh +32 -66
- package/scripts/gen-command-manifest.js +153 -0
- package/scripts/gen-embedded-assets.mjs +129 -0
- package/scripts/install.ps1 +139 -0
- package/scripts/install.sh +268 -0
- package/scripts/lib/beads-migrate-to-dolt.mjs +503 -0
- package/scripts/lib/release-asset.mjs +84 -0
- package/scripts/parity-check.mjs +145 -0
- package/scripts/parity-check.test.mjs +58 -0
- package/scripts/pin-agentic-workflow-images.js +112 -0
- package/scripts/pr-coordinator.sh +3 -0
- package/scripts/preflight-sonar.eslint.config.mjs +44 -0
- package/scripts/preflight.sh +108 -0
- package/scripts/protected-state-check.js +104 -0
- package/scripts/smart-status-score.js +31 -0
- package/scripts/smart-status-sessions.js +51 -0
- package/scripts/smart-status.sh +117 -369
- package/scripts/spikes/config-race-bench.js +111 -0
- package/scripts/spikes/harness-capability-matrix.js +13 -0
- package/scripts/spikes/patch-anchor-stability-bench.js +125 -0
- package/scripts/spikes/protected-path-manifest.js +20 -0
- package/scripts/spikes/skill-auto-invoke-parity.js +292 -0
- package/scripts/sync-agent-skills.js +62 -0
- package/scripts/sync-agentic-workflow.js +48 -0
- package/scripts/sync-utils.sh +3 -0
- package/scripts/test-ci-shard.js +251 -0
- package/scripts/test-dashboard.js +188 -52
- package/scripts/test-full-suite.js +186 -0
- package/scripts/test-profile.js +278 -0
- package/scripts/test.js +302 -28
- package/scripts/validate.js +143 -0
- package/scripts/validate.sh +18 -1
- package/skills/claim-safety/SKILL.md +102 -0
- package/skills/claim-safety/evals/evals.json +46 -0
- package/{.github/prompts/dev.prompt.md → skills/dev/SKILL.md} +46 -52
- package/skills/dev/evals/evals.json +50 -0
- package/skills/hermes-forge/SKILL.md +185 -0
- package/skills/hermes-forge/evals/evals.json +46 -0
- package/skills/issue-basics/SKILL.md +111 -0
- package/skills/issue-basics/evals/evals.json +46 -0
- package/skills/kernel/SKILL.md +166 -0
- package/skills/kernel/evals/evals.json +50 -0
- package/skills/memory/SKILL.md +102 -0
- package/skills/parallel-deep-research/SKILL.md +14 -11
- package/skills/parallel-deep-research/evals/evals.json +11 -27
- package/{.github/prompts/plan.prompt.md → skills/plan/SKILL.md} +134 -159
- package/skills/plan/evals/evals.json +42 -0
- package/skills/research/SKILL.md +195 -0
- package/skills/research/evals/evals.json +42 -0
- package/{.github/prompts/review.prompt.md → skills/review/SKILL.md} +98 -62
- package/skills/review/evals/evals.json +42 -0
- package/skills/rollback/SKILL.md +110 -0
- package/skills/rollback/evals/evals.json +46 -0
- package/skills/rollback/references/methods.md +204 -0
- package/{.cursor/commands/rollback.md → skills/rollback/references/workflow-integration.md} +10 -284
- package/skills/shepherd/SKILL.md +66 -0
- package/skills/shepherd/evals/evals.json +42 -0
- package/skills/ship/SKILL.md +251 -0
- package/skills/ship/evals/evals.json +42 -0
- package/skills/smith/SKILL.md +142 -0
- package/skills/smith/evals/evals.json +46 -0
- package/skills/smith/references/autonomy-and-gates.md +94 -0
- package/{.github/prompts/sonarcloud.prompt.md → skills/sonarcloud/SKILL.md} +14 -3
- package/skills/sonarcloud/evals/evals.json +46 -0
- package/skills/sonarcloud-analysis/SKILL.md +18 -13
- package/skills/sonarcloud-analysis/evals/evals.json +11 -15
- package/skills/status/SKILL.md +102 -0
- package/skills/status/evals/evals.json +50 -0
- package/skills/triage-ready/SKILL.md +121 -0
- package/skills/triage-ready/evals/evals.json +42 -0
- package/{.github/prompts/validate.prompt.md → skills/validate/SKILL.md} +52 -29
- package/skills/validate/evals/evals.json +42 -0
- package/skills/verify/SKILL.md +299 -0
- package/skills/verify/evals/evals.json +50 -0
- package/.claude/commands/dev.md +0 -345
- package/.claude/commands/plan.md +0 -566
- package/.claude/commands/premerge.md +0 -186
- package/.claude/commands/research.md +0 -42
- package/.claude/commands/review.md +0 -451
- package/.claude/commands/rollback.md +0 -721
- package/.claude/commands/ship.md +0 -213
- package/.claude/commands/sonarcloud.md +0 -152
- package/.claude/commands/status.md +0 -90
- package/.claude/commands/validate.md +0 -288
- package/.claude/commands/verify.md +0 -269
- package/.claude/rules/workflow.md +0 -121
- package/.cline/workflows/dev.md +0 -342
- package/.cline/workflows/plan.md +0 -563
- package/.cline/workflows/premerge.md +0 -183
- package/.cline/workflows/research.md +0 -39
- package/.cline/workflows/review.md +0 -448
- package/.cline/workflows/rollback.md +0 -718
- package/.cline/workflows/ship.md +0 -210
- package/.cline/workflows/sonarcloud.md +0 -146
- package/.cline/workflows/status.md +0 -87
- package/.cline/workflows/validate.md +0 -285
- package/.cline/workflows/verify.md +0 -266
- package/.codex/config.toml +0 -11
- package/.codex/skills/dev/SKILL.md +0 -345
- package/.codex/skills/plan/SKILL.md +0 -566
- package/.codex/skills/premerge/SKILL.md +0 -186
- package/.codex/skills/research/SKILL.md +0 -42
- package/.codex/skills/review/SKILL.md +0 -451
- package/.codex/skills/rollback/SKILL.md +0 -721
- package/.codex/skills/ship/SKILL.md +0 -213
- package/.codex/skills/sonarcloud/SKILL.md +0 -149
- package/.codex/skills/status/SKILL.md +0 -90
- package/.codex/skills/validate/SKILL.md +0 -288
- package/.codex/skills/verify/SKILL.md +0 -269
- package/.cursor/commands/dev.md +0 -342
- package/.cursor/commands/plan.md +0 -563
- package/.cursor/commands/premerge.md +0 -183
- package/.cursor/commands/research.md +0 -39
- package/.cursor/commands/review.md +0 -448
- package/.cursor/commands/ship.md +0 -210
- package/.cursor/commands/sonarcloud.md +0 -146
- package/.cursor/commands/status.md +0 -87
- package/.cursor/commands/validate.md +0 -285
- package/.cursor/commands/verify.md +0 -266
- package/.cursorrules +0 -149
- package/.github/prompts/premerge.prompt.md +0 -188
- package/.github/prompts/research.prompt.md +0 -44
- package/.github/prompts/rollback.prompt.md +0 -723
- package/.github/prompts/ship.prompt.md +0 -215
- package/.github/prompts/status.prompt.md +0 -92
- package/.github/prompts/verify.prompt.md +0 -271
- package/.github/workflows/beads-to-github.yml +0 -56
- package/.github/workflows/github-to-beads.yml +0 -97
- package/.kilocode/workflows/dev.md +0 -346
- package/.kilocode/workflows/plan.md +0 -567
- package/.kilocode/workflows/premerge.md +0 -187
- package/.kilocode/workflows/research.md +0 -43
- package/.kilocode/workflows/review.md +0 -452
- package/.kilocode/workflows/rollback.md +0 -722
- package/.kilocode/workflows/ship.md +0 -214
- package/.kilocode/workflows/sonarcloud.md +0 -150
- package/.kilocode/workflows/status.md +0 -91
- package/.kilocode/workflows/validate.md +0 -289
- package/.kilocode/workflows/verify.md +0 -270
- package/.opencode/commands/dev.md +0 -345
- package/.opencode/commands/plan.md +0 -566
- package/.opencode/commands/premerge.md +0 -186
- package/.opencode/commands/research.md +0 -42
- package/.opencode/commands/review.md +0 -451
- package/.opencode/commands/rollback.md +0 -721
- package/.opencode/commands/ship.md +0 -213
- package/.opencode/commands/sonarcloud.md +0 -149
- package/.opencode/commands/status.md +0 -90
- package/.opencode/commands/validate.md +0 -288
- package/.opencode/commands/verify.md +0 -269
- package/.roo/commands/dev.md +0 -346
- package/.roo/commands/plan.md +0 -567
- package/.roo/commands/premerge.md +0 -187
- package/.roo/commands/research.md +0 -43
- package/.roo/commands/review.md +0 -452
- package/.roo/commands/rollback.md +0 -722
- package/.roo/commands/ship.md +0 -214
- package/.roo/commands/sonarcloud.md +0 -150
- package/.roo/commands/status.md +0 -91
- package/.roo/commands/validate.md +0 -289
- package/.roo/commands/verify.md +0 -270
- package/docs/BEADS_GITHUB_SYNC.md +0 -255
- package/docs/GREPTILE_SETUP.md +0 -400
- package/docs/MANUAL_REVIEW_GUIDE.md +0 -106
- package/docs/SETUP.md +0 -663
- package/docs/VALIDATION.md +0 -363
- package/lib/agents/cline.plugin.json +0 -29
- package/lib/agents/copilot.plugin.json +0 -24
- package/lib/agents/kilocode.plugin.json +0 -22
- package/lib/agents/opencode.plugin.json +0 -23
- package/lib/agents/roo.plugin.json +0 -30
- package/lib/beads-health-check.js +0 -143
- package/lib/commands/commands-reset.js +0 -147
- package/opencode.json +0 -67
- package/scripts/beads-context.test.js +0 -567
- package/scripts/github-beads-sync/comment.mjs +0 -64
- package/scripts/github-beads-sync/config.mjs +0 -148
- package/scripts/github-beads-sync/github-api.mjs +0 -131
- package/scripts/github-beads-sync/index.mjs +0 -332
- package/scripts/github-beads-sync/label-mapper.mjs +0 -54
- package/scripts/github-beads-sync/mapping.mjs +0 -78
- package/scripts/github-beads-sync/reverse-sync-cli.mjs +0 -31
- package/scripts/github-beads-sync/reverse-sync.mjs +0 -138
- package/scripts/github-beads-sync/run-bd.mjs +0 -161
- package/scripts/github-beads-sync/sanitize.mjs +0 -121
- package/scripts/github-beads-sync.config.json +0 -26
- package/scripts/sync-commands.js +0 -600
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Static Command Manifest — GENERATED FILE, DO NOT EDIT.
|
|
3
|
+
*
|
|
4
|
+
* Regenerate with: node scripts/gen-command-manifest.js
|
|
5
|
+
* Drift is enforced by test/structural/command-manifest-drift.test.js.
|
|
6
|
+
*
|
|
7
|
+
* This module `require`s every command by a static relative path so
|
|
8
|
+
* `bun build --compile` can statically bundle the command graph. The registry
|
|
9
|
+
* (lib/commands/_registry.js) consumes `commands` as its fast, bundleable path
|
|
10
|
+
* and falls back to `fs.readdirSync` auto-discovery for dev/extension commands.
|
|
11
|
+
*
|
|
12
|
+
* @module commands/_manifest
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
'use strict';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @typedef {Object} ManifestEntry
|
|
19
|
+
* @property {string} file - Command filename (e.g. `status.js`)
|
|
20
|
+
* @property {import("./_registry").CommandModule} module - The required command module
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/** @type {ManifestEntry[]} */
|
|
24
|
+
const commands = [
|
|
25
|
+
{ file: "adapter.js", module: require("./adapter") },
|
|
26
|
+
{ file: "add.js", module: require("./add") },
|
|
27
|
+
{ file: "audit.js", module: require("./audit") },
|
|
28
|
+
{ file: "blocked.js", module: require("./blocked") },
|
|
29
|
+
{ file: "board.js", module: require("./board") },
|
|
30
|
+
{ file: "claim.js", module: require("./claim") },
|
|
31
|
+
{ file: "claims.js", module: require("./claims") },
|
|
32
|
+
{ file: "clean.js", module: require("./clean") },
|
|
33
|
+
{ file: "close.js", module: require("./close") },
|
|
34
|
+
{ file: "comment.js", module: require("./comment") },
|
|
35
|
+
{ file: "control.js", module: require("./control") },
|
|
36
|
+
{ file: "create.js", module: require("./create") },
|
|
37
|
+
{ file: "dev.js", module: require("./dev") },
|
|
38
|
+
{ file: "doc-gate.js", module: require("./doc-gate") },
|
|
39
|
+
{ file: "doctor.js", module: require("./doctor") },
|
|
40
|
+
{ file: "explain.js", module: require("./explain") },
|
|
41
|
+
{ file: "export.js", module: require("./export") },
|
|
42
|
+
{ file: "gate.js", module: require("./gate") },
|
|
43
|
+
{ file: "hooks.js", module: require("./hooks") },
|
|
44
|
+
{ file: "inbox.js", module: require("./inbox") },
|
|
45
|
+
{ file: "init.js", module: require("./init") },
|
|
46
|
+
{ file: "insights.js", module: require("./insights") },
|
|
47
|
+
{ file: "issue.js", module: require("./issue") },
|
|
48
|
+
{ file: "issues.js", module: require("./issues") },
|
|
49
|
+
{ file: "lint.js", module: require("./lint") },
|
|
50
|
+
{ file: "list.js", module: require("./list") },
|
|
51
|
+
{ file: "merge.js", module: require("./merge") },
|
|
52
|
+
{ file: "migrate.js", module: require("./migrate") },
|
|
53
|
+
{ file: "new.js", module: require("./new") },
|
|
54
|
+
{ file: "options.js", module: require("./options") },
|
|
55
|
+
{ file: "orient.js", module: require("./orient") },
|
|
56
|
+
{ file: "orphans.js", module: require("./orphans") },
|
|
57
|
+
{ file: "patch.js", module: require("./patch") },
|
|
58
|
+
{ file: "plan.js", module: require("./plan") },
|
|
59
|
+
{ file: "preflight.js", module: require("./preflight") },
|
|
60
|
+
{ file: "prime.js", module: require("./prime") },
|
|
61
|
+
{ file: "push.js", module: require("./push") },
|
|
62
|
+
{ file: "ready.js", module: require("./ready") },
|
|
63
|
+
{ file: "recall.js", module: require("./recall") },
|
|
64
|
+
{ file: "recap.js", module: require("./recap") },
|
|
65
|
+
{ file: "recommend.js", module: require("./recommend") },
|
|
66
|
+
{ file: "release.js", module: require("./release") },
|
|
67
|
+
{ file: "remember.js", module: require("./remember") },
|
|
68
|
+
{ file: "role.js", module: require("./role") },
|
|
69
|
+
{ file: "serve.js", module: require("./serve") },
|
|
70
|
+
{ file: "setup.js", module: require("./setup") },
|
|
71
|
+
{ file: "shepherd.js", module: require("./shepherd") },
|
|
72
|
+
{ file: "ship.js", module: require("./ship") },
|
|
73
|
+
{ file: "show.js", module: require("./show") },
|
|
74
|
+
{ file: "stage.js", module: require("./stage") },
|
|
75
|
+
{ file: "stale.js", module: require("./stale") },
|
|
76
|
+
{ file: "status.js", module: require("./status") },
|
|
77
|
+
{ file: "sync.js", module: require("./sync") },
|
|
78
|
+
{ file: "team.js", module: require("./team") },
|
|
79
|
+
{ file: "test.js", module: require("./test") },
|
|
80
|
+
{ file: "update.js", module: require("./update") },
|
|
81
|
+
{ file: "upgrade.js", module: require("./upgrade") },
|
|
82
|
+
{ file: "validate.js", module: require("./validate") },
|
|
83
|
+
{ file: "worktree.js", module: require("./worktree") },
|
|
84
|
+
];
|
|
85
|
+
|
|
86
|
+
module.exports = {
|
|
87
|
+
// Absolute path of the canonical commands directory this manifest describes.
|
|
88
|
+
// The registry applies the manifest only when asked to load this exact dir.
|
|
89
|
+
dir: __dirname,
|
|
90
|
+
commands,
|
|
91
|
+
};
|
|
@@ -13,11 +13,26 @@ const { existsSync, readdirSync } = require('node:fs');
|
|
|
13
13
|
const path = require('node:path');
|
|
14
14
|
const { normalizeStageId } = require('../workflow/stages');
|
|
15
15
|
|
|
16
|
+
// Static command manifest (bundleable fast path). This is a static require so
|
|
17
|
+
// `bun build --compile` can bundle the command graph; the file is generated by
|
|
18
|
+
// scripts/gen-command-manifest.js and drift-checked in test/structural. In a dev
|
|
19
|
+
// checkout before generation (or if removed) it may be absent — fall back to
|
|
20
|
+
// readdir auto-discovery below.
|
|
21
|
+
let STATIC_MANIFEST = null;
|
|
22
|
+
try {
|
|
23
|
+
STATIC_MANIFEST = require('./_manifest');
|
|
24
|
+
} catch (err) {
|
|
25
|
+
if (err.code !== 'MODULE_NOT_FOUND') {
|
|
26
|
+
console.warn(`[registry] Failed to load static manifest: ${err.message}`);
|
|
27
|
+
}
|
|
28
|
+
STATIC_MANIFEST = null;
|
|
29
|
+
}
|
|
30
|
+
|
|
16
31
|
/**
|
|
17
32
|
* @typedef {Object} CommandModule
|
|
18
33
|
* @property {string} name - Command name used for routing
|
|
19
34
|
* @property {string} description - Human-readable description
|
|
20
|
-
* @property {function(Array, Object, string): Promise<*>} handler - Async command handler
|
|
35
|
+
* @property {function(Array, Object, string, Object=): Promise<*>} handler - Async command handler (4th arg: resolved command opts)
|
|
21
36
|
* @property {string} [usage] - Usage string (optional)
|
|
22
37
|
* @property {Object<string, string>} [flags] - Flag descriptions (optional)
|
|
23
38
|
*/
|
|
@@ -57,46 +72,68 @@ function validateCommand(mod) {
|
|
|
57
72
|
* @param {string} commandsDir - Absolute path to the commands directory
|
|
58
73
|
* @returns {{ commands: Map<string, CommandModule>, getHelp: () => string }}
|
|
59
74
|
*/
|
|
60
|
-
function
|
|
61
|
-
|
|
62
|
-
|
|
75
|
+
function addCommand(commands, file, mod) {
|
|
76
|
+
const validation = validateCommand(mod);
|
|
77
|
+
if (!validation.valid) {
|
|
78
|
+
console.warn(`[registry] Skipping ${file}: ${validation.reason}`);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
63
81
|
|
|
64
|
-
if (
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
82
|
+
if (commands.has(mod.name)) {
|
|
83
|
+
console.warn(
|
|
84
|
+
`[registry] Skipping ${file}: duplicate command name "${mod.name}"`
|
|
85
|
+
);
|
|
86
|
+
return;
|
|
69
87
|
}
|
|
70
88
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
.sort(); // deterministic order — first file wins on duplicates
|
|
89
|
+
commands.set(mod.name, mod);
|
|
90
|
+
}
|
|
74
91
|
|
|
75
|
-
|
|
76
|
-
|
|
92
|
+
function loadCommands(commandsDir) {
|
|
93
|
+
/** @type {Map<string, CommandModule>} */
|
|
94
|
+
const commands = new Map();
|
|
77
95
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
96
|
+
// Files already contributed by the static manifest — skip re-requiring them
|
|
97
|
+
// during the readdir pass so they neither double-load nor warn as duplicates.
|
|
98
|
+
const seenFiles = new Set();
|
|
99
|
+
|
|
100
|
+
// 1) Static manifest fast path (bundleable). Applied only when the caller asks
|
|
101
|
+
// for the exact canonical commands dir the manifest describes; extension
|
|
102
|
+
// dirs fall through to readdir below. In a compiled binary there is no real
|
|
103
|
+
// commands dir on disk, so the manifest is the only path that resolves.
|
|
104
|
+
if (
|
|
105
|
+
STATIC_MANIFEST &&
|
|
106
|
+
Array.isArray(STATIC_MANIFEST.commands) &&
|
|
107
|
+
commandsDir &&
|
|
108
|
+
path.resolve(commandsDir) === path.resolve(STATIC_MANIFEST.dir)
|
|
109
|
+
) {
|
|
110
|
+
for (const entry of STATIC_MANIFEST.commands) {
|
|
111
|
+
seenFiles.add(entry.file);
|
|
112
|
+
addCommand(commands, entry.file, entry.module);
|
|
84
113
|
}
|
|
114
|
+
}
|
|
85
115
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
116
|
+
// 2) readdir auto-discovery (dev/extension fallback). Picks up command files
|
|
117
|
+
// not covered by the manifest — including brand-new files a developer or
|
|
118
|
+
// user drops in without regenerating the manifest — preserving extensibility.
|
|
119
|
+
if (commandsDir && existsSync(commandsDir)) {
|
|
120
|
+
const files = readdirSync(commandsDir)
|
|
121
|
+
.filter(f => f.endsWith('.js') && !f.startsWith('_'))
|
|
122
|
+
.sort(); // deterministic order — first file wins on duplicates
|
|
123
|
+
|
|
124
|
+
for (const file of files) {
|
|
125
|
+
if (seenFiles.has(file)) continue;
|
|
126
|
+
|
|
127
|
+
let mod;
|
|
128
|
+
try {
|
|
129
|
+
mod = require(path.join(commandsDir, file));
|
|
130
|
+
} catch (_err) {
|
|
131
|
+
console.warn(`[registry] Skipping ${file}: failed to load — ${_err.message}`);
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
91
134
|
|
|
92
|
-
|
|
93
|
-
console.warn(
|
|
94
|
-
`[registry] Skipping ${file}: duplicate command name "${mod.name}"`
|
|
95
|
-
);
|
|
96
|
-
continue;
|
|
135
|
+
addCommand(commands, file, mod);
|
|
97
136
|
}
|
|
98
|
-
|
|
99
|
-
commands.set(mod.name, mod);
|
|
100
137
|
}
|
|
101
138
|
|
|
102
139
|
return {
|
|
@@ -143,8 +180,9 @@ async function executeCommand(commands, commandName, args, flags, projectRoot, o
|
|
|
143
180
|
}
|
|
144
181
|
|
|
145
182
|
try {
|
|
183
|
+
let enforcement = null;
|
|
146
184
|
if (typeof options.enforceStage === 'function' && isStageCommand(commandName)) {
|
|
147
|
-
|
|
185
|
+
enforcement = await options.enforceStage({
|
|
148
186
|
commandName,
|
|
149
187
|
args,
|
|
150
188
|
flags,
|
|
@@ -161,7 +199,20 @@ async function executeCommand(commands, commandName, args, flags, projectRoot, o
|
|
|
161
199
|
}
|
|
162
200
|
}
|
|
163
201
|
|
|
164
|
-
|
|
202
|
+
// Forward a resolved per-command opts object as the handler's 4th arg. Issue/
|
|
203
|
+
// alias handlers read it (shouldUseKernelBroker(opts)); other handlers ignore
|
|
204
|
+
// it. Backward-compatible: defaults to {} so existing 3-arg handlers are
|
|
205
|
+
// unaffected.
|
|
206
|
+
const result = await command.handler(args, flags, projectRoot, options.commandOpts ?? {});
|
|
207
|
+
|
|
208
|
+
// Record stage COMPLETION into the kernel only when the command SUCCEEDED, so
|
|
209
|
+
// a stage counts as 'done' (which gates ship/review) only when its command
|
|
210
|
+
// actually passed — not merely when it was entered.
|
|
211
|
+
if (result?.success !== false && typeof enforcement?.recordCompletion === 'function') {
|
|
212
|
+
enforcement.recordCompletion();
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return result;
|
|
165
216
|
} catch (err) {
|
|
166
217
|
return {
|
|
167
218
|
success: false,
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Resolve the per-command opts object that bin/forge.js threads to the registry
|
|
5
|
+
* handler (the 4th arg). For issue/alias commands this:
|
|
6
|
+
*
|
|
7
|
+
* 1. Strips the selector tokens (`--kernel`, `--issue-backend <val>`) from the
|
|
8
|
+
* args BEFORE they reach the handler / bd. This is load-bearing: bin
|
|
9
|
+
* parseFlags() early-returns for issue passthrough commands, so these tokens
|
|
10
|
+
* otherwise flow untouched into the handler and (beads path) into bd, which
|
|
11
|
+
* rejects the unknown flag — and the positional `kernel`/`beads` value would
|
|
12
|
+
* be mistaken for an issue id.
|
|
13
|
+
* 2. Resolves the backend (flag > env > config > default) via the backend
|
|
14
|
+
* authority module (lib/issue-backend.js). The CLI flag tokens are mapped to
|
|
15
|
+
* that module's `deps.issueBackend` signal; env/config/default precedence is
|
|
16
|
+
* applied by the resolver itself.
|
|
17
|
+
* 3. When kernel, assembles the kernel deps (driver + flag) via the CLI broker
|
|
18
|
+
* factory so createKernelIssueBackend has a real driver (B1).
|
|
19
|
+
*
|
|
20
|
+
* Kernel-native tool commands (KERNEL_TOOL_COMMANDS, e.g. `export`) instead get a
|
|
21
|
+
* migrated Kernel broker injected as `_broker` (independent of the selector), and
|
|
22
|
+
* all other non-issue commands get an empty opts object and untouched args.
|
|
23
|
+
*
|
|
24
|
+
* @module commands/resolve-command-opts
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
const { resolveIssueBackend } = require('../issue-backend');
|
|
28
|
+
const {
|
|
29
|
+
buildMigratedKernelIssueDeps: defaultBuildKernelIssueDeps,
|
|
30
|
+
} = require('../kernel/cli-broker-factory');
|
|
31
|
+
|
|
32
|
+
// Commands that route issue operations and therefore honor the selector. Mirrors
|
|
33
|
+
// the alias wrappers in lib/commands/ plus the `issue`/`issues` grouping commands.
|
|
34
|
+
const ISSUE_COMMANDS = new Set([
|
|
35
|
+
'create',
|
|
36
|
+
'update',
|
|
37
|
+
'claim',
|
|
38
|
+
'release',
|
|
39
|
+
'comment',
|
|
40
|
+
'close',
|
|
41
|
+
'show',
|
|
42
|
+
'list',
|
|
43
|
+
'ready',
|
|
44
|
+
'blocked',
|
|
45
|
+
'stale',
|
|
46
|
+
'orphans',
|
|
47
|
+
'lint',
|
|
48
|
+
// Epic grouping read — must be kernel-routed (its issue.children rollup has no
|
|
49
|
+
// verified Beads equivalent), so it belongs in ISSUE_COMMANDS like the rest.
|
|
50
|
+
'children',
|
|
51
|
+
// Lease-ownership verification — a kernel-only read (leases live in the Kernel),
|
|
52
|
+
// so it is kernel-routed like the rest of the issue surface.
|
|
53
|
+
'owns',
|
|
54
|
+
// Active-lease listing — a kernel-only read (leases live in the Kernel), so it
|
|
55
|
+
// is kernel-routed like the rest of the issue surface.
|
|
56
|
+
'claims',
|
|
57
|
+
'search',
|
|
58
|
+
'stats',
|
|
59
|
+
'dep',
|
|
60
|
+
'issue',
|
|
61
|
+
'issues',
|
|
62
|
+
]);
|
|
63
|
+
|
|
64
|
+
// Kernel-native tool commands that operate directly on the Kernel regardless of the
|
|
65
|
+
// issue-backend selector, so they need a real (migrated) Kernel broker injected as
|
|
66
|
+
// the handler's `_broker`. `export` drains the Kernel projection outbox to
|
|
67
|
+
// git-tracked JSONL (D16); without an injected broker its handler always reports
|
|
68
|
+
// "No Kernel broker available" and writes nothing.
|
|
69
|
+
const KERNEL_TOOL_COMMANDS = new Set([
|
|
70
|
+
'export',
|
|
71
|
+
]);
|
|
72
|
+
|
|
73
|
+
const ISSUE_BACKEND_FLAG = '--issue-backend';
|
|
74
|
+
const KERNEL_FLAG = '--kernel';
|
|
75
|
+
const KERNEL = 'kernel';
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Remove the issue-backend selector tokens from an args array and report what
|
|
79
|
+
* they selected. Handles `--kernel`, `--issue-backend <val>` (space form), and
|
|
80
|
+
* `--issue-backend=<val>` (= form). All other tokens pass through unchanged.
|
|
81
|
+
*
|
|
82
|
+
* @param {string[]} rawArgs
|
|
83
|
+
* @returns {{ args: string[], flags: { kernel?: boolean, issueBackend?: string } }}
|
|
84
|
+
*/
|
|
85
|
+
function stripSelectorTokens(rawArgs = []) {
|
|
86
|
+
const args = [];
|
|
87
|
+
const flags = {};
|
|
88
|
+
for (let i = 0; i < rawArgs.length; i += 1) {
|
|
89
|
+
const token = rawArgs[i];
|
|
90
|
+
if (token === KERNEL_FLAG) {
|
|
91
|
+
flags.kernel = true;
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
if (token === ISSUE_BACKEND_FLAG) {
|
|
95
|
+
// Space form: consume the following value token as the backend name. Only a
|
|
96
|
+
// non-flag token counts — a missing value or a following flag (e.g.
|
|
97
|
+
// `--issue-backend --reason=x`) must throw rather than silently swallow the
|
|
98
|
+
// next flag and fall back to the default backend.
|
|
99
|
+
const next = rawArgs[i + 1];
|
|
100
|
+
if (typeof next === 'string' && !next.startsWith('--')) {
|
|
101
|
+
flags.issueBackend = next;
|
|
102
|
+
i += 1;
|
|
103
|
+
} else {
|
|
104
|
+
throw new Error(`${ISSUE_BACKEND_FLAG} requires a value: kernel or beads.`);
|
|
105
|
+
}
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
if (typeof token === 'string' && token.startsWith(`${ISSUE_BACKEND_FLAG}=`)) {
|
|
109
|
+
// Equals form: reject an empty value (`--issue-backend=`) for the same reason.
|
|
110
|
+
const value = token.slice(ISSUE_BACKEND_FLAG.length + 1).trim();
|
|
111
|
+
if (!value) {
|
|
112
|
+
throw new Error(`${ISSUE_BACKEND_FLAG} requires a value: kernel or beads.`);
|
|
113
|
+
}
|
|
114
|
+
flags.issueBackend = value;
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
args.push(token);
|
|
118
|
+
}
|
|
119
|
+
return { args, flags };
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Reduce the stripped selector flags to a single explicit backend value (or null
|
|
124
|
+
* when no flag selects one), honoring `--kernel` / `--issue-backend` equivalence
|
|
125
|
+
* and rejecting a mutually-exclusive conflict. Returned values are NOT validated
|
|
126
|
+
* here — the backend authority module normalizes/warns on unknown values.
|
|
127
|
+
*
|
|
128
|
+
* @param {{ kernel?: boolean, issueBackend?: string }} flags
|
|
129
|
+
* @returns {string|null}
|
|
130
|
+
* @throws {Error} when --kernel and --issue-backend select different backends.
|
|
131
|
+
*/
|
|
132
|
+
function resolveFlagBackend(flags = {}) {
|
|
133
|
+
const fromBackend = typeof flags.issueBackend === 'string' && flags.issueBackend.trim()
|
|
134
|
+
? flags.issueBackend.trim()
|
|
135
|
+
: null;
|
|
136
|
+
const fromKernel = flags.kernel === true ? KERNEL : null;
|
|
137
|
+
|
|
138
|
+
if (fromKernel && fromBackend && fromKernel !== fromBackend.toLowerCase()) {
|
|
139
|
+
throw new Error(
|
|
140
|
+
`Conflicting issue backend flags: --kernel selects '${KERNEL}' but `
|
|
141
|
+
+ `--issue-backend selects '${fromBackend}'. These are mutually exclusive.`,
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return fromKernel || fromBackend || null;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Run the first-use Beads import safety net for a kernel-routed command. Resolving the
|
|
149
|
+
// migrate module lives INSIDE the try so even a require() failure (missing/corrupt
|
|
150
|
+
// module) can never break command-opts resolution — the whole point of the safety net.
|
|
151
|
+
// Shared by both kernel branches (issue + KERNEL_TOOL_COMMANDS) so the two call sites
|
|
152
|
+
// cannot drift.
|
|
153
|
+
async function runRuntimeAutoMigrate(deps, kernelDeps) {
|
|
154
|
+
try {
|
|
155
|
+
const autoMigrate = deps.autoMigrateBeadsAtRuntime
|
|
156
|
+
|| require('./migrate').autoMigrateBeadsAtRuntime;
|
|
157
|
+
await autoMigrate({
|
|
158
|
+
projectRoot: deps.projectRoot,
|
|
159
|
+
databasePath: kernelDeps.kernelDatabasePath,
|
|
160
|
+
broker: kernelDeps.kernelBroker,
|
|
161
|
+
driver: kernelDeps.kernelDriver,
|
|
162
|
+
});
|
|
163
|
+
} catch {
|
|
164
|
+
// A migration-hook failure (including a require() failure) must never break the
|
|
165
|
+
// command it rides on.
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Resolve the command opts and selector-stripped args for a dispatched command.
|
|
171
|
+
*
|
|
172
|
+
* @param {string} command - The command name (e.g. 'close').
|
|
173
|
+
* @param {string[]} rawArgs - The command args (already `args.slice(1)`).
|
|
174
|
+
* @param {Object} [deps]
|
|
175
|
+
* @param {Object} [deps.env] - Environment snapshot (default process.env).
|
|
176
|
+
* @param {string} [deps.projectRoot] - Repo root for env/config resolution + kernel DB.
|
|
177
|
+
* @param {Function} [deps.buildKernelIssueDeps] - Factory override (tests). May be
|
|
178
|
+
* sync or async; its result is awaited.
|
|
179
|
+
* @returns {Promise<{ commandOpts: Object, args: string[] }>}
|
|
180
|
+
* @throws {Error} on conflicting flags (surfaced to user).
|
|
181
|
+
*/
|
|
182
|
+
async function resolveCommandOpts(command, rawArgs = [], deps = {}) {
|
|
183
|
+
const buildKernelIssueDeps = deps.buildKernelIssueDeps || defaultBuildKernelIssueDeps;
|
|
184
|
+
|
|
185
|
+
if (KERNEL_TOOL_COMMANDS.has(command)) {
|
|
186
|
+
// Kernel-native tools (e.g. `export`) always get a migrated Kernel broker the
|
|
187
|
+
// same way issue commands do (the CLI broker factory builds the driver, builds
|
|
188
|
+
// the broker, and runs initialize()). The handler consumes it as `_broker`.
|
|
189
|
+
// If no broker can be built (e.g. no SQLite runtime) we fall through with no
|
|
190
|
+
// broker so the handler skips gracefully rather than hard-failing — these tools
|
|
191
|
+
// are explicitly non-fatal when the Kernel is unavailable.
|
|
192
|
+
try {
|
|
193
|
+
const kernelDeps = await buildKernelIssueDeps({
|
|
194
|
+
projectRoot: deps.projectRoot,
|
|
195
|
+
databasePath: deps.databasePath,
|
|
196
|
+
gitCommonDir: deps.gitCommonDir,
|
|
197
|
+
});
|
|
198
|
+
// Same first-use safety net as the issue branch: an export-first upgrader would
|
|
199
|
+
// otherwise drain an EMPTY kernel and never trigger the one-time Beads import.
|
|
200
|
+
await runRuntimeAutoMigrate(deps, kernelDeps);
|
|
201
|
+
return { commandOpts: { _broker: kernelDeps.kernelBroker }, args: rawArgs };
|
|
202
|
+
} catch {
|
|
203
|
+
return { commandOpts: {}, args: rawArgs };
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
if (!ISSUE_COMMANDS.has(command)) {
|
|
208
|
+
return { commandOpts: {}, args: rawArgs };
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const env = deps.env || process.env;
|
|
212
|
+
|
|
213
|
+
const { args, flags } = stripSelectorTokens(rawArgs);
|
|
214
|
+
const flagBackend = resolveFlagBackend(flags);
|
|
215
|
+
const issueBackend = resolveIssueBackend({
|
|
216
|
+
deps: flagBackend ? { issueBackend: flagBackend } : {},
|
|
217
|
+
env,
|
|
218
|
+
projectRoot: deps.projectRoot,
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
if (issueBackend !== KERNEL) {
|
|
222
|
+
return {
|
|
223
|
+
commandOpts: {
|
|
224
|
+
issueBackend,
|
|
225
|
+
useKernelBroker: false,
|
|
226
|
+
},
|
|
227
|
+
args,
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Kernel backend: assemble the driver (B1) + migrated broker (B2). The factory
|
|
232
|
+
// builder constructs the driver, builds the broker, and runs initialize().
|
|
233
|
+
const kernelDeps = await buildKernelIssueDeps({
|
|
234
|
+
projectRoot: deps.projectRoot,
|
|
235
|
+
databasePath: deps.databasePath,
|
|
236
|
+
gitCommonDir: deps.gitCommonDir,
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
// Safety net: the kernel is the default backend, but onboarding auto-migrate runs
|
|
240
|
+
// only from `forge setup`/`init`. An existing repo whose user merely upgrades forge
|
|
241
|
+
// would read an EMPTY kernel here and their existing Beads issues would appear to
|
|
242
|
+
// vanish. Import them ONCE on first kernel use (idempotent, gated by an in-DB marker
|
|
243
|
+
// that shares the kernel DB lifecycle, stderr only).
|
|
244
|
+
await runRuntimeAutoMigrate(deps, kernelDeps);
|
|
245
|
+
|
|
246
|
+
return {
|
|
247
|
+
commandOpts: {
|
|
248
|
+
issueBackend: KERNEL,
|
|
249
|
+
...kernelDeps,
|
|
250
|
+
},
|
|
251
|
+
args,
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
module.exports = {
|
|
256
|
+
resolveCommandOpts,
|
|
257
|
+
stripSelectorTokens,
|
|
258
|
+
resolveFlagBackend,
|
|
259
|
+
ISSUE_COMMANDS,
|
|
260
|
+
KERNEL_TOOL_COMMANDS,
|
|
261
|
+
};
|