@openparser/lineage 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/CHANGELOG.md +89 -0
  2. package/LICENSE +201 -0
  3. package/README.md +211 -0
  4. package/dist/activity.d.ts +74 -0
  5. package/dist/activity.d.ts.map +1 -0
  6. package/dist/approval.d.ts +24 -0
  7. package/dist/approval.d.ts.map +1 -0
  8. package/dist/builder.d.ts +48 -0
  9. package/dist/builder.d.ts.map +1 -0
  10. package/dist/common.d.ts +34 -0
  11. package/dist/common.d.ts.map +1 -0
  12. package/dist/confidence.d.ts +61 -0
  13. package/dist/confidence.d.ts.map +1 -0
  14. package/dist/derivation.d.ts +163 -0
  15. package/dist/derivation.d.ts.map +1 -0
  16. package/dist/document.d.ts +412 -0
  17. package/dist/document.d.ts.map +1 -0
  18. package/dist/entity.d.ts +126 -0
  19. package/dist/entity.d.ts.map +1 -0
  20. package/dist/fields.d.ts +76 -0
  21. package/dist/fields.d.ts.map +1 -0
  22. package/dist/index.d.ts +21 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +870 -0
  25. package/dist/labels.d.ts +11 -0
  26. package/dist/labels.d.ts.map +1 -0
  27. package/dist/profile/grounding.d.ts +34 -0
  28. package/dist/profile/grounding.d.ts.map +1 -0
  29. package/dist/profile/index.d.ts +14 -0
  30. package/dist/profile/index.d.ts.map +1 -0
  31. package/dist/profile/index.js +1298 -0
  32. package/dist/profile/labels.d.ts +10 -0
  33. package/dist/profile/labels.d.ts.map +1 -0
  34. package/dist/profile/recognition.d.ts +70 -0
  35. package/dist/profile/recognition.d.ts.map +1 -0
  36. package/dist/profile/transform-validation.d.ts +250 -0
  37. package/dist/profile/transform-validation.d.ts.map +1 -0
  38. package/dist/prov.d.ts +40 -0
  39. package/dist/prov.d.ts.map +1 -0
  40. package/dist/relation.d.ts +27 -0
  41. package/dist/relation.d.ts.map +1 -0
  42. package/dist/traverse.d.ts +12 -0
  43. package/dist/traverse.d.ts.map +1 -0
  44. package/dist/validate.d.ts +14 -0
  45. package/dist/validate.d.ts.map +1 -0
  46. package/lineage.schema.json +625 -0
  47. package/package.json +71 -0
  48. package/src/activity.ts +65 -0
  49. package/src/approval.ts +28 -0
  50. package/src/builder.ts +129 -0
  51. package/src/common.ts +58 -0
  52. package/src/confidence.ts +72 -0
  53. package/src/derivation.ts +81 -0
  54. package/src/document.ts +82 -0
  55. package/src/entity.ts +87 -0
  56. package/src/fields.ts +163 -0
  57. package/src/index.ts +123 -0
  58. package/src/labels.ts +13 -0
  59. package/src/profile/grounding.ts +74 -0
  60. package/src/profile/index.ts +67 -0
  61. package/src/profile/labels.ts +28 -0
  62. package/src/profile/recognition.ts +149 -0
  63. package/src/profile/transform-validation.ts +1379 -0
  64. package/src/prov.ts +205 -0
  65. package/src/relation.ts +32 -0
  66. package/src/traverse.ts +91 -0
  67. package/src/validate.ts +221 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,89 @@
1
+ # @openparser/lineage
2
+
3
+ ## 1.0.2
4
+
5
+ ### Minor Changes
6
+
7
+ - e7bd767: Grounded extraction now makes every output field explainable. The extraction API can return a portable `lineage@1` derivation DAG connecting values to source text, page geometry, the closest recognition confidence supplied by the OCR model, and every operation that produced them. Downstream systems can append normalization, calculation, inference, and review activities without losing the original evidence.
8
+
9
+ The new `@openparser/lineage` package provides runtime schemas, graph validation, traversal and builder helpers, and W3C PROV interoperability for using the same lineage protocol beyond document extraction. `fields()` and `fieldTrace()` return an output field, its confidence, and its supporting evidence directly, so per-field explanations do not require walking the graph.
10
+
11
+ Lineage documents stay small enough to return with every extraction. Each field points back to the passage it came from and a single confidence for that passage, without repeating the word-by-word parse that already ships beside it. A typical multi-field result is now a few kilobytes per field, so full evidence arrives with the result rather than being dropped when it grows too large.
12
+
13
+ `fields()` and `fieldTrace()` fill in the rest on demand — a field's display path, whether its confidence was reported or derived, and whether it is grounded — so consumers do not have to reconstruct those answers themselves. The document names the model behind each step and keeps the original evidence, not presentation strings.
14
+
15
+ OpenParser Studio starts new Playground sessions with field grounding, so clicking a value immediately reveals where it came from. New review endpoints, SDK helpers, and `openparser jobs review` commands let teams confirm field values, or approve or reject a whole extraction, while preserving the original machine output and an attributed event history.
16
+
17
+ - e7bd767: A field's parse confidence now reflects the words that value was actually read from, instead of the worst word anywhere near it. When one sentence supplies two fields — a square footage and a street address, say — a street name the scanner struggled with used to drag the crisply scanned number down with it, and both fields reported the same low number. Each field is now scored on its own words, discounted a little when the surrounding text scanned poorly, so a value that reads cleanly reads as confident and reviewers can trust a low score to mean that particular value is worth a look.
18
+
19
+ Lineage keeps both readings, because they answer different questions. A cited region still reports how that region scanned as a whole, and each field that quotes it reports how clearly _its_ wording came through — so two fields from the same sentence can have different confidence, and reviewers are not asked to treat them as one score.
20
+
21
+ Pipelines that build their own lineage can apply the same per-field scoring instead of inventing a parallel rule.
22
+
23
+ - e7bd767: Extraction review now asks a reviewer for one thing: confirm what a field should say. If the value is right, confirming it signs it off; if it is wrong, correct it in the same box and confirming records the correction and the sign-off together. There is no longer a separate approve step to remember, and no way to end up with an approval that describes a value nobody agreed to — a sign-off always names the exact value it was given.
24
+
25
+ Confirming keeps you on the field, so the confirmation you just made is there to read, and Previous and Next below it move through the queue in the order the field list shows — lowest confidence first — for working a run field by field without going back to the list between each one.
26
+
27
+ Once a field is confirmed, the card that asked for the confirmation says so plainly: it turns green, carries a tick and the number of reviewers behind the value, and names whether the value was confirmed as it stood or corrected. Revisiting a field never leaves you hunting through its history to work out whether you already signed it off.
28
+
29
+ Each confirmation survives a refresh, appears in the field's history next to what it changed, and names the person who made it and when. Several reviewers can confirm the same field and each is counted separately, so a team can require two people on anything below a confidence threshold before treating it as settled. A field shows how many reviewers stand behind its current value, and you are still asked for your own confirmation on a field a colleague has already confirmed. Confirming is not a one-way door: a reviewer can still take back an eligible confirmation.
30
+
31
+ Reviewers can take back their own most recent confirmation on a field — and only that one. Withdrawing a signature from a value someone else also confirmed leaves that value standing; withdrawing one that introduced a value restores exactly what the field said before. Neither erases anything: the withdrawal is kept in the review trail. A confirmation cannot be taken back once another value has been built on top of it, and signing the run off freezes every field until the run is reopened.
32
+
33
+ Confirmations apply to anything lineage can describe, not just output fields, so teams reviewing pages or extracted regions record sign-off the same way. A confirmation covers only what it names: confirming a field makes no claim about the region it was read from.
34
+
35
+ `openparser jobs review-update` follows the same shape: `--confirm-json` takes the `{ path, value }` entries that used to go to `--changes-json`, and a value that differs from the current one corrects the field as it signs it off.
36
+
37
+ - e7bd767: Grounded extraction now records a short reason for every extracted field, explaining what in the source supports that value. Reviewers can see why the model produced each answer, not only where it came from. A reason belongs to the step that made the claim, so a field whose wording was reformatted explains the passage it read and the conversion it applied separately, each shown with the step it describes.
38
+ - e7bd767: `@openparser/lineage` now ships the `lineage@1` format on its own, with OpenParser's own conventions in a separate profile import. The format describes what a value was derived from, by which step, under which agent — a description that should hold whoever produced the document. Two rules did not belong to it: how an OCR word's score becomes a field's score, and when cited evidence counts as sufficient. The second reads an `openparser:`-namespaced attribute, so only one producer could ever satisfy it, and a format that claims to be neutral while quietly requiring a vendor's attributes is a format you cannot adopt without adopting the vendor.
39
+
40
+ Those rules moved to `@openparser/lineage/openparser`, which also gains `fieldGrounding()` — grounded, partial, or ungrounded for a field, read off the graph rather than stored. The package root keeps the schemas, validation, traversal, builder, and PROV export, and knows nothing about OpenParser.
41
+
42
+ If you scored words or read grounding status through this package, import from `@openparser/lineage/openparser`; `fieldTrace()` still returns a field's evidence and activities, which is the part of the question the format itself can answer. If you only build or validate documents, nothing changes.
43
+
44
+ - e7bd767: When a model does not copy a value straight off the page — your schema asks for a date, the contract says "20 day of May 2025", the result is `2025-05-20` — extraction still records the wording that was actually read. That read is verified by locating it in the page and discarded when it cannot be found. What the model turned the wording into is a second step, which nothing can verify, because performing that conversion mechanically is the work the model was asked to do.
45
+
46
+ Each step carries its own confidence, so a reviewer can see which half of the claim is solid. The read scores like any other verbatim match. The conversion carries the model's own reported score when the model gives one, and no score at all when it does not, because nothing measured it — a figure invented for it would be indistinguishable from the ones that mean something. What tells you a value was rewritten is the transform step being there, not a number chosen to look doubtful. One blended score would describe neither half: not that the read checked out, and not that the formatting rests on the model's word alone.
47
+
48
+ The wording is looked for first in the regions the model cited for it, so a short value that happens to appear elsewhere in the document is not treated as exactly grounded in a passage it was never read from. That holds for the quote too: wording found only outside the regions a field cites is reported as a loose match rather than a verified read of them.
49
+
50
+ A rewrite is recognised by the value differing from the verified wording, not by the value failing to resemble it. A currency amount rendered as a plain number, a name recased, a figure with its thousands separators dropped — these still resemble the text they came from, and each is now a read plus a conversion with its own account, where previously it was presented as a direct read and the model's explanation of the conversion was dropped.
51
+
52
+ In practice a reformatted value is no longer uniformly doubtful. You can highlight the exact passage a date came from at full confidence and still route the conversion to a human, and a consumer that scores a field by the weakest step in its history now gets the read's score — a true statement about the wording on the page — with the unverifiable step declaring itself in the trace rather than dragging that number down by a fixed amount.
53
+
54
+ The two steps are also explained separately. Extraction now asks the model for two accounts instead of one: why the quote it picked is the right passage, and — only when the value is not that quote as written — a bounded structured claim about how the quote became the value. Both appear in the grounding output, as `reason` and `transform_claim`, and a rewritten field's trace no longer explains a conversion in the step that merely read the page. Reviewers can accept the citation and question the formatting, which was previously one sentence covering both.
55
+
56
+ A rewritten field's trace therefore has two steps in the graph and one request on the wire: the verified wording from the page, then a transform attributed to the same model call that did the extraction. Values that appear in the document as written are a single extraction.
57
+
58
+ - e7bd767: Signing a whole run off is now unmistakable and reversible. An approved run reads as approved at a glance — the card turns green and carries the decision — and a rejected one turns red, so nobody has to hunt through a field trace to find out where a run stands. The job list and each job's own page show the same verdict, so a reviewer can see which runs are settled and which still need someone before opening any of them.
59
+
60
+ Job rows also stopped shouting the obvious. A finished job no longer wears a "succeeded" badge that looks just like an approval; instead the row's icon carries where the job is — spinning while it runs, waiting while it is queued — and a failure tints the whole row red. That leaves green and red on a job row meaning what a person decided, not a second copy of what the machine did.
61
+
62
+ A sign-off is no longer a one-way door. The reviewer who approved or rejected a run can reopen it, which returns the run to pending and unfreezes its fields for another pass — useful when a correction arrives after sign-off, or when the wrong button was clicked. Only the reviewer who signed the run off can reopen it, so one person cannot quietly undo another's decision.
63
+
64
+ Reopening hides nothing. Both the sign-off and the reopening stay in the review trail, attributed and timestamped, and the run's lineage reflects the decision that currently stands rather than every decision ever made. An auditor can still see that a run was approved on Tuesday, reopened on Wednesday, and rejected on Thursday.
65
+
66
+ `POST /jobs/{id}/review/reopen` exposes this to API, SDK, and CLI callers, and both `GET /jobs` and `GET /jobs/{id}` now report `review_status`, omitting it entirely for jobs nobody has reviewed. `GET /jobs/{id}` also reports `completed_at`, so clients can measure processing time without later review activity changing it. `openparser jobs review-reopen` does the same from the command line.
67
+
68
+ Reformatted values now carry confidence that says what was actually checked. OpenParser gives a transform full confidence only when a declared transform plan permits a versioned validator and that validator proves its narrow claim. Date/time formatting, exact decimal and unit conversions, quantity magnitudes, currency policies, aliases, and controlled text normalization can be checked without another model call. Otherwise the structured transform claim keeps the extraction model's coarse `low`, `medium`, or `high` assessment visibly reported and uncalibrated, and confidence stays unknown when nobody measured the rewrite.
69
+
70
+ - e7bd767: A correction made during extraction review is now visible at a glance. The reviewed output is what the field list and the JSON view show, so a corrected field no longer displays the value the model first produced, and a small pencil beside its name says a person changed it — hover the pencil to read that edit without leaving the list. Confidence badges now take their colour from sign-off rather than from the score, so a confirmed field wears the same green a confident one does while still reporting what the extraction scored.
71
+
72
+ Opening a corrected field shows the edit itself, character by character: the wording that was removed struck through in red, what replaced it in green. A single-letter fix in a street name is now as obvious as a rewritten sentence. When a value was replaced outright rather than touched up, the original and the correction are shown in full instead of an unreadable letter-by-letter comparison.
73
+
74
+ Each field's trace reads as one story again. A confirmation appears as a single review step naming the person who made it and when, in place of two near-identical entries, and each step shows the change that step made — so a field corrected twice reports what each pass did rather than only where it ended up. Confirming a value without changing it is a review step too — it names the person and the time, and shows no value, because nothing about the value changed. So a field several people signed off on says who they were, and the value extraction originally produced stays on that field's Output step.
75
+
76
+ Several corrections made by the same person in one sitting read as one step showing the net change, with the individual passes a click away, so settling on a value no longer buries the rest of the trace. A sitting that ends where it started reports no change at all.
77
+
78
+ The confirmation a reviewer is about to make now reads as the last step in the field's story, in the same card style as the steps above it, and stays fixed to the bottom of the panel — so a field with a long history no longer pushes the only thing there is to do out of sight. Once you have confirmed a field, that card says so and offers to withdraw it, which is the one place withdrawal is offered rather than something repeated in the history above.
79
+
80
+ ### Patch Changes
81
+
82
+ - e7bd767: The first stage of the pipeline is now called Parse everywhere it is named, replacing the mix of "OCR" and "parse" in labels, option descriptions, and lineage step names. Model names keep their own spelling, so a route such as Mistral OCR 4 still appears exactly as its vendor calls it. Option keys, request and response fields, and model ids are unchanged, so nothing needs updating in existing integrations.
83
+
84
+ ## 1.0.1
85
+
86
+ ### Patch Changes
87
+
88
+ - Initial public release of `lineage@1`: Zod schemas, strict DAG validation,
89
+ traversal helpers, `LineageBuilder`, and W3C PROV-JSON mapping.
package/LICENSE ADDED
@@ -0,0 +1,201 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for describing the origin of the Work and
141
+ reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may accept and charge a
167
+ fee for, or grant any of the foregoing rights, accept support,
168
+ warranty, indemnity, or other liability obligations and/or rights
169
+ consistent with this License. However, in accepting such obligations,
170
+ You may act only on Your own behalf and on Your sole responsibility,
171
+ not on behalf of any other Contributor, and only if You agree to
172
+ indemnify, defend, and hold each Contributor harmless for any
173
+ liability incurred by, or claims asserted against, such Contributor
174
+ by reason of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright 2026 Eigenpal
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
package/README.md ADDED
@@ -0,0 +1,211 @@
1
+ # @openparser/lineage
2
+
3
+ Zod schemas, TypeScript types, strict validation, traversal helpers, and a small
4
+ builder for **`lineage@1`** — a complete, developer-friendly data-derivation DAG.
5
+
6
+ The format records _what was produced from what, by which process, under which
7
+ agents_, with optional confidence and semantic relations. Semantics are grounded
8
+ in [W3C PROV-DM](https://www.w3.org/TR/prov-dm/) while the JSON stays ergonomic
9
+ for application code.
10
+
11
+ [OpenParser](https://openparser.dev) · [Docs](https://docs.openparser.dev)
12
+
13
+ ## Install
14
+
15
+ ```bash
16
+ npm install @openparser/lineage
17
+ ```
18
+
19
+ Import schemas and helpers from the package root:
20
+
21
+ ```ts
22
+ import {
23
+ LINEAGE_FORMAT,
24
+ LineageBuilder,
25
+ parseLineageDocument,
26
+ topologicalEntityOrder,
27
+ toProvJson,
28
+ type LineageDocument,
29
+ } from '@openparser/lineage';
30
+ ```
31
+
32
+ The package also ships the Draft 2020-12 JSON Schema at
33
+ `@openparser/lineage/schema.json`, with canonical id
34
+ `https://docs.openparser.dev/schemas/lineage/v1/schema.json`. JSON Schema validates
35
+ the wire shape. `parseLineageDocument` additionally enforces reference
36
+ resolution, unique producers, and acyclicity.
37
+
38
+ The package root is `lineage@1` and only `lineage@1`. Rules that read a
39
+ namespaced attribute, or that decide what a named confidence method computes,
40
+ belong to a profile and ship separately — OpenParser's own live at
41
+ `@openparser/lineage/openparser`. Producers other than OpenParser use the root
42
+ and need none of it.
43
+
44
+ ## Why `lineage@1`
45
+
46
+ Many systems need a portable record of how values, files, evidence, and
47
+ decisions were derived — not only “this job ran,” but the full dependency graph
48
+ of intermediate results. `lineage@1` is that graph:
49
+
50
+ | Concept | Role |
51
+ | -------------- | ----------------------------------------------------------------------- |
52
+ | **Entity** | A value, artifact, evidence item, decision, or collection |
53
+ | **Activity** | A process that used and/or generated entities |
54
+ | **Agent** | A person, organization, or software actor |
55
+ | **Derivation** | Output-centric edge: one activity produced one output from typed inputs |
56
+ | **Relation** | `member_of`, `specialization_of`, `alternate_of` outside the DAG |
57
+ | **Outputs** | Which entities are primary results of the document |
58
+
59
+ Derivations are **output-centric**: each derived entity has at most one producer.
60
+ Inputs carry optional roles and a `direct` / `indirect` effect flag. Activities
61
+ use an open `type` string so profiles can name domain operations without a
62
+ format bump.
63
+
64
+ Append operations preserve existing entities, activities, agents, derivations,
65
+ and relations. `outputs` is the current result projection, so an application can
66
+ replace that list when a newer derived value becomes its returned result.
67
+
68
+ Entity `path` values are
69
+ [RFC 6901 JSON Pointers](https://www.rfc-editor.org/rfc/rfc6901). A pointer
70
+ identifies one exact value; use JSONPath separately when you need a query that
71
+ can match several values.
72
+
73
+ ## Example
74
+
75
+ ```ts
76
+ import { LineageBuilder, toProvJson } from '@openparser/lineage';
77
+
78
+ const doc = new LineageBuilder()
79
+ .withId('invoice-extract-1')
80
+ .agent('model', { type: 'software', name: 'extractor@2' })
81
+ .entity('pdf', {
82
+ kind: 'artifact',
83
+ name: 'invoice.pdf',
84
+ locator: { uri: 's3://bucket/invoice.pdf', mediaType: 'application/pdf' },
85
+ digest: { algorithm: 'sha256', value: '…' },
86
+ })
87
+ .entity('total', {
88
+ kind: 'value',
89
+ path: '/total',
90
+ value: 42.5,
91
+ confidence: [
92
+ {
93
+ score: 0.97,
94
+ scale: { min: 0, max: 1 },
95
+ kind: 'reported',
96
+ scope: 'extraction',
97
+ calibrated: false,
98
+ },
99
+ ],
100
+ })
101
+ .activity('extract', {
102
+ type: 'ai.extract',
103
+ status: 'ended',
104
+ startedAt: '2024-06-01T12:00:00.000Z',
105
+ endedAt: '2024-06-01T12:00:02.000Z',
106
+ associations: [{ agent: 'model', role: 'executor' }],
107
+ parameters: { fields: ['total'] },
108
+ })
109
+ .derive({
110
+ id: 'd-total',
111
+ output: 'total',
112
+ activity: 'extract',
113
+ inputs: [{ entity: 'pdf', role: 'document', effect: 'direct' }],
114
+ })
115
+ .withOutputs('total')
116
+ .build();
117
+
118
+ const prov = toProvJson(doc);
119
+ ```
120
+
121
+ ## Complete DAG semantics
122
+
123
+ A document is valid only when the graph is coherent:
124
+
125
+ - IDs are globally distinct across entities, activities, agents, and derivations
126
+ - Every reference resolves (derivation I/O, associations, attributions, confidence sources, outputs, relations)
127
+ - Derivation IDs and derived outputs are unique — **one producer per derived output**
128
+ - An output cannot appear as its own input
129
+ - `member_of` targets must be `collection` entities
130
+ - The entity dependency graph induced by derivations is **acyclic**
131
+ - Activity timestamps must be RFC 3339 (offset required); `endedAt` must not precede `startedAt`
132
+
133
+ `parseLineageDocument` and `LineageBuilder.build()` enforce these rules.
134
+ Traversal helpers (`topologicalEntityOrder`, `entityAncestors`,
135
+ `entityDescendants`) operate on the validated derivation DAG.
136
+
137
+ ## Confidence
138
+
139
+ Confidence is a first-class assertion, not a naked float:
140
+
141
+ - `score` plus an explicit numeric `scale` (`min` / `max`) — **not** forced to 0..1, so original provider scales remain representable
142
+ - `kind`: `reported` | `derived` | `assessed`
143
+ - `scope`, optional `granularity`, `calibrated` flag
144
+ - optional typed `sources` (entity, activity, or agent refs), `method`, and `sampleCount`
145
+
146
+ Uncalibrated scores from different scopes or producers must not be treated as
147
+ interchangeable probabilities.
148
+
149
+ ## Extension and profiles
150
+
151
+ `profiles` lists URIs or short names that declare additional vocabulary for
152
+ activity types, selector types, attribute keys, and entity conventions. The core
153
+ format stays stable; profiles layer domain meaning.
154
+
155
+ Derivation inputs reuse OpenLineage's `direct` / `indirect` distinction, and its
156
+ transformation vocabulary reads well in `Transformation.type`: `identity`,
157
+ `transformation`, `aggregation`, `join`, `group_by`, `filter`,
158
+ `sort`, `window`, and `conditional`. `Transformation.type` remains extensible
159
+ for domain profiles, and `masking` records whether an operation obscured its
160
+ input.
161
+
162
+ OpenParser extraction lineage uses
163
+ `https://docs.openparser.dev/lineage/openparser` to
164
+ identify its document-region selectors and extraction conventions.
165
+
166
+ All published object schemas are **strict**. Incompatible shape changes require a
167
+ new `format` revision (`lineage@2`, …).
168
+
169
+ ## W3C PROV mapping
170
+
171
+ `toProvJson` projects a validated document into [PROV-JSON](https://www.w3.org/Submission/2013/SUBM-prov-json-20130424/)
172
+ structures:
173
+
174
+ | lineage@1 | PROV-JSON |
175
+ | ------------------------------------ | ---------------------------------- |
176
+ | entities / activities / agents | `entity` / `activity` / `agent` |
177
+ | derivation (per input) | `wasDerivedFrom` |
178
+ | derivation output ← activity | `wasGeneratedBy` |
179
+ | derivation input ← activity | `used` |
180
+ | activity associations | `wasAssociatedWith` |
181
+ | entity attributions | `wasAttributedTo` |
182
+ | `member_of` | `hadMember` |
183
+ | `specialization_of` / `alternate_of` | `specializationOf` / `alternateOf` |
184
+
185
+ Arbitrary lineage ids are deterministically encoded as qualified names in the
186
+ declared `lineage` namespace. Entity, activity, and agent records retain their
187
+ original id in `lineage:id`.
188
+
189
+ **Status note:** PROV-JSON is a W3C _Member Submission_. The underlying data model,
190
+ [PROV-DM](https://www.w3.org/TR/prov-dm/), is a W3C _Recommendation_. This package
191
+ uses PROV-JSON as an interchange projection while treating PROV-DM as the
192
+ semantic reference.
193
+
194
+ ## Complementary systems
195
+
196
+ `lineage@1` records **complete data derivation**. That complements, rather than
197
+ replaces:
198
+
199
+ - **[OpenLineage](https://openlineage.io/)** — job/run and dataset facet events for
200
+ data-platform observability; map runs to activities and datasets to entities
201
+ when you need operational event streams alongside a closed derivation DAG.
202
+ - **[OpenTelemetry](https://opentelemetry.io/)** — distributed traces, metrics, and
203
+ logs for runtime performance and debugging; span/trace ids can sit in activity
204
+ `attributes` without conflating telemetry with provenance.
205
+
206
+ Use those systems for where/when work ran in a fleet; use `lineage@1` for what
207
+ each datum depended on.
208
+
209
+ ## License
210
+
211
+ [Apache-2.0](./LICENSE)
@@ -0,0 +1,74 @@
1
+ import { z } from 'zod';
2
+ /** How an agent relates to an activity (PROV wasAssociatedWith). */
3
+ export declare const AssociationSchema: z.ZodObject<{
4
+ agent: z.ZodString;
5
+ role: z.ZodOptional<z.ZodString>;
6
+ attributes: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodJSONSchema>>;
7
+ }, z.core.$strict>;
8
+ export type Association = z.infer<typeof AssociationSchema>;
9
+ export declare const ACTIVITY_STATUSES: readonly ["scheduled", "started", "ended", "failed", "cancelled"];
10
+ export declare const ActivityStatusSchema: z.ZodEnum<{
11
+ scheduled: "scheduled";
12
+ started: "started";
13
+ ended: "ended";
14
+ failed: "failed";
15
+ cancelled: "cancelled";
16
+ }>;
17
+ export type ActivityStatus = z.infer<typeof ActivityStatusSchema>;
18
+ /**
19
+ * Optional description of the concrete implementation that performed an
20
+ * activity (library, model, service, script, binary, …).
21
+ */
22
+ export declare const ImplementationSchema: z.ZodObject<{
23
+ type: z.ZodOptional<z.ZodString>;
24
+ name: z.ZodOptional<z.ZodString>;
25
+ version: z.ZodOptional<z.ZodString>;
26
+ uri: z.ZodOptional<z.ZodString>;
27
+ attributes: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodJSONSchema>>;
28
+ }, z.core.$strict>;
29
+ export type Implementation = z.infer<typeof ImplementationSchema>;
30
+ /**
31
+ * A process that used and/or generated entities. `type` is an open string so
32
+ * profiles can introduce domain-specific activity types without a format bump.
33
+ *
34
+ * Map keys in `LineageDocument.activities` are the authoritative activity ids.
35
+ */
36
+ export declare const ActivitySchema: z.ZodObject<{
37
+ type: z.ZodString;
38
+ name: z.ZodOptional<z.ZodString>;
39
+ status: z.ZodOptional<z.ZodEnum<{
40
+ scheduled: "scheduled";
41
+ started: "started";
42
+ ended: "ended";
43
+ failed: "failed";
44
+ cancelled: "cancelled";
45
+ }>>;
46
+ startedAt: z.ZodOptional<z.ZodISODateTime>;
47
+ endedAt: z.ZodOptional<z.ZodISODateTime>;
48
+ implementation: z.ZodOptional<z.ZodObject<{
49
+ type: z.ZodOptional<z.ZodString>;
50
+ name: z.ZodOptional<z.ZodString>;
51
+ version: z.ZodOptional<z.ZodString>;
52
+ uri: z.ZodOptional<z.ZodString>;
53
+ attributes: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodJSONSchema>>;
54
+ }, z.core.$strict>>;
55
+ parameters: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodJSONSchema>>;
56
+ associations: z.ZodOptional<z.ZodArray<z.ZodObject<{
57
+ agent: z.ZodString;
58
+ role: z.ZodOptional<z.ZodString>;
59
+ attributes: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodJSONSchema>>;
60
+ }, z.core.$strict>>>;
61
+ attributes: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodJSONSchema>>;
62
+ }, z.core.$strict>;
63
+ export type Activity = z.infer<typeof ActivitySchema>;
64
+ /**
65
+ * An agent (person, organization, software, service) that acts or is
66
+ * attributed. Map keys in `LineageDocument.agents` are the authoritative ids.
67
+ */
68
+ export declare const AgentSchema: z.ZodObject<{
69
+ type: z.ZodOptional<z.ZodString>;
70
+ name: z.ZodOptional<z.ZodString>;
71
+ attributes: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodJSONSchema>>;
72
+ }, z.core.$strict>;
73
+ export type Agent = z.infer<typeof AgentSchema>;
74
+ //# sourceMappingURL=activity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activity.d.ts","sourceRoot":"","sources":["../src/activity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,oEAAoE;AACpE,eAAO,MAAM,iBAAiB;;;;kBAMnB,CAAC;AACZ,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE5D,eAAO,MAAM,iBAAiB,mEAAoE,CAAC;AACnG,eAAO,MAAM,oBAAoB;;;;;;EAA4B,CAAC;AAC9D,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE;;;GAGG;AACH,eAAO,MAAM,oBAAoB;;;;;;kBAQtB,CAAC;AACZ,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE;;;;;GAKG;AACH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;kBAYhB,CAAC;AACZ,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAEtD;;;GAGG;AACH,eAAO,MAAM,WAAW;;;;kBAMb,CAAC;AACZ,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC"}
@@ -0,0 +1,24 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Who currently stands behind this entity's value.
4
+ *
5
+ * An assertion names an agent and a time; it does not change the entity.
6
+ * OpenParser extraction review projects this from confirmations rather than
7
+ * storing a separate approve event: an actor counts when their newest live
8
+ * confirmation on this path names the value this entity holds. Confirming a
9
+ * matching value adds standing without minting a new entity; confirming a
10
+ * different value mints a new entity, and standing on the predecessor is left
11
+ * behind. That is why a sign-off never describes a value nobody confirmed.
12
+ *
13
+ * Standing is per entity and does not propagate. Confirming a field says
14
+ * nothing about the region it was read from — that region carries its own
15
+ * standing if someone confirms it.
16
+ */
17
+ export declare const ApprovalAssertionSchema: z.ZodObject<{
18
+ agent: z.ZodString;
19
+ at: z.ZodString;
20
+ note: z.ZodOptional<z.ZodString>;
21
+ attributes: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodJSONSchema>>;
22
+ }, z.core.$strict>;
23
+ export type ApprovalAssertion = z.infer<typeof ApprovalAssertionSchema>;
24
+ //# sourceMappingURL=approval.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approval.d.ts","sourceRoot":"","sources":["../src/approval.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,uBAAuB;;;;;kBAQzB,CAAC;AACZ,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC"}