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,559 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const ISSUE_COMMAND_SCHEMA_VERSION = 'forge.issue.v1';
|
|
4
|
+
const ISSUE_COMMAND_ERROR_SCHEMA_VERSION = 'forge.issue.error.v1';
|
|
5
|
+
|
|
6
|
+
const ISSUE_COMMAND_EXIT_CODES = Object.freeze({
|
|
7
|
+
success: 0,
|
|
8
|
+
internal: 1,
|
|
9
|
+
usage: 2,
|
|
10
|
+
notFound: 3,
|
|
11
|
+
conflict: 4,
|
|
12
|
+
unavailable: 5,
|
|
13
|
+
validation: 6,
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
// Canonical D18 taxonomy. Types and statuses are enforced at the validation layer
|
|
17
|
+
// (see taxonomy-validator), not as DB constraints, so label-based extensibility and
|
|
18
|
+
// derived readiness (ready/blocked) stay outside the stored status set.
|
|
19
|
+
const ISSUE_TYPES = Object.freeze(['epic', 'task', 'bug', 'decision']);
|
|
20
|
+
// `backlog` is a parked lifecycle state (ideas discussed but not yet scheduled): a real
|
|
21
|
+
// stored status, distinct from the derived readiness `backlog` state. Parked issues are
|
|
22
|
+
// NOT workable (excluded from WORKABLE_STATUSES) and NOT stale, but ARE counted in rollups.
|
|
23
|
+
const ISSUE_STATUSES = Object.freeze(['open', 'in_progress', 'review', 'done', 'cancelled', 'backlog']);
|
|
24
|
+
// Canonical priority labels P0..P4. The bare integers 0..4 are also accepted on input
|
|
25
|
+
// (the CLI documents `--priority 1`; normalizePriority maps ranks 0..4) — see
|
|
26
|
+
// isValidIssuePriority. P5+ / non-numeric labels are rejected at the validation layer,
|
|
27
|
+
// matching MAX_DISPLAY_PRIORITY_RANK in taxonomy-validator.
|
|
28
|
+
const ISSUE_PRIORITIES = Object.freeze(['P0', 'P1', 'P2', 'P3', 'P4']);
|
|
29
|
+
|
|
30
|
+
// True when `priority` is a canonical P0..P4 label (case-insensitive) or a bare
|
|
31
|
+
// integer 0..4. Used by the create/update validation gate to reject junk priorities
|
|
32
|
+
// (P9, BOGUS, -1) instead of persisting them verbatim — Beads rejected them too.
|
|
33
|
+
function isValidIssuePriority(priority) {
|
|
34
|
+
if (typeof priority === 'number') {
|
|
35
|
+
return Number.isInteger(priority) && priority >= 0 && priority <= 4;
|
|
36
|
+
}
|
|
37
|
+
if (typeof priority !== 'string') return false;
|
|
38
|
+
const raw = priority.trim().toUpperCase();
|
|
39
|
+
const match = /^P?([0-9]+)$/.exec(raw);
|
|
40
|
+
if (!match) return false;
|
|
41
|
+
const rank = Number(match[1]);
|
|
42
|
+
return rank >= 0 && rank <= 4;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Canonicalize a priority input to its P0..P4 label. Accepts the canonical labels
|
|
46
|
+
// (case-insensitive) and the bare ranks 0..4 the CLI documents (`--priority 1`), and
|
|
47
|
+
// maps BOTH forms to the SAME label ('1' and 'P1' -> 'P1'). Out-of-range / non-priority
|
|
48
|
+
// input is returned UNCHANGED so the create/update validation gate (isValidIssuePriority)
|
|
49
|
+
// still REJECTS it rather than silently clamping (P9 must error, not become P4). The
|
|
50
|
+
// stored canonical form is this label; priority_rank is its numeric rank.
|
|
51
|
+
function normalizePriority(priority) {
|
|
52
|
+
if (!isValidIssuePriority(priority)) return priority;
|
|
53
|
+
const raw = typeof priority === 'number' ? String(priority) : priority.trim().toUpperCase();
|
|
54
|
+
const rank = Number(/^P?([0-9]+)$/.exec(raw)[1]);
|
|
55
|
+
return `P${rank}`;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function deepFreeze(value) {
|
|
59
|
+
if (!value || typeof value !== 'object') return value;
|
|
60
|
+
Object.freeze(value);
|
|
61
|
+
for (const nestedValue of Object.values(value)) {
|
|
62
|
+
deepFreeze(nestedValue);
|
|
63
|
+
}
|
|
64
|
+
return value;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const ISSUE_SUMMARY_SCHEMA = {
|
|
68
|
+
type: 'object',
|
|
69
|
+
required: ['id', 'title', 'type', 'status', 'revision'],
|
|
70
|
+
properties: {
|
|
71
|
+
id: { type: 'string' },
|
|
72
|
+
title: { type: 'string' },
|
|
73
|
+
body: { type: ['string', 'null'] },
|
|
74
|
+
type: { enum: [...ISSUE_TYPES] },
|
|
75
|
+
status: { enum: [...ISSUE_STATUSES] },
|
|
76
|
+
priority: { type: 'string' },
|
|
77
|
+
rank: { type: 'number' },
|
|
78
|
+
revision: { type: 'integer', minimum: 0 },
|
|
79
|
+
blocked: { type: 'boolean' },
|
|
80
|
+
claimed_by: { type: ['string', 'null'] },
|
|
81
|
+
// KAP-2: stored-but-previously-unprojected fields, surfaced for agents.
|
|
82
|
+
parent_id: { type: ['string', 'null'] },
|
|
83
|
+
labels: { type: 'array', items: { type: 'string' } },
|
|
84
|
+
dependencies: { type: 'array', items: { type: 'string' } },
|
|
85
|
+
// Epic/reverse-dependency exposure: `dependents` are the ids that depend on this
|
|
86
|
+
// issue (inverse of `dependencies`); `blocked_by` is the readiness model's live
|
|
87
|
+
// blocker subset. Additive superset on every read op (schema is permissive —
|
|
88
|
+
// no additionalProperties:false — so older consumers still validate).
|
|
89
|
+
dependents: { type: 'array', items: { type: 'string' } },
|
|
90
|
+
blocked_by: { type: 'array', items: { type: 'string' } },
|
|
91
|
+
created_at: { type: 'string' },
|
|
92
|
+
updated_at: { type: 'string' },
|
|
93
|
+
// KAP-10 (acceptance_criteria/design/notes) + KAP-11 (assignee): nullable
|
|
94
|
+
// content fields and a persistent assignee. Optional (NOT required) so summaries
|
|
95
|
+
// that omit them still validate.
|
|
96
|
+
acceptance_criteria: { type: ['string', 'null'] },
|
|
97
|
+
design: { type: ['string', 'null'] },
|
|
98
|
+
notes: { type: ['string', 'null'] },
|
|
99
|
+
assignee: { type: ['string', 'null'] },
|
|
100
|
+
// Beads full-fidelity import: author, close timestamp, raw close reason and a
|
|
101
|
+
// verbatim metadata JSON blob. Optional (NOT required) and nullable so summaries
|
|
102
|
+
// that omit them still validate.
|
|
103
|
+
created_by: { type: ['string', 'null'] },
|
|
104
|
+
closed_at: { type: ['string', 'null'] },
|
|
105
|
+
close_reason: { type: ['string', 'null'] },
|
|
106
|
+
metadata: { type: ['string', 'null'] },
|
|
107
|
+
// KAP-3: `show` attaches the issue's comments; other reads (list/ready/search/
|
|
108
|
+
// stats) omit the key. Optional (NOT in required) so comment-less summaries still
|
|
109
|
+
// validate. Each item carries id/body/actor/created_at (body may be null).
|
|
110
|
+
comments: {
|
|
111
|
+
type: 'array',
|
|
112
|
+
items: {
|
|
113
|
+
type: 'object',
|
|
114
|
+
required: ['id', 'body', 'actor', 'created_at'],
|
|
115
|
+
properties: {
|
|
116
|
+
id: { type: 'string' },
|
|
117
|
+
body: { type: ['string', 'null'] },
|
|
118
|
+
actor: { type: 'string' },
|
|
119
|
+
created_at: { type: 'string' },
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
// KAP-12: `lint` attaches a content-validation result to each FAILING issue;
|
|
124
|
+
// other reads (list/ready/search/...) omit the key. Optional (NOT in required)
|
|
125
|
+
// so validation-less summaries still validate. rules_failed names the broken
|
|
126
|
+
// content rules (e.g. 'missing_acceptance_criteria').
|
|
127
|
+
validation: {
|
|
128
|
+
type: 'object',
|
|
129
|
+
required: ['rules_failed'],
|
|
130
|
+
properties: {
|
|
131
|
+
rules_failed: { type: 'array', items: { type: 'string' } },
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const NEXT_COMMANDS_SCHEMA = {
|
|
138
|
+
type: 'array',
|
|
139
|
+
items: { type: 'string' },
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
const ISSUE_COMMAND_RESPONSE_SCHEMAS = deepFreeze({
|
|
143
|
+
issue: {
|
|
144
|
+
type: 'object',
|
|
145
|
+
required: ['ok', 'schema_version', 'command', 'data', 'next_commands'],
|
|
146
|
+
properties: {
|
|
147
|
+
ok: { const: true },
|
|
148
|
+
schema_version: { const: ISSUE_COMMAND_SCHEMA_VERSION },
|
|
149
|
+
command: { type: 'string' },
|
|
150
|
+
data: ISSUE_SUMMARY_SCHEMA,
|
|
151
|
+
next_commands: NEXT_COMMANDS_SCHEMA,
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
issueList: {
|
|
155
|
+
type: 'object',
|
|
156
|
+
required: ['ok', 'schema_version', 'command', 'data', 'next_commands'],
|
|
157
|
+
properties: {
|
|
158
|
+
ok: { const: true },
|
|
159
|
+
schema_version: { const: ISSUE_COMMAND_SCHEMA_VERSION },
|
|
160
|
+
command: { type: 'string' },
|
|
161
|
+
data: {
|
|
162
|
+
type: 'object',
|
|
163
|
+
required: ['issues'],
|
|
164
|
+
properties: {
|
|
165
|
+
issues: {
|
|
166
|
+
type: 'array',
|
|
167
|
+
items: ISSUE_SUMMARY_SCHEMA,
|
|
168
|
+
},
|
|
169
|
+
count: { type: 'integer', minimum: 0 },
|
|
170
|
+
truncated: { type: 'boolean' },
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
next_commands: NEXT_COMMANDS_SCHEMA,
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
stats: {
|
|
177
|
+
type: 'object',
|
|
178
|
+
required: ['ok', 'schema_version', 'command', 'data', 'next_commands'],
|
|
179
|
+
properties: {
|
|
180
|
+
ok: { const: true },
|
|
181
|
+
schema_version: { const: ISSUE_COMMAND_SCHEMA_VERSION },
|
|
182
|
+
command: { type: 'string' },
|
|
183
|
+
data: {
|
|
184
|
+
type: 'object',
|
|
185
|
+
required: ['counts'],
|
|
186
|
+
properties: {
|
|
187
|
+
counts: { type: 'object' },
|
|
188
|
+
ready_count: { type: 'integer', minimum: 0 },
|
|
189
|
+
blocked_count: { type: 'integer', minimum: 0 },
|
|
190
|
+
active_claims: { type: 'integer', minimum: 0 },
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
next_commands: NEXT_COMMANDS_SCHEMA,
|
|
194
|
+
},
|
|
195
|
+
},
|
|
196
|
+
// KAP-7: derived read responses. `blocked` and `orphans` reuse the issueList
|
|
197
|
+
// shape above (an array of ISSUE_SUMMARY_SCHEMA + count). `stale` reuses that
|
|
198
|
+
// shape and additionally carries the threshold_days (in days) the staleness
|
|
199
|
+
// window was computed against.
|
|
200
|
+
staleList: {
|
|
201
|
+
type: 'object',
|
|
202
|
+
required: ['ok', 'schema_version', 'command', 'data', 'next_commands'],
|
|
203
|
+
properties: {
|
|
204
|
+
ok: { const: true },
|
|
205
|
+
schema_version: { const: ISSUE_COMMAND_SCHEMA_VERSION },
|
|
206
|
+
command: { type: 'string' },
|
|
207
|
+
data: {
|
|
208
|
+
type: 'object',
|
|
209
|
+
required: ['issues', 'count', 'threshold_days'],
|
|
210
|
+
properties: {
|
|
211
|
+
issues: {
|
|
212
|
+
type: 'array',
|
|
213
|
+
items: ISSUE_SUMMARY_SCHEMA,
|
|
214
|
+
},
|
|
215
|
+
count: { type: 'integer', minimum: 0 },
|
|
216
|
+
threshold_days: { type: 'integer' },
|
|
217
|
+
},
|
|
218
|
+
},
|
|
219
|
+
next_commands: NEXT_COMMANDS_SCHEMA,
|
|
220
|
+
},
|
|
221
|
+
},
|
|
222
|
+
// Epic support: `children` returns the epic header, its DIRECT children (each a full
|
|
223
|
+
// ISSUE_SUMMARY_SCHEMA), and a kernel-computed rollup. The rollup owns the status
|
|
224
|
+
// vocabulary so consumers never hard-code status names; `percentage` is done-only.
|
|
225
|
+
children: {
|
|
226
|
+
type: 'object',
|
|
227
|
+
required: ['ok', 'schema_version', 'command', 'data', 'next_commands'],
|
|
228
|
+
properties: {
|
|
229
|
+
ok: { const: true },
|
|
230
|
+
schema_version: { const: ISSUE_COMMAND_SCHEMA_VERSION },
|
|
231
|
+
command: { type: 'string' },
|
|
232
|
+
data: {
|
|
233
|
+
type: 'object',
|
|
234
|
+
required: ['epic', 'children', 'rollup', 'count'],
|
|
235
|
+
properties: {
|
|
236
|
+
epic: {
|
|
237
|
+
type: 'object',
|
|
238
|
+
required: ['id', 'title', 'type', 'status'],
|
|
239
|
+
properties: {
|
|
240
|
+
id: { type: 'string' },
|
|
241
|
+
title: { type: 'string' },
|
|
242
|
+
type: { enum: [...ISSUE_TYPES] },
|
|
243
|
+
status: { enum: [...ISSUE_STATUSES] },
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
children: {
|
|
247
|
+
type: 'array',
|
|
248
|
+
items: ISSUE_SUMMARY_SCHEMA,
|
|
249
|
+
},
|
|
250
|
+
rollup: {
|
|
251
|
+
type: 'object',
|
|
252
|
+
required: ['total', 'done', 'percentage', 'by_status'],
|
|
253
|
+
properties: {
|
|
254
|
+
total: { type: 'integer', minimum: 0 },
|
|
255
|
+
done: { type: 'integer', minimum: 0 },
|
|
256
|
+
in_progress: { type: 'integer', minimum: 0 },
|
|
257
|
+
open: { type: 'integer', minimum: 0 },
|
|
258
|
+
review: { type: 'integer', minimum: 0 },
|
|
259
|
+
cancelled: { type: 'integer', minimum: 0 },
|
|
260
|
+
backlog: { type: 'integer', minimum: 0 },
|
|
261
|
+
blocked: { type: 'integer', minimum: 0 },
|
|
262
|
+
percentage: { type: 'integer', minimum: 0 },
|
|
263
|
+
by_status: { type: 'object' },
|
|
264
|
+
},
|
|
265
|
+
},
|
|
266
|
+
count: { type: 'integer', minimum: 0 },
|
|
267
|
+
},
|
|
268
|
+
},
|
|
269
|
+
next_commands: NEXT_COMMANDS_SCHEMA,
|
|
270
|
+
},
|
|
271
|
+
},
|
|
272
|
+
// Issue 7dc229d4: the active-lease/claims read. `claims` is an array of live
|
|
273
|
+
// lease rows (state='active' AND not expired at read time). Each row carries the
|
|
274
|
+
// full who/what/where the dashboard live layer needs: actor + session_id +
|
|
275
|
+
// worktree_id + expires_at + issue_id (plus the lease id and claimed_at). The
|
|
276
|
+
// kernel_claims schema has no `agent` column, so none is surfaced. session_id /
|
|
277
|
+
// worktree_id / expires_at are nullable (a claim may carry none / never expire).
|
|
278
|
+
claimsList: {
|
|
279
|
+
type: 'object',
|
|
280
|
+
required: ['ok', 'schema_version', 'command', 'data', 'next_commands'],
|
|
281
|
+
properties: {
|
|
282
|
+
ok: { const: true },
|
|
283
|
+
schema_version: { const: ISSUE_COMMAND_SCHEMA_VERSION },
|
|
284
|
+
command: { type: 'string' },
|
|
285
|
+
data: {
|
|
286
|
+
type: 'object',
|
|
287
|
+
required: ['claims', 'count'],
|
|
288
|
+
properties: {
|
|
289
|
+
claims: {
|
|
290
|
+
type: 'array',
|
|
291
|
+
items: {
|
|
292
|
+
type: 'object',
|
|
293
|
+
required: ['id', 'issue_id', 'actor', 'session_id', 'worktree_id', 'claimed_at', 'expires_at'],
|
|
294
|
+
properties: {
|
|
295
|
+
id: { type: 'string' },
|
|
296
|
+
issue_id: { type: 'string' },
|
|
297
|
+
actor: { type: ['string', 'null'] },
|
|
298
|
+
session_id: { type: ['string', 'null'] },
|
|
299
|
+
worktree_id: { type: ['string', 'null'] },
|
|
300
|
+
claimed_at: { type: ['string', 'null'] },
|
|
301
|
+
expires_at: { type: ['string', 'null'] },
|
|
302
|
+
},
|
|
303
|
+
},
|
|
304
|
+
},
|
|
305
|
+
count: { type: 'integer', minimum: 0 },
|
|
306
|
+
},
|
|
307
|
+
},
|
|
308
|
+
next_commands: NEXT_COMMANDS_SCHEMA,
|
|
309
|
+
},
|
|
310
|
+
},
|
|
311
|
+
mutation: {
|
|
312
|
+
type: 'object',
|
|
313
|
+
required: ['ok', 'schema_version', 'command', 'data', 'next_commands'],
|
|
314
|
+
properties: {
|
|
315
|
+
ok: { const: true },
|
|
316
|
+
schema_version: { const: ISSUE_COMMAND_SCHEMA_VERSION },
|
|
317
|
+
command: { type: 'string' },
|
|
318
|
+
data: {
|
|
319
|
+
type: 'object',
|
|
320
|
+
required: ['id', 'revision'],
|
|
321
|
+
properties: {
|
|
322
|
+
id: { type: 'string' },
|
|
323
|
+
revision: { type: 'integer', minimum: 0 },
|
|
324
|
+
issue: ISSUE_SUMMARY_SCHEMA,
|
|
325
|
+
comment_id: { type: 'string' },
|
|
326
|
+
dependency_id: { type: 'string' },
|
|
327
|
+
claim_id: { type: 'string' },
|
|
328
|
+
// KAP-8: close only — ids that became ready now the issue is done.
|
|
329
|
+
// OPTIONAL (not in `required`) so every other mutation still validates.
|
|
330
|
+
newly_unblocked: { type: 'array', items: { type: 'string' } },
|
|
331
|
+
projection: {
|
|
332
|
+
type: 'object',
|
|
333
|
+
properties: {
|
|
334
|
+
status: { type: 'string' },
|
|
335
|
+
targets: { type: 'array', items: { type: 'string' } },
|
|
336
|
+
},
|
|
337
|
+
},
|
|
338
|
+
},
|
|
339
|
+
},
|
|
340
|
+
next_commands: NEXT_COMMANDS_SCHEMA,
|
|
341
|
+
},
|
|
342
|
+
},
|
|
343
|
+
// Multi-id close (`forge issue close <a> <b> ...`). The kernel close op closes a
|
|
344
|
+
// SINGLE id, so the CLI fans out one mutation per id and aggregates the outcomes
|
|
345
|
+
// into ONE envelope (never a bare array — that broke envelope parity). `ok` is a
|
|
346
|
+
// plain boolean here (true only when EVERY id closed); per-id outcomes live in
|
|
347
|
+
// `data.results`, and `data.closed` lists the ids that reached terminal state.
|
|
348
|
+
// Each result echoes the single-close mutation fields (revision/newly_unblocked)
|
|
349
|
+
// on success or the forge.issue.error.v1 `error` object on failure.
|
|
350
|
+
mutationBatch: {
|
|
351
|
+
type: 'object',
|
|
352
|
+
required: ['ok', 'schema_version', 'command', 'data', 'next_commands'],
|
|
353
|
+
properties: {
|
|
354
|
+
ok: { type: 'boolean' },
|
|
355
|
+
schema_version: { const: ISSUE_COMMAND_SCHEMA_VERSION },
|
|
356
|
+
command: { type: 'string' },
|
|
357
|
+
data: {
|
|
358
|
+
type: 'object',
|
|
359
|
+
required: ['results', 'count', 'closed'],
|
|
360
|
+
properties: {
|
|
361
|
+
results: {
|
|
362
|
+
type: 'array',
|
|
363
|
+
items: {
|
|
364
|
+
type: 'object',
|
|
365
|
+
required: ['id', 'ok'],
|
|
366
|
+
properties: {
|
|
367
|
+
id: { type: 'string' },
|
|
368
|
+
ok: { type: 'boolean' },
|
|
369
|
+
revision: { type: 'integer', minimum: 0 },
|
|
370
|
+
newly_unblocked: { type: 'array', items: { type: 'string' } },
|
|
371
|
+
error: { type: 'object' },
|
|
372
|
+
},
|
|
373
|
+
},
|
|
374
|
+
},
|
|
375
|
+
count: { type: 'integer', minimum: 0 },
|
|
376
|
+
closed: { type: 'array', items: { type: 'string' } },
|
|
377
|
+
},
|
|
378
|
+
},
|
|
379
|
+
next_commands: NEXT_COMMANDS_SCHEMA,
|
|
380
|
+
},
|
|
381
|
+
},
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
const ISSUE_COMMAND_ERROR_SCHEMA = deepFreeze({
|
|
385
|
+
type: 'object',
|
|
386
|
+
required: ['ok', 'schema_version', 'command', 'error', 'next_commands'],
|
|
387
|
+
properties: {
|
|
388
|
+
ok: { const: false },
|
|
389
|
+
schema_version: { const: ISSUE_COMMAND_ERROR_SCHEMA_VERSION },
|
|
390
|
+
command: { type: 'string' },
|
|
391
|
+
error: {
|
|
392
|
+
type: 'object',
|
|
393
|
+
required: ['code', 'message', 'exit_code', 'retryable'],
|
|
394
|
+
properties: {
|
|
395
|
+
code: { type: 'string' },
|
|
396
|
+
message: { type: 'string' },
|
|
397
|
+
exit_code: { type: 'integer' },
|
|
398
|
+
retryable: { type: 'boolean' },
|
|
399
|
+
details: { type: 'object' },
|
|
400
|
+
},
|
|
401
|
+
},
|
|
402
|
+
next_commands: NEXT_COMMANDS_SCHEMA,
|
|
403
|
+
},
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
function command(id, invocation, operation, mode, outputSchema, nextCommands) {
|
|
407
|
+
return {
|
|
408
|
+
id,
|
|
409
|
+
invocation,
|
|
410
|
+
operation,
|
|
411
|
+
mode,
|
|
412
|
+
schemaVersion: ISSUE_COMMAND_SCHEMA_VERSION,
|
|
413
|
+
outputSchema,
|
|
414
|
+
errorShape: ISSUE_COMMAND_ERROR_SCHEMA_VERSION,
|
|
415
|
+
exitCodes: ISSUE_COMMAND_EXIT_CODES,
|
|
416
|
+
nextCommands,
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
const COMMANDS = [
|
|
421
|
+
command('issue.ready', 'forge issue ready --json', 'ready', 'read', ISSUE_COMMAND_RESPONSE_SCHEMAS.issueList, [
|
|
422
|
+
'forge claim <id>',
|
|
423
|
+
'forge issue show <id> --json',
|
|
424
|
+
]),
|
|
425
|
+
command('issue.list', 'forge issue list --json', 'list', 'read', ISSUE_COMMAND_RESPONSE_SCHEMAS.issueList, [
|
|
426
|
+
'forge issue show <id> --json',
|
|
427
|
+
'forge issue search <query> --json',
|
|
428
|
+
]),
|
|
429
|
+
command('issue.show', 'forge issue show <id> --json', 'show', 'read', ISSUE_COMMAND_RESPONSE_SCHEMAS.issue, [
|
|
430
|
+
'forge claim <id>',
|
|
431
|
+
'forge issue comment <id> "<note>"',
|
|
432
|
+
]),
|
|
433
|
+
command('issue.search', 'forge issue search <query> --json', 'search', 'read', ISSUE_COMMAND_RESPONSE_SCHEMAS.issueList, [
|
|
434
|
+
'forge issue show <id> --json',
|
|
435
|
+
'forge claim <id>',
|
|
436
|
+
]),
|
|
437
|
+
command('issue.stats', 'forge issue stats --json', 'stats', 'read', ISSUE_COMMAND_RESPONSE_SCHEMAS.stats, [
|
|
438
|
+
'forge issue ready --json',
|
|
439
|
+
'forge issue list --json',
|
|
440
|
+
]),
|
|
441
|
+
command('issue.blocked', 'forge blocked --json', 'blocked', 'read', ISSUE_COMMAND_RESPONSE_SCHEMAS.issueList, [
|
|
442
|
+
'forge issue show <id> --json',
|
|
443
|
+
'forge issue ready --json',
|
|
444
|
+
]),
|
|
445
|
+
command('issue.stale', 'forge stale --json', 'stale', 'read', ISSUE_COMMAND_RESPONSE_SCHEMAS.staleList, [
|
|
446
|
+
'forge issue show <id> --json',
|
|
447
|
+
'forge issue update <id>',
|
|
448
|
+
]),
|
|
449
|
+
command('issue.orphans', 'forge orphans --json', 'orphans', 'read', ISSUE_COMMAND_RESPONSE_SCHEMAS.issueList, [
|
|
450
|
+
'forge issue show <id> --json',
|
|
451
|
+
'forge issue dep add <issue-id> <blocks-issue-id>',
|
|
452
|
+
]),
|
|
453
|
+
command('issue.lint', 'forge lint --json', 'lint', 'read', ISSUE_COMMAND_RESPONSE_SCHEMAS.issueList, [
|
|
454
|
+
'forge issue show <id> --json',
|
|
455
|
+
'forge issue update <id> --acceptance "<criteria>"',
|
|
456
|
+
]),
|
|
457
|
+
command('issue.children', 'forge issue children <id> --json', 'children', 'read', ISSUE_COMMAND_RESPONSE_SCHEMAS.children, [
|
|
458
|
+
'forge issue show <id> --json',
|
|
459
|
+
'forge claim <id>',
|
|
460
|
+
]),
|
|
461
|
+
command('issue.claims', 'forge claims --json', 'claims', 'read', ISSUE_COMMAND_RESPONSE_SCHEMAS.claimsList, [
|
|
462
|
+
'forge issue show <id> --json',
|
|
463
|
+
'forge claim <id>',
|
|
464
|
+
]),
|
|
465
|
+
command('issue.create', 'forge issue create', 'create', 'mutation', ISSUE_COMMAND_RESPONSE_SCHEMAS.mutation, [
|
|
466
|
+
'forge issue show <id> --json',
|
|
467
|
+
'forge claim <id>',
|
|
468
|
+
]),
|
|
469
|
+
command('issue.update', 'forge issue update', 'update', 'mutation', ISSUE_COMMAND_RESPONSE_SCHEMAS.mutation, [
|
|
470
|
+
'forge issue show <id> --json',
|
|
471
|
+
]),
|
|
472
|
+
command('issue.close', 'forge issue close', 'close', 'mutation', ISSUE_COMMAND_RESPONSE_SCHEMAS.mutation, [
|
|
473
|
+
'forge issue ready --json',
|
|
474
|
+
]),
|
|
475
|
+
command('issue.comment', 'forge issue comment', 'comment', 'mutation', ISSUE_COMMAND_RESPONSE_SCHEMAS.mutation, [
|
|
476
|
+
'forge issue show <id> --json',
|
|
477
|
+
]),
|
|
478
|
+
command('issue.dep.add', 'forge issue dep add', 'dep.add', 'mutation', ISSUE_COMMAND_RESPONSE_SCHEMAS.mutation, [
|
|
479
|
+
'forge issue show <id> --json',
|
|
480
|
+
'forge issue ready --json',
|
|
481
|
+
]),
|
|
482
|
+
command('issue.dep.remove', 'forge issue dep remove', 'dep.remove', 'mutation', ISSUE_COMMAND_RESPONSE_SCHEMAS.mutation, [
|
|
483
|
+
'forge issue ready --json',
|
|
484
|
+
]),
|
|
485
|
+
command('claim', 'forge claim <id>', 'claim', 'mutation', ISSUE_COMMAND_RESPONSE_SCHEMAS.mutation, [
|
|
486
|
+
'forge issue show <id> --json',
|
|
487
|
+
'forge release <id>',
|
|
488
|
+
]),
|
|
489
|
+
command('release', 'forge release <id>', 'release', 'mutation', ISSUE_COMMAND_RESPONSE_SCHEMAS.mutation, [
|
|
490
|
+
'forge issue ready --json',
|
|
491
|
+
]),
|
|
492
|
+
];
|
|
493
|
+
|
|
494
|
+
const ISSUE_COMMAND_CONTRACT = deepFreeze({
|
|
495
|
+
version: ISSUE_COMMAND_SCHEMA_VERSION,
|
|
496
|
+
errorSchemaVersion: ISSUE_COMMAND_ERROR_SCHEMA_VERSION,
|
|
497
|
+
commands: COMMANDS,
|
|
498
|
+
exitCodes: ISSUE_COMMAND_EXIT_CODES,
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
const COMMAND_BY_ID = new Map(ISSUE_COMMAND_CONTRACT.commands.map(candidate => [candidate.id, candidate]));
|
|
502
|
+
|
|
503
|
+
function getIssueCommandContract(id) {
|
|
504
|
+
return COMMAND_BY_ID.get(id) || null;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
// Resolve the catalog next_commands for a command, substituting the concrete issue
|
|
508
|
+
// id into the `<id>` placeholder when the response carries a single id (show and the
|
|
509
|
+
// mutation responses). Multi-issue responses (list/ready/blocked/...) keep the
|
|
510
|
+
// `<id>` template since there is no single id to bind. Unknown commands → [].
|
|
511
|
+
function resolveNextCommands(commandId, data = {}) {
|
|
512
|
+
const contract = COMMAND_BY_ID.get(commandId);
|
|
513
|
+
const templates = contract ? contract.nextCommands : [];
|
|
514
|
+
// Most single-id responses store the id at `data.id`; `issue.children` instead
|
|
515
|
+
// anchors on the epic, so fall back to `data.epic.id` — otherwise its
|
|
516
|
+
// next_commands would emit literal `<id>` placeholders.
|
|
517
|
+
const id = data && typeof data.id === 'string'
|
|
518
|
+
? data.id
|
|
519
|
+
: (data && data.epic && typeof data.epic.id === 'string' ? data.epic.id : null);
|
|
520
|
+
return id ? templates.map(entry => entry.replace(/<id>/g, id)) : [...templates];
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
function formatIssueCommandError(options = {}) {
|
|
524
|
+
const error = {
|
|
525
|
+
code: options.code || 'FORGE_ISSUE_ERROR',
|
|
526
|
+
message: options.message || 'Forge issue command failed',
|
|
527
|
+
exit_code: Number.isInteger(options.exitCode) ? options.exitCode : ISSUE_COMMAND_EXIT_CODES.internal,
|
|
528
|
+
retryable: Boolean(options.retryable),
|
|
529
|
+
};
|
|
530
|
+
|
|
531
|
+
if (options.details && typeof options.details === 'object') {
|
|
532
|
+
error.details = options.details;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
return {
|
|
536
|
+
ok: false,
|
|
537
|
+
schema_version: ISSUE_COMMAND_ERROR_SCHEMA_VERSION,
|
|
538
|
+
command: options.command || 'forge issue',
|
|
539
|
+
error,
|
|
540
|
+
next_commands: Array.isArray(options.nextCommands) ? options.nextCommands : [],
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
module.exports = {
|
|
545
|
+
ISSUE_COMMAND_CONTRACT,
|
|
546
|
+
ISSUE_COMMAND_ERROR_SCHEMA,
|
|
547
|
+
ISSUE_COMMAND_ERROR_SCHEMA_VERSION,
|
|
548
|
+
ISSUE_COMMAND_EXIT_CODES,
|
|
549
|
+
ISSUE_COMMAND_RESPONSE_SCHEMAS,
|
|
550
|
+
ISSUE_COMMAND_SCHEMA_VERSION,
|
|
551
|
+
ISSUE_PRIORITIES,
|
|
552
|
+
ISSUE_STATUSES,
|
|
553
|
+
ISSUE_TYPES,
|
|
554
|
+
formatIssueCommandError,
|
|
555
|
+
getIssueCommandContract,
|
|
556
|
+
isValidIssuePriority,
|
|
557
|
+
normalizePriority,
|
|
558
|
+
resolveNextCommands,
|
|
559
|
+
};
|