
Backward Traceability
- 1.2k installs
- 255 repo stars
- Updated February 27, 2026
- lingzhi227/agent-research-skills
backward-traceability is an agent skill that creates verifiable clickable links between research paper claims and the exact code or data outputs that produced each numeric result for developers who publish reproducible M
About
backward-traceability is an agent-research skill extracted from data-to-paper workflows that makes every numeric claim in a research paper traceable to code-generated output. The skill defines LaTeX patterns using \hypertarget to mark values in code output, \hyperlink to reference those values in paper text with clickable PDF jumps, and \num to evaluate derived formulas at compile time with stored explanations. Label formats connect ref_numeric_values.py, referencable_text.py, and latex_to_pdf.py style pipelines so readers click a reported metric and land on the exact artifact that produced it. Developers reach for backward-traceability when writing ML or data-science papers where reviewers demand reproducibility beyond a static results table. The skill fits teams generating LaTeX from Python pipelines who need audit-grade backward links from prose to computation.
- Generates \hypertarget markers in code-generated LaTeX output
- Creates \hyperlink references in paper text that jump to source values in compiled PDF
- Implements \num macro for compile-time evaluated formulas with automatic explanations
- Enforces strict label format {prefix}{line_number}{letter} for unambiguous provenance
- Supports 4+ HypertargetPosition modes extracted from data-to-paper pipeline
Backward Traceability by the numbers
- 1,170 all-time installs (skills.sh)
- +35 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #235 of 1,879 Documentation skills by installs in the Skillselion catalog
- Security screen: MEDIUM risk (skills.sh audit)
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/lingzhi227/agent-research-skills --skill backward-traceabilityAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1.2k |
|---|---|
| repo stars | ★ 255 |
| Security audit | 2 / 3 scanners passed |
| Last updated | February 27, 2026 |
| Repository | lingzhi227/agent-research-skills ↗ |
How do you link paper claims to reproducible code outputs?
Create verifiable, clickable links between research paper claims and the exact code or data that produced each numeric result.
Who is it for?
Researchers and ML engineers publishing LaTeX papers from Python pipelines who need clickable backward traceability from every reported number to source output.
Skip if: Developers writing application READMEs, API docs, or papers without LaTeX pipelines or code-generated numeric artifacts to link.
When should I use this skill?
A developer needs clickable PDF links from paper metrics to code output, LaTeX hypertarget labels, or reproducible numeric traceability in a research manuscript.
What you get
LaTeX hypertarget labels, hyperlink references, compile-time \num formulas, and clickable PDF traceability from prose metrics to code artifacts.
- Hypertarget label definitions
- Hyperlink reference markup
- Compile-time formula annotations
Files
Backward Traceability
Make every number in the final PDF hyperlink back to the exact code line that produced it.
Input
$0— Paper project directory containing code and LaTeX files
References
- Traceability patterns and LaTeX commands:
~/.claude/skills/backward-traceability/references/traceability-patterns.md
Scripts
Scan hypertarget/hyperlink references
python ~/.claude/skills/backward-traceability/scripts/ref_numeric_values.py \
--scan paper/main.tex --output report.jsonReports: all hypertargets, hyperlinks, orphan references, unreferenced numeric values.
Verify cross-reference integrity
python ~/.claude/skills/backward-traceability/scripts/ref_numeric_values.py \
--verify paper/main.tex --code-output results.txtCross-checks values between paper text and code output. Reports mismatches.
Workflow
Step 1: Tag Code Outputs
For every numeric value produced by experiment code, add hypertarget tags:
# In experiment code output:
print(f"\\hypertarget{{R1a}}{{45.3}}") # Mean accuracy
print(f"\\hypertarget{{R1b}}{{2.1}}") # Std deviationLabel format: {prefix}{line_number}{letter} where letter = a, b, c... for multiple values on same line.
Step 2: Reference in Paper Text
Use \hyperlink to create clickable references in the paper:
Our method achieves \hyperlink{R1a}{45.3}\% accuracy
($\pm$\hyperlink{R1b}{2.1}).Step 3: Use \num for Computed Values
For values derived from other values, use \num{} for compile-time evaluation:
% \num{formula, "explanation"} → evaluated at compile time
The improvement is \num{45.3 - 38.7, "accuracy gain"}\%.Step 4: Generate Appendix Code Listing
Create an appendix with the full code listing, with \hypertarget anchors at relevant lines:
\section*{Appendix: Code Listing}
\begin{lstlisting}[escapechar=@]
@\hypertarget{code1}{}@result = model.evaluate(test_data)
@\hypertarget{code2}{}@accuracy = result['accuracy']
\end{lstlisting}Step 5: Verify Traceability
- Every number in the paper text must have a corresponding
\hypertargetin the code - Every
\num{}formula must evaluate correctly - Click-test: every hyperlink in the PDF must jump to the correct code line
LaTeX Setup
Required packages:
\usepackage{hyperref}
\usepackage{listings}Rules
- Every numeric result in the paper MUST trace to code output
- Never manually type numbers — always reference tagged outputs
- Use
\num{}for any derived/computed values - Code listing in appendix must match actual executed code
- Verify all hyperlinks resolve correctly after compilation
Related Skills
- Upstream: experiment-code, data-analysis
- Downstream: paper-compilation
- See also: paper-assembly
Backward Traceability Patterns
Extracted from data-to-paper (ref_numeric_values.py, referencable_text.py, latex_to_pdf.py).
Core LaTeX Commands
\hypertarget — Mark a Value in Code Output
% In code-generated output:
\hypertarget{R1a}{45.3}
% R1a = reference label, 45.3 = the value\hyperlink — Reference a Value in Paper Text
% In paper body:
Our method achieves \hyperlink{R1a}{45.3}\% accuracy.
% Clicking 45.3 in PDF jumps to the code output\num — Compile-Time Evaluated Formula
% Compute derived values at compile time:
\num{45.3 - 38.7, "accuracy improvement over baseline"}
% Evaluates to 6.6 and stores explanationLabel Format Convention (data-to-paper)
Label = {prefix}{line_number}{letter}
prefix: identifies the code block (e.g., "code", "R")
line_number: line in the code that produces the value
letter: a, b, c... for multiple values on same line
Examples:
code1a → code block, line 1, 1st value
code1b → code block, line 1, 2nd value
code12a → code block, line 12, 1st value
R3c → results block, line 3, 3rd valueLetter conversion (data-to-paper referencable_text.py):
def _num_to_letters(num):
"""1→a, 2→b, ... 26→z, 27→aa, 28→ab, ..."""
letters = ''
while num > 0:
num -= 1
letters = chr(ord('a') + num % 26) + letters
num //= 26
return lettersHypertargetPosition Modes (data-to-paper)
class HypertargetPosition(Enum):
WRAP = "wrap" # \hypertarget{label}{value}
ADJACENT = "adjacent" # \hypertarget{label}{}value
HEADER = "header" # \hypertarget{label}{} (value elsewhere)
NONE = "none" # No hypertargets\num Implementation (data-to-paper latex_to_pdf.py)
def evaluate_latex_num_command(latex_str, ref_prefix='',
enforce_explanation=True):
r"""
Evaluates \num{formula} or \num{formula, "explanation"} in latex.
If ref_prefix provided, adds \hyperlink{ref_prefix?}{result}
where ? is the index.
Returns:
- new_latex_str: with \num{} replaced by computed values
- labels_to_notes: dict mapping labels to "formula = result"
"""
# Available math functions for eval():
namespace = {
'exp': np.exp, 'log': np.log,
'sin': np.sin, 'cos': np.cos, 'tan': np.tan,
'pi': np.pi, 'e': np.e,
'sqrt': np.sqrt, 'log2': np.log2, 'log10': np.log10,
'abs': np.abs,
}
result = eval(formula_without_hyperlinks, namespace)
# Create hyperlink:
label = f'{ref_prefix}{index}'
replace_with = f'\\hyperlink{{{label}}}{{{result}}}'
# Store note:
labels_to_notes[label] = f"{formula} = {result}"
if explanation:
labels_to_notes[label] += f" ({explanation})"Code Output Tagging Pattern
Python Code (Experiment Script)
# Tag every numeric output with hypertarget
def save_results_with_targets(results, prefix="R"):
"""Save results with LaTeX hypertarget tags."""
lines = []
line_no = 1
for key, value in results.items():
letter = 'a'
if isinstance(value, dict):
for subkey, subval in value.items():
label = f"{prefix}{line_no}{letter}"
lines.append(f"\\hypertarget{{{label}}}{{{subval:.4f}}}")
letter = chr(ord(letter) + 1)
else:
label = f"{prefix}{line_no}a"
lines.append(f"\\hypertarget{{{label}}}{{{value:.4f}}}")
line_no += 1
return linesUsage in Experiment
results = {
"accuracy": 0.453,
"precision": 0.421,
"recall": 0.487,
"f1": 0.452,
}
tagged = save_results_with_targets(results)
# Output:
# \hypertarget{R1a}{0.4530}
# \hypertarget{R2a}{0.4210}
# \hypertarget{R3a}{0.4870}
# \hypertarget{R4a}{0.4520}Appendix Code Listing Template
\section*{Appendix A: Experiment Code}
\begin{lstlisting}[
language=Python,
basicstyle=\ttfamily\scriptsize,
numbers=left,
numberstyle=\tiny,
escapechar=@,
caption={Main experiment code with traceability anchors}
]
@\hypertarget{code1}{}@import torch
@\hypertarget{code2}{}@from model import MyModel
@\hypertarget{code5}{}@model = MyModel(hidden_dim=256)
@\hypertarget{code6}{}@optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)
@\hypertarget{code10}{}@for epoch in range(100):
@\hypertarget{code11}{}@ loss = train_epoch(model, train_loader)
@\hypertarget{code12}{}@ acc = evaluate(model, test_loader)
@\hypertarget{code15}{}@final_accuracy = evaluate(model, test_loader)
@\hypertarget{code16}{}@print(f"Final: {final_accuracy:.4f}")
\end{lstlisting}Calculation Notes Section
\section*{Appendix B: Calculation Notes}
The following values in this paper are computed from experimental results:
\begin{itemize}
\item \hyperlink{N1}{6.6}: $45.3 - 38.7 = 6.6$ (accuracy improvement)
\item \hyperlink{N2}{1.17}: $45.3 / 38.7 = 1.17$ (relative improvement)
\item \hyperlink{N3}{14.6}: $(45.3 - 38.7) / 45.3 \times 100 = 14.6$ (\% relative gain)
\end{itemize}Required LaTeX Packages
\usepackage{hyperref} % For \hypertarget, \hyperlink
\usepackage{listings} % For code listings with escapechar
\usepackage{xcolor} % For colored hyperlinks (optional)
% Optional: make hyperlinks colored
\hypersetup{
colorlinks=true,
linkcolor=blue,
citecolor=blue,
}Verification Checklist
For every number in the paper text:
[ ] Has a corresponding \hypertarget in code output
[ ] \hyperlink label matches the \hypertarget label
[ ] Value in text matches value in code output
[ ] Click-test: hyperlink in PDF jumps to correct location
For every \num{} command:
[ ] Formula evaluates correctly
[ ] Explanation is provided
[ ] Result matches expected value
[ ] Hyperlink (if ref_prefix) resolves correctly#!/usr/bin/env python3
"""Scan and verify hypertarget/hyperlink numeric references in LaTeX files.
Two modes:
--scan: Report all \\hypertarget and \\hyperlink usage in a .tex file
--verify: Cross-reference targets vs links for integrity
Self-contained: uses only stdlib.
Extracted from data-to-paper's ref_numeric_values.py.
Usage:
python ref_numeric_values.py --scan main.tex --output report.json
python ref_numeric_values.py --verify main.tex --code-output results.txt
python ref_numeric_values.py --scan main.tex
"""
import argparse
import json
import os
import re
import sys
from dataclasses import dataclass, asdict
from typing import Optional
TARGET = r'\hypertarget'
LINK = r'\hyperlink'
def get_numeric_value_pattern(must_follow: Optional[str] = None,
allow_commas: bool = True) -> str:
"""Get a regex pattern for numeric values."""
prefix = ""
if must_follow is not None:
prefix = f"(?<={must_follow})"
if allow_commas:
pattern = r'(?:[-+]?\d+(?:,\d{3})*(?:\.\d+)?(?:e[-+]?\d+)?|\d{1,3}(?:,\d{3})+)(?!\d)'
else:
pattern = r'[-+]?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?'
return prefix + pattern
NUMERIC_PATTERN = get_numeric_value_pattern(
must_follow=r'[$,{<=\s\n\(\[]', allow_commas=True
)
@dataclass
class ReferencedValue:
"""A numeric value with a reference label."""
value: str
label: Optional[str] = None
is_target: bool = True
line_num: int = 0
@property
def command(self) -> str:
return TARGET if self.is_target else LINK
def get_hyperlink_pattern(is_target: bool = False) -> str:
"""Get regex pattern for \\hypertarget or \\hyperlink commands."""
command = re.escape(TARGET if is_target else LINK)
return rf'{command}\{{(?P<reference>[^}}]*)\}}\{{(?P<value>[^}}]*)\}}'
def find_references(text: str, is_targets: bool = False) -> list[ReferencedValue]:
"""Find all hypertarget or hyperlink references in text."""
pattern = get_hyperlink_pattern(is_targets)
refs = []
for i, line in enumerate(text.splitlines(), 1):
for match in re.finditer(pattern, line):
refs.append(ReferencedValue(
value=match.group('value'),
label=match.group('reference'),
is_target=is_targets,
line_num=i,
))
return refs
def find_numeric_values(text: str, remove_hyperlinks: bool = True) -> list[str]:
"""Find all unreferenced numeric values in text."""
text = ' ' + text + ' '
if remove_hyperlinks:
text = re.sub(get_hyperlink_pattern(is_target=False), '', text)
text = re.sub(get_hyperlink_pattern(is_target=True), '', text)
return re.findall(NUMERIC_PATTERN, text)
def replace_hyperlinks_with_values(text: str, is_targets: bool = False) -> str:
"""Replace all hypertarget/hyperlink commands with just their values."""
def replace_match(match):
return match.group('value')
pattern = get_hyperlink_pattern(is_targets)
return re.sub(pattern, replace_match, text)
def scan_file(tex_content: str) -> dict:
"""Scan a .tex file and report all hypertarget/hyperlink usage."""
targets = find_references(tex_content, is_targets=True)
links = find_references(tex_content, is_targets=False)
unreferenced = find_numeric_values(tex_content)
return {
"hypertargets": [asdict(t) for t in targets],
"hyperlinks": [asdict(l) for l in links],
"target_count": len(targets),
"link_count": len(links),
"target_labels": sorted(set(t.label for t in targets if t.label)),
"link_labels": sorted(set(l.label for l in links if l.label)),
"unreferenced_numeric_values": unreferenced[:50],
"unreferenced_count": len(unreferenced),
}
def verify_integrity(tex_content: str, code_output: str = "") -> dict:
"""Verify cross-reference integrity between targets and links."""
targets = find_references(tex_content, is_targets=True)
links = find_references(tex_content, is_targets=False)
target_labels = {t.label for t in targets if t.label}
link_labels = {l.label for l in links if l.label}
# Find mismatches
unresolved_links = link_labels - target_labels
unused_targets = target_labels - link_labels
# Check value consistency (same label should have same value)
target_values = {}
for t in targets:
if t.label:
target_values[t.label] = t.value
link_values = {}
for l in links:
if l.label:
link_values[l.label] = l.value
value_mismatches = []
for label in target_labels & link_labels:
tv = target_values.get(label, "")
lv = link_values.get(label, "")
if tv and lv and tv != lv:
value_mismatches.append({
"label": label,
"target_value": tv,
"link_value": lv,
})
# Check against code output if provided
code_values = {}
if code_output:
for line in code_output.splitlines():
m = re.search(get_hyperlink_pattern(is_target=True), line)
if m:
code_values[m.group('reference')] = m.group('value')
code_mismatches = []
if code_values:
for label, code_val in code_values.items():
tex_val = target_values.get(label)
if tex_val and tex_val != code_val:
code_mismatches.append({
"label": label,
"code_value": code_val,
"tex_value": tex_val,
})
result = {
"total_targets": len(targets),
"total_links": len(links),
"unresolved_links": sorted(unresolved_links),
"unused_targets": sorted(unused_targets),
"value_mismatches": value_mismatches,
"code_mismatches": code_mismatches,
"integrity_ok": (
len(unresolved_links) == 0
and len(value_mismatches) == 0
and len(code_mismatches) == 0
),
}
return result
def main():
parser = argparse.ArgumentParser(
description="Scan and verify hypertarget/hyperlink references in LaTeX"
)
parser.add_argument("tex_file", help="LaTeX file to analyze")
parser.add_argument("--scan", action="store_true",
help="Scan mode: report all hypertarget/hyperlink usage")
parser.add_argument("--verify", action="store_true",
help="Verify mode: check cross-reference integrity")
parser.add_argument("--code-output", help="Code output file for cross-referencing")
parser.add_argument("--output", "-o", help="Output JSON file (default: stdout)")
args = parser.parse_args()
if not args.scan and not args.verify:
args.scan = True # Default to scan mode
if not os.path.exists(args.tex_file):
print(f"Error: {args.tex_file} not found", file=sys.stderr)
sys.exit(1)
with open(args.tex_file, encoding="utf-8", errors="replace") as f:
tex_content = f.read()
code_output = ""
if args.code_output and os.path.exists(args.code_output):
with open(args.code_output, encoding="utf-8", errors="replace") as f:
code_output = f.read()
if args.scan:
result = scan_file(tex_content)
print(f"Targets: {result['target_count']}, Links: {result['link_count']}, "
f"Unreferenced numbers: {result['unreferenced_count']}", file=sys.stderr)
else:
result = verify_integrity(tex_content, code_output)
status = "OK" if result["integrity_ok"] else "ISSUES FOUND"
print(f"Integrity: {status}", file=sys.stderr)
if result["unresolved_links"]:
print(f" Unresolved links: {result['unresolved_links']}", file=sys.stderr)
if result["value_mismatches"]:
print(f" Value mismatches: {len(result['value_mismatches'])}", file=sys.stderr)
if result["code_mismatches"]:
print(f" Code mismatches: {len(result['code_mismatches'])}", file=sys.stderr)
output = json.dumps(result, indent=2, ensure_ascii=False)
if args.output:
with open(args.output, "w", encoding="utf-8") as f:
f.write(output)
print(f"Report written to {args.output}", file=sys.stderr)
else:
print(output)
if args.verify and not result["integrity_ok"]:
sys.exit(1)
if __name__ == "__main__":
main()
Related skills
How it compares
Pick backward-traceability over generic documentation skills when publishing LaTeX research papers that must link prose metrics back to code-generated outputs.
FAQ
What LaTeX commands does backward-traceability use?
backward-traceability uses \hypertarget to mark values in code-generated output, \hyperlink to reference those values in paper text with clickable PDF jumps, and \num to evaluate derived formulas at compile time with explanations.
What problem does backward-traceability solve?
backward-traceability solves unverifiable research claims by creating clickable backward links from every numeric result in a LaTeX paper to the exact code or data artifact that produced that value.
Where do backward-traceability patterns come from?
backward-traceability patterns are extracted from data-to-paper tooling such as ref_numeric_values.py, referencable_text.py, and latex_to_pdf.py workflows that generate referencable LaTeX from Python pipelines.
Is Backward Traceability safe to install?
skills.sh reports 2 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.