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,347 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Opt-in GLOBAL-config native hook installer for the two harnesses whose hook
|
|
5
|
+
* surface lives in home-directory config, which project `forge setup`
|
|
6
|
+
* intentionally never writes (kernel issue 66dd5a1f, epics 90f2f631 + 1390e1d1):
|
|
7
|
+
*
|
|
8
|
+
* - Codex : `$CODEX_HOME/config.toml` (default `~/.codex/config.toml`) — the
|
|
9
|
+
* `[[hooks.PreToolUse]]` groups rendered by renderCodexHooksToml.
|
|
10
|
+
* - Hermes : `~/.hermes/config.yaml` — the `hooks:`/`pre_tool_call:` shell-hook
|
|
11
|
+
* entries rendered by renderHermesHooksYaml.
|
|
12
|
+
*
|
|
13
|
+
* CONSENT-GUARDED: this module only runs from `forge hooks install --global`
|
|
14
|
+
* (lib/commands/hooks.js), never from project setup. Same discipline as
|
|
15
|
+
* lib/hook-renderer.js / lib/mcp-config-renderer.js: read → MERGE → write,
|
|
16
|
+
* idempotent via the `forge-native-hook.js` marker, unparseable-for-merging
|
|
17
|
+
* existing config → backed up (backupFile) + skipped, never overwritten.
|
|
18
|
+
*
|
|
19
|
+
* ADAPTER-PATH RESOLUTION (why a project-relative command works in global config):
|
|
20
|
+
* the rendered commands invoke `node .forge/hooks/forge-native-hook.js ...`
|
|
21
|
+
* RELATIVE to the harness's working directory. Codex and Hermes execute hook
|
|
22
|
+
* commands from the workspace root (S7/S16 in lib/harness-capability-matrix.js),
|
|
23
|
+
* so inside any Forge-initialized project the command resolves to THAT project's
|
|
24
|
+
* installed adapter. In a directory without `.forge/hooks/forge-native-hook.js`
|
|
25
|
+
* (a non-Forge project), node exits non-zero WITHOUT emitting a deny decision on
|
|
26
|
+
* stdout — both harnesses only block on an explicit decision payload, so the
|
|
27
|
+
* hook fails OPEN and Forge enforcement simply does not apply there.
|
|
28
|
+
*
|
|
29
|
+
* Dependency-free (no TOML/YAML lib): the mergers are conservative line-based
|
|
30
|
+
* block editors that refuse (HookConfigParseError) any existing shape they
|
|
31
|
+
* cannot merge into without risking corruption.
|
|
32
|
+
*
|
|
33
|
+
* @module hook-global-installer
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
const fs = require('node:fs');
|
|
37
|
+
const os = require('node:os');
|
|
38
|
+
const path = require('node:path');
|
|
39
|
+
|
|
40
|
+
const {
|
|
41
|
+
FORGE_HOOK_CONTRACT,
|
|
42
|
+
FORGE_HOOK_MARKER,
|
|
43
|
+
HookConfigParseError,
|
|
44
|
+
renderCodexHooksToml,
|
|
45
|
+
renderHermesHooksYaml,
|
|
46
|
+
} = require('./hook-renderer');
|
|
47
|
+
const { backupFile } = require('./mcp-config-renderer');
|
|
48
|
+
const { resolveCodexHome } = require('./codex-skills');
|
|
49
|
+
|
|
50
|
+
/** The harnesses whose native hooks live in GLOBAL (home-dir) config. */
|
|
51
|
+
const GLOBAL_HOOK_HARNESSES = ['codex', 'hermes'];
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Resolve the global hook config file for a harness.
|
|
55
|
+
* Codex honors $CODEX_HOME (same resolution as lib/codex-skills.js / #311).
|
|
56
|
+
* @param {'codex'|'hermes'} harness
|
|
57
|
+
* @param {{ env?: object, homeDir?: string }} [options]
|
|
58
|
+
* @returns {string} absolute config file path
|
|
59
|
+
*/
|
|
60
|
+
function resolveGlobalHookFile(harness, options = {}) {
|
|
61
|
+
if (harness === 'codex') {
|
|
62
|
+
return path.join(resolveCodexHome(options), 'config.toml');
|
|
63
|
+
}
|
|
64
|
+
if (harness === 'hermes') {
|
|
65
|
+
return path.join(options.homeDir || os.homedir(), '.hermes', 'config.yaml');
|
|
66
|
+
}
|
|
67
|
+
throw new Error(`Harness '${harness}' has no global hook config surface`);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function normalizedTomlHeader(line) {
|
|
71
|
+
return line.trim().replace(/\s+/g, '');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Remove Forge-owned `[[hooks.PreToolUse]]` groups (a group = the PreToolUse
|
|
76
|
+
* header segment plus its immediately-following `[[hooks.PreToolUse.hooks]]`
|
|
77
|
+
* segments) whose lines carry the forge-native-hook.js marker. Everything else
|
|
78
|
+
* — user tables, comments, user hook groups — is preserved verbatim.
|
|
79
|
+
*/
|
|
80
|
+
function stripForgeCodexHookGroups(text) {
|
|
81
|
+
const lines = String(text).split('\n');
|
|
82
|
+
const segments = [];
|
|
83
|
+
let current = { header: null, lines: [] };
|
|
84
|
+
for (const line of lines) {
|
|
85
|
+
if (line.trim().startsWith('[')) {
|
|
86
|
+
segments.push(current);
|
|
87
|
+
current = { header: normalizedTomlHeader(line), lines: [line] };
|
|
88
|
+
} else {
|
|
89
|
+
current.lines.push(line);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
segments.push(current);
|
|
93
|
+
|
|
94
|
+
const out = [];
|
|
95
|
+
for (let i = 0; i < segments.length; i += 1) {
|
|
96
|
+
const seg = segments[i];
|
|
97
|
+
if (seg.header === '[[hooks.PreToolUse]]') {
|
|
98
|
+
const group = [seg];
|
|
99
|
+
let j = i + 1;
|
|
100
|
+
while (j < segments.length && segments[j].header === '[[hooks.PreToolUse.hooks]]') {
|
|
101
|
+
group.push(segments[j]);
|
|
102
|
+
j += 1;
|
|
103
|
+
}
|
|
104
|
+
const forgeOwned = group.some(s => s.lines.some(l => l.includes(FORGE_HOOK_MARKER)));
|
|
105
|
+
if (!forgeOwned) {
|
|
106
|
+
for (const s of group) out.push(...s.lines);
|
|
107
|
+
}
|
|
108
|
+
i = j - 1;
|
|
109
|
+
} else {
|
|
110
|
+
out.push(...seg.lines);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return out.join('\n');
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/** True when the `[hooks]` table section assigns PreToolUse as a plain key. */
|
|
117
|
+
function hooksTableAssignsPreToolUse(text) {
|
|
118
|
+
const lines = String(text).split('\n');
|
|
119
|
+
let inHooksTable = false;
|
|
120
|
+
for (const line of lines) {
|
|
121
|
+
const trimmed = line.trim();
|
|
122
|
+
if (trimmed.startsWith('[')) {
|
|
123
|
+
inHooksTable = normalizedTomlHeader(line) === '[hooks]';
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
if (inHooksTable && /^PreToolUse\s*=/.test(trimmed)) return true;
|
|
127
|
+
}
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Merge Forge's `[[hooks.PreToolUse]]` groups into an existing Codex global
|
|
133
|
+
* `config.toml` string. Preserves ALL existing user config (idempotent via the
|
|
134
|
+
* forge-native-hook.js marker). TOML permits re-opening an array-of-tables
|
|
135
|
+
* later in the document, so appending fresh Forge groups after the preserved
|
|
136
|
+
* content is always valid — UNLESS `hooks.PreToolUse` already exists in a
|
|
137
|
+
* non-array shape, which is refused with HookConfigParseError (never corrupt).
|
|
138
|
+
* @param {string} existingText
|
|
139
|
+
* @param {object} [contract]
|
|
140
|
+
* @returns {string}
|
|
141
|
+
*/
|
|
142
|
+
function mergeCodexGlobalConfigToml(existingText, contract = FORGE_HOOK_CONTRACT) {
|
|
143
|
+
const text = String(existingText || '');
|
|
144
|
+
const hasPlainPreToolUseTable = text
|
|
145
|
+
.split('\n')
|
|
146
|
+
.some(line => normalizedTomlHeader(line) === '[hooks.PreToolUse]');
|
|
147
|
+
if (hasPlainPreToolUseTable || hooksTableAssignsPreToolUse(text)) {
|
|
148
|
+
throw new HookConfigParseError(
|
|
149
|
+
'existing config defines hooks.PreToolUse in a non-array shape; appending '
|
|
150
|
+
+ '[[hooks.PreToolUse]] would corrupt the file',
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const preamble = stripForgeCodexHookGroups(text).replace(/\s+$/, '');
|
|
155
|
+
const rendered = renderCodexHooksToml(contract);
|
|
156
|
+
const result = (preamble ? preamble + '\n\n' : '') + rendered;
|
|
157
|
+
return result.replace(/\n{3,}/g, '\n\n').replace(/\s+$/, '') + '\n';
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/** The rendered Hermes pre_tool_call list items, re-indented to `itemIndent` spaces. */
|
|
161
|
+
function hermesForgeItems(contract, itemIndent) {
|
|
162
|
+
// renderHermesHooksYaml emits `hooks:\n pre_tool_call:\n` then item lines at a
|
|
163
|
+
// 4-space base indent; strip the first two lines and re-base the indentation.
|
|
164
|
+
const rendered = renderHermesHooksYaml(contract).split('\n');
|
|
165
|
+
return rendered
|
|
166
|
+
.slice(2)
|
|
167
|
+
.filter(line => line.trim().length > 0)
|
|
168
|
+
.map(line => ' '.repeat(itemIndent) + line.slice(4));
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/** Split a YAML block-sequence body into items (each starting at a `- ` line). */
|
|
172
|
+
function splitYamlListItems(lines) {
|
|
173
|
+
const items = [];
|
|
174
|
+
let current = null;
|
|
175
|
+
for (const line of lines) {
|
|
176
|
+
if (/^\s*- /.test(line)) {
|
|
177
|
+
if (current) items.push(current);
|
|
178
|
+
current = [line];
|
|
179
|
+
} else if (current) {
|
|
180
|
+
current.push(line);
|
|
181
|
+
} else {
|
|
182
|
+
// Content before the first `- ` item (comments/blank lines) — keep as its own chunk.
|
|
183
|
+
items.push([line]);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
if (current) items.push(current);
|
|
187
|
+
return items;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Merge Forge's `pre_tool_call` shell-hook entries into an existing Hermes
|
|
192
|
+
* global `config.yaml` string. Preserves all user keys, the user's own hook
|
|
193
|
+
* entries, and other hook events; replaces only Forge-owned entries
|
|
194
|
+
* (idempotent via the forge-native-hook.js marker). Shapes it cannot merge
|
|
195
|
+
* without risking corruption (tabs, inline `hooks:`/`pre_tool_call:` values)
|
|
196
|
+
* are refused with HookConfigParseError so the caller backs up + skips.
|
|
197
|
+
* @param {string} existingText
|
|
198
|
+
* @param {object} [contract]
|
|
199
|
+
* @returns {string}
|
|
200
|
+
*/
|
|
201
|
+
function mergeHermesGlobalConfigYaml(existingText, contract = FORGE_HOOK_CONTRACT) {
|
|
202
|
+
const text = String(existingText || '');
|
|
203
|
+
if (!text.trim()) return renderHermesHooksYaml(contract);
|
|
204
|
+
if (text.includes('\t')) {
|
|
205
|
+
throw new HookConfigParseError('existing Hermes config contains tabs — cannot merge safely');
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const lines = text.split('\n');
|
|
209
|
+
const inlineHooks = lines.some(l => /^hooks:\s*[^\s#]/.test(l));
|
|
210
|
+
if (inlineHooks) {
|
|
211
|
+
throw new HookConfigParseError(
|
|
212
|
+
'existing `hooks:` key has an inline value Forge cannot merge into',
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const hooksIdx = lines.findIndex(l => /^hooks:\s*(#.*)?$/.test(l));
|
|
217
|
+
if (hooksIdx === -1) {
|
|
218
|
+
const base = text.replace(/\s+$/, '');
|
|
219
|
+
return base + '\n\n' + renderHermesHooksYaml(contract);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// The hooks block spans until the next non-blank line at column 0.
|
|
223
|
+
let hooksEnd = hooksIdx + 1;
|
|
224
|
+
while (hooksEnd < lines.length && !(lines[hooksEnd] && /^\S/.test(lines[hooksEnd]))) {
|
|
225
|
+
hooksEnd += 1;
|
|
226
|
+
}
|
|
227
|
+
const block = lines.slice(hooksIdx + 1, hooksEnd);
|
|
228
|
+
|
|
229
|
+
const preToolRel = block.findIndex(l => /^\s+pre_tool_call:\s*(#.*)?$/.test(l));
|
|
230
|
+
const inlinePreTool = block.some(l => /^\s+pre_tool_call:\s*[^\s#]/.test(l));
|
|
231
|
+
if (inlinePreTool) {
|
|
232
|
+
throw new HookConfigParseError(
|
|
233
|
+
'existing `pre_tool_call:` key has an inline value Forge cannot merge into',
|
|
234
|
+
);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
let newBlock;
|
|
238
|
+
if (preToolRel === -1) {
|
|
239
|
+
// No pre_tool_call event yet — append ours at the end of the hooks block.
|
|
240
|
+
newBlock = [...block, ' pre_tool_call:', ...hermesForgeItems(contract, 4)];
|
|
241
|
+
} else {
|
|
242
|
+
const keyIndent = (block[preToolRel].match(/^\s*/) || [''])[0].length;
|
|
243
|
+
// The pre_tool_call sub-block spans until the next non-blank line indented
|
|
244
|
+
// at or shallower than the key itself.
|
|
245
|
+
let subEnd = preToolRel + 1;
|
|
246
|
+
while (subEnd < block.length) {
|
|
247
|
+
const line = block[subEnd];
|
|
248
|
+
if (line.trim() && (line.match(/^\s*/) || [''])[0].length <= keyIndent) break;
|
|
249
|
+
subEnd += 1;
|
|
250
|
+
}
|
|
251
|
+
const subBody = block.slice(preToolRel + 1, subEnd);
|
|
252
|
+
const kept = splitYamlListItems(subBody)
|
|
253
|
+
.filter(item => !item.some(l => l.includes(FORGE_HOOK_MARKER)))
|
|
254
|
+
.flat();
|
|
255
|
+
const firstItem = subBody.find(l => /^\s*- /.test(l));
|
|
256
|
+
const itemIndent = firstItem ? (firstItem.match(/^\s*/) || [''])[0].length : keyIndent + 2;
|
|
257
|
+
newBlock = [
|
|
258
|
+
...block.slice(0, preToolRel + 1),
|
|
259
|
+
...kept,
|
|
260
|
+
...hermesForgeItems(contract, itemIndent),
|
|
261
|
+
...block.slice(subEnd),
|
|
262
|
+
];
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
const merged = [...lines.slice(0, hooksIdx + 1), ...newBlock, ...lines.slice(hooksEnd)];
|
|
266
|
+
return merged.join('\n').replace(/\n{3,}/g, '\n\n').replace(/\s+$/, '') + '\n';
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
const GLOBAL_MERGERS = {
|
|
270
|
+
codex: mergeCodexGlobalConfigToml,
|
|
271
|
+
hermes: mergeHermesGlobalConfigYaml,
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
/** The Forge hook block a harness's global config receives (for consent output). */
|
|
275
|
+
function renderGlobalHookBlock(harness, contract = FORGE_HOOK_CONTRACT) {
|
|
276
|
+
if (harness === 'codex') return renderCodexHooksToml(contract);
|
|
277
|
+
if (harness === 'hermes') return renderHermesHooksYaml(contract);
|
|
278
|
+
throw new Error(`Harness '${harness}' has no global hook config surface`);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Install (merge) Forge's native hooks into the GLOBAL configs of the given
|
|
283
|
+
* harnesses. Read → merge → write; dry-run returns previews without touching
|
|
284
|
+
* disk (no writes, no directories, no backups). Unmergeable existing config is
|
|
285
|
+
* backed up (backupFile) and skipped — never overwritten.
|
|
286
|
+
*
|
|
287
|
+
* @param {object} [params]
|
|
288
|
+
* @param {string[]} [params.harnesses] - subset of GLOBAL_HOOK_HARNESSES
|
|
289
|
+
* @param {boolean} [params.dryRun]
|
|
290
|
+
* @param {object} [params.env] - env override (CODEX_HOME resolution / tests)
|
|
291
|
+
* @param {string} [params.homeDir] - home-dir override (tests)
|
|
292
|
+
* @param {object} [params.contract]
|
|
293
|
+
* @returns {Array<{ harness: string, file: string, existed: boolean, wrote: boolean,
|
|
294
|
+
* skipped: boolean, changed?: boolean, dryRun?: boolean,
|
|
295
|
+
* preview?: string, backup?: string, reason?: string }>}
|
|
296
|
+
*/
|
|
297
|
+
function installGlobalHooks({
|
|
298
|
+
harnesses = GLOBAL_HOOK_HARNESSES,
|
|
299
|
+
dryRun = false,
|
|
300
|
+
env,
|
|
301
|
+
homeDir,
|
|
302
|
+
contract = FORGE_HOOK_CONTRACT,
|
|
303
|
+
} = {}) {
|
|
304
|
+
return harnesses.map((harness) => {
|
|
305
|
+
const merge = GLOBAL_MERGERS[harness];
|
|
306
|
+
if (!merge) throw new Error(`Harness '${harness}' has no global hook config surface`);
|
|
307
|
+
|
|
308
|
+
const file = resolveGlobalHookFile(harness, { env, homeDir });
|
|
309
|
+
const existed = fs.existsSync(file);
|
|
310
|
+
const existing = existed ? fs.readFileSync(file, 'utf-8') : '';
|
|
311
|
+
|
|
312
|
+
let merged;
|
|
313
|
+
try {
|
|
314
|
+
merged = merge(existing, contract);
|
|
315
|
+
} catch (err) {
|
|
316
|
+
if (err instanceof HookConfigParseError) {
|
|
317
|
+
const result = {
|
|
318
|
+
harness, file, existed, wrote: false, skipped: true, reason: err.message,
|
|
319
|
+
};
|
|
320
|
+
if (dryRun) return { ...result, dryRun: true };
|
|
321
|
+
if (existed) result.backup = backupFile(file);
|
|
322
|
+
return result;
|
|
323
|
+
}
|
|
324
|
+
throw err;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
const changed = merged !== existing;
|
|
328
|
+
if (dryRun) {
|
|
329
|
+
return {
|
|
330
|
+
harness, file, existed, wrote: false, skipped: false,
|
|
331
|
+
changed, dryRun: true, preview: merged,
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
335
|
+
if (changed) fs.writeFileSync(file, merged, 'utf-8');
|
|
336
|
+
return { harness, file, existed, wrote: true, skipped: false, changed };
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
module.exports = {
|
|
341
|
+
GLOBAL_HOOK_HARNESSES,
|
|
342
|
+
resolveGlobalHookFile,
|
|
343
|
+
mergeCodexGlobalConfigToml,
|
|
344
|
+
mergeHermesGlobalConfigYaml,
|
|
345
|
+
renderGlobalHookBlock,
|
|
346
|
+
installGlobalHooks,
|
|
347
|
+
};
|