@mccaskie-labs/workbench-config 0.2.2 → 0.2.3
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/CHANGELOG.md +6 -0
- package/capabilities/pdf.json +87 -3
- package/dist/capabilities.gen.d.ts +69 -3
- package/dist/capabilities.gen.js +88 -4
- package/dist/capability-schema.d.ts +1 -1
- package/dist/capability-schema.js +1 -1
- package/dist/skills.js +5 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @mccaskie-labs/workbench-config
|
|
2
2
|
|
|
3
|
+
## 0.2.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Saved layouts for PDFs (capabilities manifest §9.7). workbench-pdf gains `checkLayout` and `fillLayout`, and the `workbench-pdf` command: `drafts` asks the Gateway for two to four layouts with the project's development key and writes HTML previews, `pick` saves one as `workbench/pdf/<name>.json`, and `generate [--check]` writes `src/pdf-layouts.generated.ts` with a typed `PDF_LAYOUTS.<name>.document(data)`. `@mccaskie-labs/workbench-ai` is an optional peer, needed only for `drafts`. The pdf manifest gets its client questions (the `drafts` pattern: what the document is, the paper size, then drafts to pick from), so pdf leaves `OFFER_PENDING`. A must-ask question with answers to pick from now marks none of them "(Recommended)".
|
|
8
|
+
|
|
3
9
|
## 0.2.2
|
|
4
10
|
|
|
5
11
|
### Patch Changes
|
package/capabilities/pdf.json
CHANGED
|
@@ -7,13 +7,14 @@
|
|
|
7
7
|
"status": "built",
|
|
8
8
|
"delivery": {
|
|
9
9
|
"choice": "optional",
|
|
10
|
-
"intro": "PDFs such as invoices and receipts, printed with the project's logo and colours."
|
|
11
|
-
"when": "The client wants a PDF: an invoice, receipt, quote, certificate, report or anything else to download or print."
|
|
10
|
+
"intro": "PDFs such as invoices and receipts, printed with the project's logo and colours."
|
|
12
11
|
},
|
|
13
12
|
"surfaces": {
|
|
14
13
|
"package": [
|
|
15
14
|
"createPdfMaker",
|
|
16
|
-
"WorkbenchPdfError"
|
|
15
|
+
"WorkbenchPdfError",
|
|
16
|
+
"checkLayout",
|
|
17
|
+
"fillLayout"
|
|
17
18
|
]
|
|
18
19
|
},
|
|
19
20
|
"limits": [
|
|
@@ -95,6 +96,89 @@
|
|
|
95
96
|
"note": "Prints the app's own HTML holding an image from a host not in allowOrigins; the PDF is made and the browser reports that image's request as blocked"
|
|
96
97
|
}
|
|
97
98
|
],
|
|
99
|
+
"offer": {
|
|
100
|
+
"pattern": "drafts",
|
|
101
|
+
"when": "The client wants a PDF: an invoice, receipt, quote, certificate, report or anything else to download or print.",
|
|
102
|
+
"say": "I'll make this with Workbench PDFs, printed with your logo and colours. I'll show you a few layouts to pick from. The one you pick is saved, so every one looks the same from then on.",
|
|
103
|
+
"answers_file": "workbench/pdf/<name>.json",
|
|
104
|
+
"per": "document",
|
|
105
|
+
"generator": "npx workbench-pdf generate",
|
|
106
|
+
"answers_format": "the saved layout. `npx workbench-pdf pick <name> <round>-<draft>` writes it from the draft the client picked, with the draft's request id, model and cost; never write one from nothing. It holds the document's `fields` (each value is text the app formats first, money and dates through the country pack), its `blocks` with `{field}` placeholders, and made-up `sample` values. To change a saved layout in the client's words (move a block, rename a heading, add a field), edit the file and run the generator, which refuses a layout that doesn't check. In the app, print with `pdfMakerFor(env).document(PDF_LAYOUTS.<name>.document(data), { size: PDF_LAYOUTS.<name>.size })`. Drafts and their previews stay in `workbench/pdf/drafts/`, which isn't committed.",
|
|
107
|
+
"questions": [
|
|
108
|
+
{
|
|
109
|
+
"id": "pdf.what",
|
|
110
|
+
"sets": [
|
|
111
|
+
"layout.name",
|
|
112
|
+
"layout.about"
|
|
113
|
+
],
|
|
114
|
+
"ask": "What is this document, and what is it for?",
|
|
115
|
+
"style": "cards",
|
|
116
|
+
"answers": [
|
|
117
|
+
{
|
|
118
|
+
"label": "An invoice",
|
|
119
|
+
"value": "invoice",
|
|
120
|
+
"means": "What a customer owes, with the items and the total."
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"label": "A receipt",
|
|
124
|
+
"value": "receipt",
|
|
125
|
+
"means": "Proof a customer paid."
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"label": "A quote",
|
|
129
|
+
"value": "quote",
|
|
130
|
+
"means": "What a job would cost, before the customer agrees."
|
|
131
|
+
}
|
|
132
|
+
],
|
|
133
|
+
"other": {
|
|
134
|
+
"kind": "text",
|
|
135
|
+
"min": 3,
|
|
136
|
+
"max": 200,
|
|
137
|
+
"description": "What the document is, in a few words: a certificate, a run sheet, a booking confirmation."
|
|
138
|
+
},
|
|
139
|
+
"note": "The answer's value is the layout's name (lower case and underscores: run_sheet). The client's own words, with anything they add about who reads it, go in --about.",
|
|
140
|
+
"must_ask": true
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
"id": "pdf.size",
|
|
144
|
+
"sets": "layout.size",
|
|
145
|
+
"ask": "Which paper size?",
|
|
146
|
+
"style": "cards",
|
|
147
|
+
"answers": [
|
|
148
|
+
{
|
|
149
|
+
"label": "A4",
|
|
150
|
+
"value": "A4",
|
|
151
|
+
"means": "Used almost everywhere outside North America."
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
"label": "US Letter",
|
|
155
|
+
"value": "Letter",
|
|
156
|
+
"means": "Used in the United States and Canada."
|
|
157
|
+
}
|
|
158
|
+
],
|
|
159
|
+
"note": "Recommend US Letter only when the readers are in the United States or Canada. Pass it to the drafts command as --size."
|
|
160
|
+
}
|
|
161
|
+
],
|
|
162
|
+
"not_asked": [
|
|
163
|
+
{
|
|
164
|
+
"sets": "layout.colours",
|
|
165
|
+
"why": "The logo, colours and fonts come from the brand (brand.json and the admins' brand page), so every document matches the rest of the app. To restyle a part of the layout, use project.css (see Restyling)."
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
"sets": "layout.contents",
|
|
169
|
+
"why": "The drafts propose what each layout shows. The client changes a picked layout in plain words, and you edit the saved file."
|
|
170
|
+
}
|
|
171
|
+
],
|
|
172
|
+
"drafts": {
|
|
173
|
+
"of": "layouts for this document",
|
|
174
|
+
"surface": "ai",
|
|
175
|
+
"alias": "claude-default",
|
|
176
|
+
"count": 3,
|
|
177
|
+
"max_rounds": 3,
|
|
178
|
+
"job": "pdf.drafts",
|
|
179
|
+
"command": "npx workbench-pdf drafts <name> --about \"<what it is for, in the client's words>\" --size <A4 or Letter>"
|
|
180
|
+
}
|
|
181
|
+
},
|
|
98
182
|
"styles": {
|
|
99
183
|
"prefix": "wb-pdf-"
|
|
100
184
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const MANIFEST_VERSION: "
|
|
1
|
+
export declare const MANIFEST_VERSION: "0a5f38e30870";
|
|
2
2
|
export declare const capabilities: {
|
|
3
3
|
readonly ai: {
|
|
4
4
|
readonly $schema: "./schema.json";
|
|
@@ -1814,7 +1814,7 @@ export declare const capabilities: {
|
|
|
1814
1814
|
readonly summary: "workbench-pdf prints an app's content as a PDF with its brand.json logo, colours and fonts, in the app's own Worker through its Browser Rendering binding (BROWSER). Nothing goes through the Gateway and the app holds no Cloudflare token. The standard layout takes plain-text blocks; html() takes the app's own markup.";
|
|
1815
1815
|
readonly status: "built";
|
|
1816
1816
|
readonly surfaces: {
|
|
1817
|
-
readonly package: readonly ["createPdfMaker", "WorkbenchPdfError"];
|
|
1817
|
+
readonly package: readonly ["createPdfMaker", "WorkbenchPdfError", "checkLayout", "fillLayout"];
|
|
1818
1818
|
};
|
|
1819
1819
|
readonly limits: readonly [{
|
|
1820
1820
|
readonly id: "pdf.blocks";
|
|
@@ -1881,13 +1881,79 @@ export declare const capabilities: {
|
|
|
1881
1881
|
readonly cost_hint_usd: 0;
|
|
1882
1882
|
readonly note: "Prints the app's own HTML holding an image from a host not in allowOrigins; the PDF is made and the browser reports that image's request as blocked";
|
|
1883
1883
|
}];
|
|
1884
|
+
readonly offer: {
|
|
1885
|
+
readonly pattern: "drafts";
|
|
1886
|
+
readonly when: "The client wants a PDF: an invoice, receipt, quote, certificate, report or anything else to download or print.";
|
|
1887
|
+
readonly say: "I'll make this with Workbench PDFs, printed with your logo and colours. I'll show you a few layouts to pick from. The one you pick is saved, so every one looks the same from then on.";
|
|
1888
|
+
readonly answers_file: "workbench/pdf/<name>.json";
|
|
1889
|
+
readonly per: "document";
|
|
1890
|
+
readonly generator: "npx workbench-pdf generate";
|
|
1891
|
+
readonly answers_format: "the saved layout. `npx workbench-pdf pick <name> <round>-<draft>` writes it from the draft the client picked, with the draft's request id, model and cost; never write one from nothing. It holds the document's `fields` (each value is text the app formats first, money and dates through the country pack), its `blocks` with `{field}` placeholders, and made-up `sample` values. To change a saved layout in the client's words (move a block, rename a heading, add a field), edit the file and run the generator, which refuses a layout that doesn't check. In the app, print with `pdfMakerFor(env).document(PDF_LAYOUTS.<name>.document(data), { size: PDF_LAYOUTS.<name>.size })`. Drafts and their previews stay in `workbench/pdf/drafts/`, which isn't committed.";
|
|
1892
|
+
readonly questions: readonly [{
|
|
1893
|
+
readonly id: "pdf.what";
|
|
1894
|
+
readonly sets: readonly ["layout.name", "layout.about"];
|
|
1895
|
+
readonly ask: "What is this document, and what is it for?";
|
|
1896
|
+
readonly style: "cards";
|
|
1897
|
+
readonly answers: readonly [{
|
|
1898
|
+
readonly label: "An invoice";
|
|
1899
|
+
readonly value: "invoice";
|
|
1900
|
+
readonly means: "What a customer owes, with the items and the total.";
|
|
1901
|
+
}, {
|
|
1902
|
+
readonly label: "A receipt";
|
|
1903
|
+
readonly value: "receipt";
|
|
1904
|
+
readonly means: "Proof a customer paid.";
|
|
1905
|
+
}, {
|
|
1906
|
+
readonly label: "A quote";
|
|
1907
|
+
readonly value: "quote";
|
|
1908
|
+
readonly means: "What a job would cost, before the customer agrees.";
|
|
1909
|
+
}];
|
|
1910
|
+
readonly other: {
|
|
1911
|
+
readonly kind: "text";
|
|
1912
|
+
readonly min: 3;
|
|
1913
|
+
readonly max: 200;
|
|
1914
|
+
readonly description: "What the document is, in a few words: a certificate, a run sheet, a booking confirmation.";
|
|
1915
|
+
};
|
|
1916
|
+
readonly must_ask: true;
|
|
1917
|
+
readonly note: "The answer's value is the layout's name (lower case and underscores: run_sheet). The client's own words, with anything they add about who reads it, go in --about.";
|
|
1918
|
+
}, {
|
|
1919
|
+
readonly id: "pdf.size";
|
|
1920
|
+
readonly sets: "layout.size";
|
|
1921
|
+
readonly ask: "Which paper size?";
|
|
1922
|
+
readonly style: "cards";
|
|
1923
|
+
readonly answers: readonly [{
|
|
1924
|
+
readonly label: "A4";
|
|
1925
|
+
readonly value: "A4";
|
|
1926
|
+
readonly means: "Used almost everywhere outside North America.";
|
|
1927
|
+
}, {
|
|
1928
|
+
readonly label: "US Letter";
|
|
1929
|
+
readonly value: "Letter";
|
|
1930
|
+
readonly means: "Used in the United States and Canada.";
|
|
1931
|
+
}];
|
|
1932
|
+
readonly note: "Recommend US Letter only when the readers are in the United States or Canada. Pass it to the drafts command as --size.";
|
|
1933
|
+
}];
|
|
1934
|
+
readonly not_asked: readonly [{
|
|
1935
|
+
readonly sets: "layout.colours";
|
|
1936
|
+
readonly why: "The logo, colours and fonts come from the brand (brand.json and the admins' brand page), so every document matches the rest of the app. To restyle a part of the layout, use project.css (see Restyling).";
|
|
1937
|
+
}, {
|
|
1938
|
+
readonly sets: "layout.contents";
|
|
1939
|
+
readonly why: "The drafts propose what each layout shows. The client changes a picked layout in plain words, and you edit the saved file.";
|
|
1940
|
+
}];
|
|
1941
|
+
readonly drafts: {
|
|
1942
|
+
readonly of: "layouts for this document";
|
|
1943
|
+
readonly surface: "ai";
|
|
1944
|
+
readonly alias: "claude-default";
|
|
1945
|
+
readonly count: 3;
|
|
1946
|
+
readonly max_rounds: 3;
|
|
1947
|
+
readonly job: "pdf.drafts";
|
|
1948
|
+
readonly command: "npx workbench-pdf drafts <name> --about \"<what it is for, in the client's words>\" --size <A4 or Letter>";
|
|
1949
|
+
};
|
|
1950
|
+
};
|
|
1884
1951
|
readonly styles: {
|
|
1885
1952
|
readonly prefix: "wb-pdf-";
|
|
1886
1953
|
};
|
|
1887
1954
|
readonly delivery: {
|
|
1888
1955
|
readonly choice: "optional";
|
|
1889
1956
|
readonly intro: "PDFs such as invoices and receipts, printed with the project's logo and colours.";
|
|
1890
|
-
readonly when: "The client wants a PDF: an invoice, receipt, quote, certificate, report or anything else to download or print.";
|
|
1891
1957
|
};
|
|
1892
1958
|
};
|
|
1893
1959
|
readonly "sign-in": {
|
package/dist/capabilities.gen.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Generated by `npm run capabilities:build` from capabilities/*.json. Do not edit.
|
|
2
2
|
// check:capabilities fails in Checks when this file is stale.
|
|
3
|
-
export const MANIFEST_VERSION = "
|
|
3
|
+
export const MANIFEST_VERSION = "0a5f38e30870";
|
|
4
4
|
export const capabilities = {
|
|
5
5
|
"ai": {
|
|
6
6
|
"$schema": "./schema.json",
|
|
@@ -2447,7 +2447,9 @@ export const capabilities = {
|
|
|
2447
2447
|
"surfaces": {
|
|
2448
2448
|
"package": [
|
|
2449
2449
|
"createPdfMaker",
|
|
2450
|
-
"WorkbenchPdfError"
|
|
2450
|
+
"WorkbenchPdfError",
|
|
2451
|
+
"checkLayout",
|
|
2452
|
+
"fillLayout"
|
|
2451
2453
|
]
|
|
2452
2454
|
},
|
|
2453
2455
|
"limits": [
|
|
@@ -2529,13 +2531,95 @@ export const capabilities = {
|
|
|
2529
2531
|
"note": "Prints the app's own HTML holding an image from a host not in allowOrigins; the PDF is made and the browser reports that image's request as blocked"
|
|
2530
2532
|
}
|
|
2531
2533
|
],
|
|
2534
|
+
"offer": {
|
|
2535
|
+
"pattern": "drafts",
|
|
2536
|
+
"when": "The client wants a PDF: an invoice, receipt, quote, certificate, report or anything else to download or print.",
|
|
2537
|
+
"say": "I'll make this with Workbench PDFs, printed with your logo and colours. I'll show you a few layouts to pick from. The one you pick is saved, so every one looks the same from then on.",
|
|
2538
|
+
"answers_file": "workbench/pdf/<name>.json",
|
|
2539
|
+
"per": "document",
|
|
2540
|
+
"generator": "npx workbench-pdf generate",
|
|
2541
|
+
"answers_format": "the saved layout. `npx workbench-pdf pick <name> <round>-<draft>` writes it from the draft the client picked, with the draft's request id, model and cost; never write one from nothing. It holds the document's `fields` (each value is text the app formats first, money and dates through the country pack), its `blocks` with `{field}` placeholders, and made-up `sample` values. To change a saved layout in the client's words (move a block, rename a heading, add a field), edit the file and run the generator, which refuses a layout that doesn't check. In the app, print with `pdfMakerFor(env).document(PDF_LAYOUTS.<name>.document(data), { size: PDF_LAYOUTS.<name>.size })`. Drafts and their previews stay in `workbench/pdf/drafts/`, which isn't committed.",
|
|
2542
|
+
"questions": [
|
|
2543
|
+
{
|
|
2544
|
+
"id": "pdf.what",
|
|
2545
|
+
"sets": [
|
|
2546
|
+
"layout.name",
|
|
2547
|
+
"layout.about"
|
|
2548
|
+
],
|
|
2549
|
+
"ask": "What is this document, and what is it for?",
|
|
2550
|
+
"style": "cards",
|
|
2551
|
+
"answers": [
|
|
2552
|
+
{
|
|
2553
|
+
"label": "An invoice",
|
|
2554
|
+
"value": "invoice",
|
|
2555
|
+
"means": "What a customer owes, with the items and the total."
|
|
2556
|
+
},
|
|
2557
|
+
{
|
|
2558
|
+
"label": "A receipt",
|
|
2559
|
+
"value": "receipt",
|
|
2560
|
+
"means": "Proof a customer paid."
|
|
2561
|
+
},
|
|
2562
|
+
{
|
|
2563
|
+
"label": "A quote",
|
|
2564
|
+
"value": "quote",
|
|
2565
|
+
"means": "What a job would cost, before the customer agrees."
|
|
2566
|
+
}
|
|
2567
|
+
],
|
|
2568
|
+
"other": {
|
|
2569
|
+
"kind": "text",
|
|
2570
|
+
"min": 3,
|
|
2571
|
+
"max": 200,
|
|
2572
|
+
"description": "What the document is, in a few words: a certificate, a run sheet, a booking confirmation."
|
|
2573
|
+
},
|
|
2574
|
+
"must_ask": true,
|
|
2575
|
+
"note": "The answer's value is the layout's name (lower case and underscores: run_sheet). The client's own words, with anything they add about who reads it, go in --about."
|
|
2576
|
+
},
|
|
2577
|
+
{
|
|
2578
|
+
"id": "pdf.size",
|
|
2579
|
+
"sets": "layout.size",
|
|
2580
|
+
"ask": "Which paper size?",
|
|
2581
|
+
"style": "cards",
|
|
2582
|
+
"answers": [
|
|
2583
|
+
{
|
|
2584
|
+
"label": "A4",
|
|
2585
|
+
"value": "A4",
|
|
2586
|
+
"means": "Used almost everywhere outside North America."
|
|
2587
|
+
},
|
|
2588
|
+
{
|
|
2589
|
+
"label": "US Letter",
|
|
2590
|
+
"value": "Letter",
|
|
2591
|
+
"means": "Used in the United States and Canada."
|
|
2592
|
+
}
|
|
2593
|
+
],
|
|
2594
|
+
"note": "Recommend US Letter only when the readers are in the United States or Canada. Pass it to the drafts command as --size."
|
|
2595
|
+
}
|
|
2596
|
+
],
|
|
2597
|
+
"not_asked": [
|
|
2598
|
+
{
|
|
2599
|
+
"sets": "layout.colours",
|
|
2600
|
+
"why": "The logo, colours and fonts come from the brand (brand.json and the admins' brand page), so every document matches the rest of the app. To restyle a part of the layout, use project.css (see Restyling)."
|
|
2601
|
+
},
|
|
2602
|
+
{
|
|
2603
|
+
"sets": "layout.contents",
|
|
2604
|
+
"why": "The drafts propose what each layout shows. The client changes a picked layout in plain words, and you edit the saved file."
|
|
2605
|
+
}
|
|
2606
|
+
],
|
|
2607
|
+
"drafts": {
|
|
2608
|
+
"of": "layouts for this document",
|
|
2609
|
+
"surface": "ai",
|
|
2610
|
+
"alias": "claude-default",
|
|
2611
|
+
"count": 3,
|
|
2612
|
+
"max_rounds": 3,
|
|
2613
|
+
"job": "pdf.drafts",
|
|
2614
|
+
"command": "npx workbench-pdf drafts <name> --about \"<what it is for, in the client's words>\" --size <A4 or Letter>"
|
|
2615
|
+
}
|
|
2616
|
+
},
|
|
2532
2617
|
"styles": {
|
|
2533
2618
|
"prefix": "wb-pdf-"
|
|
2534
2619
|
},
|
|
2535
2620
|
"delivery": {
|
|
2536
2621
|
"choice": "optional",
|
|
2537
|
-
"intro": "PDFs such as invoices and receipts, printed with the project's logo and colours."
|
|
2538
|
-
"when": "The client wants a PDF: an invoice, receipt, quote, certificate, report or anything else to download or print."
|
|
2622
|
+
"intro": "PDFs such as invoices and receipts, printed with the project's logo and colours."
|
|
2539
2623
|
}
|
|
2540
2624
|
},
|
|
2541
2625
|
"sign-in": {
|
|
@@ -401,7 +401,7 @@ export type Offer = z.infer<typeof offer>;
|
|
|
401
401
|
* 11 November 2026: every shared tool ships its questions). The list only
|
|
402
402
|
* shrinks; a new component can't join it.
|
|
403
403
|
*/
|
|
404
|
-
export declare const OFFER_PENDING: readonly ["ai", "analytics", "country", "database", "email", "email-inbound", "image-search", "images", "
|
|
404
|
+
export declare const OFFER_PENDING: readonly ["ai", "analytics", "country", "database", "email", "email-inbound", "image-search", "images", "strings", "ui"];
|
|
405
405
|
export interface ManifestProblem {
|
|
406
406
|
file: string;
|
|
407
407
|
check: "schema" | "proof" | "ids" | "surfaces" | "errors" | "generated";
|
|
@@ -267,7 +267,7 @@ export const capabilitySchema = z.strictObject(baseShape).superRefine((m, ctx) =
|
|
|
267
267
|
* 11 November 2026: every shared tool ships its questions). The list only
|
|
268
268
|
* shrinks; a new component can't join it.
|
|
269
269
|
*/
|
|
270
|
-
export const OFFER_PENDING = ["ai", "analytics", "country", "database", "email", "email-inbound", "image-search", "images", "
|
|
270
|
+
export const OFFER_PENDING = ["ai", "analytics", "country", "database", "email", "email-inbound", "image-search", "images", "strings", "ui"];
|
|
271
271
|
function checkOffer(file, component, o, seen) {
|
|
272
272
|
const problems = [];
|
|
273
273
|
const named = new Map();
|
package/dist/skills.js
CHANGED
|
@@ -41,8 +41,11 @@ function questionBlock(q, n) {
|
|
|
41
41
|
lines.push("Ask as a table: propose a value for each row, show the table, then ask one question with the answers \"Accept all (Recommended)\", \"Change some\" and \"Add or remove\".");
|
|
42
42
|
}
|
|
43
43
|
else {
|
|
44
|
+
// A must-ask question has no safe default, so none of its answers is recommended.
|
|
45
|
+
if (q.must_ask)
|
|
46
|
+
lines.push("None of these answers is recommended: only the client knows, so don't label any \"(Recommended)\".", "");
|
|
44
47
|
lines.push("| Answer | Value | Means |", "| --- | --- | --- |");
|
|
45
|
-
(q.answers ?? []).forEach((a, i) => lines.push(`| ${cell(a.label)}${i === 0 ? " (Recommended)" : ""} | ${show(a.value)} | ${cell(a.means ?? "")} |`));
|
|
48
|
+
(q.answers ?? []).forEach((a, i) => lines.push(`| ${cell(a.label)}${i === 0 && !q.must_ask ? " (Recommended)" : ""} | ${show(a.value)} | ${cell(a.means ?? "")} |`));
|
|
46
49
|
}
|
|
47
50
|
lines.push("", otherLine(q));
|
|
48
51
|
if (q.note)
|
|
@@ -149,7 +152,7 @@ export function renderSkill(m, guide) {
|
|
|
149
152
|
}
|
|
150
153
|
out.push("", "## What to say", "", d.choice === "optional"
|
|
151
154
|
? `Once the owner's choice is yes, say: "${o.say}"`
|
|
152
|
-
: `Say: "${o.say}" Don't ask whether to use Workbench or something of the client's own. If the client says they don't want it, stop and say what they give up.`, "", "## How to ask", "", ...(o.needs?.length ? [`- First check the project setup this needs: ${o.needs.map((n) => `\`workbench/${n}.json\``).join(", ")}. If one is missing, use that component's \`workbench-<component>\` skill first.`] : []), ...PATTERN_STEPS[o.pattern].map((step) => `- ${step}`), "- Ask with the AskUserQuestion tool, up to four questions per call. Give each question's answers in the order below; the first is recommended, so label it \"(Recommended)\". The tool adds \"Other\" itself.", "- Where the client accepts every recommendation, still ask each \"Must ask\" question.", "- An \"Other\" answer must meet the rule under its question. When it doesn't, say why and ask again. Never store a value outside it.", "- Ask nothing that isn't listed here, and invent no setting. A need the questions don't cover goes back to the client as a plain question, and isn't written to the answers file.", `- Write the answers to \`${o.answers_file}\`${o.per ? `, one entry per ${o.per}` : ""}: ${o.answers_format ?? `for each question its id, the value, and the client's own words when they typed "Other" or changed a recommendation.`}${o.generator ? ` Then run \`${o.generator}\`, which writes the code and refuses anything the package can't apply (it doesn't check the "Other" rules: you do). It builds nothing while an answers file is a draft. Never edit what it writes; change the answers file and run it again.` : ""}`, "", "## Questions", "", o.questions.map((q, i) => questionBlock(q, i + 1)).join("\n\n"));
|
|
155
|
+
: `Say: "${o.say}" Don't ask whether to use Workbench or something of the client's own. If the client says they don't want it, stop and say what they give up.`, "", "## How to ask", "", ...(o.needs?.length ? [`- First check the project setup this needs: ${o.needs.map((n) => `\`workbench/${n}.json\``).join(", ")}. If one is missing, use that component's \`workbench-<component>\` skill first.`] : []), ...PATTERN_STEPS[o.pattern].map((step) => `- ${step}`), "- Ask with the AskUserQuestion tool, up to four questions per call. Give each question's answers in the order below; the first is recommended, so label it \"(Recommended)\", unless the question says none is. The tool adds \"Other\" itself.", "- Where the client accepts every recommendation, still ask each \"Must ask\" question.", "- An \"Other\" answer must meet the rule under its question. When it doesn't, say why and ask again. Never store a value outside it.", "- Ask nothing that isn't listed here, and invent no setting. A need the questions don't cover goes back to the client as a plain question, and isn't written to the answers file.", `- Write the answers to \`${o.answers_file}\`${o.per ? `, one entry per ${o.per}` : ""}: ${o.answers_format ?? `for each question its id, the value, and the client's own words when they typed "Other" or changed a recommendation.`}${o.generator ? ` Then run \`${o.generator}\`, which writes the code and refuses anything the package can't apply (it doesn't check the "Other" rules: you do). It builds nothing while an answers file is a draft. Never edit what it writes; change the answers file and run it again.` : ""}`, "", "## Questions", "", o.questions.map((q, i) => questionBlock(q, i + 1)).join("\n\n"));
|
|
153
156
|
if (o.drafts)
|
|
154
157
|
out.push("", draftsBlock(o.drafts));
|
|
155
158
|
if (o.not_asked?.length) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mccaskie-labs/workbench-config",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "Workbench app configuration: WORKBENCH_ENV, typed variables that fail by name, secrets that are never printed, and the capabilities manifest.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|