Selaa lähdekoodia

三问连答: 一次呈现三问+---分隔/JSON/单段三格式解析+缺项逐问补漏+SKILL同步

liuyuyang 1 viikko sitten
vanhempi
commit
264dd2ae8f
2 muutettua tiedostoa jossa 54 lisäystä ja 5 poistoa
  1. 1 1
      skills/study-report/SKILL.md
  2. 53 4
      skills/study-report/scripts/ask.mjs

+ 1 - 1
skills/study-report/SKILL.md

@@ -1,6 +1,6 @@
 ---
 name: study-report
-description: "学习复盘报告:自动采集近 48h 全部 Agent 工作痕迹(Claude Code/Codex/Trae/WorkBuddy/OpenClaw/元宝/Hermes/工作区)→ 三问追问感受 → 生成 skill-present 级 HTML 复盘 PPT → Storage+Gogs 双通道发布。适用:(1) 培训/研修结营复盘 (2) 数字生命工作总结 (3) 一键转发给学员 Agent 代跑全流程。"
+description: "学习复盘报告:自动采集近 48h 全部 Agent 工作痕迹(Claude Code/Codex/Trae/WorkBuddy/OpenClaw/元宝/Hermes/工作区)→ 三问追问(一次呈现三问,支持一次性连答:三段用 --- 分隔或 JSON;缺项再逐问补一轮)感受 → 生成 skill-present 级 HTML 复盘 PPT → Storage+Gogs 双通道发布。适用:(1) 培训/研修结营复盘 (2) 数字生命工作总结 (3) 一键转发给学员 Agent 代跑全流程。"
 description_en: "Learning retrospective: auto-collect 48h of all Agent work traces, ask the user three reflection questions, build a skill-present-grade HTML PPT report, and publish via Storage+Gogs dual channels. Triggers: training retrospective, agent work summary, forwardable one-click skill."
 ---
 

+ 53 - 4
skills/study-report/scripts/ask.mjs

@@ -1,7 +1,8 @@
 /**
- * ask.mjs — 三问追问交互(逐问等待用户
+ * ask.mjs — 三问追问交互(一次呈现三问,支持连答
  *
- * 采集完成后固定三轮问题(过去/现在/未来),逐问在终端等待用户输入;
+ * 采集完成后固定三问(过去/现在/未来)一次全部呈现,用户可一次性连答(推荐,省时);
+ * 也兼容逐问回答(每答以「---」分隔)或分次补充;
  * 用户口述与采集素材做「关联标记」(口述里提到的项目名 ↔ 采集条目证据)。
  * 用户不答(直接回车 / 超时 / --non-interactive)→ 该问记空值并标注【待补充:用户口述】,
  * 上游用采集数据先行出报告——不阻塞、不编造用户感受。
@@ -33,6 +34,33 @@ const QUESTIONS = [
   },
 ];
 
+/** 连答解析:把一次输入按分隔符拆成三问答案
+ *  支持三种格式:
+ *  A) 一次粘贴三段,以行「---」分隔 → 依序对应过去/现在/未来
+ *  B) JSON 对象 {"past":"...","present":"...","future":"..."}
+ *  C) 空输入 → 全部跳过
+ */
+export function parseBatchAnswer(raw) {
+  const out = { past: '', present: '', future: '' };
+  if (!raw || !raw.trim()) return out;
+  const s = raw.trim();
+  if (s.startsWith('{')) {
+    try {
+      const j = JSON.parse(s);
+      for (const q of QUESTIONS) out[q.key] = String(j[q.key] || '').trim();
+      return out;
+    } catch { /* 非 JSON, 走分隔符 */ }
+  }
+  const parts = s.split(/^---+$/m).map(x => x.trim()).filter(Boolean);
+  if (parts.length >= 3) {
+    out.past = parts[0]; out.present = parts[1]; out.future = parts.slice(2).join('\n');
+  } else {
+    // 无分隔符: 单段输入 → 记入"现在"(最常见的单次表达), 其余标待补充
+    out.present = s;
+  }
+  return out;
+}
+
 /** 口述 → 采集素材关联标记:问题里提到的项目/文件关键词 ↔ 采集条目 */
 export function linkAnswersToEvidence(answers, collectResult) {
   const links = {};
@@ -119,10 +147,31 @@ export async function runAsk({ collectFile = null, answersFile = null, timeoutMs
     console.log('[ask] 非交互模式:三轮问题全部标注【待补充:用户口述】,报告先行用采集数据生成。');
   } else {
     const nextLine = makeLineReader();
+    // 连答模式:一次呈现三问,用户可一次性回答(推荐)
+    console.log(`\n${'═'.repeat(60)}`);
+    console.log('【复盘三问】可以一次性连答(推荐)——三段答案之间用一行 --- 分隔;');
+    console.log('  也可以直接回车进入逐问模式;输入 JSON {"past":"…","present":"…","future":"…"} 亦可。');
     for (const q of QUESTIONS) {
-      console.log(`\n${'═'.repeat(60)}`);
-      console.log(`【${q.tag}】${q.text}`);
+      console.log(`\n【${q.tag}】${q.text}`);
       console.log(`  (示例:${q.placeholder})`);
+    }
+    console.log(`\n${'─'.repeat(60)}`);
+    console.log('请粘贴你的回答(三段用 --- 分隔,或 JSON;直接回车=逐问模式):');
+    process.stdout.write('> ');
+    const raw = await nextLine(Math.max(timeoutMs, 180000));
+    const batch = parseBatchAnswer(raw || '');
+    const gotAny = batch.past || batch.present || batch.future;
+    if (gotAny) {
+      Object.assign(answers, batch);
+      for (const q of QUESTIONS) {
+        if (answers[q.key]) console.log(`  ✓ ${q.tag}:已记录 ${answers[q.key].length} 字`);
+      }
+    }
+    // 逐问补漏:连答缺失的问项再单独问一轮(每问一次机会)
+    for (const q of QUESTIONS) {
+      if (answers[q.key]) continue;
+      console.log(`\n【${q.tag}】${q.text}`);
+      console.log(`  (示例:${q.placeholder})(直接回车跳过)`);
       process.stdout.write('> ');
       const line = await nextLine(timeoutMs);
       answers[q.key] = (line || '').trim();