tracecite 0.0.2__tar.gz → 0.0.4__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 (97) hide show
  1. tracecite-0.0.4/PKG-INFO +286 -0
  2. tracecite-0.0.4/README.md +257 -0
  3. {tracecite-0.0.2 → tracecite-0.0.4}/pyproject.toml +24 -9
  4. tracecite-0.0.4/src/tracecite/__init__.py +5 -0
  5. tracecite-0.0.4/src/tracecite/cli.py +222 -0
  6. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/evidence/chunking.py +63 -19
  7. tracecite-0.0.4/src/tracecite/evidence/commands.py +729 -0
  8. tracecite-0.0.4/src/tracecite/evidence/embedding.py +100 -0
  9. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/evidence/manifest.py +17 -8
  10. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/evidence/page_extraction.py +14 -17
  11. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/evidence/page_output.py +2 -3
  12. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/evidence/page_selection.py +21 -46
  13. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/evidence/parsers/base.py +14 -0
  14. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/evidence/parsers/markdown.py +9 -19
  15. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/evidence/parsers/pdf.py +11 -12
  16. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/evidence/parsers/workbook.py +2 -12
  17. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/evidence/paths.py +24 -0
  18. tracecite-0.0.4/src/tracecite/evidence/schema.py +415 -0
  19. tracecite-0.0.4/src/tracecite/evidence/sync.py +1206 -0
  20. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/evidence/vector_backend.py +10 -6
  21. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/evidence/verify.py +65 -97
  22. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/skills/routing-documentation-source-links/SKILL.md +3 -3
  23. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/skills/using-tracecite/SKILL.md +2 -2
  24. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/skills/using-tracecite/references/pdf-and-assets.md +14 -7
  25. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/skills/using-tracecite/references/schema-and-migrations.md +1 -1
  26. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/skills/using-tracecite/references/synchronisation.md +3 -8
  27. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/skills/writing-evidence-backed-reports/SKILL.md +1 -1
  28. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/skills/writing-evidence-backed-reports/fixtures/validate_fixtures.py +1 -1
  29. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/skills/writing-evidence-backed-reports/references/quotation-and-verification.md +2 -1
  30. tracecite-0.0.4/src/tracecite.egg-info/PKG-INFO +286 -0
  31. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite.egg-info/SOURCES.txt +0 -19
  32. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite.egg-info/requires.txt +0 -7
  33. {tracecite-0.0.2 → tracecite-0.0.4}/tests/test_bootstrap_docs.py +1 -1
  34. {tracecite-0.0.2 → tracecite-0.0.4}/tests/test_build_docs.py +1 -2
  35. tracecite-0.0.2/PKG-INFO +0 -320
  36. tracecite-0.0.2/README.md +0 -294
  37. tracecite-0.0.2/src/tracecite/__init__.py +0 -35
  38. tracecite-0.0.2/src/tracecite/cli.py +0 -656
  39. tracecite-0.0.2/src/tracecite/docs/__init__.py +0 -56
  40. tracecite-0.0.2/src/tracecite/docs/build.py +0 -381
  41. tracecite-0.0.2/src/tracecite/docs/config.py +0 -114
  42. tracecite-0.0.2/src/tracecite/docs/contract.py +0 -17
  43. tracecite-0.0.2/src/tracecite/docs/modes.py +0 -240
  44. tracecite-0.0.2/src/tracecite/docs/stage.py +0 -407
  45. tracecite-0.0.2/src/tracecite/docs/vectorize.py +0 -457
  46. tracecite-0.0.2/src/tracecite/evidence/commands.py +0 -552
  47. tracecite-0.0.2/src/tracecite/evidence/embedding.py +0 -59
  48. tracecite-0.0.2/src/tracecite/evidence/schema.py +0 -570
  49. tracecite-0.0.2/src/tracecite/evidence/sync.py +0 -1434
  50. tracecite-0.0.2/src/tracecite/tables/__init__.py +0 -41
  51. tracecite-0.0.2/src/tracecite/tables/_text.py +0 -142
  52. tracecite-0.0.2/src/tracecite/tables/document.py +0 -582
  53. tracecite-0.0.2/src/tracecite/tables/html.py +0 -299
  54. tracecite-0.0.2/src/tracecite/tables/models.py +0 -119
  55. tracecite-0.0.2/src/tracecite/tables/normalise.py +0 -786
  56. tracecite-0.0.2/src/tracecite/tables/pandoc.py +0 -503
  57. tracecite-0.0.2/src/tracecite/tables/publish.py +0 -238
  58. tracecite-0.0.2/src/tracecite/tables/render.py +0 -128
  59. tracecite-0.0.2/src/tracecite/tables/site.py +0 -457
  60. tracecite-0.0.2/src/tracecite.egg-info/PKG-INFO +0 -320
  61. tracecite-0.0.2/tests/test_docs.py +0 -496
  62. tracecite-0.0.2/tests/test_tables.py +0 -442
  63. {tracecite-0.0.2 → tracecite-0.0.4}/LICENSE +0 -0
  64. {tracecite-0.0.2 → tracecite-0.0.4}/setup.cfg +0 -0
  65. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/__main__.py +0 -0
  66. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/evidence/__init__.py +0 -0
  67. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/evidence/config.py +0 -0
  68. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/evidence/parsers/__init__.py +0 -0
  69. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/evidence/source_links.py +0 -0
  70. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/skills/routing-documentation-source-links/agents/openai.yaml +0 -0
  71. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/skills/routing-documentation-source-links/references/documenter-integration.md +0 -0
  72. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/skills/routing-documentation-source-links/references/registry-contract.md +0 -0
  73. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/skills/routing-documentation-source-links/references/staging-and-rewriting.md +0 -0
  74. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/skills/routing-documentation-source-links/references/validation-and-failure-modes.md +0 -0
  75. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/skills/using-tracecite/agents/openai.yaml +0 -0
  76. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/skills/using-tracecite/references/architecture.md +0 -0
  77. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/skills/using-tracecite/references/retrieval.md +0 -0
  78. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/skills/using-tracecite/references/workspace-runtime.md +0 -0
  79. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/skills/writing-evidence-backed-reports/agents/openai.yaml +0 -0
  80. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/skills/writing-evidence-backed-reports/fixtures/README.md +0 -0
  81. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/skills/writing-evidence-backed-reports/fixtures/reports/invalid-bad-path.md +0 -0
  82. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/skills/writing-evidence-backed-reports/fixtures/reports/invalid-grammar.md +0 -0
  83. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/skills/writing-evidence-backed-reports/fixtures/reports/invalid-missing-definition.md +0 -0
  84. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/skills/writing-evidence-backed-reports/fixtures/reports/invalid-page-not-indexed.md +0 -0
  85. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/skills/writing-evidence-backed-reports/fixtures/reports/invalid-unindexed-path.md +0 -0
  86. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/skills/writing-evidence-backed-reports/fixtures/reports/valid-grammar.md +0 -0
  87. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/skills/writing-evidence-backed-reports/fixtures/reports/valid-report.md +0 -0
  88. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/skills/writing-evidence-backed-reports/fixtures/source-links.toml +0 -0
  89. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/skills/writing-evidence-backed-reports/references/images-and-source-links.md +0 -0
  90. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/skills/writing-evidence-backed-reports/references/reference-style-citations.md +0 -0
  91. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite/skills/writing-evidence-backed-reports/references/report-structure.md +0 -0
  92. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite.egg-info/dependency_links.txt +0 -0
  93. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite.egg-info/entry_points.txt +0 -0
  94. {tracecite-0.0.2 → tracecite-0.0.4}/src/tracecite.egg-info/top_level.txt +0 -0
  95. {tracecite-0.0.2 → tracecite-0.0.4}/tests/test_repository_tree.py +0 -0
  96. {tracecite-0.0.2 → tracecite-0.0.4}/tests/test_skills.py +0 -0
  97. {tracecite-0.0.2 → tracecite-0.0.4}/tests/test_version.py +0 -0
@@ -0,0 +1,286 @@
1
+ Metadata-Version: 2.4
2
+ Name: tracecite
3
+ Version: 0.0.4
4
+ Summary: Source-linked table normalisation and evidence retrieval for executable documentation
5
+ Author: ARPST-UniMelb
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/yasirroni/tracecite
8
+ Project-URL: Documentation, https://yasirroni.github.io/tracecite/
9
+ Project-URL: Issues, https://github.com/yasirroni/tracecite/issues
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Science/Research
12
+ Classifier: Operating System :: MacOS
13
+ Classifier: Operating System :: POSIX :: Linux
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Topic :: Scientific/Engineering
16
+ Classifier: Topic :: Text Processing :: Indexing
17
+ Requires-Python: >=3.11
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ Provides-Extra: evidence
21
+ Requires-Dist: huggingface-hub<2,>=1.23; extra == "evidence"
22
+ Requires-Dist: pymupdf<2,>=1.28; extra == "evidence"
23
+ Requires-Dist: sentence-transformers<6,>=5.6; extra == "evidence"
24
+ Requires-Dist: sqlite-vec<0.2,>=0.1.9; extra == "evidence"
25
+ Provides-Extra: test
26
+ Requires-Dist: build>=1.2; extra == "test"
27
+ Requires-Dist: pytest<9,>=8.4; extra == "test"
28
+ Dynamic: license-file
29
+
30
+ # TraceCite
31
+
32
+ TraceCite lets people and AI agents search their documents, cite the exact page or cell, and check that a quote matches its source.
33
+
34
+ TraceCite indexes Markdown, PDF, `.xlsx`, and `.xlsm` files. It stores retained text, source hashes, full-text and vector search records, and locators (PDF pages, Markdown lines, and worksheet ranges), and verifies quotations and report citations against them.
35
+
36
+ [tracecite-docs](https://pypi.org/project/tracecite-docs/) builds Quarto sites from executable Python and Julia pages, normalises their tables into source-linked row text for search, and indexes the retained pages with TraceCite. The [TraceCite documentation](https://yasirroni.github.io/tracecite/) covers both packages.
37
+
38
+ ## Architecture
39
+
40
+ ```text
41
+ declared PDF, Markdown, or workbook sources
42
+ -> retained source extraction
43
+ -> locator-aware chunks
44
+ -> SQLite FTS5 and sqlite-vec
45
+ -> ranked JSON results with source identity and evidence locators
46
+ ```
47
+
48
+ ## Installation
49
+
50
+ TraceCite needs Python 3.11 or newer. Evidence synchronisation and hybrid search need the `evidence` extra:
51
+
52
+ ```sh
53
+ pip install "tracecite[evidence]"
54
+ ```
55
+
56
+ The `evidence` extra installs PyTorch through `sentence-transformers`. On Linux, pip installs the CUDA build by default, a download of several gigabytes. On a machine without a GPU, install the CPU build first:
57
+
58
+ ```sh
59
+ pip install torch --index-url https://download.pytorch.org/whl/cpu
60
+ ```
61
+
62
+ Workbook parsing reads OOXML packages with only the Python standard library, without Excel, Julia, Quarto, or third-party workbook readers.
63
+
64
+ ## Usage
65
+
66
+ The `tracecite` CLI syncs, searches, and verifies source evidence, and installs the bundled agent skills.
67
+
68
+ ### Index and search source evidence
69
+
70
+ List sources in a manifest by explicit path or by include and exclude globs over `.pdf`, `.md`, `.xlsx`, and `.xlsm` files.
71
+
72
+ ```toml
73
+ schema_version = 1
74
+
75
+ [[source]]
76
+ path = "2023-iasr-ev-workbook.xlsx"
77
+ ```
78
+
79
+ Sync the sources into a database, search it lexically and semantically, then check its integrity:
80
+
81
+ ```sh
82
+ tracecite sync \
83
+ --root sources \
84
+ --manifest tracecite-sources.toml \
85
+ --database .tracecite/evidence.sqlite \
86
+ --model-cache-dir .tracecite/model-cache
87
+
88
+ tracecite search \
89
+ "weekday versus weekend electric vehicle charging behaviour" \
90
+ --database .tracecite/evidence.sqlite \
91
+ --model-cache-dir .tracecite/model-cache
92
+
93
+ tracecite doctor --database .tracecite/evidence.sqlite
94
+ ```
95
+
96
+ #### Sync
97
+
98
+ - `sync` needs at least one `[[source]]` or `[[include]]` rule; without one, it stops without creating or changing the database.
99
+ - It prints one line per added, reparsed, renamed, missing, or unselected path; `--json` prints the full report.
100
+ - A declared `[[source]]` missing under the root is listed under `missing-sources`. A selected file that sync cannot read or parse, or that is a symlink, is listed under `skipped` with the reason; a skipped file indexed earlier keeps its previous rows. Either case ends with `status: incomplete` and exit 1, and the other sources still sync. A sync of one path checks only that path.
101
+ - A second `sync` or `prune --apply` of the same database waits for the first to finish. The wait uses an empty `<database>.lock` file beside the database.
102
+ - PDF pages without text, such as blank or scanned pages, are listed under `pages-without-text` when they are parsed, and `doctor` lists them on every run. Scanned pages need [Tesseract](https://github.com/tesseract-ocr/tesseract) for OCR; without it, sync stores those pages without text. After installing it, run `tracecite sync --full` to extract their text.
103
+ - `sync` is incremental and non-pruning. Sources that are gone or no longer selected stay searchable and citable until you preview and apply `tracecite prune`.
104
+
105
+ #### Prune
106
+
107
+ `prune` needs the source root (`--root` or a profile). It targets indexed sources the rules no longer select or whose file is gone from the root; the preview lists the latter under `missing_paths`. `--all` targets every indexed source and needs no root. `prune --apply` also compacts the database file.
108
+
109
+ #### Doctor
110
+
111
+ `doctor` warns about PDF pages without text, and with `--root <dir>` about sources that changed or disappeared since the last sync. Only database, vector, and asset integrity issues change its exit status; the last line counts the warnings.
112
+
113
+ #### Search
114
+
115
+ `search --source-type` (`pdf`, `markdown`, or `workbook`; repeatable) filters lexical and vector candidates before ranking and the `--limit` cut, not after:
116
+
117
+ ```sh
118
+ tracecite search "coal retirement" \
119
+ --database .tracecite/evidence.sqlite \
120
+ --source-type pdf
121
+ ```
122
+
123
+ - An empty query exits with status 2.
124
+ - `--lexical-only` uses full-text search alone and skips loading the embedding model.
125
+ - Chinese, Japanese, and Korean (CJK) text has no spaces, so lexical search also matches each CJK run of the query as a substring of the indexed text. This reads every passage, so it is slower than ordinary full-text search on a large database.
126
+ - The embedding model is English-only, so vector search leaves out the CJK text of a query. A query with only CJK text uses lexical search only.
127
+ - Byte-identical files at different paths give one hit, under the shortest path (then the first in sort order), with the others in `duplicate_paths`.
128
+
129
+ Each result includes retrieval provenance and a source-specific locator. This abbreviated workbook result shows the stable fields; the worksheet and ranges vary with the workbook and chunk settings:
130
+
131
+ ```json
132
+ {
133
+ "source_path": "inputs-and-assumptions.xlsx",
134
+ "source_type": "workbook",
135
+ "source_sha256": "<64-character SHA-256>",
136
+ "locator": {
137
+ "kind": "excel-range",
138
+ "sheet": "<worksheet name>",
139
+ "range": "<bounding A1 range>",
140
+ "range_kind": "bounding",
141
+ "exact_ranges": ["<exact A1 range>"]
142
+ },
143
+ "provenance": ["lexical", "vector"]
144
+ }
145
+ ```
146
+
147
+ The path and SHA-256 identify the workbook version, and the worksheet and `exact_ranges` identify the passage's cells. `range` is only the bounding rectangle and can include other cells. Rank only marks candidate evidence, so inspect the returned cells before citing a result.
148
+
149
+ A portable workbook citation is the path, SHA-256, worksheet, and A1 ranges. Opening the exact range needs a workbook viewer or a separate provider-specific link.
150
+
151
+ #### Workbook boundaries
152
+
153
+ - The parser supports `.xlsx` and `.xlsm` OOXML packages, not legacy binary `.xls`.
154
+ - It keeps stored text, numeric, Boolean, error, formula, and cached formula values. Cached values reflect the workbook's stored state; formulae are not recalculated.
155
+ - It reads stored package content only and does not run VBA or refresh external links, Power Query, pivot caches, or data connections.
156
+ - It ignores style-only empty cells and does not reconstruct display formatting, so styled dates and times can stay numeric serials.
157
+ - It chunks workbooks by row and does not yet infer formal Excel tables or carry complex multi-row headers into every row.
158
+
159
+ ### Retrieve retained pages and visual evidence
160
+
161
+ `tracecite page` prints retained PDF page text from the SQLite evidence database, physical page 1 by default. Selectors combine pages and closed or open ranges; overlaps are merged and pages come back in ascending physical order.
162
+
163
+ ```sh
164
+ tracecite page reports/example.pdf --database evidence.sqlite
165
+ tracecite page reports/example.pdf 5,12-15,20 --database evidence.sqlite
166
+ tracecite page reports/example.pdf 97- --database evidence.sqlite
167
+ tracecite page reports/example.pdf -20 --database evidence.sqlite
168
+ tracecite page reports/example.pdf all --database evidence.sqlite
169
+ ```
170
+
171
+ Only `all` implicitly selects the whole source, and it must stand alone. Multi-page text output marks each physical page, and a page with no text, such as a scanned page synced without OCR, adds a note on stderr. `--format json` returns an ordered array of retained text, extraction metadata, a citation link, and validated paths to the indexed page render and figure crops. Search results carry the same render and crop fields for page-local PDF matches.
172
+
173
+ `extract-pages` takes the same selectors and writes a derivative PDF and provenance manifest from the indexed source PDF. The output directory must already exist outside the source root; stale sources, symlinked output directories, overlap, and overwrites are refused.
174
+
175
+ ```sh
176
+ mkdir -p ../tracecite-exports
177
+ tracecite extract-pages reports/example.pdf 5,12-15,20 \
178
+ --database evidence.sqlite \
179
+ --output-dir ../tracecite-exports
180
+ ```
181
+
182
+ Answer page-local questions from database text or indexed page assets; select `all` only when you need the whole source.
183
+
184
+ ### Verify quotations
185
+
186
+ `tracecite verify quote` checks a quotation against the retained text of one physical page, or a contiguous range such as `4-5` for a quotation that crosses a page break:
187
+
188
+ ```sh
189
+ tracecite verify quote reports/example.pdf 4-5 "Exact quotation" --database evidence.sqlite
190
+ ```
191
+
192
+ - `exact`: the quotation occurs verbatim.
193
+ - `normalised`: matches after collapsing whitespace, straightening curly quotes and apostrophes, and ignoring case.
194
+ - `not-found`: anything else, including one changed word.
195
+ - `page-not-indexed` or `source-not-indexed`: the page range or the source is not in the database; these exit 2, other failures exit 1.
196
+
197
+ Verification reads only the indexed text, so run `tracecite sync` after a file changes to check against the new version.
198
+
199
+ ### Install the agent skills
200
+
201
+ TraceCite bundles three AI agent skills: `using-tracecite`, `writing-evidence-backed-reports`, and `routing-documentation-source-links`. Copy them into the project's `.agents/skills/` directory:
202
+
203
+ ```sh
204
+ tracecite skills install
205
+ ```
206
+
207
+ `--target` picks another directory, such as Claude Code's personal skills:
208
+
209
+ ```sh
210
+ tracecite skills install --target ~/.claude/skills
211
+ ```
212
+
213
+ Rerunning it replaces the copies with the installed version's skills.
214
+
215
+ ## Contributing
216
+
217
+ ### Environment
218
+
219
+ ```sh
220
+ uv sync --extra evidence --extra test
221
+ ```
222
+
223
+ `uv sync` also installs `tracecite-docs` from the `docs` dependency group to build the documentation.
224
+
225
+ `requirements.txt` pins the evidence dependencies to the newest versions `pyproject.toml` allows; install it for a reproducible environment. Refresh it with [`pru`](https://github.com/yasirroni/pru); installing `-e ".[evidence]"` in the same command keeps upgrades within `pyproject.toml` bounds:
226
+
227
+ ```sh
228
+ uv pip install -r requirements.txt
229
+ pru -r requirements.txt upgrade_requirements --cmd 'uv pip install --upgrade -e ".[evidence]"'
230
+ ```
231
+
232
+ ### Build the documentation
233
+
234
+ The build needs [Quarto](https://quarto.org/), which bundles Pandoc, and Julia 1.10 or newer for the Julia pages. Set up the Julia environment once:
235
+
236
+ ```sh
237
+ julia --project=. -e 'using Pkg; Pkg.instantiate()'
238
+ ```
239
+
240
+ ```sh
241
+ uv run tracecite-docs build docs
242
+ uv run tracecite-docs build docs_quarto_py --only python
243
+ uv run tracecite-docs build docs_quarto_jl --only julia
244
+ ```
245
+
246
+ <!-- TODO:
247
+ Explain the expected `[WARNING] Could not fetch resource`
248
+ -->
249
+
250
+ Without Julia, the builder names each Julia source it skips and renders the Python overlay, leaving Julia sources untouched. `--only python` or `--only julia` builds one language.
251
+
252
+ `docs/examples/report-adoption/aemo-isp-comparison/` is a complete author -> check -> index -> search -> doctor -> publish-only example using two AEMO Integrated System Plan reports.
253
+
254
+ `docs/examples/report-adoption/aemo-isp-comparison/docs/tracecite.toml` demonstrates the documentation evidence contract. Schema version 1 defines exactly `authored_root`, `retained_root`, `staged_root`, `source_links`, `index_output`, `publication_exclude`, and optional `host_render_command` under `[docs]`. Contract paths are repository-relative and stay inside the repository.
255
+
256
+ Open the built site:
257
+
258
+ ```sh
259
+ open docs/build/index.html
260
+ ```
261
+
262
+ ### Lint and format
263
+
264
+ On each commit, [pre-commit](https://pre-commit.com/) runs [Ruff](https://docs.astral.sh/ruff/) on changed Python files and [ty](https://github.com/astral-sh/ty) on the whole project. Install it once and enable the hook:
265
+
266
+ ```sh
267
+ uv tool install pre-commit
268
+ pre-commit install
269
+ ```
270
+
271
+ `pre-commit run --all-files` checks every file. [Pyright](https://github.com/microsoft/pyright), the checker behind Pylance, runs only on request with `pre-commit run --hook-stage manual pyright --all-files`.
272
+
273
+ ### Test
274
+
275
+ Python tests and build:
276
+
277
+ ```sh
278
+ python -m pytest
279
+ uv build
280
+ ```
281
+
282
+ The Julia package is tested by `docs/examples/julia/dirty_dataframe.jl`, which the documentation build runs with its hidden checks:
283
+
284
+ ```sh
285
+ tracecite-docs build docs
286
+ ```
@@ -0,0 +1,257 @@
1
+ # TraceCite
2
+
3
+ TraceCite lets people and AI agents search their documents, cite the exact page or cell, and check that a quote matches its source.
4
+
5
+ TraceCite indexes Markdown, PDF, `.xlsx`, and `.xlsm` files. It stores retained text, source hashes, full-text and vector search records, and locators (PDF pages, Markdown lines, and worksheet ranges), and verifies quotations and report citations against them.
6
+
7
+ [tracecite-docs](https://pypi.org/project/tracecite-docs/) builds Quarto sites from executable Python and Julia pages, normalises their tables into source-linked row text for search, and indexes the retained pages with TraceCite. The [TraceCite documentation](https://yasirroni.github.io/tracecite/) covers both packages.
8
+
9
+ ## Architecture
10
+
11
+ ```text
12
+ declared PDF, Markdown, or workbook sources
13
+ -> retained source extraction
14
+ -> locator-aware chunks
15
+ -> SQLite FTS5 and sqlite-vec
16
+ -> ranked JSON results with source identity and evidence locators
17
+ ```
18
+
19
+ ## Installation
20
+
21
+ TraceCite needs Python 3.11 or newer. Evidence synchronisation and hybrid search need the `evidence` extra:
22
+
23
+ ```sh
24
+ pip install "tracecite[evidence]"
25
+ ```
26
+
27
+ The `evidence` extra installs PyTorch through `sentence-transformers`. On Linux, pip installs the CUDA build by default, a download of several gigabytes. On a machine without a GPU, install the CPU build first:
28
+
29
+ ```sh
30
+ pip install torch --index-url https://download.pytorch.org/whl/cpu
31
+ ```
32
+
33
+ Workbook parsing reads OOXML packages with only the Python standard library, without Excel, Julia, Quarto, or third-party workbook readers.
34
+
35
+ ## Usage
36
+
37
+ The `tracecite` CLI syncs, searches, and verifies source evidence, and installs the bundled agent skills.
38
+
39
+ ### Index and search source evidence
40
+
41
+ List sources in a manifest by explicit path or by include and exclude globs over `.pdf`, `.md`, `.xlsx`, and `.xlsm` files.
42
+
43
+ ```toml
44
+ schema_version = 1
45
+
46
+ [[source]]
47
+ path = "2023-iasr-ev-workbook.xlsx"
48
+ ```
49
+
50
+ Sync the sources into a database, search it lexically and semantically, then check its integrity:
51
+
52
+ ```sh
53
+ tracecite sync \
54
+ --root sources \
55
+ --manifest tracecite-sources.toml \
56
+ --database .tracecite/evidence.sqlite \
57
+ --model-cache-dir .tracecite/model-cache
58
+
59
+ tracecite search \
60
+ "weekday versus weekend electric vehicle charging behaviour" \
61
+ --database .tracecite/evidence.sqlite \
62
+ --model-cache-dir .tracecite/model-cache
63
+
64
+ tracecite doctor --database .tracecite/evidence.sqlite
65
+ ```
66
+
67
+ #### Sync
68
+
69
+ - `sync` needs at least one `[[source]]` or `[[include]]` rule; without one, it stops without creating or changing the database.
70
+ - It prints one line per added, reparsed, renamed, missing, or unselected path; `--json` prints the full report.
71
+ - A declared `[[source]]` missing under the root is listed under `missing-sources`. A selected file that sync cannot read or parse, or that is a symlink, is listed under `skipped` with the reason; a skipped file indexed earlier keeps its previous rows. Either case ends with `status: incomplete` and exit 1, and the other sources still sync. A sync of one path checks only that path.
72
+ - A second `sync` or `prune --apply` of the same database waits for the first to finish. The wait uses an empty `<database>.lock` file beside the database.
73
+ - PDF pages without text, such as blank or scanned pages, are listed under `pages-without-text` when they are parsed, and `doctor` lists them on every run. Scanned pages need [Tesseract](https://github.com/tesseract-ocr/tesseract) for OCR; without it, sync stores those pages without text. After installing it, run `tracecite sync --full` to extract their text.
74
+ - `sync` is incremental and non-pruning. Sources that are gone or no longer selected stay searchable and citable until you preview and apply `tracecite prune`.
75
+
76
+ #### Prune
77
+
78
+ `prune` needs the source root (`--root` or a profile). It targets indexed sources the rules no longer select or whose file is gone from the root; the preview lists the latter under `missing_paths`. `--all` targets every indexed source and needs no root. `prune --apply` also compacts the database file.
79
+
80
+ #### Doctor
81
+
82
+ `doctor` warns about PDF pages without text, and with `--root <dir>` about sources that changed or disappeared since the last sync. Only database, vector, and asset integrity issues change its exit status; the last line counts the warnings.
83
+
84
+ #### Search
85
+
86
+ `search --source-type` (`pdf`, `markdown`, or `workbook`; repeatable) filters lexical and vector candidates before ranking and the `--limit` cut, not after:
87
+
88
+ ```sh
89
+ tracecite search "coal retirement" \
90
+ --database .tracecite/evidence.sqlite \
91
+ --source-type pdf
92
+ ```
93
+
94
+ - An empty query exits with status 2.
95
+ - `--lexical-only` uses full-text search alone and skips loading the embedding model.
96
+ - Chinese, Japanese, and Korean (CJK) text has no spaces, so lexical search also matches each CJK run of the query as a substring of the indexed text. This reads every passage, so it is slower than ordinary full-text search on a large database.
97
+ - The embedding model is English-only, so vector search leaves out the CJK text of a query. A query with only CJK text uses lexical search only.
98
+ - Byte-identical files at different paths give one hit, under the shortest path (then the first in sort order), with the others in `duplicate_paths`.
99
+
100
+ Each result includes retrieval provenance and a source-specific locator. This abbreviated workbook result shows the stable fields; the worksheet and ranges vary with the workbook and chunk settings:
101
+
102
+ ```json
103
+ {
104
+ "source_path": "inputs-and-assumptions.xlsx",
105
+ "source_type": "workbook",
106
+ "source_sha256": "<64-character SHA-256>",
107
+ "locator": {
108
+ "kind": "excel-range",
109
+ "sheet": "<worksheet name>",
110
+ "range": "<bounding A1 range>",
111
+ "range_kind": "bounding",
112
+ "exact_ranges": ["<exact A1 range>"]
113
+ },
114
+ "provenance": ["lexical", "vector"]
115
+ }
116
+ ```
117
+
118
+ The path and SHA-256 identify the workbook version, and the worksheet and `exact_ranges` identify the passage's cells. `range` is only the bounding rectangle and can include other cells. Rank only marks candidate evidence, so inspect the returned cells before citing a result.
119
+
120
+ A portable workbook citation is the path, SHA-256, worksheet, and A1 ranges. Opening the exact range needs a workbook viewer or a separate provider-specific link.
121
+
122
+ #### Workbook boundaries
123
+
124
+ - The parser supports `.xlsx` and `.xlsm` OOXML packages, not legacy binary `.xls`.
125
+ - It keeps stored text, numeric, Boolean, error, formula, and cached formula values. Cached values reflect the workbook's stored state; formulae are not recalculated.
126
+ - It reads stored package content only and does not run VBA or refresh external links, Power Query, pivot caches, or data connections.
127
+ - It ignores style-only empty cells and does not reconstruct display formatting, so styled dates and times can stay numeric serials.
128
+ - It chunks workbooks by row and does not yet infer formal Excel tables or carry complex multi-row headers into every row.
129
+
130
+ ### Retrieve retained pages and visual evidence
131
+
132
+ `tracecite page` prints retained PDF page text from the SQLite evidence database, physical page 1 by default. Selectors combine pages and closed or open ranges; overlaps are merged and pages come back in ascending physical order.
133
+
134
+ ```sh
135
+ tracecite page reports/example.pdf --database evidence.sqlite
136
+ tracecite page reports/example.pdf 5,12-15,20 --database evidence.sqlite
137
+ tracecite page reports/example.pdf 97- --database evidence.sqlite
138
+ tracecite page reports/example.pdf -20 --database evidence.sqlite
139
+ tracecite page reports/example.pdf all --database evidence.sqlite
140
+ ```
141
+
142
+ Only `all` implicitly selects the whole source, and it must stand alone. Multi-page text output marks each physical page, and a page with no text, such as a scanned page synced without OCR, adds a note on stderr. `--format json` returns an ordered array of retained text, extraction metadata, a citation link, and validated paths to the indexed page render and figure crops. Search results carry the same render and crop fields for page-local PDF matches.
143
+
144
+ `extract-pages` takes the same selectors and writes a derivative PDF and provenance manifest from the indexed source PDF. The output directory must already exist outside the source root; stale sources, symlinked output directories, overlap, and overwrites are refused.
145
+
146
+ ```sh
147
+ mkdir -p ../tracecite-exports
148
+ tracecite extract-pages reports/example.pdf 5,12-15,20 \
149
+ --database evidence.sqlite \
150
+ --output-dir ../tracecite-exports
151
+ ```
152
+
153
+ Answer page-local questions from database text or indexed page assets; select `all` only when you need the whole source.
154
+
155
+ ### Verify quotations
156
+
157
+ `tracecite verify quote` checks a quotation against the retained text of one physical page, or a contiguous range such as `4-5` for a quotation that crosses a page break:
158
+
159
+ ```sh
160
+ tracecite verify quote reports/example.pdf 4-5 "Exact quotation" --database evidence.sqlite
161
+ ```
162
+
163
+ - `exact`: the quotation occurs verbatim.
164
+ - `normalised`: matches after collapsing whitespace, straightening curly quotes and apostrophes, and ignoring case.
165
+ - `not-found`: anything else, including one changed word.
166
+ - `page-not-indexed` or `source-not-indexed`: the page range or the source is not in the database; these exit 2, other failures exit 1.
167
+
168
+ Verification reads only the indexed text, so run `tracecite sync` after a file changes to check against the new version.
169
+
170
+ ### Install the agent skills
171
+
172
+ TraceCite bundles three AI agent skills: `using-tracecite`, `writing-evidence-backed-reports`, and `routing-documentation-source-links`. Copy them into the project's `.agents/skills/` directory:
173
+
174
+ ```sh
175
+ tracecite skills install
176
+ ```
177
+
178
+ `--target` picks another directory, such as Claude Code's personal skills:
179
+
180
+ ```sh
181
+ tracecite skills install --target ~/.claude/skills
182
+ ```
183
+
184
+ Rerunning it replaces the copies with the installed version's skills.
185
+
186
+ ## Contributing
187
+
188
+ ### Environment
189
+
190
+ ```sh
191
+ uv sync --extra evidence --extra test
192
+ ```
193
+
194
+ `uv sync` also installs `tracecite-docs` from the `docs` dependency group to build the documentation.
195
+
196
+ `requirements.txt` pins the evidence dependencies to the newest versions `pyproject.toml` allows; install it for a reproducible environment. Refresh it with [`pru`](https://github.com/yasirroni/pru); installing `-e ".[evidence]"` in the same command keeps upgrades within `pyproject.toml` bounds:
197
+
198
+ ```sh
199
+ uv pip install -r requirements.txt
200
+ pru -r requirements.txt upgrade_requirements --cmd 'uv pip install --upgrade -e ".[evidence]"'
201
+ ```
202
+
203
+ ### Build the documentation
204
+
205
+ The build needs [Quarto](https://quarto.org/), which bundles Pandoc, and Julia 1.10 or newer for the Julia pages. Set up the Julia environment once:
206
+
207
+ ```sh
208
+ julia --project=. -e 'using Pkg; Pkg.instantiate()'
209
+ ```
210
+
211
+ ```sh
212
+ uv run tracecite-docs build docs
213
+ uv run tracecite-docs build docs_quarto_py --only python
214
+ uv run tracecite-docs build docs_quarto_jl --only julia
215
+ ```
216
+
217
+ <!-- TODO:
218
+ Explain the expected `[WARNING] Could not fetch resource`
219
+ -->
220
+
221
+ Without Julia, the builder names each Julia source it skips and renders the Python overlay, leaving Julia sources untouched. `--only python` or `--only julia` builds one language.
222
+
223
+ `docs/examples/report-adoption/aemo-isp-comparison/` is a complete author -> check -> index -> search -> doctor -> publish-only example using two AEMO Integrated System Plan reports.
224
+
225
+ `docs/examples/report-adoption/aemo-isp-comparison/docs/tracecite.toml` demonstrates the documentation evidence contract. Schema version 1 defines exactly `authored_root`, `retained_root`, `staged_root`, `source_links`, `index_output`, `publication_exclude`, and optional `host_render_command` under `[docs]`. Contract paths are repository-relative and stay inside the repository.
226
+
227
+ Open the built site:
228
+
229
+ ```sh
230
+ open docs/build/index.html
231
+ ```
232
+
233
+ ### Lint and format
234
+
235
+ On each commit, [pre-commit](https://pre-commit.com/) runs [Ruff](https://docs.astral.sh/ruff/) on changed Python files and [ty](https://github.com/astral-sh/ty) on the whole project. Install it once and enable the hook:
236
+
237
+ ```sh
238
+ uv tool install pre-commit
239
+ pre-commit install
240
+ ```
241
+
242
+ `pre-commit run --all-files` checks every file. [Pyright](https://github.com/microsoft/pyright), the checker behind Pylance, runs only on request with `pre-commit run --hook-stage manual pyright --all-files`.
243
+
244
+ ### Test
245
+
246
+ Python tests and build:
247
+
248
+ ```sh
249
+ python -m pytest
250
+ uv build
251
+ ```
252
+
253
+ The Julia package is tested by `docs/examples/julia/dirty_dataframe.jl`, which the documentation build runs with its hidden checks:
254
+
255
+ ```sh
256
+ tracecite-docs build docs
257
+ ```
@@ -4,22 +4,28 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "tracecite"
7
- version = "0.0.2"
7
+ version = "0.0.4"
8
8
  description = "Source-linked table normalisation and evidence retrieval for executable documentation"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
11
11
  license = "MIT"
12
12
  license-files = ["LICENSE"]
13
13
  authors = [{name = "ARPST-UniMelb"}]
14
- dependencies = [
15
- "beautifulsoup4>=4.12",
16
- "pandas>=2.0",
17
- "PyYAML>=6.0",
18
- "tabulate>=0.9",
19
- "nbformat>=5.10",
20
- "nbclient>=0.11",
21
- "ipykernel>=7.3",
14
+ classifiers = [
15
+ "Development Status :: 3 - Alpha",
16
+ "Intended Audience :: Science/Research",
17
+ "Operating System :: MacOS",
18
+ "Operating System :: POSIX :: Linux",
19
+ "Programming Language :: Python :: 3",
20
+ "Topic :: Scientific/Engineering",
21
+ "Topic :: Text Processing :: Indexing",
22
22
  ]
23
+ dependencies = []
24
+
25
+ [project.urls]
26
+ Homepage = "https://github.com/yasirroni/tracecite"
27
+ Documentation = "https://yasirroni.github.io/tracecite/"
28
+ Issues = "https://github.com/yasirroni/tracecite/issues"
23
29
 
24
30
  [project.optional-dependencies]
25
31
  evidence = [
@@ -30,6 +36,13 @@ evidence = [
30
36
  ]
31
37
  test = ["build>=1.2", "pytest>=8.4,<9"]
32
38
 
39
+ [dependency-groups]
40
+ # Builds the documentation site; the published package does not depend on it.
41
+ docs = ["tracecite-docs[docs]>=0.0.1"]
42
+
43
+ [tool.uv]
44
+ default-groups = ["docs"]
45
+
33
46
  [project.scripts]
34
47
  tracecite = "tracecite.cli:main"
35
48
 
@@ -42,6 +55,8 @@ tracecite = ["skills/**/*"]
42
55
  [tool.pyright]
43
56
  include = ["src", "tests"]
44
57
  pythonVersion = "3.11"
58
+ venvPath = "."
59
+ venv = ".venv"
45
60
 
46
61
  [tool.ruff]
47
62
  # scripts/bootstrap_docs.py copies docs_quarto_py from docs/. Markdown is not formatted
@@ -0,0 +1,5 @@
1
+ """TraceCite: source-linked evidence retrieval and citation verification."""
2
+
3
+ from importlib.metadata import version
4
+
5
+ __version__ = version("tracecite")