agentsclimarketplace

Dev gate

Skill shode666/claude-skill-shode-house/skills/workflow/dev-gate

[WHAT] บังคับ TDD cycle (red → green → refactor) + quality gate (format/lint/type/complexity/naming/test/doc) ก่อน hand-off production code. [AUDIENCE] Dave (implement) + Chris (verify) — sole owners. [WHEN] Phase 2 implement / refactor / bug-fix; ก่อน push หรือ open PR; หลัง spec ครบจาก Phase 1. [TRIGGER] /shode-house:dev-gate, "TDD", "test first", "red-green-refactor", "clean code", "เน้น quality", "production code", "refactor", "เริ่มเขียน code".From its SKILL.md

Install
npx -y skills add shode666/claude-skill-shode-house --skill dev-gate

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

20.5 KB, as published. Nobody here has run it

Dev Gate (TDD + Quality Gates) — v3.0 merged

Owner: Dave (implement) + Chris (verify). เปิด skill นี้ตอนเขียน production code Merged from v2 skills: tdd + code-quality — ลด context, รวม dev-time discipline

When NOT to use

  • Spike / prototype / throwaway script — TDD overhead ไม่คุ้ม. ใช้ diagnose แทนถ้าเป็น exploration
  • Generated code (codegen, OpenAPI client, ORM model) — gen tool ดูแล quality, dev-gate ไม่ฟิต
  • Pure config change (yaml/json/env tweak) — review + smoke test พอ ไม่ต้อง TDD
  • Production hot-fix P0/P1 — ใช้ incident skill ก่อน; dev-gate ตามมาตอน follow-up fix

Required inputs — refuse without

ก่อน hand-off Phase 2 → 3, confirm ทุก checklist. ถ้าขาด list สิ่งที่ขาด แล้วหยุด — ห้าม claim "done":

  • Spec ครบ จาก Phase 1 (BRD + AC G-W-T + ADR ที่กระทบ)
  • Test runs locally (red phase): ทุก new behavior มี failing test ก่อน implement
  • Test pass (green): ทุก unit/integration test green; ไม่ skip/disable
  • Quality gate ผ่านครบ 11 (Gate 0-10, ดู Part 2): YAGNI · format · lint · type · complexity ≤10 · naming · test · coverage ≥ threshold · doc/comment "why" · security · observability
  • Evidence paste: command + output ใน hand-off (ห้าม "should work")

หลักการ (🔴)

  1. No production code without failing test first (TDD core)
  2. Quality at dev time, not after — fix early ถูกกว่า 100x
  3. Best code = code you never wrote — ผ่าน YAGNI ladder (Step 0) ก่อนทุกครั้ง

Lazy ≠ Negligent — ห้ามตัด (carve-out)

YAGNI/compression ตัดได้เฉพาะ "ความซับซ้อนที่ยังไม่ต้องใช้" — ห้ามแตะ:

  • Trust-boundary validation (input/HTTP/queue/env — Zod/Pydantic)
  • Data-loss handling (transaction, idempotency, money R0)
  • Security control (auth, crypto, secret, injection guard)
  • Accessibility (WCAG — Uma's gate)
  • Regulation/compliance (Felix BOT/PCI · Iris OIC · domain rule)

ตัดของเหล่านี้ = Philosophy violation, ไม่ใช่ "lazy"


Part 1: TDD Cycle (red → green → refactor)

0. ⛔ YAGNI ladder — หยุดก่อนเขียน (จาก ponytail)

ก่อนเขียน production code ใด ๆ ตอบไล่จากบนลงล่าง หยุดที่ข้อแรกที่ "ใช่":

ขั้นถามถ้าใช่
1feature นี้ต้องมีจริงไหม?ไม่ → skip (YAGNI) + log เป็น bd discovered
2stdlib ทำได้ไหม?ใช้ stdlib
3native platform feature? (<input type=date>, crypto, ...)ใช้ native
4dep ที่ลงแล้วทำได้?ใช้ของเดิม ห้ามลง dep ใหม่
5one-liner พอไหม?เขียนบรรทัดเดียว
6ถ้าผ่านทั้งหมดเขียน "ขั้นต่ำที่ work" เท่านั้น

ทุกครั้งที่ตัด (ขั้น 1) หรือใช้ทางลัด → mark ด้วย shortcut(bd:N): comment (ดู Gate 3) เพื่อให้ debt harvest เก็บได้ เพดานความขี้เกียจ = carve-out ด้านบน (validation/security/a11y/regulation ห้ามตัด)

1. 🔴 Red — เขียน test ที่ fail ก่อน

  • Test เล็กที่สุด — 1 behavior
  • Naming: should_<behavior>_when_<condition> หรือ G-W-T
  • Run → ต้อง fail (assertion fail; compile error ไม่นับ)
def test_calculate_total_with_vat_includes_7_percent():
    cart = Cart(items=[Item(price=Decimal("100"))])
    total = cart.total_with_vat(rate=Decimal("0.07"))
    assert total == Decimal("107.00")

2. 🟢 Green — เขียน code น้อยที่สุดที่ pass

  • Simplest thing that works (YAGNI)
  • ห้าม anticipate future requirement
  • ห้าม refactor ตอนนี้

3. 🔵 Refactor — clean up (test ยัง pass)

  • Remove duplication, improve naming, extract function
  • ห้ามเพิ่ม behavior ใหม่ในรอบ refactor

TDD scope

✅ เหมาะ: business logic, calc, validation, state machine, parser, algorithm, bug-fix regression ❌ ไม่เหมาะ: UI prototype, spike, pure framework integration


Part 2: Quality Gates (🔴 11 gates — รัน local + pre-commit + CI)

เปลี่ยน v3.1.1: เพิ่ม Gate 0 Architecture self-check (SOLID/cohesion/readable) + เพิ่ม Gate 9 Security Lint. แตก Format เป็น Format / Imports / Remove-Unused เพราะ 3 หมวดใช้ tool ต่างกัน

#GateRead/Writeตรวจอะไรบล็อก hand-off ถ้า fail
0Architecture self-checkRead (judgment)SOLID + cohesion + human-readable🟠 (Dave judge; Chris verify)
1FormatWrite (rewrite style)indent/space/quote/line-length🔴
2Organize ImportsWrite (sort+group)stdlib/3rd-party/local + alpha sort🔴
3Remove UnusedWrite (delete)unused import/var/function/parameter🔴
4LintRead (diagnose)code smell + rule violation🔴
5Type CheckRead (diagnose types)--strict, no Any/any escape🔴
6ComplexityRead (measure)cyclomatic ≤ 10, file ≤ 500, fn ≤ 50🔴
7NamingRead (convention check)noun/verb/bool/const pattern🟠
8TestRuncoverage ≥ 80%, no skipped test🔴
9Security LintRead (SAST)injection/secret/insecure dep🔴
10DocRead (existence)docstring on public API + "why" comment🟠

Gate 0: Architecture self-check (🔴 v3.1.1 added — Dave's judgment ก่อน hand-off)

Tool ตรวจ Gate 1-10 ได้ครบ แต่ SOLID/cohesion/readable ต้องคนตัดสิน. Dave self-check ก่อน hand-off ลด round-trip กับ Chris

SOLID (5 ข้อ — ตอบ "yes" ทุกข้อก่อน hand-off):

  • SRP — class/function ทำสิ่งเดียว. "และ" ใน description = แตก
  • OCP — extend ได้ผ่าน interface/composition โดยไม่ต้องแก้ class เดิม
  • LSP — subclass แทน parent ได้ทุก context (ไม่ throw, ไม่ break invariant)
  • ISP — interface เล็ก. ห้าม "fat interface" ที่ implementor ต้อง stub method ที่ไม่ใช้
  • DIP — depend on abstraction (interface/protocol) ไม่ใช่ concrete class. business logic ห้าม import framework โดยตรง

Cohesion + Coupling:

  • High cohesion — code ในไฟล์เดียวกันแก้ปัญหาเดียว. ถ้า "และ" ปะปน → แตก module
  • Low coupling — module A ไม่ควรรู้ internal ของ module B. ผ่าน interface/event/DTO
  • Stable dependency — depend ไปทาง stable (lower layer). ห้าม domain → infra direct

Human readability (ก่อน push อ่าน diff ตัวเอง 1 รอบ):

  • Intent revealing — ชื่อ + structure บอกเจตนาได้โดยไม่ต้องอ่าน implementation
  • Linear flow — อ่าน top-to-bottom เข้าใจได้. ห้ามกระโดดข้าม helper > 3 hop
  • Comment "why" — code อ่านได้แล้ว; comment เฉพาะตอน trade-off / business rule / quirk
  • Symmetry — pattern ซ้ำในไฟล์ใช้ shape เดียวกัน (อ่าน 1 รอบเข้าใจ 10)
  • Abstraction level — function เดียวอย่าผสม high-level + low-level (e.g., business logic + bit twiddling)

Self-check format ตอน hand-off:

Dave ▸ Chris : impl bd-42 (dev-gate passed 1-10)
- Gate 0 self-check:
  - SOLID: SRP ✓ OCP ✓ LSP ✓ ISP ✓ DIP ✓
  - Cohesion: high (1 module = 1 concern)
  - Readable: diff อ่านแล้ว linear; no surprise
- Trade-off documented: <link to comment line:N> (if any)

ถ้า self-check fail → refactor ก่อน hand-off ห้าม "Chris จะ review ให้". Chris จะ reject + bd revision รอบใหม่

Per-language tool matrix (🔴 บังคับ use ตาม stack)

Stack1 Format2 Imports3 Unused4 Lint5 Type6 Complexity9 Security
Pythonruff format / blackruff --fix I / isortruff --fix F401,F841ruff E,F,B,N,UP,S,A,C90,SIM,RETmypy --strictradon cc -nbbandit / semgrep
TypeScript/JSbiome format / prettierbiome check --apply / eslint-plugin-import/ordereslint --fix no-unused-vars,no-unused-imports / ts-unused-exportsbiome check / eslint @typescript-eslint/stricttsc --strict --noUncheckedIndexedAccesseslint complexitynpm audit / semgrep
Gogofmt / goimportsgoimports (built-in)golangci-lint unusedgolangci-lint (govet,staticcheck,ineffassign,unused,gosec)(compile = check)gocyclo -over 10gosec (in golangci)
Javagoogle-java-format / spotlessspotless (importOrder)error-prone UnusedVariablespotbugs + checkstyle@Nullable/@NonNull strictpmd CyclomaticComplexityspotbugs (FindSecBugs)
Kotlinktfmt / ktlintktlint (import-ordering)detekt UnusedImportsdetekt(compile + -Werror)detekt complexity rulesdetekt (detekt-formatting)
Rustcargo fmt (rustfmt)rustfmt (built-in)cargo +nightly udepscargo clippy -- -D warnings(compile = check)clippy cognitive_complexitycargo audit
Vue/Nuxtprettier + biomebiomeeslint-plugin-vue + ts-unused-exportseslint-plugin-vue + biometsc + vue-tsceslint complexitynpm audit
PHPphp-cs-fixer / pintphp-cs-fixer (ordered_imports)rector dead-codephpstan / psalmphpstan strictphpmdcomposer audit

Rule: ใช้ all-in-one tool (Ruff / Biome / golangci-lint) ดีกว่า stitch หลาย tool — boundary error น้อย, config เดียว

Gate 1: Format

  • Auto-format on save (IDE) + pre-commit hook + CI gate (3 จุด)
  • ห้าม: manual format / "ไม่ตรง project standard but readable"

Gate 2: Organize Imports (🔴 v3.1 split out)

  • Sort + group: stdlib → 3rd-party → local
  • Alpha-sort within group
  • ห้าม wildcard import (from x import * / import *)
  • ห้าม relative .. import เกิน 1 level

Gate 3: Remove Unused (🔴 v3.1 split out)

  • Unused import → ลบ (F401 / no-unused-vars)
  • Unused local variable → ลบ (F841)
  • Unused function parameter → ลบ หรือ prefix _ ถ้าจำเป็นต้องเก็บ signature
  • Unused function/class export → ลบหรือ mark internal (ts-unused-exports / vulture)
  • ห้าม # noqa / // eslint-disable โดยไม่ comment "why" + bd track

Deferred-shortcut convention (จาก ponytail — ทางลัดที่ YAGNI ladder ตัดไว้):

  • รูปแบบบังคับ: shortcut(bd:<id>): <reason>; upgrade → <path>
  • ตัวอย่าง: # shortcut(bd:42): in-memory dict; upgrade → Redis เมื่อ >10k key
  • grep -rn 'shortcut(bd' . / /review --debt รวบเป็น ledger → "later" ไม่กลาย "never"
  • ห้าม shortcut โดยไม่มี bd id (ต้อง track ได้)

Gate 4: Lint (strict — diagnose)

  • ดู per-language matrix; เปิด strict rule set ทั้งหมด ไม่ใช่ default ที่อ่อน
  • Lint warning = bd issue (track หรือ fix); ห้าม ignore

Gate 5: Type Check (🔴 strict)

  • Py: mypy --strict — ห้าม Any เลี่ยงได้
  • TS: tsc --strict --noUncheckedIndexedAccess — ห้าม any, ใช้ unknown + narrow
  • Java: explicit null annotation (@Nullable/@NonNull)
  • ห้าม # type: ignore / // @ts-ignore / @SuppressWarnings โดยไม่ ticket

Gate 6: Complexity

  • Cyclomatic ≤ 10 / function
  • Cognitive ≤ 15 / function
  • Function ≤ 50 บรรทัด (≤ 30 ดีกว่า)
  • File ≤ 500 บรรทัด
  • Nesting ≤ 3 (early return / guard clause แทน)

Gate 7: Naming

  • Variable: noun ที่บอก what (ไม่ใช่ data/info/temp)
  • Function: verb_noun (calculate_total)
  • Boolean: is_*/has_*/should_*/can_*
  • Constant: UPPER_SNAKE
  • ห้าม abbreviation ที่ไม่เป็นมาตรฐาน
  • ห้าม magic number/string → constant + comment "why"

Gate 8: Test

  • Unit coverage ≥ 80% business logic (Chris's responsibility; Dave smoke ก่อน hand-off)
  • AAA pattern + G-W-T naming
  • Edge case + error path
  • ห้าม skipped/disabled test ไม่มี bd track

Gate 9: Security Lint (🔴 v3.1 added)

  • SAST per language (ดู matrix Gate 9 column)
  • Secret scan (gitleaks / git-secrets) — block commit ที่มี API key / password / cert
  • Dependency audit (npm audit / pip-audit / cargo audit) — block critical/high vulns
  • ห้าม: ignore security warning โดยไม่ Sentinel approve

Gate 10: Doc

  • Docstring/JSDoc สำหรับ public API (signature + example + edge case)
  • Inline comment เฉพาะ "why" ไม่ใช่ "what"
  • README update ถ้า API change

Pre-commit hook (🔴 v3.1 — บังคับทุก repo)

ติดตั้ง pre-commit (pre-commit.com) + .pre-commit-config.yaml:

# .pre-commit-config.yaml — Python project example
repos:
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.6.0
    hooks:
      - id: ruff-format         # Gate 1
      - id: ruff                # Gate 2+3+4 (--fix organize+unused+lint)
        args: [--fix, --exit-non-zero-on-fix]
  - repo: https://github.com/pre-commit/mirrors-mypy
    rev: v1.11.0
    hooks:
      - id: mypy                # Gate 5
        args: [--strict]
  - repo: https://github.com/pycqa/bandit
    rev: 1.7.9
    hooks:
      - id: bandit              # Gate 9
        args: [-c, pyproject.toml]
  - repo: https://github.com/gitleaks/gitleaks
    rev: v8.18.4
    hooks:
      - id: gitleaks            # Gate 9 secret scan
# .pre-commit-config.yaml — TS/JS project example
repos:
  - repo: https://github.com/biomejs/pre-commit
    rev: v0.5.0
    hooks:
      - id: biome-check         # Gate 1+2+3+4 (format + imports + unused + lint)
        args: [--apply]
  - repo: local
    hooks:
      - id: tsc
        name: TypeScript strict
        entry: npx tsc --noEmit --strict
        language: system
        types: [ts]
      - id: ts-unused-exports
        name: Unused exports
        entry: npx ts-unused-exports tsconfig.json
        language: system
        pass_filenames: false
  - repo: https://github.com/gitleaks/gitleaks
    rev: v8.18.4
    hooks:
      - id: gitleaks

Setup steps:

pip install pre-commit              # หรือ brew install pre-commit
pre-commit install                  # ติด git hook
pre-commit run --all-files          # รัน lint ทั้ง repo ครั้งแรก

ทุก git commit จะถูก block ถ้า gate ใด fail. ห้าม --no-verify (bypass) ใน production code


Quality Smells (🚫 reject)

SmellWhy badFix
God class (> 500 lines)hard to test/changeextract module
Long parameter list (> 4)hard to readparameter object
Duplicate codeDRY violationextract function
Deep nesting (> 3)cognitive loadearly return / guard clause
Magic number/stringmeaning unclearnamed constant
Comment explaining hackcode smellrefactor + remove comment
try ... passswallow errorlog + re-raise / handle
Unused import / variabledead codeลบ ห้าม keep "for later"
Wildcard import (from x import *)namespace pollutionexplicit import

Pre-Push Checklist (🔴 v3.1.1 — all 11 gates)

# Gate 0 — Architecture self-check (Dave answers each checkbox above ก่อนรัน mechanical gates)

make fmt          # Gate 1 — auto-format
make imports      # Gate 2 — organize imports
make clean-unused # Gate 3 — remove unused (CI auto-fail if anything found)
make lint         # Gate 4 — strict lint
make typecheck    # Gate 5 — strict types (no Any/any)
make complexity   # Gate 6 — cyclomatic + size limits
make test         # Gate 8 — unit + coverage
make security     # Gate 9 — SAST + secret scan + dep audit
make doc-check    # Gate 10 — public API docstring present

หรือเรียก make pre-push ที่รวมทุก mechanical gate ในคำสั่งเดียว:

# Makefile snippet
pre-push: fmt imports clean-unused lint typecheck complexity test security doc-check
	@echo "✅ Gates 1-10 pass — Dave: confirm Gate 0 self-check before push"

ทุก check ผ่าน → ค่อย push. CI ก็ต้องรันชุดเดียวกัน (pre-commit + GitHub Actions / GitLab CI / CircleCI)

Gate 0 ไม่อยู่ใน Makefile — ตั้งใจให้ Dave หยุดคิด 30 วินาทีก่อน push, ไม่ใช่ auto-pass. มันคือ judgment ไม่ใช่ tool


Hand-off

Dave  ▸ Chris   : impl + smoke (dev-gate passed)
Chris ▸ Quinn   : 7-dim + unit ≥ 80% + mutation ≥ 70%

ห้าม

  • ห้ามเขียน code ก่อน test (TDD core)
  • ห้าม commit test ที่ยัง fail (ใช้ skip/xfail + bd issue)
  • ห้าม refactor พร้อม add behavior — แยก commit
  • ห้าม mock business logic — mock เฉพาะ external (DB/API/clock)
  • ห้ามใช้ time.sleep ใน test → fake time/freeze
  • ห้าม disable lint rule โดยไม่ comment + bd track
  • ห้าม // @ts-ignore / # type: ignore โดยไม่ ticket
  • ห้าม commit console.log / print debug
  • ห้ามใช้ any (TS) / Any (Py) เป็นทางลัด
  • ห้าม PR ที่ลด coverage (CI ตั้ง gate, ratchet)
  • ห้าม merge code ที่ build แดง

Skill composition (where to go next)

SituationNext skillReason
Test pass แต่ยังไม่มี CI gate→ automate-testPyramid ratio + CI threshold + contract test (dev-gate = per-task; automate-test = project-wide)
Code touches frontend→ ui-testE2E + visual + a11y automation (dev-gate ไม่ครอบ visual)
Frontend public-facing (perf/SEO/security)→ web-qCWV + Lighthouse + security headers budget
Touch security control (auth/crypto/PII)→ secureSentinel threat model + abuse case (dev-gate ไม่ classify threat)
Hand-off Phase 2 → 3b review→ review-checklist skillChris 7-dim + Quinn integration matrix (used by /implement Phase 3b + /review)

Keep looking

Skills are one crate of 626,194. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.