From ec5e30e6ede1ccfc243209ca5b0b413ccdc2036b Mon Sep 17 00:00:00 2001 From: nntrivi2001 Date: Mon, 20 Jul 2026 15:23:46 +0700 Subject: [PATCH] docs: publish skills via public GitHub marketplace, fix md-writing overfitting leak --- README.md | 8 +++++--- plugins/dev/skills/md-writing/SKILL.md | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index cd6961d..eedd7fb 100644 --- a/README.md +++ b/README.md @@ -51,11 +51,11 @@ Tài liệu này tổng hợp các công cụ, cấu hình và phương pháp gi ### Marketplace nội bộ Smartgift -Chính repo này cũng là một **marketplace Claude Code**. Đăng ký một lần rồi cài plugin theo vai trò: +Bộ skill này được phát hành công khai trên GitHub — **ai cũng cài được, không cần tài khoản gitea**. Đăng ký marketplace một lần rồi cài plugin theo vai trò: ```bash -# 1. Đăng ký marketplace (một lần) -claude plugin marketplace add https://git.smartgift.io.vn/smartgift/claude-code-docs.git +# 1. Đăng ký marketplace (một lần) — public, không cần auth +claude plugin marketplace add nntrivi2001/smartgift-claude-skills # 2. Chọn MỘT plugin claude plugin install smartgift-all@smartgift # toàn bộ (khuyến nghị) @@ -63,6 +63,8 @@ claude plugin install smartgift-dev@smartgift # chỉ md-writing (team de claude plugin install smartgift-common@smartgift # chỉ prompt-sharpening ``` +> Nguồn công khai: https://github.com/nntrivi2001/smartgift-claude-skills + | Plugin | Skill | Dùng cho | |---|---|---| | `smartgift-all` | `md-writing` + `prompt-sharpening` | Mặc định — ai muốn tất cả | diff --git a/plugins/dev/skills/md-writing/SKILL.md b/plugins/dev/skills/md-writing/SKILL.md index 4abea15..e88b6b4 100644 --- a/plugins/dev/skills/md-writing/SKILL.md +++ b/plugins/dev/skills/md-writing/SKILL.md @@ -19,8 +19,8 @@ A rules file records the **owner's decisions**, not your opinion of the code. NE - **Create mode** (no `.md` set exists, or user asks for a from-scratch overhaul): full workflow below, steps 0–6. - **Update mode** (a `.md` set already exists): do NOT rewrite from scratch — the existing files hold owner-confirmed intent you must not lose. Instead: - 1. Find the sync baseline: the `Last synced: ` marker in root (fall back to the `.md` files' own last-modified commits). - 2. `git diff ..HEAD` (or review the just-made changes) → list every `.md` statement the diff invalidates: moved paths, renamed symbols, new/changed extension points, retired or new rules, new modules with no `.md` yet. + 1. Find the sync baseline: the `Last synced: ` marker in root. If the project is not a git repo (or the root is a non-git workspace of multiple repos), use the `Last synced:` timestamp instead and diff against the most recent code change after it; per-sub-repo files get their own baseline. + 2. Diff against that baseline (`git diff`, file mtimes, or manual review of the just-made changes) → list every `.md` statement the diff invalidates: moved paths, renamed symbols, new/changed extension points, retired or new rules, new modules with no `.md` yet. 2b. **Verify against the ACTUAL current state before asking anything — investigate, don't guess.** The diff tells you what changed; it does NOT tell you what is now true. Before forming any proposed update, open the current code and confirm each candidate change against reality: does the symbol/path still exist at the new location (grep it), is the new extension point really the canonical one (not a temporary/duplicate), did the logic actually change behavior or just move, does a `.md` statement you think is now wrong actually contradict the code as it stands now? EVERY question you ask the user must be one you could NOT answer yourself from the code — never ask to confirm something a 30-second grep settles. A question that reveals you didn't check is worse than no question. This is step-1's "investigate first" applied to update mode. 3. **Confirm BEFORE writing (always ask, never silent-write).** After a task changes code, do not touch the `.md` files until the user confirms. Present the proposed sync as a **plan-mode question in tiếng Việt**: list each `.md` file that would change and the one-line diff for each (what statement becomes what), then ask to proceed — with proceeding as the recommended answer, e.g. "Task vừa xong đổi `X`. Đề xuất cập nhật 2 file .md: `root` (đổi path A→B), `module/Y` (thêm extension point Z). Cập nhật luôn nhé? [Recommend: có]". Options at least: cập nhật tất cả / chọn file / bỏ qua. Do NOT write any `.md` before this confirmation. 4. On confirm, update ONLY the affected (and approved) files; new intent questions (if any) still go through the step-2 interview style — one at a time, recommended answer first, tiếng Việt. @@ -30,7 +30,7 @@ A rules file records the **owner's decisions**, not your opinion of the code. NE ### 0. Draft the raw facts — don't blank-page - **Root draft:** run `/init` (or open the existing file) for a raw scan of the project. -- **Module drafts:** `/init` does not cover modules — dispatch **Explore subagents in parallel, one per module, in a single message**, each reporting that module's raw facts (structure, patterns, extension-point candidates, commands). On a large repo this beats sequential reading by a wide margin. +- **Module drafts:** `/init` does not cover modules — dispatch **Explore subagents in parallel, one per module, in a single message**, each reporting that module's raw facts (structure, patterns, extension-point candidates, commands). Match the cost to the size: a small project (a few dozen files) reads fine inline; only dispatch subagents when the tree is too big to read in one pass. Treat all drafts as **facts to be transformed**, never as finished files. The whole job below is turning drafts into constraints. @@ -59,17 +59,17 @@ Write the files so this works (root routes precisely; each module file is self-s **Check-before-create rule — every root file MUST contain it.** Alongside the reuse map, every root `.md` you write must carry this standing rule for future work: "Before creating ANYTHING new — table, function, class, variable, config key, file, endpoint — FIRST check whether something with the same purpose or reusable already exists: search the reuse map in the relevant `.md`, then grep the code. If it exists, extend/reuse it; do NOT create a parallel one. Only create new after confirming nothing covers it." The reuse map makes the check cheap; this rule makes it mandatory — the map alone did not stop agents from building parallel structures. -**Anti-rot sync rule — every root file MUST contain it.** The set goes stale the moment code changes: paths move, extension points appear, rules stop being true — and a stale routing table is worse than no file (the model trusts it). So every root `.md` you write must carry this standing rule for future work: "Any change that makes a statement in any `.md` file wrong (moved path, new/changed extension point, retired rule) MUST update that `.md` in the same change." When YOU edit code in a project that has this file set, obey it too. Root also carries a **`Last synced: ` marker** — set it when writing, bump it on every sync; it is update mode's diff baseline. +**Anti-rot sync rule — every root file MUST contain it.** The set goes stale the moment code changes: paths move, extension points appear, rules stop being true — and a stale routing table is worse than no file (the model trusts it). So every root `.md` you write must carry this standing rule for future work: "Any change that makes a statement in any `.md` file wrong (moved path, new/changed extension point, retired rule) MUST update that `.md` in the same change." When YOU edit code in a project that has this file set, obey it too. Root also carries a **`Last synced:` marker** — set it when writing (git commit hash when available, otherwise timestamp) and bump it on every sync; it is update mode's diff baseline. **Layering — root = routing map, module = deep:** - **Root** — answers "what is this project, how do the pieces connect, and which file do I read next?". Contains: project identity (domain + stack), an **architecture table where each row points to that module's `.md`** (columns: part | role | "details at → path/CLAUDE.md"), global cross-cutting rules only, and build/test commands. The routing table is the token-saver: the model reads root, jumps straight to the right module file, never scans the tree. - **Module files** — go deeper and more specific for that part: its function, requirements, business logic, technology, mandatory patterns ("new X MUST extend Y"), and its own gotchas/prohibitions. This is where detail lives; the module still obeys "constrain not describe" (every line non-inferable intent/gotcha/prohibition), just at finer grain than root. - **Reuse map / feature inventory — the highest-value content.** For each existing feature/capability, spell out in detail WHAT already exists and WHERE every piece lives, across all layers, so nothing gets rebuilt. Per feature: - - **backend** — service/repo/controller paths (e.g. `app/Repositories/Blacklist/BlacklistRepository.php`) + - **backend** — service/repo/controller paths (e.g. `app/Repositories/Widget/WidgetRepository.php`) - **frontend/UI** — screens/components that expose it - - **database** — tables, enums, migrations (e.g. `blacklist` table, `ListType` enum) + - **database** — tables, enums, migrations (e.g. `widgets` table, `WidgetKind` enum) - **how to verify it works** — endpoint, port, command, or admin screen to check it live - - **extension point** — the imperative: "new list/blacklist types extend THIS table + THIS enum — do NOT create a parallel table" + - **extension point** — the imperative: "new widget kinds extend THIS table + THIS enum — do NOT create a parallel table" Field evidence: without this inventory, 3 of 4 test agents (including strong models WITH the .md) invented a parallel table; base-class rules alone did not prevent it. Strong models infer framework patterns on their own — what NO model infers is which existing domain structure already covers a feature and must be extended. Hunt for these in step 1 (enums, type-discriminated tables, generic repos/services, existing UI) and confirm each in the step-2 interview. - **Length follows content, not a quota.** Be detailed, complete, and accurate — include EVERY confirmed intent, invariant, gotcha, and prohibition, however many lines that takes. The only thing to cut is what the model can already read from code; never cut a real constraint to hit a size target. @@ -81,7 +81,7 @@ Produce the full list: every dir/module and the constraints each `.md` will hold - **Imperative prohibitions** (KHÔNG / CHỈ / PHẢI / NEVER / ONLY), not descriptions. Weak models obey commands, not implied intent. - Every gotcha names its **consequence** ("…else the request is rejected by the Gateway before the action runs"). - "Looks like a bug but is intentional" → say so + why, or the model will "fix" it. -- Anchor to **stable symbols** (class/method/table/enum names, e.g. `BlacklistRepository::updateListTypeFile`), not line numbers — lines drift after a few commits; use `file:line` only when no named symbol exists. On any duplication/smell you must mention, add **"describe current state — do NOT change."** +- Anchor to **stable symbols** (class/method/table/enum names, e.g. `WidgetRepo::archiveOld`), not line numbers — lines drift after a few commits; use `file:line` only when no named symbol exists. On any duplication/smell you must mention, add **"describe current state — do NOT change."** - Module rules → that module's file (scope). Don't dump into root. **Calibrate to the weakest model, without handcuffing the strongest.** Write so that the WEAKEST model that will ever read this (a Haiku-class model, a small local model) can complete a hard task in this module without struggling: full context — every location, contract, invariant, verify command, extension point it needs — spelled out, nothing left to "it will figure it out". But supply that as **context + constraints + pointers, never as recipes**: state WHAT must hold, WHERE things live, and what is FORBIDDEN — do not dictate step-by-step procedures or paste ready-made code snippets to copy. A strong model must stay free to choose its own implementation; a weak model must never be missing a fact it needed. If a line prescribes HOW to write the code rather than what must be true of it, cut the how, keep the what. @@ -91,7 +91,7 @@ Subagents do NOT auto-load CLAUDE.md files. If the workflow dispatches subagents ### 6. Verify with a weak model — the set is not done until it passes Writing the files is not the finish line; field evidence shows a set that LOOKS complete can still fail (a strong model with the .md still built a parallel table). After writing: -1. Pick 1–2 realistic one-line feature requests for this codebase (e.g. "Thêm chức năng blacklist cho địa chỉ IP") — ideally one the user suggests. +1. Pick 1–2 realistic one-line feature requests for this codebase (e.g. "Thêm chức năng rate limit theo IP cho endpoint public") — ideally one the user suggests. 2. Dispatch a **weak-model subagent** (Haiku-class) with ONLY that request plus "read the CLAUDE.md files starting from root, follow their reading protocol" — no other hints. Plan-only is enough: ask it to output its implementation plan, not apply edits. 3. Grade against the handover test: correct module? reused the named extension point (no parallel structure)? followed the mandatory patterns? minimal scope? 4. Any failure = a missing or unclear line in the `.md` set, never the subagent's fault. Fix the file, re-run until it passes. @@ -107,7 +107,7 @@ Report the verification result to the user as part of delivery. | "CSP is permissive with `unsafe-inline`" | "CSP `unsafe-inline` is REQUIRED (jQuery/GA). Don't tighten without testing inline scripts." | | "`LotteryService` uses `getUserIndex() % ratioCycle`" | "Lottery is deterministic ON PURPOSE — NOT random. Don't 'fix' to `rand()`." | -**Inventory paths are NOT noise.** "Delete what the model reads from code" applies to structure trivia (registration order, config keys). It does NOT apply to the reuse map: a path is only readable from code if the model already knows to look there — the inventory's job is exactly that routing ("blacklist already exists: backend at a, frontend at b, DB at c, verify via port 123"). Keep those. +**Inventory paths are NOT noise.** "Delete what the model reads from code" applies to structure trivia (registration order, config keys). It does NOT apply to the reuse map: a path is only readable from code if the model already knows to look there — the inventory's job is exactly that routing ("feature X already exists: backend at a, frontend at b, DB at c, verify via port 123"). Keep those. ## Checklist before writing any line 1. Can the model read this from code? → **delete** (noise) — EXCEPT reuse-map/feature-inventory lines (see above).