@trohde/earos 1.1.2 → 1.3.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 (70) hide show
  1. package/assets/init/docs/getting-started.md +1 -1
  2. package/assets/init/docs/onboarding/agent-assisted.md +19 -19
  3. package/assets/init/docs/onboarding/first-assessment.md +18 -18
  4. package/assets/init/docs/onboarding/governed-review.md +10 -10
  5. package/assets/init/docs/onboarding/overview.md +15 -15
  6. package/assets/init/docs/onboarding/scaling-optimization.md +13 -13
  7. package/assets/init/docs/plans/2026-03-23-001-refactor-site-review-findings-plan.md +195 -0
  8. package/assets/init/docs/plans/2026-03-23-002-refactor-cli-review-findings-plan.md +736 -0
  9. package/assets/init/docs/profile-authoring-guide.md +5 -9
  10. package/assets/init/docs/terminology.md +1 -1
  11. package/bin.js +156 -36
  12. package/dist/assets/{_basePickBy-PmSUrUsK.js → _basePickBy-BlC_TeV6.js} +1 -1
  13. package/dist/assets/{_baseUniq-HuZouVIz.js → _baseUniq-CVy7rcC1.js} +1 -1
  14. package/dist/assets/{arc-CJFxtF3d.js → arc-Cd8wvd7z.js} +1 -1
  15. package/dist/assets/{architectureDiagram-2XIMDMQ5-XA-oU2UG.js → architectureDiagram-2XIMDMQ5-D_f4_aMp.js} +1 -1
  16. package/dist/assets/{blockDiagram-WCTKOSBZ-Oxp-wAST.js → blockDiagram-WCTKOSBZ-B-y6N5--.js} +1 -1
  17. package/dist/assets/{c4Diagram-IC4MRINW-D8m5hQH9.js → c4Diagram-IC4MRINW-C3-v3oNT.js} +1 -1
  18. package/dist/assets/channel-BSC0F15G.js +1 -0
  19. package/dist/assets/{chunk-4BX2VUAB-D2kBTn2O.js → chunk-4BX2VUAB-CMPwQN83.js} +1 -1
  20. package/dist/assets/{chunk-55IACEB6-Dxqrf5oZ.js → chunk-55IACEB6-Bdkfhvrr.js} +1 -1
  21. package/dist/assets/{chunk-FMBD7UC4-DoOEFFQC.js → chunk-FMBD7UC4-ptKQX5uF.js} +1 -1
  22. package/dist/assets/{chunk-JSJVCQXG-BerphV2K.js → chunk-JSJVCQXG-DO0UU_OX.js} +1 -1
  23. package/dist/assets/{chunk-KX2RTZJC-CxUAqT05.js → chunk-KX2RTZJC-DRj2OZnD.js} +1 -1
  24. package/dist/assets/{chunk-NQ4KR5QH-fCqZgFkU.js → chunk-NQ4KR5QH-C4Nsf7ww.js} +1 -1
  25. package/dist/assets/{chunk-QZHKN3VN-HlpHnJEy.js → chunk-QZHKN3VN-B1GO0Nwy.js} +1 -1
  26. package/dist/assets/{chunk-WL4C6EOR-D9yxAHyd.js → chunk-WL4C6EOR-lFR6fjR8.js} +1 -1
  27. package/dist/assets/classDiagram-VBA2DB6C-BHDWMOEz.js +1 -0
  28. package/dist/assets/classDiagram-v2-RAHNMMFH-BHDWMOEz.js +1 -0
  29. package/dist/assets/clone-BdN-3iAD.js +1 -0
  30. package/dist/assets/{cose-bilkent-S5V4N54A-F5xOBvqW.js → cose-bilkent-S5V4N54A-IpR9mVIO.js} +1 -1
  31. package/dist/assets/{dagre-KLK3FWXG-CD3BTpHv.js → dagre-KLK3FWXG-B4YA6T7N.js} +1 -1
  32. package/dist/assets/{diagram-E7M64L7V-C3D9MCay.js → diagram-E7M64L7V-Do5l6es_.js} +1 -1
  33. package/dist/assets/{diagram-IFDJBPK2-zJBVM-GK.js → diagram-IFDJBPK2-D5MxfKVv.js} +1 -1
  34. package/dist/assets/{diagram-P4PSJMXO-BrmFZOLB.js → diagram-P4PSJMXO-Djr28EgW.js} +1 -1
  35. package/dist/assets/{erDiagram-INFDFZHY-aSMhKiV2.js → erDiagram-INFDFZHY-BuM-rbCL.js} +1 -1
  36. package/dist/assets/{flowDiagram-PKNHOUZH-DwgX7l8F.js → flowDiagram-PKNHOUZH-By3WGI7Q.js} +1 -1
  37. package/dist/assets/{ganttDiagram-A5KZAMGK-C57Hz6QW.js → ganttDiagram-A5KZAMGK-GLmBfK72.js} +1 -1
  38. package/dist/assets/{gitGraphDiagram-K3NZZRJ6-CuchqqGh.js → gitGraphDiagram-K3NZZRJ6-BN0iXeIv.js} +1 -1
  39. package/dist/assets/{graph-CPFGBV5J.js → graph-CDzuMtjV.js} +1 -1
  40. package/dist/assets/{index-DMt1cpG6.js → index-DoeSN_Oe.js} +130 -130
  41. package/dist/assets/{infoDiagram-LFFYTUFH-Dd_5tfX7.js → infoDiagram-LFFYTUFH-C888gaFw.js} +1 -1
  42. package/dist/assets/{ishikawaDiagram-PHBUUO56-DwosSEvT.js → ishikawaDiagram-PHBUUO56-ChIO9DG-.js} +1 -1
  43. package/dist/assets/{journeyDiagram-4ABVD52K-BuCxcsX0.js → journeyDiagram-4ABVD52K-CufMUDcs.js} +1 -1
  44. package/dist/assets/{kanban-definition-K7BYSVSG-DF_1UCkW.js → kanban-definition-K7BYSVSG-BpsSVpX8.js} +1 -1
  45. package/dist/assets/{layout-DIcS6m1g.js → layout-B8RWVBSF.js} +1 -1
  46. package/dist/assets/{linear-BXkwBhoJ.js → linear-BJwxtq9r.js} +1 -1
  47. package/dist/assets/{mindmap-definition-YRQLILUH-DcDvYagd.js → mindmap-definition-YRQLILUH-C6WPimbf.js} +1 -1
  48. package/dist/assets/{pieDiagram-SKSYHLDU-BmeDeWDM.js → pieDiagram-SKSYHLDU-DeCGMWf8.js} +1 -1
  49. package/dist/assets/{quadrantDiagram-337W2JSQ-3zfjULUM.js → quadrantDiagram-337W2JSQ-D9TWaS83.js} +1 -1
  50. package/dist/assets/{requirementDiagram-Z7DCOOCP-B2wQMJpq.js → requirementDiagram-Z7DCOOCP-DTnuXlAq.js} +1 -1
  51. package/dist/assets/{sankeyDiagram-WA2Y5GQK-__kKlCTq.js → sankeyDiagram-WA2Y5GQK-B2dplCgD.js} +1 -1
  52. package/dist/assets/{sequenceDiagram-2WXFIKYE-B7O81Vih.js → sequenceDiagram-2WXFIKYE-cBvgSSju.js} +1 -1
  53. package/dist/assets/{stateDiagram-RAJIS63D-CcJaDrAK.js → stateDiagram-RAJIS63D-Cwr7VtSX.js} +1 -1
  54. package/dist/assets/stateDiagram-v2-FVOUBMTO-B59h7VTZ.js +1 -0
  55. package/dist/assets/{timeline-definition-YZTLITO2-DSaQQqIU.js → timeline-definition-YZTLITO2-Dkp163fK.js} +1 -1
  56. package/dist/assets/{treemap-KZPCXAKY-9Hcrd8XD.js → treemap-KZPCXAKY-BUWHa5xU.js} +1 -1
  57. package/dist/assets/{vennDiagram-LZ73GAT5-BqHNyca2.js → vennDiagram-LZ73GAT5-BihD66ma.js} +1 -1
  58. package/dist/assets/{xychartDiagram-JWTSCODW-BqeYf6Fk.js → xychartDiagram-JWTSCODW-Cw4lPbuZ.js} +1 -1
  59. package/dist/index.html +1 -1
  60. package/export-docx.js +12 -4
  61. package/init.js +19 -14
  62. package/manifest-cli.mjs +32 -3
  63. package/package.json +3 -2
  64. package/serve.js +44 -19
  65. package/utils/export-markdown.js +486 -0
  66. package/dist/assets/channel-SoktpVBQ.js +0 -1
  67. package/dist/assets/classDiagram-VBA2DB6C-BT2AdZTe.js +0 -1
  68. package/dist/assets/classDiagram-v2-RAHNMMFH-BT2AdZTe.js +0 -1
  69. package/dist/assets/clone-DOjIfi5r.js +0 -1
  70. package/dist/assets/stateDiagram-v2-FVOUBMTO-B2goOPt-.js +0 -1
@@ -0,0 +1,486 @@
1
+ /**
2
+ * EaROS — Markdown export utilities for artifacts, rubrics, and evaluations.
3
+ *
4
+ * Pure client-side functions that convert structured data objects to Markdown strings.
5
+ */
6
+ // ─── Shared helpers ──────────────────────────────────────────────────────────
7
+ function humanize(key) {
8
+ return key.replace(/_/g, ' ').replace(/\b\w/g, (c) => c.toUpperCase());
9
+ }
10
+ function str(v) {
11
+ if (v == null)
12
+ return '';
13
+ if (typeof v === 'string')
14
+ return v.trim();
15
+ if (typeof v === 'number' || typeof v === 'boolean')
16
+ return String(v);
17
+ return '';
18
+ }
19
+ function mdTable(headers, rows) {
20
+ if (rows.length === 0)
21
+ return '';
22
+ const sep = headers.map(() => '---');
23
+ const lines = [
24
+ `| ${headers.join(' | ')} |`,
25
+ `| ${sep.join(' | ')} |`,
26
+ ...rows.map((r) => `| ${r.map((c) => c.replace(/\|/g, '\\|').replace(/\n/g, ' ')).join(' | ')} |`),
27
+ ];
28
+ return lines.join('\n');
29
+ }
30
+ function mdList(items) {
31
+ return items.map((i) => `- ${i}`).join('\n');
32
+ }
33
+ function isPlainObject(v) {
34
+ return !!v && typeof v === 'object' && !Array.isArray(v);
35
+ }
36
+ export function downloadAsFile(content, filename, mimeType) {
37
+ if (typeof document === 'undefined')
38
+ return; // Node.js — no browser download
39
+ const blob = new Blob([content], { type: mimeType });
40
+ const url = URL.createObjectURL(blob);
41
+ const a = document.createElement('a');
42
+ a.href = url;
43
+ a.download = filename;
44
+ a.click();
45
+ URL.revokeObjectURL(url);
46
+ }
47
+ // ─── Artifact Markdown ───────────────────────────────────────────────────────
48
+ const SECTION_ORDER = [
49
+ 'reading_guide',
50
+ 'scope',
51
+ 'drivers_and_principles',
52
+ 'architecture_views',
53
+ 'crosscutting_concerns',
54
+ 'component_classification',
55
+ 'components',
56
+ 'decisions',
57
+ 'architecture_decisions',
58
+ 'quality_attributes',
59
+ 'operational_model',
60
+ 'implementation_guidance',
61
+ 'implementation_artifacts',
62
+ 'governance',
63
+ 'raid',
64
+ 'decisions_and_actions',
65
+ 'getting_started',
66
+ 'evolution',
67
+ 'glossary',
68
+ ];
69
+ function renderMetadataMd(meta) {
70
+ const lines = [];
71
+ const skip = new Set(['title', 'artifact_type']);
72
+ for (const [key, value] of Object.entries(meta)) {
73
+ if (skip.has(key))
74
+ continue;
75
+ if (value == null)
76
+ continue;
77
+ if (Array.isArray(value)) {
78
+ if (value.length === 0)
79
+ continue;
80
+ if (isPlainObject(value[0])) {
81
+ lines.push(`\n**${humanize(key)}:**\n`);
82
+ const keys = Object.keys(value[0]);
83
+ lines.push(mdTable(keys.map(humanize), value.map((item) => keys.map((k) => str(item[k])))));
84
+ }
85
+ else {
86
+ lines.push(`**${humanize(key)}:** ${value.map(str).join(', ')}`);
87
+ }
88
+ }
89
+ else if (isPlainObject(value)) {
90
+ lines.push(`**${humanize(key)}:**`);
91
+ for (const [k, v] of Object.entries(value)) {
92
+ lines.push(`- ${humanize(k)}: ${str(v)}`);
93
+ }
94
+ }
95
+ else {
96
+ lines.push(`**${humanize(key)}:** ${str(value)}`);
97
+ }
98
+ }
99
+ return lines.join('\n');
100
+ }
101
+ function renderValueMd(value, level) {
102
+ const lines = [];
103
+ const hl = '#'.repeat(Math.min(level, 6));
104
+ if (typeof value === 'string') {
105
+ // Check for Mermaid diagram source
106
+ if (value.trim().startsWith('graph ') || value.trim().startsWith('flowchart ') ||
107
+ value.trim().startsWith('sequenceDiagram') || value.trim().startsWith('classDiagram') ||
108
+ value.trim().startsWith('stateDiagram') || value.trim().startsWith('erDiagram') ||
109
+ value.trim().startsWith('gantt') || value.trim().startsWith('pie') ||
110
+ value.trim().startsWith('journey') || value.trim().startsWith('C4') ||
111
+ value.trim().startsWith('mindmap') || value.trim().startsWith('timeline') ||
112
+ value.trim().startsWith('block-beta') || value.trim().startsWith('architecture-beta')) {
113
+ lines.push('```mermaid', value.trim(), '```');
114
+ }
115
+ else {
116
+ lines.push(value);
117
+ }
118
+ }
119
+ else if (Array.isArray(value)) {
120
+ if (value.length === 0)
121
+ return '';
122
+ if (typeof value[0] === 'string') {
123
+ lines.push(mdList(value.map(str)));
124
+ }
125
+ else if (isPlainObject(value[0])) {
126
+ const keys = Object.keys(value[0]);
127
+ lines.push(mdTable(keys.map(humanize), value.map((item) => keys.map((k) => str(item[k])))));
128
+ }
129
+ }
130
+ else if (isPlainObject(value)) {
131
+ for (const [key, child] of Object.entries(value)) {
132
+ if (child == null)
133
+ continue;
134
+ if (key === 'diagram_source' || key === 'mermaid_source') {
135
+ lines.push('```mermaid', str(child), '```');
136
+ }
137
+ else if (typeof child === 'string') {
138
+ lines.push(`**${humanize(key)}:** ${child}`);
139
+ }
140
+ else if (Array.isArray(child)) {
141
+ if (child.length === 0)
142
+ continue;
143
+ lines.push(`\n${hl}# ${humanize(key)}\n`);
144
+ lines.push(renderValueMd(child, level + 1));
145
+ }
146
+ else if (isPlainObject(child)) {
147
+ lines.push(`\n${hl}# ${humanize(key)}\n`);
148
+ lines.push(renderValueMd(child, level + 1));
149
+ }
150
+ }
151
+ }
152
+ return lines.join('\n');
153
+ }
154
+ function renderSectionMd(key, value) {
155
+ const lines = [];
156
+ lines.push(`## ${humanize(key)}`);
157
+ lines.push('');
158
+ lines.push(renderValueMd(value, 3));
159
+ lines.push('');
160
+ return lines.join('\n');
161
+ }
162
+ export function exportArtifactToMarkdown(data) {
163
+ const lines = [];
164
+ const meta = data?.metadata ?? {};
165
+ const sections = data?.sections ?? {};
166
+ // Title
167
+ const title = str(meta.title) || 'Architecture Artifact';
168
+ const artifactType = str(data?.artifact_type ?? meta?.artifact_type ?? '');
169
+ lines.push(`# ${title}`);
170
+ if (artifactType) {
171
+ lines.push(`\n*${humanize(artifactType)}*`);
172
+ }
173
+ lines.push('');
174
+ // Metadata
175
+ const metaMd = renderMetadataMd(meta);
176
+ if (metaMd) {
177
+ lines.push(metaMd);
178
+ lines.push('\n---\n');
179
+ }
180
+ // Sections in preferred order
181
+ const rendered = new Set();
182
+ for (const key of SECTION_ORDER) {
183
+ if (key in sections) {
184
+ lines.push(renderSectionMd(key, sections[key]));
185
+ rendered.add(key);
186
+ }
187
+ }
188
+ // Unknown sections
189
+ for (const [key, value] of Object.entries(sections)) {
190
+ if (!rendered.has(key)) {
191
+ lines.push(renderSectionMd(key, value));
192
+ rendered.add(key);
193
+ }
194
+ }
195
+ // Top-level keys outside sections
196
+ const TOP_SKIP = new Set(['kind', 'artifact_type', 'metadata', 'sections']);
197
+ for (const [key, value] of Object.entries(data)) {
198
+ if (TOP_SKIP.has(key) || rendered.has(key))
199
+ continue;
200
+ lines.push(renderSectionMd(key, value));
201
+ }
202
+ return lines.join('\n').replace(/\n{3,}/g, '\n\n').trim() + '\n';
203
+ }
204
+ // ─── Rubric Markdown ─────────────────────────────────────────────────────────
205
+ export function exportRubricToMarkdown(data) {
206
+ const lines = [];
207
+ // Title & metadata
208
+ const title = str(data?.title) || 'EaROS Rubric';
209
+ lines.push(`# ${title}`);
210
+ lines.push('');
211
+ const metaFields = [
212
+ ['Rubric ID', data?.rubric_id],
213
+ ['Version', data?.version],
214
+ ['Kind', data?.kind],
215
+ ['Status', data?.status],
216
+ ['Artifact Type', data?.artifact_type],
217
+ ['Design Method', data?.design_method],
218
+ ['Owner', data?.owner],
219
+ ['Effective Date', data?.effective_date],
220
+ ];
221
+ if (data?.inherits?.length)
222
+ metaFields.push(['Inherits', data.inherits.join(', ')]);
223
+ const validMeta = metaFields.filter(([, v]) => v != null && v !== '');
224
+ if (validMeta.length) {
225
+ lines.push(mdTable(['Field', 'Value'], validMeta.map(([k, v]) => [k, str(v)])));
226
+ lines.push('\n---\n');
227
+ }
228
+ // Dimensions & criteria
229
+ const dimensions = data?.dimensions ?? [];
230
+ for (const dim of dimensions) {
231
+ const weight = dim.weight != null ? ` (weight: ${dim.weight})` : '';
232
+ lines.push(`## ${str(dim.name)}${weight}`);
233
+ lines.push('');
234
+ if (dim.description)
235
+ lines.push(`*${str(dim.description)}*\n`);
236
+ const criteria = dim.criteria ?? [];
237
+ for (const c of criteria) {
238
+ lines.push(`### ${str(c.id)}: ${str(c.question)}`);
239
+ lines.push('');
240
+ if (c.description)
241
+ lines.push(str(c.description) + '\n');
242
+ // Gate
243
+ if (c.gate && typeof c.gate === 'object' && c.gate.enabled) {
244
+ lines.push(`**Gate:** ${c.gate.severity ?? 'unknown'}${c.gate.failure_effect ? ` — ${c.gate.failure_effect}` : ''}`);
245
+ }
246
+ else {
247
+ lines.push('**Gate:** None');
248
+ }
249
+ lines.push('');
250
+ // Required evidence
251
+ if (c.required_evidence?.length) {
252
+ lines.push('**Required Evidence:**\n');
253
+ lines.push(mdList(c.required_evidence.map(str)));
254
+ lines.push('');
255
+ }
256
+ // Scoring guide
257
+ if (c.scoring_guide) {
258
+ lines.push('**Scoring Guide:**\n');
259
+ const sgRows = Object.entries(c.scoring_guide).map(([level, desc]) => [level, str(desc)]);
260
+ lines.push(mdTable(['Level', 'Description'], sgRows));
261
+ lines.push('');
262
+ }
263
+ // Anti-patterns
264
+ if (c.anti_patterns?.length) {
265
+ lines.push('**Anti-patterns:**\n');
266
+ lines.push(mdList(c.anti_patterns.map(str)));
267
+ lines.push('');
268
+ }
269
+ // Examples
270
+ if (c.examples) {
271
+ if (c.examples.good?.length) {
272
+ lines.push('**Good Examples:**\n');
273
+ lines.push(mdList(c.examples.good.map(str)));
274
+ lines.push('');
275
+ }
276
+ if (c.examples.bad?.length) {
277
+ lines.push('**Bad Examples:**\n');
278
+ lines.push(mdList(c.examples.bad.map(str)));
279
+ lines.push('');
280
+ }
281
+ }
282
+ // Decision tree
283
+ if (c.decision_tree) {
284
+ lines.push('**Decision Tree:**\n');
285
+ lines.push(`> ${str(c.decision_tree).replace(/\n/g, '\n> ')}`);
286
+ lines.push('');
287
+ }
288
+ // Remediation hints
289
+ if (c.remediation_hints?.length) {
290
+ lines.push('**Remediation Hints:**\n');
291
+ lines.push(mdList(c.remediation_hints.map(str)));
292
+ lines.push('');
293
+ }
294
+ lines.push('---\n');
295
+ }
296
+ }
297
+ // Scoring section
298
+ if (data?.scoring) {
299
+ lines.push('## Scoring Model\n');
300
+ if (data.scoring.scale)
301
+ lines.push(`**Scale:** ${str(data.scoring.scale)}`);
302
+ if (data.scoring.method)
303
+ lines.push(`**Method:** ${str(data.scoring.method)}`);
304
+ if (data.scoring.thresholds) {
305
+ lines.push('\n**Thresholds:**\n');
306
+ for (const [k, v] of Object.entries(data.scoring.thresholds)) {
307
+ lines.push(`- **${humanize(k)}:** ${str(v)}`);
308
+ }
309
+ }
310
+ lines.push('');
311
+ }
312
+ // Outputs section
313
+ if (data?.outputs) {
314
+ lines.push('## Outputs\n');
315
+ for (const [k, v] of Object.entries(data.outputs)) {
316
+ lines.push(`- **${humanize(k)}:** ${str(v)}`);
317
+ }
318
+ lines.push('');
319
+ }
320
+ return lines.join('\n').replace(/\n{3,}/g, '\n\n').trim() + '\n';
321
+ }
322
+ function scoreEmoji(score) {
323
+ if (score === null || score === 'N/A')
324
+ return '';
325
+ if (score >= 3)
326
+ return '🟢';
327
+ if (score >= 2)
328
+ return '🟡';
329
+ if (score >= 1)
330
+ return '🟠';
331
+ return '🔴';
332
+ }
333
+ function statusLabel(status) {
334
+ const map = {
335
+ pass: 'Pass',
336
+ conditional_pass: 'Conditional Pass',
337
+ rework_required: 'Rework Required',
338
+ reject: 'Reject',
339
+ not_reviewable: 'Not Reviewable',
340
+ incomplete: 'Incomplete',
341
+ };
342
+ return map[status] ?? humanize(status);
343
+ }
344
+ export function exportEvaluationToMarkdown(meta, primaryRubricId, dimensions, results) {
345
+ const lines = [];
346
+ // Compute summary inline (same logic as computeSummary in AssessmentSummary)
347
+ const dimSummaries = dimensions.map((dim) => {
348
+ const scored = dim.criteria.filter((c) => {
349
+ const r = results[c.id];
350
+ return r && r.score !== null && r.score !== 'N/A';
351
+ });
352
+ const sum = scored.reduce((acc, c) => acc + results[c.id].score, 0);
353
+ const avg = scored.length > 0 ? sum / scored.length : null;
354
+ return { id: dim.id, name: dim.name, weight: dim.weight ?? 1.0, avgScore: avg };
355
+ });
356
+ const gateFailures = [];
357
+ for (const dim of dimensions) {
358
+ for (const c of dim.criteria) {
359
+ if (!c.gate || typeof c.gate !== 'object' || !c.gate.enabled)
360
+ continue;
361
+ const sev = c.gate.severity;
362
+ if (!sev || sev === 'none')
363
+ continue;
364
+ const r = results[c.id];
365
+ if (!r || r.score === null || r.score === 'N/A')
366
+ continue;
367
+ if (r.score < 2) {
368
+ gateFailures.push({ id: c.id, question: c.question, severity: sev, score: r.score, failure_effect: c.gate.failure_effect ?? '' });
369
+ }
370
+ }
371
+ }
372
+ const criticalFailures = gateFailures.filter((g) => g.severity === 'critical');
373
+ const majorFailures = gateFailures.filter((g) => g.severity === 'major');
374
+ const scoredDims = dimSummaries.filter((d) => d.avgScore !== null);
375
+ const weightedSum = scoredDims.reduce((acc, d) => acc + d.avgScore * d.weight, 0);
376
+ const totalWeight = scoredDims.reduce((acc, d) => acc + d.weight, 0);
377
+ const overallScore = scoredDims.length > 0 ? weightedSum / totalWeight : null;
378
+ const totalCriteria = dimensions.reduce((acc, d) => acc + d.criteria.length, 0);
379
+ const scoredCriteria = dimensions.reduce((acc, d) => acc + d.criteria.filter((c) => results[c.id]?.score !== null).length, 0);
380
+ let status = 'incomplete';
381
+ if (overallScore !== null) {
382
+ const noLowDim = dimSummaries.every((d) => d.avgScore === null || d.avgScore >= 2.0);
383
+ if (criticalFailures.length > 0) {
384
+ const hasNotReviewable = criticalFailures.some((g) => {
385
+ const effect = g.failure_effect.toLowerCase();
386
+ return effect.includes('not_reviewable') || effect.includes('not reviewable');
387
+ });
388
+ status = hasNotReviewable ? 'not_reviewable' : 'reject';
389
+ }
390
+ else if (overallScore >= 3.2 && noLowDim && majorFailures.length === 0) {
391
+ status = 'pass';
392
+ }
393
+ else if (overallScore >= 2.4 || majorFailures.length > 0) {
394
+ status = 'conditional_pass';
395
+ }
396
+ else {
397
+ status = 'rework_required';
398
+ }
399
+ }
400
+ // Title
401
+ lines.push('# EaROS Architecture Assessment Report');
402
+ lines.push('');
403
+ if (meta.title)
404
+ lines.push(`**Artifact:** ${meta.title}`);
405
+ if (meta.version)
406
+ lines.push(`**Artifact Version:** ${meta.version}`);
407
+ lines.push(`**Rubric:** ${primaryRubricId}`);
408
+ lines.push(`**Evaluation Date:** ${meta.date || new Date().toISOString().slice(0, 10)}`);
409
+ if (meta.author)
410
+ lines.push(`**Evaluator:** ${meta.author}`);
411
+ lines.push('');
412
+ lines.push('---\n');
413
+ // Executive Summary
414
+ lines.push('## Executive Summary\n');
415
+ lines.push(mdTable(['', ''], [
416
+ ['**Overall Status**', `**${statusLabel(status).toUpperCase()}**`],
417
+ ['**Overall Score**', overallScore !== null ? `**${overallScore.toFixed(2)} / 4.0**` : 'N/A'],
418
+ ['**Pass Threshold**', '3.2 / 4.0'],
419
+ ['**Gate Failures**', gateFailures.length > 0 ? `${gateFailures.length} (${criticalFailures.length} critical)` : 'None'],
420
+ ['**Criteria Scored**', `${scoredCriteria} of ${totalCriteria}`],
421
+ ]));
422
+ lines.push('\n---\n');
423
+ // Traffic-Light Dashboard
424
+ lines.push('## Traffic-Light Dashboard\n');
425
+ const dashRows = [];
426
+ for (const dim of dimensions) {
427
+ for (const c of dim.criteria) {
428
+ const r = results[c.id];
429
+ const score = r?.score;
430
+ const scoreStr = score !== null && score !== undefined ? `${score}` : '-';
431
+ const gateLabel = c.gate && typeof c.gate === 'object' && c.gate.enabled
432
+ ? ` ⚠️ ${(c.gate.severity ?? '').toUpperCase()} GATE` : '';
433
+ dashRows.push([
434
+ str(c.id) + gateLabel,
435
+ str(c.question),
436
+ scoreStr === 'N/A' ? 'N/A' : `${scoreStr} / 4`,
437
+ score !== null && score !== 'N/A' ? scoreEmoji(score) : '',
438
+ ]);
439
+ }
440
+ }
441
+ lines.push(mdTable(['Criterion', 'Name', 'Score', 'Status'], dashRows));
442
+ lines.push('\n**Legend:** 🟢 Score ≥ 3 · 🟡 Score 2–2.9 · 🟠 Score 1–1.9 · 🔴 Score 0 or gate failure\n');
443
+ lines.push('---\n');
444
+ // Dimension Summary
445
+ lines.push('## Dimension Summary\n');
446
+ const dimRows = dimSummaries.map((d) => [
447
+ d.id,
448
+ d.name,
449
+ d.weight.toFixed(1),
450
+ d.avgScore !== null ? d.avgScore.toFixed(1) : '-',
451
+ d.avgScore !== null ? (d.avgScore * d.weight).toFixed(1) : '-',
452
+ ]);
453
+ lines.push(mdTable(['Dimension', 'Name', 'Weight', 'Score', 'Weighted'], dimRows));
454
+ if (overallScore !== null) {
455
+ lines.push(`\n**Overall weighted score: ${overallScore.toFixed(2)} / 4.0**`);
456
+ }
457
+ lines.push('\n---\n');
458
+ // Gate Failures
459
+ if (gateFailures.length > 0) {
460
+ lines.push('## Gate Failures\n');
461
+ lines.push(mdTable(['Criterion', 'Question', 'Severity', 'Score', 'Effect'], gateFailures.map((g) => [g.id, g.question, g.severity, String(g.score), g.failure_effect || '\u2014'])));
462
+ lines.push('\n---\n');
463
+ }
464
+ // Per-criterion Evidence Details
465
+ const hasEvidence = dimensions.some((d) => d.criteria.some((c) => results[c.id]?.evidence));
466
+ if (hasEvidence) {
467
+ lines.push('## Criterion Details\n');
468
+ for (const dim of dimensions) {
469
+ for (const c of dim.criteria) {
470
+ const r = results[c.id];
471
+ if (!r || r.score === null)
472
+ continue;
473
+ lines.push(`### ${c.id}: ${c.question}\n`);
474
+ lines.push(`- **Score:** ${r.score}`);
475
+ if (r.confidence)
476
+ lines.push(`- **Confidence:** ${r.confidence}`);
477
+ if (r.evidence_class)
478
+ lines.push(`- **Evidence Class:** ${r.evidence_class}`);
479
+ if (r.evidence)
480
+ lines.push(`- **Evidence:** ${r.evidence}`);
481
+ lines.push('');
482
+ }
483
+ }
484
+ }
485
+ return lines.join('\n').replace(/\n{3,}/g, '\n\n').trim() + '\n';
486
+ }
@@ -1 +0,0 @@
1
- import{aq as o,ar as n}from"./index-DMt1cpG6.js";const t=(r,a)=>o.lang.round(n.parse(r)[a]);export{t as c};
@@ -1 +0,0 @@
1
- import{s as a,c as s,a as e,C as t}from"./chunk-WL4C6EOR-D9yxAHyd.js";import{_ as i}from"./index-DMt1cpG6.js";import"./chunk-FMBD7UC4-DoOEFFQC.js";import"./chunk-JSJVCQXG-BerphV2K.js";import"./chunk-55IACEB6-Dxqrf5oZ.js";import"./chunk-KX2RTZJC-CxUAqT05.js";var u={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{u as diagram};
@@ -1 +0,0 @@
1
- import{s as a,c as s,a as e,C as t}from"./chunk-WL4C6EOR-D9yxAHyd.js";import{_ as i}from"./index-DMt1cpG6.js";import"./chunk-FMBD7UC4-DoOEFFQC.js";import"./chunk-JSJVCQXG-BerphV2K.js";import"./chunk-55IACEB6-Dxqrf5oZ.js";import"./chunk-KX2RTZJC-CxUAqT05.js";var u={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{u as diagram};
@@ -1 +0,0 @@
1
- import{b as r}from"./_baseUniq-HuZouVIz.js";var e=4;function a(o){return r(o,e)}export{a as c};
@@ -1 +0,0 @@
1
- import{s as t,b as r,a,S as s}from"./chunk-NQ4KR5QH-fCqZgFkU.js";import{_ as i}from"./index-DMt1cpG6.js";import"./chunk-55IACEB6-Dxqrf5oZ.js";import"./chunk-KX2RTZJC-CxUAqT05.js";var l={parser:a,get db(){return new s(2)},renderer:r,styles:t,init:i(e=>{e.state||(e.state={}),e.state.arrowMarkerAbsolute=e.arrowMarkerAbsolute},"init")};export{l as diagram};