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.
- package/AGENTS.md +14 -7
- package/CHANGELOG.md +43 -1
- package/README.md +6 -2
- package/bin/forge-cmd.js +21 -1
- package/bin/forge.js +16 -369
- package/docs/INDEX.md +1 -1
- package/docs/guides/BEADS_GITHUB_SYNC.md +2 -31
- package/docs/guides/MIGRATION.md +4 -4
- package/docs/guides/SETUP.md +16 -16
- package/docs/reference/COMMANDS.md +9 -4
- package/docs/reference/INSIGHTS_RECAP.md +9 -20
- package/docs/reference/RELEASE.md +5 -3
- package/docs/reference/TOOLCHAIN.md +8 -0
- package/docs/reference/protected-state-surfaces.md +4 -4
- package/docs/reference/shepherd.md +117 -17
- package/lefthook.yml +12 -0
- package/lib/activation/ensure-forge-home.js +33 -15
- package/lib/adapters/greptile-review-adapter.js +1 -1
- package/lib/adapters/pr-state-adapter.js +397 -100
- package/lib/agents-config.js +5 -0
- package/lib/audit-evidence.js +71 -110
- package/lib/capped-jsonl-log.js +236 -0
- package/lib/commands/_issue.js +31 -46
- package/lib/commands/_manifest.js +1 -1
- package/lib/commands/_registry.js +2 -2
- package/lib/commands/_resolve-command-opts.js +36 -29
- package/lib/commands/claim.js +2 -4
- package/lib/commands/clean.js +196 -32
- package/lib/commands/dev.js +4 -33
- package/lib/commands/hooks.js +358 -13
- package/lib/commands/insights.js +8 -3
- package/lib/commands/merge.js +600 -40
- package/lib/commands/plan.js +23 -115
- package/lib/commands/pr.js +1 -1
- package/lib/commands/preflight.js +11 -2
- package/lib/commands/prime.js +23 -3
- package/lib/commands/push.js +41 -51
- package/lib/commands/recall.js +60 -16
- package/lib/commands/recap.js +6 -1
- package/lib/commands/release.js +18 -4
- package/lib/commands/serve.js +5 -2
- package/lib/commands/setup.js +191 -95
- package/lib/commands/shepherd.js +49 -4
- package/lib/commands/ship.js +22 -23
- package/lib/commands/skill.js +383 -0
- package/lib/commands/status.js +54 -33
- package/lib/commands/test.js +56 -34
- package/lib/commands/worktree.js +247 -43
- package/lib/core/runtime-graph.js +89 -15
- package/lib/doc-assertions.js +297 -0
- package/lib/existing-tdd-gate.js +253 -0
- package/lib/forge-context.js +1 -4
- package/lib/forge-issues.js +64 -491
- package/lib/git-defaults.js +56 -0
- package/lib/harness-capability-matrix.js +5 -5
- package/lib/hook-renderer.js +147 -16
- package/lib/insights.js +96 -80
- package/lib/issue-backend.js +42 -3
- package/lib/kernel/backing-issue.js +14 -2
- package/lib/kernel/broker.js +44 -0
- package/lib/kernel/cli-broker-factory.js +12 -1
- package/lib/kernel/close-on-merge.js +154 -0
- package/lib/kernel/fs-class.js +42 -25
- package/lib/kernel/migrations.js +30 -2
- package/lib/kernel/schema.js +35 -0
- package/lib/kernel/sqlite-driver.js +292 -18
- package/lib/lefthook-wiring.js +21 -1
- package/lib/memory/router.js +16 -1
- package/lib/memory-digest.js +47 -15
- package/lib/memory-recall-events.js +145 -0
- package/lib/memory-recall.js +212 -0
- package/lib/merge-rules.js +8 -4
- package/lib/npm-publish-workflow.js +272 -0
- package/lib/orientation.js +371 -49
- package/lib/plugin-catalog.js +14 -4
- package/lib/pr-bundle.js +9 -6
- package/lib/pr-monitor/journal.js +18 -2
- package/lib/pr-monitor/reconcile-executor.js +842 -0
- package/lib/pr-monitor/reconcile-tick.js +138 -0
- package/lib/pr-monitor/reconcile.js +0 -0
- package/lib/pr-monitor/render-summary.js +196 -0
- package/lib/pr-monitor/shepherd-lease.js +252 -0
- package/lib/pr-monitor/watch-lifecycle.js +14 -2
- package/lib/pr-pull.js +98 -24
- package/lib/pr-shepherd.js +34 -8
- package/lib/preflight/gates.js +65 -18
- package/lib/preflight/runner.js +5 -0
- package/lib/project-memory.js +40 -0
- package/lib/protected-state-authority.js +305 -0
- package/lib/protected-state-surfaces.js +64 -44
- package/lib/release-readiness.js +51 -4
- package/lib/rules-sync.js +4 -0
- package/lib/runtime-health.js +15 -46
- package/lib/shell-utils.js +1 -1
- package/lib/skill-eval.js +750 -0
- package/lib/skills-sync.js +6 -3
- package/lib/smart-merge.js +28 -4
- package/lib/status/identity.js +46 -0
- package/lib/status/presenter.js +0 -35
- package/lib/status/snapshot.js +11 -16
- package/lib/symlink-utils.js +74 -26
- package/lib/upgrade-safety.js +47 -9
- package/lib/using-forge.js +328 -0
- package/lib/workflow/enforce-stage.js +5 -5
- package/lib/workflow/state-manager.js +23 -23
- package/package.json +6 -7
- package/rules/using-forge.md +24 -0
- package/scripts/doc-asserting-tests.js +158 -0
- package/scripts/forge-team/index.sh +0 -5
- package/scripts/forge-team/tests/dispatcher.test.sh +1 -1
- package/scripts/forge-team/tests/workflow-integration.test.sh +0 -1
- package/scripts/lib/behavioral-eval-runner.js +310 -0
- package/scripts/lib/behavioral-eval-runtime.js +456 -0
- package/scripts/lib/eval-evidence.js +328 -0
- package/scripts/lib/eval-runner.js +81 -41
- package/scripts/lib/immutable-eval-corpus.js +309 -0
- package/scripts/lib/promotion-evidence-loader.js +94 -0
- package/scripts/lib/promotion-scorecard.js +314 -0
- package/scripts/npm-release-receipt.js +134 -0
- package/scripts/process-tree.js +761 -0
- package/scripts/protected-state-check.js +47 -22
- package/scripts/run-command-eval.js +29 -1
- package/scripts/sync-d20-audit.js +172 -0
- package/scripts/test-full-suite.js +249 -37
- package/scripts/test.js +184 -44
- package/skills/claim-safety/SKILL.md +4 -0
- package/skills/claim-safety/evals/scorecard.json +41 -0
- package/skills/coverage.json +83 -0
- package/skills/dev/SKILL.md +4 -0
- package/skills/dev/evals/scorecard.json +41 -0
- package/skills/gates/SKILL.md +80 -0
- package/skills/gates/evals/evals.json +38 -0
- package/skills/gates/evals/scorecard.json +41 -0
- package/skills/hermes-forge/SKILL.md +1 -0
- package/skills/hermes-forge/evals/scorecard.json +41 -0
- package/skills/issue-basics/SKILL.md +1 -0
- package/skills/issue-basics/evals/scorecard.json +41 -0
- package/skills/kernel/SKILL.md +38 -0
- package/skills/kernel/evals/scorecard.json +41 -0
- package/skills/memory/SKILL.md +16 -1
- package/skills/memory/evals/scorecard.json +41 -0
- package/skills/parallel-deep-research/SKILL.md +1 -0
- package/skills/parallel-deep-research/evals/scorecard.json +41 -0
- package/skills/plan/SKILL.md +6 -0
- package/skills/plan/evals/scorecard.json +41 -0
- package/skills/portability/SKILL.md +47 -0
- package/skills/portability/evals/evals.json +34 -0
- package/skills/portability/evals/scorecard.json +41 -0
- package/skills/research/SKILL.md +1 -0
- package/skills/research/evals/scorecard.json +41 -0
- package/skills/review/SKILL.md +10 -11
- package/skills/review/evals/scorecard.json +41 -0
- package/skills/rollback/SKILL.md +5 -11
- package/skills/rollback/evals/scorecard.json +41 -0
- package/skills/setup/SKILL.md +91 -0
- package/skills/setup/evals/evals.json +42 -0
- package/skills/setup/evals/scorecard.json +41 -0
- package/skills/shepherd/SKILL.md +84 -38
- package/skills/shepherd/evals/evals.json +21 -9
- package/skills/shepherd/evals/scorecard.json +41 -0
- package/skills/ship/SKILL.md +10 -12
- package/skills/ship/evals/scorecard.json +41 -0
- package/skills/smith/SKILL.md +8 -0
- package/skills/smith/evals/scorecard.json +41 -0
- package/skills/sonarcloud/SKILL.md +1 -0
- package/skills/sonarcloud/evals/scorecard.json +41 -0
- package/skills/sonarcloud-analysis/SKILL.md +1 -0
- package/skills/sonarcloud-analysis/evals/scorecard.json +41 -0
- package/skills/status/SKILL.md +3 -0
- package/skills/status/evals/scorecard.json +41 -0
- package/skills/triage-ready/SKILL.md +2 -0
- package/skills/triage-ready/evals/scorecard.json +41 -0
- package/skills/using-forge/SKILL.md +104 -0
- package/skills/using-forge/evals/scorecard.json +41 -0
- package/skills/validate/SKILL.md +4 -0
- package/skills/validate/evals/scorecard.json +41 -0
- package/skills/verify/SKILL.md +4 -0
- package/skills/verify/evals/scorecard.json +41 -0
- package/skills/worktree/SKILL.md +92 -0
- package/skills/worktree/evals/evals.json +38 -0
- package/skills/worktree/evals/scorecard.json +41 -0
- package/lib/adapters/beads-issue-adapter.js +0 -127
- package/lib/beads-nudge.js +0 -91
- package/lib/beads-setup.js +0 -538
- package/lib/beads-sync-scaffold.js +0 -189
- package/lib/commands/board.js +0 -64
- package/lib/pat-setup.js +0 -207
- package/lib/pr-monitor/render-sticky.js +0 -192
- package/lib/pr-monitor/upsert-sticky.js +0 -169
- package/lib/status/beads-snapshot.js +0 -145
- package/scripts/beads-context.sh +0 -577
- package/scripts/beads-migrate-to-dolt.sh +0 -7
- package/scripts/beads-upgrade-smoke.sh +0 -284
- package/scripts/forge-team/lib/dashboard.sh +0 -316
- package/scripts/forge-team/tests/dashboard.test.sh +0 -155
- package/scripts/lib/beads-migrate-to-dolt.mjs +0 -503
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skill": "review",
|
|
3
|
+
"fixtures": "present",
|
|
4
|
+
"static": {
|
|
5
|
+
"token_cost": {
|
|
6
|
+
"desc_chars": 261,
|
|
7
|
+
"body_lines": 476,
|
|
8
|
+
"score": 40
|
|
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": 82
|
|
41
|
+
}
|
package/skills/rollback/SKILL.md
CHANGED
|
@@ -1,18 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: rollback
|
|
3
|
+
invocation: user
|
|
3
4
|
description: >
|
|
4
|
-
Safely
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
PR (git revert -m 1), restore individual files to a prior version, revert a commit range, or
|
|
8
|
-
dry-run/preview first. Use when the user says roll back, revert, undo, back out, or restore
|
|
9
|
-
— e.g. "undo the last commit", "undo that change, the approach was wrong", "back out PR
|
|
10
|
-
#123", "revert the merge commit", "restore src/auth.js to before my last commit", or when a
|
|
11
|
-
shipped/merged change broke something and must be pulled back. Do NOT use for: replying to
|
|
12
|
-
or fixing PR review feedback (review), monitoring an open PR's checks toward merge
|
|
13
|
-
(shepherd), the post-merge CI health check on master (verify), pushing a branch or opening a
|
|
14
|
-
PR (ship), or ordinary issue status/field edits (issue-basics).
|
|
5
|
+
Safely undo committed or shipped changes with non-destructive git revert or restore. Use
|
|
6
|
+
only when the user explicitly asks to roll back, revert, undo, back out, or restore; never
|
|
7
|
+
reset hard, force-push, or substitute for PR review, monitoring, or issue status work.
|
|
15
8
|
allowed-tools: Bash, Read, Edit, Grep, Glob
|
|
9
|
+
terminal: true
|
|
16
10
|
---
|
|
17
11
|
|
|
18
12
|
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": 266,
|
|
7
|
+
"body_lines": 95,
|
|
8
|
+
"score": 78
|
|
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": 93
|
|
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
|
+
}
|
package/skills/shepherd/SKILL.md
CHANGED
|
@@ -1,66 +1,112 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: shepherd
|
|
3
3
|
description: >
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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 (Forge automatically
|
|
10
|
+
wakes the singleton; the 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
|
-
|
|
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
|
|
27
|
+
`shepherd` is the PR-ownership utility, not a workflow stage. It has two modes over the **single `forge shepherd` verb**:
|
|
23
28
|
|
|
24
|
-
|
|
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.
|
|
25
31
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
forge shepherd <pr
|
|
29
|
-
|
|
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
|
+
## Automatic attachment
|
|
38
|
+
|
|
39
|
+
Forge wakes the singleton after a successful supported session start, every
|
|
40
|
+
successful push, and every successful non-dry-run ship. Push does not require a
|
|
41
|
+
locally resolved PR number; the daemon enumerates all open and draft PRs itself.
|
|
42
|
+
Ordinary commands do not launch it.
|
|
30
43
|
|
|
31
|
-
|
|
44
|
+
The daemon is a **repo singleton** guarded by an O_EXCL lease, so no liveness
|
|
45
|
+
check is needed first. Forge prefers a supplied harness background shell; its
|
|
46
|
+
bare-CLI detached fallback launches from the stable common repository root, not
|
|
47
|
+
the current disposable worktree. Agents never launch a detached spawn directly.
|
|
48
|
+
(A `forge prime` daemon-liveness line remains the separate W-S5 follow-up.)
|
|
32
49
|
|
|
33
|
-
|
|
50
|
+
## Reading verdicts (the common case)
|
|
34
51
|
|
|
35
|
-
|
|
52
|
+
```bash
|
|
53
|
+
forge shepherd <pr> --pull --json # actionable payload: WHY blocked + exactly what to fix
|
|
54
|
+
forge shepherd <pr> --bundle --json # the COMPLETE read-only PR-state bundle
|
|
55
|
+
forge shepherd events <pr> --since <seq> # only the new events since sequence <seq>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
`--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
59
|
|
|
37
|
-
|
|
60
|
+
### Verdict vocabulary (collapsed, W-S1)
|
|
38
61
|
|
|
39
|
-
|
|
62
|
+
| Verdict | Meaning |
|
|
63
|
+
| --- | --- |
|
|
64
|
+
| `MERGE_READY` | Required checks green, branch up to date — hand off to a human to merge. |
|
|
65
|
+
| `PENDING` | A Tier-A action was taken, or checks are still running — await the next tick/pass. |
|
|
66
|
+
| `BLOCKED` | Something actionable blocks merge (failing/missing/skipped required check, conflict, behind, unresolved threads, changes requested). Read `blockers[]`. |
|
|
67
|
+
| `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. |
|
|
68
|
+
| `ESCALATE` | A Tier-C condition (conflict, unreadable required set, persistent failure, oscillation, budget exhaustion). Context is posted to the PR. |
|
|
69
|
+
| `HARD_STOP` | A permanent auth/scope failure retrying cannot fix — a human must widen token scope. |
|
|
40
70
|
|
|
41
|
-
|
|
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`.
|
|
71
|
+
## Trigger scenario → command
|
|
43
72
|
|
|
44
|
-
|
|
73
|
+
| Situation | Command |
|
|
74
|
+
| --- | --- |
|
|
75
|
+
| PR just opened / shipped | automatic singleton wake; read with `forge shepherd <pr> --pull` |
|
|
76
|
+
| Session starts with open PRs | automatic singleton wake |
|
|
77
|
+
| "Why isn't my PR merging / what's blocking it" | `forge shepherd <pr> --pull` |
|
|
78
|
+
| "Is the PR ready?" | `forge shepherd <pr> --pull` (read `MERGE_READY`) |
|
|
79
|
+
| "A check failed / went red" | `forge shepherd <pr> --pull --json` (read `failures[]`) |
|
|
80
|
+
| "Keep watching / babysit my PRs" | ensure `forge shepherd daemon` running |
|
|
81
|
+
| Read incremental deltas | `forge shepherd events <pr> --since <seq>` |
|
|
45
82
|
|
|
46
|
-
|
|
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.
|
|
83
|
+
## Boundaries (kept — true of both modes)
|
|
49
84
|
|
|
50
|
-
|
|
85
|
+
- **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.
|
|
86
|
+
- **Never resolves review threads.** It refreshes a single **sticky** status comment; thread *resolution* is semantic and stays with `review`.
|
|
87
|
+
- **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`).
|
|
88
|
+
- **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.
|
|
89
|
+
- **HEAD-changed abort.** Before any mutating action it re-reads the head SHA and aborts if HEAD moved.
|
|
51
90
|
|
|
52
|
-
|
|
91
|
+
## Adjacent skills
|
|
53
92
|
|
|
54
|
-
|
|
93
|
+
- Fixing review feedback (CodeRabbit/Greptile/human comments, resolving threads) → `review`.
|
|
94
|
+
- Opening or pushing the PR → `ship`.
|
|
95
|
+
- Post-merge health (CI green on main, close issues) → `verify`.
|
|
96
|
+
- "Where am I / what's in flight" orientation → `status`.
|
|
55
97
|
|
|
56
|
-
|
|
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.
|
|
98
|
+
## Kill-switches
|
|
58
99
|
|
|
59
|
-
|
|
100
|
+
```bash
|
|
101
|
+
FORGE_SHEPHERD_DISABLE=1 # env: makes automatic firing inert
|
|
102
|
+
forge gate disable rail.auto_shepherd # config gate honored by every automatic seam
|
|
103
|
+
```
|
|
60
104
|
|
|
61
|
-
|
|
62
|
-
|
|
105
|
+
CI/test (`NODE_ENV=test`, `BUN_ENV=test`, `CI`, `GITHUB_ACTIONS`, or
|
|
106
|
+
`GITLAB_CI`), dry-run, uninitialized repositories, and disabled paths return
|
|
107
|
+
before lease, Kernel-state, or process work. All leave the manual
|
|
108
|
+
`forge shepherd` surface usable; they only stop automatic daemon fire.
|
|
63
109
|
|
|
64
110
|
## State
|
|
65
111
|
|
|
66
|
-
Progress is durable in GitHub
|
|
112
|
+
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
27
|
+
"query": "Start the shepherd daemon so my open PRs get watched.",
|
|
20
28
|
"should_trigger": true
|
|
21
29
|
},
|
|
22
30
|
{
|
|
23
|
-
"query": "
|
|
24
|
-
"should_trigger":
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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
|
]
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skill": "shepherd",
|
|
3
|
+
"fixtures": "present",
|
|
4
|
+
"static": {
|
|
5
|
+
"token_cost": {
|
|
6
|
+
"desc_chars": 987,
|
|
7
|
+
"body_lines": 92,
|
|
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": 9,
|
|
27
|
+
"fixtures_best_hit": 6,
|
|
28
|
+
"reachable": true,
|
|
29
|
+
"keyword_alignment": 0.67
|
|
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
|
+
}
|
package/skills/ship/SKILL.md
CHANGED
|
@@ -1,25 +1,23 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ship
|
|
3
|
+
invocation: user
|
|
3
4
|
description: >
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
want a PR on the board. Triggers: "ship it", "ship this branch", "open the PR", "push and
|
|
8
|
-
open a PR", "gh pr create", "checks passed, now cut the PR". Runs branch-freshness +
|
|
9
|
-
parallel-PR merge-sim checks, force-with-lease push, records the ship->review handoff, then
|
|
10
|
-
stops. One stage only; not for: the whole plan->dev->validate->ship->review pipeline or
|
|
11
|
-
drive-to-done (smith); type-check/lint/tests/security first (validate); addressing PR
|
|
12
|
-
comments or resolving Greptile/SonarCloud/CodeRabbit threads on an existing PR (review);
|
|
13
|
-
babysitting an open PR toward merge (shepherd); post-merge CI health check + closing issues
|
|
14
|
-
(verify); reverting an already-shipped change (rollback). If the PR already exists, this is
|
|
15
|
-
not the skill.
|
|
5
|
+
Push a validated feature branch and open its PR from the project's template, then stop for
|
|
6
|
+
manual merge. Use only when the user asks to ship or open the PR after validation; never
|
|
7
|
+
merges, auto-merges, reviews an existing PR, or replaces end-to-end Smith.
|
|
16
8
|
allowed-tools: Bash, Read, Edit, Grep, Glob
|
|
9
|
+
next: review
|
|
10
|
+
terminal: false
|
|
11
|
+
handoffs:
|
|
12
|
+
- shepherd
|
|
17
13
|
---
|
|
18
14
|
|
|
19
15
|
Push code and create a pull request with full context and documentation links.
|
|
20
16
|
|
|
21
17
|
# Ship
|
|
22
18
|
|
|
19
|
+
> **Chain (HARD-GATE):** the successor depends on the change classification (source of truth: lib/workflow/stages.js) — Standard → `review`; Critical → `review` → `verify`; Simple/Hotfix/Refactor/Docs END at `ship`. `review` is the default/critical-path next; `shepherd` may monitor the PR's checks. `ship` never merges.
|
|
20
|
+
|
|
23
21
|
This skill creates a PR after validation passes.
|
|
24
22
|
|
|
25
23
|
## Usage
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skill": "ship",
|
|
3
|
+
"fixtures": "present",
|
|
4
|
+
"static": {
|
|
5
|
+
"token_cost": {
|
|
6
|
+
"desc_chars": 254,
|
|
7
|
+
"body_lines": 237,
|
|
8
|
+
"score": 64
|
|
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": 89
|
|
41
|
+
}
|