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,592 +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">
6
- <title>Platform Eng — Week of Mar 10</title>
7
- <style>
8
- /* ------------------------------------------------------------------
9
- Design tokens
10
- ------------------------------------------------------------------ */
11
- :root {
12
- --ivory: #FAF9F5;
13
- --slate: #141413;
14
- --clay: #D97757;
15
- --oat: #E3DACC;
16
- --olive: #788C5D;
17
- --gray-150:#F0EEE6;
18
- --gray-300:#D1CFC5;
19
- --gray-500:#87867F;
20
- --gray-700:#3D3D3A;
21
-
22
- --serif: ui-serif, Georgia, "Times New Roman", serif;
23
- --sans: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
24
- --mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
25
- }
26
-
27
- * { margin: 0; padding: 0; box-sizing: border-box; }
28
-
29
- html { scroll-behavior: smooth; }
30
-
31
- body {
32
- font-family: var(--sans);
33
- background: var(--ivory);
34
- color: var(--slate);
35
- -webkit-font-smoothing: antialiased;
36
- scroll-snap-type: y mandatory;
37
- overflow-x: hidden;
38
- }
39
-
40
- /* ------------------------------------------------------------------
41
- Slide shell
42
- ------------------------------------------------------------------ */
43
- .slide {
44
- width: 100vw;
45
- height: 100vh;
46
- scroll-snap-align: start;
47
- scroll-snap-stop: always;
48
- display: flex;
49
- align-items: center;
50
- justify-content: center;
51
- padding: 8vh 6vw;
52
- }
53
-
54
- .slide-inner {
55
- width: 100%;
56
- max-width: 780px;
57
- }
58
-
59
- .slide.invert {
60
- background: var(--slate);
61
- color: var(--ivory);
62
- }
63
-
64
- /* ------------------------------------------------------------------
65
- Typography
66
- ------------------------------------------------------------------ */
67
- .eyebrow {
68
- font-family: var(--mono);
69
- font-size: 12px;
70
- letter-spacing: 0.12em;
71
- text-transform: uppercase;
72
- color: var(--gray-500);
73
- margin-bottom: 28px;
74
- }
75
- .invert .eyebrow { color: var(--gray-300); }
76
-
77
- h1 {
78
- font-family: var(--serif);
79
- font-weight: 500;
80
- font-size: clamp(40px, 6vw, 64px);
81
- line-height: 1.08;
82
- letter-spacing: -0.01em;
83
- margin-bottom: 20px;
84
- }
85
-
86
- h2 {
87
- font-family: var(--serif);
88
- font-weight: 500;
89
- font-size: clamp(30px, 4vw, 42px);
90
- line-height: 1.15;
91
- letter-spacing: -0.005em;
92
- margin-bottom: 44px;
93
- }
94
-
95
- .subtitle {
96
- font-size: 17px;
97
- line-height: 1.6;
98
- color: var(--gray-700);
99
- max-width: 520px;
100
- }
101
-
102
- .mono { font-family: var(--mono); }
103
-
104
- /* ------------------------------------------------------------------
105
- Slide 1 — title
106
- ------------------------------------------------------------------ */
107
- .title-slide .slide-inner { text-align: left; }
108
-
109
- .ornament {
110
- display: block;
111
- margin: 0 0 40px 0;
112
- }
113
-
114
- .byline {
115
- margin-top: 56px;
116
- font-family: var(--mono);
117
- font-size: 12px;
118
- color: var(--gray-500);
119
- display: flex;
120
- gap: 24px;
121
- }
122
-
123
- /* ------------------------------------------------------------------
124
- Slide 2 — shipped list
125
- ------------------------------------------------------------------ */
126
- .ship-list {
127
- list-style: none;
128
- display: flex;
129
- flex-direction: column;
130
- gap: 28px;
131
- }
132
-
133
- .ship-item {
134
- display: grid;
135
- grid-template-columns: 14px 1fr auto;
136
- column-gap: 20px;
137
- align-items: baseline;
138
- padding-bottom: 24px;
139
- border-bottom: 1px solid var(--gray-150);
140
- }
141
- .ship-item:last-child { border-bottom: none; }
142
-
143
- .ship-dot {
144
- width: 9px;
145
- height: 9px;
146
- border-radius: 50%;
147
- background: var(--olive);
148
- margin-top: 8px;
149
- align-self: start;
150
- }
151
-
152
- .ship-title {
153
- font-family: var(--serif);
154
- font-size: 20px;
155
- font-weight: 500;
156
- margin-bottom: 6px;
157
- }
158
-
159
- .ship-desc {
160
- font-size: 14px;
161
- line-height: 1.55;
162
- color: var(--gray-700);
163
- }
164
-
165
- .ship-ref {
166
- font-family: var(--mono);
167
- font-size: 11px;
168
- color: var(--gray-500);
169
- white-space: nowrap;
170
- padding-top: 4px;
171
- }
172
-
173
- /* ------------------------------------------------------------------
174
- Slide 3 — in progress
175
- ------------------------------------------------------------------ */
176
- .prog-list {
177
- list-style: none;
178
- display: flex;
179
- flex-direction: column;
180
- gap: 40px;
181
- }
182
-
183
- .prog-item .prog-head {
184
- display: flex;
185
- justify-content: space-between;
186
- align-items: baseline;
187
- margin-bottom: 10px;
188
- }
189
-
190
- .prog-title {
191
- font-family: var(--serif);
192
- font-size: 20px;
193
- font-weight: 500;
194
- }
195
-
196
- .prog-pct {
197
- font-family: var(--mono);
198
- font-size: 12px;
199
- color: var(--gray-500);
200
- }
201
-
202
- .prog-track {
203
- width: 100%;
204
- height: 5px;
205
- background: var(--gray-150);
206
- border-radius: 3px;
207
- overflow: hidden;
208
- margin-bottom: 10px;
209
- }
210
-
211
- .prog-fill {
212
- height: 100%;
213
- background: var(--clay);
214
- border-radius: 3px;
215
- }
216
-
217
- .prog-note {
218
- font-size: 13px;
219
- line-height: 1.55;
220
- color: var(--gray-700);
221
- }
222
-
223
- /* ------------------------------------------------------------------
224
- Slide 4 — metrics
225
- ------------------------------------------------------------------ */
226
- .metrics {
227
- display: grid;
228
- grid-template-columns: 1fr 1fr;
229
- gap: 56px;
230
- margin-bottom: 48px;
231
- }
232
-
233
- .metric-label {
234
- font-family: var(--mono);
235
- font-size: 11px;
236
- letter-spacing: 0.08em;
237
- text-transform: uppercase;
238
- color: var(--gray-500);
239
- margin-bottom: 14px;
240
- }
241
-
242
- .metric-value {
243
- font-family: var(--serif);
244
- font-size: 52px;
245
- font-weight: 500;
246
- line-height: 1;
247
- letter-spacing: -0.01em;
248
- }
249
-
250
- .metric-delta {
251
- font-family: var(--mono);
252
- font-size: 13px;
253
- margin-top: 12px;
254
- }
255
- .metric-delta.down { color: var(--olive); }
256
- .metric-delta.up { color: var(--clay); }
257
-
258
- .sparkline-wrap {
259
- border-top: 1px solid var(--gray-300);
260
- padding-top: 28px;
261
- }
262
-
263
- .sparkline-caption {
264
- font-size: 12px;
265
- color: var(--gray-500);
266
- margin-top: 10px;
267
- }
268
-
269
- /* ------------------------------------------------------------------
270
- Slide 5 — decision (inverted)
271
- ------------------------------------------------------------------ */
272
- .decision-card {
273
- border: 1.5px solid var(--clay);
274
- border-radius: 14px;
275
- padding: 36px 38px;
276
- background: rgba(217, 119, 87, 0.06);
277
- }
278
-
279
- .decision-q {
280
- font-family: var(--serif);
281
- font-size: 24px;
282
- line-height: 1.4;
283
- margin-bottom: 12px;
284
- }
285
-
286
- .decision-context {
287
- font-size: 14px;
288
- line-height: 1.6;
289
- color: var(--gray-300);
290
- }
291
-
292
- .options {
293
- display: flex;
294
- gap: 14px;
295
- margin-top: 32px;
296
- flex-wrap: wrap;
297
- }
298
-
299
- .chip {
300
- font-family: var(--mono);
301
- font-size: 12px;
302
- padding: 10px 18px;
303
- border-radius: 999px;
304
- border: 1px solid var(--gray-700);
305
- color: var(--ivory);
306
- background: transparent;
307
- }
308
- .chip.lean {
309
- border-color: var(--clay);
310
- color: var(--clay);
311
- }
312
-
313
- /* ------------------------------------------------------------------
314
- Slide 6 — next week
315
- ------------------------------------------------------------------ */
316
- .next-list {
317
- list-style: none;
318
- display: flex;
319
- flex-direction: column;
320
- gap: 22px;
321
- }
322
-
323
- .next-list li {
324
- font-family: var(--serif);
325
- font-size: 21px;
326
- line-height: 1.45;
327
- padding-left: 36px;
328
- position: relative;
329
- }
330
-
331
- .next-list li::before {
332
- content: "";
333
- position: absolute;
334
- left: 0;
335
- top: 0.55em;
336
- width: 18px;
337
- height: 1.5px;
338
- background: var(--clay);
339
- }
340
-
341
- .footnote {
342
- margin-top: 56px;
343
- font-family: var(--mono);
344
- font-size: 11px;
345
- color: var(--gray-500);
346
- }
347
-
348
- /* ------------------------------------------------------------------
349
- Slide counter
350
- ------------------------------------------------------------------ */
351
- #counter {
352
- position: fixed;
353
- bottom: 22px;
354
- right: 28px;
355
- font-family: var(--mono);
356
- font-size: 12px;
357
- color: var(--gray-500);
358
- user-select: none;
359
- z-index: 10;
360
- }
361
-
362
- @media (max-width: 640px) {
363
- .metrics { grid-template-columns: 1fr; gap: 36px; }
364
- .ship-item { grid-template-columns: 14px 1fr; }
365
- .ship-ref { grid-column: 2; padding-top: 8px; }
366
- }
367
- </style>
368
- </head>
369
- <body>
370
-
371
- <!-- ============================================================
372
- Slide 1 — Title
373
- ============================================================ -->
374
- <section class="slide title-slide" id="s1">
375
- <div class="slide-inner">
376
- <svg class="ornament" width="56" height="56" viewBox="0 0 56 56" aria-hidden="true">
377
- <circle cx="28" cy="28" r="22" fill="none" stroke="#D1CFC5" stroke-width="1.5"/>
378
- <path d="M16 28 H40 M28 16 V40" stroke="#D97757" stroke-width="1.5" stroke-linecap="round"/>
379
- <circle cx="28" cy="28" r="3" fill="#141413"/>
380
- </svg>
381
- <h1>Platform Eng<br>— Week of Mar 10</h1>
382
- <p class="subtitle">
383
- What shipped, what's moving, and one decision we need from the
384
- room before the Birchline 2.4 cut.
385
- </p>
386
- <div class="byline">
387
- <span>Friday demo</span>
388
- <span>6 slides</span>
389
- <span>~4 min</span>
390
- </div>
391
- </div>
392
- </section>
393
-
394
- <!-- ============================================================
395
- Slide 2 — Shipped
396
- ============================================================ -->
397
- <section class="slide" id="s2">
398
- <div class="slide-inner">
399
- <div class="eyebrow">Shipped this week</div>
400
- <h2>Three things out the door</h2>
401
- <ul class="ship-list">
402
- <li class="ship-item">
403
- <span class="ship-dot"></span>
404
- <div>
405
- <div class="ship-title">Bulk task import</div>
406
- <div class="ship-desc">
407
- CSV and JSON uploads now land straight into a board with
408
- column mapping — no more paste-and-pray.
409
- </div>
410
- </div>
411
- <span class="ship-ref">#4211</span>
412
- </li>
413
- <li class="ship-item">
414
- <span class="ship-dot"></span>
415
- <div>
416
- <div class="ship-title">Webhook retries v2</div>
417
- <div class="ship-desc">
418
- Exponential backoff with jitter; dead-letter queue surfaces
419
- in the workspace admin panel.
420
- </div>
421
- </div>
422
- <span class="ship-ref">#4188 #4203</span>
423
- </li>
424
- <li class="ship-item">
425
- <span class="ship-dot"></span>
426
- <div>
427
- <div class="ship-title">Postgres 16 migration</div>
428
- <div class="ship-desc">
429
- All read replicas cut over Tuesday night; zero customer-facing
430
- downtime, ~9% faster aggregate queries.
431
- </div>
432
- </div>
433
- <span class="ship-ref">#4179</span>
434
- </li>
435
- </ul>
436
- </div>
437
- </section>
438
-
439
- <!-- ============================================================
440
- Slide 3 — In progress
441
- ============================================================ -->
442
- <section class="slide" id="s3">
443
- <div class="slide-inner">
444
- <div class="eyebrow">In progress</div>
445
- <h2>Carrying into next week</h2>
446
- <ul class="prog-list">
447
- <li class="prog-item">
448
- <div class="prog-head">
449
- <span class="prog-title">Recurring tasks engine</span>
450
- <span class="prog-pct">~70%</span>
451
- </div>
452
- <div class="prog-track"><div class="prog-fill" style="width:70%"></div></div>
453
- <p class="prog-note">
454
- Scheduler and RRULE parsing are done; remaining work is the
455
- timezone edge cases and the "skip holidays" toggle.
456
- </p>
457
- </li>
458
- <li class="prog-item">
459
- <div class="prog-head">
460
- <span class="prog-title">Audit log export</span>
461
- <span class="prog-pct">~35%</span>
462
- </div>
463
- <div class="prog-track"><div class="prog-fill" style="width:35%"></div></div>
464
- <p class="prog-note">
465
- Streaming NDJSON endpoint is up behind a flag; still wiring
466
- the S3 destination picker and retention policy UI.
467
- </p>
468
- </li>
469
- </ul>
470
- </div>
471
- </section>
472
-
473
- <!-- ============================================================
474
- Slide 4 — Metrics
475
- ============================================================ -->
476
- <section class="slide" id="s4">
477
- <div class="slide-inner">
478
- <div class="eyebrow">Metrics</div>
479
- <h2>Numbers we watch</h2>
480
-
481
- <div class="metrics">
482
- <div class="metric">
483
- <div class="metric-label">API p95 latency</div>
484
- <div class="metric-value">184<span style="font-size:28px">ms</span></div>
485
- <div class="metric-delta down">↓ 12% wk/wk</div>
486
- </div>
487
- <div class="metric">
488
- <div class="metric-label">Background job error rate</div>
489
- <div class="metric-value">0.21<span style="font-size:28px">%</span></div>
490
- <div class="metric-delta down">↓ 0.08pp</div>
491
- </div>
492
- </div>
493
-
494
- <div class="sparkline-wrap">
495
- <svg width="100%" height="64" viewBox="0 0 780 64" preserveAspectRatio="none" aria-hidden="true">
496
- <polyline
497
- points="0,22 110,30 220,18 330,34 440,26 550,40 660,24 780,12"
498
- fill="none"
499
- stroke="#788C5D"
500
- stroke-width="2"
501
- stroke-linejoin="round"
502
- stroke-linecap="round"/>
503
- <circle cx="780" cy="12" r="3.5" fill="#788C5D"/>
504
- <line x1="0" y1="63" x2="780" y2="63" stroke="#D1CFC5" stroke-width="1"/>
505
- </svg>
506
- <div class="sparkline-caption">
507
- p95 latency, trailing 8 days — lower is better
508
- </div>
509
- </div>
510
- </div>
511
- </section>
512
-
513
- <!-- ============================================================
514
- Slide 5 — Decision needed (inverted)
515
- ============================================================ -->
516
- <section class="slide invert" id="s5">
517
- <div class="slide-inner">
518
- <div class="eyebrow">Decision needed</div>
519
- <h2>One call to make</h2>
520
-
521
- <div class="decision-card">
522
- <p class="decision-q">
523
- Do we ship recurring tasks behind a workspace flag in 2.4, or
524
- hold one more week for the timezone fixes?
525
- </p>
526
- <p class="decision-context">
527
- Flagged rollout gets it to design partners Friday but means two
528
- code paths for ~2 weeks. Holding keeps a single path but slips
529
- the partner promise.
530
- </p>
531
- </div>
532
-
533
- <div class="options">
534
- <span class="chip lean">A — Flag it, ship Friday</span>
535
- <span class="chip">B — Hold for 2.5</span>
536
- </div>
537
- </div>
538
- </section>
539
-
540
- <!-- ============================================================
541
- Slide 6 — Next week
542
- ============================================================ -->
543
- <section class="slide" id="s6">
544
- <div class="slide-inner">
545
- <div class="eyebrow">Next week</div>
546
- <h2>On deck</h2>
547
- <ul class="next-list">
548
- <li>Finish recurring tasks — timezone matrix tests, then dogfood on the internal ops board.</li>
549
- <li>Audit log export to private beta — three workspaces lined up.</li>
550
- <li>Start scoping rate-limit headers for the public API; RFC draft by Thursday.</li>
551
- </ul>
552
- <div class="footnote">
553
- Questions → drop them in the platform channel or grab anyone after standup.
554
- </div>
555
- </div>
556
- </section>
557
-
558
- <!-- ============================================================
559
- Slide counter
560
- ============================================================ -->
561
- <div id="counter">1 / 6</div>
562
-
563
- <script>
564
- (function () {
565
- const slides = Array.from(document.querySelectorAll('.slide'));
566
- const counter = document.getElementById('counter');
567
- let current = 0;
568
-
569
- function go(i) {
570
- current = Math.max(0, Math.min(slides.length - 1, i));
571
- slides[current].scrollIntoView({ behavior: 'smooth' });
572
- }
573
-
574
- document.addEventListener('keydown', function (e) {
575
- if (e.key === 'ArrowRight' || e.key === 'ArrowDown' || e.key === ' ') { e.preventDefault(); go(current + 1); }
576
- if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') { e.preventDefault(); go(current - 1); }
577
- });
578
-
579
- const obs = new IntersectionObserver(function (entries) {
580
- entries.forEach(function (en) {
581
- if (en.isIntersecting) {
582
- current = slides.indexOf(en.target);
583
- counter.textContent = (current + 1) + ' / ' + slides.length;
584
- }
585
- });
586
- }, { threshold: 0.6 });
587
-
588
- slides.forEach(function (s) { obs.observe(s); });
589
- })();
590
- </script>
591
- </body>
592
- </html>