@orderful/droid 0.53.0 → 0.55.0

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 (28) hide show
  1. package/.claude-plugin/plugin.json +4 -0
  2. package/CHANGELOG.md +16 -0
  3. package/README.md +21 -1
  4. package/dist/tools/propose-plan/skills/propose-plan/SKILL.md +6 -1
  5. package/dist/tools/test-blueprints/.claude-plugin/plugin.json +22 -0
  6. package/dist/tools/test-blueprints/TOOL.yaml +22 -0
  7. package/dist/tools/test-blueprints/commands/test-blueprints.md +27 -0
  8. package/dist/tools/test-blueprints/skills/test-blueprints/SKILL.md +160 -0
  9. package/dist/tools/test-blueprints/skills/test-blueprints/references/codebase-paths.md +79 -0
  10. package/dist/tools/test-blueprints/skills/test-blueprints/scripts/validate.d.ts +28 -0
  11. package/dist/tools/test-blueprints/skills/test-blueprints/scripts/validate.d.ts.map +1 -0
  12. package/dist/tools/test-blueprints/skills/test-blueprints/scripts/validate.ts +250 -0
  13. package/dist/tools/webform/.claude-plugin/plugin.json +22 -0
  14. package/dist/tools/webform/TOOL.yaml +26 -0
  15. package/dist/tools/webform/commands/webform.md +17 -0
  16. package/dist/tools/webform/skills/webform/SKILL.md +354 -0
  17. package/package.json +1 -1
  18. package/src/tools/propose-plan/skills/propose-plan/SKILL.md +6 -1
  19. package/src/tools/test-blueprints/.claude-plugin/plugin.json +22 -0
  20. package/src/tools/test-blueprints/TOOL.yaml +22 -0
  21. package/src/tools/test-blueprints/commands/test-blueprints.md +27 -0
  22. package/src/tools/test-blueprints/skills/test-blueprints/SKILL.md +160 -0
  23. package/src/tools/test-blueprints/skills/test-blueprints/references/codebase-paths.md +79 -0
  24. package/src/tools/test-blueprints/skills/test-blueprints/scripts/validate.ts +250 -0
  25. package/src/tools/webform/.claude-plugin/plugin.json +22 -0
  26. package/src/tools/webform/TOOL.yaml +26 -0
  27. package/src/tools/webform/commands/webform.md +17 -0
  28. package/src/tools/webform/skills/webform/SKILL.md +354 -0
@@ -23,6 +23,10 @@ A plan has two parts:
23
23
 
24
24
  The human reviewer sees your evidence first (the reasoning and impact), then reviews each action. Clear evidence builds trust; vague evidence gets rejected.
25
25
 
26
+ **An empty actions array is valid.** If your research shows no writes are needed — conflicts block all operations, the work is already done, or the situation requires human input before any action can be proposed — return `"actions": []` with evidence explaining why. This is a "findings only" output. The reviewer still gets your analysis.
27
+
28
+ **Partial plans are also valid.** If some items are blocked but others are clear, include actions only for the clear ones. Flag blocked items in caveats with specific reasons. Don't skip the entire plan because one item has a conflict.
29
+
26
30
  ## Output Format
27
31
 
28
32
  Produce a single JSON object matching the schema in `references/output-schema.json`. The shape:
@@ -169,7 +173,8 @@ These are hard rules. Violating any of them will cause the plan to be rejected o
169
173
  - **Don't include read operations as actions.** Actions are for writes only — things that change state and need human approval. Reading data is research, not an action. If you need to look something up, use read tools directly during your research phase.
170
174
  - **Don't fabricate data.** If a value wasn't in your research and you can't verify it with read tools, say so in caveats. Never guess IDs, names, emails, or configuration values. A plan with honest gaps gets sent back for more research. A plan with invented data gets approved and breaks things.
171
175
  - **Don't produce actions for tools outside your available list.** You can only propose actions for tools you've been given. If an operation requires a tool you don't have, note it as a caveat — don't invent an action for it. The execution step will reject unknown tools.
172
- - **Don't skip evidence.** A plan without evidence will be rejected. The reviewer needs to see what you found, what it means, and what will change. Evidence is not optional filler — it is how the reviewer decides whether to approve.
176
+ - **Don't skip evidence.** A plan without evidence will be rejected — even if the actions array is empty. The reviewer needs to see what you found, what it means, and what will change. Evidence is not optional filler — it is how the reviewer decides whether to approve.
177
+ - **Don't force actions when none are possible.** If conflicts or preconditions block all operations, return an empty actions array with evidence explaining why. A findings-only plan is better than a plan with actions that will fail.
173
178
  - **Don't combine multiple operations into one action.** Each action is one tool call. "Create org and set up billing" is two actions, not one. The execution step calls each action individually — a combined action will fail.
174
179
  - **Don't hardcode values from actions that haven't run yet.** If action 2 needs the org ID from action 1, don't guess or invent a value — use a template reference: `"orgId": "{{ actions.0.result.id }}"`. The execution step resolves these at runtime. Never put a placeholder like `"TBD"` or `"<org-id>"` in a payload.
175
180
  - **Don't use vague descriptions.** "Create org" tells the reviewer nothing. "Create Orderful org 'Acme Corp' with ISA ID 'ACME001'" tells them exactly what will happen. The description is what the reviewer reads before deciding whether to expand the payload.
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "droid-test-blueprints",
3
+ "version": "0.1.0",
4
+ "description": "Write and verify test blueprint HBS templates for EDI transaction types. Automates scenario design, template creation, registration, and Zod schema validation.",
5
+ "author": {
6
+ "name": "Orderful",
7
+ "url": "https://github.com/orderful"
8
+ },
9
+ "repository": "https://github.com/orderful/droid",
10
+ "license": "MIT",
11
+ "keywords": [
12
+ "droid",
13
+ "ai",
14
+ "test-blueprints"
15
+ ],
16
+ "skills": [
17
+ "./skills/test-blueprints/SKILL.md"
18
+ ],
19
+ "commands": [
20
+ "./commands/test-blueprints.md"
21
+ ]
22
+ }
@@ -0,0 +1,22 @@
1
+ name: test-blueprints
2
+ description: "Write and verify test blueprint HBS templates for EDI transaction types. Automates scenario design, template creation, registration, and Zod schema validation."
3
+ version: 0.1.0
4
+ status: beta
5
+ audience:
6
+ - engineering
7
+
8
+ includes:
9
+ skills:
10
+ - name: test-blueprints
11
+ required: true
12
+ commands:
13
+ - name: test-blueprints
14
+ is_alias: false
15
+ agents: []
16
+
17
+ dependencies: []
18
+
19
+ prerequisites:
20
+ - "ts-node and tsconfig-paths must be available in the target workspace (used by the validate script)"
21
+
22
+ config_schema: {}
@@ -0,0 +1,27 @@
1
+ ---
2
+ name: test-blueprints
3
+ description: "Write and verify test blueprint HBS templates for EDI transaction types."
4
+ argument-hint: "[write {type} | verify {type}]"
5
+ ---
6
+
7
+ # /test-blueprints
8
+
9
+ **User invoked:** `/test-blueprints $ARGUMENTS`
10
+
11
+ **Your task:** Invoke the **test-blueprints skill** with these arguments.
12
+
13
+ ## Examples
14
+
15
+ - `/test-blueprints write 943`
16
+ - `/test-blueprints verify 943`
17
+ - `/test-blueprints 944`
18
+
19
+ ## Quick Reference
20
+
21
+ ```bash
22
+ /test-blueprints write {type} # Full create flow: schema → scenarios → templates → register → validate
23
+ /test-blueprints verify {type} # Validate existing blueprints against Zod schema
24
+ /test-blueprints {type} # Alias for write {type}
25
+ ```
26
+
27
+ See the **test-blueprints skill** for full behaviour and validation rules.
@@ -0,0 +1,160 @@
1
+ ---
2
+ name: test-blueprints
3
+ description: "Write and verify test blueprint HBS templates for EDI transaction types. Use when creating test scenarios for a new transaction type (e.g., 'create blueprints for 943'), verifying existing blueprints against their Zod schema (e.g., 'verify 943 blueprints', 'validate the 855 templates'), or adding test blueprints to the testTransformation module. User prompts like 'create test blueprints for 940', 'generate 944 test templates', 'verify 943 blueprints', 'validate the 855 templates', 'check if 944 blueprints are valid'."
4
+ argument-hint: "[write {type} | verify {type}]"
5
+ allowed-tools: [Read, Write, Edit, Glob, Grep, Bash, Agent]
6
+ ---
7
+
8
+ # Test Blueprints Skill
9
+
10
+ Write and verify test blueprint HBS templates for EDI transaction types in the Orderful platform. Each blueprint is a JSON file conforming to the transaction type's simplified Zod schema, representing a distinct business scenario.
11
+
12
+ ## Commands
13
+
14
+ | Command | Action |
15
+ |---------|--------|
16
+ | `/test-blueprints write {type}` | Full workflow: discover schema, design scenarios, create templates, register, validate |
17
+ | `/test-blueprints verify {type}` | Validate existing blueprints against the Zod schema and report results |
18
+ | `/test-blueprints {type}` | Alias for `write {type}` |
19
+
20
+ ---
21
+
22
+ ## Command: verify
23
+
24
+ Validate existing blueprint templates against their Zod schema. Use this to check that all templates for a transaction type are still valid after schema changes, or to spot-check templates at any time.
25
+
26
+ ### Steps
27
+
28
+ 1. **Locate files.** Read `references/codebase-paths.md` for exact paths.
29
+ - Find the Zod schema for the transaction type
30
+ - Find the blueprint directory (`testBlueprints/{type}s/`)
31
+ - If no blueprints exist for the type, report that and stop
32
+
33
+ 2. **Read the Zod schema** to determine the schema export name and import path.
34
+
35
+ 3. **Run the validation script:**
36
+ ```bash
37
+ droid exec test-blueprints validate \
38
+ --workspace {workspace-root} \
39
+ --schema-import "{import-path}" \
40
+ --schema-name "{SchemaExportName}" \
41
+ --blueprints-dir "{path-to-blueprints-dir}"
42
+ ```
43
+
44
+ The script automatically:
45
+ - Discovers all `.json.hbs` files in the blueprints directory
46
+ - Skips templates containing Handlebars expressions (validated at render time, not statically)
47
+ - Validates remaining templates against the Zod schema via ts-node
48
+ - Returns structured JSON with per-file pass/fail/skip results
49
+
50
+ 4. **Report results.** Parse the JSON output and show a summary table:
51
+ - PASS / FAIL / SKIP status per template
52
+ - For failures: the exact field path and error message
53
+ - Suggest fixes for common mistakes (see Common Validation Pitfalls below)
54
+
55
+ ---
56
+
57
+ ## Command: write
58
+
59
+ Full workflow to create test blueprint templates for a transaction type.
60
+
61
+ ### Phase 1: Discovery
62
+
63
+ Identify the transaction type and locate the required files. Read `references/codebase-paths.md` for exact paths.
64
+
65
+ 1. **Find the Zod schema** for the transaction type. This is the source of truth for the template shape. Read it fully - every field, every enum value, every `metaEnum` definition. Also read `shared.zod.ts` for all imported shared types and their enum values.
66
+
67
+ 2. **Find the example JSON** (if one exists) in the simplified schema examples directory. This shows realistic field values.
68
+
69
+ 3. **Check TransactionTypeName** to confirm the enum key exists (e.g., `T943`).
70
+
71
+ 4. **Check existing blueprints** to see if templates already exist for this type. If they do, ask the user whether to replace or augment.
72
+
73
+ 5. **Determine if the template is static or templated.** This is an EDI domain question, not a codebase config lookup — the config may not exist yet for the transaction type.
74
+
75
+ Ask: **"Is this transaction type a direct response that echoes back data from a specific inbound document?"**
76
+
77
+ - **Static** — The transaction originates from the sender's own system data. The sender generates it from their own records (WMS, ERP, inventory system) without referencing a specific inbound EDI document. Templates are pure JSON with no Handlebars expressions.
78
+ - Examples: 846 (inventory report from seller's system), 943 (warehouse ships from WMS data), 944 (warehouse reports what it received), 940 (depositor issues a shipping order)
79
+ - **Templated** — The transaction is a direct response to a specific inbound document and structurally echoes back fields from it (line items, PO numbers, product IDs). Templates use Handlebars expressions to pull from the upstream document's data.
80
+ - Examples: 855 (acknowledges an 850's line items), 856 (ships against an 850), 810 (invoices against an 856)
81
+
82
+ If unsure, check existing templates for similar transaction types in the same document family.
83
+
84
+ ### Phase 2: Scenario Design
85
+
86
+ Analyse the Zod schema to identify the key variability dimensions, then design scenarios.
87
+
88
+ **Identify dimensions of variability:**
89
+ - Enum fields (especially top-level ones like reporting codes, purpose codes, status codes) - each distinct value is a potential scenario axis
90
+ - Optional object blocks (parties, dates, notes, references, carrier details) - presence/absence is a scenario axis
91
+ - Array fields (line items, pallets) - single vs. multiple is a scenario axis
92
+ - Nested optional structures (exception details, physical details, lot tracking) - exercising these is important
93
+
94
+ **Select 8-12 scenarios** ranked by business impact. Always include:
95
+ 1. **Standard/baseline** - the happy path with typical fields populated
96
+ 2. **Comprehensive** - every field populated (mirrors `810_comprehensive` / `846_comprehensive` pattern)
97
+ 3. **Minimal** - only required fields, everything optional absent
98
+
99
+ Then select the remaining scenarios based on what the schema uniquely supports. Prioritise:
100
+ - Each distinct enum value for top-level enums (e.g., different reporting codes)
101
+ - Key structural variations (pallets vs. loose items, single vs. multi-line)
102
+ - Industry-specific scenarios (cold chain, lot tracking, ocean shipment, returns)
103
+ - Correction/amendment flows (if the schema has a purpose/action code)
104
+
105
+ **Present the scenario list to the user** with a brief rationale for each before creating files. Wait for approval.
106
+
107
+ ### Phase 3: Template Creation
108
+
109
+ Create the blueprint files.
110
+
111
+ 1. **Create the directory** at:
112
+ ```
113
+ apps/platform-api/src/modules/testTransformation/data/testBlueprints/{type}s/
114
+ ```
115
+ where `{type}` is the three-digit transaction number (e.g., `943s`, `944s`).
116
+
117
+ 2. **Write each template** as a `.json.hbs` file. Follow these rules:
118
+ - File naming: `{type}_{scenarioName}.json.hbs` (e.g., `943_standard.json.hbs`)
119
+ - If static: pure JSON, no Handlebars expressions
120
+ - If templated: use Handlebars expressions to reference upstream context (e.g., `{{purchaseOrder.*}}`, `{{#each purchaseOrder.lineItems}}`). See existing 855 templates for the PO-response pattern.
121
+ - Use realistic but clearly fictional data (company names, addresses, product descriptions)
122
+ - Use distinct data across templates - don't copy-paste the same parties/products everywhere
123
+ - Every enum value must be a valid value from the Zod schema's `metaEnum` definition - use the simplified name (e.g., `"commonCarrier"`), not the X12 code (e.g., not `"M"`)
124
+
125
+ ### Phase 4: Registration
126
+
127
+ Register the blueprints in the repository.
128
+
129
+ 1. **Edit `testBlueprint.repository.ts`**:
130
+ - Add imports for each template file (follow the existing naming convention)
131
+ - Add a new entry in `blueprintsByTransactionType` under the appropriate `TransactionTypeName` key
132
+ - Place it in alphabetical/numerical order relative to existing entries
133
+
134
+ ### Phase 5: Validation
135
+
136
+ Run the **verify** command for the newly created templates. Fix any errors and re-run until all pass.
137
+
138
+ ### Phase 6: Summary
139
+
140
+ Report to the user:
141
+ - How many templates were created
142
+ - A table of template names and the scenario each covers
143
+ - The file edited for registration
144
+ - Validation result (all pass)
145
+
146
+ ---
147
+
148
+ ## Common Validation Pitfalls
149
+
150
+ These are the most frequent errors when writing blueprints. Check `shared.zod.ts` to verify exact enum values.
151
+
152
+ | Mistake | Fix |
153
+ |---------|-----|
154
+ | `"motor"` for transportation method | Use `"commonCarrier"` |
155
+ | `"truck"` for transportation method | Use `"commonCarrier"` or `"privateCarrier"` |
156
+ | `"inches"` for dimension UOM | Use `"inch"` |
157
+ | `"assignedByBuyer"` for identification code type | Use `"receiversId"` or a value from the enum |
158
+ | X12 codes like `"M"`, `"F"`, `"01"` | Use simplified names like `"commonCarrier"`, `"fullDetail"`, `"damaged"` |
159
+ | `"lbs"` or `"kg"` for weight UOM | Use `"pound"` or `"kilogram"` |
160
+ | `"EA"` or `"CS"` for unit of measure | Use `"each"` or `"case"` (lowercase simplified names) |
@@ -0,0 +1,79 @@
1
+ # Codebase Paths Reference
2
+
3
+ All paths are relative to the orderful-workspace root.
4
+
5
+ ## Zod Schemas (source of truth for template shape)
6
+
7
+ ```
8
+ libs/schemas/src/lib/data/simplifiedSchemas/
9
+ ```
10
+
11
+ To find the Zod schema for a transaction type, search the index:
12
+ ```bash
13
+ grep -r "TransactionTypeName.T<number>" libs/schemas/src/lib/data/simplifiedSchemas/index.ts
14
+ ```
15
+
16
+ Then find the schema file and export name from the import.
17
+
18
+ ## Example JSON (realistic field values)
19
+
20
+ ```
21
+ libs/schemas/src/lib/data/simplifiedSchemas/examples/
22
+ ```
23
+
24
+ Pattern: `simplified-<schemaName>.json`
25
+
26
+ ## Shared Zod Schemas (enum values, shared types)
27
+
28
+ ```
29
+ libs/schemas/src/lib/data/simplifiedSchemas/shared.zod.ts
30
+ ```
31
+
32
+ This file defines all shared types used across transaction schemas:
33
+ - `PartySchema` - party identification with contacts
34
+ - `QuantitySchema` - value + unit of measure
35
+ - `PhysicalDetailsSchema` - pack, weight, dimensions
36
+ - `LineItemIdentifiersSchema` - product IDs (buyer, vendor, GTIN)
37
+ - `ProductAttributeDetailsSchema` - description, color, size, material
38
+ - `RoutingDetailsSchema` - carrier and transportation method
39
+ - `EquipmentDetailsSchema` - trailer, container, seal
40
+ - `FOBDetailsSchema` - freight payment terms
41
+ - `SpecialHandlingDetailsSchema` - handling codes
42
+ - `CarrierWeightDetailsSchema` - shipment weight totals
43
+ - `NoteDetailsSchema` - notes with text array
44
+ - `PalletExchangeSchema` - pallet exchange/return enum
45
+ - `ContactSchema` - contact person details
46
+
47
+ ## TransactionTypeName Enum
48
+
49
+ ```
50
+ libs/platform-types/src/lib/transactionTypeNames.ts
51
+ ```
52
+
53
+ Check this file for the exact enum key (e.g., `T943`, `T944`).
54
+
55
+ ## Blueprint Templates
56
+
57
+ ```
58
+ apps/platform-api/src/modules/testTransformation/data/testBlueprints/
59
+ ```
60
+
61
+ Organised by type: `810s/`, `846s/`, `855s/`, `856s/`, `943s/`, etc.
62
+
63
+ ## Blueprint Repository (registration)
64
+
65
+ ```
66
+ apps/platform-api/src/modules/testTransformation/repositories/testBlueprint.repository.ts
67
+ ```
68
+
69
+ This file:
70
+ 1. Imports all `.json.hbs` template files
71
+ 2. Registers them in `blueprintsByTransactionType` under the `TransactionTypeName` key
72
+ 3. Optionally registers upstream blueprints in `upstreamBlueprints`
73
+
74
+ ## Validation Script Execution
75
+
76
+ ```bash
77
+ cd <workspace-root> && npx ts-node -r tsconfig-paths/register \
78
+ --project apps/platform-api/tsconfig.json <path-to-script>
79
+ ```
@@ -0,0 +1,250 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * test-blueprints validate
4
+ *
5
+ * Validate blueprint .json.hbs templates against their Zod schema.
6
+ * Generates a temporary validation script in the workspace and runs it
7
+ * via ts-node so that tsconfig paths resolve correctly.
8
+ *
9
+ * Usage:
10
+ * droid exec test-blueprints validate \
11
+ * --workspace /path/to/orderful-workspace \
12
+ * --schema-import "simplifiedSchemas/schemaFile" \
13
+ * --schema-name "Simplified943Schema" \
14
+ * --blueprints-dir "apps/platform-api/src/modules/testTransformation/data/testBlueprints/943s"
15
+ *
16
+ * Output (JSON):
17
+ * {
18
+ * "success": true,
19
+ * "results": [
20
+ * { "file": "943_standard.json.hbs", "status": "pass" },
21
+ * { "file": "943_templated.json.hbs", "status": "skip", "reason": "contains Handlebars expressions" },
22
+ * { "file": "943_bad.json.hbs", "status": "fail", "errors": [{ "path": "header.type", "message": "Invalid enum value" }] }
23
+ * ],
24
+ * "summary": { "pass": 8, "fail": 1, "skip": 2, "total": 11 }
25
+ * }
26
+ */
27
+
28
+ import { execSync } from 'child_process';
29
+ import { existsSync, writeFileSync, unlinkSync, readdirSync, readFileSync } from 'fs';
30
+ import { join } from 'path';
31
+ import { tmpdir } from 'os';
32
+
33
+ interface ValidationError {
34
+ path: string;
35
+ message: string;
36
+ }
37
+
38
+ interface FileResult {
39
+ file: string;
40
+ status: 'pass' | 'fail' | 'skip';
41
+ reason?: string;
42
+ errors?: ValidationError[];
43
+ }
44
+
45
+ interface ValidateResult {
46
+ success: boolean;
47
+ results?: FileResult[];
48
+ summary?: { pass: number; fail: number; skip: number; total: number };
49
+ error?: string;
50
+ }
51
+
52
+ interface ParsedArgs {
53
+ workspace?: string;
54
+ schemaImport?: string;
55
+ schemaName?: string;
56
+ blueprintsDir?: string;
57
+ }
58
+
59
+ function parseArgs(args: string[]): ParsedArgs {
60
+ const result: ParsedArgs = {};
61
+
62
+ for (let i = 0; i < args.length; i++) {
63
+ const arg = args[i];
64
+ if (arg === '--workspace' && args[i + 1]) {
65
+ result.workspace = args[++i];
66
+ } else if (arg === '--schema-import' && args[i + 1]) {
67
+ result.schemaImport = args[++i];
68
+ } else if (arg === '--schema-name' && args[i + 1]) {
69
+ result.schemaName = args[++i];
70
+ } else if (arg === '--blueprints-dir' && args[i + 1]) {
71
+ result.blueprintsDir = args[++i];
72
+ }
73
+ }
74
+
75
+ return result;
76
+ }
77
+
78
+ function expandPath(p: string): string {
79
+ if (p.startsWith('~/')) {
80
+ return p.replace('~', process.env.HOME || '');
81
+ }
82
+ if (p.startsWith('$HOME/')) {
83
+ return p.replace('$HOME', process.env.HOME || '');
84
+ }
85
+ return p;
86
+ }
87
+
88
+ function validate(parsed: ParsedArgs): ValidateResult {
89
+ if (!parsed.workspace) {
90
+ return { success: false, error: 'Missing --workspace' };
91
+ }
92
+ if (!parsed.schemaImport) {
93
+ return { success: false, error: 'Missing --schema-import' };
94
+ }
95
+ if (!parsed.schemaName) {
96
+ return { success: false, error: 'Missing --schema-name' };
97
+ }
98
+ if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(parsed.schemaName)) {
99
+ return { success: false, error: 'Invalid --schema-name: must be a valid identifier' };
100
+ }
101
+ if (/['"\n\r]/.test(parsed.schemaImport)) {
102
+ return { success: false, error: 'Invalid --schema-import: must not contain quotes or newlines' };
103
+ }
104
+ if (!parsed.blueprintsDir) {
105
+ return { success: false, error: 'Missing --blueprints-dir' };
106
+ }
107
+
108
+ const workspace = expandPath(parsed.workspace);
109
+ if (!existsSync(workspace)) {
110
+ return { success: false, error: `Workspace not found: ${workspace}` };
111
+ }
112
+
113
+ const blueprintsDir = parsed.blueprintsDir.startsWith('/')
114
+ ? parsed.blueprintsDir
115
+ : join(workspace, parsed.blueprintsDir);
116
+
117
+ if (!existsSync(blueprintsDir)) {
118
+ return { success: false, error: `Blueprints directory not found: ${blueprintsDir}` };
119
+ }
120
+
121
+ // Find .json.hbs files
122
+ const files = readdirSync(blueprintsDir).filter(f => f.endsWith('.json.hbs'));
123
+ if (files.length === 0) {
124
+ return { success: false, error: `No .json.hbs files found in ${blueprintsDir}` };
125
+ }
126
+
127
+ // Pre-check for Handlebars templates (skip these from Zod validation)
128
+ const results: FileResult[] = [];
129
+ const filesToValidate: string[] = [];
130
+
131
+ for (const file of files) {
132
+ const content = readFileSync(join(blueprintsDir, file), 'utf-8');
133
+ if (content.includes('{{')) {
134
+ results.push({ file, status: 'skip', reason: 'contains Handlebars expressions' });
135
+ } else {
136
+ // Check JSON parsability before sending to ts-node
137
+ try {
138
+ JSON.parse(content);
139
+ filesToValidate.push(file);
140
+ } catch (e) {
141
+ const err = e as Error;
142
+ results.push({ file, status: 'fail', errors: [{ path: '(root)', message: `Invalid JSON: ${err.message}` }] });
143
+ }
144
+ }
145
+ }
146
+
147
+ // If all files are skipped or failed JSON parse, return early
148
+ if (filesToValidate.length === 0) {
149
+ const summary = {
150
+ pass: 0,
151
+ fail: results.filter(r => r.status === 'fail').length,
152
+ skip: results.filter(r => r.status === 'skip').length,
153
+ total: results.length,
154
+ };
155
+ return { success: summary.fail === 0, results, summary };
156
+ }
157
+
158
+ // Generate validation script
159
+ const validationScript = `
160
+ import { ${parsed.schemaName} } from '${parsed.schemaImport}';
161
+ import * as fs from 'fs';
162
+ import * as path from 'path';
163
+
164
+ const dir = ${JSON.stringify(blueprintsDir)};
165
+ const filesToValidate: string[] = ${JSON.stringify(filesToValidate)};
166
+ const results: Array<{ file: string; status: string; errors?: Array<{ path: string; message: string }> }> = [];
167
+
168
+ for (const file of filesToValidate) {
169
+ const content = fs.readFileSync(path.join(dir, file), 'utf-8');
170
+ const parsed = JSON.parse(content);
171
+ const result = ${parsed.schemaName}.safeParse(parsed);
172
+
173
+ if (result.success) {
174
+ results.push({ file, status: 'pass' });
175
+ } else {
176
+ results.push({
177
+ file,
178
+ status: 'fail',
179
+ errors: result.error.issues.map((issue: { path: (string | number)[]; message: string }) => ({
180
+ path: issue.path.join('.'),
181
+ message: issue.message,
182
+ })),
183
+ });
184
+ }
185
+ }
186
+
187
+ console.log(JSON.stringify(results));
188
+ `.trim();
189
+
190
+ const scriptPath = join(tmpdir(), `_validate-${Date.now()}.ts`);
191
+
192
+ try {
193
+ writeFileSync(scriptPath, validationScript, 'utf-8');
194
+
195
+ const output = execSync(
196
+ `npx ts-node -r tsconfig-paths/register --project apps/platform-api/tsconfig.json ${JSON.stringify(scriptPath)}`,
197
+ {
198
+ cwd: workspace,
199
+ encoding: 'utf-8',
200
+ stdio: ['pipe', 'pipe', 'pipe'],
201
+ timeout: 60_000,
202
+ }
203
+ );
204
+
205
+ let zodResults: Array<{ file: string; status: string; errors?: ValidationError[] }>;
206
+ try {
207
+ zodResults = JSON.parse(output.trim());
208
+ } catch {
209
+ return { success: false, error: `Failed to parse validation output: ${output}` };
210
+ }
211
+
212
+ for (const r of zodResults) {
213
+ results.push({
214
+ file: r.file,
215
+ status: r.status as 'pass' | 'fail',
216
+ errors: r.errors,
217
+ });
218
+ }
219
+ } catch (err: unknown) {
220
+ const error = err as { stderr?: string; message?: string };
221
+ return {
222
+ success: false,
223
+ error: `Validation script failed: ${error.stderr || error.message}`,
224
+ };
225
+ } finally {
226
+ try { unlinkSync(scriptPath); } catch { /* ignore cleanup errors */ }
227
+ }
228
+
229
+ // Sort results to match original file order
230
+ results.sort((a, b) => files.indexOf(a.file) - files.indexOf(b.file));
231
+
232
+ const summary = {
233
+ pass: results.filter(r => r.status === 'pass').length,
234
+ fail: results.filter(r => r.status === 'fail').length,
235
+ skip: results.filter(r => r.status === 'skip').length,
236
+ total: results.length,
237
+ };
238
+
239
+ return { success: summary.fail === 0, results, summary };
240
+ }
241
+
242
+ // Main
243
+ const args = process.argv.slice(2);
244
+ const parsed = parseArgs(args);
245
+ const result = validate(parsed);
246
+ console.log(JSON.stringify(result, null, 2));
247
+
248
+ if (!result.success) {
249
+ process.exit(1);
250
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "droid-webform",
3
+ "version": "0.1.0",
4
+ "description": "Generate PrintView webform templates for EDI transaction types. Reads Orderful JSON schemas and sample transactions, proposes a visual layout, then generates template code with reusable subsection items.",
5
+ "author": {
6
+ "name": "Orderful",
7
+ "url": "https://github.com/orderful"
8
+ },
9
+ "repository": "https://github.com/orderful/droid",
10
+ "license": "MIT",
11
+ "keywords": [
12
+ "droid",
13
+ "ai",
14
+ "webform"
15
+ ],
16
+ "skills": [
17
+ "./skills/webform/SKILL.md"
18
+ ],
19
+ "commands": [
20
+ "./commands/webform.md"
21
+ ]
22
+ }
@@ -0,0 +1,26 @@
1
+ name: webform
2
+ description: "Generate PrintView webform templates for EDI transaction types. Reads Orderful JSON schemas and sample transactions, proposes a visual layout, then generates template code with reusable subsection items."
3
+ version: 0.1.0
4
+ status: beta
5
+ audience:
6
+ - engineering
7
+ - product
8
+
9
+ includes:
10
+ skills:
11
+ - name: webform
12
+ required: true
13
+ commands:
14
+ - name: webform
15
+ is_alias: false
16
+ agents: []
17
+
18
+ dependencies: []
19
+
20
+ config_schema:
21
+ schema_repo:
22
+ type: string
23
+ description: "Path to orderful-workspace repo (contains Orderful JSON schemas)"
24
+ ui_repo:
25
+ type: string
26
+ description: "Path to o2-app-ui repo (contains PrintView templates and subsection items)"
@@ -0,0 +1,17 @@
1
+ ---
2
+ name: webform
3
+ description: "Generate PrintView webform templates for EDI transaction types"
4
+ argument-hint: "{transaction-type} [sample-transaction-path-or-inline-json]"
5
+ ---
6
+
7
+ # /webform
8
+
9
+ **User invoked:** `/webform $ARGUMENTS`
10
+
11
+ **Your task:** Invoke the **webform skill** with these arguments.
12
+
13
+ ## Examples
14
+
15
+ - `/webform 850 ~/Downloads/sample-850.json` → Generate 850 template from sample
16
+ - `/webform 812 ~/Downloads/812.edi` → Generate 812 template from EDI file
17
+ - `/webform 997` → Start 997 template (will ask for sample transaction)