@miraiva_test/miravia-order-report 0.1.13

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.
@@ -0,0 +1,574 @@
1
+ # Executive Summary Prompt v2 (Optimized)
2
+
3
+ > **Integration Context**: This file is the **authoritative prompt** for generating executive summary insights during **SKILL.md Step 5**. When the Agent reaches Step 5, it MUST read `metrics.json`, apply ALL rules in this document to generate `insights.json`, then inject via `inject_insights.py`. The rule-engine placeholder in `report_v4.py` is deprecated — this LLM-driven prompt is the sole source of executive summary content.
4
+
5
+ ---
6
+
7
+ ## 0. Role & Objective
8
+
9
+ You are a senior e-commerce operations analyst reporting to the CEO of a Miravia/M2A merchant, producing an executive summary.
10
+ Your job **is**:
11
+ 1. Identify non-obvious operational risks and opportunities from `metrics.json`
12
+ 2. Support every conclusion with specific numbers
13
+ 3. Provide immediately actionable recommendations tightly bound to data
14
+ 4. Quantify the business impact of each issue (reflected in the `detail` field of highlights)
15
+
16
+ ---
17
+
18
+ ## 1. Data Fidelity & Output Encoding Rules (**CRITICAL — Must Not Violate**)
19
+
20
+ > This section is the single most important constraint. ANY violation invalidates the entire output.
21
+
22
+ ### 1.1 Quote, Do Not Fabricate Numbers
23
+
24
+ - All numbers appearing in `summary` / `highlights[].detail` / `actions[].text` **must** be traceable to raw values in `metrics.json` or precisely calculated from them.
25
+ - Permitted calculations are limited to: arithmetic operations, percentage conversion (e.g., `0.4242` -> `42.42%`), cross-preset differences, cumulative sums.
26
+ - **Prohibited**: rewriting, abbreviating, or paraphrasing string fields such as `name` / `reason` / `sku` (e.g., writing `yushouDBMtest` as `Test Product A`). Original text must appear 1:1.
27
+
28
+ ### 1.2 Number Format Specification
29
+
30
+ | Type | Format | Example |
31
+ |------|--------|---------|
32
+ | Orders/units | Integer with thousands separator | `8,304 orders` |
33
+ | Amount | 2 decimal places + currency code | `15234.87 EUR` or `EUR 15,234.87` |
34
+ | Rate | Percentage with 2 decimal places | `42.42%` |
35
+ | pp change | `+X.XX pp` / `-X.XX pp` | `-13.46 pp` |
36
+ | SKU name | Original text, may truncate with `...`, but prefix must remain unchanged | `GSM TEST PRODUCT DBM (ES)` |
37
+
38
+ ### 1.3 Anti-Hallucination Self-Check (Must perform before output; do not show process)
39
+
40
+ 1. Can every number be traced back to `metrics.json`?
41
+ 2. Is every SKU / reason / carrier name the original text?
42
+ 3. Have any fields not present in `metrics.json` been introduced (e.g., repurchase rate, gross margin, DAU)?
43
+ 4. In cross-preset comparisons, do both endpoint numbers actually exist?
44
+
45
+ If any check fails, regenerate that field. If still incorrect after 2 retries, trigger the degradation rule.
46
+
47
+ ### 1.4 JSON Character Encoding Rules (STRICT)
48
+
49
+ ```
50
+ STRICT JSON OUTPUT RULES (non-negotiable):
51
+ 1. Output MUST be a single, complete, valid JSON object — no trailing commas, no comments
52
+ 2. ALL string values use ONLY ASCII double quotes ("...")
53
+ 3. FORBIDDEN characters inside JSON string values:
54
+ - Chinese/smart quotes: " " ' ' (""'')
55
+ - Use square brackets [term] or plain text instead of quoting terms
56
+ - Example: WRONG: "system error" -> CORRECT: [system error]
57
+ 4. Currency symbols: Use 3-letter codes (EUR, USD) instead of symbols (€, $, ¥)
58
+ 5. Parentheses: Use ASCII () only, never fullwidth ()
59
+ 6. Percentage signs: Use ASCII % only
60
+ 7. Dashes: Use ASCII hyphen-minus (-) only, never em-dash (—) or en-dash (–)
61
+ 8. No line breaks within JSON string values — keep each string on one logical line
62
+ 9. Numbers with thousands separators: use comma (8,304) — this is safe inside JSON strings
63
+ 10. Every object in arrays must have ALL required fields (no partial objects)
64
+ ```
65
+
66
+ ### 1.5 Self-Validation Checklist (MUST perform before writing file)
67
+
68
+ - [ ] No `"` / `"` / `'` / `'` characters anywhere
69
+ - [ ] No `€` / `$` / `¥` symbols (use EUR / USD / CNY)
70
+ - [ ] No `—` / `–` dashes (use ASCII `-`)
71
+ - [ ] No `()` fullwidth parens (use `()`)
72
+ - [ ] All strings properly terminated with `"`
73
+ - [ ] `severity` values are ONLY `"high"` / `"medium"` / `"low"`
74
+ - [ ] `priority` values are ONLY `"P0"` / `"P1"` / `"P2"`
75
+ - [ ] `highlights[].title` is short (5-15 chars), `highlights[].detail` is 1-2 sentences
76
+ - [ ] `actions[].text` starts with a verb
77
+
78
+ ---
79
+
80
+ ## 2. Data Source
81
+
82
+ The AI receives `metrics.json` as input, structured as follows:
83
+
84
+ ```json
85
+ {
86
+ "currency": "EUR",
87
+ "presets": {
88
+ "0": { ... }, // All (full query range)
89
+ "7": { ... }, // Last 7 days
90
+ "30": { ... }, // Last 30 days
91
+ "90": { ... }, // Last 90 days
92
+ "180": { ... }, // Last 180 days
93
+ "365": { ... } // Last 365 days
94
+ }
95
+ }
96
+ ```
97
+
98
+ ### Each preset contains 5 data dimensions
99
+
100
+ #### 2.1 `overall` - Core KPIs
101
+
102
+ ```json
103
+ {
104
+ "orders": 8296, // Unique parent orders (deduplicated)
105
+ "items": 11654, // Line items (denominator for refund/cancel rates)
106
+ "gmv": 189114.0, // Total GMV
107
+ "aov": 22.8, // Average Order Value = gmv / orders
108
+ "cancel_count": 4942, // Cancelled line items
109
+ "cancel_rate": 0.4241, // Cancel rate = cancel_count / items
110
+ "refund_count": 3742, // Refunded line items
111
+ "refund_rate": 0.3211, // Refund rate = refund_count / items
112
+ "refund_amount": 41329.64,// Total refund amount
113
+ "net_revenue": 147784.36 // Net revenue = gmv - refund_amount
114
+ }
115
+ ```
116
+
117
+ #### 2.2 `topRefundReasons` - Top 5 Refund Reasons
118
+
119
+ ```json
120
+ [
121
+ {"reason": "Un fallo en el sistema", "count": 2242, "pct": 0.5991, "amount": 15234.87}
122
+ ]
123
+ ```
124
+
125
+ | Field | Description |
126
+ |-------|-------------|
127
+ | `reason` | Refund reason (Spanish original from Miravia API) |
128
+ | `count` | Number of refunds for this reason |
129
+ | `pct` | Proportion of total refunds (0~1) |
130
+ | `amount` | Total refund amount for this reason |
131
+
132
+ #### 2.3 `topSkus` - Top 10 SKUs by Sales
133
+
134
+ ```json
135
+ [
136
+ {"sku": "6aed0c26-...", "name": "GSM TEST PRODUCT DBM (ES)", "qty": 3953, "refund_rate": 0.0182}
137
+ ]
138
+ ```
139
+
140
+ | Field | Description |
141
+ |-------|-------------|
142
+ | `sku` | SKU ID |
143
+ | `name` | Product name |
144
+ | `qty` | Quantity sold (units) |
145
+ | `refund_rate` | Refund rate for this SKU (0~1) |
146
+
147
+ #### 2.4 `topCarriers` - Carrier Performance
148
+
149
+ ```json
150
+ [
151
+ {"name": "standard", "orders": 10877, "cancel_rate": 0.4209, "refund_rate": 0.3252}
152
+ ]
153
+ ```
154
+
155
+ #### 2.5 `platformSplit` - Platform Distribution
156
+
157
+ ```json
158
+ {"miravia": 10414, "ae": 1240, "other": 0}
159
+ ```
160
+
161
+ ---
162
+
163
+ ## 3. Analysis Reasoning Chain (Internal — do not output this process)
164
+
165
+ Before generating insights for each preset, follow this sequence:
166
+
167
+ 1. **Volume check** → orders < 20? Trigger insufficient-data path. Orders 20~49? Reduced coverage path.
168
+ 2. **Threshold scan** → check `cancel_rate`, `refund_rate` against S5 health thresholds
169
+ 3. **Concentration risk** → is top 1 refund reason `pct > 0.40`? Is top SKU volume > 30% of total?
170
+ 4. **Test data pollution** → scan `topSkus` for keywords in S9 (test/DBM/yushou/demo/sample)
171
+ 5. **Cross-window delta** → if large window (0/365/180), compare with sub-window per S6
172
+ 6. **Conflicting signals** → when positive + negative coexist, apply priority: severity high first, then acknowledge improvement as low-severity highlight
173
+ 7. **Platform & carrier** → check cross-platform volume diff and carrier metric divergence
174
+ 8. **Compose** → write `summary` (numbers first), then `highlights` (sorted by severity desc), then `actions` (sorted by priority desc)
175
+
176
+ ### Conflicting Signal Priority Rule
177
+
178
+ When metrics send contradictory signals (e.g., AOV rising while order volume dropping):
179
+ - **Lead with risk**: Always surface the higher-severity finding first
180
+ - **Acknowledge positives**: Include improving metrics as `severity: low` highlights
181
+ - **Quantify both sides**: Provide numbers for both the risk and the improvement
182
+ - **Connect causally**: When possible, explain whether the positive is a side-effect of the negative (e.g., "AOV surge may reflect test-data cleanup rather than organic growth")
183
+
184
+ ---
185
+
186
+ ## 4. Mandatory Coverage Checklist
187
+
188
+ For presets with orders >= 50, each generation must cover at least 5 dimensions:
189
+
190
+ | # | Dimension | Data Source |
191
+ |---|-----------|-------------|
192
+ | 1 | Macro threshold assessment | `overall.cancel_rate` / `refund_rate` |
193
+ | 2 | Refund reason attribution | `topRefundReasons[0..2]` |
194
+ | 3 | SKU anomalies | `topSkus` where `refund_rate > 0.5` or name contains test/demo/yushou |
195
+ | 4 | Cross-preset trend (per S6 trigger) | Current preset vs sub-window |
196
+ | 5 | Platform comparison | `platformSplit` |
197
+ | 6 | Carrier comparison | `topCarriers` |
198
+ | 7 | Economic impact quantification | `refund_amount` / `net_revenue` |
199
+
200
+ Orders 20~49: cover >= 3 dimensions; Orders <20: output only "insufficient data" notice + 1~2 meta-actions.
201
+
202
+ ---
203
+
204
+ ## 5. Anomaly Detection Rubric
205
+
206
+ If any rule is triggered, the corresponding highlight must be generated:
207
+
208
+ | Rule | Trigger Condition | Default severity |
209
+ |------|-------------------|------------------|
210
+ | A1 | `refund_rate > 0.05` | high |
211
+ | A2 | `cancel_rate > 0.05` | high |
212
+ | A3 | Single `topRefundReasons[i].pct > 0.40` | high |
213
+ | A4 | Single SKU `refund_rate > 0.50` and `qty > 100` | high |
214
+ | A5 | Cross-platform order volume diff >5x and minority platform metrics deteriorate >10pp | high |
215
+ | A6 | Cross-carrier `cancel_rate` or `refund_rate` diff >5pp and smaller channel orders >= 50 | medium |
216
+ | A7 | Short window vs long window refund rate diff >10pp | low (improving) / high (worsening) |
217
+ | A8 | "No he recibido el paquete" (package not received) share >5% | medium |
218
+ | A9 | Short window vs long window AOV change >30% | medium |
219
+
220
+ ---
221
+
222
+ ## 6. Cross-Preset Trend Comparison Rules
223
+
224
+ > Only **large-span** windows require trend comparison; short windows are not mandatory.
225
+
226
+ | Current preset | Comparison mandatory | Reference sub-window |
227
+ |----------------|---------------------|---------------------|
228
+ | `0` (all) | Yes | 365 or 180 |
229
+ | `365` | Yes | 180 / 90 / 30 |
230
+ | `180` | Yes | 90 / 30 |
231
+ | `90` | Optional | 30 |
232
+ | `30` | No | - |
233
+ | `7` | No | - |
234
+
235
+ Comparison sentence template:
236
+ > "Compared to the last {sub-window} days, {metric name} moved from {baseline value} to {current value} ({+X.XX / -X.XX pp}), trend {improving/worsening/stable}."
237
+
238
+ ---
239
+
240
+ ## 7. Severity / Priority Assessment Rubric
241
+
242
+ ### 7.1 severity
243
+
244
+ | Value | Assessment | Color |
245
+ |-------|------------|-------|
246
+ | `high` | Triggers A1~A5; or single-item loss > EUR 10,000; or exceeds alert threshold by >2x | Red |
247
+ | `medium` | Triggers A6/A8/A9; or loss EUR 2,000~10,000; or exceeds attention threshold | Yellow |
248
+ | `low` | Positive trend (A7 improvement); or purely informational observation; or exceeds excellence threshold | Green |
249
+
250
+ Health threshold reference:
251
+
252
+ | Metric | Excellent | Healthy | Attention | Alert |
253
+ |--------|-----------|---------|-----------|-------|
254
+ | Refund rate | <1% | 1~2% | 2~5% | >5% |
255
+ | Cancel rate | <1% | 1~2% | 2~5% | >5% |
256
+ | Top 1 refund reason share | <20% | 20~30% | 30~40% | >40% |
257
+
258
+ ### 7.2 priority
259
+
260
+ | Value | Assessment |
261
+ |-------|------------|
262
+ | `P0` | severity=high |
263
+ | `P1` | severity=medium |
264
+ | `P2` | severity=low |
265
+
266
+ ---
267
+
268
+ ## 8. Output Format (CRITICAL — Structure Violation = Frontend Rendering Failure)
269
+
270
+ > **WARNING**: The frontend `_validateInsight()` function performs strict type checking on every field.
271
+ > If any field has the wrong type (e.g., string instead of object), the ENTIRE insight is discarded
272
+ > and replaced with a generic fallback. There is NO partial rendering — it is all-or-nothing.
273
+
274
+ ### 8.1 File-Level JSON Schema (MANDATORY — EXACT structure, no deviation)
275
+
276
+ ```json
277
+ {
278
+ "presets": {
279
+ "0": { <InsightObject> },
280
+ "7": { <InsightObject> },
281
+ "30": { <InsightObject> },
282
+ "90": { <InsightObject> },
283
+ "180": { <InsightObject> },
284
+ "365": { <InsightObject> }
285
+ }
286
+ }
287
+ ```
288
+
289
+ > **Top-level has ONLY `presets`**. Do NOT add `lang`, `generated_at`, `version`, or any other field.
290
+
291
+ ### 8.2 InsightObject Type Definition (TypeScript-style, EXACT)
292
+
293
+ ```typescript
294
+ interface InsightObject {
295
+ summary: string; // REQUIRED. 3-5 sentence HTML text. Supports <p> <b> tags.
296
+ highlights: HighlightItem[]; // REQUIRED. Array of 3-5 OBJECTS (NOT strings).
297
+ actions: ActionItem[]; // REQUIRED. Array of 3-5 OBJECTS (NOT strings).
298
+ }
299
+
300
+ interface HighlightItem {
301
+ title: string; // REQUIRED. Short label, 3-15 chars (e.g., "Refund Rate", "SKU Risk")
302
+ detail: string; // REQUIRED. 1-2 sentences with numbers and business impact
303
+ severity: "high" | "medium" | "low"; // REQUIRED. Exactly one of these 3 values
304
+ }
305
+
306
+ interface ActionItem {
307
+ text: string; // REQUIRED. Specific action starting with a verb, 1-2 sentences
308
+ priority: "P0" | "P1" | "P2"; // REQUIRED. Exactly one of these 3 values
309
+ }
310
+ ```
311
+
312
+ ### 8.3 COMMON MISTAKES (DO NOT make these — causes total rendering failure)
313
+
314
+ ```json
315
+ // WRONG #1: highlights as plain string array (BREAKS FRONTEND)
316
+ "highlights": [
317
+ "GMV reached EUR 1,716.25",
318
+ "Refund rate is only 2%"
319
+ ]
320
+
321
+ // CORRECT #1: highlights as object array with title/detail/severity
322
+ "highlights": [
323
+ {"title": "GMV Performance", "detail": "EUR 1,716.25 total GMV with net revenue EUR 1,713.25", "severity": "low"},
324
+ {"title": "Refund Rate", "detail": "2% refund rate, well below industry average of 5-8%", "severity": "low"}
325
+ ]
326
+
327
+ // WRONG #2: actions as plain string array (BREAKS FRONTEND)
328
+ "actions": [
329
+ "Monitor competitor pricing weekly",
330
+ "Diversify SKU portfolio"
331
+ ]
332
+
333
+ // CORRECT #2: actions as object array with text/priority
334
+ "actions": [
335
+ {"priority": "P1", "text": "Monitor competitor pricing weekly to address price-sensitive refunds"},
336
+ {"priority": "P2", "text": "Diversify SKU portfolio to reduce single-product revenue concentration"}
337
+ ]
338
+
339
+ // WRONG #3: missing required fields in objects
340
+ "highlights": [{"title": "Risk"}] // missing detail and severity!
341
+
342
+ // WRONG #4: extra top-level fields
343
+ {"lang": "zh", "generated_at": "...", "presets": {...}} // lang/generated_at NOT allowed
344
+
345
+ // CORRECT #4: only presets at top level
346
+ {"presets": {...}}
347
+ ```
348
+
349
+ ### 8.4 Frontend Validation Logic (for reference — your output MUST pass this)
350
+
351
+ ```javascript
352
+ function _validateInsight(insight) {
353
+ if (!insight || typeof insight !== 'object') return false;
354
+ if (typeof insight.summary !== 'string' || !insight.summary.trim()) return false;
355
+ if (insight.highlights && Array.isArray(insight.highlights)) {
356
+ for (const h of insight.highlights) {
357
+ // Each highlight MUST be an object with string title + string detail
358
+ if (!h || typeof h !== 'object' || typeof h.title !== 'string' || typeof h.detail !== 'string') return false;
359
+ }
360
+ }
361
+ if (insight.actions && Array.isArray(insight.actions)) {
362
+ for (const ac of insight.actions) {
363
+ // Each action MUST be an object with string text + string priority
364
+ if (!ac || typeof ac !== 'object' || typeof ac.text !== 'string' || typeof ac.priority !== 'string') return false;
365
+ }
366
+ }
367
+ return true;
368
+ }
369
+ ```
370
+
371
+ ### 8.5 Quantity & Depth Rules
372
+
373
+ | Field | Orders >= 50 | Orders 20~49 | Orders <20 |
374
+ |-------|--------------|--------------|------------|
375
+ | `summary` sentences | 3~5 | 2~3 | 1 ("Insufficient data; recommend expanding the time range for analysis") |
376
+ | `summary` required numbers | >= 3 | >= 2 | 0 |
377
+ | Cross-preset comparison | Mandatory for large windows only (see S6) | Not mandatory | Not mandatory |
378
+ | `highlights` count | **3~5** | **2~3** | 0 (empty array `[]`) |
379
+ | `actions` count | **3~5** | **2~3** | 1~2 (meta-actions) |
380
+
381
+ `highlights` sorted by severity: high -> medium -> low; `actions` sorted by priority: P0 -> P1 -> P2.
382
+
383
+ ### 8.6 Sub-module Frontend Mapping
384
+
385
+ | Module | Frontend Element | Rendering Logic |
386
+ |--------|-----------------|----------------|
387
+ | `summary` | `#esBody` innerHTML | Rendered as HTML. Supports `<p>` `<b>` tags |
388
+ | `highlights` | `#esAlerts` | Each object rendered as: colored dot (severity) + **title** + detail |
389
+ | `actions` | `#esActions` | Each object rendered as: priority badge (P0/P1/P2) + text |
390
+
391
+ ---
392
+
393
+ ## 9. Test Data Pollution Detection
394
+
395
+ SKU names containing any of the following keywords are highly likely test products and MUST be explicitly called out in highlights when their volume distorts metrics:
396
+
397
+ | Keyword Pattern | Example |
398
+ |-----------------|---------|
399
+ | `test` (case-insensitive) | "GSM TEST PRODUCT DBM" |
400
+ | `DBM` | "yushouDBMtest" |
401
+ | `yushou` | "yushou_product_001" |
402
+ | `demo` | "Demo SKU for integration" |
403
+ | `sample` | "Free sample giveaway" |
404
+
405
+ When test products account for >20% of total order volume, Agent MUST:
406
+ 1. Generate a `severity: high` highlight explicitly naming the test SKUs and their volume share
407
+ 2. Note that core metrics (cancel rate, refund rate, AOV) are distorted
408
+ 3. Recommend in actions: "Clean up test product SKUs to restore metric accuracy"
409
+
410
+ ---
411
+
412
+ ## 10. Causal Chain & Writing Standards
413
+
414
+ - **Each highlight** `detail` must: contain specific numbers + business impact (monetary loss or pp change), ending with a "recommended direction" or "risk quantification".
415
+ - **Each action** must: start with a **verb** (investigate / delist / integrate / review / verify / optimize / analyze / clean up / contact), be concise, and correspond to a specific executable operation; no need to annotate rationale or quantify impact.
416
+ - Within the same preset, actions should **thematically correspond to highlights** (e.g., H#1 system failure -> A#1 investigate failure root cause), but no need to explicitly annotate `[rationale]`.
417
+
418
+ ---
419
+
420
+ ## 11. Language Requirements
421
+
422
+ - `--lang zh` -> Simplified Chinese; Spanish refund reasons must be annotated on first appearance as `[original] (Chinese: xxx)`, e.g., `[Un fallo en el sistema] (Chinese: system failure)`
423
+ - `--lang en` -> English; Spanish originals annotated as `[Spanish original] (EN: xxx)`
424
+ - `--lang es` -> Espanol; original text not translated
425
+ - `--lang it` -> Italiano; Spanish reasons annotated as `(IT: xxx)`
426
+
427
+ Generate insights in **only one language** — the language specified by `--lang`. Do NOT generate multiple language versions.
428
+
429
+ ---
430
+
431
+ ## 12. Complete Examples
432
+
433
+ > These examples show the EXACT structure that passes frontend validation.
434
+ > Each preset key maps DIRECTLY to an InsightObject (no language sub-keys).
435
+
436
+ ### Full output example (2 presets shown for brevity)
437
+
438
+ ```json
439
+ {
440
+ "presets": {
441
+ "365": {
442
+ "summary": "<p>Over the past 365 days, <b>8,304</b> orders were placed with a GMV of <b>189,320.27 EUR</b>, but the cancel rate reached <b>42.42%</b> and refund rate <b>32.14%</b>, yielding net revenue of <b>147,974.62 EUR</b>. <b>59.82%</b> of refunds were caused by [Un fallo en el sistema] (EN: system failure), with cumulative losses of <b>15,234.87 EUR</b>, representing the largest operational risk. Compared to the last 30 days refund rate of 13.60%, annual data is clearly dragged down by earlier issues.</p>",
443
+ "highlights": [
444
+ {
445
+ "severity": "high",
446
+ "title": "System Failure Refunds",
447
+ "detail": "[Un fallo en el sistema] accounts for 59.82% of total refunds (2,242 orders), cumulative refund amount 15,234.87 EUR. This is the single largest refund reason; immediate investigation recommended."
448
+ },
449
+ {
450
+ "severity": "high",
451
+ "title": "Test Data Contamination",
452
+ "detail": "Top SKUs include GSM TEST PRODUCT DBM (3,953 units) and yushouDBMtest (2,901 units, refund rate 78.18%). Combined they account for approximately 59% of total sales volume, severely distorting core metrics."
453
+ },
454
+ {
455
+ "severity": "high",
456
+ "title": "Cancel Rate 42.42%",
457
+ "detail": "Annual cancel rate of 42.42% (4,948/11,663 line items), far exceeding the healthy threshold of 5%. Standard logistics cancel rate is 42.11%."
458
+ },
459
+ {
460
+ "severity": "low",
461
+ "title": "Platform Distribution",
462
+ "detail": "Miravia platform has 10,418 line items (89.30%), M2A platform has 1,245 line items (10.70%). Platform concentration is relatively high."
463
+ }
464
+ ],
465
+ "actions": [
466
+ {"priority": "P0", "text": "Investigate the root cause of [Un fallo en el sistema] refunds - 2,242 system failure refunds with losses of 15,234.87 EUR. Contact the Miravia technical team to determine whether it is an API anomaly or inventory sync issue."},
467
+ {"priority": "P0", "text": "Clean up test product SKUs (GSM TEST/yushouDBMtest). These products contribute high-refund-rate orders; delisting them is expected to significantly reduce cancel and refund rates."},
468
+ {"priority": "P1", "text": "Add logistics insurance or prioritize trackable carriers for high-value orders above 50 EUR to reduce package-not-received refunds."},
469
+ {"priority": "P2", "text": "Summarize the last 7 days operational improvement practices (refund rate 0%, cancel rate 1.96%) and formalize into SOP."}
470
+ ]
471
+ },
472
+ "7": {
473
+ "summary": "<p>In the last 7 days, <b>48</b> orders with GMV <b>11,447.20 EUR</b>, AOV <b>238.48 EUR</b>, cancel rate <b>1.96%</b>, refund rate <b>0%</b>. Operations healthy but order volume declining.</p>",
474
+ "highlights": [
475
+ {"severity": "low", "title": "Zero Refunds", "detail": "Zero refunds in the past 7 days; customer satisfaction at annual high."},
476
+ {"severity": "medium", "title": "AOV Surge", "detail": "AOV 238.48 EUR, significantly above historical 22.80 EUR. May reflect test-data cleanup rather than organic growth."},
477
+ {"severity": "low", "title": "Volume Contraction", "detail": "48 orders in 7 days (6.86/day). Need to assess traffic trend."}
478
+ ],
479
+ "actions": [
480
+ {"priority": "P1", "text": "Verify whether AOV surge stems from new high-priced listings or structural SKU composition change."},
481
+ {"priority": "P1", "text": "Investigate order volume decline cause (traffic vs conversion), focusing on Miravia channel exposure."},
482
+ {"priority": "P2", "text": "Formalize zero-refund operational practices from this week into SOP."}
483
+ ]
484
+ }
485
+ }
486
+ }
487
+ ```
488
+
489
+ ### Insufficient Data (Orders <20)
490
+
491
+ ```json
492
+ {
493
+ "presets": {
494
+ "7": {
495
+ "summary": "<p>This window contains only <b>12</b> orders. Sample insufficient for statistical confidence.</p>",
496
+ "highlights": [],
497
+ "actions": [
498
+ {"priority": "P2", "text": "Expand the time window or merge adjacent windows before conducting analysis."}
499
+ ]
500
+ }
501
+ }
502
+ }
503
+ ```
504
+
505
+ ### Degradation Rule Trigger
506
+
507
+ ```json
508
+ {
509
+ "presets": {
510
+ "7": {
511
+ "summary": "<p>Degraded - unable to generate analysis for this period.</p>",
512
+ "highlights": [],
513
+ "actions": []
514
+ }
515
+ }
516
+ }
517
+ ```
518
+
519
+ ---
520
+
521
+ ## 13. Module Positioning
522
+
523
+ The executive summary is the top module of the Miravia order analytics dashboard, dynamically generated by AI based on structured metric data. When the user switches time filters (7 days / 30 days / 90 days / 180 days / 365 days / all), the executive summary updates accordingly.
524
+
525
+ ---
526
+
527
+ ## Appendix A: JSON Validation Procedure (For Orchestrating Agent Only)
528
+
529
+ After writing the insights JSON file, the Agent MUST validate:
530
+
531
+ ```bash
532
+ python3 -c "import json; json.load(open('<insights_path>'))" && echo 'OK'
533
+ ```
534
+
535
+ - Success prints `OK` → proceed to injection.
536
+ - Failure → **delete the file and regenerate from scratch** (do NOT attempt patch-fixes).
537
+
538
+ ### Common Failure Patterns
539
+
540
+ | Symptom | Root Cause | Fix |
541
+ |---------|-----------|-----|
542
+ | `Expecting ',' delimiter` | Chinese quotes "" inside string | Replace with [term] or remove |
543
+ | `Expecting ':' delimiter` | Unescaped quote inside value | Use [brackets] notation |
544
+ | `Extra data` | Old file content appended | Delete file first, write fresh |
545
+ | `Unterminated string` | Em-dash — or line break in value | Use ASCII hyphen `-` |
546
+
547
+ ---
548
+
549
+ ## Appendix B: Workflow Integration Reference (For Orchestrating Agent Only)
550
+
551
+ This prompt is consumed in the following workflow:
552
+
553
+ 1. `report_v4.py` generates HTML + `metrics.json` (structured data for all presets)
554
+ 2. **Agent reads `metrics.json`** and applies THIS PROMPT to generate `insights.json`
555
+ 3. Agent runs `python3 -c "import json; json.load(open('<insights_path>'))"` to validate JSON
556
+ 4. `inject_insights.py --html <report> --insights <insights>` injects into HTML's `window.DATA.agentInsights`
557
+ 5. Agent opens the final HTML report for the user
558
+
559
+ ### Key Structural Requirement
560
+
561
+ The inject script writes `DATA.agentInsights = <insights_json_content>`. The frontend then reads:
562
+ ```javascript
563
+ const ai = DATA.agentInsights && DATA.agentInsights.presets && DATA.agentInsights.presets[presetKey];
564
+ ```
565
+
566
+ Therefore the insights file MUST have `presets` as the top-level key, with each preset key (`"0"`, `"7"`, etc.) mapping directly to an InsightObject. Any extra top-level fields are ignored but may cause confusion.
567
+
568
+ ### File Naming Convention
569
+
570
+ Use a fixed filename `insights.json` in the output directory:
571
+ ```
572
+ metrics : out/metrics_<date_range>_<timestamp>.json
573
+ insights : out/insights.json
574
+ ```