@planu/cli 0.55.0 → 0.57.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 (190) hide show
  1. package/dist/config/license-plans.json +2 -0
  2. package/dist/engine/doc-generator/executive-summary/executive-summary-generator.d.ts +7 -1
  3. package/dist/engine/doc-generator/executive-summary/executive-summary-generator.d.ts.map +1 -1
  4. package/dist/engine/doc-generator/executive-summary/executive-summary-generator.js +16 -3
  5. package/dist/engine/doc-generator/executive-summary/executive-summary-generator.js.map +1 -1
  6. package/dist/engine/doc-generator/executive-summary/html-template.d.ts +5 -2
  7. package/dist/engine/doc-generator/executive-summary/html-template.d.ts.map +1 -1
  8. package/dist/engine/doc-generator/executive-summary/html-template.js +7 -3
  9. package/dist/engine/doc-generator/executive-summary/html-template.js.map +1 -1
  10. package/dist/engine/doc-generator/per-spec-report/html-wrapper.d.ts +5 -3
  11. package/dist/engine/doc-generator/per-spec-report/html-wrapper.d.ts.map +1 -1
  12. package/dist/engine/doc-generator/per-spec-report/html-wrapper.js +27 -6
  13. package/dist/engine/doc-generator/per-spec-report/html-wrapper.js.map +1 -1
  14. package/dist/engine/doc-generator/portal/analytics-page.d.ts +8 -0
  15. package/dist/engine/doc-generator/portal/analytics-page.d.ts.map +1 -0
  16. package/dist/engine/doc-generator/portal/analytics-page.js +265 -0
  17. package/dist/engine/doc-generator/portal/analytics-page.js.map +1 -0
  18. package/dist/engine/doc-generator/portal/architecture-page.d.ts +6 -0
  19. package/dist/engine/doc-generator/portal/architecture-page.d.ts.map +1 -0
  20. package/dist/engine/doc-generator/portal/architecture-page.js +250 -0
  21. package/dist/engine/doc-generator/portal/architecture-page.js.map +1 -0
  22. package/dist/engine/doc-generator/portal/changelog-page.d.ts +6 -0
  23. package/dist/engine/doc-generator/portal/changelog-page.d.ts.map +1 -0
  24. package/dist/engine/doc-generator/portal/changelog-page.js +204 -0
  25. package/dist/engine/doc-generator/portal/changelog-page.js.map +1 -0
  26. package/dist/engine/doc-generator/portal/data-aggregators/accuracy-aggregator.d.ts +11 -0
  27. package/dist/engine/doc-generator/portal/data-aggregators/accuracy-aggregator.d.ts.map +1 -0
  28. package/dist/engine/doc-generator/portal/data-aggregators/accuracy-aggregator.js +24 -0
  29. package/dist/engine/doc-generator/portal/data-aggregators/accuracy-aggregator.js.map +1 -0
  30. package/dist/engine/doc-generator/portal/data-aggregators/bottleneck-detector.d.ts +9 -0
  31. package/dist/engine/doc-generator/portal/data-aggregators/bottleneck-detector.d.ts.map +1 -0
  32. package/dist/engine/doc-generator/portal/data-aggregators/bottleneck-detector.js +31 -0
  33. package/dist/engine/doc-generator/portal/data-aggregators/bottleneck-detector.js.map +1 -0
  34. package/dist/engine/doc-generator/portal/data-aggregators/burndown-aggregator.d.ts +10 -0
  35. package/dist/engine/doc-generator/portal/data-aggregators/burndown-aggregator.d.ts.map +1 -0
  36. package/dist/engine/doc-generator/portal/data-aggregators/burndown-aggregator.js +77 -0
  37. package/dist/engine/doc-generator/portal/data-aggregators/burndown-aggregator.js.map +1 -0
  38. package/dist/engine/doc-generator/portal/data-aggregators/velocity-aggregator.d.ts +9 -0
  39. package/dist/engine/doc-generator/portal/data-aggregators/velocity-aggregator.d.ts.map +1 -0
  40. package/dist/engine/doc-generator/portal/data-aggregators/velocity-aggregator.js +31 -0
  41. package/dist/engine/doc-generator/portal/data-aggregators/velocity-aggregator.js.map +1 -0
  42. package/dist/engine/doc-generator/portal/decision-page.d.ts +6 -0
  43. package/dist/engine/doc-generator/portal/decision-page.d.ts.map +1 -0
  44. package/dist/engine/doc-generator/portal/decision-page.js +169 -0
  45. package/dist/engine/doc-generator/portal/decision-page.js.map +1 -0
  46. package/dist/engine/doc-generator/portal/decision-timeline-builder.d.ts +8 -0
  47. package/dist/engine/doc-generator/portal/decision-timeline-builder.d.ts.map +1 -0
  48. package/dist/engine/doc-generator/portal/decision-timeline-builder.js +131 -0
  49. package/dist/engine/doc-generator/portal/decision-timeline-builder.js.map +1 -0
  50. package/dist/engine/doc-generator/portal/index.d.ts +19 -0
  51. package/dist/engine/doc-generator/portal/index.d.ts.map +1 -0
  52. package/dist/engine/doc-generator/portal/index.js +21 -0
  53. package/dist/engine/doc-generator/portal/index.js.map +1 -0
  54. package/dist/engine/doc-generator/portal/kanban-view-builder.d.ts +8 -0
  55. package/dist/engine/doc-generator/portal/kanban-view-builder.d.ts.map +1 -0
  56. package/dist/engine/doc-generator/portal/kanban-view-builder.js +140 -0
  57. package/dist/engine/doc-generator/portal/kanban-view-builder.js.map +1 -0
  58. package/dist/engine/doc-generator/portal/portal-breadcrumbs.d.ts +27 -0
  59. package/dist/engine/doc-generator/portal/portal-breadcrumbs.d.ts.map +1 -0
  60. package/dist/engine/doc-generator/portal/portal-breadcrumbs.js +139 -0
  61. package/dist/engine/doc-generator/portal/portal-breadcrumbs.js.map +1 -0
  62. package/dist/engine/doc-generator/portal/portal-landing-cards.d.ts +8 -0
  63. package/dist/engine/doc-generator/portal/portal-landing-cards.d.ts.map +1 -0
  64. package/dist/engine/doc-generator/portal/portal-landing-cards.js +177 -0
  65. package/dist/engine/doc-generator/portal/portal-landing-cards.js.map +1 -0
  66. package/dist/engine/doc-generator/portal/portal-navbar.d.ts +15 -0
  67. package/dist/engine/doc-generator/portal/portal-navbar.d.ts.map +1 -0
  68. package/dist/engine/doc-generator/portal/portal-navbar.js +143 -0
  69. package/dist/engine/doc-generator/portal/portal-navbar.js.map +1 -0
  70. package/dist/engine/doc-generator/portal/portal-page-detector.d.ts +22 -0
  71. package/dist/engine/doc-generator/portal/portal-page-detector.d.ts.map +1 -0
  72. package/dist/engine/doc-generator/portal/portal-page-detector.js +58 -0
  73. package/dist/engine/doc-generator/portal/portal-page-detector.js.map +1 -0
  74. package/dist/engine/doc-generator/portal/portal-theme.d.ts +7 -0
  75. package/dist/engine/doc-generator/portal/portal-theme.d.ts.map +1 -0
  76. package/dist/engine/doc-generator/portal/portal-theme.js +53 -0
  77. package/dist/engine/doc-generator/portal/portal-theme.js.map +1 -0
  78. package/dist/engine/doc-generator/portal/risk-gauge-svg.d.ts +5 -0
  79. package/dist/engine/doc-generator/portal/risk-gauge-svg.d.ts.map +1 -0
  80. package/dist/engine/doc-generator/portal/risk-gauge-svg.js +80 -0
  81. package/dist/engine/doc-generator/portal/risk-gauge-svg.js.map +1 -0
  82. package/dist/engine/doc-generator/portal/risk-matrix-svg.d.ts +11 -0
  83. package/dist/engine/doc-generator/portal/risk-matrix-svg.d.ts.map +1 -0
  84. package/dist/engine/doc-generator/portal/risk-matrix-svg.js +181 -0
  85. package/dist/engine/doc-generator/portal/risk-matrix-svg.js.map +1 -0
  86. package/dist/engine/doc-generator/portal/risk-page.d.ts +7 -0
  87. package/dist/engine/doc-generator/portal/risk-page.d.ts.map +1 -0
  88. package/dist/engine/doc-generator/portal/risk-page.js +219 -0
  89. package/dist/engine/doc-generator/portal/risk-page.js.map +1 -0
  90. package/dist/engine/doc-generator/portal/roadmap-page.d.ts +7 -0
  91. package/dist/engine/doc-generator/portal/roadmap-page.d.ts.map +1 -0
  92. package/dist/engine/doc-generator/portal/roadmap-page.js +204 -0
  93. package/dist/engine/doc-generator/portal/roadmap-page.js.map +1 -0
  94. package/dist/engine/doc-generator/portal/svg-charts/bar-chart.d.ts +4 -0
  95. package/dist/engine/doc-generator/portal/svg-charts/bar-chart.d.ts.map +1 -0
  96. package/dist/engine/doc-generator/portal/svg-charts/bar-chart.js +50 -0
  97. package/dist/engine/doc-generator/portal/svg-charts/bar-chart.js.map +1 -0
  98. package/dist/engine/doc-generator/portal/svg-charts/chart-utils.d.ts +16 -0
  99. package/dist/engine/doc-generator/portal/svg-charts/chart-utils.d.ts.map +1 -0
  100. package/dist/engine/doc-generator/portal/svg-charts/chart-utils.js +45 -0
  101. package/dist/engine/doc-generator/portal/svg-charts/chart-utils.js.map +1 -0
  102. package/dist/engine/doc-generator/portal/svg-charts/line-chart.d.ts +16 -0
  103. package/dist/engine/doc-generator/portal/svg-charts/line-chart.d.ts.map +1 -0
  104. package/dist/engine/doc-generator/portal/svg-charts/line-chart.js +159 -0
  105. package/dist/engine/doc-generator/portal/svg-charts/line-chart.js.map +1 -0
  106. package/dist/engine/doc-generator/portal/svg-charts/pie-chart.d.ts +7 -0
  107. package/dist/engine/doc-generator/portal/svg-charts/pie-chart.d.ts.map +1 -0
  108. package/dist/engine/doc-generator/portal/svg-charts/pie-chart.js +52 -0
  109. package/dist/engine/doc-generator/portal/svg-charts/pie-chart.js.map +1 -0
  110. package/dist/engine/doc-generator/proposal/proposal-gantt-builder.d.ts +8 -0
  111. package/dist/engine/doc-generator/proposal/proposal-gantt-builder.d.ts.map +1 -0
  112. package/dist/engine/doc-generator/proposal/proposal-gantt-builder.js +126 -0
  113. package/dist/engine/doc-generator/proposal/proposal-gantt-builder.js.map +1 -0
  114. package/dist/engine/doc-generator/proposal/proposal-generator.d.ts +10 -0
  115. package/dist/engine/doc-generator/proposal/proposal-generator.d.ts.map +1 -0
  116. package/dist/engine/doc-generator/proposal/proposal-generator.js +93 -0
  117. package/dist/engine/doc-generator/proposal/proposal-generator.js.map +1 -0
  118. package/dist/engine/doc-generator/proposal/proposal-html-wrapper.d.ts +7 -0
  119. package/dist/engine/doc-generator/proposal/proposal-html-wrapper.d.ts.map +1 -0
  120. package/dist/engine/doc-generator/proposal/proposal-html-wrapper.js +31 -0
  121. package/dist/engine/doc-generator/proposal/proposal-html-wrapper.js.map +1 -0
  122. package/dist/engine/doc-generator/proposal/proposal-i18n.d.ts +12 -0
  123. package/dist/engine/doc-generator/proposal/proposal-i18n.d.ts.map +1 -0
  124. package/dist/engine/doc-generator/proposal/proposal-i18n.js +230 -0
  125. package/dist/engine/doc-generator/proposal/proposal-i18n.js.map +1 -0
  126. package/dist/engine/doc-generator/proposal/proposal-kpi-builder.d.ts +8 -0
  127. package/dist/engine/doc-generator/proposal/proposal-kpi-builder.d.ts.map +1 -0
  128. package/dist/engine/doc-generator/proposal/proposal-kpi-builder.js +32 -0
  129. package/dist/engine/doc-generator/proposal/proposal-kpi-builder.js.map +1 -0
  130. package/dist/engine/doc-generator/proposal/proposal-section-builders-advanced.d.ts +14 -0
  131. package/dist/engine/doc-generator/proposal/proposal-section-builders-advanced.d.ts.map +1 -0
  132. package/dist/engine/doc-generator/proposal/proposal-section-builders-advanced.js +248 -0
  133. package/dist/engine/doc-generator/proposal/proposal-section-builders-advanced.js.map +1 -0
  134. package/dist/engine/doc-generator/proposal/proposal-section-builders.d.ts +13 -0
  135. package/dist/engine/doc-generator/proposal/proposal-section-builders.d.ts.map +1 -0
  136. package/dist/engine/doc-generator/proposal/proposal-section-builders.js +423 -0
  137. package/dist/engine/doc-generator/proposal/proposal-section-builders.js.map +1 -0
  138. package/dist/engine/doc-generator/proposal/proposal-themes.d.ts +4 -0
  139. package/dist/engine/doc-generator/proposal/proposal-themes.d.ts.map +1 -0
  140. package/dist/engine/doc-generator/proposal/proposal-themes.js +194 -0
  141. package/dist/engine/doc-generator/proposal/proposal-themes.js.map +1 -0
  142. package/dist/engine/pdf/browser-finder.d.ts +5 -0
  143. package/dist/engine/pdf/browser-finder.d.ts.map +1 -0
  144. package/dist/engine/pdf/browser-finder.js +119 -0
  145. package/dist/engine/pdf/browser-finder.js.map +1 -0
  146. package/dist/engine/pdf/html-to-pdf.d.ts +3 -0
  147. package/dist/engine/pdf/html-to-pdf.d.ts.map +1 -0
  148. package/dist/engine/pdf/html-to-pdf.js +114 -0
  149. package/dist/engine/pdf/html-to-pdf.js.map +1 -0
  150. package/dist/engine/pdf/index.d.ts +6 -0
  151. package/dist/engine/pdf/index.d.ts.map +1 -0
  152. package/dist/engine/pdf/index.js +4 -0
  153. package/dist/engine/pdf/index.js.map +1 -0
  154. package/dist/engine/pdf/pdf-options.d.ts +6 -0
  155. package/dist/engine/pdf/pdf-options.d.ts.map +1 -0
  156. package/dist/engine/pdf/pdf-options.js +34 -0
  157. package/dist/engine/pdf/pdf-options.js.map +1 -0
  158. package/dist/engine/spec-summary-html.d.ts.map +1 -1
  159. package/dist/engine/spec-summary-html.js +17 -5
  160. package/dist/engine/spec-summary-html.js.map +1 -1
  161. package/dist/index.js +4 -0
  162. package/dist/index.js.map +1 -1
  163. package/dist/tools/export-pdf.d.ts +3 -0
  164. package/dist/tools/export-pdf.d.ts.map +1 -0
  165. package/dist/tools/export-pdf.js +82 -0
  166. package/dist/tools/export-pdf.js.map +1 -0
  167. package/dist/tools/generate-proposal.d.ts +3 -0
  168. package/dist/tools/generate-proposal.d.ts.map +1 -0
  169. package/dist/tools/generate-proposal.js +166 -0
  170. package/dist/tools/generate-proposal.js.map +1 -0
  171. package/dist/types/docs.d.ts +41 -0
  172. package/dist/types/docs.d.ts.map +1 -1
  173. package/dist/types/index.d.ts +1 -0
  174. package/dist/types/index.d.ts.map +1 -1
  175. package/dist/types/index.js +1 -0
  176. package/dist/types/index.js.map +1 -1
  177. package/dist/types/pdf.d.ts +42 -0
  178. package/dist/types/pdf.d.ts.map +1 -0
  179. package/dist/types/pdf.js +3 -0
  180. package/dist/types/pdf.js.map +1 -0
  181. package/dist/types/portal.d.ts +128 -0
  182. package/dist/types/portal.d.ts.map +1 -0
  183. package/dist/types/portal.js +3 -0
  184. package/dist/types/portal.js.map +1 -0
  185. package/dist/types/proposal.d.ts +57 -0
  186. package/dist/types/proposal.d.ts.map +1 -0
  187. package/dist/types/proposal.js +2 -0
  188. package/dist/types/proposal.js.map +1 -0
  189. package/package.json +1 -1
  190. package/src/config/license-plans.json +2 -0
@@ -133,6 +133,8 @@
133
133
  "validate_team_results",
134
134
  "audit_claude_config",
135
135
  "generate_docs_site",
136
+ "generate_proposal",
137
+ "export_pdf",
136
138
  "export_spec",
137
139
  "analyze_spec_dependencies",
138
140
  "validate_annotations",
@@ -1,7 +1,13 @@
1
1
  import type { ProjectKnowledge, Spec, GeneratedDocument } from '../../../types/index.js';
2
2
  /**
3
3
  * Generate a self-contained HTML executive summary document.
4
+ * Output is placed at planu/executive-summary.html (portal hub location).
4
5
  * Returns a GeneratedDocument with type 'executive-summary'.
6
+ *
7
+ * @param knowledge - Project knowledge data.
8
+ * @param specs - All project specs.
9
+ * @param _language - Language hint (reserved for future i18n).
10
+ * @param availablePages - Portal pages that exist on disk (for navbar display).
5
11
  */
6
- export declare function generateExecutiveSummary(knowledge: ProjectKnowledge, specs: Spec[], _language: string): GeneratedDocument;
12
+ export declare function generateExecutiveSummary(knowledge: ProjectKnowledge, specs: Spec[], _language: string, availablePages?: string[]): GeneratedDocument;
7
13
  //# sourceMappingURL=executive-summary-generator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"executive-summary-generator.d.ts","sourceRoot":"","sources":["../../../../src/engine/doc-generator/executive-summary/executive-summary-generator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,IAAI,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAmBzF;;;GAGG;AACH,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,gBAAgB,EAC3B,KAAK,EAAE,IAAI,EAAE,EACb,SAAS,EAAE,MAAM,GAChB,iBAAiB,CAiCnB"}
1
+ {"version":3,"file":"executive-summary-generator.d.ts","sourceRoot":"","sources":["../../../../src/engine/doc-generator/executive-summary/executive-summary-generator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,IAAI,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAqBzF;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,gBAAgB,EAC3B,KAAK,EAAE,IAAI,EAAE,EACb,SAAS,EAAE,MAAM,EACjB,cAAc,CAAC,EAAE,MAAM,EAAE,GACxB,iBAAiB,CAuCnB"}
@@ -2,17 +2,28 @@ import { buildExecutiveSummaryData } from './data-extractors.js';
2
2
  import { generateArchitectureSvg, generateTimelineSvg, generateRiskDistributionSvg, } from './svg-diagrams.js';
3
3
  import { wrapInHtmlDocument } from './html-template.js';
4
4
  import { buildHeaderSection, buildOverviewSection, buildSpecsTableSection, buildEstimationSection, buildRiskSection, buildArchitectureSection, buildTimelineSection, buildFooterSection, } from './section-builders.js';
5
+ import { buildNavbar } from '../portal/portal-navbar.js';
6
+ import { getPortalThemeCSS } from '../portal/portal-theme.js';
5
7
  /**
6
8
  * Generate a self-contained HTML executive summary document.
9
+ * Output is placed at planu/executive-summary.html (portal hub location).
7
10
  * Returns a GeneratedDocument with type 'executive-summary'.
11
+ *
12
+ * @param knowledge - Project knowledge data.
13
+ * @param specs - All project specs.
14
+ * @param _language - Language hint (reserved for future i18n).
15
+ * @param availablePages - Portal pages that exist on disk (for navbar display).
8
16
  */
9
- export function generateExecutiveSummary(knowledge, specs, _language) {
17
+ export function generateExecutiveSummary(knowledge, specs, _language, availablePages) {
10
18
  const data = buildExecutiveSummaryData(knowledge, specs);
11
19
  const archSvg = generateArchitectureSvg(data.architecture);
12
20
  const timelineSvg = generateTimelineSvg(data.specs);
13
21
  const riskSvg = generateRiskDistributionSvg(data.riskProfile);
14
22
  const hasActuals = data.specs.some((s) => s.actualDevHours !== undefined);
23
+ // Navbar is at root level (planu/), so basePath is empty
24
+ const navbar = buildNavbar('executive-summary', '', availablePages);
15
25
  const body = [
26
+ navbar,
16
27
  buildHeaderSection(data.projectName, data.generatedAt, data.specs.length),
17
28
  buildOverviewSection(data.architecture),
18
29
  buildSpecsTableSection(data.specs),
@@ -23,11 +34,13 @@ export function generateExecutiveSummary(knowledge, specs, _language) {
23
34
  buildFooterSection(),
24
35
  ].join('\n');
25
36
  const title = `Executive Summary — ${data.projectName}`;
26
- const content = wrapInHtmlDocument(title, body);
37
+ // Inject portal theme CSS before the existing document CSS
38
+ const content = wrapInHtmlDocument(title, body, getPortalThemeCSS());
27
39
  return {
28
40
  type: 'executive-summary',
29
41
  title,
30
- path: 'docs/executive-summary.html',
42
+ // Changed from docs/ to planu/ — this is now part of the portal hub
43
+ path: 'planu/executive-summary.html',
31
44
  content,
32
45
  audience: 'stakeholder',
33
46
  sections: [],
@@ -1 +1 @@
1
- {"version":3,"file":"executive-summary-generator.js","sourceRoot":"","sources":["../../../../src/engine/doc-generator/executive-summary/executive-summary-generator.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EACL,uBAAuB,EACvB,mBAAmB,EACnB,2BAA2B,GAC5B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,sBAAsB,EACtB,sBAAsB,EACtB,gBAAgB,EAChB,wBAAwB,EACxB,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAE/B;;;GAGG;AACH,MAAM,UAAU,wBAAwB,CACtC,SAA2B,EAC3B,KAAa,EACb,SAAiB;IAEjB,MAAM,IAAI,GAAG,yBAAyB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAEzD,MAAM,OAAO,GAAG,uBAAuB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC3D,MAAM,WAAW,GAAG,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACpD,MAAM,OAAO,GAAG,2BAA2B,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAE9D,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,KAAK,SAAS,CAAC,CAAC;IAE1E,MAAM,IAAI,GAAG;QACX,kBAAkB,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;QACzE,oBAAoB,CAAC,IAAI,CAAC,YAAY,CAAC;QACvC,sBAAsB,CAAC,IAAI,CAAC,KAAK,CAAC;QAClC,sBAAsB,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC;QACnD,gBAAgB,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC;QAC3C,wBAAwB,CAAC,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC;QACpD,oBAAoB,CAAC,WAAW,CAAC;QACjC,kBAAkB,EAAE;KACrB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEb,MAAM,KAAK,GAAG,uBAAuB,IAAI,CAAC,WAAW,EAAE,CAAC;IACxD,MAAM,OAAO,GAAG,kBAAkB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAEhD,OAAO;QACL,IAAI,EAAE,mBAAmB;QACzB,KAAK;QACL,IAAI,EAAE,6BAA6B;QACnC,OAAO;QACP,QAAQ,EAAE,aAAa;QACvB,QAAQ,EAAE,EAAE;QACZ,QAAQ,EAAE,EAAE;QACZ,YAAY,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC1C,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"executive-summary-generator.js","sourceRoot":"","sources":["../../../../src/engine/doc-generator/executive-summary/executive-summary-generator.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EACL,uBAAuB,EACvB,mBAAmB,EACnB,2BAA2B,GAC5B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,sBAAsB,EACtB,sBAAsB,EACtB,gBAAgB,EAChB,wBAAwB,EACxB,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAE9D;;;;;;;;;GASG;AACH,MAAM,UAAU,wBAAwB,CACtC,SAA2B,EAC3B,KAAa,EACb,SAAiB,EACjB,cAAyB;IAEzB,MAAM,IAAI,GAAG,yBAAyB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAEzD,MAAM,OAAO,GAAG,uBAAuB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC3D,MAAM,WAAW,GAAG,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACpD,MAAM,OAAO,GAAG,2BAA2B,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAE9D,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,KAAK,SAAS,CAAC,CAAC;IAE1E,yDAAyD;IACzD,MAAM,MAAM,GAAG,WAAW,CAAC,mBAAmB,EAAE,EAAE,EAAE,cAAc,CAAC,CAAC;IAEpE,MAAM,IAAI,GAAG;QACX,MAAM;QACN,kBAAkB,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;QACzE,oBAAoB,CAAC,IAAI,CAAC,YAAY,CAAC;QACvC,sBAAsB,CAAC,IAAI,CAAC,KAAK,CAAC;QAClC,sBAAsB,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC;QACnD,gBAAgB,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC;QAC3C,wBAAwB,CAAC,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC;QACpD,oBAAoB,CAAC,WAAW,CAAC;QACjC,kBAAkB,EAAE;KACrB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEb,MAAM,KAAK,GAAG,uBAAuB,IAAI,CAAC,WAAW,EAAE,CAAC;IACxD,2DAA2D;IAC3D,MAAM,OAAO,GAAG,kBAAkB,CAAC,KAAK,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAAC,CAAC;IAErE,OAAO;QACL,IAAI,EAAE,mBAAmB;QACzB,KAAK;QACL,oEAAoE;QACpE,IAAI,EAAE,8BAA8B;QACpC,OAAO;QACP,QAAQ,EAAE,aAAa;QACvB,QAAQ,EAAE,EAAE;QACZ,QAAQ,EAAE,EAAE;QACZ,YAAY,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC1C,CAAC;AACJ,CAAC"}
@@ -1,3 +1,6 @@
1
- /** Wrap body content in a full HTML document with inline CSS. */
2
- export declare function wrapInHtmlDocument(title: string, bodyContent: string): string;
1
+ /**
2
+ * Wrap body content in a full HTML document with inline CSS.
3
+ * Optionally prepend extra CSS (e.g. portal theme variables) before the page CSS.
4
+ */
5
+ export declare function wrapInHtmlDocument(title: string, bodyContent: string, extraCss?: string): string;
3
6
  //# sourceMappingURL=html-template.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"html-template.d.ts","sourceRoot":"","sources":["../../../../src/engine/doc-generator/executive-summary/html-template.ts"],"names":[],"mappings":"AAgCA,iEAAiE;AACjE,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAa7E"}
1
+ {"version":3,"file":"html-template.d.ts","sourceRoot":"","sources":["../../../../src/engine/doc-generator/executive-summary/html-template.ts"],"names":[],"mappings":"AAgCA;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAchG"}
@@ -28,15 +28,19 @@ const CSS = `
28
28
  svg { max-width: 100%; height: auto; }
29
29
  .footer { margin-top: 32px; padding-top: 16px; border-top: 1px solid #e5e7eb; font-size: 0.78em; color: #9ca3af; text-align: center; }
30
30
  `;
31
- /** Wrap body content in a full HTML document with inline CSS. */
32
- export function wrapInHtmlDocument(title, bodyContent) {
31
+ /**
32
+ * Wrap body content in a full HTML document with inline CSS.
33
+ * Optionally prepend extra CSS (e.g. portal theme variables) before the page CSS.
34
+ */
35
+ export function wrapInHtmlDocument(title, bodyContent, extraCss) {
36
+ const styles = extraCss !== undefined ? `${extraCss}${CSS}` : CSS;
33
37
  return `<!DOCTYPE html>
34
38
  <html lang="en">
35
39
  <head>
36
40
  <meta charset="UTF-8"/>
37
41
  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
38
42
  <title>${escapeHtml(title)}</title>
39
- <style>${CSS}</style>
43
+ <style>${styles}</style>
40
44
  </head>
41
45
  <body>
42
46
  ${bodyContent}
@@ -1 +1 @@
1
- {"version":3,"file":"html-template.js","sourceRoot":"","sources":["../../../../src/engine/doc-generator/executive-summary/html-template.ts"],"names":[],"mappings":"AAAA,sEAAsE;AAEtE,MAAM,GAAG,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4BX,CAAC;AAEF,iEAAiE;AACjE,MAAM,UAAU,kBAAkB,CAAC,KAAa,EAAE,WAAmB;IACnE,OAAO;;;;;WAKE,UAAU,CAAC,KAAK,CAAC;WACjB,GAAG;;;EAGZ,WAAW;;QAEL,CAAC;AACT,CAAC;AAED,SAAS,UAAU,CAAC,GAAW;IAC7B,OAAO,GAAG;SACP,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC7B,CAAC"}
1
+ {"version":3,"file":"html-template.js","sourceRoot":"","sources":["../../../../src/engine/doc-generator/executive-summary/html-template.ts"],"names":[],"mappings":"AAAA,sEAAsE;AAEtE,MAAM,GAAG,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4BX,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAa,EAAE,WAAmB,EAAE,QAAiB;IACtF,MAAM,MAAM,GAAG,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,QAAQ,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;IAClE,OAAO;;;;;WAKE,UAAU,CAAC,KAAK,CAAC;WACjB,MAAM;;;EAGf,WAAW;;QAEL,CAAC;AACT,CAAC;AAED,SAAS,UAAU,CAAC,GAAW;IAC7B,OAAO,GAAG;SACP,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC7B,CAAC"}
@@ -1,6 +1,8 @@
1
+ import type { PerSpecHtmlOptions } from '../../../types/docs.js';
2
+ export type { PerSpecHtmlOptions };
1
3
  /**
2
- * Wrap body content in a full HTML document with per-spec report CSS.
3
- * Optionally includes extra scripts (e.g. Mermaid.js CDN).
4
+ * Wrap body content in a full HTML document with per-spec report CSS + portal navbar.
5
+ * basePath is always "../../" because per-spec reports live in planu/specs/SPEC-XXX/.
4
6
  */
5
- export declare function wrapPerSpecHtml(title: string, bodyContent: string, extraScripts?: string): string;
7
+ export declare function wrapPerSpecHtml(title: string, bodyContent: string, extraScriptsOrOptions?: string | PerSpecHtmlOptions): string;
6
8
  //# sourceMappingURL=html-wrapper.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"html-wrapper.d.ts","sourceRoot":"","sources":["../../../../src/engine/doc-generator/per-spec-report/html-wrapper.ts"],"names":[],"mappings":"AA+BA;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAoBjG"}
1
+ {"version":3,"file":"html-wrapper.d.ts","sourceRoot":"","sources":["../../../../src/engine/doc-generator/per-spec-report/html-wrapper.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AA+BjE,YAAY,EAAE,kBAAkB,EAAE,CAAC;AAEnC;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,EACnB,qBAAqB,CAAC,EAAE,MAAM,GAAG,kBAAkB,GAClD,MAAM,CA0CR"}
@@ -1,9 +1,12 @@
1
- // Planu — HTML wrapper for per-spec reports (shared CSS)
1
+ // Planu — HTML wrapper for per-spec reports (shared CSS + portal navbar)
2
+ import { getPortalThemeCSS } from '../portal/portal-theme.js';
3
+ import { buildNavbar } from '../portal/portal-navbar.js';
4
+ import { buildBreadcrumbs } from '../portal/portal-breadcrumbs.js';
2
5
  const CSS = `
3
6
  @page { margin: 2cm; size: A4; }
4
7
  @media print { print-color-adjust: exact; -webkit-print-color-adjust: exact; }
5
8
  * { box-sizing: border-box; margin: 0; padding: 0; }
6
- body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; font-size: 14px; color: #1f2937; max-width: 900px; margin: 0 auto; padding: 24px; background: #fff; }
9
+ body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; font-size: 14px; color: #1f2937; max-width: 960px; margin: 0 auto; padding: 24px; background: #fff; }
7
10
  .header { border-bottom: 3px solid #4F46E5; padding-bottom: 16px; margin-bottom: 24px; }
8
11
  .header h1 { font-size: 1.1em; color: #6b7280; font-weight: 400; margin-bottom: 4px; }
9
12
  .header h2 { font-size: 1.8em; color: #111827; font-weight: 700; }
@@ -28,24 +31,42 @@ const CSS = `
28
31
  .footer { margin-top: 32px; padding-top: 16px; border-top: 1px solid #e5e7eb; font-size: 0.78em; color: #9ca3af; text-align: center; }
29
32
  `;
30
33
  /**
31
- * Wrap body content in a full HTML document with per-spec report CSS.
32
- * Optionally includes extra scripts (e.g. Mermaid.js CDN).
34
+ * Wrap body content in a full HTML document with per-spec report CSS + portal navbar.
35
+ * basePath is always "../../" because per-spec reports live in planu/specs/SPEC-XXX/.
33
36
  */
34
- export function wrapPerSpecHtml(title, bodyContent, extraScripts) {
37
+ export function wrapPerSpecHtml(title, bodyContent, extraScriptsOrOptions) {
38
+ // Backward-compatible: accept plain string (extraScripts) or options object
39
+ let extraScripts;
40
+ let options = {};
41
+ if (typeof extraScriptsOrOptions === 'string') {
42
+ extraScripts = extraScriptsOrOptions;
43
+ }
44
+ else if (extraScriptsOrOptions !== undefined) {
45
+ options = extraScriptsOrOptions;
46
+ extraScripts = options.extraScripts;
47
+ }
35
48
  const escapedTitle = title
36
49
  .replace(/&/g, '&amp;')
37
50
  .replace(/</g, '&lt;')
38
51
  .replace(/>/g, '&gt;')
39
52
  .replace(/"/g, '&quot;');
53
+ // Per-spec reports are always 2 levels deep: planu/specs/SPEC-XXX/report.html
54
+ const basePath = '../../';
55
+ const navbar = buildNavbar(options.activePage ?? 'dashboard', basePath, options.availablePages);
56
+ const breadcrumbsHtml = options.breadcrumbs && options.breadcrumbs.length > 0
57
+ ? buildBreadcrumbs(options.breadcrumbs)
58
+ : '';
40
59
  return `<!DOCTYPE html>
41
60
  <html lang="en">
42
61
  <head>
43
62
  <meta charset="UTF-8"/>
44
63
  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
45
64
  <title>${escapedTitle}</title>
46
- <style>${CSS}</style>
65
+ <style>${getPortalThemeCSS()}${CSS}</style>
47
66
  </head>
48
67
  <body>
68
+ ${navbar}
69
+ ${breadcrumbsHtml}
49
70
  ${bodyContent}
50
71
  ${extraScripts ?? ''}
51
72
  </body>
@@ -1 +1 @@
1
- {"version":3,"file":"html-wrapper.js","sourceRoot":"","sources":["../../../../src/engine/doc-generator/per-spec-report/html-wrapper.ts"],"names":[],"mappings":"AAAA,yDAAyD;AAEzD,MAAM,GAAG,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BX,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,KAAa,EAAE,WAAmB,EAAE,YAAqB;IACvF,MAAM,YAAY,GAAG,KAAK;SACvB,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAE3B,OAAO;;;;;WAKE,YAAY;WACZ,GAAG;;;EAGZ,WAAW;EACX,YAAY,IAAI,EAAE;;QAEZ,CAAC;AACT,CAAC"}
1
+ {"version":3,"file":"html-wrapper.js","sourceRoot":"","sources":["../../../../src/engine/doc-generator/per-spec-report/html-wrapper.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAGnE,MAAM,GAAG,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BX,CAAC;AAIF;;;GAGG;AACH,MAAM,UAAU,eAAe,CAC7B,KAAa,EACb,WAAmB,EACnB,qBAAmD;IAEnD,4EAA4E;IAC5E,IAAI,YAAgC,CAAC;IACrC,IAAI,OAAO,GAAuB,EAAE,CAAC;IAErC,IAAI,OAAO,qBAAqB,KAAK,QAAQ,EAAE,CAAC;QAC9C,YAAY,GAAG,qBAAqB,CAAC;IACvC,CAAC;SAAM,IAAI,qBAAqB,KAAK,SAAS,EAAE,CAAC;QAC/C,OAAO,GAAG,qBAAqB,CAAC;QAChC,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;IACtC,CAAC;IAED,MAAM,YAAY,GAAG,KAAK;SACvB,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAE3B,8EAA8E;IAC9E,MAAM,QAAQ,GAAG,QAAQ,CAAC;IAC1B,MAAM,MAAM,GAAG,WAAW,CAAC,OAAO,CAAC,UAAU,IAAI,WAAW,EAAE,QAAQ,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IAEhG,MAAM,eAAe,GACnB,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC;QACnD,CAAC,CAAC,gBAAgB,CAAC,OAAO,CAAC,WAAW,CAAC;QACvC,CAAC,CAAC,EAAE,CAAC;IAET,OAAO;;;;;WAKE,YAAY;WACZ,iBAAiB,EAAE,GAAG,GAAG;;;EAGlC,MAAM;EACN,eAAe;EACf,WAAW;EACX,YAAY,IAAI,EAAE;;QAEZ,CAAC;AACT,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { Spec } from '../../../types/index.js';
2
+ import type { MetricsHistory } from '../../../types/project/config-metrics.js';
3
+ /**
4
+ * Generate the full analytics.html page for the Planu portal.
5
+ * Returns an HTML string ready to write to disk.
6
+ */
7
+ export declare function generateAnalyticsPage(specs: Spec[], metrics?: MetricsHistory): string;
8
+ //# sourceMappingURL=analytics-page.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analytics-page.d.ts","sourceRoot":"","sources":["../../../../src/engine/doc-generator/portal/analytics-page.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0CAA0C,CAAC;AAa/E;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,MAAM,CAkDrF"}
@@ -0,0 +1,265 @@
1
+ import { getPortalThemeCSS } from './portal-theme.js';
2
+ import { buildNavbar } from './portal-navbar.js';
3
+ import { buildSvgBarChart } from './svg-charts/bar-chart.js';
4
+ import { buildSvgDualLineChart } from './svg-charts/line-chart.js';
5
+ import { buildSvgPieChart } from './svg-charts/pie-chart.js';
6
+ import { CHART_COLORS } from './svg-charts/chart-utils.js';
7
+ import { computeVelocity } from './data-aggregators/velocity-aggregator.js';
8
+ import { computeBurndown } from './data-aggregators/burndown-aggregator.js';
9
+ import { detectBottlenecks } from './data-aggregators/bottleneck-detector.js';
10
+ import { computeAccuracy } from './data-aggregators/accuracy-aggregator.js';
11
+ /**
12
+ * Generate the full analytics.html page for the Planu portal.
13
+ * Returns an HTML string ready to write to disk.
14
+ */
15
+ export function generateAnalyticsPage(specs, metrics) {
16
+ const navbar = buildNavbar('analytics', '', ['analytics', 'dashboard']);
17
+ const kpiHtml = buildKpiSection(specs);
18
+ const burndownHtml = buildBurndownSection(specs);
19
+ const velocityHtml = buildVelocitySection(specs);
20
+ const accuracyHtml = buildAccuracySection(specs, metrics);
21
+ const distributionHtml = buildDistributionSection(specs);
22
+ const bottleneckHtml = buildBottleneckSection(specs);
23
+ return `<!DOCTYPE html>
24
+ <html lang="en">
25
+ <head>
26
+ <meta charset="UTF-8"/>
27
+ <meta name="viewport" content="width=device-width,initial-scale=1"/>
28
+ <title>Analytics — Planu</title>
29
+ <style>
30
+ ${getPortalThemeCSS()}
31
+ ${ANALYTICS_CSS}
32
+ </style>
33
+ </head>
34
+ <body>
35
+ ${navbar}
36
+ <main class="analytics-main">
37
+ <h1 class="analytics-title">📈 Analytics</h1>
38
+ ${kpiHtml}
39
+ <div class="analytics-charts-row">
40
+ <section class="planu-card analytics-section">
41
+ <h2>Burn-down</h2>
42
+ ${burndownHtml}
43
+ </section>
44
+ <section class="planu-card analytics-section">
45
+ <h2>Velocity</h2>
46
+ ${velocityHtml}
47
+ </section>
48
+ </div>
49
+ <section class="planu-card analytics-section">
50
+ <h2>Estimated vs Actual Hours</h2>
51
+ ${accuracyHtml}
52
+ </section>
53
+ <section class="planu-card analytics-section">
54
+ <h2>Distribution</h2>
55
+ ${distributionHtml}
56
+ </section>
57
+ <section class="planu-card analytics-section">
58
+ <h2>Bottlenecks</h2>
59
+ ${bottleneckHtml}
60
+ </section>
61
+ </main>
62
+ </body>
63
+ </html>`;
64
+ }
65
+ // --- Section builders ---
66
+ function buildKpiSection(specs) {
67
+ if (specs.length === 0) {
68
+ return '<p class="analytics-empty">No specs available.</p>';
69
+ }
70
+ const total = specs.length;
71
+ const done = specs.filter((s) => s.status === 'done').length;
72
+ const pct = total > 0 ? Math.round((done / total) * 100) : 0;
73
+ const accuracyRecords = computeAccuracy(specs);
74
+ const avgAccuracy = accuracyRecords.length > 0
75
+ ? Math.round(accuracyRecords.reduce((s, r) => s + r.accuracy, 0) / accuracyRecords.length)
76
+ : 0;
77
+ const totalHours = specs.reduce((s, sp) => s + sp.estimation.devHours, 0);
78
+ const velocity = computeVelocity(specs);
79
+ const avgVelocity = velocity.length > 0
80
+ ? Math.round(velocity.reduce((s, v) => s + v.count, 0) / velocity.length)
81
+ : 0;
82
+ const kpis = [
83
+ { label: 'Total Specs', value: String(total), icon: '📋' },
84
+ { label: 'Done', value: String(done), icon: '✅' },
85
+ { label: 'Completion', value: `${pct}%`, icon: '📊' },
86
+ { label: 'Avg Accuracy', value: `${avgAccuracy}%`, icon: '🎯' },
87
+ { label: 'Total Hours', value: String(totalHours), icon: '⏱️' },
88
+ { label: 'Avg Velocity', value: `${avgVelocity}/mo`, icon: '🚀' },
89
+ ];
90
+ const cards = kpis
91
+ .map((k) => `<div class="kpi-card planu-card">
92
+ <div class="kpi-icon">${k.icon}</div>
93
+ <div class="kpi-value">${escapeHtml(k.value)}</div>
94
+ <div class="kpi-label">${escapeHtml(k.label)}</div>
95
+ </div>`)
96
+ .join('\n');
97
+ return `<div class="kpi-row">${cards}</div>`;
98
+ }
99
+ function buildBurndownSection(specs) {
100
+ const points = computeBurndown(specs);
101
+ if (points.length === 0) {
102
+ return '<p class="analytics-empty">Insufficient data for burndown.</p>';
103
+ }
104
+ const series1 = points.map((p, i) => ({ x: i, y: p.remaining, label: p.date }));
105
+ const series2 = points.map((p, i) => ({ x: i, y: p.ideal }));
106
+ return buildSvgDualLineChart(series1, series2, {
107
+ title: 'Remaining vs Ideal',
108
+ label1: 'Remaining',
109
+ label2: 'Ideal',
110
+ showDots: false,
111
+ });
112
+ }
113
+ function buildVelocitySection(specs) {
114
+ const velocity = computeVelocity(specs);
115
+ if (velocity.length === 0) {
116
+ return '<p class="analytics-empty">No completed specs with dates.</p>';
117
+ }
118
+ const data = velocity.map((v, i) => ({
119
+ label: v.period,
120
+ value: v.count,
121
+ color: CHART_COLORS[i % CHART_COLORS.length],
122
+ }));
123
+ return buildSvgBarChart(data, { title: 'Specs Completed per Month' });
124
+ }
125
+ function buildAccuracySection(specs, _metrics) {
126
+ const records = computeAccuracy(specs);
127
+ if (records.length === 0) {
128
+ return '<p class="analytics-empty">No completed specs with estimation data.</p>';
129
+ }
130
+ const estimated = records.map((r) => ({
131
+ label: r.specId,
132
+ value: r.estimated,
133
+ color: CHART_COLORS[0],
134
+ }));
135
+ const actual = records.map((r) => ({
136
+ label: r.specId,
137
+ value: r.actual,
138
+ color: CHART_COLORS[1],
139
+ }));
140
+ const estSvg = buildSvgBarChart(estimated, { title: 'Estimated Hours' });
141
+ const actSvg = buildSvgBarChart(actual, { title: 'Actual Hours' });
142
+ return `<div class="analytics-charts-row">${estSvg}${actSvg}</div>`;
143
+ }
144
+ function buildDistributionSection(specs) {
145
+ if (specs.length === 0) {
146
+ return '<p class="analytics-empty">No specs to distribute.</p>';
147
+ }
148
+ const byType = countBy(specs, (s) => s.type);
149
+ const byRisk = countBy(specs, (s) => s.risk);
150
+ const byDifficulty = countBy(specs, (s) => String(s.difficulty));
151
+ const typePie = buildSvgPieChart(mapToPieSlices(byType));
152
+ const riskPie = buildSvgPieChart(mapToPieSlices(byRisk));
153
+ const diffPie = buildSvgPieChart(mapToPieSlices(byDifficulty));
154
+ return `<div class="distribution-row">
155
+ <div class="distribution-col">
156
+ <h3>By Type</h3>${typePie}
157
+ </div>
158
+ <div class="distribution-col">
159
+ <h3>By Risk</h3>${riskPie}
160
+ </div>
161
+ <div class="distribution-col">
162
+ <h3>By Difficulty</h3>${diffPie}
163
+ </div>
164
+ </div>`;
165
+ }
166
+ function buildBottleneckSection(specs) {
167
+ const bottlenecks = detectBottlenecks(specs);
168
+ if (bottlenecks.length === 0) {
169
+ return '<p class="analytics-empty">No bottlenecks detected. 🎉</p>';
170
+ }
171
+ const rows = bottlenecks.map((b) => {
172
+ const badgeClass = b.staleDays > 30 ? 'planu-badge-danger' : 'planu-badge-warning';
173
+ return `<tr>
174
+ <td>${escapeHtml(b.specId)}</td>
175
+ <td>${escapeHtml(b.title)}</td>
176
+ <td><span class="planu-badge planu-badge-muted">${escapeHtml(b.status)}</span></td>
177
+ <td><span class="planu-badge ${badgeClass}">${b.staleDays}d</span></td>
178
+ </tr>`;
179
+ });
180
+ return `<table class="bottleneck-table">
181
+ <thead>
182
+ <tr><th>ID</th><th>Title</th><th>Status</th><th>Stale</th></tr>
183
+ </thead>
184
+ <tbody>
185
+ ${rows.join('\n')}
186
+ </tbody>
187
+ </table>`;
188
+ }
189
+ // --- Helpers ---
190
+ function countBy(arr, key) {
191
+ const map = new Map();
192
+ for (const item of arr) {
193
+ const k = key(item);
194
+ map.set(k, (map.get(k) ?? 0) + 1);
195
+ }
196
+ return map;
197
+ }
198
+ function mapToPieSlices(counts) {
199
+ return Array.from(counts.entries()).map(([label, value], i) => ({
200
+ label,
201
+ value,
202
+ color: CHART_COLORS[i % CHART_COLORS.length] ?? '#e94560',
203
+ }));
204
+ }
205
+ function escapeHtml(str) {
206
+ return str
207
+ .replace(/&/g, '&amp;')
208
+ .replace(/</g, '&lt;')
209
+ .replace(/>/g, '&gt;')
210
+ .replace(/"/g, '&quot;');
211
+ }
212
+ const ANALYTICS_CSS = `
213
+ .analytics-main {
214
+ max-width: 1100px;
215
+ margin: 0 auto;
216
+ padding: 0 16px 40px;
217
+ }
218
+ .analytics-title { font-size: 1.5rem; color: var(--planu-primary); margin-bottom: 20px; }
219
+ .analytics-empty { color: #9ca3af; font-style: italic; padding: 12px 0; }
220
+ .analytics-section { margin-bottom: 24px; }
221
+ .analytics-section h2 {
222
+ font-size: 1.05rem;
223
+ color: var(--planu-secondary);
224
+ margin-bottom: 14px;
225
+ border-bottom: 1px solid var(--planu-border);
226
+ padding-bottom: 6px;
227
+ }
228
+ .analytics-charts-row {
229
+ display: grid;
230
+ grid-template-columns: 1fr 1fr;
231
+ gap: 16px;
232
+ margin-bottom: 24px;
233
+ }
234
+ @media (max-width: 700px) { .analytics-charts-row { grid-template-columns: 1fr; } }
235
+ .kpi-row {
236
+ display: grid;
237
+ grid-template-columns: repeat(6, 1fr);
238
+ gap: 12px;
239
+ margin-bottom: 24px;
240
+ }
241
+ @media (max-width: 900px) { .kpi-row { grid-template-columns: repeat(3, 1fr); } }
242
+ @media (max-width: 500px) { .kpi-row { grid-template-columns: repeat(2, 1fr); } }
243
+ .kpi-card { text-align: center; padding: 14px 10px; }
244
+ .kpi-icon { font-size: 1.6rem; margin-bottom: 4px; }
245
+ .kpi-value { font-size: 1.5rem; font-weight: 700; color: var(--planu-primary); }
246
+ .kpi-label { font-size: 0.75rem; color: #6b7280; margin-top: 2px; }
247
+ .distribution-row {
248
+ display: grid;
249
+ grid-template-columns: repeat(3, 1fr);
250
+ gap: 16px;
251
+ }
252
+ @media (max-width: 700px) { .distribution-row { grid-template-columns: 1fr; } }
253
+ .distribution-col h3 { font-size: 0.9rem; color: #4b5563; margin-bottom: 8px; text-align: center; }
254
+ .bottleneck-table { width: 100%; border-collapse: collapse; font-size: 0.85rem; }
255
+ .bottleneck-table th {
256
+ background: #f3f4f6;
257
+ text-align: left;
258
+ padding: 8px 10px;
259
+ font-size: 0.8rem;
260
+ color: #6b7280;
261
+ }
262
+ .bottleneck-table td { padding: 8px 10px; border-bottom: 1px solid #f3f4f6; }
263
+ @media print { .analytics-charts-row { grid-template-columns: 1fr; } }
264
+ `;
265
+ //# sourceMappingURL=analytics-page.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analytics-page.js","sourceRoot":"","sources":["../../../../src/engine/doc-generator/portal/analytics-page.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { ProjectKnowledge } from '../../../types/project/core.js';
2
+ /**
3
+ * Generate the architecture.html portal page.
4
+ */
5
+ export declare function generateArchitecturePage(knowledge: ProjectKnowledge): string;
6
+ //# sourceMappingURL=architecture-page.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"architecture-page.d.ts","sourceRoot":"","sources":["../../../../src/engine/doc-generator/portal/architecture-page.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAc,MAAM,gCAAgC,CAAC;AAuPnF;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,gBAAgB,GAAG,MAAM,CAoC5E"}