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

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 (155) hide show
  1. package/.forge/hooks/check-tdd.js +79 -5
  2. package/.forge/hooks/forge-native-hook.js +194 -8
  3. package/AGENTS.md +2 -1
  4. package/CHANGELOG.md +28 -0
  5. package/QUICKSTART.md +6 -2
  6. package/README.md +3 -1
  7. package/bin/forge-cmd.js +1 -1
  8. package/bin/forge.js +95 -19
  9. package/docs/guides/SETUP.md +4 -1
  10. package/docs/guides/SUPPORT.md +5 -0
  11. package/docs/reference/COMMANDS.md +12 -1
  12. package/docs/reference/shepherd.md +114 -3
  13. package/lib/activation/ensure-forge-home.js +135 -0
  14. package/lib/adapters/beads-kernel-compat.js +67 -0
  15. package/lib/adapters/greptile-review-adapter.js +1 -1
  16. package/lib/adapters/pr-state-adapter.js +103 -8
  17. package/lib/adoption-profiles.js +17 -4
  18. package/lib/agents-config.js +5 -0
  19. package/lib/beads-detect.js +60 -0
  20. package/lib/commands/_aliases.js +248 -0
  21. package/lib/commands/_issue.js +65 -41
  22. package/lib/commands/_manifest.js +3 -1
  23. package/lib/commands/_registry.js +14 -0
  24. package/lib/commands/_resolve-command-opts.js +36 -60
  25. package/lib/commands/claim.js +2 -4
  26. package/lib/commands/gate.js +19 -2
  27. package/lib/commands/hooks.js +294 -12
  28. package/lib/commands/init.js +26 -20
  29. package/lib/commands/memory.js +81 -0
  30. package/lib/commands/migrate.js +0 -161
  31. package/lib/commands/plan.js +71 -123
  32. package/lib/commands/pr.js +88 -0
  33. package/lib/commands/prime.js +8 -1
  34. package/lib/commands/push.js +66 -0
  35. package/lib/commands/recall.js +67 -12
  36. package/lib/commands/recap.js +18 -4
  37. package/lib/commands/release.js +15 -3
  38. package/lib/commands/remember.js +86 -20
  39. package/lib/commands/serve.js +5 -2
  40. package/lib/commands/setup.js +135 -73
  41. package/lib/commands/shepherd.js +102 -4
  42. package/lib/commands/ship.js +40 -4
  43. package/lib/commands/skill.js +275 -0
  44. package/lib/commands/status.js +37 -32
  45. package/lib/commands/test.js +32 -0
  46. package/lib/commands/worktree.js +87 -5
  47. package/lib/core/runtime-graph.js +122 -17
  48. package/lib/forge-issues.js +13 -464
  49. package/lib/gate-events.js +54 -55
  50. package/lib/global-flags.js +30 -0
  51. package/lib/grounding/context-events.js +230 -0
  52. package/lib/grounding/read-first.js +112 -0
  53. package/lib/harness-capability-matrix.js +2 -2
  54. package/lib/hook-renderer.js +144 -12
  55. package/lib/issue-backend.js +42 -3
  56. package/lib/kernel/backing-issue.js +7 -1
  57. package/lib/kernel/broker.js +28 -0
  58. package/lib/kernel/migrations.js +30 -2
  59. package/lib/kernel/owned-kernel.js +43 -0
  60. package/lib/kernel/schema.js +35 -0
  61. package/lib/kernel/sqlite-driver.js +187 -1
  62. package/lib/memory-recall.js +151 -0
  63. package/lib/orientation.js +303 -6
  64. package/lib/pr-bundle.js +6 -2
  65. package/lib/pr-monitor/auto-actions.js +175 -0
  66. package/lib/pr-monitor/digest.js +206 -0
  67. package/lib/pr-monitor/reconcile-executor.js +659 -0
  68. package/lib/pr-monitor/reconcile-tick.js +138 -0
  69. package/lib/pr-monitor/reconcile.js +0 -0
  70. package/lib/pr-monitor/render-sticky.js +57 -8
  71. package/lib/pr-monitor/shepherd-lease.js +243 -0
  72. package/lib/pr-monitor/upsert-sticky.js +169 -0
  73. package/lib/pr-monitor/watch-lifecycle.js +1 -1
  74. package/lib/pr-pull.js +113 -17
  75. package/lib/project-memory.js +8 -0
  76. package/lib/release-readiness.js +17 -1
  77. package/lib/rules-sync.js +4 -0
  78. package/lib/runtime-health.js +15 -46
  79. package/lib/skill-eval.js +750 -0
  80. package/lib/status/identity.js +46 -0
  81. package/lib/status/presenter.js +0 -35
  82. package/lib/status/snapshot.js +11 -16
  83. package/lib/upgrade-safety.js +52 -1
  84. package/lib/using-forge.js +315 -0
  85. package/lib/workflow/enforce-stage.js +64 -7
  86. package/lib/workflow/state-manager.js +23 -23
  87. package/package.json +2 -2
  88. package/rules/using-forge.md +24 -0
  89. package/scripts/forge-team/index.sh +0 -5
  90. package/scripts/forge-team/tests/dispatcher.test.sh +1 -1
  91. package/scripts/forge-team/tests/workflow-integration.test.sh +0 -1
  92. package/scripts/pr-auto-actions.js +93 -0
  93. package/scripts/pr-verdict-label.js +50 -0
  94. package/scripts/test.js +8 -1
  95. package/skills/claim-safety/SKILL.md +4 -0
  96. package/skills/claim-safety/evals/scorecard.json +41 -0
  97. package/skills/coverage.json +83 -0
  98. package/skills/dev/SKILL.md +4 -0
  99. package/skills/dev/evals/scorecard.json +41 -0
  100. package/skills/gates/SKILL.md +80 -0
  101. package/skills/gates/evals/evals.json +38 -0
  102. package/skills/gates/evals/scorecard.json +41 -0
  103. package/skills/hermes-forge/SKILL.md +1 -0
  104. package/skills/hermes-forge/evals/scorecard.json +41 -0
  105. package/skills/issue-basics/SKILL.md +1 -0
  106. package/skills/issue-basics/evals/scorecard.json +41 -0
  107. package/skills/kernel/SKILL.md +38 -0
  108. package/skills/kernel/evals/scorecard.json +41 -0
  109. package/skills/memory/SKILL.md +16 -1
  110. package/skills/memory/evals/scorecard.json +41 -0
  111. package/skills/parallel-deep-research/SKILL.md +1 -0
  112. package/skills/parallel-deep-research/evals/scorecard.json +41 -0
  113. package/skills/plan/SKILL.md +6 -0
  114. package/skills/plan/evals/scorecard.json +41 -0
  115. package/skills/portability/SKILL.md +47 -0
  116. package/skills/portability/evals/evals.json +34 -0
  117. package/skills/portability/evals/scorecard.json +41 -0
  118. package/skills/research/SKILL.md +1 -0
  119. package/skills/research/evals/scorecard.json +41 -0
  120. package/skills/review/SKILL.md +6 -0
  121. package/skills/review/evals/scorecard.json +41 -0
  122. package/skills/rollback/SKILL.md +1 -0
  123. package/skills/rollback/evals/scorecard.json +41 -0
  124. package/skills/setup/SKILL.md +91 -0
  125. package/skills/setup/evals/evals.json +42 -0
  126. package/skills/setup/evals/scorecard.json +41 -0
  127. package/skills/shepherd/SKILL.md +76 -36
  128. package/skills/shepherd/evals/evals.json +21 -9
  129. package/skills/shepherd/evals/scorecard.json +41 -0
  130. package/skills/ship/SKILL.md +6 -0
  131. package/skills/ship/evals/scorecard.json +41 -0
  132. package/skills/smith/SKILL.md +8 -0
  133. package/skills/smith/evals/scorecard.json +41 -0
  134. package/skills/sonarcloud/SKILL.md +1 -0
  135. package/skills/sonarcloud/evals/scorecard.json +41 -0
  136. package/skills/sonarcloud-analysis/SKILL.md +1 -0
  137. package/skills/sonarcloud-analysis/evals/scorecard.json +41 -0
  138. package/skills/status/SKILL.md +3 -0
  139. package/skills/status/evals/scorecard.json +41 -0
  140. package/skills/triage-ready/SKILL.md +2 -0
  141. package/skills/triage-ready/evals/scorecard.json +41 -0
  142. package/skills/using-forge/SKILL.md +104 -0
  143. package/skills/using-forge/evals/scorecard.json +41 -0
  144. package/skills/validate/SKILL.md +4 -0
  145. package/skills/validate/evals/scorecard.json +41 -0
  146. package/skills/verify/SKILL.md +4 -0
  147. package/skills/verify/evals/scorecard.json +41 -0
  148. package/skills/worktree/SKILL.md +87 -0
  149. package/skills/worktree/evals/evals.json +38 -0
  150. package/skills/worktree/evals/scorecard.json +41 -0
  151. package/lib/adapters/beads-issue-adapter.js +0 -127
  152. package/lib/commands/board.js +0 -64
  153. package/lib/status/beads-snapshot.js +0 -145
  154. package/scripts/forge-team/lib/dashboard.sh +0 -316
  155. package/scripts/forge-team/tests/dashboard.test.sh +0 -155
@@ -0,0 +1,34 @@
1
+ [
2
+ {
3
+ "query": "Back up the kernel backlog to a git-tracked JSONL snapshot.",
4
+ "should_trigger": true
5
+ },
6
+ {
7
+ "query": "Export the kernel backlog to git-tracked JSONL.",
8
+ "should_trigger": true
9
+ },
10
+ {
11
+ "query": "Migrate our Beads issue store into the Forge kernel.",
12
+ "should_trigger": true
13
+ },
14
+ {
15
+ "query": "Dry-run the beads migration and show what would be imported.",
16
+ "should_trigger": true
17
+ },
18
+ {
19
+ "query": "Re-import the exported backlog JSONL into the kernel.",
20
+ "should_trigger": true
21
+ },
22
+ {
23
+ "query": "Migrate the database schema to add the new billing column.",
24
+ "should_trigger": false
25
+ },
26
+ {
27
+ "query": "Sync my feature branch with main before opening the PR.",
28
+ "should_trigger": false
29
+ },
30
+ {
31
+ "query": "Remember this decision for later.",
32
+ "should_trigger": false
33
+ }
34
+ ]
@@ -0,0 +1,41 @@
1
+ {
2
+ "skill": "portability",
3
+ "fixtures": "present",
4
+ "static": {
5
+ "token_cost": {
6
+ "desc_chars": 957,
7
+ "body_lines": 31,
8
+ "score": 50
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": 5,
27
+ "fixtures_best_hit": 5,
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": 85
41
+ }
@@ -14,6 +14,7 @@ description: >
14
14
  heavyweight EXTERNAL market/competitive report (paid Parallel AI); `plan` for the full plan
15
15
  stage (brainstorm + tasks); `dev` or `validate` to implement or scan rather than investigate.
16
16
  allowed-tools: Bash, Read, Write, Grep, Glob, WebSearch, WebFetch
17
+ terminal: true
17
18
  ---
18
19
 
19
20
  Investigate anything, from anywhere: verify a claim, search the web, find better options, pull
@@ -0,0 +1,41 @@
1
+ {
2
+ "skill": "research",
3
+ "fixtures": "present",
4
+ "static": {
5
+ "token_cost": {
6
+ "desc_chars": 1014,
7
+ "body_lines": 179,
8
+ "score": 33
9
+ },
10
+ "caps": {
11
+ "desc_within": true,
12
+ "body_within": true,
13
+ "score": 100
14
+ },
15
+ "description_quality": {
16
+ "has_trigger_cues": false,
17
+ "has_disambiguation_cues": true,
18
+ "adequate_length": true,
19
+ "score": 60
20
+ }
21
+ },
22
+ "router_reachability": {
23
+ "has_curated_rule": true,
24
+ "router_exempt": false,
25
+ "fixtures": "present",
26
+ "fixtures_total": 5,
27
+ "fixtures_best_hit": 2,
28
+ "reachable": true,
29
+ "keyword_alignment": 0.4
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": 60
41
+ }
@@ -13,12 +13,18 @@ description: >
13
13
  closing issues), ship (pushes the branch + opens the PR), validate (PRE-PR local
14
14
  type/lint/test/security), and sonarcloud / sonarcloud-analysis (only QUERY SonarCloud data).
15
15
  allowed-tools: Bash, Read, Edit, Grep, Glob
16
+ next: verify
17
+ terminal: false
18
+ handoffs:
19
+ - shepherd
16
20
  ---
17
21
 
18
22
  Process ALL pull request issues including GitHub Actions failures, review-agent inline comments (Greptile, CodeRabbit, Qodo, or human reviewers), SonarCloud analysis, and other CI/CD checks.
19
23
 
20
24
  # Review
21
25
 
26
+ > **Chain (HARD-GATE):** the successor depends on the change classification (source of truth: lib/workflow/stages.js) — Critical → `verify` (post-merge health check); Standard ENDS at `review`. `verify` is the default/critical-path next. While the PR is still open you may hand off to `shepherd` to watch checks toward merge. `review` never merges.
27
+
22
28
  This skill handles ALL issues that arise after creating a pull request.
23
29
 
24
30
  ## Usage
@@ -0,0 +1,41 @@
1
+ {
2
+ "skill": "review",
3
+ "fixtures": "present",
4
+ "static": {
5
+ "token_cost": {
6
+ "desc_chars": 988,
7
+ "body_lines": 476,
8
+ "score": 4
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": 5,
27
+ "fixtures_best_hit": 3,
28
+ "reachable": true,
29
+ "keyword_alignment": 0.6
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": 71
41
+ }
@@ -13,6 +13,7 @@ description: >
13
13
  (shepherd), the post-merge CI health check on master (verify), pushing a branch or opening a
14
14
  PR (ship), or ordinary issue status/field edits (issue-basics).
15
15
  allowed-tools: Bash, Read, Edit, Grep, Glob
16
+ terminal: true
16
17
  ---
17
18
 
18
19
  Comprehensive rollback system with multiple methods and automatic USER content preservation.
@@ -0,0 +1,41 @@
1
+ {
2
+ "skill": "rollback",
3
+ "fixtures": "present",
4
+ "static": {
5
+ "token_cost": {
6
+ "desc_chars": 965,
7
+ "body_lines": 95,
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": 1,
28
+ "reachable": true,
29
+ "keyword_alignment": 0.17
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
+ }
@@ -0,0 +1,91 @@
1
+ ---
2
+ name: setup
3
+ description: >
4
+ Forge install & setup lifecycle. `forge setup` interactively configures Forge for your
5
+ coding agents; `forge init [--profile minimal|standard|full]` writes the
6
+ adoption config in a fresh repo; `forge doctor` reports whether the kernel DB is on a
7
+ cloud/network path; `forge upgrade [--dry-run]` previews + self-heals upgrade readiness;
8
+ `forge hooks install --global` installs native hooks; `forge reset --soft|--hard --force`
9
+ and `forge reinstall --force` undo/redo the install; `forge recommend` lists suggested
10
+ tools. Use when the user says "install/set up forge", "init forge", "adoption profile",
11
+ "forge doctor", "upgrade forge", "install the hooks globally", or "reset/reinstall forge".
12
+ Footguns: setup is interactive — pass `--yes` in automation; `doctor` only checks the
13
+ kernel-DB filesystem class, NOT general health; `upgrade` self-heals Forge state, NOT the
14
+ npm package; reset/reinstall need `--force`. NOT toggling a gate/rail (gates), NOT
15
+ orienting in a set-up repo (status), NOT installing project deps (dev).
16
+ allowed-tools: Bash, Read, Grep, Glob
17
+ terminal: true
18
+ ---
19
+
20
+ Getting Forge installed, configured, upgraded, and diagnosed in a repo. These are the bootstrap and maintenance commands — distinct from the everyday workflow stages.
21
+
22
+ # Install & configure
23
+
24
+ ```bash
25
+ forge setup # interactive agent configuration (Claude/Cursor/Codex …)
26
+ forge setup --yes # non-interactive: accept defaults (use this in automation)
27
+ forge setup --agents claude,cursor --skip-external # target specific harnesses, skip service prompts
28
+ forge setup --path <dir> --dry-run # preview against another dir, write nothing
29
+ ```
30
+
31
+ `forge setup` is **interactive by default**. In any automated/agent context pass `--yes` (or `--non-interactive`) so it never blocks on a prompt.
32
+
33
+ # Initialize a fresh repo
34
+
35
+ ```bash
36
+ forge init --minimal # shortcut for --profile minimal --yes
37
+ forge init --profile standard --harness claude,cursor
38
+ forge init --classification standard --dry-run # preview the adoption config
39
+ ```
40
+
41
+ `forge init` writes the Forge adoption config (`.forge/config.yaml`). The profile picks how much enforcement ships on: `minimal` (rails off) → `standard` → `full`. This configures the workflow; toggling an individual gate afterward is the **gates** skill.
42
+
43
+ # Diagnose
44
+
45
+ ```bash
46
+ forge doctor # is the kernel DB on a cloud-synced / network path? (reliability signal)
47
+ forge doctor --json # machine-readable
48
+ ```
49
+
50
+ `forge doctor` is **narrow**: it reports the filesystem class of the Forge kernel database path (local / cloud-synced / network) so you can catch the reliability footgun of running the DB on OneDrive/Dropbox/a network share. It is **not** a general health check.
51
+
52
+ # Upgrade readiness
53
+
54
+ ```bash
55
+ forge upgrade --dry-run # preview the planned self-heal, change nothing
56
+ forge upgrade # apply safe self-heal steps to make the repo upgrade-ready
57
+ ```
58
+
59
+ `forge upgrade` previews and applies **safe self-heal** steps for Forge's own state. It does **not** update the installed npm package — use your package manager for that.
60
+
61
+ # Global hooks
62
+
63
+ ```bash
64
+ forge hooks install --global # install native hooks for all harnesses
65
+ forge hooks install --global --harness codex # scope to one harness (codex|hermes|all)
66
+ forge hooks install --global --dry-run # preview
67
+ ```
68
+
69
+ `--global` is the required consent flag — it opts you into installing hooks at the user level. (The other `forge hooks` subcommands — `session-start`, `inbox-pickup`, `shepherd-events`, `memory-recall`, `capture` — are machine-facing hook emitters the harness calls, not things you run by hand.)
70
+
71
+ # Undo / redo the install
72
+
73
+ ```bash
74
+ forge reset --soft --force # remove .forge/ config only (keeps commands, rules, agents)
75
+ forge reset --hard --force # remove ALL forge-managed files (keeps user-created files)
76
+ forge reinstall --force # remove + re-run default setup in one step
77
+ ```
78
+
79
+ `reset` and `reinstall` are destructive, so `--force` is required. `reset` with no `--soft`/`--hard` just prints usage.
80
+
81
+ # Recommend tooling
82
+
83
+ ```bash
84
+ forge recommend # suggest tools/integrations for the current project
85
+ ```
86
+
87
+ ## Boundaries
88
+
89
+ - Toggling a single gate/rail (e.g. TDD, kernel-tracking) is **gates** — `init` *writes* the initial config; `gates` *flips* one afterward.
90
+ - "Where am I / how is forge set up" in an already-configured repo is **status** / **kernel**, not setup.
91
+ - Installing project dependencies (`bun install`) is **dev**, not `forge setup`.
@@ -0,0 +1,42 @@
1
+ [
2
+ {
3
+ "query": "Install Forge into this repo and configure it for Claude and Cursor.",
4
+ "should_trigger": true
5
+ },
6
+ {
7
+ "query": "Initialize forge in this fresh repository with the minimal adoption profile.",
8
+ "should_trigger": true
9
+ },
10
+ {
11
+ "query": "Run forge doctor — is the kernel database on a cloud-synced path?",
12
+ "should_trigger": true
13
+ },
14
+ {
15
+ "query": "Upgrade forge and self-heal anything unsafe first.",
16
+ "should_trigger": true
17
+ },
18
+ {
19
+ "query": "Install the Forge native hooks globally for Codex.",
20
+ "should_trigger": true
21
+ },
22
+ {
23
+ "query": "Undo the forge install — reset this repo's forge files.",
24
+ "should_trigger": true
25
+ },
26
+ {
27
+ "query": "Disable the TDD gate, it's blocking my commit.",
28
+ "should_trigger": false
29
+ },
30
+ {
31
+ "query": "Set up the database schema for the new billing feature.",
32
+ "should_trigger": false
33
+ },
34
+ {
35
+ "query": "Upgrade the eslint dependency to the latest version.",
36
+ "should_trigger": false
37
+ },
38
+ {
39
+ "query": "Install the project dependencies with bun install.",
40
+ "should_trigger": false
41
+ }
42
+ ]
@@ -0,0 +1,41 @@
1
+ {
2
+ "skill": "setup",
3
+ "fixtures": "present",
4
+ "static": {
5
+ "token_cost": {
6
+ "desc_chars": 1021,
7
+ "body_lines": 74,
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,66 +1,106 @@
1
1
  ---
2
2
  name: shepherd
3
3
  description: >
4
- Monitor an already-reviewed OPEN pull request toward merge: read the CI/check rollup and the
5
- branch-protection required-check set, take at most one idempotent action (re-run a flaky
6
- required check, or post a status reply to a thread), then declare MERGE_READY, PENDING, or
7
- escalate. Use when the user says "is PR #123 ready to merge yet?", "poll/watch the checks on
8
- my PR", "the required CI job is flaky — kick off a re-run", "keep an eye on this PR until
9
- it's green", "babysit the checks after /review", "shepherd PR 45", or "monitor the PR toward
10
- merge (rebase if behind, --auto-rebase)". NEVER merges (the human merges in the GitHub UI),
11
- edits code, or resolves review threads. Do NOT use to fix or reply-and-resolve PR feedback
12
- from Greptile/CodeRabbit/SonarCloud that is `review`; nor to open/push the PR that is
13
- `ship`; nor for the post-merge "CI green on master + close issues" check that is `verify`;
14
- nor for a general "where am I / what's in flight" report — that is `status`.
4
+ Own open PRs to merge-readiness autonomously. Forge provides a singleton
5
+ shepherd daemon start it with `forge shepherd daemon` that then watches every
6
+ open PR, converges CI check state into kernel verdicts, re-runs flaky required
7
+ checks, reaps orphan watchers, and self-retires when no PRs remain; one-shot
8
+ passes (forge shepherd <pr>) exist for a single bounded check. Use when a PR was
9
+ just opened or shipped; when a session starts with open PRs (start the daemon in
10
+ a background shell the singleton lease makes a duplicate start a safe no-op);
11
+ when the user asks "why isn't my PR merging", "what's
12
+ blocking the PR", "is the PR ready", "did a check fail / go red"; when asked to
13
+ "keep watching / keep an eye on / babysit my PRs"; or to read PR verdicts
14
+ (forge shepherd <pr> --pull --json, forge shepherd events). NEVER merges and
15
+ never resolves review threads — fixing review feedback is `review`; opening the
16
+ PR is `ship`; post-merge health is `verify`; general orientation is `status`.
15
17
  allowed-tools: Bash, Read, Grep, Glob
18
+ terminal: true
19
+ handoffs:
20
+ - review
16
21
  ---
17
22
 
18
- Run one bounded monitor pass over a pull request: read CI and check state, take at most one idempotent action, then hand off. Never merges and never resolves review threads.
23
+ Forge owns your open PRs. A singleton daemon converges every open PR toward merge-readiness; you read its verdicts and only step in on escalations. Never merges, never resolves review threads.
19
24
 
20
25
  # Shepherd
21
26
 
22
- `shepherd` is a **utility command, not a workflow stage.** It automates the polling / rerun / escalation loop that today is done by hand after `/review`. It does **not** replace `/review` (which still owns semantic review and its stage transition) and does **not** perform the pre-merge doc gate (embedded in `/ship` and `/review`).
27
+ `shepherd` is the PR-ownership utility, not a workflow stage. It has two modes over the **single `forge shepherd` verb**:
23
28
 
24
- ## Usage
29
+ - **Daemon (default ownership):** `forge shepherd daemon` is a machine-wide singleton for this repo. It heartbeats and converges the whole PR world every ~60s — self-registering hand-opened PRs, restarting killed watchers, reaping verified orphans, converging CI check state into kernel verdicts, retiring merged/closed PRs — then self-retires (releases the lease, kills its children, exits) once no PRs remain open. You do NOT poll by hand; the daemon does.
30
+ - **One-shot pass:** `forge shepherd <pr>` reads one PR's state, takes at most one idempotent Tier-A action, and exits. Use it for a point-in-time question about a single PR.
31
+
32
+ ## Which mode? (decision rule)
33
+
34
+ - User asks about **one PR, right now** ("is #212 ready?", "why is this blocked?") → **one-shot** (`forge shepherd <pr> --pull`).
35
+ - Anything **ongoing** — "keep", "until it merges", "watch", "babysit", multiple PRs, or a session that starts with PRs already open → **ensure the daemon is running**.
36
+
37
+ ## Session-start ritual
38
+
39
+ When a session starts and the repo has open PRs, ensure the daemon is running:
25
40
 
26
41
  ```bash
27
- forge shepherd <pr-number>
28
- forge shepherd <pr-number> --auto-rebase # opt-in, default OFF
42
+ forge shepherd daemon # start it in the HARNESS BACKGROUND SHELL
29
43
  ```
30
44
 
31
- ## Bounded-pass model (one pass = one invocation)
45
+ The daemon is a **repo singleton** guarded by an O_EXCL lease, so you do NOT need a liveness check first — a second start when one is already running simply exits (the lease is already held). Start it in the harness background shell (Claude Code / Codex background-shell) so it is session-scoped and reaped with the session. NEVER launch a detached spawn from the agent: the detached path is Forge's bare-CLI fallback only. (Automatic per-command launch and a `forge prime` daemon-liveness line are planned follow-ups — W-S4c/W-S5 — not yet wired; until then you start the daemon explicitly as above.)
32
46
 
33
- Each `forge shepherd <pr>` invocation is **ONE discrete bounded pass**: it reads PR state, takes at most the allowed Tier-A action, then **exits**. It never sits in-process polling "until merge-ready."
47
+ ## Reading verdicts (the common case)
34
48
 
35
- This mirrors the project's documented ergonomic from `/review`, the pre-merge gate, and the Greptile process: **poll briefly, then stop and hand off.** Any pass that finds checks still pending exits as `PENDING`, and the next scheduled pass picks up where it left off.
49
+ ```bash
50
+ forge shepherd <pr> --pull --json # actionable payload: WHY blocked + exactly what to fix
51
+ forge shepherd <pr> --bundle --json # the COMPLETE read-only PR-state bundle
52
+ forge shepherd events <pr> --since <seq> # only the new events since sequence <seq>
53
+ ```
54
+
55
+ `--pull` is strictly read-only (dry-run pass: no rerun, no rebase, no merge, no thread resolution). It returns one bounded, actionable-only payload — `blockers[]`, classified `requiredChecks`, failed-check log `failures[]` (matrix-deduped), and every unresolved `reviewThreads[]` — so you get "everything blocking this PR + what to fix" in one call. Passing checks and satisfied policy are omitted.
36
56
 
37
- A `--watch` affordance, if you want one, lives in an **external scheduler** (e.g. cron or a `/loop`) that re-invokes the bounded pass on an interval with debounce (>= 60s between passes, cancel-in-progress). There is no in-process infinite loop.
57
+ ### Verdict vocabulary (collapsed, W-S1)
38
58
 
39
- ## What it never does
59
+ | Verdict | Meaning |
60
+ | --- | --- |
61
+ | `MERGE_READY` | Required checks green, branch up to date — hand off to a human to merge. |
62
+ | `PENDING` | A Tier-A action was taken, or checks are still running — await the next tick/pass. |
63
+ | `BLOCKED` | Something actionable blocks merge (failing/missing/skipped required check, conflict, behind, unresolved threads, changes requested). Read `blockers[]`. |
64
+ | `CI_DEAD_HEAD` | The head has no required checks running (e.g. an auto-update authored by `GITHUB_TOKEN` never re-triggered CI). Recovery is an **escalation, not an autonomous Tier-A rerun**: it needs a maintainer-provided `FORGE_PR_TOKEN` (contents + pull-requests + checks) to re-author the push so CI re-triggers. |
65
+ | `ESCALATE` | A Tier-C condition (conflict, unreadable required set, persistent failure, oscillation, budget exhaustion). Context is posted to the PR. |
66
+ | `HARD_STOP` | A permanent auth/scope failure retrying cannot fix — a human must widen token scope. |
40
67
 
41
- - **Never merges.** There is no merge action and no server-side auto-merge latch. The shepherd terminates at `MERGE_READY` and hands off to the human, who merges in the GitHub UI (mirroring the pre-merge gate's merge handoff).
42
- - **Never resolves review threads.** It may post a status **reply** to a thread (via the existing `.claude/scripts/review-resolve.sh reply` helper), but thread **resolution** is semantic and stays with `/review`.
68
+ ## Trigger scenario command
43
69
 
44
- ## Action ladder
70
+ | Situation | Command |
71
+ | --- | --- |
72
+ | PR just opened / shipped | ensure `forge shepherd daemon` running |
73
+ | Session starts, open PRs exist, daemon dead | `forge shepherd daemon` (background shell) |
74
+ | "Why isn't my PR merging / what's blocking it" | `forge shepherd <pr> --pull` |
75
+ | "Is the PR ready?" | `forge shepherd <pr> --pull` (read `MERGE_READY`) |
76
+ | "A check failed / went red" | `forge shepherd <pr> --pull --json` (read `failures[]`) |
77
+ | "Keep watching / babysit my PRs" | ensure `forge shepherd daemon` running |
78
+ | Read incremental deltas | `forge shepherd events <pr> --since <seq>` |
45
79
 
46
- - **Tier-A (autonomous, idempotent, reversible):** re-run a flaky **required** check via `gh run rerun --failed` (capped by a rerun budget). Post status replies to threads (reply only).
47
- - **Tier-B (opt-in per-flag, default OFF):** `--auto-rebase` rebases onto the base and force-pushes with lease. Preconditions: clean working tree, HEAD unchanged during the pass. A lease rejection is a **hard-stop + escalate** — the shepherd never re-arms the lease, because doing so would clobber the concurrent human push the lease exists to protect.
48
- - **Tier-C (human escalation):** merge conflicts, required-check failures a rerun did not fix, an unreadable required-check set, unknown mergeability, auth/scope failures, oscillation, and budget exhaustion all stop and escalate with context posted to the PR.
80
+ ## Boundaries (kept true of both modes)
49
81
 
50
- ## Merge-readiness gate
82
+ - **Never merges.** No merge action, no server-side auto-merge latch. Terminates at `MERGE_READY` and hands off — a human merges in the GitHub UI.
83
+ - **Never resolves review threads.** It refreshes a single **sticky** status comment; thread *resolution* is semantic and stays with `review`.
84
+ - **Action ladder.** Tier-A (autonomous, idempotent): re-run a flaky **required** check (rerun-budget capped); refresh the single **sticky** status comment — an *upsert*, never an append, so the ~60s daemon loop cannot post duplicate comments. Tier-B (opt-in, default OFF): `--auto-rebase` rebases onto base and force-pushes with lease — a lease rejection is a hard-stop, never re-armed. Tier-C: everything else escalates (incl. `CI_DEAD_HEAD` recovery, which needs the maintainer `FORGE_PR_TOKEN`).
85
+ - **Required-check gate.** `MERGE_READY` only when the branch-protection required set is *known* and all green; if protection is unreadable, it escalates rather than guessing.
86
+ - **HEAD-changed abort.** Before any mutating action it re-reads the head SHA and aborts if HEAD moved.
51
87
 
52
- Merge-ready is declared **only** when the branch-protection required-check set is **known** AND all of it is green AND the branch is not behind base. The required set is read from `gh api repos/{owner}/{repo}/branches/{base}/protection/required_status_checks`. If branch protection is unreadable (insufficient token scope, or the branch is not protected), the shepherd does **not** guess — it escalates with the readable rollup attached.
88
+ ## Adjacent skills
53
89
 
54
- ## Concurrency & safety
90
+ - Fixing review feedback (CodeRabbit/Greptile/human comments, resolving threads) → `review`.
91
+ - Opening or pushing the PR → `ship`.
92
+ - Post-merge health (CI green on main, close issues) → `verify`.
93
+ - "Where am I / what's in flight" orientation → `status`.
55
94
 
56
- - The advisory `shepherd:active` marker is **not** mutual exclusion. The real guard is a per-action HEAD-SHA re-read: before any mutating action the shepherd re-reads the head SHA, and if HEAD moved since the pass started it **aborts** the action.
57
- - Auth taxonomy: token expiry (401) pauses and surfaces; insufficient scope (403) is a permanent **hard-stop**; a secondary rate limit (403 + `Retry-After`) honors the delay and resumes on the next pass.
95
+ ## Kill-switches
58
96
 
59
- ## Per-harness behavior
97
+ ```bash
98
+ FORGE_SHEPHERD_DISABLE=1 # env: makes the shepherd trigger inert (once the auto-fire wiring lands, W-S4c)
99
+ forge gate disable rail.auto_shepherd # config gate honored by the trigger + ship/push arming
100
+ ```
60
101
 
61
- - **Claude Code / Codex:** invoke `forge shepherd <pr>` directly; an external scheduler may drive repeated bounded passes.
62
- - **Cursor:** manually-invoked only. Run `forge shepherd <pr>` from a terminal — there is no polling-loop affordance and no hook reliance on this surface.
102
+ Both leave the manual `forge shepherd` surface usable; they only stop the automatic daemon fire.
63
103
 
64
104
  ## State
65
105
 
66
- Progress is durable in GitHub: PR **comments** and **labels** plus `git`. There is no separate local state store.
106
+ Progress is durable in GitHub (PR comments, labels, `git`). The one local store is the per-PR journal under `.forge/pr-monitor/<repo>-<pr>/` (append-only `events.ndjson` + snapshot/consumer cursors) — the replay surface for `events --since`. The bounded one-shot pass keeps no separate local state.
@@ -1,30 +1,42 @@
1
1
  [
2
+ {
3
+ "query": "A PR just got shipped — keep watching it until every required check is green.",
4
+ "should_trigger": true
5
+ },
6
+ {
7
+ "query": "Why isn't my PR merging? Tell me exactly what's blocking the PR.",
8
+ "should_trigger": true
9
+ },
2
10
  {
3
11
  "query": "Is PR #212 ready to merge yet?",
4
12
  "should_trigger": true
5
13
  },
6
14
  {
7
- "query": "The lint check on my PR keeps failing intermittentlykick off a re-run of the failed jobs.",
15
+ "query": "My PR has been sitting for an hour with no merge poll the PR and tell me what's wrong.",
8
16
  "should_trigger": true
9
17
  },
10
18
  {
11
- "query": "Keep an eye on pull request 88 and tell me when all the required checks pass.",
19
+ "query": "One of the checks failed on my pull request kick off a re-run of the required job.",
12
20
  "should_trigger": true
13
21
  },
14
22
  {
15
- "query": "I just wrapped up /review on this PR babysit the checks and escalate if it isn't mergeable.",
23
+ "query": "Keep an eye on my open PRs and babysit them toward merge.",
16
24
  "should_trigger": true
17
25
  },
18
26
  {
19
- "query": "Shepherd PR 300 and rebase it onto master if it's behind.",
27
+ "query": "Start the shepherd daemon so my open PRs get watched.",
20
28
  "should_trigger": true
21
29
  },
22
30
  {
23
- "query": "Fix all the CodeRabbit and Greptile comments on my PR and resolve each review thread.",
24
- "should_trigger": false
31
+ "query": "Watch the pull request and let me know when it's mergeable.",
32
+ "should_trigger": true
33
+ },
34
+ {
35
+ "query": "What's the current PR verdict on #90 — read it back for me.",
36
+ "should_trigger": true
25
37
  },
26
38
  {
27
- "query": "The PR just merged to master confirm CI is green there and close the linked issue.",
39
+ "query": "Fix all the CodeRabbit and Greptile comments on my PR and resolve each review thread.",
28
40
  "should_trigger": false
29
41
  },
30
42
  {
@@ -32,11 +44,11 @@
32
44
  "should_trigger": false
33
45
  },
34
46
  {
35
- "query": "Where am I in the workflow and what work is still in flight right now?",
47
+ "query": "The PR merged to master run the post-merge health check and close the linked issue.",
36
48
  "should_trigger": false
37
49
  },
38
50
  {
39
- "query": "Show me the SonarCloud issues flagged on this PR.",
51
+ "query": "Where am I in the workflow and what work is still in flight right now?",
40
52
  "should_trigger": false
41
53
  }
42
54
  ]