github-issue-tower-defence-management 1.132.0 → 1.132.1

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/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## [1.132.1](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/compare/v1.132.0...v1.132.1) (2026-07-25)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * stop systemd cl scope when killing tmux session ([#1262](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/issues/1262)) ([dd062f7](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/commit/dd062f7082fa927525055b372be8c31f0f392cfd))
7
+
1
8
  # [1.132.0](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/compare/v1.131.1...v1.132.0) (2026-07-25)
2
9
 
3
10
 
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.NodeTmuxSessionRepository = void 0;
4
+ const clSessionScopeUnitName_1 = require("./clSessionScopeUnitName");
4
5
  class NodeTmuxSessionRepository {
5
6
  constructor(localCommandRunner) {
6
7
  this.localCommandRunner = localCommandRunner;
@@ -60,6 +61,24 @@ class NodeTmuxSessionRepository {
60
61
  if (exitCode !== 0) {
61
62
  throw new Error(`Failed to kill tmux session "${sessionName}": exit code ${exitCode}${stderr ? `: ${stderr}` : ''}`);
62
63
  }
64
+ await this.stopClSessionScope(sessionName);
65
+ };
66
+ this.stopClSessionScope = async (sessionName) => {
67
+ const scopeUnitName = (0, clSessionScopeUnitName_1.clSessionScopeUnitName)(sessionName);
68
+ await this.localCommandRunner.runCommand('systemctl', [
69
+ '--user',
70
+ 'reset-failed',
71
+ scopeUnitName,
72
+ ]);
73
+ const { stderr, exitCode } = await this.localCommandRunner.runCommand('systemctl', ['--user', 'stop', scopeUnitName]);
74
+ await this.localCommandRunner.runCommand('systemctl', [
75
+ '--user',
76
+ 'reset-failed',
77
+ scopeUnitName,
78
+ ]);
79
+ if (exitCode !== 0) {
80
+ console.error(`Failed to stop systemd user scope "${scopeUnitName}" for tmux session "${sessionName}": exit code ${exitCode}${stderr ? `: ${stderr}` : ''}`);
81
+ }
63
82
  };
64
83
  }
65
84
  }
@@ -1 +1 @@
1
- {"version":3,"file":"NodeTmuxSessionRepository.js","sourceRoot":"","sources":["../../../src/adapter/repositories/NodeTmuxSessionRepository.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"NodeTmuxSessionRepository.js","sourceRoot":"","sources":["../../../src/adapter/repositories/NodeTmuxSessionRepository.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.clSessionScopeUnitName = void 0;
4
+ const clSessionScopeUnitName = (sessionName) => {
5
+ const safe = sessionName.replace(/[^a-zA-Z0-9]/g, '-');
6
+ const raw = `cl-${safe}`;
7
+ return `${raw.replace(/[^a-zA-Z0-9._-]/g, '-')}.scope`;
8
+ };
9
+ exports.clSessionScopeUnitName = clSessionScopeUnitName;
10
+ //# sourceMappingURL=clSessionScopeUnitName.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clSessionScopeUnitName.js","sourceRoot":"","sources":["../../../src/adapter/repositories/clSessionScopeUnitName.ts"],"names":[],"mappings":";;;AAAO,MAAM,sBAAsB,GAAG,CAAC,WAAmB,EAAU,EAAE;IACpE,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,eAAe,EAAE,GAAG,CAAC,CAAC;IACvD,MAAM,GAAG,GAAG,MAAM,IAAI,EAAE,CAAC;IACzB,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC,QAAQ,CAAC;AACzD,CAAC,CAAC;AAJW,QAAA,sBAAsB,0BAIjC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "github-issue-tower-defence-management",
3
- "version": "1.132.0",
3
+ "version": "1.132.1",
4
4
  "description": "",
5
5
  "main": "bin/index.js",
6
6
  "scripts": {
@@ -123,6 +123,61 @@ describe('NodeTmuxSessionRepository', () => {
123
123
  'Failed to kill tmux session "missing_session": exit code 1',
124
124
  );
125
125
  });
126
+
127
+ it('stops the systemd user scope for the session after killing it, wrapping the stop with reset-failed', async () => {
128
+ const runner = createMockRunner();
129
+ runner.runCommand.mockResolvedValue({
130
+ stdout: '',
131
+ stderr: '',
132
+ exitCode: 0,
133
+ });
134
+ const repository = new NodeTmuxSessionRepository(runner);
135
+
136
+ await repository.killSession('https_//github_com/owner/repo/issues/9');
137
+
138
+ const expectedScopeUnitName =
139
+ 'cl-https---github-com-owner-repo-issues-9.scope';
140
+ const calls = runner.runCommand.mock.calls;
141
+ expect(calls[0]).toEqual([
142
+ 'tmux',
143
+ ['kill-session', '-t', 'https_//github_com/owner/repo/issues/9'],
144
+ ]);
145
+ const systemctlCalls = calls.filter((call) => call[0] === 'systemctl');
146
+ expect(systemctlCalls).toEqual([
147
+ ['systemctl', ['--user', 'reset-failed', expectedScopeUnitName]],
148
+ ['systemctl', ['--user', 'stop', expectedScopeUnitName]],
149
+ ['systemctl', ['--user', 'reset-failed', expectedScopeUnitName]],
150
+ ]);
151
+ });
152
+
153
+ it('logs an error but does not throw when stopping the systemd user scope fails', async () => {
154
+ const runner = createMockRunner();
155
+ runner.runCommand.mockImplementation(async (program: string) => {
156
+ if (program === 'systemctl') {
157
+ return {
158
+ stdout: '',
159
+ stderr: 'Failed to stop cl-leader-session.scope: Unit not loaded.',
160
+ exitCode: 5,
161
+ };
162
+ }
163
+ return { stdout: '', stderr: '', exitCode: 0 };
164
+ });
165
+ const errorSpy = jest
166
+ .spyOn(console, 'error')
167
+ .mockImplementation(() => undefined);
168
+ const repository = new NodeTmuxSessionRepository(runner);
169
+
170
+ await expect(
171
+ repository.killSession('leader_session'),
172
+ ).resolves.toBeUndefined();
173
+
174
+ expect(errorSpy).toHaveBeenCalledWith(
175
+ expect.stringContaining(
176
+ 'Failed to stop systemd user scope "cl-leader-session.scope"',
177
+ ),
178
+ );
179
+ errorSpy.mockRestore();
180
+ });
126
181
  });
127
182
 
128
183
  describe('listInteractiveProcessCommandLines', () => {
@@ -1,6 +1,7 @@
1
1
  import { LocalCommandRunner } from '../../domain/usecases/adapter-interfaces/LocalCommandRunner';
2
2
  import { TmuxSessionRepository } from '../../domain/usecases/adapter-interfaces/TmuxSessionRepository';
3
3
  import { LiveTmuxSession } from '../../domain/entities/LiveTmuxSession';
4
+ import { clSessionScopeUnitName } from './clSessionScopeUnitName';
4
5
 
5
6
  export class NodeTmuxSessionRepository implements TmuxSessionRepository {
6
7
  constructor(private readonly localCommandRunner: LocalCommandRunner) {}
@@ -85,5 +86,31 @@ export class NodeTmuxSessionRepository implements TmuxSessionRepository {
85
86
  }`,
86
87
  );
87
88
  }
89
+ await this.stopClSessionScope(sessionName);
90
+ };
91
+
92
+ private stopClSessionScope = async (sessionName: string): Promise<void> => {
93
+ const scopeUnitName = clSessionScopeUnitName(sessionName);
94
+ await this.localCommandRunner.runCommand('systemctl', [
95
+ '--user',
96
+ 'reset-failed',
97
+ scopeUnitName,
98
+ ]);
99
+ const { stderr, exitCode } = await this.localCommandRunner.runCommand(
100
+ 'systemctl',
101
+ ['--user', 'stop', scopeUnitName],
102
+ );
103
+ await this.localCommandRunner.runCommand('systemctl', [
104
+ '--user',
105
+ 'reset-failed',
106
+ scopeUnitName,
107
+ ]);
108
+ if (exitCode !== 0) {
109
+ console.error(
110
+ `Failed to stop systemd user scope "${scopeUnitName}" for tmux session "${sessionName}": exit code ${exitCode}${
111
+ stderr ? `: ${stderr}` : ''
112
+ }`,
113
+ );
114
+ }
88
115
  };
89
116
  }
@@ -0,0 +1,76 @@
1
+ import { execFileSync } from 'node:child_process';
2
+ import { existsSync } from 'node:fs';
3
+ import { homedir } from 'node:os';
4
+ import { join } from 'node:path';
5
+ import { toTmuxSessionName } from '../../domain/usecases/intmux/InTmuxByHumanSessionReconcileUseCase';
6
+ import { clSessionScopeUnitName } from './clSessionScopeUnitName';
7
+
8
+ const issueUrls = [
9
+ 'https://github.com/HiromiShikata/secretary/issues/1261',
10
+ 'https://github.com/owner/repo/issues/9',
11
+ 'https://github.com/owner/repo/pull/42',
12
+ ];
13
+
14
+ const sessionNames = [
15
+ ...issueUrls,
16
+ ...issueUrls.map((url) => toTmuxSessionName(url)),
17
+ 'idle_no_task_session',
18
+ 'plain-session',
19
+ 'ALLCAPS123',
20
+ ];
21
+
22
+ const canonicalScopeLibPath = (): string | null => {
23
+ const explicitPath = process.env.CL_SCOPE_LIB_PATH;
24
+ if (explicitPath !== undefined && existsSync(explicitPath)) {
25
+ return explicitPath;
26
+ }
27
+ const defaultPath = join(
28
+ homedir(),
29
+ 'git',
30
+ 'secretary',
31
+ 'machine',
32
+ 'sk',
33
+ 'sh',
34
+ 'cl-scope-lib.sh',
35
+ );
36
+ return existsSync(defaultPath) ? defaultPath : null;
37
+ };
38
+
39
+ describe('clSessionScopeUnitName cross-component contract', () => {
40
+ it('derives a systemd-safe scope unit name of the form cl-<safe>.scope for every session form', () => {
41
+ for (const sessionName of sessionNames) {
42
+ const unitName = clSessionScopeUnitName(sessionName);
43
+ expect(unitName.startsWith('cl-')).toBe(true);
44
+ expect(unitName.endsWith('.scope')).toBe(true);
45
+ const core = unitName.slice(0, -'.scope'.length);
46
+ expect(/^[A-Za-z0-9._-]+$/.test(core)).toBe(true);
47
+ }
48
+ });
49
+
50
+ it('collapses a raw issue URL and its tmux-normalized session name to the same scope unit name', () => {
51
+ for (const url of issueUrls) {
52
+ expect(clSessionScopeUnitName(toTmuxSessionName(url))).toBe(
53
+ clSessionScopeUnitName(url),
54
+ );
55
+ }
56
+ });
57
+
58
+ const libPath = canonicalScopeLibPath();
59
+ const canonicalContractTest = libPath === null ? it.skip : it;
60
+ canonicalContractTest(
61
+ 'matches the canonical cl_scope_unit_name derivation shared with cl',
62
+ () => {
63
+ if (libPath === null) {
64
+ return;
65
+ }
66
+ for (const sessionName of sessionNames) {
67
+ const canonicalUnitName = execFileSync(
68
+ 'bash',
69
+ [libPath, 'unit-name', sessionName],
70
+ { encoding: 'utf8' },
71
+ );
72
+ expect(clSessionScopeUnitName(sessionName)).toBe(canonicalUnitName);
73
+ }
74
+ },
75
+ );
76
+ });
@@ -0,0 +1,5 @@
1
+ export const clSessionScopeUnitName = (sessionName: string): string => {
2
+ const safe = sessionName.replace(/[^a-zA-Z0-9]/g, '-');
3
+ const raw = `cl-${safe}`;
4
+ return `${raw.replace(/[^a-zA-Z0-9._-]/g, '-')}.scope`;
5
+ };
@@ -9,5 +9,6 @@ export declare class NodeTmuxSessionRepository implements TmuxSessionRepository
9
9
  listInteractiveProcessCommandLines: () => Promise<string[]>;
10
10
  launchDetachedSession: (sessionName: string, launcherCommand: string, issueUrl: string) => Promise<void>;
11
11
  killSession: (sessionName: string) => Promise<void>;
12
+ private stopClSessionScope;
12
13
  }
13
14
  //# sourceMappingURL=NodeTmuxSessionRepository.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"NodeTmuxSessionRepository.d.ts","sourceRoot":"","sources":["../../../src/adapter/repositories/NodeTmuxSessionRepository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,6DAA6D,CAAC;AACjG,OAAO,EAAE,qBAAqB,EAAE,MAAM,gEAAgE,CAAC;AACvG,OAAO,EAAE,eAAe,EAAE,MAAM,uCAAuC,CAAC;AAExE,qBAAa,yBAA0B,YAAW,qBAAqB;IACzD,OAAO,CAAC,QAAQ,CAAC,kBAAkB;gBAAlB,kBAAkB,EAAE,kBAAkB;IAEnE,oBAAoB,QAAa,OAAO,CAAC,MAAM,EAAE,CAAC,CAYhD;IAEF,4BAA4B,QAAa,OAAO,CAAC,eAAe,EAAE,CAAC,CAkBjE;IAEF,kCAAkC,QAAa,OAAO,CAAC,MAAM,EAAE,CAAC,CAY9D;IAEF,qBAAqB,GACnB,aAAa,MAAM,EACnB,iBAAiB,MAAM,EACvB,UAAU,MAAM,KACf,OAAO,CAAC,IAAI,CAAC,CAcd;IAEF,WAAW,GAAU,aAAa,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC,CAYtD;CACH"}
1
+ {"version":3,"file":"NodeTmuxSessionRepository.d.ts","sourceRoot":"","sources":["../../../src/adapter/repositories/NodeTmuxSessionRepository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,6DAA6D,CAAC;AACjG,OAAO,EAAE,qBAAqB,EAAE,MAAM,gEAAgE,CAAC;AACvG,OAAO,EAAE,eAAe,EAAE,MAAM,uCAAuC,CAAC;AAGxE,qBAAa,yBAA0B,YAAW,qBAAqB;IACzD,OAAO,CAAC,QAAQ,CAAC,kBAAkB;gBAAlB,kBAAkB,EAAE,kBAAkB;IAEnE,oBAAoB,QAAa,OAAO,CAAC,MAAM,EAAE,CAAC,CAYhD;IAEF,4BAA4B,QAAa,OAAO,CAAC,eAAe,EAAE,CAAC,CAkBjE;IAEF,kCAAkC,QAAa,OAAO,CAAC,MAAM,EAAE,CAAC,CAY9D;IAEF,qBAAqB,GACnB,aAAa,MAAM,EACnB,iBAAiB,MAAM,EACvB,UAAU,MAAM,KACf,OAAO,CAAC,IAAI,CAAC,CAcd;IAEF,WAAW,GAAU,aAAa,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC,CAatD;IAEF,OAAO,CAAC,kBAAkB,CAuBxB;CACH"}
@@ -0,0 +1,2 @@
1
+ export declare const clSessionScopeUnitName: (sessionName: string) => string;
2
+ //# sourceMappingURL=clSessionScopeUnitName.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clSessionScopeUnitName.d.ts","sourceRoot":"","sources":["../../../src/adapter/repositories/clSessionScopeUnitName.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,sBAAsB,GAAI,aAAa,MAAM,KAAG,MAI5D,CAAC"}