@longtable/cli 0.1.42 → 0.1.43

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
@@ -188,6 +188,12 @@ Inside a LongTable project workspace, panel planning also appends an
188
188
  `InvocationRecord` to `.longtable/state.json`, creates a pending follow-up
189
189
  `QuestionRecord`, and refreshes `CURRENT.md`.
190
190
 
191
+ Panel output should remain inspectable. A panel or debate result is expected to
192
+ show the consulted roles, each role's main claim or objection, the disagreement
193
+ map, decision options, a defensible recommendation when one exists, and the
194
+ exact researcher-facing question before a high-stakes decision is treated as
195
+ settled.
196
+
191
197
  Default panel roles include:
192
198
 
193
199
  - `reviewer`
@@ -204,6 +210,12 @@ measurement, theory, method, evidence, authorship, or tacit-assumption risks.
204
210
  Use `--record` inside a LongTable workspace to store the finding as an
205
211
  unconfirmed inferred hypothesis.
206
212
 
213
+ The Codex hook stays quiet for advisory-only questions. Required hook context is
214
+ reserved for durable Researcher Checkpoints, especially when a prompt would
215
+ change the research question/scope, theory frame, measurement/coding standard,
216
+ method design, or analysis strategy. Low-risk reversible work should proceed
217
+ with visible assumptions rather than a noisy hook interruption.
218
+
207
219
  `longtable team` creates a file-backed agent-team review under
208
220
  `.longtable/team/<id>/`: independent review, cross-review, and
209
221
  synthesis/checkpoint. Use it when roles should inspect each other's concerns
@@ -1,5 +1,5 @@
1
1
  import { pathToFileURL } from "node:url";
2
- import { buildQuestionOpportunitySpecs, createWorkspaceFollowUpQuestions, loadProjectContextFromDirectory, loadWorkspaceState, pendingQuestionObligations } from "./index.js";
2
+ import { createWorkspaceFollowUpQuestions, loadProjectContextFromDirectory, loadWorkspaceState, pendingQuestionObligations } from "./index.js";
3
3
  function safeString(value) {
4
4
  return typeof value === "string" ? value : "";
5
5
  }
@@ -115,7 +115,7 @@ function looksLikeLongTableProductOrToolingPrompt(prompt) {
115
115
  if (!normalized) {
116
116
  return false;
117
117
  }
118
- return /\b(longlongtable|hook|checkpoint|mcp|agents?|skills?|ux|interface|setup|install|cli|npm|version|global|release|deploy|git|github|readme|docs?|documentation|workflow|package|router|autocomplete|simulation test)\b/i.test(normalized)
118
+ return /\b(longtable|longlongtable|hook|checkpoint|mcp|agents?|skills?|ux|interface|setup|install|cli|npm|version|global|release|deploy|git|github|readme|docs?|documentation|workflow|package|router|autocomplete|simulation test)\b/i.test(normalized)
119
119
  || /롱테이블|훅|체크포인트|에이전트|스킬|사용성|인터페이스|설치|세팅|글로벌|배포|버전|릴리즈|깃|깃허브|문서화된\s*절차|패키지|라우터|자동완성|시뮬레이션\s*테스트/.test(normalized);
120
120
  }
121
121
  function looksLikeResearchDomainPrompt(prompt) {
@@ -123,11 +123,38 @@ function looksLikeResearchDomainPrompt(prompt) {
123
123
  if (!normalized) {
124
124
  return false;
125
125
  }
126
- return /\b(research|study|paper|manuscript|journal|article|method|methodology|measurement|construct|theory|analysis|model|data|participant|sample|scale|survey|instrument|validity|hypothesis|literature|meta[- ]?analysis|gold standard|coding|trust|reliance|calibration)\b/i.test(normalized)
127
- || /연구|논문|원고|저널|방법론|방법|연구\s*설계|측정|구성개념|개념|이론|분석|모형|모델|데이터|참가자|표본|샘플|척도|설문|도구|타당도|가설|문헌|메타\s*분석|골드\s*스탠더드|코딩|신뢰|의존|캘리브레이션|교정|보정/.test(normalized);
126
+ return /\b(research|research question|research direction|scope|boundary|study|paper|manuscript|journal|article|method|methodology|measurement|construct|theory|framework|analysis|analysis plan|model|data|participant|sample|scale|survey|instrument|validity|hypothesis|literature|meta[- ]?analysis|gold standard|coding|criteria|trust|reliance|calibration)\b/i.test(normalized)
127
+ || /연구|연구\s*질문|연구\s*방향|범위|경계|논문|원고|저널|방법론|방법|연구\s*설계|측정|구성개념|개념|이론|프레임워크|분석|분석\s*계획|모형|모델|데이터|참가자|표본|샘플|척도|설문|도구|타당도|가설|문헌|메타\s*분석|골드\s*스탠더드|코딩|기준|신뢰|의존|캘리브레이션|교정|보정/.test(normalized);
128
128
  }
129
129
  function looksLikeResearchCommitmentPrompt(prompt) {
130
- return looksLikeResearchDomainPrompt(prompt) && looksLikeClosurePrompt(prompt);
130
+ return looksLikeResearchDomainPrompt(prompt) && (looksLikeClosurePrompt(prompt) ||
131
+ /\b(change|revise|update|replace|reframe|modify|alter)\b/i.test(prompt) ||
132
+ /바꾸|변경|수정|교체|전환|재설정/.test(prompt));
133
+ }
134
+ function looksLikeQuestionGenerationPrompt(prompt) {
135
+ return /\b(needed questions?|necessary questions?|question generation|clarifying questions?|ask questions?)\b/i.test(prompt)
136
+ || /필요한\s*질문|질문을\s*(모두|많이|생성)|질문\s*생성|물어봐|질문해/.test(prompt);
137
+ }
138
+ function looksLikeMultiCommitmentChangePrompt(prompt) {
139
+ const normalized = prompt.trim();
140
+ const actionCue = /\b(change|revise|update|replace|reframe|modify|alter)\b/i.test(normalized)
141
+ || /바꾸|변경|수정|교체|전환|재설정/.test(normalized);
142
+ if (!actionCue) {
143
+ return false;
144
+ }
145
+ const categories = [
146
+ /\b(research question|research direction|scope|boundary|inclusion criteria|exclusion criteria)\b/i.test(normalized)
147
+ || /연구\s*질문|연구\s*문제|연구\s*방향|범위|경계|포함\s*기준|제외\s*기준/.test(normalized),
148
+ /\b(theory|framework|conceptual model|construct map)\b/i.test(normalized)
149
+ || /이론|프레임워크|개념\s*모형|구성개념\s*지도|컨스트럭트/.test(normalized),
150
+ /\b(measure|measurement|scale|instrument|coding|coding rule|extraction rule|operationali[sz]ation)\b/i.test(normalized)
151
+ || /측정|척도|도구|코딩|코딩\s*규칙|코딩\s*기준|추출\s*규칙|추출\s*기준|조작화/.test(normalized),
152
+ /\b(method|methodology|study design|sampling|sample)\b/i.test(normalized)
153
+ || /방법론|방법|연구\s*설계|표본|샘플링/.test(normalized),
154
+ /\b(analysis plan|analysis method|meta[- ]?analysis|masem|(?:statistical|structural|path|analysis) model|moderator|random[- ]?effects)\b/i.test(normalized)
155
+ || /분석\s*계획|분석\s*방법|메타\s*분석|분석\s*(?:모형|모델)|통계\s*(?:모형|모델)|구조\s*방정식|경로\s*모형|조절효과|랜덤\s*효과/.test(normalized)
156
+ ];
157
+ return categories.filter(Boolean).length >= 2;
131
158
  }
132
159
  function looksLikeExplicitInterviewPrompt(prompt) {
133
160
  const normalized = prompt.trim();
@@ -156,28 +183,14 @@ function looksLikeResearchStateConfirmationPrompt(prompt) {
156
183
  function shouldSurfaceInterviewContext(prompt) {
157
184
  return looksLikeExplicitInterviewPrompt(prompt) || looksLikeResearchStateConfirmationPrompt(prompt);
158
185
  }
159
- function buildResponseOnlyAdvisoryQuestions(prompt) {
160
- if (looksLikeLongTableProductOrToolingPrompt(prompt)) {
161
- return [];
162
- }
163
- const opportunities = buildQuestionOpportunitySpecs(prompt, {
164
- includeFallback: false,
165
- autoOnly: true
166
- });
167
- if (opportunities.length === 0) {
168
- return [];
169
- }
170
- if (!looksLikeResearchDomainPrompt(prompt) && !/\b(needed questions?|necessary questions?|clarifying questions?|question generation|assumptions?|uncertain|not sure|gap|tension|trade[- ]?off)\b/i.test(prompt) && !/필요한\s*질문|질문\s*생성|물어봐|질문해|전제|가정|불확실|모르겠|공백|긴장|상충|균형/.test(prompt)) {
171
- return [];
172
- }
173
- return opportunities.slice(0, 3);
174
- }
175
186
  function shouldCreateRequiredQuestionsForPrompt(prompt) {
176
187
  return !looksLikeLongTableProductOrToolingPrompt(prompt) && looksLikeResearchCommitmentPrompt(prompt);
177
188
  }
178
189
  function shouldApplyProtectedDecisionClosure(runtime, prompt) {
179
190
  return Boolean(runtime.context.session.protectedDecision) &&
180
- shouldCreateRequiredQuestionsForPrompt(prompt);
191
+ shouldCreateRequiredQuestionsForPrompt(prompt) &&
192
+ !looksLikeQuestionGenerationPrompt(prompt) &&
193
+ !looksLikeMultiCommitmentChangePrompt(prompt);
181
194
  }
182
195
  function protectedDecisionClosurePrompt(prompt) {
183
196
  return [
@@ -262,16 +275,6 @@ function buildGeneratedQuestionsContext(questions, created) {
262
275
  lines.push("Do not choose or record answers for these checkpoints unless the researcher explicitly provides the selections.");
263
276
  return lines.join("\n");
264
277
  }
265
- function buildAdvisoryQuestionsContext(questions) {
266
- const lines = [
267
- `LongTable surfaced ${questions.length} response-only advisory question${questions.length === 1 ? "" : "s"} for this prompt.`,
268
- "Use these only if they help the reply. Do not create QuestionRecord entries, call longtable decide, or answer for the researcher unless the prompt explicitly asks to commit a research decision."
269
- ];
270
- for (const question of questions) {
271
- lines.push(`- ${question.title}: ${question.question}`);
272
- }
273
- return lines.join("\n");
274
- }
275
278
  function buildPendingObligationContext(obligation) {
276
279
  return [
277
280
  `Pending LongTable research obligation: ${obligation.prompt}`,
@@ -347,37 +350,33 @@ async function userPromptSubmitContext(runtime, prompt) {
347
350
  }
348
351
  const generatedQuestions = [];
349
352
  let createdQuestions = false;
350
- if (shouldCreateRequiredQuestionsForPrompt(prompt)) {
351
- const generated = await createWorkspaceFollowUpQuestions({
353
+ if (shouldApplyProtectedDecisionClosure(runtime, prompt)) {
354
+ const protectedGenerated = await createWorkspaceFollowUpQuestions({
352
355
  context: runtime.context,
353
- prompt,
356
+ prompt: protectedDecisionClosurePrompt(prompt),
354
357
  provider: "codex",
355
358
  required: true,
356
359
  auto: true,
357
360
  requiredOnly: true
358
361
  });
359
- generatedQuestions.push(...generated.questions);
360
- createdQuestions = createdQuestions || generated.created;
362
+ generatedQuestions.push(...protectedGenerated.questions);
363
+ createdQuestions = createdQuestions || protectedGenerated.created;
361
364
  }
362
- if (shouldApplyProtectedDecisionClosure(runtime, prompt)) {
363
- const protectedGenerated = await createWorkspaceFollowUpQuestions({
365
+ else if (shouldCreateRequiredQuestionsForPrompt(prompt)) {
366
+ const generated = await createWorkspaceFollowUpQuestions({
364
367
  context: runtime.context,
365
- prompt: protectedDecisionClosurePrompt(prompt),
368
+ prompt,
366
369
  provider: "codex",
367
370
  required: true,
368
371
  auto: true,
369
372
  requiredOnly: true
370
373
  });
371
- generatedQuestions.push(...protectedGenerated.questions.filter((question) => !generatedQuestions.some((existing) => existing.id === question.id)));
372
- createdQuestions = createdQuestions || protectedGenerated.created;
374
+ generatedQuestions.push(...generated.questions);
375
+ createdQuestions = createdQuestions || generated.created;
373
376
  }
374
377
  if (generatedQuestions.length > 0) {
375
378
  return buildGeneratedQuestionsContext(generatedQuestions, createdQuestions);
376
379
  }
377
- const advisoryQuestions = buildResponseOnlyAdvisoryQuestions(prompt);
378
- if (advisoryQuestions.length > 0) {
379
- return buildAdvisoryQuestionsContext(advisoryQuestions);
380
- }
381
380
  return null;
382
381
  }
383
382
  function preToolUseOutput(runtime, payload) {
@@ -1001,6 +1001,29 @@ function optionsForCheckpointTrigger(family, checkpointKey) {
1001
1001
  function includesAny(prompt, patterns) {
1002
1002
  return patterns.some((pattern) => pattern.test(prompt));
1003
1003
  }
1004
+ function questionPriority(spec) {
1005
+ const byKey = {
1006
+ protected_decision_closure: 100,
1007
+ research_direction_change_commitment: 96,
1008
+ construct_boundary_commitment: 94,
1009
+ measurement_coding_standard: 92,
1010
+ analysis_strategy_commitment: 90,
1011
+ theory_frame_commitment: 88,
1012
+ method_design_commitment: 86,
1013
+ research_scope_boundary: 84,
1014
+ epistemic_alignment_boundary: 82,
1015
+ value_conflict_boundary: 80,
1016
+ source_authority: 70,
1017
+ knowledge_gap_probe: 68,
1018
+ tacit_assumption_probe: 66,
1019
+ needed_question_policy: 60,
1020
+ philosophical_checkpoint_boundary: 58,
1021
+ harness_question_harness: 55
1022
+ };
1023
+ const confidenceWeight = spec.confidence === "high" ? 10 : spec.confidence === "medium" ? 5 : 0;
1024
+ const requiredWeight = spec.kind === "research_commitment" || spec.required ? 20 : 0;
1025
+ return (byKey[spec.key] ?? 0) + confidenceWeight + requiredWeight;
1026
+ }
1004
1027
  function followUpQuestionOptions(first, second, third, fourth) {
1005
1028
  return [first, second, third, ...(fourth ? [fourth] : [])];
1006
1029
  }
@@ -1018,6 +1041,158 @@ export function buildQuestionOpportunitySpecs(prompt, options = {}) {
1018
1041
  });
1019
1042
  }
1020
1043
  }
1044
+ const decisionActionCue = includesAny(normalized, [
1045
+ /\b(final|finalize|commit|decide|settle|freeze|lock|record|apply|incorporate|change|revise|update|replace|reframe|modify|alter)\b/i,
1046
+ /최종|확정|결정|고정|기록|반영|바꾸|변경|수정|교체|전환|재설정/
1047
+ ]);
1048
+ const scopeCue = includesAny(normalized, [
1049
+ /\bresearch question\b/i,
1050
+ /\bresearch direction\b/i,
1051
+ /\bscope\b/i,
1052
+ /\bboundary\b/i,
1053
+ /\binclusion criteria\b/i,
1054
+ /\bexclusion criteria\b/i,
1055
+ /연구\s*질문|연구\s*문제|연구\s*방향|범위|경계|포함\s*기준|제외\s*기준/
1056
+ ]);
1057
+ const theoryCue = includesAny(normalized, [
1058
+ /\btheory\b/i,
1059
+ /\bframework\b/i,
1060
+ /\bconceptual model\b/i,
1061
+ /\bconstruct map\b/i,
1062
+ /이론|프레임워크|개념\s*모형|구성개념\s*지도|컨스트럭트/
1063
+ ]);
1064
+ const measurementCodingCue = includesAny(normalized, [
1065
+ /\bmeasure\b/i,
1066
+ /\bmeasurement\b/i,
1067
+ /\bscale\b/i,
1068
+ /\binstrument\b/i,
1069
+ /\bcoding\b/i,
1070
+ /\bcoding rule\b/i,
1071
+ /\bextraction rule\b/i,
1072
+ /\boperationali[sz]ation\b/i,
1073
+ /측정|척도|도구|코딩|코딩\s*규칙|코딩\s*기준|추출\s*규칙|추출\s*기준|조작화/
1074
+ ]);
1075
+ const methodCue = includesAny(normalized, [
1076
+ /\bmethod\b/i,
1077
+ /\bmethodology\b/i,
1078
+ /\bstudy design\b/i,
1079
+ /\bsampling\b/i,
1080
+ /\bsample\b/i,
1081
+ /방법론|방법|연구\s*설계|표본|샘플링/
1082
+ ]);
1083
+ const analysisCue = includesAny(normalized, [
1084
+ /\banalysis plan\b/i,
1085
+ /\banalysis method\b/i,
1086
+ /\bmeta[- ]?analysis\b/i,
1087
+ /\bmasem\b/i,
1088
+ /\b(statistical|structural|path|analysis) model\b/i,
1089
+ /\bmoderator\b/i,
1090
+ /\brandom[- ]?effects\b/i,
1091
+ /분석\s*계획|분석\s*방법|메타\s*분석|분석\s*(?:모형|모델)|통계\s*(?:모형|모델)|구조\s*방정식|경로\s*모형|조절효과|랜덤\s*효과/
1092
+ ]);
1093
+ const decisionFamilyCount = [scopeCue, theoryCue, measurementCodingCue, methodCue, analysisCue]
1094
+ .filter(Boolean).length;
1095
+ if (decisionActionCue && decisionFamilyCount >= 2) {
1096
+ push({
1097
+ key: "research_direction_change_commitment",
1098
+ kind: "research_commitment",
1099
+ title: "Research direction change",
1100
+ question: "Which high-risk research commitment should LongTable clarify first before changing the project direction?",
1101
+ whyNow: "The prompt touches multiple protected research commitments; proceeding silently would let LongTable choose the priority order for the researcher.",
1102
+ options: followUpQuestionOptions({ value: "scope_first", label: "Scope or research question first", description: "Clarify what the study includes, excludes, or asks before changing downstream work.", recommended: true }, { value: "theory_first", label: "Theory or construct frame first", description: "Clarify the conceptual frame before changing methods or analysis." }, { value: "method_analysis_first", label: "Method or analysis first", description: "Clarify design, data, or analysis implications before changing the artifact." }, { value: "defer", label: "Keep the direction open", description: "Do not change the research direction until the commitment order is explicit." }),
1103
+ confidence: "high",
1104
+ autoEligible: true,
1105
+ required: true,
1106
+ cues: ["research_direction", "multi_commitment_change"]
1107
+ });
1108
+ }
1109
+ if (decisionActionCue && scopeCue) {
1110
+ push({
1111
+ key: "research_scope_boundary",
1112
+ kind: "research_commitment",
1113
+ title: "Research scope boundary",
1114
+ question: "What scope boundary should LongTable keep explicit before treating the research direction as changed?",
1115
+ whyNow: "Scope changes can redefine the population, domain, corpus, or research question before the researcher has explicitly chosen the boundary.",
1116
+ options: followUpQuestionOptions({ value: "revise_scope", label: "Revise the scope", description: "Change the inclusion boundary before downstream work continues.", recommended: true }, { value: "compare_boundaries", label: "Compare boundaries first", description: "Keep candidate scopes visible before choosing one." }, { value: "proceed_with_scope_assumption", label: "Proceed with scope assumption", description: "Continue only after stating the assumed boundary." }, { value: "defer", label: "Keep scope open", description: "Do not settle the scope yet." }),
1117
+ confidence: "high",
1118
+ autoEligible: true,
1119
+ cues: ["research_scope", "boundary"]
1120
+ });
1121
+ }
1122
+ if (decisionActionCue && theoryCue) {
1123
+ push({
1124
+ key: "theory_frame_commitment",
1125
+ kind: "research_commitment",
1126
+ title: "Theory frame",
1127
+ question: "Which theory or construct frame should LongTable treat as the candidate commitment before revising the model?",
1128
+ whyNow: "Theory-frame changes can make later measurement, coding, and analysis choices look settled when they are only inferred.",
1129
+ options: followUpQuestionOptions({ value: "compare_theories", label: "Compare theory frames first", description: "Keep competing theoretical anchors visible before choosing one.", recommended: true }, { value: "revise_theory", label: "Revise the frame", description: "Change the framework and record the conceptual tradeoff." }, { value: "use_current_frame", label: "Use current frame tentatively", description: "Proceed but mark the theory choice as provisional." }, { value: "defer", label: "Keep theory open", description: "Do not settle the theory frame yet." }),
1130
+ confidence: "high",
1131
+ autoEligible: true,
1132
+ cues: ["theory", "framework", "construct"]
1133
+ });
1134
+ }
1135
+ if (decisionActionCue && measurementCodingCue) {
1136
+ push({
1137
+ key: "measurement_coding_standard",
1138
+ kind: "research_commitment",
1139
+ title: "Measurement and coding standard",
1140
+ question: "What measurement or coding rule should LongTable ask you to fix before extracting or revising data?",
1141
+ whyNow: "Measurement and coding rules decide what counts as evidence; changing them silently can make later synthesis non-reproducible.",
1142
+ options: followUpQuestionOptions({ value: "define_construct_rule", label: "Define construct rule first", description: "Clarify what counts as the construct or variable before extraction.", recommended: true }, { value: "define_extraction_rule", label: "Define extraction rule first", description: "Clarify correlation, path, beta, or qualitative evidence extraction rules." }, { value: "pilot_code", label: "Pilot the coding rule", description: "Test the rule on a small sample before committing." }, { value: "defer", label: "Keep coding open", description: "Do not settle measurement or coding yet." }),
1143
+ confidence: "high",
1144
+ autoEligible: true,
1145
+ cues: ["measurement", "coding", "extraction"]
1146
+ });
1147
+ }
1148
+ if (decisionActionCue && methodCue) {
1149
+ push({
1150
+ key: "method_design_commitment",
1151
+ kind: "research_commitment",
1152
+ title: "Method design",
1153
+ question: "Which method-design choice should LongTable keep explicit before changing the study plan?",
1154
+ whyNow: "Method changes affect the defensible claim, sample, evidence standard, and ethics boundary.",
1155
+ options: followUpQuestionOptions({ value: "revise_design", label: "Revise design first", description: "Change the design or sample boundary before proceeding.", recommended: true }, { value: "check_feasibility", label: "Check feasibility first", description: "Inspect whether data, evidence, and access support the method." }, { value: "proceed_with_method_assumption", label: "Proceed with method assumption", description: "Continue only after stating the assumed method." }, { value: "defer", label: "Keep method open", description: "Do not commit the method yet." }),
1156
+ confidence: "high",
1157
+ autoEligible: true,
1158
+ cues: ["method", "study_design", "sample"]
1159
+ });
1160
+ }
1161
+ if (decisionActionCue && analysisCue) {
1162
+ push({
1163
+ key: "analysis_strategy_commitment",
1164
+ kind: "research_commitment",
1165
+ title: "Analysis strategy",
1166
+ question: "What analysis strategy should LongTable treat as unsettled before revising or running the synthesis?",
1167
+ whyNow: "Analysis choices determine what effect sizes, moderators, and interpretations become defensible.",
1168
+ options: followUpQuestionOptions({ value: "choose_analysis_family", label: "Choose analysis family first", description: "Clarify MASEM, family-level meta-analysis, moderator analysis, or narrative synthesis.", recommended: true }, { value: "check_data_sufficiency", label: "Check data sufficiency first", description: "Inspect whether primary quantitative effects support the analysis." }, { value: "proceed_with_analysis_assumption", label: "Proceed with assumption", description: "Continue only after stating the analysis assumption." }, { value: "defer", label: "Keep analysis open", description: "Do not settle the analysis plan yet." }),
1169
+ confidence: "high",
1170
+ autoEligible: true,
1171
+ cues: ["analysis", "model", "meta_analysis"]
1172
+ });
1173
+ }
1174
+ if (decisionActionCue && includesAny(normalized, [
1175
+ /\bconflict\b/i,
1176
+ /\bcontradict/i,
1177
+ /\bontology\b/i,
1178
+ /\bepistem/i,
1179
+ /\bhuman knowledge\b/i,
1180
+ /\bai knowledge\b/i,
1181
+ /\balignment\b/i,
1182
+ /충돌|상충|모순|존재론|인식론|지식|인간의\s*지식|ai의\s*지식|정렬|방향성/
1183
+ ])) {
1184
+ push({
1185
+ key: "epistemic_alignment_boundary",
1186
+ kind: "value_conflict",
1187
+ title: "Knowledge alignment",
1188
+ question: "When researcher knowledge, AI inference, and project state conflict, what should LongTable privilege before acting?",
1189
+ whyNow: "The prompt asks LongTable to mediate knowledge conflict; that mediation should be visible rather than hidden inside an implementation choice.",
1190
+ options: followUpQuestionOptions({ value: "ask_researcher", label: "Ask researcher clarity first", description: "Pause when human meaning or priority is underspecified.", recommended: true }, { value: "inspect_project_state", label: "Inspect project state first", description: "Use durable files and prior decisions before inferring intent." }, { value: "proceed_with_trace", label: "Proceed with explicit trace", description: "Continue only after naming the conflict and assumption." }, { value: "defer", label: "Keep conflict open", description: "Do not collapse the conflict into one answer yet." }),
1191
+ confidence: "high",
1192
+ autoEligible: true,
1193
+ cues: ["knowledge_conflict", "epistemic_alignment"]
1194
+ });
1195
+ }
1021
1196
  if (includesAny(normalized, [
1022
1197
  /\blongtable\b/,
1023
1198
  /\bharness\b/,
@@ -1251,7 +1426,13 @@ export function buildQuestionOpportunitySpecs(prompt, options = {}) {
1251
1426
  if (options.requiredOnly === true) {
1252
1427
  selected = selected.filter((spec) => spec.kind === "research_commitment");
1253
1428
  }
1254
- return selected;
1429
+ if (normalized.includes("protected decision closure pressure")) {
1430
+ selected = selected.filter((spec) => spec.key === "protected_decision_closure");
1431
+ }
1432
+ else if (options.requiredOnly === true && selected.some((spec) => spec.key === "research_direction_change_commitment")) {
1433
+ selected = selected.filter((spec) => spec.key === "research_direction_change_commitment");
1434
+ }
1435
+ return selected.sort((a, b) => questionPriority(b) - questionPriority(a));
1255
1436
  }
1256
1437
  function buildFollowUpQuestionSpecs(prompt) {
1257
1438
  return buildQuestionOpportunitySpecs(prompt);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@longtable/cli",
3
- "version": "0.1.42",
3
+ "version": "0.1.43",
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.42",
33
- "@longtable/core": "0.1.42",
34
- "@longtable/memory": "0.1.42",
35
- "@longtable/provider-claude": "0.1.42",
36
- "@longtable/provider-codex": "0.1.42",
37
- "@longtable/setup": "0.1.42"
32
+ "@longtable/checkpoints": "0.1.43",
33
+ "@longtable/core": "0.1.43",
34
+ "@longtable/memory": "0.1.43",
35
+ "@longtable/provider-claude": "0.1.43",
36
+ "@longtable/provider-codex": "0.1.43",
37
+ "@longtable/setup": "0.1.43"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@types/node": "^22.10.1",