forge-workflow 0.0.10 → 0.1.0-beta.3
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 +82 -5
- package/.forge/hooks/forge-native-hook.js +431 -0
- package/.forge/protected-paths.yaml +157 -0
- package/AGENTS.md +151 -61
- package/CHANGELOG.md +709 -0
- package/CLAUDE.md +9 -118
- package/QUICKSTART.md +175 -0
- package/README.md +275 -365
- package/bin/forge-cmd.js +120 -9
- package/bin/forge-preflight.js +26 -5
- package/bin/forge.js +532 -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/forge/TOOLCHAIN.md +670 -0
- 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 +121 -0
- package/docs/guides/SUPPORT.md +190 -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 +214 -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/{TOOLCHAIN.md → reference/TOOLCHAIN.md} +62 -47
- 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 +155 -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/activation/ensure-forge-home.js +135 -0
- package/lib/adapter-cli.js +307 -0
- package/lib/adapters/beads-issue-adapter.js +127 -0
- package/lib/adapters/beads-kernel-compat.js +1109 -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 +139 -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-detect.js +60 -0
- package/lib/beads-nudge.js +91 -0
- package/lib/beads-setup.js +121 -0
- package/lib/beads-sync-scaffold.js +25 -101
- package/lib/codex-skills.js +51 -1
- package/lib/commands/_aliases.js +248 -0
- package/lib/commands/_issue.js +780 -77
- package/lib/commands/_manifest.js +93 -0
- package/lib/commands/_registry.js +99 -34
- package/lib/commands/_resolve-command-opts.js +230 -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 +209 -0
- package/lib/commands/hooks.js +377 -0
- package/lib/commands/inbox.js +118 -0
- package/lib/commands/init.js +604 -0
- package/lib/commands/insights.js +79 -0
- package/lib/commands/issue.js +12 -1
- package/lib/commands/issues.js +17 -0
- package/lib/commands/lint.js +5 -0
- package/lib/commands/list.js +2 -2
- package/lib/commands/memory.js +81 -0
- package/lib/commands/merge.js +312 -0
- package/lib/commands/migrate.js +362 -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 +481 -29
- package/lib/commands/pr.js +88 -0
- package/lib/commands/preflight.js +211 -0
- package/lib/commands/prime.js +13 -0
- package/lib/commands/push.js +135 -2
- package/lib/commands/ready.js +2 -2
- package/lib/commands/recall.js +171 -0
- package/lib/commands/recap.js +75 -0
- package/lib/commands/recommend.js +0 -1
- package/lib/commands/release.js +104 -0
- package/lib/commands/remember.js +140 -0
- package/lib/commands/role.js +99 -0
- package/lib/commands/serve.js +581 -0
- package/lib/commands/setup.js +900 -971
- package/lib/commands/shepherd.js +501 -0
- package/lib/commands/ship.js +59 -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 +158 -21
- package/lib/commands/sync.js +34 -46
- package/lib/commands/team.js +4 -1
- package/lib/commands/test.js +43 -27
- package/lib/commands/update.js +2 -2
- package/lib/commands/upgrade.js +47 -0
- package/lib/commands/validate.js +43 -18
- package/lib/commands/worktree.js +362 -99
- package/lib/config-writer.js +202 -0
- package/lib/control-plane.js +236 -0
- package/lib/core/runtime-graph.js +977 -0
- package/lib/dep-guard/keyword-ripple.js +2 -2
- package/lib/deprecated-sync-cleanup.js +362 -0
- package/lib/detect-agent.js +2 -28
- package/lib/detect-worktree.js +35 -9
- 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 +382 -11
- package/lib/forge-lock.js +262 -0
- package/lib/gate-events.js +192 -0
- package/lib/global-flags.js +104 -0
- package/lib/greptile-match.js +7 -63
- package/lib/grounding/context-events.js +230 -0
- package/lib/grounding/read-first.js +112 -0
- package/lib/harness-capability-matrix.js +380 -0
- package/lib/hook-global-installer.js +347 -0
- package/lib/hook-renderer.js +541 -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/kernel/backing-issue.js +311 -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/owned-kernel.js +43 -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 +2540 -0
- package/lib/kernel/taxonomy-validator.js +394 -0
- package/lib/lefthook-check.js +3 -2
- 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/auto-actions.js +175 -0
- package/lib/pr-monitor/differ.js +195 -0
- package/lib/pr-monitor/digest.js +206 -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 +192 -0
- package/lib/pr-monitor/upsert-sticky.js +169 -0
- package/lib/pr-monitor/watch-lifecycle.js +95 -0
- package/lib/pr-monitor/watch.js +247 -0
- package/lib/pr-pull.js +1314 -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 +99 -497
- package/lib/protected-path-manifest.js +281 -0
- package/lib/protected-state-surfaces.js +387 -0
- package/lib/release-readiness.js +2105 -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 +241 -20
- 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/scoring.js +17 -3
- package/lib/status/beads-snapshot.js +45 -2
- package/lib/status/presenter.js +169 -18
- 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 +251 -0
- package/lib/workflow/enforce-stage.js +351 -45
- package/lib/workflow/stage-transition.js +115 -0
- package/lib/workflow/stages.js +30 -6
- package/lib/workflow/state-manager.js +11 -22
- package/lib/workflow/state.js +23 -1
- package/lib/workflow-profiles.js +17 -5
- package/package.json +37 -35
- 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 +81 -57
- package/scripts/beads-upgrade-smoke.sh +24 -3
- 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.sh +22 -3
- 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 +49 -84
- 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 +50 -83
- 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/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-auto-actions.js +93 -0
- package/scripts/pr-coordinator.sh +3 -0
- package/scripts/pr-verdict-label.js +50 -0
- package/scripts/preflight-sonar.eslint.config.mjs +44 -0
- package/scripts/preflight.sh +21 -94
- package/scripts/protected-state-check.js +104 -0
- package/scripts/smart-status.sh +60 -57
- 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-utils.sh +3 -0
- package/scripts/test-ci-shard.js +13 -6
- package/scripts/test.js +95 -12
- 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} +44 -50
- 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} +132 -157
- 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/{.github/prompts/ship.prompt.md → skills/ship/SKILL.md} +81 -45
- 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/{.github/prompts/status.prompt.md → skills/status/SKILL.md} +20 -10
- 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/verify.prompt.md +0 -271
- package/.github/workflows/beads-to-github.yml +0 -89
- package/.github/workflows/github-to-beads.yml +0 -100
- 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 -281
- 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-bootstrap.js +0 -225
- package/lib/beads-health-check.js +0 -188
- package/lib/commands/commands-reset.js +0 -147
- package/opencode.json +0 -67
- package/scripts/beads-context.test.js +0 -584
- 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 -356
- package/scripts/github-beads-sync/label-mapper.mjs +0 -54
- package/scripts/github-beads-sync/mapping.mjs +0 -132
- package/scripts/github-beads-sync/reverse-sync-cli.mjs +0 -31
- package/scripts/github-beads-sync/reverse-sync.mjs +0 -162
- 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
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
const fs = require('node:fs');
|
|
4
4
|
const path = require('node:path');
|
|
5
5
|
const { execFileSync } = require('node:child_process');
|
|
6
|
+
const { cleanupDeprecatedSyncFiles } = require('./deprecated-sync-cleanup');
|
|
6
7
|
|
|
7
8
|
const DEFAULT_BEADS_VERSION = '1.0.0';
|
|
8
9
|
|
|
@@ -141,119 +142,41 @@ function templateWorkflows(workflowDir, branch, beadsVersion, createdFiles = [])
|
|
|
141
142
|
}
|
|
142
143
|
}
|
|
143
144
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
* @property {string[]} filesSkipped - Relative paths of files that already existed and were preserved
|
|
148
|
-
*/
|
|
145
|
+
function cleanupDeprecatedBeadsSync(projectRoot, options = {}) {
|
|
146
|
+
return cleanupDeprecatedSyncFiles(projectRoot, options);
|
|
147
|
+
}
|
|
149
148
|
|
|
150
149
|
/**
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
* @
|
|
154
|
-
* @
|
|
155
|
-
* @
|
|
150
|
+
* @typedef {Object} ScaffoldResult
|
|
151
|
+
* @property {string[]} filesCreated - Always empty; retained for deprecated API compatibility.
|
|
152
|
+
* @property {string[]} filesSkipped - Always empty; retained for deprecated API compatibility.
|
|
153
|
+
* @property {string[]} filesRemoved - Relative paths of deprecated generated sync files removed.
|
|
154
|
+
* @property {boolean} deprecated - Indicates the legacy scaffold path is deprecated.
|
|
155
|
+
* @property {string} message - Deprecation guidance for future sync direction.
|
|
156
156
|
*/
|
|
157
|
-
function copyFileWithDirs(src, dest) {
|
|
158
|
-
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
159
|
-
fs.copyFileSync(src, dest);
|
|
160
|
-
}
|
|
161
157
|
|
|
162
158
|
/**
|
|
163
|
-
*
|
|
159
|
+
* Deprecated compatibility shim for removed Beads/GitHub sync scaffolding.
|
|
164
160
|
*
|
|
165
|
-
*
|
|
166
|
-
*
|
|
161
|
+
* Performs cleanup of generated legacy sync artifacts only. User-owned files
|
|
162
|
+
* at matching paths are preserved unless their content matches known generated
|
|
163
|
+
* templates.
|
|
167
164
|
*
|
|
168
165
|
* @param {string} projectRoot - Absolute path to the user's project root
|
|
169
166
|
* @param {string} packageDir - Absolute path to the forge package install location
|
|
170
167
|
* @param {Object} [_options={}] - Reserved for future options
|
|
171
|
-
* @returns {ScaffoldResult}
|
|
168
|
+
* @returns {ScaffoldResult} Deprecated cleanup result.
|
|
172
169
|
*/
|
|
173
170
|
function scaffoldBeadsSync(projectRoot, packageDir, _options = {}) {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
const srcWorkflowsDir = path.join(packageDir, '.github', 'workflows');
|
|
184
|
-
|
|
185
|
-
for (const name of workflowNames) {
|
|
186
|
-
const src = path.join(srcWorkflowsDir, name);
|
|
187
|
-
const relPath = `.github/workflows/${name}`;
|
|
188
|
-
const dest = path.join(projectRoot, '.github', 'workflows', name);
|
|
189
|
-
|
|
190
|
-
if (!fs.existsSync(src)) continue;
|
|
191
|
-
if (fs.existsSync(dest)) {
|
|
192
|
-
filesSkipped.push(relPath);
|
|
193
|
-
} else {
|
|
194
|
-
copyFileWithDirs(src, dest);
|
|
195
|
-
filesCreated.push(relPath);
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
// --- Step b: Copy sync modules ---
|
|
200
|
-
const srcSyncDir = path.join(packageDir, 'scripts', 'github-beads-sync');
|
|
201
|
-
const destSyncDir = path.join(githubDir, 'scripts', 'beads-sync');
|
|
202
|
-
|
|
203
|
-
if (fs.existsSync(srcSyncDir)) {
|
|
204
|
-
const entries = fs.readdirSync(srcSyncDir);
|
|
205
|
-
for (const entry of entries) {
|
|
206
|
-
const srcFile = path.join(srcSyncDir, entry);
|
|
207
|
-
const stat = fs.statSync(srcFile);
|
|
208
|
-
if (stat.isFile()) {
|
|
209
|
-
const relPath = `.github/scripts/beads-sync/${entry}`;
|
|
210
|
-
const dest = path.join(destSyncDir, entry);
|
|
211
|
-
if (fs.existsSync(dest)) {
|
|
212
|
-
filesSkipped.push(relPath);
|
|
213
|
-
} else {
|
|
214
|
-
copyFileWithDirs(srcFile, dest);
|
|
215
|
-
filesCreated.push(relPath);
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
// --- Step c: Create beads-sync-config.json ---
|
|
222
|
-
const configRelPath = '.github/beads-sync-config.json';
|
|
223
|
-
const configDest = path.join(githubDir, 'beads-sync-config.json');
|
|
224
|
-
const srcConfig = path.join(packageDir, 'scripts', 'github-beads-sync.config.json');
|
|
225
|
-
|
|
226
|
-
if (fs.existsSync(configDest)) {
|
|
227
|
-
filesSkipped.push(configRelPath);
|
|
228
|
-
} else if (fs.existsSync(srcConfig)) {
|
|
229
|
-
copyFileWithDirs(srcConfig, configDest);
|
|
230
|
-
filesCreated.push(configRelPath);
|
|
231
|
-
} else {
|
|
232
|
-
// Create a sensible default config
|
|
233
|
-
const defaultConfig = {
|
|
234
|
-
defaultType: 'task',
|
|
235
|
-
defaultPriority: 2,
|
|
236
|
-
mapAssignee: true,
|
|
237
|
-
publicRepoGate: 'none'
|
|
238
|
-
};
|
|
239
|
-
fs.mkdirSync(path.dirname(configDest), { recursive: true });
|
|
240
|
-
fs.writeFileSync(configDest, JSON.stringify(defaultConfig, null, 2) + '\n');
|
|
241
|
-
filesCreated.push(configRelPath);
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
// --- Step d: Create beads-mapping.json if not exists ---
|
|
245
|
-
const mappingRelPath = '.github/beads-mapping.json';
|
|
246
|
-
const mappingDest = path.join(githubDir, 'beads-mapping.json');
|
|
247
|
-
|
|
248
|
-
if (fs.existsSync(mappingDest)) {
|
|
249
|
-
filesSkipped.push(mappingRelPath);
|
|
250
|
-
} else {
|
|
251
|
-
fs.mkdirSync(path.dirname(mappingDest), { recursive: true });
|
|
252
|
-
fs.writeFileSync(mappingDest, '{}');
|
|
253
|
-
filesCreated.push(mappingRelPath);
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
return { filesCreated, filesSkipped };
|
|
171
|
+
const cleanup = cleanupDeprecatedBeadsSync(projectRoot, { packageDir });
|
|
172
|
+
|
|
173
|
+
return {
|
|
174
|
+
filesCreated: [],
|
|
175
|
+
filesSkipped: [],
|
|
176
|
+
filesRemoved: cleanup.removed,
|
|
177
|
+
deprecated: true,
|
|
178
|
+
message: 'Beads GitHub sync scaffolding is deprecated; future GitHub issue sync must use Forge Kernel/server authority.'
|
|
179
|
+
};
|
|
257
180
|
}
|
|
258
181
|
|
|
259
182
|
module.exports = {
|
|
@@ -261,5 +184,6 @@ module.exports = {
|
|
|
261
184
|
detectDefaultBranch,
|
|
262
185
|
detectBeadsVersion,
|
|
263
186
|
templateWorkflows,
|
|
187
|
+
cleanupDeprecatedBeadsSync,
|
|
264
188
|
scaffoldBeadsSync,
|
|
265
189
|
};
|
package/lib/codex-skills.js
CHANGED
|
@@ -2,6 +2,19 @@ const fs = require('node:fs');
|
|
|
2
2
|
const os = require('node:os');
|
|
3
3
|
const path = require('node:path');
|
|
4
4
|
|
|
5
|
+
const { populateAgentSkills } = require('./skills-sync');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Codex's documented repo-local skill discovery directory, relative to a project
|
|
9
|
+
* root. Codex scans `.agents/skills/<name>/SKILL.md` from the current working
|
|
10
|
+
* directory up to the repo root (developers.openai.com/codex/skills). Unlike the
|
|
11
|
+
* GLOBAL `$CODEX_HOME/skills` install, this surface is COMMITTED to the repo (kept
|
|
12
|
+
* byte-identical to the canonical `skills/` source by a pre-commit sync hook and
|
|
13
|
+
* the drift gate), so a teammate who clones the repo WITHOUT running `forge setup`
|
|
14
|
+
* still gets the Forge skills/stages auto-discovered.
|
|
15
|
+
*/
|
|
16
|
+
const CODEX_REPO_SKILLS_DIR = '.agents/skills';
|
|
17
|
+
|
|
5
18
|
function injectForgeAdapter(content, commandName) {
|
|
6
19
|
const adapter = [
|
|
7
20
|
'> Forge stage adapter',
|
|
@@ -20,7 +33,10 @@ function injectForgeAdapter(content, commandName) {
|
|
|
20
33
|
}
|
|
21
34
|
|
|
22
35
|
function listCodexSkillEntries(sourceRoot) {
|
|
23
|
-
|
|
36
|
+
// Read from the canonical `skills/` source (single source of truth) rather than
|
|
37
|
+
// a committed `.codex/skills` mirror. The GLOBAL `$CODEX_HOME/skills` install is
|
|
38
|
+
// generated from these entries with the stage adapter injected below.
|
|
39
|
+
const skillsDir = path.join(sourceRoot, 'skills');
|
|
24
40
|
|
|
25
41
|
if (!fs.existsSync(skillsDir)) {
|
|
26
42
|
return [];
|
|
@@ -94,10 +110,44 @@ function buildCodexSkillInstallPlan(sourceRoot, options = {}) {
|
|
|
94
110
|
}));
|
|
95
111
|
}
|
|
96
112
|
|
|
113
|
+
/**
|
|
114
|
+
* Absolute path to a project's repo-local Codex skill discovery dir.
|
|
115
|
+
*
|
|
116
|
+
* @param {string} projectRoot - The project/repo root.
|
|
117
|
+
* @returns {string} `<projectRoot>/.agents/skills`.
|
|
118
|
+
*/
|
|
119
|
+
function resolveCodexRepoSkillsDir(projectRoot) {
|
|
120
|
+
return path.join(projectRoot, '.agents', 'skills');
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Generate the repo-local Codex skill discovery mirror (`.agents/skills`) from
|
|
125
|
+
* the canonical `skills/` source.
|
|
126
|
+
*
|
|
127
|
+
* Content matches the other harness mirrors byte-for-byte (raw canonical — the
|
|
128
|
+
* `$CODEX_HOME` stage adapter is NOT injected here) so the skills-sync drift gate
|
|
129
|
+
* can enforce it, and so repo-local discovery reaches parity with the
|
|
130
|
+
* `.claude/skills` / `.cursor/skills` discovery surfaces.
|
|
131
|
+
*
|
|
132
|
+
* @param {object} params
|
|
133
|
+
* @param {string} params.sourceRoot - Root containing the canonical `skills/` dir.
|
|
134
|
+
* @param {string} params.projectRoot - Target project/repo root.
|
|
135
|
+
* @param {boolean} [params.clean=false] - Remove stale canonical-managed dirs first.
|
|
136
|
+
* @returns {{targetSkillsDir: string, written: string[]}}
|
|
137
|
+
*/
|
|
138
|
+
function populateCodexRepoSkills({ sourceRoot, projectRoot, clean = false }) {
|
|
139
|
+
const targetSkillsDir = resolveCodexRepoSkillsDir(projectRoot);
|
|
140
|
+
const { written } = populateAgentSkills({ sourceRoot, targetSkillsDir, clean });
|
|
141
|
+
return { targetSkillsDir, written };
|
|
142
|
+
}
|
|
143
|
+
|
|
97
144
|
module.exports = {
|
|
145
|
+
CODEX_REPO_SKILLS_DIR,
|
|
98
146
|
buildCodexSkillInstallPlan,
|
|
99
147
|
formatCodexSkillsInstallDir,
|
|
100
148
|
listCodexSkillEntries,
|
|
149
|
+
populateCodexRepoSkills,
|
|
101
150
|
resolveCodexHome,
|
|
151
|
+
resolveCodexRepoSkillsDir,
|
|
102
152
|
resolveCodexSkillsInstallDir,
|
|
103
153
|
};
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command Aliases — declarative back-compat alias map.
|
|
3
|
+
*
|
|
4
|
+
* Generalises the former hardcoded `ISSUE_ALIAS_COMMANDS` allowlist (bin/forge.js)
|
|
5
|
+
* into a single declarative source of truth for command-surface unification
|
|
6
|
+
* (kernel issue 33d1a906, epic eea186fa). Each entry maps a bare top-level alias
|
|
7
|
+
* to the canonical `<noun> <sub>` form it stands in for, plus two flags:
|
|
8
|
+
*
|
|
9
|
+
* { canonical: 'issue create', visible: false, deprecated?: true }
|
|
10
|
+
*
|
|
11
|
+
* - `canonical` — the canonical noun+subcommand this alias resolves to.
|
|
12
|
+
* - `visible` — true → routable AND shown in `forge --help`;
|
|
13
|
+
* false → routable but hidden from help (back-compat only).
|
|
14
|
+
* - `deprecated` — optional; when true, using the alias emits a one-line hint
|
|
15
|
+
* to STDERR, but ONLY when `FORGE_DEPRECATION_WARNINGS` is set.
|
|
16
|
+
* Aliases are NEVER removed or broken (docker still ships
|
|
17
|
+
* `docker pull`).
|
|
18
|
+
*
|
|
19
|
+
* P0 SCOPE: seeds ONLY the existing issue aliases migrated verbatim from
|
|
20
|
+
* `ISSUE_ALIAS_COMMANDS` (all hidden, none deprecated) so behaviour is identical.
|
|
21
|
+
* No new noun mappings are added here — those land in later phases. The bare
|
|
22
|
+
* files (create.js, update.js, …) still exist and remain the routed handlers, so
|
|
23
|
+
* `resolveDispatch` is a strict no-op for the seed set (its first clause skips any
|
|
24
|
+
* name that is still a registered command).
|
|
25
|
+
*
|
|
26
|
+
* Files starting with `_` are excluded from command auto-discovery (see
|
|
27
|
+
* `_registry.js`), so this module is never mistaken for a command itself.
|
|
28
|
+
*
|
|
29
|
+
* @module _aliases
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @typedef {Object} AliasDescriptor
|
|
34
|
+
* @property {string} canonical - Canonical `<noun> <sub>` form the alias resolves to.
|
|
35
|
+
* @property {boolean} visible - Whether the alias appears in `forge --help`.
|
|
36
|
+
* @property {boolean} [deprecated] - Whether using the alias emits an opt-in hint.
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
/** @type {Object<string, AliasDescriptor>} */
|
|
40
|
+
const ALIASES = {
|
|
41
|
+
create: { canonical: 'issue create', visible: false },
|
|
42
|
+
update: { canonical: 'issue update', visible: false },
|
|
43
|
+
claim: { canonical: 'issue claim', visible: false },
|
|
44
|
+
close: { canonical: 'issue close', visible: false },
|
|
45
|
+
show: { canonical: 'issue show', visible: false },
|
|
46
|
+
list: { canonical: 'issue list', visible: false },
|
|
47
|
+
ready: { canonical: 'issue ready', visible: false },
|
|
48
|
+
blocked: { canonical: 'issue blocked', visible: false },
|
|
49
|
+
stale: { canonical: 'issue stale', visible: false },
|
|
50
|
+
orphans: { canonical: 'issue orphans', visible: false },
|
|
51
|
+
lint: { canonical: 'issue lint', visible: false },
|
|
52
|
+
claims: { canonical: 'issue claims', visible: false },
|
|
53
|
+
// `issues` is the plural convenience form of `issue list`.
|
|
54
|
+
issues: { canonical: 'issue list', visible: false },
|
|
55
|
+
|
|
56
|
+
// P1 (kernel issue febf7690) — memory noun shortcuts. The `memory` noun
|
|
57
|
+
// (add/recall/search/insights) shipped in PR #392 (issue 25362344); P1 wires the
|
|
58
|
+
// bare verbs as VISIBLE back-compat shortcuts of the canonical `memory <sub>`
|
|
59
|
+
// form. The canonical WRITE verb is `memory add` (there is NO `save`). These stay
|
|
60
|
+
// registered command files (remember.js/recall.js/insights.js), so resolveDispatch
|
|
61
|
+
// is a strict no-op for them and bare-verb dispatch stays byte-identical; the
|
|
62
|
+
// entries exist to document the mapping and drive the `forge --help` Shortcuts
|
|
63
|
+
// block. They are deliberately NOT issue-backend flag-passthrough aliases (see
|
|
64
|
+
// passthroughAliasNames) so global flags (`-p`, `--help`, `--all`) still parse
|
|
65
|
+
// exactly as they did for the standalone commands.
|
|
66
|
+
remember: { canonical: 'memory add', visible: true },
|
|
67
|
+
recall: { canonical: 'memory recall', visible: true },
|
|
68
|
+
insights: { canonical: 'memory insights', visible: true },
|
|
69
|
+
|
|
70
|
+
// P2 (kernel issue 6ab3f30c) — the `pr` noun (ship/preflight/shepherd/merge) plus
|
|
71
|
+
// folding doc-gate under the existing `gate` noun. `pr ship` is the canonical
|
|
72
|
+
// PR-creation form, but bare `ship` stays a VISIBLE shortcut (hot workflow verb,
|
|
73
|
+
// zero keystroke loss); `preflight` is likewise VISIBLE. shepherd/merge/doc-gate
|
|
74
|
+
// are less-hot, so they stay HIDDEN back-compat aliases. Every one keeps its own
|
|
75
|
+
// registered command file (ship.js/preflight.js/shepherd.js/merge.js/doc-gate.js),
|
|
76
|
+
// so resolveDispatch is a strict no-op for them and bare-verb dispatch stays
|
|
77
|
+
// byte-identical — the entries document the mapping and drive the `forge --help`
|
|
78
|
+
// Shortcuts block. Their canonical is a `pr `/`gate ` form (NOT `issue `), so
|
|
79
|
+
// passthroughAliasNames() excludes them and their global flags (`--pull`,
|
|
80
|
+
// `--json`, `--bundle`, `--all`, `-h`) parse exactly as the standalone commands'.
|
|
81
|
+
ship: { canonical: 'pr ship', visible: true },
|
|
82
|
+
preflight: { canonical: 'pr preflight', visible: true },
|
|
83
|
+
shepherd: { canonical: 'pr shepherd', visible: false },
|
|
84
|
+
merge: { canonical: 'pr merge', visible: false },
|
|
85
|
+
'doc-gate': { canonical: 'gate doc', visible: false },
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Look up an alias descriptor by bare name.
|
|
90
|
+
* @param {string} name
|
|
91
|
+
* @returns {AliasDescriptor|undefined}
|
|
92
|
+
*/
|
|
93
|
+
function resolveAlias(name) {
|
|
94
|
+
return Object.prototype.hasOwnProperty.call(ALIASES, name) ? ALIASES[name] : undefined;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* @param {string} name
|
|
99
|
+
* @returns {boolean} true if `name` is a registered alias.
|
|
100
|
+
*/
|
|
101
|
+
function isAlias(name) {
|
|
102
|
+
return resolveAlias(name) !== undefined;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* All alias names. Replaces the flat `ISSUE_ALIAS_COMMANDS` array — used to skip
|
|
107
|
+
* global flag parsing so passthrough flags reach the handler intact.
|
|
108
|
+
* @returns {string[]}
|
|
109
|
+
*/
|
|
110
|
+
function aliasNames() {
|
|
111
|
+
return Object.keys(ALIASES);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* The subset of aliases that delegate ALL flag parsing to the issue backend
|
|
116
|
+
* and therefore must SKIP global flag parsing in bin/forge.js so flags like
|
|
117
|
+
* `--type` / `-p` / `--help` reach the handler intact. This is issue-specific:
|
|
118
|
+
* only issue-canonical aliases passthrough. Non-issue aliases (e.g. the P1 memory
|
|
119
|
+
* shortcuts) parse global flags normally — exactly as their standalone command
|
|
120
|
+
* files did — so their behaviour stays byte-identical after becoming aliases.
|
|
121
|
+
* @returns {string[]}
|
|
122
|
+
*/
|
|
123
|
+
function passthroughAliasNames() {
|
|
124
|
+
return Object.keys(ALIASES).filter(name => ALIASES[name].canonical.startsWith('issue '));
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Names of aliases shown in the `forge --help` Shortcuts block — visible
|
|
129
|
+
* back-compat shortcuts for a canonical `<noun> <sub>` form. Hidden (back-compat
|
|
130
|
+
* only) aliases are excluded.
|
|
131
|
+
* @returns {string[]}
|
|
132
|
+
*/
|
|
133
|
+
function visibleAliasNames() {
|
|
134
|
+
return Object.keys(ALIASES).filter(name => ALIASES[name].visible === true);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Whether a descriptor is hidden from help. Pure predicate over the `visible`
|
|
139
|
+
* flag so the visible-vs-hidden distinction can be tested independent of the
|
|
140
|
+
* P0 seed (which is entirely hidden).
|
|
141
|
+
* @param {AliasDescriptor|undefined} descriptor
|
|
142
|
+
* @returns {boolean}
|
|
143
|
+
*/
|
|
144
|
+
function isHidden(descriptor) {
|
|
145
|
+
return !!descriptor && descriptor.visible === false;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Whether the named alias is hidden from `forge --help`. Drives the help filter.
|
|
150
|
+
* @param {string} name
|
|
151
|
+
* @returns {boolean}
|
|
152
|
+
*/
|
|
153
|
+
function isHiddenAlias(name) {
|
|
154
|
+
return isHidden(resolveAlias(name));
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Whether the named alias is a visible (help-listed) shortcut.
|
|
159
|
+
* @param {string} name
|
|
160
|
+
* @returns {boolean}
|
|
161
|
+
*/
|
|
162
|
+
function isVisibleAlias(name) {
|
|
163
|
+
const descriptor = resolveAlias(name);
|
|
164
|
+
return !!descriptor && descriptor.visible === true;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Render the one-line deprecation hint for an alias.
|
|
169
|
+
* @param {string} name
|
|
170
|
+
* @param {AliasDescriptor} descriptor
|
|
171
|
+
* @returns {string}
|
|
172
|
+
*/
|
|
173
|
+
function renderHint(name, descriptor) {
|
|
174
|
+
return `forge ${name} is a back-compat alias; prefer 'forge ${descriptor.canonical}'`;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Whether a deprecation hint should be emitted: requires BOTH the opt-in env flag
|
|
179
|
+
* AND a descriptor explicitly marked deprecated. Default (flag unset) is silent,
|
|
180
|
+
* so scripted stdout is never affected.
|
|
181
|
+
* @param {AliasDescriptor|undefined} descriptor
|
|
182
|
+
* @param {Object} env
|
|
183
|
+
* @returns {boolean}
|
|
184
|
+
*/
|
|
185
|
+
function shouldWarn(descriptor, env) {
|
|
186
|
+
return !!(env && env.FORGE_DEPRECATION_WARNINGS && descriptor && descriptor.deprecated);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Emit an opt-in deprecation hint to stderr when both gates pass. Never writes to
|
|
191
|
+
* stdout (would corrupt `--json`). Returns whether a hint was emitted.
|
|
192
|
+
* @param {string} name
|
|
193
|
+
* @param {{env?: Object, stderr?: {write: function}, resolve?: function}} [opts]
|
|
194
|
+
* @returns {boolean}
|
|
195
|
+
*/
|
|
196
|
+
function maybeWarnDeprecation(name, opts = {}) {
|
|
197
|
+
const env = opts.env || process.env;
|
|
198
|
+
const stderr = opts.stderr || process.stderr;
|
|
199
|
+
const resolve = opts.resolve || resolveAlias;
|
|
200
|
+
const descriptor = resolve(name);
|
|
201
|
+
if (!shouldWarn(descriptor, env)) return false;
|
|
202
|
+
stderr.write(`${renderHint(name, descriptor)}\n`);
|
|
203
|
+
return true;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Resolve a bare command to its canonical noun handler for dispatch.
|
|
208
|
+
*
|
|
209
|
+
* A command that is still a registered command file (`isRegistered(command)` is
|
|
210
|
+
* true) is NEVER rewritten — dispatch stays byte-identical. Only a bare alias
|
|
211
|
+
* whose name is NOT a registered command resolves to `<noun> <sub>`; this
|
|
212
|
+
* activates when a later phase folds a bare verb into a noun handler. For the P0
|
|
213
|
+
* seed every alias is still registered, so this always returns `redirected:false`.
|
|
214
|
+
*
|
|
215
|
+
* @param {string} command - The bare command name (args[0]).
|
|
216
|
+
* @param {string[]} argv - The full argv (argv[0] is the command token).
|
|
217
|
+
* @param {function(string): boolean} isRegistered - Predicate: is this a live command?
|
|
218
|
+
* @returns {{command: string, args: string[], redirected: boolean}}
|
|
219
|
+
*/
|
|
220
|
+
function resolveDispatch(command, argv, isRegistered) {
|
|
221
|
+
if (typeof isRegistered === 'function' && isRegistered(command)) {
|
|
222
|
+
return { command, args: argv, redirected: false };
|
|
223
|
+
}
|
|
224
|
+
const descriptor = resolveAlias(command);
|
|
225
|
+
if (!descriptor) {
|
|
226
|
+
return { command, args: argv, redirected: false };
|
|
227
|
+
}
|
|
228
|
+
const parts = String(descriptor.canonical).trim().split(/\s+/);
|
|
229
|
+
const noun = parts[0];
|
|
230
|
+
const rest = Array.isArray(argv) ? argv.slice(1) : [];
|
|
231
|
+
return { command: noun, args: [noun, ...parts.slice(1), ...rest], redirected: true };
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
module.exports = {
|
|
235
|
+
ALIASES,
|
|
236
|
+
resolveAlias,
|
|
237
|
+
isAlias,
|
|
238
|
+
aliasNames,
|
|
239
|
+
passthroughAliasNames,
|
|
240
|
+
visibleAliasNames,
|
|
241
|
+
isHidden,
|
|
242
|
+
isHiddenAlias,
|
|
243
|
+
isVisibleAlias,
|
|
244
|
+
renderHint,
|
|
245
|
+
shouldWarn,
|
|
246
|
+
maybeWarnDeprecation,
|
|
247
|
+
resolveDispatch,
|
|
248
|
+
};
|