@longtable/cli 0.1.38 → 0.1.39

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
@@ -156,16 +156,21 @@ longtable codex install-skills
156
156
  longtable claude install-skills
157
157
  ```
158
158
 
159
- Codex skills include `longtable`, `longtable-panel`, and generated role-specific
160
- skills such as `longtable-methods-critic`. If your Codex build exposes explicit
161
- skill shortcuts, `$longtable-interview` is the research-start entry and
162
- `$longtable` is the general router. Do not depend on `/prompts`; current Codex
163
- builds may reject it.
164
-
165
- Claude Code skills include `longtable`, `longtable-panel`, and generated
166
- role-specific skills such as `longtable-methods-critic`. They also include
167
- `longtable-interview` for the First Research Shape workflow. They are adapter
168
- files generated from the LongTable role registry.
159
+ By default, provider skills use the compact surface: `longtable`,
160
+ `longtable-interview`, and five short role shortcuts: `longtable-methods`,
161
+ `longtable-measure`, `longtable-theory`, `longtable-reviewer`, and
162
+ `longtable-voice`. `$longtable` remains the general router and can still invoke
163
+ editor, ethics, venue, panel, explore, or review behavior when the request calls
164
+ for it.
165
+
166
+ Power users can install the legacy full surface explicitly:
167
+
168
+ ```bash
169
+ longtable codex install-skills --surface full
170
+ longtable claude install-skills --surface full
171
+ ```
172
+
173
+ Do not depend on `/prompts`; current Codex builds may reject it.
169
174
 
170
175
  ## Panel Orchestration
171
176
 
package/dist/cli.js CHANGED
@@ -17,7 +17,7 @@ import { buildPersonaGuidance, parseInvocationDirective } from "./persona-router
17
17
  import { PERSONA_DEFINITIONS, listRoleDefinitions } from "./personas.js";
18
18
  import { buildPanelFallback, renderPanelSummary } from "./panel.js";
19
19
  import { LONGTABLE_MANAGED_HOOK_EVENTS, codexHooksEnabled, enableCodexHooksFeature, getMissingManagedCodexHookEvents, mergeManagedCodexHooksConfig, removeManagedCodexHooks } from "./codex-hooks.js";
20
- import { appendInvocationRecordToWorkspace, assertWorkspaceNotBlocked, answerWorkspaceQuestion, buildQuestionOpportunitySpecs, clearWorkspaceQuestion, createWorkspaceFollowUpQuestions, createWorkspaceQuestion, createOrUpdateProjectWorkspace, inspectProjectWorkspace, loadWorkspaceState, loadProjectContextFromDirectory, repairWorkspaceStateConsistency, renderProjectWorkspaceSummary, syncCurrentWorkspaceView } from "./project-session.js";
20
+ import { appendInvocationRecordToWorkspace, assertWorkspaceNotBlocked, answerWorkspaceQuestion, buildQuestionOpportunitySpecs, clearWorkspaceQuestion, createWorkspaceFollowUpQuestions, createWorkspaceQuestion, createOrUpdateProjectWorkspace, inspectProjectWorkspace, loadWorkspaceState, loadProjectContextFromDirectory, pruneWorkspaceQuestions, repairWorkspaceStateConsistency, renderProjectWorkspaceSummary, syncCurrentWorkspaceView } from "./project-session.js";
21
21
  import { buildTeamDebate, buildTeamReview, renderTeamDebateSummary } from "./debate.js";
22
22
  import { createPromptRenderer } from "./prompt-renderer.js";
23
23
  const VALID_MODES = new Set([
@@ -45,7 +45,7 @@ const ANSI = {
45
45
  green: "\u001B[32m"
46
46
  };
47
47
  const LONGTABLE_MCP_SERVER_NAME = "longtable-state";
48
- const LONGTABLE_MCP_PACKAGE_VERSION = "0.1.38";
48
+ const LONGTABLE_MCP_PACKAGE_VERSION = "0.1.39";
49
49
  const LONGTABLE_MCP_MARKER_START = "# LongTable state MCP START";
50
50
  const LONGTABLE_MCP_MARKER_END = "# LongTable state MCP END";
51
51
  function style(text, prefix) {
@@ -120,16 +120,17 @@ function usage() {
120
120
  " longtable decide [--question <id>] --answer <value-or-text> [--rationale <text>] [--provider codex|claude] [--cwd <path>] [--json]",
121
121
  " longtable explore|review|critique|draft|commit|submit [--prompt <text>] [--role <role[,role]>] [--panel] [--show-conflicts] [--show-deliberation] [--print] [--json] [--stage <stage>] [--setup <path>] [--cwd <path>]",
122
122
  " longtable codex persist-init [--answers-json <json> | --stdin | full setup flags] [--install-skills] [--install-prompts] [--json]",
123
- " longtable codex install-skills [--dir <path>]",
123
+ " longtable codex install-skills [--surface compact|full] [--dir <path>]",
124
124
  " longtable codex remove-skills [--dir <path>]",
125
125
  " longtable codex install-prompts [--dir <path>]",
126
126
  " longtable codex remove-prompts [--dir <path>]",
127
127
  " longtable codex install-hooks [--codex-config <path>] [--hooks-path <path>] [--json]",
128
128
  " longtable codex remove-hooks [--codex-config <path>] [--hooks-path <path>] [--json]",
129
- " longtable codex status [--dir <path>] [--codex-config <path>] [--hooks-path <path>] [--json]",
130
- " longtable claude install-skills [--dir <path>]",
129
+ " longtable codex status [--surface compact|full] [--dir <path>] [--codex-config <path>] [--hooks-path <path>] [--json]",
130
+ " longtable claude install-skills [--surface compact|full] [--dir <path>]",
131
131
  " longtable claude remove-skills [--dir <path>]",
132
- " longtable claude status [--dir <path>] [--json]",
132
+ " longtable claude status [--surface compact|full] [--dir <path>] [--json]",
133
+ " longtable prune-questions [--cwd <path>] [--dry-run] [--json]",
133
134
  " longtable mcp install --provider all",
134
135
  "",
135
136
  "Examples:",
@@ -150,7 +151,7 @@ function parseArgs(argv) {
150
151
  const values = {};
151
152
  let subcommand = maybeSubcommand;
152
153
  const modeCommand = command && VALID_MODES.has(command);
153
- const directCommand = command && ["init", "setup", "start", "resume", "doctor", "status", "audit", "roles", "show", "install", "mcp", "codex", "claude", "ask", "clarify", "question", "clear-question", "panel", "decide", "sentinel", "team", "search"].includes(command);
154
+ const directCommand = command && ["init", "setup", "start", "resume", "doctor", "status", "audit", "roles", "show", "install", "mcp", "codex", "claude", "ask", "clarify", "question", "clear-question", "prune-questions", "panel", "decide", "sentinel", "team", "search"].includes(command);
154
155
  let startIndex = 1;
155
156
  if (modeCommand) {
156
157
  subcommand = undefined;
@@ -238,6 +239,16 @@ function questionSection(questionId) {
238
239
  function formatModeLabel(mode) {
239
240
  return `${mode[0].toUpperCase()}${mode.slice(1)}`;
240
241
  }
242
+ function parseSkillSurface(args) {
243
+ const value = args.surface;
244
+ if (value === undefined || value === true) {
245
+ return "compact";
246
+ }
247
+ if (value === "compact" || value === "full") {
248
+ return value;
249
+ }
250
+ throw new Error("Invalid --surface value. Use compact or full.");
251
+ }
241
252
  function stripWrappingQuotes(value) {
242
253
  const trimmed = value.trim();
243
254
  if ((trimmed.startsWith("\"") && trimmed.endsWith("\"")) ||
@@ -1416,6 +1427,7 @@ function setupForProvider(setup, provider) {
1416
1427
  }
1417
1428
  async function collectDoctorStatus(args) {
1418
1429
  const roles = listRoleDefinitions();
1430
+ const skillSurface = parseSkillSurface(args);
1419
1431
  const setupOverride = typeof args.setup === "string"
1420
1432
  ? args.setup
1421
1433
  : typeof args.path === "string"
@@ -1458,11 +1470,11 @@ async function collectDoctorStatus(args) {
1458
1470
  const missingManagedHookEvents = codexHooksContent
1459
1471
  ? (getMissingManagedCodexHookEvents(codexHooksContent) ?? [...LONGTABLE_MANAGED_HOOK_EVENTS])
1460
1472
  : [...LONGTABLE_MANAGED_HOOK_EVENTS];
1461
- const expectedCodexSkills = buildCodexSkillSpecs(roles).map((skill) => skill.name);
1462
- const expectedClaudeSkills = buildClaudeSkillSpecs(roles).map((skill) => skill.name);
1473
+ const expectedCodexSkills = buildCodexSkillSpecs(roles, skillSurface).map((skill) => skill.name);
1474
+ const expectedClaudeSkills = buildClaudeSkillSpecs(roles, skillSurface).map((skill) => skill.name);
1463
1475
  const [codexSkills, claudeSkills, codexAliases, workspace] = await Promise.all([
1464
- listInstalledCodexSkills(roles, codexDir),
1465
- listInstalledClaudeSkills(roles, claudeDir),
1476
+ listInstalledCodexSkills(roles, codexDir, skillSurface),
1477
+ listInstalledClaudeSkills(roles, claudeDir, skillSurface),
1466
1478
  listInstalledCodexPromptAliases(codexPromptsDir),
1467
1479
  inspectProjectWorkspace(typeof args.cwd === "string" ? args.cwd : cwd())
1468
1480
  ]);
@@ -1646,6 +1658,7 @@ function renderRepairSummary(repair) {
1646
1658
  }
1647
1659
  async function repairDoctorStatus(args, status) {
1648
1660
  const roles = listRoleDefinitions();
1661
+ const skillSurface = parseSkillSurface(args);
1649
1662
  const codexDir = typeof args["codex-dir"] === "string"
1650
1663
  ? args["codex-dir"]
1651
1664
  : typeof args.dir === "string"
@@ -1684,10 +1697,10 @@ async function repairDoctorStatus(args, status) {
1684
1697
  skipped: []
1685
1698
  };
1686
1699
  if (status.providers.codex.missingSkills.length > 0) {
1687
- repair.installedCodexSkills = (await installCodexSkills(roles, codexDir)).map((skill) => skill.name);
1700
+ repair.installedCodexSkills = (await installCodexSkills(roles, codexDir, skillSurface)).map((skill) => skill.name);
1688
1701
  }
1689
1702
  if (status.providers.claude.missingSkills.length > 0) {
1690
- repair.installedClaudeSkills = (await installClaudeSkills(roles, claudeDir)).map((skill) => skill.name);
1703
+ repair.installedClaudeSkills = (await installClaudeSkills(roles, claudeDir, skillSurface)).map((skill) => skill.name);
1691
1704
  }
1692
1705
  if (status.providers.codex.legacyPromptFilesInstalled.length > 0) {
1693
1706
  repair.removedLegacyPromptFiles = await removeCodexPromptAliases(codexPromptsDir);
@@ -1851,10 +1864,10 @@ function runRoleAudit() {
1851
1864
  "longtable-review"
1852
1865
  ]);
1853
1866
  const roles = [
1854
- ...buildCodexSkillSpecs(listRoleDefinitions())
1867
+ ...buildCodexSkillSpecs(listRoleDefinitions(), "full")
1855
1868
  .filter((spec) => !baseSkillNames.has(spec.name))
1856
1869
  .map((spec) => buildRoleAuditEntry("codex", spec)),
1857
- ...buildClaudeSkillSpecs(listRoleDefinitions())
1870
+ ...buildClaudeSkillSpecs(listRoleDefinitions(), "full")
1858
1871
  .filter((spec) => !baseSkillNames.has(spec.name))
1859
1872
  .map((spec) => buildRoleAuditEntry("claude", spec))
1860
1873
  ];
@@ -2671,6 +2684,41 @@ async function runClearQuestion(args) {
2671
2684
  console.log(`- state: ${context.stateFilePath}`);
2672
2685
  console.log(`- current: ${context.currentFilePath}`);
2673
2686
  }
2687
+ async function runPruneQuestions(args) {
2688
+ const workingDirectory = typeof args.cwd === "string" ? args.cwd : cwd();
2689
+ const context = await loadProjectContextFromDirectory(workingDirectory);
2690
+ if (!context) {
2691
+ throw new Error("No LongTable project workspace was found here. Run this inside a project or pass --cwd.");
2692
+ }
2693
+ const dryRun = args["dry-run"] === true;
2694
+ const result = await pruneWorkspaceQuestions({
2695
+ context,
2696
+ dryRun
2697
+ });
2698
+ if (args.json === true) {
2699
+ console.log(JSON.stringify({
2700
+ dryRun,
2701
+ removedCount: result.removedQuestions.length,
2702
+ removedQuestions: result.removedQuestions.map((question) => ({
2703
+ id: question.id,
2704
+ title: question.prompt.title,
2705
+ reason: question.clearedReason
2706
+ })),
2707
+ files: {
2708
+ state: context.stateFilePath,
2709
+ current: context.currentFilePath
2710
+ }
2711
+ }, null, 2));
2712
+ return;
2713
+ }
2714
+ console.log(dryRun ? "LongTable question prune preview" : "LongTable questions pruned");
2715
+ console.log(`- removed false-positive cleared questions: ${result.removedQuestions.length}`);
2716
+ for (const question of result.removedQuestions) {
2717
+ console.log(` - ${question.id}: ${question.prompt.title}`);
2718
+ }
2719
+ console.log(`- state: ${context.stateFilePath}`);
2720
+ console.log(`- current: ${context.currentFilePath}`);
2721
+ }
2674
2722
  function isInteractiveTerminal() {
2675
2723
  return Boolean(input.isTTY && output.isTTY);
2676
2724
  }
@@ -3241,11 +3289,12 @@ async function runResume(args) {
3241
3289
  async function runCodexSubcommand(subcommand, args) {
3242
3290
  const customDir = typeof args.dir === "string" ? args.dir : undefined;
3243
3291
  const roles = listRoleDefinitions();
3292
+ const skillSurface = parseSkillSurface(args);
3244
3293
  if (subcommand === "install-skills") {
3245
- const installed = await installCodexSkills(roles, customDir);
3246
- console.log(`Installed ${installed.length} LongTable Codex skills in ${resolveCodexSkillsDir(customDir)}`);
3294
+ const installed = await installCodexSkills(roles, customDir, skillSurface);
3295
+ console.log(`Installed ${installed.length} LongTable Codex skills in ${resolveCodexSkillsDir(customDir)} (${skillSurface} surface)`);
3247
3296
  console.log("Use them inside Codex with natural-language triggers such as `lt explore: ...` or `lt panel: ...`.");
3248
- console.log("If you want an explicit trigger, use `$longtable` when your Codex build exposes skills that way.");
3297
+ console.log("Use `$longtable` as the general router; compact installs expose only the most common role shortcuts.");
3249
3298
  for (const skill of installed) {
3250
3299
  console.log(`- ${skill.name}`);
3251
3300
  }
@@ -3295,7 +3344,7 @@ async function runCodexSubcommand(subcommand, args) {
3295
3344
  }
3296
3345
  if (subcommand === "status") {
3297
3346
  const aliases = await listInstalledCodexPromptAliases(customDir);
3298
- const skills = await listInstalledCodexSkills(roles, customDir);
3347
+ const skills = await listInstalledCodexSkills(roles, customDir, skillSurface);
3299
3348
  const setupPath = resolveDefaultSetupPath(typeof args.path === "string" ? args.path : undefined).path;
3300
3349
  const runtimePath = resolveDefaultRuntimeConfigPath("codex", typeof args["runtime-path"] === "string" ? args["runtime-path"] : undefined).path;
3301
3350
  const configPath = resolveCodexMcpConfigPath(args);
@@ -3308,6 +3357,7 @@ async function runCodexSubcommand(subcommand, args) {
3308
3357
  runtimePath,
3309
3358
  runtimeExists: existsSync(runtimePath),
3310
3359
  skillsDir: resolveCodexSkillsDir(customDir),
3360
+ skillSurface,
3311
3361
  skillsInstalled: skills.map((skill) => skill.name),
3312
3362
  promptsDir: resolveCodexPromptsDir(customDir),
3313
3363
  legacyPromptFilesInstalled: aliases.map((alias) => alias.name),
@@ -3327,6 +3377,7 @@ async function runCodexSubcommand(subcommand, args) {
3327
3377
  console.log(`- setup: ${status.setupExists ? "present" : "missing"} (${setupPath})`);
3328
3378
  console.log(`- codex runtime artifact: ${status.runtimeExists ? "present" : "missing"} (${runtimePath})`);
3329
3379
  console.log(`- skills dir: ${status.skillsDir}`);
3380
+ console.log(`- skill surface: ${status.skillSurface}`);
3330
3381
  if (skills.length === 0) {
3331
3382
  console.log("- skills: none");
3332
3383
  }
@@ -3358,9 +3409,10 @@ async function runCodexSubcommand(subcommand, args) {
3358
3409
  async function runClaudeSubcommand(subcommand, args) {
3359
3410
  const customDir = typeof args.dir === "string" ? args.dir : undefined;
3360
3411
  const roles = listRoleDefinitions();
3412
+ const skillSurface = parseSkillSurface(args);
3361
3413
  if (subcommand === "install-skills") {
3362
- const installed = await installClaudeSkills(roles, customDir);
3363
- console.log(`Installed ${installed.length} LongTable Claude skills in ${resolveClaudeSkillsDir(customDir)}`);
3414
+ const installed = await installClaudeSkills(roles, customDir, skillSurface);
3415
+ console.log(`Installed ${installed.length} LongTable Claude skills in ${resolveClaudeSkillsDir(customDir)} (${skillSurface} surface)`);
3364
3416
  console.log("Use them inside Claude Code with natural-language triggers such as `lt explore: ...` or `lt panel: ...`.");
3365
3417
  for (const skill of installed) {
3366
3418
  console.log(`- ${skill.name}`);
@@ -3373,7 +3425,7 @@ async function runClaudeSubcommand(subcommand, args) {
3373
3425
  return;
3374
3426
  }
3375
3427
  if (subcommand === "status") {
3376
- const skills = await listInstalledClaudeSkills(roles, customDir);
3428
+ const skills = await listInstalledClaudeSkills(roles, customDir, skillSurface);
3377
3429
  const setupPath = resolveDefaultSetupPath(typeof args.path === "string" ? args.path : undefined).path;
3378
3430
  const runtimePath = resolveDefaultRuntimeConfigPath("claude", typeof args["runtime-path"] === "string" ? args["runtime-path"] : undefined).path;
3379
3431
  const status = {
@@ -3382,6 +3434,7 @@ async function runClaudeSubcommand(subcommand, args) {
3382
3434
  runtimePath,
3383
3435
  runtimeExists: existsSync(runtimePath),
3384
3436
  skillsDir: resolveClaudeSkillsDir(customDir),
3437
+ skillSurface,
3385
3438
  skillsInstalled: skills.map((skill) => skill.name)
3386
3439
  };
3387
3440
  if (args.json === true) {
@@ -3392,6 +3445,7 @@ async function runClaudeSubcommand(subcommand, args) {
3392
3445
  console.log(`- setup: ${status.setupExists ? "present" : "missing"} (${setupPath})`);
3393
3446
  console.log(`- claude runtime artifact: ${status.runtimeExists ? "present" : "missing"} (${runtimePath})`);
3394
3447
  console.log(`- skills dir: ${status.skillsDir}`);
3448
+ console.log(`- skill surface: ${status.skillSurface}`);
3395
3449
  if (skills.length === 0) {
3396
3450
  console.log("- skills: none");
3397
3451
  }
@@ -3472,6 +3526,10 @@ async function main() {
3472
3526
  await runClearQuestion(values);
3473
3527
  return;
3474
3528
  }
3529
+ if (command === "prune-questions") {
3530
+ await runPruneQuestions(values);
3531
+ return;
3532
+ }
3475
3533
  if (command === "panel") {
3476
3534
  await runPanelCommand(values);
3477
3535
  return;
@@ -110,35 +110,16 @@ function looksLikeClosurePrompt(prompt) {
110
110
  return /\b(final|finalize|commit|ship|submit|revise|rewrite|draft|publish|implement|fix)\b/i.test(normalized)
111
111
  || /최종|확정|커밋|제출|수정|초안|구현|진행|고쳐/.test(normalized);
112
112
  }
113
- function looksLikeExecutionDirective(prompt) {
114
- const normalized = prompt.trim();
115
- if (!normalized) {
116
- return false;
117
- }
118
- return /\b(proceed|implement|fix|publish|release|deploy|tag|push|ship)\b/i.test(normalized)
119
- || /진행|구현|수정|고쳐|배포|릴리즈|태그|푸시|출시/.test(normalized);
120
- }
121
113
  function looksLikeLongTableEngineeringPrompt(prompt) {
122
114
  const normalized = prompt.trim();
123
115
  if (!normalized) {
124
116
  return false;
125
117
  }
126
- return /\b(longtable|hook|checkpoint|mcp|agent|npm|version|global|publish|release|deploy|git)\b/i.test(normalized)
127
- || /롱테이블|훅|체크포인트|에이전트|글로벌|배포|버전|릴리즈|깃|깃허브/.test(normalized);
128
- }
129
- function looksLikeDiagnosticOrExplanatoryPrompt(prompt) {
130
- const normalized = prompt.trim();
131
- if (!normalized) {
132
- return false;
133
- }
134
- return /\b(explain|why|how|diagnos(?:e|is)|debug|inspect|check|verify|status|simulate|simulation|test|logs?)\b/i.test(normalized)
135
- || /설명|왜|어떻게|진단|디버그|확인|점검|상태|시뮬레이션|테스트|로그|불필요/.test(normalized);
118
+ return /\b(longtable|hook|checkpoint|mcp|agent|skill|skills|ux|interface|setup|install|cli|npm|version|global|publish|release|deploy|git)\b/i.test(normalized)
119
+ || /롱테이블|훅|체크포인트|에이전트|스킬|사용성|인터페이스|설치|세팅|글로벌|배포|버전|릴리즈|깃|깃허브/.test(normalized);
136
120
  }
137
121
  function shouldAutoCreateQuestionsForPrompt(prompt) {
138
- if (!looksLikeLongTableEngineeringPrompt(prompt)) {
139
- return true;
140
- }
141
- return !looksLikeExecutionDirective(prompt) && !looksLikeDiagnosticOrExplanatoryPrompt(prompt);
122
+ return !looksLikeLongTableEngineeringPrompt(prompt);
142
123
  }
143
124
  function shouldApplyProtectedDecisionClosure(runtime, prompt) {
144
125
  return Boolean(runtime.context.session.protectedDecision) &&
@@ -277,6 +277,13 @@ export declare function clearWorkspaceQuestion(options: {
277
277
  question: QuestionRecord;
278
278
  state: ResearchState;
279
279
  }>;
280
+ export declare function pruneWorkspaceQuestions(options: {
281
+ context: LongTableProjectContext;
282
+ dryRun?: boolean;
283
+ }): Promise<{
284
+ removedQuestions: QuestionRecord[];
285
+ state: ResearchState;
286
+ }>;
280
287
  export declare function repairWorkspaceStateConsistency(options: {
281
288
  context: LongTableProjectContext;
282
289
  }): Promise<{
@@ -1513,6 +1513,53 @@ export async function clearWorkspaceQuestion(options) {
1513
1513
  state: updated
1514
1514
  };
1515
1515
  }
1516
+ function isPrunableFalsePositiveQuestion(record) {
1517
+ if (record.status !== "cleared") {
1518
+ return false;
1519
+ }
1520
+ return /false-positive|duplicated automatic hook/i.test(record.clearedReason ?? "");
1521
+ }
1522
+ export async function pruneWorkspaceQuestions(options) {
1523
+ const state = await loadResearchState(options.context.stateFilePath);
1524
+ const removedQuestions = (state.questionLog ?? []).filter(isPrunableFalsePositiveQuestion);
1525
+ if (removedQuestions.length === 0 || options.dryRun) {
1526
+ return {
1527
+ removedQuestions,
1528
+ state
1529
+ };
1530
+ }
1531
+ const removedIds = new Set(removedQuestions.map((question) => question.id));
1532
+ const updated = {
1533
+ ...state,
1534
+ questionLog: (state.questionLog ?? []).filter((question) => !removedIds.has(question.id)),
1535
+ questionObligations: (state.questionObligations ?? []).filter((obligation) => !obligation.questionId || !removedIds.has(obligation.questionId)),
1536
+ invocationLog: (state.invocationLog ?? []).map((record) => ({
1537
+ ...record,
1538
+ ...(record.panelResult
1539
+ ? {
1540
+ panelResult: {
1541
+ ...record.panelResult,
1542
+ linkedQuestionRecordIds: record.panelResult.linkedQuestionRecordIds.filter((id) => !removedIds.has(id))
1543
+ }
1544
+ }
1545
+ : {}),
1546
+ ...(record.teamDebateRun
1547
+ ? {
1548
+ teamDebateRun: {
1549
+ ...record.teamDebateRun,
1550
+ linkedQuestionRecordIds: record.teamDebateRun.linkedQuestionRecordIds.filter((id) => !removedIds.has(id))
1551
+ }
1552
+ }
1553
+ : {})
1554
+ }))
1555
+ };
1556
+ await writeFile(options.context.stateFilePath, JSON.stringify(updated, null, 2), "utf8");
1557
+ await syncCurrentWorkspaceView(options.context);
1558
+ return {
1559
+ removedQuestions,
1560
+ state: updated
1561
+ };
1562
+ }
1516
1563
  export async function repairWorkspaceStateConsistency(options) {
1517
1564
  const state = await loadResearchState(options.context.stateFilePath);
1518
1565
  const repaired = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@longtable/cli",
3
- "version": "0.1.38",
3
+ "version": "0.1.39",
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.38",
33
- "@longtable/core": "0.1.38",
34
- "@longtable/memory": "0.1.38",
35
- "@longtable/provider-claude": "0.1.38",
36
- "@longtable/provider-codex": "0.1.38",
37
- "@longtable/setup": "0.1.38"
32
+ "@longtable/checkpoints": "0.1.39",
33
+ "@longtable/core": "0.1.39",
34
+ "@longtable/memory": "0.1.39",
35
+ "@longtable/provider-claude": "0.1.39",
36
+ "@longtable/provider-codex": "0.1.39",
37
+ "@longtable/setup": "0.1.39"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@types/node": "^22.10.1",