throughline 0.3.21 → 0.3.22

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "throughline",
3
- "version": "0.3.21",
3
+ "version": "0.3.22",
4
4
  "type": "module",
5
5
  "description": "Claude Code hooks plugin for structured context compression (/clear-safe persistent memory)",
6
6
  "keywords": [
@@ -39,7 +39,7 @@ const SC_HOOKS = {
39
39
  hooks: [{ type: 'command', command: 'throughline session-start' }],
40
40
  },
41
41
  Stop: {
42
- hooks: [{ type: 'command', command: 'throughline process-turn' }],
42
+ hooks: [{ type: 'command', command: 'throughline process-turn', async: true }],
43
43
  },
44
44
  UserPromptSubmit: {
45
45
  hooks: [{ type: 'command', command: 'throughline prompt-submit' }],
@@ -124,6 +124,35 @@ test('uninstall preserves unrelated slash commands in the same dir', async () =>
124
124
  }
125
125
  });
126
126
 
127
+ test('Stop hook is registered with async:true so it does not block ターン完了 UX', async () => {
128
+ const home = makeTempHome();
129
+ if (home.resolved !== home.dir) {
130
+ home.restore();
131
+ return;
132
+ }
133
+ const unsilence = silence();
134
+ try {
135
+ await run([]);
136
+ const settings = JSON.parse(readFileSync(join(home.dir, '.claude', 'settings.json'), 'utf8'));
137
+ const processTurnHook = settings.hooks.Stop
138
+ .flatMap(g => g.hooks ?? [])
139
+ .find(h => h.command === 'throughline process-turn');
140
+ assert.ok(processTurnHook, 'Stop should have throughline process-turn');
141
+ assert.equal(processTurnHook.async, true, 'Stop hook must be async to avoid blocking ターン完了');
142
+ const sessionStartHook = settings.hooks.SessionStart
143
+ .flatMap(g => g.hooks ?? [])
144
+ .find(h => h.command === 'throughline session-start');
145
+ assert.notEqual(sessionStartHook.async, true, 'SessionStart stays synchronous (needs to inject context before turn)');
146
+ const promptSubmitHook = settings.hooks.UserPromptSubmit
147
+ .flatMap(g => g.hooks ?? [])
148
+ .find(h => h.command === 'throughline prompt-submit');
149
+ assert.notEqual(promptSubmitHook.async, true, 'UserPromptSubmit stays synchronous (needs baton write committed before turn)');
150
+ } finally {
151
+ unsilence();
152
+ home.restore();
153
+ }
154
+ });
155
+
127
156
  test('install is idempotent: second run keeps exactly one tl.md and one hook entry', async () => {
128
157
  const home = makeTempHome();
129
158
  if (home.resolved !== home.dir) {