@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 +25 -1
- package/dist/cli.js +45 -82
- package/dist/debate.js +21 -21
- package/dist/longtable-codex-native-hook.js +1 -1
- package/dist/panel.js +1 -1
- package/dist/persona-router.d.ts +1 -1
- package/dist/persona-router.js +2 -2
- package/dist/project-session.js +1 -1
- package/package.json +7 -7
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
|
|
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
|
|
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
|
|
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 (
|
|
2270
|
-
return "
|
|
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 "
|
|
2284
|
+
return "panel";
|
|
2286
2285
|
}
|
|
2287
2286
|
if (highStakes) {
|
|
2288
|
-
return "
|
|
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 === "
|
|
3390
|
-
await
|
|
3388
|
+
if (collaborationRoute === "debate") {
|
|
3389
|
+
await runPanelDebateCommand({
|
|
3391
3390
|
...delegatedArgs,
|
|
3392
|
-
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
|
|
3412
|
-
await mkdir(
|
|
3413
|
-
await writeFile(join(
|
|
3414
|
-
await writeJsonFile(join(
|
|
3415
|
-
await writeJsonFile(join(
|
|
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(
|
|
3419
|
+
await writeJsonFile(join(panelDir, contribution.artifactPath), contribution);
|
|
3421
3420
|
}
|
|
3422
3421
|
}
|
|
3423
|
-
await writeJsonFile(join(
|
|
3424
|
-
await writeJsonFile(join(
|
|
3425
|
-
await writeJsonFile(join(
|
|
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
|
|
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
|
|
3511
|
-
|
|
3512
|
-
|
|
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
|
|
3525
|
-
const
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
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
|
|
3530
|
+
await writePanelDebateArtifacts(debate, panelDir, prompt);
|
|
3572
3531
|
const canRecordWorkspace = projectAware.projectContextFound && projectContext && existsSync(projectContext.stateFilePath);
|
|
3573
3532
|
if (canRecordWorkspace) {
|
|
3574
|
-
await appendInvocationRecordToWorkspace(projectContext,
|
|
3533
|
+
await appendInvocationRecordToWorkspace(projectContext, debate.invocationRecord, [debate.questionRecord]);
|
|
3575
3534
|
}
|
|
3576
3535
|
if (args.json === true) {
|
|
3577
3536
|
console.log(JSON.stringify({
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
plan:
|
|
3581
|
-
run:
|
|
3582
|
-
questionRecord:
|
|
3583
|
-
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:
|
|
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(
|
|
3595
|
-
console.log(`-
|
|
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
|
-
|
|
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" : "
|
|
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: "
|
|
205
|
-
title: isDebate ? "
|
|
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
|
-
"
|
|
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
|
-
`
|
|
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
|
|
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("
|
|
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("
|
|
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("
|
|
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("
|
|
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("
|
|
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: "
|
|
325
|
+
surface: "file_backed_panel_debate",
|
|
326
326
|
interactionDepth: kind === "debate" ? "debated" : "cross_reviewed",
|
|
327
|
-
roundPolicy: kind === "debate" ? "fixed" : "
|
|
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("
|
|
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
|
|
357
|
-
: "
|
|
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" ? "
|
|
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
|
|
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
|
|
393
|
-
`-
|
|
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
|
|
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: "
|
|
186
|
+
degradationReason: "Sequential fallback is the stable LongTable panel surface."
|
|
187
187
|
};
|
|
188
188
|
}
|
|
189
189
|
function roleInstruction(member) {
|
package/dist/persona-router.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ export interface LongTableInvocationDirective {
|
|
|
12
12
|
explicit: boolean;
|
|
13
13
|
cleanedPrompt: string;
|
|
14
14
|
mode?: InteractionMode | "panel" | "status";
|
|
15
|
-
collaboration?: "panel" | "
|
|
15
|
+
collaboration?: "panel" | "debate";
|
|
16
16
|
roles: CanonicalPersona[];
|
|
17
17
|
panel: boolean;
|
|
18
18
|
showConflicts: boolean;
|
package/dist/persona-router.js
CHANGED
|
@@ -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: "
|
|
12
|
-
{ key: "debate", mode: "
|
|
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"] },
|
package/dist/project-session.js
CHANGED
|
@@ -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.
|
|
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.
|
|
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.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",
|