@longtable/cli 0.1.52 → 0.1.53

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 CHANGED
@@ -4,7 +4,8 @@ Researcher-facing CLI for LongTable.
4
4
 
5
5
  LongTable keeps scholarly project state in `.longtable/` and exposes generated
6
6
  provider skills for Codex and Claude Code. The CLI installs setup, state,
7
- checkpoint, search, and diagnostic tooling. It does not replace the provider.
7
+ checkpoint, search, panel, and diagnostic tooling. It does not replace the
8
+ provider.
8
9
 
9
10
  ## Install
10
11
 
@@ -74,11 +75,34 @@ longtable question --prompt "<decision context>"
74
75
  longtable decide --question <id> --answer <value>
75
76
  longtable spec read --cwd "<project-path>"
76
77
  longtable search --query "<topic>"
78
+ longtable panel --prompt "review this measurement plan" --json
77
79
  ```
78
80
 
79
81
  `longtable start` remains available for scripted workspace creation with
80
82
  `--no-interview --json`, but it is not the primary research-start surface.
81
83
 
84
+ ## Panel Orchestration
85
+
86
+ Panel orchestration is for moments where disagreement matters: methods risk,
87
+ measurement validity, theory fit, literature positioning, and claims that need
88
+ challenge before they become project memory.
89
+
90
+ The CLI creates a provider-neutral `PanelPlan` and returns a planned
91
+ `PanelResult`. When native subagents are unavailable, LongTable uses a stable
92
+ sequential fallback prompt. That keeps the same research semantics available in
93
+ Codex and Claude Code without making either provider's native question or agent
94
+ tool the source of truth.
95
+
96
+ ```bash
97
+ longtable panel --prompt "Review this measurement plan." --role editor,measurement_auditor --json
98
+ longtable panel --visibility always_visible --prompt "Keep unresolved disagreement visible." --json
99
+ longtable ask --prompt "lt debate: Review this design before I commit it." --json
100
+ ```
101
+
102
+ Team-style requests route through panel. Explicit debate-language requests write
103
+ panel debate records under `.longtable/panel/`; LongTable team execution is
104
+ disabled for new work.
105
+
82
106
  ## Development
83
107
 
84
108
  ```bash
package/dist/cli.js CHANGED
@@ -20,7 +20,7 @@ import { PERSONA_DEFINITIONS, listRoleDefinitions } from "./personas.js";
20
20
  import { buildPanelFallback, renderPanelSummary } from "./panel.js";
21
21
  import { LONGTABLE_MANAGED_HOOK_EVENTS, codexHooksEnabled, enableCodexHooksFeature, getMissingManagedCodexHookEvents, getMissingManagedCodexHookTrustState, mergeCodexHookTrustState, mergeManagedCodexHooksConfig, removeCodexHookTrustState, removeManagedCodexHooks } from "./codex-hooks.js";
22
22
  import { appendInvocationRecordToWorkspace, applyResearchSpecificationPatch, assertWorkspaceNotBlocked, answerWorkspaceQuestion, buildQuestionOpportunitySpecs, clearWorkspaceQuestion, createWorkspaceFollowUpQuestions, createWorkspaceQuestion, createOrUpdateProjectWorkspace, diffResearchSpecifications, inspectProjectWorkspace, loadWorkspaceState, loadProjectContextFromDirectory, findUnincorporatedResearchEvidence, proposeResearchSpecificationPatch, pruneWorkspaceQuestions, readResearchSpecificationHistory, repairWorkspaceStateConsistency, renderProjectWorkspaceSummary, syncCurrentWorkspaceView } from "./project-session.js";
23
- import { buildTeamDebate, buildTeamReview, renderTeamDebateSummary } from "./debate.js";
23
+ import { buildTeamDebate } from "./debate.js";
24
24
  import { createPromptRenderer } from "./prompt-renderer.js";
25
25
  const VALID_MODES = new Set([
26
26
  "explore",
@@ -154,7 +154,6 @@ function usage() {
154
154
  " longtable access probe --doi <doi> [--publisher auto|elsevier|springer_nature|wiley|taylor_francis] [--json]",
155
155
  " longtable search --query <text> [--intent literature|theory|measurement|citation|metadata|venue] [--field <text>] [--source all|crossref,arxiv,openalex,semantic_scholar,pubmed,eric,doaj,unpaywall] [--must <term[,term]>] [--exclude <term[,term]>] [--limit <n>] [--allow-partial] [--publisher-access] [--record] [--cwd <path>] [--json]",
156
156
  " longtable sentinel --prompt <text> [--cwd <path>] [--json] [--record]",
157
- " longtable team --prompt <text> [--role <role[,role]>] [--debate] [--rounds 3|5] [--cwd <path>] [--json]",
158
157
  " longtable ask [--prompt <text>] [--print] [--json] [--setup <path>] [--cwd <path>]",
159
158
  " longtable clarify --prompt <task-context> [--provider codex|claude] [--required|--advisory] [--print] [--cwd <path>] [--json] [--force]",
160
159
  " longtable question --prompt <decision-context> [--title <text>] [--text <question>] [--provider codex|claude] [--required|--advisory] [--print] [--cwd <path>] [--json]",
@@ -2264,10 +2263,10 @@ function inferCollaborationRoute(prompt) {
2264
2263
  if (explicitDebate) {
2265
2264
  return "debate";
2266
2265
  }
2267
- const explicitTeam = /\bagent team\b|\bresearch team\b|\bteam review\b|\bteam-style\b|\buse a team\b/i.test(prompt) ||
2266
+ const explicitPanelTeam = /\bagent team\b|\bresearch team\b|\bteam review\b|\bteam-style\b|\buse a team\b/i.test(prompt) ||
2268
2267
  /에이전트\s*팀|연구\s*팀|팀\s*(리뷰|검토)|팀으로/.test(prompt);
2269
- if (explicitTeam) {
2270
- return "team";
2268
+ if (explicitPanelTeam) {
2269
+ return "panel";
2271
2270
  }
2272
2271
  const panelCue = /\bpanel\b|\bmulti[- ]?role\b|\bmultiple perspectives\b|\brole disagreement\b|\bdisagreement\b|\bconflict\b/i.test(prompt) ||
2273
2272
  /패널|여러\s*관점|복수\s*관점|역할.*불일치|불일치|충돌/.test(prompt);
@@ -2282,10 +2281,10 @@ function inferCollaborationRoute(prompt) {
2282
2281
  trigger.signal.artifactStakes === "study_protocol" ||
2283
2282
  trigger.requiresQuestionBeforeClosure;
2284
2283
  if (panelCue && trigger.signal.artifactStakes === "external_submission") {
2285
- return "debate";
2284
+ return "panel";
2286
2285
  }
2287
2286
  if (highStakes) {
2288
- return "team";
2287
+ return "panel";
2289
2288
  }
2290
2289
  return "panel";
2291
2290
  }
@@ -3386,10 +3385,10 @@ async function runAsk(args) {
3386
3385
  (directive.panel || delegatedArgs.panel === true
3387
3386
  ? "panel"
3388
3387
  : inferCollaborationRoute(effectivePrompt) ?? (inferred === "panel" ? "panel" : null));
3389
- if (collaborationRoute === "team" || collaborationRoute === "debate") {
3390
- await runTeam({
3388
+ if (collaborationRoute === "debate") {
3389
+ await runPanelDebateCommand({
3391
3390
  ...delegatedArgs,
3392
- debate: collaborationRoute === "debate"
3391
+ debate: true
3393
3392
  });
3394
3393
  return;
3395
3394
  }
@@ -3408,21 +3407,21 @@ function localId(prefix) {
3408
3407
  async function writeJsonFile(path, value) {
3409
3408
  await writeFile(path, `${JSON.stringify(value, null, 2)}\n`, "utf8");
3410
3409
  }
3411
- async function writeTeamDebateArtifacts(bundle, teamDir, prompt) {
3412
- await mkdir(teamDir, { recursive: true });
3413
- await writeFile(join(teamDir, "prompt.txt"), prompt, "utf8");
3414
- await writeJsonFile(join(teamDir, "plan.json"), bundle.plan);
3415
- await writeJsonFile(join(teamDir, "run.json"), bundle.run);
3410
+ async function writePanelDebateArtifacts(bundle, panelDir, prompt) {
3411
+ await mkdir(panelDir, { recursive: true });
3412
+ await writeFile(join(panelDir, "prompt.txt"), prompt, "utf8");
3413
+ await writeJsonFile(join(panelDir, "plan.json"), bundle.plan);
3414
+ await writeJsonFile(join(panelDir, "run.json"), bundle.run);
3416
3415
  for (const round of bundle.run.rounds) {
3417
3416
  await mkdir(round.artifactDir, { recursive: true });
3418
3417
  await writeJsonFile(join(round.artifactDir, "round.json"), round);
3419
3418
  for (const contribution of round.contributions) {
3420
- await writeJsonFile(join(teamDir, contribution.artifactPath), contribution);
3419
+ await writeJsonFile(join(panelDir, contribution.artifactPath), contribution);
3421
3420
  }
3422
3421
  }
3423
- await writeJsonFile(join(teamDir, "synthesis.json"), bundle.run.synthesis);
3424
- await writeJsonFile(join(teamDir, "checkpoint.json"), bundle.questionRecord);
3425
- await writeJsonFile(join(teamDir, "invocation.json"), bundle.invocationRecord);
3422
+ await writeJsonFile(join(panelDir, "synthesis.json"), bundle.run.synthesis);
3423
+ await writeJsonFile(join(panelDir, "checkpoint.json"), bundle.questionRecord);
3424
+ await writeJsonFile(join(panelDir, "invocation.json"), bundle.invocationRecord);
3426
3425
  }
3427
3426
  function sentinelSummary(prompt, workingDirectory) {
3428
3427
  const trigger = classifyCheckpointTrigger(prompt, {
@@ -3501,19 +3500,15 @@ async function runSentinel(args) {
3501
3500
  console.log(context ? `- recorded in: ${context.stateFilePath}` : "- record skipped: no LongTable workspace found");
3502
3501
  }
3503
3502
  }
3504
- async function runTeam(args) {
3503
+ async function runPanelDebateCommand(args) {
3505
3504
  const workingDirectory = typeof args.cwd === "string" ? args.cwd : cwd();
3506
3505
  const prompt = await resolvePrompt(typeof args.prompt === "string" ? args.prompt : undefined);
3507
3506
  if (!prompt) {
3508
3507
  throw new Error("A prompt is required.");
3509
3508
  }
3510
- const isDebate = args.debate === true;
3511
- const expectedRounds = isDebate ? 5 : 3;
3512
- const rounds = typeof args.rounds === "string" ? Number(args.rounds) : expectedRounds;
3513
- if (!Number.isInteger(rounds) || rounds !== expectedRounds) {
3514
- throw new Error(isDebate
3515
- ? "LongTable team debate v1 supports `--rounds 5` only."
3516
- : "LongTable team v1 supports `--rounds 3` cross-review only.");
3509
+ const rounds = typeof args.rounds === "string" ? Number(args.rounds) : 5;
3510
+ if (!Number.isInteger(rounds) || rounds !== 5) {
3511
+ throw new Error("LongTable panel debate v1 supports `--rounds 5` only.");
3517
3512
  }
3518
3513
  const setup = await loadOptionalSetup(typeof args.setup === "string" ? args.setup : undefined);
3519
3514
  const projectContext = await loadProjectContextFromDirectory(workingDirectory);
@@ -3521,78 +3516,47 @@ async function runTeam(args) {
3521
3516
  await assertWorkspaceNotBlocked(projectContext);
3522
3517
  }
3523
3518
  const projectAware = await buildProjectAwarePrompt(prompt, workingDirectory);
3524
- const teamId = localId("team");
3525
- const teamDir = join(workingDirectory, ".longtable", "team", teamId);
3526
- if (isDebate) {
3527
- const debate = buildTeamDebate({
3528
- teamId,
3529
- teamDir,
3530
- prompt: projectAware.prompt,
3531
- roleFlag: typeof args.role === "string" ? args.role : undefined,
3532
- provider: setup?.providerSelection.provider,
3533
- visibility: "always_visible",
3534
- roundCount: rounds
3535
- });
3536
- await writeTeamDebateArtifacts(debate, teamDir, prompt);
3537
- const canRecordWorkspace = projectAware.projectContextFound && projectContext && existsSync(projectContext.stateFilePath);
3538
- if (canRecordWorkspace) {
3539
- await appendInvocationRecordToWorkspace(projectContext, debate.invocationRecord, [debate.questionRecord]);
3540
- }
3541
- if (args.json === true) {
3542
- console.log(JSON.stringify({
3543
- teamId,
3544
- teamDir,
3545
- plan: debate.plan,
3546
- run: debate.run,
3547
- questionRecord: debate.questionRecord,
3548
- invocationRecord: debate.invocationRecord,
3549
- execution: {
3550
- status: "completed",
3551
- surface: debate.run.surface,
3552
- projectContextFound: projectAware.projectContextFound,
3553
- invocationLogged: canRecordWorkspace
3554
- }
3555
- }, null, 2));
3556
- return;
3557
- }
3558
- console.log(renderTeamDebateSummary(debate.run));
3559
- console.log(`- checkpoint: ${debate.questionRecord.id}`);
3560
- return;
3561
- }
3562
- const team = buildTeamReview({
3563
- teamId,
3564
- teamDir,
3519
+ const panelId = localId("panel_debate");
3520
+ const panelDir = join(workingDirectory, ".longtable", "panel", panelId);
3521
+ const debate = buildTeamDebate({
3522
+ teamId: panelId,
3523
+ teamDir: panelDir,
3565
3524
  prompt: projectAware.prompt,
3566
3525
  roleFlag: typeof args.role === "string" ? args.role : undefined,
3567
3526
  provider: setup?.providerSelection.provider,
3568
3527
  visibility: "always_visible",
3569
3528
  roundCount: rounds
3570
3529
  });
3571
- await writeTeamDebateArtifacts(team, teamDir, prompt);
3530
+ await writePanelDebateArtifacts(debate, panelDir, prompt);
3572
3531
  const canRecordWorkspace = projectAware.projectContextFound && projectContext && existsSync(projectContext.stateFilePath);
3573
3532
  if (canRecordWorkspace) {
3574
- await appendInvocationRecordToWorkspace(projectContext, team.invocationRecord, [team.questionRecord]);
3533
+ await appendInvocationRecordToWorkspace(projectContext, debate.invocationRecord, [debate.questionRecord]);
3575
3534
  }
3576
3535
  if (args.json === true) {
3577
3536
  console.log(JSON.stringify({
3578
- teamId,
3579
- teamDir,
3580
- plan: team.plan,
3581
- run: team.run,
3582
- questionRecord: team.questionRecord,
3583
- invocationRecord: team.invocationRecord,
3537
+ panelId,
3538
+ panelDir,
3539
+ plan: debate.plan,
3540
+ run: debate.run,
3541
+ questionRecord: debate.questionRecord,
3542
+ invocationRecord: debate.invocationRecord,
3584
3543
  execution: {
3585
3544
  status: "completed",
3586
- surface: team.run.surface,
3587
- interactionDepth: team.run.interactionDepth,
3545
+ surface: debate.run.surface,
3588
3546
  projectContextFound: projectAware.projectContextFound,
3589
3547
  invocationLogged: canRecordWorkspace
3590
3548
  }
3591
3549
  }, null, 2));
3592
3550
  return;
3593
3551
  }
3594
- console.log(renderTeamDebateSummary(team.run));
3595
- console.log(`- checkpoint: ${team.questionRecord.id}`);
3552
+ console.log("LongTable Panel Debate");
3553
+ console.log(`- panel: ${panelId}`);
3554
+ console.log(`- interaction depth: ${debate.run.interactionDepth}`);
3555
+ console.log(`- rounds: ${debate.run.roundCount}`);
3556
+ console.log(`- checkpoint: ${debate.questionRecord.id}`);
3557
+ }
3558
+ function disabledTeamCommandError() {
3559
+ return new Error("`longtable team` is disabled. Use `longtable panel --prompt <text>` for visible multi-role review, or `longtable ask --prompt \"lt debate: <text>\"` when debate is explicitly requested.");
3596
3560
  }
3597
3561
  async function runDecide(args) {
3598
3562
  const workingDirectory = typeof args.cwd === "string" ? args.cwd : cwd();
@@ -4037,8 +4001,7 @@ async function main() {
4037
4001
  return;
4038
4002
  }
4039
4003
  if (command === "team") {
4040
- await runTeam(values);
4041
- return;
4004
+ throw disabledTeamCommandError();
4042
4005
  }
4043
4006
  if (command === "decide") {
4044
4007
  await runDecide(values);
package/dist/debate.js CHANGED
@@ -166,7 +166,7 @@ function convergenceContribution(roundId, plan, role, label, artifactPath) {
166
166
  function buildSynthesis(plan, artifactPath, kind) {
167
167
  const labels = plan.members.map((member) => member.label);
168
168
  const highSensitivity = plan.checkpointSensitivity === "high";
169
- const runLabel = kind === "debate" ? "debate" : "team review";
169
+ const runLabel = kind === "debate" ? "panel debate" : "panel review";
170
170
  return {
171
171
  artifactPath,
172
172
  summary: `The ${runLabel} completed across ${labels.join(", ")}. It should slow closure by turning role disagreement into an explicit researcher decision.`,
@@ -201,8 +201,8 @@ export function createTeamDebateQuestionRecord(run, provider) {
201
201
  status: "pending",
202
202
  prompt: {
203
203
  id: createId("question_prompt"),
204
- checkpointKey: "team_debate_next_decision",
205
- title: isDebate ? "Team debate follow-up decision" : "Agent team follow-up decision",
204
+ checkpointKey: "panel_debate_next_decision",
205
+ title: isDebate ? "Panel debate follow-up decision" : "Panel review follow-up decision",
206
206
  question: run.synthesis.recommendedCheckpoint,
207
207
  type: "single_choice",
208
208
  options: [
@@ -238,11 +238,11 @@ export function createTeamDebateQuestionRecord(run, provider) {
238
238
  ? "Role rebuttals and convergence should connect to an explicit researcher decision."
239
239
  : "Cross-review created role disagreement that should connect to an explicit researcher decision.",
240
240
  rationale: [
241
- "Agent team orchestration is a research harness surface, not a substitute for researcher judgment.",
241
+ "LongTable panel orchestration is a research harness surface, not a substitute for researcher judgment.",
242
242
  isDebate
243
243
  ? "The fixed debate rounds created disagreement that should connect to an explicit researcher decision."
244
244
  : "The cross-review round created disagreement that should connect to an explicit researcher decision.",
245
- `Agent team run: ${run.id}.`
245
+ `LongTable panel run: ${run.id}.`
246
246
  ],
247
247
  preferredSurfaces: provider === "claude"
248
248
  ? ["native_structured", "numbered"]
@@ -255,8 +255,8 @@ function buildTeamBundle(options, kind) {
255
255
  const expectedRounds = kind === "debate" ? 5 : 3;
256
256
  if (roundCount !== expectedRounds) {
257
257
  throw new Error(kind === "debate"
258
- ? "LongTable debate v1 supports fixed 5-round debate only."
259
- : "LongTable team v1 supports fixed 3-round cross-review only.");
258
+ ? "LongTable panel debate v1 supports fixed 5-round debate only."
259
+ : "LongTable panel review v1 supports fixed 3-round cross-review only.");
260
260
  }
261
261
  const createdAt = nowIso();
262
262
  const plan = buildPanelPlan({
@@ -267,7 +267,7 @@ function buildTeamBundle(options, kind) {
267
267
  visibility: options.visibility ?? "always_visible"
268
268
  });
269
269
  const rounds = [];
270
- const round1Id = createId("team_round");
270
+ const round1Id = createId("panel_round");
271
271
  const independentContributions = plan.members.map((member) => independentContribution(round1Id, plan, member.role, member.label, join("round-1-independent", `${member.role}.json`)));
272
272
  rounds.push({
273
273
  id: round1Id,
@@ -278,7 +278,7 @@ function buildTeamBundle(options, kind) {
278
278
  artifactDir: join(options.teamDir, "round-1-independent"),
279
279
  contributions: independentContributions
280
280
  });
281
- const round2Id = createId("team_round");
281
+ const round2Id = createId("panel_round");
282
282
  const crossContributions = plan.members.flatMap((member) => plan.members
283
283
  .filter((target) => target.role !== member.role)
284
284
  .map((target) => crossReviewContribution(round2Id, plan, member.role, member.label, target.role, target.label, independentContributions.find((contribution) => contribution.role === target.role), join("round-2-cross-review", `${member.role}-on-${target.role}.json`))));
@@ -292,7 +292,7 @@ function buildTeamBundle(options, kind) {
292
292
  contributions: crossContributions
293
293
  });
294
294
  if (kind === "debate") {
295
- const round3Id = createId("team_round");
295
+ const round3Id = createId("panel_round");
296
296
  rounds.push({
297
297
  id: round3Id,
298
298
  index: 3,
@@ -302,7 +302,7 @@ function buildTeamBundle(options, kind) {
302
302
  artifactDir: join(options.teamDir, "round-3-rebuttal"),
303
303
  contributions: plan.members.map((member) => rebuttalContribution(round3Id, member.role, member.label, join("round-3-rebuttal", `${member.role}.json`)))
304
304
  });
305
- const round4Id = createId("team_round");
305
+ const round4Id = createId("panel_round");
306
306
  rounds.push({
307
307
  id: round4Id,
308
308
  index: 4,
@@ -315,22 +315,22 @@ function buildTeamBundle(options, kind) {
315
315
  }
316
316
  const synthesis = buildSynthesis(plan, "synthesis.json", kind);
317
317
  const run = {
318
- id: createId("team_debate_run"),
318
+ id: createId("panel_debate_run"),
319
319
  teamId: options.teamId,
320
320
  createdAt,
321
321
  updatedAt: createdAt,
322
322
  prompt: options.prompt,
323
323
  roles: plan.members,
324
324
  status: "completed",
325
- surface: "file_backed_debate",
325
+ surface: "file_backed_panel_debate",
326
326
  interactionDepth: kind === "debate" ? "debated" : "cross_reviewed",
327
- roundPolicy: kind === "debate" ? "fixed" : "team_cross_review",
327
+ roundPolicy: kind === "debate" ? "fixed" : "panel_cross_review",
328
328
  roundCount,
329
329
  artifactRoot: options.teamDir,
330
330
  rounds: [
331
331
  ...rounds,
332
332
  {
333
- id: createId("team_round"),
333
+ id: createId("panel_round"),
334
334
  index: roundCount,
335
335
  kind: "synthesis",
336
336
  title: "Coordinator synthesis and checkpoint",
@@ -353,12 +353,12 @@ function buildTeamBundle(options, kind) {
353
353
  checkpointSensitivity: plan.checkpointSensitivity,
354
354
  rationale: [
355
355
  kind === "debate"
356
- ? "Autonomous debate requested through LongTable team orchestration."
357
- : "Agent team cross-review requested through LongTable team orchestration.",
356
+ ? "Autonomous debate requested through LongTable panel orchestration."
357
+ : "Cross-role review requested through LongTable panel orchestration.",
358
358
  "File-backed rounds keep disagreement inspectable before researcher closure."
359
359
  ]
360
360
  });
361
- intent.kind = kind === "debate" ? "team_debate" : "team";
361
+ intent.kind = kind === "debate" ? "panel_debate" : "panel";
362
362
  intent.requestedSurface = run.surface;
363
363
  const invocationRecord = {
364
364
  id: createId("invocation_record"),
@@ -371,7 +371,7 @@ function buildTeamBundle(options, kind) {
371
371
  interactionDepth: run.interactionDepth,
372
372
  panelPlan: plan,
373
373
  teamDebateRun: run,
374
- degradationReason: "File-backed team artifacts are the canonical execution record."
374
+ degradationReason: "File-backed panel artifacts are the canonical execution record."
375
375
  };
376
376
  return {
377
377
  plan,
@@ -389,8 +389,8 @@ export function buildTeamDebate(options) {
389
389
  }
390
390
  export function renderTeamDebateSummary(run) {
391
391
  return [
392
- "LongTable Team Debate",
393
- `- team: ${run.teamId}`,
392
+ "LongTable Panel Debate",
393
+ `- panel: ${run.teamId}`,
394
394
  `- surface: ${run.surface}`,
395
395
  `- interaction depth: ${run.interactionDepth}`,
396
396
  `- rounds: ${run.roundCount} ${run.roundPolicy}`,
@@ -225,7 +225,7 @@ function mutatesLongTableResearchState(command) {
225
225
  return false;
226
226
  }
227
227
  return /\.longtable(?:\/|\b)|\bCURRENT\.md\b/.test(normalized)
228
- || /\blongtable\s+(?:start|question|clear-question|prune-questions|ask|clarify|panel|team)\b/.test(normalized);
228
+ || /\blongtable\s+(?:start|question|clear-question|prune-questions|ask|clarify|panel)\b/.test(normalized);
229
229
  }
230
230
  async function loadLongTableRuntime(startPath) {
231
231
  const context = await loadProjectContextFromDirectory(startPath);
package/dist/panel.js CHANGED
@@ -183,7 +183,7 @@ export function createPlannedInvocationRecord(options) {
183
183
  interactionDepth: "independent",
184
184
  panelPlan: options.plan,
185
185
  panelResult: options.result,
186
- degradationReason: "Native provider team execution is optional; sequential fallback is the stable LongTable surface."
186
+ degradationReason: "Sequential fallback is the stable LongTable panel surface."
187
187
  };
188
188
  }
189
189
  function roleInstruction(member) {
@@ -12,7 +12,7 @@ export interface LongTableInvocationDirective {
12
12
  explicit: boolean;
13
13
  cleanedPrompt: string;
14
14
  mode?: InteractionMode | "panel" | "status";
15
- collaboration?: "panel" | "team" | "debate";
15
+ collaboration?: "panel" | "debate";
16
16
  roles: CanonicalPersona[];
17
17
  panel: boolean;
18
18
  showConflicts: boolean;
@@ -8,8 +8,8 @@ const DIRECTIVE_MAP = [
8
8
  { key: "draft", mode: "draft" },
9
9
  { key: "commit", mode: "commit" },
10
10
  { key: "panel", mode: "panel", collaboration: "panel", panel: true, showConflicts: true },
11
- { key: "team", mode: "review", collaboration: "team", panel: true, showConflicts: true },
12
- { key: "debate", mode: "review", collaboration: "debate", panel: true, showConflicts: true },
11
+ { key: "team", mode: "panel", collaboration: "panel", panel: true, showConflicts: true },
12
+ { key: "debate", mode: "panel", collaboration: "debate", panel: true, showConflicts: true },
13
13
  { key: "status", mode: "status" },
14
14
  { key: "editor", mode: "review", roles: ["editor"] },
15
15
  { key: "reviewer", mode: "review", roles: ["reviewer"] },
@@ -2275,7 +2275,7 @@ const COMMITMENT_FAMILY_BY_CHECKPOINT = [
2275
2275
  [/research_question|research_direction|scope|boundary|inclusion|exclusion/, "scope"],
2276
2276
  [/theory|construct|conceptual/, "construct"],
2277
2277
  [/measurement|coding|codebook|extraction/, "coding"],
2278
- [/method|analysis|panel_disagreement|team_debate|review/, "method"],
2278
+ [/method|analysis|panel_disagreement|panel_debate|team_debate|review/, "method"],
2279
2279
  [/evidence|scholarly_access|source_authority/, "evidence"],
2280
2280
  [/knowledge_gap|tacit_assumption|epistemic/, "epistemic_authority"]
2281
2281
  ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@longtable/cli",
3
- "version": "0.1.52",
3
+ "version": "0.1.53",
4
4
  "private": false,
5
5
  "description": "Researcher-facing LongTable CLI",
6
6
  "type": "module",
@@ -29,12 +29,12 @@
29
29
  },
30
30
  "dependencies": {
31
31
  "@clack/prompts": "^1.2.0",
32
- "@longtable/checkpoints": "0.1.52",
33
- "@longtable/core": "0.1.52",
34
- "@longtable/memory": "0.1.52",
35
- "@longtable/provider-claude": "0.1.52",
36
- "@longtable/provider-codex": "0.1.52",
37
- "@longtable/setup": "0.1.52"
32
+ "@longtable/checkpoints": "0.1.53",
33
+ "@longtable/core": "0.1.53",
34
+ "@longtable/memory": "0.1.53",
35
+ "@longtable/provider-claude": "0.1.53",
36
+ "@longtable/provider-codex": "0.1.53",
37
+ "@longtable/setup": "0.1.53"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@types/node": "^22.10.1",