shiftblame 1.0.1 → 1.2.0
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/.claude/agents/{L2_DEV_be.md → DEV-be.md} +6 -6
- package/.claude/agents/{L2_DEV_db.md → DEV-db.md} +6 -6
- package/.claude/agents/{L2_DEV_fe.md → DEV-fe.md} +5 -5
- package/.claude/agents/{L2_DEV_LEAD.md → DEV.md} +27 -25
- package/.claude/agents/MIS-cicd.md +140 -0
- package/.claude/agents/MIS-cloud.md +100 -0
- package/.claude/agents/MIS-infra.md +107 -0
- package/.claude/agents/MIS.md +132 -0
- package/.claude/agents/PRD-arch.md +71 -0
- package/.claude/agents/PRD-market.md +70 -0
- package/.claude/agents/PRD-plan.md +75 -0
- package/.claude/agents/PRD.md +109 -0
- package/.claude/agents/{L2_QA_e2e.md → QA-e2e.md} +5 -5
- package/.claude/agents/{L2_QA_integ.md → QA-integ.md} +5 -5
- package/.claude/agents/{L2_QA_unit.md → QA-unit.md} +5 -5
- package/.claude/agents/{L2_QA_LEAD.md → QA.md} +26 -24
- package/.claude/agents/QC-test.md +96 -0
- package/.claude/agents/{L3_SEC_consistency.md → QC-uni.md} +16 -16
- package/.claude/agents/{L3_QC_user.md → QC-user.md} +7 -7
- package/.claude/agents/QC.md +138 -0
- package/.claude/agents/{L3_SEC_blue.md → SEC-blue.md} +11 -11
- package/.claude/agents/{L3_SEC_red.md → SEC-red.md} +11 -11
- package/.claude/agents/SEC-white.md +103 -0
- package/.claude/agents/SEC.md +164 -0
- package/.claude/agents/SECRETARY.md +44 -0
- package/.claude/commands/secretary.md +9 -0
- package/.claude/skills/blame-init/SKILL.md +49 -36
- package/.claude/skills/blame-reflect/SKILL.md +6 -6
- package/README.md +41 -58
- package/package.json +3 -2
- package/scripts/postinstall.js +72 -8
- package/scripts/preuninstall.js +81 -0
- package/.claude/agents/L1_ADM_LEAD.md +0 -177
- package/.claude/agents/L1_AUTO_LEAD.md +0 -131
- package/.claude/agents/L1_AUTO_cd.md +0 -84
- package/.claude/agents/L1_AUTO_ci.md +0 -136
- package/.claude/agents/L1_MIS_LEAD.md +0 -150
- package/.claude/agents/L1_OPS_LEAD.md +0 -136
- package/.claude/agents/L1_OPS_cloud.md +0 -140
- package/.claude/agents/L1_OPS_infra.md +0 -128
- package/.claude/agents/L2_PM_LEAD.md +0 -79
- package/.claude/agents/L3_ARC_LEAD.md +0 -81
- package/.claude/agents/L3_MKT_LEAD.md +0 -142
- package/.claude/agents/L3_PRD_LEAD.md +0 -77
- package/.claude/agents/L3_QC_LEAD.md +0 -131
- package/.claude/agents/L3_QC_edge.md +0 -80
- package/.claude/agents/L3_QC_fuzz.md +0 -89
- package/.claude/agents/L3_SEC_LEAD.md +0 -179
- package/.claude/agents/L3_SEC_audit.md +0 -104
- package/.claude/skills/secretary/SKILL.md +0 -332
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: SEC
|
|
3
|
+
description: 資安主管。調度環境準備與紅藍隊,綜合研判回傳 ACCEPTED / REJECTED / ALERT。
|
|
4
|
+
tools: Read, Write, Edit, Grep, Glob, Bash, Agent
|
|
5
|
+
model: haiku
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
做資安:調度白隊(工具審核)與紅藍隊(安全掃描),綜合研判回傳最終安全結論。
|
|
9
|
+
標籤:SEC
|
|
10
|
+
產出:安全報告
|
|
11
|
+
- 團隊歷史:`~/.shiftblame/<repo>/SEC/`
|
|
12
|
+
- 自己的鍋:`~/.shiftblame/blame/SEC/BLAME.md`
|
|
13
|
+
- 工程師的鍋(子資料夾):
|
|
14
|
+
- `~/.shiftblame/blame/SEC/white/BLAME.md`
|
|
15
|
+
- `~/.shiftblame/blame/SEC/red/BLAME.md`
|
|
16
|
+
- `~/.shiftblame/blame/SEC/blue/BLAME.md`
|
|
17
|
+
|
|
18
|
+
## 定位
|
|
19
|
+
資安主管。管理三個下屬:白隊(工具審核)、紅隊(攻擊)、藍隊(防禦)。白隊在環境階段審核 MIS-infra 的工具安裝需求,紅藍隊在安全階段做攻防掃描,綜合研判回傳 ACCEPTED / REJECTED / ALERT。
|
|
20
|
+
|
|
21
|
+
## 為什麼這層存在
|
|
22
|
+
如果拿掉這層:工具安裝無安全把關、攻防兩個面向各自為戰,沒有人做交叉比對和最終研判。
|
|
23
|
+
核心問題:統籌工具安全 + 攻防安全,做出最終判斷。
|
|
24
|
+
|
|
25
|
+
## 唯一職責
|
|
26
|
+
1. 接收秘書交棒
|
|
27
|
+
2. 環境階段:啟動 SEC-white 審核 MIS-infra 的工具安裝清單
|
|
28
|
+
3. 安全階段:啟動 SEC-red / SEC-blue 做安全掃描
|
|
29
|
+
4. 收合報告
|
|
30
|
+
5. 綜合研判
|
|
31
|
+
6. 產出安全報告 → `~/.shiftblame/<repo>/SEC/<slug>.md`
|
|
32
|
+
7. 回傳 ACCEPTED / REJECTED / ALERT
|
|
33
|
+
|
|
34
|
+
## 輸入
|
|
35
|
+
### 環境階段(MIS-infra 盤點後)
|
|
36
|
+
`slug`、`MIS-infra 提交的工具安裝清單`。
|
|
37
|
+
|
|
38
|
+
### worktree 階段(QC 之後)
|
|
39
|
+
`Worktree 路徑`、`分支名稱`(`shiftblame/<slug>`)、`slug`。
|
|
40
|
+
|
|
41
|
+
### main 階段(合併後)
|
|
42
|
+
`合併後 main HEAD`、`主 repo 路徑`。
|
|
43
|
+
|
|
44
|
+
## 工具權限
|
|
45
|
+
- ✅ Agent:啟動 white / red / blue 三個下屬
|
|
46
|
+
- ✅ Read / Grep / Glob:讀各部門產出
|
|
47
|
+
- ✅ Write:只寫 `~/.shiftblame/<repo>/SEC/<slug>.md` 與 `~/.shiftblame/blame/SEC/BLAME.md`
|
|
48
|
+
|
|
49
|
+
## 工作流程
|
|
50
|
+
|
|
51
|
+
### 1. 歷史參考
|
|
52
|
+
- Glob `~/.shiftblame/<repo>/SEC/*.md` 看過去的報告
|
|
53
|
+
- Read `~/.shiftblame/blame/SEC/BLAME.md`(若存在)
|
|
54
|
+
|
|
55
|
+
### 2. 工具審核(MIS-infra 盤點後,安裝前)
|
|
56
|
+
使用 Agent 工具啟動 SEC-white:
|
|
57
|
+
- `SEC-white`:審核 MIS-infra 提交的工具安裝清單
|
|
58
|
+
- 收回 APPROVED → 通知秘書,MIS-infra 可開始安裝
|
|
59
|
+
- 收回 REJECTED → 回報秘書,退回 MIS-infra 替換工具
|
|
60
|
+
|
|
61
|
+
### 3. 啟動紅藍隊(main 上,合併後)
|
|
62
|
+
使用 Agent 工具啟動,按任務複雜度分配模型(預設 sonnet,複雜度 ≥ 80 用 opus):
|
|
63
|
+
- `SEC-red`:攻擊方
|
|
64
|
+
- `SEC-blue`:防禦方
|
|
65
|
+
|
|
66
|
+
兩隊獨立作業,互不知對方結果。
|
|
67
|
+
|
|
68
|
+
### 4. 收合紅藍隊報告 + 綜合研判
|
|
69
|
+
- 紅隊找到的漏洞,藍隊有沒有偵測到?(防禦盲區)
|
|
70
|
+
- 藍隊掃到的風險,紅隊有沒有成功利用?(威脅等級)
|
|
71
|
+
- 綜合判斷安全等級
|
|
72
|
+
|
|
73
|
+
### 5. 寫安全報告
|
|
74
|
+
Write `~/.shiftblame/<repo>/SEC/<slug>.md`(格式見下)。
|
|
75
|
+
|
|
76
|
+
### 6. 回傳結論
|
|
77
|
+
- 安全無虞 → **ACCEPTED**
|
|
78
|
+
- 安全有嚴重漏洞 → **REJECTED**(附退回對象)
|
|
79
|
+
- 安全有疑慮但可接受 → **ALERT**
|
|
80
|
+
|
|
81
|
+
## 安全報告格式
|
|
82
|
+
```markdown
|
|
83
|
+
# 安全報告 · <slug>
|
|
84
|
+
|
|
85
|
+
## Part A:工具審核
|
|
86
|
+
(SEC-white 回報,僅環境階段產出)
|
|
87
|
+
- 審核結果:[APPROVED / REJECTED]
|
|
88
|
+
- 工具清單:...
|
|
89
|
+
|
|
90
|
+
## Part B:紅隊報告
|
|
91
|
+
(SEC-red 回報)
|
|
92
|
+
- 嘗試攻擊向量:<清單>
|
|
93
|
+
- 成功突破:<清單或「無」>
|
|
94
|
+
|
|
95
|
+
## Part C:藍隊報告
|
|
96
|
+
(SEC-blue 回報)
|
|
97
|
+
- 依賴審計:[安全 / 有漏洞]
|
|
98
|
+
- 敏感檔案:[安全 / 有問題]
|
|
99
|
+
- OWASP 防禦:[通過 / 風險]
|
|
100
|
+
|
|
101
|
+
## Part D:紅藍對照
|
|
102
|
+
- 防禦盲區:<紅隊找到但藍隊未偵測>
|
|
103
|
+
- 威脅等級:<藍隊掃到但紅隊未利用>
|
|
104
|
+
|
|
105
|
+
## Part E:結論
|
|
106
|
+
|
|
107
|
+
**[ACCEPTED]** / **[REJECTED]** / **[ALERT]**
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## 決策原則
|
|
111
|
+
- 紅隊嚴重突破 → REJECTED → 退回 DEV 修復
|
|
112
|
+
- 紅隊突破 + 嚴重 → ALERT
|
|
113
|
+
- 全部安全 → ACCEPTED
|
|
114
|
+
|
|
115
|
+
## 自主決策範圍
|
|
116
|
+
可以自行決定(不需回報):下屬啟動順序、報告詳細程度。
|
|
117
|
+
必須回報:REJECTED(附退回對象)、ALERT(附風險清單)。
|
|
118
|
+
|
|
119
|
+
## 嚴禁
|
|
120
|
+
- ❌ 自己直接跑掃描(必須透過下屬)
|
|
121
|
+
- ❌ 修改程式碼或測試
|
|
122
|
+
- ❌ 執行合併(合併由 MIS-cicd 負責)
|
|
123
|
+
- ❌ 跳過任何下屬的報告
|
|
124
|
+
- ❌ 過度嚴苛或過度放水
|
|
125
|
+
|
|
126
|
+
## 回傳(ACCEPTED)
|
|
127
|
+
```
|
|
128
|
+
## SEC 交付
|
|
129
|
+
🔍 安全報告:~/.shiftblame/<repo>/SEC/<slug>.md
|
|
130
|
+
🎉 結論:ACCEPTED
|
|
131
|
+
安全:PASS
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## 回傳(REJECTED)
|
|
135
|
+
```
|
|
136
|
+
## SEC 交付
|
|
137
|
+
🔍 安全報告:~/.shiftblame/<repo>/SEC/<slug>.md
|
|
138
|
+
❌ 結論:REJECTED
|
|
139
|
+
安全風險:<具體清單>
|
|
140
|
+
退回對象:<部門> — <原因>
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## 回傳(ALERT)
|
|
144
|
+
```
|
|
145
|
+
## SEC 交付
|
|
146
|
+
🔍 安全報告:~/.shiftblame/<repo>/SEC/<slug>.md
|
|
147
|
+
⚠️ 結論:ALERT
|
|
148
|
+
安全風險:<具體清單>
|
|
149
|
+
請鍋長轉告老闆決定是否繼續部署。
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## 犯錯處理
|
|
153
|
+
在 `~/.shiftblame/blame/SEC/BLAME.md` 附加新條目(Read → 檔頭插入 → Write 回去):
|
|
154
|
+
```markdown
|
|
155
|
+
## <slug> · <YYYY-MM-DD>
|
|
156
|
+
**犯了什麼錯**:...
|
|
157
|
+
**怎麼被抓的**:...
|
|
158
|
+
**本質原因**:...
|
|
159
|
+
**背後的機制**:為什麼這個原因會導致這個錯?結構上是什麼在壞?
|
|
160
|
+
**下次怎麼避免**:...(具體 rule)
|
|
161
|
+
**為什麼這條規則有效**:這條規則在什麼條件下成立?什麼情境下會失效?
|
|
162
|
+
**要改什麼**:...
|
|
163
|
+
---
|
|
164
|
+
```
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: SECRETARY
|
|
3
|
+
description: 老闆的貼身秘書。協助釐清方向、路由需求、預審閘門、對照原話、文件聚合。
|
|
4
|
+
tools: Read, Write, Edit, Grep, Glob, Bash, Agent, Skill
|
|
5
|
+
model: sonnet
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
老闆的貼身秘書(推鍋鍋長)。五件事:
|
|
9
|
+
1. 老闆還沒想清楚時,幫他釐清方向(諮詢模式)
|
|
10
|
+
2. 掃描 agents 目錄,把需求推給對的部門(動態調度)
|
|
11
|
+
3. 每個部門啟動前翻成人話請老闆預審(老闆只回 OK / 不 OK)
|
|
12
|
+
4. 收好老闆原話,完成後親自對照產物,彙報達成進度
|
|
13
|
+
5. 完成後做文件聚合
|
|
14
|
+
|
|
15
|
+
標籤:SECRETARY
|
|
16
|
+
產出:對照報告 + 文件聚合
|
|
17
|
+
- 自己的鍋:`~/.shiftblame/blame/SECRETARY/BLAME.md`
|
|
18
|
+
|
|
19
|
+
## 定位
|
|
20
|
+
秘書是鍋長。不動手寫 code 或產出文件(唯一例外:老闆明示直接修改)。只負責判斷、路由、預審、對照、聚合。
|
|
21
|
+
|
|
22
|
+
## 可調用 Skill
|
|
23
|
+
- `Skill("blame-init")`:初始化推鍋環境(`.shiftblame/` 不存在或結構過時時自動呼叫)
|
|
24
|
+
- `Skill("blame-reflect")`:聚合各部門鍋紀錄,提煉常識與認知
|
|
25
|
+
|
|
26
|
+
## 文件聚合
|
|
27
|
+
完成後對 `~/.shiftblame/<repo>/` 的各部門目錄進行文件聚合:
|
|
28
|
+
- 掃描各部門目錄
|
|
29
|
+
- 每個目錄保留最新 3 筆 STM,其餘聚合至 REPO.md
|
|
30
|
+
- 即使少於 3 筆仍聚合(原檔保留不刪)
|
|
31
|
+
|
|
32
|
+
## 犯錯處理
|
|
33
|
+
在 `~/.shiftblame/blame/SECRETARY/BLAME.md` 附加新條目(Read → 檔頭插入 → Write 回去):
|
|
34
|
+
```markdown
|
|
35
|
+
## <slug> · <YYYY-MM-DD>
|
|
36
|
+
**犯了什麼錯**:...
|
|
37
|
+
**怎麼被抓的**:...
|
|
38
|
+
**本質原因**:...
|
|
39
|
+
**背後的機制**:為什麼這個原因會導致這個錯?結構上是什麼在壞?
|
|
40
|
+
**下次怎麼避免**:...(具體 rule)
|
|
41
|
+
**為什麼這條規則有效**:這條規則在什麼條件下成立?什麼情境下會失效?
|
|
42
|
+
**要改什麼**:...
|
|
43
|
+
---
|
|
44
|
+
```
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: blame-init
|
|
3
3
|
description: >-
|
|
4
|
-
初始化推鍋環境。建立 ~/.shiftblame/ 資料夾結構、repo symlink、.gitignore 檢查、commit 並推送。
|
|
4
|
+
初始化推鍋環境。建立 ~/.shiftblame/ 資料夾結構、REPO.md、repo symlink、.gitignore 檢查、commit 並推送。
|
|
5
5
|
Use this skill when: the repo has no .shiftblame/ directory, or when the user says "初始化", "init", "/blame-init".
|
|
6
6
|
---
|
|
7
7
|
|
|
@@ -21,36 +21,24 @@ REPO_NAME=$(basename "$REPO_ROOT")
|
|
|
21
21
|
|
|
22
22
|
#### blame 目錄(跨 repo 共用)
|
|
23
23
|
```bash
|
|
24
|
-
#
|
|
25
|
-
mkdir -p ~/.shiftblame/blame/
|
|
26
|
-
mkdir -p ~/.shiftblame/blame/
|
|
27
|
-
|
|
28
|
-
mkdir -p ~/.shiftblame/blame/
|
|
29
|
-
#
|
|
30
|
-
mkdir -p ~/.shiftblame/blame/
|
|
31
|
-
mkdir -p ~/.shiftblame/blame/
|
|
32
|
-
mkdir -p ~/.shiftblame/blame/
|
|
33
|
-
# L3
|
|
34
|
-
mkdir -p ~/.shiftblame/blame/L3/PRD/LEAD
|
|
35
|
-
mkdir -p ~/.shiftblame/blame/L3/ARC/LEAD
|
|
36
|
-
mkdir -p ~/.shiftblame/blame/L3/MKT/LEAD
|
|
37
|
-
mkdir -p ~/.shiftblame/blame/L3/QC/{LEAD,edge,fuzz,user}
|
|
38
|
-
mkdir -p ~/.shiftblame/blame/L3/SEC/{LEAD,audit,consistency,red,blue}
|
|
24
|
+
# 開發執行
|
|
25
|
+
mkdir -p ~/.shiftblame/blame/DEV/{fe,be,db}
|
|
26
|
+
mkdir -p ~/.shiftblame/blame/QA/{unit,integ,e2e}
|
|
27
|
+
# 支援與維運
|
|
28
|
+
mkdir -p ~/.shiftblame/blame/MIS/{infra,cicd,cloud}
|
|
29
|
+
# 規劃決策
|
|
30
|
+
mkdir -p ~/.shiftblame/blame/PRD/{plan,arch,market}
|
|
31
|
+
mkdir -p ~/.shiftblame/blame/QC/{test,uni,user}
|
|
32
|
+
mkdir -p ~/.shiftblame/blame/SEC/{red,white,blue}
|
|
39
33
|
# 特殊
|
|
40
|
-
mkdir -p ~/.shiftblame/blame/
|
|
41
|
-
mkdir -p ~/.shiftblame/blame/boss
|
|
34
|
+
mkdir -p ~/.shiftblame/blame/SECRETARY
|
|
42
35
|
```
|
|
43
36
|
|
|
44
37
|
#### repo 文件目錄(per repo)
|
|
45
38
|
```bash
|
|
46
|
-
|
|
47
|
-
mkdir -p ~/.shiftblame/"$REPO_NAME"/
|
|
48
|
-
|
|
49
|
-
mkdir -p ~/.shiftblame/"$REPO_NAME"/L2/{PM,DEV,QA}
|
|
50
|
-
# L3
|
|
51
|
-
mkdir -p ~/.shiftblame/"$REPO_NAME"/L3/{PRD,ARC,MKT,QC,SEC}
|
|
52
|
-
# report
|
|
53
|
-
mkdir -p ~/.shiftblame/"$REPO_NAME"/report
|
|
39
|
+
mkdir -p ~/.shiftblame/"$REPO_NAME"/{MIS}
|
|
40
|
+
mkdir -p ~/.shiftblame/"$REPO_NAME"/{DEV,QA}
|
|
41
|
+
mkdir -p ~/.shiftblame/"$REPO_NAME"/{PRD,QC,SEC}
|
|
54
42
|
```
|
|
55
43
|
|
|
56
44
|
### 3. 建立 repo 內 symlink
|
|
@@ -60,7 +48,32 @@ ln -sfn ~/.shiftblame/"$REPO_NAME" "$REPO_ROOT/.shiftblame/$REPO_NAME"
|
|
|
60
48
|
ln -sfn ~/.shiftblame/blame "$REPO_ROOT/.shiftblame/blame"
|
|
61
49
|
```
|
|
62
50
|
|
|
63
|
-
### 4.
|
|
51
|
+
### 4. 建立 REPO.md(專案長期記憶)
|
|
52
|
+
|
|
53
|
+
在 `~/.shiftblame/$REPO_NAME/REPO.md` 建立專案長期記憶檔案。若已存在則跳過。
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
REPO_MD=~/.shiftblame/"$REPO_NAME"/REPO.md
|
|
57
|
+
if [ ! -f "$REPO_MD" ]; then
|
|
58
|
+
cat > "$REPO_MD" << EOF
|
|
59
|
+
# $REPO_NAME — REPO.md
|
|
60
|
+
|
|
61
|
+
## 專案簡介
|
|
62
|
+
(待填寫)
|
|
63
|
+
|
|
64
|
+
## 技術棧
|
|
65
|
+
(待填寫)
|
|
66
|
+
|
|
67
|
+
## 進行中
|
|
68
|
+
(待填寫)
|
|
69
|
+
EOF
|
|
70
|
+
echo "✅ REPO.md 已建立"
|
|
71
|
+
else
|
|
72
|
+
echo "⏭️ REPO.md 已存在,跳過"
|
|
73
|
+
fi
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### 5. 檢查 .gitignore
|
|
64
77
|
|
|
65
78
|
確認 `.gitignore` 存在且包含必要項目:
|
|
66
79
|
|
|
@@ -84,7 +97,7 @@ done
|
|
|
84
97
|
|
|
85
98
|
若格式不對(例如項目被黏在其他行後面),修正為每項獨立一行。
|
|
86
99
|
|
|
87
|
-
###
|
|
100
|
+
### 6. Commit 並推送
|
|
88
101
|
|
|
89
102
|
```bash
|
|
90
103
|
cd "$REPO_ROOT"
|
|
@@ -99,7 +112,7 @@ fi
|
|
|
99
112
|
|
|
100
113
|
若 `.gitignore` 沒有變更(已經正確),跳過 commit。
|
|
101
114
|
|
|
102
|
-
###
|
|
115
|
+
### 7. 回報結果
|
|
103
116
|
|
|
104
117
|
```
|
|
105
118
|
✅ shiftblame:init 完成
|
|
@@ -108,14 +121,14 @@ symlink:
|
|
|
108
121
|
.shiftblame/<repo> → ~/.shiftblame/<repo>/
|
|
109
122
|
.shiftblame/blame → ~/.shiftblame/blame/
|
|
110
123
|
|
|
124
|
+
REPO.md:[已建立 / 已存在]
|
|
125
|
+
|
|
111
126
|
目錄結構:
|
|
112
|
-
blame/
|
|
113
|
-
blame/
|
|
114
|
-
|
|
115
|
-
<repo>/
|
|
116
|
-
<repo>/
|
|
117
|
-
<repo>/L3/{PRD,ARC,MKT,QC,SEC}/
|
|
118
|
-
<repo>/report/
|
|
127
|
+
blame/{DEV,MIS,PRD,QA,QC,SEC}/...
|
|
128
|
+
blame/SECRETARY/
|
|
129
|
+
<repo>/{MIS}/
|
|
130
|
+
<repo>/{DEV,QA}/
|
|
131
|
+
<repo>/{PRD,QC,SEC}/
|
|
119
132
|
|
|
120
133
|
.gitignore:✓ 已包含 .shiftblame/ 和 .worktree/
|
|
121
134
|
commit:[已推送 / 無需變更]
|
|
@@ -11,7 +11,7 @@ description: >-
|
|
|
11
11
|
|
|
12
12
|
## 聚合邏輯
|
|
13
13
|
|
|
14
|
-
對每個 `~/.shiftblame/blame/<
|
|
14
|
+
對每個 `~/.shiftblame/blame/<DEPT>/<role>/BLAME.md`:
|
|
15
15
|
|
|
16
16
|
1. 掃描所有 `## <slug> · <YYYY-MM-DD>` 區塊
|
|
17
17
|
2. 提煉「下次怎麼避免」→ **常識(規則)**
|
|
@@ -43,7 +43,7 @@ find ~/.shiftblame/blame/ -name 'BLAME.md' -size +0c
|
|
|
43
43
|
|
|
44
44
|
格式:
|
|
45
45
|
```markdown
|
|
46
|
-
# <
|
|
46
|
+
# <DEPT>/<role> 鍋紀錄
|
|
47
47
|
|
|
48
48
|
## 常識(規則)
|
|
49
49
|
|
|
@@ -74,9 +74,9 @@ find ~/.shiftblame/blame/ -name 'BLAME.md' -size +0c
|
|
|
74
74
|
✅ shiftblame:reflect 完成
|
|
75
75
|
|
|
76
76
|
已更新 X 個 BLAME.md:
|
|
77
|
-
-
|
|
78
|
-
-
|
|
79
|
-
-
|
|
77
|
+
- DEV/fe:N 條常識 / M 條認知
|
|
78
|
+
- MIS/infra:N 條常識 / M 條認知
|
|
79
|
+
- SEC/red:N 條常識 / M 條認知
|
|
80
80
|
- ...
|
|
81
81
|
跳過(空檔案):Y 個
|
|
82
82
|
```
|
|
@@ -84,4 +84,4 @@ find ~/.shiftblame/blame/ -name 'BLAME.md' -size +0c
|
|
|
84
84
|
## 注意事項
|
|
85
85
|
- 只處理 `~/.shiftblame/blame/` 下的檔案
|
|
86
86
|
- 不修改任何 repo 內的檔案
|
|
87
|
-
- `
|
|
87
|
+
- `SECRETARY/BLAME.md` 也要處理(不在各部門目錄下)
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
|
|
3
|
-
#
|
|
3
|
+
# shiftblame
|
|
4
4
|
|
|
5
5
|
### 推鍋
|
|
6
6
|
|
|
@@ -8,7 +8,7 @@ _一套明確責任歸屬的 Agents 開發框架_
|
|
|
8
8
|
|
|
9
9
|
[](./LICENSE)
|
|
10
10
|
[](https://claude.com/claude-code)
|
|
11
|
-
[](#資源供給機制)
|
|
12
12
|
[](#)
|
|
13
13
|
|
|
14
14
|
> _「這不是我的鍋。」_
|
|
@@ -25,25 +25,20 @@ _一套明確責任歸屬的 Agents 開發框架_
|
|
|
25
25
|
|
|
26
26
|
---
|
|
27
27
|
|
|
28
|
-
##
|
|
28
|
+
## 資源供給機制
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|------|------|------|------|
|
|
32
|
-
| **L1** | 支援與維運 | **haiku** | MIS、ADM、OPS(+cloud、infra)、AUTO(+ci、cd) |
|
|
33
|
-
| **L2** | 開發執行 | **sonnet** | PM、DEV(+fe、be、db)、QA(+unit、integ、e2e) |
|
|
34
|
-
| **L3** | 規劃決策 | **opus** | PRD、ARC、MKT、QC(+edge、fuzz、user)、SEC(+audit、consistency、red、blue) |
|
|
30
|
+
模型分配**按角色類型**,不按部門層級:
|
|
35
31
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
32
|
+
| 角色類型 | 模型 | 對象 |
|
|
33
|
+
|----------|------|------|
|
|
34
|
+
| **管理層**(調度 sub-agent) | **haiku** | PRD、DEV、QA、QC、SEC、MIS |
|
|
35
|
+
| **執行職級**(sub-agent) | **sonnet**(預設)/**opus**(複雜度 ≥ 80) | 由主管按任務複雜度分配 |
|
|
39
36
|
|
|
40
|
-
|
|
37
|
+
---
|
|
41
38
|
|
|
42
|
-
|
|
39
|
+
## 誰的鍋
|
|
43
40
|
|
|
44
|
-
|
|
45
|
-
|------|------------------|----------|
|
|
46
|
-
| **老闆明示直接修改**:親口說「直接改」「不用跑流程」 | 老闆下令跳過流程,改壞了自己扛。commit 以 `BOSS-HOTFIX:` 為前綴 | `git revert` |
|
|
41
|
+
每個部門都有自己的 `~/.shiftblame/blame/<DEPT>/<role>/BLAME.md`,犯錯就記,下次避雷。
|
|
47
42
|
|
|
48
43
|
### 秘書的鍋
|
|
49
44
|
|
|
@@ -56,18 +51,12 @@ _一套明確責任歸屬的 Agents 開發框架_
|
|
|
56
51
|
|
|
57
52
|
| 部門 | 典型犯錯情境 |
|
|
58
53
|
|------|-------------|
|
|
59
|
-
|
|
|
60
|
-
|
|
|
61
|
-
|
|
|
62
|
-
|
|
|
63
|
-
|
|
|
64
|
-
|
|
|
65
|
-
| L3 QC | e2e 場景遺漏關鍵流程、邊緣/模糊測試不足 |
|
|
66
|
-
| L3 SEC | 該抓的沒抓到(放水)、退回理由不具體、安全掃描遺漏 |
|
|
67
|
-
| L1 OPS | 部署步驟與 ARC 不符、上線後 smoke test 沒跑或漏驗 |
|
|
68
|
-
| L1 AUTO | CI/CD pipeline 配置錯誤、合併出包、rollback 機制失效 |
|
|
69
|
-
| L1 MIS | 環境盤點遺漏、安裝了錯誤版本的工具 |
|
|
70
|
-
| L1 ADM | 聚合遺漏、REPO.md 格式錯亂、誤刪 STM 檔案 |
|
|
54
|
+
| PRD | PRD 漏掉老闆明確提到的需求、自作主張加了老闆沒說的東西、技術選型不可行、市調資料不準確 |
|
|
55
|
+
| QA | 測試涵蓋度不足、拆分任務不當導致測試工程師產出衝突 |
|
|
56
|
+
| DEV | 實作偏離 spec、引入新 bug、拆分任務不當導致工程師產出衝突 |
|
|
57
|
+
| QC | 品管場景遺漏關鍵流程、邊緣/模糊測試不足、一致性遺漏、使用者體驗問題 |
|
|
58
|
+
| SEC | 該抓的沒抓到(放水)、退回理由不具體、安全掃描遺漏 |
|
|
59
|
+
| MIS | 環境盤點遺漏、CI/CD pipeline 配置錯誤、合併出包、部署失敗 |
|
|
71
60
|
|
|
72
61
|
---
|
|
73
62
|
|
|
@@ -119,40 +108,35 @@ _一套明確責任歸屬的 Agents 開發框架_
|
|
|
119
108
|
|
|
120
109
|
| 需求性質 | 推給 |
|
|
121
110
|
|---|---|
|
|
122
|
-
| 全新功能 / 方向性變更 |
|
|
123
|
-
| 技術選型 / 工具比較 |
|
|
124
|
-
| 架構調整 / 技術遷移 |
|
|
125
|
-
| 加細節 / 改驗收條件 |
|
|
126
|
-
| 測試不足 / 要補測試 |
|
|
127
|
-
| 已知 bug / 程式修正 |
|
|
128
|
-
| 使用者體驗問題 |
|
|
129
|
-
| 部署 / 上線方式調整 |
|
|
130
|
-
| 環境 / 工具問題 |
|
|
131
|
-
| CI/CD / 自動化調整 |
|
|
132
|
-
|
|
133
|
-
全新功能的典型路徑:`PRD →
|
|
111
|
+
| 全新功能 / 方向性變更 | PRD |
|
|
112
|
+
| 技術選型 / 工具比較 | PRD |
|
|
113
|
+
| 架構調整 / 技術遷移 | PRD |
|
|
114
|
+
| 加細節 / 改驗收條件 | DEV |
|
|
115
|
+
| 測試不足 / 要補測試 | QA |
|
|
116
|
+
| 已知 bug / 程式修正 | DEV |
|
|
117
|
+
| 使用者體驗問題 | QC |
|
|
118
|
+
| 部署 / 上線方式調整 | MIS |
|
|
119
|
+
| 環境 / 工具問題 | MIS |
|
|
120
|
+
| CI/CD / 自動化調整 | MIS |
|
|
121
|
+
|
|
122
|
+
全新功能的典型路徑:`PRD → MIS(環境) → QA → DEV → QC → SEC(安全) → MIS(合併+部署)`,但秘書可依實際需求動態跳過或新增步驟。
|
|
134
123
|
|
|
135
124
|
### 檔案結構
|
|
136
125
|
|
|
137
126
|
```
|
|
138
127
|
~/.shiftblame/
|
|
139
128
|
├── blame/ # 鍋紀錄(所有 repo 共用)
|
|
140
|
-
│ ├──
|
|
141
|
-
│ ├──
|
|
142
|
-
│ ├──
|
|
143
|
-
│ ├──
|
|
144
|
-
│ ├──
|
|
145
|
-
│ ├──
|
|
146
|
-
│
|
|
147
|
-
│ ├── L3/QC/{LEAD,edge,fuzz,user}/BLAME.md
|
|
148
|
-
│ ├── L3/SEC/{LEAD,audit,consistency,red,blue}/BLAME.md
|
|
149
|
-
│ ├── secretary/BLAME.md
|
|
150
|
-
│ └── boss/BLAME.md
|
|
129
|
+
│ ├── DEV/{fe,be,db}/BLAME.md
|
|
130
|
+
│ ├── MIS/{infra,cicd,cloud}/BLAME.md
|
|
131
|
+
│ ├── PRD/{plan,arch,market}/BLAME.md
|
|
132
|
+
│ ├── QA/{unit,integ,e2e}/BLAME.md
|
|
133
|
+
│ ├── QC/{test,uni,user}/BLAME.md
|
|
134
|
+
│ ├── SEC/{red,white,blue}/BLAME.md
|
|
135
|
+
│ └── SECRETARY/BLAME.md
|
|
151
136
|
└── <repo>/
|
|
152
|
-
├──
|
|
153
|
-
├──
|
|
154
|
-
├──
|
|
155
|
-
├── report/<YYYY-MM-DD_HHMMSS>-<slug>.md
|
|
137
|
+
├── {MIS}/<slug>.md
|
|
138
|
+
├── {DEV,QA}/<slug>.md
|
|
139
|
+
├── {PRD,QC,SEC}/<slug>.md
|
|
156
140
|
└── REPO.md
|
|
157
141
|
|
|
158
142
|
~/.worktree/<repo>/<slug>/ # 共享 worktree
|
|
@@ -229,9 +213,8 @@ npm install shiftblame
|
|
|
229
213
|
1. 掃描 `.claude/agents/` 取得可用部門清單
|
|
230
214
|
2. 保存你的**原話逐字稿**
|
|
231
215
|
3. 每個部門啟動前先用人話告訴你「接下來要做的事」,你回 OK 才繼續
|
|
232
|
-
4.
|
|
233
|
-
5.
|
|
234
|
-
6. 通知 L1 ADM 進行文件聚合
|
|
216
|
+
4. 完成後親自對照原話,呈報「完全達成 X / 部分達成 Y / 未達成 Z」
|
|
217
|
+
5. 完成後親自執行文件聚合
|
|
235
218
|
|
|
236
219
|
你在過程中只需要:
|
|
237
220
|
|
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shiftblame",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "推鍋",
|
|
5
5
|
"scripts": {
|
|
6
|
-
"postinstall": "node scripts/postinstall.js"
|
|
6
|
+
"postinstall": "node scripts/postinstall.js",
|
|
7
|
+
"preuninstall": "node scripts/preuninstall.js"
|
|
7
8
|
},
|
|
8
9
|
"license": "MIT",
|
|
9
10
|
"repository": {
|
package/scripts/postinstall.js
CHANGED
|
@@ -1,26 +1,81 @@
|
|
|
1
1
|
const { execSync } = require("child_process");
|
|
2
2
|
const path = require("path");
|
|
3
3
|
const fs = require("fs");
|
|
4
|
+
const pkg = require("../package.json");
|
|
4
5
|
|
|
5
6
|
const src = path.join(__dirname, "..", ".claude");
|
|
7
|
+
const MANIFEST_NAME = ".shiftblame-manifest.json";
|
|
8
|
+
|
|
6
9
|
const isGlobal = Boolean(
|
|
7
10
|
process.env.npm_config_global === "true" ||
|
|
8
11
|
process.env.npm_config_prefix ===
|
|
9
12
|
execSync("npm config get prefix -g", { encoding: "utf8" }).trim()
|
|
10
13
|
);
|
|
11
14
|
|
|
15
|
+
let dest, installType;
|
|
12
16
|
if (isGlobal) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
console.log("shiftblame: user 級別安裝完成 → ~/.claude/");
|
|
17
|
+
dest = path.join(require("os").homedir(), ".claude");
|
|
18
|
+
installType = "global";
|
|
16
19
|
} else {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
dest = path.join(findProjectRoot(process.cwd()), ".claude");
|
|
21
|
+
installType = "local";
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// 1. 讀舊 manifest
|
|
25
|
+
const manifestPath = path.join(dest, MANIFEST_NAME);
|
|
26
|
+
let oldFiles = [];
|
|
27
|
+
if (fs.existsSync(manifestPath)) {
|
|
28
|
+
try {
|
|
29
|
+
const old = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
|
|
30
|
+
oldFiles = old.files || [];
|
|
31
|
+
} catch (_) {}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// 2. 掃描 src 建立新檔案清單
|
|
35
|
+
const newFiles = [];
|
|
36
|
+
function collectFiles(dir, base) {
|
|
37
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
38
|
+
const rel = base ? base + "/" + entry.name : entry.name;
|
|
39
|
+
if (entry.name === MANIFEST_NAME) continue;
|
|
40
|
+
if (entry.isDirectory()) {
|
|
41
|
+
collectFiles(path.join(dir, entry.name), rel);
|
|
42
|
+
} else {
|
|
43
|
+
newFiles.push(rel);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (fs.existsSync(src)) {
|
|
48
|
+
collectFiles(src, "");
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// 3. 清理舊版殘留(在新版中已不存在的檔案)
|
|
52
|
+
const newSet = new Set(newFiles);
|
|
53
|
+
const staleFiles = oldFiles.filter((f) => !newSet.has(f));
|
|
54
|
+
for (const file of staleFiles) {
|
|
55
|
+
const filePath = path.join(dest, file);
|
|
56
|
+
if (fs.existsSync(filePath)) {
|
|
57
|
+
fs.unlinkSync(filePath);
|
|
58
|
+
}
|
|
21
59
|
}
|
|
60
|
+
// 清理空目錄
|
|
61
|
+
cleanEmptyDirs(dest, dest);
|
|
62
|
+
|
|
63
|
+
// 4. 複製新檔案
|
|
64
|
+
copyRecursive(src, dest);
|
|
22
65
|
|
|
23
|
-
|
|
66
|
+
// 5. 寫入新 manifest
|
|
67
|
+
const manifest = { version: pkg.version, type: installType, files: newFiles };
|
|
68
|
+
fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
|
|
69
|
+
|
|
70
|
+
// 6. 輸出
|
|
71
|
+
const label = isGlobal ? "user 級別" : "repo 級別";
|
|
72
|
+
console.log(`shiftblame: ${label}安裝完成 → ${dest}/`);
|
|
73
|
+
if (staleFiles.length > 0) {
|
|
74
|
+
console.log(`shiftblame: 已清除 ${staleFiles.length} 個舊版殘留檔案`);
|
|
75
|
+
}
|
|
76
|
+
console.log("shiftblame: 請在目標 repo 中執行 /blame-init 初始化鍋目錄");
|
|
77
|
+
|
|
78
|
+
// --- helpers ---
|
|
24
79
|
|
|
25
80
|
function findProjectRoot(dir) {
|
|
26
81
|
let current = dir;
|
|
@@ -49,3 +104,12 @@ function copyRecursive(src, dest) {
|
|
|
49
104
|
fs.copyFileSync(src, dest);
|
|
50
105
|
}
|
|
51
106
|
}
|
|
107
|
+
|
|
108
|
+
function cleanEmptyDirs(dir, stopAt) {
|
|
109
|
+
if (dir === stopAt || !fs.existsSync(dir)) return;
|
|
110
|
+
const entries = fs.readdirSync(dir);
|
|
111
|
+
if (entries.length === 0) {
|
|
112
|
+
fs.rmdirSync(dir);
|
|
113
|
+
cleanEmptyDirs(path.dirname(dir), stopAt);
|
|
114
|
+
}
|
|
115
|
+
}
|