ppdevskill 1.2.0 → 1.3.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/README.md CHANGED
@@ -1,108 +1,183 @@
1
1
  # ppdevskill — Engineering Partner Skill
2
2
 
3
- Claude Skill ที่เปลี่ยน Claude จาก "AI ที่พ่นโค้ดให้เสร็จ ไป" ให้กลายเป็น **เพื่อนร่วมงานวิศวกรรมจริง ๆ**เข้าใจความต้องการที่แท้จริง แก้ให้ถูกจุด ไม่ over-engineer และเขียนโค้ดอย่างมีหลักการ
3
+ A Claude skill that turns Claude from *"an AI that throws out throwaway code to finish fast"* into a **real engineering thought-partner** one that understands the actual need, fixes the right spot, avoids over-engineering, and writes principled code.
4
+
5
+ > **Language note:** by design, the skill **replies to you in Thai**, keeping technical terms — function names, paths, errors, commands, code — in English. That is why the `examples/` walkthroughs and a few quoted strings below are in Thai: they are not untranslated debt, they are the demonstrated behavior.
4
6
 
5
7
  ---
6
8
 
7
- ## คืออะไร
9
+ ## What it is
8
10
 
9
- `ppdevskill` คือ skill เดียวที่รวม workflow งานวิศวกรรมซอฟต์แวร์ไว้ครบ 5 โหมด แต่ละโหมดมี **gate (ด่านบังคับ)** ที่ข้ามไม่ได้ เพื่อกัน Claude ไม่ให้ลงมือเขียนโค้ดก่อนที่ข้อมูลจะครบและก่อนที่ผู้ใช้จะอนุมัติ
11
+ `ppdevskill` is a single skill that unifies the software-engineering workflow into **six modes plus a commit action**. Every mode has a **hard gate** that cannot be skipped — the gate stops Claude from writing code before the information is complete and before you have approved a plan.
10
12
 
11
- หัวใจของ skill คือ **zero drift** LLM มักจะ "หลุด" กฎเมื่อบทสนทนายาวขึ้นหรือเมื่อผู้ใช้เร่ง skill นี้บังคับให้ Claude ยึดกฎตามตัวอักษรทุกครั้ง แม้ผู้ใช้จะบอกว่า "ทำเลย" หรือ "ข้าม gate ไปเถอะ" ก็ไม่ถือเป็นการอนุญาตให้ละเมิดกฎ
13
+ The core idea is **zero drift**. LLMs tend to "slip" their rules as a conversation grows longer or as the user grows impatient. This skill forces Claude to follow every rule literally, every time. A user saying *"just do it"* or *"skip the gate"* is **not** authorization to break a rule — the rule is restated and the work stops until the gate is genuinely satisfied.
12
14
 
13
15
  ---
14
16
 
15
- ## โหมดทั้งหมด
17
+ ## Modes & commands
16
18
 
17
- | โหมด | คำสั่ง | ใช้เมื่อ |
19
+ | Mode | Command | Use when |
18
20
  |---|---|---|
19
- | Plan | `#plan` | งานใหญ่หลายขั้น ข้ามหลายโหมด หรือ >3 slices — orchestrate / วางแผน |
20
- | Debug | `#dbg` | เจอ bug, มี error / stack trace, ของพัง |
21
- | Feature | `#ft` | เพิ่ม / สร้าง / implement ฟีเจอร์ใหม่ |
22
- | Refactor | `#rf` | ทำความสะอาด / จัดโครงสร้างโค้ด (ไม่เปลี่ยนพฤติกรรม) |
23
- | Review | `#rv` | review / audit PR, diff, plan, design doc |
24
- | Post-mortem | `#pm` | เขียน RCA / post-mortem หลังแก้ bug เสร็จ |
25
- | Commit/Push | `#cp` | commit และ push (ข้อความสะอาด ไม่มี AI attribution) |
26
-
27
- - `#pp` — auto-route: ให้ Claude เลือกโหมดเองจากบริบท
28
- - `#plan`orchestrator: แตกงานใหญ่เป็น slice (ตาม dependency), tag โหมดให้แต่ละ slice, แล้ว hand off **ไม่เขียนโค้ดเอง** (เหมือน `#bs`)
29
- - **Security** เป็นด่านขวาง (cross-cutting) ไม่ใช่โหมดที่ 6 ทุกการเปลี่ยนแปลงที่แตะ trust boundary (input / auth / token / file / SQL / shell / crypto / secret / network) จะเปิด security gate อัตโนมัติ และ **ปิดไม่ได้**
21
+ | Plan | `#plan` | A big multi-step arc spanning more than one mode or more than 3 slices — orchestrate and decompose |
22
+ | Debug | `#dbg` | A bug, an error / stack trace, something broken or throwing |
23
+ | Feature | `#ft` | Add / build / implement a new capability |
24
+ | Refactor | `#rf` | Clean up / restructure code with **no behavior change** |
25
+ | Review | `#rv` | Review / audit a PR, diff, plan, or design doc |
26
+ | Post-mortem | `#pm` | Write the RCA / post-mortem after a fix has landed |
27
+
28
+ Plus two routers and one action:
29
+
30
+ - **`#pp`**auto-route: Claude picks the mode from context; if it is ambiguous, it asks one question and stops.
31
+ - **`#plan`** orchestrator: breaks a big arc into slices (ordered by dependency), tags each slice with a mode, then hands off. It **never writes code itself**.
32
+ - **`#cp`** — commit / push **action** (not a mode): clean message, no AI attribution, stage only what the change touched. Runs *after* the work is verified.
33
+ - **`#bs`** — brainstorm-partner is a **separate skill** the workflow hands off to when the *approach itself* is undecided (it generates and selects, never builds).
34
+
35
+ ```mermaid
36
+ flowchart TD
37
+ U[User request or command] --> PP{"#pp — auto-route"}
38
+ PP -->|"bug / stack trace / broken"| DBG["#dbg Debug"]
39
+ PP -->|"add / build / implement"| FT["#ft Feature"]
40
+ PP -->|"clean up / restructure"| RF["#rf Refactor"]
41
+ PP -->|"review / audit PR or diff"| RV["#rv Review"]
42
+ PP -->|"write RCA / post-mortem"| PM["#pm Post-mortem"]
43
+ PP -->|"big multi-step arc"| PLAN["#plan Orchestrate"]
44
+ PP -->|"ambiguous"| ASK["Ask one question, stop"]
45
+ PLAN -.->|"decompose into slices,<br/>each faces its own gate"| DBG
46
+ PLAN -.-> FT
47
+ PLAN -.-> RF
48
+ PP -.->|"approach undecided"| BS["#bs Brainstorm<br/>(separate skill)"]
49
+ ```
50
+
51
+ ---
52
+
53
+ ## The gate model
54
+
55
+ Each mode opens with a gate. **No gate, no proceed** — if the gate is not satisfied, Claude states exactly what is missing, stops, and waits. Security is a cross-cutting gate that **cannot be waved off**.
56
+
57
+ - **GATE 0 `#plan`** — outcome stated as an end state + size gate passed + unknowns surfaced + whole-arc definition of done.
58
+ - **GATE 1 `#dbg`** — a reliable reproduction exists; no repro → full stop, no hypothesizing.
59
+ - **GATE 2 `#ft`** — real need stated + at least 3 given/when/then acceptance scenarios + scope bounded IN/OUT.
60
+ - **GATE 3 `#rf`** — a safety net + a concrete motivation (a named smell) + behavior pinned in one sentence.
61
+ - **GATE 4 `#rv`** — outsider stance, end-to-end trace, cite `file:line`, no rubber stamps.
62
+ - **GATE 5 `#pm`** — repro + root cause + fix + validation all in hand, else refuse.
63
+ - **SECURITY GATE (cross-cutting)** — any change touching a trust boundary (input / auth / token / file / SQL / shell / crypto / secret / network / access control / new dependency) trips this gate; the abuse case is written and the relevant OWASP Top 10 items are exercised, not assumed.
64
+
65
+ ```mermaid
66
+ flowchart LR
67
+ PLAN["#plan"] --> G0["GATE 0<br/>outcome + size + DoD"]
68
+ DBG["#dbg"] --> G1["GATE 1<br/>reliable repro"]
69
+ FT["#ft"] --> G2["GATE 2<br/>need + 3 scenarios + scope"]
70
+ RF["#rf"] --> G3["GATE 3<br/>safety net + smell + pin"]
71
+ RV["#rv"] --> G4["GATE 4<br/>outsider trace + cite"]
72
+ PM["#pm"] --> G5["GATE 5<br/>repro + cause + fix + validation"]
73
+ G0 --> D{Gate satisfied?}
74
+ G1 --> D
75
+ G2 --> D
76
+ G3 --> D
77
+ G4 --> D
78
+ G5 --> D
79
+ D -->|No| B["BLOCKED — state what's missing, stop"]
80
+ D -->|Yes| P["Proceed to the mode's steps"]
81
+ SEC["SECURITY GATE<br/>cross-cutting, cannot be waived"] -.-> P
82
+ ```
83
+
84
+ ---
85
+
86
+ ## VERIFIED discipline + mechanical enforcement
87
+
88
+ The skill never claims success it has not observed. Any claim-word — *done*, *works*, *complete*, `เสร็จ`, `เรียบร้อย` — must be backed by a `VERIFIED:` block (the actual commands run + their actual output) **immediately above it**. The escape hatch is `NOT VERIFIED:`, which lists every skipped step, the reason, and the concrete checks the user must perform. Static checks (type-check, lint) do not count as verification.
89
+
90
+ This is not left to willpower. A **Stop hook** (`hooks/verify-guard.sh`) blocks the turn from ending when a ppdevskill response carries a banner and a claim-word but no verification block, and feeds the reason back so the model fixes it in the same turn. It is **self-scoping** (fires only on responses with a ppdevskill banner — other workflows are untouched), **fail-open** (any error → allow; a discipline hook must never brick a session), and catches **Thai claim-words too**.
91
+
92
+ ```mermaid
93
+ flowchart TD
94
+ R["Assistant reply at turn end"] --> H["verify-guard.sh (Stop hook)"]
95
+ H --> S{"ppdevskill banner present?"}
96
+ S -->|No| A["Allow — not a ppdevskill turn"]
97
+ S -->|Yes| V{"VERIFIED: / NOT VERIFIED: block?"}
98
+ V -->|Yes| A
99
+ V -->|No| C{"claim-word? (done / works / เสร็จ ...)"}
100
+ C -->|No| A
101
+ C -->|Yes| BL["Block — feed reason back, fix this turn"]
102
+ H -.->|"any error / no jq / no banner"| A
103
+ ```
30
104
 
31
105
  ---
32
106
 
33
- ## ใช้ยังไง
107
+ ## Ledger — anti-drift persistence
108
+
109
+ `#plan` / `#dbg` / `#ft` / `#rf` persist their gate state (slice table, hypotheses, scope) to `.ppdev/<mode>-ledger.md` in the working repo, so it **survives context compaction** — Claude re-anchors from the file, not from memory. Add `.ppdev/` to that repo's `.gitignore`.
110
+
111
+ The ledger is **bounded to one active unit, never append-only**: a new unit overwrites the file, a finished slice is marked `[x]` in place, a replan edits the table in place, and a met definition-of-done clears the file. Steady-state size is one unit's worth (a slice table is ~4–12 rows). If a ledger grows past that, it is being mis-appended — truncate it to the current unit.
112
+
113
+ ---
34
114
 
35
- ### 1. ติดตั้ง
115
+ ## Install
36
116
 
37
- **วิธีง่ายสุดผ่าน npm:**
117
+ **Easiestvia npm:**
38
118
 
39
119
  ```bash
40
- npx ppdevskill@latest install # copy เข้า ~/.claude/skills/ + ถามว่าจะ wire hook ไหม
41
- npx ppdevskill install --with-hook # wire Stop hook ให้เลย ไม่ถาม
42
- npx ppdevskill install --no-hook # ไม่แตะ settings.json (print snippet ให้ paste เอง)
120
+ npx ppdevskill@latest install # copy into ~/.claude/skills/ + ask whether to wire the hook
121
+ npx ppdevskill install --with-hook # wire the Stop hook immediately, no prompt
122
+ npx ppdevskill install --no-hook # don't touch settings.json (prints the snippet to paste)
43
123
  ```
44
124
 
45
- installer จะ backup ของเดิมก่อน, `chmod +x` hook ให้, และไม่ทับ key อื่นใน settings.json. เสร็จแล้ว restart Claude Code.
125
+ The installer backs up any existing install first, `chmod +x` the hook, and never clobbers unrelated keys in `settings.json`. Restart Claude Code afterward.
46
126
 
47
- **หรือ git clone:**
127
+ **Or git clone:**
48
128
 
49
129
  ```bash
50
130
  git clone https://github.com/Kamisadev/ppdevskill.git ~/.claude/skills/ppdevskill
51
131
  ```
52
132
 
53
- โครงสร้างไฟล์:
133
+ **Enable the hook manually** (if you used `--no-hook` or cloned): merge `hooks/settings.snippet.json` into `~/.claude/settings.json` (global) or `.claude/settings.json` (per project) — if a `hooks` key already exists, add the `Stop` entry, **do not overwrite**. The hook requires `jq`.
134
+
135
+ ```bash
136
+ chmod +x ~/.claude/skills/ppdevskill/hooks/verify-guard.sh
137
+ ```
138
+
139
+ File layout:
54
140
 
55
141
  ```
56
142
  ppdevskill/
57
- ├── SKILL.md # hub หลัก กฎ, principles, routing
143
+ ├── SKILL.md # main hub — rules, principles, routing
58
144
  ├── references/
59
- │ ├── plan.md # GATE 0 + ขั้นตอนโหมด ultra-plan (orchestrator)
60
- │ ├── dbg.md # gate + ขั้นตอนโหมด debug
61
- │ ├── ft.md # gate + ขั้นตอนโหมด feature
62
- │ ├── rf.md # gate + ขั้นตอนโหมด refactor
63
- │ ├── rv.md # gate + ขั้นตอนโหมด review
64
- │ ├── pm.md # gate + ขั้นตอนโหมด post-mortem
145
+ │ ├── plan.md # GATE 0 + steps for the ultra-plan orchestrator
146
+ │ ├── dbg.md # gate + steps for debug
147
+ │ ├── ft.md # gate + steps for feature
148
+ │ ├── rf.md # gate + steps for refactor
149
+ │ ├── rv.md # gate + steps for review
150
+ │ ├── pm.md # gate + steps for post-mortem
65
151
  │ ├── sec.md # security gate (OWASP Top 10)
66
- │ ├── verify.md # ตารางวิธี verify ตามชนิดงาน
67
- │ └── git-auto.md # ขั้นตอน #cp commit / push
152
+ │ ├── verify.md # verification recipes per work type
153
+ │ └── git-auto.md # #cp commit / push procedure
68
154
  ├── hooks/
69
- │ ├── verify-guard.sh # Stop hook — บังคับ VERIFIED block ด้วยกลไก
70
- │ └── settings.snippet.json # config ที่ merge เข้า settings.json
71
- └── examples/ # worked example ต่อโหมดอ่าน on demand
72
- ├── plan.md # ตัวอย่างโหมด ultra-plan (GATE 0 → slice table)
73
- ├── dbg.md # ตัวอย่างโหมด debug (gate → VERIFIED)
74
- ├── ft.md # ตัวอย่างโหมด feature
75
- ├── rf.md # ตัวอย่างโหมด refactor
76
- ├── rv.md # ตัวอย่างโหมด review
77
- ├── pm.md # ตัวอย่างโหมด post-mortem
78
- └── cp.md # ตัวอย่าง commit / push
79
- ```
80
-
81
- ### 1.5 เปิดการบังคับด้วยกลไก (hooks) — แนะนำ
82
-
83
- ทำให้กฎ VERIFIED block บังคับด้วย Stop hook จริง ไม่พึ่งวินัย LLM ล้วน. merge `hooks/settings.snippet.json` เข้า `~/.claude/settings.json` (global) หรือ `.claude/settings.json` (ต่อ project) — ถ้ามี key `hooks` อยู่แล้ว เพิ่ม entry `Stop` เข้าไป **อย่าทับ**.
84
-
85
- ```bash
86
- chmod +x ~/.claude/skills/ppdevskill/hooks/verify-guard.sh
155
+ │ ├── verify-guard.sh # Stop hook — mechanically enforces the VERIFIED block
156
+ │ └── settings.snippet.json # config to merge into settings.json
157
+ └── examples/ # one worked example per mode read on demand
158
+ ├── plan.md # ultra-plan example (GATE 0 → slice table)
159
+ ├── dbg.md # debug example (gate → VERIFIED)
160
+ ├── ft.md # feature example
161
+ ├── rf.md # refactor example
162
+ ├── rv.md # review example
163
+ ├── pm.md # post-mortem example
164
+ └── cp.md # commit / push example
87
165
  ```
88
166
 
89
- หลัง merge: response ที่มี ppdevskill banner + อ้างว่าเสร็จ (`done`/`เสร็จ`/`works`) แต่ไม่มี `VERIFIED:`/`NOT VERIFIED:` block → hook **block** + บังคับแก้ในเทิร์นนั้น. **scope เฉพาะ ppdevskill** (ดูจาก banner) — workflow อื่นไม่โดน. **fail-open** — hook พังเมื่อไหร่ = ปล่อยผ่าน ไม่เคย brick session. ต้องมี `jq`.
90
-
91
- > **ledger**: `#plan`/`#dbg`/`#ft`/`#rf` เขียน gate state (slice table / hypotheses / scope) ลง `.ppdev/<mode>-ledger.md` ใน repo ที่ทำงานอยู่ → รอด context compaction. เพิ่ม `.ppdev/` ใน `.gitignore` ของ repo นั้น.
92
- > **ไม่บวม**: ledger เก็บ "1 unit ที่กำลังทำ" เท่านั้น — unit ใหม่ = overwrite (ไม่ append), slice เสร็จ = mark `[x]` ในที่, replan = แก้ table ในที่, DoD ครบ = เคลียร์ไฟล์. ขนาดคงที่ ~1 unit (slice table ~4–12 แถว). โตเกินนั้น = ถูก append ผิด ให้ truncate.
167
+ ---
93
168
 
94
- ### 2. เรียกใช้
169
+ ## Usage
95
170
 
96
- พิมพ์คำสั่งโหมดในแชต หรือปล่อยให้ trigger ทำงานเอง:
171
+ Type a mode command in chat, or let the triggers fire on their own. (Realistic input is in Thai — the skill is built for a Thai-replying workflow.)
97
172
 
98
173
  ```
99
174
  #dbg API /users คืน 500 ตอน login
100
175
  #ft เพิ่มหน้า export CSV ให้รายงานยอดขาย
101
176
  #rv ช่วย review PR นี้หน่อย
102
- #pp <อธิบายงาน>ให้เลือกโหมดให้
177
+ #pp <describe the task>let Claude pick the mode
103
178
  ```
104
179
 
105
- Claude จะตอบเป็นภาษาไทย (เก็บศัพท์เทคนิค / ชื่อ function / path / error เป็นภาษาอังกฤษ) พร้อม banner บอกโหมดและสถานะ gate ทุกครั้ง เช่น:
180
+ Claude replies in Thai (technical terms / function names / paths / errors stay English), with a one-line banner stating the mode and gate status on every response, e.g.:
106
181
 
107
182
  ```
108
183
  > #dbg | GATE 1 PASS | STEP 1.2
@@ -110,22 +185,37 @@ Claude จะตอบเป็นภาษาไทย (เก็บศัพ
110
185
 
111
186
  ---
112
187
 
113
- ## ประโยชน์
114
-
115
- - **กันโค้ดมั่ว**ไม่มี gate ไม่เขียนโค้ด ข้อมูลไม่ครบต้อง brainstorm ก่อน ไม่เดามั่ว
116
- - **แก้ถูกจุด**หา root cause ก่อน ไม่แก้ที่อาการ
117
- - **ไม่ over-engineer** — ยึดหลัก YAGNI ไม่สร้าง abstraction ก่อนเวลา
118
- - **บอกความจริง**ไม่ประจบ ไม่ hedge ไม่ rubber-stamp มีจุดยืนและคำแนะนำที่ชัดเจน
119
- - **ไม่อ้างว่าเสร็จลอย ๆ** ทุกคำว่า "เสร็จ / done / works" ต้องมี `VERIFIED:` block (คำสั่งที่รันจริง + output จริง) กำกับ
120
- - **Security มาก่อน**แตะ trust boundary เมื่อไหร่ ต้องผ่าน security gate (อ้างอิง OWASP Top 10) เสมอ ปิดไม่ได้
121
- - **บังคับด้วยกลไก ไม่ใช่แค่ขอ** — Stop hook บังคับ VERIFIED block, ledger ลงไฟล์กัน drift ในเซสชันยาว (ดู `hooks/`)
122
- - **มีตัวอย่างจริง + offer commit ให้เอง** — `examples/<mode>.md` แสดงแต่ละโหมดตั้งแต่ gate ถึง VERIFIED block · พองาน verified แล้ว skill จะ **offer `#cp` ให้เอง** (ไม่ auto-commit, ไม่ offer ตอนงานยังพัง) ไม่ต้องนึกเองว่าถึงเวลา commit
123
- - **แยก concern ชัด**เปลี่ยนพฤติกรรมกับ refactor ห้ามอยู่ใน diff เดียวกัน หนึ่ง response หนึ่งโหมด
188
+ ## What it buys you
189
+
190
+ - **No code from thin air** no gate, no code; incomplete information means brainstorm first, never guess.
191
+ - **Fix the right spot** find the root cause, don't patch the symptom.
192
+ - **No over-engineering** — YAGNI: no abstraction before its time.
193
+ - **An honest stance** no flattery, no hedging, no rubber-stamps; an opinionated recommendation with the tradeoffs.
194
+ - **No hollow "it's done"** every *done / works / เสร็จ* is backed by a `VERIFIED:` block (real commands + real output).
195
+ - **Security first**touching a trust boundary always goes through the security gate (OWASP Top 10), and it cannot be waved off.
196
+ - **Enforced by mechanism, not just by asking** the Stop hook enforces the VERIFIED block; the ledger persists to disk to fight drift in long sessions.
197
+ - **Worked examples + an automatic commit offer** — `examples/<mode>.md` shows each mode from gate to VERIFIED block; once work is verified, the skill **offers `#cp`** on its own (never auto-commits, never offers on broken work).
198
+ - **Clean separation of concerns** behavior change and refactor never share a diff; one response, one mode.
199
+
200
+ ```mermaid
201
+ flowchart TD
202
+ P0["#plan GATE 0"] --> ST["slice table → .ppdev/plan-ledger.md"]
203
+ ST --> S1["slice 1 → its mode (full gate)"]
204
+ S1 --> Vf{"VERIFIED?"}
205
+ Vf -->|"No"| S1
206
+ Vf -->|"Yes"| CP["offer #cp → commit"]
207
+ CP --> NEXT["next slice ..."]
208
+ NEXT --> DOD{"arc DoD met?"}
209
+ DOD -->|"No"| S1
210
+ DOD -->|"Yes"| RVW["#rv over the whole arc"]
211
+ ```
124
212
 
125
213
  ---
126
214
 
127
- ## ปรัชญาหลัก
215
+ ## Core philosophy
128
216
 
129
217
  > "ขอเวลาห้านาทีเพื่อทำให้ถูก ดีกว่าทำผิดไปห้าชั่วโมง" — **การปฏิเสธคือฟีเจอร์**
218
+ >
219
+ > *"Five minutes to get it right beats five hours doing the wrong thing"* — **refusal is a feature.**
130
220
 
131
- แก้ที่ความต้องการจริง ไม่ใช่แค่คำสั่งที่พิมพ์มา ถ้าสองอย่างนี้ขัดกัน Claude จะหยุดถามก่อนเสมอ
221
+ Solve the real need, not just the request as typed. When the two diverge, Claude surfaces it and confirms before doing the work.
package/SKILL.md CHANGED
@@ -20,7 +20,7 @@ Follow every rule literally. Do not soften, skip, or reinterpret a rule because
20
20
  5. Replying in Thai, technical terms kept in English?
21
21
  6. Flattery, hedging ("might possibly"), or rubber-stamp ("LGTM")? → delete, state directly.
22
22
  7. Mixing modes, mixing behavior change with refactor, or "while I'm here" work?
23
- 8. **FORMAT CHECK (literal text scan, not introspection):** does the response contain a claim-word (`done`, `เสร็จ`, `เสร็จแล้ว`, `เรียบร้อย`, `พร้อมใช้`, `ใช้ได้แล้ว`, `complete`, `finished`, `ready`, `works`, `should work`, `looks good`, `LGTM`, or equivalent) without a `VERIFIED:` / `NOT VERIFIED:` block immediately above it? → response invalid, rewrite: paste the block, or replace the claim-word with a precise statement of what was actually accomplished. No third option. (Enforced mechanically by the Stop hook — see MECHANICAL ENFORCEMENT. The hook is the net; it does not excuse skipping the block.)
23
+ 8. **FORMAT CHECK (literal text scan, not introspection):** does the response contain a claim-word (`done`, `เสร็จ`, `เสร็จแล้ว`, `เรียบร้อย`, `พร้อมใช้`, `ใช้ได้แล้ว`, `complete`, `completed`, `finished`, `ready`, `works`, `should work`, `looks good`, `LGTM`, or equivalent) without a `VERIFIED:` / `NOT VERIFIED:` block immediately above it? → response invalid, rewrite: paste the block, or replace the claim-word with a precise statement of what was actually accomplished. No third option. (Enforced mechanically by the Stop hook — see MECHANICAL ENFORCEMENT. The hook is the net; it does not excuse skipping the block. This claim-word list is load-bearing: it mirrors the `CLAIM_EN`/`CLAIM_TH` regex in `hooks/verify-guard.sh` — change one, change both.)
24
24
  9. Asking something I could determine myself? → analyze it; ask only genuine judgment/intent calls.
25
25
  10. Friction proportional to stakes? Trivial/reversible work just proceeds.
26
26
  11. Re-litigating a concern already flagged and waved off? → drop it.
package/bin/cli.js CHANGED
@@ -13,7 +13,7 @@ const readline = require('readline');
13
13
 
14
14
  const PKG_ROOT = path.resolve(__dirname, '..');
15
15
  const pkg = require(path.join(PKG_ROOT, 'package.json'));
16
- const ITEMS = ['SKILL.md', 'references', 'hooks', 'README.md', 'LICENSE'];
16
+ const ITEMS = ['SKILL.md', 'references', 'examples', 'hooks', 'README.md', 'LICENSE'];
17
17
 
18
18
  const log = (m) => process.stdout.write(m + '\n');
19
19
  const errln = (m) => process.stderr.write(m + '\n');
package/examples/dbg.md CHANGED
@@ -25,9 +25,9 @@ repro เชื่อถือได้ + stack ชี้จุดชัด. อ
25
25
 
26
26
  **Hypothesis:** บรรทัด 42 `req.user.role` — `req.user` เป็น `null` เมื่อ token decode สำเร็จแต่ user ถูกลบไปแล้ว: `db.findUser(id)` คืน `null` แต่โค้ดไม่เช็กก่อน access `.role`. root cause = missing null guard ไม่ใช่ตัว middleware เอง
27
27
 
28
- > #dbg | GATE 1 PASS | STEP 1.4 fix + verify
28
+ > #dbg | GATE 1 PASS | STEP 1.5 fix + verify
29
29
 
30
- fix: เพิ่ม null check หลัง `db.findUser(id)` → คืน 401 แทน crash
30
+ fix ที่ cause ไม่ใช่ symptom (มันตรา 8): "user หายแต่ token ยังใช้ได้" คือ invariant ที่ควรมี — guard นี้คืนค่า 401 เป็น state ที่ถูกต้อง ไม่ใช่ปิดแผล. เพิ่ม null check หลัง `db.findUser(id)` → คืน 401 แทน crash
31
31
 
32
32
  ```
33
33
  VERIFIED:
@@ -41,4 +41,4 @@ $ curl -H "Authorization: Bearer <stale-token>" localhost:3000/users
41
41
 
42
42
  ---
43
43
 
44
- **สิ่งที่ตัวอย่างนี้สอน:** ไม่มี repro = หยุด ไม่เดา · hypothesis มาก่อน fix · อ่านเฉพาะไฟล์ที่ hypothesis ต้องการ · ทุกคำว่า "fixed" มี VERIFIED block (คำสั่งจริง + output จริง) · จบงานแล้ว offer `#cp` ไม่ auto-commit
44
+ **สิ่งที่ตัวอย่างนี้สอน:** ไม่มี repro = หยุด ไม่เดา · hypothesis มาก่อน fix · อ่านเฉพาะไฟล์ที่ hypothesis ต้องการ · fix ที่ cause ไม่ใช่ symptom (มันตรา 8) · ทุกคำว่า "fixed" มี VERIFIED block (คำสั่งจริง + output จริง — ควรพิสูจน์ทั้งสองทาง: fix→green, revert→red, มันตรา 9) · จบงานแล้ว offer `#cp` ไม่ auto-commit
@@ -51,8 +51,16 @@ printf '%s' "$TEXT" | grep -Eq '> #(dbg|ft|rf|rv|pm|cp|pp)\b' || allow
51
51
  printf '%s' "$TEXT" | grep -q 'VERIFIED:' && allow
52
52
 
53
53
  # Claim-word present without a verification block -> violation (SKILL.md self-check 8 list).
54
- CLAIM='done|complete|completed|finished|ready|works|should work|looks good|LGTM|เสร็จ|เสร็จแล้ว|เรียบร้อย|พร้อมใช้|ใช้ได้แล้ว'
55
- printf '%s' "$TEXT" | grep -Eiq "$CLAIM" || allow
54
+ # ASCII claims are bounded by a non-letter or a string edge -- portable across BSD/GNU/ugrep
55
+ # (\b is non-portable) -- so substrings like "abandoned"/"already"/"workspace"/"framework" do
56
+ # NOT false-trigger. Thai has no word breaks, so Thai claims match as-is.
57
+ # This list MUST stay in sync with SKILL.md self-check 8 (the model-side mirror).
58
+ CLAIM_EN='done|complete|completed|finished|ready|works|should work|looks good|LGTM'
59
+ CLAIM_TH='เสร็จ|เสร็จแล้ว|เรียบร้อย|พร้อมใช้|ใช้ได้แล้ว'
60
+ claimed=0
61
+ printf '%s' "$TEXT" | grep -Eiq "(^|[^a-zA-Z])(${CLAIM_EN})([^a-zA-Z]|\$)" && claimed=1
62
+ printf '%s' "$TEXT" | grep -Eq "$CLAIM_TH" && claimed=1
63
+ [ "$claimed" = 1 ] || allow
56
64
 
57
65
  # Block: feed the reason back so the model fixes it this turn.
58
66
  jq -nc '{
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ppdevskill",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "Unified engineering-partner workflow for Claude Code — debug, build, refactor, review, post-mortem — with hard gates and mechanical (hook-enforced) verification discipline.",
5
5
  "bin": {
6
6
  "ppdevskill": "bin/cli.js"
@@ -15,7 +15,7 @@
15
15
  "LICENSE"
16
16
  ],
17
17
  "scripts": {
18
- "test": "node bin/cli.js --version"
18
+ "test": "sh test/run.sh && sh test/claim-sync.sh && node bin/cli.js --version"
19
19
  },
20
20
  "keywords": [
21
21
  "claude",
package/references/dbg.md CHANGED
@@ -1,12 +1,17 @@
1
1
  # `#dbg` — Debug
2
2
 
3
- Four steps, in order. No skipping, no reordering.
3
+ Gated steps, in order (GATE 1 → 1.2 → 1.3 → 1.4 → 1.5). No skipping, no reordering. The mantra is title-only so it stays scannable and recitable; the body of each step carries the detail — read the step, not just the title.
4
4
 
5
5
  Recite this mantra verbatim once per session (user says "skip the mantra" → apply silently):
6
6
  > 1. **Reproducibility first** — can the issue be reproduced reliably?
7
7
  > 2. **Know the fail path** — debugger first → source trace + knob enumeration → in-code instrumentation.
8
8
  > 3. **Question your hypothesis** — what would disprove it?
9
9
  > 4. **Every run is a breadcrumb** — cross-reference all of them.
10
+ > 5. **Check the plug before the logic** — observing the real system, not a stale build / wrong env?
11
+ > 6. **Shrink the repro to the bone** — cut until one more cut makes it pass; the residue is the cause.
12
+ > 7. **Binary-search the fault** — probe the midpoint, discard half; bisect, never linear-scan.
13
+ > 8. **Fix the cause, not the symptom** — patch where the invariant breaks, not where it surfaces.
14
+ > 9. **Toggle the fix, prove causality both ways** — fix → green AND revert → red, else coincidence.
10
15
 
11
16
  ## GATE 1 — Reliable Repro (before anything else)
12
17
 
@@ -18,12 +23,18 @@ Recite this mantra verbatim once per session (user says "skip the mantra" → ap
18
23
 
19
24
  Target: fast (1–5s), deterministic pass/fail. Pin time, seed RNG, freeze network. Proposing a fix without a reliable repro is a violation — return to this gate.
20
25
 
26
+ **Shrink to the bone (mantra 6).** Reliable ≠ minimal — a repro can be 500 lines of noise and still pass this gate. Once it repros, cut inputs, steps, and config one at a time until one more cut makes it pass; what remains IS the cause, and it becomes the regression test in STEP 1.5. Reduce before you read source: a minimal artifact collapses the suspect space and sharpens every disproof in 1.3.
27
+
21
28
  ## PARTNER CALL — Pattern Recognition (after GATE 1)
22
29
 
23
30
  Symptom resembles a known failure class → call it: one sentence what it looks like, one where to look (e.g. *"Intermittent + load-dependent + passes in isolation = race condition writing shared state without a lock. Check [X] first."*). No match → *"No pattern match yet; need to trace the fail path first."* A pattern call is a hypothesis for 1.3, not a conclusion.
24
31
 
25
32
  ## STEP 1.2 — Know the Fail Path
26
33
 
34
+ **Check the plug first (mantra 5).** Before tracing anything, confirm you are observing the real system: the build actually ran, the live binary / branch / env / dependency / input is the one you think it is, no stale artifact or wrong venv. When the trace contradicts your mental model, suspect the observation surface before rewriting the model — the data is rarely the liar. Debugging code that never executed is the most expensive waste there is.
35
+
36
+ **Binary-search the fault (mantra 7).** Over any *ordered* range — commits, input size, the call path — probe the midpoint and let each result discard half (O(log n), not linear). `git bisect` a regression down to the breaking commit; wolf-fence a pipeline; halve the input. This picks *where* on the path to look; knob enumeration below picks *what* to vary once you are there.
37
+
27
38
  Escalate in order; document why each escalation was needed. Do not jump to 3 if 1 is available.
28
39
  1. **Debugger** — step to the failure site (one breakpoint beats ten logs).
29
40
  2. **Source trace + knob enumeration** — walk the code path end-to-end; list every knob (config, env, toggle, branch, input shape, timing, concurrency); flip one at a time.
@@ -39,6 +50,12 @@ Session ledger: each entry = what changed, what happened, what it ruled in/out.
39
50
  - New hypothesis → must hold for every prior observation; contradiction → refine or discard.
40
51
  - Stuck → design the **single experiment** whose outcome resolves the ambiguity; run that next.
41
52
 
53
+ ## STEP 1.5 — Fix at the Cause, Prove Both Ways
54
+
55
+ Only after a hypothesis survives 1.3 disproof. Diagnosis (1.2) found *where the bug lives*; this step decides *where the edit lands* and *whether it actually worked*.
56
+ - **Fix the cause, not the symptom (mantra 8).** Patch where the invariant first breaks, not where it surfaces. A null-check, clamp, retry, or try/catch wrapped around a bad value is usually a coverup — the mechanism is still alive upstream and resurfaces elsewhere. If you cannot name the invariant being restored, you have not found the cause yet. (A guard IS the right fix when "absent/invalid" is a legitimate state — e.g. stale token → 401; the test is whether you are restoring an invariant or hiding a violation.)
57
+ - **Toggle the fix, prove causality both ways (mantra 9).** The fix makes the repro green AND reverting the fix makes it red again — one direction alone admits a flaky or coincidental green. Capture this as a regression test you watched FAIL for the right reason *before* it passed; that automated guard outlives the manual GATE 1 repro and pins the bug class shut.
58
+
42
59
  ## HARD RULES
43
60
 
44
- Mantra once per session, verbatim · steps 1→2→3→4 · no fix proposed until GATE 1 passes · no hypothesis testing until 1.2 narrows the path · no hypothesis committed until 1.3 disproof attempt · caught proposing a fix without repro → return to GATE 1 · **after applying any fix: rerun the GATE 1 repro and see it pass, plus the verify recipe (`references/verify.md`)** — green output is done; "the fix should work" is not.
61
+ Mantra once per session, verbatim · steps 1→2→3→4→5 · no fix proposed until GATE 1 passes · no hypothesis testing until 1.2 narrows the path · no hypothesis committed until 1.3 disproof attempt · caught proposing a fix without repro → return to GATE 1 · fix lands at the cause, not the symptom (1.5) · **after applying any fix: rerun the GATE 1 repro and see it pass AND revert-to-confirm it fails again (mantra 9), plus the verify recipe (`references/verify.md`)** — green output is done; "the fix should work" is not.