throughline 0.3.24 → 0.3.25
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/.claude/commands/tl-trim.md +42 -0
- package/.codex-sidecar.yml +62 -0
- package/CHANGELOG.md +583 -0
- package/README.ja.md +42 -5
- package/README.md +383 -23
- package/bin/throughline.mjs +168 -4
- package/codex/skills/throughline/SKILL.md +157 -0
- package/codex/skills/throughline/agents/openai.yaml +7 -0
- package/docs/INHERITANCE_ON_CLEAR_ONLY.md +146 -0
- package/docs/L1_L2_L3_REDESIGN.md +415 -0
- package/docs/PUBLIC_RELEASE_PLAN.md +184 -0
- package/docs/THROUGHLINE_CODEX_DUAL_SUPPORT.md +249 -0
- package/docs/THROUGHLINE_CODEX_FIRST_ROADMAP.md +555 -0
- package/docs/THROUGHLINE_CODEX_MONITOR_IMPLEMENTATION_PLAN.md +220 -0
- package/docs/THROUGHLINE_CODEX_TRIM_IMPLEMENTATION_PLAN.md +528 -0
- package/docs/THROUGHLINE_CODEX_TRIM_ROLLBACK_FIX_PLAN.md +672 -0
- package/docs/archive/CONCEPT.md +476 -0
- package/docs/archive/EXPERIMENT.md +371 -0
- package/docs/archive/README.md +22 -0
- package/docs/archive/SESSION_LINKING_DESIGN.md +231 -0
- package/docs/archive/THROUGHLINE_NEXT_STEPS.md +134 -0
- package/docs/throughline-codex-trim-rollback-incident-report.md +306 -0
- package/docs/throughline-handoff-context.example.json +57 -0
- package/docs/throughline-rollback-context-trim-insight.md +455 -0
- package/package.json +6 -2
- package/src/cli/codex-capture.mjs +95 -0
- package/src/cli/codex-handoff-model-smoke.mjs +292 -0
- package/src/cli/codex-handoff-model-smoke.test.mjs +262 -0
- package/src/cli/codex-handoff-smoke.mjs +163 -0
- package/src/cli/codex-handoff-smoke.test.mjs +149 -0
- package/src/cli/codex-handoff-start.mjs +291 -0
- package/src/cli/codex-handoff-start.test.mjs +194 -0
- package/src/cli/codex-hook.mjs +276 -0
- package/src/cli/codex-hook.test.mjs +293 -0
- package/src/cli/codex-host-primitive-audit.mjs +110 -0
- package/src/cli/codex-host-primitive-audit.test.mjs +75 -0
- package/src/cli/codex-restore-smoke.mjs +357 -0
- package/src/cli/codex-restore-source-audit.mjs +304 -0
- package/src/cli/codex-resume.mjs +138 -0
- package/src/cli/codex-rollback-model-visible-smoke.mjs +373 -0
- package/src/cli/codex-rollback-model-visible-smoke.test.mjs +255 -0
- package/src/cli/codex-sidecar-diagnostics.mjs +48 -0
- package/src/cli/codex-sidecar-dry-run.mjs +85 -0
- package/src/cli/codex-summarize.mjs +224 -0
- package/src/cli/codex-threads.mjs +89 -0
- package/src/cli/codex-visibility-smoke.mjs +196 -0
- package/src/cli/codex-vscode-restore-smoke.mjs +226 -0
- package/src/cli/codex-vscode-rollback-smoke.mjs +114 -0
- package/src/cli/doctor.mjs +503 -1
- package/src/cli/doctor.test.mjs +542 -3
- package/src/cli/handoff-preview.mjs +78 -0
- package/src/cli/help.test.mjs +64 -0
- package/src/cli/install.mjs +227 -4
- package/src/cli/install.test.mjs +207 -4
- package/src/cli/trim.mjs +564 -0
- package/src/codex-app-server.mjs +1816 -0
- package/src/codex-app-server.test.mjs +512 -0
- package/src/codex-auto-refresh.mjs +194 -0
- package/src/codex-auto-refresh.test.mjs +182 -0
- package/src/codex-capture.mjs +235 -0
- package/src/codex-capture.test.mjs +393 -0
- package/src/codex-handoff-model-smoke.mjs +114 -0
- package/src/codex-handoff-model-smoke.test.mjs +89 -0
- package/src/codex-handoff-smoke.mjs +124 -0
- package/src/codex-handoff-smoke.test.mjs +103 -0
- package/src/codex-handoff.mjs +331 -0
- package/src/codex-handoff.test.mjs +220 -0
- package/src/codex-host-primitive-audit.mjs +374 -0
- package/src/codex-host-primitive-audit.test.mjs +208 -0
- package/src/codex-restore-smoke.test.mjs +639 -0
- package/src/codex-restore-source-audit.mjs +1348 -0
- package/src/codex-restore-source-audit.test.mjs +623 -0
- package/src/codex-resume.test.mjs +242 -0
- package/src/codex-rollout-memory.mjs +711 -0
- package/src/codex-rollout-memory.test.mjs +610 -0
- package/src/codex-sidecar-cli.test.mjs +75 -0
- package/src/codex-sidecar.mjs +246 -0
- package/src/codex-sidecar.test.mjs +172 -0
- package/src/codex-summarize.test.mjs +143 -0
- package/src/codex-thread-identity.mjs +23 -0
- package/src/codex-thread-index.mjs +173 -0
- package/src/codex-thread-index.test.mjs +164 -0
- package/src/codex-usage.mjs +110 -0
- package/src/codex-usage.test.mjs +140 -0
- package/src/codex-visibility-smoke.test.mjs +222 -0
- package/src/codex-vscode-restore-smoke.mjs +206 -0
- package/src/codex-vscode-restore-smoke.test.mjs +325 -0
- package/src/codex-vscode-rollback-smoke.mjs +90 -0
- package/src/codex-vscode-rollback-smoke.test.mjs +290 -0
- package/src/db-schema.test.mjs +97 -0
- package/src/haiku-summarizer.mjs +267 -26
- package/src/haiku-summarizer.test.mjs +282 -0
- package/src/handoff-preview.test.mjs +108 -0
- package/src/handoff-record.mjs +294 -0
- package/src/handoff-record.test.mjs +226 -0
- package/src/hook-entrypoints.test.mjs +326 -0
- package/src/package-files.test.mjs +19 -0
- package/src/prompt-submit.mjs +9 -6
- package/src/resume-context.mjs +44 -140
- package/src/resume-context.test.mjs +172 -0
- package/src/session-start.mjs +8 -5
- package/src/state-file.mjs +50 -6
- package/src/state-file.test.mjs +50 -0
- package/src/token-monitor.mjs +14 -10
- package/src/token-monitor.test.mjs +27 -0
- package/src/trim-cli.test.mjs +1584 -0
- package/src/trim-model.mjs +584 -0
- package/src/trim-model.test.mjs +568 -0
- package/src/turn-processor.mjs +17 -10
- package/src/vscode-task.mjs +33 -10
- package/src/vscode-task.test.mjs +19 -9
package/src/vscode-task.mjs
CHANGED
|
@@ -239,7 +239,12 @@ export function buildSetupNotice(action) {
|
|
|
239
239
|
return null;
|
|
240
240
|
}
|
|
241
241
|
|
|
242
|
-
function
|
|
242
|
+
function shouldEmitNotices(env) {
|
|
243
|
+
return env.THROUGHLINE_SUPPRESS_VSCODE_NOTICES !== '1';
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function emitSetupNotice(action, env) {
|
|
247
|
+
if (!shouldEmitNotices(env)) return;
|
|
243
248
|
const text = buildSetupNotice(action);
|
|
244
249
|
if (text) process.stdout.write(text);
|
|
245
250
|
}
|
|
@@ -279,9 +284,18 @@ export function shouldRecommendGitignore(cwd) {
|
|
|
279
284
|
return true;
|
|
280
285
|
}
|
|
281
286
|
|
|
282
|
-
function emitGitignoreRecommendationOnce(vscodeDir) {
|
|
287
|
+
function emitGitignoreRecommendationOnce(vscodeDir, env) {
|
|
283
288
|
const markerPath = join(vscodeDir, GITIGNORE_MARKER_FILENAME);
|
|
284
289
|
if (existsSync(markerPath)) return;
|
|
290
|
+
if (!shouldEmitNotices(env)) {
|
|
291
|
+
try {
|
|
292
|
+
writeFileSync(markerPath, `${new Date().toISOString()}\n`);
|
|
293
|
+
} catch (err) {
|
|
294
|
+
const msg = err instanceof Error ? err.message : 'unknown';
|
|
295
|
+
process.stderr.write(`[throughline] failed to write gitignore marker: ${msg}\n`);
|
|
296
|
+
}
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
285
299
|
process.stdout.write(
|
|
286
300
|
'<system-reminder>\n' +
|
|
287
301
|
'Throughline ヒント: .vscode/tasks.json には現環境の絶対パス (node 実行ファイル / throughline.mjs)\n' +
|
|
@@ -305,9 +319,18 @@ function emitGitignoreRecommendationOnce(vscodeDir) {
|
|
|
305
319
|
}
|
|
306
320
|
}
|
|
307
321
|
|
|
308
|
-
function emitJsoncGuidanceOnce(vscodeDir) {
|
|
322
|
+
function emitJsoncGuidanceOnce(vscodeDir, env) {
|
|
309
323
|
const markerPath = join(vscodeDir, JSONC_MARKER_FILENAME);
|
|
310
324
|
if (existsSync(markerPath)) return;
|
|
325
|
+
if (!shouldEmitNotices(env)) {
|
|
326
|
+
try {
|
|
327
|
+
writeFileSync(markerPath, `${new Date().toISOString()}\n`);
|
|
328
|
+
} catch (err) {
|
|
329
|
+
const msg = err instanceof Error ? err.message : 'unknown';
|
|
330
|
+
process.stderr.write(`[throughline] failed to write JSONC marker: ${msg}\n`);
|
|
331
|
+
}
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
311
334
|
process.stderr.write(
|
|
312
335
|
`[throughline] .vscode/tasks.json contains JSONC features (comments or trailing commas). ` +
|
|
313
336
|
`Auto-edit is unsafe on this file — add the Throughline Monitor task manually. ` +
|
|
@@ -363,15 +386,15 @@ export function ensureMonitorTaskFile(opts = {}) {
|
|
|
363
386
|
if (!existsSync(vscodeDir)) mkdirSync(vscodeDir, { recursive: true });
|
|
364
387
|
const obj = { version: '2.0.0', tasks: [buildMonitorTask(bin)] };
|
|
365
388
|
atomicWrite(tasksPath, JSON.stringify(obj, null, 2) + '\n');
|
|
366
|
-
emitSetupNotice('created');
|
|
367
|
-
if (shouldRecommendGitignore(cwd)) emitGitignoreRecommendationOnce(vscodeDir);
|
|
389
|
+
emitSetupNotice('created', env);
|
|
390
|
+
if (shouldRecommendGitignore(cwd)) emitGitignoreRecommendationOnce(vscodeDir, env);
|
|
368
391
|
return { action: 'created', path: tasksPath };
|
|
369
392
|
}
|
|
370
393
|
|
|
371
394
|
const text = readFileSync(tasksPath, 'utf8');
|
|
372
395
|
|
|
373
396
|
if (detectJsoncFeatures(text)) {
|
|
374
|
-
emitJsoncGuidanceOnce(vscodeDir);
|
|
397
|
+
emitJsoncGuidanceOnce(vscodeDir, env);
|
|
375
398
|
return { action: 'skipped', reason: 'jsonc_unsupported', path: tasksPath };
|
|
376
399
|
}
|
|
377
400
|
|
|
@@ -398,8 +421,8 @@ export function ensureMonitorTaskFile(opts = {}) {
|
|
|
398
421
|
nextTasks[existingIdx] = repaired;
|
|
399
422
|
const nextObj = { ...obj, version: obj.version ?? '2.0.0', tasks: nextTasks };
|
|
400
423
|
atomicWrite(tasksPath, JSON.stringify(nextObj, null, indent) + '\n');
|
|
401
|
-
emitSetupNotice('repaired');
|
|
402
|
-
if (shouldRecommendGitignore(cwd)) emitGitignoreRecommendationOnce(vscodeDir);
|
|
424
|
+
emitSetupNotice('repaired', env);
|
|
425
|
+
if (shouldRecommendGitignore(cwd)) emitGitignoreRecommendationOnce(vscodeDir, env);
|
|
403
426
|
return { action: 'repaired', path: tasksPath };
|
|
404
427
|
}
|
|
405
428
|
return { action: 'already_present', path: tasksPath };
|
|
@@ -412,7 +435,7 @@ export function ensureMonitorTaskFile(opts = {}) {
|
|
|
412
435
|
tasks: [...(Array.isArray(obj.tasks) ? obj.tasks : []), buildMonitorTask(bin)],
|
|
413
436
|
};
|
|
414
437
|
atomicWrite(tasksPath, JSON.stringify(nextObj, null, indent) + '\n');
|
|
415
|
-
emitSetupNotice('merged');
|
|
416
|
-
if (shouldRecommendGitignore(cwd)) emitGitignoreRecommendationOnce(vscodeDir);
|
|
438
|
+
emitSetupNotice('merged', env);
|
|
439
|
+
if (shouldRecommendGitignore(cwd)) emitGitignoreRecommendationOnce(vscodeDir, env);
|
|
417
440
|
return { action: 'merged', path: tasksPath };
|
|
418
441
|
}
|
package/src/vscode-task.test.mjs
CHANGED
|
@@ -16,7 +16,13 @@ import {
|
|
|
16
16
|
shouldRecommendGitignore,
|
|
17
17
|
} from './vscode-task.mjs';
|
|
18
18
|
|
|
19
|
-
const VSCODE_ENV = {
|
|
19
|
+
const VSCODE_ENV = {
|
|
20
|
+
TERM_PROGRAM: 'vscode',
|
|
21
|
+
THROUGHLINE_SUPPRESS_VSCODE_NOTICES: '1',
|
|
22
|
+
};
|
|
23
|
+
// Production notices are Claude-facing additional context. Tests keep them
|
|
24
|
+
// silent by default and opt in only when asserting notice text.
|
|
25
|
+
const VSCODE_NOTICE_ENV = { TERM_PROGRAM: 'vscode' };
|
|
20
26
|
// 実在する絶対パスを使う。`isMonitorTaskBroken` が「絶対パス + 非存在」で broken 判定するので、
|
|
21
27
|
// 架空パスを使うと意図せず repaired ブランチに落ちてしまう。
|
|
22
28
|
const FAKE_BIN = process.execPath;
|
|
@@ -436,7 +442,11 @@ test('ensureMonitorTaskFile: already_present when command references throughline
|
|
|
436
442
|
{
|
|
437
443
|
label: 'My Custom Monitor',
|
|
438
444
|
type: 'process',
|
|
439
|
-
|
|
445
|
+
// 実在する絶対パスを使う。`/usr/bin/node` は WSL2 では実在するが
|
|
446
|
+
// CI runner (Linux/macOS は /opt/hostedtoolcache, Windows は別) では
|
|
447
|
+
// 存在しないので isMonitorTaskBroken が true になり repaired ブランチに落ちる。
|
|
448
|
+
// process.execPath なら「いま走らせている node 自身の絶対パス」なので必ず実在する。
|
|
449
|
+
command: process.execPath,
|
|
440
450
|
// 相対パスにして broken 判定を避ける(このテストは「label renamed でも検出できるか」だけが論点)
|
|
441
451
|
args: ['./throughline.mjs', 'monitor'],
|
|
442
452
|
},
|
|
@@ -573,7 +583,7 @@ test('ensureMonitorTaskFile: created emits gitignore recommendation when .git ex
|
|
|
573
583
|
mkdirSync(join(dir, '.git'));
|
|
574
584
|
const result = ensureMonitorTaskFile({
|
|
575
585
|
cwd: dir,
|
|
576
|
-
env:
|
|
586
|
+
env: VSCODE_NOTICE_ENV,
|
|
577
587
|
throughlineBin: FAKE_BIN,
|
|
578
588
|
});
|
|
579
589
|
assert.equal(result.action, 'created');
|
|
@@ -597,7 +607,7 @@ test('ensureMonitorTaskFile: created does NOT emit gitignore recommendation when
|
|
|
597
607
|
try {
|
|
598
608
|
const result = ensureMonitorTaskFile({
|
|
599
609
|
cwd: dir,
|
|
600
|
-
env:
|
|
610
|
+
env: VSCODE_NOTICE_ENV,
|
|
601
611
|
throughlineBin: FAKE_BIN,
|
|
602
612
|
});
|
|
603
613
|
assert.equal(result.action, 'created');
|
|
@@ -624,7 +634,7 @@ test('ensureMonitorTaskFile: gitignore recommendation is emitted only once per p
|
|
|
624
634
|
// 1 回目: created → gitignore 推奨が出る
|
|
625
635
|
const r1 = ensureMonitorTaskFile({
|
|
626
636
|
cwd: dir,
|
|
627
|
-
env:
|
|
637
|
+
env: VSCODE_NOTICE_ENV,
|
|
628
638
|
throughlineBin: FAKE_BIN,
|
|
629
639
|
});
|
|
630
640
|
assert.equal(r1.action, 'created');
|
|
@@ -791,7 +801,7 @@ test('ensureMonitorTaskFile: repaired emits notice on stdout', () => {
|
|
|
791
801
|
|
|
792
802
|
const result = ensureMonitorTaskFile({
|
|
793
803
|
cwd: dir,
|
|
794
|
-
env:
|
|
804
|
+
env: VSCODE_NOTICE_ENV,
|
|
795
805
|
throughlineBin: FAKE_BIN,
|
|
796
806
|
});
|
|
797
807
|
assert.equal(result.action, 'repaired');
|
|
@@ -867,7 +877,7 @@ test('ensureMonitorTaskFile: jsonc_unsupported marker suppresses stderr on 2nd c
|
|
|
867
877
|
try {
|
|
868
878
|
const r1 = ensureMonitorTaskFile({
|
|
869
879
|
cwd: dir,
|
|
870
|
-
env:
|
|
880
|
+
env: VSCODE_NOTICE_ENV,
|
|
871
881
|
throughlineBin: FAKE_BIN,
|
|
872
882
|
});
|
|
873
883
|
assert.equal(r1.action, 'skipped');
|
|
@@ -956,13 +966,13 @@ test('buildSetupNotice: ensureMonitorTaskFile writes notice to stdout on first c
|
|
|
956
966
|
try {
|
|
957
967
|
const r1 = ensureMonitorTaskFile({
|
|
958
968
|
cwd: dir,
|
|
959
|
-
env:
|
|
969
|
+
env: VSCODE_NOTICE_ENV,
|
|
960
970
|
throughlineBin: FAKE_BIN,
|
|
961
971
|
});
|
|
962
972
|
assert.equal(r1.action, 'created');
|
|
963
973
|
const r2 = ensureMonitorTaskFile({
|
|
964
974
|
cwd: dir,
|
|
965
|
-
env:
|
|
975
|
+
env: VSCODE_NOTICE_ENV,
|
|
966
976
|
throughlineBin: FAKE_BIN,
|
|
967
977
|
});
|
|
968
978
|
assert.equal(r2.action, 'already_present');
|