Health: Agent Config and AI Maintainability Prefix your first line with 🥷 inline, not as its own paragraph. Audit the current project's agent setup and AI coding maintainability against this framework: Find violations. Identify the misaligned layer. Calibrate to project complexity only. Output language: Check in order: (1) project agent instructions ( before runtime-specific files); (2) global agent instructions; (3) user's recent language; (4) English. Budget posture: Start with the summary audit. Escalate automatically when the user asks for a deep, full, complete, thorough, "深入", "完整", "彻…

)\nTABLE_RE = re.compile(r'^\\[([A-Za-z0-9_.@\"\\-/]+)\\]\\s*

Health: Agent Config and AI Maintainability Prefix your first line with 🥷 inline, not as its own paragraph. Audit the current project's agent setup and AI coding maintainability against this framework: Find violations. Identify the misaligned layer. Calibrate to project complexity only. Output language: Check in order: (1) project agent instructions ( before runtime-specific files); (2) global agent instructions; (3) user's recent language; (4) English. Budget posture: Start with the summary audit. Escalate automatically when the user asks for a deep, full, complete, thorough, "深入", "完整", "彻…

)\n\n\ndef rel(path: Path, root: Path) -> str:\n try:\n return path.resolve().relative_to(root).as_posix()\n except ValueError:\n return path.as_posix()\n\n\ndef read(path: Path, limit: int | None = None) -> str:\n try:\n data = path.read_text(encoding=\"utf-8\", errors=\"replace\")\n except OSError:\n return \"\"\n return data[:limit] if limit else data\n\n\ndef yes(path: Path) -> str:\n return \"yes\" if path.exists() else \"no\"\n\n\ndef print_list(title: str, items: list[str], empty: str = \"(none)\", limit: int | None = None) -> None:\n print(f\"{title}:\")\n shown = items if limit is None else items[:limit]\n if not shown:\n print(f\" {empty}\")\n return\n for item in shown:\n print(f\" {item}\")\n if limit is not None and len(items) > limit:\n print(f\" ... {len(items) - limit} more\")\n\n\ndef project_instruction_files(root: Path) -> list[Path]:\n files = [\n root / \"AGENTS.md\",\n root / \"CLAUDE.md\",\n root / \".github\" / \"copilot-instructions.md\",\n root / \"GEMINI.md\",\n ]\n instructions_dir = root / \".github\" / \"instructions\"\n if instructions_dir.is_dir():\n files.extend(sorted(instructions_dir.glob(\"*.md\")))\n return [path for path in files if path.is_file()]\n\n\ndef claude_delegates_to_agents(path: Path) -> bool:\n text = read(path, 20_000)\n if not text:\n return False\n meaningful = [\n line.strip()\n for line in text.splitlines()\n if line.strip() and not line.strip().startswith(\"#\")\n ]\n return any(\"AGENTS.md\" in line for line in meaningful)\n\n\ndef parse_codex_config(\n path: Path,\n) -> tuple[dict[str, str], list[str], list[str], list[str], list[str]]:\n projects: dict[str, str] = {}\n features: list[str] = []\n plugins: list[str] = []\n marketplaces: list[str] = []\n redacted: list[str] = []\n if not path.is_file():\n return projects, features, plugins, marketplaces, redacted\n\n section = \"\"\n for raw in read(path).splitlines():\n line = raw.strip()\n if not line or line.startswith(\"#\"):\n continue\n project_match = PROJECT_RE.match(line)\n if project_match:\n section = f'projects.\"{project_match.group(1)}\"'\n projects.setdefault(project_match.group(1), \"\")\n continue\n table_match = TABLE_RE.match(line)\n if table_match:\n section = table_match.group(1)\n marketplace_match = re.match(r'marketplaces\\.([A-Za-z0-9_.@-]+)

Health: Agent Config and AI Maintainability Prefix your first line with 🥷 inline, not as its own paragraph. Audit the current project's agent setup and AI coding maintainability against this framework: Find violations. Identify the misaligned layer. Calibrate to project complexity only. Output language: Check in order: (1) project agent instructions ( before runtime-specific files); (2) global agent instructions; (3) user's recent language; (4) English. Budget posture: Start with the summary audit. Escalate automatically when the user asks for a deep, full, complete, thorough, "深入", "完整", "彻…

, section)\n plugin_match = re.match(r'plugins\\.\"?([^\"]+)\"?

Health: Agent Config and AI Maintainability Prefix your first line with 🥷 inline, not as its own paragraph. Audit the current project's agent setup and AI coding maintainability against this framework: Find violations. Identify the misaligned layer. Calibrate to project complexity only. Output language: Check in order: (1) project agent instructions ( before runtime-specific files); (2) global agent instructions; (3) user's recent language; (4) English. Budget posture: Start with the summary audit. Escalate automatically when the user asks for a deep, full, complete, thorough, "深入", "完整", "彻…

, section)\n if marketplace_match:\n marketplaces.append(marketplace_match.group(1))\n if plugin_match:\n plugins.append(plugin_match.group(1))\n continue\n\n if SENSITIVE_RE.search(line):\n key = line.split(\"=\", 1)[0].strip() if \"=\" in line else \"sensitive\"\n redacted.append(f\"{key}=[REDACTED]\")\n continue\n\n if \"=\" not in line:\n continue\n key, value = [part.strip() for part in line.split(\"=\", 1)]\n if section == \"features\" and value.lower() == \"true\":\n features.append(key)\n elif section.startswith('projects.\"') and key == \"trust_level\":\n project = section[len('projects.\"'): -1]\n projects[project] = value.strip('\"')\n\n return (\n projects,\n sorted(set(features)),\n sorted(set(plugins)),\n sorted(set(marketplaces)),\n sorted(set(redacted)),\n )\n\n\ndef project_trust(projects: dict[str, str], root: Path) -> str:\n root_text = root.as_posix()\n if root_text in projects:\n return f\"exact:{projects[root_text] or 'configured'}\"\n candidates = []\n for project, level in projects.items():\n try:\n project_path = Path(project).expanduser().resolve()\n except OSError:\n continue\n if project_path == root:\n return f\"exact:{level or 'configured'}\"\n try:\n root.relative_to(project_path)\n except ValueError:\n continue\n candidates.append(\n (len(project_path.as_posix()), level or \"configured\", project_path.as_posix())\n )\n if candidates:\n _, level, project = sorted(candidates, reverse=True)[0]\n return f\"inherited:{level} from {project}\"\n return \"missing\"\n\n\ndef main() -> int:\n parser = argparse.ArgumentParser(description=__doc__)\n parser.add_argument(\"root\", nargs=\"?\", default=\".\", help=\"Repo root (default: cwd)\")\n parser.add_argument(\n \"mode\", nargs=\"?\", default=\"summary\", choices=(\"summary\", \"deep\"),\n help=\"Output detail level\",\n )\n args = parser.parse_args()\n root = Path(args.root).resolve()\n mode = args.mode\n home = Path(os.environ.get(\"HOME\", str(Path.home()))).expanduser()\n\n if not root.is_dir():\n print(f\"Repo root not found: {root}\", file=sys.stderr)\n return 2\n\n instruction_files = project_instruction_files(root)\n agents = root / \"AGENTS.md\"\n claude = root / \"CLAUDE.md\"\n claude_delegates = claude_delegates_to_agents(claude)\n github_instructions_dir = root / \".github\" / \"instructions\"\n github_instruction_count = (\n len(list(github_instructions_dir.glob(\"*.md\"))) if github_instructions_dir.is_dir() else 0\n )\n\n instruction_findings: list[str] = []\n if not instruction_files:\n instruction_findings.append(\"no project agent instruction files\")\n if agents.is_file() and claude.is_file() and not claude_delegates:\n claude_lines = len(read(claude).splitlines())\n agents_lines = len(read(agents).splitlines())\n if claude_lines > 20 and agents_lines > 20:\n instruction_findings.append(\n \"AGENTS.md and CLAUDE.md both contain substantial guidance without delegation\"\n )\n\n global_codex_agents = home / \".codex\" / \"AGENTS.md\"\n codex_config = home / \".codex\" / \"config.toml\"\n projects, features, plugins, marketplaces, redacted = parse_codex_config(codex_config)\n trust = project_trust(projects, root) if codex_config.is_file() else \"unavailable\"\n codex_findings: list[str] = []\n if not global_codex_agents.is_file() and not codex_config.is_file():\n codex_findings.append(\"Codex surface not found\")\n elif codex_config.is_file() and trust == \"missing\":\n codex_findings.append(\"current project is not configured in Codex trust table\")\n\n global_claude = home / \".claude\" / \"CLAUDE.md\"\n project_settings = root / \".claude\" / \"settings.local.json\"\n project_rules = root / \".claude\" / \"rules\"\n project_skills = root / \".claude\" / \"skills\"\n global_skills = home / \".claude\" / \"skills\"\n claude_findings: list[str] = []\n if claude.is_file() and claude_delegates:\n claude_findings.append(\"CLAUDE.md delegates to AGENTS.md\")\n if not global_claude.is_file() and not claude.is_file():\n claude_findings.append(\"Claude instruction surface not found\")\n\n conflict_findings: list[str] = []\n if agents.is_file() and claude.is_file() and not claude_delegates:\n conflict_findings.append(\"AGENTS.md and CLAUDE.md both exist; verify they do not diverge\")\n\n instruction_status = \"FAIL\" if not instruction_files else (\"WARN\" if instruction_findings else \"PASS\")\n codex_status = \"WARN\" if codex_findings else \"PASS\"\n claude_status = (\n \"WARN\"\n if claude_findings and \"surface not found\" in \" \".join(claude_findings)\n else \"PASS\"\n )\n conflict_status = \"WARN\" if conflict_findings else \"PASS\"\n\n print(\"=== AGENT INSTRUCTION SURFACE ===\")\n print(f\"agent_instruction_status: {instruction_status}\")\n print(f\"mode: {mode}\")\n print(f\"AGENTS.md: {yes(agents)}\")\n print(f\"CLAUDE.md: {yes(claude)}\")\n print(f\"claude_delegates_to_agents: {'yes' if claude_delegates else 'no'}\")\n print(f\".github/copilot-instructions.md: {yes(root / '.github' / 'copilot-instructions.md')}\")\n print(f\".github/instructions/*.md: {github_instruction_count}\")\n print(f\"GEMINI.md: {yes(root / 'GEMINI.md')}\")\n print_list(\"instruction_files\", [rel(path, root) for path in instruction_files])\n print_list(\"instruction_findings\", instruction_findings)\n\n print(\"=== CODEX SURFACE ===\")\n print(f\"codex_status: {codex_status}\")\n print(f\"global_agents_md: {yes(global_codex_agents)}\")\n print(f\"global_config_toml: {yes(codex_config)}\")\n print(f\"project_trust: {trust}\")\n print_list(\"features\", features, limit=20 if mode == \"summary\" else None)\n print_list(\"enabled_plugins\", plugins, limit=20 if mode == \"summary\" else None)\n print_list(\"marketplaces\", marketplaces, limit=20 if mode == \"summary\" else None)\n print_list(\"redacted_config_entries\", redacted)\n print_list(\"codex_findings\", codex_findings)\n\n print(\"=== CLAUDE SURFACE ===\")\n print(f\"claude_status: {claude_status}\")\n print(f\"global_claude_md: {yes(global_claude)}\")\n print(f\"project_claude_md: {yes(claude)}\")\n print(f\"settings_local_json: {yes(project_settings)}\")\n rule_count = len(list(project_rules.glob('*.md'))) if project_rules.is_dir() else 0\n local_skill_count = len(list(project_skills.glob('*/SKILL.md'))) if project_skills.is_dir() else 0\n global_skill_count = len(list(global_skills.glob('*/SKILL.md'))) if global_skills.is_dir() else 0\n print(f\"project_rules: {rule_count}\")\n print(f\"project_skills: {local_skill_count}\")\n print(f\"global_skills: {global_skill_count}\")\n print_list(\"claude_findings\", claude_findings)\n\n print(\"=== INSTRUCTION CONFLICTS ===\")\n print(f\"conflict_status: {conflict_status}\")\n print_list(\"conflict_findings\", conflict_findings)\n return 0\n\n\nif __name__ == \"__main__\":\n sys.exit(main())\n","content_type":"text/x-python; charset=utf-8","language":"python","size":10442,"content_sha256":"db20533d015444ee2eed686aafe07322bfe1a65fbb2d0c09e83d58fe63e42d5f"},{"filename":"scripts/check_doc_refs.py","content":"#!/usr/bin/env python3\n\"\"\"Check that doc references (@path, ~/.claude/..., docs/..., references/...) in\nAGENTS.md, CLAUDE.md, .claude/rules/*.md, and .claude/skills/*/SKILL.md resolve\nto real files. Prints `doc references: ok` on success, otherwise lists every\nMISSING reference with source location.\n\nRun as: python3 check_doc_refs.py [ROOT]\nROOT defaults to the current working directory.\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport os\nimport re\nimport sys\nfrom pathlib import Path\n\n\nREF_RE = re.compile(\n r\"(?\u003c![\\w/.-])(\"\n r\"@[A-Za-z0-9_~/.-]+(?:\\.md|/)|\"\n r\"~/\\.claude/[A-Za-z0-9_/.-]+(?:\\.md|/)|\"\n r\"(?:docs|references)/[A-Za-z0-9_/.-]+\\.md\"\n r\")\"\n)\n\n\ndef resolve_ref(source: Path, raw: str, root: Path, home: Path) -> Path:\n ref = raw[1:] if raw.startswith(\"@\") else raw\n\n if ref.startswith(\"~/\"):\n return (home / ref[2:]).resolve()\n\n path = Path(ref)\n if path.is_absolute():\n return path.resolve()\n\n if raw.startswith(\"@\"):\n return (root / ref).resolve()\n\n if ref.startswith(\"docs/\"):\n return (root / ref).resolve()\n\n if ref.startswith(\"references/\"):\n source_parts = source.relative_to(root).parts\n if len(source_parts) >= 4 and source_parts[:2] == (\".claude\", \"skills\"):\n skill_root = root.joinpath(*source_parts[:3])\n return (skill_root / ref).resolve()\n return (root / ref).resolve()\n\n return (source.parent / ref).resolve()\n\n\ndef collect_scan_files(root: Path) -> list[Path]:\n scan_files: list[Path] = []\n for candidate in (root / \"AGENTS.md\", root / \"CLAUDE.md\"):\n if candidate.is_file():\n scan_files.append(candidate)\n for pattern in (\".claude/rules/*.md\", \".claude/skills/*/SKILL.md\"):\n scan_files.extend(sorted(root.glob(pattern)))\n return scan_files\n\n\ndef main() -> int:\n parser = argparse.ArgumentParser(description=__doc__)\n parser.add_argument(\"root\", nargs=\"?\", default=\".\", help=\"Project root (default: cwd)\")\n args = parser.parse_args()\n root = Path(args.root).resolve()\n home = Path(os.environ.get(\"HOME\", \"\")).expanduser()\n\n scan_files = collect_scan_files(root)\n\n missing: list[str] = []\n seen: set[tuple[Path, int, str]] = set()\n for path in scan_files:\n in_fence = False\n for lineno, line in enumerate(\n path.read_text(encoding=\"utf-8\", errors=\"replace\").splitlines(), start=1\n ):\n stripped = line.lstrip()\n if stripped.startswith(\"```\") or stripped.startswith(\"~~~\"):\n in_fence = not in_fence\n continue\n if in_fence:\n continue\n\n for match in REF_RE.finditer(line):\n raw = match.group(1)\n key = (path, lineno, raw)\n if key in seen:\n continue\n seen.add(key)\n\n target = resolve_ref(path, raw, root, home)\n exists = target.is_dir() if raw.endswith(\"/\") else target.is_file()\n if not exists:\n source = path.relative_to(root)\n missing.append(f\"MISSING: {source}:{lineno} -> {raw}\")\n\n if missing:\n print(\"\\n\".join(missing))\n return 1\n\n print(\"doc references: ok\")\n return 0\n\n\nif __name__ == \"__main__\":\n sys.exit(main())\n","content_type":"text/x-python; charset=utf-8","language":"python","size":3346,"content_sha256":"0b7eda43e7955fcd0da96ba255e9a60bcb5bffb0fd93193873d92cfc20df3c73"},{"filename":"scripts/check_maintainability.py","content":"#!/usr/bin/env python3\n\"\"\"AI maintainability audit: project shape, context surface, verification surface,\ndecision artifacts, drift markers, hotspot ownership, markdown links.\n\nRun as: python3 check_maintainability.py [ROOT] [summary|deep]\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport json\nimport os\nimport re\nimport subprocess\nimport sys\nimport urllib.parse\nfrom collections import Counter\nfrom pathlib import Path\n\n\nEXCLUDED_DIRS = {\n \".git\",\n \".hg\",\n \".svn\",\n \"node_modules\",\n \"dist\",\n \"build\",\n \".next\",\n \"__pycache__\",\n \".turbo\",\n \"target\",\n \".venv\",\n \"venv\",\n \"vendor\",\n \"coverage\",\n \".cache\",\n \".parcel-cache\",\n \".pytest_cache\",\n \".mypy_cache\",\n \".ruff_cache\",\n}\n\nSOURCE_EXTS = {\n \".c\", \".cc\", \".cpp\", \".cs\", \".css\", \".go\", \".h\", \".hpp\", \".html\",\n \".java\", \".js\", \".jsx\", \".kt\", \".lua\", \".m\", \".mm\", \".md\", \".mjs\",\n \".php\", \".py\", \".rb\", \".rs\", \".scss\", \".sh\", \".swift\", \".ts\", \".tsx\",\n \".vue\", \".yaml\", \".yml\",\n}\n\nMARKER_RE = re.compile(r\"\\b(TODO|FIXME|HACK|XXX)\\b\", re.IGNORECASE)\nMAKE_RE = re.compile(r\"^([A-Za-z0-9_.-]+)\\s*:(?![=])\")\nMAKE_CMD_RE = re.compile(r\"\\bmake\\s+([A-Za-z0-9_.-]+)\\b\")\nNPM_CMD_RE = re.compile(r\"\\b(?:npm|pnpm|yarn|bun)\\s+run\\s+([A-Za-z0-9:_-]+)\\b\")\nCOMMAND_LINE_RE = re.compile(r\"^(?:make|npm|pnpm|yarn|bun)\\s+\")\nMARKDOWN_LINK_RE = re.compile(r\"!?\\[[^\\]]*\\]\\(([^)]+)\\)\")\nURL_RE = re.compile(r\"^[A-Za-z][A-Za-z0-9+.-]*:\")\nHOTSPOT_WORD_RE = re.compile(\n r\"(hotspot|large file|ownership|owner|boundary|module|owned|owns|\"\n r\"负责|边界|模块|热点|大文件)\",\n re.IGNORECASE,\n)\nVERIFICATION_WORD_RE = re.compile(\n r\"(verification|verify|test|check|make\\s+\\w+|pytest|go test|cargo test|\"\n r\"npm test|npm run|pnpm|yarn|swift test|xcodebuild|验证|测试)\",\n re.IGNORECASE,\n)\n\n\ndef rel(path: Path, root: Path) -> str:\n try:\n return path.resolve().relative_to(root).as_posix()\n except ValueError:\n return path.as_posix()\n\n\ndef is_excluded(path: Path, root: Path) -> bool:\n parts = path.relative_to(root).parts if path.is_absolute() else path.parts\n return any(part in EXCLUDED_DIRS for part in parts)\n\n\ndef read_text(path: Path, limit: int | None = None) -> str:\n try:\n data = path.read_text(encoding=\"utf-8\", errors=\"replace\")\n except OSError:\n return \"\"\n return data[:limit] if limit else data\n\n\ndef iter_files(root: Path) -> list[Path]:\n try:\n proc = subprocess.run(\n [\"git\", \"-C\", str(root), \"ls-files\", \"--cached\", \"--others\", \"--exclude-standard\"],\n text=True,\n stdout=subprocess.PIPE,\n stderr=subprocess.DEVNULL,\n check=False,\n )\n if proc.returncode == 0 and proc.stdout.strip():\n files = []\n for line in proc.stdout.splitlines():\n path = root / line\n if path.is_file() and not is_excluded(path, root):\n files.append(path)\n return files\n except OSError:\n pass\n\n files = []\n for dirpath, dirnames, filenames in os.walk(root):\n current = Path(dirpath)\n dirnames[:] = [name for name in dirnames if name not in EXCLUDED_DIRS]\n if is_excluded(current, root):\n continue\n for filename in filenames:\n path = current / filename\n if path.is_file() and not is_excluded(path, root):\n files.append(path)\n return files\n\n\ndef line_count(path: Path) -> int:\n try:\n with path.open(\"rb\") as handle:\n return sum(1 for _ in handle)\n except OSError:\n return 0\n\n\ndef print_list(items: list[str], empty: str = \"(none)\", limit: int | None = None) -> None:\n shown = items if limit is None else items[:limit]\n if not shown:\n print(f\" {empty}\")\n return\n for item in shown:\n print(f\" {item}\")\n if limit is not None and len(items) > limit:\n print(f\" ... {len(items) - limit} more\")\n\n\ndef instruction_paths(root: Path) -> list[Path]:\n candidates = [\n root / \"AGENTS.md\",\n root / \"CLAUDE.md\",\n root / \".github\" / \"copilot-instructions.md\",\n root / \"GEMINI.md\",\n ]\n instructions_dir = root / \".github\" / \"instructions\"\n if instructions_dir.is_dir():\n candidates.extend(sorted(instructions_dir.glob(\"*.md\")))\n return [path for path in candidates if path.is_file() and not is_excluded(path, root)]\n\n\ndef find_text_signal(paths: list[Path], patterns: list[str]) -> bool:\n regexes = [re.compile(pattern, re.IGNORECASE) for pattern in patterns]\n for path in paths:\n text = read_text(path, 200_000)\n if any(regex.search(text) for regex in regexes):\n return True\n return False\n\n\ndef parse_makefile(root: Path) -> tuple[set[str], list[str]]:\n makefile = root / \"Makefile\"\n targets: set[str] = set()\n commands: list[str] = []\n if not makefile.is_file():\n return targets, commands\n for line in read_text(makefile).splitlines():\n match = MAKE_RE.match(line)\n if not match:\n continue\n target = match.group(1)\n if target.startswith(\".\"):\n continue\n targets.add(target)\n if re.search(r\"(test|check|lint|type|build|package|verify|smoke)\", target, re.IGNORECASE):\n commands.append(f\"make {target}\")\n return targets, commands\n\n\ndef parse_package_json(root: Path) -> tuple[set[str], list[str]]:\n package = root / \"package.json\"\n script_names: set[str] = set()\n commands: list[str] = []\n if not package.is_file():\n return script_names, commands\n try:\n data = json.loads(read_text(package))\n except json.JSONDecodeError:\n return script_names, commands\n scripts = data.get(\"scripts\", {})\n if not isinstance(scripts, dict):\n return script_names, commands\n for name in sorted(scripts):\n script_names.add(name)\n if re.search(r\"(test|check|lint|type|build|verify)\", name, re.IGNORECASE):\n commands.append(f\"npm run {name}\")\n return script_names, commands\n\n\ndef parse_ci_commands(root: Path) -> list[str]:\n workflows_dir = root / \".github\" / \"workflows\"\n workflows = sorted(workflows_dir.glob(\"*.yml\")) if workflows_dir.is_dir() else []\n workflows += sorted(workflows_dir.glob(\"*.yaml\")) if workflows_dir.is_dir() else []\n commands: list[str] = []\n for workflow in workflows:\n for raw in read_text(workflow).splitlines():\n line = raw.strip()\n if line.startswith(\"- run:\"):\n command = line.split(\"- run:\", 1)[1].strip().strip(\"'\\\"\")\n elif line.startswith(\"run:\"):\n command = line.split(\"run:\", 1)[1].strip().strip(\"'\\\"\")\n else:\n continue\n if command and command != \"|\":\n commands.append(f\"{rel(workflow, root)}: {command}\")\n return commands\n\n\ndef scan_markdown_links(files: list[Path], root: Path) -> list[str]:\n missing: list[str] = []\n markdown_files = [path for path in files if path.suffix.lower() == \".md\"]\n for path in markdown_files:\n for lineno, line in enumerate(read_text(path).splitlines(), 1):\n for raw in MARKDOWN_LINK_RE.findall(line):\n target = raw.strip().split()[0].strip(\"\u003c>\")\n if not target or target.startswith(\"#\") or URL_RE.match(target):\n continue\n target = urllib.parse.unquote(target.split(\"#\", 1)[0])\n if not target:\n continue\n full = (path.parent / target).resolve()\n if not full.exists():\n missing.append(f\"{rel(path, root)}:{lineno} -> {target}\")\n return missing\n\n\ndef verification_surface(\n root: Path, instruction_files: list[Path]\n) -> tuple[list[str], list[str], set[str], set[str]]:\n make_targets, make_commands = parse_makefile(root)\n package_scripts, package_commands = parse_package_json(root)\n commands = make_commands + package_commands + parse_ci_commands(root)\n\n if (root / \"Cargo.toml\").is_file():\n commands.extend([\"cargo test\", \"cargo check\"])\n if (root / \"go.mod\").is_file():\n commands.append(\"go test ./...\")\n if (root / \"pyproject.toml\").is_file() or (root / \"pytest.ini\").is_file():\n commands.append(\"pytest\")\n if (root / \"pom.xml\").is_file():\n commands.append(\"mvn test\")\n if (root / \"deno.json\").is_file() or (root / \"deno.jsonc\").is_file():\n commands.append(\"deno test\")\n\n missing: list[str] = []\n for path in instruction_files:\n text = read_text(path, 200_000)\n snippets: list[str] = []\n for raw_line in text.splitlines():\n snippets.extend(re.findall(r\"`([^`]+)`\", raw_line))\n stripped = raw_line.strip().strip(\"`\")\n if COMMAND_LINE_RE.match(stripped):\n snippets.append(stripped)\n for snippet in snippets:\n for target in MAKE_CMD_RE.findall(snippet):\n if target not in make_targets:\n missing.append(f\"{rel(path, root)} references missing make target: {target}\")\n for script in NPM_CMD_RE.findall(snippet):\n if script not in package_scripts:\n missing.append(f\"{rel(path, root)} references missing package script: {script}\")\n\n unique_commands = list(dict.fromkeys(commands))\n unique_missing = list(dict.fromkeys(missing))\n return unique_commands, unique_missing, make_targets, package_scripts\n\n\ndef hotspot_ownership_surface(\n records: list[tuple[int, int, Path]],\n instruction_files: list[Path],\n mode: str,\n root: Path,\n) -> tuple[str, list[str], list[str], list[str]]:\n if mode != \"deep\":\n return \"SKIPPED\", [], [], []\n if not records:\n return \"PASS\", [], [], []\n\n snippets: list[str] = []\n for path in instruction_files:\n snippets.append(f\"\\n# {rel(path, root)}\\n{read_text(path, 200_000)}\")\n instruction_text = \"\\n\".join(snippets)\n lower_text = instruction_text.lower()\n instruction_lines = instruction_text.splitlines()\n\n documented: list[str] = []\n missing: list[str] = []\n for lines, _size, path in records:\n relative = rel(path, root)\n relative_lower = relative.lower()\n indices: list[int] = []\n start = 0\n while True:\n index = lower_text.find(relative_lower, start)\n if index \u003c 0:\n break\n indices.append(index)\n start = index + len(relative_lower)\n\n if not indices:\n missing.append(f\"{relative} lines={lines} reason=not mentioned in agent instructions\")\n continue\n\n saw_hotspot_context = False\n saw_verification_context = False\n has_documented_entry = False\n for index in indices:\n window = lower_text[max(0, index - 700): index + len(relative_lower) + 700]\n line_no = lower_text[:index].count(\"\\n\")\n local_lines = instruction_lines[max(0, line_no - 1): line_no + 4]\n local_context = \"\\n\".join(local_lines)\n has_hotspot_context = bool(HOTSPOT_WORD_RE.search(window))\n has_verification_context = bool(VERIFICATION_WORD_RE.search(local_context))\n saw_hotspot_context = saw_hotspot_context or has_hotspot_context\n saw_verification_context = saw_verification_context or has_verification_context\n if has_hotspot_context and has_verification_context:\n has_documented_entry = True\n break\n\n if has_documented_entry:\n documented.append(f\"{relative} lines={lines}\")\n else:\n reasons = []\n if not saw_hotspot_context:\n reasons.append(\"missing ownership/boundary context\")\n if not saw_verification_context:\n reasons.append(\"missing verification context\")\n if saw_hotspot_context and saw_verification_context:\n reasons.append(\"ownership and verification are not in the same hotspot entry\")\n missing.append(f\"{relative} lines={lines} reason={'; '.join(reasons)}\")\n\n findings: list[str] = []\n if missing:\n findings.append(\"large source files lack hotspot ownership or verification map\")\n return (\"WARN\" if missing else \"PASS\"), documented, missing, findings\n\n\ndef main() -> int:\n parser = argparse.ArgumentParser(description=__doc__)\n parser.add_argument(\"root\", nargs=\"?\", default=\".\", help=\"Repo root (default: cwd)\")\n parser.add_argument(\n \"mode\", nargs=\"?\", default=\"summary\", choices=(\"summary\", \"deep\"),\n help=\"Output detail level\",\n )\n args = parser.parse_args()\n root = Path(args.root).resolve()\n mode = args.mode\n\n if not root.is_dir():\n print(f\"Repo root not found: {root}\", file=sys.stderr)\n return 2\n\n files = iter_files(root)\n tracked_count = len(files)\n extensions = Counter(path.suffix.lower() or \"(none)\" for path in files)\n detected_manifests = [\n name\n for name in [\n \"Makefile\", \"package.json\", \"Cargo.toml\", \"go.mod\", \"pyproject.toml\",\n \"pytest.ini\", \"pom.xml\", \"deno.json\", \"deno.jsonc\",\n ]\n if (root / name).is_file()\n ]\n workflows_dir = root / \".github\" / \"workflows\"\n workflow_count = 0\n if workflows_dir.is_dir():\n workflow_count = len(list(workflows_dir.glob(\"*.yml\"))) + len(list(workflows_dir.glob(\"*.yaml\")))\n if workflow_count:\n detected_manifests.append(f\".github/workflows ({workflow_count})\")\n\n source_files = [path for path in files if path.suffix.lower() in SOURCE_EXTS]\n source_stats: list[tuple[int, int, Path]] = []\n for path in source_files:\n try:\n size = path.stat().st_size\n except OSError:\n size = 0\n source_stats.append((line_count(path), size, path))\n source_stats.sort(key=lambda item: (item[0], item[1]), reverse=True)\n\n dir_counts: Counter[str] = Counter()\n for path in files:\n relative_parts = Path(rel(path, root)).parts\n top = relative_parts[0] if len(relative_parts) > 1 else \".\"\n dir_counts[top] += 1\n\n instruction_files = instruction_paths(root)\n project_map = find_text_signal(\n instruction_files,\n [r\"repository map\", r\"project map\", r\"repo map\", r\"\\bproject\\b\", r\"目录\", r\"仓库\", r\"结构\"],\n )\n instruction_verification = find_text_signal(\n instruction_files,\n [r\"verification\", r\"test plan\", r\"make test\", r\"npm test\", r\"pytest\", r\"cargo test\", r\"验证\", r\"测试\"],\n )\n boundaries = find_text_signal(\n instruction_files,\n [r\"not for\", r\"do not\", r\"non-?goals?\", r\"scope\", r\"boundar\", r\"never\", r\"avoid\", r\"边界\", r\"非目标\", r\"不要\"],\n )\n commands, missing_references, make_targets, _package_scripts = verification_surface(root, instruction_files)\n stable_make_targets = sorted(make_targets & {\"check\", \"test\", \"verify\"})\n wrapper_warnings: list[str] = []\n if len(commands) >= 2 and (root / \"Makefile\").is_file() and not stable_make_targets:\n wrapper_warnings.append(\n \"multiple verification commands discovered but Makefile lacks check/test/verify wrapper\"\n )\n\n decision_artifacts = {\n \"docs_dir\": (root / \"docs\").is_dir(),\n \"specs_dir\": (root / \"specs\").is_dir(),\n \"specify_dir\": (root / \".specify\").is_dir(),\n \"handoff_md\": any(path.name.upper() == \"HANDOFF.MD\" for path in root.glob(\"*.md\")),\n \"changelog\": any(path.name.upper().startswith(\"CHANGELOG\") for path in root.glob(\"*\")),\n \"issue_templates\": (root / \".github\" / \"ISSUE_TEMPLATE\").exists(),\n \"pr_template\": any(\n path.is_file()\n for path in [\n root / \".github\" / \"pull_request_template.md\",\n root / \".github\" / \"PULL_REQUEST_TEMPLATE.md\",\n ]\n ),\n }\n\n todo_counts: Counter[str] = Counter()\n todo_total = 0\n for path in source_files:\n text = read_text(path, 200_000)\n # Count marker-bearing lines, not marker words. Documentation often names\n # the full marker family in one rule line; treating that as four issues\n # makes the checker flag itself instead of real TODO piles.\n count = sum(1 for line in text.splitlines() if MARKER_RE.search(line))\n if count:\n todo_counts[rel(path, root)] += count\n todo_total += count\n\n large_line_limit = 1200 if mode == \"summary\" else 800\n large_file_records = [\n (lines, size, path) for lines, size, path in source_stats if lines >= large_line_limit\n ]\n large_files = [f\"{rel(path, root)} lines={lines} bytes={size}\" for lines, size, path in large_file_records]\n todo_hotspots = [\n f\"{path} markers={count}\" for path, count in todo_counts.most_common(8 if mode == \"deep\" else 5)\n ]\n\n doc_ref_status = \"unavailable\"\n doc_ref_detail = \"\"\n checker = os.environ.get(\"DOC_REF_CHECKER\")\n if checker and Path(checker).is_file():\n proc = subprocess.run(\n [\"bash\", checker, str(root)],\n text=True,\n stdout=subprocess.PIPE,\n stderr=subprocess.STDOUT,\n check=False,\n )\n doc_ref_status = \"pass\" if proc.returncode == 0 else \"fail\"\n if proc.stdout.strip():\n first_lines = proc.stdout.strip().splitlines()[:8]\n doc_ref_detail = \" | \".join(first_lines)\n\n has_instruction_surface = bool(instruction_files)\n has_command_surface = bool(commands)\n context_warnings: list[str] = []\n verification_warnings: list[str] = []\n drift_warnings: list[str] = []\n\n if not has_instruction_surface:\n context_warnings.append(\"no agent instruction surface\")\n if has_instruction_surface and not project_map:\n context_warnings.append(\"instructions lack project map\")\n if has_instruction_surface and not instruction_verification:\n context_warnings.append(\"instructions lack verification guidance\")\n if has_instruction_surface and not boundaries:\n context_warnings.append(\"instructions lack scope/boundary language\")\n if not has_command_surface:\n verification_warnings.append(\"no executable verification command discovered\")\n if missing_references:\n verification_warnings.append(\"instruction references missing commands\")\n if todo_total >= (50 if mode == \"summary\" else 25):\n drift_warnings.append(\"TODO/FIXME/HACK/XXX markers are concentrated\")\n hotspot_status, documented_hotspots, missing_hotspot_ownership, hotspot_findings = (\n hotspot_ownership_surface(large_file_records, instruction_files, mode, root)\n )\n if large_files and mode != \"deep\":\n drift_warnings.append(\"large source files need ownership or module boundaries\")\n if hotspot_status == \"WARN\":\n drift_warnings.extend(hotspot_findings)\n if doc_ref_status == \"fail\":\n drift_warnings.append(\"broken documentation references\")\n\n markdown_missing: list[str] = []\n markdown_link_status = \"SKIPPED\"\n if mode == \"deep\":\n markdown_missing = scan_markdown_links(files, root)\n markdown_link_status = \"WARN\" if markdown_missing else \"PASS\"\n if markdown_missing:\n drift_warnings.append(\"broken Markdown links\")\n\n context_status = \"FAIL\" if not has_instruction_surface else (\"WARN\" if context_warnings else \"PASS\")\n verification_status = \"FAIL\" if not has_command_surface else (\"WARN\" if verification_warnings else \"PASS\")\n decision_status = \"PASS\"\n wrapper_status = \"WARN\" if wrapper_warnings else \"PASS\"\n drift_status = \"WARN\" if drift_warnings else \"PASS\"\n\n if context_status == \"FAIL\" or verification_status == \"FAIL\" or doc_ref_status == \"fail\":\n overall = \"FAIL\"\n elif \"WARN\" in {\n context_status, verification_status, decision_status, wrapper_status,\n drift_status, markdown_link_status, hotspot_status,\n }:\n overall = \"WARN\"\n else:\n overall = \"PASS\"\n\n top_ext = [f\"{ext} files={count}\" for ext, count in extensions.most_common(10)]\n largest_sources = [\n f\"{rel(path, root)} lines={lines} bytes={size}\"\n for lines, size, path in source_stats[: (10 if mode == \"deep\" else 5)]\n ]\n largest_dirs = [f\"{directory} files={count}\" for directory, count in dir_counts.most_common(8)]\n\n print(\"=== PROJECT SHAPE ===\")\n print(f\"maintainability_status: {overall}\")\n print(f\"mode: {mode}\")\n print(f\"tracked_files: {tracked_count}\")\n print(\"top_extensions:\")\n print_list(top_ext)\n print(\"largest_source_files:\")\n print_list(largest_sources)\n print(\"largest_directories:\")\n print_list(largest_dirs)\n\n print(\"=== AI CONTEXT SURFACE ===\")\n print(f\"context_status: {context_status}\")\n print(f\"AGENTS.md: {'yes' if (root / 'AGENTS.md').is_file() else 'no'}\")\n print(f\"CLAUDE.md: {'yes' if (root / 'CLAUDE.md').is_file() else 'no'}\")\n print(f\".github/copilot-instructions.md: {'yes' if (root / '.github' / 'copilot-instructions.md').is_file() else 'no'}\")\n github_instruction_count = (\n len(list((root / \".github\" / \"instructions\").glob(\"*.md\")))\n if (root / \".github\" / \"instructions\").is_dir() else 0\n )\n print(f\".github/instructions/*.md: {github_instruction_count}\")\n print(f\"GEMINI.md: {'yes' if (root / 'GEMINI.md').is_file() else 'no'}\")\n print(f\"project_map: {'yes' if project_map else 'no'}\")\n print(f\"verification_guidance: {'yes' if instruction_verification else 'no'}\")\n print(f\"boundary_guidance: {'yes' if boundaries else 'no'}\")\n print(\"context_findings:\")\n print_list(context_warnings)\n print(\"instruction_files:\")\n print_list([rel(path, root) for path in instruction_files])\n\n print(\"=== VERIFICATION SURFACE ===\")\n print(f\"verification_status: {verification_status}\")\n print(\"detected_manifests:\")\n print_list(detected_manifests)\n print(\"commands:\")\n print_list(commands, limit=12 if mode == \"summary\" else None)\n print(\"missing_referenced_commands:\")\n print_list(missing_references, limit=10 if mode == \"summary\" else None)\n print(\"verification_findings:\")\n print_list(verification_warnings)\n\n print(\"=== VERIFICATION WRAPPER SURFACE ===\")\n print(f\"wrapper_status: {wrapper_status}\")\n print(f\"makefile_present: {'yes' if (root / 'Makefile').is_file() else 'no'}\")\n print(\"stable_make_targets:\")\n print_list([f\"make {target}\" for target in stable_make_targets])\n print(\"wrapper_findings:\")\n print_list(wrapper_warnings)\n\n print(\"=== DECISION ARTIFACTS ===\")\n print(f\"decision_artifacts_status: {decision_status}\")\n for key, value in decision_artifacts.items():\n print(f\"{key}: {'yes' if value else 'no'}\")\n\n print(\"=== DRIFT MARKERS ===\")\n print(f\"drift_status: {drift_status}\")\n print(f\"todo_markers: {todo_total}\")\n print(\"todo_hotspots:\")\n print_list(todo_hotspots)\n print(\"large_source_files:\")\n print_list(large_files[: (10 if mode == \"deep\" else 5)])\n print(f\"broken_doc_references: {doc_ref_status}\")\n if doc_ref_detail and (mode == \"deep\" or doc_ref_status == \"fail\"):\n print(f\"broken_doc_reference_detail: {doc_ref_detail}\")\n print(\"drift_findings:\")\n print_list(drift_warnings)\n\n print(\"=== HOTSPOT OWNERSHIP SURFACE ===\")\n print(f\"hotspot_ownership_status: {hotspot_status}\")\n print(f\"large_hotspot_threshold_lines: {large_line_limit if mode == 'deep' else '(deep mode only)'}\")\n print(\"documented_hotspots:\")\n if mode == \"deep\":\n print_list(documented_hotspots)\n else:\n print(\" (skipped: deep mode only)\")\n print(\"missing_hotspot_ownership:\")\n if mode == \"deep\":\n print_list(missing_hotspot_ownership)\n else:\n print(\" (skipped: deep mode only)\")\n print(\"hotspot_ownership_findings:\")\n if mode == \"deep\":\n print_list(hotspot_findings)\n else:\n print(\" (skipped: deep mode only)\")\n\n print(\"=== MARKDOWN LINK SURFACE ===\")\n print(f\"markdown_link_status: {markdown_link_status}\")\n print(\"missing_markdown_links:\")\n if mode == \"deep\":\n print_list(markdown_missing, limit=20)\n else:\n print(\" (skipped: deep mode only)\")\n return 0\n\n\nif __name__ == \"__main__\":\n sys.exit(main())\n","content_type":"text/x-python; charset=utf-8","language":"python","size":24336,"content_sha256":"5b0477c20a6564dffbc8ea6af7d8665779d7110d7e5d63801b3189e74169fb74"},{"filename":"scripts/check_verifier_output.py","content":"#!/usr/bin/env python3\n\"\"\"Scan a verifier log for stale external paths and suggest cache-clean commands.\n\nDetects /tmp/ and /private/tmp/ file references that no longer exist; these are\nthe signature of stale worktrees pointed at by a verifier (golangci-lint cache,\ngo build cache, npm cache, etc.).\n\nRun as: python3 check_verifier_output.py ROOT LOG_FILE\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport re\nimport sys\nfrom pathlib import Path\n\n\nTOKEN_RE = re.compile(\n r\"(?P\u003cpath>(?:/|\\.\\./)(?:[^\\s:'\\\"(),]+/)*[^\\s:'\\\"(),]+\\.[A-Za-z0-9_+-]+)\"\n)\nTMP_RE = re.compile(r\"(^|/)(private/)?tmp/\")\n\n\ndef main() -> int:\n parser = argparse.ArgumentParser(description=__doc__)\n parser.add_argument(\"root\", help=\"Repo root\")\n parser.add_argument(\"log_file\", help=\"Verifier log to scan\")\n args = parser.parse_args()\n\n root = Path(args.root).resolve()\n log_file = Path(args.log_file).resolve()\n if not root.is_dir():\n print(f\"Repo root not found: {root}\", file=sys.stderr)\n return 2\n if not log_file.is_file():\n print(f\"Log file not found: {log_file}\", file=sys.stderr)\n return 2\n\n text = log_file.read_text(encoding=\"utf-8\", errors=\"replace\")\n\n def normalize(token: str) -> Path:\n if token.startswith(\"/\"):\n return Path(token)\n return (root / token).resolve()\n\n paths: list[Path] = []\n for match in TOKEN_RE.finditer(text):\n token = match.group(\"path\").rstrip(\".\")\n if \"/.git/\" in token:\n continue\n path = normalize(token)\n if TMP_RE.search(path.as_posix()):\n paths.append(path)\n\n unique_paths = []\n seen = set()\n for path in paths:\n value = path.as_posix()\n if value in seen:\n continue\n seen.add(value)\n unique_paths.append(path)\n\n stale_paths = [path for path in unique_paths if not path.exists()]\n existing_paths = [path for path in unique_paths if path.exists()]\n lower = text.lower()\n\n actions: list[str] = []\n if stale_paths:\n if \"golangci-lint\" in lower or \"errcheck\" in lower:\n actions.append(\"golangci-lint cache clean\")\n if re.search(r\"\\bgo (test|vet|build)\\b\", lower) or \"go-build\" in lower:\n actions.append(\"go clean -cache -testcache\")\n if \"npm\" in lower or \"node_modules\" in lower:\n actions.append(\"npm cache verify\")\n if not actions:\n actions.append(\"rerun the verifier after removing stale temporary worktrees\")\n\n status = \"WARN\" if stale_paths else \"PASS\"\n\n print(\"=== VERIFIER OUTPUT SURFACE ===\")\n print(f\"verifier_output_status: {status}\")\n print(f\"log_file: {log_file}\")\n print(\"stale_paths:\")\n if stale_paths:\n for path in stale_paths[:20]:\n print(f\" {path}\")\n if len(stale_paths) > 20:\n print(f\" ... {len(stale_paths) - 20} more\")\n else:\n print(\" (none)\")\n print(\"existing_tmp_paths:\")\n if existing_paths:\n for path in existing_paths[:10]:\n print(f\" {path}\")\n if len(existing_paths) > 10:\n print(f\" ... {len(existing_paths) - 10} more\")\n else:\n print(\" (none)\")\n print(\"recommended_actions:\")\n if actions:\n for action in dict.fromkeys(actions):\n print(f\" {action}\")\n else:\n print(\" (none)\")\n print(\"verifier_findings:\")\n if stale_paths:\n print(\" stale external verifier paths detected\")\n else:\n print(\" (none)\")\n return 0\n\n\nif __name__ == \"__main__\":\n sys.exit(main())\n","content_type":"text/x-python; charset=utf-8","language":"python","size":3561,"content_sha256":"15b7be020d913b2a59805e7af8bad5674f53f69a4c3bf96d817fcf0e9d4c07bb"},{"filename":"scripts/check-agent-context.sh","content":"#!/usr/bin/env bash\nset -euo pipefail\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\nexec python3 \"$SCRIPT_DIR/check_agent_context.py\" \"$@\"\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":153,"content_sha256":"18a7f26c11c0bcf020b50e7f40baf6fd6f558bc7a4a817fbb3582cbfcdb0f3d6"},{"filename":"scripts/check-doc-refs.sh","content":"#!/usr/bin/env bash\nset -euo pipefail\n\nROOT=\"${1:-$PWD}\"\nROOT=\"$(cd \"$ROOT\" && pwd)\"\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\n\nexec python3 \"$SCRIPT_DIR/check_doc_refs.py\" \"$ROOT\"\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":198,"content_sha256":"142466ef8b35f3f3527ecb4dca467eb2175efb4fa4bb1ffbb36726b3c8ace205"},{"filename":"scripts/check-maintainability.sh","content":"#!/usr/bin/env bash\nset -euo pipefail\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\n# Let the Python checker run the doc-ref checker as a subprocess; keep the env\n# var so existing callers depending on this delegation keep working.\nexport DOC_REF_CHECKER=\"${DOC_REF_CHECKER:-$SCRIPT_DIR/check-doc-refs.sh}\"\nexec python3 \"$SCRIPT_DIR/check_maintainability.py\" \"$@\"\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":378,"content_sha256":"2f318cd7159c0cbea74283c673a1542568c54c054848ec54496445bc37cd4ab1"},{"filename":"scripts/check-verifier-output.sh","content":"#!/usr/bin/env bash\nset -euo pipefail\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\nexec python3 \"$SCRIPT_DIR/check_verifier_output.py\" \"$@\"\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":155,"content_sha256":"d6ad40b8c304a9203c48a68ad9a104a086e5824b2a45cf6edce64fe991961676"},{"filename":"scripts/collect-data.sh","content":"#!/usr/bin/env bash\n# Collect agent configuration data for health audit.\n# Outputs labeled sections for each data source.\n# Run from any directory; uses pwd as the project root.\n#\n# Known failure modes (for interpreting (unavailable) output):\n# jq not installed -> conversation extract and signals print \"(unavailable)\"; treat as [INSUFFICIENT DATA]\n# python3 not on PATH -> MCP/hooks/allowedTools sections print \"(unavailable)\"; do not flag those areas\n# settings.local.json absent -> hooks, MCP, allowedTools all show \"(unavailable)\"; normal for global-settings-only projects\n# MEMORY.md path -> built via sed on pwd; unusual chars produce wrong project key; verify manually if (none) seems wrong\n# Conversation scope -> only 2 most recent .jsonl files sampled; fewer than 2 = [LOW CONFIDENCE]\n# MCP token estimate -> assumes ~25 tools/server, ~200 tokens/tool; treat as directional, not precise\n# Tier misclassification -> .next/, __pycache__, .turbo/ can inflate file count; recheck manually if tier feels wrong\nset -euo pipefail\n\nP=$(pwd)\nSETTINGS=\"$P/.claude/settings.local.json\"\nTIER=\"${1:-auto}\"\nMODE=\"${2:-${WAZA_HEALTH_MODE:-summary}}\"\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\nif [ \"${WAZA_HEALTH_DEEP:-0}\" = \"1\" ]; then\n MODE=\"deep\"\nfi\ncase \"$MODE\" in\n summary|deep) ;;\n *) MODE=\"summary\" ;;\nesac\nPROJECT_KEY=$(printf '%s' \"$P\" | sed 's|[/_]|-|g; s|^-||')\nCONVO_DIR=\"$HOME/.claude/projects/-${PROJECT_KEY}\"\n\nresolve_health_helper() {\n local name=\"$1\"\n local installed_path=\"\"\n local candidate=\"\"\n\n for candidate in \"$SCRIPT_DIR/$name\" \"./skills/health/scripts/$name\"; do\n if [ -f \"$candidate\" ]; then\n printf '%s\\n' \"$candidate\"\n return 0\n fi\n done\n\n installed_path=\"$(npx skills path tw93/Waza 2>/dev/null || true)\"\n if [ -n \"$installed_path\" ] && [ -f \"$installed_path/skills/health/scripts/$name\" ]; then\n printf '%s\\n' \"$installed_path/skills/health/scripts/$name\"\n return 0\n fi\n\n return 1\n}\n\ncount_project_files() {\n local count\n count=$(git -C \"$P\" ls-files 2>/dev/null | wc -l | tr -d ' ' || true)\n if [ -z \"$count\" ] || [ \"$count\" = \"0\" ]; then\n count=$(find \"$P\" -type f \\\n -not -path \"*/.git/*\" \\\n -not -path \"*/node_modules/*\" \\\n -not -path \"*/dist/*\" \\\n -not -path \"*/build/*\" \\\n 2>/dev/null | wc -l | tr -d ' ')\n fi\n printf '%s\\n' \"${count:-0}\"\n}\n\ncount_contributors() {\n local count\n count=$(git -C \"$P\" log -n 500 --format='%ae' 2>/dev/null | sort -u | wc -l | tr -d ' ' || true)\n printf '%s\\n' \"${count:-0}\"\n}\n\ncount_ci_workflows() {\n local count=0\n if [ -d \"$P/.github/workflows\" ]; then\n count=$(find \"$P/.github/workflows\" -maxdepth 1 -type f \\( -name \"*.yml\" -o -name \"*.yaml\" \\) 2>/dev/null | wc -l | tr -d ' ')\n fi\n printf '%s\\n' \"${count:-0}\"\n}\n\ncount_local_skills() {\n local count=0\n if [ -d \"$P/.claude/skills\" ]; then\n count=$(find -L \"$P/.claude/skills\" -maxdepth 4 -name \"SKILL.md\" 2>/dev/null | while IFS= read -r f; do\n grep -q '^name: health

Health: Agent Config and AI Maintainability Prefix your first line with 🥷 inline, not as its own paragraph. Audit the current project's agent setup and AI coding maintainability against this framework: Find violations. Identify the misaligned layer. Calibrate to project complexity only. Output language: Check in order: (1) project agent instructions ( before runtime-specific files); (2) global agent instructions; (3) user's recent language; (4) English. Budget posture: Start with the summary audit. Escalate automatically when the user asks for a deep, full, complete, thorough, "深入", "完整", "彻…

\"$f\" 2>/dev/null && continue\n echo \"$f\"\n done | wc -l | tr -d ' ')\n fi\n printf '%s\\n' \"${count:-0}\"\n}\n\nresolve_symlink() {\n readlink -f \"$1\" 2>/dev/null && return\n # macOS fallback: resolve symlink chain manually\n local target=\"$1\"\n local depth=0\n while [ -L \"$target\" ] && [ \"$depth\" -lt 32 ]; do\n local dir\n dir=$(cd \"$(dirname \"$target\")\" && pwd -P)\n target=$(readlink \"$target\")\n case \"$target\" in /*) ;; *) target=\"$dir/$target\" ;; esac\n depth=$((depth + 1))\n done\n printf '%s\\n' \"$target\"\n}\n\ncount_file_lines() {\n local file=\"$1\"\n if [ -f \"$file\" ]; then\n wc -l \u003c \"$file\" | tr -d ' '\n else\n echo 0\n fi\n}\n\ncount_file_words() {\n local file=\"$1\"\n if [ -f \"$file\" ]; then\n wc -w \u003c \"$file\" | tr -d ' '\n else\n echo 0\n fi\n}\n\nlist_rule_files() {\n if [ -d \"$P/.claude/rules\" ]; then\n find \"$P/.claude/rules\" -type f -name \"*.md\" 2>/dev/null | sort || true\n fi\n}\n\nprint_rule_files() {\n local found=0\n while IFS= read -r f; do\n [ -n \"$f\" ] || continue\n found=1\n echo \"--- $f ---\"\n cat \"$f\"\n done \u003c \u003c(list_rule_files)\n [ \"$found\" -eq 1 ] || echo \"(none)\"\n}\n\nprint_file_summary() {\n local label=\"$1\"\n local file=\"$2\"\n\n if [ ! -f \"$file\" ]; then\n echo \"${label}_present: no\"\n return\n fi\n\n echo \"${label}_present: yes\"\n echo \"${label}_path: $file\"\n echo \"${label}_lines: $(count_file_lines \"$file\")\"\n echo \"${label}_words: $(count_file_words \"$file\")\"\n\n local headings\n headings=$(grep -nE '^[[:space:]]*#{1,3}[[:space:]]+' \"$file\" 2>/dev/null | head -8 || true)\n if [ -n \"$headings\" ]; then\n echo \"${label}_headings:\"\n printf '%s\\n' \"$headings\" | sed 's/^/ /'\n fi\n}\n\nprint_settings_summary() {\n local file=\"$1\"\n if [ ! -f \"$file\" ]; then\n echo \"settings_local_json: no\"\n return\n fi\n\n echo \"settings_local_json: yes\"\n echo \"settings_local_json_path: $file\"\n echo \"settings_local_json_lines: $(count_file_lines \"$file\")\"\n echo \"settings_local_json_bytes: $(wc -c \u003c \"$file\" | tr -d ' ')\"\n}\n\nprint_rule_file_summary() {\n local files count=0\n files=$(list_rule_files)\n if [ -z \"$files\" ]; then\n echo \"rule_files: 0\"\n return\n fi\n\n count=$(printf '%s\\n' \"$files\" | wc -l | tr -d ' ')\n echo \"rule_files: $count\"\n while IFS= read -r f; do\n [ -n \"$f\" ] || continue\n echo \"path=$f lines=$(count_file_lines \"$f\") words=$(count_file_words \"$f\")\"\n done \u003c\u003cEOF\n$files\nEOF\n}\n\nrules_word_count() {\n local words=0\n if [ -d \"$P/.claude/rules\" ]; then\n words=$(while IFS= read -r f; do\n [ -n \"$f\" ] || continue\n cat \"$f\"\n done \u003c \u003c(list_rule_files) | wc -w | tr -d ' ')\n fi\n printf '%s\\n' \"${words:-0}\"\n}\n\ncollect_skill_descriptions_raw() {\n if [ -d \"$P/.claude/skills\" ]; then\n grep -r \"^description:\" \"$P/.claude/skills\" 2>/dev/null || true\n fi\n if [ -d \"$HOME/.claude/skills\" ]; then\n grep -r \"^description:\" \"$HOME/.claude/skills\" 2>/dev/null || true\n fi\n}\n\nprint_skill_descriptions() {\n local out\n out=$(collect_skill_descriptions_raw | sort -u)\n if [ -n \"$out\" ]; then\n printf '%s\\n' \"$out\"\n else\n echo \"(none)\"\n fi\n}\n\nprint_skill_description_summary() {\n local out count\n out=$(collect_skill_descriptions_raw | sort -u)\n if [ -z \"$out\" ]; then\n echo \"skill_descriptions: 0\"\n return\n fi\n\n count=$(printf '%s\\n' \"$out\" | wc -l | tr -d ' ')\n echo \"skill_descriptions: $count\"\n printf '%s\\n' \"$out\" | head -20 | awk -F: '{\n path=$1\n line=$0\n sub(/^[^:]*:/, \"\", line)\n printf \"path=%s description_chars=%d\\n\", path, length(line)\n }'\n if [ \"$count\" -gt 20 ]; then\n echo \"skill_descriptions_truncated: yes\"\n fi\n}\n\nskill_description_word_count() {\n local words\n words=$(collect_skill_descriptions_raw | wc -w | tr -d ' ')\n printf '%s\\n' \"${words:-0}\"\n}\n\nlist_skill_files() {\n local dir=\"$1\"\n [ -d \"$dir\" ] || return 0\n find -L \"$dir\" -maxdepth 4 -name \"SKILL.md\" 2>/dev/null | sort || true\n}\n\nis_health_skill() {\n grep -q '^name: health

Health: Agent Config and AI Maintainability Prefix your first line with 🥷 inline, not as its own paragraph. Audit the current project's agent setup and AI coding maintainability against this framework: Find violations. Identify the misaligned layer. Calibrate to project complexity only. Output language: Check in order: (1) project agent instructions ( before runtime-specific files); (2) global agent instructions; (3) user's recent language; (4) English. Budget posture: Start with the summary audit. Escalate automatically when the user asks for a deep, full, complete, thorough, "深入", "完整", "彻…

\"$1\" 2>/dev/null\n}\n\nlist_conversation_files() {\n [ -d \"$CONVO_DIR\" ] || return 0\n ls -1t \"$CONVO_DIR\"/*.jsonl 2>/dev/null || true\n}\n\nprint_conversation_file_listing() {\n local out\n out=$(ls -lhS \"$CONVO_DIR\"/*.jsonl 2>/dev/null || true)\n if [ -n \"$out\" ]; then\n printf '%s\\n' \"$out\" | head -10\n else\n echo \"(no conversation files)\"\n fi\n}\n\nprevious_conversation_files() {\n list_conversation_files | tail -n +2 | head -2\n}\n\nsample_jsonl_prefix() {\n local file=\"$1\"\n local limit=\"${2:-512000}\"\n LC_ALL=C awk -v limit=\"$limit\" '\n {\n line = $0 ORS\n next_bytes = bytes + length(line)\n if (next_bytes > limit) {\n exit\n }\n printf \"%s\", line\n bytes = next_bytes\n }\n ' \"$file\"\n}\n\nextract_messages_from_file() {\n local file=\"$1\"\n sample_jsonl_prefix \"$file\" | jq -r '\n def flatten:\n if (.isMeta // false) or (.toolUseResult? != null) then\n empty\n else\n (.message.content // .content // .text // \"\")\n | if type == \"array\" then\n [ .[] | if type == \"object\" and .type == \"text\" then .text elif type == \"string\" then . else empty end ] | join(\" \")\n elif type == \"string\" then .\n else empty\n end\n | gsub(\"[\\\\r\\\\n]+\"; \" \")\n | gsub(\" +\"; \" \")\n | sub(\"^ \"; \"\")\n | sub(\" $\"; \"\")\n end;\n (.type // .role // \"\") as $kind\n | (flatten) as $text\n | if ($text | length) == 0 then\n empty\n elif $kind == \"user\" then\n \"USER: \" + $text\n elif $kind == \"assistant\" then\n \"ASSISTANT: \" + $text\n elif $kind == \"system\" then\n \"SYSTEM: \" + $text\n else\n empty\n end\n ' 2>/dev/null\n}\n\nextract_signals_from_file() {\n local file=\"$1\"\n sample_jsonl_prefix \"$file\" | jq -r '\n def flatten:\n if (.isMeta // false) or (.toolUseResult? != null) then\n empty\n else\n (.message.content // .content // .text // \"\")\n | if type == \"array\" then\n [ .[] | if type == \"object\" and .type == \"text\" then .text elif type == \"string\" then . else empty end ] | join(\" \")\n elif type == \"string\" then .\n else empty\n end\n | gsub(\"[\\\\r\\\\n]+\"; \" \")\n | gsub(\" +\"; \" \")\n | sub(\"^ \"; \"\")\n | sub(\" $\"; \"\")\n end;\n def is_correction:\n test(\"(?i)(\\\\bdon'\\''t\\\\b|\\\\bdo not\\\\b|\\\\bplease don'\\''t\\\\b|\\\\binstead\\\\b|\\\\bnext time\\\\b|\\\\bremember\\\\b|\\\\buse\\\\b.*\\\\binstead\\\\b|\\\\bnot\\\\b.*\\\\bbut\\\\b)\")\n or test(\"(不要再|请不要|不要|别再|下次|记得|改成|改为|而不是|别用|去掉|统一成)\");\n (.type // .role // \"\") as $kind\n | (flatten) as $text\n | if ($text | length) == 0 then\n empty\n elif ($text | test(\"(?i)(conversation was compressed|context limit|context window|truncat|/compact|context management|token limit|window is full|compaction)\")) then\n \"CONTEXT SIGNAL: \" + $text\n # Keep this conservative: false positives pollute enforcement-gap analysis.\n elif $kind == \"user\" and ($text | is_correction) then\n \"USER CORRECTION: \" + $text\n else\n empty\n end\n ' 2>/dev/null\n}\n\nprint_conversation_signals() {\n local files file chunk found=0\n files=$(previous_conversation_files)\n if [ -z \"$files\" ]; then\n echo \"(no conversation files)\"\n return\n fi\n if ! command -v jq >/dev/null 2>&1; then\n echo \"(unavailable: jq not installed or parse error)\"\n return\n fi\n while IFS= read -r file; do\n [ -f \"$file\" ] || continue\n if ! chunk=$(extract_signals_from_file \"$file\"); then\n echo \"(unavailable: jq not installed or parse error)\"\n return\n fi\n chunk=$(printf '%s\\n' \"$chunk\" | head -20 || true)\n if [ -n \"$chunk\" ]; then\n found=1\n echo \"--- file: $file ---\"\n printf '%s\\n' \"$chunk\"\n fi\n done \u003c\u003cEOF\n$files\nEOF\n [ \"$found\" -eq 1 ] || echo \"(no conversation signals detected)\"\n}\n\nprint_conversation_extract() {\n local files file chunk found=0\n files=$(previous_conversation_files)\n if [ -z \"$files\" ]; then\n echo \"(no conversation files)\"\n return\n fi\n if ! command -v jq >/dev/null 2>&1; then\n echo \"(unavailable: jq not installed or parse error)\"\n return\n fi\n while IFS= read -r file; do\n [ -f \"$file\" ] || continue\n found=1\n echo \"--- file: $file ---\"\n if ! chunk=$(extract_messages_from_file \"$file\"); then\n echo \"(unavailable: jq not installed or parse error)\"\n return\n fi\n chunk=$(printf '%s\\n' \"$chunk\" | grep -v '^ASSISTANT:

Health: Agent Config and AI Maintainability Prefix your first line with 🥷 inline, not as its own paragraph. Audit the current project's agent setup and AI coding maintainability against this framework: Find violations. Identify the misaligned layer. Calibrate to project complexity only. Output language: Check in order: (1) project agent instructions ( before runtime-specific files); (2) global agent instructions; (3) user's recent language; (4) English. Budget posture: Start with the summary audit. Escalate automatically when the user asks for a deep, full, complete, thorough, "深入", "完整", "彻…

| head -150 || true)\n if [ -n \"$chunk\" ]; then\n printf '%s\\n' \"$chunk\"\n else\n echo \"(no extractable conversation messages)\"\n fi\n done \u003c\u003cEOF\n$files\nEOF\n [ \"$found\" -eq 1 ] || echo \"(no conversation files)\"\n}\n\nprint_mcp_access_denials() {\n local files file chunk found=0\n files=$(list_conversation_files | head -5)\n if [ -z \"$files\" ]; then\n echo \"(no conversation files)\"\n return\n fi\n while IFS= read -r file; do\n [ -f \"$file\" ] || continue\n chunk=$(head -c 1048576 \"$file\" | grep -Em 2 'Access denied - path outside allowed directories|tool-results/.+ not in ' 2>/dev/null || true)\n if [ -n \"$chunk\" ]; then\n found=1\n printf '%s\\n' \"$chunk\"\n fi\n done \u003c\u003cEOF\n$files\nEOF\n [ \"$found\" -eq 1 ] || echo \"(none found)\"\n}\n\nPROJECT_FILES=$(count_project_files)\nCONTRIBUTORS=$(count_contributors)\nCI_WORKFLOWS=$(count_ci_workflows)\n\necho \"[1/12] Tier metrics...\"\necho \"=== TIER METRICS ===\"\necho \"project_files: $PROJECT_FILES\"\necho \"contributors: $CONTRIBUTORS\"\necho \"ci_workflows: $CI_WORKFLOWS\"\necho \"skills: $(count_local_skills)\"\necho \"claude_md_lines: $(count_file_lines \"$P/CLAUDE.md\")\"\necho \"collection_mode: $MODE\"\n\n# Auto-detect tier if not passed as argument.\n# Matches SKILL.md definition: Simple = \u003c500 files AND \u003c=1 contributor AND no CI.\nif [ \"$TIER\" = \"auto\" ]; then\n if [ \"${PROJECT_FILES:-0}\" -lt 500 ] && [ \"${CONTRIBUTORS:-0}\" -le 1 ] && [ \"${CI_WORKFLOWS:-0}\" -eq 0 ]; then\n TIER=\"simple\"\n elif [ \"${PROJECT_FILES:-0}\" -lt 5000 ]; then\n TIER=\"standard\"\n else\n TIER=\"complex\"\n fi\nfi\necho \"detected_tier: $TIER\"\n\necho \"[2/12] CLAUDE.md (global + local)...\"\necho \"=== CLAUDE.md (global) ===\"\nif [ \"$MODE\" = \"deep\" ]; then\n cat ~/.claude/CLAUDE.md 2>/dev/null || echo \"(none)\"\nelse\n print_file_summary \"global_claude_md\" \"$HOME/.claude/CLAUDE.md\"\nfi\necho \"=== CLAUDE.md (local) ===\"\nif [ \"$MODE\" = \"deep\" ]; then\n cat \"$P/CLAUDE.md\" 2>/dev/null || echo \"(none)\"\nelse\n print_file_summary \"local_claude_md\" \"$P/CLAUDE.md\"\nfi\n\necho \"[3/12] Settings, hooks, MCP...\"\necho \"=== settings.local.json ===\"\nif [ \"$MODE\" = \"deep\" ]; then\n cat \"$SETTINGS\" 2>/dev/null || echo \"(none)\"\nelse\n print_settings_summary \"$SETTINGS\"\nfi\n\necho \"[4/12] Rules + skill descriptions...\"\necho \"=== rules/ ===\"\nif [ \"$MODE\" = \"deep\" ]; then\n print_rule_files\nelse\n print_rule_file_summary\nfi\necho \"=== skill descriptions ===\"\nif [ \"$MODE\" = \"deep\" ]; then\n print_skill_descriptions\nelse\n print_skill_description_summary\nfi\n\necho \"[5/12] Context budget estimate...\"\necho \"=== STARTUP CONTEXT ESTIMATE ===\"\necho \"global_claude_words: $(count_file_words \"$HOME/.claude/CLAUDE.md\")\"\necho \"local_claude_words: $(count_file_words \"$P/CLAUDE.md\")\"\necho \"rules_words: $(rules_word_count)\"\necho \"skill_desc_words: $(skill_description_word_count)\"\nif command -v python3 >/dev/null 2>&1; then\npython3 - \"$SETTINGS\" \"$MODE\" \u003c\u003c'PYEOF' 2>/dev/null || echo \"(unavailable)\"\nimport json\nimport sys\n\npath = sys.argv[1]\nmode = sys.argv[2]\ntry:\n with open(path) as fh:\n d = json.load(fh)\nexcept Exception:\n msg = '(unavailable: settings.local.json missing or malformed)'\n print('=== hooks ===')\n print(msg)\n print('=== MCP ===')\n print(msg)\n print('=== MCP FILESYSTEM ===')\n print(msg)\n print('=== allowedTools count ===')\n print(msg)\n sys.exit(0)\n\nprint('=== hooks ===')\nhooks = d.get('hooks', {})\nif mode == 'deep':\n print(json.dumps(hooks, indent=2))\nelif isinstance(hooks, dict):\n names = sorted(hooks.keys())\n print(f'hook_events: {len(names)}')\n print('hook_event_names:', ', '.join(names) if names else '(none)')\nelse:\n print('hook_events: (unknown format)')\n\nprint('=== MCP ===')\nservers = d.get('mcpServers', d.get('enabledMcpjsonServers', {}))\nnames = list(servers.keys()) if isinstance(servers, dict) else list(servers)\ncount = len(names)\nprint(f'servers({count}):', ', '.join(names))\nest = count * 25 * 200\nprint(f'est_tokens: ~{est} ({round(est/2000)}% of 200K)')\n\nprint('=== MCP FILESYSTEM ===')\nif isinstance(servers, list):\n print('filesystem_present: (array format -- check .mcp.json)')\n print('allowedDirectories: (not detectable)')\nelse:\n filesystem = servers.get('filesystem') if isinstance(servers, dict) else None\n allowed = []\n if isinstance(filesystem, dict):\n allowed = filesystem.get('allowedDirectories') or (\n filesystem.get('config', {}).get('allowedDirectories')\n if isinstance(filesystem.get('config'), dict)\n else []\n )\n if not allowed and isinstance(filesystem.get('args'), list):\n args = filesystem['args']\n for index, value in enumerate(args):\n if value in ('--allowed-directories', '--allowedDirectories') and index + 1 \u003c len(args):\n allowed = [args[index + 1]]\n break\n if not allowed:\n allowed = [value for value in args if value.startswith('/') or (value.startswith('~') and len(value) > 1)]\n print('filesystem_present:', 'yes' if filesystem else 'no')\n if mode == 'deep':\n print('allowedDirectories:', allowed or '(missing or not detected)')\n else:\n print('allowedDirectories_count:', len(allowed))\n\nprint('=== allowedTools count ===')\nprint(len(d.get('permissions', {}).get('allow', [])))\nPYEOF\nelse\n echo \"=== hooks ===\"\n echo \"(unavailable)\"\n echo \"=== MCP ===\"\n echo \"(unavailable)\"\n echo \"=== MCP FILESYSTEM ===\"\n echo \"(unavailable)\"\n echo \"=== allowedTools count ===\"\n echo \"(unavailable)\"\nfi\n\necho \"[6/12] Nested CLAUDE.md + gitignore...\"\necho \"=== NESTED CLAUDE.md ===\"\n_NESTED_CLAUDE=$(find \"$P\" -maxdepth 4 -name \"CLAUDE.md\" -not -path \"$P/CLAUDE.md\" -not -path \"*/.git/*\" -not -path \"*/node_modules/*\" 2>/dev/null || true)\nif [ -n \"$_NESTED_CLAUDE\" ]; then\n printf '%s\\n' \"$_NESTED_CLAUDE\"\nelse\n echo \"(none)\"\nfi\necho \"=== GITIGNORE ===\"\n_GITIGNORE_HIT=$(git -C \"$P\" check-ignore -v .claude/settings.local.json 2>/dev/null || true)\nif [ -n \"$_GITIGNORE_HIT\" ]; then\n _GITIGNORE_SOURCE=${_GITIGNORE_HIT%%:*}\n case \"$_GITIGNORE_SOURCE\" in\n .gitignore|.claude/.gitignore)\n echo \"settings.local.json: gitignored\"\n ;;\n *)\n echo \"settings.local.json: ignored only by non-project rule ($_GITIGNORE_SOURCE) -- add a repo-local ignore rule\"\n ;;\n esac\nelse\n echo \"settings.local.json: NOT gitignored -- risk of committing tokens/credentials\"\nfi\n\necho \"[7/12] HANDOFF.md + MEMORY.md...\"\necho \"=== HANDOFF.md ===\" ; cat \"$P/HANDOFF.md\" 2>/dev/null || echo \"(none)\"\necho \"=== MEMORY.md ===\"\nif [ -f \"$HOME/.claude/projects/-${PROJECT_KEY}/memory/MEMORY.md\" ]; then\n head -50 \"$HOME/.claude/projects/-${PROJECT_KEY}/memory/MEMORY.md\"\nelse\n echo \"(none)\"\nfi\n\necho \"[8/12] Conversation signals + extract...\"\necho \"=== CONVERSATION FILES ===\"\nprint_conversation_file_listing\n\necho \"=== CONVERSATION SIGNALS ===\"\nprint_conversation_signals\n\nif [ \"$TIER\" != \"simple\" ] && [ \"$MODE\" = \"deep\" ]; then\necho \"=== CONVERSATION EXTRACT ===\"\nprint_conversation_extract\necho \"=== MCP ACCESS DENIALS ===\"\nprint_mcp_access_denials\nelse\n echo \"=== CONVERSATION EXTRACT ===\" ; echo \"(skipped: summary mode; ask for a deep health audit or run collect-data.sh auto deep for full conversation extracts)\"\n echo \"=== MCP ACCESS DENIALS ===\" ; echo \"(skipped: summary mode; ask for a deep health audit or run collect-data.sh auto deep for access-denial scan)\"\nfi\n\necho \"[9/12] Agent config...\"\nif [ \"$MODE\" = \"deep\" ]; then\n echo \"=== AGENT CONFIG DETAIL ===\"\nelse\n echo \"=== AGENT CONFIG SUMMARY ===\"\nfi\nAGENT_CONTEXT_SCRIPT=\"$(resolve_health_helper check-agent-context.sh || true)\"\nif [ -n \"$AGENT_CONTEXT_SCRIPT\" ]; then\n if ! bash \"$AGENT_CONTEXT_SCRIPT\" \"$P\" \"$MODE\"; then\n echo \"(unavailable: check-agent-context.sh failed)\"\n fi\nelse\n echo \"(unavailable: check-agent-context.sh not found)\"\nfi\n\necho \"[10/12] AI maintainability...\"\nif [ \"$MODE\" = \"deep\" ]; then\n echo \"=== AI MAINTAINABILITY DETAIL ===\"\nelse\n echo \"=== AI MAINTAINABILITY SUMMARY ===\"\nfi\nMAINTAINABILITY_SCRIPT=\"$(resolve_health_helper check-maintainability.sh || true)\"\nif [ -n \"$MAINTAINABILITY_SCRIPT\" ]; then\n if ! bash \"$MAINTAINABILITY_SCRIPT\" \"$P\" \"$MODE\"; then\n echo \"(unavailable: check-maintainability.sh failed)\"\n fi\nelse\n echo \"(unavailable: check-maintainability.sh not found)\"\nfi\n\necho \"[11/12] Skill inventory + frontmatter + provenance...\"\necho \"=== SKILL INVENTORY ===\"\n_SKILL_FOUND=0\nfor DIR in \"$P/.claude/skills\" \"$HOME/.claude/skills\"; do\n [ -d \"$DIR\" ] || continue\n while IFS= read -r f; do\n [ -n \"$f\" ] || continue\n is_health_skill \"$f\" && continue\n _SKILL_FOUND=1\n WORDS=$(wc -w \u003c \"$f\" | tr -d ' ')\n IS_LINK=\"no\"; LINK_TARGET=\"\"\n SKILL_DIR=$(dirname \"$f\")\n if [ -L \"$SKILL_DIR\" ]; then\n IS_LINK=\"yes\"; LINK_TARGET=$(resolve_symlink \"$SKILL_DIR\")\n fi\n echo \"path=$f words=$WORDS symlink=$IS_LINK target=$LINK_TARGET\"\n done \u003c \u003c(list_skill_files \"$DIR\")\ndone\n[ \"$_SKILL_FOUND\" -eq 1 ] || echo \"(none)\"\n\necho \"=== SKILL FRONTMATTER ===\"\nif [ \"$MODE\" = \"deep\" ]; then\n _FRONTMATTER_FOUND=0\n for DIR in \"$P/.claude/skills\" \"$HOME/.claude/skills\"; do\n [ -d \"$DIR\" ] || continue\n while IFS= read -r f; do\n [ -n \"$f\" ] || continue\n is_health_skill \"$f\" && continue\n _FRONTMATTER_FOUND=1\n if head -1 \"$f\" | grep -q '^---'; then\n echo \"frontmatter=yes path=$f\"\n sed -n '2,/^---$/p' \"$f\" | head -10\n else\n echo \"frontmatter=MISSING path=$f\"\n fi\n done \u003c \u003c(list_skill_files \"$DIR\")\n done\n [ \"$_FRONTMATTER_FOUND\" -eq 1 ] || echo \"(none)\"\nelse\n echo \"(skipped: summary mode; use collect-data.sh auto deep to print skill frontmatter samples)\"\nfi\n\necho \"=== SKILL SYMLINK PROVENANCE ===\"\n_PROVENANCE_FOUND=0\nfor DIR in \"$P/.claude/skills\" \"$HOME/.claude/skills\"; do\n [ -d \"$DIR\" ] || continue\n find \"$DIR\" -maxdepth 1 -type l 2>/dev/null | while IFS= read -r link; do\n _PROVENANCE_FOUND=1\n TARGET=$(resolve_symlink \"$link\")\n echo \"link=$(basename \"$link\") target=$TARGET\"\n GIT_ROOT=$(git -C \"$TARGET\" rev-parse --show-toplevel 2>/dev/null || echo \"\")\n if [ -n \"$GIT_ROOT\" ]; then\n REMOTE=$(git -C \"$GIT_ROOT\" remote get-url origin 2>/dev/null || echo \"unknown\")\n COMMIT=$(git -C \"$GIT_ROOT\" rev-parse --short HEAD 2>/dev/null || echo \"unknown\")\n echo \" git_remote=$REMOTE commit=$COMMIT\"\n fi\n done\ndone\nif ! { for DIR in \"$P/.claude/skills\" \"$HOME/.claude/skills\"; do\n [ -d \"$DIR\" ] || continue\n find \"$DIR\" -maxdepth 1 -type l 2>/dev/null\ndone | grep -q .; }; then\n echo \"(none)\"\nfi\n\necho \"[12/12] Skill content sample + security scan...\"\nif [ \"$TIER\" != \"simple\" ] && [ \"$MODE\" = \"deep\" ]; then\necho \"=== SKILL FULL CONTENT ===\"\n_CONTENT_COUNT=0\nfor DIR in \"$P/.claude/skills\" \"$HOME/.claude/skills\"; do\n [ -d \"$DIR\" ] || continue\n while IFS= read -r f; do\n [ -n \"$f\" ] || continue\n is_health_skill \"$f\" && continue\n _CONTENT_COUNT=$((_CONTENT_COUNT + 1))\n [ \"$_CONTENT_COUNT\" -le 3 ] || break\n echo \"--- FULL: $f ---\"\n head -60 \"$f\"\n done \u003c \u003c(list_skill_files \"$DIR\")\n [ \"$_CONTENT_COUNT\" -ge 3 ] && break\ndone\n[ \"$_CONTENT_COUNT\" -gt 0 ] || echo \"(none)\"\nelse\n echo \"=== SKILL FULL CONTENT ===\" ; echo \"(skipped: summary mode; ask for a deep health audit or run collect-data.sh auto deep to sample skill bodies)\"\nfi\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":22778,"content_sha256":"d612189779f07fa8395557463edd2bd3375788af5d1dd2daf25394344cad56e8"}],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"Health: Agent Config and AI Maintainability","type":"text"}]},{"type":"paragraph","content":[{"text":"Prefix your first line with 🥷 inline, not as its own paragraph.","type":"text"}]},{"type":"paragraph","content":[{"text":"Audit the current project's agent setup and AI coding maintainability against this framework: ","type":"text"},{"text":"agent config → instruction surfaces → tools/runtime → verifiers → maintainability","type":"text","marks":[{"type":"code_inline"}]}]},{"type":"paragraph","content":[{"text":"Find violations. Identify the misaligned layer. Calibrate to project complexity only.","type":"text"}]},{"type":"paragraph","content":[{"text":"Output language:","type":"text","marks":[{"type":"strong"}]},{"text":" Check in order: (1) project agent instructions (","type":"text"},{"text":"AGENTS.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" before runtime-specific files); (2) global agent instructions; (3) user's recent language; (4) English.","type":"text"}]},{"type":"paragraph","content":[{"text":"Budget posture:","type":"text","marks":[{"type":"strong"}]},{"text":" Start with the summary audit. Escalate automatically when the user asks for a deep, full, complete, thorough, \"深入\", \"完整\", \"彻底\", or \"继续跑完\" audit, when the user explicitly mentions AI coding code rot, Codex/Claude config drift, unclear context, missing verification, verifier output that points at stale paths, or \"代码变烂\", when current project instructions or remembered user preference says to run deep health checks by default, when the project is Complex, or when the summary pass exposes a critical ambiguity that cannot be resolved locally. Otherwise do not read full conversation extracts or launch inspector subagents. Tell the user before escalating because deep health audits can consume significant token quota.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Durable Context Preflight","type":"text"}]},{"type":"paragraph","content":[{"text":"See ","type":"text"},{"text":"rules/durable-context.md","type":"text","marks":[{"type":"link","attrs":{"href":"../../rules/durable-context.md","title":null}}]},{"text":" for when to read durable context, the read-order budget, and the memory-type mapping.","type":"text"}]},{"type":"paragraph","content":[{"text":"For ","type":"text"},{"text":"/health","type":"text","marks":[{"type":"code_inline"}]},{"text":", audit expectations are ","type":"text"},{"text":"decision","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"preference","type":"text","marks":[{"type":"code_inline"}]},{"text":", and ","type":"text"},{"text":"principle","type":"text","marks":[{"type":"code_inline"}]},{"text":" entries; checks for repeated failures are ","type":"text"},{"text":"pattern","type":"text","marks":[{"type":"code_inline"}]},{"text":" and ","type":"text"},{"text":"learning","type":"text","marks":[{"type":"code_inline"}]},{"text":". Current CLAUDE.md, installed skills, hooks, MCP config, command output, and live probes override memory. Also flag durable memory problems when they affect behavior: oversized injected summaries, stale or contradictory entries, missing project entrypoint references, or private paths copied into public instructions. Keep these as context findings, not code-review findings.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Step 0: Assess project tier","type":"text"}]},{"type":"paragraph","content":[{"text":"Pick one. Apply only that tier's requirements.","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Tier","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Signal","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"What's expected","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Simple","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\u003c500 files, 1 contributor, no CI","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"CLAUDE.md only; 0-1 skills; hooks optional","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Standard","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"500-5K files, small team or CI","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"CLAUDE.md + 1-2 rules; 2-4 skills; basic hooks","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Complex","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":">5K files, multi-contributor, active CI","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Full six-layer setup required","type":"text"}]}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Step 1: Collect data","type":"text"}]},{"type":"paragraph","content":[{"text":"Run the collection script in summary mode first. Do not interpret yet.","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Resolve collect-data.sh from canonical locations (no personal home-dir paths).\nHEALTH_SCRIPT=\"${CLAUDE_SKILL_DIR:+$CLAUDE_SKILL_DIR/scripts/collect-data.sh}\"\nif [ ! -f \"${HEALTH_SCRIPT:-}\" ]; then\n for candidate in \\\n \"./skills/health/scripts/collect-data.sh\" \\\n \"$(npx skills path tw93/Waza 2>/dev/null)/skills/health/scripts/collect-data.sh\"; do\n [ -f \"$candidate\" ] && HEALTH_SCRIPT=\"$candidate\" && break\n done\nfi\nif [ ! -f \"${HEALTH_SCRIPT:-}\" ]; then\n echo \"health collect-data.sh not found; set CLAUDE_SKILL_DIR or reinstall: npx skills add tw93/Waza -a claude-code -g -y\"\n exit 1\nfi\nbash \"$HEALTH_SCRIPT\"","type":"text"}]},{"type":"paragraph","content":[{"text":"Sections may show ","type":"text"},{"text":"(unavailable)","type":"text","marks":[{"type":"code_inline"}]},{"text":" when tools are missing:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"jq","type":"text","marks":[{"type":"code_inline"}]},{"text":" missing → conversation sections unavailable","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"python3","type":"text","marks":[{"type":"code_inline"}]},{"text":" missing → MCP/hooks/allowedTools sections unavailable","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"settings.local.json","type":"text","marks":[{"type":"code_inline"}]},{"text":" absent → hooks/MCP may be unavailable (normal for global-only setups)","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Treat ","type":"text"},{"text":"(unavailable)","type":"text","marks":[{"type":"code_inline"}]},{"text":" as insufficient data, not a finding. Do not flag those areas.","type":"text"}]},{"type":"paragraph","content":[{"text":"The collector includes both runtime-specific and agent-agnostic surfaces:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"AGENT CONFIG SUMMARY","type":"text","marks":[{"type":"code_inline"}]},{"text":" / ","type":"text"},{"text":"AGENT CONFIG DETAIL","type":"text","marks":[{"type":"code_inline"}]},{"text":" for Codex, Claude, and project instruction files.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"AI MAINTAINABILITY SUMMARY","type":"text","marks":[{"type":"code_inline"}]},{"text":" / ","type":"text"},{"text":"AI MAINTAINABILITY DETAIL","type":"text","marks":[{"type":"code_inline"}]},{"text":" for project shape, verification surface, hotspot ownership, wrappers, and doc links.","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Step 1b: MCP Live Check","type":"text"}]},{"type":"paragraph","content":[{"text":"Test every MCP server: call one harmless tool per server. Record ","type":"text"},{"text":"live=yes/no","type":"text","marks":[{"type":"code_inline"}]},{"text":" with error detail. Respect ","type":"text"},{"text":"enabled: false","type":"text","marks":[{"type":"code_inline"}]},{"text":" (skip without flagging). For API keys, only check if the env var is set (","type":"text"},{"text":"echo $VAR | head -c 5","type":"text","marks":[{"type":"code_inline"}]},{"text":"), never print full keys.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Step 2: Analyze","type":"text"}]},{"type":"paragraph","content":[{"text":"Confirm the tier. Then route:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Simple:","type":"text","marks":[{"type":"strong"}]},{"text":" Analyze locally. No subagents.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Standard:","type":"text","marks":[{"type":"strong"}]},{"text":" Analyze locally from the summary output. Do not launch subagents by default. If the user asks for a deep/full/thorough audit, or if local analysis cannot classify a security/control issue, escalate to deep mode and explain the likely token cost.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Complex, remembered deep preference, explicit deep audit, or explicit AI maintainability audit:","type":"text","marks":[{"type":"strong"}]},{"text":" Re-run collection with ","type":"text"},{"text":"bash \"$HEALTH_SCRIPT\" auto deep","type":"text","marks":[{"type":"code_inline"}]},{"text":", then launch the relevant subagents in parallel. Redact credentials to ","type":"text"},{"text":"[REDACTED]","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Agent 1","type":"text","marks":[{"type":"strong"}]},{"text":" (Context + Security): Read ","type":"text"},{"text":"agents/inspector-context.md","type":"text","marks":[{"type":"code_inline"}]},{"text":". Feed ","type":"text"},{"text":"CONVERSATION SIGNALS","type":"text","marks":[{"type":"code_inline"}]},{"text":" section.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Agent 2","type":"text","marks":[{"type":"strong"}]},{"text":" (Control + Behavior): Read ","type":"text"},{"text":"agents/inspector-control.md","type":"text","marks":[{"type":"code_inline"}]},{"text":". Feed detected tier.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Agent 3","type":"text","marks":[{"type":"strong"}]},{"text":" (AI Maintainability): Read ","type":"text"},{"text":"agents/inspector-maintainability.md","type":"text","marks":[{"type":"code_inline"}]},{"text":". Feed only ","type":"text"},{"text":"TIER METRICS","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"AI MAINTAINABILITY SUMMARY","type":"text","marks":[{"type":"code_inline"}]},{"text":" or ","type":"text"},{"text":"AI MAINTAINABILITY DETAIL","type":"text","marks":[{"type":"code_inline"}]},{"text":", and the script hotspot lists. Launch this agent only for deep health audits, Complex projects, or explicit code-rot/AI-maintainability requests.","type":"text"}]}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Fallback:","type":"text","marks":[{"type":"strong"}]},{"text":" If a subagent fails, analyze that layer locally and note \"(analyzed locally)\".","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Step 3: Report","type":"text"}]},{"type":"paragraph","content":[{"text":"Health Report: {project} ({tier} tier, {file_count} files)","type":"text","marks":[{"type":"strong"}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"[PASS] Passing checks (table, max 5 rows)","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Finding format","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"- [severity] \u003csymptom> ({file}:{line} if known)\n Why: \u003cone-line reason>\n Action: \u003cexact command or edit to fix>","type":"text"}]},{"type":"paragraph","content":[{"text":"Action:","type":"text","marks":[{"type":"code_inline"}]},{"text":" must be copy-pasteable. Never write \"investigate X\" or \"consider Y\". If the fix is unknown, name the diagnostic command.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"[!] Critical -- fix now","type":"text"}]},{"type":"paragraph","content":[{"text":"Rules violated, dangerous allowedTools, MCP overhead >12.5%, security findings, leaked credentials.","type":"text"}]},{"type":"paragraph","content":[{"text":"Example:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"[!] ","type":"text"},{"text":"settings.local.json","type":"text","marks":[{"type":"code_inline"}]},{"text":" committed to git (exposes MCP tokens) Why: leaked token enables remote code execution via installed MCP servers Action: ","type":"text"},{"text":"git rm --cached .claude/settings.local.json && echo '.claude/settings.local.json' >> .gitignore","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"[~] Structural -- fix soon","type":"text"}]},{"type":"paragraph","content":[{"text":"Agent instructions in the wrong layer, missing hooks, oversized descriptions, verifier gaps.","type":"text"}]},{"type":"paragraph","content":[{"text":"Codex/Claude instruction drift.","type":"text","marks":[{"type":"strong"}]},{"text":" Use ","type":"text"},{"text":"AGENT CONFIG SUMMARY","type":"text","marks":[{"type":"code_inline"}]},{"text":" first. Report a Structural finding when ","type":"text"},{"text":"AGENTS.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" and runtime-specific files both contain substantial guidance without delegation, when Codex ","type":"text"},{"text":"config.toml","type":"text","marks":[{"type":"code_inline"}]},{"text":" lacks trust for the current project, when project agent instructions are missing, or when runtime-specific instructions contradict the shared project source of truth. Also report when important rules live only in ignored or private local instruction overlays but the tracked/public docs lack them; those overlays are private context, not durable project source of truth. Do not print raw config values. Secrets, tokens, keys, and passwords must appear only as ","type":"text"},{"text":"[REDACTED]","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]},{"type":"paragraph","content":[{"text":"Quick check from the project root:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"bash skills/health/scripts/check-agent-context.sh . summary","type":"text"}]},{"type":"paragraph","content":[{"text":"AI-maintainability gaps.","type":"text","marks":[{"type":"strong"}]},{"text":" Use ","type":"text"},{"text":"AI MAINTAINABILITY SUMMARY","type":"text","marks":[{"type":"code_inline"}]},{"text":" in summary mode and ","type":"text"},{"text":"AI MAINTAINABILITY DETAIL","type":"text","marks":[{"type":"code_inline"}]},{"text":" in deep mode. Report ","type":"text"},{"text":"FAIL","type":"text","marks":[{"type":"code_inline"}]},{"text":" when the project has no executable verification command, no agent instruction surface for a non-trivial repo, or broken doc references. Report ","type":"text"},{"text":"WARN","type":"text","marks":[{"type":"code_inline"}]},{"text":" when instructions exist but lack a project map, verification guidance, boundary/non-goal language, when TODO/HACK markers are concentrated, when large source hotspots lack ownership/boundary and verification guidance, or when durable docs contain raw one-off review reports, scorecards, dated line references, or diagnostic dumps instead of stable invariants. Treat missing ","type":"text"},{"text":"docs/","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"specs/","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":".specify/","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"HANDOFF.md","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"CHANGELOG","type":"text","marks":[{"type":"code_inline"}]},{"text":", issue templates, and PR templates as informational unless project complexity makes them necessary for handoff. The action for stale reports is to extract stable rules into public instructions, rules, references, or verifier scripts, then remove or archive the transient report.","type":"text"}]},{"type":"paragraph","content":[{"text":"Hotspot ownership gaps.","type":"text","marks":[{"type":"strong"}]},{"text":" In deep mode, read ","type":"text"},{"text":"HOTSPOT OWNERSHIP SURFACE","type":"text","marks":[{"type":"code_inline"}]},{"text":". If a largest source file exceeds the hotspot threshold and ","type":"text"},{"text":"AGENTS.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" / ","type":"text"},{"text":"CLAUDE.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" / shared instruction files do not name who owns the hotspot, what boundary should stay stable, and which verification command covers it, report a Structural ","type":"text"},{"text":"WARN","type":"text","marks":[{"type":"code_inline"}]},{"text":". Do not treat documented large files as code rot by size alone; some modules are intentionally large.","type":"text"}]},{"type":"paragraph","content":[{"text":"Missing stable verifier wrapper.","type":"text","marks":[{"type":"strong"}]},{"text":" If the repo exposes multiple verification commands through CI, scripts, or manifests but ","type":"text"},{"text":"Makefile","type":"text","marks":[{"type":"code_inline"}]},{"text":" has no ","type":"text"},{"text":"check","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"test","type":"text","marks":[{"type":"code_inline"}]},{"text":", or ","type":"text"},{"text":"verify","type":"text","marks":[{"type":"code_inline"}]},{"text":" target, report a Structural ","type":"text"},{"text":"WARN","type":"text","marks":[{"type":"code_inline"}]},{"text":". This is an AI-maintainability gap because agents need one stable default entrypoint, not because the project is broken.","type":"text"}]},{"type":"paragraph","content":[{"text":"Quick check from the project root:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"bash skills/health/scripts/check-maintainability.sh . summary","type":"text"}]},{"type":"paragraph","content":[{"text":"For deep audits:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"bash skills/health/scripts/check-maintainability.sh . deep","type":"text"}]},{"type":"paragraph","content":[{"text":"Keep actions concrete and non-invasive: add or fix the smallest useful instruction surface, add one executable validation command, document hotspot ownership and tests, split only when the boundary is already clear, or repair the broken reference. Do not propose broad rewrites from the script output alone.","type":"text"}]},{"type":"paragraph","content":[{"text":"Broken doc references.","type":"text","marks":[{"type":"strong"}]},{"text":" Scan ","type":"text"},{"text":"AGENTS.md","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"CLAUDE.md","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":".claude/rules/*.md","type":"text","marks":[{"type":"code_inline"}]},{"text":", and every ","type":"text"},{"text":".claude/skills/*/SKILL.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" for references shaped like ","type":"text"},{"text":"@\u003cpath>","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"~/.claude/rules/\u003cname>.md","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"~/.claude/skills/\u003cname>/","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"docs/\u003cname>.md","type":"text","marks":[{"type":"code_inline"}]},{"text":", or ","type":"text"},{"text":"references/\u003cname>.md","type":"text","marks":[{"type":"code_inline"}]},{"text":". For each match, check that the target exists on disk. Report every \"referenced but missing\" pointer with the source file and line.","type":"text"}]},{"type":"paragraph","content":[{"text":"Common offenders:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"A project-level rule references a global rule file that was never created (e.g. ","type":"text"},{"text":"~/.claude/rules/swift.md","type":"text","marks":[{"type":"code_inline"}]},{"text":").","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"A ","type":"text"},{"text":"CLAUDE.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" uses an ","type":"text"},{"text":"@AGENTS.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" placeholder but the actual ","type":"text"},{"text":"AGENTS.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" is missing or empty.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"A skill body references ","type":"text"},{"text":"references/\u003cname>.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" but only ","type":"text"},{"text":"references/\u003cname>-v2.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" exists.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"A rule file references a deleted skill path.","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Quick check from the project root:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"bash skills/health/scripts/check-doc-refs.sh .","type":"text"}]},{"type":"paragraph","content":[{"text":"The checker resolves ","type":"text"},{"text":"@...","type":"text","marks":[{"type":"code_inline"}]},{"text":" and ","type":"text"},{"text":"docs/...","type":"text","marks":[{"type":"code_inline"}]},{"text":" from the project root, expands ","type":"text"},{"text":"~","type":"text","marks":[{"type":"code_inline"}]},{"text":", resolves ","type":"text"},{"text":"references/...","type":"text","marks":[{"type":"code_inline"}]},{"text":" from each ","type":"text"},{"text":".claude/skills/\u003cname>/SKILL.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" directory, checks every reference on a line, skips fenced code examples, and exits non-zero when any target is missing.","type":"text"}]},{"type":"paragraph","content":[{"text":"Report missing references as Structural findings, not Critical, unless the missing file is named as a hard dependency (e.g. ","type":"text"},{"text":"release.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" for the project's release skill).","type":"text"}]},{"type":"paragraph","content":[{"text":"Broken Markdown references.","type":"text","marks":[{"type":"strong"}]},{"text":" In deep mode, ","type":"text"},{"text":"check-maintainability.sh","type":"text","marks":[{"type":"code_inline"}]},{"text":" also scans repository Markdown links. Report these as Structural findings when they point to missing local files, especially design, security, release, or handoff docs that agents may follow during future work.","type":"text"}]},{"type":"paragraph","content":[{"text":"Stale verifier cache output.","type":"text","marks":[{"type":"strong"}]},{"text":" If validation output points at a deleted temp worktree or non-existent ","type":"text"},{"text":"/tmp","type":"text","marks":[{"type":"code_inline"}]},{"text":" / ","type":"text"},{"text":"/private/tmp","type":"text","marks":[{"type":"code_inline"}]},{"text":" file, parse the captured log with:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"bash skills/health/scripts/check-verifier-output.sh . \u003clog-file>","type":"text"}]},{"type":"paragraph","content":[{"text":"Only use this script for existing command output supplied by the user or generated during the current audit. Do not run project tests just to feed this checker. Known actions include ","type":"text"},{"text":"golangci-lint cache clean","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"go clean -cache -testcache","type":"text","marks":[{"type":"code_inline"}]},{"text":", and ","type":"text"},{"text":"npm cache verify","type":"text","marks":[{"type":"code_inline"}]},{"text":"; unknown tools get a diagnostic rerun action.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"[-] Incremental -- nice to have","type":"text"}]},{"type":"paragraph","content":[{"text":"Outdated items, global vs local placement, context hygiene, stale allowedTools entries.","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"paragraph","content":[{"text":"If no issues: ","type":"text"},{"text":"All relevant checks passed. Nothing to fix.","type":"text","marks":[{"type":"code_inline"}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Non-goals","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Never auto-apply fixes without confirmation.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Never apply complex-tier checks to simple projects.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Never act as a heavy lint, typecheck, duplication, or architecture-rewrite substitute; ","type":"text"},{"text":"/health","type":"text","marks":[{"type":"code_inline"}]},{"text":" reports maintainability guardrails and concrete next actions only.","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Gotchas","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"What happened","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Rule","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Missed the local override","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Always read ","type":"text"},{"text":"settings.local.json","type":"text","marks":[{"type":"code_inline"}]},{"text":" too; it shadows the committed file","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Subagent timeout reported as MCP failure","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"MCP failures come from the live probe, not data collection","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Reported issues in wrong language","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Honor CLAUDE.md Communication rule first","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Flagged intentionally noisy hook as broken","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Ask before calling a hook \"broken\"","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Hook seemed not to fire, but it did -- a later UI element rendered above it","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Hook firing order is not visual order. Before re-editing the hook config: (a) confirm with ","type":"text"},{"text":"--debug","type":"text","marks":[{"type":"code_inline"}]},{"text":" or by piping output, (b) check whether a diff dialog, permission prompt, or other UI element rendered on top and pushed the hook output offscreen, (c) only then suspect the hook itself.","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"/health","type":"text","marks":[{"type":"code_inline"}]},{"text":" burned too much quota on first run","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Stay in summary mode first. Full conversation extracts and inspector subagents are deep-audit tools, not the default path for Standard projects.","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Treated missing specs/docs as a failure","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Decision artifacts are optional by default. Escalate missing docs/specs only when the tier, active handoff risk, or user request makes them necessary.","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Treated an ignored AGENTS/CLAUDE file as durable project truth","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Report whether the rule is tracked and distributed. Local overlays can inform the audit, but durable fixes belong in public repo docs or shipped skill/rule files.","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Treated a review scorecard as maintainability documentation","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Scorecards are snapshots. Extract the invariant and verification path, then remove or archive the report instead of calling the score itself a durable rule.","type":"text"}]}]}]}]},{"type":"hr","attrs":{"markup":"---"}}]},"metadata":{"date":"2026-06-05","name":"health","author":"@skillopedia","source":{"stars":273,"repo_name":"skills","origin_url":"https://github.com/ninehills/skills/blob/HEAD/health/SKILL.md","repo_owner":"ninehills","body_sha256":"444b045be6329d23a55dcaf112f77c7400a1c4de5ed26b33743b9b92ca7ac0be","cluster_key":"b1fff23214a8d8b6f5bfc71cf1109f679d5e3b9cea25ba430fc8463e116d0fda","clean_bundle":{"format":"clean-skill-bundle-v1","source":"ninehills/skills/health/SKILL.md","attachments":[{"id":"9b676c0a-79a1-56ff-92ec-78cf5df64ade","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/9b676c0a-79a1-56ff-92ec-78cf5df64ade/attachment.md","path":"agents/inspector-context.md","size":8226,"sha256":"a209f3db760ff9973353f8c4f6d70cebda94c400804c7be7e4a61383f0744f00","contentType":"text/markdown; charset=utf-8"},{"id":"c3af2ac8-6af0-5bcf-a6f1-fe430e6450c0","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/c3af2ac8-6af0-5bcf-a6f1-fe430e6450c0/attachment.md","path":"agents/inspector-control.md","size":5568,"sha256":"f8d3cca0add176323f0a7d233139b4838fc47802406a9d48459e4ee84caf7ab4","contentType":"text/markdown; charset=utf-8"},{"id":"45a647b0-754c-51f1-a99d-bf324d28621b","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/45a647b0-754c-51f1-a99d-bf324d28621b/attachment.md","path":"agents/inspector-maintainability.md","size":2844,"sha256":"c5342e85d0c3db762f23c01ca125f6aa6249e0008a548338ed5b5c0fc24fcc11","contentType":"text/markdown; charset=utf-8"},{"id":"79886aa9-d9cb-521f-a6ee-c93d2639dbc2","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/79886aa9-d9cb-521f-a6ee-c93d2639dbc2/attachment.sh","path":"scripts/check-agent-context.sh","size":153,"sha256":"18a7f26c11c0bcf020b50e7f40baf6fd6f558bc7a4a817fbb3582cbfcdb0f3d6","contentType":"application/x-sh; charset=utf-8"},{"id":"3ff4b609-21ac-57a1-8258-ff7e247922f0","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/3ff4b609-21ac-57a1-8258-ff7e247922f0/attachment.sh","path":"scripts/check-doc-refs.sh","size":198,"sha256":"142466ef8b35f3f3527ecb4dca467eb2175efb4fa4bb1ffbb36726b3c8ace205","contentType":"application/x-sh; charset=utf-8"},{"id":"30b9b820-6366-55f1-8be8-dd9a6718d680","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/30b9b820-6366-55f1-8be8-dd9a6718d680/attachment.sh","path":"scripts/check-maintainability.sh","size":378,"sha256":"2f318cd7159c0cbea74283c673a1542568c54c054848ec54496445bc37cd4ab1","contentType":"application/x-sh; charset=utf-8"},{"id":"f4bb3542-b398-5518-bfa1-e326ddd04b9f","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/f4bb3542-b398-5518-bfa1-e326ddd04b9f/attachment.sh","path":"scripts/check-verifier-output.sh","size":155,"sha256":"d6ad40b8c304a9203c48a68ad9a104a086e5824b2a45cf6edce64fe991961676","contentType":"application/x-sh; charset=utf-8"},{"id":"943092bd-1763-5bfb-8a18-6e4793c85ee7","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/943092bd-1763-5bfb-8a18-6e4793c85ee7/attachment.py","path":"scripts/check_agent_context.py","size":10442,"sha256":"db20533d015444ee2eed686aafe07322bfe1a65fbb2d0c09e83d58fe63e42d5f","contentType":"text/x-python; charset=utf-8"},{"id":"1ed2dd85-99e5-5204-b4dd-23c2fdc218d4","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/1ed2dd85-99e5-5204-b4dd-23c2fdc218d4/attachment.py","path":"scripts/check_doc_refs.py","size":3346,"sha256":"0b7eda43e7955fcd0da96ba255e9a60bcb5bffb0fd93193873d92cfc20df3c73","contentType":"text/x-python; charset=utf-8"},{"id":"73b48d0b-10e0-56ff-a236-3f39daa60e08","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/73b48d0b-10e0-56ff-a236-3f39daa60e08/attachment.py","path":"scripts/check_maintainability.py","size":24336,"sha256":"5b0477c20a6564dffbc8ea6af7d8665779d7110d7e5d63801b3189e74169fb74","contentType":"text/x-python; charset=utf-8"},{"id":"b913c743-654e-56e9-8291-684662c12adc","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/b913c743-654e-56e9-8291-684662c12adc/attachment.py","path":"scripts/check_verifier_output.py","size":3561,"sha256":"15b7be020d913b2a59805e7af8bad5674f53f69a4c3bf96d817fcf0e9d4c07bb","contentType":"text/x-python; charset=utf-8"},{"id":"13af172b-d2b7-5f2a-9d40-8a2108ffce33","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/13af172b-d2b7-5f2a-9d40-8a2108ffce33/attachment.sh","path":"scripts/collect-data.sh","size":22778,"sha256":"d612189779f07fa8395557463edd2bd3375788af5d1dd2daf25394344cad56e8","contentType":"application/x-sh; charset=utf-8"}],"bundle_sha256":"142f7fe3a3aced67f7d918ea839ccdd44e62de3f0214a56ea93dc88bddc1b5a6","attachment_count":12,"text_attachments":12,"attachment_storage":"skillopedia-attachments-v1","binary_attachments":0,"excluded_attachments":[]},"cluster_size":1,"skill_md_path":"health/SKILL.md","import_metadata":{"date":"2026-06-05","author":"@skillopedia","version":"v1","category":"security","category_label":"Security"},"exact_dupes_collapsed_into_this":0},"version":"v1","category":"security","import_tag":"clean-skills-v1","description":"Runs a budget-aware Agent Health audit for Codex, Claude Code, agent instructions, verifier surfaces, and AI maintainability when agents ignore instructions, hooks/MCP fail, validation is missing, or AI-written code is hard to maintain. Flags issues by severity. Not for debugging code or reviewing PRs.","when_to_use":"检查claude, 检查codex, Codex 配置, AGENTS.md, config.toml, agent instructions, 健康度, 配置检查, 配置对不对, AI coding 腐化, 代码变烂, 维护性, 上下文混乱, 验证缺失, 验证命令失真, Claude ignoring instructions, check config, settings not working, audit config","dispatch_intent":"Codex/Claude ignoring instructions, agent config audit, hooks/MCP broken, health token usage, AI coding code rot, hotspot ownership, unclear context, missing verification, stale verifier output"}},"renderedAt":1782981527287}

Health: Agent Config and AI Maintainability Prefix your first line with 🥷 inline, not as its own paragraph. Audit the current project's agent setup and AI coding maintainability against this framework: Find violations. Identify the misaligned layer. Calibrate to project complexity only. Output language: Check in order: (1) project agent instructions ( before runtime-specific files); (2) global agent instructions; (3) user's recent language; (4) English. Budget posture: Start with the summary audit. Escalate automatically when the user asks for a deep, full, complete, thorough, "深入", "完整", "彻…