structural-codes-viewer 0.1.0-alpha.1 → 0.1.0-alpha.2

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 (135) hide show
  1. package/LICENSE +501 -0
  2. package/NOTICE +16 -0
  3. package/README.md +119 -63
  4. package/package-dist/CorpusContent.d.ts +44 -9
  5. package/package-dist/CorpusContent.js +452 -26
  6. package/package-dist/CorpusContent.js.map +1 -1
  7. package/package-dist/NormativeViewer.d.ts +23 -2
  8. package/package-dist/NormativeViewer.js +1699 -234
  9. package/package-dist/NormativeViewer.js.map +1 -1
  10. package/package-dist/ReferenceTools.d.ts +49 -0
  11. package/package-dist/ReferenceTools.js +14 -0
  12. package/package-dist/ReferenceTools.js.map +1 -0
  13. package/package-dist/annotations/AnnotationUi.d.ts +57 -0
  14. package/package-dist/annotations/AnnotationUi.js +114 -0
  15. package/package-dist/annotations/AnnotationUi.js.map +1 -0
  16. package/package-dist/annotations/annotationTargets.d.ts +39 -0
  17. package/package-dist/annotations/annotationTargets.js +94 -0
  18. package/package-dist/annotations/annotationTargets.js.map +1 -0
  19. package/package-dist/annotations/exportImport.d.ts +6 -0
  20. package/package-dist/annotations/exportImport.js +30 -0
  21. package/package-dist/annotations/exportImport.js.map +1 -0
  22. package/package-dist/annotations/index.d.ts +4 -0
  23. package/package-dist/annotations/index.js +5 -0
  24. package/package-dist/annotations/index.js.map +1 -0
  25. package/package-dist/annotations/indexedDb.d.ts +21 -0
  26. package/package-dist/annotations/indexedDb.js +210 -0
  27. package/package-dist/annotations/indexedDb.js.map +1 -0
  28. package/package-dist/annotations/schema.d.ts +8 -0
  29. package/package-dist/annotations/schema.js +102 -0
  30. package/package-dist/annotations/schema.js.map +1 -0
  31. package/package-dist/annotations/types.d.ts +52 -0
  32. package/package-dist/annotations/types.js +18 -0
  33. package/package-dist/annotations/types.js.map +1 -0
  34. package/package-dist/chatntc/canonicalization.d.ts +15 -0
  35. package/package-dist/chatntc/canonicalization.js +107 -0
  36. package/package-dist/chatntc/canonicalization.js.map +1 -0
  37. package/package-dist/chatntc/directives.d.ts +2 -0
  38. package/package-dist/chatntc/directives.js +38 -0
  39. package/package-dist/chatntc/directives.js.map +1 -0
  40. package/package-dist/chatntc/evidence.d.ts +17 -0
  41. package/package-dist/chatntc/evidence.js +116 -0
  42. package/package-dist/chatntc/evidence.js.map +1 -0
  43. package/package-dist/chatntc/index.d.ts +10 -0
  44. package/package-dist/chatntc/index.js +9 -0
  45. package/package-dist/chatntc/index.js.map +1 -0
  46. package/package-dist/chatntc/issueCategories.d.ts +2 -0
  47. package/package-dist/chatntc/issueCategories.js +11 -0
  48. package/package-dist/chatntc/issueCategories.js.map +1 -0
  49. package/package-dist/chatntc/policy.d.ts +35 -0
  50. package/package-dist/chatntc/policy.js +36 -0
  51. package/package-dist/chatntc/policy.js.map +1 -0
  52. package/package-dist/chatntc/provider.d.ts +42 -0
  53. package/package-dist/chatntc/provider.js +2 -0
  54. package/package-dist/chatntc/provider.js.map +1 -0
  55. package/package-dist/chatntc/responseContract.d.ts +52 -0
  56. package/package-dist/chatntc/responseContract.js +73 -0
  57. package/package-dist/chatntc/responseContract.js.map +1 -0
  58. package/package-dist/chatntc/retrieval.d.ts +5 -0
  59. package/package-dist/chatntc/retrieval.js +220 -0
  60. package/package-dist/chatntc/retrieval.js.map +1 -0
  61. package/package-dist/chatntc/types.d.ts +240 -0
  62. package/package-dist/chatntc/types.js +2 -0
  63. package/package-dist/chatntc/types.js.map +1 -0
  64. package/package-dist/chatntc/validation.d.ts +8 -0
  65. package/package-dist/chatntc/validation.js +299 -0
  66. package/package-dist/chatntc/validation.js.map +1 -0
  67. package/package-dist/chatntc/viewerArtifacts.d.ts +14 -0
  68. package/package-dist/chatntc/viewerArtifacts.js +168 -0
  69. package/package-dist/chatntc/viewerArtifacts.js.map +1 -0
  70. package/package-dist/chatntc-history/index.d.ts +2 -0
  71. package/package-dist/chatntc-history/index.js +3 -0
  72. package/package-dist/chatntc-history/index.js.map +1 -0
  73. package/package-dist/chatntc-history/indexedDb.d.ts +27 -0
  74. package/package-dist/chatntc-history/indexedDb.js +258 -0
  75. package/package-dist/chatntc-history/indexedDb.js.map +1 -0
  76. package/package-dist/chatntc-history/schema.d.ts +5 -0
  77. package/package-dist/chatntc-history/schema.js +102 -0
  78. package/package-dist/chatntc-history/schema.js.map +1 -0
  79. package/package-dist/chatntc-history/types.d.ts +78 -0
  80. package/package-dist/chatntc-history/types.js +23 -0
  81. package/package-dist/chatntc-history/types.js.map +1 -0
  82. package/package-dist/chatntc-ui/ChatNTCHistoryPanel.d.ts +9 -0
  83. package/package-dist/chatntc-ui/ChatNTCHistoryPanel.js +239 -0
  84. package/package-dist/chatntc-ui/ChatNTCHistoryPanel.js.map +1 -0
  85. package/package-dist/chatntc-ui/ChatNTCIcons.d.ts +10 -0
  86. package/package-dist/chatntc-ui/ChatNTCIcons.js +20 -0
  87. package/package-dist/chatntc-ui/ChatNTCIcons.js.map +1 -0
  88. package/package-dist/chatntc-ui/ChatNTCLoadingSkeleton.d.ts +1 -0
  89. package/package-dist/chatntc-ui/ChatNTCLoadingSkeleton.js +5 -0
  90. package/package-dist/chatntc-ui/ChatNTCLoadingSkeleton.js.map +1 -0
  91. package/package-dist/chatntc-ui/ChatNTCMarkdown.d.ts +14 -0
  92. package/package-dist/chatntc-ui/ChatNTCMarkdown.js +112 -0
  93. package/package-dist/chatntc-ui/ChatNTCMarkdown.js.map +1 -0
  94. package/package-dist/chatntc-ui/ChatNTCPanel.d.ts +29 -0
  95. package/package-dist/chatntc-ui/ChatNTCPanel.js +241 -0
  96. package/package-dist/chatntc-ui/ChatNTCPanel.js.map +1 -0
  97. package/package-dist/chatntc-ui/historyMessages.d.ts +5 -0
  98. package/package-dist/chatntc-ui/historyMessages.js +53 -0
  99. package/package-dist/chatntc-ui/historyMessages.js.map +1 -0
  100. package/package-dist/chatntc-ui/index.d.ts +3 -0
  101. package/package-dist/chatntc-ui/index.js +4 -0
  102. package/package-dist/chatntc-ui/index.js.map +1 -0
  103. package/package-dist/chatntc-ui/transport.d.ts +51 -0
  104. package/package-dist/chatntc-ui/transport.js +9 -0
  105. package/package-dist/chatntc-ui/transport.js.map +1 -0
  106. package/package-dist/chunkNavigation.d.ts +12 -0
  107. package/package-dist/chunkNavigation.js +44 -0
  108. package/package-dist/chunkNavigation.js.map +1 -0
  109. package/package-dist/corpusData.d.ts +176 -33
  110. package/package-dist/corpusData.js +52 -0
  111. package/package-dist/corpusData.js.map +1 -1
  112. package/package-dist/crossReferences.d.ts +46 -0
  113. package/package-dist/crossReferences.js +198 -0
  114. package/package-dist/crossReferences.js.map +1 -0
  115. package/package-dist/generate-artifacts.mjs +47 -12
  116. package/package-dist/globalScrubber.d.ts +10 -0
  117. package/package-dist/globalScrubber.js +85 -0
  118. package/package-dist/globalScrubber.js.map +1 -0
  119. package/package-dist/permalinks.d.ts +22 -0
  120. package/package-dist/permalinks.js +36 -0
  121. package/package-dist/permalinks.js.map +1 -0
  122. package/package-dist/searchClient.d.ts +22 -0
  123. package/package-dist/searchClient.js +133 -0
  124. package/package-dist/searchClient.js.map +1 -0
  125. package/package-dist/searchEngine.d.ts +68 -0
  126. package/package-dist/searchEngine.js +558 -0
  127. package/package-dist/searchEngine.js.map +1 -0
  128. package/package-dist/searchWorker.d.ts +1 -0
  129. package/package-dist/searchWorker.js +32 -0
  130. package/package-dist/searchWorker.js.map +1 -0
  131. package/package-dist/styles.css +927 -182
  132. package/package-dist/tableCaptions.d.mts +3 -0
  133. package/package-dist/tableCaptions.mjs +35 -0
  134. package/package-dist/tableCaptions.mjs.map +1 -0
  135. package/package.json +61 -15
package/README.md CHANGED
@@ -1,18 +1,21 @@
1
1
  # structural-codes-viewer
2
2
 
3
- `structural-codes-viewer` è la reference UI React per consultare il corpus
4
- `structural-codes`. Il sottoprogetto contiene anche il consumer standalone
5
- locale usato per la revisione editoriale.
3
+ `structural-codes-viewer` è il package React per consultare il corpus
4
+ `structural-codes`. La stessa directory contiene l'applicazione standalone e
5
+ la route ChatNTC self-hosted, che restano fuori dal tarball del package.
6
6
 
7
- - `structural-codes` contiene corpus, schema, provenance e relazioni canoniche;
8
- - `structural-codes-viewer` contiene UI React, client lazy degli artefatti e
9
- generatore deterministico;
10
- - il viewer standalone Vinext/Vite è un consumer locale della stessa UI e può
11
- aggiungere il PDF ufficiale tramite `OfficialPdfPanel`;
12
- - un futuro `ocfem-website` consumerà la stessa UI senza Vinext, Cloudflare o
13
- PDF.js.
7
+ ## Boundary
14
8
 
15
- ## Uso React
9
+ - `structural-codes`: corpus, schema, provenance e helper non React;
10
+ - `structural-codes-viewer`: componenti React, client lazy, generatore
11
+ artefatti e API ChatNTC condivise;
12
+ - `viewer/app/` e `viewer/server/`: composizione standalone, route e adapter
13
+ provider non pubblicati nel package.
14
+
15
+ React e ReactDOM sono peer dependency. Il package non dipende a runtime da
16
+ Next/Vinext, `pdfjs-dist`, BGE-M3, adapter provider o file `.local`.
17
+
18
+ ## Viewer React
16
19
 
17
20
  ```tsx
18
21
  import { NormativeViewer } from "structural-codes-viewer";
@@ -23,80 +26,133 @@ export function Normativa() {
23
26
  }
24
27
  ```
25
28
 
26
- La modalità predefinita è `combined`: la NTC resta la struttura principale e
27
- la Circolare viene inserita soltanto tramite relazioni esplicite del corpus.
28
- Le relazioni `proposed` restano tracciate nei dati senza aggiungere etichette
29
- testuali alla lettura. Il client verifica `formatVersion`, schema e manifest; non usa
30
- la uguaglianza delle versioni SemVer per interpretare i dati.
31
-
32
- API intenzionale:
29
+ Props principali:
33
30
 
34
31
  - `defaultMode`: `combined`, `ntc` o `circ`;
35
- - `dataBaseUrl`: directory degli artefatti lazy, default `/data/codes`;
36
- - `assetsBaseUrl`: directory delle figure, default `/assets`;
37
- - `auxiliaryPanel`: pannello opzionale o render prop locale;
38
- - `auxiliaryPanelDefaultVisible`: visibilità iniziale del pannello opzionale.
39
-
40
- La ricerca è sempre visibile ma carica `search-index.json` soltanto con almeno
41
- due caratteri. Manifest, indice documento, chunk e relazioni restano separati.
42
- Le figure sono lazy e il package shared non importa `pdfjs-dist`, non conosce
43
- `/api/source-pdf` e non dipende da Vinext o Cloudflare. React e ReactDOM sono
44
- peer dependencies React 19. Nell’indice della consultazione comparata ogni
45
- colonna segue la selezione corrente: capitolo → paragrafi → sottoparagrafi →
46
- dettagli. I capitoli entro la soglia di caricamento sono continui; quelli più
47
- grandi caricano il testo in continuità quando si seleziona il singolo paragrafo.
32
+ - `dataBaseUrl`: artefatti lazy, default `/data/codes`;
33
+ - `assetsBaseUrl`: figure, default `/assets`;
34
+ - `auxiliaryPanel`: pannello opzionale o render prop;
35
+ - `auxiliaryPanelDefaultVisible`, `auxiliaryPanelKeepMounted` e modalità
36
+ consentite del pannello.
48
37
 
49
- ## Artefatti
38
+ La vista combinata mantiene le NTC come struttura principale e inserisce la
39
+ Circolare solo tramite relazioni esplicite. Ricerca, chunk, relazioni, figure e
40
+ prefetch sono lazy; il package shared non importa PDF o route standalone.
50
41
 
51
- `npm run sync:corpus` mantiene il consumer locale aggiornato sotto
52
- `public/data/codes/`:
42
+ ## Artefatti
53
43
 
54
- ```text
55
- manifest.json
56
- relations.json
57
- relation-diagnostics.json
58
- search-index.json
59
- ntc2018/index.json
60
- ntc2018/chunks/*.json
61
- circ2019/index.json
62
- circ2019/chunks/*.json
44
+ ```bash
45
+ npm --prefix viewer run sync:corpus
63
46
  ```
64
47
 
65
- Il generatore condiviso legge soltanto i file pubblici del package
66
- `structural-codes`, è deterministico e non richiede un checkout sibling. La
67
- CLI inclusa nel package può materializzare gli stessi artefatti in un consumer:
48
+ Il comando genera sotto `viewer/public/data/codes/` manifest, indici documento,
49
+ chunk, relazioni, riferimenti e indice di ricerca. `viewer/public/` è ignorato
50
+ da Git e rigenerabile dal corpus canonico.
51
+
52
+ Un consumer può usare la CLI inclusa:
68
53
 
69
54
  ```bash
70
55
  npx structural-codes-viewer --source structural-codes \
71
56
  --output public/data/codes --assets public/assets
72
57
  ```
73
58
 
74
- Il comando non copia il corpus completo nel package viewer: usa il package
75
- `structural-codes` installato dal consumer come sorgente.
59
+ Il package viewer non include il corpus completo: il generatore legge il
60
+ package `structural-codes` installato nel consumer.
61
+
62
+ ## Export ChatNTC
63
+
64
+ ```ts
65
+ import {
66
+ CHATNTC_DEFAULT_RETRIEVAL,
67
+ retrieveChatNTCEvidence,
68
+ validateChatNTCResponse,
69
+ } from "structural-codes-viewer/chatntc";
70
+ import { createViewerArtifactRepository } from
71
+ "structural-codes-viewer/chatntc/viewer-artifacts";
72
+ import { ChatNTCPanel, type ChatTransport } from
73
+ "structural-codes-viewer/chatntc-ui";
74
+ import { IndexedDbChatHistoryStore, type ChatHistoryStore } from
75
+ "structural-codes-viewer/chatntc-history";
76
+ ```
77
+
78
+ Questi export sono shared/browser-safe. Route HTTP, provider secrets,
79
+ `LocalChatTransport`, `LocalAIConfiguration` e impostazioni standalone non
80
+ sono API del package.
76
81
 
77
- ## Viewer standalone
82
+ ## Standalone senza ChatNTC
78
83
 
79
84
  ```bash
85
+ npm ci
86
+ npm run sync:corpus
80
87
  npm run dev
81
- npm run build
82
- npm test
83
88
  ```
84
89
 
85
- La route `/consultazione` usa `NormativeViewer` e compone il pannello PDF
86
- locale opzionale. PDF.js e il file PDF vengono caricati solo dopo l’azione
87
- esplicita “Apri PDF ufficiale”; il PDF non entra nel package shared.
90
+ Il viewer funziona senza provider e senza ChatNTC. Il PDF ufficiale è un
91
+ ausilio locale/debug e non entra nel build pubblico o nel package.
88
92
 
89
- ## Package
93
+ ## ChatNTC self-hosted
90
94
 
91
- La prerelease non viene pubblicata da questo repository. Per una futura
92
- pubblicazione, dopo review:
95
+ Dal root della repository:
93
96
 
94
97
  ```bash
95
- npm run build:library
96
- npm pack
97
- npm publish --access public
98
+ npm run dev
98
99
  ```
99
100
 
100
- Il tarball contiene soltanto `package-dist/`, CSS, README e metadati del
101
- package; non contiene app standalone, worker Cloudflare, test, cache, corpus
102
- completo o `pdfjs-dist`.
101
+ Il launcher abilita ChatNTC e vincola il server a `127.0.0.1`. In alternativa,
102
+ copiando `viewer/.env.example` in `viewer/.env.local`, impostare:
103
+
104
+ ```dotenv
105
+ CHATNTC_ENABLED=true
106
+ CHATNTC_PROVIDER=deepseek
107
+ CHATNTC_DEEPSEEK_API_KEY=
108
+ CHATNTC_SEMANTIC_MODE=off
109
+ ```
110
+
111
+ La chiave può restare vuota se l'utente usa la UI BYOK. Le chiavi environment
112
+ rimangono server-side; quelle UI rimangono in memoria e viaggiano in un header
113
+ stessa origine, mai nel body o nella history.
114
+
115
+ Pipeline standard:
116
+
117
+ ```text
118
+ query → lexical retrieval → structural expansion → Evidence Package
119
+ → LLM → Citation Validator → risposta verificata
120
+ ```
121
+
122
+ Dettagli: [overview](../docs/chatntc-core.md),
123
+ [self-hosting](../docs/chatntc-server.md),
124
+ [BYOK](../docs/chatntc-byok.md) e
125
+ [history](../docs/chatntc-history.md).
126
+
127
+ ## Semantic retrieval sperimentale
128
+
129
+ `CHATNTC_SEMANTIC_MODE=off|shadow|on`; il default è `off`.
130
+
131
+ - `off`: percorso lessicale standard, nessun indice o embedding;
132
+ - `shadow`: calcolo semantic osservazionale, output lessicale invariato;
133
+ - `on`: ranking fuso RRF con fallback lessicale.
134
+
135
+ Gli adapter BGE-M3 HTTP e Ollama, i generatori indice e i benchmark sono
136
+ strumenti opt-in. BGE-M3 non è una dipendenza obbligatoria del viewer o di
137
+ ChatNTC. Vedere la
138
+ [documentazione semantic](../docs/chatntc-semantic-index.md).
139
+
140
+ ## Sviluppo e verifica
141
+
142
+ ```bash
143
+ npm ci
144
+ npm run lint
145
+ npm test
146
+ npm run check
147
+ npm run pack:verify
148
+ npm run test:consumer
149
+ ```
150
+
151
+ `check` costruisce app e libreria ed esegue test viewer, ChatNTC, history,
152
+ semantic e boundary. `pack:verify` mostra il contenuto effettivo del tarball.
153
+ `test:consumer` crea tarball reali di entrambi i package, li installa in una
154
+ nuova app Next e verifica viewer, export ChatNTC runtime e tipi pubblici.
155
+
156
+ Il tarball deve contenere soltanto `package-dist/`, README, licenza, notice e
157
+ manifest. Sono vietati `app/`, `server/`, test, PDF, corpus completo, `.env`,
158
+ cache, indici semantic e output standalone.
@@ -1,16 +1,51 @@
1
- import type { AssetBundle, CorpusBlock, CorpusUnit } from "./corpusData";
1
+ import type { AssetBundle, CorpusBlock, DocumentId, InlineSegment, CorpusUnit } from "./corpusData";
2
+ export declare function leadingMathLabelEnd(inline: InlineSegment[]): number;
3
+ export declare function hasOfficialListMarker(block: CorpusBlock): boolean;
4
+ export declare function hasAlphaRatioListLayout(block: CorpusBlock, sourceUnitId?: string): boolean;
5
+ export declare function hasInferredAlphaRatioListMarker(block: CorpusBlock, sourceUnitId?: string): boolean;
6
+ export declare function hasAlphabeticListMarker(block: CorpusBlock): boolean;
7
+ export declare function hasSimpleDashMarker(block: CorpusBlock): boolean;
8
+ export declare function hasNoListMarker(block: CorpusBlock): boolean;
9
+ export declare function listMarkerClass(block: CorpusBlock): "" | "list-item-with-bullet";
10
+ export declare function listLevelClass(block: CorpusBlock): string;
11
+ export declare function indentLevelClass(block: CorpusBlock): string;
12
+ export declare function hasLeadingMath(block: CorpusBlock): boolean;
13
+ export declare function hasAlignedListContinuation(block: CorpusBlock): boolean;
14
+ export declare function hasLeadingEmphasisLabel(block: CorpusBlock): boolean;
15
+ export declare function leadingLabelKind(block: CorpusBlock): "math" | "emphasis" | null;
16
+ export type CorpusBlockGroup = {
17
+ kind: "label-list";
18
+ blocks: CorpusBlock[];
19
+ } | {
20
+ kind: "block";
21
+ block: CorpusBlock;
22
+ index: number;
23
+ };
24
+ export declare function groupAlignedLabelBlocks(blocks: CorpusBlock[]): CorpusBlockGroup[];
25
+ export declare function hasTrailingStrong(block: CorpusBlock): boolean;
26
+ export declare function hasTrailingMath(block: CorpusBlock): boolean;
2
27
  export interface BlockContentProps {
3
28
  block: CorpusBlock;
4
29
  assets: AssetBundle | null;
5
- showRaw?: boolean;
6
30
  assetsBaseUrl?: string;
31
+ aligned?: boolean;
32
+ sourceUnitId?: string;
33
+ sourceDocument?: DocumentId;
7
34
  }
8
- export declare function BlockContent({ block, assets, showRaw, assetsBaseUrl }: BlockContentProps): import("react/jsx-runtime").JSX.Element;
9
- export declare function isRepeatedUnitTitle(unit: CorpusUnit, block: CorpusUnit["blocks"][number]): boolean;
10
- export declare function UnitBlocks({ unit, assets, showRaw, compact, assetsBaseUrl }: {
11
- unit: CorpusUnit;
12
- assets: AssetBundle;
13
- showRaw?: boolean;
14
- compact?: boolean;
35
+ type InlineSegments = InlineSegment[];
36
+ interface ReferenceContext {
37
+ sourceUnitId: string;
38
+ sourceDocument: DocumentId;
39
+ }
40
+ export declare function renderInlineSegments(inline: InlineSegments, context?: ReferenceContext | null): import("react").ReactNode[];
41
+ export declare function BlockContent({ block, assets, assetsBaseUrl, aligned, sourceUnitId, sourceDocument }: BlockContentProps): import("react/jsx-runtime").JSX.Element;
42
+ export declare function AlignedLabelList({ blocks, assets, assetsBaseUrl, sourceUnitId, sourceDocument, renderAccessory }: {
43
+ blocks: CorpusBlock[];
44
+ assets: AssetBundle | null;
15
45
  assetsBaseUrl?: string;
46
+ sourceUnitId?: string;
47
+ sourceDocument?: DocumentId;
48
+ renderAccessory?: (block: CorpusBlock) => React.ReactNode;
16
49
  }): import("react/jsx-runtime").JSX.Element;
50
+ export declare function isRepeatedUnitTitle(unit: CorpusUnit, block: CorpusUnit["blocks"][number]): boolean;
51
+ export {};