@bendyline/gilde 0.1.95 → 0.2.1
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/authoring/chat-models/minicpm-v4.7-35b-a3b-q4.json +106 -0
- package/data/chat-models/index.json +1 -1
- package/data/chat-models/mi/minicpm-v4.7-35b-a3b-q4/manifest.json +184 -0
- package/data/chat-models/mi/minicpm-v4.7-35b-a3b-q4/versions/1.0.0/manifest.json +93 -0
- package/data/chat-models/raw-index.json +1 -1
- package/data/craftbook-templates/ab/ab-test-readout/manifest.json +4 -0
- package/data/craftbook-templates/al/album-curate/manifest.json +4 -0
- package/data/craftbook-templates/an/anniversary-cut/manifest.json +4 -0
- package/data/craftbook-templates/an/annotated-bibliography/manifest.json +4 -0
- package/data/craftbook-templates/an/annual-document-review/manifest.json +4 -0
- package/data/craftbook-templates/an/anomaly-scan/manifest.json +3 -0
- package/data/craftbook-templates/au/audio-ad-spot/manifest.json +4 -0
- package/data/craftbook-templates/bo/board-deck/manifest.json +3 -0
- package/data/craftbook-templates/bo/board-game-web/manifest.json +4 -0
- package/data/craftbook-templates/br/branding-website/manifest.json +4 -0
- package/data/craftbook-templates/br/broadcast-announcement/manifest.json +4 -0
- package/data/craftbook-templates/ca/calendar-brief/manifest.json +3 -0
- package/data/craftbook-templates/ch/chapter-weave/manifest.json +4 -0
- package/data/craftbook-templates/ch/chart-pack/manifest.json +3 -0
- package/data/craftbook-templates/co/codebase-ux-review/manifest.json +3 -0
- package/data/craftbook-templates/co/cohort-analysis/manifest.json +3 -0
- package/data/craftbook-templates/co/company-research-brief/manifest.json +4 -0
- package/data/craftbook-templates/co/compat-check/manifest.json +4 -0
- package/data/craftbook-templates/co/competitive-analysis/manifest.json +4 -0
- package/data/craftbook-templates/co/content-accuracy-review/manifest.json +4 -0
- package/data/craftbook-templates/co/content-deck/manifest.json +4 -0
- package/data/craftbook-templates/co/contract-template/manifest.json +4 -0
- package/data/craftbook-templates/co/corpus-email-digest/manifest.json +3 -0
- package/data/craftbook-templates/co/cover-letter/manifest.json +3 -0
- package/data/craftbook-templates/cr/crm-update-batch/manifest.json +3 -0
- package/data/craftbook-templates/cr/crossword-forge/manifest.json +4 -0
- package/data/craftbook-templates/cs/csv-transformer/manifest.json +3 -0
- package/data/craftbook-templates/da/dashboard-spec/manifest.json +4 -0
- package/data/craftbook-templates/da/data-dictionary/manifest.json +3 -0
- package/data/craftbook-templates/da/data-export-migrate/manifest.json +4 -0
- package/data/craftbook-templates/da/data-join-merge/manifest.json +3 -0
- package/data/craftbook-templates/da/data-quality-audit/manifest.json +3 -0
- package/data/craftbook-templates/da/data-to-report/manifest.json +4 -0
- package/data/craftbook-templates/da/data-viz-page/manifest.json +4 -0
- package/data/craftbook-templates/da/dataset-clean/manifest.json +3 -0
- package/data/craftbook-templates/de/design-review/manifest.json +4 -0
- package/data/craftbook-templates/de/design-system-consultation/manifest.json +4 -0
- package/data/craftbook-templates/di/diagram-from-text/manifest.json +4 -0
- package/data/craftbook-templates/dr/drive-wrap-up/manifest.json +4 -0
- package/data/craftbook-templates/du/due-diligence-brief/manifest.json +4 -0
- package/data/craftbook-templates/en/engineering-retrospective/manifest.json +4 -0
- package/data/craftbook-templates/ex/expense-categorize/manifest.json +4 -0
- package/data/craftbook-templates/ex/explain-code-folder/manifest.json +26 -0
- package/data/craftbook-templates/ex/explain-code-folder/versions/1.0.0/craftbook.json +233 -0
- package/data/craftbook-templates/ex/explain-code-folder/versions/1.0.0/samples/todo-cli/README.md +29 -0
- package/data/craftbook-templates/ex/explain-code-folder/versions/1.0.0/samples/todo-cli/package.json +17 -0
- package/data/craftbook-templates/ex/explain-code-folder/versions/1.0.0/samples/todo-cli/src/format.js +15 -0
- package/data/craftbook-templates/ex/explain-code-folder/versions/1.0.0/samples/todo-cli/src/index.js +50 -0
- package/data/craftbook-templates/ex/explain-code-folder/versions/1.0.0/samples/todo-cli/src/store.js +45 -0
- package/data/craftbook-templates/ex/explain-code-folder/versions/1.0.0/samples/todo-cli/test/store.test.js +61 -0
- package/data/craftbook-templates/ex/explain-code-folder/versions/1.0.0/test.json +106 -0
- package/data/craftbook-templates/fa/family-story-chapter/manifest.json +4 -0
- package/data/craftbook-templates/fo/forecast-model/manifest.json +4 -0
- package/data/craftbook-templates/ga/game-with-screens/manifest.json +4 -0
- package/data/craftbook-templates/gl/glossary-build/manifest.json +3 -0
- package/data/craftbook-templates/ha/handbook-section/manifest.json +3 -0
- package/data/craftbook-templates/he/hero-image/manifest.json +4 -0
- package/data/craftbook-templates/ht/html-arcade-game/manifest.json +4 -0
- package/data/craftbook-templates/ht/html-puzzle-game/manifest.json +4 -0
- package/data/craftbook-templates/id/idle-clicker-game/manifest.json +4 -0
- package/data/craftbook-templates/in/inbox-triage/manifest.json +3 -0
- package/data/craftbook-templates/in/insurance-inventory/manifest.json +4 -0
- package/data/craftbook-templates/in/interactive-quiz/manifest.json +3 -0
- package/data/craftbook-templates/in/invoice-generator/manifest.json +3 -0
- package/data/craftbook-templates/in/invoice-run/manifest.json +3 -0
- package/data/craftbook-templates/index.json +1 -1
- package/data/craftbook-templates/ju/juice-pass/manifest.json +4 -0
- package/data/craftbook-templates/kp/kpi-scorecard/manifest.json +4 -0
- package/data/craftbook-templates/la/landing-page/manifest.json +4 -0
- package/data/craftbook-templates/le/lead-enrichment/manifest.json +4 -0
- package/data/craftbook-templates/li/literature-review/manifest.json +4 -0
- package/data/craftbook-templates/lo/logo-set/manifest.json +4 -0
- package/data/craftbook-templates/ma/market-scan/manifest.json +4 -0
- package/data/craftbook-templates/me/meeting-minutes/manifest.json +3 -0
- package/data/craftbook-templates/me/meeting-notes-to-actions/manifest.json +3 -0
- package/data/craftbook-templates/me/meeting-notes-to-actions/versions/1.1.2/craftbook.json +255 -0
- package/data/craftbook-templates/me/meeting-notes-to-actions/versions/1.1.2/samples/team-sync/notes.md +47 -0
- package/data/craftbook-templates/me/meeting-notes-to-actions/versions/1.1.2/test.json +78 -0
- package/data/craftbook-templates/me/meeting-prep-brief/manifest.json +3 -0
- package/data/craftbook-templates/me/meeting-summary-audio/manifest.json +3 -0
- package/data/craftbook-templates/me/memory-prompt-session/manifest.json +3 -0
- package/data/craftbook-templates/mi/micro-game-jam/manifest.json +4 -0
- package/data/craftbook-templates/mo/mock-interview/manifest.json +3 -0
- package/data/craftbook-templates/mo/mod-scaffold/manifest.json +4 -0
- package/data/craftbook-templates/mo/month-close/manifest.json +3 -0
- package/data/craftbook-templates/mo/monthly-recording-review/manifest.json +3 -0
- package/data/craftbook-templates/oc/ocr-extract/manifest.json +4 -0
- package/data/craftbook-templates/of/offer-compare/manifest.json +3 -0
- package/data/craftbook-templates/on/one-pager/manifest.json +4 -0
- package/data/craftbook-templates/ph/photo-cull/manifest.json +4 -0
- package/data/craftbook-templates/ph/photo-library-nightly/manifest.json +4 -0
- package/data/craftbook-templates/ph/physics-toy/manifest.json +4 -0
- package/data/craftbook-templates/pi/pitch-deck/manifest.json +4 -0
- package/data/craftbook-templates/pl/playtest-report/manifest.json +4 -0
- package/data/craftbook-templates/po/powerpoint-deck/manifest.json +4 -0
- package/data/craftbook-templates/pr/practice-exam/manifest.json +3 -0
- package/data/craftbook-templates/pr/practice-session/manifest.json +3 -0
- package/data/craftbook-templates/pr/price-tracker/manifest.json +4 -0
- package/data/craftbook-templates/pr/proposal-sow/manifest.json +3 -0
- package/data/craftbook-templates/pu/puzzle-pack-layout/manifest.json +4 -0
- package/data/craftbook-templates/qu/quarterly-summary/manifest.json +4 -0
- package/data/craftbook-templates/raw-index.json +1 -1
- package/data/craftbook-templates/re/reading-list/manifest.json +3 -0
- package/data/craftbook-templates/re/receipt-intake/manifest.json +4 -0
- package/data/craftbook-templates/re/receipt-ocr-ledger/manifest.json +3 -0
- package/data/craftbook-templates/re/recurring-invoice-run/manifest.json +3 -0
- package/data/craftbook-templates/re/release-announcement/manifest.json +4 -0
- package/data/craftbook-templates/re/resume-cv/manifest.json +3 -0
- package/data/craftbook-templates/re/review-code-folder/manifest.json +25 -0
- package/data/craftbook-templates/re/review-code-folder/versions/1.0.0/craftbook.json +223 -0
- package/data/craftbook-templates/re/review-code-folder/versions/1.0.0/samples/todo-cli-bugs/README.md +29 -0
- package/data/craftbook-templates/re/review-code-folder/versions/1.0.0/samples/todo-cli-bugs/package.json +17 -0
- package/data/craftbook-templates/re/review-code-folder/versions/1.0.0/samples/todo-cli-bugs/src/format.js +15 -0
- package/data/craftbook-templates/re/review-code-folder/versions/1.0.0/samples/todo-cli-bugs/src/index.js +50 -0
- package/data/craftbook-templates/re/review-code-folder/versions/1.0.0/samples/todo-cli-bugs/src/store.js +44 -0
- package/data/craftbook-templates/re/review-code-folder/versions/1.0.0/samples/todo-cli-bugs/test/store.test.js +37 -0
- package/data/craftbook-templates/re/review-code-folder/versions/1.0.0/test.json +108 -0
- package/data/craftbook-templates/sc/scrape-to-structured/manifest.json +3 -0
- package/data/craftbook-templates/sp/spa-dashboard/manifest.json +4 -0
- package/data/craftbook-templates/sp/spreadsheet-findings/manifest.json +26 -0
- package/data/craftbook-templates/sp/spreadsheet-findings/versions/1.0.0/craftbook.json +186 -0
- package/data/craftbook-templates/sp/spreadsheet-findings/versions/1.0.0/samples/shop-sales/sales.csv +49 -0
- package/data/craftbook-templates/sp/spreadsheet-findings/versions/1.0.0/test.json +88 -0
- package/data/craftbook-templates/sp/spreadsheet-model/manifest.json +4 -0
- package/data/craftbook-templates/sp/sprite-sheet/manifest.json +4 -0
- package/data/craftbook-templates/sq/sql-analysis/manifest.json +3 -0
- package/data/craftbook-templates/st/standup-summary/manifest.json +3 -0
- package/data/craftbook-templates/st/status-report/manifest.json +3 -0
- package/data/craftbook-templates/su/subscription-audit/manifest.json +4 -0
- package/data/craftbook-templates/su/survey-analysis/manifest.json +4 -0
- package/data/craftbook-templates/ta/tailor-resume/manifest.json +3 -0
- package/data/craftbook-templates/ti/tidy-spreadsheet/manifest.json +26 -0
- package/data/craftbook-templates/ti/tidy-spreadsheet/versions/1.0.0/craftbook.json +183 -0
- package/data/craftbook-templates/ti/tidy-spreadsheet/versions/1.0.0/samples/club-members/members.csv +43 -0
- package/data/craftbook-templates/ti/tidy-spreadsheet/versions/1.0.0/test.json +108 -0
- package/data/craftbook-templates/ti/tileset-batch/manifest.json +4 -0
- package/data/craftbook-templates/to/topic-explainer/manifest.json +4 -0
- package/data/craftbook-templates/tr/transcribe-audio/manifest.json +4 -0
- package/data/craftbook-templates/tr/transcribe-index/manifest.json +4 -0
- package/data/craftbook-templates/vi/visit-prep/manifest.json +4 -0
- package/data/craftbook-templates/we/weak-spot-drill/manifest.json +3 -0
- package/data/craftbook-templates/we/week-plan/manifest.json +3 -0
- package/data/craftbook-templates/we/weekly-pipeline-review/manifest.json +3 -0
- package/data/craftbook-templates/we/weekly-review/manifest.json +3 -0
- package/data/craftbook-templates/ye/year-in-review/manifest.json +4 -0
- package/data/image-models/an/animagine-xl-4/versions/4.0.1/manifest.json +16 -0
- package/data/image-models/fl/flux-2-klein-4b-q4/versions/1.0.1/manifest.json +29 -0
- package/data/image-models/index.json +1 -1
- package/data/image-models/ir/iris-3b-f32/versions/1.0.1/manifest.json +25 -0
- package/data/image-models/kr/krea-2-turbo-q4/versions/1.0.1/manifest.json +29 -0
- package/data/image-models/kr/krea-2-turbo-q6/versions/1.0.1/manifest.json +29 -0
- package/data/image-models/kr/krea-2-turbo-q8/versions/1.0.1/manifest.json +29 -0
- package/data/image-models/mi/ming-image-0.1-design-bf16/versions/1.0.1/manifest.json +50 -0
- package/data/image-models/raw-index.json +1 -1
- package/data/image-models/sd/sd-1.5/versions/1.0.1/manifest.json +16 -0
- package/data/image-models/sd/sd-turbo/versions/1.0.1/manifest.json +16 -0
- package/data/image-models/sd/sdxl-base-1.0/versions/1.0.1/manifest.json +16 -0
- package/data/image-models/sd/sdxl-lightning-4step/versions/1.0.1/manifest.json +16 -0
- package/data/image-models/sd/sdxl-turbo/versions/1.0.1/manifest.json +16 -0
- package/data/project-types/ca/caregiving-binder/manifest.json +4 -0
- package/data/project-types/de/design-scheme/manifest.json +4 -0
- package/data/project-types/fi/fitness-coach/manifest.json +4 -0
- package/data/project-types/fr/freelance-office/manifest.json +3 -0
- package/data/project-types/fu/fundraiser-hq/manifest.json +4 -0
- package/data/project-types/ho/household-budget/manifest.json +3 -0
- package/data/project-types/index.json +1 -1
- package/data/project-types/jo/job-hunt/manifest.json +4 -0
- package/data/project-types/jo/job-hunt/versions/1.0.3/about.md +10 -0
- package/data/project-types/jo/job-hunt/versions/1.0.3/activity.json +4 -0
- package/data/project-types/jo/job-hunt/versions/1.0.3/manifest.json +212 -0
- package/data/project-types/jo/job-hunt/versions/1.0.3/mission.md +9 -0
- package/data/project-types/jo/job-hunt/versions/1.0.3/pages/dashboard/index.html +430 -0
- package/data/project-types/jo/job-hunt/versions/1.0.3/pipeline.json +6 -0
- package/data/project-types/li/life-binder/manifest.json +4 -0
- package/data/project-types/raw-index.json +1 -1
- package/data/project-types/so/social-feed/manifest.json +3 -0
- package/data/project-types/tr/trip-planner/versions/1.0.3/about.md +7 -0
- package/data/project-types/tr/trip-planner/versions/1.0.3/journal.json +4 -0
- package/data/project-types/tr/trip-planner/versions/1.0.3/manifest.json +226 -0
- package/data/project-types/tr/trip-planner/versions/1.0.3/mission.md +4 -0
- package/data/project-types/tr/trip-planner/versions/1.0.3/packing.json +8 -0
- package/data/project-types/tr/trip-planner/versions/1.0.3/pages/dashboard/index.html +368 -0
- package/data/project-types/tr/trip-planner/versions/1.0.3/trip.json +8 -0
- package/data/toolsets/do/docblocks/versions/2.7.0/manifest.json +95 -0
- package/data/toolsets/index.json +1 -1
- package/data/toolsets/raw-index.json +1 -1
- package/data/video-models/index.json +1 -1
- package/data/video-models/lt/ltx-2-19b/versions/1.0.1/manifest.json +375 -0
- package/data/video-models/lt/ltx-2.3-22b/versions/1.0.1/manifest.json +377 -0
- package/data/video-models/lt/ltx-2.3-22b-distilled/versions/1.0.1/manifest.json +377 -0
- package/data/video-models/lt/ltx-video-0.9.7-dev/versions/1.0.1/manifest.json +195 -0
- package/data/video-models/lt/ltx-video-0.9.8-13b-distilled/versions/1.0.1/manifest.json +190 -0
- package/data/video-models/raw-index.json +1 -1
- package/data/video-models/wa/wan2.2-ti2v-5b/versions/1.0.1/manifest.json +168 -0
- package/package.json +2 -1
- package/schemas/craftbook-doc.schema.json +35 -0
- package/schemas/craftbook-template-identity.schema.json +18 -0
- package/schemas/craftbook-template-version.schema.json +35 -0
- package/schemas/image-model-identity.schema.json +0 -2
- package/schemas/image-model-version.schema.json +50 -0
- package/schemas/project-type-identity.schema.json +18 -0
- package/schemas/video-model-identity.schema.json +0 -2
- package/schemas/video-model-version.schema.json +25 -0
- package/data/image-models/fl/flux-1-dev-q4/manifest.json +0 -38
- package/data/image-models/fl/flux-1-dev-q4/versions/1.0.0/manifest.json +0 -29
- package/data/image-models/fl/flux-1-schnell-q4/manifest.json +0 -39
- package/data/image-models/fl/flux-1-schnell-q4/versions/1.0.0/manifest.json +0 -29
|
@@ -4,6 +4,9 @@
|
|
|
4
4
|
"id": "reading-list",
|
|
5
5
|
"role": "general",
|
|
6
6
|
"category": "research",
|
|
7
|
+
"interests": [
|
|
8
|
+
"learning"
|
|
9
|
+
],
|
|
7
10
|
"name": "Curated Annotated Reading List",
|
|
8
11
|
"description": "Curate an annotated reading list on a topic for a defined reader: a planner sets the reader, their goal, and the selection and ordering criteria, then a researcher curates and annotates each pick with why it matters, what it covers, and a suggested reading order. The ordering matters because a list assembled without a reader and a goal becomes a random link dump, and one without annotations forces the reader to guess what to read first; fixing who it is for and what 'good for this reader' means up front turns it into a guided learning path. Use this for curated reading lists, a syllabus or learning path, 'what should I read to learn X', resource roundups, and annotated bibliographies of recommended materials.",
|
|
9
12
|
"tags": [
|
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
"id": "receipt-intake",
|
|
5
5
|
"role": "general",
|
|
6
6
|
"category": "business",
|
|
7
|
+
"interests": [
|
|
8
|
+
"home",
|
|
9
|
+
"business"
|
|
10
|
+
],
|
|
7
11
|
"name": "Receipt Intake",
|
|
8
12
|
"description": "Empty the shoebox inbox properly: every waiting receipt becomes a dated, categorized ledger entry that names its source file, likely duplicates get flagged instead of double-counted, and the genuinely ambiguous ones become owner questions instead of guesses. Locks the intake rules FIRST, then works the inbox receipt by receipt, then reports the totals and the question list — the year-round habit that makes April an afternoon. Use for receipt intake, emptying the receipt inbox, 'get these into the ledger', and monthly shoebox catch-ups.",
|
|
9
13
|
"tags": [
|
|
@@ -4,6 +4,9 @@
|
|
|
4
4
|
"id": "receipt-ocr-ledger",
|
|
5
5
|
"role": "general",
|
|
6
6
|
"category": "business",
|
|
7
|
+
"interests": [
|
|
8
|
+
"business"
|
|
9
|
+
],
|
|
7
10
|
"name": "Receipts to Expense Ledger",
|
|
8
11
|
"description": "Turn a folder of receipt photos/PDFs into a clean expense ledger: OCR each receipt, extract vendor, date, line items, tax, and total, assign an expense category, and reconcile that each extracted total matches its line items. Locks the per-receipt field schema, the category set, and the math/reconciliation rules FIRST, then OCRs and extracts each receipt into rows, then verifies every receipt was processed, totals reconcile, currencies/dates are normalized, and low-confidence reads are flagged for review. Defining the schema and the total-equals-line-items check before extraction is what keeps an expense ledger trustworthy for reimbursement or tax.",
|
|
9
12
|
"tags": [
|
|
@@ -4,6 +4,9 @@
|
|
|
4
4
|
"id": "recurring-invoice-run",
|
|
5
5
|
"role": "general",
|
|
6
6
|
"category": "business",
|
|
7
|
+
"interests": [
|
|
8
|
+
"business"
|
|
9
|
+
],
|
|
7
10
|
"name": "Generate and Send Recurring Invoices",
|
|
8
11
|
"description": "Run a recurring billing batch: for each active client/subscription due this period, generate a correctly-numbered, line-itemed invoice with taxes and totals, render it, and send it — once, idempotently, with a sent-log. Locks the invoice template, the numbering scheme, the tax/total math, and the due/idempotency rules FIRST, then builds the generate-render-send batch keyed to a billing-run log, then verifies every due client was invoiced exactly once, totals are arithmetically correct, and numbers are sequential with no gaps or dupes. Locking numbering and math up front is what keeps recurring billing audit-clean instead of producing duplicate or mis-totaled invoices.",
|
|
9
12
|
"tags": [
|
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
"id": "release-announcement",
|
|
5
5
|
"role": "general",
|
|
6
6
|
"category": "marketing",
|
|
7
|
+
"interests": [
|
|
8
|
+
"software",
|
|
9
|
+
"content"
|
|
10
|
+
],
|
|
7
11
|
"name": "Release Announcement",
|
|
8
12
|
"description": "Write a public-facing release announcement that turns a shipped version into a compelling story for users — a blog-post / email-style piece that leads with the headline value, shows the marquee features with concrete before/after benefits, links to the full release notes and upgrade path, and ends with a clear call to action. A planner picks the 2-4 things actually worth announcing and the audience/channel, a copywriter writes the benefit-led announcement in the brand voice, and a reviewer checks it is accurate, on-message, and that every claim traces to a real shipped change. Use this for product launch posts, 'what's new' announcements, version launch emails, and changelog-to-marketing translations.",
|
|
9
13
|
"tags": [
|
|
@@ -4,6 +4,9 @@
|
|
|
4
4
|
"id": "resume-cv",
|
|
5
5
|
"role": "general",
|
|
6
6
|
"category": "business",
|
|
7
|
+
"interests": [
|
|
8
|
+
"learning"
|
|
9
|
+
],
|
|
7
10
|
"name": "Résumé / CV",
|
|
8
11
|
"description": "Build a clean, ATS-friendly résumé or CV from a person's background, tailored to a target role. Scopes the target role and the highlight reel of achievements FIRST (so the résumé is targeted, not a life history), then designs a single-column, parser-safe layout, then writes impact-led bullets with metrics that fit one to two pages. Use for job applications, LinkedIn-to-résumé conversions, and role-targeted CV rewrites.",
|
|
9
12
|
"tags": [
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"kind": "craftbook-template",
|
|
4
|
+
"id": "review-code-folder",
|
|
5
|
+
"role": "general",
|
|
6
|
+
"category": "code-review",
|
|
7
|
+
"interests": [
|
|
8
|
+
"software"
|
|
9
|
+
],
|
|
10
|
+
"name": "Review a code folder",
|
|
11
|
+
"description": "A careful colleague's review of a folder of code: a short summary, each real problem with its file and line, how serious it is, what goes wrong and a suggested fix, and what the code does well. It reads the code without running it and reports only problems it can point to in a line.",
|
|
12
|
+
"tags": [
|
|
13
|
+
"gallery",
|
|
14
|
+
"first-project",
|
|
15
|
+
"code",
|
|
16
|
+
"review",
|
|
17
|
+
"bugs",
|
|
18
|
+
"quality"
|
|
19
|
+
],
|
|
20
|
+
"maintainer": {
|
|
21
|
+
"name": "Gezel"
|
|
22
|
+
},
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"yankedVersions": []
|
|
25
|
+
}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "review-code-folder",
|
|
3
|
+
"name": "Review a code folder",
|
|
4
|
+
"description": "A careful colleague's review of a folder of code: a short summary, each real problem with its file and line, how serious it is, what goes wrong and a suggested fix, and what the code does well. It reads the code without running it and reports only problems it can point to in a line.\n\nIt works on the folder you choose when you launch it: a folder in this project, or one you pick from your computer. It never runs or changes the code. No code to hand? Try it on the sample, a small to-do app.",
|
|
5
|
+
"entryStepId": "review",
|
|
6
|
+
"triggers": [
|
|
7
|
+
"review a code folder",
|
|
8
|
+
"review this folder of code",
|
|
9
|
+
"find bugs in this code",
|
|
10
|
+
"what is wrong with this code"
|
|
11
|
+
],
|
|
12
|
+
"samples": [
|
|
13
|
+
{
|
|
14
|
+
"id": "todo-cli-bugs",
|
|
15
|
+
"title": "a small to-do app's code",
|
|
16
|
+
"param": "source",
|
|
17
|
+
"files": [
|
|
18
|
+
"samples/todo-cli-bugs/README.md",
|
|
19
|
+
"samples/todo-cli-bugs/package.json",
|
|
20
|
+
"samples/todo-cli-bugs/src/index.js",
|
|
21
|
+
"samples/todo-cli-bugs/src/store.js",
|
|
22
|
+
"samples/todo-cli-bugs/src/format.js",
|
|
23
|
+
"samples/todo-cli-bugs/test/store.test.js"
|
|
24
|
+
]
|
|
25
|
+
}
|
|
26
|
+
],
|
|
27
|
+
"paramSchema": {
|
|
28
|
+
"type": "object",
|
|
29
|
+
"required": [
|
|
30
|
+
"source"
|
|
31
|
+
],
|
|
32
|
+
"properties": {
|
|
33
|
+
"source": {
|
|
34
|
+
"type": "string",
|
|
35
|
+
"title": "Code folder",
|
|
36
|
+
"description": "The folder of code to review: a folder in this project, or one you pick from your computer.",
|
|
37
|
+
"input": {
|
|
38
|
+
"kind": "folder",
|
|
39
|
+
"accept": [
|
|
40
|
+
".js",
|
|
41
|
+
".mjs",
|
|
42
|
+
".cjs",
|
|
43
|
+
".jsx",
|
|
44
|
+
".ts",
|
|
45
|
+
".tsx",
|
|
46
|
+
".py",
|
|
47
|
+
".rb",
|
|
48
|
+
".go",
|
|
49
|
+
".rs",
|
|
50
|
+
".java",
|
|
51
|
+
".kt",
|
|
52
|
+
".cs",
|
|
53
|
+
".php",
|
|
54
|
+
".swift",
|
|
55
|
+
".c",
|
|
56
|
+
".h",
|
|
57
|
+
".cpp",
|
|
58
|
+
".hpp",
|
|
59
|
+
".sh",
|
|
60
|
+
".sql",
|
|
61
|
+
".html",
|
|
62
|
+
".css",
|
|
63
|
+
".scss",
|
|
64
|
+
".vue",
|
|
65
|
+
".svelte",
|
|
66
|
+
".md",
|
|
67
|
+
".txt",
|
|
68
|
+
".json",
|
|
69
|
+
".toml",
|
|
70
|
+
".yaml",
|
|
71
|
+
".yml",
|
|
72
|
+
".ini",
|
|
73
|
+
".cfg",
|
|
74
|
+
".xml"
|
|
75
|
+
]
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
"workPath": {
|
|
79
|
+
"type": "string",
|
|
80
|
+
"title": "Working folder",
|
|
81
|
+
"description": "Per-task working folder in the artifacts drawer. Defaults to this task's own folder so runs never collide; override with a stable name when you deliberately want runs to share files.",
|
|
82
|
+
"default": "{{task.dir}}",
|
|
83
|
+
"askUser": false
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
"steps": [
|
|
88
|
+
{
|
|
89
|
+
"id": "review",
|
|
90
|
+
"name": "Review the code",
|
|
91
|
+
"description": "Read the code and write a review of the real problems in it.",
|
|
92
|
+
"prompt": "Review the code in the `source` input the way a careful colleague would, and write the review to `{{workPath}}/review.md`.\n\n1. Open the file list `{{task.dir}}/inputs/source.json` with `read_artifact`. It lists every file in the folder and the drawer they are in.\n2. Read every source file and test with the tool named on the `source` line under Invocation parameters. If there are more than 20, read the entry point and the files it uses first, 20 at most.\n3. Look for real defects. Follow one concrete input through each function: does it return the right thing, change the right item, save what it changed, wait for what it starts, and handle the errors it can hit? Watch for counting that is off by one, a missing `await`, a change that is never saved, an error that is swallowed, input that is never checked, and a crash on an empty or missing value.\n4. Write `{{workPath}}/review.md` with `write_artifact`, under exactly these three headings:\n - `## Summary`: two or three sentences on what the code does and how sound it is.\n - `## Findings`: one entry per real problem, the most serious first. Give each one its file and line (`path/to/file.js:12`), a severity of high, medium or low, what goes wrong with a concrete example, and a suggested fix. If you find no real problem, write `No problems found.`\n - `## What is good`: two or three things the code does well.\n\nReport only problems you can point to in a line of the code you read. Never invent a file, a line or a bug, and do not pad the list: one real finding beats five guesses.\n\nIf the folder holds no file you can read, do not write `review.md`. Write a task note with `write_task_note` that says what you found, then end your turn.",
|
|
93
|
+
"suggestedRole": "reviewer",
|
|
94
|
+
"toolPolicy": {
|
|
95
|
+
"disallowBuiltinToolsets": [
|
|
96
|
+
"ai-apps",
|
|
97
|
+
"archives",
|
|
98
|
+
"audio",
|
|
99
|
+
"browser-automation",
|
|
100
|
+
"code-execution",
|
|
101
|
+
"craftbooks",
|
|
102
|
+
"data-tables",
|
|
103
|
+
"entity-intel",
|
|
104
|
+
"git",
|
|
105
|
+
"image-intel",
|
|
106
|
+
"images",
|
|
107
|
+
"role-delegation",
|
|
108
|
+
"role-delegation-escalation",
|
|
109
|
+
"security-intel",
|
|
110
|
+
"team-management",
|
|
111
|
+
"videos",
|
|
112
|
+
"web",
|
|
113
|
+
"workspace-fs-write"
|
|
114
|
+
],
|
|
115
|
+
"outputMedium": "artifact",
|
|
116
|
+
"additionalOutputMedia": [
|
|
117
|
+
"task-note"
|
|
118
|
+
]
|
|
119
|
+
},
|
|
120
|
+
"consumes": [
|
|
121
|
+
{
|
|
122
|
+
"file": "{{task.dir}}/inputs/source.json",
|
|
123
|
+
"artifact": true
|
|
124
|
+
}
|
|
125
|
+
],
|
|
126
|
+
"advanceWhen": {
|
|
127
|
+
"file": "{{workPath}}/review.md",
|
|
128
|
+
"minBytes": 1,
|
|
129
|
+
"sniff": "nonempty",
|
|
130
|
+
"artifact": true
|
|
131
|
+
},
|
|
132
|
+
"gate": {
|
|
133
|
+
"at": "completion",
|
|
134
|
+
"checks": [
|
|
135
|
+
{
|
|
136
|
+
"kind": "minBytes",
|
|
137
|
+
"file": "{{workPath}}/review.md",
|
|
138
|
+
"bytes": 300,
|
|
139
|
+
"artifact": true
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
"kind": "contains",
|
|
143
|
+
"file": "{{workPath}}/review.md",
|
|
144
|
+
"pattern": "(?:^|\\n)#{1,3}\\s*Summary",
|
|
145
|
+
"flags": "i",
|
|
146
|
+
"label": "a \"## Summary\" section",
|
|
147
|
+
"artifact": true
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
"kind": "contains",
|
|
151
|
+
"file": "{{workPath}}/review.md",
|
|
152
|
+
"pattern": "(?:^|\\n)#{1,3}\\s*Findings",
|
|
153
|
+
"flags": "i",
|
|
154
|
+
"label": "a \"## Findings\" section",
|
|
155
|
+
"artifact": true
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
"kind": "contains",
|
|
159
|
+
"file": "{{workPath}}/review.md",
|
|
160
|
+
"pattern": "(?:^|\\n)#{1,3}\\s*What is good",
|
|
161
|
+
"flags": "i",
|
|
162
|
+
"label": "a \"## What is good\" section",
|
|
163
|
+
"artifact": true
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
"kind": "contains",
|
|
167
|
+
"file": "{{workPath}}/review.md",
|
|
168
|
+
"pattern": "[\\w./-]+\\.[A-Za-z0-9]{1,10}`?\\s*(?::|,?\\s*\\(?lines?\\s*)\\d+|lines?\\s+\\d+\\s+(?:of|in)\\s+`?[\\w./-]+\\.[A-Za-z0-9]{1,10}|No problems found",
|
|
169
|
+
"flags": "i",
|
|
170
|
+
"label": "a finding that names its file and line, or \"No problems found.\"",
|
|
171
|
+
"artifact": true
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
"kind": "contains",
|
|
175
|
+
"file": "{{workPath}}/review.md",
|
|
176
|
+
"pattern": "\\b(?:high|medium|low)\\b|No problems found",
|
|
177
|
+
"flags": "i",
|
|
178
|
+
"label": "a severity of high, medium or low on the findings",
|
|
179
|
+
"artifact": true
|
|
180
|
+
}
|
|
181
|
+
],
|
|
182
|
+
"onReject": "review",
|
|
183
|
+
"maxAttempts": 3
|
|
184
|
+
},
|
|
185
|
+
"next": "finish"
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
"id": "finish",
|
|
189
|
+
"name": "Finish",
|
|
190
|
+
"description": "The deliverable passed its checks. Stamp a short summary and report DONE.",
|
|
191
|
+
"prompt": "The deliverable passed its checks. Write a one-paragraph DONE summary to task notes via `write_task_note`: what you made, the deliverable path(s), and a one-line confirmation that each required section is there. Then report DONE.",
|
|
192
|
+
"suggestedRole": "reviewer",
|
|
193
|
+
"toolPolicy": {
|
|
194
|
+
"disallowBuiltinToolsets": [
|
|
195
|
+
"ai-apps",
|
|
196
|
+
"archives",
|
|
197
|
+
"artifacts",
|
|
198
|
+
"audio",
|
|
199
|
+
"browser-automation",
|
|
200
|
+
"code-execution",
|
|
201
|
+
"craftbooks",
|
|
202
|
+
"data-tables",
|
|
203
|
+
"entity-intel",
|
|
204
|
+
"git",
|
|
205
|
+
"image-intel",
|
|
206
|
+
"images",
|
|
207
|
+
"role-delegation",
|
|
208
|
+
"role-delegation-escalation",
|
|
209
|
+
"security-intel",
|
|
210
|
+
"team-management",
|
|
211
|
+
"videos",
|
|
212
|
+
"web",
|
|
213
|
+
"workspace-fs-write"
|
|
214
|
+
],
|
|
215
|
+
"outputMedium": "task-note"
|
|
216
|
+
},
|
|
217
|
+
"terminal": true
|
|
218
|
+
}
|
|
219
|
+
],
|
|
220
|
+
"version": "1.0.0",
|
|
221
|
+
"releasedAt": "2026-10-12T00:00:00Z",
|
|
222
|
+
"minGezelVersion": "1.26285"
|
|
223
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# todo-cli
|
|
2
|
+
|
|
3
|
+
A tiny to-do list for the command line. It keeps your to-dos in a JSON file
|
|
4
|
+
in the current folder, so each project folder can have its own list.
|
|
5
|
+
|
|
6
|
+
## Usage
|
|
7
|
+
|
|
8
|
+
```sh
|
|
9
|
+
node src/index.js add "Buy oat milk"
|
|
10
|
+
node src/index.js list
|
|
11
|
+
node src/index.js done 2
|
|
12
|
+
node src/index.js remove 1
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
`list` prints every to-do with its number. `done` and `remove` take that
|
|
16
|
+
number. Set `TODO_FILE` to keep the list somewhere else:
|
|
17
|
+
|
|
18
|
+
```sh
|
|
19
|
+
TODO_FILE=~/todos.json node src/index.js list
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Tests
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
npm test
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
The tests use Node's built-in test runner (Node 18 or newer). There are no
|
|
29
|
+
dependencies to install.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "todo-cli",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "A tiny to-do list for the command line.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"todo": "src/index.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"start": "node src/index.js",
|
|
11
|
+
"test": "node --test"
|
|
12
|
+
},
|
|
13
|
+
"engines": {
|
|
14
|
+
"node": ">=18"
|
|
15
|
+
},
|
|
16
|
+
"license": "MIT"
|
|
17
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export function formatTodo(todo, index) {
|
|
2
|
+
const box = todo.done ? '[x]' : '[ ]';
|
|
3
|
+
return `${String(index + 1).padStart(2)}. ${box} ${todo.text}`;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export function formatList(todos) {
|
|
7
|
+
if (todos.length === 0) return 'Nothing to do. Add one with: todo add "..."';
|
|
8
|
+
return todos.map(formatTodo).join('\n');
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function formatSummary(todos) {
|
|
12
|
+
const open = todos.filter((todo) => !todo.done).length;
|
|
13
|
+
const word = open === 1 ? 'to-do' : 'to-dos';
|
|
14
|
+
return `${open} open ${word}, ${todos.length - open} done.`;
|
|
15
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { formatList, formatSummary } from './format.js';
|
|
3
|
+
import { addTodo, completeTodo, loadTodos, removeTodo } from './store.js';
|
|
4
|
+
|
|
5
|
+
const file = process.env.TODO_FILE ?? 'todos.json';
|
|
6
|
+
const [command, ...rest] = process.argv.slice(2);
|
|
7
|
+
|
|
8
|
+
function readNumber(value) {
|
|
9
|
+
const number = Number(value);
|
|
10
|
+
if (!Number.isInteger(number) || number < 1) {
|
|
11
|
+
throw new Error(`"${value}" is not a to-do number. Run "todo list" to see the numbers.`);
|
|
12
|
+
}
|
|
13
|
+
return number;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async function main() {
|
|
17
|
+
switch (command) {
|
|
18
|
+
case 'add': {
|
|
19
|
+
const text = rest.join(' ').trim();
|
|
20
|
+
if (!text) throw new Error('Say what to add: todo add "Buy oat milk"');
|
|
21
|
+
const todo = await addTodo(file, text);
|
|
22
|
+
console.log(`Added: ${todo.text}`);
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
case 'list': {
|
|
26
|
+
const todos = await loadTodos(file);
|
|
27
|
+
console.log(formatList(todos));
|
|
28
|
+
console.log(formatSummary(todos));
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
case 'done': {
|
|
32
|
+
const todo = await completeTodo(file, readNumber(rest[0]));
|
|
33
|
+
console.log(`Done: ${todo.text}`);
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
case 'remove': {
|
|
37
|
+
const todo = await removeTodo(file, readNumber(rest[0]));
|
|
38
|
+
console.log(`Removed: ${todo.text}`);
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
default:
|
|
42
|
+
console.log('Usage: todo <add|list|done|remove> [text or number]');
|
|
43
|
+
process.exitCode = command ? 1 : 0;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
main().catch((error) => {
|
|
48
|
+
console.error(error.message);
|
|
49
|
+
process.exitCode = 1;
|
|
50
|
+
});
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
2
|
+
|
|
3
|
+
export async function loadTodos(file) {
|
|
4
|
+
try {
|
|
5
|
+
const text = await readFile(file, 'utf8');
|
|
6
|
+
return JSON.parse(text);
|
|
7
|
+
} catch (error) {
|
|
8
|
+
if (error.code === 'ENOENT') return [];
|
|
9
|
+
throw error;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export async function saveTodos(file, todos) {
|
|
14
|
+
await writeFile(file, `${JSON.stringify(todos, null, 2)}\n`);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export async function addTodo(file, text) {
|
|
18
|
+
const todos = await loadTodos(file);
|
|
19
|
+
const todo = { text, done: false, added: new Date().toISOString().slice(0, 10) };
|
|
20
|
+
todos.push(todo);
|
|
21
|
+
await saveTodos(file, todos);
|
|
22
|
+
return todo;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function pick(todos, number) {
|
|
26
|
+
const todo = todos[number - 1];
|
|
27
|
+
if (!todo) throw new Error(`There is no to-do number ${number}.`);
|
|
28
|
+
return todo;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export async function completeTodo(file, number) {
|
|
32
|
+
const todos = await loadTodos(file);
|
|
33
|
+
const todo = pick(todos, number);
|
|
34
|
+
todo.done = true;
|
|
35
|
+
return todo;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export async function removeTodo(file, number) {
|
|
39
|
+
const todos = await loadTodos(file);
|
|
40
|
+
pick(todos, number);
|
|
41
|
+
const [removed] = todos.splice(number, 1);
|
|
42
|
+
await saveTodos(file, todos);
|
|
43
|
+
return removed;
|
|
44
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import { mkdtemp, rm } from 'node:fs/promises';
|
|
3
|
+
import { tmpdir } from 'node:os';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
import { test } from 'node:test';
|
|
6
|
+
import { addTodo, loadTodos, removeTodo } from '../src/store.js';
|
|
7
|
+
|
|
8
|
+
async function withFile(run) {
|
|
9
|
+
const dir = await mkdtemp(join(tmpdir(), 'todo-cli-'));
|
|
10
|
+
try {
|
|
11
|
+
await run(join(dir, 'todos.json'));
|
|
12
|
+
} finally {
|
|
13
|
+
await rm(dir, { recursive: true, force: true });
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
test('a missing file is an empty list', () =>
|
|
18
|
+
withFile(async (file) => {
|
|
19
|
+
assert.deepEqual(await loadTodos(file), []);
|
|
20
|
+
}));
|
|
21
|
+
|
|
22
|
+
test('add keeps to-dos in the order they were added', () =>
|
|
23
|
+
withFile(async (file) => {
|
|
24
|
+
await addTodo(file, 'Buy oat milk');
|
|
25
|
+
await addTodo(file, 'Call the plumber');
|
|
26
|
+
const todos = await loadTodos(file);
|
|
27
|
+
assert.deepEqual(
|
|
28
|
+
todos.map((todo) => todo.text),
|
|
29
|
+
['Buy oat milk', 'Call the plumber'],
|
|
30
|
+
);
|
|
31
|
+
}));
|
|
32
|
+
|
|
33
|
+
test('a number past the end is an error', () =>
|
|
34
|
+
withFile(async (file) => {
|
|
35
|
+
await addTodo(file, 'Buy oat milk');
|
|
36
|
+
await assert.rejects(removeTodo(file, 3), /no to-do number 3/);
|
|
37
|
+
}));
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"mode": "workflow",
|
|
4
|
+
"title": "Review a code folder on the todo-cli-bugs sample",
|
|
5
|
+
"objective": "Prove that a small local model can run the Review a code folder craftbook on its bundled todo-cli-bugs sample, offline, and reach the terminal step with a review that finds the two real defects in store.js with their lines.",
|
|
6
|
+
"tags": [
|
|
7
|
+
"first-project",
|
|
8
|
+
"sample",
|
|
9
|
+
"code"
|
|
10
|
+
],
|
|
11
|
+
"prompt": "Review the code of this small to-do app and tell me what is wrong with it.",
|
|
12
|
+
"setup": {
|
|
13
|
+
"projectName": "Todo CLI review",
|
|
14
|
+
"about": "A tiny made-up Node.js to-do app for the command line, six files in source/todo-cli-bugs. Nothing needs to be run or installed; read the code.",
|
|
15
|
+
"missionObjectives": "Run the craftbook on source/todo-cli-bugs and leave review.md in the task folder, reporting only problems that can be pointed to in a line.",
|
|
16
|
+
"files": [
|
|
17
|
+
{
|
|
18
|
+
"path": "source/todo-cli-bugs/README.md",
|
|
19
|
+
"content": "# todo-cli\n\nA tiny to-do list for the command line. It keeps your to-dos in a JSON file\nin the current folder, so each project folder can have its own list.\n\n## Usage\n\n```sh\nnode src/index.js add \"Buy oat milk\"\nnode src/index.js list\nnode src/index.js done 2\nnode src/index.js remove 1\n```\n\n`list` prints every to-do with its number. `done` and `remove` take that\nnumber. Set `TODO_FILE` to keep the list somewhere else:\n\n```sh\nTODO_FILE=~/todos.json node src/index.js list\n```\n\n## Tests\n\n```sh\nnpm test\n```\n\nThe tests use Node's built-in test runner (Node 18 or newer). There are no\ndependencies to install.\n"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"path": "source/todo-cli-bugs/package.json",
|
|
23
|
+
"content": "{\n \"name\": \"todo-cli\",\n \"version\": \"0.3.0\",\n \"description\": \"A tiny to-do list for the command line.\",\n \"type\": \"module\",\n \"bin\": {\n \"todo\": \"src/index.js\"\n },\n \"scripts\": {\n \"start\": \"node src/index.js\",\n \"test\": \"node --test\"\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"license\": \"MIT\"\n}\n"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"path": "source/todo-cli-bugs/src/format.js",
|
|
27
|
+
"content": "export function formatTodo(todo, index) {\n const box = todo.done ? '[x]' : '[ ]';\n return `${String(index + 1).padStart(2)}. ${box} ${todo.text}`;\n}\n\nexport function formatList(todos) {\n if (todos.length === 0) return 'Nothing to do. Add one with: todo add \"...\"';\n return todos.map(formatTodo).join('\\n');\n}\n\nexport function formatSummary(todos) {\n const open = todos.filter((todo) => !todo.done).length;\n const word = open === 1 ? 'to-do' : 'to-dos';\n return `${open} open ${word}, ${todos.length - open} done.`;\n}\n"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"path": "source/todo-cli-bugs/src/index.js",
|
|
31
|
+
"content": "#!/usr/bin/env node\nimport { formatList, formatSummary } from './format.js';\nimport { addTodo, completeTodo, loadTodos, removeTodo } from './store.js';\n\nconst file = process.env.TODO_FILE ?? 'todos.json';\nconst [command, ...rest] = process.argv.slice(2);\n\nfunction readNumber(value) {\n const number = Number(value);\n if (!Number.isInteger(number) || number < 1) {\n throw new Error(`\"${value}\" is not a to-do number. Run \"todo list\" to see the numbers.`);\n }\n return number;\n}\n\nasync function main() {\n switch (command) {\n case 'add': {\n const text = rest.join(' ').trim();\n if (!text) throw new Error('Say what to add: todo add \"Buy oat milk\"');\n const todo = await addTodo(file, text);\n console.log(`Added: ${todo.text}`);\n break;\n }\n case 'list': {\n const todos = await loadTodos(file);\n console.log(formatList(todos));\n console.log(formatSummary(todos));\n break;\n }\n case 'done': {\n const todo = await completeTodo(file, readNumber(rest[0]));\n console.log(`Done: ${todo.text}`);\n break;\n }\n case 'remove': {\n const todo = await removeTodo(file, readNumber(rest[0]));\n console.log(`Removed: ${todo.text}`);\n break;\n }\n default:\n console.log('Usage: todo <add|list|done|remove> [text or number]');\n process.exitCode = command ? 1 : 0;\n }\n}\n\nmain().catch((error) => {\n console.error(error.message);\n process.exitCode = 1;\n});\n"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"path": "source/todo-cli-bugs/src/store.js",
|
|
35
|
+
"content": "import { readFile, writeFile } from 'node:fs/promises';\n\nexport async function loadTodos(file) {\n try {\n const text = await readFile(file, 'utf8');\n return JSON.parse(text);\n } catch (error) {\n if (error.code === 'ENOENT') return [];\n throw error;\n }\n}\n\nexport async function saveTodos(file, todos) {\n await writeFile(file, `${JSON.stringify(todos, null, 2)}\\n`);\n}\n\nexport async function addTodo(file, text) {\n const todos = await loadTodos(file);\n const todo = { text, done: false, added: new Date().toISOString().slice(0, 10) };\n todos.push(todo);\n await saveTodos(file, todos);\n return todo;\n}\n\nfunction pick(todos, number) {\n const todo = todos[number - 1];\n if (!todo) throw new Error(`There is no to-do number ${number}.`);\n return todo;\n}\n\nexport async function completeTodo(file, number) {\n const todos = await loadTodos(file);\n const todo = pick(todos, number);\n todo.done = true;\n return todo;\n}\n\nexport async function removeTodo(file, number) {\n const todos = await loadTodos(file);\n pick(todos, number);\n const [removed] = todos.splice(number, 1);\n await saveTodos(file, todos);\n return removed;\n}\n"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"path": "source/todo-cli-bugs/test/store.test.js",
|
|
39
|
+
"content": "import assert from 'node:assert/strict';\nimport { mkdtemp, rm } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport { test } from 'node:test';\nimport { addTodo, loadTodos, removeTodo } from '../src/store.js';\n\nasync function withFile(run) {\n const dir = await mkdtemp(join(tmpdir(), 'todo-cli-'));\n try {\n await run(join(dir, 'todos.json'));\n } finally {\n await rm(dir, { recursive: true, force: true });\n }\n}\n\ntest('a missing file is an empty list', () =>\n withFile(async (file) => {\n assert.deepEqual(await loadTodos(file), []);\n }));\n\ntest('add keeps to-dos in the order they were added', () =>\n withFile(async (file) => {\n await addTodo(file, 'Buy oat milk');\n await addTodo(file, 'Call the plumber');\n const todos = await loadTodos(file);\n assert.deepEqual(\n todos.map((todo) => todo.text),\n ['Buy oat milk', 'Call the plumber'],\n );\n }));\n\ntest('a number past the end is an error', () =>\n withFile(async (file) => {\n await addTodo(file, 'Buy oat milk');\n await assert.rejects(removeTodo(file, 3), /no to-do number 3/);\n }));\n"
|
|
40
|
+
}
|
|
41
|
+
],
|
|
42
|
+
"craftbookParams": {
|
|
43
|
+
"source": "source/todo-cli-bugs"
|
|
44
|
+
},
|
|
45
|
+
"worker": {
|
|
46
|
+
"name": "Reviewer",
|
|
47
|
+
"role": "reviewer",
|
|
48
|
+
"about": "A careful, fair code reviewer. Follow the craftbook steps exactly, read the code you are given, and report only problems you can point to in a line."
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"mocks": [],
|
|
52
|
+
"success": {
|
|
53
|
+
"summary": "The review-code-folder task read the sample folder, wrote review.md with all three sections, found the off-by-one in removeTodo and the unsaved done flag in completeTodo with their lines, and reached its terminal step without external services.",
|
|
54
|
+
"deliverables": [
|
|
55
|
+
{
|
|
56
|
+
"path": "{{task.dir}}/review.md",
|
|
57
|
+
"kind": "markdown-report",
|
|
58
|
+
"artifact": true,
|
|
59
|
+
"minBytes": 300,
|
|
60
|
+
"checks": [
|
|
61
|
+
{
|
|
62
|
+
"kind": "contains",
|
|
63
|
+
"file": "{{task.dir}}/review.md",
|
|
64
|
+
"pattern": "splice\\(\\s*number\\s*,|off[- ]by[- ]one|wrong (?:item|to-do|todo|entry)|next (?:item|to-do|todo)",
|
|
65
|
+
"flags": "i",
|
|
66
|
+
"label": "the off-by-one in removeTodo",
|
|
67
|
+
"artifact": true
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"kind": "contains",
|
|
71
|
+
"file": "{{task.dir}}/review.md",
|
|
72
|
+
"pattern": "(?:never|not|isn't|is not|doesn't|does not|without|missing|no)\\s+(?:\\w+\\s+){0,3}(?:sav\\w*|persist\\w*|writ\\w*|saveTodos)",
|
|
73
|
+
"flags": "i",
|
|
74
|
+
"label": "the done flag that is never saved",
|
|
75
|
+
"artifact": true
|
|
76
|
+
}
|
|
77
|
+
]
|
|
78
|
+
}
|
|
79
|
+
],
|
|
80
|
+
"taskGraph": {
|
|
81
|
+
"requireCraftbookTask": true,
|
|
82
|
+
"requireTerminalStep": true
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
"rubric": {
|
|
86
|
+
"artifact": {
|
|
87
|
+
"path": "{{task.dir}}/review.md",
|
|
88
|
+
"kind": "markdown"
|
|
89
|
+
},
|
|
90
|
+
"axes": [
|
|
91
|
+
{
|
|
92
|
+
"name": "accuracy",
|
|
93
|
+
"description": "The findings are the two real defects (removeTodo removes the item after the one asked for; completeTodo never saves the done flag), each with its file and line, and no invented bugs."
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"name": "usefulness",
|
|
97
|
+
"description": "Each finding has a fair severity, a concrete example of what goes wrong, and a fix a developer could apply as written."
|
|
98
|
+
}
|
|
99
|
+
],
|
|
100
|
+
"contextNote": "Advisory only. Deterministic pass/fail comes from the craftbook runtime gates, the deliverable checks, attribution, and terminal progress."
|
|
101
|
+
},
|
|
102
|
+
"qualityFocus": [
|
|
103
|
+
"real review-code-folder craftbook task attribution",
|
|
104
|
+
"findings pointed to a file and line",
|
|
105
|
+
"no invented bugs",
|
|
106
|
+
"terminal workflow progress offline"
|
|
107
|
+
]
|
|
108
|
+
}
|
|
@@ -4,6 +4,9 @@
|
|
|
4
4
|
"id": "scrape-to-structured",
|
|
5
5
|
"role": "general",
|
|
6
6
|
"category": "code-data",
|
|
7
|
+
"interests": [
|
|
8
|
+
"data"
|
|
9
|
+
],
|
|
7
10
|
"name": "Scrape a Site to Structured Data",
|
|
8
11
|
"description": "Turn one or more web pages into a clean, structured dataset (JSON or CSV) with a fixed schema — product listings, directory entries, articles, tables, or job posts. Scopes the exact fields and a sample-row target FIRST so extraction is verifiable, then crawls and parses each page into rows, then validates that every row matches the schema, types are coerced, required fields are non-empty, and there are no duplicates. The scope-before-scrape ordering is the point: a small model that locks the field list and one hand-written sample row extracts consistently instead of inventing keys per page.",
|
|
9
12
|
"tags": [
|
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
"id": "spa-dashboard",
|
|
5
5
|
"role": "project-starter",
|
|
6
6
|
"category": "code-build",
|
|
7
|
+
"interests": [
|
|
8
|
+
"software",
|
|
9
|
+
"data"
|
|
10
|
+
],
|
|
7
11
|
"name": "Metrics / Admin Dashboard",
|
|
8
12
|
"description": "Build a single-page metrics or admin dashboard with KPI summary cards, at least one chart, and a data table, rendered from sample or provided data. Locks the data model and which metrics matter first, then a scannable dashboard layout (grid of cards, chart placement, table), then builds the interactive HTML with a lightweight charting approach and a sortable/filterable table. Deciding the metrics and layout before coding prevents a small model from dumping raw data with no hierarchy; a dashboard's value is the at-a-glance summary up top.",
|
|
9
13
|
"tags": [
|