flonat-research 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (285) hide show
  1. package/.claude/agents/domain-reviewer.md +336 -0
  2. package/.claude/agents/fixer.md +226 -0
  3. package/.claude/agents/paper-critic.md +370 -0
  4. package/.claude/agents/peer-reviewer.md +289 -0
  5. package/.claude/agents/proposal-reviewer.md +215 -0
  6. package/.claude/agents/referee2-reviewer.md +367 -0
  7. package/.claude/agents/references/journal-referee-profiles.md +354 -0
  8. package/.claude/agents/references/paper-critic/council-personas.md +77 -0
  9. package/.claude/agents/references/paper-critic/council-prompts.md +198 -0
  10. package/.claude/agents/references/peer-reviewer/report-template.md +199 -0
  11. package/.claude/agents/references/peer-reviewer/sa-prompts.md +260 -0
  12. package/.claude/agents/references/peer-reviewer/security-scan.md +188 -0
  13. package/.claude/agents/references/proposal-reviewer/report-template.md +144 -0
  14. package/.claude/agents/references/proposal-reviewer/sa-prompts.md +149 -0
  15. package/.claude/agents/references/referee-config.md +114 -0
  16. package/.claude/agents/references/referee2-reviewer/audit-checklists.md +287 -0
  17. package/.claude/agents/references/referee2-reviewer/report-template.md +334 -0
  18. package/.claude/rules/design-before-results.md +52 -0
  19. package/.claude/rules/ignore-agents-md.md +17 -0
  20. package/.claude/rules/ignore-gemini-md.md +17 -0
  21. package/.claude/rules/lean-claude-md.md +45 -0
  22. package/.claude/rules/learn-tags.md +99 -0
  23. package/.claude/rules/overleaf-separation.md +67 -0
  24. package/.claude/rules/plan-first.md +175 -0
  25. package/.claude/rules/read-docs-first.md +50 -0
  26. package/.claude/rules/scope-discipline.md +28 -0
  27. package/.claude/settings.json +125 -0
  28. package/.context/current-focus.md +33 -0
  29. package/.context/preferences/priorities.md +36 -0
  30. package/.context/preferences/task-naming.md +28 -0
  31. package/.context/profile.md +29 -0
  32. package/.context/projects/_index.md +41 -0
  33. package/.context/projects/papers/nudge-exp.md +22 -0
  34. package/.context/projects/papers/uncertainty.md +31 -0
  35. package/.context/resources/claude-scientific-writer-review.md +48 -0
  36. package/.context/resources/cunningham-multi-analyst-agents.md +104 -0
  37. package/.context/resources/cunningham-multilang-code-audit.md +62 -0
  38. package/.context/resources/google-ai-co-scientist-review.md +72 -0
  39. package/.context/resources/karpathy-llm-council-review.md +58 -0
  40. package/.context/resources/multi-coder-reliability-protocol.md +175 -0
  41. package/.context/resources/pedro-santanna-takeaways.md +96 -0
  42. package/.context/resources/venue-rankings/abs_ajg_2024.csv +1823 -0
  43. package/.context/resources/venue-rankings/abs_ajg_2024_econ.csv +356 -0
  44. package/.context/resources/venue-rankings/cabs_4_4star_theory.csv +40 -0
  45. package/.context/resources/venue-rankings/core_2026.csv +801 -0
  46. package/.context/resources/venue-rankings.md +147 -0
  47. package/.context/workflows/README.md +69 -0
  48. package/.context/workflows/daily-review.md +91 -0
  49. package/.context/workflows/meeting-actions.md +108 -0
  50. package/.context/workflows/replication-protocol.md +155 -0
  51. package/.context/workflows/weekly-review.md +113 -0
  52. package/.mcp-server-biblio/formatters.py +158 -0
  53. package/.mcp-server-biblio/pyproject.toml +11 -0
  54. package/.mcp-server-biblio/server.py +678 -0
  55. package/.mcp-server-biblio/sources/__init__.py +14 -0
  56. package/.mcp-server-biblio/sources/base.py +73 -0
  57. package/.mcp-server-biblio/sources/formatters.py +83 -0
  58. package/.mcp-server-biblio/sources/models.py +22 -0
  59. package/.mcp-server-biblio/sources/multi_source.py +243 -0
  60. package/.mcp-server-biblio/sources/openalex_source.py +183 -0
  61. package/.mcp-server-biblio/sources/scopus_source.py +309 -0
  62. package/.mcp-server-biblio/sources/wos_source.py +508 -0
  63. package/.mcp-server-biblio/uv.lock +896 -0
  64. package/.scripts/README.md +161 -0
  65. package/.scripts/ai_pattern_density.py +446 -0
  66. package/.scripts/conf +445 -0
  67. package/.scripts/config.py +122 -0
  68. package/.scripts/count_inventory.py +275 -0
  69. package/.scripts/daily_digest.py +288 -0
  70. package/.scripts/done +177 -0
  71. package/.scripts/extract_meeting_actions.py +223 -0
  72. package/.scripts/focus +176 -0
  73. package/.scripts/generate-codex-agents-md.py +217 -0
  74. package/.scripts/inbox +194 -0
  75. package/.scripts/notion_helpers.py +325 -0
  76. package/.scripts/openalex/query_helpers.py +306 -0
  77. package/.scripts/papers +227 -0
  78. package/.scripts/query +223 -0
  79. package/.scripts/session-history.py +201 -0
  80. package/.scripts/skill-health.py +516 -0
  81. package/.scripts/skill-log-miner.py +273 -0
  82. package/.scripts/sync-to-codex.sh +252 -0
  83. package/.scripts/task +213 -0
  84. package/.scripts/tasks +190 -0
  85. package/.scripts/week +206 -0
  86. package/CLAUDE.md +197 -0
  87. package/LICENSE +21 -0
  88. package/MEMORY.md +38 -0
  89. package/README.md +269 -0
  90. package/docs/agents.md +44 -0
  91. package/docs/bibliography-setup.md +55 -0
  92. package/docs/council-mode.md +36 -0
  93. package/docs/getting-started.md +245 -0
  94. package/docs/hooks.md +38 -0
  95. package/docs/mcp-servers.md +82 -0
  96. package/docs/notion-setup.md +109 -0
  97. package/docs/rules.md +33 -0
  98. package/docs/scripts.md +303 -0
  99. package/docs/setup-overview/setup-overview.pdf +0 -0
  100. package/docs/skills.md +70 -0
  101. package/docs/system.md +159 -0
  102. package/hooks/block-destructive-git.sh +66 -0
  103. package/hooks/context-monitor.py +114 -0
  104. package/hooks/postcompact-restore.py +157 -0
  105. package/hooks/precompact-autosave.py +181 -0
  106. package/hooks/promise-checker.sh +124 -0
  107. package/hooks/protect-source-files.sh +81 -0
  108. package/hooks/resume-context-loader.sh +53 -0
  109. package/hooks/startup-context-loader.sh +102 -0
  110. package/package.json +51 -0
  111. package/packages/cli-council/.github/workflows/claude-code-review.yml +44 -0
  112. package/packages/cli-council/.github/workflows/claude.yml +50 -0
  113. package/packages/cli-council/README.md +100 -0
  114. package/packages/cli-council/pyproject.toml +43 -0
  115. package/packages/cli-council/src/cli_council/__init__.py +19 -0
  116. package/packages/cli-council/src/cli_council/__main__.py +185 -0
  117. package/packages/cli-council/src/cli_council/backends/__init__.py +8 -0
  118. package/packages/cli-council/src/cli_council/backends/base.py +81 -0
  119. package/packages/cli-council/src/cli_council/backends/claude.py +25 -0
  120. package/packages/cli-council/src/cli_council/backends/codex.py +27 -0
  121. package/packages/cli-council/src/cli_council/backends/gemini.py +26 -0
  122. package/packages/cli-council/src/cli_council/checkpoint.py +212 -0
  123. package/packages/cli-council/src/cli_council/config.py +51 -0
  124. package/packages/cli-council/src/cli_council/council.py +391 -0
  125. package/packages/cli-council/src/cli_council/models.py +46 -0
  126. package/packages/llm-council/.github/workflows/claude-code-review.yml +44 -0
  127. package/packages/llm-council/.github/workflows/claude.yml +50 -0
  128. package/packages/llm-council/README.md +453 -0
  129. package/packages/llm-council/pyproject.toml +42 -0
  130. package/packages/llm-council/src/llm_council/__init__.py +23 -0
  131. package/packages/llm-council/src/llm_council/__main__.py +259 -0
  132. package/packages/llm-council/src/llm_council/checkpoint.py +193 -0
  133. package/packages/llm-council/src/llm_council/client.py +253 -0
  134. package/packages/llm-council/src/llm_council/config.py +232 -0
  135. package/packages/llm-council/src/llm_council/council.py +482 -0
  136. package/packages/llm-council/src/llm_council/models.py +46 -0
  137. package/packages/mcp-bibliography/MEMORY.md +31 -0
  138. package/packages/mcp-bibliography/_app.py +226 -0
  139. package/packages/mcp-bibliography/formatters.py +158 -0
  140. package/packages/mcp-bibliography/log/2026-03-13-2100.md +35 -0
  141. package/packages/mcp-bibliography/pyproject.toml +15 -0
  142. package/packages/mcp-bibliography/run.sh +20 -0
  143. package/packages/mcp-bibliography/scholarly_formatters.py +83 -0
  144. package/packages/mcp-bibliography/server.py +1857 -0
  145. package/packages/mcp-bibliography/tools/__init__.py +28 -0
  146. package/packages/mcp-bibliography/tools/_registry.py +19 -0
  147. package/packages/mcp-bibliography/tools/altmetric.py +107 -0
  148. package/packages/mcp-bibliography/tools/core.py +92 -0
  149. package/packages/mcp-bibliography/tools/dblp.py +52 -0
  150. package/packages/mcp-bibliography/tools/openalex.py +296 -0
  151. package/packages/mcp-bibliography/tools/opencitations.py +102 -0
  152. package/packages/mcp-bibliography/tools/openreview.py +179 -0
  153. package/packages/mcp-bibliography/tools/orcid.py +131 -0
  154. package/packages/mcp-bibliography/tools/scholarly.py +575 -0
  155. package/packages/mcp-bibliography/tools/unpaywall.py +63 -0
  156. package/packages/mcp-bibliography/tools/zenodo.py +123 -0
  157. package/packages/mcp-bibliography/uv.lock +711 -0
  158. package/scripts/setup.sh +143 -0
  159. package/skills/beamer-deck/SKILL.md +199 -0
  160. package/skills/beamer-deck/references/quality-rubric.md +54 -0
  161. package/skills/beamer-deck/references/review-prompts.md +106 -0
  162. package/skills/bib-validate/SKILL.md +261 -0
  163. package/skills/bib-validate/references/council-mode.md +34 -0
  164. package/skills/bib-validate/references/deep-verify.md +79 -0
  165. package/skills/bib-validate/references/fix-mode.md +36 -0
  166. package/skills/bib-validate/references/openalex-verification.md +45 -0
  167. package/skills/bib-validate/references/preprint-check.md +31 -0
  168. package/skills/bib-validate/references/ref-manager-crossref.md +41 -0
  169. package/skills/bib-validate/references/report-template.md +82 -0
  170. package/skills/code-archaeology/SKILL.md +141 -0
  171. package/skills/code-review/SKILL.md +265 -0
  172. package/skills/code-review/references/quality-rubric.md +67 -0
  173. package/skills/consolidate-memory/SKILL.md +208 -0
  174. package/skills/context-status/SKILL.md +126 -0
  175. package/skills/creation-guard/SKILL.md +230 -0
  176. package/skills/devils-advocate/SKILL.md +130 -0
  177. package/skills/devils-advocate/references/competing-hypotheses.md +83 -0
  178. package/skills/init-project/SKILL.md +115 -0
  179. package/skills/init-project-course/references/memory-and-settings.md +92 -0
  180. package/skills/init-project-course/references/organise-templates.md +94 -0
  181. package/skills/init-project-course/skill.md +147 -0
  182. package/skills/init-project-light/skill.md +139 -0
  183. package/skills/init-project-research/SKILL.md +368 -0
  184. package/skills/init-project-research/references/atlas-pipeline-sync.md +70 -0
  185. package/skills/init-project-research/references/atlas-schema.md +81 -0
  186. package/skills/init-project-research/references/confirmation-report.md +39 -0
  187. package/skills/init-project-research/references/domain-profile-template.md +104 -0
  188. package/skills/init-project-research/references/interview-round3.md +34 -0
  189. package/skills/init-project-research/references/literature-discovery.md +43 -0
  190. package/skills/init-project-research/references/scaffold-details.md +197 -0
  191. package/skills/init-project-research/templates/field-calibration.md +60 -0
  192. package/skills/init-project-research/templates/pipeline-manifest.md +63 -0
  193. package/skills/init-project-research/templates/run-all.sh +116 -0
  194. package/skills/init-project-research/templates/seed-files.md +337 -0
  195. package/skills/insights-deck/SKILL.md +151 -0
  196. package/skills/interview-me/SKILL.md +157 -0
  197. package/skills/latex/SKILL.md +141 -0
  198. package/skills/latex/references/latex-configs.md +183 -0
  199. package/skills/latex-autofix/SKILL.md +230 -0
  200. package/skills/latex-autofix/references/known-errors.md +183 -0
  201. package/skills/latex-autofix/references/quality-rubric.md +50 -0
  202. package/skills/latex-health-check/SKILL.md +161 -0
  203. package/skills/learn/SKILL.md +220 -0
  204. package/skills/learn/scripts/validate_skill.py +265 -0
  205. package/skills/lessons-learned/SKILL.md +201 -0
  206. package/skills/literature/SKILL.md +335 -0
  207. package/skills/literature/references/agent-templates.md +393 -0
  208. package/skills/literature/references/bibliometric-apis.md +44 -0
  209. package/skills/literature/references/cli-council-search.md +79 -0
  210. package/skills/literature/references/openalex-api-guide.md +371 -0
  211. package/skills/literature/references/openalex-common-queries.md +381 -0
  212. package/skills/literature/references/openalex-workflows.md +248 -0
  213. package/skills/literature/references/reference-manager-sync.md +36 -0
  214. package/skills/literature/references/scopus-api-guide.md +208 -0
  215. package/skills/literature/references/wos-api-guide.md +308 -0
  216. package/skills/multi-perspective/SKILL.md +311 -0
  217. package/skills/multi-perspective/references/computational-many-analysts.md +77 -0
  218. package/skills/pipeline-manifest/SKILL.md +226 -0
  219. package/skills/pre-submission-report/SKILL.md +153 -0
  220. package/skills/process-reviews/SKILL.md +244 -0
  221. package/skills/process-reviews/references/rr-routing.md +101 -0
  222. package/skills/project-deck/SKILL.md +87 -0
  223. package/skills/project-safety/SKILL.md +135 -0
  224. package/skills/proofread/SKILL.md +254 -0
  225. package/skills/proofread/references/quality-rubric.md +104 -0
  226. package/skills/python-env/SKILL.md +57 -0
  227. package/skills/quarto-deck/SKILL.md +226 -0
  228. package/skills/quarto-deck/references/markdown-format.md +143 -0
  229. package/skills/quarto-deck/references/quality-rubric.md +54 -0
  230. package/skills/save-context/SKILL.md +174 -0
  231. package/skills/session-log/SKILL.md +98 -0
  232. package/skills/shared/concept-validation-gate.md +161 -0
  233. package/skills/shared/council-protocol.md +265 -0
  234. package/skills/shared/distribution-diagnostics.md +164 -0
  235. package/skills/shared/engagement-stratified-sampling.md +218 -0
  236. package/skills/shared/escalation-protocol.md +74 -0
  237. package/skills/shared/external-audit-protocol.md +205 -0
  238. package/skills/shared/intercoder-reliability.md +256 -0
  239. package/skills/shared/mcp-degradation.md +81 -0
  240. package/skills/shared/method-probing-questions.md +163 -0
  241. package/skills/shared/multi-language-conventions.md +143 -0
  242. package/skills/shared/paid-api-safety.md +174 -0
  243. package/skills/shared/palettes.md +90 -0
  244. package/skills/shared/progressive-disclosure.md +92 -0
  245. package/skills/shared/project-documentation-content.md +443 -0
  246. package/skills/shared/project-documentation-format.md +281 -0
  247. package/skills/shared/project-documentation.md +100 -0
  248. package/skills/shared/publication-output.md +138 -0
  249. package/skills/shared/quality-scoring.md +70 -0
  250. package/skills/shared/reference-resolution.md +77 -0
  251. package/skills/shared/research-quality-rubric.md +165 -0
  252. package/skills/shared/rhetoric-principles.md +54 -0
  253. package/skills/shared/skill-design-patterns.md +272 -0
  254. package/skills/shared/skill-index.md +240 -0
  255. package/skills/shared/system-documentation.md +334 -0
  256. package/skills/shared/tikz-rules.md +402 -0
  257. package/skills/shared/validation-tiers.md +121 -0
  258. package/skills/shared/venue-guides/README.md +46 -0
  259. package/skills/shared/venue-guides/cell_press_style.md +483 -0
  260. package/skills/shared/venue-guides/conferences_formatting.md +564 -0
  261. package/skills/shared/venue-guides/cs_conference_style.md +463 -0
  262. package/skills/shared/venue-guides/examples/cell_summary_example.md +247 -0
  263. package/skills/shared/venue-guides/examples/medical_structured_abstract.md +313 -0
  264. package/skills/shared/venue-guides/examples/nature_abstract_examples.md +213 -0
  265. package/skills/shared/venue-guides/examples/neurips_introduction_example.md +245 -0
  266. package/skills/shared/venue-guides/journals_formatting.md +486 -0
  267. package/skills/shared/venue-guides/medical_journal_styles.md +535 -0
  268. package/skills/shared/venue-guides/ml_conference_style.md +556 -0
  269. package/skills/shared/venue-guides/nature_science_style.md +405 -0
  270. package/skills/shared/venue-guides/reviewer_expectations.md +417 -0
  271. package/skills/shared/venue-guides/venue_writing_styles.md +321 -0
  272. package/skills/split-pdf/SKILL.md +172 -0
  273. package/skills/split-pdf/methodology.md +48 -0
  274. package/skills/sync-notion/SKILL.md +93 -0
  275. package/skills/system-audit/SKILL.md +157 -0
  276. package/skills/system-audit/references/sub-agent-prompts.md +294 -0
  277. package/skills/task-management/SKILL.md +131 -0
  278. package/skills/update-focus/SKILL.md +204 -0
  279. package/skills/update-project-doc/SKILL.md +194 -0
  280. package/skills/validate-bib/SKILL.md +242 -0
  281. package/skills/validate-bib/references/council-mode.md +34 -0
  282. package/skills/validate-bib/references/deep-verify.md +71 -0
  283. package/skills/validate-bib/references/openalex-verification.md +45 -0
  284. package/skills/validate-bib/references/preprint-check.md +31 -0
  285. package/skills/validate-bib/references/report-template.md +62 -0
@@ -0,0 +1,265 @@
1
+ """Validate a skill directory against conventions.
2
+
3
+ Checks frontmatter, naming, description quality, body length,
4
+ referenced files, and allowed_tools format.
5
+
6
+ Usage:
7
+ uv run python validate_skill.py <skill-directory> [--strict] [--all]
8
+
9
+ Exit codes: 0 = valid, 1 = errors found, 2 = warnings promoted by --strict.
10
+ """
11
+
12
+ import re
13
+ import sys
14
+ from pathlib import Path
15
+
16
+ try:
17
+ import yaml
18
+ except ImportError:
19
+ print("pyyaml not installed. Run: uv pip install pyyaml", file=sys.stderr)
20
+ sys.exit(1)
21
+
22
+ _NAME_PATTERN = re.compile(r"^[a-z0-9]([a-z0-9-]{0,62}[a-z0-9])?$")
23
+ _PLACEHOLDER_PATTERNS = (
24
+ re.compile(r"\bTODO\b", re.IGNORECASE),
25
+ re.compile(r"\bplaceholder\b", re.IGNORECASE),
26
+ re.compile(r"\bFIXME\b", re.IGNORECASE),
27
+ re.compile(r"\bXXX\b"),
28
+ )
29
+ _KNOWN_TOOLS = {
30
+ "Read", "Write", "Edit", "Glob", "Grep", "Bash",
31
+ "AskUserQuestion", "Task", "WebFetch", "WebSearch",
32
+ "NotebookEdit", "EnterPlanMode", "ExitPlanMode", "Skill",
33
+ }
34
+
35
+
36
+ def _split_frontmatter(content: str) -> tuple[str, str]:
37
+ """Split SKILL.md into frontmatter string and body."""
38
+ lines = content.split("\n")
39
+ start = 0
40
+ while start < len(lines) and lines[start].strip() == "":
41
+ start += 1
42
+ if start >= len(lines) or lines[start].strip() != "---":
43
+ return "", ""
44
+ close = None
45
+ for i in range(start + 1, len(lines)):
46
+ if lines[i].strip() == "---":
47
+ close = i
48
+ break
49
+ if close is None:
50
+ return "", ""
51
+ frontmatter_str = "\n".join(lines[start + 1 : close])
52
+ body = "\n".join(lines[close + 1 :]).strip()
53
+ return frontmatter_str, body
54
+
55
+
56
+ def _parse_yaml(frontmatter_str: str) -> dict | None:
57
+ """Parse YAML frontmatter."""
58
+ try:
59
+ data = yaml.safe_load(frontmatter_str)
60
+ return data if isinstance(data, dict) else None
61
+ except yaml.YAMLError:
62
+ return None
63
+
64
+
65
+ def _has_placeholder(text: str) -> bool:
66
+ return any(p.search(text) for p in _PLACEHOLDER_PATTERNS)
67
+
68
+
69
+ def _count_body_lines(body: str) -> int:
70
+ return len([line for line in body.split("\n") if line.strip()])
71
+
72
+
73
+ def validate_skill(path: Path, strict: bool = False) -> tuple[bool, list[str], list[str]]:
74
+ """Validate a skill directory.
75
+
76
+ Returns (is_valid, errors, warnings).
77
+ """
78
+ errors: list[str] = []
79
+ warnings: list[str] = []
80
+ skill_dir = Path(path)
81
+
82
+ # --- SKILL.md exists ---
83
+ skill_md = skill_dir / "SKILL.md"
84
+ if not skill_md.exists():
85
+ errors.append("SKILL.md not found.")
86
+ return (False, errors, warnings)
87
+
88
+ content = skill_md.read_text()
89
+
90
+ # --- Valid frontmatter ---
91
+ frontmatter_str, body = _split_frontmatter(content)
92
+ if not frontmatter_str:
93
+ errors.append("Missing or invalid YAML frontmatter (needs --- delimiters).")
94
+ return (False, errors, warnings)
95
+
96
+ data = _parse_yaml(frontmatter_str)
97
+ if data is None:
98
+ errors.append("Frontmatter is not valid YAML.")
99
+ return (False, errors, warnings)
100
+
101
+ # --- Body non-empty ---
102
+ if not body:
103
+ errors.append("Body (system prompt) is empty.")
104
+
105
+ # --- Name present and valid ---
106
+ name = data.get("name")
107
+ if not name or not isinstance(name, str):
108
+ errors.append("Required field 'name' is missing.")
109
+ elif not _NAME_PATTERN.match(name):
110
+ errors.append(f"Invalid name '{name}': must be lowercase alphanumeric + hyphens, 1-64 chars.")
111
+ else:
112
+ if name != skill_dir.name:
113
+ errors.append(f"Name '{name}' does not match directory '{skill_dir.name}'.")
114
+
115
+ if isinstance(name, str) and _has_placeholder(name):
116
+ errors.append(f"Name '{name}' contains placeholder text.")
117
+
118
+ # --- Description present and useful ---
119
+ description = data.get("description")
120
+ if not description or not isinstance(description, str):
121
+ errors.append("Required field 'description' is missing.")
122
+ else:
123
+ desc_clean = description.replace("\n", " ").strip()
124
+ if len(desc_clean) > 1024:
125
+ errors.append(f"Description too long ({len(desc_clean)} chars, max 1024).")
126
+ if _has_placeholder(desc_clean):
127
+ errors.append("Description contains placeholder text.")
128
+ if len(desc_clean) < 20:
129
+ warnings.append(f"Description very short ({len(desc_clean)} chars) — may not trigger correctly.")
130
+ if not any(kw in desc_clean.lower() for kw in ("use when", "use for", "use this", "when ")):
131
+ warnings.append("Description lacks activation hint (e.g., 'Use when...'). May not trigger reliably.")
132
+
133
+ # --- Body quality ---
134
+ if body:
135
+ line_count = _count_body_lines(body)
136
+ if line_count < 5:
137
+ warnings.append(f"Body is very short ({line_count} non-empty lines).")
138
+ if line_count > 300:
139
+ warnings.append(f"Body is long ({line_count} lines). Consider moving detail to references/.")
140
+
141
+ # --- allowed_tools / allowed-tools ---
142
+ tools = data.get("allowed_tools") or data.get("allowed-tools")
143
+ if tools and isinstance(tools, list):
144
+ for tool in tools:
145
+ if isinstance(tool, str):
146
+ # Strip Bash(pattern) to just Bash for the check
147
+ base = tool.split("(")[0]
148
+ if base not in _KNOWN_TOOLS:
149
+ warnings.append(f"Unknown tool '{tool}' in allowed_tools.")
150
+
151
+ # --- Referenced files exist ---
152
+ refs_dir = skill_dir / "references"
153
+ scripts_dir = skill_dir / "scripts"
154
+ # Check for broken relative links in body (strip #anchors before checking)
155
+ for match in re.finditer(r'\[.*?\]\(((?!http)[^)]+)\)', body):
156
+ rel_path = match.group(1)
157
+ file_path_str = rel_path.split("#")[0] # strip fragment
158
+ if not file_path_str or file_path_str.startswith("<"): # skip placeholders like <name>.md
159
+ continue
160
+ full_path = skill_dir / file_path_str
161
+ if not full_path.exists():
162
+ errors.append(f"Broken link: '{rel_path}' — file '{file_path_str}' does not exist.")
163
+
164
+ # Check that references/ and scripts/ dirs, if linked to, actually exist
165
+ # Only flag when there's a markdown link pointing into these dirs
166
+ refs_link = re.search(r'\]\(references/', body)
167
+ scripts_link = re.search(r'\]\(scripts/', body)
168
+ if refs_link and not refs_dir.exists():
169
+ warnings.append("Body links to 'references/' but directory does not exist.")
170
+ if scripts_link and not scripts_dir.exists():
171
+ warnings.append("Body links to 'scripts/' but directory does not exist.")
172
+
173
+ # --- Determine validity ---
174
+ if strict:
175
+ is_valid = len(errors) + len(warnings) == 0
176
+ else:
177
+ is_valid = len(errors) == 0
178
+
179
+ return (is_valid, errors, warnings)
180
+
181
+
182
+ def _color(text: str, code: str) -> str:
183
+ return f"\033[{code}m{text}\033[0m"
184
+
185
+
186
+ def print_report(skill_path: Path, errors: list[str], warnings: list[str], strict: bool) -> None:
187
+ print(f"\n Validating: {skill_path.name}")
188
+
189
+ if not errors and not warnings:
190
+ print(f" {_color('PASS', '32')} All checks passed.\n")
191
+ return
192
+
193
+ for err in errors:
194
+ print(f" {_color('ERROR', '31')} {err}")
195
+
196
+ for warn in warnings:
197
+ label = "ERROR" if strict else "WARN "
198
+ color = "31" if strict else "33"
199
+ print(f" {_color(label, color)} {warn}")
200
+
201
+ total = len(errors) + (len(warnings) if strict else 0)
202
+ if total > 0:
203
+ print(f" {_color(f'{total} issue(s)', '31')}\n")
204
+ else:
205
+ print(f" {_color('PASS', '32')} {len(warnings)} warning(s)\n")
206
+
207
+
208
+ def main() -> int:
209
+ import argparse
210
+
211
+ parser = argparse.ArgumentParser(description="Validate skill directories.")
212
+ parser.add_argument("skill_directory", nargs="?", type=Path, help="Path to skill directory")
213
+ parser.add_argument("--strict", action="store_true", help="Promote warnings to errors")
214
+ parser.add_argument("--all", action="store_true", help="Validate all skills in the parent directory")
215
+ args = parser.parse_args()
216
+
217
+ if args.all:
218
+ # Find skills root: if inside a skill dir, go up; otherwise use cwd
219
+ if args.skill_directory:
220
+ skills_root = args.skill_directory.resolve()
221
+ else:
222
+ skills_root = Path.cwd()
223
+
224
+ total_errors = 0
225
+ total_warnings = 0
226
+ total_pass = 0
227
+ total_fail = 0
228
+
229
+ for child in sorted(skills_root.iterdir()):
230
+ if not child.is_dir() or child.name == "shared" or child.name.startswith("."):
231
+ continue
232
+ skill_md = child / "SKILL.md"
233
+ if not skill_md.exists():
234
+ continue
235
+
236
+ is_valid, errors, warnings = validate_skill(child, strict=args.strict)
237
+ print_report(child, errors, warnings, strict=args.strict)
238
+ total_errors += len(errors)
239
+ total_warnings += len(warnings)
240
+ if is_valid:
241
+ total_pass += 1
242
+ else:
243
+ total_fail += 1
244
+
245
+ print(f" Summary: {total_pass} passed, {total_fail} failed, {total_warnings} warnings\n")
246
+ return 1 if total_fail > 0 else 0
247
+
248
+ if not args.skill_directory:
249
+ parser.error("skill_directory is required unless --all is used")
250
+
251
+ skill_path = args.skill_directory.resolve()
252
+ if not skill_path.is_dir():
253
+ print(f"Error: '{skill_path}' is not a directory.", file=sys.stderr)
254
+ return 1
255
+
256
+ is_valid, errors, warnings = validate_skill(skill_path, strict=args.strict)
257
+ print_report(skill_path, errors, warnings, strict=args.strict)
258
+
259
+ if not is_valid:
260
+ return 2 if (not errors and args.strict) else 1
261
+ return 0
262
+
263
+
264
+ if __name__ == "__main__":
265
+ sys.exit(main())
@@ -0,0 +1,201 @@
1
+ ---
2
+ name: lessons-learned
3
+ description: "Use when you need a structured post-mortem after incidents, mistakes, or stuck sessions."
4
+ allowed_tools:
5
+ - Read
6
+ - Write
7
+ - Edit
8
+ - Glob
9
+ - Grep
10
+ - AskUserQuestion
11
+ ---
12
+
13
+ # Lessons Learned: Structured Retrospective
14
+
15
+ Analyse incidents using a structured framework, identify root causes, and encode preventive measures directly into skills, guards, or documentation. The goal is systematic improvement, not blame.
16
+
17
+ ## When to Use
18
+
19
+ - After incidents, mistakes, rollbacks, or near-misses
20
+ - When the user says "what went wrong", "lessons learned", "post-mortem", "retrospective", or "how do we prevent this"
21
+ - After a stuck session where significant time was lost
22
+ - After a wrong-approach event (plan existed but execution diverged)
23
+
24
+ ## Process
25
+
26
+ ### Phase 1: Incident Definition
27
+
28
+ Capture the facts first, analysis later.
29
+
30
+ ```markdown
31
+ ## Incident Summary
32
+
33
+ **What happened:** [Factual description]
34
+ **When:** [Date/time]
35
+ **Impact:** [What was affected, scope]
36
+ **Resolution:** [How it was fixed/rolled back]
37
+ **Time to resolution:** [How long to fix]
38
+ ```
39
+
40
+ ### Phase 2: Timeline Reconstruction
41
+
42
+ Build a chronological sequence of events:
43
+
44
+ | Time | Action | Actor | Outcome |
45
+ |------|--------|-------|---------|
46
+ | HH:MM | [What was done] | [Claude/User] | [Result] |
47
+
48
+ Key questions:
49
+ - What was the trigger?
50
+ - Where did the sequence diverge from expected?
51
+ - What was the point of no return?
52
+
53
+ ### Phase 3: Root Cause Analysis (5 Whys)
54
+
55
+ ```
56
+ 1. Why did [incident] happen?
57
+ → Because [immediate cause]
58
+
59
+ 2. Why did [immediate cause] happen?
60
+ → Because [deeper cause]
61
+
62
+ 3. Why did [deeper cause] happen?
63
+ → Because [systemic issue]
64
+
65
+ 4. Why did [systemic issue] exist?
66
+ → Because [process gap]
67
+
68
+ 5. Why did [process gap] exist?
69
+ → Because [root cause]
70
+ ```
71
+
72
+ Stop when you reach a cause that can be addressed by a concrete change to the system (skill, rule, hook, doc).
73
+
74
+ ### Phase 4: Contributing Factors
75
+
76
+ Identify all factors, not just the root cause:
77
+
78
+ | Category | Factor | Contribution |
79
+ |----------|--------|--------------|
80
+ | **Process** | Missing checkpoint, unclear workflow | [How it contributed] |
81
+ | **Communication** | Ambiguous instructions, assumed consent | [How it contributed] |
82
+ | **Technical** | Missing guard, no validation | [How it contributed] |
83
+ | **Context** | Session continuation, prior assumptions | [How it contributed] |
84
+ | **Human** | Fatigue, time pressure, overconfidence | [How it contributed] |
85
+
86
+ ### Phase 5: Fix Classification
87
+
88
+ Classify each fix by type:
89
+
90
+ | Fix Type | When to Use | How to Encode |
91
+ |----------|-------------|---------------|
92
+ | **Skill** | Recurring workflow needs structure | Create SKILL.md via `/learn` |
93
+ | **Guard** | Action requires mandatory checkpoint | Add approval gate to existing skill |
94
+ | **Rule** | Behavioural constraint needed globally | Create `.claude/rules/*.md` |
95
+ | **Documentation** | Knowledge gap caused the issue | Update CLAUDE.md, MEMORY.md, or docs/ |
96
+ | **Hook** | Manual step was forgotten | Create script in hooks/ |
97
+ | **Checklist** | Multiple steps need verification | Add to existing skill |
98
+
99
+ ### Phase 6: Fix Implementation
100
+
101
+ **Implement fixes during the retrospective, not after.** This is the critical difference from a report-only post-mortem.
102
+
103
+ For each fix:
104
+ 1. Implement it (create/edit the file)
105
+ 2. Record what was done:
106
+
107
+ | Fix | Type | Location | Status |
108
+ |-----|------|----------|--------|
109
+ | [Description] | Skill/Guard/Rule/Doc/Hook | [File path] | Created/Updated |
110
+
111
+ Also record a `[LEARN]` tag in MEMORY.md for each key correction (per the `learn-tags` rule).
112
+
113
+ ### Phase 7: Verification
114
+
115
+ Define how to verify the fix works:
116
+
117
+ ```markdown
118
+ ## Verification
119
+
120
+ **Test scenario:** [How to test the fix]
121
+ **Success criteria:** [What "fixed" looks like]
122
+ **Review date:** [When to check if fix is working — default: 2 weeks]
123
+ ```
124
+
125
+ ## Output
126
+
127
+ Write the report to `log/incidents/YYYY-MM-DD_short-description.md`:
128
+
129
+ ```markdown
130
+ # Lessons Learned: [Incident Title]
131
+
132
+ **Date:** YYYY-MM-DD
133
+ **Severity:** [Low|Medium|High|Critical]
134
+ **Status:** [Resolved|Monitoring|Open]
135
+
136
+ ## Incident Summary
137
+ [Brief description]
138
+
139
+ ## Timeline
140
+ | Time | Action | Actor | Outcome |
141
+ |------|--------|-------|---------|
142
+
143
+ ## Root Cause
144
+ [The fundamental issue]
145
+
146
+ ## Contributing Factors
147
+ - [Factor 1]
148
+ - [Factor 2]
149
+
150
+ ## Fixes Implemented
151
+ | Fix | Type | Location | Status |
152
+ |-----|------|----------|--------|
153
+
154
+ ## Prevention
155
+ [How this prevents recurrence]
156
+
157
+ ## Lessons
158
+ 1. [Key takeaway 1]
159
+ 2. [Key takeaway 2]
160
+ ```
161
+
162
+ Create `log/incidents/` if it doesn't exist.
163
+
164
+ ## Common Incident Patterns
165
+
166
+ | Pattern | Symptom | Root Cause | Typical Fix |
167
+ |---------|---------|------------|-------------|
168
+ | Premature action | Action taken before approval | Implied consent ≠ explicit | Add approval gate to skill |
169
+ | Sequence error | Steps in wrong order | Missing dependency chain | Encode sequence in skill |
170
+ | Missing validation | Bad data passed through | No checkpoint | Add pre-flight check |
171
+ | Context carryover | Stale assumptions from prior session | State assumed to persist | Explicit context verification |
172
+ | Scope creep | Did more than requested | Task scope too broad | Clarifying questions first |
173
+ | Planning loop | Re-planned instead of executing | Perfectionism / uncertainty | Execution stall detector |
174
+
175
+ ## Anti-Patterns
176
+
177
+ | Anti-Pattern | Problem | Instead |
178
+ |--------------|---------|---------|
179
+ | Blame assignment | Creates defensiveness | Focus on process, not people |
180
+ | Single-cause thinking | Oversimplifies | Use 5 Whys, multiple factors |
181
+ | Recommend without acting | Lessons forgotten, recurs | Implement fixes during retro |
182
+ | Vague fixes ("be more careful") | Not verifiable | Encode specific changes |
183
+ | Skip verification | No way to know if fix worked | Define success criteria |
184
+
185
+ ## Cross-References
186
+
187
+ - **`[LEARN]` tags** — record one-liner corrections in MEMORY.md (the quick complement to this skill)
188
+ - **`/learn`** — extract a full skill from a session (when the fix type is "Skill")
189
+ - **`/ideas`** — if a fix is too large for this session, capture as an idea for later
190
+
191
+ ## Success Criteria
192
+
193
+ The retrospective is complete when:
194
+ - [ ] Incident clearly defined with timeline
195
+ - [ ] Root cause identified (not just symptoms)
196
+ - [ ] Contributing factors documented
197
+ - [ ] At least one fix implemented (not just recommended)
198
+ - [ ] Fix encoded in appropriate location (skill, rule, hook, doc)
199
+ - [ ] `[LEARN]` tags recorded in MEMORY.md
200
+ - [ ] Verification criteria defined
201
+ - [ ] Report written to `log/incidents/`