psyclaw 0.28.1 → 0.28.3

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 (135) hide show
  1. package/README.md +5 -5
  2. package/agents/recommended/catalog.json +1 -1
  3. package/dist/src/adapters/pi/extension.js +79 -25
  4. package/dist/src/adapters/pi/extension.js.map +1 -1
  5. package/dist/src/ars/keybindings.d.ts +13 -0
  6. package/dist/src/ars/keybindings.js +50 -0
  7. package/dist/src/ars/keybindings.js.map +1 -0
  8. package/dist/src/ars/mode-editor.d.ts +25 -0
  9. package/dist/src/ars/mode-editor.js +78 -0
  10. package/dist/src/ars/mode-editor.js.map +1 -0
  11. package/dist/src/ars/profile.d.ts +4 -1
  12. package/dist/src/ars/profile.js +23 -6
  13. package/dist/src/ars/profile.js.map +1 -1
  14. package/dist/src/chat.js +3 -0
  15. package/dist/src/chat.js.map +1 -1
  16. package/dist/src/panel/server.js +1 -1
  17. package/dist/src/panel/server.js.map +1 -1
  18. package/package.json +10 -3
  19. package/vendor/academic-paper-skills/LICENSE +21 -0
  20. package/vendor/academic-paper-skills/NOTICE.md +7 -0
  21. package/vendor/academic-paper-skills/PSYCLAW_SOURCE.json +14 -0
  22. package/vendor/academic-paper-skills/academic-paper-composer/SKILL.md +840 -0
  23. package/vendor/academic-paper-skills/academic-paper-composer/references/section_guides.md +675 -0
  24. package/vendor/academic-paper-skills/academic-paper-composer/references/writing_standards.md +629 -0
  25. package/vendor/academic-paper-skills/academic-paper-composer/scripts/chapter_quality_check.py +470 -0
  26. package/vendor/academic-paper-skills/academic-paper-composer/scripts/final_evaluation.py +550 -0
  27. package/vendor/academic-paper-skills/academic-paper-strategist/SKILL.md +670 -0
  28. package/vendor/academic-paper-skills/academic-paper-strategist/references/quality_standards.md +336 -0
  29. package/vendor/academic-paper-skills/academic-paper-strategist/references/search_strategy.md +459 -0
  30. package/vendor/academic-paper-skills/academic-paper-strategist/scripts/evaluate_samples.py +300 -0
  31. package/vendor/academic-paper-skills/academic-paper-strategist/scripts/gap_analysis.py +399 -0
  32. package/vendor/ars/pi/wrapper.js +9 -0
  33. package/vendor/nature-skills/LICENSE +201 -0
  34. package/vendor/nature-skills/NOTICE.md +7 -0
  35. package/vendor/nature-skills/PSYCLAW_SOURCE.json +19 -0
  36. package/vendor/nature-skills/skills/nature-figure/README.md +107 -0
  37. package/vendor/nature-skills/skills/nature-figure/README_EN.md +107 -0
  38. package/vendor/nature-skills/skills/nature-figure/SKILL.md +154 -0
  39. package/vendor/nature-skills/skills/nature-figure/agents/openai.yaml +4 -0
  40. package/vendor/nature-skills/skills/nature-figure/evals/evals.json +325 -0
  41. package/vendor/nature-skills/skills/nature-figure/manifest.yaml +103 -0
  42. package/vendor/nature-skills/skills/nature-figure/references/ai-graphical-abstract-workflow.md +129 -0
  43. package/vendor/nature-skills/skills/nature-figure/references/api.md +576 -0
  44. package/vendor/nature-skills/skills/nature-figure/references/asset-adaptation.md +72 -0
  45. package/vendor/nature-skills/skills/nature-figure/references/backend-selection.md +118 -0
  46. package/vendor/nature-skills/skills/nature-figure/references/chart-types.md +348 -0
  47. package/vendor/nature-skills/skills/nature-figure/references/common-patterns.md +371 -0
  48. package/vendor/nature-skills/skills/nature-figure/references/demos.md +58 -0
  49. package/vendor/nature-skills/skills/nature-figure/references/design-theory.md +467 -0
  50. package/vendor/nature-skills/skills/nature-figure/references/figure-contract.md +122 -0
  51. package/vendor/nature-skills/skills/nature-figure/references/figure-legend-conventions.md +90 -0
  52. package/vendor/nature-skills/skills/nature-figure/references/multipanel-evidence-architecture.md +268 -0
  53. package/vendor/nature-skills/skills/nature-figure/references/nature-2026-observations.md +124 -0
  54. package/vendor/nature-skills/skills/nature-figure/references/nature-article-requirements.md +149 -0
  55. package/vendor/nature-skills/skills/nature-figure/references/openrouter-image-generation.md +141 -0
  56. package/vendor/nature-skills/skills/nature-figure/references/qa-contract.md +344 -0
  57. package/vendor/nature-skills/skills/nature-figure/references/r-template-index.md +66 -0
  58. package/vendor/nature-skills/skills/nature-figure/references/r-workflow.md +234 -0
  59. package/vendor/nature-skills/skills/nature-figure/references/template-catalog.md +33 -0
  60. package/vendor/nature-skills/skills/nature-figure/references/tutorials.md +260 -0
  61. package/vendor/nature-skills/skills/nature-figure/requirements.txt +1 -0
  62. package/vendor/nature-skills/skills/nature-figure/scripts/audit_figure_collisions.py +742 -0
  63. package/vendor/nature-skills/skills/nature-figure/scripts/audit_panel_alignment.py +933 -0
  64. package/vendor/nature-skills/skills/nature-figure/scripts/audit_pdf_text.py +152 -0
  65. package/vendor/nature-skills/skills/nature-figure/scripts/figure_safety.py +50 -0
  66. package/vendor/nature-skills/skills/nature-figure/scripts/generate_openrouter_schematic.py +260 -0
  67. package/vendor/nature-skills/skills/nature-figure/scripts/nature_figure_backend.py +93 -0
  68. package/vendor/nature-skills/skills/nature-figure/scripts/panel_alignment.R +188 -0
  69. package/vendor/nature-skills/skills/nature-figure/scripts/plot_templates.py +604 -0
  70. package/vendor/nature-skills/skills/nature-figure/scripts/validate_figure.py +835 -0
  71. package/vendor/nature-skills/skills/nature-figure/static/core/contract.md +55 -0
  72. package/vendor/nature-skills/skills/nature-figure/static/core/stance.md +41 -0
  73. package/vendor/nature-skills/skills/nature-figure/static/fragments/backend/python.md +56 -0
  74. package/vendor/nature-skills/skills/nature-figure/static/fragments/backend/r.md +63 -0
  75. package/vendor/nature-skills/skills/nature-figure/tests/test_figure_safety.py +209 -0
  76. package/vendor/nature-skills/skills/nature-polishing/README.md +58 -0
  77. package/vendor/nature-skills/skills/nature-polishing/README_EN.md +58 -0
  78. package/vendor/nature-skills/skills/nature-polishing/SKILL.md +111 -0
  79. package/vendor/nature-skills/skills/nature-polishing/agents/openai.yaml +4 -0
  80. package/vendor/nature-skills/skills/nature-polishing/manifest.yaml +101 -0
  81. package/vendor/nature-skills/skills/nature-polishing/references/latex-layout.md +211 -0
  82. package/vendor/nature-skills/skills/nature-polishing/references/nat-comms-2025-diction.md +73 -0
  83. package/vendor/nature-skills/skills/nature-polishing/references/phrasebank-playbook.md +175 -0
  84. package/vendor/nature-skills/skills/nature-polishing/references/published-article-patterns.md +126 -0
  85. package/vendor/nature-skills/skills/nature-polishing/references/section-moves.md +252 -0
  86. package/vendor/nature-skills/skills/nature-polishing/references/style-guardrails.md +94 -0
  87. package/vendor/nature-skills/skills/nature-polishing/references/writing-strategy.md +160 -0
  88. package/vendor/nature-skills/skills/nature-polishing/static/core/failure-modes.md +29 -0
  89. package/vendor/nature-skills/skills/nature-polishing/static/core/output-format.md +21 -0
  90. package/vendor/nature-skills/skills/nature-polishing/static/core/stance.md +26 -0
  91. package/vendor/nature-skills/skills/nature-polishing/static/fragments/journal/generic.md +17 -0
  92. package/vendor/nature-skills/skills/nature-polishing/static/fragments/journal/nat-comms.md +38 -0
  93. package/vendor/nature-skills/skills/nature-polishing/static/fragments/journal/nat-mach-intell.md +102 -0
  94. package/vendor/nature-skills/skills/nature-polishing/static/fragments/journal/nature.md +19 -0
  95. package/vendor/nature-skills/skills/nature-polishing/static/fragments/language/en.md +19 -0
  96. package/vendor/nature-skills/skills/nature-polishing/static/fragments/language/zh-to-en.md +19 -0
  97. package/vendor/nature-skills/skills/nature-polishing/static/fragments/paper_type/algorithmic.md +18 -0
  98. package/vendor/nature-skills/skills/nature-polishing/static/fragments/paper_type/hypothesis.md +17 -0
  99. package/vendor/nature-skills/skills/nature-polishing/static/fragments/paper_type/methods.md +35 -0
  100. package/vendor/nature-skills/skills/nature-polishing/static/fragments/paper_type/research.md +29 -0
  101. package/vendor/nature-skills/skills/nature-polishing/static/fragments/paper_type/review.md +17 -0
  102. package/vendor/nature-skills/skills/nature-polishing/static/fragments/section/abstract.md +26 -0
  103. package/vendor/nature-skills/skills/nature-polishing/static/fragments/section/conclusion.md +15 -0
  104. package/vendor/nature-skills/skills/nature-polishing/static/fragments/section/discussion.md +48 -0
  105. package/vendor/nature-skills/skills/nature-polishing/static/fragments/section/intro.md +33 -0
  106. package/vendor/nature-skills/skills/nature-polishing/static/fragments/section/methods.md +26 -0
  107. package/vendor/nature-skills/skills/nature-polishing/static/fragments/section/results.md +61 -0
  108. package/vendor/nature-skills/skills/nature-polishing/static/fragments/section/title.md +17 -0
  109. package/vendor/nature-skills/skills/nature-ref-verifier/README.md +44 -0
  110. package/vendor/nature-skills/skills/nature-ref-verifier/README_EN.md +44 -0
  111. package/vendor/nature-skills/skills/nature-ref-verifier/SKILL.md +196 -0
  112. package/vendor/nature-skills/skills/nature-ref-verifier/agents/openai.yaml +4 -0
  113. package/vendor/nature-skills/skills/nature-ref-verifier/manifest.yaml +19 -0
  114. package/vendor/nature-skills/skills/nature-ref-verifier/references/common-patterns.md +96 -0
  115. package/vendor/nature-skills/skills/nature-shared/README.md +43 -0
  116. package/vendor/nature-skills/skills/nature-shared/README_EN.md +43 -0
  117. package/vendor/nature-skills/skills/nature-shared/SKILL.md +33 -0
  118. package/vendor/nature-skills/skills/nature-shared/agents/openai.yaml +6 -0
  119. package/vendor/nature-skills/skills/nature-shared/core/consistency-sweep.md +122 -0
  120. package/vendor/nature-skills/skills/nature-shared/core/discussion-argument-language.md +192 -0
  121. package/vendor/nature-skills/skills/nature-shared/core/ethics.md +88 -0
  122. package/vendor/nature-skills/skills/nature-shared/core/main-text-discipline.md +179 -0
  123. package/vendor/nature-skills/skills/nature-shared/core/nature-abstract.md +171 -0
  124. package/vendor/nature-skills/skills/nature-shared/core/nature-introduction.md +164 -0
  125. package/vendor/nature-skills/skills/nature-shared/core/nature-results-discussion.md +215 -0
  126. package/vendor/nature-skills/skills/nature-shared/core/paper-type-taxonomy.md +41 -0
  127. package/vendor/nature-skills/skills/nature-shared/core/reader-workflow.md +21 -0
  128. package/vendor/nature-skills/skills/nature-shared/core/research-compliance.md +192 -0
  129. package/vendor/nature-skills/skills/nature-shared/core/terminology-ledger.md +58 -0
  130. package/vendor/nature-skills/skills/nature-shared/journal-formats/nat-comms.md +139 -0
  131. package/vendor/nature-skills/skills/nature-shared/journal-formats/nature-machine-intelligence.md +431 -0
  132. package/vendor/nature-skills/skills/nature-shared/journal-formats/nature.md +313 -0
  133. package/vendor/nature-skills/skills/nature-shared/manifest.yaml +52 -0
  134. package/vendor/nature-skills/skills/nature-shared/scripts/check_consistency.py +273 -0
  135. package/vendor/nature-skills/skills/nature-shared/tests/test_check_consistency.py +63 -0
@@ -0,0 +1,344 @@
1
+ # QA Contract
2
+
3
+ ## Contents
4
+
5
+ - [Current official references to verify](#current-official-references-to-verify)
6
+ - [Pre-submission checklist](#pre-submission-checklist)
7
+ - [Statistics legend minimum](#statistics-legend-minimum)
8
+ - [Image-integrity minimum](#image-integrity-minimum)
9
+ - [Automated source preflight](#automated-source-preflight)
10
+ - [Automatic multi-panel alignment gate](#automatic-multi-panel-alignment-gate)
11
+ - [Automatic rendered collision audit](#automatic-rendered-collision-audit)
12
+ - [Rendered panel-by-panel audit](#rendered-panel-by-panel-audit)
13
+ - [Typography and PDF glyph floor](#typography-and-pdf-glyph-floor)
14
+ - [Uncertainty consistency](#uncertainty-consistency)
15
+ - [Geometry and annotation placement](#geometry-and-annotation-placement)
16
+ - [Color separation and salience](#color-separation-and-salience)
17
+ - [Transformation and paired-effect checks](#transformation-and-paired-effect-checks)
18
+ - [Export checks](#export-checks)
19
+
20
+
21
+ Use this before final delivery, before a revision package, and whenever the figure
22
+ contains microscopy, blots, gels, clinical subgroup analysis, or statistical claims.
23
+ Journal rules change, so verify the latest target journal author guide for final
24
+ submission. The values below are conservative defaults for Nature-family style work.
25
+ For the flagship journal Nature, load `nature-article-requirements.md` and use
26
+ its stage-specific main-figure, Extended Data and legend contracts.
27
+
28
+ ## Current official references to verify
29
+
30
+ - Nature research figure guide: `https://research-figure-guide.nature.com/`
31
+ - Nature building/exporting panels: `https://research-figure-guide.nature.com/figures/building-and-exporting-figure-panels/`
32
+ - Nature preparing figures/specifications: `https://research-figure-guide.nature.com/figures/preparing-figures-our-specifications/`
33
+ - Nature initial submission and statistics guidance: `https://www.nature.com/nature/for-authors/initial-submission`
34
+ - Nature formatting guide: `https://www.nature.com/nature/for-authors/formatting-guide`
35
+ - Journal of Cell Biology figure/video guidelines for microscopy-oriented image QA: `https://rupress.org/jcb/pages/fig-vid-guidelines`
36
+ - Elsevier/Cell-family image-manipulation baseline: `https://www.sciencedirect.com/journal/the-cell-surface/publish/guide-for-authors`
37
+
38
+ ## Pre-submission checklist
39
+
40
+ | Check | Pass condition |
41
+ |---|---|
42
+ | Core conclusion | One-sentence claim exists and every panel maps to it |
43
+ | Archetype | Figure has a declared archetype and panel hierarchy |
44
+ | Backend exclusivity | The selected backend produced all plotting, previews, exports, and visual QA renders |
45
+ | Final size | Single-column about 89 mm or double-column about 183 mm, height not above target journal limit |
46
+ | Text size | Body/tick/legend text is readable at final size, usually 5-7 pt for dense journal figures |
47
+ | Rendered glyph floor | Every PDF text run, including math superscripts/subscripts, is at least 5 pt |
48
+ | Panel labels | Lowercase, bold, near top-left, typically 8 pt at final size |
49
+ | Editable text | SVG/PDF text remains editable; no outlined text unless unavoidable for special symbols |
50
+ | Font | Arial/Helvetica/sans-serif fallback is used consistently |
51
+ | Color | No rainbow color maps; red/green is not the only encoding; grayscale print remains interpretable |
52
+ | Legend strategy | Shared or direct labels where possible; no repeated redundant legends |
53
+ | Display terminology | Legend labels use display-style initial capitalization and preserve canonical model names |
54
+ | Statistics | `n`, biological/technical repeat definition, center, spread, test, correction, and exact comparison are documented |
55
+ | Comparable uncertainty | Every comparable seed/fold/split aggregate panel shows the same variability definition or documents an exemption |
56
+ | Annotation clearance | Automatic PDF collision audit has no FAIL findings; every WARN is reviewed at final size and justified or fixed |
57
+ | Panel alignment | Every multi-panel figure has a fresh alignment JSON; comparable row/column edges, dimensions, labels and repeated gutters are within 1.5 pt or carry a reasoned exemption |
58
+ | Visual hierarchy | Hero evidence remains more salient than neutral baselines after rendering |
59
+ | Numerical transforms | Interpolation/normalization direction and monotonicity assumptions are asserted in code |
60
+ | Source data | Quantitative panels can be traced to a clean CSV/TSV/XLSX or script output |
61
+ | Raster resolution | Photos/microscopy are high-resolution enough for final size; line art uses vector where possible |
62
+ | Microscopy scale | Scale bar is present, calibrated, and not only a magnification factor |
63
+ | Image integrity | Crop, contrast, pseudo-color, stitching, reuse, and raw-file provenance are recorded |
64
+ | Export bundle | Script, source data, SVG, PDF, TIFF/PNG preview, and QA notes are delivered together when requested; previews are not mislabeled as accepted main-figure upload formats |
65
+
66
+ ## Statistics legend minimum
67
+
68
+ For each quantitative panel, capture:
69
+
70
+ ```text
71
+ n definition:
72
+ biological replicates:
73
+ technical replicates:
74
+ center statistic:
75
+ spread/interval:
76
+ test:
77
+ multiple-comparison correction:
78
+ p-value display:
79
+ source-data file:
80
+ ```
81
+
82
+ For machine-learning/model figures, also capture:
83
+
84
+ ```text
85
+ train/validation/test split:
86
+ number of seeds or folds:
87
+ metric definition:
88
+ confidence interval or variability definition:
89
+ baseline definition:
90
+ ```
91
+
92
+ ## Image-integrity minimum
93
+
94
+ For each image panel, capture:
95
+
96
+ ```text
97
+ raw file:
98
+ processed file:
99
+ crop:
100
+ brightness/contrast/gamma:
101
+ pseudo-color:
102
+ scale calibration:
103
+ stitching:
104
+ reuse in other figures:
105
+ quantification link:
106
+ ```
107
+
108
+ Global adjustments are generally safer than local selective edits. If an adjustment
109
+ changes the visibility of relevant background or bands, flag it instead of silently
110
+ normalizing it away.
111
+
112
+ ## Automated source preflight
113
+
114
+ Run the dependency-free validator on the final plotting source before rendering the delivery bundle:
115
+
116
+ ```bash
117
+ # Python source
118
+ python skills/nature-figure/scripts/validate_figure.py path/to/figure.py
119
+
120
+ # R, R Markdown, or Quarto source
121
+ python skills/nature-figure/scripts/validate_figure.py path/to/figure.R
122
+
123
+ # Machine-readable report or stricter warning gate
124
+ python skills/nature-figure/scripts/validate_figure.py path/to/figure.py --json
125
+ python skills/nature-figure/scripts/validate_figure.py path/to/figure.py --strict
126
+
127
+ # Exported-PDF glyph-size audit
128
+ python skills/nature-figure/scripts/audit_pdf_text.py path/to/figure.pdf --min-pt 5
129
+ python skills/nature-figure/scripts/audit_pdf_text.py path/to/figure.pdf --min-pt 5 --json
130
+
131
+ # Backend-neutral audit of the render-time Python/R panel-layout manifest
132
+ python skills/nature-figure/scripts/audit_panel_alignment.py path/to/figure.alignment-layout.json \
133
+ --json-out path/to/figure.alignment.json \
134
+ --overlay-svg path/to/figure.alignment.svg \
135
+ --strict
136
+
137
+ # Mandatory rendered collision audit for Python and R figures
138
+ python skills/nature-figure/scripts/audit_figure_collisions.py path/to/figure.pdf \
139
+ --json-out path/to/figure.collision-audit.json \
140
+ --overlay-pdf path/to/figure.collision-audit.pdf
141
+
142
+ # Optional: make ambiguous WARN findings blocking
143
+ python skills/nature-figure/scripts/audit_figure_collisions.py path/to/figure.pdf --strict
144
+ ```
145
+
146
+ The source preflight checks syntax, font configuration and size floor, mathtext shrinkage risk, literal legend-label capitalization, unsafe color maps, editable-text settings, vector/raster exports, DPI, common journal widths, potential sampling or unreported missing-data exclusion, simulated-data leakage, log guards, interpolation monotonicity, stochastic uncertainty encoding, rotated-text anchoring, risky annotation workarounds, and obvious cross-backend plotting references. The panel-alignment gate reads final axes/grob rectangles measured by the selected backend and applies one physical-point contract to Python and R. The PDF text audit scans supported content streams for actual `Tf` font-size operators and catches reduced script glyphs that source-level `fontsize` checks miss. The rendered collision audit uses PyMuPDF geometry from the final PDF and therefore applies equally to Python- and R-generated figures.
147
+
148
+ Treat the result as a deterministic source audit, not as evidence that the analysis or rendered figure is correct. Resolve all `FAIL` findings before delivery. Review every `WARN`, then run the selected backend and inspect the actual SVG/PDF/TIFF/PNG outputs at final size. A warning may be acceptable only when the QA notes state the reason.
149
+
150
+ ## Automatic multi-panel alignment gate
151
+
152
+ Run the gate for every figure with at least two comparable panels, after the
153
+ final layout engine has drawn fonts, legends, colorbars and constrained/tight
154
+ layout, and before exporting submission files. Rerun it after any change that
155
+ can affect panel geometry. A single-panel figure is `not applicable`; a
156
+ multi-panel figure with no declared or inferable comparison groups is `NOT
157
+ AUDITABLE`, not a pass.
158
+
159
+ The default tolerance is `1.5 pt` (about `0.53 mm`) at final physical size. The
160
+ auditor checks:
161
+
162
+ - panels in one row: common top and bottom edges plus equal plot-area height;
163
+ - three or four same-row panels with equal grid spans: equal final plot-area
164
+ widths within `1.5 pt`;
165
+ - panels in one column: common left and right edges plus equal plot-area width;
166
+ - unequal-span grid panels: shared outer start/stop edges, including automatic
167
+ `left two + right one` and `left one + right two` arrangements;
168
+ - three or more comparable panels: uniform repeated horizontal/vertical gutters;
169
+ - detectable bold lowercase top-left panel labels: common y anchors within rows
170
+ and common x anchors within columns;
171
+ - plot-area rectangles do not overlap.
172
+
173
+ For Matplotlib, copy `audit_panel_alignment.py` beside the plotting script or
174
+ add the skill scripts directory to `PYTHONPATH`, then call this after the last
175
+ layout change:
176
+
177
+ ```python
178
+ from audit_panel_alignment import require_matplotlib_panel_alignment
179
+
180
+ require_matplotlib_panel_alignment(
181
+ fig,
182
+ json_out="figure.alignment.json",
183
+ overlay_svg="figure.alignment.svg",
184
+ tolerance_pt=1.5,
185
+ gutter_tolerance_pt=1.5,
186
+ require_panel_labels=True,
187
+ strict=True,
188
+ )
189
+ ```
190
+
191
+ Ordinary `subplots`/`GridSpec` row and column groups are inferred from
192
+ `SubplotSpec`. A panel spanning both grid rows is automatically compared with
193
+ the upper small panel at their shared top boundary and the lower small panel at
194
+ their shared bottom boundary; this works whether the spanning panel is in the
195
+ left or right column. The spanning panel is not incorrectly required to equal
196
+ either small panel's height. Position outside panel letters with a fixed point
197
+ offset from the axes corner rather than a shared axes-fraction offset, because
198
+ `y=1.02` produces different physical displacements for tall and short panels.
199
+ For a horizontal row of three or four panels, equal column spans imply equal
200
+ final widths. Intentional unequal `width_ratios` must use a narrow exemption
201
+ such as `{"panels": ["b"], "checks": ["panel-width"], "reason": "middle hero panel"}`;
202
+ do not exempt the entire row or increase the tolerance.
203
+ Pass explicit `row_groups` and `column_groups` when axes come from nested grids
204
+ or separately created containers. Exclude a
205
+ colorbar or inset with `exclude_axes=[...]`, or add an exemption containing the
206
+ affected panel, the exact checks and a non-empty scientific/layout reason.
207
+
208
+ For R/patchwork, source `panel_alignment.R` and call
209
+ `require_patchwork_panel_alignment()` with the same width/height used for final
210
+ export. Common patchwork groups and structured unequal-span designs are inferred
211
+ from gtable cells, including two stacked panels beside a two-row spanning panel
212
+ in either column. Same-row groups of three or four equal gtable spans must also
213
+ have equal final widths. Nested or manually positioned designs must provide explicit
214
+ `row_groups` / `column_groups`. The R helper requires `patchwork`, `grid` and
215
+ `jsonlite`; it measures in R and invokes the Python CLI only to audit the
216
+ resulting JSON, so it does not redraw or replace the R figure.
217
+
218
+ | Result | Required action |
219
+ |---|---|
220
+ | `NOT APPLICABLE`, exit `0` | Single rendered plot-area only; preserve the JSON and continue |
221
+ | `PASS`, exit `0` | Preserve the alignment JSON and continue to export/PDF QA |
222
+ | `FIX BEFORE DELIVERY`, exit `1` | Correct the selected-backend layout and rerun; do not export the delivery bundle |
223
+ | `REVIEW REQUIRED` | Resolve WARN or document it; `--strict` makes WARN blocking |
224
+ | `NOT AUDITABLE`, exit `2` | Supply valid measured geometry and comparison groups; do not claim alignment passed |
225
+
226
+ The QA-only alignment SVG shows measured panel rectangles, not scientific
227
+ content. It must not replace the selected backend's figure. Do not weaken the
228
+ global tolerance to hide one exception. Structured grid spanning is audited
229
+ automatically; a free-positioned hero panel, inset, legend-only axis or colorbar
230
+ should be omitted from unrelated groups or carry a specific exemption reason.
231
+
232
+ ## Automatic rendered collision audit
233
+
234
+ Run `audit_figure_collisions.py` after **every generated figure and every
235
+ revision that can change layout**, including edits to text, fonts, legend,
236
+ annotations, axes, data, uncertainty, panel size or arrangement. Do not reuse a
237
+ report from an earlier render. Preserve the JSON report with the delivery QA;
238
+ the marked PDF is diagnostic only.
239
+
240
+ | Result | Meaning | Required action |
241
+ |---|---|---|
242
+ | `text-text` FAIL | Two rendered text boxes materially overlap | Separate, shorten, rotate or resize the labels and rerun |
243
+ | `text-stroke` FAIL | A line, curve, marker edge, error bar or other stroked path crosses the interior of text | Move the text or alter the layout; do not hide the path with an opaque white box |
244
+ | `text-page-clipping` FAIL | A rendered text trace extends beyond the final PDF page | Expand/reposition the layout and re-export |
245
+ | `text-fill-edge` WARN | Text only partly overlaps a bar, heatmap cell or other fill | Inspect at final size; fix unless the edge overlap is intentional and legible |
246
+ | `text-image-edge` WARN | Text only partly overlaps a raster image boundary | Inspect panel labels, scale bars and image annotations at final size |
247
+ | contained overlay count | Text is fully inside a fill or image | Informational because in-bar labels, heatmap values and image annotations can be intentional |
248
+
249
+ Exit code `1` and verdict `FIX BEFORE DELIVERY` block delivery. Exit code `2`
250
+ or `NOT AUDITABLE` means the PDF/dependency could not be checked and must not be
251
+ reported as a pass. `REVIEW REQUIRED` does not silently pass: inspect each WARN
252
+ and record the reason, or use `--strict` to make WARN blocking. PyMuPDF is
253
+ declared in `requirements.txt`; install it with:
254
+
255
+ ```bash
256
+ python -m pip install -r skills/nature-figure/requirements.txt
257
+ ```
258
+
259
+ The detector deliberately separates reliable geometry failures from ambiguous
260
+ fill/image overlays. It does not prove visual quality, semantic correctness,
261
+ adequate contrast or accessibility, so the final-size panel audit remains
262
+ mandatory.
263
+
264
+ ## Rendered panel-by-panel audit
265
+
266
+ Do not approve a figure from a whole-page glance. Inspect each panel at final physical size, then inspect the assembled figure. Record one row per panel:
267
+
268
+ | Panel | Unique claim | Center/summary | Spread/interval | Replicate unit | Labels/legend | Alignment group/result | Collision check | Pass |
269
+ |---|---|---|---|---|---|---|---|---|
270
+ | a | What question only this panel answers | mean/median/raw | SD/SE/CI/none + reason | seeds/folds/subjects/etc. | exact display labels | row/column group, deviation or exemption | collision report findings + data/error extent + text bbox | yes/no |
271
+
272
+ Cover each panel mentally. If the figure's argument remains complete, merge or remove that panel. Compare repeated panels side by side for consistent terminology, uncertainty, axes, and color mapping. After adding error bars or uncertainty bands, remove arrows, brackets, or fills that encode the same gap and occupy the same geometry.
273
+
274
+ ## Typography and PDF glyph floor
275
+
276
+ - The 5 pt floor applies to every rendered glyph, not only the parent `fontsize` in source code.
277
+ - Matplotlib mathtext commonly scales superscripts/subscripts to about 0.7 of the parent. A 7 pt `$R^2$` can therefore contain a 4.9 pt glyph. Prefer a Unicode glyph such as `R²` when it preserves the intended notation, or increase the parent size and confirm the PDF audit.
278
+ - Measure long labels against their allocated group width at final size. Compare rendered text bounding-box width in millimetres with the available slot; do not rely on the source font number alone.
279
+ - Keep canonical capitalization such as `XGBoost`, `DeepSeek`, `GPT-5.2`, and `RF`. Legend labels start with display-style capitalization, while prose follows normal sentence grammar. Do not use blind string title-casing.
280
+
281
+ ## Uncertainty consistency
282
+
283
+ - If a line or bar is a mean/median across random seeds, folds, splits, subjects, or repeated experiments, encode the requested spread in every comparable panel.
284
+ - State the exact definition, for example `median ± one seed SD`, in the legend or panel notes. Do not infer or invent it.
285
+ - Presence of one `fill_between`, `errorbar`, `yerr`, or `geom_errorbar` call does not prove coverage. Use the panel audit table to verify every comparable panel.
286
+ - Recompute label clearance from the upper uncertainty extent after error bars are added.
287
+
288
+ ## Geometry and annotation placement
289
+
290
+ - Measure spacing between the actual objects being compared. Use rendered/tight bounding boxes for panel-to-legend or legend-row gaps; scanning an entire raster row can mix unrelated objects at different horizontal positions.
291
+ - Use plot-area rectangles for axes alignment and tight bounding boxes for outer-content clearance; do not confuse unequal tick-label widths with a shifted data rectangle.
292
+ - Derive label positions from data and uncertainty bounds, for example `max(center + spread) + margin`, rather than a fixed `LABEL_Y`.
293
+ - For rotated Matplotlib text, use `rotation_mode="anchor"` and verify the final bounding box.
294
+ - If a curve crosses a label, reposition the label beyond the local data envelope. Avoid opaque white `bbox` masks that cut a conspicuous hole in a line.
295
+ - Equal pixel y-coordinates can still look uneven when bar heights create unequal whitespace. Diagnose the perceived gap before moving already aligned labels.
296
+
297
+ ## Color separation and salience
298
+
299
+ - Pairwise ΔE and white-background contrast are necessary checks, not a complete design test.
300
+ - Verify hierarchy after rendering: neutral baselines should not appear stronger than the proposed method or primary evidence.
301
+ - Do not repurpose a sequential light-to-dark palette as unrelated categorical colors merely because the hues look attractive.
302
+ - Check grayscale and color-vision robustness, then inspect the actual figure because metrics do not encode which series should dominate attention.
303
+
304
+ ## Transformation and paired-effect checks
305
+
306
+ - `numpy.interp` requires increasing `xp`. Use `scripts/figure_safety.py::interp_monotone`, or explicitly assert monotonicity and reverse/sort `xp` and `fp` together. Plausible-looking output is not evidence of correctness.
307
+ - Do not plan one figure per source table. Group panels by the distinct claims they support.
308
+ - When repeated units are matched, inspect paired differences. Broad between-dataset or between-subject heterogeneity can make four marginal distributions overlap even when the within-unit effect is strong; use a paired-difference view when the scientific claim is paired.
309
+
310
+ ## Export checks
311
+
312
+ Run only the export block for the selected backend. If that backend is unavailable,
313
+ stop and report the missing runtime/package instead of producing a substitute export
314
+ with the other language.
315
+
316
+ ### Python
317
+
318
+ ```python
319
+ import matplotlib as mpl
320
+ mpl.rcParams["svg.fonttype"] = "none"
321
+ mpl.rcParams["pdf.fonttype"] = 42
322
+ fig.savefig("figure.svg", bbox_inches="tight")
323
+ fig.savefig("figure.pdf", bbox_inches="tight")
324
+ fig.savefig("figure.tiff", dpi=600, bbox_inches="tight")
325
+ ```
326
+
327
+ ### R
328
+
329
+ ```r
330
+ svglite::svglite("figure.svg", width = width_mm / 25.4, height = height_mm / 25.4)
331
+ print(plot)
332
+ dev.off()
333
+
334
+ grDevices::cairo_pdf("figure.pdf", width = width_mm / 25.4, height = height_mm / 25.4, family = "Arial")
335
+ print(plot)
336
+ dev.off()
337
+
338
+ ragg::agg_tiff("figure.tiff", width = width_mm / 25.4, height = height_mm / 25.4, units = "in", res = 600)
339
+ print(plot)
340
+ dev.off()
341
+ ```
342
+
343
+ Open the SVG/PDF after export and verify that text can be selected, labels do not
344
+ overlap, and the figure still reads at final printed size.
@@ -0,0 +1,66 @@
1
+ # Private R Template Adaptation
2
+
3
+ Use this reference when the user chooses R and provides or mentions an existing
4
+ R plotting template collection. Treat such material as private working context.
5
+ Do not reveal absolute paths, folder names, filenames, screenshots, provenance, or
6
+ any identifying labels from the source collection in user-facing output.
7
+
8
+ ## Privacy rules
9
+
10
+ - Never include absolute local paths in generated code, reports, comments, or final replies.
11
+ - Never mention the original source file, folder, template number, course title, download
12
+ location, chat attachment, or private document name.
13
+ - When a template is useful, describe it generically by chart family: "a grouped bar
14
+ template", "a ComplexHeatmap workflow", "a survival plotting workflow".
15
+ - If a reusable idea is copied from a private template, rewrite the final code as a clean,
16
+ self-contained script with neutral function names and neutral comments.
17
+ - If the user asks where a style came from, say it was adapted from the provided working
18
+ materials without identifying the path or source file.
19
+
20
+ ## Generic search strategy
21
+
22
+ Search private materials by chart family and package names, not by exposing paths:
23
+
24
+ ```bash
25
+ find <private-template-root> -type f \( -name '*.R' -o -name '*.Rmd' -o -name '*.r' \)
26
+ rg -n "ggplot|patchwork|ComplexHeatmap|ggrepel|svglite|cairo_pdf|survminer|circlize" <private-template-root>
27
+ ```
28
+
29
+ Keep these commands in internal working notes only. Do not paste the user's private
30
+ root path into the final answer.
31
+
32
+ ## Chart-family map
33
+
34
+ Use these generic families to decide what to inspect:
35
+
36
+ | Need | Search targets |
37
+ |---|---|
38
+ | Bars and grouped comparisons | `geom_col`, `geom_bar`, `position_dodge`, `stat_compare_means` |
39
+ | Error bars and point-interval plots | `geom_errorbar`, `geom_pointrange`, `mean_se`, `stat_summary` |
40
+ | Stacked or bidirectional bars | `position_stack`, `coord_flip`, signed values, paired positive/negative bars |
41
+ | Box, violin, paired, and raincloud-style distributions | `geom_boxplot`, `geom_violin`, `geom_jitter`, paired sample identifiers |
42
+ | Heatmaps and annotated heatmaps | `ComplexHeatmap`, `HeatmapAnnotation`, `pheatmap`, `geom_tile` |
43
+ | Correlation, scatter, bubble, and volcano plots | `geom_point`, `geom_smooth`, `ggrepel`, `logFC`, `pvalue`, bubble size scales |
44
+ | PCA, PCoA, NMDS, tSNE, UMAP | `prcomp`, `cmdscale`, `vegan`, `Rtsne`, `Seurat`, embedding coordinates |
45
+ | Survival, Cox, subgroup, ROC, forest | `survival`, `survminer`, `coxph`, `forestplot`, `timeROC`, hazard ratios |
46
+ | Enrichment and pathway summaries | `clusterProfiler`, `GSEA`, `enrichGO`, `enrichKEGG`, dot plots, ridge plots |
47
+ | Circular, genome, phylogeny, chromosome | `circlize`, `ggtree`, `karyoploteR`, genome interval tracks |
48
+ | Single-cell and omics workflows | `Seurat`, marker genes, differential expression, cell-type annotation |
49
+ | Maps, anatomy, and spatial summaries | `sf`, `maps`, `gganatogram`, spatial coordinates |
50
+ | Radar, lollipop, dumbbell, UpSet, Venn, Sankey | `ggradar`, `geom_segment`, `UpSetR`, `ggalluvial`, set operations |
51
+
52
+ ## Adaptation checklist
53
+
54
+ When adapting a private template:
55
+
56
+ - Keep useful data wrangling, statistics, and geoms.
57
+ - Replace template-specific colors with the figure-level semantic palette.
58
+ - Normalize fonts to final-size 5-7 pt text and 8 pt bold lowercase panel labels.
59
+ - Convert single-output PNG/PDF scripts to SVG/PDF/TIFF export.
60
+ - Remove decorative elements that do not support the core conclusion.
61
+ - Ensure each statistical comparison has `n`, center, spread, test, and correction
62
+ information in the legend or source-data notes.
63
+ - For image panels, document raw file, crop, contrast, scale-bar calibration, and any
64
+ stitching or pseudo-coloring in private QA notes.
65
+ - Final code should be self-contained and should not require the original private
66
+ folder structure unless the user explicitly asks to keep that workflow.
@@ -0,0 +1,234 @@
1
+ # R Workflow
2
+
3
+ ## Contents
4
+
5
+ - [R-only execution rule](#r-only-execution-rule)
6
+ - [Required packages by task](#required-packages-by-task)
7
+ - [Contract scaffold](#contract-scaffold)
8
+ - [Panel labels in R](#panel-labels-in-r)
9
+ - [Patchwork layout patterns](#patchwork-layout-patterns)
10
+ - [Patchwork panel-alignment gate](#patchwork-panel-alignment-gate)
11
+ - [ComplexHeatmap export](#complexheatmap-export)
12
+ - [Template reuse rule](#template-reuse-rule)
13
+
14
+
15
+ Use this when the user chooses R, brings R data/scripts, or asks to reuse the local
16
+ R plotting templates. The R track should still follow the same figure contract:
17
+ claim first, evidence hierarchy second, plotting code third.
18
+
19
+ ## R-only execution rule
20
+
21
+ When the user has selected R, do all figure drawing, previewing, exporting, and
22
+ visual QA in R. Do not call Python/matplotlib/seaborn/plotly to create a temporary
23
+ preview, fallback export, or layout approximation. If R, `Rscript`, or required R
24
+ packages are missing, pause rendering, continue independent script or data checks, and report the missing dependency. You
25
+ may still write the R script, provide `install.packages()` commands, or ask permission
26
+ to install dependencies, but do not cross-render the figure in another language.
27
+
28
+ Allowed non-R utilities are limited to non-visual tasks such as shell file inspection,
29
+ CSV line counts, checksums, archive extraction, or text search. They must not create
30
+ image/vector outputs or alter visual layout.
31
+
32
+ ## Required packages by task
33
+
34
+ | Task | Preferred packages |
35
+ |---|---|
36
+ | Bars, boxplots, violins, dot plots, lines, volcano plots | `ggplot2`, `ggrepel`, `dplyr`, `tidyr` |
37
+ | Multi-panel assembly and alignment QA | `patchwork`, `grid`, `jsonlite`; use `cowplot` only when inset alignment requires it |
38
+ | Rich omics heatmaps | `ComplexHeatmap`, `circlize`, `grid` |
39
+ | Survival and clinical subgroup plots | `survival`, `survminer`, `forestplot`, `ggplot2` |
40
+ | Circular/genome plots | `circlize`, `ggtree`, `gggenes`, domain-specific packages |
41
+ | Export | `svglite`, `grDevices::cairo_pdf`, `ragg` |
42
+
43
+ ## Contract scaffold
44
+
45
+ ```r
46
+ library(ggplot2)
47
+ library(patchwork)
48
+ source("skills/nature-figure/scripts/panel_alignment.R")
49
+
50
+ palette_contract <- c(
51
+ neutral_dark = "#272727",
52
+ neutral_mid = "#767676",
53
+ neutral_light = "#D8D8D8",
54
+ signal_blue = "#3182BD",
55
+ signal_teal = "#33B5A5",
56
+ accent_red = "#D24B40",
57
+ accent_orange = "#E28E2C"
58
+ )
59
+
60
+ theme_nature_contract <- function(base_size = 6.5, base_family = "Arial") {
61
+ theme_classic(base_size = base_size, base_family = base_family) +
62
+ theme(
63
+ axis.line = element_line(linewidth = 0.35, colour = "black"),
64
+ axis.ticks = element_line(linewidth = 0.35, colour = "black"),
65
+ axis.title = element_text(size = base_size),
66
+ axis.text = element_text(size = base_size - 0.5),
67
+ legend.title = element_text(size = base_size - 0.3),
68
+ legend.text = element_text(size = base_size - 0.7),
69
+ strip.text = element_text(size = base_size - 0.3, face = "bold"),
70
+ plot.title = element_text(size = base_size + 0.5, face = "bold"),
71
+ panel.grid = element_blank()
72
+ )
73
+ }
74
+
75
+ theme_set(theme_nature_contract())
76
+
77
+ save_pub_r <- function(plot, filename, width_mm = 183, height_mm = 120, dpi = 600) {
78
+ w <- width_mm / 25.4
79
+ h <- height_mm / 25.4
80
+
81
+ if (inherits(plot, "patchwork")) {
82
+ require_patchwork_panel_alignment(
83
+ plot,
84
+ manifest_path = paste0(filename, ".alignment-layout.json"),
85
+ report_path = paste0(filename, ".alignment.json"),
86
+ overlay_svg = paste0(filename, ".alignment.svg"),
87
+ width_in = w,
88
+ height_in = h,
89
+ tolerance_pt = 1.5,
90
+ gutter_tolerance_pt = 1.5,
91
+ strict = TRUE
92
+ )
93
+ }
94
+
95
+ svglite::svglite(paste0(filename, ".svg"), width = w, height = h)
96
+ print(plot)
97
+ dev.off()
98
+
99
+ grDevices::cairo_pdf(paste0(filename, ".pdf"), width = w, height = h, family = "Arial")
100
+ print(plot)
101
+ dev.off()
102
+
103
+ ragg::agg_tiff(paste0(filename, ".tiff"), width = w, height = h, units = "in", res = dpi)
104
+ print(plot)
105
+ dev.off()
106
+ }
107
+ ```
108
+
109
+ ## Panel labels in R
110
+
111
+ Use patchwork tags for most multi-panel figures:
112
+
113
+ ```r
114
+ fig <- (p_a | p_b) / (p_c | p_d) +
115
+ plot_annotation(tag_levels = "a") &
116
+ theme(plot.tag = element_text(size = 8, face = "bold"))
117
+ ```
118
+
119
+ Use manual labels only when dark image plates or inset geometry make patchwork tags
120
+ misalign.
121
+
122
+ ## Patchwork layout patterns
123
+
124
+ ### Quantitative grid
125
+
126
+ ```r
127
+ fig <- (p_a | p_b | guide_area()) /
128
+ (p_c | p_d | p_e) +
129
+ plot_layout(guides = "collect", widths = c(1, 1, 0.45)) &
130
+ theme(legend.position = "right")
131
+ ```
132
+
133
+ ### Schematic-led composite
134
+
135
+ ```r
136
+ design <- "
137
+ AAAA
138
+ BBCD
139
+ "
140
+ fig <- p_schematic + p_b + p_c + p_d +
141
+ plot_layout(design = design, heights = c(1.8, 1))
142
+ ```
143
+
144
+ ### Image plate plus quant
145
+
146
+ Keep black backgrounds inside image panels only. Put scale bars on the image, then
147
+ place quantification next to or below the representative image.
148
+
149
+ ```r
150
+ p_img <- ggplot(img_df, aes(x, y, fill = intensity)) +
151
+ geom_raster() +
152
+ scale_fill_gradient(low = "black", high = "white") +
153
+ coord_fixed(expand = FALSE) +
154
+ annotate("segment", x = 10, xend = 40, y = 10, yend = 10,
155
+ linewidth = 0.6, colour = "white") +
156
+ theme_void() +
157
+ theme(legend.position = "none", plot.background = element_rect(fill = "black", colour = NA))
158
+ ```
159
+
160
+ ## Patchwork panel-alignment gate
161
+
162
+ `panel_alignment.R` converts the final patchwork gtable cells to physical-point
163
+ rectangles on a temporary R graphics device with the same dimensions as the
164
+ real export. It then invokes the backend-neutral
165
+ `audit_panel_alignment.py` JSON auditor. Python does not render or modify the R
166
+ figure.
167
+
168
+ Simple patchwork grids infer row/column groups from gtable cells. Structured
169
+ unequal-span designs are also automatic: two stacked panels in the left column
170
+ beside one two-row panel in the right column, and the mirrored arrangement,
171
+ receive shared top/bottom boundary checks without an invalid equal-height
172
+ comparison. Horizontal groups of three or four equal gtable spans must also
173
+ have equal final widths; intentional unequal widths require a reasoned
174
+ `panel-width` exemption. For nested or manually composed figures, declare the intended
175
+ comparisons explicitly:
176
+
177
+ ```r
178
+ require_patchwork_panel_alignment(
179
+ fig,
180
+ manifest_path = "figures/fig2.alignment-layout.json",
181
+ report_path = "figures/fig2.alignment.json",
182
+ overlay_svg = "figures/fig2.alignment.svg",
183
+ width_in = 183 / 25.4,
184
+ height_in = 120 / 25.4,
185
+ panel_ids = c("a", "b", "c", "d"),
186
+ row_groups = list(c("a", "b"), c("c", "d")),
187
+ column_groups = list(c("a", "c"), c("b", "d")),
188
+ exemptions = list(
189
+ list(
190
+ panels = c("a"),
191
+ checks = c("column", "panel-width"),
192
+ reason = "hero panel intentionally spans the evidence columns"
193
+ )
194
+ ),
195
+ tolerance_pt = 1.5,
196
+ gutter_tolerance_pt = 1.5,
197
+ strict = TRUE
198
+ )
199
+ ```
200
+
201
+ Every exemption must name the panel, the exact check and the reason. Do not
202
+ increase the global tolerance to hide an inset, colorbar, legend-only cell or
203
+ hero panel. A non-zero audit status stops the R delivery script. Preserve both
204
+ the measured layout manifest and audit JSON; the alignment SVG is QA-only.
205
+
206
+ ## ComplexHeatmap export
207
+
208
+ `ComplexHeatmap` objects are grid objects, not ggplot objects. Export them by opening
209
+ the graphics device, drawing, then closing it.
210
+
211
+ ```r
212
+ library(ComplexHeatmap)
213
+ library(circlize)
214
+
215
+ pdf("heatmap.pdf", width = 7.2, height = 4.8, family = "Arial")
216
+ draw(ht, heatmap_legend_side = "right", annotation_legend_side = "right")
217
+ dev.off()
218
+
219
+ svglite::svglite("heatmap.svg", width = 7.2, height = 4.8)
220
+ draw(ht, heatmap_legend_side = "right", annotation_legend_side = "right")
221
+ dev.off()
222
+ ```
223
+
224
+ ## Template reuse rule
225
+
226
+ The local R materials are examples, not final style. When reusing them:
227
+
228
+ 1. Inspect only the nearest template folder.
229
+ 2. Keep useful data wrangling, statistics, and geoms.
230
+ 3. Replace ad hoc colors, oversized fonts, dense legends, and PNG-only export.
231
+ 4. Rebuild the final script around `theme_nature_contract()` and `save_pub_r()`.
232
+ 5. Add source-data output if the figure is manuscript-facing.
233
+
234
+ Open `references/r-template-index.md` for the local template atlas.