diff --git a/design/ui_kits/console/Transcript.jsx b/design/ui_kits/console/Transcript.jsx
new file mode 100644
index 0000000..c4ba1ca
--- /dev/null
+++ b/design/ui_kits/console/Transcript.jsx
@@ -0,0 +1,48 @@
+// 历史 transcript 回放:拉某任务指定 kind 的 run 的转录(/api/tasks/:id/runs → /api/runs/:id/transcript),
+// 渲染成结构化行(text / tool_use / tool_result / result)。挂 window.MaestroTranscript,供拆解评审「拆解轨迹」等处复用。
+// 转录已是脱敏 + 截断的扁平 schema:{type, text?, name?, input?, isError?}(见 src/executor/transcript.ts)。
+function TcLine({ m }) {
+ if (m.type === 'tool_use') {
+ return
⚙ {m.name}{m.input ? {m.input} : null}
;
+ }
+ if (m.type === 'tool_result') {
+ return
↩ {m.text || '(空)'}
;
+ }
+ if (m.type === 'result') return
■ {m.text || 'done'}
;
+ return
{m.text}
;
+}
+
+function MaestroTranscript({ taskId, kind }) {
+ const [state, setState] = React.useState({ loading: true, msgs: null, err: false });
+ React.useEffect(() => {
+ let alive = true;
+ setState({ loading: true, msgs: null, err: false });
+ (async () => {
+ try {
+ const runs = await fetch('/api/tasks/' + taskId + '/runs').then((r) => r.ok ? r.json() : Promise.reject(new Error('http')));
+ const list = Array.isArray(runs) ? runs : [];
+ const run = (kind ? list.filter((r) => r.kind === kind) : list)
+ .slice().sort((a, b) => String(b.startedAt || '').localeCompare(String(a.startedAt || '')))[0] || list[0];
+ if (!run) { if (alive) setState({ loading: false, msgs: [], err: false }); return; }
+ const d = await fetch('/api/runs/' + run.id + '/transcript').then((r) => r.ok ? r.json() : Promise.reject(new Error('http')));
+ const msgs = Array.isArray(d) ? d : (d.messages || []);
+ if (alive) setState({ loading: false, msgs, err: false });
+ } catch (e) {
+ if (alive) setState({ loading: false, msgs: null, err: true });
+ }
+ })();
+ return () => { alive = false; };
+ }, [taskId, kind]);
+
+ const hint = (txt) =>
{txt}
;
+ if (state.loading) return hint('… 加载轨迹');
+ if (state.err) return hint('轨迹取不到');
+ if (!state.msgs || !state.msgs.length) return hint('无轨迹记录');
+ return (
+
+ {state.msgs.map((m, i) => )}
+
+ );
+}
+
+window.MaestroTranscript = MaestroTranscript;
diff --git a/design/ui_kits/console/i18n.js b/design/ui_kits/console/i18n.js
index 9956fae..5c6132f 100644
--- a/design/ui_kits/console/i18n.js
+++ b/design/ui_kits/console/i18n.js
@@ -35,7 +35,7 @@ window.MAESTRO_I18N = {
fgroups: { todo: '待办', doing: '进行中', gate: '待审批', bad: '异常', hold: '挂起', done: '完成' },
fStatus: '状态', fAssignee: '执行者', assignees: { agent: '智能体', human: '人工' },
fullRead: '全屏阅读', depsLabel: 'DEPS · 依赖(全部完成才可执行)', depDone: '完成', depWait: '等待',
- gateSection: '审批闸', accept: '✓ 通过', reject: '✕ 驳回', confirmReject: '确认驳回',
+ gateSection: '需你处理', gateNeedsHuman: '需人工', gRequeue: '↻ 重投', gTakeover: '⌨ 接管', gCancelTask: '⊘ 取消', accept: '✓ 通过', reject: '✕ 驳回', confirmReject: '确认驳回',
rejectPlaceholder: '改进意见(必填)',
taskSection: '任务树', newTask: '+ 新建任务', titleLabel: '标题', titlePlaceholder: '要做什么',
complexity: '复杂度', cplxAuto: '智能', parentTask: '父任务', topLevel: '(顶层)', priority: '优先级',
@@ -49,7 +49,7 @@ window.MAESTRO_I18N = {
gatePassed: ' 通过',
status: { init: '新建', analyzing: '分析拆解中', plan_review: '待确认拆解', decomposed: '已拆解', speccing: '写方案中', spec_review: '待确认方案', ready: '可执行', blocked: '被依赖阻塞', queued: '排队中', executing: '执行中', exec_review: '待审/合', failed: '失败', needs_attention: '需人工', done: '完成', paused: '暂停', cancelled: '取消' },
gates: { plan: '拆解评审', spec: '方案评审', exec: '结果评审' },
- gateSubtasks: '拆解出的子任务', noDeps: '无依赖', dependsOn: '依赖',
+ gateSubtasks: '拆解出的子任务', frozenPending: '待拆解确认', scopeFiles: '文件范围', planTranscript: '拆解轨迹(agent 执行记录)', noDeps: '无依赖', dependsOn: '依赖',
lblCodeReview: '代码复审', lblSecurity: '安全审计', lblChanges: '改动', vApprove: '通过', vReject: '驳回', vNone: '无结论',
eventTypes: { 'task.created': '任务创建', 'task.updated': '任务更新', 'status.changed': '状态变更', 'approval.requested': '请求审批', 'approval.granted': '审批通过', 'approval.rejected': '审批驳回', 'run.started': '运行开始', 'run.finished': '运行结束', 'project.synced': 'todo 同步' },
},
@@ -85,7 +85,7 @@ window.MAESTRO_I18N = {
fgroups: { todo: 'To do', doing: 'In progress', gate: 'Pending review', bad: 'Issues', hold: 'On hold', done: 'Done' },
fStatus: 'Status', fAssignee: 'Assignee', assignees: { agent: 'Agent', human: 'Human' },
fullRead: 'Read fullscreen', depsLabel: 'DEPS (all must complete to run)', depDone: 'done', depWait: 'waiting',
- gateSection: 'Approval gates', accept: '✓ Accept', reject: '✕ Reject', confirmReject: 'Confirm reject',
+ gateSection: 'Needs you', gateNeedsHuman: 'Needs human', gRequeue: '↻ Requeue', gTakeover: '⌨ Take over', gCancelTask: '⊘ Cancel', accept: '✓ Accept', reject: '✕ Reject', confirmReject: 'Confirm reject',
rejectPlaceholder: 'Improvement feedback (required)',
taskSection: 'Task tree', newTask: '+ New task', titleLabel: 'Title', titlePlaceholder: 'What needs doing',
complexity: 'Complexity', cplxAuto: 'AUTO', parentTask: 'Parent', topLevel: '(top level)', priority: 'Priority',
@@ -99,7 +99,7 @@ window.MAESTRO_I18N = {
gatePassed: ' approved',
status: { init: 'New', analyzing: 'Analyzing', plan_review: 'Plan review', decomposed: 'Decomposed', speccing: 'Drafting spec', spec_review: 'Spec review', ready: 'Ready', blocked: 'Blocked', queued: 'Queued', executing: 'Executing', exec_review: 'Review & merge', failed: 'Failed', needs_attention: 'Needs attention', done: 'Done', paused: 'Paused', cancelled: 'Cancelled' },
gates: { plan: 'PLAN REVIEW', spec: 'SPEC REVIEW', exec: 'EXEC REVIEW' },
- gateSubtasks: 'Decomposed subtasks', noDeps: 'no deps', dependsOn: 'deps',
+ gateSubtasks: 'Decomposed subtasks', frozenPending: 'awaiting approval', scopeFiles: 'files', planTranscript: 'Decompose trace', noDeps: 'no deps', dependsOn: 'deps',
lblCodeReview: 'Code review', lblSecurity: 'Security', lblChanges: 'Changes', vApprove: 'Approve', vReject: 'Reject', vNone: 'No verdict',
eventTypes: { 'task.created': 'Task created', 'task.updated': 'Task updated', 'status.changed': 'Status changed', 'approval.requested': 'Approval requested', 'approval.granted': 'Approval granted', 'approval.rejected': 'Approval rejected', 'run.started': 'Run started', 'run.finished': 'Run finished', 'project.synced': 'Todo synced' },
},
@@ -135,7 +135,7 @@ window.MAESTRO_I18N = {
fgroups: { todo: 'Pendientes', doing: 'En curso', gate: 'Por revisar', bad: 'Incidencias', hold: 'En pausa', done: 'Hechas' },
fStatus: 'Estado', fAssignee: 'Ejecutor', assignees: { agent: 'Agente', human: 'Humano' },
fullRead: 'Pantalla completa', depsLabel: 'DEPS (todas deben completarse)', depDone: 'hecha', depWait: 'esperando',
- gateSection: 'Puertas de aprobación', accept: '✓ Aceptar', reject: '✕ Rechazar', confirmReject: 'Confirmar rechazo',
+ gateSection: 'Requiere acción', gateNeedsHuman: 'Manual', gRequeue: '↻ Reencolar', gTakeover: '⌨ Tomar', gCancelTask: '⊘ Cancelar', accept: '✓ Aceptar', reject: '✕ Rechazar', confirmReject: 'Confirmar rechazo',
rejectPlaceholder: 'Comentario de mejora (obligatorio)',
taskSection: 'Árbol de tareas', newTask: '+ Nueva tarea', titleLabel: 'Título', titlePlaceholder: 'Qué hay que hacer',
complexity: 'Complejidad', cplxAuto: 'AUTO', parentTask: 'Padre', topLevel: '(raíz)', priority: 'Prioridad',
@@ -149,7 +149,7 @@ window.MAESTRO_I18N = {
gatePassed: ' aprobada',
status: { init: 'Nueva', analyzing: 'Analizando', plan_review: 'Revisión de plan', decomposed: 'Descompuesta', speccing: 'Redactando spec', spec_review: 'Revisión de spec', ready: 'Lista', blocked: 'Bloqueada', queued: 'En cola', executing: 'Ejecutando', exec_review: 'Revisar y fusionar', failed: 'Fallida', needs_attention: 'Requiere atención', done: 'Hecha', paused: 'Pausada', cancelled: 'Cancelada' },
gates: { plan: 'REVISIÓN DE PLAN', spec: 'REVISIÓN DE SPEC', exec: 'REVISIÓN DE RESULTADO' },
- gateSubtasks: 'Subtareas', noDeps: 'sin deps', dependsOn: 'deps',
+ gateSubtasks: 'Subtareas', frozenPending: 'pendiente aprob.', scopeFiles: 'archivos', planTranscript: 'Traza de descomposición', noDeps: 'sin deps', dependsOn: 'deps',
lblCodeReview: 'Revisión', lblSecurity: 'Seguridad', lblChanges: 'Cambios', vApprove: 'Aprobar', vReject: 'Rechazar', vNone: 'Sin veredicto',
eventTypes: { 'task.created': 'Tarea creada', 'task.updated': 'Tarea actualizada', 'status.changed': 'Cambio de estado', 'approval.requested': 'Aprobación solicitada', 'approval.granted': 'Aprobación concedida', 'approval.rejected': 'Aprobación rechazada', 'run.started': 'Run iniciado', 'run.finished': 'Run terminado', 'project.synced': 'Todo sincronizado' },
},
@@ -185,7 +185,7 @@ window.MAESTRO_I18N = {
fgroups: { todo: '未着手', doing: '進行中', gate: '承認待ち', bad: '異常', hold: '保留', done: '完了' },
fStatus: 'ステータス', fAssignee: '担当', assignees: { agent: 'エージェント', human: '人手' },
fullRead: '全画面で読む', depsLabel: 'DEPS · 依存(全完了で実行可)', depDone: '完了', depWait: '待機',
- gateSection: '承認ゲート', accept: '✓ 承認', reject: '✕ 却下', confirmReject: '却下を確定',
+ gateSection: '要対応', gateNeedsHuman: '要人手', gRequeue: '↻ 再投入', gTakeover: '⌨ 引継ぎ', gCancelTask: '⊘ 取消', accept: '✓ 承認', reject: '✕ 却下', confirmReject: '却下を確定',
rejectPlaceholder: '改善フィードバック(必須)',
taskSection: 'タスクツリー', newTask: '+ 新規タスク', titleLabel: 'タイトル', titlePlaceholder: '何をしますか',
complexity: '複雑度', cplxAuto: '智能', parentTask: '親タスク', topLevel: '(トップ)', priority: '優先度',
@@ -199,7 +199,7 @@ window.MAESTRO_I18N = {
gatePassed: ' 承認',
status: { init: '新規', analyzing: '分析・分解中', plan_review: '分解確認待ち', decomposed: '分解済み', speccing: '方針作成中', spec_review: '方針確認待ち', ready: '実行可能', blocked: '依存ブロック', queued: 'キュー待ち', executing: '実行中', exec_review: 'レビュー/マージ', failed: '失敗', needs_attention: '要対応', done: '完了', paused: '一時停止', cancelled: 'キャンセル' },
gates: { plan: '分解レビュー', spec: '方針レビュー', exec: '結果レビュー' },
- gateSubtasks: '分解されたサブタスク', noDeps: '依存なし', dependsOn: '依存',
+ gateSubtasks: '分解されたサブタスク', frozenPending: '承認待ち', scopeFiles: 'ファイル範囲', planTranscript: '分解トレース', noDeps: '依存なし', dependsOn: '依存',
lblCodeReview: 'コードレビュー', lblSecurity: 'セキュリティ', lblChanges: '変更', vApprove: '承認', vReject: '却下', vNone: '判定なし',
eventTypes: { 'task.created': 'タスク作成', 'task.updated': 'タスク更新', 'status.changed': 'ステータス変更', 'approval.requested': '承認リクエスト', 'approval.granted': '承認', 'approval.rejected': '却下', 'run.started': 'run 開始', 'run.finished': 'run 終了', 'project.synced': 'todo 同期' },
},
@@ -235,7 +235,7 @@ window.MAESTRO_I18N = {
fgroups: { todo: 'À faire', doing: 'En cours', gate: 'À approuver', bad: 'Anomalies', hold: 'En attente', done: 'Terminées' },
fStatus: 'Statut', fAssignee: 'Exécutant', assignees: { agent: 'Agent', human: 'Humain' },
fullRead: 'Plein écran', depsLabel: 'DEPS (toutes requises)', depDone: 'terminée', depWait: 'en attente',
- gateSection: "Portes d'approbation", accept: '✓ Accepter', reject: '✕ Rejeter', confirmReject: 'Confirmer le rejet',
+ gateSection: 'À traiter', gateNeedsHuman: 'Manuel', gRequeue: '↻ Relancer', gTakeover: '⌨ Reprendre', gCancelTask: '⊘ Annuler', accept: '✓ Accepter', reject: '✕ Rejeter', confirmReject: 'Confirmer le rejet',
rejectPlaceholder: "Retour d'amélioration (obligatoire)",
taskSection: 'Arbre des tâches', newTask: '+ Nouvelle tâche', titleLabel: 'Titre', titlePlaceholder: 'Que faut-il faire',
complexity: 'Complexité', cplxAuto: 'AUTO', parentTask: 'Parent', topLevel: '(racine)', priority: 'Priorité',
@@ -249,7 +249,7 @@ window.MAESTRO_I18N = {
gatePassed: ' approuvée',
status: { init: 'Nouvelle', analyzing: 'Analyse', plan_review: 'Revue du plan', decomposed: 'Décomposée', speccing: 'Rédaction spec', spec_review: 'Revue de spec', ready: 'Prête', blocked: 'Bloquée', queued: 'En file', executing: 'En exécution', exec_review: 'Revue & fusion', failed: 'Échouée', needs_attention: 'À traiter', done: 'Terminée', paused: 'En pause', cancelled: 'Annulée' },
gates: { plan: 'REVUE DU PLAN', spec: 'REVUE DE SPEC', exec: 'REVUE DU RÉSULTAT' },
- gateSubtasks: 'Sous-tâches', noDeps: 'sans deps', dependsOn: 'deps',
+ gateSubtasks: 'Sous-tâches', frozenPending: 'en attente', scopeFiles: 'fichiers', planTranscript: 'Trace de décomposition', noDeps: 'sans deps', dependsOn: 'deps',
lblCodeReview: 'Revue', lblSecurity: 'Sécurité', lblChanges: 'Modifs', vApprove: 'Approuver', vReject: 'Rejeter', vNone: 'Sans verdict',
eventTypes: { 'task.created': 'Tâche créée', 'task.updated': 'Tâche mise à jour', 'status.changed': "Changement d'état", 'approval.requested': 'Approbation demandée', 'approval.granted': 'Approbation accordée', 'approval.rejected': 'Approbation rejetée', 'run.started': 'Run démarré', 'run.finished': 'Run terminé', 'project.synced': 'Todo synchronisé' },
},
diff --git a/design/ui_kits/console/index.html b/design/ui_kits/console/index.html
index 745e707..cc5b888 100644
--- a/design/ui_kits/console/index.html
+++ b/design/ui_kits/console/index.html
@@ -10,6 +10,11 @@
+
+
+
+
+
@@ -37,6 +42,8 @@
+
+