@reddb-io/red-skills-dev 2.75.2
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/LICENSE +202 -0
- package/README.md +30 -0
- package/package.json +32 -0
- package/skills/engineering/README.md +36 -0
- package/skills/engineering/_report-runtime/WRAPPER.md +47 -0
- package/skills/engineering/afk/AGENT-PROMPT.md +295 -0
- package/skills/engineering/afk/SAFETY.md +103 -0
- package/skills/engineering/afk/SKILL.md +160 -0
- package/skills/engineering/afk/TROUBLESHOOTING.md +260 -0
- package/skills/engineering/afk/actions-lane.md +213 -0
- package/skills/engineering/afk/bin/README.md +29 -0
- package/skills/engineering/afk/bin/afk.mjs +51 -0
- package/skills/engineering/afk/defaults/cargo-pre-worktree.sh +37 -0
- package/skills/engineering/afk/defaults/envelope-post-attempt.sh +47 -0
- package/skills/engineering/afk/defaults/gradle-pre-worktree.sh +42 -0
- package/skills/engineering/afk/defaults/heartbeat-post-attempt.sh +43 -0
- package/skills/engineering/afk/defaults/validation-post-merge.sh +77 -0
- package/skills/engineering/afk/detectors/README.md +72 -0
- package/skills/engineering/afk/detectors/cargo.sh +27 -0
- package/skills/engineering/afk/detectors/gradle.sh +35 -0
- package/skills/engineering/afk/docs/BOOT-SWEEPS.md +81 -0
- package/skills/engineering/afk/docs/CONFIG.md +238 -0
- package/skills/engineering/afk/docs/ENVELOPE.md +177 -0
- package/skills/engineering/afk/docs/HANDOFF.md +70 -0
- package/skills/engineering/afk/docs/LIVENESS.md +56 -0
- package/skills/engineering/afk/docs/OPERATIONS.md +409 -0
- package/skills/engineering/afk/examples/only-mine.sh +32 -0
- package/skills/engineering/afk/examples/red-afk-attempt-action.yml +53 -0
- package/skills/engineering/afk/examples/rs-afk-attempt.yml +76 -0
- package/skills/engineering/afk/fleet.md +127 -0
- package/skills/engineering/afk/hooks/red-cargo +44 -0
- package/skills/engineering/afk/hooks/red-envelope +50 -0
- package/skills/engineering/afk/hooks/red-gradle +50 -0
- package/skills/engineering/afk/hooks/red-heartbeat +46 -0
- package/skills/engineering/afk/hooks/red-validation +79 -0
- package/skills/engineering/afk/monitor.md +170 -0
- package/skills/engineering/afk/runner-claude-minimax.md +71 -0
- package/skills/engineering/afk/runner-claude.md +67 -0
- package/skills/engineering/afk/runner-codex.md +138 -0
- package/skills/engineering/afk/runner-hermes.md +40 -0
- package/skills/engineering/afk/runner-opencode.md +142 -0
- package/skills/engineering/ask-red/SKILL.md +137 -0
- package/skills/engineering/audit-skills/SKILL.md +46 -0
- package/skills/engineering/code-review/SKILL.md +106 -0
- package/skills/engineering/context/SKILL.md +142 -0
- package/skills/engineering/curate/SKILL.md +133 -0
- package/skills/engineering/daily-review/SKILL.md +68 -0
- package/skills/engineering/dashboard/SKILL.md +44 -0
- package/skills/engineering/diagnose/SKILL.md +155 -0
- package/skills/engineering/diagnose/scripts/hitl-loop.template.sh +41 -0
- package/skills/engineering/go/SKILL.md +144 -0
- package/skills/engineering/go/TROUBLESHOOTING.md +81 -0
- package/skills/engineering/ground-truth/SKILL.md +84 -0
- package/skills/engineering/hitl/SKILL.md +171 -0
- package/skills/engineering/hitl/TROUBLESHOOTING.md +76 -0
- package/skills/engineering/implement/SKILL.md +69 -0
- package/skills/engineering/improve-codebase-architecture/DEEPENING.md +37 -0
- package/skills/engineering/improve-codebase-architecture/INTERFACE-DESIGN.md +44 -0
- package/skills/engineering/improve-codebase-architecture/LANGUAGE.md +53 -0
- package/skills/engineering/improve-codebase-architecture/SKILL.md +81 -0
- package/skills/engineering/model-tier-policy/SKILL.md +83 -0
- package/skills/engineering/prototype/LOGIC.md +79 -0
- package/skills/engineering/prototype/SKILL.md +30 -0
- package/skills/engineering/prototype/UI.md +112 -0
- package/skills/engineering/red-doctor/APPLY.md +35 -0
- package/skills/engineering/red-doctor/SKILL.md +172 -0
- package/skills/engineering/red-gains/SKILL.md +49 -0
- package/skills/engineering/red-setup/INTERVIEW.md +266 -0
- package/skills/engineering/red-setup/ISSUE-SWEEP.md +18 -0
- package/skills/engineering/red-setup/REFERENCE.md +35 -0
- package/skills/engineering/red-setup/SKILL.md +58 -0
- package/skills/engineering/red-setup/WORKFLOWS.md +74 -0
- package/skills/engineering/red-setup/WRITE-CONTRACT.md +151 -0
- package/skills/engineering/red-setup/config-template.yaml +174 -0
- package/skills/engineering/red-setup/domain.md +52 -0
- package/skills/engineering/red-setup/issue-tracker-github.md +88 -0
- package/skills/engineering/red-setup/rsp-retirement-runbook.md +35 -0
- package/skills/engineering/red-setup/scripts/install-runtime-shim.sh +189 -0
- package/skills/engineering/red-setup/triage-labels.md +176 -0
- package/skills/engineering/red-setup/workflows/red-issues-needs-triage.yml +36 -0
- package/skills/engineering/red-statusline/HOST-NOTES.md +180 -0
- package/skills/engineering/red-statusline/SKILL.md +58 -0
- package/skills/engineering/report-bug/SKILL.md +155 -0
- package/skills/engineering/resolving-merge-conflicts/SKILL.md +143 -0
- package/skills/engineering/retake/SKILL.md +184 -0
- package/skills/engineering/review-adrs/SKILL.md +125 -0
- package/skills/engineering/start/ADR-FORMAT.md +47 -0
- package/skills/engineering/start/CONTEXT-FORMAT.md +77 -0
- package/skills/engineering/start/DOC-LANDING-FINALIZER.md +9 -0
- package/skills/engineering/start/SKILL.md +179 -0
- package/skills/engineering/tdd/SKILL.md +96 -0
- package/skills/engineering/tdd/deep-modules.md +33 -0
- package/skills/engineering/tdd/interface-design.md +31 -0
- package/skills/engineering/tdd/mocking.md +59 -0
- package/skills/engineering/tdd/tests.md +85 -0
- package/skills/engineering/to-spec/SKILL.md +104 -0
- package/skills/engineering/to-tickets/SKILL.md +158 -0
- package/skills/engineering/triage/AGENT-BRIEF.md +207 -0
- package/skills/engineering/triage/OUT-OF-SCOPE.md +101 -0
- package/skills/engineering/triage/SKILL.md +176 -0
- package/skills/engineering/verify/SKILL.md +136 -0
- package/skills/engineering/wayfinder/SKILL.md +128 -0
- package/skills/engineering/zoom-out/SKILL.md +51 -0
- package/skills/engineering/zoom-out/scripts/graph-mode-plumbing.sh +36 -0
- package/skills/engineering/zoom-out/scripts/tests/contract.test.sh +168 -0
- package/skills/knowledge/README.md +5 -0
- package/skills/knowledge/research/SKILL.md +76 -0
- package/skills/misc/README.md +8 -0
- package/skills/misc/branch-lock/SKILL.md +187 -0
- package/skills/misc/branch-lock/scripts/branch-lock-hook.sh +113 -0
- package/skills/misc/branch-lock/scripts/branch-lock-session-start.sh +81 -0
- package/skills/misc/branch-lock/scripts/branch-lock.sh +68 -0
- package/skills/misc/branch-lock/scripts/lib/dev-config.sh +126 -0
- package/skills/misc/branch-lock/scripts/lib/git-command-classifier.sh +198 -0
- package/skills/misc/branch-lock/scripts/lib/lock-store.sh +67 -0
- package/skills/misc/branch-lock/scripts/lib/scope-resolver.sh +43 -0
- package/skills/misc/branch-lock/scripts/tests/branch-lock-cli.test.sh +114 -0
- package/skills/misc/branch-lock/scripts/tests/claude-plugin-hook.test.sh +117 -0
- package/skills/misc/branch-lock/scripts/tests/codex-hook.test.sh +229 -0
- package/skills/misc/branch-lock/scripts/tests/dev-config.test.sh +99 -0
- package/skills/misc/branch-lock/scripts/tests/git-command-classifier.test.sh +187 -0
- package/skills/misc/branch-lock/scripts/tests/lock-store.test.sh +90 -0
- package/skills/misc/branch-lock/scripts/tests/scope-resolver.test.sh +63 -0
- package/skills/misc/branch-lock/scripts/tests/session-start.test.sh +123 -0
- package/skills/misc/git-guardrails-claude-code/SKILL.md +105 -0
- package/skills/misc/git-guardrails-claude-code/scripts/block-dangerous-git.sh +231 -0
- package/skills/misc/git-guardrails-claude-code/scripts/tests/block-dangerous-git.test.sh +143 -0
- package/skills/misc/migrate-to-shoehorn/SKILL.md +96 -0
- package/skills/misc/setup-pre-commit/SKILL.md +94 -0
- package/skills/productivity/README.md +8 -0
- package/skills/productivity/ff/SKILL.md +116 -0
- package/skills/productivity/handoff/SKILL.md +37 -0
- package/skills/productivity/reflect/SKILL.md +18 -0
- package/skills/productivity/write-a-skill/SKILL.md +190 -0
- package/skills/productivity/write-a-skill/WRITING-STYLE.md +62 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Issue tracker: GitHub
|
|
2
|
+
|
|
3
|
+
Issues and Specs for this repo live as GitHub issues. Use the `gh` CLI for all operations.
|
|
4
|
+
|
|
5
|
+
## Conventions
|
|
6
|
+
|
|
7
|
+
- **Create an issue**: `gh issue create --title "..." --body "..."`. Use a heredoc for multi-line bodies.
|
|
8
|
+
- **Read an issue**: `gh issue view <number> --comments`, filtering comments by `jq` and also fetching labels.
|
|
9
|
+
- **List issues**: `gh issue list --state open --json number,title,body,labels,comments --jq '[.[] | {number, title, body, labels: [.labels[].name], comments: [.comments[].body]}]'` with appropriate `--label` and `--state` filters.
|
|
10
|
+
- **Comment on an issue**: `gh issue comment <number> --body "..."`
|
|
11
|
+
- **Apply / remove labels**: `gh issue edit <number> --add-label "..."` / `--remove-label "..."`
|
|
12
|
+
- **Close**: `gh issue close <number> --comment "..."`
|
|
13
|
+
|
|
14
|
+
Infer the repo from `git remote -v` — `gh` does this automatically when run inside a clone.
|
|
15
|
+
|
|
16
|
+
## When a skill says "publish to the issue tracker"
|
|
17
|
+
|
|
18
|
+
Create a GitHub issue.
|
|
19
|
+
|
|
20
|
+
## When a skill says "fetch the relevant ticket"
|
|
21
|
+
|
|
22
|
+
Run `gh issue view <number> --comments`.
|
|
23
|
+
|
|
24
|
+
## Dependency & hierarchy operations
|
|
25
|
+
|
|
26
|
+
Use GitHub's native issue relationships for the human-facing graph, and keep the RedSkills labels/body fallback in sync for AFK machinery.
|
|
27
|
+
|
|
28
|
+
### Create a native sub-issue relationship
|
|
29
|
+
|
|
30
|
+
Create the child issue first, then attach it to its parent Spec or map with the sub-issues endpoint. Pass the child's numeric database id with `-F` (typed field) so `gh` sends it as a JSON integer — `-f` sends a string and the endpoint rejects it with HTTP 422:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
child_id="$(gh api "repos/{owner}/{repo}/issues/<child-number>" --jq '.id')"
|
|
34
|
+
gh api --method POST "repos/{owner}/{repo}/issues/<parent-number>/sub_issues" \
|
|
35
|
+
-F "sub_issue_id=$child_id"
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
For Spec slicing, also apply `spec:<parent-number>` to the child. For `/wayfinder`, the parent carries `wayfinder:map` and the child carries exactly one `wayfinder:<type>` label.
|
|
39
|
+
|
|
40
|
+
### Create a native blocked-by relationship
|
|
41
|
+
|
|
42
|
+
Use the child's dependency endpoint and pass the blocker issue's numeric database id (again with `-F`, for the same reason):
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
blocker_id="$(gh api "repos/{owner}/{repo}/issues/<blocker-number>" --jq '.id')"
|
|
46
|
+
gh api --method POST "repos/{owner}/{repo}/issues/<child-number>/dependencies/blocked_by" \
|
|
47
|
+
-F "issue_id=$blocker_id"
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**Trap:** `issue_id` must be the blocker's numeric database id from the REST issue `.id` field. It is never the GitHub issue `#number`, and it is never the GraphQL `node_id`. Passing the wrong value can link the wrong issue silently.
|
|
51
|
+
|
|
52
|
+
For AFK dependencies, also apply `blocked:dependency` plus one `req:<blocker-number>` label per blocker. Keep the strict `## Blocked by` body fallback when the issue should auto-promote after blockers close.
|
|
53
|
+
|
|
54
|
+
### Read blocked-by edges for audit
|
|
55
|
+
|
|
56
|
+
Audit the actual native blocker list from the child's endpoint:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
gh api "repos/{owner}/{repo}/issues/<child-number>/dependencies/blocked_by" \
|
|
60
|
+
--jq '.[] | {number, id, state, title}'
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Use this list when checking whether native blocked-by edges and `req:N` labels diverge.
|
|
64
|
+
|
|
65
|
+
### Read dependency summary counts
|
|
66
|
+
|
|
67
|
+
The REST issue payload includes `issue_dependencies_summary`. Its `blocked_by` field is an open-blocker count only:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
gh api "repos/{owner}/{repo}/issues/<child-number>" \
|
|
71
|
+
--jq '.issue_dependencies_summary.blocked_by'
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
`issue_dependencies_summary.blocked_by == 0` means no open blockers remain; it does not enumerate blockers and it should not replace the blocked-by audit endpoint above.
|
|
75
|
+
|
|
76
|
+
## Wayfinding operations
|
|
77
|
+
|
|
78
|
+
This repo expresses `/wayfinder` maps and tickets with GitHub Issues plus the RedSkills label vocabulary:
|
|
79
|
+
|
|
80
|
+
- The map is one GitHub issue labeled `wayfinder:map`.
|
|
81
|
+
- Tickets are native GitHub sub-issues of the map. Each ticket carries exactly one type label: `wayfinder:research`, `wayfinder:prototype`, `wayfinder:grilling`, or `wayfinder:task`.
|
|
82
|
+
- Blocking uses GitHub's native blocked-by relationship. Mirror every native blocking edge as a `req:N` label, per ADR 0094, so existing RedSkills queue and backpressure tools see the same dependency.
|
|
83
|
+
- Create and audit these native relationships with the commands in [Dependency & hierarchy operations](#dependency--hierarchy-operations).
|
|
84
|
+
- The frontier is the set of open child issues whose blockers are all closed and that have no assignee. Claim by assignment: assign yourself before working a ticket, and treat any assigned open ticket as claimed.
|
|
85
|
+
- AFK-typed children (`wayfinder:research` and AFK-safe `wayfinder:task`) enter the autonomous queue with `ready-for-agent` once unblocked. Blocked AFK children use `blocked:dependency` plus their `req:N` labels, not `ready-for-agent`.
|
|
86
|
+
- HITL-typed children (`wayfinder:grilling`, `wayfinder:prototype`, and any human-only `wayfinder:task`) use `ready-for-human` plus assignment to the expected human or role. They move back to the autonomous lane only after `/hitl` or `/retake` determines the blocker is resolved.
|
|
87
|
+
- An unblocked AFK-safe `wayfinder:task` is in `ready-for-agent` and can be dispatched immediately with `/afk --issues <n>`. The wayfinder session must not resolve it inline — route it to the AFK engine instead.
|
|
88
|
+
- If native blocking is unavailable, add a strict `## Blocked by` fallback section to the ticket body and list the blocking issue names with links. Keep the `req:N` labels in sync with that fallback.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# rsp Retirement Operator Runbook
|
|
2
|
+
|
|
3
|
+
RTK is retired for live RedSkills guidance after the measured parity decision in #1420. This runbook documents the operator-owned machine cleanup. Repository code must not execute these steps automatically.
|
|
4
|
+
|
|
5
|
+
## Scope
|
|
6
|
+
|
|
7
|
+
- Live guidance should point at `rsp` wrappers, loss levels, `rsp show`, and the per-repo hook opt-in.
|
|
8
|
+
- Historical ADRs, issue threads, benchmark fixtures, and memory artifacts are history and should not be rewritten only to remove older names.
|
|
9
|
+
- The ambient host-instruction replacement for per-host RTK.md files is tracked in #1415. Treat it as the follow-up deliverable that ships the generated `apps/rsp/generated/AMBIENT-SKILL.md` surface to each host.
|
|
10
|
+
|
|
11
|
+
## Remove the Pre-Execution Hook
|
|
12
|
+
|
|
13
|
+
Inspect each agent's local settings and remove the RTK pre-execution hook entry. The exact file is host-specific, but the intent is the same: delete only the hook command that invokes the retired binary and keep unrelated hooks intact.
|
|
14
|
+
|
|
15
|
+
After editing settings, open a fresh agent session and confirm routine commands are no longer rewritten by the retired hook. In repos that opt in with `rsp.enabled: true`, the RedSkills hook may still rewrite simple supported commands to `rsp`; that is expected.
|
|
16
|
+
|
|
17
|
+
## Delete the Binary
|
|
18
|
+
|
|
19
|
+
Remove the retired binary from the operator-managed bin directory or package manager that installed it. Verify that the shell no longer resolves it:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
command -v <retired-binary>
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
If another unrelated tool with the same executable name remains on `PATH`, leave that tool alone and document the distinction in local operator notes rather than changing repo guidance.
|
|
26
|
+
|
|
27
|
+
## Telemetry Database Retention
|
|
28
|
+
|
|
29
|
+
The old telemetry database includes a parse-failure ledger with forensic value. Keeping it, archiving it, or deleting it is an operator decision:
|
|
30
|
+
|
|
31
|
+
- **Keep** when recent failures may still inform `rsp` parity audits or incident review.
|
|
32
|
+
- **Archive** when the ledger is no longer active but may be needed for provenance.
|
|
33
|
+
- **Delete** only when local retention policy says the forensic value has expired.
|
|
34
|
+
|
|
35
|
+
Do not migrate this ledger into repo state. `rsp` stores current reversible elisions in the repo RedDB store under its own collection; the retired telemetry database remains a machine-local artifact.
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
bin_dir="${XDG_BIN_HOME:-$HOME/.local/bin}"
|
|
5
|
+
name="${1:-red-skills-dev}"
|
|
6
|
+
dev_target="$bin_dir/$name"
|
|
7
|
+
rsp_target="$bin_dir/rsp"
|
|
8
|
+
|
|
9
|
+
mkdir -p "$bin_dir"
|
|
10
|
+
|
|
11
|
+
cat >"$dev_target" <<'SH'
|
|
12
|
+
#!/usr/bin/env bash
|
|
13
|
+
set -euo pipefail
|
|
14
|
+
|
|
15
|
+
env_launcher() {
|
|
16
|
+
local root
|
|
17
|
+
for root in \
|
|
18
|
+
"${RED_SKILLS_DEV_PLUGIN_ROOT:-}" \
|
|
19
|
+
"${CLAUDE_PLUGIN_ROOT:-}" \
|
|
20
|
+
"${CODEX_PLUGIN_ROOT:-}" \
|
|
21
|
+
"${OPENCODE_PLUGIN_ROOT:-}"
|
|
22
|
+
do
|
|
23
|
+
[ -n "$root" ] || continue
|
|
24
|
+
if [ -f "$root/skills/engineering/afk/bin/afk.mjs" ]; then
|
|
25
|
+
printf '%s\n' "$root/skills/engineering/afk/bin/afk.mjs"
|
|
26
|
+
return 0
|
|
27
|
+
fi
|
|
28
|
+
done
|
|
29
|
+
return 1
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
latest_cache_launcher() {
|
|
33
|
+
local dir
|
|
34
|
+
for dir in "$HOME"/.codex/plugins/cache/red-skills/dev/* "$HOME"/.claude/plugins/cache/red-skills/dev/*; do
|
|
35
|
+
[ -f "$dir/skills/engineering/afk/bin/afk.mjs" ] &&
|
|
36
|
+
printf '%s\t%s\n' "$(basename "$dir")" "$dir/skills/engineering/afk/bin/afk.mjs"
|
|
37
|
+
done | sort -V | tail -1 | cut -f2-
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
latest_bundle() {
|
|
41
|
+
local bundle
|
|
42
|
+
for bundle in "$HOME"/.cache/red-skills/bundles/dev-*.bundle.min.mjs; do
|
|
43
|
+
[ -f "$bundle" ] || continue
|
|
44
|
+
local version="${bundle##*/dev-}"
|
|
45
|
+
version="${version%.bundle.min.mjs}"
|
|
46
|
+
printf '%s\t%s\n' "$version" "$bundle"
|
|
47
|
+
done | sort -V | tail -1 | cut -f2-
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
launcher="$(env_launcher || true)"
|
|
51
|
+
if [ -n "$launcher" ]; then
|
|
52
|
+
exec node "$launcher" "$@"
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
launcher="$(latest_cache_launcher || true)"
|
|
56
|
+
if [ -n "$launcher" ]; then
|
|
57
|
+
exec node "$launcher" "$@"
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
bundle="$(latest_bundle || true)"
|
|
61
|
+
if [ -n "$bundle" ]; then
|
|
62
|
+
exec node "$bundle" "$@"
|
|
63
|
+
fi
|
|
64
|
+
|
|
65
|
+
cat >&2 <<'EOF'
|
|
66
|
+
red-skills-dev: no RedSkills dev runtime found.
|
|
67
|
+
|
|
68
|
+
Expected one of:
|
|
69
|
+
- an installed dev plugin under ~/.codex/plugins/cache/red-skills/dev/*
|
|
70
|
+
- an installed dev plugin under ~/.claude/plugins/cache/red-skills/dev/*
|
|
71
|
+
- a warmed bundle under ~/.cache/red-skills/bundles/dev-*.bundle.min.mjs
|
|
72
|
+
|
|
73
|
+
Fallback:
|
|
74
|
+
npx -y -p @reddb-io/red-skills@<version> red-skills-dev "$@"
|
|
75
|
+
|
|
76
|
+
Run /red-setup in a repo with plugins.dev.enabled: true, then restart the
|
|
77
|
+
agent session so the plugin SessionStart hook can warm the runtime cache, or use
|
|
78
|
+
the npm direct-run fallback above for a fresh machine.
|
|
79
|
+
EOF
|
|
80
|
+
exit 127
|
|
81
|
+
SH
|
|
82
|
+
|
|
83
|
+
cat >"$rsp_target" <<'SH'
|
|
84
|
+
#!/usr/bin/env bash
|
|
85
|
+
set -euo pipefail
|
|
86
|
+
|
|
87
|
+
env_bundle() {
|
|
88
|
+
local root bundle
|
|
89
|
+
for root in \
|
|
90
|
+
"${RED_SKILLS_DEV_PLUGIN_ROOT:-}" \
|
|
91
|
+
"${CLAUDE_PLUGIN_ROOT:-}" \
|
|
92
|
+
"${CODEX_PLUGIN_ROOT:-}" \
|
|
93
|
+
"${OPENCODE_PLUGIN_ROOT:-}"
|
|
94
|
+
do
|
|
95
|
+
[ -n "$root" ] || continue
|
|
96
|
+
for bundle in \
|
|
97
|
+
"$root/../../dist/rsp.bundle.min.mjs" \
|
|
98
|
+
"$root/dist/rsp.bundle.min.mjs"
|
|
99
|
+
do
|
|
100
|
+
if [ -f "$bundle" ]; then
|
|
101
|
+
printf '%s\n' "$bundle"
|
|
102
|
+
return 0
|
|
103
|
+
fi
|
|
104
|
+
done
|
|
105
|
+
done
|
|
106
|
+
return 1
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
latest_cache_bundle() {
|
|
110
|
+
local dir bundle
|
|
111
|
+
for dir in "$HOME"/.codex/plugins/cache/red-skills/dev/* "$HOME"/.claude/plugins/cache/red-skills/dev/*; do
|
|
112
|
+
[ -d "$dir" ] || continue
|
|
113
|
+
for bundle in "$dir/../../dist/rsp.bundle.min.mjs" "$dir/dist/rsp.bundle.min.mjs"; do
|
|
114
|
+
[ -f "$bundle" ] &&
|
|
115
|
+
printf '%s\t%s\n' "$(basename "$dir")" "$bundle"
|
|
116
|
+
done
|
|
117
|
+
done | sort -V | tail -1 | cut -f2-
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
latest_bundle() {
|
|
121
|
+
local cache_root bundle version
|
|
122
|
+
cache_root="${RED_SKILLS_CACHE_DIR:-${XDG_CACHE_HOME:-$HOME/.cache}/red-skills/bundles}"
|
|
123
|
+
|
|
124
|
+
if [ -f "$cache_root/rsp.bundle.min.mjs" ]; then
|
|
125
|
+
printf '%s\n' "$cache_root/rsp.bundle.min.mjs"
|
|
126
|
+
return 0
|
|
127
|
+
fi
|
|
128
|
+
|
|
129
|
+
for bundle in "$cache_root"/rsp-*.bundle.min.mjs; do
|
|
130
|
+
[ -f "$bundle" ] || continue
|
|
131
|
+
version="${bundle##*/rsp-}"
|
|
132
|
+
version="${version%.bundle.min.mjs}"
|
|
133
|
+
printf '%s\t%s\n' "$version" "$bundle"
|
|
134
|
+
done | sort -V | tail -1 | cut -f2-
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
find_red_binary() {
|
|
138
|
+
local cache_root red version
|
|
139
|
+
cache_root="${RED_SKILLS_CACHE_DIR:-${XDG_CACHE_HOME:-$HOME/.cache}/red-skills/bundles}"
|
|
140
|
+
|
|
141
|
+
for red in "$cache_root"/reddb/*/red "$cache_root"/reddb/*/red.exe; do
|
|
142
|
+
[ -x "$red" ] || continue
|
|
143
|
+
version="${red%/*}"
|
|
144
|
+
version="${version##*/}"
|
|
145
|
+
printf '%s\t%s\n' "$version" "$red"
|
|
146
|
+
done | sort -V | tail -1 | cut -f2-
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
with_red_binary() {
|
|
150
|
+
local red
|
|
151
|
+
red="$(find_red_binary || true)"
|
|
152
|
+
if [ -n "$red" ]; then
|
|
153
|
+
REDDB_BIN="$red" exec node "$@"
|
|
154
|
+
fi
|
|
155
|
+
exec node "$@"
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
bundle="$(env_bundle || true)"
|
|
159
|
+
if [ -n "$bundle" ]; then
|
|
160
|
+
with_red_binary "$bundle" "$@"
|
|
161
|
+
fi
|
|
162
|
+
|
|
163
|
+
bundle="$(latest_cache_bundle || true)"
|
|
164
|
+
if [ -n "$bundle" ]; then
|
|
165
|
+
with_red_binary "$bundle" "$@"
|
|
166
|
+
fi
|
|
167
|
+
|
|
168
|
+
bundle="$(latest_bundle || true)"
|
|
169
|
+
if [ -n "$bundle" ]; then
|
|
170
|
+
with_red_binary "$bundle" "$@"
|
|
171
|
+
fi
|
|
172
|
+
|
|
173
|
+
cat >&2 <<'EOF'
|
|
174
|
+
rsp: no RedSkills rsp runtime found.
|
|
175
|
+
|
|
176
|
+
Expected one of:
|
|
177
|
+
- an installed dev plugin with dist/rsp.bundle.min.mjs under ~/.codex/plugins/cache/red-skills/dev/*
|
|
178
|
+
- an installed dev plugin with dist/rsp.bundle.min.mjs under ~/.claude/plugins/cache/red-skills/dev/*
|
|
179
|
+
- a warmed rsp bundle under ${RED_SKILLS_CACHE_DIR:-${XDG_CACHE_HOME:-$HOME/.cache}/red-skills/bundles}
|
|
180
|
+
|
|
181
|
+
Run /red-setup in a repo with plugins.dev.enabled: true, then restart the
|
|
182
|
+
agent session so the plugin SessionStart hook can warm the runtime cache.
|
|
183
|
+
EOF
|
|
184
|
+
exit 127
|
|
185
|
+
SH
|
|
186
|
+
|
|
187
|
+
chmod 0755 "$dev_target" "$rsp_target"
|
|
188
|
+
printf 'installed %s\n' "$dev_target"
|
|
189
|
+
printf 'installed %s\n' "$rsp_target"
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# Triage Labels
|
|
2
|
+
|
|
3
|
+
Canonical label vocabulary and full issue lifecycle. This is the single source of truth — `/triage`, `/afk`, `/to-tickets`, and `/to-spec` all reference this file.
|
|
4
|
+
|
|
5
|
+
## Label Mapping
|
|
6
|
+
|
|
7
|
+
The skills speak in terms of canonical triage roles. Map them here to the actual label strings used in this repo's issue tracker.
|
|
8
|
+
|
|
9
|
+
| Canonical role | Label in our tracker | Applied by | Removed by |
|
|
10
|
+
| ------------------ | -------------------- | ------------------------------------- | ----------------------------------- |
|
|
11
|
+
| `needs-triage` | `needs-triage` | `red-issues-needs-triage` workflow, `/triage` | `/triage` (when state transitions) |
|
|
12
|
+
| `needs-info` | `needs-info` | `/triage` | `/triage` (when reporter replies) |
|
|
13
|
+
| `ready-for-agent` | `ready-for-agent` | `/triage`, `/to-tickets` | `/afk` (when claiming) |
|
|
14
|
+
| `running` | `running` | `/afk` (when claiming an issue) | `/afk` (on close, blocker, or release) |
|
|
15
|
+
| `ready-for-human` | `ready-for-human` | `/triage`, `/afk` (on blocker) | maintainer |
|
|
16
|
+
| `wontfix` | `wontfix` | `/triage` (then close) | rarely — usually issue closes |
|
|
17
|
+
| `needs-slicing` | `needs-slicing` | `/to-spec` (on publish) | `/to-tickets` (when slices are created) |
|
|
18
|
+
| `type:spec` | `type:spec` | `/to-spec` (on publish) | never — type marker, permanent |
|
|
19
|
+
|
|
20
|
+
Edit the right-hand column to match whatever vocabulary you actually use.
|
|
21
|
+
|
|
22
|
+
## Full Lifecycle
|
|
23
|
+
|
|
24
|
+
Every issue moves through this state machine. Arrows show the transitions; the actor on each arrow is the skill or workflow responsible.
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
┌─────────────────────┐
|
|
28
|
+
│ issue created │
|
|
29
|
+
│ (any source) │
|
|
30
|
+
└──────────┬──────────┘
|
|
31
|
+
│
|
|
32
|
+
red-issues-needs-triage workflow
|
|
33
|
+
(auto on opened/reopened, no label)
|
|
34
|
+
▼
|
|
35
|
+
┌─────────────────────┐
|
|
36
|
+
┌─────────────│ needs-triage │────────────┐
|
|
37
|
+
│ └──────────┬──────────┘ │
|
|
38
|
+
│ │ │
|
|
39
|
+
/triage: /triage: /triage:
|
|
40
|
+
needs-info wontfix ready-for-*
|
|
41
|
+
│ │ │
|
|
42
|
+
▼ ▼ │
|
|
43
|
+
┌──────────────┐ ┌──────────────┐ │
|
|
44
|
+
│ needs-info │ │ wontfix │ │
|
|
45
|
+
│ (await user) │ │ + close │ │
|
|
46
|
+
└──────┬───────┘ └──────────────┘ │
|
|
47
|
+
│ │
|
|
48
|
+
reporter replies │
|
|
49
|
+
→ /triage │
|
|
50
|
+
│ │
|
|
51
|
+
└──────────────────► needs-triage │
|
|
52
|
+
▼
|
|
53
|
+
┌───────────────────────────────────┐
|
|
54
|
+
│ │
|
|
55
|
+
▼ ▼
|
|
56
|
+
┌──────────────────────┐ ┌──────────────────────┐
|
|
57
|
+
│ ready-for-agent │ │ ready-for-human │
|
|
58
|
+
│ (## Agent brief │ │ (needs judgment) │
|
|
59
|
+
│ in body) │ └──────────────────────┘
|
|
60
|
+
└──────────┬───────────┘ │
|
|
61
|
+
│ │
|
|
62
|
+
/afk claim: human picks up
|
|
63
|
+
removes ready-for-agent, (manual impl,
|
|
64
|
+
adds running eventually closes)
|
|
65
|
+
│
|
|
66
|
+
▼
|
|
67
|
+
┌──────────────────────┐
|
|
68
|
+
│ running │
|
|
69
|
+
│ (worktree active, │
|
|
70
|
+
│ heartbeats post) │
|
|
71
|
+
└──────────┬───────────┘
|
|
72
|
+
│
|
|
73
|
+
┌──────────────┼──────────────┐
|
|
74
|
+
│ │ │
|
|
75
|
+
/afk: DONE /afk: BLOCKED /afk: merge conflict
|
|
76
|
+
│ │ │
|
|
77
|
+
▼ ▼ ▼
|
|
78
|
+
┌─────────┐ ┌────────────────────────────┐
|
|
79
|
+
│ closed │ │ remove running, │
|
|
80
|
+
│ + merge │ │ add ready-for-human, │
|
|
81
|
+
│ comment │ │ worktree preserved │
|
|
82
|
+
└─────────┘ └────────────────────────────┘
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## State Definitions
|
|
86
|
+
|
|
87
|
+
### `needs-triage`
|
|
88
|
+
Maintainer has not evaluated the issue yet. **Applied automatically** by `red-issues-needs-triage.yml` workflow on every fresh `opened`/`reopened` issue with no labels. Manual application by `/triage` when the maintainer puts an evaluated issue back into the queue. Removed by `/triage` when the issue transitions to a definitive state.
|
|
89
|
+
|
|
90
|
+
### `needs-info`
|
|
91
|
+
The triage agent or maintainer needs more information from the reporter before a decision can be made. Removed by `/triage` once the reporter responds and the issue cycles back through `needs-triage`.
|
|
92
|
+
|
|
93
|
+
### `ready-for-agent`
|
|
94
|
+
The issue body contains a complete `## Agent brief` section (see `triage/AGENT-BRIEF.md`) that forms a contract sufficient for an AFK agent to implement without human context. **This is the only state `/afk` consumes.** Applied by `/triage` (after grilling) or `/to-tickets` (on creation when the slice is AFK-safe).
|
|
95
|
+
|
|
96
|
+
### `running`
|
|
97
|
+
`/afk` has claimed the issue and is actively executing it. Applied atomically with the removal of `ready-for-agent` so two parallel `/afk` runs cannot race on the same issue. The orchestrator's heartbeat sub-shell posts `:one:` → `:four:` comments every 10 min while this label is present. Removed on close (success), on blocker (replaced with `ready-for-human`), or on graceful release (if the user interrupts the loop).
|
|
98
|
+
|
|
99
|
+
### `ready-for-human`
|
|
100
|
+
The issue requires human decision or resolution before it can proceed or be delegated. Two sources: `/triage` decides it during evaluation (e.g. architectural call, design review needed), or `/afk` promotes it from `running` after a blocker (inner agent gave up, merge conflict couldn't be auto-resolved, both runners exhausted). When `/afk` promotes, the worktree is **preserved at the moment of blocker** so the human can inspect or resolve the blocker in place.
|
|
101
|
+
|
|
102
|
+
### `wontfix`
|
|
103
|
+
Will not be actioned. Applied by `/triage`. For bugs, paired with a polite explanation and close. For enhancements, paired with a `.out-of-scope/*.md` entry (see `triage/OUT-OF-SCOPE.md`).
|
|
104
|
+
|
|
105
|
+
### `type:spec`
|
|
106
|
+
Permanent type marker for Spec issues created by `/to-spec`. A Spec is a planning artifact, **not an implementable slice** — it describes *what* to build at the product level and must be split into child issues by `/to-tickets` before any agent can execute. `/afk` hard-filters issues carrying `type:spec` from its candidate list even if `ready-for-agent` was applied by mistake. Never remove this label.
|
|
107
|
+
|
|
108
|
+
### `needs-slicing`
|
|
109
|
+
The Spec has been published but `/to-tickets` has not yet split it into child slices. Applied by `/to-spec` on publish, removed by `/to-tickets` once at least one child issue with `spec:{N}` exists. `/afk` counts these in its straggler check so a forgotten Spec surfaces before the loop runs dry.
|
|
110
|
+
|
|
111
|
+
## Heartbeat Comments
|
|
112
|
+
|
|
113
|
+
While `running`, `/afk` posts a heartbeat comment every 10 minutes so the issue is never silent during long executions:
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
t=10 min → :one:
|
|
117
|
+
t=20 min → :two:
|
|
118
|
+
t=30 min → :three:
|
|
119
|
+
t=40 min → :four:
|
|
120
|
+
t=50 min → :one: (cycle resets)
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Stops on any terminal transition out of `running`.
|
|
124
|
+
|
|
125
|
+
## Optional Auxiliary Labels
|
|
126
|
+
|
|
127
|
+
These exist for filtering and don't drive lifecycle transitions:
|
|
128
|
+
|
|
129
|
+
| Label | Meaning | Applied by |
|
|
130
|
+
| -------------- | ----------------------------------------------- | -------------------------------- |
|
|
131
|
+
| `bug` | Something is broken | `/triage` |
|
|
132
|
+
| `enhancement` | New feature or improvement | `/triage` |
|
|
133
|
+
| `priority:high` | Urgent / high-impact — `/afk` drains these first | `/triage` or maintainer |
|
|
134
|
+
| `priority:low` | Everything else | `/triage` or maintainer |
|
|
135
|
+
| `spec:{N}` | Issue belongs to Spec #N | `/to-tickets` when splitting a Spec |
|
|
136
|
+
| `wayfinder:map` | Planning map Ticket for work too large for one agent session. Carries `## Destination`, `## Not yet specified`, and `## Out of scope`; the map is an index, not a store. | `/wayfinder` |
|
|
137
|
+
| `wayfinder:research` | Wayfinder child type for AFK-typed research scoped to one session. Unblocked children use `ready-for-agent`; blocked children use `blocked:dependency` plus `req:N`. | `/wayfinder` |
|
|
138
|
+
| `wayfinder:grilling` | Wayfinder child type for HITL-typed decision work routed to a `/start` session and claimed by assignment. | `/wayfinder` |
|
|
139
|
+
| `wayfinder:prototype` | Wayfinder child type for HITL-typed design or logic exploration routed to a `/prototype` session and claimed by assignment. | `/wayfinder` |
|
|
140
|
+
| `wayfinder:task` | Wayfinder child type for AFK-typed implementation/docs work scoped to one session. Unblocked children use `ready-for-agent`; blocked children use `blocked:dependency` plus `req:N`. | `/wayfinder` |
|
|
141
|
+
| `runner-error` | `/afk` fleet supervisor parked a slot after fast-death streak; affected issues were restored to `ready-for-agent` after the runner was discarded | `/afk` fleet supervisor on circuit trip |
|
|
142
|
+
| `landing:manual` | Per-issue **manual-landing** mode (#1049): on a `ready-for-agent` issue, `/afk` runs the full pipeline + opens the PR, then **holds for a human's merge click** (parks `ready-for-human`, never auto-merges, never re-runs the agent). The issue auto-closes on PR merge via `Closes #N`. Lets agent-codable slices that must not be auto-merged stay in the autonomous lane instead of being hand-dispatched via `/go`. | `/triage` at brief time, or `/hitl`'s **delegable-manual-landing** disposition |
|
|
143
|
+
|
|
144
|
+
`runner-error` is the only auxiliary label `/afk` may create autonomously: the fleet supervisor calls `gh label create runner-error` when it trips the circuit breaker, so the cleanup never fails just because the label has not been provisioned. Provision it up front via `/red-setup` to keep colour/description consistent across repos.
|
|
145
|
+
|
|
146
|
+
## Blocked Reasons (`blocked:<reason>`) — typed, auto-classified
|
|
147
|
+
|
|
148
|
+
`/afk` already computes a precise terminal outcome for every iteration; instead of flattening every failure to one `blocked`, it tags the issue with the matching **`blocked:<reason>`** label so the backlog is filterable by *what kind* of block it is. The reason is derived automatically from the outcome — **no human classification**.
|
|
149
|
+
|
|
150
|
+
| Outcome (runtime) | Label | Recovery | Retry cap (env) |
|
|
151
|
+
| ----------------- | ----- | -------- | --------------- |
|
|
152
|
+
| runner quota / both exhausted | `blocked:quota` | **auto-retry** → ready-for-agent | 3 (`RED_AFK_RETRY_QUOTA`) |
|
|
153
|
+
| runner transport/setup failed | `blocked:runner-transient` | **auto-retry** → ready-for-agent | 3 (`RED_AFK_RETRY_RUNNER_TRANSIENT`) |
|
|
154
|
+
| couldn't integrate or land | `blocked:merge-conflict` | **auto-retry** (base settles) | 3 (`RED_AFK_RETRY_MERGE`) |
|
|
155
|
+
| mergeable PR blocked by CI (required check failed / still pending) | `blocked:ci` | **pages** → ready-for-human / CI-aware finisher (never re-runs the agent) | — (never auto) |
|
|
156
|
+
| agent exited without a sentinel | `blocked:crashed` | **auto-retry once** (transient) | 1 (`RED_AFK_RETRY_CRASH`) |
|
|
157
|
+
| a user `pre_*` guard hook rejected it | `blocked:policy` | **auto-retry once** | 1 (`RED_AFK_RETRY_POLICY`) |
|
|
158
|
+
| agent emitted `<promise>BLOCKED</promise>` | `blocked:spec` | **pages** → ready-for-human (decide/clarify) | — (never auto) |
|
|
159
|
+
| feedback gate failed (test/lint/build) | `blocked:validation` | **pages** → ready-for-human (review diff) | — (never auto) |
|
|
160
|
+
| stall-reaper killed a hung worker | `blocked:stalled` | **auto-retry** → ready-for-agent (clean) | 3 (`RED_AFK_RETRY_STALLED`) |
|
|
161
|
+
| worktree/base/push setup failed | `blocked:infra` | pages → ready-for-human (ops) | — |
|
|
162
|
+
|
|
163
|
+
**Bounded auto-recovery (live).** The recoverable reasons loop back to `ready-for-agent` and are retried, up to their per-reason cap (counting real attempt-ledger attempts); on the cap they **escalate** to `ready-for-human` with a `🤖 /afk escalating … retry budget exhausted (attempt N/cap)` comment. So a transient hiccup self-heals and never pages, but a persistent one still surfaces — bounded, no runaway loop. The supervisor stall-reaper's `blocked:stalled` re-queue is bounded by the **same** policy (`RED_AFK_RETRY_STALLED`, default 3). Caps are env-tunable (non-numeric/0 → default). `spec`, `validation`, and `ci` **always page** (a human must decide / review the diff / drive the open PR to merge); `dependency` waits on its `req:N` edges (never pages). `blocked:ci` (#812) is deliberately non-recoverable: the work is already complete and committed on the open PR, so re-running the agent would re-spend tokens for nothing — a human / CI-aware finisher merges the existing PR once CI is green. **A re-queue is hygienic:** promoting an issue to `ready-for-agent` (auto-retry) or `running` (claim) sheds any `blocked:*` label in the same edit, so no live/queued issue ever carries `ready-for-agent`/`running` together with `blocked:*`. The typed `blocked:<reason>` label rides only the `ready-for-human` escalation.
|
|
164
|
+
|
|
165
|
+
> Not yet wired: time-based backoff (today the re-queue is immediate; the cap is what prevents runaway).
|
|
166
|
+
|
|
167
|
+
All `blocked:*` labels are created on the fly when first applied (mirroring `runner-error`) and provisioned by `/red-setup`.
|
|
168
|
+
|
|
169
|
+
## Naming Convention
|
|
170
|
+
|
|
171
|
+
All labels follow one of two shapes:
|
|
172
|
+
|
|
173
|
+
- **kebab-case** — `needs-triage`, `ready-for-agent`, `running`, `wontfix`, `bug`.
|
|
174
|
+
- **`prefix:value`** — `priority:high`, `spec:42`.
|
|
175
|
+
|
|
176
|
+
No uppercase, CamelCase, snake_case, or spaces. GitHub matches labels case-insensitively for filtering but stores the case you create them with — keep the tracker clean by normalising on creation. `/red-setup` surfaces non-conforming labels and offers to rename via `gh label edit "Old Name" --name "new-name"`.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Auto-applies the `needs-triage` label to any newly opened or reopened issue
|
|
2
|
+
# that has no labels yet. Keeps fresh issues from slipping past `/triage` and
|
|
3
|
+
# `/afk` (which only consumes `ready-for-agent`).
|
|
4
|
+
#
|
|
5
|
+
# Installed by `/red-setup`. Filename prefix `red-` marks it as belonging
|
|
6
|
+
# to the RedSkills ecosystem.
|
|
7
|
+
|
|
8
|
+
name: red-issues-needs-triage
|
|
9
|
+
|
|
10
|
+
on:
|
|
11
|
+
issues:
|
|
12
|
+
types: [opened, reopened]
|
|
13
|
+
|
|
14
|
+
permissions:
|
|
15
|
+
issues: write
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
label:
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/github-script@v7
|
|
22
|
+
with:
|
|
23
|
+
script: |
|
|
24
|
+
const issue = context.payload.issue;
|
|
25
|
+
const labels = (issue.labels || []).map(l => l.name);
|
|
26
|
+
if (labels.length > 0) {
|
|
27
|
+
core.info(`Issue #${issue.number} already labelled (${labels.join(', ')}). Skipping.`);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
await github.rest.issues.addLabels({
|
|
31
|
+
owner: context.repo.owner,
|
|
32
|
+
repo: context.repo.repo,
|
|
33
|
+
issue_number: issue.number,
|
|
34
|
+
labels: ['needs-triage']
|
|
35
|
+
});
|
|
36
|
+
core.info(`Applied 'needs-triage' to #${issue.number}.`);
|