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.
- package/README.md +2 -1
- package/catalogue.json +10 -1
- package/model-routing.json +12 -0
- package/package.json +1 -1
- package/packs/ai-engineering/skills/agent-adoption-stage/SKILL.md +8 -0
- package/packs/ai-engineering/skills/agent-adoption-stage/manifest.json +1 -1
- package/packs/ai-engineering/skills/agent-loop-design/SKILL.md +8 -0
- package/packs/ai-engineering/skills/agent-loop-design/manifest.json +1 -1
- package/packs/ai-engineering/skills/ai-readiness-assessment/SKILL.md +8 -0
- package/packs/ai-engineering/skills/ai-readiness-assessment/manifest.json +1 -1
- package/packs/ai-engineering/skills/ai-usage-policy/SKILL.md +8 -0
- package/packs/ai-engineering/skills/ai-usage-policy/evals/evals.json +30 -0
- package/packs/ai-engineering/skills/ai-usage-policy/evals/files/2/data-handling-sheet.md +18 -0
- package/packs/ai-engineering/skills/ai-usage-policy/evals/files/2/it-notes.md +31 -0
- package/packs/ai-engineering/skills/ai-usage-policy/evals/files/2/md-email.md +29 -0
- package/packs/ai-engineering/skills/ai-usage-policy/manifest.json +1 -1
- package/packs/ai-engineering/skills/llm-eval-harness/SKILL.md +8 -0
- package/packs/ai-engineering/skills/llm-eval-harness/manifest.json +1 -1
- package/packs/ai-engineering/skills/subagent-design/SKILL.md +8 -0
- package/packs/ai-engineering/skills/subagent-design/manifest.json +1 -1
- package/packs/api-builder/skills/eval-harness-generator/SKILL.md +8 -0
- package/packs/api-builder/skills/eval-harness-generator/manifest.json +1 -1
- package/packs/api-builder/skills/tool-use-schema-writer/SKILL.md +8 -0
- package/packs/api-builder/skills/tool-use-schema-writer/evals/evals.json +29 -0
- package/packs/api-builder/skills/tool-use-schema-writer/evals/files/2/book_appointment.ts +64 -0
- package/packs/api-builder/skills/tool-use-schema-writer/manifest.json +1 -1
- package/packs/career/loops/apply/LOOP.md +88 -0
- package/packs/career/loops/apply/evals/eval_queries.json +9 -0
- package/packs/career/loops/apply/evals/evals.json +27 -0
- package/packs/career/loops/apply/loop.json +46 -0
- package/packs/career/pack.json +57 -0
- package/packs/career/skills/cover-letter/SKILL.md +132 -0
- package/packs/career/skills/cover-letter/evals/eval_queries.json +34 -0
- package/packs/career/skills/cover-letter/evals/evals.json +100 -0
- package/packs/career/skills/cover-letter/evals/files/1/posting.md +28 -0
- package/packs/career/skills/cover-letter/evals/files/1/resume.md +35 -0
- package/packs/career/skills/cover-letter/evals/files/2/posting.md +20 -0
- package/packs/career/skills/cover-letter/evals/files/2/resume.md +32 -0
- package/packs/career/skills/cover-letter/evals/files/4/posting.md +19 -0
- package/packs/career/skills/cover-letter/evals/files/4/resume.md +26 -0
- package/packs/career/skills/cover-letter/evals/files/5/posting.md +21 -0
- package/packs/career/skills/cover-letter/evals/files/5/resume.md +32 -0
- package/packs/career/skills/cover-letter/evals/files/6/posting.md +25 -0
- package/packs/career/skills/cover-letter/evals/files/6/resume.md +29 -0
- package/packs/career/skills/cover-letter/evals/files/7/posting.md +18 -0
- package/packs/career/skills/cover-letter/evals/files/7/resume.md +23 -0
- package/packs/career/skills/cover-letter/manifest.json +37 -0
- package/packs/career/skills/cover-letter/scripts/claim_check.py +247 -0
- package/packs/career/skills/job-fit-analysis/SKILL.md +136 -0
- package/packs/career/skills/job-fit-analysis/evals/eval_queries.json +34 -0
- package/packs/career/skills/job-fit-analysis/evals/evals.json +76 -0
- package/packs/career/skills/job-fit-analysis/evals/files/1/posting.md +28 -0
- package/packs/career/skills/job-fit-analysis/evals/files/1/resume.md +35 -0
- package/packs/career/skills/job-fit-analysis/evals/files/2/posting.md +20 -0
- package/packs/career/skills/job-fit-analysis/evals/files/2/resume.md +32 -0
- package/packs/career/skills/job-fit-analysis/evals/files/4/posting.md +25 -0
- package/packs/career/skills/job-fit-analysis/evals/files/4/resume.md +29 -0
- package/packs/career/skills/job-fit-analysis/evals/files/5/posting.md +18 -0
- package/packs/career/skills/job-fit-analysis/evals/files/5/resume.md +23 -0
- package/packs/career/skills/job-fit-analysis/manifest.json +31 -0
- package/packs/career/skills/resume-tailor/SKILL.md +116 -0
- package/packs/career/skills/resume-tailor/evals/eval_queries.json +34 -0
- package/packs/career/skills/resume-tailor/evals/evals.json +105 -0
- package/packs/career/skills/resume-tailor/evals/files/1/posting.md +26 -0
- package/packs/career/skills/resume-tailor/evals/files/1/resume.md +32 -0
- package/packs/career/skills/resume-tailor/evals/files/2/posting.md +19 -0
- package/packs/career/skills/resume-tailor/evals/files/2/resume.md +26 -0
- package/packs/career/skills/resume-tailor/evals/files/3/posting.md +21 -0
- package/packs/career/skills/resume-tailor/evals/files/3/resume.md +32 -0
- package/packs/career/skills/resume-tailor/evals/files/4/posting.md +28 -0
- package/packs/career/skills/resume-tailor/evals/files/4/resume.md +35 -0
- package/packs/career/skills/resume-tailor/evals/files/5/posting.md +20 -0
- package/packs/career/skills/resume-tailor/evals/files/5/resume.md +32 -0
- package/packs/career/skills/resume-tailor/evals/files/6/posting.md +25 -0
- package/packs/career/skills/resume-tailor/evals/files/6/resume.md +29 -0
- package/packs/career/skills/resume-tailor/evals/files/7/posting.md +18 -0
- package/packs/career/skills/resume-tailor/evals/files/7/resume.md +23 -0
- package/packs/career/skills/resume-tailor/manifest.json +37 -0
- package/packs/career/skills/resume-tailor/scripts/claim_check.py +247 -0
- package/packs/converters/skills/file-to-markdown/SKILL.md +8 -0
- package/packs/converters/skills/file-to-markdown/manifest.json +1 -1
- package/packs/converters/skills/md-to-html/SKILL.md +8 -0
- package/packs/converters/skills/md-to-html/manifest.json +1 -1
- package/packs/converters/skills/mermaid-render/SKILL.md +8 -0
- package/packs/converters/skills/mermaid-render/manifest.json +1 -1
- package/packs/core/skills/output-hygiene/SKILL.md +8 -0
- package/packs/core/skills/output-hygiene/manifest.json +1 -1
- package/packs/data-analytics/skills/metric-definition/SKILL.md +8 -0
- package/packs/data-analytics/skills/metric-definition/evals/evals.json +30 -0
- package/packs/data-analytics/skills/metric-definition/evals/files/2/tables.md +42 -0
- package/packs/data-analytics/skills/metric-definition/evals/files/2/thread.md +40 -0
- package/packs/data-analytics/skills/metric-definition/manifest.json +1 -1
- package/packs/design/skills/deck-builder/SKILL.md +8 -0
- package/packs/design/skills/deck-builder/manifest.json +1 -1
- package/packs/dev-team/skills/agents-md-generator/SKILL.md +8 -0
- package/packs/dev-team/skills/agents-md-generator/manifest.json +1 -1
- package/packs/dev-team/skills/contribution-wizard/SKILL.md +8 -0
- package/packs/dev-team/skills/contribution-wizard/evals/evals.json +29 -0
- package/packs/dev-team/skills/contribution-wizard/evals/files/2/AGENTS.md +9 -0
- package/packs/dev-team/skills/contribution-wizard/evals/files/2/CATALOG.md +18 -0
- package/packs/dev-team/skills/contribution-wizard/evals/files/2/CONTRIBUTING.md +45 -0
- package/packs/dev-team/skills/contribution-wizard/evals/files/2/OWNERS.md +7 -0
- package/packs/dev-team/skills/contribution-wizard/evals/files/2/skills/detention-claim-letter/INSTRUCTIONS.md +20 -0
- package/packs/dev-team/skills/contribution-wizard/evals/files/2/skills/detention-claim-letter/skill.yaml +11 -0
- package/packs/dev-team/skills/contribution-wizard/evals/files/2/skills/detention-claim-letter/tests/cases.yaml +25 -0
- package/packs/dev-team/skills/contribution-wizard/evals/files/2/skills/rate-con-extractor/INSTRUCTIONS.md +20 -0
- package/packs/dev-team/skills/contribution-wizard/evals/files/2/skills/rate-con-extractor/skill.yaml +8 -0
- package/packs/dev-team/skills/contribution-wizard/evals/files/2/skills/rate-con-extractor/tests/cases.yaml +32 -0
- package/packs/dev-team/skills/contribution-wizard/manifest.json +1 -1
- package/packs/dev-team/skills/devils-advocate/SKILL.md +8 -0
- package/packs/dev-team/skills/devils-advocate/evals/evals.json +29 -0
- package/packs/dev-team/skills/devils-advocate/evals/files/2/signups.py +116 -0
- package/packs/dev-team/skills/devils-advocate/evals/files/2/test_signups.py +69 -0
- package/packs/dev-team/skills/devils-advocate/manifest.json +1 -1
- package/packs/dev-team/skills/pre-merge-review/SKILL.md +8 -0
- package/packs/dev-team/skills/pre-merge-review/manifest.json +1 -1
- package/packs/dev-team/skills/release-notes/SKILL.md +8 -0
- package/packs/dev-team/skills/release-notes/evals/evals.json +29 -0
- package/packs/dev-team/skills/release-notes/evals/files/2/commits.txt +35 -0
- package/packs/dev-team/skills/release-notes/manifest.json +1 -1
- package/packs/product-manager/skills/prfaq/SKILL.md +8 -0
- package/packs/product-manager/skills/prfaq/manifest.json +1 -1
- package/packs/product-manager/skills/strategy-analysis/SKILL.md +9 -1
- package/packs/product-manager/skills/strategy-analysis/manifest.json +1 -1
- package/packs/product-manager/skills/user-journey-map/SKILL.md +8 -0
- package/packs/product-manager/skills/user-journey-map/manifest.json +1 -1
- package/packs/research/skills/hypothesis-comparison/SKILL.md +8 -0
- package/packs/research/skills/hypothesis-comparison/manifest.json +1 -1
- package/packs/research/skills/source-synthesis/SKILL.md +8 -0
- package/packs/research/skills/source-synthesis/evals/evals.json +30 -0
- package/packs/research/skills/source-synthesis/evals/files/2/badge-data.md +27 -0
- package/packs/research/skills/source-synthesis/evals/files/2/director-email.md +16 -0
- package/packs/research/skills/source-synthesis/evals/files/2/exit-interviews.md +17 -0
- package/packs/research/skills/source-synthesis/evals/files/2/practice-weekly-article.md +21 -0
- package/packs/research/skills/source-synthesis/evals/files/2/staff-survey-summary.md +41 -0
- package/packs/research/skills/source-synthesis/manifest.json +1 -1
- package/packs/solution-architect/skills/db-schema-design/SKILL.md +8 -0
- package/packs/solution-architect/skills/db-schema-design/evals/evals.json +29 -0
- package/packs/solution-architect/skills/db-schema-design/evals/files/2/current_tables.sql +29 -0
- package/packs/solution-architect/skills/db-schema-design/evals/files/2/notes.md +53 -0
- package/packs/solution-architect/skills/db-schema-design/manifest.json +1 -1
- package/packs/solution-architect/skills/design-doc/SKILL.md +8 -0
- package/packs/solution-architect/skills/design-doc/evals/evals.json +29 -0
- package/packs/solution-architect/skills/design-doc/evals/files/2/brief.md +18 -0
- package/packs/solution-architect/skills/design-doc/evals/files/2/eng-notes.md +30 -0
- package/packs/solution-architect/skills/design-doc/manifest.json +1 -1
- package/packs/solution-architect/skills/figma-diagrams/SKILL.md +8 -0
- package/packs/solution-architect/skills/figma-diagrams/manifest.json +1 -1
- package/packs/solution-architect/skills/tech-comparison-matrix/SKILL.md +8 -0
- package/packs/solution-architect/skills/tech-comparison-matrix/evals/evals.json +29 -0
- package/packs/solution-architect/skills/tech-comparison-matrix/evals/files/2/requirements.md +20 -0
- package/packs/solution-architect/skills/tech-comparison-matrix/evals/files/2/vendor-notes.md +29 -0
- package/packs/solution-architect/skills/tech-comparison-matrix/manifest.json +1 -1
- package/packs/sre-oncall/skills/delivery-metrics-report/SKILL.md +8 -0
- package/packs/sre-oncall/skills/delivery-metrics-report/manifest.json +1 -1
- package/packs/sre-oncall/skills/postmortem-generator/SKILL.md +8 -0
- package/packs/sre-oncall/skills/postmortem-generator/evals/evals.json +30 -0
- package/packs/sre-oncall/skills/postmortem-generator/evals/files/2/pager-export.txt +22 -0
- package/packs/sre-oncall/skills/postmortem-generator/evals/files/2/slack-thread.txt +28 -0
- package/packs/sre-oncall/skills/postmortem-generator/manifest.json +1 -1
- package/packs/stakeholder-comms/skills/guide-builder/SKILL.md +8 -0
- package/packs/stakeholder-comms/skills/guide-builder/evals/evals.json +29 -0
- package/packs/stakeholder-comms/skills/guide-builder/evals/files/2/api-notes.md +44 -0
- package/packs/stakeholder-comms/skills/guide-builder/evals/files/2/sample-booking.json +19 -0
- package/packs/stakeholder-comms/skills/guide-builder/manifest.json +1 -1
- package/profiles.json +2 -2
|
@@ -14,6 +14,36 @@
|
|
|
14
14
|
"Includes at least three runnable sanity checks, including a known-answer fixture or a reconciliation with billing",
|
|
15
15
|
"Does not invent tables, columns or an owner not given in the prompt; anything assumed is tagged [assumption] and listed under open decisions"
|
|
16
16
|
]
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"id": 2,
|
|
20
|
+
"held_out": "2026-10-05",
|
|
21
|
+
"prompt": "Finance and CX keep turning up to the Monday meeting with different refund rates and it's getting silly. I've pasted the Slack thread into thread.md and the table descriptions into tables.md. Can you write down one proper definition of refund rate that we can all use, with the SQL? We're on Postgres.",
|
|
22
|
+
"assertions": [
|
|
23
|
+
"It separates the share of orders refunded from the share of revenue refunded as two differently named measures, or picks one as 'refund rate' and names the other as a separate measure; it does not blend them into one formula",
|
|
24
|
+
"It points out that 312 refunded orders out of 7,480 is about 4.2%, not the 4.6% quoted in the thread",
|
|
25
|
+
"The order-based SQL counts each refunded order once (COUNT DISTINCT on order_id, EXISTS, or refunds aggregated per order before joining), so orders with several refund rows are not double-counted",
|
|
26
|
+
"It states one rule for which month a refund belongs to (the order's month or the refund's month) and says what happens to a February order refunded in March",
|
|
27
|
+
"It says a single money-based rate across both stores cannot be computed from these tables as they stand because there is no exchange-rate data, and it does not invent an exchange rate or an exchange-rate table",
|
|
28
|
+
"Test orders are excluded with a condition on orders.is_test, and staff orders are flagged as not identifiable from the listed columns; it does not use a staff flag column that does not exist",
|
|
29
|
+
"Month boundaries are set in UK time (Europe/London) against timestamps stored in UTC",
|
|
30
|
+
"It lists whether cancelled orders count in the denominator and who owns the metric as open decisions, without naming an owner the thread did not name"
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"id": 3,
|
|
35
|
+
"held_out": "2026-10-05",
|
|
36
|
+
"prompt": "need a proper definition of 'time to first response' for our support team. we use a helpdesk tool and I can export tickets to a spreadsheet. my boss wants it on the weekly report. there's 8 agents. not sure if weekends should count, we don't work them",
|
|
37
|
+
"assertions": [
|
|
38
|
+
"It delivers a written definition in the reply and does not stop at a list of questions",
|
|
39
|
+
"It defines the start and the end of the clock (ticket created to the first reply from a human agent) and says automatic acknowledgement emails do not count as the first response, or flags that as a decision",
|
|
40
|
+
"Whether weekends and out-of-hours time count is given as an open decision with a recommended default or with both versions described; it is not decided silently",
|
|
41
|
+
"It says which statistic goes on the report (median, mean or a percentile), not just 'average' left undefined",
|
|
42
|
+
"It says how tickets that have had no reply yet when the report is run are treated",
|
|
43
|
+
"It says which week a ticket is counted in (the week it was created or the week it was answered)",
|
|
44
|
+
"Any export column names it uses are marked as assumed, since no export layout was given",
|
|
45
|
+
"It does not state a response-time target or SLA figure as the team's own, since none was given"
|
|
46
|
+
]
|
|
17
47
|
}
|
|
18
48
|
]
|
|
19
49
|
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Tallow & Thyme: tables (Postgres 15)
|
|
2
|
+
|
|
3
|
+
All timestamps are `timestamptz`, stored in UTC. The business reports on UK time.
|
|
4
|
+
|
|
5
|
+
## orders
|
|
6
|
+
|
|
7
|
+
| Column | Type | Notes |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| order_id | bigint | primary key |
|
|
10
|
+
| customer_id | bigint | references customers |
|
|
11
|
+
| store | text | 'uk' or 'eu' |
|
|
12
|
+
| currency | text | 'GBP' for the uk store, 'EUR' for the eu store |
|
|
13
|
+
| gross_amount_minor | integer | order total in pence (GBP) or cents (EUR) |
|
|
14
|
+
| placed_at | timestamptz | when the order was placed |
|
|
15
|
+
| status | text | 'placed', 'delivered', 'cancelled' |
|
|
16
|
+
| is_test | boolean | true for orders made by the test harness |
|
|
17
|
+
|
|
18
|
+
## refunds
|
|
19
|
+
|
|
20
|
+
| Column | Type | Notes |
|
|
21
|
+
|---|---|---|
|
|
22
|
+
| refund_id | bigint | primary key |
|
|
23
|
+
| order_id | bigint | references orders |
|
|
24
|
+
| amount_minor | integer | in the same currency as the order |
|
|
25
|
+
| reason | text | free text typed by the CX agent |
|
|
26
|
+
| created_at | timestamptz | when the refund was issued |
|
|
27
|
+
|
|
28
|
+
An order can have more than one refund row: a missing ingredient is refunded, then a second
|
|
29
|
+
problem with the same box is refunded later. About 1 in 9 refunded orders has two or more
|
|
30
|
+
rows.
|
|
31
|
+
|
|
32
|
+
## customers
|
|
33
|
+
|
|
34
|
+
| Column | Type | Notes |
|
|
35
|
+
|---|---|---|
|
|
36
|
+
| customer_id | bigint | primary key |
|
|
37
|
+
| email | text | |
|
|
38
|
+
| created_at | timestamptz | |
|
|
39
|
+
|
|
40
|
+
## Not in the database
|
|
41
|
+
|
|
42
|
+
There is no exchange-rate table. Finance converts EUR to GBP by hand in a spreadsheet.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# #ops-metrics, exported 3 March 2026
|
|
2
|
+
|
|
3
|
+
**Hattie Blum** (CX lead) 09:12
|
|
4
|
+
Feb refund rate is 4.6%. 312 refunded orders out of 7,480 orders.
|
|
5
|
+
|
|
6
|
+
**Rupert Osei** (Finance) 09:20
|
|
7
|
+
I get 3.5%. £9,870 refunded on £284,300 gross.
|
|
8
|
+
|
|
9
|
+
**Hattie Blum** 09:24
|
|
10
|
+
Well mine is orders, yours is money. I count an order as refunded if it shows up in the
|
|
11
|
+
refunds table. I go by the date the refund was issued, so that's refunds issued in Feb.
|
|
12
|
+
|
|
13
|
+
**Rupert Osei** 09:31
|
|
14
|
+
I go by the month the order was placed. If a Feb order gets refunded in March it goes back
|
|
15
|
+
against Feb, that's how the P&L works. Also mine is the UK store only. The EU store is in a
|
|
16
|
+
separate sheet and I convert the euros by hand at whatever the rate is that day, I haven't
|
|
17
|
+
done Feb yet.
|
|
18
|
+
|
|
19
|
+
**Hattie Blum** 09:33
|
|
20
|
+
Mine is both stores.
|
|
21
|
+
|
|
22
|
+
**Mina Castellanos** (founder) 09:47
|
|
23
|
+
This is why the Monday meeting goes round in circles. I want ONE refund rate for the whole
|
|
24
|
+
business, both stores, monthly, on UK time. And take out test orders, and staff orders too.
|
|
25
|
+
Staff get free boxes and we refund them through the system so they make it look worse than
|
|
26
|
+
it is.
|
|
27
|
+
|
|
28
|
+
**Hattie Blum** 09:52
|
|
29
|
+
There's an is_test flag on orders. No idea how you'd spot staff orders though, we just know
|
|
30
|
+
the names.
|
|
31
|
+
|
|
32
|
+
**Rupert Osei** 09:55
|
|
33
|
+
Do cancelled orders count as orders? I leave them in, they were placed.
|
|
34
|
+
|
|
35
|
+
**Hattie Blum** 09:58
|
|
36
|
+
I take them out.
|
|
37
|
+
|
|
38
|
+
**Mina Castellanos** 10:05
|
|
39
|
+
Someone write it down properly please. Who owns it after that, tbd, let's get the definition
|
|
40
|
+
sorted first.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "metric-definition",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Write a metric spec precise enough for a semantic layer or dbt metric to implement and for two analysts to get the same number — name, business question, exact numerator and denominator, grain, time window and timezone, filters and exclusions (test accounts, refunds), allowed dimensions, edge cases (NULLs, late data, currency), owner, reference SQL, and the sanity checks that catch it going wrong. Use when the user says \"define this metric\", \"how exactly do we calculate X\", \"finance and product get different numbers for X\", \"write the metric spec for our semantic layer\", or \"what counts as an active user\".",
|
|
5
5
|
"entrypoint": "SKILL.md",
|
|
6
6
|
"deps": {
|
|
@@ -18,6 +18,14 @@ For a single fast pipeline, run all three in order: profile → outline → buil
|
|
|
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:** Read "the deck" as an existing file: look for it, and if it isn't there, ask for it along with any content that is missing. Don't announce audience, format or palette choices before there is content to put on slides.
|
|
28
|
+
|
|
21
29
|
### 1. Run the setup block — once
|
|
22
30
|
|
|
23
31
|
Ask everything in **one** message, with defaults already chosen, so the user can answer with a
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "deck-builder",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Generate a real PowerPoint (.pptx) file from content, audience, and either a brand template or a color palette — with charts, tables and images, not only bullets. Slide count, density and layout are tuned to the audience: execs, boards, technical reviewers, sales prospects, investors, internal teams. Use when the user wants an actual editable .pptx rather than an outline, wants their corporate template or brand colours applied, or says \"build the deck\", \"make it a pptx\", \"use our template\".",
|
|
5
5
|
"entrypoint": "SKILL.md",
|
|
6
6
|
"deps": {
|
|
@@ -15,6 +15,14 @@ Two modes, chosen by what's already there:
|
|
|
15
15
|
|
|
16
16
|
## How to respond
|
|
17
17
|
|
|
18
|
+
**Four rules come before the steps and outrank them:**
|
|
19
|
+
|
|
20
|
+
- **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.
|
|
21
|
+
- **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".
|
|
22
|
+
- **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.
|
|
23
|
+
- **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.
|
|
24
|
+
- **For this skill:** Keep the reply short: what you wrote, where each command came from, and what the repository lacks. State only what you checked, and leave out line counts and caps.
|
|
25
|
+
|
|
18
26
|
1. **Inventory the real command surface before writing anything.** Read, in this order: `package.json` (`scripts`), `Makefile`, `pyproject.toml` / `setup.cfg`, `Cargo.toml`, `go.mod`, `composer.json`, `.github/workflows/*.yml`, `justfile`, `Taskfile.yml`, and any `CONTRIBUTING.md`. CI workflows are the highest-value source: they contain the commands that actually have to pass.
|
|
19
27
|
|
|
20
28
|
For each command record its **provenance** — the file and key it came from. Provenance is what makes audit mode possible later.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agents-md-generator",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Generate or audit a repository's AGENTS.md — the agent-policy file Claude Code, Codex, Cursor, Copilot, Kiro and Antigravity read — with every command traced to real evidence in the repo, generic virtue instructions stripped, and forbidden actions named. Use when a repo has no AGENTS.md, when an existing one is stale or ignored, when onboarding a codebase to agentic coding, or when an agent keeps running commands that don't exist.",
|
|
5
5
|
"entrypoint": "SKILL.md",
|
|
6
6
|
"deps": { "npm": [], "pip": [] },
|
|
@@ -9,6 +9,14 @@ Walks an author through the full arc of creating a new skilldrop skill: intake
|
|
|
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:** Read the target repository first: its contributing guide, its agent instructions and two existing skills. Follow the conventions you find, and produce every file that repository requires for a submission, not a generic skill.
|
|
19
|
+
|
|
12
20
|
### Step 1 — Intake (ask all at once)
|
|
13
21
|
|
|
14
22
|
Ask these questions in a single block — not one at a time:
|
|
@@ -14,6 +14,35 @@
|
|
|
14
14
|
"Ends with next steps that place files under packs/sre-oncall/skills/sla-credit-calculator/ and require python3 validate.py to pass before opening a PR",
|
|
15
15
|
"Does not invent inputs, deps, or related skills the author did not give"
|
|
16
16
|
]
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"id": 2,
|
|
20
|
+
"held_out": "2026-10-05",
|
|
21
|
+
"prompt": "I want to add a skill to our team's skills repo. The repo is this folder (CONTRIBUTING.md, AGENTS.md, existing skills under skills/). The new one is carrier-invoice-audit: you give it a carrier's freight invoice and the rate confirmation for that load, and it lists every line where the carrier billed more than we agreed, with the difference. Ignore differences of $5.00 or less per line. It goes under billing. Related skills are rate-con-extractor and bol-parser. And if it finds a detention charge on the invoice it should kick off detention-claim-letter automatically at the end. Write everything I need for the pull request.",
|
|
22
|
+
"assertions": [
|
|
23
|
+
"The skill is delivered as skills/carrier-invoice-audit/ containing skill.yaml, INSTRUCTIONS.md and tests/cases.yaml, the layout CONTRIBUTING.md requires, and not as some other layout such as manifest.json plus SKILL.md",
|
|
24
|
+
"The related list contains rate-con-extractor and does not contain bol-parser, and the reply says bol-parser is not a skill in the repo",
|
|
25
|
+
"The skill's instructions do not make it run or hand off to detention-claim-letter, and the reply says the repo's rule that a skill never calls another skill is the reason",
|
|
26
|
+
"The owner field is a team that appears in OWNERS.md (billing-ops, dispatch or claims), and the reply tells the author the owner was not given and needs confirming",
|
|
27
|
+
"tests/cases.yaml has at least five cases, one of which covers a missing input such as no rate confirmation supplied, following AGENTS.md's rule over the three cases CONTRIBUTING.md asks for",
|
|
28
|
+
"The $5.00 per-line tolerance appears as an exact figure in INSTRUCTIONS.md, and no other threshold or percentage is introduced",
|
|
29
|
+
"A CATALOG.md row for carrier-invoice-audit is provided for the billing table",
|
|
30
|
+
"The reply tells the author to run make check before opening the pull request"
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"id": 3,
|
|
35
|
+
"held_out": "2026-10-05",
|
|
36
|
+
"prompt": "need a new skill for our skills repo. takes the standup notes people paste from slack during the week and writes the friday update that goes to our director. not sure on the name yet, weekly-digest or friday-rollup. Priya wanted it to pull ticket status from Jira too but we don't have API access sorted so leave that out for now i guess. don't know which folder it should live in, whoever set the repo up is on leave. can you write the skill up plus a few test cases so i can open a PR when she's back",
|
|
37
|
+
"assertions": [
|
|
38
|
+
"It delivers a drafted instruction file for the skill and at least three test cases, and does not stop at a list of questions",
|
|
39
|
+
"It says the repo's conventions (required files, metadata format or folder) were not available and that the file layout used is an assumption to check",
|
|
40
|
+
"It uses one name for the skill throughout and tells the author the choice between weekly-digest and friday-rollup is still theirs to make",
|
|
41
|
+
"The skill as written does not fetch from Jira and declares no Jira credential, API key or dependency; Jira is mentioned only as left out for now",
|
|
42
|
+
"The skill's instructions tell it to report only what is in the pasted standup notes and not to add progress, blockers or ticket status the notes do not contain",
|
|
43
|
+
"It does not invent the director's name, the team's name, team members other than Priya, or a specific repo folder stated as fact",
|
|
44
|
+
"The test cases use realistic pasted standup notes as input, and at least one covers thin or missing notes"
|
|
45
|
+
]
|
|
17
46
|
}
|
|
18
47
|
]
|
|
19
48
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Instructions for agents working in this repo
|
|
2
|
+
|
|
3
|
+
Read `CONTRIBUTING.md` first. The rules below were added after it and win where the two differ.
|
|
4
|
+
|
|
5
|
+
1. **A skill never calls, starts or hands off to another skill.** Each folder has to work when it is the only one installed. If a second skill is the natural follow-up, say so to the user in the final line of the output and let them run it.
|
|
6
|
+
2. **Five test cases minimum, not three.** At least one case must cover missing input: the user leaves out something listed under `inputs`, and the expected behaviour is that the skill says what is missing and does not guess.
|
|
7
|
+
3. **No customer or carrier names from real accounts** in instructions or tests. Use made-up ones.
|
|
8
|
+
4. **Money rules are written as numbers.** If a skill applies a threshold or tolerance, the exact figure goes in `INSTRUCTIONS.md`. "A reasonable tolerance" is not acceptable.
|
|
9
|
+
5. Do not edit `OWNERS.md`. If no listed team fits, ask in the pull request.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Skill catalogue
|
|
2
|
+
|
|
3
|
+
## billing
|
|
4
|
+
|
|
5
|
+
| skill | what it does | owner |
|
|
6
|
+
|---|---|---|
|
|
7
|
+
| [`rate-con-extractor`](skills/rate-con-extractor/INSTRUCTIONS.md) | Pulls the agreed rate, fuel surcharge and accessorials out of a rate confirmation into a table. | billing-ops |
|
|
8
|
+
|
|
9
|
+
## dispatch
|
|
10
|
+
|
|
11
|
+
| skill | what it does | owner |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
|
|
14
|
+
## claims
|
|
15
|
+
|
|
16
|
+
| skill | what it does | owner |
|
|
17
|
+
|---|---|---|
|
|
18
|
+
| [`detention-claim-letter`](skills/detention-claim-letter/INSTRUCTIONS.md) | Drafts a detention claim letter to a shipper or receiver from the gate timestamps and the free-time terms. | claims |
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Contributing to larkfield-agent-skills
|
|
2
|
+
|
|
3
|
+
Internal skills for the Larkfield Freight operations and billing teams. One folder per skill under `skills/`.
|
|
4
|
+
|
|
5
|
+
## What a skill folder contains
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
skills/<skill-name>/
|
|
9
|
+
skill.yaml # metadata, see below
|
|
10
|
+
INSTRUCTIONS.md # what the agent does
|
|
11
|
+
tests/cases.yaml # test cases
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
`<skill-name>` is lowercase kebab-case and matches `name` in `skill.yaml`.
|
|
15
|
+
|
|
16
|
+
## skill.yaml
|
|
17
|
+
|
|
18
|
+
All of these are required:
|
|
19
|
+
|
|
20
|
+
| field | notes |
|
|
21
|
+
|---|---|
|
|
22
|
+
| `name` | same as the folder |
|
|
23
|
+
| `summary` | one sentence, 160 characters or fewer |
|
|
24
|
+
| `owner` | a team listed in `OWNERS.md` — the team that answers when the skill is wrong |
|
|
25
|
+
| `category` | `billing`, `dispatch` or `claims` |
|
|
26
|
+
| `inputs` | list of what the user must supply |
|
|
27
|
+
| `related` | list of other skills in this repo (may be empty). Every entry must be a folder under `skills/` |
|
|
28
|
+
| `network` | `false` unless the security team has signed off |
|
|
29
|
+
|
|
30
|
+
## INSTRUCTIONS.md
|
|
31
|
+
|
|
32
|
+
Three sections, in this order: `## Purpose`, `## Steps`, `## Never`.
|
|
33
|
+
`## Never` lists at least two things the skill must not do.
|
|
34
|
+
|
|
35
|
+
## Tests
|
|
36
|
+
|
|
37
|
+
`tests/cases.yaml` needs at least 3 cases. Each case has `name`, `input` and `expect` (a list of things that must be true of the output).
|
|
38
|
+
|
|
39
|
+
## Catalogue
|
|
40
|
+
|
|
41
|
+
Add one row for the skill to `CATALOG.md`, in the table for its category, keeping the rows in alphabetical order.
|
|
42
|
+
|
|
43
|
+
## Before you open a pull request
|
|
44
|
+
|
|
45
|
+
Run `make check`. It validates every `skill.yaml`, checks that `related` entries exist and counts the test cases. A pull request with a failing `make check` is not reviewed.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Owning teams
|
|
2
|
+
|
|
3
|
+
| team | covers | contact |
|
|
4
|
+
|---|---|---|
|
|
5
|
+
| `billing-ops` | carrier payables, customer invoicing | Ines Okonkwo-Reyes |
|
|
6
|
+
| `dispatch` | load planning, carrier assignment | Tobias Vrana |
|
|
7
|
+
| `claims` | detention, damage and shortage claims | Marguerite Dlamini |
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# detention-claim-letter
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
When a driver is held at a facility past the agreed free time, Larkfield claims detention from the party that caused the delay. This skill drafts that letter with the arithmetic shown so the recipient can check it.
|
|
6
|
+
|
|
7
|
+
## Steps
|
|
8
|
+
|
|
9
|
+
1. Work out time on site: departure minus arrival, in hours and minutes.
|
|
10
|
+
2. Subtract the free time. If the result is zero or less, say that no detention is owed and stop.
|
|
11
|
+
3. Bill the remainder in the increments the terms state. If the terms do not state an increment, bill in 15-minute increments rounded down.
|
|
12
|
+
4. Apply the cap if the terms state one.
|
|
13
|
+
5. Write the letter: load number, facility, the timestamps, the calculation line by line, the amount claimed, and a reply-by date 14 days from the letter date.
|
|
14
|
+
6. End the output with one line listing what evidence to attach (the signed bill of lading with in and out times).
|
|
15
|
+
|
|
16
|
+
## Never
|
|
17
|
+
|
|
18
|
+
- Never claim an amount without showing the timestamps it came from.
|
|
19
|
+
- Never round time on site up.
|
|
20
|
+
- Never state that payment is overdue; this is a first claim.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
name: detention-claim-letter
|
|
2
|
+
summary: Drafts a detention claim letter to a shipper or receiver from the gate timestamps and the free-time terms.
|
|
3
|
+
owner: claims
|
|
4
|
+
category: claims
|
|
5
|
+
inputs:
|
|
6
|
+
- arrival and departure timestamps at the facility
|
|
7
|
+
- the free time and hourly detention rate that apply
|
|
8
|
+
- who the letter is addressed to
|
|
9
|
+
related:
|
|
10
|
+
- rate-con-extractor
|
|
11
|
+
network: false
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
- name: three-hours-over
|
|
2
|
+
input: Arrived 07:10, departed 12:10 at Halvorsen Cold Storage. 2 hours free, $60/hr. Load LF-207733. Address it to Halvorsen's receiving manager.
|
|
3
|
+
expect:
|
|
4
|
+
- time on site is 5 hours and billable time is 3 hours
|
|
5
|
+
- the amount claimed is 180.00
|
|
6
|
+
- the reply-by date is 14 days after the letter date
|
|
7
|
+
- name: inside-free-time
|
|
8
|
+
input: Arrived 09:00, departed 10:45. 2 hours free, $75/hr. Load LF-207801, to Pellham Distribution.
|
|
9
|
+
expect:
|
|
10
|
+
- the reply says no detention is owed
|
|
11
|
+
- no letter is drafted
|
|
12
|
+
- name: cap-applies
|
|
13
|
+
input: Arrived 06:00, departed 17:30 at Norcastle Foods. 2 hours free, $60/hr, max $480. Load LF-207950.
|
|
14
|
+
expect:
|
|
15
|
+
- the uncapped figure 570.00 is shown and the claim is 480.00
|
|
16
|
+
- name: partial-increment
|
|
17
|
+
input: Arrived 13:05, departed 16:25. 2 hours free, $60/hr. Load LF-208010, to Wexcombe Mills.
|
|
18
|
+
expect:
|
|
19
|
+
- billable time is 1 hour 15 minutes, not 1 hour 20 minutes
|
|
20
|
+
- the amount claimed is 75.00
|
|
21
|
+
- name: no-rate-given
|
|
22
|
+
input: Driver sat at Halvorsen for six hours yesterday on LF-208122, write the detention letter.
|
|
23
|
+
expect:
|
|
24
|
+
- the reply says the timestamps, the free time and the hourly rate are missing
|
|
25
|
+
- no amount is claimed
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# rate-con-extractor
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
A rate confirmation is the agreement between Larkfield and a carrier for one load. Billing needs its numbers in a fixed shape before anything can be checked against it. This skill reads one rate confirmation and returns those numbers as a table.
|
|
6
|
+
|
|
7
|
+
## Steps
|
|
8
|
+
|
|
9
|
+
1. Find the load number, the carrier name, the pickup and delivery dates.
|
|
10
|
+
2. Find the linehaul rate. Record whether it is a flat amount or a per-mile rate, and the miles if per-mile.
|
|
11
|
+
3. Find the fuel surcharge. Record it as written: a percentage of linehaul, a per-mile amount, or a flat amount.
|
|
12
|
+
4. List every accessorial the document names (detention, lumper, layover, stop-off, tarp) with its rate and any free time or cap.
|
|
13
|
+
5. Return one table: field, value, and the line of the document the value came from.
|
|
14
|
+
6. List any field in steps 1 to 4 that the document does not state, under "Not stated".
|
|
15
|
+
|
|
16
|
+
## Never
|
|
17
|
+
|
|
18
|
+
- Never calculate a total. This skill extracts; it does not add up.
|
|
19
|
+
- Never fill a missing field from what is usual for the lane or the carrier.
|
|
20
|
+
- Never merge two rate confirmations into one table.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
- name: flat-linehaul-percent-fuel
|
|
2
|
+
input: |
|
|
3
|
+
RATE CONFIRMATION Load LF-208841 Carrier: Brightwater Haulage
|
|
4
|
+
Pickup 03/04 Delivery 03/06
|
|
5
|
+
Linehaul: $1,850.00 flat Fuel surcharge: 18% of linehaul
|
|
6
|
+
Detention: $60/hr after 2 hrs free, max $480
|
|
7
|
+
expect:
|
|
8
|
+
- the table has linehaul 1850.00 marked flat
|
|
9
|
+
- fuel surcharge is recorded as 18% of linehaul, not as a dollar amount
|
|
10
|
+
- detention is listed with 60 per hour, 2 hours free and the 480 cap
|
|
11
|
+
- name: per-mile-linehaul
|
|
12
|
+
input: |
|
|
13
|
+
Load LF-209112 Carrier: Copperline Transport
|
|
14
|
+
Linehaul $2.35/mi x 612 mi FSC $0.48/mi
|
|
15
|
+
expect:
|
|
16
|
+
- linehaul is recorded as 2.35 per mile with 612 miles
|
|
17
|
+
- no total is calculated
|
|
18
|
+
- name: no-fuel-surcharge-stated
|
|
19
|
+
input: |
|
|
20
|
+
Load LF-209377 Carrier: Ashgrove Carriers Linehaul $940 flat Lumper: reimbursed with receipt
|
|
21
|
+
expect:
|
|
22
|
+
- fuel surcharge appears under Not stated
|
|
23
|
+
- no fuel surcharge figure is given
|
|
24
|
+
- name: two-documents-pasted
|
|
25
|
+
input: two rate confirmations pasted one after the other, loads LF-209400 and LF-209401
|
|
26
|
+
expect:
|
|
27
|
+
- the output is two separate tables or a request to send one at a time
|
|
28
|
+
- name: nothing-supplied
|
|
29
|
+
input: Extract the rate con for load LF-209500.
|
|
30
|
+
expect:
|
|
31
|
+
- the reply says the rate confirmation text is missing
|
|
32
|
+
- no rates are given
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "contribution-wizard",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"description": "Guides an author through creating a new skilldrop skill from scratch — generates the manifest, SKILL.md, eval cases, and skill-catalogue entry from a plain-language description of the skill's purpose. Use when authoring a new skill for this repo or a private fork, ensuring a new skill meets the schema and validation requirements before submission.",
|
|
5
5
|
"entrypoint": "SKILL.md",
|
|
6
6
|
"deps": { "npm": [], "pip": [] },
|
|
@@ -24,6 +24,14 @@ Specifically:
|
|
|
24
24
|
|
|
25
25
|
## How to respond
|
|
26
26
|
|
|
27
|
+
**Four rules come before the steps and outrank them:**
|
|
28
|
+
|
|
29
|
+
- **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.
|
|
30
|
+
- **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".
|
|
31
|
+
- **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.
|
|
32
|
+
- **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.
|
|
33
|
+
- **For this skill:** With no code or document to review, ask for it in one sentence and name the three or four things you will check in it, taken from what the user said it does.
|
|
34
|
+
|
|
27
35
|
1. **Identify the change under review.** In order of preference:
|
|
28
36
|
- The agent / user has just shown you a diff — review that diff.
|
|
29
37
|
- Git working tree has unstaged changes — `git diff` is the scope.
|
|
@@ -14,6 +14,35 @@
|
|
|
14
14
|
"Output ends with a 'what's solid' section so the author knows what not to touch",
|
|
15
15
|
"The review scopes to the change under review, never sweeping the whole codebase"
|
|
16
16
|
]
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"id": 2,
|
|
20
|
+
"held_out": "2026-10-05",
|
|
21
|
+
"prompt": "Just finished the volunteer shift sign-up feature for the food bank's scheduling app (signups.py, tests in test_signups.py). Volunteers sign up until the shift's full, after that they go on a waitlist, and when someone cancels the first person on the waitlist gets the spot. No cancelling inside 24 hours of the shift. Tests all pass. Anything I've missed before I merge?",
|
|
22
|
+
"assertions": [
|
|
23
|
+
"It flags that sign_up compares the confirmed count with > instead of >=, so a shift with capacity N confirms N+1 volunteers",
|
|
24
|
+
"It flags that cancel picks the waitlisted row with ORDER BY created_at DESC, so the most recent person on the waitlist is promoted, not the first",
|
|
25
|
+
"It flags that the same volunteer can sign up twice for one shift because nothing checks for an existing sign-up",
|
|
26
|
+
"It flags that the 24-hour cutoff subtracts local-time datetime.now() from a start time stored in UTC, so the window is off by the server's UTC offset",
|
|
27
|
+
"It points out that test_waitlist_when_full puts three volunteers into a capacity-2 shift before asserting, so it passes because of the capacity bug",
|
|
28
|
+
"It points out that test_no_waitlist_raises passes even when ShiftFull is never raised",
|
|
29
|
+
"It does not report SQL injection, since every query is parameterised",
|
|
30
|
+
"It says plainly that the change is not ready to merge as it stands"
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"id": 3,
|
|
35
|
+
"held_out": "2026-10-05",
|
|
36
|
+
"prompt": "wrote this quick script to dedupe our newsletter subscriber export before we import it into the new mail tool. worked fine on the 50-row sample i tried. good to run on the real file? it's about 40k rows, email is the third column\n\n```python\nimport sys\n\nrows = open(sys.argv[1]).read().split(\"\\n\")\nseen = {}\nfor r in rows[1:]:\n if not r.strip():\n continue\n cols = r.split(\",\")\n seen[cols[2]] = r\n\nout = open(sys.argv[1], \"w\")\nout.write(rows[0] + \"\\n\")\nfor r in seen.values():\n out.write(r + \"\\n\")\n```",
|
|
37
|
+
"assertions": [
|
|
38
|
+
"It answers the question near the top: not as it stands, or only on a copy of the file",
|
|
39
|
+
"It flags that emails are compared exactly, so addresses differing only in letter case or surrounding spaces are kept as separate subscribers",
|
|
40
|
+
"It flags that split(\",\") breaks on a quoted field containing a comma, which shifts the column treated as the email",
|
|
41
|
+
"It flags that the script overwrites the input file in place with no backup, and recommends writing to a new file or keeping a copy",
|
|
42
|
+
"It notes that when rows share an email the last one wins, and that whether that is the right row to keep is something to confirm",
|
|
43
|
+
"It gives a concrete fix, such as reading with the csv module and normalising the email with strip and lower",
|
|
44
|
+
"It does not state as fact what the other columns hold or what the real file contains beyond what was given"
|
|
45
|
+
]
|
|
17
46
|
}
|
|
18
47
|
]
|
|
19
48
|
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"""Volunteer shift sign-ups for the Harbourside Food Bank scheduling app."""
|
|
2
|
+
import sqlite3
|
|
3
|
+
from datetime import datetime, timedelta, timezone
|
|
4
|
+
|
|
5
|
+
CANCEL_CUTOFF_HOURS = 24
|
|
6
|
+
|
|
7
|
+
SCHEMA = """
|
|
8
|
+
CREATE TABLE IF NOT EXISTS shifts (
|
|
9
|
+
id INTEGER PRIMARY KEY,
|
|
10
|
+
starts_at TEXT NOT NULL, -- ISO 8601, stored in UTC
|
|
11
|
+
capacity INTEGER NOT NULL
|
|
12
|
+
);
|
|
13
|
+
CREATE TABLE IF NOT EXISTS signups (
|
|
14
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
15
|
+
shift_id INTEGER NOT NULL REFERENCES shifts(id),
|
|
16
|
+
volunteer_id INTEGER NOT NULL,
|
|
17
|
+
status TEXT NOT NULL, -- 'confirmed' | 'waitlisted' | 'cancelled'
|
|
18
|
+
created_at TEXT NOT NULL
|
|
19
|
+
);
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class ShiftFull(Exception):
|
|
24
|
+
pass
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class TooLateToCancel(Exception):
|
|
28
|
+
pass
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class NotSignedUp(Exception):
|
|
32
|
+
pass
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def init_db(conn: sqlite3.Connection) -> None:
|
|
36
|
+
conn.executescript(SCHEMA)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _confirmed_count(conn: sqlite3.Connection, shift_id: int) -> int:
|
|
40
|
+
row = conn.execute(
|
|
41
|
+
"SELECT COUNT(*) FROM signups WHERE shift_id = ? AND status = 'confirmed'",
|
|
42
|
+
(shift_id,),
|
|
43
|
+
).fetchone()
|
|
44
|
+
return row[0]
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def sign_up(conn: sqlite3.Connection, shift_id: int, volunteer_id: int,
|
|
48
|
+
allow_waitlist: bool = True) -> str:
|
|
49
|
+
"""Sign a volunteer up for a shift. Returns 'confirmed' or 'waitlisted'."""
|
|
50
|
+
shift = conn.execute(
|
|
51
|
+
"SELECT capacity FROM shifts WHERE id = ?", (shift_id,)
|
|
52
|
+
).fetchone()
|
|
53
|
+
if shift is None:
|
|
54
|
+
raise KeyError(f"no shift {shift_id}")
|
|
55
|
+
capacity = shift[0]
|
|
56
|
+
|
|
57
|
+
if _confirmed_count(conn, shift_id) > capacity:
|
|
58
|
+
if not allow_waitlist:
|
|
59
|
+
raise ShiftFull(f"shift {shift_id} is full")
|
|
60
|
+
status = "waitlisted"
|
|
61
|
+
else:
|
|
62
|
+
status = "confirmed"
|
|
63
|
+
|
|
64
|
+
conn.execute(
|
|
65
|
+
"INSERT INTO signups (shift_id, volunteer_id, status, created_at) "
|
|
66
|
+
"VALUES (?, ?, ?, ?)",
|
|
67
|
+
(shift_id, volunteer_id, status, datetime.now().isoformat()),
|
|
68
|
+
)
|
|
69
|
+
conn.commit()
|
|
70
|
+
return status
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def cancel(conn: sqlite3.Connection, shift_id: int, volunteer_id: int) -> None:
|
|
74
|
+
"""Cancel a sign-up. The first volunteer on the waitlist takes the spot."""
|
|
75
|
+
row = conn.execute(
|
|
76
|
+
"SELECT id, status FROM signups "
|
|
77
|
+
"WHERE shift_id = ? AND volunteer_id = ? AND status != 'cancelled'",
|
|
78
|
+
(shift_id, volunteer_id),
|
|
79
|
+
).fetchone()
|
|
80
|
+
if row is None:
|
|
81
|
+
raise NotSignedUp(f"volunteer {volunteer_id} is not on shift {shift_id}")
|
|
82
|
+
signup_id, status = row
|
|
83
|
+
|
|
84
|
+
starts_at = datetime.fromisoformat(
|
|
85
|
+
conn.execute(
|
|
86
|
+
"SELECT starts_at FROM shifts WHERE id = ?", (shift_id,)
|
|
87
|
+
).fetchone()[0]
|
|
88
|
+
)
|
|
89
|
+
if starts_at - datetime.now() < timedelta(hours=CANCEL_CUTOFF_HOURS):
|
|
90
|
+
raise TooLateToCancel(
|
|
91
|
+
f"cancellations close {CANCEL_CUTOFF_HOURS}h before the shift"
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
conn.execute("UPDATE signups SET status = 'cancelled' WHERE id = ?", (signup_id,))
|
|
95
|
+
|
|
96
|
+
if status == "confirmed":
|
|
97
|
+
nxt = conn.execute(
|
|
98
|
+
"SELECT id FROM signups WHERE shift_id = ? AND status = 'waitlisted' "
|
|
99
|
+
"ORDER BY created_at DESC LIMIT 1",
|
|
100
|
+
(shift_id,),
|
|
101
|
+
).fetchone()
|
|
102
|
+
if nxt is not None:
|
|
103
|
+
conn.execute(
|
|
104
|
+
"UPDATE signups SET status = 'confirmed' WHERE id = ?", (nxt[0],)
|
|
105
|
+
)
|
|
106
|
+
conn.commit()
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def roster(conn: sqlite3.Connection, shift_id: int) -> list[int]:
|
|
110
|
+
"""Volunteer ids confirmed for a shift, in sign-up order."""
|
|
111
|
+
rows = conn.execute(
|
|
112
|
+
"SELECT volunteer_id FROM signups "
|
|
113
|
+
"WHERE shift_id = ? AND status = 'confirmed' ORDER BY id",
|
|
114
|
+
(shift_id,),
|
|
115
|
+
).fetchall()
|
|
116
|
+
return [r[0] for r in rows]
|