@inflexa-ai/harness 0.19.2 → 0.21.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 (139) hide show
  1. package/dist/agents/conversation-agent.d.ts +26 -14
  2. package/dist/agents/conversation-agent.js +12 -23
  3. package/dist/agents/report-session-agent.d.ts +31 -5
  4. package/dist/agents/report-session-agent.js +31 -6
  5. package/dist/app/chat-turn.js +3 -1
  6. package/dist/app/message-assembly.d.ts +15 -1
  7. package/dist/app/message-assembly.js +22 -8
  8. package/dist/app/report-session-runtime.d.ts +21 -4
  9. package/dist/app/report-session-runtime.js +53 -6
  10. package/dist/app/spawn-report-session.d.ts +174 -17
  11. package/dist/app/spawn-report-session.js +233 -21
  12. package/dist/contracts/chat-events.d.ts +7 -2
  13. package/dist/contracts/message.d.ts +10 -0
  14. package/dist/contracts/report-blocks.d.ts +743 -19
  15. package/dist/contracts/report-blocks.js +186 -11
  16. package/dist/contracts/report-reference.d.ts +88 -0
  17. package/dist/contracts/report-reference.js +48 -0
  18. package/dist/index.d.ts +9 -0
  19. package/dist/index.js +20 -0
  20. package/dist/lib/chrome.d.ts +26 -6
  21. package/dist/lib/chrome.js +99 -32
  22. package/dist/lib/eyes.d.ts +57 -0
  23. package/dist/lib/eyes.js +45 -0
  24. package/dist/lib/page-capture.d.ts +14 -0
  25. package/dist/lib/page-capture.js +56 -2
  26. package/dist/literature/sources/pubmed.js +2 -1
  27. package/dist/loop/run-agent.js +58 -23
  28. package/dist/loop/tool-detail.d.ts +19 -2
  29. package/dist/loop/tool-detail.js +35 -2
  30. package/dist/memory/content-to-cortex.d.ts +3 -2
  31. package/dist/memory/content-to-cortex.js +21 -12
  32. package/dist/memory/conversation-display-replay.js +14 -7
  33. package/dist/memory/thread-history.d.ts +60 -3
  34. package/dist/memory/thread-history.js +55 -16
  35. package/dist/memory/thread-store.d.ts +11 -1
  36. package/dist/memory/thread-store.js +12 -2
  37. package/dist/prompts/conversation.d.ts +1 -1
  38. package/dist/prompts/conversation.js +23 -6
  39. package/dist/prompts/report-session.d.ts +1 -1
  40. package/dist/prompts/report-session.js +183 -9
  41. package/dist/report-model/authoring-grammar.d.ts +463 -0
  42. package/dist/report-model/authoring-grammar.js +77 -0
  43. package/dist/report-model/block-walk.d.ts +57 -14
  44. package/dist/report-model/block-walk.js +116 -11
  45. package/dist/report-model/draft-finish.d.ts +22 -4
  46. package/dist/report-model/draft-finish.js +39 -7
  47. package/dist/report-model/draft-operations.d.ts +3 -0
  48. package/dist/report-model/draft-operations.js +19 -5
  49. package/dist/report-model/draft-read.d.ts +8 -5
  50. package/dist/report-model/draft-read.js +21 -5
  51. package/dist/report-model/fixture-resolver.js +15 -4
  52. package/dist/report-model/pin-snapshot.d.ts +24 -6
  53. package/dist/report-model/pin-snapshot.js +204 -6
  54. package/dist/report-model/production-resolver.js +15 -4
  55. package/dist/report-model/reference-resolver.d.ts +50 -1
  56. package/dist/report-model/reference-resolver.js +94 -1
  57. package/dist/report-model/reference-stamp.d.ts +45 -0
  58. package/dist/report-model/reference-stamp.js +173 -0
  59. package/dist/report-model/structural-validation.d.ts +4 -1
  60. package/dist/report-model/structural-validation.js +48 -3
  61. package/dist/report-model/validate.d.ts +1 -1
  62. package/dist/report-model/validate.js +1 -1
  63. package/dist/report-render/asset-lookup.d.ts +19 -0
  64. package/dist/report-render/asset-lookup.js +37 -0
  65. package/dist/report-render/assets.d.ts +45 -1
  66. package/dist/report-render/assets.js +65 -6
  67. package/dist/report-render/chart-presets.d.ts +102 -0
  68. package/dist/report-render/chart-presets.js +205 -0
  69. package/dist/report-render/chart.d.ts +112 -10
  70. package/dist/report-render/chart.js +1164 -41
  71. package/dist/report-render/design.d.ts +99 -0
  72. package/dist/report-render/design.js +289 -107
  73. package/dist/report-render/number-format.d.ts +117 -0
  74. package/dist/report-render/number-format.js +479 -0
  75. package/dist/report-render/page.d.ts +121 -5
  76. package/dist/report-render/page.js +689 -7
  77. package/dist/report-render/references.d.ts +70 -16
  78. package/dist/report-render/references.js +54 -22
  79. package/dist/report-render/render.d.ts +23 -5
  80. package/dist/report-render/render.js +81 -22
  81. package/dist/report-render/table-data.d.ts +92 -0
  82. package/dist/report-render/table-data.js +129 -0
  83. package/dist/report-render/types.d.ts +15 -0
  84. package/dist/report-render/value-bridge.js +6 -2
  85. package/dist/report-render/views/chart-view.d.ts +12 -5
  86. package/dist/report-render/views/chart-view.js +14 -8
  87. package/dist/report-render/views/page-view.d.ts +36 -15
  88. package/dist/report-render/views/page-view.js +45 -23
  89. package/dist/report-render/views/prose.d.ts +12 -2
  90. package/dist/report-render/views/prose.js +29 -7
  91. package/dist/report-render/views/references-view.d.ts +22 -8
  92. package/dist/report-render/views/references-view.js +101 -13
  93. package/dist/report-render/views/values.d.ts +128 -13
  94. package/dist/report-render/views/values.js +199 -18
  95. package/dist/runtime/assemble.d.ts +39 -5
  96. package/dist/runtime/assemble.js +47 -6
  97. package/dist/sandbox/client.d.ts +10 -1
  98. package/dist/sandbox/create-sandbox.d.ts +9 -4
  99. package/dist/sandbox/create-sandbox.js +22 -16
  100. package/dist/sandbox/docker-client.js +10 -7
  101. package/dist/sandbox/k8s-client.js +11 -18
  102. package/dist/sandbox/mount-plan.d.ts +45 -7
  103. package/dist/sandbox/mount-plan.js +43 -5
  104. package/dist/sandbox/types.d.ts +10 -6
  105. package/dist/state/init.js +38 -9
  106. package/dist/state/report-session-state.d.ts +42 -1
  107. package/dist/state/report-session-state.js +70 -2
  108. package/dist/state/report-versions.d.ts +22 -17
  109. package/dist/state/report-versions.js +48 -35
  110. package/dist/state/snapshot-parse.js +16 -1
  111. package/dist/tasks/data-profile.d.ts +7 -4
  112. package/dist/tasks/data-profile.js +9 -9
  113. package/dist/tools/define-tool.d.ts +32 -0
  114. package/dist/tools/define-tool.js +4 -0
  115. package/dist/tools/detail-resolver.d.ts +7 -2
  116. package/dist/tools/detail-resolver.js +7 -2
  117. package/dist/tools/iterate-report.d.ts +1 -1
  118. package/dist/tools/report/preview-snapshot.js +1 -0
  119. package/dist/tools/report-authoring/authoring-tools.d.ts +15 -6
  120. package/dist/tools/report-authoring/authoring-tools.js +99 -18
  121. package/dist/tools/report-session/derive-table.d.ts +162 -0
  122. package/dist/tools/report-session/derive-table.js +459 -0
  123. package/dist/tools/report-session/examine-page.d.ts +48 -18
  124. package/dist/tools/report-session/examine-page.js +204 -24
  125. package/dist/tools/report-session/index.d.ts +2 -0
  126. package/dist/tools/report-session/index.js +2 -0
  127. package/dist/tools/report-session/list-artifacts.d.ts +97 -0
  128. package/dist/tools/report-session/list-artifacts.js +197 -0
  129. package/dist/tools/report-session/preview-report.d.ts +6 -0
  130. package/dist/tools/report-session/preview-report.js +180 -28
  131. package/dist/tools/report-session/record-version.d.ts +22 -10
  132. package/dist/tools/report-session/record-version.js +99 -14
  133. package/dist/tools/start-report-session.d.ts +115 -0
  134. package/dist/tools/start-report-session.js +179 -0
  135. package/dist/workflows/sandbox-step.d.ts +7 -4
  136. package/dist/workflows/sandbox-step.js +10 -12
  137. package/dist/workspace/paths.d.ts +50 -0
  138. package/dist/workspace/paths.js +63 -0
  139. package/package.json +2 -1
@@ -7,10 +7,14 @@
7
7
  * serves. Thus a `figure` here carries a ready `src` string, and the renderer holds no policy about the
8
8
  * image bytes.
9
9
  */
10
+ import type { DataAsset } from "./table-data.js";
10
11
  /**
11
12
  * The value that one block resolves to, as a closed union. A `scalar` gives one number or one string. A
12
13
  * `table` gives the rows and the optional column order. A `figure` gives a ready source string. A
13
14
  * `citation` echoes one external id.
15
+ *
16
+ * A `table` carries `total` when a row bound cut the rows of the artifact. The renderer states the shown
17
+ * count against it. A table with no bound carries none, and the row count answers for it.
14
18
  */
15
19
  export type RenderValue = {
16
20
  type: "scalar";
@@ -19,6 +23,7 @@ export type RenderValue = {
19
23
  type: "table";
20
24
  rows: Array<Record<string, string | number>>;
21
25
  columns?: string[];
26
+ total?: number;
22
27
  } | {
23
28
  type: "figure";
24
29
  src: string;
@@ -37,3 +42,13 @@ export interface RenderProblem {
37
42
  }
38
43
  /** The value map that the renderer takes, keyed by block id. */
39
44
  export type RenderValues = Record<string, RenderValue>;
45
+ /**
46
+ * One rendered page: the HTML string, and each data asset that the page references.
47
+ *
48
+ * The renderer writes no file. Thus it gives the asset bytes back to the caller, and the caller stages
49
+ * them beside the page. A document with no table gives an empty list, and its page references none.
50
+ */
51
+ export interface RenderedPage {
52
+ html: string;
53
+ dataAssets: DataAsset[];
54
+ }
@@ -69,12 +69,16 @@ export function bridgeValues(resolutions, figureSrc) {
69
69
  /**
70
70
  * Map a resolved table onto a render table. The explicit column order carries through when it is present,
71
71
  * and it stays absent otherwise, thus the renderer keeps its first-row order as the default.
72
+ *
73
+ * The pre-bound total carries through the same way. The resolution is the one step that reads the whole
74
+ * artifact, thus the renderer takes that count and never counts again.
72
75
  */
73
76
  function tableValue(value) {
77
+ const total = value.total === undefined ? {} : { total: value.total };
74
78
  if (value.columns !== undefined) {
75
- return { type: "table", rows: value.rows, columns: value.columns };
79
+ return { type: "table", rows: value.rows, columns: value.columns, ...total };
76
80
  }
77
- return { type: "table", rows: value.rows };
81
+ return { type: "table", rows: value.rows, ...total };
78
82
  }
79
83
  /** Make one mismatch that names the block, its kind, the resolved type that it needs, and the type that arrived. */
80
84
  function mismatch(blockId, blockKind, expected, actual) {
@@ -1,14 +1,21 @@
1
1
  /**
2
- * The chart panel markup.
2
+ * The chart card markup.
3
3
  *
4
4
  * The bootstrap in `page.ts` reads the option from the next element sibling of the container. Thus the
5
5
  * `<script type="application/json">` element MUST follow the container div with no element between them.
6
6
  *
7
- * The panel is the window-chrome form: the three dots on the left, the title in the center, and the
8
- * `CORTEX` badge on the right. It is the one component with rounded corners. The chart body carries a fixed
7
+ * The card is the square corner-accent form of the table and the figure, with the mono title line over it. A
8
+ * report is a document, thus the card wears no application-window costume. The chart body carries a fixed
9
9
  * height, because the chart runtime measures the container and a container with no height shows no chart.
10
10
  */
11
11
  import type { ChartBlock } from "../../contracts/report-blocks.js";
12
12
  import type { EchartOption } from "../chart.js";
13
- /** Render the panel markup for a chart. */
14
- export declare function renderChart(block: ChartBlock, option: EchartOption): string;
13
+ import type { ReferenceLedger } from "../references.js";
14
+ /**
15
+ * Render the card markup for a chart.
16
+ *
17
+ * The whole-table binding joins the reference ladder, thus the title line carries the marker and the
18
+ * appendix names the artifact that the chart plots. A chart with no title still shows its marker on the
19
+ * same line.
20
+ */
21
+ export declare function renderChart(block: ChartBlock, ledger: ReferenceLedger, option: EchartOption): string;
@@ -1,26 +1,32 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "hono/jsx/jsx-runtime";
2
2
  /**
3
- * The chart panel markup.
3
+ * The chart card markup.
4
4
  *
5
5
  * The bootstrap in `page.ts` reads the option from the next element sibling of the container. Thus the
6
6
  * `<script type="application/json">` element MUST follow the container div with no element between them.
7
7
  *
8
- * The panel is the window-chrome form: the three dots on the left, the title in the center, and the
9
- * `CORTEX` badge on the right. It is the one component with rounded corners. The chart body carries a fixed
8
+ * The card is the square corner-accent form of the table and the figure, with the mono title line over it. A
9
+ * report is a document, thus the card wears no application-window costume. The chart body carries a fixed
10
10
  * height, because the chart runtime measures the container and a container with no height shows no chart.
11
11
  */
12
12
  import { raw } from "hono/html";
13
+ import { Marker } from "./references-view.js";
13
14
  import { scriptJson } from "../script-json.js";
14
- /** The product badge of a chart panel. */
15
- const PANEL_BADGE = "CORTEX";
16
- /** Render the panel markup for a chart. */
17
- export function renderChart(block, option) {
15
+ /**
16
+ * Render the card markup for a chart.
17
+ *
18
+ * The whole-table binding joins the reference ladder, thus the title line carries the marker and the
19
+ * appendix names the artifact that the chart plots. A chart with no title still shows its marker on the
20
+ * same line.
21
+ */
22
+ export function renderChart(block, ledger, option) {
23
+ const n = ledger.mark(block.binding);
18
24
  const containerId = chartContainerId(block.id);
19
25
  // The JSON goes to the page through `raw()`, thus `scriptJson` is the sole guard of this sink. It
20
26
  // replaces every `<` with `\u003c`, thus a `</script` sequence in a string cell cannot close the
21
27
  // element early. The JSON parser reads `\u003c` as `<`, thus the option value stays exact.
22
28
  const json = scriptJson(option);
23
- return String(_jsxs("div", { class: "report-chart", children: [_jsxs("div", { class: "window-chrome", children: [_jsxs("div", { class: "window-chrome-bar", children: [_jsxs("div", { class: "chrome-dots", children: [_jsx("span", { class: "chrome-dot dot-1" }), _jsx("span", { class: "chrome-dot dot-2" }), _jsx("span", { class: "chrome-dot dot-3" })] }), block.title !== undefined ? _jsx("span", { class: "window-chrome-title", children: block.title }) : null, _jsx("span", { class: "window-chrome-badge", children: PANEL_BADGE })] }), _jsxs("div", { class: "window-chrome-body", children: [_jsx("div", { id: containerId, "data-echarts-id": block.id, class: "chart-container" }), _jsx("script", { type: "application/json", children: raw(json) })] })] }), block.caption !== undefined ? _jsx("p", { class: "report-caption", children: block.caption }) : null] }));
29
+ return String(_jsxs("div", { class: "report-chart", children: [_jsxs("div", { class: "report-chart-title", children: [block.title, _jsx(Marker, { n: n })] }), _jsxs("div", { class: "report-chart-card corner-accents", children: [_jsx("div", { id: containerId, "data-echarts-id": block.id, class: "chart-container" }), _jsx("script", { type: "application/json", children: raw(json) })] }), block.caption !== undefined ? _jsx("p", { class: "report-caption", children: block.caption }) : null] }));
24
30
  }
25
31
  /** The container id derives from the block id, thus the id stays stable across renders. */
26
32
  function chartContainerId(blockId) {
@@ -1,17 +1,24 @@
1
1
  /**
2
- * The page assembly: the hero, the bands, the reference band, and the footer.
2
+ * The page assembly: the hero, the bands, the appendix band, and the footer.
3
3
  *
4
- * The skeleton inlines the style rules in the head, and it puts the three scripts at the end of the body.
5
- * The order of the three scripts is a contract. The theme registration runs before the chart bootstrap,
6
- * thus each chart finds its theme. The fade-in observer also runs before the chart bootstrap, thus the
7
- * bootstrap finds the reveal gate and it signals readiness after the first reveal pass. The navigation, the
8
- * main content, and the reference frame arrive as already-escaped markup strings, thus `raw()` inserts them
9
- * byte for byte.
4
+ * The skeleton inlines the style rules in the head, and it puts the page scripts at the end of the body.
5
+ * The script order is a contract. The theme registration runs before the chart bootstrap, thus each chart
6
+ * finds its theme. The fade-in observer also runs before the chart bootstrap, thus the bootstrap finds the
7
+ * reveal gate and it signals readiness after the first reveal pass. The grid boot runs before the chart
8
+ * bootstrap too, thus every grid stands before the page signals that it is ready. The scrollspy reads the
9
+ * sections alone, thus its position is free. The navigation, the main content, and the reference frame
10
+ * arrive as already-escaped markup strings, thus `raw()` inserts them byte for byte.
10
11
  *
11
12
  * One band holds one top-level section. The band index drives the alternation of the background and of the
12
13
  * texture, thus a caller that adds a band passes the next index.
14
+ *
15
+ * The container gives the full-bleed gutter of a region, and the content column inside it gives the one
16
+ * measure of the page. The hero, each band, and the footer use the same pair. Thus every block kind reads at
17
+ * one width, and the title over them sits on the same left edge.
13
18
  */
14
- import type { ReferenceLedger } from "../references.js";
19
+ import type { DataAsset } from "../table-data.js";
20
+ import type { CitationRecords } from "../../report-model/reference-resolver.js";
21
+ import type { DerivationChains, ReferenceLedger } from "../references.js";
15
22
  /**
16
23
  * Wrap already-escaped markup in one full-bleed band. An even index gives the white background and the dot
17
24
  * texture, and an odd index gives the slate background and the grid texture. The noise texture lies over
@@ -19,13 +26,27 @@ import type { ReferenceLedger } from "../references.js";
19
26
  */
20
27
  export declare function renderBand(index: number, inner: string): string;
21
28
  /**
22
- * Wrap the reference list in the final band. An empty ledger gives an empty string, thus the page shows no
23
- * empty reference band. The index continues the band alternation of the sections.
29
+ * Wrap the one appendix in a band of its own, under the one title.
30
+ *
31
+ * The two reference kinds answer different questions, but one marker notation sends the reader to both.
32
+ * Thus one list serves them, and the kind tag of an entry states which question it answers.
33
+ *
34
+ * An empty ledger renders no band. The index continues the band alternation of the sections, thus the
35
+ * appendix takes the next surface. The records carry the bibliography of each cited key, and a ledger with
36
+ * no citation reads none of them. The chains carry the derivation of each derived path, and an entry of
37
+ * such a path states it.
24
38
  */
25
- export declare function renderReferenceSection(ledger: ReferenceLedger, index: number): string;
39
+ export declare function renderReferenceSection(ledger: ReferenceLedger, index: number, records?: CitationRecords, chains?: DerivationChains): string;
26
40
  /**
27
- * Assemble the page from the title, the navigation, the main content, and the reference frame. The title
28
- * passes through the runtime as text, and the runtime escapes it. The reference frame is optional, thus
29
- * an empty frame adds no markup.
41
+ * Assemble the page from the title, the navigation, the main content, the reference frame, and the data
42
+ * assets. The title passes through the runtime as text, and the runtime escapes it. The reference frame is
43
+ * optional, thus an empty frame adds no markup.
44
+ *
45
+ * Each data asset rides a classic `script` tag at the end of the body, and the decoder runs after the last
46
+ * of them. Thus every payload is registered before any reader looks. A page with no asset carries no tag
47
+ * and no decoder.
48
+ *
49
+ * `grids` states that the content holds a grid mount. The grid runtime weighs about two megabytes, thus a
50
+ * page whose only payload feeds a chart references neither the runtime nor the grid boot.
30
51
  */
31
- export declare function assemblePage(title: string, nav: string, content: string, references: string): string;
52
+ export declare function assemblePage(title: string, nav: string, content: string, references: string, dataAssets: readonly DataAsset[], grids: boolean): string;
@@ -1,26 +1,34 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "hono/jsx/jsx-runtime";
2
2
  /**
3
- * The page assembly: the hero, the bands, the reference band, and the footer.
3
+ * The page assembly: the hero, the bands, the appendix band, and the footer.
4
4
  *
5
- * The skeleton inlines the style rules in the head, and it puts the three scripts at the end of the body.
6
- * The order of the three scripts is a contract. The theme registration runs before the chart bootstrap,
7
- * thus each chart finds its theme. The fade-in observer also runs before the chart bootstrap, thus the
8
- * bootstrap finds the reveal gate and it signals readiness after the first reveal pass. The navigation, the
9
- * main content, and the reference frame arrive as already-escaped markup strings, thus `raw()` inserts them
10
- * byte for byte.
5
+ * The skeleton inlines the style rules in the head, and it puts the page scripts at the end of the body.
6
+ * The script order is a contract. The theme registration runs before the chart bootstrap, thus each chart
7
+ * finds its theme. The fade-in observer also runs before the chart bootstrap, thus the bootstrap finds the
8
+ * reveal gate and it signals readiness after the first reveal pass. The grid boot runs before the chart
9
+ * bootstrap too, thus every grid stands before the page signals that it is ready. The scrollspy reads the
10
+ * sections alone, thus its position is free. The navigation, the main content, and the reference frame
11
+ * arrive as already-escaped markup strings, thus `raw()` inserts them byte for byte.
11
12
  *
12
13
  * One band holds one top-level section. The band index drives the alternation of the background and of the
13
14
  * texture, thus a caller that adds a band passes the next index.
15
+ *
16
+ * The container gives the full-bleed gutter of a region, and the content column inside it gives the one
17
+ * measure of the page. The hero, each band, and the footer use the same pair. Thus every block kind reads at
18
+ * one width, and the title over them sits on the same left edge.
14
19
  */
15
20
  import { raw } from "hono/html";
16
- import { ASSET_HEAD, CHART_BOOTSTRAP, FADE_IN_OBSERVER } from "../page.js";
21
+ import { ASSET_HEAD, CHART_BOOTSTRAP, FADE_IN_OBSERVER, GRID_ASSET_HEAD, GRID_BOOTSTRAP, SECTION_SPY, TABLE_DATA_DECODER } from "../page.js";
22
+ import { stagedSource } from "../assets.js";
17
23
  import { DESIGN_CSS, ECHARTS_THEME, ECHARTS_THEME_NAME } from "../design.js";
18
- import { renderReferenceList } from "./references-view.js";
24
+ import { renderReferences } from "./references-view.js";
19
25
  import { scriptJson } from "../script-json.js";
20
26
  /** The constant eyebrow of the hero. The render reads no clock, thus the hero carries no date. */
21
27
  const HERO_EYEBROW = "INFLEXA · ANALYSIS REPORT";
22
28
  /** The constant note of the footer. */
23
- const FOOTER_NOTE = "Powered by Inflexa Cortex";
29
+ const FOOTER_NOTE = "Powered by Inflexa";
30
+ /** The title of the one appendix. It holds each artifact and each paper that the report names. */
31
+ const REFERENCES_TITLE = "References";
24
32
  /**
25
33
  * The theme object as script-safe JSON. `scriptJson` replaces every `<` with `\u003c`, thus a later edit
26
34
  * that adds a `<` to the theme stays safe inside the script sink. The JSON parser reads `\u003c` as `<`, thus
@@ -44,26 +52,40 @@ const THEME_REGISTRATION = `(function () {
44
52
  */
45
53
  export function renderBand(index, inner) {
46
54
  const surface = index % 2 === 0 ? "report-band-white texture-dots" : "report-band-slate texture-grid";
47
- return String(_jsx("section", { class: `report-band ${surface} texture-noise`, children: _jsx("div", { class: "report-container fade-in", children: raw(inner) }) }));
55
+ return String(_jsx("section", { class: `report-band ${surface} texture-noise`, children: _jsx("div", { class: "report-container fade-in", children: _jsx("div", { class: "report-content", children: raw(inner) }) }) }));
48
56
  }
49
57
  /**
50
- * Wrap the reference list in the final band. An empty ledger gives an empty string, thus the page shows no
51
- * empty reference band. The index continues the band alternation of the sections.
58
+ * Wrap the one appendix in a band of its own, under the one title.
59
+ *
60
+ * The two reference kinds answer different questions, but one marker notation sends the reader to both.
61
+ * Thus one list serves them, and the kind tag of an entry states which question it answers.
62
+ *
63
+ * An empty ledger renders no band. The index continues the band alternation of the sections, thus the
64
+ * appendix takes the next surface. The records carry the bibliography of each cited key, and a ledger with
65
+ * no citation reads none of them. The chains carry the derivation of each derived path, and an entry of
66
+ * such a path states it.
52
67
  */
53
- export function renderReferenceSection(ledger, index) {
54
- const list = renderReferenceList(ledger);
55
- if (list === "") {
68
+ export function renderReferenceSection(ledger, index, records, chains) {
69
+ const references = renderReferences(ledger, records, chains);
70
+ if (references === "") {
56
71
  return "";
57
72
  }
58
- const heading = String(_jsx("h2", { class: "report-heading report-heading-2", children: "References" }));
59
- return renderBand(index, heading + list);
73
+ const heading = String(_jsx("h2", { class: "report-heading report-heading-3 report-ref-title", children: REFERENCES_TITLE }));
74
+ return renderBand(index, heading + references);
60
75
  }
61
76
  /**
62
- * Assemble the page from the title, the navigation, the main content, and the reference frame. The title
63
- * passes through the runtime as text, and the runtime escapes it. The reference frame is optional, thus
64
- * an empty frame adds no markup.
77
+ * Assemble the page from the title, the navigation, the main content, the reference frame, and the data
78
+ * assets. The title passes through the runtime as text, and the runtime escapes it. The reference frame is
79
+ * optional, thus an empty frame adds no markup.
80
+ *
81
+ * Each data asset rides a classic `script` tag at the end of the body, and the decoder runs after the last
82
+ * of them. Thus every payload is registered before any reader looks. A page with no asset carries no tag
83
+ * and no decoder.
84
+ *
85
+ * `grids` states that the content holds a grid mount. The grid runtime weighs about two megabytes, thus a
86
+ * page whose only payload feeds a chart references neither the runtime nor the grid boot.
65
87
  */
66
- export function assemblePage(title, nav, content, references) {
88
+ export function assemblePage(title, nav, content, references, dataAssets, grids) {
67
89
  return ("<!doctype html>" +
68
- String(_jsxs("html", { lang: "en", children: [_jsxs("head", { children: [_jsx("meta", { charset: "utf-8" }), _jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }), _jsx("title", { children: title }), raw(ASSET_HEAD), _jsx("style", { children: raw(DESIGN_CSS) })] }), _jsxs("body", { children: [raw(nav), _jsx("header", { class: "report-hero texture-noise", children: _jsxs("div", { class: "report-container", children: [_jsx("p", { class: "report-eyebrow", children: HERO_EYEBROW }), _jsx("h1", { class: "report-display", children: title })] }) }), _jsxs("main", { children: [raw(content), references.length > 0 ? raw(references) : null] }), _jsx("footer", { class: "report-footer", children: _jsxs("div", { class: "report-container report-footer-row", children: [_jsx("span", { class: "report-footer-title", children: title }), _jsx("span", { class: "report-footer-note", children: FOOTER_NOTE })] }) }), _jsx("script", { children: raw(THEME_REGISTRATION) }), _jsx("script", { children: raw(FADE_IN_OBSERVER) }), _jsx("script", { children: raw(CHART_BOOTSTRAP) })] })] })));
90
+ String(_jsxs("html", { lang: "en", children: [_jsxs("head", { children: [_jsx("meta", { charset: "utf-8" }), _jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }), _jsx("title", { children: title }), raw(ASSET_HEAD), grids ? raw(GRID_ASSET_HEAD) : null, _jsx("style", { children: raw(DESIGN_CSS) })] }), _jsxs("body", { children: [raw(nav), _jsx("header", { class: "report-hero texture-noise", children: _jsx("div", { class: "report-container", children: _jsxs("div", { class: "report-content", children: [_jsx("p", { class: "report-eyebrow", children: HERO_EYEBROW }), _jsx("h1", { class: "report-display", children: title })] }) }) }), _jsxs("main", { children: [raw(content), references.length > 0 ? raw(references) : null] }), _jsx("footer", { class: "report-footer", children: _jsx("div", { class: "report-container", children: _jsxs("div", { class: "report-content report-footer-row", children: [_jsx("span", { class: "report-footer-title", children: title }), _jsx("span", { class: "report-footer-note", children: FOOTER_NOTE })] }) }) }), dataAssets.map((asset) => (_jsx("script", { src: stagedSource(asset.name) }))), dataAssets.length > 0 ? _jsx("script", { children: raw(TABLE_DATA_DECODER) }) : null, _jsx("script", { children: raw(THEME_REGISTRATION) }), _jsx("script", { children: raw(FADE_IN_OBSERVER) }), grids ? _jsx("script", { children: raw(GRID_BOOTSTRAP) }) : null, _jsx("script", { children: raw(CHART_BOOTSTRAP) }), _jsx("script", { children: raw(SECTION_SPY) })] })] })));
69
91
  }
@@ -4,15 +4,25 @@
4
4
  * The runtime escapes every interpolated string, thus hostile prose reaches the page as text. A text
5
5
  * block and a claim block split the prose on a blank line, and each part becomes one paragraph. A claim
6
6
  * adds one marker for each binding, and the markers number through the shared ledger.
7
+ *
8
+ * A text block also carries a typed list, and the list renders as list markup after the paragraphs. Each
9
+ * item takes the same escape as a paragraph, thus no item reaches the page as markup.
7
10
  */
8
11
  import type { ClaimBlock, SectionBlock, TextBlock } from "../../contracts/report-blocks.js";
9
12
  import type { ReferenceLedger } from "../references.js";
10
- /** Render a text block as escaped paragraphs. */
13
+ /**
14
+ * Render a text block as escaped paragraphs, and then its list.
15
+ *
16
+ * The lead sentences introduce the enumeration, thus the list comes after them. An empty prose gives no
17
+ * paragraph, and a block with a list alone renders the list alone. A block with no list renders the
18
+ * paragraphs alone, exactly as it did before the field existed.
19
+ */
11
20
  export declare function renderText(block: TextBlock): string;
12
21
  /**
13
22
  * Render a claim block as escaped paragraphs plus evidence markers. The markers attach to the last
14
23
  * paragraph, thus they sit at the end of the claim text. The ledger marks each binding, thus a shared
15
- * reference keeps one number across the page.
24
+ * reference keeps one number across the page. An artifact binding and a citation binding read the same
25
+ * bracket, because one ladder counts them both.
16
26
  */
17
27
  export declare function renderClaim(block: ClaimBlock, ledger: ReferenceLedger): string;
18
28
  /**
@@ -5,11 +5,18 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "hono/jsx/jsx-
5
5
  * The runtime escapes every interpolated string, thus hostile prose reaches the page as text. A text
6
6
  * block and a claim block split the prose on a blank line, and each part becomes one paragraph. A claim
7
7
  * adds one marker for each binding, and the markers number through the shared ledger.
8
+ *
9
+ * A text block also carries a typed list, and the list renders as list markup after the paragraphs. Each
10
+ * item takes the same escape as a paragraph, thus no item reaches the page as markup.
8
11
  */
9
12
  import { raw } from "hono/html";
10
13
  import { Marker } from "./references-view.js";
11
- /** The paragraph class of a text block and a claim block. The measure caps the line inside the wide band. */
14
+ /** The paragraph class of a text block and a claim block. The paragraph fills the content column. */
12
15
  const PARAGRAPH_CLASS = "report-prose";
16
+ /** The class of a rendered list. The list fills the content column, the same as a paragraph. */
17
+ const LIST_CLASS = "report-list";
18
+ /** The site that the navigation brand links to. It is the one reference of the page that leaves the page. */
19
+ const BRAND_HREF = "https://inflexa.ai/";
13
20
  /**
14
21
  * Split prose into paragraphs on a blank line. A run of blank lines makes one split. An empty part drops
15
22
  * out, thus a leading or a trailing blank line adds no empty paragraph.
@@ -25,19 +32,34 @@ function splitParagraphs(prose) {
25
32
  }
26
33
  return paragraphs;
27
34
  }
28
- /** Render a text block as escaped paragraphs. */
35
+ /**
36
+ * One typed list as list markup. The flag selects the element: an ordered list numbers its items, and an
37
+ * unordered one bullets them. Each item is one inline line, thus no item holds a list of its own.
38
+ */
39
+ function TextListView({ list }) {
40
+ const items = list.items.map((item) => _jsx("li", { class: "report-list-item", children: item }));
41
+ return list.ordered ? _jsx("ol", { class: LIST_CLASS, children: items }) : _jsx("ul", { class: LIST_CLASS, children: items });
42
+ }
43
+ /**
44
+ * Render a text block as escaped paragraphs, and then its list.
45
+ *
46
+ * The lead sentences introduce the enumeration, thus the list comes after them. An empty prose gives no
47
+ * paragraph, and a block with a list alone renders the list alone. A block with no list renders the
48
+ * paragraphs alone, exactly as it did before the field existed.
49
+ */
29
50
  export function renderText(block) {
30
51
  const paragraphs = splitParagraphs(block.content.prose);
31
- return String(_jsx(_Fragment, { children: paragraphs.map((paragraph) => (_jsx("p", { class: PARAGRAPH_CLASS, children: paragraph }))) }));
52
+ const list = block.content.list;
53
+ return String(_jsxs(_Fragment, { children: [paragraphs.map((paragraph) => (_jsx("p", { class: PARAGRAPH_CLASS, children: paragraph }))), list !== undefined ? _jsx(TextListView, { list: list }) : null] }));
32
54
  }
33
55
  /**
34
56
  * Render a claim block as escaped paragraphs plus evidence markers. The markers attach to the last
35
57
  * paragraph, thus they sit at the end of the claim text. The ledger marks each binding, thus a shared
36
- * reference keeps one number across the page.
58
+ * reference keeps one number across the page. An artifact binding and a citation binding read the same
59
+ * bracket, because one ladder counts them both.
37
60
  */
38
61
  export function renderClaim(block, ledger) {
39
- const markerNumbers = block.bindings.map((reference) => ledger.mark(reference));
40
- const markers = markerNumbers.map((n) => _jsx(Marker, { n: n }));
62
+ const markers = block.bindings.map((reference) => _jsx(Marker, { n: ledger.mark(reference) }));
41
63
  const paragraphs = splitParagraphs(block.content.prose);
42
64
  if (paragraphs.length === 0) {
43
65
  return String(_jsx("p", { class: PARAGRAPH_CLASS, children: markers }));
@@ -65,5 +87,5 @@ export function renderSection(section, depth, childrenHtml) {
65
87
  * The `report-sidebar` id is the hook of the layout shift on a large viewport.
66
88
  */
67
89
  export function renderNav(topSections) {
68
- return String(_jsxs("aside", { id: "report-sidebar", class: "report-nav", "aria-label": "Report navigation", children: [_jsx("div", { class: "report-nav-brand", children: _jsx("span", { class: "report-nav-brand-name", children: "inflexa" }) }), _jsx("nav", { class: "report-nav-list", "aria-label": "Report sections", children: topSections.map((section, index) => (_jsxs("a", { href: `#${section.id}`, class: "report-nav-link", children: [_jsx("span", { class: "report-nav-index", children: index + 1 }), _jsx("span", { class: "report-nav-label", children: section.title })] }))) })] }));
90
+ return String(_jsxs("aside", { id: "report-sidebar", class: "report-nav", "aria-label": "Report navigation", children: [_jsx("div", { class: "report-nav-brand", children: _jsx("a", { class: "report-nav-brand-name", href: BRAND_HREF, children: "inflexa" }) }), _jsx("nav", { class: "report-nav-list", "aria-label": "Report sections", children: topSections.map((section, index) => (_jsxs("a", { href: `#${section.id}`, class: "report-nav-link", children: [_jsx("span", { class: "report-nav-index", children: index + 1 }), _jsx("span", { class: "report-nav-label", children: section.title })] }))) })] }));
69
91
  }
@@ -1,20 +1,34 @@
1
1
  /**
2
- * The reference markup: the evidence marker and the ordered reference list.
2
+ * The reference markup: the one evidence marker, and the one appendix list under it.
3
3
  *
4
4
  * The runtime escapes each child and each attribute value, thus a hostile path, a hostile id, or a
5
- * hostile operation reaches the page as text. The list keeps the first-appearance order of the ledger,
5
+ * hostile operation reaches the page as text. The list keeps the first-appearance order of the ladder,
6
6
  * thus the ordinal of each item matches its marker.
7
+ *
8
+ * One list holds both reference kinds, flat and in number order. Each entry leads with a kind tag, thus an
9
+ * artifact entry and a literature entry stay apart on sight without a heading between them. A page with an
10
+ * empty ledger renders no list at all.
7
11
  */
8
- import type { ReferenceLedger } from "../references.js";
12
+ import { type CitationRecords } from "../../report-model/reference-resolver.js";
13
+ import { type DerivationChains, type ReferenceLedger } from "../references.js";
9
14
  /**
10
- * One evidence marker as a superscript that links to the list entry. The number comes from the ledger as
11
- * an integer.
15
+ * One evidence marker as a bracket number that links to its appendix entry.
16
+ *
17
+ * A bracket reads as a reference inside prose, and it stays a span beside the words. One notation serves
18
+ * every kind, thus one list answers every marker.
12
19
  */
13
20
  export declare function Marker({ n }: {
14
21
  n: number;
15
22
  }): import("hono/jsx/jsx-dev-runtime").JSX.Element;
16
23
  /**
17
- * The ordered reference list for the end of the page. An empty ledger gives an empty string, thus the
18
- * page shows no empty list.
24
+ * The one appendix list: one entry for each distinct reference of the page, in the order of the ladder.
25
+ *
26
+ * The list is an appendix: a reader consults one entry from a marker, thus the design keeps it quieter than
27
+ * the body. The ordered list numbers its own items, thus the shown number of an entry matches the marker
28
+ * that sent the reader to it. An empty ledger gives an empty string, thus the page shows no empty list.
29
+ *
30
+ * The records carry the bibliography of each cited key, and a ledger with no citation reads none of them.
31
+ * The chains are the derivations of the session, keyed by the output path. An entry whose path the chains
32
+ * hold carries the chain line, and each other entry carries none.
19
33
  */
20
- export declare function renderReferenceList(ledger: ReferenceLedger): string;
34
+ export declare function renderReferences(ledger: ReferenceLedger, records?: CitationRecords, chains?: DerivationChains): string;
@@ -1,10 +1,14 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "hono/jsx/jsx-runtime";
2
+ import { citationRecordOf } from "../../report-model/reference-resolver.js";
3
+ import { citationKeyOf } from "../references.js";
2
4
  /**
3
- * One evidence marker as a superscript that links to the list entry. The number comes from the ledger as
4
- * an integer.
5
+ * One evidence marker as a bracket number that links to its appendix entry.
6
+ *
7
+ * A bracket reads as a reference inside prose, and it stays a span beside the words. One notation serves
8
+ * every kind, thus one list answers every marker.
5
9
  */
6
10
  export function Marker({ n }) {
7
- return (_jsx("sup", { class: "report-marker", children: _jsx("a", { href: `#ref-${n}`, children: n }) }));
11
+ return (_jsx("span", { class: "report-marker", children: _jsx("a", { href: `#ref-${n}`, children: `[${n}]` }) }));
8
12
  }
9
13
  /** The kind label of one reference entry. */
10
14
  function RefKind({ children }) {
@@ -18,6 +22,56 @@ function PathCode({ children }) {
18
22
  function Detail({ children }) {
19
23
  return _jsx("span", { class: "report-ref-detail", children: children });
20
24
  }
25
+ /** The head of a content hash in a monospace span. */
26
+ function HashCode({ children }) {
27
+ return _jsx("code", { class: "report-ref-hash", children: children });
28
+ }
29
+ /**
30
+ * The count of hash characters that a chain line shows.
31
+ *
32
+ * A content hash is 64 hex characters, and a line that carries three whole ones reads as noise. The head
33
+ * identifies the bytes, and it matches the count that a staged file name carries. Thus a reader compares the
34
+ * two by sight.
35
+ */
36
+ const CHAIN_HASH_CHARS = 12;
37
+ /** The head of one content hash: the hex after the algorithm name, cut to the shown length. */
38
+ function hashHead(hash) {
39
+ return hash.slice(hash.lastIndexOf(":") + 1).slice(0, CHAIN_HASH_CHARS);
40
+ }
41
+ /**
42
+ * The head of the script hash, as a link to the staged script where the caller staged one.
43
+ *
44
+ * The hash head stays the text of the link. Thus the reader reads the same head as before, and the click
45
+ * opens the script itself. A chain with no staged script shows the head alone.
46
+ */
47
+ function ScriptLink({ chain }) {
48
+ const head = _jsx(HashCode, { children: hashHead(chain.scriptHash) });
49
+ return chain.scriptSource === undefined ? (head) : (_jsx("a", { class: "report-ref-link", href: chain.scriptSource, children: head }));
50
+ }
51
+ /**
52
+ * The chain of one derived path: each source with the head of its hash, then the head of the script hash,
53
+ * then the derived file.
54
+ *
55
+ * The line rides under the entry of the path, thus the entry itself keeps the form of a pinned artifact and
56
+ * the chain adds one quiet line under it. A reader mounts the same sources, runs the same script, and gets
57
+ * the same bytes.
58
+ *
59
+ * The script and the derived file are relative links, thus the whole chain walks with no network and no
60
+ * host. Each hash head stays beside its link, because the head is what a reader compares against the name of
61
+ * a staged file.
62
+ */
63
+ function ChainLine({ chain }) {
64
+ return (_jsxs("div", { class: "report-ref-chain", children: [_jsx(RefKind, { children: "Derived from" }), " ", chain.sources.map((source, index) => (_jsxs(_Fragment, { children: [index > 0 ? " and " : "", _jsx(PathCode, { children: source.path }), " ", _jsx(HashCode, { children: hashHead(source.hash) })] }))), " ", _jsx(Detail, { children: "by script" }), " ", _jsx(ScriptLink, { chain: chain }), chain.outputSource !== undefined ? (_jsxs(_Fragment, { children: [" ", _jsx(Detail, { children: "into" }), " ", _jsx("a", { class: "report-ref-link", href: chain.outputSource, children: _jsx(PathCode, { children: chain.outputSource }) })] })) : null] }));
65
+ }
66
+ /**
67
+ * The one path that an artifact reference names, or `undefined` for a kind that names no single file.
68
+ *
69
+ * A derivation reference computes over two inputs, thus it names no output file of its own and no chain
70
+ * belongs to it.
71
+ */
72
+ function pathOf(reference) {
73
+ return reference.kind === "derivation" ? undefined : reference.path;
74
+ }
21
75
  /**
22
76
  * Describe a locator as plain text: the column and the one row selector. The refine of the schema admits
23
77
  * exactly one of `row` or `rowFilter`, thus the two branches cover a valid locator.
@@ -33,11 +87,11 @@ function describeLocator(locator) {
33
87
  return `column ${locator.column}`;
34
88
  }
35
89
  /**
36
- * The inner markup of one list entry. An artifact entry names its path, and it adds the locator when the
37
- * reference pins one cell. A citation entry names its identifier space and its id. A derivation entry
38
- * names its operation and its two inputs, each by path and locator.
90
+ * The inner markup of one artifact entry. An artifact entry names its path, and it adds the locator when
91
+ * the reference pins one cell. A derivation entry names its operation and its two inputs, each by path and
92
+ * locator.
39
93
  */
40
- function ReferenceEntry({ reference }) {
94
+ function ReferenceBody({ reference }) {
41
95
  switch (reference.kind) {
42
96
  case "artifact-value":
43
97
  return (_jsxs(_Fragment, { children: [_jsx(RefKind, { children: "Artifact value" }), " ", _jsx(PathCode, { children: reference.path }), " ", _jsx(Detail, { children: describeLocator(reference.locator) })] }));
@@ -45,20 +99,54 @@ function ReferenceEntry({ reference }) {
45
99
  return (_jsxs(_Fragment, { children: [_jsx(RefKind, { children: "Artifact table" }), " ", _jsx(PathCode, { children: reference.path })] }));
46
100
  case "artifact-file":
47
101
  return (_jsxs(_Fragment, { children: [_jsx(RefKind, { children: "Artifact file" }), " ", _jsx(PathCode, { children: reference.path })] }));
48
- case "citation":
49
- return (_jsxs(_Fragment, { children: [_jsx(RefKind, { children: "Citation" }), " ", _jsx(Detail, { children: `${reference.idKind}:${reference.id}` })] }));
50
102
  case "derivation":
51
103
  return (_jsxs(_Fragment, { children: [_jsx(RefKind, { children: `Derivation (${reference.op})` }), " ", reference.inputs.map((input, index) => (_jsxs(_Fragment, { children: [index > 0 ? " and " : "", _jsx(PathCode, { children: input.path }), " ", _jsx(Detail, { children: describeLocator(input.locator) })] })))] }));
52
104
  }
53
105
  }
54
106
  /**
55
- * The ordered reference list for the end of the page. An empty ledger gives an empty string, thus the
56
- * page shows no empty list.
107
+ * One artifact entry: the body of its kind, and the chain of its path where the records hold one.
108
+ *
109
+ * A path that no record names renders the body alone, thus a page over pinned artifacts alone reads exactly
110
+ * as it did before the chains existed.
111
+ */
112
+ function ArtifactEntry({ reference, chains }) {
113
+ const path = pathOf(reference);
114
+ const chain = path === undefined ? undefined : chains?.get(path);
115
+ return (_jsxs(_Fragment, { children: [_jsx(ReferenceBody, { reference: reference }), chain !== undefined ? _jsx(ChainLine, { chain: chain }) : null] }));
116
+ }
117
+ /**
118
+ * The inner markup of one literature entry: the kind tag, the short citation of the pinned record, the key,
119
+ * and the description of the record on a line of its own. A key that the record map does not hold shows the
120
+ * key alone, because absence is a normal condition.
121
+ *
122
+ * The description sits in the appendix and never on the card. The card sits in the body of the report,
123
+ * where a paragraph about the paper competes with the prose around it.
124
+ */
125
+ function CitationEntry({ reference, records }) {
126
+ const key = citationKeyOf(reference);
127
+ const record = citationRecordOf(records, key);
128
+ const description = record?.description;
129
+ return (_jsxs(_Fragment, { children: [_jsx(RefKind, { children: "Citation" }), " ", record !== undefined ? (_jsxs(_Fragment, { children: [_jsx("span", { class: "report-cite-source", children: record.citation }), " "] })) : null, _jsx(Detail, { children: key }), description !== undefined ? _jsx("div", { class: "report-cite-description", children: description }) : null] }));
130
+ }
131
+ /** One appendix entry. The kind of the reference selects the shape, and the two shapes share the ladder. */
132
+ function ReferenceEntry({ reference, records, chains }) {
133
+ return reference.kind === "citation" ? _jsx(CitationEntry, { reference: reference, records: records }) : _jsx(ArtifactEntry, { reference: reference, chains: chains });
134
+ }
135
+ /**
136
+ * The one appendix list: one entry for each distinct reference of the page, in the order of the ladder.
137
+ *
138
+ * The list is an appendix: a reader consults one entry from a marker, thus the design keeps it quieter than
139
+ * the body. The ordered list numbers its own items, thus the shown number of an entry matches the marker
140
+ * that sent the reader to it. An empty ledger gives an empty string, thus the page shows no empty list.
141
+ *
142
+ * The records carry the bibliography of each cited key, and a ledger with no citation reads none of them.
143
+ * The chains are the derivations of the session, keyed by the output path. An entry whose path the chains
144
+ * hold carries the chain line, and each other entry carries none.
57
145
  */
58
- export function renderReferenceList(ledger) {
146
+ export function renderReferences(ledger, records, chains) {
59
147
  const entries = ledger.entries();
60
148
  if (entries.length === 0) {
61
149
  return "";
62
150
  }
63
- return String(_jsx("ol", { class: "report-references", children: entries.map((reference, index) => (_jsx("li", { id: `ref-${index + 1}`, class: "report-ref-item", children: _jsx(ReferenceEntry, { reference: reference }) }))) }));
151
+ return String(_jsx("ol", { class: "report-references", children: entries.map((reference, index) => (_jsx("li", { id: `ref-${index + 1}`, class: "report-ref-item", children: _jsx(ReferenceEntry, { reference: reference, records: records, chains: chains }) }))) }));
64
152
  }