synergyspec-selfevolving 1.4.0 → 2.1.0
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 +31 -18
- package/dist/commands/learn.d.ts +12 -1
- package/dist/commands/learn.js +158 -11
- package/dist/commands/self-evolution-episode.d.ts +177 -0
- package/dist/commands/self-evolution-episode.js +431 -0
- package/dist/commands/self-evolution.d.ts +12 -190
- package/dist/commands/self-evolution.js +114 -866
- package/dist/core/archive.d.ts +0 -1
- package/dist/core/archive.js +0 -58
- package/dist/core/artifact-graph/instruction-loader.d.ts +2 -4
- package/dist/core/artifact-graph/instruction-loader.js +3 -31
- package/dist/core/fitness/loss.d.ts +5 -5
- package/dist/core/fitness/loss.js +4 -4
- package/dist/core/fitness/test-failures.js +10 -2
- package/dist/core/project-config.d.ts +19 -0
- package/dist/core/project-config.js +96 -0
- package/dist/core/self-evolution/candidate-fitness.d.ts +23 -1
- package/dist/core/self-evolution/candidate-fitness.js +31 -5
- package/dist/core/self-evolution/candidates.d.ts +0 -9
- package/dist/core/self-evolution/critic-agent.d.ts +192 -0
- package/dist/core/self-evolution/critic-agent.js +568 -0
- package/dist/core/self-evolution/edits-contract.d.ts +53 -0
- package/dist/core/self-evolution/edits-contract.js +89 -0
- package/dist/core/self-evolution/episode-orchestrator.d.ts +234 -0
- package/dist/core/self-evolution/episode-orchestrator.js +681 -0
- package/dist/core/self-evolution/episode-store.d.ts +266 -0
- package/dist/core/self-evolution/episode-store.js +573 -0
- package/dist/core/self-evolution/evolution-switches.d.ts +1 -1
- package/dist/core/self-evolution/evolution-switches.js +5 -10
- package/dist/core/self-evolution/evolving-agent.d.ts +208 -0
- package/dist/core/self-evolution/evolving-agent.js +535 -0
- package/dist/core/self-evolution/host-harness.d.ts +14 -15
- package/dist/core/self-evolution/host-harness.js +48 -23
- package/dist/core/self-evolution/index.d.ts +11 -6
- package/dist/core/self-evolution/index.js +20 -6
- package/dist/core/self-evolution/line-diff.d.ts +60 -0
- package/dist/core/self-evolution/line-diff.js +130 -0
- package/dist/core/self-evolution/policy/fs-safe.d.ts +19 -0
- package/dist/core/self-evolution/policy/fs-safe.js +89 -0
- package/dist/core/self-evolution/policy/index.d.ts +13 -0
- package/dist/core/self-evolution/policy/index.js +13 -0
- package/dist/core/self-evolution/policy/policy-store.d.ts +217 -0
- package/dist/core/self-evolution/policy/policy-store.js +774 -0
- package/dist/core/self-evolution/policy/prediction-reconcile.d.ts +54 -0
- package/dist/core/self-evolution/policy/prediction-reconcile.js +191 -0
- package/dist/core/self-evolution/policy/reject-buffer.d.ts +55 -0
- package/dist/core/self-evolution/policy/reject-buffer.js +170 -0
- package/dist/core/self-evolution/promote.d.ts +1 -1
- package/dist/core/self-evolution/promote.js +6 -33
- package/dist/core/self-evolution/promotion.js +1 -2
- package/dist/core/self-evolution/reward-agent.d.ts +379 -0
- package/dist/core/self-evolution/reward-agent.js +940 -0
- package/dist/core/self-evolution/reward-aggregator.d.ts +59 -0
- package/dist/core/self-evolution/reward-aggregator.js +262 -0
- package/dist/core/self-evolution/scope-gate.d.ts +66 -0
- package/dist/core/self-evolution/scope-gate.js +107 -0
- package/dist/core/self-evolution/success-channel.js +2 -2
- package/dist/core/self-evolution/tamper-check.d.ts +24 -0
- package/dist/core/self-evolution/tamper-check.js +236 -0
- package/dist/core/self-evolution/tool-evolution.js +2 -13
- package/dist/core/self-evolution/verdict.d.ts +8 -5
- package/dist/core/self-evolution/verdict.js +4 -7
- package/dist/core/templates/workflows/gen-tests.js +1 -1
- package/dist/core/templates/workflows/learn.d.ts +3 -2
- package/dist/core/templates/workflows/learn.js +21 -18
- package/dist/core/templates/workflows/self-evolving.d.ts +6 -4
- package/dist/core/templates/workflows/self-evolving.js +62 -172
- package/dist/core/trajectory/scrub.d.ts +27 -0
- package/dist/core/trajectory/scrub.js +79 -0
- package/dist/core/trajectory/skeleton.d.ts +27 -1
- package/dist/core/trajectory/skeleton.js +152 -8
- package/dist/dashboard/data.d.ts +25 -51
- package/dist/dashboard/data.js +68 -180
- package/dist/dashboard/react-client.js +458 -503
- package/dist/dashboard/react-styles.js +3 -3
- package/dist/dashboard/server.js +23 -17
- package/dist/ui/ascii-patterns.d.ts +7 -15
- package/dist/ui/ascii-patterns.js +123 -54
- package/dist/ui/welcome-screen.d.ts +0 -14
- package/dist/ui/welcome-screen.js +16 -35
- package/package.json +1 -1
- package/dist/core/self-evolution/ga-selection.d.ts +0 -94
- package/dist/core/self-evolution/ga-selection.js +0 -153
- package/dist/core/self-evolution/proposer-agent.d.ts +0 -182
- package/dist/core/self-evolution/proposer-agent.js +0 -326
- package/dist/core/self-evolution/replay-runner.d.ts +0 -100
- package/dist/core/self-evolution/replay-runner.js +0 -170
- package/dist/core/self-evolution/replay.d.ts +0 -45
- package/dist/core/self-evolution/replay.js +0 -56
- package/dist/core/self-evolution/template-variants.d.ts +0 -62
- package/dist/core/self-evolution/template-variants.js +0 -171
- package/dist/core/self-evolution/trajectory.d.ts +0 -65
- package/dist/core/self-evolution/trajectory.js +0 -185
|
@@ -14,8 +14,9 @@ export const dashboardClientScript = String.raw `
|
|
|
14
14
|
changes: '/api/changes',
|
|
15
15
|
cliHistory: '/api/cli-history?limit=200',
|
|
16
16
|
agentInterface: '/api/agent-interface',
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
episodes: '/api/episodes',
|
|
18
|
+
policyLedger: '/api/policy/ledger',
|
|
19
|
+
rejectBuffer: '/api/reject-buffer',
|
|
19
20
|
architecture: '/api/architecture',
|
|
20
21
|
history: '/api/history',
|
|
21
22
|
codeAgent: '/api/code-agent',
|
|
@@ -90,18 +91,18 @@ export const dashboardClientScript = String.raw `
|
|
|
90
91
|
en: 'Verification finds the gaps. Learn proposes durable rules. With your approval, those rules become the next change\'s pre-flight check.',
|
|
91
92
|
zh: '校验定位缺口;学习阶段提出可固化的规则;经你审核后,这些规则成为下一次变更的飞行前检查。'
|
|
92
93
|
},
|
|
93
|
-
'intro.selfevo.col3.title': { en: '
|
|
94
|
+
'intro.selfevo.col3.title': { en: 'Loop promotes carefully', zh: '闭环谨慎晋升' },
|
|
94
95
|
'intro.selfevo.col3.body': {
|
|
95
|
-
en: 'The
|
|
96
|
-
zh: '
|
|
96
|
+
en: 'The Self-Evolution Loop scores each change by graded advantage against a baseline arm, and rolls back before evolving on a bad result. Only changes with a positive advantage are kept.',
|
|
97
|
+
zh: '自演进闭环以分级优势(advantage)对照基线臂为每次改动打分,结果不佳时先回滚再演进。只有优势为正的改动才会被保留。'
|
|
97
98
|
},
|
|
98
99
|
'intro.selfevo.diag.gen': { en: 'GENERATION', zh: '代' },
|
|
99
100
|
'intro.selfevo.diag.change': { en: 'CHANGE', zh: '变更' },
|
|
100
101
|
'intro.selfevo.diag.memory': { en: 'MEMORY ACCUMULATES', zh: '记忆累积' },
|
|
101
102
|
'intro.selfevo.diag.leverage': { en: 'LEVERAGE PER CHANGE GROWS', zh: '单次杠杆增长' },
|
|
102
|
-
'intro.selfevo.stat.generations': { en: '
|
|
103
|
+
'intro.selfevo.stat.generations': { en: 'Policy versions', zh: '策略版本' },
|
|
103
104
|
'intro.selfevo.stat.entries': { en: 'Memory entries', zh: '记忆条目' },
|
|
104
|
-
'intro.selfevo.stat.candidates': { en: '
|
|
105
|
+
'intro.selfevo.stat.candidates': { en: 'Kept episodes', zh: '已保留回合' },
|
|
105
106
|
|
|
106
107
|
'intro.kpi.eyebrow': { en: 'Live signals', zh: '实时信号' },
|
|
107
108
|
'intro.kpi.title': { en: 'Where this workspace is, right now', zh: '此刻这个工作区在哪一步' },
|
|
@@ -190,9 +191,9 @@ export const dashboardClientScript = String.raw `
|
|
|
190
191
|
'intro.boundary.b2.label': { en: 'Reviewed learning', zh: '经审学习' },
|
|
191
192
|
'intro.boundary.b2.title': { en: 'learn previews, you approve', zh: 'learn 仅预览 · 你来审批' },
|
|
192
193
|
'intro.boundary.b2.body': { en: 'Memory candidates surface in the agent. Nothing silently rewrites prompts, templates, or skills.', zh: '记忆候选在智能体内浮现。没有任何东西会静默改写 prompt / 模板 / 技能。' },
|
|
193
|
-
'intro.boundary.b3.label': { en: '
|
|
194
|
+
'intro.boundary.b3.label': { en: 'Self-Evolution Loop', zh: '自演进闭环' },
|
|
194
195
|
'intro.boundary.b3.title': { en: 'maintainer-only self-evolution', zh: '仅维护者的自演进通道' },
|
|
195
|
-
'intro.boundary.b3.body': { en: '
|
|
196
|
+
'intro.boundary.b3.body': { en: 'Two-arm forward, graded advantage, and rollback-before-evolution — kept fully out of the normal loop.', zh: '双臂前向 · 分级优势 · 先回滚再演进——完全独立于日常循环。' },
|
|
196
197
|
|
|
197
198
|
'intro.commands.eyebrow': { en: 'Command surface', zh: '命令面' },
|
|
198
199
|
'intro.commands.title': { en: 'How to act, in any agent', zh: '在任何智能体里如何下指令' },
|
|
@@ -221,9 +222,9 @@ export const dashboardClientScript = String.raw `
|
|
|
221
222
|
'overview.hero.body': { en: 'Ask the Code Agent to check, explain, or modify code in this repo.', zh: '让 Code Agent 检查、解释或修改这个仓库里的代码。' },
|
|
222
223
|
'overview.hero.chip.changes': { en: 'explore active changes', zh: '了解活跃变更' },
|
|
223
224
|
'overview.hero.chip.trace': { en: 'view agent trace', zh: '查看智能体轨迹' },
|
|
224
|
-
'overview.hero.chip.runs': { en: 'study
|
|
225
|
+
'overview.hero.chip.runs': { en: 'study episodes', zh: '研究演进回合' },
|
|
225
226
|
'overview.eyebrow': { en: 'Latest dynamics', zh: '最新动态' },
|
|
226
|
-
'overview.subhead': { en: 'A live control plane for specs, agent traces, CLI history, and self-evolution
|
|
227
|
+
'overview.subhead': { en: 'A live control plane for specs, agent traces, CLI history, and self-evolution episodes.', zh: 'spec / 智能体轨迹 / CLI 历史 / 自演进回合的实时控制面板。' },
|
|
227
228
|
'overview.metric.active': { en: 'Active changes', zh: '进行中变更' },
|
|
228
229
|
'overview.metric.completed': { en: 'Completed specs', zh: '已完成 spec' },
|
|
229
230
|
'overview.metric.traceEvents': { en: 'Trace events', zh: '轨迹事件' },
|
|
@@ -235,22 +236,22 @@ export const dashboardClientScript = String.raw `
|
|
|
235
236
|
'overview.delta.streamConnected': { en: 'stream connected', zh: '数据流已连接' },
|
|
236
237
|
'overview.delta.streamIdle': { en: 'stream idle', zh: '数据流待机' },
|
|
237
238
|
'overview.delta.recentCli': { en: '{n} recent CLI events', zh: '近期 {n} 条 CLI 事件' },
|
|
238
|
-
'overview.delta.
|
|
239
|
+
'overview.delta.noEpisodes': { en: 'no episodes', zh: '暂无回合' },
|
|
239
240
|
'overview.section.recentChanges': { en: 'Recent changes', zh: '近期变更' },
|
|
240
241
|
'overview.section.agentTrace': { en: 'Agent trace', zh: '智能体轨迹' },
|
|
241
242
|
'overview.section.toolDistribution': { en: 'Tool distribution', zh: '工具分布' },
|
|
242
243
|
'overview.section.cliHistory': { en: 'CLI history', zh: 'CLI 历史' },
|
|
243
|
-
'overview.section.evoRuns': { en: '
|
|
244
|
+
'overview.section.evoRuns': { en: 'Self-evolution episodes', zh: '自演进回合' },
|
|
244
245
|
'overview.total': { en: '{n} total', zh: '共 {n} 项' },
|
|
245
246
|
'overview.events': { en: '{n} events', zh: '{n} 条事件' },
|
|
246
|
-
'overview.empty.noRuns': { en: 'No
|
|
247
|
-
'overview.empty.noRunsHint': { en: '
|
|
247
|
+
'overview.empty.noRuns': { en: 'No episodes', zh: '暂无回合' },
|
|
248
|
+
'overview.empty.noRunsHint': { en: 'self-evolution/episodes is empty', zh: 'self-evolution/episodes 为空' },
|
|
248
249
|
|
|
249
250
|
'interface.eyebrow': { en: 'Agent-native interface', zh: '智能体原生界面' },
|
|
250
251
|
'interface.title': { en: 'User interface for Claude Code, Codex, and OpenCode', zh: '面向 Claude Code · Codex · OpenCode 的用户界面' },
|
|
251
252
|
'interface.lead': { en: 'The user talks to slash commands in the coding agent. The CLI stays underneath as skill plumbing for status, artifact creation, validation, and archive operations.', zh: '用户通过编码智能体里的斜杠命令交互。CLI 作为底层管线,承担状态查询、文件创建、校验与归档。' },
|
|
252
253
|
'interface.hero.title': { en: 'One product surface, tool-native command syntax.', zh: '一套产品界面 · 各家工具的原生命令语法。' },
|
|
253
|
-
'interface.hero.body': { en: 'SynergySpec-SelfEvolving should feel like an agent workflow: plan the change, build it, review it, learn from it, and archive it. Advanced self-evolution remains in the
|
|
254
|
+
'interface.hero.body': { en: 'SynergySpec-SelfEvolving should feel like an agent workflow: plan the change, build it, review it, learn from it, and archive it. Advanced self-evolution remains in the Self-Evolution Loop.', zh: 'SynergySpec-SelfEvolving 应当像智能体工作流:规划变更 · 构建 · 审阅 · 学习 · 归档。进阶的自演进保留在自演进闭环。' },
|
|
254
255
|
'interface.chip.openChanges': { en: 'open changes', zh: '未结变更' },
|
|
255
256
|
'interface.chip.readyApply': { en: 'ready to apply', zh: '可实施' },
|
|
256
257
|
'interface.chip.readyReview': { en: 'ready to review', zh: '可审阅' },
|
|
@@ -308,18 +309,19 @@ export const dashboardClientScript = String.raw `
|
|
|
308
309
|
|
|
309
310
|
'evolve.eyebrow': { en: 'Self-evolution console', zh: '自演进控制台' },
|
|
310
311
|
'evolve.title': { en: 'SynergySpec-SelfEvolving', zh: 'SynergySpec-SelfEvolving' },
|
|
311
|
-
'evolve.lead': { en: '
|
|
312
|
-
'evolve.chip.
|
|
313
|
-
'evolve.chip.
|
|
314
|
-
'evolve.metric.
|
|
315
|
-
'evolve.metric.candidates': { en: '
|
|
316
|
-
'evolve.metric.candidates.detailEmpty': { en: 'no
|
|
317
|
-
'evolve.metric.candidates.detail': { en: '{p}
|
|
318
|
-
'evolve.metric.
|
|
319
|
-
'evolve.section.history': { en: 'Evolution
|
|
320
|
-
'evolve.section.lineage': { en: '
|
|
321
|
-
'evolve.
|
|
322
|
-
'evolve.
|
|
312
|
+
'evolve.lead': { en: 'Episodes, two-arm forward advantage, policy version ledger, and the reject-buffer in one console.', zh: '回合 · 双臂前向优势 · 策略版本账本 · 否决缓冲,全在一个控制台。' },
|
|
313
|
+
'evolve.chip.episodes': { en: 'episodes', zh: '回合数' },
|
|
314
|
+
'evolve.chip.version': { en: 'policy version', zh: '策略版本' },
|
|
315
|
+
'evolve.metric.latestStage': { en: 'Latest stage', zh: '最新阶段' },
|
|
316
|
+
'evolve.metric.candidates': { en: 'Kept episodes', zh: '已保留回合' },
|
|
317
|
+
'evolve.metric.candidates.detailEmpty': { en: 'no kept episodes', zh: '暂无已保留回合' },
|
|
318
|
+
'evolve.metric.candidates.detail': { en: '{p} mean advantage', zh: '平均优势 {p}' },
|
|
319
|
+
'evolve.metric.waitingEpisodes': { en: 'waiting for episodes', zh: '等待回合' },
|
|
320
|
+
'evolve.section.history': { en: 'Evolution episodes', zh: '自演进回合' },
|
|
321
|
+
'evolve.section.lineage': { en: 'Policy version ledger', zh: '策略版本账本' },
|
|
322
|
+
'evolve.section.rejectBuffer': { en: 'Reject-buffer', zh: '否决缓冲' },
|
|
323
|
+
'evolve.episodes.label': { en: '{n} episodes', zh: '{n} 个回合' },
|
|
324
|
+
'evolve.ledger.label': { en: 'v{n}', zh: '第 {n} 版' },
|
|
323
325
|
|
|
324
326
|
'learn.eyebrow': { en: 'Skill · review & extract', zh: '技能 · 审阅与提炼' },
|
|
325
327
|
'learn.title': { en: 'Learn — close the loop after verify, before archive', zh: 'Learn — 校验之后、归档之前的闭环' },
|
|
@@ -566,16 +568,16 @@ export const dashboardClientScript = String.raw `
|
|
|
566
568
|
'common.noChange': { en: 'No change', zh: '无变更' },
|
|
567
569
|
'common.openDetail': { en: 'Open detail', zh: '查看详情' },
|
|
568
570
|
'common.openLatest': { en: 'Open latest', zh: '打开最新' },
|
|
569
|
-
'common.noRun': { en: 'No
|
|
571
|
+
'common.noRun': { en: 'No episode', zh: '无回合' },
|
|
570
572
|
'common.copyCommand': { en: 'Copy command', zh: '复制命令' },
|
|
571
573
|
'common.copied': { en: 'Copied', zh: '已复制' },
|
|
572
574
|
'common.copyFailed': { en: 'Copy failed', zh: '复制失败' },
|
|
573
575
|
'common.nextAction': { en: 'Next action', zh: '下一步操作' },
|
|
574
|
-
'common.nextAction.runLab': { en: 'Run
|
|
575
|
-
'common.nextAction.inspect': { en: 'Inspect the latest
|
|
576
|
+
'common.nextAction.runLab': { en: 'Run an episode to create graded evidence.', zh: '运行一个回合以生成评级证据。' },
|
|
577
|
+
'common.nextAction.inspect': { en: 'Inspect the latest rolled-back episode.', zh: '检查最近被回滚的回合。' },
|
|
576
578
|
'common.loading': { en: 'Loading dashboard data', zh: '加载控制台数据中' },
|
|
577
|
-
'common.
|
|
578
|
-
'common.
|
|
579
|
+
'common.targetDefault': { en: 'default target', zh: '默认目标' },
|
|
580
|
+
'common.target': { en: 'target {id}', zh: '目标 {id}' },
|
|
579
581
|
|
|
580
582
|
'nav.design': { en: 'Design', zh: '设计' },
|
|
581
583
|
|
|
@@ -713,8 +715,8 @@ export const dashboardClientScript = String.raw `
|
|
|
713
715
|
'arch.metric.surfaces.delta': { en: '{n} live', zh: '{n} 个在线' },
|
|
714
716
|
'arch.metric.traceEvents': { en: 'Trace events', zh: '轨迹事件' },
|
|
715
717
|
'arch.metric.traceEvents.delta': { en: '{n} decisions', zh: '{n} 项决策' },
|
|
716
|
-
'arch.metric.runs': { en: '
|
|
717
|
-
'arch.metric.runs.delta': { en: 'no
|
|
718
|
+
'arch.metric.runs': { en: 'Episodes', zh: '回合' },
|
|
719
|
+
'arch.metric.runs.delta': { en: 'no stage yet', zh: '尚无阶段' },
|
|
718
720
|
|
|
719
721
|
'arch.model.eyebrow': { en: 'The model', zh: '模型' },
|
|
720
722
|
'arch.model.title': { en: '4+1 mapped onto this workspace', zh: '4+1 映射到本工作区' },
|
|
@@ -726,7 +728,7 @@ export const dashboardClientScript = String.raw `
|
|
|
726
728
|
|
|
727
729
|
'arch.process.tag': { en: 'Process view', zh: '过程视图' },
|
|
728
730
|
'arch.process.title': { en: 'Runtime loop', zh: '运行时循环' },
|
|
729
|
-
'arch.process.lead': { en: 'What happens at runtime: trace events, recorded decisions,
|
|
731
|
+
'arch.process.lead': { en: 'What happens at runtime: trace events, recorded decisions, test runs, and the tools the agent actually exercises.', zh: '运行时发生了什么:轨迹事件、记录的决策、测试运行,以及智能体实际调用的工具。' },
|
|
730
732
|
|
|
731
733
|
'arch.development.tag': { en: 'Development view', zh: '开发视图' },
|
|
732
734
|
'arch.development.title': { en: 'Module structure', zh: '模块结构' },
|
|
@@ -833,72 +835,72 @@ export const dashboardClientScript = String.raw `
|
|
|
833
835
|
|
|
834
836
|
const evolutionPhases = [
|
|
835
837
|
{
|
|
836
|
-
key: '
|
|
838
|
+
key: 'forward',
|
|
837
839
|
icon: '01',
|
|
838
|
-
title: '
|
|
839
|
-
detail: '
|
|
840
|
-
evolves: '
|
|
841
|
-
evidence: ['
|
|
840
|
+
title: 'Two-arm forward',
|
|
841
|
+
detail: 'Run the main agent (vN+1) alongside the critic baseline (vN) on the same task.',
|
|
842
|
+
evolves: 'Paired episode trajectory',
|
|
843
|
+
evidence: ['Main-arm trace', 'Baseline-arm trace', 'Run summaries']
|
|
842
844
|
},
|
|
843
845
|
{
|
|
844
|
-
key: '
|
|
846
|
+
key: 'reward',
|
|
845
847
|
icon: '02',
|
|
846
|
-
title: '
|
|
847
|
-
detail: '
|
|
848
|
-
evolves: '
|
|
849
|
-
evidence: ['
|
|
848
|
+
title: 'Reward / advantage',
|
|
849
|
+
detail: 'The reward agent scores each arm; advantage = reward(main) - reward(baseline).',
|
|
850
|
+
evolves: 'Graded advantage signal',
|
|
851
|
+
evidence: ['Reward(main)', 'Reward(baseline)', 'Advantage']
|
|
850
852
|
},
|
|
851
853
|
{
|
|
852
|
-
key: '
|
|
854
|
+
key: 'rollback',
|
|
853
855
|
icon: '03',
|
|
854
|
-
title: '
|
|
855
|
-
detail: '
|
|
856
|
-
evolves: '
|
|
857
|
-
evidence: ['
|
|
856
|
+
title: 'Rollback first',
|
|
857
|
+
detail: 'On bad advantage, roll back the change and push it to the reject-buffer before any edit.',
|
|
858
|
+
evolves: 'Reject-buffer',
|
|
859
|
+
evidence: ['Advantage sign', 'Revert checkpoint', 'Reject-buffer entry']
|
|
858
860
|
},
|
|
859
861
|
{
|
|
860
|
-
key: '
|
|
862
|
+
key: 'evolve',
|
|
861
863
|
icon: '04',
|
|
862
|
-
title: '
|
|
863
|
-
detail: '
|
|
864
|
-
evolves: '
|
|
865
|
-
evidence: ['Typecheck/lint', '
|
|
864
|
+
title: 'Evolving agent',
|
|
865
|
+
detail: 'On good advantage, the evolving agent makes one bounded edit (<= L) to the policy.',
|
|
866
|
+
evolves: 'Bounded policy edit',
|
|
867
|
+
evidence: ['Typecheck/lint', 'Edit budget L', 'Round-trip revert']
|
|
866
868
|
},
|
|
867
869
|
{
|
|
868
|
-
key: '
|
|
870
|
+
key: 'writeback',
|
|
869
871
|
icon: '05',
|
|
870
|
-
title: '
|
|
871
|
-
detail: '
|
|
872
|
-
evolves: '
|
|
873
|
-
evidence: ['
|
|
872
|
+
title: 'Write-back',
|
|
873
|
+
detail: 'Commit the kept edit and its verdict to the policy and the version ledger.',
|
|
874
|
+
evolves: 'Policy + ledger',
|
|
875
|
+
evidence: ['Policy diff', 'Version ledger', 'Verdict record']
|
|
874
876
|
}
|
|
875
877
|
];
|
|
876
878
|
|
|
877
879
|
const selfEvolvingConsoleRows = [
|
|
878
880
|
{
|
|
879
|
-
step: '
|
|
880
|
-
does: '
|
|
881
|
-
evolves: '
|
|
881
|
+
step: 'Two-arm forward',
|
|
882
|
+
does: 'Run the main agent (candidate vN+1) alongside the critic baseline (vN) on the same task',
|
|
883
|
+
evolves: 'Paired episode trajectory'
|
|
882
884
|
},
|
|
883
885
|
{
|
|
884
|
-
step: '
|
|
885
|
-
does: '
|
|
886
|
-
evolves: '
|
|
886
|
+
step: 'Reward / advantage',
|
|
887
|
+
does: 'The reward agent scores each arm; advantage = reward(main) - reward(baseline)',
|
|
888
|
+
evolves: 'Graded advantage signal'
|
|
887
889
|
},
|
|
888
890
|
{
|
|
889
|
-
step: '
|
|
890
|
-
does: '
|
|
891
|
-
evolves: '
|
|
891
|
+
step: 'Rollback first',
|
|
892
|
+
does: 'On bad advantage, roll back the change and push it to the reject-buffer before any edit',
|
|
893
|
+
evolves: 'Reject-buffer'
|
|
892
894
|
},
|
|
893
895
|
{
|
|
894
|
-
step: '
|
|
895
|
-
does: '
|
|
896
|
-
evolves: '
|
|
896
|
+
step: 'Evolving agent',
|
|
897
|
+
does: 'On good advantage, the evolving agent makes one bounded edit (<= L) to the policy',
|
|
898
|
+
evolves: 'Bounded policy edit'
|
|
897
899
|
},
|
|
898
900
|
{
|
|
899
|
-
step: '
|
|
900
|
-
does: '
|
|
901
|
-
evolves: '
|
|
901
|
+
step: 'Write-back',
|
|
902
|
+
does: 'Commit the kept edit and its verdict to the policy and the version ledger',
|
|
903
|
+
evolves: 'Policy + ledger'
|
|
902
904
|
}
|
|
903
905
|
];
|
|
904
906
|
|
|
@@ -1015,8 +1017,8 @@ export const dashboardClientScript = String.raw `
|
|
|
1015
1017
|
detail: 'Learn previews memory candidates. It does not silently rewrite prompts, templates, or skills.'
|
|
1016
1018
|
},
|
|
1017
1019
|
{
|
|
1018
|
-
title: '
|
|
1019
|
-
detail: 'Raw self-evolution is a maintainer workflow
|
|
1020
|
+
title: 'Self-Evolution Loop',
|
|
1021
|
+
detail: 'Raw self-evolution is a maintainer workflow: two-arm forward, graded advantage, and rollback-before-evolution.'
|
|
1020
1022
|
}
|
|
1021
1023
|
];
|
|
1022
1024
|
|
|
@@ -1061,7 +1063,7 @@ export const dashboardClientScript = String.raw `
|
|
|
1061
1063
|
try {
|
|
1062
1064
|
if (console.groupCollapsed) {
|
|
1063
1065
|
console.groupCollapsed('%cSynergySpec-SelfEvolving%c browser console map', titleStyle, mutedStyle);
|
|
1064
|
-
console.log('%cPurpose%c
|
|
1066
|
+
console.log('%cPurpose%c Self-evolution loop v2 (in-context RL) over SynergySpec-SelfEvolving itself; no automatic promotion.', labelStyle, bodyStyle);
|
|
1065
1067
|
console.log('%cNormal loop%c propose -> apply -> verify -> learn -> archive stays the user workflow.', labelStyle, bodyStyle);
|
|
1066
1068
|
if (console.table) {
|
|
1067
1069
|
console.table(selfEvolvingConsoleRows);
|
|
@@ -1070,18 +1072,18 @@ export const dashboardClientScript = String.raw `
|
|
|
1070
1072
|
console.log(String(index + 1) + '. ' + row.step + ' - ' + row.does + ' [' + row.evolves + ']');
|
|
1071
1073
|
});
|
|
1072
1074
|
}
|
|
1073
|
-
console.log('%cEvolvable surface%c templates, archive memory, runtime memory, task decomposition, alignment verifier, tool guard
|
|
1074
|
-
console.log('%cBoundary%c Browser dashboard observes and explains.
|
|
1075
|
+
console.log('%cEvolvable surface%c templates, archive memory, runtime memory, task decomposition, alignment verifier, tool guard.', labelStyle, bodyStyle);
|
|
1076
|
+
console.log('%cBoundary%c Browser dashboard observes and explains. Evolution is gated by a graded advantage with rollback-before-evolution.', labelStyle, bodyStyle);
|
|
1075
1077
|
if (console.groupEnd) console.groupEnd();
|
|
1076
1078
|
return;
|
|
1077
1079
|
}
|
|
1078
1080
|
|
|
1079
1081
|
console.log([
|
|
1080
1082
|
'SynergySpec-SelfEvolving',
|
|
1081
|
-
'Purpose:
|
|
1082
|
-
'Loop:
|
|
1083
|
-
'Surface: templates, archive memory, runtime memory, task decomposition, alignment verifier, tool guard
|
|
1084
|
-
'Boundary: browser dashboard observes and explains;
|
|
1083
|
+
'Purpose: Self-evolution loop v2 (in-context RL) over SynergySpec-SelfEvolving itself; no automatic promotion.',
|
|
1084
|
+
'Loop: two-arm forward -> reward agent scores (advantage) -> rollback-before-evolution -> evolving agent.',
|
|
1085
|
+
'Surface: templates, archive memory, runtime memory, task decomposition, alignment verifier, tool guard.',
|
|
1086
|
+
'Boundary: browser dashboard observes and explains; evolution is gated by a graded advantage with rollback-before-evolution.'
|
|
1085
1087
|
].join('\n'));
|
|
1086
1088
|
} catch {}
|
|
1087
1089
|
}
|
|
@@ -1243,67 +1245,55 @@ export const dashboardClientScript = String.raw `
|
|
|
1243
1245
|
return 'muted';
|
|
1244
1246
|
}
|
|
1245
1247
|
|
|
1246
|
-
function
|
|
1247
|
-
|
|
1248
|
-
if (run.passRate !== undefined) return normalizeRate(run.passRate);
|
|
1249
|
-
const counts = safeObject(run.verdictCounts);
|
|
1250
|
-
const entries = Object.entries(counts);
|
|
1251
|
-
const total = entries.reduce(function (sum, entry) {
|
|
1252
|
-
return sum + numberOr(entry[1], 0);
|
|
1253
|
-
}, 0);
|
|
1254
|
-
if (!total) return 0;
|
|
1255
|
-
const passed = entries.reduce(function (sum, entry) {
|
|
1256
|
-
const key = String(entry[0]).toLowerCase();
|
|
1257
|
-
return key.includes('pass') || key.includes('success') ? sum + numberOr(entry[1], 0) : sum;
|
|
1258
|
-
}, 0);
|
|
1259
|
-
return passed / total;
|
|
1248
|
+
function episodeAdvantage(ep) {
|
|
1249
|
+
return ep && typeof ep.advantage === 'number' ? ep.advantage : null;
|
|
1260
1250
|
}
|
|
1261
1251
|
|
|
1262
|
-
function
|
|
1263
|
-
|
|
1264
|
-
const counts = safeObject(run.verdictCounts);
|
|
1265
|
-
return Object.keys(counts).some(function (key) { return numberOr(counts[key], 0) > 0; });
|
|
1252
|
+
function formatAdvantage(a) {
|
|
1253
|
+
return a == null ? 'n/a' : (a >= 0 ? '+' : '') + Number(a).toFixed(2);
|
|
1266
1254
|
}
|
|
1267
1255
|
|
|
1268
|
-
function
|
|
1269
|
-
|
|
1256
|
+
function advantageTone(ep) {
|
|
1257
|
+
const a = episodeAdvantage(ep);
|
|
1258
|
+
return a == null ? 'muted' : a > 0 ? 'good' : a < 0 ? 'bad' : 'info';
|
|
1270
1259
|
}
|
|
1271
1260
|
|
|
1272
|
-
function
|
|
1273
|
-
return
|
|
1274
|
-
const verdict = runVerdict(run);
|
|
1275
|
-
return verdict.tone !== 'bad' && runScore(run) > 0;
|
|
1276
|
-
});
|
|
1261
|
+
function hasGradedAdvantage(ep) {
|
|
1262
|
+
return !!ep && ep.advantage != null;
|
|
1277
1263
|
}
|
|
1278
1264
|
|
|
1279
|
-
function
|
|
1280
|
-
|
|
1281
|
-
if (run.failureReasonSummary) return run.failureReasonSummary;
|
|
1282
|
-
const verdict = runVerdict(run);
|
|
1283
|
-
if (verdict.tone === 'bad') return verdict.label;
|
|
1284
|
-
if (run.status === 'empty') return 'Run directory exists, but no summary or task evidence was found';
|
|
1285
|
-
if (run.status === 'pending') return 'Run has files but no completed summary yet';
|
|
1286
|
-
return 'No blocking issue detected';
|
|
1265
|
+
function gradedEpisodes(eps) {
|
|
1266
|
+
return safeArray(eps).filter(hasGradedAdvantage);
|
|
1287
1267
|
}
|
|
1288
1268
|
|
|
1289
|
-
function
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
const counts = safeObject(run && run.verdictCounts);
|
|
1293
|
-
const entries = Object.entries(counts).filter(function (entry) {
|
|
1294
|
-
return numberOr(entry[1], 0) > 0;
|
|
1269
|
+
function keptEpisodes(eps) {
|
|
1270
|
+
return safeArray(eps).filter(function (ep) {
|
|
1271
|
+
return ep.stage === 'kept' || ep.stage === 'evolved';
|
|
1295
1272
|
});
|
|
1296
|
-
if (!entries.length) return { label: 'pending', tone: 'muted' };
|
|
1297
|
-
const bad = entries.some(function (entry) { return isFailure(entry[0]); });
|
|
1298
|
-
const pass = entries.some(function (entry) { return String(entry[0]).toLowerCase().includes('pass'); });
|
|
1299
|
-
return {
|
|
1300
|
-
label: entries.map(function (entry) { return entry[0] + ' ' + entry[1]; }).join(', '),
|
|
1301
|
-
tone: bad ? 'bad' : pass ? 'good' : 'info'
|
|
1302
|
-
};
|
|
1303
1273
|
}
|
|
1304
1274
|
|
|
1305
|
-
function
|
|
1306
|
-
|
|
1275
|
+
function episodeBlocker(ep) {
|
|
1276
|
+
if (!ep) return 'No episode yet';
|
|
1277
|
+
if (ep.stage === 'evolution-refused') return ep.baselineSkippedReason || 'Evolution refused';
|
|
1278
|
+
if (ep.stage === 'rolled-back') return 'Rolled back to reject-buffer';
|
|
1279
|
+
if (ep.stage === 'abstained') return 'Reward agent abstained';
|
|
1280
|
+
return 'No blocker';
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1283
|
+
function episodeVerdict(ep) {
|
|
1284
|
+
const stage = ep && ep.stage ? ep.stage : 'pending';
|
|
1285
|
+
const tone = stage === 'kept' || stage === 'evolved'
|
|
1286
|
+
? 'good'
|
|
1287
|
+
: stage === 'rolled-back' || stage === 'evolution-refused'
|
|
1288
|
+
? 'bad'
|
|
1289
|
+
: stage === 'abstained' || stage === 'baseline-skipped'
|
|
1290
|
+
? 'muted'
|
|
1291
|
+
: 'info';
|
|
1292
|
+
return { label: stage, tone: tone };
|
|
1293
|
+
}
|
|
1294
|
+
|
|
1295
|
+
function episodeTime(ep) {
|
|
1296
|
+
return (ep && (ep.updatedAt || ep.createdAt)) || '';
|
|
1307
1297
|
}
|
|
1308
1298
|
|
|
1309
1299
|
async function loadEndpoint(url, fallback) {
|
|
@@ -1408,25 +1398,24 @@ export const dashboardClientScript = String.raw `
|
|
|
1408
1398
|
" philosophy: fluid, not phase-gated — revisit any artifact anytime."
|
|
1409
1399
|
].join("\n");
|
|
1410
1400
|
const DIAGRAM_OUTER_LOOP = [
|
|
1411
|
-
"
|
|
1412
|
-
" │",
|
|
1413
|
-
" ▼ runGeneration() × N generations (or until USD budget)",
|
|
1401
|
+
" synergyspec-selfevolving self-evolution episode (in-context RL, one episode)",
|
|
1414
1402
|
" │",
|
|
1415
|
-
" ①
|
|
1403
|
+
" ① 主智能体 MAIN AGENT (policy vN+1) ∥ CRITIC AGENT 基线智能体 (reruns vN)",
|
|
1404
|
+
" │ same change · isolated worktree · 产物即弃",
|
|
1405
|
+
" ▼",
|
|
1406
|
+
" ② 磁盘 DISK episode store (transcripts × both arms)",
|
|
1416
1407
|
" │",
|
|
1417
|
-
"
|
|
1418
|
-
" │
|
|
1419
|
-
" │
|
|
1408
|
+
" ③ 奖励智能体 REWARD AGENT (LLM judge) reward(主臂) · reward(基线臂)",
|
|
1409
|
+
" │ advantage = reward(主臂) − reward(基线臂) · 文本梯度",
|
|
1410
|
+
" │ writes diagnosis.json · never edits · 弃权 abstains",
|
|
1420
1411
|
" │",
|
|
1421
|
-
"
|
|
1422
|
-
" │ runTask ─► the SynergySpec pipeline (headless)",
|
|
1423
|
-
" │ ─► verify ─► verdict",
|
|
1424
|
-
" │ oracle = held_out (curated) OR generated (frozen)",
|
|
1425
|
-
" │ micro-averaged passRate [eval-cache keyed by hash]",
|
|
1412
|
+
" ④ bad advantage ─► rollbackPolicyVersion + appendRejectBufferEntry FIRST",
|
|
1426
1413
|
" │",
|
|
1427
|
-
"
|
|
1414
|
+
" ⑤ 演进智能体 EVOLVING AGENT (optimizer.step) ONE bounded edit ≤ L",
|
|
1415
|
+
" │ gates ×3: static · observed-GREEN · 范围⊆诊断",
|
|
1416
|
+
" │ usecases.md · gen-tests.ts · run-tests.ts are FROZEN ✗",
|
|
1428
1417
|
" │",
|
|
1429
|
-
" ▼
|
|
1418
|
+
" ▼ write back vN+2 to 策略 POLICY = design template (主智能体的「权重」)"
|
|
1430
1419
|
].join("\n");
|
|
1431
1420
|
const DIAGRAM_ORACLE = [
|
|
1432
1421
|
" PER-TASK PIPELINE",
|
|
@@ -1506,21 +1495,21 @@ export const dashboardClientScript = String.raw `
|
|
|
1506
1495
|
function NextActionBar(props) {
|
|
1507
1496
|
const t = props.t || function (k, params) {
|
|
1508
1497
|
if (k === 'common.nextAction') return 'Next action';
|
|
1509
|
-
if (k === 'common.nextAction.runLab') return 'Run
|
|
1510
|
-
if (k === 'common.nextAction.inspect') return 'Inspect the latest
|
|
1498
|
+
if (k === 'common.nextAction.runLab') return 'Run an episode to create graded evidence.';
|
|
1499
|
+
if (k === 'common.nextAction.inspect') return 'Inspect the latest rolled-back episode.';
|
|
1511
1500
|
if (k === 'common.openLatest') return 'Open latest';
|
|
1512
|
-
if (k === 'common.noRun') return 'No
|
|
1501
|
+
if (k === 'common.noRun') return 'No episode';
|
|
1513
1502
|
if (k === 'common.copyCommand') return 'Copy command';
|
|
1514
1503
|
if (k === 'common.copied') return 'Copied';
|
|
1515
1504
|
if (k === 'common.copyFailed') return 'Copy failed';
|
|
1516
|
-
if (k === 'common.
|
|
1517
|
-
if (k === 'common.
|
|
1505
|
+
if (k === 'common.target') return 'target ' + (params && params.id || '');
|
|
1506
|
+
if (k === 'common.targetDefault') return 'default target';
|
|
1518
1507
|
return k;
|
|
1519
1508
|
};
|
|
1520
1509
|
const latest = props.latest;
|
|
1521
|
-
const blocker =
|
|
1522
|
-
const command = 'synergyspec-selfevolving self-evolution
|
|
1523
|
-
const commandLabel = latest && latest.
|
|
1510
|
+
const blocker = episodeBlocker(latest);
|
|
1511
|
+
const command = 'synergyspec-selfevolving self-evolution episode';
|
|
1512
|
+
const commandLabel = latest && latest.targetId ? t('common.target', { id: latest.targetId }) : t('common.targetDefault');
|
|
1524
1513
|
const [copyStatus, setCopyStatus] = useState('idle');
|
|
1525
1514
|
const copyCommand = function () {
|
|
1526
1515
|
const finish = function (status) {
|
|
@@ -1552,7 +1541,7 @@ export const dashboardClientScript = String.raw `
|
|
|
1552
1541
|
type: 'button',
|
|
1553
1542
|
className: 'action-button primary',
|
|
1554
1543
|
onClick: function () {
|
|
1555
|
-
if (props.onSelect && latest && latest.
|
|
1544
|
+
if (props.onSelect && latest && latest.episodeId) props.onSelect({ type: 'episode', id: latest.episodeId, data: latest });
|
|
1556
1545
|
},
|
|
1557
1546
|
disabled: !latest
|
|
1558
1547
|
}, latest ? t('common.openLatest') : t('common.noRun')),
|
|
@@ -1724,7 +1713,7 @@ export const dashboardClientScript = String.raw `
|
|
|
1724
1713
|
learn: props.metrics.readyToLearn,
|
|
1725
1714
|
trace: props.metrics.totalTrace,
|
|
1726
1715
|
spec: props.metrics.openChanges,
|
|
1727
|
-
evolve: props.metrics.
|
|
1716
|
+
evolve: props.metrics.totalEpisodes,
|
|
1728
1717
|
architecture: props.metrics.totalChanges
|
|
1729
1718
|
};
|
|
1730
1719
|
return e('header', { className: 'sidebar' },
|
|
@@ -2003,71 +1992,67 @@ export const dashboardClientScript = String.raw `
|
|
|
2003
1992
|
);
|
|
2004
1993
|
}
|
|
2005
1994
|
|
|
2006
|
-
function
|
|
2007
|
-
const
|
|
2008
|
-
const
|
|
2009
|
-
const
|
|
2010
|
-
const openRun = function () { props.onSelect({ type: 'run', id: run.runId, data: run }); };
|
|
1995
|
+
function EpisodeCard(props) {
|
|
1996
|
+
const ep = props.episode;
|
|
1997
|
+
const verdict = episodeVerdict(ep);
|
|
1998
|
+
const openEpisode = function () { props.onSelect({ type: 'episode', id: ep.episodeId, data: ep }); };
|
|
2011
1999
|
return e('div', Object.assign({
|
|
2012
2000
|
className: 'run-card',
|
|
2013
|
-
'aria-label': 'Open
|
|
2014
|
-
}, interactiveProps(
|
|
2001
|
+
'aria-label': 'Open episode ' + ep.episodeId
|
|
2002
|
+
}, interactiveProps(openEpisode)),
|
|
2015
2003
|
e('div', { className: 'run-head' },
|
|
2016
2004
|
e('div', { style: { minWidth: 0 } },
|
|
2017
|
-
e('div', { className: '
|
|
2018
|
-
e('div', { className: 'run-id' },
|
|
2005
|
+
e('div', { className: 'episode-name', title: ep.changeName || ep.episodeId }, ep.changeName || 'episode'),
|
|
2006
|
+
e('div', { className: 'run-id' }, ep.episodeId)
|
|
2019
2007
|
),
|
|
2020
|
-
e(
|
|
2008
|
+
e('div', { className: 'lane-score ' + advantageTone(ep) }, formatAdvantage(episodeAdvantage(ep)))
|
|
2021
2009
|
),
|
|
2022
2010
|
e('div', { className: 'run-stats' },
|
|
2023
|
-
e('div', null, e('div', { className: 'stat-label' }, '
|
|
2024
|
-
e('div', null, e('div', { className: 'stat-label' }, '
|
|
2025
|
-
e('div', null, e('div', { className: 'stat-label' }, '
|
|
2011
|
+
e('div', null, e('div', { className: 'stat-label' }, 'Target'), e('div', { className: 'stat-value' }, compact(ep.targetId || 'default', 18))),
|
|
2012
|
+
e('div', null, e('div', { className: 'stat-label' }, 'Main'), e('div', { className: 'stat-value' }, ep.policyVersionMain == null ? 'n/a' : 'v' + ep.policyVersionMain)),
|
|
2013
|
+
e('div', null, e('div', { className: 'stat-label' }, 'Baseline'), e('div', { className: 'stat-value' }, ep.policyVersionBaseline == null ? 'n/a' : 'v' + ep.policyVersionBaseline))
|
|
2026
2014
|
),
|
|
2027
2015
|
e('div', { className: 'run-footer' },
|
|
2028
2016
|
e(Pill, { tone: verdict.tone }, verdict.label),
|
|
2029
|
-
e('span', null, formatDate(
|
|
2030
|
-
run.isolationMode ? e('span', null, run.isolationMode) : null
|
|
2017
|
+
e('span', null, formatDate(episodeTime(ep)))
|
|
2031
2018
|
)
|
|
2032
2019
|
);
|
|
2033
2020
|
}
|
|
2034
2021
|
|
|
2035
|
-
function
|
|
2036
|
-
const
|
|
2037
|
-
if (!
|
|
2022
|
+
function EpisodeHistoryTable(props) {
|
|
2023
|
+
const episodes = safeArray(props.episodes);
|
|
2024
|
+
if (!episodes.length) return e(EmptyState, { title: 'No episodes', hint: 'self-evolution/episodes is empty' });
|
|
2038
2025
|
return e('div', { className: 'run-table-wrap' },
|
|
2039
2026
|
e('table', { className: 'run-table' },
|
|
2040
2027
|
e('thead', null,
|
|
2041
2028
|
e('tr', null,
|
|
2042
2029
|
e('th', null, 'Time'),
|
|
2043
|
-
e('th', null, '
|
|
2044
|
-
e('th', null, '
|
|
2045
|
-
e('th', null, '
|
|
2046
|
-
e('th', null, '
|
|
2030
|
+
e('th', null, 'Change'),
|
|
2031
|
+
e('th', null, 'Target'),
|
|
2032
|
+
e('th', null, 'Advantage'),
|
|
2033
|
+
e('th', null, 'Stage'),
|
|
2047
2034
|
e('th', null, 'Blocker'),
|
|
2048
|
-
e('th', null, '
|
|
2049
|
-
e('th', null, 'Cost'),
|
|
2050
|
-
e('th', null, 'Wall')
|
|
2035
|
+
e('th', null, 'Versions')
|
|
2051
2036
|
)
|
|
2052
2037
|
),
|
|
2053
2038
|
e('tbody', null,
|
|
2054
|
-
|
|
2055
|
-
const verdict =
|
|
2056
|
-
const
|
|
2039
|
+
episodes.map(function (ep, index) {
|
|
2040
|
+
const verdict = episodeVerdict(ep);
|
|
2041
|
+
const openEpisode = function () { props.onSelect({ type: 'episode', id: ep.episodeId, data: ep }); };
|
|
2042
|
+
const main = ep.policyVersionMain == null ? '-' : 'v' + ep.policyVersionMain;
|
|
2043
|
+
const baseline = ep.policyVersionBaseline == null ? '-' : 'v' + ep.policyVersionBaseline;
|
|
2057
2044
|
return e('tr', Object.assign({
|
|
2058
|
-
key:
|
|
2045
|
+
key: ep.episodeId || index,
|
|
2059
2046
|
className: 'run-table-row ' + verdict.tone,
|
|
2060
|
-
'aria-label': 'Open
|
|
2061
|
-
}, interactiveProps(
|
|
2062
|
-
e('td', { 'data-label': 'Time' }, formatDate(
|
|
2063
|
-
e('td', { 'data-label': '
|
|
2064
|
-
e('td', { 'data-label': '
|
|
2065
|
-
e('td', { 'data-label': '
|
|
2066
|
-
e('td', { 'data-label': '
|
|
2067
|
-
e('td', { 'data-label': 'Blocker', title:
|
|
2068
|
-
e('td', { 'data-label': '
|
|
2069
|
-
e('td', { 'data-label': 'Cost', className: 'mono-cell' }, formatUsd(run.totalCostUsd)),
|
|
2070
|
-
e('td', { 'data-label': 'Wall', className: 'mono-cell' }, formatDuration(run.totalWallTimeMs))
|
|
2047
|
+
'aria-label': 'Open episode ' + (ep.episodeId || index)
|
|
2048
|
+
}, interactiveProps(openEpisode)),
|
|
2049
|
+
e('td', { 'data-label': 'Time' }, formatDate(episodeTime(ep))),
|
|
2050
|
+
e('td', { 'data-label': 'Change', title: ep.changeName || ep.episodeId }, compact(ep.changeName || ep.episodeId || 'episode', 44)),
|
|
2051
|
+
e('td', { 'data-label': 'Target', title: ep.targetId || '' }, compact(ep.targetId || 'default', 28)),
|
|
2052
|
+
e('td', { 'data-label': 'Advantage', className: 'mono-cell ' + advantageTone(ep) }, formatAdvantage(episodeAdvantage(ep))),
|
|
2053
|
+
e('td', { 'data-label': 'Stage' }, e(Pill, { tone: verdict.tone }, verdict.label)),
|
|
2054
|
+
e('td', { 'data-label': 'Blocker', title: episodeBlocker(ep) }, compact(episodeBlocker(ep), 54)),
|
|
2055
|
+
e('td', { 'data-label': 'Versions', className: 'mono-cell' }, main + ' / ' + baseline)
|
|
2071
2056
|
);
|
|
2072
2057
|
})
|
|
2073
2058
|
)
|
|
@@ -2076,101 +2061,104 @@ export const dashboardClientScript = String.raw `
|
|
|
2076
2061
|
}
|
|
2077
2062
|
|
|
2078
2063
|
function EvolutionStage(props) {
|
|
2079
|
-
const
|
|
2080
|
-
const
|
|
2081
|
-
const entries = safeArray(archive.entries);
|
|
2064
|
+
const episodes = safeArray(props.episodes);
|
|
2065
|
+
const lineages = safeArray(props.policyLineages);
|
|
2082
2066
|
const phaseIndex = props.phaseIndex % evolutionPhases.length;
|
|
2083
|
-
const
|
|
2084
|
-
const
|
|
2085
|
-
const latest =
|
|
2086
|
-
const
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
const
|
|
2093
|
-
const
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
});
|
|
2097
|
-
const
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2067
|
+
const graded = gradedEpisodes(episodes);
|
|
2068
|
+
const kept = keptEpisodes(episodes);
|
|
2069
|
+
const latest = episodes[0];
|
|
2070
|
+
const headVersion = lineages.reduce(function (max, lineage) {
|
|
2071
|
+
return lineage.headVersion == null ? max : Math.max(max, lineage.headVersion);
|
|
2072
|
+
}, null);
|
|
2073
|
+
const stageCount = function (stage) {
|
|
2074
|
+
return episodes.filter(function (ep) { return ep.stage === stage; }).length;
|
|
2075
|
+
};
|
|
2076
|
+
const baselineArm = episodes.filter(function (ep) { return ep.policyVersionBaseline != null; }).length;
|
|
2077
|
+
const baselineSkipped = stageCount('baseline-skipped');
|
|
2078
|
+
const mainArm = episodes.filter(function (ep) { return ep.policyVersionMain != null; }).length;
|
|
2079
|
+
const scored = graded.length;
|
|
2080
|
+
const evolveCount = lineages.reduce(function (sum, lineage) { return sum + numberOr(lineage.evolveCount, 0); }, 0);
|
|
2081
|
+
const rollbackCount = lineages.reduce(function (sum, lineage) { return sum + numberOr(lineage.rollbackCount, 0); }, 0);
|
|
2082
|
+
const refusedCount = lineages.reduce(function (sum, lineage) { return sum + numberOr(lineage.refusedCount, 0); }, 0);
|
|
2083
|
+
const meanAdvantage = graded.length
|
|
2084
|
+
? graded.reduce(function (sum, ep) { return sum + episodeAdvantage(ep); }, 0) / graded.length
|
|
2085
|
+
: null;
|
|
2086
|
+
const blockedEpisodes = episodes.filter(function (ep) { return episodeVerdict(ep).tone === 'bad'; });
|
|
2087
|
+
const selectedEpisodeId = props.selectedEpisodeId || (latest && latest.episodeId) || '';
|
|
2088
|
+
const selectedEpisode = episodes.find(function (ep) { return ep.episodeId === selectedEpisodeId; }) || latest;
|
|
2089
|
+
const latestVerdict = episodeVerdict(latest);
|
|
2102
2090
|
const pipelineStages = [
|
|
2103
2091
|
{
|
|
2104
|
-
key: 'baseline',
|
|
2092
|
+
key: 'baseline-arm',
|
|
2105
2093
|
phase: 0,
|
|
2106
|
-
label: 'Baseline',
|
|
2107
|
-
value:
|
|
2108
|
-
detail:
|
|
2109
|
-
tone:
|
|
2110
|
-
evidence: '
|
|
2094
|
+
label: 'Baseline arm',
|
|
2095
|
+
value: baselineArm ? formatInt(baselineArm) + ' captured' : 'none',
|
|
2096
|
+
detail: baselineSkipped ? formatInt(baselineSkipped) + ' baseline-skipped' : 'fresh baseline-policy rollout',
|
|
2097
|
+
tone: baselineArm ? 'good' : 'warn',
|
|
2098
|
+
evidence: 'baseline-arm-captured'
|
|
2111
2099
|
},
|
|
2112
2100
|
{
|
|
2113
|
-
key: '
|
|
2101
|
+
key: 'main-arm',
|
|
2114
2102
|
phase: 2,
|
|
2115
|
-
label: '
|
|
2116
|
-
value:
|
|
2117
|
-
detail: latest ? compact(latest.
|
|
2103
|
+
label: 'Main arm',
|
|
2104
|
+
value: mainArm ? formatInt(mainArm) + ' captured' : 'none',
|
|
2105
|
+
detail: latest ? compact(latest.changeName || latest.episodeId, 72) : 'run an episode to capture the main arm',
|
|
2118
2106
|
tone: latest ? latestVerdict.tone : 'muted',
|
|
2119
|
-
evidence:
|
|
2107
|
+
evidence: 'main-arm-captured'
|
|
2120
2108
|
},
|
|
2121
2109
|
{
|
|
2122
|
-
key: '
|
|
2110
|
+
key: 'reward',
|
|
2123
2111
|
phase: 3,
|
|
2124
|
-
label: '
|
|
2125
|
-
value:
|
|
2126
|
-
detail:
|
|
2127
|
-
tone:
|
|
2128
|
-
evidence: '
|
|
2112
|
+
label: 'Reward + advantage',
|
|
2113
|
+
value: scored ? formatAdvantage(meanAdvantage) + ' mean' : 'unscored',
|
|
2114
|
+
detail: formatInt(scored) + ' graded of ' + formatInt(episodes.length) + ' episodes',
|
|
2115
|
+
tone: scored ? 'info' : 'warn',
|
|
2116
|
+
evidence: 'scored'
|
|
2129
2117
|
},
|
|
2130
2118
|
{
|
|
2131
|
-
key: '
|
|
2119
|
+
key: 'decision',
|
|
2132
2120
|
phase: 3,
|
|
2133
|
-
label: '
|
|
2134
|
-
value:
|
|
2135
|
-
detail: formatInt(
|
|
2136
|
-
tone:
|
|
2137
|
-
evidence: '
|
|
2121
|
+
label: 'Rollback or evolve',
|
|
2122
|
+
value: evolveCount ? formatInt(evolveCount) + ' evolved' : 'none',
|
|
2123
|
+
detail: formatInt(rollbackCount) + ' rolled back / ' + formatInt(refusedCount) + ' refused',
|
|
2124
|
+
tone: blockedEpisodes.length ? 'bad' : evolveCount ? 'good' : 'muted',
|
|
2125
|
+
evidence: 'kept / rolled-back'
|
|
2138
2126
|
},
|
|
2139
2127
|
{
|
|
2140
|
-
key: '
|
|
2128
|
+
key: 'writeback',
|
|
2141
2129
|
phase: 4,
|
|
2142
|
-
label: '
|
|
2143
|
-
value:
|
|
2144
|
-
detail:
|
|
2145
|
-
tone:
|
|
2146
|
-
evidence: '
|
|
2130
|
+
label: 'Write-back ledger',
|
|
2131
|
+
value: headVersion == null ? 'no version' : 'v' + headVersion,
|
|
2132
|
+
detail: kept.length ? formatInt(kept.length) + ' kept episodes' : 'no kept episode yet',
|
|
2133
|
+
tone: headVersion == null ? 'warn' : 'good',
|
|
2134
|
+
evidence: 'policy ledger'
|
|
2147
2135
|
}
|
|
2148
2136
|
];
|
|
2149
|
-
const
|
|
2150
|
-
if (!
|
|
2151
|
-
if (props.
|
|
2137
|
+
const selectEpisode = function (ep) {
|
|
2138
|
+
if (!ep || !ep.episodeId) return;
|
|
2139
|
+
if (props.onEpisodeSelect) props.onEpisodeSelect(ep.episodeId);
|
|
2152
2140
|
};
|
|
2153
2141
|
const latestHeadline = latest
|
|
2154
2142
|
? latestVerdict.tone === 'bad'
|
|
2155
|
-
? 'Latest
|
|
2143
|
+
? 'Latest episode ' + latestVerdict.label
|
|
2156
2144
|
: latestVerdict.tone === 'good'
|
|
2157
|
-
? 'Latest
|
|
2158
|
-
: 'Latest
|
|
2159
|
-
: 'No
|
|
2145
|
+
? 'Latest episode ' + latestVerdict.label
|
|
2146
|
+
: 'Latest episode ' + latestVerdict.label
|
|
2147
|
+
: 'No episode evidence';
|
|
2160
2148
|
return e('section', { className: 'evo-stage', 'aria-label': 'Self-evolution evidence pipeline' },
|
|
2161
2149
|
e('div', { className: 'evo-map-head' },
|
|
2162
2150
|
e('div', { className: 'map-copy' },
|
|
2163
2151
|
e('div', { className: 'eyebrow' }, 'Evidence pipeline'),
|
|
2164
2152
|
e('h2', null, latestHeadline),
|
|
2165
|
-
e('p', null, latest ?
|
|
2153
|
+
e('p', null, latest ? episodeBlocker(latest) : 'Run an episode to populate two-arm evidence.')
|
|
2166
2154
|
),
|
|
2167
2155
|
e('div', { className: 'map-totals' },
|
|
2168
|
-
e('div', { className: 'map-total' }, e('span', null, '
|
|
2169
|
-
e('div', { className: 'map-total' }, e('span', null, 'Blocked'), e('strong', null, formatInt(
|
|
2170
|
-
e('div', { className: 'map-total' }, e('span', null, '
|
|
2156
|
+
e('div', { className: 'map-total' }, e('span', null, 'Episodes'), e('strong', null, formatInt(episodes.length))),
|
|
2157
|
+
e('div', { className: 'map-total' }, e('span', null, 'Blocked'), e('strong', null, formatInt(blockedEpisodes.length))),
|
|
2158
|
+
e('div', { className: 'map-total' }, e('span', null, 'Head'), e('strong', null, headVersion == null ? 'n/a' : 'v' + headVersion))
|
|
2171
2159
|
)
|
|
2172
2160
|
),
|
|
2173
|
-
e('div', { className: 'pipeline-rail', role: 'tablist', 'aria-label': '
|
|
2161
|
+
e('div', { className: 'pipeline-rail', role: 'tablist', 'aria-label': 'Episode evidence stages' },
|
|
2174
2162
|
pipelineStages.map(function (stage, index) {
|
|
2175
2163
|
return e('button', {
|
|
2176
2164
|
key: stage.key,
|
|
@@ -2194,39 +2182,39 @@ export const dashboardClientScript = String.raw `
|
|
|
2194
2182
|
e('div', { className: 'run-board' },
|
|
2195
2183
|
e('div', { className: 'board-toolbar' },
|
|
2196
2184
|
e('div', null,
|
|
2197
|
-
e('span', { className: 'node-kicker' }, '
|
|
2198
|
-
e('strong', null,
|
|
2185
|
+
e('span', { className: 'node-kicker' }, 'Episode board'),
|
|
2186
|
+
e('strong', null, episodes.length ? 'Recorded episodes' : 'No episodes yet')
|
|
2199
2187
|
),
|
|
2200
|
-
e('div', { className: 'board-filters', 'aria-label': '
|
|
2188
|
+
e('div', { className: 'board-filters', 'aria-label': 'Episode evidence summary' },
|
|
2201
2189
|
e(Pill, { tone: latest ? latestVerdict.tone : 'muted' }, latest ? latestVerdict.label : 'no latest'),
|
|
2202
|
-
e(Pill, { tone:
|
|
2203
|
-
e(Pill, { tone:
|
|
2190
|
+
e(Pill, { tone: kept.length ? 'good' : 'bad' }, formatInt(kept.length) + ' kept'),
|
|
2191
|
+
e(Pill, { tone: graded.length ? 'info' : 'muted' }, formatInt(graded.length) + ' graded')
|
|
2204
2192
|
)
|
|
2205
2193
|
),
|
|
2206
|
-
|
|
2207
|
-
const verdict =
|
|
2194
|
+
episodes.length ? episodes.slice(0, 8).map(function (ep, index) {
|
|
2195
|
+
const verdict = episodeVerdict(ep);
|
|
2208
2196
|
return e('button', {
|
|
2209
|
-
key:
|
|
2197
|
+
key: ep.episodeId || index,
|
|
2210
2198
|
type: 'button',
|
|
2211
|
-
className: 'run-lane ' + verdict.tone + (
|
|
2212
|
-
onClick: function () {
|
|
2213
|
-
title:
|
|
2199
|
+
className: 'run-lane ' + verdict.tone + (selectedEpisode && selectedEpisode.episodeId === ep.episodeId ? ' selected' : ''),
|
|
2200
|
+
onClick: function () { selectEpisode(ep); },
|
|
2201
|
+
title: ep.episodeId || ''
|
|
2214
2202
|
},
|
|
2215
|
-
e('span', { className: 'lane-time' }, formatDate(
|
|
2203
|
+
e('span', { className: 'lane-time' }, formatDate(episodeTime(ep))),
|
|
2216
2204
|
e('span', { className: 'lane-main' },
|
|
2217
|
-
e('strong', null, compact(
|
|
2218
|
-
e('small', null, shortId(
|
|
2205
|
+
e('strong', null, compact(ep.changeName || ep.episodeId, 62)),
|
|
2206
|
+
e('small', null, shortId(ep.episodeId || ('episode-' + index)) + ' / ' + compact(ep.targetId || 'default', 24))
|
|
2219
2207
|
),
|
|
2220
|
-
e('span', { className: 'lane-score' },
|
|
2208
|
+
e('span', { className: 'lane-score ' + advantageTone(ep) }, formatAdvantage(episodeAdvantage(ep))),
|
|
2221
2209
|
e('span', { className: 'lane-verdict' },
|
|
2222
2210
|
e(Pill, { tone: verdict.tone }, verdict.label),
|
|
2223
|
-
e('small', null,
|
|
2211
|
+
e('small', null, (ep.policyVersionMain == null ? '-' : 'v' + ep.policyVersionMain) + ' / ' + (ep.policyVersionBaseline == null ? '-' : 'v' + ep.policyVersionBaseline))
|
|
2224
2212
|
),
|
|
2225
|
-
e('span', { className: 'lane-blocker' },
|
|
2213
|
+
e('span', { className: 'lane-blocker' }, episodeBlocker(ep))
|
|
2226
2214
|
);
|
|
2227
2215
|
}) : e('div', { className: 'candidate-empty' },
|
|
2228
|
-
e('strong', null, 'Run
|
|
2229
|
-
e('span', null, '
|
|
2216
|
+
e('strong', null, 'Run an episode to populate lanes'),
|
|
2217
|
+
e('span', null, 'Two-arm episodes will appear here with stages, advantage, and policy versions.')
|
|
2230
2218
|
)
|
|
2231
2219
|
)
|
|
2232
2220
|
)
|
|
@@ -2235,59 +2223,55 @@ export const dashboardClientScript = String.raw `
|
|
|
2235
2223
|
|
|
2236
2224
|
function EvolutionInspector(props) {
|
|
2237
2225
|
const phase = evolutionPhases[props.phaseIndex % evolutionPhases.length];
|
|
2238
|
-
const
|
|
2239
|
-
const
|
|
2240
|
-
const
|
|
2241
|
-
const
|
|
2242
|
-
const
|
|
2243
|
-
const
|
|
2244
|
-
const
|
|
2245
|
-
const
|
|
2246
|
-
const
|
|
2247
|
-
const
|
|
2248
|
-
const
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
const
|
|
2254
|
-
|
|
2255
|
-
});
|
|
2256
|
-
const averageScore = evidenceRuns.length
|
|
2257
|
-
? evidenceRuns.reduce(function (sum, run) { return sum + runScore(run); }, 0) / evidenceRuns.length
|
|
2258
|
-
: 0;
|
|
2226
|
+
const episodes = safeArray(props.episodes);
|
|
2227
|
+
const lineages = safeArray(props.policyLineages);
|
|
2228
|
+
const rejectBuffer = safeArray(props.rejectBuffer);
|
|
2229
|
+
const latest = episodes[0];
|
|
2230
|
+
const graded = gradedEpisodes(episodes);
|
|
2231
|
+
const kept = keptEpisodes(episodes);
|
|
2232
|
+
const selectedEpisodeId = props.selectedEpisodeId || (latest && latest.episodeId) || '';
|
|
2233
|
+
const selectedEpisode = episodes.find(function (ep) { return ep.episodeId === selectedEpisodeId; }) || latest;
|
|
2234
|
+
const selectedVerdict = episodeVerdict(selectedEpisode);
|
|
2235
|
+
const blockedEpisodes = episodes.filter(function (ep) { return episodeVerdict(ep).tone === 'bad'; });
|
|
2236
|
+
const meanAdvantage = graded.length
|
|
2237
|
+
? graded.reduce(function (sum, ep) { return sum + episodeAdvantage(ep); }, 0) / graded.length
|
|
2238
|
+
: null;
|
|
2239
|
+
const activeLineage = (selectedEpisode && lineages.find(function (lineage) { return lineage.targetId === selectedEpisode.targetId; })) || lineages[0] || null;
|
|
2240
|
+
const lineageEntries = activeLineage ? safeArray(activeLineage.entries) : [];
|
|
2241
|
+
const headVersion = activeLineage ? activeLineage.headVersion : null;
|
|
2242
|
+
const rejectNewestFirst = rejectBuffer.slice().reverse();
|
|
2259
2243
|
const stageSignals = [
|
|
2260
2244
|
['Focus', phase.title],
|
|
2261
|
-
['
|
|
2262
|
-
['Blocked', formatInt(
|
|
2263
|
-
['
|
|
2245
|
+
['Episodes', formatInt(episodes.length)],
|
|
2246
|
+
['Blocked', formatInt(blockedEpisodes.length)],
|
|
2247
|
+
['Kept', formatInt(kept.length)]
|
|
2264
2248
|
];
|
|
2265
|
-
const
|
|
2266
|
-
if (
|
|
2249
|
+
const selectEpisode = function (ep) {
|
|
2250
|
+
if (ep && ep.episodeId && props.onEpisodeSelect) props.onEpisodeSelect(ep.episodeId);
|
|
2267
2251
|
};
|
|
2268
|
-
const
|
|
2269
|
-
if (
|
|
2252
|
+
const openEpisode = function (ep) {
|
|
2253
|
+
if (ep && ep.episodeId && props.onOpenEpisode) props.onOpenEpisode(ep);
|
|
2270
2254
|
};
|
|
2271
|
-
const
|
|
2272
|
-
if (entry &&
|
|
2255
|
+
const openReject = function (entry) {
|
|
2256
|
+
if (entry && props.onOpenReject) props.onOpenReject(entry);
|
|
2273
2257
|
};
|
|
2274
2258
|
return e('aside', { className: 'evo-inspector' },
|
|
2275
2259
|
e('div', { className: 'inspector-top' },
|
|
2276
|
-
e('div', { className: 'inspector-phase' }, '
|
|
2277
|
-
e('h2', null,
|
|
2278
|
-
e('p', null,
|
|
2260
|
+
e('div', { className: 'inspector-phase' }, 'Episode inspector'),
|
|
2261
|
+
e('h2', null, selectedEpisode ? compact(selectedEpisode.changeName || selectedEpisode.episodeId, 72) : 'No selected episode'),
|
|
2262
|
+
e('p', null, selectedEpisode ? episodeBlocker(selectedEpisode) : 'Select an episode to inspect its stage, advantage, versions, and policy ledger.'),
|
|
2279
2263
|
e('div', { className: 'inspector-actions' },
|
|
2280
2264
|
e('button', {
|
|
2281
2265
|
type: 'button',
|
|
2282
2266
|
className: 'step-button',
|
|
2283
|
-
disabled: !
|
|
2284
|
-
onClick: function () {
|
|
2285
|
-
},
|
|
2267
|
+
disabled: !blockedEpisodes.length,
|
|
2268
|
+
onClick: function () { selectEpisode(blockedEpisodes[0]); }
|
|
2269
|
+
}, blockedEpisodes.length ? 'Select blocker' : 'No blocker'),
|
|
2286
2270
|
e('button', {
|
|
2287
2271
|
type: 'button',
|
|
2288
2272
|
className: 'step-button primary',
|
|
2289
|
-
disabled: !
|
|
2290
|
-
onClick: function () {
|
|
2273
|
+
disabled: !selectedEpisode,
|
|
2274
|
+
onClick: function () { openEpisode(selectedEpisode); }
|
|
2291
2275
|
}, 'Open detail')
|
|
2292
2276
|
)
|
|
2293
2277
|
),
|
|
@@ -2299,51 +2283,55 @@ export const dashboardClientScript = String.raw `
|
|
|
2299
2283
|
);
|
|
2300
2284
|
})
|
|
2301
2285
|
),
|
|
2302
|
-
|
|
2286
|
+
selectedEpisode ? e('div', { className: 'selected-run-sheet' },
|
|
2303
2287
|
e('div', { className: 'sheet-row' },
|
|
2304
|
-
e('span', null, '
|
|
2305
|
-
e('strong', null, shortId(
|
|
2288
|
+
e('span', null, 'Episode'),
|
|
2289
|
+
e('strong', null, shortId(selectedEpisode.episodeId))
|
|
2306
2290
|
),
|
|
2307
2291
|
e('div', { className: 'sheet-row' },
|
|
2308
|
-
e('span', null, '
|
|
2292
|
+
e('span', null, 'Stage'),
|
|
2309
2293
|
e(Pill, { tone: selectedVerdict.tone }, selectedVerdict.label)
|
|
2310
2294
|
),
|
|
2311
2295
|
e('div', { className: 'sheet-row' },
|
|
2312
|
-
e('span', null, '
|
|
2313
|
-
e('strong',
|
|
2296
|
+
e('span', null, 'Advantage'),
|
|
2297
|
+
e('strong', { className: advantageTone(selectedEpisode) }, formatAdvantage(episodeAdvantage(selectedEpisode)))
|
|
2314
2298
|
),
|
|
2315
2299
|
e('div', { className: 'sheet-row' },
|
|
2316
|
-
e('span', null, '
|
|
2317
|
-
e('strong', null,
|
|
2300
|
+
e('span', null, 'Versions'),
|
|
2301
|
+
e('strong', null, (selectedEpisode.policyVersionMain == null ? '-' : 'v' + selectedEpisode.policyVersionMain) + ' / ' + (selectedEpisode.policyVersionBaseline == null ? '-' : 'v' + selectedEpisode.policyVersionBaseline))
|
|
2318
2302
|
),
|
|
2319
2303
|
e('div', { className: 'sheet-row' },
|
|
2320
|
-
e('span', null, '
|
|
2321
|
-
e('strong', null,
|
|
2304
|
+
e('span', null, 'Change'),
|
|
2305
|
+
e('strong', null, compact(selectedEpisode.changeName || 'n/a', 40))
|
|
2306
|
+
),
|
|
2307
|
+
e('div', { className: 'sheet-row' },
|
|
2308
|
+
e('span', null, 'Target'),
|
|
2309
|
+
e('strong', null, compact(selectedEpisode.targetId || 'default', 40))
|
|
2322
2310
|
),
|
|
2323
2311
|
e('div', { className: 'sheet-row wide' },
|
|
2324
2312
|
e('span', null, 'Artifact path'),
|
|
2325
|
-
e('code', null, '
|
|
2313
|
+
e('code', null, 'self-evolution/episodes/' + selectedEpisode.episodeId)
|
|
2326
2314
|
)
|
|
2327
2315
|
) : null,
|
|
2328
2316
|
e('div', { className: 'evidence-queue' },
|
|
2329
2317
|
e('div', { className: 'queue-head' },
|
|
2330
2318
|
e('span', null, 'Evidence queue'),
|
|
2331
|
-
e(Pill, { tone:
|
|
2319
|
+
e(Pill, { tone: blockedEpisodes.length ? 'bad' : 'muted' }, formatInt(blockedEpisodes.length) + ' blockers')
|
|
2332
2320
|
),
|
|
2333
|
-
(
|
|
2334
|
-
const verdict =
|
|
2321
|
+
(blockedEpisodes.length ? blockedEpisodes : episodes.slice(0, 3)).slice(0, 5).map(function (ep, index) {
|
|
2322
|
+
const verdict = episodeVerdict(ep);
|
|
2335
2323
|
return e('button', {
|
|
2336
|
-
key:
|
|
2324
|
+
key: ep.episodeId || index,
|
|
2337
2325
|
type: 'button',
|
|
2338
|
-
className: 'queue-run ' + verdict.tone + (
|
|
2339
|
-
onClick: function () {
|
|
2326
|
+
className: 'queue-run ' + verdict.tone + (selectedEpisode && selectedEpisode.episodeId === ep.episodeId ? ' selected' : ''),
|
|
2327
|
+
onClick: function () { selectEpisode(ep); }
|
|
2340
2328
|
},
|
|
2341
|
-
e('span', null, compact(
|
|
2342
|
-
e('strong', null,
|
|
2343
|
-
e('small', null, shortId(
|
|
2329
|
+
e('span', null, compact(ep.changeName || ep.episodeId, 46)),
|
|
2330
|
+
e('strong', null, episodeBlocker(ep)),
|
|
2331
|
+
e('small', null, shortId(ep.episodeId) + ' / ' + formatDate(episodeTime(ep)))
|
|
2344
2332
|
);
|
|
2345
2333
|
}),
|
|
2346
|
-
!
|
|
2334
|
+
!blockedEpisodes.length && !episodes.length ? e('div', { className: 'queue-empty' }, 'No episode queue. Run an episode to populate evidence.') : null
|
|
2347
2335
|
),
|
|
2348
2336
|
e('div', { className: 'signal-grid' },
|
|
2349
2337
|
e('div', { className: 'signal' },
|
|
@@ -2357,55 +2345,49 @@ export const dashboardClientScript = String.raw `
|
|
|
2357
2345
|
e('div', { className: 'signal-detail' }, phase.detail)
|
|
2358
2346
|
),
|
|
2359
2347
|
e('div', { className: 'signal' },
|
|
2360
|
-
e('div', { className: 'signal-label' }, '
|
|
2361
|
-
e('div', { className: 'signal-value' },
|
|
2362
|
-
e('div', { className: 'signal-detail' }, formatInt(
|
|
2348
|
+
e('div', { className: 'signal-label' }, 'Advantage snapshot'),
|
|
2349
|
+
e('div', { className: 'signal-value' }, graded.length ? formatAdvantage(meanAdvantage) + ' mean advantage' : 'no graded signal'),
|
|
2350
|
+
e('div', { className: 'signal-detail' }, formatInt(graded.length) + ' graded of ' + formatInt(episodes.length) + ' episodes')
|
|
2363
2351
|
),
|
|
2364
2352
|
e('div', { className: 'signal' },
|
|
2365
|
-
e('div', { className: 'signal-label' }, '
|
|
2366
|
-
e('div', { className: 'signal-value' },
|
|
2367
|
-
e('div', { className: 'signal-detail' },
|
|
2353
|
+
e('div', { className: 'signal-label' }, 'Policy lineage'),
|
|
2354
|
+
e('div', { className: 'signal-value' }, headVersion == null ? 'no version' : 'v' + headVersion),
|
|
2355
|
+
e('div', { className: 'signal-detail' }, lineageEntries.length ? formatInt(lineageEntries.length) + ' ledger entries' : 'ledger has no entries')
|
|
2368
2356
|
)
|
|
2369
2357
|
),
|
|
2370
2358
|
e('div', { className: 'archive-queue' },
|
|
2371
2359
|
e('div', { className: 'queue-head' },
|
|
2372
|
-
e('span', null, '
|
|
2373
|
-
e(Pill, { tone:
|
|
2360
|
+
e('span', null, 'Reject-buffer'),
|
|
2361
|
+
e(Pill, { tone: rejectBuffer.length ? 'bad' : 'muted' }, formatInt(rejectBuffer.length) + ' entries')
|
|
2374
2362
|
),
|
|
2375
|
-
|
|
2363
|
+
rejectBuffer.length ? rejectNewestFirst.slice(0, 4).map(function (entry, index) {
|
|
2364
|
+
const summary = safeObject(entry.editSummary);
|
|
2376
2365
|
return e('button', {
|
|
2377
|
-
key: entry.
|
|
2366
|
+
key: (entry.episodeId || 'reject') + '-' + index,
|
|
2378
2367
|
type: 'button',
|
|
2379
2368
|
className: 'archive-queue-row',
|
|
2380
|
-
onClick: function () {
|
|
2369
|
+
onClick: function () { openReject(entry); }
|
|
2381
2370
|
},
|
|
2382
|
-
e('span', null,
|
|
2383
|
-
e('strong',
|
|
2384
|
-
e('small', null,
|
|
2371
|
+
e('span', null, entry.reason || 'reject'),
|
|
2372
|
+
e('strong', { className: advantageTone(entry) }, formatAdvantage(entry.advantage == null ? null : entry.advantage)),
|
|
2373
|
+
e('small', null, shortId(entry.episodeId) + ' / ' + compact(summary.rationaleExcerpt || '', 40))
|
|
2385
2374
|
);
|
|
2386
|
-
}) : e('div', { className: 'queue-empty' }, 'No
|
|
2375
|
+
}) : e('div', { className: 'queue-empty' }, 'No reject-buffer entries yet')
|
|
2387
2376
|
)
|
|
2388
2377
|
);
|
|
2389
2378
|
}
|
|
2390
2379
|
|
|
2391
|
-
function
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
}
|
|
2396
|
-
|
|
2397
|
-
function Lineage(props) {
|
|
2398
|
-
const entries = safeArray(props.archive && props.archive.entries).slice().sort(function (a, b) {
|
|
2399
|
-
return numberOr(b.generation, 0) - numberOr(a.generation, 0) || String(b.createdAt || '').localeCompare(String(a.createdAt || ''));
|
|
2400
|
-
}).slice(0, 12);
|
|
2401
|
-
if (!entries.length) return e(EmptyState, { title: 'No archived lineage', hint: 'evolve/archive/archive.json has no entries' });
|
|
2380
|
+
function PolicyLedger(props) {
|
|
2381
|
+
const lineage = props.lineage || {};
|
|
2382
|
+
const entries = safeArray(lineage.entries).slice().reverse().slice(0, 12);
|
|
2383
|
+
if (!entries.length) return e(EmptyState, { title: 'No policy ledger', hint: 'self-evolution/policy/ledger.ndjson has no entries' });
|
|
2402
2384
|
return e('div', { className: 'lineage' },
|
|
2403
|
-
entries.map(function (entry) {
|
|
2404
|
-
return e('div', { key: entry.
|
|
2405
|
-
e('div', { className: 'gen' }, '
|
|
2406
|
-
e('strong', { title: entry.
|
|
2407
|
-
e('span', null, formatDate(entry.
|
|
2408
|
-
e('span', null,
|
|
2385
|
+
entries.map(function (entry, index) {
|
|
2386
|
+
return e('div', { key: (entry.version != null ? entry.version : index) + '-' + index, className: 'lineage-node' },
|
|
2387
|
+
e('div', { className: 'gen' }, 'v' + formatInt(entry.version)),
|
|
2388
|
+
e('strong', { title: entry.action || '' }, entry.action || 'n/a'),
|
|
2389
|
+
e('span', null, formatDate(entry.at)),
|
|
2390
|
+
e('span', null, compact(entry.reason || '', 40))
|
|
2409
2391
|
);
|
|
2410
2392
|
})
|
|
2411
2393
|
);
|
|
@@ -3156,10 +3138,12 @@ export const dashboardClientScript = String.raw `
|
|
|
3156
3138
|
function IntroductionView(props) {
|
|
3157
3139
|
const t = props.t || function (k) { return k; };
|
|
3158
3140
|
const changes = safeArray(props.changes);
|
|
3159
|
-
const
|
|
3160
|
-
const
|
|
3161
|
-
const
|
|
3162
|
-
const
|
|
3141
|
+
const episodes = safeArray(props.episodes);
|
|
3142
|
+
const lineages = safeArray(props.policyLineages);
|
|
3143
|
+
const ledgerEntries = lineages.reduce(function (sum, lineage) { return sum + safeArray(lineage.entries).length; }, 0);
|
|
3144
|
+
const headVersion = lineages.reduce(function (max, lineage) {
|
|
3145
|
+
return lineage.headVersion == null ? max : Math.max(max, lineage.headVersion);
|
|
3146
|
+
}, 0);
|
|
3163
3147
|
const openChanges = changes.filter(function (change) { return change.status !== 'completed'; });
|
|
3164
3148
|
const readyToApply = changes.filter(function (change) {
|
|
3165
3149
|
return change.hasProposal && change.hasTasks && change.totalTasks > 0 && change.completedTasks < change.totalTasks;
|
|
@@ -3171,8 +3155,8 @@ export const dashboardClientScript = String.raw `
|
|
|
3171
3155
|
return change.hasTasks && change.totalTasks > 0 && change.completedTasks >= change.totalTasks && (change.hasTestReport || change.hasTestPlan);
|
|
3172
3156
|
});
|
|
3173
3157
|
const completed = changes.filter(function (change) { return change.status === 'completed'; });
|
|
3174
|
-
const
|
|
3175
|
-
const latestVerdict =
|
|
3158
|
+
const latestEpisode = episodes[0];
|
|
3159
|
+
const latestVerdict = latestEpisode ? episodeVerdict(latestEpisode) : { label: 'n/a', tone: 'muted' };
|
|
3176
3160
|
const nextChange = archiveReady[0] || readyToReview[0] || readyToApply[0] || openChanges[0] || changes[0];
|
|
3177
3161
|
const nextLabel = archiveReady.length
|
|
3178
3162
|
? t('intro.cta.label.review')
|
|
@@ -3230,8 +3214,8 @@ export const dashboardClientScript = String.raw `
|
|
|
3230
3214
|
{ num: '03', titleKey: 'intro.selfevo.col3.title', bodyKey: 'intro.selfevo.col3.body', tone: 'warn' }
|
|
3231
3215
|
];
|
|
3232
3216
|
|
|
3233
|
-
const archiveGenCount =
|
|
3234
|
-
const archiveEntryCount =
|
|
3217
|
+
const archiveGenCount = headVersion || Math.max(2, Math.min(8, Math.ceil(completed.length / 3) || 4));
|
|
3218
|
+
const archiveEntryCount = ledgerEntries || completed.length || changes.length || 0;
|
|
3235
3219
|
|
|
3236
3220
|
return e('div', { className: 'ss2', 'aria-label': 'Introduction' },
|
|
3237
3221
|
// ---------------- Hero (now self-evolving-forward)
|
|
@@ -3286,7 +3270,7 @@ export const dashboardClientScript = String.raw `
|
|
|
3286
3270
|
),
|
|
3287
3271
|
e('div', { className: 'ss2-selfevo-stat' },
|
|
3288
3272
|
e('span', { className: 'label' }, t('intro.selfevo.stat.candidates')),
|
|
3289
|
-
e('span', { className: 'value' }, formatInt(
|
|
3273
|
+
e('span', { className: 'value' }, formatInt(keptEpisodes(episodes).length))
|
|
3290
3274
|
)
|
|
3291
3275
|
),
|
|
3292
3276
|
e('div', { className: 'ss2-selfevo-cols' },
|
|
@@ -3335,7 +3319,7 @@ export const dashboardClientScript = String.raw `
|
|
|
3335
3319
|
e('div', { className: 'ss2-kpi' },
|
|
3336
3320
|
e('span', { className: 'label' }, t('intro.kpi.latestVerdict')),
|
|
3337
3321
|
e('span', { className: 'value mono' }, latestVerdict.label),
|
|
3338
|
-
e('span', { className: 'delta' },
|
|
3322
|
+
e('span', { className: 'delta' }, latestEpisode ? shortId(latestEpisode.episodeId) + ' · ' + formatDate(episodeTime(latestEpisode)) : t('intro.kpi.latestVerdict.delta.empty'))
|
|
3339
3323
|
)
|
|
3340
3324
|
)
|
|
3341
3325
|
),
|
|
@@ -3659,8 +3643,8 @@ export const dashboardClientScript = String.raw `
|
|
|
3659
3643
|
),
|
|
3660
3644
|
e(Panel, { title: 'Evaluation boundary' },
|
|
3661
3645
|
e('div', { className: 'boundary-note warn' },
|
|
3662
|
-
e('strong', null, 'Keep self-evolution in the
|
|
3663
|
-
e('span', null, '
|
|
3646
|
+
e('strong', null, 'Keep self-evolution in the loop'),
|
|
3647
|
+
e('span', null, 'Two-arm forward, graded advantage, and rollback-before-evolution are maintainer tools, not the first-run user interface.')
|
|
3664
3648
|
)
|
|
3665
3649
|
),
|
|
3666
3650
|
e(Panel, { title: 'Implementation rule' },
|
|
@@ -4020,11 +4004,11 @@ export const dashboardClientScript = String.raw `
|
|
|
4020
4004
|
const changes = safeArray(props.changes);
|
|
4021
4005
|
const cli = safeArray(props.cli);
|
|
4022
4006
|
const history = safeArray(props.history);
|
|
4023
|
-
const
|
|
4007
|
+
const episodes = safeArray(props.episodes);
|
|
4024
4008
|
const completed = changes.filter(function (change) { return change.status === 'completed'; }).length;
|
|
4025
4009
|
const inProgress = changes.filter(function (change) { return change.status === 'in-progress'; }).length;
|
|
4026
4010
|
const failures = cli.filter(function (event) { return isFailure(event.outcome); }).length;
|
|
4027
|
-
const
|
|
4011
|
+
const latestEpisode = episodes[0];
|
|
4028
4012
|
return e(React.Fragment, null,
|
|
4029
4013
|
e(HeroBand, {
|
|
4030
4014
|
agent: true,
|
|
@@ -4033,7 +4017,7 @@ export const dashboardClientScript = String.raw `
|
|
|
4033
4017
|
chips: [
|
|
4034
4018
|
e(Chip, { key: 'changes', label: t('overview.hero.chip.changes'), value: formatInt(changes.length) }),
|
|
4035
4019
|
e(Chip, { key: 'trace', label: t('overview.hero.chip.trace'), value: formatInt(history.length) }),
|
|
4036
|
-
e(Chip, { key: 'runs', label: t('overview.hero.chip.runs'), value: formatInt(
|
|
4020
|
+
e(Chip, { key: 'runs', label: t('overview.hero.chip.runs'), value: formatInt(episodes.length) })
|
|
4037
4021
|
]
|
|
4038
4022
|
}),
|
|
4039
4023
|
e(PageHead, {
|
|
@@ -4053,7 +4037,7 @@ export const dashboardClientScript = String.raw `
|
|
|
4053
4037
|
e(Metric, { label: t('overview.metric.completed'), value: formatInt(completed), delta: changes.length ? t('overview.delta.complete', { p: formatPercent(completed / changes.length) }) : t('overview.delta.noChanges') }),
|
|
4054
4038
|
e(Metric, { label: t('overview.metric.traceEvents'), value: formatInt(history.length), delta: props.live ? t('overview.delta.streamConnected') : t('overview.delta.streamIdle'), className: 'accent' }),
|
|
4055
4039
|
e(Metric, { label: t('overview.metric.cliFailures'), value: formatInt(failures), delta: t('overview.delta.recentCli', { n: cli.length }) }),
|
|
4056
|
-
e(Metric, { label: t('overview.metric.latestEvolve'), value:
|
|
4040
|
+
e(Metric, { label: t('overview.metric.latestEvolve'), value: latestEpisode ? formatAdvantage(episodeAdvantage(latestEpisode)) : 'n/a', delta: latestEpisode ? formatDate(episodeTime(latestEpisode)) : t('overview.delta.noEpisodes'), className: 'mono' })
|
|
4057
4041
|
),
|
|
4058
4042
|
e('div', { className: 'layout-2' },
|
|
4059
4043
|
e(Panel, { title: t('overview.section.recentChanges'), meta: t('overview.total', { n: changes.length }), tight: true },
|
|
@@ -4071,8 +4055,8 @@ export const dashboardClientScript = String.raw `
|
|
|
4071
4055
|
e(CliList, { events: cli, limit: 7, onSelect: props.onSelect })
|
|
4072
4056
|
),
|
|
4073
4057
|
e(Panel, { title: t('overview.section.evoRuns') },
|
|
4074
|
-
|
|
4075
|
-
return e(
|
|
4058
|
+
episodes.length ? e('div', { className: 'runs-grid' }, episodes.slice(0, 2).map(function (ep) {
|
|
4059
|
+
return e(EpisodeCard, { key: ep.episodeId, episode: ep, onSelect: props.onSelect });
|
|
4076
4060
|
})) : e(EmptyState, { title: t('overview.empty.noRuns'), hint: t('overview.empty.noRunsHint') })
|
|
4077
4061
|
)
|
|
4078
4062
|
)
|
|
@@ -4193,29 +4177,33 @@ export const dashboardClientScript = String.raw `
|
|
|
4193
4177
|
|
|
4194
4178
|
function SelfEvolveView(props) {
|
|
4195
4179
|
const t = props.t || function (k) { return k; };
|
|
4196
|
-
const
|
|
4197
|
-
const
|
|
4198
|
-
const
|
|
4199
|
-
const latest =
|
|
4200
|
-
const
|
|
4201
|
-
const
|
|
4202
|
-
const
|
|
4203
|
-
?
|
|
4204
|
-
:
|
|
4180
|
+
const episodes = safeArray(props.episodes);
|
|
4181
|
+
const lineages = safeArray(props.policyLineages);
|
|
4182
|
+
const reject = safeArray(props.rejectBuffer);
|
|
4183
|
+
const latest = episodes[0];
|
|
4184
|
+
const candidates = keptEpisodes(episodes);
|
|
4185
|
+
const graded = gradedEpisodes(episodes);
|
|
4186
|
+
const meanAdvantage = graded.length
|
|
4187
|
+
? graded.reduce(function (sum, ep) { return sum + episodeAdvantage(ep); }, 0) / graded.length
|
|
4188
|
+
: null;
|
|
4189
|
+
const headVersion = lineages.reduce(function (max, lineage) {
|
|
4190
|
+
return lineage.headVersion == null ? max : Math.max(max, lineage.headVersion);
|
|
4191
|
+
}, null);
|
|
4192
|
+
const activeLineage = (latest && lineages.find(function (lineage) { return lineage.targetId === latest.targetId; })) || lineages[0] || { entries: [], headVersion: null };
|
|
4205
4193
|
const [selectedPhaseIndex, setSelectedPhaseIndex] = useState(0);
|
|
4206
|
-
const [
|
|
4194
|
+
const [selectedEpisodeId, setSelectedEpisodeId] = useState(latest && latest.episodeId ? latest.episodeId : '');
|
|
4207
4195
|
useEffect(function () {
|
|
4208
|
-
if (!latest || !latest.
|
|
4209
|
-
if (!
|
|
4210
|
-
|
|
4196
|
+
if (!latest || !latest.episodeId) return;
|
|
4197
|
+
if (!selectedEpisodeId || !episodes.some(function (ep) { return ep.episodeId === selectedEpisodeId; })) {
|
|
4198
|
+
setSelectedEpisodeId(latest.episodeId);
|
|
4211
4199
|
}
|
|
4212
|
-
}, [latest && latest.
|
|
4213
|
-
const latestVerdict = latest ?
|
|
4214
|
-
const
|
|
4215
|
-
if (
|
|
4200
|
+
}, [latest && latest.episodeId, selectedEpisodeId, episodes.length]);
|
|
4201
|
+
const latestVerdict = latest ? episodeVerdict(latest) : { label: 'n/a', tone: 'muted' };
|
|
4202
|
+
const openEpisode = function (ep) {
|
|
4203
|
+
if (ep && ep.episodeId) props.onSelect({ type: 'episode', id: ep.episodeId, data: ep });
|
|
4216
4204
|
};
|
|
4217
|
-
const
|
|
4218
|
-
if (entry
|
|
4205
|
+
const openReject = function (entry) {
|
|
4206
|
+
if (entry) props.onSelect({ type: 'reject', id: entry.episodeId, data: entry });
|
|
4219
4207
|
};
|
|
4220
4208
|
return e(React.Fragment, null,
|
|
4221
4209
|
e(PageHead, {
|
|
@@ -4223,45 +4211,46 @@ export const dashboardClientScript = String.raw `
|
|
|
4223
4211
|
title: t('evolve.title'),
|
|
4224
4212
|
subhead: t('evolve.lead'),
|
|
4225
4213
|
actions: [
|
|
4226
|
-
e(Chip, { key: '
|
|
4227
|
-
e(Chip, { key: '
|
|
4214
|
+
e(Chip, { key: 'episodes', label: t('evolve.chip.episodes'), value: formatInt(episodes.length) }),
|
|
4215
|
+
e(Chip, { key: 'version', label: t('evolve.chip.version'), value: headVersion == null ? 'n/a' : 'v' + headVersion })
|
|
4228
4216
|
]
|
|
4229
4217
|
}),
|
|
4230
4218
|
e('section', { className: 'evolve-command-center', 'aria-label': 'Self-evolution command center' },
|
|
4231
4219
|
e('div', { className: 'evolve-status-strip', 'aria-label': 'Self-evolution operational summary' },
|
|
4232
|
-
e(StatusItem, { label: t('evolve.metric.
|
|
4233
|
-
e(StatusItem, { label: t('evolve.metric.candidates'), value: formatInt(candidates.length), detail:
|
|
4220
|
+
e(StatusItem, { label: t('evolve.metric.latestStage'), value: latestVerdict.label, detail: latest ? shortId(latest.episodeId) : t('evolve.metric.waitingEpisodes'), tone: latestVerdict.tone }),
|
|
4221
|
+
e(StatusItem, { label: t('evolve.metric.candidates'), value: formatInt(candidates.length), detail: graded.length ? t('evolve.metric.candidates.detail', { p: formatAdvantage(meanAdvantage) }) : t('evolve.metric.candidates.detailEmpty'), tone: candidates.length ? 'info' : 'bad' })
|
|
4234
4222
|
),
|
|
4235
4223
|
e(NextActionBar, { latest: latest, onSelect: props.onSelect, t: t })
|
|
4236
4224
|
),
|
|
4237
4225
|
e('div', { className: 'evolution-studio' },
|
|
4238
4226
|
e(EvolutionStage, {
|
|
4239
|
-
|
|
4240
|
-
|
|
4227
|
+
episodes: episodes,
|
|
4228
|
+
policyLineages: lineages,
|
|
4241
4229
|
phaseIndex: selectedPhaseIndex,
|
|
4242
4230
|
onPhaseSelect: setSelectedPhaseIndex,
|
|
4243
|
-
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
|
|
4231
|
+
selectedEpisodeId: selectedEpisodeId,
|
|
4232
|
+
onEpisodeSelect: setSelectedEpisodeId,
|
|
4233
|
+
onOpenEpisode: openEpisode,
|
|
4234
|
+
onOpenReject: openReject
|
|
4247
4235
|
}),
|
|
4248
4236
|
e(EvolutionInspector, {
|
|
4249
|
-
|
|
4250
|
-
|
|
4237
|
+
episodes: episodes,
|
|
4238
|
+
policyLineages: lineages,
|
|
4239
|
+
rejectBuffer: reject,
|
|
4251
4240
|
phaseIndex: selectedPhaseIndex,
|
|
4252
4241
|
onPhaseSelect: setSelectedPhaseIndex,
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
|
|
4242
|
+
selectedEpisodeId: selectedEpisodeId,
|
|
4243
|
+
onEpisodeSelect: setSelectedEpisodeId,
|
|
4244
|
+
onOpenEpisode: openEpisode,
|
|
4245
|
+
onOpenReject: openReject
|
|
4257
4246
|
})
|
|
4258
4247
|
),
|
|
4259
|
-
e(Panel, { title: t('evolve.section.history'), meta: t('evolve.
|
|
4260
|
-
e(
|
|
4248
|
+
e(Panel, { title: t('evolve.section.history'), meta: t('evolve.episodes.label', { n: episodes.length }), tight: true },
|
|
4249
|
+
e(EpisodeHistoryTable, { episodes: episodes, onSelect: props.onSelect })
|
|
4261
4250
|
),
|
|
4262
4251
|
e('div', { style: { height: '16px' } }),
|
|
4263
|
-
e(Panel, { title: t('evolve.section.lineage'), meta: t('evolve.
|
|
4264
|
-
e(
|
|
4252
|
+
e(Panel, { title: t('evolve.section.lineage'), meta: t('evolve.ledger.label', { n: headVersion == null ? 0 : headVersion }) },
|
|
4253
|
+
e(PolicyLedger, { lineage: activeLineage })
|
|
4265
4254
|
)
|
|
4266
4255
|
);
|
|
4267
4256
|
}
|
|
@@ -4277,9 +4266,9 @@ export const dashboardClientScript = String.raw `
|
|
|
4277
4266
|
useEffect(function () {
|
|
4278
4267
|
let cancelled = false;
|
|
4279
4268
|
setDetail(null);
|
|
4280
|
-
if (!selected || (selected.type !== '
|
|
4281
|
-
const url = selected.type === '
|
|
4282
|
-
? '/api/
|
|
4269
|
+
if (!selected || (selected.type !== 'episode' && selected.type !== 'change')) return undefined;
|
|
4270
|
+
const url = selected.type === 'episode'
|
|
4271
|
+
? '/api/episodes/' + encodeURIComponent(selected.id)
|
|
4283
4272
|
: '/api/changes/' + encodeURIComponent(selected.id);
|
|
4284
4273
|
setLoading(true);
|
|
4285
4274
|
loadEndpoint(url, selected.data || {}).then(function (result) {
|
|
@@ -4330,16 +4319,16 @@ export const dashboardClientScript = String.raw `
|
|
|
4330
4319
|
|
|
4331
4320
|
if (!selected) return null;
|
|
4332
4321
|
const data = detail || selected.data || {};
|
|
4333
|
-
const title = selected.type === '
|
|
4334
|
-
? '
|
|
4322
|
+
const title = selected.type === 'episode'
|
|
4323
|
+
? 'Episode'
|
|
4335
4324
|
: selected.type === 'change'
|
|
4336
4325
|
? 'Change detail'
|
|
4337
4326
|
: selected.type === 'cli'
|
|
4338
4327
|
? 'CLI event'
|
|
4339
|
-
: selected.type === '
|
|
4340
|
-
? '
|
|
4328
|
+
: selected.type === 'reject' || selected.type === 'ledger'
|
|
4329
|
+
? 'Reject-buffer entry'
|
|
4341
4330
|
: 'Trace event';
|
|
4342
|
-
const subtitle = selected.id || data.
|
|
4331
|
+
const subtitle = selected.id || data.episodeId || data.id || data.eventId || 'detail';
|
|
4343
4332
|
const titleId = 'detail-drawer-title';
|
|
4344
4333
|
return e(React.Fragment, null,
|
|
4345
4334
|
e('div', { className: 'modal-backdrop', onClick: onClose }),
|
|
@@ -4354,7 +4343,6 @@ export const dashboardClientScript = String.raw `
|
|
|
4354
4343
|
e('div', { className: 'slide-body' },
|
|
4355
4344
|
loading ? e('div', { className: 'empty-hint' }, 'loading detail') : null,
|
|
4356
4345
|
e(DetailSummary, { type: selected.type, data: data }),
|
|
4357
|
-
selected.type === 'run' ? e(RunDiagnostics, { data: data }) : null,
|
|
4358
4346
|
e('div', { className: 'section-title' }, 'Payload'),
|
|
4359
4347
|
e('pre', {
|
|
4360
4348
|
style: {
|
|
@@ -4374,58 +4362,20 @@ export const dashboardClientScript = String.raw `
|
|
|
4374
4362
|
);
|
|
4375
4363
|
}
|
|
4376
4364
|
|
|
4377
|
-
function LogBlock(props) {
|
|
4378
|
-
if (!props.text) return null;
|
|
4379
|
-
return e(React.Fragment, null,
|
|
4380
|
-
e('div', { className: 'section-title' }, props.title),
|
|
4381
|
-
e('pre', {
|
|
4382
|
-
style: {
|
|
4383
|
-
margin: '0 0 12px',
|
|
4384
|
-
padding: '12px',
|
|
4385
|
-
border: '1px solid var(--line)',
|
|
4386
|
-
borderRadius: '8px',
|
|
4387
|
-
background: 'var(--surface-2)',
|
|
4388
|
-
color: 'var(--ink-2)',
|
|
4389
|
-
font: '11px/1.5 var(--mono)',
|
|
4390
|
-
maxHeight: '320px',
|
|
4391
|
-
overflow: 'auto',
|
|
4392
|
-
whiteSpace: 'pre-wrap'
|
|
4393
|
-
}
|
|
4394
|
-
}, props.text)
|
|
4395
|
-
);
|
|
4396
|
-
}
|
|
4397
|
-
|
|
4398
|
-
function RunDiagnostics(props) {
|
|
4399
|
-
const data = props.data || {};
|
|
4400
|
-
const fileListing = safeArray(data.fileListing);
|
|
4401
|
-
const hasAny = data.wrapperStderrTail || data.wrapperStdoutTail || fileListing.length;
|
|
4402
|
-
if (!hasAny) return null;
|
|
4403
|
-
return e('div', { style: { marginTop: '12px' } },
|
|
4404
|
-
e(LogBlock, { title: 'wrapper.stderr.log (tail)', text: data.wrapperStderrTail }),
|
|
4405
|
-
e(LogBlock, { title: 'wrapper.stdout.log (tail)', text: data.wrapperStdoutTail }),
|
|
4406
|
-
fileListing.length ? e(React.Fragment, null,
|
|
4407
|
-
e('div', { className: 'section-title' }, 'Run directory'),
|
|
4408
|
-
e('div', { style: { marginBottom: '12px', font: '11px/1.5 var(--mono)', color: 'var(--ink-2)' } },
|
|
4409
|
-
fileListing.join(' '))
|
|
4410
|
-
) : null
|
|
4411
|
-
);
|
|
4412
|
-
}
|
|
4413
|
-
|
|
4414
4365
|
function DetailSummary(props) {
|
|
4415
4366
|
const data = props.data || {};
|
|
4416
4367
|
let rows;
|
|
4417
|
-
if (props.type === '
|
|
4368
|
+
if (props.type === 'episode') {
|
|
4418
4369
|
rows = [
|
|
4419
|
-
['
|
|
4420
|
-
['
|
|
4421
|
-
['
|
|
4422
|
-
['
|
|
4423
|
-
['
|
|
4424
|
-
['
|
|
4425
|
-
['
|
|
4426
|
-
['
|
|
4427
|
-
['
|
|
4428
|
-
['finished', formatDate(data.finishedAt)]
|
|
4370
|
+
['episode', data.episodeId],
|
|
4371
|
+
['stage', data.stage],
|
|
4372
|
+
['change', data.changeName],
|
|
4373
|
+
['target', data.targetId],
|
|
4374
|
+
['advantage', data.advantage != null ? formatAdvantage(data.advantage) : 'abstained'],
|
|
4375
|
+
['main version', data.policyVersionMain == null ? 'n/a' : 'v' + data.policyVersionMain],
|
|
4376
|
+
['baseline version', data.policyVersionBaseline == null ? 'n/a' : 'v' + data.policyVersionBaseline],
|
|
4377
|
+
['created', formatDate(data.createdAt)],
|
|
4378
|
+
['updated', formatDate(data.updatedAt)]
|
|
4429
4379
|
];
|
|
4430
4380
|
} else if (props.type === 'change') {
|
|
4431
4381
|
rows = [
|
|
@@ -4446,14 +4396,15 @@ export const dashboardClientScript = String.raw `
|
|
|
4446
4396
|
['started', formatDate(data.startedAt)],
|
|
4447
4397
|
['finished', formatDate(data.finishedAt)]
|
|
4448
4398
|
];
|
|
4449
|
-
} else if (props.type === '
|
|
4399
|
+
} else if (props.type === 'reject' || props.type === 'ledger') {
|
|
4400
|
+
const summary = safeObject(data.editSummary);
|
|
4450
4401
|
rows = [
|
|
4451
|
-
['
|
|
4452
|
-
['
|
|
4453
|
-
['
|
|
4454
|
-
['
|
|
4455
|
-
['
|
|
4456
|
-
['
|
|
4402
|
+
['episode', data.episodeId],
|
|
4403
|
+
['from', data.fromVersion == null ? 'n/a' : 'v' + data.fromVersion],
|
|
4404
|
+
['to', data.toVersion == null ? 'n/a' : 'v' + data.toVersion],
|
|
4405
|
+
['advantage', data.advantage != null ? formatAdvantage(data.advantage) : 'n/a'],
|
|
4406
|
+
['reason', data.reason],
|
|
4407
|
+
['rationale', summary.rationaleExcerpt]
|
|
4457
4408
|
];
|
|
4458
4409
|
} else {
|
|
4459
4410
|
rows = [
|
|
@@ -4746,8 +4697,9 @@ export const dashboardClientScript = String.raw `
|
|
|
4746
4697
|
const [changes, setChanges] = useState(initial && Array.isArray(initial.changes) ? initial.changes : []);
|
|
4747
4698
|
const [cli, setCli] = useState(initial && Array.isArray(initial.cliHistory) ? initial.cliHistory : []);
|
|
4748
4699
|
const [agentInterface, setAgentInterface] = useState(initial && initial.agentInterface ? initial.agentInterface : {});
|
|
4749
|
-
const [
|
|
4750
|
-
const [
|
|
4700
|
+
const [episodes, setEpisodes] = useState(initial && Array.isArray(initial.episodes) ? initial.episodes : []);
|
|
4701
|
+
const [policyLineages, setPolicyLineages] = useState(initial && Array.isArray(initial.policyLineages) ? initial.policyLineages : []);
|
|
4702
|
+
const [rejectBuffer, setRejectBuffer] = useState(initial && Array.isArray(initial.rejectBuffer) ? initial.rejectBuffer : []);
|
|
4751
4703
|
const [architecture, setArchitecture] = useState(initial && initial.architecture ? initial.architecture : {});
|
|
4752
4704
|
const [history, setHistory] = useState(initial && Array.isArray(initial.history) ? initial.history : []);
|
|
4753
4705
|
const [streamEvents, setStreamEvents] = useState([]);
|
|
@@ -4762,8 +4714,9 @@ export const dashboardClientScript = String.raw `
|
|
|
4762
4714
|
loadEndpoint(API.changes, []),
|
|
4763
4715
|
loadEndpoint(API.cliHistory, []),
|
|
4764
4716
|
loadEndpoint(API.agentInterface, {}),
|
|
4765
|
-
loadEndpoint(API.
|
|
4766
|
-
loadEndpoint(API.
|
|
4717
|
+
loadEndpoint(API.episodes, []),
|
|
4718
|
+
loadEndpoint(API.policyLedger, []),
|
|
4719
|
+
loadEndpoint(API.rejectBuffer, []),
|
|
4767
4720
|
loadEndpoint(API.history, []),
|
|
4768
4721
|
loadEndpoint(API.architecture, {})
|
|
4769
4722
|
]);
|
|
@@ -4771,10 +4724,11 @@ export const dashboardClientScript = String.raw `
|
|
|
4771
4724
|
setChanges(safeArray(results[1].value));
|
|
4772
4725
|
setCli(safeArray(results[2].value));
|
|
4773
4726
|
setAgentInterface(safeObject(results[3].value));
|
|
4774
|
-
|
|
4775
|
-
|
|
4776
|
-
|
|
4777
|
-
|
|
4727
|
+
setEpisodes(safeArray(results[4].value));
|
|
4728
|
+
setPolicyLineages(safeArray(results[5].value));
|
|
4729
|
+
setRejectBuffer(safeArray(results[6].value));
|
|
4730
|
+
setHistory(safeArray(results[7].value));
|
|
4731
|
+
setArchitecture(safeObject(results[8].value));
|
|
4778
4732
|
const errors = results.filter(function (result) { return !result.ok; }).map(function (result) { return result.error; });
|
|
4779
4733
|
setError(errors.join(' | '));
|
|
4780
4734
|
setLoading(false);
|
|
@@ -4822,10 +4776,10 @@ export const dashboardClientScript = String.raw `
|
|
|
4822
4776
|
openChanges: openChanges,
|
|
4823
4777
|
readyToLearn: readyToLearn,
|
|
4824
4778
|
totalTrace: history.length,
|
|
4825
|
-
|
|
4779
|
+
totalEpisodes: episodes.length,
|
|
4826
4780
|
totalAgentSignals: numberOr(agentSummary.totalSignals, 0)
|
|
4827
4781
|
};
|
|
4828
|
-
}, [changes, history,
|
|
4782
|
+
}, [changes, history, episodes, agentInterface]);
|
|
4829
4783
|
|
|
4830
4784
|
const tickerItems = streamEvents.length ? streamEvents : sortByTimeDesc(history).slice(0, 10);
|
|
4831
4785
|
const setView = useCallback(function (nextView) {
|
|
@@ -4840,8 +4794,9 @@ export const dashboardClientScript = String.raw `
|
|
|
4840
4794
|
changes: changes,
|
|
4841
4795
|
cli: cli,
|
|
4842
4796
|
agentInterface: agentInterface,
|
|
4843
|
-
|
|
4844
|
-
|
|
4797
|
+
episodes: episodes,
|
|
4798
|
+
policyLineages: policyLineages,
|
|
4799
|
+
rejectBuffer: rejectBuffer,
|
|
4845
4800
|
history: history,
|
|
4846
4801
|
architecture: architecture,
|
|
4847
4802
|
streamEvents: streamEvents,
|