@moon791017/neo-skills 1.1.14 → 1.1.17
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/README.md +5 -34
- package/package.json +1 -1
- package/skills/neo-pr/SKILL.md +112 -0
- package/skills/neo-pr/evals/eval_queries.json +14 -0
- package/skills/neo-pr/evals/evals.json +16 -0
- package/skills/neo-pr/references/pr-template.md +47 -0
- package/skills/neo-pr/scripts/git-pr-extractor.py +100 -0
package/README.md
CHANGED
|
@@ -63,6 +63,7 @@
|
|
|
63
63
|
| 技能開發 | `generate-skill` | 建立、更新、審查或最佳化 Agent Skill,包含規格、觸發描述、延伸資源、評估資料與設計模式。 |
|
|
64
64
|
| 可觀測性 | `neo-opentelemetry` | 解釋 OpenTelemetry 概念、規劃或審查 Collector 架構與設定、處理維運排障、安全、零程式 instrumentation 及相容性遷移。 |
|
|
65
65
|
| 文字潤飾 | `neo-stop-slop` | 去除繁中或英文中的 AI 腔、贅詞、公式化句式,支援文件、註解、commit message 與 PR 說明。 |
|
|
66
|
+
| PR 產出 | `neo-pr` | 詢問或自動偵測 Repository 來源與目標分支,擷取變更並產生重點式且去 AI 腔的 PR Title 與 PR Description。 |
|
|
66
67
|
|
|
67
68
|
`generate-skill` 位於 `.agents/skills/`,可由 Agent Skills CLI 探索與安裝;其餘技能位於 `skills/`。
|
|
68
69
|
|
|
@@ -84,48 +85,18 @@ node bin/install-skills.js
|
|
|
84
85
|
|
|
85
86
|
### Agent Skills CLI 安裝
|
|
86
87
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
| Agent | `--agent` ID |
|
|
90
|
-
| :--- | :--- |
|
|
91
|
-
| Claude Code | `claude-code` |
|
|
92
|
-
| Copilot CLI | `github-copilot` |
|
|
93
|
-
| Codex | `codex` |
|
|
94
|
-
| Antigravity CLI | `antigravity-cli` |
|
|
95
|
-
|
|
96
|
-
安裝全部技能到目前專案(以 Codex 為例):
|
|
97
|
-
|
|
98
|
-
```bash
|
|
99
|
-
npx skills add Benknightdark/neo-skills --skill '*' --agent codex -y
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
安裝全部技能到全域(以 Codex 為例):
|
|
103
|
-
|
|
104
|
-
```bash
|
|
105
|
-
npx skills add Benknightdark/neo-skills --skill '*' --agent codex -g -y
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
同時安裝到多個 Agent 時,重複傳入 `--agent`:
|
|
88
|
+
安裝全部技能到目前專案:
|
|
109
89
|
|
|
110
90
|
```bash
|
|
111
|
-
npx skills add Benknightdark/neo-skills --skill
|
|
112
|
-
--agent codex \
|
|
113
|
-
--agent antigravity-cli \
|
|
114
|
-
-g -y
|
|
91
|
+
npx skills add Benknightdark/neo-skills --skill --all -y
|
|
115
92
|
```
|
|
116
93
|
|
|
117
|
-
|
|
94
|
+
安裝全部技能到全域:
|
|
118
95
|
|
|
119
96
|
```bash
|
|
120
|
-
npx skills add Benknightdark/neo-skills
|
|
121
|
-
--skill neo-typescript \
|
|
122
|
-
--skill neo-vue \
|
|
123
|
-
--agent codex \
|
|
124
|
-
-y
|
|
97
|
+
npx skills add Benknightdark/neo-skills --skill --all -g -y
|
|
125
98
|
```
|
|
126
99
|
|
|
127
|
-
> `--all` 等同同時選取全部技能與全部 Agent。不要使用 `--all -g` 表示「全域安裝全部技能」;Eve 與 PromptScript 僅支援專案範圍,會使該組合回報安裝失敗。
|
|
128
|
-
|
|
129
100
|
## 系統提示詞安裝
|
|
130
101
|
|
|
131
102
|
Agent Skills 規格同步的是技能目錄;`AGENTS.md`、`CLAUDE.md`、Copilot instructions 或 Antigravity `agents.md` 這類指導檔需要另外安裝。
|
package/package.json
CHANGED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: neo-pr
|
|
3
|
+
description: >
|
|
4
|
+
Use this skill when the user asks to create, draft, review, format, or generate a Pull
|
|
5
|
+
Request (PR) title and description, specify target or source branches for a repository,
|
|
6
|
+
or convert git branch diffs into concise, high-impact, non-AI-slop PR content.
|
|
7
|
+
license: MIT
|
|
8
|
+
compatibility: Requires Python 3.10+ (uv or python3) for git-pr-extractor.py, and Node.js for analyze-slop.js validation.
|
|
9
|
+
metadata:
|
|
10
|
+
author: Ben Knight Dark
|
|
11
|
+
version: "1.0.0"
|
|
12
|
+
patterns: generator, reviewer, inversion
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# Neo PR Generator & Refiner
|
|
16
|
+
|
|
17
|
+
`neo-pr` is an expert skill engineered to generate precise, concise, and non-AI-slop Pull Request (PR) titles and descriptions for Git repositories. It proactively guides the user to clarify repository and branch targets, extracts change histories, and outputs clear, highly structured PR content.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Gotchas
|
|
22
|
+
|
|
23
|
+
* **Non-existent or Unaligned Branches**: If the specified source or target branch does not exist locally or on remote, prompt the user to run `git fetch` or provide the correct branch name. Do not invent non-existent base branches.
|
|
24
|
+
* **Overly Long Diffs and Token Overhead**: If the branch diff spans dozens of files or thousands of lines, inspect `git diff --stat` and commit logs first to gain high-level context instead of loading full diffs at once.
|
|
25
|
+
* **De-slop Does Not Mean Removing Technical Substance**: When stripping AI fluff, eliminate throat-clearing openers (e.g., "It is worth noting that...", "This PR aims to..."), but strictly preserve essential context, key logic shifts, breaking changes, and test instructions.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Workflow Checklist
|
|
30
|
+
|
|
31
|
+
- [ ] **Step 1 — Perceive (Gather Branch & Repository Context)**: Identify the repository path, source branch (`source branch`), and target branch (`target branch`). If unspecified, prompt the user or detect the current Git state.
|
|
32
|
+
- [ ] **Step 2 — Reason & Load References (Load Templates & Guidelines)**: Read [pr-template.md](file:///Users/ben/projects/neo-skills/skills/neo-pr/references/pr-template.md) for structural standards and de-slop conventions.
|
|
33
|
+
- [ ] **Step 3 — Act: Extract Diff (Fetch Change Record)**: Execute the helper script `git-pr-extractor.py` to retrieve commit logs, file statistics, and diff snippets.
|
|
34
|
+
- [ ] **Step 4 — Act: Generate & De-slop (Produce Concise PR Content)**: Write a Conventional Commits title and bulleted PR description while eliminating all AI tells.
|
|
35
|
+
- [ ] **Step 5 — Verify (Quality Check)**: Verify that the generated title and description adhere to de-slop standards (optionally run `analyze-slop.js` to score density).
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Detailed Guidelines
|
|
40
|
+
|
|
41
|
+
### Step 1 — Perceive (Gather Branch & Repository Context)
|
|
42
|
+
|
|
43
|
+
Determine the following core parameters:
|
|
44
|
+
1. **Repository Context**: Current working directory or specified GitHub/GitLab workspace.
|
|
45
|
+
2. **Source Branch**: Branch containing the new changes (e.g., `feature/user-auth` or current checked-out branch).
|
|
46
|
+
3. **Target Branch**: Base branch to merge into (e.g., `main`, `master`, or `develop`).
|
|
47
|
+
|
|
48
|
+
If the user has not specified branches, ask with a concise prompt:
|
|
49
|
+
> "Please specify your **source branch** (e.g., `feature/xxx`) and **target branch** (e.g., `main` or `develop`). If omitted, I will default to PRing the current branch into `main`."
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
### Step 2 — Reason & Load References
|
|
54
|
+
|
|
55
|
+
Load relevant design documents based on diff scope:
|
|
56
|
+
* **PR Structure & Template**: Read `references/pr-template.md` for standard markdown sections.
|
|
57
|
+
* **De-slop Rules**: Apply core `neo-stop-slop` principles (active voice, remove filler phrases, focus on objective facts).
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
### Step 3 — Act: Extract Diff (Fetch Change Record)
|
|
62
|
+
|
|
63
|
+
Run `git-pr-extractor.py` non-interactively in the target repository directory:
|
|
64
|
+
```bash
|
|
65
|
+
python3 skills/neo-pr/scripts/git-pr-extractor.py --target-branch <target> --source-branch <source>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Alternatively, run native Git commands if script execution is unavailable:
|
|
69
|
+
```bash
|
|
70
|
+
git log <target>..<source> --oneline
|
|
71
|
+
git diff <target>..<source> --stat
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
### Step 4 — Act: Generate & De-slop (Produce Concise PR Content)
|
|
77
|
+
|
|
78
|
+
Construct the PR Title and Description based on extracted commit and diff context.
|
|
79
|
+
|
|
80
|
+
#### 1. PR Title Standard (Conventional Commits)
|
|
81
|
+
* Format: `<type>(<scope>): <short summary>`
|
|
82
|
+
* Example: `feat(auth): 新增 JWT 驗證與 Token 自動刷新`
|
|
83
|
+
* Rules:
|
|
84
|
+
- Do not begin with filler phrases ("This PR implements...", "A commit to...").
|
|
85
|
+
- Keep under 50 characters, imperative mood, direct and actionable.
|
|
86
|
+
|
|
87
|
+
#### 2. PR Output Standard Structure
|
|
88
|
+
The PR output must strictly consist of only the following two sections:
|
|
89
|
+
|
|
90
|
+
```markdown
|
|
91
|
+
標題:
|
|
92
|
+
<Conventional Commits 格式標題>
|
|
93
|
+
|
|
94
|
+
內容:
|
|
95
|
+
- 列點並重點化的說明重要變更內容(包含主要模組/檔案調整、邏輯變更與重大影響)。
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
#### 3. Strict De-slop Rules
|
|
99
|
+
* ❌ Never use: "It is worth noting that", "Needless to say", "This PR aims to", "In summary", "Clearly".
|
|
100
|
+
* ❌ Avoid hyperbolic fluff: "dramatically improves", "seamlessly integrates", "highly robust".
|
|
101
|
+
* ⭕ Use concrete facts & metrics: "reduces response latency by 30ms", "fixes NullReferenceException on null payload".
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
### Step 5 — Verify (Quality Check)
|
|
106
|
+
|
|
107
|
+
1. Ensure no critical modifications are omitted from the generated title or description.
|
|
108
|
+
2. Run de-slop score check if `skills/neo-stop-slop/scripts/analyze-slop.js` is available:
|
|
109
|
+
```bash
|
|
110
|
+
node skills/neo-stop-slop/scripts/analyze-slop.js --input "<generated PR description>" --format json
|
|
111
|
+
```
|
|
112
|
+
Confirm `slopDensityScore` is **under 0.5%** (Grade **A+**).
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"should_trigger": [
|
|
3
|
+
"Help me generate a PR title and description for merging feature/user-auth into main",
|
|
4
|
+
"Draft a clean, bulleted Pull Request description with no AI slop",
|
|
5
|
+
"Ask me for source and target branches, then generate concise PR content",
|
|
6
|
+
"Extract git diff and output a structured PR title and body"
|
|
7
|
+
],
|
|
8
|
+
"should_not_trigger": [
|
|
9
|
+
"Perform a code review on this file and report security risks",
|
|
10
|
+
"Run git status to show my current uncommitted changes",
|
|
11
|
+
"Write a git commit message for fixing the crash bug",
|
|
12
|
+
"Rewrite this technical blog post to remove AI tells"
|
|
13
|
+
]
|
|
14
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skill_name": "neo-pr",
|
|
3
|
+
"evals": [
|
|
4
|
+
{
|
|
5
|
+
"id": 1,
|
|
6
|
+
"prompt": "Generate a concise, non-AI-slop PR title and description for merging feature/user-auth into main.",
|
|
7
|
+
"expected_output": "A PR title adhering to Conventional Commits format under '標題:', and a bulleted markdown PR description under '內容:' with no AI fluff phrases.",
|
|
8
|
+
"assertions": [
|
|
9
|
+
"PR Title complies with Conventional Commits format under 標題:",
|
|
10
|
+
"PR Description includes bullet points summarizing key changes under 內容:",
|
|
11
|
+
"Content is structured strictly with bullet points",
|
|
12
|
+
"Does not contain AI tells like 'It is worth noting that' or 'This PR aims to'"
|
|
13
|
+
]
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# PR Title & Description Standard Reference
|
|
2
|
+
|
|
3
|
+
This document serves as the standard PR output template and Anti-Slop writing reference for the `neo-pr` skill.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. PR Title Standard (Conventional Commits)
|
|
8
|
+
|
|
9
|
+
Titles must be clear, concise, and directly reflect the underlying changes using Conventional Commits format:
|
|
10
|
+
|
|
11
|
+
`<type>(<scope>): <description>`
|
|
12
|
+
|
|
13
|
+
### Common Types:
|
|
14
|
+
* `feat`: A new feature
|
|
15
|
+
* `fix`: A bug fix
|
|
16
|
+
* `refactor`: A code change that neither fixes a bug nor adds a feature
|
|
17
|
+
* `docs`: Documentation changes only
|
|
18
|
+
* `test`: Adding missing tests or correcting existing tests
|
|
19
|
+
* `chore`: Changes to the build process, auxiliary tools, or dependencies
|
|
20
|
+
* `perf`: A code change that improves performance
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 2. PR Description Template
|
|
25
|
+
|
|
26
|
+
The PR output format must strictly follow:
|
|
27
|
+
|
|
28
|
+
```markdown
|
|
29
|
+
標題:
|
|
30
|
+
<type>(<scope>): <short summary>
|
|
31
|
+
|
|
32
|
+
內容:
|
|
33
|
+
- **[重要變更/關鍵模組 1]**:說明具體調整內容與目的。
|
|
34
|
+
- **[重要變更/關鍵模組 2]**:說明具體調整內容與目的。
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## 3. Anti-Slop Conversion Table
|
|
40
|
+
|
|
41
|
+
When drafting PR descriptions, rigorously filter out filler words according to the following mapping:
|
|
42
|
+
|
|
43
|
+
| ❌ Fluff Phrase | ⭕ Clean Alternative | Explanation |
|
|
44
|
+
| :--- | :--- | :--- |
|
|
45
|
+
| It is worth noting that this PR refactors auth logic. | 重構驗證邏輯,改用統一中介軟體。 | Delete throat-clearing openers; use direct action verbs. |
|
|
46
|
+
| This PR aims to resolve a potential crash during login. | 修復登入時因 null 使用者引發的閃退問題。 | Omit "This PR aims to"; state goal and root cause directly. |
|
|
47
|
+
| In summary, this change seamlessly boosts system performance. | 減少 DB 查詢,降低 API 延遲 40ms。 | Replace "seamlessly" with concrete metrics. |
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# /// script
|
|
2
|
+
# dependencies = []
|
|
3
|
+
# ///
|
|
4
|
+
|
|
5
|
+
"""
|
|
6
|
+
git-pr-extractor.py
|
|
7
|
+
|
|
8
|
+
Non-interactive Git diff and commit extraction script.
|
|
9
|
+
Given target_branch and source_branch, fetches Git logs, changed files, and diff summary,
|
|
10
|
+
then outputs JSON formatted data to stdout.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import argparse
|
|
14
|
+
import json
|
|
15
|
+
import os
|
|
16
|
+
import subprocess
|
|
17
|
+
import sys
|
|
18
|
+
|
|
19
|
+
def run_command(cmd, cwd=None):
|
|
20
|
+
result = subprocess.run(
|
|
21
|
+
cmd,
|
|
22
|
+
cwd=cwd,
|
|
23
|
+
stdout=subprocess.PIPE,
|
|
24
|
+
stderr=subprocess.PIPE,
|
|
25
|
+
text=True
|
|
26
|
+
)
|
|
27
|
+
return result.returncode, result.stdout, result.stderr
|
|
28
|
+
|
|
29
|
+
def main():
|
|
30
|
+
parser = argparse.ArgumentParser(description="Extract git diff and commit information for PR generation.")
|
|
31
|
+
parser.add_argument("--target-branch", default="main", help="Target base branch (e.g. main, develop)")
|
|
32
|
+
parser.add_argument("--source-branch", default="HEAD", help="Source feature branch (e.g. feature/auth, HEAD)")
|
|
33
|
+
parser.add_argument("--repo-path", default=".", help="Path to git repository")
|
|
34
|
+
parser.add_argument("--max-diff-lines", type=int, default=500, help="Maximum lines of diff to include")
|
|
35
|
+
|
|
36
|
+
args = parser.parse_args()
|
|
37
|
+
repo_path = os.path.abspath(args.repo_path)
|
|
38
|
+
|
|
39
|
+
# Verify if directory is inside a valid Git workspace
|
|
40
|
+
code, out, err = run_command(["git", "rev-parse", "--is-inside-work-tree"], cwd=repo_path)
|
|
41
|
+
if code != 0:
|
|
42
|
+
sys.stderr.write(f"Error: Path {repo_path} is not a valid git repository.\n{err}")
|
|
43
|
+
sys.exit(1)
|
|
44
|
+
|
|
45
|
+
# Retrieve current branch name for fallback reference
|
|
46
|
+
_, current_branch, _ = run_command(["git", "rev-parse", "--abbrev-ref", "HEAD"], cwd=repo_path)
|
|
47
|
+
current_branch = current_branch.strip()
|
|
48
|
+
|
|
49
|
+
source = args.source_branch
|
|
50
|
+
if source == "HEAD":
|
|
51
|
+
source_name = current_branch
|
|
52
|
+
else:
|
|
53
|
+
source_name = source
|
|
54
|
+
|
|
55
|
+
target = args.target_branch
|
|
56
|
+
rev_range = f"{target}..{source}"
|
|
57
|
+
|
|
58
|
+
# 1. Fetch Commit History
|
|
59
|
+
code, log_out, log_err = run_command(["git", "log", rev_range, "--oneline"], cwd=repo_path)
|
|
60
|
+
if code != 0:
|
|
61
|
+
sys.stderr.write(f"Error executing git log for range {rev_range}:\n{log_err}")
|
|
62
|
+
sys.exit(1)
|
|
63
|
+
|
|
64
|
+
commits = [line.strip() for line in log_out.strip().split("\n") if line.strip()]
|
|
65
|
+
|
|
66
|
+
# 2. Fetch git diff --stat Summary
|
|
67
|
+
_, stat_out, _ = run_command(["git", "diff", rev_range, "--stat"], cwd=repo_path)
|
|
68
|
+
|
|
69
|
+
# 3. Fetch List of Modified Files
|
|
70
|
+
_, name_status_out, _ = run_command(["git", "diff", rev_range, "--name-status"], cwd=repo_path)
|
|
71
|
+
changed_files = []
|
|
72
|
+
for line in name_status_out.strip().split("\n"):
|
|
73
|
+
if line.strip():
|
|
74
|
+
parts = line.strip().split(maxsplit=1)
|
|
75
|
+
if len(parts) == 2:
|
|
76
|
+
changed_files.append({"status": parts[0], "file": parts[1]})
|
|
77
|
+
|
|
78
|
+
# 4. Fetch Truncated Git Diff Output (Prevents Token Overhead)
|
|
79
|
+
_, diff_out, _ = run_command(["git", "diff", rev_range], cwd=repo_path)
|
|
80
|
+
diff_lines = diff_out.split("\n")
|
|
81
|
+
is_truncated = len(diff_lines) > args.max_diff_lines
|
|
82
|
+
short_diff = "\n".join(diff_lines[:args.max_diff_lines])
|
|
83
|
+
|
|
84
|
+
output_data = {
|
|
85
|
+
"repository_path": repo_path,
|
|
86
|
+
"target_branch": target,
|
|
87
|
+
"source_branch": source_name,
|
|
88
|
+
"commit_count": len(commits),
|
|
89
|
+
"commits": commits,
|
|
90
|
+
"stat_summary": stat_out.strip(),
|
|
91
|
+
"changed_files": changed_files,
|
|
92
|
+
"diff_snippet": short_diff,
|
|
93
|
+
"diff_truncated": is_truncated
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
# Output JSON string exclusively to stdout
|
|
97
|
+
print(json.dumps(output_data, ensure_ascii=False, indent=2))
|
|
98
|
+
|
|
99
|
+
if __name__ == "__main__":
|
|
100
|
+
main()
|