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
|
@@ -9,34 +9,152 @@ const { getWorkflowPath, WORKFLOW_CLASSIFICATIONS, normalizeStageId } = require(
|
|
|
9
9
|
|
|
10
10
|
const WORKFLOW_STATE_FILENAME = '.forge-state.json';
|
|
11
11
|
|
|
12
|
+
function parseRelaxedWorkflowStatePayload(payload = '') {
|
|
13
|
+
const currentStage = String(payload).match(/currentStage:([a-z]+)/)?.[1];
|
|
14
|
+
if (!currentStage) {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const completedStages = (String(payload).match(/completedStages:\[([^\]]*)\]/)?.[1] || '')
|
|
19
|
+
.split(',')
|
|
20
|
+
.map(stage => stage.trim())
|
|
21
|
+
.filter(Boolean);
|
|
22
|
+
const skippedStages = (String(payload).match(/skippedStages:\[([^\]]*)\]/)?.[1] || '')
|
|
23
|
+
.split(',')
|
|
24
|
+
.map(stage => stage.trim())
|
|
25
|
+
.filter(Boolean);
|
|
26
|
+
const classification = String(payload).match(/classification:([a-z]+)/)?.[1] || 'standard';
|
|
27
|
+
const reason = String(payload).match(/reason:([^,}\]]+)/)?.[1]?.trim() || 'legacy-comment';
|
|
28
|
+
|
|
29
|
+
return readWorkflowState(JSON.stringify({
|
|
30
|
+
currentStage,
|
|
31
|
+
completedStages,
|
|
32
|
+
skippedStages,
|
|
33
|
+
workflowDecisions: {
|
|
34
|
+
classification,
|
|
35
|
+
reason,
|
|
36
|
+
userOverride: false,
|
|
37
|
+
overrides: [],
|
|
38
|
+
},
|
|
39
|
+
parallelTracks: [],
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
42
|
+
|
|
12
43
|
function extractWorkflowStateFromComments(comments = '') {
|
|
13
|
-
const matches = String(comments)
|
|
44
|
+
const matches = String(comments)
|
|
45
|
+
.split(/\r?\n/)
|
|
46
|
+
.filter(line => line.startsWith('WorkflowState:'));
|
|
14
47
|
if (!matches || matches.length === 0) {
|
|
15
48
|
return null;
|
|
16
49
|
}
|
|
17
50
|
|
|
18
|
-
const
|
|
19
|
-
|
|
51
|
+
for (const match of [...matches].reverse()) {
|
|
52
|
+
const payload = match.replace(/^WorkflowState:\s*/, '');
|
|
53
|
+
try {
|
|
54
|
+
return readWorkflowState(payload);
|
|
55
|
+
} catch (_strictError) {
|
|
56
|
+
try {
|
|
57
|
+
const relaxedState = parseRelaxedWorkflowStatePayload(payload);
|
|
58
|
+
if (relaxedState) {
|
|
59
|
+
return relaxedState;
|
|
60
|
+
}
|
|
61
|
+
} catch (_relaxedError) {
|
|
62
|
+
// Continue to any earlier payloads.
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return null;
|
|
20
68
|
}
|
|
21
69
|
|
|
22
|
-
function
|
|
70
|
+
function extractWorkflowStateFromIssue(issue = {}) {
|
|
71
|
+
if (!issue || typeof issue !== 'object') {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (typeof issue.comments === 'string') {
|
|
76
|
+
return extractWorkflowStateFromComments(issue.comments);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (!Array.isArray(issue.comments) || issue.comments.length === 0) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const mergedComments = issue.comments
|
|
84
|
+
.map(comment => {
|
|
85
|
+
if (typeof comment === 'string') {
|
|
86
|
+
return comment;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return comment && typeof comment === 'object' ? comment.text || '' : '';
|
|
90
|
+
})
|
|
91
|
+
.filter(Boolean)
|
|
92
|
+
.join('\n');
|
|
93
|
+
|
|
94
|
+
if (!mergedComments) {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return extractWorkflowStateFromComments(mergedComments);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function readBeadsIssue(issueId, options = {}) {
|
|
23
102
|
if (!issueId) {
|
|
24
103
|
return null;
|
|
25
104
|
}
|
|
26
105
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
106
|
+
try {
|
|
107
|
+
const { projectRoot, ...execOptions } = options;
|
|
108
|
+
const raw = secureExecFileSync('forge', ['issue', 'show', issueId, '--json'], {
|
|
109
|
+
encoding: 'utf8',
|
|
110
|
+
cwd: projectRoot,
|
|
111
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
112
|
+
...execOptions,
|
|
113
|
+
}).trim();
|
|
114
|
+
|
|
115
|
+
if (!raw) {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const parsed = JSON.parse(raw);
|
|
120
|
+
if (Array.isArray(parsed)) {
|
|
121
|
+
return parsed[0] || null;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return parsed;
|
|
125
|
+
} catch (_error) {
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
31
129
|
|
|
32
|
-
|
|
130
|
+
function readWorkflowStateFromBeads(issueId, options = {}) {
|
|
131
|
+
if (!issueId) {
|
|
33
132
|
return null;
|
|
34
133
|
}
|
|
35
134
|
|
|
36
|
-
|
|
135
|
+
if (options.issue) {
|
|
136
|
+
const state = extractWorkflowStateFromIssue(options.issue);
|
|
137
|
+
if (state) {
|
|
138
|
+
return state;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (options.comments) {
|
|
143
|
+
const state = extractWorkflowStateFromComments(options.comments);
|
|
144
|
+
if (state) {
|
|
145
|
+
return state;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// `forge issue show --json` returns the issue together with its full comment
|
|
150
|
+
// history, so a single read covers both the structured issue and the raw
|
|
151
|
+
// comment text carrying the serialized WorkflowState marker. No separate
|
|
152
|
+
// comment-list read is required.
|
|
153
|
+
const issue = readBeadsIssue(issueId, { projectRoot: options.projectRoot });
|
|
154
|
+
return extractWorkflowStateFromIssue(issue);
|
|
37
155
|
}
|
|
38
156
|
|
|
39
|
-
function loadStateFromBeads(options) {
|
|
157
|
+
function loadStateFromBeads(options, projectRoot) {
|
|
40
158
|
if (options.comments) {
|
|
41
159
|
const state = extractWorkflowStateFromComments(options.comments);
|
|
42
160
|
if (state) {
|
|
@@ -44,8 +162,19 @@ function loadStateFromBeads(options) {
|
|
|
44
162
|
}
|
|
45
163
|
}
|
|
46
164
|
|
|
165
|
+
if (options.issue) {
|
|
166
|
+
const state = extractWorkflowStateFromIssue(options.issue);
|
|
167
|
+
if (state) {
|
|
168
|
+
return { state, source: 'beads' };
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
47
172
|
if (options.issueId) {
|
|
48
|
-
const state = readWorkflowStateFromBeads(options.issueId, {
|
|
173
|
+
const state = readWorkflowStateFromBeads(options.issueId, {
|
|
174
|
+
comments: options.comments,
|
|
175
|
+
issue: options.issue,
|
|
176
|
+
projectRoot,
|
|
177
|
+
});
|
|
49
178
|
if (state) {
|
|
50
179
|
return { state, source: 'beads' };
|
|
51
180
|
}
|
|
@@ -56,10 +185,24 @@ function loadStateFromBeads(options) {
|
|
|
56
185
|
|
|
57
186
|
function loadState(projectRoot, options = {}) {
|
|
58
187
|
if (!projectRoot) {
|
|
59
|
-
const beadsResult = loadStateFromBeads(options);
|
|
188
|
+
const beadsResult = loadStateFromBeads(options, null);
|
|
60
189
|
return beadsResult || { state: null, source: null };
|
|
61
190
|
}
|
|
62
191
|
|
|
192
|
+
if (options.preferBeads && (options.comments || options.issue || options.issueId)) {
|
|
193
|
+
try {
|
|
194
|
+
const beadsResult = loadStateFromBeads(options, projectRoot);
|
|
195
|
+
if (beadsResult) {
|
|
196
|
+
return beadsResult;
|
|
197
|
+
}
|
|
198
|
+
} catch (error) {
|
|
199
|
+
if (typeof options.onBeadsError === 'function') {
|
|
200
|
+
options.onBeadsError(error);
|
|
201
|
+
}
|
|
202
|
+
// Fall through to the on-disk state file when Beads cannot be read.
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
63
206
|
const statePath = path.join(projectRoot, WORKFLOW_STATE_FILENAME);
|
|
64
207
|
if (fs.existsSync(statePath)) {
|
|
65
208
|
try {
|
|
@@ -70,7 +213,7 @@ function loadState(projectRoot, options = {}) {
|
|
|
70
213
|
}
|
|
71
214
|
}
|
|
72
215
|
|
|
73
|
-
const beadsResult = loadStateFromBeads(options);
|
|
216
|
+
const beadsResult = loadStateFromBeads(options, projectRoot);
|
|
74
217
|
if (beadsResult) {
|
|
75
218
|
return beadsResult;
|
|
76
219
|
}
|
|
@@ -185,8 +328,10 @@ function transitionStage(projectRoot, toStage, options = {}) {
|
|
|
185
328
|
module.exports = {
|
|
186
329
|
WORKFLOW_STATE_FILENAME,
|
|
187
330
|
extractWorkflowStateFromComments,
|
|
331
|
+
extractWorkflowStateFromIssue,
|
|
188
332
|
initializeState,
|
|
189
333
|
loadState,
|
|
334
|
+
readBeadsIssue,
|
|
190
335
|
readWorkflowStateFromBeads,
|
|
191
336
|
saveState,
|
|
192
337
|
transitionStage,
|
package/lib/workflow/state.js
CHANGED
|
@@ -5,7 +5,7 @@ const {
|
|
|
5
5
|
STAGE_IDS,
|
|
6
6
|
STAGE_MODEL,
|
|
7
7
|
getWorkflowPath,
|
|
8
|
-
normalizeStageId,
|
|
8
|
+
normalizeStageId: normalizeCanonicalStageId,
|
|
9
9
|
} = require('./stages.js');
|
|
10
10
|
|
|
11
11
|
const WORKFLOW_STATE_SCHEMA_VERSION = 2;
|
|
@@ -19,6 +19,28 @@ const LEGACY_STANDARD_WORKFLOW_PATH = Object.freeze([
|
|
|
19
19
|
'premerge',
|
|
20
20
|
'verify',
|
|
21
21
|
]);
|
|
22
|
+
|
|
23
|
+
// Stages that the canonical model no longer recognizes but that legacy
|
|
24
|
+
// schemaVersion 1 standard workflows persisted (e.g. pre-merge, retired as a
|
|
25
|
+
// standalone stage and re-homed as a task-type gate). We still accept these ids
|
|
26
|
+
// when normalizing legacy state so historical .forge-state.json files survive a
|
|
27
|
+
// read/write round-trip. The workflow-path membership checks below remain the
|
|
28
|
+
// real guard: a non-legacy classification whose path omits the stage still
|
|
29
|
+
// rejects it, so accepting the id here never leaks retired stages into current
|
|
30
|
+
// flows.
|
|
31
|
+
const LEGACY_STAGE_IDS = Object.freeze(
|
|
32
|
+
LEGACY_STANDARD_WORKFLOW_PATH.filter(stage => !normalizeCanonicalStageId(stage))
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
function normalizeStageId(stage) {
|
|
36
|
+
const canonical = normalizeCanonicalStageId(stage);
|
|
37
|
+
if (canonical) {
|
|
38
|
+
return canonical;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const value = typeof stage === 'string' ? stage.trim() : '';
|
|
42
|
+
return LEGACY_STAGE_IDS.includes(value) ? value : null;
|
|
43
|
+
}
|
|
22
44
|
const LEGACY_WORKFLOW_STATE_OPTIONS = Object.freeze({
|
|
23
45
|
allowLegacyDefaultClassification: true,
|
|
24
46
|
allowLegacyStandardVerify: true,
|
package/lib/workflow-profiles.js
CHANGED
|
@@ -9,10 +9,17 @@
|
|
|
9
9
|
/**
|
|
10
10
|
* Internal workflow profiles aligned with AGENTS.md specification
|
|
11
11
|
*/
|
|
12
|
+
// `stages` lists ONLY the numbered workflow stages (aligned with the canonical stage
|
|
13
|
+
// model in lib/workflow/stages.js). `/status` is a utility — an always-available
|
|
14
|
+
// status/shepherd command, not a stage in any workflow — so it lives under
|
|
15
|
+
// `utilities`, never inside `stages`.
|
|
16
|
+
const UTILITIES = ['/status'];
|
|
17
|
+
|
|
12
18
|
const PROFILES = {
|
|
13
19
|
critical: {
|
|
14
20
|
name: 'Critical (Maximum Rigor)',
|
|
15
|
-
stages: ['/
|
|
21
|
+
stages: ['/plan', '/dev', '/validate', '/ship', '/review', '/verify'],
|
|
22
|
+
utilities: UTILITIES,
|
|
16
23
|
tdd: 'strict',
|
|
17
24
|
research: 'required',
|
|
18
25
|
description: 'Security, auth, payments, data integrity, breaking changes',
|
|
@@ -21,7 +28,8 @@ const PROFILES = {
|
|
|
21
28
|
|
|
22
29
|
standard: {
|
|
23
30
|
name: 'Standard (Full Workflow)',
|
|
24
|
-
stages: ['/
|
|
31
|
+
stages: ['/plan', '/dev', '/validate', '/ship', '/review'],
|
|
32
|
+
utilities: UTILITIES,
|
|
25
33
|
tdd: 'required',
|
|
26
34
|
research: 'optional',
|
|
27
35
|
description: 'Most features and non-critical enhancements'
|
|
@@ -29,7 +37,8 @@ const PROFILES = {
|
|
|
29
37
|
|
|
30
38
|
simple: {
|
|
31
39
|
name: 'Simple (Streamlined)',
|
|
32
|
-
stages: ['/dev', '/validate', '/ship'
|
|
40
|
+
stages: ['/dev', '/validate', '/ship'],
|
|
41
|
+
utilities: UTILITIES,
|
|
33
42
|
tdd: 'recommended',
|
|
34
43
|
research: 'skip',
|
|
35
44
|
description: 'UI tweaks, small improvements, minor fixes'
|
|
@@ -38,6 +47,7 @@ const PROFILES = {
|
|
|
38
47
|
hotfix: {
|
|
39
48
|
name: 'Hotfix (Emergency)',
|
|
40
49
|
stages: ['/dev', '/validate', '/ship'],
|
|
50
|
+
utilities: UTILITIES,
|
|
41
51
|
tdd: 'required', // Must reproduce bug
|
|
42
52
|
research: 'skip',
|
|
43
53
|
description: 'Production bugs, urgent fixes',
|
|
@@ -46,7 +56,8 @@ const PROFILES = {
|
|
|
46
56
|
|
|
47
57
|
docs: {
|
|
48
58
|
name: 'Docs (Documentation Only)',
|
|
49
|
-
stages: ['/verify', '/ship'
|
|
59
|
+
stages: ['/verify', '/ship'],
|
|
60
|
+
utilities: UTILITIES,
|
|
50
61
|
tdd: 'no',
|
|
51
62
|
research: 'no',
|
|
52
63
|
description: 'Documentation updates, README changes'
|
|
@@ -54,7 +65,8 @@ const PROFILES = {
|
|
|
54
65
|
|
|
55
66
|
refactor: {
|
|
56
67
|
name: 'Refactor (Behavior-Preserving)',
|
|
57
|
-
stages: ['/plan', '/dev', '/validate', '/ship'
|
|
68
|
+
stages: ['/plan', '/dev', '/validate', '/ship'],
|
|
69
|
+
utilities: UTILITIES,
|
|
58
70
|
tdd: 'strict', // Must preserve behavior
|
|
59
71
|
research: 'optional',
|
|
60
72
|
description: 'Code cleanup, optimization, behavior-preserving improvements'
|
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "forge-workflow",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.1.0-beta.2",
|
|
4
|
+
"description": "Local runtime control plane for AI-assisted engineering workflows, gates, evidence, and all AI agents",
|
|
5
5
|
"bin": {
|
|
6
6
|
"forge": "bin/forge.js",
|
|
7
|
+
"forge-workflow": "bin/forge.js",
|
|
7
8
|
"forge-preflight": "bin/forge-preflight.js"
|
|
8
9
|
},
|
|
9
10
|
"workspaces": [
|
|
@@ -12,18 +13,31 @@
|
|
|
12
13
|
"scripts": {
|
|
13
14
|
"test": "bun test --timeout 15000",
|
|
14
15
|
"test:setup": "bash test-env/automation/setup-fixtures.sh",
|
|
15
|
-
"test:all": "bun run test:setup && bun test",
|
|
16
|
-
"test:coverage": "c8 --check-coverage bun test",
|
|
16
|
+
"test:all": "bun run test:setup && bun test --timeout 15000",
|
|
17
|
+
"test:coverage": "c8 --check-coverage bun test --timeout 15000",
|
|
18
|
+
"test:ci:shard": "node scripts/test-ci-shard.js",
|
|
17
19
|
"typecheck": "echo 'No TypeScript in project - skipping type check'",
|
|
20
|
+
"gen:manifest": "node scripts/gen-command-manifest.js",
|
|
21
|
+
"gen:manifest:check": "node scripts/gen-command-manifest.js --check",
|
|
22
|
+
"prebuild": "node scripts/gen-command-manifest.js",
|
|
18
23
|
"lint": "eslint . --max-warnings 0",
|
|
19
|
-
"check": "
|
|
24
|
+
"check": "node scripts/validate.js",
|
|
20
25
|
"prepare": "lefthook install || echo 'Note: lefthook not installed. Git hooks disabled. Run: bun add -d lefthook'",
|
|
21
26
|
"setup": "node ./bin/forge.js setup",
|
|
22
27
|
"help": "node ./bin/forge.js --help",
|
|
28
|
+
"gen:assets": "bun scripts/gen-embedded-assets.mjs",
|
|
29
|
+
"build:binary": "bun scripts/gen-embedded-assets.mjs && bun build --compile --define FORGE_COMPILED=true ./bin/forge.js --outfile forge-bin",
|
|
30
|
+
"parity:binary": "bun scripts/parity-check.mjs",
|
|
23
31
|
"validate:yaml": "find . \\( -name '*.yml' -o -name '*.yaml' \\) | grep -v node_modules | while IFS= read -r file; do echo \"Checking $file...\" && bun x js-yaml \"$file\" > /dev/null || exit 1; done",
|
|
24
32
|
"test:mutation": "npx stryker run",
|
|
25
|
-
"test:benchmark": "node scripts/benchmark.js",
|
|
26
|
-
"test:
|
|
33
|
+
"test:benchmark": "node scripts/benchmark.js --output test-results/benchmark-results.json --profile-dir test-results/benchmark-profiles",
|
|
34
|
+
"test:benchmark:full": "node scripts/benchmark.js --output test-results/benchmark-full-results.json --profile-dir test-results/benchmark-full-profiles --group full-suite --group validate",
|
|
35
|
+
"test:full:parallel": "node scripts/test-full-suite.js",
|
|
36
|
+
"test:dashboard": "node scripts/test-dashboard.js",
|
|
37
|
+
"test:profile": "node scripts/test-profile.js --input-dir test-results --output test-results/test-profile.json --label local",
|
|
38
|
+
"test:randomized": "bun test --timeout 15000 --randomize",
|
|
39
|
+
"test:rerun": "bun test --timeout 15000 --rerun-each 2",
|
|
40
|
+
"agentic:sync": "node scripts/sync-agentic-workflow.js"
|
|
27
41
|
},
|
|
28
42
|
"peerDependencies": {
|
|
29
43
|
"lefthook": "^1.0.0"
|
|
@@ -34,17 +48,18 @@
|
|
|
34
48
|
}
|
|
35
49
|
},
|
|
36
50
|
"devDependencies": {
|
|
37
|
-
"@commitlint/cli": "^
|
|
38
|
-
"@commitlint/config-conventional": "^
|
|
51
|
+
"@commitlint/cli": "^21.0.0",
|
|
52
|
+
"@commitlint/config-conventional": "^21.0.0",
|
|
39
53
|
"@eslint/js": "^10.0.1",
|
|
40
54
|
"@microsoft/eslint-formatter-sarif": "^3.1.0",
|
|
41
55
|
"@stryker-mutator/core": "^9.6.0",
|
|
42
56
|
"c8": "^11.0.0",
|
|
43
57
|
"eslint": "^10.0.2",
|
|
58
|
+
"eslint-plugin-sonarjs": "^4.1.0",
|
|
44
59
|
"globals": "^17.3.0",
|
|
45
|
-
"js-yaml": "^
|
|
60
|
+
"js-yaml": "^5.1.0",
|
|
46
61
|
"lefthook": "^2.1.4",
|
|
47
|
-
"
|
|
62
|
+
"typescript": "5.4.5"
|
|
48
63
|
},
|
|
49
64
|
"keywords": [
|
|
50
65
|
"ai",
|
|
@@ -53,17 +68,15 @@
|
|
|
53
68
|
"agents-md",
|
|
54
69
|
"claude-code",
|
|
55
70
|
"cursor",
|
|
56
|
-
"kilo-code",
|
|
57
|
-
"opencode",
|
|
58
|
-
"copilot",
|
|
59
|
-
"cline",
|
|
60
|
-
"roo-code",
|
|
61
71
|
"codex",
|
|
62
72
|
"development",
|
|
63
73
|
"testing"
|
|
64
74
|
],
|
|
65
75
|
"author": "Harsha Nandak",
|
|
66
76
|
"license": "MIT",
|
|
77
|
+
"engines": {
|
|
78
|
+
"node": ">=22.16.0"
|
|
79
|
+
},
|
|
67
80
|
"repository": {
|
|
68
81
|
"type": "git",
|
|
69
82
|
"url": "git+https://github.com/harshanandak/forge.git"
|
|
@@ -75,47 +88,44 @@
|
|
|
75
88
|
"files": [
|
|
76
89
|
"bin/",
|
|
77
90
|
"lib/",
|
|
91
|
+
"rules/",
|
|
78
92
|
"skills/",
|
|
79
|
-
".claude/commands/",
|
|
80
93
|
".claude/rules/",
|
|
81
94
|
".claude/scripts/",
|
|
82
95
|
".claude/skills/",
|
|
83
96
|
".cursor/",
|
|
84
97
|
"!.cursor/node_modules/",
|
|
85
|
-
".cline/",
|
|
86
|
-
"!.cline/node_modules/",
|
|
87
|
-
".roo/",
|
|
88
|
-
"!.roo/node_modules/",
|
|
89
|
-
".codex/",
|
|
90
|
-
"!.codex/node_modules/",
|
|
91
|
-
".kilocode/",
|
|
92
|
-
"!.kilocode/node_modules/",
|
|
93
|
-
".opencode/",
|
|
94
|
-
"!.opencode/node_modules/",
|
|
95
98
|
"scripts/",
|
|
96
|
-
"
|
|
99
|
+
"!scripts/github-beads-sync/",
|
|
100
|
+
"!scripts/github-beads-sync.config.json",
|
|
101
|
+
"!scripts/**/*.test.js",
|
|
97
102
|
".github/PLUGIN_TEMPLATE.json",
|
|
98
|
-
".github/workflows/github-to-beads.yml",
|
|
99
|
-
".github/workflows/beads-to-github.yml",
|
|
100
103
|
".forge/hooks/",
|
|
104
|
+
".forge/protected-paths.yaml",
|
|
105
|
+
"CHANGELOG.md",
|
|
106
|
+
"QUICKSTART.md",
|
|
101
107
|
"docs/*.md",
|
|
108
|
+
"docs/architecture/**/*.md",
|
|
109
|
+
"docs/guides/*.md",
|
|
110
|
+
"docs/reference/*.md",
|
|
111
|
+
"docs/forge/*.md",
|
|
102
112
|
"install.sh",
|
|
103
113
|
"lefthook.yml",
|
|
104
114
|
"AGENTS.md",
|
|
105
115
|
"CLAUDE.md",
|
|
106
|
-
".mcp.json.example"
|
|
107
|
-
".cursorrules",
|
|
108
|
-
"opencode.json"
|
|
116
|
+
".mcp.json.example"
|
|
109
117
|
],
|
|
110
118
|
"dependencies": {
|
|
111
|
-
"@babel/parser": "^
|
|
112
|
-
"fastest-levenshtein": "^1.0.16"
|
|
119
|
+
"@babel/parser": "^8.0.0",
|
|
120
|
+
"fastest-levenshtein": "^1.0.16",
|
|
121
|
+
"yaml": "^2.8.3"
|
|
113
122
|
},
|
|
114
123
|
"overrides": {
|
|
115
124
|
"eslint": "^10.0.2",
|
|
125
|
+
"fast-uri": "^3.1.2",
|
|
116
126
|
"flatted": "3.4.2",
|
|
117
127
|
"minimatch": "10.2.4",
|
|
118
|
-
"brace-expansion": "5.0.
|
|
128
|
+
"brace-expansion": "5.0.6",
|
|
119
129
|
"lodash": "4.18.1"
|
|
120
130
|
},
|
|
121
131
|
"c8": {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Progressive documentation standards"
|
|
3
|
+
alwaysApply: false
|
|
4
|
+
globs: []
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Documentation Standards
|
|
8
|
+
|
|
9
|
+
Thin pointer — progressive documentation is part of every stage; the authoritative
|
|
10
|
+
guidance lives in `AGENTS.md` and the `ship`/`verify` skills. Do not duplicate it here.
|
|
11
|
+
|
|
12
|
+
Update documentation as you go, not at the end:
|
|
13
|
+
|
|
14
|
+
- **/plan** — record design intent, rationale, and alternatives in the plan doc.
|
|
15
|
+
- **/dev** — comment the *why* for non-obvious logic; keep JSDoc/TSDoc current.
|
|
16
|
+
- **/ship** — update README/CHANGELOG for user-facing or breaking changes.
|
|
17
|
+
- **/verify** — cross-check docs, validate examples, fix broken internal links.
|
|
18
|
+
|
|
19
|
+
Keep terminology consistent, link to code, and remove stale docs promptly.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Always: file every issue, idea, bug, and decision to the Forge Kernel"
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
globs: []
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Kernel Tracking (nothing discussed goes missing)
|
|
8
|
+
|
|
9
|
+
**NON-NEGOTIABLE.** Anything raised in a session — a bug, an idea, a design
|
|
10
|
+
decision, a follow-up, a TODO, a risk you noticed in passing — MUST become a
|
|
11
|
+
Forge Kernel issue **immediately**, before it can be forgotten. This is a
|
|
12
|
+
structural rule, not a judgment call.
|
|
13
|
+
|
|
14
|
+
- Found or discussed something trackable? Run `forge issue create` right then —
|
|
15
|
+
do not wait for "later" or the end of the session.
|
|
16
|
+
- Triage it: set a type and link it to its epic/parent so it is discoverable.
|
|
17
|
+
- Deferring work? File the follow-up issue and reference it — never leave scope
|
|
18
|
+
cuts unfiled.
|
|
19
|
+
- The Kernel is the single source of truth. Do NOT use TodoWrite, markdown TODO
|
|
20
|
+
lists, or memory notes as a substitute for a filed issue.
|
|
21
|
+
|
|
22
|
+
This rule is a **thin pointer** — the authoritative workflow contract lives in
|
|
23
|
+
`AGENTS.md` (see "Forge Issue Tracker") and the stage skills in
|
|
24
|
+
`skills/<stage>/SKILL.md`. It is default-on and governed by the
|
|
25
|
+
`rail.kernel_tracking` runtime rail (`forge gate disable rail.kernel_tracking`
|
|
26
|
+
to turn it off). Do not duplicate policy here.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "OWASP Top 10 security checks"
|
|
3
|
+
alwaysApply: false
|
|
4
|
+
globs: []
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Security Scanning Guidelines
|
|
8
|
+
|
|
9
|
+
Thin pointer — full security analysis is documented in the plan design doc
|
|
10
|
+
(OWASP Top 10 pass during `/plan`) and enforced in the `validate` skill. Do not
|
|
11
|
+
duplicate the checklist here.
|
|
12
|
+
|
|
13
|
+
For every feature, analyze the **OWASP Top 10 (2021)**: broken access control,
|
|
14
|
+
cryptographic failures, injection (SQL/XSS/command), insecure design, security
|
|
15
|
+
misconfiguration, vulnerable components, auth failures, integrity failures,
|
|
16
|
+
logging/monitoring gaps, and SSRF.
|
|
17
|
+
|
|
18
|
+
- Parameterize queries; sanitize output; validate all inputs.
|
|
19
|
+
- Never store secrets or keys in code; reference env vars.
|
|
20
|
+
- Run dependency audits (`npm audit`) and add security test cases.
|
|
21
|
+
|
|
22
|
+
Load the `validate` skill and see `AGENTS.md` for the enforced gates.
|
package/rules/tdd.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "TDD patterns and enforcement"
|
|
3
|
+
alwaysApply: false
|
|
4
|
+
globs: ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# TDD Enforcement
|
|
8
|
+
|
|
9
|
+
Thin pointer — the full TDD procedure lives in the `dev` skill
|
|
10
|
+
(`skills/dev/SKILL.md`) and `AGENTS.md`. Do not duplicate it here.
|
|
11
|
+
|
|
12
|
+
**RED → GREEN → REFACTOR** is mandatory. No implementation without a failing
|
|
13
|
+
test first:
|
|
14
|
+
|
|
15
|
+
- **RED** — write the failing test first; run it and see it fail for the right reason.
|
|
16
|
+
- **GREEN** — write the minimal code to pass; nothing beyond the test's scope.
|
|
17
|
+
- **REFACTOR** — clean up while keeping tests green; commit each phase.
|
|
18
|
+
|
|
19
|
+
Test behavior, not implementation. Cover edge cases, errors, and OWASP-relevant
|
|
20
|
+
inputs. Load the `dev` skill for the enforced HARD-GATE loop and decision gate.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "When working with Forge workflow commands"
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
globs: []
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Forge TDD Workflow Template
|
|
8
|
+
|
|
9
|
+
TDD-first workflow. This rule is a **thin pointer** — the authoritative contract
|
|
10
|
+
lives in `AGENTS.md`, and each stage's detailed steps live in its skill
|
|
11
|
+
(`skills/<stage>/SKILL.md`). Do not duplicate policy here.
|
|
12
|
+
|
|
13
|
+
Stages: `/plan` → `/dev` → `/validate` → `/ship` → `/review` → `/verify`
|
|
14
|
+
(pre-merge gate before merge). `/status` and `/shepherd` are utilities, not stages.
|
|
15
|
+
|
|
16
|
+
- `/plan` — design intent → research → branch + worktree + task list
|
|
17
|
+
- `/dev` — subagent-driven TDD per task (RED → GREEN → REFACTOR)
|
|
18
|
+
- `/validate` — type check, lint, tests, security (HARD-GATE on exit)
|
|
19
|
+
- `/ship` — push and open a PR referencing the design doc
|
|
20
|
+
- `/review` — resolve ALL PR feedback (CI, Greptile, SonarCloud)
|
|
21
|
+
- `/verify` — post-merge health check on the default branch
|
|
22
|
+
|
|
23
|
+
> **Pre-merge gate** (not a numbered stage): finish docs on the branch, confirm CI
|
|
24
|
+
> is green, hand off the PR. Embedded in `/ship` and `/review`, not a command.
|
|
25
|
+
|
|
26
|
+
Load the matching stage skill for the full procedure. Default stack: `bun` test
|
|
27
|
+
runner, Git conventional commits, OWASP-aware. See `AGENTS.md` for the rest.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Pre-push auto-file rail (kernel issue a4b8f56f).
|
|
6
|
+
*
|
|
7
|
+
* Ensures the branch being pushed has a backing Kernel issue so a RAW `git push`
|
|
8
|
+
* (NOT routed through `forge push`, which wires the same rail) still auto-files
|
|
9
|
+
* started work — "nothing goes missing". BEST-EFFORT + NON-BLOCKING: a hook must
|
|
10
|
+
* never block a push on tracking, so `run()` swallows every error and the CLI entry
|
|
11
|
+
* ALWAYS exits 0. Idempotent via ensureBackingIssue (deduped by branch), so it never
|
|
12
|
+
* duplicates an issue `forge worktree`/`forge push` already filed.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
const { execFileSync } = require('node:child_process');
|
|
16
|
+
const path = require('node:path');
|
|
17
|
+
const fs = require('node:fs');
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @param {object} [deps] - injection seam for tests:
|
|
21
|
+
* { getBranch, ensureBackingIssue, buildDeps, projectRoot, existsSync }
|
|
22
|
+
* @returns {Promise<object|null>} the backing-issue descriptor, or null when skipped.
|
|
23
|
+
*/
|
|
24
|
+
async function run(deps = {}) {
|
|
25
|
+
try {
|
|
26
|
+
const projectRoot = deps.projectRoot || process.cwd();
|
|
27
|
+
const existsSync = deps.existsSync || fs.existsSync;
|
|
28
|
+
const getBranch = deps.getBranch || (() => execFileSync('git', ['branch', '--show-current'], { encoding: 'utf8' }).trim());
|
|
29
|
+
const branch = getBranch();
|
|
30
|
+
if (!branch) return null;
|
|
31
|
+
if (!existsSync(path.join(projectRoot, '.git'))) return null;
|
|
32
|
+
|
|
33
|
+
const ensure = deps.ensureBackingIssue || require('../lib/kernel/backing-issue').ensureBackingIssue;
|
|
34
|
+
const buildDeps = deps.buildDeps || (root => require('../lib/kernel/cli-broker-factory').buildMigratedKernelIssueDeps({ projectRoot: root }));
|
|
35
|
+
const { kernelDriver, kernelBroker } = await buildDeps(projectRoot);
|
|
36
|
+
return await ensure({ branch, projectRoot, driver: kernelDriver, broker: kernelBroker });
|
|
37
|
+
} catch {
|
|
38
|
+
// Non-blocking: tracking must never break a push.
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
module.exports = { run };
|
|
44
|
+
|
|
45
|
+
if (require.main === module) {
|
|
46
|
+
run().finally(() => process.exit(0));
|
|
47
|
+
}
|