@longtable/cli 0.1.37 → 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 +15 -10
- package/dist/cli.js +80 -22
- package/dist/longtable-codex-native-hook.js +3 -11
- package/dist/project-session.d.ts +7 -0
- package/dist/project-session.js +47 -0
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -156,16 +156,21 @@ longtable codex install-skills
|
|
|
156
156
|
longtable claude install-skills
|
|
157
157
|
```
|
|
158
158
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
`$longtable`
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
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.
|
|
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("
|
|
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,24 +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
|
-
||
|
|
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);
|
|
128
120
|
}
|
|
129
121
|
function shouldAutoCreateQuestionsForPrompt(prompt) {
|
|
130
|
-
return !
|
|
122
|
+
return !looksLikeLongTableEngineeringPrompt(prompt);
|
|
131
123
|
}
|
|
132
124
|
function shouldApplyProtectedDecisionClosure(runtime, prompt) {
|
|
133
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<{
|
package/dist/project-session.js
CHANGED
|
@@ -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.
|
|
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.
|
|
33
|
-
"@longtable/core": "0.1.
|
|
34
|
-
"@longtable/memory": "0.1.
|
|
35
|
-
"@longtable/provider-claude": "0.1.
|
|
36
|
-
"@longtable/provider-codex": "0.1.
|
|
37
|
-
"@longtable/setup": "0.1.
|
|
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",
|