Skip to content

Latest commit

 

History

History
490 lines (409 loc) · 29.1 KB

File metadata and controls

490 lines (409 loc) · 29.1 KB

PaperGuard 终极交接文档 v2.5.0

2026-05-23 — fifth revision of the handoff (after 2.0.14, 2.1.5, 2.2.5, 2.2.7).

Paste this file in a fresh Claude Code session to continue without context loss. Tokens are NOT in this file — the user has them and pastes when needed.


1. Project identity

Name PaperGuard — research-data integrity triage
Current version 2.5.0 (local = origin = PyPI = release tag, all in sync)
Detector count 39 (35 academic + 4 industrial) — G5 reagent-temporal added in 2.4.0
Local root C:\Users\USER\Desktop\PROJECT_DIR\PaperGuard
Python venv .venv/Scripts/python.exe
CLI entry .venv/Scripts/paperguard.exe
GitHub https://github.com/exergyleizhou-ux/PaperGuard
PyPI https://pypi.org/project/paperguard/
HF Space (live) https://huggingface.co/spaces/exergyleizhou/paperguard-demo
Detector count 38 built-in (34 academic + 4 industrial including I6 over-smoothness) + plugin entry-point support
Industrial templates 12 (wastewater / waste_gas / distillers_grain / chemical / pharma / food / semiconductor / environment / medical / agriculture / biopharma / biocomputation)
Docker ghcr.io/exergyleizhou-ux/paperguard:latest (linux/amd64 + linux/arm64)

2. Quality state (verified 2026-05-23)

PYTEST    534 passed (+ 3 deselected for network)
RUFF      All checks passed
MYPY      Success: 103 source files (--strict)
COMMITS   ~85 on main
TAGS      v2.0.1 → v2.5.0 (50 releases, no gap)
PRIVACY   ✅ HEAD + history fully sanitized (git filter-repo
          force-pushed 2026-05-22; backup bundle at
          ../paperguard-pre-rewrite-backup-2026-05-22.bundle).
          The current main hash plus every tag's SHA changed in
          that operation. Banned-token blob scan: clean.
LOCAL = ORIGIN = PyPI = RELEASE TAG  ✅ fully synced
HF SPACE  ✅ live on 2.2.7 banner — RUNNING, gradio 5.34.0,
          python 3.11. (Banner string still says "v2.2.7"; the
          Space re-pulls paperguard>=2.2.7 from PyPI at each
          rebuild so the actual installed package is the
          latest 2.5.0.)

3. Credentials (held by user, not in this file)

Tokens are not committed to the repo. The user has them on hand and pastes them when needed. Placeholders below.

PYPI_TOKEN     = [PYPI_TOKEN — full-account scope, ask user]
HF_TOKEN       = [HF_TOKEN — see private session credentials]

# ✅ unlocked in 2.4.0 — OpenAI direct, project-scoped (sk-proj-*).
OPENAI_KEY     = [OPENAI_KEY — see private session credentials.
                  Verified 2026-05-23: gpt-4o-mini and gpt-4o both
                  return REAL per-token logprobs. Total spend
                  through 2.4.2: ≈ $0.05.]
OPENAI_BASE    = https://api.openai.com/v1

# Free tier, logprobs only on qwen/qwen3-32b (not Llama).
GROQ_KEY       = [GROQ_KEY — see private session credentials]
GROQ_BASE      = https://api.groq.com/openai/v1

# Legacy team-pool proxy (gpt-5.x reasoning models, NO logprobs).
TEAM_LLM_BASE  = https://cliproxy.eqing.tech/v1
TEAM_LLM_KEY   = [TEAM_LLM_KEY — see private session credentials]
TEAM_LLM_MODEL = gpt-5.4-mini   (cliproxy's standard model)

GIT_LOCAL_USER = exergyleizhou-ux
GIT_LOCAL_EMAIL = exergyleizhou@gmail.com
GH_AUTH        = authenticated (token in Windows Credential Manager)
HF_USER        = exergyleizhou

⚠️ cliproxy quirk — proven empirically (2.1.10, re-confirmed 2.4.1): does NOT return the logprobs field on any gpt-5.x variant (7 variants tested in 2.4.1 with the new team-pool key; all return logprobs: null). T7 silent no-op on this endpoint; T8 structurally broken because the gpt-5.x paraphrasers are reasoning models that preserve manifold (2.2.7 scope claim).

⚠️ Groq logprobs only on qwen/qwen3-32b — not on llama-3.1-8b-instant, llama-3.3-70b-versatile, meta-llama/llama-4-scout-17b-16e-instruct. The Llama-3 reference-LM T7 validation experiment is therefore blocked on Groq; full validation requires self-hosted vLLM.

OpenAI direct unlock (2.4.0) is the headline win since 2.2.6. Both T7 and T8 now have real LR+ on api.openai.com:

  • T7 on gpt-4o: LR+ = 8.0 at calibrated inverted threshold (TPR 80 %, FPR 10 %, N=10+10, p=0.0011). Set PAPERGUARD_T7_INVERT_THRESHOLD=1 (added in 2.4.2) to flip the detector into HIGH-ppl-is-signal mode.
  • T8 on gpt-4o: LR+ = ∞ (2/10 TP, 0/10 FP). Direction textbook.

⚠️ PyPI token has full-account scope and has been exposed in this session across multiple messages. User explicitly declined to revoke. New session should use it sparingly. GitHub secret-scanning push protection caught one near-leak in 2.1.5 — the HANDOFF.md was redacted before the push succeeded.

4. What was shipped in the 2.0.14 → 2.5.0 cycle (cumulative)

37 versions over 4 days.

Ver What
2.0.15 T6 dynamic dictionary + T7 perplexity proxy detector (32 detectors)
2.0.16 T8 DetectGPT detector (33) + dictionary JSON + batch/notify --*-check flags + v8 N=50
2.0.17 HF Space Gradio demo (examples/hf_space_app.py)
2.1.0 v9 N=30 retest + transparent T7/T8 dataset
2.1.1 docs/paperguard_technical_report.md (7-section technical report)
2.1.2 Image-layer F1/F4 recall (recall_image_v1) + JOSS paper draft + T6 abstract-only mode
2.1.3 B4 statcheck cross-validation (N=41, recall 100 %, decision-flip 94 %) + HF Space deployed (live)
2.1.4 README + ROADMAP refresh
2.1.5 README.zh.md sync + first HANDOFF doc
2.1.6 paperguard doctor diagnostic command (19-check pre-flight)
2.1.7 F6 patch-splice detector (Bik 2016 style) — 34th detector
2.1.8 recall_image_v2 N=18 F1+F4+F6 study, F6 FPR 75 % at default discovered
2.1.9 F6 default tightened to z=6 / cluster=8 based on v2 finding
2.1.10 T8 controlled benchmark (N=20) — formal proof cliproxy can't drive T8, LR+ = 0
2.1.11 paper/paper.md JOSS-ready + paper/JOSS_SUBMISSION.md walkthrough
2.1.12 recall_test_v10 N=200 — first true positive at 0.001 threshold
2.1.13 Continuity refresh — earlier HANDOFF + docs/INDEX.md + README badges
2.1.14 Detector deep-dive pages for E1 / T7 / T8 / F6 + M1
2.1.15 WebUI rate-limit + optional Redis backend (production hardening)
2.1.16 WebUI SHA-keyed scan-result cache (5-min TTL)
2.1.17 Legacy .doc / .docb text + image extraction via olefile
2.1.18 statcheck-R Cohen's κ = 0.79 on decision-flip class (Landis-Koch substantial)
2.1.19 Image recall v3 N=85 — F6 LR+ = 1.91 confirms the 2.1.9 calibration
2.2.0 Industrial extension pack — I1 / I2 / I5 detectors + HDF5 ingest
2.2.1 12 industrial-domain templates (wastewater, pharma, semiconductor, …)
2.2.2 paperguard scan-industrial --domain X file.csv CLI command
2.2.3 I6 over-smoothness detector (38th) + multi-arch Docker → ghcr.io
2.2.4 Industrial recall v1 study (N=100/domain) + refresh-ai-dict --auto
2.2.5 Image recall v4 (N=159): F6 LR+ = 1.63, confirms calibration across 3 samples
2.2.6 T7+T8 real-endpoint benchmarks (Groq Qwen3-32B + DeepSeek-v4-flash) — T7 LR+ = 1.69 weak (p=0.11, N=17), T8 LR+ = 0.25 reversed on reasoning model (N=20). docs/llm_detection_real_endpoints.md writeup.
2.2.7 Honest scope statement for T7/T8 (docs-only). Detector docstrings + real-endpoints doc + llm_detection_v2 + README all now name validated vs structurally-incompatible endpoint classes. HF Space synced (gradio 5.34 + py 3.11 pins fix audioop + HfFolder regressions). Pre-existing benchmark JSON path leaks sanitized in HEAD.
2.3.0 Web UI hardening — PAPERGUARD_BEHIND_PROXY=1 (Secure-cookie + trust X-Forwarded-For) + per-IP rate-limit on /login (10/5min), /redeem (5/10min), /scan (60/60s on top of existing per-user).
2.3.1 Image-recall v5 (N=132+48 PDF-OK from N=200+200) — F6 LR+ collapsed from v4's 1.63 to 0.92 (Wilson 95 % CI [0.75, 1.20]); F4 LR+ rose to 4.36 [0.48, 41.28]. Honest revision: v4's 1.63 was a small-sample upward fluctuation.
2.4.0 G5 reagent-temporal detector (39th) absorbed from the geng-fraud-skill 第六式 — flags reagent / equipment / catalog context near a year postdating the paper. NOTE-tier only, 4 innocent explanations. + first real-OpenAI T7/T8 LR+: T7 on gpt-4o-mini = signal REVERSED p=0.047, T8 on gpt-4o LR+ = ∞ (2/10 TP, 0/10 FP).
2.4.1 T7 on gpt-4o study: LR+ = 8.0 at calibrated inverted threshold (TPR 80 % / FPR 10 %, p=0.0011). 2.4.0's reference-LM-size hypothesis disproved — bigger model amplified the reversal, not flipped it. New RLHF-suppression hypothesis.
2.4.2 PAPERGUARD_T7_INVERT_THRESHOLD=1 env var — flips T7 into HIGH-ppl-is-signal mode for OpenAI endpoints. + partial RLHF-hypothesis validation (Qwen3 textbook direction LR+ 1.69 vs gpt-4o reversed LR+ 8.0, two-endpoint disagreement consistent with hypothesis).
2.5.0 Audit log v1AuditEvent SQLAlchemy model, audit_event() best-effort helper, 11 hook sites (login / logout / redeem / scan / project / admin invite, all with success / failure / rate_limited variants where applicable), PAPERGUARD_AUDIT_FILE JSON-lines mirror, admin read endpoint GET /app/admin/audit.

4a. HF Space sync (2.2.7) — environment regressions learned

When syncing the live HF Space to 2.2.7, two regressions surfaced on the HF default container that the repo had no record of:

  1. HF default Python jumped to 3.13. Python 3.13 removed the stdlib audioop module (PEP 594). gradio 4.44's pydub dependency imports audioop at startup → ModuleNotFoundError → APP_STARTING → RUNTIME_ERROR.

    • Fix: pin python_version: "3.11" in Space README frontmatter to keep stdlib audioop.
  2. gradio 4.44 imports HfFolder from huggingface_hub, which was removed in huggingface_hub 1.x (now what the container ships). Pure version-skew failure with no app-code component.

    • Fix: bump sdk_version: 5.34.0 in Space README frontmatter and gradio>=5.0,<6.0 in requirements. App code uses only gr.Blocks / gr.Markdown / gr.Textbox / gr.Button / gr.Tab / gr.click() which carry over 4.x → 5.x cleanly.

Working post-fix config is checked into examples/hf_space_readme.md and examples/hf_space_requirements.txt. Don't re-derive from the runtime logs next time.

5. Reproducible 3-gate command

cd "C:/Users/USER/Desktop/PROJECT_DIR/PaperGuard"
PYTHONIOENCODING=utf-8 .venv/Scripts/python.exe -m pytest -m "not network" -q
.venv/Scripts/python.exe -m ruff check src/ tests/ examples/
.venv/Scripts/python.exe -m mypy src/

Privacy gate (must be clean before every release):

find . -type d -name "__pycache__" -not -path "./.venv/*" -exec rm -rf {} +
grep -rlnE "[REDACTED-INST]|[REDACTED-CODENAME-1]|[REDACTED-CODENAME-2]|USER|PROJECT_DIR|[REDACTED-NAME]|[REDACTED-NAME-EN]|[REDACTED-DOI-1-PREFIX]|[REDACTED-DOI-2-PREFIX]" \
  src/ tests/ examples/ docs/ scripts/ paper/ README.md README.zh.md \
  CHANGELOG.md ROADMAP.md CONTRIBUTING.md SECURITY.md LICENSE \
  CITATION.cff pyproject.toml HANDOFF.md

Expected empty.

6. The 39 detectors (verified count, 2.5.0)

ID Family Source
A1-A7 Digit-distribution + arithmetic + bounds a*.py
B1, B4-B8 GRIM / statcheck / TIVA / GRIMMER / p-curve / SPRITE b*.py
C1 Carlisle baseline c1_carlisle.py
D1, D2 Residual smoothness / Missing pattern d*.py
E1 ICC Independence (new in 2.0.14) e1_icc_independence.py
F1-F5 Image forensics (pHash / ORB / splice / cross-paper / EXIF cluster) f*.py
F6 Per-channel histogram patch splice (Bik 2016, new in 2.1.7) f6_patch_splice.py
G1, G3, G4 EXIF / docx rsid / file metadata g*.py
G5 Reagent / equipment year temporal consistency (NEW in 2.4.0, absorbed from geng-fraud-skill 第六式) g5_reagent_temporal.py
M1 Paper-mill graph m1_paper_mill_graph.py
T1-T5 Plagiarism / NCT outcome / data-availability / tortured / stylometry t*.py
T6-T8 LLM-text family (lexical / perplexity / DetectGPT-curvature) t6/t7/t8
I1, I2, I5, I6 Industrial: mass-balance / SCADA timestamp / batch-repetition / trend-oversmooth (2.2.0+) i.py*

LLM-text family (T6/T7/T8):

  • T6: lexical phrase signature + dynamic user dictionary at ~/.paperguard/ai_dictionary.json. 2.1.12 empirically calibrated: at 0.001 threshold, LR+ = ∞ on N=200 (1 TP / 0 FP).
  • T7: continuation-perplexity. 2.4.2 update: real-OpenAI runs show inversion — gpt-4o-mini p=0.047 reversed direction, gpt-4o p=0.0011 reversed even more strongly (LR+ = 8.0 at calibrated inverted threshold; TPR 80 %, FPR 10 %; N=10+10). Set PAPERGUARD_T7_INVERT_THRESHOLD=1 on OpenAI endpoints. Qwen3-32B free path gives weak textbook-direction LR+ 1.69 at N=17.
  • T8: DetectGPT-style curvature. 2.4.0 real-endpoint: gpt-4o gives LR+ = ∞ (2/10 TP, 0/10 FP). Reasoning paraphrasers (o-series, DeepSeek-v4, Qwen3-thinking) still structurally incompatible (LR+ 0.25 on DeepSeek-v4).

6a. Audit log (new in 2.5.0)

  • Single model AuditEvent in src/paperguard/webui/models.py. Flat schema: kind (string), user_id, subject_id, subject_type, ip, meta_json.
  • Single helper await audit_event(session, kind=..., user_id=..., ip=..., meta={...}) in src/paperguard/webui/audit.py. Best-effort write semantics; never raises.
  • 11 hook sites wired in routes_auth.py + routes_app.py. Event taxonomy: auth.login.*, auth.logout, auth.redeem.*, project.create, report.scan.*, admin.invite.create.
  • Optional JSON-lines mirror at PAPERGUARD_AUDIT_FILE=/path/to/audit.jsonl. Wire your logshipper (vector / fluent-bit / promtail / rsyslog imfile) here.
  • Admin read endpoint: GET /app/admin/audit?since=&until=&user=&kind=&limit= — returns newest-first JSON. Admin-only.
  • 12 tests in tests/test_webui_audit.py. The audit_event swallow-DB-failures contract has a direct unit test.

Industrial family (I1/I2/I5/I6, new in 2.2.0-2.2.3):

  • I1: closure of mass-balance equations across SCADA log columns.
  • I2: SCADA timestamp integrity (monotonic / no large gaps / consistent cadence).
  • I5: batch-repetition detection — identifies suspicious copy-paste of historical batches into current logs. Wastewater recall study: LR+ = ∞ at N=50+50 (per-domain); same study runs pharma at N=50+50 for a 200-dataset total (docs/recall_industrial_v1.md). I1/I2 fire 100%/100% at the same defaults — out-of-the-box tolerances need plant-specific calibration.
  • I6: process-trend over-smoothness — flags suspiciously low-variance trend windows that are inconsistent with measurement noise floor.

7. Empirical datasets in the repo (2.1.13)

File What Headline result
scripts/recall_test_v5_results.json (legacy) N=100+100 full pipeline see docs/recall_test_v5.md
scripts/recall_test_v8_results.json N=50+50 T6-only PMC text LR+ ≈ 0 at default
scripts/recall_test_v9_results.json N=30+30, T7/T8 columns wired (empty) T7/T8 await real OpenAI key
scripts/recall_test_v10_results.json N=100+100 — 159 records LR+ = ∞ at 0.001 threshold (1 TP / 0 FP); 1 TP is PLOS ONE 2024 paper-mill retraction
scripts/recall_image_v1_results.json N=15+15 F1/F4 see docs/recall_image_v1.md
scripts/recall_image_v2_results.json N=10+8 F1+F4+F6 F6 default FPR=75% → tightened in 2.1.9 to z=6/cluster=8 (FPR 62.5%)
scripts/crossval_statcheck_results.json N=41 ground-truth, B4 vs scipy ref recall 100%, decision-flip 94%
scripts/t8_controlled_benchmark_results.json N=10+10 human-vs-AI text T8 LR+ = 0 on cliproxy (formal endpoint-limitation proof)

8. Open work (priority order for next session)

8.A — Real GPT-4o T7/T8 LR+ (HIGHEST VALUE, blocked on credentials)

When the user provides a real OpenAI key (sk-… or sk-proj-…), run:

cd "C:/Users/USER/Desktop/PROJECT_DIR/PaperGuard"
OPENAI_API_KEY="sk-REAL" \
PAPERGUARD_LLM_MODEL="gpt-4o-mini" \
PYTHONIOENCODING=utf-8 \
.venv/Scripts/python.exe scripts/recall_test_v9.py \
    --n 30 --year-min 2020 \
    --run-t7 --run-t8 \
    --out scripts/recall_test_v9_results.json \
    --resume

The v9 script has --run-t7 --run-t8 --resume pre-wired and only populates the empty t7_* / t8_* columns — T6 work preserved. Cost ~200 OpenAI API calls, < $0.50 on gpt-4o-mini.

8.B — JOSS submission (USER ACTION, paper ready)

paper/paper.md + paper/paper.bib + paper/JOSS_SUBMISSION.md are ready. PDF builds in ~43 s via .github/workflows/draft-pdf.yml. User must:

  1. Register / look up ORCID at https://orcid.org/register
  2. Replace 0000-0000-0000-0000 in paper/paper.md with real ORCID
  3. Submit at https://joss.theoj.org/papers/new with:
    • Repository URL: https://github.com/exergyleizhou-ux/PaperGuard
    • Branch: main
    • Version: latest tag (currently v2.5.0)

Median time-to-DOI: 6-12 weeks.

8.C — F1/F4 N=50+50 expansion

Image recall study is currently N=15+15 (v1) and N=10+8 (v2). To get tight CI, expand:

python scripts/recall_image_v2.py --n 50 --resume

Idempotent — skips records already in the .partial.json.

8.D — statcheck-R Cohen's κ (needs R)

When R is available:

install.packages("statcheck")
library(statcheck)
results <- statcheck("crossval_corpus.txt")

Then compute κ between B4 output and statcheck-R output on the same N=41 corpus. Expected κ > 0.85.

8.E — Multi-tenant Web UI production hardening

src/paperguard/webui/ exists and works in dev. Production needs:

  • Redis cache backend (currently in-memory)
  • HTTPS termination guidance in deploy docs
  • Rate-limiting on /scan endpoint
  • Audit-log shipping (currently file-based)

8.F — Submit to additional venues

After JOSS DOI lands:

  • Scientific Data (Springer Nature) — repackage v8/v9/v10/image_v2/ statcheck_crossval/T8_benchmark as a public dataset paper
  • F1000Research — open peer review, software paper companion
  • Bibliometrics journals — Scientometrics, Journal of Informetrics

9. Tripwire / gotchas (encountered in this session, now 23)

# Trap Workaround
1 Windows __pycache__ has compile-time absolute paths → grep "USER" false-positive find . -name __pycache__ -exec rm -rf {} + before every privacy grep
2 paperguard.exe Chinese output garbled in PowerShell GBK $env:PYTHONIOENCODING="utf-8"
3 git LF/CRLF warning on every commit Normal Windows behavior, leave alone
4 diskcache cross-test contamination Test decorator: unique uuid.uuid4().hex namespace
5 networkx/opencv/pymupdf/biopython have no stubs # type: ignore[import-untyped] (not [no-untyped-call])
6 Pydantic mypy plugin pyproject.toml has plugins = ["pydantic.mypy"] — don't remove
7 D1 monotonic-index false positive Detector has a monotonic-skip rule — don't remove
8 G4 publisher allowlist Springer/Elsevier/Wiley/LaTeX 30+ entries pre-whitelisted
9 PDF image size filter F1/F2/F3 inputs must pass extract_pdf_images (≥200×200, ≥8KB)
10 subprocess Unicode on Windows Use text=False + manual utf-8 decode
11 F1 raster fallback slow on long PDFs Default raster_max_pages=5, timeout 600s — don't bump
12 twine upload progress bar crashes on GBK PYTHONIOENCODING=utf-8 before upload
13 cliproxy doesn't return logprobs (T7 blocked) Tested all 5 gpt-5.x variants in 2.1.10 — confirmed
14 cliproxy paraphraser preserves LLM markers (T8 LR+ = 0) Formally measured in 2.1.10 N=20 study
15 GitHub secret-scanning push protection caught PyPI token in HANDOFF.md 2.1.5 Always redact tokens before committing; user must --bypass is NOT acceptable
16 DeepSeek-v4 + Groq Qwen3-32B are reasoning models T7 needs max_tokens ≥ 256 for continuation; T8 needs max_tokens ≥ 500 for score and ≥ 1500 for paraphrase with skip-reasoning retry. logprobs from DeepSeek are fake all-zeros. T8 LR+ collapses on reasoning paraphrasers (manifold preserved).
17 HF Space default container moved to Python 3.13 Breaks gradio 4.44 via removed audioop stdlib (PEP 594). Pin python_version: "3.11" in Space README frontmatter. Learned 2.2.7.
18 gradio 4.44 imports HfFolder, removed in huggingface_hub 1.x Bump sdk_version: 5.34.0 in Space README + gradio>=5.0,<6.0 in requirements. App code (gr.Blocks / gr.Markdown / gr.Textbox / gr.Button / gr.Tab / gr.click()) carries over 4.x → 5.x cleanly. Learned 2.2.7.
19 cliproxy + Cloudflare block default curl UA Add User-Agent: Mozilla/5.0 ... header or the request returns Cloudflare 403 "Access denied: Your client is not allowed." Learned 2.2.7-era HF Space sync (also re-encountered with the 2.4.0 team-pool key).
20 OpenAlex filter field is has_pmid / has_pmcid — not has_pmid_id etc. The error message lists all valid filter fields; check it before guessing syntax. Also: is_retracted:true + has_pmcid:true intersects to zero results — PMC IDs sparsely populated for retracted papers. Use has_pmid:true instead. Learned 2.5.0 (v6 script).
21 Groq exposes logprobs ONLY on qwen/qwen3-32b Llama-3.1-8b-instant, Llama-3.3-70b-versatile, Llama-4-scout all return "logprobs is not supported with this model" (HTTP 400). The Llama-3 reference-LM T7 hypothesis test requires self-hosted vLLM. Learned 2.4.2.
22 OpenAI gpt-4o flips T7 direction (AI ppl > human ppl, not the textbook reverse) RLHF-suppression hypothesis — the reference LM was trained to avoid LLM-style markers, so they become low-probability tokens for it. Use PAPERGUARD_T7_INVERT_THRESHOLD=1 env var (added 2.4.2). Learned 2.4.1.
23 Web UI auth routes don't await session.commit() — audit_event must commit its own row The DBSession dependency context manager exits WITHOUT auto-commit on routes that only do reads (login, logout, redeem). Audit rows added via session.add() would be discarded. audit_event() therefore does its own commit + rollback-on-failure (best-effort). Learned 2.5.0 during audit-log v1 wiring.

10. User behaviour pattern

User says "go / 做 / 全做 / 继续" = green light, batch action permitted.

User says "目前进度 / 现在呢" = green-light count exhausted. Each such question burns a tool call. Strategy: 1-2 Bash calls max, then explicitly tell user to step away for X minutes.

User is a Chinese-American based in the US: bilingual interaction (speaks Chinese to the agent but operates US infrastructure). All endpoints work directly — GitHub, OpenAI, Anthropic, OpenAlex, Europe PMC, Unpaywall, PyPI, HuggingFace, Groq, DeepSeek, cliproxy. No GFW workarounds needed. OpenAI billing accepts US credit cards directly. The Chinese-locale earlier guesses (cliproxy necessity, TLS-jitter retries) were wrong; keep the retries for robustness but don't assume the user can't reach api.openai.com.

User occasionally pastes sensitive info: Gmail passwords / tokens have appeared. Warn but don't leak. The PYPI_TOKEN above has full account scope and was exposed many times — the user knows.

User's own paper was scanned in this session: PaperGuard correctly returned NOTE-level findings (T6 false-positive on "synergy" as legitimate technical term, G3 rsid low from pandoc generation, T3 missing-CoI in SI). Also surfaced 3 real [TODO:...] placeholders in the manuscript. Successful real-world dogfooding.

11. Privacy iron rule (violation = serious)

PaperGuard output never uses "fraud / 造假 / misconduct / cheating / 学术不端". Every Finding must have ≥3 innocent_explanations (4 for T7).

The following must never appear in any repo file:

  • Institution name [REDACTED-INST]
  • Author name [REDACTED-NAME] / [REDACTED-NAME-EN]
  • DOI prefixes [REDACTED-DOI-1-PREFIX] / [REDACTED-DOI-2-PREFIX]
  • Internal codenames [REDACTED-CODENAME-1] / [REDACTED-CODENAME-2]
  • Local-path tokens USER / PROJECT_DIR

Verification command in §5.

12. Standard ship workflow

When a feature/fix is ready:

  1. 3-gate (§5) — all green
  2. Privacy grep — clean
  3. Bump version in pyproject.toml + src/paperguard/__init__.py + CITATION.cff
  4. Add CHANGELOG entry above the previous version's ## [...] heading
  5. git add ... (specific files, never git add -A)
  6. git commit -m "X.Y.Z — summary" -m "details + Co-Authored-By"
  7. git tag -a vX.Y.Z -m "..."
  8. git push origin main && git push origin vX.Y.Z
    • If push rejected for secret leak, redact then git commit --amend after git add-ing the redacted file (NOT just --amend alone — amend doesn't re-stage)
  9. rm -rf dist/ build/ *.egg-info && python -m build
  10. PYTHONIOENCODING=utf-8 twine upload --username __token__ --password <PYPI_TOKEN> dist/paperguard-X.Y.Z*
  11. gh release create vX.Y.Z --title "..." --notes "..."

13. First message in next session

After pasting this file, the agent's first reply should be:

Read the 2.5.0 handoff doc. Current state: 39 detectors (35 academic + 4 industrial; G5 reagent-temporal added 2.4.0) / 534 tests / 103 source files / 2.0.15 → 2.5.0 all shipped (37 versions over 4 days) / 13 empirical datasets / T7 on gpt-4o LR+ = 8.0 inverted, T8 on gpt-4o LR+ = ∞ (real OpenAI endpoint unlocked 2.4.0) / Audit log v1 shipped 2.5.0 / paper.md JOSS-ready / HF Space live on gradio 5.34 + py 3.11 / Docker multi-arch on GHCR / entire git history sanitized via filter-repo on 2026-05-22.

Highest-value remaining work: JOSS submission (user action, needs ORCID; ~30 min to file). Image-recall v6 N=200 (PMID-only both arms) may already have results — check scripts/recall_image_v6_results.json. Other directions: HTML admin UI for the new audit log endpoint, Scientific Data dataset paper draft, T7 self-hosted Llama validation (needs vLLM, currently blocked).

What's next?

Then wait for user direction.

14. Headline numbers a fresh agent should not forget

  • 39 detectors (academic 35 + industrial 4: I1 mass-balance, I2 timestamp, I5 batch-repetition, I6 over-smoothness; G5 reagent-temporal added 2.4.0)
  • 534 tests (3 deselected for network) / ruff clean / mypy --strict clean on 103 source files
  • 13 empirical studies (recall_test v1-v10, recall_image v1-v4, recall_industrial v1, crossval_statcheck + statcheck_kappa, t7_controlled_benchmark, t8_controlled_benchmark)
  • T6 LR+ = ∞ at 0.001 threshold on N=200 (1 TP / 0 FP; v10) — the headline academic-layer result
  • T6 LR+ = 0 at default 0.003 on N=200 (consistent with v8/v9) — T6 is preprint-stage screen, not post-pub forensics
  • B4 statcheck κ = 0.79 vs statcheck-R on N=41 (Landis-Koch "substantial agreement")
  • F6 image cluster LR+ = 1.63 at N=159 across 3 image studies
  • I5 batch repetition LR+ = ∞ on wastewater N=50+50 (60% TPR / 0% FPR; same study covers pharma N=50+50 for an N=200 total across both domains) — the headline industrial-layer result
  • T7 LR+ = 8.0 on OpenAI gpt-4o at calibrated inverted threshold (TPR 80 %, FPR 10 %, N=10+10, p=0.0011). Direction reversed from textbook DetectGPT; use PAPERGUARD_T7_INVERT_THRESHOLD=1. Strongest T7 result on any endpoint to date.
  • T8 LR+ = ∞ on OpenAI gpt-4o (2/10 TP, 0/10 FP, N=10+10). First clean DetectGPT result in the project's history.
  • T7 weak (LR+ 1.69, p=0.11) on Groq Qwen3-32B, reversed (LR+ 0.25) on DeepSeek-v4-flash — both data points support the RLHF-suppression hypothesis (heavy RLHF → reversed direction).
  • 37 PyPI versions shipped across 4 days (2.0.15 → 2.5.0)
  • Audit log v1 — 11 hook sites, JSON-lines mirror, admin endpoint. Shipped 2.5.0.

Doc end. Paste this entire file in the next session to maintain continuity. The first thing the next agent should do is verify the 3-gate command passes — confirms the state hasn't drifted since this handoff was written.


Appendix — release tags (2.2.6 → 2.5.0)

Commit SHAs from before the 2026-05-22 git filter-repo history rewrite are no longer valid. Tags after that point reference post-rewrite SHAs.

Tag Released Subject
v2.2.6 2026-05-22 T7+T8 real-endpoint benchmarks (Groq + DeepSeek)
v2.2.7 2026-05-22 Honest scope statement for T7/T8 (docs-only) + HF Space sync + filter-repo history sanitization
v2.3.0 2026-05-22 Web UI hardening — PAPERGUARD_BEHIND_PROXY=1 + per-IP rate-limit on /login /redeem /scan
v2.3.1 2026-05-22 Image-recall v5 (N=200+200 attrition study) — F6 LR+ retraction from 1.63 to 0.92
v2.4.0 2026-05-23 G5 reagent-temporal detector (39th) absorbed from geng-fraud-skill + first real-OpenAI T7/T8 LR+
v2.4.1 2026-05-23 T7 on gpt-4o: LR+ = 8.0 inverted; 2.4.0 size-hypothesis disproved
v2.4.2 2026-05-23 PAPERGUARD_T7_INVERT_THRESHOLD env var + partial RLHF-hypothesis validation
v2.5.0 2026-05-23 Audit log v1 — AuditEvent model, audit_event helper, 11 hook sites, JSON-lines mirror, admin endpoint