Report Creator
Workflow for building and deploying RDLX-JSON reports using the dxs CLI. Reports render in ActiveReportsJS within Datex Studio.
Key principle: Plan before code. Build the layout prototype before writing final JSON.
Prototyping and design: This skill has its own visual prototyping workflow — dxs report create + dxs report batch + dxs studio open for live preview in a browser. Do NOT use external brainstorming visual companions, browser-based mockup tools, or other prototyping tools unless the user explicitly requests them. The Studio live preview IS the design tool.
Authoring approach:
- Live prototyping for new reports — create a blank
.rdlx-json, build layout incrementally withdxs report create+dxs report batch, preview live in Studio - Incremental CLI (
add/set/move/remove/batch) for targeted edits during layout iteration - Direct JSON only for advanced structures not yet in the CLI (e.g., complex BandedList grouping, custom Tablix column/row hierarchies beyond simple header/detail)
References (shared):
- ../datex-studio-shared/branch-setup.md — Branch & connection selection
- ../datex-studio-shared/report-authoring/design-standards.md — Datex design language: color palette, typography, table styling, field label-value pattern, grid alignment, report categories
- ../datex-studio-shared/report-authoring/json-structure.md — Document template, element JSON formats, expression quick reference
- ../datex-studio-shared/report-authoring/design-patterns.md — Coordinate system, layout patterns, element sizing
- ../datex-studio-shared/report-authoring/cli-commands.md — Detailed CLI syntax: batch ops, tablix, images, datasets, set/move/remove
- ../datex-studio-shared/report-authoring/sample-data.md — Companion
.data.jsonfiles for live preview - ../datex-studio-shared/report-authoring/dataset-rules.md — DataSet management: CommandText rules, collection handling, date annotations
- ../datex-studio-shared/report-authoring/deploy-patterns.md — Upload, preview, and verification patterns
- ../datex-studio-shared/report-authoring/troubleshooting.md — Common RDLX-JSON and CLI mistakes & fixes
- ../datex-studio-shared/studio-management.md — Studio lifecycle: check, start, cleanup
References (creation-specific):
- references/ssrs-migration.md — Converting legacy SSRS (.rdl) reports to NextGen RDLX-JSON
- references/examples/ — Platonic ideals: canonical patterns for common report types, distilled from real-world corpus analysis
Orchestration Model
This skill is the top-level orchestrator for new report creation. It invokes dependency skills in sequence with validation gates between phases. Do NOT invoke the dependency skills independently before this skill — this skill triggers them at the right time with the right context.
report-creator (this skill — orchestrates everything)
│
├── Phase 1: Setup + Requirements
│ ├── Select branch + connection
│ └── Invoke `requirements-gathering` skill (routes to right source)
│ ├── DevOps work item → invokes `devops-requirements` skill
│ ├── Mockup/screenshot → visual analysis
│ ├── User conversation → structured Q&A
│ ├── Existing report (.rdl, .rdlx-json) → extract structure
│ └── Document/spec → extract fields and layout
│ Output: standardized requirements brief
│
├── Phase 2: Schema Discovery + Datasource Creation
│ ├── Invoke `schema-explorer` (via `datasource-creator`) for EVERY entity
│ ├── Invoke `datasource-creator` for EVERY datasource
│ ├── Invoke `odata-execution` to verify queries
│ │
│ ├── ▶ COVERAGE GATE: requirements brief vs datasource fields
│ │ For EVERY field in the requirements brief:
│ │ - Is it mapped to an OData path? If not, why?
│ │ - Is it included in a datasource config? If not, why?
│ │ - Does it need a calculated expression? Document it.
│ │ Present gap report to user. Do NOT proceed until gaps are
│ │ resolved or explicitly accepted.
│ │
│ └── Output: validated datasource configs + field coverage report
│
├── Phase 3: Layout Prototype (live in Studio)
│ ├── Create report + open in Studio
│ ├── Build sections incrementally with user feedback
│ ├── Add DataSets + sample data
│ └── Output: working .rdlx-json with sample data preview
│
├── Phase 4: Report Finalization
│ └── Verify DataSets, refine expressions, validate
│
└── Phase 5: Deploy & Verify
└── Upload, preview with real data, provide test parameters
Intent routing: create vs modify existing
If the user asks to modify an existing report on a branch (e.g., "add a column to the receiving report", "change the label on the BOL", "update the report on branch 64"), invoke the report-editor skill instead. Report-creator is for building new reports from scratch.
If the user says "modify" but the report does not exist yet on the branch, confirm with the user: "That report doesn't exist on this branch yet. Should I create it from scratch?" If yes, continue with report-creator.
Planning boundary: Phases 1-3 complete during planning (before ExitPlanMode). The prototype IS the report file — Phase 4 picks up where Phase 3 left off. Phases 4-5 execute after plan approval.
Phase 1: Setup + Requirements
Select branch
Follow branch-setup.md to identify the active organization, list repositories, select a feature branch, and discover API connections.
Artifact collection (optional)
Ask the user if they want to save process artifacts to disk (schema notes, queries, report file, sample data, preview images). Suggested location: ./reports/<report-name>/.
If yes, create the artifact directory and use this naming convention:
| Filename | Content |
|---|---|
01-schema-exploration.md |
Entity descriptions, field lists, relationships |
02-field-mapping.md |
Field mapping table |
<report-name>.rdlx-json |
The report file (created in Phase 3, refined in Phase 4) |
<report-name>.data.json |
Sample data for live Studio preview |
04-query-building.md |
Incremental query steps and final verified query |
<report-name>-preview.svg |
Preview image from dxs report preview |
requirements/ |
Downloaded attachments and requirements brief (DevOps) |
Requirements gathering
Invoke the requirements-gathering skill. It handles routing to the right source (DevOps work item, mockup, conversation, document, existing report) and produces a standardized requirements brief with:
- Field list with semantic roles (what each field means, not just its name)
- Layout expectations
- Business rules and calculated fields
- Parameters
The requirements brief is the input to Phase 2 (schema exploration + datasource creation) and the coverage gate that follows it.
Platonic ideals: Check references/examples/ for a canonical pattern matching the report type (e.g., license plate label, BOL, packing slip). These are distilled from corpus analysis of real-world reports and define the essential elements, common optional fields, layout properties, and structural archetypes. Use the platonic ideal to validate requirements completeness and guide layout decisions — it tells you what a typical report of this type looks like and what variations exist.
For SSRS migrations: If the source includes .rdl files, also see references/ssrs-migration.md for how to read them and translate SQL→OData.
Phase 2: Schema Discovery + Datasource Creation
Examples and templates are hypotheses. Schema exploration against the CURRENT connection is the validation. Entity availability, property names, types, and relationships vary between connections.
Footprint reports — check
footprint-entity-expertfirst. If the report queries Footprint WMS entities (Tasks, Shipments, ArchivedShippingLicensePlateContents, LicensePlate, Lot, Material, etc.), thefootprint-entity-expertskill has navigation chains, weight-calc rules, and entity-selection guidance that schema metadata alone won't tell you. Consult it before invokingdatasource-creatorso the schema exploration is targeted at the right entities. Skip this for non-Footprint apps.
For each datasource the report needs:
- Invoke
datasource-creatorskill with mode =owned— the default. Usestandaloneonly when an override applies: another report or component genuinely needs the same query, or a flow datasource must reach it via$datasources.<Package>.<name>(flow dependencies are always standalone). Full list in ../datasource-creator/references/datasources.md → Owned by Default. For a report, "owned" means the datasource stays its own file, registered in the folder manifest with--owned FILE:ALIAS— not a block spliced into the report JSON - Datasource-creator invokes
schema-explorerandodata-executionto validate entities and properties against the live connection - For flow datasources: schema exploration identifies the OData entities and fields the flow code will query, then the type definition is built from validated schema — not from examples
- Collect the return summary: JSON config file path, reference name, result type, in_params, and field summary (used in Phase 3 Step 5 for DataSet creation)
Repeat for each datasource needed by the report.
Volume awareness: the 5,000-record OData cap
OData endpoints return at most 5,000 records per request. For any datasource that aggregates over a date range, multiple owners/projects, or any other dimension that produces high record counts (Tasks, ArchivedShippingLicensePlateContents, Shipments, etc.), the report will silently truncate to the first 5k rows unless the underlying flow paginates.
When designing the datasource:
- Single-record OData datasources (
--param-keys, e.g.,Shipments(0)) — no pagination needed. - Collection OData datasources backing a tablix (typical line-items query) — usually no pagination needed if the parent filter already bounds the rows (e.g.,
ShipmentLines?$filter=ShipmentId eq X). - Flow datasources that aggregate over date ranges, warehouses, owners, etc. — must paginate. Surface this to the
datasource-creatorinvocation so the standalone OData datasources it builds declare askipinParam, and the flow code loops until a short page comes back.
See ../datex-studio-shared/flow-code-patterns.md#odata-pagination--the-5000-record-cap for the wiring details and the canonical loop. If you don't paginate when you should, the report under-counts at busy warehouses without any error — the symptom is silent data loss.
Coverage gate: requirements vs datasource fields
For every field in the requirements brief:
| Check | Action if failed |
|---|---|
| Field has an OData path in the schema mapping | Investigate: is the entity missing? Is the path too deep? Propose a linked or flow datasource. |
| Field is included in a datasource config | Add it — the datasource may need regeneration with additional $select/$expand paths. |
Field requires a calculation (e.g., tareWeight = GrossWeight - NetWeight) |
Document the expression for Phase 3. Note fields needed as inputs. |
| Field has no OData equivalent (e.g., SQL function, custom view) | Propose a flow datasource, or flag as a known gap for user decision. |
Present the coverage report to the user:
### Coverage Report: Requirements → Datasources
✅ Covered (N fields): [list]
⚠️ Calculated (N fields): [field → expression]
❌ Not available (N fields): [field → reason + proposed solution]
Proceed to layout? [Y / resolve gaps first]
This gate catches errors like:
- Shipper mapped to wrong entity (Account instead of Owner)
- Line-item fields omitted from datasource (tareWeight, packUOM)
- Deep navigation paths skipped without alternatives (Owner address)
Phase 3: Layout Prototype (Live in Studio)
Build an actual RDLX-JSON report and preview it live in Datex Studio. The prototype IS the report file — Phase 4 picks up where this phase leaves off. The user sees every change in real time.
Step 1: Create a blank report
dxs report create <artifact_dir>/<report_name>_report --page letter --margins 0.5in
Use --page for standard sizes (letter, legal, a4, 4x6, 4x8) or custom (WxH). Add --landscape for landscape orientation. --margins supports CSS-style shorthand.
Naming rule: The folder name becomes the report's referenceName, which the Datex Studio platform uses to generate TypeScript service classes. It must be a valid JavaScript identifier — letters, digits, underscores, $ only. No hyphens, dots, or spaces. Use the _report suffix convention.
| Bad | Good | Why |
|---|---|---|
srs-bol |
srs_bol_report |
Hyphens break TS class names |
srs-bol.rdlx-json |
srs_bol_report |
Dots and extensions break TS imports |
my report |
my_report |
Spaces are not valid in identifiers |
Alias rule for owned datasources: When adding owned datasources with dxs report datasource add --owned FILE:ALIAS, the alias must match the datasource's referenceName inside the JSON config file. The platform registers services by referenceName but the report references them by alias — a mismatch causes "property does not exist" TS errors. Example: if the config has "referenceName": "ds_bol_header", use --owned ds_bol_header.json:ds_bol_header.
Step 2: Open in Studio
dxs studio open <artifact_dir>/<report_name>_report/report.rdlx-json
This opens the report in the Studio design canvas at http://127.0.0.1:5051/design. Every file change is reflected live.
Auto-manage Studio per ../datex-studio-shared/studio-management.md: check status, start in background if needed (with readiness verification), open the report, and clean up after Phase 5.
Step 3: Build layout incrementally with dxs report batch
Use dxs report batch to add elements in groups. Write ops to a file and use --ops-file to avoid shell escaping issues. Maximum 25 operations per batch.
Apply the Datex design language from ../datex-studio-shared/report-authoring/design-standards.md: set FontFamily: Arial on all text elements (use Courier New for numeric values and barcode captions), use the official color palette (Black, DimGray, LightGray, Gray, Datex Purple #5B08B2), style tables with purple header borders and LightGray row separators (no background colors), follow the field label-value pattern (8pt DimGray labels above 10pt Black values), and snap positions to the 0.25in grid.
Build in logical sections using rectangle containers. Every major section (header, info fields, address blocks, footer) should be wrapped in a rectangle. Add the rectangle first, then add child elements with "parent": "RectangleName". Child coordinates are relative to the rectangle's top-left corner (0,0), so moving the rectangle repositions everything inside it. This is important for layout iteration — without rectangles, repositioning a section means moving every element individually. See ../datex-studio-shared/report-authoring/cli-commands.md for the batch pattern. Tables are self-contained and don't need a rectangle wrapper.
Tables: Use dxs report add tablix for line items with --header-cell, --detail-cell, --footer-cell (repeated options, one per cell) and --header-style/--detail-style/--footer-style for row-level defaults. Prefer footer rows over standalone textboxes for totals.
Lines use start-x/start-y/end-x/end-y in batch (not left/top/width/height). move does not work on lines — edit JSON directly.
Images: Use dxs report add image --file logo.png for embedded images, --source Database --value '=Fields!X.Value' for data-bound images. Database-bound images need data URIs in the sample data file — see ../datex-studio-shared/report-authoring/sample-data.md.
PageHeader/PageFooter: These are document-root elements requiring direct JSON editing — see ../datex-studio-shared/report-authoring/json-structure.md.
See ../datex-studio-shared/report-authoring/cli-commands.md for detailed syntax and examples of all batch operations, tablix creation, image handling, and element editing.
Step 4: Create sample data file
Create a companion <report-name>.data.json alongside the report. Studio auto-discovers this file.
Scaffold from DataSets — after adding DataSets (Step 5), generate a template:
dxs report data generate <report-name>.rdlx-json -o <report-name>.data.json
Then replace placeholders with realistic sample values — 3-5 rows per dataset. Field names must match DataSet field Names (underscore notation, e.g., Lines_Material_LookupCode), not dot-notation DataField paths.
See ../datex-studio-shared/report-authoring/sample-data.md for the full format and examples.
Step 5: Add DataSets to the report
REQUIRED for Studio preview. Without DataSet definitions, Studio shows "no matching DataSet in report" errors and field expressions render as raw text.
Follow dataset-rules.md for DataSet creation, CommandText patterns, collection handling, date annotations, and sensitivity properties.
Use the field summary from the datasource-creator's return as the primary source for field names — it is extracted directly from the generated config's type definitions and is authoritative. Include ALL fields, not just the ones used in expressions. The field-mapping artifact provides additional human-readable context for layout decisions but should not be the primary source for DataSet field names.
Immediately after dataset add, verify the CommandText matches the datasource result type from the Phase 2 datasource-creator return:
- If
Result type: collection→ CommandText must end with.*(e.g.,$.ds_name.result.*) - If
Result type: single→ CommandText must not end with.*(e.g.,$.ds_name.result)
Getting this wrong silently produces an empty report (no error, no data, no warning). This is the single most common DataSet binding mistake.
Phase 4 will verify against the actual datasource (standalone) or the config JSON (owned).
Handling collection fields in DataSets:
Check the datasource-creator return for fields marked [collection]. These cannot be added as flat DataSet fields on a single-result DataSet — they will silently render blank.
Preferred approach: flow datasource. If the datasource-creator return contains collections with fields needed in standalone textboxes, go back to Phase 2 and rebuild that datasource as a flow. The flow code fetches the OData data and flattens collections into scalar fields. This is the production pattern used by all existing Datex Studio reports with complex navigation.
Alternative: child datasets with CommandText deep paths. If a flow rewrite is not feasible, create a separate DataSet that navigates into the collection:
{
"Name": "ds_shipment_OrderLookups",
"Fields": [
{"Name": "Order_OwnerReference", "DataField": "Order.OwnerReference"},
{"Name": "Order_Account_Name", "DataField": "Order.Account.Name"}
],
"Query": {
"DataSourceName": "Datasource",
"CommandText": "$.ds_shipment.result.OrderLookups.*"
}
}
Then reference fields with =First(Fields!Order_OwnerReference.Value, "ds_shipment_OrderLookups") in standalone textboxes. For nested collections (collection within collection), chain the path: $.ds_shipment.result.OrderLookups.*.Order.Addresses.*.
CommandText .* suffix rule:
- Single result, scalar fields:
$.ds_name.result(no.*) - Collection result (table/tablix):
$.ds_name.result.* - Collection within single result:
$.ds_name.result.CollectionPath.*
Step 6: Verify with preview
dxs report preview <file> -o /tmp/preview.svg
dxs report preview <file> --bbox Title:red --bbox LinesTable:blue -o /tmp/inspect.svg
Use --bbox NAME[:COLOR] for visual debugging with colored bounding boxes.
Feedback iteration loop
After building each section, ask the user how it looks in Studio. Use dxs report batch with set/move/remove ops for changes. Repeat until the user approves.
Layout reference
See ../datex-studio-shared/report-authoring/design-patterns.md for pattern examples (Shipping Label, GS1, BOL, Tabular Report) and element sizing tables.
Phase 4: Report Finalization
The .rdlx-json file already exists from Phase 3 with layout, elements, sample data, and DataSet definitions. This phase finalizes it for deployment.
Finalization checklist
- Verify DataSets — For standalone datasources: compare field Names/DataFields against
dxs report datasource-fields <ref> --branch <id>output. For owned datasources: compare against the field summary from Phase 2 (datasource-fields is only available post-upload). Add missing fields withdxs report dataset add-field. EnsureCommandText = $.{ds_name}.result.*and all sensitivity properties are present. - Refine expressions — Update any placeholder values with final
=Fields!Name.Valueexpressions. See ../datex-studio-shared/report-authoring/json-structure.md for expression quick reference. - Validate:
dxs report validate my-report.rdlx-json
For incremental edits during finalization, see ../datex-studio-shared/report-authoring/cli-commands.md for set/move/remove/dataset add-field syntax.
Phase 5: Deploy & Verify
Follow deploy-patterns.md for upload (owned vs standalone), preview, verification, and test parameter discovery.
Artifact: Save preview with dxs report preview <report>.rdlx-json -o <artifact_dir>/<report-name>-preview.svg.
Wrap-up (after the upload is verified)
Once the config is confirmed on the branch:
- Files: follow the Cleanup prompt in deploy-patterns.md — ask the user before deleting session files; never clean up silently. If the user opted into artifact collection in Phase 1, default to keeping the artifacts.
- Processes: stop what you started, per the Cleanup section in studio-management.md —
dxs studio stopif you launched Studio in the background (no need to ask; never stop a server the user launched), and check for lingering preview processes (agent-browser session daemons / headless Chrome frompreview-arjs/validate-arjs). A process that refuses to die, or any leftover that blocks the terminal, is a reportable CLI lifecycle defect — record the symptom chain rather than killing blindly.
Troubleshooting
See troubleshooting.md for common RDLX-JSON expression issues and layout/CLI mistakes.
After your edit, invoke post-edit-verification to surface description/JSON/schema violations. For a final review, invoke component-validator.