From 33c2c304c6cca4e09fd48ed21839142ef755f496 Mon Sep 17 00:00:00 2001 From: yaojingang Date: Mon, 6 Apr 2026 20:05:48 +0800 Subject: [PATCH] refine reference scan source priorities --- README.md | 6 ++- SKILL.md | 2 +- docs/README.fr-FR.md | 2 +- docs/README.ja-JP.md | 2 +- docs/README.ru-RU.md | 2 +- docs/README.zh-CN.md | 2 +- references/reference-scan.md | 26 ++++++++-- references/skill-engineering-method.md | 2 + scripts/render_reference_scan.py | 69 ++++++++++++++++++++------ scripts/yao.py | 6 +++ tests/verify_reference_scan.py | 10 ++-- tests/verify_yao_cli.py | 4 +- 12 files changed, 102 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index fc7f55f7..0bbfb4ed 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ Read it in 10 seconds: ## Quick Start 1. Describe the workflow, prompt set, or repeated task you want to turn into a skill. -2. Run a short reference scan so the package can borrow strong patterns without copying extra weight. +2. Run a short reference scan with external benchmarks first, then use local files only for fit and privacy checks. 3. Use `yao-meta-skill` to generate or improve the package in scaffold, production, or library mode. 4. Run `context_sizer.py`, `resource_boundary_check.py`, `governance_check.py`, `trigger_eval.py`, and `cross_packager.py` as needed to validate and export the result. @@ -55,7 +55,9 @@ Or use the unified authoring CLI: ```bash python3 scripts/yao.py init my-skill --description "Describe what the skill does." -python3 scripts/yao.py reference-scan my-skill --reference "World Class Method::method::Borrow a tight evaluation loop.::Do not copy heavy process." +python3 scripts/yao.py reference-scan my-skill \ + --external-reference "World Class Method::method::Borrow a tight evaluation loop.::Do not copy heavy process." \ + --local-constraint "Current Library Naming::structure::Keep naming aligned with the local skill library.::Do not inherit private references." python3 scripts/yao.py skill-report my-skill python3 scripts/yao.py package . --platform generic --output-dir dist ``` diff --git a/SKILL.md b/SKILL.md index 723782a3..101dddff 100644 --- a/SKILL.md +++ b/SKILL.md @@ -28,7 +28,7 @@ Mode rules: [Operating Modes](references/operating-modes.md), [QA Ladder](refere ## Compact Workflow 1. Decide whether the request should become a skill, then choose the lightest archetype. -2. Run a short reference scan to borrow patterns from strong benchmark objects without copying their prose or weight. +2. Run a short reference scan with external benchmark objects first, then use local files only for fit, privacy, and compatibility calibration. 3. Capture the recurring job, outputs, trigger phrases, and exclusions. 4. Write the `description` early, then test route quality before expanding the package. 5. Add only the folders and gates that earn their keep: `trigger_eval.py`, `optimize_description.py`, `judge_blind_eval.py`, `resource_boundary_check.py`, `governance_check.py`, `cross_packager.py`. diff --git a/docs/README.fr-FR.md b/docs/README.fr-FR.md index 232fe1b8..1c4967f2 100644 --- a/docs/README.fr-FR.md +++ b/docs/README.fr-FR.md @@ -37,7 +37,7 @@ Lecture en 10 secondes : ## Quick Start 1. Décrivez le workflow, l'ensemble de prompts ou la tâche répétée que vous voulez transformer en skill. -2. Lancez un court reference scan pour extraire les bons patterns sans copier la lourdeur des sources. +2. Lancez un court reference scan en privilégiant GitHub et les objets publics de référence ; les fichiers locaux ne servent ensuite qu'à l'ajustement, à la confidentialité et à la compatibilité. 3. Utilisez `yao-meta-skill` pour générer ou améliorer le paquet en mode scaffold, production ou library. 4. Chaque nouveau skill reçoit aussi `reports/skill-overview.html` et `reports/reference-scan.md`, pour comprendre rapidement son architecture, sa logique, son usage et ses références utiles. diff --git a/docs/README.ja-JP.md b/docs/README.ja-JP.md index 6d04119c..d719f82a 100644 --- a/docs/README.ja-JP.md +++ b/docs/README.ja-JP.md @@ -37,7 +37,7 @@ flowchart LR ## Quick Start 1. skill 化したい workflow、prompt 集合、または反復タスクを説明します。 -2. まず短い reference scan を行い、借りるべき pattern だけを抽出します。 +2. まず短い reference scan を行い、GitHub や世界トップ級の公開対象を主参照にし、ローカル資産は適合確認と privacy 調整だけに使います。 3. `yao-meta-skill` を使って scaffold、production、library のいずれかのモードでパッケージを生成または改善します。 4. 新しく作成した skill には `reports/skill-overview.html` と `reports/reference-scan.md` が付き、構造、ロジック、使い方、参考対象をすぐ確認できます。 diff --git a/docs/README.ru-RU.md b/docs/README.ru-RU.md index 792c89c8..99b3f1f3 100644 --- a/docs/README.ru-RU.md +++ b/docs/README.ru-RU.md @@ -37,7 +37,7 @@ flowchart LR ## Quick Start 1. Опишите workflow, набор prompts или повторяющуюся задачу, которую хотите превратить в skill. -2. Сначала выполните короткий reference scan, чтобы взять сильные паттерны без копирования лишней тяжести. +2. Сначала выполните короткий reference scan, где основными источниками будут GitHub и сильные публичные эталоны, а локальные файлы будут использоваться только для адаптации, приватности и совместимости. 3. Используйте `yao-meta-skill`, чтобы сгенерировать или улучшить пакет в режиме scaffold, production или library. 4. Каждый новый skill также получает `reports/skill-overview.html` и `reports/reference-scan.md`, чтобы быстро понять архитектуру, логику, способ использования и полезные ориентиры. diff --git a/docs/README.zh-CN.md b/docs/README.zh-CN.md index aa9203fe..c11cf162 100644 --- a/docs/README.zh-CN.md +++ b/docs/README.zh-CN.md @@ -37,7 +37,7 @@ flowchart LR ## Quick Start 1. 先描述你想沉淀成 skill 的 workflow、prompt 集合或重复任务。 -2. 先做一轮简短的参考扫描,提炼可借鉴模式,而不是直接复制现成做法。 +2. 先做一轮简短的参考扫描,以 GitHub 和世界级公开对象为主来源,本地文件只做适配和隐私校准。 3. 使用 `yao-meta-skill` 以 scaffold、production 或 library 模式生成或改进 skill 包。 4. 新建 skill 后,会默认附带 `reports/skill-overview.html` 和 `reports/reference-scan.md`,方便理解架构、逻辑、使用方法和可借鉴对象。 diff --git a/references/reference-scan.md b/references/reference-scan.md index 79f81e96..b975926f 100644 --- a/references/reference-scan.md +++ b/references/reference-scan.md @@ -2,6 +2,21 @@ Use a short benchmark scan before deep authoring. The goal is to borrow durable patterns from strong reference objects without importing their prose, weight, or brand language into the new skill. +## Source Priority + +Reference scan has two layers, and they must not be treated equally: + +1. **External Benchmark Scan** + - primary source of patterns + - use public GitHub repos, official docs, strong public examples, and world-class products + - this layer defines the upper bound for quality +2. **Local Fit Check** + - secondary calibration layer + - use local files only for naming, privacy, compatibility, migration, and library-fit constraints + - this layer should not define the main design pattern + +External sources should lead. Local files should calibrate. + ## Why This Step Exists A new skill often fails because it starts from an isolated idea instead of a proven pattern. A controlled reference scan improves the package before it grows: @@ -33,6 +48,7 @@ Do not turn this into open-ended research. - pick from no more than `3` categories - extract patterns, not long copied content - stop as soon as the borrow plan is clear +- prefer at least `2` external benchmark objects before treating the scan as complete ## Reference Categories @@ -50,10 +66,11 @@ A good scan produces a short report with: 1. current skill anchor 2. scan focus -3. `3-5` reference objects at most -4. what to borrow -5. what not to borrow -6. a compact borrow plan +3. external benchmark objects +4. local fit constraints +5. what to borrow +6. what not to borrow +7. a compact borrow plan ## What To Borrow @@ -72,6 +89,7 @@ Do not borrow: - unnecessary directories - quality gates that exceed the skill's risk tier - platform lock-in disguised as best practice +- local historical habits that are weaker than public top-tier benchmarks ## Design Principle diff --git a/references/skill-engineering-method.md b/references/skill-engineering-method.md index fab43263..348b7d18 100644 --- a/references/skill-engineering-method.md +++ b/references/skill-engineering-method.md @@ -58,6 +58,8 @@ Boundary work comes before polishing prose. Run a short benchmark pass before deep authoring. - scan `3-5` reference objects at most +- prioritize external GitHub and official benchmark sources first +- use local files second, only for fit, privacy, and compatibility calibration - choose from method, structure, execution, portability, and domain patterns - extract only what improves reliability or clarity - record what not to borrow so the new skill stays light diff --git a/scripts/render_reference_scan.py b/scripts/render_reference_scan.py index d9f9ea03..df0d858a 100644 --- a/scripts/render_reference_scan.py +++ b/scripts/render_reference_scan.py @@ -38,7 +38,7 @@ def extract_title(body: str, fallback: str) -> str: return fallback -def parse_reference(value: str) -> dict: +def parse_reference(value: str, source: str) -> dict: parts = [part.strip() for part in value.split("::")] while len(parts) < 4: parts.append("") @@ -48,6 +48,7 @@ def parse_reference(value: str) -> dict: "category": category or "general", "borrow": borrow or "Capture the reusable pattern, not the prose.", "avoid": avoid or "Do not copy source-specific language or unnecessary weight.", + "source": source, } @@ -83,6 +84,12 @@ def infer_scan_focus(skill_dir: Path, description: str) -> list[dict]: return checks[:4] +def split_references(references: list[dict]) -> tuple[list[dict], list[dict]]: + externals = [item for item in references if item.get("source") == "external"] + locals_ = [item for item in references if item.get("source") == "local"] + return externals, locals_ + + def build_summary(skill_dir: Path, references: list[dict]) -> dict: skill_text = (skill_dir / "SKILL.md").read_text(encoding="utf-8") frontmatter, body = parse_frontmatter(skill_text) @@ -90,28 +97,32 @@ def build_summary(skill_dir: Path, references: list[dict]) -> dict: description = frontmatter.get("description", "No description found.") title = extract_title(body, name.replace("-", " ").title()) focus = infer_scan_focus(skill_dir, description) + external_references, local_constraints = split_references(references) borrow_plan = [ - "Method: borrow the smallest repeatable loop that improves reliability.", - "Structure: borrow directory or metadata patterns only when they reduce ambiguity.", - "Execution: borrow operator-facing flow, not source-specific ceremony.", - "Portability: borrow neutral metadata and degradation ideas, not client-specific lock-in.", + "External benchmark first: let world-class references define the upper bound for method, structure, execution, or portability.", + "Local fit second: use local assets only to detect naming conflicts, private dependencies, or compatibility constraints.", + "Borrow patterns, not prose: extract loops, boundaries, metadata, and operator flow without copying source-specific language.", + "Keep the package light: reject any borrowed pattern that increases context cost faster than it increases reliability.", ] - if references: - borrow_plan.append("Apply only the parts that fit the chosen archetype, gates, and context budget.") + if external_references: + borrow_plan.append("Apply only the benchmark patterns that fit the chosen archetype, gates, and context budget.") return { "skill_name": name, "title": title, "description": description, "scan_focus": focus, - "references": references, + "external_references": external_references, + "local_constraints": local_constraints, "borrow_plan": borrow_plan, + "priority_rule": "External benchmark objects set the pattern ceiling. Local files only calibrate fit, risk, and compatibility.", "non_goals": [ "Do not copy source prose or branding into the new skill.", "Do not import gates that cost more context than they save.", "Do not use benchmark scanning to justify scope creep.", + "Do not let local historical habits outrank stronger public benchmarks.", ], } @@ -124,7 +135,7 @@ def render_markdown(summary: dict) -> str: "", "## Why This Step Exists", "", - "Use a short benchmark pass before authoring the package in depth. The goal is to borrow durable patterns from strong reference objects without copying their prose or carrying their weight into the new skill.", + "Use a short benchmark pass before authoring the package in depth. External benchmark objects should define the pattern ceiling. Local files are used afterward only to calibrate fit, privacy, naming, and compatibility.", "", "## Current Skill Anchor", "", @@ -137,9 +148,11 @@ def render_markdown(summary: dict) -> str: for item in summary["scan_focus"]: lines.append(f"- **{item['label']}**: {item['reason']}") - lines.extend(["", "## Reference Objects", ""]) - if summary["references"]: - for ref in summary["references"]: + lines.extend(["", "## Priority Rule", "", f"- {summary['priority_rule']}", ""]) + + lines.extend(["## External Benchmark Objects", ""]) + if summary["external_references"]: + for ref in summary["external_references"]: lines.extend( [ f"### {ref['name']}", @@ -152,13 +165,34 @@ def render_markdown(summary: dict) -> str: else: lines.extend( [ - "- No explicit reference objects recorded yet.", - "- Recommended: capture 3 to 5 references at most.", + "- No explicit external benchmark objects recorded yet.", + "- Recommended: capture 2 to 5 external references at most.", "- Suggested mix: one method reference, one structure reference, one execution or portability reference.", "", ] ) + lines.extend(["## Local Fit Check", ""]) + if summary["local_constraints"]: + for ref in summary["local_constraints"]: + lines.extend( + [ + f"### {ref['name']}", + f"- Category: `{ref['category']}`", + f"- Keep in mind: {ref['borrow']}", + f"- Do not inherit: {ref['avoid']}", + "", + ] + ) + else: + lines.extend( + [ + "- No local constraints recorded yet.", + "- Use this section for naming collisions, private dependencies, compatibility limits, or existing library conventions.", + "", + ] + ) + lines.extend(["## Borrow Plan", ""]) for item in summary["borrow_plan"]: lines.append(f"- {item}") @@ -195,12 +229,15 @@ def render_reference_scan(skill_dir: Path, references: list[dict], output_md: Pa def main() -> None: parser = argparse.ArgumentParser(description="Render a benchmark-oriented reference scan for a skill package.") parser.add_argument("skill_dir", nargs="?", default=".") - parser.add_argument("--reference", action="append", default=[], help="Format: name::category::borrow::avoid") + parser.add_argument("--external-reference", action="append", default=[], help="Format: name::category::borrow::avoid") + parser.add_argument("--local-constraint", action="append", default=[], help="Format: name::category::borrow::avoid") + parser.add_argument("--reference", action="append", default=[], help="Legacy alias for --external-reference.") parser.add_argument("--output-md") parser.add_argument("--output-json") args = parser.parse_args() - refs = [parse_reference(item) for item in args.reference] + refs = [parse_reference(item, "external") for item in [*args.external_reference, *args.reference]] + refs.extend(parse_reference(item, "local") for item in args.local_constraint) result = render_reference_scan( Path(args.skill_dir), refs, diff --git a/scripts/yao.py b/scripts/yao.py index 95624c53..b84e70d3 100644 --- a/scripts/yao.py +++ b/scripts/yao.py @@ -228,6 +228,10 @@ def command_skill_report(args: argparse.Namespace) -> int: def command_reference_scan(args: argparse.Namespace) -> int: skill_dir = str(Path(args.skill_dir).resolve()) cmd = [skill_dir] + for reference in args.external_reference: + cmd.extend(["--external-reference", reference]) + for constraint in args.local_constraint: + cmd.extend(["--local-constraint", constraint]) for reference in args.reference: cmd.extend(["--reference", reference]) if args.output_md: @@ -454,6 +458,8 @@ def build_parser() -> argparse.ArgumentParser: ) reference_scan_cmd.add_argument("skill_dir", nargs="?", default=".") reference_scan_cmd.add_argument("--reference", action="append", default=[]) + reference_scan_cmd.add_argument("--external-reference", action="append", default=[]) + reference_scan_cmd.add_argument("--local-constraint", action="append", default=[]) reference_scan_cmd.add_argument("--output-md") reference_scan_cmd.add_argument("--output-json") reference_scan_cmd.set_defaults(func=command_reference_scan) diff --git a/tests/verify_reference_scan.py b/tests/verify_reference_scan.py index 4156e418..6961cb41 100644 --- a/tests/verify_reference_scan.py +++ b/tests/verify_reference_scan.py @@ -38,10 +38,12 @@ def main() -> None: sys.executable, str(SCRIPT), str(created), - "--reference", + "--external-reference", "Top Method::method::Borrow a tight benchmark loop.::Avoid copying source-specific branding.", - "--reference", + "--external-reference", "Portable System::portability::Borrow neutral metadata and degradation rules.::Avoid target lock-in.", + "--local-constraint", + "Current Team Naming::structure::Keep naming compatible with the current library.::Avoid inheriting private examples.", ], cwd=ROOT, capture_output=True, @@ -58,10 +60,12 @@ def main() -> None: report_text = md_path.read_text(encoding="utf-8") assert "# Reference Scan" in report_text, report_text[:200] assert "Top Method" in report_text, report_text[:300] + assert "Local Fit Check" in report_text, report_text[:700] assert "Borrow Plan" in report_text, report_text[:500] summary = json.loads(json_path.read_text(encoding="utf-8")) - assert len(summary["references"]) == 2, summary + assert len(summary["external_references"]) == 2, summary + assert len(summary["local_constraints"]) == 1, summary print(json.dumps({"ok": True}, ensure_ascii=False, indent=2)) diff --git a/tests/verify_yao_cli.py b/tests/verify_yao_cli.py index a61c7f27..57f405b5 100644 --- a/tests/verify_yao_cli.py +++ b/tests/verify_yao_cli.py @@ -50,8 +50,10 @@ def main() -> None: reference_scan_result = run( "reference-scan", str(created), - "--reference", + "--external-reference", "World Class Method::method::Borrow the smallest repeatable evaluation loop.::Do not copy heavy ceremony.", + "--local-constraint", + "Local Naming::structure::Keep folder naming aligned with the local library.::Do not inherit private references.", ) assert reference_scan_result["ok"], reference_scan_result assert reference_scan_result["payload"]["artifacts"]["markdown"].endswith("reports/reference-scan.md"), reference_scan_result