@iiwish/agentrecord 0.0.1
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/LICENSE +21 -0
- package/README.md +109 -0
- package/examples/basic/README.md +23 -0
- package/examples/basic/agentrecord.config.example.json +36 -0
- package/locales/en-US.json +45 -0
- package/locales/zh-CN.json +45 -0
- package/package.json +36 -0
- package/references/evidence-rules.json +112 -0
- package/references/evidence-rules.zh-CN.json +112 -0
- package/schemas/evidence.schema.json +30 -0
- package/schemas/profile.schema.json +34 -0
- package/scripts/smoke-install.mjs +76 -0
- package/src/build/artifacts.mjs +29 -0
- package/src/build/catalog.mjs +33 -0
- package/src/build/codex-account.mjs +183 -0
- package/src/build/evidence.mjs +143 -0
- package/src/build/paths.mjs +6 -0
- package/src/build/profile.mjs +608 -0
- package/src/build/renderers.mjs +1267 -0
- package/src/build/report.mjs +64 -0
- package/src/build/run-context.mjs +97 -0
- package/src/build/stats.mjs +176 -0
- package/src/build/utils.mjs +50 -0
- package/src/cli.mjs +78 -0
- package/src/commands/build.mjs +75 -0
- package/src/commands/doctor.mjs +20 -0
- package/src/commands/init.mjs +62 -0
- package/src/commands/open.mjs +81 -0
- package/src/commands/scan.mjs +58 -0
- package/src/commands/validate.mjs +365 -0
- package/src/core/args.mjs +60 -0
- package/src/core/config.mjs +228 -0
|
@@ -0,0 +1,1267 @@
|
|
|
1
|
+
import { formatEvidenceMix } from "./profile.mjs";
|
|
2
|
+
import { esc, formatCompactNumber, formatNumber } from "./utils.mjs";
|
|
3
|
+
|
|
4
|
+
export function renderMarkdown(profile, localeBundle) {
|
|
5
|
+
const t = (key) => localeBundle.ui?.[key] || key;
|
|
6
|
+
const codex = profile.agent_ledger.clients.find((client) => client.client_id === "codex") || {};
|
|
7
|
+
const displayUsage = codex.display_usage || {};
|
|
8
|
+
const displayTokens = displayUsage.token_usage?.total_tokens || codex.token_usage?.total_tokens || 0;
|
|
9
|
+
return `# ${profile.owner.display_name} ${t("title")}
|
|
10
|
+
|
|
11
|
+
${t("subtitle")}
|
|
12
|
+
|
|
13
|
+
- ${t("generated")}: ${profile.generated_at}
|
|
14
|
+
- ${t("trace_window")}: ${codex.trace_window?.start || "unknown"} to ${codex.trace_window?.end || "unknown"}
|
|
15
|
+
- ${t("sessions")}: ${formatNumber(codex.sessions || 0, profile.report.locale)}
|
|
16
|
+
- ${t("token_activity")}: ${formatNumber(displayTokens, profile.report.locale)} (${displayUsage.source_label || "local"})
|
|
17
|
+
- ${t("evidence")}: ${formatNumber(profile.evidence_notes.length, profile.report.locale)}
|
|
18
|
+
|
|
19
|
+
## ${t("identity")}
|
|
20
|
+
|
|
21
|
+
${profile.work_identity.summary}
|
|
22
|
+
|
|
23
|
+
Strongest evidence-backed claim: ${profile.work_identity.strongest_claim}
|
|
24
|
+
|
|
25
|
+
Confidence: ${profile.work_identity.confidence}
|
|
26
|
+
|
|
27
|
+
Evidence IDs: ${profile.work_identity.evidence_ids.join(", ") || "none"}
|
|
28
|
+
|
|
29
|
+
## ${t("role_signals")}
|
|
30
|
+
|
|
31
|
+
${profile.work_role_signals.map((role) => `- ${role.label}: ${role.band}, ${role.confidence}. ${role.why} Evidence: ${role.evidence_ids.join(", ") || "none"}`).join("\n")}
|
|
32
|
+
|
|
33
|
+
## ${t("ability_model")}
|
|
34
|
+
|
|
35
|
+
${profile.ability_model.map((ability) => `- ${ability.label}: ${ability.band}, ${ability.confidence}. Evidence mix: ${formatEvidenceMix(ability.evidence_level_mix)}. Evidence: ${ability.evidence_ids.join(", ") || "none"}`).join("\n")}
|
|
36
|
+
|
|
37
|
+
## ${t("agent_ledger")}
|
|
38
|
+
|
|
39
|
+
${profile.agent_ledger.clients.map((client) => `- ${client.client_id}: ${client.status}${Number.isFinite(client.sessions) ? `, ${formatNumber(client.sessions, profile.report.locale)} sessions` : ""}`).join("\n")}
|
|
40
|
+
|
|
41
|
+
Token usage and session counts are activity-density context, not direct proof of ability.
|
|
42
|
+
|
|
43
|
+
## ${t("evidence")}
|
|
44
|
+
|
|
45
|
+
${profile.evidence_notes.map((card) => `### ${card.evidence_id}: ${card.title}
|
|
46
|
+
|
|
47
|
+
- Level: ${card.level.join(", ")}
|
|
48
|
+
- Confidence: ${card.confidence}
|
|
49
|
+
- Summary: ${card.summary}
|
|
50
|
+
- Refs: ${card.refs.map(formatPublicRef).join("; ")}
|
|
51
|
+
`).join("\n")}
|
|
52
|
+
|
|
53
|
+
## ${t("calibration")}
|
|
54
|
+
|
|
55
|
+
${profile.calibration_notes.map((note) => `- ${note.severity}: ${note.summary}`).join("\n")}
|
|
56
|
+
|
|
57
|
+
## ${t("privacy_boundary")}
|
|
58
|
+
|
|
59
|
+
${t("public_safe")}
|
|
60
|
+
|
|
61
|
+
${t("not_hiring")}
|
|
62
|
+
`;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function renderHtml(profile, localeBundle) {
|
|
66
|
+
const t = (key) => localeBundle.ui?.[key] || key;
|
|
67
|
+
const isZh = profile.report.locale === "zh-CN";
|
|
68
|
+
const codex = profile.agent_ledger.clients.find((client) => client.client_id === "codex") || {};
|
|
69
|
+
const clients = profile.agent_ledger.clients || [];
|
|
70
|
+
const measuredClients = clients.filter((client) => client.status === "measured").map((client) => client.client_id);
|
|
71
|
+
|
|
72
|
+
const archetype = profile.archetype || {
|
|
73
|
+
code: "SRVC",
|
|
74
|
+
name: "AI 架构审查官",
|
|
75
|
+
enName: "THE CHIEF JUSTICE",
|
|
76
|
+
tagline: "“代码可以不跑,但测试必须全绿。”",
|
|
77
|
+
talent: "像素级代码审计,把 AI 治得服服帖帖",
|
|
78
|
+
quote: "“把证据拿出来,没跑过测试别跟我谈交付。”",
|
|
79
|
+
weakness: "宁可在本地写 3 小时规范提示词,也不愿意自己动手改一行 JS。",
|
|
80
|
+
status: "每天都在跟 AI 进行严密的法庭辩论,直至其乖乖跑通所有校验。",
|
|
81
|
+
rigor: 92,
|
|
82
|
+
control: 76,
|
|
83
|
+
strategic: 85,
|
|
84
|
+
closedLoop: 88,
|
|
85
|
+
tags: ["#代码质检委", "#无情测试监工", "#提示词洁癖"],
|
|
86
|
+
traceDays: 42,
|
|
87
|
+
activeStatus: "85% 默契协从"
|
|
88
|
+
};
|
|
89
|
+
const cardTheme = archetype.card_theme || {
|
|
90
|
+
id: "audit",
|
|
91
|
+
label: "审查型",
|
|
92
|
+
accent: "#0b695e",
|
|
93
|
+
accentSoft: "#e4f4f2",
|
|
94
|
+
field: "#e1ebd2",
|
|
95
|
+
page: "#f0f3ef",
|
|
96
|
+
gold: "#c28d2e",
|
|
97
|
+
stripGradient: "linear-gradient(180deg, #153f39 0%, #0b695e 35%, #d09a2f 70%, #121816 100%)",
|
|
98
|
+
chipGradient: "linear-gradient(135deg, #f4cc50 0%, #b88308 100%)",
|
|
99
|
+
bannerPattern: "repeating-linear-gradient(45deg, rgba(255,255,255,0.05) 0 8px, transparent 8px 16px)"
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const formatChineseCompact = (value) => {
|
|
103
|
+
if (value >= 1e8) return `${(value / 1e8).toFixed(1)} 亿字`;
|
|
104
|
+
if (value >= 1e4) return `${(value / 1e4).toFixed(0)} 万字`;
|
|
105
|
+
return `${value} 字`;
|
|
106
|
+
};
|
|
107
|
+
const formatDuration = (seconds) => {
|
|
108
|
+
const totalSeconds = Math.max(0, Number(seconds) || 0);
|
|
109
|
+
if (!totalSeconds) return null;
|
|
110
|
+
const hours = Math.floor(totalSeconds / 3600);
|
|
111
|
+
const minutes = Math.floor((totalSeconds % 3600) / 60);
|
|
112
|
+
if (isZh) return hours > 0 ? `${hours} 小时 ${minutes} 分` : `${minutes} 分`;
|
|
113
|
+
return hours > 0 ? `${hours}h ${minutes}m` : `${minutes}m`;
|
|
114
|
+
};
|
|
115
|
+
const displayUsage = codex.display_usage || {};
|
|
116
|
+
const displayTokenUsage = displayUsage.token_usage || {};
|
|
117
|
+
const displayTokens = displayTokenUsage.total_tokens || codex.token_usage?.total_tokens || 0;
|
|
118
|
+
const hasAccountUsage = displayUsage.source === "codex_account_usage";
|
|
119
|
+
const longestTask = formatDuration(displayTokenUsage.longest_running_turn_sec);
|
|
120
|
+
const currentStreakDays = displayTokenUsage.current_streak_days;
|
|
121
|
+
const longestStreakDays = displayTokenUsage.longest_streak_days;
|
|
122
|
+
|
|
123
|
+
const copy = isZh ? {
|
|
124
|
+
productMark: "AGENTRECORD / 智能体协同数字身份证",
|
|
125
|
+
proofStamp: "本地加密生成",
|
|
126
|
+
identityLabel: "AI 协作身份",
|
|
127
|
+
strongestClaim: "最强事实存证结论",
|
|
128
|
+
traceWindow: "Trace 活跃区间",
|
|
129
|
+
agentClients: "Agent 客户端",
|
|
130
|
+
evidenceCount: "证据卡片数",
|
|
131
|
+
confidence: "画像置信度",
|
|
132
|
+
privacy: "数据隐私边界",
|
|
133
|
+
sections: {
|
|
134
|
+
roles: "工作角色倾向",
|
|
135
|
+
abilities: "核心能力维度",
|
|
136
|
+
ledger: "智能体活动台账",
|
|
137
|
+
evidence: "脱敏存证卷宗",
|
|
138
|
+
calibration: "偏差校准说明",
|
|
139
|
+
redaction: "数据安全隔离边界"
|
|
140
|
+
},
|
|
141
|
+
roleIntro: "角色信号由真实行为证据链推导,表示在 AI 协作中的技术倾斜与团队定位。",
|
|
142
|
+
abilityIntro: "能力模型呈现多维度的调度习惯。雷达排序分数仅用于组内加权,不构成外部评价。",
|
|
143
|
+
ledgerIntro: "智能体台账客观记录会话规模与活跃度,属于行为密度,不直接等同于技术水平。",
|
|
144
|
+
evidenceIntro: "案卷仅保留可审计的轻量脱敏存证(Case File),绝不泄漏任何核心业务逻辑与隐私数据。",
|
|
145
|
+
redactionIntro: "公开报告可放心用于简历展示或社交分享,原始 Trace 和私有会话数据将永远锁在本地。",
|
|
146
|
+
measured: "已接入测量",
|
|
147
|
+
pending: "未配置适配器",
|
|
148
|
+
sessions: "会话",
|
|
149
|
+
localThreads: "本地线程",
|
|
150
|
+
accountTokens: "账号 Token",
|
|
151
|
+
accountOverview: "账号总览",
|
|
152
|
+
localAudited: "本地可审计",
|
|
153
|
+
longestTask: "最长任务",
|
|
154
|
+
streakDays: "连续天数",
|
|
155
|
+
tokenActivity: "Token 活跃度",
|
|
156
|
+
refs: "事实证据索引",
|
|
157
|
+
evidenceIds: "证据 ID",
|
|
158
|
+
missing: "拼图缺口",
|
|
159
|
+
excluded: "数据脱敏:已被物理擦除的敏感内容",
|
|
160
|
+
artifacts: "存证输出:生成的公开静态制品",
|
|
161
|
+
generated: "生成日期",
|
|
162
|
+
noEvidence: "暂无直接证据支持",
|
|
163
|
+
noMissing: "完美覆盖,暂无明确能力短板"
|
|
164
|
+
} : {
|
|
165
|
+
productMark: "AGENTRECORD / AI WORKER BADGE",
|
|
166
|
+
proofStamp: "LOCAL PROOF STAMP",
|
|
167
|
+
identityLabel: "AI Work Identity",
|
|
168
|
+
strongestClaim: "Strongest Claim",
|
|
169
|
+
traceWindow: "Trace Active Window",
|
|
170
|
+
agentClients: "Agent Clients",
|
|
171
|
+
evidenceCount: "Evidence Cards",
|
|
172
|
+
confidence: "Profile Confidence",
|
|
173
|
+
privacy: "Privacy Boundary",
|
|
174
|
+
sections: {
|
|
175
|
+
roles: "Role Signals",
|
|
176
|
+
abilities: "Ability Dimensions",
|
|
177
|
+
ledger: "Agent Activity Ledger",
|
|
178
|
+
evidence: "Evidence Case Files",
|
|
179
|
+
calibration: "Calibration Notes",
|
|
180
|
+
redaction: "Redaction Boundaries"
|
|
181
|
+
},
|
|
182
|
+
roleIntro: "Role signals indicate your work tendencies derived from evidence, not standard seniority.",
|
|
183
|
+
abilityIntro: "Ability dimensions showcase operational precision. Internal scores are for relative ranking, not absolute scale.",
|
|
184
|
+
ledgerIntro: "Sessions and token activity show interaction density, not a direct proxy for competency.",
|
|
185
|
+
evidenceIntro: "Each case file retains only safe, non-identifying trace references and abstract audit summaries.",
|
|
186
|
+
redactionIntro: "Public artifacts are built for local review or static sharing. Raw conversation histories never leave your machine.",
|
|
187
|
+
measured: "measured",
|
|
188
|
+
pending: "not configured",
|
|
189
|
+
sessions: "sessions",
|
|
190
|
+
localThreads: "local threads",
|
|
191
|
+
accountTokens: "account tokens",
|
|
192
|
+
accountOverview: "account overview",
|
|
193
|
+
localAudited: "local audit",
|
|
194
|
+
longestTask: "longest task",
|
|
195
|
+
streakDays: "streak days",
|
|
196
|
+
tokenActivity: "token activity",
|
|
197
|
+
refs: "Audit Refs",
|
|
198
|
+
evidenceIds: "Evidence IDs",
|
|
199
|
+
missing: "Gaps",
|
|
200
|
+
excluded: "Redacted: Excluded from public artifacts",
|
|
201
|
+
artifacts: "Artifacts: Generated public-safe files",
|
|
202
|
+
generated: "Generated",
|
|
203
|
+
noEvidence: "No direct evidence yet",
|
|
204
|
+
noMissing: "Pristine coverage, no explicit gap"
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
const clientSummary = measuredClients.length
|
|
208
|
+
? measuredClients.map((client) => `${client}: ${copy.measured}`).join(" / ")
|
|
209
|
+
: clients.map((client) => `${client.client_id}: ${client.status}`).join(" / ") || "none";
|
|
210
|
+
const traceWindow = `${codex.trace_window?.start || "unknown"} -> ${codex.trace_window?.end || "unknown"}`;
|
|
211
|
+
const heroEvidenceIds = profile.work_identity.evidence_ids?.slice(0, 4) || [];
|
|
212
|
+
const streakSource = hasAccountUsage && Number.isFinite(longestStreakDays)
|
|
213
|
+
? `<em class="stats-source">${isZh ? `最长 ${longestStreakDays} 天` : `longest ${longestStreakDays}d`}</em>`
|
|
214
|
+
: "";
|
|
215
|
+
|
|
216
|
+
return `<!doctype html>
|
|
217
|
+
<html lang="${esc(localeBundle.html_lang || profile.report.locale)}">
|
|
218
|
+
<head>
|
|
219
|
+
<meta charset="utf-8">
|
|
220
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
221
|
+
<title>${esc(profile.owner.display_name)} @ AgentRecord</title>
|
|
222
|
+
<style>
|
|
223
|
+
:root {
|
|
224
|
+
color-scheme: light;
|
|
225
|
+
--page: ${esc(cardTheme.page)};
|
|
226
|
+
--sheet: #ffffff;
|
|
227
|
+
--ink: #0a0f0d;
|
|
228
|
+
--muted: #4d5d56;
|
|
229
|
+
--line: #0a0f0d;
|
|
230
|
+
--steel: #1b2621;
|
|
231
|
+
--field: ${esc(cardTheme.field)};
|
|
232
|
+
--accent: ${esc(cardTheme.accent)};
|
|
233
|
+
--accent-soft: ${esc(cardTheme.accentSoft)};
|
|
234
|
+
--stamp: #b82d22;
|
|
235
|
+
--gold: ${esc(cardTheme.gold)};
|
|
236
|
+
--case: #fafcf9;
|
|
237
|
+
--strip-gradient: ${cardTheme.stripGradient};
|
|
238
|
+
--chip-gradient: ${cardTheme.chipGradient};
|
|
239
|
+
--banner-pattern: ${cardTheme.bannerPattern};
|
|
240
|
+
font-family: ui-sans-serif, system-ui, -apple-system, sans-serif;
|
|
241
|
+
}
|
|
242
|
+
* { box-sizing: border-box; }
|
|
243
|
+
html { background: var(--page); }
|
|
244
|
+
body {
|
|
245
|
+
margin: 0;
|
|
246
|
+
background-color: var(--page);
|
|
247
|
+
background-image:
|
|
248
|
+
linear-gradient(rgba(10, 15, 13, 0.035) 1px, transparent 1px),
|
|
249
|
+
linear-gradient(90deg, rgba(10, 15, 13, 0.035) 1px, transparent 1px);
|
|
250
|
+
background-size: 20px 20px;
|
|
251
|
+
color: var(--ink);
|
|
252
|
+
padding: 0 16px;
|
|
253
|
+
}
|
|
254
|
+
main { width: min(1200px, 100%); margin: 0 auto; padding: 40px 0 80px; }
|
|
255
|
+
|
|
256
|
+
/* SINGLE PANEL WRAPPER FOR SHARABLE CARD */
|
|
257
|
+
.share-container {
|
|
258
|
+
display: flex;
|
|
259
|
+
justify-content: center;
|
|
260
|
+
align-items: center;
|
|
261
|
+
margin-bottom: 32px;
|
|
262
|
+
padding: 10px 0;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/* THE CARD (AI WORKER BADGE) */
|
|
266
|
+
.badge-card {
|
|
267
|
+
max-width: 540px;
|
|
268
|
+
width: 100%;
|
|
269
|
+
border: 3.5px solid var(--line);
|
|
270
|
+
border-radius: 16px;
|
|
271
|
+
box-shadow: 10px 10px 0 var(--line);
|
|
272
|
+
background: var(--sheet);
|
|
273
|
+
overflow: hidden;
|
|
274
|
+
position: relative;
|
|
275
|
+
display: flex;
|
|
276
|
+
flex-direction: column;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/* Holographic Edge Strip */
|
|
280
|
+
.holo-strip {
|
|
281
|
+
position: absolute;
|
|
282
|
+
left: 0; top: 0; bottom: 0;
|
|
283
|
+
width: 14px;
|
|
284
|
+
background: var(--strip-gradient);
|
|
285
|
+
opacity: 0.85;
|
|
286
|
+
border-right: 2px solid var(--line);
|
|
287
|
+
z-index: 10;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
.badge-body {
|
|
291
|
+
padding: 30px 28px 24px 44px; /* extra left padding for holo-strip */
|
|
292
|
+
position: relative;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/* Golden chip */
|
|
296
|
+
.chip-container {
|
|
297
|
+
display: flex;
|
|
298
|
+
justify-content: space-between;
|
|
299
|
+
align-items: start;
|
|
300
|
+
margin-bottom: 24px;
|
|
301
|
+
}
|
|
302
|
+
.card-chip {
|
|
303
|
+
width: 44px;
|
|
304
|
+
height: 32px;
|
|
305
|
+
background: var(--chip-gradient);
|
|
306
|
+
border: 2px solid var(--line);
|
|
307
|
+
border-radius: 6px;
|
|
308
|
+
position: relative;
|
|
309
|
+
box-shadow: inset 1px 1px 1px rgba(255,255,255,0.45), 2.5px 2.5px 0 rgba(0,0,0,0.15);
|
|
310
|
+
}
|
|
311
|
+
.card-chip::after {
|
|
312
|
+
content: "";
|
|
313
|
+
position: absolute;
|
|
314
|
+
top: 0; left: 0; right: 0; bottom: 0;
|
|
315
|
+
background: repeating-linear-gradient(90deg, transparent, transparent 5px, rgba(11,16,13,0.12) 5px, rgba(11,16,13,0.12) 6px);
|
|
316
|
+
border-radius: 4px;
|
|
317
|
+
}
|
|
318
|
+
.card-header-meta {
|
|
319
|
+
text-align: right;
|
|
320
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
321
|
+
font-size: 11px;
|
|
322
|
+
font-weight: 800;
|
|
323
|
+
letter-spacing: 1px;
|
|
324
|
+
color: var(--muted);
|
|
325
|
+
text-transform: uppercase;
|
|
326
|
+
line-height: 1.3;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/* Badge Holder Name & Tags */
|
|
330
|
+
.holder-name {
|
|
331
|
+
font-size: 34px;
|
|
332
|
+
font-weight: 900;
|
|
333
|
+
margin: 0 0 8px 0;
|
|
334
|
+
letter-spacing: -1.5px;
|
|
335
|
+
color: var(--ink);
|
|
336
|
+
line-height: 1.0;
|
|
337
|
+
}
|
|
338
|
+
.holder-tags {
|
|
339
|
+
display: flex;
|
|
340
|
+
flex-wrap: wrap;
|
|
341
|
+
gap: 6px;
|
|
342
|
+
margin-bottom: 24px;
|
|
343
|
+
}
|
|
344
|
+
.holder-tag {
|
|
345
|
+
background: var(--field);
|
|
346
|
+
border: 1.5px solid var(--line);
|
|
347
|
+
border-radius: 6px;
|
|
348
|
+
padding: 3px 8px;
|
|
349
|
+
font-size: 12px;
|
|
350
|
+
font-weight: 800;
|
|
351
|
+
color: var(--steel);
|
|
352
|
+
box-shadow: 1px 1px 0 var(--line);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/* Character Archetype Banner */
|
|
356
|
+
.archetype-banner {
|
|
357
|
+
background: var(--accent);
|
|
358
|
+
color: #ffffff;
|
|
359
|
+
border: 2.5px solid var(--line);
|
|
360
|
+
border-radius: 8px;
|
|
361
|
+
padding: 16px;
|
|
362
|
+
margin-bottom: 20px;
|
|
363
|
+
box-shadow: 3.5px 3.5px 0 var(--line);
|
|
364
|
+
position: relative;
|
|
365
|
+
overflow: hidden;
|
|
366
|
+
}
|
|
367
|
+
.archetype-banner::after {
|
|
368
|
+
content: "";
|
|
369
|
+
position: absolute;
|
|
370
|
+
top: 0; left: 0; right: 0; bottom: 0;
|
|
371
|
+
background: var(--banner-pattern);
|
|
372
|
+
background-size: 16px 16px;
|
|
373
|
+
pointer-events: none;
|
|
374
|
+
}
|
|
375
|
+
.archetype-label {
|
|
376
|
+
font-size: 10px;
|
|
377
|
+
font-weight: 900;
|
|
378
|
+
letter-spacing: 2px;
|
|
379
|
+
text-transform: uppercase;
|
|
380
|
+
opacity: 0.85;
|
|
381
|
+
margin-bottom: 4px;
|
|
382
|
+
}
|
|
383
|
+
.archetype-title {
|
|
384
|
+
font-size: 24px;
|
|
385
|
+
font-weight: 950;
|
|
386
|
+
margin: 0;
|
|
387
|
+
line-height: 1.2;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/* Quote style */
|
|
391
|
+
.badge-quote {
|
|
392
|
+
font-style: italic;
|
|
393
|
+
color: var(--steel);
|
|
394
|
+
border-left: 3.5px solid var(--accent);
|
|
395
|
+
padding-left: 14px;
|
|
396
|
+
font-size: 14.5px;
|
|
397
|
+
line-height: 1.5;
|
|
398
|
+
margin-bottom: 14px;
|
|
399
|
+
font-weight: 700;
|
|
400
|
+
}
|
|
401
|
+
.signature-line {
|
|
402
|
+
border: 1.5px solid var(--line);
|
|
403
|
+
border-radius: 8px;
|
|
404
|
+
background: var(--accent-soft);
|
|
405
|
+
color: var(--steel);
|
|
406
|
+
padding: 8px 11px;
|
|
407
|
+
margin-bottom: 24px;
|
|
408
|
+
box-shadow: 2px 2px 0 var(--line);
|
|
409
|
+
display: grid;
|
|
410
|
+
grid-template-columns: 74px minmax(0, 1fr);
|
|
411
|
+
gap: 10px;
|
|
412
|
+
align-items: center;
|
|
413
|
+
}
|
|
414
|
+
.signature-line span {
|
|
415
|
+
font-size: 9px;
|
|
416
|
+
font-weight: 900;
|
|
417
|
+
letter-spacing: 1.4px;
|
|
418
|
+
text-transform: uppercase;
|
|
419
|
+
color: var(--accent);
|
|
420
|
+
white-space: nowrap;
|
|
421
|
+
}
|
|
422
|
+
.signature-line b {
|
|
423
|
+
font-size: 12px;
|
|
424
|
+
line-height: 1.35;
|
|
425
|
+
overflow-wrap: anywhere;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
/* RPG Attributes Panel */
|
|
429
|
+
.rpg-section-title {
|
|
430
|
+
font-size: 11px;
|
|
431
|
+
font-weight: 900;
|
|
432
|
+
letter-spacing: 2px;
|
|
433
|
+
color: var(--muted);
|
|
434
|
+
text-transform: uppercase;
|
|
435
|
+
margin-bottom: 12px;
|
|
436
|
+
border-bottom: 1.5px dashed rgba(10, 15, 13, 0.15);
|
|
437
|
+
padding-bottom: 4px;
|
|
438
|
+
}
|
|
439
|
+
.rpg-panel {
|
|
440
|
+
display: grid;
|
|
441
|
+
gap: 12px;
|
|
442
|
+
margin-bottom: 28px;
|
|
443
|
+
}
|
|
444
|
+
.rpg-row {
|
|
445
|
+
display: grid;
|
|
446
|
+
grid-template-columns: 85px 1fr 45px;
|
|
447
|
+
gap: 14px;
|
|
448
|
+
align-items: center;
|
|
449
|
+
}
|
|
450
|
+
.rpg-label {
|
|
451
|
+
font-size: 13.5px;
|
|
452
|
+
font-weight: 900;
|
|
453
|
+
color: var(--ink);
|
|
454
|
+
}
|
|
455
|
+
.rpg-track {
|
|
456
|
+
height: 12px;
|
|
457
|
+
border: 2px solid var(--line);
|
|
458
|
+
background: var(--page);
|
|
459
|
+
border-radius: 4px;
|
|
460
|
+
overflow: hidden;
|
|
461
|
+
position: relative;
|
|
462
|
+
}
|
|
463
|
+
.rpg-fill {
|
|
464
|
+
height: 100%;
|
|
465
|
+
background: repeating-linear-gradient(-45deg, var(--gold), var(--gold) 4px, #a37c22 4px, #a37c22 8px);
|
|
466
|
+
border-right: 1.5px solid var(--line);
|
|
467
|
+
}
|
|
468
|
+
.rpg-value {
|
|
469
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
470
|
+
font-size: 13px;
|
|
471
|
+
font-weight: 900;
|
|
472
|
+
text-align: right;
|
|
473
|
+
color: var(--ink);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/* Battle Stats Grid */
|
|
477
|
+
.stats-grid {
|
|
478
|
+
display: grid;
|
|
479
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
480
|
+
gap: 10px;
|
|
481
|
+
margin-bottom: 28px;
|
|
482
|
+
}
|
|
483
|
+
.stats-item {
|
|
484
|
+
border: 1.5px solid var(--line);
|
|
485
|
+
border-radius: 8px;
|
|
486
|
+
background: var(--case);
|
|
487
|
+
padding: 10px 14px;
|
|
488
|
+
display: flex;
|
|
489
|
+
flex-direction: column;
|
|
490
|
+
justify-content: space-between;
|
|
491
|
+
min-height: 68px;
|
|
492
|
+
box-shadow: 3px 3px 0 var(--line);
|
|
493
|
+
}
|
|
494
|
+
.stats-item span {
|
|
495
|
+
font-size: 10px;
|
|
496
|
+
font-weight: 800;
|
|
497
|
+
color: var(--muted);
|
|
498
|
+
text-transform: uppercase;
|
|
499
|
+
letter-spacing: 0.5px;
|
|
500
|
+
}
|
|
501
|
+
.stats-item b {
|
|
502
|
+
font-size: 17px;
|
|
503
|
+
font-weight: 900;
|
|
504
|
+
color: var(--ink);
|
|
505
|
+
margin-top: 4px;
|
|
506
|
+
}
|
|
507
|
+
.stats-source {
|
|
508
|
+
display: inline-flex;
|
|
509
|
+
align-items: center;
|
|
510
|
+
width: fit-content;
|
|
511
|
+
max-width: 100%;
|
|
512
|
+
margin-top: 6px;
|
|
513
|
+
border: 1px solid rgba(10, 15, 13, 0.22);
|
|
514
|
+
border-radius: 5px;
|
|
515
|
+
padding: 1px 5px;
|
|
516
|
+
font-size: 8.5px;
|
|
517
|
+
line-height: 1.25;
|
|
518
|
+
font-weight: 900;
|
|
519
|
+
letter-spacing: 0.6px;
|
|
520
|
+
text-transform: uppercase;
|
|
521
|
+
color: var(--accent);
|
|
522
|
+
background: #fff;
|
|
523
|
+
overflow-wrap: anywhere;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
/* Card stamp & Barcode */
|
|
527
|
+
.card-footer-strip {
|
|
528
|
+
display: flex;
|
|
529
|
+
justify-content: space-between;
|
|
530
|
+
align-items: end;
|
|
531
|
+
border-top: 2px dashed rgba(10, 15, 13, 0.15);
|
|
532
|
+
padding-top: 20px;
|
|
533
|
+
}
|
|
534
|
+
.card-stamp {
|
|
535
|
+
border: 3px double var(--stamp);
|
|
536
|
+
color: var(--stamp);
|
|
537
|
+
border-radius: 4px;
|
|
538
|
+
padding: 4px 10px;
|
|
539
|
+
transform: rotate(-3deg);
|
|
540
|
+
font-size: 11px;
|
|
541
|
+
font-weight: 900;
|
|
542
|
+
letter-spacing: 1.5px;
|
|
543
|
+
text-transform: uppercase;
|
|
544
|
+
background: rgba(184, 45, 34, 0.02);
|
|
545
|
+
box-shadow: inset 0 0 0 1px var(--stamp);
|
|
546
|
+
}
|
|
547
|
+
.card-barcode-box {
|
|
548
|
+
text-align: right;
|
|
549
|
+
}
|
|
550
|
+
.card-barcode {
|
|
551
|
+
display: inline-block;
|
|
552
|
+
height: 26px;
|
|
553
|
+
width: 120px;
|
|
554
|
+
background: repeating-linear-gradient(90deg, var(--ink), var(--ink) 1.5px, transparent 1.5px, transparent 4.5px, var(--ink) 4.5px, var(--ink) 5.5px, transparent 5.5px, transparent 8.5px);
|
|
555
|
+
opacity: 0.85;
|
|
556
|
+
}
|
|
557
|
+
.card-serial {
|
|
558
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
559
|
+
font-size: 9px;
|
|
560
|
+
letter-spacing: 1.5px;
|
|
561
|
+
color: var(--muted);
|
|
562
|
+
margin-top: 2px;
|
|
563
|
+
text-transform: uppercase;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
/* Card MRZ Zone */
|
|
567
|
+
.card-mrz {
|
|
568
|
+
background: var(--page);
|
|
569
|
+
border-top: 2.5px solid var(--line);
|
|
570
|
+
padding: 12px 12px 12px 24px;
|
|
571
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
572
|
+
font-size: 10px;
|
|
573
|
+
line-height: 1.4;
|
|
574
|
+
letter-spacing: 2px;
|
|
575
|
+
color: var(--muted);
|
|
576
|
+
white-space: nowrap;
|
|
577
|
+
overflow: hidden;
|
|
578
|
+
text-overflow: ellipsis;
|
|
579
|
+
text-transform: uppercase;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
/* SCROLL DOWN PROMPT */
|
|
583
|
+
.scroll-prompt {
|
|
584
|
+
text-align: center;
|
|
585
|
+
margin: 16px 0 40px;
|
|
586
|
+
font-size: 13px;
|
|
587
|
+
font-weight: 800;
|
|
588
|
+
color: var(--accent);
|
|
589
|
+
letter-spacing: 1px;
|
|
590
|
+
text-transform: uppercase;
|
|
591
|
+
animation: bounce 2s infinite;
|
|
592
|
+
}
|
|
593
|
+
@keyframes bounce {
|
|
594
|
+
0%, 20%, 50%, 80%, 100% { transform: translateY(0); }
|
|
595
|
+
40% { transform: translateY(-4px); }
|
|
596
|
+
60% { transform: translateY(-2px); }
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
/* AUDIT DETAILS (DOWNSTREAM LEDGER) */
|
|
600
|
+
.dossier-section { margin-top: 24px; padding: clamp(20px, 4vw, 36px); background: var(--sheet); }
|
|
601
|
+
.section-head { display: grid; grid-template-columns: minmax(0, 1fr) minmax(260px, .36fr); gap: 24px; align-items: end; margin-bottom: 28px; border-bottom: 2px dashed #dce2dc; padding-bottom: 16px; }
|
|
602
|
+
.kicker { color: var(--accent); margin-bottom: 6px; font-size: 13px; font-family: ui-monospace, monospace; }
|
|
603
|
+
h2 { margin: 0; font-size: clamp(24px, 4vw, 42px); line-height: 1.0; letter-spacing: -1px; overflow-wrap: anywhere; font-weight: 900; }
|
|
604
|
+
.section-head p { margin: 0; color: var(--muted); line-height: 1.5; font-size: 14px; font-weight: 600; }
|
|
605
|
+
|
|
606
|
+
.signal-list, .ability-list, .ledger-list, .case-list, .note-list, .boundary-grid { display: grid; gap: 12px; }
|
|
607
|
+
.signal-row, .ability-row, .ledger-row, .case-file, .note-file, .boundary-panel { min-width: 0; border: 2px solid var(--line); border-radius: 10px; background: #fafdfa; padding: 20px; box-shadow: 4px 4px 0 var(--line); transition: all 0.15s ease; }
|
|
608
|
+
.signal-row:hover, .ability-row:hover, .ledger-row:hover, .case-file:hover { transform: translate(-1.5px, -1.5px); box-shadow: 5.5px 5.5px 0 var(--line); }
|
|
609
|
+
|
|
610
|
+
.signal-row, .ability-row, .ledger-row { display: grid; grid-template-columns: minmax(180px, .55fr) minmax(0, 1fr) minmax(140px, .24fr); gap: 20px; align-items: center; }
|
|
611
|
+
.name { font-weight: 900; font-size: 19px; overflow-wrap: anywhere; color: var(--ink); }
|
|
612
|
+
.meta, .small { color: var(--muted); font-size: 13px; line-height: 1.45; overflow-wrap: anywhere; font-weight: 600; }
|
|
613
|
+
|
|
614
|
+
/* Sliders / Vintage Analog Meters */
|
|
615
|
+
.band-track { height: 14px; border: 2px solid var(--line); background: var(--field); overflow: hidden; border-radius: 4px; }
|
|
616
|
+
.band-fill {
|
|
617
|
+
height: 100%;
|
|
618
|
+
background: repeating-linear-gradient(
|
|
619
|
+
-45deg,
|
|
620
|
+
var(--accent),
|
|
621
|
+
var(--accent) 7px,
|
|
622
|
+
#128c7f 7px,
|
|
623
|
+
#128c7f 14px
|
|
624
|
+
);
|
|
625
|
+
border-right: 2px solid var(--line);
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
.pill-line { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
|
|
629
|
+
.pill { border: 1px solid var(--line); border-radius: 6px; padding: 4px 10px; background: #f0f6f1; color: var(--steel); font-size: 11px; font-weight: 800; overflow-wrap: anywhere; box-shadow: 1px 1px 0 var(--line); }
|
|
630
|
+
|
|
631
|
+
.ledger-row { grid-template-columns: minmax(140px, .3fr) minmax(0, 1fr) minmax(160px, .28fr); }
|
|
632
|
+
.case-list { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
|
|
633
|
+
|
|
634
|
+
/* Index Cards with Watermark */
|
|
635
|
+
.case-file {
|
|
636
|
+
background: var(--case);
|
|
637
|
+
position: relative;
|
|
638
|
+
}
|
|
639
|
+
.case-file::after {
|
|
640
|
+
content: "CONFIDENTIAL";
|
|
641
|
+
position: absolute;
|
|
642
|
+
bottom: 12px;
|
|
643
|
+
right: 16px;
|
|
644
|
+
font-size: 18px;
|
|
645
|
+
font-weight: 950;
|
|
646
|
+
color: rgba(184, 45, 34, 0.04);
|
|
647
|
+
transform: rotate(-12deg);
|
|
648
|
+
letter-spacing: 2px;
|
|
649
|
+
pointer-events: none;
|
|
650
|
+
font-family: ui-monospace, monospace;
|
|
651
|
+
}
|
|
652
|
+
.case-title { display: flex; justify-content: space-between; gap: 12px; align-items: start; }
|
|
653
|
+
.case-title b { font-size: 18px; line-height: 1.25; overflow-wrap: anywhere; font-weight: 900; color: var(--ink); }
|
|
654
|
+
.case-id { color: var(--accent); font-size: 12px; font-weight: 900; overflow-wrap: anywhere; font-family: ui-monospace, monospace; }
|
|
655
|
+
.case-file p, .note-file p, .boundary-panel p { margin: 10px 0 0; color: var(--muted); line-height: 1.5; overflow-wrap: anywhere; font-size: 13.5px; font-weight: 600; }
|
|
656
|
+
.case-file p b { color: var(--ink); }
|
|
657
|
+
|
|
658
|
+
.boundary-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
|
|
659
|
+
.boundary-panel { background: var(--case); }
|
|
660
|
+
ul.clean { margin: 10px 0 0; padding: 0; list-style: none; color: var(--muted); line-height: 1.6; font-size: 13px; font-weight: 600; }
|
|
661
|
+
ul.clean li { overflow-wrap: anywhere; padding-left: 14px; position: relative; margin-bottom: 4px; }
|
|
662
|
+
ul.clean li::before { content: "▪"; position: absolute; left: 0; color: var(--accent); font-size: 8px; top: 1px; }
|
|
663
|
+
|
|
664
|
+
@media (max-width: 960px) {
|
|
665
|
+
main { width: 100%; padding-top: 16px; }
|
|
666
|
+
.hero, .section-head, .case-list, .boundary-grid { grid-template-columns: 1fr; }
|
|
667
|
+
.signal-row, .ability-row, .ledger-row { grid-template-columns: 1fr; gap: 14px; }
|
|
668
|
+
h1 { font-size: clamp(32px, 8vw, 48px); }
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
/* Clean CSS Tabs & Linear Aesthetic */
|
|
672
|
+
.tab-input { display: none; }
|
|
673
|
+
.tab-nav-wrapper {
|
|
674
|
+
display: flex;
|
|
675
|
+
justify-content: center;
|
|
676
|
+
gap: 12px;
|
|
677
|
+
margin: 20px 0 32px 0;
|
|
678
|
+
flex-wrap: wrap;
|
|
679
|
+
}
|
|
680
|
+
.tab-label {
|
|
681
|
+
background: var(--sheet);
|
|
682
|
+
border: 2px solid var(--line);
|
|
683
|
+
border-radius: 8px;
|
|
684
|
+
padding: 10px 20px;
|
|
685
|
+
font-size: 14px;
|
|
686
|
+
font-weight: 850;
|
|
687
|
+
color: var(--steel);
|
|
688
|
+
cursor: pointer;
|
|
689
|
+
box-shadow: 3px 3px 0 var(--line);
|
|
690
|
+
transition: all 0.15s ease-in-out;
|
|
691
|
+
user-select: none;
|
|
692
|
+
}
|
|
693
|
+
.tab-label:hover {
|
|
694
|
+
transform: translate(-1px, -1px);
|
|
695
|
+
box-shadow: 4px 4px 0 var(--line);
|
|
696
|
+
}
|
|
697
|
+
.tab-content {
|
|
698
|
+
display: none;
|
|
699
|
+
animation: tabFadeIn 0.2s cubic-bezier(0.16, 1, 0.3, 1) both;
|
|
700
|
+
}
|
|
701
|
+
#tab-specialties:checked ~ .tab-nav-wrapper label[for="tab-specialties"],
|
|
702
|
+
#tab-evidence:checked ~ .tab-nav-wrapper label[for="tab-evidence"],
|
|
703
|
+
#tab-ledger:checked ~ .tab-nav-wrapper label[for="tab-ledger"],
|
|
704
|
+
#tab-redaction:checked ~ .tab-nav-wrapper label[for="tab-redaction"] {
|
|
705
|
+
background: var(--accent);
|
|
706
|
+
color: #ffffff;
|
|
707
|
+
border-color: var(--line);
|
|
708
|
+
box-shadow: 1px 1px 0 var(--line);
|
|
709
|
+
transform: translate(2px, 2px);
|
|
710
|
+
}
|
|
711
|
+
#tab-specialties:checked ~ #content-specialties,
|
|
712
|
+
#tab-evidence:checked ~ #content-evidence,
|
|
713
|
+
#tab-ledger:checked ~ #content-ledger,
|
|
714
|
+
#tab-redaction:checked ~ #content-redaction {
|
|
715
|
+
display: block;
|
|
716
|
+
}
|
|
717
|
+
@keyframes tabFadeIn {
|
|
718
|
+
from { opacity: 0; transform: translateY(6px); }
|
|
719
|
+
to { opacity: 1; transform: translateY(0); }
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
/* Specialty Split Columns */
|
|
723
|
+
.specialty-columns {
|
|
724
|
+
display: grid;
|
|
725
|
+
grid-template-columns: 1fr 1fr;
|
|
726
|
+
gap: 20px;
|
|
727
|
+
}
|
|
728
|
+
@media (max-width: 850px) {
|
|
729
|
+
.specialty-columns { grid-template-columns: 1fr; }
|
|
730
|
+
}
|
|
731
|
+
</style>
|
|
732
|
+
</head>
|
|
733
|
+
<body>
|
|
734
|
+
<main>
|
|
735
|
+
<!-- GORGEOUS SHARABLE BADGE CARD -->
|
|
736
|
+
<div class="share-container">
|
|
737
|
+
<div class="badge-card variant-${esc(cardTheme.id)}">
|
|
738
|
+
<!-- Rainbow edge border decoration -->
|
|
739
|
+
<div class="holo-strip"></div>
|
|
740
|
+
|
|
741
|
+
<div class="badge-body">
|
|
742
|
+
<!-- Card top header -->
|
|
743
|
+
<div class="chip-container">
|
|
744
|
+
<div class="card-chip"></div>
|
|
745
|
+
<div class="card-header-meta">
|
|
746
|
+
<div>${esc(copy.productMark)}</div>
|
|
747
|
+
<div style="font-weight:900; color:var(--ink);">${esc(copy.generated)} ${esc(profile.generated_at.slice(0, 10))}</div>
|
|
748
|
+
</div>
|
|
749
|
+
</div>
|
|
750
|
+
|
|
751
|
+
<!-- Holder name -->
|
|
752
|
+
<h1 class="holder-name">${esc(profile.owner.display_name)}</h1>
|
|
753
|
+
|
|
754
|
+
<!-- Witty programmer-specific tags -->
|
|
755
|
+
<div class="holder-tags">
|
|
756
|
+
${archetype.tags.map((tag) => `<span class="holder-tag">${esc(tag)}</span>`).join("\n")}
|
|
757
|
+
</div>
|
|
758
|
+
|
|
759
|
+
<!-- Character Archetype Banner -->
|
|
760
|
+
<div class="archetype-banner">
|
|
761
|
+
<div class="archetype-label">${isZh ? "AI 协同职业倾向" : "COLLABORATION ARCHETYPE"}</div>
|
|
762
|
+
<h2 class="archetype-title">${esc(archetype.name)} / <span style="font-size:16px; opacity:0.85;">${esc(archetype.enName)}</span></h2>
|
|
763
|
+
</div>
|
|
764
|
+
|
|
765
|
+
<!-- Quote -->
|
|
766
|
+
<div class="badge-quote">
|
|
767
|
+
${esc(isZh ? archetype.tagline : archetype.enTagline)}
|
|
768
|
+
</div>
|
|
769
|
+
<div class="signature-line">
|
|
770
|
+
<span>${isZh ? "主导信号" : "Signal"}</span>
|
|
771
|
+
<b>${esc(archetype.signature || `${archetype.dominant?.role_label || archetype.name} · ${archetype.dominant?.ability_label || cardTheme.label}`)}</b>
|
|
772
|
+
</div>
|
|
773
|
+
|
|
774
|
+
<!-- RPG Attributes Slider Panel -->
|
|
775
|
+
<div class="rpg-section-title">${isZh ? "驯化属性倾向 / OPERATOR STATS" : "OPERATOR ATRIBUTES"}</div>
|
|
776
|
+
<div class="rpg-panel">
|
|
777
|
+
<div class="rpg-row">
|
|
778
|
+
<div class="rpg-label">${isZh ? "防错严谨度" : "Audit Rigor"}</div>
|
|
779
|
+
<div class="rpg-track"><div class="rpg-fill" style="width:${archetype.rigor}%"></div></div>
|
|
780
|
+
<div class="rpg-value">${archetype.rigor}%</div>
|
|
781
|
+
</div>
|
|
782
|
+
<div class="rpg-row">
|
|
783
|
+
<div class="rpg-label">${isZh ? "高频操控欲" : "Control"}</div>
|
|
784
|
+
<div class="rpg-track"><div class="rpg-fill" style="width:${archetype.control}%"></div></div>
|
|
785
|
+
<div class="rpg-value">${archetype.control}%</div>
|
|
786
|
+
</div>
|
|
787
|
+
<div class="rpg-row">
|
|
788
|
+
<div class="rpg-label">${isZh ? "顶层大局观" : "Strategy"}</div>
|
|
789
|
+
<div class="rpg-track"><div class="rpg-fill" style="width:${archetype.strategic}%"></div></div>
|
|
790
|
+
<div class="rpg-value">${archetype.strategic}%</div>
|
|
791
|
+
</div>
|
|
792
|
+
<div class="rpg-row">
|
|
793
|
+
<div class="rpg-label">${isZh ? "冷血闭环值" : "Execution"}</div>
|
|
794
|
+
<div class="rpg-track"><div class="rpg-fill" style="width:${archetype.closedLoop}%"></div></div>
|
|
795
|
+
<div class="rpg-value">${archetype.closedLoop}%</div>
|
|
796
|
+
</div>
|
|
797
|
+
</div>
|
|
798
|
+
|
|
799
|
+
<!-- Battle Stats Grid -->
|
|
800
|
+
<div class="rpg-section-title">${isZh ? "调教战绩统计 / INTERACTION BATTLE RECORDS" : "BATTLE STATS"}</div>
|
|
801
|
+
<div class="stats-grid">
|
|
802
|
+
<div class="stats-item">
|
|
803
|
+
<span>${esc(copy.localThreads)}</span>
|
|
804
|
+
<b>${formatNumber(codex.sessions || 0, profile.report.locale)} 次</b>
|
|
805
|
+
<em class="stats-source">${esc(copy.localAudited)}</em>
|
|
806
|
+
</div>
|
|
807
|
+
<div class="stats-item">
|
|
808
|
+
<span>${esc(hasAccountUsage ? copy.accountTokens : copy.tokenActivity)}</span>
|
|
809
|
+
<b>${formatChineseCompact(displayTokens)}</b>
|
|
810
|
+
<em class="stats-source">${esc(hasAccountUsage ? copy.accountOverview : copy.localAudited)}</em>
|
|
811
|
+
</div>
|
|
812
|
+
<div class="stats-item">
|
|
813
|
+
<span>${esc(hasAccountUsage ? copy.longestTask : (isZh ? "驯化周期" : "Trace Active"))}</span>
|
|
814
|
+
<b>${esc(hasAccountUsage && longestTask ? longestTask : `${archetype.traceDays} 天`)}</b>
|
|
815
|
+
</div>
|
|
816
|
+
<div class="stats-item">
|
|
817
|
+
<span>${esc(hasAccountUsage ? copy.streakDays : (isZh ? "当前状态" : "Active Status"))}</span>
|
|
818
|
+
<b style="color:var(--accent);">${esc(hasAccountUsage && Number.isFinite(currentStreakDays) ? `${currentStreakDays} 天` : archetype.activeStatus)}</b>${streakSource}
|
|
819
|
+
</div>
|
|
820
|
+
</div>
|
|
821
|
+
|
|
822
|
+
<!-- Card barcode and stamp -->
|
|
823
|
+
<div class="card-footer-strip">
|
|
824
|
+
<div class="card-stamp">${esc(copy.proofStamp)}</div>
|
|
825
|
+
<div class="card-barcode-box">
|
|
826
|
+
<div class="card-barcode"></div>
|
|
827
|
+
<div class="card-serial">AR-${esc(archetype.code)}-${esc(profile.owner.id.toUpperCase())}</div>
|
|
828
|
+
</div>
|
|
829
|
+
</div>
|
|
830
|
+
</div>
|
|
831
|
+
|
|
832
|
+
<!-- Passport MRZ zone -->
|
|
833
|
+
<div class="card-mrz">
|
|
834
|
+
P<CHN<${esc(profile.owner.id.toUpperCase())}<<<<<<<<<<<<<<<<<<<<<<<<<<<<<br>
|
|
835
|
+
AR<${esc(archetype.code)}<${esc(formatCompactNumber(displayTokens, "en-US").toUpperCase())}<${esc(codex.sessions || 0)}<EVI<<<<<<<<<
|
|
836
|
+
</div>
|
|
837
|
+
</div>
|
|
838
|
+
</div>
|
|
839
|
+
|
|
840
|
+
<!-- Bounce prompt to scroll -->
|
|
841
|
+
<div class="scroll-prompt">
|
|
842
|
+
▼ ${isZh ? "向下滚动解密:底层技术审计链 & 事实证据卷宗" : "Scroll to inspect: low-level audit trace & evidence dossiers"}
|
|
843
|
+
</div>
|
|
844
|
+
|
|
845
|
+
<!-- Clean CSS Tabs for Progressive Disclosure -->
|
|
846
|
+
<input type="radio" name="tabs" id="tab-specialties" checked class="tab-input">
|
|
847
|
+
<input type="radio" name="tabs" id="tab-evidence" class="tab-input">
|
|
848
|
+
<input type="radio" name="tabs" id="tab-ledger" class="tab-input">
|
|
849
|
+
<input type="radio" name="tabs" id="tab-redaction" class="tab-input">
|
|
850
|
+
|
|
851
|
+
<div class="tab-nav-wrapper">
|
|
852
|
+
<label for="tab-specialties" class="tab-label">${isZh ? "🌟 协作特长" : "Specialties"}</label>
|
|
853
|
+
<label for="tab-evidence" class="tab-label">${isZh ? "📁 事实存证" : "Evidence"}</label>
|
|
854
|
+
<label for="tab-ledger" class="tab-label">${isZh ? "🔌 智能体台账" : "Ledger"}</label>
|
|
855
|
+
<label for="tab-redaction" class="tab-label">${isZh ? "🛡️ 数据合规墙" : "Redaction"}</label>
|
|
856
|
+
</div>
|
|
857
|
+
|
|
858
|
+
<!-- TAB CONTENT 1: SPECIALTIES -->
|
|
859
|
+
<div class="tab-content" id="content-specialties">
|
|
860
|
+
<div class="specialty-columns">
|
|
861
|
+
<!-- 01 / ROLE SIGNALS -->
|
|
862
|
+
<section class="dossier-section" style="margin-top:0;">
|
|
863
|
+
<div class="section-head">
|
|
864
|
+
<div><div class="kicker">01 / ${esc(copy.identityLabel)}</div><h2>${esc(copy.sections.roles)}</h2></div>
|
|
865
|
+
<p>${esc(copy.roleIntro)}</p>
|
|
866
|
+
</div>
|
|
867
|
+
<div class="signal-list">
|
|
868
|
+
${profile.work_role_signals.slice(0, 3).map((role) => {
|
|
869
|
+
const barSegments = Math.round(role.score / 10);
|
|
870
|
+
let segmentHtml = "";
|
|
871
|
+
for (let i = 0; i < 10; i++) {
|
|
872
|
+
const isActive = i < barSegments;
|
|
873
|
+
const color = role.score >= 78 ? "var(--accent)" : "var(--gold)";
|
|
874
|
+
segmentHtml += `<div class="segment-block" style="flex:1; height:100%; background: ${isActive ? color : "var(--field)"}; border-right: 1.5px solid var(--line); transition: background 0.2s ease;"></div>`;
|
|
875
|
+
}
|
|
876
|
+
return `<article class="signal-row" style="grid-template-columns: minmax(130px, 0.45fr) minmax(0, 1fr); padding: 16px; margin-bottom: 8px;">
|
|
877
|
+
<div>
|
|
878
|
+
<div class="name" style="font-size:17.5px;">${esc(role.label)}</div>
|
|
879
|
+
<div class="meta" style="font-family:ui-monospace,monospace; font-size:11.5px; letter-spacing:0.5px;">${esc(role.role_id)}</div>
|
|
880
|
+
</div>
|
|
881
|
+
<div>
|
|
882
|
+
<div class="meta" style="font-weight:800; color:var(--accent); text-transform:uppercase; font-size:11px; letter-spacing:0.5px; margin-bottom:6px;">
|
|
883
|
+
<span class="pill" style="box-shadow:none; padding:1px 5px; background:var(--accent-soft); color:var(--accent); border-color:var(--accent); margin-right:4px; font-size:10px;">${esc(role.band).toUpperCase()}</span>
|
|
884
|
+
置信度: ${esc(role.confidence).toUpperCase()}
|
|
885
|
+
</div>
|
|
886
|
+
<div class="segment-track" style="display:flex; height:10px; border:2px solid var(--line); border-radius:4px; overflow:hidden; background:var(--field); margin-bottom:8px;">
|
|
887
|
+
${segmentHtml}
|
|
888
|
+
</div>
|
|
889
|
+
<div class="pill-line" style="margin-top:4px;">${(role.evidence_ids.length ? role.evidence_ids.slice(0, 3) : [copy.noEvidence]).map((id) => `<span class="pill" style="font-family:ui-monospace,monospace; font-size:10.5px; padding:2px 6px;">${esc(id)}</span>`).join("")}</div>
|
|
890
|
+
</div>
|
|
891
|
+
</article>`;
|
|
892
|
+
}).join("\n")}
|
|
893
|
+
</div>
|
|
894
|
+
</section>
|
|
895
|
+
|
|
896
|
+
<!-- 02 / ABILITIES -->
|
|
897
|
+
<section class="dossier-section" style="margin-top:0;">
|
|
898
|
+
<div class="section-head">
|
|
899
|
+
<div><div class="kicker">02 / ${esc(copy.sections.abilities)}</div><h2>${esc(copy.sections.abilities)}</h2></div>
|
|
900
|
+
<p>${esc(copy.abilityIntro)}</p>
|
|
901
|
+
</div>
|
|
902
|
+
<div class="ability-list">
|
|
903
|
+
${profile.ability_model.slice(0, 3).map((ability) => {
|
|
904
|
+
const bandLower = String(ability.band).toLowerCase();
|
|
905
|
+
let ratingText = "●●○○○ [入门]";
|
|
906
|
+
let ratingColor = "var(--muted)";
|
|
907
|
+
if (bandLower === "strong") {
|
|
908
|
+
ratingText = "●●●●● [精通]";
|
|
909
|
+
ratingColor = "var(--accent)";
|
|
910
|
+
} else if (bandLower === "solid") {
|
|
911
|
+
ratingText = "●●●●○ [熟练]";
|
|
912
|
+
ratingColor = "var(--gold)";
|
|
913
|
+
} else if (bandLower === "developing") {
|
|
914
|
+
ratingText = "●●●○○ [掌握]";
|
|
915
|
+
ratingColor = "var(--ink)";
|
|
916
|
+
}
|
|
917
|
+
return `<article class="ability-row" style="grid-template-columns: minmax(130px, 0.45fr) minmax(0, 1fr); padding: 16px; margin-bottom: 8px;">
|
|
918
|
+
<div>
|
|
919
|
+
<div class="name" style="font-size:17.5px;">${esc(ability.label)}</div>
|
|
920
|
+
<div class="meta" style="font-family:ui-monospace,monospace; font-size:11.5px; letter-spacing:0.5px;">${esc(ability.dimension_id)}</div>
|
|
921
|
+
</div>
|
|
922
|
+
<div>
|
|
923
|
+
<div class="meta" style="font-weight:800; color:${ratingColor}; font-size:11.5px; margin-bottom:6px; font-family:ui-monospace,monospace;">
|
|
924
|
+
${ratingText}
|
|
925
|
+
</div>
|
|
926
|
+
<div class="band-track" aria-hidden="true" style="height:10px;"><div class="band-fill" style="width:${ability.score}%"></div></div>
|
|
927
|
+
<div class="pill-line" style="margin-top:4px;">${(ability.evidence_ids.length ? ability.evidence_ids.slice(0, 3) : [copy.noEvidence]).map((id) => `<span class="pill" style="font-family:ui-monospace,monospace; font-size:10.5px; padding:2px 6px;">${esc(id)}</span>`).join("")}</div>
|
|
928
|
+
</div>
|
|
929
|
+
</article>`;
|
|
930
|
+
}).join("\n")}
|
|
931
|
+
</div>
|
|
932
|
+
</section>
|
|
933
|
+
</div>
|
|
934
|
+
</div>
|
|
935
|
+
|
|
936
|
+
<!-- TAB CONTENT 2: EVIDENCE -->
|
|
937
|
+
<div class="tab-content" id="content-evidence">
|
|
938
|
+
<section class="dossier-section" style="margin-top:0;">
|
|
939
|
+
<div class="section-head">
|
|
940
|
+
<div><div class="kicker">03 / ${esc(copy.sections.evidence)}</div><h2>脱敏存证事实卷宗</h2></div>
|
|
941
|
+
<p>${esc(copy.evidenceIntro)}</p>
|
|
942
|
+
</div>
|
|
943
|
+
<div class="case-list">
|
|
944
|
+
${profile.evidence_notes.slice(0, 3).map((card) => `<div class="case-card-wrapper" style="margin-top:10px;">
|
|
945
|
+
<div class="case-tab" style="display:inline-block; background:var(--field); border:2px solid var(--line); border-bottom:none; border-radius:6px 6px 0 0; padding:4px 12px; font-family:ui-monospace,monospace; font-size:11px; font-weight:900; color:var(--steel); margin-bottom:-2px; position:relative; z-index:2; box-shadow: 2px 0 0 rgba(0,0,0,0.05);">${esc(card.evidence_id)}</div>
|
|
946
|
+
|
|
947
|
+
<article class="case-file" style="margin-top:0; border-top-left-radius:0; z-index:1; position:relative; padding: 20px;">
|
|
948
|
+
<div class="case-title">
|
|
949
|
+
<b style="font-size:17.5px;">${esc(card.title)}</b>
|
|
950
|
+
</div>
|
|
951
|
+
<div class="pill-line" style="margin-top:8px;">
|
|
952
|
+
<span class="pill" style="background:#fff; font-family:ui-monospace,monospace;">等级: ${esc(card.level.join(" / "))}</span>
|
|
953
|
+
<span class="pill" style="background:#fff; color:var(--accent); border-color:var(--accent); font-weight:800;">${isZh ? `置信度: ${card.confidence === "high" ? "高" : card.confidence === "medium" ? "中" : "低"}` : `${esc(card.confidence).toUpperCase()} CONFIDENCE`}</span>
|
|
954
|
+
${card.agent_clients.map((client) => `<span class="pill" style="background:#fff; font-family:ui-monospace,monospace;">${esc(client)}</span>`).join("")}
|
|
955
|
+
</div>
|
|
956
|
+
<p style="margin-top:12px; line-height:1.6; font-size:13.5px; color:var(--muted); font-weight:600;">${esc(card.summary)}</p>
|
|
957
|
+
|
|
958
|
+
<p style="font-size:12.5px; margin-top:16px; font-family:ui-monospace,monospace; background:rgba(0,0,0,0.02); border:1px dashed rgba(0,0,0,0.1); padding:8px 12px; border-radius:6px;">
|
|
959
|
+
<b style="color:var(--accent); font-family:ui-sans-serif,sans-serif;">${esc(copy.refs)}:</b> <span style="color:var(--muted); font-weight:700;">$ cat trace.log | grep "${esc(card.refs.map(formatPublicRef).join(" | "))}"</span>
|
|
960
|
+
</p>
|
|
961
|
+
</article>
|
|
962
|
+
</div>`).join("\n")}
|
|
963
|
+
</div>
|
|
964
|
+
</section>
|
|
965
|
+
</div>
|
|
966
|
+
|
|
967
|
+
<!-- TAB CONTENT 3: LEDGER -->
|
|
968
|
+
<div class="tab-content" id="content-ledger">
|
|
969
|
+
<section class="dossier-section" style="margin-top:0;">
|
|
970
|
+
<div class="section-head">
|
|
971
|
+
<div><div class="kicker">04 / ${esc(copy.sections.ledger)}</div><h2>${esc(copy.sections.ledger)}</h2></div>
|
|
972
|
+
<p>${esc(copy.ledgerIntro)}</p>
|
|
973
|
+
</div>
|
|
974
|
+
<div class="ledger-list">
|
|
975
|
+
${clients.map((client) => {
|
|
976
|
+
const isMeasured = client.status === "measured";
|
|
977
|
+
const clientDisplayUsage = client.display_usage || {};
|
|
978
|
+
const clientDisplayTokens = clientDisplayUsage.token_usage?.total_tokens || client.token_usage?.total_tokens || 0;
|
|
979
|
+
const clientHasAccountUsage = clientDisplayUsage.source === "codex_account_usage";
|
|
980
|
+
const sessionText = Number.isFinite(client.sessions)
|
|
981
|
+
? `<span style="font-family:ui-monospace,monospace; font-size:14px; color:var(--ink);">${formatNumber(client.sessions, profile.report.locale)}</span> ${copy.sessions}`
|
|
982
|
+
: copy.pending;
|
|
983
|
+
const traceText = client.trace_window
|
|
984
|
+
? ` · <span style="font-family:ui-monospace,monospace; font-size:12.5px; color:var(--muted);">${client.trace_window.start} -> ${client.trace_window.end}</span>`
|
|
985
|
+
: "";
|
|
986
|
+
const evidenceText = Number.isFinite(client.evidence_count)
|
|
987
|
+
? `<span style="color:var(--accent); font-size:13px;">${formatNumber(client.evidence_count, profile.report.locale)}</span> ${copy.evidenceCount}`
|
|
988
|
+
: "";
|
|
989
|
+
const tokenText = clientDisplayTokens
|
|
990
|
+
? ` · <span style="color:var(--gold); font-size:13px;">${formatCompactNumber(clientDisplayTokens, profile.report.locale)}</span> ${clientHasAccountUsage ? copy.accountOverview : copy.tokenActivity}`
|
|
991
|
+
: "";
|
|
992
|
+
return `<article class="ledger-row" style="border-left: 5px solid ${isMeasured ? "var(--accent)" : "var(--field)"};">
|
|
993
|
+
<div>
|
|
994
|
+
<div class="name" style="font-family:ui-monospace,monospace; letter-spacing:-0.5px; display:flex; align-items:center; gap:8px;">
|
|
995
|
+
${esc(client.client_id)}
|
|
996
|
+
</div>
|
|
997
|
+
<div class="meta" style="display:flex; align-items:center; gap:6px; font-weight:800; font-size:11.5px; color:${isMeasured ? "var(--accent)" : "var(--muted)"};">
|
|
998
|
+
<span style="display:inline-block; width:8px; height:8px; border-radius:50%; background:${isMeasured ? "var(--accent)" : "#cbd4cc"}; border:1px solid var(--line);"></span>
|
|
999
|
+
${isMeasured ? (isZh ? "已在线适配 / ACTIVE" : "ACTIVE") : (isZh ? "未挂载 / OFFLINE" : "OFFLINE")}
|
|
1000
|
+
</div>
|
|
1001
|
+
</div>
|
|
1002
|
+
<div class="meta" style="font-weight:700;">
|
|
1003
|
+
${sessionText}${traceText}
|
|
1004
|
+
</div>
|
|
1005
|
+
<div class="small" style="font-family:ui-monospace,monospace; font-weight:800; text-align:right;">${evidenceText}${tokenText}</div>
|
|
1006
|
+
</article>`;
|
|
1007
|
+
}).join("\n")}
|
|
1008
|
+
</div>
|
|
1009
|
+
</section>
|
|
1010
|
+
</div>
|
|
1011
|
+
|
|
1012
|
+
<!-- TAB CONTENT 4: REDACTION -->
|
|
1013
|
+
<div class="tab-content" id="content-redaction">
|
|
1014
|
+
<section class="dossier-section" style="margin-top:0;">
|
|
1015
|
+
<div class="section-head">
|
|
1016
|
+
<div><div class="kicker">05 / ${esc(copy.sections.redaction)}</div><h2>数据隔离与合规红线</h2></div>
|
|
1017
|
+
<p>${esc(copy.redactionIntro)}</p>
|
|
1018
|
+
</div>
|
|
1019
|
+
|
|
1020
|
+
<div class="boundary-grid" style="margin-bottom:24px;">
|
|
1021
|
+
<article class="boundary-panel" style="border-top: 4px solid var(--stamp); background:linear-gradient(180deg, #ffffff, #fffbfb);">
|
|
1022
|
+
<div class="name" style="color:var(--stamp); font-size:16px; display:flex; align-items:center; gap:8px;">
|
|
1023
|
+
<span style="font-size:18px;">🛑</span> ${esc(copy.excluded)}
|
|
1024
|
+
</div>
|
|
1025
|
+
<ul class="clean" style="margin-top:14px;">${profile.privacy_boundary.excluded_from_public_artifacts.map((item) => `<li style="color:var(--muted); font-weight:600;"><span style="font-family:ui-monospace,monospace; font-weight:800; color:var(--stamp);">$ redacted:</span> ${esc(item)}</li>`).join("\n")}</ul>
|
|
1026
|
+
</article>
|
|
1027
|
+
<article class="boundary-panel" style="border-top: 4px solid var(--accent); background:linear-gradient(180deg, #ffffff, #fafdfa);">
|
|
1028
|
+
<div class="name" style="color:var(--accent); font-size:16px; display:flex; align-items:center; gap:8px;">
|
|
1029
|
+
<span style="font-size:18px;">🛡️</span> ${esc(copy.artifacts)}
|
|
1030
|
+
</div>
|
|
1031
|
+
<ul class="clean" style="margin-top:14px;">${profile.privacy_boundary.public_artifacts.map((item) => `<li style="color:var(--muted); font-weight:600;"><span style="font-family:ui-monospace,monospace; font-weight:800; color:var(--accent);">$ write:</span> ${esc(item)}</li>`).join("\n")}</ul>
|
|
1032
|
+
<p style="margin-top:18px; font-size:12.5px; border-top:1.5px dashed rgba(0,0,0,0.08); padding-top:12px; color:var(--muted);"><b>${esc(copy.confidence)}:</b> <span style="font-family:ui-monospace,monospace; font-weight:800; color:var(--accent);">${esc(profile.work_identity.confidence).toUpperCase()}</span> · <b>${esc(copy.evidenceIds)}:</b> <span style="font-family:ui-monospace,monospace; color:var(--muted); font-size:11.5px;">${esc(profile.work_identity.evidence_ids.join(", "))}</span></p>
|
|
1033
|
+
</article>
|
|
1034
|
+
</div>
|
|
1035
|
+
|
|
1036
|
+
<div class="note-list">
|
|
1037
|
+
${profile.calibration_notes.map((note) => {
|
|
1038
|
+
const isHigh = note.severity === "high";
|
|
1039
|
+
const isMed = note.severity === "medium";
|
|
1040
|
+
const stripeColor = isHigh ? "var(--stamp)" : isMed ? "var(--gold)" : "var(--accent)";
|
|
1041
|
+
const stripeHtml = isHigh || isMed
|
|
1042
|
+
? `
|
|
1043
|
+
<div style="position:absolute; left:0; top:0; bottom:0; width:4px; background:repeating-linear-gradient(45deg, ${stripeColor}, ${stripeColor} 4px, #000 4px, #000 8px); opacity:0.15;"></div>`
|
|
1044
|
+
: "";
|
|
1045
|
+
return `<article class="note-file" style="border-left: 6px solid ${stripeColor}; position:relative; overflow:hidden;">${stripeHtml}
|
|
1046
|
+
<div class="case-title" style="padding-left:${isHigh || isMed ? "6px" : "0"};">
|
|
1047
|
+
<b style="font-family:ui-monospace,monospace; font-size:14px; letter-spacing:0.5px; color:var(--ink);">${esc(note.type).toUpperCase()}</b>
|
|
1048
|
+
<span class="pill" style="background:${isHigh ? "#fff5f4" : isMed ? "#fffdf0" : "#f4faf7"}; color:${stripeColor}; border-color:currentColor; font-size:11px; padding:2px 8px; font-weight:800;">${esc(note.severity).toUpperCase()}</span>
|
|
1049
|
+
</div>
|
|
1050
|
+
<p style="padding-left:${isHigh || isMed ? "6px" : "0"}; margin-top:8px; line-height:1.55; color:var(--muted); font-size:13.5px; font-weight:600;">${esc(note.summary)}</p>
|
|
1051
|
+
</article>`;
|
|
1052
|
+
}).join("\n")}
|
|
1053
|
+
</div>
|
|
1054
|
+
</section>
|
|
1055
|
+
</div>
|
|
1056
|
+
</main>
|
|
1057
|
+
</body>
|
|
1058
|
+
</html>`;
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
export function renderAgentContextJson(profile) {
|
|
1062
|
+
const topRoles = profile.work_role_signals.slice(0, 5);
|
|
1063
|
+
const topAbilities = profile.ability_model.slice(0, 6);
|
|
1064
|
+
return {
|
|
1065
|
+
schema_version: "agentrecord.agent_context.v0",
|
|
1066
|
+
generated_at: profile.generated_at,
|
|
1067
|
+
owner: {
|
|
1068
|
+
id: profile.owner.id,
|
|
1069
|
+
display_name: profile.owner.display_name
|
|
1070
|
+
},
|
|
1071
|
+
locale: profile.report.locale,
|
|
1072
|
+
work_identity: {
|
|
1073
|
+
label: profile.work_identity.primary_label,
|
|
1074
|
+
summary: profile.work_identity.summary,
|
|
1075
|
+
strongest_claim: profile.work_identity.strongest_claim,
|
|
1076
|
+
confidence: profile.work_identity.confidence,
|
|
1077
|
+
evidence_ids: profile.work_identity.evidence_ids
|
|
1078
|
+
},
|
|
1079
|
+
collaboration_style: [
|
|
1080
|
+
"Prefers evidence-bound execution with clear scope, explicit assumptions, and concrete validation.",
|
|
1081
|
+
"Values direct status reporting, reviewable diffs, and preserving unrelated user work.",
|
|
1082
|
+
"Works well with agents that separate product claims, implementation evidence, and residual risk."
|
|
1083
|
+
],
|
|
1084
|
+
verification_preferences: [
|
|
1085
|
+
"Run the narrowest meaningful command first, then expand validation when shared behavior or release readiness is affected.",
|
|
1086
|
+
"Report command outcomes plainly, including skipped or unavailable checks.",
|
|
1087
|
+
"Treat green tests as necessary but not sufficient when privacy, packaging, or public artifacts are in scope."
|
|
1088
|
+
],
|
|
1089
|
+
scope_control: [
|
|
1090
|
+
"Keep default outputs local-first and self/share oriented.",
|
|
1091
|
+
"Do not introduce employment-decision, leaderboard, or unsupported seniority conclusions into default artifacts.",
|
|
1092
|
+
"Keep private state under the profile-local private state directory and public artifacts redacted."
|
|
1093
|
+
],
|
|
1094
|
+
risk_boundaries: profile.privacy_boundary.excluded_from_public_artifacts,
|
|
1095
|
+
handoff_preferences: [
|
|
1096
|
+
"Lead with verdict, changed files, validation evidence, privacy risk, and residual risk.",
|
|
1097
|
+
"Use evidence IDs when referencing strong claims.",
|
|
1098
|
+
"Make blockers concrete instead of guessing."
|
|
1099
|
+
],
|
|
1100
|
+
role_signals: topRoles.map((role) => ({
|
|
1101
|
+
role_id: role.role_id,
|
|
1102
|
+
label: role.label,
|
|
1103
|
+
band: role.band,
|
|
1104
|
+
confidence: role.confidence,
|
|
1105
|
+
evidence_mix: formatEvidenceMix(role.evidence_level_mix),
|
|
1106
|
+
evidence_ids: role.evidence_ids,
|
|
1107
|
+
missing_evidence: role.missing_evidence
|
|
1108
|
+
})),
|
|
1109
|
+
ability_model: topAbilities.map((ability) => ({
|
|
1110
|
+
dimension_id: ability.dimension_id,
|
|
1111
|
+
label: ability.label,
|
|
1112
|
+
band: ability.band,
|
|
1113
|
+
confidence: ability.confidence,
|
|
1114
|
+
evidence_mix: formatEvidenceMix(ability.evidence_level_mix),
|
|
1115
|
+
evidence_ids: ability.evidence_ids,
|
|
1116
|
+
missing_evidence: ability.missing_evidence
|
|
1117
|
+
})),
|
|
1118
|
+
evidence_summary: profile.evidence_notes.map((card) => ({
|
|
1119
|
+
evidence_id: card.evidence_id,
|
|
1120
|
+
level: card.level,
|
|
1121
|
+
title: card.title,
|
|
1122
|
+
summary: card.summary,
|
|
1123
|
+
confidence: card.confidence,
|
|
1124
|
+
agent_clients: card.agent_clients,
|
|
1125
|
+
dimensions: card.dimensions,
|
|
1126
|
+
role_signals: card.role_signals
|
|
1127
|
+
})),
|
|
1128
|
+
calibration_notes: profile.calibration_notes,
|
|
1129
|
+
privacy_boundary: {
|
|
1130
|
+
local_only_generation: profile.privacy_boundary.local_only_generation,
|
|
1131
|
+
raw_logs_included: profile.privacy_boundary.raw_logs_included,
|
|
1132
|
+
public_session_ids_included: profile.privacy_boundary.public_session_ids_included,
|
|
1133
|
+
public_project_paths_included: profile.privacy_boundary.public_project_paths_included
|
|
1134
|
+
}
|
|
1135
|
+
};
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
export function renderAgentContextMarkdown(profile, localeBundle) {
|
|
1139
|
+
const t = (key) => localeBundle.ui?.[key] || key;
|
|
1140
|
+
const context = renderAgentContextJson(profile);
|
|
1141
|
+
return `# AgentRecord Agent Context Pack
|
|
1142
|
+
|
|
1143
|
+
Generated: ${profile.generated_at}
|
|
1144
|
+
Owner: ${profile.owner.display_name}
|
|
1145
|
+
Locale: ${profile.report.locale}
|
|
1146
|
+
|
|
1147
|
+
This context pack is a compact, public-safe summary for future agents. It does not include raw traces, private project details, raw session IDs, terminal output, source bodies, or secret-like values.
|
|
1148
|
+
|
|
1149
|
+
## Work Identity
|
|
1150
|
+
|
|
1151
|
+
${profile.work_identity.primary_label}
|
|
1152
|
+
|
|
1153
|
+
${profile.work_identity.summary}
|
|
1154
|
+
|
|
1155
|
+
Strongest evidence-backed claim: ${profile.work_identity.strongest_claim}
|
|
1156
|
+
|
|
1157
|
+
Confidence: ${profile.work_identity.confidence}
|
|
1158
|
+
|
|
1159
|
+
Evidence IDs: ${profile.work_identity.evidence_ids.join(", ") || "none"}
|
|
1160
|
+
|
|
1161
|
+
## Collaboration Style
|
|
1162
|
+
|
|
1163
|
+
${context.collaboration_style.map((item) => `- ${item}`).join("\n")}
|
|
1164
|
+
|
|
1165
|
+
## Verification Preferences
|
|
1166
|
+
|
|
1167
|
+
${context.verification_preferences.map((item) => `- ${item}`).join("\n")}
|
|
1168
|
+
|
|
1169
|
+
## Scope Control
|
|
1170
|
+
|
|
1171
|
+
${context.scope_control.map((item) => `- ${item}`).join("\n")}
|
|
1172
|
+
|
|
1173
|
+
## Handoff Preferences
|
|
1174
|
+
|
|
1175
|
+
${context.handoff_preferences.map((item) => `- ${item}`).join("\n")}
|
|
1176
|
+
|
|
1177
|
+
## ${t("role_signals")}
|
|
1178
|
+
|
|
1179
|
+
${context.role_signals.map((role) => `- ${role.label}: ${role.band}, ${role.confidence}. Evidence mix: ${role.evidence_mix}. Evidence: ${role.evidence_ids.join(", ") || "none"}`).join("\n")}
|
|
1180
|
+
|
|
1181
|
+
## ${t("ability_model")}
|
|
1182
|
+
|
|
1183
|
+
${context.ability_model.map((ability) => `- ${ability.label}: ${ability.band}, ${ability.confidence}. Evidence mix: ${ability.evidence_mix}. Evidence: ${ability.evidence_ids.join(", ") || "none"}`).join("\n")}
|
|
1184
|
+
|
|
1185
|
+
## Evidence Summary
|
|
1186
|
+
|
|
1187
|
+
${context.evidence_summary.map((card) => `- ${card.evidence_id}: ${card.title}. ${card.level.join(" / ")} · ${card.confidence}. ${card.summary}`).join("\n")}
|
|
1188
|
+
|
|
1189
|
+
## ${t("calibration")}
|
|
1190
|
+
|
|
1191
|
+
${profile.calibration_notes.map((note) => `- ${note.severity}: ${note.summary}`).join("\n")}
|
|
1192
|
+
|
|
1193
|
+
## ${t("privacy_boundary")}
|
|
1194
|
+
|
|
1195
|
+
${t("public_safe")}
|
|
1196
|
+
`;
|
|
1197
|
+
}
|
|
1198
|
+
|
|
1199
|
+
export function renderRedactionReport(profile, localeBundle) {
|
|
1200
|
+
const t = (key) => localeBundle.ui?.[key] || key;
|
|
1201
|
+
return `# Redaction Report
|
|
1202
|
+
|
|
1203
|
+
Generated: ${profile.generated_at}
|
|
1204
|
+
Owner: ${profile.owner.display_name}
|
|
1205
|
+
|
|
1206
|
+
## Included
|
|
1207
|
+
|
|
1208
|
+
- Aggregate Codex session counts.
|
|
1209
|
+
- Aggregate token activity.
|
|
1210
|
+
- Codex account-level token usage when available through the local Codex CLI app-server.
|
|
1211
|
+
- Redacted project references.
|
|
1212
|
+
- Public evidence IDs and public-safe summaries.
|
|
1213
|
+
- Evidence refs at summary level.
|
|
1214
|
+
|
|
1215
|
+
## Excluded
|
|
1216
|
+
|
|
1217
|
+
${profile.privacy_boundary.excluded_from_public_artifacts.map((item) => `- ${item}`).join("\n")}
|
|
1218
|
+
|
|
1219
|
+
## Boundary
|
|
1220
|
+
|
|
1221
|
+
${t("public_safe")}
|
|
1222
|
+
|
|
1223
|
+
${t("not_hiring")}
|
|
1224
|
+
`;
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
export function renderRunReport(profile, localeBundle) {
|
|
1228
|
+
const t = (key) => localeBundle.ui?.[key] || key;
|
|
1229
|
+
const run = profile.run_metadata;
|
|
1230
|
+
const codex = profile.agent_ledger.clients.find((client) => client.client_id === "codex") || {};
|
|
1231
|
+
const accountUsage = codex.account_usage || {};
|
|
1232
|
+
const deltaStatus = run.changed_sessions_this_run === 0
|
|
1233
|
+
? "no significant delta"
|
|
1234
|
+
: run.new_sessions_this_run > 0
|
|
1235
|
+
? "new local sessions detected"
|
|
1236
|
+
: "existing local sessions updated; this can happen when an active session continues accumulating token metadata";
|
|
1237
|
+
return `# AgentRecord Run Report
|
|
1238
|
+
|
|
1239
|
+
Generated: ${profile.generated_at}
|
|
1240
|
+
|
|
1241
|
+
## ${t("run_metadata")}
|
|
1242
|
+
|
|
1243
|
+
- Mode: ${run.mode}
|
|
1244
|
+
- Run count: ${run.run_count}
|
|
1245
|
+
- Previous generated at: ${run.previous_generated_at || "none"}
|
|
1246
|
+
- Reset requested: ${run.reset ? "yes" : "no"}
|
|
1247
|
+
- New sessions this run: ${run.new_sessions_this_run}
|
|
1248
|
+
- Updated sessions this run: ${run.updated_sessions_this_run}
|
|
1249
|
+
- Changed sessions this run: ${run.changed_sessions_this_run}
|
|
1250
|
+
- Delta status: ${deltaStatus}
|
|
1251
|
+
- Token delta this run: ${run.token_delta_this_run.total_tokens}
|
|
1252
|
+
- Total sessions seen: ${run.total_sessions_seen}
|
|
1253
|
+
- Total token-accounted sessions seen: ${run.total_token_sessions_seen}
|
|
1254
|
+
- Codex account usage: ${accountUsage.status || "unavailable"}${accountUsage.status_reason ? ` (${accountUsage.status_reason})` : ""}
|
|
1255
|
+
- Public session IDs included: ${run.public_session_ids_included ? "yes" : "no"}
|
|
1256
|
+
- Private state present: ${run.private_state_present ? "yes" : "no"}
|
|
1257
|
+
|
|
1258
|
+
## Privacy
|
|
1259
|
+
|
|
1260
|
+
Public artifacts do not include raw session IDs or raw local trace paths.
|
|
1261
|
+
`;
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
function formatPublicRef(ref) {
|
|
1265
|
+
if (ref.type === "memory") return `${ref.source}:${ref.start_line}-${ref.end_line}`;
|
|
1266
|
+
return ref.source || ref.type || "ref";
|
|
1267
|
+
}
|