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
|
@@ -3,16 +3,17 @@ set -euo pipefail
|
|
|
3
3
|
|
|
4
4
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
5
5
|
|
|
6
|
-
# ── Setup temp dir for test isolation ────────────────────────────────────
|
|
7
6
|
TEST_TMP="$(mktemp -d)"
|
|
8
7
|
trap 'rm -rf "$TEST_TMP" "$mock_dir"' EXIT
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
mock_dir="$(mktemp -d)"
|
|
10
|
+
portable_bin="$(mktemp -d)"
|
|
12
11
|
log_file="$mock_dir/calls.log"
|
|
13
12
|
touch "$log_file"
|
|
13
|
+
REAL_GREP="$(command -v grep)"
|
|
14
|
+
ORIGINAL_PATH="$PATH"
|
|
15
|
+
export REAL_GREP
|
|
14
16
|
|
|
15
|
-
# ── Mock gh ──────────────────────────────────────────────────────────────
|
|
16
17
|
cat > "$mock_dir/gh" << 'MOCK'
|
|
17
18
|
#!/usr/bin/env bash
|
|
18
19
|
echo "$*" >> "$LOG_FILE"
|
|
@@ -23,45 +24,57 @@ case "$1 $2" in
|
|
|
23
24
|
"issue comment") echo ""; exit 0 ;;
|
|
24
25
|
"api user") echo "testuser"; exit 0 ;;
|
|
25
26
|
esac
|
|
26
|
-
echo "unknown gh command: $*" >&2
|
|
27
|
+
echo "unknown gh command: $*" >&2
|
|
28
|
+
exit 1
|
|
27
29
|
MOCK
|
|
28
30
|
chmod +x "$mock_dir/gh"
|
|
29
31
|
|
|
30
|
-
#
|
|
31
|
-
|
|
32
|
+
# Mock forge: `issue show --json` carries the github_issue:<n> association as a
|
|
33
|
+
# label; `issue update --label` records it. Args are logged for assertions.
|
|
34
|
+
cat > "$mock_dir/forge" << 'MOCK'
|
|
32
35
|
#!/usr/bin/env bash
|
|
33
36
|
echo "$*" >> "$LOG_FILE"
|
|
34
|
-
case "$1" in
|
|
35
|
-
show)
|
|
36
|
-
|
|
37
|
-
echo "Title: Test Issue"
|
|
37
|
+
case "$1 $2" in
|
|
38
|
+
"issue show")
|
|
39
|
+
printf '{"data":{"issue":{"id":"beads-001","title":"Test Issue","labels":["github_issue:42"]}}}\n'
|
|
38
40
|
;;
|
|
39
|
-
|
|
41
|
+
"issue update") echo "Updated" ;;
|
|
40
42
|
esac
|
|
41
43
|
MOCK
|
|
42
|
-
chmod +x "$mock_dir/
|
|
44
|
+
chmod +x "$mock_dir/forge"
|
|
43
45
|
|
|
44
|
-
|
|
45
|
-
cat > "$mock_dir/bd-no-gh" << 'MOCK'
|
|
46
|
+
cat > "$mock_dir/forge-no-gh" << 'MOCK'
|
|
46
47
|
#!/usr/bin/env bash
|
|
47
48
|
echo "$*" >> "$LOG_FILE"
|
|
48
|
-
case "$1" in
|
|
49
|
-
show)
|
|
50
|
-
|
|
51
|
-
echo "Title: Test Issue"
|
|
49
|
+
case "$1 $2" in
|
|
50
|
+
"issue show")
|
|
51
|
+
printf '{"data":{"issue":{"id":"beads-999","title":"Test Issue","labels":[]}}}\n'
|
|
52
52
|
;;
|
|
53
|
-
|
|
53
|
+
"issue update") echo "Updated" ;;
|
|
54
54
|
esac
|
|
55
55
|
MOCK
|
|
56
|
-
chmod +x "$mock_dir/
|
|
56
|
+
chmod +x "$mock_dir/forge-no-gh"
|
|
57
|
+
|
|
58
|
+
cat > "$portable_bin/grep" << 'MOCK'
|
|
59
|
+
#!/usr/bin/env bash
|
|
60
|
+
for arg in "$@"; do
|
|
61
|
+
case "$arg" in
|
|
62
|
+
-P|--perl-regexp|-*P*)
|
|
63
|
+
echo "grep: PCRE support disabled for test" >&2
|
|
64
|
+
exit 2
|
|
65
|
+
;;
|
|
66
|
+
esac
|
|
67
|
+
done
|
|
68
|
+
exec "$REAL_GREP" "$@"
|
|
69
|
+
MOCK
|
|
70
|
+
chmod +x "$portable_bin/grep"
|
|
57
71
|
|
|
58
|
-
# Export env for mocks
|
|
59
72
|
export LOG_FILE="$log_file"
|
|
60
73
|
export GH_CMD="$mock_dir/gh"
|
|
61
|
-
export
|
|
74
|
+
export FORGE_CMD="$mock_dir/forge"
|
|
62
75
|
export TEAM_MAP_ROOT="$TEST_TMP"
|
|
76
|
+
mapping_file="$TEAM_MAP_ROOT/.github/beads-mapping.json"
|
|
63
77
|
|
|
64
|
-
# Source the library under test
|
|
65
78
|
source "$SCRIPT_DIR/lib/sync-github.sh"
|
|
66
79
|
|
|
67
80
|
PASS=0
|
|
@@ -70,140 +83,231 @@ FAIL=0
|
|
|
70
83
|
assert_eq() {
|
|
71
84
|
local label="$1" expected="$2" actual="$3"
|
|
72
85
|
if [[ "$actual" == "$expected" ]]; then
|
|
73
|
-
PASS=$((PASS + 1))
|
|
86
|
+
PASS=$((PASS + 1))
|
|
87
|
+
echo " PASS: $label"
|
|
74
88
|
else
|
|
75
|
-
FAIL=$((FAIL + 1))
|
|
89
|
+
FAIL=$((FAIL + 1))
|
|
90
|
+
echo " FAIL: $label (expected '$expected', got '$actual')"
|
|
76
91
|
fi
|
|
77
92
|
}
|
|
78
93
|
|
|
79
94
|
assert_contains() {
|
|
80
95
|
local label="$1" expected="$2" actual="$3"
|
|
81
96
|
if [[ "$actual" == *"$expected"* ]]; then
|
|
82
|
-
PASS=$((PASS + 1))
|
|
97
|
+
PASS=$((PASS + 1))
|
|
98
|
+
echo " PASS: $label"
|
|
83
99
|
else
|
|
84
|
-
FAIL=$((FAIL + 1))
|
|
100
|
+
FAIL=$((FAIL + 1))
|
|
101
|
+
echo " FAIL: $label (expected to contain '$expected', got '$actual')"
|
|
102
|
+
fi
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
assert_not_contains() {
|
|
106
|
+
local label="$1" unexpected="$2" actual="$3"
|
|
107
|
+
if [[ "$actual" == *"$unexpected"* ]]; then
|
|
108
|
+
FAIL=$((FAIL + 1))
|
|
109
|
+
echo " FAIL: $label (did not expect '$unexpected', got '$actual')"
|
|
110
|
+
else
|
|
111
|
+
PASS=$((PASS + 1))
|
|
112
|
+
echo " PASS: $label"
|
|
85
113
|
fi
|
|
86
114
|
}
|
|
87
115
|
|
|
88
116
|
assert_exit() {
|
|
89
117
|
local label="$1" expected="$2" actual="$3"
|
|
90
118
|
if [[ "$actual" -eq "$expected" ]]; then
|
|
91
|
-
PASS=$((PASS + 1))
|
|
119
|
+
PASS=$((PASS + 1))
|
|
120
|
+
echo " PASS: $label"
|
|
92
121
|
else
|
|
93
|
-
FAIL=$((FAIL + 1))
|
|
122
|
+
FAIL=$((FAIL + 1))
|
|
123
|
+
echo " FAIL: $label (expected exit $expected, got $actual)"
|
|
94
124
|
fi
|
|
95
125
|
}
|
|
96
126
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
> "$log_file" # clear log
|
|
127
|
+
echo "== Test 1: sync_issue_create =="
|
|
128
|
+
> "$log_file"
|
|
100
129
|
rc=0
|
|
101
130
|
sync_issue_create "beads-001" || rc=$?
|
|
102
131
|
assert_exit "exit code 0" 0 "$rc"
|
|
103
|
-
# Check gh was called with issue create
|
|
104
132
|
log_contents="$(cat "$log_file")"
|
|
105
133
|
assert_contains "gh issue create called" "issue create" "$log_contents"
|
|
106
134
|
assert_contains "title includes Test Issue" "Test Issue" "$log_contents"
|
|
107
135
|
assert_contains "body includes beads-001" "beads-001" "$log_contents"
|
|
108
|
-
|
|
109
|
-
assert_contains "
|
|
110
|
-
assert_contains "
|
|
136
|
+
assert_contains "sync create writes github_issue label" "github_issue:42" "$log_contents"
|
|
137
|
+
assert_contains "sync create calls issue update for the label" "issue update" "$log_contents"
|
|
138
|
+
assert_contains "sync create persists mapping entry" '"42": "beads-001"' "$(cat "$mapping_file")"
|
|
111
139
|
|
|
112
|
-
|
|
113
|
-
echo ""
|
|
114
|
-
echo "── Test 2: sync_issue_claim ──"
|
|
140
|
+
echo
|
|
141
|
+
echo "== Test 2: sync_issue_claim =="
|
|
115
142
|
> "$log_file"
|
|
116
143
|
unset _GITHUB_USER_CACHE
|
|
117
144
|
rc=0
|
|
118
145
|
sync_issue_claim "beads-001" || rc=$?
|
|
119
146
|
assert_exit "exit code 0" 0 "$rc"
|
|
120
147
|
log_contents="$(cat "$log_file")"
|
|
148
|
+
assert_contains "canonical lookup uses --json" "--json" "$log_contents"
|
|
121
149
|
assert_contains "gh issue edit called" "issue edit" "$log_contents"
|
|
122
150
|
assert_contains "add-assignee used" "--add-assignee" "$log_contents"
|
|
123
151
|
assert_contains "assignee is testuser" "testuser" "$log_contents"
|
|
124
152
|
|
|
125
|
-
|
|
126
|
-
echo ""
|
|
127
|
-
echo "── Test 3: sync_issue_status ──"
|
|
153
|
+
echo
|
|
154
|
+
echo "== Test 3: sync_issue_status =="
|
|
128
155
|
> "$log_file"
|
|
129
156
|
rc=0
|
|
130
157
|
sync_issue_status "beads-001" "in_progress" || rc=$?
|
|
131
158
|
assert_exit "exit code 0" 0 "$rc"
|
|
132
159
|
log_contents="$(cat "$log_file")"
|
|
160
|
+
assert_contains "canonical lookup uses --json" "--json" "$log_contents"
|
|
133
161
|
assert_contains "gh issue edit called" "issue edit" "$log_contents"
|
|
134
162
|
assert_contains "removes status/open" "--remove-label status/open" "$log_contents"
|
|
135
163
|
assert_contains "adds status/in-progress" "--add-label status/in-progress" "$log_contents"
|
|
136
164
|
|
|
137
|
-
|
|
138
|
-
echo ""
|
|
139
|
-
echo "── Test 4: sync_issue_close ──"
|
|
165
|
+
echo
|
|
166
|
+
echo "== Test 4: sync_issue_close =="
|
|
140
167
|
> "$log_file"
|
|
141
168
|
rc=0
|
|
142
169
|
sync_issue_close "beads-001" || rc=$?
|
|
143
170
|
assert_exit "exit code 0" 0 "$rc"
|
|
144
171
|
log_contents="$(cat "$log_file")"
|
|
172
|
+
assert_contains "canonical lookup uses --json" "--json" "$log_contents"
|
|
145
173
|
assert_contains "gh issue close called" "issue close" "$log_contents"
|
|
146
174
|
assert_contains "closes issue 42" " 42" "$log_contents"
|
|
147
175
|
|
|
148
|
-
|
|
149
|
-
echo ""
|
|
150
|
-
echo "── Test 5: sync_issue_deps ──"
|
|
176
|
+
echo
|
|
177
|
+
echo "== Test 5: sync_issue_deps =="
|
|
151
178
|
> "$log_file"
|
|
152
179
|
rc=0
|
|
153
180
|
sync_issue_deps "beads-001" "beads-002" || rc=$?
|
|
154
181
|
assert_exit "exit code 0" 0 "$rc"
|
|
155
182
|
log_contents="$(cat "$log_file")"
|
|
183
|
+
assert_contains "canonical lookup uses --json" "--json" "$log_contents"
|
|
156
184
|
assert_contains "gh issue comment called" "issue comment" "$log_contents"
|
|
157
185
|
assert_contains "Blocked by referenced" "Blocked by #42" "$log_contents"
|
|
158
186
|
|
|
159
|
-
|
|
160
|
-
echo ""
|
|
161
|
-
echo "── Test 6: _get_github_issue_number ──"
|
|
187
|
+
echo
|
|
188
|
+
echo "== Test 6: _get_github_issue_number =="
|
|
162
189
|
result="$(_get_github_issue_number "beads-001")"
|
|
163
190
|
assert_eq "extracts issue number 42" "42" "$result"
|
|
191
|
+
log_contents="$(cat "$log_file")"
|
|
192
|
+
assert_contains "_get_github_issue_number uses JSON" "--json" "$log_contents"
|
|
193
|
+
|
|
194
|
+
echo
|
|
195
|
+
echo "== Test 7: Mapping fallback when canonical GitHub number missing =="
|
|
196
|
+
mkdir -p "$(dirname "$mapping_file")"
|
|
197
|
+
cat > "$mapping_file" << 'JSON'
|
|
198
|
+
{
|
|
199
|
+
"77": "beads-999"
|
|
200
|
+
}
|
|
201
|
+
JSON
|
|
202
|
+
export FORGE_CMD="$mock_dir/forge-no-gh"
|
|
203
|
+
result="$(_get_github_issue_number "beads-999")"
|
|
204
|
+
assert_eq "mapping fallback returns issue number 77" "77" "$result"
|
|
205
|
+
export FORGE_CMD="$mock_dir/forge"
|
|
206
|
+
|
|
207
|
+
echo
|
|
208
|
+
echo "== Test 8: Mapping fallback returns newest issue number =="
|
|
209
|
+
cat > "$mapping_file" << 'JSON'
|
|
210
|
+
{
|
|
211
|
+
"77": "beads-999",
|
|
212
|
+
"91": "beads-999",
|
|
213
|
+
"88": "beads-other"
|
|
214
|
+
}
|
|
215
|
+
JSON
|
|
216
|
+
export FORGE_CMD="$mock_dir/forge-no-gh"
|
|
217
|
+
result="$(_get_github_issue_number "beads-999")"
|
|
218
|
+
assert_eq "mapping fallback returns newest matching issue number" "91" "$result"
|
|
219
|
+
export FORGE_CMD="$mock_dir/forge"
|
|
164
220
|
|
|
165
|
-
|
|
166
|
-
echo ""
|
|
167
|
-
|
|
168
|
-
export
|
|
221
|
+
echo
|
|
222
|
+
echo "== Test 9: Missing canonical GitHub number =="
|
|
223
|
+
rm -f "$mapping_file"
|
|
224
|
+
export FORGE_CMD="$mock_dir/forge-no-gh"
|
|
169
225
|
rc=0
|
|
170
226
|
result="$(_get_github_issue_number "beads-999" 2>/dev/null)" || rc=$?
|
|
171
|
-
assert_exit "returns error when no
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
227
|
+
assert_exit "returns error when no canonical github number" 1 "$rc"
|
|
228
|
+
export FORGE_CMD="$mock_dir/forge"
|
|
229
|
+
|
|
230
|
+
echo
|
|
231
|
+
echo "== Test 10: github_issue label lookup =="
|
|
232
|
+
cat > "$mock_dir/forge-legacy" << 'MOCK'
|
|
233
|
+
#!/usr/bin/env bash
|
|
234
|
+
echo "$*" >> "$LOG_FILE"
|
|
235
|
+
case "$1 $2" in
|
|
236
|
+
"issue show")
|
|
237
|
+
printf '{"data":{"issue":{"id":"beads-legacy","title":"Legacy Issue","labels":["github_issue:43"]}}}\n'
|
|
238
|
+
;;
|
|
239
|
+
"issue update") echo "Updated" ;;
|
|
240
|
+
esac
|
|
241
|
+
MOCK
|
|
242
|
+
chmod +x "$mock_dir/forge-legacy"
|
|
243
|
+
export FORGE_CMD="$mock_dir/forge-legacy"
|
|
244
|
+
rc=0
|
|
245
|
+
result="$(_get_github_issue_number "beads-legacy" 2>/dev/null)" || rc=$?
|
|
246
|
+
assert_exit "legacy github_issue exits successfully" 0 "$rc"
|
|
247
|
+
assert_eq "legacy github_issue returns number" "43" "$result"
|
|
248
|
+
export FORGE_CMD="$mock_dir/forge"
|
|
249
|
+
|
|
250
|
+
echo
|
|
251
|
+
echo "== Test 11: Injection in title sanitized =="
|
|
252
|
+
cat > "$mock_dir/forge-inject" << 'MOCK'
|
|
180
253
|
#!/usr/bin/env bash
|
|
181
254
|
echo "$*" >> "$LOG_FILE"
|
|
182
|
-
case "$1" in
|
|
183
|
-
show)
|
|
184
|
-
|
|
185
|
-
echo 'Title: Evil $(rm -rf /) Issue'
|
|
255
|
+
case "$1 $2" in
|
|
256
|
+
"issue show")
|
|
257
|
+
printf '{"data":{"issue":{"id":"beads-inject","title":"Evil $(rm -rf /) Issue","labels":["github_issue:99"]}}}\n'
|
|
186
258
|
;;
|
|
187
|
-
|
|
259
|
+
"issue update") echo "Updated" ;;
|
|
188
260
|
esac
|
|
189
261
|
MOCK
|
|
190
|
-
chmod +x "$mock_dir/
|
|
191
|
-
export
|
|
262
|
+
chmod +x "$mock_dir/forge-inject"
|
|
263
|
+
export FORGE_CMD="$mock_dir/forge-inject"
|
|
192
264
|
> "$log_file"
|
|
193
265
|
rc=0
|
|
194
266
|
sync_issue_create "beads-inject" || rc=$?
|
|
195
267
|
assert_exit "exit code 0 with injection" 0 "$rc"
|
|
196
268
|
log_contents="$(cat "$log_file")"
|
|
197
|
-
# The $(...) pattern must NOT appear in the gh call
|
|
198
269
|
if [[ "$log_contents" == *'$(rm'* ]]; then
|
|
199
|
-
FAIL=$((FAIL + 1))
|
|
270
|
+
FAIL=$((FAIL + 1))
|
|
271
|
+
echo " FAIL: injection NOT sanitized - \$\(rm found in gh call"
|
|
200
272
|
else
|
|
201
|
-
PASS=$((PASS + 1))
|
|
273
|
+
PASS=$((PASS + 1))
|
|
274
|
+
echo " PASS: injection sanitized - no \$\(rm in gh call"
|
|
202
275
|
fi
|
|
203
|
-
|
|
204
|
-
|
|
276
|
+
export FORGE_CMD="$mock_dir/forge"
|
|
277
|
+
|
|
278
|
+
echo
|
|
279
|
+
echo "== Test 11: sync_issue_create without grep -P =="
|
|
280
|
+
export PATH="$portable_bin:$ORIGINAL_PATH"
|
|
281
|
+
> "$log_file"
|
|
282
|
+
rc=0
|
|
283
|
+
sync_issue_create "beads-001" || rc=$?
|
|
284
|
+
assert_exit "sync_issue_create works when grep -P is unavailable" 0 "$rc"
|
|
285
|
+
log_contents="$(cat "$log_file")"
|
|
286
|
+
assert_contains "gh issue create called without PCRE grep" "issue create" "$log_contents"
|
|
287
|
+
export PATH="$ORIGINAL_PATH"
|
|
288
|
+
|
|
289
|
+
echo
|
|
290
|
+
echo "== Test 12: sync_issue_create reads title from issue show JSON =="
|
|
291
|
+
cat > "$mock_dir/forge-summary-only" << 'MOCK'
|
|
292
|
+
#!/usr/bin/env bash
|
|
293
|
+
echo "$*" >> "$LOG_FILE"
|
|
294
|
+
case "$1 $2" in
|
|
295
|
+
"issue show")
|
|
296
|
+
printf '{"data":{"issue":{"id":"beads-summary","title":"Summary Only Title","labels":["github_issue:77"]}}}\n'
|
|
297
|
+
;;
|
|
298
|
+
"issue update") echo "Updated" ;;
|
|
299
|
+
esac
|
|
300
|
+
MOCK
|
|
301
|
+
chmod +x "$mock_dir/forge-summary-only"
|
|
302
|
+
export FORGE_CMD="$mock_dir/forge-summary-only"
|
|
303
|
+
> "$log_file"
|
|
304
|
+
rc=0
|
|
305
|
+
sync_issue_create "beads-summary" || rc=$?
|
|
306
|
+
assert_exit "sync_issue_create works with title from issue show JSON" 0 "$rc"
|
|
307
|
+
log_contents="$(cat "$log_file")"
|
|
308
|
+
assert_contains "summary-only title is passed to gh issue create" "Summary Only Title" "$log_contents"
|
|
309
|
+
export FORGE_CMD="$mock_dir/forge"
|
|
205
310
|
|
|
206
|
-
|
|
207
|
-
echo ""
|
|
311
|
+
echo
|
|
208
312
|
echo "Results: $PASS passed, $FAIL failed"
|
|
209
313
|
[[ $FAIL -eq 0 ]] && exit 0 || exit 1
|
|
@@ -7,7 +7,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
|
7
7
|
TEST_TMP="$(mktemp -d)"
|
|
8
8
|
trap 'rm -rf "$TEST_TMP"' EXIT
|
|
9
9
|
|
|
10
|
-
# Override TEAM_MAP_ROOT so tests don't touch real .
|
|
10
|
+
# Override TEAM_MAP_ROOT so tests don't touch real .forge/
|
|
11
11
|
export TEAM_MAP_ROOT="$TEST_TMP"
|
|
12
12
|
|
|
13
13
|
# ── Create mock directories ────────────────────────────────────────────
|
|
@@ -66,47 +66,34 @@ exit 1
|
|
|
66
66
|
MOCK
|
|
67
67
|
chmod +x "$mock_dir/gh-noauth"
|
|
68
68
|
|
|
69
|
-
# ── Mock
|
|
70
|
-
|
|
69
|
+
# ── Mock forge (emits Kernel-shaped issue list JSON) ───────────────────
|
|
70
|
+
# The GitHub association lives in each issue's labels as github_issue:<n>.
|
|
71
|
+
# Tests drive which issues appear via FORGE_MOCK_OPEN / FORGE_MOCK_INPROGRESS
|
|
72
|
+
# (JSON arrays, each defaulting to []).
|
|
73
|
+
cat > "$mock_dir/forge" << 'MOCK'
|
|
71
74
|
#!/usr/bin/env bash
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
echo "Owner: devone"
|
|
84
|
-
if [[ -z "${BD_MOCK_NO_GITHUB_AAA:-}" ]]; then
|
|
85
|
-
echo "State: github_issue:10"
|
|
86
|
-
fi
|
|
87
|
-
;;
|
|
88
|
-
forge-bbb)
|
|
89
|
-
echo "○ forge-bbb · Feature B [● P2 · OPEN]"
|
|
90
|
-
echo "Owner: devtwo"
|
|
91
|
-
if [[ -z "${BD_MOCK_NO_GITHUB_BBB:-}" ]]; then
|
|
92
|
-
echo "State: github_issue:20"
|
|
93
|
-
fi
|
|
94
|
-
;;
|
|
95
|
-
forge-ccc)
|
|
96
|
-
echo "◐ forge-ccc · Feature C [● P1 · IN_PROGRESS]"
|
|
97
|
-
echo "Owner: devone"
|
|
98
|
-
# forge-ccc never has github_issue (for orphan tests)
|
|
99
|
-
;;
|
|
100
|
-
esac
|
|
101
|
-
exit 0
|
|
102
|
-
;;
|
|
103
|
-
esac
|
|
75
|
+
args="$*"
|
|
76
|
+
if [[ "$args" == *"issue list"* ]]; then
|
|
77
|
+
if [[ "$args" == *"--status=open"* ]]; then
|
|
78
|
+
printf '{"data":{"issues":%s}}\n' "${FORGE_MOCK_OPEN:-[]}"
|
|
79
|
+
elif [[ "$args" == *"--status=in_progress"* ]]; then
|
|
80
|
+
printf '{"data":{"issues":%s}}\n' "${FORGE_MOCK_INPROGRESS:-[]}"
|
|
81
|
+
else
|
|
82
|
+
printf '{"data":{"issues":[]}}\n'
|
|
83
|
+
fi
|
|
84
|
+
exit 0
|
|
85
|
+
fi
|
|
104
86
|
exit 0
|
|
105
87
|
MOCK
|
|
106
|
-
chmod +x "$mock_dir/
|
|
88
|
+
chmod +x "$mock_dir/forge"
|
|
89
|
+
|
|
90
|
+
# Reusable issue fixtures (synced issues carry a github_issue:<n> label)
|
|
91
|
+
ccc_orphan='{"id":"forge-ccc","title":"Feature C","status":"in_progress","assignee":"devone","labels":[],"dependencies":[]}'
|
|
92
|
+
aaa_synced='{"id":"forge-aaa","title":"Feature A","status":"in_progress","assignee":"devone","labels":["github_issue:10"],"dependencies":[]}'
|
|
93
|
+
bbb_synced='{"id":"forge-bbb","title":"Feature B","status":"open","assignee":"devtwo","labels":["github_issue:20"],"dependencies":[]}'
|
|
107
94
|
|
|
108
95
|
export GH_CMD="$mock_dir/gh"
|
|
109
|
-
export
|
|
96
|
+
export FORGE_CMD="$mock_dir/forge"
|
|
110
97
|
|
|
111
98
|
# Source the library under test
|
|
112
99
|
source "$SCRIPT_DIR/lib/agent-prompt.sh"
|
|
@@ -158,11 +145,12 @@ echo "── Test 1: All clean → exit 0 ──"
|
|
|
158
145
|
# Setup: identity exists in team map
|
|
159
146
|
unset _GITHUB_USER_CACHE
|
|
160
147
|
export GH_CMD="$mock_dir/gh"
|
|
161
|
-
export
|
|
148
|
+
export FORGE_CMD="$mock_dir/forge"
|
|
162
149
|
team_map_add "testuser" "Test User"
|
|
163
150
|
|
|
164
|
-
# No
|
|
165
|
-
export
|
|
151
|
+
# No tracked issues, no github issues
|
|
152
|
+
export FORGE_MOCK_OPEN="[]"
|
|
153
|
+
export FORGE_MOCK_INPROGRESS="[]"
|
|
166
154
|
export GH_MOCK_ISSUES="[]"
|
|
167
155
|
|
|
168
156
|
# Create empty mapping file
|
|
@@ -194,10 +182,11 @@ echo "── Test 3: Orphan Beads issue detected ──"
|
|
|
194
182
|
|
|
195
183
|
unset _GITHUB_USER_CACHE
|
|
196
184
|
export GH_CMD="$mock_dir/gh"
|
|
197
|
-
export
|
|
185
|
+
export FORGE_MOCK_OPEN="[]"
|
|
186
|
+
export FORGE_MOCK_INPROGRESS="[$ccc_orphan]"
|
|
198
187
|
export GH_MOCK_ISSUES="[]"
|
|
199
188
|
|
|
200
|
-
# forge-ccc
|
|
189
|
+
# forge-ccc carries no github_issue label (see fixtures above)
|
|
201
190
|
rc=0
|
|
202
191
|
output="$(cmd_verify 2>&1)" || rc=$?
|
|
203
192
|
assert_exit "orphan beads exits 1" 1 "$rc"
|
|
@@ -210,7 +199,8 @@ echo "── Test 4: Orphan GitHub issue detected ──"
|
|
|
210
199
|
|
|
211
200
|
unset _GITHUB_USER_CACHE
|
|
212
201
|
export GH_CMD="$mock_dir/gh"
|
|
213
|
-
export
|
|
202
|
+
export FORGE_MOCK_OPEN="[]"
|
|
203
|
+
export FORGE_MOCK_INPROGRESS="[]"
|
|
214
204
|
export GH_MOCK_ISSUES='[{"number":42,"title":"Some feature"},{"number":45,"title":"Another feature"}]'
|
|
215
205
|
|
|
216
206
|
# Mapping file has neither #42 nor #45
|
|
@@ -231,8 +221,8 @@ unset _GITHUB_USER_CACHE
|
|
|
231
221
|
export GH_CMD="$mock_dir/gh"
|
|
232
222
|
|
|
233
223
|
# Setup: forge-aaa has github_issue:10, forge-bbb has github_issue:20
|
|
234
|
-
export
|
|
235
|
-
|
|
224
|
+
export FORGE_MOCK_OPEN="[$bbb_synced]"
|
|
225
|
+
export FORGE_MOCK_INPROGRESS="[$aaa_synced]"
|
|
236
226
|
|
|
237
227
|
# Create mapping with both issues
|
|
238
228
|
cat > "$TEST_TMP/.github/beads-mapping.json" << 'EOF'
|
|
@@ -300,7 +290,8 @@ echo "── Test 6: No issues at all → exit 0 ──"
|
|
|
300
290
|
|
|
301
291
|
unset _GITHUB_USER_CACHE
|
|
302
292
|
export GH_CMD="$mock_dir/gh"
|
|
303
|
-
export
|
|
293
|
+
export FORGE_MOCK_OPEN="[]"
|
|
294
|
+
export FORGE_MOCK_INPROGRESS="[]"
|
|
304
295
|
export GH_MOCK_ISSUES="[]"
|
|
305
296
|
echo '{}' > "$TEST_TMP/.github/beads-mapping.json"
|
|
306
297
|
|
|
@@ -31,11 +31,11 @@ assert_contains_file "ship calls sync" "forge-team.*sync" "$SHIP"
|
|
|
31
31
|
assert_contains_file "ship calls verify" "forge-team.*verify" "$SHIP"
|
|
32
32
|
|
|
33
33
|
echo ""
|
|
34
|
-
echo "──
|
|
35
|
-
if
|
|
36
|
-
|
|
34
|
+
echo "── Skill sync check ──"
|
|
35
|
+
if (cd "$SCRIPT_DIR" && node -e "const r=require('./lib/skills-sync').checkSkillsSync({repoRoot:process.cwd()}); process.exit(r.inSync?0:1)"); then
|
|
36
|
+
PASS=$((PASS + 1)); echo " PASS: all agent skill dirs in sync"
|
|
37
37
|
else
|
|
38
|
-
|
|
38
|
+
FAIL=$((FAIL + 1)); echo " FAIL: skill drift detected"
|
|
39
39
|
fi
|
|
40
40
|
|
|
41
41
|
echo ""
|