psyclaw 0.24.0 → 0.25.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +46 -53
- package/{dist/apps → apps}/panel/index.html +28 -50
- package/package.json +10 -20
- package/scripts/__pycache__/build_dist.cpython-314.pyc +0 -0
- package/scripts/__pycache__/build_whitepaper_docx.cpython-314.pyc +0 -0
- package/scripts/build_preprint_docx.py +729 -0
- package/scripts/build_preprint_figures.py +238 -0
- package/scripts/build_three_line_table_fixture.py +56 -0
- package/scripts/build_whitepaper_docx.py +768 -0
- package/scripts/check-branding.mjs +159 -0
- package/scripts/copy-panel.mjs +11 -0
- package/scripts/rebrand-pi.mjs +292 -0
- package/scripts/verify_docx.py +41 -0
- package/skills/core/citation-audit/SKILL.md +9 -9
- package/skills/core/evidence-capture/SKILL.md +9 -9
- package/skills/core/manifest.json +15 -15
- package/skills/core/research-brief/SKILL.md +8 -8
- package/skills/core/research-intake/SKILL.md +9 -9
- package/dist/src/adapters/pi/extension.d.ts +0 -19
- package/dist/src/adapters/pi/extension.js +0 -735
- package/dist/src/adapters/pi/extension.js.map +0 -1
- package/dist/src/adapters/pi/model.d.ts +0 -72
- package/dist/src/adapters/pi/model.js +0 -152
- package/dist/src/adapters/pi/model.js.map +0 -1
- package/dist/src/adapters/pi/resources.d.ts +0 -23
- package/dist/src/adapters/pi/resources.js +0 -54
- package/dist/src/adapters/pi/resources.js.map +0 -1
- package/dist/src/adapters/pi/rpc.d.ts +0 -56
- package/dist/src/adapters/pi/rpc.js +0 -248
- package/dist/src/adapters/pi/rpc.js.map +0 -1
- package/dist/src/adapters/pi/session.d.ts +0 -30
- package/dist/src/adapters/pi/session.js +0 -64
- package/dist/src/adapters/pi/session.js.map +0 -1
- package/dist/src/agents/catalog.d.ts +0 -30
- package/dist/src/agents/catalog.js +0 -118
- package/dist/src/agents/catalog.js.map +0 -1
- package/dist/src/agents/discover.d.ts +0 -28
- package/dist/src/agents/discover.js +0 -127
- package/dist/src/agents/discover.js.map +0 -1
- package/dist/src/agents/import.d.ts +0 -67
- package/dist/src/agents/import.js +0 -801
- package/dist/src/agents/import.js.map +0 -1
- package/dist/src/analysis/hooks.d.ts +0 -81
- package/dist/src/analysis/hooks.js +0 -139
- package/dist/src/analysis/hooks.js.map +0 -1
- package/dist/src/analysis/pre-registration.d.ts +0 -18
- package/dist/src/analysis/pre-registration.js +0 -86
- package/dist/src/analysis/pre-registration.js.map +0 -1
- package/dist/src/branding.d.ts +0 -43
- package/dist/src/branding.js +0 -127
- package/dist/src/branding.js.map +0 -1
- package/dist/src/chat.d.ts +0 -16
- package/dist/src/chat.js +0 -67
- package/dist/src/chat.js.map +0 -1
- package/dist/src/cli.d.ts +0 -2
- package/dist/src/cli.js +0 -316
- package/dist/src/cli.js.map +0 -1
- package/dist/src/core/citations.d.ts +0 -44
- package/dist/src/core/citations.js +0 -48
- package/dist/src/core/citations.js.map +0 -1
- package/dist/src/core/contracts.d.ts +0 -119
- package/dist/src/core/contracts.js +0 -2
- package/dist/src/core/contracts.js.map +0 -1
- package/dist/src/core/docx.d.ts +0 -11
- package/dist/src/core/docx.js +0 -46
- package/dist/src/core/docx.js.map +0 -1
- package/dist/src/core/doi.d.ts +0 -41
- package/dist/src/core/doi.js +0 -82
- package/dist/src/core/doi.js.map +0 -1
- package/dist/src/core/evidence-policy.d.ts +0 -24
- package/dist/src/core/evidence-policy.js +0 -308
- package/dist/src/core/evidence-policy.js.map +0 -1
- package/dist/src/core/filekind.d.ts +0 -15
- package/dist/src/core/filekind.js +0 -82
- package/dist/src/core/filekind.js.map +0 -1
- package/dist/src/core/hash.d.ts +0 -2
- package/dist/src/core/hash.js +0 -17
- package/dist/src/core/hash.js.map +0 -1
- package/dist/src/core/pricing.d.ts +0 -38
- package/dist/src/core/pricing.js +0 -110
- package/dist/src/core/pricing.js.map +0 -1
- package/dist/src/core/redact.d.ts +0 -12
- package/dist/src/core/redact.js +0 -48
- package/dist/src/core/redact.js.map +0 -1
- package/dist/src/core/references.d.ts +0 -55
- package/dist/src/core/references.js +0 -102
- package/dist/src/core/references.js.map +0 -1
- package/dist/src/core/schemas.d.ts +0 -162
- package/dist/src/core/schemas.js +0 -160
- package/dist/src/core/schemas.js.map +0 -1
- package/dist/src/extension.d.ts +0 -1
- package/dist/src/extension.js +0 -2
- package/dist/src/extension.js.map +0 -1
- package/dist/src/index.d.ts +0 -72
- package/dist/src/index.js +0 -73
- package/dist/src/index.js.map +0 -1
- package/dist/src/install/installer.d.ts +0 -147
- package/dist/src/install/installer.js +0 -743
- package/dist/src/install/installer.js.map +0 -1
- package/dist/src/integrations/contracts.d.ts +0 -35
- package/dist/src/integrations/contracts.js +0 -27
- package/dist/src/integrations/contracts.js.map +0 -1
- package/dist/src/integrations/mcp.d.ts +0 -155
- package/dist/src/integrations/mcp.js +0 -826
- package/dist/src/integrations/mcp.js.map +0 -1
- package/dist/src/knowledge-map/contracts.d.ts +0 -20
- package/dist/src/knowledge-map/contracts.js +0 -2
- package/dist/src/knowledge-map/contracts.js.map +0 -1
- package/dist/src/knowledge-map/index.d.ts +0 -4
- package/dist/src/knowledge-map/index.js +0 -39
- package/dist/src/knowledge-map/index.js.map +0 -1
- package/dist/src/literature/contracts.d.ts +0 -106
- package/dist/src/literature/contracts.js +0 -2
- package/dist/src/literature/contracts.js.map +0 -1
- package/dist/src/literature/fulltext.d.ts +0 -7
- package/dist/src/literature/fulltext.js +0 -24
- package/dist/src/literature/fulltext.js.map +0 -1
- package/dist/src/literature/knowledge-map.d.ts +0 -2
- package/dist/src/literature/knowledge-map.js +0 -20
- package/dist/src/literature/knowledge-map.js.map +0 -1
- package/dist/src/literature/ledger.d.ts +0 -3
- package/dist/src/literature/ledger.js +0 -17
- package/dist/src/literature/ledger.js.map +0 -1
- package/dist/src/literature/metadata.d.ts +0 -6
- package/dist/src/literature/metadata.js +0 -32
- package/dist/src/literature/metadata.js.map +0 -1
- package/dist/src/memory/store.d.ts +0 -22
- package/dist/src/memory/store.js +0 -73
- package/dist/src/memory/store.js.map +0 -1
- package/dist/src/orchestration/contracts.d.ts +0 -61
- package/dist/src/orchestration/contracts.js +0 -2
- package/dist/src/orchestration/contracts.js.map +0 -1
- package/dist/src/orchestration/pi-executor.d.ts +0 -28
- package/dist/src/orchestration/pi-executor.js +0 -169
- package/dist/src/orchestration/pi-executor.js.map +0 -1
- package/dist/src/orchestration/runner.d.ts +0 -196
- package/dist/src/orchestration/runner.js +0 -991
- package/dist/src/orchestration/runner.js.map +0 -1
- package/dist/src/orchestration/scheduler.d.ts +0 -8
- package/dist/src/orchestration/scheduler.js +0 -335
- package/dist/src/orchestration/scheduler.js.map +0 -1
- package/dist/src/panel/events.d.ts +0 -20
- package/dist/src/panel/events.js +0 -93
- package/dist/src/panel/events.js.map +0 -1
- package/dist/src/panel/extension.d.ts +0 -8
- package/dist/src/panel/extension.js +0 -114
- package/dist/src/panel/extension.js.map +0 -1
- package/dist/src/panel/literature-map.d.ts +0 -26
- package/dist/src/panel/literature-map.js +0 -34
- package/dist/src/panel/literature-map.js.map +0 -1
- package/dist/src/panel/projection.d.ts +0 -51
- package/dist/src/panel/projection.js +0 -288
- package/dist/src/panel/projection.js.map +0 -1
- package/dist/src/panel/server.d.ts +0 -46
- package/dist/src/panel/server.js +0 -1610
- package/dist/src/panel/server.js.map +0 -1
- package/dist/src/panel/usage.d.ts +0 -53
- package/dist/src/panel/usage.js +0 -150
- package/dist/src/panel/usage.js.map +0 -1
- package/dist/src/project/bootstrap.d.ts +0 -10
- package/dist/src/project/bootstrap.js +0 -83
- package/dist/src/project/bootstrap.js.map +0 -1
- package/dist/src/project/hitl.d.ts +0 -12
- package/dist/src/project/hitl.js +0 -43
- package/dist/src/project/hitl.js.map +0 -1
- package/dist/src/project/jsonl.d.ts +0 -16
- package/dist/src/project/jsonl.js +0 -93
- package/dist/src/project/jsonl.js.map +0 -1
- package/dist/src/project/manuscript.d.ts +0 -21
- package/dist/src/project/manuscript.js +0 -74
- package/dist/src/project/manuscript.js.map +0 -1
- package/dist/src/project/paths.d.ts +0 -38
- package/dist/src/project/paths.js +0 -166
- package/dist/src/project/paths.js.map +0 -1
- package/dist/src/project/versions.d.ts +0 -10
- package/dist/src/project/versions.js +0 -14
- package/dist/src/project/versions.js.map +0 -1
- package/dist/src/psyclaw-theme.d.ts +0 -88
- package/dist/src/psyclaw-theme.js +0 -89
- package/dist/src/psyclaw-theme.js.map +0 -1
- package/dist/src/research/brief.d.ts +0 -11
- package/dist/src/research/brief.js +0 -81
- package/dist/src/research/brief.js.map +0 -1
- package/dist/src/research/ledger.d.ts +0 -12
- package/dist/src/research/ledger.js +0 -43
- package/dist/src/research/ledger.js.map +0 -1
- package/dist/src/run.d.ts +0 -20
- package/dist/src/run.js +0 -34
- package/dist/src/run.js.map +0 -1
- package/dist/src/setup.d.ts +0 -54
- package/dist/src/setup.js +0 -221
- package/dist/src/setup.js.map +0 -1
- package/dist/src/skills/contracts.d.ts +0 -105
- package/dist/src/skills/contracts.js +0 -3
- package/dist/src/skills/contracts.js.map +0 -1
- package/dist/src/skills/preflight.d.ts +0 -10
- package/dist/src/skills/preflight.js +0 -39
- package/dist/src/skills/preflight.js.map +0 -1
- package/dist/src/skills/registry.d.ts +0 -28
- package/dist/src/skills/registry.js +0 -556
- package/dist/src/skills/registry.js.map +0 -1
- package/dist/src/style/artifact.d.ts +0 -6
- package/dist/src/style/artifact.js +0 -61
- package/dist/src/style/artifact.js.map +0 -1
- package/dist/src/style/cli-ui.d.ts +0 -41
- package/dist/src/style/cli-ui.js +0 -119
- package/dist/src/style/cli-ui.js.map +0 -1
- package/dist/src/style/contracts.d.ts +0 -34
- package/dist/src/style/contracts.js +0 -2
- package/dist/src/style/contracts.js.map +0 -1
- package/dist/src/style/registry.d.ts +0 -16
- package/dist/src/style/registry.js +0 -50
- package/dist/src/style/registry.js.map +0 -1
- package/dist/src/trust/manifest.d.ts +0 -42
- package/dist/src/trust/manifest.js +0 -53
- package/dist/src/trust/manifest.js.map +0 -1
- package/dist/src/trust/sbom.d.ts +0 -54
- package/dist/src/trust/sbom.js +0 -77
- package/dist/src/trust/sbom.js.map +0 -1
- package/dist/src/tui/app.d.ts +0 -3
- package/dist/src/tui/app.js +0 -103
- package/dist/src/tui/app.js.map +0 -1
- package/dist/src/tui/model.d.ts +0 -13
- package/dist/src/tui/model.js +0 -25
- package/dist/src/tui/model.js.map +0 -1
- package/dist/src/updates/check.d.ts +0 -43
- package/dist/src/updates/check.js +0 -68
- package/dist/src/updates/check.js.map +0 -1
- package/dist/src/updates/manifest.d.ts +0 -19
- package/dist/src/updates/manifest.js +0 -58
- package/dist/src/updates/manifest.js.map +0 -1
- package/dist/src/updates/registry.d.ts +0 -21
- package/dist/src/updates/registry.js +0 -82
- package/dist/src/updates/registry.js.map +0 -1
- package/dist/src/updates/skills.d.ts +0 -15
- package/dist/src/updates/skills.js +0 -39
- package/dist/src/updates/skills.js.map +0 -1
- package/dist/src/updates/status.d.ts +0 -7
- package/dist/src/updates/status.js +0 -37
- package/dist/src/updates/status.js.map +0 -1
- package/dist/src/updates/update.d.ts +0 -43
- package/dist/src/updates/update.js +0 -126
- package/dist/src/updates/update.js.map +0 -1
- package/dist/src/wizard.d.ts +0 -7
- package/dist/src/wizard.js +0 -90
- package/dist/src/wizard.js.map +0 -1
- package/dist/src/workflows/analysis-delegation.d.ts +0 -3
- package/dist/src/workflows/analysis-delegation.js +0 -96
- package/dist/src/workflows/analysis-delegation.js.map +0 -1
- package/dist/src/workflows/expert-review-runner.d.ts +0 -29
- package/dist/src/workflows/expert-review-runner.js +0 -35
- package/dist/src/workflows/expert-review-runner.js.map +0 -1
- package/dist/src/workflows/expert-review.d.ts +0 -140
- package/dist/src/workflows/expert-review.js +0 -111
- package/dist/src/workflows/expert-review.js.map +0 -1
- package/dist/src/workflows/institutional-fulltext.d.ts +0 -16
- package/dist/src/workflows/institutional-fulltext.js +0 -110
- package/dist/src/workflows/institutional-fulltext.js.map +0 -1
- package/dist/src/workflows/literature-review.d.ts +0 -3
- package/dist/src/workflows/literature-review.js +0 -76
- package/dist/src/workflows/literature-review.js.map +0 -1
- package/dist/src/workflows/meta-analysis.d.ts +0 -38
- package/dist/src/workflows/meta-analysis.js +0 -185
- package/dist/src/workflows/meta-analysis.js.map +0 -1
- package/dist/src/workflows/publish.d.ts +0 -51
- package/dist/src/workflows/publish.js +0 -153
- package/dist/src/workflows/publish.js.map +0 -1
- package/dist/src/workflows/spec.d.ts +0 -51
- package/dist/src/workflows/spec.js +0 -157
- package/dist/src/workflows/spec.js.map +0 -1
- package/dist/src/workflows/style-contract.d.ts +0 -24
- package/dist/src/workflows/style-contract.js +0 -23
- package/dist/src/workflows/style-contract.js.map +0 -1
- package/dist/src/workflows/writing-review.d.ts +0 -15
- package/dist/src/workflows/writing-review.js +0 -82
- package/dist/src/workflows/writing-review.js.map +0 -1
- package/package.json.psyclaw +0 -21
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""生成 PsyClaw 预印本的示意图(图1 架构与数据流;图2 三理念协同)。
|
|
4
|
+
输出 300 dpi PNG 至 figures/。中文用 macOS 自带 Hiragino/Arial Unicode。
|
|
5
|
+
重跑:UV_DEFAULT_INDEX=https://mirrors.aliyun.com/pypi/simple/ \
|
|
6
|
+
uv run --python 3.12 --with matplotlib python scripts/build_preprint_figures.py
|
|
7
|
+
"""
|
|
8
|
+
import os
|
|
9
|
+
import matplotlib
|
|
10
|
+
matplotlib.use("Agg")
|
|
11
|
+
import matplotlib.pyplot as plt
|
|
12
|
+
from matplotlib.patches import FancyBboxPatch, FancyArrowPatch
|
|
13
|
+
from matplotlib.font_manager import FontProperties
|
|
14
|
+
|
|
15
|
+
# ---- 中文字体 ----
|
|
16
|
+
_CANDIDATES = [
|
|
17
|
+
"/System/Library/Fonts/Hiragino Sans GB.ttc",
|
|
18
|
+
"/System/Library/Fonts/Supplemental/Arial Unicode.ttf",
|
|
19
|
+
"/System/Library/Fonts/STHeiti Medium.ttc",
|
|
20
|
+
]
|
|
21
|
+
_FP = next((FontProperties(fname=p) for p in _CANDIDATES if os.path.exists(p)), FontProperties())
|
|
22
|
+
def F(size, weight="normal"):
|
|
23
|
+
fp = _FP.copy(); fp.set_size(size); fp.set_weight(weight); return fp
|
|
24
|
+
|
|
25
|
+
# ---- 品牌配色 ----
|
|
26
|
+
TEAL = "#0F8B8D" # 主青
|
|
27
|
+
TEAL_D = "#0A5F61" # 深青
|
|
28
|
+
TEAL_L = "#D8ECEC" # 浅青底
|
|
29
|
+
INK = "#22303A" # 墨
|
|
30
|
+
GREY = "#5B6B75" # 次要文字
|
|
31
|
+
PAPER = "#FBFCFC" # 底
|
|
32
|
+
BAND = "#F0F4F5" # 层带底
|
|
33
|
+
GOLD = "#C7853B" # 强调(核查/阻断)
|
|
34
|
+
GOLD_L = "#F6EBDA"
|
|
35
|
+
|
|
36
|
+
OUT = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "figures")
|
|
37
|
+
os.makedirs(OUT, exist_ok=True)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _box(ax, x, y, w, h, fc, ec, lw=1.4, r=0.035, z=2):
|
|
41
|
+
p = FancyBboxPatch((x, y), w, h, boxstyle=f"round,pad=0.0,rounding_size={r}",
|
|
42
|
+
linewidth=lw, edgecolor=ec, facecolor=fc, zorder=z)
|
|
43
|
+
ax.add_patch(p)
|
|
44
|
+
return p
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _txt(ax, x, y, s, fp, color=INK, ha="center", va="center", z=5):
|
|
48
|
+
ax.text(x, y, s, fontproperties=fp, color=color, ha=ha, va=va, zorder=z)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _arrow(ax, xy1, xy2, color=TEAL_D, lw=1.6, style="-|>", ms=11, ls="-", rad=0.0, z=4):
|
|
52
|
+
a = FancyArrowPatch(xy1, xy2, arrowstyle=style, mutation_scale=ms, lw=lw,
|
|
53
|
+
color=color, linestyle=ls, zorder=z,
|
|
54
|
+
connectionstyle=f"arc3,rad={rad}", shrinkA=2, shrinkB=2)
|
|
55
|
+
ax.add_patch(a)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
# =========================================================================
|
|
59
|
+
# 图 1:四层 + 两横切架构与数据流
|
|
60
|
+
# =========================================================================
|
|
61
|
+
def figure1():
|
|
62
|
+
fig, ax = plt.subplots(figsize=(11.2, 7.6))
|
|
63
|
+
ax.set_xlim(0, 100); ax.set_ylim(0, 100); ax.axis("off")
|
|
64
|
+
fig.patch.set_facecolor(PAPER); ax.set_facecolor(PAPER)
|
|
65
|
+
|
|
66
|
+
_txt(ax, 50, 96.5, "图 1 PsyClaw 四层加两横切架构与数据流", F(15, "bold"), INK)
|
|
67
|
+
|
|
68
|
+
# 用户 / CLI 入口
|
|
69
|
+
_box(ax, 6, 87.5, 66, 6.6, "#FFFFFF", INK, 1.4)
|
|
70
|
+
_txt(ax, 10, 90.8, "研究者", F(11, "bold"), INK, ha="left")
|
|
71
|
+
_txt(ax, 39, 90.8, "自然语言 · chat / run / auto", F(10.5), GREY)
|
|
72
|
+
|
|
73
|
+
# 横切两条:Harness(左)Memory(右)—— 贯穿四层背景
|
|
74
|
+
band_top, band_bot = 84.0, 12.0
|
|
75
|
+
_box(ax, 4.0, band_bot, 6.4, band_top - band_bot, GOLD_L, GOLD, 1.3, r=0.02, z=1)
|
|
76
|
+
ax.text(7.2, (band_top+band_bot)/2, "Harness 横切\n每步前置检查(失败即阻断)\n机器可读总验收",
|
|
77
|
+
fontproperties=F(9.2, "bold"), color=GOLD, ha="center", va="center",
|
|
78
|
+
rotation=90, zorder=3)
|
|
79
|
+
_box(ax, 89.6, band_bot, 6.4, band_top - band_bot, TEAL_L, TEAL_D, 1.3, r=0.02, z=1)
|
|
80
|
+
ax.text(92.8, (band_top+band_bot)/2, "Memory 横切\n三层记忆\n方法学·期刊·教训",
|
|
81
|
+
fontproperties=F(9.2, "bold"), color=TEAL_D, ha="center", va="center",
|
|
82
|
+
rotation=90, zorder=3)
|
|
83
|
+
|
|
84
|
+
# 四层主栈(在两横切之间)
|
|
85
|
+
lx, lw = 11.6, 76.8
|
|
86
|
+
layers = [
|
|
87
|
+
("L0 路由 Router", "三入口共享路由定义 modes.py:chat(对话)· run(声明式流程)· auto(自主)",
|
|
88
|
+
77.0, 6.4, TEAL, "#FFFFFF"),
|
|
89
|
+
("L1 流程 Workflow", "每类研究 = 一份纯数据(步骤 + 前置检查);引擎逐步跑 + HITL + 断点恢复 + 总验收",
|
|
90
|
+
67.6, 6.4, TEAL_L, INK),
|
|
91
|
+
("L2 子功能 Step", "每步薄封装:可单用(多为 CLI 命令)· 可拆(纯函数)· 可拼(进任意流程)",
|
|
92
|
+
58.2, 6.4, TEAL_L, INK),
|
|
93
|
+
("L3 实现 Skill + MCP", "既有命令 / 技能 / MCP 后端;统计计算整体落此层",
|
|
94
|
+
48.8, 6.4, TEAL_L, INK),
|
|
95
|
+
]
|
|
96
|
+
for title, sub, y, h, fc, tc in layers:
|
|
97
|
+
_box(ax, lx, y, lw, h, fc, TEAL_D, 1.5)
|
|
98
|
+
_txt(ax, lx + 2.5, y + h*0.66, title, F(11.5, "bold"), tc, ha="left")
|
|
99
|
+
_txt(ax, lx + 2.5, y + h*0.26, sub, F(8.8), tc if tc != "#FFFFFF" else "#EAF6F6", ha="left")
|
|
100
|
+
|
|
101
|
+
# 竖向数据流箭头(逐层)与回流(上行)
|
|
102
|
+
cx = lx + lw*0.30
|
|
103
|
+
for y0, y1 in [(77.0, 74.0), (67.6, 64.6), (58.2, 55.2)]:
|
|
104
|
+
_arrow(ax, (cx, y0), (cx, y1), TEAL_D, 1.8, ms=12)
|
|
105
|
+
ux = lx + lw*0.70
|
|
106
|
+
for y0, y1 in [(55.2, 58.2), (64.6, 67.6), (74.0, 77.0)]:
|
|
107
|
+
_arrow(ax, (ux, y0), (ux, y1), GREY, 1.3, ms=10, ls=(0, (4, 2)))
|
|
108
|
+
_txt(ax, cx - 1.2, 71.0, "逐层委托", F(8.2), TEAL_D, ha="right")
|
|
109
|
+
_txt(ax, ux + 1.2, 71.0, "结果 / 证据回流", F(8.2), GREY, ha="left")
|
|
110
|
+
|
|
111
|
+
# L3 之下:外部实现(统计外移)——标题独占一行,库框在下
|
|
112
|
+
_box(ax, lx, 39.6, lw, 7.6, "#FFFFFF", INK, 1.4)
|
|
113
|
+
_txt(ax, lx + lw/2, 46.1, "统计外移 —— 本仓不实现任何统计算法", F(10.5, "bold"), GOLD)
|
|
114
|
+
ext = [("pingouin", 13.5), ("statsmodels", 27.5), ("SciPy", 41.5),
|
|
115
|
+
("MNE-MCP", 54.5), ("SPSS/Stata/Mplus\n(MCP)", 70.5)]
|
|
116
|
+
for name, x in ext:
|
|
117
|
+
_box(ax, x, 40.4, 12.4, 4.1, TEAL_L, TEAL_D, 1.2, r=0.05)
|
|
118
|
+
_txt(ax, x + 6.2, 42.45, name, F(8.6, "bold"), TEAL_D)
|
|
119
|
+
for x in [19.7, 33.7, 47.7, 60.7, 76.7]:
|
|
120
|
+
_arrow(ax, (x, 48.6), (x, 47.5), TEAL_D, 1.2, ms=9, ls=(0, (3, 2)))
|
|
121
|
+
|
|
122
|
+
# 四类声明式流程(L1 展开示例)
|
|
123
|
+
_box(ax, lx, 27.5, lw, 9.5, BAND, GREY, 1.2, r=0.02, z=1)
|
|
124
|
+
_txt(ax, lx + lw/2, 34.7, "L1 的四类声明式研究流程", F(10, "bold"), INK)
|
|
125
|
+
flows = [
|
|
126
|
+
("文献综述", "clarify → 检索(PRISMA) →\n筛选 → 合成 → 评审"),
|
|
127
|
+
("元分析", "校验效应量 → 委托\nstatsmodels 随机效应"),
|
|
128
|
+
("实证分析", "数据画像 → 推荐 →\n委托 pingouin/SciPy"),
|
|
129
|
+
("质性分析", "转录本 → LLM 辅助\n编码/主题(HITL)"),
|
|
130
|
+
]
|
|
131
|
+
fw = 17.6
|
|
132
|
+
for i, (nm, desc) in enumerate(flows):
|
|
133
|
+
x = lx + 2.6 + i * (fw + 1.4)
|
|
134
|
+
_box(ax, x, 28.4, fw, 4.9, "#FFFFFF", TEAL_D, 1.2, r=0.05)
|
|
135
|
+
_txt(ax, x + fw/2, 32.4, nm, F(9.3, "bold"), TEAL_D)
|
|
136
|
+
_txt(ax, x + fw/2, 30.2, desc, F(7.6), GREY)
|
|
137
|
+
|
|
138
|
+
# 产物
|
|
139
|
+
_box(ax, lx, 13.5, lw, 6.2, GOLD_L, GOLD, 1.4)
|
|
140
|
+
_txt(ax, lx + lw/2, 16.6, "可复现产物", F(10.5, "bold"), GOLD)
|
|
141
|
+
_txt(ax, lx + lw/2, 14.5,
|
|
142
|
+
"等效脚本 + 数据指纹 · 机器可读总验收 workflow_summary.json · 按序号归档",
|
|
143
|
+
F(8.8), INK)
|
|
144
|
+
|
|
145
|
+
# 全局竖向主脉:入口→L0→…→产物
|
|
146
|
+
_arrow(ax, (lx + lw*0.5, 87.5), (lx + lw*0.5, 83.5), INK, 1.6, ms=11)
|
|
147
|
+
_arrow(ax, (lx + lw*0.5, 48.8), (lx + lw*0.5, 47.3), INK, 1.4, ms=10)
|
|
148
|
+
_arrow(ax, (lx + lw*0.5, 39.6), (lx + lw*0.5, 37.1), INK, 1.4, ms=10)
|
|
149
|
+
_arrow(ax, (lx + lw*0.5, 27.5), (lx + lw*0.5, 19.8), INK, 1.4, ms=10)
|
|
150
|
+
|
|
151
|
+
# gate 标记(Harness 对每层的约束)示意:右向三角,指向各层
|
|
152
|
+
for y in [80.2, 70.8, 61.4, 52.0]:
|
|
153
|
+
ax.plot(10.9, y, marker=">", markersize=9, color=GOLD,
|
|
154
|
+
markeredgecolor=GOLD, zorder=6)
|
|
155
|
+
|
|
156
|
+
fig.subplots_adjust(left=0.01, right=0.99, top=0.99, bottom=0.01)
|
|
157
|
+
path = os.path.join(OUT, "psyclaw_fig1_architecture.png")
|
|
158
|
+
fig.savefig(path, dpi=300, facecolor=PAPER)
|
|
159
|
+
plt.close(fig)
|
|
160
|
+
return path
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
# =========================================================================
|
|
164
|
+
# 图 2:三理念协同(声明式流程 · 失败即阻断的核查 · 统计外移)
|
|
165
|
+
# =========================================================================
|
|
166
|
+
def figure2():
|
|
167
|
+
fig, ax = plt.subplots(figsize=(11.2, 6.6))
|
|
168
|
+
ax.set_xlim(0, 100); ax.set_ylim(0, 100); ax.axis("off")
|
|
169
|
+
fig.patch.set_facecolor(PAPER); ax.set_facecolor(PAPER)
|
|
170
|
+
|
|
171
|
+
_txt(ax, 50, 95.5, "图 2 三项核心设计理念在一个流程步骤上的协同", F(15, "bold"), INK)
|
|
172
|
+
|
|
173
|
+
# 中央:一个「流程步骤」
|
|
174
|
+
_box(ax, 38, 44, 24, 14, TEAL, TEAL_D, 1.8, r=0.06)
|
|
175
|
+
_txt(ax, 50, 53.3, "一个流程步骤", F(12.5, "bold"), "#FFFFFF")
|
|
176
|
+
_txt(ax, 50, 49.6, "Step", F(9.5), "#EAF6F6")
|
|
177
|
+
_txt(ax, 50, 46.4, "(如「分析」「合成」)", F(8.6), "#DCEFEF")
|
|
178
|
+
|
|
179
|
+
# 理念一:声明式流程(上)——步骤的来源
|
|
180
|
+
_box(ax, 30, 78, 40, 12.5, TEAL_L, TEAL_D, 1.5, r=0.05)
|
|
181
|
+
_txt(ax, 50, 86.4, "① 声明式研究流程", F(12, "bold"), TEAL_D)
|
|
182
|
+
_txt(ax, 50, 82.7, "流程 = 纯数据(步骤 + 前置检查);引擎逐步执行,", F(8.9), INK)
|
|
183
|
+
_txt(ax, 50, 80.2, "可重放、可改装、末尾出机器可读总验收", F(8.9), INK)
|
|
184
|
+
_arrow(ax, (50, 78), (50, 58.3), TEAL_D, 2.0, ms=13)
|
|
185
|
+
_txt(ax, 51.5, 68, "定义并驱动", F(8.6), TEAL_D, ha="left")
|
|
186
|
+
|
|
187
|
+
# 理念二:失败即阻断的核查(左)——步骤执行前的关卡
|
|
188
|
+
_box(ax, 3.5, 40, 26, 22, GOLD_L, GOLD, 1.6, r=0.05)
|
|
189
|
+
_txt(ax, 16.5, 58.0, "② 学术诚信核查", F(12, "bold"), GOLD)
|
|
190
|
+
for i, s in enumerate([
|
|
191
|
+
"效应量 + CI 必报",
|
|
192
|
+
"区分探索 / 确证",
|
|
193
|
+
"确证须预注册",
|
|
194
|
+
"相关 ≠ 因果",
|
|
195
|
+
"图件完整性",
|
|
196
|
+
"PRISMA · APA7 · 复现脚本",
|
|
197
|
+
]):
|
|
198
|
+
_txt(ax, 6.0, 53.6 - i*2.55, "•", F(9.5, "bold"), GOLD, ha="left")
|
|
199
|
+
_txt(ax, 8.2, 53.6 - i*2.55, s, F(8.7), INK, ha="left")
|
|
200
|
+
# 核查把关箭头(阻断/放行)
|
|
201
|
+
_arrow(ax, (29.5, 51), (38, 51), GOLD, 2.0, ms=13)
|
|
202
|
+
_txt(ax, 33.5, 53.2, "PASS→放行", F(8.0), TEAL_D)
|
|
203
|
+
_arrow(ax, (35, 47.5), (31, 43), GOLD, 1.8, ms=12, style="-|>", rad=0.3)
|
|
204
|
+
_txt(ax, 36.0, 41.0, "FAIL→阻断 + 修复", F(8.0), GOLD, ha="center")
|
|
205
|
+
|
|
206
|
+
# 理念三:统计外移(右)——步骤把计算委托出去
|
|
207
|
+
_box(ax, 70.5, 40, 26, 22, TEAL_L, TEAL_D, 1.6, r=0.05)
|
|
208
|
+
_txt(ax, 83.5, 58.0, "③ 统计外移", F(12, "bold"), TEAL_D)
|
|
209
|
+
_txt(ax, 83.5, 54.6, "本仓不实现任何统计算法", F(8.9, "bold"), GOLD)
|
|
210
|
+
_txt(ax, 83.5, 51.8, "委托成熟库 / MCP 后端:", F(8.6), INK)
|
|
211
|
+
for i, s in enumerate(["pingouin · statsmodels · SciPy",
|
|
212
|
+
"MNE-MCP · SPSS / Stata / Mplus"]):
|
|
213
|
+
_txt(ax, 83.5, 48.6 - i*2.6, s, F(8.4), TEAL_D)
|
|
214
|
+
_txt(ax, 83.5, 42.7, "数值正确性归外部库承担", F(8.2), GREY)
|
|
215
|
+
_arrow(ax, (62, 51), (70.5, 51), TEAL_D, 2.0, ms=13)
|
|
216
|
+
_txt(ax, 66.2, 53.2, "委托计算", F(8.0), TEAL_D)
|
|
217
|
+
_arrow(ax, (70.5, 47.5), (62, 45), GREY, 1.4, ms=10, ls=(0, (4, 2)), rad=-0.25)
|
|
218
|
+
_txt(ax, 66.2, 43.4, "结果回流", F(7.8), GREY)
|
|
219
|
+
|
|
220
|
+
# 底部:三者合力 → 产物
|
|
221
|
+
_box(ax, 22, 12, 56, 12, "#FFFFFF", INK, 1.5, r=0.04)
|
|
222
|
+
_txt(ax, 50, 20.6, "合力产出", F(11.5, "bold"), INK)
|
|
223
|
+
_txt(ax, 50, 17.3, "工作流可复现(等效脚本 + 指纹 + 归档)", F(9.0), TEAL_D)
|
|
224
|
+
_txt(ax, 50, 14.4, "× 内容合规(核查把关) × 数值可信(外部库)", F(9.0), GOLD)
|
|
225
|
+
_arrow(ax, (50, 44), (50, 24.2), INK, 1.8, ms=12)
|
|
226
|
+
|
|
227
|
+
fig.subplots_adjust(left=0.01, right=0.99, top=0.99, bottom=0.01)
|
|
228
|
+
path = os.path.join(OUT, "psyclaw_fig2_principles.png")
|
|
229
|
+
fig.savefig(path, dpi=300, facecolor=PAPER)
|
|
230
|
+
plt.close(fig)
|
|
231
|
+
return path
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
if __name__ == "__main__":
|
|
235
|
+
p1 = figure1()
|
|
236
|
+
p2 = figure2()
|
|
237
|
+
print("wrote:", p1)
|
|
238
|
+
print("wrote:", p2)
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Build a small DOCX fixture that exercises APA three-line tables."""
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
from psyclaw.output.apa7 import APA7Document
|
|
9
|
+
from psyclaw.output.docx_contract import assert_docx_contract
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def main() -> int:
|
|
13
|
+
parser = argparse.ArgumentParser()
|
|
14
|
+
parser.add_argument("output", nargs="?", default="outputs/three-line-table-test.docx")
|
|
15
|
+
args = parser.parse_args()
|
|
16
|
+
|
|
17
|
+
output = Path(args.output)
|
|
18
|
+
output.parent.mkdir(parents=True, exist_ok=True)
|
|
19
|
+
|
|
20
|
+
doc = APA7Document(
|
|
21
|
+
title="APA 三线表生成测试",
|
|
22
|
+
authors="PsyClaw DOCX regression fixture",
|
|
23
|
+
affiliation="Local verification",
|
|
24
|
+
)
|
|
25
|
+
doc.add_heading("结果", 1)
|
|
26
|
+
doc.add_paragraph("以下表格用于检查边框、固定列宽、中文换行与跨页稳定性。")
|
|
27
|
+
doc.add_stat_table(
|
|
28
|
+
"Table 1\n描述性统计",
|
|
29
|
+
["变量", "n", "M", "SD", "95% CI"],
|
|
30
|
+
[
|
|
31
|
+
["抑郁症状", "128", "14.20", "3.40", "[13.60, 14.80]"],
|
|
32
|
+
["焦虑症状", "128", "11.10", "2.90", "[10.59, 11.61]"],
|
|
33
|
+
["生活满意度(较长的中文变量名称,用于测试自动换行)", "128", "24.80", "5.10", "[23.90, 25.70]"],
|
|
34
|
+
],
|
|
35
|
+
)
|
|
36
|
+
doc.add_stat_table(
|
|
37
|
+
"Table 2\n相关矩阵",
|
|
38
|
+
["变量", "1", "2", "3"],
|
|
39
|
+
[
|
|
40
|
+
["1. 抑郁", "—", "", ""],
|
|
41
|
+
["2. 焦虑", ".45", "—", ""],
|
|
42
|
+
["3. 满意度", "-.31", "-.27", "—"],
|
|
43
|
+
],
|
|
44
|
+
)
|
|
45
|
+
doc.add_stat_table("Table 3\n仅表头边界情况", ["变量", "结果"], [])
|
|
46
|
+
|
|
47
|
+
doc.to_docx(output)
|
|
48
|
+
result = assert_docx_contract(output)
|
|
49
|
+
print(f"generated={output.resolve()}")
|
|
50
|
+
print(f"sha256={result['sha256']}")
|
|
51
|
+
print(f"tables={result['tables']}")
|
|
52
|
+
return 0
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
if __name__ == "__main__":
|
|
56
|
+
raise SystemExit(main())
|