forge-workflow 0.0.10 → 0.1.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/rules/{greptile-review-process.md → review-process.md} +56 -41
- package/.claude/scripts/{greptile-resolve.sh → review-resolve.sh} +13 -3
- package/.cursor/rules/permissions-guidance.mdc +2 -2
- package/.forge/hooks/check-tdd.js +82 -5
- package/.forge/hooks/forge-native-hook.js +431 -0
- package/.forge/protected-paths.yaml +157 -0
- package/AGENTS.md +151 -61
- package/CHANGELOG.md +709 -0
- package/CLAUDE.md +9 -118
- package/QUICKSTART.md +175 -0
- package/README.md +275 -365
- package/bin/forge-cmd.js +120 -9
- package/bin/forge-preflight.js +26 -5
- package/bin/forge.js +532 -489
- package/docs/INDEX.md +93 -0
- package/docs/PROJECT_DESIGN.md +685 -0
- package/docs/architecture/index.md +66 -0
- package/docs/architecture/notes/README.md +35 -0
- package/docs/architecture/subsystems/README.md +46 -0
- package/docs/forge/TOOLCHAIN.md +670 -0
- package/docs/forge/VALIDATION.md +82 -0
- package/docs/{AGENT_INSTALL_PROMPT.md → guides/AGENT_INSTALL_PROMPT.md} +3 -3
- package/docs/guides/BEADS_GITHUB_SYNC.md +32 -0
- package/docs/{ENHANCED_ONBOARDING.md → guides/ENHANCED_ONBOARDING.md} +16 -12
- package/docs/guides/GREPTILE_SETUP.md +46 -0
- package/docs/guides/MANUAL_REVIEW_GUIDE.md +58 -0
- package/docs/guides/MIGRATION.md +56 -0
- package/docs/guides/SETUP.md +121 -0
- package/docs/guides/SUPPORT.md +190 -0
- package/docs/guides/WORKFLOW_TEMPLATES.md +74 -0
- package/docs/guides/memory-backends.md +183 -0
- package/docs/reference/ADAPTERS.md +128 -0
- package/docs/reference/AGENT_SKILL_PARITY.md +175 -0
- package/docs/reference/COMMANDS.md +214 -0
- package/docs/reference/DECISION_DRIFT_GUARDS.md +97 -0
- package/docs/{EXAMPLES.md → reference/EXAMPLES.md} +7 -5
- package/docs/reference/FORGE_KERNEL_STORAGE_MODEL.md +135 -0
- package/docs/reference/HERMES_INTEGRATION.md +118 -0
- package/docs/reference/INSIGHTS_RECAP.md +63 -0
- package/docs/reference/INSTALL.md +164 -0
- package/docs/reference/KERNEL_TAXONOMY_VALIDATION.md +161 -0
- package/docs/reference/PROTECTED_PATH_MANIFEST.md +25 -0
- package/docs/reference/RELEASE.md +68 -0
- package/docs/reference/RESEARCH_TEMPLATE.md +292 -0
- package/docs/{ROADMAP.md → reference/ROADMAP.md} +12 -9
- package/docs/reference/SKILLS.md +35 -0
- package/docs/reference/STATUS_BOARD.md +80 -0
- package/docs/reference/TEMPLATES.md +106 -0
- package/docs/{TOOLCHAIN.md → reference/TOOLCHAIN.md} +62 -47
- package/docs/reference/VALIDATION.md +82 -0
- package/docs/reference/agent-permissions.md +169 -0
- package/docs/reference/beads-to-kernel-migration-ux.md +61 -0
- package/docs/reference/control-plane-guarantees.md +125 -0
- package/docs/reference/dependency-chain.md +331 -0
- package/docs/reference/forge-kernel-issue-command-contract.md +161 -0
- package/docs/reference/forge-kernel-schema.md +72 -0
- package/docs/reference/kernel-conflict-evaluators.md +27 -0
- package/docs/reference/patch-md-format.md +77 -0
- package/docs/reference/protected-state-surfaces.md +59 -0
- package/docs/reference/shepherd.md +155 -0
- package/docs/reference/superpowers-analysis.md +320 -0
- package/docs/reference/superpowers-integration-options.md +404 -0
- package/docs/reference/test-environment.md +519 -0
- package/docs/reference/upgrade-safety.md +59 -0
- package/lefthook.yml +18 -0
- package/lib/activation/ensure-forge-home.js +135 -0
- package/lib/adapter-cli.js +307 -0
- package/lib/adapters/beads-issue-adapter.js +127 -0
- package/lib/adapters/beads-kernel-compat.js +1109 -0
- package/lib/adapters/greptile-review-adapter.js +141 -0
- package/lib/adapters/kernel-issue-adapter.js +101 -0
- package/lib/adapters/pr-state-adapter.js +484 -0
- package/lib/adoption-profiles.js +139 -0
- package/lib/agents/README.md +2 -6
- package/lib/agents/claude.plugin.json +3 -8
- package/lib/agents/codex.plugin.json +9 -1
- package/lib/agents/cursor.plugin.json +2 -6
- package/lib/agents/hermes.plugin.json +22 -0
- package/lib/agents-config.js +39 -1236
- package/lib/audit-evidence.js +282 -0
- package/lib/beads-detect.js +60 -0
- package/lib/beads-nudge.js +91 -0
- package/lib/beads-setup.js +121 -0
- package/lib/beads-sync-scaffold.js +25 -101
- package/lib/codex-skills.js +51 -1
- package/lib/commands/_aliases.js +248 -0
- package/lib/commands/_issue.js +780 -77
- package/lib/commands/_manifest.js +93 -0
- package/lib/commands/_registry.js +99 -34
- package/lib/commands/_resolve-command-opts.js +230 -0
- package/lib/commands/_serve-security.js +270 -0
- package/lib/commands/adapter.js +12 -0
- package/lib/commands/add.js +118 -0
- package/lib/commands/audit.js +70 -0
- package/lib/commands/blocked.js +5 -0
- package/lib/commands/board.js +64 -0
- package/lib/commands/claim.js +21 -2
- package/lib/commands/claims.js +7 -0
- package/lib/commands/clean.js +485 -75
- package/lib/commands/close.js +2 -2
- package/lib/commands/comment.js +5 -0
- package/lib/commands/control.js +148 -0
- package/lib/commands/create.js +2 -2
- package/lib/commands/dev.js +185 -7
- package/lib/commands/doc-gate.js +336 -0
- package/lib/commands/doctor.js +156 -0
- package/lib/commands/explain.js +15 -0
- package/lib/commands/export.js +237 -0
- package/lib/commands/gate.js +209 -0
- package/lib/commands/hooks.js +377 -0
- package/lib/commands/inbox.js +118 -0
- package/lib/commands/init.js +604 -0
- package/lib/commands/insights.js +79 -0
- package/lib/commands/issue.js +12 -1
- package/lib/commands/issues.js +17 -0
- package/lib/commands/lint.js +5 -0
- package/lib/commands/list.js +2 -2
- package/lib/commands/memory.js +81 -0
- package/lib/commands/merge.js +312 -0
- package/lib/commands/migrate.js +362 -0
- package/lib/commands/new.js +12 -0
- package/lib/commands/options.js +241 -0
- package/lib/commands/orient.js +13 -0
- package/lib/commands/orphans.js +5 -0
- package/lib/commands/patch.js +67 -0
- package/lib/commands/plan.js +481 -29
- package/lib/commands/pr.js +88 -0
- package/lib/commands/preflight.js +211 -0
- package/lib/commands/prime.js +13 -0
- package/lib/commands/push.js +135 -2
- package/lib/commands/ready.js +2 -2
- package/lib/commands/recall.js +171 -0
- package/lib/commands/recap.js +75 -0
- package/lib/commands/recommend.js +0 -1
- package/lib/commands/release.js +104 -0
- package/lib/commands/remember.js +140 -0
- package/lib/commands/role.js +99 -0
- package/lib/commands/serve.js +581 -0
- package/lib/commands/setup.js +900 -971
- package/lib/commands/shepherd.js +501 -0
- package/lib/commands/ship.js +59 -1
- package/lib/commands/show.js +2 -2
- package/lib/commands/stage.js +192 -0
- package/lib/commands/stale.js +5 -0
- package/lib/commands/status.js +158 -21
- package/lib/commands/sync.js +34 -46
- package/lib/commands/team.js +4 -1
- package/lib/commands/test.js +43 -27
- package/lib/commands/update.js +2 -2
- package/lib/commands/upgrade.js +47 -0
- package/lib/commands/validate.js +43 -18
- package/lib/commands/worktree.js +362 -99
- package/lib/config-writer.js +202 -0
- package/lib/control-plane.js +236 -0
- package/lib/core/runtime-graph.js +977 -0
- package/lib/dep-guard/keyword-ripple.js +2 -2
- package/lib/deprecated-sync-cleanup.js +362 -0
- package/lib/detect-agent.js +2 -28
- package/lib/detect-worktree.js +35 -9
- package/lib/doc-gate/declaration.js +177 -0
- package/lib/doc-gate/detect.js +289 -0
- package/lib/doc-gate/gate.js +375 -0
- package/lib/doc-gate/okf-config.js +128 -0
- package/lib/doc-gate/okf.js +429 -0
- package/lib/docs-command.js +1161 -6
- package/lib/forge-issues.js +382 -11
- package/lib/forge-lock.js +262 -0
- package/lib/gate-events.js +192 -0
- package/lib/global-flags.js +104 -0
- package/lib/greptile-match.js +7 -63
- package/lib/grounding/context-events.js +230 -0
- package/lib/grounding/read-first.js +112 -0
- package/lib/harness-capability-matrix.js +380 -0
- package/lib/hook-global-installer.js +347 -0
- package/lib/hook-renderer.js +541 -0
- package/lib/inbox.js +391 -0
- package/lib/insights.js +397 -0
- package/lib/issue-adapter.js +156 -0
- package/lib/issue-backend.js +145 -0
- package/lib/issue-render.js +220 -0
- package/lib/kernel/backing-issue.js +311 -0
- package/lib/kernel/broker.js +1218 -0
- package/lib/kernel/cli-broker-factory.js +130 -0
- package/lib/kernel/conflict-signal.js +82 -0
- package/lib/kernel/evaluators.js +195 -0
- package/lib/kernel/fs-class.js +495 -0
- package/lib/kernel/issue-command-contract.js +559 -0
- package/lib/kernel/issue-id-resolver.js +186 -0
- package/lib/kernel/lease-enforcer.js +158 -0
- package/lib/kernel/migrations.js +333 -0
- package/lib/kernel/owned-kernel.js +43 -0
- package/lib/kernel/planning-buckets-schema.js +109 -0
- package/lib/kernel/projection-jsonl-writer.js +450 -0
- package/lib/kernel/readiness-model.js +329 -0
- package/lib/kernel/schema.js +356 -0
- package/lib/kernel/sqlite-driver.js +2540 -0
- package/lib/kernel/taxonomy-validator.js +394 -0
- package/lib/lefthook-check.js +3 -2
- package/lib/lefthook-wiring.js +413 -0
- package/lib/mcp-config-renderer.js +288 -0
- package/lib/memory/graphiti-mcp.js +106 -0
- package/lib/memory/router.js +387 -0
- package/lib/memory/typed-api.js +102 -0
- package/lib/memory-digest.js +195 -0
- package/lib/merge-rules.js +395 -0
- package/lib/migrate-dry-run.js +466 -0
- package/lib/orientation.js +863 -0
- package/lib/package-manager-remediation.js +103 -0
- package/lib/package-root.js +381 -0
- package/lib/patch-intent.js +890 -0
- package/lib/plugin-catalog.js +3 -4
- package/lib/plugin-manager.js +0 -5
- package/lib/pr-bundle.js +186 -0
- package/lib/pr-monitor/auto-actions.js +175 -0
- package/lib/pr-monitor/differ.js +195 -0
- package/lib/pr-monitor/digest.js +206 -0
- package/lib/pr-monitor/events.js +0 -0
- package/lib/pr-monitor/gather.js +124 -0
- package/lib/pr-monitor/journal.js +299 -0
- package/lib/pr-monitor/monitor.js +146 -0
- package/lib/pr-monitor/render-sticky.js +192 -0
- package/lib/pr-monitor/upsert-sticky.js +169 -0
- package/lib/pr-monitor/watch-lifecycle.js +95 -0
- package/lib/pr-monitor/watch.js +247 -0
- package/lib/pr-pull.js +1314 -0
- package/lib/pr-shepherd.js +494 -0
- package/lib/pr-state-validator.js +59 -0
- package/lib/preflight/gates.js +237 -0
- package/lib/preflight/runner.js +116 -0
- package/lib/project-discovery.js +0 -53
- package/lib/project-memory.js +99 -497
- package/lib/protected-path-manifest.js +281 -0
- package/lib/protected-state-surfaces.js +387 -0
- package/lib/release-readiness.js +2105 -0
- package/lib/reset.js +59 -45
- package/lib/review-adapter.js +68 -0
- package/lib/rules-sync.js +260 -0
- package/lib/runtime-health.js +241 -20
- package/lib/safety-config-renderer.js +268 -0
- package/lib/setup-action-log.js +1 -7
- package/lib/setup.js +27 -65
- package/lib/shell-utils.js +76 -6
- package/lib/skills-sync.js +330 -0
- package/lib/smart-status/scoring.js +17 -3
- package/lib/status/beads-snapshot.js +45 -2
- package/lib/status/presenter.js +169 -18
- package/lib/status/snapshot.js +186 -0
- package/lib/sync-backend.js +202 -0
- package/lib/untrusted-content.js +52 -0
- package/lib/upgrade-safety.js +251 -0
- package/lib/workflow/enforce-stage.js +351 -45
- package/lib/workflow/stage-transition.js +115 -0
- package/lib/workflow/stages.js +30 -6
- package/lib/workflow/state-manager.js +11 -22
- package/lib/workflow/state.js +23 -1
- package/lib/workflow-profiles.js +17 -5
- package/package.json +37 -35
- package/rules/documentation.md +19 -0
- package/rules/kernel-tracking.md +26 -0
- package/rules/security.md +22 -0
- package/rules/tdd.md +20 -0
- package/rules/workflow.md +27 -0
- package/scripts/auto-backing-issue.js +47 -0
- package/scripts/beads-context.sh +81 -57
- package/scripts/beads-upgrade-smoke.sh +24 -3
- package/scripts/bootstrap-windows-tools.sh +78 -0
- package/scripts/branch-protection.js +2 -3
- package/scripts/check-agents.js +34 -137
- package/scripts/commitlint.js +3 -1
- package/scripts/conflict-detect.sh +3 -0
- package/scripts/dep-guard.sh +22 -3
- package/scripts/file-index.sh +3 -0
- package/scripts/forge-team/lib/claim.sh +34 -18
- package/scripts/forge-team/lib/dashboard.sh +61 -86
- package/scripts/forge-team/lib/epic.sh +99 -263
- package/scripts/forge-team/lib/hooks.sh +26 -28
- package/scripts/forge-team/lib/identity.sh +4 -4
- package/scripts/forge-team/lib/sync-github.sh +49 -84
- package/scripts/forge-team/lib/verify.sh +93 -83
- package/scripts/forge-team/lib/workload.sh +41 -65
- package/scripts/forge-team/tests/claim.test.sh +25 -19
- package/scripts/forge-team/tests/dashboard.test.sh +31 -46
- package/scripts/forge-team/tests/epic.test.sh +52 -71
- package/scripts/forge-team/tests/hooks.test.sh +38 -50
- package/scripts/forge-team/tests/identity.test.sh +3 -3
- package/scripts/forge-team/tests/integration.test.sh +44 -66
- package/scripts/forge-team/tests/sync-github.test.sh +50 -83
- package/scripts/forge-team/tests/verify.test.sh +37 -46
- package/scripts/forge-team/tests/workflow-integration.test.sh +4 -4
- package/scripts/forge-team/tests/workload.test.sh +32 -66
- package/scripts/gen-command-manifest.js +153 -0
- package/scripts/gen-embedded-assets.mjs +129 -0
- package/scripts/install.ps1 +139 -0
- package/scripts/install.sh +268 -0
- package/scripts/lib/release-asset.mjs +84 -0
- package/scripts/parity-check.mjs +145 -0
- package/scripts/parity-check.test.mjs +58 -0
- package/scripts/pin-agentic-workflow-images.js +112 -0
- package/scripts/pr-auto-actions.js +93 -0
- package/scripts/pr-coordinator.sh +3 -0
- package/scripts/pr-verdict-label.js +50 -0
- package/scripts/preflight-sonar.eslint.config.mjs +44 -0
- package/scripts/preflight.sh +21 -94
- package/scripts/protected-state-check.js +104 -0
- package/scripts/smart-status.sh +60 -57
- package/scripts/spikes/config-race-bench.js +111 -0
- package/scripts/spikes/harness-capability-matrix.js +13 -0
- package/scripts/spikes/patch-anchor-stability-bench.js +125 -0
- package/scripts/spikes/protected-path-manifest.js +20 -0
- package/scripts/spikes/skill-auto-invoke-parity.js +292 -0
- package/scripts/sync-agent-skills.js +62 -0
- package/scripts/sync-utils.sh +3 -0
- package/scripts/test-ci-shard.js +13 -6
- package/scripts/test.js +95 -12
- package/skills/claim-safety/SKILL.md +102 -0
- package/skills/claim-safety/evals/evals.json +46 -0
- package/{.github/prompts/dev.prompt.md → skills/dev/SKILL.md} +44 -50
- package/skills/dev/evals/evals.json +50 -0
- package/skills/hermes-forge/SKILL.md +185 -0
- package/skills/hermes-forge/evals/evals.json +46 -0
- package/skills/issue-basics/SKILL.md +111 -0
- package/skills/issue-basics/evals/evals.json +46 -0
- package/skills/kernel/SKILL.md +166 -0
- package/skills/kernel/evals/evals.json +50 -0
- package/skills/memory/SKILL.md +102 -0
- package/skills/parallel-deep-research/SKILL.md +14 -11
- package/skills/parallel-deep-research/evals/evals.json +11 -27
- package/{.github/prompts/plan.prompt.md → skills/plan/SKILL.md} +132 -157
- package/skills/plan/evals/evals.json +42 -0
- package/skills/research/SKILL.md +195 -0
- package/skills/research/evals/evals.json +42 -0
- package/{.github/prompts/review.prompt.md → skills/review/SKILL.md} +98 -62
- package/skills/review/evals/evals.json +42 -0
- package/skills/rollback/SKILL.md +110 -0
- package/skills/rollback/evals/evals.json +46 -0
- package/skills/rollback/references/methods.md +204 -0
- package/{.cursor/commands/rollback.md → skills/rollback/references/workflow-integration.md} +10 -284
- package/skills/shepherd/SKILL.md +66 -0
- package/skills/shepherd/evals/evals.json +42 -0
- package/{.github/prompts/ship.prompt.md → skills/ship/SKILL.md} +81 -45
- package/skills/ship/evals/evals.json +42 -0
- package/skills/smith/SKILL.md +142 -0
- package/skills/smith/evals/evals.json +46 -0
- package/skills/smith/references/autonomy-and-gates.md +94 -0
- package/{.github/prompts/sonarcloud.prompt.md → skills/sonarcloud/SKILL.md} +14 -3
- package/skills/sonarcloud/evals/evals.json +46 -0
- package/skills/sonarcloud-analysis/SKILL.md +18 -13
- package/skills/sonarcloud-analysis/evals/evals.json +11 -15
- package/{.github/prompts/status.prompt.md → skills/status/SKILL.md} +20 -10
- package/skills/status/evals/evals.json +50 -0
- package/skills/triage-ready/SKILL.md +121 -0
- package/skills/triage-ready/evals/evals.json +42 -0
- package/{.github/prompts/validate.prompt.md → skills/validate/SKILL.md} +52 -29
- package/skills/validate/evals/evals.json +42 -0
- package/skills/verify/SKILL.md +299 -0
- package/skills/verify/evals/evals.json +50 -0
- package/.claude/commands/dev.md +0 -345
- package/.claude/commands/plan.md +0 -566
- package/.claude/commands/premerge.md +0 -186
- package/.claude/commands/research.md +0 -42
- package/.claude/commands/review.md +0 -451
- package/.claude/commands/rollback.md +0 -721
- package/.claude/commands/ship.md +0 -213
- package/.claude/commands/sonarcloud.md +0 -152
- package/.claude/commands/status.md +0 -90
- package/.claude/commands/validate.md +0 -288
- package/.claude/commands/verify.md +0 -269
- package/.claude/rules/workflow.md +0 -121
- package/.cline/workflows/dev.md +0 -342
- package/.cline/workflows/plan.md +0 -563
- package/.cline/workflows/premerge.md +0 -183
- package/.cline/workflows/research.md +0 -39
- package/.cline/workflows/review.md +0 -448
- package/.cline/workflows/rollback.md +0 -718
- package/.cline/workflows/ship.md +0 -210
- package/.cline/workflows/sonarcloud.md +0 -146
- package/.cline/workflows/status.md +0 -87
- package/.cline/workflows/validate.md +0 -285
- package/.cline/workflows/verify.md +0 -266
- package/.codex/config.toml +0 -11
- package/.codex/skills/dev/SKILL.md +0 -345
- package/.codex/skills/plan/SKILL.md +0 -566
- package/.codex/skills/premerge/SKILL.md +0 -186
- package/.codex/skills/research/SKILL.md +0 -42
- package/.codex/skills/review/SKILL.md +0 -451
- package/.codex/skills/rollback/SKILL.md +0 -721
- package/.codex/skills/ship/SKILL.md +0 -213
- package/.codex/skills/sonarcloud/SKILL.md +0 -149
- package/.codex/skills/status/SKILL.md +0 -90
- package/.codex/skills/validate/SKILL.md +0 -288
- package/.codex/skills/verify/SKILL.md +0 -269
- package/.cursor/commands/dev.md +0 -342
- package/.cursor/commands/plan.md +0 -563
- package/.cursor/commands/premerge.md +0 -183
- package/.cursor/commands/research.md +0 -39
- package/.cursor/commands/review.md +0 -448
- package/.cursor/commands/ship.md +0 -210
- package/.cursor/commands/sonarcloud.md +0 -146
- package/.cursor/commands/status.md +0 -87
- package/.cursor/commands/validate.md +0 -285
- package/.cursor/commands/verify.md +0 -266
- package/.cursorrules +0 -149
- package/.github/prompts/premerge.prompt.md +0 -188
- package/.github/prompts/research.prompt.md +0 -44
- package/.github/prompts/rollback.prompt.md +0 -723
- package/.github/prompts/verify.prompt.md +0 -271
- package/.github/workflows/beads-to-github.yml +0 -89
- package/.github/workflows/github-to-beads.yml +0 -100
- package/.kilocode/workflows/dev.md +0 -346
- package/.kilocode/workflows/plan.md +0 -567
- package/.kilocode/workflows/premerge.md +0 -187
- package/.kilocode/workflows/research.md +0 -43
- package/.kilocode/workflows/review.md +0 -452
- package/.kilocode/workflows/rollback.md +0 -722
- package/.kilocode/workflows/ship.md +0 -214
- package/.kilocode/workflows/sonarcloud.md +0 -150
- package/.kilocode/workflows/status.md +0 -91
- package/.kilocode/workflows/validate.md +0 -289
- package/.kilocode/workflows/verify.md +0 -270
- package/.opencode/commands/dev.md +0 -345
- package/.opencode/commands/plan.md +0 -566
- package/.opencode/commands/premerge.md +0 -186
- package/.opencode/commands/research.md +0 -42
- package/.opencode/commands/review.md +0 -451
- package/.opencode/commands/rollback.md +0 -721
- package/.opencode/commands/ship.md +0 -213
- package/.opencode/commands/sonarcloud.md +0 -149
- package/.opencode/commands/status.md +0 -90
- package/.opencode/commands/validate.md +0 -288
- package/.opencode/commands/verify.md +0 -269
- package/.roo/commands/dev.md +0 -346
- package/.roo/commands/plan.md +0 -567
- package/.roo/commands/premerge.md +0 -187
- package/.roo/commands/research.md +0 -43
- package/.roo/commands/review.md +0 -452
- package/.roo/commands/rollback.md +0 -722
- package/.roo/commands/ship.md +0 -214
- package/.roo/commands/sonarcloud.md +0 -150
- package/.roo/commands/status.md +0 -91
- package/.roo/commands/validate.md +0 -289
- package/.roo/commands/verify.md +0 -270
- package/docs/BEADS_GITHUB_SYNC.md +0 -281
- package/docs/GREPTILE_SETUP.md +0 -400
- package/docs/MANUAL_REVIEW_GUIDE.md +0 -106
- package/docs/SETUP.md +0 -663
- package/docs/VALIDATION.md +0 -363
- package/lib/agents/cline.plugin.json +0 -29
- package/lib/agents/copilot.plugin.json +0 -24
- package/lib/agents/kilocode.plugin.json +0 -22
- package/lib/agents/opencode.plugin.json +0 -23
- package/lib/agents/roo.plugin.json +0 -30
- package/lib/beads-bootstrap.js +0 -225
- package/lib/beads-health-check.js +0 -188
- package/lib/commands/commands-reset.js +0 -147
- package/opencode.json +0 -67
- package/scripts/beads-context.test.js +0 -584
- package/scripts/github-beads-sync/comment.mjs +0 -64
- package/scripts/github-beads-sync/config.mjs +0 -148
- package/scripts/github-beads-sync/github-api.mjs +0 -131
- package/scripts/github-beads-sync/index.mjs +0 -356
- package/scripts/github-beads-sync/label-mapper.mjs +0 -54
- package/scripts/github-beads-sync/mapping.mjs +0 -132
- package/scripts/github-beads-sync/reverse-sync-cli.mjs +0 -31
- package/scripts/github-beads-sync/reverse-sync.mjs +0 -162
- package/scripts/github-beads-sync/run-bd.mjs +0 -161
- package/scripts/github-beads-sync/sanitize.mjs +0 -121
- package/scripts/github-beads-sync.config.json +0 -26
- package/scripts/sync-commands.js +0 -600
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const {
|
|
4
|
+
buildIssueRecap,
|
|
5
|
+
formatOrientationText,
|
|
6
|
+
} = require('../orientation');
|
|
7
|
+
const { recordContextLoaded } = require('../grounding/context-events');
|
|
8
|
+
|
|
9
|
+
const usage = 'Usage: forge recap <issue> [--budget N] [--json]';
|
|
10
|
+
|
|
11
|
+
// Options that consume the following token as their value. The issue-id scan
|
|
12
|
+
// must skip these values so `forge recap --budget 220 <issue>` is not misread.
|
|
13
|
+
const OPTIONS_WITH_VALUES = new Set(['--budget']);
|
|
14
|
+
|
|
15
|
+
function readOption(args, name, fallback) {
|
|
16
|
+
const equals = args.find(arg => arg.startsWith(`${name}=`));
|
|
17
|
+
if (equals) return equals.slice(name.length + 1);
|
|
18
|
+
const index = args.indexOf(name);
|
|
19
|
+
if (index >= 0 && args[index + 1] && !args[index + 1].startsWith('-')) return args[index + 1];
|
|
20
|
+
return fallback;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function readIssueArg(args) {
|
|
24
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
25
|
+
const arg = args[index];
|
|
26
|
+
if (!arg) continue;
|
|
27
|
+
if (OPTIONS_WITH_VALUES.has(arg)) {
|
|
28
|
+
index += 1;
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
if (arg.startsWith('-')) continue;
|
|
32
|
+
return arg;
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// `forge recap <issue>` summarizes a single issue from the deterministic
|
|
38
|
+
// orientation source assembly — it is issue-scoped, not a project-wide recap.
|
|
39
|
+
async function handler(args, _flags, projectRoot, opts = {}) {
|
|
40
|
+
const issueId = readIssueArg(args);
|
|
41
|
+
if (!issueId) {
|
|
42
|
+
// Use `error` (not `output`) so the CLI dispatcher prints the usage line
|
|
43
|
+
// once via console.error instead of also appending a redundant bare
|
|
44
|
+
// "Command failed" (see bin/forge.js registry dispatch).
|
|
45
|
+
return { success: false, error: usage };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const budget = readOption(args, '--budget', undefined);
|
|
49
|
+
const recap = buildIssueRecap(projectRoot, issueId, { budgetTokens: budget });
|
|
50
|
+
|
|
51
|
+
// Grounding (gate.read_first): a successful recap IS the load-the-doc action,
|
|
52
|
+
// so append a `context.loaded` event that unblocks a later `forge claim <id>`.
|
|
53
|
+
// Best-effort and awaited so the event is durable before the CLI process exits;
|
|
54
|
+
// a bookkeeping failure never fails the recap render.
|
|
55
|
+
const deps = (opts.kernelBroker && opts.kernelDriver)
|
|
56
|
+
? { kernelBroker: opts.kernelBroker, kernelDriver: opts.kernelDriver }
|
|
57
|
+
: undefined;
|
|
58
|
+
try {
|
|
59
|
+
await recordContextLoaded(projectRoot, {
|
|
60
|
+
issueId, cmd: 'recap', budget, session: opts.session, env: opts.env, deps, now: opts.now,
|
|
61
|
+
});
|
|
62
|
+
} catch { /* best-effort: never fail a recap on grounding bookkeeping */ }
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
success: true,
|
|
66
|
+
output: args.includes('--json') ? `${JSON.stringify(recap, null, 2)}\n` : formatOrientationText(recap),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
module.exports = {
|
|
71
|
+
name: 'recap',
|
|
72
|
+
description: 'Summarize a single issue from deterministic orientation source files',
|
|
73
|
+
usage,
|
|
74
|
+
handler,
|
|
75
|
+
};
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const {
|
|
4
|
+
SUPPORTED_TARGET,
|
|
5
|
+
buildReadinessReport,
|
|
6
|
+
renderReadinessReport,
|
|
7
|
+
writeAuditArtifact,
|
|
8
|
+
} = require('../release-readiness');
|
|
9
|
+
const { runIssueOperation: defaultRunIssueOperation } = require('../forge-issues');
|
|
10
|
+
const { normalizeArgs, normalizeIssueResult, withResolvedIssueBackend } = require('./_issue');
|
|
11
|
+
|
|
12
|
+
// `forge release <id>` releases a claimed issue; `forge release check` runs the
|
|
13
|
+
// release-readiness gate. The two share the top-level verb, so this command
|
|
14
|
+
// dispatches `check` to the gate and routes everything else through the shared
|
|
15
|
+
// issue dispatch (resolve backend → runIssueOperation('release') → normalize). The
|
|
16
|
+
// Beads backend has no release op and returns the Kernel-only contract error.
|
|
17
|
+
const usage = 'Usage: forge release <id> | forge release check --target 0.1.0 [--json] | forge release regen-audit';
|
|
18
|
+
|
|
19
|
+
async function runReleaseIssue(args, projectRoot, opts = {}) {
|
|
20
|
+
const resolved = withResolvedIssueBackend(projectRoot, opts);
|
|
21
|
+
const runIssueOperation = resolved.runIssueOperation || defaultRunIssueOperation;
|
|
22
|
+
const normalizedArgs = normalizeArgs(args);
|
|
23
|
+
const result = await runIssueOperation('release', normalizedArgs, projectRoot,
|
|
24
|
+
{ ...resolved, kernelBroker: resolved.kernelBroker });
|
|
25
|
+
return normalizeIssueResult(result, 'release', { json: normalizedArgs.includes('--json') });
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function readOption(args, name, fallback) {
|
|
29
|
+
const equals = args.find(arg => arg.startsWith(`${name}=`));
|
|
30
|
+
if (equals) {
|
|
31
|
+
return equals.slice(name.length + 1);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const index = args.indexOf(name);
|
|
35
|
+
if (index >= 0 && args[index + 1] && !args[index + 1].startsWith('-')) {
|
|
36
|
+
return args[index + 1];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return fallback;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function parseReleaseArgs(args = []) {
|
|
43
|
+
const subcommand = args.find((arg, index) => {
|
|
44
|
+
if (arg.startsWith('-')) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
const previous = args[index - 1];
|
|
48
|
+
return previous !== '--target';
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
subcommand,
|
|
53
|
+
target: readOption(args, '--target', SUPPORTED_TARGET),
|
|
54
|
+
json: args.includes('--json'),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async function handler(args, _flags, projectRoot, opts = {}) {
|
|
59
|
+
const parsed = parseReleaseArgs(args);
|
|
60
|
+
|
|
61
|
+
if (parsed.subcommand === 'regen-audit') {
|
|
62
|
+
// forge release regen-audit — rewrite the D20 kill-list from a live re-scan.
|
|
63
|
+
// The staleness gate (lib/release-readiness d20 check) points here so a
|
|
64
|
+
// Beads-removal PR that shifts the census is a one-command fix, not a
|
|
65
|
+
// hand-edit that red-fails CI until it matches byte-for-byte.
|
|
66
|
+
const { path: artifact } = writeAuditArtifact(projectRoot);
|
|
67
|
+
return {
|
|
68
|
+
success: true,
|
|
69
|
+
output: `Regenerated ${artifact}. Commit it to clear the d20 staleness gate.\n`,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (parsed.subcommand !== 'check') {
|
|
74
|
+
// forge release <id> — release a claimed issue via the shared issue dispatch.
|
|
75
|
+
return runReleaseIssue(args, projectRoot, opts);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const report = buildReadinessReport(projectRoot, { target: parsed.target });
|
|
79
|
+
const output = parsed.json
|
|
80
|
+
? `${JSON.stringify(report, null, 2)}\n`
|
|
81
|
+
: renderReadinessReport(report);
|
|
82
|
+
const error = parsed.json
|
|
83
|
+
? `Forge release readiness check failed for ${report.target}`
|
|
84
|
+
: output;
|
|
85
|
+
|
|
86
|
+
return {
|
|
87
|
+
success: report.success,
|
|
88
|
+
report,
|
|
89
|
+
output,
|
|
90
|
+
error: report.success ? undefined : error,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
module.exports = {
|
|
95
|
+
name: 'release',
|
|
96
|
+
description: 'Release a claimed issue, or run Forge release readiness gates (forge release check)',
|
|
97
|
+
usage,
|
|
98
|
+
flags: {
|
|
99
|
+
'--target <version>': 'Release target to check',
|
|
100
|
+
'--json': 'Emit the readiness report as JSON',
|
|
101
|
+
},
|
|
102
|
+
handler,
|
|
103
|
+
parseReleaseArgs,
|
|
104
|
+
};
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const memoryRouter = require('../memory/router');
|
|
4
|
+
const { stripGlobalFlags } = require('../global-flags');
|
|
5
|
+
|
|
6
|
+
const usage =
|
|
7
|
+
'Usage: forge remember <note> [--kind <type>] [--session-summary] [--tag <label>]... ' +
|
|
8
|
+
'[--what <text>] [--why <text>] [--where <text>] [--learned <text>] [--json]';
|
|
9
|
+
|
|
10
|
+
// Structured note fields (kernel issue 8cc1db4d). Each is optional and, when present, is
|
|
11
|
+
// folded into the stored note body as a labeled line so it stays FTS-searchable. Order is
|
|
12
|
+
// fixed for a stable, readable render.
|
|
13
|
+
const STRUCTURED_FIELDS = [
|
|
14
|
+
['--what', 'What'],
|
|
15
|
+
['--why', 'Why'],
|
|
16
|
+
['--where', 'Where'],
|
|
17
|
+
['--learned', 'Learned'],
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
// A note's type is stored as a reserved `type:<value>` tag — cheap, additive, and filterable
|
|
21
|
+
// by recall/search WITHOUT a store-schema change (a missing type is fine). The CLI flag is
|
|
22
|
+
// `--kind` (NOT `--type`): `--type` is a reserved GLOBAL flag that bin/forge.js hard-validates
|
|
23
|
+
// against workflow classifications (critical|standard|…), so it can never carry a note type.
|
|
24
|
+
const TYPE_TAG_PREFIX = 'type:';
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Split positional note words from `--kind`, `--tag <label>`, the structured field flags,
|
|
28
|
+
* and `--json`. Global flags (e.g. `-p <dir>`) are stripped first so they never leak into the
|
|
29
|
+
* stored note content (kernel issue c1e090ff); `--kind` is NOT a global flag, so it survives
|
|
30
|
+
* the strip and is parsed here.
|
|
31
|
+
*
|
|
32
|
+
* @param {string[]} rawArgs - Raw command arguments.
|
|
33
|
+
* @returns {{ note: string, tags: string[], type: (string|undefined), fields: object, json: boolean }}
|
|
34
|
+
*/
|
|
35
|
+
function parseArgs(rawArgs) {
|
|
36
|
+
const args = stripGlobalFlags(rawArgs);
|
|
37
|
+
const fieldFlags = new Map(STRUCTURED_FIELDS.map(([flag, label]) => [flag, label]));
|
|
38
|
+
const words = [];
|
|
39
|
+
const tags = [];
|
|
40
|
+
const fields = {};
|
|
41
|
+
let type;
|
|
42
|
+
let json = false;
|
|
43
|
+
|
|
44
|
+
// Consume `--flag value` / `--flag=value`, guarding against swallowing the next flag.
|
|
45
|
+
const takeValue = (index) => {
|
|
46
|
+
const arg = args[index];
|
|
47
|
+
const eq = arg.indexOf('=');
|
|
48
|
+
if (eq >= 0) return { value: arg.slice(eq + 1), consumed: 0 };
|
|
49
|
+
const next = args[index + 1];
|
|
50
|
+
if (next && !next.startsWith('--')) return { value: next, consumed: 1 };
|
|
51
|
+
return { value: undefined, consumed: 0 };
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
55
|
+
const arg = args[index];
|
|
56
|
+
const bare = arg.startsWith('--') ? arg.split('=', 1)[0] : arg;
|
|
57
|
+
if (arg === '--json') {
|
|
58
|
+
json = true;
|
|
59
|
+
} else if (arg === '--session-summary') {
|
|
60
|
+
// Memorable one-flag alias for `--kind session-summary` — the explicit capture-on-exit
|
|
61
|
+
// path an agent calls (via `forge memory add --session-summary` / `forge remember`) to
|
|
62
|
+
// persist a structured session summary with the same --what/--why/--learned fields.
|
|
63
|
+
type = 'session-summary';
|
|
64
|
+
} else if (bare === '--kind') {
|
|
65
|
+
const { value, consumed } = takeValue(index);
|
|
66
|
+
if (value) type = value.trim();
|
|
67
|
+
index += consumed;
|
|
68
|
+
} else if (bare === '--tag') {
|
|
69
|
+
const { value, consumed } = takeValue(index);
|
|
70
|
+
if (value) tags.push(value);
|
|
71
|
+
index += consumed;
|
|
72
|
+
} else if (fieldFlags.has(bare)) {
|
|
73
|
+
const { value, consumed } = takeValue(index);
|
|
74
|
+
if (value) fields[fieldFlags.get(bare)] = value.trim();
|
|
75
|
+
index += consumed;
|
|
76
|
+
} else {
|
|
77
|
+
words.push(arg);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return { note: words.join(' ').trim(), tags, type, fields, json };
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Compose the stored note body from the positional note plus any structured fields. Fields
|
|
86
|
+
* are appended as labeled lines under the note so recall renders them readably and they stay
|
|
87
|
+
* searchable. Returns the empty string only when nothing at all was provided.
|
|
88
|
+
*/
|
|
89
|
+
function composeBody(note, fields) {
|
|
90
|
+
const lines = STRUCTURED_FIELDS
|
|
91
|
+
.map(([, label]) => (fields[label] ? `${label}: ${fields[label]}` : null))
|
|
92
|
+
.filter(Boolean);
|
|
93
|
+
return [note, ...lines].filter(Boolean).join('\n');
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async function handler(args, _flags, projectRoot) {
|
|
97
|
+
const { note, tags, type, fields, json } = parseArgs(args);
|
|
98
|
+
const body = composeBody(note, fields);
|
|
99
|
+
|
|
100
|
+
if (!body) {
|
|
101
|
+
return {
|
|
102
|
+
success: false,
|
|
103
|
+
error: `No note provided.\n${usage}`,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// The type rides as a reserved tag so it is stored and filterable without a schema change.
|
|
108
|
+
const allTags = type ? [...tags, `${TYPE_TAG_PREFIX}${type}`] : tags;
|
|
109
|
+
const entry = memoryRouter.append(projectRoot, body, { tags: allTags });
|
|
110
|
+
|
|
111
|
+
if (json) {
|
|
112
|
+
const payload = type ? { ...entry, type } : entry;
|
|
113
|
+
return { success: true, output: `${JSON.stringify(payload, null, 2)}\n` };
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const userTags = entry.tags.filter(tag => !tag.startsWith(TYPE_TAG_PREFIX));
|
|
117
|
+
const tagSuffix = userTags.length > 0 ? ` [${userTags.join(', ')}]` : '';
|
|
118
|
+
const typePrefix = type ? `(${type}) ` : '';
|
|
119
|
+
return {
|
|
120
|
+
success: true,
|
|
121
|
+
output: `Remembered: ${typePrefix}${entry.note}${tagSuffix}`,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
module.exports = {
|
|
126
|
+
name: 'remember',
|
|
127
|
+
description: 'Persist a project-memory note to the kernel-backed memory store',
|
|
128
|
+
usage,
|
|
129
|
+
flags: {
|
|
130
|
+
'--kind': 'Type the note (decision|bugfix|gotcha|...) — filterable by recall (--type is reserved)',
|
|
131
|
+
'--session-summary': 'Alias for --kind session-summary — capture a session summary on exit',
|
|
132
|
+
'--tag': 'Attach a search label (repeatable)',
|
|
133
|
+
'--what': 'Structured field: what happened/changed',
|
|
134
|
+
'--why': 'Structured field: why',
|
|
135
|
+
'--where': 'Structured field: where (file/area)',
|
|
136
|
+
'--learned': 'Structured field: what was learned',
|
|
137
|
+
'--json': 'Emit machine-readable JSON output',
|
|
138
|
+
},
|
|
139
|
+
handler,
|
|
140
|
+
};
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* `forge role <role> --use <skill> [--ideology <name>]`
|
|
5
|
+
*
|
|
6
|
+
* Thin SWAP verb over the sparse config writer: binds a role to a skill and/or
|
|
7
|
+
* ideology by writing `roles.<role>.skill` / `roles.<role>.ideology` in
|
|
8
|
+
* `.forge/config.yaml`. `forge options roles --json` reflects the binding
|
|
9
|
+
* through the shipped resolver (`applyRoleConfig`).
|
|
10
|
+
*
|
|
11
|
+
* Write-time validation errors BEFORE anything is written:
|
|
12
|
+
* - unknown role (not in the KNOWN closed set ROLE_IDS)
|
|
13
|
+
* - unresolvable skill (no SKILL.md under `.skills/ > skills/`)
|
|
14
|
+
*
|
|
15
|
+
* The skill name is OPEN-WORLD (a bring-your-own skill is fine) — it is checked
|
|
16
|
+
* for existence/trust, never against the closed PLAN_SUBSKILL enum.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
const { setConfigOverride, resolveSkill } = require('../config-writer');
|
|
20
|
+
const { ROLE_IDS } = require('../core/runtime-graph');
|
|
21
|
+
|
|
22
|
+
function usage() {
|
|
23
|
+
return 'Usage: forge role <role> --use <skill> [--ideology <name>]';
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function parseArgs(args) {
|
|
27
|
+
const parsed = { role: args[0], skill: undefined, ideology: undefined };
|
|
28
|
+
for (let i = 1; i < args.length; i += 1) {
|
|
29
|
+
const token = args[i];
|
|
30
|
+
if (token === '--use' || token === '--skill') {
|
|
31
|
+
if (i + 1 >= args.length) {
|
|
32
|
+
return { error: `${token} requires a value.` };
|
|
33
|
+
}
|
|
34
|
+
parsed.skill = args[i + 1];
|
|
35
|
+
i += 1;
|
|
36
|
+
} else if (token === '--ideology') {
|
|
37
|
+
if (i + 1 >= args.length) {
|
|
38
|
+
return { error: `${token} requires a value.` };
|
|
39
|
+
}
|
|
40
|
+
parsed.ideology = args[i + 1];
|
|
41
|
+
i += 1;
|
|
42
|
+
} else {
|
|
43
|
+
return { error: `Unknown argument '${token}'.` };
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return { parsed };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async function handler(args, _flags, projectRoot = process.cwd()) {
|
|
50
|
+
const { parsed, error } = parseArgs(args);
|
|
51
|
+
if (error) {
|
|
52
|
+
return { success: false, error: `${error}\n${usage()}` };
|
|
53
|
+
}
|
|
54
|
+
if (!parsed.role) {
|
|
55
|
+
return { success: false, error: usage() };
|
|
56
|
+
}
|
|
57
|
+
if (!ROLE_IDS.has(parsed.role)) {
|
|
58
|
+
return {
|
|
59
|
+
success: false,
|
|
60
|
+
error: `Unknown role '${parsed.role}'. Known roles: ${[...ROLE_IDS].join(', ')}`,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
if (parsed.skill === undefined && parsed.ideology === undefined) {
|
|
64
|
+
return { success: false, error: `Nothing to set — pass --use and/or --ideology.\n${usage()}` };
|
|
65
|
+
}
|
|
66
|
+
if (parsed.skill !== undefined) {
|
|
67
|
+
if (typeof parsed.skill !== 'string' || parsed.skill === '') {
|
|
68
|
+
return { success: false, error: `--use requires a skill name.\n${usage()}` };
|
|
69
|
+
}
|
|
70
|
+
if (!resolveSkill(projectRoot, parsed.skill)) {
|
|
71
|
+
return {
|
|
72
|
+
success: false,
|
|
73
|
+
error: `Unknown skill '${parsed.skill}' — no SKILL.md found under .skills/ or skills/.`,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (parsed.ideology !== undefined && (typeof parsed.ideology !== 'string' || parsed.ideology === '')) {
|
|
78
|
+
return { success: false, error: `--ideology requires a name.\n${usage()}` };
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const writes = [];
|
|
82
|
+
if (parsed.skill !== undefined) {
|
|
83
|
+
setConfigOverride(projectRoot, ['roles', parsed.role, 'skill'], parsed.skill);
|
|
84
|
+
writes.push(`roles.${parsed.role}.skill=${parsed.skill}`);
|
|
85
|
+
}
|
|
86
|
+
if (parsed.ideology !== undefined) {
|
|
87
|
+
setConfigOverride(projectRoot, ['roles', parsed.role, 'ideology'], parsed.ideology);
|
|
88
|
+
writes.push(`roles.${parsed.role}.ideology=${parsed.ideology}`);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return { success: true, output: `Updated ${writes.join(', ')}` };
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
module.exports = {
|
|
95
|
+
name: 'role',
|
|
96
|
+
description: 'Bind a role to a skill/ideology in .forge/config.yaml',
|
|
97
|
+
usage: usage(),
|
|
98
|
+
handler,
|
|
99
|
+
};
|