ppdevskill 1.2.0 → 1.3.1
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 +129 -82
- package/SKILL.md +1 -1
- package/bin/cli.js +1 -1
- package/examples/dbg.md +3 -3
- package/hooks/verify-guard.sh +10 -2
- package/package.json +2 -2
- package/references/dbg.md +19 -2
package/README.md
CHANGED
|
@@ -1,131 +1,178 @@
|
|
|
1
|
-
# ppdevskill —
|
|
1
|
+
# ppdevskill — your engineering partner, not a code vending machine
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/ppdevskill)
|
|
4
|
+
[](./LICENSE)
|
|
5
|
+
|
|
6
|
+
> Turn 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, refuses to over-engineer, and never says *"it's done"* about something it never ran.
|
|
7
|
+
|
|
8
|
+
`ppdevskill` is a single [Claude](https://claude.ai/code) skill that unifies the whole software-engineering workflow into **six modes + a commit action**, each guarded by 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.
|
|
9
|
+
|
|
10
|
+
> **Language note:** by design the skill **replies in Thai**, keeping technical terms — function names, paths, errors, commands, code — in English. The technical docs below are English for reach; the demonstrated behavior is Thai.
|
|
4
11
|
|
|
5
12
|
---
|
|
6
13
|
|
|
7
|
-
##
|
|
14
|
+
## The problem it solves
|
|
15
|
+
|
|
16
|
+
LLM coding assistants share three expensive failure modes:
|
|
17
|
+
|
|
18
|
+
1. **Code from thin air** — they start editing before they understand the need.
|
|
19
|
+
2. **"It works" that doesn't** — they claim success they never verified.
|
|
20
|
+
3. **Unguarded boundaries** — they touch auth / SQL / file-upload without a threat model.
|
|
8
21
|
|
|
9
|
-
|
|
22
|
+
And a fourth that grows over time: **drift** — the longer the session, the more they "slip" their own rules.
|
|
10
23
|
|
|
11
|
-
|
|
24
|
+
`ppdevskill` attacks all four with **gates, a verification discipline, a mechanical Stop-hook, and an on-disk ledger** — discipline backed by mechanism, not willpower.
|
|
12
25
|
|
|
13
26
|
---
|
|
14
27
|
|
|
15
|
-
##
|
|
28
|
+
## Modes & commands
|
|
16
29
|
|
|
17
|
-
|
|
|
18
|
-
|
|
19
|
-
| Plan | `#plan` |
|
|
20
|
-
| Debug | `#dbg` |
|
|
21
|
-
| Feature | `#ft` |
|
|
22
|
-
| Refactor | `#rf` |
|
|
23
|
-
| Review | `#rv` |
|
|
24
|
-
| Post-mortem | `#pm` |
|
|
25
|
-
| Commit/Push | `#cp` | commit และ push (ข้อความสะอาด ไม่มี AI attribution) |
|
|
30
|
+
| Mode | Command | Use when | Gate |
|
|
31
|
+
|---|---|---|---|
|
|
32
|
+
| Plan | `#plan` | A big multi-step arc spanning >1 mode or >3 slices — orchestrate & decompose | GATE 0 · outcome + size + DoD |
|
|
33
|
+
| Debug | `#dbg` | A bug, error / stack trace, something broken or throwing | GATE 1 · reliable repro |
|
|
34
|
+
| Feature | `#ft` | Add / build / implement a new capability | GATE 2 · need + 3 scenarios + scope |
|
|
35
|
+
| Refactor | `#rf` | Clean up / restructure with **no behavior change** | GATE 3 · safety net + smell + pin |
|
|
36
|
+
| Review | `#rv` | Review / audit a PR, diff, plan, or design doc | GATE 4 · outsider trace + cite |
|
|
37
|
+
| Post-mortem | `#pm` | Write the RCA after a fix has landed | GATE 5 · repro + cause + fix + validation |
|
|
26
38
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
39
|
+
Plus: **`#pp`** auto-routes from context · **`#cp`** is the commit/push action (clean message, no AI attribution, runs only after work is verified) · **`#bs`** hands off to a separate brainstorm skill when the *approach itself* is undecided.
|
|
40
|
+
|
|
41
|
+
**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** — any change touching a trust boundary (input / auth / token / file / SQL / shell / crypto / secret / network / access control / new dependency) trips it, and the abuse case is *exercised, not assumed*.
|
|
42
|
+
|
|
43
|
+
```mermaid
|
|
44
|
+
flowchart LR
|
|
45
|
+
REQ["request / command"] --> ROUTE["pick mode + gate"]
|
|
46
|
+
ROUTE --> G{"gate satisfied?<br/>(info + approval)"}
|
|
47
|
+
G -->|No| B["BLOCKED — name what's missing, stop"]
|
|
48
|
+
G -->|Yes| P["proceed + VERIFIED block"]
|
|
49
|
+
SEC["security gate · cannot be waived"] -.-> P
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
A user saying *"just do it"* / *"ทำเลย"* / *"trust me"* is **not** authorization to break a rule. The rule is restated and the work stops until the gate is genuinely satisfied. This is the **zero-drift** core.
|
|
30
53
|
|
|
31
54
|
---
|
|
32
55
|
|
|
33
|
-
##
|
|
56
|
+
## VERIFIED discipline + mechanical enforcement
|
|
34
57
|
|
|
35
|
-
|
|
58
|
+
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 you must perform. Static checks (type-check, lint) do **not** count as verification.
|
|
36
59
|
|
|
37
|
-
|
|
60
|
+
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 + 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 ppdevskill responses — other workflows untouched), **fail-open** (any error → allow; a discipline hook must never brick a session), and catches **Thai claim-words too**.
|
|
38
61
|
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
62
|
+
```mermaid
|
|
63
|
+
flowchart TD
|
|
64
|
+
R["reply at turn end"] --> H["verify-guard.sh (Stop hook)"]
|
|
65
|
+
H --> S{"ppdevskill banner?"}
|
|
66
|
+
S -->|No| A["allow — not our turn"]
|
|
67
|
+
S -->|Yes| V{"VERIFIED: / NOT VERIFIED: block?"}
|
|
68
|
+
V -->|Yes| A
|
|
69
|
+
V -->|No| C{"claim-word? (done / works / เสร็จ ...)"}
|
|
70
|
+
C -->|No| A
|
|
71
|
+
C -->|Yes| BL["block — feed reason back, fix this turn"]
|
|
72
|
+
H -.->|"any error / no jq / no banner"| A
|
|
43
73
|
```
|
|
44
74
|
|
|
45
|
-
|
|
75
|
+
**Ledger — anti-drift persistence.** `#plan` / `#dbg` / `#ft` / `#rf` persist their gate state (slice table, hypotheses, scope) to `.ppdev/<mode>-ledger.md`, so it **survives context compaction** — Claude re-anchors from the file, not from memory. It is bounded to one active unit (overwrite on a new unit, mark `[x]` in place, clear when done).
|
|
46
76
|
|
|
47
|
-
|
|
77
|
+
---
|
|
48
78
|
|
|
49
|
-
|
|
50
|
-
git clone https://github.com/Kamisadev/ppdevskill.git ~/.claude/skills/ppdevskill
|
|
51
|
-
```
|
|
79
|
+
## Does it actually change anything? (benchmark)
|
|
52
80
|
|
|
53
|
-
|
|
81
|
+
Measured on a 27-trial A/B benchmark — **same model both arms**, identical prompts, with-skill vs without-skill, across all 7 modes + 3 security classes. The skill does not make a weak model smart; it makes a capable model **consistently, mechanically disciplined**.
|
|
54
82
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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
|
-
```
|
|
83
|
+
| Behavior | Without skill | With skill |
|
|
84
|
+
|---|---:|---:|
|
|
85
|
+
| Wrote code with no plan/approval | **64%** of turns | **0%** |
|
|
86
|
+
| Claimed "works/done" without running it | **100%** (2/2) | **0%** |
|
|
87
|
+
| Enumerated abuse-cases on a boundary task | **0%** (0/7) | **100%** (6/6) |
|
|
88
|
+
| Guessed a root cause before a repro existed | yes | **no** |
|
|
89
|
+
| Mixed a bug-fix into a refactor diff | yes | **no** |
|
|
90
|
+
| Discipline banner + gate state every reply | 0% | **100%** |
|
|
91
|
+
|
|
92
|
+
The underrated win is **consistency**: the with-skill arm has near-zero variance; the baseline is disciplined only some of the time, which is exactly what you can't trust in production.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Pros & cons — the honest list
|
|
80
97
|
|
|
81
|
-
|
|
98
|
+
**Pros**
|
|
82
99
|
|
|
83
|
-
|
|
100
|
+
- ✅ **Kills "fake done."** Every claim is backed by real commands + real output, or an explicit `NOT VERIFIED:`.
|
|
101
|
+
- ✅ **No code from thin air.** No gate, no code; incomplete info → it asks, never guesses.
|
|
102
|
+
- ✅ **Security is non-negotiable.** Trust-boundary changes always go through the OWASP gate, and it cannot be waved off.
|
|
103
|
+
- ✅ **Finds the root cause.** Demands a repro before hypothesizing; fixes the cause, not the symptom.
|
|
104
|
+
- ✅ **Clean separation.** Behavior change and refactor never share a diff.
|
|
105
|
+
- ✅ **Mechanical, not aspirational.** The Stop hook enforces verification; the ledger fights drift in long sessions.
|
|
106
|
+
- ✅ **Consistent floor.** Near-zero variance — it behaves the same on turn 50 as on turn 1.
|
|
107
|
+
- ✅ **An honest stance.** No flattery, no hedging, no rubber-stamp "LGTM" — an opinionated recommendation with tradeoffs.
|
|
108
|
+
- ✅ **Plays nice.** The hook is self-scoping and fail-open: it never touches other workflows and never bricks a session.
|
|
109
|
+
|
|
110
|
+
**Cons** *(so you can decide with eyes open)*
|
|
111
|
+
|
|
112
|
+
- ⚠️ **It costs more per turn.** ~1.8× tokens and latency on a *cold* turn (it reads its own rules). This amortizes over a session, but it is real upfront cost.
|
|
113
|
+
- ⚠️ **It adds friction to trivial work.** A one-line rename or a throwaway script still meets some ceremony. For spikes / REPL experiments, that friction is not worth it.
|
|
114
|
+
- ⚠️ **It replies in Thai by design.** Technical terms stay English, but the prose is Thai. If you need English replies, this is a mismatch.
|
|
115
|
+
- ⚠️ **The Stop hook needs `jq`.** No `jq`, the hook fails open (so nothing breaks) but you lose the mechanical net.
|
|
116
|
+
- ⚠️ **It pushes back.** It will ask for a repro, acceptance scenarios, or a security abuse-case before writing code. If you just want code *now*, that refusal is friction — by design ("refusal is a feature").
|
|
117
|
+
- ⚠️ **Benchmark caveat.** Gains are measured against the *same* model, so the value is *consistency and guarantees*, not raw capability. Multi-turn anti-drift benefits are real but harder to quantify.
|
|
118
|
+
|
|
119
|
+
**Bottom line:** use it for production code, anything touching auth / payments / data deletion, PR reviews, and long multi-day arcs. Skip it for throwaway scripts and quick learning spikes.
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Install
|
|
124
|
+
|
|
125
|
+
**Easiest — via npm:**
|
|
84
126
|
|
|
85
127
|
```bash
|
|
86
|
-
|
|
128
|
+
npx ppdevskill@latest install # copy into ~/.claude/skills/ + ask whether to wire the hook
|
|
129
|
+
npx ppdevskill install --with-hook # wire the Stop hook immediately, no prompt
|
|
130
|
+
npx ppdevskill install --no-hook # don't touch settings.json (prints the snippet to paste)
|
|
87
131
|
```
|
|
88
132
|
|
|
89
|
-
|
|
133
|
+
The installer backs up any existing install, `chmod +x` the hook, and never clobbers unrelated keys in `settings.json`. Restart Claude Code afterward. The hook requires `jq`.
|
|
90
134
|
|
|
91
|
-
|
|
92
|
-
> **ไม่บวม**: ledger เก็บ "1 unit ที่กำลังทำ" เท่านั้น — unit ใหม่ = overwrite (ไม่ append), slice เสร็จ = mark `[x]` ในที่, replan = แก้ table ในที่, DoD ครบ = เคลียร์ไฟล์. ขนาดคงที่ ~1 unit (slice table ~4–12 แถว). โตเกินนั้น = ถูก append ผิด ให้ truncate.
|
|
135
|
+
**Or git clone:**
|
|
93
136
|
|
|
94
|
-
|
|
137
|
+
```bash
|
|
138
|
+
git clone https://github.com/Kamisadev/ppdevskill.git ~/.claude/skills/ppdevskill
|
|
139
|
+
```
|
|
95
140
|
|
|
96
|
-
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## Usage
|
|
144
|
+
|
|
145
|
+
Type a mode command in chat, or let the triggers fire on their own:
|
|
97
146
|
|
|
98
147
|
```
|
|
99
148
|
#dbg API /users คืน 500 ตอน login
|
|
100
149
|
#ft เพิ่มหน้า export CSV ให้รายงานยอดขาย
|
|
101
150
|
#rv ช่วย review PR นี้หน่อย
|
|
102
|
-
#pp
|
|
151
|
+
#pp <describe the task> ← let Claude pick the mode
|
|
103
152
|
```
|
|
104
153
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
```
|
|
108
|
-
> #dbg | GATE 1 PASS | STEP 1.2
|
|
109
|
-
```
|
|
154
|
+
Every reply carries a one-line banner stating mode + gate status, e.g. `> #dbg | GATE 1 PASS | STEP 1.2`.
|
|
110
155
|
|
|
111
156
|
---
|
|
112
157
|
|
|
113
|
-
##
|
|
158
|
+
## Thank you 🙏 — no strings attached
|
|
159
|
+
|
|
160
|
+
If you are reading this, you might be about to try this skill — and that already means a lot.
|
|
161
|
+
|
|
162
|
+
**Even a single download is real encouragement to me.** It tells me this skill is useful to someone out there, and that is the whole reason I keep building it. You don't owe me anything: use it for months on a serious codebase, or just `npx` it once to see how it feels and walk away. Both are completely fine. **No commitment, no lock-in, no pressure.**
|
|
163
|
+
|
|
164
|
+
> ขอบคุณจริง ๆ สำหรับการดาวน์โหลดและทดลองใช้ครับ 🙏
|
|
165
|
+
> แค่ **1 download** ก็เป็นกำลังใจดี ๆ ให้ผมแล้วว่า skill นี้มีประโยชน์ต่อใครสักคน
|
|
166
|
+
> จะใช้ยาว ๆ กับงานจริง หรือลองเล่นแล้วเลิกก็ได้ — **ไม่ผูกมัดอะไรทั้งนั้น** ขอบคุณที่ให้โอกาสครับ
|
|
114
167
|
|
|
115
|
-
|
|
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 หนึ่งโหมด
|
|
168
|
+
If it saved you from one "it works" that didn't, it did its job. ❤️
|
|
124
169
|
|
|
125
170
|
---
|
|
126
171
|
|
|
127
|
-
##
|
|
172
|
+
## Core philosophy
|
|
128
173
|
|
|
129
174
|
> "ขอเวลาห้านาทีเพื่อทำให้ถูก ดีกว่าทำผิดไปห้าชั่วโมง" — **การปฏิเสธคือฟีเจอร์**
|
|
175
|
+
>
|
|
176
|
+
> *"Five minutes to get it right beats five hours doing the wrong thing"* — **refusal is a feature.**
|
|
130
177
|
|
|
131
|
-
|
|
178
|
+
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.
|
|
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
|
package/hooks/verify-guard.sh
CHANGED
|
@@ -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
|
-
|
|
55
|
-
|
|
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.
|
|
3
|
+
"version": "1.3.1",
|
|
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
|
-
|
|
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.
|