@longtable/cli 0.1.57 → 0.1.59

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/dist/debate.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { join } from "node:path";
2
- import { buildInvocationIntent, buildPanelPlan } from "./panel.js";
2
+ import { buildInvocationIntent, buildPanelDecisionContext, buildPanelPlan } from "./panel.js";
3
3
  import { getPersonaDefinition, parsePersonaKey } from "./personas.js";
4
4
  function nowIso() {
5
5
  return new Date().toISOString();
@@ -167,6 +167,10 @@ function buildSynthesis(plan, artifactPath, kind) {
167
167
  const labels = plan.members.map((member) => member.label);
168
168
  const highSensitivity = plan.checkpointSensitivity === "high";
169
169
  const runLabel = kind === "debate" ? "panel debate" : "panel review";
170
+ const decisionContext = buildPanelDecisionContext(plan.prompt);
171
+ const localizedRunLabel = decisionContext.language === "ko"
172
+ ? (kind === "debate" ? "패널 토론" : "패널 리뷰")
173
+ : runLabel;
170
174
  return {
171
175
  artifactPath,
172
176
  summary: `The ${runLabel} completed across ${labels.join(", ")}. It should slow closure by turning role disagreement into an explicit researcher decision.`,
@@ -187,13 +191,16 @@ function buildSynthesis(plan, artifactPath, kind) {
187
191
  "Choose whether the debate should affect the current artifact, the research design, or only the decision log."
188
192
  ],
189
193
  recommendedCheckpoint: highSensitivity
190
- ? `The ${runLabel} surfaced high-sensitivity disagreement. What should LongTable treat as the next human decision before closure?`
191
- : `The ${runLabel} surfaced role disagreement. Should LongTable revise, verify evidence, proceed, or keep the tension open?`
194
+ ? (decisionContext.language === "ko"
195
+ ? `${localizedRunLabel}에서 ${decisionContext.focus} 대한 높은 민감도의 불일치가 드러났습니다. ${decisionContext.decisionQuestion}`
196
+ : `The ${runLabel} surfaced high-sensitivity disagreement about ${decisionContext.focus}. ${decisionContext.decisionQuestion}`)
197
+ : decisionContext.decisionQuestion
192
198
  };
193
199
  }
194
200
  export function createTeamDebateQuestionRecord(run, provider) {
195
201
  const createdAt = nowIso();
196
202
  const isDebate = run.interactionDepth === "debated";
203
+ const decisionContext = buildPanelDecisionContext(run.prompt);
197
204
  return {
198
205
  id: createId("question_record"),
199
206
  createdAt,
@@ -202,51 +209,32 @@ export function createTeamDebateQuestionRecord(run, provider) {
202
209
  prompt: {
203
210
  id: createId("question_prompt"),
204
211
  checkpointKey: "panel_debate_next_decision",
205
- title: isDebate ? "Panel debate follow-up decision" : "Panel review follow-up decision",
212
+ title: decisionContext.language === "ko"
213
+ ? (isDebate ? "패널 토론 후속 결정" : "패널 리뷰 후속 결정")
214
+ : (isDebate ? "Panel debate follow-up decision" : "Panel review follow-up decision"),
206
215
  question: run.synthesis.recommendedCheckpoint,
207
216
  type: "single_choice",
208
- options: [
209
- {
210
- value: "revise",
211
- label: "Revise before proceeding",
212
- description: "Use the debate result to revise the claim, design, or draft first."
213
- },
214
- {
215
- value: "evidence",
216
- label: "Gather or verify evidence first",
217
- description: "Check source, data, or local artifact support before proceeding."
218
- },
219
- {
220
- value: "proceed",
221
- label: "Proceed with current direction",
222
- description: "Accept the risk profile and continue with the current direction."
223
- },
224
- {
225
- value: "defer",
226
- label: "Keep this open",
227
- description: "Do not commit yet; keep the debate issue visible as an open tension."
228
- }
229
- ],
217
+ options: decisionContext.options,
230
218
  allowOther: true,
231
- otherLabel: "Other decision",
219
+ otherLabel: decisionContext.otherLabel,
232
220
  required: run.roles.some((member) => {
233
221
  const key = parsePersonaKey(member.role);
234
222
  return key ? getPersonaDefinition(key).checkpointSensitivity === "high" : false;
235
223
  }),
236
224
  source: "runtime_guidance",
237
- displayReason: isDebate
238
- ? "Role rebuttals and convergence should connect to an explicit researcher decision."
239
- : "Cross-review created role disagreement that should connect to an explicit researcher decision.",
225
+ displayReason: decisionContext.displayReason,
240
226
  rationale: [
241
227
  "LongTable panel orchestration is a research harness surface, not a substitute for researcher judgment.",
242
228
  isDebate
243
229
  ? "The fixed debate rounds created disagreement that should connect to an explicit researcher decision."
244
230
  : "The cross-review round created disagreement that should connect to an explicit researcher decision.",
231
+ `Panel decision focus: ${decisionContext.focus}.`,
232
+ "Panel follow-up choices are compact by default; unlisted decisions should use Other.",
245
233
  `LongTable panel run: ${run.id}.`
246
234
  ],
247
235
  preferredSurfaces: provider === "claude"
248
236
  ? ["native_structured", "numbered"]
249
- : ["mcp_elicitation", "numbered"]
237
+ : ["tmux_popup", "mcp_elicitation", "numbered"]
250
238
  }
251
239
  };
252
240
  }
@@ -57,12 +57,41 @@ function readCombinedOutput(payload) {
57
57
  safeString(payload.output)
58
58
  ].filter(Boolean).join("\n").trim();
59
59
  }
60
- function formatQuestionOptions(question) {
61
- const options = question.prompt.options.map((option) => option.value);
60
+ function questionUsesKorean(question) {
61
+ return /[가-힣]/.test([
62
+ question.prompt.title,
63
+ question.prompt.question,
64
+ question.prompt.displayReason ?? "",
65
+ ...question.prompt.options.flatMap((option) => [option.label, option.description ?? ""]),
66
+ question.prompt.otherLabel ?? ""
67
+ ].join("\n"));
68
+ }
69
+ function formatQuestionChoices(question) {
70
+ const korean = questionUsesKorean(question);
71
+ const options = question.prompt.options.flatMap((option, index) => {
72
+ const recommended = option.recommended ? (korean ? " (추천)" : " (recommended)") : "";
73
+ return [
74
+ `${index + 1}. ${option.label}${recommended}`,
75
+ ...(option.description ? [` ${option.description}`] : []),
76
+ ` ${korean ? "기록값" : "Record value"}: ${option.value}`
77
+ ];
78
+ });
62
79
  if (question.prompt.allowOther) {
63
- options.push("other");
80
+ options.push(`${question.prompt.options.length + 1}. ${question.prompt.otherLabel ?? (korean ? "직접 입력" : "Other")}`);
81
+ options.push(` ${korean ? "기록값" : "Record value"}: other`);
64
82
  }
65
- return options.join("/");
83
+ return options.join("\n");
84
+ }
85
+ function buildQuestionDecisionCard(question) {
86
+ const korean = questionUsesKorean(question);
87
+ return [
88
+ korean ? "LongTable 결정 카드" : "LongTable Decision Card",
89
+ `${korean ? "체크포인트" : "Checkpoint"}: ${question.prompt.title}`,
90
+ `${korean ? "무엇이 걸렸나" : "What is blocked"}: ${question.prompt.displayReason ?? question.prompt.rationale[0] ?? question.prompt.title}`,
91
+ `${korean ? "지금 결정할 것" : "Decision needed"}: ${question.prompt.question}`,
92
+ korean ? "선택지:" : "Choices:",
93
+ formatQuestionChoices(question)
94
+ ].join("\n");
66
95
  }
67
96
  function pendingRequiredQuestions(state) {
68
97
  return (state.questionLog ?? []).filter((question) => question.status === "pending" && question.prompt.required);
@@ -271,8 +300,8 @@ function buildWorkspaceSummary(runtime, detail = "compact") {
271
300
  }
272
301
  function buildPendingQuestionContext(question) {
273
302
  return [
274
- `Required Researcher Checkpoint is still pending: ${question.prompt.question}`,
275
- `Options: ${formatQuestionOptions(question)}`,
303
+ "Required Researcher Checkpoint is still pending.",
304
+ buildQuestionDecisionCard(question),
276
305
  `Record it with longtable decide --question ${question.id} --answer <value> if you are outside MCP elicitation.`,
277
306
  "Do not choose or record an answer unless the researcher explicitly provides the selection."
278
307
  ].join("\n");
@@ -291,8 +320,7 @@ function buildGeneratedQuestionsContext(questions, created) {
291
320
  : `LongTable found ${questions.length} pending Researcher Checkpoint${questions.length === 1 ? "" : "s"} for this prompt.`
292
321
  ];
293
322
  for (const question of questions) {
294
- lines.push(`- ${question.prompt.title}: ${question.prompt.question}`);
295
- lines.push(` Options: ${formatQuestionOptions(question)}`);
323
+ lines.push(buildQuestionDecisionCard(question));
296
324
  lines.push(` Record it with longtable decide --question ${question.id} --answer <value> if you are outside MCP elicitation.`);
297
325
  }
298
326
  lines.push("Do not choose or record answers for these checkpoints unless the researcher explicitly provides the selections.");
@@ -17,4 +17,5 @@ export declare function refreshPanelWorkerRun(run: PanelWorkerRun): Promise<{
17
17
  }>;
18
18
  export declare function requestPanelWorkerStop(run: PanelWorkerRun): Promise<PanelWorkerRun>;
19
19
  export declare function resumePanelWorkerRun(run: PanelWorkerRun): Promise<PanelWorkerRun>;
20
+ export declare function shutdownPanelWorkerRun(run: PanelWorkerRun): Promise<PanelWorkerRun>;
20
21
  export declare function waitForPanelWorkerRun(run: PanelWorkerRun, timeoutMs: number): Promise<PanelWorkerRun>;