@longtable/checkpoints 0.1.9 → 0.1.10
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 +10 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/trigger-classifier.d.ts +2 -0
- package/dist/trigger-classifier.js +312 -0
- package/dist/types.d.ts +19 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -5,6 +5,16 @@ Checkpoint policy and runtime guidance engine for LongTable.
|
|
|
5
5
|
Current responsibilities:
|
|
6
6
|
|
|
7
7
|
- structural and adaptive checkpoint resolution
|
|
8
|
+
- natural-language checkpoint trigger classification
|
|
8
9
|
- runtime guidance generation by interaction mode
|
|
9
10
|
- closure-disposition rules for provider adapters
|
|
10
11
|
- question-first governance for high-ambiguity research work
|
|
12
|
+
|
|
13
|
+
Key API:
|
|
14
|
+
|
|
15
|
+
- `classifyCheckpointTrigger(prompt, options)` converts natural-language context
|
|
16
|
+
into a provider-neutral `CheckpointSignal`.
|
|
17
|
+
- `resolveCheckpointPolicy(profile, signal)` decides whether the checkpoint is
|
|
18
|
+
blocking, recommended, log-only, or inactive.
|
|
19
|
+
- `resolveRuntimeGuidance(profile, signal, policy)` generates ordering guidance
|
|
20
|
+
for provider adapters.
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
const RULES = [
|
|
2
|
+
{
|
|
3
|
+
family: "meta_decision",
|
|
4
|
+
checkpointKey: "meta_decision",
|
|
5
|
+
stage: "problem_framing",
|
|
6
|
+
mode: "commit",
|
|
7
|
+
level: "adaptive_required",
|
|
8
|
+
cues: [
|
|
9
|
+
/\brename\b/i,
|
|
10
|
+
/\bnaming\b/i,
|
|
11
|
+
/\bproduct language\b/i,
|
|
12
|
+
/\bplatform term\b/i,
|
|
13
|
+
/\breadme\b/i,
|
|
14
|
+
/\bcheckpoint policy\b/i,
|
|
15
|
+
/\bmake .*authoritative\b/i,
|
|
16
|
+
/이름|명명|리드미|체크포인트 정책|플랫폼 용어|제품 언어/
|
|
17
|
+
],
|
|
18
|
+
rationale: "Platform language and checkpoint policy shape future LongTable behavior."
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
family: "submission",
|
|
22
|
+
checkpointKey: "submission_release",
|
|
23
|
+
stage: "submission",
|
|
24
|
+
stakes: "external_submission",
|
|
25
|
+
mode: "submit",
|
|
26
|
+
level: "adaptive_required",
|
|
27
|
+
cues: [
|
|
28
|
+
/\bsubmit\b/i,
|
|
29
|
+
/\bsubmission\b/i,
|
|
30
|
+
/\bjournal\b/i,
|
|
31
|
+
/\bpublic\b/i,
|
|
32
|
+
/\brelease\b/i,
|
|
33
|
+
/\bpreregistration\b/i,
|
|
34
|
+
/\bpre[- ]?registration\b/i,
|
|
35
|
+
/\birb\b/i,
|
|
36
|
+
/투고|제출|공개|배포|출시|사전등록|심의/
|
|
37
|
+
],
|
|
38
|
+
rationale: "External-facing artifacts require explicit researcher responsibility before closure."
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
family: "commitment",
|
|
42
|
+
checkpointKey: "research_question_freeze",
|
|
43
|
+
stage: "problem_framing",
|
|
44
|
+
mode: "commit",
|
|
45
|
+
level: "adaptive_required",
|
|
46
|
+
cues: [
|
|
47
|
+
/\bresearch question\b/i,
|
|
48
|
+
/\bfreeze\b/i,
|
|
49
|
+
/\bfinali[sz]e\b/i,
|
|
50
|
+
/\bsettle\b/i,
|
|
51
|
+
/\bdecide\b/i,
|
|
52
|
+
/\bcommit\b/i,
|
|
53
|
+
/연구문제|연구 질문|확정|결정|고정|커밋/
|
|
54
|
+
],
|
|
55
|
+
rationale: "Freezing the research question converts ambiguity into a human commitment."
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
family: "commitment",
|
|
59
|
+
checkpointKey: "theory_selection",
|
|
60
|
+
stage: "theory_selection",
|
|
61
|
+
mode: "commit",
|
|
62
|
+
level: "adaptive_required",
|
|
63
|
+
cues: [
|
|
64
|
+
/\btheory\b/i,
|
|
65
|
+
/\bframework\b/i,
|
|
66
|
+
/\bconceptual\b/i,
|
|
67
|
+
/\bconstruct\b/i,
|
|
68
|
+
/이론|프레임워크|개념|구성개념/
|
|
69
|
+
],
|
|
70
|
+
rationale: "Theory and construct choices constrain the rest of the study."
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
family: "commitment",
|
|
74
|
+
checkpointKey: "method_design_commitment",
|
|
75
|
+
stage: "method_design",
|
|
76
|
+
mode: "commit",
|
|
77
|
+
level: "adaptive_required",
|
|
78
|
+
cues: [
|
|
79
|
+
/\bmethod\b/i,
|
|
80
|
+
/\bmethodology\b/i,
|
|
81
|
+
/\bstudy design\b/i,
|
|
82
|
+
/\bdesign\b/i,
|
|
83
|
+
/\bsampling\b/i,
|
|
84
|
+
/방법론|방법|연구 설계|표본|샘플링/
|
|
85
|
+
],
|
|
86
|
+
rationale: "Method commitments can silently decide what claims become defensible."
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
family: "commitment",
|
|
90
|
+
checkpointKey: "measurement_validity",
|
|
91
|
+
stage: "measurement_design",
|
|
92
|
+
mode: "commit",
|
|
93
|
+
level: "adaptive_required",
|
|
94
|
+
cues: [
|
|
95
|
+
/\bmeasure\b/i,
|
|
96
|
+
/\bmeasurement\b/i,
|
|
97
|
+
/\bscale\b/i,
|
|
98
|
+
/\bsurvey\b/i,
|
|
99
|
+
/\binstrument\b/i,
|
|
100
|
+
/\bvalidity\b/i,
|
|
101
|
+
/측정|척도|설문|도구|타당도/
|
|
102
|
+
],
|
|
103
|
+
rationale: "Measurement choices should not be settled without construct-validity judgment."
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
family: "commitment",
|
|
107
|
+
checkpointKey: "analysis_plan",
|
|
108
|
+
stage: "analysis_planning",
|
|
109
|
+
mode: "commit",
|
|
110
|
+
level: "adaptive_required",
|
|
111
|
+
cues: [
|
|
112
|
+
/\banalysis plan\b/i,
|
|
113
|
+
/\banaly[sz]e\b/i,
|
|
114
|
+
/\bmodel\b/i,
|
|
115
|
+
/\bstatistical\b/i,
|
|
116
|
+
/\bregression\b/i,
|
|
117
|
+
/\bqualitative coding\b/i,
|
|
118
|
+
/분석 계획|분석|모형|모델|통계|회귀|코딩/
|
|
119
|
+
],
|
|
120
|
+
rationale: "Analysis choices affect inference and should remain inspectable."
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
family: "evidence",
|
|
124
|
+
checkpointKey: "evidence_claim",
|
|
125
|
+
stage: "writing",
|
|
126
|
+
mode: "review",
|
|
127
|
+
level: "recommended",
|
|
128
|
+
cues: [
|
|
129
|
+
/\bcitation\b/i,
|
|
130
|
+
/\breference\b/i,
|
|
131
|
+
/\bevidence\b/i,
|
|
132
|
+
/\bsource\b/i,
|
|
133
|
+
/\bhallucination\b/i,
|
|
134
|
+
/\bclaim\b/i,
|
|
135
|
+
/인용|레퍼런스|근거|출처|환각|할루시네이션|주장/
|
|
136
|
+
],
|
|
137
|
+
rationale: "Evidence-sensitive claims need provenance before synthesis."
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
family: "authorship",
|
|
141
|
+
checkpointKey: "authorship_voice",
|
|
142
|
+
stage: "writing",
|
|
143
|
+
mode: "draft",
|
|
144
|
+
level: "recommended",
|
|
145
|
+
cues: [
|
|
146
|
+
/\bauthor voice\b/i,
|
|
147
|
+
/\bauthorship\b/i,
|
|
148
|
+
/\bmy voice\b/i,
|
|
149
|
+
/\bnarrative\b/i,
|
|
150
|
+
/저자성|내 목소리|문체|서사|나의 생각/
|
|
151
|
+
],
|
|
152
|
+
rationale: "LongTable should preserve researcher authorship rather than over-smoothing."
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
family: "exploration",
|
|
156
|
+
checkpointKey: "problem_exploration",
|
|
157
|
+
stage: "problem_framing",
|
|
158
|
+
mode: "explore",
|
|
159
|
+
level: "recommended",
|
|
160
|
+
cues: [
|
|
161
|
+
/\bexplore\b/i,
|
|
162
|
+
/\bnarrow\b/i,
|
|
163
|
+
/\bbrainstorm\b/i,
|
|
164
|
+
/\bframe\b/i,
|
|
165
|
+
/탐색|좁혀|브레인스토밍|프레이밍/
|
|
166
|
+
],
|
|
167
|
+
rationale: "Exploration should ask tension questions before recommendation."
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
family: "review",
|
|
171
|
+
checkpointKey: "research_review",
|
|
172
|
+
stage: "analysis_planning",
|
|
173
|
+
mode: "review",
|
|
174
|
+
level: "recommended",
|
|
175
|
+
cues: [
|
|
176
|
+
/\breview\b/i,
|
|
177
|
+
/\bcritique\b/i,
|
|
178
|
+
/\bcheck\b/i,
|
|
179
|
+
/\baudit\b/i,
|
|
180
|
+
/리뷰|검토|비판|체크|감사/
|
|
181
|
+
],
|
|
182
|
+
rationale: "Review requests should preserve objections and unresolved assumptions."
|
|
183
|
+
}
|
|
184
|
+
];
|
|
185
|
+
function matchCues(prompt, rule) {
|
|
186
|
+
return rule.cues
|
|
187
|
+
.filter((cue) => cue.test(prompt))
|
|
188
|
+
.map((cue) => cue.source);
|
|
189
|
+
}
|
|
190
|
+
function inferModeFromPlainCue(prompt) {
|
|
191
|
+
if (/\bsubmit\b|\bsubmission\b|\bjournal\b|\bpublic\b|투고|제출|공개/.test(prompt))
|
|
192
|
+
return "submit";
|
|
193
|
+
if (/\bcommit\b|\bdecide\b|\bfinali[sz]e\b|확정|결정|고정/.test(prompt))
|
|
194
|
+
return "commit";
|
|
195
|
+
if (/\bdraft\b|\bwrite\b|초안|작성/.test(prompt))
|
|
196
|
+
return "draft";
|
|
197
|
+
if (/\bcritique\b|비판/.test(prompt))
|
|
198
|
+
return "critique";
|
|
199
|
+
if (/\breview\b|\bcheck\b|검토|리뷰/.test(prompt))
|
|
200
|
+
return "review";
|
|
201
|
+
if (/\bexplore\b|\bnarrow\b|\bbrainstorm\b|탐색|좁혀/.test(prompt))
|
|
202
|
+
return "explore";
|
|
203
|
+
return null;
|
|
204
|
+
}
|
|
205
|
+
function inferConfidence(matchCount, level) {
|
|
206
|
+
if (level === "universal_required" || level === "adaptive_required" || matchCount >= 2) {
|
|
207
|
+
return "high";
|
|
208
|
+
}
|
|
209
|
+
if (matchCount === 1) {
|
|
210
|
+
return "medium";
|
|
211
|
+
}
|
|
212
|
+
return "low";
|
|
213
|
+
}
|
|
214
|
+
function requiresQuestion(level, mode, family) {
|
|
215
|
+
return (level === "universal_required" ||
|
|
216
|
+
level === "adaptive_required" ||
|
|
217
|
+
mode === "submit" ||
|
|
218
|
+
family === "meta_decision");
|
|
219
|
+
}
|
|
220
|
+
function pickBestRule(prompt) {
|
|
221
|
+
const candidates = RULES.map((rule) => ({ rule, matches: matchCues(prompt, rule) }))
|
|
222
|
+
.filter((candidate) => candidate.matches.length > 0)
|
|
223
|
+
.sort((a, b) => {
|
|
224
|
+
const requiredDelta = Number(requiresQuestion(b.rule.level, b.rule.mode ?? "review", b.rule.family)) -
|
|
225
|
+
Number(requiresQuestion(a.rule.level, a.rule.mode ?? "review", a.rule.family));
|
|
226
|
+
if (requiredDelta !== 0)
|
|
227
|
+
return requiredDelta;
|
|
228
|
+
const genericDelta = Number(a.rule.checkpointKey === "research_question_freeze") -
|
|
229
|
+
Number(b.rule.checkpointKey === "research_question_freeze");
|
|
230
|
+
if (genericDelta !== 0)
|
|
231
|
+
return genericDelta;
|
|
232
|
+
return b.matches.length - a.matches.length;
|
|
233
|
+
});
|
|
234
|
+
return candidates[0] ?? null;
|
|
235
|
+
}
|
|
236
|
+
function fallbackStage(mode) {
|
|
237
|
+
switch (mode) {
|
|
238
|
+
case "submit":
|
|
239
|
+
return "submission";
|
|
240
|
+
case "draft":
|
|
241
|
+
return "writing";
|
|
242
|
+
case "commit":
|
|
243
|
+
return "theory_selection";
|
|
244
|
+
case "review":
|
|
245
|
+
case "critique":
|
|
246
|
+
return "analysis_planning";
|
|
247
|
+
case "explore":
|
|
248
|
+
default:
|
|
249
|
+
return "problem_framing";
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
function fallbackStakes(mode) {
|
|
253
|
+
switch (mode) {
|
|
254
|
+
case "submit":
|
|
255
|
+
return "external_submission";
|
|
256
|
+
case "commit":
|
|
257
|
+
return "study_protocol";
|
|
258
|
+
case "draft":
|
|
259
|
+
return "internal_draft";
|
|
260
|
+
case "review":
|
|
261
|
+
case "critique":
|
|
262
|
+
case "explore":
|
|
263
|
+
default:
|
|
264
|
+
return "private_note";
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
function fallbackLevel(mode) {
|
|
268
|
+
switch (mode) {
|
|
269
|
+
case "submit":
|
|
270
|
+
return "adaptive_required";
|
|
271
|
+
case "commit":
|
|
272
|
+
return "recommended";
|
|
273
|
+
default:
|
|
274
|
+
return "recommended";
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
export function classifyCheckpointTrigger(prompt, options = {}) {
|
|
278
|
+
const normalizedPrompt = prompt.trim();
|
|
279
|
+
const best = pickBestRule(normalizedPrompt);
|
|
280
|
+
const inferredMode = inferModeFromPlainCue(normalizedPrompt);
|
|
281
|
+
const mode = options.preferredMode ?? best?.rule.mode ?? inferredMode ?? options.fallbackMode ?? "explore";
|
|
282
|
+
const stage = options.researchStage ?? best?.rule.stage ?? fallbackStage(mode);
|
|
283
|
+
const stakes = options.artifactStakes ?? best?.rule.stakes ?? fallbackStakes(mode);
|
|
284
|
+
const level = best?.rule.level ?? fallbackLevel(mode);
|
|
285
|
+
const family = best?.rule.family ?? (mode === "explore" ? "exploration" : "advisory");
|
|
286
|
+
const matchedCues = best?.matches ?? [];
|
|
287
|
+
const checkpointKey = options.checkpointKey ?? best?.rule.checkpointKey ?? `${mode}_runtime_guidance`;
|
|
288
|
+
const rationale = [
|
|
289
|
+
best?.rule.rationale ?? "No strong checkpoint cue was detected; use runtime guidance without forcing closure.",
|
|
290
|
+
...(options.unresolvedTensions && options.unresolvedTensions.length > 0
|
|
291
|
+
? ["Existing unresolved tensions increase the need to keep questions visible."]
|
|
292
|
+
: [])
|
|
293
|
+
];
|
|
294
|
+
const questionRequired = requiresQuestion(level, mode, family);
|
|
295
|
+
return {
|
|
296
|
+
signal: {
|
|
297
|
+
checkpointKey,
|
|
298
|
+
baseLevel: level,
|
|
299
|
+
mode,
|
|
300
|
+
artifactStakes: stakes,
|
|
301
|
+
researchStage: stage,
|
|
302
|
+
...(options.unresolvedTensions ? { unresolvedTensions: options.unresolvedTensions } : {}),
|
|
303
|
+
...(options.studyContract ? { studyContract: options.studyContract } : {})
|
|
304
|
+
},
|
|
305
|
+
family,
|
|
306
|
+
confidence: inferConfidence(matchedCues.length, level),
|
|
307
|
+
matchedCues,
|
|
308
|
+
requiresQuestionBeforeClosure: questionRequired,
|
|
309
|
+
advisoryOnly: !questionRequired,
|
|
310
|
+
rationale
|
|
311
|
+
};
|
|
312
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -8,6 +8,25 @@ export interface CheckpointSignal {
|
|
|
8
8
|
unresolvedTensions?: string[];
|
|
9
9
|
studyContract?: StudyContract;
|
|
10
10
|
}
|
|
11
|
+
export type CheckpointTriggerFamily = "exploration" | "review" | "commitment" | "submission" | "meta_decision" | "evidence" | "authorship" | "advisory";
|
|
12
|
+
export interface CheckpointTriggerClassification {
|
|
13
|
+
signal: CheckpointSignal;
|
|
14
|
+
family: CheckpointTriggerFamily;
|
|
15
|
+
confidence: "low" | "medium" | "high";
|
|
16
|
+
matchedCues: string[];
|
|
17
|
+
requiresQuestionBeforeClosure: boolean;
|
|
18
|
+
advisoryOnly: boolean;
|
|
19
|
+
rationale: string[];
|
|
20
|
+
}
|
|
21
|
+
export interface CheckpointTriggerClassificationOptions {
|
|
22
|
+
preferredMode?: InteractionMode;
|
|
23
|
+
fallbackMode?: InteractionMode;
|
|
24
|
+
researchStage?: ResearchStage;
|
|
25
|
+
artifactStakes?: ArtifactStakes;
|
|
26
|
+
checkpointKey?: string;
|
|
27
|
+
unresolvedTensions?: string[];
|
|
28
|
+
studyContract?: StudyContract;
|
|
29
|
+
}
|
|
11
30
|
export interface ResolvedCheckpointPolicy {
|
|
12
31
|
checkpointKey: string;
|
|
13
32
|
level: CheckpointLevel;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@longtable/checkpoints",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.10",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Checkpoint policy engine for LongTable",
|
|
6
6
|
"type": "module",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@longtable/core": "0.1.
|
|
24
|
+
"@longtable/core": "0.1.10"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"typescript": "^5.6.0"
|