claude-dev-env 1.82.0 → 1.84.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 (217) hide show
  1. package/CLAUDE.md +16 -13
  2. package/_shared/pr-loop/audit-contract.md +24 -12
  3. package/_shared/pr-loop/scripts/CLAUDE.md +1 -0
  4. package/_shared/pr-loop/scripts/README.md +1 -0
  5. package/_shared/pr-loop/scripts/_claude_permissions_common.py +16 -5
  6. package/_shared/pr-loop/scripts/code_rules_gate.py +2 -3
  7. package/_shared/pr-loop/scripts/pr_loop_shared_constants/CLAUDE.md +1 -0
  8. package/_shared/pr-loop/scripts/pr_loop_shared_constants/reviewer_availability_constants.py +12 -0
  9. package/_shared/pr-loop/scripts/pr_loop_shared_constants/terminology_sweep_constants.py +0 -2
  10. package/_shared/pr-loop/scripts/reviewer_availability.py +182 -0
  11. package/_shared/pr-loop/scripts/reviews_disabled.py +2 -0
  12. package/_shared/pr-loop/scripts/terminology_sweep.py +9 -33
  13. package/_shared/pr-loop/scripts/tests/CLAUDE.md +2 -0
  14. package/_shared/pr-loop/scripts/tests/test__claude_permissions_common.py +212 -0
  15. package/_shared/pr-loop/scripts/tests/test_agent_config_carveout.py +18 -0
  16. package/_shared/pr-loop/scripts/tests/test_claude_permissions_common.py +18 -0
  17. package/_shared/pr-loop/scripts/tests/test_code_rules_gate.py +37 -0
  18. package/_shared/pr-loop/scripts/tests/test_reviewer_availability.py +159 -0
  19. package/_shared/pr-loop/scripts/tests/test_reviewer_availability_constants.py +36 -0
  20. package/_shared/pr-loop/scripts/tests/test_reviews_disabled.py +14 -0
  21. package/_shared/pr-loop/scripts/tests/test_terminology_sweep.py +14 -4
  22. package/agents/clean-coder.md +3 -0
  23. package/audit-rubrics/category_rubrics/category-o-docstring-vs-impl-drift.md +1 -1
  24. package/bin/install.mjs +16 -8
  25. package/bin/install.test.mjs +17 -6
  26. package/commands/CLAUDE.md +0 -1
  27. package/docs/CODE_RULES.md +1 -1
  28. package/hooks/blocking/CLAUDE.md +2 -4
  29. package/hooks/blocking/code_rules_constants_config.py +164 -1
  30. package/hooks/blocking/code_rules_docstrings.py +428 -15
  31. package/hooks/blocking/code_rules_enforcer.py +33 -0
  32. package/hooks/blocking/code_rules_imports_logging.py +867 -1
  33. package/hooks/blocking/code_rules_magic_values.py +5 -0
  34. package/hooks/blocking/code_rules_naming_collection.py +152 -6
  35. package/hooks/blocking/code_rules_shared.py +34 -0
  36. package/hooks/blocking/code_rules_string_magic.py +68 -0
  37. package/hooks/blocking/duplicate_rmtree_helper_blocker.py +4 -4
  38. package/hooks/blocking/pre_tool_use_dispatcher.py +3 -3
  39. package/hooks/blocking/reviewer_spawn_gate.py +182 -0
  40. package/hooks/blocking/stale_comment_reference_blocker.py +267 -0
  41. package/hooks/blocking/state_description_blocker.py +96 -5
  42. package/hooks/blocking/test_code_rules_config_duplicate_path_anchor.py +132 -0
  43. package/hooks/blocking/test_code_rules_enforcer_cap_meta.py +2 -0
  44. package/hooks/blocking/test_code_rules_enforcer_docstring_delegation_summary.py +385 -0
  45. package/hooks/blocking/test_code_rules_enforcer_docstring_prose_wall_illustration.py +197 -0
  46. package/hooks/blocking/test_code_rules_enforcer_docstring_runon_sentence.py +27 -0
  47. package/hooks/blocking/test_code_rules_enforcer_join_separator_magic.py +67 -0
  48. package/hooks/blocking/test_code_rules_enforcer_module_docstring_roster.py +40 -0
  49. package/hooks/blocking/test_code_rules_enforcer_naive_datetime.py +213 -0
  50. package/hooks/blocking/test_code_rules_enforcer_referenced_underscore_loop.py +169 -0
  51. package/hooks/blocking/test_code_rules_enforcer_split_constants_config.py +33 -0
  52. package/hooks/blocking/test_code_rules_enforcer_split_shared.py +23 -0
  53. package/hooks/blocking/test_code_rules_js_bare_flag_return_directive.py +266 -0
  54. package/hooks/blocking/test_code_rules_js_sibling_return_object_key_drift.py +490 -0
  55. package/hooks/blocking/test_code_rules_logging_adjacent_literals.py +171 -0
  56. package/hooks/blocking/test_code_rules_magic_values.py +54 -0
  57. package/hooks/blocking/test_duplicate_rmtree_helper_blocker.py +0 -6
  58. package/hooks/blocking/test_pr_converge_bugteam_enforcer_state_tolerance.py +184 -0
  59. package/hooks/blocking/test_pre_tool_use_dispatcher.py +9 -3
  60. package/hooks/blocking/test_reviewer_spawn_gate.py +230 -0
  61. package/hooks/blocking/test_shared_stdin_adoption.py +5 -30
  62. package/hooks/blocking/test_stale_comment_reference_blocker.py +236 -0
  63. package/hooks/blocking/test_state_description_blocker.py +135 -0
  64. package/hooks/hooks.json +5 -0
  65. package/hooks/hooks_constants/CLAUDE.md +3 -4
  66. package/hooks/hooks_constants/blocking_check_limits.py +46 -0
  67. package/hooks/hooks_constants/code_rules_enforcer_constants.py +41 -0
  68. package/hooks/hooks_constants/code_rules_path_utils_constants.py +1 -1
  69. package/hooks/hooks_constants/duplicate_rmtree_helper_blocker_constants.py +0 -1
  70. package/hooks/hooks_constants/post_tool_use_dispatcher_constants.py +0 -5
  71. package/hooks/hooks_constants/pre_tool_use_dispatcher_constants.py +4 -0
  72. package/hooks/hooks_constants/reviewer_spawn_gate_constants.py +41 -0
  73. package/hooks/hooks_constants/stale_comment_reference_blocker_constants.py +76 -0
  74. package/hooks/hooks_constants/state_description_blocker_constants.py +8 -0
  75. package/hooks/validation/post_tool_use_dispatcher.py +1 -1
  76. package/hooks/validation/test_post_tool_use_dispatcher.py +51 -35
  77. package/hooks/workflow/CLAUDE.md +2 -8
  78. package/package.json +1 -1
  79. package/rules/CLAUDE.md +5 -2
  80. package/rules/claude-md-orphan-file.md +5 -0
  81. package/rules/docstring-prose-matches-implementation.md +10 -1
  82. package/rules/env-var-table-code-drift.md +5 -0
  83. package/rules/es-exe-file-search.md +17 -0
  84. package/rules/no-historical-clutter.md +12 -1
  85. package/rules/orphan-css-class.md +5 -0
  86. package/rules/package-inventory-stale-entry.md +10 -0
  87. package/rules/paired-test-coverage.md +5 -0
  88. package/rules/plain-illustrative-docstrings.md +40 -1
  89. package/rules/verify-before-asking.md +7 -0
  90. package/rules/verify-runtime-state.md +40 -0
  91. package/rules/windows-filesystem-safe.md +8 -0
  92. package/rules/workers-done-before-complete.md +33 -0
  93. package/rules/workflow-substitution-slots.md +5 -0
  94. package/skills/CLAUDE.md +7 -2
  95. package/skills/autoconverge/SKILL.md +48 -61
  96. package/skills/autoconverge/reference/closing-report.md +6 -6
  97. package/skills/autoconverge/reference/convergence.md +17 -15
  98. package/skills/autoconverge/reference/gotchas.md +6 -3
  99. package/skills/autoconverge/workflow/autoconverge_report_constants/render_report_constants.py +2 -9
  100. package/skills/autoconverge/workflow/converge.contract.test.mjs +153 -10
  101. package/skills/autoconverge/workflow/converge.copilot-gate.test.mjs +55 -19
  102. package/skills/autoconverge/workflow/converge.merge-conflict.test.mjs +16 -9
  103. package/skills/autoconverge/workflow/converge.mjs +167 -106
  104. package/skills/autoconverge/workflow/render_report.py +7 -11
  105. package/skills/bugteam/CLAUDE.md +1 -1
  106. package/skills/bugteam/PROMPTS.md +7 -6
  107. package/skills/bugteam/SKILL.md +25 -72
  108. package/skills/bugteam/reference/CLAUDE.md +1 -3
  109. package/skills/bugteam/reference/README.md +1 -1
  110. package/skills/bugteam/reference/audit-and-teammates.md +1 -1
  111. package/skills/bugteam/reference/obstacles/fix-publish-summary.md +1 -1
  112. package/skills/bugteam/reference/team-setup.md +8 -7
  113. package/skills/bugteam/scripts/CLAUDE.md +0 -6
  114. package/skills/bugteam/scripts/README.md +0 -4
  115. package/skills/bugteam/scripts/bugteam_scripts_constants/CLAUDE.md +0 -1
  116. package/skills/code/SKILL.md +2 -0
  117. package/skills/copilot-review/CLAUDE.md +1 -1
  118. package/skills/copilot-review/SKILL.md +25 -23
  119. package/skills/everything-search/SKILL.md +5 -0
  120. package/skills/findbugs/CLAUDE.md +2 -2
  121. package/skills/findbugs/SKILL.md +22 -83
  122. package/skills/fixbugs/SKILL.md +2 -4
  123. package/skills/log-audit/CLAUDE.md +20 -0
  124. package/skills/log-audit/SKILL.md +68 -0
  125. package/skills/log-audit/reference/CLAUDE.md +9 -0
  126. package/skills/log-audit/reference/charter.md +52 -0
  127. package/skills/log-audit/scripts/CLAUDE.md +27 -0
  128. package/skills/log-audit/scripts/cluster_recurrences.py +261 -0
  129. package/skills/log-audit/scripts/collect_log_window.py +199 -0
  130. package/skills/log-audit/scripts/log_audit_constants/CLAUDE.md +12 -0
  131. package/skills/log-audit/scripts/log_audit_constants/cluster_recurrences_constants.py +23 -0
  132. package/skills/log-audit/scripts/log_audit_constants/collect_log_window_constants.py +24 -0
  133. package/skills/log-audit/scripts/log_audit_constants/mine_copilot_findings_constants.py +49 -0
  134. package/skills/log-audit/scripts/mine_copilot_findings.py +302 -0
  135. package/skills/log-audit/scripts/test_cluster_recurrences.py +160 -0
  136. package/skills/log-audit/scripts/test_collect_log_window.py +111 -0
  137. package/skills/log-audit/scripts/test_mine_copilot_findings.py +126 -0
  138. package/skills/monitor-open-prs/SKILL.md +2 -2
  139. package/skills/post-audit-findings/SKILL.md +84 -0
  140. package/skills/pr-converge/CLAUDE.md +2 -0
  141. package/skills/pr-converge/SKILL.md +72 -59
  142. package/skills/pr-converge/reference/CLAUDE.md +1 -1
  143. package/skills/pr-converge/reference/convergence-gates.md +16 -19
  144. package/skills/pr-converge/reference/examples.md +5 -5
  145. package/skills/pr-converge/reference/fix-protocol.md +16 -43
  146. package/skills/pr-converge/reference/obstacles/fix-publish-summary.md +1 -1
  147. package/skills/pr-converge/reference/per-tick.md +24 -45
  148. package/skills/pr-converge/reference/state-schema.md +15 -0
  149. package/skills/pr-converge/scripts/README.md +3 -5
  150. package/skills/pr-fix-protocol/SKILL.md +70 -0
  151. package/skills/pr-loop-lifecycle/SKILL.md +73 -0
  152. package/skills/{bugteam → pr-loop-lifecycle}/reference/teardown-publish-permissions.md +22 -24
  153. package/skills/pr-scope-resolve/SKILL.md +48 -0
  154. package/skills/qbug/CLAUDE.md +4 -4
  155. package/skills/qbug/SKILL.md +46 -144
  156. package/skills/qbug/test_qbug_skill_audit_schema.py +2 -2
  157. package/skills/qbug/test_qbug_skill_post_fix_audit.py +1 -1
  158. package/skills/reviewer-gates/SKILL.md +96 -0
  159. package/skills/session-log/CLAUDE.md +7 -7
  160. package/skills/session-log/SKILL.md +27 -44
  161. package/skills/test_markdown_link_integrity.py +103 -0
  162. package/commands/doc-gist.md +0 -16
  163. package/hooks/blocking/_md_to_html_blocker_test_support.py +0 -65
  164. package/hooks/blocking/conftest.py +0 -30
  165. package/hooks/blocking/md_path_exemptions.py +0 -224
  166. package/hooks/blocking/md_to_html_blocker.py +0 -155
  167. package/hooks/blocking/test_md_to_html_blocker_exemptions.py +0 -434
  168. package/hooks/blocking/test_md_to_html_blocker_extensions.py +0 -157
  169. package/hooks/blocking/test_md_to_html_blocker_path_resolution.py +0 -336
  170. package/hooks/hooks_constants/doc_gist_auto_publish_constants.py +0 -18
  171. package/hooks/hooks_constants/html_companion_constants.py +0 -20
  172. package/hooks/hooks_constants/md_to_html_blocker_constants.py +0 -76
  173. package/hooks/hooks_constants/test_md_to_html_blocker_constants.py +0 -125
  174. package/hooks/workflow/doc_gist_auto_publish.py +0 -144
  175. package/hooks/workflow/md_to_html_companion.py +0 -358
  176. package/hooks/workflow/test_doc_gist_auto_publish.py +0 -117
  177. package/hooks/workflow/test_md_to_html_companion.py +0 -613
  178. package/skills/bugteam/reference/audit-contract.md +0 -163
  179. package/skills/bugteam/scripts/_bugteam_permissions_common.py +0 -455
  180. package/skills/bugteam/scripts/bugteam_scripts_constants/claude_permissions_common_constants.py +0 -69
  181. package/skills/bugteam/scripts/grant_project_claude_permissions.py +0 -280
  182. package/skills/bugteam/scripts/revoke_project_claude_permissions.py +0 -266
  183. package/skills/bugteam/scripts/test__bugteam_permissions_common.py +0 -160
  184. package/skills/bugteam/scripts/test_agent_config_carveout.py +0 -356
  185. package/skills/bugteam/scripts/test_bugteam_permissions_common.py +0 -140
  186. package/skills/doc-gist/CLAUDE.md +0 -25
  187. package/skills/doc-gist/SKILL.md +0 -97
  188. package/skills/doc-gist/references/CLAUDE.md +0 -9
  189. package/skills/doc-gist/references/examples/01-exploration-code-approaches.html +0 -453
  190. package/skills/doc-gist/references/examples/02-exploration-visual-designs.html +0 -515
  191. package/skills/doc-gist/references/examples/03-code-review-pr.html +0 -638
  192. package/skills/doc-gist/references/examples/04-code-understanding.html +0 -491
  193. package/skills/doc-gist/references/examples/05-design-system.html +0 -629
  194. package/skills/doc-gist/references/examples/06-component-variants.html +0 -605
  195. package/skills/doc-gist/references/examples/07-prototype-animation.html +0 -455
  196. package/skills/doc-gist/references/examples/08-prototype-interaction.html +0 -396
  197. package/skills/doc-gist/references/examples/09-slide-deck.html +0 -592
  198. package/skills/doc-gist/references/examples/10-svg-illustrations.html +0 -492
  199. package/skills/doc-gist/references/examples/11-status-report.html +0 -528
  200. package/skills/doc-gist/references/examples/12-incident-report.html +0 -596
  201. package/skills/doc-gist/references/examples/13-flowchart-diagram.html +0 -395
  202. package/skills/doc-gist/references/examples/14-research-feature-explainer.html +0 -381
  203. package/skills/doc-gist/references/examples/15-research-concept-explainer.html +0 -368
  204. package/skills/doc-gist/references/examples/16-implementation-plan.html +0 -702
  205. package/skills/doc-gist/references/examples/17-pr-writeup.html +0 -595
  206. package/skills/doc-gist/references/examples/18-editor-triage-board.html +0 -573
  207. package/skills/doc-gist/references/examples/19-editor-feature-flags.html +0 -663
  208. package/skills/doc-gist/references/examples/20-editor-prompt-tuner.html +0 -722
  209. package/skills/doc-gist/references/examples/21-decision-signoff.html +0 -546
  210. package/skills/doc-gist/references/examples/CLAUDE.md +0 -25
  211. package/skills/doc-gist/references/examples/README.md +0 -5
  212. package/skills/doc-gist/scripts/CLAUDE.md +0 -27
  213. package/skills/doc-gist/scripts/doc_gist_scripts_constants/CLAUDE.md +0 -10
  214. package/skills/doc-gist/scripts/doc_gist_scripts_constants/gist_upload_constants.py +0 -16
  215. package/skills/doc-gist/scripts/gist_upload.py +0 -177
  216. package/skills/doc-gist/scripts/test_gist_upload.py +0 -51
  217. /package/skills/{doc-gist/scripts/doc_gist_scripts_constants → log-audit/scripts/log_audit_constants}/__init__.py +0 -0
@@ -1,97 +0,0 @@
1
- ---
2
- name: doc-gist
3
- description: >-
4
- Use when the user asks to share, publish, preview, or open as a webpage any HTML doc,
5
- writeup, report, plan, runbook, or interactive artifact. Triggers on /doc-gist,
6
- "publish this", "share as a gist", "open this as a webpage", "make me a writeup", or
7
- any request ending in a shareable HTML preview URL. Provides the gist_upload transport
8
- script, the <!-- @publish-as-gist --> auto-publish hook, and an HTML pattern gallery.
9
- ---
10
-
11
- # doc-gist
12
-
13
- Design fresh HTML for the artifact at hand, mark it for publishing, write it. The rest is automatic — a hook spots the marker, uploads to a secret gist, and prints the htmlpreview URL into your output for the user to click.
14
-
15
- ## Principle (and what this skill deliberately does not ship)
16
-
17
- This skill ships **transport, not shape**. There are no document templates here. There is no markdown-to-HTML converter. There is no rebase-report mode. The shape of every artifact is your fresh design per request, drawing on the gallery in [`references/examples/`](references/examples/) for inspiration.
18
-
19
- Per Thariq's html-effectiveness thesis: *"twenty self-contained .html files an agent produced — each one trades a document you'd skim for one you'd actually read."* Every doc-gist invocation produces a fresh design appropriate to the work, not a template fill.
20
-
21
- ## How auto-publish works
22
-
23
- 1. You write HTML to any path (no directory rule, no naming rule).
24
- 2. The HTML contains the marker comment `<!-- @publish-as-gist -->` — typically as the first child of `<head>` or just inside `<body>`.
25
- 3. The PostToolUse hook ([`workflow/doc_gist_auto_publish.py`](../../hooks/workflow/doc_gist_auto_publish.py)) fires after the Write/Edit completes, sees the marker, and runs [`skills/doc-gist/scripts/gist_upload.py`](scripts/gist_upload.py) against the file.
26
- 4. The upload script's gist + preview URLs print into your tool output. Quote them back to the user.
27
-
28
- The hook is a no-op for any HTML that lacks the marker — React components, test fixtures, scraped pages, partial fragments. The marker is the *intent signal*; absent marker means "this HTML isn't for sharing."
29
-
30
- ## Gotchas
31
-
32
- - **`gh` must be authenticated.** The upload runs `gh gist create`. If `gh auth status` is failing, the hook surfaces the error to stderr and exits 0 (does not block the write). Run `gh auth login` and re-trigger by editing the HTML once more.
33
- - **The marker is a literal HTML comment, not a meta tag.** `<!-- @publish-as-gist -->` exactly. `<meta name="publish-as-gist">` does not match. Whitespace inside the marker breaks it.
34
- - **htmlpreview render delay.** First load of the preview URL takes 5–10 seconds while htmlpreview.github.io fetches the raw gist content. A blank page on first visit means refresh once.
35
- - **Filenames carry into the gist.** The gist filename is the same as the source file's name. Name your files for the artifact, not for filesystem convenience — `auth-migration-plan.html` reads better in the gist UI than `tmp_plan_v3_final.html`.
36
- - **Markers in code samples need escaping.** If you embed an example HTML snippet inside `<pre><code>` and that snippet contains the literal marker text, the hook will publish on first save. Either escape the comment angle brackets in the embedded sample, or write the marker as `<!- - @publish-as-gist - ->` in the embedded version.
37
- - **Self-contained HTML only.** The upload sends a single file. External CSS/JS via `<link href="./style.css">` or `<script src="./app.js">` will fail to load in the htmlpreview view. Inline everything — `<style>`, `<script>`, base64 images, SVG.
38
- - **Secret gist, not private.** `gh gist create` defaults to "secret" (anyone with the URL can view; not indexed; not on your public profile). Treat the preview URL like a shareable Google Doc — share with intent.
39
-
40
- ## When to include the marker
41
-
42
- Include `<!-- @publish-as-gist -->` when **the artifact is for sharing or reading**: writeups, plans, reports, explainers, decision records, runbooks, status updates, prototypes the user will look at. Skip the marker for: HTML that's part of a code change (React components, test fixtures), HTML you're authoring as a one-off scratch file you'll delete, embedded HTML samples inside other artifacts.
43
-
44
- The user's prompt is the strongest signal. *"Make me a writeup of this PR"* → publish. *"Add this React component"* → don't publish.
45
-
46
- ## The transport script — `skills/doc-gist/scripts/gist_upload.py`
47
-
48
- For manual invocation when the marker route doesn't apply (an existing file you want to publish, HTML piped from another tool, a one-off):
49
-
50
- ```
51
- python3 skills/doc-gist/scripts/gist_upload.py --input <path-or-stdin>
52
- [--filename gist-file.html]
53
- [--description "short label"]
54
- [--no-open]
55
- ```
56
-
57
- Reads HTML from `--input <path>` or stdin (`--input -`), runs `gh gist create`, prints `Gist:` and `Preview:` URLs to stderr, prints the preview URL to stdout (so callers can pipe), opens the preview in the default browser unless `--no-open`.
58
-
59
- ## Designing fresh — the example gallery
60
-
61
- The skill ships [`references/examples/`](references/examples/) with 21 html-effectiveness examples: Thariq's 20 prototypes verbatim from [thariqs.github.io/html-effectiveness](https://thariqs.github.io/html-effectiveness/) (`01`–`20`), plus one original addition (`21-decision-signoff.html`). They are *examples to learn from, not templates to fill.*
62
-
63
- When the user requests an artifact, decide the shape that fits. Use the gallery for grounding:
64
-
65
- | User wants | Gallery entries to study |
66
- |---|---|
67
- | PR writeup with file-by-file tour | `17-pr-writeup.html` |
68
- | Annotated diff or code review | `03-code-review-pr.html` |
69
- | Code-explainer with module map | `04-code-understanding.html` |
70
- | Implementation plan with timeline + risks | `16-implementation-plan.html` |
71
- | Side-by-side approach exploration | `01-exploration-code-approaches.html` |
72
- | Visual design comparison | `02-exploration-visual-designs.html` |
73
- | Design system swatches | `05-design-system.html` |
74
- | Component variants matrix | `06-component-variants.html` |
75
- | Animation tuning sandbox with sliders | `07-prototype-animation.html` |
76
- | Multi-screen interaction mockup | `08-prototype-interaction.html` |
77
- | Slide deck (keyboard-navigable) | `09-slide-deck.html` |
78
- | SVG illustration | `10-svg-illustrations.html` |
79
- | Status report (visual) | `11-status-report.html` |
80
- | Incident timeline / post-mortem | `12-incident-report.html` |
81
- | Flowchart / pipeline diagram | `13-flowchart-diagram.html` |
82
- | Feature explainer with collapsibles | `14-research-feature-explainer.html` |
83
- | Concept explainer (interactive learning) | `15-research-concept-explainer.html` |
84
- | Triage / kanban board (drag-drop) | `18-editor-triage-board.html` |
85
- | Feature flag toggles with deps | `19-editor-feature-flags.html` |
86
- | Live-updating template editor | `20-editor-prompt-tuner.html` |
87
- | Decision / sign-off doc (accept-or-change each call, export digest) | `21-decision-signoff.html` |
88
-
89
- Read the matching example for the artifact you're designing. Crib palette, typography, spatial idioms, component patterns. **Adapt — do not copy.** A PR writeup for a hooks PR shouldn't look identical to one for a notification-queue PR. The gallery teaches what shapes work; the request decides which shape fits.
90
-
91
- ## Folder map
92
-
93
- - `SKILL.md` — this file.
94
- - `skills/doc-gist/scripts/gist_upload.py` — transport: HTML in, gist + preview URLs out.
95
- - `skills/doc-gist/scripts/doc_gist_scripts_constants/gist_upload_constants.py` — the URL prefixes and template strings.
96
- - `references/examples/` — Thariq's 20 html-effectiveness prototypes (`01`–`20`) plus one original addition (`21-decision-signoff.html`).
97
- - (PostToolUse hook lives in `packages/claude-dev-env/hooks/workflow/doc_gist_auto_publish.py` — wired into the plugin's `hooks.json`.)
@@ -1,9 +0,0 @@
1
- # doc-gist/references
2
-
3
- Reference material for the `doc-gist` skill.
4
-
5
- ## Subdirectories
6
-
7
- | Directory | Role |
8
- |---|---|
9
- | `examples/` | A gallery of 21 self-contained HTML artifact examples that show distinct shapes — annotated PR diff, design system swatches, slide deck, incident timeline, prompt tuner, decision sign-off, and more. Study these when designing a fresh artifact; do not copy them verbatim. |
@@ -1,453 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Debounced search — three approaches</title>
7
- <style>
8
- :root {
9
- --ivory: #FAF9F5;
10
- --slate: #141413;
11
- --clay: #D97757;
12
- --oat: #E3DACC;
13
- --olive: #788C5D;
14
- --gray-150: #F0EEE6;
15
- --gray-300: #D1CFC5;
16
- --gray-500: #87867F;
17
- --gray-700: #3D3D3A;
18
- --white: #FFFFFF;
19
-
20
- --serif: ui-serif, Georgia, 'Times New Roman', serif;
21
- --sans: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
22
- --mono: ui-monospace, 'SF Mono', Menlo, Monaco, monospace;
23
- }
24
-
25
- * { margin: 0; padding: 0; box-sizing: border-box; }
26
-
27
- body {
28
- font-family: var(--sans);
29
- background: var(--ivory);
30
- color: var(--gray-700);
31
- line-height: 1.55;
32
- padding: 56px 32px 96px;
33
- -webkit-font-smoothing: antialiased;
34
- }
35
-
36
- .page {
37
- max-width: 1360px;
38
- margin: 0 auto;
39
- }
40
-
41
- /* ---------- header ---------- */
42
-
43
- header.page-head {
44
- margin-bottom: 48px;
45
- max-width: 760px;
46
- }
47
-
48
- .eyebrow {
49
- font-size: 12px;
50
- letter-spacing: 0.08em;
51
- text-transform: uppercase;
52
- color: var(--gray-500);
53
- margin-bottom: 12px;
54
- }
55
-
56
- h1 {
57
- font-family: var(--serif);
58
- font-weight: 500;
59
- font-size: 38px;
60
- line-height: 1.15;
61
- color: var(--slate);
62
- margin-bottom: 18px;
63
- letter-spacing: -0.01em;
64
- }
65
-
66
- .prompt-box {
67
- background: var(--gray-150);
68
- border: 1.5px solid var(--gray-300);
69
- border-radius: 12px;
70
- padding: 16px 20px;
71
- font-size: 14.5px;
72
- color: var(--gray-700);
73
- }
74
-
75
- .prompt-box .label {
76
- font-family: var(--mono);
77
- font-size: 11px;
78
- text-transform: uppercase;
79
- letter-spacing: 0.06em;
80
- color: var(--gray-500);
81
- display: block;
82
- margin-bottom: 6px;
83
- }
84
-
85
- /* ---------- approach grid ---------- */
86
-
87
- .approaches {
88
- display: grid;
89
- grid-template-columns: repeat(3, minmax(0, 1fr));
90
- gap: 28px;
91
- margin-bottom: 56px;
92
- }
93
-
94
- @media (max-width: 1100px) {
95
- .approaches { grid-template-columns: 1fr; }
96
- }
97
-
98
- .approach {
99
- background: var(--white);
100
- border: 1.5px solid var(--gray-300);
101
- border-radius: 12px;
102
- padding: 24px;
103
- display: flex;
104
- flex-direction: column;
105
- gap: 20px;
106
- }
107
-
108
- .approach-head h2 {
109
- font-family: var(--serif);
110
- font-weight: 500;
111
- font-size: 21px;
112
- color: var(--slate);
113
- margin-bottom: 6px;
114
- }
115
-
116
- .approach-head .num {
117
- display: inline-block;
118
- font-family: var(--mono);
119
- font-size: 12px;
120
- background: var(--oat);
121
- color: var(--slate);
122
- padding: 2px 8px;
123
- border-radius: 8px;
124
- margin-right: 8px;
125
- vertical-align: 3px;
126
- }
127
-
128
- .approach-head p {
129
- font-size: 14px;
130
- color: var(--gray-500);
131
- }
132
-
133
- /* ---------- code panel ---------- */
134
-
135
- .code {
136
- background: var(--slate);
137
- border-radius: 12px;
138
- padding: 18px 20px;
139
- overflow-x: auto;
140
- }
141
-
142
- .code pre {
143
- font-family: var(--mono);
144
- font-size: 12.5px;
145
- line-height: 1.65;
146
- color: #E8E6DE;
147
- white-space: pre;
148
- }
149
-
150
- .code .kw { color: var(--clay); } /* keywords */
151
- .code .str { color: var(--olive); } /* strings */
152
- .code .cm { color: var(--gray-500); } /* comments */
153
- .code .fn { color: #C9B98A; } /* identifiers, subtle warm */
154
-
155
- /* ---------- tradeoffs table ---------- */
156
-
157
- .tradeoffs {
158
- border: 1.5px solid var(--gray-300);
159
- border-radius: 8px;
160
- overflow: hidden;
161
- font-size: 13px;
162
- }
163
-
164
- .tradeoffs .row {
165
- display: grid;
166
- grid-template-columns: 1fr 1fr;
167
- }
168
-
169
- .tradeoffs .row + .row {
170
- border-top: 1.5px solid var(--gray-300);
171
- }
172
-
173
- .tradeoffs .cell {
174
- padding: 10px 14px;
175
- }
176
-
177
- .tradeoffs .cell:first-child {
178
- border-right: 1.5px solid var(--gray-300);
179
- }
180
-
181
- .tradeoffs .head {
182
- background: var(--gray-150);
183
- font-weight: 600;
184
- color: var(--slate);
185
- font-size: 12px;
186
- text-transform: uppercase;
187
- letter-spacing: 0.04em;
188
- }
189
-
190
- .tradeoffs .pro::before,
191
- .tradeoffs .con::before {
192
- content: '';
193
- display: inline-block;
194
- width: 6px;
195
- height: 6px;
196
- border-radius: 50%;
197
- margin-right: 8px;
198
- vertical-align: 2px;
199
- }
200
- .tradeoffs .pro::before { background: var(--olive); }
201
- .tradeoffs .con::before { background: var(--clay); }
202
-
203
- /* ---------- chip footer ---------- */
204
-
205
- .chips {
206
- display: flex;
207
- flex-wrap: wrap;
208
- gap: 8px;
209
- }
210
-
211
- .chip {
212
- font-family: var(--mono);
213
- font-size: 11.5px;
214
- background: var(--gray-150);
215
- border: 1.5px solid var(--gray-300);
216
- color: var(--gray-700);
217
- padding: 5px 10px;
218
- border-radius: 8px;
219
- white-space: nowrap;
220
- }
221
-
222
- .chip strong { color: var(--slate); font-weight: 600; }
223
-
224
- /* ---------- recommendation ---------- */
225
-
226
- .reco {
227
- border-left: 4px solid var(--clay);
228
- background: var(--white);
229
- border-radius: 0 12px 12px 0;
230
- padding: 24px 28px;
231
- max-width: 860px;
232
- }
233
-
234
- .reco h2 {
235
- font-family: var(--serif);
236
- font-weight: 500;
237
- font-size: 22px;
238
- color: var(--slate);
239
- margin-bottom: 10px;
240
- }
241
-
242
- .reco p {
243
- font-size: 15px;
244
- margin-bottom: 8px;
245
- }
246
-
247
- .reco code {
248
- font-family: var(--mono);
249
- font-size: 0.92em;
250
- background: var(--gray-150);
251
- padding: 1px 6px;
252
- border-radius: 4px;
253
- }
254
- </style>
255
- </head>
256
- <body>
257
- <div class="page">
258
-
259
- <header class="page-head">
260
- <div class="eyebrow">Exploration · Birchline web client</div>
261
- <h1>Three ways to implement debounced search</h1>
262
- <div class="prompt-box">
263
- <span class="label">Prompt</span>
264
- Show me three different ways to implement debounced search for the task
265
- filter input in our React codebase, with tradeoffs for each.
266
- </div>
267
- </header>
268
-
269
- <!-- ============================================================= -->
270
-
271
- <section class="approaches">
272
-
273
- <!-- ---------- Approach 1 ---------- -->
274
- <article class="approach">
275
- <header class="approach-head">
276
- <h2><span class="num">01</span>Inline useEffect + setTimeout</h2>
277
- <p>Debounce logic lives directly inside the component that owns the input.</p>
278
- </header>
279
-
280
- <div class="code"><pre><span class="kw">export function</span> <span class="fn">TaskSearch</span>() {
281
- <span class="kw">const</span> [draft, setDraft] = <span class="fn">useState</span>(<span class="str">''</span>);
282
- <span class="kw">const</span> [query, setQuery] = <span class="fn">useState</span>(<span class="str">''</span>);
283
-
284
- <span class="fn">useEffect</span>(() <span class="kw">=&gt;</span> {
285
- <span class="kw">const</span> id = <span class="fn">setTimeout</span>(() <span class="kw">=&gt;</span> setQuery(draft), <span class="str">300</span>);
286
- <span class="kw">return</span> () <span class="kw">=&gt;</span> <span class="fn">clearTimeout</span>(id);
287
- }, [draft]);
288
-
289
- <span class="kw">const</span> { data } = <span class="fn">useTasks</span>({ search: query });
290
-
291
- <span class="kw">return</span> (
292
- &lt;<span class="fn">input</span>
293
- value={draft}
294
- onChange={(e) <span class="kw">=&gt;</span> setDraft(e.target.value)}
295
- placeholder=<span class="str">"Filter tasks…"</span>
296
- /&gt;
297
- );
298
- }</pre></div>
299
-
300
- <div class="tradeoffs">
301
- <div class="row head">
302
- <div class="cell">Pro</div>
303
- <div class="cell">Con</div>
304
- </div>
305
- <div class="row">
306
- <div class="cell pro">Zero new abstractions to learn</div>
307
- <div class="cell con">Logic duplicated everywhere search exists</div>
308
- </div>
309
- <div class="row">
310
- <div class="cell pro">Easy to step through in devtools</div>
311
- <div class="cell con">Two pieces of state for one conceptual value</div>
312
- </div>
313
- <div class="row">
314
- <div class="cell pro">No dependency or bundle change</div>
315
- <div class="cell con">Delay constant is buried in component body</div>
316
- </div>
317
- </div>
318
-
319
- <div class="chips">
320
- <span class="chip">Bundle impact: <strong>+0 kb</strong></span>
321
- <span class="chip">Testability: <strong>medium</strong></span>
322
- <span class="chip">Reuse: <strong>low</strong></span>
323
- <span class="chip">SSR safe: <strong>yes</strong></span>
324
- </div>
325
- </article>
326
-
327
- <!-- ---------- Approach 2 ---------- -->
328
- <article class="approach">
329
- <header class="approach-head">
330
- <h2><span class="num">02</span>Custom useDebounce hook</h2>
331
- <p>Extract the timer into a shared hook under <code style="font-family:var(--mono)">src/hooks/</code>.</p>
332
- </header>
333
-
334
- <div class="code"><pre><span class="cm">// src/hooks/useDebounce.ts</span>
335
- <span class="kw">export function</span> <span class="fn">useDebounce</span>&lt;T&gt;(value: T, ms = <span class="str">300</span>): T {
336
- <span class="kw">const</span> [debounced, setDebounced] = <span class="fn">useState</span>(value);
337
- <span class="fn">useEffect</span>(() <span class="kw">=&gt;</span> {
338
- <span class="kw">const</span> id = <span class="fn">setTimeout</span>(() <span class="kw">=&gt;</span> setDebounced(value), ms);
339
- <span class="kw">return</span> () <span class="kw">=&gt;</span> <span class="fn">clearTimeout</span>(id);
340
- }, [value, ms]);
341
- <span class="kw">return</span> debounced;
342
- }
343
-
344
- <span class="cm">// TaskSearch.tsx</span>
345
- <span class="kw">const</span> [draft, setDraft] = <span class="fn">useState</span>(<span class="str">''</span>);
346
- <span class="kw">const</span> query = <span class="fn">useDebounce</span>(draft, <span class="str">300</span>);
347
- <span class="kw">const</span> { data } = <span class="fn">useTasks</span>({ search: query });</pre></div>
348
-
349
- <div class="tradeoffs">
350
- <div class="row head">
351
- <div class="cell">Pro</div>
352
- <div class="cell">Con</div>
353
- </div>
354
- <div class="row">
355
- <div class="cell pro">Single import reused across filter, command bar, board search</div>
356
- <div class="cell con">One more file to maintain and document</div>
357
- </div>
358
- <div class="row">
359
- <div class="cell pro">Trivial to unit test with fake timers</div>
360
- <div class="cell con">Generic <code style="font-family:var(--mono)">T</code> hides intent slightly</div>
361
- </div>
362
- <div class="row">
363
- <div class="cell pro">Delay is a visible, tunable argument</div>
364
- <div class="cell con">Still re-renders on every keystroke</div>
365
- </div>
366
- </div>
367
-
368
- <div class="chips">
369
- <span class="chip">Bundle impact: <strong>+0.2 kb</strong></span>
370
- <span class="chip">Testability: <strong>high</strong></span>
371
- <span class="chip">Reuse: <strong>high</strong></span>
372
- <span class="chip">SSR safe: <strong>yes</strong></span>
373
- </div>
374
- </article>
375
-
376
- <!-- ---------- Approach 3 ---------- -->
377
- <article class="approach">
378
- <header class="approach-head">
379
- <h2><span class="num">03</span>Tiny external library</h2>
380
- <p>Adopt <code style="font-family:var(--mono)">use-debounce</code> for both values and callbacks.</p>
381
- </header>
382
-
383
- <div class="code"><pre><span class="kw">import</span> { useDebouncedCallback }
384
- <span class="kw">from</span> <span class="str">'use-debounce'</span>;
385
-
386
- <span class="kw">export function</span> <span class="fn">TaskSearch</span>() {
387
- <span class="kw">const</span> [query, setQuery] = <span class="fn">useState</span>(<span class="str">''</span>);
388
-
389
- <span class="kw">const</span> onChange = <span class="fn">useDebouncedCallback</span>(
390
- (next: <span class="kw">string</span>) <span class="kw">=&gt;</span> setQuery(next),
391
- <span class="str">300</span>,
392
- { leading: <span class="kw">false</span>, maxWait: <span class="str">1000</span> },
393
- );
394
-
395
- <span class="kw">const</span> { data } = <span class="fn">useTasks</span>({ search: query });
396
-
397
- <span class="kw">return</span> (
398
- &lt;<span class="fn">input</span>
399
- defaultValue=<span class="str">""</span>
400
- onChange={(e) <span class="kw">=&gt;</span> onChange(e.target.value)}
401
- /&gt;
402
- );
403
- }</pre></div>
404
-
405
- <div class="tradeoffs">
406
- <div class="row head">
407
- <div class="cell">Pro</div>
408
- <div class="cell">Con</div>
409
- </div>
410
- <div class="row">
411
- <div class="cell pro">leading / trailing / maxWait handled for us</div>
412
- <div class="cell con">New runtime dependency to audit and update</div>
413
- </div>
414
- <div class="row">
415
- <div class="cell pro">Callback form skips intermediate re-renders</div>
416
- <div class="cell con">Uncontrolled input diverges from Birchline form patterns</div>
417
- </div>
418
- <div class="row">
419
- <div class="cell pro">Well-tested edge cases (unmount, flush, cancel)</div>
420
- <div class="cell con">~1.4 kb gzipped for something we could own</div>
421
- </div>
422
- </div>
423
-
424
- <div class="chips">
425
- <span class="chip">Bundle impact: <strong>+1.4 kb</strong></span>
426
- <span class="chip">Testability: <strong>high</strong></span>
427
- <span class="chip">Reuse: <strong>high</strong></span>
428
- <span class="chip">SSR safe: <strong>yes</strong></span>
429
- </div>
430
- </article>
431
-
432
- </section>
433
-
434
- <!-- ============================================================= -->
435
-
436
- <aside class="reco">
437
- <h2>Recommendation</h2>
438
- <p>
439
- Go with <strong>approach 02, the custom <code>useDebounce</code> hook</strong>.
440
- Birchline already has three places that hand-roll the inline pattern
441
- (task filter, command palette, member picker), so extracting one
442
- shared hook removes duplication without taking on a new dependency.
443
- </p>
444
- <p>
445
- Revisit approach 03 only if we later need <code>maxWait</code> or
446
- <code>flush()</code> semantics — the library earns its bundle cost
447
- once the requirements outgrow a ten-line hook.
448
- </p>
449
- </aside>
450
-
451
- </div>
452
- </body>
453
- </html>