forge-workflow 0.1.0-beta.3 → 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.
- package/AGENTS.md +1 -1
- package/bin/forge-cmd.js +1 -1
- package/bin/forge.js +5 -0
- package/docs/reference/COMMANDS.md +3 -1
- package/docs/reference/shepherd.md +72 -1
- package/lib/adapters/greptile-review-adapter.js +1 -1
- package/lib/adapters/pr-state-adapter.js +103 -8
- package/lib/agents-config.js +5 -0
- package/lib/commands/_issue.js +31 -46
- package/lib/commands/_manifest.js +1 -1
- package/lib/commands/_resolve-command-opts.js +36 -29
- package/lib/commands/claim.js +2 -4
- package/lib/commands/hooks.js +155 -8
- package/lib/commands/plan.js +23 -115
- package/lib/commands/prime.js +8 -1
- package/lib/commands/release.js +1 -2
- package/lib/commands/serve.js +5 -2
- package/lib/commands/setup.js +0 -1
- package/lib/commands/shepherd.js +36 -3
- package/lib/commands/skill.js +275 -0
- package/lib/commands/status.js +37 -32
- package/lib/commands/test.js +32 -0
- package/lib/commands/worktree.js +27 -1
- package/lib/core/runtime-graph.js +88 -14
- package/lib/forge-issues.js +13 -464
- package/lib/harness-capability-matrix.js +2 -2
- package/lib/hook-renderer.js +54 -12
- package/lib/issue-backend.js +42 -3
- package/lib/kernel/broker.js +28 -0
- package/lib/kernel/migrations.js +30 -2
- package/lib/kernel/schema.js +35 -0
- package/lib/kernel/sqlite-driver.js +150 -0
- package/lib/memory-recall.js +151 -0
- package/lib/orientation.js +303 -6
- package/lib/pr-bundle.js +6 -2
- package/lib/pr-monitor/reconcile-executor.js +659 -0
- package/lib/pr-monitor/reconcile-tick.js +138 -0
- package/lib/pr-monitor/reconcile.js +0 -0
- package/lib/pr-monitor/render-sticky.js +14 -0
- package/lib/pr-monitor/shepherd-lease.js +243 -0
- package/lib/pr-monitor/upsert-sticky.js +1 -1
- package/lib/pr-monitor/watch-lifecycle.js +1 -1
- package/lib/pr-pull.js +70 -15
- package/lib/project-memory.js +8 -0
- package/lib/rules-sync.js +4 -0
- package/lib/runtime-health.js +15 -46
- package/lib/skill-eval.js +750 -0
- package/lib/status/identity.js +46 -0
- package/lib/status/presenter.js +0 -35
- package/lib/status/snapshot.js +11 -16
- package/lib/upgrade-safety.js +8 -9
- package/lib/using-forge.js +315 -0
- package/lib/workflow/enforce-stage.js +5 -5
- package/lib/workflow/state-manager.js +23 -23
- package/package.json +1 -1
- package/rules/using-forge.md +24 -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/test.js +8 -1
- 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 +6 -0
- package/skills/review/evals/scorecard.json +41 -0
- package/skills/rollback/SKILL.md +1 -0
- 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 +76 -36
- package/skills/shepherd/evals/evals.json +21 -9
- package/skills/shepherd/evals/scorecard.json +41 -0
- package/skills/ship/SKILL.md +6 -0
- 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 +87 -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/commands/board.js +0 -64
- package/lib/status/beads-snapshot.js +0 -145
- package/scripts/forge-team/lib/dashboard.sh +0 -316
- package/scripts/forge-team/tests/dashboard.test.sh +0 -155
package/package.json
CHANGED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Always: before any response, if a Forge skill could apply, invoke it (or run forge skill for)"
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
globs: []
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Using Forge (skill dispatch — auto-trigger)
|
|
8
|
+
|
|
9
|
+
**Before ANY response or action** — including clarifying questions, exploring the
|
|
10
|
+
codebase, or checking files — if there is even a **1% chance** a Forge skill
|
|
11
|
+
applies to what you are doing, invoke that skill first. Then announce
|
|
12
|
+
`Using [skill] to [purpose]` and follow it.
|
|
13
|
+
|
|
14
|
+
- Not sure which skill fits? Run `forge skill for "<what you are about to do>"`
|
|
15
|
+
for the deterministic best-fit, or read the routing table in the dispatch skill.
|
|
16
|
+
- Common routes: build/scope a feature -> plan; implement a task -> dev; fix a
|
|
17
|
+
failing test -> dev (debug first); run checks/lint/tests -> validate; open a PR
|
|
18
|
+
-> ship; address review feedback -> review; where am I -> status.
|
|
19
|
+
|
|
20
|
+
This rule is a **thin pointer**. The full 1%-rule, red-flags table, subagent
|
|
21
|
+
escape hatch, and routing table live in the **`using-forge` dispatch skill**,
|
|
22
|
+
installed into your agent's own skill surface by `forge setup` (for Cursor:
|
|
23
|
+
`.cursor/skills/using-forge/SKILL.md`) — invoke it by name, or run
|
|
24
|
+
`forge skill for "<situation>"`. Do not duplicate that policy here.
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
# Subcommands:
|
|
5
5
|
# workload Show team workload by developer
|
|
6
6
|
# epic Epic progress rollup
|
|
7
|
-
# dashboard Team health dashboard
|
|
8
7
|
# add Add developer to team map
|
|
9
8
|
# verify Check 1:1 Beads<>GitHub enforcement
|
|
10
9
|
# sync Manual GitHub<>Beads sync
|
|
@@ -22,7 +21,6 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
22
21
|
[[ -f "$SCRIPT_DIR/lib/identity.sh" ]] && source "$SCRIPT_DIR/lib/identity.sh"
|
|
23
22
|
[[ -f "$SCRIPT_DIR/lib/workload.sh" ]] && source "$SCRIPT_DIR/lib/workload.sh"
|
|
24
23
|
[[ -f "$SCRIPT_DIR/lib/epic.sh" ]] && source "$SCRIPT_DIR/lib/epic.sh"
|
|
25
|
-
[[ -f "$SCRIPT_DIR/lib/dashboard.sh" ]] && source "$SCRIPT_DIR/lib/dashboard.sh"
|
|
26
24
|
[[ -f "$SCRIPT_DIR/lib/hooks.sh" ]] && source "$SCRIPT_DIR/lib/hooks.sh"
|
|
27
25
|
[[ -f "$SCRIPT_DIR/lib/verify.sh" ]] && source "$SCRIPT_DIR/lib/verify.sh"
|
|
28
26
|
[[ -f "$SCRIPT_DIR/lib/claim.sh" ]] && source "$SCRIPT_DIR/lib/claim.sh"
|
|
@@ -34,7 +32,6 @@ FORGE_SCRIPTS="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
|
34
32
|
# ── Stub implementations ──
|
|
35
33
|
# cmd_workload provided by lib/workload.sh
|
|
36
34
|
# cmd_epic provided by lib/epic.sh
|
|
37
|
-
# cmd_dashboard provided by lib/dashboard.sh
|
|
38
35
|
cmd_add() { auto_detect_identity "$@"; }
|
|
39
36
|
# cmd_verify provided by lib/verify.sh
|
|
40
37
|
cmd_sync() { forge_team_sync "$@"; }
|
|
@@ -47,7 +44,6 @@ Usage: forge team <subcommand> [args...]
|
|
|
47
44
|
Subcommands:
|
|
48
45
|
workload [--developer=<user>] [--me] Show team workload
|
|
49
46
|
epic <issue-id> Epic progress rollup
|
|
50
|
-
dashboard Team health dashboard
|
|
51
47
|
add [--github=<user>] Add developer to team map
|
|
52
48
|
verify Check 1:1 Beads<>GitHub sync
|
|
53
49
|
sync Manual GitHub<>Beads sync
|
|
@@ -69,7 +65,6 @@ main() {
|
|
|
69
65
|
case "$subcommand" in
|
|
70
66
|
workload) cmd_workload "$@" ;;
|
|
71
67
|
epic) cmd_epic "$@" ;;
|
|
72
|
-
dashboard) cmd_dashboard "$@" ;;
|
|
73
68
|
add) cmd_add "$@" ;;
|
|
74
69
|
verify) cmd_verify "$@" ;;
|
|
75
70
|
sync) cmd_sync "$@" ;;
|
|
@@ -60,7 +60,7 @@ assert_output_contains "unknown subcommand shows error" "unknown subcommand" bas
|
|
|
60
60
|
# Test 4: Each stub subcommand is reachable (exits 0)
|
|
61
61
|
echo ""
|
|
62
62
|
echo "-- stub subcommands reachable --"
|
|
63
|
-
for cmd in workload epic
|
|
63
|
+
for cmd in workload epic add verify sync claim; do
|
|
64
64
|
assert_exit "$cmd exits 0" 0 bash "$DISPATCHER" "$cmd"
|
|
65
65
|
assert_output_contains "$cmd outputs stub message" "not implemented" bash "$DISPATCHER" "$cmd"
|
|
66
66
|
done
|
|
@@ -17,7 +17,6 @@ assert_contains_file() {
|
|
|
17
17
|
echo "── /status integration ──"
|
|
18
18
|
STATUS="$SCRIPT_DIR/.claude/commands/status.md"
|
|
19
19
|
assert_contains_file "status calls workload --me" "forge-team.*workload.*--me" "$STATUS"
|
|
20
|
-
assert_contains_file "status calls dashboard" "forge-team.*dashboard" "$STATUS"
|
|
21
20
|
|
|
22
21
|
echo ""
|
|
23
22
|
echo "── /plan integration ──"
|
package/scripts/test.js
CHANGED
|
@@ -156,6 +156,8 @@ function isKnownTargetablePath(file) {
|
|
|
156
156
|
|
|
157
157
|
if (file === 'README.md'
|
|
158
158
|
|| file === 'bin/forge.js'
|
|
159
|
+
|| file === 'bin/forge-cmd.js'
|
|
160
|
+
|| file === 'bin/forge-preflight.js'
|
|
159
161
|
|| file === 'QUICKSTART.md'
|
|
160
162
|
|| file === 'CHANGELOG.md'
|
|
161
163
|
|| file === 'AGENTS.md'
|
|
@@ -166,7 +168,12 @@ function isKnownTargetablePath(file) {
|
|
|
166
168
|
|| file.startsWith('docs/guides/')
|
|
167
169
|
|| file.startsWith('docs/plans/')
|
|
168
170
|
|| file.startsWith('docs/reference/')
|
|
169
|
-
|| file.startsWith('docs/work/')
|
|
171
|
+
|| file.startsWith('docs/work/')
|
|
172
|
+
// Skill sources + their committed mirror map to the skill suite (see
|
|
173
|
+
// SKILL_TEST_TARGETS in lib/commands/test.js); a skills-only PR stays on the
|
|
174
|
+
// targeted lane instead of the full suite.
|
|
175
|
+
|| file.startsWith('skills/')
|
|
176
|
+
|| file.startsWith('.agents/skills/')) {
|
|
170
177
|
return true;
|
|
171
178
|
}
|
|
172
179
|
|
|
@@ -14,10 +14,14 @@ description: >
|
|
|
14
14
|
and NOT for read-only selecting or ranking the next ready issue without claiming (that is
|
|
15
15
|
triage-ready).
|
|
16
16
|
allowed-tools: Read, Bash(forge:*)
|
|
17
|
+
next: dev
|
|
18
|
+
terminal: false
|
|
17
19
|
---
|
|
18
20
|
|
|
19
21
|
# Claim safety — claim, then prove you own the lease
|
|
20
22
|
|
|
23
|
+
> **Chain:** once you have PROVEN the lease (`forge issue owns <id>` exits 0), continue to `dev` to work the issue (`smith` proceeds into plan/dev after this proof). Usable standalone whenever ownership is in question.
|
|
24
|
+
|
|
21
25
|
Claiming is not owning. The Forge kernel keys a claim's idempotency on
|
|
22
26
|
`claim.create:<issue_id>:<actor>`, so a **same-key duplicate replay returns
|
|
23
27
|
`ok:true`** echoing the *current* call's `claim_id`. A genuine cross-actor
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skill": "claim-safety",
|
|
3
|
+
"fixtures": "present",
|
|
4
|
+
"static": {
|
|
5
|
+
"token_cost": {
|
|
6
|
+
"desc_chars": 995,
|
|
7
|
+
"body_lines": 88,
|
|
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": 2,
|
|
28
|
+
"reachable": true,
|
|
29
|
+
"keyword_alignment": 0.33
|
|
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,83 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"description": "Command -> owning-skill coverage map (plan 2026-07-20-next-phase-plan.md §3.3). Every registered user-facing command MUST map to an existing skill OR carry an explicit { exempt: <reason> }. Enforced by the coverage gate (lib/skill-eval.js evaluateCoverage, surfaced by `forge skill coverage`/`forge skill scores`, gated in test/skill-eval.test.js). Exempts reference the pending skill from plan §3.2 and are tightened as those skills land.",
|
|
4
|
+
"commands": {
|
|
5
|
+
"plan": "plan",
|
|
6
|
+
"dev": "dev",
|
|
7
|
+
"validate": "validate",
|
|
8
|
+
"ship": "ship",
|
|
9
|
+
"shepherd": "shepherd",
|
|
10
|
+
"status": "status",
|
|
11
|
+
"prime": "status",
|
|
12
|
+
"orient": "hermes-forge",
|
|
13
|
+
"recap": "hermes-forge",
|
|
14
|
+
"remember": "memory",
|
|
15
|
+
"recall": "memory",
|
|
16
|
+
"memory": "memory",
|
|
17
|
+
"ready": "triage-ready",
|
|
18
|
+
"blocked": "triage-ready",
|
|
19
|
+
"claim": "claim-safety",
|
|
20
|
+
"claims": "claim-safety",
|
|
21
|
+
"issue": "issue-basics",
|
|
22
|
+
"issues": "issue-basics",
|
|
23
|
+
"create": "issue-basics",
|
|
24
|
+
"close": "issue-basics",
|
|
25
|
+
"comment": "issue-basics",
|
|
26
|
+
"show": "issue-basics",
|
|
27
|
+
"update": "issue-basics",
|
|
28
|
+
"list": "issue-basics",
|
|
29
|
+
"skill": "using-forge",
|
|
30
|
+
|
|
31
|
+
"worktree": "worktree",
|
|
32
|
+
"clean": "worktree",
|
|
33
|
+
"orphans": { "exempt": "full ownership (command-name routing + `forge issue orphans` guidance in the issue-basics body) pending — issue e1e33cf8; issue-basics does not yet document it, so mapping now would be a hollow claim" },
|
|
34
|
+
"rollback": "rollback",
|
|
35
|
+
"review": "review",
|
|
36
|
+
"verify": "verify",
|
|
37
|
+
"check": { "exempt": "legacy alias for `validate` (renamed in PR #50) — bin/forge-cmd.js VALID_COMMANDS only; owned by the `validate` skill" },
|
|
38
|
+
"docs": { "exempt": "bin/forge.js-direct; AGENTS.md/docs management — owning skill pending (coverage pass, plan §3.2)" },
|
|
39
|
+
"reset": "setup",
|
|
40
|
+
"reinstall": "setup",
|
|
41
|
+
|
|
42
|
+
"gate": "gates",
|
|
43
|
+
"control": "gates",
|
|
44
|
+
"doc-gate": "gates",
|
|
45
|
+
|
|
46
|
+
"adapter": { "exempt": "extensions skill pending (plan §3.2 B: new `extensions` skill)" },
|
|
47
|
+
"add": { "exempt": "extensions skill pending (plan §3.2 B: new `extensions` skill)" },
|
|
48
|
+
"new": { "exempt": "extensions skill pending (plan §3.2 B: new `extensions` skill)" },
|
|
49
|
+
"audit": { "exempt": "extensions skill pending (plan §3.2 B: new `extensions` skill)" },
|
|
50
|
+
"role": { "exempt": "extensions skill pending — role/skill binding (plan §3.2 B)" },
|
|
51
|
+
|
|
52
|
+
"export": "portability",
|
|
53
|
+
"migrate": "portability",
|
|
54
|
+
"sync": { "exempt": "cloud-native external-platform sync (ADR-0004); a local no-op with no value until a server backend is configured — skill deferred (issue 666f4b4c)" },
|
|
55
|
+
|
|
56
|
+
"inbox": { "exempt": "team skill pending (plan §3.2 B: new `team` skill)" },
|
|
57
|
+
"serve": { "exempt": "team skill pending (plan §3.2 B: new `team` skill)" },
|
|
58
|
+
"team": { "exempt": "team skill pending (plan §3.2 B: new `team` skill)" },
|
|
59
|
+
|
|
60
|
+
"setup": "setup",
|
|
61
|
+
"init": "setup",
|
|
62
|
+
"upgrade": "setup",
|
|
63
|
+
"doctor": "setup",
|
|
64
|
+
"hooks": "setup",
|
|
65
|
+
"recommend": "setup",
|
|
66
|
+
|
|
67
|
+
"push": { "exempt": "ship skill push/preflight extension pending (plan §3.2 B)" },
|
|
68
|
+
"preflight": { "exempt": "ship skill push/preflight extension pending (plan §3.2 B)" },
|
|
69
|
+
"pr": { "exempt": "ship/shepherd PR-lifecycle extension pending (plan §3.2)" },
|
|
70
|
+
"merge": { "exempt": "ship/shepherd PR-lifecycle extension pending (plan §3.2)" },
|
|
71
|
+
|
|
72
|
+
"patch": { "exempt": "kernel skill fold pending (plan §3.2 C: fold into `kernel`)" },
|
|
73
|
+
"stage": { "exempt": "kernel skill fold pending (plan §3.2 C: fold into `kernel`)" },
|
|
74
|
+
"explain": { "exempt": "kernel skill fold pending (plan §3.2 C: fold into `kernel`)" },
|
|
75
|
+
"options": { "exempt": "kernel skill fold pending (plan §3.2 C: fold into `kernel`)" },
|
|
76
|
+
"insights": { "exempt": "kernel skill fold pending — kernel evidence inspection (plan §3.2 C)" },
|
|
77
|
+
|
|
78
|
+
"lint": { "exempt": "internal quality plumbing; skill assignment pending (coverage pass)" },
|
|
79
|
+
"release": { "exempt": "internal release plumbing; skill assignment pending (coverage pass)" },
|
|
80
|
+
"test": { "exempt": "internal test-runner plumbing; skill assignment pending (coverage pass)" },
|
|
81
|
+
"stale": { "exempt": "internal stale-detection plumbing; skill assignment pending (coverage pass)" }
|
|
82
|
+
}
|
|
83
|
+
}
|
package/skills/dev/SKILL.md
CHANGED
|
@@ -13,12 +13,16 @@ description: >
|
|
|
13
13
|
opening the PR (ship), for addressing PR review feedback (review), or for orchestrating
|
|
14
14
|
several stages / taking an issue end-to-end to a merged PR (smith).
|
|
15
15
|
allowed-tools: Bash, Read, Write, Edit, Grep, Glob
|
|
16
|
+
next: validate
|
|
17
|
+
terminal: false
|
|
16
18
|
---
|
|
17
19
|
|
|
18
20
|
Implement each task from the /plan task list using a subagent-driven loop: implementer → spec compliance reviewer → code quality reviewer per task.
|
|
19
21
|
|
|
20
22
|
# Dev
|
|
21
23
|
|
|
24
|
+
> **Chain (HARD-GATE):** the ONLY skill you invoke after `dev` is `validate`. Never open a PR straight from `dev`.
|
|
25
|
+
|
|
22
26
|
This skill reads the task list created by `/plan` and implements each task using a three-stage subagent loop. TDD is enforced inside each implementer subagent.
|
|
23
27
|
|
|
24
28
|
## Usage
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skill": "dev",
|
|
3
|
+
"fixtures": "present",
|
|
4
|
+
"static": {
|
|
5
|
+
"token_cost": {
|
|
6
|
+
"desc_chars": 962,
|
|
7
|
+
"body_lines": 328,
|
|
8
|
+
"score": 20
|
|
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": 2,
|
|
28
|
+
"reachable": true,
|
|
29
|
+
"keyword_alignment": 0.33
|
|
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": 76
|
|
41
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: gates
|
|
3
|
+
description: >
|
|
4
|
+
Toggle Forge's workflow gates and rails — strong-but-toggleable enforcement. `forge gate
|
|
5
|
+
enable|disable <gate-id>` flips `workflow.gates.<id>.enabled` in `.forge/config.yaml`; the
|
|
6
|
+
installed git hooks read resolved config at run time, so disabling a rail makes them
|
|
7
|
+
genuinely inert. `forge gate approve|reject <issue> <gate>` records durable human-gate
|
|
8
|
+
approval events; `forge gate status`/`check` query them; `forge control <id>
|
|
9
|
+
<mandatory|optional|permission>` sets tri-state DECLARED intent (writes the same `enabled`
|
|
10
|
+
field — no independent runtime enforcement). Use when the user says "disable the gate",
|
|
11
|
+
"turn off TDD enforcement", "the tdd intent rail is blocking me", "toggle or enable a
|
|
12
|
+
gate", "loosen enforcement", or "approve a human gate". Common default-ON toggleable rails:
|
|
13
|
+
`rail.tdd_intent`, `rail.kernel_tracking`, `rail.auto_shepherd` — e.g. `forge gate disable
|
|
14
|
+
rail.tdd_intent`. NOT for addressing PR review feedback (review), NOT the status snapshot
|
|
15
|
+
of work in flight (status).
|
|
16
|
+
allowed-tools: Bash, Read, Grep, Glob
|
|
17
|
+
terminal: true
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
Forge's gates and rails are **default-strong but toggleable**. The `gates` skill is how you flip one off (or back on), record a human-gate approval, and see enforcement state. The stored truth is one field — `workflow.gates.<id>.enabled` — and the installed hooks read the resolved config at run time, so a disabled rail is genuinely inert, not cosmetically off.
|
|
21
|
+
|
|
22
|
+
# Toggling gates and rails
|
|
23
|
+
|
|
24
|
+
## When to use
|
|
25
|
+
|
|
26
|
+
- "Disable the gate", "turn off TDD enforcement", "the tdd intent rail is blocking me".
|
|
27
|
+
- "Toggle / enable a gate", "loosen enforcement for this repo".
|
|
28
|
+
- "Approve a human gate" (record a durable approval event on an issue).
|
|
29
|
+
|
|
30
|
+
## Toggle a gate or rail (the enforcement switch)
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
forge gate disable <gate-id> # set workflow.gates.<id>.enabled = false in .forge/config.yaml
|
|
34
|
+
forge gate enable <gate-id> # set it back to true
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
An unknown gate id — or disabling a **locked** gate — errors **before** anything is written, never mid-run. Because the hooks resolve config at run time, the flip takes effect immediately with no reinstall.
|
|
38
|
+
|
|
39
|
+
### Common rails (default-ON, toggleable)
|
|
40
|
+
|
|
41
|
+
| Rail | What it enforces | Turn off with |
|
|
42
|
+
| --- | --- | --- |
|
|
43
|
+
| `rail.tdd_intent` | Pre-commit TDD gate (source changed ⇒ tests changed). The `minimal` adoption profile ships it off. | `forge gate disable rail.tdd_intent` |
|
|
44
|
+
| `rail.kernel_tracking` | "File every issue" — nothing discussed goes missing. | `forge gate disable rail.kernel_tracking` |
|
|
45
|
+
| `rail.auto_shepherd` | The autonomous PR-shepherd daemon fire. | `forge gate disable rail.auto_shepherd` |
|
|
46
|
+
|
|
47
|
+
The `gate.*` and `rail.*` id namespaces are disjoint, so `forge gate enable|disable` governs both through one flat surface.
|
|
48
|
+
|
|
49
|
+
## Human-gate approval events
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
forge gate approve <issue-id> <gate-id> # record a durable gate.approved event
|
|
53
|
+
forge gate reject <issue-id> <gate-id> # record gate.rejected
|
|
54
|
+
forge gate status <issue-id> # list recorded events for that issue (resume-safe)
|
|
55
|
+
forge gate check <issue-id> <gate-id> # exit 0 iff gate DISABLED or an approval exists on that issue
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
`check` is the reusable enforcement primitive a stage skill calls: it passes when the gate is disabled or an approval event has been recorded for that specific issue id (approvals are issue-scoped, so pass the same `<issue-id>` you approved against). Events are durable on the issue, so they survive a compaction or crash.
|
|
59
|
+
|
|
60
|
+
## Tri-state control (declared intent)
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
forge control <gate-id|rail-id> <mandatory|optional|permission>
|
|
64
|
+
forge control status [--json]
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
`forge control` sets the **declared intent** vocabulary and writes the **same** `enabled` field that `forge gate` writes — there is deliberately no parallel key. It is a view/intent layer: today no runtime consumer denies purely on a control flag (MCP/rules/skills are presence-only and refused). For actually turning enforcement off, use `forge gate disable`.
|
|
68
|
+
|
|
69
|
+
## The doc-update gate
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
forge gate doc <detect|check|init|...> # = forge doc-gate (run `forge doc-gate --help`)
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
The doc-update gate folds under this noun as `forge gate doc`; bare `forge doc-gate` stays as a back-compat alias.
|
|
76
|
+
|
|
77
|
+
## Adjacent skills
|
|
78
|
+
|
|
79
|
+
- Addressing PR review feedback / resolving threads → `review`.
|
|
80
|
+
- The snapshot of where the project stands and what's in flight → `status`.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"query": "Disable the tdd gate for this repo.",
|
|
4
|
+
"should_trigger": true
|
|
5
|
+
},
|
|
6
|
+
{
|
|
7
|
+
"query": "Turn off TDD enforcement — the tdd intent rail is blocking my commit.",
|
|
8
|
+
"should_trigger": true
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"query": "Toggle the kernel tracking rail off for now.",
|
|
12
|
+
"should_trigger": true
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"query": "Enable a gate that I disabled earlier and loosen enforcement.",
|
|
16
|
+
"should_trigger": true
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"query": "Approve the human gate on this issue so the stage can proceed.",
|
|
20
|
+
"should_trigger": true
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"query": "Disable the auto shepherd rail so no PR daemon fires.",
|
|
24
|
+
"should_trigger": true
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"query": "Address the CodeRabbit review feedback and resolve the threads.",
|
|
28
|
+
"should_trigger": false
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"query": "Where am I in the workflow and what work is in flight right now?",
|
|
32
|
+
"should_trigger": false
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"query": "Run the tests and lint before I push.",
|
|
36
|
+
"should_trigger": false
|
|
37
|
+
}
|
|
38
|
+
]
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skill": "gates",
|
|
3
|
+
"fixtures": "present",
|
|
4
|
+
"static": {
|
|
5
|
+
"token_cost": {
|
|
6
|
+
"desc_chars": 994,
|
|
7
|
+
"body_lines": 63,
|
|
8
|
+
"score": 45
|
|
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": 84
|
|
41
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skill": "hermes-forge",
|
|
3
|
+
"fixtures": "present",
|
|
4
|
+
"static": {
|
|
5
|
+
"token_cost": {
|
|
6
|
+
"desc_chars": 993,
|
|
7
|
+
"body_lines": 157,
|
|
8
|
+
"score": 36
|
|
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": 2,
|
|
28
|
+
"reachable": true,
|
|
29
|
+
"keyword_alignment": 0.33
|
|
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": 81
|
|
41
|
+
}
|
|
@@ -14,6 +14,7 @@ description: >
|
|
|
14
14
|
the plan->dev->validate->ship pipeline or open a PR (use smith or stage skills); does NOT
|
|
15
15
|
report the current stage or what's in flight (use status).
|
|
16
16
|
allowed-tools: Read, Bash(forge:*)
|
|
17
|
+
terminal: true
|
|
17
18
|
---
|
|
18
19
|
|
|
19
20
|
# Issue basics — the CRUD floor
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skill": "issue-basics",
|
|
3
|
+
"fixtures": "present",
|
|
4
|
+
"static": {
|
|
5
|
+
"token_cost": {
|
|
6
|
+
"desc_chars": 991,
|
|
7
|
+
"body_lines": 95,
|
|
8
|
+
"score": 42
|
|
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": 6,
|
|
27
|
+
"fixtures_best_hit": 0,
|
|
28
|
+
"reachable": false,
|
|
29
|
+
"keyword_alignment": 0
|
|
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": 63
|
|
41
|
+
}
|
package/skills/kernel/SKILL.md
CHANGED
|
@@ -14,6 +14,7 @@ description: >
|
|
|
14
14
|
merged PR under gates → `smith`; token-bounded state for the Hermes harness →
|
|
15
15
|
`hermes-forge`.
|
|
16
16
|
allowed-tools: Read, Bash(forge:*)
|
|
17
|
+
terminal: true
|
|
17
18
|
---
|
|
18
19
|
|
|
19
20
|
# Forge kernel surface
|
|
@@ -56,6 +57,43 @@ mutating it — a claim returning ok:true does not by itself prove ownership).
|
|
|
56
57
|
status → plan → dev → validate → ship → review → verify
|
|
57
58
|
```
|
|
58
59
|
|
|
60
|
+
### Chain map (each skill declares its successor)
|
|
61
|
+
|
|
62
|
+
Every skill carries chain metadata in its frontmatter (`next`, `terminal`,
|
|
63
|
+
`subskills`, `handoffs`); each workflow STAGE skill additionally carries a
|
|
64
|
+
HARD-GATE chain line in its body, so each stage announces the next one. The
|
|
65
|
+
linear ladder:
|
|
66
|
+
|
|
67
|
+
| Skill | `next` | `terminal` |
|
|
68
|
+
|-------|--------|-----------|
|
|
69
|
+
| `plan` | `dev` | `false` |
|
|
70
|
+
| `dev` | `validate` | `false` |
|
|
71
|
+
| `validate` | `ship` | `false` |
|
|
72
|
+
| `ship` | `review` | `false` |
|
|
73
|
+
| `review` | `verify` | `false` |
|
|
74
|
+
| `verify` | `ship` | `false` |
|
|
75
|
+
|
|
76
|
+
The `next` column is each stage's DEFAULT / critical-path successor (`plan`
|
|
77
|
+
composes `research`; `ship` and `review` also carry a `shepherd` handoff). The
|
|
78
|
+
actual successor after `ship`, `review`, and `verify` is classification-dependent
|
|
79
|
+
— see the note below. `verify`'s `next` (`ship`) is the `docs`-only pre-ship
|
|
80
|
+
reuse; in every other flow nothing follows `verify`.
|
|
81
|
+
|
|
82
|
+
Feeders into the chain: `triage-ready` → `claim-safety` → `dev` (rank the pick,
|
|
83
|
+
prove the live lease, then work it). `research` is standalone / callable
|
|
84
|
+
mid-workflow and returns to its CALLER (no forced `next`); it is also a `subskill`
|
|
85
|
+
of `plan`. The `smith` orchestrator composes the six stages (`subskills`).
|
|
86
|
+
Utility/terminal skills (`status`, `shepherd`, `kernel`, `issue-basics`, `memory`,
|
|
87
|
+
`rollback`, `research`, `sonarcloud`, `sonarcloud-analysis`,
|
|
88
|
+
`parallel-deep-research`, `using-forge`) declare no forward-stage `next`. Meta
|
|
89
|
+
skills (`hermes-forge`) are chain-exempt.
|
|
90
|
+
|
|
91
|
+
The stage `next` values above are the DEFAULT / critical-path successors. The
|
|
92
|
+
actual successor after `ship`, `review`, and `verify` is
|
|
93
|
+
classification-dependent — the authoritative matrix is `lib/workflow/stages.js`
|
|
94
|
+
(Simple/Hotfix/Refactor end at `ship`; Standard ends at `review`; Critical runs
|
|
95
|
+
through `verify`; the `docs` classification reuses `verify` → `ship`).
|
|
96
|
+
|
|
59
97
|
## Orchestrator super-skill
|
|
60
98
|
|
|
61
99
|
`smith` is the flagship: a thin orchestrator that COMPOSES the skills above into
|