complydoc 0.3.0__tar.gz

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 (172) hide show
  1. complydoc-0.3.0/.github/images/complydoc-architecture-dark.html +148 -0
  2. complydoc-0.3.0/.github/images/complydoc-architecture-dark.svg +123 -0
  3. complydoc-0.3.0/.github/images/complydoc-architecture.html +148 -0
  4. complydoc-0.3.0/.github/images/complydoc-architecture.svg +123 -0
  5. complydoc-0.3.0/.github/images/logo-dark.svg +13 -0
  6. complydoc-0.3.0/.github/images/logo-light.svg +13 -0
  7. complydoc-0.3.0/.github/images/report-dark.png +0 -0
  8. complydoc-0.3.0/.github/images/report-light.png +0 -0
  9. complydoc-0.3.0/.github/workflows/checks.yml +91 -0
  10. complydoc-0.3.0/.github/workflows/publish.yml +73 -0
  11. complydoc-0.3.0/.github/workflows/release.yml +127 -0
  12. complydoc-0.3.0/.gitignore +32 -0
  13. complydoc-0.3.0/.python-version +1 -0
  14. complydoc-0.3.0/CONTRIBUTING.md +190 -0
  15. complydoc-0.3.0/LICENSE +21 -0
  16. complydoc-0.3.0/Makefile +145 -0
  17. complydoc-0.3.0/PKG-INFO +362 -0
  18. complydoc-0.3.0/README.md +316 -0
  19. complydoc-0.3.0/pyproject.toml +134 -0
  20. complydoc-0.3.0/scripts/build_diagram.py +211 -0
  21. complydoc-0.3.0/scripts/build_price_table.py +202 -0
  22. complydoc-0.3.0/scripts/build_sbom.py +93 -0
  23. complydoc-0.3.0/src/complydoc/CHANGELOG.md +347 -0
  24. complydoc-0.3.0/src/complydoc/__init__.py +6 -0
  25. complydoc-0.3.0/src/complydoc/audit.py +467 -0
  26. complydoc-0.3.0/src/complydoc/cli.py +1148 -0
  27. complydoc-0.3.0/src/complydoc/config/__init__.py +0 -0
  28. complydoc-0.3.0/src/complydoc/config/loader.py +335 -0
  29. complydoc-0.3.0/src/complydoc/config/model_prices.json +1628 -0
  30. complydoc-0.3.0/src/complydoc/config/pricing.yaml +264 -0
  31. complydoc-0.3.0/src/complydoc/config/readiness.yaml +230 -0
  32. complydoc-0.3.0/src/complydoc/config/schema.py +406 -0
  33. complydoc-0.3.0/src/complydoc/config/sensitive.yaml +371 -0
  34. complydoc-0.3.0/src/complydoc/cost/__init__.py +0 -0
  35. complydoc-0.3.0/src/complydoc/cost/estimator.py +387 -0
  36. complydoc-0.3.0/src/complydoc/cost/price_table.py +192 -0
  37. complydoc-0.3.0/src/complydoc/cost/pricing_import.py +241 -0
  38. complydoc-0.3.0/src/complydoc/cost/tokenizer.py +89 -0
  39. complydoc-0.3.0/src/complydoc/cost/vision.py +106 -0
  40. complydoc-0.3.0/src/complydoc/discovery.py +68 -0
  41. complydoc-0.3.0/src/complydoc/geometry.py +40 -0
  42. complydoc-0.3.0/src/complydoc/ingest/__init__.py +0 -0
  43. complydoc-0.3.0/src/complydoc/ingest/base.py +290 -0
  44. complydoc-0.3.0/src/complydoc/ingest/docx.py +146 -0
  45. complydoc-0.3.0/src/complydoc/ingest/engines/__init__.py +0 -0
  46. complydoc-0.3.0/src/complydoc/ingest/engines/base.py +46 -0
  47. complydoc-0.3.0/src/complydoc/ingest/engines/rapidocr.py +104 -0
  48. complydoc-0.3.0/src/complydoc/ingest/engines/registry.py +53 -0
  49. complydoc-0.3.0/src/complydoc/ingest/engines/tesseract.py +75 -0
  50. complydoc-0.3.0/src/complydoc/ingest/extractors/__init__.py +0 -0
  51. complydoc-0.3.0/src/complydoc/ingest/extractors/base.py +110 -0
  52. complydoc-0.3.0/src/complydoc/ingest/extractors/pdfium.py +65 -0
  53. complydoc-0.3.0/src/complydoc/ingest/extractors/plumber.py +53 -0
  54. complydoc-0.3.0/src/complydoc/ingest/extractors/pypdfreader.py +47 -0
  55. complydoc-0.3.0/src/complydoc/ingest/extractors/registry.py +58 -0
  56. complydoc-0.3.0/src/complydoc/ingest/image.py +92 -0
  57. complydoc-0.3.0/src/complydoc/ingest/ocr.py +126 -0
  58. complydoc-0.3.0/src/complydoc/ingest/pdf.py +697 -0
  59. complydoc-0.3.0/src/complydoc/ingest/registry.py +55 -0
  60. complydoc-0.3.0/src/complydoc/ingest/xlsx.py +90 -0
  61. complydoc-0.3.0/src/complydoc/offline.py +97 -0
  62. complydoc-0.3.0/src/complydoc/overall.py +254 -0
  63. complydoc-0.3.0/src/complydoc/quickwins.py +299 -0
  64. complydoc-0.3.0/src/complydoc/readiness/__init__.py +0 -0
  65. complydoc-0.3.0/src/complydoc/readiness/analyser.py +116 -0
  66. complydoc-0.3.0/src/complydoc/readiness/base.py +89 -0
  67. complydoc-0.3.0/src/complydoc/readiness/registry.py +52 -0
  68. complydoc-0.3.0/src/complydoc/readiness/scoring.py +120 -0
  69. complydoc-0.3.0/src/complydoc/readiness/signals/__init__.py +0 -0
  70. complydoc-0.3.0/src/complydoc/readiness/signals/acroform.py +23 -0
  71. complydoc-0.3.0/src/complydoc/readiness/signals/columns.py +75 -0
  72. complydoc-0.3.0/src/complydoc/readiness/signals/date_formats.py +60 -0
  73. complydoc-0.3.0/src/complydoc/readiness/signals/encryption.py +31 -0
  74. complydoc-0.3.0/src/complydoc/readiness/signals/fonts.py +59 -0
  75. complydoc-0.3.0/src/complydoc/readiness/signals/garbled.py +75 -0
  76. complydoc-0.3.0/src/complydoc/readiness/signals/image_area.py +38 -0
  77. complydoc-0.3.0/src/complydoc/readiness/signals/language.py +73 -0
  78. complydoc-0.3.0/src/complydoc/readiness/signals/ocr_confidence.py +38 -0
  79. complydoc-0.3.0/src/complydoc/readiness/signals/page_size.py +32 -0
  80. complydoc-0.3.0/src/complydoc/readiness/signals/rotation_skew.py +198 -0
  81. complydoc-0.3.0/src/complydoc/readiness/signals/scan_dpi.py +50 -0
  82. complydoc-0.3.0/src/complydoc/readiness/signals/tables.py +124 -0
  83. complydoc-0.3.0/src/complydoc/readiness/signals/text_coverage.py +38 -0
  84. complydoc-0.3.0/src/complydoc/readiness/signals/text_layer.py +35 -0
  85. complydoc-0.3.0/src/complydoc/report/__init__.py +0 -0
  86. complydoc-0.3.0/src/complydoc/report/charts.py +339 -0
  87. complydoc-0.3.0/src/complydoc/report/diffing.py +108 -0
  88. complydoc-0.3.0/src/complydoc/report/html_writer.py +394 -0
  89. complydoc-0.3.0/src/complydoc/report/json_writer.py +24 -0
  90. complydoc-0.3.0/src/complydoc/report/limitations.py +385 -0
  91. complydoc-0.3.0/src/complydoc/report/models.py +400 -0
  92. complydoc-0.3.0/src/complydoc/report/preview.py +379 -0
  93. complydoc-0.3.0/src/complydoc/report/templates/report.html.j2 +1732 -0
  94. complydoc-0.3.0/src/complydoc/report/text_writer.py +69 -0
  95. complydoc-0.3.0/src/complydoc/sample/employee-record.pdf +0 -0
  96. complydoc-0.3.0/src/complydoc/sample/financial-summary.pdf +0 -0
  97. complydoc-0.3.0/src/complydoc/sample/invoice-scan.pdf +79 -0
  98. complydoc-0.3.0/src/complydoc/sample/supplier-list.docx +0 -0
  99. complydoc-0.3.0/src/complydoc/sample/supplier-onboarding.pdf +0 -0
  100. complydoc-0.3.0/src/complydoc/sample/terms-and-conditions.pdf +0 -0
  101. complydoc-0.3.0/src/complydoc/sampling.py +78 -0
  102. complydoc-0.3.0/src/complydoc/sensitive/__init__.py +0 -0
  103. complydoc-0.3.0/src/complydoc/sensitive/base.py +125 -0
  104. complydoc-0.3.0/src/complydoc/sensitive/detectors/__init__.py +0 -0
  105. complydoc-0.3.0/src/complydoc/sensitive/detectors/ner.py +113 -0
  106. complydoc-0.3.0/src/complydoc/sensitive/detectors/regex_detector.py +68 -0
  107. complydoc-0.3.0/src/complydoc/sensitive/masking.py +60 -0
  108. complydoc-0.3.0/src/complydoc/sensitive/registry.py +59 -0
  109. complydoc-0.3.0/src/complydoc/sensitive/scanner.py +224 -0
  110. complydoc-0.3.0/src/complydoc/sensitive/validators.py +313 -0
  111. complydoc-0.3.0/src/complydoc/skill/SKILL.md +122 -0
  112. complydoc-0.3.0/src/complydoc/skill/__init__.py +0 -0
  113. complydoc-0.3.0/src/complydoc/text.py +96 -0
  114. complydoc-0.3.0/src/complydoc/vendor/__init__.py +14 -0
  115. complydoc-0.3.0/src/complydoc/vendor/tiktoken_cache/9b5ad71b2ce5302211f9c61530b329a4922fc6a4 +100256 -0
  116. complydoc-0.3.0/src/complydoc/vendor/tiktoken_cache/fb374d419588a4632f3f557e76b4b70aebbca790 +199998 -0
  117. complydoc-0.3.0/src/complydoc/warm.py +44 -0
  118. complydoc-0.3.0/tests/__init__.py +0 -0
  119. complydoc-0.3.0/tests/conftest.py +36 -0
  120. complydoc-0.3.0/tests/fixtures/acroform.pdf +0 -0
  121. complydoc-0.3.0/tests/fixtures/broken.pdf +3 -0
  122. complydoc-0.3.0/tests/fixtures/dense_text.pdf +0 -0
  123. complydoc-0.3.0/tests/fixtures/encrypted.pdf +0 -0
  124. complydoc-0.3.0/tests/fixtures/garbled.pdf +0 -0
  125. complydoc-0.3.0/tests/fixtures/merged_header_table.pdf +0 -0
  126. complydoc-0.3.0/tests/fixtures/mixed_page_sizes.pdf +0 -0
  127. complydoc-0.3.0/tests/fixtures/native_text.pdf +0 -0
  128. complydoc-0.3.0/tests/fixtures/notes.txt +1 -0
  129. complydoc-0.3.0/tests/fixtures/rotated_scan.pdf +96 -0
  130. complydoc-0.3.0/tests/fixtures/sample.docx +0 -0
  131. complydoc-0.3.0/tests/fixtures/sample.xlsx +0 -0
  132. complydoc-0.3.0/tests/fixtures/scan_page.png +0 -0
  133. complydoc-0.3.0/tests/fixtures/scanned_page.pdf +79 -0
  134. complydoc-0.3.0/tests/fixtures/sensitive_sample.pdf +0 -0
  135. complydoc-0.3.0/tests/fixtures/two_column.pdf +0 -0
  136. complydoc-0.3.0/tests/fixtures/whitespace_table.pdf +0 -0
  137. complydoc-0.3.0/tests/generate_fixtures.py +568 -0
  138. complydoc-0.3.0/tests/helpers.py +22 -0
  139. complydoc-0.3.0/tests/test_charts.py +110 -0
  140. complydoc-0.3.0/tests/test_cli.py +387 -0
  141. complydoc-0.3.0/tests/test_config.py +124 -0
  142. complydoc-0.3.0/tests/test_cost.py +178 -0
  143. complydoc-0.3.0/tests/test_diffing.py +97 -0
  144. complydoc-0.3.0/tests/test_engines.py +92 -0
  145. complydoc-0.3.0/tests/test_extractors.py +260 -0
  146. complydoc-0.3.0/tests/test_ingest.py +161 -0
  147. complydoc-0.3.0/tests/test_limitations.py +131 -0
  148. complydoc-0.3.0/tests/test_offline_guard.py +59 -0
  149. complydoc-0.3.0/tests/test_overall.py +92 -0
  150. complydoc-0.3.0/tests/test_pageview.py +257 -0
  151. complydoc-0.3.0/tests/test_parallel.py +153 -0
  152. complydoc-0.3.0/tests/test_preview.py +317 -0
  153. complydoc-0.3.0/tests/test_price_table.py +230 -0
  154. complydoc-0.3.0/tests/test_pricing_import.py +209 -0
  155. complydoc-0.3.0/tests/test_progress.py +75 -0
  156. complydoc-0.3.0/tests/test_quickwins.py +83 -0
  157. complydoc-0.3.0/tests/test_readings.py +194 -0
  158. complydoc-0.3.0/tests/test_report.py +528 -0
  159. complydoc-0.3.0/tests/test_sampling.py +65 -0
  160. complydoc-0.3.0/tests/test_security_order.py +83 -0
  161. complydoc-0.3.0/tests/test_sensitive/__init__.py +0 -0
  162. complydoc-0.3.0/tests/test_sensitive/test_evidence.py +90 -0
  163. complydoc-0.3.0/tests/test_sensitive/test_masking.py +69 -0
  164. complydoc-0.3.0/tests/test_sensitive/test_scanner.py +154 -0
  165. complydoc-0.3.0/tests/test_sensitive/test_validators.py +161 -0
  166. complydoc-0.3.0/tests/test_signals/__init__.py +0 -0
  167. complydoc-0.3.0/tests/test_signals/test_awkward_documents.py +193 -0
  168. complydoc-0.3.0/tests/test_signals/test_ocr_confidence.py +38 -0
  169. complydoc-0.3.0/tests/test_signals/test_tables.py +63 -0
  170. complydoc-0.3.0/tests/test_timing.py +117 -0
  171. complydoc-0.3.0/tests/test_warm.py +40 -0
  172. complydoc-0.3.0/uv.lock +2420 -0
@@ -0,0 +1,148 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>complydoc — pipeline architecture</title>
7
+ <link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Geist:wght@400;500;600&family=Geist+Mono:wght@400;500;600&display=swap" rel="stylesheet">
8
+ <style>
9
+ body { margin:0; background:#22272e; color:#f5f5f5;
10
+ font-family:'Geist',sans-serif; padding:3rem 2rem; }
11
+ .wrap { max-width:1080px; margin:0 auto; }
12
+ .eyebrow { font-family:'Geist Mono',monospace; font-size:8px; letter-spacing:0.14em;
13
+ text-transform:uppercase; color:#8e98ac; margin:0 0 0.5rem; }
14
+ h1 { font-family:'Instrument Serif',serif; font-weight:400; font-size:1.75rem;
15
+ margin:0 0 0.25rem; }
16
+ .sub { color:#bfc0c0; font-size:0.875rem; margin:0 0 2rem; max-width:64ch; }
17
+ svg { width:100%; height:auto; display:block; }
18
+ </style>
19
+ </head>
20
+ <body>
21
+ <div class="wrap">
22
+ <p class="eyebrow">complydoc</p>
23
+ <h1>Pipeline</h1>
24
+ <p class="sub">Files are read locally by per-format loaders, then passed to three analysis
25
+ components that run independently. Each run writes a JSON report and an HTML report.</p>
26
+ <svg viewBox="0 0 1000 600" role="img" aria-labelledby="complydoc-architecture-dark-title complydoc-architecture-dark-desc" xmlns="http://www.w3.org/2000/svg">
27
+ <title id="complydoc-architecture-dark-title">complydoc pipeline architecture</title>
28
+ <desc id="complydoc-architecture-dark-desc">A folder of documents passes through discovery and a format-specific ingest layer into three independent analysis components — cost, difficulty and sensitive data — which are driven by YAML config and emit a diffable JSON report and a self-contained HTML report. The whole pipeline sits inside a network guard boundary, so no document content can leave the machine.</desc>
29
+ <defs>
30
+ <marker id="complydoc-architecture-dark-arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
31
+ <polygon points="0 0, 8 3, 0 6" fill="#bfc0c0"/>
32
+ </marker>
33
+ <marker id="complydoc-architecture-dark-arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
34
+ <polygon points="0 0, 8 3, 0 6" fill="#2fa96a"/>
35
+ </marker>
36
+ </defs>
37
+
38
+ <rect width="100%" height="100%" fill="#22272e"/>
39
+
40
+ <!-- Network guard boundary: drawn first, behind everything -->
41
+ <rect x="24" y="72" width="940" height="440" rx="8" fill="rgba(47,169,106,0.05)" stroke="rgba(47,169,106,0.60)" stroke-width="1" stroke-dasharray="4,4"/>
42
+ <rect x="44" y="64" width="96" height="16" rx="2" fill="#22272e"/>
43
+ <text x="52" y="76" fill="#2fa96a" font-size="8" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" letter-spacing="0.14em">NETWORK GUARD</text>
44
+
45
+ <!-- Analysis zone -->
46
+ <rect x="560" y="112" width="208" height="296" rx="8" fill="rgba(245,245,245,0.03)" stroke="rgba(245,245,245,0.12)" stroke-width="0.8"/>
47
+ <rect x="596" y="104" width="136" height="16" rx="2" fill="#22272e"/>
48
+ <text x="664" y="116" fill="rgba(245,245,245,0.45)" font-size="7" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle" letter-spacing="0.14em">ANALYSIS · INDEPENDENT</text>
49
+
50
+ <!-- Arrows, drawn before boxes -->
51
+ <line x1="184" y1="272" x2="216" y2="272" stroke="#bfc0c0" stroke-width="1.2" marker-end="url(#complydoc-architecture-dark-arrow)"/>
52
+ <line x1="352" y1="272" x2="384" y2="272" stroke="#bfc0c0" stroke-width="1.2" marker-end="url(#complydoc-architecture-dark-arrow)"/>
53
+
54
+ <path d="M 528,252 H 544 Q 552,252 552,244 V 184 Q 552,176 560,176 H 576" fill="none" stroke="#bfc0c0" stroke-width="1.2" marker-end="url(#complydoc-architecture-dark-arrow)"/>
55
+ <line x1="528" y1="272" x2="576" y2="272" stroke="#bfc0c0" stroke-width="1.2" marker-end="url(#complydoc-architecture-dark-arrow)"/>
56
+ <path d="M 528,292 H 544 Q 552,292 552,300 V 360 Q 552,368 560,368 H 576" fill="none" stroke="#bfc0c0" stroke-width="1.2" marker-end="url(#complydoc-architecture-dark-arrow)"/>
57
+
58
+ <line x1="664" y1="448" x2="664" y2="408" stroke="#bfc0c0" stroke-width="1.2" stroke-dasharray="4,3" marker-end="url(#complydoc-architecture-dark-arrow)"/>
59
+ <rect x="676" y="420" width="84" height="12" rx="2" fill="#22272e"/>
60
+ <text x="680" y="429" fill="#8e98ac" font-size="8" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" letter-spacing="0.06em">THRESHOLDS</text>
61
+
62
+ <line x1="768" y1="240" x2="804" y2="240" stroke="#bfc0c0" stroke-width="1.2" marker-end="url(#complydoc-architecture-dark-arrow)"/>
63
+ <path d="M 768,300 H 778 Q 786,300 786,308 V 328 Q 786,336 794,336 H 804" fill="none" stroke="#bfc0c0" stroke-width="1.2" marker-end="url(#complydoc-architecture-dark-arrow)"/>
64
+
65
+ <!-- Nodes -->
66
+
67
+ <rect x="48" y="240" width="136" height="64" rx="6" fill="#22272e"/>
68
+ <rect x="48" y="240" width="136" height="64" rx="6" fill="rgba(191,192,192,0.10)" stroke="#8e98ac" stroke-width="1"/>
69
+ <rect x="60" y="250" width="36" height="12" rx="2" fill="none" stroke="#8e98ac" stroke-opacity="0.40" stroke-width="0.8"/>
70
+ <text x="78.0" y="259" fill="#8e98ac" fill-opacity="0.85" font-size="7" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle" letter-spacing="0.08em">INPUT</text>
71
+ <text x="116.0" y="280.0" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', 'Helvetica Neue', Helvetica, Arial, sans-serif" text-anchor="middle">documents/</text>
72
+ <text x="116.0" y="296.0" fill="#8e98ac" font-size="9" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle">pdf · img · docx · xlsx</text>
73
+
74
+ <rect x="216" y="240" width="136" height="64" rx="6" fill="#22272e"/>
75
+ <rect x="216" y="240" width="136" height="64" rx="6" fill="#2c323b" stroke="#f5f5f5" stroke-width="1"/>
76
+ <rect x="228" y="250" width="32" height="12" rx="2" fill="none" stroke="#f5f5f5" stroke-opacity="0.40" stroke-width="0.8"/>
77
+ <text x="244.0" y="259" fill="#f5f5f5" fill-opacity="0.85" font-size="7" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle" letter-spacing="0.08em">WALK</text>
78
+ <text x="284.0" y="280.0" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', 'Helvetica Neue', Helvetica, Arial, sans-serif" text-anchor="middle">Discovery</text>
79
+ <text x="284.0" y="296.0" fill="#8e98ac" font-size="9" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle">skips unopenable</text>
80
+
81
+ <rect x="384" y="240" width="144" height="64" rx="6" fill="#22272e"/>
82
+ <rect x="384" y="240" width="144" height="64" rx="6" fill="#2c323b" stroke="#f5f5f5" stroke-width="1"/>
83
+ <rect x="396" y="250" width="32" height="12" rx="2" fill="none" stroke="#f5f5f5" stroke-opacity="0.40" stroke-width="0.8"/>
84
+ <text x="412.0" y="259" fill="#f5f5f5" fill-opacity="0.85" font-size="7" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle" letter-spacing="0.08em">LOAD</text>
85
+ <text x="456.0" y="280.0" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', 'Helvetica Neue', Helvetica, Arial, sans-serif" text-anchor="middle">Ingest</text>
86
+ <text x="456.0" y="296.0" fill="#8e98ac" font-size="9" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle">per-format loaders</text>
87
+
88
+ <rect x="576" y="144" width="176" height="64" rx="6" fill="#22272e"/>
89
+ <rect x="576" y="144" width="176" height="64" rx="6" fill="#2c323b" stroke="#f5f5f5" stroke-width="1"/>
90
+ <rect x="588" y="154" width="20" height="12" rx="2" fill="none" stroke="#f5f5f5" stroke-opacity="0.40" stroke-width="0.8"/>
91
+ <text x="598.0" y="163" fill="#f5f5f5" fill-opacity="0.85" font-size="7" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle" letter-spacing="0.08em">01</text>
92
+ <text x="664.0" y="184.0" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', 'Helvetica Neue', Helvetica, Arial, sans-serif" text-anchor="middle">Cost</text>
93
+ <text x="664.0" y="200.0" fill="#8e98ac" font-size="9" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle">tokens, pages, price</text>
94
+
95
+ <rect x="576" y="240" width="176" height="64" rx="6" fill="#22272e"/>
96
+ <rect x="576" y="240" width="176" height="64" rx="6" fill="#2c323b" stroke="#f5f5f5" stroke-width="1"/>
97
+ <rect x="588" y="250" width="20" height="12" rx="2" fill="none" stroke="#f5f5f5" stroke-opacity="0.40" stroke-width="0.8"/>
98
+ <text x="598.0" y="259" fill="#f5f5f5" fill-opacity="0.85" font-size="7" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle" letter-spacing="0.08em">02</text>
99
+ <text x="664.0" y="280.0" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', 'Helvetica Neue', Helvetica, Arial, sans-serif" text-anchor="middle">Difficulty</text>
100
+ <text x="664.0" y="296.0" fill="#8e98ac" font-size="9" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle">18 measured signals</text>
101
+
102
+ <rect x="576" y="336" width="176" height="64" rx="6" fill="#22272e"/>
103
+ <rect x="576" y="336" width="176" height="64" rx="6" fill="rgba(47,169,106,0.14)" stroke="#2fa96a" stroke-width="1"/>
104
+ <rect x="588" y="346" width="20" height="12" rx="2" fill="none" stroke="#2fa96a" stroke-opacity="0.40" stroke-width="0.8"/>
105
+ <text x="598.0" y="355" fill="#2fa96a" fill-opacity="0.85" font-size="7" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle" letter-spacing="0.08em">03</text>
106
+ <text x="664.0" y="376.0" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', 'Helvetica Neue', Helvetica, Arial, sans-serif" text-anchor="middle">Sensitive</text>
107
+ <text x="664.0" y="392.0" fill="#8e98ac" font-size="9" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle">masked by default</text>
108
+
109
+ <rect x="576" y="448" width="176" height="52" rx="6" fill="#22272e"/>
110
+ <rect x="576" y="448" width="176" height="52" rx="6" fill="rgba(245,245,245,0.06)" stroke="#bfc0c0" stroke-width="1"/>
111
+ <rect x="588" y="458" width="32" height="12" rx="2" fill="none" stroke="#bfc0c0" stroke-opacity="0.40" stroke-width="0.8"/>
112
+ <text x="604.0" y="467" fill="#bfc0c0" fill-opacity="0.85" font-size="7" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle" letter-spacing="0.08em">YAML</text>
113
+ <text x="664.0" y="482.0" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', 'Helvetica Neue', Helvetica, Arial, sans-serif" text-anchor="middle">Config</text>
114
+ <text x="664.0" y="498.0" fill="#8e98ac" font-size="9" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle">prices · weights · patterns</text>
115
+
116
+ <rect x="804" y="208" width="136" height="64" rx="6" fill="#22272e"/>
117
+ <rect x="804" y="208" width="136" height="64" rx="6" fill="rgba(245,245,245,0.06)" stroke="#bfc0c0" stroke-width="1"/>
118
+ <rect x="816" y="218" width="32" height="12" rx="2" fill="none" stroke="#bfc0c0" stroke-opacity="0.40" stroke-width="0.8"/>
119
+ <text x="832.0" y="227" fill="#bfc0c0" fill-opacity="0.85" font-size="7" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle" letter-spacing="0.08em">JSON</text>
120
+ <text x="872.0" y="248.0" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', 'Helvetica Neue', Helvetica, Arial, sans-serif" text-anchor="middle">report.json</text>
121
+ <text x="872.0" y="264.0" fill="#8e98ac" font-size="9" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle">machine readable</text>
122
+
123
+ <rect x="804" y="304" width="136" height="64" rx="6" fill="#22272e"/>
124
+ <rect x="804" y="304" width="136" height="64" rx="6" fill="rgba(245,245,245,0.06)" stroke="#bfc0c0" stroke-width="1"/>
125
+ <rect x="816" y="314" width="32" height="12" rx="2" fill="none" stroke="#bfc0c0" stroke-opacity="0.40" stroke-width="0.8"/>
126
+ <text x="832.0" y="323" fill="#bfc0c0" fill-opacity="0.85" font-size="7" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle" letter-spacing="0.08em">HTML</text>
127
+ <text x="872.0" y="344.0" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', 'Helvetica Neue', Helvetica, Arial, sans-serif" text-anchor="middle">report.html</text>
128
+ <text x="872.0" y="360.0" fill="#8e98ac" font-size="9" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle">self-contained</text>
129
+
130
+ <!-- Legend -->
131
+ <line x1="24" y1="544" x2="976" y2="544" stroke="rgba(245,245,245,0.14)" stroke-width="0.8"/>
132
+ <text x="24" y="566" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" letter-spacing="0.14em">LEGEND</text>
133
+
134
+ <rect x="112" y="556" width="14" height="12" rx="2" fill="rgba(47,169,106,0.14)" stroke="#2fa96a" stroke-width="1"/>
135
+ <text x="134" y="566" fill="#8e98ac" font-size="8" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace">MASKED VALUES</text>
136
+
137
+ <rect x="356" y="556" width="14" height="12" rx="2" fill="rgba(47,169,106,0.05)" stroke="rgba(47,169,106,0.60)" stroke-width="1" stroke-dasharray="3,3"/>
138
+ <text x="378" y="566" fill="#8e98ac" font-size="8" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace">NO OUTBOUND SOCKET</text>
139
+
140
+ <rect x="592" y="556" width="14" height="12" rx="2" fill="#2c323b" stroke="#f5f5f5" stroke-width="1"/>
141
+ <text x="614" y="566" fill="#8e98ac" font-size="8" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace">PIPELINE STAGE</text>
142
+
143
+ <rect x="792" y="556" width="14" height="12" rx="2" fill="rgba(245,245,245,0.06)" stroke="#bfc0c0" stroke-width="1"/>
144
+ <text x="814" y="566" fill="#8e98ac" font-size="8" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace">CONFIG AND OUTPUT</text>
145
+ </svg>
146
+ </div>
147
+ </body>
148
+ </html>
@@ -0,0 +1,123 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg viewBox="0 0 1000 600" role="img" aria-labelledby="complydoc-architecture-dark-title complydoc-architecture-dark-desc" xmlns="http://www.w3.org/2000/svg">
3
+ <title id="complydoc-architecture-dark-title">complydoc pipeline architecture</title>
4
+ <desc id="complydoc-architecture-dark-desc">A folder of documents passes through discovery and a format-specific ingest layer into three independent analysis components — cost, difficulty and sensitive data — which are driven by YAML config and emit a diffable JSON report and a self-contained HTML report. The whole pipeline sits inside a network guard boundary, so no document content can leave the machine.</desc>
5
+ <defs>
6
+ <style>@import url('https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&amp;family=Geist:wght@400;500;600&amp;family=Geist+Mono:wght@400;500;600&amp;display=swap');</style>
7
+
8
+ <marker id="complydoc-architecture-dark-arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
9
+ <polygon points="0 0, 8 3, 0 6" fill="#bfc0c0"/>
10
+ </marker>
11
+ <marker id="complydoc-architecture-dark-arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
12
+ <polygon points="0 0, 8 3, 0 6" fill="#2fa96a"/>
13
+ </marker>
14
+ </defs>
15
+
16
+ <rect width="100%" height="100%" fill="#22272e"/>
17
+
18
+ <!-- Network guard boundary: drawn first, behind everything -->
19
+ <rect x="24" y="72" width="940" height="440" rx="8" fill="rgba(47,169,106,0.05)" stroke="rgba(47,169,106,0.60)" stroke-width="1" stroke-dasharray="4,4"/>
20
+ <rect x="44" y="64" width="96" height="16" rx="2" fill="#22272e"/>
21
+ <text x="52" y="76" fill="#2fa96a" font-size="8" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" letter-spacing="0.14em">NETWORK GUARD</text>
22
+
23
+ <!-- Analysis zone -->
24
+ <rect x="560" y="112" width="208" height="296" rx="8" fill="rgba(245,245,245,0.03)" stroke="rgba(245,245,245,0.12)" stroke-width="0.8"/>
25
+ <rect x="596" y="104" width="136" height="16" rx="2" fill="#22272e"/>
26
+ <text x="664" y="116" fill="rgba(245,245,245,0.45)" font-size="7" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle" letter-spacing="0.14em">ANALYSIS · INDEPENDENT</text>
27
+
28
+ <!-- Arrows, drawn before boxes -->
29
+ <line x1="184" y1="272" x2="216" y2="272" stroke="#bfc0c0" stroke-width="1.2" marker-end="url(#complydoc-architecture-dark-arrow)"/>
30
+ <line x1="352" y1="272" x2="384" y2="272" stroke="#bfc0c0" stroke-width="1.2" marker-end="url(#complydoc-architecture-dark-arrow)"/>
31
+
32
+ <path d="M 528,252 H 544 Q 552,252 552,244 V 184 Q 552,176 560,176 H 576" fill="none" stroke="#bfc0c0" stroke-width="1.2" marker-end="url(#complydoc-architecture-dark-arrow)"/>
33
+ <line x1="528" y1="272" x2="576" y2="272" stroke="#bfc0c0" stroke-width="1.2" marker-end="url(#complydoc-architecture-dark-arrow)"/>
34
+ <path d="M 528,292 H 544 Q 552,292 552,300 V 360 Q 552,368 560,368 H 576" fill="none" stroke="#bfc0c0" stroke-width="1.2" marker-end="url(#complydoc-architecture-dark-arrow)"/>
35
+
36
+ <line x1="664" y1="448" x2="664" y2="408" stroke="#bfc0c0" stroke-width="1.2" stroke-dasharray="4,3" marker-end="url(#complydoc-architecture-dark-arrow)"/>
37
+ <rect x="676" y="420" width="84" height="12" rx="2" fill="#22272e"/>
38
+ <text x="680" y="429" fill="#8e98ac" font-size="8" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" letter-spacing="0.06em">THRESHOLDS</text>
39
+
40
+ <line x1="768" y1="240" x2="804" y2="240" stroke="#bfc0c0" stroke-width="1.2" marker-end="url(#complydoc-architecture-dark-arrow)"/>
41
+ <path d="M 768,300 H 778 Q 786,300 786,308 V 328 Q 786,336 794,336 H 804" fill="none" stroke="#bfc0c0" stroke-width="1.2" marker-end="url(#complydoc-architecture-dark-arrow)"/>
42
+
43
+ <!-- Nodes -->
44
+
45
+ <rect x="48" y="240" width="136" height="64" rx="6" fill="#22272e"/>
46
+ <rect x="48" y="240" width="136" height="64" rx="6" fill="rgba(191,192,192,0.10)" stroke="#8e98ac" stroke-width="1"/>
47
+ <rect x="60" y="250" width="36" height="12" rx="2" fill="none" stroke="#8e98ac" stroke-opacity="0.40" stroke-width="0.8"/>
48
+ <text x="78.0" y="259" fill="#8e98ac" fill-opacity="0.85" font-size="7" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle" letter-spacing="0.08em">INPUT</text>
49
+ <text x="116.0" y="280.0" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', 'Helvetica Neue', Helvetica, Arial, sans-serif" text-anchor="middle">documents/</text>
50
+ <text x="116.0" y="296.0" fill="#8e98ac" font-size="9" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle">pdf · img · docx · xlsx</text>
51
+
52
+ <rect x="216" y="240" width="136" height="64" rx="6" fill="#22272e"/>
53
+ <rect x="216" y="240" width="136" height="64" rx="6" fill="#2c323b" stroke="#f5f5f5" stroke-width="1"/>
54
+ <rect x="228" y="250" width="32" height="12" rx="2" fill="none" stroke="#f5f5f5" stroke-opacity="0.40" stroke-width="0.8"/>
55
+ <text x="244.0" y="259" fill="#f5f5f5" fill-opacity="0.85" font-size="7" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle" letter-spacing="0.08em">WALK</text>
56
+ <text x="284.0" y="280.0" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', 'Helvetica Neue', Helvetica, Arial, sans-serif" text-anchor="middle">Discovery</text>
57
+ <text x="284.0" y="296.0" fill="#8e98ac" font-size="9" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle">skips unopenable</text>
58
+
59
+ <rect x="384" y="240" width="144" height="64" rx="6" fill="#22272e"/>
60
+ <rect x="384" y="240" width="144" height="64" rx="6" fill="#2c323b" stroke="#f5f5f5" stroke-width="1"/>
61
+ <rect x="396" y="250" width="32" height="12" rx="2" fill="none" stroke="#f5f5f5" stroke-opacity="0.40" stroke-width="0.8"/>
62
+ <text x="412.0" y="259" fill="#f5f5f5" fill-opacity="0.85" font-size="7" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle" letter-spacing="0.08em">LOAD</text>
63
+ <text x="456.0" y="280.0" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', 'Helvetica Neue', Helvetica, Arial, sans-serif" text-anchor="middle">Ingest</text>
64
+ <text x="456.0" y="296.0" fill="#8e98ac" font-size="9" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle">per-format loaders</text>
65
+
66
+ <rect x="576" y="144" width="176" height="64" rx="6" fill="#22272e"/>
67
+ <rect x="576" y="144" width="176" height="64" rx="6" fill="#2c323b" stroke="#f5f5f5" stroke-width="1"/>
68
+ <rect x="588" y="154" width="20" height="12" rx="2" fill="none" stroke="#f5f5f5" stroke-opacity="0.40" stroke-width="0.8"/>
69
+ <text x="598.0" y="163" fill="#f5f5f5" fill-opacity="0.85" font-size="7" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle" letter-spacing="0.08em">01</text>
70
+ <text x="664.0" y="184.0" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', 'Helvetica Neue', Helvetica, Arial, sans-serif" text-anchor="middle">Cost</text>
71
+ <text x="664.0" y="200.0" fill="#8e98ac" font-size="9" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle">tokens, pages, price</text>
72
+
73
+ <rect x="576" y="240" width="176" height="64" rx="6" fill="#22272e"/>
74
+ <rect x="576" y="240" width="176" height="64" rx="6" fill="#2c323b" stroke="#f5f5f5" stroke-width="1"/>
75
+ <rect x="588" y="250" width="20" height="12" rx="2" fill="none" stroke="#f5f5f5" stroke-opacity="0.40" stroke-width="0.8"/>
76
+ <text x="598.0" y="259" fill="#f5f5f5" fill-opacity="0.85" font-size="7" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle" letter-spacing="0.08em">02</text>
77
+ <text x="664.0" y="280.0" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', 'Helvetica Neue', Helvetica, Arial, sans-serif" text-anchor="middle">Difficulty</text>
78
+ <text x="664.0" y="296.0" fill="#8e98ac" font-size="9" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle">18 measured signals</text>
79
+
80
+ <rect x="576" y="336" width="176" height="64" rx="6" fill="#22272e"/>
81
+ <rect x="576" y="336" width="176" height="64" rx="6" fill="rgba(47,169,106,0.14)" stroke="#2fa96a" stroke-width="1"/>
82
+ <rect x="588" y="346" width="20" height="12" rx="2" fill="none" stroke="#2fa96a" stroke-opacity="0.40" stroke-width="0.8"/>
83
+ <text x="598.0" y="355" fill="#2fa96a" fill-opacity="0.85" font-size="7" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle" letter-spacing="0.08em">03</text>
84
+ <text x="664.0" y="376.0" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', 'Helvetica Neue', Helvetica, Arial, sans-serif" text-anchor="middle">Sensitive</text>
85
+ <text x="664.0" y="392.0" fill="#8e98ac" font-size="9" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle">masked by default</text>
86
+
87
+ <rect x="576" y="448" width="176" height="52" rx="6" fill="#22272e"/>
88
+ <rect x="576" y="448" width="176" height="52" rx="6" fill="rgba(245,245,245,0.06)" stroke="#bfc0c0" stroke-width="1"/>
89
+ <rect x="588" y="458" width="32" height="12" rx="2" fill="none" stroke="#bfc0c0" stroke-opacity="0.40" stroke-width="0.8"/>
90
+ <text x="604.0" y="467" fill="#bfc0c0" fill-opacity="0.85" font-size="7" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle" letter-spacing="0.08em">YAML</text>
91
+ <text x="664.0" y="482.0" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', 'Helvetica Neue', Helvetica, Arial, sans-serif" text-anchor="middle">Config</text>
92
+ <text x="664.0" y="498.0" fill="#8e98ac" font-size="9" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle">prices · weights · patterns</text>
93
+
94
+ <rect x="804" y="208" width="136" height="64" rx="6" fill="#22272e"/>
95
+ <rect x="804" y="208" width="136" height="64" rx="6" fill="rgba(245,245,245,0.06)" stroke="#bfc0c0" stroke-width="1"/>
96
+ <rect x="816" y="218" width="32" height="12" rx="2" fill="none" stroke="#bfc0c0" stroke-opacity="0.40" stroke-width="0.8"/>
97
+ <text x="832.0" y="227" fill="#bfc0c0" fill-opacity="0.85" font-size="7" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle" letter-spacing="0.08em">JSON</text>
98
+ <text x="872.0" y="248.0" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', 'Helvetica Neue', Helvetica, Arial, sans-serif" text-anchor="middle">report.json</text>
99
+ <text x="872.0" y="264.0" fill="#8e98ac" font-size="9" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle">machine readable</text>
100
+
101
+ <rect x="804" y="304" width="136" height="64" rx="6" fill="#22272e"/>
102
+ <rect x="804" y="304" width="136" height="64" rx="6" fill="rgba(245,245,245,0.06)" stroke="#bfc0c0" stroke-width="1"/>
103
+ <rect x="816" y="314" width="32" height="12" rx="2" fill="none" stroke="#bfc0c0" stroke-opacity="0.40" stroke-width="0.8"/>
104
+ <text x="832.0" y="323" fill="#bfc0c0" fill-opacity="0.85" font-size="7" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle" letter-spacing="0.08em">HTML</text>
105
+ <text x="872.0" y="344.0" fill="#f5f5f5" font-size="12" font-weight="600" font-family="'Geist', 'Helvetica Neue', Helvetica, Arial, sans-serif" text-anchor="middle">report.html</text>
106
+ <text x="872.0" y="360.0" fill="#8e98ac" font-size="9" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle">self-contained</text>
107
+
108
+ <!-- Legend -->
109
+ <line x1="24" y1="544" x2="976" y2="544" stroke="rgba(245,245,245,0.14)" stroke-width="0.8"/>
110
+ <text x="24" y="566" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" letter-spacing="0.14em">LEGEND</text>
111
+
112
+ <rect x="112" y="556" width="14" height="12" rx="2" fill="rgba(47,169,106,0.14)" stroke="#2fa96a" stroke-width="1"/>
113
+ <text x="134" y="566" fill="#8e98ac" font-size="8" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace">MASKED VALUES</text>
114
+
115
+ <rect x="356" y="556" width="14" height="12" rx="2" fill="rgba(47,169,106,0.05)" stroke="rgba(47,169,106,0.60)" stroke-width="1" stroke-dasharray="3,3"/>
116
+ <text x="378" y="566" fill="#8e98ac" font-size="8" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace">NO OUTBOUND SOCKET</text>
117
+
118
+ <rect x="592" y="556" width="14" height="12" rx="2" fill="#2c323b" stroke="#f5f5f5" stroke-width="1"/>
119
+ <text x="614" y="566" fill="#8e98ac" font-size="8" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace">PIPELINE STAGE</text>
120
+
121
+ <rect x="792" y="556" width="14" height="12" rx="2" fill="rgba(245,245,245,0.06)" stroke="#bfc0c0" stroke-width="1"/>
122
+ <text x="814" y="566" fill="#8e98ac" font-size="8" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace">CONFIG AND OUTPUT</text>
123
+ </svg>
@@ -0,0 +1,148 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>complydoc — pipeline architecture</title>
7
+ <link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Geist:wght@400;500;600&family=Geist+Mono:wght@400;500;600&display=swap" rel="stylesheet">
8
+ <style>
9
+ body { margin:0; background:#f5f5f5; color:#22272e;
10
+ font-family:'Geist',sans-serif; padding:3rem 2rem; }
11
+ .wrap { max-width:1080px; margin:0 auto; }
12
+ .eyebrow { font-family:'Geist Mono',monospace; font-size:8px; letter-spacing:0.14em;
13
+ text-transform:uppercase; color:#7a8399; margin:0 0 0.5rem; }
14
+ h1 { font-family:'Instrument Serif',serif; font-weight:400; font-size:1.75rem;
15
+ margin:0 0 0.25rem; }
16
+ .sub { color:#4f5d75; font-size:0.875rem; margin:0 0 2rem; max-width:64ch; }
17
+ svg { width:100%; height:auto; display:block; }
18
+ </style>
19
+ </head>
20
+ <body>
21
+ <div class="wrap">
22
+ <p class="eyebrow">complydoc</p>
23
+ <h1>Pipeline</h1>
24
+ <p class="sub">Files are read locally by per-format loaders, then passed to three analysis
25
+ components that run independently. Each run writes a JSON report and an HTML report.</p>
26
+ <svg viewBox="0 0 1000 600" role="img" aria-labelledby="complydoc-architecture-title complydoc-architecture-desc" xmlns="http://www.w3.org/2000/svg">
27
+ <title id="complydoc-architecture-title">complydoc pipeline architecture</title>
28
+ <desc id="complydoc-architecture-desc">A folder of documents passes through discovery and a format-specific ingest layer into three independent analysis components — cost, difficulty and sensitive data — which are driven by YAML config and emit a diffable JSON report and a self-contained HTML report. The whole pipeline sits inside a network guard boundary, so no document content can leave the machine.</desc>
29
+ <defs>
30
+ <marker id="complydoc-architecture-arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
31
+ <polygon points="0 0, 8 3, 0 6" fill="#4f5d75"/>
32
+ </marker>
33
+ <marker id="complydoc-architecture-arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
34
+ <polygon points="0 0, 8 3, 0 6" fill="#1a7f4b"/>
35
+ </marker>
36
+ </defs>
37
+
38
+ <rect width="100%" height="100%" fill="#f5f5f5"/>
39
+
40
+ <!-- Network guard boundary: drawn first, behind everything -->
41
+ <rect x="24" y="72" width="940" height="440" rx="8" fill="rgba(26,127,75,0.04)" stroke="rgba(26,127,75,0.55)" stroke-width="1" stroke-dasharray="4,4"/>
42
+ <rect x="44" y="64" width="96" height="16" rx="2" fill="#f5f5f5"/>
43
+ <text x="52" y="76" fill="#1a7f4b" font-size="8" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" letter-spacing="0.14em">NETWORK GUARD</text>
44
+
45
+ <!-- Analysis zone -->
46
+ <rect x="560" y="112" width="208" height="296" rx="8" fill="rgba(34,39,46,0.02)" stroke="rgba(34,39,46,0.10)" stroke-width="0.8"/>
47
+ <rect x="596" y="104" width="136" height="16" rx="2" fill="#f5f5f5"/>
48
+ <text x="664" y="116" fill="rgba(34,39,46,0.40)" font-size="7" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle" letter-spacing="0.14em">ANALYSIS · INDEPENDENT</text>
49
+
50
+ <!-- Arrows, drawn before boxes -->
51
+ <line x1="184" y1="272" x2="216" y2="272" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#complydoc-architecture-arrow)"/>
52
+ <line x1="352" y1="272" x2="384" y2="272" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#complydoc-architecture-arrow)"/>
53
+
54
+ <path d="M 528,252 H 544 Q 552,252 552,244 V 184 Q 552,176 560,176 H 576" fill="none" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#complydoc-architecture-arrow)"/>
55
+ <line x1="528" y1="272" x2="576" y2="272" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#complydoc-architecture-arrow)"/>
56
+ <path d="M 528,292 H 544 Q 552,292 552,300 V 360 Q 552,368 560,368 H 576" fill="none" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#complydoc-architecture-arrow)"/>
57
+
58
+ <line x1="664" y1="448" x2="664" y2="408" stroke="#4f5d75" stroke-width="1.2" stroke-dasharray="4,3" marker-end="url(#complydoc-architecture-arrow)"/>
59
+ <rect x="676" y="420" width="84" height="12" rx="2" fill="#f5f5f5"/>
60
+ <text x="680" y="429" fill="#7a8399" font-size="8" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" letter-spacing="0.06em">THRESHOLDS</text>
61
+
62
+ <line x1="768" y1="240" x2="804" y2="240" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#complydoc-architecture-arrow)"/>
63
+ <path d="M 768,300 H 778 Q 786,300 786,308 V 328 Q 786,336 794,336 H 804" fill="none" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#complydoc-architecture-arrow)"/>
64
+
65
+ <!-- Nodes -->
66
+
67
+ <rect x="48" y="240" width="136" height="64" rx="6" fill="#f5f5f5"/>
68
+ <rect x="48" y="240" width="136" height="64" rx="6" fill="rgba(79,93,117,0.10)" stroke="#7a8399" stroke-width="1"/>
69
+ <rect x="60" y="250" width="36" height="12" rx="2" fill="none" stroke="#7a8399" stroke-opacity="0.40" stroke-width="0.8"/>
70
+ <text x="78.0" y="259" fill="#7a8399" fill-opacity="0.85" font-size="7" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle" letter-spacing="0.08em">INPUT</text>
71
+ <text x="116.0" y="280.0" fill="#22272e" font-size="12" font-weight="600" font-family="'Geist', 'Helvetica Neue', Helvetica, Arial, sans-serif" text-anchor="middle">documents/</text>
72
+ <text x="116.0" y="296.0" fill="#7a8399" font-size="9" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle">pdf · img · docx · xlsx</text>
73
+
74
+ <rect x="216" y="240" width="136" height="64" rx="6" fill="#f5f5f5"/>
75
+ <rect x="216" y="240" width="136" height="64" rx="6" fill="#ffffff" stroke="#22272e" stroke-width="1"/>
76
+ <rect x="228" y="250" width="32" height="12" rx="2" fill="none" stroke="#22272e" stroke-opacity="0.40" stroke-width="0.8"/>
77
+ <text x="244.0" y="259" fill="#22272e" fill-opacity="0.85" font-size="7" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle" letter-spacing="0.08em">WALK</text>
78
+ <text x="284.0" y="280.0" fill="#22272e" font-size="12" font-weight="600" font-family="'Geist', 'Helvetica Neue', Helvetica, Arial, sans-serif" text-anchor="middle">Discovery</text>
79
+ <text x="284.0" y="296.0" fill="#7a8399" font-size="9" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle">skips unopenable</text>
80
+
81
+ <rect x="384" y="240" width="144" height="64" rx="6" fill="#f5f5f5"/>
82
+ <rect x="384" y="240" width="144" height="64" rx="6" fill="#ffffff" stroke="#22272e" stroke-width="1"/>
83
+ <rect x="396" y="250" width="32" height="12" rx="2" fill="none" stroke="#22272e" stroke-opacity="0.40" stroke-width="0.8"/>
84
+ <text x="412.0" y="259" fill="#22272e" fill-opacity="0.85" font-size="7" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle" letter-spacing="0.08em">LOAD</text>
85
+ <text x="456.0" y="280.0" fill="#22272e" font-size="12" font-weight="600" font-family="'Geist', 'Helvetica Neue', Helvetica, Arial, sans-serif" text-anchor="middle">Ingest</text>
86
+ <text x="456.0" y="296.0" fill="#7a8399" font-size="9" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle">per-format loaders</text>
87
+
88
+ <rect x="576" y="144" width="176" height="64" rx="6" fill="#f5f5f5"/>
89
+ <rect x="576" y="144" width="176" height="64" rx="6" fill="#ffffff" stroke="#22272e" stroke-width="1"/>
90
+ <rect x="588" y="154" width="20" height="12" rx="2" fill="none" stroke="#22272e" stroke-opacity="0.40" stroke-width="0.8"/>
91
+ <text x="598.0" y="163" fill="#22272e" fill-opacity="0.85" font-size="7" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle" letter-spacing="0.08em">01</text>
92
+ <text x="664.0" y="184.0" fill="#22272e" font-size="12" font-weight="600" font-family="'Geist', 'Helvetica Neue', Helvetica, Arial, sans-serif" text-anchor="middle">Cost</text>
93
+ <text x="664.0" y="200.0" fill="#7a8399" font-size="9" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle">tokens, pages, price</text>
94
+
95
+ <rect x="576" y="240" width="176" height="64" rx="6" fill="#f5f5f5"/>
96
+ <rect x="576" y="240" width="176" height="64" rx="6" fill="#ffffff" stroke="#22272e" stroke-width="1"/>
97
+ <rect x="588" y="250" width="20" height="12" rx="2" fill="none" stroke="#22272e" stroke-opacity="0.40" stroke-width="0.8"/>
98
+ <text x="598.0" y="259" fill="#22272e" fill-opacity="0.85" font-size="7" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle" letter-spacing="0.08em">02</text>
99
+ <text x="664.0" y="280.0" fill="#22272e" font-size="12" font-weight="600" font-family="'Geist', 'Helvetica Neue', Helvetica, Arial, sans-serif" text-anchor="middle">Difficulty</text>
100
+ <text x="664.0" y="296.0" fill="#7a8399" font-size="9" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle">18 measured signals</text>
101
+
102
+ <rect x="576" y="336" width="176" height="64" rx="6" fill="#f5f5f5"/>
103
+ <rect x="576" y="336" width="176" height="64" rx="6" fill="rgba(26,127,75,0.08)" stroke="#1a7f4b" stroke-width="1"/>
104
+ <rect x="588" y="346" width="20" height="12" rx="2" fill="none" stroke="#1a7f4b" stroke-opacity="0.40" stroke-width="0.8"/>
105
+ <text x="598.0" y="355" fill="#1a7f4b" fill-opacity="0.85" font-size="7" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle" letter-spacing="0.08em">03</text>
106
+ <text x="664.0" y="376.0" fill="#22272e" font-size="12" font-weight="600" font-family="'Geist', 'Helvetica Neue', Helvetica, Arial, sans-serif" text-anchor="middle">Sensitive</text>
107
+ <text x="664.0" y="392.0" fill="#7a8399" font-size="9" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle">masked by default</text>
108
+
109
+ <rect x="576" y="448" width="176" height="52" rx="6" fill="#f5f5f5"/>
110
+ <rect x="576" y="448" width="176" height="52" rx="6" fill="rgba(34,39,46,0.05)" stroke="#4f5d75" stroke-width="1"/>
111
+ <rect x="588" y="458" width="32" height="12" rx="2" fill="none" stroke="#4f5d75" stroke-opacity="0.40" stroke-width="0.8"/>
112
+ <text x="604.0" y="467" fill="#4f5d75" fill-opacity="0.85" font-size="7" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle" letter-spacing="0.08em">YAML</text>
113
+ <text x="664.0" y="482.0" fill="#22272e" font-size="12" font-weight="600" font-family="'Geist', 'Helvetica Neue', Helvetica, Arial, sans-serif" text-anchor="middle">Config</text>
114
+ <text x="664.0" y="498.0" fill="#7a8399" font-size="9" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle">prices · weights · patterns</text>
115
+
116
+ <rect x="804" y="208" width="136" height="64" rx="6" fill="#f5f5f5"/>
117
+ <rect x="804" y="208" width="136" height="64" rx="6" fill="rgba(34,39,46,0.05)" stroke="#4f5d75" stroke-width="1"/>
118
+ <rect x="816" y="218" width="32" height="12" rx="2" fill="none" stroke="#4f5d75" stroke-opacity="0.40" stroke-width="0.8"/>
119
+ <text x="832.0" y="227" fill="#4f5d75" fill-opacity="0.85" font-size="7" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle" letter-spacing="0.08em">JSON</text>
120
+ <text x="872.0" y="248.0" fill="#22272e" font-size="12" font-weight="600" font-family="'Geist', 'Helvetica Neue', Helvetica, Arial, sans-serif" text-anchor="middle">report.json</text>
121
+ <text x="872.0" y="264.0" fill="#7a8399" font-size="9" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle">machine readable</text>
122
+
123
+ <rect x="804" y="304" width="136" height="64" rx="6" fill="#f5f5f5"/>
124
+ <rect x="804" y="304" width="136" height="64" rx="6" fill="rgba(34,39,46,0.05)" stroke="#4f5d75" stroke-width="1"/>
125
+ <rect x="816" y="314" width="32" height="12" rx="2" fill="none" stroke="#4f5d75" stroke-opacity="0.40" stroke-width="0.8"/>
126
+ <text x="832.0" y="323" fill="#4f5d75" fill-opacity="0.85" font-size="7" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle" letter-spacing="0.08em">HTML</text>
127
+ <text x="872.0" y="344.0" fill="#22272e" font-size="12" font-weight="600" font-family="'Geist', 'Helvetica Neue', Helvetica, Arial, sans-serif" text-anchor="middle">report.html</text>
128
+ <text x="872.0" y="360.0" fill="#7a8399" font-size="9" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" text-anchor="middle">self-contained</text>
129
+
130
+ <!-- Legend -->
131
+ <line x1="24" y1="544" x2="976" y2="544" stroke="rgba(34,39,46,0.12)" stroke-width="0.8"/>
132
+ <text x="24" y="566" fill="#4f5d75" font-size="8" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace" letter-spacing="0.14em">LEGEND</text>
133
+
134
+ <rect x="112" y="556" width="14" height="12" rx="2" fill="rgba(26,127,75,0.08)" stroke="#1a7f4b" stroke-width="1"/>
135
+ <text x="134" y="566" fill="#7a8399" font-size="8" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace">MASKED VALUES</text>
136
+
137
+ <rect x="356" y="556" width="14" height="12" rx="2" fill="rgba(26,127,75,0.04)" stroke="rgba(26,127,75,0.55)" stroke-width="1" stroke-dasharray="3,3"/>
138
+ <text x="378" y="566" fill="#7a8399" font-size="8" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace">NO OUTBOUND SOCKET</text>
139
+
140
+ <rect x="592" y="556" width="14" height="12" rx="2" fill="#ffffff" stroke="#22272e" stroke-width="1"/>
141
+ <text x="614" y="566" fill="#7a8399" font-size="8" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace">PIPELINE STAGE</text>
142
+
143
+ <rect x="792" y="556" width="14" height="12" rx="2" fill="rgba(34,39,46,0.05)" stroke="#4f5d75" stroke-width="1"/>
144
+ <text x="814" y="566" fill="#7a8399" font-size="8" font-family="'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace">CONFIG AND OUTPUT</text>
145
+ </svg>
146
+ </div>
147
+ </body>
148
+ </html>