forge-workflow 0.1.0-beta.3 → 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 (196) 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 +21 -1
  5. package/bin/forge.js +16 -369
  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 +9 -4
  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 +117 -17
  16. package/lefthook.yml +12 -0
  17. package/lib/activation/ensure-forge-home.js +33 -15
  18. package/lib/adapters/greptile-review-adapter.js +1 -1
  19. package/lib/adapters/pr-state-adapter.js +397 -100
  20. package/lib/agents-config.js +5 -0
  21. package/lib/audit-evidence.js +71 -110
  22. package/lib/capped-jsonl-log.js +236 -0
  23. package/lib/commands/_issue.js +31 -46
  24. package/lib/commands/_manifest.js +1 -1
  25. package/lib/commands/_registry.js +2 -2
  26. package/lib/commands/_resolve-command-opts.js +36 -29
  27. package/lib/commands/claim.js +2 -4
  28. package/lib/commands/clean.js +196 -32
  29. package/lib/commands/dev.js +4 -33
  30. package/lib/commands/hooks.js +358 -13
  31. package/lib/commands/insights.js +8 -3
  32. package/lib/commands/merge.js +600 -40
  33. package/lib/commands/plan.js +23 -115
  34. package/lib/commands/pr.js +1 -1
  35. package/lib/commands/preflight.js +11 -2
  36. package/lib/commands/prime.js +23 -3
  37. package/lib/commands/push.js +41 -51
  38. package/lib/commands/recall.js +60 -16
  39. package/lib/commands/recap.js +6 -1
  40. package/lib/commands/release.js +18 -4
  41. package/lib/commands/serve.js +5 -2
  42. package/lib/commands/setup.js +191 -95
  43. package/lib/commands/shepherd.js +49 -4
  44. package/lib/commands/ship.js +22 -23
  45. package/lib/commands/skill.js +383 -0
  46. package/lib/commands/status.js +54 -33
  47. package/lib/commands/test.js +56 -34
  48. package/lib/commands/worktree.js +247 -43
  49. package/lib/core/runtime-graph.js +89 -15
  50. package/lib/doc-assertions.js +297 -0
  51. package/lib/existing-tdd-gate.js +253 -0
  52. package/lib/forge-context.js +1 -4
  53. package/lib/forge-issues.js +64 -491
  54. package/lib/git-defaults.js +56 -0
  55. package/lib/harness-capability-matrix.js +5 -5
  56. package/lib/hook-renderer.js +147 -16
  57. package/lib/insights.js +96 -80
  58. package/lib/issue-backend.js +42 -3
  59. package/lib/kernel/backing-issue.js +14 -2
  60. package/lib/kernel/broker.js +44 -0
  61. package/lib/kernel/cli-broker-factory.js +12 -1
  62. package/lib/kernel/close-on-merge.js +154 -0
  63. package/lib/kernel/fs-class.js +42 -25
  64. package/lib/kernel/migrations.js +30 -2
  65. package/lib/kernel/schema.js +35 -0
  66. package/lib/kernel/sqlite-driver.js +292 -18
  67. package/lib/lefthook-wiring.js +21 -1
  68. package/lib/memory/router.js +16 -1
  69. package/lib/memory-digest.js +47 -15
  70. package/lib/memory-recall-events.js +145 -0
  71. package/lib/memory-recall.js +212 -0
  72. package/lib/merge-rules.js +8 -4
  73. package/lib/npm-publish-workflow.js +272 -0
  74. package/lib/orientation.js +371 -49
  75. package/lib/plugin-catalog.js +14 -4
  76. package/lib/pr-bundle.js +9 -6
  77. package/lib/pr-monitor/journal.js +18 -2
  78. package/lib/pr-monitor/reconcile-executor.js +842 -0
  79. package/lib/pr-monitor/reconcile-tick.js +138 -0
  80. package/lib/pr-monitor/reconcile.js +0 -0
  81. package/lib/pr-monitor/render-summary.js +196 -0
  82. package/lib/pr-monitor/shepherd-lease.js +252 -0
  83. package/lib/pr-monitor/watch-lifecycle.js +14 -2
  84. package/lib/pr-pull.js +98 -24
  85. package/lib/pr-shepherd.js +34 -8
  86. package/lib/preflight/gates.js +65 -18
  87. package/lib/preflight/runner.js +5 -0
  88. package/lib/project-memory.js +40 -0
  89. package/lib/protected-state-authority.js +305 -0
  90. package/lib/protected-state-surfaces.js +64 -44
  91. package/lib/release-readiness.js +51 -4
  92. package/lib/rules-sync.js +4 -0
  93. package/lib/runtime-health.js +15 -46
  94. package/lib/shell-utils.js +1 -1
  95. package/lib/skill-eval.js +750 -0
  96. package/lib/skills-sync.js +6 -3
  97. package/lib/smart-merge.js +28 -4
  98. package/lib/status/identity.js +46 -0
  99. package/lib/status/presenter.js +0 -35
  100. package/lib/status/snapshot.js +11 -16
  101. package/lib/symlink-utils.js +74 -26
  102. package/lib/upgrade-safety.js +47 -9
  103. package/lib/using-forge.js +328 -0
  104. package/lib/workflow/enforce-stage.js +5 -5
  105. package/lib/workflow/state-manager.js +23 -23
  106. package/package.json +6 -7
  107. package/rules/using-forge.md +24 -0
  108. package/scripts/doc-asserting-tests.js +158 -0
  109. package/scripts/forge-team/index.sh +0 -5
  110. package/scripts/forge-team/tests/dispatcher.test.sh +1 -1
  111. package/scripts/forge-team/tests/workflow-integration.test.sh +0 -1
  112. package/scripts/lib/behavioral-eval-runner.js +310 -0
  113. package/scripts/lib/behavioral-eval-runtime.js +456 -0
  114. package/scripts/lib/eval-evidence.js +328 -0
  115. package/scripts/lib/eval-runner.js +81 -41
  116. package/scripts/lib/immutable-eval-corpus.js +309 -0
  117. package/scripts/lib/promotion-evidence-loader.js +94 -0
  118. package/scripts/lib/promotion-scorecard.js +314 -0
  119. package/scripts/npm-release-receipt.js +134 -0
  120. package/scripts/process-tree.js +761 -0
  121. package/scripts/protected-state-check.js +47 -22
  122. package/scripts/run-command-eval.js +29 -1
  123. package/scripts/sync-d20-audit.js +172 -0
  124. package/scripts/test-full-suite.js +249 -37
  125. package/scripts/test.js +184 -44
  126. package/skills/claim-safety/SKILL.md +4 -0
  127. package/skills/claim-safety/evals/scorecard.json +41 -0
  128. package/skills/coverage.json +83 -0
  129. package/skills/dev/SKILL.md +4 -0
  130. package/skills/dev/evals/scorecard.json +41 -0
  131. package/skills/gates/SKILL.md +80 -0
  132. package/skills/gates/evals/evals.json +38 -0
  133. package/skills/gates/evals/scorecard.json +41 -0
  134. package/skills/hermes-forge/SKILL.md +1 -0
  135. package/skills/hermes-forge/evals/scorecard.json +41 -0
  136. package/skills/issue-basics/SKILL.md +1 -0
  137. package/skills/issue-basics/evals/scorecard.json +41 -0
  138. package/skills/kernel/SKILL.md +38 -0
  139. package/skills/kernel/evals/scorecard.json +41 -0
  140. package/skills/memory/SKILL.md +16 -1
  141. package/skills/memory/evals/scorecard.json +41 -0
  142. package/skills/parallel-deep-research/SKILL.md +1 -0
  143. package/skills/parallel-deep-research/evals/scorecard.json +41 -0
  144. package/skills/plan/SKILL.md +6 -0
  145. package/skills/plan/evals/scorecard.json +41 -0
  146. package/skills/portability/SKILL.md +47 -0
  147. package/skills/portability/evals/evals.json +34 -0
  148. package/skills/portability/evals/scorecard.json +41 -0
  149. package/skills/research/SKILL.md +1 -0
  150. package/skills/research/evals/scorecard.json +41 -0
  151. package/skills/review/SKILL.md +10 -11
  152. package/skills/review/evals/scorecard.json +41 -0
  153. package/skills/rollback/SKILL.md +5 -11
  154. package/skills/rollback/evals/scorecard.json +41 -0
  155. package/skills/setup/SKILL.md +91 -0
  156. package/skills/setup/evals/evals.json +42 -0
  157. package/skills/setup/evals/scorecard.json +41 -0
  158. package/skills/shepherd/SKILL.md +84 -38
  159. package/skills/shepherd/evals/evals.json +21 -9
  160. package/skills/shepherd/evals/scorecard.json +41 -0
  161. package/skills/ship/SKILL.md +10 -12
  162. package/skills/ship/evals/scorecard.json +41 -0
  163. package/skills/smith/SKILL.md +8 -0
  164. package/skills/smith/evals/scorecard.json +41 -0
  165. package/skills/sonarcloud/SKILL.md +1 -0
  166. package/skills/sonarcloud/evals/scorecard.json +41 -0
  167. package/skills/sonarcloud-analysis/SKILL.md +1 -0
  168. package/skills/sonarcloud-analysis/evals/scorecard.json +41 -0
  169. package/skills/status/SKILL.md +3 -0
  170. package/skills/status/evals/scorecard.json +41 -0
  171. package/skills/triage-ready/SKILL.md +2 -0
  172. package/skills/triage-ready/evals/scorecard.json +41 -0
  173. package/skills/using-forge/SKILL.md +104 -0
  174. package/skills/using-forge/evals/scorecard.json +41 -0
  175. package/skills/validate/SKILL.md +4 -0
  176. package/skills/validate/evals/scorecard.json +41 -0
  177. package/skills/verify/SKILL.md +4 -0
  178. package/skills/verify/evals/scorecard.json +41 -0
  179. package/skills/worktree/SKILL.md +92 -0
  180. package/skills/worktree/evals/evals.json +38 -0
  181. package/skills/worktree/evals/scorecard.json +41 -0
  182. package/lib/adapters/beads-issue-adapter.js +0 -127
  183. package/lib/beads-nudge.js +0 -91
  184. package/lib/beads-setup.js +0 -538
  185. package/lib/beads-sync-scaffold.js +0 -189
  186. package/lib/commands/board.js +0 -64
  187. package/lib/pat-setup.js +0 -207
  188. package/lib/pr-monitor/render-sticky.js +0 -192
  189. package/lib/pr-monitor/upsert-sticky.js +0 -169
  190. package/lib/status/beads-snapshot.js +0 -145
  191. package/scripts/beads-context.sh +0 -577
  192. package/scripts/beads-migrate-to-dolt.sh +0 -7
  193. package/scripts/beads-upgrade-smoke.sh +0 -284
  194. package/scripts/forge-team/lib/dashboard.sh +0 -316
  195. package/scripts/forge-team/tests/dashboard.test.sh +0 -155
  196. package/scripts/lib/beads-migrate-to-dolt.mjs +0 -503
@@ -0,0 +1,41 @@
1
+ {
2
+ "skill": "worktree",
3
+ "fixtures": "present",
4
+ "static": {
5
+ "token_cost": {
6
+ "desc_chars": 1013,
7
+ "body_lines": 75,
8
+ "score": 43
9
+ },
10
+ "caps": {
11
+ "desc_within": true,
12
+ "body_within": true,
13
+ "score": 100
14
+ },
15
+ "description_quality": {
16
+ "has_trigger_cues": true,
17
+ "has_disambiguation_cues": true,
18
+ "adequate_length": true,
19
+ "score": 100
20
+ }
21
+ },
22
+ "router_reachability": {
23
+ "has_curated_rule": true,
24
+ "router_exempt": false,
25
+ "fixtures": "present",
26
+ "fixtures_total": 6,
27
+ "fixtures_best_hit": 6,
28
+ "reachable": true,
29
+ "keyword_alignment": 1
30
+ },
31
+ "behavioral": {
32
+ "trigger_recall": null,
33
+ "trigger_precision": null,
34
+ "disambiguation": null,
35
+ "chain_correctness": null,
36
+ "outcome_quality": null,
37
+ "variance": null,
38
+ "note": "behavioral — W5 (LLM judge): semantic recall/precision/chain/outcome/variance, not deterministic"
39
+ },
40
+ "composite": 83
41
+ }
@@ -1,127 +0,0 @@
1
- 'use strict';
2
-
3
- const {
4
- IssueAdapter,
5
- decideIssueAuthority,
6
- normalizeIssueStatus,
7
- } = require('../issue-adapter.js');
8
-
9
- class BeadsIssueAdapter extends IssueAdapter {
10
- constructor(options = {}) {
11
- super({
12
- id: options.id || 'beads',
13
- kind: 'issue',
14
- name: options.name || 'Beads Issue Adapter',
15
- version: options.version || '0.1.0',
16
- });
17
- this.runBeadsOperation = options.runBeadsOperation;
18
- }
19
-
20
- run(operation, args = [], context = {}) {
21
- if (typeof this.runBeadsOperation !== 'function') {
22
- throw new TypeError('runBeadsOperation is not configured on this adapter');
23
- }
24
-
25
- return this.runBeadsOperation(operation, args, context, context.deps || {});
26
- }
27
-
28
- list(args = [], context = {}) {
29
- return this.run('list', args, context);
30
- }
31
-
32
- ready(args = [], context = {}) {
33
- return this.run('ready', args, context);
34
- }
35
-
36
- read(args = [], context = {}) {
37
- return this.run('show', args, context);
38
- }
39
-
40
- show(args = [], context = {}) {
41
- return this.read(args, context);
42
- }
43
-
44
- create(args = [], context = {}) {
45
- return this.run('create', args, context);
46
- }
47
-
48
- search(args = [], context = {}) {
49
- return this.run('search', args, context);
50
- }
51
-
52
- stats(args = [], context = {}) {
53
- return this.run('stats', args, context);
54
- }
55
-
56
- update(args = [], context = {}) {
57
- return this.run('update', args, context);
58
- }
59
-
60
- close(args = [], context = {}) {
61
- return this.run('close', args, context);
62
- }
63
-
64
- comment(args = [], context = {}) {
65
- return this.run('comment', args, context);
66
- }
67
-
68
- depAdd(args = [], context = {}) {
69
- return this.run('dep.add', args, context);
70
- }
71
-
72
- depRemove(args = [], context = {}) {
73
- return this.run('dep.remove', args, context);
74
- }
75
-
76
- // De-bead parity: claim/release and the KAP-7/KAP-12 derived reads now route
77
- // through the backend abstraction (the translations moved out of _issue.js). The
78
- // beads layer maps claim -> `update <id> --claim`; release has no bd equivalent
79
- // and returns the Kernel-only contract error (handled in runBeadsOperation).
80
- claim(args = [], context = {}) {
81
- return this.run('claim', args, context);
82
- }
83
-
84
- release(args = [], context = {}) {
85
- return this.run('release', args, context);
86
- }
87
-
88
- blocked(args = [], context = {}) {
89
- return this.run('blocked', args, context);
90
- }
91
-
92
- stale(args = [], context = {}) {
93
- return this.run('stale', args, context);
94
- }
95
-
96
- orphans(args = [], context = {}) {
97
- return this.run('orphans', args, context);
98
- }
99
-
100
- lint(args = [], context = {}) {
101
- return this.run('lint', args, context);
102
- }
103
-
104
- // Lease ownership is Kernel-only; the beads layer returns the Kernel-only contract
105
- // error (handled in runBeadsOperation), matching the release passthrough.
106
- owns(args = [], context = {}) {
107
- return this.run('owns', args, context);
108
- }
109
-
110
- // Active-lease listing is Kernel-only (kernel_claims); the beads layer returns the
111
- // Kernel-only contract error (handled in runBeadsOperation), matching owns/release.
112
- claims(args = [], context = {}) {
113
- return this.run('claims', args, context);
114
- }
115
-
116
- mapStatus(status, context = {}) {
117
- return normalizeIssueStatus(status, context);
118
- }
119
-
120
- decideAuthority(change = {}, context = {}) {
121
- return decideIssueAuthority(change, context);
122
- }
123
- }
124
-
125
- module.exports = {
126
- BeadsIssueAdapter,
127
- };
@@ -1,91 +0,0 @@
1
- 'use strict';
2
-
3
- const { resolveIssueBackend } = require('./issue-backend');
4
- const { detectBeadsJsonlSource } = require('./beads-detect');
5
-
6
- // Unmigrated legacy-store nudge (kernel issue a5399f3d — upgrade-safety
7
- // 0.0.10 -> current).
8
- //
9
- // The 0.0.10 -> current upgrade flipped the DEFAULT issue backend to the Kernel,
10
- // but the legacy -> kernel migration fires ONLY from `forge setup`/`init`, never
11
- // lazily on the issue path. So a user who runs `bun update` then `forge list` /
12
- // `forge ready` reads an EMPTY kernel and their 0.0.10 issues APPEAR GONE — the
13
- // data is safe on disk, just invisible, with no hint. This helper closes that
14
- // footgun: when the resolved backend is the (default) Kernel, a read comes back
15
- // empty, AND a legacy jsonl store still exists, it prints a one-time guided hint.
16
- //
17
- // It lives in this NEUTRAL module (not lib/commands/_issue.js) on purpose: the
18
- // message text names the retired backend + its `.beads` store, and _issue.js is a
19
- // D20 release-readiness hot-path surface that must stay free of those tokens (the
20
- // bd-call-site audit + kernel-backed checks scan it). Keeping the strings here
21
- // lets the hot path call a token-free helper.
22
- //
23
- // Best-effort and non-blocking: it NEVER throws and never alters the read result.
24
- // Fires at most once per project root per process to avoid spam.
25
- const NUDGE_READS = new Set(['list', 'ready']);
26
- const warnedRoots = new Set();
27
-
28
- // A kernel read looks empty when its contract data carries no issues. Handles the
29
- // issue.list/issue.ready shape ({ issues, count }) plus a bare array / null, and
30
- // is deliberately conservative: anything it cannot confirm as empty is treated as
31
- // NON-empty so a user with real kernel issues is never nagged.
32
- function kernelReadLooksEmpty(result) {
33
- if (!result || typeof result !== 'object' || result.ok !== true) {
34
- return false;
35
- }
36
- const data = result.data;
37
- if (data === null || data === undefined) {
38
- return true;
39
- }
40
- if (Array.isArray(data)) {
41
- return data.length === 0;
42
- }
43
- if (Array.isArray(data.issues)) {
44
- return data.issues.length === 0;
45
- }
46
- if (Array.isArray(data.items)) {
47
- return data.items.length === 0;
48
- }
49
- if (typeof data.count === 'number') {
50
- return data.count === 0;
51
- }
52
- return false;
53
- }
54
-
55
- function maybeWarnUnmigratedBeads(subcommand, result, projectRoot, rawOpts = {}) {
56
- try {
57
- if (!NUDGE_READS.has(subcommand) || !projectRoot) {
58
- return;
59
- }
60
- if (warnedRoots.has(projectRoot)) {
61
- return;
62
- }
63
- const env = rawOpts.env || process.env;
64
- // Resolve the EFFECTIVE backend (default kernel). An explicit opt-in to the
65
- // retired backend means the user chose it deliberately — nothing to nudge.
66
- const backend = resolveIssueBackend({ deps: rawOpts, env, projectRoot, warn: () => {} });
67
- if (backend !== 'kernel' || !kernelReadLooksEmpty(result)) {
68
- return;
69
- }
70
- if (!detectBeadsJsonlSource(projectRoot)) {
71
- return;
72
- }
73
- warnedRoots.add(projectRoot);
74
- console.error(
75
- '\n[forge] Legacy issue data detected (.beads/*.jsonl) but the Kernel issue store is empty.\n'
76
- + 'Forge now defaults to the Kernel backend (breaking change since 0.0.10). Your legacy\n'
77
- + 'issues are safe on disk but will not appear until migrated. To migrate:\n'
78
- + ' forge migrate --from beads # import your legacy issues into the Kernel\n'
79
- + ' forge setup # (re)wire hooks + provision the Kernel store\n'
80
- + 'Prefer to stay on the legacy backend? Set `issueBackend: beads` in .forge/config.yaml '
81
- + '(or FORGE_ISSUE_BACKEND=beads).\n',
82
- );
83
- } catch (_err) { // NOSONAR S2486 — line-scoped; must sit on the catch line
84
- /* the nudge is a best-effort hint; it must never break a read */
85
- }
86
- }
87
-
88
- module.exports = {
89
- maybeWarnUnmigratedBeads,
90
- kernelReadLooksEmpty,
91
- };