citevahti 0.8.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.
- citevahti-0.8.0/.gitignore +13 -0
- citevahti-0.8.0/CHANGELOG.md +480 -0
- citevahti-0.8.0/LICENSE +201 -0
- citevahti-0.8.0/NOTICE +10 -0
- citevahti-0.8.0/PKG-INFO +268 -0
- citevahti-0.8.0/README.md +245 -0
- citevahti-0.8.0/pyproject.toml +48 -0
- citevahti-0.8.0/src/citevahti/__init__.py +29 -0
- citevahti-0.8.0/src/citevahti/agent/__init__.py +40 -0
- citevahti-0.8.0/src/citevahti/agent/mcp_server.py +71 -0
- citevahti-0.8.0/src/citevahti/agent/policy.py +47 -0
- citevahti-0.8.0/src/citevahti/agent/tools.py +184 -0
- citevahti-0.8.0/src/citevahti/assess/__init__.py +9 -0
- citevahti-0.8.0/src/citevahti/assess/service.py +102 -0
- citevahti-0.8.0/src/citevahti/bbt/__init__.py +5 -0
- citevahti-0.8.0/src/citevahti/bbt/client.py +66 -0
- citevahti-0.8.0/src/citevahti/bibsync/__init__.py +23 -0
- citevahti-0.8.0/src/citevahti/bibsync/extract.py +140 -0
- citevahti-0.8.0/src/citevahti/bibsync/provider.py +87 -0
- citevahti-0.8.0/src/citevahti/bibsync/service.py +207 -0
- citevahti-0.8.0/src/citevahti/bootstrap/__init__.py +10 -0
- citevahti-0.8.0/src/citevahti/bootstrap/service.py +135 -0
- citevahti-0.8.0/src/citevahti/capabilities.py +149 -0
- citevahti-0.8.0/src/citevahti/cite.py +95 -0
- citevahti-0.8.0/src/citevahti/claimcheck/__init__.py +9 -0
- citevahti-0.8.0/src/citevahti/claimcheck/service.py +78 -0
- citevahti-0.8.0/src/citevahti/claims/__init__.py +16 -0
- citevahti-0.8.0/src/citevahti/claims/candidates.py +81 -0
- citevahti-0.8.0/src/citevahti/claims/decisions.py +85 -0
- citevahti-0.8.0/src/citevahti/claims/service.py +101 -0
- citevahti-0.8.0/src/citevahti/claims/support.py +217 -0
- citevahti-0.8.0/src/citevahti/cli.py +1478 -0
- citevahti-0.8.0/src/citevahti/corpus/__init__.py +21 -0
- citevahti-0.8.0/src/citevahti/corpus/diff.py +162 -0
- citevahti-0.8.0/src/citevahti/corpus/snapshot.py +70 -0
- citevahti-0.8.0/src/citevahti/corpus/source.py +156 -0
- citevahti-0.8.0/src/citevahti/credentials.py +152 -0
- citevahti-0.8.0/src/citevahti/evidence/__init__.py +11 -0
- citevahti-0.8.0/src/citevahti/evidence/map_ops.py +217 -0
- citevahti-0.8.0/src/citevahti/export/__init__.py +10 -0
- citevahti-0.8.0/src/citevahti/export/agreement.py +319 -0
- citevahti-0.8.0/src/citevahti/export/evidence.py +290 -0
- citevahti-0.8.0/src/citevahti/export/kappa.py +56 -0
- citevahti-0.8.0/src/citevahti/extract/__init__.py +9 -0
- citevahti-0.8.0/src/citevahti/extract/fields.py +96 -0
- citevahti-0.8.0/src/citevahti/extract/service.py +88 -0
- citevahti-0.8.0/src/citevahti/intake/__init__.py +25 -0
- citevahti-0.8.0/src/citevahti/intake/dedupe.py +105 -0
- citevahti-0.8.0/src/citevahti/intake/manual.py +145 -0
- citevahti-0.8.0/src/citevahti/intake/service.py +225 -0
- citevahti-0.8.0/src/citevahti/onboarding.py +175 -0
- citevahti-0.8.0/src/citevahti/prisma/__init__.py +6 -0
- citevahti-0.8.0/src/citevahti/prisma/service.py +117 -0
- citevahti-0.8.0/src/citevahti/probe/__init__.py +30 -0
- citevahti-0.8.0/src/citevahti/probe/client.py +67 -0
- citevahti-0.8.0/src/citevahti/probe/probe.py +201 -0
- citevahti-0.8.0/src/citevahti/pubmed/__init__.py +25 -0
- citevahti-0.8.0/src/citevahti/pubmed/parse.py +97 -0
- citevahti-0.8.0/src/citevahti/pubmed/provider.py +217 -0
- citevahti-0.8.0/src/citevahti/rating/__init__.py +11 -0
- citevahti-0.8.0/src/citevahti/rating/ai.py +43 -0
- citevahti-0.8.0/src/citevahti/rating/engine.py +165 -0
- citevahti-0.8.0/src/citevahti/report/__init__.py +6 -0
- citevahti-0.8.0/src/citevahti/report/claim_report.py +116 -0
- citevahti-0.8.0/src/citevahti/report/markdown.py +81 -0
- citevahti-0.8.0/src/citevahti/retraction/__init__.py +21 -0
- citevahti-0.8.0/src/citevahti/retraction/provider.py +51 -0
- citevahti-0.8.0/src/citevahti/retraction/service.py +115 -0
- citevahti-0.8.0/src/citevahti/retrieval/__init__.py +24 -0
- citevahti-0.8.0/src/citevahti/retrieval/service.py +116 -0
- citevahti-0.8.0/src/citevahti/retrieval/source.py +125 -0
- citevahti-0.8.0/src/citevahti/retrieval/text.py +62 -0
- citevahti-0.8.0/src/citevahti/schemas/__init__.py +90 -0
- citevahti-0.8.0/src/citevahti/schemas/bibsync.py +38 -0
- citevahti-0.8.0/src/citevahti/schemas/bootstrap.py +43 -0
- citevahti-0.8.0/src/citevahti/schemas/candidate.py +63 -0
- citevahti-0.8.0/src/citevahti/schemas/claim.py +55 -0
- citevahti-0.8.0/src/citevahti/schemas/claim_support.py +89 -0
- citevahti-0.8.0/src/citevahti/schemas/claimcheck.py +36 -0
- citevahti-0.8.0/src/citevahti/schemas/common.py +95 -0
- citevahti-0.8.0/src/citevahti/schemas/config.py +217 -0
- citevahti-0.8.0/src/citevahti/schemas/corpus.py +44 -0
- citevahti-0.8.0/src/citevahti/schemas/decision.py +45 -0
- citevahti-0.8.0/src/citevahti/schemas/evidence_map.py +118 -0
- citevahti-0.8.0/src/citevahti/schemas/export.py +66 -0
- citevahti-0.8.0/src/citevahti/schemas/extract.py +36 -0
- citevahti-0.8.0/src/citevahti/schemas/frame.py +120 -0
- citevahti-0.8.0/src/citevahti/schemas/intake.py +88 -0
- citevahti-0.8.0/src/citevahti/schemas/passage.py +39 -0
- citevahti-0.8.0/src/citevahti/schemas/prisma.py +44 -0
- citevahti-0.8.0/src/citevahti/schemas/rating.py +130 -0
- citevahti-0.8.0/src/citevahti/schemas/report.py +69 -0
- citevahti-0.8.0/src/citevahti/schemas/results.py +79 -0
- citevahti-0.8.0/src/citevahti/schemas/snapshot.py +56 -0
- citevahti-0.8.0/src/citevahti/schemas/transaction.py +43 -0
- citevahti-0.8.0/src/citevahti/schemas/validation_record.py +60 -0
- citevahti-0.8.0/src/citevahti/schemas/writeback.py +59 -0
- citevahti-0.8.0/src/citevahti/state/__init__.py +6 -0
- citevahti-0.8.0/src/citevahti/state/audit.py +90 -0
- citevahti-0.8.0/src/citevahti/state/store.py +488 -0
- citevahti-0.8.0/src/citevahti/tools.py +657 -0
- citevahti-0.8.0/src/citevahti/util.py +51 -0
- citevahti-0.8.0/src/citevahti/validators/__init__.py +46 -0
- citevahti-0.8.0/src/citevahti/validators/candidate.py +30 -0
- citevahti-0.8.0/src/citevahti/validators/claim.py +27 -0
- citevahti-0.8.0/src/citevahti/validators/claim_support.py +97 -0
- citevahti-0.8.0/src/citevahti/validators/config.py +52 -0
- citevahti-0.8.0/src/citevahti/validators/decision.py +42 -0
- citevahti-0.8.0/src/citevahti/validators/errors.py +39 -0
- citevahti-0.8.0/src/citevahti/validators/evidence_map.py +160 -0
- citevahti-0.8.0/src/citevahti/validators/frame.py +57 -0
- citevahti-0.8.0/src/citevahti/validators/intake.py +35 -0
- citevahti-0.8.0/src/citevahti/validators/prisma.py +32 -0
- citevahti-0.8.0/src/citevahti/validators/probe.py +27 -0
- citevahti-0.8.0/src/citevahti/validators/rating.py +145 -0
- citevahti-0.8.0/src/citevahti/validators/transaction.py +34 -0
- citevahti-0.8.0/src/citevahti/warehouse.py +106 -0
- citevahti-0.8.0/src/citevahti/writeback/__init__.py +32 -0
- citevahti-0.8.0/src/citevahti/writeback/backend.py +155 -0
- citevahti-0.8.0/src/citevahti/writeback/layer.py +175 -0
- citevahti-0.8.0/src/citevahti/writeback/service.py +310 -0
- citevahti-0.8.0/src/citevahti/writeback/transaction.py +188 -0
- citevahti-0.8.0/src/citevahti/writeback/webapi.py +200 -0
- citevahti-0.8.0/src/citevahti/zotero/__init__.py +21 -0
- citevahti-0.8.0/src/citevahti/zotero/connect.py +160 -0
- citevahti-0.8.0/src/citevahti/zotero/library.py +59 -0
- citevahti-0.8.0/src/citevahti/zotero/read.py +274 -0
|
@@ -0,0 +1,480 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to CiteVahti (a product of Vahtian; formerly developed as
|
|
4
|
+
ZotSynth). The project was built in reviewed steps, each on its own branch off the
|
|
5
|
+
previous one.
|
|
6
|
+
|
|
7
|
+
## Unreleased
|
|
8
|
+
|
|
9
|
+
_Nothing yet._
|
|
10
|
+
|
|
11
|
+
## 0.8.0 — Full rename to CiteVahti + a richer inline review card (2026-06-05)
|
|
12
|
+
|
|
13
|
+
The product fully sheds the `zotsynth` name (ADR-0006), the inline evidence card
|
|
14
|
+
gains the data a researcher actually weighs, and "Change reference" becomes a real
|
|
15
|
+
search-and-link flow. Folds in the post-0.7.0 work (rebrand, guided Zotero
|
|
16
|
+
connect, safety hardening, QUICKSTART). 502 offline tests.
|
|
17
|
+
|
|
18
|
+
- **refactor(rename): full rename `zotsynth` → `citevahti` (ADR-0006).** The
|
|
19
|
+
importable package (`src/citevahti/`), the CLI (only `citevahti` /
|
|
20
|
+
`citevahti-mcp` now), the OS-keychain service (`CiteVahti`), the env vars
|
|
21
|
+
(`CITEVAHTI_*`), and the on-disk state dir (`.citevahti/`) all move to the brand
|
|
22
|
+
name; `ZotSynthStore` → `CiteVahtiStore`. **Supersedes ADR-0004 §2.3a/§6** (the
|
|
23
|
+
stable-alias decision): pre-1.0, single-user, no installed base, so the
|
|
24
|
+
disruptive rename is free now and won't be later. History (ADRs, this changelog,
|
|
25
|
+
release notes) keeps the old name as the record.
|
|
26
|
+
- **feat(report): PICO fit + excerpt on the inline evidence card.** The report now
|
|
27
|
+
surfaces — **only from the committed human rating, never the blinded AI** — each
|
|
28
|
+
candidate's PICO + claim fit subscores, a citation-fit score (`n/8`,
|
|
29
|
+
Strong/Moderate/Weak), and the supporting excerpt, rendered as fit-check chips on
|
|
30
|
+
the VS Code card. Mirrors the existing `ai_support` blinding so the card can't
|
|
31
|
+
leak the AI assessment. +1 test.
|
|
32
|
+
- **feat(change-ref): a real "Change reference" flow.** New `--json` output on
|
|
33
|
+
`literature-search` (batch id + staged hits) and `claim-link-candidates`
|
|
34
|
+
(linked/skipped/total); the VS Code **"⇄ Change reference…"** action searches
|
|
35
|
+
PubMed (verbatim query), lets you pick results, and links them as new candidates.
|
|
36
|
+
Swapping among already-linked candidates is afforded directly on the card. Links
|
|
37
|
+
only — no rating, decision, or Zotero write. +2 tests.
|
|
38
|
+
- **docs(readme): "Try it" + "What to test".** A followable 4-step inline-review
|
|
39
|
+
walk-through and a what-to-test block (offline suite + extension build + a manual
|
|
40
|
+
acceptance checklist); fixes the rename artifact in the header note and the test
|
|
41
|
+
count (→ 502).
|
|
42
|
+
- **fix(safety): stress-test findings — preview-first CLI write + honest Zotero scope.**
|
|
43
|
+
- **Sev-4 (the important one):** `claim-commit --commit` no longer one-call writes.
|
|
44
|
+
Without `--confirm-token` it now **shows the preview and requires explicit
|
|
45
|
+
confirmation** (interactive `y/N`); non-interactive callers (scripts/agents)
|
|
46
|
+
must replay the token, and `--json` returns `preview_required /
|
|
47
|
+
missing_confirm_token` — so nothing is ever written unseen. `claim-decide`'s
|
|
48
|
+
hint reworded to "review+write (shows a preview and asks)".
|
|
49
|
+
- **Sev-3:** `connect-zotero` now reports **personal-library write vs group-library
|
|
50
|
+
access** honestly (no false confidence), adds `--groups none|read|write` (and a
|
|
51
|
+
VS Code "Include shared/group" choice) to pre-select shared-library scope.
|
|
52
|
+
- **Sev-2:** `decision-list` now prints each `decision_id` (+ the `claim-commit`
|
|
53
|
+
command) so the write id is recoverable; PyPI build verified end-to-end and the
|
|
54
|
+
recipe captured in `docs/RELEASING.md`.
|
|
55
|
+
- **Sev-1:** README test count corrected (→ 499).
|
|
56
|
+
- **docs: `QUICKSTART.md` — zero to first verified citation (~10 min).** Install →
|
|
57
|
+
`connect-zotero` → add a claim → PubMed search → rate → decide → guarded write →
|
|
58
|
+
report, with both the VS Code review loop and the full CLI path. Linked from the
|
|
59
|
+
README. Also: `claim-decide` now prints the `decision_id` and the exact
|
|
60
|
+
`claim-commit` command (removes a `decision-list` lookup on the CLI write path).
|
|
61
|
+
- **feat(zotero): guided one-paste connection — no hand-crafted API keys (ADR-0005).**
|
|
62
|
+
A spike confirmed Zotero's local API is read-only and the connector write path is
|
|
63
|
+
fragile/undocumented, and that OAuth needs a callback server (→ a hosted feature).
|
|
64
|
+
So the beta connects keyless reads + a **one-paste key** for writes:
|
|
65
|
+
`citevahti connect-zotero` (and the VS Code **“Connect Zotero”** command) opens
|
|
66
|
+
Zotero's new-key page **pre-filled** (name + `write_access=1`), takes the pasted
|
|
67
|
+
key, validates it against the Web API, **learns the userID automatically**, stores
|
|
68
|
+
the key in the **OS keychain** (never config/argv/logs — the extension passes it
|
|
69
|
+
by env), and enables the guarded `web_api` backend. Read-only/invalid keys are
|
|
70
|
+
refused; write-back stays decision-gated, previewed, and undoable. New
|
|
71
|
+
`zotero.ZoteroConnectService`, `tools.connect_zotero` / `zotero_new_key_url`,
|
|
72
|
+
`connect-zotero` CLI, and the `citevahti.connectZotero` command. +9 tests.
|
|
73
|
+
- **chore(brand): rebrand the product to CiteVahti (a product of Vahtian).** The
|
|
74
|
+
distribution is now `citevahti`; the CLI is `citevahti` / `citevahti-mcp`; the VS
|
|
75
|
+
Code extension is `vahtian.citevahti` (command `CiteVahti: Verify claims`, config
|
|
76
|
+
namespace `citevahti.*`); README, NOTICE, and forward-facing docs are rebranded.
|
|
77
|
+
**Kept as stable aliases so nothing breaks:** the Python import path `zotsynth`,
|
|
78
|
+
the `zotsynth` / `zotsynth-mcp` CLI commands, the `ZotSynth` OS-keychain service
|
|
79
|
+
(stored secrets survive), and the `.zotsynth/` state directory. See
|
|
80
|
+
[ADR-0004](docs/adr/0004-brand-ip-and-entity.md). Also fixed a stale
|
|
81
|
+
`__version__` (0.6.0 → 0.7.0).
|
|
82
|
+
- **docs: add `CONTRIBUTING.md`** — DCO sign-off gate + the open-core ground rules,
|
|
83
|
+
so external contributions come in cleanly and the Apache/BSL boundary holds.
|
|
84
|
+
|
|
85
|
+
## 0.7.0 — Manuscript surfaces: interactive review, editor report, revision diff (2026-06-04)
|
|
86
|
+
|
|
87
|
+
The manuscript becomes the workspace. Three surfaces over the one ledger
|
|
88
|
+
(claim → candidate → blinded rating → decision → guarded write): an **inline
|
|
89
|
+
VS Code review loop**, an **editor-mode Markdown report** for supervisors/editors,
|
|
90
|
+
and an **agent-proposes / human-accepts revision diff**. Hardened across two
|
|
91
|
+
headless-reviewer passes and a **live VS Code F5 pass** (disposable workspace +
|
|
92
|
+
fake Zotero Web API): the decision loop, preview→commit collection/token binding,
|
|
93
|
+
and undo all verified live; the revision-accept path verified live after the
|
|
94
|
+
manuscript-location fix below.
|
|
95
|
+
|
|
96
|
+
- **fix(F5): bugs found and fixed during the live extension run.**
|
|
97
|
+
- **Undo retry no longer carries a stale `undo_unavailable`.** A successful undo
|
|
98
|
+
after a prior failed one now clears `error_code`/`remediation`
|
|
99
|
+
([writeback/transaction.py]); regression test
|
|
100
|
+
`test_successful_retry_clears_prior_undo_failure_fields`.
|
|
101
|
+
- **Nonce-based webview CSP.** The panel sets
|
|
102
|
+
`default-src 'none'; style-src/script-src 'nonce-…'` and stamps the inline
|
|
103
|
+
`<style>`/`<script>` with the nonce — no missing-CSP warning, no inline-script
|
|
104
|
+
escape hatch.
|
|
105
|
+
- **Revision accept no longer depends on the active editor.** The pending rewrite
|
|
106
|
+
carries `manuscript_location` to the webview; accept opens the manuscript from
|
|
107
|
+
that location if needed, then applies the edit.
|
|
108
|
+
- **fix(safety): headless-reviewer hardening of the write + revision paths.**
|
|
109
|
+
- The card's **preview→commit is now tightly bound**: the preview sends
|
|
110
|
+
`--collection-key` and the commit replays the preview's **`confirm_token`**
|
|
111
|
+
(`--confirm-token`) — no commit without a confirmable preview, and the target
|
|
112
|
+
collection is shown in the confirm modal.
|
|
113
|
+
- **`oo` no longer double-records.** A single-`o` keypress is held on a short
|
|
114
|
+
timer so a fast `o o` resolves to one `accept`, never `accepted_with_caution`
|
|
115
|
+
then `accept`.
|
|
116
|
+
- **Revision accept can no longer diverge** manuscript text from ZotSynth state:
|
|
117
|
+
single-span selection / duplicate guard, rollback of the manuscript edit if the
|
|
118
|
+
CLI fails, and a **stale-diff guard** — `claim-accept-revision --expected-text`
|
|
119
|
+
(and `accept_revision(expected_text=…)`) refuses to apply if the pending rewrite
|
|
120
|
+
changed since it was previewed.
|
|
121
|
+
- **feat(revision): the revision-diff loop — propose → review the diff → accept/reject.**
|
|
122
|
+
A claim can carry a *pending rewrite*. An agent may **propose** one
|
|
123
|
+
(`propose_revision`, flagged `ai` with a pinned model) but can **never apply** it
|
|
124
|
+
(`accept_revision` is a forbidden agent capability); only a human accepts. The
|
|
125
|
+
inline card renders the pending rewrite as a **−was / +now diff** with *Accept
|
|
126
|
+
revision* / *Keep original*, plus *✎ Revise wording…* for a human-authored
|
|
127
|
+
rewrite. **Accept applies a visible `WorkspaceEdit`** to the manuscript text and
|
|
128
|
+
then updates the stored claim — the claim text is **never silently edited**, and
|
|
129
|
+
the change is audited with the before/after. New CLI: `claim-propose-revision`,
|
|
130
|
+
`claim-accept-revision`, `claim-reject-revision`; the report row + editor-mode
|
|
131
|
+
Markdown surface the pending rewrite.
|
|
132
|
+
- **feat(vscode): the interactive `oo/o/r/d` decision loop.** Expanding a claim
|
|
133
|
+
shows its candidate evidence cards (paper, human rating, AI rating *blinded
|
|
134
|
+
until the human rates*, recorded decision). Focus a candidate and press a
|
|
135
|
+
fit-code (or click): `oo`→accept · `o`→accepted_with_caution · `r`→
|
|
136
|
+
needs_second_review · `d`→reject. The extension prompts for a reason and runs
|
|
137
|
+
`claim-decide` (the human decides; ZotSynth records/audits/undoes), then
|
|
138
|
+
refreshes the report + decorations. The mission invariant is enforced by the
|
|
139
|
+
CLI and surfaced in the UI.
|
|
140
|
+
- **feat(report): evidence carries `rating_id` + blinded human/AI support** so the
|
|
141
|
+
card has what it needs to act (the AI value is `"hidden"` until the human rates).
|
|
142
|
+
- **feat(report): editor-mode Markdown report (`--format md`).** A shareable
|
|
143
|
+
**Citation-Integrity Report** for supervisors / journal editors / methodologists
|
|
144
|
+
— read-only, claim-by-claim with state, evidence, ratings, and decisions, an
|
|
145
|
+
"attention needed" section, and a non-overclaim footer. `claim-report --format
|
|
146
|
+
text|md|json --output <file>`; new `report.render_markdown`. No Zotero write.
|
|
147
|
+
- **feat(vscode): staged, undoable Zotero write from the card.** "✓ Add to Zotero"
|
|
148
|
+
on an accepted candidate **previews** (`claim-commit --json` dry-run; you confirm
|
|
149
|
+
the item + dedupe status), **commits** through the decision-gated transaction,
|
|
150
|
+
and offers **Undo** (deletes only what it created). `dedupe_unverified` surfaces
|
|
151
|
+
an explicit *Override and add* — never a silent duplicate. Adds `--json` to
|
|
152
|
+
`claim-commit` / `txn-undo`, `decision_id` to the report evidence, and a
|
|
153
|
+
`zotsynth.collectionKey` setting.
|
|
154
|
+
|
|
155
|
+
## 0.6.0 — citation-integrity report + VS Code surface + Apache-2.0
|
|
156
|
+
|
|
157
|
+
Tag: `v0.6.0`. The 4-state report (the VS Code / editor / agent data) and the VS Code
|
|
158
|
+
extension first cut; relicensed to Apache-2.0.
|
|
159
|
+
|
|
160
|
+
- **feat(report): the 4-state citation-integrity report.** Treats the manuscript
|
|
161
|
+
like code — each claim is a unit test whose state is *derived* (read-only) from
|
|
162
|
+
the ledger: `[oo] verified` (accepted supporting evidence), `[o ] needs_support`
|
|
163
|
+
(no accepted evidence yet), `[r ] review_needed` (unresolved discordance / a
|
|
164
|
+
2nd-review decision), `[d ] decision_recorded` (all candidates settled, none
|
|
165
|
+
accepted). New `schemas/report.py`, `report/ClaimReportService`,
|
|
166
|
+
`tools.claim_report`, and a CI-style `claim-report` CLI (`--json` for tooling;
|
|
167
|
+
exits non-zero when claims still need attention).
|
|
168
|
+
- **feat(agent): `verify_claims`** — the read-only report added to the constrained
|
|
169
|
+
agent surface so an agent can run the citation tests (still no write power).
|
|
170
|
+
- **feat(vscode): VS Code extension (first cut).** `vscode-extension/` — a thin
|
|
171
|
+
client over `claim-report --json` that highlights each claim in the open
|
|
172
|
+
manuscript by its 4-state result (amber/teal/violet/rose, no green/red) and
|
|
173
|
+
shows a side report. The interactive `oo/o/r/d` keystroke flow + evidence-card
|
|
174
|
+
popover (prototyped in `mockups/zotsynth-inline/`) wire to the MCP tools next.
|
|
175
|
+
|
|
176
|
+
## 0.5.0 — constrained agent (MCP) surface
|
|
177
|
+
|
|
178
|
+
Tag: `v0.5.0`. ZotSynth is now safely callable by AI agents (MCP): capability without power.
|
|
179
|
+
|
|
180
|
+
- **feat(agent): the constrained agent tool surface.** Exposes ZotSynth to AI
|
|
181
|
+
agents (Codex/Claude Code) as a small, fixed set of safe verbs — *capability
|
|
182
|
+
without power*. `pubmed_search`, `propose_claim`, `link_candidates`,
|
|
183
|
+
`start_support_rating`, `submit_ai_support_rating` (recorded **blind**, value
|
|
184
|
+
not echoed), `preview_write` → `commit_write(approval_token)`, `undo`,
|
|
185
|
+
`get_provenance` (AI rating **blinded until the human rates**), `status`. An
|
|
186
|
+
agent can NEVER reach a raw Zotero write, a one-call commit, the human's rating,
|
|
187
|
+
the final decision, the AI rating before the human, or credentials — enforced by
|
|
188
|
+
`agent/policy.py` (asserted at import + serve). New `agent/` package, a lazy
|
|
189
|
+
`mcp-serve` MCP server (`zotsynth-mcp`, optional `[mcp]` extra), `agent-tools`
|
|
190
|
+
CLI, `ClaimSupportEngine.submit_ai_rating`, and `docs/AGENT.md`. +9 tests.
|
|
191
|
+
|
|
192
|
+
## 0.4.1 — beta hardening (second stress test)
|
|
193
|
+
|
|
194
|
+
Tag: `v0.4.1`. Closes the agent-write-boundary + dedupe-unverified findings.
|
|
195
|
+
|
|
196
|
+
- **fix(writeback): agent-write boundary — a confirmed validated write requires a
|
|
197
|
+
prior preview's approval token.** `commit_for_decision(dry_run=False)` /
|
|
198
|
+
`tools.commit_decision` now refuse (`missing_confirm_token`) unless given a
|
|
199
|
+
token from a prior dry-run preview, so an agent cannot one-call write to Zotero
|
|
200
|
+
without a user-visible preview/approval step. The CLI `claim-commit --commit`
|
|
201
|
+
previews then commits (human one-command path); an explicit `--confirm-token`
|
|
202
|
+
is also accepted.
|
|
203
|
+
- **fix(writeback): `dedupe_unverified` no longer proceeds silently.** When the
|
|
204
|
+
write-target existence check is unavailable (Zotero search down), a validated
|
|
205
|
+
write is **refused** (`dedupe_unverified`) rather than risking a duplicate;
|
|
206
|
+
override with `allow_unverified_dedupe` / `--allow-unverified-dedupe`. Dry-run
|
|
207
|
+
previews warn.
|
|
208
|
+
- **fix(writeback): block writes from `review_required` intake batches.** A batch
|
|
209
|
+
flagged for review (malformed/translated PubMed query) is blocked from
|
|
210
|
+
committing (`batch_review_required`) unless `--allow-review-required`.
|
|
211
|
+
- **fix(ui): mockup language + blinded validation.** The `d` state reads
|
|
212
|
+
**Unsupported** (not "Delete"); actions are "Remove candidate from claim" /
|
|
213
|
+
"Remove candidate + strike claim (diff)" with explicit diff/undo framing; the
|
|
214
|
+
inline mock now hides the AI rating during blinded human validation (was
|
|
215
|
+
leaking it).
|
|
216
|
+
- **fix(cli): `claim-commit --commit` returns non-zero on a non-committed write**
|
|
217
|
+
(reviewer-contributed, with a regression test).
|
|
218
|
+
|
|
219
|
+
## 0.4.0 — validation warehouse + UI direction + duplicate-safety
|
|
220
|
+
|
|
221
|
+
**First public beta milestone.** Tag: `v0.4.0`. Completes the ADR-0001 §10 build
|
|
222
|
+
sequence (the de-identified validation warehouse, step 6), records the inline
|
|
223
|
+
review-layer UI direction (ADR-0002), and closes the stress-test duplicate-safety
|
|
224
|
+
blockers. 443 tests, fully offline. Beta scope: local-first, single-user,
|
|
225
|
+
PubMed-only; the hosted layer and the VS Code review-layer UI are the next phase.
|
|
226
|
+
|
|
227
|
+
### Inline review-layer UI (ADR-0002)
|
|
228
|
+
- **docs(design): ADR-0002 — the `[oo/o/r/d]` inline review layer.** Citation
|
|
229
|
+
integrity lives *inside* the writing surface (a VS Code-style editor companion),
|
|
230
|
+
not a separate dashboard. Four operational fit-codes over the ledger
|
|
231
|
+
(`oo` supported→accept · `o` partly→accepted_with_caution · `r` revise→2nd
|
|
232
|
+
review · `d` delete→reject), four distinct accessible status hues
|
|
233
|
+
(amber/teal/violet/rose; lilac brand; no green/red), claim text never edited
|
|
234
|
+
silently (inline diffs), and the `r`/`d` cards each expose their two real
|
|
235
|
+
choices. Adds `docs/design/` (tokens, reference, logo) and runnable mockups
|
|
236
|
+
(`mockups/zotsynth-inline` primary; `zotsynth-ui` dashboard demoted to legacy).
|
|
237
|
+
|
|
238
|
+
### Duplicate-safety hardening (stress-test Sev-4)
|
|
239
|
+
|
|
240
|
+
- **fix(writeback): cross-boundary duplicate protection.** Library dedupe checks
|
|
241
|
+
the *local* Zotero API, so a paper created via the Web API but not yet synced
|
|
242
|
+
locally looked "new" and could be duplicated. Backends gain
|
|
243
|
+
`find_existing(pmid, doi)` (queries the **write target**); the validated
|
|
244
|
+
`commit_for_decision` re-checks it and **refuses** with a `failed` /
|
|
245
|
+
`duplicate_on_write_target` transaction (dry-run warns), and an uncheckable
|
|
246
|
+
result degrades to "proceed" (never blocks a write because the check was down).
|
|
247
|
+
- **fix(writeback): `intake-push` hardening.** The generic staging push now
|
|
248
|
+
enforces the same rules as the validated path — it skips `duplicate_in_run`
|
|
249
|
+
records, records with **no PMID/DOI**, items already in the local library, and
|
|
250
|
+
items already on the Web-API write target (was: staged all of them and minted a
|
|
251
|
+
token).
|
|
252
|
+
- **fix(cli): clean errors for transaction/state failures.** `_safe` now catches
|
|
253
|
+
`TransactionError` / `StateError` / `WriteUnavailable` (e.g. undoing an
|
|
254
|
+
already-undone transaction) and prints a one-line message instead of a traceback.
|
|
255
|
+
- **feat(claims): `implementation` claim type** (implementation-science claims are
|
|
256
|
+
first-class for guideline/QI users).
|
|
257
|
+
- **fix(writeback): committed `intake-push` records a transaction + undo.** The
|
|
258
|
+
staging write now produces a `ZoteroTransaction` (`validated=False`) with an
|
|
259
|
+
undo path, like the validated path. The CLI shows created keys / collection /
|
|
260
|
+
transaction id (post-write verification).
|
|
261
|
+
- **fix(intake): `review_required` on malformed/translated queries.** PubMed
|
|
262
|
+
warnings or a query re-translation flag the intake record and surface a
|
|
263
|
+
prominent CLI "REVIEW REQUIRED" banner (Sev-3).
|
|
264
|
+
- **fix(cli): unsupported previews stop printing a blank `confirm_token`** — they
|
|
265
|
+
say no confirmable write was produced and exit non-zero (Sev-2).
|
|
266
|
+
### Validation warehouse (ADR-0001 step 6)
|
|
267
|
+
- **feat(warehouse): de-identified validation warehouse (ADR-0001 step 6).** The
|
|
268
|
+
moat — but privacy-bounded. **Opt-in, default-off** (`config.validation_warehouse`).
|
|
269
|
+
When enabled, a final decision becomes one append-only, de-identified
|
|
270
|
+
`ValidationRecord`: `claim_type`, a one-way claim-text hash, the public PMID/DOI,
|
|
271
|
+
the AI/human/final support ratings, PICO fit, and agreement. It stores **no**
|
|
272
|
+
identity, manuscript text, Zotero keys, or project-internal ids. Claim text is a
|
|
273
|
+
top-sensitivity tier kept only on a second opt-in (`include_claim_text`). Records
|
|
274
|
+
are append-only (`validation/records.jsonl`); the warehouse is purgeable (consent
|
|
275
|
+
withdrawal) and `auto_emit` lets labels emerge from the workflow. New
|
|
276
|
+
`schemas/validation_record.py`, `warehouse.py`, config block, store CRUD
|
|
277
|
+
(`validation.record` / `validation.purge` audit), and `warehouse-status/-emit/
|
|
278
|
+
-export/-purge` CLI. Completes the ADR-0001 §10 build sequence.
|
|
279
|
+
|
|
280
|
+
## 0.3.0 — citation-integrity ledger (ADR-0001 steps 1–5) + capability foundation
|
|
281
|
+
|
|
282
|
+
Tag: `v0.3.0-citation-ledger`. Reorients ZotSynth around the **claim** (ADR-0001):
|
|
283
|
+
the ledger is `claim → candidate → blinded support rating → final decision →
|
|
284
|
+
decision-gated, undoable Zotero write`, every step hash-chain audited. Also folds
|
|
285
|
+
in the connection/capability hardening sprint. 421 tests, fully offline.
|
|
286
|
+
|
|
287
|
+
### Citation-integrity direction (ADR-0001)
|
|
288
|
+
|
|
289
|
+
- **docs(adr): ADR-0001 — ZotSynth is Citation Integrity Infrastructure.** The
|
|
290
|
+
claim (not the paper) is the spine; the evidence-decision ledger is the asset;
|
|
291
|
+
writes are decision-gated. Reconciles the manifesto against the current code;
|
|
292
|
+
records four accepted decisions and a six-step local-first build sequence.
|
|
293
|
+
- **feat(claims): the claim entity (ADR-0001 step 1).** First-class,
|
|
294
|
+
manuscript-anchored `Claim` (`claim_text`, controlled `claim_type`,
|
|
295
|
+
`manuscript_location`, extraction provenance), persisted to
|
|
296
|
+
`.zotsynth/claims/`, provenance-stamped and audited (`claim.write`).
|
|
297
|
+
AI-extracted claims must name their model (mirrors the AI-needs-provenance
|
|
298
|
+
rule). New `claims/` package, `schemas/claim.py`, `validators/claim.py`, store
|
|
299
|
+
CRUD, and `claim-add` / `claim-list` CLI. Mutates no Zotero state, decides
|
|
300
|
+
nothing — the spine only.
|
|
301
|
+
- **feat(claims): claim ↔ candidate linkage (ADR-0001 step 2).** Link staged
|
|
302
|
+
intake hits to a claim as `ClaimPaperCandidate`s, preserving retrieval
|
|
303
|
+
query/source/rank/why-found, deduped per claim by normalized PMID/DOI (never
|
|
304
|
+
title-only). Persisted to `.zotsynth/candidates/<claim_id>.json`, audited
|
|
305
|
+
(`candidate.link`). New `schemas/candidate.py`, `validators/candidate.py`,
|
|
306
|
+
`CandidateService`, store CRUD, and `claim-link-candidates` / `candidate-list`
|
|
307
|
+
CLI. Asserts no support, decides nothing, writes nothing to Zotero.
|
|
308
|
+
- **feat(claims): claim-support dual rating (ADR-0001 step 3).** The core asset
|
|
309
|
+
dimension — *does this paper support **this claim**?* — distinct from study
|
|
310
|
+
quality. A `ClaimSupportRating` keyed to `(claim_id, candidate_id)` with a
|
|
311
|
+
controlled support vocabulary (`directly_supports … contradicts`/`unclear`) +
|
|
312
|
+
PICO fit subscores (0/1/2). Rides on the same dual-rating invariants and
|
|
313
|
+
**reuses** the proven value blocks (`AIProvenance`/`Comparison`/`Adjudication`/
|
|
314
|
+
`Blinding`): human value locked, AI blind + advisory + never final, discordance
|
|
315
|
+
needs human/panel adjudication, final never sourced from AI. New
|
|
316
|
+
`schemas/claim_support.py`, `validators/claim_support.py`, `ClaimSupportEngine`
|
|
317
|
+
+ `ClaimSupportRater` seam (`FakeClaimSupportRater`), store CRUD with the
|
|
318
|
+
human-lock guard, and the `claim-support-*` CLI family.
|
|
319
|
+
- **feat(claims): final decisions (ADR-0001 step 4).** The human-owned terminal
|
|
320
|
+
judgment per (claim, candidate): `accept | reject | needs_second_review |
|
|
321
|
+
accepted_with_caution`, recording the final support status it rests on, the
|
|
322
|
+
human/AI agreement status, decider, and reason. **Mission invariant** (enforced):
|
|
323
|
+
you cannot `accept`/`accepted_with_caution` a candidate whose final support
|
|
324
|
+
status does not support the claim, and you cannot finalize accept/reject on an
|
|
325
|
+
unresolved discordance (adjudicate first or record `needs_second_review`). New
|
|
326
|
+
`schemas/decision.py`, `validators/decision.py`, `DecisionService`, store CRUD
|
|
327
|
+
(`decision.final` audit), `claim-decide` / `decision-list` CLI. This is the
|
|
328
|
+
object the decision-gated write (step 5) will require.
|
|
329
|
+
- **feat(writeback): decision-gated write transactions + undo (ADR-0001 step 5).**
|
|
330
|
+
Promotes the one-use write token into a durable `ZoteroTransaction`
|
|
331
|
+
(`previewed | committed | undone | failed`) with an `undo_snapshot`, enforcing
|
|
332
|
+
the §6 invariant: a *validated* Zotero write exists only for a final `accept`/
|
|
333
|
+
`accepted_with_caution` decision and always carries its chain (claim · candidate
|
|
334
|
+
· decision · provenance · transaction · audit · undo). Refuses a candidate with
|
|
335
|
+
no PMID/DOI (anti-fabrication); previews by default; degrades honestly to a
|
|
336
|
+
`failed` transaction with no silent write. `undo` deletes **only** the keys the
|
|
337
|
+
transaction created, version-guarded (`If-Unmodified-Since-Version`) so a user
|
|
338
|
+
edit aborts the delete (HTTP 412) instead of clobbering it. New
|
|
339
|
+
`schemas/transaction.py`, `validators/transaction.py`, `TransactionService`,
|
|
340
|
+
backend `undo()` capability (+ `HttpClient.delete`), store CRUD
|
|
341
|
+
(`zotero.transaction.*` audit), `claim-commit` / `txn-list` / `txn-show` /
|
|
342
|
+
`txn-undo` CLI. Closes the stress-test's "no undo" gap.
|
|
343
|
+
|
|
344
|
+
### Connection & capability foundation
|
|
345
|
+
|
|
346
|
+
Hardening sprint driven by an external persona stress test. Builds a
|
|
347
|
+
truth-telling foundation and fixes four verified bugs (each a violation of
|
|
348
|
+
ZotSynth's own integrity invariants).
|
|
349
|
+
|
|
350
|
+
- **feat: `zotsynth status` — Connection & Capabilities (read-only).** Reports
|
|
351
|
+
live Zotero/BBT connection + versions, PubMed email + secret *state* (source,
|
|
352
|
+
never the value), and the configured write backend's **actual** supported vs
|
|
353
|
+
unsupported operations + a permission summary. `capabilities.py` +
|
|
354
|
+
`CapabilityStatusService`.
|
|
355
|
+
- **fix(credentials): keyring errors degrade gracefully.** A macOS
|
|
356
|
+
`KeyringError(-50)` during NCBI-key lookup used to crash `literature_search`
|
|
357
|
+
(`resolve_secret` only caught `CredentialError`). `KeyringCredentialStore` now
|
|
358
|
+
raises a clean `CredentialError` → resolved to keyless, not a crash; status
|
|
359
|
+
reports `store_unavailable`.
|
|
360
|
+
- **fix(pubmed): capture search diagnostics.** `esearch` now surfaces the true
|
|
361
|
+
total count, NCBI query translation, and `warninglist`/`errorlist`. A
|
|
362
|
+
malformed query (`lung cancer AND (`) is flagged (`warnings`) or degrades
|
|
363
|
+
(`pubmed_query_error`) instead of silently staging unintended hits. Carried
|
|
364
|
+
onto the intake record + printed by the CLI. The exact query is still preserved.
|
|
365
|
+
- **fix(writeback): capability-honest previews + audited failures.** Backends
|
|
366
|
+
expose `supports(kind)`. A preview for an op the backend can't perform (e.g.
|
|
367
|
+
`note_add`/`tag_add` on the web_api backend) now fails **early** with
|
|
368
|
+
`operation_unsupported` and mints **no** token, instead of previewing success
|
|
369
|
+
then failing on confirm. Every failed write attempt (unsupported, unavailable,
|
|
370
|
+
backend error) now appends a `zotero.write.failed` audit event.
|
|
371
|
+
|
|
372
|
+
## 0.2.0 — write-back + secure onboarding
|
|
373
|
+
|
|
374
|
+
- **feat(writeback): Zotero Web API item-creation backend.** `WebApiWriteBackend`
|
|
375
|
+
(api.zotero.org) creates items (`item_add` / `intake_push`) and assigns them to
|
|
376
|
+
a collection at creation. `make_backend` wires `web_api` when enabled with
|
|
377
|
+
credentials resolved from env/keyring; missing creds → UnavailableBackend (no
|
|
378
|
+
silent fallback). All write guards intact (dry-run default, one-use token,
|
|
379
|
+
audit, honest degradation).
|
|
380
|
+
- **feat: secure onboarding (`zotsynth onboard`).** Non-secret identifiers
|
|
381
|
+
(PubMed email, Zotero user/library id, default collection) → config; secret
|
|
382
|
+
keys (Zotero write key, NCBI key) → OS keyring via `keyring`, with
|
|
383
|
+
`ZOTSYNTH_*` env escape hatch. Secrets are validated, then stored, and never
|
|
384
|
+
written to config/logs/history or echoed. Adds `credentials.py`,
|
|
385
|
+
`onboarding.py`, config fields, and the `keyring` optional dependency.
|
|
386
|
+
- **fix: resolve citekeys from Better BibTeX CSL-JSON (`item.search`).** The
|
|
387
|
+
shared resolver (map_bootstrap / extract / claim_check) now parses the Zotero
|
|
388
|
+
key from the CSL `id` URI instead of a non-existent `itemKey` field; contract
|
|
389
|
+
test pins the real response shape.
|
|
390
|
+
|
|
391
|
+
## 0.1.1 — patch
|
|
392
|
+
|
|
393
|
+
- **fix(pubmed): efetch DOI from the article's own id list, not cited
|
|
394
|
+
references.** efetch parsing used `.//ArticleIdList/ArticleId`, which descends
|
|
395
|
+
into `PubmedData/ReferenceList` and could surface a *cited reference's* DOI as
|
|
396
|
+
the article's DOI. Now scoped to the article's own `PubmedData/ArticleIdList`.
|
|
397
|
+
Citation-integrity fix surfaced by a live `literature_search` run; covered by a
|
|
398
|
+
regression test with decoy reference DOIs.
|
|
399
|
+
- Package metadata and runtime `__version__` bumped to `0.1.1`.
|
|
400
|
+
|
|
401
|
+
## 0.1.0 — integrity spine (steps 1–9)
|
|
402
|
+
> The `0.1.0` line was released from the build below (internally versioned 0.7.0
|
|
403
|
+
> during development, then aligned to 0.1.0). Tag: `v0.1.0-integrity-spine`.
|
|
404
|
+
|
|
405
|
+
## 0.7.0 — full build (steps 1–9)
|
|
406
|
+
|
|
407
|
+
### Step 1 — probe layer + state (`bbc0b37`, hardened in `319cd88`)
|
|
408
|
+
- Startup probe (probe-not-proof): Zotero `/api/` (read-only/GET-only), Better
|
|
409
|
+
BibTeX `api.ready`, CAYW `probe=1`, with remediation strings.
|
|
410
|
+
- Honest version parsing: Zotero app version from `x-zotero-version`; schema
|
|
411
|
+
version (`42`) and local-API version never surfaced as the app version; BBT
|
|
412
|
+
version read live from `api.ready` (`betterbibtex` field), never hardcoded.
|
|
413
|
+
- `.zotsynth/` state layer: `config.json`, version-stamped frames, evidence map
|
|
414
|
+
+ citekey-centered reverse index, per-rating records, snapshots, intake,
|
|
415
|
+
prisma, and a hash-chained `audit_log.jsonl`.
|
|
416
|
+
- Binding validators: model-pin-required, rating-vs-assist task split,
|
|
417
|
+
frame/subject keying, and the rating-record validity invariant.
|
|
418
|
+
|
|
419
|
+
### Step 2 — read/discover + cite (`778d3f8`)
|
|
420
|
+
- Read-only `zot_search`/`zot_item`/`zot_collections`/`zot_attachments` honoring
|
|
421
|
+
the personal/group/all library selector; honest degradation when absent.
|
|
422
|
+
- `cite` resolves citekeys by exact match via Better BibTeX; never invents keys.
|
|
423
|
+
|
|
424
|
+
### Step 3 — bib_sync + evidence map (`5f7d7e5`)
|
|
425
|
+
- `bib_sync`: multi-file Pandoc/LaTeX citekey extraction (code/URL/email masked),
|
|
426
|
+
exact-match resolution, orphan/unused reporting, per-file + master exports,
|
|
427
|
+
honest degradation.
|
|
428
|
+
- Operational evidence-map model: typed nodes/attachments with per-kind scope
|
|
429
|
+
rules and a citekey-centered reverse index; all mutations audited.
|
|
430
|
+
|
|
431
|
+
### Step 4 — extraction + claim_check (`e2ef3ce`)
|
|
432
|
+
- Deterministic passage retrieval over Zotero full text + annotations.
|
|
433
|
+
- `extract`: assistive regex/rule extraction with passages; unverifiable when
|
|
434
|
+
absent; never guesses; never writes the evidence map.
|
|
435
|
+
- `claim_check`: lexical support only — `supported_candidate` / `no_support_found`
|
|
436
|
+
/ `unverifiable`; never asserts truth; never invents keys.
|
|
437
|
+
|
|
438
|
+
### Step 5 — PubMed intake + manual import (`50b9db5`)
|
|
439
|
+
- PubMed-only provider (E-utilities) with rate-limit (3/10 rps) + 429 retry and
|
|
440
|
+
honest degradation (`missing_ncbi_email` / `pubmed_unavailable`).
|
|
441
|
+
- `literature_search` (verbatim user query) + `import_results` (RIS/CSV/BibTeX),
|
|
442
|
+
dedupe (in-run / prior-intake / library by DOI+PMID, never title-only),
|
|
443
|
+
pre-decision intake records (`decision: null`).
|
|
444
|
+
|
|
445
|
+
### Step 6 — snapshot / corpus_diff / surveillance / map_bootstrap (`e5abf40`)
|
|
446
|
+
- `snapshot`: hashed read-only corpus + evidence-map capture; never invents
|
|
447
|
+
citekeys; no fake snapshot when Zotero is down.
|
|
448
|
+
- `corpus_diff`: identity-continuity diffing; reverse-index-driven staleness.
|
|
449
|
+
- `surveillance_refresh`: re-run a saved query from its own last-run date
|
|
450
|
+
(mechanical date append, not a redesign).
|
|
451
|
+
- `map_bootstrap` (minimal): section/study/explicit-outcome seeding; dry-run
|
|
452
|
+
default; orphans never invented.
|
|
453
|
+
|
|
454
|
+
### Step 7 — dual-rating + assess + retraction + PRISMA (`e197ea4`)
|
|
455
|
+
- Dual-rating engine (`rating_start`/`commit_human`/`run_ai`/`compare`/
|
|
456
|
+
`adjudicate`): blinded advisory AI behind an `AiRater` seam; the hardening
|
|
457
|
+
invariants enforced and audited.
|
|
458
|
+
- `assess`: human-chosen controlled values only; tag-mirror deferred to step 9.
|
|
459
|
+
- `retraction_scan`: DOI/PMID via a provider seam (no title-only truth).
|
|
460
|
+
- `prisma_ledger`: human-only decisions; AI votes referenced by `rating_id` only.
|
|
461
|
+
|
|
462
|
+
### Step 8 — evidence export + agreement report (`d45f916`)
|
|
463
|
+
- `evidence_export`: neutral CSV/Markdown/CSL-JSON; AI values excluded by
|
|
464
|
+
default and clearly labelled/separated when requested; mutates nothing.
|
|
465
|
+
- `agreement_report`: raw agreement, Cohen κ, ordinal weighted κ (ROBINS-I
|
|
466
|
+
*No information* excluded + reported), adjudication rate; refuses κ across
|
|
467
|
+
mixed schemes; PRISMA-trAIce / RAISE-style transparency section that disclaims
|
|
468
|
+
any compliance/endorsement claim.
|
|
469
|
+
|
|
470
|
+
### Step 9 — guarded Zotero write-back (`fcbaf18`)
|
|
471
|
+
- Optional write layer: dry-run default, payload-bound one-use confirmation
|
|
472
|
+
tokens, distinct `zotero.write.applied` audit event, **no silent fallback**.
|
|
473
|
+
- Tools: `note_add`, `annotation_add`, `item_add`, `tag_add`, `tag_remove`,
|
|
474
|
+
`collection_add_item`, `intake_push`, `assessment_tag_mirror` (mirrors only
|
|
475
|
+
human/final values; replaces prior same-scheme tag). Live default backend is
|
|
476
|
+
clearly degraded (`write_layer_unavailable`); no network writes.
|
|
477
|
+
|
|
478
|
+
### Testing
|
|
479
|
+
- 308 tests, fully offline (fake Zotero/BBT/PubMed/write/AI seams). No live
|
|
480
|
+
PubMed calls and no live Zotero writes occur during the suite.
|