forge-workflow 0.1.0-beta.4 → 0.1.0-beta.5

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.
Files changed (119) hide show
  1. package/AGENTS.md +14 -7
  2. package/CHANGELOG.md +43 -1
  3. package/README.md +6 -2
  4. package/bin/forge-cmd.js +20 -0
  5. package/bin/forge.js +16 -374
  6. package/docs/INDEX.md +1 -1
  7. package/docs/guides/BEADS_GITHUB_SYNC.md +2 -31
  8. package/docs/guides/MIGRATION.md +4 -4
  9. package/docs/guides/SETUP.md +16 -16
  10. package/docs/reference/COMMANDS.md +8 -5
  11. package/docs/reference/INSIGHTS_RECAP.md +9 -20
  12. package/docs/reference/RELEASE.md +5 -3
  13. package/docs/reference/TOOLCHAIN.md +8 -0
  14. package/docs/reference/protected-state-surfaces.md +4 -4
  15. package/docs/reference/shepherd.md +54 -25
  16. package/lefthook.yml +12 -0
  17. package/lib/activation/ensure-forge-home.js +33 -15
  18. package/lib/adapters/pr-state-adapter.js +344 -142
  19. package/lib/audit-evidence.js +71 -110
  20. package/lib/capped-jsonl-log.js +236 -0
  21. package/lib/commands/_registry.js +2 -2
  22. package/lib/commands/clean.js +196 -32
  23. package/lib/commands/dev.js +4 -33
  24. package/lib/commands/hooks.js +223 -25
  25. package/lib/commands/insights.js +8 -3
  26. package/lib/commands/merge.js +600 -40
  27. package/lib/commands/pr.js +1 -1
  28. package/lib/commands/preflight.js +11 -2
  29. package/lib/commands/prime.js +21 -8
  30. package/lib/commands/push.js +41 -51
  31. package/lib/commands/recall.js +60 -16
  32. package/lib/commands/recap.js +6 -1
  33. package/lib/commands/release.js +17 -2
  34. package/lib/commands/setup.js +191 -94
  35. package/lib/commands/shepherd.js +13 -1
  36. package/lib/commands/ship.js +22 -23
  37. package/lib/commands/skill.js +119 -11
  38. package/lib/commands/status.js +17 -1
  39. package/lib/commands/test.js +24 -34
  40. package/lib/commands/worktree.js +220 -42
  41. package/lib/core/runtime-graph.js +1 -1
  42. package/lib/doc-assertions.js +297 -0
  43. package/lib/existing-tdd-gate.js +253 -0
  44. package/lib/forge-context.js +1 -4
  45. package/lib/forge-issues.js +56 -32
  46. package/lib/git-defaults.js +56 -0
  47. package/lib/harness-capability-matrix.js +3 -3
  48. package/lib/hook-renderer.js +93 -4
  49. package/lib/insights.js +96 -80
  50. package/lib/kernel/backing-issue.js +14 -2
  51. package/lib/kernel/broker.js +16 -0
  52. package/lib/kernel/cli-broker-factory.js +12 -1
  53. package/lib/kernel/close-on-merge.js +154 -0
  54. package/lib/kernel/fs-class.js +42 -25
  55. package/lib/kernel/sqlite-driver.js +153 -29
  56. package/lib/lefthook-wiring.js +21 -1
  57. package/lib/memory/router.js +16 -1
  58. package/lib/memory-digest.js +47 -15
  59. package/lib/memory-recall-events.js +145 -0
  60. package/lib/memory-recall.js +71 -10
  61. package/lib/merge-rules.js +8 -4
  62. package/lib/npm-publish-workflow.js +272 -0
  63. package/lib/orientation.js +68 -43
  64. package/lib/plugin-catalog.js +14 -4
  65. package/lib/pr-bundle.js +5 -6
  66. package/lib/pr-monitor/journal.js +18 -2
  67. package/lib/pr-monitor/reconcile-executor.js +224 -41
  68. package/lib/pr-monitor/render-summary.js +196 -0
  69. package/lib/pr-monitor/shepherd-lease.js +10 -1
  70. package/lib/pr-monitor/watch-lifecycle.js +13 -1
  71. package/lib/pr-pull.js +33 -14
  72. package/lib/pr-shepherd.js +34 -8
  73. package/lib/preflight/gates.js +65 -18
  74. package/lib/preflight/runner.js +5 -0
  75. package/lib/project-memory.js +33 -1
  76. package/lib/protected-state-authority.js +305 -0
  77. package/lib/protected-state-surfaces.js +64 -44
  78. package/lib/release-readiness.js +51 -4
  79. package/lib/shell-utils.js +1 -1
  80. package/lib/skills-sync.js +6 -3
  81. package/lib/smart-merge.js +28 -4
  82. package/lib/symlink-utils.js +74 -26
  83. package/lib/upgrade-safety.js +39 -0
  84. package/lib/using-forge.js +19 -6
  85. package/package.json +6 -7
  86. package/scripts/doc-asserting-tests.js +158 -0
  87. package/scripts/lib/behavioral-eval-runner.js +310 -0
  88. package/scripts/lib/behavioral-eval-runtime.js +456 -0
  89. package/scripts/lib/eval-evidence.js +328 -0
  90. package/scripts/lib/eval-runner.js +81 -41
  91. package/scripts/lib/immutable-eval-corpus.js +309 -0
  92. package/scripts/lib/promotion-evidence-loader.js +94 -0
  93. package/scripts/lib/promotion-scorecard.js +314 -0
  94. package/scripts/npm-release-receipt.js +134 -0
  95. package/scripts/process-tree.js +761 -0
  96. package/scripts/protected-state-check.js +47 -22
  97. package/scripts/run-command-eval.js +29 -1
  98. package/scripts/sync-d20-audit.js +172 -0
  99. package/scripts/test-full-suite.js +249 -37
  100. package/scripts/test.js +176 -43
  101. package/skills/review/SKILL.md +4 -11
  102. package/skills/review/evals/scorecard.json +3 -3
  103. package/skills/rollback/SKILL.md +4 -11
  104. package/skills/rollback/evals/scorecard.json +3 -3
  105. package/skills/shepherd/SKILL.md +20 -14
  106. package/skills/shepherd/evals/scorecard.json +2 -2
  107. package/skills/ship/SKILL.md +4 -12
  108. package/skills/ship/evals/scorecard.json +3 -3
  109. package/skills/worktree/SKILL.md +6 -1
  110. package/skills/worktree/evals/scorecard.json +2 -2
  111. package/lib/beads-setup.js +0 -538
  112. package/lib/beads-sync-scaffold.js +0 -189
  113. package/lib/pat-setup.js +0 -207
  114. package/lib/pr-monitor/render-sticky.js +0 -206
  115. package/lib/pr-monitor/upsert-sticky.js +0 -169
  116. package/scripts/beads-context.sh +0 -577
  117. package/scripts/beads-migrate-to-dolt.sh +0 -7
  118. package/scripts/beads-upgrade-smoke.sh +0 -284
  119. package/scripts/lib/beads-migrate-to-dolt.mjs +0 -503
package/bin/forge.js CHANGED
@@ -80,10 +80,8 @@ const { firstPositionalIndex } = require('../lib/global-flags');
80
80
  const contextMerge = require('../lib/context-merge');
81
81
  const projectDiscovery = require('../lib/project-discovery');
82
82
 
83
- // Load lib modules for symlink, beads, and PAT setup
83
+ // Load lib modules for symlink setup
84
84
  const { createSymlinkOrCopy: libCreateSymlinkOrCopy } = require('../lib/symlink-utils');
85
- const beadsSetupLib = require('../lib/beads-setup');
86
- const { scaffoldBeadsSync } = require('../lib/beads-sync-scaffold');
87
85
 
88
86
  // Load incremental setup modules
89
87
  const { detectEnvironment } = require('../lib/detect-agent');
@@ -113,7 +111,6 @@ let FORCE_MODE = false;
113
111
  let VERBOSE_MODE = false;
114
112
  let NON_INTERACTIVE = false;
115
113
  let SYMLINK_ONLY = false; // --symlink: fail instead of copy fallback
116
- let SYNC_ENABLED = false; // --sync: scaffold Beads GitHub sync workflows
117
114
  let actionLog = new SetupActionLog();
118
115
 
119
116
  // Detected package manager
@@ -429,7 +426,7 @@ Use these default-template commands via \`/command-name\`:
429
426
  - \`/validate\` - Type check, lint, security, tests (HARD-GATE)
430
427
  - \`/ship\` - Push and create PR with design doc reference
431
428
  - \`/review\` - Handle ALL PR issues (Actions, Greptile, SonarCloud)
432
- - \`/verify\` - Post-merge health check (CI on main, close Beads)
429
+ - \`/verify\` - Post-merge health check (CI on main, close kernel issues)
433
430
 
434
431
  Pre-merge gate (not a numbered stage): finish docs + confirm CI green + hand off the PR — embedded in the /ship and /review stages.
435
432
 
@@ -706,9 +703,7 @@ async function detectProjectStatus() {
706
703
  agentsMdLines: 0,
707
704
  claudeMdLines: 0,
708
705
  // Project tools status
709
- hasBeads: isBeadsInitialized(),
710
706
  hasSkills: isSkillsInitialized(),
711
- beadsInstallType: checkForBeads(),
712
707
  skillsInstallType: checkForSkills(),
713
708
  // Enhanced: Auto-detected project context
714
709
  autoDetected: null
@@ -2196,15 +2191,6 @@ function displaySetupSummary(selectedAgents) {
2196
2191
  console.log('Project Tools Status:');
2197
2192
  console.log('');
2198
2193
 
2199
- // Beads status
2200
- if (isBeadsInitialized()) {
2201
- console.log(' ✓ Beads initialized - Track work: forge ready');
2202
- } else if (checkForBeads()) {
2203
- console.log(' ! Beads available - Run: bd init');
2204
- } else {
2205
- console.log(` - Beads not installed - Run: ${PKG_MANAGER} install -g @beads/bd && bd init`);
2206
- }
2207
-
2208
2194
  // Skills status
2209
2195
  if (isSkillsInitialized()) {
2210
2196
  console.log(' ✓ Skills initialized - Manage skills: skills list');
@@ -2351,7 +2337,7 @@ function parseFlags() {
2351
2337
  verbose: false, // Show file-by-file detail in setup summary
2352
2338
  dryRun: false, // Preview planned actions without writing files
2353
2339
  symlink: false, // Create CLAUDE.md as symlink to AGENTS.md (--symlink)
2354
- sync: false, // Scaffold Beads GitHub sync workflows (--sync)
2340
+ skillsOnly: false, // Install skills without Git or harness hook enforcement
2355
2341
  };
2356
2342
 
2357
2343
  // Issue passthrough commands delegate all flags to bd.
@@ -2417,8 +2403,8 @@ function parseFlags() {
2417
2403
  } else if (arg === '--symlink') {
2418
2404
  flags.symlink = true;
2419
2405
  i++;
2420
- } else if (arg === '--sync') {
2421
- flags.sync = true;
2406
+ } else if (arg === '--skills-only' || arg === '--no-hooks') {
2407
+ flags.skillsOnly = true;
2422
2408
  i++;
2423
2409
  } else if (arg === '--interview') {
2424
2410
  flags.interview = true;
@@ -2577,6 +2563,8 @@ function showHelp() {
2577
2563
  console.log(' --type <type> Set workflow profile type manually');
2578
2564
  console.log(' Options: critical, standard, simple, hotfix, docs, refactor');
2579
2565
  console.log(' --dry-run Preview planned actions without writing any files');
2566
+ console.log(' --skills-only Install skills without Git hooks, Forge-native, or harness hooks');
2567
+ console.log(' Alias: --no-hooks');
2580
2568
  console.log(' --interview Force context interview (gather project information)');
2581
2569
  console.log(' --budget <mode> Budget mode for recommend (free, open-source, startup, professional, custom)');
2582
2570
  console.log(' --yes, -y Non-interactive setup with sensible defaults');
@@ -2602,6 +2590,7 @@ function showHelp() {
2602
2590
  console.log(' npx forge setup --yes # Non-interactive, defaults to claude');
2603
2591
  console.log(' npx forge setup --yes --agents cursor # Non-interactive, specific agent');
2604
2592
  console.log(' npx forge setup --all --skip-external # All agents, no services');
2593
+ console.log(' npx forge setup --agents claude --skills-only # Skills without hook enforcement');
2605
2594
  console.log(' npx forge setup --merge=smart # Use intelligent merge for existing files');
2606
2595
  console.log(' npx forge setup --type=critical # Set workflow profile manually');
2607
2596
  console.log(' npx forge setup --interview # Force context interview');
@@ -2835,121 +2824,6 @@ function checkForLefthook() {
2835
2824
  return status;
2836
2825
  }
2837
2826
 
2838
- // Check if Beads is installed (global, local, or bunx-capable)
2839
- function checkForBeads() {
2840
- // Try global install first
2841
- try {
2842
- secureExecFileSync('bd', ['version'], { stdio: 'ignore' });
2843
- return 'global';
2844
- } catch (err) {
2845
- // Not global
2846
- console.warn('Beads not found globally:', err.message);
2847
- }
2848
-
2849
- // Check if bunx can run it
2850
- try {
2851
- secureExecFileSync('bunx', ['@beads/bd', 'version'], { stdio: 'ignore' });
2852
- return 'bunx';
2853
- } catch (err) {
2854
- // Not bunx-capable
2855
- console.warn('Beads not available via bunx:', err.message);
2856
- }
2857
-
2858
- // Check local project installation
2859
- const pkgPath = path.join(projectRoot, 'package.json');
2860
- if (!fs.existsSync(pkgPath)) return null;
2861
-
2862
- try {
2863
- const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
2864
- const isInstalled = pkg.devDependencies?.['@beads/bd'] || pkg.dependencies?.['@beads/bd'];
2865
- return isInstalled ? 'local' : null;
2866
- } catch (err) {
2867
- console.warn('Failed to check Beads in package.json:', err.message);
2868
- return null;
2869
- }
2870
- }
2871
- // Check if Beads is initialized in project — delegates to lib/beads-setup
2872
- function isBeadsInitialized() {
2873
- return beadsSetupLib.isBeadsInitialized(projectRoot);
2874
- }
2875
-
2876
- function migrateExistingBeadsLocalState() {
2877
- if (!fs.existsSync(path.join(projectRoot, '.beads'))) {
2878
- return;
2879
- }
2880
-
2881
- try {
2882
- beadsSetupLib.ensureBeadsGitExclude(projectRoot);
2883
- } catch (err) {
2884
- console.warn(` Warning: failed to migrate Beads local state: ${err.message}`);
2885
- }
2886
- }
2887
-
2888
- // Initialize Beads in the project using the defensive safeBeadsInit wrapper
2889
- // Handles config/gitignore writes, hook snapshot/restore, and JSONL pre-seeding
2890
- function initializeBeads(installType) {
2891
- console.log('Initializing Beads in project...');
2892
-
2893
- // Build the execBdInit function based on installType
2894
- const execBdInit = (root) => {
2895
- // SECURITY: execFileSync with hardcoded commands
2896
- if (installType === 'global') {
2897
- secureExecFileSync('bd', ['init'], { stdio: 'inherit', cwd: root });
2898
- } else if (installType === 'bunx') {
2899
- secureExecFileSync('bunx', ['@beads/bd', 'init'], { stdio: 'inherit', cwd: root });
2900
- } else if (installType === 'local') {
2901
- secureExecFileSync('npx', ['bd', 'init'], { stdio: 'inherit', cwd: root });
2902
- }
2903
- };
2904
-
2905
- // Derive prefix from package.json name or directory name
2906
- let prefix;
2907
- try {
2908
- const pkg = JSON.parse(fs.readFileSync(path.join(projectRoot, 'package.json'), 'utf8'));
2909
- prefix = pkg.name || path.basename(projectRoot);
2910
- } catch (_e) {
2911
- prefix = path.basename(projectRoot);
2912
- }
2913
-
2914
- try {
2915
- const result = beadsSetupLib.safeBeadsInit(projectRoot, {
2916
- prefix,
2917
- execBdInit,
2918
- restoreLefthook: (root) => {
2919
- try {
2920
- secureExecFileSync('lefthook', ['install'], { stdio: 'ignore', cwd: root });
2921
- } catch (_e) {
2922
- // lefthook may not be installed yet — non-fatal
2923
- }
2924
- }
2925
- });
2926
-
2927
- if (result.skipped) {
2928
- console.log(' ✓ Beads already initialized');
2929
- return true;
2930
- }
2931
-
2932
- if (!result.success) {
2933
- for (const e of result.errors) {
2934
- console.log(` ⚠ ${e}`);
2935
- }
2936
- console.log(' Run manually: bd init');
2937
- return false;
2938
- }
2939
-
2940
- for (const w of result.warnings) {
2941
- console.warn(` ⚠ ${w}`);
2942
- }
2943
- console.log(' ✓ Beads initialized');
2944
-
2945
- return true;
2946
- } catch (err) {
2947
- console.log(' ⚠ Failed to initialize Beads:', err.message);
2948
- console.log(' Run manually: bd init');
2949
- return false;
2950
- }
2951
- }
2952
-
2953
2827
  // Check if Skills CLI is installed
2954
2828
  function checkForSkills() {
2955
2829
  // Try global install first
@@ -3006,60 +2880,6 @@ function initializeSkills(installType) {
3006
2880
  }
3007
2881
  }
3008
2882
 
3009
- // Prompt for Beads setup - extracted to reduce cognitive complexity
3010
- async function promptBeadsSetup(question) {
3011
- console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
3012
- console.log('Beads Setup (Recommended)');
3013
- console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
3014
- console.log('');
3015
-
3016
- const beadsInitialized = isBeadsInitialized();
3017
- const beadsStatus = checkForBeads();
3018
-
3019
- if (beadsInitialized) {
3020
- migrateExistingBeadsLocalState();
3021
- console.log('✓ Beads is already initialized in this project');
3022
- console.log('');
3023
- return;
3024
- }
3025
-
3026
- if (beadsStatus) {
3027
- // Already installed, just need to initialize
3028
- console.log(`ℹ Beads is installed (${beadsStatus}), but not initialized`);
3029
- const initBeads = await question('Initialize Beads in this project? (y/n): ');
3030
-
3031
- if (initBeads.toLowerCase() === 'y') {
3032
- initializeBeads(beadsStatus);
3033
- } else {
3034
- console.log('Skipped Beads initialization. Run manually: bd init');
3035
- }
3036
- console.log('');
3037
- return;
3038
- }
3039
-
3040
- // Not installed
3041
- console.log('ℹ Beads is not installed');
3042
- const installBeads = await question('Install Beads? (y/n): ');
3043
-
3044
- if (installBeads.toLowerCase() !== 'y') {
3045
- console.log('Skipped Beads installation');
3046
- console.log('');
3047
- return;
3048
- }
3049
-
3050
- console.log('');
3051
- console.log('Choose installation method:');
3052
- console.log(' 1. Global (recommended) - Available system-wide');
3053
- console.log(' 2. Local - Project-specific devDependency');
3054
- console.log(' 3. Bunx - Use via bunx (requires bun)');
3055
- console.log('');
3056
- const method = await question('Choose method (1-3): ');
3057
-
3058
- console.log('');
3059
- installBeadsWithMethod(method);
3060
- console.log('');
3061
- }
3062
-
3063
2883
  // Helper: Install tool via bunx - extracted to reduce cognitive complexity
3064
2884
  function installViaBunx(packageName, versionArgs, initFn, toolName) {
3065
2885
  console.log('Testing bunx capability...');
@@ -3073,68 +2893,6 @@ function installViaBunx(packageName, versionArgs, initFn, toolName) {
3073
2893
  }
3074
2894
  }
3075
2895
 
3076
- // Helper: Install Beads with chosen method - extracted to reduce cognitive complexity
3077
- // SECURITY NOTE: Downloads and executes a remote PowerShell script.
3078
- // The npm @beads/bd package is broken on Windows (GitHub Issue #1031, closed "not planned"),
3079
- // so the official PowerShell installer is the only supported path.
3080
- // Mitigations: HTTPS transport (prevents MITM), official beads repo, user-visible URL.
3081
- // TODO: Pin to a versioned release tag once beads publishes tagged releases (e.g. v0.49.1).
3082
- const BEADS_INSTALL_PS1_URL = 'https://raw.githubusercontent.com/steveyegge/beads/main/install.ps1';
3083
-
3084
- function installBeadsOnWindows() {
3085
- console.log(' (Windows detected: using PowerShell installer)');
3086
- console.log(` Downloading: ${BEADS_INSTALL_PS1_URL}`);
3087
- secureExecFileSync('powershell.exe', [
3088
- '-NoProfile', '-NonInteractive', '-Command',
3089
- `irm ${BEADS_INSTALL_PS1_URL} | iex`
3090
- ], { stdio: 'inherit' });
3091
- }
3092
-
3093
- function installBeadsWithMethod(method) {
3094
- try {
3095
- // SECURITY: secureExecFileSync with hardcoded commands
3096
- if (method === '1') {
3097
- console.log('Installing Beads globally...');
3098
- if (process.platform === 'win32') {
3099
- installBeadsOnWindows();
3100
- } else {
3101
- const pkgManager = PKG_MANAGER === 'bun' ? 'bun' : 'npm';
3102
- secureExecFileSync(pkgManager, ['install', '-g', '@beads/bd'], { stdio: 'inherit' });
3103
- }
3104
- console.log(' ✓ Beads installed globally');
3105
- initializeBeads('global');
3106
- } else if (method === '2') {
3107
- console.log('Installing Beads locally...');
3108
- // On Windows, npm postinstall for @beads/bd runs Expand-Archive which has EPERM file-locking
3109
- // (GitHub Issue #1031, closed "not planned") — same root cause as global install.
3110
- // Redirect Windows users to the global PowerShell installer instead.
3111
- if (process.platform === 'win32') {
3112
- console.log(' ⚠ Local install not supported on Windows (npm @beads/bd EPERM issue).');
3113
- console.log(' Falling back to global PowerShell installer...');
3114
- installBeadsOnWindows();
3115
- } else {
3116
- const pkgManager = PKG_MANAGER === 'bun' ? 'bun' : 'npm';
3117
- secureExecFileSync(pkgManager, ['install', '-D', '@beads/bd'], { stdio: 'inherit', cwd: projectRoot });
3118
- }
3119
- console.log(' ✓ Beads installed');
3120
- // On Windows the fallback was global (PowerShell installer), so init as 'global'
3121
- initializeBeads(process.platform === 'win32' ? 'global' : 'local');
3122
- } else if (method === '3') {
3123
- installViaBunx('@beads/bd', ['version'], initializeBeads, 'Beads');
3124
- } else {
3125
- console.log('Invalid choice. Skipping Beads installation.');
3126
- }
3127
- } catch (err) {
3128
- console.warn('Beads installation failed:', err.message);
3129
- console.log(' ⚠ Failed to install Beads:', err.message);
3130
- if (process.platform === 'win32') {
3131
- console.log(` Run manually: irm ${BEADS_INSTALL_PS1_URL} | iex`);
3132
- } else {
3133
- console.log(` Run manually: ${PKG_MANAGER === 'bun' ? 'bun add -g' : 'npm install -g'} @beads/bd && bd init`);
3134
- }
3135
- }
3136
- }
3137
-
3138
2896
  // Helper: Get package-manager-specific install args for Skills
3139
2897
  function getSkillsInstallArgs(scope) {
3140
2898
  const globalFlag = scope === 'global' ? '-g' : '-D';
@@ -3223,68 +2981,23 @@ async function promptSkillsSetup(question) {
3223
2981
  console.log('');
3224
2982
  }
3225
2983
 
3226
- // Interactive setup for Beads and Skills
3227
- async function setupProjectTools(rl, question) {
2984
+ // Interactive setup for Skills
2985
+ async function setupProjectTools(_rl, question) {
3228
2986
  console.log('');
3229
2987
  console.log('═══════════════════════════════════════════════════════════');
3230
2988
  console.log(' STEP 2: Project Tools (Recommended)');
3231
2989
  console.log('═══════════════════════════════════════════════════════════');
3232
2990
  console.log('');
3233
- console.log('Forge recommends three tools for enhanced workflows:');
3234
- console.log('');
3235
- console.log('• Beads - Git-backed issue tracking');
3236
- console.log(' Persists tasks across sessions, tracks dependencies.');
3237
- console.log(' Command: forge ready, forge create, forge close');
2991
+ console.log('Forge recommends the following tool for enhanced workflows:');
3238
2992
  console.log('');
3239
2993
  console.log('• Skills - Universal SKILL.md management');
3240
2994
  console.log(' Manage AI agent skills across all agents.');
3241
2995
  console.log(' Command: skills create, skills list, skills sync');
3242
2996
  console.log('');
3243
2997
 
3244
- // Use helper functions to reduce complexity
3245
- await promptBeadsSetup(question);
3246
2998
  await promptSkillsSetup(question);
3247
2999
  }
3248
3000
 
3249
- // Auto-setup Beads in quick mode - extracted to reduce cognitive complexity
3250
- function autoSetupBeadsInQuickMode() {
3251
- const beadsStatus = checkForBeads();
3252
- const beadsInitialized = isBeadsInitialized();
3253
-
3254
- if (beadsInitialized) {
3255
- migrateExistingBeadsLocalState();
3256
- }
3257
-
3258
- if (!beadsInitialized && beadsStatus) {
3259
- console.log('📦 Initializing Beads...');
3260
- initializeBeads(beadsStatus);
3261
- console.log('');
3262
- } else if (!beadsInitialized && !beadsStatus) {
3263
- console.log('📦 Installing Beads globally...');
3264
- try {
3265
- // SECURITY: use PowerShell on Windows (npm @beads/bd is broken on Windows - Issue #1031)
3266
- if (process.platform === 'win32') {
3267
- installBeadsOnWindows();
3268
- } else {
3269
- const pkgManager = PKG_MANAGER === 'bun' ? 'bun' : 'npm';
3270
- secureExecFileSync(pkgManager, ['install', '-g', '@beads/bd'], { stdio: 'inherit' });
3271
- }
3272
- console.log(' ✓ Beads installed globally');
3273
- initializeBeads('global');
3274
- } catch (err) {
3275
- // Installation failed - provide manual instructions
3276
- console.log(' ⚠ Could not install Beads automatically');
3277
- console.log(` Error: ${err.message}`);
3278
- if (process.platform === 'win32') {
3279
- console.log(` Run manually: irm ${BEADS_INSTALL_PS1_URL} | iex`);
3280
- } else {
3281
- console.log(` Run manually: ${PKG_MANAGER === 'bun' ? 'bun add -g' : 'npm install -g'} @beads/bd && bd init`);
3282
- }
3283
- }
3284
- console.log('');
3285
- }
3286
- }
3287
-
3288
3001
  // Helper: Auto-install lefthook if not present - extracted to reduce cognitive complexity
3289
3002
  function autoInstallLefthook() {
3290
3003
  const status = checkForLefthook();
@@ -3340,26 +3053,9 @@ function autoInstallLefthook() {
3340
3053
  }
3341
3054
 
3342
3055
  // Helper: Verify a tool is callable after install - extracted to reduce cognitive complexity
3343
- function verifyToolInstall(command, args, toolName) {
3344
- try {
3345
- secureExecFileSync(command, args, { stdio: 'ignore' });
3346
- return true;
3347
- } catch (_err) { // NOSONAR - S2486: Intentionally ignored; verification failure is handled by caller
3348
- console.log(` ⚠ ${toolName} installed but not callable. Check your PATH.`);
3349
- return false;
3350
- }
3351
- }
3352
3056
 
3353
3057
  // Helper: Auto-setup tools (Skills) in quick mode - extracted to reduce cognitive complexity
3354
3058
  function autoSetupToolsInQuickMode() {
3355
- // Beads: auto-install or initialize
3356
- autoSetupBeadsInQuickMode();
3357
-
3358
- // Post-install verification for Beads
3359
- if (isBeadsInitialized()) {
3360
- verifyToolInstall('bd', ['version'], 'Beads');
3361
- }
3362
-
3363
3059
  // Skills: only initialize if already installed (recommended tool)
3364
3060
  const skillsStatus = checkForSkills();
3365
3061
  if (skillsStatus && !isSkillsInitialized()) {
@@ -3421,7 +3117,7 @@ async function quickSetup(selectedAgents, skipExternal) {
3421
3117
  // Auto-install lefthook if missing
3422
3118
  autoInstallLefthook();
3423
3119
 
3424
- // Auto-setup project tools (Beads, Skills)
3120
+ // Auto-setup project tools (Skills)
3425
3121
  autoSetupToolsInQuickMode();
3426
3122
 
3427
3123
  // Setup Claude first if selected, then remaining agents
@@ -3440,11 +3136,6 @@ async function quickSetup(selectedAgents, skipExternal) {
3440
3136
  // Configure external services with defaults (unless skipped)
3441
3137
  configureDefaultExternalServices(skipExternal);
3442
3138
 
3443
- // --sync flag: scaffold Beads GitHub sync workflows without prompting
3444
- if (SYNC_ENABLED) {
3445
- await handleSyncScaffold();
3446
- }
3447
-
3448
3139
  // Progressive setup summary
3449
3140
  console.log('');
3450
3141
  console.log(renderSetupSummary(actionLog, selectedAgents, VERBOSE_MODE));
@@ -3862,8 +3553,6 @@ async function executeSetup(config) {
3862
3553
  checkPrerequisites();
3863
3554
  console.log('');
3864
3555
 
3865
- migrateExistingBeadsLocalState();
3866
-
3867
3556
  // Copy AGENTS.md (only if not exists — preserve user customizations; actionLog tracks it)
3868
3557
  const agentsDest = path.join(projectRoot, 'AGENTS.md');
3869
3558
  if (fs.existsSync(agentsDest)) {
@@ -3894,32 +3583,12 @@ async function executeSetup(config) {
3894
3583
  // External services (unless skipped)
3895
3584
  await handleExternalServices(skipExternal, agents);
3896
3585
 
3897
- // --sync flag: scaffold Beads GitHub sync workflows without prompting
3898
- if (SYNC_ENABLED) {
3899
- await handleSyncScaffold();
3900
- }
3901
-
3902
3586
  // Progressive setup summary
3903
3587
  console.log('');
3904
3588
  console.log(renderSetupSummary(actionLog, agents, VERBOSE_MODE));
3905
3589
  console.log('');
3906
3590
  }
3907
3591
 
3908
- // Helper: Scaffold Beads GitHub sync when --sync flag is provided
3909
- async function handleSyncScaffold() {
3910
- console.log('');
3911
- console.log('Beads GitHub sync scaffolding is deprecated (--sync).');
3912
- try {
3913
- const result = scaffoldBeadsSync(projectRoot, packageDir);
3914
- console.log(` ${result.message}`);
3915
- for (const f of result.filesRemoved || []) {
3916
- console.log(` Removed deprecated sync file: ${f}`);
3917
- }
3918
- } catch (err) {
3919
- console.error(` Error scaffolding GitHub-Beads sync: ${err.message}`);
3920
- }
3921
- }
3922
-
3923
3592
  // Helper: Handle setup command in non-quick mode
3924
3593
  async function handleSetupCommand(selectedAgents, flags) {
3925
3594
  // Allow callers (e.g. reinstall) to override projectRoot without process.chdir()
@@ -3938,7 +3607,6 @@ async function handleSetupCommand(selectedAgents, flags) {
3938
3607
  }
3939
3608
 
3940
3609
  async function runInteractiveSetupFallback(flags, interactiveSetup = interactiveSetupWithFlags) {
3941
- migrateExistingBeadsLocalState();
3942
3610
  return interactiveSetup(flags);
3943
3611
  }
3944
3612
 
@@ -3989,7 +3657,6 @@ async function main() {
3989
3657
  VERBOSE_MODE = flags.verbose;
3990
3658
  NON_INTERACTIVE = flags.nonInteractive || flags.yes || isNonInteractive();
3991
3659
  SYMLINK_ONLY = flags.symlink;
3992
- SYNC_ENABLED = flags.sync;
3993
3660
  actionLog = new SetupActionLog();
3994
3661
 
3995
3662
  // The non-interactive agent-selection notice is DEBUG-ONLY (kernel issue
@@ -4159,11 +3826,10 @@ async function main() {
4159
3826
  console.error(`Error running '${command}':`, err.message);
4160
3827
  process.exit(1);
4161
3828
  }
4162
- // NOTE: the autonomous-shepherd per-command trigger is intentionally NOT wired here.
4163
- // The reconcile engine + daemon land in this PR; the auto-fire wiring is deferred to a
4164
- // follow-up (W-S4c) because a naive dispatch-finally trigger spawns a session-outliving
4165
- // daemon on EVERY command, which breaks test isolation (Windows rmSync EBUSY) and needs
4166
- // its own firing-policy + containment design. Start the daemon via `forge shepherd daemon`.
3829
+ // NOTE: an autonomous-shepherd every-command dispatch-finally trigger is intentionally
3830
+ // NOT wired here. Automatic firing is deliberately limited to the approved seams:
3831
+ // supported session start, successful push, and successful non-dry-run ship. Ordinary
3832
+ // commands cannot spawn a session-outliving daemon or break test isolation.
4167
3833
  return;
4168
3834
  }
4169
3835
 
@@ -4216,12 +3882,6 @@ async function main() {
4216
3882
  return;
4217
3883
  }
4218
3884
 
4219
- if (flags.sync && selectedAgents.length === 0) {
4220
- migrateExistingBeadsLocalState();
4221
- await handleSyncScaffold();
4222
- return;
4223
- }
4224
-
4225
3885
  // Agents specified via flag or --yes default (non-quick mode)
4226
3886
  if (selectedAgents.length > 0) {
4227
3887
  await handleSetupCommand(selectedAgents, flags);
@@ -4621,20 +4281,6 @@ function checkGitWorkingDirectory() {
4621
4281
  }
4622
4282
  }
4623
4283
 
4624
- // Helper: Update Beads issue after PR rollback
4625
- function updateBeadsIssue(commitMessage) {
4626
- const issueMatch = commitMessage.match(/#(\d+)/);
4627
- if (!issueMatch) return;
4628
-
4629
- try {
4630
- const { execFileSync } = require('node:child_process');
4631
- execFileSync('bd', ['update', issueMatch[1], '--status', 'reverted', '--comment', 'PR reverted'], { stdio: 'inherit' });
4632
- console.log(` Updated Beads issue #${issueMatch[1]} to 'reverted'`);
4633
- } catch {
4634
- // Beads not installed - silently continue
4635
- }
4636
- }
4637
-
4638
4284
  // Helper: Handle commit rollback
4639
4285
  function handleCommitRollback(target, dryRun, execSync) {
4640
4286
  if (dryRun) {
@@ -4656,10 +4302,6 @@ function handlePrRollback(target, dryRun, execSync) {
4656
4302
  files.trim().split('\n').forEach(f => console.log(` - ${f}`));
4657
4303
  } else {
4658
4304
  execSync(`git revert -m 1 --no-edit ${target}`, { stdio: 'inherit' });
4659
-
4660
- // Update Beads issue if linked
4661
- const commitMsg = execSync(`git log -1 --format=%B ${target}`, { encoding: 'utf-8' });
4662
- updateBeadsIssue(commitMsg);
4663
4305
  }
4664
4306
  }
4665
4307
 
package/docs/INDEX.md CHANGED
@@ -49,7 +49,7 @@ This is the canonical map for Forge documentation. DeepWiki and other generated
49
49
  - [Protected path manifest](reference/PROTECTED_PATH_MANIFEST.md) - protected path manifest schema, harness enforcement mapping, and evidence command.
50
50
  - [Patch format](reference/patch-md-format.md) - `.forge/patch.md` conventions.
51
51
  - [Upgrade safety](reference/upgrade-safety.md) - trust policy and rollback limits.
52
- - [Insights and recap](reference/INSIGHTS_RECAP.md) - `forge insights` and `forge recap` evidence sources, output, and limitations.
52
+ - [Insights and recap](reference/INSIGHTS_RECAP.md) - `forge insights` and `forge recap <issue>` evidence sources, output, and limitations.
53
53
  - [Examples](reference/EXAMPLES.md) - worked examples.
54
54
  - [Test environment](reference/test-environment.md) - test harness notes.
55
55
  - [Agent permissions](reference/agent-permissions.md) - agent permission model.
@@ -1,32 +1,3 @@
1
- # Beads/GitHub Sync Deprecation
1
+ # Beads/GitHub Sync (Retired)
2
2
 
3
- Beads/GitHub workflow sync is deprecated. Forge no longer ships active `github-to-beads.yml` or `beads-to-github.yml` workflow templates, and `forge setup --sync` must not create new Beads/GitHub sync scaffolding.
4
-
5
- ## Current Behavior
6
-
7
- - `.beads/` is local runtime/export state and is not committed.
8
- - `forge setup --sync` is retained only as a compatibility cleanup path and removes old generated Beads/GitHub sync files from existing installs when they are present.
9
- - Plain `forge setup` does not perform Beads/GitHub sync cleanup as a side effect.
10
- - `forge sync` may still run local Beads/Dolt sync operations while Beads compatibility remains, but it is not GitHub issue lifecycle sync.
11
-
12
- ## Removed Generated Files
13
-
14
- The `forge setup --sync` compatibility cleanup removes the old generated files:
15
-
16
- ```text
17
- .github/workflows/github-to-beads.yml
18
- .github/workflows/beads-to-github.yml
19
- .github/beads-mapping.json
20
- .github/beads-sync-config.json
21
- .github/scripts/beads-sync/*.mjs
22
- scripts/github-beads-sync.config.json
23
- scripts/github-beads-sync/*.mjs
24
- ```
25
-
26
- Unrelated GitHub workflows are preserved.
27
-
28
- ## Replacement Direction
29
-
30
- Future GitHub issue sync must use Forge Kernel/server authority. Local-only work is durable in local Kernel SQLite. Team or cross-machine issue state is serialized through server authority, then GitHub issues can be updated as a projection from that authority.
31
-
32
- Do not commit live `.beads/` files, create metadata-only PRs, or bypass protected branches to update issue tracker state.
3
+ **Historical.** Beads/GitHub workflow sync was retired with **D45** — Beads is no longer a live Forge feature, so there is nothing left to keep in sync. Forge ships no `github-to-beads.yml` or `beads-to-github.yml` templates and never scaffolds new sync files. Bringing an existing Beads store into Forge is a one-time import, `forge migrate --from beads`; after that the Forge Kernel is the sole issue-state authority, and GitHub issue updates are a server-side projection from that authority (see [docs/work/2026-04-28-skeleton-pivot/forge-kernel-authority-control-plane.md](../work/2026-04-28-skeleton-pivot/forge-kernel-authority-control-plane.md)). Installs that still carry old generated sync files are cleaned automatically: the `forge setup` compatibility cleanup removes the old generated files, with no flag required.
@@ -1,6 +1,6 @@
1
1
  # Migration Guide
2
2
 
3
- Use this guide when moving older Forge docs, habits, or installed scaffolding toward the v0.0.11 public framing.
3
+ Use this guide when moving older Forge docs, habits, or installed scaffolding toward the v0.1.0-beta.5 public framing.
4
4
 
5
5
  ## What Changed
6
6
 
@@ -26,7 +26,7 @@ Use both entry points correctly:
26
26
 
27
27
  - `forge init` creates the `.forge/` adoption skeleton.
28
28
  - `forge setup` installs agent instructions, skills, harness files, local Beads compatibility, and optional setup material.
29
- - `forge setup --sync` is deprecated and retained only to remove old generated Beads/GitHub sync scaffolding when present.
29
+ - `forge setup` also removes old generated Beads/GitHub sync scaffolding when present, with no flag needed.
30
30
 
31
31
  ## From Singular Agent Flags
32
32
 
@@ -39,8 +39,8 @@ forge setup --agents claude,cursor
39
39
 
40
40
  ## Version Labels
41
41
 
42
- - `0.0.11` is the package version for this public docs/readiness release.
43
- - `0.0.10` is the previous published package version.
42
+ - `0.1.0-beta.5` is the current prerelease package version.
43
+ - `0.1.0-beta.4` is the previous prerelease package version.
44
44
  - Internal labels such as `0.0.19` or `v3` describe roadmap slices or historical codenames. Do not present them as current package versions.
45
45
 
46
46
  ## Safe Upgrade Path