返回 Skills 目录
danangjoyoo/nerd包含需要注意的行为

SKILL DETAIL

nerd-fast

danangjoyoo/nerd/nerd-fast

Nerd Fast 是一个全局修饰技能,旨在通过减少顺序关键路径轮次来最小化智能体的墙钟时间,同时不降低准确性。它强调复用、批处理、并行化和针对性操作,并遵循“复用 -> 批处理 -> 并行化 -> 针对性操作 -> 基于证据升级 -> 证明后停止”的原则。该技能包含读取量门控、验证成本门控和自适应路径等机制,以确保高效执行。 Nerd Fast 不应与 Superpowers、Ponytail 或 Caveman 技能组合使用,除非用户明确要求。它通常与 nerd-smart 组合以解决歧义,仅在用户明确调用时才与 nerd-silent 组合。该技能优先遵循用户指令、仓库权威、安全性和活动工作流,并在冲突时让位于更高权威。

安装量 · 227查看来源

Installation

npx skills add https://github.com/danangjoyoo/nerd --skill nerd-fast

技能文件

SKILL.md

最近同步 · 2026年8月28日

agents/openai.yaml
interface:
  display_name: "Nerd Fast"
  short_description: "Critical-path latency without accuracy loss"
  default_prompt: "Use $nerd-fast with this task to minimize wall-clock latency while preserving correctness and proportionate proof."
policy:
  allow_implicit_invocation: true
scripts/symbol_index.py
#!/usr/bin/env python3
from __future__ import annotations

from dataclasses import dataclass
from pathlib import Path
from typing import Iterable, Mapping
import argparse
import hashlib
import json
import os
import sqlite3
import subprocess
import sys
import tempfile


SCHEMA_VERSION = "1"
DEFAULT_EXCLUDED_DIRS = {
    ".git",
    ".hg",
    ".svn",
    ".venv",
    "venv",
    "node_modules",
    "vendor",
    "dist",
    "build",
    "target",
}


@dataclass(frozen=True)
class FileFingerprint:
    mtime_ns: int
    size: int


def _cache_base() -> Path:
    if os.name == "nt" and os.environ.get("LOCALAPPDATA"):
        return Path(os.environ["LOCALAPPDATA"])
    if sys.platform == "darwin":
        return Path.home() / "Library" / "Caches"
    if os.environ.get("XDG_CACHE_HOME"):
        return Path(os.environ["XDG_CACHE_HOME"])
    return Path.home() / ".cache"


def default_cache_path(root: Path) -> Path:
    canonical = root.resolve()
    key = hashlib.sha256(os.fsencode(canonical)).hexdigest()[:20]
    return _cache_base() / "nerd" / "symbol-index" / key / "index.sqlite3"


def connect_cache(path: Path) -> sqlite3.Connection:
    path.parent.mkdir(parents=True, exist_ok=True)
    connection = sqlite3.connect(path)
    connection.row_factory = sqlite3.Row
    connection.execute("PRAGMA journal_mode=WAL")
    connection.execute("PRAGMA synchronous=NORMAL")
    return connection


def initialize_schema(connection: sqlite3.Connection, root: Path) -> None:
    connection.executescript(
        """
        CREATE TABLE IF NOT EXISTS metadata (
            key TEXT PRIMARY KEY,
            value TEXT NOT NULL
        );
        CREATE TABLE IF NOT EXISTS files (
            path TEXT PRIMARY KEY,
            mtime_ns INTEGER NOT NULL,
            size INTEGER NOT NULL
        );
        CREATE TABLE IF NOT EXISTS symbols (
            name TEXT NOT NULL,
            path TEXT NOT NULL,
            line INTEGER NOT NULL,
            kind TEXT,
            scope TEXT,
            language TEXT,
            signature TEXT,
            FOREIGN KEY(path) REFERENCES files(path) ON DELETE CASCADE
        );
        CREATE INDEX IF NOT EXISTS symbols_name_idx ON symbols(name);
        CREATE INDEX IF NOT EXISTS symbols_path_idx ON symbols(path);
        """
    )
    expected = {
        "schema_version": SCHEMA_VERSION,
        "root": str(root.resolve()),
    }
    existing = dict(connection.execute("SELECT key, value FROM metadata"))
    if existing and existing != expected:
        raise RuntimeError("symbol index metadata does not match this workspace")
    connection.executemany(
        "INSERT OR REPLACE INTO metadata(key, value) VALUES (?, ?)",
        expected.items(),
    )
    connection.commit()


def replace_file_symbols(
    connection: sqlite3.Connection,
    relative_path: str,
    fingerprint: FileFingerprint,
    symbols: Iterable[Mapping[str, object]],
) -> None:
    rows = [dict(symbol) for symbol in symbols]
    with connection:
        connection.execute("DELETE FROM symbols WHERE path = ?", (relative_path,))
        connection.execute(
            "INSERT OR REPLACE INTO files(path, mtime_ns, size) VALUES (?, ?, ?)",
            (relative_path, fingerprint.mtime_ns, fingerprint.size),
        )
        connection.executemany(
            """
            INSERT INTO symbols(name, path, line, kind, scope, language, signature)
            VALUES (:name, :path, :line, :kind, :scope, :language, :signature)
            """,
            rows,
        )


def find_symbol(
    connection: sqlite3.Connection,
    name: str,
    limit: int = 50,
) -> list[dict[str, object]]:
    rows = connection.execute(
        """
        SELECT name, path, line, kind, scope, language, signature
        FROM symbols
        WHERE name = ?
        ORDER BY path, line
        LIMIT ?
        """,
        (name, limit),
    )
    return [dict(row) for row in rows]


def require_universal_ctags(binary: str, runner=subprocess.run) -> None:
    try:
        version = runner(
            [binary, "--version"],
            capture_output=True,
            text=True,
            check=False,
        )
    except OSError as error:
        raise RuntimeError(
            f"Universal Ctags executable is unavailable: {binary}"
        ) from error
    if version.returncode != 0 or "Universal Ctags" not in version.stdout:
        raise RuntimeError("Universal Ctags is required for indexed refresh")
    features = runner(
        [binary, "--list-features"],
        capture_output=True,
        text=True,
        check=False,
    )
    available = {
        line.split(maxsplit=1)[0].casefold()
        for line in features.stdout.splitlines()
        if line.strip()
    }
    if features.returncode != 0 or "json" not in available:
        raise RuntimeError("Universal Ctags JSON support is required for indexed refresh")


def parse_ctags_json(lines: Iterable[str], root: Path) -> list[dict[str, object]]:
    parsed: list[dict[str, object]] = []
    for line in lines:
        if not line.strip():
            continue
        value = json.loads(line)
        if value.get("_type") != "tag" or not value.get("name"):
            continue
        path = Path(str(value["path"]))
        if path.is_absolute():
            path = path.resolve().relative_to(root.resolve())
        parsed.append(
            {
                "name": str(value["name"]),
                "path": path.as_posix(),
                "line": int(value["line"]),
                "kind": value.get("kind"),
                "scope": value.get("scope"),
                "language": value.get("language"),
                "signature": value.get("signature"),
            }
        )
    return parsed


def _ctags_operand(path: str) -> str:
    return path if os.path.isabs(path) else f"./{path}"


def _line_list_safe(path: str) -> bool:
    return "\n" not in path and "\r" not in path and not path[-1:].isspace()


def _generate_tag_batch(
    binary: str,
    root: Path,
    paths: list[str],
) -> list[dict[str, object]]:
    command = [
        binary,
        "--output-format=json",
        "--fields=+nsS-P",
        "--sort=no",
        *(_ctags_operand(path) for path in paths),
    ]
    with tempfile.TemporaryFile(mode="w+t", encoding="utf-8") as errors:
        process = subprocess.Popen(
            command,
            cwd=root,
            stdout=subprocess.PIPE,
            stderr=errors,
            text=True,
            bufsize=1,
        )
        if process.stdout is None:
            raise RuntimeError("Universal Ctags stdout pipe was not created")
        try:
            parsed = parse_ctags_json(process.stdout, root)
        finally:
            process.stdout.close()
        returncode = process.wait()
        if returncode != 0:
            errors.seek(0)
            detail = errors.read().strip()
            raise RuntimeError(f"Universal Ctags failed ({returncode}): {detail}")
    return parsed


def _generate_tag_list(
    binary: str,
    root: Path,
    paths: list[str],
) -> list[dict[str, object]]:
    command = [
        binary,
        "--output-format=json",
        "--fields=+nsS-P",
        "--sort=no",
        "-L",
        "-",
    ]
    with (
        tempfile.TemporaryFile(mode="w+t", encoding="utf-8") as inputs,
        tempfile.TemporaryFile(mode="w+t", encoding="utf-8") as errors,
    ):
        inputs.writelines(f"{_ctags_operand(path)}\n" for path in paths)
        inputs.seek(0)
        process = subprocess.Popen(
            command,
            cwd=root,
            stdin=inputs,
            stdout=subprocess.PIPE,
            stderr=errors,
            text=True,
            bufsize=1,
        )
        if process.stdout is None:
            raise RuntimeError("Universal Ctags stdout pipe was not created")
        try:
            parsed = parse_ctags_json(process.stdout, root)
        finally:
            process.stdout.close()
        returncode = process.wait()
        if returncode != 0:
            errors.seek(0)
            detail = errors.read().strip()
            raise RuntimeError(f"Universal Ctags failed ({returncode}): {detail}")
    return parsed


def generate_tags(binary: str, root: Path, paths: list[str]) -> list[dict[str, object]]:
    if len(paths) > 200 and all(_line_list_safe(path) for path in paths):
        return _generate_tag_list(binary, root, paths)
    parsed: list[dict[str, object]] = []
    for start in range(0, len(paths), 200):
        parsed.extend(_generate_tag_batch(binary, root, paths[start : start + 200]))
    return parsed


def enumerate_files(root: Path) -> list[str]:
    try:
        git = subprocess.run(
            ["git", "-C", str(root), "ls-files", "-co", "--exclude-standard", "-z"],
            capture_output=True,
            check=False,
        )
    except OSError:
        git = None
    if git is not None and git.returncode == 0:
        return sorted(os.fsdecode(value) for value in git.stdout.split(b"\0") if value)

    discovered: list[str] = []
    for directory, names, files in os.walk(root):
        names[:] = sorted(name for name in names if name not in DEFAULT_EXCLUDED_DIRS)
        base = Path(directory)
        for name in sorted(files):
            path = base / name
            if path.is_symlink() or not path.is_file():
                continue
            discovered.append(path.relative_to(root).as_posix())
    return discovered


def fingerprint(path: Path) -> FileFingerprint:
    stat = path.stat()
    return FileFingerprint(mtime_ns=stat.st_mtime_ns, size=stat.st_size)


def refresh_index(
    connection: sqlite3.Connection,
    root: Path,
    tag_provider,
    *,
    files: list[str] | None = None,
) -> dict[str, int]:
    current_paths = enumerate_files(root) if files is None else sorted(files)
    current = {path: fingerprint(root / path) for path in current_paths}
    stored = {
        row["path"]: FileFingerprint(row["mtime_ns"], row["size"])
        for row in connection.execute("SELECT path, mtime_ns, size FROM files")
    }
    changed = [path for path, value in current.items() if stored.get(path) != value]
    removed = sorted(set(stored) - set(current))
    generated = tag_provider(changed) if changed else []
    by_path: dict[str, list[dict[str, object]]] = {path: [] for path in changed}
    for symbol in generated:
        path = str(symbol["path"])
        if path in by_path:
            by_path[path].append(symbol)

    with connection:
        for path in removed:
            connection.execute("DELETE FROM symbols WHERE path = ?", (path,))
            connection.execute("DELETE FROM files WHERE path = ?", (path,))
        for path in changed:
            connection.execute("DELETE FROM symbols WHERE path = ?", (path,))
            connection.execute(
                "INSERT OR REPLACE INTO files(path, mtime_ns, size) VALUES (?, ?, ?)",
                (path, current[path].mtime_ns, current[path].size),
            )
            connection.executemany(
                """
                INSERT INTO symbols(name, path, line, kind, scope, language, signature)
                VALUES (:name, :path, :line, :kind, :scope, :language, :signature)
                """,
                by_path[path],
            )
    return {"changed": len(changed), "removed": len(removed)}


def _parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(description="Persistent exact-symbol index")
    subparsers = parser.add_subparsers(dest="command", required=True)
    for name in ("ensure", "find", "status", "invalidate"):
        command = subparsers.add_parser(name)
        command.add_argument("--root", type=Path, default=Path.cwd())
        command.add_argument("--cache", type=Path)
    subparsers.choices["ensure"].add_argument("--ctags", default="ctags")
    subparsers.choices["find"].add_argument("name")
    subparsers.choices["find"].add_argument("--limit", type=int, default=50)
    return parser


def _resolved_cache(args: argparse.Namespace) -> Path:
    return args.cache if args.cache is not None else default_cache_path(args.root)


def main(argv: list[str] | None = None) -> int:
    args = _parser().parse_args(argv)
    root = args.root.resolve()
    cache = _resolved_cache(args)
    if args.command == "invalidate":
        cache.unlink(missing_ok=True)
        print(json.dumps({"status": "invalidated", "cache": str(cache)}))
        return 0
    if args.command == "find" and not cache.is_file():
        print(
            "symbol index is missing; run ensure or use narrow text search",
            file=sys.stderr,
        )
        return 3

    connection = connect_cache(cache)
    try:
        initialize_schema(connection, root)
        if args.command == "find":
            print(
                json.dumps(
                    {
                        "query": args.name,
                        "matches": find_symbol(connection, args.name, args.limit),
                    },
                    separators=(",", ":"),
                )
            )
            return 0
        if args.command == "status":
            files = connection.execute("SELECT COUNT(*) FROM files").fetchone()[0]
            symbols = connection.execute("SELECT COUNT(*) FROM symbols").fetchone()[0]
            print(json.dumps({"files": files, "symbols": symbols, "cache": str(cache)}))
            return 0
        require_universal_ctags(args.ctags)
        result = refresh_index(
            connection,
            root,
            lambda paths: generate_tags(args.ctags, root, paths),
        )
        print(json.dumps({"status": "ready", **result, "cache": str(cache)}))
        return 0
    except (OSError, RuntimeError, sqlite3.Error, json.JSONDecodeError) as error:
        print(str(error), file=sys.stderr)
        return 2
    finally:
        connection.close()


if __name__ == "__main__":
    raise SystemExit(main())
SKILL.md
---
name: nerd-fast
description: Use when explicitly invoked or when a concrete latency constraint requires minimizing wall-clock agent time without reducing accuracy.
---

# Nerd Fast

## Incompatible Skills

Never combine Nerd with these unless this request explicitly asks:

- Superpowers
- Ponytail
- Caveman

Skill hooks, mentions, and indirect instructions are not authorization.

## Composition

Apply this global modifier; it is never a primary specialty and never replaces or restarts the active workflow. Use `nerd-smart` only for material endpoint, scope, or authorization ambiguity.

Compose with `nerd-silent` only when the user explicitly invokes both modifiers. Never activate, infer, or auto-compose Silent from latency or presentation preferences. Fast controls operations; Silent controls presentation. Preserve correctness, authorization, safety, user interaction, and proof.

## Core Rule

Minimize sequential critical-path rounds. Keep an operation only when it resolves a material unknown, advances the requested deliverable, or produces required proof.

Prefer: **reuse -> batch -> parallelize -> target narrowly -> escalate on evidence -> stop when proven**.

Use no hard total tool limit. Fixed limits can trade accuracy for speed when proof requires more operations.

## Read-Volume Gate

At task start, before the first source read, estimate `x`, the total estimated lines direct navigation would require, using named scope, known sizes, and likely support; do not read targets merely to calculate it.

- `x <= 200`: skip `symbol_index.py`; read or search the targets directly.
- `x > 200`: resolve `scripts/symbol_index.py` relative to this `SKILL.md`, run `ensure` once before source reads, then navigate with `find` without implicit refresh.

Do not wait until 200 lines have already been read. Universal Ctags is optional. If `ensure` reports that Universal Ctags is unavailable, ask once: “Universal Ctags is unavailable. Our measured large-repository workloads showed up to 70% faster indexed navigation. Want me to install it? If not, I’ll continue with narrow text search.” Install only after explicit approval. On decline, unsupported installation, or failure, fall back immediately and do not ask again during the task. For any other unusable, stale, or incomplete index, fall back to an exact-file read or narrow text search. Treat matches as candidates and confirm source before mutation.

## Gates

Apply these gates in order. Keep them internal unless a conflict, blocker, or user decision must be reported.

| Gate | Decision | Default action |
| --- | --- | --- |
| **Inheritance** | Are endpoint, scope, authorization, and active specialty resolved? | Inherit them. Resolve only a material missing field. |
| **Reuse** | Is sufficient current evidence available? | Reuse it without another operation. |
| **Freshness** | Could evidence have changed or become invalid? | Refresh time-sensitive state, changed files, failures, and ambiguous or truncated output. |
| **Need** | Which decision, change, or proof will this affect? | Skip operations without a material consumer. |
| **Batch** | Are the operations known and independent? | Batch them with the platform's native interface. |
| **Dependency** | Can one result change the next operation? | Keep adaptive dependencies sequential. |
| **Escalation** | What is the cheapest operation that distinguishes the possibilities? | Start narrowly and broaden only on evidence. |
| **Recovery** | Did the failed attempt produce new evidence? | Make at most two evidence-driven corrections by default, then report the blocker. |
| **Verification cost** | What is the lowest-cost fresh proof supporting the claim? | Select the lowest sufficient tier and escalate only on a verification trigger. |
| **Stop** | Are the outcome and required proof satisfied? | Stop without optional exploration or review. |

User instructions, repository authority, safety, and the active workflow override these defaults.

## Batching and Dependencies

Batch independent operations when their commands and reactions are known. Prefer one operation across known targets or the native batching or parallel interface. Keep adaptive work sequential when an output can change the next operation.

Before dispatching a mutation batch, require every step to be idempotent, transactional, or safely recoverable; otherwise keep mutations sequential and inspect state between them.

## Verification-Cost Gate

Select the cheapest fresh check that observes the property being claimed.

### Proof Ladder

| Tier | Proof | Typical use |
| --- | --- | --- |
| **V0** | Existing current evidence or no verification claim | Read-only answers, unchanged facts, or work without a proportionate executable check. Report `Not verified` when completion would otherwise imply proof. |
| **V1** | Static, parse, content, or syntax check | Documentation, metadata, formatting, configuration, or static artifacts. |
| **V2** | Focused behavioral check | The unit, contract, repository, component, regression, or browser test closest to the change. |
| **V3** | Boundary or package validation | A relevant package suite, type check, build, integration test, migration check, or multi-component validation. |
| **V4** | Full-system or live validation | A full repository suite, end-to-end run, deployment smoke test, or authorized live integration. |

Choose the lowest tier that directly supports the exact claim. Use V0 only if no mutation invalidated its evidence. Any file mutation, structural refactor, or code addition requires at least V1. Any behavioral completion claim after mutation requires fresh proof.

Reuse dependency, compiler, transpiler, test, runtime, and build caches when trustworthy. Preserve active daemons and watch processes. For static claims, use the narrowest syntax, type, lint, compile, or AST check. For behavioral claims, run one test method, case, file, package, or affected component. Without evidence, avoid clearing caches, reinstalling dependencies, rebuilding unaffected targets, recreating environments, or restarting healthy services. Run clean builds, broad suites, or environment resets only for repository authority, stale state, contradictory evidence, release parity, or a trigger below.

### Verification Escalation Triggers

- The user or repository instructions require broader proof.
- The change crosses packages, services, persistence boundaries, or public contracts that narrower proof cannot cover.
- Security, authorization, migration, data-loss, concurrency, release, or production risk makes broader proof proportionate.
- The targeted check fails ambiguously or reveals a wider affected surface.
- The lower tier cannot observe a material part of the completion claim.

Do not run a full suite merely because one exists. Do not rerun an unchanged passing check. Classify failures as related, unrelated, or unknown; correct only related failures in scope. After two evidence-driven correction attempts, report the command, evidence, and smallest needed decision. If proof is narrower, narrow the claim to the verified boundary or `Not verified`.

## Adaptive Path

- If current evidence is sufficient, perform the active endpoint, apply proportionate proof, and stop.
- If an exact target is named, apply the Read-Volume Gate and navigate the target plus its nearest authority or test.
- If the target is unknown, run one narrow discovery batch, inspect the best evidence, and narrow scope.
- If operations are independent, batch or parallelize them and synthesize once.
- If an output can change the next operation, sequence them.
- If a current plan exists, execute its remaining work without rediscovery.
- If current or external information is required, query authoritative sources together and confirm freshness.
- If a failure or contradiction appears, reuse it as evidence, reproduce once when needed, and test one bounded hypothesis.
- If work continues from an earlier turn, reuse the current record, plan, outputs, and diff; refresh only changed or stale evidence.

Use the smallest applicable path; conditions do not grant permission or replace the active workflow.

## Execution Discipline

For non-atomic work, keep current evidence, one critical unknown, next independent batch, lowest sufficient proof, and stop condition. Skip fields without a material consumer.

Each TODO must deliver an outcome, remove a blocker, or provide proof. Do not reread unchanged files, repeat passing commands, or replan after each result. Reuse evidence until mutation, contradiction, staleness, or dependency failure invalidates it.

Prefer a structured patch or targeted-edit primitive. Do not reproduce unchanged file content. Rewrite a whole file only when generated, mostly changed, or handled by a trusted formatter or codemod.

For routine authorized operations, invoke the tool immediately. Explain first only for approval, safety, a material decision, or a required progress update. Silent controls overall narration and final presentation.

Dispatch reviewers or subagents only when the active workflow permits them and expected wall-clock savings exceed setup and handoff cost.

## Conflict Discipline

When Fast conflicts with repository instructions, safety, the active workflow, or a supported completion claim, yield to the higher authority and take the lowest-cost valid path.

Treat tool errors as evidence. Correct the invocation or assumption once, then broaden only when the error shows that the current scope or source is insufficient.

After changing this skill family, run `python3 scripts/validate_skills.py`.
nerd-fast · 热门 Agent Skills | Mengbi