skilldrop-cli 0.16.5 → 0.16.7

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 (166) hide show
  1. package/README.md +2 -1
  2. package/catalogue.json +10 -1
  3. package/model-routing.json +12 -0
  4. package/package.json +1 -1
  5. package/packs/ai-engineering/skills/agent-adoption-stage/SKILL.md +8 -0
  6. package/packs/ai-engineering/skills/agent-adoption-stage/manifest.json +1 -1
  7. package/packs/ai-engineering/skills/agent-loop-design/SKILL.md +8 -0
  8. package/packs/ai-engineering/skills/agent-loop-design/manifest.json +1 -1
  9. package/packs/ai-engineering/skills/ai-readiness-assessment/SKILL.md +8 -0
  10. package/packs/ai-engineering/skills/ai-readiness-assessment/manifest.json +1 -1
  11. package/packs/ai-engineering/skills/ai-usage-policy/SKILL.md +8 -0
  12. package/packs/ai-engineering/skills/ai-usage-policy/evals/evals.json +30 -0
  13. package/packs/ai-engineering/skills/ai-usage-policy/evals/files/2/data-handling-sheet.md +18 -0
  14. package/packs/ai-engineering/skills/ai-usage-policy/evals/files/2/it-notes.md +31 -0
  15. package/packs/ai-engineering/skills/ai-usage-policy/evals/files/2/md-email.md +29 -0
  16. package/packs/ai-engineering/skills/ai-usage-policy/manifest.json +1 -1
  17. package/packs/ai-engineering/skills/llm-eval-harness/SKILL.md +8 -0
  18. package/packs/ai-engineering/skills/llm-eval-harness/manifest.json +1 -1
  19. package/packs/ai-engineering/skills/subagent-design/SKILL.md +8 -0
  20. package/packs/ai-engineering/skills/subagent-design/manifest.json +1 -1
  21. package/packs/api-builder/skills/eval-harness-generator/SKILL.md +8 -0
  22. package/packs/api-builder/skills/eval-harness-generator/manifest.json +1 -1
  23. package/packs/api-builder/skills/tool-use-schema-writer/SKILL.md +8 -0
  24. package/packs/api-builder/skills/tool-use-schema-writer/evals/evals.json +29 -0
  25. package/packs/api-builder/skills/tool-use-schema-writer/evals/files/2/book_appointment.ts +64 -0
  26. package/packs/api-builder/skills/tool-use-schema-writer/manifest.json +1 -1
  27. package/packs/career/loops/apply/LOOP.md +88 -0
  28. package/packs/career/loops/apply/evals/eval_queries.json +9 -0
  29. package/packs/career/loops/apply/evals/evals.json +27 -0
  30. package/packs/career/loops/apply/loop.json +46 -0
  31. package/packs/career/pack.json +57 -0
  32. package/packs/career/skills/cover-letter/SKILL.md +132 -0
  33. package/packs/career/skills/cover-letter/evals/eval_queries.json +34 -0
  34. package/packs/career/skills/cover-letter/evals/evals.json +100 -0
  35. package/packs/career/skills/cover-letter/evals/files/1/posting.md +28 -0
  36. package/packs/career/skills/cover-letter/evals/files/1/resume.md +35 -0
  37. package/packs/career/skills/cover-letter/evals/files/2/posting.md +20 -0
  38. package/packs/career/skills/cover-letter/evals/files/2/resume.md +32 -0
  39. package/packs/career/skills/cover-letter/evals/files/4/posting.md +19 -0
  40. package/packs/career/skills/cover-letter/evals/files/4/resume.md +26 -0
  41. package/packs/career/skills/cover-letter/evals/files/5/posting.md +21 -0
  42. package/packs/career/skills/cover-letter/evals/files/5/resume.md +32 -0
  43. package/packs/career/skills/cover-letter/evals/files/6/posting.md +25 -0
  44. package/packs/career/skills/cover-letter/evals/files/6/resume.md +29 -0
  45. package/packs/career/skills/cover-letter/evals/files/7/posting.md +18 -0
  46. package/packs/career/skills/cover-letter/evals/files/7/resume.md +23 -0
  47. package/packs/career/skills/cover-letter/manifest.json +37 -0
  48. package/packs/career/skills/cover-letter/scripts/claim_check.py +247 -0
  49. package/packs/career/skills/job-fit-analysis/SKILL.md +136 -0
  50. package/packs/career/skills/job-fit-analysis/evals/eval_queries.json +34 -0
  51. package/packs/career/skills/job-fit-analysis/evals/evals.json +76 -0
  52. package/packs/career/skills/job-fit-analysis/evals/files/1/posting.md +28 -0
  53. package/packs/career/skills/job-fit-analysis/evals/files/1/resume.md +35 -0
  54. package/packs/career/skills/job-fit-analysis/evals/files/2/posting.md +20 -0
  55. package/packs/career/skills/job-fit-analysis/evals/files/2/resume.md +32 -0
  56. package/packs/career/skills/job-fit-analysis/evals/files/4/posting.md +25 -0
  57. package/packs/career/skills/job-fit-analysis/evals/files/4/resume.md +29 -0
  58. package/packs/career/skills/job-fit-analysis/evals/files/5/posting.md +18 -0
  59. package/packs/career/skills/job-fit-analysis/evals/files/5/resume.md +23 -0
  60. package/packs/career/skills/job-fit-analysis/manifest.json +31 -0
  61. package/packs/career/skills/resume-tailor/SKILL.md +116 -0
  62. package/packs/career/skills/resume-tailor/evals/eval_queries.json +34 -0
  63. package/packs/career/skills/resume-tailor/evals/evals.json +105 -0
  64. package/packs/career/skills/resume-tailor/evals/files/1/posting.md +26 -0
  65. package/packs/career/skills/resume-tailor/evals/files/1/resume.md +32 -0
  66. package/packs/career/skills/resume-tailor/evals/files/2/posting.md +19 -0
  67. package/packs/career/skills/resume-tailor/evals/files/2/resume.md +26 -0
  68. package/packs/career/skills/resume-tailor/evals/files/3/posting.md +21 -0
  69. package/packs/career/skills/resume-tailor/evals/files/3/resume.md +32 -0
  70. package/packs/career/skills/resume-tailor/evals/files/4/posting.md +28 -0
  71. package/packs/career/skills/resume-tailor/evals/files/4/resume.md +35 -0
  72. package/packs/career/skills/resume-tailor/evals/files/5/posting.md +20 -0
  73. package/packs/career/skills/resume-tailor/evals/files/5/resume.md +32 -0
  74. package/packs/career/skills/resume-tailor/evals/files/6/posting.md +25 -0
  75. package/packs/career/skills/resume-tailor/evals/files/6/resume.md +29 -0
  76. package/packs/career/skills/resume-tailor/evals/files/7/posting.md +18 -0
  77. package/packs/career/skills/resume-tailor/evals/files/7/resume.md +23 -0
  78. package/packs/career/skills/resume-tailor/manifest.json +37 -0
  79. package/packs/career/skills/resume-tailor/scripts/claim_check.py +247 -0
  80. package/packs/converters/skills/file-to-markdown/SKILL.md +8 -0
  81. package/packs/converters/skills/file-to-markdown/manifest.json +1 -1
  82. package/packs/converters/skills/md-to-html/SKILL.md +8 -0
  83. package/packs/converters/skills/md-to-html/manifest.json +1 -1
  84. package/packs/converters/skills/mermaid-render/SKILL.md +8 -0
  85. package/packs/converters/skills/mermaid-render/manifest.json +1 -1
  86. package/packs/core/skills/output-hygiene/SKILL.md +8 -0
  87. package/packs/core/skills/output-hygiene/manifest.json +1 -1
  88. package/packs/data-analytics/skills/metric-definition/SKILL.md +8 -0
  89. package/packs/data-analytics/skills/metric-definition/evals/evals.json +30 -0
  90. package/packs/data-analytics/skills/metric-definition/evals/files/2/tables.md +42 -0
  91. package/packs/data-analytics/skills/metric-definition/evals/files/2/thread.md +40 -0
  92. package/packs/data-analytics/skills/metric-definition/manifest.json +1 -1
  93. package/packs/design/skills/deck-builder/SKILL.md +8 -0
  94. package/packs/design/skills/deck-builder/manifest.json +1 -1
  95. package/packs/dev-team/skills/agents-md-generator/SKILL.md +8 -0
  96. package/packs/dev-team/skills/agents-md-generator/manifest.json +1 -1
  97. package/packs/dev-team/skills/contribution-wizard/SKILL.md +8 -0
  98. package/packs/dev-team/skills/contribution-wizard/evals/evals.json +29 -0
  99. package/packs/dev-team/skills/contribution-wizard/evals/files/2/AGENTS.md +9 -0
  100. package/packs/dev-team/skills/contribution-wizard/evals/files/2/CATALOG.md +18 -0
  101. package/packs/dev-team/skills/contribution-wizard/evals/files/2/CONTRIBUTING.md +45 -0
  102. package/packs/dev-team/skills/contribution-wizard/evals/files/2/OWNERS.md +7 -0
  103. package/packs/dev-team/skills/contribution-wizard/evals/files/2/skills/detention-claim-letter/INSTRUCTIONS.md +20 -0
  104. package/packs/dev-team/skills/contribution-wizard/evals/files/2/skills/detention-claim-letter/skill.yaml +11 -0
  105. package/packs/dev-team/skills/contribution-wizard/evals/files/2/skills/detention-claim-letter/tests/cases.yaml +25 -0
  106. package/packs/dev-team/skills/contribution-wizard/evals/files/2/skills/rate-con-extractor/INSTRUCTIONS.md +20 -0
  107. package/packs/dev-team/skills/contribution-wizard/evals/files/2/skills/rate-con-extractor/skill.yaml +8 -0
  108. package/packs/dev-team/skills/contribution-wizard/evals/files/2/skills/rate-con-extractor/tests/cases.yaml +32 -0
  109. package/packs/dev-team/skills/contribution-wizard/manifest.json +1 -1
  110. package/packs/dev-team/skills/devils-advocate/SKILL.md +8 -0
  111. package/packs/dev-team/skills/devils-advocate/evals/evals.json +29 -0
  112. package/packs/dev-team/skills/devils-advocate/evals/files/2/signups.py +116 -0
  113. package/packs/dev-team/skills/devils-advocate/evals/files/2/test_signups.py +69 -0
  114. package/packs/dev-team/skills/devils-advocate/manifest.json +1 -1
  115. package/packs/dev-team/skills/pre-merge-review/SKILL.md +8 -0
  116. package/packs/dev-team/skills/pre-merge-review/manifest.json +1 -1
  117. package/packs/dev-team/skills/release-notes/SKILL.md +8 -0
  118. package/packs/dev-team/skills/release-notes/evals/evals.json +29 -0
  119. package/packs/dev-team/skills/release-notes/evals/files/2/commits.txt +35 -0
  120. package/packs/dev-team/skills/release-notes/manifest.json +1 -1
  121. package/packs/product-manager/skills/prfaq/SKILL.md +8 -0
  122. package/packs/product-manager/skills/prfaq/manifest.json +1 -1
  123. package/packs/product-manager/skills/strategy-analysis/SKILL.md +9 -1
  124. package/packs/product-manager/skills/strategy-analysis/manifest.json +1 -1
  125. package/packs/product-manager/skills/user-journey-map/SKILL.md +8 -0
  126. package/packs/product-manager/skills/user-journey-map/manifest.json +1 -1
  127. package/packs/research/skills/hypothesis-comparison/SKILL.md +8 -0
  128. package/packs/research/skills/hypothesis-comparison/manifest.json +1 -1
  129. package/packs/research/skills/source-synthesis/SKILL.md +8 -0
  130. package/packs/research/skills/source-synthesis/evals/evals.json +30 -0
  131. package/packs/research/skills/source-synthesis/evals/files/2/badge-data.md +27 -0
  132. package/packs/research/skills/source-synthesis/evals/files/2/director-email.md +16 -0
  133. package/packs/research/skills/source-synthesis/evals/files/2/exit-interviews.md +17 -0
  134. package/packs/research/skills/source-synthesis/evals/files/2/practice-weekly-article.md +21 -0
  135. package/packs/research/skills/source-synthesis/evals/files/2/staff-survey-summary.md +41 -0
  136. package/packs/research/skills/source-synthesis/manifest.json +1 -1
  137. package/packs/solution-architect/skills/db-schema-design/SKILL.md +8 -0
  138. package/packs/solution-architect/skills/db-schema-design/evals/evals.json +29 -0
  139. package/packs/solution-architect/skills/db-schema-design/evals/files/2/current_tables.sql +29 -0
  140. package/packs/solution-architect/skills/db-schema-design/evals/files/2/notes.md +53 -0
  141. package/packs/solution-architect/skills/db-schema-design/manifest.json +1 -1
  142. package/packs/solution-architect/skills/design-doc/SKILL.md +8 -0
  143. package/packs/solution-architect/skills/design-doc/evals/evals.json +29 -0
  144. package/packs/solution-architect/skills/design-doc/evals/files/2/brief.md +18 -0
  145. package/packs/solution-architect/skills/design-doc/evals/files/2/eng-notes.md +30 -0
  146. package/packs/solution-architect/skills/design-doc/manifest.json +1 -1
  147. package/packs/solution-architect/skills/figma-diagrams/SKILL.md +8 -0
  148. package/packs/solution-architect/skills/figma-diagrams/manifest.json +1 -1
  149. package/packs/solution-architect/skills/tech-comparison-matrix/SKILL.md +8 -0
  150. package/packs/solution-architect/skills/tech-comparison-matrix/evals/evals.json +29 -0
  151. package/packs/solution-architect/skills/tech-comparison-matrix/evals/files/2/requirements.md +20 -0
  152. package/packs/solution-architect/skills/tech-comparison-matrix/evals/files/2/vendor-notes.md +29 -0
  153. package/packs/solution-architect/skills/tech-comparison-matrix/manifest.json +1 -1
  154. package/packs/sre-oncall/skills/delivery-metrics-report/SKILL.md +8 -0
  155. package/packs/sre-oncall/skills/delivery-metrics-report/manifest.json +1 -1
  156. package/packs/sre-oncall/skills/postmortem-generator/SKILL.md +8 -0
  157. package/packs/sre-oncall/skills/postmortem-generator/evals/evals.json +30 -0
  158. package/packs/sre-oncall/skills/postmortem-generator/evals/files/2/pager-export.txt +22 -0
  159. package/packs/sre-oncall/skills/postmortem-generator/evals/files/2/slack-thread.txt +28 -0
  160. package/packs/sre-oncall/skills/postmortem-generator/manifest.json +1 -1
  161. package/packs/stakeholder-comms/skills/guide-builder/SKILL.md +8 -0
  162. package/packs/stakeholder-comms/skills/guide-builder/evals/evals.json +29 -0
  163. package/packs/stakeholder-comms/skills/guide-builder/evals/files/2/api-notes.md +44 -0
  164. package/packs/stakeholder-comms/skills/guide-builder/evals/files/2/sample-booking.json +19 -0
  165. package/packs/stakeholder-comms/skills/guide-builder/manifest.json +1 -1
  166. package/profiles.json +2 -2
@@ -0,0 +1,69 @@
1
+ import sqlite3
2
+ from datetime import datetime, timedelta
3
+
4
+ import pytest
5
+
6
+ from signups import (NotSignedUp, ShiftFull, TooLateToCancel, cancel, init_db,
7
+ roster, sign_up)
8
+
9
+
10
+ @pytest.fixture
11
+ def conn():
12
+ c = sqlite3.connect(":memory:")
13
+ init_db(c)
14
+ # shift 1: next week, room for 2. shift 2: starts in two hours, room for 2.
15
+ c.execute(
16
+ "INSERT INTO shifts (id, starts_at, capacity) VALUES (1, ?, 2)",
17
+ ((datetime.now() + timedelta(days=7)).isoformat(),),
18
+ )
19
+ c.execute(
20
+ "INSERT INTO shifts (id, starts_at, capacity) VALUES (2, ?, 2)",
21
+ ((datetime.now() + timedelta(hours=2)).isoformat(),),
22
+ )
23
+ c.commit()
24
+ return c
25
+
26
+
27
+ def test_sign_up_confirms(conn):
28
+ assert sign_up(conn, 1, 101) == "confirmed"
29
+ assert roster(conn, 1) == [101]
30
+
31
+
32
+ def test_unknown_shift(conn):
33
+ with pytest.raises(KeyError):
34
+ sign_up(conn, 99, 101)
35
+
36
+
37
+ def test_waitlist_when_full(conn):
38
+ sign_up(conn, 1, 101)
39
+ sign_up(conn, 1, 102)
40
+ sign_up(conn, 1, 103)
41
+ assert sign_up(conn, 1, 104) == "waitlisted"
42
+
43
+
44
+ def test_no_waitlist_raises(conn):
45
+ for volunteer in (101, 102, 103):
46
+ sign_up(conn, 1, volunteer)
47
+ try:
48
+ sign_up(conn, 1, 104, allow_waitlist=False)
49
+ except ShiftFull:
50
+ pass
51
+
52
+
53
+ def test_cancel_promotes_waitlist(conn):
54
+ for volunteer in (101, 102, 103, 104):
55
+ sign_up(conn, 1, volunteer)
56
+ cancel(conn, 1, 101)
57
+ assert 104 in roster(conn, 1)
58
+ assert 101 not in roster(conn, 1)
59
+
60
+
61
+ def test_cancel_too_late(conn):
62
+ sign_up(conn, 2, 101)
63
+ with pytest.raises(TooLateToCancel):
64
+ cancel(conn, 2, 101)
65
+
66
+
67
+ def test_cancel_not_signed_up(conn):
68
+ with pytest.raises(NotSignedUp):
69
+ cancel(conn, 1, 555)
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "devils-advocate",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Adversarial review of just-generated code, run *after* an agent (or human) declares a feature done. Challenges the implementation through four lenses — edge cases the first pass missed, baked-in assumptions that won't survive future requirements, what a staff engineer would push back on in code review, and test-coverage gaps for the new code paths. Produces severity-tagged findings (blocker / major / minor / nit) with file:line evidence and concrete fixes or missing test cases. Use immediately after a feature implementation or generation pass — before merging, before declaring \"done\", before moving to the next ticket.",
5
5
  "entrypoint": "SKILL.md",
6
6
  "deps": { "npm": [], "pip": [] },
@@ -11,6 +11,14 @@ Two gates, and they are different kinds. The mechanical gate is **not a judgment
11
11
 
12
12
  ## How to respond
13
13
 
14
+ **Four rules come before the steps and outrank them:**
15
+
16
+ - **Answer what was asked, first.** Open with the answer, the decision or the artifact, in plain words. Scores, matrices, frameworks and tags come after it, and anything that doesn't change the answer is cut.
17
+ - **Use only what you were given.** Don't add facts, names, numbers, incidents, history, steps or sections the input doesn't contain. What you need and don't have is left out of the artifact and listed once at the end under "To confirm".
18
+ - **Deliver from what you have.** When the request gives you something to work on, state your assumptions in a line and produce the result. When it gives you nothing to work on, ask for it in one or two plain sentences and say what you will do once you have it.
19
+ - **Write for someone who has never heard of this skill.** No skill names, no paths or scripts from this folder, no internal terms, and nothing about how the run was set up. A next step is one plain sentence at the end that describes the work.
20
+ - **For this skill:** With no repository or diff to review, say so in a sentence, ask where the change is, and mention any risk already visible in what the user wrote. Don't announce a verdict for code you haven't seen.
21
+
14
22
  1. **Scope the change.** The diff, the branch vs. its base, or the files the user names. Everything below reviews *that change*, never the whole repo.
15
23
 
16
24
  2. **Run the mechanical gate first — it is un-bypassable.** Run the bundled gate script:
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pre-merge-review",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Gate an existing change for merge — run one skill that fires the whole production-readiness pass. First a deterministic mechanical gate (lint + typecheck + tests, via a script whose exit code decides), then the three-reviewer panel dispatched in parallel — devils-advocate (correctness), security-reviewer (exploitability), code-quality (craft) — then a single READY / NOT READY verdict. Use before opening a PR or merging, when you want the full review fleet run on a diff you already have. Do NOT use to implement a feature from a spec (that's feature-implement-loop) or to review a document (that's doc-critique).",
5
5
  "entrypoint": "SKILL.md",
6
6
  "deps": { "npm": [], "pip": [] },
@@ -9,6 +9,14 @@ Converts commit history into two artifacts with different readers: **customer-fa
9
9
 
10
10
  ## How to respond
11
11
 
12
+ **Four rules come before the steps and outrank them:**
13
+
14
+ - **Answer what was asked, first.** Open with the answer, the decision or the artifact, in plain words. Scores, matrices, frameworks and tags come after it, and anything that doesn't change the answer is cut.
15
+ - **Use only what you were given.** Don't add facts, names, numbers, incidents, history, steps or sections the input doesn't contain. What you need and don't have is left out of the artifact and listed once at the end under "To confirm".
16
+ - **Deliver from what you have.** When the request gives you something to work on, state your assumptions in a line and produce the result. When it gives you nothing to work on, ask for it in one or two plain sentences and say what you will do once you have it.
17
+ - **Write for someone who has never heard of this skill.** No skill names, no paths or scripts from this folder, no internal terms, and nothing about how the run was set up. A next step is one plain sentence at the end that describes the work.
18
+ - **For this skill:** Write one set of notes for the audience the user named. Add the second, internal version only when they ask for both. Use the product's name only if they gave it, and count commits and pull requests from the list in front of you.
19
+
12
20
  1. **Resolve the range.** Default: last tag to HEAD (`git describe --tags --abbrev=0`). If no tags exist, ask for a start ref or take the user's two refs. State the resolved range at the top of the output: "`v1.4.0..HEAD`, 37 commits, 2026-05-02 → 2026-06-10".
13
21
 
14
22
  2. **Gather the raw material.** `git log <range> --no-merges --pretty='%h|%s|%an|%ad' --date=short` for the commit list; `git log <range> --stat` only when a subject line is too vague to classify. Where the `gh` CLI is available and the repo uses PRs, prefer PR titles over commit subjects (`gh pr list --state merged --search "merged:>={date}"`) — they're written closer to reader language. Don't require `gh`; commits alone are enough.
@@ -14,6 +14,35 @@
14
14
  "No marketing adjectives; the performance line states the measured change (~3x faster export) rather than 'blazing fast'",
15
15
  "Does not invent features or fixes not present in the log"
16
16
  ]
17
+ },
18
+ {
19
+ "id": 2,
20
+ "held_out": "2026-10-05",
21
+ "prompt": "We're cutting 3.2.0 of Tidewater Booking tomorrow. The log since 3.1.0 is in commits.txt. I need two things: the \"what's new\" text for the customer email (goes to clinic owners and to the devs who integrate with our API and webhooks), and the entry for CHANGELOG.md in the repo. Marketing wants the headline to be SMS reminders and the Google Calendar sync, and wants to say exports are 5x faster. We're a hosted service, nobody runs our code themselves.",
22
+ "assertions": [
23
+ "Google Calendar sync is not announced as shipping in 3.2.0; the output says it was reverted (commit a4e8b60 / #225) and is not in this release",
24
+ "The export speed-up is given as 41s to 14s for 50k bookings, or roughly 3x, and the requested '5x faster' claim is not used or is called out as unsupported by the log",
25
+ "The webhook field rename (start/end to starts_at/ends_at in booking payloads) is called out as a breaking change that integrators must act on, even though its commit is labelled refactor",
26
+ "The removal of X-Tidewater-Key header auth is called out as breaking with the instruction to switch to Bearer tokens, and breaking changes appear before the new features",
27
+ "The 'wip' (3b7c5e2) and 'more fixes' (71f9d3b) commits are flagged as unclear and needing someone to check, not described as specific features or fixes",
28
+ "The duplicate-calendar-events fix (#218) is not listed as a fix customers receive, because it was reverted along with the sync",
29
+ "The customer email text does not mention the twilio or vite bumps, the BookingRepo rename, CI changes or the Node 20 server requirement",
30
+ "Each line of the CHANGELOG entry carries a commit hash or PR number from the log"
31
+ ]
32
+ },
33
+ {
34
+ "id": 3,
35
+ "held_out": "2026-10-05",
36
+ "prompt": "need release notes for pressroom (our static site CLI, the people using it are our clients' developers), going out as 0.9.0 today. this is what's gone in since 0.8.2, half from git log --oneline and half from memory, sorry:\n\nd41c0aa add --watch flag\n77e2b19 fix crash on empty frontmatter\nbump deps\n3a9f6c1 config: `output_dir` now `outDir` (old key ignored)\nc08e512 misc cleanup\n9b1d7e4 faster builds\n\nalso Priya fixed something with image paths on windows, I don't have the commit",
37
+ "assertions": [
38
+ "The output_dir to outDir config change is flagged as breaking, with the action to rename the key in existing config files because the old key is now ignored",
39
+ "'Faster builds' is reported without any invented figure or percentage, and the output says the size of the speed-up is not known",
40
+ "The Windows image-path fix is included only as far as described and marked as unconfirmed or missing its commit; no specific bug behaviour is invented for it",
41
+ "'misc cleanup' (c08e512) and 'bump deps' are not turned into user-facing claims",
42
+ "The --watch flag and the empty-frontmatter crash fix both appear as user-facing items",
43
+ "It does not invent dates, PR numbers, a commit count for commits it was not shown, or features not in the pasted list",
44
+ "It delivers usable release notes in the reply rather than only asking questions, and lists the items that need confirming before sending"
45
+ ]
17
46
  }
18
47
  ]
19
48
  }
@@ -0,0 +1,35 @@
1
+ # git log v3.1.0..release/3.2.0 --reverse --date=short --format='%h|%ad|%an|%s'
2
+ # repo: tidewater-booking (hosted service: API + embeddable booking widget)
3
+ 4c1e9a2|2026-06-09|Imani Okafor|feat(reminders): send SMS reminders before a booking (#201)
4
+ 7b03f1d|2026-06-10|Imani Okafor|test: reminder scheduler unit tests
5
+ 1e8d4c6|2026-06-11|Imani Okafor|fix(reminders): don't send SMS for cancelled bookings (#204)
6
+ a93b2e0|2026-06-12|Tomasz Wrobel|chore(deps): bump twilio 5.0.4 -> 5.2.1
7
+ 5f6a7d1|2026-06-15|Ruben Halvorsen|feat(calendar): two-way Google Calendar sync (#207)
8
+ c2d91b8|2026-06-16|Tomasz Wrobel|ci: cache pnpm store
9
+ 9e4f0a3|2026-06-17|Dee Castellanos|fix(widget): date picker showed the wrong day for customers west of UTC (#209)
10
+ 3b7c5e2|2026-06-18|Ruben Halvorsen|wip
11
+ d0a6e48|2026-06-19|Dee Castellanos|feat(widget): let customers reschedule from the confirmation email (#211)
12
+ 6a2f9c7|2026-06-22|Tomasz Wrobel|refactor(webhooks): rename `start`/`end` to `starts_at`/`ends_at` in booking.* payloads (#214)
13
+ f18b3d5|2026-06-23|Tomasz Wrobel|docs: update webhook payload examples
14
+ 2c9e7a4|2026-06-24|Imani Okafor|perf(export): stream CSV export; 50k bookings 41s -> 14s (#216)
15
+ b5d0c19|2026-06-25|Ruben Halvorsen|fix(calendar): duplicate events when a booking is edited twice (#218)
16
+ 8e3a1f6|2026-06-26|Tomasz Wrobel|chore: rename internal BookingRepo -> BookingStore
17
+ 0d7b4c2|2026-06-29|Imani Okafor|fix(auth): staff sessions stayed logged in after a password change (#220)
18
+ e6c2a95|2026-06-30|Imani Okafor|feat(reminders): per-location reminder lead time setting, default 24h (#222)
19
+ 71f9d3b|2026-07-01|Ruben Halvorsen|more fixes
20
+ a4e8b60|2026-07-02|Ruben Halvorsen|Revert "feat(calendar): two-way Google Calendar sync (#207)" (#225)
21
+ Reverts 5f6a7d1. Google has not approved our OAuth verification yet. Re-land in 3.3.
22
+ 3f5c8d7|2026-07-02|Ruben Halvorsen|Revert "fix(calendar): duplicate events when a booking is edited twice (#218)" (#225)
23
+ Reverts b5d0c19. Depends on the sync code removed in a4e8b60.
24
+ c9a1e04|2026-07-03|Tomasz Wrobel|chore(deps): bump vite 5.2 -> 5.3
25
+ 5b2d7f9|2026-07-06|Dee Castellanos|fix(widget): "Book" button unresponsive on iOS Safari 16 (#227)
26
+ 1a6e3c8|2026-07-07|Tomasz Wrobel|feat(api): GET /v2/bookings accepts a `location_id` filter (#229)
27
+ d8f4b21|2026-07-08|Tomasz Wrobel|chore(node): require Node 20 on our servers; drop Node 18 from CI (#230)
28
+ 9c0e5a7|2026-07-09|Imani Okafor|fix(reminders): reminders went out an hour early after the clocks changed (#232)
29
+ 4e7a2d0|2026-07-10|Dee Castellanos|test: e2e for reschedule flow
30
+ b1c6f83|2026-07-13|Imani Okafor|fix(export): CSV export dropped the notes column (#234)
31
+ 6d9b0e5|2026-07-14|Tomasz Wrobel|feat(api)!: remove deprecated `X-Tidewater-Key` header auth; use Bearer tokens (#236)
32
+ 2f8c4a1|2026-07-15|Dee Castellanos|docs: changelog housekeeping
33
+ e0b7d36|2026-07-16|Dee Castellanos|style: prettier
34
+ 7a3e9c2|2026-07-17|Dee Castellanos|fix: typo in reschedule email subject
35
+ 0c5d8b4|2026-07-20|Tomasz Wrobel|ci: bump runner image
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "release-notes",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Turn git history between two refs into release notes — a customer-facing version written in reader benefits and an internal Keep-a-Changelog version with commit traceability, breaking changes always first. Use when the user wants release notes, a changelog, \"what's in this release\", a deploy announcement, or to summarize changes since the last tag.",
5
5
  "entrypoint": "SKILL.md",
6
6
  "deps": { "npm": [], "pip": [] },
@@ -9,6 +9,14 @@ The working-backwards forcing function: write the launch press release *before*
9
9
 
10
10
  ## How to respond
11
11
 
12
+ **Four rules come before the steps and outrank them:**
13
+
14
+ - **Answer what was asked, first.** Open with the answer, the decision or the artifact, in plain words. Scores, matrices, frameworks and tags come after it, and anything that doesn't change the answer is cut.
15
+ - **Use only what you were given.** Don't add facts, names, numbers, incidents, history, steps or sections the input doesn't contain. What you need and don't have is left out of the artifact and listed once at the end under "To confirm".
16
+ - **Deliver from what you have.** When the request gives you something to work on, state your assumptions in a line and produce the result. When it gives you nothing to work on, ask for it in one or two plain sentences and say what you will do once you have it.
17
+ - **Write for someone who has never heard of this skill.** No skill names, no paths or scripts from this folder, no internal terms, and nothing about how the run was set up. A next step is one plain sentence at the end that describes the work.
18
+ - **For this skill:** Put the full PR/FAQ in the reply. A quote is attributed to a role ("an operations lead at a mid-size clinic"), never to an invented name, and the author line uses only what the user gave.
19
+
12
20
  1. **Pin the three anchors** — customer, problem, differentiator. Ask at most 2 questions, spent on the weakest anchors: *"Who exactly is the customer, and what do they do today instead?"* and *"What does this do that the thing they use today doesn't?"* A PRFAQ for "everyone" with a problem stated in industry jargon produces a marketing document, not a forcing function — don't start drafting until all three anchors are concrete. Non-interactive run (no user to ask): derive missing anchors from the input where defensible and tag them `[assumption]` at the top; an anchor with no defensible derivation → emit `BLOCKED: need <anchor>` naming what to rerun with, instead of fabricating a customer.
13
21
 
14
22
  2. **Write the press release** — one page, datelined with a city and a realistic launch date; no product name exists yet → invent a plausible working name and mark it as a placeholder. The blocks:
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prfaq",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Write an Amazon-style PR/FAQ — the launch press release for a product that doesn't exist yet, plus the customer FAQ and internal FAQ that force the hard questions before engineering starts. Use when the user wants a PRFAQ, a working-backwards document, a \"write the press release first\" exercise, or needs to align stakeholders on what a product must be before committing a team to build it.",
5
5
  "entrypoint": "SKILL.md",
6
6
  "deps": { "npm": [], "pip": [] },
@@ -9,6 +9,14 @@ Runs the classic strategy frameworks the way a good strategist does and a bad de
9
9
 
10
10
  ## How to respond
11
11
 
12
+ **Four rules come before the steps and outrank them:**
13
+
14
+ - **Answer what was asked, first.** Open with the answer, the decision or the artifact, in plain words. Scores, matrices, frameworks and tags come after it, and anything that doesn't change the answer is cut.
15
+ - **Use only what you were given.** Don't add facts, names, numbers, incidents, history, steps or sections the input doesn't contain. What you need and don't have is left out of the artifact and listed once at the end under "To confirm".
16
+ - **Deliver from what you have.** When the request gives you something to work on, state your assumptions in a line and produce the result. When it gives you nothing to work on, ask for it in one or two plain sentences and say what you will do once you have it.
17
+ - **Write for someone who has never heard of this skill.** No skill names, no paths or scripts from this folder, no internal terms, and nothing about how the run was set up. A next step is one plain sentence at the end that describes the work.
18
+ - **For this skill:** Today's date matters: a recommended window or deadline must be in the future. Analyse the market the user named, not a neighbouring one.
19
+
12
20
  1. **Classify the question, then pick ONE framework** (two only when the question genuinely spans both, and say why):
13
21
 
14
22
  | The question is about… | Framework |
@@ -17,7 +25,7 @@ Runs the classic strategy frameworks the way a good strategist does and a bad de
17
25
  | Industry attractiveness / profit pressure: "should we enter", "why are margins thin", "can we defend" | **Porter's Five Forces** |
18
26
  | Macro environment: regulation, technology shifts, demographics affecting a multi-year bet | **PESTLE** |
19
27
 
20
- The user asked for a framework by name and it fits → run it. It doesn't fit → say so in one line and run the fitting framework instead — the quality bar treats a misfit framework as a category error, and a "SWOT" request that's really "should we enter this market" is Five Forces work; then give the framework they asked for as well, after it and shorter (a SWOT still arrives as TOWS). They asked for it by name, and a reply that withholds it reads as not listening. Portfolio-allocation questions across many products (BCG-matrix territory) → name it, note it needs per-product market-share and growth data, and run it only if that data is supplied.
28
+ The user asked for a framework by name and it fits → run it. It doesn't fit → run the framework they asked for, in full (a SWOT still arrives as TOWS), because they asked for it by name. Then say in two or three sentences which framework fits the question better and what it would add — a "SWOT" request that's really "should we enter this market" is Five Forces work — and offer to run it. Don't replace or shorten what they asked for. Portfolio-allocation questions across many products (BCG-matrix territory) → name it, note it needs per-product market-share and growth data, and run it only if that data is supplied.
21
29
 
22
30
  2. **Collect the evidence base before filling anything.** Name what is known `[data: …]`, reported `[reported by …]`, drawn from general market knowledge `[market: …]`, and assumed `[assumption]`. The `[market: …]` tag exists because on a short prompt most cells are filled from the model's own market knowledge — that's legitimate, but it must stay distinguishable from the user's facts and from guesses. Ask at most 2 questions, spent on the decision the analysis feeds ("what decision does this inform, and by when?") and the competitive set ("who do customers actually compare you to?"). No decision named → the analysis has no ranking criterion; get one before proceeding. Non-interactive run (no user to ask): derive the most plausible decision from the input, state it as `[assumption]` at the top, and rank against it; none derivable → emit `BLOCKED: need the decision this analysis feeds` rather than an unranked survey.
23
31
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "strategy-analysis",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Run a strategy framework — SWOT/TOWS, Porter's Five Forces, or PESTLE — on a product, company, or market question, choosing the right framework for the question and forcing every cell to carry evidence and a so-what. Use when the user asks for a SWOT, a competitive/market analysis, \"should we enter this market\", \"what's our position against X\", or a macro-environment scan.",
5
5
  "entrypoint": "SKILL.md",
6
6
  "deps": { "npm": [], "pip": [] },
@@ -9,6 +9,14 @@ Maps what one customer experiences on the way to one outcome — outside-in, fro
9
9
 
10
10
  ## How to respond
11
11
 
12
+ **Four rules come before the steps and outrank them:**
13
+
14
+ - **Answer what was asked, first.** Open with the answer, the decision or the artifact, in plain words. Scores, matrices, frameworks and tags come after it, and anything that doesn't change the answer is cut.
15
+ - **Use only what you were given.** Don't add facts, names, numbers, incidents, history, steps or sections the input doesn't contain. What you need and don't have is left out of the artifact and listed once at the end under "To confirm".
16
+ - **Deliver from what you have.** When the request gives you something to work on, state your assumptions in a line and produce the result. When it gives you nothing to work on, ask for it in one or two plain sentences and say what you will do once you have it.
17
+ - **Write for someone who has never heard of this skill.** No skill names, no paths or scripts from this folder, no internal terms, and nothing about how the run was set up. A next step is one plain sentence at the end that describes the work.
18
+ - **For this skill:** Call the map a hypothesis when it isn't built on research. Scores on the emotion arc show its shape; say once that they are estimates, and build the persona only from what the user told you.
19
+
12
20
  1. **Anchor persona, outcome, and evidence level.** Ask at most 2 questions, spent on the weakest anchors: *"whose journey — one specific persona?"* and *"what outcome are they trying to reach?"* No persona or outcome → don't draft; a journey for "users" toward "using the product" has no stage boundaries. Non-interactive run (no user to ask): derive a specific persona and outcome from the input if defensible and tag them `[assumption]`; underivable → emit `BLOCKED: need persona + outcome` naming both. Tag the whole map's **evidence level**: `[observational]` (interviews, session recordings), `[survey/analytics]`, or `[assumption-based]` (team hypothesis). Assumption-based is legitimate — it's a hypothesis that directs research — but it must say so at the top, not masquerade as findings.
13
21
 
14
22
  2. **Fix the journey's edges.** Start trigger (the event that puts the persona on this path — in their life, not on your site: ✅ *"payroll fails on the last Friday of the month"*) and end state (what "done" means *to the persona* — ❌ "completes checkout" if their outcome is "salary problem solved"). Wrong edges are the most common defect: starting at the landing page amputates the discovery pain, ending at purchase hides the abandonment cliff in activation.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "user-journey-map",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Map a customer's end-to-end journey toward an outcome — 3–6 stages, each with actions, emotions, pains, and opportunities, plus a rendered Mermaid emotion arc and the ranked pain points design should attack first. Use when the user wants a journey map, customer experience map, \"map the user's path through onboarding\", touchpoint analysis, or \"where do users feel friction\".",
5
5
  "entrypoint": "SKILL.md",
6
6
  "deps": { "npm": [], "pip": [] },
@@ -19,6 +19,14 @@ the evidence in the first place, plan it with `research-plan` and summarise sour
19
19
 
20
20
  ## How to respond
21
21
 
22
+ **Four rules come before the steps and outrank them:**
23
+
24
+ - **Answer what was asked, first.** Open with the answer, the decision or the artifact, in plain words. Scores, matrices, frameworks and tags come after it, and anything that doesn't change the answer is cut.
25
+ - **Use only what you were given.** Don't add facts, names, numbers, incidents, history, steps or sections the input doesn't contain. What you need and don't have is left out of the artifact and listed once at the end under "To confirm".
26
+ - **Deliver from what you have.** When the request gives you something to work on, state your assumptions in a line and produce the result. When it gives you nothing to work on, ask for it in one or two plain sentences and say what you will do once you have it.
27
+ - **Write for someone who has never heard of this skill.** No skill names, no paths or scripts from this folder, no internal terms, and nothing about how the run was set up. A next step is one plain sentence at the end that describes the work.
28
+ - **For this skill:** End on the hypothesis the evidence favours, with your confidence, when one is ahead; a tie is for when the evidence really is even. Check shares against absolute numbers before scoring: a stable share of a larger total is a rise.
29
+
22
30
  1. **Ask once for what's missing.** You need three things: the **observation** to explain,
23
31
  stated as a fact with a time and a size (✅ *"Mobile conversion fell 18% from 8 Sep"* — ❌
24
32
  *"sales are weird"*); the **evidence** the user has; and any **hypotheses** already on the
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hypothesis-comparison",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Compare rival explanations for an observation with analysis of competing hypotheses (ACH) — list the hypotheses and the evidence, build a consistency matrix (consistent / inconsistent / neutral), rank hypotheses by how little evidence contradicts them rather than how much supports them, name the diagnostic evidence and the linchpins, and say which next observation would tell the leaders apart. Use when the user asks \"why did X happen\", \"which explanation fits the evidence\", \"what's really causing this\", wants to stop arguing over a favourite theory, or says \"compare these hypotheses\", \"competing explanations\", \"ACH\".",
5
5
  "entrypoint": "SKILL.md",
6
6
  "deps": {
@@ -18,6 +18,14 @@ a brief for another skill rather than findings, use `brief-intake`.
18
18
 
19
19
  ## How to respond
20
20
 
21
+ **Four rules come before the steps and outrank them:**
22
+
23
+ - **Answer what was asked, first.** Open with the answer, the decision or the artifact, in plain words. Scores, matrices, frameworks and tags come after it, and anything that doesn't change the answer is cut.
24
+ - **Use only what you were given.** Don't add facts, names, numbers, incidents, history, steps or sections the input doesn't contain. What you need and don't have is left out of the artifact and listed once at the end under "To confirm".
25
+ - **Deliver from what you have.** When the request gives you something to work on, state your assumptions in a line and produce the result. When it gives you nothing to work on, ask for it in one or two plain sentences and say what you will do once you have it.
26
+ - **Write for someone who has never heard of this skill.** No skill names, no paths or scripts from this folder, no internal terms, and nothing about how the run was set up. A next step is one plain sentence at the end that describes the work.
27
+ - **For this skill:** The reply itself carries the answer: the recommendation, the numbers behind it and the caveats. Saved files are extra. Don't report that your own checks passed.
28
+
21
29
  1. **Ask once for what's missing.** You need the **sources** themselves (text, files or
22
30
  excerpts, not titles) and the **question** the synthesis answers. If the user has a
23
31
  research plan, take the question and sub-questions from it. Ask for both in one message.
@@ -14,6 +14,36 @@
14
14
  "Does not add facts, benchmarks or figures that are not in the three sources, unless tagged [outside]",
15
15
  "Runs or recommends the citation checker and reports its result"
16
16
  ]
17
+ },
18
+ {
19
+ "id": 2,
20
+ "held_out": "2026-10-05",
21
+ "prompt": "We're a 45-person architecture practice and the directors are split on the 3-days-in-the-studio rule. Everything we have is in this folder: staff-survey-summary.md, badge-data.md, exit-interviews.md, director-email.md and practice-weekly-article.md. Can you pull it together for Thursday's directors' meeting? The choice is keep 3 days, drop to 2, or go up to 4 like Lucian wants. And tell me what changing it would do to retention.",
22
+ "assertions": [
23
+ "It corrects the claim that productivity is down 20%: the Castellan survey found 20% of managers believed productivity had fallen (and 34% believed it had risen), and it measured perceptions, not output",
24
+ "It treats Lucian's email and the Practice Weekly article as resting on the same Castellan survey, not as two independent pieces of evidence",
25
+ "It notes the Castellan fieldwork dates from October–November 2021 and treats it as dated or weak evidence for a 2026 decision",
26
+ "It points out that the Q1 answers in the staff survey add up to 40 (27 + 9 + 4) against 38 stated responses",
27
+ "It states that actual attendance already averages 2.4 days a week, below the 3-day rule, with 14 of 45 staff averaging 3 or more days",
28
+ "On retention it says the material cannot answer the question: three leavers, only one of whom (the technologist who moved to Bristol) linked leaving to office days; it gives no predicted retention effect",
29
+ "Each finding names the file it comes from, and the findings are grouped by topic, not written as one summary per file",
30
+ "It does not bring in studies, statistics or claims about hybrid working that are not in the five files"
31
+ ]
32
+ },
33
+ {
34
+ "id": 3,
35
+ "held_out": "2026-10-05",
36
+ "prompt": "I talked to five cafe owners last week about whether they'd pay for our stock-ordering app. My notes are rubbish, sorry, here's what I've got:\n\n- Marta, Kiln St Coffee (2 sites). Orders by WhatsApp to 3 suppliers. Forgets oat milk 'every other week'. Said 'I'd try it'. Asked if it works with her till (Lumo), I didn't know.\n- Joss, The Larder. Does the ordering Sunday nights, takes about 2 hrs. 'If it saved me an hour I'd pay, maybe £30 a month?'\n- Dee, Dee's. Happy with her spreadsheet, 'not a problem for me'. But said her friend who runs a bakery would def pay £50/mo.\n- Priyank, Corner Cup. Ran out of time, he mostly talked about a supplier delivering late. Didn't get to the app.\n- can't find my notes for the fifth one. think it was positive\n\nCan you pull together what we learned? Do they want it, and what should we charge?",
37
+ "assertions": [
38
+ "It delivers the write-up from the notes as given and does not stop to ask for better notes first",
39
+ "It says only one owner, Joss, named a price they would pay (about £30 a month, said tentatively and conditional on saving an hour)",
40
+ "It does not treat the £50 a month figure as evidence of willingness to pay: it is Dee's second-hand remark about a bakery owner who was not interviewed",
41
+ "It says Dee does not see ordering as a problem and that Priyank's conversation never reached the app, so at most two of the four noted conversations show interest",
42
+ "The fifth conversation is treated as no evidence because the notes are missing; 'think it was positive' is not counted as a positive result",
43
+ "Marta's 'I'd try it' is reported as interest in trying, not as agreement to pay",
44
+ "It says five conversations are too few to set a price or to conclude that cafe owners want it, and gives any price suggestion as tentative",
45
+ "It does not add market figures, competitor prices or cafe-industry facts that are not in the notes"
46
+ ]
17
47
  }
18
48
  ]
19
49
  }
@@ -0,0 +1,27 @@
1
+ # Studio door badge data
2
+
3
+ Pulled by Odette Marsh from the access system. Covers 8 weeks, Monday 5 January to
4
+ Friday 27 February 2026. 45 staff.
5
+
6
+ ## Average attendance
7
+
8
+ Average days in the studio per person per week: **2.4**
9
+
10
+ Staff who averaged 3 or more days a week over the period: **14 of 45**
11
+
12
+ ## By weekday (share of staff badged in, average over the 8 weeks)
13
+
14
+ | Day | Share in |
15
+ |---|---|
16
+ | Monday | 31% |
17
+ | Tuesday | 74% |
18
+ | Wednesday | 77% |
19
+ | Thursday | 40% |
20
+ | Friday | 18% |
21
+
22
+ ## Caveats
23
+
24
+ - The reader misses anyone let in by a colleague. Facilities think the undercount is small
25
+ but nobody has measured it.
26
+ - The period includes no school holidays.
27
+ - Site visits and client offices are not recorded, so a day on site looks like a day at home.
@@ -0,0 +1,16 @@
1
+ From: Lucian Farrow
2
+ To: Directors
3
+ Date: 2 March 2026
4
+ Subject: Office days, my view before the meeting
5
+
6
+ All,
7
+
8
+ I'll be blunt. Productivity is down 20% since hybrid. It's in the Castellan research, see
9
+ the Practice Weekly piece I forwarded. That is a fifth of our output gone.
10
+
11
+ I also hear from two clients that they like seeing the team together when they visit.
12
+
13
+ Three days is not working. I want us at four days from the summer, with Friday as the
14
+ flexible day.
15
+
16
+ Lucian
@@ -0,0 +1,17 @@
1
+ # Exit interview notes, September 2025 to February 2026
2
+
3
+ Notes taken by Odette Marsh. Three people left in the period.
4
+
5
+ ## Leaver A, Part 2 assistant, left October 2025
6
+
7
+ Went to a larger practice for a higher salary. Asked about office days: "fine, didn't
8
+ bother me". Main reason given: pay.
9
+
10
+ ## Leaver B, senior architectural technologist, left January 2026
11
+
12
+ Moved to Bristol for family reasons. Said: "Three days in made it impossible to stay on
13
+ after the move. Two I could have done." Main reason given: relocation.
14
+
15
+ ## Leaver C, associate, left February 2026
16
+
17
+ Left to set up their own practice. Office days were not discussed.
@@ -0,0 +1,21 @@
1
+ # Is hybrid hurting studios?
2
+
3
+ Practice Weekly, 9 February 2026. By Ines Calloway.
4
+
5
+ Five years on from the first lockdowns, studio principals are still arguing about how many
6
+ days their teams should be at their desks.
7
+
8
+ The most widely quoted figures come from the Castellan Institute's Workplace Pulse survey.
9
+ Castellan questioned 1,200 managers at professional-services firms. Fieldwork ran in October
10
+ and November 2021. Asked how their team's productivity had changed since moving to hybrid
11
+ working, 20% of managers said they believed it had fallen, 46% said it had not changed and
12
+ 34% said they believed it had risen. The survey recorded managers' perceptions. It did not
13
+ measure output.
14
+
15
+ Castellan did not publish a breakdown for architecture practices.
16
+
17
+ "You cannot teach someone to detail a junction over a video call," said one studio principal
18
+ who asked not to be named. Another said her practice had dropped its fixed days altogether
19
+ and "nobody noticed, except the people who used to commute two hours".
20
+
21
+ No newer wave of the survey has been published.
@@ -0,0 +1,41 @@
1
+ # Staff survey on office days: summary
2
+
3
+ Compiled by Odette Marsh, studio manager, 12 March 2026.
4
+ Sent to all 45 staff. 38 responses. Anonymous.
5
+
6
+ ## Q1. How many days a week would you choose to be in the studio?
7
+
8
+ | Answer | Responses |
9
+ |---|---|
10
+ | 2 or fewer | 27 |
11
+ | 3 | 9 |
12
+ | 4 or 5 | 4 |
13
+
14
+ ## Q2. "The 3-day rule helps me do my job well."
15
+
16
+ | Answer | Responses |
17
+ |---|---|
18
+ | Agree | 11 |
19
+ | Neutral | 9 |
20
+ | Disagree | 18 |
21
+
22
+ ## Q3. Main reason you come in (pick one)
23
+
24
+ | Answer | Responses |
25
+ |---|---|
26
+ | Design reviews and crits | 19 |
27
+ | Mentoring / being mentored | 8 |
28
+ | Client meetings | 7 |
29
+ | Home is not a good place to work | 4 |
30
+
31
+ ## Free text
32
+
33
+ - 7 respondents identified themselves as Part 1 or Part 2 assistants. 6 of those 7 wrote
34
+ that they learn more on days when senior staff are in.
35
+ - "Tuesdays are great. Fridays I sit on my own with my headphones on."
36
+ - "I'd come in more if I knew my team would be there."
37
+ - "Three days is fine, it's being told which three I mind."
38
+
39
+ ## Limits
40
+
41
+ No breakdown by team or seniority beyond the assistants who identified themselves.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "source-synthesis",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Synthesise a set of supplied sources — papers, articles, reports, interview transcripts — into findings where every claim is cited to a source and a location ([S1:p4]), agreement and disagreement across sources are explicit, each finding carries an evidence-strength rating with the criteria used, and the gaps and what the sources do not say are listed. Never adds outside facts unless tagged as such, and ships a citation checker. Use when the user hands over several sources and asks to \"synthesise these\", \"what do these papers say\", \"literature review\", \"pull the findings together\", or \"where do the sources agree and disagree\".",
5
5
  "entrypoint": "SKILL.md",
6
6
  "deps": {
@@ -9,6 +9,14 @@ Designs the storage layer **from the queries backward** — because a schema is
9
9
 
10
10
  ## How to respond
11
11
 
12
+ **Four rules come before the steps and outrank them:**
13
+
14
+ - **Answer what was asked, first.** Open with the answer, the decision or the artifact, in plain words. Scores, matrices, frameworks and tags come after it, and anything that doesn't change the answer is cut.
15
+ - **Use only what you were given.** Don't add facts, names, numbers, incidents, history, steps or sections the input doesn't contain. What you need and don't have is left out of the artifact and listed once at the end under "To confirm".
16
+ - **Deliver from what you have.** When the request gives you something to work on, state your assumptions in a line and produce the result. When it gives you nothing to work on, ask for it in one or two plain sentences and say what you will do once you have it.
17
+ - **Write for someone who has never heard of this skill.** No skill names, no paths or scripts from this folder, no internal terms, and nothing about how the run was set up. A next step is one plain sentence at the end that describes the work.
18
+ - **For this skill:** Give DDL that runs, and the query for each access pattern the user named. Leave out multitenancy, partitioning, rollups and reconciliation unless they asked or a named query needs them.
19
+
12
20
  1. **Collect the access patterns before drawing a single table.** The deliverable starts as a list: each read and write the feature needs, with **frequency**, **latency sensitivity**, **selectivity** (one row / a range / a scan), and **consistency need** (read-your-writes? eventual ok?). Ask at most 2 questions, spent on the highest-frequency query and the largest-growth entity. A schema designed from the entity diagram instead of the queries is how you get a clean model that can't serve its hottest path.
13
21
 
14
22
  2. **Choose the paradigm deliberately, with a reason** (selection matrix in [`reference.md`](reference.md)). Relational is the correct default for most transactional features and needs no defense; reaching *past* it does. ✅ *"Document store — the entity is read and written whole, no cross-entity queries, and the shape varies per type"* — ❌ *"NoSQL because scale"* (scale is a property of access patterns and data size, not a vibe). For NoSQL especially, the access patterns *are* the schema — you cannot add a query later for free the way SQL lets you.
@@ -11,6 +11,35 @@
11
11
  "Every index maps to a real predicate from the listed queries rather than being speculative",
12
12
  "Denormalization, where proposed, names the read it serves and the write cost it adds"
13
13
  ]
14
+ },
15
+ {
16
+ "id": 2,
17
+ "held_out": "2026-10-05",
18
+ "prompt": "We're rebuilding the booking system for our vet clinics and I need the database tables designed properly this time. My notes on what it has to do are in notes.md and the tables we have today are in current_tables.sql. Can you give me the new schema, with the SQL to create it and the queries for the screens and the report?",
19
+ "assertions": [
20
+ "It includes CREATE TABLE statements for the new schema, with owners and pets as their own tables instead of the owner_name, owner_phone and pet_name columns repeated on each appointment",
21
+ "Double-booking a vet is prevented by a database constraint that handles appointments of different lengths (for example an exclusion constraint on a time range, or one row per time slot with a unique key), not only by an application check or by a unique key on vet and start time alone",
22
+ "Cancelled appointments are excluded from that constraint, so a cancelled time can be booked again",
23
+ "It points out that the notes say Postgres 15 while the contractor says the current app runs on MySQL 8, and states which one the SQL is written for",
24
+ "Prices are stored as an exact type (integer cents or a decimal/numeric), not FLOAT, and the price is modelled per appointment type per clinic",
25
+ "Appointment times are stored with a time zone or in UTC with each clinic's time zone recorded, and it notes that storing Sydney local time is wrong for the Brisbane clinics",
26
+ "It says the no-show report cannot be produced from the current statuses (booked, cancelled, completed) and adds a no-show status or an equivalent field",
27
+ "It gives a query or a named index for the vet's-day screen that leads on the vet and the appointment start time, and does not add tables for invoicing, payments, stock or clinical records"
28
+ ]
29
+ },
30
+ {
31
+ "id": 3,
32
+ "held_out": "2026-10-05",
33
+ "prompt": "need somewhere to store sensor readings from our greenhouses. about 200 sensors, each does temperature + humidity, a reading every minute or so I think. I want to chart the last 24h for any one sensor and get an alert when something goes out of range. haven't picked a database yet. what tables do I need?",
34
+ "assertions": [
35
+ "It gives concrete table definitions (SQL or an equivalent column-by-column layout) in the reply, and does not stop to ask questions before delivering them",
36
+ "The readings table has a key or index on the sensor and the reading time together, and the reply ties it to the last-24-hours chart for one sensor",
37
+ "It works out the volume from the numbers given: about 288,000 readings a day (roughly 105 million a year) at one reading per sensor per minute, or an equivalent calculation",
38
+ "It names a database to use, or says which one it assumed, with a reason linked to the chart and alert queries",
39
+ "It says how long readings should be kept is not known and lists it as something to decide, without stating a retention period as if it had been given",
40
+ "It stores the allowed range somewhere (per sensor, per greenhouse or per sensor type) and says the actual range values were not given; any numbers shown are labelled as examples",
41
+ "Reading times are stored with a time zone or in UTC"
42
+ ]
14
43
  }
15
44
  ]
16
45
  }
@@ -0,0 +1,29 @@
1
+ -- Dump of the tables the current booking app uses. Schema only.
2
+ -- NOTE (Devraj): all times are stored as Sydney local time, for every clinic.
3
+
4
+ CREATE TABLE clinics (
5
+ id INT AUTO_INCREMENT PRIMARY KEY,
6
+ name VARCHAR(80) NOT NULL,
7
+ city VARCHAR(40) NOT NULL
8
+ );
9
+
10
+ CREATE TABLE vets (
11
+ id INT AUTO_INCREMENT PRIMARY KEY,
12
+ full_name VARCHAR(120) NOT NULL,
13
+ clinic_id INT NOT NULL -- home clinic only
14
+ );
15
+
16
+ CREATE TABLE appointments (
17
+ id INT AUTO_INCREMENT PRIMARY KEY,
18
+ clinic_id INT NOT NULL,
19
+ vet_id INT NOT NULL,
20
+ appt_time DATETIME NOT NULL, -- start time, Sydney local
21
+ appt_type VARCHAR(40) NOT NULL, -- free text: 'consult', 'Consult', 'vacc', ...
22
+ price FLOAT,
23
+ owner_name VARCHAR(120),
24
+ owner_phone VARCHAR(40),
25
+ pet_name VARCHAR(80),
26
+ status VARCHAR(20) NOT NULL -- 'booked', 'cancelled', 'completed'
27
+ );
28
+
29
+ -- no indexes other than the primary keys