@longtable/cli 0.1.49 → 0.1.51
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 +35 -248
- package/dist/cli.js +13 -12
- package/dist/longtable-codex-native-hook.js +3 -3
- package/dist/project-session.d.ts +12 -2
- package/dist/project-session.js +145 -35
- package/dist/prompt-aliases.js +3 -3
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -2,16 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
Researcher-facing CLI for LongTable.
|
|
4
4
|
|
|
5
|
-
LongTable
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
The basic contract is:
|
|
10
|
-
|
|
11
|
-
1. approve provider/runtime support once
|
|
12
|
-
2. start each project inside the provider with `$longtable-interview`
|
|
13
|
-
3. create or resume a workspace from that interview
|
|
14
|
-
4. preserve decisions, tensions, and evidence as durable project state
|
|
5
|
+
LongTable keeps scholarly project state in `.longtable/` and exposes generated
|
|
6
|
+
provider skills for Codex and Claude Code. The CLI installs setup, state,
|
|
7
|
+
checkpoint, search, and diagnostic tooling. It does not replace the provider.
|
|
15
8
|
|
|
16
9
|
## Install
|
|
17
10
|
|
|
@@ -19,55 +12,35 @@ The basic contract is:
|
|
|
19
12
|
npm install -g @longtable/cli
|
|
20
13
|
```
|
|
21
14
|
|
|
22
|
-
The npm install only installs the CLI. It does not write Codex skills, MCP
|
|
23
|
-
config, hooks, or provider runtime files without explicit setup approval.
|
|
24
|
-
|
|
25
15
|
## Primary Flow
|
|
26
16
|
|
|
27
|
-
Start Codex from the research folder. The provider uses the shell working
|
|
28
|
-
directory at process start as the session workspace.
|
|
29
|
-
|
|
30
17
|
```bash
|
|
31
18
|
longtable setup --provider codex
|
|
32
19
|
cd "<research-folder>"
|
|
33
20
|
codex
|
|
34
21
|
```
|
|
35
22
|
|
|
36
|
-
|
|
37
|
-
Changing directories after Codex is already running does not change that
|
|
38
|
-
session's workspace root or rerun LongTable's `SessionStart` hook.
|
|
39
|
-
|
|
40
|
-
Examples:
|
|
23
|
+
Then invoke:
|
|
41
24
|
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
codex -C "/Users/yourname/Research/My-Research-Project"
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
```powershell
|
|
48
|
-
# Windows PowerShell
|
|
49
|
-
codex -C "C:\Users\YourName\Documents\Research\My-Research-Project"
|
|
25
|
+
```text
|
|
26
|
+
$longtable-start
|
|
50
27
|
```
|
|
51
28
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
`longtable setup --provider codex` is the permission-first setup route. It asks
|
|
55
|
-
where LongTable may install support, which runtime surfaces it may enable, how
|
|
56
|
-
strongly it may interrupt research decisions, and whether to show the
|
|
57
|
-
provider-native interview launch steps. `longtable init` remains only as a
|
|
58
|
-
deprecated compatibility alias.
|
|
29
|
+
`$longtable-start` creates or resumes the workspace, asks open research-start
|
|
30
|
+
questions, and stores a Research Specification when there is enough material.
|
|
59
31
|
|
|
60
|
-
|
|
32
|
+
After a Research Specification exists, use:
|
|
61
33
|
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
codex
|
|
34
|
+
```text
|
|
35
|
+
$longtable-interview
|
|
65
36
|
```
|
|
66
37
|
|
|
67
|
-
|
|
68
|
-
|
|
38
|
+
`$longtable-interview` is post-start. It uses option-first follow-up choices for
|
|
39
|
+
spec revisions, checkpoint resolution, evidence boundaries, coding rules, method
|
|
40
|
+
choices, and protected decisions. If no usable Research Specification exists, it
|
|
41
|
+
must route to `$longtable-start`.
|
|
69
42
|
|
|
70
|
-
##
|
|
43
|
+
## Workspace Artifacts
|
|
71
44
|
|
|
72
45
|
```text
|
|
73
46
|
<project>/
|
|
@@ -80,221 +53,35 @@ summary without starting a provider session.
|
|
|
80
53
|
sessions/
|
|
81
54
|
```
|
|
82
55
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
- `
|
|
87
|
-
- `.longtable/project.json`: stable project identity
|
|
88
|
-
- `.longtable/current-session.json`: current session cursor
|
|
89
|
-
- `.longtable/state.json`: layered memory state, including First Research
|
|
90
|
-
Shape and Research Specification when the interview has produced them
|
|
91
|
-
- `.longtable/sessions/`: historical snapshots
|
|
92
|
-
|
|
93
|
-
`$longtable-interview` first stabilizes a short First Research Shape. When the
|
|
94
|
-
conversation is substantive enough, it should also preserve a Research
|
|
95
|
-
Specification covering scope, construct ontology, theory framing,
|
|
96
|
-
measurement/coding, method options, evidence/access requirements, epistemic
|
|
97
|
-
alignment, protected decisions, open questions, and next actions. `CURRENT.md`
|
|
98
|
-
renders that specification so later agents do not need to reconstruct the full
|
|
99
|
-
interview from memory.
|
|
100
|
-
|
|
101
|
-
## Why This Shape
|
|
102
|
-
|
|
103
|
-
The CLI tries to keep the root simple for novice researchers while preserving enough structure for power users and downstream tooling.
|
|
104
|
-
|
|
105
|
-
The memory model distinguishes:
|
|
106
|
-
|
|
107
|
-
- explicit state
|
|
108
|
-
- working state
|
|
109
|
-
- inferred hypotheses
|
|
110
|
-
- open tensions
|
|
111
|
-
- narrative traces
|
|
56
|
+
- `CURRENT.md`: human-readable current project state
|
|
57
|
+
- `.longtable/state.json`: durable memory, questions, decisions, interview
|
|
58
|
+
turns, evidence records, First Research Shape, and Research Specification
|
|
59
|
+
- `QuestionRecord -> DecisionRecord`: the durable checkpoint lifecycle
|
|
112
60
|
|
|
113
|
-
|
|
61
|
+
Provider UI is transport. LongTable supports MCP/native structured elicitation,
|
|
62
|
+
interactive TTY selector surfaces, and numbered/plain-text fallback. Tmux is not
|
|
63
|
+
required for LongTable core behavior.
|
|
114
64
|
|
|
115
65
|
## Commands
|
|
116
66
|
|
|
117
67
|
```bash
|
|
118
|
-
longtable setup
|
|
68
|
+
longtable setup --provider codex
|
|
69
|
+
longtable doctor
|
|
70
|
+
longtable status --cwd "<project-path>"
|
|
119
71
|
longtable resume --cwd "<project-path>"
|
|
120
72
|
longtable roles
|
|
121
|
-
longtable
|
|
122
|
-
longtable
|
|
123
|
-
longtable
|
|
124
|
-
longtable
|
|
125
|
-
longtable team --debate --prompt "Review this measurement plan." --role editor,measurement_auditor --json
|
|
126
|
-
longtable codex install-skills
|
|
127
|
-
longtable claude install-skills
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
Useful structured routes for scripts and debugging:
|
|
131
|
-
|
|
132
|
-
```bash
|
|
133
|
-
longtable panel --prompt "review this methods section" --json
|
|
134
|
-
longtable review --role methods_critic,measurement_auditor --panel --prompt "review this methods section" --json
|
|
135
|
-
longtable ask --prompt "lt panel: show the disagreement before I commit" --json
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
## Inside Codex
|
|
139
|
-
|
|
140
|
-
Natural language should be the default.
|
|
141
|
-
|
|
142
|
-
Codex UI Researcher Checkpoints are a core LongTable feature when enabled:
|
|
143
|
-
|
|
144
|
-
```bash
|
|
145
|
-
longtable setup --provider codex --surfaces skills_mcp --checkpoint-ui strong
|
|
73
|
+
longtable question --prompt "<decision context>"
|
|
74
|
+
longtable decide --question <id> --answer <value>
|
|
75
|
+
longtable spec read --cwd "<project-path>"
|
|
76
|
+
longtable search --query "<topic>"
|
|
146
77
|
```
|
|
147
78
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
`QuestionRecord` pending and falls back to numbered text.
|
|
151
|
-
|
|
152
|
-
## Runtime Boundary
|
|
153
|
-
|
|
154
|
-
LongTable is not a replacement wrapper for Codex. Markdown docs and generated
|
|
155
|
-
skills are soft policy; hooks, MCP elicitation, CLI gates, and `.longtable/`
|
|
156
|
-
state are the enforcement layers.
|
|
157
|
-
|
|
158
|
-
LongTable should ask and stop before acting when the next step would change or
|
|
159
|
-
settle one of four high-risk research commitments:
|
|
160
|
-
|
|
161
|
-
1. Research question or scope
|
|
162
|
-
2. Theory frame or construct map
|
|
163
|
-
3. Measurement, coding, or extraction standard
|
|
164
|
-
4. Method design or analysis strategy
|
|
165
|
-
|
|
166
|
-
Low-risk reversible work should continue with visible assumptions instead of a
|
|
167
|
-
hook interruption. If human knowledge, AI inference, and durable project state
|
|
168
|
-
conflict, LongTable should prefer the most explicit durable state; if that state
|
|
169
|
-
is not explicit enough, it should ask the researcher for clarity.
|
|
170
|
-
|
|
171
|
-
Explicit short forms are available when needed:
|
|
172
|
-
|
|
173
|
-
```text
|
|
174
|
-
lt explore: Where should I narrow the question first?
|
|
175
|
-
lt review: What is weak in this claim?
|
|
176
|
-
lt panel: Show me the disagreement before I commit.
|
|
177
|
-
lt methods: Where is the design vulnerable?
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
Provider-native surfaces are available when installed:
|
|
181
|
-
|
|
182
|
-
```bash
|
|
183
|
-
longtable codex install-skills
|
|
184
|
-
longtable claude install-skills
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
By default, provider skills use the compact surface: `longtable`,
|
|
188
|
-
`longtable-interview`, and five short role shortcuts: `longtable-methods`,
|
|
189
|
-
`longtable-measure`, `longtable-theory`, `longtable-reviewer`, and
|
|
190
|
-
`longtable-voice`. `$longtable` remains the general router and can still invoke
|
|
191
|
-
editor, ethics, venue, panel, explore, or review behavior when the request calls
|
|
192
|
-
for it.
|
|
193
|
-
|
|
194
|
-
Power users can install the legacy full surface explicitly:
|
|
195
|
-
|
|
196
|
-
```bash
|
|
197
|
-
longtable codex install-skills --surface full
|
|
198
|
-
longtable claude install-skills --surface full
|
|
199
|
-
```
|
|
200
|
-
|
|
201
|
-
Do not depend on `/prompts`; current Codex builds may reject it.
|
|
202
|
-
|
|
203
|
-
## Panel Orchestration
|
|
204
|
-
|
|
205
|
-
Panel orchestration is for moments where disagreement matters: methods risk,
|
|
206
|
-
measurement validity, theory fit, literature positioning, and claims that need
|
|
207
|
-
challenge before they become project memory.
|
|
208
|
-
|
|
209
|
-
The CLI creates a provider-neutral `PanelPlan` and returns a planned
|
|
210
|
-
`PanelResult`. When native subagents are unavailable, LongTable uses a stable
|
|
211
|
-
sequential fallback prompt. That keeps the same research semantics available in
|
|
212
|
-
Codex and Claude Code without making either provider's native question or agent
|
|
213
|
-
tool the source of truth.
|
|
214
|
-
|
|
215
|
-
Inside a LongTable project workspace, panel planning also appends an
|
|
216
|
-
`InvocationRecord` to `.longtable/state.json`, creates a pending follow-up
|
|
217
|
-
`QuestionRecord`, and refreshes `CURRENT.md`.
|
|
218
|
-
|
|
219
|
-
Panel output should remain inspectable. A panel or debate result is expected to
|
|
220
|
-
show the consulted roles, each role's main claim or objection, the disagreement
|
|
221
|
-
map, decision options, a defensible recommendation when one exists, and the
|
|
222
|
-
exact researcher-facing question before a high-stakes decision is treated as
|
|
223
|
-
settled.
|
|
224
|
-
|
|
225
|
-
Default panel roles include:
|
|
226
|
-
|
|
227
|
-
- `reviewer`
|
|
228
|
-
- `methods_critic`
|
|
229
|
-
- `measurement_auditor`
|
|
230
|
-
- `theory_critic`
|
|
231
|
-
|
|
232
|
-
Use `--role` to constrain the panel when the research problem is already clear.
|
|
233
|
-
|
|
234
|
-
## Sentinel And Agent Team
|
|
235
|
-
|
|
236
|
-
`longtable sentinel` is an explicit gap/tacit check for prompts that may contain
|
|
237
|
-
measurement, theory, method, evidence, authorship, or tacit-assumption risks.
|
|
238
|
-
Use `--record` inside a LongTable workspace to store the finding as an
|
|
239
|
-
unconfirmed inferred hypothesis.
|
|
240
|
-
|
|
241
|
-
The Codex hook stays quiet for advisory-only questions. Required hook context is
|
|
242
|
-
reserved for durable Researcher Checkpoints, especially when a prompt would
|
|
243
|
-
change the research question/scope, theory frame, measurement/coding standard,
|
|
244
|
-
method design, or analysis strategy. Low-risk reversible work should proceed
|
|
245
|
-
with visible assumptions rather than a noisy hook interruption.
|
|
246
|
-
|
|
247
|
-
`longtable team` creates a file-backed agent-team review under
|
|
248
|
-
`.longtable/team/<id>/`: independent review, cross-review, and
|
|
249
|
-
synthesis/checkpoint. Use it when roles should inspect each other's concerns
|
|
250
|
-
before LongTable proposes a researcher decision.
|
|
251
|
-
|
|
252
|
-
`longtable team --debate` creates a fixed five-round debate record under
|
|
253
|
-
`.longtable/team/<id>/`: independent review, cross-review, rebuttal,
|
|
254
|
-
convergence, and synthesis/checkpoint. The file-backed artifact directory is
|
|
255
|
-
the source of truth.
|
|
256
|
-
|
|
257
|
-
See `docs/AGENT-TEAM-README.md` in the repository for a user-facing guide to
|
|
258
|
-
panel, team, and debate surfaces.
|
|
259
|
-
|
|
260
|
-
## Evidence And Search Direction
|
|
261
|
-
|
|
262
|
-
LongTable should not behave like a generic web scraper. Research search should
|
|
263
|
-
start from scholarly routes when the user needs literature discovery, citation
|
|
264
|
-
verification, publication metadata, or evidence-backed research decisions.
|
|
265
|
-
|
|
266
|
-
`longtable search` routes research queries through arXiv, Crossref, OpenAlex,
|
|
267
|
-
Semantic Scholar, PubMed/NCBI, ERIC, DOAJ, and Unpaywall, then normalizes,
|
|
268
|
-
deduplicates, ranks, and labels results as evidence cards. Some sources work
|
|
269
|
-
without keys, some require a contact email, and some need API keys for reliable
|
|
270
|
-
use.
|
|
271
|
-
|
|
272
|
-
Scholarly access is configured separately through `longtable access setup`.
|
|
273
|
-
It records readiness for metadata, OA full text, institutional access,
|
|
274
|
-
publisher API/TDM credentials, and manual PDFs without storing secrets.
|
|
275
|
-
Publisher probes cover Elsevier, Springer Nature, Wiley, and Taylor & Francis.
|
|
276
|
-
|
|
277
|
-
Citation support should be checked explicitly. A reference can be useful as
|
|
278
|
-
background while still failing to support the specific claim attached to it.
|
|
279
|
-
|
|
280
|
-
```bash
|
|
281
|
-
longtable access setup
|
|
282
|
-
longtable access probe --doi "10.1016/example" --publisher elsevier
|
|
283
|
-
longtable search --query "trust calibration measurement" --intent measurement
|
|
284
|
-
longtable search --query "trust calibration measurement" --publisher-access --json
|
|
285
|
-
longtable search --query "trust calibration citation support" --intent citation --record
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
See:
|
|
289
|
-
|
|
290
|
-
- [Research Search](https://github.com/HosungYou/LongTable/blob/main/docs/RESEARCH-SEARCH.md)
|
|
291
|
-
- [Evidence Policy](https://github.com/HosungYou/LongTable/blob/main/docs/EVIDENCE-POLICY.md)
|
|
292
|
-
- [LongTable Command Surface](https://github.com/HosungYou/LongTable/blob/main/docs/LONGTABLE-COMMAND-SURFACE.md)
|
|
79
|
+
`longtable start` remains available for scripted workspace creation with
|
|
80
|
+
`--no-interview --json`, but it is not the primary research-start surface.
|
|
293
81
|
|
|
294
|
-
##
|
|
82
|
+
## Development
|
|
295
83
|
|
|
296
84
|
```bash
|
|
297
|
-
npm
|
|
298
|
-
npm run typecheck
|
|
299
|
-
npm run build
|
|
85
|
+
npm run build --workspace @longtable/cli
|
|
86
|
+
npm run typecheck --workspace @longtable/cli
|
|
300
87
|
```
|
package/dist/cli.js
CHANGED
|
@@ -112,16 +112,16 @@ function renderBrandBanner(title, subtitle) {
|
|
|
112
112
|
}
|
|
113
113
|
function renderInterviewLaunchSteps(provider) {
|
|
114
114
|
const command = provider === "codex" ? "codex" : "claude";
|
|
115
|
-
return renderSectionCard("LongTable
|
|
115
|
+
return renderSectionCard("LongTable Start", [
|
|
116
116
|
"Setup is permission and runtime calibration, not the research interview.",
|
|
117
117
|
"The first research conversation now happens inside the provider so the model can listen, reflect, and ask one natural-language follow-up at a time.",
|
|
118
118
|
"",
|
|
119
119
|
"Next:",
|
|
120
120
|
"1. cd \"<research-folder>\"",
|
|
121
121
|
`2. run \`${command}\``,
|
|
122
|
-
"3. invoke `$longtable-
|
|
122
|
+
"3. invoke `$longtable-start`",
|
|
123
123
|
"",
|
|
124
|
-
"The interview will create or resume `.longtable/`, may store a short First Research Shape handle, and uses option UI for the final Research Specification confirmation."
|
|
124
|
+
"The start interview will create or resume `.longtable/`, may store a short First Research Shape handle, and uses option UI for the final Research Specification confirmation."
|
|
125
125
|
]);
|
|
126
126
|
}
|
|
127
127
|
function renderProgressBar(current, total) {
|
|
@@ -133,7 +133,7 @@ function usage() {
|
|
|
133
133
|
return [
|
|
134
134
|
"Usage:",
|
|
135
135
|
" Run `longtable ...` in your terminal, not inside the Codex chat box.",
|
|
136
|
-
" LongTable research starts inside Codex or Claude with `$longtable-
|
|
136
|
+
" LongTable research starts inside Codex or Claude with `$longtable-start` after setup.",
|
|
137
137
|
"",
|
|
138
138
|
" longtable setup [--provider codex|claude] [--install-scope user|project|none] [--surfaces cli_only|skills|skills_mcp|skills_mcp_sentinel] [--intervention advisory|balanced|strong] [--checkpoint-ui off|interactive|strong] [--workspace create|later] [--project-dir <path>] [--json] [--dir <path>] [--skills-dir <path>] [--runtime-path <file>] [--setup-path <file>]",
|
|
139
139
|
" longtable init [deprecated alias for setup; full legacy flags still supported for automation]",
|
|
@@ -178,7 +178,7 @@ function usage() {
|
|
|
178
178
|
"Examples:",
|
|
179
179
|
" longtable setup --provider codex",
|
|
180
180
|
" cd \"<research-folder>\" && codex",
|
|
181
|
-
" $longtable-
|
|
181
|
+
" $longtable-start",
|
|
182
182
|
" longtable start --no-interview --path ~/Research/My-Project --name \"AI Adoption Meta-Analysis\" --goal \"Narrow the review question\"",
|
|
183
183
|
" longtable doctor",
|
|
184
184
|
" longtable roles",
|
|
@@ -525,12 +525,12 @@ function buildPermissionSetupChoices() {
|
|
|
525
525
|
{
|
|
526
526
|
id: "create",
|
|
527
527
|
label: "Show interview launch steps",
|
|
528
|
-
description: "Why: research should start inside the provider. What you get: setup finishes with Codex/Claude + $longtable-
|
|
528
|
+
description: "Why: research should start inside the provider. What you get: setup finishes with Codex/Claude + $longtable-start steps. Tradeoff: workspace creation waits for the in-provider interview."
|
|
529
529
|
},
|
|
530
530
|
{
|
|
531
531
|
id: "later",
|
|
532
532
|
label: "No, prepare runtime only",
|
|
533
|
-
description: "Why: keeps setup short. What you get: runtime support without project state. Tradeoff: no durable research memory until `$longtable-
|
|
533
|
+
description: "Why: keeps setup short. What you get: runtime support without project state. Tradeoff: no durable research memory until `$longtable-start` creates or resumes a workspace."
|
|
534
534
|
}
|
|
535
535
|
]
|
|
536
536
|
};
|
|
@@ -652,7 +652,7 @@ async function runSetup(args) {
|
|
|
652
652
|
interventionPosture: effectiveIntervention,
|
|
653
653
|
checkpointUiMode: checkpointUi,
|
|
654
654
|
workspaceCreationPreference: workspacePreference,
|
|
655
|
-
officialStartSurface: "$longtable-
|
|
655
|
+
officialStartSurface: "$longtable-start",
|
|
656
656
|
setupPosture: "permission_first",
|
|
657
657
|
teamMode: "panel"
|
|
658
658
|
};
|
|
@@ -698,9 +698,9 @@ async function runSetup(args) {
|
|
|
698
698
|
mcpInstall,
|
|
699
699
|
workspacePreference,
|
|
700
700
|
nextStep: {
|
|
701
|
-
surface: "$longtable-
|
|
701
|
+
surface: "$longtable-start",
|
|
702
702
|
command: provider === "codex" ? "codex" : "claude",
|
|
703
|
-
description: "Open the provider in the research folder and invoke `$longtable-
|
|
703
|
+
description: "Open the provider in the research folder and invoke `$longtable-start`."
|
|
704
704
|
}
|
|
705
705
|
}, null, 2));
|
|
706
706
|
return;
|
|
@@ -734,7 +734,7 @@ async function runSetup(args) {
|
|
|
734
734
|
console.log(renderInterviewLaunchSteps(provider));
|
|
735
735
|
if (workspacePreference === "create") {
|
|
736
736
|
console.log("");
|
|
737
|
-
console.log("Workspace launch requested. Open the provider in your research folder and run `$longtable-
|
|
737
|
+
console.log("Workspace launch requested. Open the provider in your research folder and run `$longtable-start`; the interview will create `.longtable/` there.");
|
|
738
738
|
}
|
|
739
739
|
}
|
|
740
740
|
function perspectiveChoices() {
|
|
@@ -2009,6 +2009,7 @@ function buildRoleAuditEntry(provider, spec) {
|
|
|
2009
2009
|
function runRoleAudit() {
|
|
2010
2010
|
const baseSkillNames = new Set([
|
|
2011
2011
|
"longtable",
|
|
2012
|
+
"longtable-start",
|
|
2012
2013
|
"longtable-interview",
|
|
2013
2014
|
"longtable-panel",
|
|
2014
2015
|
"longtable-explore",
|
|
@@ -3624,7 +3625,7 @@ async function runStart(args) {
|
|
|
3624
3625
|
"1. longtable setup --provider codex",
|
|
3625
3626
|
"2. cd \"<research-folder>\"",
|
|
3626
3627
|
"3. codex",
|
|
3627
|
-
"4. $longtable-
|
|
3628
|
+
"4. $longtable-start",
|
|
3628
3629
|
"",
|
|
3629
3630
|
"For automation, pass `--no-interview --json` with `--name`, `--path`, and `--goal`."
|
|
3630
3631
|
]));
|
|
@@ -168,15 +168,15 @@ function looksLikeExplicitInterviewPrompt(prompt) {
|
|
|
168
168
|
if (!normalized) {
|
|
169
169
|
return false;
|
|
170
170
|
}
|
|
171
|
-
if (/\$longtable-interview\b/i.test(normalized)) {
|
|
171
|
+
if (/\$longtable-(?:start|interview)\b/i.test(normalized)) {
|
|
172
172
|
return true;
|
|
173
173
|
}
|
|
174
174
|
if (looksLikeLongTableProductOrToolingPrompt(normalized)) {
|
|
175
175
|
return false;
|
|
176
176
|
}
|
|
177
|
-
return /\bLongTable\b.*\
|
|
177
|
+
return /\bLongTable\b.*\b(?:start|interview)\b/i.test(normalized)
|
|
178
178
|
|| /\bfirst research shape\b/i.test(normalized)
|
|
179
|
-
||
|
|
179
|
+
|| /롱테이블.*(?:시작|인터뷰)|LongTable.*인터뷰|First Research Shape/i.test(normalized);
|
|
180
180
|
}
|
|
181
181
|
function looksLikeResearchStateConfirmationPrompt(prompt) {
|
|
182
182
|
if (looksLikeLongTableProductOrToolingPrompt(prompt) && !looksLikeExplicitInterviewPrompt(prompt)) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { DecisionRecord, EvidenceRecord, InvocationRecord, LongTableQuestionObligation, ProviderKind, QuestionOption, QuestionCommitmentFamily, QuestionEpistemicBasis, QuestionGenerationResult, QuestionOpportunity, QuestionSurface, QuestionRecord, ResearchSpecificationChange, ResearchSpecificationPatch, ResearchSpecificationPatchSource, ResearchSpecificationRevision, ResearchState } from "@longtable/core";
|
|
1
|
+
import type { DecisionRecord, EvidenceRecord, InvocationRecord, LongTableQuestionObligation, ProviderKind, QuestionOption, QuestionCommitmentFamily, QuestionEpistemicBasis, QuestionGenerationResult, QuestionOpportunity, QuestionSurface, QuestionPromptType, QuestionRecord, ResearchSpecificationChange, ResearchSpecificationPatch, ResearchSpecificationPatchSource, ResearchSpecificationRevision, ResearchState } from "@longtable/core";
|
|
2
2
|
import type { SetupPersistedOutput } from "@longtable/setup";
|
|
3
3
|
export type ProjectDisagreementPreference = "synthesis_only" | "show_on_conflict" | "always_visible";
|
|
4
4
|
export type StartInterviewSignal = "phenomenon" | "audience" | "artifact" | "evidence" | "assumption" | "decision_risk" | "voice";
|
|
@@ -393,8 +393,11 @@ export declare function createWorkspaceQuestion(options: {
|
|
|
393
393
|
prompt: string;
|
|
394
394
|
title?: string;
|
|
395
395
|
question?: string;
|
|
396
|
+
type?: QuestionPromptType;
|
|
396
397
|
checkpointKey?: string;
|
|
397
398
|
questionOptions?: QuestionOption[];
|
|
399
|
+
allowOther?: boolean;
|
|
400
|
+
otherLabel?: string;
|
|
398
401
|
displayReason?: string;
|
|
399
402
|
provider?: ProviderKind;
|
|
400
403
|
required?: boolean;
|
|
@@ -404,10 +407,17 @@ export declare function createWorkspaceQuestion(options: {
|
|
|
404
407
|
question: QuestionRecord;
|
|
405
408
|
state: ResearchState;
|
|
406
409
|
}>;
|
|
410
|
+
type WorkspaceQuestionAnswerInput = string | string[] | {
|
|
411
|
+
answer?: string | string[];
|
|
412
|
+
selectedValue?: string;
|
|
413
|
+
selectedValues?: string[];
|
|
414
|
+
otherText?: string;
|
|
415
|
+
rationale?: string;
|
|
416
|
+
};
|
|
407
417
|
export declare function answerWorkspaceQuestion(options: {
|
|
408
418
|
context: LongTableProjectContext;
|
|
409
419
|
questionId?: string;
|
|
410
|
-
answer:
|
|
420
|
+
answer: WorkspaceQuestionAnswerInput;
|
|
411
421
|
rationale?: string;
|
|
412
422
|
provider?: "codex" | "claude";
|
|
413
423
|
surface?: QuestionSurface;
|
package/dist/project-session.js
CHANGED
|
@@ -339,7 +339,7 @@ function buildCurrentGuide(project, session, recentInvocations = [], pendingQues
|
|
|
339
339
|
"",
|
|
340
340
|
"## 빠른 시작",
|
|
341
341
|
"- 이 디렉토리에서 `codex`를 엽니다.",
|
|
342
|
-
`- 첫 메시지는 보통 \`${session.firstResearchShape ? suggestedPrompt : "$longtable-
|
|
342
|
+
`- 첫 메시지는 보통 \`${session.firstResearchShape ? suggestedPrompt : "$longtable-start"}\` 정도면 충분합니다.`,
|
|
343
343
|
"",
|
|
344
344
|
"## 증거 규칙",
|
|
345
345
|
"- 외부 사실이나 현재 정보는 source를 붙이거나 inference로 낮춥니다."
|
|
@@ -416,7 +416,7 @@ function buildCurrentGuide(project, session, recentInvocations = [], pendingQues
|
|
|
416
416
|
"",
|
|
417
417
|
"## Quick Start",
|
|
418
418
|
"- Open `codex` in this directory.",
|
|
419
|
-
`- A good first message is usually \`${session.firstResearchShape ? suggestedPrompt : "$longtable-
|
|
419
|
+
`- A good first message is usually \`${session.firstResearchShape ? suggestedPrompt : "$longtable-start"}\`.`,
|
|
420
420
|
"",
|
|
421
421
|
"## Evidence Rule",
|
|
422
422
|
"- External or current claims should carry a source link or be labeled as inference."
|
|
@@ -878,7 +878,8 @@ function buildProjectAgentsMd(project, session) {
|
|
|
878
878
|
"- Treat `AGENTS.md` as runtime guidance, not as the researcher-facing resume artifact.",
|
|
879
879
|
"",
|
|
880
880
|
"## Invocation Rules",
|
|
881
|
-
"- If the user message starts with `$longtable-
|
|
881
|
+
"- If the user message starts with `$longtable-start`, run the LongTable research-start flow before generic research advice.",
|
|
882
|
+
"- If the user message starts with `$longtable-interview`, use post-start structured interview only when a usable Research Specification exists; otherwise route to `$longtable-start`.",
|
|
882
883
|
"- If the user message starts with `lt `, `longtable `, `long table `, or `롱테이블 ` followed by a directive and `:`, treat it as an explicit LongTable invocation.",
|
|
883
884
|
"- Supported explicit directives are: interview, explore, review, critique, draft, commit, panel, status, editor, reviewer, methods, theory, measurement, ethics, voice, venue.",
|
|
884
885
|
"- For explicit LongTable invocations, do not begin by scanning the workspace. Use the current session files first and answer as LongTable immediately.",
|
|
@@ -886,13 +887,14 @@ function buildProjectAgentsMd(project, session) {
|
|
|
886
887
|
"",
|
|
887
888
|
"## Research Behavior",
|
|
888
889
|
"- Begin exploratory work with clarifying or tension questions before recommending a direction.",
|
|
889
|
-
"- For `$longtable-
|
|
890
|
-
"- Do not summarize `$longtable-
|
|
890
|
+
"- For `$longtable-start`, ask one natural-language question at a time, reflect with `LongTable hears: ...`, record turns when MCP is available, and avoid early reader/reviewer or theory/method/measurement classification.",
|
|
891
|
+
"- Do not summarize `$longtable-start` because a fixed number of turns has passed; wait for content-based readiness around research object, focal uncertainty, boundary, evidence/material, protected decision, and next action.",
|
|
891
892
|
"- First Research Shape is a short handle/resume index, not the default closure point.",
|
|
892
893
|
"- After the First Research Shape, create a Research Specification when the interview has enough detail to preserve scope, construct ontology, theory framing, coding rules, method options, evidence/access requirements, epistemic alignment, protected decisions, open questions, and next actions.",
|
|
893
894
|
"- If a confirmed First Research Shape exists without a Research Specification, continue directly into the next Research Specification question instead of asking shape-level continue/revise/restart questions.",
|
|
894
895
|
"- If the researcher chooses `ask_one_more` or `revise_section` at Research Specification confirmation, answer that gap and return to the Research Specification Preview before ending the interview.",
|
|
895
|
-
"- Do not let unrelated pending Researcher Checkpoints interrupt `$longtable-
|
|
896
|
+
"- Do not let unrelated pending Researcher Checkpoints interrupt `$longtable-start`; mention them only as separate unresolved checkpoints unless the researcher is confirming, saving, or recording a research decision.",
|
|
897
|
+
"- For `$longtable-interview` after a Research Specification exists, use option-first follow-up choices with Other/free-text or one open-question escape hatch.",
|
|
896
898
|
"- Use structured options at the final Research Specification confirmation, at explicit short-handle stop points, or at true checkpoint boundaries.",
|
|
897
899
|
"- If you foreground role perspectives, disclose them with `LongTable consulted: ...`.",
|
|
898
900
|
"- Keep one accountable synthesis, but do not hide meaningful disagreement.",
|
|
@@ -1195,7 +1197,7 @@ export async function beginLongTableInterview(options) {
|
|
|
1195
1197
|
turns: [],
|
|
1196
1198
|
qualityNotes: [],
|
|
1197
1199
|
rationale: [
|
|
1198
|
-
"Official LongTable research start surface is provider-native `$longtable-
|
|
1200
|
+
"Official LongTable research start surface is provider-native `$longtable-start`, not the CLI start questionnaire.",
|
|
1199
1201
|
"The hook keeps early research ambiguity open until a first research handle can be summarized."
|
|
1200
1202
|
]
|
|
1201
1203
|
};
|
|
@@ -1203,7 +1205,7 @@ export async function beginLongTableInterview(options) {
|
|
|
1203
1205
|
updated.workingState = {
|
|
1204
1206
|
...updated.workingState,
|
|
1205
1207
|
activeInterviewHookId: hook.id,
|
|
1206
|
-
interviewSurface: "$longtable-
|
|
1208
|
+
interviewSurface: "$longtable-start",
|
|
1207
1209
|
...(options.openingQuestion ? { interviewOpeningQuestion: options.openingQuestion } : {}),
|
|
1208
1210
|
...(options.seedAnswer ? { interviewSeedAnswer: options.seedAnswer } : {})
|
|
1209
1211
|
};
|
|
@@ -1335,7 +1337,7 @@ export async function summarizeLongTableInterview(options) {
|
|
|
1335
1337
|
updated.narrativeTraces.push({
|
|
1336
1338
|
id: createId("narrative_trace"),
|
|
1337
1339
|
timestamp,
|
|
1338
|
-
source: "$longtable-
|
|
1340
|
+
source: "$longtable-start",
|
|
1339
1341
|
traceType: "judgment",
|
|
1340
1342
|
summary: `First Research Shape: ${shape.handle}.`,
|
|
1341
1343
|
visibility: "explicit",
|
|
@@ -1457,7 +1459,7 @@ export async function summarizeLongTableResearchSpecification(options) {
|
|
|
1457
1459
|
updated.narrativeTraces.push({
|
|
1458
1460
|
id: createId("narrative_trace"),
|
|
1459
1461
|
timestamp,
|
|
1460
|
-
source: "$longtable-
|
|
1462
|
+
source: "$longtable-start",
|
|
1461
1463
|
traceType: "judgment",
|
|
1462
1464
|
summary: `Research Specification draft: ${specification.title}.`,
|
|
1463
1465
|
visibility: "explicit",
|
|
@@ -2397,6 +2399,7 @@ export async function createWorkspaceQuestion(options) {
|
|
|
2397
2399
|
studyContract: state.studyContract
|
|
2398
2400
|
});
|
|
2399
2401
|
const checkpointKey = options.checkpointKey ?? trigger.signal.checkpointKey;
|
|
2402
|
+
const promptType = options.type ?? "single_choice";
|
|
2400
2403
|
const createdAt = nowIso();
|
|
2401
2404
|
const title = options.title ?? questionTitleForCheckpoint(trigger.family, checkpointKey);
|
|
2402
2405
|
const questionText = options.question ?? questionTextForCheckpoint(trigger.family, options.prompt, checkpointKey);
|
|
@@ -2427,10 +2430,10 @@ export async function createWorkspaceQuestion(options) {
|
|
|
2427
2430
|
checkpointKey,
|
|
2428
2431
|
title,
|
|
2429
2432
|
question: questionText,
|
|
2430
|
-
type:
|
|
2433
|
+
type: promptType,
|
|
2431
2434
|
options: options.questionOptions ?? optionsForCheckpointTrigger(trigger.family, checkpointKey),
|
|
2432
|
-
allowOther:
|
|
2433
|
-
otherLabel: "Other decision",
|
|
2435
|
+
allowOther: options.allowOther ?? promptType !== "free_text",
|
|
2436
|
+
otherLabel: options.otherLabel ?? "Other decision",
|
|
2434
2437
|
required: options.required ?? trigger.requiresQuestionBeforeClosure,
|
|
2435
2438
|
source: "checkpoint",
|
|
2436
2439
|
displayReason: options.displayReason ?? trigger.rationale[0],
|
|
@@ -2486,53 +2489,159 @@ function splitAnswerAndRationale(rawAnswer) {
|
|
|
2486
2489
|
...(rationale ? { rationale } : {})
|
|
2487
2490
|
};
|
|
2488
2491
|
}
|
|
2489
|
-
function
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
if (
|
|
2492
|
+
function uniqueStrings(values) {
|
|
2493
|
+
return [...new Set(values.map((value) => value.trim()).filter(Boolean))];
|
|
2494
|
+
}
|
|
2495
|
+
function answerInputParts(input) {
|
|
2496
|
+
if (typeof input === "string") {
|
|
2497
|
+
return { values: [input], rawText: input };
|
|
2498
|
+
}
|
|
2499
|
+
if (Array.isArray(input)) {
|
|
2500
|
+
return { values: input };
|
|
2501
|
+
}
|
|
2502
|
+
let values = input.selectedValues ?? [];
|
|
2503
|
+
if (values.length === 0 && input.selectedValue) {
|
|
2504
|
+
values = [input.selectedValue];
|
|
2505
|
+
}
|
|
2506
|
+
if (values.length === 0 && Array.isArray(input.answer)) {
|
|
2507
|
+
values = input.answer;
|
|
2508
|
+
}
|
|
2509
|
+
if (values.length === 0 && typeof input.answer === "string") {
|
|
2510
|
+
values = [input.answer];
|
|
2511
|
+
}
|
|
2512
|
+
const otherText = input.otherText?.trim();
|
|
2513
|
+
const rationale = input.rationale?.trim();
|
|
2514
|
+
return {
|
|
2515
|
+
values,
|
|
2516
|
+
...(otherText ? { otherText } : {}),
|
|
2517
|
+
...(rationale ? { inlineRationale: rationale } : {})
|
|
2518
|
+
};
|
|
2519
|
+
}
|
|
2520
|
+
function splitSelectionTokens(selection, type) {
|
|
2521
|
+
if (type !== "multi_choice") {
|
|
2522
|
+
return [selection];
|
|
2523
|
+
}
|
|
2524
|
+
return selection.split(/[;,]/).map((token) => token.trim()).filter(Boolean);
|
|
2525
|
+
}
|
|
2526
|
+
function normalizeFreeTextAnswer(input) {
|
|
2527
|
+
const parts = answerInputParts(input);
|
|
2528
|
+
const selectedText = parts.values.join("\n").trim();
|
|
2529
|
+
const text = parts.rawText ?? (selectedText || parts.otherText || "");
|
|
2530
|
+
const trimmed = text.trim();
|
|
2531
|
+
if (!trimmed) {
|
|
2532
|
+
throw new Error("Free-text LongTable question answers cannot be empty.");
|
|
2533
|
+
}
|
|
2534
|
+
return {
|
|
2535
|
+
selectedValues: [trimmed],
|
|
2536
|
+
selectedLabels: [trimmed],
|
|
2537
|
+
otherText: trimmed,
|
|
2538
|
+
...(parts.inlineRationale ? { inlineRationale: parts.inlineRationale } : {})
|
|
2539
|
+
};
|
|
2540
|
+
}
|
|
2541
|
+
function resolveQuestionAnswerToken(question, token) {
|
|
2542
|
+
const trimmed = token.trim();
|
|
2543
|
+
if (!trimmed) {
|
|
2544
|
+
throw new Error("LongTable question answers cannot contain empty selections.");
|
|
2545
|
+
}
|
|
2546
|
+
const numeric = Number(trimmed);
|
|
2547
|
+
if (/^\d+$/.test(trimmed) && Number.isInteger(numeric)) {
|
|
2494
2548
|
const option = question.prompt.options[numeric - 1];
|
|
2495
2549
|
if (option) {
|
|
2496
2550
|
return {
|
|
2497
2551
|
selectedValue: option.value,
|
|
2498
|
-
selectedLabel: option.label
|
|
2499
|
-
...(rationale ? { inlineRationale: rationale } : {})
|
|
2552
|
+
selectedLabel: option.label
|
|
2500
2553
|
};
|
|
2501
2554
|
}
|
|
2502
2555
|
if (question.prompt.allowOther && numeric === question.prompt.options.length + 1) {
|
|
2503
2556
|
return {
|
|
2504
2557
|
selectedValue: "other",
|
|
2505
|
-
selectedLabel: question.prompt.otherLabel ?? "Other"
|
|
2506
|
-
...(rationale ? { inlineRationale: rationale } : {})
|
|
2558
|
+
selectedLabel: question.prompt.otherLabel ?? "Other"
|
|
2507
2559
|
};
|
|
2508
2560
|
}
|
|
2509
|
-
throw new Error(`Answer ${
|
|
2561
|
+
throw new Error(`Answer ${trimmed} is outside the available LongTable question options.`);
|
|
2510
2562
|
}
|
|
2511
|
-
const normalizedSelection = normalizeAnswerToken(
|
|
2563
|
+
const normalizedSelection = normalizeAnswerToken(trimmed);
|
|
2512
2564
|
const option = question.prompt.options.find((candidate) => optionAnswerCandidates(candidate).includes(normalizedSelection));
|
|
2513
2565
|
if (option) {
|
|
2514
2566
|
return {
|
|
2515
2567
|
selectedValue: option.value,
|
|
2516
|
-
selectedLabel: option.label
|
|
2517
|
-
...(rationale ? { inlineRationale: rationale } : {})
|
|
2568
|
+
selectedLabel: option.label
|
|
2518
2569
|
};
|
|
2519
2570
|
}
|
|
2520
2571
|
if (normalizedSelection === "other" && question.prompt.allowOther) {
|
|
2521
2572
|
return {
|
|
2522
2573
|
selectedValue: "other",
|
|
2523
|
-
selectedLabel: question.prompt.otherLabel ?? "Other"
|
|
2524
|
-
...(rationale ? { inlineRationale: rationale } : {})
|
|
2574
|
+
selectedLabel: question.prompt.otherLabel ?? "Other"
|
|
2525
2575
|
};
|
|
2526
2576
|
}
|
|
2527
2577
|
if (question.prompt.allowOther) {
|
|
2528
2578
|
return {
|
|
2529
|
-
selectedValue:
|
|
2530
|
-
selectedLabel:
|
|
2531
|
-
otherText: trimmed
|
|
2532
|
-
...(rationale ? { inlineRationale: rationale } : {})
|
|
2579
|
+
selectedValue: trimmed,
|
|
2580
|
+
selectedLabel: question.prompt.otherLabel ?? "Other",
|
|
2581
|
+
otherText: trimmed
|
|
2533
2582
|
};
|
|
2534
2583
|
}
|
|
2535
|
-
throw new Error(`Answer "${
|
|
2584
|
+
throw new Error(`Answer "${trimmed}" does not match a LongTable question option.`);
|
|
2585
|
+
}
|
|
2586
|
+
function isOtherAnswerToken(question, token) {
|
|
2587
|
+
if (!question.prompt.allowOther) {
|
|
2588
|
+
return false;
|
|
2589
|
+
}
|
|
2590
|
+
const trimmed = token.trim();
|
|
2591
|
+
const normalized = normalizeAnswerToken(trimmed);
|
|
2592
|
+
const otherLabel = normalizeAnswerToken(question.prompt.otherLabel ?? "Other");
|
|
2593
|
+
if (normalized === "other" || normalized === otherLabel) {
|
|
2594
|
+
return true;
|
|
2595
|
+
}
|
|
2596
|
+
const numeric = Number(trimmed);
|
|
2597
|
+
return /^\d+$/.test(trimmed) && Number.isInteger(numeric) && numeric === question.prompt.options.length + 1;
|
|
2598
|
+
}
|
|
2599
|
+
function normalizeQuestionAnswerSelection(question, rawAnswer) {
|
|
2600
|
+
if (question.prompt.type === "free_text") {
|
|
2601
|
+
return normalizeFreeTextAnswer(rawAnswer);
|
|
2602
|
+
}
|
|
2603
|
+
const parts = answerInputParts(rawAnswer);
|
|
2604
|
+
const parsedValues = parts.values.flatMap((value) => {
|
|
2605
|
+
if (typeof rawAnswer === "string") {
|
|
2606
|
+
const { selection } = splitAnswerAndRationale(value.trim());
|
|
2607
|
+
return splitSelectionTokens(selection, question.prompt.type);
|
|
2608
|
+
}
|
|
2609
|
+
return splitSelectionTokens(value, question.prompt.type);
|
|
2610
|
+
});
|
|
2611
|
+
const inlineRationale = typeof rawAnswer === "string"
|
|
2612
|
+
? splitAnswerAndRationale(rawAnswer.trim()).rationale
|
|
2613
|
+
: parts.inlineRationale;
|
|
2614
|
+
const hasOtherText = Boolean(parts.otherText);
|
|
2615
|
+
const hasOtherToken = parsedValues.some((value) => isOtherAnswerToken(question, value));
|
|
2616
|
+
if (hasOtherText && !hasOtherToken) {
|
|
2617
|
+
throw new Error("Other text requires selecting the LongTable question Other option.");
|
|
2618
|
+
}
|
|
2619
|
+
const selectionTokens = parts.otherText
|
|
2620
|
+
? parsedValues.filter((value) => !isOtherAnswerToken(question, value))
|
|
2621
|
+
: parsedValues;
|
|
2622
|
+
const tokens = uniqueStrings([
|
|
2623
|
+
...selectionTokens,
|
|
2624
|
+
...(parts.otherText ? [parts.otherText] : [])
|
|
2625
|
+
]);
|
|
2626
|
+
if (tokens.length === 0) {
|
|
2627
|
+
throw new Error("LongTable question answers cannot be empty.");
|
|
2628
|
+
}
|
|
2629
|
+
if (question.prompt.type !== "multi_choice" && tokens.length > 1) {
|
|
2630
|
+
throw new Error("Single-choice LongTable questions accept exactly one answer.");
|
|
2631
|
+
}
|
|
2632
|
+
const resolved = tokens.map((token) => resolveQuestionAnswerToken(question, token));
|
|
2633
|
+
const selectedValues = uniqueStrings(resolved.map((entry) => entry.selectedValue));
|
|
2634
|
+
const selectedLabels = selectedValues.map((value) => {
|
|
2635
|
+
const entry = resolved.find((candidate) => candidate.selectedValue === value);
|
|
2636
|
+
return entry?.selectedLabel ?? value;
|
|
2637
|
+
});
|
|
2638
|
+
const otherText = parts.otherText ?? resolved.map((entry) => entry.otherText).find(Boolean);
|
|
2639
|
+
return {
|
|
2640
|
+
selectedValues,
|
|
2641
|
+
selectedLabels,
|
|
2642
|
+
...(otherText ? { otherText } : {}),
|
|
2643
|
+
...(inlineRationale ? { inlineRationale } : {})
|
|
2644
|
+
};
|
|
2536
2645
|
}
|
|
2537
2646
|
export async function answerWorkspaceQuestion(options) {
|
|
2538
2647
|
const state = await loadResearchState(options.context.stateFilePath);
|
|
@@ -2546,8 +2655,8 @@ export async function answerWorkspaceQuestion(options) {
|
|
|
2546
2655
|
.join("\n");
|
|
2547
2656
|
const answer = {
|
|
2548
2657
|
promptId: question.prompt.id,
|
|
2549
|
-
selectedValues:
|
|
2550
|
-
selectedLabels:
|
|
2658
|
+
selectedValues: normalized.selectedValues,
|
|
2659
|
+
selectedLabels: normalized.selectedLabels,
|
|
2551
2660
|
...(normalized.otherText ? { otherText: normalized.otherText } : {}),
|
|
2552
2661
|
...(rationale ? { rationale } : {}),
|
|
2553
2662
|
...(options.provider ? { provider: options.provider } : {}),
|
|
@@ -2564,6 +2673,7 @@ export async function answerWorkspaceQuestion(options) {
|
|
|
2564
2673
|
...(question.commitmentFamily ? { commitmentFamily: question.commitmentFamily } : {}),
|
|
2565
2674
|
...(question.epistemicBasis ? { epistemicBasis: question.epistemicBasis } : {}),
|
|
2566
2675
|
selectedOption: answer.selectedValues[0],
|
|
2676
|
+
selectedOptions: answer.selectedValues,
|
|
2567
2677
|
...(rationale ? { rationale } : {})
|
|
2568
2678
|
};
|
|
2569
2679
|
const answeredQuestion = {
|
package/dist/prompt-aliases.js
CHANGED
|
@@ -29,7 +29,7 @@ function promptSpec() {
|
|
|
29
29
|
argumentHint: "[project context or current uncertainty]",
|
|
30
30
|
body: [
|
|
31
31
|
"You are LongTable setup guidance inside Codex.",
|
|
32
|
-
"Treat `longtable init` as deprecated. Prefer `longtable setup --provider codex` for runtime permissions, then `$longtable-
|
|
32
|
+
"Treat `longtable init` as deprecated. Prefer `longtable setup --provider codex` for runtime permissions, then `$longtable-start` inside Codex for the project interview.",
|
|
33
33
|
"Ask exactly one setup question at a time.",
|
|
34
34
|
"Use numbered choices and include a concise Why / What you get / Tradeoff for each option.",
|
|
35
35
|
"Do not move to the next question until the researcher answers the current one.",
|
|
@@ -37,10 +37,10 @@ function promptSpec() {
|
|
|
37
37
|
"Do not ask for field, career stage, experience level, authorship signal, weakest domain, or panel preference during runtime setup.",
|
|
38
38
|
"Project interview covers: the first research handle, early uncertainty, first inspectable material, and final structured confirmation.",
|
|
39
39
|
"After collecting runtime answers, summarize the proposed setup and output the exact `longtable setup --provider codex ...` command.",
|
|
40
|
-
"If the researcher is ready to create a project workspace, tell them to open Codex in the research folder and invoke `$longtable-
|
|
40
|
+
"If the researcher is ready to create a project workspace, tell them to open Codex in the research folder and invoke `$longtable-start`.",
|
|
41
41
|
"If the researcher asks you to stay inside Codex, keep the conversation in numbered form and do not prematurely close.",
|
|
42
42
|
"Frame setup as permission and intervention calibration, not a researcher profile interview.",
|
|
43
|
-
"Do not pretend setup is the full project-start interview. The project-start interview happens in `$longtable-
|
|
43
|
+
"Do not pretend setup is the full project-start interview. The project-start interview happens in `$longtable-start`.",
|
|
44
44
|
"Treat any slash-command arguments as context for why setup is being done now."
|
|
45
45
|
]
|
|
46
46
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@longtable/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.51",
|
|
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.51",
|
|
33
|
+
"@longtable/core": "0.1.51",
|
|
34
|
+
"@longtable/memory": "0.1.51",
|
|
35
|
+
"@longtable/provider-claude": "0.1.51",
|
|
36
|
+
"@longtable/provider-codex": "0.1.51",
|
|
37
|
+
"@longtable/setup": "0.1.51"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@types/node": "^22.10.1",
|