@bendyline/gilde 0.1.16 → 0.1.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/README.md +5 -1
  2. package/authoring/gstack/LICENSE.gstack +21 -0
  3. package/authoring/gstack/README.md +50 -0
  4. package/authoring/gstack/evals/cso.json +152 -0
  5. package/authoring/gstack/evals/design-consultation.json +201 -0
  6. package/authoring/gstack/evals/document-generate.json +174 -0
  7. package/authoring/gstack/evals/investigate.json +153 -0
  8. package/authoring/gstack/evals/office-hours.json +141 -0
  9. package/authoring/gstack/evals/plan-ceo-review.json +135 -0
  10. package/authoring/gstack/evals/qa-only.json +376 -0
  11. package/authoring/gstack/evals/retro.json +191 -0
  12. package/authoring/gstack/evals/spec.json +162 -0
  13. package/authoring/gstack/overlays/cso.json +132 -0
  14. package/authoring/gstack/overlays/design-consultation.json +153 -0
  15. package/authoring/gstack/overlays/document-generate.json +124 -0
  16. package/authoring/gstack/overlays/investigate.json +128 -0
  17. package/authoring/gstack/overlays/office-hours.json +119 -0
  18. package/authoring/gstack/overlays/plan-ceo-review.json +128 -0
  19. package/authoring/gstack/overlays/qa-only.json +145 -0
  20. package/authoring/gstack/overlays/retro.json +132 -0
  21. package/authoring/gstack/overlays/spec.json +140 -0
  22. package/authoring/gstack/persona-drafts/cso.about.md +9 -0
  23. package/authoring/gstack/persona-drafts/design-consultation.about.md +9 -0
  24. package/authoring/gstack/persona-drafts/office-hours.about.md +9 -0
  25. package/authoring/gstack/persona-drafts/qa-only.about.md +5 -0
  26. package/authoring/gstack/persona-drafts/spec.about.md +26 -0
  27. package/authoring/gstack/snapshots/cso/SKILL.md +1285 -0
  28. package/authoring/gstack/snapshots/design-consultation/SKILL.md +1230 -0
  29. package/authoring/gstack/snapshots/document-generate/SKILL.md +1252 -0
  30. package/authoring/gstack/snapshots/investigate/SKILL.md +1074 -0
  31. package/authoring/gstack/snapshots/office-hours/SKILL.md +1697 -0
  32. package/authoring/gstack/snapshots/plan-ceo-review/SKILL.md +1476 -0
  33. package/authoring/gstack/snapshots/qa-only/SKILL.md +1256 -0
  34. package/authoring/gstack/snapshots/retro/SKILL.md +1812 -0
  35. package/authoring/gstack/snapshots/spec/SKILL.md +2359 -0
  36. package/authoring/gstack/wave.json +103 -0
  37. package/data/connector-types/gi/github-releases/manifest.json +17 -0
  38. package/data/connector-types/gi/github-releases/versions/1.0.0/manifest.json +71 -0
  39. package/data/connector-types/index.json +1 -1
  40. package/data/craftbook-templates/br/branding-website/versions/1.1.0/craftbook.json +190 -0
  41. package/data/craftbook-templates/br/branding-website/versions/1.1.0/test.json +164 -0
  42. package/data/craftbook-templates/br/browser-qa-audit/versions/2.0.0/craftbook.json +358 -0
  43. package/data/craftbook-templates/br/browser-qa-audit/versions/2.0.0/test.json +376 -0
  44. package/data/craftbook-templates/ca/careful-mode/versions/1.1.0/craftbook.json +43 -0
  45. package/data/craftbook-templates/ca/careful-mode/versions/1.1.0/test.json +110 -0
  46. package/data/craftbook-templates/ca/careful-mode/versions/1.2.0/craftbook.json +43 -0
  47. package/data/craftbook-templates/ca/careful-mode/versions/1.2.0/test.json +110 -0
  48. package/data/craftbook-templates/co/content-deck/versions/1.1.0/craftbook.json +185 -0
  49. package/data/craftbook-templates/co/content-deck/versions/1.1.0/test.json +166 -0
  50. package/data/craftbook-templates/co/content-deck/versions/1.2.0/craftbook.json +185 -0
  51. package/data/craftbook-templates/co/content-deck/versions/1.2.0/test.json +169 -0
  52. package/data/craftbook-templates/co/corpus-email-digest/versions/1.1.0/craftbook.json +189 -0
  53. package/data/craftbook-templates/co/corpus-email-digest/versions/1.1.0/test.json +182 -0
  54. package/data/craftbook-templates/co/corpus-email-digest/versions/1.2.0/craftbook.json +189 -0
  55. package/data/craftbook-templates/co/corpus-email-digest/versions/1.2.0/test.json +187 -0
  56. package/data/craftbook-templates/de/design-system-consultation/versions/2.0.0/craftbook.json +385 -0
  57. package/data/craftbook-templates/de/design-system-consultation/versions/2.0.0/test.json +201 -0
  58. package/data/craftbook-templates/en/engineering-retrospective/versions/2.0.0/craftbook.json +353 -0
  59. package/data/craftbook-templates/en/engineering-retrospective/versions/2.0.0/test.json +191 -0
  60. package/data/craftbook-templates/ex/executive-level-review/versions/2.0.0/craftbook.json +347 -0
  61. package/data/craftbook-templates/ex/executive-level-review/versions/2.0.0/test.json +135 -0
  62. package/data/craftbook-templates/fr/freeze-scope/versions/1.2.0/craftbook.json +50 -0
  63. package/data/craftbook-templates/fr/freeze-scope/versions/1.2.0/test.json +131 -0
  64. package/data/craftbook-templates/fr/freeze-scope/versions/1.3.0/craftbook.json +50 -0
  65. package/data/craftbook-templates/fr/freeze-scope/versions/1.3.0/test.json +131 -0
  66. package/data/craftbook-templates/ht/html-arcade-game/versions/1.1.0/craftbook.json +197 -0
  67. package/data/craftbook-templates/ht/html-arcade-game/versions/1.1.0/test.json +173 -0
  68. package/data/craftbook-templates/ht/html-arcade-game/versions/1.2.0/craftbook.json +197 -0
  69. package/data/craftbook-templates/ht/html-arcade-game/versions/1.2.0/test.json +176 -0
  70. package/data/craftbook-templates/id/idea-office-hours/versions/2.0.0/craftbook.json +333 -0
  71. package/data/craftbook-templates/id/idea-office-hours/versions/2.0.0/test.json +141 -0
  72. package/data/craftbook-templates/im/image-set-index/versions/1.1.0/craftbook.json +163 -0
  73. package/data/craftbook-templates/im/image-set-index/versions/1.1.0/test.json +177 -0
  74. package/data/craftbook-templates/im/image-set-index/versions/1.2.0/craftbook.json +163 -0
  75. package/data/craftbook-templates/im/image-set-index/versions/1.2.0/test.json +180 -0
  76. package/data/craftbook-templates/index.json +1 -1
  77. package/data/craftbook-templates/po/powerpoint-deck/versions/1.6.0/craftbook.json +257 -0
  78. package/data/craftbook-templates/po/powerpoint-deck/versions/1.6.0/test.json +225 -0
  79. package/data/craftbook-templates/re/release-artifact-sanity-check/art.json +13 -0
  80. package/data/craftbook-templates/re/release-artifact-sanity-check/logo.webp +0 -0
  81. package/data/craftbook-templates/re/release-artifact-sanity-check/manifest.json +24 -0
  82. package/data/craftbook-templates/re/release-artifact-sanity-check/versions/1.0.0/craftbook.json +202 -0
  83. package/data/craftbook-templates/re/release-artifact-sanity-check/versions/1.0.0/test.json +138 -0
  84. package/data/craftbook-templates/ro/root-cause-investigation/versions/2.0.0/craftbook.json +348 -0
  85. package/data/craftbook-templates/ro/root-cause-investigation/versions/2.0.0/test.json +153 -0
  86. package/data/craftbook-templates/se/security-architecture-review/versions/2.0.0/craftbook.json +353 -0
  87. package/data/craftbook-templates/se/security-architecture-review/versions/2.0.0/test.json +152 -0
  88. package/data/craftbook-templates/sp/spec-authoring/versions/2.0.0/craftbook.json +391 -0
  89. package/data/craftbook-templates/sp/spec-authoring/versions/2.0.0/test.json +162 -0
  90. package/data/craftbook-templates/te/technical-documentation/versions/2.0.0/craftbook.json +343 -0
  91. package/data/craftbook-templates/te/technical-documentation/versions/2.0.0/test.json +174 -0
  92. package/data/craftbook-templates/tr/translate-content/versions/1.1.0/craftbook.json +84 -0
  93. package/data/craftbook-templates/tr/translate-content/versions/1.1.0/test.json +141 -0
  94. package/package.json +8 -4
  95. package/schemas/craftbook-test.schema.json +232 -3
@@ -0,0 +1,177 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "title": "Deterministic image-index workflow",
4
+ "objective": "Run the Index & Describe an Image Set craftbook against deterministic metadata, verifying schema-first staging, exact coverage, valid JSON, and no invented images.",
5
+ "tags": [
6
+ "media",
7
+ "json",
8
+ "workflow"
9
+ ],
10
+ "prompt": "Use the Index & Describe an Image Set craftbook. This text-only local-model eval supplies authoritative vision metadata in workspace `images/descriptions.csv`; read it as the sidecar for the four named images. Define the schema first, stage valid JSON in workspace `work/image-descriptions.json`, and write final workspace `index.json` as an object with an `images` array containing exactly one record per source filename. Each record must include filename, caption, tags, dominantColors, orientation, containsText, and qualityFlags. Use only the sidecar facts and report coverage as 4/4.",
11
+ "setup": {
12
+ "projectName": "Image Set Index Eval",
13
+ "about": "Self-contained workflow eval for a non-vision local model. The seeded descriptions.csv is authoritative image metadata; the schema belongs in artifacts, while staged and final JSON belong in the workspace.",
14
+ "missionObjectives": "Index all four seeded images into valid JSON with exact filenames, complete required fields, controlled tags, consistent arrays/booleans, and no invented images.",
15
+ "files": [
16
+ {
17
+ "path": "images/descriptions.csv",
18
+ "content": "filename,caption,tags,dominantColors,orientation,containsText,qualityFlags\nmarket-stand.jpg,Outdoor produce stand with crates of greens,produce;outdoor;market,green;wood;white,landscape,false,usable\npacking-sheet.png,Spreadsheet screenshot showing Thursday packing counts,spreadsheet;packing;counts,white;blue;gray,landscape,true,text-heavy\nvolunteer-badge.jpg,Close-up volunteer badge on a red lanyard,volunteer;badge;people,red;white;black,portrait,true,cropped\npickup-line.jpg,Members waiting near pickup tables at dusk,pickup;members;queue,navy;yellow;gray,landscape,false,low-light\n"
19
+ },
20
+ {
21
+ "path": "tests/verify-index.mjs",
22
+ "content": "import { readFileSync } from 'node:fs';\n\nconst expected = ['market-stand.jpg', 'packing-sheet.png', 'pickup-line.jpg', 'volunteer-badge.jpg'];\nconst required = ['filename', 'caption', 'tags', 'dominantColors', 'orientation', 'containsText', 'qualityFlags'];\nconst doc = JSON.parse(readFileSync('index.json', 'utf8'));\nif (!Array.isArray(doc.images)) throw new Error('images must be an array');\nif (doc.images.length !== expected.length) throw new Error(`expected 4 records, got ${doc.images.length}`);\nconst names = doc.images.map((row) => row.filename).sort();\nif (JSON.stringify(names) !== JSON.stringify(expected)) throw new Error(`filename coverage mismatch: ${names.join(', ')}`);\nfor (const row of doc.images) {\n for (const field of required) if (!(field in row)) throw new Error(`${row.filename}: missing ${field}`);\n if (typeof row.caption !== 'string' || row.caption.trim().length < 12) throw new Error(`${row.filename}: caption too short`);\n if (!Array.isArray(row.tags) || row.tags.length < 2) throw new Error(`${row.filename}: tags must be an array`);\n if (!Array.isArray(row.dominantColors) || row.dominantColors.length < 2) throw new Error(`${row.filename}: dominantColors must be an array`);\n if (typeof row.containsText !== 'boolean') throw new Error(`${row.filename}: containsText must be boolean`);\n if (!Array.isArray(row.qualityFlags)) throw new Error(`${row.filename}: qualityFlags must be an array`);\n}\nconsole.log('INDEX_OK 4/4');\n",
23
+ "surface": "harness"
24
+ }
25
+ ],
26
+ "worker": {
27
+ "name": "Iris",
28
+ "role": "Analyst"
29
+ }
30
+ },
31
+ "mocks": [],
32
+ "success": {
33
+ "summary": "A craftbook task records a schema artifact, stages valid per-image JSON, and ships index.json with exact 4/4 fixture coverage.",
34
+ "deliverables": [
35
+ {
36
+ "path": "index.json",
37
+ "kind": "json",
38
+ "minBytes": 900,
39
+ "checks": [
40
+ {
41
+ "kind": "contains",
42
+ "file": "index.json",
43
+ "pattern": "market-stand\\.jpg"
44
+ },
45
+ {
46
+ "kind": "contains",
47
+ "file": "index.json",
48
+ "pattern": "packing-sheet\\.png"
49
+ },
50
+ {
51
+ "kind": "contains",
52
+ "file": "index.json",
53
+ "pattern": "volunteer-badge\\.jpg"
54
+ },
55
+ {
56
+ "kind": "contains",
57
+ "file": "index.json",
58
+ "pattern": "pickup-line\\.jpg"
59
+ },
60
+ {
61
+ "kind": "contains",
62
+ "file": "index.json",
63
+ "pattern": "dominantColors[\\s\\S]*containsText[\\s\\S]*qualityFlags"
64
+ },
65
+ {
66
+ "kind": "notContains",
67
+ "file": "index.json",
68
+ "pattern": "hero\\.png|logo\\.png|unknown",
69
+ "flags": "i"
70
+ }
71
+ ]
72
+ },
73
+ {
74
+ "path": "work/image-descriptions.json",
75
+ "kind": "json",
76
+ "minBytes": 700,
77
+ "checks": [
78
+ {
79
+ "kind": "contains",
80
+ "file": "work/image-descriptions.json",
81
+ "pattern": "filename[\\s\\S]*caption[\\s\\S]*tags",
82
+ "flags": "i"
83
+ }
84
+ ]
85
+ }
86
+ ],
87
+ "checks": [
88
+ {
89
+ "kind": "minBytes",
90
+ "file": "image-index/schema.md",
91
+ "bytes": 500,
92
+ "artifact": true
93
+ },
94
+ {
95
+ "kind": "contains",
96
+ "file": "image-index/schema.md",
97
+ "pattern": "filename[\\s\\S]*caption[\\s\\S]*tags[\\s\\S]*dominantColors",
98
+ "flags": "i",
99
+ "artifact": true
100
+ },
101
+ {
102
+ "kind": "nodeScriptPasses",
103
+ "script": "tests/verify-index.mjs",
104
+ "requiredOutput": [
105
+ {
106
+ "pattern": "INDEX_OK 4/4",
107
+ "label": "exact image coverage"
108
+ }
109
+ ]
110
+ }
111
+ ],
112
+ "taskNotes": {
113
+ "minBytes": 160,
114
+ "requireCraftbookTask": true,
115
+ "checks": [
116
+ {
117
+ "kind": "contains",
118
+ "file": "task-notes.md",
119
+ "pattern": "4/4|four of four|coverage.*4",
120
+ "flags": "i"
121
+ },
122
+ {
123
+ "kind": "contains",
124
+ "file": "task-notes.md",
125
+ "pattern": "schema\\.md",
126
+ "flags": "i"
127
+ },
128
+ {
129
+ "kind": "contains",
130
+ "file": "task-notes.md",
131
+ "pattern": "image-descriptions\\.json",
132
+ "flags": "i"
133
+ },
134
+ {
135
+ "kind": "contains",
136
+ "file": "task-notes.md",
137
+ "pattern": "index\\.json",
138
+ "flags": "i"
139
+ }
140
+ ]
141
+ },
142
+ "taskGraph": {
143
+ "requireCraftbookTask": true,
144
+ "requireTerminalStep": true
145
+ }
146
+ },
147
+ "rubric": {
148
+ "artifact": {
149
+ "path": "index.json",
150
+ "kind": "json"
151
+ },
152
+ "axes": [
153
+ {
154
+ "name": "schema consistency",
155
+ "description": "Every record uses the same types and required fields, with arrays and booleans represented consistently."
156
+ },
157
+ {
158
+ "name": "grounding",
159
+ "description": "Captions, tags, colors, orientation, text flags, and quality flags preserve only the authoritative sidecar facts."
160
+ },
161
+ {
162
+ "name": "coverage",
163
+ "description": "Every source filename appears exactly once, with no missing or invented images."
164
+ },
165
+ {
166
+ "name": "workflow evidence",
167
+ "description": "The schema artifact and staged JSON demonstrate a schema-first, reviewable indexing workflow."
168
+ }
169
+ ]
170
+ },
171
+ "qualityFocus": [
172
+ "craftbook attribution",
173
+ "schema-first indexing",
174
+ "executable exact-coverage check",
175
+ "text-only vision surrogate"
176
+ ]
177
+ }
@@ -0,0 +1,163 @@
1
+ {
2
+ "id": "image-set-index",
3
+ "name": "Index & Describe an Image Set",
4
+ "description": "Given a folder of images, produce a structured index that describes each one (caption, tags, notable content) in a consistent schema, then validates coverage and consistency. For cataloguing, search, or alt-text generation over an image collection.\n\nA gallery craftbook generated from an archetype spec. It runs\n`phase → (per-phase gate) → … → evaluate → (loop) → finish`. Each build\nphase that produces a checkable artifact is followed by a **runtime\ngate-checkpoint** — the runtime verifies the artifact and routes with no\nmodel turn, looping back to redo the phase on a miss. The final `evaluate`\nstep holds a static deliverable gate plus a reviewer QA pass. What it adds\nover the generic `build-loop`: a specialist role per phase, a\ndomain-correct ordering, and a concrete per-phase quality bar.\n\nDeliverables marked \"artifact\" land in the project's artifacts drawer (`write_artifact` / `read_artifact`), not the shipped workspace — review output is not product source.\n\nPhases:\n\n1. Scope the index (planner) — fields per image + output schema + criteria → gated on artifact `image-index/schema.md` (markdown-notes)\n2. Describe each image (developer) — read each image, write structured descriptions → gated on `work/image-descriptions.json` (json)\n3. Assemble the index (developer) — write the index file in the chosen format → gated on `index.json` (json)\n\nThe gates never advance with an unmet criterion, and loop back to the\nowning phase to fix named gaps.\n",
5
+ "entryStepId": "scope",
6
+ "triggers": [
7
+ "index images",
8
+ "describe images",
9
+ "caption a folder",
10
+ "image catalog"
11
+ ],
12
+ "steps": [
13
+ {
14
+ "id": "scope",
15
+ "name": "Scope the index",
16
+ "description": "fields per image + output schema + criteria",
17
+ "prompt": "Decide the index schema before describing anything. The final output is workspace `index.json` with an `images` array; define fields per image (filename, caption, tags, dominantColors, orientation, containsText, and qualityFlags), controlled vocabulary rules, and an **acceptance-criteria checklist** (\"every source image has exactly one record\", \"captions are 1-2 sentences\", \"tags use a consistent vocabulary\", \"the JSON parses\"). Save the schema + checklist to artifact `image-index/schema.md` with `write_artifact`; note the path in task notes.",
18
+ "suggestedRole": "planner",
19
+ "advanceWhen": {
20
+ "file": "image-index/schema.md",
21
+ "minBytes": 1,
22
+ "sniff": "nonempty",
23
+ "artifact": true
24
+ },
25
+ "gate": {
26
+ "at": "completion",
27
+ "checks": [
28
+ {
29
+ "kind": "minBytes",
30
+ "file": "image-index/schema.md",
31
+ "bytes": 500,
32
+ "artifact": true
33
+ },
34
+ {
35
+ "kind": "sniff",
36
+ "file": "image-index/schema.md",
37
+ "sniff": "nonempty",
38
+ "artifact": true
39
+ },
40
+ {
41
+ "kind": "contains",
42
+ "file": "image-index/schema.md",
43
+ "pattern": "filename[\\s\\S]*caption[\\s\\S]*tags",
44
+ "flags": "i",
45
+ "label": "core schema fields",
46
+ "artifact": true
47
+ },
48
+ {
49
+ "kind": "contains",
50
+ "file": "image-index/schema.md",
51
+ "pattern": "every|coverage|exactly one",
52
+ "flags": "i",
53
+ "label": "coverage criterion",
54
+ "artifact": true
55
+ }
56
+ ],
57
+ "onReject": "scope",
58
+ "maxAttempts": 3
59
+ },
60
+ "next": "describe"
61
+ },
62
+ {
63
+ "id": "describe",
64
+ "name": "Describe each image",
65
+ "description": "read each image, write structured descriptions",
66
+ "prompt": "Read artifact `image-index/schema.md` with `read_artifact`, then list the source image folder with workspace tools. For each image, use the available image-reading or description capability to populate the schema. If the user supplied an authoritative metadata sidecar because image binaries or vision are unavailable, read it with `read_file`, preserve only its facts, and record that limitation. Keep vocabulary consistent and do not skip or invent images. Stage the complete per-image array as valid workspace JSON at `work/image-descriptions.json` with `write_file`.",
67
+ "suggestedRole": "developer",
68
+ "advanceWhen": {
69
+ "file": "work/image-descriptions.json",
70
+ "minBytes": 1,
71
+ "sniff": "json-valid"
72
+ },
73
+ "gate": {
74
+ "at": "completion",
75
+ "checks": [
76
+ {
77
+ "kind": "minBytes",
78
+ "file": "work/image-descriptions.json",
79
+ "bytes": 300
80
+ },
81
+ {
82
+ "kind": "contains",
83
+ "file": "work/image-descriptions.json",
84
+ "pattern": "\"filename\"[\\s\\S]*\"caption\"[\\s\\S]*\"tags\"",
85
+ "flags": "i",
86
+ "label": "per-image fields"
87
+ }
88
+ ],
89
+ "scripts": [
90
+ {
91
+ "name": "checkJsonValid",
92
+ "scope": "standard",
93
+ "inputs": {
94
+ "file": "work/image-descriptions.json"
95
+ }
96
+ }
97
+ ],
98
+ "onReject": "describe",
99
+ "maxAttempts": 3
100
+ },
101
+ "next": "assemble"
102
+ },
103
+ {
104
+ "id": "assemble",
105
+ "name": "Assemble the index",
106
+ "description": "write the index file in the chosen format",
107
+ "prompt": "Read workspace `work/image-descriptions.json` with `read_file`, reconcile it against the complete source-folder or sidecar listing, and write the final JSON object to workspace `index.json` with `write_file`. Ensure the `images` array has exactly one record per source filename, every required field is present, and vocabulary is consistent. On a loop-back, fix only the named gaps (missing/extra records, malformed JSON, inconsistent tags). `write_task_note` the index path and an explicit coverage count (records vs source images).",
108
+ "suggestedRole": "developer",
109
+ "advanceWhen": {
110
+ "file": "index.json",
111
+ "minBytes": 1,
112
+ "sniff": "json-valid"
113
+ },
114
+ "gate": {
115
+ "at": "completion",
116
+ "checks": [
117
+ {
118
+ "kind": "minBytes",
119
+ "file": "index.json",
120
+ "bytes": 500
121
+ },
122
+ {
123
+ "kind": "contains",
124
+ "file": "index.json",
125
+ "pattern": "\"images\"\\s*:",
126
+ "flags": "i",
127
+ "label": "images array"
128
+ }
129
+ ],
130
+ "scripts": [
131
+ {
132
+ "name": "checkJsonValid",
133
+ "scope": "standard",
134
+ "inputs": {
135
+ "file": "index.json"
136
+ }
137
+ }
138
+ ],
139
+ "onReject": "assemble",
140
+ "maxAttempts": 4
141
+ },
142
+ "next": "evaluate"
143
+ },
144
+ {
145
+ "id": "evaluate",
146
+ "name": "Evaluate",
147
+ "description": "Grade the deliverable against every acceptance criterion. All pass → finish; any fail → loop back and fix the gap.",
148
+ "prompt": "Read workspace `index.json`, `work/image-descriptions.json`, and the source-folder listing with workspace tools, plus artifact `image-index/schema.md` with `read_artifact`. Check coverage and consistency: does every source image have exactly one record, do all required fields exist, do captions/tags follow the schema and a consistent vocabulary, and does the file parse? Spot-check descriptions against actual images when available. Write PASS/FAIL per criterion.\n\nThen route — this is the whole point of the loop:\n\n- **Every criterion PASSES →** call `advance_task_step({ ref, stepId: \"evaluate\", next: \"finish\" })`.\n- **Any criterion FAILS →** write the specific gaps to notes, then call `advance_task_step({ ref, stepId: \"evaluate\", next: \"assemble\" })` to loop back. The builder fixes exactly those gaps.\n\nNever route to `finish` while any criterion is unmet. The build phase's completion gate already blocked a grossly-incomplete deliverable; your job is the judgment an automated check cannot make (does it actually work, read well, look right). After ~3 unproductive loops, stop and report DONE_WITH_CONCERNS so the user can step in.",
149
+ "suggestedRole": "reviewer",
150
+ "next": "assemble"
151
+ },
152
+ {
153
+ "id": "finish",
154
+ "name": "Finish",
155
+ "description": "All acceptance criteria met. Stamp a short summary and report DONE.",
156
+ "prompt": "Every criterion passed. Write a DONE summary: index path, format, image count, and a one-line note that coverage is complete and the schema is consistent.",
157
+ "suggestedRole": "developer",
158
+ "terminal": true
159
+ }
160
+ ],
161
+ "version": "1.2.0",
162
+ "releasedAt": "2026-08-10T00:00:00Z"
163
+ }
@@ -0,0 +1,180 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "title": "Deterministic image-index workflow",
4
+ "objective": "Run the Index & Describe an Image Set craftbook against deterministic metadata, verifying schema-first staging, exact coverage, valid JSON, and no invented images.",
5
+ "tags": [
6
+ "media",
7
+ "json",
8
+ "workflow"
9
+ ],
10
+ "prompt": "Use the Index & Describe an Image Set craftbook. This text-only local-model eval supplies authoritative vision metadata in workspace `images/descriptions.csv`; read it as the sidecar for the four named images. Define the schema first, stage valid JSON in workspace `work/image-descriptions.json`, and write final workspace `index.json` as an object with an `images` array containing exactly one record per source filename. Each record must include filename, caption, tags, dominantColors, orientation, containsText, and qualityFlags. Use only the sidecar facts and report coverage as 4/4.",
11
+ "setup": {
12
+ "projectName": "Image Set Index Eval",
13
+ "about": "Self-contained workflow eval for a non-vision local model. The seeded descriptions.csv is authoritative image metadata; the schema belongs in artifacts, while staged and final JSON belong in the workspace.",
14
+ "missionObjectives": "Index all four seeded images into valid JSON with exact filenames, complete required fields, controlled tags, consistent arrays/booleans, and no invented images.",
15
+ "files": [
16
+ {
17
+ "path": "images/descriptions.csv",
18
+ "content": "filename,caption,tags,dominantColors,orientation,containsText,qualityFlags\nmarket-stand.jpg,Outdoor produce stand with crates of greens,produce;outdoor;market,green;wood;white,landscape,false,usable\npacking-sheet.png,Spreadsheet screenshot showing Thursday packing counts,spreadsheet;packing;counts,white;blue;gray,landscape,true,text-heavy\nvolunteer-badge.jpg,Close-up volunteer badge on a red lanyard,volunteer;badge;people,red;white;black,portrait,true,cropped\npickup-line.jpg,Members waiting near pickup tables at dusk,pickup;members;queue,navy;yellow;gray,landscape,false,low-light\n"
19
+ },
20
+ {
21
+ "path": "tests/verify-index.mjs",
22
+ "content": "import { readFileSync } from 'node:fs';\n\nconst expected = ['market-stand.jpg', 'packing-sheet.png', 'pickup-line.jpg', 'volunteer-badge.jpg'];\nconst required = ['filename', 'caption', 'tags', 'dominantColors', 'orientation', 'containsText', 'qualityFlags'];\nconst doc = JSON.parse(readFileSync('index.json', 'utf8'));\nif (!Array.isArray(doc.images)) throw new Error('images must be an array');\nif (doc.images.length !== expected.length) throw new Error(`expected 4 records, got ${doc.images.length}`);\nconst names = doc.images.map((row) => row.filename).sort();\nif (JSON.stringify(names) !== JSON.stringify(expected)) throw new Error(`filename coverage mismatch: ${names.join(', ')}`);\nfor (const row of doc.images) {\n for (const field of required) if (!(field in row)) throw new Error(`${row.filename}: missing ${field}`);\n if (typeof row.caption !== 'string' || row.caption.trim().length < 12) throw new Error(`${row.filename}: caption too short`);\n if (!Array.isArray(row.tags) || row.tags.length < 2) throw new Error(`${row.filename}: tags must be an array`);\n if (!Array.isArray(row.dominantColors) || row.dominantColors.length < 2) throw new Error(`${row.filename}: dominantColors must be an array`);\n if (typeof row.containsText !== 'boolean') throw new Error(`${row.filename}: containsText must be boolean`);\n if (!Array.isArray(row.qualityFlags)) throw new Error(`${row.filename}: qualityFlags must be an array`);\n}\nconsole.log('INDEX_OK 4/4');\n",
23
+ "surface": "harness"
24
+ }
25
+ ],
26
+ "worker": {
27
+ "name": "Iris",
28
+ "role": "Analyst"
29
+ }
30
+ },
31
+ "mocks": [],
32
+ "success": {
33
+ "summary": "A craftbook task records a schema artifact, stages valid per-image JSON, and ships index.json with exact 4/4 fixture coverage.",
34
+ "deliverables": [
35
+ {
36
+ "path": "index.json",
37
+ "kind": "json",
38
+ "minBytes": 900,
39
+ "checks": [
40
+ {
41
+ "kind": "contains",
42
+ "file": "index.json",
43
+ "pattern": "market-stand\\.jpg"
44
+ },
45
+ {
46
+ "kind": "contains",
47
+ "file": "index.json",
48
+ "pattern": "packing-sheet\\.png"
49
+ },
50
+ {
51
+ "kind": "contains",
52
+ "file": "index.json",
53
+ "pattern": "volunteer-badge\\.jpg"
54
+ },
55
+ {
56
+ "kind": "contains",
57
+ "file": "index.json",
58
+ "pattern": "pickup-line\\.jpg"
59
+ },
60
+ {
61
+ "kind": "contains",
62
+ "file": "index.json",
63
+ "pattern": "dominantColors[\\s\\S]*containsText[\\s\\S]*qualityFlags"
64
+ },
65
+ {
66
+ "kind": "notContains",
67
+ "file": "index.json",
68
+ "pattern": "hero\\.png|logo\\.png|unknown",
69
+ "flags": "i"
70
+ }
71
+ ]
72
+ },
73
+ {
74
+ "path": "work/image-descriptions.json",
75
+ "kind": "json",
76
+ "minBytes": 700,
77
+ "checks": [
78
+ {
79
+ "kind": "contains",
80
+ "file": "work/image-descriptions.json",
81
+ "pattern": "filename[\\s\\S]*caption[\\s\\S]*tags",
82
+ "flags": "i"
83
+ }
84
+ ]
85
+ }
86
+ ],
87
+ "checks": [
88
+ {
89
+ "kind": "minBytes",
90
+ "file": "image-index/schema.md",
91
+ "bytes": 500,
92
+ "artifact": true
93
+ },
94
+ {
95
+ "kind": "contains",
96
+ "file": "image-index/schema.md",
97
+ "pattern": "filename[\\s\\S]*caption[\\s\\S]*tags[\\s\\S]*dominantColors",
98
+ "flags": "i",
99
+ "artifact": true
100
+ },
101
+ {
102
+ "kind": "nodeScriptPasses",
103
+ "script": "tests/verify-index.mjs",
104
+ "requiredOutput": [
105
+ {
106
+ "pattern": "INDEX_OK 4/4",
107
+ "label": "exact image coverage"
108
+ }
109
+ ]
110
+ }
111
+ ],
112
+ "taskNotes": {
113
+ "minBytes": 160,
114
+ "checks": [
115
+ {
116
+ "kind": "contains",
117
+ "file": "task-notes.md",
118
+ "pattern": "4/4|four of four|coverage.*4",
119
+ "flags": "i"
120
+ },
121
+ {
122
+ "kind": "contains",
123
+ "file": "task-notes.md",
124
+ "pattern": "schema\\.md",
125
+ "flags": "i"
126
+ },
127
+ {
128
+ "kind": "contains",
129
+ "file": "task-notes.md",
130
+ "pattern": "image-descriptions\\.json",
131
+ "flags": "i"
132
+ },
133
+ {
134
+ "kind": "contains",
135
+ "file": "task-notes.md",
136
+ "pattern": "index\\.json",
137
+ "flags": "i"
138
+ }
139
+ ],
140
+ "requireCraftbookTask": true
141
+ },
142
+ "taskGraph": {
143
+ "requireCraftbookTask": true,
144
+ "requireTerminalStep": true
145
+ },
146
+ "unchangedFixtures": [
147
+ "images/descriptions.csv"
148
+ ]
149
+ },
150
+ "rubric": {
151
+ "artifact": {
152
+ "path": "index.json",
153
+ "kind": "json"
154
+ },
155
+ "axes": [
156
+ {
157
+ "name": "schema consistency",
158
+ "description": "Every record uses the same types and required fields, with arrays and booleans represented consistently."
159
+ },
160
+ {
161
+ "name": "grounding",
162
+ "description": "Captions, tags, colors, orientation, text flags, and quality flags preserve only the authoritative sidecar facts."
163
+ },
164
+ {
165
+ "name": "coverage",
166
+ "description": "Every source filename appears exactly once, with no missing or invented images."
167
+ },
168
+ {
169
+ "name": "workflow evidence",
170
+ "description": "The schema artifact and staged JSON demonstrate a schema-first, reviewable indexing workflow."
171
+ }
172
+ ]
173
+ },
174
+ "qualityFocus": [
175
+ "craftbook attribution",
176
+ "schema-first indexing",
177
+ "executable exact-coverage check",
178
+ "text-only vision surrogate"
179
+ ]
180
+ }